Merge "Deprecate some system apis in TelephonyManager"
diff --git a/Android.bp b/Android.bp
index db0f0ea..07b3018 100644
--- a/Android.bp
+++ b/Android.bp
@@ -27,6 +27,7 @@
 
 java_library {
     name: "framework",
+    installable: true,
 
     srcs: [
         // From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS
@@ -84,6 +85,7 @@
         "core/java/android/app/IUidObserver.aidl",
         "core/java/android/app/IUiAutomationConnection.aidl",
         "core/java/android/app/IUiModeManager.aidl",
+        "core/java/android/app/IUriGrantsManager.aidl",
         "core/java/android/app/IUserSwitchObserver.aidl",
         "core/java/android/app/IWallpaperManager.aidl",
         "core/java/android/app/IWallpaperManagerCallback.aidl",
@@ -92,6 +94,7 @@
         "core/java/android/app/trust/IStrongAuthTracker.aidl",
         "core/java/android/app/trust/ITrustManager.aidl",
         "core/java/android/app/trust/ITrustListener.aidl",
+        "core/java/android/app/backup/IBackupCallback.aidl",
         "core/java/android/app/backup/IBackupManager.aidl",
         "core/java/android/app/backup/IBackupObserver.aidl",
         "core/java/android/app/backup/IBackupManagerMonitor.aidl",
@@ -478,6 +481,8 @@
         "media/java/android/media/tv/ITvRemoteServiceInput.aidl",
         "media/java/android/service/media/IMediaBrowserService.aidl",
         "media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl",
+        "telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl",
+        "telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl",
         "telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl",
         "telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl",
         "telecomm/java/com/android/internal/telecom/IVideoCallback.aidl",
@@ -490,6 +495,8 @@
         "telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl",
         "telephony/java/android/telephony/data/IDataService.aidl",
         "telephony/java/android/telephony/data/IDataServiceCallback.aidl",
+        "telephony/java/android/telephony/data/IQualifiedNetworksService.aidl",
+        "telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl",
         "telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl",
         "telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl",
         "telephony/java/android/telephony/ims/aidl/IImsConfig.aidl",
@@ -573,6 +580,7 @@
         "telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl",
         "wifi/java/android/net/wifi/ISoftApCallback.aidl",
+        "wifi/java/android/net/wifi/ITrafficStateCallback.aidl",
         "wifi/java/android/net/wifi/IWifiManager.aidl",
         "wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl",
         "wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl",
@@ -650,6 +658,8 @@
             "system/bt/binder",
             "system/security/keystore/binder",
         ],
+
+        generate_get_transaction_name: true
     },
 
     exclude_srcs: [
@@ -706,6 +716,7 @@
 // specified on the build command line.
 java_library {
     name: "framework-oahl-backward-compatibility",
+    installable: true,
     srcs: [
         "core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java",
     ],
@@ -734,22 +745,24 @@
     name: "framework-javastream-protos",
     depfile: true,
 
+    tool_files: [ "tools/genprotos.sh", ],
     tools: [
         "aprotoc",
         "protoc-gen-javastream",
         "soong_zip",
     ],
 
-    cmd: "mkdir -p $(genDir)/$(in) " +
-        "&& $(location aprotoc) " +
-        "  --plugin=$(location protoc-gen-javastream) " +
-        "  --dependency_out=$(depfile) " +
-        "  --javastream_out=$(genDir)/$(in) " +
-        "  -Iexternal/protobuf/src " +
-        "  -I . " +
-        "  $(in) " +
-        "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
-
+    // TODO This should not be needed. If you set a custom OUT_DIR or OUT_DIR_COMMON_BASE you can
+    // end up with a command that is extremely long, potentially going passed MAX_ARG_STRLEN due to
+    // the way sbox rewrites the command. See b/70221552.
+    cmd: "$(location tools/genprotos.sh) " +
+              " $(location aprotoc) " +
+              " $(location protoc-gen-javastream) " +
+              " $(location soong_zip) " +
+              " $(genDir) " +
+              " $(depfile) " +
+              " $(in) " +
+              " $(out)",
     srcs: [
         "core/proto/**/*.proto",
         "libs/incident/**/*.proto",
@@ -761,6 +774,7 @@
 // ============================================================
 java_library {
     name: "ext",
+    installable: true,
     no_framework_libs: true,
     static_libs: [
         "libphonenumber-platform",
@@ -789,6 +803,40 @@
     },
 }
 
+// ====  java proto device library (for test only)  ==============================
+java_library {
+    name: "platformprotosnano",
+    proto: {
+        type: "nano",
+        output_params: ["store_unknown_fields=true"],
+        include_dirs: ["external/protobuf/src"],
+    },
+
+    sdk_version: "current",
+    srcs: [
+        "core/proto/**/*.proto",
+        "libs/incident/proto/android/os/**/*.proto",
+    ],
+}
+
+// ====  java proto device library (for test only)  ==============================
+java_library {
+    name: "platformprotoslite",
+    proto: {
+        type: "lite",
+        include_dirs: ["external/protobuf/src"],
+    },
+
+    srcs: [
+        "core/proto/**/*.proto",
+        "libs/incident/proto/android/os/**/*.proto",
+    ],
+    // Protos have lots of MissingOverride and similar.
+    errorprone: {
+        javacflags: ["-XepDisableAllChecks"],
+    },
+}
+
 // ====  c++ proto device library  ==============================
 cc_library {
     name: "libplatformprotos",
@@ -894,6 +942,7 @@
         "core/java/android/os/IHwInterface.java",
         "core/java/android/os/DeadObjectException.java",
         "core/java/android/os/DeadSystemException.java",
+        "core/java/android/os/NativeHandle.java",
         "core/java/android/os/RemoteException.java",
         "core/java/android/util/AndroidException.java",
     ],
@@ -994,6 +1043,7 @@
      "-since $(location 26/public/api/android.txt) 26 " +
      "-since $(location 27/public/api/android.txt) 27 " +
      "-since $(location 28/public/api/android.txt) 28 " +
+     "-since $(location api/current.txt) Q " +
      "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
      "-overview $(location core/java/overview.html) " +
      // Federate Support Library references against local API file.
@@ -1001,17 +1051,13 @@
      "-federationapi SupportLib $(location current/support-api.txt) "
 
 doc_defaults {
-    name: "framework-docs-default",
+    name: "api-stubs-default",
     srcs: [
         ":opt-telephony-srcs",
         ":opt-net-voip-srcs",
         ":openjdk_javadoc_files",
         ":non_openjdk_javadoc_files",
         ":android_icu4j_src_files_for_docs",
-        ":gen-ojluni-jaif-annotated-srcs",
-    ],
-    exclude_srcs: [
-        ":annotated_ojluni_files",
     ],
     srcs_lib: "framework",
     srcs_lib_whitelist_dirs: frameworks_base_subdirs,
@@ -1025,7 +1071,7 @@
         "ext",
         "framework",
         "voip-common",
-        "android.test.mock",
+        "android.test.mock.impl",
     ],
     local_sourcepaths: frameworks_base_subdirs,
     html_dirs: [
@@ -1049,9 +1095,80 @@
     installable: false,
 }
 
-droiddoc {
-    name: "api-stubs-docs",
-    defaults: ["framework-docs-default"],
+doc_defaults {
+    name: "framework-docs-default",
+    srcs: [
+        "test-base/src/**/*.java",
+        ":opt-telephony-srcs",
+        ":opt-net-voip-srcs",
+        ":openjdk_javadoc_files",
+        ":non_openjdk_javadoc_files",
+        ":android_icu4j_src_files_for_docs",
+        "test-mock/src/**/*.java",
+        "test-runner/src/**/*.java",
+    ],
+    srcs_lib: "framework",
+    srcs_lib_whitelist_dirs: frameworks_base_subdirs,
+    srcs_lib_whitelist_pkgs: packages_to_document,
+    libs: [
+        "conscrypt",
+        "bouncycastle",
+        "voip-common",
+        "android.test.mock",
+        "android-support-annotations",
+        "android-support-compat",
+        "android-support-core-ui",
+        "android-support-core-utils",
+        "android-support-customtabs",
+        "android-support-design",
+        "android-support-dynamic-animation",
+        "android-support-exifinterface",
+        "android-support-fragment",
+        "android-support-media-compat",
+        "android-support-percent",
+        "android-support-recommendation",
+        "android-support-transition",
+        "android-support-tv-provider",
+        "android-support-v7-cardview",
+        "android-support-v7-gridlayout",
+        "android-support-v7-mediarouter",
+        "android-support-v7-palette",
+        "android-support-v7-preference",
+        "android-support-v13",
+        "android-support-v14-preference",
+        "android-support-v17-leanback",
+        "android-support-v17-preference-leanback",
+        "android-support-wear",
+        "android-support-vectordrawable",
+        "android-support-animatedvectordrawable",
+        "android-support-v7-appcompat",
+        "android-support-v7-recyclerview",
+        "android-support-emoji",
+        "android-support-emoji-appcompat",
+        "android-support-emoji-bundled",
+        "android-support-v8-renderscript",
+        "android-support-multidex",
+        "android-support-multidex-instrumentation",
+    ],
+    local_sourcepaths: frameworks_base_subdirs,
+    html_dirs: [
+        "docs/html",
+    ],
+    knowntags: [
+        "docs/knowntags.txt",
+        ":known-oj-tags",
+    ],
+    custom_template: "droiddoc-templates-sdk",
+    resourcesdir: "docs/html/reference/images/",
+    resourcesoutdir: "reference/android/images/",
+    hdf: [
+        "dac true",
+        "sdk.codename O",
+        "sdk.preview.version 1",
+        "sdk.version 7.0",
+        "sdk.rel.id 1",
+        "sdk.preview 0",
+    ],
     arg_files: [
         "core/res/AndroidManifest.xml",
         ":api-version-xml",
@@ -1059,87 +1176,201 @@
         ":current-support-api",
         "api/current.txt",
     ],
-    api_filename: "public_api.txt",
-    removed_api_filename: "removed.txt",
-    args: framework_docs_args + " -referenceonly -nodocs",
-    check_api: {
-        last_released: {
-            api_file: ":last-released-public-api",
-            removed_api_file: "api/removed.txt",
-            args: "-hide 2 -hide 3 -hide 4 -hide 5 -hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
-                  "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 " +
-                  "-error 16 -error 17 -error 18 -error 31",
-        },
-        current: {
-            api_file: "api/current.txt",
-            removed_api_file: "api/removed.txt",
-            args: "-error 2 -error 3 -error 4 -error 5 -error 6 " +
-                  "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 " +
-                  "-error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 " +
-                  "-error 25 -error 26 -error 27",
-        },
-    },
+    create_stubs: false,
 }
 
 droiddoc {
-    name: "system-api-stubs-docs",
+    name: "doc-comment-check-docs",
     defaults: ["framework-docs-default"],
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-        ":api-version-xml",
-        "core/java/overview.html",
-        ":current-support-api",
-        "api/current.txt",
-    ],
-    api_tag_name: "SYSTEM",
-    api_filename: "system-api.txt",
-    removed_api_filename: "system-removed.txt",
-    exact_api_filename: "system-exact.txt",
-    args: framework_docs_args + " -referenceonly -showAnnotation android.annotation.SystemApi -nodocs",
-    check_api: {
-        last_released: {
-            api_file: ":last-released-system-api",
-            removed_api_file: "api/system-removed.txt",
-            args: "-hide 2 -hide 3 -hide 4 -hide 5 -hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
-                  "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 " +
-                  "-error 16 -error 17 -error 18 -error 31",
-        },
-        current: {
-            api_file: "api/system-current.txt",
-            removed_api_file: "api/system-removed.txt",
-            args: "-error 2 -error 3 -error 4 -error 5 -error 6 " +
-                  "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 " +
-                  "-error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 " +
-                  "-error 25 -error 26 -error 27",
-        },
-    },
+    args: framework_docs_args + " -referenceonly -parsecomments",
+    installable: false,
 }
 
 droiddoc {
-    name: "test-api-stubs-docs",
+    name: "offline-sdk-docs",
     defaults: ["framework-docs-default"],
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-        ":api-version-xml",
-        "core/java/overview.html",
-        ":current-support-api",
-        "api/current.txt",
+    hdf: [
+        "android.whichdoc offline",
     ],
-    api_tag_name: "TEST",
-    api_filename: "test-api.txt",
-    removed_api_filename: "test-removed.txt",
-    exact_api_filename: "test-exact.txt",
-    args: framework_docs_args + " -referenceonly -showAnnotation android.annotation.TestApi -nodocs",
-    check_api: {
-        current: {
-            api_file: "api/test-current.txt",
-            removed_api_file: "api/test-removed.txt",
-            args: "-error 2 -error 3 -error 4 -error 5 -error 6 " +
-                  "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 " +
-                  "-error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 " +
-                  "-error 25 -error 26 -error 27",
-        },
-    },
+    proofread_file: "offline-sdk-docs-proofrerad.txt",
+    args: framework_docs_args + " -offlinemode -title \"Android SDK\"",
+    write_sdk_values: true,
+    static_doc_index_redirect: "docs/docs-preview-index.html",
+}
+
+droiddoc {
+    name: "offline-sdk-referenceonly-docs",
+    defaults: ["framework-docs-default"],
+    hdf: [
+        "android.whichdoc offline",
+    ],
+    proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
+    args: framework_docs_args + " -offlinemode -title \"Android SDK\" -referenceonly",
+    write_sdk_values: true,
+    static_doc_index_redirect: "docs/docs-documentation-redirect.html",
+    static_doc_properties: "docs/source.properties",
+}
+
+droiddoc {
+    name: "offline-system-sdk-referenceonly-docs",
+    defaults: ["framework-docs-default"],
+    hdf: [
+        "android.whichdoc offline",
+    ],
+    proofread_file: "offline-system-sdk-referenceonly-docs-proofrerad.txt",
+    args: framework_docs_args + " -hide 101 -hide 104 -hide 108" +
+          " -showAnnotation android.annotation.SystemApi " +
+          " -offlinemode -title \"Android System SDK\" -referenceonly",
+    write_sdk_values: true,
+    static_doc_index_redirect: "docs/docs-documentation-redirect.html",
+    static_doc_properties: "docs/source.properties",
+}
+
+droiddoc {
+    name: "online-sdk-docs",
+    defaults: ["framework-docs-default"],
+    hdf: [
+        "android.whichdoc online",
+        "android.hasSamples true",
+    ],
+    proofread_file: "online-sdk-docs-proofrerad.txt",
+    args: framework_docs_args +
+        " -toroot / -samplegroup Admin " +
+        " -samplegroup Background " +
+        " -samplegroup Connectivity " +
+        " -samplegroup Content " +
+        " -samplegroup Input " +
+        " -samplegroup Media " +
+        " -samplegroup Notification " +
+        " -samplegroup RenderScript " +
+        " -samplegroup Security " +
+        " -samplegroup Sensors " +
+        " -samplegroup System " +
+        " -samplegroup Testing " +
+        " -samplegroup UI " +
+        " -samplegroup Views " +
+        " -samplegroup Wearable -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+    name: "online-system-api-sdk-docs",
+    defaults: ["framework-docs-default"],
+    hdf: [
+        "android.whichdoc online",
+        "android.hasSamples true",
+    ],
+    proofread_file: "online-system-api-sdk-docs-proofrerad.txt",
+    args: framework_docs_args +
+        " -referenceonly " +
+        " -showAnnotation android.annotation.SystemApi " +
+        " -title \"Android SDK - Including system APIs.\" " +
+        " -hide 101 " +
+        " -hide 104 " +
+        " -hide 108 " +
+        " -toroot / -samplegroup Admin " +
+        " -samplegroup Background " +
+        " -samplegroup Connectivity " +
+        " -samplegroup Content " +
+        " -samplegroup Input " +
+        " -samplegroup Media " +
+        " -samplegroup Notification " +
+        " -samplegroup RenderScript " +
+        " -samplegroup Security " +
+        " -samplegroup Sensors " +
+        " -samplegroup System " +
+        " -samplegroup Testing " +
+        " -samplegroup UI " +
+        " -samplegroup Views " +
+        " -samplegroup Wearable -samplesdir development/samples/browseable ",
+    installable: false,
+}
+
+droiddoc {
+    name: "ds-docs",
+    defaults: ["framework-docs-default"],
+    hdf: [
+        "android.whichdoc online",
+        "android.hasSamples true",
+    ],
+    proofread_file: "ds-docs-proofrerad.txt",
+    args: framework_docs_args +
+        " -toroot / -samplegroup Admin " +
+        " -samplegroup Background " +
+        " -samplegroup Connectivity " +
+        " -samplegroup Content " +
+        " -samplegroup Input " +
+        " -samplegroup Media " +
+        " -samplegroup Notification " +
+        " -samplegroup RenderScript " +
+        " -samplegroup Security " +
+        " -samplegroup Sensors " +
+        " -samplegroup System " +
+        " -samplegroup Testing " +
+        " -samplegroup UI " +
+        " -samplegroup Views " +
+        " -samplegroup Wearable -devsite -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+    name: "ds-static-docs",
+    defaults: ["framework-docs-default"],
+    hdf: [
+        "android.whichdoc online",
+    ],
+    proofread_file: "ds-static-docs-proofrerad.txt",
+    args: framework_docs_args +
+          " -staticonly " +
+          " -toroot / " +
+          " -devsite " +
+          " -ignoreJdLinks ",
+}
+
+droiddoc {
+    name: "ds-ref-navtree-docs",
+    defaults: ["framework-docs-default"],
+    hdf: [
+        "android.whichdoc online",
+    ],
+    proofread_file: "ds-ref-navtree-docs-proofrerad.txt",
+    args: framework_docs_args +
+          " -toroot / " +
+          " -atLinksNavtree " +
+          " -navtreeonly ",
+}
+
+droiddoc {
+    name: "online-sdk-dev-docs",
+    defaults: ["framework-docs-default"],
+    hdf: [
+        "android.whichdoc online",
+        "android.hasSamples true",
+    ],
+    proofread_file: "online-sdk-dev-docs-proofrerad.txt",
+    args: framework_docs_args +
+        " -toroot / -samplegroup Admin " +
+        " -samplegroup Background " +
+        " -samplegroup Connectivity " +
+        " -samplegroup Content " +
+        " -samplegroup Input " +
+        " -samplegroup Media " +
+        " -samplegroup Notification " +
+        " -samplegroup RenderScript " +
+        " -samplegroup Security " +
+        " -samplegroup Sensors " +
+        " -samplegroup System " +
+        " -samplegroup Testing " +
+        " -samplegroup UI " +
+        " -samplegroup Views " +
+        " -samplegroup Wearable -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+    name: "hidden-docs",
+    defaults: ["framework-docs-default"],
+    proofread_file: "hidden-docs-proofrerad.txt",
+    args: framework_docs_args +
+          " -referenceonly " +
+          " -title \"Android SDK - Including hidden APIs.\"",
 }
 
 droiddoc {
@@ -1156,6 +1387,7 @@
         "core/java/android/os/IHwInterface.java",
         "core/java/android/os/DeadObjectException.java",
         "core/java/android/os/DeadSystemException.java",
+        "core/java/android/os/NativeHandle.java",
         "core/java/android/os/RemoteException.java",
         "core/java/android/util/AndroidException.java",
     ],
@@ -1175,13 +1407,15 @@
 
 droiddoc {
     name: "hiddenapi-lists",
-    defaults: ["framework-docs-default"],
+    defaults: ["api-stubs-default"],
     arg_files: [
         "core/res/AndroidManifest.xml",
         ":api-version-xml",
         "core/java/overview.html",
         ":current-support-api",
+        "api/current.txt",
     ],
+    dex_api_filename: "public-dex.txt",
     private_dex_api_filename: "private-dex.txt",
     removed_dex_api_filename: "removed-dex.txt",
     args: framework_docs_args +
@@ -1192,6 +1426,25 @@
           " -showAnnotation android.annotation.TestApi",
 }
 
+droiddoc {
+    name: "hiddenapi-mappings",
+    defaults: ["api-stubs-default"],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+        ":api-version-xml",
+        "core/java/overview.html",
+        ":current-support-api",
+        "api/current.txt",
+    ],
+    dex_mapping_filename: "dex-mapping.txt",
+    args: framework_docs_args +
+          " -referenceonly" +
+          " -nodocs" +
+          " -showUnannotated" +
+          " -showAnnotation android.annotation.SystemApi" +
+          " -showAnnotation android.annotation.TestApi",
+}
+
 filegroup {
     name: "apache-http-stubs-sources",
     srcs: [
@@ -1225,17 +1478,13 @@
     "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
 
 doc_defaults {
-    name: "metalava-framework-docs-default",
+    name: "metalava-api-stubs-default",
     srcs: [
         ":opt-telephony-srcs",
         ":opt-net-voip-srcs",
         ":openjdk_javadoc_files",
         ":non_openjdk_javadoc_files",
         ":android_icu4j_src_files_for_docs",
-        ":gen-ojluni-jaif-annotated-srcs",
-    ],
-    exclude_srcs: [
-        ":annotated_ojluni_files",
     ],
     srcs_lib: "framework",
     srcs_lib_whitelist_dirs: frameworks_base_subdirs,
@@ -1249,20 +1498,22 @@
         "ext",
         "framework",
         "voip-common",
-        "android.test.mock",
+        "android.test.mock.impl",
     ],
     local_sourcepaths: frameworks_base_subdirs,
     installable: false,
     metalava_enabled: true,
     metalava_annotations_enabled: true,
-    metalava_previous_api: ":public-api-for-metalava-annotations",
-    metalava_merge_annotations_dir: "tools/metalava/manual",
+    metalava_previous_api: ":last-released-public-api",
+    metalava_merge_annotations_dirs: [
+        "metalava-manual",
+        "ojluni-annotated-stubs",
+    ],
 }
 
 droiddoc {
-    name: "metalava-api-stubs-docs",
-    defaults: ["metalava-framework-docs-default"],
-    api_tag_name: "METALAVA_PUBLIC",
+    name: "api-stubs-docs",
+    defaults: ["metalava-api-stubs-default"],
     api_filename: "public_api.txt",
     private_api_filename: "private.txt",
     removed_api_filename: "removed.txt",
@@ -1270,12 +1521,22 @@
         "core/res/AndroidManifest.xml",
     ],
     args: metalava_framework_docs_args,
+    check_api: {
+        current: {
+            api_file: "api/current.txt",
+            removed_api_file: "api/removed.txt",
+        },
+        last_released: {
+            api_file: ":last-released-public-api",
+            removed_api_file: "api/removed.txt",
+        },
+    },
 }
 
 droiddoc {
-    name: "metalava-system-api-stubs-docs",
-    defaults: ["metalava-framework-docs-default"],
-    api_tag_name: "METALAVA_SYSTEM",
+    name: "system-api-stubs-docs",
+    defaults: ["metalava-api-stubs-default"],
+    api_tag_name: "SYSTEM",
     api_filename: "system-api.txt",
     private_api_filename: "system-private.txt",
     private_dex_api_filename: "system-private-dex.txt",
@@ -1284,16 +1545,32 @@
         "core/res/AndroidManifest.xml",
     ],
     args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi",
+    check_api: {
+        current: {
+            api_file: "api/system-current.txt",
+            removed_api_file: "api/system-removed.txt",
+        },
+        last_released: {
+            api_file: ":last-released-system-api",
+            removed_api_file: "api/system-removed.txt",
+        },
+    },
 }
 
 droiddoc {
-    name: "metalava-test-api-stubs-docs",
-    defaults: ["metalava-framework-docs-default"],
-    api_tag_name: "METALAVA_TEST",
+    name: "test-api-stubs-docs",
+    defaults: ["metalava-api-stubs-default"],
+    api_tag_name: "TEST",
     api_filename: "test-api.txt",
     removed_api_filename: "test-removed.txt",
     arg_files: [
         "core/res/AndroidManifest.xml",
     ],
     args: metalava_framework_docs_args + " --show-annotation android.annotation.TestApi",
+    check_api: {
+        current: {
+            api_file: "api/test-current.txt",
+            removed_api_file: "api/test-removed.txt",
+        },
+    },
 }
diff --git a/Android.mk b/Android.mk
index 031809c..29454e4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -171,15 +171,17 @@
     -hidePackage com.android.server
 
 # Convert an sdk level to a "since" argument.
-since-arg = -since $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(1)/public/api/android.*) $(1)
+since-arg = -since $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(1)/public/api/android.$(2)) $(1)
 
-finalized_sdks := $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.xml,%,\
-    $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.xml))
-finalized_sdks += $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.txt,%,\
-    $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.txt))
-finalized_sdks := $(call numerically_sort,$(finalized_sdks))
+finalized_xml_sdks := $(call numerically_sort,\
+    $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.xml,%,\
+    $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.xml)))
+finalized_txt_sdks := $(call numerically_sort,\
+     $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.txt,%,\
+    $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.txt)))
 
-framework_docs_LOCAL_DROIDDOC_OPTIONS += $(foreach sdk,$(finalized_sdks),$(call since-arg,$(sdk)))
+framework_docs_LOCAL_DROIDDOC_OPTIONS += $(foreach sdk,$(finalized_xml_sdks),$(call since-arg,$(sdk),xml))
+framework_docs_LOCAL_DROIDDOC_OPTIONS += $(foreach sdk,$(finalized_txt_sdks),$(call since-arg,$(sdk),txt))
 ifneq ($(PLATFORM_VERSION_CODENAME),REL)
   framework_docs_LOCAL_DROIDDOC_OPTIONS += \
       -since ./frameworks/base/api/current.txt $(PLATFORM_VERSION_CODENAME)
@@ -311,394 +313,13 @@
 $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE))
 $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE))
 
-# ====  check javadoc comments but don't generate docs ========
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-
-LOCAL_MODULE := doc-comment-check
-
-LOCAL_DROIDDOC_OPTIONS:=\
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-referenceonly \
-		-parsecomments
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_DROIDDOC)
-
-# Run this for checkbuild
-checkbuild: doc-comment-check-docs
-# Check comment when you are updating the API
-update-api: doc-comment-check-docs
-
-# ====  static html in the sdk ==================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-
-LOCAL_MODULE := offline-sdk
-
-LOCAL_DROIDDOC_OPTIONS:=\
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-offlinemode \
-		-title "Android SDK" \
-		-proofread $(OUT_DOCS)/$(LOCAL_MODULE)-proofread.txt \
-		-sdkvalues $(OUT_DOCS) \
-		-hdf android.whichdoc offline
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-static_doc_index_redirect := $(out_dir)/index.html
-$(static_doc_index_redirect): \
-	$(LOCAL_PATH)/docs/docs-preview-index.html | $(ACP)
-	$(hide) mkdir -p $(dir $@)
-	$(hide) $(ACP) $< $@
-
-$(full_target): $(static_doc_index_redirect)
-
-
-# ==== Public API static reference docs ==================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-
-LOCAL_MODULE := offline-sdk-referenceonly
-
-LOCAL_DROIDDOC_OPTIONS:=\
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-offlinemode \
-		-title "Android SDK" \
-		-proofread $(OUT_DOCS)/$(LOCAL_MODULE)-proofread.txt \
-		-sdkvalues $(OUT_DOCS) \
-		-hdf android.whichdoc offline \
-		-referenceonly
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-static_doc_index_redirect := $(out_dir)/index.html
-$(static_doc_index_redirect): $(LOCAL_PATH)/docs/docs-documentation-redirect.html
-	$(copy-file-to-target)
-
-static_doc_properties := $(out_dir)/source.properties
-$(static_doc_properties): \
-	$(LOCAL_PATH)/docs/source.properties | $(ACP)
-	$(hide) mkdir -p $(dir $@)
-	$(hide) $(ACP) $< $@
-
-$(full_target): $(static_doc_index_redirect)
-$(full_target): $(static_doc_properties)
-
-
-# ==== System API static reference docs ==================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-
-LOCAL_MODULE := offline-system-sdk-referenceonly
-
-LOCAL_DROIDDOC_OPTIONS:=\
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-hide 101 -hide 104 -hide 108 \
-		-showAnnotation android.annotation.SystemApi \
-		-offlinemode \
-		-title "Android System SDK" \
-		-proofread $(OUT_DOCS)/$(LOCAL_MODULE)-proofread.txt \
-		-sdkvalues $(OUT_DOCS) \
-		-hdf android.whichdoc offline \
-		-referenceonly
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-static_doc_index_redirect := $(out_dir)/index.html
-$(static_doc_index_redirect): $(LOCAL_PATH)/docs/docs-documentation-redirect.html
-	$(copy-file-to-target)
-
-static_doc_properties := $(out_dir)/source.properties
-$(static_doc_properties): \
-	$(LOCAL_PATH)/docs/source.properties | $(ACP)
-	$(hide) mkdir -p $(dir $@)
-	$(hide) $(ACP) $< $@
-
-$(full_target): $(static_doc_index_redirect)
-$(full_target): $(static_doc_properties)
-$(full_target): $(framework_built)
-
-
-# ==== docs for the web (on the androiddevdocs app engine server) =======================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-LOCAL_ADDITIONAL_HTML_DIR:=docs/html-intl /
-
-LOCAL_MODULE := online-sdk
-
-LOCAL_DROIDDOC_OPTIONS:= \
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-toroot / \
-		-hdf android.whichdoc online \
-		$(sample_groups) \
-		-hdf android.hasSamples true \
-		-samplesdir $(samples_dir)
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-# ==== docs for the web (on the androiddevdocs app engine server) =======================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-LOCAL_ADDITIONAL_HTML_DIR:=docs/html-intl /
-
-LOCAL_MODULE := online-system-api-sdk
-
-LOCAL_DROIDDOC_OPTIONS:= \
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-referenceonly \
-		-showAnnotation android.annotation.SystemApi \
-		-title "Android SDK - Including system APIs." \
-		-toroot / \
-		-hide 101 \
-		-hide 104 \
-		-hide 108 \
-		-hdf android.whichdoc online \
-		$(sample_groups) \
-		-hdf android.hasSamples true \
-		-samplesdir $(samples_dir)
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_DROIDDOC)
-
-# ==== docs for the web (on the devsite app engine server) =======================
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-# specify a second html input dir and an output path relative to OUT_DIR)
-LOCAL_ADDITIONAL_HTML_DIR:=docs/html-intl /
-
-LOCAL_MODULE := ds
-
-LOCAL_DROIDDOC_OPTIONS:= \
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-toroot / \
-		-hdf android.whichdoc online \
-		-devsite \
-		-yamlV2 \
-		$(sample_groups) \
-		-hdf android.hasSamples true \
-		-samplesdir $(samples_dir)
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-# ==== docs for the web (on the devsite app engine server) =======================
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-# specify a second html input dir and an output path relative to OUT_DIR)
-LOCAL_ADDITIONAL_HTML_DIR:=docs/html-intl /
-
-LOCAL_MODULE := ds-static
-
-LOCAL_DROIDDOC_OPTIONS:= \
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-hdf android.whichdoc online \
-		-staticonly \
-		-toroot / \
-		-devsite \
-		-ignoreJdLinks
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-# ==== generates full navtree for resolving @links in ds postprocessing ====
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-
-LOCAL_MODULE := ds-ref-navtree
-
-LOCAL_DROIDDOC_OPTIONS:= \
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-hdf android.whichdoc online \
-		-toroot / \
-		-atLinksNavtree \
-		-navtreeonly
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-# ==== site updates for docs (on the androiddevdocs app engine server) =======================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-LOCAL_ADDITIONAL_HTML_DIR:=docs/html-intl /
-
-LOCAL_MODULE := online-sdk-dev
-
-LOCAL_DROIDDOC_OPTIONS:= \
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-toroot / \
-		-hdf android.whichdoc online \
-		$(sample_groups) \
-		-hdf android.hasSamples true \
-		-samplesdir $(samples_dir)
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-# ==== docs that have all of the stuff that's @hidden =======================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
-LOCAL_GENERATED_SOURCES:=$(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
-LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-
-LOCAL_MODULE := hidden
-LOCAL_DROIDDOC_OPTIONS:=\
-		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		-referenceonly \
-		-title "Android SDK - Including hidden APIs."
-#		-hidden
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
-
-include $(BUILD_DROIDDOC)
-
-# ====  java proto device library (for test only)  ==============================
-include $(CLEAR_VARS)
-LOCAL_MODULE := platformprotosnano
-LOCAL_MODULE_TAGS := tests
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_PROTOC_FLAGS := \
-    -Iexternal/protobuf/src
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
-    store_unknown_fields = true
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := \
-    $(call all-proto-files-under, core/proto) \
-    $(call all-proto-files-under, libs/incident/proto/android/os)
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-
-# ====  java proto device library (for test only)  ==============================
-include $(CLEAR_VARS)
-LOCAL_MODULE := platformprotoslite
-LOCAL_MODULE_TAGS := tests
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-LOCAL_PROTOC_FLAGS := \
-    -Iexternal/protobuf/src
-LOCAL_SRC_FILES := \
-    $(call all-proto-files-under, core/proto) \
-    $(call all-proto-files-under, libs/incident/proto/android/os)
-# Protos have lots of MissingOverride and similar.
-LOCAL_ERROR_PRONE_FLAGS := -XepDisableAllChecks
-include $(BUILD_STATIC_JAVA_LIBRARY)
+# sdk.atree needs to copy the whole dir: $(OUT_DOCS)/offline-sdk to the final zip.
+# So keep offline-sdk-timestamp target here, and unzip offline-sdk-docs.zip to
+# $(OUT_DOCS)/offline-sdk.
+$(OUT_DOCS)/offline-sdk-timestamp: $(OUT_DOCS)/offline-sdk-docs-docs.zip
+	$(hide) rm -rf $(OUT_DOCS)/offline-sdk
+	$(hide) mkdir -p $(OUT_DOCS)/offline-sdk
+	( unzip -qo $< -d $(OUT_DOCS)/offline-sdk && touch -f $@ ) || exit 1
 
 # ==== hiddenapi lists =======================================
 include $(CLEAR_VARS)
@@ -712,13 +333,15 @@
 LOCAL_SRC_GREYLIST := frameworks/base/config/hiddenapi-light-greylist.txt
 LOCAL_SRC_VENDOR_LIST := frameworks/base/config/hiddenapi-vendor-list.txt
 LOCAL_SRC_FORCE_BLACKLIST := frameworks/base/config/hiddenapi-force-blacklist.txt
-LOCAL_SRC_PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
+LOCAL_SRC_PUBLIC_API := $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST)
+LOCAL_SRC_PRIVATE_API := $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST)
 LOCAL_SRC_REMOVED_API := $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE)
 
 LOCAL_SRC_ALL := \
 	$(LOCAL_SRC_GREYLIST) \
 	$(LOCAL_SRC_VENDOR_LIST) \
 	$(LOCAL_SRC_FORCE_BLACKLIST) \
+	$(LOCAL_SRC_PUBLIC_API) \
 	$(LOCAL_SRC_PRIVATE_API) \
 	$(LOCAL_SRC_REMOVED_API)
 
@@ -770,7 +393,7 @@
     "writeObject\(Ljava/io/ObjectOutputStream;\)V" \
     "writeReplace\(\)Ljava/lang/Object;"
 $(LOCAL_LIGHT_GREYLIST): $(LOCAL_SRC_ALL)
-	sort $(LOCAL_SRC_GREYLIST) $(LOCAL_SRC_VENDOR_LIST) \
+	sort $(LOCAL_SRC_GREYLIST) $(LOCAL_SRC_VENDOR_LIST) $(PRIVATE_GREYLIST_INPUTS) \
 	     <(grep -E "\->("$(subst $(space),"|",$(REGEX_SERIALIZATION))")$$" \
 	               $(LOCAL_SRC_PRIVATE_API)) \
 	     <(comm -12 <(sort $(LOCAL_SRC_REMOVED_API)) <(sort $(LOCAL_SRC_PRIVATE_API))) \
@@ -791,7 +414,8 @@
 #   (4) subtract entries shared with LOCAL_LIGHT_GREYLIST
 $(LOCAL_DARK_GREYLIST): $(LOCAL_SRC_ALL) $(LOCAL_LIGHT_GREYLIST)
 	comm -13 <(sort $(LOCAL_LIGHT_GREYLIST) $(LOCAL_SRC_FORCE_BLACKLIST)) \
-	         <(sed 's/\->.*//' $(LOCAL_LIGHT_GREYLIST) | sed 's/\(.*\/\).*/\1/' | sort | uniq | \
+	         <(cat $(LOCAL_SRC_PUBLIC_API) $(LOCAL_LIGHT_GREYLIST) | \
+	               sed 's/\->.*//' | sed 's/\(.*\/\).*/\1/' | sort | uniq | \
 	               while read PKG_NAME; do \
 	                   grep -E "^$${PKG_NAME}[^/;]*;" $(LOCAL_SRC_PRIVATE_API); \
 	               done | sort | uniq) \
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 1f8ab21..de83f3e 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,16 +1,21 @@
 [Hook Scripts]
 checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
-                  -fw core/java/android/
+                  -fw core/
                       graphics/java/android
-                      core/tests/coretests/src/android/
                       packages/PrintRecommendationService/
                       packages/PrintSpooler/
+                      packages/PackageInstaller/
                       services/print/
                       services/usb/
                       telephony/
+                      wifi/
 
 api_lint_hook = ${REPO_ROOT}/frameworks/base/tools/apilint/apilint_sha.sh ${PREUPLOAD_COMMIT}
 
 strings_lint_hook = ${REPO_ROOT}/frameworks/base/tools/stringslint/stringslint_sha.sh ${PREUPLOAD_COMMIT}
 
 hidden_api_txt_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
+
+ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
+
+owners_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "OWNERS$"
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
new file mode 100644
index 0000000..9cdeb48
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static org.junit.Assert.fail;
+
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * Benchmarks for {@link android.content.res.Resources}.
+ */
+@LargeTest
+public class ResourcesPerfTest {
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private AssetManager mAsset;
+    private Resources mRes;
+
+    private int mTextId;
+    private int mColorId;
+    private int mIntegerId;
+    private int mLayoutId;
+
+    @Before
+    public void setUp() {
+        mAsset = new AssetManager();
+        mAsset.addAssetPath("/system/framework/framework-res.apk");
+        mRes = new Resources(mAsset, null, null);
+
+        mTextId = mRes.getIdentifier("cancel", "string", "android");
+        mColorId = mRes.getIdentifier("transparent", "color", "android");
+        mIntegerId = mRes.getIdentifier("config_shortAnimTime", "integer", "android");
+        mLayoutId = mRes.getIdentifier("two_line_list_item", "layout", "android");
+    }
+
+    @After
+    public void tearDown() {
+        mAsset.close();
+    }
+
+    @Test
+    public void getText() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getText(mTextId);
+        }
+    }
+
+    @Test
+    public void getColor() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getColor(mColorId, null);
+        }
+    }
+
+    @Test
+    public void getInteger() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mRes.getInteger(mIntegerId);
+        }
+    }
+
+    @Test
+    public void getLayoutAndTravese() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            try (XmlResourceParser parser = mRes.getLayout(mLayoutId)) {
+                while (parser.next() != XmlPullParser.END_DOCUMENT) {
+                    // Walk the entire tree
+                }
+            } catch (IOException | XmlPullParserException exception) {
+                fail("Parsing of the layout failed. Something is really broken");
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java
new file mode 100644
index 0000000..bb0627e5
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/app/ResourcesThemePerfTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Benchmarks for {@link android.content.res.Resources.Theme}.
+ */
+@LargeTest
+public class ResourcesThemePerfTest {
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private Resources.Theme mTheme;
+
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getTargetContext();
+        mTheme = context.getTheme();
+
+    }
+
+    @Test
+    public void obtainStyledAttributesForViewFromMaterial() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mTheme.obtainStyledAttributes(android.R.style.Theme_Material, android.R.styleable.View);
+        }
+    }
+
+}
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
index e4a8503..66a2600d 100644
--- a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -22,6 +22,9 @@
 import android.support.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.BinderCallsStats;
+import com.android.internal.os.BinderInternal.CallSession;
+
+import java.util.Random;
 
 import org.junit.After;
 import org.junit.Before;
@@ -45,7 +48,7 @@
 
     @Before
     public void setUp() {
-        mBinderCallsStats = new BinderCallsStats(true);
+        mBinderCallsStats = new BinderCallsStats(new BinderCallsStats.Injector());
     }
 
     @After
@@ -54,25 +57,31 @@
 
     @Test
     public void timeCallSession() {
-        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        Binder b = new Binder();
-        int i = 0;
-        while (state.keepRunning()) {
-            BinderCallsStats.CallSession s = mBinderCallsStats.callStarted(b, i % 100);
-            mBinderCallsStats.callEnded(s, 0, 0);
-            i++;
-        }
+        mBinderCallsStats.setDetailedTracking(true);
+        runScenario();
+    }
+
+    @Test
+    public void timeCallSessionOnePercentSampling() {
+        mBinderCallsStats.setDetailedTracking(false);
+        mBinderCallsStats.setSamplingInterval(100);
+        runScenario();
     }
 
     @Test
     public void timeCallSessionTrackingDisabled() {
-        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        Binder b = new Binder();
-        mBinderCallsStats = new BinderCallsStats(false);
-        while (state.keepRunning()) {
-            BinderCallsStats.CallSession s = mBinderCallsStats.callStarted(b, 0);
-            mBinderCallsStats.callEnded(s, 0, 0);
-        }
+        mBinderCallsStats.setDetailedTracking(false);
+        runScenario();
     }
 
+    private void runScenario() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Binder b = new Binder();
+        while (state.keepRunning()) {
+            for (int i = 0; i < 1000; i++) {
+                CallSession s = mBinderCallsStats.callStarted(b, i % 100);
+                mBinderCallsStats.callEnded(s, 0, 0);
+            }
+        }
+    }
 }
diff --git a/apct-tests/perftests/core/src/android/os/TracePerfTest.java b/apct-tests/perftests/core/src/android/os/TracePerfTest.java
new file mode 100644
index 0000000..8e5cfaa
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/TracePerfTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+
+package android.os;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.perftests.utils.ShellHelper;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class TracePerfTest {
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @BeforeClass
+    public static void startTracing() {
+        ShellHelper.runShellCommandRaw("atrace -c --async_start -a *");
+    }
+
+    @AfterClass
+    public static void endTracing() {
+        ShellHelper.runShellCommandRaw("atrace --async_stop");
+    }
+
+    @Before
+    public void verifyTracingEnabled() {
+        Assert.assertTrue(Trace.isEnabled());
+    }
+
+    @Test
+    public void testEnabled() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Trace.isEnabled();
+        }
+    }
+
+    @Test
+    public void testBeginEndSection() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Trace.beginSection("testBeginEndSection");
+            Trace.endSection();
+        }
+    }
+
+    @Test
+    public void testAsyncBeginEnd() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Trace.beginAsyncSection("testAsyncBeginEnd", 42);
+            Trace.endAsyncSection("testAsyncBeginEnd", 42);
+        }
+    }
+
+    @Test
+    public void testCounter() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Trace.setCounter("testCounter", 123);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/text/BoringLayoutCreateDrawPerfTest.java b/apct-tests/perftests/core/src/android/text/BoringLayoutCreateDrawPerfTest.java
index 586c385..64f2800 100644
--- a/apct-tests/perftests/core/src/android/text/BoringLayoutCreateDrawPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/BoringLayoutCreateDrawPerfTest.java
@@ -46,7 +46,7 @@
     private static final float SPACING_ADD = 10f;
     private static final float SPACING_MULT = 1.5f;
 
-    @Parameterized.Parameters(name = "cached={3},{1}chars,{0}")
+    @Parameterized.Parameters(name = "cached {3} {1}chars {0}")
     public static Collection cases() {
         final List<Object[]> params = new ArrayList<>();
         for (int length : new int[]{128}) {
diff --git a/apct-tests/perftests/core/src/android/text/BoringLayoutIsBoringPerfTest.java b/apct-tests/perftests/core/src/android/text/BoringLayoutIsBoringPerfTest.java
index 9d11f29..194a88c 100644
--- a/apct-tests/perftests/core/src/android/text/BoringLayoutIsBoringPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/BoringLayoutIsBoringPerfTest.java
@@ -40,7 +40,7 @@
 
     private static final boolean[] BOOLEANS = new boolean[]{false, true};
 
-    @Parameterized.Parameters(name = "cached={4},{1}chars,{0}")
+    @Parameterized.Parameters(name = "cached {4} {1}chars {0}")
     public static Collection cases() {
         final List<Object[]> params = new ArrayList<>();
         for (int length : new int[]{128}) {
diff --git a/apct-tests/perftests/core/src/android/text/PaintMeasureDrawPerfTest.java b/apct-tests/perftests/core/src/android/text/PaintMeasureDrawPerfTest.java
index 6768798..ad5a34e 100644
--- a/apct-tests/perftests/core/src/android/text/PaintMeasureDrawPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/PaintMeasureDrawPerfTest.java
@@ -42,7 +42,7 @@
 
     private static final boolean[] BOOLEANS = new boolean[]{false, true};
 
-    @Parameterized.Parameters(name = "cached={1},{0}chars")
+    @Parameterized.Parameters(name = "cached {1} {0}chars")
     public static Collection cases() {
         final List<Object[]> params = new ArrayList<>();
         for (int length : new int[]{128}) {
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutCreateDrawPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutCreateDrawPerfTest.java
index bfdb758..deb2b0a 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutCreateDrawPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutCreateDrawPerfTest.java
@@ -50,7 +50,7 @@
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
 
-    @Parameterized.Parameters(name = "cached={3},{1}chars,{0}")
+    @Parameterized.Parameters(name = "cached {3} {1}chars {0}")
     public static Collection cases() {
         final List<Object[]> params = new ArrayList<>();
         for (int length : new int[]{128}) {
diff --git a/apct-tests/perftests/core/src/android/text/TextViewSetTextMeasurePerfTest.java b/apct-tests/perftests/core/src/android/text/TextViewSetTextMeasurePerfTest.java
index ff2d57e..4bbe404 100644
--- a/apct-tests/perftests/core/src/android/text/TextViewSetTextMeasurePerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/TextViewSetTextMeasurePerfTest.java
@@ -51,7 +51,7 @@
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
 
-    @Parameterized.Parameters(name = "cached={3},{1}chars,{0}")
+    @Parameterized.Parameters(name = "cached {3} {1}chars {0}")
     public static Collection cases() {
         final List<Object[]> params = new ArrayList<>();
         for (int length : new int[]{128}) {
@@ -92,6 +92,8 @@
         Canvas.freeTextLayoutCaches();
         final CharSequence text = createRandomText(mLength);
         final TextView textView = new TextView(InstrumentationRegistry.getTargetContext());
+        textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE);
+
         textView.setText(text);
         state.resumeTiming();
 
@@ -119,6 +121,7 @@
         final RenderNode node = RenderNode.create("benchmark", null);
         final CharSequence text = createRandomText(mLength);
         final TextView textView = new TextView(InstrumentationRegistry.getTargetContext());
+        textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE);
         textView.setText(text);
         state.resumeTiming();
 
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
index cae87fb..895547d 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
@@ -37,6 +37,14 @@
     @NonNull
     public static String runShellCommand(@NonNull String template, Object...args) {
         String command = String.format(template, args);
+        return runShellCommandRaw(command);
+    }
+
+    /**
+     * Runs a Shell command, returning a trimmed response.
+     */
+    @NonNull
+    public static String runShellCommandRaw(@NonNull String command) {
         UiAutomation automan = InstrumentationRegistry.getInstrumentation()
                 .getUiAutomation();
         ParcelFileDescriptor pfd = automan.executeShellCommand(command);
diff --git a/api/current.txt b/api/current.txt
index c641a8c..13ea5cc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11,6 +11,7 @@
     field public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
     field public static final java.lang.String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
     field public static final java.lang.String ACCESS_LOCATION_EXTRA_COMMANDS = "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS";
+    field public static final java.lang.String ACCESS_MEDIA_LOCATION = "android.permission.ACCESS_MEDIA_LOCATION";
     field public static final java.lang.String ACCESS_NETWORK_STATE = "android.permission.ACCESS_NETWORK_STATE";
     field public static final java.lang.String ACCESS_NOTIFICATION_POLICY = "android.permission.ACCESS_NOTIFICATION_POLICY";
     field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE";
@@ -101,10 +102,13 @@
     field public static final java.lang.String READ_CALENDAR = "android.permission.READ_CALENDAR";
     field public static final java.lang.String READ_CALL_LOG = "android.permission.READ_CALL_LOG";
     field public static final java.lang.String READ_CONTACTS = "android.permission.READ_CONTACTS";
-    field public static final java.lang.String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";
+    field public static final deprecated java.lang.String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";
     field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
     field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
     field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
+    field public static final java.lang.String READ_MEDIA_AUDIO = "android.permission.READ_MEDIA_AUDIO";
+    field public static final java.lang.String READ_MEDIA_IMAGES = "android.permission.READ_MEDIA_IMAGES";
+    field public static final java.lang.String READ_MEDIA_VIDEO = "android.permission.READ_MEDIA_VIDEO";
     field public static final java.lang.String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
     field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
     field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
@@ -151,8 +155,11 @@
     field public static final java.lang.String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR";
     field public static final java.lang.String WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG";
     field public static final java.lang.String WRITE_CONTACTS = "android.permission.WRITE_CONTACTS";
-    field public static final java.lang.String WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
+    field public static final deprecated java.lang.String WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
     field public static final java.lang.String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES";
+    field public static final java.lang.String WRITE_MEDIA_AUDIO = "android.permission.WRITE_MEDIA_AUDIO";
+    field public static final java.lang.String WRITE_MEDIA_IMAGES = "android.permission.WRITE_MEDIA_IMAGES";
+    field public static final java.lang.String WRITE_MEDIA_VIDEO = "android.permission.WRITE_MEDIA_VIDEO";
     field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
     field public static final java.lang.String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS";
     field public static final java.lang.String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS";
@@ -166,11 +173,13 @@
     field public static final java.lang.String CAMERA = "android.permission-group.CAMERA";
     field public static final java.lang.String CONTACTS = "android.permission-group.CONTACTS";
     field public static final java.lang.String LOCATION = "android.permission-group.LOCATION";
+    field public static final java.lang.String MEDIA_AURAL = "android.permission-group.MEDIA_AURAL";
+    field public static final java.lang.String MEDIA_VISUAL = "android.permission-group.MEDIA_VISUAL";
     field public static final java.lang.String MICROPHONE = "android.permission-group.MICROPHONE";
     field public static final java.lang.String PHONE = "android.permission-group.PHONE";
     field public static final java.lang.String SENSORS = "android.permission-group.SENSORS";
     field public static final java.lang.String SMS = "android.permission-group.SMS";
-    field public static final java.lang.String STORAGE = "android.permission-group.STORAGE";
+    field public static final deprecated java.lang.String STORAGE = "android.permission-group.STORAGE";
   }
 
   public final class R {
@@ -272,6 +281,7 @@
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
     field public static final int allowEmbedded = 16843765; // 0x10103f5
+    field public static final int allowForceDark = 16844171; // 0x101058b
     field public static final int allowParallelSyncs = 16843570; // 0x1010332
     field public static final int allowSingleTap = 16843353; // 0x1010259
     field public static final int allowTaskReparenting = 16843268; // 0x1010204
@@ -1294,6 +1304,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
+    field public static final int supportsAmbientMode = 16844172; // 0x101058c
     field public static final int supportsAssist = 16844016; // 0x10104f0
     field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
     field public static final int supportsLocalInteraction = 16844047; // 0x101050f
@@ -1321,7 +1332,7 @@
     field public static final int targetName = 16843853; // 0x101044d
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetProcesses = 16844097; // 0x1010541
-    field public static final int targetSandboxVersion = 16844108; // 0x101054c
+    field public static final deprecated int targetSandboxVersion = 16844108; // 0x101054c
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
     field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
@@ -2818,6 +2829,7 @@
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
     field public static final int SHOW_MODE_AUTO = 0; // 0x0
     field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
+    field public static final int SHOW_MODE_WITH_HARD_KEYBOARD = 2; // 0x2
   }
 
   public static abstract class AccessibilityService.GestureResultCallback {
@@ -3951,22 +3963,16 @@
     field public int uid;
   }
 
-  public static class ActivityManager.RecentTaskInfo implements android.os.Parcelable {
+  public static class ActivityManager.RecentTaskInfo extends android.app.TaskInfo implements android.os.Parcelable {
     ctor public ActivityManager.RecentTaskInfo();
     method public int describeContents();
     method public void readFromParcel(android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RecentTaskInfo> CREATOR;
-    field public int affiliatedTaskId;
-    field public android.content.ComponentName baseActivity;
-    field public android.content.Intent baseIntent;
-    field public java.lang.CharSequence description;
-    field public int id;
-    field public int numActivities;
-    field public android.content.ComponentName origActivity;
-    field public int persistentId;
-    field public android.app.ActivityManager.TaskDescription taskDescription;
-    field public android.content.ComponentName topActivity;
+    field public deprecated int affiliatedTaskId;
+    field public deprecated java.lang.CharSequence description;
+    field public deprecated int id;
+    field public deprecated int persistentId;
   }
 
   public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable {
@@ -4030,19 +4036,16 @@
     field public int uid;
   }
 
-  public static class ActivityManager.RunningTaskInfo implements android.os.Parcelable {
+  public static class ActivityManager.RunningTaskInfo extends android.app.TaskInfo implements android.os.Parcelable {
     ctor public ActivityManager.RunningTaskInfo();
     method public int describeContents();
     method public void readFromParcel(android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RunningTaskInfo> CREATOR;
-    field public android.content.ComponentName baseActivity;
-    field public java.lang.CharSequence description;
-    field public int id;
-    field public int numActivities;
-    field public int numRunning;
-    field public android.graphics.Bitmap thumbnail;
-    field public android.content.ComponentName topActivity;
+    field public deprecated java.lang.CharSequence description;
+    field public deprecated int id;
+    field public deprecated int numRunning;
+    field public deprecated android.graphics.Bitmap thumbnail;
   }
 
   public static class ActivityManager.TaskDescription implements android.os.Parcelable {
@@ -6091,6 +6094,17 @@
     method public void setDefaultTab(int);
   }
 
+  public class TaskInfo {
+    field public android.content.ComponentName baseActivity;
+    field public android.content.Intent baseIntent;
+    field public boolean isRunning;
+    field public int numActivities;
+    field public android.content.ComponentName origActivity;
+    field public android.app.ActivityManager.TaskDescription taskDescription;
+    field public int taskId;
+    field public android.content.ComponentName topActivity;
+  }
+
   public class TaskStackBuilder {
     method public android.app.TaskStackBuilder addNextIntent(android.content.Intent);
     method public android.app.TaskStackBuilder addNextIntentWithParentStack(android.content.Intent);
@@ -6120,8 +6134,10 @@
   }
 
   public final class UiAutomation {
+    method public void adoptShellPermissionIdentity();
     method public void clearWindowAnimationFrameStats();
     method public boolean clearWindowContentFrameStats(int);
+    method public void dropShellPermissionIdentity();
     method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
     method public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
@@ -6275,6 +6291,7 @@
     method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
     method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
     method public android.graphics.drawable.Drawable loadThumbnail(android.content.pm.PackageManager);
+    method public boolean supportsAmbientMode();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.WallpaperInfo> CREATOR;
   }
@@ -9135,6 +9152,7 @@
     method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException;
     method public final android.net.Uri canonicalize(android.net.Uri) throws android.os.RemoteException;
     method public void close();
+    method public static void closeQuietly(android.content.ContentProviderClient);
     method public int delete(android.net.Uri, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
     method public android.content.ContentProvider getLocalContentProvider();
     method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String) throws android.os.RemoteException;
@@ -11232,6 +11250,7 @@
     method public abstract boolean hasSystemFeature(java.lang.String, int);
     method public abstract boolean isInstantApp();
     method public abstract boolean isInstantApp(java.lang.String);
+    method public boolean isPackageSuspended(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean isPackageSuspended();
     method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public abstract boolean isSafeMode();
@@ -11903,7 +11922,7 @@
     method public int[] getIntArray(int) throws android.content.res.Resources.NotFoundException;
     method public int getInteger(int) throws android.content.res.Resources.NotFoundException;
     method public android.content.res.XmlResourceParser getLayout(int) throws android.content.res.Resources.NotFoundException;
-    method public android.graphics.Movie getMovie(int) throws android.content.res.Resources.NotFoundException;
+    method public deprecated android.graphics.Movie getMovie(int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getQuantityString(int, int, java.lang.Object...) throws android.content.res.Resources.NotFoundException;
     method public java.lang.String getQuantityString(int, int) throws android.content.res.Resources.NotFoundException;
     method public java.lang.CharSequence getQuantityText(int, int) throws android.content.res.Resources.NotFoundException;
@@ -12668,12 +12687,14 @@
     method public static void appendColumns(java.lang.StringBuilder, java.lang.String[]);
     method public void appendWhere(java.lang.CharSequence);
     method public void appendWhereEscapeString(java.lang.String);
+    method public void appendWhereStandalone(java.lang.CharSequence);
     method public java.lang.String buildQuery(java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public deprecated java.lang.String buildQuery(java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public static java.lang.String buildQueryString(boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public java.lang.String buildUnionQuery(java.lang.String[], java.lang.String, java.lang.String);
     method public java.lang.String buildUnionSubQuery(java.lang.String, java.lang.String[], java.util.Set<java.lang.String>, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public deprecated java.lang.String buildUnionSubQuery(java.lang.String, java.lang.String[], java.util.Set<java.lang.String>, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.lang.String);
+    method public int delete(android.database.sqlite.SQLiteDatabase, java.lang.String, java.lang.String[]);
     method public java.lang.String getTables();
     method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String);
     method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -12683,6 +12704,7 @@
     method public void setProjectionMap(java.util.Map<java.lang.String, java.lang.String>);
     method public void setStrict(boolean);
     method public void setTables(java.lang.String);
+    method public int update(android.database.sqlite.SQLiteDatabase, android.content.ContentValues, java.lang.String, java.lang.String[]);
   }
 
   public class SQLiteReadOnlyDatabaseException extends android.database.sqlite.SQLiteException {
@@ -14704,6 +14726,22 @@
     method public void setColorFilter(android.graphics.ColorFilter);
   }
 
+  public class ColorStateListDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    ctor public ColorStateListDrawable();
+    ctor public ColorStateListDrawable(android.content.res.ColorStateList);
+    method public void clearAlpha();
+    method public void draw(android.graphics.Canvas);
+    method public android.content.res.ColorStateList getColorStateList();
+    method public int getOpacity();
+    method public boolean hasFocusStateSpecified();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setColorStateList(android.content.res.ColorStateList);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
   public abstract class Drawable {
     ctor public Drawable();
     method public void applyTheme(android.content.res.Resources.Theme);
@@ -15168,6 +15206,48 @@
 
 package android.graphics.fonts {
 
+  public final class Font {
+    method public android.graphics.fonts.FontVariationAxis[] getAxes();
+    method public int getTtcIndex();
+    method public int getWeight();
+    method public boolean isItalic();
+    field public static final int FONT_WEIGHT_BLACK = 900; // 0x384
+    field public static final int FONT_WEIGHT_BOLD = 700; // 0x2bc
+    field public static final int FONT_WEIGHT_EXTRA_BOLD = 800; // 0x320
+    field public static final int FONT_WEIGHT_EXTRA_LIGHT = 200; // 0xc8
+    field public static final int FONT_WEIGHT_LIGHT = 300; // 0x12c
+    field public static final int FONT_WEIGHT_MEDIUM = 500; // 0x1f4
+    field public static final int FONT_WEIGHT_NORMAL = 400; // 0x190
+    field public static final int FONT_WEIGHT_SEMI_BOLD = 600; // 0x258
+    field public static final int FONT_WEIGHT_THIN = 100; // 0x64
+  }
+
+  public static class Font.Builder {
+    ctor public Font.Builder(java.nio.ByteBuffer);
+    ctor public Font.Builder(java.io.File);
+    ctor public Font.Builder(java.io.FileDescriptor);
+    ctor public Font.Builder(java.io.FileDescriptor, long, long);
+    ctor public Font.Builder(android.content.res.AssetManager, java.lang.String);
+    ctor public Font.Builder(android.content.res.Resources, int);
+    method public android.graphics.fonts.Font build() throws java.io.IOException;
+    method public android.graphics.fonts.Font.Builder setFontVariationSettings(java.lang.String);
+    method public android.graphics.fonts.Font.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
+    method public android.graphics.fonts.Font.Builder setItalic(boolean);
+    method public android.graphics.fonts.Font.Builder setTtcIndex(int);
+    method public android.graphics.fonts.Font.Builder setWeight(int);
+  }
+
+  public final class FontFamily {
+    method public android.graphics.fonts.Font getFont(int);
+    method public int getSize();
+  }
+
+  public static class FontFamily.Builder {
+    ctor public FontFamily.Builder(android.graphics.fonts.Font);
+    method public android.graphics.fonts.FontFamily.Builder addFont(android.graphics.fonts.Font);
+    method public android.graphics.fonts.FontFamily build();
+  }
+
   public final class FontVariationAxis {
     ctor public FontVariationAxis(java.lang.String, float);
     method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String);
@@ -17125,6 +17205,8 @@
     field public static final int GAMAL = 12; // 0xc
     field public static final int HAH = 13; // 0xd
     field public static final int HAMZA_ON_HEH_GOAL = 14; // 0xe
+    field public static final int HANIFI_ROHINGYA_KINNA_YA = 100; // 0x64
+    field public static final int HANIFI_ROHINGYA_PA = 101; // 0x65
     field public static final int HE = 15; // 0xf
     field public static final int HEH = 16; // 0x10
     field public static final int HEH_GOAL = 17; // 0x11
@@ -17376,6 +17458,8 @@
     field public static final int CHEROKEE_ID = 32; // 0x20
     field public static final android.icu.lang.UCharacter.UnicodeBlock CHEROKEE_SUPPLEMENT;
     field public static final int CHEROKEE_SUPPLEMENT_ID = 255; // 0xff
+    field public static final android.icu.lang.UCharacter.UnicodeBlock CHESS_SYMBOLS;
+    field public static final int CHESS_SYMBOLS_ID = 281; // 0x119
     field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY;
     field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY_FORMS;
     field public static final int CJK_COMPATIBILITY_FORMS_ID = 83; // 0x53
@@ -17452,6 +17536,8 @@
     field public static final int DEVANAGARI_ID = 15; // 0xf
     field public static final android.icu.lang.UCharacter.UnicodeBlock DINGBATS;
     field public static final int DINGBATS_ID = 56; // 0x38
+    field public static final android.icu.lang.UCharacter.UnicodeBlock DOGRA;
+    field public static final int DOGRA_ID = 282; // 0x11a
     field public static final android.icu.lang.UCharacter.UnicodeBlock DOMINO_TILES;
     field public static final int DOMINO_TILES_ID = 171; // 0xab
     field public static final android.icu.lang.UCharacter.UnicodeBlock DUPLOYAN;
@@ -17487,6 +17573,8 @@
     field public static final int GEOMETRIC_SHAPES_EXTENDED_ID = 227; // 0xe3
     field public static final int GEOMETRIC_SHAPES_ID = 54; // 0x36
     field public static final android.icu.lang.UCharacter.UnicodeBlock GEORGIAN;
+    field public static final android.icu.lang.UCharacter.UnicodeBlock GEORGIAN_EXTENDED;
+    field public static final int GEORGIAN_EXTENDED_ID = 283; // 0x11b
     field public static final int GEORGIAN_ID = 29; // 0x1d
     field public static final android.icu.lang.UCharacter.UnicodeBlock GEORGIAN_SUPPLEMENT;
     field public static final int GEORGIAN_SUPPLEMENT_ID = 135; // 0x87
@@ -17504,6 +17592,8 @@
     field public static final int GREEK_ID = 8; // 0x8
     field public static final android.icu.lang.UCharacter.UnicodeBlock GUJARATI;
     field public static final int GUJARATI_ID = 18; // 0x12
+    field public static final android.icu.lang.UCharacter.UnicodeBlock GUNJALA_GONDI;
+    field public static final int GUNJALA_GONDI_ID = 284; // 0x11c
     field public static final android.icu.lang.UCharacter.UnicodeBlock GURMUKHI;
     field public static final int GURMUKHI_ID = 17; // 0x11
     field public static final android.icu.lang.UCharacter.UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS;
@@ -17518,6 +17608,8 @@
     field public static final int HANGUL_JAMO_ID = 30; // 0x1e
     field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_SYLLABLES;
     field public static final int HANGUL_SYLLABLES_ID = 74; // 0x4a
+    field public static final android.icu.lang.UCharacter.UnicodeBlock HANIFI_ROHINGYA;
+    field public static final int HANIFI_ROHINGYA_ID = 285; // 0x11d
     field public static final android.icu.lang.UCharacter.UnicodeBlock HANUNOO;
     field public static final int HANUNOO_ID = 99; // 0x63
     field public static final android.icu.lang.UCharacter.UnicodeBlock HATRAN;
@@ -17536,6 +17628,8 @@
     field public static final int IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION_ID = 267; // 0x10b
     field public static final android.icu.lang.UCharacter.UnicodeBlock IMPERIAL_ARAMAIC;
     field public static final int IMPERIAL_ARAMAIC_ID = 186; // 0xba
+    field public static final android.icu.lang.UCharacter.UnicodeBlock INDIC_SIYAQ_NUMBERS;
+    field public static final int INDIC_SIYAQ_NUMBERS_ID = 286; // 0x11e
     field public static final android.icu.lang.UCharacter.UnicodeBlock INSCRIPTIONAL_PAHLAVI;
     field public static final int INSCRIPTIONAL_PAHLAVI_ID = 190; // 0xbe
     field public static final android.icu.lang.UCharacter.UnicodeBlock INSCRIPTIONAL_PARTHIAN;
@@ -17614,6 +17708,8 @@
     field public static final int MAHAJANI_ID = 233; // 0xe9
     field public static final android.icu.lang.UCharacter.UnicodeBlock MAHJONG_TILES;
     field public static final int MAHJONG_TILES_ID = 170; // 0xaa
+    field public static final android.icu.lang.UCharacter.UnicodeBlock MAKASAR;
+    field public static final int MAKASAR_ID = 287; // 0x11f
     field public static final android.icu.lang.UCharacter.UnicodeBlock MALAYALAM;
     field public static final int MALAYALAM_ID = 23; // 0x17
     field public static final android.icu.lang.UCharacter.UnicodeBlock MANDAIC;
@@ -17628,6 +17724,10 @@
     field public static final int MATHEMATICAL_ALPHANUMERIC_SYMBOLS_ID = 93; // 0x5d
     field public static final android.icu.lang.UCharacter.UnicodeBlock MATHEMATICAL_OPERATORS;
     field public static final int MATHEMATICAL_OPERATORS_ID = 47; // 0x2f
+    field public static final android.icu.lang.UCharacter.UnicodeBlock MAYAN_NUMERALS;
+    field public static final int MAYAN_NUMERALS_ID = 288; // 0x120
+    field public static final android.icu.lang.UCharacter.UnicodeBlock MEDEFAIDRIN;
+    field public static final int MEDEFAIDRIN_ID = 289; // 0x121
     field public static final android.icu.lang.UCharacter.UnicodeBlock MEETEI_MAYEK;
     field public static final android.icu.lang.UCharacter.UnicodeBlock MEETEI_MAYEK_EXTENSIONS;
     field public static final int MEETEI_MAYEK_EXTENSIONS_ID = 213; // 0xd5
@@ -17697,6 +17797,8 @@
     field public static final int OLD_PERMIC_ID = 241; // 0xf1
     field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_PERSIAN;
     field public static final int OLD_PERSIAN_ID = 140; // 0x8c
+    field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_SOGDIAN;
+    field public static final int OLD_SOGDIAN_ID = 290; // 0x122
     field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_SOUTH_ARABIAN;
     field public static final int OLD_SOUTH_ARABIAN_ID = 187; // 0xbb
     field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_TURKIC;
@@ -17761,6 +17863,8 @@
     field public static final int SINHALA_ID = 24; // 0x18
     field public static final android.icu.lang.UCharacter.UnicodeBlock SMALL_FORM_VARIANTS;
     field public static final int SMALL_FORM_VARIANTS_ID = 84; // 0x54
+    field public static final android.icu.lang.UCharacter.UnicodeBlock SOGDIAN;
+    field public static final int SOGDIAN_ID = 291; // 0x123
     field public static final android.icu.lang.UCharacter.UnicodeBlock SORA_SOMPENG;
     field public static final int SORA_SOMPENG_ID = 218; // 0xda
     field public static final android.icu.lang.UCharacter.UnicodeBlock SOYOMBO;
@@ -17885,6 +17989,7 @@
     field public static final int OTHER = 0; // 0x0
     field public static final int REGIONAL_INDICATOR = 13; // 0xd
     field public static final int SINGLE_QUOTE = 15; // 0xf
+    field public static final int WSEGSPACE = 22; // 0x16
     field public static final int ZWJ = 21; // 0x15
   }
 
@@ -18016,6 +18121,7 @@
     field public static final int EMOJI_MODIFIER = 59; // 0x3b
     field public static final int EMOJI_MODIFIER_BASE = 60; // 0x3c
     field public static final int EMOJI_PRESENTATION = 58; // 0x3a
+    field public static final int EXTENDED_PICTOGRAPHIC = 64; // 0x40
     field public static final int EXTENDER = 8; // 0x8
     field public static final int FULL_COMPOSITION_EXCLUSION = 9; // 0x9
     field public static final int GENERAL_CATEGORY = 4101; // 0x1005
@@ -18146,6 +18252,7 @@
     field public static final int DEMOTIC_EGYPTIAN = 69; // 0x45
     field public static final int DESERET = 9; // 0x9
     field public static final int DEVANAGARI = 10; // 0xa
+    field public static final int DOGRA = 178; // 0xb2
     field public static final int DUPLOYAN = 135; // 0x87
     field public static final int EASTERN_SYRIAC = 97; // 0x61
     field public static final int EGYPTIAN_HIEROGLYPHS = 71; // 0x47
@@ -18158,9 +18265,11 @@
     field public static final int GRANTHA = 137; // 0x89
     field public static final int GREEK = 14; // 0xe
     field public static final int GUJARATI = 15; // 0xf
+    field public static final int GUNJALA_GONDI = 179; // 0xb3
     field public static final int GURMUKHI = 16; // 0x10
     field public static final int HAN = 17; // 0x11
     field public static final int HANGUL = 18; // 0x12
+    field public static final int HANIFI_ROHINGYA = 182; // 0xb6
     field public static final int HANUNOO = 43; // 0x2b
     field public static final int HAN_WITH_BOPOMOFO = 172; // 0xac
     field public static final int HARAPPAN_INDUS = 77; // 0x4d
@@ -18203,6 +18312,7 @@
     field public static final int LYCIAN = 107; // 0x6b
     field public static final int LYDIAN = 108; // 0x6c
     field public static final int MAHAJANI = 160; // 0xa0
+    field public static final int MAKASAR = 180; // 0xb4
     field public static final int MALAYALAM = 26; // 0x1a
     field public static final int MANDAEAN = 84; // 0x54
     field public static final int MANDAIC = 84; // 0x54
@@ -18211,6 +18321,7 @@
     field public static final int MASARAM_GONDI = 175; // 0xaf
     field public static final int MATHEMATICAL_NOTATION = 128; // 0x80
     field public static final int MAYAN_HIEROGLYPHS = 85; // 0x55
+    field public static final int MEDEFAIDRIN = 181; // 0xb5
     field public static final int MEITEI_MAYEK = 115; // 0x73
     field public static final int MENDE = 140; // 0x8c
     field public static final int MEROITIC = 86; // 0x56
@@ -18236,6 +18347,7 @@
     field public static final int OLD_NORTH_ARABIAN = 142; // 0x8e
     field public static final int OLD_PERMIC = 89; // 0x59
     field public static final int OLD_PERSIAN = 61; // 0x3d
+    field public static final int OLD_SOGDIAN = 184; // 0xb8
     field public static final int OLD_SOUTH_ARABIAN = 133; // 0x85
     field public static final int OL_CHIKI = 109; // 0x6d
     field public static final int ORIYA = 31; // 0x1f
@@ -18262,6 +18374,7 @@
     field public static final int SIMPLIFIED_HAN = 73; // 0x49
     field public static final int SINDHI = 145; // 0x91
     field public static final int SINHALA = 33; // 0x21
+    field public static final int SOGDIAN = 183; // 0xb7
     field public static final int SORA_SOMPENG = 152; // 0x98
     field public static final int SOYOMBO = 176; // 0xb0
     field public static final int SUNDANESE = 113; // 0x71
@@ -21203,6 +21316,7 @@
     field public static final android.icu.util.VersionInfo UCOL_BUILDER_VERSION;
     field public static final android.icu.util.VersionInfo UCOL_RUNTIME_VERSION;
     field public static final android.icu.util.VersionInfo UNICODE_10_0;
+    field public static final android.icu.util.VersionInfo UNICODE_11_0;
     field public static final android.icu.util.VersionInfo UNICODE_1_0;
     field public static final android.icu.util.VersionInfo UNICODE_1_0_1;
     field public static final android.icu.util.VersionInfo UNICODE_1_1_0;
@@ -27628,6 +27742,7 @@
     method public java.util.Date getValidNotAfterDate();
     method public deprecated java.lang.String getValidNotBefore();
     method public java.util.Date getValidNotBeforeDate();
+    method public java.security.cert.X509Certificate getX509Certificate();
     method public static android.net.http.SslCertificate restoreState(android.os.Bundle);
     method public static android.os.Bundle saveState(android.net.http.SslCertificate);
   }
@@ -32130,6 +32245,7 @@
 
   public class Binder implements android.os.IBinder {
     ctor public Binder();
+    ctor public Binder(java.lang.String);
     method public void attachInterface(android.os.IInterface, java.lang.String);
     method public static final long clearCallingIdentity();
     method public void dump(java.io.FileDescriptor, java.lang.String[]);
@@ -32545,6 +32661,21 @@
     ctor public FileUriExposedException(java.lang.String);
   }
 
+  public class FileUtils {
+    method public static void closeQuietly(java.lang.AutoCloseable);
+    method public static void closeQuietly(java.io.FileDescriptor);
+    method public static long copy(java.io.File, java.io.File) throws java.io.IOException;
+    method public static long copy(java.io.File, java.io.File, android.os.CancellationSignal, java.util.concurrent.Executor, android.os.FileUtils.ProgressListener) throws java.io.IOException;
+    method public static long copy(java.io.InputStream, java.io.OutputStream) throws java.io.IOException;
+    method public static long copy(java.io.InputStream, java.io.OutputStream, android.os.CancellationSignal, java.util.concurrent.Executor, android.os.FileUtils.ProgressListener) throws java.io.IOException;
+    method public static long copy(java.io.FileDescriptor, java.io.FileDescriptor) throws java.io.IOException;
+    method public static long copy(java.io.FileDescriptor, java.io.FileDescriptor, android.os.CancellationSignal, java.util.concurrent.Executor, android.os.FileUtils.ProgressListener) throws java.io.IOException;
+  }
+
+  public static abstract interface FileUtils.ProgressListener {
+    method public abstract void onProgress(long);
+  }
+
   public class Handler {
     ctor public Handler();
     ctor public Handler(android.os.Handler.Callback);
@@ -32811,6 +32942,7 @@
     method public void readMap(java.util.Map, java.lang.ClassLoader);
     method public <T extends android.os.Parcelable> T readParcelable(java.lang.ClassLoader);
     method public android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
+    method public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(java.util.List<T>, java.lang.ClassLoader);
     method public android.os.PersistableBundle readPersistableBundle();
     method public android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
     method public java.io.Serializable readSerializable();
@@ -32857,6 +32989,7 @@
     method public void writeNoException();
     method public void writeParcelable(android.os.Parcelable, int);
     method public <T extends android.os.Parcelable> void writeParcelableArray(T[], int);
+    method public <T extends android.os.Parcelable> void writeParcelableList(java.util.List<T>, int);
     method public void writePersistableBundle(android.os.PersistableBundle);
     method public void writeSerializable(java.io.Serializable);
     method public void writeSize(android.util.Size);
@@ -33208,6 +33341,7 @@
     method public android.os.StrictMode.VmPolicy.Builder detectAll();
     method public android.os.StrictMode.VmPolicy.Builder detectCleartextNetwork();
     method public android.os.StrictMode.VmPolicy.Builder detectContentUriWithoutPermission();
+    method public android.os.StrictMode.VmPolicy.Builder detectCredentialProtectedWhileLocked();
     method public android.os.StrictMode.VmPolicy.Builder detectFileUriExposure();
     method public android.os.StrictMode.VmPolicy.Builder detectImplicitDirectBoot();
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
@@ -33257,8 +33391,12 @@
   }
 
   public final class Trace {
+    method public static void beginAsyncSection(java.lang.String, int);
     method public static void beginSection(java.lang.String);
+    method public static void endAsyncSection(java.lang.String, int);
     method public static void endSection();
+    method public static boolean isEnabled();
+    method public static void setCounter(java.lang.String, int);
   }
 
   public class TransactionTooLargeException extends android.os.RemoteException {
@@ -33611,6 +33749,9 @@
   public final class ContentUriWithoutPermissionViolation extends android.os.strictmode.Violation {
   }
 
+  public final class CredentialProtectedWhileLockedViolation extends android.os.strictmode.Violation {
+  }
+
   public final class CustomViolation extends android.os.strictmode.Violation {
   }
 
@@ -35507,11 +35648,11 @@
 
   protected static abstract interface ContactsContract.ContactOptionsColumns {
     field public static final java.lang.String CUSTOM_RINGTONE = "custom_ringtone";
-    field public static final java.lang.String LAST_TIME_CONTACTED = "last_time_contacted";
+    field public static final deprecated java.lang.String LAST_TIME_CONTACTED = "last_time_contacted";
     field public static final java.lang.String PINNED = "pinned";
     field public static final java.lang.String SEND_TO_VOICEMAIL = "send_to_voicemail";
     field public static final java.lang.String STARRED = "starred";
-    field public static final java.lang.String TIMES_CONTACTED = "times_contacted";
+    field public static final deprecated java.lang.String TIMES_CONTACTED = "times_contacted";
   }
 
   protected static abstract interface ContactsContract.ContactStatusColumns {
@@ -35533,7 +35674,7 @@
     method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri, boolean);
     method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri);
     field public static final android.net.Uri CONTENT_FILTER_URI;
-    field public static final android.net.Uri CONTENT_FREQUENT_URI;
+    field public static final deprecated android.net.Uri CONTENT_FREQUENT_URI;
     field public static final android.net.Uri CONTENT_GROUP_URI;
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact";
     field public static final android.net.Uri CONTENT_LOOKUP_URI;
@@ -35641,7 +35782,7 @@
   protected static abstract interface ContactsContract.DataColumnsWithJoins implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.DataUsageStatColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns {
   }
 
-  public static final class ContactsContract.DataUsageFeedback {
+  public static final deprecated class ContactsContract.DataUsageFeedback {
     ctor public ContactsContract.DataUsageFeedback();
     field public static final android.net.Uri DELETE_USAGE_URI;
     field public static final android.net.Uri FEEDBACK_URI;
@@ -35652,8 +35793,8 @@
   }
 
   protected static abstract interface ContactsContract.DataUsageStatColumns {
-    field public static final java.lang.String LAST_TIME_USED = "last_time_used";
-    field public static final java.lang.String TIMES_USED = "times_used";
+    field public static final deprecated java.lang.String LAST_TIME_USED = "last_time_used";
+    field public static final deprecated java.lang.String TIMES_USED = "times_used";
   }
 
   public static final class ContactsContract.DeletedContacts implements android.provider.ContactsContract.DeletedContactsColumns {
@@ -38880,6 +39021,7 @@
   public static class CustomDescription.Builder {
     ctor public CustomDescription.Builder(android.widget.RemoteViews);
     method public android.service.autofill.CustomDescription.Builder addChild(int, android.service.autofill.Transformation);
+    method public android.service.autofill.CustomDescription.Builder addOnClickAction(int, android.service.autofill.OnClickAction);
     method public android.service.autofill.CustomDescription.Builder batchUpdate(android.service.autofill.Validator, android.service.autofill.BatchUpdates);
     method public android.service.autofill.CustomDescription build();
   }
@@ -38970,6 +39112,7 @@
     method public int getId();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+    field public static final int FLAG_COMPATIBILITY_MODE_REQUEST = 2; // 0x2
     field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
   }
 
@@ -39017,6 +39160,9 @@
     field public static final android.os.Parcelable.Creator<android.service.autofill.LuhnChecksumValidator> CREATOR;
   }
 
+  public abstract interface OnClickAction {
+  }
+
   public final class RegexValidator implements android.os.Parcelable android.service.autofill.Validator {
     ctor public RegexValidator(android.view.autofill.AutofillId, java.util.regex.Pattern);
     method public int describeContents();
@@ -39037,6 +39183,7 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int FLAG_DELAY_SAVE = 4; // 0x4
     field public static final int FLAG_DONT_SAVE_ON_FINISH = 2; // 0x2
     field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
     field public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0; // 0x0
@@ -39111,6 +39258,18 @@
     method public static android.service.autofill.Validator or(android.service.autofill.Validator...);
   }
 
+  public final class VisibilitySetterAction implements android.service.autofill.OnClickAction android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.VisibilitySetterAction> CREATOR;
+  }
+
+  public static class VisibilitySetterAction.Builder {
+    ctor public VisibilitySetterAction.Builder(int, int);
+    method public android.service.autofill.VisibilitySetterAction build();
+    method public android.service.autofill.VisibilitySetterAction.Builder setVisibility(int, int);
+  }
+
 }
 
 package android.service.carrier {
@@ -39660,6 +39819,7 @@
     field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
     field public static final int SHOW_SOURCE_APPLICATION = 8; // 0x8
     field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
+    field public static final int SHOW_SOURCE_PUSH_TO_TALK = 32; // 0x20
     field public static final int SHOW_WITH_ASSIST = 1; // 0x1
     field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2
   }
@@ -39750,9 +39910,11 @@
     method public int getDesiredMinimumHeight();
     method public int getDesiredMinimumWidth();
     method public android.view.SurfaceHolder getSurfaceHolder();
+    method public boolean isInAmbientMode();
     method public boolean isPreview();
     method public boolean isVisible();
     method public void notifyColorsChanged();
+    method public void onAmbientModeChanged(boolean, boolean);
     method public void onApplyWindowInsets(android.view.WindowInsets);
     method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
     method public android.app.WallpaperColors onComputeColors();
@@ -40896,6 +41058,16 @@
     field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
   }
 
+  public abstract class CallRedirectionService extends android.app.Service {
+    ctor public CallRedirectionService();
+    method public final void cancelCall();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onPlaceCall(android.net.Uri, android.telecom.PhoneAccountHandle);
+    method public final void placeCallUnmodified();
+    method public final void redirectCall(android.net.Uri, android.telecom.PhoneAccountHandle);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallRedirectionService";
+  }
+
   public abstract class CallScreeningService extends android.app.Service {
     ctor public CallScreeningService();
     method public android.os.IBinder onBind(android.content.Intent);
@@ -41012,6 +41184,7 @@
     method public void onReject(java.lang.String);
     method public void onSeparate();
     method public void onShowIncomingCallUi();
+    method public void onSilence();
     method public void onStartRtt(android.telecom.Connection.RttTextStream);
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
@@ -41791,9 +41964,10 @@
     field public static final java.lang.String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
     field public static final java.lang.String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
     field public static final java.lang.String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
+    field public static final java.lang.String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY = "radio_restart_failure_causes_int_array";
     field public static final java.lang.String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string";
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
-    field public static final java.lang.String KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL = "restart_radio_on_pdp_fail_regular_deactivation_bool";
+    field public static final deprecated java.lang.String KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL = "restart_radio_on_pdp_fail_regular_deactivation_bool";
     field public static final java.lang.String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
@@ -42405,12 +42579,16 @@
     method public java.lang.CharSequence getDisplayName();
     method public java.lang.String getIccId();
     method public int getIconTint();
-    method public int getMcc();
-    method public int getMnc();
+    method public deprecated int getMcc();
+    method public java.lang.String getMccString();
+    method public deprecated int getMnc();
+    method public java.lang.String getMncString();
     method public java.lang.String getNumber();
+    method public int getParentSubId();
     method public int getSimSlotIndex();
     method public int getSubscriptionId();
     method public boolean isEmbedded();
+    method public boolean isOpportunistic();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionInfo> CREATOR;
   }
@@ -42435,6 +42613,7 @@
     method public void setSubscriptionOverrideCongested(int, boolean, long);
     method public void setSubscriptionOverrideUnmetered(int, boolean, long);
     method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
+    method public void switchToSubscription(int, android.app.PendingIntent);
     field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
     field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
     field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
@@ -42500,6 +42679,8 @@
     method public java.lang.String getImei();
     method public java.lang.String getImei(int);
     method public java.lang.String getLine1Number();
+    method public java.lang.String getManufacturerCode();
+    method public java.lang.String getManufacturerCode(int);
     method public java.lang.String getMeid();
     method public java.lang.String getMeid(int);
     method public java.lang.String getMmsUAProfUrl();
@@ -42524,6 +42705,8 @@
     method public int getSimState();
     method public int getSimState(int);
     method public java.lang.String getSubscriberId();
+    method public java.lang.String getTypeAllocationCode();
+    method public java.lang.String getTypeAllocationCode(int);
     method public java.lang.String getVisualVoicemailPackageName();
     method public java.lang.String getVoiceMailAlphaTag();
     method public java.lang.String getVoiceMailNumber();
@@ -44736,6 +44919,7 @@
   public class Linkify {
     ctor public Linkify();
     method public static final boolean addLinks(android.text.Spannable, int);
+    method public static final boolean addLinks(android.text.Spannable, int, android.text.util.Linkify.UrlSpanFactory);
     method public static final boolean addLinks(android.widget.TextView, int);
     method public static final void addLinks(android.widget.TextView, java.util.regex.Pattern, java.lang.String);
     method public static final void addLinks(android.widget.TextView, java.util.regex.Pattern, java.lang.String, android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
@@ -44743,6 +44927,7 @@
     method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String);
     method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
     method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
+    method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter, android.text.util.Linkify.UrlSpanFactory);
     field public static final int ALL = 15; // 0xf
     field public static final int EMAIL_ADDRESSES = 2; // 0x2
     field public static final deprecated int MAP_ADDRESSES = 8; // 0x8
@@ -44761,6 +44946,11 @@
     method public abstract java.lang.String transformUrl(java.util.regex.Matcher, java.lang.String);
   }
 
+  public static class Linkify.UrlSpanFactory {
+    ctor public Linkify.UrlSpanFactory();
+    method public android.text.style.URLSpan create(java.lang.String);
+  }
+
   public class Rfc822Token {
     ctor public Rfc822Token(java.lang.String, java.lang.String, java.lang.String);
     method public java.lang.String getAddress();
@@ -46355,7 +46545,7 @@
     method public final deprecated boolean dispatch(android.view.KeyEvent.Callback);
     method public final boolean dispatch(android.view.KeyEvent.Callback, android.view.KeyEvent.DispatcherState, java.lang.Object);
     method public final int getAction();
-    method public final java.lang.String getCharacters();
+    method public final deprecated java.lang.String getCharacters();
     method public static int getDeadChar(int, int);
     method public final int getDeviceId();
     method public char getDisplayLabel();
@@ -46404,7 +46594,7 @@
     method public final void startTracking();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACTION_DOWN = 0; // 0x0
-    field public static final int ACTION_MULTIPLE = 2; // 0x2
+    field public static final deprecated int ACTION_MULTIPLE = 2; // 0x2
     field public static final int ACTION_UP = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.view.KeyEvent> CREATOR;
     field public static final int FLAG_CANCELED = 32; // 0x20
@@ -47477,6 +47667,7 @@
     method public void forceLayout();
     method public static int generateViewId();
     method public java.lang.CharSequence getAccessibilityClassName();
+    method public android.view.View.AccessibilityDelegate getAccessibilityDelegate();
     method public int getAccessibilityLiveRegion();
     method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
     method public java.lang.CharSequence getAccessibilityPaneTitle();
@@ -48730,6 +48921,7 @@
     method public void dispatchOnGlobalLayout();
     method public boolean dispatchOnPreDraw();
     method public boolean isAlive();
+    method public void registerFrameCommitCallback(java.lang.Runnable);
     method public deprecated void removeGlobalOnLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener);
     method public void removeOnDrawListener(android.view.ViewTreeObserver.OnDrawListener);
     method public void removeOnGlobalFocusChangeListener(android.view.ViewTreeObserver.OnGlobalFocusChangeListener);
@@ -48739,6 +48931,7 @@
     method public void removeOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener);
     method public void removeOnWindowAttachListener(android.view.ViewTreeObserver.OnWindowAttachListener);
     method public void removeOnWindowFocusChangeListener(android.view.ViewTreeObserver.OnWindowFocusChangeListener);
+    method public boolean unregisterFrameCommitCallback(java.lang.Runnable);
   }
 
   public static abstract interface ViewTreeObserver.OnDrawListener {
@@ -49382,18 +49575,18 @@
     method public void setCheckable(boolean);
     method public void setChecked(boolean);
     method public void setClassName(java.lang.CharSequence);
-    method public void setClickable(boolean);
+    method public deprecated void setClickable(boolean);
     method public void setCollectionInfo(android.view.accessibility.AccessibilityNodeInfo.CollectionInfo);
     method public void setCollectionItemInfo(android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo);
     method public void setContentDescription(java.lang.CharSequence);
     method public void setContentInvalid(boolean);
-    method public void setContextClickable(boolean);
-    method public void setDismissable(boolean);
+    method public deprecated void setContextClickable(boolean);
+    method public deprecated void setDismissable(boolean);
     method public void setDrawingOrder(int);
     method public void setEditable(boolean);
     method public void setEnabled(boolean);
     method public void setError(java.lang.CharSequence);
-    method public void setFocusable(boolean);
+    method public deprecated void setFocusable(boolean);
     method public void setFocused(boolean);
     method public void setHeading(boolean);
     method public void setHintText(java.lang.CharSequence);
@@ -49404,7 +49597,7 @@
     method public void setLabeledBy(android.view.View);
     method public void setLabeledBy(android.view.View, int);
     method public void setLiveRegion(int);
-    method public void setLongClickable(boolean);
+    method public deprecated void setLongClickable(boolean);
     method public void setMaxTextLength(int);
     method public void setMovementGranularities(int);
     method public void setMultiLine(boolean);
@@ -49415,7 +49608,7 @@
     method public void setPassword(boolean);
     method public void setRangeInfo(android.view.accessibility.AccessibilityNodeInfo.RangeInfo);
     method public void setScreenReaderFocusable(boolean);
-    method public void setScrollable(boolean);
+    method public deprecated void setScrollable(boolean);
     method public void setSelected(boolean);
     method public void setShowingHintText(boolean);
     method public void setSource(android.view.View);
@@ -52825,6 +53018,7 @@
     method public int getWidth();
     method public float getZoom();
     method public void show(float, float);
+    method public void show(float, float, float, float);
     method public void update();
   }
 
@@ -57593,14 +57787,14 @@
     method public void setContextClassLoader(java.lang.ClassLoader);
     method public final void setDaemon(boolean);
     method public static void setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler);
-    method public final void setName(java.lang.String);
+    method public final synchronized void setName(java.lang.String);
     method public final void setPriority(int);
     method public void setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler);
     method public static void sleep(long) throws java.lang.InterruptedException;
     method public static void sleep(long, int) throws java.lang.InterruptedException;
     method public synchronized void start();
     method public final deprecated void stop();
-    method public final deprecated void stop(java.lang.Throwable);
+    method public final deprecated synchronized void stop(java.lang.Throwable);
     method public final deprecated void suspend();
     method public static void yield();
     field public static final int MAX_PRIORITY = 10; // 0xa
@@ -70634,7 +70828,7 @@
     ctor public InflaterInputStream(java.io.InputStream);
     method protected void fill() throws java.io.IOException;
     field protected byte[] buf;
-    field protected boolean closed;
+    field protected deprecated boolean closed;
     field protected java.util.zip.Inflater inf;
     field protected int len;
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index bfa1aa3..41175798 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -201,6 +201,7 @@
     field public static final java.lang.String WRITE_EMBEDDED_SUBSCRIPTIONS = "android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS";
     field public static final java.lang.String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES";
     field public static final java.lang.String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
+    field public static final java.lang.String WRITE_OBB = "android.permission.WRITE_OBB";
     field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
   }
 
@@ -1115,7 +1116,6 @@
     method public abstract void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
     method public abstract int installExistingPackage(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract int installExistingPackage(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public boolean isPackageSuspended(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(android.content.Intent, int, android.os.UserHandle);
     method public abstract void registerDexModule(java.lang.String, android.content.pm.PackageManager.DexModuleRegisterCallback);
     method public abstract void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
@@ -3835,6 +3835,7 @@
     method public final void putInt64Array(long, long[]);
     method public final void putInt8(long, byte);
     method public final void putInt8Array(long, byte[]);
+    method public final void putNativeHandle(long, android.os.NativeHandle);
     method public final void putString(long, java.lang.String);
     method public static java.lang.Boolean[] wrapArray(boolean[]);
     method public static java.lang.Long[] wrapArray(long[]);
@@ -3854,6 +3855,7 @@
     method public final double readDouble();
     method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
     method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
+    method public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
     method public final float readFloat();
     method public final java.util.ArrayList<java.lang.Float> readFloatVector();
     method public final short readInt16();
@@ -3864,6 +3866,8 @@
     method public final java.util.ArrayList<java.lang.Long> readInt64Vector();
     method public final byte readInt8();
     method public final java.util.ArrayList<java.lang.Byte> readInt8Vector();
+    method public final android.os.NativeHandle readNativeHandle();
+    method public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
     method public final java.lang.String readString();
     method public final java.util.ArrayList<java.lang.String> readStringVector();
     method public final android.os.IHwBinder readStrongBinder();
@@ -3887,6 +3891,8 @@
     method public final void writeInt8(byte);
     method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
     method public final void writeInterfaceToken(java.lang.String);
+    method public final void writeNativeHandle(android.os.NativeHandle);
+    method public final void writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>);
     method public final void writeStatus(int);
     method public final void writeString(java.lang.String);
     method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
@@ -3932,6 +3938,18 @@
     field public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
   }
 
+  public final class NativeHandle implements java.io.Closeable {
+    ctor public NativeHandle();
+    ctor public NativeHandle(java.io.FileDescriptor, boolean);
+    ctor public NativeHandle(java.io.FileDescriptor[], int[], boolean);
+    method public void close() throws java.io.IOException;
+    method public android.os.NativeHandle dup() throws java.io.IOException;
+    method public java.io.FileDescriptor getFileDescriptor();
+    method public java.io.FileDescriptor[] getFileDescriptors();
+    method public int[] getInts();
+    method public boolean hasSingleFileDescriptor();
+  }
+
   public final class PowerManager {
     method public void userActivity(long, int, int);
     field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
@@ -4371,7 +4389,10 @@
     field public static final java.lang.String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE = "autofill_user_data_max_user_data_size";
     field public static final java.lang.String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length";
     field public static final java.lang.String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
+    field public static final java.lang.String HUSH_GESTURE_USED = "hush_gesture_used";
     field public static final java.lang.String INSTANT_APPS_ENABLED = "instant_apps_enabled";
+    field public static final java.lang.String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
+    field public static final java.lang.String VOLUME_HUSH_GESTURE = "volume_hush_gesture";
   }
 
   public final class TimeZoneRulesDataContract {
@@ -4524,9 +4545,11 @@
   public abstract class AutofillFieldClassificationService extends android.app.Service {
     method public android.os.IBinder onBind(android.content.Intent);
     method public float[][] onGetScores(java.lang.String, android.os.Bundle, java.util.List<android.view.autofill.AutofillValue>, java.util.List<java.lang.String>);
+    field public static final java.lang.String RESOURCE_AVAILABLE_ALGORITHMS = "autofill_field_classification_available_algorithms";
+    field public static final java.lang.String RESOURCE_DEFAULT_ALGORITHM = "autofill_field_classification_default_algorithm";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
-    field public static final java.lang.String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.autofill.field_classification.available_algorithms";
-    field public static final java.lang.String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm";
+    field public static final deprecated java.lang.String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.autofill.field_classification.available_algorithms";
+    field public static final deprecated java.lang.String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm";
   }
 
 }
@@ -4663,7 +4686,10 @@
     method public int getUser();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+    field public static final java.lang.String KEY_IMPORTANCE = "key_importance";
     field public static final java.lang.String KEY_PEOPLE = "key_people";
+    field public static final java.lang.String KEY_SMART_ACTIONS = "key_smart_actions";
+    field public static final java.lang.String KEY_SMART_REPLIES = "key_smart_replies";
     field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
     field public static final java.lang.String KEY_USER_SENTIMENT = "key_user_sentiment";
   }
@@ -4695,9 +4721,11 @@
     method public final void adjustNotification(android.service.notification.Adjustment);
     method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
     method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
+    method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
+    method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, android.app.NotificationChannel);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap, android.service.notification.NotificationStats, int);
     method public abstract void onNotificationSnoozedUntilContext(android.service.notification.StatusBarNotification, java.lang.String);
+    method public void onNotificationsSeen(java.util.List<java.lang.String>);
     method public final void unsnoozeNotification(java.lang.String);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
   }
@@ -4706,6 +4734,7 @@
     ctor public NotificationStats();
     ctor protected NotificationStats(android.os.Parcel);
     method public int describeContents();
+    method public int getDismissalSentiment();
     method public int getDismissalSurface();
     method public boolean hasDirectReplied();
     method public boolean hasExpanded();
@@ -4714,6 +4743,7 @@
     method public boolean hasSnoozed();
     method public boolean hasViewedSettings();
     method public void setDirectReplied();
+    method public void setDismissalSentiment(int);
     method public void setDismissalSurface(int);
     method public void setExpanded();
     method public void setSeen();
@@ -4726,6 +4756,10 @@
     field public static final int DISMISSAL_OTHER = 0; // 0x0
     field public static final int DISMISSAL_PEEK = 1; // 0x1
     field public static final int DISMISSAL_SHADE = 3; // 0x3
+    field public static final int DISMISS_SENTIMENT_NEGATIVE = 0; // 0x0
+    field public static final int DISMISS_SENTIMENT_NEUTRAL = 1; // 0x1
+    field public static final int DISMISS_SENTIMENT_POSITIVE = 2; // 0x2
+    field public static final int DISMISS_SENTIMENT_UNKNOWN = -1000; // 0xfffffc18
   }
 
   public final class SnoozeCriterion implements android.os.Parcelable {
@@ -5179,8 +5213,8 @@
     method public int[] getAvailableServices();
     method public android.telephony.CellIdentity getCellIdentity();
     method public int getDomain();
-    method public int getReasonForDenial();
     method public int getRegState();
+    method public int getRejectCause();
     method public int getTransportType();
     method public boolean isEmergencyEnabled();
     method public void writeToParcel(android.os.Parcel, int);
@@ -5519,6 +5553,19 @@
     field public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
+  public abstract class QualifiedNetworksService extends android.app.Service {
+    ctor public QualifiedNetworksService();
+    method public abstract android.telephony.data.QualifiedNetworksService.NetworkAvailabilityUpdater createNetworkAvailabilityUpdater(int);
+    field public static final java.lang.String QUALIFIED_NETWORKS_SERVICE_INTERFACE = "android.telephony.data.QualifiedNetworksService";
+  }
+
+  public abstract class QualifiedNetworksService.NetworkAvailabilityUpdater implements java.lang.AutoCloseable {
+    ctor public QualifiedNetworksService.NetworkAvailabilityUpdater(int);
+    method public abstract void close();
+    method public final int getSlotIndex();
+    method public final void updateQualifiedNetworkTypes(int, int[]);
+  }
+
 }
 
 package android.telephony.euicc {
@@ -5937,6 +5984,7 @@
     field public static final int CODE_SIP_SERVER_TIMEOUT = 353; // 0x161
     field public static final int CODE_SIP_SERVICE_UNAVAILABLE = 352; // 0x160
     field public static final int CODE_SIP_TEMPRARILY_UNAVAILABLE = 336; // 0x150
+    field public static final int CODE_SIP_TRANSACTION_DOES_NOT_EXIST = 343; // 0x157
     field public static final int CODE_SIP_USER_REJECTED = 361; // 0x169
     field public static final int CODE_SUPP_SVC_CANCELLED = 1202; // 0x4b2
     field public static final int CODE_SUPP_SVC_FAILED = 1201; // 0x4b1
@@ -6035,12 +6083,16 @@
     ctor public ImsSsInfo(int, java.lang.String);
     method public int describeContents();
     method public java.lang.String getIcbNum();
+    method public int getProvisionStatus();
     method public int getStatus();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
     field public static final int DISABLED = 0; // 0x0
     field public static final int ENABLED = 1; // 0x1
     field public static final int NOT_REGISTERED = -1; // 0xffffffff
+    field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0
+    field public static final int SERVICE_PROVISIONED = 1; // 0x1
+    field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
   }
 
   public final class ImsStreamMediaProfile implements android.os.Parcelable {
@@ -6174,6 +6226,10 @@
     field public static final int STATE_UNAVAILABLE = 0; // 0x0
   }
 
+  public static class ImsFeature.Capabilities {
+    field protected int mCapabilities;
+  }
+
   protected static class ImsFeature.CapabilityCallbackProxy {
     method public void onChangeCapabilityConfigurationError(int, int, int);
   }
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 961026b..b88c760 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -81,7 +81,7 @@
 package android.os {
 
   public class Build {
-    field public static final boolean PERMISSIONS_REVIEW_REQUIRED;
+    field public static final boolean PERMISSIONS_REVIEW_REQUIRED = true;
   }
 
   public final class PowerManager {
diff --git a/api/test-current.txt b/api/test-current.txt
index 718c0f2..7947ed9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5,7 +5,9 @@
     field public static final java.lang.String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
     field public static final java.lang.String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
     field public static final java.lang.String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
+    field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION";
     field public static final java.lang.String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
+    field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
     field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
     field public static final java.lang.String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
   }
@@ -26,16 +28,22 @@
   public class ActivityManager {
     method public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
     method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
+    method public void forceStopPackage(java.lang.String);
     method public int getPackageImportance(java.lang.String);
     method public long getTotalRam();
     method public int getUidImportance(int);
     method public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
+    method public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
   }
 
   public static abstract interface ActivityManager.OnUidImportanceListener {
     method public abstract void onUidImportance(int, int);
   }
 
+  public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable {
+    field public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170; // 0xaa
+  }
+
   public static class ActivityManager.TaskDescription implements android.os.Parcelable {
     method public java.lang.String getIconFilename();
     method public int getIconResource();
@@ -49,11 +57,19 @@
   }
 
   public class ActivityTaskManager {
+    method public java.lang.String listAllStacks();
+    method public void moveTaskToStack(int, int, boolean);
+    method public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
     method public void removeStacksInWindowingModes(int[]) throws java.lang.SecurityException;
     method public void removeStacksWithActivityTypes(int[]) throws java.lang.SecurityException;
+    method public void resizeDockedStack(android.graphics.Rect, android.graphics.Rect);
     method public void resizeStack(int, android.graphics.Rect) throws java.lang.SecurityException;
+    method public void resizeStack(int, android.graphics.Rect, boolean);
+    method public void resizeTask(int, android.graphics.Rect);
     method public void setTaskWindowingMode(int, int, boolean) throws java.lang.SecurityException;
     method public void setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean) throws java.lang.SecurityException;
+    method public void startSystemLockTaskMode(int);
+    method public void stopSystemLockTaskMode();
     method public static boolean supportsMultiWindow(android.content.Context);
     method public static boolean supportsSplitScreenMultiWindow(android.content.Context);
     field public static final int INVALID_STACK_ID = -1; // 0xffffffff
@@ -228,6 +244,14 @@
 
 }
 
+package android.bluetooth {
+
+  public final class BluetoothClass implements android.os.Parcelable {
+    method public int getClassOfDevice();
+  }
+
+}
+
 package android.content {
 
   public abstract class ContentResolver {
@@ -257,6 +281,8 @@
   public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     method public boolean isPrivilegedApp();
     method public boolean isSystemApp();
+    field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8
+    field public int privateFlags;
   }
 
   public class LauncherApps {
@@ -264,6 +290,7 @@
   }
 
   public abstract class PackageManager {
+    method public abstract boolean arePermissionsIndividuallyControlled();
     method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
     method public abstract int getInstallReason(java.lang.String, android.os.UserHandle);
     method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
@@ -272,11 +299,14 @@
     method public abstract java.lang.String getPermissionControllerPackageName();
     method public abstract java.lang.String getServicesSystemSharedLibraryPackageName();
     method public abstract java.lang.String getSharedSystemSharedLibraryPackageName();
-    method public abstract boolean isPermissionReviewModeEnabled();
+    method public abstract void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
+    method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
     field public static final java.lang.String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
     field public static final java.lang.String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
     field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
     field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
+    field public static final java.lang.String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
+    field public static final java.lang.String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared";
   }
 
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
@@ -308,9 +338,6 @@
   public final class SQLiteDebug {
     method public static void dump(android.util.Printer, java.lang.String[]);
     method public static android.database.sqlite.SQLiteDebug.PagerStats getDatabaseInfo();
-    field public static final boolean DEBUG_SQL_LOG;
-    field public static final boolean DEBUG_SQL_STATEMENTS;
-    field public static final boolean DEBUG_SQL_TIME;
   }
 
   public static class SQLiteDebug.DbStats {
@@ -632,6 +659,10 @@
 
 package android.os {
 
+  public class Build {
+    method public static boolean is64BitAbi(java.lang.String);
+  }
+
   public static class Build.VERSION {
     field public static final int FIRST_SDK_INT;
     field public static final int RESOURCES_SDK_INT;
@@ -644,6 +675,7 @@
 
   public class Environment {
     method public static java.io.File buildPath(java.io.File, java.lang.String...);
+    method public static java.io.File getStorageDirectory();
   }
 
   public class IncidentManager {
@@ -666,8 +698,9 @@
     field public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
   }
 
-  public final class PowerManager {
-    method public void nap(long);
+  public final class MessageQueue {
+    method public int postSyncBarrier();
+    method public void removeSyncBarrier(int);
   }
 
   public class Process {
@@ -688,9 +721,14 @@
   }
 
   public final class StrictMode {
+    method public static void conditionallyCheckInstanceCounts();
     method public static void setViolationLogger(android.os.StrictMode.ViolationLogger);
   }
 
+  public static final class StrictMode.ThreadPolicy.Builder {
+    method public android.os.StrictMode.ThreadPolicy.Builder detectExplicitGc();
+  }
+
   public static final class StrictMode.ViolationInfo implements android.os.Parcelable {
     ctor public StrictMode.ViolationInfo(android.os.Parcel);
     ctor public StrictMode.ViolationInfo(android.os.Parcel, boolean);
@@ -715,6 +753,7 @@
   }
 
   public class SystemProperties {
+    method public static java.lang.String get(java.lang.String);
     method public static java.lang.String get(java.lang.String, java.lang.String);
   }
 
@@ -734,7 +773,17 @@
     method public static android.os.VibrationEffect get(int);
     method public static android.os.VibrationEffect get(int, boolean);
     method public static android.os.VibrationEffect get(android.net.Uri, android.content.Context);
+    method public abstract long getDuration();
     method protected static int scale(int, float, int);
+    field public static final int EFFECT_CLICK = 0; // 0x0
+    field public static final int EFFECT_DOUBLE_CLICK = 1; // 0x1
+    field public static final int EFFECT_HEAVY_CLICK = 5; // 0x5
+    field public static final int EFFECT_POP = 4; // 0x4
+    field public static final int EFFECT_STRENGTH_LIGHT = 0; // 0x0
+    field public static final int EFFECT_STRENGTH_MEDIUM = 1; // 0x1
+    field public static final int EFFECT_STRENGTH_STRONG = 2; // 0x2
+    field public static final int EFFECT_THUD = 3; // 0x3
+    field public static final int EFFECT_TICK = 2; // 0x2
     field public static final int[] RINGTONES;
   }
 
@@ -775,6 +824,86 @@
     field public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Waveform> CREATOR;
   }
 
+  public class WorkSource implements android.os.Parcelable {
+    ctor public WorkSource(int);
+    method public boolean add(int);
+    method public boolean add(int, java.lang.String);
+    method public deprecated android.os.WorkSource addReturningNewbs(android.os.WorkSource);
+    method public int get(int);
+    method public java.lang.String getName(int);
+    method public deprecated android.os.WorkSource[] setReturningDiffs(android.os.WorkSource);
+    method public int size();
+  }
+
+}
+
+package android.os.health {
+
+  public class HealthKeys {
+    ctor public HealthKeys();
+    field public static final int BASE_PACKAGE = 40000; // 0x9c40
+    field public static final int BASE_PID = 20000; // 0x4e20
+    field public static final int BASE_PROCESS = 30000; // 0x7530
+    field public static final int BASE_SERVICE = 50000; // 0xc350
+    field public static final int BASE_UID = 10000; // 0x2710
+    field public static final int TYPE_COUNT = 5; // 0x5
+    field public static final int TYPE_MEASUREMENT = 1; // 0x1
+    field public static final int TYPE_MEASUREMENTS = 4; // 0x4
+    field public static final int TYPE_STATS = 2; // 0x2
+    field public static final int TYPE_TIMER = 0; // 0x0
+    field public static final int TYPE_TIMERS = 3; // 0x3
+    field public static final int UNKNOWN_KEY = 0; // 0x0
+  }
+
+  public static abstract class HealthKeys.Constant implements java.lang.annotation.Annotation {
+  }
+
+  public static class HealthKeys.Constants {
+    ctor public HealthKeys.Constants(java.lang.Class);
+    method public java.lang.String getDataType();
+    method public int getIndex(int, int);
+    method public int[] getKeys(int);
+    method public int getSize(int);
+  }
+
+  public class HealthStats {
+    ctor public HealthStats(android.os.Parcel);
+  }
+
+  public class HealthStatsParceler implements android.os.Parcelable {
+    ctor public HealthStatsParceler(android.os.health.HealthStatsWriter);
+    ctor public HealthStatsParceler(android.os.Parcel);
+    method public int describeContents();
+    method public android.os.health.HealthStats getHealthStats();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.health.HealthStatsParceler> CREATOR;
+  }
+
+  public class HealthStatsWriter {
+    ctor public HealthStatsWriter(android.os.health.HealthKeys.Constants);
+    method public void addMeasurement(int, long);
+    method public void addMeasurements(int, java.lang.String, long);
+    method public void addStats(int, java.lang.String, android.os.health.HealthStatsWriter);
+    method public void addTimer(int, int, long);
+    method public void addTimers(int, java.lang.String, android.os.health.TimerStat);
+    method public void flattenToParcel(android.os.Parcel);
+  }
+
+}
+
+package android.os.storage {
+
+  public final class StorageVolume implements android.os.Parcelable {
+    method public java.lang.String getPath();
+  }
+
+}
+
+package android.os.strictmode {
+
+  public final class ExplicitGcViolation extends android.os.strictmode.Violation {
+  }
+
 }
 
 package android.print {
@@ -873,6 +1002,10 @@
     method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception;
   }
 
+  public final class CustomDescription implements android.os.Parcelable {
+    method public android.util.SparseArray<android.service.autofill.InternalOnClickAction> getActions();
+  }
+
   public final class DateTransformation extends android.service.autofill.InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
     method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception;
   }
@@ -889,12 +1022,19 @@
     method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception;
   }
 
+  public abstract class InternalOnClickAction implements android.service.autofill.OnClickAction android.os.Parcelable {
+    ctor public InternalOnClickAction();
+    method public abstract void onClick(android.view.ViewGroup);
+  }
+
   public abstract class InternalSanitizer implements android.os.Parcelable android.service.autofill.Sanitizer {
     ctor public InternalSanitizer();
+    method public abstract android.view.autofill.AutofillValue sanitize(android.view.autofill.AutofillValue);
   }
 
   public abstract class InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
     ctor public InternalTransformation();
+    method public static boolean batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer, android.service.autofill.InternalTransformation>>);
   }
 
   public abstract class InternalValidator implements android.os.Parcelable android.service.autofill.Validator {
@@ -919,6 +1059,10 @@
     method public abstract android.view.autofill.AutofillValue findRawValueByAutofillId(android.view.autofill.AutofillId);
   }
 
+  public final class VisibilitySetterAction extends android.service.autofill.InternalOnClickAction implements android.service.autofill.OnClickAction android.os.Parcelable {
+    method public void onClick(android.view.ViewGroup);
+  }
+
 }
 
 package android.service.notification {
@@ -934,7 +1078,10 @@
     method public int getUser();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+    field public static final java.lang.String KEY_IMPORTANCE = "key_importance";
     field public static final java.lang.String KEY_PEOPLE = "key_people";
+    field public static final java.lang.String KEY_SMART_ACTIONS = "key_smart_actions";
+    field public static final java.lang.String KEY_SMART_REPLIES = "key_smart_replies";
     field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
     field public static final java.lang.String KEY_USER_SENTIMENT = "key_user_sentiment";
   }
@@ -948,8 +1095,10 @@
     method public final void adjustNotification(android.service.notification.Adjustment);
     method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
     method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
+    method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
+    method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, android.app.NotificationChannel);
     method public abstract void onNotificationSnoozedUntilContext(android.service.notification.StatusBarNotification, java.lang.String);
+    method public void onNotificationsSeen(java.util.List<java.lang.String>);
     method public final void unsnoozeNotification(java.lang.String);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
   }
@@ -962,6 +1111,7 @@
     ctor public NotificationStats();
     ctor protected NotificationStats(android.os.Parcel);
     method public int describeContents();
+    method public int getDismissalSentiment();
     method public int getDismissalSurface();
     method public boolean hasDirectReplied();
     method public boolean hasExpanded();
@@ -970,6 +1120,7 @@
     method public boolean hasSnoozed();
     method public boolean hasViewedSettings();
     method public void setDirectReplied();
+    method public void setDismissalSentiment(int);
     method public void setDismissalSurface(int);
     method public void setExpanded();
     method public void setSeen();
@@ -982,6 +1133,10 @@
     field public static final int DISMISSAL_OTHER = 0; // 0x0
     field public static final int DISMISSAL_PEEK = 1; // 0x1
     field public static final int DISMISSAL_SHADE = 3; // 0x3
+    field public static final int DISMISS_SENTIMENT_NEGATIVE = 0; // 0x0
+    field public static final int DISMISS_SENTIMENT_NEUTRAL = 1; // 0x1
+    field public static final int DISMISS_SENTIMENT_POSITIVE = 2; // 0x2
+    field public static final int DISMISS_SENTIMENT_UNKNOWN = -1000; // 0xfffffc18
   }
 
   public final class SnoozeCriterion implements android.os.Parcelable {
@@ -1339,25 +1494,39 @@
   public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
     method public void setActionButton(int);
     method public void setButtonState(int);
+    method public void setDisplayId(int);
   }
 
   public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
     method public android.view.View getTooltipView();
     method public static boolean isDefaultFocusHighlightEnabled();
     method public boolean isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method protected void resetResolvedDrawables();
+    method public void resetResolvedLayoutDirection();
+    method public void resetResolvedPadding();
+    method public void resetResolvedTextAlignment();
+    method public void resetResolvedTextDirection();
+    method public void resetRtlProperties();
     method public boolean restoreFocusInCluster(int);
     method public boolean restoreFocusNotInCluster();
     method public void setAutofilled(boolean);
     method public final void setFocusedInCluster();
+    method public void setIsRootNamespace(boolean);
   }
 
   public class ViewConfiguration {
+    method public long getDeviceGlobalActionKeyTimeout();
     method public static int getHoverTooltipHideShortTimeout();
     method public static int getHoverTooltipHideTimeout();
     method public static int getHoverTooltipShowTimeout();
     method public static int getLongPressTooltipHideTimeout();
   }
 
+  public final class ViewTreeObserver {
+    method public void registerFrameCommitCallback(java.lang.Runnable);
+    method public boolean unregisterFrameCommitCallback(java.lang.Runnable);
+  }
+
   public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
     field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
     field public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 64; // 0x40
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 641ae00..a826ec7 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -16,10 +16,13 @@
 
 package com.android.commands.bmgr;
 
+import android.annotation.IntDef;
 import android.app.backup.BackupManager;
+import android.app.backup.BackupManagerMonitor;
 import android.app.backup.BackupProgress;
 import android.app.backup.BackupTransport;
 import android.app.backup.IBackupManager;
+import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IBackupObserver;
 import android.app.backup.IRestoreObserver;
 import android.app.backup.IRestoreSession;
@@ -28,6 +31,7 @@
 import android.content.ComponentName;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
@@ -36,10 +40,13 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
 public final class Bmgr {
@@ -247,7 +254,7 @@
     }
 
     // IBackupObserver generically usable for any backup/init operation
-    abstract class Observer extends IBackupObserver.Stub {
+    private static abstract class Observer extends IBackupObserver.Stub {
         private final Object trigger = new Object();
 
         @GuardedBy("trigger")
@@ -295,7 +302,7 @@
         }
     }
 
-    class BackupObserver extends Observer {
+    private static class BackupObserver extends Observer {
         @Override
         public void onUpdate(String currentPackage, BackupProgress backupProgress) {
             super.onUpdate(currentPackage, backupProgress);
@@ -347,7 +354,7 @@
         }
     }
 
-    private void backupNowAllPackages(boolean nonIncrementalBackup) {
+    private void backupNowAllPackages(boolean nonIncrementalBackup, @Monitor int monitorState) {
         int userId = UserHandle.USER_SYSTEM;
         IPackageManager mPm =
                 IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
@@ -372,20 +379,27 @@
                 System.err.println(e.toString());
                 System.err.println(BMGR_NOT_RUNNING_ERR);
             }
-            backupNowPackages(Arrays.asList(filteredPackages), nonIncrementalBackup);
+            backupNowPackages(Arrays.asList(filteredPackages), nonIncrementalBackup, monitorState);
         }
     }
 
-    private void backupNowPackages(List<String> packages, boolean nonIncrementalBackup) {
+    private void backupNowPackages(
+            List<String> packages, boolean nonIncrementalBackup, @Monitor int monitorState) {
         int flags = 0;
         if (nonIncrementalBackup) {
             flags |= BackupManager.FLAG_NON_INCREMENTAL_BACKUP;
         }
         try {
             BackupObserver observer = new BackupObserver();
-            // TODO: implement monitor here?
-            int err = mBmgr.requestBackup(packages.toArray(new String[packages.size()]), observer,
-                    null, flags);
+            BackupMonitor monitor =
+                    (monitorState != Monitor.OFF)
+                            ? new BackupMonitor(monitorState == Monitor.VERBOSE)
+                            : null;
+            int err = mBmgr.requestBackup(
+                    packages.toArray(new String[packages.size()]),
+                    observer,
+                    monitor,
+                    flags);
             if (err == 0) {
                 // Off and running -- wait for the backup to complete
                 observer.waitForCompletion();
@@ -402,6 +416,7 @@
         String pkg;
         boolean backupAll = false;
         boolean nonIncrementalBackup = false;
+        @Monitor int monitor = Monitor.OFF;
         ArrayList<String> allPkgs = new ArrayList<String>();
         while ((pkg = nextArg()) != null) {
             if (pkg.equals("--all")) {
@@ -410,6 +425,10 @@
                 nonIncrementalBackup = true;
             } else if (pkg.equals("--incremental")) {
                 nonIncrementalBackup = false;
+            } else if (pkg.equals("--monitor")) {
+                monitor = Monitor.NORMAL;
+            } else if (pkg.equals("--monitor-verbose")) {
+                monitor = Monitor.VERBOSE;
             } else {
                 if (!allPkgs.contains(pkg)) {
                     allPkgs.add(pkg);
@@ -420,14 +439,14 @@
             if (allPkgs.size() == 0) {
                 System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") +
                         "incremental backup for all packages.");
-                backupNowAllPackages(nonIncrementalBackup);
+                backupNowAllPackages(nonIncrementalBackup, monitor);
             } else {
                 System.err.println("Provide only '--all' flag or list of packages.");
             }
         } else if (allPkgs.size() > 0) {
             System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") +
                     "incremental backup for " + allPkgs.size() +" requested packages.");
-            backupNowPackages(allPkgs, nonIncrementalBackup);
+            backupNowPackages(allPkgs, nonIncrementalBackup, monitor);
         } else {
             System.err.println("Provide '--all' flag or list of packages.");
         }
@@ -824,8 +843,9 @@
         System.err.println("       bmgr run");
         System.err.println("       bmgr wipe TRANSPORT PACKAGE");
         System.err.println("       bmgr fullbackup PACKAGE...");
-        System.err.println("       bmgr backupnow --all|PACKAGE...");
+        System.err.println("       bmgr backupnow [--monitor|--monitor-verbose] --all|PACKAGE...");
         System.err.println("       bmgr cancel backups");
+        System.err.println("       bmgr init TRANSPORT...");
         System.err.println("");
         System.err.println("The 'backup' command schedules a backup pass for the named package.");
         System.err.println("Note that the backup pass will effectively be a no-op if the package");
@@ -878,9 +898,168 @@
         System.err.println("");
         System.err.println("The 'backupnow' command runs an immediate backup for one or more packages.");
         System.err.println("    --all flag runs backup for all eligible packages.");
+        System.err.println("    --monitor flag prints monitor events.");
+        System.err.println("    --monitor-verbose flag prints monitor events with all keys.");
         System.err.println("For each package it will run key/value or full data backup ");
         System.err.println("depending on the package's manifest declarations.");
         System.err.println("The data is sent via the currently active transport.");
+        System.err.println("");
         System.err.println("The 'cancel backups' command cancels all running backups.");
+        System.err.println("");
+        System.err.println("The 'init' command initializes the given transports, wiping all data");
+        System.err.println("from their backing data stores.");
+    }
+
+    private static class BackupMonitor extends IBackupManagerMonitor.Stub {
+        private final boolean mVerbose;
+
+        private BackupMonitor(boolean verbose) {
+            mVerbose = verbose;
+        }
+
+        @Override
+        public void onEvent(Bundle event) throws RemoteException {
+            StringBuilder out = new StringBuilder();
+            int id = event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID);
+            int category = event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY);
+            out.append("=> Event{").append(eventCategoryToString(category));
+            out.append(" / ").append(eventIdToString(id));
+            String packageName = event.getString(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME);
+            if (packageName != null) {
+                out.append(" : package = ").append(packageName);
+                if (event.containsKey(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION)) {
+                    long version =
+                            event.getLong(
+                                    BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION);
+                    out.append("(v").append(version).append(")");
+                }
+            }
+            if (mVerbose) {
+                Set<String> remainingKeys = new ArraySet<>(event.keySet());
+                remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_ID);
+                remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY);
+                remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME);
+                remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION);
+                remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION);
+                if (!remainingKeys.isEmpty()) {
+                    out.append(", other keys =");
+                    for (String key : remainingKeys) {
+                        out.append(" ").append(key);
+                    }
+                }
+            }
+            out.append("}");
+            System.out.println(out.toString());
+        }
+    }
+
+    private static String eventCategoryToString(int eventCategory) {
+        switch (eventCategory) {
+            case BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT:
+                return "TRANSPORT";
+            case BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT:
+                return "AGENT";
+            case BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY:
+                return "BACKUP_MANAGER_POLICY";
+            default:
+                return "UNKNOWN_CATEGORY";
+        }
+    }
+
+    private static String eventIdToString(int eventId) {
+        switch (eventId) {
+            case BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_CANCEL:
+                return "FULL_BACKUP_CANCEL";
+            case BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY:
+                return "ILLEGAL_KEY";
+            case BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND:
+                return "NO_DATA_TO_SEND";
+            case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_INELIGIBLE:
+                return "PACKAGE_INELIGIBLE";
+            case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT:
+                return "PACKAGE_KEY_VALUE_PARTICIPANT";
+            case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_STOPPED:
+                return "PACKAGE_STOPPED";
+            case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_FOUND:
+                return "PACKAGE_NOT_FOUND";
+            case BackupManagerMonitor.LOG_EVENT_ID_BACKUP_DISABLED:
+                return "BACKUP_DISABLED";
+            case BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED:
+                return "DEVICE_NOT_PROVISIONED";
+            case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT:
+                return "PACKAGE_TRANSPORT_NOT_PRESENT";
+            case BackupManagerMonitor.LOG_EVENT_ID_ERROR_PREFLIGHT:
+                return "ERROR_PREFLIGHT";
+            case BackupManagerMonitor.LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT:
+                return "QUOTA_HIT_PREFLIGHT";
+            case BackupManagerMonitor.LOG_EVENT_ID_EXCEPTION_FULL_BACKUP:
+                return "EXCEPTION_FULL_BACKUP";
+            case BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL:
+                return "KEY_VALUE_BACKUP_CANCEL";
+            case BackupManagerMonitor.LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE:
+                return "NO_RESTORE_METADATA_AVAILABLE";
+            case BackupManagerMonitor.LOG_EVENT_ID_NO_PM_METADATA_RECEIVED:
+                return "NO_PM_METADATA_RECEIVED";
+            case BackupManagerMonitor.LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA:
+                return "PM_AGENT_HAS_NO_METADATA";
+            case BackupManagerMonitor.LOG_EVENT_ID_LOST_TRANSPORT:
+                return "LOST_TRANSPORT";
+            case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_PRESENT:
+                return "PACKAGE_NOT_PRESENT";
+            case BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER:
+                return "RESTORE_VERSION_HIGHER";
+            case BackupManagerMonitor.LOG_EVENT_ID_APP_HAS_NO_AGENT:
+                return "APP_HAS_NO_AGENT";
+            case BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH:
+                return "SIGNATURE_MISMATCH";
+            case BackupManagerMonitor.LOG_EVENT_ID_CANT_FIND_AGENT:
+                return "CANT_FIND_AGENT";
+            case BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT:
+                return "KEY_VALUE_RESTORE_TIMEOUT";
+            case BackupManagerMonitor.LOG_EVENT_ID_RESTORE_ANY_VERSION:
+                return "RESTORE_ANY_VERSION";
+            case BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH:
+                return "VERSIONS_MATCH";
+            case BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER:
+                return "VERSION_OF_BACKUP_OLDER";
+            case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH:
+                return "FULL_RESTORE_SIGNATURE_MISMATCH";
+            case BackupManagerMonitor.LOG_EVENT_ID_SYSTEM_APP_NO_AGENT:
+                return "SYSTEM_APP_NO_AGENT";
+            case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE:
+                return "FULL_RESTORE_ALLOW_BACKUP_FALSE";
+            case BackupManagerMonitor.LOG_EVENT_ID_APK_NOT_INSTALLED:
+                return "APK_NOT_INSTALLED";
+            case BackupManagerMonitor.LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK:
+                return "CANNOT_RESTORE_WITHOUT_APK";
+            case BackupManagerMonitor.LOG_EVENT_ID_MISSING_SIGNATURE:
+                return "MISSING_SIGNATURE";
+            case BackupManagerMonitor.LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE:
+                return "EXPECTED_DIFFERENT_PACKAGE";
+            case BackupManagerMonitor.LOG_EVENT_ID_UNKNOWN_VERSION:
+                return "UNKNOWN_VERSION";
+            case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_TIMEOUT:
+                return "FULL_RESTORE_TIMEOUT";
+            case BackupManagerMonitor.LOG_EVENT_ID_CORRUPT_MANIFEST:
+                return "CORRUPT_MANIFEST";
+            case BackupManagerMonitor.LOG_EVENT_ID_WIDGET_METADATA_MISMATCH:
+                return "WIDGET_METADATA_MISMATCH";
+            case BackupManagerMonitor.LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION:
+                return "WIDGET_UNKNOWN_VERSION";
+            case BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES:
+                return "NO_PACKAGES";
+            case BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL:
+                return "TRANSPORT_IS_NULL";
+            default:
+                return "UNKNOWN_ID";
+        }
+    }
+
+    @IntDef({Monitor.OFF, Monitor.NORMAL, Monitor.VERBOSE})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface Monitor {
+        int OFF = 0;
+        int NORMAL = 1;
+        int VERBOSE = 2;
     }
 }
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 8ffe5bf..e915cc8 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -302,6 +302,7 @@
     mHeight = h;
     mFlingerSurfaceControl = control;
     mFlingerSurface = s;
+    mTargetInset = -1;
 
     // If the device has encryption turned on or is in process
     // of being encrypted we show the encrypted boot animation.
@@ -859,12 +860,12 @@
         mTimeCheckThread = nullptr;
     }
 
-    releaseAnimation(animation);
-
     if (clockFontInitialized) {
         glDeleteTextures(1, &animation->clockFont.texture.name);
     }
 
+    releaseAnimation(animation);
+
     return false;
 }
 
@@ -942,6 +943,7 @@
                 if (mClockEnabled && mTimeIsAccurate && validClock(part)) {
                     drawClock(animation.clockFont, part.clockPosX, part.clockPosY);
                 }
+                handleViewport(frameDuration);
 
                 eglSwapBuffers(mDisplay, mSurface);
 
@@ -966,7 +968,7 @@
             usleep(part.pause * ns2us(frameDuration));
 
             // For infinite parts, we've now played them at least once, so perhaps exit
-            if(exitPending() && !part.count)
+            if(exitPending() && !part.count && mCurrentInset >= mTargetInset)
                 break;
         }
 
@@ -986,6 +988,51 @@
     return true;
 }
 
+void BootAnimation::handleViewport(nsecs_t timestep) {
+    if (mShuttingDown || !mFlingerSurfaceControl || mTargetInset == 0) {
+        return;
+    }
+    if (mTargetInset < 0) {
+        // Poll the amount for the top display inset. This will return -1 until persistent properties
+        // have been loaded.
+        mTargetInset = android::base::GetIntProperty("persist.sys.displayinset.top",
+                -1 /* default */, -1 /* min */, mHeight / 2 /* max */);
+    }
+    if (mTargetInset <= 0) {
+        return;
+    }
+
+    if (mCurrentInset < mTargetInset) {
+        // After the device boots, the inset will effectively be cropped away. We animate this here.
+        float fraction = static_cast<float>(mCurrentInset) / mTargetInset;
+        int interpolatedInset = (cosf((fraction + 1) * M_PI) / 2.0f + 0.5f) * mTargetInset;
+
+        SurfaceComposerClient::Transaction()
+                .setCrop(mFlingerSurfaceControl, Rect(0, interpolatedInset, mWidth, mHeight))
+                .apply();
+    } else {
+        // At the end of the animation, we switch to the viewport that DisplayManager will apply
+        // later. This changes the coordinate system, and means we must move the surface up by
+        // the inset amount.
+        sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
+                ISurfaceComposer::eDisplayIdMain));
+
+        Rect layerStackRect(0, 0, mWidth, mHeight - mTargetInset);
+        Rect displayRect(0, mTargetInset, mWidth, mHeight);
+
+        SurfaceComposerClient::Transaction t;
+        t.setPosition(mFlingerSurfaceControl, 0, -mTargetInset)
+                .setCrop(mFlingerSurfaceControl, Rect(0, mTargetInset, mWidth, mHeight));
+        t.setDisplayProjection(dtoken, 0 /* orientation */, layerStackRect, displayRect);
+        t.apply();
+
+        mTargetInset = mCurrentInset = 0;
+    }
+
+    int delta = timestep * mTargetInset / ms2ns(200);
+    mCurrentInset += delta;
+}
+
 void BootAnimation::releaseAnimation(Animation* animation) const
 {
     for (Vector<Animation::Part>::iterator it = animation->parts.begin(),
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index dffbfde..498eebc 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -158,11 +158,15 @@
 
     void checkExit();
 
+    void handleViewport(nsecs_t timestep);
+
     sp<SurfaceComposerClient>       mSession;
     AssetManager mAssets;
     Texture     mAndroid[2];
     int         mWidth;
     int         mHeight;
+    int         mCurrentInset;
+    int         mTargetInset;
     bool        mUseNpotTextures = false;
     EGLDisplay  mDisplay;
     EGLDisplay  mContext;
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 6e0bd3a..36e51b9 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -462,7 +462,7 @@
                 IBinder token = new Binder();
                 try {
                     ContentProviderHolder holder = activityManager.getContentProviderExternal(
-                            providerName, mUserId, token);
+                            providerName, mUserId, token, "*cmd*");
                     if (holder == null) {
                         throw new IllegalStateException("Could not find provider: " + providerName);
                     }
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
index 5cc4fc4..b3e287b 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.cpp
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -42,7 +42,6 @@
 namespace uhid {
 
 static const char* UHID_PATH = "/dev/uhid";
-static const size_t UHID_MAX_NAME_LENGTH = 128;
 
 static struct {
     jmethodID onDeviceOpen;
@@ -90,8 +89,13 @@
 }
 
 Device* Device::open(int32_t id, const char* name, int32_t vid, int32_t pid,
-        std::unique_ptr<uint8_t[]> descriptor, size_t descriptorSize,
-        std::unique_ptr<DeviceCallback> callback) {
+        std::vector<uint8_t> descriptor, std::unique_ptr<DeviceCallback> callback) {
+
+    size_t size = descriptor.size();
+    if (size > HID_MAX_DESCRIPTOR_SIZE) {
+        LOGE("Received invalid hid report with descriptor size %zu, skipping", size);
+        return nullptr;
+    }
 
     int fd = ::open(UHID_PATH, O_RDWR | O_CLOEXEC);
     if (fd < 0) {
@@ -102,10 +106,10 @@
     struct uhid_event ev;
     memset(&ev, 0, sizeof(ev));
     ev.type = UHID_CREATE2;
-    strncpy((char*)ev.u.create2.name, name, UHID_MAX_NAME_LENGTH);
-    memcpy(&ev.u.create2.rd_data, descriptor.get(),
-            descriptorSize * sizeof(ev.u.create2.rd_data[0]));
-    ev.u.create2.rd_size = descriptorSize;
+    strlcpy(reinterpret_cast<char*>(ev.u.create2.name), name, sizeof(ev.u.create2.name));
+    memcpy(&ev.u.create2.rd_data, descriptor.data(),
+            size * sizeof(ev.u.create2.rd_data[0]));
+    ev.u.create2.rd_size = size;
     ev.u.create2.bus = BUS_BLUETOOTH;
     ev.u.create2.vendor = vid;
     ev.u.create2.product = pid;
@@ -156,12 +160,17 @@
     mFd = -1;
 }
 
-void Device::sendReport(uint8_t* report, size_t reportSize) {
+void Device::sendReport(const std::vector<uint8_t>& report) const {
+    if (report.size() > UHID_DATA_MAX) {
+        LOGE("Received invalid report of size %zu, skipping", report.size());
+        return;
+    }
+
     struct uhid_event ev;
     memset(&ev, 0, sizeof(ev));
     ev.type = UHID_INPUT2;
-    ev.u.input2.size = reportSize;
-    memcpy(&ev.u.input2.data, report, reportSize);
+    ev.u.input2.size = report.size();
+    memcpy(&ev.u.input2.data, report.data(), report.size() * sizeof(ev.u.input2.data[0]));
     ssize_t ret = TEMP_FAILURE_RETRY(::write(mFd, &ev, sizeof(ev)));
     if (ret < 0 || ret != sizeof(ev)) {
         LOGE("Failed to send hid event: %s", strerror(errno));
@@ -191,12 +200,13 @@
 
 } // namespace uhid
 
-std::unique_ptr<uint8_t[]> getData(JNIEnv* env, jbyteArray javaArray, size_t& outSize) {
+std::vector<uint8_t> getData(JNIEnv* env, jbyteArray javaArray) {
     ScopedByteArrayRO scopedArray(env, javaArray);
-    outSize = scopedArray.size();
-    std::unique_ptr<uint8_t[]> data(new uint8_t[outSize]);
-    for (size_t i = 0; i < outSize; i++) {
-        data[i] = static_cast<uint8_t>(scopedArray[i]);
+    size_t size = scopedArray.size();
+    std::vector<uint8_t> data;
+    data.reserve(size);
+    for (size_t i = 0; i < size; i++) {
+        data.push_back(static_cast<uint8_t>(scopedArray[i]));
     }
     return data;
 }
@@ -208,23 +218,20 @@
         return 0;
     }
 
-    size_t size;
-    std::unique_ptr<uint8_t[]> desc = getData(env, rawDescriptor, size);
+    std::vector<uint8_t> desc = getData(env, rawDescriptor);
 
     std::unique_ptr<uhid::DeviceCallback> cb(new uhid::DeviceCallback(env, callback));
 
     uhid::Device* d = uhid::Device::open(
-            id, reinterpret_cast<const char*>(name.c_str()), vid, pid,
-            std::move(desc), size, std::move(cb));
+            id, reinterpret_cast<const char*>(name.c_str()), vid, pid, desc, std::move(cb));
     return reinterpret_cast<jlong>(d);
 }
 
 static void sendReport(JNIEnv* env, jclass /* clazz */, jlong ptr, jbyteArray rawReport) {
-    size_t size;
-    std::unique_ptr<uint8_t[]> report = getData(env, rawReport, size);
+    std::vector<uint8_t> report = getData(env, rawReport);
     uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
     if (d) {
-        d->sendReport(report.get(), size);
+        d->sendReport(report);
     } else {
         LOGE("Could not send report, Device* is null!");
     }
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h
index 149456d..61a1f76 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.h
+++ b/cmds/hid/jni/com_android_commands_hid_Device.h
@@ -15,6 +15,7 @@
  */
 
 #include <memory>
+#include <vector>
 
 #include <jni.h>
 
@@ -38,13 +39,12 @@
 class Device {
 public:
     static Device* open(int32_t id, const char* name, int32_t vid, int32_t pid,
-            std::unique_ptr<uint8_t[]> descriptor, size_t descriptorSize,
-            std::unique_ptr<DeviceCallback> callback);
+            std::vector<uint8_t> descriptor, std::unique_ptr<DeviceCallback> callback);
 
     Device(int32_t id, int fd, std::unique_ptr<DeviceCallback> callback);
     ~Device();
 
-    void sendReport(uint8_t* report, size_t reportSize);
+    void sendReport(const std::vector<uint8_t>& report) const;
     void close();
 
     int handleEvents(int events);
diff --git a/cmds/incident_helper/src/ih_util.cpp b/cmds/incident_helper/src/ih_util.cpp
index 4c4d1b9..012310c 100644
--- a/cmds/incident_helper/src/ih_util.cpp
+++ b/cmds/incident_helper/src/ih_util.cpp
@@ -97,7 +97,7 @@
 
     size_t lastIndex = 0;
     int i = 0;
-    while (headerNames[i] != NULL) {
+    while (headerNames[i] != nullptr) {
         std::string s = headerNames[i];
         lastIndex = line.find(s, lastIndex);
         if (lastIndex == std::string::npos) {
@@ -237,18 +237,18 @@
 Reader::Reader(const int fd)
 {
     mFile = fdopen(fd, "r");
-    mStatus = mFile == NULL ? "Invalid fd " + std::to_string(fd) : "";
+    mStatus = mFile == nullptr ? "Invalid fd " + std::to_string(fd) : "";
 }
 
 Reader::~Reader()
 {
-    if (mFile != NULL) fclose(mFile);
+    if (mFile != nullptr) fclose(mFile);
 }
 
 bool Reader::readLine(std::string* line) {
-    if (mFile == NULL) return false;
+    if (mFile == nullptr) return false;
 
-    char* buf = NULL;
+    char* buf = nullptr;
     size_t len = 0;
     ssize_t read = getline(&buf, &len, mFile);
     if (read != -1) {
diff --git a/cmds/incident_helper/src/main.cpp b/cmds/incident_helper/src/main.cpp
index 5b6ac7af..809a771 100644
--- a/cmds/incident_helper/src/main.cpp
+++ b/cmds/incident_helper/src/main.cpp
@@ -98,7 +98,7 @@
 
     fprintf(stderr, "Pasring section %d...\n", sectionID);
     TextParserBase* parser = selectParser(sectionID);
-    if (parser != NULL) {
+    if (parser != nullptr) {
         fprintf(stderr, "Running parser: %s\n", parser->name.string());
         status_t err = parser->Parse(STDIN_FILENO, STDOUT_FILENO);
         if (err != NO_ERROR) {
diff --git a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
index eed68b9..21ced9c 100644
--- a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
+++ b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
@@ -109,7 +109,7 @@
             nextToUsage = false;
 
             // NAME is not in the list since we need to modify the end of the CMD index.
-            const char* headerNames[] = { "PID", "TID", "USER", "PR", "NI", "CPU", "S", "VIRT", "RES", "PCY", "CMD", NULL };
+            const char* headerNames[] = { "PID", "TID", "USER", "PR", "NI", "CPU", "S", "VIRT", "RES", "PCY", "CMD", nullptr };
             if (!getColumnIndices(columnIndices, headerNames, line)) {
                 return -1;
             }
diff --git a/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp b/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp
index 0615c74..2a89c920 100644
--- a/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp
+++ b/cmds/incident_helper/src/parsers/PageTypeInfoParser.cpp
@@ -75,18 +75,13 @@
             } else return BAD_VALUE;
             // expect part 2 starts with "type"
             if (stripPrefix(&record[2], "type")) {
-                // expect the rest of part 2 has number of (pageBlockOrder + 2) parts
                 // An example looks like:
                 // header line:      type    0   1   2 3 4 5 6 7 8 9 10
                 // record line: Unmovable  426 279 226 1 1 1 0 0 2 2  0
-                // The pageBlockOrder = 10 and it's zero-indexed. so total parts
-                // are 10 + 1(zero-indexed) + 1(the type part) = 12.
                 record_t pageCounts = parseRecord(record[2]);
-                int pageCountsSize = pageBlockOrder + 2;
-                if ((int)pageCounts.size() != pageCountsSize) return BAD_VALUE;
 
                 proto.write(PageTypeInfoProto::MigrateType::TYPE, pageCounts[0]);
-                for (auto i=1; i<pageCountsSize; i++) {
+                for (size_t i=1; i<pageCounts.size(); i++) {
                     proto.write(PageTypeInfoProto::MigrateType::FREE_PAGES_COUNT, toInt(pageCounts[i]));
                 }
             } else return BAD_VALUE;
@@ -125,4 +120,4 @@
 
     fprintf(stderr, "[%s]Proto size: %zu bytes\n", this->name.string(), proto.size());
     return NO_ERROR;
-}
\ No newline at end of file
+}
diff --git a/cmds/incident_helper/src/parsers/PsParser.cpp b/cmds/incident_helper/src/parsers/PsParser.cpp
index 8d64064..d3cb4be 100644
--- a/cmds/incident_helper/src/parsers/PsParser.cpp
+++ b/cmds/incident_helper/src/parsers/PsParser.cpp
@@ -48,7 +48,7 @@
         if (nline++ == 0) {
             header = parseHeader(line, DEFAULT_WHITESPACE);
 
-            const char* headerNames[] = { "LABEL", "USER", "PID", "TID", "PPID", "VSZ", "RSS", "WCHAN", "ADDR", "S", "PRI", "NI", "RTPRIO", "SCH", "PCY", "TIME", "CMD", NULL };
+            const char* headerNames[] = { "LABEL", "USER", "PID", "TID", "PPID", "VSZ", "RSS", "WCHAN", "ADDR", "S", "PRI", "NI", "RTPRIO", "SCH", "PCY", "TIME", "CMD", nullptr };
             if (!getColumnIndices(columnIndices, headerNames, line)) {
                 return -1;
             }
diff --git a/cmds/incident_helper/testdata/pagetypeinfo.txt b/cmds/incident_helper/testdata/pagetypeinfo.txt
index d45ddc4..c65b5a1 100644
--- a/cmds/incident_helper/testdata/pagetypeinfo.txt
+++ b/cmds/incident_helper/testdata/pagetypeinfo.txt
@@ -1,5 +1,5 @@
-Page block order: 10
-Pages per block:  1024
+Page block order: 9
+Pages per block:  512
 
 Free pages count per migrate type at order       0      1      2      3      4      5      6      7      8      9     10 
 Node    0, zone      DMA, type    Unmovable    426    279    226      1      1      1      0      0      2      2      0 
diff --git a/cmds/incident_helper/tests/PageTypeInfoParser_test.cpp b/cmds/incident_helper/tests/PageTypeInfoParser_test.cpp
index 9bad7be..5688681 100644
--- a/cmds/incident_helper/tests/PageTypeInfoParser_test.cpp
+++ b/cmds/incident_helper/tests/PageTypeInfoParser_test.cpp
@@ -54,8 +54,8 @@
     PageTypeInfoParser parser;
     PageTypeInfoProto expected;
 
-    expected.set_page_block_order(10);
-    expected.set_pages_per_block(1024);
+    expected.set_page_block_order(9);
+    expected.set_pages_per_block(512);
 
     PageTypeInfoProto::MigrateType* mt1 = expected.add_migrate_types();
     mt1->set_node(0);
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 1c20bff..ba2aaad8 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -45,7 +45,6 @@
     src/external/puller_util.cpp \
     src/logd/LogEvent.cpp \
     src/logd/LogListener.cpp \
-    src/logd/LogReader.cpp \
     src/matchers/CombinationLogMatchingTracker.cpp \
     src/matchers/matcher_util.cpp \
     src/matchers/SimpleLogMatchingTracker.cpp \
@@ -60,7 +59,6 @@
     src/metrics/MetricsManager.cpp \
     src/metrics/metrics_manager_util.cpp \
     src/packages/UidMap.cpp \
-    src/perfetto/perfetto_config.proto \
     src/storage/StorageManager.cpp \
     src/StatsLogProcessor.cpp \
     src/StatsService.cpp \
@@ -73,8 +71,7 @@
 
 # TODO(b/110563449): Once statsd is using a blueprint file, migrate to the proper filegroups.
 statsd_common_src += \
-    ../../../../system/extras/perfprofd/binder_interface/aidl/android/os/IPerfProfd.aidl \
-    src/perfprofd/perfprofd_config.proto
+    ../../../../system/extras/perfprofd/binder_interface/aidl/android/os/IPerfProfd.aidl
 
 statsd_common_c_includes := \
     $(LOCAL_PATH)/src \
@@ -84,8 +81,7 @@
     $(LOCAL_PATH)/../../core/java
 
 statsd_common_static_libraries := \
-    libhealthhalutils \
-    libplatformprotos \
+    libhealthhalutils
 
 statsd_common_shared_libraries := \
     libbase \
@@ -197,7 +193,6 @@
     tests/external/puller_util_test.cpp \
     tests/indexed_priority_queue_test.cpp \
     tests/LogEntryMatcher_test.cpp \
-    tests/LogReader_test.cpp \
     tests/LogEvent_test.cpp \
     tests/MetricsManager_test.cpp \
     tests/StatsLogProcessor_test.cpp \
@@ -234,7 +229,8 @@
 
 LOCAL_STATIC_LIBRARIES := \
     $(statsd_common_static_libraries) \
-    libgmock
+    libgmock \
+    libplatformprotos
 
 LOCAL_PROTOC_OPTIMIZE_TYPE := full
 
@@ -256,8 +252,6 @@
 LOCAL_SRC_FILES := \
     src/stats_log.proto \
     src/statsd_config.proto \
-    src/perfetto/perfetto_config.proto \
-    src/perfprofd/perfprofd_config.proto \
     src/atoms.proto
 
 LOCAL_PROTOC_OPTIMIZE_TYPE := lite
@@ -301,7 +295,6 @@
 LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
                         libprotobuf-cpp-full
 
-
 LOCAL_STATIC_JAVA_LIBRARIES := \
     platformprotoslite
 
@@ -319,7 +312,8 @@
 LOCAL_AIDL_INCLUDES := $(statsd_common_aidl_includes)
 
 LOCAL_STATIC_LIBRARIES := \
-    $(statsd_common_static_libraries)
+    $(statsd_common_static_libraries) \
+    libplatformprotos
 
 LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
     libgtest_prod \
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index f150f07..7b6d29b 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -141,6 +141,9 @@
         case FLOAT:
             float_value = from.float_value;
             break;
+        case DOUBLE:
+            double_value = from.double_value;
+            break;
         case STRING:
             str_value = from.str_value;
             break;
@@ -157,6 +160,8 @@
             return std::to_string(long_value) + "[L]";
         case FLOAT:
             return std::to_string(float_value) + "[F]";
+        case DOUBLE:
+            return std::to_string(double_value) + "[D]";
         case STRING:
             return str_value + "[S]";
         default:
@@ -174,6 +179,8 @@
             return long_value == that.long_value;
         case FLOAT:
             return float_value == that.float_value;
+        case DOUBLE:
+            return double_value == that.double_value;
         case STRING:
             return str_value == that.str_value;
         default:
@@ -190,6 +197,8 @@
             return long_value != that.long_value;
         case FLOAT:
             return float_value != that.float_value;
+        case DOUBLE:
+            return double_value != that.double_value;
         case STRING:
             return str_value != that.str_value;
         default:
@@ -207,6 +216,8 @@
             return long_value < that.long_value;
         case FLOAT:
             return float_value < that.float_value;
+        case DOUBLE:
+            return double_value < that.double_value;
         case STRING:
             return str_value < that.str_value;
         default:
@@ -214,6 +225,142 @@
     }
 }
 
+bool Value::operator>(const Value& that) const {
+    if (type != that.getType()) return type > that.getType();
+
+    switch (type) {
+        case INT:
+            return int_value > that.int_value;
+        case LONG:
+            return long_value > that.long_value;
+        case FLOAT:
+            return float_value > that.float_value;
+        case DOUBLE:
+            return double_value > that.double_value;
+        case STRING:
+            return str_value > that.str_value;
+        default:
+            return false;
+    }
+}
+
+bool Value::operator>=(const Value& that) const {
+    if (type != that.getType()) return type >= that.getType();
+
+    switch (type) {
+        case INT:
+            return int_value >= that.int_value;
+        case LONG:
+            return long_value >= that.long_value;
+        case FLOAT:
+            return float_value >= that.float_value;
+        case DOUBLE:
+            return double_value >= that.double_value;
+        case STRING:
+            return str_value >= that.str_value;
+        default:
+            return false;
+    }
+}
+
+Value Value::operator-(const Value& that) const {
+    Value v;
+    if (type != that.type) {
+        ALOGE("Can't operate on different value types, %d, %d", type, that.type);
+        return v;
+    }
+    if (type == STRING) {
+        ALOGE("Can't operate on string value type");
+        return v;
+    }
+
+    switch (type) {
+        case INT:
+            v.setInt(int_value - that.int_value);
+            break;
+        case LONG:
+            v.setLong(long_value - that.long_value);
+            break;
+        case FLOAT:
+            v.setFloat(float_value - that.float_value);
+            break;
+        case DOUBLE:
+            v.setDouble(double_value - that.double_value);
+            break;
+        default:
+            break;
+    }
+    return v;
+}
+
+Value& Value::operator=(const Value& that) {
+    type = that.type;
+    switch (type) {
+        case INT:
+            int_value = that.int_value;
+            break;
+        case LONG:
+            long_value = that.long_value;
+            break;
+        case FLOAT:
+            float_value = that.float_value;
+            break;
+        case DOUBLE:
+            double_value = that.double_value;
+            break;
+        case STRING:
+            str_value = that.str_value;
+            break;
+        default:
+            break;
+    }
+    return *this;
+}
+
+Value& Value::operator+=(const Value& that) {
+    if (type != that.type) {
+        ALOGE("Can't operate on different value types, %d, %d", type, that.type);
+        return *this;
+    }
+    if (type == STRING) {
+        ALOGE("Can't operate on string value type");
+        return *this;
+    }
+
+    switch (type) {
+        case INT:
+            int_value += that.int_value;
+            break;
+        case LONG:
+            long_value += that.long_value;
+            break;
+        case FLOAT:
+            float_value += that.float_value;
+            break;
+        case DOUBLE:
+            double_value += that.double_value;
+            break;
+        default:
+            break;
+    }
+    return *this;
+}
+
+double Value::getDouble() const {
+    switch (type) {
+        case INT:
+            return int_value;
+        case LONG:
+            return long_value;
+        case FLOAT:
+            return float_value;
+        case DOUBLE:
+            return double_value;
+        default:
+            return 0;
+    }
+}
+
 bool equalDimensions(const std::vector<Matcher>& dimension_a,
                      const std::vector<Matcher>& dimension_b) {
     bool eq = dimension_a.size() == dimension_b.size();
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index b1d6ab3..b1b885e 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -32,7 +32,7 @@
 const int32_t kClearLastBitDeco = 0x7f;
 const int32_t kClearAllPositionMatcherMask = 0xffff00ff;
 
-enum Type { UNKNOWN, INT, LONG, FLOAT, STRING };
+enum Type { UNKNOWN, INT, LONG, FLOAT, DOUBLE, STRING };
 
 int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth);
 
@@ -283,6 +283,11 @@
         type = FLOAT;
     }
 
+    Value(double v) {
+        double_value = v;
+        type = DOUBLE;
+    }
+
     Value(const std::string& v) {
         str_value = v;
         type = STRING;
@@ -298,10 +303,21 @@
         type = LONG;
     }
 
+    void setFloat(float v) {
+        float_value = v;
+        type = FLOAT;
+    }
+
+    void setDouble(double v) {
+        double_value = v;
+        type = DOUBLE;
+    }
+
     union {
         int32_t int_value;
         int64_t long_value;
         float float_value;
+        double double_value;
     };
     std::string str_value;
 
@@ -313,12 +329,19 @@
         return type;
     }
 
+    double getDouble() const;
+
     Value(const Value& from);
 
     bool operator==(const Value& that) const;
     bool operator!=(const Value& that) const;
 
     bool operator<(const Value& that) const;
+    bool operator>(const Value& that) const;
+    bool operator>=(const Value& that) const;
+    Value operator-(const Value& that) const;
+    Value& operator+=(const Value& that);
+    Value& operator=(const Value& that);
 };
 
 /**
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index ab0aa25..8e02f9c 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -161,10 +161,6 @@
     }
 }
 
-void StatsLogProcessor::OnLogEvent(LogEvent* event) {
-    OnLogEvent(event, false);
-}
-
 void StatsLogProcessor::resetConfigs() {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
     resetConfigsLocked(getElapsedRealtimeNs());
@@ -178,7 +174,7 @@
     resetConfigsLocked(timestampNs, configKeys);
 }
 
-void StatsLogProcessor::OnLogEvent(LogEvent* event, bool reconnected) {
+void StatsLogProcessor::OnLogEvent(LogEvent* event) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
 
 #ifdef VERY_VERBOSE_PRINTING
@@ -188,41 +184,6 @@
 #endif
     const int64_t currentTimestampNs = event->GetElapsedTimestampNs();
 
-    if (reconnected && mLastTimestampSeen != 0) {
-        // LogReader tells us the connection has just been reset. Now we need
-        // to enter reconnection state to find the last CP.
-        mInReconnection = true;
-    }
-
-    if (mInReconnection) {
-        // We see the checkpoint
-        if (currentTimestampNs == mLastTimestampSeen) {
-            mInReconnection = false;
-            // Found the CP. ignore this event, and we will start to read from next event.
-            return;
-        }
-        if (currentTimestampNs > mLargestTimestampSeen) {
-            // We see a new log but CP has not been found yet. Give up now.
-            mLogLossCount++;
-            mInReconnection = false;
-            StatsdStats::getInstance().noteLogLost(currentTimestampNs);
-            // Persist the data before we reset. Do we want this?
-            WriteDataToDiskLocked(CONFIG_RESET);
-            // We see fresher event before we see the checkpoint. We might have lost data.
-            // The best we can do is to reset.
-            resetConfigsLocked(currentTimestampNs);
-        } else {
-            // Still in search of the CP. Keep going.
-            return;
-        }
-    }
-
-    mLogCount++;
-    mLastTimestampSeen = currentTimestampNs;
-    if (mLargestTimestampSeen < currentTimestampNs) {
-        mLargestTimestampSeen = currentTimestampNs;
-    }
-
     resetIfConfigTtlExpiredLocked(currentTimestampNs);
 
     StatsdStats::getInstance().noteAtomLogged(
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 05cf0c1..df80b8e 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -18,7 +18,6 @@
 
 #include <gtest/gtest_prod.h>
 #include "config/ConfigListener.h"
-#include "logd/LogReader.h"
 #include "metrics/MetricsManager.h"
 #include "packages/UidMap.h"
 #include "external/StatsPullerManager.h"
@@ -52,9 +51,6 @@
                       const std::function<bool(const ConfigKey&)>& sendBroadcast);
     virtual ~StatsLogProcessor();
 
-    void OnLogEvent(LogEvent* event, bool reconnectionStarts);
-
-    // for testing only.
     void OnLogEvent(LogEvent* event);
 
     void OnConfigUpdated(const int64_t timestampNs, const ConfigKey& key,
@@ -174,14 +170,6 @@
 
     int64_t mLastTimestampSeen = 0;
 
-    bool mInReconnection = false;
-
-    // Processed log count
-    uint64_t mLogCount = 0;
-
-    // Log loss detected count
-    int mLogLossCount = 0;
-
     long mLastPullerCacheClearTimeSec = 0;
 
 #ifdef VERY_VERBOSE_PRINTING
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 1119eb3..91d68ea 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -403,7 +403,7 @@
     fprintf(out, "\n              *Note: If both UID and NAME are omitted then all configs will\n");
     fprintf(out, "\n                     be removed from memory and disk!\n");
     fprintf(out, "\n");
-    fprintf(out, "usage: adb shell cmd stats dump-report [UID] NAME [--proto]\n");
+    fprintf(out, "usage: adb shell cmd stats dump-report [UID] NAME [--include_current_bucket] [--proto]\n");
     fprintf(out, "  Dump all metric data for a configuration.\n");
     fprintf(out, "  UID           The uid of the configuration. It is only possible to pass\n");
     fprintf(out, "                the UID parameter on eng builds. If UID is omitted the\n");
@@ -567,12 +567,17 @@
         int argCount = args.size();
         bool good = false;
         bool proto = false;
+        bool includeCurrentBucket = false;
         int uid;
         string name;
         if (!std::strcmp("--proto", args[argCount-1].c_str())) {
             proto = true;
             argCount -= 1;
         }
+        if (!std::strcmp("--include_current_bucket", args[argCount-1].c_str())) {
+            includeCurrentBucket = true;
+            argCount -= 1;
+        }
         if (argCount == 2) {
             // Automatically pick the UID
             uid = IPCThreadState::self()->getCallingUid();
@@ -600,7 +605,7 @@
         if (good) {
             vector<uint8_t> data;
             mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
-                                     false /* include_current_bucket*/, ADB_DUMP, &data);
+                                     includeCurrentBucket, ADB_DUMP, &data);
             if (proto) {
                 for (size_t i = 0; i < data.size(); i ++) {
                     fprintf(out, "%c", data[i]);
@@ -878,8 +883,8 @@
     mConfigManager->Startup();
 }
 
-void StatsService::OnLogEvent(LogEvent* event, bool reconnectionStarts) {
-    mProcessor->OnLogEvent(event, reconnectionStarts);
+void StatsService::OnLogEvent(LogEvent* event) {
+    mProcessor->OnLogEvent(event);
 }
 
 Status StatsService::getData(int64_t key, const String16& packageName, vector<uint8_t>* output) {
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index ed90050..613f509 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -22,6 +22,7 @@
 #include "anomaly/AlarmMonitor.h"
 #include "config/ConfigManager.h"
 #include "external/StatsPullerManager.h"
+#include "logd/LogListener.h"
 #include "packages/UidMap.h"
 #include "statscompanion_util.h"
 
@@ -75,7 +76,7 @@
     /**
      * Called by LogReader when there's a log event to process.
      */
-    virtual void OnLogEvent(LogEvent* event, bool reconnectionStarts);
+    virtual void OnLogEvent(LogEvent* event);
 
     /**
      * Binder call for clients to request data for this configuration key.
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index cdb72ab..f27f7fb 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -48,7 +48,7 @@
     oneof pushed {
         // For StatsLog reasons, 1 is illegal and will not work. Must start at 2.
         BleScanStateChanged ble_scan_state_changed = 2;
-        // 3 is available for use
+        ProcessStateChanged process_state_changed = 3;
         BleScanResultReceived ble_scan_result_received = 4;
         SensorStateChanged sensor_state_changed = 5;
         GpsScanStateChanged gps_scan_state_changed = 6;
@@ -59,7 +59,12 @@
         LongPartialWakelockStateChanged long_partial_wakelock_state_changed = 11;
         MobileRadioPowerStateChanged mobile_radio_power_state_changed = 12;
         WifiRadioPowerStateChanged wifi_radio_power_state_changed = 13;
-        // 14 - 19 are available
+        ActivityManagerSleepStateChanged activity_manager_sleep_state_changed = 14;
+        MemoryFactorStateChanged memory_factor_state_changed = 15;
+        ExcessiveCpuUsageReported excessive_cpu_usage_reported = 16;
+        CachedKillReported cached_kill_reported = 17;
+        ProcessMemoryStatReported process_memory_stat_reported = 18;
+        // 19 is available
         BatterySaverModeStateChanged battery_saver_mode_state_changed = 20;
         DeviceIdleModeStateChanged device_idle_mode_state_changed = 21;
         DeviceIdlingModeStateChanged device_idling_mode_state_changed = 22;
@@ -121,12 +126,12 @@
         ANROccurred anr_occurred = 79;
         WTFOccurred wtf_occurred = 80;
         LowMemReported low_mem_reported = 81;
-
-
+        GenericAtom generic_atom = 82;
+        KeyValuePairsAtom key_value_pairs_atom = 83;
     }
 
     // Pulled events will start at field 10000.
-    // Next: 10022
+    // Next: 10024
     oneof pulled {
         WifiBytesTransfer wifi_bytes_transfer = 10000;
         WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -146,10 +151,16 @@
         SystemUptime system_uptime = 10015;
         CpuActiveTime cpu_active_time = 10016;
         CpuClusterTime cpu_cluster_time = 10017;
-        DiskSpace disk_space = 10018;
+        DiskSpace disk_space = 10018 [deprecated=true];
         RemainingBatteryCapacity remaining_battery_capacity = 10019;
         FullBatteryCapacity full_battery_capacity = 10020;
         Temperature temperature = 10021;
+        BinderCalls binder_calls = 10022;
+        BinderCallsExceptions binder_calls_exceptions = 10023;
+        DiskStats disk_stats = 10024;
+        DirectoryUsage directory_usage = 10025;
+        AppSize app_size = 10026;
+        CategorySize category_size = 10027;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP. Field numbers above
@@ -171,6 +182,20 @@
     optional string tag = 2;
 }
 
+message KeyValuePair {
+    optional int32 key = 1;
+    oneof value {
+        int64 value_int = 2;
+        string value_str = 3;
+        float value_float = 4;
+    }
+}
+
+message KeyValuePairsAtom {
+    optional int32 uid = 1;
+    repeated KeyValuePair pairs = 2;
+}
+
 /*
  * *****************************************************************************
  * Below are all of the individual atoms that are logged by Android via statsd.
@@ -209,7 +234,8 @@
 }
 
 /**
- * Logs that the state of a process state, as per the activity manager, has changed.
+ * Logs that the process state of the uid, as determined by ActivityManager
+ * (i.e. the highest process state of that uid's processes) has changed.
  *
  * Logged from:
  *   frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -222,6 +248,112 @@
 }
 
 /**
+ * Logs process state change of a process, as per the activity manager.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
+ */
+message ProcessStateChanged {
+    optional int32 uid = 1;
+    optional string process_name = 2;
+    optional string package_name = 3;
+    // TODO: remove this when validation is done
+    optional int64 version = 5;
+    // The state, from frameworks/base/core/proto/android/app/enums.proto.
+    optional android.app.ProcessStateEnum state = 4;
+}
+
+/**
+ * Logs when ActivityManagerService sleep state is changed.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+ */
+message ActivityManagerSleepStateChanged {
+    // TODO: import frameworks proto
+    enum State {
+        UNKNOWN = 0;
+        ASLEEP = 1;
+        AWAKE = 2;
+    }
+    optional State state = 1 [(stateFieldOption).option = EXCLUSIVE];
+}
+
+/**
+ * Logs when system memory state changes.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+ */
+message MemoryFactorStateChanged {
+    // TODO: import frameworks proto
+    enum State {
+        MEMORY_UNKNOWN = 0;
+        NORMAL = 1;     // normal.
+        MODERATE = 2;   // moderate memory pressure.
+        LOW = 3;        // low memory.
+        CRITICAL = 4;   // critical memory.
+
+    }
+    optional State factor = 1 [(stateFieldOption).option = EXCLUSIVE];
+}
+
+/**
+ * Logs when app is using too much cpu, according to ActivityManagerService.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+ */
+message ExcessiveCpuUsageReported {
+    optional int32 uid = 1;
+    optional string process_name = 2;
+    optional string package_name = 3;
+    // package version. TODO: remove this when validation is done
+    optional int64 version = 4;
+}
+
+/**
+ * Logs when a cached process is killed, along with its pss.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+ */
+message CachedKillReported {
+    optional int32 uid = 1;
+    optional string process_name = 2;
+    optional string package_name = 3;
+    // TODO: remove this when validation is done
+    optional int64 version = 5;
+    optional int64 pss = 4;
+}
+
+/**
+ * Logs when memory stats of a process is reported.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
+ */
+message ProcessMemoryStatReported {
+    optional int32 uid = 1;
+    optional string process_name = 2;
+    optional string package_name = 3;
+    //TODO: remove this when validation is done
+    optional int64 version = 9;
+    optional int64 pss = 4;
+    optional int64 uss = 5;
+    optional int64 rss = 6;
+    enum Type {
+        ADD_PSS_INTERNAL_SINGLE = 0;
+        ADD_PSS_INTERNAL_ALL_MEM = 1;
+        ADD_PSS_INTERNAL_ALL_POLL = 2;
+        ADD_PSS_EXTERNAL = 3;
+        ADD_PSS_EXTERNAL_SLOW = 4;
+    }
+    optional Type type = 7;
+    optional int64 duration = 8;
+}
+
+/**
  * Logs that a process started, finished, crashed, or ANRed.
  *
  * Logged from:
@@ -1614,6 +1746,17 @@
     optional uint64 timestamp_millis = 1 [(stateFieldOption).option = EXCLUSIVE];
 }
 
+/**
+ * An atom for generic metrics logging. Available from Android Q.
+ */
+message GenericAtom {
+    // The uid of the application that sent this custom atom.
+    optional int32 uid = 1 [(is_uid) = true];
+
+    // An event_id indicates the type of event.
+    optional int32 event_id = 2;
+}
+
 //////////////////////////////////////////////////////////////////////
 // Pulled atoms below this line //
 //////////////////////////////////////////////////////////////////////
@@ -1975,3 +2118,151 @@
     // Temperature in tenths of a degree C.
     optional int32 temperature_dC = 3;
 }
+
+/**
+ * Pulls the statistics of calls to Binder.
+ *
+ * Binder stats are cumulative from boot unless somebody reset the data using
+ * > adb shell dumpsys binder_calls_stats --reset
+ *
+ * Next tag: 14
+ */
+message BinderCalls {
+    optional int32 uid = 1 [(is_uid) = true];
+    // Fully qualified class name of the API call.
+    //
+    // This is a system server class name.
+    //
+    // TODO(gaillard): figure out if binder call stats includes data from isolated uids, if a uid
+    // gets recycled and we have isolated uids, we might attribute the data incorrectly.
+    // TODO(gaillard): there is a high dimensions cardinality, figure out if we should drop the less
+    // commonly used APIs.
+    optional string service_class_name = 2;
+    // Method name of the API call. It can also be a transaction code if we cannot
+    // resolve it to a name. See Binder#getTransactionName.
+    //
+    // This is a system server method name.
+    optional string service_method_name = 3;
+    // Total number of API calls.
+    optional int64 call_count = 4;
+    // True if the screen was interactive PowerManager#isInteractive at the end of the call.
+    optional bool screen_interactive = 13;
+    // Total number of API calls we have data recorded for. If we collected data for all the calls,
+    // call_count will be equal to recorded_call_count.
+    //
+    // If recorded_call_count is different than call_count, it means data collection has been
+    // sampled. All the fields below will be sampled in this case.
+    optional int64 recorded_call_count = 12;
+    // Number of exceptions thrown by the API.
+    optional int64 recorded_exception_count = 5;
+    // Total latency of all API calls.
+    // Average can be computed using total_latency_micros / recorded_call_count.
+    optional int64 recorded_total_latency_micros = 6;
+    // Maximum latency of one API call.
+    optional int64 recorded_max_latency_micros = 7;
+    // Total CPU usage of all API calls.
+    // Average can be computed using total_cpu_micros / recorded_call_count.
+    // Total can be computed using total_cpu_micros / recorded_call_count * call_count.
+    optional int64 recorded_total_cpu_micros = 8;
+    // Maximum CPU usage of one API call.
+    optional int64 recorded_max_cpu_micros = 9;
+    // Maximum parcel reply size of one API call.
+    optional int64 recorded_max_reply_size_bytes = 10;
+    // Maximum parcel request size of one API call.
+    optional int64 recorded_max_request_size_bytes = 11;
+}
+
+/**
+ * Pulls the statistics of exceptions during calls to Binder.
+ *
+ * Binder stats are cumulative from boot unless somebody reset the data using
+ * > adb shell dumpsys binder_calls_stats --reset
+ */
+message BinderCallsExceptions {
+    // Exception class name, e.g. java.lang.IllegalArgumentException.
+    //
+    // This is an exception class name thrown by the system server.
+    optional string exception_class_name = 1;
+    // Total number of exceptions.
+    optional int64 exception_count = 2;
+}
+
+
+/**
+ * Pulls disk information, such as write speed and latency.
+ */
+message DiskStats {
+    // Time taken to open, write 512B to, and close a file.
+    // -1 if error performing the check.
+    optional int64 data_write_latency_millis = 1;
+
+    optional bool file_based_encryption = 2;
+
+    // Recent disk write speed in kB/s.
+    // -1 if error querying storageed.
+    // 0 if data is unavailable.
+    optional int32 recent_disk_write_speed = 3;
+}
+
+
+/**
+ * Free and total bytes of the Data, Cache, and System partition.
+ */
+message DirectoryUsage {
+    enum Directory {
+        UNKNOWN = 0;
+        DATA = 1;
+        CACHE = 2;
+        SYSTEM = 3;
+    }
+    optional Directory directory = 1;
+    optional int64 free_bytes = 2;
+    optional int64 total_bytes = 3;
+}
+
+
+/**
+ * Size of an application: apk size, data size, and cache size.
+ * Reads from a cached file produced daily by DiskStatsLoggingService.java.
+ * Information is only reported for apps with the primary user (user 0).
+ * Sizes are aggregated by package name.
+ */
+message AppSize {
+    // Including uids will involve modifying diskstats logic.
+    optional string package_name = 1;
+    // App size in bytes. -1 if unavailable.
+    optional int64 app_size_bytes = 2;
+    // App data size in bytes. -1 if unavailable.
+    optional int64 app_data_size_bytes = 3;
+    // App cache size in bytes. -1 if unavailable.
+    optional int64 app_cache_size_bytes = 4;
+    // Time that the cache file was produced.
+    // Uses System.currentTimeMillis(), which is wall clock time.
+    optional int64 cache_time_millis = 5;
+}
+
+
+/**
+ * Size of a particular category. Eg: photos, videos.
+ * Reads from a cached file produced daily by DiskStatsLoggingService.java.
+ */
+message CategorySize {
+    enum Category {
+        UNKNOWN = 0;
+        APP_SIZE = 1;
+        APP_DATA_SIZE = 2;
+        APP_CACHE_SIZE = 3;
+        PHOTOS = 4;
+        VIDEOS = 5;
+        AUDIO = 6;
+        DOWNLOADS = 7;
+        SYSTEM = 8;
+        OTHER = 9;
+    }
+    optional Category category = 1;
+    // Category size in bytes.
+    optional int64 size_bytes = 2;
+    // Time that the cache file was produced.
+    // Uses System.currentTimeMillis(), which is wall clock time.
+    optional int64 cache_time_millis = 3;
+}
diff --git a/cmds/statsd/src/condition/condition_util.cpp b/cmds/statsd/src/condition/condition_util.cpp
index 691356b..35e03e4 100644
--- a/cmds/statsd/src/condition/condition_util.cpp
+++ b/cmds/statsd/src/condition/condition_util.cpp
@@ -76,9 +76,9 @@
             break;
         }
         case LogicalOperation::NOT:
-            newCondition = (conditionCache[children[0]] == ConditionState::kFalse)
-                                   ? ConditionState::kTrue
-                                   : ConditionState::kFalse;
+            newCondition = children.empty() ? ConditionState::kUnknown :
+                              ((conditionCache[children[0]] == ConditionState::kFalse) ?
+                                  ConditionState::kTrue : ConditionState::kFalse);
             break;
         case LogicalOperation::NAND:
             newCondition = hasFalse ? ConditionState::kTrue : ConditionState::kFalse;
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index 611c342..122e669 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -31,9 +31,6 @@
 namespace os {
 namespace statsd {
 
-// Util function to build a hard coded config with test metrics.
-StatsdConfig build_fake_config();
-
 /**
  * Keeps track of which configurations have been set from various sources.
  */
diff --git a/cmds/statsd/src/external/Perfetto.cpp b/cmds/statsd/src/external/Perfetto.cpp
index 0554483..e44351b 100644
--- a/cmds/statsd/src/external/Perfetto.cpp
+++ b/cmds/statsd/src/external/Perfetto.cpp
@@ -113,7 +113,7 @@
         return false;
     }
 
-    std::string cfgProto = config.trace_config().SerializeAsString();
+    const std::string& cfgProto = config.trace_config();
     size_t bytesWritten = fwrite(cfgProto.data(), 1, cfgProto.size(), writePipeStream);
     fclose(writePipeStream);
     if (bytesWritten != cfgProto.size() || cfgProto.size() == 0) {
diff --git a/cmds/statsd/src/external/Perfprofd.cpp b/cmds/statsd/src/external/Perfprofd.cpp
index ff237e8..1678f10 100644
--- a/cmds/statsd/src/external/Perfprofd.cpp
+++ b/cmds/statsd/src/external/Perfprofd.cpp
@@ -55,17 +55,8 @@
       return false;
     }
 
-    // Add protobufs can't be described in AIDL, we need to re-serialize
-    // the config proto to send it.
-    std::vector<uint8_t> proto_serialized;
-    {
-      const auto& config_proto = config.perfprofd_config();
-      int size = config_proto.ByteSize();
-      proto_serialized.resize(size);
-      ::google::protobuf::uint8* target_ptr =
-          reinterpret_cast<::google::protobuf::uint8*>(proto_serialized.data());
-      config_proto.SerializeWithCachedSizesToArray(target_ptr);
-    }
+    auto* data = reinterpret_cast<const uint8_t*>(config.perfprofd_config().data());
+    std::vector<uint8_t> proto_serialized(data, data + config.perfprofd_config().size());
 
     // TODO: alert-id etc?
 
diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h
index caac677..22cb2f5 100644
--- a/cmds/statsd/src/external/StatsPuller.h
+++ b/cmds/statsd/src/external/StatsPuller.h
@@ -37,6 +37,8 @@
 
     virtual ~StatsPuller() {}
 
+    // Pulls the data. The returned data will have elapsedTimeNs set as timeNs
+    // and will have wallClockTimeNs set as current wall clock time.
     bool Pull(const int64_t timeNs, std::vector<std::shared_ptr<LogEvent>>* data);
 
     // Clear cache immediately
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 06edff9e..95510f5 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -149,9 +149,6 @@
         // system_uptime
         {android::util::SYSTEM_UPTIME,
          {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
-        // disk_space
-        {android::util::DISK_SPACE,
-         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_SPACE)}},
         // remaining_battery_capacity
         {android::util::REMAINING_BATTERY_CAPACITY,
          {{},
@@ -171,7 +168,44 @@
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
         // temperature
-        {android::util::TEMPERATURE, {{}, {}, 1, new ResourceThermalManagerPuller()}}};
+        {android::util::TEMPERATURE, {{}, {}, 1, new ResourceThermalManagerPuller()}},
+        // binder_calls
+        {android::util::BINDER_CALLS,
+         {{4, 5, 6, 8, 12},
+          {2, 3, 7, 9, 10, 11, 13},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::BINDER_CALLS)}},
+        // binder_calls_exceptions
+        {android::util::BINDER_CALLS_EXCEPTIONS,
+         {{},
+          {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}},
+        // Disk Stats
+        {android::util::DISK_STATS,
+         {{},
+          {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::DISK_STATS)}},
+        // Directory usage
+        {android::util::DIRECTORY_USAGE,
+         {{},
+          {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}},
+        // Size of app's code, data, and cache
+        {android::util::APP_SIZE,
+         {{},
+          {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::APP_SIZE)}},
+        // Size of specific categories of files. Eg. Music.
+        {android::util::CATEGORY_SIZE,
+         {{},
+          {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
+        };
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
 }
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 45efc4a..bbf5d9d 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -53,9 +53,12 @@
     virtual ~StatsPullerManager() {
     }
 
+    // Registers a receiver for tagId. It will be pulled on the nextPullTimeNs
+    // and then every intervalNs thereafter.
     virtual void RegisterReceiver(int tagId, wp<PullDataReceiver> receiver, int64_t nextPullTimeNs,
                                   int64_t intervalNs);
 
+    // Stop listening on a tagId.
     virtual void UnRegisterReceiver(int tagId, wp<PullDataReceiver> receiver);
 
     // Verify if we know how to pull for this matcher
@@ -63,11 +66,16 @@
 
     void OnAlarmFired(const int64_t timeNs);
 
+    // Use respective puller to pull the data. The returned data will have
+    // elapsedTimeNs set as timeNs and will have wallClockTimeNs set as current
+    // wall clock time.
     virtual bool Pull(const int tagId, const int64_t timeNs,
                       vector<std::shared_ptr<LogEvent>>* data);
 
+    // Clear pull data cache immediately.
     int ForceClearPullerCache();
 
+    // Clear pull data cache if it is beyond respective cool down time.
     int ClearPullerCacheIfNecessary(int64_t timestampNs);
 
     void SetStatsCompanionService(sp<IStatsCompanionService> statsCompanionService);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 038cb95..33f3917 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -50,7 +50,7 @@
 // const int FIELD_ID_PULLED_ATOM_STATS = 10; // The proto is written in stats_log_util.cpp
 const int FIELD_ID_LOGGER_ERROR_STATS = 11;
 const int FIELD_ID_PERIODIC_ALARM_STATS = 12;
-const int FIELD_ID_LOG_LOSS_STATS = 14;
+// const int FIELD_ID_LOG_LOSS_STATS = 14;
 const int FIELD_ID_SYSTEM_SERVER_RESTART = 15;
 
 const int FIELD_ID_ATOM_STATS_TAG = 1;
@@ -100,6 +100,7 @@
 const int FIELD_ID_UID_MAP_DELETED_APPS = 4;
 
 const std::map<int, std::pair<size_t, size_t>> StatsdStats::kAtomDimensionKeySizeLimitMap = {
+        {android::util::BINDER_CALLS, {6000, 10000}},
         {android::util::CPU_TIME_PER_UID_FREQ, {6000, 10000}},
 };
 
@@ -179,12 +180,12 @@
     noteConfigResetInternalLocked(key);
 }
 
-void StatsdStats::noteLogLost(int64_t timestampNs) {
+void StatsdStats::noteLogLost(int32_t wallClockTimeSec, int32_t count) {
     lock_guard<std::mutex> lock(mLock);
-    if (mLogLossTimestampNs.size() == kMaxLoggerErrors) {
-        mLogLossTimestampNs.pop_front();
+    if (mLogLossStats.size() == kMaxLoggerErrors) {
+        mLogLossStats.pop_front();
     }
-    mLogLossTimestampNs.push_back(timestampNs);
+    mLogLossStats.push_back(std::make_pair(wallClockTimeSec, count));
 }
 
 void StatsdStats::noteBroadcastSent(const ConfigKey& key) {
@@ -364,15 +365,6 @@
     mSystemServerRestartSec.push_back(timeSec);
 }
 
-void StatsdStats::noteLoggerError(int error) {
-    lock_guard<std::mutex> lock(mLock);
-    // grows strictly one at a time. so it won't > kMaxLoggerErrors
-    if (mLoggerErrors.size() == kMaxLoggerErrors) {
-        mLoggerErrors.pop_front();
-    }
-    mLoggerErrors.push_back(std::make_pair(getWallClockSec(), error));
-}
-
 void StatsdStats::reset() {
     lock_guard<std::mutex> lock(mLock);
     resetInternalLocked();
@@ -385,9 +377,8 @@
     std::fill(mPushedAtomStats.begin(), mPushedAtomStats.end(), 0);
     mAnomalyAlarmRegisteredStats = 0;
     mPeriodicAlarmRegisteredStats = 0;
-    mLoggerErrors.clear();
     mSystemServerRestartSec.clear();
-    mLogLossTimestampNs.clear();
+    mLogLossStats.clear();
     for (auto& config : mConfigStats) {
         config.second->broadcast_sent_time_sec.clear();
         config.second->data_drop_time_sec.clear();
@@ -514,21 +505,14 @@
             mUidMapStats.bytes_used, mUidMapStats.changes, mUidMapStats.deleted_apps,
             mUidMapStats.dropped_changes);
 
-    for (const auto& error : mLoggerErrors) {
-        time_t error_time = error.first;
-        struct tm* error_tm = localtime(&error_time);
-        char buffer[80];
-        strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M%p\n", error_tm);
-        fprintf(out, "Logger error %d at %s\n", error.second, buffer);
-    }
-
     for (const auto& restart : mSystemServerRestartSec) {
         fprintf(out, "System server restarts at %s(%lld)\n",
             buildTimeString(restart).c_str(), (long long)restart);
     }
 
-    for (const auto& loss : mLogLossTimestampNs) {
-        fprintf(out, "Log loss detected at %lld (elapsedRealtimeNs)\n", (long long)loss);
+    for (const auto& loss : mLogLossStats) {
+        fprintf(out, "Log loss: %lld (wall clock sec) - %d (count)\n", (long long)loss.first,
+                loss.second);
     }
 }
 
@@ -676,7 +660,10 @@
     proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_DELETED_APPS, mUidMapStats.deleted_apps);
     proto.end(uidMapToken);
 
-    for (const auto& error : mLoggerErrors) {
+    for (const auto& error : mLogLossStats) {
+        // The logger error stats are not used anymore since we move away from logd.
+        // Temporarily use this field to log the log loss timestamp and count
+        // TODO(b/80538532) Add a dedicated field in stats_log for this.
         uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_LOGGER_ERROR_STATS |
                                       FIELD_COUNT_REPEATED);
         proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOGGER_STATS_TIME, error.first);
@@ -684,11 +671,6 @@
         proto.end(token);
     }
 
-    for (const auto& loss : mLogLossTimestampNs) {
-        proto.write(FIELD_TYPE_INT64 | FIELD_ID_LOG_LOSS_STATS | FIELD_COUNT_REPEATED,
-                    (long long)loss);
-    }
-
     for (const auto& restart : mSystemServerRestartSec) {
         proto.write(FIELD_TYPE_INT32 | FIELD_ID_SYSTEM_SERVER_RESTART | FIELD_COUNT_REPEATED,
                     restart);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 9fb2cd8..b5156da 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -271,11 +271,6 @@
     // Notify pull request for an atom served from cached data
     void notePullFromCache(int pullAtomId);
 
-    /**
-     * Records statsd met an error while reading from logd.
-     */
-    void noteLoggerError(int error);
-
     /*
     * Records when system server restarts.
     */
@@ -284,7 +279,7 @@
     /**
      * Records statsd skipped an event.
      */
-    void noteLogLost(int64_t timestamp);
+    void noteLogLost(int32_t wallClockTimeSec, int32_t count);
 
     /**
      * Reset the historical stats. Including all stats in icebox, and the tracked stats about
@@ -338,11 +333,8 @@
     // Maps PullAtomId to its stats. The size is capped by the puller atom counts.
     std::map<int, PulledAtomStats> mPulledAtomStats;
 
-    // Logd errors. Size capped by kMaxLoggerErrors.
-    std::list<const std::pair<int, int>> mLoggerErrors;
-
-    // Timestamps when we detect log loss after logd reconnect.
-    std::list<int64_t> mLogLossTimestampNs;
+    // Timestamps when we detect log loss, and the number of logs lost.
+    std::list<std::pair<int32_t, int32_t>> mLogLossStats;
 
     std::list<int32_t> mSystemServerRestartSec;
 
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 04d34f3..73e6572 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -18,6 +18,7 @@
 #include "logd/LogEvent.h"
 
 #include "stats_log_util.h"
+#include "statslog.h"
 
 namespace android {
 namespace os {
@@ -51,6 +52,52 @@
     }
 }
 
+LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                   int32_t uid,
+                   const std::map<int32_t, int64_t>& int_map,
+                   const std::map<int32_t, std::string>& string_map,
+                   const std::map<int32_t, float>& float_map) {
+    mLogdTimestampNs = wallClockTimestampNs;
+    mElapsedTimestampNs = elapsedTimestampNs;
+    mTagId = android::util::KEY_VALUE_PAIRS_ATOM;
+    mLogUid = uid;
+
+    int pos[] = {1, 1, 1};
+
+    mValues.push_back(FieldValue(Field(mTagId, pos, 0 /* depth */), Value(uid)));
+    pos[0]++;
+    for (const auto&itr : int_map) {
+        pos[2] = 1;
+        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
+        pos[2] = 2;
+        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
+        mValues.back().mField.decorateLastPos(2);
+        pos[1]++;
+    }
+
+    for (const auto&itr : string_map) {
+        pos[2] = 1;
+        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
+        pos[2] = 3;
+        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
+        mValues.back().mField.decorateLastPos(2);
+        pos[1]++;
+    }
+
+    for (const auto&itr : float_map) {
+        pos[2] = 1;
+        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
+        pos[2] = 4;
+        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
+        mValues.back().mField.decorateLastPos(2);
+        pos[1]++;
+    }
+    if (!mValues.empty()) {
+        mValues.back().mField.decorateLastPos(1);
+        mValues.at(mValues.size() - 2).mField.decorateLastPos(1);
+    }
+}
+
 LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) {
     mLogdTimestampNs = timestampNs;
     mTagId = tagId;
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 24d624d..9ed09dd 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -69,6 +69,15 @@
     // For testing. The timestamp is used as both elapsed real time and logd timestamp.
     explicit LogEvent(int32_t tagId, int64_t timestampNs);
 
+    /**
+     * Constructs a KeyValuePairsAtom LogEvent from value maps.
+     */
+    explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                      int32_t uid,
+                      const std::map<int32_t, int64_t>& int_map,
+                      const std::map<int32_t, std::string>& string_map,
+                      const std::map<int32_t, float>& float_map);
+
     ~LogEvent();
 
     /**
diff --git a/cmds/statsd/src/logd/LogListener.cpp b/cmds/statsd/src/logd/LogListener.cpp
index 6ac7978..ddb26f9 100644
--- a/cmds/statsd/src/logd/LogListener.cpp
+++ b/cmds/statsd/src/logd/LogListener.cpp
@@ -14,17 +14,7 @@
  * limitations under the License.
  */
 
-#include "logd/LogReader.h"
-
-#include <log/log_read.h>
-
-#include <utils/Errors.h>
-
-#include <time.h>
-#include <unistd.h>
-
-using namespace android;
-using namespace std;
+#include "logd/LogListener.h"
 
 namespace android {
 namespace os {
diff --git a/cmds/statsd/src/logd/LogListener.h b/cmds/statsd/src/logd/LogListener.h
index f924040..d8b06e9 100644
--- a/cmds/statsd/src/logd/LogListener.h
+++ b/cmds/statsd/src/logd/LogListener.h
@@ -19,7 +19,6 @@
 #include "logd/LogEvent.h"
 
 #include <utils/RefBase.h>
-#include <vector>
 
 namespace android {
 namespace os {
@@ -33,7 +32,7 @@
     LogListener();
     virtual ~LogListener();
 
-    virtual void OnLogEvent(LogEvent* msg, bool reconnectionStarts) = 0;
+    virtual void OnLogEvent(LogEvent* msg) = 0;
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/logd/LogReader.cpp b/cmds/statsd/src/logd/LogReader.cpp
deleted file mode 100644
index 26ae6a3..0000000
--- a/cmds/statsd/src/logd/LogReader.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "logd/LogReader.h"
-
-#include "guardrail/StatsdStats.h"
-
-#include <time.h>
-#include <unistd.h>
-#include <utils/Errors.h>
-
-using namespace android;
-using namespace std;
-
-namespace android {
-namespace os {
-namespace statsd {
-
-#define SNOOZE_INITIAL_MS 100
-#define SNOOZE_MAX_MS (10 * 60 * 1000)  // Ten minutes
-
-LogReader::LogReader(const sp<LogListener>& listener) : mListener(listener) {
-}
-
-LogReader::~LogReader() {
-}
-
-void LogReader::Run() {
-    int nextSnoozeMs = SNOOZE_INITIAL_MS;
-
-    // In an ideal world, this outer loop will only ever run one iteration, but it
-    // exists to handle crashes in logd.  The inner loop inside connect_and_read()
-    // reads from logd forever, but if that read fails, we fall out to the outer
-    // loop, do the backoff (resetting the backoff timeout if we successfully read
-    // something), and then try again.
-    while (true) {
-        // Connect and read
-        int lineCount = connect_and_read();
-
-        // Figure out how long to sleep.
-        if (lineCount > 0) {
-            // If we managed to read at least one line, reset the backoff
-            nextSnoozeMs = SNOOZE_INITIAL_MS;
-        } else {
-            // Otherwise, expontial backoff
-            nextSnoozeMs *= 1.5f;
-            if (nextSnoozeMs > 10 * 60 * 1000) {
-                // Don't wait for toooo long.
-                nextSnoozeMs = SNOOZE_MAX_MS;
-            }
-        }
-
-        // Sleep
-        timespec ts;
-        timespec rem;
-        ts.tv_sec = nextSnoozeMs / 1000;
-        ts.tv_nsec = (nextSnoozeMs % 1000) * 1000000L;
-        while (nanosleep(&ts, &rem) == -1) {
-            if (errno == EINTR) {
-                ts = rem;
-            }
-            // other errors are basically impossible
-        }
-    }
-}
-
-int LogReader::connect_and_read() {
-    int lineCount = 0;
-    status_t err;
-    logger_list* loggers;
-    logger* eventLogger;
-
-    // Prepare the logging context
-    loggers = android_logger_list_alloc(ANDROID_LOG_RDONLY,
-                                        /* don't stop after N lines */ 0,
-                                        /* no pid restriction */ 0);
-
-    // Open the buffer(s)
-    eventLogger = android_logger_open(loggers, LOG_ID_STATS);
-
-    // Read forever
-    if (eventLogger) {
-        log_msg msg;
-        while (true) {
-            // Read a message
-            err = android_logger_list_read(loggers, &msg);
-            // err = 0 - no content, unexpected connection drop or EOF.
-            // err = +ive number - size of retrieved data from logger
-            // err = -ive number, OS supplied error _except_ for -EAGAIN
-            if (err <= 0) {
-                StatsdStats::getInstance().noteLoggerError(err);
-                fprintf(stderr, "logcat read failure: %s\n", strerror(err));
-                break;
-            }
-
-            // Record that we read one (used above to know how to snooze).
-            lineCount++;
-
-            // Wrap it in a LogEvent object
-            LogEvent event(msg);
-
-            // Call the listener
-            mListener->OnLogEvent(&event,
-                                  lineCount == 1 /* indicate whether it's a new connection */);
-        }
-    }
-
-    // Free the logger list and close the individual loggers
-    android_logger_list_free(loggers);
-
-    return lineCount;
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/logd/LogReader.h b/cmds/statsd/src/logd/LogReader.h
deleted file mode 100644
index c51074c..0000000
--- a/cmds/statsd/src/logd/LogReader.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LOGREADER_H
-#define LOGREADER_H
-
-#include "logd/LogListener.h"
-
-#include <utils/RefBase.h>
-
-#include <vector>
-
-namespace android {
-namespace os {
-namespace statsd {
-
-/**
- * Class to read logs from logd.
- */
-class LogReader : public virtual android::RefBase {
-public:
-    /**
-     * Construct the LogReader with the event listener. (Which is StatsService)
-     */
-    LogReader(const sp<LogListener>& listener);
-
-    /**
-     * Destructor.
-     */
-    virtual ~LogReader();
-
-    /**
-     * Run the main LogReader loop
-     */
-    void Run();
-
-private:
-    /**
-     * Who is going to get the events when they're read.
-     */
-    sp<LogListener> mListener;
-
-    /**
-     * Connect to a single instance of logd, and read until there's a read error.
-     * Logd can crash, exit, be killed etc.
-     *
-     * Returns the number of lines that were read.
-     */
-    int connect_and_read();
-};
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
-
-#endif  // LOGREADER_H
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index 2f15d0f..9002f07 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -18,7 +18,6 @@
 #include "Log.h"
 
 #include "StatsService.h"
-#include "logd/LogReader.h"
 #include "socket/StatsSocketListener.h"
 
 #include <binder/IInterface.h>
@@ -39,9 +38,6 @@
 using namespace android;
 using namespace android::os::statsd;
 
-const bool kUseLogd = false;
-const bool kUseStatsdSocket = true;
-
 /**
  * Thread function data.
  */
@@ -49,58 +45,6 @@
     sp<StatsService> service;
 };
 
-/**
- * Thread func for where the log reader runs.
- */
-static void* log_reader_thread_func(void* cookie) {
-    log_reader_thread_data* data = static_cast<log_reader_thread_data*>(cookie);
-    sp<LogReader> reader = new LogReader(data->service);
-
-    // Run the read loop. Never returns.
-    reader->Run();
-
-    ALOGW("statsd LogReader.Run() is not supposed to return.");
-
-    delete data;
-    return NULL;
-}
-
-/**
- * Creates and starts the thread to own the LogReader.
- */
-static status_t start_log_reader_thread(const sp<StatsService>& service) {
-    status_t err;
-    pthread_attr_t attr;
-    pthread_t thread;
-
-    // Thread data.
-    std::unique_ptr<log_reader_thread_data> data = std::make_unique<log_reader_thread_data>();
-    data->service = service;
-
-    // Create the thread
-    err = pthread_attr_init(&attr);
-    if (err != NO_ERROR) {
-        return err;
-    }
-    err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-    if (err != NO_ERROR) {
-        pthread_attr_destroy(&attr);
-        return err;
-    }
-    err = pthread_create(&thread, &attr, log_reader_thread_func,
-                         static_cast<void*>(data.get()));
-    if (err != NO_ERROR) {
-        pthread_attr_destroy(&attr);
-        return err;
-    }
-    // Release here rather than in pthread_create, since an error creating the
-    // thread leaves `data` ownerless.
-    data.release();
-    pthread_attr_destroy(&attr);
-
-    return NO_ERROR;
-}
-
 int main(int /*argc*/, char** /*argv*/) {
     // Set up the looper
     sp<Looper> looper(Looper::prepare(0 /* opts */));
@@ -124,22 +68,11 @@
 
     sp<StatsSocketListener> socketListener = new StatsSocketListener(service);
 
-    if (kUseLogd) {
-        ALOGI("using logd");
-        // Start the log reader thread
-        status_t err = start_log_reader_thread(service);
-        if (err != NO_ERROR) {
-            return 1;
-        }
-    }
-
-    if (kUseStatsdSocket) {
         ALOGI("using statsd socket");
         // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
         if (socketListener->startListener(600)) {
             exit(1);
         }
-    }
 
     // Loop forever -- the reports run on this thread in a handler, and the
     // binder calls remain responsive in their pool of one thread.
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index a894782..bd94800 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -66,8 +66,8 @@
 CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric& metric,
                                          const int conditionIndex,
                                          const sp<ConditionWizard>& wizard,
-                                         const int64_t startTimeNs)
-    : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard) {
+                                         const int64_t timeBaseNs, const int64_t startTimeNs)
+    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard) {
     if (metric.has_bucket()) {
         mBucketSizeNs =
                 TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
@@ -100,6 +100,10 @@
 
     mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
 
+    flushIfNeededLocked(startTimeNs);
+    // Adjust start for partial bucket
+    mCurrentBucketStartTimeNs = startTimeNs;
+
     VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
          (long long)mBucketSizeNs, (long long)mTimeBaseNs);
 }
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 520d5de..39d4ae2 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -42,7 +42,7 @@
 public:
     CountMetricProducer(const ConfigKey& key, const CountMetric& countMetric,
                         const int conditionIndex, const sp<ConditionWizard>& wizard,
-                        const int64_t startTimeNs);
+                        const int64_t timeBaseNs, const int64_t startTimeNs);
 
     virtual ~CountMetricProducer();
 
@@ -98,6 +98,7 @@
     FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced);
     FRIEND_TEST(CountMetricProducerTest, TestEventWithAppUpgrade);
     FRIEND_TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket);
+    FRIEND_TEST(CountMetricProducerTest, TestFirstBucket);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index a19eb0b..9d9e5be9 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -68,8 +68,8 @@
                                                const bool nesting,
                                                const sp<ConditionWizard>& wizard,
                                                const FieldMatcher& internalDimensions,
-                                               const int64_t startTimeNs)
-    : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
+                                               const int64_t timeBaseNs, const int64_t startTimeNs)
+    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
       mAggregationType(metric.aggregation_type()),
       mStartIndex(startIndex),
       mStopIndex(stopIndex),
@@ -128,6 +128,9 @@
                                                mMetric2ConditionLinks.begin()->conditionFields);
         }
     }
+    flushIfNeededLocked(startTimeNs);
+    // Adjust start for partial bucket
+    mCurrentBucketStartTimeNs = startTimeNs;
     VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
          (long long)mBucketSizeNs, (long long)mTimeBaseNs);
 }
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index c496b12..12addb8 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -42,7 +42,7 @@
                            const int conditionIndex, const size_t startIndex,
                            const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
                            const sp<ConditionWizard>& wizard,
-                           const FieldMatcher& internalDimensions, const int64_t startTimeNs);
+                           const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs);
 
     virtual ~DurationMetricProducer();
 
@@ -141,6 +141,7 @@
     FRIEND_TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade);
     FRIEND_TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket);
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicates);
+    FRIEND_TEST(DurationMetricTrackerTest, TestFirstBucket);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index a779410..284c451 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -71,11 +71,15 @@
 GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
                                          const int conditionIndex,
                                          const sp<ConditionWizard>& wizard, const int pullTagId,
+                                         const int triggerAtomId, const int atomId,
                                          const int64_t timeBaseNs, const int64_t startTimeNs,
                                          const sp<StatsPullerManager>& pullerManager)
     : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
       mPullerManager(pullerManager),
       mPullTagId(pullTagId),
+      mTriggerAtomId(triggerAtomId),
+      mAtomId(atomId),
+      mIsPulled(pullTagId != -1),
       mMinBucketSizeNs(metric.min_bucket_size_nanos()),
       mDimensionSoftLimit(StatsdStats::kAtomDimensionKeySizeLimitMap.find(pullTagId) !=
                                           StatsdStats::kAtomDimensionKeySizeLimitMap.end()
@@ -125,11 +129,17 @@
 
     flushIfNeededLocked(startTimeNs);
     // Kicks off the puller immediately.
-    if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
+    if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
         mPullerManager->RegisterReceiver(mPullTagId, this, getCurrentBucketEndTimeNs(),
                                          mBucketSizeNs);
     }
 
+    // Adjust start for partial bucket
+    mCurrentBucketStartTimeNs = startTimeNs;
+    if (mIsPulled) {
+        pullLocked(startTimeNs);
+    }
+
     VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
          (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs,
          mConditionSliced);
@@ -137,7 +147,7 @@
 
 GaugeMetricProducer::~GaugeMetricProducer() {
     VLOG("~GaugeMetricProducer() called");
-    if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
+    if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
         mPullerManager->UnRegisterReceiver(mPullTagId, this);
     }
 }
@@ -265,12 +275,12 @@
                     uint64_t atomsToken =
                         protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
                                            FIELD_ID_ATOM);
-                    writeFieldValueTreeToStream(mTagId, *(atom.mFields), protoOutput);
+                    writeFieldValueTreeToStream(mAtomId, *(atom.mFields), protoOutput);
                     protoOutput->end(atomsToken);
                 }
                 const bool truncateTimestamp =
                         android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.find(
-                                mTagId) ==
+                                mAtomId) ==
                         android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.end();
                 for (const auto& atom : bucket.mGaugeAtoms) {
                     const int64_t elapsedTimestampNs =  truncateTimestamp ?
@@ -323,13 +333,11 @@
     if (!triggerPuller) {
         return;
     }
-
     vector<std::shared_ptr<LogEvent>> allData;
     if (!mPullerManager->Pull(mPullTagId, timestampNs, &allData)) {
-        ALOGE("Gauge Stats puller failed for tag: %d", mPullTagId);
+        ALOGE("Gauge Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
         return;
     }
-
     for (const auto& data : allData) {
         onMatchedLogEventLocked(0, *data);
     }
@@ -340,8 +348,7 @@
     VLOG("GaugeMetric %lld onConditionChanged", (long long)mMetricId);
     flushIfNeededLocked(eventTimeNs);
     mCondition = conditionMet;
-
-    if (mPullTagId != -1) {
+    if (mIsPulled) {
         pullLocked(eventTimeNs);
     }  // else: Push mode. No need to proactively pull the gauge data.
 }
@@ -354,7 +361,7 @@
     // If the condition is sliced, mCondition is true if any of the dimensions is true. And we will
     // pull for every dimension.
     mCondition = overallCondition;
-    if (mPullTagId != -1) {
+    if (mIsPulled) {
         pullLocked(eventTimeNs);
     }  // else: Push mode. No need to proactively pull the gauge data.
 }
@@ -406,7 +413,6 @@
         return;
     }
     int64_t eventTimeNs = event.GetElapsedTimestampNs();
-    mTagId = event.GetTagId();
     if (eventTimeNs < mCurrentBucketStartTimeNs) {
         VLOG("Gauge Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
              (long long)mCurrentBucketStartTimeNs);
@@ -414,6 +420,11 @@
     }
     flushIfNeededLocked(eventTimeNs);
 
+    if (mTriggerAtomId == event.GetTagId()) {
+        pullLocked(eventTimeNs);
+        return;
+    }
+
     // When gauge metric wants to randomly sample the output atom, we just simply use the first
     // gauge in the given bucket.
     if (mCurrentSlicedBucket->find(eventKey) != mCurrentSlicedBucket->end() &&
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 89b1f41..15be1d7 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -33,7 +33,7 @@
 namespace statsd {
 
 struct GaugeAtom {
-    GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t elapsedTimeNs, int wallClockNs)
+    GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t elapsedTimeNs, int64_t wallClockNs)
         : mFields(fields), mElapsedTimestamps(elapsedTimeNs), mWallClockTimestampNs(wallClockNs) {
     }
     std::shared_ptr<vector<FieldValue>> mFields;
@@ -58,7 +58,8 @@
 public:
     GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
                         const int conditionIndex, const sp<ConditionWizard>& wizard,
-                        const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
+                        const int pullTagId, const int triggerAtomId, const int atomId,
+                        const int64_t timeBaseNs, const int64_t startTimeNs,
                         const sp<StatsPullerManager>& pullerManager);
 
     virtual ~GaugeMetricProducer();
@@ -77,7 +78,7 @@
         }
         flushCurrentBucketLocked(eventTimeNs);
         mCurrentBucketStartTimeNs = eventTimeNs;
-        if (mPullTagId != -1) {
+        if (mIsPulled) {
             pullLocked(eventTimeNs);
         }
     };
@@ -115,12 +116,19 @@
 
     void pullLocked(const int64_t timestampNs);
 
-    int mTagId;
-
     sp<StatsPullerManager> mPullerManager;
     // tagId for pulled data. -1 if this is not pulled
     const int mPullTagId;
 
+    // tagId for atoms that trigger the pulling, if any
+    const int mTriggerAtomId;
+
+    // tagId for output atom
+    const int mAtomId;
+
+    // if this is pulled metric
+    const bool mIsPulled;
+
     // Save the past buckets and we can clear when the StatsLogReport is dumped.
     std::unordered_map<MetricDimensionKey, std::vector<GaugeBucket>> mPastBuckets;
 
@@ -159,12 +167,14 @@
 
     const size_t mGaugeAtomsPerDimensionLimit;
 
-    FRIEND_TEST(GaugeMetricProducerTest, TestWithCondition);
-    FRIEND_TEST(GaugeMetricProducerTest, TestWithSlicedCondition);
-    FRIEND_TEST(GaugeMetricProducerTest, TestNoCondition);
+    FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition);
+    FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition);
+    FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition);
     FRIEND_TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade);
     FRIEND_TEST(GaugeMetricProducerTest, TestPulledWithUpgrade);
-    FRIEND_TEST(GaugeMetricProducerTest, TestAnomalyDetection);
+    FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection);
+    FRIEND_TEST(GaugeMetricProducerTest, TestFirstBucket);
+    FRIEND_TEST(GaugeMetricProducerTest, TestPullOnTrigger);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index f5e953a..192a54b 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -27,7 +27,7 @@
 
 using android::util::FIELD_COUNT_REPEATED;
 using android::util::FIELD_TYPE_BOOL;
-using android::util::FIELD_TYPE_FLOAT;
+using android::util::FIELD_TYPE_DOUBLE;
 using android::util::FIELD_TYPE_INT32;
 using android::util::FIELD_TYPE_INT64;
 using android::util::FIELD_TYPE_MESSAGE;
@@ -64,7 +64,8 @@
 const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4;
 const int FIELD_ID_DIMENSION_LEAF_IN_CONDITION = 5;
 // for ValueBucketInfo
-const int FIELD_ID_VALUE = 3;
+const int FIELD_ID_VALUE_LONG = 7;
+const int FIELD_ID_VALUE_DOUBLE = 8;
 const int FIELD_ID_BUCKET_NUM = 4;
 const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 5;
 const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
@@ -73,12 +74,13 @@
 ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
                                          const int conditionIndex,
                                          const sp<ConditionWizard>& wizard, const int pullTagId,
-                                         const int64_t timeBaseNs, const int64_t startTimestampNs,
+                                         const int64_t timeBaseNs, const int64_t startTimeNs,
                                          const sp<StatsPullerManager>& pullerManager)
     : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
       mPullerManager(pullerManager),
       mValueField(metric.value_field()),
       mPullTagId(pullTagId),
+      mIsPulled(pullTagId != -1),
       mMinBucketSizeNs(metric.min_bucket_size_nanos()),
       mDimensionSoftLimit(StatsdStats::kAtomDimensionKeySizeLimitMap.find(pullTagId) !=
                                           StatsdStats::kAtomDimensionKeySizeLimitMap.end()
@@ -88,7 +90,9 @@
                                           StatsdStats::kAtomDimensionKeySizeLimitMap.end()
                                   ? StatsdStats::kAtomDimensionKeySizeLimitMap.at(pullTagId).second
                                   : StatsdStats::kDimensionKeySizeHardLimit),
-      mUseAbsoluteValueOnReset(metric.use_absolute_value_on_reset()) {
+      mUseAbsoluteValueOnReset(metric.use_absolute_value_on_reset()),
+      mAggregationType(metric.aggregation_type()),
+      mValueType(metric.aggregation_type() == ValueMetric::AVG ? DOUBLE : LONG) {
     int64_t bucketSizeMills = 0;
     if (metric.has_bucket()) {
         bucketSizeMills = TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket());
@@ -123,20 +127,27 @@
     mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()) ||
             HasPositionALL(metric.dimensions_in_condition());
 
+    flushIfNeededLocked(startTimeNs);
     // Kicks off the puller immediately.
-    flushIfNeededLocked(startTimestampNs);
-    if (mPullTagId != -1) {
-        mPullerManager->RegisterReceiver(mPullTagId, this,
-                                         mCurrentBucketStartTimeNs + mBucketSizeNs, mBucketSizeNs);
+    if (mIsPulled) {
+        mPullerManager->RegisterReceiver(mPullTagId, this, getCurrentBucketEndTimeNs(),
+                                         mBucketSizeNs);
     }
 
+    // TODO: Only do this for partial buckets like first bucket. All other buckets should use
+    // flushIfNeeded to adjust start and end to bucket boundaries.
+    // Adjust start for partial bucket
+    mCurrentBucketStartTimeNs = startTimeNs;
+    if (mIsPulled) {
+        pullLocked(startTimeNs);
+    }
     VLOG("value metric %lld created. bucket size %lld start_time: %lld",
         (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs);
 }
 
 ValueMetricProducer::~ValueMetricProducer() {
     VLOG("~ValueMetricProducer() called");
-    if (mPullTagId != -1) {
+    if (mIsPulled) {
         mPullerManager->UnRegisterReceiver(mPullTagId, this);
     }
 }
@@ -245,11 +256,15 @@
                 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_NUM,
                                    (long long)(getBucketNumFromEndTimeNs(bucket.mBucketEndNs)));
             }
-
-            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE, (long long)bucket.mValue);
+            if (mValueType == LONG) {
+                protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE_LONG,
+                                   (long long)bucket.mValueLong);
+            } else {
+                protoOutput->write(FIELD_TYPE_DOUBLE | FIELD_ID_VALUE_DOUBLE, bucket.mValueDouble);
+            }
             protoOutput->end(bucketInfoToken);
-            VLOG("\t bucket [%lld - %lld] count: %lld", (long long)bucket.mBucketStartNs,
-                 (long long)bucket.mBucketEndNs, (long long)bucket.mValue);
+            VLOG("\t bucket [%lld - %lld] count: %lld, %.2f", (long long)bucket.mBucketStartNs,
+                 (long long)bucket.mBucketEndNs, (long long)bucket.mValueLong, bucket.mValueDouble);
         }
         protoOutput->end(wrapperToken);
     }
@@ -271,17 +286,20 @@
 
     flushIfNeededLocked(eventTimeNs);
 
-    if (mPullTagId != -1) {
-        vector<shared_ptr<LogEvent>> allData;
-        if (mPullerManager->Pull(mPullTagId, eventTimeNs, &allData)) {
-            if (allData.size() == 0) {
-                return;
-            }
-            for (const auto& data : allData) {
-                onMatchedLogEventLocked(0, *data);
-            }
+    if (mIsPulled) {
+        pullLocked(eventTimeNs);
+    }
+}
+
+void ValueMetricProducer::pullLocked(const int64_t timestampNs) {
+    vector<std::shared_ptr<LogEvent>> allData;
+    if (mPullerManager->Pull(mPullTagId, timestampNs, &allData)) {
+        if (allData.size() == 0) {
+            return;
         }
-        return;
+        for (const auto& data : allData) {
+            onMatchedLogEventLocked(0, *data);
+        }
     }
 }
 
@@ -298,12 +316,14 @@
         int64_t eventTime = mTimeBaseNs +
             ((realEventTime - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
 
+        // close the end of the bucket
         mCondition = false;
         for (const auto& data : allData) {
             data->setElapsedTimestampNs(eventTime - 1);
             onMatchedLogEventLocked(0, *data);
         }
 
+        // start a new bucket
         mCondition = true;
         for (const auto& data : allData) {
             data->setElapsedTimestampNs(eventTime);
@@ -321,10 +341,10 @@
             (unsigned long)mCurrentSlicedBucket.size());
     if (verbose) {
         for (const auto& it : mCurrentSlicedBucket) {
-            fprintf(out, "\t(what)%s\t(condition)%s  (value)%lld\n",
-                it.first.getDimensionKeyInWhat().toString().c_str(),
-                it.first.getDimensionKeyInCondition().toString().c_str(),
-                (unsigned long long)it.second.sum);
+            fprintf(out, "\t(what)%s\t(condition)%s  (value)%s\n",
+                    it.first.getDimensionKeyInWhat().toString().c_str(),
+                    it.first.getDimensionKeyInCondition().toString().c_str(),
+                    it.second.value.toString().c_str());
         }
     }
 }
@@ -349,6 +369,27 @@
     return false;
 }
 
+const Value getDoubleOrLong(const Value& value) {
+    Value v;
+    switch (value.type) {
+        case INT:
+            v.setLong(value.int_value);
+            break;
+        case LONG:
+            v.setLong(value.long_value);
+            break;
+        case FLOAT:
+            v.setDouble(value.float_value);
+            break;
+        case DOUBLE:
+            v.setDouble(value.double_value);
+            break;
+        default:
+            break;
+    }
+    return v;
+}
+
 void ValueMetricProducer::onMatchedLogEventInternalLocked(
         const size_t matcherIndex, const MetricDimensionKey& eventKey,
         const ConditionKey& conditionKey, bool condition,
@@ -367,19 +408,25 @@
     }
     Interval& interval = mCurrentSlicedBucket[eventKey];
 
-    int error = 0;
-    const int64_t value = event.GetLong(mField, &error);
-    if (error < 0) {
+    if (mField > event.size()) {
+        VLOG("Failed to extract value field %d from atom %s. %d", mField, event.ToString().c_str(),
+             (int)event.size());
         return;
     }
+    Value value = getDoubleOrLong(event.getValues()[mField - 1].mValue);
 
-    if (mPullTagId != -1) { // for pulled events
+    Value diff;
+    bool hasDiff = false;
+    if (mIsPulled) {
+        // Always require condition for pulled events. In the case of no condition, only pull
+        // on bucket boundaries, in which we fake condition changes.
         if (mCondition == true) {
             if (!interval.startUpdated) {
                 interval.start = value;
                 interval.startUpdated = true;
             } else {
-                // skip it if there is already value recorded for the start
+                // Skip it if there is already value recorded for the start. Happens when puller
+                // takes too long to finish. In this case we take the previous value.
                 VLOG("Already recorded value for this dimension %s", eventKey.toString().c_str());
             }
         } else {
@@ -387,31 +434,55 @@
             // If not, take absolute value or drop it, based on config.
             if (interval.startUpdated) {
                 if (value >= interval.start) {
-                    interval.sum += (value - interval.start);
-                    interval.hasValue = true;
+                    diff = (value - interval.start);
+                    hasDiff = true;
                 } else {
                     if (mUseAbsoluteValueOnReset) {
-                        interval.sum += value;
-                        interval.hasValue = true;
+                        diff = value;
+                        hasDiff = true;
                     } else {
-                        VLOG("Dropping data for atom %d, prev: %lld, now: %lld", mPullTagId,
-                             (long long)interval.start, (long long)value);
+                        VLOG("Dropping data for atom %d, prev: %s, now: %s", mPullTagId,
+                             interval.start.toString().c_str(), value.toString().c_str());
                     }
                 }
                 interval.startUpdated = false;
             } else {
-                VLOG("No start for matching end %lld", (long long)value);
-                interval.tainted += 1;
+                VLOG("No start for matching end %s", value.toString().c_str());
             }
         }
-    } else {    // for pushed events, only accumulate when condition is true
-        if (mCondition == true || mConditionTrackerIndex < 0) {
-            interval.sum += value;
-            interval.hasValue = true;
+    } else {
+        // for pushed events, only aggregate when sliced condition is true
+        if (condition == true || mConditionTrackerIndex < 0) {
+            diff = value;
+            hasDiff = true;
         }
     }
+    if (hasDiff) {
+        if (interval.hasValue) {
+            switch (mAggregationType) {
+                case ValueMetric::SUM:
+                // for AVG, we add up and take average when flushing the bucket
+                case ValueMetric::AVG:
+                    interval.value += diff;
+                    break;
+                case ValueMetric::MIN:
+                    interval.value = diff < interval.value ? diff : interval.value;
+                    break;
+                case ValueMetric::MAX:
+                    interval.value = diff > interval.value ? diff : interval.value;
+                    break;
+                default:
+                    break;
+            }
+        } else {
+            interval.value = diff;
+            interval.hasValue = true;
+        }
+        interval.sampleSize += 1;
+    }
 
-    long wholeBucketVal = interval.sum;
+    // TODO: propgate proper values down stream when anomaly support doubles
+    long wholeBucketVal = interval.value.long_value;
     auto prev = mCurrentFullBucket.find(eventKey);
     if (prev != mCurrentFullBucket.end()) {
         wholeBucketVal += prev->second;
@@ -458,18 +529,15 @@
 
     if (info.mBucketEndNs - mCurrentBucketStartTimeNs >= mMinBucketSizeNs) {
         // The current bucket is large enough to keep.
-        int tainted = 0;
         for (const auto& slice : mCurrentSlicedBucket) {
-            tainted += slice.second.tainted;
-            tainted += slice.second.startUpdated;
             if (slice.second.hasValue) {
-                info.mValue = slice.second.sum;
+                info.mValueLong = slice.second.value.long_value;
+                info.mValueDouble = (double)slice.second.value.long_value / slice.second.sampleSize;
                 // it will auto create new vector of ValuebucketInfo if the key is not found.
                 auto& bucketList = mPastBuckets[slice.first];
                 bucketList.push_back(info);
             }
         }
-        VLOG("%d tainted pairs in the bucket", tainted);
     } else {
         mSkippedBuckets.emplace_back(info.mBucketStartNs, info.mBucketEndNs);
     }
@@ -478,7 +546,8 @@
         // Accumulate partial buckets with current value and then send to anomaly tracker.
         if (mCurrentFullBucket.size() > 0) {
             for (const auto& slice : mCurrentSlicedBucket) {
-                mCurrentFullBucket[slice.first] += slice.second.sum;
+                // TODO: fix this when anomaly can accept double values
+                mCurrentFullBucket[slice.first] += slice.second.value.long_value;
             }
             for (const auto& slice : mCurrentFullBucket) {
                 for (auto& tracker : mAnomalyTrackers) {
@@ -493,7 +562,9 @@
             for (const auto& slice : mCurrentSlicedBucket) {
                 for (auto& tracker : mAnomalyTrackers) {
                     if (tracker != nullptr) {
-                        tracker->addPastBucket(slice.first, slice.second.sum, mCurrentBucketNum);
+                        // TODO: fix this when anomaly can accept double values
+                        tracker->addPastBucket(slice.first, slice.second.value.long_value,
+                                               mCurrentBucketNum);
                     }
                 }
             }
@@ -501,7 +572,8 @@
     } else {
         // Accumulate partial bucket.
         for (const auto& slice : mCurrentSlicedBucket) {
-            mCurrentFullBucket[slice.first] += slice.second.sum;
+            // TODO: fix this when anomaly can accept double values
+            mCurrentFullBucket[slice.first] += slice.second.value.long_value;
         }
     }
 
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 943d6dc..b2f0b6f 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -23,6 +23,7 @@
 #include "../condition/ConditionTracker.h"
 #include "../external/PullDataReceiver.h"
 #include "../external/StatsPullerManager.h"
+#include "../stats_log_util.h"
 #include "MetricProducer.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 
@@ -33,7 +34,8 @@
 struct ValueBucket {
     int64_t mBucketStartNs;
     int64_t mBucketEndNs;
-    int64_t mValue;
+    int64_t mValueLong;
+    double mValueDouble;
 };
 
 class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
@@ -45,6 +47,7 @@
 
     virtual ~ValueMetricProducer();
 
+    // Process data pulled on bucket boundary.
     void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data) override;
 
     // ValueMetric needs special logic if it's a pulled atom.
@@ -52,7 +55,7 @@
                           const int64_t version) override {
         std::lock_guard<std::mutex> lock(mMutex);
 
-        if (mPullTagId != -1 && (mCondition == true || mConditionTrackerIndex < 0) ) {
+        if (mIsPulled && (mCondition == true || mConditionTrackerIndex < 0)) {
             vector<shared_ptr<LogEvent>> allData;
             mPullerManager->Pull(mPullTagId, eventTimeNs, &allData);
             if (allData.size() == 0) {
@@ -120,20 +123,22 @@
     // tagId for pulled data. -1 if this is not pulled
     const int mPullTagId;
 
+    // if this is pulled metric
+    const bool mIsPulled;
+
     int mField;
 
     // internal state of a bucket.
     typedef struct {
         // Pulled data always come in pair of <start, end>. This holds the value
-        // for start. The diff (end - start) is added to sum.
-        int64_t start;
+        // for start. The diff (end - start) is taken as the real value.
+        Value start;
         // Whether the start data point is updated
         bool startUpdated;
-        // If end data point comes before the start, record this pair as tainted
-        // and the value is not added to the running sum.
-        int tainted;
-        // Running sum of known pairs in this bucket
-        int64_t sum;
+        // Current value, depending on the aggregation type.
+        Value value;
+        // Number of samples collected.
+        int sampleSize;
         // If this dimension has any non-tainted value. If not, don't report the
         // dimension.
         bool hasValue;
@@ -154,6 +159,8 @@
     // Util function to check whether the specified dimension hits the guardrail.
     bool hitGuardRailLocked(const MetricDimensionKey& newKey);
 
+    void pullLocked(const int64_t timestampNs);
+
     static const size_t kBucketSize = sizeof(ValueBucket{});
 
     const size_t mDimensionSoftLimit;
@@ -162,7 +169,11 @@
 
     const bool mUseAbsoluteValueOnReset;
 
-    FRIEND_TEST(ValueMetricProducerTest, TestNonDimensionalEvents);
+    const ValueMetric::AggregationType mAggregationType;
+
+    const Type mValueType;
+
+    FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsNoCondition);
     FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset);
     FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset);
     FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
@@ -176,6 +187,12 @@
     FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition);
     FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2);
     FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition3);
+    FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMin);
+    FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMax);
+    FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateAvg);
+    FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateSum);
+    FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateSumSliced);
+    FRIEND_TEST(ValueMetricProducerTest, TestFirstBucket);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index e03edb3..75d6df9 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -82,6 +82,28 @@
     return true;
 }
 
+bool handlePullMetricTriggerWithLogTrackers(
+        const int64_t trigger, const int metricIndex,
+        const vector<sp<LogMatchingTracker>>& allAtomMatchers,
+        const unordered_map<int64_t, int>& logTrackerMap,
+        unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
+    auto logTrackerIt = logTrackerMap.find(trigger);
+    if (logTrackerIt == logTrackerMap.end()) {
+        ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)trigger);
+        return false;
+    }
+    if (allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) {
+        ALOGE("AtomMatcher \"%lld\" has more than one tag ids."
+              "Trigger can only be one atom type.",
+              (long long)trigger);
+        return false;
+    }
+    logTrackerIndex = logTrackerIt->second;
+    auto& metric_list = trackerToMetricMap[logTrackerIndex];
+    metric_list.push_back(metricIndex);
+    return true;
+}
+
 bool handleMetricWithConditions(
         const int64_t condition, const int metricIndex,
         const unordered_map<int64_t, int>& conditionTrackerMap,
@@ -312,7 +334,7 @@
         }
 
         sp<MetricProducer> countProducer =
-                new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
+                new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs, currentTimeNs);
         allMetricProducers.push_back(countProducer);
     }
 
@@ -382,7 +404,7 @@
 
         sp<MetricProducer> durationMetric = new DurationMetricProducer(
                 key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
-                trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs);
+                trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs, currentTimeNs);
 
         allMetricProducers.push_back(durationMetric);
     }
@@ -502,13 +524,29 @@
         }
 
         sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
-        // If it is pulled atom, it should be simple matcher with one tagId.
+        // For GaugeMetric atom, it should be simple matcher with one tagId.
         if (atomMatcher->getAtomIds().size() != 1) {
             return false;
         }
         int atomTagId = *(atomMatcher->getAtomIds().begin());
         int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
 
+        int triggerTrackerIndex;
+        int triggerAtomId = -1;
+        if (pullTagId != -1 && metric.has_trigger_event()) {
+            // event_trigger should be used with ALL_CONDITION_CHANGES
+            if (metric.sampling_type() != GaugeMetric::ALL_CONDITION_CHANGES) {
+                return false;
+            }
+            if (!handlePullMetricTriggerWithLogTrackers(metric.trigger_event(), metricIndex,
+                                                        allAtomMatchers, logTrackerMap,
+                                                        trackerToMetricMap, triggerTrackerIndex)) {
+                return false;
+            }
+            sp<LogMatchingTracker> triggerAtomMatcher = allAtomMatchers.at(triggerTrackerIndex);
+            triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin());
+        }
+
         int conditionIndex = -1;
         if (metric.has_condition()) {
             bool good = handleMetricWithConditions(
@@ -524,9 +562,9 @@
             }
         }
 
-        sp<MetricProducer> gaugeProducer =
-                new GaugeMetricProducer(key, metric, conditionIndex, wizard, pullTagId,
-                                        timeBaseTimeNs, currentTimeNs, pullerManager);
+        sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
+                key, metric, conditionIndex, wizard, pullTagId, triggerAtomId, atomTagId,
+                timeBaseTimeNs, currentTimeNs, pullerManager);
         allMetricProducers.push_back(gaugeProducer);
     }
     for (int i = 0; i < config.no_report_metric_size(); ++i) {
diff --git a/cmds/statsd/src/perfetto/perfetto_config.proto b/cmds/statsd/src/perfetto/perfetto_config.proto
deleted file mode 100644
index 56d12f8..0000000
--- a/cmds/statsd/src/perfetto/perfetto_config.proto
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-syntax = "proto2";
-
-package perfetto.protos;
-
-message DataSourceConfig {
-  message FtraceConfig {
-    repeated string event_names = 1;
-  }
-
-  optional string name = 1;
-
-  optional uint32 target_buffer = 2;
-
-  optional FtraceConfig ftrace_config = 100;
-}
-
-message TraceConfig {
-  message BufferConfig {
-    optional uint32 size_kb = 1;
-
-    enum OptimizeFor {
-      DEFAULT = 0;
-      ONE_SHOT_READ = 1;
-
-    }
-    optional OptimizeFor optimize_for = 3;
-
-    enum FillPolicy {
-      UNSPECIFIED = 0;
-      RING_BUFFER = 1;
-    }
-    optional FillPolicy fill_policy = 4;
-  }
-  repeated BufferConfig buffers = 1;
-
-  message DataSource {
-    optional protos.DataSourceConfig config = 1;
-
-    repeated string producer_name_filter = 2;
-  }
-  repeated DataSource data_sources = 2;
-
-  optional uint32 duration_ms = 3;
-}
diff --git a/cmds/statsd/src/perfprofd/perfprofd_config.proto b/cmds/statsd/src/perfprofd/perfprofd_config.proto
deleted file mode 120000
index c8be247..0000000
--- a/cmds/statsd/src/perfprofd/perfprofd_config.proto
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../system/extras/perfprofd/perfprofd_config.proto
\ No newline at end of file
diff --git a/cmds/statsd/src/socket/StatsSocketListener.cpp b/cmds/statsd/src/socket/StatsSocketListener.cpp
index 0392d67..9b0691b 100755
--- a/cmds/statsd/src/socket/StatsSocketListener.cpp
+++ b/cmds/statsd/src/socket/StatsSocketListener.cpp
@@ -40,6 +40,7 @@
 namespace statsd {
 
 static const int kLogMsgHeaderSize = 28;
+static const int kLibLogTag = 1006;
 
 StatsSocketListener::StatsSocketListener(const sp<LogListener>& listener)
     : SocketListener(getLogSocket(), false /*start listen*/), mListener(listener) {
@@ -99,6 +100,23 @@
     char* ptr = ((char*)buffer) + sizeof(android_log_header_t);
     n -= sizeof(android_log_header_t);
 
+    // When a log failed to write to statsd socket (e.g., due ot EBUSY), a special message would
+    // be sent to statsd when the socket communication becomes available again.
+    // The format is android_log_event_int_t with a single integer in the payload indicating the
+    // number of logs that failed. (*FORMAT MUST BE IN SYNC WITH system/core/libstats*)
+    // Note that all normal stats logs are in the format of event_list, so there won't be confusion.
+    //
+    // TODO(b/80538532): In addition to log it in StatsdStats, we should properly reset the config.
+    if (n == sizeof(android_log_event_int_t)) {
+        android_log_event_int_t* int_event = reinterpret_cast<android_log_event_int_t*>(ptr);
+        if (int_event->header.tag == kLibLogTag && int_event->payload.type == EVENT_TYPE_INT) {
+            ALOGE("Found dropped events: %d", int_event->payload.data);
+            StatsdStats::getInstance().noteLogLost((int32_t)getWallClockSec(),
+                                                   int_event->payload.data);
+            return true;
+        }
+    }
+
     log_msg msg;
 
     msg.entry.len = n;
@@ -111,7 +129,7 @@
     LogEvent event(msg);
 
     // Call the listener
-    mListener->OnLogEvent(&event, false /*reconnected, N/A in statsd socket*/);
+    mListener->OnLogEvent(&event);
 
     return true;
 }
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 2fe17da..db7e680 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -106,7 +106,13 @@
 
   optional int64 end_bucket_elapsed_nanos = 2;
 
-  optional int64 value = 3;
+  optional int64 value = 3 [deprecated = true];
+
+  oneof values {
+      int64 value_long = 7;
+
+      double value_double = 8;
+  }
 
   optional int64 bucket_num = 4;
 
diff --git a/cmds/statsd/src/stats_util.h b/cmds/statsd/src/stats_util.h
index 5fcb161..cfc411f 100644
--- a/cmds/statsd/src/stats_util.h
+++ b/cmds/statsd/src/stats_util.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #include "HashableDimensionKey.h"
-#include "logd/LogReader.h"
 
 #include <unordered_map>
 
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 638fbb9..d19e247 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -21,9 +21,6 @@
 option java_package = "com.android.internal.os";
 option java_outer_classname = "StatsdConfigProto";
 
-import "frameworks/base/cmds/statsd/src/perfetto/perfetto_config.proto";
-import "frameworks/base/cmds/statsd/src/perfprofd/perfprofd_config.proto";
-
 enum Position {
   POSITION_UNKNOWN = 0;
 
@@ -220,6 +217,8 @@
 
   optional int64 what = 2;
 
+  optional int64 trigger_event = 12;
+
   optional FieldFilter gauge_fields_filter = 3;
 
   optional int64 condition = 4;
@@ -262,6 +261,9 @@
 
   enum AggregationType {
     SUM = 1;
+    MIN = 2;
+    MAX = 3;
+    AVG = 4;
   }
   optional AggregationType aggregation_type = 8 [default = SUM];
 
@@ -301,11 +303,21 @@
 }
 
 message PerfettoDetails {
-  optional perfetto.protos.TraceConfig trace_config = 1;
+  // The |trace_config| field is a proto-encoded message of type
+  // perfetto.protos.TraceConfig defined in
+  // //external/perfetto/protos/perfetto/config/. On device,
+  // statsd doesn't need to deserialize the message as it's just
+  // passed binary-encoded to the perfetto cmdline client.
+  optional bytes trace_config = 1;
 }
 
 message PerfprofdDetails {
-  optional android.perfprofd.ProfilingConfig perfprofd_config = 1;
+  // The |perfprofd_config| field is a proto-encoded message of type
+  // android.perfprofd.ProfilingConfig defined in
+  // //system/extras/perfprofd/. On device, statsd doesn't need to
+  // deserialize the message as it's just passed binary-encoded to
+  // the perfprofd service.
+  optional bytes perfprofd_config = 1;
 }
 
 message BroadcastSubscriberDetails {
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 2fcde29..acfa151 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -158,6 +158,96 @@
     EXPECT_EQ((float)1.1, item7.mValue.float_value);
 }
 
+TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
+    std::map<int32_t, int64_t> int_map;
+    std::map<int32_t, std::string> string_map;
+    std::map<int32_t, float> float_map;
+
+    int_map[11] = 123L;
+    int_map[22] = 345L;
+
+    string_map[1] = "test2";
+    string_map[2] = "test1";
+
+    float_map[111] = 2.2f;
+    float_map[222] = 1.1f;
+
+    LogEvent event1(83, 2000, 2001, 10001, int_map, string_map, float_map);
+    event1.init();
+
+    EXPECT_EQ(83, event1.GetTagId());
+    EXPECT_EQ((int64_t)2000, event1.GetLogdTimestampNs());
+    EXPECT_EQ((int64_t)2001, event1.GetElapsedTimestampNs());
+
+    const auto& items = event1.getValues();
+    EXPECT_EQ((size_t)13, items.size());
+
+    const FieldValue& item0 = event1.getValues()[0];
+    EXPECT_EQ(0x00010000, item0.mField.getField());
+    EXPECT_EQ(Type::INT, item0.mValue.getType());
+    EXPECT_EQ(10001, item0.mValue.int_value);
+
+    const FieldValue& item1 = event1.getValues()[1];
+    EXPECT_EQ(0x2020101, item1.mField.getField());
+    EXPECT_EQ(Type::INT, item1.mValue.getType());
+    EXPECT_EQ(11, item1.mValue.int_value);
+
+    const FieldValue& item2 = event1.getValues()[2];
+    EXPECT_EQ(0x2020182, item2.mField.getField());
+    EXPECT_EQ(Type::LONG, item2.mValue.getType());
+    EXPECT_EQ(123L, item2.mValue.long_value);
+
+    const FieldValue& item3 = event1.getValues()[3];
+    EXPECT_EQ(0x2020201, item3.mField.getField());
+    EXPECT_EQ(Type::INT, item3.mValue.getType());
+    EXPECT_EQ(22, item3.mValue.int_value);
+
+    const FieldValue& item4 = event1.getValues()[4];
+    EXPECT_EQ(0x2020282, item4.mField.getField());
+    EXPECT_EQ(Type::LONG, item4.mValue.getType());
+    EXPECT_EQ(345L, item4.mValue.long_value);
+
+    const FieldValue& item5 = event1.getValues()[5];
+    EXPECT_EQ(0x2020301, item5.mField.getField());
+    EXPECT_EQ(Type::INT, item5.mValue.getType());
+    EXPECT_EQ(1, item5.mValue.int_value);
+
+    const FieldValue& item6 = event1.getValues()[6];
+    EXPECT_EQ(0x2020383, item6.mField.getField());
+    EXPECT_EQ(Type::STRING, item6.mValue.getType());
+    EXPECT_EQ("test2", item6.mValue.str_value);
+
+    const FieldValue& item7 = event1.getValues()[7];
+    EXPECT_EQ(0x2020401, item7.mField.getField());
+    EXPECT_EQ(Type::INT, item7.mValue.getType());
+    EXPECT_EQ(2, item7.mValue.int_value);
+
+    const FieldValue& item8 = event1.getValues()[8];
+    EXPECT_EQ(0x2020483, item8.mField.getField());
+    EXPECT_EQ(Type::STRING, item8.mValue.getType());
+    EXPECT_EQ("test1", item8.mValue.str_value);
+
+    const FieldValue& item9 = event1.getValues()[9];
+    EXPECT_EQ(0x2020501, item9.mField.getField());
+    EXPECT_EQ(Type::INT, item9.mValue.getType());
+    EXPECT_EQ(111, item9.mValue.int_value);
+
+    const FieldValue& item10 = event1.getValues()[10];
+    EXPECT_EQ(0x2020584, item10.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item10.mValue.getType());
+    EXPECT_EQ(2.2f, item10.mValue.float_value);
+
+    const FieldValue& item11 = event1.getValues()[11];
+    EXPECT_EQ(0x2028601, item11.mField.getField());
+    EXPECT_EQ(Type::INT, item11.mValue.getType());
+    EXPECT_EQ(222, item11.mValue.int_value);
+
+    const FieldValue& item12 = event1.getValues()[12];
+    EXPECT_EQ(0x2028684, item12.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item12.mValue.getType());
+    EXPECT_EQ(1.1f, item12.mValue.float_value);
+}
+
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index ecc57f5..b6f635c 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -238,132 +238,6 @@
     EXPECT_EQ(2, report.annotation(0).field_int32());
 }
 
-TEST(StatsLogProcessorTest, TestOutOfOrderLogs) {
-    // Setup simple config key corresponding to empty config.
-    sp<UidMap> m = new UidMap();
-    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    sp<AlarmMonitor> anomalyAlarmMonitor;
-    sp<AlarmMonitor> subscriberAlarmMonitor;
-    int broadcastCount = 0;
-    StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
-                        [&broadcastCount](const ConfigKey& key) {
-                            broadcastCount++;
-                            return true;
-                        });
-
-    LogEvent event1(0, 1 /*logd timestamp*/, 1001 /*elapsedRealtime*/);
-    event1.init();
-
-    LogEvent event2(0, 2, 1002);
-    event2.init();
-
-    LogEvent event3(0, 3, 1005);
-    event3.init();
-
-    LogEvent event4(0, 4, 1004);
-    event4.init();
-
-    // <----- Reconnection happens
-
-    LogEvent event5(0, 5, 999);
-    event5.init();
-
-    LogEvent event6(0, 6, 2000);
-    event6.init();
-
-    // <----- Reconnection happens
-
-    LogEvent event7(0, 7, 3000);
-    event7.init();
-
-    // first event ever
-    p.OnLogEvent(&event1, true);
-    EXPECT_EQ(1UL, p.mLogCount);
-    EXPECT_EQ(1001LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(1001LL, p.mLastTimestampSeen);
-
-    p.OnLogEvent(&event2, false);
-    EXPECT_EQ(2UL, p.mLogCount);
-    EXPECT_EQ(1002LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(1002LL, p.mLastTimestampSeen);
-
-    p.OnLogEvent(&event3, false);
-    EXPECT_EQ(3UL, p.mLogCount);
-    EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(1005LL, p.mLastTimestampSeen);
-
-    p.OnLogEvent(&event4, false);
-    EXPECT_EQ(4UL, p.mLogCount);
-    EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(1004LL, p.mLastTimestampSeen);
-    EXPECT_FALSE(p.mInReconnection);
-
-    // Reconnect happens, event1 out of buffer. Read event2
-    p.OnLogEvent(&event2, true);
-    EXPECT_EQ(4UL, p.mLogCount);
-    EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(1004LL, p.mLastTimestampSeen);
-    EXPECT_TRUE(p.mInReconnection);
-
-    p.OnLogEvent(&event3, false);
-    EXPECT_EQ(4UL, p.mLogCount);
-    EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(1004LL, p.mLastTimestampSeen);
-    EXPECT_TRUE(p.mInReconnection);
-
-    p.OnLogEvent(&event4, false);
-    EXPECT_EQ(4UL, p.mLogCount);
-    EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(1004LL, p.mLastTimestampSeen);
-    EXPECT_FALSE(p.mInReconnection);
-
-    // Fresh event comes.
-    p.OnLogEvent(&event5, false);
-    EXPECT_EQ(5UL, p.mLogCount);
-    EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(999LL, p.mLastTimestampSeen);
-
-    p.OnLogEvent(&event6, false);
-    EXPECT_EQ(6UL, p.mLogCount);
-    EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(2000LL, p.mLastTimestampSeen);
-
-    // Reconnect happens, read from event4
-    p.OnLogEvent(&event4, true);
-    EXPECT_EQ(6UL, p.mLogCount);
-    EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(2000LL, p.mLastTimestampSeen);
-    EXPECT_TRUE(p.mInReconnection);
-
-    p.OnLogEvent(&event5, false);
-    EXPECT_EQ(6UL, p.mLogCount);
-    EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(2000LL, p.mLastTimestampSeen);
-    EXPECT_TRUE(p.mInReconnection);
-
-    // Before we get out of reconnection state, it reconnects again.
-    p.OnLogEvent(&event5, true);
-    EXPECT_EQ(6UL, p.mLogCount);
-    EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(2000LL, p.mLastTimestampSeen);
-    EXPECT_TRUE(p.mInReconnection);
-
-    p.OnLogEvent(&event6, false);
-    EXPECT_EQ(6UL, p.mLogCount);
-    EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(2000LL, p.mLastTimestampSeen);
-    EXPECT_FALSE(p.mInReconnection);
-    EXPECT_EQ(0, p.mLogLossCount);
-
-    // it reconnects again. All old events are gone. We lose CP.
-    p.OnLogEvent(&event7, true);
-    EXPECT_EQ(7UL, p.mLogCount);
-    EXPECT_EQ(3000LL, p.mLargestTimestampSeen);
-    EXPECT_EQ(3000LL, p.mLastTimestampSeen);
-    EXPECT_EQ(1, p.mLogLossCount);
-    EXPECT_FALSE(p.mInReconnection);
-}
-
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp b/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp
index 23d6926..6529d65 100644
--- a/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/CombinationConditionTracker_test.cpp
@@ -40,6 +40,7 @@
     EXPECT_EQ(evaluateCombinationCondition(children, operation, conditionResults),
               ConditionState::kUnknown);
 }
+
 TEST(ConditionTrackerTest, TestAndCondition) {
     // Set up the matcher
     LogicalOperation operation = LogicalOperation::AND;
@@ -103,6 +104,11 @@
     conditionResults.clear();
     conditionResults.push_back(ConditionState::kFalse);
     EXPECT_TRUE(evaluateCombinationCondition(children, operation, conditionResults));
+
+    children.clear();
+    conditionResults.clear();
+    EXPECT_EQ(evaluateCombinationCondition(children, operation, conditionResults),
+              ConditionState::kUnknown);
 }
 
 TEST(ConditionTrackerTest, TestNandCondition) {
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index 744828e..f2e8f58 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -141,23 +141,23 @@
 
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(0).has_value());
+    EXPECT_TRUE(data.bucket_info(0).has_value_long());
 
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(1).has_value());
+    EXPECT_TRUE(data.bucket_info(1).has_value_long());
 
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(2).has_value());
+    EXPECT_TRUE(data.bucket_info(2).has_value_long());
 
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(3).has_value());
+    EXPECT_TRUE(data.bucket_info(3).has_value_long());
 
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(4).has_value());
+    EXPECT_TRUE(data.bucket_info(4).has_value_long());
 }
 
 TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
@@ -248,15 +248,15 @@
 
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(0).has_value());
+    EXPECT_TRUE(data.bucket_info(0).has_value_long());
 
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(1).has_value());
+    EXPECT_TRUE(data.bucket_info(1).has_value_long());
 
     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(2).has_value());
+    EXPECT_TRUE(data.bucket_info(2).has_value_long());
 }
 
 #else
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 9a8919e..67c704e 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -37,6 +37,19 @@
 
 const ConfigKey kConfigKey(0, 12345);
 
+TEST(CountMetricProducerTest, TestFirstBucket) {
+    CountMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_MINUTE);
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+
+    CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      5, 600 * NS_PER_SEC + NS_PER_SEC/2);
+    EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(10, countProducer.mCurrentBucketNum);
+    EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
+}
+
 TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
     int64_t bucketStartTimeNs = 10000000000;
     int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -56,8 +69,7 @@
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      bucketStartTimeNs);
-    countProducer.setBucketSize(60 * NS_PER_SEC);
+                                      bucketStartTimeNs, bucketStartTimeNs);
 
     // 2 events in bucket 1.
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
@@ -119,8 +131,7 @@
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
-    CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
-    countProducer.setBucketSize(60 * NS_PER_SEC);
+    CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs, bucketStartTimeNs);
 
     countProducer.onConditionChanged(true, bucketStartTimeNs);
     countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
@@ -181,8 +192,7 @@
     EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue));
 
     CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
-                                      bucketStartTimeNs);
-    countProducer.setBucketSize(60 * NS_PER_SEC);
+                                      bucketStartTimeNs, bucketStartTimeNs);
 
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
@@ -221,8 +231,7 @@
     event1.init();
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
-                                      bucketStartTimeNs);
-    countProducer.setBucketSize(60 * NS_PER_SEC);
+                                      bucketStartTimeNs, bucketStartTimeNs);
 
     sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
     EXPECT_TRUE(anomalyTracker != nullptr);
@@ -280,8 +289,7 @@
     event1.init();
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
-                                      bucketStartTimeNs);
-    countProducer.setBucketSize(60 * NS_PER_SEC);
+                                      bucketStartTimeNs, bucketStartTimeNs);
 
     // Bucket is flushed yet.
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
@@ -337,8 +345,7 @@
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      bucketStartTimeNs);
-    countProducer.setBucketSize(60 * NS_PER_SEC);
+                                      bucketStartTimeNs, bucketStartTimeNs);
 
     sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
 
diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
index 7ef8c5b..b540964 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -39,6 +39,23 @@
 
 const ConfigKey kConfigKey(0, 12345);
 
+TEST(DurationMetricTrackerTest, TestFirstBucket) {
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    DurationMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_MINUTE);
+    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+
+    FieldMatcher dimensions;
+    DurationMetricProducer durationProducer(
+            kConfigKey, metric, -1 /*no condition*/, 1 /* start index */, 2 /* stop index */,
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, 5, 600 * NS_PER_SEC + NS_PER_SEC/2);
+
+    EXPECT_EQ(600500000000, durationProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(10, durationProducer.mCurrentBucketNum);
+    EXPECT_EQ(660000000005, durationProducer.getCurrentBucketEndTimeNs());
+}
+
 TEST(DurationMetricTrackerTest, TestNoCondition) {
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     int64_t bucketStartTimeNs = 10000000000;
@@ -58,8 +75,7 @@
     FieldMatcher dimensions;
     DurationMetricProducer durationProducer(
             kConfigKey, metric, -1 /*no condition*/, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
-    durationProducer.setBucketSize(60 * NS_PER_SEC);
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
 
     durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
@@ -100,8 +116,7 @@
     FieldMatcher dimensions;
     DurationMetricProducer durationProducer(
             kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
-    durationProducer.setBucketSize(60 * NS_PER_SEC);
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
 
     EXPECT_FALSE(durationProducer.mCondition);
     EXPECT_FALSE(durationProducer.isConditionSliced());
@@ -151,8 +166,7 @@
     FieldMatcher dimensions;
     DurationMetricProducer durationProducer(
             kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
-    durationProducer.setBucketSize(60 * NS_PER_SEC);
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
 
     LogEvent start_event(tagId, startTimeNs);
     start_event.init();
@@ -206,8 +220,7 @@
     FieldMatcher dimensions;
     DurationMetricProducer durationProducer(
             kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
-    durationProducer.setBucketSize(60 * NS_PER_SEC);
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
 
     LogEvent start_event(tagId, startTimeNs);
     start_event.init();
@@ -261,8 +274,7 @@
     FieldMatcher dimensions;
     DurationMetricProducer durationProducer(
             kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
-    durationProducer.setBucketSize(60 * NS_PER_SEC);
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
 
     sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
     EXPECT_TRUE(anomalyTracker != nullptr);
@@ -300,8 +312,7 @@
     FieldMatcher dimensions;
     DurationMetricProducer durationProducer(
             kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
-    durationProducer.setBucketSize(60 * NS_PER_SEC);
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
 
     LogEvent start_event(tagId, startTimeNs);
     start_event.init();
@@ -348,8 +359,7 @@
     FieldMatcher dimensions;
     DurationMetricProducer durationProducer(
             kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs);
-    durationProducer.setBucketSize(60 * NS_PER_SEC);
+            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
 
     LogEvent start_event(tagId, startTimeNs);
     start_event.init();
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 19c9f77..9471faa 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -47,7 +47,34 @@
 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
 const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
 
-TEST(GaugeMetricProducerTest, TestNoCondition) {
+/*
+ * Tests that the first bucket works correctly
+ */
+TEST(GaugeMetricProducerTest, TestFirstBucket) {
+    GaugeMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_gauge_fields_filter()->set_include_all(false);
+    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+    gaugeFieldMatcher->set_field(tagId);
+    gaugeFieldMatcher->add_child()->set_field(1);
+    gaugeFieldMatcher->add_child()->set_field(3);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    // statsd started long ago.
+    // The metric starts in the middle of the bucket
+    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      -1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
+                                      pullerManager);
+
+    EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(10, gaugeProducer.mCurrentBucketNum);
+    EXPECT_EQ(660000000005, gaugeProducer.getCurrentBucketEndTimeNs());
+}
+
+TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
     GaugeMetric metric;
     metric.set_id(metricId);
     metric.set_bucket(ONE_MINUTE);
@@ -62,10 +89,20 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Invoke([](int tagId, int64_t timeNs,
+                                vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
 
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
+                                      tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -83,7 +120,9 @@
     EXPECT_EQ(10, it->mValue.int_value);
     it++;
     EXPECT_EQ(11, it->mValue.int_value);
-    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
+    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+    EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms
+        .front().mFields->begin()->mValue.int_value);
 
     allData.clear();
     std::shared_ptr<LogEvent> event2 = std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
@@ -102,7 +141,7 @@
     EXPECT_EQ(25, it->mValue.int_value);
     // One dimension.
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
     EXPECT_EQ(INT, it->mValue.getType());
     EXPECT_EQ(10L, it->mValue.int_value);
@@ -114,7 +153,7 @@
     EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
     // One dimension.
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size());
     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
     EXPECT_EQ(INT, it->mValue.getType());
     EXPECT_EQ(24L, it->mValue.int_value);
@@ -138,10 +177,9 @@
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      -1 /* -1 means no pulling */, bucketStartTimeNs,
+                                      -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
 
-    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
     sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
     EXPECT_TRUE(anomalyTracker != nullptr);
 
@@ -210,6 +248,7 @@
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Return(false))
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
@@ -222,8 +261,8 @@
             }));
 
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
+                                      tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
@@ -263,7 +302,7 @@
                          ->mValue.int_value);
 }
 
-TEST(GaugeMetricProducerTest, TestWithCondition) {
+TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
     GaugeMetric metric;
     metric.set_id(metricId);
     metric.set_bucket(ONE_MINUTE);
@@ -289,9 +328,8 @@
                 return true;
             }));
 
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
-    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
+    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, -1, tagId,
+                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -333,7 +371,7 @@
                             ->mValue.int_value);
 }
 
-TEST(GaugeMetricProducerTest, TestWithSlicedCondition) {
+TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
     const int conditionTag = 65;
     GaugeMetric metric;
     metric.set_id(1111111);
@@ -380,9 +418,8 @@
                 return true;
             }));
 
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
-    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
+    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, -1, tagId,
+                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
 
@@ -409,13 +446,14 @@
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
 }
 
-TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
+TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
     sp<AlarmMonitor> alarmMonitor;
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
 
     GaugeMetric metric;
     metric.set_id(metricId);
@@ -424,8 +462,8 @@
     gaugeFieldMatcher->set_field(tagId);
     gaugeFieldMatcher->add_child()->set_field(2);
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    gaugeProducer.setBucketSize(60 * NS_PER_SEC);
+                                      tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     Alert alert;
     alert.set_id(101);
@@ -490,6 +528,83 @@
     EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
 }
 
+TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
+    GaugeMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.set_sampling_type(GaugeMetric::ALL_CONDITION_CHANGES);
+    metric.mutable_gauge_fields_filter()->set_include_all(false);
+    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+    gaugeFieldMatcher->set_field(tagId);
+    gaugeFieldMatcher->add_child()->set_field(1);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Invoke([](int tagId, int64_t timeNs,
+                                vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3);
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, int64_t timeNs,
+                                vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                event->write(4);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, int64_t timeNs,
+                                vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+                event->write(5);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    int triggerId = 5;
+    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
+
+    vector<shared_ptr<LogEvent>> allData;
+    allData.clear();
+
+    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    LogEvent trigger(triggerId, bucketStartTimeNs + 10);
+    trigger.init();
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+    EXPECT_EQ(3UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+
+    allData.clear();
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+    event->write(10);
+    event->init();
+    allData.push_back(event);
+
+    gaugeProducer.onDataPulled(allData);
+    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
+    EXPECT_EQ(INT, it->mValue.getType());
+    EXPECT_EQ(10, it->mValue.int_value);
+    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
+    EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
+    EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value);
+    EXPECT_EQ(5, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms[2].mFields->begin()->mValue.int_value);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 5195f01..57aab97 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -50,9 +50,32 @@
 const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
 
 /*
+ * Tests that the first bucket works correctly
+ */
+TEST(ValueMetricProducerTest, TestFirstBucket) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    // statsd started long ago.
+    // The metric starts in the middle of the bucket
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      -1, 5, 600 * NS_PER_SEC + NS_PER_SEC/2, pullerManager);
+
+    EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
+    EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
+}
+
+/*
  * Tests pulled atoms with no conditions
  */
-TEST(ValueMetricProducerTest, TestNonDimensionalEvents) {
+TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
     ValueMetric metric;
     metric.set_id(metricId);
     metric.set_bucket(ONE_MINUTE);
@@ -63,10 +86,20 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Invoke([](int tagId, int64_t timeNs,
+                                vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                event->write(tagId);
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -80,14 +113,13 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
-    // startUpdated:true tainted:0 sum:0 start:11
+    // startUpdated:true sum:0 start:11
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
-    EXPECT_EQ(11, curInterval.start);
-    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+    EXPECT_EQ(false, curInterval.hasValue);
+    EXPECT_EQ(11, curInterval.start.long_value);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+    EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 
     allData.clear();
     event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -99,13 +131,12 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // tartUpdated:false tainted:0 sum:12
+    // tartUpdated:false sum:12
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 
     allData.clear();
     event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -116,13 +147,12 @@
     valueProducer.onDataPulled(allData);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false tainted:0 sum:12
+    // startUpdated:false sum:12
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 }
 
 /*
@@ -140,10 +170,10 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -157,12 +187,10 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
-    EXPECT_EQ(11, curInterval.start);
+    EXPECT_EQ(false, curInterval.hasValue);
+    EXPECT_EQ(11, curInterval.start.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     allData.clear();
@@ -176,11 +204,10 @@
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 
     allData.clear();
     event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -192,11 +219,10 @@
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 }
 
 /*
@@ -213,10 +239,10 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -230,12 +256,10 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
-    EXPECT_EQ(11, curInterval.start);
+    EXPECT_EQ(false, curInterval.hasValue);
+    EXPECT_EQ(11, curInterval.start.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     allData.clear();
@@ -249,8 +273,7 @@
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     allData.clear();
@@ -263,11 +286,10 @@
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 }
 
 /*
@@ -287,6 +309,17 @@
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
 
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            // should not take effect
+            .WillOnce(Invoke([](int tagId, int64_t timeNs,
+                                vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                event->write(tagId);
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
@@ -310,17 +343,15 @@
 
     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false tainted:0 sum:0 start:100
-    EXPECT_EQ(100, curInterval.start);
+    // startUpdated:false sum:0 start:100
+    EXPECT_EQ(100, curInterval.start.long_value);
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     vector<shared_ptr<LogEvent>> allData;
@@ -335,19 +366,19 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false tainted:0 sum:0 start:110
-    EXPECT_EQ(110, curInterval.start);
+    // startUpdated:false sum:0 start:110
+    EXPECT_EQ(110, curInterval.start.long_value);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 
     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false tainted:0 sum:0 start:110
-    EXPECT_EQ(10, curInterval.sum);
+    // startUpdated:false sum:0 start:110
+    EXPECT_EQ(10, curInterval.value.long_value);
     EXPECT_EQ(false, curInterval.startUpdated);
 }
 
@@ -362,7 +393,6 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -405,6 +435,7 @@
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Return(false))
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
@@ -417,7 +448,6 @@
             }));
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -433,7 +463,7 @@
     valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
+    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValueLong);
 
     allData.clear();
     event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
@@ -444,7 +474,7 @@
     valueProducer.onDataPulled(allData);
     EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValue);
+    EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValueLong);
 }
 
 TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
@@ -460,6 +490,7 @@
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Return(false))
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
@@ -482,7 +513,6 @@
             }));
     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
 
     valueProducer.onConditionChanged(false, bucket2StartTimeNs-100);
@@ -493,7 +523,7 @@
     EXPECT_EQ(bucket2StartTimeNs-50, valueProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucketStartTimeNs, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
-    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
+    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValueLong);
     EXPECT_FALSE(valueProducer.mCondition);
 }
 
@@ -509,7 +539,6 @@
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -523,19 +552,20 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(10, curInterval.sum);
+    EXPECT_EQ(10, curInterval.value.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
 
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(30, curInterval.sum);
+    EXPECT_EQ(30, curInterval.value.long_value);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 }
 
 TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
@@ -550,7 +580,6 @@
 
     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, -1, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -572,7 +601,7 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(20, curInterval.sum);
+    EXPECT_EQ(20, curInterval.value.long_value);
 
     shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
     event3->write(1);
@@ -583,7 +612,7 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(50, curInterval.sum);
+    EXPECT_EQ(50, curInterval.value.long_value);
 
     valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
     shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
@@ -595,12 +624,12 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(50, curInterval.sum);
+    EXPECT_EQ(50, curInterval.value.long_value);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 }
 
 TEST(ValueMetricProducerTest, TestAnomalyDetection) {
@@ -624,7 +653,6 @@
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
 
@@ -699,10 +727,10 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
 
     vector<shared_ptr<LogEvent>> allData;
     // pull 1
@@ -718,11 +746,10 @@
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
 
-    // startUpdated:true tainted:0 sum:0 start:11
+    // startUpdated:true sum:0 start:11
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
-    EXPECT_EQ(11, curInterval.start);
+    EXPECT_EQ(false, curInterval.hasValue);
+    EXPECT_EQ(11, curInterval.start.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // pull 2 at correct time
@@ -736,13 +763,12 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // tartUpdated:false tainted:0 sum:12
+    // tartUpdated:false sum:12
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 
     // pull 3 come late.
     // The previous bucket gets closed with error. (Has start value 23, no ending)
@@ -757,14 +783,13 @@
     valueProducer.onDataPulled(allData);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false tainted:0 sum:12
+    // startUpdated:false sum:12
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(36, curInterval.start);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(36, curInterval.start.long_value);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
+    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
 }
 
 /*
@@ -785,6 +810,7 @@
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
 
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Return(false))
             // condition becomes true
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
@@ -810,25 +836,22 @@
 
     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false tainted:0 sum:0 start:100
-    EXPECT_EQ(100, curInterval.start);
+    // startUpdated:false sum:0 start:100
+    EXPECT_EQ(100, curInterval.start.long_value);
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // pull on bucket boundary come late, condition change happens before it
     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(1, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // Now the alarm is delivered.
@@ -844,8 +867,7 @@
 
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(1, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 }
 
@@ -867,6 +889,7 @@
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
 
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Return(false))
             // condition becomes true
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
@@ -903,34 +926,30 @@
 
     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false tainted:0 sum:0 start:100
-    EXPECT_EQ(100, curInterval.start);
+    // startUpdated:false sum:0 start:100
+    EXPECT_EQ(100, curInterval.start.long_value);
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // pull on bucket boundary come late, condition change happens before it
     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(1, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // condition changed to true again, before the pull alarm is delivered
     valueProducer.onConditionChanged(true, bucket2StartTimeNs + 25);
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(130, curInterval.start);
-    EXPECT_EQ(1, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(130, curInterval.start.long_value);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // Now the alarm is delivered, but it is considered late, it has no effect
@@ -945,9 +964,8 @@
 
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(130, curInterval.start);
-    EXPECT_EQ(1, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(130, curInterval.start.long_value);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 }
 
@@ -969,6 +987,7 @@
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
 
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Return(false))
             // condition becomes true
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
@@ -994,17 +1013,15 @@
 
     ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
-    valueProducer.setBucketSize(60 * NS_PER_SEC);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false tainted:0 sum:0 start:100
-    EXPECT_EQ(100, curInterval.start);
+    // startUpdated:false sum:0 start:100
+    EXPECT_EQ(100, curInterval.start.long_value);
     EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(0, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // pull on bucket boundary come late, condition change happens before it.
@@ -1012,8 +1029,7 @@
     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(1, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // Alarm is delivered in time, but the pull is very slow, and pullers are called in order,
@@ -1029,11 +1045,241 @@
 
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
     EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(1, curInterval.tainted);
-    EXPECT_EQ(0, curInterval.sum);
+    EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 }
 
+TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_aggregation_type(ValueMetric::MIN);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+    event1->write(1);
+    event1->write(10);
+    event1->init();
+    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+    event2->write(1);
+    event2->write(20);
+    event2->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(10, curInterval.value.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(10, curInterval.value.long_value);
+
+    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+}
+
+TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_aggregation_type(ValueMetric::MAX);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+    event1->write(1);
+    event1->write(10);
+    event1->init();
+    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+    event2->write(1);
+    event2->write(20);
+    event2->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(10, curInterval.value.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(20, curInterval.value.long_value);
+
+    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+}
+
+TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_aggregation_type(ValueMetric::AVG);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+    event1->write(1);
+    event1->write(10);
+    event1->init();
+    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+    event2->write(1);
+    event2->write(15);
+    event2->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ValueMetricProducer::Interval curInterval;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(10, curInterval.value.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(1, curInterval.sampleSize);
+
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(25, curInterval.value.long_value);
+    EXPECT_EQ(2, curInterval.sampleSize);
+
+    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(12.5, valueProducer.mPastBuckets.begin()->second.back().mValueDouble);
+}
+
+TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_aggregation_type(ValueMetric::SUM);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+    event1->write(1);
+    event1->write(10);
+    event1->init();
+    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+    event2->write(1);
+    event2->write(15);
+    event2->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(10, curInterval.value.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(25, curInterval.value.long_value);
+
+    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(25, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+}
+
+TEST(ValueMetricProducerTest, TestPushedAggregateSumSliced) {
+    string slicedConditionName = "UID";
+    const int conditionTagId = 2;
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(1);
+    metric.set_aggregation_type(ValueMetric::SUM);
+
+    metric.set_condition(StringToId(slicedConditionName));
+    MetricConditionLink* link = metric.add_links();
+    link->set_condition(StringToId(slicedConditionName));
+    buildSimpleAtomFieldMatcher(tagId, 2, link->mutable_fields_in_what());
+    buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
+
+    LogEvent event1(tagId, bucketStartTimeNs + 10);
+    event1.write(10);  // value
+    event1.write("111"); // uid
+    event1.init();
+    ConditionKey key1;
+    key1[StringToId(slicedConditionName)] =
+        {getMockedDimensionKey(conditionTagId, 2, "111")};
+
+    LogEvent event2(tagId, bucketStartTimeNs + 20);
+    event2.write(15);
+    event2.write("222");
+    event2.init();
+    ConditionKey key2;
+    key2[StringToId(slicedConditionName)] =
+        {getMockedDimensionKey(conditionTagId, 2, "222")};
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)).WillOnce(Return(ConditionState::kFalse));
+    EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue));
+
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, -1, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(false, curInterval.hasValue);
+
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    EXPECT_EQ(15, curInterval.value.long_value);
+
+    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(15, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index 6538515..950a258 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -62,7 +62,7 @@
             IBinder token = new Binder();
             try {
                 ContentProviderHolder holder = activityManager.getContentProviderExternal(
-                        providerName, UserHandle.USER_SYSTEM, token);
+                        providerName, UserHandle.USER_SYSTEM, token, "*uiautomator*");
                 if (holder == null) {
                     throw new IllegalStateException("Could not find provider: " + providerName);
                 }
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index a787736..9ca0745 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -12204,11 +12204,11 @@
 HPLorg/json/JSONStringer;->value(Z)Lorg/json/JSONStringer;
 HPLorg/json/JSONTokener;->syntaxError(Ljava/lang/String;)Lorg/json/JSONException;
 HPLorg/json/JSONTokener;->toString()Ljava/lang/String;
-HPLorg/kxml2/io/KXmlSerializer;->getDepth()I
-HPLorg/kxml2/io/KXmlSerializer;->getNamespace()Ljava/lang/String;
-HPLorg/kxml2/io/KXmlSerializer;->getPrefix(Ljava/lang/String;ZZ)Ljava/lang/String;
-HPLorg/kxml2/io/KXmlSerializer;->setPrefix(Ljava/lang/String;Ljava/lang/String;)V
-HPLorg/kxml2/io/KXmlSerializer;->text(Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HPLcom/android/org/kxml2/io/KXmlSerializer;->getDepth()I
+HPLcom/android/org/kxml2/io/KXmlSerializer;->getNamespace()Ljava/lang/String;
+HPLcom/android/org/kxml2/io/KXmlSerializer;->getPrefix(Ljava/lang/String;ZZ)Ljava/lang/String;
+HPLcom/android/org/kxml2/io/KXmlSerializer;->setPrefix(Ljava/lang/String;Ljava/lang/String;)V
+HPLcom/android/org/kxml2/io/KXmlSerializer;->text(Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
 HPLorg/w3c/dom/NamedNodeMap;->getLength()I
 HPLorg/w3c/dom/NamedNodeMap;->getNamedItem(Ljava/lang/String;)Lorg/w3c/dom/Node;
 HPLorg/w3c/dom/NamedNodeMap;->getNamedItemNS(Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/Node;
@@ -51896,7 +51896,7 @@
 HSPLorg/apache/harmony/xml/dom/TextImpl;->getNodeType()S
 HSPLorg/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl;->newDocumentBuilder()Ljavax/xml/parsers/DocumentBuilder;
 HSPLorg/apache/harmony/xml/parsers/DocumentBuilderImpl;->appendText(Lorg/apache/harmony/xml/dom/DocumentImpl;Lorg/w3c/dom/Node;ILjava/lang/String;)V
-HSPLorg/apache/harmony/xml/parsers/DocumentBuilderImpl;->parse(Lorg/kxml2/io/KXmlParser;Lorg/apache/harmony/xml/dom/DocumentImpl;Lorg/w3c/dom/Node;I)V
+HSPLorg/apache/harmony/xml/parsers/DocumentBuilderImpl;->parse(Lcom/android/org/kxml2/io/KXmlParser;Lorg/apache/harmony/xml/dom/DocumentImpl;Lorg/w3c/dom/Node;I)V
 HSPLorg/apache/harmony/xml/parsers/DocumentBuilderImpl;->parse(Lorg/xml/sax/InputSource;)Lorg/w3c/dom/Document;
 HSPLorg/apache/harmony/xml/parsers/SAXParserFactoryImpl;->getFeature(Ljava/lang/String;)Z
 HSPLorg/apache/harmony/xml/parsers/SAXParserFactoryImpl;->isValidating()Z
@@ -52176,64 +52176,64 @@
 HSPLorg/json/JSONTokener;->readLiteral()Ljava/lang/Object;
 HSPLorg/json/JSONTokener;->readObject()Lorg/json/JSONObject;
 HSPLorg/json/JSONTokener;->skipToEndOfLine()V
-HSPLorg/kxml2/io/KXmlParser$ValueContext;-><init>(Ljava/lang/String;I)V
-HSPLorg/kxml2/io/KXmlParser;-><init>()V
-HSPLorg/kxml2/io/KXmlParser;->adjustNsp()Z
-HSPLorg/kxml2/io/KXmlParser;->close()V
-HSPLorg/kxml2/io/KXmlParser;->fillBuffer(I)Z
-HSPLorg/kxml2/io/KXmlParser;->getAttributeCount()I
-HSPLorg/kxml2/io/KXmlParser;->getAttributeName(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributeNamespace(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributePrefix(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributeType(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributeValue(I)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getAttributeValue(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getColumnNumber()I
-HSPLorg/kxml2/io/KXmlParser;->getDepth()I
-HSPLorg/kxml2/io/KXmlParser;->getEventType()I
-HSPLorg/kxml2/io/KXmlParser;->getFeature(Ljava/lang/String;)Z
-HSPLorg/kxml2/io/KXmlParser;->getLineNumber()I
-HSPLorg/kxml2/io/KXmlParser;->getName()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getNamespace()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getNamespace(Ljava/lang/String;)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getNamespaceCount(I)I
-HSPLorg/kxml2/io/KXmlParser;->getPositionDescription()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getPrefix()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getText()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->getTextCharacters([I)[C
-HSPLorg/kxml2/io/KXmlParser;->next()I
-HSPLorg/kxml2/io/KXmlParser;->next(Z)I
-HSPLorg/kxml2/io/KXmlParser;->nextTag()I
-HSPLorg/kxml2/io/KXmlParser;->nextText()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->nextToken()I
-HSPLorg/kxml2/io/KXmlParser;->parseStartTag(ZZ)V
-HSPLorg/kxml2/io/KXmlParser;->peekType(Z)I
-HSPLorg/kxml2/io/KXmlParser;->read(C)V
-HSPLorg/kxml2/io/KXmlParser;->read([C)V
-HSPLorg/kxml2/io/KXmlParser;->readComment(Z)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->readEndTag()V
-HSPLorg/kxml2/io/KXmlParser;->readEntity(Ljava/lang/StringBuilder;ZZLorg/kxml2/io/KXmlParser$ValueContext;)V
-HSPLorg/kxml2/io/KXmlParser;->readName()Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->readUntil([CZ)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->readValue(CZZLorg/kxml2/io/KXmlParser$ValueContext;)Ljava/lang/String;
-HSPLorg/kxml2/io/KXmlParser;->readXmlDeclaration()V
-HSPLorg/kxml2/io/KXmlParser;->require(ILjava/lang/String;Ljava/lang/String;)V
-HSPLorg/kxml2/io/KXmlParser;->setFeature(Ljava/lang/String;Z)V
-HSPLorg/kxml2/io/KXmlParser;->setInput(Ljava/io/InputStream;Ljava/lang/String;)V
-HSPLorg/kxml2/io/KXmlParser;->setInput(Ljava/io/Reader;)V
-HSPLorg/kxml2/io/KXmlSerializer;-><init>()V
-HSPLorg/kxml2/io/KXmlSerializer;->append(Ljava/lang/String;II)V
-HSPLorg/kxml2/io/KXmlSerializer;->attribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
-HSPLorg/kxml2/io/KXmlSerializer;->check(Z)V
-HSPLorg/kxml2/io/KXmlSerializer;->endDocument()V
-HSPLorg/kxml2/io/KXmlSerializer;->endTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
-HSPLorg/kxml2/io/KXmlSerializer;->flush()V
-HSPLorg/kxml2/io/KXmlSerializer;->setFeature(Ljava/lang/String;Z)V
-HSPLorg/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/OutputStream;Ljava/lang/String;)V
-HSPLorg/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/Writer;)V
-HSPLorg/kxml2/io/KXmlSerializer;->startDocument(Ljava/lang/String;Ljava/lang/Boolean;)V
-HSPLorg/kxml2/io/KXmlSerializer;->startTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
-HSPLorg/kxml2/io/KXmlSerializer;->writeEscaped(Ljava/lang/String;I)V
+HSPLcom/android/org/kxml2/io/KXmlParser$ValueContext;-><init>(Ljava/lang/String;I)V
+HSPLcom/android/org/kxml2/io/KXmlParser;-><init>()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->adjustNsp()Z
+HSPLcom/android/org/kxml2/io/KXmlParser;->close()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->fillBuffer(I)Z
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeCount()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeName(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeNamespace(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributePrefix(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeType(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeValue(I)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getAttributeValue(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getColumnNumber()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getDepth()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getEventType()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getFeature(Ljava/lang/String;)Z
+HSPLcom/android/org/kxml2/io/KXmlParser;->getLineNumber()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getName()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getNamespace()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getNamespace(Ljava/lang/String;)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getNamespaceCount(I)I
+HSPLcom/android/org/kxml2/io/KXmlParser;->getPositionDescription()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getPrefix()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getText()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->getTextCharacters([I)[C
+HSPLcom/android/org/kxml2/io/KXmlParser;->next()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->next(Z)I
+HSPLcom/android/org/kxml2/io/KXmlParser;->nextTag()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->nextText()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->nextToken()I
+HSPLcom/android/org/kxml2/io/KXmlParser;->parseStartTag(ZZ)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->peekType(Z)I
+HSPLcom/android/org/kxml2/io/KXmlParser;->read(C)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->read([C)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->readComment(Z)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readEndTag()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->readEntity(Ljava/lang/StringBuilder;ZZLcom/android/org/kxml2/io/KXmlParser$ValueContext;)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->readName()Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readUntil([CZ)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readValue(CZZLcom/android/org/kxml2/io/KXmlParser$ValueContext;)Ljava/lang/String;
+HSPLcom/android/org/kxml2/io/KXmlParser;->readXmlDeclaration()V
+HSPLcom/android/org/kxml2/io/KXmlParser;->require(ILjava/lang/String;Ljava/lang/String;)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->setFeature(Ljava/lang/String;Z)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->setInput(Ljava/io/InputStream;Ljava/lang/String;)V
+HSPLcom/android/org/kxml2/io/KXmlParser;->setInput(Ljava/io/Reader;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;-><init>()V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->append(Ljava/lang/String;II)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->attribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->check(Z)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->endDocument()V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->endTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->flush()V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->setFeature(Ljava/lang/String;Z)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/OutputStream;Ljava/lang/String;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->setOutput(Ljava/io/Writer;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->startDocument(Ljava/lang/String;Ljava/lang/Boolean;)V
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->startTag(Ljava/lang/String;Ljava/lang/String;)Lorg/xmlpull/v1/XmlSerializer;
+HSPLcom/android/org/kxml2/io/KXmlSerializer;->writeEscaped(Ljava/lang/String;I)V
 HSPLorg/w3c/dom/Attr;->getName()Ljava/lang/String;
 HSPLorg/w3c/dom/Attr;->getOwnerElement()Lorg/w3c/dom/Element;
 HSPLorg/w3c/dom/Attr;->getSchemaTypeInfo()Lorg/w3c/dom/TypeInfo;
@@ -63397,9 +63397,9 @@
 Lorg/json/JSONStringer$Scope;
 Lorg/json/JSONStringer;
 Lorg/json/JSONTokener;
-Lorg/kxml2/io/KXmlParser$ValueContext;
-Lorg/kxml2/io/KXmlParser;
-Lorg/kxml2/io/KXmlSerializer;
+Lcom/android/org/kxml2/io/KXmlParser$ValueContext;
+Lcom/android/org/kxml2/io/KXmlParser;
+Lcom/android/org/kxml2/io/KXmlSerializer;
 Lorg/w3c/dom/CharacterData;
 Lorg/w3c/dom/DOMImplementation;
 Lorg/w3c/dom/Document;
diff --git a/config/hiddenapi-force-blacklist.txt b/config/hiddenapi-force-blacklist.txt
index 3a9e2d1..dca3b52 100644
--- a/config/hiddenapi-force-blacklist.txt
+++ b/config/hiddenapi-force-blacklist.txt
@@ -1,38 +1,38 @@
 Ldalvik/system/VMRuntime;->setHiddenApiExemptions([Ljava/lang/String;)V
 Ljava/lang/invoke/MethodHandles$Lookup;->IMPL_LOOKUP:Ljava/lang/invoke/MethodHandles$Lookup;
 Ljava/lang/invoke/VarHandle;->acquireFence()V
-Ljava/lang/invoke/VarHandle;->compareAndExchange([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->compareAndExchangeAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->compareAndExchangeRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->compareAndSet([[Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->compareAndExchange([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->compareAndExchangeAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->compareAndExchangeRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->compareAndSet([Ljava/lang/Object;)Z
 Ljava/lang/invoke/VarHandle;->fullFence()V
-Ljava/lang/invoke/VarHandle;->get([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndAdd([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndAddAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndAddRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseAnd([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseAndAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseAndRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseOr([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseOrAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseOrRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseXor([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseXorAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseXorRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndSet([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndSetAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndSetRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getOpaque([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getVolatile([[Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->get([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndAdd([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndAddAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndAddRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseAnd([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseAndAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseAndRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseOr([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseOrAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseOrRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseXor([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseXorAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseXorRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndSet([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndSetAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndSetRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getOpaque([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getVolatile([Ljava/lang/Object;)Ljava/lang/Object;
 Ljava/lang/invoke/VarHandle;->loadLoadFence()V
 Ljava/lang/invoke/VarHandle;->releaseFence()V
-Ljava/lang/invoke/VarHandle;->set([[Ljava/lang/Object;)V
-Ljava/lang/invoke/VarHandle;->setOpaque([[Ljava/lang/Object;)V
-Ljava/lang/invoke/VarHandle;->setRelease([[Ljava/lang/Object;)V
-Ljava/lang/invoke/VarHandle;->setVolatile([[Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->set([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->setOpaque([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->setRelease([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->setVolatile([Ljava/lang/Object;)V
 Ljava/lang/invoke/VarHandle;->storeStoreFence()V
-Ljava/lang/invoke/VarHandle;->weakCompareAndSet([[Ljava/lang/Object;)Z
-Ljava/lang/invoke/VarHandle;->weakCompareAndSetAcquire([[Ljava/lang/Object;)Z
-Ljava/lang/invoke/VarHandle;->weakCompareAndSetPlain([[Ljava/lang/Object;)Z
-Ljava/lang/invoke/VarHandle;->weakCompareAndSetRelease([[Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSet([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSetAcquire([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSetPlain([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSetRelease([Ljava/lang/Object;)Z
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index f805dea..196f89c 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1,26 +1,5 @@
-Landroid/accessibilityservice/AccessibilityService;->mInfo:Landroid/accessibilityservice/AccessibilityServiceInfo;
-Landroid/accessibilityservice/AccessibilityService;->mWindowToken:Landroid/os/IBinder;
-Landroid/accessibilityservice/AccessibilityServiceInfo;->setCapabilities(I)V
 Landroid/accessibilityservice/IAccessibilityServiceConnection$Stub;-><init>()V
 Landroid/accessibilityservice/IAccessibilityServiceConnection$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accessibilityservice/IAccessibilityServiceConnection;
-Landroid/accounts/Account;->accessId:Ljava/lang/String;
-Landroid/accounts/Account;->TAG:Ljava/lang/String;
-Landroid/accounts/AccountAndUser;-><init>(Landroid/accounts/Account;I)V
-Landroid/accounts/AccountAndUser;->account:Landroid/accounts/Account;
-Landroid/accounts/AccountAndUser;->userId:I
-Landroid/accounts/AccountAuthenticatorResponse;-><init>(Landroid/accounts/IAccountAuthenticatorResponse;)V
-Landroid/accounts/AccountManager$AmsTask;->mActivity:Landroid/app/Activity;
-Landroid/accounts/AccountManager$AmsTask;->mHandler:Landroid/os/Handler;
-Landroid/accounts/AccountManager$AmsTask;->mResponse:Landroid/accounts/IAccountManagerResponse;
-Landroid/accounts/AccountManager$GetAuthTokenByTypeAndFeaturesTask;->mAuthTokenType:Ljava/lang/String;
-Landroid/accounts/AccountManager$GetAuthTokenByTypeAndFeaturesTask;->mLoginOptions:Landroid/os/Bundle;
-Landroid/accounts/AccountManager$GetAuthTokenByTypeAndFeaturesTask;->mMyCallback:Landroid/accounts/AccountManagerCallback;
-Landroid/accounts/AccountManager;-><init>(Landroid/content/Context;Landroid/accounts/IAccountManager;)V
-Landroid/accounts/AccountManager;->confirmCredentialsAsUser(Landroid/accounts/Account;Landroid/os/Bundle;Landroid/app/Activity;Landroid/accounts/AccountManagerCallback;Landroid/os/Handler;Landroid/os/UserHandle;)Landroid/accounts/AccountManagerFuture;
-Landroid/accounts/AccountManager;->getAccountsByTypeAsUser(Ljava/lang/String;Landroid/os/UserHandle;)[Landroid/accounts/Account;
-Landroid/accounts/AccountManager;->mContext:Landroid/content/Context;
-Landroid/accounts/AuthenticatorDescription;-><init>(Landroid/os/Parcel;)V
-Landroid/accounts/AuthenticatorDescription;-><init>(Ljava/lang/String;)V
 Landroid/accounts/IAccountAuthenticator$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/accounts/IAccountAuthenticator$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/accounts/IAccountAuthenticator$Stub;-><init>()V
@@ -51,425 +30,13 @@
 Landroid/accounts/IAccountManagerResponse$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountManagerResponse;
 Landroid/accounts/IAccountManagerResponse;->onError(ILjava/lang/String;)V
 Landroid/accounts/IAccountManagerResponse;->onResult(Landroid/os/Bundle;)V
-Landroid/animation/Animator;->reverse()V
-Landroid/animation/ArgbEvaluator;->getInstance()Landroid/animation/ArgbEvaluator;
-Landroid/animation/LayoutTransition;->cancel()V
-Landroid/animation/LayoutTransition;->cancel(I)V
-Landroid/animation/ValueAnimator;->animateValue(F)V
-Landroid/animation/ValueAnimator;->mDuration:J
-Landroid/animation/ValueAnimator;->sDurationScale:F
-Landroid/app/ActionBar;->collapseActionView()Z
-Landroid/app/ActionBar;->DISPLAY_TITLE_MULTIPLE_LINES:I
-Landroid/app/ActionBar;->setShowHideAnimationEnabled(Z)V
-Landroid/app/Activity;->attach(Landroid/content/Context;Landroid/app/ActivityThread;Landroid/app/Instrumentation;Landroid/os/IBinder;ILandroid/app/Application;Landroid/content/Intent;Landroid/content/pm/ActivityInfo;Ljava/lang/CharSequence;Landroid/app/Activity;Ljava/lang/String;Landroid/app/Activity$NonConfigurationInstances;Landroid/content/res/Configuration;Ljava/lang/String;Lcom/android/internal/app/IVoiceInteractor;Landroid/view/Window;Landroid/view/ViewRootImpl$ActivityConfigCallback;)V
-Landroid/app/Activity;->dispatchActivityResult(Ljava/lang/String;IILandroid/content/Intent;Ljava/lang/String;)V
-Landroid/app/Activity;->finish(I)V
-Landroid/app/Activity;->FRAGMENTS_TAG:Ljava/lang/String;
-Landroid/app/Activity;->getActivityOptions()Landroid/app/ActivityOptions;
-Landroid/app/Activity;->getActivityToken()Landroid/os/IBinder;
-Landroid/app/Activity;->isResumed()Z
-Landroid/app/Activity;->mActivityInfo:Landroid/content/pm/ActivityInfo;
-Landroid/app/Activity;->mActivityTransitionState:Landroid/app/ActivityTransitionState;
-Landroid/app/Activity;->mApplication:Landroid/app/Application;
-Landroid/app/Activity;->mCalled:Z
-Landroid/app/Activity;->mComponent:Landroid/content/ComponentName;
-Landroid/app/Activity;->mConfigChangeFlags:I
-Landroid/app/Activity;->mCurrentConfig:Landroid/content/res/Configuration;
-Landroid/app/Activity;->mDestroyed:Z
-Landroid/app/Activity;->mEmbeddedID:Ljava/lang/String;
-Landroid/app/Activity;->mFinished:Z
-Landroid/app/Activity;->mFragments:Landroid/app/FragmentController;
-Landroid/app/Activity;->mHandler:Landroid/os/Handler;
-Landroid/app/Activity;->mIdent:I
-Landroid/app/Activity;->mInstrumentation:Landroid/app/Instrumentation;
-Landroid/app/Activity;->mIntent:Landroid/content/Intent;
-Landroid/app/Activity;->mLastNonConfigurationInstances:Landroid/app/Activity$NonConfigurationInstances;
-Landroid/app/Activity;->mMainThread:Landroid/app/ActivityThread;
-Landroid/app/Activity;->mParent:Landroid/app/Activity;
-Landroid/app/Activity;->mReferrer:Ljava/lang/String;
-Landroid/app/Activity;->mResultCode:I
-Landroid/app/Activity;->mResultData:Landroid/content/Intent;
-Landroid/app/Activity;->mResumed:Z
-Landroid/app/Activity;->mStopped:Z
-Landroid/app/Activity;->mTitle:Ljava/lang/CharSequence;
-Landroid/app/Activity;->mToken:Landroid/os/IBinder;
-Landroid/app/Activity;->mVisibleFromClient:Z
-Landroid/app/Activity;->mVoiceInteractor:Landroid/app/VoiceInteractor;
-Landroid/app/Activity;->mWindow:Landroid/view/Window;
-Landroid/app/Activity;->mWindowAdded:Z
-Landroid/app/Activity;->mWindowManager:Landroid/view/WindowManager;
-Landroid/app/Activity;->performCreate(Landroid/os/Bundle;Landroid/os/PersistableBundle;)V
-Landroid/app/Activity;->saveManagedDialogs(Landroid/os/Bundle;)V
-Landroid/app/Activity;->setDisablePreviewScreenshots(Z)V
-Landroid/app/Activity;->setParent(Landroid/app/Activity;)V
-Landroid/app/Activity;->setPersistent(Z)V
-Landroid/app/Activity;->startActivityAsUser(Landroid/content/Intent;Landroid/os/UserHandle;)V
-Landroid/app/Activity;->startActivityForResult(Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;)V
-Landroid/app/Activity;->startActivityForResultAsUser(Landroid/content/Intent;ILandroid/os/UserHandle;)V
-Landroid/app/ActivityGroup;->mLocalActivityManager:Landroid/app/LocalActivityManager;
-Landroid/app/ActivityManager$MemoryInfo;->foregroundAppThreshold:J
-Landroid/app/ActivityManager$MemoryInfo;->hiddenAppThreshold:J
-Landroid/app/ActivityManager$MemoryInfo;->secondaryServerThreshold:J
-Landroid/app/ActivityManager$MemoryInfo;->visibleAppThreshold:J
-Landroid/app/ActivityManager$RecentTaskInfo;->affiliatedTaskColor:I
-Landroid/app/ActivityManager$RecentTaskInfo;->firstActiveTime:J
-Landroid/app/ActivityManager$RecentTaskInfo;->lastActiveTime:J
-Landroid/app/ActivityManager$RecentTaskInfo;->resizeMode:I
-Landroid/app/ActivityManager$RecentTaskInfo;->stackId:I
-Landroid/app/ActivityManager$RecentTaskInfo;->supportsSplitScreenMultiWindow:Z
-Landroid/app/ActivityManager$RecentTaskInfo;->userId:I
-Landroid/app/ActivityManager$RunningAppProcessInfo;->flags:I
-Landroid/app/ActivityManager$RunningAppProcessInfo;->FLAG_HAS_ACTIVITIES:I
-Landroid/app/ActivityManager$RunningAppProcessInfo;->FLAG_PERSISTENT:I
-Landroid/app/ActivityManager$RunningAppProcessInfo;->processState:I
-Landroid/app/ActivityManager$RunningAppProcessInfo;->procStateToImportance(I)I
-Landroid/app/ActivityManager$StackInfo;->bounds:Landroid/graphics/Rect;
-Landroid/app/ActivityManager$StackInfo;->displayId:I
-Landroid/app/ActivityManager$StackInfo;->position:I
-Landroid/app/ActivityManager$StackInfo;->stackId:I
-Landroid/app/ActivityManager$StackInfo;->taskBounds:[Landroid/graphics/Rect;
-Landroid/app/ActivityManager$StackInfo;->taskIds:[I
-Landroid/app/ActivityManager$StackInfo;->taskNames:[Ljava/lang/String;
-Landroid/app/ActivityManager$StackInfo;->taskUserIds:[I
-Landroid/app/ActivityManager$StackInfo;->topActivity:Landroid/content/ComponentName;
-Landroid/app/ActivityManager$StackInfo;->toString(Ljava/lang/String;)Ljava/lang/String;
-Landroid/app/ActivityManager$StackInfo;->userId:I
-Landroid/app/ActivityManager$StackInfo;->visible:Z
-Landroid/app/ActivityManager$TaskDescription;->getBackgroundColor()I
-Landroid/app/ActivityManager$TaskDescription;->getInMemoryIcon()Landroid/graphics/Bitmap;
-Landroid/app/ActivityManager$TaskDescription;->setIcon(Landroid/graphics/Bitmap;)V
-Landroid/app/ActivityManager$TaskSnapshot;->getContentInsets()Landroid/graphics/Rect;
-Landroid/app/ActivityManager$TaskSnapshot;->getOrientation()I
-Landroid/app/ActivityManager$TaskSnapshot;->getScale()F
-Landroid/app/ActivityManager$TaskSnapshot;->isRealSnapshot()Z
-Landroid/app/ActivityManager$TaskSnapshot;->isReducedResolution()Z
-Landroid/app/ActivityManager;-><init>(Landroid/content/Context;Landroid/os/Handler;)V
-Landroid/app/ActivityManager;->checkComponentPermission(Ljava/lang/String;IIZ)I
-Landroid/app/ActivityManager;->clearApplicationUserData(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)Z
-Landroid/app/ActivityManager;->forceStopPackageAsUser(Ljava/lang/String;I)V
-Landroid/app/ActivityManager;->getMaxRecentTasksStatic()I
-Landroid/app/ActivityManager;->getService()Landroid/app/IActivityManager;
-Landroid/app/ActivityManager;->IActivityManagerSingleton:Landroid/util/Singleton;
-Landroid/app/ActivityManager;->INTENT_SENDER_ACTIVITY:I
-Landroid/app/ActivityManager;->isHighEndGfx()Z
-Landroid/app/ActivityManager;->isLowRamDeviceStatic()Z
-Landroid/app/ActivityManager;->isUserRunning(I)Z
-Landroid/app/ActivityManager;->mContext:Landroid/content/Context;
-Landroid/app/ActivityManager;->PROCESS_STATE_BOUND_FOREGROUND_SERVICE:I
-Landroid/app/ActivityManager;->PROCESS_STATE_CACHED_ACTIVITY:I
-Landroid/app/ActivityManager;->PROCESS_STATE_FOREGROUND_SERVICE:I
-Landroid/app/ActivityManager;->PROCESS_STATE_HOME:I
-Landroid/app/ActivityManager;->PROCESS_STATE_IMPORTANT_BACKGROUND:I
-Landroid/app/ActivityManager;->PROCESS_STATE_RECEIVER:I
-Landroid/app/ActivityManager;->PROCESS_STATE_SERVICE:I
-Landroid/app/ActivityManager;->PROCESS_STATE_TOP:I
-Landroid/app/ActivityManager;->staticGetMemoryClass()I
-Landroid/app/ActivityManager;->switchUser(I)Z
 Landroid/app/ActivityManagerNative;-><init>()V
-Landroid/app/ActivityManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/app/IActivityManager;
-Landroid/app/ActivityManagerNative;->getDefault()Landroid/app/IActivityManager;
-Landroid/app/ActivityManagerNative;->isSystemReady()Z
-Landroid/app/ActivityOptions;->makeCustomAnimation(Landroid/content/Context;IILandroid/os/Handler;Landroid/app/ActivityOptions$OnAnimationStartedListener;)Landroid/app/ActivityOptions;
-Landroid/app/ActivityOptions;->makeMultiThumbFutureAspectScaleAnimation(Landroid/content/Context;Landroid/os/Handler;Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/app/ActivityOptions$OnAnimationStartedListener;Z)Landroid/app/ActivityOptions;
-Landroid/app/ActivityThread$ActivityClientRecord;-><init>()V
-Landroid/app/ActivityThread$ActivityClientRecord;->activity:Landroid/app/Activity;
-Landroid/app/ActivityThread$ActivityClientRecord;->activityInfo:Landroid/content/pm/ActivityInfo;
-Landroid/app/ActivityThread$ActivityClientRecord;->compatInfo:Landroid/content/res/CompatibilityInfo;
-Landroid/app/ActivityThread$ActivityClientRecord;->intent:Landroid/content/Intent;
-Landroid/app/ActivityThread$ActivityClientRecord;->mPreserveWindow:Z
-Landroid/app/ActivityThread$ActivityClientRecord;->packageInfo:Landroid/app/LoadedApk;
-Landroid/app/ActivityThread$ActivityClientRecord;->paused:Z
-Landroid/app/ActivityThread$ActivityClientRecord;->stopped:Z
-Landroid/app/ActivityThread$ActivityClientRecord;->token:Landroid/os/IBinder;
 Landroid/app/ActivityThread$AppBindData;-><init>()V
-Landroid/app/ActivityThread$AppBindData;->appInfo:Landroid/content/pm/ApplicationInfo;
-Landroid/app/ActivityThread$AppBindData;->compatInfo:Landroid/content/res/CompatibilityInfo;
-Landroid/app/ActivityThread$AppBindData;->info:Landroid/app/LoadedApk;
-Landroid/app/ActivityThread$AppBindData;->instrumentationArgs:Landroid/os/Bundle;
-Landroid/app/ActivityThread$AppBindData;->persistent:Z
-Landroid/app/ActivityThread$AppBindData;->processName:Ljava/lang/String;
-Landroid/app/ActivityThread$AppBindData;->providers:Ljava/util/List;
-Landroid/app/ActivityThread$AppBindData;->restrictedBackupMode:Z
-Landroid/app/ActivityThread$BindServiceData;->intent:Landroid/content/Intent;
-Landroid/app/ActivityThread$BindServiceData;->token:Landroid/os/IBinder;
 Landroid/app/ActivityThread$CreateServiceData;-><init>()V
-Landroid/app/ActivityThread$CreateServiceData;->compatInfo:Landroid/content/res/CompatibilityInfo;
-Landroid/app/ActivityThread$CreateServiceData;->info:Landroid/content/pm/ServiceInfo;
-Landroid/app/ActivityThread$CreateServiceData;->intent:Landroid/content/Intent;
-Landroid/app/ActivityThread$CreateServiceData;->token:Landroid/os/IBinder;
-Landroid/app/ActivityThread$H;->BIND_SERVICE:I
-Landroid/app/ActivityThread$H;->CREATE_SERVICE:I
-Landroid/app/ActivityThread$H;->DUMP_PROVIDER:I
-Landroid/app/ActivityThread$H;->ENTER_ANIMATION_COMPLETE:I
-Landroid/app/ActivityThread$H;->EXIT_APPLICATION:I
-Landroid/app/ActivityThread$H;->GC_WHEN_IDLE:I
-Landroid/app/ActivityThread$H;->INSTALL_PROVIDER:I
-Landroid/app/ActivityThread$H;->RECEIVER:I
-Landroid/app/ActivityThread$H;->REMOVE_PROVIDER:I
-Landroid/app/ActivityThread$H;->SCHEDULE_CRASH:I
-Landroid/app/ActivityThread$H;->SERVICE_ARGS:I
-Landroid/app/ActivityThread$H;->STOP_SERVICE:I
-Landroid/app/ActivityThread$H;->UNBIND_SERVICE:I
-Landroid/app/ActivityThread$ProviderClientRecord;->mHolder:Landroid/app/ContentProviderHolder;
-Landroid/app/ActivityThread$ProviderClientRecord;->mLocalProvider:Landroid/content/ContentProvider;
-Landroid/app/ActivityThread$ProviderClientRecord;->mProvider:Landroid/content/IContentProvider;
-Landroid/app/ActivityThread$ReceiverData;->compatInfo:Landroid/content/res/CompatibilityInfo;
-Landroid/app/ActivityThread$ReceiverData;->info:Landroid/content/pm/ActivityInfo;
-Landroid/app/ActivityThread$ReceiverData;->intent:Landroid/content/Intent;
-Landroid/app/ActivityThread$ServiceArgsData;->args:Landroid/content/Intent;
-Landroid/app/ActivityThread$ServiceArgsData;->token:Landroid/os/IBinder;
-Landroid/app/ActivityThread;-><init>()V
-Landroid/app/ActivityThread;->acquireExistingProvider(Landroid/content/Context;Ljava/lang/String;IZ)Landroid/content/IContentProvider;
-Landroid/app/ActivityThread;->acquireProvider(Landroid/content/Context;Ljava/lang/String;IZ)Landroid/content/IContentProvider;
-Landroid/app/ActivityThread;->attach(ZJ)V
-Landroid/app/ActivityThread;->currentActivityThread()Landroid/app/ActivityThread;
-Landroid/app/ActivityThread;->currentApplication()Landroid/app/Application;
-Landroid/app/ActivityThread;->currentPackageName()Ljava/lang/String;
-Landroid/app/ActivityThread;->currentProcessName()Ljava/lang/String;
-Landroid/app/ActivityThread;->getActivity(Landroid/os/IBinder;)Landroid/app/Activity;
-Landroid/app/ActivityThread;->getApplication()Landroid/app/Application;
-Landroid/app/ActivityThread;->getApplicationThread()Landroid/app/ActivityThread$ApplicationThread;
-Landroid/app/ActivityThread;->getHandler()Landroid/os/Handler;
-Landroid/app/ActivityThread;->getInstrumentation()Landroid/app/Instrumentation;
-Landroid/app/ActivityThread;->getLooper()Landroid/os/Looper;
-Landroid/app/ActivityThread;->getPackageInfo(Landroid/content/pm/ApplicationInfo;Landroid/content/res/CompatibilityInfo;I)Landroid/app/LoadedApk;
-Landroid/app/ActivityThread;->getPackageInfo(Ljava/lang/String;Landroid/content/res/CompatibilityInfo;I)Landroid/app/LoadedApk;
-Landroid/app/ActivityThread;->getPackageInfoNoCheck(Landroid/content/pm/ApplicationInfo;Landroid/content/res/CompatibilityInfo;)Landroid/app/LoadedApk;
-Landroid/app/ActivityThread;->getPackageManager()Landroid/content/pm/IPackageManager;
-Landroid/app/ActivityThread;->getProcessName()Ljava/lang/String;
-Landroid/app/ActivityThread;->getSystemContext()Landroid/app/ContextImpl;
-Landroid/app/ActivityThread;->handleBindApplication(Landroid/app/ActivityThread$AppBindData;)V
-Landroid/app/ActivityThread;->handleCreateService(Landroid/app/ActivityThread$CreateServiceData;)V
-Landroid/app/ActivityThread;->handleReceiver(Landroid/app/ActivityThread$ReceiverData;)V
-Landroid/app/ActivityThread;->handleUnstableProviderDied(Landroid/os/IBinder;Z)V
-Landroid/app/ActivityThread;->installContentProviders(Landroid/content/Context;Ljava/util/List;)V
-Landroid/app/ActivityThread;->installProvider(Landroid/content/Context;Landroid/app/ContentProviderHolder;Landroid/content/pm/ProviderInfo;ZZZ)Landroid/app/ContentProviderHolder;
-Landroid/app/ActivityThread;->installSystemProviders(Ljava/util/List;)V
-Landroid/app/ActivityThread;->mActivities:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mAllApplications:Ljava/util/ArrayList;
-Landroid/app/ActivityThread;->mAppThread:Landroid/app/ActivityThread$ApplicationThread;
-Landroid/app/ActivityThread;->mBoundApplication:Landroid/app/ActivityThread$AppBindData;
-Landroid/app/ActivityThread;->mConfiguration:Landroid/content/res/Configuration;
-Landroid/app/ActivityThread;->mCurDefaultDisplayDpi:I
-Landroid/app/ActivityThread;->mDensityCompatMode:Z
-Landroid/app/ActivityThread;->mH:Landroid/app/ActivityThread$H;
-Landroid/app/ActivityThread;->mInitialApplication:Landroid/app/Application;
-Landroid/app/ActivityThread;->mInstrumentation:Landroid/app/Instrumentation;
-Landroid/app/ActivityThread;->mInstrumentationAppDir:Ljava/lang/String;
-Landroid/app/ActivityThread;->mInstrumentedAppDir:Ljava/lang/String;
-Landroid/app/ActivityThread;->mLocalProviders:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mLocalProvidersByName:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mLooper:Landroid/os/Looper;
-Landroid/app/ActivityThread;->mNumVisibleActivities:I
-Landroid/app/ActivityThread;->mPackages:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mPendingConfiguration:Landroid/content/res/Configuration;
-Landroid/app/ActivityThread;->mProviderMap:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mProviderRefCountMap:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mResourcePackages:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mResourcesManager:Landroid/app/ResourcesManager;
-Landroid/app/ActivityThread;->mServices:Landroid/util/ArrayMap;
-Landroid/app/ActivityThread;->mSystemContext:Landroid/app/ContextImpl;
-Landroid/app/ActivityThread;->peekPackageInfo(Ljava/lang/String;Z)Landroid/app/LoadedApk;
-Landroid/app/ActivityThread;->performNewIntents(Landroid/os/IBinder;Ljava/util/List;Z)V
-Landroid/app/ActivityThread;->performStopActivity(Landroid/os/IBinder;ZLjava/lang/String;)V
-Landroid/app/ActivityThread;->registerOnActivityPausedListener(Landroid/app/Activity;Landroid/app/OnActivityPausedListener;)V
-Landroid/app/ActivityThread;->releaseProvider(Landroid/content/IContentProvider;Z)Z
-Landroid/app/ActivityThread;->scheduleGcIdler()V
-Landroid/app/ActivityThread;->sCurrentActivityThread:Landroid/app/ActivityThread;
-Landroid/app/ActivityThread;->sendActivityResult(Landroid/os/IBinder;Ljava/lang/String;IILandroid/content/Intent;)V
-Landroid/app/ActivityThread;->sMainThreadHandler:Landroid/os/Handler;
-Landroid/app/ActivityThread;->sPackageManager:Landroid/content/pm/IPackageManager;
-Landroid/app/ActivityThread;->startActivityNow(Landroid/app/Activity;Ljava/lang/String;Landroid/content/Intent;Landroid/content/pm/ActivityInfo;Landroid/os/IBinder;Landroid/os/Bundle;Landroid/app/Activity$NonConfigurationInstances;)Landroid/app/Activity;
-Landroid/app/ActivityThread;->systemMain()Landroid/app/ActivityThread;
-Landroid/app/ActivityThread;->unregisterOnActivityPausedListener(Landroid/app/Activity;Landroid/app/OnActivityPausedListener;)V
-Landroid/app/admin/DeviceAdminInfo$PolicyInfo;->tag:Ljava/lang/String;
-Landroid/app/admin/DeviceAdminInfo;->getUsedPolicies()Ljava/util/ArrayList;
-Landroid/app/admin/DevicePolicyManager;->ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:Ljava/lang/String;
-Landroid/app/admin/DevicePolicyManager;->getActiveAdminsAsUser(I)Ljava/util/List;
-Landroid/app/admin/DevicePolicyManager;->getCameraDisabled(Landroid/content/ComponentName;I)Z
-Landroid/app/admin/DevicePolicyManager;->getCurrentFailedPasswordAttempts(I)I
-Landroid/app/admin/DevicePolicyManager;->getKeyguardDisabledFeatures(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getMandatoryBackupTransport()Landroid/content/ComponentName;
-Landroid/app/admin/DevicePolicyManager;->getMaximumFailedPasswordsForWipe(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getMaximumTimeToLock(Landroid/content/ComponentName;I)J
-Landroid/app/admin/DevicePolicyManager;->getPasswordHistoryLength(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getPasswordMinimumLength(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getPasswordMinimumLetters(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getPasswordMinimumLowerCase(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getPasswordMinimumNonLetter(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getPasswordMinimumNumeric(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getPasswordMinimumSymbols(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getPasswordMinimumUpperCase(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getPasswordQuality(Landroid/content/ComponentName;I)I
-Landroid/app/admin/DevicePolicyManager;->getProfileOwnerAsUser(I)Landroid/content/ComponentName;
-Landroid/app/admin/DevicePolicyManager;->getRequiredStrongAuthTimeout(Landroid/content/ComponentName;I)J
-Landroid/app/admin/DevicePolicyManager;->getStorageEncryptionStatus(I)I
-Landroid/app/admin/DevicePolicyManager;->getTrustAgentConfiguration(Landroid/content/ComponentName;Landroid/content/ComponentName;I)Ljava/util/List;
-Landroid/app/admin/DevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;I)Z
-Landroid/app/admin/DevicePolicyManager;->reportFailedPasswordAttempt(I)V
-Landroid/app/admin/DevicePolicyManager;->reportSuccessfulPasswordAttempt(I)V
-Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;Z)V
-Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;ZI)V
-Landroid/app/admin/DevicePolicyManager;->setActivePasswordState(Landroid/app/admin/PasswordMetrics;I)V
-Landroid/app/admin/DevicePolicyManager;->setDefaultSmsApplication(Landroid/content/ComponentName;Ljava/lang/String;)V
-Landroid/app/admin/DevicePolicyManager;->setGlobalProxy(Landroid/content/ComponentName;Ljava/net/Proxy;Ljava/util/List;)Landroid/content/ComponentName;
-Landroid/app/admin/DevicePolicyManager;->throwIfParentInstance(Ljava/lang/String;)V
 Landroid/app/admin/IDevicePolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/admin/IDevicePolicyManager;
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
 Landroid/app/admin/IDevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;I)Z
-Landroid/app/admin/SecurityLog$SecurityEvent;-><init>([B)V
-Landroid/app/AlarmManager;->FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED:I
-Landroid/app/AlarmManager;->FLAG_IDLE_UNTIL:I
-Landroid/app/AlarmManager;->FLAG_STANDALONE:I
-Landroid/app/AlarmManager;->FLAG_WAKE_FROM_IDLE:I
-Landroid/app/AlarmManager;->mService:Landroid/app/IAlarmManager;
-Landroid/app/AlarmManager;->set(IJJJLjava/lang/String;Landroid/app/AlarmManager$OnAlarmListener;Landroid/os/Handler;Landroid/os/WorkSource;)V
-Landroid/app/AlarmManager;->WINDOW_EXACT:J
-Landroid/app/AlarmManager;->WINDOW_HEURISTIC:J
-Landroid/app/AlertDialog$Builder;->P:Lcom/android/internal/app/AlertController$AlertParams;
-Landroid/app/AlertDialog$Builder;->setRecycleOnMeasureEnabled(Z)Landroid/app/AlertDialog$Builder;
-Landroid/app/AlertDialog$Builder;->setView(Landroid/view/View;IIII)Landroid/app/AlertDialog$Builder;
-Landroid/app/AlertDialog;->mAlert:Lcom/android/internal/app/AlertController;
-Landroid/app/AppGlobals;->getInitialApplication()Landroid/app/Application;
-Landroid/app/AppGlobals;->getInitialPackage()Ljava/lang/String;
-Landroid/app/AppGlobals;->getPackageManager()Landroid/content/pm/IPackageManager;
-Landroid/app/Application;->attach(Landroid/content/Context;)V
-Landroid/app/Application;->collectActivityLifecycleCallbacks()[Ljava/lang/Object;
-Landroid/app/Application;->dispatchActivityCreated(Landroid/app/Activity;Landroid/os/Bundle;)V
-Landroid/app/Application;->dispatchActivityDestroyed(Landroid/app/Activity;)V
-Landroid/app/Application;->dispatchActivityPaused(Landroid/app/Activity;)V
-Landroid/app/Application;->dispatchActivityResumed(Landroid/app/Activity;)V
-Landroid/app/Application;->dispatchActivitySaveInstanceState(Landroid/app/Activity;Landroid/os/Bundle;)V
-Landroid/app/Application;->dispatchActivityStarted(Landroid/app/Activity;)V
-Landroid/app/Application;->dispatchActivityStopped(Landroid/app/Activity;)V
-Landroid/app/Application;->mActivityLifecycleCallbacks:Ljava/util/ArrayList;
-Landroid/app/Application;->mAssistCallbacks:Ljava/util/ArrayList;
-Landroid/app/Application;->mComponentCallbacks:Ljava/util/ArrayList;
-Landroid/app/Application;->mLoadedApk:Landroid/app/LoadedApk;
-Landroid/app/ApplicationLoaders;->getDefault()Landroid/app/ApplicationLoaders;
-Landroid/app/ApplicationLoaders;->mLoaders:Landroid/util/ArrayMap;
-Landroid/app/ApplicationPackageManager;-><init>(Landroid/app/ContextImpl;Landroid/content/pm/IPackageManager;)V
-Landroid/app/ApplicationPackageManager;->configurationChanged()V
-Landroid/app/ApplicationPackageManager;->deletePackage(Ljava/lang/String;Landroid/content/pm/IPackageDeleteObserver;I)V
-Landroid/app/ApplicationPackageManager;->getPackageCurrentVolume(Landroid/content/pm/ApplicationInfo;)Landroid/os/storage/VolumeInfo;
-Landroid/app/ApplicationPackageManager;->getPackageSizeInfoAsUser(Ljava/lang/String;ILandroid/content/pm/IPackageStatsObserver;)V
-Landroid/app/ApplicationPackageManager;->mPM:Landroid/content/pm/IPackageManager;
-Landroid/app/ApplicationPackageManager;->shouldShowRequestPermissionRationale(Ljava/lang/String;)Z
-Landroid/app/AppOpsManager$PackageOps;-><init>(Ljava/lang/String;ILjava/util/List;)V
-Landroid/app/AppOpsManager;->checkOp(IILjava/lang/String;)I
-Landroid/app/AppOpsManager;->checkOpNoThrow(IILjava/lang/String;)I
-Landroid/app/AppOpsManager;->mService:Lcom/android/internal/app/IAppOpsService;
-Landroid/app/AppOpsManager;->noteOp(I)I
-Landroid/app/AppOpsManager;->noteOp(IILjava/lang/String;)I
-Landroid/app/AppOpsManager;->noteOpNoThrow(IILjava/lang/String;)I
-Landroid/app/AppOpsManager;->noteProxyOp(ILjava/lang/String;)I
-Landroid/app/AppOpsManager;->opToName(I)Ljava/lang/String;
-Landroid/app/AppOpsManager;->opToSwitch(I)I
-Landroid/app/AppOpsManager;->OP_ACCEPT_HANDOVER:I
-Landroid/app/AppOpsManager;->OP_ACCESS_NOTIFICATIONS:I
-Landroid/app/AppOpsManager;->OP_ACTIVATE_VPN:I
-Landroid/app/AppOpsManager;->OP_ADD_VOICEMAIL:I
-Landroid/app/AppOpsManager;->OP_ANSWER_PHONE_CALLS:I
-Landroid/app/AppOpsManager;->OP_ASSIST_SCREENSHOT:I
-Landroid/app/AppOpsManager;->OP_ASSIST_STRUCTURE:I
-Landroid/app/AppOpsManager;->OP_AUDIO_ACCESSIBILITY_VOLUME:I
-Landroid/app/AppOpsManager;->OP_AUDIO_ALARM_VOLUME:I
-Landroid/app/AppOpsManager;->OP_AUDIO_BLUETOOTH_VOLUME:I
-Landroid/app/AppOpsManager;->OP_AUDIO_MASTER_VOLUME:I
-Landroid/app/AppOpsManager;->OP_AUDIO_MEDIA_VOLUME:I
-Landroid/app/AppOpsManager;->OP_AUDIO_NOTIFICATION_VOLUME:I
-Landroid/app/AppOpsManager;->OP_AUDIO_RING_VOLUME:I
-Landroid/app/AppOpsManager;->OP_AUDIO_VOICE_VOLUME:I
-Landroid/app/AppOpsManager;->OP_BIND_ACCESSIBILITY_SERVICE:I
-Landroid/app/AppOpsManager;->OP_BLUETOOTH_SCAN:I
-Landroid/app/AppOpsManager;->OP_BODY_SENSORS:I
-Landroid/app/AppOpsManager;->OP_CALL_PHONE:I
-Landroid/app/AppOpsManager;->OP_CAMERA:I
-Landroid/app/AppOpsManager;->OP_CHANGE_WIFI_STATE:I
-Landroid/app/AppOpsManager;->OP_COARSE_LOCATION:I
-Landroid/app/AppOpsManager;->OP_FINE_LOCATION:I
-Landroid/app/AppOpsManager;->OP_GET_ACCOUNTS:I
-Landroid/app/AppOpsManager;->OP_GET_USAGE_STATS:I
-Landroid/app/AppOpsManager;->OP_GPS:I
-Landroid/app/AppOpsManager;->OP_INSTANT_APP_START_FOREGROUND:I
-Landroid/app/AppOpsManager;->OP_MANAGE_IPSEC_TUNNELS:I
-Landroid/app/AppOpsManager;->OP_MOCK_LOCATION:I
-Landroid/app/AppOpsManager;->OP_MONITOR_HIGH_POWER_LOCATION:I
-Landroid/app/AppOpsManager;->OP_MONITOR_LOCATION:I
-Landroid/app/AppOpsManager;->OP_MUTE_MICROPHONE:I
-Landroid/app/AppOpsManager;->OP_NEIGHBORING_CELLS:I
-Landroid/app/AppOpsManager;->OP_NONE:I
-Landroid/app/AppOpsManager;->OP_PICTURE_IN_PICTURE:I
-Landroid/app/AppOpsManager;->OP_PLAY_AUDIO:I
-Landroid/app/AppOpsManager;->OP_POST_NOTIFICATION:I
-Landroid/app/AppOpsManager;->OP_PROCESS_OUTGOING_CALLS:I
-Landroid/app/AppOpsManager;->OP_PROJECT_MEDIA:I
-Landroid/app/AppOpsManager;->OP_READ_CALENDAR:I
-Landroid/app/AppOpsManager;->OP_READ_CALL_LOG:I
-Landroid/app/AppOpsManager;->OP_READ_CELL_BROADCASTS:I
-Landroid/app/AppOpsManager;->OP_READ_CLIPBOARD:I
-Landroid/app/AppOpsManager;->OP_READ_CONTACTS:I
-Landroid/app/AppOpsManager;->OP_READ_EXTERNAL_STORAGE:I
-Landroid/app/AppOpsManager;->OP_READ_ICC_SMS:I
-Landroid/app/AppOpsManager;->OP_READ_PHONE_NUMBERS:I
-Landroid/app/AppOpsManager;->OP_READ_PHONE_STATE:I
-Landroid/app/AppOpsManager;->OP_READ_SMS:I
-Landroid/app/AppOpsManager;->OP_RECEIVE_EMERGECY_SMS:I
-Landroid/app/AppOpsManager;->OP_RECEIVE_MMS:I
-Landroid/app/AppOpsManager;->OP_RECEIVE_SMS:I
-Landroid/app/AppOpsManager;->OP_RECEIVE_WAP_PUSH:I
-Landroid/app/AppOpsManager;->OP_REQUEST_DELETE_PACKAGES:I
-Landroid/app/AppOpsManager;->OP_REQUEST_INSTALL_PACKAGES:I
-Landroid/app/AppOpsManager;->OP_RUN_ANY_IN_BACKGROUND:I
-Landroid/app/AppOpsManager;->OP_RUN_IN_BACKGROUND:I
-Landroid/app/AppOpsManager;->OP_SEND_SMS:I
-Landroid/app/AppOpsManager;->OP_START_FOREGROUND:I
-Landroid/app/AppOpsManager;->OP_TAKE_AUDIO_FOCUS:I
-Landroid/app/AppOpsManager;->OP_TAKE_MEDIA_BUTTONS:I
-Landroid/app/AppOpsManager;->OP_TOAST_WINDOW:I
-Landroid/app/AppOpsManager;->OP_TURN_SCREEN_ON:I
-Landroid/app/AppOpsManager;->OP_USE_FINGERPRINT:I
-Landroid/app/AppOpsManager;->OP_USE_SIP:I
-Landroid/app/AppOpsManager;->OP_VIBRATE:I
-Landroid/app/AppOpsManager;->OP_WAKE_LOCK:I
-Landroid/app/AppOpsManager;->OP_WIFI_SCAN:I
-Landroid/app/AppOpsManager;->OP_WRITE_CALENDAR:I
-Landroid/app/AppOpsManager;->OP_WRITE_CALL_LOG:I
-Landroid/app/AppOpsManager;->OP_WRITE_CLIPBOARD:I
-Landroid/app/AppOpsManager;->OP_WRITE_CONTACTS:I
-Landroid/app/AppOpsManager;->OP_WRITE_EXTERNAL_STORAGE:I
-Landroid/app/AppOpsManager;->OP_WRITE_ICC_SMS:I
-Landroid/app/AppOpsManager;->OP_WRITE_SETTINGS:I
-Landroid/app/AppOpsManager;->OP_WRITE_SMS:I
-Landroid/app/AppOpsManager;->OP_WRITE_WALLPAPER:I
-Landroid/app/AppOpsManager;->resetAllModes()V
-Landroid/app/AppOpsManager;->setRestriction(III[Ljava/lang/String;)V
-Landroid/app/AppOpsManager;->sOpPerms:[Ljava/lang/String;
-Landroid/app/AppOpsManager;->_NUM_OP:I
-Landroid/app/assist/AssistContent;-><init>(Landroid/os/Parcel;)V
-Landroid/app/assist/AssistContent;->mClipData:Landroid/content/ClipData;
-Landroid/app/assist/AssistContent;->mExtras:Landroid/os/Bundle;
-Landroid/app/assist/AssistContent;->mIntent:Landroid/content/Intent;
-Landroid/app/assist/AssistContent;->mIsAppProvidedIntent:Z
-Landroid/app/assist/AssistContent;->mStructuredData:Ljava/lang/String;
-Landroid/app/assist/AssistContent;->mUri:Landroid/net/Uri;
-Landroid/app/assist/AssistContent;->writeToParcelInternal(Landroid/os/Parcel;I)V
-Landroid/app/backup/BackupDataInput$EntityHeader;->dataSize:I
-Landroid/app/backup/BackupDataInput$EntityHeader;->key:Ljava/lang/String;
-Landroid/app/backup/BackupDataInputStream;->dataSize:I
-Landroid/app/backup/BackupDataInputStream;->key:Ljava/lang/String;
-Landroid/app/backup/BackupDataOutput;->mBackupWriter:J
-Landroid/app/backup/BackupHelperDispatcher$Header;->chunkSize:I
-Landroid/app/backup/BackupHelperDispatcher$Header;->keyPrefix:Ljava/lang/String;
-Landroid/app/backup/BackupManager;->checkServiceBinder()V
-Landroid/app/backup/BackupManager;->sService:Landroid/app/backup/IBackupManager;
-Landroid/app/backup/FileBackupHelperBase;->writeNewStateDescription(Landroid/os/ParcelFileDescriptor;)V
-Landroid/app/backup/FullBackup;->backupToTar(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/FullBackupDataOutput;)I
-Landroid/app/backup/FullBackupDataOutput;-><init>(Landroid/os/ParcelFileDescriptor;)V
-Landroid/app/backup/FullBackupDataOutput;->addSize(J)V
-Landroid/app/backup/FullBackupDataOutput;->getData()Landroid/app/backup/BackupDataOutput;
-Landroid/app/backup/FullBackupDataOutput;->mData:Landroid/app/backup/BackupDataOutput;
 Landroid/app/backup/IBackupManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/backup/IBackupManager;
 Landroid/app/backup/IBackupManager;->acknowledgeFullBackupOrRestore(IZLjava/lang/String;Ljava/lang/String;Landroid/app/backup/IFullBackupRestoreObserver;)V
 Landroid/app/backup/IBackupManager;->clearBackupData(Ljava/lang/String;Ljava/lang/String;)V
@@ -483,85 +50,7 @@
 Landroid/app/backup/IBackupManager;->setBackupEnabled(Z)V
 Landroid/app/backup/IFullBackupRestoreObserver$Stub;-><init>()V
 Landroid/app/backup/IRestoreObserver$Stub;-><init>()V
-Landroid/app/ContentProviderHolder;-><init>(Landroid/content/pm/ProviderInfo;)V
-Landroid/app/ContentProviderHolder;-><init>(Landroid/os/Parcel;)V
-Landroid/app/ContentProviderHolder;->info:Landroid/content/pm/ProviderInfo;
-Landroid/app/ContentProviderHolder;->noReleaseNeeded:Z
-Landroid/app/ContentProviderHolder;->provider:Landroid/content/IContentProvider;
-Landroid/app/ContextImpl$ApplicationContentResolver;->acquireProvider(Landroid/content/Context;Ljava/lang/String;)Landroid/content/IContentProvider;
-Landroid/app/ContextImpl$ApplicationContentResolver;->mMainThread:Landroid/app/ActivityThread;
-Landroid/app/ContextImpl;->createActivityContext(Landroid/app/ActivityThread;Landroid/app/LoadedApk;Landroid/content/pm/ActivityInfo;Landroid/os/IBinder;ILandroid/content/res/Configuration;)Landroid/app/ContextImpl;
-Landroid/app/ContextImpl;->createAppContext(Landroid/app/ActivityThread;Landroid/app/LoadedApk;)Landroid/app/ContextImpl;
-Landroid/app/ContextImpl;->createSystemContext(Landroid/app/ActivityThread;)Landroid/app/ContextImpl;
-Landroid/app/ContextImpl;->getActivityToken()Landroid/os/IBinder;
-Landroid/app/ContextImpl;->getDisplay()Landroid/view/Display;
-Landroid/app/ContextImpl;->getImpl(Landroid/content/Context;)Landroid/app/ContextImpl;
-Landroid/app/ContextImpl;->getOuterContext()Landroid/content/Context;
-Landroid/app/ContextImpl;->getPreferencesDir()Ljava/io/File;
-Landroid/app/ContextImpl;->getReceiverRestrictedContext()Landroid/content/Context;
-Landroid/app/ContextImpl;->mBasePackageName:Ljava/lang/String;
-Landroid/app/ContextImpl;->mClassLoader:Ljava/lang/ClassLoader;
-Landroid/app/ContextImpl;->mContentResolver:Landroid/app/ContextImpl$ApplicationContentResolver;
-Landroid/app/ContextImpl;->mFlags:I
-Landroid/app/ContextImpl;->mMainThread:Landroid/app/ActivityThread;
-Landroid/app/ContextImpl;->mOpPackageName:Ljava/lang/String;
-Landroid/app/ContextImpl;->mOuterContext:Landroid/content/Context;
-Landroid/app/ContextImpl;->mPackageInfo:Landroid/app/LoadedApk;
-Landroid/app/ContextImpl;->mPackageManager:Landroid/content/pm/PackageManager;
-Landroid/app/ContextImpl;->mPreferencesDir:Ljava/io/File;
-Landroid/app/ContextImpl;->mResources:Landroid/content/res/Resources;
-Landroid/app/ContextImpl;->mServiceCache:[Ljava/lang/Object;
-Landroid/app/ContextImpl;->mSharedPrefsPaths:Landroid/util/ArrayMap;
-Landroid/app/ContextImpl;->mTheme:Landroid/content/res/Resources$Theme;
-Landroid/app/ContextImpl;->mThemeResource:I
-Landroid/app/ContextImpl;->scheduleFinalCleanup(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/app/ContextImpl;->setOuterContext(Landroid/content/Context;)V
-Landroid/app/ContextImpl;->sSharedPrefsCache:Landroid/util/ArrayMap;
-Landroid/app/DatePickerDialog;->mDatePicker:Landroid/widget/DatePicker;
-Landroid/app/Dialog;->CANCEL:I
-Landroid/app/Dialog;->dismissDialog()V
-Landroid/app/Dialog;->mCancelMessage:Landroid/os/Message;
-Landroid/app/Dialog;->mContext:Landroid/content/Context;
-Landroid/app/Dialog;->mDismissMessage:Landroid/os/Message;
-Landroid/app/Dialog;->mHandler:Landroid/os/Handler;
-Landroid/app/Dialog;->mListenersHandler:Landroid/os/Handler;
-Landroid/app/Dialog;->mOnKeyListener:Landroid/content/DialogInterface$OnKeyListener;
-Landroid/app/Dialog;->mOwnerActivity:Landroid/app/Activity;
-Landroid/app/Dialog;->mShowing:Z
-Landroid/app/Dialog;->mShowMessage:Landroid/os/Message;
-Landroid/app/Dialog;->mWindow:Landroid/view/Window;
-Landroid/app/DialogFragment;->mBackStackId:I
-Landroid/app/DialogFragment;->mDismissed:Z
-Landroid/app/DialogFragment;->mShownByMe:Z
-Landroid/app/DialogFragment;->mViewDestroyed:Z
-Landroid/app/DialogFragment;->showAllowingStateLoss(Landroid/app/FragmentManager;Ljava/lang/String;)V
-Landroid/app/DownloadManager$Query;->orderBy(Ljava/lang/String;I)Landroid/app/DownloadManager$Query;
-Landroid/app/DownloadManager$Query;->setOnlyIncludeVisibleInDownloadsUi(Z)Landroid/app/DownloadManager$Query;
-Landroid/app/DownloadManager$Request;->mUri:Landroid/net/Uri;
-Landroid/app/DownloadManager;->getWhereArgsForIds([J)[Ljava/lang/String;
-Landroid/app/DownloadManager;->getWhereClauseForIds([J)Ljava/lang/String;
-Landroid/app/DownloadManager;->restartDownload([[J)V
-Landroid/app/DownloadManager;->setAccessAllDownloads(Z)V
-Landroid/app/DownloadManager;->setAccessFilename(Z)V
-Landroid/app/DownloadManager;->UNDERLYING_COLUMNS:[Ljava/lang/String;
-Landroid/app/Fragment;->mAdded:Z
-Landroid/app/Fragment;->mChildFragmentManager:Landroid/app/FragmentManagerImpl;
-Landroid/app/Fragment;->mFragmentId:I
-Landroid/app/Fragment;->mFragmentManager:Landroid/app/FragmentManagerImpl;
-Landroid/app/Fragment;->mHost:Landroid/app/FragmentHostCallback;
-Landroid/app/Fragment;->mIndex:I
-Landroid/app/Fragment;->mLoadersStarted:Z
-Landroid/app/Fragment;->mSavedFragmentState:Landroid/os/Bundle;
-Landroid/app/Fragment;->mView:Landroid/view/View;
-Landroid/app/Fragment;->mWho:Ljava/lang/String;
-Landroid/app/Fragment;->sClassMap:Landroid/util/ArrayMap;
-Landroid/app/FragmentController;->mHost:Landroid/app/FragmentHostCallback;
-Landroid/app/FragmentHostCallback;->mLoadersStarted:Z
-Landroid/app/FragmentManagerImpl;->loadAnimator(Landroid/app/Fragment;IZI)Landroid/animation/Animator;
-Landroid/app/FragmentManagerImpl;->mActive:Landroid/util/SparseArray;
-Landroid/app/FragmentManagerImpl;->mAdded:Ljava/util/ArrayList;
-Landroid/app/FragmentManagerImpl;->mStateSaved:Z
-Landroid/app/FragmentManagerImpl;->noteStateNotSaved()V
+Landroid/app/DownloadManager;->restartDownload([J)V
 Landroid/app/IActivityController;->activityResuming(Ljava/lang/String;)Z
 Landroid/app/IActivityController;->activityStarting(Landroid/content/Intent;Ljava/lang/String;)Z
 Landroid/app/IActivityController;->appNotResponding(Ljava/lang/String;ILjava/lang/String;)I
@@ -688,22 +177,11 @@
 Landroid/app/INotificationManager;->cancelAllNotifications(Ljava/lang/String;I)V
 Landroid/app/INotificationManager;->cancelNotificationWithTag(Ljava/lang/String;Ljava/lang/String;II)V
 Landroid/app/INotificationManager;->cancelToast(Ljava/lang/String;Landroid/app/ITransientNotification;)V
-Landroid/app/INotificationManager;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;I)V
+Landroid/app/INotificationManager;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;II)V
 Landroid/app/INotificationManager;->getActiveNotifications(Ljava/lang/String;)[Landroid/service/notification/StatusBarNotification;
 Landroid/app/INotificationManager;->getHistoricalNotifications(Ljava/lang/String;I)[Landroid/service/notification/StatusBarNotification;
 Landroid/app/INotificationManager;->getZenMode()I
 Landroid/app/INotificationManager;->getZenModeConfig()Landroid/service/notification/ZenModeConfig;
-Landroid/app/Instrumentation;->callActivityOnNewIntent(Landroid/app/Activity;Lcom/android/internal/content/ReferrerIntent;)V
-Landroid/app/Instrumentation;->checkStartActivityResult(ILjava/lang/Object;)V
-Landroid/app/Instrumentation;->execStartActivities(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Landroid/app/Activity;[Landroid/content/Intent;Landroid/os/Bundle;)V
-Landroid/app/Instrumentation;->execStartActivitiesAsUser(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Landroid/app/Activity;[Landroid/content/Intent;Landroid/os/Bundle;I)I
-Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Landroid/app/Activity;Landroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/Instrumentation$ActivityResult;
-Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/Instrumentation$ActivityResult;
-Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/Instrumentation$ActivityResult;
-Landroid/app/Instrumentation;->execStartActivityAsCaller(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Landroid/app/Activity;Landroid/content/Intent;ILandroid/os/Bundle;ZI)Landroid/app/Instrumentation$ActivityResult;
-Landroid/app/Instrumentation;->execStartActivityFromAppTask(Landroid/content/Context;Landroid/os/IBinder;Landroid/app/IAppTask;Landroid/content/Intent;Landroid/os/Bundle;)V
-Landroid/app/IntentReceiverLeaked;-><init>(Ljava/lang/String;)V
-Landroid/app/IntentService;->mServiceHandler:Landroid/app/IntentService$ServiceHandler;
 Landroid/app/IProcessObserver$Stub;-><init>()V
 Landroid/app/ISearchManager$Stub$Proxy;->getGlobalSearchActivity()Landroid/content/ComponentName;
 Landroid/app/ISearchManager$Stub$Proxy;->getWebSearchActivity()Landroid/content/ComponentName;
@@ -753,155 +231,10 @@
 Landroid/app/job/IJobService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobService;
 Landroid/app/job/IJobService;->startJob(Landroid/app/job/JobParameters;)V
 Landroid/app/job/IJobService;->stopJob(Landroid/app/job/JobParameters;)V
-Landroid/app/job/JobInfo$Builder;->setFlags(I)Landroid/app/job/JobInfo$Builder;
-Landroid/app/job/JobInfo$Builder;->setPriority(I)Landroid/app/job/JobInfo$Builder;
-Landroid/app/job/JobInfo;->flags:I
-Landroid/app/job/JobInfo;->FLAG_WILL_BE_FOREGROUND:I
-Landroid/app/job/JobInfo;->jobId:I
-Landroid/app/job/JobInfo;->PRIORITY_FOREGROUND_APP:I
-Landroid/app/job/JobInfo;->service:Landroid/content/ComponentName;
-Landroid/app/job/JobParameters;->callback:Landroid/os/IBinder;
-Landroid/app/job/JobParameters;->getCallback()Landroid/app/job/IJobCallback;
-Landroid/app/job/JobParameters;->jobId:I
-Landroid/app/job/JobWorkItem;-><init>(Landroid/os/Parcel;)V
-Landroid/app/job/JobWorkItem;->mDeliveryCount:I
-Landroid/app/job/JobWorkItem;->mGrants:Ljava/lang/Object;
-Landroid/app/job/JobWorkItem;->mIntent:Landroid/content/Intent;
-Landroid/app/job/JobWorkItem;->mWorkId:I
-Landroid/app/KeyguardManager;->isDeviceSecure(I)Z
-Landroid/app/LoadedApk$ReceiverDispatcher;->getIIntentReceiver()Landroid/content/IIntentReceiver;
-Landroid/app/LoadedApk$ReceiverDispatcher;->getIntentReceiver()Landroid/content/BroadcastReceiver;
-Landroid/app/LoadedApk$ReceiverDispatcher;->mContext:Landroid/content/Context;
-Landroid/app/LoadedApk$ReceiverDispatcher;->mReceiver:Landroid/content/BroadcastReceiver;
-Landroid/app/LoadedApk$ServiceDispatcher$InnerConnection;->mDispatcher:Ljava/lang/ref/WeakReference;
-Landroid/app/LoadedApk$ServiceDispatcher;-><init>(Landroid/content/ServiceConnection;Landroid/content/Context;Landroid/os/Handler;I)V
-Landroid/app/LoadedApk$ServiceDispatcher;->getIServiceConnection()Landroid/app/IServiceConnection;
-Landroid/app/LoadedApk$ServiceDispatcher;->mConnection:Landroid/content/ServiceConnection;
-Landroid/app/LoadedApk$ServiceDispatcher;->mContext:Landroid/content/Context;
-Landroid/app/LoadedApk;->getAppDir()Ljava/lang/String;
-Landroid/app/LoadedApk;->getApplicationInfo()Landroid/content/pm/ApplicationInfo;
-Landroid/app/LoadedApk;->getAssets()Landroid/content/res/AssetManager;
-Landroid/app/LoadedApk;->getClassLoader()Ljava/lang/ClassLoader;
-Landroid/app/LoadedApk;->getCompatibilityInfo()Landroid/content/res/CompatibilityInfo;
-Landroid/app/LoadedApk;->getDataDirFile()Ljava/io/File;
-Landroid/app/LoadedApk;->getOverlayDirs()[Ljava/lang/String;
-Landroid/app/LoadedApk;->getPackageName()Ljava/lang/String;
-Landroid/app/LoadedApk;->getResDir()Ljava/lang/String;
-Landroid/app/LoadedApk;->getResources()Landroid/content/res/Resources;
-Landroid/app/LoadedApk;->getServiceDispatcher(Landroid/content/ServiceConnection;Landroid/content/Context;Landroid/os/Handler;I)Landroid/app/IServiceConnection;
-Landroid/app/LoadedApk;->getSplitResDirs()[Ljava/lang/String;
-Landroid/app/LoadedApk;->mActivityThread:Landroid/app/ActivityThread;
-Landroid/app/LoadedApk;->makeApplication(ZLandroid/app/Instrumentation;)Landroid/app/Application;
-Landroid/app/LoadedApk;->mAppDir:Ljava/lang/String;
-Landroid/app/LoadedApk;->mApplication:Landroid/app/Application;
-Landroid/app/LoadedApk;->mApplicationInfo:Landroid/content/pm/ApplicationInfo;
-Landroid/app/LoadedApk;->mBaseClassLoader:Ljava/lang/ClassLoader;
-Landroid/app/LoadedApk;->mClassLoader:Ljava/lang/ClassLoader;
-Landroid/app/LoadedApk;->mDataDir:Ljava/lang/String;
-Landroid/app/LoadedApk;->mDataDirFile:Ljava/io/File;
-Landroid/app/LoadedApk;->mDisplayAdjustments:Landroid/view/DisplayAdjustments;
-Landroid/app/LoadedApk;->mLibDir:Ljava/lang/String;
-Landroid/app/LoadedApk;->mPackageName:Ljava/lang/String;
-Landroid/app/LoadedApk;->mReceivers:Landroid/util/ArrayMap;
-Landroid/app/LoadedApk;->mResDir:Ljava/lang/String;
-Landroid/app/LoadedApk;->mResources:Landroid/content/res/Resources;
-Landroid/app/LoadedApk;->mServices:Landroid/util/ArrayMap;
-Landroid/app/LoadedApk;->mSplitResDirs:[Ljava/lang/String;
-Landroid/app/LoadedApk;->rewriteRValues(Ljava/lang/ClassLoader;Ljava/lang/String;I)V
-Landroid/app/LocalActivityManager;->mActivities:Ljava/util/Map;
-Landroid/app/LocalActivityManager;->mActivityArray:Ljava/util/ArrayList;
-Landroid/app/LocalActivityManager;->moveToState(Landroid/app/LocalActivityManager$LocalActivityRecord;I)V
-Landroid/app/LocalActivityManager;->mParent:Landroid/app/Activity;
-Landroid/app/LocalActivityManager;->mResumed:Landroid/app/LocalActivityManager$LocalActivityRecord;
-Landroid/app/LocalActivityManager;->mSingleMode:Z
-Landroid/app/NativeActivity;->hideIme(I)V
-Landroid/app/NativeActivity;->loadNativeCode(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[BLjava/lang/ClassLoader;Ljava/lang/String;)J
-Landroid/app/NativeActivity;->mNativeHandle:J
-Landroid/app/NativeActivity;->setWindowFlags(II)V
-Landroid/app/NativeActivity;->setWindowFormat(I)V
-Landroid/app/NativeActivity;->showIme(I)V
-Landroid/app/Notification$Action;->mIcon:Landroid/graphics/drawable/Icon;
-Landroid/app/Notification$Builder;->getBaseLayoutResource()I
-Landroid/app/Notification$Builder;->loadHeaderAppName()Ljava/lang/String;
-Landroid/app/Notification$Builder;->mActions:Ljava/util/ArrayList;
-Landroid/app/Notification$Builder;->makePublicContentView()Landroid/widget/RemoteViews;
-Landroid/app/Notification$MediaStyle;->buildStyled(Landroid/app/Notification;)Landroid/app/Notification;
-Landroid/app/Notification;-><init>(Landroid/content/Context;ILjava/lang/CharSequence;JLjava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/content/Intent;)V
-Landroid/app/Notification;->allPendingIntents:Landroid/util/ArraySet;
-Landroid/app/Notification;->isGroupChild()Z
-Landroid/app/Notification;->isGroupSummary()Z
-Landroid/app/Notification;->mChannelId:Ljava/lang/String;
-Landroid/app/Notification;->mGroupKey:Ljava/lang/String;
-Landroid/app/Notification;->mLargeIcon:Landroid/graphics/drawable/Icon;
-Landroid/app/Notification;->mSmallIcon:Landroid/graphics/drawable/Icon;
-Landroid/app/Notification;->setSmallIcon(Landroid/graphics/drawable/Icon;)V
-Landroid/app/NotificationChannel;->mId:Ljava/lang/String;
-Landroid/app/NotificationChannel;->setBlockableSystem(Z)V
-Landroid/app/NotificationChannelGroup;->mId:Ljava/lang/String;
-Landroid/app/NotificationManager;-><init>(Landroid/content/Context;Landroid/os/Handler;)V
-Landroid/app/NotificationManager;->from(Landroid/content/Context;)Landroid/app/NotificationManager;
-Landroid/app/NotificationManager;->getService()Landroid/app/INotificationManager;
-Landroid/app/NotificationManager;->getZenModeConfig()Landroid/service/notification/ZenModeConfig;
-Landroid/app/NotificationManager;->notifyAsUser(Ljava/lang/String;ILandroid/app/Notification;Landroid/os/UserHandle;)V
-Landroid/app/NotificationManager;->setZenMode(ILandroid/net/Uri;Ljava/lang/String;)V
-Landroid/app/NotificationManager;->sService:Landroid/app/INotificationManager;
 Landroid/app/PackageDeleteObserver;-><init>()V
 Landroid/app/PackageInstallObserver;-><init>()V
-Landroid/app/PackageInstallObserver;->onPackageInstalled(Ljava/lang/String;ILjava/lang/String;Landroid/os/Bundle;)V
-Landroid/app/PendingIntent;->getActivityAsUser(Landroid/content/Context;ILandroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/PendingIntent;
-Landroid/app/PendingIntent;->getBroadcastAsUser(Landroid/content/Context;ILandroid/content/Intent;ILandroid/os/UserHandle;)Landroid/app/PendingIntent;
-Landroid/app/PendingIntent;->getIntent()Landroid/content/Intent;
-Landroid/app/PendingIntent;->getTag(Ljava/lang/String;)Ljava/lang/String;
-Landroid/app/PendingIntent;->isActivity()Z
-Landroid/app/PendingIntent;->setOnMarshaledListener(Landroid/app/PendingIntent$OnMarshaledListener;)V
-Landroid/app/PictureInPictureArgs;-><init>()V
-Landroid/app/PictureInPictureArgs;->setActions(Ljava/util/List;)V
-Landroid/app/PictureInPictureArgs;->setAspectRatio(F)V
-Landroid/app/Presentation;->createPresentationContext(Landroid/content/Context;Landroid/view/Display;I)Landroid/content/Context;
-Landroid/app/ProgressDialog;->mMessageView:Landroid/widget/TextView;
-Landroid/app/ProgressDialog;->mProgress:Landroid/widget/ProgressBar;
-Landroid/app/ProgressDialog;->mProgressNumber:Landroid/widget/TextView;
-Landroid/app/QueuedWork;->addFinisher(Ljava/lang/Runnable;)V
-Landroid/app/QueuedWork;->getHandler()Landroid/os/Handler;
-Landroid/app/QueuedWork;->queue(Ljava/lang/Runnable;Z)V
-Landroid/app/QueuedWork;->removeFinisher(Ljava/lang/Runnable;)V
-Landroid/app/QueuedWork;->sFinishers:Ljava/util/LinkedList;
 Landroid/app/ResourcesManager$ActivityResources;-><init>()V
 Landroid/app/ResourcesManager;-><init>()V
-Landroid/app/ResourcesManager;->appendLibAssetForMainAssetPath(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/app/ResourcesManager;->createAssetManager(Landroid/content/res/ResourcesKey;)Landroid/content/res/AssetManager;
-Landroid/app/ResourcesManager;->getInstance()Landroid/app/ResourcesManager;
-Landroid/app/ResourcesManager;->mActivityResourceReferences:Ljava/util/WeakHashMap;
-Landroid/app/ResourcesManager;->mResConfiguration:Landroid/content/res/Configuration;
-Landroid/app/ResourcesManager;->mResourceImpls:Landroid/util/ArrayMap;
-Landroid/app/ResourcesManager;->mResourceReferences:Ljava/util/ArrayList;
-Landroid/app/ResultInfo;-><init>(Ljava/lang/String;IILandroid/content/Intent;)V
-Landroid/app/ResultInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/app/ResultInfo;->mData:Landroid/content/Intent;
-Landroid/app/ResultInfo;->mRequestCode:I
-Landroid/app/ResultInfo;->mResultWho:Ljava/lang/String;
-Landroid/app/SearchableInfo$ActionKeyInfo;->getQueryActionMsg()Ljava/lang/String;
-Landroid/app/SearchableInfo$ActionKeyInfo;->getSuggestActionMsg()Ljava/lang/String;
-Landroid/app/SearchableInfo$ActionKeyInfo;->getSuggestActionMsgColumn()Ljava/lang/String;
-Landroid/app/SearchableInfo;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;Landroid/content/ComponentName;)V
-Landroid/app/SearchableInfo;->findActionKey(I)Landroid/app/SearchableInfo$ActionKeyInfo;
-Landroid/app/SearchableInfo;->getActivityContext(Landroid/content/Context;)Landroid/content/Context;
-Landroid/app/SearchableInfo;->getIconId()I
-Landroid/app/SearchableInfo;->getLabelId()I
-Landroid/app/SearchableInfo;->getProviderContext(Landroid/content/Context;Landroid/content/Context;)Landroid/content/Context;
-Landroid/app/SearchDialog;->isLandscapeMode(Landroid/content/Context;)Z
-Landroid/app/SearchDialog;->launchQuerySearch()V
-Landroid/app/SearchDialog;->launchQuerySearch(ILjava/lang/String;)V
-Landroid/app/SearchDialog;->setWorking(Z)V
-Landroid/app/SearchManager;-><init>(Landroid/content/Context;Landroid/os/Handler;)V
-Landroid/app/SearchManager;->DISABLE_VOICE_SEARCH:Ljava/lang/String;
-Landroid/app/SearchManager;->getSuggestions(Landroid/app/SearchableInfo;Ljava/lang/String;)Landroid/database/Cursor;
-Landroid/app/SearchManager;->getSuggestions(Landroid/app/SearchableInfo;Ljava/lang/String;I)Landroid/database/Cursor;
-Landroid/app/SearchManager;->getWebSearchActivity()Landroid/content/ComponentName;
-Landroid/app/SearchManager;->isVisible()Z
-Landroid/app/SearchManager;->launchAssist(Landroid/os/Bundle;)V
-Landroid/app/SearchManager;->mSearchDialog:Landroid/app/SearchDialog;
-Landroid/app/SearchManager;->startSearch(Ljava/lang/String;ZLandroid/content/ComponentName;Landroid/os/Bundle;ZLandroid/graphics/Rect;)V
 Landroid/app/servertransaction/ActivityResultItem;->mResultInfoList:Ljava/util/List;
 Landroid/app/servertransaction/ClientTransaction;->getActivityToken()Landroid/os/IBinder;
 Landroid/app/servertransaction/ClientTransaction;->getCallbacks()Ljava/util/List;
@@ -910,306 +243,15 @@
 Landroid/app/servertransaction/LaunchActivityItem;->mInfo:Landroid/content/pm/ActivityInfo;
 Landroid/app/servertransaction/LaunchActivityItem;->mIntent:Landroid/content/Intent;
 Landroid/app/servertransaction/NewIntentItem;->mIntents:Ljava/util/List;
-Landroid/app/Service;->attach(Landroid/content/Context;Landroid/app/ActivityThread;Ljava/lang/String;Landroid/os/IBinder;Landroid/app/Application;Ljava/lang/Object;)V
-Landroid/app/Service;->mActivityManager:Landroid/app/IActivityManager;
-Landroid/app/Service;->mApplication:Landroid/app/Application;
-Landroid/app/Service;->mClassName:Ljava/lang/String;
-Landroid/app/Service;->mStartCompatibility:Z
-Landroid/app/Service;->mThread:Landroid/app/ActivityThread;
-Landroid/app/Service;->mToken:Landroid/os/IBinder;
-Landroid/app/Service;->setForeground(Z)V
-Landroid/app/ServiceConnectionLeaked;-><init>(Ljava/lang/String;)V
-Landroid/app/SharedPreferencesImpl;-><init>(Ljava/io/File;I)V
-Landroid/app/SharedPreferencesImpl;->mFile:Ljava/io/File;
-Landroid/app/SharedPreferencesImpl;->startLoadFromDisk()V
-Landroid/app/SharedPreferencesImpl;->startReloadIfChangedUnexpectedly()V
-Landroid/app/StatusBarManager;-><init>(Landroid/content/Context;)V
-Landroid/app/StatusBarManager;->collapsePanels()V
-Landroid/app/StatusBarManager;->disable(I)V
-Landroid/app/StatusBarManager;->DISABLE_EXPAND:I
-Landroid/app/StatusBarManager;->DISABLE_NONE:I
-Landroid/app/StatusBarManager;->DISABLE_NOTIFICATION_TICKER:I
-Landroid/app/StatusBarManager;->expandNotificationsPanel()V
-Landroid/app/StatusBarManager;->expandSettingsPanel()V
-Landroid/app/StatusBarManager;->expandSettingsPanel(Ljava/lang/String;)V
-Landroid/app/StatusBarManager;->getService()Lcom/android/internal/statusbar/IStatusBarService;
-Landroid/app/StatusBarManager;->mContext:Landroid/content/Context;
-Landroid/app/StatusBarManager;->mToken:Landroid/os/IBinder;
-Landroid/app/StatusBarManager;->setIconVisibility(Ljava/lang/String;Z)V
 Landroid/app/TaskStackListener;-><init>()V
-Landroid/app/TimePickerDialog;->mTimePicker:Landroid/widget/TimePicker;
 Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/app/trust/TrustManager;->reportUnlockAttempt(ZI)V
-Landroid/app/UiAutomation;-><init>(Landroid/os/Looper;Landroid/app/IUiAutomationConnection;)V
-Landroid/app/UiAutomation;->connect()V
-Landroid/app/UiAutomation;->disconnect()V
 Landroid/app/UiAutomationConnection;-><init>()V
-Landroid/app/UiModeManager;-><init>()V
-Landroid/app/usage/ConfigurationStats;->mActivationCount:I
-Landroid/app/usage/ConfigurationStats;->mBeginTimeStamp:J
-Landroid/app/usage/ConfigurationStats;->mConfiguration:Landroid/content/res/Configuration;
-Landroid/app/usage/ConfigurationStats;->mEndTimeStamp:J
-Landroid/app/usage/ConfigurationStats;->mLastTimeActive:J
-Landroid/app/usage/ConfigurationStats;->mTotalTimeActive:J
 Landroid/app/usage/IUsageStatsManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/usage/IUsageStatsManager;
 Landroid/app/usage/IUsageStatsManager;->isAppInactive(Ljava/lang/String;I)Z
 Landroid/app/usage/IUsageStatsManager;->queryConfigurationStats(IJJLjava/lang/String;)Landroid/content/pm/ParceledListSlice;
 Landroid/app/usage/IUsageStatsManager;->queryUsageStats(IJJLjava/lang/String;)Landroid/content/pm/ParceledListSlice;
 Landroid/app/usage/IUsageStatsManager;->setAppInactive(Ljava/lang/String;ZI)V
-Landroid/app/usage/NetworkStatsManager;-><init>(Landroid/content/Context;)V
-Landroid/app/usage/UsageEvents$Event;->mClass:Ljava/lang/String;
-Landroid/app/usage/UsageEvents$Event;->mConfiguration:Landroid/content/res/Configuration;
-Landroid/app/usage/UsageEvents$Event;->mEventType:I
-Landroid/app/usage/UsageEvents$Event;->mPackage:Ljava/lang/String;
-Landroid/app/usage/UsageEvents$Event;->mTimeStamp:J
-Landroid/app/usage/UsageEvents;-><init>(Landroid/os/Parcel;)V
-Landroid/app/usage/UsageEvents;->findStringIndex(Ljava/lang/String;)I
-Landroid/app/usage/UsageEvents;->mEventCount:I
-Landroid/app/usage/UsageEvents;->mEventsToWrite:Ljava/util/List;
-Landroid/app/usage/UsageEvents;->mIndex:I
-Landroid/app/usage/UsageEvents;->mParcel:Landroid/os/Parcel;
-Landroid/app/usage/UsageEvents;->mStringPool:[Ljava/lang/String;
-Landroid/app/usage/UsageEvents;->readEventFromParcel(Landroid/os/Parcel;Landroid/app/usage/UsageEvents$Event;)V
-Landroid/app/usage/UsageEvents;->writeEventToParcel(Landroid/app/usage/UsageEvents$Event;Landroid/os/Parcel;I)V
-Landroid/app/usage/UsageStats;->mBeginTimeStamp:J
-Landroid/app/usage/UsageStats;->mEndTimeStamp:J
-Landroid/app/usage/UsageStats;->mLastEvent:I
-Landroid/app/usage/UsageStats;->mLastTimeUsed:J
-Landroid/app/usage/UsageStats;->mLaunchCount:I
-Landroid/app/usage/UsageStats;->mPackageName:Ljava/lang/String;
-Landroid/app/usage/UsageStats;->mTotalTimeInForeground:J
-Landroid/app/usage/UsageStatsManager;->mContext:Landroid/content/Context;
-Landroid/app/usage/UsageStatsManager;->mService:Landroid/app/usage/IUsageStatsManager;
-Landroid/app/usage/UsageStatsManager;->sEmptyResults:Landroid/app/usage/UsageEvents;
 Landroid/app/UserSwitchObserver;-><init>()V
-Landroid/app/VrManager;->mService:Landroid/service/vr/IVrManager;
-Landroid/app/WallpaperColors;->getColorHints()I
-Landroid/app/WallpaperManager;->addOnColorsChangedListener(Landroid/app/WallpaperManager$OnColorsChangedListener;Landroid/os/Handler;I)V
-Landroid/app/WallpaperManager;->getBitmap()Landroid/graphics/Bitmap;
-Landroid/app/WallpaperManager;->getBitmap(Z)Landroid/graphics/Bitmap;
-Landroid/app/WallpaperManager;->getIWallpaperManager()Landroid/app/IWallpaperManager;
-Landroid/app/WallpaperManager;->getWallpaperColors(II)Landroid/app/WallpaperColors;
-Landroid/app/WallpaperManager;->getWallpaperFile(II)Landroid/os/ParcelFileDescriptor;
-Landroid/app/WallpaperManager;->openDefaultWallpaper(Landroid/content/Context;I)Ljava/io/InputStream;
-Landroid/app/WallpaperManager;->setBitmap(Landroid/graphics/Bitmap;Landroid/graphics/Rect;ZII)I
-Landroid/app/WallpaperManager;->setWallpaperComponent(Landroid/content/ComponentName;I)Z
-Landroid/app/WallpaperManager;->sGlobals:Landroid/app/WallpaperManager$Globals;
-Landroid/appwidget/AppWidgetHost;-><init>(Landroid/content/Context;ILandroid/widget/RemoteViews$OnClickHandler;Landroid/os/Looper;)V
-Landroid/appwidget/AppWidgetHost;->HANDLE_VIEW_DATA_CHANGED:I
-Landroid/appwidget/AppWidgetHost;->mHandler:Landroid/os/Handler;
-Landroid/appwidget/AppWidgetHost;->sService:Lcom/android/internal/appwidget/IAppWidgetService;
-Landroid/appwidget/AppWidgetHostView;->getDefaultPaddingForWidget(Landroid/content/Context;Landroid/content/pm/ApplicationInfo;Landroid/graphics/Rect;)Landroid/graphics/Rect;
-Landroid/appwidget/AppWidgetHostView;->mAppWidgetId:I
-Landroid/appwidget/AppWidgetHostView;->mInfo:Landroid/appwidget/AppWidgetProviderInfo;
-Landroid/appwidget/AppWidgetHostView;->updateAppWidgetSize(Landroid/os/Bundle;IIIIZ)V
-Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;)V
-Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;Landroid/os/Bundle;)V
-Landroid/appwidget/AppWidgetManager;->bindAppWidgetIdIfAllowed(IILandroid/content/ComponentName;Landroid/os/Bundle;)Z
-Landroid/appwidget/AppWidgetManager;->bindRemoteViewsService(Landroid/content/Context;ILandroid/content/Intent;Landroid/app/IServiceConnection;I)Z
-Landroid/appwidget/AppWidgetManager;->getInstalledProviders(I)Ljava/util/List;
-Landroid/appwidget/AppWidgetManager;->getInstalledProvidersForProfile(ILandroid/os/UserHandle;Ljava/lang/String;)Ljava/util/List;
-Landroid/appwidget/AppWidgetManager;->mService:Lcom/android/internal/appwidget/IAppWidgetService;
-Landroid/appwidget/AppWidgetProviderInfo;->providerInfo:Landroid/content/pm/ActivityInfo;
-Landroid/bluetooth/BluetoothA2dp;->ACTION_ACTIVE_DEVICE_CHANGED:Ljava/lang/String;
-Landroid/bluetooth/BluetoothA2dp;->ACTION_CODEC_CONFIG_CHANGED:Ljava/lang/String;
-Landroid/bluetooth/BluetoothA2dp;->close()V
-Landroid/bluetooth/BluetoothA2dp;->connect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothA2dp;->disableOptionalCodecs(Landroid/bluetooth/BluetoothDevice;)V
-Landroid/bluetooth/BluetoothA2dp;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothA2dp;->enableOptionalCodecs(Landroid/bluetooth/BluetoothDevice;)V
-Landroid/bluetooth/BluetoothA2dp;->getActiveDevice()Landroid/bluetooth/BluetoothDevice;
-Landroid/bluetooth/BluetoothA2dp;->getCodecStatus(Landroid/bluetooth/BluetoothDevice;)Landroid/bluetooth/BluetoothCodecStatus;
-Landroid/bluetooth/BluetoothA2dp;->getOptionalCodecsEnabled(Landroid/bluetooth/BluetoothDevice;)I
-Landroid/bluetooth/BluetoothA2dp;->getPriority(Landroid/bluetooth/BluetoothDevice;)I
-Landroid/bluetooth/BluetoothA2dp;->OPTIONAL_CODECS_NOT_SUPPORTED:I
-Landroid/bluetooth/BluetoothA2dp;->OPTIONAL_CODECS_PREF_DISABLED:I
-Landroid/bluetooth/BluetoothA2dp;->OPTIONAL_CODECS_PREF_ENABLED:I
-Landroid/bluetooth/BluetoothA2dp;->OPTIONAL_CODECS_PREF_UNKNOWN:I
-Landroid/bluetooth/BluetoothA2dp;->OPTIONAL_CODECS_SUPPORTED:I
-Landroid/bluetooth/BluetoothA2dp;->OPTIONAL_CODECS_SUPPORT_UNKNOWN:I
-Landroid/bluetooth/BluetoothA2dp;->setActiveDevice(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothA2dp;->setCodecConfigPreference(Landroid/bluetooth/BluetoothDevice;Landroid/bluetooth/BluetoothCodecConfig;)V
-Landroid/bluetooth/BluetoothA2dp;->setOptionalCodecsEnabled(Landroid/bluetooth/BluetoothDevice;I)V
-Landroid/bluetooth/BluetoothA2dp;->stateToString(I)Ljava/lang/String;
-Landroid/bluetooth/BluetoothA2dp;->supportsOptionalCodecs(Landroid/bluetooth/BluetoothDevice;)I
-Landroid/bluetooth/BluetoothA2dpSink;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothAdapter;->disable(Z)Z
-Landroid/bluetooth/BluetoothAdapter;->factoryReset()Z
-Landroid/bluetooth/BluetoothAdapter;->getBluetoothManager()Landroid/bluetooth/IBluetoothManager;
-Landroid/bluetooth/BluetoothAdapter;->getBluetoothService(Landroid/bluetooth/IBluetoothManagerCallback;)Landroid/bluetooth/IBluetooth;
-Landroid/bluetooth/BluetoothAdapter;->getConnectionState()I
-Landroid/bluetooth/BluetoothAdapter;->getDiscoverableTimeout()I
-Landroid/bluetooth/BluetoothAdapter;->getLeState()I
-Landroid/bluetooth/BluetoothAdapter;->getUuids()[Landroid/os/ParcelUuid;
-Landroid/bluetooth/BluetoothAdapter;->listenUsingEncryptedRfcommWithServiceRecord(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;
-Landroid/bluetooth/BluetoothAdapter;->listenUsingRfcommOn(IZZ)Landroid/bluetooth/BluetoothServerSocket;
-Landroid/bluetooth/BluetoothAdapter;->mService:Landroid/bluetooth/IBluetooth;
-Landroid/bluetooth/BluetoothAdapter;->setDiscoverableTimeout(I)V
-Landroid/bluetooth/BluetoothAdapter;->setScanMode(I)Z
-Landroid/bluetooth/BluetoothAdapter;->setScanMode(II)Z
-Landroid/bluetooth/BluetoothClass;-><init>(I)V
-Landroid/bluetooth/BluetoothClass;->doesClassMatch(I)Z
-Landroid/bluetooth/BluetoothClass;->PROFILE_A2DP:I
-Landroid/bluetooth/BluetoothClass;->PROFILE_HEADSET:I
-Landroid/bluetooth/BluetoothCodecConfig;
-Landroid/bluetooth/BluetoothCodecConfig;-><init>(IIIIIJJJJ)V
-Landroid/bluetooth/BluetoothCodecConfig;->BITS_PER_SAMPLE_16:I
-Landroid/bluetooth/BluetoothCodecConfig;->BITS_PER_SAMPLE_24:I
-Landroid/bluetooth/BluetoothCodecConfig;->BITS_PER_SAMPLE_32:I
-Landroid/bluetooth/BluetoothCodecConfig;->BITS_PER_SAMPLE_NONE:I
-Landroid/bluetooth/BluetoothCodecConfig;->CHANNEL_MODE_MONO:I
-Landroid/bluetooth/BluetoothCodecConfig;->CHANNEL_MODE_NONE:I
-Landroid/bluetooth/BluetoothCodecConfig;->CHANNEL_MODE_STEREO:I
-Landroid/bluetooth/BluetoothCodecConfig;->CODEC_PRIORITY_DEFAULT:I
-Landroid/bluetooth/BluetoothCodecConfig;->CODEC_PRIORITY_DISABLED:I
-Landroid/bluetooth/BluetoothCodecConfig;->CODEC_PRIORITY_HIGHEST:I
-Landroid/bluetooth/BluetoothCodecConfig;->getBitsPerSample()I
-Landroid/bluetooth/BluetoothCodecConfig;->getChannelMode()I
-Landroid/bluetooth/BluetoothCodecConfig;->getCodecPriority()I
-Landroid/bluetooth/BluetoothCodecConfig;->getCodecSpecific1()J
-Landroid/bluetooth/BluetoothCodecConfig;->getCodecSpecific2()J
-Landroid/bluetooth/BluetoothCodecConfig;->getCodecSpecific3()J
-Landroid/bluetooth/BluetoothCodecConfig;->getCodecSpecific4()J
-Landroid/bluetooth/BluetoothCodecConfig;->getCodecType()I
-Landroid/bluetooth/BluetoothCodecConfig;->getSampleRate()I
-Landroid/bluetooth/BluetoothCodecConfig;->SAMPLE_RATE_176400:I
-Landroid/bluetooth/BluetoothCodecConfig;->SAMPLE_RATE_192000:I
-Landroid/bluetooth/BluetoothCodecConfig;->SAMPLE_RATE_44100:I
-Landroid/bluetooth/BluetoothCodecConfig;->SAMPLE_RATE_48000:I
-Landroid/bluetooth/BluetoothCodecConfig;->SAMPLE_RATE_88200:I
-Landroid/bluetooth/BluetoothCodecConfig;->SAMPLE_RATE_96000:I
-Landroid/bluetooth/BluetoothCodecConfig;->SAMPLE_RATE_NONE:I
-Landroid/bluetooth/BluetoothCodecConfig;->setCodecPriority(I)V
-Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_AAC:I
-Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_APTX:I
-Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_APTX_HD:I
-Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_INVALID:I
-Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_LDAC:I
-Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_MAX:I
-Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_SBC:I
-Landroid/bluetooth/BluetoothCodecStatus;
-Landroid/bluetooth/BluetoothCodecStatus;->EXTRA_CODEC_STATUS:Ljava/lang/String;
-Landroid/bluetooth/BluetoothCodecStatus;->getCodecConfig()Landroid/bluetooth/BluetoothCodecConfig;
-Landroid/bluetooth/BluetoothCodecStatus;->getCodecsLocalCapabilities()[Landroid/bluetooth/BluetoothCodecConfig;
-Landroid/bluetooth/BluetoothCodecStatus;->getCodecsSelectableCapabilities()[Landroid/bluetooth/BluetoothCodecConfig;
-Landroid/bluetooth/BluetoothDevice;-><init>(Ljava/lang/String;)V
-Landroid/bluetooth/BluetoothDevice;->ACTION_ALIAS_CHANGED:Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->ACTION_DISAPPEARED:Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->ACTION_PAIRING_CANCEL:Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->ACTION_SDP_RECORD:Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->cancelPairingUserInput()Z
-Landroid/bluetooth/BluetoothDevice;->connectGatt(Landroid/content/Context;ZLandroid/bluetooth/BluetoothGattCallback;IZILandroid/os/Handler;)Landroid/bluetooth/BluetoothGatt;
-Landroid/bluetooth/BluetoothDevice;->convertPinToBytes(Ljava/lang/String;)[B
-Landroid/bluetooth/BluetoothDevice;->createBond(I)Z
-Landroid/bluetooth/BluetoothDevice;->createInsecureRfcommSocket(I)Landroid/bluetooth/BluetoothSocket;
-Landroid/bluetooth/BluetoothDevice;->createRfcommSocket(I)Landroid/bluetooth/BluetoothSocket;
-Landroid/bluetooth/BluetoothDevice;->createScoSocket()Landroid/bluetooth/BluetoothSocket;
-Landroid/bluetooth/BluetoothDevice;->EXTRA_REASON:Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->EXTRA_SDP_SEARCH_STATUS:Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->getAlias()Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->getAliasName()Ljava/lang/String;
-Landroid/bluetooth/BluetoothDevice;->getBatteryLevel()I
-Landroid/bluetooth/BluetoothDevice;->getMessageAccessPermission()I
-Landroid/bluetooth/BluetoothDevice;->getPhonebookAccessPermission()I
-Landroid/bluetooth/BluetoothDevice;->getService()Landroid/bluetooth/IBluetooth;
-Landroid/bluetooth/BluetoothDevice;->isBluetoothDock()Z
-Landroid/bluetooth/BluetoothDevice;->isBondingInitiatedLocally()Z
-Landroid/bluetooth/BluetoothDevice;->setAlias(Ljava/lang/String;)Z
-Landroid/bluetooth/BluetoothDevice;->setMessageAccessPermission(I)Z
-Landroid/bluetooth/BluetoothDevice;->setPasskey(I)Z
-Landroid/bluetooth/BluetoothDevice;->setSimAccessPermission(I)Z
-Landroid/bluetooth/BluetoothDevice;->UNBOND_REASON_AUTH_FAILED:I
-Landroid/bluetooth/BluetoothDevice;->UNBOND_REASON_AUTH_REJECTED:I
-Landroid/bluetooth/BluetoothDevice;->UNBOND_REASON_AUTH_TIMEOUT:I
-Landroid/bluetooth/BluetoothDevice;->UNBOND_REASON_DISCOVERY_IN_PROGRESS:I
-Landroid/bluetooth/BluetoothDevice;->UNBOND_REASON_REMOTE_AUTH_CANCELED:I
-Landroid/bluetooth/BluetoothDevice;->UNBOND_REASON_REMOTE_DEVICE_DOWN:I
-Landroid/bluetooth/BluetoothDevice;->UNBOND_REASON_REPEATED_ATTEMPTS:I
-Landroid/bluetooth/BluetoothGatt;->connect(Ljava/lang/Boolean;Landroid/bluetooth/BluetoothGattCallback;Landroid/os/Handler;)Z
-Landroid/bluetooth/BluetoothGatt;->mAuthRetryState:I
-Landroid/bluetooth/BluetoothGatt;->mAutoConnect:Z
-Landroid/bluetooth/BluetoothGatt;->mCallback:Landroid/bluetooth/BluetoothGattCallback;
-Landroid/bluetooth/BluetoothGatt;->mClientIf:I
-Landroid/bluetooth/BluetoothGatt;->mDeviceBusy:Ljava/lang/Boolean;
-Landroid/bluetooth/BluetoothGatt;->mService:Landroid/bluetooth/IBluetoothGatt;
-Landroid/bluetooth/BluetoothGatt;->mTransport:I
-Landroid/bluetooth/BluetoothGatt;->refresh()Z
-Landroid/bluetooth/BluetoothGatt;->unregisterApp()V
-Landroid/bluetooth/BluetoothGattCharacteristic;->mInstance:I
-Landroid/bluetooth/BluetoothGattCharacteristic;->mService:Landroid/bluetooth/BluetoothGattService;
-Landroid/bluetooth/BluetoothGattCharacteristic;->setKeySize(I)V
-Landroid/bluetooth/BluetoothGattCharacteristic;->setService(Landroid/bluetooth/BluetoothGattService;)V
-Landroid/bluetooth/BluetoothGattDescriptor;->mCharacteristic:Landroid/bluetooth/BluetoothGattCharacteristic;
-Landroid/bluetooth/BluetoothGattDescriptor;->mInstance:I
-Landroid/bluetooth/BluetoothGattDescriptor;->setCharacteristic(Landroid/bluetooth/BluetoothGattCharacteristic;)V
-Landroid/bluetooth/BluetoothGattService;->mDevice:Landroid/bluetooth/BluetoothDevice;
-Landroid/bluetooth/BluetoothGattService;->setAdvertisePreferred(Z)V
-Landroid/bluetooth/BluetoothGattService;->setInstanceId(I)V
-Landroid/bluetooth/BluetoothHeadset;->ACTION_ACTIVE_DEVICE_CHANGED:Ljava/lang/String;
-Landroid/bluetooth/BluetoothHeadset;->close()V
-Landroid/bluetooth/BluetoothHeadset;->connectAudio()Z
-Landroid/bluetooth/BluetoothHeadset;->disconnectAudio()Z
-Landroid/bluetooth/BluetoothHeadset;->getActiveDevice()Landroid/bluetooth/BluetoothDevice;
-Landroid/bluetooth/BluetoothHeadset;->getAudioState(Landroid/bluetooth/BluetoothDevice;)I
-Landroid/bluetooth/BluetoothHeadset;->getPriority(Landroid/bluetooth/BluetoothDevice;)I
-Landroid/bluetooth/BluetoothHeadset;->isEnabled()Z
-Landroid/bluetooth/BluetoothHeadset;->setActiveDevice(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothHeadset;->startScoUsingVirtualVoiceCall()Z
-Landroid/bluetooth/BluetoothHeadset;->stopScoUsingVirtualVoiceCall()Z
-Landroid/bluetooth/BluetoothHeadsetClient;->acceptCall(Landroid/bluetooth/BluetoothDevice;I)Z
-Landroid/bluetooth/BluetoothHeadsetClient;->connect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothHeadsetClient;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothHeadsetClient;->getAudioState(Landroid/bluetooth/BluetoothDevice;)I
-Landroid/bluetooth/BluetoothHeadsetClient;->rejectCall(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothHeadsetClientCall;->getId()I
-Landroid/bluetooth/BluetoothHeadsetClientCall;->getNumber()Ljava/lang/String;
-Landroid/bluetooth/BluetoothHeadsetClientCall;->getState()I
-Landroid/bluetooth/BluetoothHeadsetClientCall;->isMultiParty()Z
-Landroid/bluetooth/BluetoothHeadsetClientCall;->isOutgoing()Z
-Landroid/bluetooth/BluetoothHearingAid;->ACTION_ACTIVE_DEVICE_CHANGED:Ljava/lang/String;
-Landroid/bluetooth/BluetoothHearingAid;->getActiveDevices()Ljava/util/List;
-Landroid/bluetooth/BluetoothHearingAid;->setActiveDevice(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothMap;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothMapClient;->sendMessage(Landroid/bluetooth/BluetoothDevice;[Landroid/net/Uri;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;)Z
-Landroid/bluetooth/BluetoothPan;-><init>(Landroid/content/Context;Landroid/bluetooth/BluetoothProfile$ServiceListener;)V
-Landroid/bluetooth/BluetoothPan;->close()V
-Landroid/bluetooth/BluetoothPan;->connect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothPan;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothPan;->doBind()Z
-Landroid/bluetooth/BluetoothPan;->isEnabled()Z
-Landroid/bluetooth/BluetoothPan;->isTetheringOn()Z
-Landroid/bluetooth/BluetoothPan;->isValidDevice(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothPan;->log(Ljava/lang/String;)V
-Landroid/bluetooth/BluetoothPan;->setBluetoothTethering(Z)V
-Landroid/bluetooth/BluetoothPbap;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothProfile;->A2DP_SINK:I
-Landroid/bluetooth/BluetoothProfile;->AVRCP_CONTROLLER:I
-Landroid/bluetooth/BluetoothProfile;->PAN:I
-Landroid/bluetooth/BluetoothProfile;->PRIORITY_AUTO_CONNECT:I
-Landroid/bluetooth/BluetoothProfile;->PRIORITY_UNDEFINED:I
-Landroid/bluetooth/BluetoothSap;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
-Landroid/bluetooth/BluetoothServerSocket;->mSocket:Landroid/bluetooth/BluetoothSocket;
-Landroid/bluetooth/BluetoothSocket;->EADDRINUSE:I
-Landroid/bluetooth/BluetoothSocket;->flush()V
-Landroid/bluetooth/BluetoothSocket;->mPfd:Landroid/os/ParcelFileDescriptor;
-Landroid/bluetooth/BluetoothSocket;->mPort:I
-Landroid/bluetooth/BluetoothSocket;->mSocket:Landroid/net/LocalSocket;
-Landroid/bluetooth/BluetoothUuid;->AdvAudioDist:Landroid/os/ParcelUuid;
-Landroid/bluetooth/BluetoothUuid;->AudioSink:Landroid/os/ParcelUuid;
-Landroid/bluetooth/BluetoothUuid;->containsAnyUuid([Landroid/os/ParcelUuid;[Landroid/os/ParcelUuid;)Z
-Landroid/bluetooth/BluetoothUuid;->Handsfree:Landroid/os/ParcelUuid;
-Landroid/bluetooth/BluetoothUuid;->Hogp:Landroid/os/ParcelUuid;
-Landroid/bluetooth/BluetoothUuid;->HSP:Landroid/os/ParcelUuid;
-Landroid/bluetooth/BluetoothUuid;->is16BitUuid(Landroid/os/ParcelUuid;)Z
-Landroid/bluetooth/BluetoothUuid;->is32BitUuid(Landroid/os/ParcelUuid;)Z
-Landroid/bluetooth/BluetoothUuid;->isAdvAudioDist(Landroid/os/ParcelUuid;)Z
-Landroid/bluetooth/BluetoothUuid;->isAudioSource(Landroid/os/ParcelUuid;)Z
-Landroid/bluetooth/BluetoothUuid;->isAvrcpTarget(Landroid/os/ParcelUuid;)Z
-Landroid/bluetooth/BluetoothUuid;->isUuidPresent([Landroid/os/ParcelUuid;Landroid/os/ParcelUuid;)Z
-Landroid/bluetooth/BluetoothUuid;->NAP:Landroid/os/ParcelUuid;
-Landroid/bluetooth/BluetoothUuid;->ObexObjectPush:Landroid/os/ParcelUuid;
-Landroid/bluetooth/BluetoothUuid;->PBAP_PSE:Landroid/os/ParcelUuid;
-Landroid/bluetooth/BluetoothUuid;->RESERVED_UUIDS:[Landroid/os/ParcelUuid;
 Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
 Landroid/bluetooth/IBluetooth$Stub$Proxy;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I
 Landroid/bluetooth/IBluetooth$Stub;-><init>()V
@@ -1249,114 +291,8 @@
 Landroid/bluetooth/IBluetoothManagerCallback$Stub;-><init>()V
 Landroid/bluetooth/IBluetoothPbap$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothPbap;
 Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;-><init>()V
-Landroid/bluetooth/le/ScanRecord;->parseFromBytes([B)Landroid/bluetooth/le/ScanRecord;
-Landroid/content/AsyncTaskLoader;->mExecutor:Ljava/util/concurrent/Executor;
-Landroid/content/AsyncTaskLoader;->waitForLoader()V
-Landroid/content/BroadcastReceiver$PendingResult;-><init>(ILjava/lang/String;Landroid/os/Bundle;IZZLandroid/os/IBinder;II)V
-Landroid/content/BroadcastReceiver$PendingResult;->mAbortBroadcast:Z
-Landroid/content/BroadcastReceiver$PendingResult;->mFinished:Z
-Landroid/content/BroadcastReceiver$PendingResult;->mFlags:I
-Landroid/content/BroadcastReceiver$PendingResult;->mInitialStickyHint:Z
-Landroid/content/BroadcastReceiver$PendingResult;->mOrderedHint:Z
-Landroid/content/BroadcastReceiver$PendingResult;->mResultCode:I
-Landroid/content/BroadcastReceiver$PendingResult;->mResultData:Ljava/lang/String;
-Landroid/content/BroadcastReceiver$PendingResult;->mResultExtras:Landroid/os/Bundle;
-Landroid/content/BroadcastReceiver$PendingResult;->mSendingUser:I
-Landroid/content/BroadcastReceiver$PendingResult;->mToken:Landroid/os/IBinder;
-Landroid/content/BroadcastReceiver$PendingResult;->mType:I
-Landroid/content/BroadcastReceiver;->getPendingResult()Landroid/content/BroadcastReceiver$PendingResult;
-Landroid/content/BroadcastReceiver;->mPendingResult:Landroid/content/BroadcastReceiver$PendingResult;
-Landroid/content/BroadcastReceiver;->setPendingResult(Landroid/content/BroadcastReceiver$PendingResult;)V
-Landroid/content/ClipboardManager;-><init>(Landroid/content/Context;Landroid/os/Handler;)V
-Landroid/content/ClipboardManager;->reportPrimaryClipChanged()V
-Landroid/content/ClipData$Item;->mUri:Landroid/net/Uri;
-Landroid/content/ClipData;->getIcon()Landroid/graphics/Bitmap;
-Landroid/content/ComponentName;->appendShortString(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/content/ComponentName;->printShortString(Ljava/io/PrintWriter;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/content/ContentProvider;->coerceToLocalContentProvider(Landroid/content/IContentProvider;)Landroid/content/ContentProvider;
-Landroid/content/ContentProvider;->mAuthorities:[Ljava/lang/String;
-Landroid/content/ContentProvider;->mAuthority:Ljava/lang/String;
-Landroid/content/ContentProvider;->maybeAddUserId(Landroid/net/Uri;I)Landroid/net/Uri;
-Landroid/content/ContentProvider;->mContext:Landroid/content/Context;
-Landroid/content/ContentProvider;->mPathPermissions:[Landroid/content/pm/PathPermission;
-Landroid/content/ContentProvider;->mReadPermission:Ljava/lang/String;
-Landroid/content/ContentProvider;->mWritePermission:Ljava/lang/String;
-Landroid/content/ContentProvider;->setAppOps(II)V
-Landroid/content/ContentProviderClient;->mContentProvider:Landroid/content/IContentProvider;
-Landroid/content/ContentProviderClient;->mPackageName:Ljava/lang/String;
-Landroid/content/ContentProviderNative;->asInterface(Landroid/os/IBinder;)Landroid/content/IContentProvider;
-Landroid/content/ContentProviderOperation;->getType()I
-Landroid/content/ContentProviderOperation;->mSelection:Ljava/lang/String;
-Landroid/content/ContentProviderOperation;->mType:I
-Landroid/content/ContentProviderOperation;->mUri:Landroid/net/Uri;
-Landroid/content/ContentProviderOperation;->TYPE_DELETE:I
-Landroid/content/ContentProviderOperation;->TYPE_INSERT:I
-Landroid/content/ContentProviderOperation;->TYPE_UPDATE:I
-Landroid/content/ContentResolver$OpenResourceIdResult;->id:I
-Landroid/content/ContentResolver$OpenResourceIdResult;->r:Landroid/content/res/Resources;
-Landroid/content/ContentResolver;->acquireExistingProvider(Landroid/content/Context;Ljava/lang/String;)Landroid/content/IContentProvider;
-Landroid/content/ContentResolver;->acquireExistingProvider(Landroid/net/Uri;)Landroid/content/IContentProvider;
-Landroid/content/ContentResolver;->acquireProvider(Landroid/content/Context;Ljava/lang/String;)Landroid/content/IContentProvider;
-Landroid/content/ContentResolver;->acquireProvider(Landroid/net/Uri;)Landroid/content/IContentProvider;
-Landroid/content/ContentResolver;->acquireProvider(Ljava/lang/String;)Landroid/content/IContentProvider;
-Landroid/content/ContentResolver;->acquireUnstableProvider(Landroid/content/Context;Ljava/lang/String;)Landroid/content/IContentProvider;
-Landroid/content/ContentResolver;->acquireUnstableProvider(Ljava/lang/String;)Landroid/content/IContentProvider;
-Landroid/content/ContentResolver;->getContentService()Landroid/content/IContentService;
-Landroid/content/ContentResolver;->getPackageName()Ljava/lang/String;
-Landroid/content/ContentResolver;->getResourceId(Landroid/net/Uri;)Landroid/content/ContentResolver$OpenResourceIdResult;
-Landroid/content/ContentResolver;->getSyncStatus(Landroid/accounts/Account;Ljava/lang/String;)Landroid/content/SyncStatusInfo;
-Landroid/content/ContentResolver;->getSyncStatusAsUser(Landroid/accounts/Account;Ljava/lang/String;I)Landroid/content/SyncStatusInfo;
-Landroid/content/ContentResolver;->mContext:Landroid/content/Context;
-Landroid/content/ContentResolver;->mPackageName:Ljava/lang/String;
-Landroid/content/ContentResolver;->releaseProvider(Landroid/content/IContentProvider;)Z
-Landroid/content/ContentResolver;->releaseUnstableProvider(Landroid/content/IContentProvider;)Z
-Landroid/content/ContentResolver;->sContentService:Landroid/content/IContentService;
-Landroid/content/ContentResolver;->SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS:I
-Landroid/content/ContentResolver;->SYNC_OBSERVER_TYPE_STATUS:I
-Landroid/content/ContentResolver;->takePersistableUriPermission(Ljava/lang/String;Landroid/net/Uri;I)V
-Landroid/content/ContentResolver;->unstableProviderDied(Landroid/content/IContentProvider;)V
-Landroid/content/ContentValues;-><init>(Ljava/util/HashMap;)V
-Landroid/content/ContentValues;->mValues:Ljava/util/HashMap;
-Landroid/content/Context;->bindServiceAsUser(Landroid/content/Intent;Landroid/content/ServiceConnection;ILandroid/os/Handler;Landroid/os/UserHandle;)Z
-Landroid/content/Context;->canStartActivityForResult()Z
-Landroid/content/Context;->checkPermission(Ljava/lang/String;IILandroid/os/IBinder;)I
-Landroid/content/Context;->COUNTRY_DETECTOR:Ljava/lang/String;
-Landroid/content/Context;->createApplicationContext(Landroid/content/pm/ApplicationInfo;I)Landroid/content/Context;
-Landroid/content/Context;->ETHERNET_SERVICE:Ljava/lang/String;
-Landroid/content/Context;->getBasePackageName()Ljava/lang/String;
-Landroid/content/Context;->getDisplay()Landroid/view/Display;
-Landroid/content/Context;->getSharedPrefsFile(Ljava/lang/String;)Ljava/io/File;
-Landroid/content/Context;->getThemeResId()I
-Landroid/content/Context;->sendBroadcast(Landroid/content/Intent;Ljava/lang/String;I)V
-Landroid/content/Context;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;I)V
-Landroid/content/Context;->sendOrderedBroadcast(Landroid/content/Intent;Ljava/lang/String;ILandroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V
-Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V
-Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/os/Bundle;Landroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V
-Landroid/content/Context;->startActivityAsUser(Landroid/content/Intent;Landroid/os/Bundle;Landroid/os/UserHandle;)V
-Landroid/content/Context;->startActivityForResult(Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;)V
-Landroid/content/Context;->STATUS_BAR_SERVICE:Ljava/lang/String;
-Landroid/content/ContextWrapper;->createApplicationContext(Landroid/content/pm/ApplicationInfo;I)Landroid/content/Context;
-Landroid/content/ContextWrapper;->getBasePackageName()Ljava/lang/String;
-Landroid/content/ContextWrapper;->getDisplay()Landroid/view/Display;
-Landroid/content/ContextWrapper;->mBase:Landroid/content/Context;
-Landroid/content/ContextWrapper;->registerReceiverAsUser(Landroid/content/BroadcastReceiver;Landroid/os/UserHandle;Landroid/content/IntentFilter;Ljava/lang/String;Landroid/os/Handler;)Landroid/content/Intent;
-Landroid/content/ContextWrapper;->startActivityAsUser(Landroid/content/Intent;Landroid/os/UserHandle;)V
-Landroid/content/ContextWrapper;->startForegroundServiceAsUser(Landroid/content/Intent;Landroid/os/UserHandle;)Landroid/content/ComponentName;
-Landroid/content/ContextWrapper;->startServiceAsUser(Landroid/content/Intent;Landroid/os/UserHandle;)Landroid/content/ComponentName;
-Landroid/content/CursorEntityIterator;-><init>(Landroid/database/Cursor;)V
-Landroid/content/CursorLoader;->mCancellationSignal:Landroid/os/CancellationSignal;
-Landroid/content/CursorLoader;->mObserver:Landroid/content/Loader$ForceLoadContentObserver;
-Landroid/content/Entity;->mSubValues:Ljava/util/ArrayList;
-Landroid/content/Entity;->mValues:Landroid/content/ContentValues;
 Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
-Landroid/content/IContentProvider;->bulkInsert(Ljava/lang/String;Landroid/net/Uri;[Landroid/content/ContentValues;)I
-Landroid/content/IContentProvider;->call(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;
-Landroid/content/IContentProvider;->delete(Ljava/lang/String;Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I
-Landroid/content/IContentProvider;->descriptor:Ljava/lang/String;
-Landroid/content/IContentProvider;->insert(Ljava/lang/String;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
-Landroid/content/IContentProvider;->QUERY_TRANSACTION:I
-Landroid/content/IContentProvider;->update(Ljava/lang/String;Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I
 Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IContentService$Stub;-><init>()V
 Landroid/content/IContentService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IContentService;
@@ -1373,29 +309,6 @@
 Landroid/content/IIntentReceiver;->performReceive(Landroid/content/Intent;ILjava/lang/String;Landroid/os/Bundle;ZZI)V
 Landroid/content/IIntentSender$Stub;-><init>()V
 Landroid/content/IIntentSender$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IIntentSender;
-Landroid/content/Intent;->ACTION_ALARM_CHANGED:Ljava/lang/String;
-Landroid/content/Intent;->ACTION_USER_SWITCHED:Ljava/lang/String;
-Landroid/content/Intent;->FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT:I
-Landroid/content/Intent;->getExtra(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
-Landroid/content/Intent;->isExcludingStopped()Z
-Landroid/content/Intent;->mExtras:Landroid/os/Bundle;
-Landroid/content/Intent;->parseCommandArgs(Landroid/os/ShellCommand;Landroid/content/Intent$CommandOptionHandler;)Landroid/content/Intent;
-Landroid/content/Intent;->prepareToLeaveProcess(Landroid/content/Context;)V
-Landroid/content/Intent;->printIntentArgsHelp(Ljava/io/PrintWriter;Ljava/lang/String;)V
-Landroid/content/Intent;->putExtra(Ljava/lang/String;Landroid/os/IBinder;)Landroid/content/Intent;
-Landroid/content/Intent;->setAllowFds(Z)V
-Landroid/content/Intent;->toInsecureString()Ljava/lang/String;
-Landroid/content/IntentFilter;->hasDataAuthority(Landroid/content/IntentFilter$AuthorityEntry;)Z
-Landroid/content/IntentFilter;->hasDataPath(Landroid/os/PatternMatcher;)Z
-Landroid/content/IntentFilter;->hasDataSchemeSpecificPart(Landroid/os/PatternMatcher;)Z
-Landroid/content/IntentFilter;->hasExactDataType(Ljava/lang/String;)Z
-Landroid/content/IntentFilter;->isVerified()Z
-Landroid/content/IntentFilter;->mActions:Ljava/util/ArrayList;
-Landroid/content/IntentFilter;->mOrder:I
-Landroid/content/IntentFilter;->setAutoVerify(Z)V
-Landroid/content/IntentSender;-><init>(Landroid/content/IIntentSender;)V
-Landroid/content/IntentSender;->getTarget()Landroid/content/IIntentSender;
-Landroid/content/IntentSender;->mTarget:Landroid/content/IIntentSender;
 Landroid/content/IOnPrimaryClipChangedListener$Stub;-><init>()V
 Landroid/content/IOnPrimaryClipChangedListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IOnPrimaryClipChangedListener;
 Landroid/content/IRestrictionsManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IRestrictionsManager;
@@ -1421,46 +334,17 @@
 Landroid/content/om/IOverlayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/om/IOverlayManager;
 Landroid/content/om/IOverlayManager;->getAllOverlays(I)Ljava/util/Map;
 Landroid/content/om/IOverlayManager;->getOverlayInfo(Ljava/lang/String;I)Landroid/content/om/OverlayInfo;
-Landroid/content/om/OverlayInfo;->isEnabled()Z
-Landroid/content/om/OverlayInfo;->packageName:Ljava/lang/String;
-Landroid/content/om/OverlayInfo;->state:I
-Landroid/content/om/OverlayInfo;->targetPackageName:Ljava/lang/String;
-Landroid/content/pm/ActivityInfo;->activityInfoConfigJavaToNative(I)I
-Landroid/content/pm/ActivityInfo;->FLAG_ALLOW_EMBEDDED:I
-Landroid/content/pm/ActivityInfo;->FLAG_SHOW_FOR_ALL_USERS:I
-Landroid/content/pm/ActivityInfo;->isResizeableMode(I)Z
-Landroid/content/pm/ActivityInfo;->resizeMode:I
-Landroid/content/pm/ActivityInfo;->supportsPictureInPicture()Z
-Landroid/content/pm/ApplicationInfo$DisplayNameComparator;->mPM:Landroid/content/pm/PackageManager;
-Landroid/content/pm/ApplicationInfo$DisplayNameComparator;->sCollator:Ljava/text/Collator;
-Landroid/content/pm/ApplicationInfo;->disableCompatibilityMode()V
-Landroid/content/pm/ApplicationInfo;->enabledSetting:I
-Landroid/content/pm/ApplicationInfo;->fullBackupContent:I
-Landroid/content/pm/ApplicationInfo;->getBaseResourcePath()Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->getCodePath()Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->hasRtlSupport()Z
-Landroid/content/pm/ApplicationInfo;->installLocation:I
-Landroid/content/pm/ApplicationInfo;->isForwardLocked()Z
-Landroid/content/pm/ApplicationInfo;->isPackageUnavailable(Landroid/content/pm/PackageManager;)Z
-Landroid/content/pm/ApplicationInfo;->nativeLibraryRootDir:Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->primaryCpuAbi:Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->privateFlags:I
-Landroid/content/pm/ApplicationInfo;->PRIVATE_FLAG_PRIVILEGED:I
-Landroid/content/pm/ApplicationInfo;->resourceDirs:[Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->scanPublicSourceDir:Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->scanSourceDir:Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->secondaryCpuAbi:Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->secondaryNativeLibraryDir:Ljava/lang/String;
-Landroid/content/pm/ApplicationInfo;->versionCode:I
-Landroid/content/pm/BaseParceledListSlice;->getList()Ljava/util/List;
-Landroid/content/pm/BaseParceledListSlice;->writeParcelableCreator(Ljava/lang/Object;Landroid/os/Parcel;)V
-Landroid/content/pm/ComponentInfo;->getComponentName()Landroid/content/ComponentName;
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->onRemoveCompleted(Ljava/lang/String;Z)V
 Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver;
+Landroid/content/pm/IPackageDataObserver$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/content/pm/IPackageDataObserver$Stub;->TRANSACTION_onRemoveCompleted:I
 Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V
 Landroid/content/pm/IPackageDeleteObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
+Landroid/content/pm/IPackageDeleteObserver$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/content/pm/IPackageDeleteObserver$Stub;->TRANSACTION_packageDeleted:I
 Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageDeleteObserver2$Stub;-><init>()V
@@ -1559,1043 +443,31 @@
 Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageStatsObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageStatsObserver;
+Landroid/content/pm/IPackageStatsObserver$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/content/pm/IPackageStatsObserver$Stub;->TRANSACTION_onGetStatsCompleted:I
 Landroid/content/pm/IShortcutService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IShortcutService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IShortcutService;
-Landroid/content/pm/LauncherActivityInfo;->mActivityInfo:Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/LauncherApps;->mPm:Landroid/content/pm/PackageManager;
-Landroid/content/pm/LauncherApps;->mService:Landroid/content/pm/ILauncherApps;
-Landroid/content/pm/LauncherApps;->startShortcut(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Rect;Landroid/os/Bundle;I)V
-Landroid/content/pm/PackageInfo;-><init>(Landroid/os/Parcel;)V
-Landroid/content/pm/PackageInfo;->coreApp:Z
-Landroid/content/pm/PackageInfo;->INSTALL_LOCATION_UNSPECIFIED:I
-Landroid/content/pm/PackageInfo;->overlayTarget:Ljava/lang/String;
-Landroid/content/pm/PackageInfoLite;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/content/pm/PackageInstaller$Session;->addProgress(F)V
-Landroid/content/pm/PackageInstaller$SessionInfo;-><init>()V
-Landroid/content/pm/PackageInstaller$SessionInfo;->active:Z
-Landroid/content/pm/PackageInstaller$SessionInfo;->appIcon:Landroid/graphics/Bitmap;
-Landroid/content/pm/PackageInstaller$SessionInfo;->appLabel:Ljava/lang/CharSequence;
-Landroid/content/pm/PackageInstaller$SessionInfo;->appPackageName:Ljava/lang/String;
-Landroid/content/pm/PackageInstaller$SessionInfo;->installerPackageName:Ljava/lang/String;
-Landroid/content/pm/PackageInstaller$SessionInfo;->mode:I
-Landroid/content/pm/PackageInstaller$SessionInfo;->progress:F
-Landroid/content/pm/PackageInstaller$SessionInfo;->resolvedBaseCodePath:Ljava/lang/String;
-Landroid/content/pm/PackageInstaller$SessionInfo;->sealed:Z
-Landroid/content/pm/PackageInstaller$SessionInfo;->sessionId:I
-Landroid/content/pm/PackageInstaller$SessionInfo;->sizeBytes:J
-Landroid/content/pm/PackageInstaller$SessionParams;->appIcon:Landroid/graphics/Bitmap;
-Landroid/content/pm/PackageInstaller$SessionParams;->appLabel:Ljava/lang/String;
-Landroid/content/pm/PackageInstaller$SessionParams;->appPackageName:Ljava/lang/String;
-Landroid/content/pm/PackageInstaller$SessionParams;->installFlags:I
-Landroid/content/pm/PackageInstaller$SessionParams;->mode:I
-Landroid/content/pm/PackageInstaller$SessionParams;->originatingUid:I
-Landroid/content/pm/PackageInstaller$SessionParams;->sizeBytes:J
-Landroid/content/pm/PackageItemInfo;->setForceSafeLabels(Z)V
-Landroid/content/pm/PackageManager;->addCrossProfileIntentFilter(Landroid/content/IntentFilter;III)V
-Landroid/content/pm/PackageManager;->addPreferredActivityAsUser(Landroid/content/IntentFilter;I[Landroid/content/ComponentName;Landroid/content/ComponentName;I)V
-Landroid/content/pm/PackageManager;->buildRequestPermissionsIntent([Ljava/lang/String;)Landroid/content/Intent;
-Landroid/content/pm/PackageManager;->clearApplicationUserData(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)V
-Landroid/content/pm/PackageManager;->clearCrossProfileIntentFilters(I)V
-Landroid/content/pm/PackageManager;->deleteApplicationCacheFiles(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)V
-Landroid/content/pm/PackageManager;->deleteApplicationCacheFilesAsUser(Ljava/lang/String;ILandroid/content/pm/IPackageDataObserver;)V
-Landroid/content/pm/PackageManager;->deletePackage(Ljava/lang/String;Landroid/content/pm/IPackageDeleteObserver;I)V
-Landroid/content/pm/PackageManager;->deletePackageAsUser(Ljava/lang/String;Landroid/content/pm/IPackageDeleteObserver;II)V
-Landroid/content/pm/PackageManager;->deleteStatusToString(I)Ljava/lang/String;
-Landroid/content/pm/PackageManager;->flushPackageRestrictionsAsUser(I)V
-Landroid/content/pm/PackageManager;->freeStorage(JLandroid/content/IntentSender;)V
-Landroid/content/pm/PackageManager;->freeStorage(Ljava/lang/String;JLandroid/content/IntentSender;)V
-Landroid/content/pm/PackageManager;->freeStorageAndNotify(JLandroid/content/pm/IPackageDataObserver;)V
-Landroid/content/pm/PackageManager;->freeStorageAndNotify(Ljava/lang/String;JLandroid/content/pm/IPackageDataObserver;)V
-Landroid/content/pm/PackageManager;->getApplicationHiddenSettingAsUser(Ljava/lang/String;Landroid/os/UserHandle;)Z
-Landroid/content/pm/PackageManager;->getApplicationInfoAsUser(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo;
-Landroid/content/pm/PackageManager;->getHomeActivities(Ljava/util/List;)Landroid/content/ComponentName;
-Landroid/content/pm/PackageManager;->getKeySetByAlias(Ljava/lang/String;Ljava/lang/String;)Landroid/content/pm/KeySet;
-Landroid/content/pm/PackageManager;->getMoveStatus(I)I
-Landroid/content/pm/PackageManager;->getPackageCandidateVolumes(Landroid/content/pm/ApplicationInfo;)Ljava/util/List;
-Landroid/content/pm/PackageManager;->getPackageCurrentVolume(Landroid/content/pm/ApplicationInfo;)Landroid/os/storage/VolumeInfo;
-Landroid/content/pm/PackageManager;->getPackageInfoAsUser(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
-Landroid/content/pm/PackageManager;->getPackageSizeInfo(Ljava/lang/String;Landroid/content/pm/IPackageStatsObserver;)V
-Landroid/content/pm/PackageManager;->getPackageSizeInfoAsUser(Ljava/lang/String;ILandroid/content/pm/IPackageStatsObserver;)V
-Landroid/content/pm/PackageManager;->getPackageUidAsUser(Ljava/lang/String;I)I
-Landroid/content/pm/PackageManager;->getPackageUidAsUser(Ljava/lang/String;II)I
-Landroid/content/pm/PackageManager;->getResourcesForApplicationAsUser(Ljava/lang/String;I)Landroid/content/res/Resources;
-Landroid/content/pm/PackageManager;->getSigningKeySet(Ljava/lang/String;)Landroid/content/pm/KeySet;
-Landroid/content/pm/PackageManager;->getUidForSharedUser(Ljava/lang/String;)I
-Landroid/content/pm/PackageManager;->getUserBadgeForDensity(Landroid/os/UserHandle;I)Landroid/graphics/drawable/Drawable;
-Landroid/content/pm/PackageManager;->getUserBadgeForDensityNoBackground(Landroid/os/UserHandle;I)Landroid/graphics/drawable/Drawable;
-Landroid/content/pm/PackageManager;->installExistingPackageAsUser(Ljava/lang/String;I)I
-Landroid/content/pm/PackageManager;->installStatusToString(I)Ljava/lang/String;
-Landroid/content/pm/PackageManager;->installStatusToString(ILjava/lang/String;)Ljava/lang/String;
-Landroid/content/pm/PackageManager;->INSTALL_REPLACE_EXISTING:I
-Landroid/content/pm/PackageManager;->isPackageAvailable(Ljava/lang/String;)Z
-Landroid/content/pm/PackageManager;->isPackageSuspendedForUser(Ljava/lang/String;I)Z
-Landroid/content/pm/PackageManager;->isSignedBy(Ljava/lang/String;Landroid/content/pm/KeySet;)Z
-Landroid/content/pm/PackageManager;->isSignedByExactly(Ljava/lang/String;Landroid/content/pm/KeySet;)Z
-Landroid/content/pm/PackageManager;->isUpgrade()Z
-Landroid/content/pm/PackageManager;->loadItemIcon(Landroid/content/pm/PackageItemInfo;Landroid/content/pm/ApplicationInfo;)Landroid/graphics/drawable/Drawable;
-Landroid/content/pm/PackageManager;->loadUnbadgedItemIcon(Landroid/content/pm/PackageItemInfo;Landroid/content/pm/ApplicationInfo;)Landroid/graphics/drawable/Drawable;
-Landroid/content/pm/PackageManager;->movePackage(Ljava/lang/String;Landroid/os/storage/VolumeInfo;)I
-Landroid/content/pm/PackageManager;->MOVE_EXTERNAL_MEDIA:I
-Landroid/content/pm/PackageManager;->MOVE_INTERNAL:I
-Landroid/content/pm/PackageManager;->NO_NATIVE_LIBRARIES:I
-Landroid/content/pm/PackageManager;->queryBroadcastReceivers(Landroid/content/Intent;II)Ljava/util/List;
-Landroid/content/pm/PackageManager;->queryBroadcastReceiversAsUser(Landroid/content/Intent;II)Ljava/util/List;
-Landroid/content/pm/PackageManager;->queryIntentActivitiesAsUser(Landroid/content/Intent;II)Ljava/util/List;
-Landroid/content/pm/PackageManager;->queryIntentContentProvidersAsUser(Landroid/content/Intent;II)Ljava/util/List;
-Landroid/content/pm/PackageManager;->queryIntentServicesAsUser(Landroid/content/Intent;II)Ljava/util/List;
-Landroid/content/pm/PackageManager;->registerMoveCallback(Landroid/content/pm/PackageManager$MoveCallback;Landroid/os/Handler;)V
-Landroid/content/pm/PackageManager;->replacePreferredActivity(Landroid/content/IntentFilter;I[Landroid/content/ComponentName;Landroid/content/ComponentName;)V
-Landroid/content/pm/PackageManager;->replacePreferredActivityAsUser(Landroid/content/IntentFilter;I[Landroid/content/ComponentName;Landroid/content/ComponentName;I)V
-Landroid/content/pm/PackageManager;->resolveActivityAsUser(Landroid/content/Intent;II)Landroid/content/pm/ResolveInfo;
-Landroid/content/pm/PackageManager;->resolveContentProviderAsUser(Ljava/lang/String;II)Landroid/content/pm/ProviderInfo;
-Landroid/content/pm/PackageManager;->setApplicationHiddenSettingAsUser(Ljava/lang/String;ZLandroid/os/UserHandle;)Z
-Landroid/content/pm/PackageManager;->shouldShowRequestPermissionRationale(Ljava/lang/String;)Z
-Landroid/content/pm/PackageManager;->unregisterMoveCallback(Landroid/content/pm/PackageManager$MoveCallback;)V
-Landroid/content/pm/PackageParser$Activity;->info:Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/PackageParser$ActivityIntentInfo;->activity:Landroid/content/pm/PackageParser$Activity;
-Landroid/content/pm/PackageParser$Component;->className:Ljava/lang/String;
-Landroid/content/pm/PackageParser$Component;->getComponentName()Landroid/content/ComponentName;
-Landroid/content/pm/PackageParser$Component;->intents:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Component;->metaData:Landroid/os/Bundle;
-Landroid/content/pm/PackageParser$Component;->owner:Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser$Instrumentation;->info:Landroid/content/pm/InstrumentationInfo;
-Landroid/content/pm/PackageParser$IntentInfo;-><init>()V
-Landroid/content/pm/PackageParser$IntentInfo;->banner:I
-Landroid/content/pm/PackageParser$IntentInfo;->hasDefault:Z
-Landroid/content/pm/PackageParser$IntentInfo;->icon:I
-Landroid/content/pm/PackageParser$IntentInfo;->labelRes:I
-Landroid/content/pm/PackageParser$IntentInfo;->logo:I
-Landroid/content/pm/PackageParser$IntentInfo;->nonLocalizedLabel:Ljava/lang/CharSequence;
-Landroid/content/pm/PackageParser$NewPermissionInfo;->name:Ljava/lang/String;
-Landroid/content/pm/PackageParser$NewPermissionInfo;->sdkVersion:I
-Landroid/content/pm/PackageParser$Package;-><init>(Ljava/lang/String;)V
-Landroid/content/pm/PackageParser$Package;->activities:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->applicationInfo:Landroid/content/pm/ApplicationInfo;
-Landroid/content/pm/PackageParser$Package;->configPreferences:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->installLocation:I
-Landroid/content/pm/PackageParser$Package;->instrumentation:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->mAppMetaData:Landroid/os/Bundle;
-Landroid/content/pm/PackageParser$Package;->mExtras:Ljava/lang/Object;
-Landroid/content/pm/PackageParser$Package;->mKeySetMapping:Landroid/util/ArrayMap;
-Landroid/content/pm/PackageParser$Package;->mPreferredOrder:I
-Landroid/content/pm/PackageParser$Package;->mSharedUserId:Ljava/lang/String;
-Landroid/content/pm/PackageParser$Package;->mSharedUserLabel:I
-Landroid/content/pm/PackageParser$Package;->mSigningDetails:Landroid/content/pm/PackageParser$SigningDetails;
-Landroid/content/pm/PackageParser$Package;->mUpgradeKeySets:Landroid/util/ArraySet;
-Landroid/content/pm/PackageParser$Package;->mVersionCode:I
-Landroid/content/pm/PackageParser$Package;->mVersionName:Ljava/lang/String;
-Landroid/content/pm/PackageParser$Package;->packageName:Ljava/lang/String;
-Landroid/content/pm/PackageParser$Package;->permissionGroups:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->permissions:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->protectedBroadcasts:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->providers:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->receivers:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->reqFeatures:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->requestedPermissions:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->services:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->setPackageName(Ljava/lang/String;)V
-Landroid/content/pm/PackageParser$Package;->usesLibraries:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$Package;->usesLibraryFiles:[Ljava/lang/String;
-Landroid/content/pm/PackageParser$Package;->usesOptionalLibraries:Ljava/util/ArrayList;
-Landroid/content/pm/PackageParser$PackageLite;->installLocation:I
-Landroid/content/pm/PackageParser$PackageLite;->packageName:Ljava/lang/String;
-Landroid/content/pm/PackageParser$Permission;-><init>(Landroid/content/pm/PackageParser$Package;Landroid/content/pm/PermissionInfo;)V
-Landroid/content/pm/PackageParser$Permission;->group:Landroid/content/pm/PackageParser$PermissionGroup;
-Landroid/content/pm/PackageParser$Permission;->info:Landroid/content/pm/PermissionInfo;
-Landroid/content/pm/PackageParser$Permission;->tree:Z
-Landroid/content/pm/PackageParser$PermissionGroup;->info:Landroid/content/pm/PermissionGroupInfo;
-Landroid/content/pm/PackageParser$Provider;-><init>(Landroid/content/pm/PackageParser$Provider;)V
-Landroid/content/pm/PackageParser$Provider;->info:Landroid/content/pm/ProviderInfo;
-Landroid/content/pm/PackageParser$Provider;->syncable:Z
-Landroid/content/pm/PackageParser$ProviderIntentInfo;->provider:Landroid/content/pm/PackageParser$Provider;
-Landroid/content/pm/PackageParser$Service;->info:Landroid/content/pm/ServiceInfo;
-Landroid/content/pm/PackageParser$ServiceIntentInfo;->service:Landroid/content/pm/PackageParser$Service;
-Landroid/content/pm/PackageParser$SigningDetails$Builder;-><init>()V
-Landroid/content/pm/PackageParser$SigningDetails$Builder;->build()Landroid/content/pm/PackageParser$SigningDetails;
-Landroid/content/pm/PackageParser$SigningDetails$Builder;->setPastSigningCertificates([Landroid/content/pm/Signature;)Landroid/content/pm/PackageParser$SigningDetails$Builder;
-Landroid/content/pm/PackageParser$SigningDetails$Builder;->setPastSigningCertificatesFlags([I)Landroid/content/pm/PackageParser$SigningDetails$Builder;
-Landroid/content/pm/PackageParser$SigningDetails$Builder;->setSignatures([Landroid/content/pm/Signature;)Landroid/content/pm/PackageParser$SigningDetails$Builder;
-Landroid/content/pm/PackageParser$SigningDetails$Builder;->setSignatureSchemeVersion(I)Landroid/content/pm/PackageParser$SigningDetails$Builder;
-Landroid/content/pm/PackageParser$SigningDetails;->signatures:[Landroid/content/pm/Signature;
-Landroid/content/pm/PackageParser;-><init>()V
-Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Ljava/io/File;Z)V
-Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Z)V
-Landroid/content/pm/PackageParser;->generateActivityInfo(Landroid/content/pm/PackageParser$Activity;ILandroid/content/pm/PackageUserState;I)Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/PackageParser;->generateApplicationInfo(Landroid/content/pm/PackageParser$Package;ILandroid/content/pm/PackageUserState;)Landroid/content/pm/ApplicationInfo;
-Landroid/content/pm/PackageParser;->generateApplicationInfo(Landroid/content/pm/PackageParser$Package;ILandroid/content/pm/PackageUserState;I)Landroid/content/pm/ApplicationInfo;
-Landroid/content/pm/PackageParser;->generateInstrumentationInfo(Landroid/content/pm/PackageParser$Instrumentation;I)Landroid/content/pm/InstrumentationInfo;
-Landroid/content/pm/PackageParser;->generatePackageInfo(Landroid/content/pm/PackageParser$Package;[IIJJLjava/util/Set;Landroid/content/pm/PackageUserState;)Landroid/content/pm/PackageInfo;
-Landroid/content/pm/PackageParser;->generatePackageInfo(Landroid/content/pm/PackageParser$Package;[IIJJLjava/util/Set;Landroid/content/pm/PackageUserState;I)Landroid/content/pm/PackageInfo;
-Landroid/content/pm/PackageParser;->generatePermissionGroupInfo(Landroid/content/pm/PackageParser$PermissionGroup;I)Landroid/content/pm/PermissionGroupInfo;
-Landroid/content/pm/PackageParser;->generatePermissionInfo(Landroid/content/pm/PackageParser$Permission;I)Landroid/content/pm/PermissionInfo;
-Landroid/content/pm/PackageParser;->generateProviderInfo(Landroid/content/pm/PackageParser$Provider;ILandroid/content/pm/PackageUserState;I)Landroid/content/pm/ProviderInfo;
-Landroid/content/pm/PackageParser;->generateServiceInfo(Landroid/content/pm/PackageParser$Service;ILandroid/content/pm/PackageUserState;I)Landroid/content/pm/ServiceInfo;
-Landroid/content/pm/PackageParser;->mCallback:Landroid/content/pm/PackageParser$Callback;
-Landroid/content/pm/PackageParser;->NEW_PERMISSIONS:[Landroid/content/pm/PackageParser$NewPermissionInfo;
-Landroid/content/pm/PackageParser;->parseBaseApk(Ljava/lang/String;Landroid/content/res/Resources;Landroid/content/res/XmlResourceParser;I[Ljava/lang/String;)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parseBaseApplication(Landroid/content/pm/PackageParser$Package;Landroid/content/res/Resources;Landroid/content/res/XmlResourceParser;I[Ljava/lang/String;)Z
-Landroid/content/pm/PackageParser;->parseMonolithicPackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;IZ)Landroid/content/pm/PackageParser$Package;
-Landroid/content/pm/PackageParser;->parsePackageLite(Ljava/io/File;I)Landroid/content/pm/PackageParser$PackageLite;
-Landroid/content/pm/PackageParser;->setCompatibilityModeEnabled(Z)V
-Landroid/content/pm/PackageParser;->setSeparateProcesses([Ljava/lang/String;)V
-Landroid/content/pm/PackageStats;->userHandle:I
-Landroid/content/pm/PackageUserState;-><init>()V
-Landroid/content/pm/ParceledListSlice;-><init>(Ljava/util/List;)V
-Landroid/content/pm/ParceledListSlice;->CREATOR:Landroid/os/Parcelable$ClassLoaderCreator;
-Landroid/content/pm/ParceledListSlice;->writeParcelableCreator(Landroid/os/Parcelable;Landroid/os/Parcel;)V
-Landroid/content/pm/PermissionInfo;->protectionToString(I)Ljava/lang/String;
-Landroid/content/pm/RegisteredServicesCache$ServiceInfo;->componentName:Landroid/content/ComponentName;
-Landroid/content/pm/RegisteredServicesCache$ServiceInfo;->type:Ljava/lang/Object;
-Landroid/content/pm/RegisteredServicesCache$ServiceInfo;->uid:I
-Landroid/content/pm/RegisteredServicesCache;-><init>(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/content/pm/XmlSerializerAndParser;)V
-Landroid/content/pm/ResolveInfo;->getComponentInfo()Landroid/content/pm/ComponentInfo;
-Landroid/content/pm/ResolveInfo;->handleAllWebDataURI:Z
-Landroid/content/pm/ResolveInfo;->system:Z
-Landroid/content/pm/ResolveInfo;->targetUserId:I
-Landroid/content/pm/ShortcutInfo;->getIcon()Landroid/graphics/drawable/Icon;
-Landroid/content/pm/ShortcutManager;->mService:Landroid/content/pm/IShortcutService;
-Landroid/content/pm/Signature;->getPublicKey()Ljava/security/PublicKey;
-Landroid/content/pm/UserInfo;-><init>(ILjava/lang/String;I)V
-Landroid/content/pm/UserInfo;-><init>(ILjava/lang/String;Ljava/lang/String;I)V
-Landroid/content/pm/UserInfo;->creationTime:J
-Landroid/content/pm/UserInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/content/pm/UserInfo;->flags:I
-Landroid/content/pm/UserInfo;->FLAG_PRIMARY:I
-Landroid/content/pm/UserInfo;->getUserHandle()Landroid/os/UserHandle;
-Landroid/content/pm/UserInfo;->guestToRemove:Z
-Landroid/content/pm/UserInfo;->iconPath:Ljava/lang/String;
-Landroid/content/pm/UserInfo;->id:I
-Landroid/content/pm/UserInfo;->isAdmin()Z
-Landroid/content/pm/UserInfo;->isEnabled()Z
-Landroid/content/pm/UserInfo;->isGuest()Z
-Landroid/content/pm/UserInfo;->isManagedProfile()Z
-Landroid/content/pm/UserInfo;->isPrimary()Z
-Landroid/content/pm/UserInfo;->isRestricted()Z
-Landroid/content/pm/UserInfo;->lastLoggedInTime:J
-Landroid/content/pm/UserInfo;->name:Ljava/lang/String;
-Landroid/content/pm/UserInfo;->partial:Z
-Landroid/content/pm/UserInfo;->profileGroupId:I
-Landroid/content/pm/UserInfo;->serialNumber:I
-Landroid/content/pm/VerifierInfo;-><init>(Ljava/lang/String;Ljava/security/PublicKey;)V
-Landroid/content/pm/XmlSerializerAndParser;->createFromXml(Lorg/xmlpull/v1/XmlPullParser;)Ljava/lang/Object;
-Landroid/content/pm/XmlSerializerAndParser;->writeAsXml(Ljava/lang/Object;Lorg/xmlpull/v1/XmlSerializer;)V
-Landroid/content/res/ApkAssets;->getAssetPath()Ljava/lang/String;
-Landroid/content/res/AssetFileDescriptor;->mFd:Landroid/os/ParcelFileDescriptor;
-Landroid/content/res/AssetFileDescriptor;->mLength:J
-Landroid/content/res/AssetFileDescriptor;->mStartOffset:J
-Landroid/content/res/AssetManager$AssetInputStream;->getAssetInt()I
-Landroid/content/res/AssetManager$AssetInputStream;->getNativeAsset()J
-Landroid/content/res/AssetManager;-><init>()V
-Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I
-Landroid/content/res/AssetManager;->addAssetPathAsSharedLibrary(Ljava/lang/String;)I
-Landroid/content/res/AssetManager;->addOverlayPath(Ljava/lang/String;)I
-Landroid/content/res/AssetManager;->applyStyle(JIILandroid/content/res/XmlBlock$Parser;[IJJ)V
-Landroid/content/res/AssetManager;->createTheme()J
-Landroid/content/res/AssetManager;->getApkAssets()[Landroid/content/res/ApkAssets;
-Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray;
-Landroid/content/res/AssetManager;->getGlobalAssetCount()I
-Landroid/content/res/AssetManager;->getGlobalAssetManagerCount()I
-Landroid/content/res/AssetManager;->getResourceBagText(II)Ljava/lang/CharSequence;
-Landroid/content/res/AssetManager;->getResourceEntryName(I)Ljava/lang/String;
-Landroid/content/res/AssetManager;->getResourceIdentifier(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
-Landroid/content/res/AssetManager;->getResourceName(I)Ljava/lang/String;
-Landroid/content/res/AssetManager;->getResourcePackageName(I)Ljava/lang/String;
-Landroid/content/res/AssetManager;->getResourceText(I)Ljava/lang/CharSequence;
-Landroid/content/res/AssetManager;->getResourceTypeName(I)Ljava/lang/String;
-Landroid/content/res/AssetManager;->getResourceValue(IILandroid/util/TypedValue;Z)Z
-Landroid/content/res/AssetManager;->getSystem()Landroid/content/res/AssetManager;
-Landroid/content/res/AssetManager;->isUpToDate()Z
-Landroid/content/res/AssetManager;->mObject:J
-Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;)Ljava/io/InputStream;
-Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;I)Ljava/io/InputStream;
-Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;)Ljava/io/InputStream;
-Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;I)Ljava/io/InputStream;
-Landroid/content/res/AssetManager;->resolveAttrs(JII[I[I[I[I)Z
-Landroid/content/res/AssetManager;->retrieveAttributes(Landroid/content/res/XmlBlock$Parser;[I[I[I)Z
-Landroid/content/res/AssetManager;->setConfiguration(IILjava/lang/String;IIIIIIIIIIIIIII)V
-Landroid/content/res/AssetManager;->sSystem:Landroid/content/res/AssetManager;
-Landroid/content/res/ColorStateList$ColorStateListFactory;-><init>(Landroid/content/res/ColorStateList;)V
-Landroid/content/res/ColorStateList;-><init>()V
-Landroid/content/res/ColorStateList;->canApplyTheme()Z
-Landroid/content/res/ColorStateList;->getColors()[I
-Landroid/content/res/ColorStateList;->getStates()[[I
-Landroid/content/res/ColorStateList;->mColors:[I
-Landroid/content/res/ColorStateList;->mDefaultColor:I
-Landroid/content/res/ColorStateList;->mFactory:Landroid/content/res/ColorStateList$ColorStateListFactory;
-Landroid/content/res/ColorStateList;->mStateSpecs:[[I
-Landroid/content/res/ColorStateList;->obtainForTheme(Landroid/content/res/Resources$Theme;)Landroid/content/res/ColorStateList;
-Landroid/content/res/ColorStateList;->onColorsChanged()V
-Landroid/content/res/CompatibilityInfo$Translator;->applicationInvertedScale:F
-Landroid/content/res/CompatibilityInfo$Translator;->applicationScale:F
-Landroid/content/res/CompatibilityInfo$Translator;->getTranslatedContentInsets(Landroid/graphics/Rect;)Landroid/graphics/Rect;
-Landroid/content/res/CompatibilityInfo$Translator;->translateCanvas(Landroid/graphics/Canvas;)V
-Landroid/content/res/CompatibilityInfo$Translator;->translateEventInScreenToAppWindow(Landroid/view/MotionEvent;)V
-Landroid/content/res/CompatibilityInfo$Translator;->translateRectInAppWindowToScreen(Landroid/graphics/Rect;)V
-Landroid/content/res/CompatibilityInfo$Translator;->translateRectInScreenToAppWindow(Landroid/graphics/Rect;)V
-Landroid/content/res/CompatibilityInfo$Translator;->translateRectInScreenToAppWinFrame(Landroid/graphics/Rect;)V
-Landroid/content/res/CompatibilityInfo$Translator;->translateRegionInWindowToScreen(Landroid/graphics/Region;)V
-Landroid/content/res/CompatibilityInfo$Translator;->translateWindowLayout(Landroid/view/WindowManager$LayoutParams;)V
-Landroid/content/res/CompatibilityInfo;-><init>()V
-Landroid/content/res/CompatibilityInfo;-><init>(Landroid/content/pm/ApplicationInfo;IIZ)V
-Landroid/content/res/CompatibilityInfo;->applicationScale:F
-Landroid/content/res/CompatibilityInfo;->computeCompatibleScaling(Landroid/util/DisplayMetrics;Landroid/util/DisplayMetrics;)F
-Landroid/content/res/CompatibilityInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/content/res/CompatibilityInfo;->DEFAULT_COMPATIBILITY_INFO:Landroid/content/res/CompatibilityInfo;
-Landroid/content/res/CompatibilityInfo;->getTranslator()Landroid/content/res/CompatibilityInfo$Translator;
-Landroid/content/res/CompatibilityInfo;->isScalingRequired()Z
-Landroid/content/res/CompatibilityInfo;->supportsScreen()Z
-Landroid/content/res/Configuration;->generateDelta(Landroid/content/res/Configuration;Landroid/content/res/Configuration;)Landroid/content/res/Configuration;
-Landroid/content/res/Configuration;->makeDefault()V
-Landroid/content/res/Configuration;->resourceQualifierString(Landroid/content/res/Configuration;)Ljava/lang/String;
-Landroid/content/res/Configuration;->seq:I
-Landroid/content/res/Configuration;->userSetLocale:Z
 Landroid/content/res/ConfigurationBoundResourceCache;-><init>()V
 Landroid/content/res/DrawableCache;-><init>()V
-Landroid/content/res/DrawableCache;->getInstance(JLandroid/content/res/Resources;Landroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
-Landroid/content/res/ObbInfo;->salt:[B
-Landroid/content/res/Resources$Theme;->mThemeImpl:Landroid/content/res/ResourcesImpl$ThemeImpl;
-Landroid/content/res/Resources$Theme;->resolveAttributes([I[I)Landroid/content/res/TypedArray;
-Landroid/content/res/Resources;-><init>()V
-Landroid/content/res/Resources;-><init>(Ljava/lang/ClassLoader;)V
-Landroid/content/res/Resources;->getCompatibilityInfo()Landroid/content/res/CompatibilityInfo;
-Landroid/content/res/Resources;->getDisplayAdjustments()Landroid/view/DisplayAdjustments;
-Landroid/content/res/Resources;->getDrawableInflater()Landroid/graphics/drawable/DrawableInflater;
-Landroid/content/res/Resources;->getFloat(I)F
-Landroid/content/res/Resources;->getImpl()Landroid/content/res/ResourcesImpl;
-Landroid/content/res/Resources;->getPreloadedDrawables()Landroid/util/LongSparseArray;
-Landroid/content/res/Resources;->loadDrawable(Landroid/util/TypedValue;IILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
-Landroid/content/res/Resources;->loadXmlResourceParser(ILjava/lang/String;)Landroid/content/res/XmlResourceParser;
-Landroid/content/res/Resources;->loadXmlResourceParser(Ljava/lang/String;IILjava/lang/String;)Landroid/content/res/XmlResourceParser;
-Landroid/content/res/Resources;->mClassLoader:Ljava/lang/ClassLoader;
-Landroid/content/res/Resources;->mDrawableInflater:Landroid/graphics/drawable/DrawableInflater;
-Landroid/content/res/Resources;->mResourcesImpl:Landroid/content/res/ResourcesImpl;
-Landroid/content/res/Resources;->mSystem:Landroid/content/res/Resources;
-Landroid/content/res/Resources;->mTmpValue:Landroid/util/TypedValue;
-Landroid/content/res/Resources;->mTypedArrayPool:Landroid/util/Pools$SynchronizedPool;
-Landroid/content/res/Resources;->selectDefaultTheme(II)I
-Landroid/content/res/Resources;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
-Landroid/content/res/Resources;->setImpl(Landroid/content/res/ResourcesImpl;)V
-Landroid/content/res/Resources;->updateSystemConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;Landroid/content/res/CompatibilityInfo;)V
-Landroid/content/res/ResourcesImpl;-><init>(Landroid/content/res/AssetManager;Landroid/util/DisplayMetrics;Landroid/content/res/Configuration;Landroid/view/DisplayAdjustments;)V
-Landroid/content/res/ResourcesImpl;->getAssets()Landroid/content/res/AssetManager;
-Landroid/content/res/ResourcesImpl;->getDisplayMetrics()Landroid/util/DisplayMetrics;
-Landroid/content/res/ResourcesImpl;->getValue(ILandroid/util/TypedValue;Z)V
-Landroid/content/res/ResourcesImpl;->mAccessLock:Ljava/lang/Object;
-Landroid/content/res/ResourcesImpl;->mAnimatorCache:Landroid/content/res/ConfigurationBoundResourceCache;
-Landroid/content/res/ResourcesImpl;->mAssets:Landroid/content/res/AssetManager;
-Landroid/content/res/ResourcesImpl;->mColorDrawableCache:Landroid/content/res/DrawableCache;
-Landroid/content/res/ResourcesImpl;->mConfiguration:Landroid/content/res/Configuration;
-Landroid/content/res/ResourcesImpl;->mDrawableCache:Landroid/content/res/DrawableCache;
-Landroid/content/res/ResourcesImpl;->mPreloading:Z
-Landroid/content/res/ResourcesImpl;->mStateListAnimatorCache:Landroid/content/res/ConfigurationBoundResourceCache;
-Landroid/content/res/ResourcesImpl;->sPreloadedColorDrawables:Landroid/util/LongSparseArray;
-Landroid/content/res/ResourcesImpl;->sPreloadedComplexColors:Landroid/util/LongSparseArray;
-Landroid/content/res/ResourcesImpl;->sPreloadedDrawables:[Landroid/util/LongSparseArray;
-Landroid/content/res/ResourcesImpl;->TRACE_FOR_MISS_PRELOAD:Z
-Landroid/content/res/ResourcesImpl;->TRACE_FOR_PRELOAD:Z
-Landroid/content/res/ResourcesKey;-><init>(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ILandroid/content/res/Configuration;Landroid/content/res/CompatibilityInfo;)V
-Landroid/content/res/ResourcesKey;->mResDir:Ljava/lang/String;
-Landroid/content/res/ResourcesKey;->mSplitResDirs:[Ljava/lang/String;
-Landroid/content/res/StringBlock;-><init>(JZ)V
-Landroid/content/res/StringBlock;->get(I)Ljava/lang/CharSequence;
-Landroid/content/res/ThemedResourceCache;->mThemedEntries:Landroid/util/ArrayMap;
-Landroid/content/res/ThemedResourceCache;->onConfigurationChange(I)V
-Landroid/content/res/TypedArray;->extractThemeAttrs()[I
-Landroid/content/res/TypedArray;->extractThemeAttrs([I)[I
-Landroid/content/res/TypedArray;->getNonConfigurationString(II)Ljava/lang/String;
-Landroid/content/res/TypedArray;->getValueAt(ILandroid/util/TypedValue;)Z
-Landroid/content/res/TypedArray;->mAssets:Landroid/content/res/AssetManager;
-Landroid/content/res/TypedArray;->mData:[I
-Landroid/content/res/TypedArray;->mIndices:[I
-Landroid/content/res/TypedArray;->mLength:I
-Landroid/content/res/TypedArray;->mMetrics:Landroid/util/DisplayMetrics;
-Landroid/content/res/TypedArray;->mRecycled:Z
-Landroid/content/res/TypedArray;->mResources:Landroid/content/res/Resources;
-Landroid/content/res/TypedArray;->mTheme:Landroid/content/res/Resources$Theme;
-Landroid/content/res/TypedArray;->mValue:Landroid/util/TypedValue;
-Landroid/content/res/TypedArray;->mXml:Landroid/content/res/XmlBlock$Parser;
-Landroid/content/res/XmlBlock$Parser;->mBlock:Landroid/content/res/XmlBlock;
-Landroid/content/res/XmlBlock$Parser;->mParseState:J
-Landroid/content/res/XmlBlock;-><init>([B)V
-Landroid/content/res/XmlBlock;->newParser()Landroid/content/res/XmlResourceParser;
-Landroid/content/RestrictionsManager;->mService:Landroid/content/IRestrictionsManager;
-Landroid/content/SearchRecentSuggestionsProvider;->mSuggestionProjection:[Ljava/lang/String;
-Landroid/content/SyncAdaptersCache;-><init>(Landroid/content/Context;)V
-Landroid/content/SyncAdapterType;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/content/SyncAdapterType;->allowParallelSyncs:Z
-Landroid/content/SyncAdapterType;->isAlwaysSyncable:Z
-Landroid/content/SyncAdapterType;->settingsActivity:Ljava/lang/String;
-Landroid/content/SyncAdapterType;->supportsUploading:Z
-Landroid/content/SyncAdapterType;->userVisible:Z
-Landroid/content/SyncContext;-><init>(Landroid/content/ISyncContext;)V
-Landroid/content/SyncContext;->setStatusText(Ljava/lang/String;)V
-Landroid/content/SyncInfo;-><init>(ILandroid/accounts/Account;Ljava/lang/String;J)V
-Landroid/content/SyncInfo;-><init>(Landroid/os/Parcel;)V
-Landroid/content/SyncInfo;->authorityId:I
-Landroid/content/SyncInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/content/SyncRequest;->mAccountToSync:Landroid/accounts/Account;
-Landroid/content/SyncRequest;->mAuthority:Ljava/lang/String;
-Landroid/content/SyncRequest;->mExtras:Landroid/os/Bundle;
-Landroid/content/SyncRequest;->mIsPeriodic:Z
-Landroid/content/SyncRequest;->mSyncRunTimeSecs:J
-Landroid/content/SyncStatusInfo;-><init>(I)V
-Landroid/content/SyncStatusInfo;-><init>(Landroid/os/Parcel;)V
-Landroid/content/SyncStatusInfo;->authorityId:I
-Landroid/content/SyncStatusInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/content/SyncStatusInfo;->ensurePeriodicSyncTimeSize(I)V
-Landroid/content/SyncStatusInfo;->getLastFailureMesgAsInt(I)I
-Landroid/content/SyncStatusInfo;->getPeriodicSyncTime(I)J
-Landroid/content/SyncStatusInfo;->initialFailureTime:J
-Landroid/content/SyncStatusInfo;->initialize:Z
-Landroid/content/SyncStatusInfo;->lastFailureMesg:Ljava/lang/String;
-Landroid/content/SyncStatusInfo;->lastFailureSource:I
-Landroid/content/SyncStatusInfo;->lastFailureTime:J
-Landroid/content/SyncStatusInfo;->lastSuccessSource:I
-Landroid/content/SyncStatusInfo;->lastSuccessTime:J
-Landroid/content/SyncStatusInfo;->pending:Z
-Landroid/content/SyncStatusInfo;->periodicSyncTimes:Ljava/util/ArrayList;
-Landroid/content/SyncStatusInfo;->removePeriodicSyncTime(I)V
-Landroid/content/SyncStatusInfo;->setPeriodicSyncTime(IJ)V
 Landroid/content/UndoManager;-><init>()V
-Landroid/content/UndoManager;->addOperation(Landroid/content/UndoOperation;I)V
-Landroid/content/UndoManager;->beginUpdate(Ljava/lang/CharSequence;)V
-Landroid/content/UndoManager;->commitState(Landroid/content/UndoOwner;)I
-Landroid/content/UndoManager;->countRedos([Landroid/content/UndoOwner;)I
-Landroid/content/UndoManager;->countUndos([Landroid/content/UndoOwner;)I
-Landroid/content/UndoManager;->endUpdate()V
-Landroid/content/UndoManager;->forgetRedos([Landroid/content/UndoOwner;I)I
-Landroid/content/UndoManager;->forgetUndos([Landroid/content/UndoOwner;I)I
-Landroid/content/UndoManager;->getLastOperation(Ljava/lang/Class;Landroid/content/UndoOwner;I)Landroid/content/UndoOperation;
-Landroid/content/UndoManager;->getOwner(Ljava/lang/String;Ljava/lang/Object;)Landroid/content/UndoOwner;
-Landroid/content/UndoManager;->isInUndo()Z
-Landroid/content/UndoManager;->redo([Landroid/content/UndoOwner;I)I
-Landroid/content/UndoManager;->restoreInstanceState(Landroid/os/Parcel;Ljava/lang/ClassLoader;)V
-Landroid/content/UndoManager;->saveInstanceState(Landroid/os/Parcel;)V
-Landroid/content/UndoManager;->setUndoLabel(Ljava/lang/CharSequence;)V
-Landroid/content/UndoManager;->undo([Landroid/content/UndoOwner;I)I
-Landroid/content/UndoOperation;-><init>(Landroid/content/UndoOwner;)V
-Landroid/content/UndoOperation;-><init>(Landroid/os/Parcel;Ljava/lang/ClassLoader;)V
-Landroid/content/UriMatcher;->mChildren:Ljava/util/ArrayList;
-Landroid/content/UriMatcher;->mText:Ljava/lang/String;
-Landroid/database/AbstractCursor;->mExtras:Landroid/os/Bundle;
-Landroid/database/AbstractCursor;->mNotifyUri:Landroid/net/Uri;
-Landroid/database/AbstractWindowedCursor;->clearOrCreateWindow(Ljava/lang/String;)V
-Landroid/database/AbstractWindowedCursor;->closeWindow()V
-Landroid/database/AbstractWindowedCursor;->onDeactivateOrClose()V
-Landroid/database/ContentObserver;->releaseContentObserver()Landroid/database/IContentObserver;
-Landroid/database/CursorWindow;->mWindowPtr:J
-Landroid/database/CursorWindow;->printStats()Ljava/lang/String;
-Landroid/database/CursorWindow;->sCursorWindowSize:I
-Landroid/database/CursorWindow;->sWindowToPidMap:Landroid/util/LongSparseArray;
-Landroid/database/CursorWrapper;->mCursor:Landroid/database/Cursor;
-Landroid/database/DatabaseUtils;->cursorPickFillWindowStartPosition(II)I
-Landroid/database/DatabaseUtils;->getTypeOfObject(Ljava/lang/Object;)I
 Landroid/database/IContentObserver$Stub;-><init>()V
 Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/database/IContentObserver;
 Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V
-Landroid/database/MatrixCursor;->data:[Ljava/lang/Object;
-Landroid/database/MatrixCursor;->get(I)Ljava/lang/Object;
-Landroid/database/MatrixCursor;->rowCount:I
-Landroid/database/sqlite/DatabaseObjectNotClosedException;-><init>()V
-Landroid/database/sqlite/SQLiteClosable;->mReferenceCount:I
-Landroid/database/sqlite/SQLiteCursor;->fillWindow(I)V
-Landroid/database/sqlite/SQLiteCursor;->mEditTable:Ljava/lang/String;
-Landroid/database/sqlite/SQLiteCursor;->mQuery:Landroid/database/sqlite/SQLiteQuery;
-Landroid/database/sqlite/SQLiteCustomFunction;->dispatchCallback([Ljava/lang/String;)V
-Landroid/database/sqlite/SQLiteCustomFunction;->name:Ljava/lang/String;
-Landroid/database/sqlite/SQLiteCustomFunction;->numArgs:I
-Landroid/database/sqlite/SQLiteDatabase;->beginTransaction(Landroid/database/sqlite/SQLiteTransactionListener;Z)V
-Landroid/database/sqlite/SQLiteDatabase;->collectDbStats(Ljava/util/ArrayList;)V
-Landroid/database/sqlite/SQLiteDatabase;->CONFLICT_VALUES:[Ljava/lang/String;
-Landroid/database/sqlite/SQLiteDatabase;->getActiveDatabases()Ljava/util/ArrayList;
-Landroid/database/sqlite/SQLiteDatabase;->getThreadSession()Landroid/database/sqlite/SQLiteSession;
-Landroid/database/sqlite/SQLiteDatabase;->mConfigurationLocked:Landroid/database/sqlite/SQLiteDatabaseConfiguration;
-Landroid/database/sqlite/SQLiteDatabase;->mConnectionPoolLocked:Landroid/database/sqlite/SQLiteConnectionPool;
-Landroid/database/sqlite/SQLiteDatabase;->mThreadSession:Ljava/lang/ThreadLocal;
-Landroid/database/sqlite/SQLiteDatabase;->openDatabase(Ljava/lang/String;Landroid/database/sqlite/SQLiteDatabase$OpenParams;)Landroid/database/sqlite/SQLiteDatabase;
-Landroid/database/sqlite/SQLiteDatabase;->reopenReadWrite()V
-Landroid/database/sqlite/SQLiteDatabaseConfiguration;->maxSqlCacheSize:I
-Landroid/database/sqlite/SQLiteOpenHelper;->mName:Ljava/lang/String;
-Landroid/database/sqlite/SQLiteProgram;->mBindArgs:[Ljava/lang/Object;
-Landroid/database/sqlite/SQLiteProgram;->mSql:Ljava/lang/String;
-Landroid/database/sqlite/SQLiteQueryBuilder;->computeProjection([Ljava/lang/String;)[Ljava/lang/String;
-Landroid/database/sqlite/SQLiteQueryBuilder;->mDistinct:Z
-Landroid/database/sqlite/SQLiteQueryBuilder;->mTables:Ljava/lang/String;
-Landroid/database/sqlite/SQLiteQueryBuilder;->mWhereClause:Ljava/lang/StringBuilder;
-Landroid/database/sqlite/SQLiteSession;->beginTransaction(ILandroid/database/sqlite/SQLiteTransactionListener;ILandroid/os/CancellationSignal;)V
-Landroid/database/sqlite/SQLiteStatement;-><init>(Landroid/database/sqlite/SQLiteDatabase;Ljava/lang/String;[Ljava/lang/Object;)V
-Landroid/database/sqlite/SqliteWrapper;->checkSQLiteException(Landroid/content/Context;Landroid/database/sqlite/SQLiteException;)V
-Landroid/database/sqlite/SqliteWrapper;->delete(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I
-Landroid/database/sqlite/SqliteWrapper;->update(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I
-Landroid/ddm/DdmHandleAppName;->getAppName()Ljava/lang/String;
-Landroid/ddm/DdmHandleAppName;->setAppName(Ljava/lang/String;I)V
-Landroid/filterfw/core/Filter;-><init>(Ljava/lang/String;)V
-Landroid/filterfw/core/Filter;->isAvailable(Ljava/lang/String;)Z
-Landroid/filterfw/core/Filter;->setInputValue(Ljava/lang/String;Ljava/lang/Object;)V
-Landroid/filterfw/core/FilterContext;->getFrameManager()Landroid/filterfw/core/FrameManager;
-Landroid/filterfw/core/FilterContext;->getGLEnvironment()Landroid/filterfw/core/GLEnvironment;
-Landroid/filterfw/core/FilterGraph;->getFilter(Ljava/lang/String;)Landroid/filterfw/core/Filter;
-Landroid/filterfw/core/FilterGraph;->tearDown(Landroid/filterfw/core/FilterContext;)V
-Landroid/filterfw/core/Frame;->getBitmap()Landroid/graphics/Bitmap;
-Landroid/filterfw/core/Frame;->getFormat()Landroid/filterfw/core/FrameFormat;
-Landroid/filterfw/core/Frame;->getTimestamp()J
-Landroid/filterfw/core/Frame;->release()Landroid/filterfw/core/Frame;
-Landroid/filterfw/core/Frame;->setInts([I)V
-Landroid/filterfw/core/Frame;->setTimestamp(J)V
-Landroid/filterfw/core/FrameFormat;->getHeight()I
-Landroid/filterfw/core/FrameFormat;->getTarget()I
-Landroid/filterfw/core/FrameFormat;->getWidth()I
-Landroid/filterfw/core/FrameFormat;->mutableCopy()Landroid/filterfw/core/MutableFrameFormat;
-Landroid/filterfw/core/FrameManager;->duplicateFrame(Landroid/filterfw/core/Frame;)Landroid/filterfw/core/Frame;
-Landroid/filterfw/core/FrameManager;->newBoundFrame(Landroid/filterfw/core/FrameFormat;IJ)Landroid/filterfw/core/Frame;
-Landroid/filterfw/core/FrameManager;->newFrame(Landroid/filterfw/core/FrameFormat;)Landroid/filterfw/core/Frame;
-Landroid/filterfw/core/GLEnvironment;->activate()V
-Landroid/filterfw/core/GLEnvironment;->activateSurfaceWithId(I)V
-Landroid/filterfw/core/GLEnvironment;->deactivate()V
-Landroid/filterfw/core/GLEnvironment;->isActive()Z
-Landroid/filterfw/core/GLEnvironment;->registerSurfaceFromMediaRecorder(Landroid/media/MediaRecorder;)I
-Landroid/filterfw/core/GLEnvironment;->setSurfaceTimestamp(J)V
-Landroid/filterfw/core/GLEnvironment;->swapBuffers()V
-Landroid/filterfw/core/GLEnvironment;->unregisterSurfaceId(I)V
-Landroid/filterfw/core/GLFrame;->generateMipMap()V
-Landroid/filterfw/core/GLFrame;->getTextureId()I
-Landroid/filterfw/core/GLFrame;->setBitmap(Landroid/graphics/Bitmap;)V
-Landroid/filterfw/core/GLFrame;->setTextureParameter(II)V
-Landroid/filterfw/core/GraphRunner;->getError()Ljava/lang/Exception;
-Landroid/filterfw/core/GraphRunner;->getGraph()Landroid/filterfw/core/FilterGraph;
-Landroid/filterfw/core/GraphRunner;->run()V
-Landroid/filterfw/core/GraphRunner;->setDoneCallback(Landroid/filterfw/core/GraphRunner$OnRunnerDoneListener;)V
-Landroid/filterfw/core/GraphRunner;->stop()V
-Landroid/filterfw/core/MutableFrameFormat;-><init>(II)V
-Landroid/filterfw/core/MutableFrameFormat;->setBytesPerSample(I)V
-Landroid/filterfw/core/MutableFrameFormat;->setDimensions(II)V
-Landroid/filterfw/core/Program;->process(Landroid/filterfw/core/Frame;Landroid/filterfw/core/Frame;)V
-Landroid/filterfw/core/Program;->process([Landroid/filterfw/core/Frame;Landroid/filterfw/core/Frame;)V
-Landroid/filterfw/core/Program;->setHostValue(Ljava/lang/String;Ljava/lang/Object;)V
-Landroid/filterfw/core/ShaderProgram;-><init>(Landroid/filterfw/core/FilterContext;Ljava/lang/String;)V
-Landroid/filterfw/core/ShaderProgram;->createIdentity(Landroid/filterfw/core/FilterContext;)Landroid/filterfw/core/ShaderProgram;
-Landroid/filterfw/core/ShaderProgram;->process([Landroid/filterfw/core/Frame;Landroid/filterfw/core/Frame;)V
-Landroid/filterfw/core/ShaderProgram;->setHostValue(Ljava/lang/String;Ljava/lang/Object;)V
-Landroid/filterfw/core/ShaderProgram;->setMaximumTileSize(I)V
-Landroid/filterfw/core/ShaderProgram;->setSourceRect(FFFF)V
-Landroid/filterfw/core/ShaderProgram;->setSourceRegion(Landroid/filterfw/geometry/Quad;)V
-Landroid/filterfw/format/ImageFormat;->create(I)Landroid/filterfw/core/MutableFrameFormat;
-Landroid/filterfw/format/ImageFormat;->create(II)Landroid/filterfw/core/MutableFrameFormat;
-Landroid/filterfw/format/ImageFormat;->create(IIII)Landroid/filterfw/core/MutableFrameFormat;
-Landroid/filterfw/geometry/Point;-><init>()V
-Landroid/filterfw/geometry/Point;-><init>(FF)V
-Landroid/filterfw/geometry/Point;->x:F
-Landroid/filterfw/geometry/Point;->y:F
-Landroid/filterfw/geometry/Quad;-><init>()V
-Landroid/filterfw/geometry/Quad;-><init>(Landroid/filterfw/geometry/Point;Landroid/filterfw/geometry/Point;Landroid/filterfw/geometry/Point;Landroid/filterfw/geometry/Point;)V
-Landroid/filterfw/geometry/Quad;->p0:Landroid/filterfw/geometry/Point;
-Landroid/filterfw/geometry/Quad;->p1:Landroid/filterfw/geometry/Point;
-Landroid/filterfw/geometry/Quad;->p2:Landroid/filterfw/geometry/Point;
-Landroid/filterfw/geometry/Quad;->p3:Landroid/filterfw/geometry/Point;
-Landroid/filterfw/GraphEnvironment;-><init>()V
-Landroid/filterfw/GraphEnvironment;->getRunner(II)Landroid/filterfw/core/GraphRunner;
-Landroid/filterfw/GraphEnvironment;->loadGraph(Landroid/content/Context;I)I
-Landroid/graphics/BaseCanvas;->mNativeCanvasWrapper:J
-Landroid/graphics/Bitmap$Config;->nativeInt:I
-Landroid/graphics/Bitmap$Config;->nativeToConfig(I)Landroid/graphics/Bitmap$Config;
-Landroid/graphics/Bitmap;-><init>(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;)V
-Landroid/graphics/Bitmap;->createAshmemBitmap()Landroid/graphics/Bitmap;
-Landroid/graphics/Bitmap;->createAshmemBitmap(Landroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;
-Landroid/graphics/Bitmap;->getDefaultDensity()I
-Landroid/graphics/Bitmap;->mHeight:I
-Landroid/graphics/Bitmap;->mNativePtr:J
-Landroid/graphics/Bitmap;->mNinePatchChunk:[B
-Landroid/graphics/Bitmap;->mNinePatchInsets:Landroid/graphics/NinePatch$InsetStruct;
-Landroid/graphics/Bitmap;->mWidth:I
-Landroid/graphics/Bitmap;->nativeReconfigure(JIIIZ)V
-Landroid/graphics/Bitmap;->reinit(IIZ)V
-Landroid/graphics/Bitmap;->scaleFromDensity(III)I
-Landroid/graphics/Bitmap;->setDefaultDensity(I)V
-Landroid/graphics/Bitmap;->setNinePatchChunk([B)V
-Landroid/graphics/BitmapFactory;->nativeDecodeAsset(JLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapFactory;->nativeDecodeByteArray([BIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapFactory;->nativeDecodeFileDescriptor(Ljava/io/FileDescriptor;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapFactory;->nativeDecodeStream(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapRegionDecoder;-><init>(J)V
-Landroid/graphics/BitmapRegionDecoder;->nativeNewInstance([BIIZ)Landroid/graphics/BitmapRegionDecoder;
-Landroid/graphics/BitmapShader;->mBitmap:Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapShader;->mTileX:I
-Landroid/graphics/BitmapShader;->mTileY:I
-Landroid/graphics/Camera;->native_instance:J
-Landroid/graphics/Canvas;-><init>(J)V
-Landroid/graphics/Canvas;->freeCaches()V
-Landroid/graphics/Canvas;->freeTextLayoutCaches()V
-Landroid/graphics/Canvas;->getGL()Ljavax/microedition/khronos/opengles/GL;
-Landroid/graphics/Canvas;->getNativeCanvasWrapper()J
-Landroid/graphics/Canvas;->mBitmap:Landroid/graphics/Bitmap;
-Landroid/graphics/Canvas;->release()V
-Landroid/graphics/Canvas;->setScreenDensity(I)V
-Landroid/graphics/CanvasProperty;->createFloat(F)Landroid/graphics/CanvasProperty;
-Landroid/graphics/CanvasProperty;->createPaint(Landroid/graphics/Paint;)Landroid/graphics/CanvasProperty;
-Landroid/graphics/ColorMatrixColorFilter;->mMatrix:Landroid/graphics/ColorMatrix;
-Landroid/graphics/ColorMatrixColorFilter;->setColorMatrix(Landroid/graphics/ColorMatrix;)V
-Landroid/graphics/ColorMatrixColorFilter;->setColorMatrixArray([F)V
-Landroid/graphics/drawable/AnimatedImageDrawable;->onAnimationEnd()V
-Landroid/graphics/drawable/AnimatedRotateDrawable;->setFramesCount(I)V
-Landroid/graphics/drawable/AnimatedRotateDrawable;->setFramesDuration(I)V
-Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;->mStateIds:Landroid/util/SparseIntArray;
-Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;->mTransitions:Landroid/util/LongSparseLongArray;
-Landroid/graphics/drawable/AnimatedStateListDrawable;->mState:Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;
-Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;->callOnFinished(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V
-Landroid/graphics/drawable/AnimatedVectorDrawable;->forceAnimationOnUI()V
-Landroid/graphics/drawable/AnimatedVectorDrawable;->mAnimatedVectorState:Landroid/graphics/drawable/AnimatedVectorDrawable$AnimatedVectorDrawableState;
-Landroid/graphics/drawable/AnimatedVectorDrawable;->mAnimatorSet:Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;
-Landroid/graphics/drawable/AnimationDrawable;->mCurFrame:I
-Landroid/graphics/drawable/BitmapDrawable;->getTint()Landroid/content/res/ColorStateList;
-Landroid/graphics/drawable/BitmapDrawable;->getTintMode()Landroid/graphics/PorterDuff$Mode;
-Landroid/graphics/drawable/BitmapDrawable;->mBitmapState:Landroid/graphics/drawable/BitmapDrawable$BitmapState;
-Landroid/graphics/drawable/BitmapDrawable;->mTargetDensity:I
-Landroid/graphics/drawable/BitmapDrawable;->setBitmap(Landroid/graphics/Bitmap;)V
-Landroid/graphics/drawable/ClipDrawable;->mState:Landroid/graphics/drawable/ClipDrawable$ClipState;
-Landroid/graphics/drawable/ColorDrawable$ColorState;->mUseColor:I
-Landroid/graphics/drawable/ColorDrawable;->mPaint:Landroid/graphics/Paint;
-Landroid/graphics/drawable/Drawable;->inflateWithAttributes(Landroid/content/res/Resources;Lorg/xmlpull/v1/XmlPullParser;Landroid/content/res/TypedArray;I)V
-Landroid/graphics/drawable/Drawable;->mCallback:Ljava/lang/ref/WeakReference;
-Landroid/graphics/drawable/Drawable;->mSrcDensityOverride:I
-Landroid/graphics/drawable/Drawable;->parseTintMode(ILandroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuff$Mode;
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;-><init>(Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;Landroid/graphics/drawable/DrawableContainer;Landroid/content/res/Resources;)V
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mConstantPadding:Landroid/graphics/Rect;
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mDrawables:[Landroid/graphics/drawable/Drawable;
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mHasColorFilter:Z
-Landroid/graphics/drawable/DrawableContainer;->mDrawableContainerState:Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;
-Landroid/graphics/drawable/DrawableContainer;->mLastDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/graphics/drawable/DrawableInflater;->mClassLoader:Ljava/lang/ClassLoader;
-Landroid/graphics/drawable/DrawableWrapper;->mState:Landroid/graphics/drawable/DrawableWrapper$DrawableWrapperState;
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mAngle:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mGradient:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mGradientColors:[I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mHeight:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mInnerRadius:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mInnerRadiusRatio:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mOrientation:Landroid/graphics/drawable/GradientDrawable$Orientation;
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mPadding:Landroid/graphics/Rect;
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mPositions:[F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mRadius:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mRadiusArray:[F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mShape:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mSolidColors:Landroid/content/res/ColorStateList;
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mStrokeDashGap:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mStrokeDashWidth:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mStrokeWidth:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mThickness:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mThicknessRatio:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mWidth:I
-Landroid/graphics/drawable/GradientDrawable;->mFillPaint:Landroid/graphics/Paint;
-Landroid/graphics/drawable/GradientDrawable;->mGradientState:Landroid/graphics/drawable/GradientDrawable$GradientState;
-Landroid/graphics/drawable/GradientDrawable;->mPadding:Landroid/graphics/Rect;
-Landroid/graphics/drawable/GradientDrawable;->mStrokePaint:Landroid/graphics/Paint;
-Landroid/graphics/drawable/Icon;->createWithResource(Landroid/content/res/Resources;I)Landroid/graphics/drawable/Icon;
-Landroid/graphics/drawable/Icon;->getBitmap()Landroid/graphics/Bitmap;
-Landroid/graphics/drawable/Icon;->getDataBytes()[B
-Landroid/graphics/drawable/Icon;->getDataLength()I
-Landroid/graphics/drawable/Icon;->getDataOffset()I
-Landroid/graphics/drawable/Icon;->getResources()Landroid/content/res/Resources;
-Landroid/graphics/drawable/Icon;->hasTint()Z
-Landroid/graphics/drawable/Icon;->mString1:Ljava/lang/String;
-Landroid/graphics/drawable/Icon;->mType:I
-Landroid/graphics/drawable/InsetDrawable;->mState:Landroid/graphics/drawable/InsetDrawable$InsetState;
-Landroid/graphics/drawable/LayerDrawable$ChildDrawable;->mDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/graphics/drawable/LayerDrawable$LayerState;->mChildren:[Landroid/graphics/drawable/LayerDrawable$ChildDrawable;
-Landroid/graphics/drawable/LayerDrawable;->addLayer(Landroid/graphics/drawable/LayerDrawable$ChildDrawable;)I
-Landroid/graphics/drawable/LayerDrawable;->ensurePadding()V
-Landroid/graphics/drawable/LayerDrawable;->mLayerState:Landroid/graphics/drawable/LayerDrawable$LayerState;
-Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;->mNinePatch:Landroid/graphics/NinePatch;
-Landroid/graphics/drawable/NinePatchDrawable;->mNinePatchState:Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;
-Landroid/graphics/drawable/RippleDrawable$RippleState;->mColor:Landroid/content/res/ColorStateList;
-Landroid/graphics/drawable/RippleDrawable;->getRipplePaint()Landroid/graphics/Paint;
-Landroid/graphics/drawable/RippleDrawable;->mDensity:I
-Landroid/graphics/drawable/RippleDrawable;->mState:Landroid/graphics/drawable/RippleDrawable$RippleState;
-Landroid/graphics/drawable/RippleDrawable;->setForceSoftware(Z)V
-Landroid/graphics/drawable/RotateDrawable;->mState:Landroid/graphics/drawable/RotateDrawable$RotateState;
-Landroid/graphics/drawable/ScaleDrawable;->mState:Landroid/graphics/drawable/ScaleDrawable$ScaleState;
-Landroid/graphics/drawable/StateListDrawable$StateListState;->addStateSet([ILandroid/graphics/drawable/Drawable;)I
-Landroid/graphics/drawable/StateListDrawable;->extractStateSet(Landroid/util/AttributeSet;)[I
-Landroid/graphics/drawable/StateListDrawable;->mStateListState:Landroid/graphics/drawable/StateListDrawable$StateListState;
-Landroid/graphics/drawable/StateListDrawable;->updateStateFromTypedArray(Landroid/content/res/TypedArray;)V
-Landroid/graphics/drawable/TransitionDrawable;->mAlpha:I
-Landroid/graphics/drawable/TransitionDrawable;->mCrossFade:Z
-Landroid/graphics/drawable/TransitionDrawable;->mTo:I
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setPivotX(F)V
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setPivotY(F)V
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setRotation(F)V
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setTranslateX(F)V
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setTranslateY(F)V
-Landroid/graphics/drawable/VectorDrawable;->getTargetByName(Ljava/lang/String;)Ljava/lang/Object;
-Landroid/graphics/drawable/VectorDrawable;->mTintFilter:Landroid/graphics/PorterDuffColorFilter;
-Landroid/graphics/drawable/VectorDrawable;->setAllowCaching(Z)V
-Landroid/graphics/FontFamily;-><init>()V
-Landroid/graphics/FontFamily;-><init>([Ljava/lang/String;I)V
-Landroid/graphics/FontFamily;->abortCreation()V
-Landroid/graphics/FontFamily;->addFontFromAssetManager(Landroid/content/res/AssetManager;Ljava/lang/String;IZIII[Landroid/graphics/fonts/FontVariationAxis;)Z
-Landroid/graphics/FontFamily;->addFontFromBuffer(Ljava/nio/ByteBuffer;I[Landroid/graphics/fonts/FontVariationAxis;II)Z
-Landroid/graphics/FontFamily;->freeze()Z
-Landroid/graphics/FontFamily;->mNativePtr:J
-Landroid/graphics/FontListParser;->parse(Ljava/io/InputStream;)Landroid/text/FontConfig;
-Landroid/graphics/fonts/FontVariationAxis;->mStyleValue:F
-Landroid/graphics/fonts/FontVariationAxis;->mTag:I
-Landroid/graphics/GraphicBuffer;-><init>(IIIIJ)V
-Landroid/graphics/GraphicBuffer;->createFromExisting(IIIIJ)Landroid/graphics/GraphicBuffer;
-Landroid/graphics/GraphicBuffer;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/graphics/GraphicBuffer;->mNativeObject:J
-Landroid/graphics/ImageDecoder;->postProcessAndRelease(Landroid/graphics/Canvas;)I
-Landroid/graphics/ImageFormat;->Y8:I
-Landroid/graphics/LightingColorFilter;->setColorAdd(I)V
-Landroid/graphics/LightingColorFilter;->setColorMultiply(I)V
-Landroid/graphics/LinearGradient;->mColor0:I
-Landroid/graphics/LinearGradient;->mColor1:I
-Landroid/graphics/LinearGradient;->mColors:[I
-Landroid/graphics/LinearGradient;->mPositions:[F
-Landroid/graphics/LinearGradient;->mTileMode:Landroid/graphics/Shader$TileMode;
-Landroid/graphics/LinearGradient;->mX0:F
-Landroid/graphics/LinearGradient;->mX1:F
-Landroid/graphics/LinearGradient;->mY0:F
-Landroid/graphics/LinearGradient;->mY1:F
-Landroid/graphics/Matrix;->IDENTITY_MATRIX:Landroid/graphics/Matrix;
-Landroid/graphics/Matrix;->native_instance:J
-Landroid/graphics/Movie;-><init>(J)V
-Landroid/graphics/Movie;->mNativeMovie:J
-Landroid/graphics/NinePatch$InsetStruct;-><init>(IIIIIIIIFIF)V
-Landroid/graphics/NinePatch;->mBitmap:Landroid/graphics/Bitmap;
-Landroid/graphics/NinePatch;->mNativeChunk:J
-Landroid/graphics/Outline;->mRect:Landroid/graphics/Rect;
-Landroid/graphics/Paint;->getNativeInstance()J
-Landroid/graphics/Paint;->getTextRunAdvances([CIIIIZ[FI)F
-Landroid/graphics/Paint;->getTextRunCursor([CIIIII)I
-Landroid/graphics/Paint;->mNativePaint:J
-Landroid/graphics/Paint;->mTypeface:Landroid/graphics/Typeface;
-Landroid/graphics/Paint;->setCompatibilityScaling(F)V
-Landroid/graphics/Paint;->setHyphenEdit(I)V
-Landroid/graphics/Path;->isSimplePath:Z
-Landroid/graphics/Path;->rects:Landroid/graphics/Region;
-Landroid/graphics/pdf/PdfRenderer;->doClose()V
-Landroid/graphics/pdf/PdfRenderer;->mCurrentPage:Landroid/graphics/pdf/PdfRenderer$Page;
-Landroid/graphics/Picture;->mNativePicture:J
-Landroid/graphics/PorterDuff$Mode;->nativeInt:I
-Landroid/graphics/PorterDuffColorFilter;->getColor()I
-Landroid/graphics/PorterDuffColorFilter;->getMode()Landroid/graphics/PorterDuff$Mode;
-Landroid/graphics/RadialGradient;->mCenterColor:I
-Landroid/graphics/RadialGradient;->mColors:[I
-Landroid/graphics/RadialGradient;->mEdgeColor:I
-Landroid/graphics/RadialGradient;->mPositions:[F
-Landroid/graphics/RadialGradient;->mRadius:F
-Landroid/graphics/RadialGradient;->mTileMode:Landroid/graphics/Shader$TileMode;
-Landroid/graphics/RadialGradient;->mX:F
-Landroid/graphics/RadialGradient;->mY:F
-Landroid/graphics/Rect;->printShortString(Ljava/io/PrintWriter;)V
-Landroid/graphics/Rect;->scale(F)V
-Landroid/graphics/Region$Op;->nativeInt:I
-Landroid/graphics/Region;-><init>(JI)V
-Landroid/graphics/Region;->mNativeRegion:J
-Landroid/graphics/Region;->recycle()V
-Landroid/graphics/Region;->scale(F)V
-Landroid/graphics/Shader$TileMode;->nativeInt:I
-Landroid/graphics/SurfaceTexture;->mFrameAvailableListener:J
-Landroid/graphics/SurfaceTexture;->mOnFrameAvailableHandler:Landroid/os/Handler;
-Landroid/graphics/SurfaceTexture;->mProducer:J
-Landroid/graphics/SurfaceTexture;->mSurfaceTexture:J
-Landroid/graphics/SurfaceTexture;->nativeDetachFromGLContext()I
-Landroid/graphics/SurfaceTexture;->postEventFromNative(Ljava/lang/ref/WeakReference;)V
-Landroid/graphics/SweepGradient;->mColor0:I
-Landroid/graphics/SweepGradient;->mColor1:I
-Landroid/graphics/SweepGradient;->mColors:[I
-Landroid/graphics/SweepGradient;->mCx:F
-Landroid/graphics/SweepGradient;->mCy:F
-Landroid/graphics/SweepGradient;->mPositions:[F
-Landroid/graphics/TableMaskFilter;->CreateClipTable(II)Landroid/graphics/TableMaskFilter;
-Landroid/graphics/TemporaryBuffer;->obtain(I)[C
-Landroid/graphics/TemporaryBuffer;->recycle([C)V
-Landroid/graphics/Typeface;-><init>(J)V
-Landroid/graphics/Typeface;->createFromFamilies([Landroid/graphics/FontFamily;)Landroid/graphics/Typeface;
-Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;II)Landroid/graphics/Typeface;
-Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;Ljava/lang/String;II)Landroid/graphics/Typeface;
-Landroid/graphics/Typeface;->mStyle:I
-Landroid/graphics/Typeface;->nativeCreateFromArray([JII)J
-Landroid/graphics/Typeface;->nativeCreateWeightAlias(JI)J
-Landroid/graphics/Typeface;->native_instance:J
-Landroid/graphics/Typeface;->sDefaults:[Landroid/graphics/Typeface;
-Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V
-Landroid/graphics/Typeface;->sSystemFallbackMap:Ljava/util/Map;
-Landroid/graphics/Typeface;->sSystemFontMap:Ljava/util/Map;
-Landroid/graphics/Xfermode;->porterDuffMode:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_GOOD:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_IMAGER_DIRTY:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_INSUFFICIENT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_PARTIAL:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_TOO_FAST:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_TOO_SLOW:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_CANCELED:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_HW_NOT_PRESENT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_HW_UNAVAILABLE:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_LOCKOUT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_LOCKOUT_PERMANENT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_NO_BIOMETRICS:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_NO_SPACE:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_TIMEOUT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_UNABLE_TO_PROCESS:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_USER_CANCELED:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_VENDOR:I
 Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_VENDOR_BASE:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_GOOD:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_IMAGER_DIRTY:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_INSUFFICIENT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_PARTIAL:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_TOO_FAST:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_TOO_SLOW:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_CANCELED:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_HW_NOT_PRESENT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_HW_UNAVAILABLE:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_LOCKOUT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_LOCKOUT_PERMANENT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_NO_FINGERPRINTS:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_NO_SPACE:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_TIMEOUT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_UNABLE_TO_PROCESS:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_USER_CANCELED:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_VENDOR:I
 Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_VENDOR_BASE:I
-Landroid/hardware/Camera$Parameters;->copyFrom(Landroid/hardware/Camera$Parameters;)V
-Landroid/hardware/Camera$Parameters;->dump()V
-Landroid/hardware/Camera$Parameters;->splitArea(Ljava/lang/String;)Ljava/util/ArrayList;
-Landroid/hardware/camera2/CameraCharacteristics$Key;-><init>(Ljava/lang/String;Landroid/hardware/camera2/utils/TypeReference;)V
-Landroid/hardware/camera2/CameraCharacteristics$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
-Landroid/hardware/camera2/CameraCharacteristics$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
-Landroid/hardware/camera2/CameraCharacteristics$Key;->getNativeKey()Landroid/hardware/camera2/impl/CameraMetadataNative$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->CONTROL_MAX_REGIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->LED_AVAILABLE_LEDS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->LENS_INFO_SHADING_MAP_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->LOGICAL_MULTI_CAMERA_PHYSICAL_IDS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->mProperties:Landroid/hardware/camera2/impl/CameraMetadataNative;
-Landroid/hardware/camera2/CameraCharacteristics;->QUIRKS_USE_PARTIAL_RESULT:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->REQUEST_AVAILABLE_CHARACTERISTICS_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->REQUEST_AVAILABLE_REQUEST_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->REQUEST_AVAILABLE_RESULT_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->REQUEST_AVAILABLE_SESSION_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->REQUEST_MAX_NUM_OUTPUT_STREAMS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_FORMATS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_JPEG_MIN_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_JPEG_SIZES:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_PROCESSED_SIZES:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CameraCharacteristics;->SCALER_AVAILABLE_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;
-Landroid/hardware/camera2/CaptureRequest$Builder;->setPartOfCHSRequestList(Z)V
-Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Landroid/hardware/camera2/utils/TypeReference;)V
-Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
-Landroid/hardware/camera2/CaptureRequest$Key;->getNativeKey()Landroid/hardware/camera2/impl/CameraMetadataNative$Key;
-Landroid/hardware/camera2/CaptureRequest;->getTargets()Ljava/util/Collection;
-Landroid/hardware/camera2/CaptureRequest;->JPEG_GPS_COORDINATES:Landroid/hardware/camera2/CaptureRequest$Key;
-Landroid/hardware/camera2/CaptureRequest;->JPEG_GPS_PROCESSING_METHOD:Landroid/hardware/camera2/CaptureRequest$Key;
-Landroid/hardware/camera2/CaptureRequest;->JPEG_GPS_TIMESTAMP:Landroid/hardware/camera2/CaptureRequest$Key;
-Landroid/hardware/camera2/CaptureRequest;->LED_TRANSMIT:Landroid/hardware/camera2/CaptureRequest$Key;
-Landroid/hardware/camera2/CaptureRequest;->mLogicalCameraSettings:Landroid/hardware/camera2/impl/CameraMetadataNative;
-Landroid/hardware/camera2/CaptureRequest;->REQUEST_ID:Landroid/hardware/camera2/CaptureRequest$Key;
-Landroid/hardware/camera2/CaptureRequest;->TONEMAP_CURVE_BLUE:Landroid/hardware/camera2/CaptureRequest$Key;
-Landroid/hardware/camera2/CaptureRequest;->TONEMAP_CURVE_GREEN:Landroid/hardware/camera2/CaptureRequest$Key;
-Landroid/hardware/camera2/CaptureRequest;->TONEMAP_CURVE_RED:Landroid/hardware/camera2/CaptureRequest$Key;
-Landroid/hardware/camera2/CaptureResult$Key;-><init>(Ljava/lang/String;Landroid/hardware/camera2/utils/TypeReference;)V
-Landroid/hardware/camera2/CaptureResult$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
-Landroid/hardware/camera2/CaptureResult$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
-Landroid/hardware/camera2/CaptureResult$Key;->getNativeKey()Landroid/hardware/camera2/impl/CameraMetadataNative$Key;
-Landroid/hardware/camera2/CaptureResult;->JPEG_GPS_COORDINATES:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->JPEG_GPS_PROCESSING_METHOD:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->JPEG_GPS_TIMESTAMP:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->LED_TRANSMIT:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->mResults:Landroid/hardware/camera2/impl/CameraMetadataNative;
-Landroid/hardware/camera2/CaptureResult;->QUIRKS_PARTIAL_RESULT:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->REQUEST_FRAME_COUNT:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->REQUEST_ID:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_FACE_IDS:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_FACE_LANDMARKS:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_FACE_RECTANGLES:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_FACE_SCORES:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_LENS_SHADING_MAP:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_OIS_TIMESTAMPS:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_OIS_X_SHIFTS:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_OIS_Y_SHIFTS:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_PREDICTED_COLOR_GAINS:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->STATISTICS_PREDICTED_COLOR_TRANSFORM:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->SYNC_FRAME_NUMBER:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->TONEMAP_CURVE_BLUE:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->TONEMAP_CURVE_GREEN:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/CaptureResult;->TONEMAP_CURVE_RED:Landroid/hardware/camera2/CaptureResult$Key;
-Landroid/hardware/camera2/impl/CameraMetadataNative$Key;->getTag()I
-Landroid/hardware/camera2/impl/CameraMetadataNative;->mMetadataPtr:J
-Landroid/hardware/camera2/impl/CameraMetadataNative;->nativeGetTagFromKeyLocal(Ljava/lang/String;)I
-Landroid/hardware/camera2/impl/CameraMetadataNative;->nativeGetTypeFromTagLocal(I)I
-Landroid/hardware/camera2/impl/CameraMetadataNative;->nativeReadValues(I)[B
-Landroid/hardware/camera2/utils/SurfaceUtils;->getSurfaceSize(Landroid/view/Surface;)Landroid/util/Size;
-Landroid/hardware/camera2/utils/TypeReference;-><init>()V
-Landroid/hardware/camera2/utils/TypeReference;->createSpecializedTypeReference(Ljava/lang/reflect/Type;)Landroid/hardware/camera2/utils/TypeReference;
-Landroid/hardware/Camera;->addCallbackBuffer([BI)V
-Landroid/hardware/Camera;->addRawImageCallbackBuffer([B)V
-Landroid/hardware/Camera;->CAMERA_HAL_API_VERSION_1_0:I
-Landroid/hardware/Camera;->getEmptyParameters()Landroid/hardware/Camera$Parameters;
-Landroid/hardware/Camera;->mNativeContext:J
-Landroid/hardware/Camera;->native_getParameters()Ljava/lang/String;
-Landroid/hardware/Camera;->native_setParameters(Ljava/lang/String;)V
-Landroid/hardware/Camera;->native_setup(Ljava/lang/Object;IILjava/lang/String;)I
-Landroid/hardware/Camera;->openLegacy(II)Landroid/hardware/Camera;
-Landroid/hardware/Camera;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
-Landroid/hardware/Camera;->previewEnabled()Z
-Landroid/hardware/Camera;->setPreviewSurface(Landroid/view/Surface;)V
-Landroid/hardware/display/DisplayManager;->ACTION_WIFI_DISPLAY_STATUS_CHANGED:Ljava/lang/String;
-Landroid/hardware/display/DisplayManager;->connectWifiDisplay(Ljava/lang/String;)V
-Landroid/hardware/display/DisplayManager;->disconnectWifiDisplay()V
-Landroid/hardware/display/DisplayManager;->EXTRA_WIFI_DISPLAY_STATUS:Ljava/lang/String;
-Landroid/hardware/display/DisplayManager;->forgetWifiDisplay(Ljava/lang/String;)V
-Landroid/hardware/display/DisplayManager;->getWifiDisplayStatus()Landroid/hardware/display/WifiDisplayStatus;
-Landroid/hardware/display/DisplayManager;->pauseWifiDisplay()V
-Landroid/hardware/display/DisplayManager;->renameWifiDisplay(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/hardware/display/DisplayManager;->resumeWifiDisplay()V
-Landroid/hardware/display/DisplayManager;->startWifiDisplayScan()V
-Landroid/hardware/display/DisplayManager;->stopWifiDisplayScan()V
-Landroid/hardware/display/DisplayManagerGlobal;->disconnectWifiDisplay()V
-Landroid/hardware/display/DisplayManagerGlobal;->getDisplayIds()[I
-Landroid/hardware/display/DisplayManagerGlobal;->getDisplayInfo(I)Landroid/view/DisplayInfo;
-Landroid/hardware/display/DisplayManagerGlobal;->getWifiDisplayStatus()Landroid/hardware/display/WifiDisplayStatus;
-Landroid/hardware/display/DisplayManagerGlobal;->mDm:Landroid/hardware/display/IDisplayManager;
-Landroid/hardware/display/DisplayManagerGlobal;->sInstance:Landroid/hardware/display/DisplayManagerGlobal;
 Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager;
 Landroid/hardware/display/IDisplayManager;->getDisplayInfo(I)Landroid/view/DisplayInfo;
-Landroid/hardware/display/WifiDisplay;->canConnect()Z
-Landroid/hardware/display/WifiDisplay;->equals(Landroid/hardware/display/WifiDisplay;)Z
-Landroid/hardware/display/WifiDisplay;->getDeviceAddress()Ljava/lang/String;
-Landroid/hardware/display/WifiDisplay;->getDeviceAlias()Ljava/lang/String;
-Landroid/hardware/display/WifiDisplay;->getDeviceName()Ljava/lang/String;
-Landroid/hardware/display/WifiDisplay;->isAvailable()Z
-Landroid/hardware/display/WifiDisplay;->isRemembered()Z
-Landroid/hardware/display/WifiDisplayStatus;->DISPLAY_STATE_CONNECTED:I
-Landroid/hardware/display/WifiDisplayStatus;->DISPLAY_STATE_CONNECTING:I
-Landroid/hardware/display/WifiDisplayStatus;->DISPLAY_STATE_NOT_CONNECTED:I
-Landroid/hardware/display/WifiDisplayStatus;->FEATURE_STATE_ON:I
-Landroid/hardware/display/WifiDisplayStatus;->getActiveDisplay()Landroid/hardware/display/WifiDisplay;
-Landroid/hardware/display/WifiDisplayStatus;->getActiveDisplayState()I
-Landroid/hardware/display/WifiDisplayStatus;->getDisplays()[Landroid/hardware/display/WifiDisplay;
-Landroid/hardware/display/WifiDisplayStatus;->getFeatureState()I
-Landroid/hardware/display/WifiDisplayStatus;->getScanState()I
-Landroid/hardware/display/WifiDisplayStatus;->mActiveDisplay:Landroid/hardware/display/WifiDisplay;
-Landroid/hardware/display/WifiDisplayStatus;->mDisplays:[Landroid/hardware/display/WifiDisplay;
-Landroid/hardware/display/WifiDisplayStatus;->SCAN_STATE_NOT_SCANNING:I
-Landroid/hardware/fingerprint/FingerprintManager$AuthenticationResult;->getFingerprint()Landroid/hardware/fingerprint/Fingerprint;
-Landroid/hardware/fingerprint/FingerprintManager;->getAuthenticatorId()J
-Landroid/hardware/fingerprint/FingerprintManager;->getEnrolledFingerprints()Ljava/util/List;
-Landroid/hardware/fingerprint/FingerprintManager;->getEnrolledFingerprints(I)Ljava/util/List;
 Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/fingerprint/IFingerprintService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/fingerprint/IFingerprintService;
-Landroid/hardware/HardwareBuffer;-><init>(J)V
-Landroid/hardware/HardwareBuffer;->mNativeObject:J
 Landroid/hardware/ICameraService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/ICameraService;
 Landroid/hardware/input/IInputManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager;
 Landroid/hardware/input/IInputManager$Stub;->TRANSACTION_injectInputEvent:I
 Landroid/hardware/input/IInputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z
-Landroid/hardware/input/InputManager;->createInputForwarder(I)Landroid/app/IInputForwarder;
-Landroid/hardware/input/InputManager;->getInstance()Landroid/hardware/input/InputManager;
-Landroid/hardware/input/InputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z
-Landroid/hardware/input/InputManager;->INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH:I
-Landroid/hardware/input/InputManager;->mIm:Landroid/hardware/input/IInputManager;
-Landroid/hardware/input/InputManager;->setPointerIconType(I)V
 Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
 Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
-Landroid/hardware/Sensor;->getHandle()I
-Landroid/hardware/Sensor;->mFlags:I
-Landroid/hardware/Sensor;->TYPE_DEVICE_ORIENTATION:I
-Landroid/hardware/Sensor;->TYPE_PICK_UP_GESTURE:I
-Landroid/hardware/SensorEvent;-><init>(I)V
-Landroid/hardware/SensorManager;-><init>()V
-Landroid/hardware/SerialManager;->getSerialPorts()[Ljava/lang/String;
-Landroid/hardware/SerialManager;->openSerialPort(Ljava/lang/String;I)Landroid/hardware/SerialPort;
-Landroid/hardware/SerialPort;->close()V
-Landroid/hardware/SerialPort;->mNativeContext:I
-Landroid/hardware/SerialPort;->write(Ljava/nio/ByteBuffer;I)V
-Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;-><init>(II)V
-Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;->confidenceLevel:I
-Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;->userId:I
-Landroid/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V
-Landroid/hardware/soundtrigger/SoundTrigger$GenericSoundModel;-><init>(Ljava/util/UUID;Ljava/util/UUID;[B)V
-Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;-><init>(IILjava/lang/String;Ljava/lang/String;[I)V
-Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->id:I
-Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->locale:Ljava/lang/String;
-Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->recognitionModes:I
-Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->text:Ljava/lang/String;
-Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->users:[I
-Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V
-Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent;->keyphraseExtras:[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;
-Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;-><init>(III[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;)V
-Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;->coarseConfidenceLevel:I
-Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;->confidenceLevels:[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;
-Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;->id:I
-Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;->recognitionModes:I
-Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;-><init>(Ljava/util/UUID;Ljava/util/UUID;[B[Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;)V
-Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;->keyphrases:[Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;
-Landroid/hardware/soundtrigger/SoundTrigger$ModuleProperties;-><init>(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIZIZIZ)V
-Landroid/hardware/soundtrigger/SoundTrigger$ModuleProperties;->id:I
-Landroid/hardware/soundtrigger/SoundTrigger$ModuleProperties;->maxSoundModels:I
-Landroid/hardware/soundtrigger/SoundTrigger$ModuleProperties;->uuid:Ljava/util/UUID;
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;-><init>(ZZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;[B)V
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->captureRequested:Z
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->data:[B
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->keyphrases:[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;->captureAvailable:Z
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;->captureSession:I
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;->data:[B
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;->soundModelHandle:I
-Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;->status:I
-Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->data:[B
-Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->uuid:Ljava/util/UUID;
-Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->vendorUuid:Ljava/util/UUID;
-Landroid/hardware/soundtrigger/SoundTrigger$SoundModelEvent;-><init>(II[B)V
-Landroid/hardware/soundtrigger/SoundTrigger;->attachModule(ILandroid/hardware/soundtrigger/SoundTrigger$StatusListener;Landroid/os/Handler;)Landroid/hardware/soundtrigger/SoundTriggerModule;
-Landroid/hardware/soundtrigger/SoundTrigger;->listModules(Ljava/util/ArrayList;)I
-Landroid/hardware/soundtrigger/SoundTriggerModule;->detach()V
-Landroid/hardware/soundtrigger/SoundTriggerModule;->loadSoundModel(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;[I)I
-Landroid/hardware/soundtrigger/SoundTriggerModule;->mId:I
-Landroid/hardware/soundtrigger/SoundTriggerModule;->mNativeContext:J
-Landroid/hardware/soundtrigger/SoundTriggerModule;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
-Landroid/hardware/soundtrigger/SoundTriggerModule;->startRecognition(ILandroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)I
-Landroid/hardware/soundtrigger/SoundTriggerModule;->stopRecognition(I)I
-Landroid/hardware/soundtrigger/SoundTriggerModule;->unloadSoundModel(I)I
-Landroid/hardware/SystemSensorManager$BaseEventQueue;->dispatchAdditionalInfoEvent(III[F[I)V
-Landroid/hardware/SystemSensorManager$BaseEventQueue;->dispatchFlushCompleteEvent(I)V
-Landroid/hardware/SystemSensorManager$BaseEventQueue;->dispatchSensorEvent(I[FIJ)V
 Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
-Landroid/hardware/usb/UsbDevice;->mInterfaces:[Landroid/hardware/usb/UsbInterface;
-Landroid/hardware/usb/UsbDeviceConnection;->mNativeContext:J
-Landroid/hardware/usb/UsbManager;-><init>(Landroid/content/Context;Landroid/hardware/usb/IUsbManager;)V
-Landroid/hardware/usb/UsbManager;->ACTION_USB_STATE:Ljava/lang/String;
-Landroid/hardware/usb/UsbManager;->getPorts()[Landroid/hardware/usb/UsbPort;
-Landroid/hardware/usb/UsbManager;->getPortStatus(Landroid/hardware/usb/UsbPort;)Landroid/hardware/usb/UsbPortStatus;
-Landroid/hardware/usb/UsbManager;->isFunctionEnabled(Ljava/lang/String;)Z
-Landroid/hardware/usb/UsbManager;->setCurrentFunction(Ljava/lang/String;Z)V
-Landroid/hardware/usb/UsbManager;->setPortRoles(Landroid/hardware/usb/UsbPort;II)V
-Landroid/hardware/usb/UsbManager;->USB_CONNECTED:Ljava/lang/String;
-Landroid/hardware/usb/UsbManager;->USB_DATA_UNLOCKED:Ljava/lang/String;
-Landroid/hardware/usb/UsbManager;->USB_FUNCTION_NONE:Ljava/lang/String;
-Landroid/hardware/usb/UsbPortStatus;->getCurrentDataRole()I
-Landroid/hardware/usb/UsbPortStatus;->getCurrentMode()I
-Landroid/hardware/usb/UsbPortStatus;->getCurrentPowerRole()I
-Landroid/hardware/usb/UsbPortStatus;->getSupportedRoleCombinations()I
-Landroid/hardware/usb/UsbPortStatus;->isConnected()Z
-Landroid/hardware/usb/UsbPortStatus;->isRoleCombinationSupported(II)Z
-Landroid/hardware/usb/UsbRequest;->mBuffer:Ljava/nio/ByteBuffer;
-Landroid/hardware/usb/UsbRequest;->mLength:I
-Landroid/hardware/usb/UsbRequest;->mNativeContext:J
 Landroid/icu/impl/CurrencyData;-><init>()V
 Landroid/icu/text/ArabicShaping;-><init>(I)V
 Landroid/icu/text/ArabicShaping;->isAlefMaksouraChar(C)Z
@@ -2619,7 +491,6 @@
 Landroid/icu/text/Transliterator;->transliterate(Landroid/icu/text/Replaceable;Landroid/icu/text/Transliterator$Position;Ljava/lang/String;)V
 Landroid/icu/text/Transliterator;->transliterate(Ljava/lang/String;)Ljava/lang/String;
 Landroid/icu/text/UFormat;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/UForwardCharacterIterator;->DONE:I
 Landroid/icu/util/Calendar;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
 Landroid/icu/util/PersianCalendar;-><init>(Ljava/util/Locale;)V
 Landroid/icu/util/UResourceBundle;->getBundleInstance(Ljava/lang/String;Landroid/icu/util/ULocale;)Landroid/icu/util/UResourceBundle;
@@ -2628,38 +499,6 @@
 Landroid/icu/util/UResourceBundle;->getType()I
 Landroid/icu/util/UResourceBundleIterator;->hasNext()Z
 Landroid/icu/util/UResourceBundleIterator;->next()Landroid/icu/util/UResourceBundle;
-Landroid/inputmethodservice/InputMethodService$SettingsObserver;->shouldShowImeWithHardKeyboard()Z
-Landroid/inputmethodservice/InputMethodService;->mExtractEditText:Landroid/inputmethodservice/ExtractEditText;
-Landroid/inputmethodservice/InputMethodService;->mExtractView:Landroid/view/View;
-Landroid/inputmethodservice/InputMethodService;->mRootView:Landroid/view/View;
-Landroid/inputmethodservice/InputMethodService;->mSettingsObserver:Landroid/inputmethodservice/InputMethodService$SettingsObserver;
-Landroid/inputmethodservice/InputMethodService;->mTheme:I
-Landroid/inputmethodservice/InputMethodService;->mTmpInsets:Landroid/inputmethodservice/InputMethodService$Insets;
-Landroid/inputmethodservice/InputMethodService;->onExtractedDeleteText(II)V
-Landroid/inputmethodservice/InputMethodService;->onExtractedReplaceText(IILjava/lang/CharSequence;)V
-Landroid/inputmethodservice/InputMethodService;->onExtractedSetSpan(Ljava/lang/Object;III)V
-Landroid/inputmethodservice/Keyboard;->mModifierKeys:Ljava/util/List;
-Landroid/inputmethodservice/Keyboard;->mTotalHeight:I
-Landroid/inputmethodservice/Keyboard;->mTotalWidth:I
-Landroid/inputmethodservice/Keyboard;->resize(II)V
-Landroid/inputmethodservice/KeyboardView;->mKeyBackground:Landroid/graphics/drawable/Drawable;
-Landroid/inputmethodservice/KeyboardView;->mLabelTextSize:I
-Landroid/inputmethodservice/KeyboardView;->mPreviewText:Landroid/widget/TextView;
-Landroid/inputmethodservice/KeyboardView;->openPopupIfRequired(Landroid/view/MotionEvent;)Z
-Landroid/inputmethodservice/KeyboardView;->repeatKey()Z
-Landroid/inputmethodservice/KeyboardView;->showKey(I)V
-Landroid/location/Country;-><init>(Ljava/lang/String;I)V
-Landroid/location/Country;->getCountryIso()Ljava/lang/String;
-Landroid/location/Country;->getSource()I
-Landroid/location/CountryDetector;-><init>(Landroid/location/ICountryDetector;)V
-Landroid/location/CountryDetector;->addCountryListener(Landroid/location/CountryListener;Landroid/os/Looper;)V
-Landroid/location/CountryDetector;->detectCountry()Landroid/location/Country;
-Landroid/location/CountryDetector;->removeCountryListener(Landroid/location/CountryListener;)V
-Landroid/location/CountryListener;->onCountryDetected(Landroid/location/Country;)V
-Landroid/location/GeocoderParams;->getClientPackage()Ljava/lang/String;
-Landroid/location/GeocoderParams;->getLocale()Ljava/util/Locale;
-Landroid/location/Geofence;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/location/GpsStatus;->setTimeToFirstFix(I)V
 Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryDetector;
 Landroid/location/ICountryListener$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;-><init>()V
@@ -2678,234 +517,6 @@
 Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
 Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I
 Landroid/location/ILocationManager;->getAllProviders()Ljava/util/List;
-Landroid/location/Location;->mElapsedRealtimeNanos:J
-Landroid/location/Location;->mProvider:Ljava/lang/String;
-Landroid/location/LocationManager;->mService:Landroid/location/ILocationManager;
-Landroid/location/LocationManager;->requestLocationUpdates(Landroid/location/LocationRequest;Landroid/location/LocationListener;Landroid/os/Looper;Landroid/app/PendingIntent;)V
-Landroid/location/LocationManager;->sendNiResponse(II)Z
-Landroid/location/LocationRequest;->checkDisplacement(F)V
-Landroid/location/LocationRequest;->checkInterval(J)V
-Landroid/location/LocationRequest;->checkProvider(Ljava/lang/String;)V
-Landroid/location/LocationRequest;->checkQuality(I)V
-Landroid/location/LocationRequest;->mExpireAt:J
-Landroid/location/LocationRequest;->mExplicitFastestInterval:Z
-Landroid/location/LocationRequest;->mFastestInterval:J
-Landroid/location/LocationRequest;->mHideFromAppOps:Z
-Landroid/location/LocationRequest;->mInterval:J
-Landroid/location/LocationRequest;->mNumUpdates:I
-Landroid/location/LocationRequest;->mProvider:Ljava/lang/String;
-Landroid/location/LocationRequest;->mQuality:I
-Landroid/location/LocationRequest;->mSmallestDisplacement:F
-Landroid/location/LocationRequest;->mWorkSource:Landroid/os/WorkSource;
-Landroid/media/AmrInputStream;-><init>(Ljava/io/InputStream;)V
-Landroid/media/AsyncPlayer;->setUsesWakeLock(Landroid/content/Context;)V
-Landroid/media/AudioAttributes$Builder;->addTag(Ljava/lang/String;)Landroid/media/AudioAttributes$Builder;
-Landroid/media/AudioAttributes$Builder;->setInternalLegacyStreamType(I)Landroid/media/AudioAttributes$Builder;
-Landroid/media/AudioAttributes;->mContentType:I
-Landroid/media/AudioAttributes;->mFlags:I
-Landroid/media/AudioAttributes;->mFormattedTags:Ljava/lang/String;
-Landroid/media/AudioAttributes;->mSource:I
-Landroid/media/AudioAttributes;->mUsage:I
-Landroid/media/AudioAttributes;->toLegacyStreamType(Landroid/media/AudioAttributes;)I
-Landroid/media/AudioDevicePort;-><init>(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V
-Landroid/media/AudioDevicePort;->type()I
-Landroid/media/AudioDevicePortConfig;-><init>(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V
-Landroid/media/AudioFormat;-><init>(IIII)V
-Landroid/media/AudioFormat;->mChannelMask:I
-Landroid/media/AudioFormat;->mEncoding:I
-Landroid/media/AudioFormat;->mSampleRate:I
-Landroid/media/audiofx/AudioEffect;-><init>(Ljava/util/UUID;Ljava/util/UUID;II)V
-Landroid/media/audiofx/AudioEffect;->checkState(Ljava/lang/String;)V
-Landroid/media/audiofx/AudioEffect;->command(I[B[B)I
-Landroid/media/audiofx/AudioEffect;->getParameter([I[B)I
-Landroid/media/audiofx/AudioEffect;->getParameter([I[I)I
-Landroid/media/audiofx/AudioEffect;->setParameter([I[S)I
-Landroid/media/audiofx/Visualizer;->mId:I
-Landroid/media/AudioGain;-><init>(IIIIIIIII)V
-Landroid/media/AudioGainConfig;-><init>(ILandroid/media/AudioGain;II[II)V
-Landroid/media/AudioGainConfig;->mChannelMask:I
-Landroid/media/AudioGainConfig;->mIndex:I
-Landroid/media/AudioGainConfig;->mMode:I
-Landroid/media/AudioGainConfig;->mRampDurationMs:I
-Landroid/media/AudioGainConfig;->mValues:[I
-Landroid/media/AudioHandle;-><init>(I)V
-Landroid/media/AudioHandle;->mId:I
-Landroid/media/AudioManager;-><init>()V
-Landroid/media/AudioManager;-><init>(Landroid/content/Context;)V
-Landroid/media/AudioManager;->abandonAudioFocusForCall()V
-Landroid/media/AudioManager;->createAudioPatch([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I
-Landroid/media/AudioManager;->DEVICE_OUT_ANLG_DOCK_HEADSET:I
-Landroid/media/AudioManager;->DEVICE_OUT_BLUETOOTH_A2DP:I
-Landroid/media/AudioManager;->DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:I
-Landroid/media/AudioManager;->DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:I
-Landroid/media/AudioManager;->DEVICE_OUT_BLUETOOTH_SCO_HEADSET:I
-Landroid/media/AudioManager;->DEVICE_OUT_DGTL_DOCK_HEADSET:I
-Landroid/media/AudioManager;->DEVICE_OUT_EARPIECE:I
-Landroid/media/AudioManager;->DEVICE_OUT_HDMI:I
-Landroid/media/AudioManager;->DEVICE_OUT_SPEAKER:I
-Landroid/media/AudioManager;->DEVICE_OUT_WIRED_HEADPHONE:I
-Landroid/media/AudioManager;->DEVICE_OUT_WIRED_HEADSET:I
-Landroid/media/AudioManager;->EXTRA_VOLUME_STREAM_TYPE:Ljava/lang/String;
-Landroid/media/AudioManager;->EXTRA_VOLUME_STREAM_VALUE:Ljava/lang/String;
-Landroid/media/AudioManager;->forceVolumeControlStream(I)V
-Landroid/media/AudioManager;->getDevicesForStream(I)I
-Landroid/media/AudioManager;->getLastAudibleStreamVolume(I)I
-Landroid/media/AudioManager;->getOutputLatency(I)I
-Landroid/media/AudioManager;->getRingerModeInternal()I
-Landroid/media/AudioManager;->getService()Landroid/media/IAudioService;
-Landroid/media/AudioManager;->isMasterMute()Z
-Landroid/media/AudioManager;->isMusicActiveRemotely()Z
-Landroid/media/AudioManager;->isSilentMode()Z
-Landroid/media/AudioManager;->isValidRingerMode(I)Z
-Landroid/media/AudioManager;->listAudioPatches(Ljava/util/ArrayList;)I
-Landroid/media/AudioManager;->listAudioPorts(Ljava/util/ArrayList;)I
-Landroid/media/AudioManager;->mAudioFocusIdListenerMap:Ljava/util/concurrent/ConcurrentHashMap;
-Landroid/media/AudioManager;->NUM_SOUND_EFFECTS:I
-Landroid/media/AudioManager;->releaseAudioPatch(Landroid/media/AudioPatch;)I
-Landroid/media/AudioManager;->reloadAudioSettings()V
-Landroid/media/AudioManager;->requestAudioFocusForCall(II)V
-Landroid/media/AudioManager;->setMasterMute(ZI)V
-Landroid/media/AudioManager;->setRingerModeInternal(I)V
-Landroid/media/AudioManager;->setWiredDeviceConnectionState(IILjava/lang/String;Ljava/lang/String;)V
-Landroid/media/AudioManager;->startBluetoothScoVirtualCall()V
-Landroid/media/AudioManager;->STREAM_BLUETOOTH_SCO:I
-Landroid/media/AudioManager;->STREAM_SYSTEM_ENFORCED:I
-Landroid/media/AudioManager;->STREAM_TTS:I
-Landroid/media/AudioManager;->VOLUME_CHANGED_ACTION:Ljava/lang/String;
-Landroid/media/AudioMixPort;-><init>(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V
-Landroid/media/AudioMixPort;->ioHandle()I
-Landroid/media/AudioMixPortConfig;-><init>(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V
-Landroid/media/AudioPatch;-><init>(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V
-Landroid/media/AudioPatch;->mHandle:Landroid/media/AudioHandle;
-Landroid/media/AudioPatch;->sinks()[Landroid/media/AudioPortConfig;
-Landroid/media/AudioPatch;->sources()[Landroid/media/AudioPortConfig;
-Landroid/media/audiopolicy/AudioMix;->mCallbackFlags:I
-Landroid/media/audiopolicy/AudioMix;->mDeviceAddress:Ljava/lang/String;
-Landroid/media/audiopolicy/AudioMix;->mDeviceSystemType:I
-Landroid/media/audiopolicy/AudioMix;->mFormat:Landroid/media/AudioFormat;
-Landroid/media/audiopolicy/AudioMix;->mMixType:I
-Landroid/media/audiopolicy/AudioMix;->mRouteFlags:I
-Landroid/media/audiopolicy/AudioMix;->mRule:Landroid/media/audiopolicy/AudioMixingRule;
-Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;->mAttr:Landroid/media/AudioAttributes;
-Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;->mIntProp:I
-Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;->mRule:I
-Landroid/media/audiopolicy/AudioMixingRule;->mCriteria:Ljava/util/ArrayList;
-Landroid/media/AudioPort;-><init>(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V
-Landroid/media/AudioPort;->id()I
-Landroid/media/AudioPort;->mActiveConfig:Landroid/media/AudioPortConfig;
-Landroid/media/AudioPort;->mGains:[Landroid/media/AudioGain;
-Landroid/media/AudioPort;->mHandle:Landroid/media/AudioHandle;
-Landroid/media/AudioPort;->mRole:I
-Landroid/media/AudioPort;->role()I
-Landroid/media/AudioPortConfig;-><init>(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V
-Landroid/media/AudioPortConfig;->mChannelMask:I
-Landroid/media/AudioPortConfig;->mConfigMask:I
-Landroid/media/AudioPortConfig;->mFormat:I
-Landroid/media/AudioPortConfig;->mGain:Landroid/media/AudioGainConfig;
-Landroid/media/AudioPortConfig;->mPort:Landroid/media/AudioPort;
-Landroid/media/AudioPortConfig;->mSamplingRate:I
-Landroid/media/AudioPortConfig;->port()Landroid/media/AudioPort;
-Landroid/media/AudioPortEventHandler;->mJniCallback:J
-Landroid/media/AudioPortEventHandler;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
-Landroid/media/AudioRecord;->mAudioAttributes:Landroid/media/AudioAttributes;
-Landroid/media/AudioRecord;->mInitializationLooper:Landroid/os/Looper;
-Landroid/media/AudioRecord;->mNativeCallbackCookie:J
-Landroid/media/AudioRecord;->mNativeDeviceCallback:J
-Landroid/media/AudioRecord;->mNativeRecorderInJavaObj:J
-Landroid/media/AudioRecord;->native_release()V
-Landroid/media/AudioRecord;->native_setup(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILjava/lang/String;J)I
-Landroid/media/AudioRecord;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
-Landroid/media/AudioRecordingConfiguration;->getClientPackageName()Ljava/lang/String;
-Landroid/media/AudioRecordingConfiguration;->getClientUid()I
-Landroid/media/AudioSystem;->DEVICE_IN_AMBIENT:I
-Landroid/media/AudioSystem;->DEVICE_IN_ANLG_DOCK_HEADSET:I
-Landroid/media/AudioSystem;->DEVICE_IN_AUX_DIGITAL:I
-Landroid/media/AudioSystem;->DEVICE_IN_BACK_MIC:I
-Landroid/media/AudioSystem;->DEVICE_IN_BLUETOOTH_A2DP:I
-Landroid/media/AudioSystem;->DEVICE_IN_BLUETOOTH_SCO_HEADSET:I
-Landroid/media/AudioSystem;->DEVICE_IN_BUILTIN_MIC:I
-Landroid/media/AudioSystem;->DEVICE_IN_COMMUNICATION:I
-Landroid/media/AudioSystem;->DEVICE_IN_DEFAULT:I
-Landroid/media/AudioSystem;->DEVICE_IN_DGTL_DOCK_HEADSET:I
-Landroid/media/AudioSystem;->DEVICE_IN_REMOTE_SUBMIX:I
-Landroid/media/AudioSystem;->DEVICE_IN_USB_ACCESSORY:I
-Landroid/media/AudioSystem;->DEVICE_IN_USB_DEVICE:I
-Landroid/media/AudioSystem;->DEVICE_IN_VOICE_CALL:I
-Landroid/media/AudioSystem;->DEVICE_IN_WIRED_HEADSET:I
-Landroid/media/AudioSystem;->DEVICE_OUT_ALL_USB:I
-Landroid/media/AudioSystem;->DEVICE_OUT_ANLG_DOCK_HEADSET:I
-Landroid/media/AudioSystem;->DEVICE_OUT_AUX_DIGITAL:I
-Landroid/media/AudioSystem;->DEVICE_OUT_BLUETOOTH_A2DP:I
-Landroid/media/AudioSystem;->DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:I
-Landroid/media/AudioSystem;->DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:I
-Landroid/media/AudioSystem;->DEVICE_OUT_BLUETOOTH_SCO:I
-Landroid/media/AudioSystem;->DEVICE_OUT_BLUETOOTH_SCO_CARKIT:I
-Landroid/media/AudioSystem;->DEVICE_OUT_BLUETOOTH_SCO_HEADSET:I
-Landroid/media/AudioSystem;->DEVICE_OUT_DGTL_DOCK_HEADSET:I
-Landroid/media/AudioSystem;->DEVICE_OUT_EARPIECE:I
-Landroid/media/AudioSystem;->DEVICE_OUT_FM:I
-Landroid/media/AudioSystem;->DEVICE_OUT_REMOTE_SUBMIX:I
-Landroid/media/AudioSystem;->DEVICE_OUT_SPEAKER:I
-Landroid/media/AudioSystem;->DEVICE_OUT_TELEPHONY_TX:I
-Landroid/media/AudioSystem;->DEVICE_OUT_USB_ACCESSORY:I
-Landroid/media/AudioSystem;->DEVICE_OUT_USB_DEVICE:I
-Landroid/media/AudioSystem;->DEVICE_OUT_WIRED_HEADPHONE:I
-Landroid/media/AudioSystem;->DEVICE_OUT_WIRED_HEADSET:I
-Landroid/media/AudioSystem;->DEVICE_STATE_AVAILABLE:I
-Landroid/media/AudioSystem;->DEVICE_STATE_UNAVAILABLE:I
-Landroid/media/AudioSystem;->dynamicPolicyCallbackFromNative(ILjava/lang/String;I)V
-Landroid/media/AudioSystem;->errorCallbackFromNative(I)V
-Landroid/media/AudioSystem;->FORCE_ANALOG_DOCK:I
-Landroid/media/AudioSystem;->FORCE_BT_CAR_DOCK:I
-Landroid/media/AudioSystem;->FORCE_BT_DESK_DOCK:I
-Landroid/media/AudioSystem;->FORCE_DIGITAL_DOCK:I
-Landroid/media/AudioSystem;->FORCE_NONE:I
-Landroid/media/AudioSystem;->getDeviceConnectionState(ILjava/lang/String;)I
-Landroid/media/AudioSystem;->getDevicesForStream(I)I
-Landroid/media/AudioSystem;->getMasterMute()Z
-Landroid/media/AudioSystem;->getNumStreamTypes()I
-Landroid/media/AudioSystem;->getOutputDeviceName(I)Ljava/lang/String;
-Landroid/media/AudioSystem;->getOutputLatency(I)I
-Landroid/media/AudioSystem;->getPrimaryOutputFrameCount()I
-Landroid/media/AudioSystem;->getPrimaryOutputSamplingRate()I
-Landroid/media/AudioSystem;->initStreamVolume(III)I
-Landroid/media/AudioSystem;->isMicrophoneMuted()Z
-Landroid/media/AudioSystem;->isSourceActive(I)Z
-Landroid/media/AudioSystem;->isStreamActive(II)Z
-Landroid/media/AudioSystem;->muteMicrophone(Z)I
-Landroid/media/AudioSystem;->recordingCallbackFromNative(IIII[I)V
-Landroid/media/AudioSystem;->setDeviceConnectionState(IILjava/lang/String;Ljava/lang/String;)I
-Landroid/media/AudioSystem;->setErrorCallback(Landroid/media/AudioSystem$ErrorCallback;)V
-Landroid/media/AudioSystem;->setMasterMute(Z)I
-Landroid/media/AudioSystem;->setPhoneState(I)I
-Landroid/media/AudioSystem;->setStreamVolumeIndex(III)I
-Landroid/media/AudioSystem;->STREAM_SYSTEM_ENFORCED:I
-Landroid/media/AudioTrack;->deferred_connect(J)V
-Landroid/media/AudioTrack;->getLatency()I
-Landroid/media/AudioTrack;->mJniData:J
-Landroid/media/AudioTrack;->mNativeTrackInJavaObj:J
-Landroid/media/AudioTrack;->mStreamType:I
-Landroid/media/AudioTrack;->native_release()V
-Landroid/media/AudioTrack;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
-Landroid/media/CamcorderProfile;->native_get_camcorder_profile(II)Landroid/media/CamcorderProfile;
-Landroid/media/CamcorderProfile;->native_init()V
-Landroid/media/DecoderCapabilities$AudioDecoder;->AUDIO_DECODER_WMA:Landroid/media/DecoderCapabilities$AudioDecoder;
-Landroid/media/DecoderCapabilities$VideoDecoder;->VIDEO_DECODER_WMV:Landroid/media/DecoderCapabilities$VideoDecoder;
-Landroid/media/DecoderCapabilities;->getAudioDecoders()Ljava/util/List;
-Landroid/media/DecoderCapabilities;->getVideoDecoders()Ljava/util/List;
-Landroid/media/EncoderCapabilities$VideoEncoderCap;->mCodec:I
-Landroid/media/EncoderCapabilities$VideoEncoderCap;->mMaxFrameHeight:I
-Landroid/media/EncoderCapabilities$VideoEncoderCap;->mMaxFrameWidth:I
-Landroid/media/EncoderCapabilities$VideoEncoderCap;->mMinFrameHeight:I
-Landroid/media/EncoderCapabilities$VideoEncoderCap;->mMinFrameWidth:I
-Landroid/media/EncoderCapabilities;->getVideoEncoders()Ljava/util/List;
-Landroid/media/ExifInterface;->convertRationalLatLonToFloat(Ljava/lang/String;Ljava/lang/String;)F
-Landroid/media/ExifInterface;->getDateTime()J
-Landroid/media/ExifInterface;->getGpsDateTime()J
-Landroid/media/ExifInterface;->mAttributes:[Ljava/util/HashMap;
-Landroid/media/ExifInterface;->mFilename:Ljava/lang/String;
-Landroid/media/ExifInterface;->mHasThumbnail:Z
-Landroid/media/ExifInterface;->sFormatter:Ljava/text/SimpleDateFormat;
 Landroid/media/IAudioFocusDispatcher;->dispatchAudioFocusChange(ILjava/lang/String;)V
 Landroid/media/IAudioRoutesObserver$Stub;-><init>()V
 Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -2915,8 +526,6 @@
 Landroid/media/IAudioService;->getStreamVolume(I)I
 Landroid/media/IAudioService;->setStreamVolume(IIILjava/lang/String;)V
 Landroid/media/IAudioService;->startWatchingRoutes(Landroid/media/IAudioRoutesObserver;)Landroid/media/AudioRoutesInfo;
-Landroid/media/Image$Plane;-><init>()V
-Landroid/media/Image;-><init>()V
 Landroid/media/IMediaRouterService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaRouterService;
 Landroid/media/IMediaScannerListener$Stub;-><init>()V
 Landroid/media/IMediaScannerService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaScannerService;
@@ -2925,381 +534,9 @@
 Landroid/media/IRemoteDisplayCallback;->onStateChanged(Landroid/media/RemoteDisplayState;)V
 Landroid/media/IRingtonePlayer;->play(Landroid/os/IBinder;Landroid/net/Uri;Landroid/media/AudioAttributes;FZ)V
 Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
-Landroid/media/JetPlayer;->mNativePlayerInJavaObj:J
-Landroid/media/JetPlayer;->postEventFromNative(Ljava/lang/Object;III)V
-Landroid/media/MediaCodec$CodecException;-><init>(IILjava/lang/String;)V
-Landroid/media/MediaCodec;->getBuffers(Z)[Ljava/nio/ByteBuffer;
-Landroid/media/MediaCodec;->mNativeContext:J
-Landroid/media/MediaCodec;->releaseOutputBuffer(IZZJ)V
-Landroid/media/MediaCodec;->setParameters([Ljava/lang/String;[Ljava/lang/Object;)V
-Landroid/media/MediaCodecInfo$VideoCapabilities;->create(Landroid/media/MediaFormat;Landroid/media/MediaCodecInfo$CodecCapabilities;)Landroid/media/MediaCodecInfo$VideoCapabilities;
-Landroid/media/MediaFile$MediaFileType;->fileType:I
-Landroid/media/MediaFile$MediaFileType;->mimeType:Ljava/lang/String;
 Landroid/media/MediaFile;-><init>()V
-Landroid/media/MediaFile;->addFileType(Ljava/lang/String;ILjava/lang/String;)V
-Landroid/media/MediaFile;->FIRST_AUDIO_FILE_TYPE:I
-Landroid/media/MediaFile;->getFileTitle(Ljava/lang/String;)Ljava/lang/String;
-Landroid/media/MediaFile;->getFileType(Ljava/lang/String;)Landroid/media/MediaFile$MediaFileType;
-Landroid/media/MediaFile;->getFileTypeForMimeType(Ljava/lang/String;)I
-Landroid/media/MediaFile;->getMimeTypeForFile(Ljava/lang/String;)Ljava/lang/String;
-Landroid/media/MediaFile;->isAudioFileType(I)Z
-Landroid/media/MediaFile;->isDrmFileType(I)Z
-Landroid/media/MediaFile;->isImageFileType(I)Z
-Landroid/media/MediaFile;->isPlayListFileType(I)Z
-Landroid/media/MediaFile;->isVideoFileType(I)Z
-Landroid/media/MediaFile;->LAST_AUDIO_FILE_TYPE:I
-Landroid/media/MediaFile;->sFileTypeMap:Ljava/util/HashMap;
-Landroid/media/MediaFile;->sFileTypeToFormatMap:Ljava/util/HashMap;
-Landroid/media/MediaFile;->sFormatToMimeTypeMap:Ljava/util/HashMap;
-Landroid/media/MediaFile;->sMimeTypeToFormatMap:Ljava/util/HashMap;
-Landroid/media/MediaFormat;->getMap()Ljava/util/Map;
-Landroid/media/MediaFormat;->mMap:Ljava/util/Map;
-Landroid/media/MediaHTTPConnection;-><init>()V
-Landroid/media/MediaHTTPConnection;->connect(Ljava/lang/String;Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/media/MediaHTTPConnection;->disconnect()V
-Landroid/media/MediaHTTPConnection;->getMIMEType()Ljava/lang/String;
-Landroid/media/MediaHTTPConnection;->getUri()Ljava/lang/String;
-Landroid/media/MediaHTTPConnection;->mAllowCrossDomainRedirect:Z
-Landroid/media/MediaHTTPConnection;->mAllowCrossProtocolRedirect:Z
-Landroid/media/MediaHTTPConnection;->mConnection:Ljava/net/HttpURLConnection;
-Landroid/media/MediaHTTPConnection;->mCurrentOffset:J
-Landroid/media/MediaHTTPConnection;->mHeaders:Ljava/util/Map;
-Landroid/media/MediaHTTPConnection;->mTotalSize:J
-Landroid/media/MediaHTTPConnection;->mURL:Ljava/net/URL;
-Landroid/media/MediaHTTPConnection;->readAt(JI)I
-Landroid/media/MediaHTTPService;->createHttpServiceBinderIfNecessary(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/media/MediaInserter;->flushAll()V
-Landroid/media/MediaMetadata;->getKeyFromMetadataEditorKey(I)Ljava/lang/String;
-Landroid/media/MediaMetadataRetriever;->getEmbeddedPicture(I)[B
-Landroid/media/MediaMetadataRetriever;->native_finalize()V
-Landroid/media/MediaMetadataRetriever;->native_init()V
-Landroid/media/MediaMetadataRetriever;->native_setup()V
-Landroid/media/MediaMuxer;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/media/MediaMuxer;->mNativeObject:J
-Landroid/media/MediaMuxer;->mState:I
-Landroid/media/MediaMuxer;->MUXER_STATE_STARTED:I
-Landroid/media/MediaMuxer;->MUXER_STATE_STOPPED:I
-Landroid/media/MediaMuxer;->MUXER_STATE_UNINITIALIZED:I
-Landroid/media/MediaMuxer;->nativeRelease(J)V
-Landroid/media/MediaMuxer;->nativeSetup(Ljava/io/FileDescriptor;I)J
-Landroid/media/MediaPlayer$TrackInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/media/MediaPlayer2$TrackInfo;->getLanguage()Ljava/lang/String;
-Landroid/media/MediaPlayer2$TrackInfo;->getTrackType()I
-Landroid/media/MediaPlayer;->addSubtitleSource(Ljava/io/InputStream;Landroid/media/MediaFormat;)V
-Landroid/media/MediaPlayer;->BYPASS_METADATA_FILTER:Z
-Landroid/media/MediaPlayer;->getMediaTimeProvider()Landroid/media/MediaTimeProvider;
-Landroid/media/MediaPlayer;->getMetadata(ZZ)Landroid/media/Metadata;
-Landroid/media/MediaPlayer;->invoke(Landroid/os/Parcel;Landroid/os/Parcel;)V
-Landroid/media/MediaPlayer;->MEDIA_INFO_EXTERNAL_METADATA_UPDATE:I
-Landroid/media/MediaPlayer;->MEDIA_INFO_TIMED_TEXT_ERROR:I
-Landroid/media/MediaPlayer;->METADATA_ALL:Z
-Landroid/media/MediaPlayer;->mEventHandler:Landroid/media/MediaPlayer$EventHandler;
-Landroid/media/MediaPlayer;->mOnCompletionListener:Landroid/media/MediaPlayer$OnCompletionListener;
-Landroid/media/MediaPlayer;->mOnErrorListener:Landroid/media/MediaPlayer$OnErrorListener;
-Landroid/media/MediaPlayer;->mOnInfoListener:Landroid/media/MediaPlayer$OnInfoListener;
-Landroid/media/MediaPlayer;->mOnPreparedListener:Landroid/media/MediaPlayer$OnPreparedListener;
-Landroid/media/MediaPlayer;->mOnSeekCompleteListener:Landroid/media/MediaPlayer$OnSeekCompleteListener;
-Landroid/media/MediaPlayer;->mOnTimedTextListener:Landroid/media/MediaPlayer$OnTimedTextListener;
-Landroid/media/MediaPlayer;->newRequest()Landroid/os/Parcel;
-Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;Ljava/util/Map;)V
-Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)V
-Landroid/media/MediaPlayer;->setDataSource(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/util/List;)V
-Landroid/media/MediaPlayer;->setParameter(ILandroid/os/Parcel;)Z
-Landroid/media/MediaPlayer;->setRetransmitEndpoint(Ljava/net/InetSocketAddress;)V
-Landroid/media/MediaPlayer;->setSubtitleAnchor(Landroid/media/SubtitleController;Landroid/media/SubtitleController$Anchor;)V
-Landroid/media/MediaRecorder;->mEventHandler:Landroid/media/MediaRecorder$EventHandler;
-Landroid/media/MediaRecorder;->mFd:Ljava/io/FileDescriptor;
-Landroid/media/MediaRecorder;->mOnErrorListener:Landroid/media/MediaRecorder$OnErrorListener;
-Landroid/media/MediaRecorder;->mOnInfoListener:Landroid/media/MediaRecorder$OnInfoListener;
-Landroid/media/MediaRecorder;->mPath:Ljava/lang/String;
-Landroid/media/MediaRecorder;->mSurface:Landroid/view/Surface;
-Landroid/media/MediaRecorder;->native_finalize()V
-Landroid/media/MediaRecorder;->native_init()V
-Landroid/media/MediaRecorder;->native_reset()V
-Landroid/media/MediaRecorder;->native_setup(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/media/MediaRecorder;->setParameter(Ljava/lang/String;)V
-Landroid/media/MediaRecorder;->_prepare()V
-Landroid/media/MediaRouter$RouteInfo;->getDeviceAddress()Ljava/lang/String;
-Landroid/media/MediaRouter$RouteInfo;->getName(Landroid/content/res/Resources;)Ljava/lang/CharSequence;
-Landroid/media/MediaRouter$RouteInfo;->getStatusCode()I
-Landroid/media/MediaRouter$RouteInfo;->isDefault()Z
-Landroid/media/MediaRouter$RouteInfo;->isSelected()Z
-Landroid/media/MediaRouter$RouteInfo;->matchesTypes(I)Z
-Landroid/media/MediaRouter$RouteInfo;->mNameResId:I
-Landroid/media/MediaRouter$RouteInfo;->select()V
-Landroid/media/MediaRouter$RouteInfo;->STATUS_CONNECTING:I
-Landroid/media/MediaRouter;->getSelectedRoute()Landroid/media/MediaRouter$RouteInfo;
-Landroid/media/MediaRouter;->selectRouteInt(ILandroid/media/MediaRouter$RouteInfo;Z)V
-Landroid/media/MediaScanner$FileEntry;-><init>(JLjava/lang/String;JI)V
-Landroid/media/MediaScanner$FileEntry;->mLastModifiedChanged:Z
-Landroid/media/MediaScanner$FileEntry;->mRowId:J
-Landroid/media/MediaScanner$MyMediaScannerClient;->beginFile(Ljava/lang/String;Ljava/lang/String;JJZZ)Landroid/media/MediaScanner$FileEntry;
-Landroid/media/MediaScanner$MyMediaScannerClient;->doScanFile(Ljava/lang/String;Ljava/lang/String;JJZZZ)Landroid/net/Uri;
-Landroid/media/MediaScanner$MyMediaScannerClient;->endFile(Landroid/media/MediaScanner$FileEntry;ZZZZZ)Landroid/net/Uri;
-Landroid/media/MediaScanner$MyMediaScannerClient;->getFileTypeFromDrm(Ljava/lang/String;)I
-Landroid/media/MediaScanner$MyMediaScannerClient;->handleStringTag(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/media/MediaScanner$MyMediaScannerClient;->mFileType:I
-Landroid/media/MediaScanner$MyMediaScannerClient;->mIsDrm:Z
-Landroid/media/MediaScanner$MyMediaScannerClient;->mMimeType:Ljava/lang/String;
-Landroid/media/MediaScanner$MyMediaScannerClient;->mNoMedia:Z
-Landroid/media/MediaScanner$MyMediaScannerClient;->mPath:Ljava/lang/String;
-Landroid/media/MediaScanner$MyMediaScannerClient;->scanFile(Ljava/lang/String;JJZZ)V
-Landroid/media/MediaScanner$MyMediaScannerClient;->setMimeType(Ljava/lang/String;)V
-Landroid/media/MediaScanner$MyMediaScannerClient;->toValues()Landroid/content/ContentValues;
-Landroid/media/MediaScanner;-><init>(Landroid/content/Context;Ljava/lang/String;)V
-Landroid/media/MediaScanner;->FILES_PRESCAN_PROJECTION:[Ljava/lang/String;
-Landroid/media/MediaScanner;->isDrmEnabled()Z
-Landroid/media/MediaScanner;->isNoMediaPath(Ljava/lang/String;)Z
-Landroid/media/MediaScanner;->makeEntryFor(Ljava/lang/String;)Landroid/media/MediaScanner$FileEntry;
-Landroid/media/MediaScanner;->mAudioUri:Landroid/net/Uri;
-Landroid/media/MediaScanner;->mClient:Landroid/media/MediaScanner$MyMediaScannerClient;
-Landroid/media/MediaScanner;->mContext:Landroid/content/Context;
-Landroid/media/MediaScanner;->mDefaultAlarmAlertFilename:Ljava/lang/String;
-Landroid/media/MediaScanner;->mDefaultNotificationFilename:Ljava/lang/String;
-Landroid/media/MediaScanner;->mDefaultRingtoneFilename:Ljava/lang/String;
-Landroid/media/MediaScanner;->mFilesUri:Landroid/net/Uri;
-Landroid/media/MediaScanner;->mMediaInserter:Landroid/media/MediaInserter;
-Landroid/media/MediaScanner;->mPackageName:Ljava/lang/String;
-Landroid/media/MediaScanner;->postscan([Ljava/lang/String;)V
-Landroid/media/MediaScanner;->prescan(Ljava/lang/String;Z)V
-Landroid/media/MediaScanner;->scanSingleFile(Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri;
-Landroid/media/MediaScanner;->setLocale(Ljava/lang/String;)V
-Landroid/media/Metadata;-><init>()V
-Landroid/media/Metadata;->getBoolean(I)Z
-Landroid/media/Metadata;->getByteArray(I)[B
-Landroid/media/Metadata;->getDate(I)Ljava/util/Date;
-Landroid/media/Metadata;->getDouble(I)D
-Landroid/media/Metadata;->getInt(I)I
-Landroid/media/Metadata;->getLong(I)J
-Landroid/media/Metadata;->getString(I)Ljava/lang/String;
-Landroid/media/Metadata;->has(I)Z
-Landroid/media/Metadata;->keySet()Ljava/util/Set;
-Landroid/media/Metadata;->parse(Landroid/os/Parcel;)Z
-Landroid/media/Metadata;->PAUSE_AVAILABLE:I
-Landroid/media/Metadata;->SEEK_AVAILABLE:I
-Landroid/media/Metadata;->SEEK_BACKWARD_AVAILABLE:I
-Landroid/media/Metadata;->SEEK_FORWARD_AVAILABLE:I
-Landroid/media/MicrophoneInfo;-><init>(Ljava/lang/String;ILjava/lang/String;IIILandroid/media/MicrophoneInfo$Coordinate3F;Landroid/media/MicrophoneInfo$Coordinate3F;Ljava/util/List;Ljava/util/List;FFFI)V
-Landroid/media/MiniThumbFile;->reset()V
-Landroid/media/PlaybackParams;->mAudioFallbackMode:I
-Landroid/media/PlaybackParams;->mAudioStretchMode:I
-Landroid/media/PlaybackParams;->mPitch:F
-Landroid/media/PlaybackParams;->mSet:I
-Landroid/media/PlaybackParams;->mSpeed:F
-Landroid/media/PlaybackParams;->SET_AUDIO_FALLBACK_MODE:I
-Landroid/media/PlaybackParams;->SET_AUDIO_STRETCH_MODE:I
-Landroid/media/PlaybackParams;->SET_PITCH:I
-Landroid/media/PlaybackParams;->SET_SPEED:I
 Landroid/media/projection/IMediaProjectionManager;->hasProjectionPermission(ILjava/lang/String;)Z
-Landroid/media/RemoteControlClient;->MEDIA_POSITION_READABLE:I
-Landroid/media/RemoteControlClient;->MEDIA_POSITION_WRITABLE:I
-Landroid/media/RemoteController;->getUpdateListener()Landroid/media/RemoteController$OnClientUpdateListener;
-Landroid/media/RemoteController;->mCurrentSession:Landroid/media/session/MediaController;
-Landroid/media/RemoteController;->setArtworkConfiguration(ZII)Z
-Landroid/media/RemoteDisplay;->dispose()V
-Landroid/media/RemoteDisplay;->notifyDisplayConnected(Landroid/view/Surface;IIII)V
-Landroid/media/RemoteDisplay;->notifyDisplayDisconnected()V
-Landroid/media/RemoteDisplay;->notifyDisplayError(I)V
-Landroid/media/RemoteDisplayState;-><init>()V
-Landroid/media/RemoteDisplayState;->displays:Ljava/util/ArrayList;
-Landroid/media/Ringtone;-><init>(Landroid/content/Context;Z)V
-Landroid/media/Ringtone;->getUri()Landroid/net/Uri;
-Landroid/media/Ringtone;->mLocalPlayer:Landroid/media/MediaPlayer;
-Landroid/media/Ringtone;->mUri:Landroid/net/Uri;
-Landroid/media/Ringtone;->setUri(Landroid/net/Uri;)V
-Landroid/media/RingtoneManager;->getInternalRingtones()Landroid/database/Cursor;
-Landroid/media/RingtoneManager;->getMediaRingtones(Landroid/content/Context;)Landroid/database/Cursor;
-Landroid/media/RingtoneManager;->getRingtone(Landroid/content/Context;Landroid/net/Uri;I)Landroid/media/Ringtone;
-Landroid/media/RingtoneManager;->mCursor:Landroid/database/Cursor;
 Landroid/media/session/ISessionManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/session/ISessionManager;
-Landroid/media/session/MediaController;->controlsSameSession(Landroid/media/session/MediaController;)Z
-Landroid/media/session/MediaSession$QueueItem;->mId:J
-Landroid/media/session/MediaSession;->getCallingPackage()Ljava/lang/String;
-Landroid/media/session/MediaSession;->mCallback:Landroid/media/session/MediaSession$CallbackMessageHandler;
-Landroid/media/session/MediaSessionLegacyHelper;->getHelper(Landroid/content/Context;)Landroid/media/session/MediaSessionLegacyHelper;
-Landroid/media/session/MediaSessionManager;->getActiveSessionsForUser(Landroid/content/ComponentName;I)Ljava/util/List;
-Landroid/media/soundtrigger/SoundTriggerDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer;
-Landroid/media/soundtrigger/SoundTriggerDetector$EventPayload;->getData()[B
-Landroid/media/soundtrigger/SoundTriggerManager;->isRecognitionActive(Ljava/util/UUID;)Z
-Landroid/media/soundtrigger/SoundTriggerManager;->loadSoundModel(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;)I
-Landroid/media/soundtrigger/SoundTriggerManager;->startRecognition(Ljava/util/UUID;Landroid/os/Bundle;Landroid/content/ComponentName;Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)I
-Landroid/media/soundtrigger/SoundTriggerManager;->stopRecognition(Ljava/util/UUID;)I
-Landroid/media/soundtrigger/SoundTriggerManager;->unloadSoundModel(Ljava/util/UUID;)I
-Landroid/media/SubtitleController;-><init>(Landroid/content/Context;Landroid/media/MediaTimeProvider;Landroid/media/SubtitleController$Listener;)V
-Landroid/media/SubtitleController;->hide()V
-Landroid/media/SubtitleController;->mHandler:Landroid/os/Handler;
-Landroid/media/SubtitleController;->registerRenderer(Landroid/media/SubtitleController$Renderer;)V
-Landroid/media/SubtitleController;->reset()V
-Landroid/media/SubtitleController;->show()V
-Landroid/media/SubtitleTrack$RenderingWidget;->draw(Landroid/graphics/Canvas;)V
-Landroid/media/SubtitleTrack$RenderingWidget;->onAttachedToWindow()V
-Landroid/media/SubtitleTrack$RenderingWidget;->onDetachedFromWindow()V
-Landroid/media/SubtitleTrack$RenderingWidget;->setOnChangedListener(Landroid/media/SubtitleTrack$RenderingWidget$OnChangedListener;)V
-Landroid/media/SubtitleTrack$RenderingWidget;->setSize(II)V
-Landroid/media/ThumbnailUtils;->closeSilently(Landroid/os/ParcelFileDescriptor;)V
-Landroid/media/ThumbnailUtils;->computeInitialSampleSize(Landroid/graphics/BitmapFactory$Options;II)I
-Landroid/media/ThumbnailUtils;->computeSampleSize(Landroid/graphics/BitmapFactory$Options;II)I
-Landroid/media/ThumbnailUtils;->createImageThumbnail(Ljava/lang/String;I)Landroid/graphics/Bitmap;
-Landroid/media/ThumbnailUtils;->createThumbnailFromEXIF(Ljava/lang/String;IILandroid/media/ThumbnailUtils$SizedThumbnailBitmap;)V
-Landroid/media/ThumbnailUtils;->makeInputStream(Landroid/net/Uri;Landroid/content/ContentResolver;)Landroid/os/ParcelFileDescriptor;
-Landroid/media/ThumbnailUtils;->TARGET_SIZE_MICRO_THUMBNAIL:I
-Landroid/media/ThumbnailUtils;->transform(Landroid/graphics/Matrix;Landroid/graphics/Bitmap;III)Landroid/graphics/Bitmap;
-Landroid/media/TimedText;->getObject(I)Ljava/lang/Object;
-Landroid/media/ToneGenerator;->mNativeContext:J
-Landroid/media/TtmlRenderer;-><init>(Landroid/content/Context;)V
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_16_9:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_1_1:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_2_3:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_3_2:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_4_3:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->AVAILABILITY_AVAILABLE:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->AVAILABILITY_FREE_WITH_SUBSCRIPTION:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->AVAILABILITY_PAID_CONTENT:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_AUTHOR:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_AVAILABILITY:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_BROWSABLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_CONTENT_ID:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_DURATION_MILLIS:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_INTENT_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_INTERACTION_COUNT:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_INTERACTION_TYPE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_INTERNAL_PROVIDER_ID:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_ITEM_COUNT:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_LAST_PLAYBACK_POSITION_MILLIS:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_LIVE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_LOGO_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_OFFER_PRICE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_POSTER_ART_ASPECT_RATIO:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_PREVIEW_VIDEO_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_RELEASE_DATE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_STARTING_PRICE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_THUMBNAIL_ASPECT_RATIO:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_TRANSIENT:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_TYPE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_FANS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_FOLLOWERS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_LIKES:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_LISTENS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_THUMBS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_VIEWERS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_VIEWS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_ALBUM:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_ARTIST:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_CHANNEL:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_CLIP:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_EVENT:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_MOVIE:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_PLAYLIST:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_STATION:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_TRACK:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_TV_EPISODE:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_TV_SEASON:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_TV_SERIES:I
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_AUDIO_LANGUAGE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_CANONICAL_GENRE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_CONTENT_RATING:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_EPISODE_DISPLAY_NUMBER:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_EPISODE_TITLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_DATA:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_FLAG1:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_FLAG2:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_FLAG3:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_FLAG4:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_LONG_DESCRIPTION:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_POSTER_ART_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_REVIEW_RATING:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_REVIEW_RATING_STYLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SEARCHABLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SEASON_DISPLAY_NUMBER:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SEASON_TITLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SHORT_DESCRIPTION:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_THUMBNAIL_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_TITLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_VERSION_NUMBER:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_VIDEO_HEIGHT:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_VIDEO_WIDTH:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->REVIEW_RATING_STYLE_PERCENTAGE:I
-Landroid/media/tv/TvContract$ProgramColumns;->REVIEW_RATING_STYLE_STARS:I
-Landroid/media/tv/TvContract$ProgramColumns;->REVIEW_RATING_STYLE_THUMBS_UP_DOWN:I
-Landroid/media/tv/TvInputInfo;->getComponent()Landroid/content/ComponentName;
-Landroid/media/tv/TvInputService$Session;->mOverlayFrame:Landroid/graphics/Rect;
-Landroid/media/VolumeShaper$Configuration;-><init>(IIIDI[F[F)V
-Landroid/media/VolumeShaper$Configuration;->mDurationMs:D
-Landroid/media/VolumeShaper$Configuration;->mId:I
-Landroid/media/VolumeShaper$Configuration;->mInterpolatorType:I
-Landroid/media/VolumeShaper$Configuration;->mOptionFlags:I
-Landroid/media/VolumeShaper$Configuration;->mTimes:[F
-Landroid/media/VolumeShaper$Configuration;->mType:I
-Landroid/media/VolumeShaper$Configuration;->mVolumes:[F
-Landroid/media/VolumeShaper$Operation;-><init>(IIF)V
-Landroid/media/VolumeShaper$Operation;->mFlags:I
-Landroid/media/VolumeShaper$Operation;->mReplaceId:I
-Landroid/media/VolumeShaper$Operation;->mXOffset:F
-Landroid/media/VolumeShaper$State;-><init>(FF)V
-Landroid/media/VolumeShaper$State;->mVolume:F
-Landroid/media/VolumeShaper$State;->mXOffset:F
-Landroid/media/WebVttRenderer;-><init>(Landroid/content/Context;)V
-Landroid/mtp/MtpPropertyList;->append(IIIJ)V
-Landroid/mtp/MtpPropertyList;->append(IILjava/lang/String;)V
-Landroid/mtp/MtpStorage;->getPath()Ljava/lang/String;
-Landroid/mtp/MtpStorage;->getStorageId()I
-Landroid/net/ConnectivityManager;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String;
-Landroid/net/ConnectivityManager;->EXTRA_ACTIVE_TETHER:Ljava/lang/String;
-Landroid/net/ConnectivityManager;->EXTRA_AVAILABLE_TETHER:Ljava/lang/String;
-Landroid/net/ConnectivityManager;->EXTRA_ERRORED_TETHER:Ljava/lang/String;
-Landroid/net/ConnectivityManager;->from(Landroid/content/Context;)Landroid/net/ConnectivityManager;
-Landroid/net/ConnectivityManager;->getActiveLinkProperties()Landroid/net/LinkProperties;
-Landroid/net/ConnectivityManager;->getActiveNetworkInfoForUid(I)Landroid/net/NetworkInfo;
-Landroid/net/ConnectivityManager;->getDefaultNetworkCapabilitiesForUser(I)[Landroid/net/NetworkCapabilities;
-Landroid/net/ConnectivityManager;->getInstance()Landroid/net/ConnectivityManager;
-Landroid/net/ConnectivityManager;->getLastTetherError(Ljava/lang/String;)I
-Landroid/net/ConnectivityManager;->getLinkProperties(I)Landroid/net/LinkProperties;
-Landroid/net/ConnectivityManager;->getMobileDataEnabled()Z
-Landroid/net/ConnectivityManager;->getNetworkForType(I)Landroid/net/Network;
-Landroid/net/ConnectivityManager;->getNetworkTypeName(I)Ljava/lang/String;
-Landroid/net/ConnectivityManager;->getTetherableBluetoothRegexs()[Ljava/lang/String;
-Landroid/net/ConnectivityManager;->getTetherableIfaces()[Ljava/lang/String;
-Landroid/net/ConnectivityManager;->getTetherableUsbRegexs()[Ljava/lang/String;
-Landroid/net/ConnectivityManager;->getTetherableWifiRegexs()[Ljava/lang/String;
-Landroid/net/ConnectivityManager;->getTetheredIfaces()[Ljava/lang/String;
-Landroid/net/ConnectivityManager;->getTetheringErroredIfaces()[Ljava/lang/String;
-Landroid/net/ConnectivityManager;->INET_CONDITION_ACTION:Ljava/lang/String;
-Landroid/net/ConnectivityManager;->isNetworkSupported(I)Z
-Landroid/net/ConnectivityManager;->isNetworkTypeMobile(I)Z
-Landroid/net/ConnectivityManager;->mService:Landroid/net/IConnectivityManager;
-Landroid/net/ConnectivityManager;->networkCapabilitiesForFeature(ILjava/lang/String;)Landroid/net/NetworkCapabilities;
-Landroid/net/ConnectivityManager;->registerNetworkFactory(Landroid/os/Messenger;Ljava/lang/String;)V
-Landroid/net/ConnectivityManager;->removeRequestForFeature(Landroid/net/NetworkCapabilities;)Z
-Landroid/net/ConnectivityManager;->requestNetworkForFeatureLocked(Landroid/net/NetworkCapabilities;)Landroid/net/NetworkRequest;
-Landroid/net/ConnectivityManager;->requestRouteToHostAddress(ILjava/net/InetAddress;)Z
-Landroid/net/ConnectivityManager;->setBackgroundDataSetting(Z)V
-Landroid/net/ConnectivityManager;->setProcessDefaultNetworkForHostResolution(Landroid/net/Network;)Z
-Landroid/net/ConnectivityManager;->setUsbTethering(Z)I
-Landroid/net/ConnectivityManager;->sLegacyRequests:Ljava/util/HashMap;
-Landroid/net/ConnectivityManager;->TYPE_MOBILE_CBS:I
-Landroid/net/ConnectivityManager;->TYPE_MOBILE_EMERGENCY:I
-Landroid/net/ConnectivityManager;->TYPE_MOBILE_FOTA:I
-Landroid/net/ConnectivityManager;->TYPE_MOBILE_IA:I
-Landroid/net/ConnectivityManager;->TYPE_MOBILE_IMS:I
-Landroid/net/ConnectivityManager;->TYPE_NONE:I
-Landroid/net/ConnectivityManager;->TYPE_PROXY:I
-Landroid/net/ConnectivityManager;->TYPE_WIFI_P2P:I
-Landroid/net/ConnectivityManager;->unregisterNetworkFactory(Landroid/os/Messenger;)V
-Landroid/net/EthernetManager$Listener;->onAvailabilityChanged(Ljava/lang/String;Z)V
-Landroid/net/EthernetManager;->addListener(Landroid/net/EthernetManager$Listener;)V
-Landroid/net/EthernetManager;->getAvailableInterfaces()[Ljava/lang/String;
-Landroid/net/EthernetManager;->getConfiguration(Ljava/lang/String;)Landroid/net/IpConfiguration;
-Landroid/net/EthernetManager;->isAvailable()Z
-Landroid/net/EthernetManager;->isAvailable(Ljava/lang/String;)Z
-Landroid/net/EthernetManager;->removeListener(Landroid/net/EthernetManager$Listener;)V
-Landroid/net/EthernetManager;->setConfiguration(Ljava/lang/String;Landroid/net/IpConfiguration;)V
-Landroid/net/http/SslCertificate;->getDigest(Ljava/security/cert/X509Certificate;Ljava/lang/String;)Ljava/lang/String;
-Landroid/net/http/SslCertificate;->getSerialNumber(Ljava/security/cert/X509Certificate;)Ljava/lang/String;
-Landroid/net/http/SslCertificate;->inflateCertificateView(Landroid/content/Context;)Landroid/view/View;
-Landroid/net/http/SslCertificate;->mX509Certificate:Ljava/security/cert/X509Certificate;
-Landroid/net/http/SslError;->mCertificate:Landroid/net/http/SslCertificate;
-Landroid/net/http/SslError;->mErrors:I
-Landroid/net/http/SslError;->mUrl:Ljava/lang/String;
 Landroid/net/IConnectivityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveLinkProperties()Landroid/net/LinkProperties;
 Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveNetworkInfo()Landroid/net/NetworkInfo;
@@ -3344,205 +581,10 @@
 Landroid/net/INetworkStatsSession;->close()V
 Landroid/net/INetworkStatsSession;->getSummaryForAllUid(Landroid/net/NetworkTemplate;JJZ)Landroid/net/NetworkStats;
 Landroid/net/INetworkStatsSession;->getSummaryForNetwork(Landroid/net/NetworkTemplate;JJ)Landroid/net/NetworkStats;
-Landroid/net/InterfaceConfiguration;->clearFlag(Ljava/lang/String;)V
-Landroid/net/InterfaceConfiguration;->getFlags()Ljava/lang/Iterable;
-Landroid/net/InterfaceConfiguration;->setFlag(Ljava/lang/String;)V
-Landroid/net/InterfaceConfiguration;->setInterfaceDown()V
-Landroid/net/InterfaceConfiguration;->setInterfaceUp()V
-Landroid/net/IpConfiguration$IpAssignment;->STATIC:Landroid/net/IpConfiguration$IpAssignment;
-Landroid/net/IpConfiguration$ProxySettings;->NONE:Landroid/net/IpConfiguration$ProxySettings;
-Landroid/net/IpConfiguration;-><init>(Landroid/net/IpConfiguration$IpAssignment;Landroid/net/IpConfiguration$ProxySettings;Landroid/net/StaticIpConfiguration;Landroid/net/ProxyInfo;)V
-Landroid/net/IpConfiguration;->httpProxy:Landroid/net/ProxyInfo;
-Landroid/net/LinkAddress;->address:Ljava/net/InetAddress;
-Landroid/net/LinkAddress;->getNetworkPrefixLength()I
-Landroid/net/LinkAddress;->prefixLength:I
-Landroid/net/LinkProperties;->addLinkAddress(Landroid/net/LinkAddress;)Z
-Landroid/net/LinkProperties;->getAddresses()Ljava/util/List;
-Landroid/net/LinkProperties;->getAllAddresses()Ljava/util/List;
-Landroid/net/LinkProperties;->getAllLinkAddresses()Ljava/util/List;
-Landroid/net/LinkProperties;->getTcpBufferSizes()Ljava/lang/String;
-Landroid/net/LinkProperties;->isIdenticalHttpProxy(Landroid/net/LinkProperties;)Z
-Landroid/net/LinkProperties;->isIdenticalInterfaceName(Landroid/net/LinkProperties;)Z
-Landroid/net/LinkProperties;->mIfaceName:Ljava/lang/String;
-Landroid/net/LinkProperties;->setHttpProxy(Landroid/net/ProxyInfo;)V
-Landroid/net/LinkQualityInfo;->setDataSampleDuration(I)V
-Landroid/net/LinkQualityInfo;->setLastDataSampleTime(J)V
-Landroid/net/LinkQualityInfo;->setPacketCount(J)V
-Landroid/net/LinkQualityInfo;->setPacketErrorCount(J)V
-Landroid/net/LocalSocket;->impl:Landroid/net/LocalSocketImpl;
-Landroid/net/LocalSocketImpl;-><init>()V
-Landroid/net/LocalSocketImpl;->inboundFileDescriptors:[Ljava/io/FileDescriptor;
-Landroid/net/LocalSocketImpl;->outboundFileDescriptors:[Ljava/io/FileDescriptor;
 Landroid/net/MobileLinkQualityInfo;-><init>()V
-Landroid/net/MobileLinkQualityInfo;->getMobileNetworkType()I
-Landroid/net/MobileLinkQualityInfo;->setCdmaDbm(I)V
-Landroid/net/MobileLinkQualityInfo;->setCdmaEcio(I)V
-Landroid/net/MobileLinkQualityInfo;->setEvdoDbm(I)V
-Landroid/net/MobileLinkQualityInfo;->setEvdoEcio(I)V
-Landroid/net/MobileLinkQualityInfo;->setEvdoSnr(I)V
-Landroid/net/MobileLinkQualityInfo;->setGsmErrorRate(I)V
-Landroid/net/MobileLinkQualityInfo;->setLteCqi(I)V
-Landroid/net/MobileLinkQualityInfo;->setLteRsrp(I)V
-Landroid/net/MobileLinkQualityInfo;->setLteRsrq(I)V
-Landroid/net/MobileLinkQualityInfo;->setLteRssnr(I)V
-Landroid/net/MobileLinkQualityInfo;->setLteSignalStrength(I)V
-Landroid/net/MobileLinkQualityInfo;->setMobileNetworkType(I)V
-Landroid/net/MobileLinkQualityInfo;->setRssi(I)V
-Landroid/net/NetworkAgent;->sendNetworkInfo(Landroid/net/NetworkInfo;)V
-Landroid/net/NetworkCapabilities;-><init>()V
-Landroid/net/NetworkCapabilities;->addCapability(I)Landroid/net/NetworkCapabilities;
-Landroid/net/NetworkCapabilities;->addTransportType(I)Landroid/net/NetworkCapabilities;
-Landroid/net/NetworkCapabilities;->mNetworkCapabilities:J
-Landroid/net/NetworkCapabilities;->mSignalStrength:I
-Landroid/net/NetworkCapabilities;->removeCapability(I)Landroid/net/NetworkCapabilities;
-Landroid/net/NetworkCapabilities;->setSignalStrength(I)Landroid/net/NetworkCapabilities;
-Landroid/net/NetworkFactory;-><init>(Landroid/os/Looper;Landroid/content/Context;Ljava/lang/String;Landroid/net/NetworkCapabilities;)V
-Landroid/net/NetworkFactory;->dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V
-Landroid/net/NetworkFactory;->setScoreFilter(I)V
-Landroid/net/NetworkInfo;-><init>(IILjava/lang/String;Ljava/lang/String;)V
-Landroid/net/NetworkInfo;-><init>(Landroid/net/NetworkInfo;)V
-Landroid/net/NetworkInfo;->setDetailedState(Landroid/net/NetworkInfo$DetailedState;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/net/NetworkInfo;->setFailover(Z)V
-Landroid/net/NetworkInfo;->setIsAvailable(Z)V
-Landroid/net/NetworkInfo;->setRoaming(Z)V
-Landroid/net/NetworkInfo;->setSubtype(ILjava/lang/String;)V
-Landroid/net/NetworkPolicy;-><init>(Landroid/net/NetworkTemplate;ILjava/lang/String;JJJJZZ)V
-Landroid/net/NetworkPolicy;->clearSnooze()V
-Landroid/net/NetworkPolicy;->compareTo(Landroid/net/NetworkPolicy;)I
-Landroid/net/NetworkPolicy;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/NetworkPolicy;->inferred:Z
-Landroid/net/NetworkPolicy;->isOverLimit(J)Z
-Landroid/net/NetworkPolicy;->isOverWarning(J)Z
-Landroid/net/NetworkPolicy;->limitBytes:J
-Landroid/net/NetworkPolicy;->metered:Z
-Landroid/net/NetworkPolicy;->template:Landroid/net/NetworkTemplate;
-Landroid/net/NetworkPolicy;->warningBytes:J
-Landroid/net/NetworkPolicyManager;->from(Landroid/content/Context;)Landroid/net/NetworkPolicyManager;
-Landroid/net/NetworkPolicyManager;->getNetworkPolicies()[Landroid/net/NetworkPolicy;
-Landroid/net/NetworkPolicyManager;->getRestrictBackground()Z
-Landroid/net/NetworkPolicyManager;->getUidPolicy(I)I
-Landroid/net/NetworkPolicyManager;->getUidsWithPolicy(I)[I
-Landroid/net/NetworkPolicyManager;->mService:Landroid/net/INetworkPolicyManager;
-Landroid/net/NetworkPolicyManager;->registerListener(Landroid/net/INetworkPolicyListener;)V
-Landroid/net/NetworkPolicyManager;->setRestrictBackground(Z)V
-Landroid/net/NetworkPolicyManager;->setUidPolicy(II)V
-Landroid/net/NetworkPolicyManager;->unregisterListener(Landroid/net/INetworkPolicyListener;)V
-Landroid/net/NetworkQuotaInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/NetworkRequest$Builder;->clearCapabilities()Landroid/net/NetworkRequest$Builder;
-Landroid/net/NetworkRequest;->legacyType:I
-Landroid/net/NetworkRequest;->requestId:I
-Landroid/net/NetworkState;-><init>(Landroid/os/Parcel;)V
-Landroid/net/NetworkState;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/NetworkStats;-><init>(Landroid/os/Parcel;)V
-Landroid/net/NetworkStats;->capacity:I
-Landroid/net/NetworkStats;->combineAllValues(Landroid/net/NetworkStats;)V
-Landroid/net/NetworkStats;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/NetworkStats;->defaultNetwork:[I
-Landroid/net/NetworkStats;->getTotal(Landroid/net/NetworkStats$Entry;)Landroid/net/NetworkStats$Entry;
-Landroid/net/NetworkStats;->getTotal(Landroid/net/NetworkStats$Entry;I)Landroid/net/NetworkStats$Entry;
-Landroid/net/NetworkStats;->getTotalBytes()J
-Landroid/net/NetworkStats;->getTotalIncludingTags(Landroid/net/NetworkStats$Entry;)Landroid/net/NetworkStats$Entry;
-Landroid/net/NetworkStats;->getUniqueUids()[I
-Landroid/net/NetworkStats;->getValues(ILandroid/net/NetworkStats$Entry;)Landroid/net/NetworkStats$Entry;
-Landroid/net/NetworkStats;->iface:[Ljava/lang/String;
-Landroid/net/NetworkStats;->metered:[I
-Landroid/net/NetworkStats;->operations:[J
-Landroid/net/NetworkStats;->roaming:[I
-Landroid/net/NetworkStats;->rxBytes:[J
-Landroid/net/NetworkStats;->rxPackets:[J
-Landroid/net/NetworkStats;->set:[I
-Landroid/net/NetworkStats;->size()I
-Landroid/net/NetworkStats;->size:I
-Landroid/net/NetworkStats;->tag:[I
-Landroid/net/NetworkStats;->txBytes:[J
-Landroid/net/NetworkStats;->txPackets:[J
-Landroid/net/NetworkStats;->uid:[I
-Landroid/net/NetworkStatsHistory$Entry;->bucketDuration:J
-Landroid/net/NetworkStatsHistory$Entry;->bucketStart:J
-Landroid/net/NetworkStatsHistory$Entry;->rxBytes:J
-Landroid/net/NetworkStatsHistory$Entry;->rxPackets:J
-Landroid/net/NetworkStatsHistory$Entry;->txPackets:J
-Landroid/net/NetworkStatsHistory;-><init>(J)V
-Landroid/net/NetworkStatsHistory;-><init>(Landroid/os/Parcel;)V
-Landroid/net/NetworkStatsHistory;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/NetworkStatsHistory;->getEnd()J
-Landroid/net/NetworkStatsHistory;->getIndexBefore(J)I
-Landroid/net/NetworkStatsHistory;->getValues(ILandroid/net/NetworkStatsHistory$Entry;)Landroid/net/NetworkStatsHistory$Entry;
-Landroid/net/NetworkStatsHistory;->getValues(JJJLandroid/net/NetworkStatsHistory$Entry;)Landroid/net/NetworkStatsHistory$Entry;
-Landroid/net/NetworkStatsHistory;->recordEntireHistory(Landroid/net/NetworkStatsHistory;)V
-Landroid/net/NetworkStatsHistory;->size()I
-Landroid/net/NetworkTemplate;-><init>(ILjava/lang/String;Ljava/lang/String;)V
-Landroid/net/NetworkTemplate;->buildTemplateEthernet()Landroid/net/NetworkTemplate;
-Landroid/net/NetworkTemplate;->buildTemplateMobileWildcard()Landroid/net/NetworkTemplate;
-Landroid/net/NetworkTemplate;->buildTemplateWifi()Landroid/net/NetworkTemplate;
-Landroid/net/NetworkTemplate;->buildTemplateWifiWildcard()Landroid/net/NetworkTemplate;
-Landroid/net/NetworkTemplate;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/NetworkTemplate;->getMatchRule()I
-Landroid/net/NetworkTemplate;->getSubscriberId()Ljava/lang/String;
-Landroid/net/NetworkTemplate;->normalize(Landroid/net/NetworkTemplate;[Ljava/lang/String;)Landroid/net/NetworkTemplate;
-Landroid/net/NetworkUtils;->intToInetAddress(I)Ljava/net/InetAddress;
-Landroid/net/NetworkUtils;->numericToInetAddress(Ljava/lang/String;)Ljava/net/InetAddress;
-Landroid/net/NetworkUtils;->prefixLengthToNetmaskInt(I)I
-Landroid/net/NetworkUtils;->trimV4AddrZeros(Ljava/lang/String;)Ljava/lang/String;
 Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager;
 Landroid/net/nsd/INsdManager;->getMessenger()Landroid/os/Messenger;
-Landroid/net/nsd/NsdServiceInfo;->setAttribute(Ljava/lang/String;[B)V
-Landroid/net/Proxy;->getProxy(Landroid/content/Context;Ljava/lang/String;)Ljava/net/Proxy;
-Landroid/net/Proxy;->setHttpProxySystemProperty(Landroid/net/ProxyInfo;)V
-Landroid/net/ProxyInfo;-><init>(Ljava/lang/String;ILjava/lang/String;)V
-Landroid/net/RouteInfo;-><init>(Landroid/net/LinkAddress;Ljava/net/InetAddress;)V
-Landroid/net/RouteInfo;-><init>(Landroid/net/LinkAddress;Ljava/net/InetAddress;Ljava/lang/String;)V
-Landroid/net/RouteInfo;-><init>(Ljava/net/InetAddress;)V
-Landroid/net/RouteInfo;->isHost()Z
-Landroid/net/RouteInfo;->mGateway:Ljava/net/InetAddress;
-Landroid/net/RouteInfo;->mIsHost:Z
 Landroid/net/SntpClient;-><init>()V
-Landroid/net/SSLCertificateSocketFactory;-><init>(ILandroid/net/SSLSessionCache;Z)V
-Landroid/net/SSLCertificateSocketFactory;->castToOpenSSLSocket(Ljava/net/Socket;)Lcom/android/org/conscrypt/OpenSSLSocketImpl;
-Landroid/net/SSLCertificateSocketFactory;->getAlpnSelectedProtocol(Ljava/net/Socket;)[B
-Landroid/net/SSLCertificateSocketFactory;->getDelegate()Ljavax/net/ssl/SSLSocketFactory;
-Landroid/net/SSLCertificateSocketFactory;->INSECURE_TRUST_MANAGER:[Ljavax/net/ssl/TrustManager;
-Landroid/net/SSLCertificateSocketFactory;->isSslCheckRelaxed()Z
-Landroid/net/SSLCertificateSocketFactory;->makeSocketFactory([Ljavax/net/ssl/KeyManager;[Ljavax/net/ssl/TrustManager;)Ljavax/net/ssl/SSLSocketFactory;
-Landroid/net/SSLCertificateSocketFactory;->mAlpnProtocols:[B
-Landroid/net/SSLCertificateSocketFactory;->mChannelIdPrivateKey:Ljava/security/PrivateKey;
-Landroid/net/SSLCertificateSocketFactory;->mHandshakeTimeoutMillis:I
-Landroid/net/SSLCertificateSocketFactory;->mInsecureFactory:Ljavax/net/ssl/SSLSocketFactory;
-Landroid/net/SSLCertificateSocketFactory;->mKeyManagers:[Ljavax/net/ssl/KeyManager;
-Landroid/net/SSLCertificateSocketFactory;->mNpnProtocols:[B
-Landroid/net/SSLCertificateSocketFactory;->mSecure:Z
-Landroid/net/SSLCertificateSocketFactory;->mSecureFactory:Ljavax/net/ssl/SSLSocketFactory;
-Landroid/net/SSLCertificateSocketFactory;->mSessionCache:Lcom/android/org/conscrypt/SSLClientSessionCache;
-Landroid/net/SSLCertificateSocketFactory;->mTrustManagers:[Ljavax/net/ssl/TrustManager;
-Landroid/net/SSLCertificateSocketFactory;->setAlpnProtocols([[B)V
-Landroid/net/SSLCertificateSocketFactory;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
-Landroid/net/SSLCertificateSocketFactory;->setSoWriteTimeout(Ljava/net/Socket;I)V
-Landroid/net/SSLCertificateSocketFactory;->TAG:Ljava/lang/String;
-Landroid/net/SSLCertificateSocketFactory;->verifyHostname(Ljava/net/Socket;Ljava/lang/String;)V
-Landroid/net/SSLSessionCache;->mSessionCache:Lcom/android/org/conscrypt/SSLClientSessionCache;
-Landroid/net/StaticIpConfiguration;-><init>()V
-Landroid/net/StaticIpConfiguration;->gateway:Ljava/net/InetAddress;
-Landroid/net/StaticIpConfiguration;->ipAddress:Landroid/net/LinkAddress;
-Landroid/net/TrafficStats;->getMobileIfaces()[Ljava/lang/String;
-Landroid/net/TrafficStats;->getRxBytes(Ljava/lang/String;)J
-Landroid/net/TrafficStats;->getStatsService()Landroid/net/INetworkStatsService;
-Landroid/net/TrafficStats;->getTxBytes(Ljava/lang/String;)J
-Landroid/net/Uri;-><init>()V
-Landroid/net/Uri;->getCanonicalUri()Landroid/net/Uri;
-Landroid/net/Uri;->toSafeString()Ljava/lang/String;
-Landroid/net/VpnService$Builder;->mAddresses:Ljava/util/List;
-Landroid/net/VpnService$Builder;->mRoutes:Ljava/util/List;
-Landroid/net/WebAddress;->getAuthInfo()Ljava/lang/String;
-Landroid/net/WebAddress;->getHost()Ljava/lang/String;
-Landroid/net/WebAddress;->getPath()Ljava/lang/String;
-Landroid/net/WebAddress;->getPort()I
-Landroid/net/WebAddress;->getScheme()Ljava/lang/String;
-Landroid/net/WebAddress;->mHost:Ljava/lang/String;
-Landroid/net/WebAddress;->mPath:Ljava/lang/String;
-Landroid/net/WebAddress;->mPort:I
-Landroid/net/WebAddress;->mScheme:Ljava/lang/String;
-Landroid/net/WebAddress;->setHost(Ljava/lang/String;)V
-Landroid/net/WebAddress;->setPath(Ljava/lang/String;)V
 Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/wifi/IWifiManager$Stub;-><init>()V
 Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager;
@@ -3555,185 +597,6 @@
 Landroid/net/wifi/IWifiScanner$Stub;-><init>()V
 Landroid/net/wifi/IWifiScanner$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiScanner;
 Landroid/net/wifi/p2p/IWifiP2pManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/p2p/IWifiP2pManager;
-Landroid/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo;->createRequest(Ljava/lang/String;II)Ljava/lang/String;
-Landroid/net/wifi/p2p/nsd/WifiP2pServiceInfo;-><init>(Ljava/util/List;)V
-Landroid/net/wifi/p2p/nsd/WifiP2pServiceInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/wifi/p2p/nsd/WifiP2pServiceInfo;->mQueryList:Ljava/util/List;
-Landroid/net/wifi/p2p/nsd/WifiP2pServiceRequest;-><init>(ILjava/lang/String;)V
-Landroid/net/wifi/p2p/nsd/WifiP2pServiceRequest;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/wifi/p2p/WifiP2pConfig;-><init>(Ljava/lang/String;)V
-Landroid/net/wifi/p2p/WifiP2pConfig;->MIN_GROUP_OWNER_INTENT:I
-Landroid/net/wifi/p2p/WifiP2pConfig;->netId:I
-Landroid/net/wifi/p2p/WifiP2pDevice;-><init>(Ljava/lang/String;)V
-Landroid/net/wifi/p2p/WifiP2pDevice;->deviceCapability:I
-Landroid/net/wifi/p2p/WifiP2pDevice;->groupCapability:I
-Landroid/net/wifi/p2p/WifiP2pDevice;->update(Landroid/net/wifi/p2p/WifiP2pDevice;)V
-Landroid/net/wifi/p2p/WifiP2pDevice;->wfdInfo:Landroid/net/wifi/p2p/WifiP2pWfdInfo;
-Landroid/net/wifi/p2p/WifiP2pDevice;->wpsConfigMethodsSupported:I
-Landroid/net/wifi/p2p/WifiP2pDeviceList;->remove(Ljava/lang/String;)Landroid/net/wifi/p2p/WifiP2pDevice;
-Landroid/net/wifi/p2p/WifiP2pDeviceList;->update(Landroid/net/wifi/p2p/WifiP2pDevice;)V
-Landroid/net/wifi/p2p/WifiP2pGroup;-><init>(Ljava/lang/String;)V
-Landroid/net/wifi/p2p/WifiP2pGroup;->getNetworkId()I
-Landroid/net/wifi/p2p/WifiP2pGroup;->isClientListEmpty()Z
-Landroid/net/wifi/p2p/WifiP2pGroup;->setInterface(Ljava/lang/String;)V
-Landroid/net/wifi/p2p/WifiP2pGroup;->setIsGroupOwner(Z)V
-Landroid/net/wifi/p2p/WifiP2pGroup;->setNetworkId(I)V
-Landroid/net/wifi/p2p/WifiP2pGroup;->TEMPORARY_NET_ID:I
-Landroid/net/wifi/p2p/WifiP2pGroupList;-><init>(Landroid/net/wifi/p2p/WifiP2pGroupList;Landroid/net/wifi/p2p/WifiP2pGroupList$GroupDeleteListener;)V
-Landroid/net/wifi/p2p/WifiP2pGroupList;->getGroupList()Ljava/util/Collection;
-Landroid/net/wifi/p2p/WifiP2pGroupList;->mGroups:Landroid/util/LruCache;
-Landroid/net/wifi/p2p/WifiP2pManager$Channel;->mAsyncChannel:Lcom/android/internal/util/AsyncChannel;
-Landroid/net/wifi/p2p/WifiP2pManager$Channel;->putListener(Ljava/lang/Object;)I
-Landroid/net/wifi/p2p/WifiP2pManager;-><init>(Landroid/net/wifi/p2p/IWifiP2pManager;)V
-Landroid/net/wifi/p2p/WifiP2pManager;->CREATE_GROUP:I
-Landroid/net/wifi/p2p/WifiP2pManager;->deletePersistentGroup(Landroid/net/wifi/p2p/WifiP2pManager$Channel;ILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
-Landroid/net/wifi/p2p/WifiP2pManager;->requestPersistentGroupInfo(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/p2p/WifiP2pManager$PersistentGroupInfoListener;)V
-Landroid/net/wifi/p2p/WifiP2pManager;->setDeviceName(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Ljava/lang/String;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
-Landroid/net/wifi/p2p/WifiP2pManager;->setMiracastMode(I)V
-Landroid/net/wifi/p2p/WifiP2pManager;->setWFDInfo(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/p2p/WifiP2pWfdInfo;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
-Landroid/net/wifi/p2p/WifiP2pManager;->setWifiP2pChannels(Landroid/net/wifi/p2p/WifiP2pManager$Channel;IILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
-Landroid/net/wifi/p2p/WifiP2pManager;->startWps(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/WpsInfo;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V
-Landroid/net/wifi/p2p/WifiP2pProvDiscEvent;-><init>()V
-Landroid/net/wifi/p2p/WifiP2pProvDiscEvent;->device:Landroid/net/wifi/p2p/WifiP2pDevice;
-Landroid/net/wifi/p2p/WifiP2pProvDiscEvent;->event:I
-Landroid/net/wifi/p2p/WifiP2pProvDiscEvent;->pin:Ljava/lang/String;
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;-><init>()V
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;-><init>(III)V
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;-><init>(Landroid/net/wifi/p2p/WifiP2pWfdInfo;)V
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;->getDeviceType()I
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;->isWfdEnabled()Z
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;->setControlPort(I)V
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;->setDeviceType(I)Z
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;->setMaxThroughput(I)V
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;->setSessionAvailable(Z)V
-Landroid/net/wifi/p2p/WifiP2pWfdInfo;->setWfdEnabled(Z)V
-Landroid/net/wifi/ScanResult$InformationElement;->bytes:[B
-Landroid/net/wifi/ScanResult$InformationElement;->EID_BSS_LOAD:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_ERP:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_EXTENDED_CAPS:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_EXTENDED_SUPPORTED_RATES:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_HT_OPERATION:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_INTERWORKING:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_ROAMING_CONSORTIUM:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_RSN:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_SSID:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_SUPPORTED_RATES:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_TIM:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_VHT_OPERATION:I
-Landroid/net/wifi/ScanResult$InformationElement;->EID_VSA:I
-Landroid/net/wifi/ScanResult$InformationElement;->id:I
-Landroid/net/wifi/ScanResult;->anqpDomainId:I
-Landroid/net/wifi/ScanResult;->anqpLines:Ljava/util/List;
-Landroid/net/wifi/ScanResult;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/wifi/ScanResult;->distanceCm:I
-Landroid/net/wifi/ScanResult;->distanceSdCm:I
-Landroid/net/wifi/ScanResult;->flags:J
-Landroid/net/wifi/ScanResult;->hessid:J
-Landroid/net/wifi/ScanResult;->informationElements:[Landroid/net/wifi/ScanResult$InformationElement;
-Landroid/net/wifi/ScanResult;->is80211McRTTResponder:Z
-Landroid/net/wifi/ScanResult;->numUsage:I
-Landroid/net/wifi/ScanResult;->seen:J
-Landroid/net/wifi/ScanResult;->wifiSsid:Landroid/net/wifi/WifiSsid;
-Landroid/net/wifi/WifiConfiguration;-><init>(Landroid/net/wifi/WifiConfiguration;)V
-Landroid/net/wifi/WifiConfiguration;->apBand:I
-Landroid/net/wifi/WifiConfiguration;->apChannel:I
-Landroid/net/wifi/WifiConfiguration;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/wifi/WifiConfiguration;->defaultGwMacAddress:Ljava/lang/String;
-Landroid/net/wifi/WifiConfiguration;->getAuthType()I
-Landroid/net/wifi/WifiConfiguration;->getIpAssignment()Landroid/net/IpConfiguration$IpAssignment;
-Landroid/net/wifi/WifiConfiguration;->getIpConfiguration()Landroid/net/IpConfiguration;
-Landroid/net/wifi/WifiConfiguration;->getPrintableSsid()Ljava/lang/String;
-Landroid/net/wifi/WifiConfiguration;->getProxySettings()Landroid/net/IpConfiguration$ProxySettings;
-Landroid/net/wifi/WifiConfiguration;->getStaticIpConfiguration()Landroid/net/StaticIpConfiguration;
-Landroid/net/wifi/WifiConfiguration;->INVALID_RSSI:I
-Landroid/net/wifi/WifiConfiguration;->isEnterprise()Z
-Landroid/net/wifi/WifiConfiguration;->lastConnectUid:I
-Landroid/net/wifi/WifiConfiguration;->mIpConfiguration:Landroid/net/IpConfiguration;
-Landroid/net/wifi/WifiConfiguration;->noInternetAccessExpected:Z
-Landroid/net/wifi/WifiConfiguration;->numNoInternetAccessReports:I
-Landroid/net/wifi/WifiConfiguration;->selfAdded:Z
-Landroid/net/wifi/WifiConfiguration;->setIpAssignment(Landroid/net/IpConfiguration$IpAssignment;)V
-Landroid/net/wifi/WifiConfiguration;->setIpConfiguration(Landroid/net/IpConfiguration;)V
-Landroid/net/wifi/WifiConfiguration;->setProxy(Landroid/net/IpConfiguration$ProxySettings;Landroid/net/ProxyInfo;)V
-Landroid/net/wifi/WifiConfiguration;->setProxySettings(Landroid/net/IpConfiguration$ProxySettings;)V
-Landroid/net/wifi/WifiConfiguration;->setStaticIpConfiguration(Landroid/net/StaticIpConfiguration;)V
-Landroid/net/wifi/WifiConfiguration;->shared:Z
-Landroid/net/wifi/WifiConfiguration;->validatedInternetAccess:Z
-Landroid/net/wifi/WifiConfiguration;->wepKeyVarNames:[Ljava/lang/String;
-Landroid/net/wifi/WifiEnterpriseConfig;->getCaCertificateAlias()Ljava/lang/String;
-Landroid/net/wifi/WifiEnterpriseConfig;->getClientCertificateAlias()Ljava/lang/String;
-Landroid/net/wifi/WifiEnterpriseConfig;->mFields:Ljava/util/HashMap;
-Landroid/net/wifi/WifiEnterpriseConfig;->setCaCertificateAlias(Ljava/lang/String;)V
-Landroid/net/wifi/WifiEnterpriseConfig;->setClientCertificateAlias(Ljava/lang/String;)V
-Landroid/net/wifi/WifiInfo;-><init>()V
-Landroid/net/wifi/WifiInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/wifi/WifiInfo;->DEFAULT_MAC_ADDRESS:Ljava/lang/String;
-Landroid/net/wifi/WifiInfo;->getMeteredHint()Z
-Landroid/net/wifi/WifiInfo;->getWifiSsid()Landroid/net/wifi/WifiSsid;
-Landroid/net/wifi/WifiInfo;->INVALID_RSSI:I
-Landroid/net/wifi/WifiInfo;->isEphemeral()Z
-Landroid/net/wifi/WifiInfo;->mBSSID:Ljava/lang/String;
-Landroid/net/wifi/WifiInfo;->mIpAddress:Ljava/net/InetAddress;
-Landroid/net/wifi/WifiInfo;->mMacAddress:Ljava/lang/String;
-Landroid/net/wifi/WifiInfo;->mWifiSsid:Landroid/net/wifi/WifiSsid;
-Landroid/net/wifi/WifiInfo;->removeDoubleQuotes(Ljava/lang/String;)Ljava/lang/String;
-Landroid/net/wifi/WifiInfo;->setBSSID(Ljava/lang/String;)V
-Landroid/net/wifi/WifiInfo;->setLinkSpeed(I)V
-Landroid/net/wifi/WifiInfo;->setMacAddress(Ljava/lang/String;)V
-Landroid/net/wifi/WifiInfo;->setNetworkId(I)V
-Landroid/net/wifi/WifiInfo;->setRssi(I)V
-Landroid/net/wifi/WifiInfo;->setSupplicantState(Landroid/net/wifi/SupplicantState;)V
-Landroid/net/wifi/WifiInfo;->setSupplicantState(Ljava/lang/String;)V
-Landroid/net/wifi/WifiManager;->cancelLocalOnlyHotspotRequest()V
-Landroid/net/wifi/WifiManager;->connect(ILandroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->disable(ILandroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->enableVerboseLogging(I)V
-Landroid/net/wifi/WifiManager;->forget(ILandroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->getCountryCode()Ljava/lang/String;
-Landroid/net/wifi/WifiManager;->getCurrentNetwork()Landroid/net/Network;
-Landroid/net/wifi/WifiManager;->getMatchingWifiConfig(Landroid/net/wifi/ScanResult;)Landroid/net/wifi/WifiConfiguration;
-Landroid/net/wifi/WifiManager;->getVerboseLoggingLevel()I
-Landroid/net/wifi/WifiManager;->getWifiServiceMessenger()Landroid/os/Messenger;
-Landroid/net/wifi/WifiManager;->initializeMulticastFiltering()Z
-Landroid/net/wifi/WifiManager;->isDualBandSupported()Z
-Landroid/net/wifi/WifiManager;->LINK_CONFIGURATION_CHANGED_ACTION:Ljava/lang/String;
-Landroid/net/wifi/WifiManager;->mActiveLockCount:I
-Landroid/net/wifi/WifiManager;->MAX_RSSI:I
-Landroid/net/wifi/WifiManager;->MIN_RSSI:I
-Landroid/net/wifi/WifiManager;->mService:Landroid/net/wifi/IWifiManager;
-Landroid/net/wifi/WifiManager;->RSSI_LEVELS:I
-Landroid/net/wifi/WifiManager;->save(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V
-Landroid/net/wifi/WifiManager;->WIFI_FREQUENCY_BAND_2GHZ:I
-Landroid/net/wifi/WifiManager;->WIFI_FREQUENCY_BAND_5GHZ:I
-Landroid/net/wifi/WifiManager;->WIFI_FREQUENCY_BAND_AUTO:I
-Landroid/net/wifi/WifiSsid;->createFromAsciiEncoded(Ljava/lang/String;)Landroid/net/wifi/WifiSsid;
-Landroid/net/wifi/WifiSsid;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/wifi/WifiSsid;->getOctets()[B
-Landroid/net/wifi/WifiSsid;->NONE:Ljava/lang/String;
-Landroid/net/wifi/WifiSsid;->octets:Ljava/io/ByteArrayOutputStream;
-Landroid/nfc/cardemulation/AidGroup;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/nfc/cardemulation/AidGroup;->aids:Ljava/util/List;
-Landroid/nfc/cardemulation/AidGroup;->category:Ljava/lang/String;
-Landroid/nfc/cardemulation/AidGroup;->createFromXml(Lorg/xmlpull/v1/XmlPullParser;)Landroid/nfc/cardemulation/AidGroup;
-Landroid/nfc/cardemulation/AidGroup;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/nfc/cardemulation/AidGroup;->description:Ljava/lang/String;
-Landroid/nfc/cardemulation/AidGroup;->getAids()Ljava/util/List;
-Landroid/nfc/cardemulation/AidGroup;->getCategory()Ljava/lang/String;
-Landroid/nfc/cardemulation/AidGroup;->writeAsXml(Lorg/xmlpull/v1/XmlSerializer;)V
-Landroid/nfc/cardemulation/ApduServiceInfo;-><init>(Landroid/content/pm/PackageManager;Landroid/content/pm/ResolveInfo;Z)V
-Landroid/nfc/cardemulation/ApduServiceInfo;-><init>(Landroid/content/pm/ResolveInfo;ZLjava/lang/String;Ljava/util/ArrayList;Ljava/util/ArrayList;ZIILjava/lang/String;)V
-Landroid/nfc/cardemulation/ApduServiceInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/nfc/cardemulation/ApduServiceInfo;->getDescription()Ljava/lang/String;
-Landroid/nfc/cardemulation/ApduServiceInfo;->getSettingsActivityName()Ljava/lang/String;
-Landroid/nfc/cardemulation/ApduServiceInfo;->getUid()I
-Landroid/nfc/cardemulation/ApduServiceInfo;->isOnHost()Z
-Landroid/nfc/cardemulation/ApduServiceInfo;->loadBanner(Landroid/content/pm/PackageManager;)Landroid/graphics/drawable/Drawable;
-Landroid/nfc/cardemulation/ApduServiceInfo;->mDynamicAidGroups:Ljava/util/HashMap;
-Landroid/nfc/cardemulation/ApduServiceInfo;->mService:Landroid/content/pm/ResolveInfo;
-Landroid/nfc/cardemulation/ApduServiceInfo;->mStaticAidGroups:Ljava/util/HashMap;
-Landroid/nfc/cardemulation/ApduServiceInfo;->requiresUnlock()Z
-Landroid/nfc/ErrorCodes;->isError(I)Z
 Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I
 Landroid/nfc/INfcAdapterExtras;->authenticate(Ljava/lang/String;[B)V
 Landroid/nfc/INfcAdapterExtras;->close(Ljava/lang/String;Landroid/os/IBinder;)Landroid/os/Bundle;
@@ -3742,28 +605,6 @@
 Landroid/nfc/INfcAdapterExtras;->open(Ljava/lang/String;Landroid/os/IBinder;)Landroid/os/Bundle;
 Landroid/nfc/INfcAdapterExtras;->setCardEmulationRoute(Ljava/lang/String;I)V
 Landroid/nfc/INfcAdapterExtras;->transceive(Ljava/lang/String;[B)Landroid/os/Bundle;
-Landroid/nfc/NdefRecord;->mId:[B
-Landroid/nfc/NfcActivityManager;->mAdapter:Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->attemptDeadServiceRecovery(Ljava/lang/Exception;)V
-Landroid/nfc/NfcAdapter;->getAdapterState()I
-Landroid/nfc/NfcAdapter;->getContext()Landroid/content/Context;
-Landroid/nfc/NfcAdapter;->getDefaultAdapter()Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->getNfcAdapter(Landroid/content/Context;)Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->getNfcAdapterExtrasInterface()Landroid/nfc/INfcAdapterExtras;
-Landroid/nfc/NfcAdapter;->getService()Landroid/nfc/INfcAdapter;
-Landroid/nfc/NfcAdapter;->setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;I)V
-Landroid/nfc/NfcAdapter;->sService:Landroid/nfc/INfcAdapter;
-Landroid/nfc/NfcManager;-><init>(Landroid/content/Context;)V
-Landroid/nfc/Tag;->getServiceHandle()I
-Landroid/nfc/Tag;->getTagService()Landroid/nfc/INfcTag;
-Landroid/nfc/Tag;->mId:[B
-Landroid/opengl/EGL14;->eglGetDisplay(J)Landroid/opengl/EGLDisplay;
-Landroid/opengl/GLES20;->glGetActiveAttrib(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V
-Landroid/opengl/GLES20;->glGetActiveUniform(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V
-Landroid/opengl/GLSurfaceView$EglHelper;->mEglContext:Ljavax/microedition/khronos/egl/EGLContext;
-Landroid/opengl/GLSurfaceView$GLThread;->mEglHelper:Landroid/opengl/GLSurfaceView$EglHelper;
-Landroid/opengl/GLSurfaceView;->mGLThread:Landroid/opengl/GLSurfaceView$GLThread;
-Landroid/opengl/GLSurfaceView;->mRenderer:Landroid/opengl/GLSurfaceView$Renderer;
 Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;)Landroid/os/AsyncResult;
 Landroid/os/AsyncTask;->mFuture:Ljava/util/concurrent/FutureTask;
 Landroid/os/AsyncTask;->mStatus:Landroid/os/AsyncTask$Status;
@@ -3925,7 +766,6 @@
 Landroid/os/Environment;->getDataSystemDirectory()Ljava/io/File;
 Landroid/os/Environment;->getLegacyExternalStorageObbDirectory()Ljava/io/File;
 Landroid/os/Environment;->getOemDirectory()Ljava/io/File;
-Landroid/os/Environment;->getStorageDirectory()Ljava/io/File;
 Landroid/os/Environment;->getVendorDirectory()Ljava/io/File;
 Landroid/os/Environment;->initForCurrentUser()V
 Landroid/os/Environment;->maybeTranslateEmulatedPathToInternal(Ljava/io/File;)Ljava/io/File;
@@ -3952,18 +792,6 @@
 Landroid/os/Handler;->mCallback:Landroid/os/Handler$Callback;
 Landroid/os/Handler;->mLooper:Landroid/os/Looper;
 Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger;
-Landroid/os/health/HealthKeys$Constants;-><init>(Ljava/lang/Class;)V
-Landroid/os/health/HealthStats;-><init>(Landroid/os/Parcel;)V
-Landroid/os/health/HealthStatsParceler;-><init>(Landroid/os/health/HealthStatsWriter;)V
-Landroid/os/health/HealthStatsParceler;-><init>(Landroid/os/Parcel;)V
-Landroid/os/health/HealthStatsParceler;->getHealthStats()Landroid/os/health/HealthStats;
-Landroid/os/health/HealthStatsWriter;-><init>(Landroid/os/health/HealthKeys$Constants;)V
-Landroid/os/health/HealthStatsWriter;->addMeasurement(IJ)V
-Landroid/os/health/HealthStatsWriter;->addMeasurements(ILjava/lang/String;J)V
-Landroid/os/health/HealthStatsWriter;->addStats(ILjava/lang/String;Landroid/os/health/HealthStatsWriter;)V
-Landroid/os/health/HealthStatsWriter;->addTimer(IIJ)V
-Landroid/os/health/HealthStatsWriter;->addTimers(ILjava/lang/String;Landroid/os/health/TimerStat;)V
-Landroid/os/health/HealthStatsWriter;->flattenToParcel(Landroid/os/Parcel;)V
 Landroid/os/health/SystemHealthManager;-><init>()V
 Landroid/os/health/SystemHealthManager;->from(Landroid/content/Context;)Landroid/os/health/SystemHealthManager;
 Landroid/os/HwParcel;-><init>(Z)V
@@ -4039,8 +867,6 @@
 Landroid/os/MessageQueue;->mQuitAllowed:Z
 Landroid/os/MessageQueue;->nativePollOnce(JI)V
 Landroid/os/MessageQueue;->next()Landroid/os/Message;
-Landroid/os/MessageQueue;->postSyncBarrier()I
-Landroid/os/MessageQueue;->removeSyncBarrier(I)V
 Landroid/os/Parcel$ReadWriteHelper;-><init>()V
 Landroid/os/Parcel;->getGlobalAllocCount()J
 Landroid/os/Parcel;->getGlobalAllocSize()J
@@ -4052,13 +878,11 @@
 Landroid/os/Parcel;->readCreator(Landroid/os/Parcelable$Creator;Ljava/lang/ClassLoader;)Landroid/os/Parcelable;
 Landroid/os/Parcel;->readExceptionCode()I
 Landroid/os/Parcel;->readParcelableCreator(Ljava/lang/ClassLoader;)Landroid/os/Parcelable$Creator;
-Landroid/os/Parcel;->readParcelableList(Ljava/util/List;Ljava/lang/ClassLoader;)Ljava/util/List;
 Landroid/os/Parcel;->readRawFileDescriptor()Ljava/io/FileDescriptor;
 Landroid/os/Parcel;->writeArrayMap(Landroid/util/ArrayMap;)V
 Landroid/os/Parcel;->writeArraySet(Landroid/util/ArraySet;)V
 Landroid/os/Parcel;->writeCharSequence(Ljava/lang/CharSequence;)V
 Landroid/os/Parcel;->writeParcelableCreator(Landroid/os/Parcelable;)V
-Landroid/os/Parcel;->writeParcelableList(Ljava/util/List;I)V
 Landroid/os/ParcelableParcel;-><init>(Ljava/lang/ClassLoader;)V
 Landroid/os/ParcelableParcel;->CREATOR:Landroid/os/Parcelable$ClassLoaderCreator;
 Landroid/os/ParcelableParcel;->getClassLoader()Ljava/lang/ClassLoader;
@@ -4206,7 +1030,6 @@
 Landroid/os/storage/StorageVolume;->getFatVolumeId()I
 Landroid/os/storage/StorageVolume;->getMaxFileSize()J
 Landroid/os/storage/StorageVolume;->getOwner()Landroid/os/UserHandle;
-Landroid/os/storage/StorageVolume;->getPath()Ljava/lang/String;
 Landroid/os/storage/StorageVolume;->getPathFile()Ljava/io/File;
 Landroid/os/storage/StorageVolume;->getUserLabel()Ljava/lang/String;
 Landroid/os/storage/StorageVolume;->mDescription:Ljava/lang/String;
@@ -4252,7 +1075,6 @@
 Landroid/os/StrictMode$ThreadPolicy;->mask:I
 Landroid/os/StrictMode$VmPolicy$Builder;->mMask:I
 Landroid/os/StrictMode$VmPolicy;->mask:I
-Landroid/os/StrictMode;->conditionallyCheckInstanceCounts()V
 Landroid/os/StrictMode;->disableDeathOnFileUriExposure()V
 Landroid/os/StrictMode;->enableDeathOnFileUriExposure()V
 Landroid/os/StrictMode;->enterCriticalSpan(Ljava/lang/String;)Landroid/os/StrictMode$Span;
@@ -4368,290 +1190,16 @@
 Landroid/os/VintfRuntimeInfo;->getOsName()Ljava/lang/String;
 Landroid/os/VintfRuntimeInfo;->getOsRelease()Ljava/lang/String;
 Landroid/os/VintfRuntimeInfo;->getOsVersion()Ljava/lang/String;
-Landroid/os/WorkSource;-><init>(I)V
 Landroid/os/WorkSource;-><init>(Landroid/os/Parcel;)V
-Landroid/os/WorkSource;->add(I)Z
-Landroid/os/WorkSource;->add(ILjava/lang/String;)Z
-Landroid/os/WorkSource;->addReturningNewbs(Landroid/os/WorkSource;)Landroid/os/WorkSource;
-Landroid/os/WorkSource;->get(I)I
-Landroid/os/WorkSource;->getName(I)Ljava/lang/String;
 Landroid/os/WorkSource;->mNames:[Ljava/lang/String;
 Landroid/os/WorkSource;->mNum:I
 Landroid/os/WorkSource;->mUids:[I
-Landroid/os/WorkSource;->setReturningDiffs(Landroid/os/WorkSource;)[Landroid/os/WorkSource;
 Landroid/os/WorkSource;->sGoneWork:Landroid/os/WorkSource;
-Landroid/os/WorkSource;->size()I
 Landroid/os/WorkSource;->sNewbWork:Landroid/os/WorkSource;
 Landroid/os/WorkSource;->sTmpWorkSource:Landroid/os/WorkSource;
 Landroid/os/WorkSource;->updateLocked(Landroid/os/WorkSource;ZZ)Z
 Landroid/os/ZygoteStartFailedEx;-><init>(Ljava/lang/String;)V
 Landroid/os/ZygoteStartFailedEx;-><init>(Ljava/lang/Throwable;)V
-Landroid/permissionpresenterservice/RuntimePermissionPresenterService;->onRevokeRuntimePermission(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/preference/DialogPreference;->mBuilder:Landroid/app/AlertDialog$Builder;
-Landroid/preference/DialogPreference;->mDialog:Landroid/app/Dialog;
-Landroid/preference/DialogPreference;->mDialogIcon:Landroid/graphics/drawable/Drawable;
-Landroid/preference/DialogPreference;->mDialogMessage:Ljava/lang/CharSequence;
-Landroid/preference/DialogPreference;->mDialogTitle:Ljava/lang/CharSequence;
-Landroid/preference/DialogPreference;->mNegativeButtonText:Ljava/lang/CharSequence;
-Landroid/preference/DialogPreference;->mPositiveButtonText:Ljava/lang/CharSequence;
-Landroid/preference/DialogPreference;->mWhichButtonClicked:I
-Landroid/preference/EditTextPreference;->mEditText:Landroid/widget/EditText;
-Landroid/preference/ListPreference;->mClickedDialogEntryIndex:I
-Landroid/preference/Preference;->getId()J
-Landroid/preference/Preference;->mLayoutResId:I
-Landroid/preference/Preference;->mSummary:Ljava/lang/CharSequence;
-Landroid/preference/Preference;->mWidgetLayoutResId:I
-Landroid/preference/Preference;->onKey(Landroid/view/View;ILandroid/view/KeyEvent;)Z
-Landroid/preference/Preference;->performClick(Landroid/preference/PreferenceScreen;)V
-Landroid/preference/Preference;->registerDependent(Landroid/preference/Preference;)V
-Landroid/preference/Preference;->setOnPreferenceChangeInternalListener(Landroid/preference/Preference$OnPreferenceChangeInternalListener;)V
-Landroid/preference/PreferenceActivity;->getHeaders()Ljava/util/List;
-Landroid/preference/PreferenceActivity;->mPreferenceManager:Landroid/preference/PreferenceManager;
-Landroid/preference/PreferenceActivity;->mPrefsContainer:Landroid/view/ViewGroup;
-Landroid/preference/PreferenceActivity;->postBindPreferences()V
-Landroid/preference/PreferenceActivity;->requirePreferenceManager()V
-Landroid/preference/PreferenceFragment;->getListView()Landroid/widget/ListView;
-Landroid/preference/PreferenceFragment;->mPreferenceManager:Landroid/preference/PreferenceManager;
-Landroid/preference/PreferenceManager;-><init>(Landroid/app/Activity;I)V
-Landroid/preference/PreferenceManager;-><init>(Landroid/content/Context;)V
-Landroid/preference/PreferenceManager;->dispatchActivityDestroy()V
-Landroid/preference/PreferenceManager;->dispatchActivityResult(IILandroid/content/Intent;)V
-Landroid/preference/PreferenceManager;->dispatchActivityStop()V
-Landroid/preference/PreferenceManager;->getActivity()Landroid/app/Activity;
-Landroid/preference/PreferenceManager;->getEditor()Landroid/content/SharedPreferences$Editor;
-Landroid/preference/PreferenceManager;->getFragment()Landroid/preference/PreferenceFragment;
-Landroid/preference/PreferenceManager;->getNextRequestCode()I
-Landroid/preference/PreferenceManager;->getPreferenceScreen()Landroid/preference/PreferenceScreen;
-Landroid/preference/PreferenceManager;->inflateFromIntent(Landroid/content/Intent;Landroid/preference/PreferenceScreen;)Landroid/preference/PreferenceScreen;
-Landroid/preference/PreferenceManager;->inflateFromResource(Landroid/content/Context;ILandroid/preference/PreferenceScreen;)Landroid/preference/PreferenceScreen;
-Landroid/preference/PreferenceManager;->mActivityDestroyListeners:Ljava/util/List;
-Landroid/preference/PreferenceManager;->mFragment:Landroid/preference/PreferenceFragment;
-Landroid/preference/PreferenceManager;->mOnPreferenceTreeClickListener:Landroid/preference/PreferenceManager$OnPreferenceTreeClickListener;
-Landroid/preference/PreferenceManager;->mSharedPreferences:Landroid/content/SharedPreferences;
-Landroid/preference/PreferenceManager;->registerOnActivityDestroyListener(Landroid/preference/PreferenceManager$OnActivityDestroyListener;)V
-Landroid/preference/PreferenceManager;->registerOnActivityResultListener(Landroid/preference/PreferenceManager$OnActivityResultListener;)V
-Landroid/preference/PreferenceManager;->registerOnActivityStopListener(Landroid/preference/PreferenceManager$OnActivityStopListener;)V
-Landroid/preference/PreferenceManager;->setFragment(Landroid/preference/PreferenceFragment;)V
-Landroid/preference/PreferenceManager;->setNoCommit(Z)V
-Landroid/preference/PreferenceManager;->setPreferences(Landroid/preference/PreferenceScreen;)Z
-Landroid/preference/PreferenceManager;->shouldCommit()Z
-Landroid/preference/PreferenceManager;->unregisterOnActivityDestroyListener(Landroid/preference/PreferenceManager$OnActivityDestroyListener;)V
-Landroid/preference/PreferenceManager;->unregisterOnActivityResultListener(Landroid/preference/PreferenceManager$OnActivityResultListener;)V
-Landroid/preference/PreferenceManager;->unregisterOnActivityStopListener(Landroid/preference/PreferenceManager$OnActivityStopListener;)V
-Landroid/preference/PreferenceScreen;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Landroid/preference/PreferenceScreen;->mListView:Landroid/widget/ListView;
-Landroid/preference/PreferenceScreen;->mRootAdapter:Landroid/widget/ListAdapter;
-Landroid/preference/RingtonePreference;->mRequestCode:I
-Landroid/preference/SeekBarDialogPreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Landroid/preference/SeekBarPreference;-><init>(Landroid/content/Context;)V
-Landroid/preference/SeekBarPreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Landroid/preference/SeekBarPreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;I)V
-Landroid/preference/SeekBarVolumizer;-><init>(Landroid/content/Context;ILandroid/net/Uri;Landroid/preference/SeekBarVolumizer$Callback;)V
-Landroid/preference/SeekBarVolumizer;->mAudioManager:Landroid/media/AudioManager;
-Landroid/preference/SeekBarVolumizer;->mContext:Landroid/content/Context;
-Landroid/preference/SeekBarVolumizer;->mLastProgress:I
-Landroid/preference/SeekBarVolumizer;->mOriginalStreamVolume:I
-Landroid/preference/SeekBarVolumizer;->mRingtone:Landroid/media/Ringtone;
-Landroid/preference/SeekBarVolumizer;->mSeekBar:Landroid/widget/SeekBar;
-Landroid/preference/SeekBarVolumizer;->mStreamType:I
-Landroid/preference/SeekBarVolumizer;->stop()V
-Landroid/preference/SwitchPreference;->mListener:Landroid/preference/SwitchPreference$Listener;
-Landroid/preference/TwoStatePreference;->syncSummaryView(Landroid/view/View;)V
-Landroid/preference/VolumePreference$VolumeStore;->originalVolume:I
-Landroid/preference/VolumePreference$VolumeStore;->volume:I
-Landroid/preference/VolumePreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Landroid/preference/VolumePreference;->mStreamType:I
-Landroid/print/PrinterId;->getServiceName()Landroid/content/ComponentName;
-Landroid/print/PrintJobInfo;->getAdvancedOptions()Landroid/os/Bundle;
-Landroid/print/PrintJobInfo;->getDocumentInfo()Landroid/print/PrintDocumentInfo;
-Landroid/print/PrintManager;->addPrintJobStateChangeListener(Landroid/print/PrintManager$PrintJobStateChangeListener;)V
-Landroid/provider/Browser;->getVisitedHistory(Landroid/content/ContentResolver;)[Ljava/lang/String;
-Landroid/provider/Browser;->sendString(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
-Landroid/provider/BrowserContract$Accounts;->CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/BrowserContract$Bookmarks;->buildFolderUri(J)Landroid/net/Uri;
-Landroid/provider/BrowserContract$Bookmarks;->CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/BrowserContract$Bookmarks;->CONTENT_URI_DEFAULT_FOLDER:Landroid/net/Uri;
-Landroid/provider/BrowserContract$Combined;->CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/BrowserContract$History;->CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/BrowserContract$Images;->CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/BrowserContract;->AUTHORITY_URI:Landroid/net/Uri;
-Landroid/provider/CalendarContract$CalendarAlerts;->findNextAlarmTime(Landroid/content/ContentResolver;J)J
-Landroid/provider/CalendarContract$CalendarAlerts;->rescheduleMissedAlarms(Landroid/content/ContentResolver;Landroid/content/Context;Landroid/app/AlarmManager;)V
-Landroid/provider/CalendarContract$CalendarAlerts;->scheduleAlarm(Landroid/content/Context;Landroid/app/AlarmManager;J)V
-Landroid/provider/CallLog$Calls;->addCall(Lcom/android/internal/telephony/CallerInfo;Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIILandroid/telecom/PhoneAccountHandle;JILjava/lang/Long;ZLandroid/os/UserHandle;Z)Landroid/net/Uri;
-Landroid/provider/ContactsContract$ContactCounts;->EXTRA_ADDRESS_BOOK_INDEX:Ljava/lang/String;
-Landroid/provider/ContactsContract$ContactCounts;->EXTRA_ADDRESS_BOOK_INDEX_COUNTS:Ljava/lang/String;
-Landroid/provider/ContactsContract$ContactCounts;->EXTRA_ADDRESS_BOOK_INDEX_TITLES:Ljava/lang/String;
-Landroid/provider/ContactsContract$Contacts$AggregationSuggestions;->builder()Landroid/provider/ContactsContract$Contacts$AggregationSuggestions$Builder;
-Landroid/provider/ContactsContract$Contacts;->CORP_CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/ContactsContract$QuickContact;->composeQuickContactsIntent(Landroid/content/Context;Landroid/graphics/Rect;Landroid/net/Uri;I[Ljava/lang/String;)Landroid/content/Intent;
-Landroid/provider/ContactsInternal;->startQuickContactWithErrorToast(Landroid/content/Context;Landroid/content/Intent;)V
-Landroid/provider/DocumentsContract$Root;->FLAG_ADVANCED:I
-Landroid/provider/DocumentsContract;->getDocumentThumbnail(Landroid/content/ContentProviderClient;Landroid/net/Uri;Landroid/graphics/Point;Landroid/os/CancellationSignal;)Landroid/graphics/Bitmap;
-Landroid/provider/DocumentsContract;->METHOD_CREATE_DOCUMENT:Ljava/lang/String;
-Landroid/provider/DocumentsContract;->moveDocument(Landroid/content/ContentProviderClient;Landroid/net/Uri;Landroid/net/Uri;Landroid/net/Uri;)Landroid/net/Uri;
-Landroid/provider/DocumentsContract;->PATH_DOCUMENT:Ljava/lang/String;
-Landroid/provider/DocumentsContract;->PATH_TREE:Ljava/lang/String;
-Landroid/provider/DocumentsContract;->setManageMode(Landroid/net/Uri;)Landroid/net/Uri;
-Landroid/provider/Downloads$Impl$RequestHeaders;->INSERT_KEY_PREFIX:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->ALL_DOWNLOADS_CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/Downloads$Impl;->COLUMN_ALLOWED_NETWORK_TYPES:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_ALLOW_ROAMING:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_COOKIE_DATA:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_DELETED:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_DESCRIPTION:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_DESTINATION:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_FILE_NAME_HINT:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_IS_PUBLIC_API:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_MEDIA_SCANNED:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_MIME_TYPE:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_NOTIFICATION_CLASS:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_NOTIFICATION_EXTRAS:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_NOTIFICATION_PACKAGE:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_REFERER:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_TITLE:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_URI:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->COLUMN_VISIBILITY:Ljava/lang/String;
-Landroid/provider/Downloads$Impl;->CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/Downloads$Impl;->DESTINATION_CACHE_PARTITION_PURGEABLE:I
-Landroid/provider/Downloads$Impl;->DESTINATION_FILE_URI:I
-Landroid/provider/Downloads$Impl;->isNotificationToBeDisplayed(I)Z
-Landroid/provider/Downloads$Impl;->isStatusCompleted(I)Z
-Landroid/provider/Downloads$Impl;->isStatusError(I)Z
-Landroid/provider/Downloads$Impl;->isStatusSuccess(I)Z
-Landroid/provider/Downloads$Impl;->PUBLICLY_ACCESSIBLE_DOWNLOADS_URI:Landroid/net/Uri;
-Landroid/provider/MediaStore$Files$FileColumns;->FORMAT:Ljava/lang/String;
-Landroid/provider/MediaStore$Files$FileColumns;->STORAGE_ID:Ljava/lang/String;
-Landroid/provider/MediaStore$Files;->getMtpObjectsUri(Ljava/lang/String;)Landroid/net/Uri;
-Landroid/provider/MediaStore$Files;->getMtpObjectsUri(Ljava/lang/String;J)Landroid/net/Uri;
-Landroid/provider/MediaStore$Files;->getMtpReferencesUri(Ljava/lang/String;J)Landroid/net/Uri;
-Landroid/provider/MediaStore$MediaColumns;->IS_DRM:Ljava/lang/String;
-Landroid/provider/Settings$Bookmarks;->add(Landroid/content/ContentResolver;Landroid/content/Intent;Ljava/lang/String;Ljava/lang/String;CI)Landroid/net/Uri;
-Landroid/provider/Settings$Bookmarks;->CONTENT_URI:Landroid/net/Uri;
-Landroid/provider/Settings$ContentProviderHolder;->mContentProvider:Landroid/content/IContentProvider;
-Landroid/provider/Settings$Global;->ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Global;->HEADS_UP_NOTIFICATIONS_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Global;->HEADS_UP_OFF:I
-Landroid/provider/Settings$Global;->HEADS_UP_ON:I
-Landroid/provider/Settings$Global;->MOBILE_DATA:Ljava/lang/String;
-Landroid/provider/Settings$Global;->MOVED_TO_SECURE:Ljava/util/HashSet;
-Landroid/provider/Settings$Global;->MULTI_SIM_USER_PREFERRED_SUBS:[Ljava/lang/String;
-Landroid/provider/Settings$Global;->MULTI_SIM_VOICE_PROMPT:Ljava/lang/String;
-Landroid/provider/Settings$Global;->NETWORK_SCORER_APP:Ljava/lang/String;
-Landroid/provider/Settings$Global;->PACKAGE_VERIFIER_ENABLE:Ljava/lang/String;
-Landroid/provider/Settings$Global;->PREFERRED_NETWORK_MODE:Ljava/lang/String;
-Landroid/provider/Settings$Global;->putStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;I)Z
-Landroid/provider/Settings$Global;->REQUIRE_PASSWORD_TO_DECRYPT:Ljava/lang/String;
-Landroid/provider/Settings$Global;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
-Landroid/provider/Settings$Global;->sProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
-Landroid/provider/Settings$Global;->WEBVIEW_PROVIDER:Ljava/lang/String;
-Landroid/provider/Settings$Global;->WIFI_SAVED_STATE:Ljava/lang/String;
-Landroid/provider/Settings$Global;->WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Global;->ZEN_MODE:Ljava/lang/String;
-Landroid/provider/Settings$Global;->ZEN_MODE_ALARMS:I
-Landroid/provider/Settings$Global;->ZEN_MODE_CONFIG_ETAG:Ljava/lang/String;
-Landroid/provider/Settings$Global;->ZEN_MODE_IMPORTANT_INTERRUPTIONS:I
-Landroid/provider/Settings$Global;->ZEN_MODE_NO_INTERRUPTIONS:I
-Landroid/provider/Settings$Global;->ZEN_MODE_OFF:I
-Landroid/provider/Settings$NameValueCache;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
-Landroid/provider/Settings$NameValueCache;->mProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
-Landroid/provider/Settings$Secure;->ACCESSIBILITY_AUTOCLICK_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->ACCESSIBILITY_CAPTIONING_TYPEFACE:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->ACCESSIBILITY_DISPLAY_DALTONIZER:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->ACCESSIBILITY_LARGE_POINTER_ICON:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->ANR_SHOW_BACKGROUND:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->ASSISTANT:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->BACKUP_AUTO_RESTORE:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->BACKUP_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->BACKUP_PROVISIONED:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->BACKUP_TRANSPORT:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->DIALER_DEFAULT_APPLICATION:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->DOZE_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->ENABLED_NOTIFICATION_LISTENERS:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->ENABLED_PRINT_SERVICES:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->getIntForUser(Landroid/content/ContentResolver;Ljava/lang/String;II)I
-Landroid/provider/Settings$Secure;->getLongForUser(Landroid/content/ContentResolver;Ljava/lang/String;JI)J
-Landroid/provider/Settings$Secure;->IMMERSIVE_MODE_CONFIRMATIONS:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->INCALL_POWER_BUTTON_BEHAVIOR:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->LOCK_SCREEN_LOCK_AFTER_TIMEOUT:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->LOCK_SCREEN_OWNER_INFO_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->LOCK_SCREEN_SHOW_NOTIFICATIONS:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->LONG_PRESS_TIMEOUT:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->MOVED_TO_GLOBAL:Ljava/util/HashSet;
-Landroid/provider/Settings$Secure;->MOVED_TO_LOCK_SETTINGS:Ljava/util/HashSet;
-Landroid/provider/Settings$Secure;->NFC_PAYMENT_DEFAULT_COMPONENT:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->PACKAGE_VERIFIER_USER_CONSENT:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->putIntForUser(Landroid/content/ContentResolver;Ljava/lang/String;II)Z
-Landroid/provider/Settings$Secure;->putLongForUser(Landroid/content/ContentResolver;Ljava/lang/String;JI)Z
-Landroid/provider/Settings$Secure;->putStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;I)Z
-Landroid/provider/Settings$Secure;->putStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)Z
-Landroid/provider/Settings$Secure;->SELECTED_SPELL_CHECKER:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->SELECTED_SPELL_CHECKER_SUBTYPE:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->SETTINGS_TO_BACKUP:[Ljava/lang/String;
-Landroid/provider/Settings$Secure;->SMS_DEFAULT_APPLICATION:Ljava/lang/String;
-Landroid/provider/Settings$Secure;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
-Landroid/provider/Settings$Secure;->sProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
-Landroid/provider/Settings$Secure;->VOICE_RECOGNITION_SERVICE:Ljava/lang/String;
-Landroid/provider/Settings$System;->AIRPLANE_MODE_TOGGLEABLE_RADIOS:Ljava/lang/String;
-Landroid/provider/Settings$System;->CAR_DOCK_SOUND:Ljava/lang/String;
-Landroid/provider/Settings$System;->CAR_UNDOCK_SOUND:Ljava/lang/String;
-Landroid/provider/Settings$System;->CLONE_TO_MANAGED_PROFILE:Ljava/util/Set;
-Landroid/provider/Settings$System;->DESK_DOCK_SOUND:Ljava/lang/String;
-Landroid/provider/Settings$System;->DESK_UNDOCK_SOUND:Ljava/lang/String;
-Landroid/provider/Settings$System;->DOCK_SOUNDS_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$System;->getIntForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)I
-Landroid/provider/Settings$System;->getIntForUser(Landroid/content/ContentResolver;Ljava/lang/String;II)I
-Landroid/provider/Settings$System;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
-Landroid/provider/Settings$System;->HEARING_AID:Ljava/lang/String;
-Landroid/provider/Settings$System;->HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY:Ljava/lang/String;
-Landroid/provider/Settings$System;->LOCKSCREEN_SOUNDS_ENABLED:Ljava/lang/String;
-Landroid/provider/Settings$System;->LOCK_SOUND:Ljava/lang/String;
-Landroid/provider/Settings$System;->MASTER_MONO:Ljava/lang/String;
-Landroid/provider/Settings$System;->MOVED_TO_GLOBAL:Ljava/util/HashSet;
-Landroid/provider/Settings$System;->MOVED_TO_SECURE:Ljava/util/HashSet;
-Landroid/provider/Settings$System;->MOVED_TO_SECURE_THEN_GLOBAL:Ljava/util/HashSet;
-Landroid/provider/Settings$System;->NOTIFICATION_LIGHT_PULSE:Ljava/lang/String;
-Landroid/provider/Settings$System;->POINTER_LOCATION:Ljava/lang/String;
-Landroid/provider/Settings$System;->POINTER_SPEED:Ljava/lang/String;
-Landroid/provider/Settings$System;->PRIVATE_SETTINGS:Ljava/util/Set;
-Landroid/provider/Settings$System;->PUBLIC_SETTINGS:Ljava/util/Set;
-Landroid/provider/Settings$System;->putIntForUser(Landroid/content/ContentResolver;Ljava/lang/String;II)Z
-Landroid/provider/Settings$System;->putStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;I)Z
-Landroid/provider/Settings$System;->SCREEN_AUTO_BRIGHTNESS_ADJ:Ljava/lang/String;
-Landroid/provider/Settings$System;->SETTINGS_TO_BACKUP:[Ljava/lang/String;
-Landroid/provider/Settings$System;->SHOW_TOUCHES:Ljava/lang/String;
-Landroid/provider/Settings$System;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
-Landroid/provider/Settings$System;->sProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
-Landroid/provider/Settings$System;->TTY_MODE:Ljava/lang/String;
-Landroid/provider/Settings$System;->UNLOCK_SOUND:Ljava/lang/String;
-Landroid/provider/Settings$System;->VALIDATORS:Ljava/util/Map;
-Landroid/provider/Settings$System;->VIBRATE_IN_SILENT:Ljava/lang/String;
-Landroid/provider/Settings;->ACTION_TRUSTED_CREDENTIALS_USER:Ljava/lang/String;
-Landroid/provider/Settings;->ACTION_USER_DICTIONARY_INSERT:Ljava/lang/String;
-Landroid/provider/Settings;->EXTRA_APP_UID:Ljava/lang/String;
-Landroid/provider/Settings;->isCallingPackageAllowedToDrawOverlays(Landroid/content/Context;ILjava/lang/String;Z)Z
-Landroid/provider/Settings;->isCallingPackageAllowedToPerformAppOpsProtectedOperation(Landroid/content/Context;ILjava/lang/String;ZI[Ljava/lang/String;Z)Z
-Landroid/provider/Settings;->isCallingPackageAllowedToWriteSettings(Landroid/content/Context;ILjava/lang/String;Z)Z
-Landroid/provider/Telephony$Mms;->extractAddrSpec(Ljava/lang/String;)Ljava/lang/String;
-Landroid/provider/Telephony$Mms;->isPhoneNumber(Ljava/lang/String;)Z
-Landroid/provider/Telephony$Mms;->NAME_ADDR_EMAIL_PATTERN:Ljava/util/regex/Pattern;
-Landroid/provider/Telephony$Sms$Draft;->addMessage(ILandroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms$Inbox;->addMessage(ILandroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Z)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms$Inbox;->addMessage(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Z)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms$Sent;->addMessage(ILandroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms$Sent;->addMessage(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms;->addMessageToUri(ILandroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZ)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms;->addMessageToUri(ILandroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZJ)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms;->addMessageToUri(Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZ)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms;->addMessageToUri(Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZZJ)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms;->isOutgoingFolder(I)Z
-Landroid/provider/Telephony$Sms;->moveMessageToFolder(Landroid/content/Context;Landroid/net/Uri;II)Z
-Landroid/provider/Telephony$Sms;->query(Landroid/content/ContentResolver;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
-Landroid/provider/Telephony$Threads;->ID_PROJECTION:[Ljava/lang/String;
-Landroid/provider/Telephony$Threads;->THREAD_ID_CONTENT_URI:Landroid/net/Uri;
 Landroid/R$styleable;->ActionBar:[I
 Landroid/R$styleable;->ActionBar_background:I
 Landroid/R$styleable;->ActionBar_backgroundSplit:I
@@ -4915,102 +1463,7 @@
 Landroid/R$styleable;->Window:[I
 Landroid/R$styleable;->Window_windowBackground:I
 Landroid/R$styleable;->Window_windowFrame:I
-Landroid/renderscript/BaseObj;->mRS:Landroid/renderscript/RenderScript;
-Landroid/renderscript/Element;->createUser(Landroid/renderscript/RenderScript;Landroid/renderscript/Element$DataType;)Landroid/renderscript/Element;
-Landroid/renderscript/FileA3D$EntryType;->MESH:Landroid/renderscript/FileA3D$EntryType;
-Landroid/renderscript/FileA3D$IndexEntry;->getEntryType()Landroid/renderscript/FileA3D$EntryType;
-Landroid/renderscript/FileA3D$IndexEntry;->getObject()Landroid/renderscript/BaseObj;
-Landroid/renderscript/FileA3D;->createFromResource(Landroid/renderscript/RenderScript;Landroid/content/res/Resources;I)Landroid/renderscript/FileA3D;
-Landroid/renderscript/FileA3D;->getIndexEntry(I)Landroid/renderscript/FileA3D$IndexEntry;
-Landroid/renderscript/Font$Style;->ITALIC:Landroid/renderscript/Font$Style;
-Landroid/renderscript/Font;->create(Landroid/renderscript/RenderScript;Landroid/content/res/Resources;Ljava/lang/String;Landroid/renderscript/Font$Style;F)Landroid/renderscript/Font;
-Landroid/renderscript/Matrix4f;->mMat:[F
-Landroid/renderscript/Mesh$AllocationBuilder;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/Mesh$AllocationBuilder;->addIndexSetAllocation(Landroid/renderscript/Allocation;Landroid/renderscript/Mesh$Primitive;)Landroid/renderscript/Mesh$AllocationBuilder;
-Landroid/renderscript/Mesh$AllocationBuilder;->addIndexSetType(Landroid/renderscript/Mesh$Primitive;)Landroid/renderscript/Mesh$AllocationBuilder;
-Landroid/renderscript/Mesh$AllocationBuilder;->addVertexAllocation(Landroid/renderscript/Allocation;)Landroid/renderscript/Mesh$AllocationBuilder;
-Landroid/renderscript/Mesh$AllocationBuilder;->create()Landroid/renderscript/Mesh;
-Landroid/renderscript/Mesh$Primitive;->POINT:Landroid/renderscript/Mesh$Primitive;
-Landroid/renderscript/Mesh$Primitive;->TRIANGLE:Landroid/renderscript/Mesh$Primitive;
-Landroid/renderscript/Mesh$TriangleMeshBuilder;-><init>(Landroid/renderscript/RenderScript;II)V
-Landroid/renderscript/Mesh$TriangleMeshBuilder;->addTriangle(III)Landroid/renderscript/Mesh$TriangleMeshBuilder;
-Landroid/renderscript/Mesh$TriangleMeshBuilder;->addVertex(FF)Landroid/renderscript/Mesh$TriangleMeshBuilder;
-Landroid/renderscript/Mesh$TriangleMeshBuilder;->create(Z)Landroid/renderscript/Mesh;
-Landroid/renderscript/Mesh;->getVertexAllocation(I)Landroid/renderscript/Allocation;
-Landroid/renderscript/Program$BaseProgramBuilder;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/Program$BaseProgramBuilder;->mConstantCount:I
-Landroid/renderscript/Program$BaseProgramBuilder;->mConstants:[Landroid/renderscript/Type;
-Landroid/renderscript/Program$BaseProgramBuilder;->mInputCount:I
-Landroid/renderscript/Program$BaseProgramBuilder;->mInputs:[Landroid/renderscript/Element;
-Landroid/renderscript/Program$BaseProgramBuilder;->mOutputCount:I
-Landroid/renderscript/Program$BaseProgramBuilder;->mOutputs:[Landroid/renderscript/Element;
-Landroid/renderscript/Program$BaseProgramBuilder;->mRS:Landroid/renderscript/RenderScript;
-Landroid/renderscript/Program$BaseProgramBuilder;->mShader:Ljava/lang/String;
-Landroid/renderscript/Program$BaseProgramBuilder;->mTextureCount:I
-Landroid/renderscript/Program$TextureType;->TEXTURE_2D:Landroid/renderscript/Program$TextureType;
-Landroid/renderscript/ProgramFragment$Builder;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/ProgramFragment$Builder;->create()Landroid/renderscript/ProgramFragment;
-Landroid/renderscript/ProgramFragmentFixedFunction$Builder$EnvMode;->MODULATE:Landroid/renderscript/ProgramFragmentFixedFunction$Builder$EnvMode;
-Landroid/renderscript/ProgramFragmentFixedFunction$Builder$EnvMode;->REPLACE:Landroid/renderscript/ProgramFragmentFixedFunction$Builder$EnvMode;
-Landroid/renderscript/ProgramFragmentFixedFunction$Builder$Format;->ALPHA:Landroid/renderscript/ProgramFragmentFixedFunction$Builder$Format;
-Landroid/renderscript/ProgramFragmentFixedFunction$Builder$Format;->RGB:Landroid/renderscript/ProgramFragmentFixedFunction$Builder$Format;
-Landroid/renderscript/ProgramFragmentFixedFunction$Builder$Format;->RGBA:Landroid/renderscript/ProgramFragmentFixedFunction$Builder$Format;
-Landroid/renderscript/ProgramFragmentFixedFunction$Builder;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/ProgramFragmentFixedFunction$Builder;->create()Landroid/renderscript/ProgramFragmentFixedFunction;
-Landroid/renderscript/ProgramFragmentFixedFunction$Builder;->setTexture(Landroid/renderscript/ProgramFragmentFixedFunction$Builder$EnvMode;Landroid/renderscript/ProgramFragmentFixedFunction$Builder$Format;I)Landroid/renderscript/ProgramFragmentFixedFunction$Builder;
-Landroid/renderscript/ProgramFragmentFixedFunction$Builder;->setVaryingColor(Z)Landroid/renderscript/ProgramFragmentFixedFunction$Builder;
-Landroid/renderscript/ProgramRaster$Builder;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/ProgramRaster$Builder;->create()Landroid/renderscript/ProgramRaster;
-Landroid/renderscript/ProgramRaster$Builder;->setPointSpriteEnabled(Z)Landroid/renderscript/ProgramRaster$Builder;
-Landroid/renderscript/ProgramStore$BlendDstFunc;->ONE:Landroid/renderscript/ProgramStore$BlendDstFunc;
-Landroid/renderscript/ProgramStore$BlendDstFunc;->ONE_MINUS_SRC_ALPHA:Landroid/renderscript/ProgramStore$BlendDstFunc;
-Landroid/renderscript/ProgramStore$BlendDstFunc;->ZERO:Landroid/renderscript/ProgramStore$BlendDstFunc;
-Landroid/renderscript/ProgramStore$BlendSrcFunc;->ONE:Landroid/renderscript/ProgramStore$BlendSrcFunc;
-Landroid/renderscript/ProgramStore$BlendSrcFunc;->SRC_ALPHA:Landroid/renderscript/ProgramStore$BlendSrcFunc;
-Landroid/renderscript/ProgramStore$Builder;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/ProgramStore$Builder;->create()Landroid/renderscript/ProgramStore;
-Landroid/renderscript/ProgramStore$Builder;->setBlendFunc(Landroid/renderscript/ProgramStore$BlendSrcFunc;Landroid/renderscript/ProgramStore$BlendDstFunc;)Landroid/renderscript/ProgramStore$Builder;
-Landroid/renderscript/ProgramStore$Builder;->setDepthFunc(Landroid/renderscript/ProgramStore$DepthFunc;)Landroid/renderscript/ProgramStore$Builder;
-Landroid/renderscript/ProgramStore$Builder;->setDepthMaskEnabled(Z)Landroid/renderscript/ProgramStore$Builder;
-Landroid/renderscript/ProgramStore$Builder;->setDitherEnabled(Z)Landroid/renderscript/ProgramStore$Builder;
-Landroid/renderscript/ProgramStore$DepthFunc;->ALWAYS:Landroid/renderscript/ProgramStore$DepthFunc;
-Landroid/renderscript/ProgramStore$DepthFunc;->LESS:Landroid/renderscript/ProgramStore$DepthFunc;
-Landroid/renderscript/ProgramStore;->BLEND_ALPHA_DEPTH_NONE(Landroid/renderscript/RenderScript;)Landroid/renderscript/ProgramStore;
-Landroid/renderscript/ProgramVertex$Builder;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/ProgramVertex$Builder;->addInput(Landroid/renderscript/Element;)Landroid/renderscript/ProgramVertex$Builder;
-Landroid/renderscript/ProgramVertex$Builder;->create()Landroid/renderscript/ProgramVertex;
-Landroid/renderscript/ProgramVertexFixedFunction$Builder;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/ProgramVertexFixedFunction$Builder;->create()Landroid/renderscript/ProgramVertexFixedFunction;
-Landroid/renderscript/ProgramVertexFixedFunction$Constants;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/ProgramVertexFixedFunction$Constants;->setProjection(Landroid/renderscript/Matrix4f;)V
-Landroid/renderscript/ProgramVertexFixedFunction;->bindConstants(Landroid/renderscript/ProgramVertexFixedFunction$Constants;)V
-Landroid/renderscript/RenderScript;->create(Landroid/content/Context;I)Landroid/renderscript/RenderScript;
-Landroid/renderscript/RenderScript;->create(Landroid/content/Context;ILandroid/renderscript/RenderScript$ContextType;I)Landroid/renderscript/RenderScript;
-Landroid/renderscript/RenderScript;->getMinorID()J
-Landroid/renderscript/RenderScript;->mMessageCallback:Landroid/renderscript/RenderScript$RSMessageHandler;
-Landroid/renderscript/RenderScript;->nScriptCCreate(Ljava/lang/String;Ljava/lang/String;[BI)J
-Landroid/renderscript/RenderScript;->sPointerSize:I
-Landroid/renderscript/RenderScript;->validate()V
-Landroid/renderscript/RenderScriptCacheDir;->mCacheDir:Ljava/io/File;
-Landroid/renderscript/RenderScriptCacheDir;->setupDiskCache(Ljava/io/File;)V
-Landroid/renderscript/RenderScriptGL$SurfaceConfig;-><init>()V
-Landroid/renderscript/RenderScriptGL$SurfaceConfig;->setDepth(II)V
-Landroid/renderscript/RenderScriptGL;-><init>(Landroid/content/Context;Landroid/renderscript/RenderScriptGL$SurfaceConfig;)V
-Landroid/renderscript/RenderScriptGL;->bindProgramRaster(Landroid/renderscript/ProgramRaster;)V
-Landroid/renderscript/RenderScriptGL;->bindProgramStore(Landroid/renderscript/ProgramStore;)V
-Landroid/renderscript/RenderScriptGL;->bindProgramVertex(Landroid/renderscript/ProgramVertex;)V
-Landroid/renderscript/RenderScriptGL;->bindRootScript(Landroid/renderscript/Script;)V
-Landroid/renderscript/RenderScriptGL;->setSurface(Landroid/view/SurfaceHolder;II)V
-Landroid/renderscript/RSSurfaceView;-><init>(Landroid/content/Context;)V
-Landroid/renderscript/RSSurfaceView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Landroid/renderscript/Script$Builder;-><init>(Landroid/renderscript/RenderScript;)V
-Landroid/renderscript/Script$Builder;->mRS:Landroid/renderscript/RenderScript;
-Landroid/security/Credentials;->convertToPem([[Ljava/security/cert/Certificate;)[B
-Landroid/security/Credentials;->getInstance()Landroid/security/Credentials;
-Landroid/security/Credentials;->install(Landroid/content/Context;Ljava/lang/String;[B)V
-Landroid/security/Credentials;->install(Landroid/content/Context;Ljava/security/KeyPair;)V
-Landroid/security/Credentials;->unlock(Landroid/content/Context;)V
-Landroid/security/GateKeeper;->getSecureUserId()J
+Landroid/security/Credentials;->convertToPem([Ljava/security/cert/Certificate;)[B
 Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
 Landroid/security/IKeyChainService;->requestPrivateKey(Ljava/lang/String;)Ljava/lang/String;
 Landroid/security/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeystoreService;
@@ -5029,42 +1482,8 @@
 Landroid/security/IKeystoreService;->sign(Ljava/lang/String;[B)[B
 Landroid/security/IKeystoreService;->ungrant(Ljava/lang/String;I)I
 Landroid/security/IKeystoreService;->verify(Ljava/lang/String;[B[B)I
-Landroid/security/keymaster/ExportResult;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/security/keymaster/KeyCharacteristics;-><init>()V
-Landroid/security/keymaster/KeyCharacteristics;->readFromParcel(Landroid/os/Parcel;)V
-Landroid/security/keymaster/KeymasterArguments;-><init>()V
-Landroid/security/keymaster/KeymasterArguments;->addEnum(II)V
-Landroid/security/keymaster/KeymasterArguments;->addUnsignedInt(IJ)V
-Landroid/security/keymaster/KeymasterArguments;->addUnsignedLong(ILjava/math/BigInteger;)V
-Landroid/security/keymaster/KeymasterArguments;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/security/keymaster/KeymasterArguments;->readFromParcel(Landroid/os/Parcel;)V
-Landroid/security/keymaster/KeymasterBlob;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/security/keymaster/OperationResult;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/security/KeyStore$State;->LOCKED:Landroid/security/KeyStore$State;
-Landroid/security/KeyStore$State;->UNLOCKED:Landroid/security/KeyStore$State;
-Landroid/security/keystore/AndroidKeyStoreProvider;->getKeyStoreOperationHandle(Ljava/lang/Object;)J
-Landroid/security/keystore/KeyGenParameterSpec;->getUid()I
-Landroid/security/keystore/KeyGenParameterSpec;->isUniqueIdIncluded()Z
-Landroid/security/KeyStore;->delete(Ljava/lang/String;)Z
-Landroid/security/KeyStore;->get(Ljava/lang/String;)[B
-Landroid/security/KeyStore;->getApplicationContext()Landroid/content/Context;
-Landroid/security/KeyStore;->getInstance()Landroid/security/KeyStore;
-Landroid/security/KeyStore;->getKeyStoreException(I)Landroid/security/KeyStoreException;
-Landroid/security/KeyStore;->isEmpty()Z
-Landroid/security/KeyStore;->NO_ERROR:I
-Landroid/security/KeyStore;->reset()Z
-Landroid/security/KeyStore;->state()Landroid/security/KeyStore$State;
-Landroid/security/KeyStore;->state(I)Landroid/security/KeyStore$State;
-Landroid/security/KeyStore;->unlock(Ljava/lang/String;)Z
-Landroid/security/KeystoreArguments;-><init>([[B)V
-Landroid/security/KeystoreArguments;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/security/net/config/RootTrustManager;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
 Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
 Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
-Landroid/service/dreams/DreamService;->getDozeScreenBrightness()I
-Landroid/service/dreams/DreamService;->setDozeScreenBrightness(I)V
-Landroid/service/dreams/DreamService;->setDozeScreenState(I)V
-Landroid/service/dreams/DreamService;->setWindowless(Z)V
 Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
 Landroid/service/dreams/IDreamManager;->awaken()V
 Landroid/service/dreams/IDreamManager;->dream()V
@@ -5088,46 +1507,8 @@
 Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnectFailed()V
 Landroid/service/media/IMediaBrowserServiceCallbacks;->onLoadChildren(Ljava/lang/String;Landroid/content/pm/ParceledListSlice;)V
 Landroid/service/media/IMediaBrowserServiceCallbacks;->onLoadChildrenWithOptions(Ljava/lang/String;Landroid/content/pm/ParceledListSlice;Landroid/os/Bundle;)V
-Landroid/service/media/MediaBrowserService$Result;->mFlags:I
-Landroid/service/media/MediaBrowserService;->KEY_MEDIA_ITEM:Ljava/lang/String;
 Landroid/service/notification/INotificationListener$Stub;-><init>()V
-Landroid/service/notification/NotificationListenerService$Ranking;->getVisibilityOverride()I
-Landroid/service/notification/NotificationListenerService;->getNotificationInterface()Landroid/app/INotificationManager;
-Landroid/service/notification/NotificationListenerService;->isBound()Z
-Landroid/service/notification/NotificationListenerService;->mHandler:Landroid/os/Handler;
-Landroid/service/notification/NotificationListenerService;->mNoMan:Landroid/app/INotificationManager;
-Landroid/service/notification/NotificationListenerService;->mWrapper:Landroid/service/notification/NotificationListenerService$NotificationListenerWrapper;
-Landroid/service/notification/NotificationListenerService;->TAG:Ljava/lang/String;
-Landroid/service/notification/StatusBarNotification;->getInitialPid()I
-Landroid/service/notification/StatusBarNotification;->getOpPkg()Ljava/lang/String;
-Landroid/service/notification/StatusBarNotification;->getPackageContext(Landroid/content/Context;)Landroid/content/Context;
-Landroid/service/notification/StatusBarNotification;->getUid()I
-Landroid/service/notification/StatusBarNotification;->id:I
-Landroid/service/notification/StatusBarNotification;->initialPid:I
-Landroid/service/notification/StatusBarNotification;->notification:Landroid/app/Notification;
-Landroid/service/notification/StatusBarNotification;->pkg:Ljava/lang/String;
-Landroid/service/notification/StatusBarNotification;->postTime:J
-Landroid/service/notification/StatusBarNotification;->tag:Ljava/lang/String;
-Landroid/service/notification/StatusBarNotification;->uid:I
-Landroid/service/notification/StatusBarNotification;->user:Landroid/os/UserHandle;
-Landroid/service/notification/ZenModeConfig$ScheduleInfo;->days:[I
-Landroid/service/notification/ZenModeConfig$ScheduleInfo;->endHour:I
-Landroid/service/notification/ZenModeConfig$ScheduleInfo;->endMinute:I
-Landroid/service/notification/ZenModeConfig$ScheduleInfo;->startHour:I
-Landroid/service/notification/ZenModeConfig$ScheduleInfo;->startMinute:I
-Landroid/service/notification/ZenModeConfig$ZenRule;->conditionId:Landroid/net/Uri;
-Landroid/service/notification/ZenModeConfig$ZenRule;->creationTime:J
-Landroid/service/notification/ZenModeConfig$ZenRule;->enabled:Z
-Landroid/service/notification/ZenModeConfig$ZenRule;->name:Ljava/lang/String;
-Landroid/service/notification/ZenModeConfig$ZenRule;->snoozing:Z
-Landroid/service/notification/ZenModeConfig$ZenRule;->zenMode:I
-Landroid/service/notification/ZenModeConfig;-><init>()V
-Landroid/service/notification/ZenModeConfig;->allowAlarms:Z
-Landroid/service/notification/ZenModeConfig;->automaticRules:Landroid/util/ArrayMap;
-Landroid/service/notification/ZenModeConfig;->tryParseScheduleConditionId(Landroid/net/Uri;)Landroid/service/notification/ZenModeConfig$ScheduleInfo;
 Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/persistentdata/IPersistentDataBlockService;
-Landroid/service/voice/AlwaysOnHotwordDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer;
-Landroid/service/voice/VoiceInteractionService;->isKeyphraseAndLocaleSupportedForHotword(Ljava/lang/String;Ljava/util/Locale;)Z
 Landroid/service/vr/IVrManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/vr/IVrManager;
 Landroid/service/vr/IVrManager;->getVr2dDisplayId()I
 Landroid/service/vr/IVrManager;->getVrModeState()Z
@@ -5138,21 +1519,7 @@
 Landroid/service/wallpaper/IWallpaperEngine;->setDesiredSize(II)V
 Landroid/service/wallpaper/IWallpaperEngine;->setVisibility(Z)V
 Landroid/service/wallpaper/IWallpaperService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/wallpaper/IWallpaperService;
-Landroid/service/wallpaper/WallpaperService$Engine;->mPendingXOffset:F
-Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V
-Landroid/service/wallpaper/WallpaperService;->MSG_WINDOW_RESIZED:I
 Landroid/speech/IRecognitionListener;->onEvent(ILandroid/os/Bundle;)V
-Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String;
-Landroid/speech/tts/TextToSpeech;->mConnectingServiceConnection:Landroid/speech/tts/TextToSpeech$Connection;
-Landroid/speech/tts/TextToSpeech;->mCurrentEngine:Ljava/lang/String;
-Landroid/speech/tts/TextToSpeech;->mInitListener:Landroid/speech/tts/TextToSpeech$OnInitListener;
-Landroid/speech/tts/TtsEngines;-><init>(Landroid/content/Context;)V
-Landroid/speech/tts/TtsEngines;->getEngines()Ljava/util/List;
-Landroid/speech/tts/TtsEngines;->getLocalePrefForEngine(Ljava/lang/String;)Ljava/util/Locale;
-Landroid/speech/tts/TtsEngines;->getSettingsIntent(Ljava/lang/String;)Landroid/content/Intent;
-Landroid/speech/tts/TtsEngines;->normalizeTTSLocale(Ljava/util/Locale;)Ljava/util/Locale;
-Landroid/speech/tts/TtsEngines;->parseLocaleString(Ljava/lang/String;)Ljava/util/Locale;
-Landroid/speech/tts/TtsEngines;->updateLocalePrefForEngine(Ljava/lang/String;Ljava/util/Locale;)V
 Landroid/system/Int32Ref;->value:I
 Landroid/system/OsConstants;-><init>()V
 Landroid/system/OsConstants;->AF_NETLINK:I
@@ -5209,525 +1576,8 @@
 Landroid/system/OsConstants;->XATTR_REPLACE:I
 Landroid/system/OsConstants;->_LINUX_CAPABILITY_VERSION_3:I
 Landroid/system/StructTimeval;->fromMillis(J)Landroid/system/StructTimeval;
-Landroid/telecom/AudioState;->isMuted:Z
-Landroid/telecom/AudioState;->route:I
-Landroid/telecom/AudioState;->supportedRouteMask:I
-Landroid/telecom/Call$Details;->CAPABILITY_CAN_UPGRADE_TO_VIDEO:I
-Landroid/telecom/Connection$VideoProvider;-><init>(Landroid/os/Looper;)V
-Landroid/telecom/Phone;->setProximitySensorOff(Z)V
-Landroid/telecom/Phone;->setProximitySensorOn()V
-Landroid/telecom/PhoneAccountHandle;-><init>(Landroid/os/Parcel;)V
-Landroid/telecom/PhoneAccountHandle;->mComponentName:Landroid/content/ComponentName;
-Landroid/telecom/PhoneAccountHandle;->mId:Ljava/lang/String;
-Landroid/telecom/TelecomManager;->EXTRA_IS_HANDOVER:Ljava/lang/String;
-Landroid/telecom/TelecomManager;->getCallCapablePhoneAccounts(Z)Ljava/util/List;
-Landroid/telecom/TelecomManager;->getCurrentTtyMode()I
-Landroid/telecom/TelecomManager;->getSimCallManager(I)Landroid/telecom/PhoneAccountHandle;
-Landroid/telecom/TelecomManager;->getSystemDialerPackage()Ljava/lang/String;
-Landroid/telecom/TelecomManager;->getUserSelectedOutgoingPhoneAccount()Landroid/telecom/PhoneAccountHandle;
-Landroid/telecom/TelecomManager;->setDefaultDialer(Ljava/lang/String;)Z
-Landroid/telecom/TelecomManager;->setUserSelectedOutgoingPhoneAccount(Landroid/telecom/PhoneAccountHandle;)V
-Landroid/telecom/TelecomManager;->TTY_MODE_OFF:I
-Landroid/telecom/VideoCallImpl;->destroy()V
-Landroid/telephony/CarrierConfigManager;->KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY:Ljava/lang/String;
-Landroid/telephony/CarrierConfigManager;->KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL:Ljava/lang/String;
 Landroid/telephony/CarrierMessagingServiceManager;-><init>()V
-Landroid/telephony/cdma/CdmaCellLocation;->equalsHandlesNulls(Ljava/lang/Object;Ljava/lang/Object;)Z
-Landroid/telephony/cdma/CdmaCellLocation;->mBaseStationId:I
-Landroid/telephony/cdma/CdmaCellLocation;->mBaseStationLatitude:I
-Landroid/telephony/cdma/CdmaCellLocation;->mBaseStationLongitude:I
-Landroid/telephony/cdma/CdmaCellLocation;->mNetworkId:I
-Landroid/telephony/cdma/CdmaCellLocation;->mSystemId:I
-Landroid/telephony/CellBroadcastMessage;-><init>(Landroid/telephony/SmsCbMessage;)V
-Landroid/telephony/CellBroadcastMessage;->createFromCursor(Landroid/database/Cursor;)Landroid/telephony/CellBroadcastMessage;
-Landroid/telephony/CellBroadcastMessage;->getContentValues()Landroid/content/ContentValues;
-Landroid/telephony/CellBroadcastMessage;->getDeliveryTime()J
-Landroid/telephony/CellBroadcastMessage;->getEtwsWarningInfo()Landroid/telephony/SmsCbEtwsInfo;
-Landroid/telephony/CellBroadcastMessage;->getLanguageCode()Ljava/lang/String;
-Landroid/telephony/CellBroadcastMessage;->getMessageBody()Ljava/lang/String;
-Landroid/telephony/CellBroadcastMessage;->getSerialNumber()I
-Landroid/telephony/CellBroadcastMessage;->getServiceCategory()I
-Landroid/telephony/CellBroadcastMessage;->getSpokenDateString(Landroid/content/Context;)Ljava/lang/String;
-Landroid/telephony/CellBroadcastMessage;->isCmasMessage()Z
-Landroid/telephony/CellBroadcastMessage;->isEmergencyAlertMessage()Z
-Landroid/telephony/CellBroadcastMessage;->isEtwsMessage()Z
-Landroid/telephony/CellBroadcastMessage;->isRead()Z
-Landroid/telephony/CellIdentityCdma;-><init>(IIIII)V
-Landroid/telephony/CellIdentityGsm;-><init>()V
-Landroid/telephony/CellIdentityGsm;->mArfcn:I
-Landroid/telephony/CellIdentityGsm;->mBsic:I
-Landroid/telephony/CellIdentityLte;-><init>()V
-Landroid/telephony/CellIdentityLte;-><init>(IIIII)V
-Landroid/telephony/CellIdentityLte;->mEarfcn:I
-Landroid/telephony/CellIdentityWcdma;->mUarfcn:I
-Landroid/telephony/CellInfo;->getTimeStampType()I
-Landroid/telephony/CellInfo;->timeStampTypeToString(I)Ljava/lang/String;
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_ANTENNA:I
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_JAVA_RIL:I
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_MODEM:I
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_OEM_RIL:I
-Landroid/telephony/CellInfo;->TIMESTAMP_TYPE_UNKNOWN:I
-Landroid/telephony/CellInfoCdma;-><init>()V
-Landroid/telephony/CellInfoCdma;-><init>(Landroid/telephony/CellInfoCdma;)V
-Landroid/telephony/CellInfoCdma;->setCellIdentity(Landroid/telephony/CellIdentityCdma;)V
-Landroid/telephony/CellInfoGsm;-><init>()V
-Landroid/telephony/CellInfoLte;-><init>()V
-Landroid/telephony/CellInfoLte;->setCellIdentity(Landroid/telephony/CellIdentityLte;)V
-Landroid/telephony/CellInfoLte;->setCellSignalStrength(Landroid/telephony/CellSignalStrengthLte;)V
-Landroid/telephony/CellLocation;->fillInNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/CellLocation;->isEmpty()Z
-Landroid/telephony/CellLocation;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/CellLocation;
-Landroid/telephony/CellSignalStrengthGsm;-><init>()V
-Landroid/telephony/CellSignalStrengthGsm;->mBitErrorRate:I
-Landroid/telephony/CellSignalStrengthGsm;->mSignalStrength:I
-Landroid/telephony/CellSignalStrengthGsm;->mTimingAdvance:I
-Landroid/telephony/CellSignalStrengthLte;-><init>()V
-Landroid/telephony/CellSignalStrengthLte;->mCqi:I
-Landroid/telephony/CellSignalStrengthLte;->mRsrp:I
-Landroid/telephony/CellSignalStrengthLte;->mRsrq:I
-Landroid/telephony/CellSignalStrengthLte;->mRssnr:I
-Landroid/telephony/CellSignalStrengthLte;->mSignalStrength:I
-Landroid/telephony/CellSignalStrengthLte;->mTimingAdvance:I
-Landroid/telephony/CellSignalStrengthWcdma;->mBitErrorRate:I
-Landroid/telephony/CellSignalStrengthWcdma;->mSignalStrength:I
-Landroid/telephony/DisconnectCause;->toString(I)Ljava/lang/String;
-Landroid/telephony/euicc/EuiccInfo;->osVersion:Ljava/lang/String;
-Landroid/telephony/gsm/GsmCellLocation;->setPsc(I)V
-Landroid/telephony/ims/ImsSsInfo;-><init>()V
-Landroid/telephony/NeighboringCellInfo;->mCid:I
-Landroid/telephony/NeighboringCellInfo;->mLac:I
-Landroid/telephony/NeighboringCellInfo;->mNetworkType:I
-Landroid/telephony/NeighboringCellInfo;->mPsc:I
-Landroid/telephony/NeighboringCellInfo;->mRssi:I
-Landroid/telephony/PhoneNumberFormattingTextWatcher;->mFormatter:Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;
-Landroid/telephony/PhoneNumberUtils;->cdmaCheckAndProcessPlusCode(Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->compare(Ljava/lang/String;Ljava/lang/String;Z)Z
-Landroid/telephony/PhoneNumberUtils;->compareLoosely(Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->compareStrictly(Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->compareStrictly(Ljava/lang/String;Ljava/lang/String;Z)Z
-Landroid/telephony/PhoneNumberUtils;->convertPreDial(Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->extractNetworkPortionAlt(Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->getUsernameFromUriNumber(Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->isEmergencyNumber(Ljava/lang/String;Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isNanp(Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isPotentialLocalEmergencyNumber(Landroid/content/Context;Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isUriNumber(Ljava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isVoiceMailNumber(Landroid/content/Context;ILjava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->MIN_MATCH:I
-Landroid/telephony/PhoneNumberUtils;->ttsSpanAsPhoneNumber(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
-Landroid/telephony/PhoneStateListener;-><init>(Landroid/os/Looper;)V
-Landroid/telephony/PhoneStateListener;->callback:Lcom/android/internal/telephony/IPhoneStateListener;
-Landroid/telephony/PhoneStateListener;->LISTEN_PRECISE_CALL_STATE:I
-Landroid/telephony/PhoneStateListener;->mSubId:Ljava/lang/Integer;
-Landroid/telephony/PhoneStateListener;->onDataConnectionRealTimeInfoChanged(Landroid/telephony/DataConnectionRealTimeInfo;)V
-Landroid/telephony/PhoneStateListener;->onOemHookRawEvent([B)V
-Landroid/telephony/PhoneStateListener;->onOtaspChanged(I)V
-Landroid/telephony/PhoneStateListener;->onPreciseCallStateChanged(Landroid/telephony/PreciseCallState;)V
-Landroid/telephony/PhoneStateListener;->onPreciseDataConnectionStateChanged(Landroid/telephony/PreciseDataConnectionState;)V
-Landroid/telephony/PhoneStateListener;->onVoLteServiceStateChanged(Landroid/telephony/VoLteServiceState;)V
-Landroid/telephony/PreciseCallState;-><init>(IIIII)V
-Landroid/telephony/PreciseCallState;->getDisconnectCause()I
-Landroid/telephony/PreciseCallState;->getPreciseDisconnectCause()I
-Landroid/telephony/PreciseCallState;->getRingingCallState()I
-Landroid/telephony/PreciseDataConnectionState;-><init>(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/net/LinkProperties;Ljava/lang/String;)V
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionAPN()Ljava/lang/String;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionAPNType()Ljava/lang/String;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionChangeReason()Ljava/lang/String;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionFailCause()Ljava/lang/String;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionLinkProperties()Landroid/net/LinkProperties;
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionNetworkType()I
-Landroid/telephony/PreciseDataConnectionState;->getDataConnectionState()I
-Landroid/telephony/RadioAccessFamily;->getNetworkTypeFromRaf(I)I
-Landroid/telephony/RadioAccessFamily;->getPhoneId()I
-Landroid/telephony/RadioAccessFamily;->getRadioAccessFamily()I
-Landroid/telephony/Rlog;->d(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/telephony/Rlog;->i(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/telephony/Rlog;->v(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/Rlog;->w(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/Rlog;->w(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/telephony/ServiceState;->bearerBitmapHasCdma(I)Z
-Landroid/telephony/ServiceState;->equalsHandlesNulls(Ljava/lang/Object;Ljava/lang/Object;)Z
-Landroid/telephony/ServiceState;->fillInNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/ServiceState;->getCdmaDefaultRoamingIndicator()I
-Landroid/telephony/ServiceState;->getCdmaEriIconIndex()I
-Landroid/telephony/ServiceState;->getCdmaEriIconMode()I
-Landroid/telephony/ServiceState;->getCdmaRoamingIndicator()I
-Landroid/telephony/ServiceState;->getCssIndicator()I
-Landroid/telephony/ServiceState;->getDataNetworkType()I
-Landroid/telephony/ServiceState;->getDataOperatorAlphaShort()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getDataOperatorNumeric()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getDataRoamingType()I
-Landroid/telephony/ServiceState;->getRadioTechnology()I
-Landroid/telephony/ServiceState;->getRilVoiceRadioTechnology()I
-Landroid/telephony/ServiceState;->getVoiceOperatorAlphaLong()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getVoiceOperatorAlphaShort()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getVoiceOperatorNumeric()Ljava/lang/String;
-Landroid/telephony/ServiceState;->getVoiceRoaming()Z
-Landroid/telephony/ServiceState;->getVoiceRoamingType()I
-Landroid/telephony/ServiceState;->mCdmaDefaultRoamingIndicator:I
-Landroid/telephony/ServiceState;->mCdmaEriIconIndex:I
-Landroid/telephony/ServiceState;->mCdmaEriIconMode:I
-Landroid/telephony/ServiceState;->mCdmaRoamingIndicator:I
-Landroid/telephony/ServiceState;->mCssIndicator:Z
-Landroid/telephony/ServiceState;->mIsManualNetworkSelection:Z
-Landroid/telephony/ServiceState;->mIsUsingCarrierAggregation:Z
-Landroid/telephony/ServiceState;->mNetworkId:I
-Landroid/telephony/ServiceState;->mSystemId:I
-Landroid/telephony/ServiceState;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState;
-Landroid/telephony/ServiceState;->RIL_RADIO_TECHNOLOGY_IWLAN:I
-Landroid/telephony/ServiceState;->setCdmaDefaultRoamingIndicator(I)V
-Landroid/telephony/ServiceState;->setCdmaEriIconIndex(I)V
-Landroid/telephony/ServiceState;->setCdmaEriIconMode(I)V
-Landroid/telephony/ServiceState;->setCdmaRoamingIndicator(I)V
-Landroid/telephony/ServiceState;->setCssIndicator(I)V
-Landroid/telephony/ServiceState;->setDataRegState(I)V
-Landroid/telephony/ServiceState;->setDataRoaming(Z)V
-Landroid/telephony/ServiceState;->setDataRoamingFromRegistration(Z)V
-Landroid/telephony/ServiceState;->setDataRoamingType(I)V
-Landroid/telephony/ServiceState;->setEmergencyOnly(Z)V
-Landroid/telephony/ServiceState;->setFromNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/ServiceState;->setOperatorAlphaLong(Ljava/lang/String;)V
-Landroid/telephony/ServiceState;->setVoiceRegState(I)V
-Landroid/telephony/ServiceState;->setVoiceRoaming(Z)V
-Landroid/telephony/ServiceState;->setVoiceRoamingType(I)V
-Landroid/telephony/SignalStrength;-><init>()V
-Landroid/telephony/SignalStrength;-><init>(Landroid/os/Parcel;)V
-Landroid/telephony/SignalStrength;-><init>(Landroid/telephony/SignalStrength;)V
-Landroid/telephony/SignalStrength;-><init>(Z)V
-Landroid/telephony/SignalStrength;->copyFrom(Landroid/telephony/SignalStrength;)V
-Landroid/telephony/SignalStrength;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/telephony/SignalStrength;->fillInNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/SignalStrength;->getAsuLevel()I
-Landroid/telephony/SignalStrength;->getCdmaAsuLevel()I
-Landroid/telephony/SignalStrength;->getCdmaLevel()I
-Landroid/telephony/SignalStrength;->getDbm()I
-Landroid/telephony/SignalStrength;->getEvdoAsuLevel()I
-Landroid/telephony/SignalStrength;->getEvdoLevel()I
-Landroid/telephony/SignalStrength;->getGsmAsuLevel()I
-Landroid/telephony/SignalStrength;->getGsmDbm()I
-Landroid/telephony/SignalStrength;->getGsmLevel()I
-Landroid/telephony/SignalStrength;->getLteAsuLevel()I
-Landroid/telephony/SignalStrength;->getLteCqi()I
-Landroid/telephony/SignalStrength;->getLteDbm()I
-Landroid/telephony/SignalStrength;->getLteLevel()I
-Landroid/telephony/SignalStrength;->getLteRsrp()I
-Landroid/telephony/SignalStrength;->getLteRsrq()I
-Landroid/telephony/SignalStrength;->getLteRssnr()I
-Landroid/telephony/SignalStrength;->getLteSignalStrength()I
-Landroid/telephony/SignalStrength;->getTdScdmaAsuLevel()I
-Landroid/telephony/SignalStrength;->getTdScdmaDbm()I
-Landroid/telephony/SignalStrength;->getTdScdmaLevel()I
-Landroid/telephony/SignalStrength;->mCdmaDbm:I
-Landroid/telephony/SignalStrength;->mCdmaEcio:I
-Landroid/telephony/SignalStrength;->mEvdoDbm:I
-Landroid/telephony/SignalStrength;->mEvdoEcio:I
-Landroid/telephony/SignalStrength;->mEvdoSnr:I
-Landroid/telephony/SignalStrength;->mGsmBitErrorRate:I
-Landroid/telephony/SignalStrength;->mGsmSignalStrength:I
-Landroid/telephony/SignalStrength;->mLteCqi:I
-Landroid/telephony/SignalStrength;->mLteRsrp:I
-Landroid/telephony/SignalStrength;->mLteRsrpBoost:I
-Landroid/telephony/SignalStrength;->mLteRsrq:I
-Landroid/telephony/SignalStrength;->mLteRssnr:I
-Landroid/telephony/SignalStrength;->mLteSignalStrength:I
-Landroid/telephony/SignalStrength;->mTdScdmaRscp:I
-Landroid/telephony/SignalStrength;->mWcdmaRscp:I
-Landroid/telephony/SignalStrength;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/SignalStrength;
-Landroid/telephony/SignalStrength;->NUM_SIGNAL_STRENGTH_BINS:I
-Landroid/telephony/SignalStrength;->setFromNotifierBundle(Landroid/os/Bundle;)V
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_GOOD:I
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_GREAT:I
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_MODERATE:I
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_NONE_OR_UNKNOWN:I
-Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_POOR:I
-Landroid/telephony/SignalStrength;->validateInput()V
-Landroid/telephony/SmsManager;->copyMessageToIcc([B[BI)Z
-Landroid/telephony/SmsManager;->deleteMessageFromIcc(I)Z
-Landroid/telephony/SmsManager;->disableCellBroadcastRange(III)Z
-Landroid/telephony/SmsManager;->enableCellBroadcastRange(III)Z
-Landroid/telephony/SmsManager;->getAllMessagesFromIcc()Ljava/util/ArrayList;
-Landroid/telephony/SmsManager;->isSMSPromptEnabled()Z
-Landroid/telephony/SmsManager;->mSubId:I
-Landroid/telephony/SmsManager;->sendMultipartTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;Ljava/util/ArrayList;Ljava/util/ArrayList;IZI)V
-Landroid/telephony/SmsManager;->sendTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;IZI)V
-Landroid/telephony/SmsManager;->sendTextMessageWithoutPersisting(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;IZI)V
-Landroid/telephony/SmsManager;->updateMessageOnIcc(II[B)Z
-Landroid/telephony/SmsMessage;->fragmentText(Ljava/lang/String;)Ljava/util/ArrayList;
-Landroid/telephony/SmsMessage;->getSubId()I
-Landroid/telephony/SmsMessage;->mSubId:I
-Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase;
-Landroid/telephony/SmsMessage;->setSubId(I)V
-Landroid/telephony/SmsMessage;->useCdmaFormatForMoSms()Z
-Landroid/telephony/SmsMessage;->useCdmaFormatForMoSms(I)Z
-Landroid/telephony/SubscriptionInfo;->getNameSource()I
-Landroid/telephony/SubscriptionManager;-><init>(Landroid/content/Context;)V
-Landroid/telephony/SubscriptionManager;->CONTENT_URI:Landroid/net/Uri;
-Landroid/telephony/SubscriptionManager;->DEFAULT_SUBSCRIPTION_ID:I
-Landroid/telephony/SubscriptionManager;->getActiveSubscriptionIdList()[I
-Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoCount()I
-Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoList()Ljava/util/List;
-Landroid/telephony/SubscriptionManager;->getDefaultDataPhoneId()I
-Landroid/telephony/SubscriptionManager;->getDefaultDataSubscriptionInfo()Landroid/telephony/SubscriptionInfo;
-Landroid/telephony/SubscriptionManager;->getDefaultSmsPhoneId()I
-Landroid/telephony/SubscriptionManager;->getDefaultVoiceSubscriptionInfo()Landroid/telephony/SubscriptionInfo;
-Landroid/telephony/SubscriptionManager;->getPhoneId(I)I
-Landroid/telephony/SubscriptionManager;->getSlotIndex(I)I
-Landroid/telephony/SubscriptionManager;->getSubId(I)[I
-Landroid/telephony/SubscriptionManager;->NAME_SOURCE_USER_INPUT:I
-Landroid/telephony/SubscriptionManager;->setDataRoaming(II)I
-Landroid/telephony/SubscriptionManager;->setDefaultDataSubId(I)V
-Landroid/telephony/SubscriptionManager;->setDefaultSmsSubId(I)V
-Landroid/telephony/SubscriptionManager;->setDisplayNumber(Ljava/lang/String;I)I
-Landroid/telephony/TelephonyManager$MultiSimVariants;->TSTS:Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager$MultiSimVariants;->UNKNOWN:Landroid/telephony/TelephonyManager$MultiSimVariants;
 Landroid/telephony/TelephonyManager$MultiSimVariants;->values()[Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager;-><init>()V
-Landroid/telephony/TelephonyManager;-><init>(Landroid/content/Context;)V
-Landroid/telephony/TelephonyManager;-><init>(Landroid/content/Context;I)V
-Landroid/telephony/TelephonyManager;->ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED:Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->from(Landroid/content/Context;)Landroid/telephony/TelephonyManager;
-Landroid/telephony/TelephonyManager;->getCallState(I)I
-Landroid/telephony/TelephonyManager;->getCdmaEriIconIndex(I)I
-Landroid/telephony/TelephonyManager;->getCdmaEriIconMode(I)I
-Landroid/telephony/TelephonyManager;->getCdmaEriText(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getDataNetworkType(I)I
-Landroid/telephony/TelephonyManager;->getDefault()Landroid/telephony/TelephonyManager;
-Landroid/telephony/TelephonyManager;->getDeviceSoftwareVersion(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getGroupIdLevel1(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getIccAuthentication(IIILjava/lang/String;)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getImsConfig(II)Landroid/telephony/ims/aidl/IImsConfig;
-Landroid/telephony/TelephonyManager;->getImsRegistration(II)Landroid/telephony/ims/aidl/IImsRegistration;
-Landroid/telephony/TelephonyManager;->getIsimImpi()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getIsimImpu()[Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getIsimPcscf()[Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getITelephony()Lcom/android/internal/telephony/ITelephony;
-Landroid/telephony/TelephonyManager;->getLine1AlphaTag(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getLine1Number(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getLteOnCdmaMode()I
-Landroid/telephony/TelephonyManager;->getLteOnCdmaMode(I)I
-Landroid/telephony/TelephonyManager;->getLteOnCdmaModeStatic()I
-Landroid/telephony/TelephonyManager;->getMergedSubscriberIds()[Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getMsisdn()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getMsisdn(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getMultiSimConfiguration()Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager;->getNai(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkClass(I)I
-Landroid/telephony/TelephonyManager;->getNetworkCountryIso(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkCountryIsoForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkOperator(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkOperatorForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkOperatorName(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkType(I)I
-Landroid/telephony/TelephonyManager;->getNetworkTypeName(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getOtaSpNumberSchemaForPhone(ILjava/lang/String;)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getPhoneId(I)I
-Landroid/telephony/TelephonyManager;->getPhoneType(I)I
-Landroid/telephony/TelephonyManager;->getPhoneTypeFromProperty(I)I
-Landroid/telephony/TelephonyManager;->getProcCmdLine()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimCount()I
-Landroid/telephony/TelephonyManager;->getSimCountryIso(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimCountryIsoForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperator(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorName(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorNameForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorNumeric()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorNumeric(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimOperatorNumericForPhone(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSimSerialNumber(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSlotIndex()I
-Landroid/telephony/TelephonyManager;->getSubId(I)I
-Landroid/telephony/TelephonyManager;->getSubIdForPhoneAccount(Landroid/telecom/PhoneAccount;)I
-Landroid/telephony/TelephonyManager;->getSubscriberId(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getSubscriberInfo()Lcom/android/internal/telephony/IPhoneSubInfo;
-Landroid/telephony/TelephonyManager;->getTelephonyProperty(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getTelephonyProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getVoiceMailAlphaTag(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getVoiceMailNumber(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getVoiceMessageCount(I)I
-Landroid/telephony/TelephonyManager;->hasIccCard(I)Z
-Landroid/telephony/TelephonyManager;->isMultiSimEnabled()Z
-Landroid/telephony/TelephonyManager;->isNetworkRoaming(I)Z
-Landroid/telephony/TelephonyManager;->isVideoTelephonyAvailable()Z
-Landroid/telephony/TelephonyManager;->isVolteAvailable()Z
-Landroid/telephony/TelephonyManager;->isWifiCallingAvailable()Z
-Landroid/telephony/TelephonyManager;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
-Landroid/telephony/TelephonyManager;->NETWORK_CLASS_2_G:I
-Landroid/telephony/TelephonyManager;->NETWORK_CLASS_3_G:I
-Landroid/telephony/TelephonyManager;->NETWORK_CLASS_4_G:I
-Landroid/telephony/TelephonyManager;->NETWORK_TYPE_LTE_CA:I
-Landroid/telephony/TelephonyManager;->nvReadItem(I)Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->setBasebandVersionForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setDataNetworkTypeForPhone(II)V
-Landroid/telephony/TelephonyManager;->setImsRegistrationState(Z)V
-Landroid/telephony/TelephonyManager;->setNetworkOperatorNameForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setNetworkOperatorNumericForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setNetworkRoamingForPhone(IZ)V
-Landroid/telephony/TelephonyManager;->setPhoneType(II)V
-Landroid/telephony/TelephonyManager;->setRoamingOverride(Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;)Z
-Landroid/telephony/TelephonyManager;->setSimCountryIsoForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setSimOperatorNameForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setSimOperatorNumericForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setSimStateForPhone(ILjava/lang/String;)V
-Landroid/telephony/TelephonyManager;->setTelephonyProperty(ILjava/lang/String;Ljava/lang/String;)V
-Landroid/telephony/VoLteServiceState;-><init>(I)V
-Landroid/text/AndroidBidi;->bidi(I[C[B)I
-Landroid/text/BoringLayout;->isBoring(Ljava/lang/CharSequence;Landroid/text/TextPaint;Landroid/text/TextDirectionHeuristic;Landroid/text/BoringLayout$Metrics;)Landroid/text/BoringLayout$Metrics;
-Landroid/text/DynamicLayout;-><init>(Ljava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/text/TextPaint;ILandroid/text/Layout$Alignment;Landroid/text/TextDirectionHeuristic;FFZIIILandroid/text/TextUtils$TruncateAt;I)V
-Landroid/text/DynamicLayout;->getBlockEndLines()[I
-Landroid/text/DynamicLayout;->getBlockIndices()[I
-Landroid/text/DynamicLayout;->getIndexFirstChangedBlock()I
-Landroid/text/DynamicLayout;->getNumberOfBlocks()I
-Landroid/text/DynamicLayout;->setIndexFirstChangedBlock(I)V
-Landroid/text/DynamicLayout;->sStaticLayout:Landroid/text/StaticLayout;
-Landroid/text/FontConfig$Family;->getFonts()[Landroid/text/FontConfig$Font;
-Landroid/text/FontConfig$Family;->getName()Ljava/lang/String;
-Landroid/text/FontConfig$Family;->getVariant()I
-Landroid/text/FontConfig$Font;->getAxes()[Landroid/graphics/fonts/FontVariationAxis;
-Landroid/text/FontConfig$Font;->getTtcIndex()I
-Landroid/text/FontConfig$Font;->getWeight()I
-Landroid/text/FontConfig$Font;->isItalic()Z
-Landroid/text/FontConfig;->getFamilies()[Landroid/text/FontConfig$Family;
-Landroid/text/format/DateFormat;->getTimeFormatString(Landroid/content/Context;)Ljava/lang/String;
-Landroid/text/format/DateFormat;->getTimeFormatString(Landroid/content/Context;I)Ljava/lang/String;
-Landroid/text/format/DateFormat;->hasDesignator(Ljava/lang/CharSequence;C)Z
-Landroid/text/format/DateFormat;->hasSeconds(Ljava/lang/CharSequence;)Z
-Landroid/text/format/DateFormat;->is24HourFormat(Landroid/content/Context;I)Z
-Landroid/text/format/DateUtils;->formatDuration(J)Ljava/lang/CharSequence;
-Landroid/text/format/DateUtils;->formatDuration(JI)Ljava/lang/CharSequence;
-Landroid/text/format/Formatter;->formatBytes(Landroid/content/res/Resources;JI)Landroid/text/format/Formatter$BytesResult;
-Landroid/text/format/Formatter;->formatShortElapsedTime(Landroid/content/Context;J)Ljava/lang/String;
-Landroid/text/format/Formatter;->formatShortElapsedTimeRoundingUpToMinutes(Landroid/content/Context;J)Ljava/lang/String;
-Landroid/text/Html;->withinStyle(Ljava/lang/StringBuilder;Ljava/lang/CharSequence;II)V
-Landroid/text/InputFilter$LengthFilter;->mMax:I
-Landroid/text/Layout$Alignment;->ALIGN_LEFT:Landroid/text/Layout$Alignment;
-Landroid/text/Layout$Alignment;->ALIGN_RIGHT:Landroid/text/Layout$Alignment;
-Landroid/text/Layout;->DIRS_ALL_LEFT_TO_RIGHT:Landroid/text/Layout$Directions;
-Landroid/text/Layout;->DIRS_ALL_RIGHT_TO_LEFT:Landroid/text/Layout$Directions;
-Landroid/text/Layout;->DIR_REQUEST_DEFAULT_LTR:I
-Landroid/text/Layout;->drawBackground(Landroid/graphics/Canvas;Landroid/graphics/Path;Landroid/graphics/Paint;III)V
-Landroid/text/Layout;->drawText(Landroid/graphics/Canvas;II)V
-Landroid/text/Layout;->getLineRangeForDraw(Landroid/graphics/Canvas;)J
-Landroid/text/Layout;->getPrimaryHorizontal(IZ)F
-Landroid/text/Layout;->getSecondaryHorizontal(IZ)F
-Landroid/text/Layout;->isLevelBoundary(I)Z
-Landroid/text/Layout;->mPaint:Landroid/text/TextPaint;
-Landroid/text/Layout;->shouldClampCursor(I)Z
-Landroid/text/method/AllCapsTransformationMethod;-><init>(Landroid/content/Context;)V
-Landroid/text/method/HideReturnsTransformationMethod;->sInstance:Landroid/text/method/HideReturnsTransformationMethod;
-Landroid/text/method/LinkMovementMethod;->sInstance:Landroid/text/method/LinkMovementMethod;
-Landroid/text/method/MetaKeyKeyListener;->startSelecting(Landroid/view/View;Landroid/text/Spannable;)V
-Landroid/text/method/MetaKeyKeyListener;->stopSelecting(Landroid/view/View;Landroid/text/Spannable;)V
-Landroid/text/method/PasswordTransformationMethod;->DOT:C
-Landroid/text/method/PasswordTransformationMethod;->sInstance:Landroid/text/method/PasswordTransformationMethod;
-Landroid/text/method/TransformationMethod2;->setLengthChangesAllowed(Z)V
-Landroid/text/method/WordIterator;-><init>(Ljava/util/Locale;)V
-Landroid/text/method/WordIterator;->following(I)I
-Landroid/text/method/WordIterator;->getBeginning(I)I
-Landroid/text/method/WordIterator;->getEnd(I)I
-Landroid/text/method/WordIterator;->getNextWordEndOnTwoWordBoundary(I)I
-Landroid/text/method/WordIterator;->getPrevWordBeginningOnTwoWordsBoundary(I)I
-Landroid/text/method/WordIterator;->getPunctuationBeginning(I)I
-Landroid/text/method/WordIterator;->getPunctuationEnd(I)I
-Landroid/text/method/WordIterator;->isAfterPunctuation(I)Z
-Landroid/text/method/WordIterator;->isBoundary(I)Z
-Landroid/text/method/WordIterator;->isOnPunctuation(I)Z
-Landroid/text/method/WordIterator;->nextBoundary(I)I
-Landroid/text/method/WordIterator;->preceding(I)I
-Landroid/text/method/WordIterator;->prevBoundary(I)I
-Landroid/text/method/WordIterator;->setCharSequence(Ljava/lang/CharSequence;II)V
-Landroid/text/Selection;->moveToFollowing(Landroid/text/Spannable;Landroid/text/Selection$PositionIterator;Z)Z
-Landroid/text/Selection;->moveToPreceding(Landroid/text/Spannable;Landroid/text/Selection$PositionIterator;Z)Z
-Landroid/text/SpannableStringBuilder;->getSpans(IILjava/lang/Class;Z)[Ljava/lang/Object;
-Landroid/text/SpannableStringBuilder;->mGapLength:I
-Landroid/text/SpannableStringBuilder;->mGapStart:I
-Landroid/text/SpannableStringBuilder;->mSpanCount:I
-Landroid/text/SpannableStringBuilder;->mSpanEnds:[I
-Landroid/text/SpannableStringBuilder;->mSpanFlags:[I
-Landroid/text/SpannableStringBuilder;->mSpans:[Ljava/lang/Object;
-Landroid/text/SpannableStringBuilder;->mSpanStarts:[I
-Landroid/text/SpannableStringBuilder;->mText:[C
-Landroid/text/SpannableStringBuilder;->sendToSpanWatchers(III)V
-Landroid/text/SpannableStringBuilder;->substring(II)Ljava/lang/String;
-Landroid/text/SpannableStringInternal;-><init>(Ljava/lang/CharSequence;II)V
-Landroid/text/SpannableStringInternal;->charAt(I)C
-Landroid/text/SpannableStringInternal;->checkRange(Ljava/lang/String;II)V
-Landroid/text/SpannableStringInternal;->COLUMNS:I
-Landroid/text/SpannableStringInternal;->copySpans(Landroid/text/SpannableStringInternal;II)V
-Landroid/text/SpannableStringInternal;->copySpans(Landroid/text/Spanned;II)V
-Landroid/text/SpannableStringInternal;->EMPTY:[Ljava/lang/Object;
-Landroid/text/SpannableStringInternal;->END:I
-Landroid/text/SpannableStringInternal;->FLAGS:I
-Landroid/text/SpannableStringInternal;->getChars(II[CI)V
-Landroid/text/SpannableStringInternal;->getSpanEnd(Ljava/lang/Object;)I
-Landroid/text/SpannableStringInternal;->getSpanFlags(Ljava/lang/Object;)I
-Landroid/text/SpannableStringInternal;->getSpans(IILjava/lang/Class;)[Ljava/lang/Object;
-Landroid/text/SpannableStringInternal;->getSpanStart(Ljava/lang/Object;)I
-Landroid/text/SpannableStringInternal;->isIndexFollowsNextLine(I)Z
-Landroid/text/SpannableStringInternal;->isOutOfCopyRange(IIII)Z
-Landroid/text/SpannableStringInternal;->length()I
-Landroid/text/SpannableStringInternal;->mSpanCount:I
-Landroid/text/SpannableStringInternal;->mSpanData:[I
-Landroid/text/SpannableStringInternal;->mSpans:[Ljava/lang/Object;
-Landroid/text/SpannableStringInternal;->mText:Ljava/lang/String;
-Landroid/text/SpannableStringInternal;->nextSpanTransition(IILjava/lang/Class;)I
-Landroid/text/SpannableStringInternal;->region(II)Ljava/lang/String;
-Landroid/text/SpannableStringInternal;->removeSpan(Ljava/lang/Object;)V
-Landroid/text/SpannableStringInternal;->sendSpanAdded(Ljava/lang/Object;II)V
-Landroid/text/SpannableStringInternal;->sendSpanChanged(Ljava/lang/Object;IIII)V
-Landroid/text/SpannableStringInternal;->sendSpanRemoved(Ljava/lang/Object;II)V
-Landroid/text/SpannableStringInternal;->setSpan(Ljava/lang/Object;III)V
-Landroid/text/SpannableStringInternal;->setSpan(Ljava/lang/Object;IIIZ)V
-Landroid/text/SpannableStringInternal;->START:I
-Landroid/text/SpanSet;->spans:[Ljava/lang/Object;
-Landroid/text/StaticLayout$LineBreaks;->ascents:[F
-Landroid/text/StaticLayout$LineBreaks;->breaks:[I
-Landroid/text/StaticLayout$LineBreaks;->descents:[F
-Landroid/text/StaticLayout$LineBreaks;->flags:[I
-Landroid/text/StaticLayout$LineBreaks;->widths:[F
-Landroid/text/StaticLayout;-><init>(Ljava/lang/CharSequence;IILandroid/text/TextPaint;ILandroid/text/Layout$Alignment;Landroid/text/TextDirectionHeuristic;FFZLandroid/text/TextUtils$TruncateAt;II)V
-Landroid/text/StaticLayout;->ELLIPSIS_START:I
-Landroid/text/StaticLayout;->getHeight(Z)I
-Landroid/text/StaticLayout;->mColumns:I
-Landroid/text/StaticLayout;->mLineCount:I
-Landroid/text/StaticLayout;->mLineDirections:[Landroid/text/Layout$Directions;
-Landroid/text/StaticLayout;->mLines:[I
-Landroid/text/StaticLayout;->mMaximumVisibleLineCount:I
-Landroid/text/style/BulletSpan;->mColor:I
-Landroid/text/style/BulletSpan;->mGapWidth:I
-Landroid/text/style/BulletSpan;->mWantColor:Z
-Landroid/text/style/DynamicDrawableSpan;->mDrawableRef:Ljava/lang/ref/WeakReference;
-Landroid/text/style/EasyEditSpan;->getPendingIntent()Landroid/app/PendingIntent;
-Landroid/text/style/EasyEditSpan;->isDeleteEnabled()Z
-Landroid/text/style/EasyEditSpan;->setDeleteEnabled(Z)V
-Landroid/text/style/ImageSpan;->mDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/text/style/SpellCheckSpan;-><init>()V
-Landroid/text/style/SpellCheckSpan;-><init>(Landroid/os/Parcel;)V
-Landroid/text/style/SpellCheckSpan;->isSpellCheckInProgress()Z
-Landroid/text/style/SpellCheckSpan;->setSpellCheckInProgress(Z)V
-Landroid/text/style/SuggestionRangeSpan;-><init>()V
-Landroid/text/style/SuggestionRangeSpan;-><init>(Landroid/os/Parcel;)V
-Landroid/text/style/SuggestionRangeSpan;->setBackgroundColor(I)V
-Landroid/text/style/SuggestionSpan;->getNotificationTargetClassName()Ljava/lang/String;
-Landroid/text/style/SuggestionSpan;->getUnderlineColor()I
-Landroid/text/style/SuggestionSpan;->mEasyCorrectUnderlineColor:I
-Landroid/text/style/SuggestionSpan;->mEasyCorrectUnderlineThickness:F
-Landroid/text/style/SuggestionSpan;->notifySelection(Landroid/content/Context;Ljava/lang/String;I)V
-Landroid/text/TextLine;->mCharacterStyleSpanSet:Landroid/text/SpanSet;
-Landroid/text/TextLine;->mMetricAffectingSpanSpanSet:Landroid/text/SpanSet;
-Landroid/text/TextLine;->mReplacementSpanSpanSet:Landroid/text/SpanSet;
-Landroid/text/TextLine;->mSpanned:Landroid/text/Spanned;
-Landroid/text/TextLine;->mText:Ljava/lang/CharSequence;
-Landroid/text/TextLine;->obtain()Landroid/text/TextLine;
-Landroid/text/TextLine;->sCached:[Landroid/text/TextLine;
-Landroid/text/TextPaint;->setUnderlineText(IF)V
-Landroid/text/TextPaint;->underlineColor:I
-Landroid/text/TextPaint;->underlineThickness:F
-Landroid/text/TextUtils$TruncateAt;->END_SMALL:Landroid/text/TextUtils$TruncateAt;
-Landroid/text/TextUtils;->packRangeInLong(II)J
-Landroid/text/TextUtils;->unpackRangeEndFromLong(J)I
-Landroid/text/TextUtils;->unpackRangeStartFromLong(J)I
-Landroid/text/util/Linkify;->gatherTelLinks(Ljava/util/ArrayList;Landroid/text/Spannable;Landroid/content/Context;)V
 Landroid/transition/ChangeBounds;->BOTTOM_RIGHT_ONLY_PROPERTY:Landroid/util/Property;
 Landroid/transition/ChangeBounds;->POSITION_PROPERTY:Landroid/util/Property;
 Landroid/transition/Scene;->mEnterAction:Ljava/lang/Runnable;
@@ -5739,128 +1589,7 @@
 Landroid/transition/TransitionManager;->getRunningTransitions()Landroid/util/ArrayMap;
 Landroid/transition/TransitionManager;->sPendingTransitions:Ljava/util/ArrayList;
 Landroid/transition/TransitionManager;->sRunningTransitions:Ljava/lang/ThreadLocal;
-Landroid/util/ArrayMap;->allocArrays(I)V
-Landroid/util/ArrayMap;->append(Ljava/lang/Object;Ljava/lang/Object;)V
-Landroid/util/ArrayMap;->CACHE_SIZE:I
-Landroid/util/ArrayMap;->EMPTY:Landroid/util/ArrayMap;
-Landroid/util/ArrayMap;->EMPTY_IMMUTABLE_INTS:[I
-Landroid/util/ArrayMap;->freeArrays([I[Ljava/lang/Object;I)V
-Landroid/util/ArrayMap;->indexOf(Ljava/lang/Object;I)I
-Landroid/util/ArrayMap;->indexOfNull()I
-Landroid/util/ArrayMap;->indexOfValue(Ljava/lang/Object;)I
-Landroid/util/ArrayMap;->mArray:[Ljava/lang/Object;
-Landroid/util/ArrayMap;->mBaseCache:[Ljava/lang/Object;
-Landroid/util/ArrayMap;->mBaseCacheSize:I
-Landroid/util/ArrayMap;->mHashes:[I
-Landroid/util/ArrayMap;->mSize:I
-Landroid/util/ArrayMap;->mTwiceBaseCache:[Ljava/lang/Object;
-Landroid/util/ArrayMap;->mTwiceBaseCacheSize:I
-Landroid/util/ArraySet;-><init>(Ljava/util/Collection;)V
-Landroid/util/ArraySet;->allocArrays(I)V
-Landroid/util/ArraySet;->freeArrays([I[Ljava/lang/Object;I)V
-Landroid/util/ArraySet;->indexOf(Ljava/lang/Object;I)I
-Landroid/util/ArraySet;->indexOfNull()I
-Landroid/util/ArraySet;->mArray:[Ljava/lang/Object;
-Landroid/util/ArraySet;->mHashes:[I
-Landroid/util/ArraySet;->mSize:I
-Landroid/util/Base64;-><init>()V
-Landroid/util/Base64OutputStream;-><init>(Ljava/io/OutputStream;IZ)V
-Landroid/util/DebugUtils;->buildShortClassTag(Ljava/lang/Object;Ljava/lang/StringBuilder;)V
-Landroid/util/DisplayMetrics;->DENSITY_DEVICE:I
-Landroid/util/DisplayMetrics;->noncompatDensityDpi:I
-Landroid/util/DisplayMetrics;->noncompatHeightPixels:I
-Landroid/util/DisplayMetrics;->noncompatWidthPixels:I
-Landroid/util/EventLog$Event;-><init>([B)V
-Landroid/util/IconDrawableFactory;->getBadgedIcon(Landroid/content/pm/ApplicationInfo;)Landroid/graphics/drawable/Drawable;
-Landroid/util/LocalLog;->dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V
-Landroid/util/Log;->println_native(IILjava/lang/String;Ljava/lang/String;)I
-Landroid/util/Log;->wtf(ILjava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;ZZ)I
-Landroid/util/LogWriter;-><init>(ILjava/lang/String;)V
-Landroid/util/LongSparseLongArray;->mKeys:[J
-Landroid/util/LongSparseLongArray;->mSize:I
-Landroid/util/LongSparseLongArray;->mValues:[J
-Landroid/util/LruCache;->map:Ljava/util/LinkedHashMap;
-Landroid/util/MathUtils;->abs(F)F
-Landroid/util/MathUtils;->constrain(FFF)F
-Landroid/util/MathUtils;->constrain(III)I
-Landroid/util/MathUtils;->lerp(FFF)F
-Landroid/util/MathUtils;->max(II)F
-Landroid/util/NtpTrustedTime;->currentTimeMillis()J
-Landroid/util/NtpTrustedTime;->forceRefresh()Z
-Landroid/util/NtpTrustedTime;->getCachedNtpTime()J
-Landroid/util/NtpTrustedTime;->getCachedNtpTimeReference()J
-Landroid/util/NtpTrustedTime;->getInstance(Landroid/content/Context;)Landroid/util/NtpTrustedTime;
-Landroid/util/NtpTrustedTime;->hasCache()Z
-Landroid/util/PathParser;->createPathFromPathData(Ljava/lang/String;)Landroid/graphics/Path;
-Landroid/util/Pools$Pool;->acquire()Ljava/lang/Object;
-Landroid/util/Pools$Pool;->release(Ljava/lang/Object;)Z
-Landroid/util/Pools$SimplePool;-><init>(I)V
-Landroid/util/Pools$SimplePool;->acquire()Ljava/lang/Object;
-Landroid/util/Pools$SimplePool;->mPool:[Ljava/lang/Object;
-Landroid/util/Pools$SimplePool;->release(Ljava/lang/Object;)Z
-Landroid/util/Pools$SynchronizedPool;-><init>(I)V
-Landroid/util/Pools$SynchronizedPool;->acquire()Ljava/lang/Object;
-Landroid/util/Pools$SynchronizedPool;->release(Ljava/lang/Object;)Z
-Landroid/util/Rational;->mDenominator:I
-Landroid/util/Rational;->mNumerator:I
 Landroid/util/Singleton;-><init>()V
-Landroid/util/Singleton;->get()Ljava/lang/Object;
-Landroid/util/Singleton;->mInstance:Ljava/lang/Object;
-Landroid/util/Slog;->d(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/Slog;->d(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/util/Slog;->i(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/Slog;->v(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/Slog;->w(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/Slog;->w(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/util/Slog;->wtf(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/util/Slog;->wtfStack(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/SparseArray;->mKeys:[I
-Landroid/util/SparseArray;->mSize:I
-Landroid/util/SparseArray;->mValues:[Ljava/lang/Object;
-Landroid/util/SparseBooleanArray;->mKeys:[I
-Landroid/util/SparseBooleanArray;->mSize:I
-Landroid/util/SparseBooleanArray;->mValues:[Z
-Landroid/util/SparseIntArray;->mKeys:[I
-Landroid/util/SparseIntArray;->mSize:I
-Landroid/util/SparseIntArray;->mValues:[I
-Landroid/util/TimeUtils;->formatDuration(JLjava/io/PrintWriter;)V
-Landroid/util/TimeUtils;->formatDuration(JLjava/io/PrintWriter;I)V
-Landroid/util/TimeUtils;->logTimeOfDay(J)Ljava/lang/String;
-Landroid/util/TrustedTime;->currentTimeMillis()J
-Landroid/util/TrustedTime;->forceRefresh()Z
-Landroid/util/TrustedTime;->getCacheAge()J
-Landroid/util/TrustedTime;->hasCache()Z
-Landroid/view/accessibility/AccessibilityEvent;->mAction:I
-Landroid/view/accessibility/AccessibilityEvent;->mEventType:I
-Landroid/view/accessibility/AccessibilityInteractionClient;->clearCache()V
-Landroid/view/accessibility/AccessibilityInteractionClient;->getInstance()Landroid/view/accessibility/AccessibilityInteractionClient;
-Landroid/view/accessibility/AccessibilityInteractionClient;->setSameThreadMessage(Landroid/os/Message;)V
-Landroid/view/accessibility/AccessibilityManager;->DALTONIZER_SIMULATE_MONOCHROMACY:I
-Landroid/view/accessibility/AccessibilityManager;->getInstance(Landroid/content/Context;)Landroid/view/accessibility/AccessibilityManager;
-Landroid/view/accessibility/AccessibilityManager;->isHighTextContrastEnabled()Z
-Landroid/view/accessibility/AccessibilityManager;->mAccessibilityStateChangeListeners:Landroid/util/ArrayMap;
-Landroid/view/accessibility/AccessibilityManager;->mHandler:Landroid/os/Handler;
-Landroid/view/accessibility/AccessibilityManager;->mIsEnabled:Z
-Landroid/view/accessibility/AccessibilityManager;->mIsHighTextContrastEnabled:Z
-Landroid/view/accessibility/AccessibilityManager;->mLock:Ljava/lang/Object;
-Landroid/view/accessibility/AccessibilityManager;->mService:Landroid/view/accessibility/IAccessibilityManager;
-Landroid/view/accessibility/AccessibilityManager;->mUserId:I
-Landroid/view/accessibility/AccessibilityManager;->setStateLocked(I)V
-Landroid/view/accessibility/AccessibilityManager;->sInstance:Landroid/view/accessibility/AccessibilityManager;
-Landroid/view/accessibility/AccessibilityManager;->sInstanceSync:Ljava/lang/Object;
-Landroid/view/accessibility/AccessibilityNodeInfo;->getAccessibilityViewId(J)I
-Landroid/view/accessibility/AccessibilityNodeInfo;->getSourceNodeId()J
-Landroid/view/accessibility/AccessibilityNodeInfo;->getVirtualDescendantId(J)I
-Landroid/view/accessibility/AccessibilityNodeInfo;->isSealed()Z
-Landroid/view/accessibility/AccessibilityNodeInfo;->mChildNodeIds:Landroid/util/LongArray;
-Landroid/view/accessibility/AccessibilityNodeInfo;->mSealed:Z
-Landroid/view/accessibility/AccessibilityNodeInfo;->mSourceNodeId:J
-Landroid/view/accessibility/AccessibilityNodeInfo;->refresh(Landroid/os/Bundle;Z)Z
-Landroid/view/accessibility/AccessibilityNodeInfo;->setSealed(Z)V
-Landroid/view/accessibility/AccessibilityRecord;->getSourceNodeId()J
-Landroid/view/accessibility/AccessibilityRecord;->mSealed:Z
-Landroid/view/accessibility/AccessibilityRecord;->mSourceNodeId:J
-Landroid/view/accessibility/CaptioningManager$CaptionStyle;->PRESETS:[Landroid/view/accessibility/CaptioningManager$CaptionStyle;
 Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setFindAccessibilityNodeInfoResult(Landroid/view/accessibility/AccessibilityNodeInfo;I)V
 Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setFindAccessibilityNodeInfosResult(Ljava/util/List;I)V
 Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setPerformAccessibilityActionResult(ZI)V
@@ -5869,144 +1598,12 @@
 Landroid/view/accessibility/IAccessibilityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/accessibility/IAccessibilityManager;
 Landroid/view/accessibility/IAccessibilityManager;->getEnabledAccessibilityServiceList(II)Ljava/util/List;
 Landroid/view/AccessibilityIterators$AbstractTextSegmentIterator;-><init>()V
-Landroid/view/AccessibilityIterators$AbstractTextSegmentIterator;->mText:Ljava/lang/String;
-Landroid/view/ActionProvider;->reset()V
-Landroid/view/ActionProvider;->setSubUiVisibilityListener(Landroid/view/ActionProvider$SubUiVisibilityListener;)V
-Landroid/view/animation/Animation;->detach()V
-Landroid/view/animation/Animation;->getInvalidateRegion(IIIILandroid/graphics/RectF;Landroid/view/animation/Transformation;)V
-Landroid/view/animation/Animation;->initializeInvalidateRegion(IIII)V
-Landroid/view/animation/Animation;->mListener:Landroid/view/animation/Animation$AnimationListener;
-Landroid/view/animation/Animation;->mPreviousRegion:Landroid/graphics/RectF;
-Landroid/view/animation/Animation;->mPreviousTransformation:Landroid/view/animation/Transformation;
-Landroid/view/animation/Animation;->mRegion:Landroid/graphics/RectF;
-Landroid/view/animation/Animation;->mTransformation:Landroid/view/animation/Transformation;
-Landroid/view/animation/AnimationUtils;->createAnimationFromXml(Landroid/content/Context;Lorg/xmlpull/v1/XmlPullParser;Landroid/view/animation/AnimationSet;Landroid/util/AttributeSet;)Landroid/view/animation/Animation;
-Landroid/view/animation/Transformation;->printShortString(Ljava/io/PrintWriter;)V
-Landroid/view/animation/TranslateAnimation;->mFromXValue:F
-Landroid/view/animation/TranslateAnimation;->mFromYValue:F
-Landroid/view/animation/TranslateAnimation;->mToXValue:F
-Landroid/view/animation/TranslateAnimation;->mToYValue:F
-Landroid/view/animation/TranslateYAnimation;-><init>(IFIF)V
 Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/view/autofill/IAutoFillManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/autofill/IAutoFillManager;
-Landroid/view/Choreographer$CallbackQueue;->addCallbackLocked(JLjava/lang/Object;Ljava/lang/Object;)V
-Landroid/view/Choreographer$CallbackRecord;->run(J)V
-Landroid/view/Choreographer;->doFrame(JI)V
-Landroid/view/Choreographer;->getFrameTime()J
-Landroid/view/Choreographer;->getFrameTimeNanos()J
-Landroid/view/Choreographer;->mCallbackQueues:[Landroid/view/Choreographer$CallbackQueue;
-Landroid/view/Choreographer;->mDisplayEventReceiver:Landroid/view/Choreographer$FrameDisplayEventReceiver;
-Landroid/view/Choreographer;->mFrameIntervalNanos:J
-Landroid/view/Choreographer;->mLastFrameTimeNanos:J
-Landroid/view/Choreographer;->mLock:Ljava/lang/Object;
-Landroid/view/Choreographer;->scheduleVsyncLocked()V
-Landroid/view/Choreographer;->USE_VSYNC:Z
-Landroid/view/ContextThemeWrapper;->getThemeResId()I
-Landroid/view/ContextThemeWrapper;->initializeTheme()V
-Landroid/view/ContextThemeWrapper;->mInflater:Landroid/view/LayoutInflater;
-Landroid/view/ContextThemeWrapper;->mResources:Landroid/content/res/Resources;
-Landroid/view/ContextThemeWrapper;->mTheme:Landroid/content/res/Resources$Theme;
-Landroid/view/ContextThemeWrapper;->mThemeResource:I
-Landroid/view/Display$HdrCapabilities;-><init>([IFFF)V
-Landroid/view/Display$Mode;-><init>(IIIF)V
-Landroid/view/Display;->getAddress()Ljava/lang/String;
-Landroid/view/Display;->getDisplayAdjustments()Landroid/view/DisplayAdjustments;
-Landroid/view/Display;->getDisplayInfo(Landroid/view/DisplayInfo;)Z
-Landroid/view/Display;->getMaximumSizeDimension()I
-Landroid/view/Display;->getOwnerPackageName()Ljava/lang/String;
-Landroid/view/Display;->getType()I
-Landroid/view/Display;->mDisplayInfo:Landroid/view/DisplayInfo;
-Landroid/view/Display;->TYPE_HDMI:I
-Landroid/view/Display;->TYPE_UNKNOWN:I
-Landroid/view/Display;->TYPE_VIRTUAL:I
-Landroid/view/Display;->TYPE_WIFI:I
-Landroid/view/DisplayAdjustments;-><init>()V
-Landroid/view/DisplayAdjustments;->getConfiguration()Landroid/content/res/Configuration;
-Landroid/view/DisplayAdjustments;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
-Landroid/view/DisplayEventReceiver;-><init>(Landroid/os/Looper;)V
-Landroid/view/DisplayEventReceiver;->dispatchHotplug(JIZ)V
-Landroid/view/DisplayEventReceiver;->dispatchVsync(JII)V
-Landroid/view/DisplayEventReceiver;->mReceiverPtr:J
-Landroid/view/DisplayEventReceiver;->onHotplug(JIZ)V
-Landroid/view/DisplayEventReceiver;->onVsync(JII)V
-Landroid/view/DisplayEventReceiver;->scheduleVsync()V
-Landroid/view/DisplayInfo;-><init>()V
-Landroid/view/DisplayInfo;->displayCutout:Landroid/view/DisplayCutout;
-Landroid/view/DisplayInfo;->logicalHeight:I
-Landroid/view/DisplayInfo;->logicalWidth:I
-Landroid/view/DisplayInfo;->rotation:I
-Landroid/view/DisplayListCanvas;->callDrawGLFunction2(J)V
-Landroid/view/DisplayListCanvas;->drawCircle(Landroid/graphics/CanvasProperty;Landroid/graphics/CanvasProperty;Landroid/graphics/CanvasProperty;Landroid/graphics/CanvasProperty;)V
-Landroid/view/DisplayListCanvas;->drawGLFunctor2(JLjava/lang/Runnable;)V
-Landroid/view/DragEvent;->mClipData:Landroid/content/ClipData;
-Landroid/view/DragEvent;->mClipDescription:Landroid/content/ClipDescription;
-Landroid/view/DragEvent;->obtain(Landroid/view/DragEvent;)Landroid/view/DragEvent;
-Landroid/view/FrameMetrics;->mTimingData:[J
-Landroid/view/FrameMetricsObserver;->mFrameMetrics:Landroid/view/FrameMetrics;
-Landroid/view/FrameMetricsObserver;->mMessageQueue:Landroid/os/MessageQueue;
-Landroid/view/FrameMetricsObserver;->notifyDataAvailable(I)V
-Landroid/view/GestureDetector;->LONGPRESS_TIMEOUT:I
-Landroid/view/GestureDetector;->mAlwaysInTapRegion:Z
-Landroid/view/GestureDetector;->mListener:Landroid/view/GestureDetector$OnGestureListener;
-Landroid/view/GestureDetector;->mMinimumFlingVelocity:I
-Landroid/view/GestureDetector;->mTouchSlopSquare:I
-Landroid/view/GhostView;->addGhost(Landroid/view/View;Landroid/view/ViewGroup;)Landroid/view/GhostView;
-Landroid/view/GhostView;->addGhost(Landroid/view/View;Landroid/view/ViewGroup;Landroid/graphics/Matrix;)Landroid/view/GhostView;
-Landroid/view/GhostView;->removeGhost(Landroid/view/View;)V
 Landroid/view/IApplicationToken$Stub;-><init>()V
 Landroid/view/IDockedStackListener$Stub;-><init>()V
 Landroid/view/IGraphicsStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/view/IGraphicsStats$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IGraphicsStats;
-Landroid/view/InputChannel;-><init>()V
-Landroid/view/InputChannel;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/view/InputChannel;->mPtr:J
-Landroid/view/InputDevice;-><init>(IIILjava/lang/String;IILjava/lang/String;ZIILandroid/view/KeyCharacterMap;ZZZ)V
-Landroid/view/InputDevice;->addMotionRange(IIFFFFF)V
-Landroid/view/InputDevice;->isExternal()Z
-Landroid/view/InputDevice;->mIsExternal:Z
-Landroid/view/InputEvent;->getSequenceNumber()I
-Landroid/view/InputEventConsistencyVerifier;-><init>(Ljava/lang/Object;I)V
-Landroid/view/InputEventConsistencyVerifier;->isInstrumentationEnabled()Z
-Landroid/view/InputEventConsistencyVerifier;->onTouchEvent(Landroid/view/MotionEvent;I)V
-Landroid/view/InputEventConsistencyVerifier;->onUnhandledEvent(Landroid/view/InputEvent;I)V
-Landroid/view/InputEventReceiver;->dispatchBatchedInputEventPending()V
-Landroid/view/InputEventReceiver;->dispatchInputEvent(ILandroid/view/InputEvent;)V
-Landroid/view/InputEventSender;->dispatchInputEventFinished(IZ)V
-Landroid/view/InputFilter;-><init>(Landroid/os/Looper;)V
-Landroid/view/InputFilter;->onInputEvent(Landroid/view/InputEvent;I)V
-Landroid/view/inputmethod/InputMethodInfo;->isDefault(Landroid/content/Context;)Z
-Landroid/view/inputmethod/InputMethodInfo;->mSubtypes:Landroid/view/inputmethod/InputMethodSubtypeArray;
-Landroid/view/inputmethod/InputMethodManager;->checkFocus()V
-Landroid/view/inputmethod/InputMethodManager;->closeCurrentInput()V
-Landroid/view/inputmethod/InputMethodManager;->finishInputLocked()V
-Landroid/view/inputmethod/InputMethodManager;->focusIn(Landroid/view/View;)V
-Landroid/view/inputmethod/InputMethodManager;->focusOut(Landroid/view/View;)V
-Landroid/view/inputmethod/InputMethodManager;->getClient()Lcom/android/internal/view/IInputMethodClient;
-Landroid/view/inputmethod/InputMethodManager;->getInputContext()Lcom/android/internal/view/IInputContext;
-Landroid/view/inputmethod/InputMethodManager;->getInputMethodWindowVisibleHeight()I
-Landroid/view/inputmethod/InputMethodManager;->getInstance()Landroid/view/inputmethod/InputMethodManager;
-Landroid/view/inputmethod/InputMethodManager;->isCursorAnchorInfoEnabled()Z
-Landroid/view/inputmethod/InputMethodManager;->mCurId:Ljava/lang/String;
-Landroid/view/inputmethod/InputMethodManager;->mCurMethod:Lcom/android/internal/view/IInputMethodSession;
-Landroid/view/inputmethod/InputMethodManager;->mCurRootView:Landroid/view/View;
-Landroid/view/inputmethod/InputMethodManager;->mCursorRect:Landroid/graphics/Rect;
-Landroid/view/inputmethod/InputMethodManager;->mH:Landroid/view/inputmethod/InputMethodManager$H;
-Landroid/view/inputmethod/InputMethodManager;->mNextServedView:Landroid/view/View;
-Landroid/view/inputmethod/InputMethodManager;->mServedInputConnectionWrapper:Landroid/view/inputmethod/InputMethodManager$ControlledInputConnectionWrapper;
-Landroid/view/inputmethod/InputMethodManager;->mServedView:Landroid/view/View;
-Landroid/view/inputmethod/InputMethodManager;->mService:Lcom/android/internal/view/IInputMethodManager;
-Landroid/view/inputmethod/InputMethodManager;->mTmpCursorRect:Landroid/graphics/Rect;
-Landroid/view/inputmethod/InputMethodManager;->notifySuggestionPicked(Landroid/text/style/SuggestionSpan;Ljava/lang/String;I)V
-Landroid/view/inputmethod/InputMethodManager;->notifyUserAction()V
-Landroid/view/inputmethod/InputMethodManager;->onPreWindowFocus(Landroid/view/View;Z)V
-Landroid/view/inputmethod/InputMethodManager;->peekInstance()Landroid/view/inputmethod/InputMethodManager;
-Landroid/view/inputmethod/InputMethodManager;->registerSuggestionSpansForNotification([Landroid/text/style/SuggestionSpan;)V
-Landroid/view/inputmethod/InputMethodManager;->setUpdateCursorAnchorInfoMode(I)V
-Landroid/view/inputmethod/InputMethodManager;->showSoftInputUnchecked(ILandroid/os/ResultReceiver;)V
-Landroid/view/inputmethod/InputMethodManager;->sInstance:Landroid/view/inputmethod/InputMethodManager;
-Landroid/view/inputmethod/InputMethodManager;->windowDismissed(Landroid/os/IBinder;)V
-Landroid/view/inputmethod/InputMethodSubtypeArray;-><init>(Ljava/util/List;)V
-Landroid/view/InputQueue;->finishInputEvent(JZ)V
 Landroid/view/IOnKeyguardExitResult;->onKeyguardExitResult(Z)V
 Landroid/view/IRecentsAnimationController;->setAnimationTargetsBehindSystemBars(Z)V
 Landroid/view/IRotationWatcher$Stub;-><init>()V
@@ -6063,1281 +1660,19 @@
 Landroid/view/IWindowSession;->setTransparentRegion(Landroid/view/IWindow;Landroid/graphics/Region;)V
 Landroid/view/IWindowSession;->wallpaperCommandComplete(Landroid/os/IBinder;Landroid/os/Bundle;)V
 Landroid/view/IWindowSession;->wallpaperOffsetsComplete(Landroid/os/IBinder;)V
-Landroid/view/KeyCharacterMap$FallbackAction;->keyCode:I
-Landroid/view/KeyCharacterMap$FallbackAction;->metaState:I
-Landroid/view/KeyCharacterMap;-><init>(J)V
-Landroid/view/KeyEvent;->isConfirmKey(I)Z
-Landroid/view/KeyEvent;->isDown()Z
-Landroid/view/KeyEvent;->mAction:I
-Landroid/view/KeyEvent;->mCharacters:Ljava/lang/String;
-Landroid/view/KeyEvent;->mDeviceId:I
-Landroid/view/KeyEvent;->mDownTime:J
-Landroid/view/KeyEvent;->META_ALL_MASK:I
-Landroid/view/KeyEvent;->META_ALT_LOCKED:I
-Landroid/view/KeyEvent;->META_CAP_LOCKED:I
-Landroid/view/KeyEvent;->META_INVALID_MODIFIER_MASK:I
-Landroid/view/KeyEvent;->META_LOCK_MASK:I
-Landroid/view/KeyEvent;->META_MODIFIER_MASK:I
-Landroid/view/KeyEvent;->META_SELECTING:I
-Landroid/view/KeyEvent;->META_SYMBOLIC_NAMES:[Ljava/lang/String;
-Landroid/view/KeyEvent;->META_SYM_LOCKED:I
-Landroid/view/KeyEvent;->META_SYNTHETIC_MASK:I
-Landroid/view/KeyEvent;->mEventTime:J
-Landroid/view/KeyEvent;->mFlags:I
-Landroid/view/KeyEvent;->mKeyCode:I
-Landroid/view/KeyEvent;->mMetaState:I
-Landroid/view/KeyEvent;->mRepeatCount:I
-Landroid/view/KeyEvent;->mScanCode:I
-Landroid/view/KeyEvent;->mSource:I
-Landroid/view/KeyEvent;->obtain(JJIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;
-Landroid/view/KeyEvent;->recycle()V
-Landroid/view/LayoutInflater;->ATTRS_THEME:[I
-Landroid/view/LayoutInflater;->createViewFromTag(Landroid/view/View;Ljava/lang/String;Landroid/content/Context;Landroid/util/AttributeSet;)Landroid/view/View;
-Landroid/view/LayoutInflater;->createViewFromTag(Landroid/view/View;Ljava/lang/String;Landroid/content/Context;Landroid/util/AttributeSet;Z)Landroid/view/View;
-Landroid/view/LayoutInflater;->mConstructorArgs:[Ljava/lang/Object;
-Landroid/view/LayoutInflater;->mConstructorSignature:[Ljava/lang/Class;
-Landroid/view/LayoutInflater;->mContext:Landroid/content/Context;
-Landroid/view/LayoutInflater;->mFactory2:Landroid/view/LayoutInflater$Factory2;
-Landroid/view/LayoutInflater;->mFactory:Landroid/view/LayoutInflater$Factory;
-Landroid/view/LayoutInflater;->mFactorySet:Z
-Landroid/view/LayoutInflater;->mPrivateFactory:Landroid/view/LayoutInflater$Factory2;
-Landroid/view/LayoutInflater;->parseInclude(Lorg/xmlpull/v1/XmlPullParser;Landroid/content/Context;Landroid/view/View;Landroid/util/AttributeSet;)V
-Landroid/view/LayoutInflater;->sConstructorMap:Ljava/util/HashMap;
-Landroid/view/LayoutInflater;->setPrivateFactory(Landroid/view/LayoutInflater$Factory2;)V
-Landroid/view/MotionEvent$PointerCoords;->createArray(I)[Landroid/view/MotionEvent$PointerCoords;
-Landroid/view/MotionEvent$PointerCoords;->mPackedAxisBits:J
-Landroid/view/MotionEvent$PointerCoords;->mPackedAxisValues:[F
-Landroid/view/MotionEvent$PointerProperties;->createArray(I)[Landroid/view/MotionEvent$PointerProperties;
-Landroid/view/MotionEvent;->addBatch(Landroid/view/MotionEvent;)Z
-Landroid/view/MotionEvent;->copy()Landroid/view/MotionEvent;
-Landroid/view/MotionEvent;->getEventTimeNano()J
-Landroid/view/MotionEvent;->getPointerIdBits()I
-Landroid/view/MotionEvent;->HISTORY_CURRENT:I
-Landroid/view/MotionEvent;->mNativePtr:J
-Landroid/view/MotionEvent;->nativeGetRawAxisValue(JIII)F
-Landroid/view/MotionEvent;->obtain()Landroid/view/MotionEvent;
-Landroid/view/MotionEvent;->scale(F)V
-Landroid/view/MotionEvent;->setDownTime(J)V
-Landroid/view/MotionEvent;->split(I)Landroid/view/MotionEvent;
-Landroid/view/NotificationHeaderView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Landroid/view/PointerIcon;->load(Landroid/content/Context;)Landroid/view/PointerIcon;
-Landroid/view/PointerIcon;->mBitmap:Landroid/graphics/Bitmap;
-Landroid/view/PointerIcon;->mBitmapFrames:[Landroid/graphics/Bitmap;
-Landroid/view/PointerIcon;->mDurationPerFrame:I
-Landroid/view/PointerIcon;->mHotSpotX:F
-Landroid/view/PointerIcon;->mHotSpotY:F
-Landroid/view/PointerIcon;->mType:I
-Landroid/view/RemoteAnimationDefinition;->addRemoteAnimation(IILandroid/view/RemoteAnimationAdapter;)V
-Landroid/view/RemoteAnimationTarget;->clipRect:Landroid/graphics/Rect;
-Landroid/view/RemoteAnimationTarget;->contentInsets:Landroid/graphics/Rect;
-Landroid/view/RemoteAnimationTarget;->isNotInRecents:Z
-Landroid/view/RemoteAnimationTarget;->isTranslucent:Z
-Landroid/view/RemoteAnimationTarget;->leash:Landroid/view/SurfaceControl;
-Landroid/view/RemoteAnimationTarget;->mode:I
-Landroid/view/RemoteAnimationTarget;->position:Landroid/graphics/Point;
-Landroid/view/RemoteAnimationTarget;->prefixOrderIndex:I
-Landroid/view/RemoteAnimationTarget;->sourceContainerBounds:Landroid/graphics/Rect;
-Landroid/view/RemoteAnimationTarget;->taskId:I
-Landroid/view/RemoteAnimationTarget;->windowConfiguration:Landroid/app/WindowConfiguration;
-Landroid/view/RenderNode;->discardDisplayList()V
-Landroid/view/RenderNode;->offsetLeftAndRight(I)Z
-Landroid/view/RenderNode;->output()V
-Landroid/view/RenderNode;->setHasOverlappingRendering(Z)Z
-Landroid/view/RenderNode;->setProjectBackwards(Z)Z
-Landroid/view/RenderNodeAnimator;-><init>(IF)V
-Landroid/view/RenderNodeAnimator;-><init>(Landroid/graphics/CanvasProperty;F)V
-Landroid/view/RenderNodeAnimator;-><init>(Landroid/graphics/CanvasProperty;IF)V
-Landroid/view/RenderNodeAnimator;->callOnFinished(Landroid/view/RenderNodeAnimator;)V
-Landroid/view/RenderNodeAnimator;->mapViewPropertyToRenderProperty(I)I
-Landroid/view/RenderNodeAnimator;->setStartValue(F)V
-Landroid/view/RenderNodeAnimator;->setTarget(Landroid/view/View;)V
-Landroid/view/ScaleGestureDetector;->mListener:Landroid/view/ScaleGestureDetector$OnScaleGestureListener;
-Landroid/view/ScaleGestureDetector;->mMinSpan:I
-Landroid/view/ScaleGestureDetector;->mSpanSlop:I
-Landroid/view/Surface;-><init>()V
-Landroid/view/Surface;-><init>(J)V
-Landroid/view/Surface;->copyFrom(Landroid/view/SurfaceControl;)V
-Landroid/view/Surface;->destroy()V
-Landroid/view/Surface;->mLock:Ljava/lang/Object;
-Landroid/view/Surface;->mLockedObject:J
-Landroid/view/Surface;->mName:Ljava/lang/String;
-Landroid/view/Surface;->mNativeObject:J
-Landroid/view/Surface;->nativeRelease(J)V
-Landroid/view/Surface;->transferFrom(Landroid/view/Surface;)V
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;-><init>()V
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;->appVsyncOffsetNanos:J
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;->density:F
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;->height:I
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;->presentationDeadlineNanos:J
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;->refreshRate:F
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;->secure:Z
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;->width:I
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;->xDpi:F
-Landroid/view/SurfaceControl$PhysicalDisplayInfo;->yDpi:F
-Landroid/view/SurfaceControl;->closeTransaction()V
-Landroid/view/SurfaceControl;->createDisplay(Ljava/lang/String;Z)Landroid/os/IBinder;
-Landroid/view/SurfaceControl;->destroyDisplay(Landroid/os/IBinder;)V
-Landroid/view/SurfaceControl;->getBuiltInDisplay(I)Landroid/os/IBinder;
-Landroid/view/SurfaceControl;->getDisplayConfigs(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;
-Landroid/view/SurfaceControl;->HIDDEN:I
-Landroid/view/SurfaceControl;->hide()V
-Landroid/view/SurfaceControl;->openTransaction()V
-Landroid/view/SurfaceControl;->screenshot(Landroid/graphics/Rect;III)Landroid/graphics/Bitmap;
-Landroid/view/SurfaceControl;->screenshot(Landroid/graphics/Rect;IIIIZI)Landroid/graphics/Bitmap;
-Landroid/view/SurfaceControl;->screenshot(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V
-Landroid/view/SurfaceControl;->setDisplayLayerStack(Landroid/os/IBinder;I)V
-Landroid/view/SurfaceControl;->setDisplayProjection(Landroid/os/IBinder;ILandroid/graphics/Rect;Landroid/graphics/Rect;)V
-Landroid/view/SurfaceControl;->setDisplaySurface(Landroid/os/IBinder;Landroid/view/Surface;)V
-Landroid/view/SurfaceControl;->setLayer(I)V
-Landroid/view/SurfaceControl;->setPosition(FF)V
-Landroid/view/SurfaceControl;->show()V
-Landroid/view/SurfaceSession;-><init>()V
-Landroid/view/SurfaceSession;->kill()V
-Landroid/view/SurfaceSession;->mNativeClient:J
-Landroid/view/SurfaceView;->isFixedSize()Z
-Landroid/view/SurfaceView;->mCallbacks:Ljava/util/ArrayList;
-Landroid/view/SurfaceView;->mDrawingStopped:Z
-Landroid/view/SurfaceView;->mDrawListener:Landroid/view/ViewTreeObserver$OnPreDrawListener;
-Landroid/view/SurfaceView;->mFormat:I
-Landroid/view/SurfaceView;->mHaveFrame:Z
-Landroid/view/SurfaceView;->mIsCreating:Z
-Landroid/view/SurfaceView;->mLastLockTime:J
-Landroid/view/SurfaceView;->mRequestedFormat:I
-Landroid/view/SurfaceView;->mRequestedHeight:I
-Landroid/view/SurfaceView;->mRequestedWidth:I
-Landroid/view/SurfaceView;->mSurface:Landroid/view/Surface;
-Landroid/view/SurfaceView;->mSurfaceFrame:Landroid/graphics/Rect;
-Landroid/view/SurfaceView;->mSurfaceHolder:Landroid/view/SurfaceHolder;
-Landroid/view/SurfaceView;->mSurfaceLock:Ljava/util/concurrent/locks/ReentrantLock;
-Landroid/view/SurfaceView;->setFrame(IIII)Z
-Landroid/view/SurfaceView;->surfacePositionLost_uiRtSync(J)V
-Landroid/view/SurfaceView;->updateSurfacePosition_renderWorker(JIIII)V
-Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(III)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
-Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(IIILandroid/view/textclassifier/TextClassification;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
-Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(II)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
-Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(IILandroid/view/textclassifier/TextClassification;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
-Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(IILandroid/view/textclassifier/TextSelection;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
-Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionStarted(I)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;
-Landroid/view/textclassifier/logging/SmartSelectionEventTracker;-><init>(Landroid/content/Context;I)V
-Landroid/view/textclassifier/logging/SmartSelectionEventTracker;->logEvent(Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;)V
-Landroid/view/textclassifier/TextClassificationManager;->getTextClassifier(I)Landroid/view/textclassifier/TextClassifier;
-Landroid/view/textclassifier/TextClassifier;->classifyText(Ljava/lang/CharSequence;IILandroid/view/textclassifier/TextClassification$Options;)Landroid/view/textclassifier/TextClassification;
-Landroid/view/textclassifier/TextClassifier;->generateLinks(Ljava/lang/CharSequence;Landroid/view/textclassifier/TextLinks$Options;)Landroid/view/textclassifier/TextLinks;
-Landroid/view/textclassifier/TextClassifier;->suggestSelection(Ljava/lang/CharSequence;IILandroid/view/textclassifier/TextSelection$Options;)Landroid/view/textclassifier/TextSelection;
-Landroid/view/textclassifier/TextLinks$Options;-><init>()V
-Landroid/view/textservice/SpellCheckerSession;->mSpellCheckerSessionListener:Landroid/view/textservice/SpellCheckerSession$SpellCheckerSessionListener;
-Landroid/view/textservice/TextServicesManager;->getCurrentSpellChecker()Landroid/view/textservice/SpellCheckerInfo;
-Landroid/view/textservice/TextServicesManager;->getCurrentSpellCheckerSubtype(Z)Landroid/view/textservice/SpellCheckerSubtype;
-Landroid/view/textservice/TextServicesManager;->getEnabledSpellCheckers()[Landroid/view/textservice/SpellCheckerInfo;
-Landroid/view/textservice/TextServicesManager;->getInstance()Landroid/view/textservice/TextServicesManager;
-Landroid/view/textservice/TextServicesManager;->isSpellCheckerEnabled()Z
-Landroid/view/TextureView;->destroyHardwareLayer()V
-Landroid/view/TextureView;->destroyHardwareResources()V
-Landroid/view/TextureView;->mLayer:Landroid/view/TextureLayer;
-Landroid/view/TextureView;->mNativeWindow:J
-Landroid/view/TextureView;->mOpaque:Z
-Landroid/view/TextureView;->mSurface:Landroid/graphics/SurfaceTexture;
-Landroid/view/TextureView;->mUpdateListener:Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;
-Landroid/view/TextureView;->mUpdateSurface:Z
-Landroid/view/TextureView;->nCreateNativeWindow(Landroid/graphics/SurfaceTexture;)V
-Landroid/view/TextureView;->nDestroyNativeWindow()V
-Landroid/view/TextureView;->onDetachedFromWindowInternal()V
-Landroid/view/ThreadedRenderer;->addRenderNode(Landroid/view/RenderNode;Z)V
-Landroid/view/ThreadedRenderer;->drawRenderNode(Landroid/view/RenderNode;)V
-Landroid/view/ThreadedRenderer;->removeRenderNode(Landroid/view/RenderNode;)V
-Landroid/view/ThreadedRenderer;->setContentDrawBounds(IIII)V
-Landroid/view/ThreadedRenderer;->setupDiskCache(Ljava/io/File;)V
-Landroid/view/TouchDelegate;->mDelegateTargeted:Z
-Landroid/view/VelocityTracker$Estimator;->confidence:F
-Landroid/view/VelocityTracker$Estimator;->degree:I
-Landroid/view/VelocityTracker$Estimator;->xCoeff:[F
-Landroid/view/VelocityTracker$Estimator;->yCoeff:[F
-Landroid/view/VelocityTracker;->obtain(Ljava/lang/String;)Landroid/view/VelocityTracker;
-Landroid/view/View$AccessibilityDelegate;->createAccessibilityNodeInfo(Landroid/view/View;)Landroid/view/accessibility/AccessibilityNodeInfo;
 Landroid/view/View$AttachInfo$InvalidateInfo;-><init>()V
-Landroid/view/View$AttachInfo$InvalidateInfo;->bottom:I
-Landroid/view/View$AttachInfo$InvalidateInfo;->left:I
-Landroid/view/View$AttachInfo$InvalidateInfo;->right:I
-Landroid/view/View$AttachInfo$InvalidateInfo;->target:Landroid/view/View;
-Landroid/view/View$AttachInfo$InvalidateInfo;->top:I
-Landroid/view/View$AttachInfo;->mApplicationScale:F
-Landroid/view/View$AttachInfo;->mContentInsets:Landroid/graphics/Rect;
-Landroid/view/View$AttachInfo;->mDisplayState:I
-Landroid/view/View$AttachInfo;->mDrawingTime:J
-Landroid/view/View$AttachInfo;->mGivenInternalInsets:Landroid/view/ViewTreeObserver$InternalInsetsInfo;
-Landroid/view/View$AttachInfo;->mHandler:Landroid/os/Handler;
-Landroid/view/View$AttachInfo;->mHasWindowFocus:Z
-Landroid/view/View$AttachInfo;->mInTouchMode:Z
-Landroid/view/View$AttachInfo;->mKeepScreenOn:Z
-Landroid/view/View$AttachInfo;->mKeyDispatchState:Landroid/view/KeyEvent$DispatcherState;
-Landroid/view/View$AttachInfo;->mRecomputeGlobalAttributes:Z
-Landroid/view/View$AttachInfo;->mScalingRequired:Z
-Landroid/view/View$AttachInfo;->mScrollContainers:Ljava/util/ArrayList;
-Landroid/view/View$AttachInfo;->mSession:Landroid/view/IWindowSession;
-Landroid/view/View$AttachInfo;->mStableInsets:Landroid/graphics/Rect;
-Landroid/view/View$AttachInfo;->mTreeObserver:Landroid/view/ViewTreeObserver;
-Landroid/view/View$AttachInfo;->mViewScrollChanged:Z
-Landroid/view/View$AttachInfo;->mViewVisibilityChanged:Z
-Landroid/view/View$AttachInfo;->mVisibleInsets:Landroid/graphics/Rect;
-Landroid/view/View$AttachInfo;->mWindow:Landroid/view/IWindow;
-Landroid/view/View$DragShadowBuilder;->mView:Ljava/lang/ref/WeakReference;
 Landroid/view/View$ListenerInfo;-><init>()V
-Landroid/view/View$ListenerInfo;->mOnClickListener:Landroid/view/View$OnClickListener;
-Landroid/view/View$ListenerInfo;->mOnCreateContextMenuListener:Landroid/view/View$OnCreateContextMenuListener;
-Landroid/view/View$ListenerInfo;->mOnDragListener:Landroid/view/View$OnDragListener;
-Landroid/view/View$ListenerInfo;->mOnFocusChangeListener:Landroid/view/View$OnFocusChangeListener;
-Landroid/view/View$ListenerInfo;->mOnGenericMotionListener:Landroid/view/View$OnGenericMotionListener;
-Landroid/view/View$ListenerInfo;->mOnHoverListener:Landroid/view/View$OnHoverListener;
-Landroid/view/View$ListenerInfo;->mOnKeyListener:Landroid/view/View$OnKeyListener;
-Landroid/view/View$ListenerInfo;->mOnLongClickListener:Landroid/view/View$OnLongClickListener;
-Landroid/view/View$ListenerInfo;->mOnTouchListener:Landroid/view/View$OnTouchListener;
-Landroid/view/View$MeasureSpec;->makeSafeMeasureSpec(II)I
-Landroid/view/View$ScrollabilityCache;->host:Landroid/view/View;
-Landroid/view/View$ScrollabilityCache;->scrollBar:Landroid/widget/ScrollBarDrawable;
-Landroid/view/View$ScrollabilityCache;->state:I
-Landroid/view/View;-><init>()V
-Landroid/view/View;->applyDrawableToTransparentRegion(Landroid/graphics/drawable/Drawable;Landroid/graphics/Region;)V
-Landroid/view/View;->assignParent(Landroid/view/ViewParent;)V
-Landroid/view/View;->cancel(Landroid/view/View$SendViewScrolledAccessibilityEvent;)V
-Landroid/view/View;->clearAccessibilityFocus()V
-Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z
-Landroid/view/View;->computeOpaqueFlags()V
-Landroid/view/View;->createSnapshot(Landroid/view/ViewDebug$CanvasProvider;Z)Landroid/graphics/Bitmap;
-Landroid/view/View;->DBG:Z
-Landroid/view/View;->debug()V
-Landroid/view/View;->debug(I)V
-Landroid/view/View;->DEBUG_LAYOUT_PROPERTY:Ljava/lang/String;
-Landroid/view/View;->destroyHardwareResources()V
-Landroid/view/View;->dispatchAttachedToWindow(Landroid/view/View$AttachInfo;I)V
-Landroid/view/View;->dispatchDetachedFromWindow()V
-Landroid/view/View;->dispatchPointerEvent(Landroid/view/MotionEvent;)Z
-Landroid/view/View;->drawBackground(Landroid/graphics/Canvas;)V
-Landroid/view/View;->ensureTransformationInfo()V
-Landroid/view/View;->findViewByAccessibilityId(I)Landroid/view/View;
-Landroid/view/View;->fitsSystemWindows()Z
-Landroid/view/View;->gatherTransparentRegion(Landroid/graphics/Region;)Z
-Landroid/view/View;->getAccessibilityDelegate()Landroid/view/View$AccessibilityDelegate;
-Landroid/view/View;->getAccessibilityViewId()I
-Landroid/view/View;->getBoundsOnScreen(Landroid/graphics/Rect;)V
-Landroid/view/View;->getBoundsOnScreen(Landroid/graphics/Rect;Z)V
-Landroid/view/View;->getHorizontalScrollFactor()F
-Landroid/view/View;->getInverseMatrix()Landroid/graphics/Matrix;
-Landroid/view/View;->getIterableTextForAccessibility()Ljava/lang/CharSequence;
-Landroid/view/View;->getIteratorForGranularity(I)Landroid/view/AccessibilityIterators$TextSegmentIterator;
-Landroid/view/View;->getListenerInfo()Landroid/view/View$ListenerInfo;
-Landroid/view/View;->getLocationInSurface([I)V
-Landroid/view/View;->getLocationOnScreen()[I
-Landroid/view/View;->getRawTextAlignment()I
-Landroid/view/View;->getRawTextDirection()I
-Landroid/view/View;->getScrollCache()Landroid/view/View$ScrollabilityCache;
-Landroid/view/View;->getThreadedRenderer()Landroid/view/ThreadedRenderer;
-Landroid/view/View;->getTransitionAlpha()F
-Landroid/view/View;->getVerticalScrollFactor()F
-Landroid/view/View;->getViewRootImpl()Landroid/view/ViewRootImpl;
-Landroid/view/View;->getWindowDisplayFrame(Landroid/graphics/Rect;)V
-Landroid/view/View;->getWindowSession()Landroid/view/IWindowSession;
-Landroid/view/View;->hasIdentityMatrix()Z
-Landroid/view/View;->hasRtlSupport()Z
-Landroid/view/View;->includeForAccessibility()Z
-Landroid/view/View;->initializeScrollbarsInternal(Landroid/content/res/TypedArray;)V
-Landroid/view/View;->internalSetPadding(IIII)V
-Landroid/view/View;->invalidate(Z)V
-Landroid/view/View;->invalidateParentCaches()V
-Landroid/view/View;->invalidateParentIfNeeded()V
-Landroid/view/View;->invalidateViewProperty(ZZ)V
-Landroid/view/View;->isDraggingScrollBar()Z
-Landroid/view/View;->isInScrollingContainer()Z
-Landroid/view/View;->isLayoutRtl()Z
-Landroid/view/View;->isOnScrollbarThumb(FF)Z
-Landroid/view/View;->isPaddingResolved()Z
-Landroid/view/View;->isRootNamespace()Z
-Landroid/view/View;->isVisibleToUser()Z
-Landroid/view/View;->isVisibleToUser(Landroid/graphics/Rect;)Z
-Landroid/view/View;->mAccessibilityDelegate:Landroid/view/View$AccessibilityDelegate;
-Landroid/view/View;->mAccessibilityViewId:I
-Landroid/view/View;->makeOptionalFitsSystemWindows()V
-Landroid/view/View;->mAnimator:Landroid/view/ViewPropertyAnimator;
-Landroid/view/View;->mAttachInfo:Landroid/view/View$AttachInfo;
-Landroid/view/View;->mBackground:Landroid/graphics/drawable/Drawable;
-Landroid/view/View;->mBackgroundResource:I
-Landroid/view/View;->mBottom:I
-Landroid/view/View;->mCachingFailed:Z
-Landroid/view/View;->mContext:Landroid/content/Context;
-Landroid/view/View;->mDrawingCache:Landroid/graphics/Bitmap;
-Landroid/view/View;->mHasPerformedLongPress:Z
-Landroid/view/View;->mKeyedTags:Landroid/util/SparseArray;
-Landroid/view/View;->mLayoutParams:Landroid/view/ViewGroup$LayoutParams;
-Landroid/view/View;->mLeft:I
-Landroid/view/View;->mListenerInfo:Landroid/view/View$ListenerInfo;
-Landroid/view/View;->mMeasuredHeight:I
-Landroid/view/View;->mMeasuredWidth:I
-Landroid/view/View;->mMinHeight:I
-Landroid/view/View;->mMinWidth:I
-Landroid/view/View;->mPaddingBottom:I
-Landroid/view/View;->mPaddingLeft:I
-Landroid/view/View;->mPaddingRight:I
-Landroid/view/View;->mPaddingTop:I
-Landroid/view/View;->mParent:Landroid/view/ViewParent;
-Landroid/view/View;->mPendingCheckForTap:Landroid/view/View$CheckForTap;
-Landroid/view/View;->mPrivateFlags2:I
-Landroid/view/View;->mPrivateFlags3:I
-Landroid/view/View;->mPrivateFlags:I
-Landroid/view/View;->mRecreateDisplayList:Z
-Landroid/view/View;->mRenderNode:Landroid/view/RenderNode;
-Landroid/view/View;->mResources:Landroid/content/res/Resources;
-Landroid/view/View;->mRight:I
-Landroid/view/View;->mScrollCache:Landroid/view/View$ScrollabilityCache;
-Landroid/view/View;->mScrollX:I
-Landroid/view/View;->mScrollY:I
-Landroid/view/View;->mStartActivityRequestWho:Ljava/lang/String;
-Landroid/view/View;->mTag:Ljava/lang/Object;
-Landroid/view/View;->mTop:I
-Landroid/view/View;->mTransformationInfo:Landroid/view/View$TransformationInfo;
-Landroid/view/View;->mUnscaledDrawingCache:Landroid/graphics/Bitmap;
-Landroid/view/View;->mVerticalScrollbarPosition:I
-Landroid/view/View;->mViewFlags:I
-Landroid/view/View;->NAVIGATION_BAR_TRANSIENT:I
-Landroid/view/View;->notifySubtreeAccessibilityStateChangedIfNeeded()V
-Landroid/view/View;->notifyViewAccessibilityStateChangedIfNeeded(I)V
-Landroid/view/View;->onCloseSystemDialogs(Ljava/lang/String;)V
-Landroid/view/View;->onDetachedFromWindowInternal()V
-Landroid/view/View;->onDrawHorizontalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
-Landroid/view/View;->onDrawVerticalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
-Landroid/view/View;->onFocusLost()V
-Landroid/view/View;->onInitializeAccessibilityEventInternal(Landroid/view/accessibility/AccessibilityEvent;)V
-Landroid/view/View;->performAccessibilityActionInternal(ILandroid/os/Bundle;)Z
-Landroid/view/View;->pointInView(FFF)Z
-Landroid/view/View;->recomputePadding()V
-Landroid/view/View;->removePerformClickCallback()V
-Landroid/view/View;->requestAccessibilityFocus()Z
-Landroid/view/View;->resetDisplayList()V
-Landroid/view/View;->resetPaddingToInitialValues()V
-Landroid/view/View;->resetResolvedDrawables()V
-Landroid/view/View;->resetResolvedLayoutDirection()V
-Landroid/view/View;->resetResolvedPadding()V
-Landroid/view/View;->resetResolvedTextAlignment()V
-Landroid/view/View;->resetResolvedTextDirection()V
-Landroid/view/View;->resetRtlProperties()V
-Landroid/view/View;->resolvePadding()V
-Landroid/view/View;->setAlphaNoInvalidation(F)Z
-Landroid/view/View;->setAnimationMatrix(Landroid/graphics/Matrix;)V
-Landroid/view/View;->setAssistBlocked(Z)V
-Landroid/view/View;->setDisabledSystemUiVisibility(I)V
-Landroid/view/View;->setFlags(II)V
-Landroid/view/View;->setFrame(IIII)Z
-Landroid/view/View;->setIsRootNamespace(Z)V
-Landroid/view/View;->setLeftTopRightBottom(IIII)V
-Landroid/view/View;->setTagInternal(ILjava/lang/Object;)V
-Landroid/view/View;->setTransitionAlpha(F)V
-Landroid/view/View;->startActivityForResult(Landroid/content/Intent;I)V
-Landroid/view/View;->STATUS_BAR_DISABLE_BACK:I
-Landroid/view/View;->STATUS_BAR_DISABLE_EXPAND:I
-Landroid/view/View;->STATUS_BAR_DISABLE_HOME:I
-Landroid/view/View;->STATUS_BAR_DISABLE_RECENT:I
-Landroid/view/View;->toGlobalMotionEvent(Landroid/view/MotionEvent;)Z
-Landroid/view/View;->toLocalMotionEvent(Landroid/view/MotionEvent;)Z
-Landroid/view/View;->transformMatrixToGlobal(Landroid/graphics/Matrix;)V
-Landroid/view/View;->transformMatrixToLocal(Landroid/graphics/Matrix;)V
-Landroid/view/View;->updateDisplayListIfDirty()Landroid/view/RenderNode;
-Landroid/view/ViewConfiguration;->getDeviceGlobalActionKeyTimeout()J
-Landroid/view/ViewConfiguration;->getDoubleTapMinTime()I
-Landroid/view/ViewConfiguration;->getDoubleTapSlop()I
-Landroid/view/ViewConfiguration;->getHoverTapSlop()I
-Landroid/view/ViewConfiguration;->getScaledDoubleTapTouchSlop()I
-Landroid/view/ViewConfiguration;->isFadingMarqueeEnabled()Z
-Landroid/view/ViewConfiguration;->mFadingMarqueeEnabled:Z
-Landroid/view/ViewConfiguration;->sConfigurations:Landroid/util/SparseArray;
-Landroid/view/ViewConfiguration;->SCROLL_FRICTION:F
-Landroid/view/ViewConfiguration;->sHasPermanentMenuKey:Z
-Landroid/view/ViewConfiguration;->sHasPermanentMenuKeySet:Z
-Landroid/view/ViewDebug;->dispatchCommand(Landroid/view/View;Ljava/lang/String;Ljava/lang/String;Ljava/io/OutputStream;)V
-Landroid/view/ViewDebug;->dump(Landroid/view/View;ZZLjava/io/OutputStream;)V
-Landroid/view/ViewDebug;->getViewInstanceCount()J
-Landroid/view/ViewDebug;->getViewRootImplCount()J
-Landroid/view/ViewGroup$LayoutParams;-><init>()V
-Landroid/view/ViewGroup$MarginLayoutParams;->endMargin:I
-Landroid/view/ViewGroup$MarginLayoutParams;->setMarginsRelative(IIII)V
-Landroid/view/ViewGroup$MarginLayoutParams;->startMargin:I
-Landroid/view/ViewGroup$TouchTarget;-><init>()V
-Landroid/view/ViewGroup$TouchTarget;->child:Landroid/view/View;
-Landroid/view/ViewGroup;->addTransientView(Landroid/view/View;I)V
-Landroid/view/ViewGroup;->cancelTouchTarget(Landroid/view/View;)V
-Landroid/view/ViewGroup;->DBG:Z
-Landroid/view/ViewGroup;->dispatchAttachedToWindow(Landroid/view/View$AttachInfo;I)V
-Landroid/view/ViewGroup;->dispatchDetachedFromWindow()V
-Landroid/view/ViewGroup;->dispatchGetDisplayList()V
-Landroid/view/ViewGroup;->dispatchViewAdded(Landroid/view/View;)V
-Landroid/view/ViewGroup;->dispatchViewRemoved(Landroid/view/View;)V
-Landroid/view/ViewGroup;->encodeProperties(Landroid/view/ViewHierarchyEncoder;)V
-Landroid/view/ViewGroup;->FLAG_DISALLOW_INTERCEPT:I
-Landroid/view/ViewGroup;->FLAG_SUPPORT_STATIC_TRANSFORMATIONS:I
-Landroid/view/ViewGroup;->FLAG_USE_CHILD_DRAWING_ORDER:I
-Landroid/view/ViewGroup;->getTransientView(I)Landroid/view/View;
-Landroid/view/ViewGroup;->getTransientViewCount()I
-Landroid/view/ViewGroup;->isTransformedTouchPointInView(FFLandroid/view/View;Landroid/graphics/PointF;)Z
-Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V
-Landroid/view/ViewGroup;->mChildren:[Landroid/view/View;
-Landroid/view/ViewGroup;->mChildrenCount:I
-Landroid/view/ViewGroup;->mDisappearingChildren:Ljava/util/ArrayList;
-Landroid/view/ViewGroup;->mFirstTouchTarget:Landroid/view/ViewGroup$TouchTarget;
-Landroid/view/ViewGroup;->mFocused:Landroid/view/View;
-Landroid/view/ViewGroup;->mGroupFlags:I
-Landroid/view/ViewGroup;->mOnHierarchyChangeListener:Landroid/view/ViewGroup$OnHierarchyChangeListener;
-Landroid/view/ViewGroup;->mPersistentDrawingCache:I
-Landroid/view/ViewGroup;->offsetChildrenTopAndBottom(I)V
-Landroid/view/ViewGroup;->onChildVisibilityChanged(Landroid/view/View;II)V
-Landroid/view/ViewGroup;->onInitializeAccessibilityNodeInfoInternal(Landroid/view/accessibility/AccessibilityNodeInfo;)V
-Landroid/view/ViewGroup;->removeTransientView(Landroid/view/View;)V
-Landroid/view/ViewGroup;->resetResolvedDrawables()V
-Landroid/view/ViewGroup;->resetResolvedLayoutDirection()V
-Landroid/view/ViewGroup;->resetResolvedPadding()V
-Landroid/view/ViewGroup;->resetResolvedTextAlignment()V
-Landroid/view/ViewGroup;->resetResolvedTextDirection()V
-Landroid/view/ViewGroup;->resolvePadding()V
-Landroid/view/ViewGroup;->suppressLayout(Z)V
-Landroid/view/ViewGroup;->transformPointToViewLocal([FLandroid/view/View;)V
-Landroid/view/ViewHierarchyEncoder;->addProperty(Ljava/lang/String;F)V
-Landroid/view/ViewHierarchyEncoder;->addProperty(Ljava/lang/String;I)V
-Landroid/view/ViewHierarchyEncoder;->addProperty(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/view/ViewHierarchyEncoder;->addProperty(Ljava/lang/String;Z)V
-Landroid/view/ViewOverlay;->getOverlayView()Landroid/view/ViewGroup;
-Landroid/view/ViewOverlay;->isEmpty()Z
-Landroid/view/ViewPropertyAnimator;->mRTBackend:Landroid/view/ViewPropertyAnimatorRT;
-Landroid/view/ViewRootImpl$CalledFromWrongThreadException;-><init>(Ljava/lang/String;)V
-Landroid/view/ViewRootImpl;->addConfigCallback(Landroid/view/ViewRootImpl$ConfigChangedCallback;)V
-Landroid/view/ViewRootImpl;->cancelInvalidate(Landroid/view/View;)V
-Landroid/view/ViewRootImpl;->detachFunctor(J)V
-Landroid/view/ViewRootImpl;->dispatchInputEvent(Landroid/view/InputEvent;)V
-Landroid/view/ViewRootImpl;->dispatchInputEvent(Landroid/view/InputEvent;Landroid/view/InputEventReceiver;)V
-Landroid/view/ViewRootImpl;->dispatchKeyFromIme(Landroid/view/KeyEvent;)V
-Landroid/view/ViewRootImpl;->dispatchResized(Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;ZLandroid/util/MergedConfiguration;Landroid/graphics/Rect;ZZILandroid/view/DisplayCutout$ParcelableWrapper;)V
-Landroid/view/ViewRootImpl;->dispatchUnhandledInputEvent(Landroid/view/InputEvent;)V
-Landroid/view/ViewRootImpl;->enableHardwareAcceleration(Landroid/view/WindowManager$LayoutParams;)V
-Landroid/view/ViewRootImpl;->enqueueInputEvent(Landroid/view/InputEvent;)V
-Landroid/view/ViewRootImpl;->enqueueInputEvent(Landroid/view/InputEvent;Landroid/view/InputEventReceiver;IZ)V
-Landroid/view/ViewRootImpl;->ensureTouchMode(Z)Z
-Landroid/view/ViewRootImpl;->getAccessibilityFocusedHost()Landroid/view/View;
-Landroid/view/ViewRootImpl;->getAccessibilityFocusedVirtualView()Landroid/view/accessibility/AccessibilityNodeInfo;
-Landroid/view/ViewRootImpl;->getLastTouchPoint(Landroid/graphics/Point;)V
-Landroid/view/ViewRootImpl;->getView()Landroid/view/View;
-Landroid/view/ViewRootImpl;->getWindowFlags()I
-Landroid/view/ViewRootImpl;->invalidate()V
-Landroid/view/ViewRootImpl;->invokeFunctor(JZ)V
-Landroid/view/ViewRootImpl;->mAdded:Z
-Landroid/view/ViewRootImpl;->mAttachInfo:Landroid/view/View$AttachInfo;
-Landroid/view/ViewRootImpl;->mContext:Landroid/content/Context;
-Landroid/view/ViewRootImpl;->mDirty:Landroid/graphics/Rect;
-Landroid/view/ViewRootImpl;->mFallbackEventHandler:Landroid/view/FallbackEventHandler;
-Landroid/view/ViewRootImpl;->mHeight:I
-Landroid/view/ViewRootImpl;->mLastScrolledFocus:Ljava/lang/ref/WeakReference;
-Landroid/view/ViewRootImpl;->mStopped:Z
-Landroid/view/ViewRootImpl;->mSurface:Landroid/view/Surface;
-Landroid/view/ViewRootImpl;->mView:Landroid/view/View;
-Landroid/view/ViewRootImpl;->mWidth:I
-Landroid/view/ViewRootImpl;->mWindowSession:Landroid/view/IWindowSession;
-Landroid/view/ViewRootImpl;->scheduleTraversals()V
-Landroid/view/ViewRootImpl;->setLocalDragState(Ljava/lang/Object;)V
-Landroid/view/ViewRootImpl;->sRunQueues:Ljava/lang/ThreadLocal;
 Landroid/view/ViewTreeObserver$InternalInsetsInfo;-><init>()V
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->contentInsets:Landroid/graphics/Rect;
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->mTouchableInsets:I
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->set(Landroid/view/ViewTreeObserver$InternalInsetsInfo;)V
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->setTouchableInsets(I)V
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->touchableRegion:Landroid/graphics/Region;
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->TOUCHABLE_INSETS_REGION:I
-Landroid/view/ViewTreeObserver$InternalInsetsInfo;->visibleInsets:Landroid/graphics/Rect;
-Landroid/view/ViewTreeObserver;->addOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
-Landroid/view/ViewTreeObserver;->dispatchOnComputeInternalInsets(Landroid/view/ViewTreeObserver$InternalInsetsInfo;)V
-Landroid/view/ViewTreeObserver;->dispatchOnGlobalFocusChange(Landroid/view/View;Landroid/view/View;)V
-Landroid/view/ViewTreeObserver;->dispatchOnScrollChanged()V
-Landroid/view/ViewTreeObserver;->dispatchOnTouchModeChanged(Z)V
-Landroid/view/ViewTreeObserver;->hasComputeInternalInsetsListeners()Z
-Landroid/view/ViewTreeObserver;->mOnComputeInternalInsetsListeners:Landroid/view/ViewTreeObserver$CopyOnWriteArray;
-Landroid/view/ViewTreeObserver;->mOnGlobalLayoutListeners:Landroid/view/ViewTreeObserver$CopyOnWriteArray;
-Landroid/view/ViewTreeObserver;->mOnScrollChangedListeners:Landroid/view/ViewTreeObserver$CopyOnWriteArray;
-Landroid/view/ViewTreeObserver;->mOnTouchModeChangeListeners:Ljava/util/concurrent/CopyOnWriteArrayList;
-Landroid/view/ViewTreeObserver;->removeOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
-Landroid/view/Window;->addPrivateFlags(I)V
-Landroid/view/Window;->alwaysReadCloseOnTouchAttr()V
-Landroid/view/Window;->FEATURE_MAX:I
-Landroid/view/Window;->isDestroyed()Z
-Landroid/view/Window;->mAppName:Ljava/lang/String;
-Landroid/view/Window;->mAppToken:Landroid/os/IBinder;
-Landroid/view/Window;->mCallback:Landroid/view/Window$Callback;
-Landroid/view/Window;->mContext:Landroid/content/Context;
-Landroid/view/Window;->mDestroyed:Z
-Landroid/view/Window;->mFeatures:I
-Landroid/view/Window;->mHardwareAccelerated:Z
-Landroid/view/Window;->mLocalFeatures:I
-Landroid/view/Window;->mWindowAttributes:Landroid/view/WindowManager$LayoutParams;
-Landroid/view/Window;->mWindowManager:Landroid/view/WindowManager;
-Landroid/view/Window;->mWindowStyle:Landroid/content/res/TypedArray;
-Landroid/view/Window;->setCloseOnTouchOutside(Z)V
-Landroid/view/Window;->setCloseOnTouchOutsideIfNotSet(Z)V
-Landroid/view/Window;->setNeedsMenuKey(I)V
-Landroid/view/Window;->shouldCloseOnTouch(Landroid/content/Context;Landroid/view/MotionEvent;)Z
-Landroid/view/WindowAnimationFrameStats;->init(J[J)V
-Landroid/view/WindowContentFrameStats;->init(J[J[J[J)V
-Landroid/view/WindowInsets;-><init>(Landroid/graphics/Rect;)V
-Landroid/view/WindowInsets;->CONSUMED:Landroid/view/WindowInsets;
-Landroid/view/WindowInsets;->getSystemWindowInsets()Landroid/graphics/Rect;
-Landroid/view/WindowInsets;->inset(IIII)Landroid/view/WindowInsets;
-Landroid/view/WindowLeaked;-><init>(Ljava/lang/String;)V
-Landroid/view/WindowManager$LayoutParams;->backup()V
-Landroid/view/WindowManager$LayoutParams;->FLAG_SLIPPERY:I
-Landroid/view/WindowManager$LayoutParams;->hasSystemUiListeners:Z
-Landroid/view/WindowManager$LayoutParams;->hideTimeoutMilliseconds:J
-Landroid/view/WindowManager$LayoutParams;->inputFeatures:I
-Landroid/view/WindowManager$LayoutParams;->INPUT_FEATURE_DISABLE_USER_ACTIVITY:I
-Landroid/view/WindowManager$LayoutParams;->needsMenuKey:I
-Landroid/view/WindowManager$LayoutParams;->NEEDS_MENU_SET_FALSE:I
-Landroid/view/WindowManager$LayoutParams;->NEEDS_MENU_SET_TRUE:I
-Landroid/view/WindowManager$LayoutParams;->PRIVATE_FLAG_SHOW_FOR_ALL_USERS:I
-Landroid/view/WindowManager$LayoutParams;->restore()V
-Landroid/view/WindowManager$LayoutParams;->subtreeSystemUiVisibility:I
-Landroid/view/WindowManager$LayoutParams;->TYPE_APPLICATION_MEDIA_OVERLAY:I
-Landroid/view/WindowManager$LayoutParams;->TYPE_DISPLAY_OVERLAY:I
-Landroid/view/WindowManager$LayoutParams;->TYPE_SECURE_SYSTEM_OVERLAY:I
-Landroid/view/WindowManager$LayoutParams;->userActivityTimeout:J
-Landroid/view/WindowManagerGlobal;->getInstance()Landroid/view/WindowManagerGlobal;
-Landroid/view/WindowManagerGlobal;->getRootView(Ljava/lang/String;)Landroid/view/View;
-Landroid/view/WindowManagerGlobal;->getRootViews(Landroid/os/IBinder;)Ljava/util/ArrayList;
-Landroid/view/WindowManagerGlobal;->getViewRootNames()[Ljava/lang/String;
-Landroid/view/WindowManagerGlobal;->getWindowManagerService()Landroid/view/IWindowManager;
-Landroid/view/WindowManagerGlobal;->getWindowSession()Landroid/view/IWindowSession;
-Landroid/view/WindowManagerGlobal;->initialize()V
-Landroid/view/WindowManagerGlobal;->mLock:Ljava/lang/Object;
-Landroid/view/WindowManagerGlobal;->mParams:Ljava/util/ArrayList;
-Landroid/view/WindowManagerGlobal;->mRoots:Ljava/util/ArrayList;
-Landroid/view/WindowManagerGlobal;->mViews:Ljava/util/ArrayList;
-Landroid/view/WindowManagerGlobal;->peekWindowSession()Landroid/view/IWindowSession;
-Landroid/view/WindowManagerGlobal;->removeView(Landroid/view/View;Z)V
-Landroid/view/WindowManagerGlobal;->sDefaultWindowManager:Landroid/view/WindowManagerGlobal;
-Landroid/view/WindowManagerGlobal;->sWindowManagerService:Landroid/view/IWindowManager;
-Landroid/view/WindowManagerGlobal;->sWindowSession:Landroid/view/IWindowSession;
-Landroid/view/WindowManagerGlobal;->trimMemory(I)V
-Landroid/view/WindowManagerImpl;->mGlobal:Landroid/view/WindowManagerGlobal;
 Landroid/webkit/CacheManager$CacheResult;-><init>()V
-Landroid/webkit/CacheManager$CacheResult;->contentdisposition:Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->contentLength:J
-Landroid/webkit/CacheManager$CacheResult;->crossDomain:Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->encoding:Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->etag:Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->expires:J
-Landroid/webkit/CacheManager$CacheResult;->expiresString:Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getContentDisposition()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getContentLength()J
-Landroid/webkit/CacheManager$CacheResult;->getEncoding()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getETag()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getExpires()J
-Landroid/webkit/CacheManager$CacheResult;->getExpiresString()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getHttpStatusCode()I
-Landroid/webkit/CacheManager$CacheResult;->getInputStream()Ljava/io/InputStream;
-Landroid/webkit/CacheManager$CacheResult;->getLastModified()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getLocalPath()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getLocation()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getMimeType()Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->getOutputStream()Ljava/io/OutputStream;
-Landroid/webkit/CacheManager$CacheResult;->httpStatusCode:I
-Landroid/webkit/CacheManager$CacheResult;->inStream:Ljava/io/InputStream;
-Landroid/webkit/CacheManager$CacheResult;->lastModified:Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->localPath:Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->location:Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->mimeType:Ljava/lang/String;
-Landroid/webkit/CacheManager$CacheResult;->outFile:Ljava/io/File;
-Landroid/webkit/CacheManager$CacheResult;->outStream:Ljava/io/OutputStream;
-Landroid/webkit/CacheManager$CacheResult;->setEncoding(Ljava/lang/String;)V
-Landroid/webkit/CacheManager$CacheResult;->setInputStream(Ljava/io/InputStream;)V
-Landroid/webkit/CacheManager;->cacheDisabled()Z
-Landroid/webkit/CacheManager;->endCacheTransaction()Z
-Landroid/webkit/CacheManager;->getCacheFile(Ljava/lang/String;Ljava/util/Map;)Landroid/webkit/CacheManager$CacheResult;
-Landroid/webkit/CacheManager;->getCacheFileBaseDir()Ljava/io/File;
-Landroid/webkit/CacheManager;->saveCacheFile(Ljava/lang/String;JLandroid/webkit/CacheManager$CacheResult;)V
-Landroid/webkit/CacheManager;->saveCacheFile(Ljava/lang/String;Landroid/webkit/CacheManager$CacheResult;)V
-Landroid/webkit/CacheManager;->startCacheTransaction()Z
-Landroid/webkit/ConsoleMessage;->mLevel:Landroid/webkit/ConsoleMessage$MessageLevel;
-Landroid/webkit/ConsoleMessage;->mLineNumber:I
-Landroid/webkit/ConsoleMessage;->mMessage:Ljava/lang/String;
-Landroid/webkit/ConsoleMessage;->mSourceId:Ljava/lang/String;
 Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/webkit/IWebViewUpdateService$Stub$Proxy;->waitForAndGetProvider()Landroid/webkit/WebViewProviderResponse;
 Landroid/webkit/IWebViewUpdateService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/webkit/IWebViewUpdateService;
 Landroid/webkit/IWebViewUpdateService;->getCurrentWebViewPackageName()Ljava/lang/String;
 Landroid/webkit/IWebViewUpdateService;->getValidWebViewPackages()[Landroid/webkit/WebViewProviderInfo;
 Landroid/webkit/IWebViewUpdateService;->isFallbackPackage(Ljava/lang/String;)Z
-Landroid/webkit/JsResult;->mReceiver:Landroid/webkit/JsResult$ResultReceiver;
-Landroid/webkit/PluginData;-><init>(Ljava/io/InputStream;JLjava/util/Map;I)V
-Landroid/webkit/PluginData;->getContentLength()J
-Landroid/webkit/PluginData;->getHeaders()Ljava/util/Map;
-Landroid/webkit/PluginData;->getInputStream()Ljava/io/InputStream;
-Landroid/webkit/PluginData;->getStatusCode()I
-Landroid/webkit/UrlInterceptHandler;->getPluginData(Ljava/lang/String;Ljava/util/Map;)Landroid/webkit/PluginData;
-Landroid/webkit/UrlInterceptHandler;->service(Ljava/lang/String;Ljava/util/Map;)Landroid/webkit/CacheManager$CacheResult;
-Landroid/webkit/UrlInterceptRegistry;->getPluginData(Ljava/lang/String;Ljava/util/Map;)Landroid/webkit/PluginData;
-Landroid/webkit/UrlInterceptRegistry;->registerHandler(Landroid/webkit/UrlInterceptHandler;)Z
-Landroid/webkit/UrlInterceptRegistry;->setUrlInterceptDisabled(Z)V
-Landroid/webkit/UrlInterceptRegistry;->unregisterHandler(Landroid/webkit/UrlInterceptHandler;)Z
-Landroid/webkit/URLUtil;->isResourceUrl(Ljava/lang/String;)Z
-Landroid/webkit/URLUtil;->parseContentDisposition(Ljava/lang/String;)Ljava/lang/String;
-Landroid/webkit/URLUtil;->verifyURLEncoding(Ljava/lang/String;)Z
-Landroid/webkit/WebResourceResponse;->mImmutable:Z
-Landroid/webkit/WebResourceResponse;->mStatusCode:I
-Landroid/webkit/WebSettings$TextSize;->value:I
-Landroid/webkit/WebSyncManager;->mHandler:Landroid/os/Handler;
-Landroid/webkit/WebSyncManager;->syncFromRamToFlash()V
-Landroid/webkit/WebView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;IILjava/util/Map;Z)V
-Landroid/webkit/WebView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;ILjava/util/Map;Z)V
-Landroid/webkit/WebView;->checkThread()V
-Landroid/webkit/WebView;->debugDump()V
-Landroid/webkit/WebView;->disablePlatformNotifications()V
-Landroid/webkit/WebView;->emulateShiftHeld()V
-Landroid/webkit/WebView;->enablePlatformNotifications()V
-Landroid/webkit/WebView;->freeMemoryForTests()V
-Landroid/webkit/WebView;->getContentWidth()I
-Landroid/webkit/WebView;->getFactory()Landroid/webkit/WebViewFactoryProvider;
-Landroid/webkit/WebView;->getTouchIconUrl()Ljava/lang/String;
-Landroid/webkit/WebView;->getVisibleTitleHeight()I
-Landroid/webkit/WebView;->isPaused()Z
-Landroid/webkit/WebView;->mProvider:Landroid/webkit/WebViewProvider;
-Landroid/webkit/WebView;->mWebViewThread:Landroid/os/Looper;
-Landroid/webkit/WebView;->notifyFindDialogDismissed()V
-Landroid/webkit/WebView;->onDrawVerticalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
-Landroid/webkit/WebView;->restorePicture(Landroid/os/Bundle;Ljava/io/File;)Z
-Landroid/webkit/WebView;->savePicture(Landroid/os/Bundle;Ljava/io/File;)Z
-Landroid/webkit/WebView;->sEnforceThreadChecking:Z
-Landroid/webkit/WebView;->setFrame(IIII)Z
-Landroid/webkit/WebViewDelegate;-><init>()V
-Landroid/webkit/WebViewFactory;->getProvider()Landroid/webkit/WebViewFactoryProvider;
-Landroid/webkit/WebViewFactory;->getProviderClass()Ljava/lang/Class;
-Landroid/webkit/WebViewFactory;->getUpdateService()Landroid/webkit/IWebViewUpdateService;
-Landroid/webkit/WebViewFactory;->getWebViewContextAndSetProvider()Landroid/content/Context;
-Landroid/webkit/WebViewFactory;->sPackageInfo:Landroid/content/pm/PackageInfo;
-Landroid/webkit/WebViewFactory;->sProviderInstance:Landroid/webkit/WebViewFactoryProvider;
-Landroid/webkit/WebViewProviderInfo;-><init>(Landroid/os/Parcel;)V
-Landroid/webkit/WebViewProviderResponse;->packageInfo:Landroid/content/pm/PackageInfo;
-Landroid/webkit/WebViewUpdateService;-><init>()V
-Landroid/widget/AbsListView$FlingRunnable;->endFling()V
-Landroid/widget/AbsListView$FlingRunnable;->mScroller:Landroid/widget/OverScroller;
-Landroid/widget/AbsListView$FlingRunnable;->start(I)V
-Landroid/widget/AbsListView$LayoutParams;->scrappedFromPosition:I
-Landroid/widget/AbsListView$LayoutParams;->viewType:I
-Landroid/widget/AbsListView$RecycleBin;->clear()V
-Landroid/widget/AbsListView$RecycleBin;->mRecyclerListener:Landroid/widget/AbsListView$RecyclerListener;
-Landroid/widget/AbsListView$SavedState;->firstId:J
-Landroid/widget/AbsListView$SavedState;->viewTop:I
-Landroid/widget/AbsListView;->canScrollDown()Z
-Landroid/widget/AbsListView;->canScrollUp()Z
-Landroid/widget/AbsListView;->findMotionRow(I)I
-Landroid/widget/AbsListView;->invokeOnItemScrollListener()V
-Landroid/widget/AbsListView;->isVerticalScrollBarHidden()Z
-Landroid/widget/AbsListView;->mActivePointerId:I
-Landroid/widget/AbsListView;->mAdapter:Landroid/widget/ListAdapter;
-Landroid/widget/AbsListView;->mChoiceActionMode:Landroid/view/ActionMode;
-Landroid/widget/AbsListView;->mContextMenuInfo:Landroid/view/ContextMenu$ContextMenuInfo;
-Landroid/widget/AbsListView;->mDataSetObserver:Landroid/widget/AbsListView$AdapterDataSetObserver;
-Landroid/widget/AbsListView;->mEdgeGlowBottom:Landroid/widget/EdgeEffect;
-Landroid/widget/AbsListView;->mEdgeGlowTop:Landroid/widget/EdgeEffect;
-Landroid/widget/AbsListView;->mFastScroll:Landroid/widget/FastScroller;
-Landroid/widget/AbsListView;->mFlingRunnable:Landroid/widget/AbsListView$FlingRunnable;
-Landroid/widget/AbsListView;->mIsChildViewEnabled:Z
-Landroid/widget/AbsListView;->mLayoutMode:I
-Landroid/widget/AbsListView;->mMaximumVelocity:I
-Landroid/widget/AbsListView;->mMotionPosition:I
-Landroid/widget/AbsListView;->mMotionY:I
-Landroid/widget/AbsListView;->mOnScrollListener:Landroid/widget/AbsListView$OnScrollListener;
-Landroid/widget/AbsListView;->mOverflingDistance:I
-Landroid/widget/AbsListView;->mOverscrollDistance:I
-Landroid/widget/AbsListView;->mPendingCheckForLongPress:Landroid/widget/AbsListView$CheckForLongPress;
-Landroid/widget/AbsListView;->mPendingCheckForTap:Landroid/widget/AbsListView$CheckForTap;
-Landroid/widget/AbsListView;->mPopup:Landroid/widget/PopupWindow;
-Landroid/widget/AbsListView;->mPositionScroller:Landroid/widget/AbsListView$AbsPositionScroller;
-Landroid/widget/AbsListView;->mRecycler:Landroid/widget/AbsListView$RecycleBin;
-Landroid/widget/AbsListView;->mSelectionBottomPadding:I
-Landroid/widget/AbsListView;->mSelectionTopPadding:I
-Landroid/widget/AbsListView;->mSelector:Landroid/graphics/drawable/Drawable;
-Landroid/widget/AbsListView;->mSelectorPosition:I
-Landroid/widget/AbsListView;->mSelectorRect:Landroid/graphics/Rect;
-Landroid/widget/AbsListView;->mTouchMode:I
-Landroid/widget/AbsListView;->mTouchSlop:I
-Landroid/widget/AbsListView;->mVelocityTracker:Landroid/view/VelocityTracker;
-Landroid/widget/AbsListView;->performLongPress(Landroid/view/View;IJ)Z
-Landroid/widget/AbsListView;->performLongPress(Landroid/view/View;IJFF)Z
-Landroid/widget/AbsListView;->positionSelector(ILandroid/view/View;ZFF)V
-Landroid/widget/AbsListView;->reportScrollStateChange(I)V
-Landroid/widget/AbsListView;->resurrectSelectionIfNeeded()Z
-Landroid/widget/AbsListView;->smoothScrollBy(IIZZ)V
-Landroid/widget/AbsListView;->trackMotionScroll(II)Z
-Landroid/widget/AbsListView;->updateSelectorState()V
-Landroid/widget/AbsSeekBar;->drawThumb(Landroid/graphics/Canvas;)V
-Landroid/widget/AbsSeekBar;->mDisabledAlpha:F
-Landroid/widget/AbsSeekBar;->mIsDragging:Z
-Landroid/widget/AbsSeekBar;->mIsUserSeekable:Z
-Landroid/widget/AbsSeekBar;->mSplitTrack:Z
-Landroid/widget/AbsSeekBar;->mThumb:Landroid/graphics/drawable/Drawable;
-Landroid/widget/AbsSeekBar;->mTouchProgressOffset:F
-Landroid/widget/AbsSeekBar;->trackTouchEvent(Landroid/view/MotionEvent;)V
-Landroid/widget/ActionMenuPresenter;->dismissPopupMenus()Z
-Landroid/widget/ActionMenuPresenter;->isOverflowMenuShowing()Z
-Landroid/widget/ActionMenuPresenter;->onRestoreInstanceState(Landroid/os/Parcelable;)V
-Landroid/widget/ActionMenuPresenter;->onSaveInstanceState()Landroid/os/Parcelable;
-Landroid/widget/ActionMenuView$ActionMenuChildView;->needsDividerBefore()Z
-Landroid/widget/ActionMenuView$LayoutParams;->cellsUsed:I
-Landroid/widget/ActionMenuView$LayoutParams;->expandable:Z
-Landroid/widget/ActionMenuView$LayoutParams;->expanded:Z
-Landroid/widget/ActionMenuView$LayoutParams;->extraPixels:I
-Landroid/widget/ActionMenuView$LayoutParams;->isOverflowButton:Z
-Landroid/widget/ActionMenuView$LayoutParams;->preventEdgeOffset:Z
-Landroid/widget/ActionMenuView;->hasDividerBeforeChildAt(I)Z
-Landroid/widget/ActionMenuView;->isOverflowMenuShowPending()Z
-Landroid/widget/ActionMenuView;->isOverflowReserved()Z
-Landroid/widget/ActionMenuView;->peekMenu()Lcom/android/internal/view/menu/MenuBuilder;
-Landroid/widget/ActionMenuView;->setExpandedActionViewsExclusive(Z)V
-Landroid/widget/ActionMenuView;->setMenuCallbacks(Lcom/android/internal/view/menu/MenuPresenter$Callback;Lcom/android/internal/view/menu/MenuBuilder$Callback;)V
-Landroid/widget/ActivityChooserModel;->chooseActivity(I)Landroid/content/Intent;
-Landroid/widget/ActivityChooserModel;->get(Landroid/content/Context;Ljava/lang/String;)Landroid/widget/ActivityChooserModel;
-Landroid/widget/ActivityChooserModel;->getActivity(I)Landroid/content/pm/ResolveInfo;
-Landroid/widget/ActivityChooserModel;->getActivityCount()I
-Landroid/widget/ActivityChooserModel;->setIntent(Landroid/content/Intent;)V
-Landroid/widget/ActivityChooserModel;->setOnChooseActivityListener(Landroid/widget/ActivityChooserModel$OnChooseActivityListener;)V
-Landroid/widget/ActivityChooserView;->setExpandActivityOverflowButtonDrawable(Landroid/graphics/drawable/Drawable;)V
-Landroid/widget/AdapterView;->mDataChanged:Z
-Landroid/widget/AdapterView;->mFirstPosition:I
-Landroid/widget/AdapterView;->mNeedSync:Z
-Landroid/widget/AdapterView;->mNextSelectedPosition:I
-Landroid/widget/AdapterView;->mNextSelectedRowId:J
-Landroid/widget/AdapterView;->mOldSelectedPosition:I
-Landroid/widget/AdapterView;->mOnItemClickListener:Landroid/widget/AdapterView$OnItemClickListener;
-Landroid/widget/AdapterView;->mOnItemSelectedListener:Landroid/widget/AdapterView$OnItemSelectedListener;
-Landroid/widget/AdapterView;->mSelectedPosition:I
-Landroid/widget/AdapterView;->mSyncPosition:I
-Landroid/widget/AdapterView;->selectionChanged()V
-Landroid/widget/AdapterView;->setNextSelectedPositionInt(I)V
-Landroid/widget/AdapterView;->setSelectedPositionInt(I)V
-Landroid/widget/AnalogClock;->mDial:Landroid/graphics/drawable/Drawable;
-Landroid/widget/AnalogClock;->mHourHand:Landroid/graphics/drawable/Drawable;
-Landroid/widget/AnalogClock;->mMinuteHand:Landroid/graphics/drawable/Drawable;
-Landroid/widget/AppSecurityPermissions;-><init>(Landroid/content/Context;Ljava/lang/String;)V
-Landroid/widget/AppSecurityPermissions;->getPermissionCount()I
-Landroid/widget/AppSecurityPermissions;->getPermissionsView()Landroid/view/View;
-Landroid/widget/ArrayAdapter;->mLock:Ljava/lang/Object;
-Landroid/widget/ArrayAdapter;->mObjects:Ljava/util/List;
-Landroid/widget/ArrayAdapter;->mOriginalValues:Ljava/util/ArrayList;
-Landroid/widget/AutoCompleteTextView;->doAfterTextChanged()V
-Landroid/widget/AutoCompleteTextView;->doBeforeTextChanged()V
-Landroid/widget/AutoCompleteTextView;->ensureImeVisible(Z)V
-Landroid/widget/AutoCompleteTextView;->isInputMethodNotNeeded()Z
-Landroid/widget/AutoCompleteTextView;->mHintView:Landroid/widget/TextView;
-Landroid/widget/AutoCompleteTextView;->mObserver:Landroid/widget/AutoCompleteTextView$PopupDataSetObserver;
-Landroid/widget/AutoCompleteTextView;->mPassThroughClickListener:Landroid/widget/AutoCompleteTextView$PassThroughClickListener;
-Landroid/widget/AutoCompleteTextView;->mPopup:Landroid/widget/ListPopupWindow;
-Landroid/widget/AutoCompleteTextView;->setDropDownAlwaysVisible(Z)V
-Landroid/widget/AutoCompleteTextView;->setDropDownAnimationStyle(I)V
-Landroid/widget/AutoCompleteTextView;->setDropDownDismissedOnCompletion(Z)V
-Landroid/widget/AutoCompleteTextView;->setForceIgnoreOutsideTouch(Z)V
-Landroid/widget/AutoCompleteTextView;->showDropDownAfterLayout()V
-Landroid/widget/BaseAdapter;->mDataSetObservable:Landroid/database/DataSetObservable;
-Landroid/widget/CalendarView;->mDelegate:Landroid/widget/CalendarView$CalendarViewDelegate;
-Landroid/widget/CheckedTextView;->mCheckMarkDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/CheckedTextView;->mCheckMarkGravity:I
-Landroid/widget/CompoundButton;->mBroadcasting:Z
-Landroid/widget/CompoundButton;->mButtonDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/CompoundButton;->mOnCheckedChangeListener:Landroid/widget/CompoundButton$OnCheckedChangeListener;
-Landroid/widget/CursorAdapter;->mChangeObserver:Landroid/widget/CursorAdapter$ChangeObserver;
-Landroid/widget/CursorAdapter;->mContext:Landroid/content/Context;
-Landroid/widget/CursorAdapter;->mCursor:Landroid/database/Cursor;
-Landroid/widget/CursorAdapter;->mDataSetObserver:Landroid/database/DataSetObserver;
-Landroid/widget/CursorAdapter;->mDataValid:Z
-Landroid/widget/CursorAdapter;->mRowIDColumn:I
-Landroid/widget/DatePicker;->mDelegate:Landroid/widget/DatePicker$DatePickerDelegate;
-Landroid/widget/DatePicker;->setValidationCallback(Landroid/widget/DatePicker$ValidationCallback;)V
-Landroid/widget/DateTimeView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Landroid/widget/DateTimeView;->setTime(J)V
-Landroid/widget/DateTimeView;->update()V
-Landroid/widget/EdgeEffect;->mGlowScaleY:F
-Landroid/widget/EdgeEffect;->mPaint:Landroid/graphics/Paint;
-Landroid/widget/Editor$InputContentType;->privateImeOptions:Ljava/lang/String;
-Landroid/widget/Editor;->invalidateTextDisplayList()V
-Landroid/widget/Editor;->mCreatedWithASelection:Z
-Landroid/widget/Editor;->mInsertionControllerEnabled:Z
-Landroid/widget/Editor;->mSelectHandleCenter:Landroid/graphics/drawable/Drawable;
-Landroid/widget/Editor;->mSelectHandleLeft:Landroid/graphics/drawable/Drawable;
-Landroid/widget/Editor;->mSelectHandleRight:Landroid/graphics/drawable/Drawable;
-Landroid/widget/Editor;->mSelectionControllerEnabled:Z
-Landroid/widget/Editor;->mShowCursor:J
-Landroid/widget/Editor;->mShowSoftInputOnFocus:Z
-Landroid/widget/ExpandableListView;->GROUP_STATE_SETS:[[I
-Landroid/widget/ExpandableListView;->mChildDivider:Landroid/graphics/drawable/Drawable;
-Landroid/widget/ExpandableListView;->mConnector:Landroid/widget/ExpandableListConnector;
-Landroid/widget/ExpandableListView;->mGroupIndicator:Landroid/graphics/drawable/Drawable;
-Landroid/widget/ExpandableListView;->mIndicatorLeft:I
-Landroid/widget/ExpandableListView;->mIndicatorRight:I
-Landroid/widget/ExpandableListView;->mOnChildClickListener:Landroid/widget/ExpandableListView$OnChildClickListener;
-Landroid/widget/ExpandableListView;->mOnGroupClickListener:Landroid/widget/ExpandableListView$OnGroupClickListener;
-Landroid/widget/ExpandableListView;->mOnGroupCollapseListener:Landroid/widget/ExpandableListView$OnGroupCollapseListener;
-Landroid/widget/ExpandableListView;->mOnGroupExpandListener:Landroid/widget/ExpandableListView$OnGroupExpandListener;
-Landroid/widget/FastScroller;-><init>(Landroid/widget/AbsListView;I)V
-Landroid/widget/FastScroller;->mContainerRect:Landroid/graphics/Rect;
-Landroid/widget/FastScroller;->mHeaderCount:I
-Landroid/widget/FastScroller;->mLongList:Z
-Landroid/widget/FastScroller;->mMinimumTouchTarget:I
-Landroid/widget/FastScroller;->mThumbDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/FastScroller;->mThumbImage:Landroid/widget/ImageView;
-Landroid/widget/FastScroller;->mTrackDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/FastScroller;->mTrackImage:Landroid/widget/ImageView;
-Landroid/widget/FastScroller;->onInterceptTouchEvent(Landroid/view/MotionEvent;)Z
-Landroid/widget/FastScroller;->onSizeChanged(IIII)V
-Landroid/widget/FastScroller;->onTouchEvent(Landroid/view/MotionEvent;)Z
-Landroid/widget/FastScroller;->remove()V
-Landroid/widget/FastScroller;->setState(I)V
-Landroid/widget/Filter;->setDelayer(Landroid/widget/Filter$Delayer;)V
-Landroid/widget/FrameLayout;->mForegroundPaddingBottom:I
-Landroid/widget/FrameLayout;->mForegroundPaddingLeft:I
-Landroid/widget/FrameLayout;->mForegroundPaddingRight:I
-Landroid/widget/FrameLayout;->mForegroundPaddingTop:I
-Landroid/widget/FrameLayout;->mMeasureAllChildren:Z
-Landroid/widget/Gallery$FlingRunnable;->startUsingVelocity(I)V
-Landroid/widget/Gallery;->fillToGalleryLeft()V
-Landroid/widget/Gallery;->fillToGalleryRight()V
-Landroid/widget/Gallery;->getCenterOfGallery()I
-Landroid/widget/Gallery;->getCenterOfView(Landroid/view/View;)I
-Landroid/widget/Gallery;->makeAndAddView(IIIZ)Landroid/view/View;
-Landroid/widget/Gallery;->mDownTouchPosition:I
-Landroid/widget/Gallery;->mDownTouchView:Landroid/view/View;
-Landroid/widget/Gallery;->mFlingRunnable:Landroid/widget/Gallery$FlingRunnable;
-Landroid/widget/Gallery;->mGestureDetector:Landroid/view/GestureDetector;
-Landroid/widget/Gallery;->moveDirection(I)Z
-Landroid/widget/Gallery;->mSelectedChild:Landroid/view/View;
-Landroid/widget/Gallery;->mSpacing:I
-Landroid/widget/Gallery;->trackMotionScroll(I)V
-Landroid/widget/GridLayout;->UNDEFINED_ALIGNMENT:Landroid/widget/GridLayout$Alignment;
-Landroid/widget/GridView;->determineColumns(I)Z
-Landroid/widget/GridView;->fillDown(II)Landroid/view/View;
-Landroid/widget/GridView;->fillUp(II)Landroid/view/View;
-Landroid/widget/GridView;->mColumnWidth:I
-Landroid/widget/GridView;->mHorizontalSpacing:I
-Landroid/widget/GridView;->mNumColumns:I
-Landroid/widget/GridView;->mRequestedColumnWidth:I
-Landroid/widget/GridView;->mRequestedHorizontalSpacing:I
-Landroid/widget/GridView;->mRequestedNumColumns:I
-Landroid/widget/GridView;->mVerticalSpacing:I
-Landroid/widget/GridView;->sequenceScroll(I)Z
-Landroid/widget/HeaderViewListAdapter;->mAdapter:Landroid/widget/ListAdapter;
-Landroid/widget/HeaderViewListAdapter;->mFooterViewInfos:Ljava/util/ArrayList;
-Landroid/widget/HeaderViewListAdapter;->mHeaderViewInfos:Ljava/util/ArrayList;
-Landroid/widget/HorizontalScrollView;->mChildToScrollTo:Landroid/view/View;
-Landroid/widget/HorizontalScrollView;->mEdgeGlowLeft:Landroid/widget/EdgeEffect;
-Landroid/widget/HorizontalScrollView;->mEdgeGlowRight:Landroid/widget/EdgeEffect;
-Landroid/widget/HorizontalScrollView;->mIsBeingDragged:Z
-Landroid/widget/HorizontalScrollView;->mLastMotionX:I
-Landroid/widget/HorizontalScrollView;->mOverflingDistance:I
-Landroid/widget/HorizontalScrollView;->mOverscrollDistance:I
-Landroid/widget/HorizontalScrollView;->mScroller:Landroid/widget/OverScroller;
-Landroid/widget/HorizontalScrollView;->mVelocityTracker:Landroid/view/VelocityTracker;
-Landroid/widget/HorizontalScrollView;->recycleVelocityTracker()V
-Landroid/widget/ImageView;->animateTransform(Landroid/graphics/Matrix;)V
-Landroid/widget/ImageView;->mAdjustViewBounds:Z
-Landroid/widget/ImageView;->mAlpha:I
-Landroid/widget/ImageView;->mCropToPadding:Z
-Landroid/widget/ImageView;->mDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/ImageView;->mDrawableHeight:I
-Landroid/widget/ImageView;->mDrawableWidth:I
-Landroid/widget/ImageView;->mDrawMatrix:Landroid/graphics/Matrix;
-Landroid/widget/ImageView;->mMaxHeight:I
-Landroid/widget/ImageView;->mMaxWidth:I
-Landroid/widget/ImageView;->mRecycleableBitmapDrawable:Landroid/graphics/drawable/BitmapDrawable;
-Landroid/widget/ImageView;->mResource:I
-Landroid/widget/ImageView;->mUri:Landroid/net/Uri;
-Landroid/widget/ImageView;->resizeFromDrawable()V
-Landroid/widget/ImageView;->resolveUri()V
-Landroid/widget/ImageView;->scaleTypeToScaleToFit(Landroid/widget/ImageView$ScaleType;)Landroid/graphics/Matrix$ScaleToFit;
-Landroid/widget/ImageView;->setImageResourceAsync(I)Ljava/lang/Runnable;
-Landroid/widget/ImageView;->setImageURIAsync(Landroid/net/Uri;)Ljava/lang/Runnable;
-Landroid/widget/ImageView;->updateDrawable(Landroid/graphics/drawable/Drawable;)V
-Landroid/widget/LinearLayout$LayoutParams;->encodeProperties(Landroid/view/ViewHierarchyEncoder;)V
-Landroid/widget/LinearLayout;->INDEX_BOTTOM:I
-Landroid/widget/LinearLayout;->INDEX_TOP:I
-Landroid/widget/LinearLayout;->mDivider:Landroid/graphics/drawable/Drawable;
-Landroid/widget/LinearLayout;->mGravity:I
-Landroid/widget/LinearLayout;->mMaxAscent:[I
-Landroid/widget/LinearLayout;->mMaxDescent:[I
-Landroid/widget/LinearLayout;->mTotalLength:I
-Landroid/widget/LinearLayout;->mUseLargestChild:Z
-Landroid/widget/ListPopupWindow;->buildDropDown()I
-Landroid/widget/ListPopupWindow;->isDropDownAlwaysVisible()Z
-Landroid/widget/ListPopupWindow;->mDropDownList:Landroid/widget/DropDownListView;
-Landroid/widget/ListPopupWindow;->mPopup:Landroid/widget/PopupWindow;
-Landroid/widget/ListPopupWindow;->setDropDownAlwaysVisible(Z)V
-Landroid/widget/ListPopupWindow;->setForceIgnoreOutsideTouch(Z)V
-Landroid/widget/ListPopupWindow;->setListItemExpandMax(I)V
-Landroid/widget/ListView;->arrowScroll(I)Z
-Landroid/widget/ListView;->correctTooHigh(I)V
-Landroid/widget/ListView;->correctTooLow(I)V
-Landroid/widget/ListView;->fillDown(II)Landroid/view/View;
-Landroid/widget/ListView;->fillSpecific(II)Landroid/view/View;
-Landroid/widget/ListView;->fillUp(II)Landroid/view/View;
-Landroid/widget/ListView;->getHeightForPosition(I)I
-Landroid/widget/ListView;->isDirectChildHeaderOrFooter(Landroid/view/View;)Z
-Landroid/widget/ListView;->makeAndAddView(IIZIZ)Landroid/view/View;
-Landroid/widget/ListView;->mAreAllItemsSelectable:Z
-Landroid/widget/ListView;->mDivider:Landroid/graphics/drawable/Drawable;
-Landroid/widget/ListView;->mDividerHeight:I
-Landroid/widget/ListView;->measureHeightOfChildren(IIIII)I
-Landroid/widget/ListView;->mFooterViewInfos:Ljava/util/ArrayList;
-Landroid/widget/ListView;->mHeaderViewInfos:Ljava/util/ArrayList;
-Landroid/widget/ListView;->scrollListItemsBy(I)V
-Landroid/widget/ListView;->setSelectionInt(I)V
-Landroid/widget/ListView;->trackMotionScroll(II)Z
-Landroid/widget/MediaController;->mAnchor:Landroid/view/View;
-Landroid/widget/MediaController;->mContext:Landroid/content/Context;
-Landroid/widget/MediaController;->mCurrentTime:Landroid/widget/TextView;
-Landroid/widget/MediaController;->mDecor:Landroid/view/View;
-Landroid/widget/MediaController;->mDecorLayoutParams:Landroid/view/WindowManager$LayoutParams;
-Landroid/widget/MediaController;->mEndTime:Landroid/widget/TextView;
-Landroid/widget/MediaController;->mFfwdButton:Landroid/widget/ImageButton;
-Landroid/widget/MediaController;->mFfwdListener:Landroid/view/View$OnClickListener;
-Landroid/widget/MediaController;->mNextButton:Landroid/widget/ImageButton;
-Landroid/widget/MediaController;->mPauseButton:Landroid/widget/ImageButton;
-Landroid/widget/MediaController;->mPlayer:Landroid/widget/MediaController$MediaPlayerControl;
-Landroid/widget/MediaController;->mPrevButton:Landroid/widget/ImageButton;
-Landroid/widget/MediaController;->mProgress:Landroid/widget/ProgressBar;
-Landroid/widget/MediaController;->mRewButton:Landroid/widget/ImageButton;
-Landroid/widget/MediaController;->mRewListener:Landroid/view/View$OnClickListener;
-Landroid/widget/MediaController;->mRoot:Landroid/view/View;
-Landroid/widget/MediaController;->mSeekListener:Landroid/widget/SeekBar$OnSeekBarChangeListener;
-Landroid/widget/MediaController;->mShowing:Z
-Landroid/widget/MediaController;->mWindow:Landroid/view/Window;
-Landroid/widget/MediaController;->mWindowManager:Landroid/view/WindowManager;
-Landroid/widget/MediaController;->updatePausePlay()V
-Landroid/widget/NumberPicker;->changeValueByOne(Z)V
-Landroid/widget/NumberPicker;->getTwoDigitFormatter()Landroid/widget/NumberPicker$Formatter;
-Landroid/widget/NumberPicker;->initializeSelectorWheelIndices()V
-Landroid/widget/NumberPicker;->mFlingScroller:Landroid/widget/Scroller;
-Landroid/widget/NumberPicker;->mInputText:Landroid/widget/EditText;
-Landroid/widget/NumberPicker;->mMaximumFlingVelocity:I
-Landroid/widget/NumberPicker;->mMaxValue:I
-Landroid/widget/NumberPicker;->mMinHeight:I
-Landroid/widget/NumberPicker;->mMinWidth:I
-Landroid/widget/NumberPicker;->mOnValueChangeListener:Landroid/widget/NumberPicker$OnValueChangeListener;
-Landroid/widget/NumberPicker;->mSelectionDivider:Landroid/graphics/drawable/Drawable;
-Landroid/widget/NumberPicker;->mSelectionDividerHeight:I
-Landroid/widget/NumberPicker;->mSelectorIndices:[I
-Landroid/widget/NumberPicker;->mSelectorWheelPaint:Landroid/graphics/Paint;
-Landroid/widget/NumberPicker;->mTextSize:I
-Landroid/widget/NumberPicker;->SELECTOR_MIDDLE_ITEM_INDEX:I
-Landroid/widget/NumberPicker;->SELECTOR_WHEEL_ITEM_COUNT:I
-Landroid/widget/OverScroller$SplineOverScroller;->mCurrVelocity:F
-Landroid/widget/OverScroller;-><init>(Landroid/content/Context;Landroid/view/animation/Interpolator;Z)V
-Landroid/widget/OverScroller;->extendDuration(I)V
-Landroid/widget/OverScroller;->isScrollingInDirection(FF)Z
-Landroid/widget/OverScroller;->mInterpolator:Landroid/view/animation/Interpolator;
-Landroid/widget/OverScroller;->mScrollerY:Landroid/widget/OverScroller$SplineOverScroller;
-Landroid/widget/OverScroller;->setInterpolator(Landroid/view/animation/Interpolator;)V
-Landroid/widget/PopupMenu;->mContext:Landroid/content/Context;
-Landroid/widget/PopupMenu;->mPopup:Lcom/android/internal/view/menu/MenuPopupHelper;
-Landroid/widget/PopupWindow;->computeAnimationResource()I
-Landroid/widget/PopupWindow;->createPopupLayoutParams(Landroid/os/IBinder;)Landroid/view/WindowManager$LayoutParams;
-Landroid/widget/PopupWindow;->invokePopup(Landroid/view/WindowManager$LayoutParams;)V
-Landroid/widget/PopupWindow;->mAboveAnchor:Z
-Landroid/widget/PopupWindow;->mAboveAnchorBackgroundDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/PopupWindow;->mAnchor:Ljava/lang/ref/WeakReference;
-Landroid/widget/PopupWindow;->mAnimationStyle:I
-Landroid/widget/PopupWindow;->mBackgroundView:Landroid/view/View;
-Landroid/widget/PopupWindow;->mBelowAnchorBackgroundDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/PopupWindow;->mContentView:Landroid/view/View;
-Landroid/widget/PopupWindow;->mContext:Landroid/content/Context;
-Landroid/widget/PopupWindow;->mDecorView:Landroid/widget/PopupWindow$PopupDecorView;
-Landroid/widget/PopupWindow;->mHeightMode:I
-Landroid/widget/PopupWindow;->mIsDropdown:Z
-Landroid/widget/PopupWindow;->mIsShowing:Z
-Landroid/widget/PopupWindow;->mLastHeight:I
-Landroid/widget/PopupWindow;->mLastWidth:I
-Landroid/widget/PopupWindow;->mLayoutInScreen:Z
-Landroid/widget/PopupWindow;->mNotTouchModal:Z
-Landroid/widget/PopupWindow;->mOnDismissListener:Landroid/widget/PopupWindow$OnDismissListener;
-Landroid/widget/PopupWindow;->mOnScrollChangedListener:Landroid/view/ViewTreeObserver$OnScrollChangedListener;
-Landroid/widget/PopupWindow;->mOverlapAnchor:Z
-Landroid/widget/PopupWindow;->mTouchInterceptor:Landroid/view/View$OnTouchListener;
-Landroid/widget/PopupWindow;->mWidthMode:I
-Landroid/widget/PopupWindow;->mWindowLayoutType:I
-Landroid/widget/PopupWindow;->mWindowManager:Landroid/view/WindowManager;
-Landroid/widget/PopupWindow;->preparePopup(Landroid/view/WindowManager$LayoutParams;)V
-Landroid/widget/PopupWindow;->setAllowScrollingAnchorParent(Z)V
-Landroid/widget/PopupWindow;->setClipToScreenEnabled(Z)V
-Landroid/widget/PopupWindow;->setEpicenterBounds(Landroid/graphics/Rect;)V
-Landroid/widget/PopupWindow;->setLayoutInScreenEnabled(Z)V
-Landroid/widget/PopupWindow;->setLayoutInsetDecor(Z)V
-Landroid/widget/PopupWindow;->setTouchModal(Z)V
-Landroid/widget/PopupWindow;->showAtLocation(Landroid/os/IBinder;III)V
-Landroid/widget/PopupWindow;->updateAboveAnchor(Z)V
-Landroid/widget/ProgressBar;->mCurrentDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/ProgressBar;->mDuration:I
-Landroid/widget/ProgressBar;->mIndeterminate:Z
-Landroid/widget/ProgressBar;->mMaxHeight:I
-Landroid/widget/ProgressBar;->mMinHeight:I
-Landroid/widget/ProgressBar;->mMinWidth:I
-Landroid/widget/ProgressBar;->mMirrorForRtl:Z
-Landroid/widget/ProgressBar;->mOnlyIndeterminate:Z
-Landroid/widget/ProgressBar;->refreshProgress(IIZZ)V
-Landroid/widget/ProgressBar;->setProgressInternal(IZZ)Z
-Landroid/widget/ProgressBar;->startAnimation()V
-Landroid/widget/ProgressBar;->stopAnimation()V
-Landroid/widget/ProgressBar;->tileify(Landroid/graphics/drawable/Drawable;Z)Landroid/graphics/drawable/Drawable;
-Landroid/widget/QuickContactBadge;->mOverlay:Landroid/graphics/drawable/Drawable;
-Landroid/widget/RadioGroup;->mChildOnCheckedChangeListener:Landroid/widget/CompoundButton$OnCheckedChangeListener;
-Landroid/widget/RadioGroup;->mOnCheckedChangeListener:Landroid/widget/RadioGroup$OnCheckedChangeListener;
-Landroid/widget/RatingBar;->mOnRatingBarChangeListener:Landroid/widget/RatingBar$OnRatingBarChangeListener;
 Landroid/widget/RelativeLayout$DependencyGraph$Node;-><init>()V
-Landroid/widget/RelativeLayout$LayoutParams;->mBottom:I
-Landroid/widget/RelativeLayout$LayoutParams;->mLeft:I
-Landroid/widget/RelativeLayout$LayoutParams;->mRight:I
-Landroid/widget/RelativeLayout$LayoutParams;->mTop:I
-Landroid/widget/RelativeLayout;->mGravity:I
-Landroid/widget/RemoteViews$Action;->mergeBehavior()I
-Landroid/widget/RemoteViews$Action;->viewId:I
-Landroid/widget/RemoteViews$BitmapCache;->mBitmaps:Ljava/util/ArrayList;
-Landroid/widget/RemoteViews$BitmapReflectionAction;->bitmap:Landroid/graphics/Bitmap;
-Landroid/widget/RemoteViews$BitmapReflectionAction;->methodName:Ljava/lang/String;
 Landroid/widget/RemoteViews$OnClickHandler;-><init>()V
-Landroid/widget/RemoteViews$OnClickHandler;->onClickHandler(Landroid/view/View;Landroid/app/PendingIntent;Landroid/content/Intent;)Z
-Landroid/widget/RemoteViews$ReflectionAction;->methodName:Ljava/lang/String;
-Landroid/widget/RemoteViews$ReflectionAction;->value:Ljava/lang/Object;
-Landroid/widget/RemoteViews$SetOnClickPendingIntent;->pendingIntent:Landroid/app/PendingIntent;
-Landroid/widget/RemoteViews$SetPendingIntentTemplate;->pendingIntentTemplate:Landroid/app/PendingIntent;
-Landroid/widget/RemoteViews$ViewGroupActionAdd;->mNestedViews:Landroid/widget/RemoteViews;
-Landroid/widget/RemoteViews;->addView(ILandroid/widget/RemoteViews;I)V
-Landroid/widget/RemoteViews;->estimateMemoryUsage()I
-Landroid/widget/RemoteViews;->mActions:Ljava/util/ArrayList;
-Landroid/widget/RemoteViews;->mApplication:Landroid/content/pm/ApplicationInfo;
-Landroid/widget/RemoteViews;->mBitmapCache:Landroid/widget/RemoteViews$BitmapCache;
-Landroid/widget/RemoteViews;->mergeRemoteViews(Landroid/widget/RemoteViews;)V
-Landroid/widget/RemoteViews;->mLayoutId:I
-Landroid/widget/RemoteViews;->mPortrait:Landroid/widget/RemoteViews;
-Landroid/widget/RemoteViews;->setIsWidgetCollectionChild(Z)V
-Landroid/widget/RemoteViews;->setRemoteAdapter(ILjava/util/ArrayList;I)V
-Landroid/widget/RemoteViewsAdapter;->getRemoteViewsServiceIntent()Landroid/content/Intent;
-Landroid/widget/RemoteViewsAdapter;->isDataReady()Z
-Landroid/widget/RemoteViewsAdapter;->mCache:Landroid/widget/RemoteViewsAdapter$FixedSizeRemoteViewsCache;
-Landroid/widget/RemoteViewsAdapter;->mWorkerThread:Landroid/os/HandlerThread;
-Landroid/widget/RemoteViewsAdapter;->saveRemoteViewsCache()V
-Landroid/widget/RemoteViewsAdapter;->setRemoteViewsOnClickHandler(Landroid/widget/RemoteViews$OnClickHandler;)V
-Landroid/widget/RemoteViewsAdapter;->setVisibleRangeHint(II)V
 Landroid/widget/ScrollBarDrawable;-><init>()V
-Landroid/widget/ScrollBarDrawable;->mVerticalThumb:Landroid/graphics/drawable/Drawable;
-Landroid/widget/ScrollBarDrawable;->setHorizontalThumbDrawable(Landroid/graphics/drawable/Drawable;)V
-Landroid/widget/ScrollBarDrawable;->setVerticalThumbDrawable(Landroid/graphics/drawable/Drawable;)V
-Landroid/widget/Scroller;->DECELERATION_RATE:F
-Landroid/widget/Scroller;->INFLEXION:F
-Landroid/widget/Scroller;->mDeceleration:F
-Landroid/widget/Scroller;->mDuration:I
-Landroid/widget/Scroller;->mInterpolator:Landroid/view/animation/Interpolator;
-Landroid/widget/Scroller;->mPhysicalCoeff:F
-Landroid/widget/ScrollView;->canScroll()Z
-Landroid/widget/ScrollView;->endDrag()V
-Landroid/widget/ScrollView;->mChildToScrollTo:Landroid/view/View;
-Landroid/widget/ScrollView;->mEdgeGlowBottom:Landroid/widget/EdgeEffect;
-Landroid/widget/ScrollView;->mEdgeGlowTop:Landroid/widget/EdgeEffect;
-Landroid/widget/ScrollView;->mFlingStrictSpan:Landroid/os/StrictMode$Span;
-Landroid/widget/ScrollView;->mIsBeingDragged:Z
-Landroid/widget/ScrollView;->mLastMotionY:I
-Landroid/widget/ScrollView;->mLastScroll:J
-Landroid/widget/ScrollView;->mMinimumVelocity:I
-Landroid/widget/ScrollView;->mOverflingDistance:I
-Landroid/widget/ScrollView;->mOverscrollDistance:I
-Landroid/widget/ScrollView;->mScroller:Landroid/widget/OverScroller;
-Landroid/widget/ScrollView;->mVelocityTracker:Landroid/view/VelocityTracker;
-Landroid/widget/SearchView$SearchAutoComplete;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Landroid/widget/SearchView;->mClearingFocus:Z
-Landroid/widget/SearchView;->mCloseButton:Landroid/widget/ImageView;
-Landroid/widget/SearchView;->mCollapsedImeOptions:I
-Landroid/widget/SearchView;->mExpandedInActionView:Z
-Landroid/widget/SearchView;->mIconified:Z
-Landroid/widget/SearchView;->mIconifiedByDefault:Z
-Landroid/widget/SearchView;->mOnClickListener:Landroid/view/View$OnClickListener;
-Landroid/widget/SearchView;->mOnItemClickListener:Landroid/widget/AdapterView$OnItemClickListener;
-Landroid/widget/SearchView;->mOnQueryChangeListener:Landroid/widget/SearchView$OnQueryTextListener;
-Landroid/widget/SearchView;->mSearchButton:Landroid/widget/ImageView;
-Landroid/widget/SearchView;->mSearchEditFrame:Landroid/view/View;
-Landroid/widget/SearchView;->mSearchHintIcon:Landroid/graphics/drawable/Drawable;
-Landroid/widget/SearchView;->mSearchPlate:Landroid/view/View;
-Landroid/widget/SearchView;->mSearchSrcTextView:Landroid/widget/SearchView$SearchAutoComplete;
-Landroid/widget/SearchView;->mSubmitArea:Landroid/view/View;
-Landroid/widget/SearchView;->mSuggestionsAdapter:Landroid/widget/CursorAdapter;
-Landroid/widget/SearchView;->mUserQuery:Ljava/lang/CharSequence;
-Landroid/widget/SearchView;->mVoiceButton:Landroid/widget/ImageView;
-Landroid/widget/SearchView;->mVoiceButtonEnabled:Z
-Landroid/widget/SearchView;->onCloseClicked()V
-Landroid/widget/SearchView;->setQuery(Ljava/lang/CharSequence;)V
-Landroid/widget/SearchView;->updateSubmitArea()V
-Landroid/widget/SearchView;->updateSubmitButton(Z)V
-Landroid/widget/SearchView;->updateViewsVisibility(Z)V
-Landroid/widget/SeekBar;->mOnSeekBarChangeListener:Landroid/widget/SeekBar$OnSeekBarChangeListener;
-Landroid/widget/SeekBar;->onProgressRefresh(FZI)V
-Landroid/widget/SimpleAdapter;->mData:Ljava/util/List;
-Landroid/widget/SimpleCursorAdapter;->mFrom:[I
-Landroid/widget/SimpleCursorAdapter;->mTo:[I
-Landroid/widget/SlidingDrawer;->mTopOffset:I
-Landroid/widget/SlidingDrawer;->mTouchDelta:I
-Landroid/widget/SlidingDrawer;->mTracking:Z
-Landroid/widget/SlidingDrawer;->mVelocityTracker:Landroid/view/VelocityTracker;
-Landroid/widget/SlidingDrawer;->prepareContent()V
-Landroid/widget/SlidingDrawer;->prepareTracking(I)V
-Landroid/widget/Spinner$DialogPopup;->isShowing()Z
-Landroid/widget/Spinner$SpinnerPopup;->isShowing()Z
-Landroid/widget/Spinner;->mForwardingListener:Landroid/widget/ForwardingListener;
-Landroid/widget/Spinner;->mPopup:Landroid/widget/Spinner$SpinnerPopup;
-Landroid/widget/Spinner;->setOnItemClickListenerInt(Landroid/widget/AdapterView$OnItemClickListener;)V
-Landroid/widget/Switch;->cancelPositionAnimator()V
-Landroid/widget/Switch;->mOffLayout:Landroid/text/Layout;
-Landroid/widget/Switch;->mOnLayout:Landroid/text/Layout;
-Landroid/widget/Switch;->mSwitchHeight:I
-Landroid/widget/Switch;->mSwitchMinWidth:I
-Landroid/widget/Switch;->mSwitchWidth:I
-Landroid/widget/Switch;->mThumbDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/Switch;->mThumbWidth:I
-Landroid/widget/Switch;->mTrackDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/widget/Switch;->setThumbPosition(F)V
-Landroid/widget/TabHost$IntentContentStrategy;->getContentView()Landroid/view/View;
-Landroid/widget/TabHost$IntentContentStrategy;->tabClosed()V
-Landroid/widget/TabHost$TabSpec;->mContentStrategy:Landroid/widget/TabHost$ContentStrategy;
-Landroid/widget/TabHost$TabSpec;->mIndicatorStrategy:Landroid/widget/TabHost$IndicatorStrategy;
-Landroid/widget/TabHost;->mCurrentTab:I
-Landroid/widget/TabHost;->mOnTabChangeListener:Landroid/widget/TabHost$OnTabChangeListener;
-Landroid/widget/TabHost;->mTabSpecs:Ljava/util/List;
-Landroid/widget/TabWidget;->mDrawBottomStrips:Z
-Landroid/widget/TabWidget;->mSelectedTab:I
-Landroid/widget/TabWidget;->setTabSelectionListener(Landroid/widget/TabWidget$OnTabSelectionChanged;)V
-Landroid/widget/TextClock;->getFormat()Ljava/lang/CharSequence;
-Landroid/widget/TextClock;->onTimeChanged()V
-Landroid/widget/TextView$SavedState;->text:Ljava/lang/CharSequence;
-Landroid/widget/TextView;->assumeLayout()V
-Landroid/widget/TextView;->bringTextIntoView()Z
-Landroid/widget/TextView;->canPaste()Z
-Landroid/widget/TextView;->checkForRelayout()V
-Landroid/widget/TextView;->compressText(F)Z
-Landroid/widget/TextView;->createEditorIfNeeded()V
-Landroid/widget/TextView;->deleteText_internal(II)V
-Landroid/widget/TextView;->getHintLayout()Landroid/text/Layout;
-Landroid/widget/TextView;->getHorizontallyScrolling()Z
-Landroid/widget/TextView;->getIterableTextForAccessibility()Ljava/lang/CharSequence;
-Landroid/widget/TextView;->getLayoutAlignment()Landroid/text/Layout$Alignment;
-Landroid/widget/TextView;->getLineAtCoordinate(F)I
-Landroid/widget/TextView;->getTextDirectionHeuristic()Landroid/text/TextDirectionHeuristic;
-Landroid/widget/TextView;->getTextForAccessibility()Ljava/lang/CharSequence;
-Landroid/widget/TextView;->getTextServicesLocale(Z)Ljava/util/Locale;
-Landroid/widget/TextView;->getTransformedText(II)Ljava/lang/CharSequence;
-Landroid/widget/TextView;->getUpdatedHighlightPath()Landroid/graphics/Path;
-Landroid/widget/TextView;->getVerticalOffset(Z)I
-Landroid/widget/TextView;->isSingleLine()Z
-Landroid/widget/TextView;->isTextEditable()Z
-Landroid/widget/TextView;->LINES:I
-Landroid/widget/TextView;->makeNewLayout(IILandroid/text/BoringLayout$Metrics;Landroid/text/BoringLayout$Metrics;IZ)V
-Landroid/widget/TextView;->mAllowTransformationLengthChange:Z
-Landroid/widget/TextView;->mBoring:Landroid/text/BoringLayout$Metrics;
-Landroid/widget/TextView;->mBufferType:Landroid/widget/TextView$BufferType;
-Landroid/widget/TextView;->mChangeWatcher:Landroid/widget/TextView$ChangeWatcher;
-Landroid/widget/TextView;->mCharWrapper:Landroid/widget/TextView$CharWrapper;
-Landroid/widget/TextView;->mCurHintTextColor:I
-Landroid/widget/TextView;->mCursorDrawableRes:I
-Landroid/widget/TextView;->mCurTextColor:I
-Landroid/widget/TextView;->mDesiredHeightAtMeasure:I
-Landroid/widget/TextView;->mDrawables:Landroid/widget/TextView$Drawables;
-Landroid/widget/TextView;->mEditableFactory:Landroid/text/Editable$Factory;
-Landroid/widget/TextView;->mEditor:Landroid/widget/Editor;
-Landroid/widget/TextView;->mGravity:I
-Landroid/widget/TextView;->mHighlightColor:I
-Landroid/widget/TextView;->mHighlightPaint:Landroid/graphics/Paint;
-Landroid/widget/TextView;->mHighlightPathBogus:Z
-Landroid/widget/TextView;->mHintBoring:Landroid/text/BoringLayout$Metrics;
-Landroid/widget/TextView;->mHintLayout:Landroid/text/Layout;
-Landroid/widget/TextView;->mHorizontallyScrolling:Z
-Landroid/widget/TextView;->mIncludePad:Z
-Landroid/widget/TextView;->mLayout:Landroid/text/Layout;
-Landroid/widget/TextView;->mListeners:Ljava/util/ArrayList;
-Landroid/widget/TextView;->mMarquee:Landroid/widget/TextView$Marquee;
-Landroid/widget/TextView;->mMarqueeFadeMode:I
-Landroid/widget/TextView;->mMaximum:I
-Landroid/widget/TextView;->mMaxMode:I
-Landroid/widget/TextView;->mMaxWidth:I
-Landroid/widget/TextView;->mMaxWidthMode:I
-Landroid/widget/TextView;->mMinimum:I
-Landroid/widget/TextView;->mMinMode:I
-Landroid/widget/TextView;->mMinWidth:I
-Landroid/widget/TextView;->mMinWidthMode:I
-Landroid/widget/TextView;->mOldMaximum:I
-Landroid/widget/TextView;->mOldMaxMode:I
-Landroid/widget/TextView;->mRestartMarquee:Z
-Landroid/widget/TextView;->mSavedHintLayout:Landroid/text/BoringLayout;
-Landroid/widget/TextView;->mSavedLayout:Landroid/text/BoringLayout;
-Landroid/widget/TextView;->mSavedMarqueeModeLayout:Landroid/text/Layout;
-Landroid/widget/TextView;->mShadowDx:F
-Landroid/widget/TextView;->mShadowDy:F
-Landroid/widget/TextView;->mShadowRadius:F
-Landroid/widget/TextView;->mSingleLine:Z
-Landroid/widget/TextView;->mSpacingAdd:F
-Landroid/widget/TextView;->mSpacingMult:F
-Landroid/widget/TextView;->mSpannableFactory:Landroid/text/Spannable$Factory;
-Landroid/widget/TextView;->mText:Ljava/lang/CharSequence;
-Landroid/widget/TextView;->mTextDir:Landroid/text/TextDirectionHeuristic;
-Landroid/widget/TextView;->mTextPaint:Landroid/text/TextPaint;
-Landroid/widget/TextView;->mTextSelectHandleLeftRes:I
-Landroid/widget/TextView;->mTextSelectHandleRes:I
-Landroid/widget/TextView;->mTextSelectHandleRightRes:I
-Landroid/widget/TextView;->mTransformed:Ljava/lang/CharSequence;
-Landroid/widget/TextView;->mUserSetTextScaleX:Z
-Landroid/widget/TextView;->nullLayouts()V
-Landroid/widget/TextView;->setInputType(IZ)V
-Landroid/widget/TextView;->setRawTextSize(FZ)V
-Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;Landroid/widget/TextView$BufferType;ZI)V
-Landroid/widget/TextView;->startMarquee()V
-Landroid/widget/TextView;->startStopMarquee(Z)V
-Landroid/widget/TextView;->stopTextActionMode()V
-Landroid/widget/TextView;->updateTextServicesLocaleLocked()V
-Landroid/widget/TextView;->viewportToContentVerticalOffset()I
-Landroid/widget/TimePicker;->mDelegate:Landroid/widget/TimePicker$TimePickerDelegate;
-Landroid/widget/Toast$TN;->handleHide()V
-Landroid/widget/Toast$TN;->mGravity:I
-Landroid/widget/Toast$TN;->mNextView:Landroid/view/View;
-Landroid/widget/Toast$TN;->mParams:Landroid/view/WindowManager$LayoutParams;
-Landroid/widget/Toast$TN;->mView:Landroid/view/View;
-Landroid/widget/Toast$TN;->mY:I
-Landroid/widget/Toast$TN;->show(Landroid/os/IBinder;)V
-Landroid/widget/Toast;->getService()Landroid/app/INotificationManager;
-Landroid/widget/Toast;->getWindowParams()Landroid/view/WindowManager$LayoutParams;
-Landroid/widget/Toast;->mDuration:I
-Landroid/widget/Toast;->mTN:Landroid/widget/Toast$TN;
-Landroid/widget/Toast;->sService:Landroid/app/INotificationManager;
-Landroid/widget/Toolbar;->mNavButtonView:Landroid/widget/ImageButton;
-Landroid/widget/Toolbar;->mTitleMarginBottom:I
-Landroid/widget/Toolbar;->mTitleMarginEnd:I
-Landroid/widget/Toolbar;->mTitleMarginStart:I
-Landroid/widget/Toolbar;->mTitleMarginTop:I
-Landroid/widget/Toolbar;->mTitleTextView:Landroid/widget/TextView;
-Landroid/widget/VideoView2$OnViewTypeChangedListener;->onViewTypeChanged(Landroid/view/View;I)V
-Landroid/widget/VideoView2;->getMediaController()Landroid/media/session/MediaController;
-Landroid/widget/VideoView2;->setOnViewTypeChangedListener(Landroid/widget/VideoView2$OnViewTypeChangedListener;)V
-Landroid/widget/VideoView2;->setVideoPath(Ljava/lang/String;)V
-Landroid/widget/VideoView;->mCurrentBufferPercentage:I
-Landroid/widget/VideoView;->mCurrentState:I
-Landroid/widget/VideoView;->mErrorListener:Landroid/media/MediaPlayer$OnErrorListener;
-Landroid/widget/VideoView;->mHeaders:Ljava/util/Map;
-Landroid/widget/VideoView;->mMediaController:Landroid/widget/MediaController;
-Landroid/widget/VideoView;->mMediaPlayer:Landroid/media/MediaPlayer;
-Landroid/widget/VideoView;->mPreparedListener:Landroid/media/MediaPlayer$OnPreparedListener;
-Landroid/widget/VideoView;->mSHCallback:Landroid/view/SurfaceHolder$Callback;
-Landroid/widget/VideoView;->mSurfaceHolder:Landroid/view/SurfaceHolder;
-Landroid/widget/VideoView;->mTargetState:I
-Landroid/widget/VideoView;->mUri:Landroid/net/Uri;
-Landroid/widget/VideoView;->mVideoHeight:I
-Landroid/widget/VideoView;->mVideoWidth:I
-Landroid/widget/VideoView;->release(Z)V
-Landroid/widget/VideoView;->STATE_IDLE:I
-Landroid/widget/ViewAnimator;->mFirstTime:Z
-Landroid/widget/ViewAnimator;->mWhichChild:I
-Landroid/widget/ViewAnimator;->showOnly(IZ)V
-Landroid/widget/ViewFlipper;->mUserPresent:Z
-Landroid/widget/ViewFlipper;->updateRunning(Z)V
-Landroid/widget/ZoomControls;->mZoomIn:Landroid/widget/ZoomButton;
-Landroid/widget/ZoomControls;->mZoomOut:Landroid/widget/ZoomButton;
 Lcom/android/ims/ImsConfigListener$Stub;-><init>()V
 Lcom/android/ims/internal/IImsCallSession$Stub;-><init>()V
 Lcom/android/ims/internal/IImsCallSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsCallSession;
@@ -7356,116 +1691,7 @@
 Lcom/android/ims/internal/IImsVideoCallCallback;->receiveSessionModifyResponse(ILandroid/telecom/VideoProfile;Landroid/telecom/VideoProfile;)V
 Lcom/android/ims/internal/IImsVideoCallProvider$Stub;-><init>()V
 Lcom/android/ims/internal/IImsVideoCallProvider;->setCallback(Lcom/android/ims/internal/IImsVideoCallCallback;)V
-Lcom/android/ims/internal/uce/common/CapInfo;-><init>()V
-Lcom/android/ims/internal/uce/common/CapInfo;->setCapTimestamp(J)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setCdViaPresenceSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setExts([Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFtHttpSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFtSnFSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFtSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFtThumbSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFullSnFGroupChatSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setGeoPullFtSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setGeoPullSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setGeoPushSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setImSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setIpVideoSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setIpVoiceSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setIsSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setRcsIpVideoCallSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setRcsIpVideoOnlyCallSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setRcsIpVoiceCallSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setSmSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setSpSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setVsDuringCSSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setVsSupported(Z)V
-Lcom/android/ims/internal/uce/common/StatusCode;-><init>()V
-Lcom/android/ims/internal/uce/common/StatusCode;->setStatusCode(I)V
-Lcom/android/ims/internal/uce/common/UceLong;->getUceLong()J
-Lcom/android/ims/internal/uce/common/UceLong;->setUceLong(J)V
-Lcom/android/ims/internal/uce/presence/PresCmdId;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresCmdId;->setCmdId(I)V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setCmdId(Lcom/android/ims/internal/uce/presence/PresCmdId;)V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setRequestId(I)V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setStatus(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setUserData(I)V
-Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;->setPublishTrigeerType(I)V
-Lcom/android/ims/internal/uce/presence/PresResInfo;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresResInfo;->setDisplayName(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInfo;->setInstanceInfo(Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;)V
-Lcom/android/ims/internal/uce/presence/PresResInfo;->setResUri(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setPresentityUri(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setReason(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setResId(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setResInstanceState(I)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setTupleInfo([Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setFullState(Z)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setListName(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setPresSubscriptionState(Lcom/android/ims/internal/uce/presence/PresSubscriptionState;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setRequestId(I)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setSubscriptionExpireTime(I)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setSubscriptionTerminatedReason(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setUri(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setVersion(I)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setCmdId(Lcom/android/ims/internal/uce/presence/PresCmdId;)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setReasonPhrase(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setRequestId(I)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setRetryAfter(I)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setSipResponseCode(I)V
-Lcom/android/ims/internal/uce/presence/PresSubscriptionState;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresSubscriptionState;->setPresSubscriptionState(I)V
-Lcom/android/ims/internal/uce/presence/PresTupleInfo;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setContactUri(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setFeatureTag(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setTimestamp(Ljava/lang/String;)V
 Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
-Lcom/android/internal/app/AlertController$AlertParams;-><init>(Landroid/content/Context;)V
-Lcom/android/internal/app/AlertController$AlertParams;->apply(Lcom/android/internal/app/AlertController;)V
-Lcom/android/internal/app/AlertController$AlertParams;->mAdapter:Landroid/widget/ListAdapter;
-Lcom/android/internal/app/AlertController$AlertParams;->mCancelable:Z
-Lcom/android/internal/app/AlertController$AlertParams;->mCheckedItem:I
-Lcom/android/internal/app/AlertController$AlertParams;->mCheckedItems:[Z
-Lcom/android/internal/app/AlertController$AlertParams;->mContext:Landroid/content/Context;
-Lcom/android/internal/app/AlertController$AlertParams;->mCursor:Landroid/database/Cursor;
-Lcom/android/internal/app/AlertController$AlertParams;->mCustomTitleView:Landroid/view/View;
-Lcom/android/internal/app/AlertController$AlertParams;->mIcon:Landroid/graphics/drawable/Drawable;
-Lcom/android/internal/app/AlertController$AlertParams;->mInflater:Landroid/view/LayoutInflater;
-Lcom/android/internal/app/AlertController$AlertParams;->mIsCheckedColumn:Ljava/lang/String;
-Lcom/android/internal/app/AlertController$AlertParams;->mIsMultiChoice:Z
-Lcom/android/internal/app/AlertController$AlertParams;->mIsSingleChoice:Z
-Lcom/android/internal/app/AlertController$AlertParams;->mItems:[Ljava/lang/CharSequence;
-Lcom/android/internal/app/AlertController$AlertParams;->mLabelColumn:Ljava/lang/String;
-Lcom/android/internal/app/AlertController$AlertParams;->mNeutralButtonListener:Landroid/content/DialogInterface$OnClickListener;
-Lcom/android/internal/app/AlertController$AlertParams;->mNeutralButtonText:Ljava/lang/CharSequence;
-Lcom/android/internal/app/AlertController$AlertParams;->mOnCancelListener:Landroid/content/DialogInterface$OnCancelListener;
-Lcom/android/internal/app/AlertController$AlertParams;->mOnCheckboxClickListener:Landroid/content/DialogInterface$OnMultiChoiceClickListener;
-Lcom/android/internal/app/AlertController$AlertParams;->mOnClickListener:Landroid/content/DialogInterface$OnClickListener;
-Lcom/android/internal/app/AlertController$AlertParams;->mOnDismissListener:Landroid/content/DialogInterface$OnDismissListener;
-Lcom/android/internal/app/AlertController$AlertParams;->mOnItemSelectedListener:Landroid/widget/AdapterView$OnItemSelectedListener;
-Lcom/android/internal/app/AlertController$AlertParams;->mOnKeyListener:Landroid/content/DialogInterface$OnKeyListener;
-Lcom/android/internal/app/AlertController$RecycleListView;-><init>(Landroid/content/Context;)V
-Lcom/android/internal/app/AlertController$RecycleListView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
-Lcom/android/internal/app/AlertController;-><init>(Landroid/content/Context;Landroid/content/DialogInterface;Landroid/view/Window;)V
-Lcom/android/internal/app/AlertController;->getListView()Landroid/widget/ListView;
-Lcom/android/internal/app/AlertController;->installContent()V
-Lcom/android/internal/app/AlertController;->mCustomTitleView:Landroid/view/View;
-Lcom/android/internal/app/AlertController;->mForceInverseBackground:Z
-Lcom/android/internal/app/AlertController;->mTitle:Ljava/lang/CharSequence;
-Lcom/android/internal/app/AlertController;->mView:Landroid/view/View;
-Lcom/android/internal/app/AlertController;->onKeyDown(ILandroid/view/KeyEvent;)Z
-Lcom/android/internal/app/AlertController;->onKeyUp(ILandroid/view/KeyEvent;)Z
-Lcom/android/internal/app/AlertController;->setButton(ILjava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;Landroid/os/Message;)V
-Lcom/android/internal/app/AlertController;->setCustomTitle(Landroid/view/View;)V
-Lcom/android/internal/app/AlertController;->setIcon(I)V
-Lcom/android/internal/app/AlertController;->setIcon(Landroid/graphics/drawable/Drawable;)V
-Lcom/android/internal/app/AlertController;->setMessage(Ljava/lang/CharSequence;)V
-Lcom/android/internal/app/AlertController;->setTitle(Ljava/lang/CharSequence;)V
-Lcom/android/internal/app/AlertController;->setView(Landroid/view/View;)V
 Lcom/android/internal/app/IAppOpsCallback$Stub;-><init>()V
 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
@@ -7536,182 +1762,13 @@
 Lcom/android/internal/backup/IBackupTransport;->requestBackupTime()J
 Lcom/android/internal/backup/IBackupTransport;->startRestore(J[Landroid/content/pm/PackageInfo;)I
 Lcom/android/internal/backup/IBackupTransport;->transportDirName()Ljava/lang/String;
-Lcom/android/internal/content/PackageMonitor;->isPackageDisappearing(Ljava/lang/String;)I
-Lcom/android/internal/content/PackageMonitor;->isPackageModified(Ljava/lang/String;)Z
-Lcom/android/internal/content/PackageMonitor;->onPackageChanged(Ljava/lang/String;I[Ljava/lang/String;)Z
-Lcom/android/internal/content/PackageMonitor;->onPackageRemoved(Ljava/lang/String;I)V
-Lcom/android/internal/content/PackageMonitor;->register(Landroid/content/Context;Landroid/os/Looper;Z)V
-Lcom/android/internal/content/ReferrerIntent;-><init>(Landroid/content/Intent;Ljava/lang/String;)V
-Lcom/android/internal/content/ReferrerIntent;->mReferrer:Ljava/lang/String;
 Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
 Lcom/android/internal/logging/MetricsLogger;-><init>()V
-Lcom/android/internal/logging/MetricsLogger;->write(Landroid/metrics/LogMaker;)V
 Lcom/android/internal/net/LegacyVpnInfo;-><init>()V
-Lcom/android/internal/net/LegacyVpnInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/net/LegacyVpnInfo;->key:Ljava/lang/String;
-Lcom/android/internal/net/LegacyVpnInfo;->state:I
 Lcom/android/internal/net/VpnConfig;-><init>()V
-Lcom/android/internal/net/VpnProfile;-><init>(Landroid/os/Parcel;)V
-Lcom/android/internal/net/VpnProfile;->decode(Ljava/lang/String;[B)Lcom/android/internal/net/VpnProfile;
-Lcom/android/internal/net/VpnProfile;->key:Ljava/lang/String;
-Lcom/android/internal/net/VpnProfile;->name:Ljava/lang/String;
-Lcom/android/internal/net/VpnProfile;->saveLogin:Z
-Lcom/android/internal/net/VpnProfile;->server:Ljava/lang/String;
-Lcom/android/internal/net/VpnProfile;->type:I
-Lcom/android/internal/net/VpnProfile;->username:Ljava/lang/String;
-Lcom/android/internal/os/AtomicFile;-><init>(Ljava/io/File;)V
-Lcom/android/internal/os/AtomicFile;->failWrite(Ljava/io/FileOutputStream;)V
-Lcom/android/internal/os/AtomicFile;->finishWrite(Ljava/io/FileOutputStream;)V
-Lcom/android/internal/os/AtomicFile;->getBaseFile()Ljava/io/File;
-Lcom/android/internal/os/AtomicFile;->openAppend()Ljava/io/FileOutputStream;
-Lcom/android/internal/os/AtomicFile;->openRead()Ljava/io/FileInputStream;
-Lcom/android/internal/os/AtomicFile;->readFully()[B
-Lcom/android/internal/os/AtomicFile;->startWrite()Ljava/io/FileOutputStream;
-Lcom/android/internal/os/AtomicFile;->truncate()V
-Lcom/android/internal/os/BatterySipper$DrainType;->APP:Lcom/android/internal/os/BatterySipper$DrainType;
 Lcom/android/internal/os/BatterySipper$DrainType;->values()[Lcom/android/internal/os/BatterySipper$DrainType;
-Lcom/android/internal/os/BatterySipper;-><init>(Lcom/android/internal/os/BatterySipper$DrainType;Landroid/os/BatteryStats$Uid;D)V
-Lcom/android/internal/os/BatterySipper;->add(Lcom/android/internal/os/BatterySipper;)V
-Lcom/android/internal/os/BatterySipper;->cpuFgTimeMs:J
-Lcom/android/internal/os/BatterySipper;->cpuPowerMah:D
-Lcom/android/internal/os/BatterySipper;->cpuTimeMs:J
-Lcom/android/internal/os/BatterySipper;->drainType:Lcom/android/internal/os/BatterySipper$DrainType;
-Lcom/android/internal/os/BatterySipper;->getPackages()[Ljava/lang/String;
-Lcom/android/internal/os/BatterySipper;->getUid()I
-Lcom/android/internal/os/BatterySipper;->gpsTimeMs:J
-Lcom/android/internal/os/BatterySipper;->mPackages:[Ljava/lang/String;
-Lcom/android/internal/os/BatterySipper;->packageWithHighestDrain:Ljava/lang/String;
-Lcom/android/internal/os/BatterySipper;->totalPowerMah:D
-Lcom/android/internal/os/BatterySipper;->uidObj:Landroid/os/BatteryStats$Uid;
-Lcom/android/internal/os/BatterySipper;->usageTimeMs:J
-Lcom/android/internal/os/BatterySipper;->userId:I
-Lcom/android/internal/os/BatterySipper;->wakeLockTimeMs:J
-Lcom/android/internal/os/BatterySipper;->wifiRunningTimeMs:J
-Lcom/android/internal/os/BatteryStatsHelper;-><init>(Landroid/content/Context;)V
-Lcom/android/internal/os/BatteryStatsHelper;-><init>(Landroid/content/Context;Z)V
-Lcom/android/internal/os/BatteryStatsHelper;-><init>(Landroid/content/Context;ZZ)V
-Lcom/android/internal/os/BatteryStatsHelper;->clearStats()V
-Lcom/android/internal/os/BatteryStatsHelper;->create(Landroid/os/Bundle;)V
-Lcom/android/internal/os/BatteryStatsHelper;->dropFile(Landroid/content/Context;Ljava/lang/String;)V
-Lcom/android/internal/os/BatteryStatsHelper;->getBatteryBroadcast()Landroid/content/Intent;
-Lcom/android/internal/os/BatteryStatsHelper;->getMaxPower()D
-Lcom/android/internal/os/BatteryStatsHelper;->getStats()Landroid/os/BatteryStats;
-Lcom/android/internal/os/BatteryStatsHelper;->getTotalPower()D
-Lcom/android/internal/os/BatteryStatsHelper;->getUsageList()Ljava/util/List;
-Lcom/android/internal/os/BatteryStatsHelper;->load()V
-Lcom/android/internal/os/BatteryStatsHelper;->mBatteryInfo:Lcom/android/internal/app/IBatteryStats;
-Lcom/android/internal/os/BatteryStatsHelper;->mPowerProfile:Lcom/android/internal/os/PowerProfile;
-Lcom/android/internal/os/BatteryStatsHelper;->mUsageList:Ljava/util/List;
-Lcom/android/internal/os/BatteryStatsHelper;->refreshStats(II)V
-Lcom/android/internal/os/BatteryStatsHelper;->refreshStats(ILandroid/util/SparseArray;)V
-Lcom/android/internal/os/BatteryStatsHelper;->refreshStats(ILjava/util/List;)V
-Lcom/android/internal/os/BatteryStatsHelper;->storeState()V
-Lcom/android/internal/os/BatteryStatsImpl$Counter;->mCount:Ljava/util/concurrent/atomic/AtomicInteger;
-Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;->detach()V
-Lcom/android/internal/os/BatteryStatsImpl$Timer;->getCountLocked(I)I
-Lcom/android/internal/os/BatteryStatsImpl$Timer;->getTotalTimeLocked(JI)J
-Lcom/android/internal/os/BatteryStatsImpl$Timer;->writeTimerToParcel(Landroid/os/Parcel;Lcom/android/internal/os/BatteryStatsImpl$Timer;J)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;->getBatteryStats()Lcom/android/internal/os/BatteryStatsImpl;
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;->startLaunchedLocked()V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;->startRunningLocked()V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;->stopLaunchedLocked()V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;->stopRunningLocked()V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->addCpuTimeLocked(II)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->addForegroundTimeLocked(J)V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->getForegroundTime(I)J
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->getStarts(I)I
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->getSystemTime(I)J
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->getUserTime(I)J
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;->incStartsLocked()V
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Sensor;->getHandle()I
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Sensor;->getSensorTime()Lcom/android/internal/os/BatteryStatsImpl$Timer;
-Lcom/android/internal/os/BatteryStatsImpl$Uid$Wakelock;->getWakeTime(I)Lcom/android/internal/os/BatteryStatsImpl$Timer;
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getProcessStats()Landroid/util/ArrayMap;
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getSensorStats()Landroid/util/SparseArray;
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getUid()I
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getWakelockStats()Landroid/util/ArrayMap;
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getWifiRunningTime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl$Uid;->getWifiScanTime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;-><init>(Landroid/os/Parcel;)V
-Lcom/android/internal/os/BatteryStatsImpl;->commitPendingDataToDisk()V
-Lcom/android/internal/os/BatteryStatsImpl;->computeBatteryRealtime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;->computeBatteryTimeRemaining(J)J
-Lcom/android/internal/os/BatteryStatsImpl;->computeBatteryUptime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/os/BatteryStatsImpl;->getAwakeTimeBattery()J
-Lcom/android/internal/os/BatteryStatsImpl;->getAwakeTimePlugged()J
-Lcom/android/internal/os/BatteryStatsImpl;->getBatteryRealtime(J)J
-Lcom/android/internal/os/BatteryStatsImpl;->getDischargeAmount(I)I
-Lcom/android/internal/os/BatteryStatsImpl;->getDischargeAmountScreenOff()I
-Lcom/android/internal/os/BatteryStatsImpl;->getDischargeAmountScreenOn()I
-Lcom/android/internal/os/BatteryStatsImpl;->getGlobalWifiRunningTime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;->getKernelWakelockStats()Ljava/util/Map;
-Lcom/android/internal/os/BatteryStatsImpl;->getMobileRadioActiveTime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;->getNetworkActivityBytes(II)J
-Lcom/android/internal/os/BatteryStatsImpl;->getNextHistoryLocked(Landroid/os/BatteryStats$HistoryItem;)Z
-Lcom/android/internal/os/BatteryStatsImpl;->getPackageStatsLocked(ILjava/lang/String;)Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg;
-Lcom/android/internal/os/BatteryStatsImpl;->getPhoneDataConnectionCount(II)I
-Lcom/android/internal/os/BatteryStatsImpl;->getPhoneDataConnectionTime(IJI)J
-Lcom/android/internal/os/BatteryStatsImpl;->getPhoneSignalStrengthCount(II)I
-Lcom/android/internal/os/BatteryStatsImpl;->getProcessStatsLocked(ILjava/lang/String;)Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;
-Lcom/android/internal/os/BatteryStatsImpl;->getScreenOnTime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;->getServiceStatsLocked(ILjava/lang/String;Ljava/lang/String;)Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;
-Lcom/android/internal/os/BatteryStatsImpl;->getUidStats()Landroid/util/SparseArray;
-Lcom/android/internal/os/BatteryStatsImpl;->getUidStatsLocked(I)Lcom/android/internal/os/BatteryStatsImpl$Uid;
-Lcom/android/internal/os/BatteryStatsImpl;->isOnBattery()Z
-Lcom/android/internal/os/BatteryStatsImpl;->mFullTimers:Ljava/util/ArrayList;
-Lcom/android/internal/os/BatteryStatsImpl;->mPartialTimers:Ljava/util/ArrayList;
-Lcom/android/internal/os/BatteryStatsImpl;->mWindowTimers:Ljava/util/ArrayList;
-Lcom/android/internal/os/BatteryStatsImpl;->noteAudioOffLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->noteAudioOnLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->noteFullWifiLockAcquiredLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->noteFullWifiLockReleasedLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->notePhoneDataConnectionStateLocked(IZ)V
-Lcom/android/internal/os/BatteryStatsImpl;->notePhoneOffLocked()V
-Lcom/android/internal/os/BatteryStatsImpl;->notePhoneOnLocked()V
-Lcom/android/internal/os/BatteryStatsImpl;->notePhoneSignalStrengthLocked(Landroid/telephony/SignalStrength;)V
-Lcom/android/internal/os/BatteryStatsImpl;->noteScreenBrightnessLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->noteUserActivityLocked(II)V
-Lcom/android/internal/os/BatteryStatsImpl;->noteVideoOffLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->noteVideoOnLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->noteWifiMulticastDisabledLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->noteWifiMulticastEnabledLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->readLocked()V
-Lcom/android/internal/os/BatteryStatsImpl;->removeUidStatsLocked(I)V
-Lcom/android/internal/os/BatteryStatsImpl;->startIteratingHistoryLocked()Z
-Lcom/android/internal/os/FuseAppLoop;->onCommand(IJJJI[B)V
-Lcom/android/internal/os/FuseAppLoop;->onOpen(JJ)[B
-Lcom/android/internal/os/HandlerCaller;->obtainMessage(I)Landroid/os/Message;
-Lcom/android/internal/os/HandlerCaller;->obtainMessageIO(IILjava/lang/Object;)Landroid/os/Message;
-Lcom/android/internal/os/HandlerCaller;->obtainMessageIOO(IILjava/lang/Object;Ljava/lang/Object;)Landroid/os/Message;
-Lcom/android/internal/os/HandlerCaller;->obtainMessageO(ILjava/lang/Object;)Landroid/os/Message;
-Lcom/android/internal/os/HandlerCaller;->obtainMessageOO(ILjava/lang/Object;Ljava/lang/Object;)Landroid/os/Message;
-Lcom/android/internal/os/HandlerCaller;->obtainMessageOOO(ILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Landroid/os/Message;
-Lcom/android/internal/os/HandlerCaller;->sendMessage(Landroid/os/Message;)V
 Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
 Lcom/android/internal/os/IDropBoxManagerService;->getNextEntry(Ljava/lang/String;JLjava/lang/String;)Landroid/os/DropBoxManager$Entry;
-Lcom/android/internal/os/PowerProfile;-><init>(Landroid/content/Context;)V
-Lcom/android/internal/os/PowerProfile;->getAveragePower(Ljava/lang/String;)D
-Lcom/android/internal/os/PowerProfile;->getAveragePower(Ljava/lang/String;I)D
-Lcom/android/internal/os/PowerProfile;->getBatteryCapacity()D
-Lcom/android/internal/os/PowerProfile;->getNumCpuClusters()I
-Lcom/android/internal/os/PowerProfile;->getNumSpeedStepsInCpuCluster(I)I
-Lcom/android/internal/os/PowerProfile;->POWER_BLUETOOTH_AT_CMD:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_BLUETOOTH_ON:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_CPU_ACTIVE:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_CPU_IDLE:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_GPS_ON:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_RADIO_ACTIVE:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_RADIO_ON:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_RADIO_SCANNING:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_SCREEN_FULL:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_SCREEN_ON:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_WIFI_ACTIVE:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_WIFI_ON:Ljava/lang/String;
-Lcom/android/internal/os/PowerProfile;->POWER_WIFI_SCAN:Ljava/lang/String;
-Lcom/android/internal/os/SomeArgs;->arg1:Ljava/lang/Object;
-Lcom/android/internal/os/SomeArgs;->argi2:I
-Lcom/android/internal/os/SomeArgs;->argi3:I
 Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService;
 Lcom/android/internal/policy/IKeyguardService;->doKeyguardTimeout(Landroid/os/Bundle;)V
 Lcom/android/internal/policy/IKeyguardService;->setKeyguardEnabled(Z)V
@@ -8367,40 +2424,9 @@
 Lcom/android/internal/telephony/SmsRawData;->CREATOR:Landroid/os/Parcelable$Creator;
 Lcom/android/internal/telephony/SmsRawData;->getBytes()[B
 Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/util/AsyncChannel;->cmdToString(I)Ljava/lang/String;
-Lcom/android/internal/util/AsyncChannel;->CMD_CHANNEL_FULL_CONNECTION:I
-Lcom/android/internal/util/AsyncChannel;->CMD_CHANNEL_HALF_CONNECTED:I
-Lcom/android/internal/util/AsyncChannel;->connected(Landroid/content/Context;Landroid/os/Handler;Landroid/os/Messenger;)V
-Lcom/android/internal/util/AsyncChannel;->connectSync(Landroid/content/Context;Landroid/os/Handler;Landroid/os/Messenger;)I
-Lcom/android/internal/util/AsyncChannel;->disconnect()V
-Lcom/android/internal/util/AsyncChannel;->replyToMessage(Landroid/os/Message;I)V
-Lcom/android/internal/util/AsyncChannel;->replyToMessage(Landroid/os/Message;II)V
-Lcom/android/internal/util/AsyncChannel;->replyToMessage(Landroid/os/Message;IIILjava/lang/Object;)V
-Lcom/android/internal/util/AsyncChannel;->replyToMessage(Landroid/os/Message;ILjava/lang/Object;)V
-Lcom/android/internal/util/AsyncChannel;->replyToMessage(Landroid/os/Message;Landroid/os/Message;)V
-Lcom/android/internal/util/AsyncChannel;->sendMessage(I)V
-Lcom/android/internal/util/AsyncChannel;->sendMessage(II)V
-Lcom/android/internal/util/AsyncChannel;->sendMessage(III)V
-Lcom/android/internal/util/AsyncChannel;->sendMessage(IIILjava/lang/Object;)V
-Lcom/android/internal/util/AsyncChannel;->sendMessageSynchronously(III)Landroid/os/Message;
-Lcom/android/internal/util/AsyncChannel;->sendMessageSynchronously(Landroid/os/Message;)Landroid/os/Message;
-Lcom/android/internal/util/AsyncChannel;->STATUS_SUCCESSFUL:I
-Lcom/android/internal/util/FastPrintWriter;-><init>(Ljava/io/OutputStream;)V
-Lcom/android/internal/util/JournaledFile;-><init>(Ljava/io/File;Ljava/io/File;)V
-Lcom/android/internal/util/JournaledFile;->chooseForRead()Ljava/io/File;
-Lcom/android/internal/util/JournaledFile;->chooseForWrite()Ljava/io/File;
-Lcom/android/internal/util/JournaledFile;->commit()V
-Lcom/android/internal/util/JournaledFile;->rollback()V
-Lcom/android/internal/util/XmlUtils;->convertValueToBoolean(Ljava/lang/CharSequence;Z)Z
-Lcom/android/internal/util/XmlUtils;->convertValueToInt(Ljava/lang/CharSequence;I)I
-Lcom/android/internal/util/XmlUtils;->readMapXml(Ljava/io/InputStream;)Ljava/util/HashMap;
-Lcom/android/internal/util/XmlUtils;->skipCurrentTag(Lorg/xmlpull/v1/XmlPullParser;)V
-Lcom/android/internal/util/XmlUtils;->writeMapXml(Ljava/util/Map;Ljava/io/OutputStream;)V
+Lcom/android/internal/util/HexDump;->toHexString([BZ)Ljava/lang/String;
 Lcom/android/internal/view/BaseIWindow;-><init>()V
-Lcom/android/internal/view/IInputConnectionWrapper;->mInputConnection:Landroid/view/inputmethod/InputConnection;
-Lcom/android/internal/view/IInputConnectionWrapper;->mLock:Ljava/lang/Object;
 Lcom/android/internal/view/IInputMethod$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethod;
-Lcom/android/internal/view/IInputMethod;->attachToken(Landroid/os/IBinder;)V
 Lcom/android/internal/view/IInputMethod;->bindInput(Landroid/view/inputmethod/InputBinding;)V
 Lcom/android/internal/view/IInputMethod;->hideSoftInput(ILandroid/os/ResultReceiver;)V
 Lcom/android/internal/view/IInputMethod;->setSessionEnabled(Lcom/android/internal/view/IInputMethodSession;Z)V
@@ -8412,56 +2438,7 @@
 Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;->getEnabledInputMethodList()Ljava/util/List;
 Lcom/android/internal/view/IInputMethodManager$Stub;-><init>()V
 Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager;
-Lcom/android/internal/view/IInputMethodManager;->addClient(Lcom/android/internal/view/IInputMethodClient;Lcom/android/internal/view/IInputContext;II)V
-Lcom/android/internal/view/IInputMethodManager;->removeClient(Lcom/android/internal/view/IInputMethodClient;)V
 Lcom/android/internal/view/IInputMethodSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodSession;
-Lcom/android/internal/view/InputBindResult;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/view/InputBindResult;->method:Lcom/android/internal/view/IInputMethodSession;
-Lcom/android/internal/view/menu/ActionMenuItemView;->hasText()Z
-Lcom/android/internal/view/menu/MenuBuilder$Callback;->onMenuItemSelected(Lcom/android/internal/view/menu/MenuBuilder;Landroid/view/MenuItem;)Z
-Lcom/android/internal/view/menu/MenuBuilder$Callback;->onMenuModeChange(Lcom/android/internal/view/menu/MenuBuilder;)V
-Lcom/android/internal/view/menu/MenuBuilder;-><init>(Landroid/content/Context;)V
-Lcom/android/internal/view/menu/MenuBuilder;->addMenuPresenter(Lcom/android/internal/view/menu/MenuPresenter;)V
-Lcom/android/internal/view/menu/MenuBuilder;->addMenuPresenter(Lcom/android/internal/view/menu/MenuPresenter;Landroid/content/Context;)V
-Lcom/android/internal/view/menu/MenuBuilder;->collapseItemActionView(Lcom/android/internal/view/menu/MenuItemImpl;)Z
-Lcom/android/internal/view/menu/MenuBuilder;->getContext()Landroid/content/Context;
-Lcom/android/internal/view/menu/MenuBuilder;->getHeaderIcon()Landroid/graphics/drawable/Drawable;
-Lcom/android/internal/view/menu/MenuBuilder;->getHeaderTitle()Ljava/lang/CharSequence;
-Lcom/android/internal/view/menu/MenuBuilder;->getNonActionItems()Ljava/util/ArrayList;
-Lcom/android/internal/view/menu/MenuBuilder;->getRootMenu()Lcom/android/internal/view/menu/MenuBuilder;
-Lcom/android/internal/view/menu/MenuBuilder;->getVisibleItems()Ljava/util/ArrayList;
-Lcom/android/internal/view/menu/MenuBuilder;->mContext:Landroid/content/Context;
-Lcom/android/internal/view/menu/MenuBuilder;->removeMenuPresenter(Lcom/android/internal/view/menu/MenuPresenter;)V
-Lcom/android/internal/view/menu/MenuBuilder;->setCallback(Lcom/android/internal/view/menu/MenuBuilder$Callback;)V
-Lcom/android/internal/view/menu/MenuBuilder;->setCurrentMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V
-Lcom/android/internal/view/menu/MenuBuilder;->setDefaultShowAsAction(I)Lcom/android/internal/view/menu/MenuBuilder;
-Lcom/android/internal/view/menu/MenuBuilder;->setOptionalIconsVisible(Z)V
-Lcom/android/internal/view/menu/MenuBuilder;->startDispatchingItemsChanged()V
-Lcom/android/internal/view/menu/MenuBuilder;->stopDispatchingItemsChanged()V
-Lcom/android/internal/view/menu/MenuItemImpl;->invoke()Z
-Lcom/android/internal/view/menu/MenuItemImpl;->isActionButton()Z
-Lcom/android/internal/view/menu/MenuItemImpl;->mIconResId:I
-Lcom/android/internal/view/menu/MenuItemImpl;->requestsActionButton()Z
-Lcom/android/internal/view/menu/MenuItemImpl;->requiresActionButton()Z
-Lcom/android/internal/view/menu/MenuItemImpl;->setActionViewExpanded(Z)V
-Lcom/android/internal/view/menu/MenuItemImpl;->setExclusiveCheckable(Z)V
-Lcom/android/internal/view/menu/MenuItemImpl;->setMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V
-Lcom/android/internal/view/menu/MenuPopupHelper;-><init>(Landroid/content/Context;Lcom/android/internal/view/menu/MenuBuilder;)V
-Lcom/android/internal/view/menu/MenuPopupHelper;-><init>(Landroid/content/Context;Lcom/android/internal/view/menu/MenuBuilder;Landroid/view/View;)V
-Lcom/android/internal/view/menu/MenuPopupHelper;->dismiss()V
-Lcom/android/internal/view/menu/MenuPopupHelper;->getPopup()Lcom/android/internal/view/menu/MenuPopup;
-Lcom/android/internal/view/menu/MenuPopupHelper;->mForceShowIcon:Z
-Lcom/android/internal/view/menu/MenuPopupHelper;->setAnchorView(Landroid/view/View;)V
-Lcom/android/internal/view/menu/MenuPopupHelper;->setForceShowIcon(Z)V
-Lcom/android/internal/view/menu/MenuPopupHelper;->setGravity(I)V
-Lcom/android/internal/view/menu/MenuPopupHelper;->show()V
-Lcom/android/internal/view/menu/MenuPopupHelper;->tryShow()Z
-Lcom/android/internal/view/menu/MenuPresenter$Callback;->onOpenSubMenu(Lcom/android/internal/view/menu/MenuBuilder;)Z
-Lcom/android/internal/view/menu/MenuView$ItemView;->getItemData()Lcom/android/internal/view/menu/MenuItemImpl;
-Lcom/android/internal/view/menu/MenuView;->getWindowAnimations()I
-Lcom/android/internal/view/menu/SubMenuBuilder;->getRootMenu()Lcom/android/internal/view/menu/MenuBuilder;
-Lcom/android/internal/view/menu/SubMenuBuilder;->setCallback(Lcom/android/internal/view/menu/MenuBuilder$Callback;)V
-Lcom/android/internal/widget/CachingIconView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
 Lcom/android/internal/widget/ILockSettings$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings;
 Lcom/android/internal/widget/ILockSettings;->getBoolean(Ljava/lang/String;ZI)Z
 Lcom/android/internal/widget/ILockSettings;->getLong(Ljava/lang/String;JI)J
@@ -8480,16 +2457,7 @@
 Lcom/android/internal/widget/IRemoteViewsFactory;->hasStableIds()Z
 Lcom/android/internal/widget/IRemoteViewsFactory;->isCreated()Z
 Lcom/android/internal/widget/IRemoteViewsFactory;->onDataSetChanged()V
-Lcom/android/internal/widget/ScrollingTabContainerView;-><init>(Landroid/content/Context;)V
-Lcom/android/internal/widget/ScrollingTabContainerView;->addTab(Landroid/app/ActionBar$Tab;IZ)V
-Lcom/android/internal/widget/ScrollingTabContainerView;->addTab(Landroid/app/ActionBar$Tab;Z)V
-Lcom/android/internal/widget/ScrollingTabContainerView;->animateToTab(I)V
-Lcom/android/internal/widget/ScrollingTabContainerView;->animateToVisibility(I)V
-Lcom/android/internal/widget/ScrollingTabContainerView;->removeAllTabs()V
-Lcom/android/internal/widget/ScrollingTabContainerView;->removeTabAt(I)V
-Lcom/android/internal/widget/ScrollingTabContainerView;->setAllowCollapse(Z)V
-Lcom/android/internal/widget/ScrollingTabContainerView;->setTabSelected(I)V
-Lcom/android/internal/widget/ScrollingTabContainerView;->updateTab(I)V
+Lcom/android/internal/widget/ScrollBarUtils;->getThumbLength(IIII)I
 Lcom/android/okhttp/Connection;->getSocket()Ljava/net/Socket;
 Lcom/android/okhttp/ConnectionPool;->connections:Ljava/util/Deque;
 Lcom/android/okhttp/ConnectionPool;->keepAliveDurationNs:J
@@ -8551,6 +2519,8 @@
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->setNpnProtocols([B)V
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->setSoWriteTimeout(I)V
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->setUseSessionTickets(Z)V
+Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setHostname(Ljava/lang/String;)V
+Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setUseSessionTickets(Z)V
 Lcom/android/org/conscrypt/ConscryptSocketBase;->getHostname()Ljava/lang/String;
 Lcom/android/org/conscrypt/ConscryptSocketBase;->getHostnameOrIP()Ljava/lang/String;
 Lcom/android/org/conscrypt/ConscryptSocketBase;->getSoWriteTimeout()I
@@ -9020,46 +2990,6 @@
 Ljava/util/zip/Inflater;->len:I
 Ljava/util/zip/Inflater;->needDict:Z
 Ljava/util/zip/Inflater;->off:I
-Ljava/util/zip/ZipConstants;->CENATT:I
-Ljava/util/zip/ZipConstants;->CENATX:I
-Ljava/util/zip/ZipConstants;->CENCOM:I
-Ljava/util/zip/ZipConstants;->CENCRC:I
-Ljava/util/zip/ZipConstants;->CENDSK:I
-Ljava/util/zip/ZipConstants;->CENEXT:I
-Ljava/util/zip/ZipConstants;->CENFLG:I
-Ljava/util/zip/ZipConstants;->CENHDR:I
-Ljava/util/zip/ZipConstants;->CENHOW:I
-Ljava/util/zip/ZipConstants;->CENLEN:I
-Ljava/util/zip/ZipConstants;->CENNAM:I
-Ljava/util/zip/ZipConstants;->CENOFF:I
-Ljava/util/zip/ZipConstants;->CENSIG:J
-Ljava/util/zip/ZipConstants;->CENSIZ:I
-Ljava/util/zip/ZipConstants;->CENTIM:I
-Ljava/util/zip/ZipConstants;->CENVEM:I
-Ljava/util/zip/ZipConstants;->CENVER:I
-Ljava/util/zip/ZipConstants;->ENDCOM:I
-Ljava/util/zip/ZipConstants;->ENDHDR:I
-Ljava/util/zip/ZipConstants;->ENDOFF:I
-Ljava/util/zip/ZipConstants;->ENDSIG:J
-Ljava/util/zip/ZipConstants;->ENDSIZ:I
-Ljava/util/zip/ZipConstants;->ENDSUB:I
-Ljava/util/zip/ZipConstants;->ENDTOT:I
-Ljava/util/zip/ZipConstants;->EXTCRC:I
-Ljava/util/zip/ZipConstants;->EXTHDR:I
-Ljava/util/zip/ZipConstants;->EXTLEN:I
-Ljava/util/zip/ZipConstants;->EXTSIG:J
-Ljava/util/zip/ZipConstants;->EXTSIZ:I
-Ljava/util/zip/ZipConstants;->LOCCRC:I
-Ljava/util/zip/ZipConstants;->LOCEXT:I
-Ljava/util/zip/ZipConstants;->LOCFLG:I
-Ljava/util/zip/ZipConstants;->LOCHDR:I
-Ljava/util/zip/ZipConstants;->LOCHOW:I
-Ljava/util/zip/ZipConstants;->LOCLEN:I
-Ljava/util/zip/ZipConstants;->LOCNAM:I
-Ljava/util/zip/ZipConstants;->LOCSIG:J
-Ljava/util/zip/ZipConstants;->LOCSIZ:I
-Ljava/util/zip/ZipConstants;->LOCTIM:I
-Ljava/util/zip/ZipConstants;->LOCVER:I
 Ljava/util/zip/ZipEntry;-><init>(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V
 Ljava/util/zip/ZipEntry;->method:I
 Ljava/util/zip/ZipFile;->close(J)V
@@ -9070,21 +3000,21 @@
 Ljava/util/zip/ZipOutputStream;->method:I
 Ljava/util/zip/ZipOutputStream;->names:Ljava/util/HashSet;
 Ljava/util/zip/ZipOutputStream;->written:J
-Ljavax/microedition/khronos/egl/EGL10;->eglReleaseThread()Z
 Ljavax/net/ssl/SSLServerSocketFactory;->defaultServerSocketFactory:Ljavax/net/ssl/SSLServerSocketFactory;
 Ljavax/net/ssl/SSLSocketFactory;->createSocket(Ljava/net/Socket;Ljava/io/InputStream;Z)Ljava/net/Socket;
 Ljavax/net/ssl/SSLSocketFactory;->defaultSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
+Llibcore/icu/ICU;->addLikelySubtags(Ljava/util/Locale;)Ljava/util/Locale;
+Llibcore/io/Memory;->peekByte(J)B
+Llibcore/io/Memory;->peekByteArray(J[BII)V
+Llibcore/io/Memory;->peekInt(JZ)I
+Llibcore/io/Memory;->peekLong(JZ)J
+Llibcore/io/Memory;->pokeByte(JB)V
+Llibcore/io/Memory;->pokeByteArray(J[BII)V
+Llibcore/io/Memory;->pokeInt(JIZ)V
+Llibcore/io/Memory;->pokeLong(JJZ)V
+Llibcore/io/Streams;->copy(Ljava/io/InputStream;Ljava/io/OutputStream;)I
 Llibcore/util/BasicLruCache;->map:Ljava/util/LinkedHashMap;
 Llibcore/util/ZoneInfo;->mTransitions:[J
-Lorg/apache/http/conn/ssl/AbstractVerifier;->BAD_COUNTRY_2LDS:[Ljava/lang/String;
-Lorg/apache/http/conn/ssl/SSLSocketFactory;-><init>()V
-Lorg/apache/http/conn/ssl/SSLSocketFactory;-><init>(Ljavax/net/ssl/SSLSocketFactory;)V
-Lorg/apache/http/conn/ssl/SSLSocketFactory;->createKeyManagers(Ljava/security/KeyStore;Ljava/lang/String;)[Ljavax/net/ssl/KeyManager;
-Lorg/apache/http/conn/ssl/SSLSocketFactory;->createTrustManagers(Ljava/security/KeyStore;)[Ljavax/net/ssl/TrustManager;
-Lorg/apache/http/conn/ssl/SSLSocketFactory;->hostnameVerifier:Lorg/apache/http/conn/ssl/X509HostnameVerifier;
-Lorg/apache/http/conn/ssl/SSLSocketFactory;->nameResolver:Lorg/apache/http/conn/scheme/HostNameResolver;
-Lorg/apache/http/conn/ssl/SSLSocketFactory;->socketfactory:Ljavax/net/ssl/SSLSocketFactory;
-Lorg/apache/http/conn/ssl/SSLSocketFactory;->sslcontext:Ljavax/net/ssl/SSLContext;
 Lorg/ccil/cowan/tagsoup/AttributesImpl;->data:[Ljava/lang/String;
 Lorg/ccil/cowan/tagsoup/AttributesImpl;->length:I
 Lorg/ccil/cowan/tagsoup/ElementType;->theAtts:Lorg/ccil/cowan/tagsoup/AttributesImpl;
@@ -9096,6 +3026,8 @@
 Lorg/ccil/cowan/tagsoup/ElementType;->theNamespace:Ljava/lang/String;
 Lorg/ccil/cowan/tagsoup/ElementType;->theParent:Lorg/ccil/cowan/tagsoup/ElementType;
 Lorg/ccil/cowan/tagsoup/ElementType;->theSchema:Lorg/ccil/cowan/tagsoup/Schema;
+Lorg/ccil/cowan/tagsoup/HTMLSchema;-><init>()V
+Lorg/ccil/cowan/tagsoup/Parser;-><init>()V
 Lorg/ccil/cowan/tagsoup/Schema;->theElementTypes:Ljava/util/HashMap;
 Lorg/ccil/cowan/tagsoup/Schema;->theEntities:Ljava/util/HashMap;
 Lorg/ccil/cowan/tagsoup/Schema;->thePrefix:Ljava/lang/String;
@@ -9195,10 +3127,84 @@
 Lorg/xml/sax/SAXParseException;->lineNumber:I
 Lorg/xml/sax/SAXParseException;->publicId:Ljava/lang/String;
 Lorg/xml/sax/SAXParseException;->systemId:Ljava/lang/String;
+Lsun/misc/Cleaner;->clean()V
+Lsun/misc/Unsafe;->addressSize()I
+Lsun/misc/Unsafe;->allocateInstance(Ljava/lang/Class;)Ljava/lang/Object;
+Lsun/misc/Unsafe;->allocateMemory(J)J
+Lsun/misc/Unsafe;->arrayBaseOffset(Ljava/lang/Class;)I
+Lsun/misc/Unsafe;->arrayIndexScale(Ljava/lang/Class;)I
+Lsun/misc/Unsafe;->compareAndSwapInt(Ljava/lang/Object;JII)Z
+Lsun/misc/Unsafe;->compareAndSwapLong(Ljava/lang/Object;JJJ)Z
+Lsun/misc/Unsafe;->compareAndSwapObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z
+Lsun/misc/Unsafe;->copyMemory(JJJ)V
+Lsun/misc/Unsafe;->copyMemoryFromPrimitiveArray(Ljava/lang/Object;JJJ)V
+Lsun/misc/Unsafe;->copyMemoryToPrimitiveArray(JLjava/lang/Object;JJ)V
+Lsun/misc/Unsafe;->freeMemory(J)V
+Lsun/misc/Unsafe;->fullFence()V
+Lsun/misc/Unsafe;->getAndAddInt(Ljava/lang/Object;JI)I
+Lsun/misc/Unsafe;->getAndAddLong(Ljava/lang/Object;JJ)J
+Lsun/misc/Unsafe;->getAndSetInt(Ljava/lang/Object;JI)I
+Lsun/misc/Unsafe;->getAndSetLong(Ljava/lang/Object;JJ)J
+Lsun/misc/Unsafe;->getAndSetObject(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;
+Lsun/misc/Unsafe;->getArrayBaseOffsetForComponentType(Ljava/lang/Class;)I
+Lsun/misc/Unsafe;->getArrayIndexScaleForComponentType(Ljava/lang/Class;)I
+Lsun/misc/Unsafe;->getBoolean(Ljava/lang/Object;J)Z
+Lsun/misc/Unsafe;->getByte(J)B
+Lsun/misc/Unsafe;->getByte(Ljava/lang/Object;J)B
+Lsun/misc/Unsafe;->getChar(J)C
+Lsun/misc/Unsafe;->getChar(Ljava/lang/Object;J)C
+Lsun/misc/Unsafe;->getDouble(J)D
+Lsun/misc/Unsafe;->getDouble(Ljava/lang/Object;J)D
+Lsun/misc/Unsafe;->getFloat(J)F
+Lsun/misc/Unsafe;->getFloat(Ljava/lang/Object;J)F
+Lsun/misc/Unsafe;->getInt(J)I
+Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I
+Lsun/misc/Unsafe;->getIntVolatile(Ljava/lang/Object;J)I
+Lsun/misc/Unsafe;->getLong(J)J
+Lsun/misc/Unsafe;->getLong(Ljava/lang/Object;J)J
+Lsun/misc/Unsafe;->getLongVolatile(Ljava/lang/Object;J)J
+Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object;
+Lsun/misc/Unsafe;->getObjectVolatile(Ljava/lang/Object;J)Ljava/lang/Object;
+Lsun/misc/Unsafe;->getShort(J)S
+Lsun/misc/Unsafe;->getShort(Ljava/lang/Object;J)S
+Lsun/misc/Unsafe;->getUnsafe()Lsun/misc/Unsafe;
+Lsun/misc/Unsafe;->INVALID_FIELD_OFFSET:I
+Lsun/misc/Unsafe;->loadFence()V
+Lsun/misc/Unsafe;->objectFieldOffset(Ljava/lang/reflect/Field;)J
+Lsun/misc/Unsafe;->pageSize()I
+Lsun/misc/Unsafe;->park(ZJ)V
+Lsun/misc/Unsafe;->putBoolean(Ljava/lang/Object;JZ)V
+Lsun/misc/Unsafe;->putByte(JB)V
+Lsun/misc/Unsafe;->putByte(Ljava/lang/Object;JB)V
+Lsun/misc/Unsafe;->putChar(JC)V
+Lsun/misc/Unsafe;->putChar(Ljava/lang/Object;JC)V
+Lsun/misc/Unsafe;->putDouble(JD)V
+Lsun/misc/Unsafe;->putDouble(Ljava/lang/Object;JD)V
+Lsun/misc/Unsafe;->putFloat(JF)V
+Lsun/misc/Unsafe;->putFloat(Ljava/lang/Object;JF)V
+Lsun/misc/Unsafe;->putInt(JI)V
+Lsun/misc/Unsafe;->putInt(Ljava/lang/Object;JI)V
+Lsun/misc/Unsafe;->putIntVolatile(Ljava/lang/Object;JI)V
+Lsun/misc/Unsafe;->putLong(JJ)V
+Lsun/misc/Unsafe;->putLong(Ljava/lang/Object;JJ)V
+Lsun/misc/Unsafe;->putLongVolatile(Ljava/lang/Object;JJ)V
+Lsun/misc/Unsafe;->putObject(Ljava/lang/Object;JLjava/lang/Object;)V
+Lsun/misc/Unsafe;->putObjectVolatile(Ljava/lang/Object;JLjava/lang/Object;)V
+Lsun/misc/Unsafe;->putOrderedInt(Ljava/lang/Object;JI)V
+Lsun/misc/Unsafe;->putOrderedLong(Ljava/lang/Object;JJ)V
+Lsun/misc/Unsafe;->putOrderedObject(Ljava/lang/Object;JLjava/lang/Object;)V
+Lsun/misc/Unsafe;->putShort(JS)V
+Lsun/misc/Unsafe;->putShort(Ljava/lang/Object;JS)V
+Lsun/misc/Unsafe;->setMemory(JJB)V
+Lsun/misc/Unsafe;->storeFence()V
 Lsun/misc/Unsafe;->theUnsafe:Lsun/misc/Unsafe;
 Lsun/misc/Unsafe;->THE_ONE:Lsun/misc/Unsafe;
+Lsun/misc/Unsafe;->unpark(Ljava/lang/Object;)V
 Lsun/misc/URLClassPath$JarLoader;->getJarFile()Ljava/util/jar/JarFile;
 Lsun/misc/URLClassPath;->lmap:Ljava/util/HashMap;
 Lsun/misc/URLClassPath;->loaders:Ljava/util/ArrayList;
 Lsun/misc/URLClassPath;->urls:Ljava/util/Stack;
+Lsun/nio/ch/DirectBuffer;->cleaner()Lsun/misc/Cleaner;
+Lsun/security/x509/AlgorithmId;->get(Ljava/lang/String;)Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/AlgorithmId;->getName()Ljava/lang/String;
 Lsun/security/x509/AVA;->hasRFC2253Keyword()Z
diff --git a/config/hiddenapi-p-light-greylist.txt b/config/hiddenapi-p-light-greylist.txt
index e360879..e26a4c7 100644
--- a/config/hiddenapi-p-light-greylist.txt
+++ b/config/hiddenapi-p-light-greylist.txt
@@ -534,7 +534,7 @@
 Landroid/app/INotificationManager;->cancelAllNotifications(Ljava/lang/String;I)V
 Landroid/app/INotificationManager;->cancelNotificationWithTag(Ljava/lang/String;Ljava/lang/String;II)V
 Landroid/app/INotificationManager;->cancelToast(Ljava/lang/String;Landroid/app/ITransientNotification;)V
-Landroid/app/INotificationManager;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;I)V
+Landroid/app/INotificationManager;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;II)V
 Landroid/app/IProcessObserver$Stub;-><init>()V
 Landroid/app/ISearchManager$Stub$Proxy;->getGlobalSearchActivity()Landroid/content/ComponentName;
 Landroid/app/ISearchManager$Stub$Proxy;->getWebSearchActivity()Landroid/content/ComponentName;
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 43b1a0e..9e6abe4 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -1,20 +1,3 @@
-Landroid/accounts/AccountManager;-><init>(Landroid/content/Context;Landroid/accounts/IAccountManager;Landroid/os/Handler;)V
-Landroid/app/Activity;->managedQuery(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
-Landroid/app/Activity;->registerRemoteAnimations(Landroid/view/RemoteAnimationDefinition;)V
-Landroid/app/ActivityManager$RecentTaskInfo;->configuration:Landroid/content/res/Configuration;
-Landroid/app/ActivityManager$TaskDescription;->loadTaskDescriptionIcon(Ljava/lang/String;I)Landroid/graphics/Bitmap;
-Landroid/app/ActivityManager$TaskSnapshot;->getSnapshot()Landroid/graphics/GraphicBuffer;
-Landroid/app/ActivityManagerNative;->broadcastStickyIntent(Landroid/content/Intent;Ljava/lang/String;I)V
-Landroid/app/ActivityOptions;->makeRemoteAnimation(Landroid/view/RemoteAnimationAdapter;)Landroid/app/ActivityOptions;
-Landroid/app/ActivityOptions;->setSplitScreenCreateMode(I)V
-Landroid/app/ActivityView;-><init>(Landroid/content/Context;)V
-Landroid/app/ActivityView;->release()V
-Landroid/app/ActivityView;->startActivity(Landroid/app/PendingIntent;)V
-Landroid/app/ActivityView;->startActivity(Landroid/content/Intent;)V
-Landroid/app/AppOpsManager$OpEntry;->getOp()I
-Landroid/app/AppOpsManager$OpEntry;->getTime()J
-Landroid/app/AppOpsManager;->getPackagesForOps([I)Ljava/util/List;
-Landroid/app/AppOpsManager;->getToken(Lcom/android/internal/app/IAppOpsService;)Landroid/os/IBinder;
 Landroid/app/IActivityController$Stub;-><init>()V
 Landroid/app/IActivityManager;->cancelRecentsAnimation(Z)V
 Landroid/app/IActivityManager;->cancelTaskWindowTransition(I)V
@@ -36,53 +19,11 @@
 Landroid/app/IAssistDataReceiver$Stub;-><init>()V
 Landroid/app/IAssistDataReceiver;->onHandleAssistData(Landroid/os/Bundle;)V
 Landroid/app/IAssistDataReceiver;->onHandleAssistScreenshot(Landroid/graphics/Bitmap;)V
-Landroid/app/KeyguardManager;->isDeviceLocked(I)Z
-Landroid/app/NotificationManager;->cancelAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)V
-Landroid/app/StatusBarManager;->removeIcon(Ljava/lang/String;)V
-Landroid/app/StatusBarManager;->setIcon(Ljava/lang/String;IILjava/lang/String;)V
-Landroid/app/TaskStackListener;->onActivityDismissingDockedStack()V
-Landroid/app/TaskStackListener;->onActivityForcedResizable(Ljava/lang/String;II)V
-Landroid/app/TaskStackListener;->onActivityLaunchOnSecondaryDisplayFailed()V
-Landroid/app/TaskStackListener;->onActivityPinned(Ljava/lang/String;III)V
-Landroid/app/TaskStackListener;->onActivityRequestedOrientationChanged(II)V
-Landroid/app/TaskStackListener;->onActivityUnpinned()V
-Landroid/app/TaskStackListener;->onPinnedActivityRestartAttempt(Z)V
-Landroid/app/TaskStackListener;->onPinnedStackAnimationEnded()V
-Landroid/app/TaskStackListener;->onPinnedStackAnimationStarted()V
-Landroid/app/TaskStackListener;->onTaskMovedToFront(I)V
-Landroid/app/TaskStackListener;->onTaskProfileLocked(II)V
-Landroid/app/TaskStackListener;->onTaskRemoved(I)V
-Landroid/app/TaskStackListener;->onTaskSnapshotChanged(ILandroid/app/ActivityManager$TaskSnapshot;)V
-Landroid/app/TaskStackListener;->onTaskStackChanged()V
-Landroid/app/WallpaperColors;-><init>(Landroid/graphics/Color;Landroid/graphics/Color;Landroid/graphics/Color;I)V
-Landroid/bluetooth/BluetoothHeadset;->phoneStateChanged(IIILjava/lang/String;I)V
 Landroid/bluetooth/IBluetooth;->sendConnectionStateChange(Landroid/bluetooth/BluetoothDevice;III)V
-Landroid/companion/AssociationRequest;->getDeviceFilters()Ljava/util/List;
-Landroid/companion/AssociationRequest;->isSingleDevice()Z
-Landroid/companion/BluetoothDeviceFilter;->getAddress()Ljava/lang/String;
-Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceDisplayNameInternal(Landroid/bluetooth/BluetoothDevice;)Ljava/lang/String;
-Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceDisplayNameInternal(Landroid/net/wifi/ScanResult;)Ljava/lang/String;
-Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceMacAddress(Landroid/os/Parcelable;)Ljava/lang/String;
-Landroid/companion/BluetoothLeDeviceFilter;->getScanFilter()Landroid/bluetooth/le/ScanFilter;
-Landroid/companion/DeviceFilter;->getDeviceDisplayName(Landroid/os/Parcelable;)Ljava/lang/String;
-Landroid/companion/DeviceFilter;->matches(Landroid/os/Parcelable;)Z
 Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V
 Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V
 Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V
 Landroid/companion/IFindDeviceCallback;->onSuccess(Landroid/app/PendingIntent;)V
-Landroid/content/ContentProvider;-><init>(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;[Landroid/content/pm/PathPermission;)V
-Landroid/content/ContentProvider;->attachInfoForTesting(Landroid/content/Context;Landroid/content/pm/ProviderInfo;)V
-Landroid/content/ContentProvider;->getIContentProvider()Landroid/content/IContentProvider;
-Landroid/content/ContentResolver;->registerContentObserver(Landroid/net/Uri;ZLandroid/database/ContentObserver;I)V
-Landroid/content/ContentValues;->getStringArrayList(Ljava/lang/String;)Ljava/util/ArrayList;
-Landroid/content/ContentValues;->putStringArrayList(Ljava/lang/String;Ljava/util/ArrayList;)V
-Landroid/content/Context;->registerReceiverAsUser(Landroid/content/BroadcastReceiver;Landroid/os/UserHandle;Landroid/content/IntentFilter;Ljava/lang/String;Landroid/os/Handler;)Landroid/content/Intent;
-Landroid/content/Context;->startActivityAsUser(Landroid/content/Intent;Landroid/os/UserHandle;)V
-Landroid/content/Context;->startServiceAsUser(Landroid/content/Intent;Landroid/os/UserHandle;)Landroid/content/ComponentName;
-Landroid/content/ContextWrapper;->getThemeResId()I
-Landroid/content/Intent;->getExtra(Ljava/lang/String;)Ljava/lang/Object;
-Landroid/content/Intent;->getIBinderExtra(Ljava/lang/String;)Landroid/os/IBinder;
-Landroid/content/Intent;->resolveSystemService(Landroid/content/pm/PackageManager;I)Landroid/content/ComponentName;
 Landroid/content/pm/IPackageDataObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageDeleteObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageDeleteObserver;->packageDeleted(Ljava/lang/String;I)V
@@ -91,16 +32,6 @@
 Landroid/content/pm/IPackageManager;->getHomeActivities(Ljava/util/List;)Landroid/content/ComponentName;
 Landroid/content/pm/IPackageManager;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
 Landroid/content/pm/IPackageStatsObserver;->onGetStatsCompleted(Landroid/content/pm/PackageStats;Z)V
-Landroid/database/sqlite/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
-Landroid/database/sqlite/SqliteWrapper;->query(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
-Landroid/graphics/Bitmap;->createGraphicBufferHandle()Landroid/graphics/GraphicBuffer;
-Landroid/graphics/Bitmap;->createHardwareBitmap(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;
-Landroid/graphics/drawable/Drawable;->isProjected()Z
-Landroid/graphics/drawable/Drawable;->updateTintFilter(Landroid/graphics/PorterDuffColorFilter;Landroid/content/res/ColorStateList;Landroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuffColorFilter;
-Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
-Landroid/hardware/display/DisplayManagerGlobal;->getInstance()Landroid/hardware/display/DisplayManagerGlobal;
-Landroid/hardware/display/DisplayManagerGlobal;->getRealDisplay(I)Landroid/view/Display;
-Landroid/hardware/location/GeofenceHardware;-><init>(Landroid/hardware/location/IGeofenceHardware;)V
 Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V
 Landroid/location/IGeocodeProvider;->getFromLocation(DDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String;
 Landroid/location/IGeocodeProvider;->getFromLocationName(Ljava/lang/String;DDDDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String;
@@ -109,21 +40,6 @@
 Landroid/location/ILocationManager;->reportLocation(Landroid/location/Location;Z)V
 Landroid/location/INetInitiatedListener$Stub;-><init>()V
 Landroid/location/INetInitiatedListener;->sendNiResponse(II)Z
-Landroid/location/Location;->setExtraLocation(Ljava/lang/String;Landroid/location/Location;)V
-Landroid/media/AudioManager;->registerAudioPortUpdateListener(Landroid/media/AudioManager$OnAudioPortUpdateListener;)V
-Landroid/media/AudioManager;->unregisterAudioPortUpdateListener(Landroid/media/AudioManager$OnAudioPortUpdateListener;)V
-Landroid/media/AudioSystem;->checkAudioFlinger()I
-Landroid/media/AudioSystem;->getForceUse(I)I
-Landroid/media/AudioSystem;->getParameters(Ljava/lang/String;)Ljava/lang/String;
-Landroid/media/AudioSystem;->setForceUse(II)I
-Landroid/media/AudioSystem;->setParameters(Ljava/lang/String;)I
-Landroid/media/MediaDrm$Certificate;->getContent()[B
-Landroid/media/MediaDrm$Certificate;->getWrappedPrivateKey()[B
-Landroid/media/MediaDrm$CertificateRequest;->getData()[B
-Landroid/media/MediaDrm$CertificateRequest;->getDefaultUrl()Ljava/lang/String;
-Landroid/media/MediaDrm;->getCertificateRequest(ILjava/lang/String;)Landroid/media/MediaDrm$CertificateRequest;
-Landroid/media/MediaDrm;->provideCertificateResponse([B)Landroid/media/MediaDrm$Certificate;
-Landroid/media/MediaDrm;->signRSA([BLjava/lang/String;[B[B)[B
 Landroid/media/tv/ITvRemoteProvider$Stub;-><init>()V
 Landroid/media/tv/ITvRemoteServiceInput;->clearInputBridge(Landroid/os/IBinder;)V
 Landroid/media/tv/ITvRemoteServiceInput;->closeInputBridge(Landroid/os/IBinder;)V
@@ -134,23 +50,7 @@
 Landroid/media/tv/ITvRemoteServiceInput;->sendPointerSync(Landroid/os/IBinder;)V
 Landroid/media/tv/ITvRemoteServiceInput;->sendPointerUp(Landroid/os/IBinder;I)V
 Landroid/media/tv/ITvRemoteServiceInput;->sendTimestamp(Landroid/os/IBinder;J)V
-Landroid/net/ConnectivityManager$PacketKeepalive;->stop()V
 Landroid/net/ConnectivityManager$PacketKeepaliveCallback;-><init>()V
-Landroid/net/ConnectivityManager$PacketKeepaliveCallback;->onError(I)V
-Landroid/net/ConnectivityManager$PacketKeepaliveCallback;->onStarted()V
-Landroid/net/ConnectivityManager$PacketKeepaliveCallback;->onStopped()V
-Landroid/net/ConnectivityManager;->getActiveNetworkQuotaInfo()Landroid/net/NetworkQuotaInfo;
-Landroid/net/ConnectivityManager;->setAirplaneMode(Z)V
-Landroid/net/ConnectivityManager;->startNattKeepalive(Landroid/net/Network;ILandroid/net/ConnectivityManager$PacketKeepaliveCallback;Ljava/net/InetAddress;ILjava/net/InetAddress;)Landroid/net/ConnectivityManager$PacketKeepalive;
-Landroid/net/ConnectivityManager;->tether(Ljava/lang/String;)I
-Landroid/net/ConnectivityManager;->untether(Ljava/lang/String;)I
-Landroid/net/DhcpResults;-><init>()V
-Landroid/net/DhcpResults;-><init>(Landroid/net/DhcpResults;)V
-Landroid/net/DhcpResults;-><init>(Landroid/net/StaticIpConfiguration;)V
-Landroid/net/DhcpResults;->leaseDuration:I
-Landroid/net/DhcpResults;->mtu:I
-Landroid/net/DhcpResults;->serverAddress:Ljava/net/Inet4Address;
-Landroid/net/DhcpResults;->vendorInfo:Ljava/lang/String;
 Landroid/net/IConnectivityManager;->getAllNetworkState()[Landroid/net/NetworkState;
 Landroid/net/INetd$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetd;
 Landroid/net/INetd;->interfaceAddAddress(Ljava/lang/String;Ljava/lang/String;I)V
@@ -159,149 +59,7 @@
 Landroid/net/INetworkStatsSession;->getHistoryForNetwork(Landroid/net/NetworkTemplate;I)Landroid/net/NetworkStatsHistory;
 Landroid/net/INetworkStatsSession;->getHistoryForUid(Landroid/net/NetworkTemplate;IIII)Landroid/net/NetworkStatsHistory;
 Landroid/net/InterfaceConfiguration;-><init>()V
-Landroid/net/InterfaceConfiguration;->setLinkAddress(Landroid/net/LinkAddress;)V
-Landroid/net/LinkAddress;-><init>(Ljava/lang/String;)V
-Landroid/net/LinkAddress;-><init>(Ljava/net/InetAddress;I)V
-Landroid/net/LinkAddress;->isIPv6()Z
-Landroid/net/LinkAddress;->isSameAddressAs(Landroid/net/LinkAddress;)Z
-Landroid/net/LinkProperties$ProvisioningChange;->GAINED_PROVISIONING:Landroid/net/LinkProperties$ProvisioningChange;
-Landroid/net/LinkProperties$ProvisioningChange;->LOST_PROVISIONING:Landroid/net/LinkProperties$ProvisioningChange;
-Landroid/net/LinkProperties$ProvisioningChange;->STILL_NOT_PROVISIONED:Landroid/net/LinkProperties$ProvisioningChange;
-Landroid/net/LinkProperties$ProvisioningChange;->STILL_PROVISIONED:Landroid/net/LinkProperties$ProvisioningChange;
 Landroid/net/LinkProperties$ProvisioningChange;->values()[Landroid/net/LinkProperties$ProvisioningChange;
-Landroid/net/LinkProperties;-><init>()V
-Landroid/net/LinkProperties;-><init>(Landroid/net/LinkProperties;)V
-Landroid/net/LinkProperties;->addDnsServer(Ljava/net/InetAddress;)Z
-Landroid/net/LinkProperties;->addRoute(Landroid/net/RouteInfo;)Z
-Landroid/net/LinkProperties;->addStackedLink(Landroid/net/LinkProperties;)Z
-Landroid/net/LinkProperties;->clear()V
-Landroid/net/LinkProperties;->compareProvisioning(Landroid/net/LinkProperties;Landroid/net/LinkProperties;)Landroid/net/LinkProperties$ProvisioningChange;
-Landroid/net/LinkProperties;->getAllInterfaceNames()Ljava/util/List;
-Landroid/net/LinkProperties;->getAllRoutes()Ljava/util/List;
-Landroid/net/LinkProperties;->getMtu()I
-Landroid/net/LinkProperties;->getStackedLinks()Ljava/util/List;
-Landroid/net/LinkProperties;->hasGlobalIPv6Address()Z
-Landroid/net/LinkProperties;->hasIPv4Address()Z
-Landroid/net/LinkProperties;->hasIPv4DefaultRoute()Z
-Landroid/net/LinkProperties;->hasIPv4DnsServer()Z
-Landroid/net/LinkProperties;->hasIPv6DefaultRoute()Z
-Landroid/net/LinkProperties;->hasIPv6DnsServer()Z
-Landroid/net/LinkProperties;->isIdenticalAddresses(Landroid/net/LinkProperties;)Z
-Landroid/net/LinkProperties;->isIdenticalDnses(Landroid/net/LinkProperties;)Z
-Landroid/net/LinkProperties;->isIdenticalRoutes(Landroid/net/LinkProperties;)Z
-Landroid/net/LinkProperties;->isIdenticalStackedLinks(Landroid/net/LinkProperties;)Z
-Landroid/net/LinkProperties;->isIPv6Provisioned()Z
-Landroid/net/LinkProperties;->isProvisioned()Z
-Landroid/net/LinkProperties;->isReachable(Ljava/net/InetAddress;)Z
-Landroid/net/LinkProperties;->removeDnsServer(Ljava/net/InetAddress;)Z
-Landroid/net/LinkProperties;->removeRoute(Landroid/net/RouteInfo;)Z
-Landroid/net/LinkProperties;->setDnsServers(Ljava/util/Collection;)V
-Landroid/net/LinkProperties;->setDomains(Ljava/lang/String;)V
-Landroid/net/LinkProperties;->setInterfaceName(Ljava/lang/String;)V
-Landroid/net/LinkProperties;->setLinkAddresses(Ljava/util/Collection;)V
-Landroid/net/LinkProperties;->setMtu(I)V
-Landroid/net/LinkProperties;->setTcpBufferSizes(Ljava/lang/String;)V
-Landroid/net/MacAddress;->ALL_ZEROS_ADDRESS:Landroid/net/MacAddress;
-Landroid/net/metrics/ApfProgramEvent;-><init>()V
-Landroid/net/metrics/ApfProgramEvent;->actualLifetime:J
-Landroid/net/metrics/ApfProgramEvent;->currentRas:I
-Landroid/net/metrics/ApfProgramEvent;->filteredRas:I
-Landroid/net/metrics/ApfProgramEvent;->flags:I
-Landroid/net/metrics/ApfProgramEvent;->flagsFor(ZZ)I
-Landroid/net/metrics/ApfProgramEvent;->lifetime:J
-Landroid/net/metrics/ApfProgramEvent;->programLength:I
-Landroid/net/metrics/ApfStats;-><init>()V
-Landroid/net/metrics/ApfStats;->droppedRas:I
-Landroid/net/metrics/ApfStats;->durationMs:J
-Landroid/net/metrics/ApfStats;->matchingRas:I
-Landroid/net/metrics/ApfStats;->maxProgramSize:I
-Landroid/net/metrics/ApfStats;->parseErrors:I
-Landroid/net/metrics/ApfStats;->programUpdates:I
-Landroid/net/metrics/ApfStats;->programUpdatesAll:I
-Landroid/net/metrics/ApfStats;->programUpdatesAllowingMulticast:I
-Landroid/net/metrics/ApfStats;->receivedRas:I
-Landroid/net/metrics/ApfStats;->zeroLifetimeRas:I
-Landroid/net/metrics/DhcpClientEvent;-><init>(Ljava/lang/String;I)V
-Landroid/net/metrics/DhcpErrorEvent;-><init>(I)V
-Landroid/net/metrics/DhcpErrorEvent;->BOOTP_TOO_SHORT:I
-Landroid/net/metrics/DhcpErrorEvent;->BUFFER_UNDERFLOW:I
-Landroid/net/metrics/DhcpErrorEvent;->DHCP_BAD_MAGIC_COOKIE:I
-Landroid/net/metrics/DhcpErrorEvent;->DHCP_INVALID_OPTION_LENGTH:I
-Landroid/net/metrics/DhcpErrorEvent;->DHCP_NO_COOKIE:I
-Landroid/net/metrics/DhcpErrorEvent;->DHCP_NO_MSG_TYPE:I
-Landroid/net/metrics/DhcpErrorEvent;->DHCP_UNKNOWN_MSG_TYPE:I
-Landroid/net/metrics/DhcpErrorEvent;->errorCodeWithOption(II)I
-Landroid/net/metrics/DhcpErrorEvent;->L2_TOO_SHORT:I
-Landroid/net/metrics/DhcpErrorEvent;->L2_WRONG_ETH_TYPE:I
-Landroid/net/metrics/DhcpErrorEvent;->L3_INVALID_IP:I
-Landroid/net/metrics/DhcpErrorEvent;->L3_NOT_IPV4:I
-Landroid/net/metrics/DhcpErrorEvent;->L3_TOO_SHORT:I
-Landroid/net/metrics/DhcpErrorEvent;->L4_NOT_UDP:I
-Landroid/net/metrics/DhcpErrorEvent;->L4_WRONG_PORT:I
-Landroid/net/metrics/DhcpErrorEvent;->PARSING_ERROR:I
-Landroid/net/metrics/DhcpErrorEvent;->RECEIVE_ERROR:I
-Landroid/net/metrics/IpConnectivityLog;-><init>()V
-Landroid/net/metrics/IpConnectivityLog;->log(Landroid/os/Parcelable;)Z
-Landroid/net/metrics/IpConnectivityLog;->log(Ljava/lang/String;Landroid/os/Parcelable;)Z
-Landroid/net/metrics/IpManagerEvent;-><init>(IJ)V
-Landroid/net/metrics/IpReachabilityEvent;-><init>(I)V
-Landroid/net/metrics/IpReachabilityEvent;->nudFailureEventType(ZZ)I
-Landroid/net/metrics/RaEvent$Builder;-><init>()V
-Landroid/net/metrics/RaEvent$Builder;->build()Landroid/net/metrics/RaEvent;
-Landroid/net/metrics/RaEvent$Builder;->updateDnsslLifetime(J)Landroid/net/metrics/RaEvent$Builder;
-Landroid/net/metrics/RaEvent$Builder;->updatePrefixPreferredLifetime(J)Landroid/net/metrics/RaEvent$Builder;
-Landroid/net/metrics/RaEvent$Builder;->updatePrefixValidLifetime(J)Landroid/net/metrics/RaEvent$Builder;
-Landroid/net/metrics/RaEvent$Builder;->updateRdnssLifetime(J)Landroid/net/metrics/RaEvent$Builder;
-Landroid/net/metrics/RaEvent$Builder;->updateRouteInfoLifetime(J)Landroid/net/metrics/RaEvent$Builder;
-Landroid/net/metrics/RaEvent$Builder;->updateRouterLifetime(J)Landroid/net/metrics/RaEvent$Builder;
-Landroid/net/Network;-><init>(I)V
-Landroid/net/Network;->netId:I
-Landroid/net/NetworkCapabilities;->getNetworkSpecifier()Landroid/net/NetworkSpecifier;
-Landroid/net/NetworkCapabilities;->getSignalStrength()I
-Landroid/net/NetworkCapabilities;->hasSignalStrength()Z
-Landroid/net/NetworkCapabilities;->transportNamesOf([I)Ljava/lang/String;
-Landroid/net/NetworkQuotaInfo;->getEstimatedBytes()J
-Landroid/net/NetworkQuotaInfo;->getHardLimitBytes()J
-Landroid/net/NetworkQuotaInfo;->getSoftLimitBytes()J
-Landroid/net/NetworkRequest$Builder;->setSignalStrength(I)Landroid/net/NetworkRequest$Builder;
-Landroid/net/NetworkRequest;->networkCapabilities:Landroid/net/NetworkCapabilities;
-Landroid/net/NetworkState;->network:Landroid/net/Network;
-Landroid/net/NetworkStats$Entry;-><init>()V
-Landroid/net/NetworkStats$Entry;->iface:Ljava/lang/String;
-Landroid/net/NetworkStats$Entry;->rxBytes:J
-Landroid/net/NetworkStats$Entry;->rxPackets:J
-Landroid/net/NetworkStats$Entry;->set:I
-Landroid/net/NetworkStats$Entry;->tag:I
-Landroid/net/NetworkStats$Entry;->txBytes:J
-Landroid/net/NetworkStats$Entry;->txPackets:J
-Landroid/net/NetworkStats$Entry;->uid:I
-Landroid/net/NetworkStats;-><init>(JI)V
-Landroid/net/NetworkStats;->combineValues(Landroid/net/NetworkStats$Entry;)Landroid/net/NetworkStats;
-Landroid/net/NetworkStatsHistory$Entry;->txBytes:J
-Landroid/net/NetworkStatsHistory;->getStart()J
-Landroid/net/NetworkStatsHistory;->getValues(JJLandroid/net/NetworkStatsHistory$Entry;)Landroid/net/NetworkStatsHistory$Entry;
-Landroid/net/NetworkTemplate;->buildTemplateMobileAll(Ljava/lang/String;)Landroid/net/NetworkTemplate;
-Landroid/net/NetworkUtils;->attachControlPacketFilter(Ljava/io/FileDescriptor;I)V
-Landroid/net/NetworkUtils;->attachDhcpFilter(Ljava/io/FileDescriptor;)V
-Landroid/net/NetworkUtils;->attachRaFilter(Ljava/io/FileDescriptor;I)V
-Landroid/net/NetworkUtils;->getImplicitNetmask(Ljava/net/Inet4Address;)I
-Landroid/net/NetworkUtils;->netmaskToPrefixLength(Ljava/net/Inet4Address;)I
-Landroid/net/NetworkUtils;->protectFromVpn(Ljava/io/FileDescriptor;)Z
-Landroid/net/RouteInfo;-><init>(Landroid/net/IpPrefix;Ljava/net/InetAddress;Ljava/lang/String;)V
-Landroid/net/RouteInfo;->hasGateway()Z
-Landroid/net/RouteInfo;->selectBestRoute(Ljava/util/Collection;Ljava/net/InetAddress;)Landroid/net/RouteInfo;
-Landroid/net/SntpClient;->getNtpTime()J
-Landroid/net/SntpClient;->getNtpTimeReference()J
-Landroid/net/SntpClient;->getRoundTripTime()J
-Landroid/net/SntpClient;->requestTime(Ljava/lang/String;I)Z
-Landroid/net/StaticIpConfiguration;->dnsServers:Ljava/util/ArrayList;
-Landroid/net/StaticIpConfiguration;->domains:Ljava/lang/String;
-Landroid/net/StaticIpConfiguration;->getRoutes(Ljava/lang/String;)Ljava/util/List;
-Landroid/net/StringNetworkSpecifier;->specifier:Ljava/lang/String;
-Landroid/net/TrafficStats;->getMobileTcpRxPackets()J
-Landroid/net/TrafficStats;->getMobileTcpTxPackets()J
-Landroid/net/wifi/WifiInfo;->is5GHz()Z
-Landroid/net/wifi/WifiInfo;->score:I
 Landroid/os/AsyncResult;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V
 Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable;
 Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;Ljava/lang/Object;Ljava/lang/Throwable;)Landroid/os/AsyncResult;
@@ -370,24 +128,7 @@
 Landroid/os/UserHandle;->isSameApp(II)Z
 Landroid/os/UserManager;->hasUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
 Landroid/os/UserManager;->isAdminUser()Z
-Landroid/print/PrintDocumentAdapter$LayoutResultCallback;-><init>()V
-Landroid/print/PrintDocumentAdapter$WriteResultCallback;-><init>()V
-Landroid/provider/CalendarContract$Events;->PROVIDER_WRITABLE_COLUMNS:[Ljava/lang/String;
-Landroid/provider/ContactsContract$CommonDataKinds$Phone;->getDisplayLabel(Landroid/content/Context;ILjava/lang/CharSequence;)Ljava/lang/CharSequence;
-Landroid/provider/Settings$Global;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
-Landroid/provider/Settings$Secure;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
-Landroid/provider/Telephony$Mms;->isEmailAddress(Ljava/lang/String;)Z
-Landroid/provider/Telephony$Sms$Draft;->addMessage(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)Landroid/net/Uri;
-Landroid/provider/Telephony$Sms$Outbox;->addMessage(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;ZJ)Landroid/net/Uri;
 Landroid/R$styleable;->CheckBoxPreference:[I
-Landroid/service/dreams/DreamService;->canDoze()Z
-Landroid/service/dreams/DreamService;->isDozing()Z
-Landroid/service/dreams/DreamService;->startDozing()V
-Landroid/service/dreams/DreamService;->stopDozing()V
-Landroid/service/euicc/EuiccProfileInfo;-><init>(Ljava/lang/String;[Landroid/telephony/UiccAccessRule;Ljava/lang/String;)V
-Landroid/service/euicc/GetDefaultDownloadableSubscriptionListResult;->result:I
-Landroid/service/euicc/GetDownloadableSubscriptionMetadataResult;->result:I
-Landroid/service/vr/VrListenerService;->onCurrentVrActivityChanged(Landroid/content/ComponentName;ZI)V
 Landroid/system/NetlinkSocketAddress;-><init>(II)V
 Landroid/system/Os;->bind(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V
 Landroid/system/Os;->connect(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V
@@ -396,49 +137,10 @@
 Landroid/system/Os;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
 Landroid/system/PacketSocketAddress;-><init>(I[B)V
 Landroid/system/PacketSocketAddress;-><init>(SI)V
-Landroid/telecom/ParcelableCall;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/telecom/ParcelableCall;->getConnectTimeMillis()J
-Landroid/telecom/ParcelableCall;->getDisconnectCause()Landroid/telecom/DisconnectCause;
-Landroid/telecom/ParcelableCall;->getHandle()Landroid/net/Uri;
-Landroid/telecom/ParcelableCall;->getId()Ljava/lang/String;
-Landroid/telecom/TelecomManager;->from(Landroid/content/Context;)Landroid/telecom/TelecomManager;
-Landroid/telecom/VideoProfile$CameraCapabilities;-><init>(IIZF)V
-Landroid/telephony/euicc/DownloadableSubscription;->encodedActivationCode:Ljava/lang/String;
-Landroid/telephony/euicc/DownloadableSubscription;->setAccessRules([Landroid/telephony/UiccAccessRule;)V
-Landroid/telephony/euicc/DownloadableSubscription;->setCarrierName(Ljava/lang/String;)V
-Landroid/telephony/ims/compat/feature/ImsFeature;->getFeatureState()I
-Landroid/telephony/ims/compat/feature/ImsFeature;->setFeatureState(I)V
 Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V
 Landroid/telephony/ims/compat/ImsService;-><init>()V
-Landroid/telephony/ims/compat/ImsService;->mImsServiceController:Landroid/os/IBinder;
 Landroid/telephony/ims/compat/stub/ImsCallSessionImplBase;-><init>()V
-Landroid/telephony/ims/compat/stub/ImsConfigImplBase;-><init>(Landroid/content/Context;)V
-Landroid/telephony/ims/compat/stub/ImsConfigImplBase;->getIImsConfig()Lcom/android/ims/internal/IImsConfig;
 Landroid/telephony/ims/compat/stub/ImsUtListenerImplBase;-><init>()V
-Landroid/telephony/ims/ImsCallForwardInfo;-><init>()V
-Landroid/telephony/ims/ImsCallForwardInfo;->mCondition:I
-Landroid/telephony/ims/ImsCallForwardInfo;->mNumber:Ljava/lang/String;
-Landroid/telephony/ims/ImsCallForwardInfo;->mServiceClass:I
-Landroid/telephony/ims/ImsCallForwardInfo;->mStatus:I
-Landroid/telephony/ims/ImsCallForwardInfo;->mTimeSeconds:I
-Landroid/telephony/ims/ImsCallForwardInfo;->mToA:I
-Landroid/telephony/ims/ImsCallProfile;->mCallExtras:Landroid/os/Bundle;
-Landroid/telephony/ims/ImsCallProfile;->mCallType:I
-Landroid/telephony/ims/ImsCallProfile;->mMediaProfile:Landroid/telephony/ims/ImsStreamMediaProfile;
-Landroid/telephony/ims/ImsCallProfile;->mRestrictCause:I
-Landroid/telephony/ims/ImsCallProfile;->presentationToOIR(I)I
-Landroid/telephony/ims/ImsExternalCallState;-><init>(ILandroid/net/Uri;ZIIZ)V
-Landroid/telephony/ims/ImsReasonInfo;-><init>(II)V
-Landroid/telephony/ims/ImsReasonInfo;->mCode:I
-Landroid/telephony/ims/ImsReasonInfo;->mExtraCode:I
-Landroid/telephony/ims/ImsReasonInfo;->mExtraMessage:Ljava/lang/String;
-Landroid/telephony/ims/ImsSsInfo;->mIcbNum:Ljava/lang/String;
-Landroid/telephony/ims/ImsSsInfo;->mStatus:I
-Landroid/telephony/ims/ImsStreamMediaProfile;-><init>()V
-Landroid/telephony/ims/ImsStreamMediaProfile;->mAudioDirection:I
-Landroid/telephony/ims/ImsStreamMediaProfile;->mAudioQuality:I
-Landroid/telephony/ims/ImsStreamMediaProfile;->mVideoDirection:I
-Landroid/telephony/ims/ImsVideoCallProvider;->getInterface()Lcom/android/ims/internal/IImsVideoCallProvider;
 Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V
 Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V
 Landroid/telephony/mbms/vendor/IMbmsStreamingService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/telephony/mbms/vendor/IMbmsStreamingService;
@@ -446,81 +148,7 @@
 Landroid/telephony/mbms/vendor/IMbmsStreamingService;->initialize(Landroid/telephony/mbms/IMbmsStreamingSessionCallback;I)I
 Landroid/telephony/mbms/vendor/IMbmsStreamingService;->requestUpdateStreamingServices(ILjava/util/List;)I
 Landroid/telephony/mbms/vendor/IMbmsStreamingService;->startStreaming(ILjava/lang/String;Landroid/telephony/mbms/IStreamingServiceCallback;)I
-Landroid/telephony/PhoneNumberUtils;->formatNumber(Ljava/lang/String;I)Ljava/lang/String;
-Landroid/telephony/PhoneNumberUtils;->isEmergencyNumber(ILjava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isPotentialEmergencyNumber(ILjava/lang/String;)Z
-Landroid/telephony/PhoneNumberUtils;->isPotentialLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z
-Landroid/telephony/PhoneStateListener;-><init>(Ljava/lang/Integer;)V
-Landroid/telephony/PhoneStateListener;-><init>(Ljava/lang/Integer;Landroid/os/Looper;)V
-Landroid/telephony/PreciseCallState;->getBackgroundCallState()I
-Landroid/telephony/PreciseCallState;->getForegroundCallState()I
-Landroid/telephony/RadioAccessFamily;-><init>(II)V
-Landroid/telephony/RadioAccessFamily;->getRafFromNetworkType(I)I
-Landroid/telephony/Rlog;->d(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/telephony/Rlog;->i(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/telephony/ServiceState;->bitmaskHasTech(II)Z
-Landroid/telephony/ServiceState;->getDataRegState()I
-Landroid/telephony/ServiceState;->getDataRoaming()Z
-Landroid/telephony/ServiceState;->getRilDataRadioTechnology()I
-Landroid/telephony/ServiceState;->getVoiceNetworkType()I
-Landroid/telephony/ServiceState;->getVoiceRegState()I
-Landroid/telephony/ServiceState;->isCdma(I)Z
-Landroid/telephony/ServiceState;->isEmergencyOnly()Z
-Landroid/telephony/ServiceState;->isGsm(I)Z
-Landroid/telephony/ServiceState;->mergeServiceStates(Landroid/telephony/ServiceState;Landroid/telephony/ServiceState;)Landroid/telephony/ServiceState;
-Landroid/telephony/ServiceState;->rilRadioTechnologyToString(I)Ljava/lang/String;
-Landroid/telephony/SubscriptionInfo;->setDisplayName(Ljava/lang/CharSequence;)V
-Landroid/telephony/SubscriptionInfo;->setIconTint(I)V
-Landroid/telephony/SubscriptionManager;->clearDefaultsForInactiveSubIds()V
-Landroid/telephony/SubscriptionManager;->getDefaultVoicePhoneId()I
-Landroid/telephony/SubscriptionManager;->getResourcesForSubId(Landroid/content/Context;I)Landroid/content/res/Resources;
-Landroid/telephony/SubscriptionManager;->isActiveSubId(I)Z
-Landroid/telephony/SubscriptionManager;->isUsableSubIdValue(I)Z
-Landroid/telephony/SubscriptionManager;->isValidPhoneId(I)Z
-Landroid/telephony/SubscriptionManager;->isValidSlotIndex(I)Z
-Landroid/telephony/SubscriptionManager;->isValidSubscriptionId(I)Z
-Landroid/telephony/SubscriptionManager;->putPhoneIdAndSubIdExtra(Landroid/content/Intent;I)V
-Landroid/telephony/SubscriptionManager;->putPhoneIdAndSubIdExtra(Landroid/content/Intent;II)V
-Landroid/telephony/SubscriptionManager;->setDisplayName(Ljava/lang/String;IJ)I
-Landroid/telephony/SubscriptionManager;->setIconTint(II)I
-Landroid/telephony/TelephonyManager$MultiSimVariants;->DSDA:Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager$MultiSimVariants;->DSDS:Landroid/telephony/TelephonyManager$MultiSimVariants;
-Landroid/telephony/TelephonyManager;->getIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;I)I
-Landroid/telephony/TelephonyManager;->getIsimDomain()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getNetworkTypeName()Ljava/lang/String;
-Landroid/telephony/TelephonyManager;->getPreferredNetworkType(I)I
-Landroid/telephony/TelephonyManager;->getServiceStateForSubscriber(I)Landroid/telephony/ServiceState;
-Landroid/telephony/TelephonyManager;->getVoiceMessageCount()I
-Landroid/telephony/TelephonyManager;->getVoiceNetworkType(I)I
-Landroid/telephony/TelephonyManager;->isImsRegistered()Z
-Landroid/telephony/TelephonyManager;->nvResetConfig(I)Z
-Landroid/telephony/TelephonyManager;->putIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;II)Z
-Landroid/telephony/TelephonyManager;->setPreferredNetworkType(II)Z
-Landroid/text/TextUtils;->isPrintableAsciiOnly(Ljava/lang/CharSequence;)Z
-Landroid/util/IconDrawableFactory;->getBadgedIcon(Landroid/content/pm/PackageItemInfo;Landroid/content/pm/ApplicationInfo;I)Landroid/graphics/drawable/Drawable;
-Landroid/util/IconDrawableFactory;->newInstance(Landroid/content/Context;)Landroid/util/IconDrawableFactory;
-Landroid/util/LocalLog$ReadOnlyLocalLog;->dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V
-Landroid/util/LocalLog;-><init>(I)V
-Landroid/util/LocalLog;->log(Ljava/lang/String;)V
-Landroid/util/LocalLog;->readOnlyLocalLog()Landroid/util/LocalLog$ReadOnlyLocalLog;
-Landroid/util/LongArray;-><init>()V
-Landroid/util/LongArray;->add(IJ)V
-Landroid/util/LongArray;->get(I)J
-Landroid/util/LongArray;->size()I
-Landroid/util/RecurrenceRule;->buildRecurringMonthly(ILjava/time/ZoneId;)Landroid/util/RecurrenceRule;
-Landroid/util/RecurrenceRule;->start:Ljava/time/ZonedDateTime;
-Landroid/util/Slog;->e(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/util/Slog;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I
-Landroid/util/Slog;->println(ILjava/lang/String;Ljava/lang/String;)I
-Landroid/util/Slog;->wtf(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/view/AppTransitionAnimationSpec;-><init>(ILandroid/graphics/GraphicBuffer;Landroid/graphics/Rect;)V
-Landroid/view/BatchedInputEventReceiver;-><init>(Landroid/view/InputChannel;Landroid/os/Looper;Landroid/view/Choreographer;)V
-Landroid/view/Choreographer;->getSfInstance()Landroid/view/Choreographer;
-Landroid/view/DisplayListCanvas;->drawRenderNode(Landroid/view/RenderNode;)V
 Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;-><init>()V
-Landroid/view/InputEventReceiver;->onInputEvent(Landroid/view/InputEvent;)V
 Landroid/view/IRecentsAnimationController;->finish(Z)V
 Landroid/view/IRecentsAnimationController;->screenshotTask(I)Landroid/app/ActivityManager$TaskSnapshot;
 Landroid/view/IRecentsAnimationController;->setInputConsumerEnabled(Z)V
@@ -538,42 +166,6 @@
 Landroid/view/IWindowManager;->overridePendingAppTransitionMultiThumbFuture(Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/os/IRemoteCallback;Z)V
 Landroid/view/IWindowManager;->overridePendingAppTransitionRemote(Landroid/view/RemoteAnimationAdapter;)V
 Landroid/view/IWindowManager;->setNavBarVirtualKeyHapticFeedbackEnabled(Z)V
-Landroid/view/RemoteAnimationAdapter;-><init>(Landroid/view/IRemoteAnimationRunner;JJ)V
-Landroid/view/RemoteAnimationDefinition;-><init>()V
-Landroid/view/RemoteAnimationDefinition;->addRemoteAnimation(ILandroid/view/RemoteAnimationAdapter;)V
-Landroid/view/RenderNode;->create(Ljava/lang/String;Landroid/view/View;)Landroid/view/RenderNode;
-Landroid/view/RenderNode;->end(Landroid/view/DisplayListCanvas;)V
-Landroid/view/RenderNode;->isValid()Z
-Landroid/view/RenderNode;->setClipToBounds(Z)Z
-Landroid/view/RenderNode;->setLeftTopRightBottom(IIII)Z
-Landroid/view/RenderNode;->start(II)Landroid/view/DisplayListCanvas;
-Landroid/view/Surface;->getNextFrameNumber()J
-Landroid/view/SurfaceControl$Transaction;-><init>()V
-Landroid/view/SurfaceControl$Transaction;->apply()V
-Landroid/view/SurfaceControl$Transaction;->deferTransactionUntil(Landroid/view/SurfaceControl;Landroid/os/IBinder;J)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->deferTransactionUntilSurface(Landroid/view/SurfaceControl;Landroid/view/Surface;J)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->hide(Landroid/view/SurfaceControl;)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->setAlpha(Landroid/view/SurfaceControl;F)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->setColor(Landroid/view/SurfaceControl;[F)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->setFinalCrop(Landroid/view/SurfaceControl;Landroid/graphics/Rect;)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->setLayer(Landroid/view/SurfaceControl;I)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->setMatrix(Landroid/view/SurfaceControl;FFFF)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->setMatrix(Landroid/view/SurfaceControl;Landroid/graphics/Matrix;[F)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->setPosition(Landroid/view/SurfaceControl;FF)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->setSize(Landroid/view/SurfaceControl;II)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->setWindowCrop(Landroid/view/SurfaceControl;Landroid/graphics/Rect;)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/SurfaceControl$Transaction;->show(Landroid/view/SurfaceControl;)Landroid/view/SurfaceControl$Transaction;
-Landroid/view/ThreadedRenderer;->createHardwareBitmap(Landroid/view/RenderNode;II)Landroid/graphics/Bitmap;
-Landroid/view/View;->hideTooltip()V
-Landroid/view/View;->setTooltip(Ljava/lang/CharSequence;)V
-Landroid/webkit/WebSettings;->getPluginsPath()Ljava/lang/String;
-Landroid/webkit/WebSettings;->getUseDoubleTree()Z
-Landroid/webkit/WebSettings;->setPluginsPath(Ljava/lang/String;)V
-Landroid/webkit/WebSettings;->setUseDoubleTree(Z)V
-Landroid/webkit/WebView;->getPluginList()Landroid/webkit/PluginList;
-Landroid/webkit/WebView;->getZoomControls()Landroid/view/View;
-Landroid/webkit/WebView;->refreshPlugins(Z)V
-Landroid/widget/ListView;->lookForSelectablePosition(IZ)I
 Lcom/android/ims/ImsConfigListener;->onSetFeatureResponse(IIII)V
 Lcom/android/ims/internal/IImsCallSessionListener;->callSessionConferenceStateUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsConferenceState;)V
 Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandover(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V
@@ -611,31 +203,6 @@
 Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueryFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V
 Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdated(Lcom/android/ims/internal/IImsUt;I)V
 Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdateFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/uce/common/CapInfo;->getCapTimestamp()J
-Lcom/android/ims/internal/uce/common/CapInfo;->isCdViaPresenceSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFtHttpSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFtSnFSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFtSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFtThumbSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFullSnFGroupChatSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isGeoPullFtSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isGeoPullSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isGeoPushSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isImSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isIpVideoSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isIpVoiceSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isIsSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isRcsIpVideoCallSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isRcsIpVideoOnlyCallSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isRcsIpVoiceCallSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isSmSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isSpSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isVsDuringCSSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isVsSupported()Z
-Lcom/android/ims/internal/uce/common/StatusCode;->getStatusCode()I
-Lcom/android/ims/internal/uce/common/UceLong;-><init>()V
-Lcom/android/ims/internal/uce/common/UceLong;->getClientId()I
-Lcom/android/ims/internal/uce/common/UceLong;->setClientId(I)V
 Lcom/android/ims/internal/uce/options/IOptionsListener;->cmdStatus(Lcom/android/ims/internal/uce/options/OptionsCmdStatus;)V
 Lcom/android/ims/internal/uce/options/IOptionsListener;->getVersionCb(Ljava/lang/String;)V
 Lcom/android/ims/internal/uce/options/IOptionsListener;->incomingOptions(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;I)V
@@ -651,24 +218,6 @@
 Lcom/android/ims/internal/uce/options/IOptionsService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
 Lcom/android/ims/internal/uce/options/IOptionsService;->responseIncomingOptions(IIILjava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;Z)Lcom/android/ims/internal/uce/common/StatusCode;
 Lcom/android/ims/internal/uce/options/IOptionsService;->setMyInfo(ILcom/android/ims/internal/uce/common/CapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;-><init>()V
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;->getCapInfo()Lcom/android/ims/internal/uce/common/CapInfo;
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;->getSdp()Ljava/lang/String;
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;->setCapInfo(Lcom/android/ims/internal/uce/common/CapInfo;)V
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;->setSdp(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/options/OptionsCmdId;-><init>()V
-Lcom/android/ims/internal/uce/options/OptionsCmdId;->setCmdId(I)V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;-><init>()V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setCapInfo(Lcom/android/ims/internal/uce/common/CapInfo;)V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setCmdId(Lcom/android/ims/internal/uce/options/OptionsCmdId;)V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setStatus(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setUserData(I)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;-><init>()V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setCmdId(Lcom/android/ims/internal/uce/options/OptionsCmdId;)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setReasonPhrase(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setRequestId(I)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setRetryAfter(I)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setSipResponseCode(I)V
 Lcom/android/ims/internal/uce/presence/IPresenceListener;->capInfoReceived(Ljava/lang/String;[Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V
 Lcom/android/ims/internal/uce/presence/IPresenceListener;->cmdStatus(Lcom/android/ims/internal/uce/presence/PresCmdStatus;)V
 Lcom/android/ims/internal/uce/presence/IPresenceListener;->getVersionCb(Ljava/lang/String;)V
@@ -687,18 +236,6 @@
 Lcom/android/ims/internal/uce/presence/IPresenceService;->reenableService(II)Lcom/android/ims/internal/uce/common/StatusCode;
 Lcom/android/ims/internal/uce/presence/IPresenceService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
 Lcom/android/ims/internal/uce/presence/IPresenceService;->setNewFeatureTag(ILjava/lang/String;Lcom/android/ims/internal/uce/presence/PresServiceInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/PresCapInfo;->getCapInfo()Lcom/android/ims/internal/uce/common/CapInfo;
-Lcom/android/ims/internal/uce/presence/PresCapInfo;->getContactUri()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresCapInfo;->mContactUri:Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getMediaType()I
-Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceDesc()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceId()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceVer()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getCmdId()Lcom/android/ims/internal/uce/presence/PresCmdId;
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getReasonPhrase()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getRequestId()I
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getRetryAfter()I
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getSipResponseCode()I
 Lcom/android/ims/internal/uce/uceservice/IUceListener;->setStatus(I)V
 Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V
 Lcom/android/ims/internal/uce/uceservice/IUceService;->createOptionsService(Lcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)I
@@ -711,19 +248,8 @@
 Lcom/android/ims/internal/uce/uceservice/IUceService;->isServiceStarted()Z
 Lcom/android/ims/internal/uce/uceservice/IUceService;->startService(Lcom/android/ims/internal/uce/uceservice/IUceListener;)Z
 Lcom/android/ims/internal/uce/uceservice/IUceService;->stopService()Z
-Lcom/android/internal/app/AlertController$AlertParams;->mIconId:I
-Lcom/android/internal/app/AlertController$AlertParams;->mMessage:Ljava/lang/CharSequence;
-Lcom/android/internal/app/AlertController$AlertParams;->mNegativeButtonListener:Landroid/content/DialogInterface$OnClickListener;
-Lcom/android/internal/app/AlertController$AlertParams;->mNegativeButtonText:Ljava/lang/CharSequence;
-Lcom/android/internal/app/AlertController$AlertParams;->mPositiveButtonListener:Landroid/content/DialogInterface$OnClickListener;
-Lcom/android/internal/app/AlertController$AlertParams;->mPositiveButtonText:Ljava/lang/CharSequence;
-Lcom/android/internal/app/AlertController$AlertParams;->mTitle:Ljava/lang/CharSequence;
-Lcom/android/internal/app/AlertController$AlertParams;->mView:Landroid/view/View;
-Lcom/android/internal/app/AlertController;->getButton(I)Landroid/widget/Button;
 Lcom/android/internal/app/IAppOpsService;->finishOperation(Landroid/os/IBinder;IILjava/lang/String;)V
 Lcom/android/internal/content/PackageMonitor;-><init>()V
-Lcom/android/internal/content/PackageMonitor;->register(Landroid/content/Context;Landroid/os/Looper;Landroid/os/UserHandle;Z)V
-Lcom/android/internal/content/PackageMonitor;->unregister()V
 Lcom/android/internal/location/ILocationProvider$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProvider;
 Lcom/android/internal/location/ILocationProvider;->disable()V
 Lcom/android/internal/location/ILocationProvider;->enable()V
@@ -732,21 +258,6 @@
 Lcom/android/internal/location/ILocationProvider;->getStatusUpdateTime()J
 Lcom/android/internal/location/ILocationProvider;->sendExtraCommand(Ljava/lang/String;Landroid/os/Bundle;)Z
 Lcom/android/internal/location/ILocationProvider;->setRequest(Lcom/android/internal/location/ProviderRequest;Landroid/os/WorkSource;)V
-Lcom/android/internal/location/ProviderRequest;-><init>()V
-Lcom/android/internal/location/ProviderRequest;->interval:J
-Lcom/android/internal/location/ProviderRequest;->locationRequests:Ljava/util/List;
-Lcom/android/internal/location/ProviderRequest;->reportLocation:Z
-Lcom/android/internal/os/BatteryStatsImpl;->getDischargeCurrentLevel()I
-Lcom/android/internal/os/BatteryStatsImpl;->getDischargeStartLevel()I
-Lcom/android/internal/os/BatteryStatsImpl;->getPhoneOnTime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;->getPhoneSignalScanningTime(JI)J
-Lcom/android/internal/os/BatteryStatsImpl;->getPhoneSignalStrengthTime(IJI)J
-Lcom/android/internal/os/BatteryStatsImpl;->getScreenBrightnessTime(IJI)J
-Lcom/android/internal/os/BatteryStatsImpl;->getWifiOnTime(JI)J
-Lcom/android/internal/os/SomeArgs;->arg2:Ljava/lang/Object;
-Lcom/android/internal/os/SomeArgs;->arg3:Ljava/lang/Object;
-Lcom/android/internal/os/SomeArgs;->obtain()Lcom/android/internal/os/SomeArgs;
-Lcom/android/internal/os/SomeArgs;->recycle()V
 Lcom/android/internal/R$styleable;->NumberPicker:[I
 Lcom/android/internal/R$styleable;->TwoLineListItem:[I
 Lcom/android/internal/telephony/GsmAlphabet;->gsm7BitPackedToString([BII)Ljava/lang/String;
@@ -760,14 +271,6 @@
 Lcom/android/internal/telephony/OperatorInfo;->getOperatorAlphaShort()Ljava/lang/String;
 Lcom/android/internal/telephony/OperatorInfo;->getOperatorNumeric()Ljava/lang/String;
 Lcom/android/internal/telephony/OperatorInfo;->getState()Lcom/android/internal/telephony/OperatorInfo$State;
-Lcom/android/internal/util/AsyncChannel;-><init>()V
-Lcom/android/internal/util/AsyncChannel;->connect(Landroid/content/Context;Landroid/os/Handler;Landroid/os/Messenger;)V
-Lcom/android/internal/util/AsyncChannel;->sendMessage(Landroid/os/Message;)V
-Lcom/android/internal/util/IndentingPrintWriter;-><init>(Ljava/io/Writer;Ljava/lang/String;)V
-Lcom/android/internal/util/IndentingPrintWriter;->decreaseIndent()Lcom/android/internal/util/IndentingPrintWriter;
-Lcom/android/internal/util/IndentingPrintWriter;->increaseIndent()Lcom/android/internal/util/IndentingPrintWriter;
-Lcom/android/internal/util/XmlUtils;->beginDocument(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)V
-Lcom/android/internal/util/XmlUtils;->nextElement(Lorg/xmlpull/v1/XmlPullParser;)V
 Ljava/lang/System;->arraycopy([BI[BII)V
 Ljava/net/Inet4Address;->ALL:Ljava/net/InetAddress;
 Ljava/net/Inet4Address;->ANY:Ljava/net/InetAddress;
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 0014793..63c583f 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -6236,9 +6236,9 @@
 org.json.JSONStringer
 org.json.JSONStringer$Scope
 org.json.JSONTokener
-org.kxml2.io.KXmlParser
-org.kxml2.io.KXmlParser$ValueContext
-org.kxml2.io.KXmlSerializer
+com.android.org.kxml2.io.KXmlParser
+com.android.org.kxml2.io.KXmlParser$ValueContext
+com.android.org.kxml2.io.KXmlSerializer
 org.w3c.dom.CharacterData
 org.w3c.dom.DOMImplementation
 org.w3c.dom.Document
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 829a9444..5b73eaa 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
@@ -31,7 +32,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
@@ -398,17 +398,55 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "SHOW_MODE_" }, value = {
             SHOW_MODE_AUTO,
-            SHOW_MODE_HIDDEN
+            SHOW_MODE_HIDDEN,
+            SHOW_MODE_WITH_HARD_KEYBOARD
     })
     public @interface SoftKeyboardShowMode {}
 
+    /**
+     * Allow the system to control when the soft keyboard is shown.
+     * @see SoftKeyboardController
+     */
     public static final int SHOW_MODE_AUTO = 0;
+
+    /**
+     * Never show the soft keyboard.
+     * @see SoftKeyboardController
+     */
     public static final int SHOW_MODE_HIDDEN = 1;
 
+    /**
+     * Allow the soft keyboard to be shown, even if a hard keyboard is connected
+     * @see SoftKeyboardController
+     */
+    public static final int SHOW_MODE_WITH_HARD_KEYBOARD = 2;
+
+    /**
+     * Mask used to cover the show modes supported in public API
+     * @hide
+     */
+    public static final int SHOW_MODE_MASK = 0x03;
+
+    /**
+     * Bit used to hold the old value of the hard IME setting to restore when a service is shut
+     * down.
+     * @hide
+     */
+    public static final int SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE = 0x20000000;
+
+    /**
+     * Bit for show mode setting to indicate that the user has overridden the hard keyboard
+     * behavior.
+     * @hide
+     */
+    public static final int SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN = 0x40000000;
+
     private int mConnectionId = AccessibilityInteractionClient.NO_ID;
 
+    @UnsupportedAppUsage
     private AccessibilityServiceInfo mInfo;
 
+    @UnsupportedAppUsage
     private IBinder mWindowToken;
 
     private WindowManager mWindowManager;
@@ -1147,7 +1185,27 @@
     }
 
     /**
-     * Used to control and query the soft keyboard show mode.
+     * Used to control, query, and listen for changes to the soft keyboard show mode.
+     * <p>
+     * Accessibility services may request to override the decisions normally made about whether or
+     * not the soft keyboard is shown.
+     * <p>
+     * If multiple services make conflicting requests, the last request is honored. A service may
+     * register a listener to find out if the mode has changed under it.
+     * <p>
+     * If the user takes action to override the behavior behavior requested by an accessibility
+     * service, the user's request takes precendence, the show mode will be reset to
+     * {@link AccessibilityService#SHOW_MODE_AUTO}, and services will no longer be able to control
+     * that aspect of the soft keyboard's behavior.
+     * <p>
+     * Note: Because soft keyboards are independent apps, the framework does not have total control
+     * over their behavior. They may choose to show themselves, or not, without regard to requests
+     * made here. So the framework will make a best effort to deliver the behavior requested, but
+     * cannot guarantee success.
+     *
+     * @see AccessibilityService#SHOW_MODE_AUTO
+     * @see AccessibilityService#SHOW_MODE_HIDDEN
+     * @see AccessibilityService#SHOW_MODE_WITH_HARD_KEYBOARD
      */
     public static final class SoftKeyboardController {
         private final AccessibilityService mService;
@@ -1217,7 +1275,8 @@
          * @param listener the listener to remove, must be non-null
          * @return {@code true} if the listener was removed, {@code false} otherwise
          */
-        public boolean removeOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener) {
+        public boolean removeOnShowModeChangedListener(
+                @NonNull OnShowModeChangedListener listener) {
             if (mListeners == null) {
                 return false;
             }
@@ -1289,32 +1348,32 @@
         }
 
         /**
-         * Returns the show mode of the soft keyboard. The default show mode is
-         * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
-         * focused. An AccessibilityService can also request the show mode
-         * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
+         * Returns the show mode of the soft keyboard.
          *
          * @return the current soft keyboard show mode
+         *
+         * @see AccessibilityService#SHOW_MODE_AUTO
+         * @see AccessibilityService#SHOW_MODE_HIDDEN
+         * @see AccessibilityService#SHOW_MODE_WITH_HARD_KEYBOARD
          */
         @SoftKeyboardShowMode
         public int getShowMode() {
-           try {
-               return Settings.Secure.getInt(mService.getContentResolver(),
-                       Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
-           } catch (Settings.SettingNotFoundException e) {
-               Log.v(LOG_TAG, "Failed to obtain the soft keyboard mode", e);
-               // The settings hasn't been changed yet, so it's value is null. Return the default.
-               return 0;
-           }
+            final IAccessibilityServiceConnection connection =
+                    AccessibilityInteractionClient.getInstance().getConnection(
+                            mService.mConnectionId);
+            if (connection != null) {
+                try {
+                    return connection.getSoftKeyboardShowMode();
+                } catch (RemoteException re) {
+                    Log.w(LOG_TAG, "Failed to set soft keyboard behavior", re);
+                    re.rethrowFromSystemServer();
+                }
+            }
+            return SHOW_MODE_AUTO;
         }
 
         /**
-         * Sets the soft keyboard show mode. The default show mode is
-         * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
-         * focused. An AccessibilityService can also request the show mode
-         * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
-         * The lastto this method will be honored, regardless of any previous calls (including those
-         * made by other AccessibilityServices).
+         * Sets the soft keyboard show mode.
          * <p>
          * <strong>Note:</strong> If the service is not yet connected (e.g.
          * {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
@@ -1322,6 +1381,10 @@
          *
          * @param showMode the new show mode for the soft keyboard
          * @return {@code true} on success
+         *
+         * @see AccessibilityService#SHOW_MODE_AUTO
+         * @see AccessibilityService#SHOW_MODE_HIDDEN
+         * @see AccessibilityService#SHOW_MODE_WITH_HARD_KEYBOARD
          */
         public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
            final IAccessibilityServiceConnection connection =
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index ed684d7..f0a0e88 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -29,7 +30,6 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.hardware.fingerprint.FingerprintManager;
-import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
@@ -189,12 +189,10 @@
      * content and also the accessibility service will receive accessibility events from
      * them.
      * <p>
-     * <strong>Note:</strong> For accessibility services targeting API version
-     * {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly
-     * set for the system to regard views that are not important for accessibility. For
-     * accessibility services targeting API version lower than
-     * {@link Build.VERSION_CODES#JELLY_BEAN} this flag is ignored and all views are
-     * regarded for accessibility purposes.
+     * <strong>Note:</strong> For accessibility services targeting Android 4.1 (API level 16) or
+     * higher, this flag has to be explicitly set for the system to regard views that are not
+     * important for accessibility. For accessibility services targeting Android 4.0.4 (API level
+     * 15) or lower, this flag is ignored and all views are regarded for accessibility purposes.
      * </p>
      * <p>
      * Usually views not important for accessibility are layout managers that do not
@@ -219,19 +217,19 @@
      * flag does not guarantee that the device will not be in touch exploration
      * mode since there may be another enabled service that requested it.
      * <p>
-     * For accessibility services targeting API version higher than
-     * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set
-     * this flag have to declare this capability in their meta-data by setting
-     * the attribute {@link android.R.attr#canRequestTouchExplorationMode
-     * canRequestTouchExplorationMode} to true, otherwise this flag will
+     * For accessibility services targeting Android 4.3 (API level 18) or higher
+     * that want to set this flag have to declare this capability in their
+     * meta-data by setting the attribute
+     * {@link android.R.attr#canRequestTouchExplorationMode
+     * canRequestTouchExplorationMode} to true. Otherwise, this flag will
      * be ignored. For how to declare the meta-data of a service refer to
      * {@value AccessibilityService#SERVICE_META_DATA}.
      * </p>
      * <p>
-     * Services targeting API version equal to or lower than
-     * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e.
-     * the first time they are run, if this flag is specified, a dialog is
-     * shown to the user to confirm enabling explore by touch.
+     * Services targeting Android 4.2.2 (API level 17) or lower will work
+     * normally. In other words, the first time they are run, if this flag is
+     * specified, a dialog is shown to the user to confirm enabling explore by
+     * touch.
      * </p>
      * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
      */
@@ -387,10 +385,10 @@
     public int feedbackType;
 
     /**
-     * The timeout after the most recent event of a given type before an
+     * The timeout, in milliseconds, after the most recent event of a given type before an
      * {@link AccessibilityService} is notified.
      * <p>
-     *   <strong>Can be dynamically set at runtime.</strong>.
+     *   <strong>Can be dynamically set at runtime.</strong>
      * </p>
      * <p>
      * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
@@ -695,6 +693,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCapabilities(int capabilities) {
         mCapabilities = capabilities;
     }
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 037aeb0..276131f 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -87,6 +87,8 @@
 
     boolean setSoftKeyboardShowMode(int showMode);
 
+    int getSoftKeyboardShowMode();
+
     void setSoftKeyboardCallbackEnabled(boolean enabled);
 
     boolean isAccessibilityButtonAvailable();
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index b6e85f1..f07f5ec 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Parcelable;
 import android.os.Parcel;
@@ -36,6 +37,7 @@
  * suitable for use as the key of a {@link java.util.Map}
  */
 public class Account implements Parcelable {
+    @UnsupportedAppUsage
     private static final String TAG = "Account";
 
     @GuardedBy("sAccessedAccounts")
@@ -43,6 +45,7 @@
 
     public final String name;
     public final String type;
+    @UnsupportedAppUsage
     private final @Nullable String accessId;
 
     public boolean equals(Object o) {
diff --git a/core/java/android/accounts/AccountAndUser.java b/core/java/android/accounts/AccountAndUser.java
index 04157cc..b0d5343 100644
--- a/core/java/android/accounts/AccountAndUser.java
+++ b/core/java/android/accounts/AccountAndUser.java
@@ -16,15 +16,20 @@
 
 package android.accounts;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Used to store the Account and the UserId this account is associated with.
  *
  * @hide
  */
 public class AccountAndUser {
+    @UnsupportedAppUsage
     public Account account;
+    @UnsupportedAppUsage
     public int userId;
 
+    @UnsupportedAppUsage
     public AccountAndUser(Account account, int userId) {
         this.account = account;
         this.userId = userId;
diff --git a/core/java/android/accounts/AccountAuthenticatorResponse.java b/core/java/android/accounts/AccountAuthenticatorResponse.java
index 41f26ac..bcc9f90 100644
--- a/core/java/android/accounts/AccountAuthenticatorResponse.java
+++ b/core/java/android/accounts/AccountAuthenticatorResponse.java
@@ -16,6 +16,7 @@
 
 package android.accounts;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.Parcel;
@@ -33,6 +34,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public AccountAuthenticatorResponse(IAccountAuthenticatorResponse response) {
         mAccountAuthenticatorResponse = response;
     }
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 5176d71e..3189d08 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -27,6 +27,7 @@
 import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.BroadcastBehavior;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -336,6 +337,7 @@
     public static final String ACCOUNT_ACCESS_TOKEN_TYPE =
             "com.android.AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE";
 
+    @UnsupportedAppUsage
     private final Context mContext;
     private final IAccountManager mService;
     private final Handler mMainHandler;
@@ -409,6 +411,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public AccountManager(Context context, IAccountManager service) {
         mContext = context;
         mService = service;
@@ -418,6 +421,7 @@
     /**
      * @hide used for testing only
      */
+    @UnsupportedAppUsage
     public AccountManager(Context context, IAccountManager service, Handler handler) {
         mContext = context;
         mService = service;
@@ -685,6 +689,7 @@
 
     /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
     @NonNull
+    @UnsupportedAppUsage
     public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
         try {
             return mService.getAccountsAsUser(type, userHandle.getIdentifier(),
@@ -2014,6 +2019,7 @@
      * Same as {@link #confirmCredentials(Account, Bundle, Activity, AccountManagerCallback, Handler)}
      * but for the specified user.
      */
+    @UnsupportedAppUsage
     public AccountManagerFuture<Bundle> confirmCredentialsAsUser(final Account account,
             final Bundle options,
             final Activity activity,
@@ -2225,9 +2231,12 @@
     }
 
     private abstract class AmsTask extends FutureTask<Bundle> implements AccountManagerFuture<Bundle> {
+        @UnsupportedAppUsage
         final IAccountManagerResponse mResponse;
+        @UnsupportedAppUsage
         final Handler mHandler;
         final AccountManagerCallback<Bundle> mCallback;
+        @UnsupportedAppUsage
         final Activity mActivity;
         public AmsTask(Activity activity, Handler handler, AccountManagerCallback<Bundle> callback) {
             super(new Callable<Bundle>() {
@@ -2552,10 +2561,13 @@
         }
         volatile AccountManagerFuture<Bundle> mFuture = null;
         final String mAccountType;
+        @UnsupportedAppUsage
         final String mAuthTokenType;
         final String[] mFeatures;
         final Bundle mAddAccountOptions;
+        @UnsupportedAppUsage
         final Bundle mLoginOptions;
+        @UnsupportedAppUsage
         final AccountManagerCallback<Bundle> mMyCallback;
         private volatile int mNumAccounts = 0;
 
diff --git a/core/java/android/accounts/AuthenticatorDescription.java b/core/java/android/accounts/AuthenticatorDescription.java
index 5d9abb0..6875867 100644
--- a/core/java/android/accounts/AuthenticatorDescription.java
+++ b/core/java/android/accounts/AuthenticatorDescription.java
@@ -16,6 +16,7 @@
 
 package android.accounts;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 import android.os.Parcel;
 
@@ -76,6 +77,7 @@
         return new AuthenticatorDescription(type);
     }
 
+    @UnsupportedAppUsage
     private AuthenticatorDescription(String type) {
         this.type = type;
         this.packageName = null;
@@ -86,6 +88,7 @@
         this.customTokens = false;
     }
 
+    @UnsupportedAppUsage
     private AuthenticatorDescription(Parcel source) {
         this.type = source.readString();
         this.packageName = source.readString();
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 4ebcc44..17d54d2 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -17,6 +17,7 @@
 package android.animation;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ConstantState;
 
@@ -460,6 +461,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void reverse() {
         throw new IllegalStateException("Reverse is not supported");
     }
diff --git a/core/java/android/animation/ArgbEvaluator.java b/core/java/android/animation/ArgbEvaluator.java
index a96bee6..5b69d18 100644
--- a/core/java/android/animation/ArgbEvaluator.java
+++ b/core/java/android/animation/ArgbEvaluator.java
@@ -16,6 +16,8 @@
 
 package android.animation;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * This evaluator can be used to perform type interpolation between integer
  * values that represent ARGB colors.
@@ -31,6 +33,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static ArgbEvaluator getInstance() {
         return sInstance;
     }
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index 5a23fdd..5b3813d 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -16,6 +16,7 @@
 
 package android.animation;
 
+import android.annotation.UnsupportedAppUsage;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
@@ -1070,6 +1071,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void cancel() {
         if (currentChangingAnimations.size() > 0) {
             LinkedHashMap<View, Animator> currentAnimCopy =
@@ -1105,6 +1107,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void cancel(int transitionType) {
         switch (transitionType) {
             case CHANGE_APPEARING:
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index cc95eb6..a0464df 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -19,6 +19,7 @@
 import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Looper;
 import android.os.Trace;
 import android.util.AndroidRuntimeException;
@@ -75,6 +76,7 @@
     /**
      * Internal constants
      */
+    @UnsupportedAppUsage
     private static float sDurationScale = 1.0f;
 
     /**
@@ -200,6 +202,7 @@
     //
 
     // How long the animation should last in ms
+    @UnsupportedAppUsage
     private long mDuration = 300;
 
     // The amount of time in ms to delay starting the animation after start() is called. Note
@@ -1534,6 +1537,7 @@
      * @param fraction The elapsed fraction of the animation.
      */
     @CallSuper
+    @UnsupportedAppUsage
     void animateValue(float fraction) {
         fraction = mInterpolator.getInterpolation(fraction);
         mCurrentFraction = fraction;
diff --git a/core/java/android/annotation/UnsupportedAppUsage.java b/core/java/android/annotation/UnsupportedAppUsage.java
new file mode 100644
index 0000000..fbba6da
--- /dev/null
+++ b/core/java/android/annotation/UnsupportedAppUsage.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a class member, that is not part of the SDK, is used by apps.
+ * Since the member is not part of the SDK, such use is not supported.
+ *
+ * This annotation acts as a heads up that changing a given method or field
+ * may affect apps, potentially breaking them when the next Android version is
+ * released. In some cases, for members that are heavily used, this annotation
+ * may imply restrictions on changes to the member.
+ *
+ * This annotation also results in access to the member being permitted by the
+ * runtime, with a warning being generated in debug builds.
+ *
+ * For more details, see go/UnsupportedAppUsage.
+ *
+ * {@hide}
+ */
+@Retention(CLASS)
+@Target({CONSTRUCTOR, METHOD, FIELD})
+public @interface UnsupportedAppUsage {
+
+    /**
+     * Associates a bug tracking the work to add a public alternative to this API. Optional.
+     *
+     * @return ID of the associated tracking bug
+     */
+    long trackingBug() default 0;
+
+    /**
+     * Indicates that usage of this API is limited to apps based on their target SDK version.
+     *
+     * Access to the API is allowed if the targetSdkVersion in the apps manifest is no greater than
+     * this value. Access checks are performed at runtime.
+     *
+     * This is used to give app developers a grace period to migrate off a non-SDK interface. When
+     * making Android version N, existing APIs can have a maxTargetSdk of N-1 added to them.
+     * Developers must then migrate off the API when their app is updated in future, but it will
+     * continue working in the meantime.
+     *
+     * Possible values are:
+     * <ul>
+     *     <li>
+     *         {@link android.os.Build.VERSION_CODES#O} or {@link android.os.Build.VERSION_CODES#P},
+     *         to limit access to apps targeting these SDKs (or earlier).
+     *     </li>
+     *     <li>
+     *         absent (default value) - All apps can access this API, but doing so may result in
+     *         warnings in the log, UI warnings (on developer builds) and/or strictmode violations.
+     *         The API is likely to be further restricted in future.
+     *     </li>
+     *
+     * </ul>
+     *
+     * Note, if this is set to {@link android.os.Build.VERSION_CODES#O}, apps targeting O
+     * maintenance releases will also be allowed to use the API, and similarly for any future
+     * maintenance releases of P.
+     *
+     * @return The maximum value for an apps targetSdkVersion in order to access this API.
+     */
+    int maxTargetSdk() default Integer.MAX_VALUE;
+
+    /**
+     * For debug use only. The expected dex signature to be generated for this API, used to verify
+     * parts of the build process.
+     *
+     * @return A dex API signature.
+     */
+    String expectedSignature() default "";
+}
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 04ff48c..831cac2 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -22,6 +22,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -210,6 +211,7 @@
      * Allow the title to wrap onto multiple lines if space is available
      * @hide pending API approval
      */
+    @UnsupportedAppUsage
     public static final int DISPLAY_TITLE_MULTIPLE_LINES = 0x20;
 
     /**
@@ -1050,6 +1052,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setShowHideAnimationEnabled(boolean enabled) {
     }
 
@@ -1092,6 +1095,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean collapseActionView() {
         return false;
     }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6bac52d..8d5b96b 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -31,6 +31,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.StyleRes;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.VoiceInteractor.Request;
 import android.app.admin.DevicePolicyManager;
 import android.app.assist.AssistContent;
@@ -735,6 +736,7 @@
      */
     public static final int FINISH_TASK_WITH_ACTIVITY = 2;
 
+    @UnsupportedAppUsage
     static final String FRAGMENTS_TAG = "android:fragments";
     private static final String LAST_AUTOFILL_ID = "android:lastAutofillId";
 
@@ -768,22 +770,38 @@
     private SparseArray<ManagedDialog> mManagedDialogs;
 
     // set by the thread after the constructor and before onCreate(Bundle savedInstanceState) is called.
+    @UnsupportedAppUsage
     private Instrumentation mInstrumentation;
+    @UnsupportedAppUsage
     private IBinder mToken;
+    @UnsupportedAppUsage
     private int mIdent;
+    @UnsupportedAppUsage
     /*package*/ String mEmbeddedID;
+    @UnsupportedAppUsage
     private Application mApplication;
+    @UnsupportedAppUsage
     /*package*/ Intent mIntent;
+    @UnsupportedAppUsage
     /*package*/ String mReferrer;
+    @UnsupportedAppUsage
     private ComponentName mComponent;
+    @UnsupportedAppUsage
     /*package*/ ActivityInfo mActivityInfo;
+    @UnsupportedAppUsage
     /*package*/ ActivityThread mMainThread;
+    @UnsupportedAppUsage
     Activity mParent;
+    @UnsupportedAppUsage
     boolean mCalled;
+    @UnsupportedAppUsage
     /*package*/ boolean mResumed;
+    @UnsupportedAppUsage
     /*package*/ boolean mStopped;
+    @UnsupportedAppUsage
     boolean mFinished;
     boolean mStartedActivity;
+    @UnsupportedAppUsage
     private boolean mDestroyed;
     private boolean mDoReportFullyDrawn = true;
     private boolean mRestoredFromBundle;
@@ -795,7 +813,9 @@
     /*package*/ boolean mTemporaryPause = false;
     /** true if the activity is being destroyed in order to recreate it with a new configuration */
     /*package*/ boolean mChangingConfigurations = false;
+    @UnsupportedAppUsage
     /*package*/ int mConfigChangeFlags;
+    @UnsupportedAppUsage
     /*package*/ Configuration mCurrentConfig;
     private SearchManager mSearchManager;
     private MenuInflater mMenuInflater;
@@ -810,25 +830,34 @@
         ArrayMap<String, LoaderManager> loaders;
         VoiceInteractor voiceInteractor;
     }
+    @UnsupportedAppUsage
     /* package */ NonConfigurationInstances mLastNonConfigurationInstances;
 
+    @UnsupportedAppUsage
     private Window mWindow;
 
+    @UnsupportedAppUsage
     private WindowManager mWindowManager;
     /*package*/ View mDecor = null;
+    @UnsupportedAppUsage
     /*package*/ boolean mWindowAdded = false;
     /*package*/ boolean mVisibleFromServer = false;
+    @UnsupportedAppUsage
     /*package*/ boolean mVisibleFromClient = true;
     /*package*/ ActionBar mActionBar = null;
     private boolean mEnableDefaultActionBarUp;
 
+    @UnsupportedAppUsage
     private VoiceInteractor mVoiceInteractor;
 
+    @UnsupportedAppUsage
     private CharSequence mTitle;
     private int mTitleColor = 0;
 
     // we must have a handler before the FragmentController is constructed
+    @UnsupportedAppUsage
     final Handler mHandler = new Handler();
+    @UnsupportedAppUsage
     final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
 
     private static final class ManagedCursor {
@@ -847,8 +876,10 @@
     private final ArrayList<ManagedCursor> mManagedCursors = new ArrayList<>();
 
     @GuardedBy("this")
+    @UnsupportedAppUsage
     int mResultCode = RESULT_CANCELED;
     @GuardedBy("this")
+    @UnsupportedAppUsage
     Intent mResultData = null;
 
     private TranslucentConversionListener mTranslucentCallback;
@@ -872,6 +903,7 @@
 
     private Thread mUiThread;
 
+    @UnsupportedAppUsage
     ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
     SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
     SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;
@@ -1086,7 +1118,7 @@
      *
      * @param savedInstanceState contains the saved state
      */
-    final void performRestoreInstanceState(Bundle savedInstanceState) {
+    final void performRestoreInstanceState(@NonNull Bundle savedInstanceState) {
         onRestoreInstanceState(savedInstanceState);
         restoreManagedDialogs(savedInstanceState);
     }
@@ -1100,8 +1132,8 @@
      * @param savedInstanceState contains the saved state
      * @param persistentState contains the persistable saved state
      */
-    final void performRestoreInstanceState(Bundle savedInstanceState,
-            PersistableBundle persistentState) {
+    final void performRestoreInstanceState(@Nullable Bundle savedInstanceState,
+            @Nullable PersistableBundle persistentState) {
         onRestoreInstanceState(savedInstanceState, persistentState);
         if (savedInstanceState != null) {
             restoreManagedDialogs(savedInstanceState);
@@ -1128,7 +1160,7 @@
      * @see #onResume
      * @see #onSaveInstanceState
      */
-    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
         if (mWindow != null) {
             Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
             if (windowState != null) {
@@ -1149,8 +1181,12 @@
      *
      * <p>If this method is called {@link #onRestoreInstanceState(Bundle)} will not be called.
      *
-     * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
-     * @param persistentState the data most recently supplied in {@link #onSaveInstanceState}.
+     * <p>At least one of {@code savedInstanceState} or {@code persistentState} will not be null.
+     *
+     * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}
+     *     or null.
+     * @param persistentState the data most recently supplied in {@link #onSaveInstanceState}
+     *     or null.
      *
      * @see #onRestoreInstanceState(Bundle)
      * @see #onCreate
@@ -1158,8 +1194,8 @@
      * @see #onResume
      * @see #onSaveInstanceState
      */
-    public void onRestoreInstanceState(Bundle savedInstanceState,
-            PersistableBundle persistentState) {
+    public void onRestoreInstanceState(@Nullable Bundle savedInstanceState,
+            @Nullable PersistableBundle persistentState) {
         if (savedInstanceState != null) {
             onRestoreInstanceState(savedInstanceState);
         }
@@ -1545,7 +1581,7 @@
      *
      * @param outState The bundle to save the state to.
      */
-    final void performSaveInstanceState(Bundle outState) {
+    final void performSaveInstanceState(@NonNull Bundle outState) {
         onSaveInstanceState(outState);
         saveManagedDialogs(outState);
         mActivityTransitionState.saveState(outState);
@@ -1562,7 +1598,8 @@
      * @param outState The bundle to save the state to.
      * @param outPersistentState The bundle to save persistent state to.
      */
-    final void performSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+    final void performSaveInstanceState(@NonNull Bundle outState,
+            @NonNull PersistableBundle outPersistentState) {
         onSaveInstanceState(outState, outPersistentState);
         saveManagedDialogs(outState);
         storeHasCurrentPermissionRequest(outState);
@@ -1618,7 +1655,7 @@
      * @see #onRestoreInstanceState
      * @see #onPause
      */
-    protected void onSaveInstanceState(Bundle outState) {
+    protected void onSaveInstanceState(@NonNull Bundle outState) {
         outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
 
         outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
@@ -1648,7 +1685,8 @@
      * @see #onRestoreInstanceState(Bundle, PersistableBundle)
      * @see #onPause
      */
-    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+    public void onSaveInstanceState(@NonNull Bundle outState,
+            @NonNull PersistableBundle outPersistentState) {
         onSaveInstanceState(outState);
     }
 
@@ -1657,6 +1695,7 @@
      *
      * @param outState place to store the saved state.
      */
+    @UnsupportedAppUsage
     private void saveManagedDialogs(Bundle outState) {
         if (mManagedDialogs == null) {
             return;
@@ -2515,6 +2554,7 @@
      * @deprecated Use {@link CursorLoader} instead.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public final Cursor managedQuery(Uri uri, String[] projection, String selection,
             String sortOrder) {
         Cursor c = getContentResolver().query(uri, projection, selection, null, sortOrder);
@@ -2635,6 +2675,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setPersistent(boolean isPersistent) {
     }
 
@@ -4657,6 +4698,7 @@
     /**
      * @hide Implement to provide correct calling token.
      */
+    @UnsupportedAppUsage
     public void startActivityForResultAsUser(Intent intent, int requestCode, UserHandle user) {
         startActivityForResultAsUser(intent, requestCode, null, user);
     }
@@ -4702,6 +4744,7 @@
     /**
      * @hide Implement to provide correct calling token.
      */
+    @UnsupportedAppUsage
     public void startActivityAsUser(Intent intent, UserHandle user) {
         startActivityAsUser(intent, null, user);
     }
@@ -5265,6 +5308,7 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     public void startActivityForResult(
             String who, Intent intent, int requestCode, @Nullable Bundle options) {
         Uri referrer = onProvideReferrer();
@@ -5591,6 +5635,7 @@
      * Finishes the current activity and specifies whether to remove the task associated with this
      * activity.
      */
+    @UnsupportedAppUsage
     private void finish(int finishTask) {
         if (mParent == null) {
             int resultCode;
@@ -6337,6 +6382,10 @@
     }
 
     void dumpInner(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        if (args != null && args.length > 0 && args[0].equals("--autofill")) {
+            dumpAutofillManager(prefix, writer);
+            return;
+        }
         writer.print(prefix); writer.print("Local Activity ");
                 writer.print(Integer.toHexString(System.identityHashCode(this)));
                 writer.println(" State:");
@@ -6364,16 +6413,20 @@
 
         mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
 
+        dumpAutofillManager(prefix, writer);
+
+        ResourcesManager.getInstance().dump(prefix, writer);
+    }
+
+    void dumpAutofillManager(String prefix, PrintWriter writer) {
         final AutofillManager afm = getAutofillManager();
         if (afm != null) {
+            afm.dump(prefix, writer);
             writer.print(prefix); writer.print("Autofill Compat Mode: ");
             writer.println(isAutofillCompatibilityEnabled());
-            afm.dump(prefix, writer);
         } else {
             writer.print(prefix); writer.println("No AutofillManager");
         }
-
-        ResourcesManager.getInstance().dump(prefix, writer);
     }
 
     /**
@@ -6515,6 +6568,7 @@
      * @return The ActivityOptions passed to {@link #convertToTranslucent}.
      * @hide
      */
+    @UnsupportedAppUsage
     ActivityOptions getActivityOptions() {
         try {
             return ActivityOptions.fromBundle(
@@ -7035,10 +7089,12 @@
 
     // ------------------ Internal API ------------------
 
+    @UnsupportedAppUsage
     final void setParent(Activity parent) {
         mParent = parent;
     }
 
+    @UnsupportedAppUsage
     final void attach(Context context, ActivityThread aThread,
             Instrumentation instr, IBinder token, int ident,
             Application application, Intent intent, ActivityInfo info,
@@ -7111,6 +7167,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public final IBinder getActivityToken() {
         return mParent != null ? mParent.getActivityToken() : mToken;
     }
@@ -7125,6 +7182,7 @@
         performCreate(icicle, null);
     }
 
+    @UnsupportedAppUsage
     final void performCreate(Bundle icicle, PersistableBundle persistentState) {
         mCanEnterPictureInPicture = true;
         restoreHasCurrentPermissionRequest(icicle);
@@ -7425,6 +7483,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public final boolean isResumed() {
         return mResumed;
     }
@@ -7442,6 +7501,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data,
             String reason) {
         if (false) Log.v(
@@ -7809,6 +7869,7 @@
      * @param disable {@code true} to disable preview screenshots; {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDisablePreviewScreenshots(boolean disable) {
         try {
             ActivityTaskManager.getService().setDisablePreviewScreenshots(mToken, disable);
@@ -7872,6 +7933,7 @@
      * @hide
      */
     @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
+    @UnsupportedAppUsage
     public void registerRemoteAnimations(RemoteAnimationDefinition definition) {
         try {
             ActivityTaskManager.getService().registerRemoteAnimations(mToken, definition);
diff --git a/core/java/android/app/ActivityGroup.java b/core/java/android/app/ActivityGroup.java
index 228067c..d4aa01b 100644
--- a/core/java/android/app/ActivityGroup.java
+++ b/core/java/android/app/ActivityGroup.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.os.Bundle;
 
@@ -37,6 +38,7 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected LocalActivityManager mLocalActivityManager;
     
     public ActivityGroup() {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 3f579bc..8354235 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+
 import android.Manifest;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
@@ -25,10 +27,10 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.IPackageDataObserver;
@@ -60,7 +62,6 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.WorkSource;
-import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.Singleton;
@@ -123,6 +124,7 @@
 public class ActivityManager {
     private static String TAG = "ActivityManager";
 
+    @UnsupportedAppUsage
     private final Context mContext;
 
     private static volatile boolean sSystemReady = false;
@@ -425,6 +427,7 @@
      * for a startActivity operation.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int INTENT_SENDER_ACTIVITY = 2;
 
     /**
@@ -488,18 +491,22 @@
 
     /** @hide Process is hosting the current top activities.  Note that this covers
      * all activities that are visible to the user. */
+    @UnsupportedAppUsage
     public static final int PROCESS_STATE_TOP = 2;
 
     /** @hide Process is hosting a foreground service. */
+    @UnsupportedAppUsage
     public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
 
     /** @hide Process is hosting a foreground service due to a system binding. */
+    @UnsupportedAppUsage
     public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 4;
 
     /** @hide Process is important to the user, and something they are aware of. */
     public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 5;
 
     /** @hide Process is important to the user, but not something they are aware of. */
+    @UnsupportedAppUsage
     public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 6;
 
     /** @hide Process is in the background transient so we will try to keep running. */
@@ -511,12 +518,14 @@
     /** @hide Process is in the background running a service.  Unlike oom_adj, this level
      * is used for both the normal running in background state and the executing
      * operations state. */
+    @UnsupportedAppUsage
     public static final int PROCESS_STATE_SERVICE = 9;
 
     /** @hide Process is in the background running a receiver.   Note that from the
      * perspective of oom_adj, receivers run at a higher foreground level, but for our
      * prioritization here that is not necessary and putting them below services means
      * many fewer changes in some process states as they receive broadcasts. */
+    @UnsupportedAppUsage
     public static final int PROCESS_STATE_RECEIVER = 10;
 
     /** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */
@@ -527,12 +536,14 @@
     public static final int PROCESS_STATE_HEAVY_WEIGHT = 12;
 
     /** @hide Process is in the background but hosts the home activity. */
+    @UnsupportedAppUsage
     public static final int PROCESS_STATE_HOME = 13;
 
     /** @hide Process is in the background but hosts the last shown activity. */
     public static final int PROCESS_STATE_LAST_ACTIVITY = 14;
 
     /** @hide Process is being cached for later use and contains activities. */
+    @UnsupportedAppUsage
     public static final int PROCESS_STATE_CACHED_ACTIVITY = 15;
 
     /** @hide Process is being cached for later use and is a client of another cached
@@ -679,6 +690,7 @@
 
     Point mAppTaskThumbnailSize;
 
+    @UnsupportedAppUsage
     /*package*/ ActivityManager(Context context, Handler handler) {
         mContext = context;
     }
@@ -810,6 +822,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     static public int staticGetMemoryClass() {
         // Really brain dead right now -- just take this from the configured
         // vm heap size, and assume it is in megabytes and thus ends with "m".
@@ -856,6 +869,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isLowRamDeviceStatic() {
         return RoSystemProperties.CONFIG_LOW_RAM ||
                 (Build.IS_DEBUGGABLE && DEVELOPMENT_FORCE_LOW_RAM);
@@ -879,6 +893,7 @@
      * (which tends to consume a lot more RAM).
      * @hide
      */
+    @UnsupportedAppUsage
     static public boolean isHighEndGfx() {
         return !isLowRamDeviceStatic()
                 && !RoSystemProperties.CONFIG_AVOID_GFX_ACCEL
@@ -903,6 +918,7 @@
      * @deprecated Use {@link ActivityTaskManager#getMaxRecentTasksStatic()}
      */
     @Deprecated
+    @UnsupportedAppUsage
     static public int getMaxRecentTasksStatic() {
         return ActivityTaskManager.getMaxRecentTasksStatic();
     }
@@ -1122,6 +1138,7 @@
          * Sets the icon for this task description.
          * @hide
          */
+        @UnsupportedAppUsage
         public void setIcon(Bitmap icon) {
             mIcon = icon;
         }
@@ -1174,11 +1191,13 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public Bitmap getInMemoryIcon() {
             return mIcon;
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static Bitmap loadTaskDescriptionIcon(String iconFilename, int userId) {
             if (iconFilename != null) {
                 try {
@@ -1202,6 +1221,7 @@
          * @return The background color.
          * @hide
          */
+        @UnsupportedAppUsage
         public int getBackgroundColor() {
             return mColorBackground;
         }
@@ -1323,197 +1343,66 @@
      * Information you can retrieve about tasks that the user has most recently
      * started or visited.
      */
-    public static class RecentTaskInfo implements Parcelable {
+    public static class RecentTaskInfo extends TaskInfo implements Parcelable {
         /**
          * If this task is currently running, this is the identifier for it.
          * If it is not running, this will be -1.
+         *
+         * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, use
+         * {@link RecentTaskInfo#taskId} to get the task id and {@link RecentTaskInfo#isRunning}
+         * to determine if it is running.
          */
+        @Deprecated
         public int id;
 
         /**
          * The true identifier of this task, valid even if it is not running.
+         *
+         * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, use
+         * {@link RecentTaskInfo#taskId}.
          */
+        @Deprecated
         public int persistentId;
 
         /**
-         * The original Intent used to launch the task.  You can use this
-         * Intent to re-launch the task (if it is no longer running) or bring
-         * the current task to the front.
-         */
-        public Intent baseIntent;
-
-        /**
-         * If this task was started from an alias, this is the actual
-         * activity component that was initially started; the component of
-         * the baseIntent in this case is the name of the actual activity
-         * implementation that the alias referred to.  Otherwise, this is null.
-         */
-        public ComponentName origActivity;
-
-        /**
-         * The actual activity component that started the task.
-         * @hide
-         */
-        @Nullable
-        public ComponentName realActivity;
-
-        /**
          * Description of the task's last state.
+         *
+         * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, currently always null.
          */
+        @Deprecated
         public CharSequence description;
 
         /**
-         * The id of the ActivityStack this Task was on most recently.
-         * @hide
-         */
-        public int stackId;
-
-        /**
-         * The id of the user the task was running as.
-         * @hide
-         */
-        public int userId;
-
-        /**
-         * The first time this task was active.
-         * @hide
-         */
-        public long firstActiveTime;
-
-        /**
-         * The last time this task was active.
-         * @hide
-         */
-        public long lastActiveTime;
-
-        /**
-         * The recent activity values for the highest activity in the stack to have set the values.
-         * {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.
-         */
-        public TaskDescription taskDescription;
-
-        /**
          * Task affiliation for grouping with other tasks.
+         *
+         * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, currently always 0.
          */
+        @Deprecated
         public int affiliatedTaskId;
 
-        /**
-         * Task affiliation color of the source task with the affiliated task id.
-         *
-         * @hide
-         */
-        public int affiliatedTaskColor;
-
-        /**
-         * The component launched as the first activity in the task.
-         * This can be considered the "application" of this task.
-         */
-        public ComponentName baseActivity;
-
-        /**
-         * The activity component at the top of the history stack of the task.
-         * This is what the user is currently doing.
-         */
-        public ComponentName topActivity;
-
-        /**
-         * Number of activities in this task.
-         */
-        public int numActivities;
-
-        /**
-         * The bounds of the task.
-         * @hide
-         */
-        public Rect bounds;
-
-        /**
-         * True if the task can go in the docked stack.
-         * @hide
-         */
-        public boolean supportsSplitScreenMultiWindow;
-
-        /**
-         * The resize mode of the task. See {@link ActivityInfo#resizeMode}.
-         * @hide
-         */
-        public int resizeMode;
-
-        /**
-         * The current configuration this task is in.
-         * @hide
-         */
-        final public Configuration configuration = new Configuration();
-
         public RecentTaskInfo() {
         }
 
+        private RecentTaskInfo(Parcel source) {
+            readFromParcel(source);
+        }
+
         @Override
         public int describeContents() {
             return 0;
         }
 
+        public void readFromParcel(Parcel source) {
+            id = source.readInt();
+            persistentId = source.readInt();
+            super.readFromParcel(source);
+        }
+
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(id);
             dest.writeInt(persistentId);
-            if (baseIntent != null) {
-                dest.writeInt(1);
-                baseIntent.writeToParcel(dest, 0);
-            } else {
-                dest.writeInt(0);
-            }
-            ComponentName.writeToParcel(origActivity, dest);
-            ComponentName.writeToParcel(realActivity, dest);
-            TextUtils.writeToParcel(description, dest,
-                    Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            if (taskDescription != null) {
-                dest.writeInt(1);
-                taskDescription.writeToParcel(dest, 0);
-            } else {
-                dest.writeInt(0);
-            }
-            dest.writeInt(stackId);
-            dest.writeInt(userId);
-            dest.writeLong(lastActiveTime);
-            dest.writeInt(affiliatedTaskId);
-            dest.writeInt(affiliatedTaskColor);
-            ComponentName.writeToParcel(baseActivity, dest);
-            ComponentName.writeToParcel(topActivity, dest);
-            dest.writeInt(numActivities);
-            if (bounds != null) {
-                dest.writeInt(1);
-                bounds.writeToParcel(dest, 0);
-            } else {
-                dest.writeInt(0);
-            }
-            dest.writeInt(supportsSplitScreenMultiWindow ? 1 : 0);
-            dest.writeInt(resizeMode);
-            configuration.writeToParcel(dest, flags);
-        }
-
-        public void readFromParcel(Parcel source) {
-            id = source.readInt();
-            persistentId = source.readInt();
-            baseIntent = source.readInt() > 0 ? Intent.CREATOR.createFromParcel(source) : null;
-            origActivity = ComponentName.readFromParcel(source);
-            realActivity = ComponentName.readFromParcel(source);
-            description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-            taskDescription = source.readInt() > 0 ?
-                    TaskDescription.CREATOR.createFromParcel(source) : null;
-            stackId = source.readInt();
-            userId = source.readInt();
-            lastActiveTime = source.readLong();
-            affiliatedTaskId = source.readInt();
-            affiliatedTaskColor = source.readInt();
-            baseActivity = ComponentName.readFromParcel(source);
-            topActivity = ComponentName.readFromParcel(source);
-            numActivities = source.readInt();
-            bounds = source.readInt() > 0 ?
-                    Rect.CREATOR.createFromParcel(source) : null;
-            supportsSplitScreenMultiWindow = source.readInt() == 1;
-            resizeMode = source.readInt();
-            configuration.readFromParcel(source);
+            super.writeToParcel(dest, flags);
         }
 
         public static final Creator<RecentTaskInfo> CREATOR
@@ -1526,8 +1415,40 @@
             }
         };
 
-        private RecentTaskInfo(Parcel source) {
-            readFromParcel(source);
+        /**
+         * @hide
+         */
+        public void dump(PrintWriter pw, String indent) {
+            final String activityType = WindowConfiguration.activityTypeToString(
+                    configuration.windowConfiguration.getActivityType());
+            final String windowingMode = WindowConfiguration.activityTypeToString(
+                    configuration.windowConfiguration.getActivityType());
+
+            pw.println(); pw.print("   ");
+            pw.print(" id=" + persistentId);
+            pw.print(" stackId=" + stackId);
+            pw.print(" userId=" + userId);
+            pw.print(" hasTask=" + (id != -1));
+            pw.print(" lastActiveTime=" + lastActiveTime);
+            pw.println(); pw.print("   ");
+            pw.print(" baseIntent=" + baseIntent);
+            pw.println(); pw.print("   ");
+            pw.print(" isExcluded="
+                    + ((baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0));
+            pw.print(" activityType=" + activityType);
+            pw.print(" windowingMode=" + windowingMode);
+            pw.print(" supportsSplitScreenMultiWindow=" + supportsSplitScreenMultiWindow);
+            if (taskDescription != null) {
+                pw.println(); pw.print("   ");
+                final ActivityManager.TaskDescription td = taskDescription;
+                pw.print(" taskDescription {");
+                pw.print(" colorBackground=#" + Integer.toHexString(td.getBackgroundColor()));
+                pw.print(" colorPrimary=#" + Integer.toHexString(td.getPrimaryColor()));
+                pw.print(" iconRes=" + (td.getIconResource() != 0));
+                pw.print(" iconBitmap=" + (td.getIconFilename() != null
+                        || td.getInMemoryIcon() != null));
+                pw.println(" }");
+            }
         }
     }
 
@@ -1596,119 +1517,62 @@
      * the system may have killed its process and is only holding on to its
      * last state in order to restart it when the user returns.
      */
-    public static class RunningTaskInfo implements Parcelable {
+    public static class RunningTaskInfo extends TaskInfo implements Parcelable {
+
         /**
          * A unique identifier for this task.
+         *
+         * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, use
+         * {@link RunningTaskInfo#taskId}.
          */
+        @Deprecated
         public int id;
 
         /**
-         * The stack that currently contains this task.
-         * @hide
+         * Thumbnail representation of the task's current state.
+         *
+         * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, currently always null.
          */
-        public int stackId;
-
-        /**
-         * The component launched as the first activity in the task.  This can
-         * be considered the "application" of this task.
-         */
-        public ComponentName baseActivity;
-
-        /**
-         * The activity component at the top of the history stack of the task.
-         * This is what the user is currently doing.
-         */
-        public ComponentName topActivity;
-
-        /**
-         * Thumbnail representation of the task's current state.  Currently
-         * always null.
-         */
+        @Deprecated
         public Bitmap thumbnail;
 
         /**
          * Description of the task's current state.
+         *
+         * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, currently always null.
          */
+        @Deprecated
         public CharSequence description;
 
         /**
-         * Number of activities in this task.
+         * Number of activities that are currently running (not stopped and persisted) in this task.
+         *
+         * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, currently always 0.
          */
-        public int numActivities;
-
-        /**
-         * Number of activities that are currently running (not stopped
-         * and persisted) in this task.
-         */
+        @Deprecated
         public int numRunning;
 
-        /**
-         * Last time task was run. For sorting.
-         * @hide
-         */
-        public long lastActiveTime;
-
-        /**
-         * True if the task can go in the docked stack.
-         * @hide
-         */
-        public boolean supportsSplitScreenMultiWindow;
-
-        /**
-         * The resize mode of the task. See {@link ActivityInfo#resizeMode}.
-         * @hide
-         */
-        public int resizeMode;
-
-        /**
-         * The full configuration the task is currently running in.
-         * @hide
-         */
-        final public Configuration configuration = new Configuration();
-
         public RunningTaskInfo() {
         }
 
+        private RunningTaskInfo(Parcel source) {
+            readFromParcel(source);
+        }
+
+        @Override
         public int describeContents() {
             return 0;
         }
 
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeInt(id);
-            dest.writeInt(stackId);
-            ComponentName.writeToParcel(baseActivity, dest);
-            ComponentName.writeToParcel(topActivity, dest);
-            if (thumbnail != null) {
-                dest.writeInt(1);
-                thumbnail.writeToParcel(dest, 0);
-            } else {
-                dest.writeInt(0);
-            }
-            TextUtils.writeToParcel(description, dest,
-                    Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            dest.writeInt(numActivities);
-            dest.writeInt(numRunning);
-            dest.writeInt(supportsSplitScreenMultiWindow ? 1 : 0);
-            dest.writeInt(resizeMode);
-            configuration.writeToParcel(dest, flags);
-        }
-
         public void readFromParcel(Parcel source) {
             id = source.readInt();
-            stackId = source.readInt();
-            baseActivity = ComponentName.readFromParcel(source);
-            topActivity = ComponentName.readFromParcel(source);
-            if (source.readInt() != 0) {
-                thumbnail = Bitmap.CREATOR.createFromParcel(source);
-            } else {
-                thumbnail = null;
-            }
-            description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-            numActivities = source.readInt();
-            numRunning = source.readInt();
-            supportsSplitScreenMultiWindow = source.readInt() != 0;
-            resizeMode = source.readInt();
-            configuration.readFromParcel(source);
+            super.readFromParcel(source);
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(id);
+            super.writeToParcel(dest, flags);
         }
 
         public static final Creator<RunningTaskInfo> CREATOR = new Creator<RunningTaskInfo>() {
@@ -1719,10 +1583,6 @@
                 return new RunningTaskInfo[size];
             }
         };
-
-        private RunningTaskInfo(Parcel source) {
-            readFromParcel(source);
-        }
     }
 
     /**
@@ -1923,6 +1783,7 @@
         /**
          * @return The graphic buffer representing the screenshot.
          */
+        @UnsupportedAppUsage
         public GraphicBuffer getSnapshot() {
             return mSnapshot;
         }
@@ -1930,6 +1791,7 @@
         /**
          * @return The screen orientation the screenshot was taken in.
          */
+        @UnsupportedAppUsage
         public int getOrientation() {
             return mOrientation;
         }
@@ -1938,6 +1800,7 @@
          * @return The system/content insets on the snapshot. These can be clipped off in order to
          *         remove any areas behind system bars in the snapshot.
          */
+        @UnsupportedAppUsage
         public Rect getContentInsets() {
             return mContentInsets;
         }
@@ -1945,6 +1808,7 @@
         /**
          * @return Whether this snapshot is a down-sampled version of the full resolution.
          */
+        @UnsupportedAppUsage
         public boolean isReducedResolution() {
             return mReducedResolution;
         }
@@ -1953,6 +1817,7 @@
          * @return Whether or not the snapshot is a real snapshot or an app-theme generated snapshot
          * due to the task having a secure window or having previews disabled.
          */
+        @UnsupportedAppUsage
         public boolean isRealSnapshot() {
             return mIsRealSnapshot;
         }
@@ -1983,6 +1848,7 @@
         /**
          * @return The scale this snapshot was taken in.
          */
+        @UnsupportedAppUsage
         public float getScale() {
             return mScale;
         }
@@ -2323,12 +2189,16 @@
         public boolean lowMemory;
 
         /** @hide */
+        @UnsupportedAppUsage
         public long hiddenAppThreshold;
         /** @hide */
+        @UnsupportedAppUsage
         public long secondaryServerThreshold;
         /** @hide */
+        @UnsupportedAppUsage
         public long visibleAppThreshold;
         /** @hide */
+        @UnsupportedAppUsage
         public long foregroundAppThreshold;
 
         public MemoryInfo() {
@@ -2398,17 +2268,28 @@
      * @hide
      */
     public static class StackInfo implements Parcelable {
+        @UnsupportedAppUsage
         public int stackId;
+        @UnsupportedAppUsage
         public Rect bounds = new Rect();
+        @UnsupportedAppUsage
         public int[] taskIds;
+        @UnsupportedAppUsage
         public String[] taskNames;
+        @UnsupportedAppUsage
         public Rect[] taskBounds;
+        @UnsupportedAppUsage
         public int[] taskUserIds;
+        @UnsupportedAppUsage
         public ComponentName topActivity;
+        @UnsupportedAppUsage
         public int displayId;
+        @UnsupportedAppUsage
         public int userId;
+        @UnsupportedAppUsage
         public boolean visible;
         // Index of the stack in the display's stack list, can be used for comparison of stack order
+        @UnsupportedAppUsage
         public int position;
         /**
          * The full configuration the stack is currently running in.
@@ -2498,6 +2379,7 @@
             readFromParcel(source);
         }
 
+        @UnsupportedAppUsage
         public String toString(String prefix) {
             StringBuilder sb = new StringBuilder(256);
             sb.append(prefix); sb.append("Stack id="); sb.append(stackId);
@@ -2535,6 +2417,7 @@
      */
     @RequiresPermission(anyOf={Manifest.permission.CLEAR_APP_USER_DATA,
             Manifest.permission.ACCESS_INSTANT_APPS})
+    @UnsupportedAppUsage
     public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) {
         try {
             return getService().clearApplicationUserData(packageName, false,
@@ -2559,7 +2442,6 @@
         return clearApplicationUserData(mContext.getPackageName(), null);
     }
 
-
     /**
      * Permits an application to get the persistent URI permissions granted to another.
      *
@@ -2571,17 +2453,13 @@
      * @return list of granted URI permissions
      *
      * @hide
+     * @deprecated use {@link UriGrantsManager#getGrantedUriPermissions(String)} instead.
      */
+    @Deprecated
     public ParceledListSlice<GrantedUriPermission> getGrantedUriPermissions(
             @Nullable String packageName) {
-        try {
-            @SuppressWarnings("unchecked")
-            final ParceledListSlice<GrantedUriPermission> castedList = getService()
-                    .getGrantedUriPermissions(packageName, mContext.getUserId());
-            return castedList;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return ((UriGrantsManager) mContext.getSystemService(Context.URI_GRANTS_SERVICE))
+                .getGrantedUriPermissions(packageName);
     }
 
     /**
@@ -2592,14 +2470,12 @@
      * @param packageName application to clear its granted permissions
      *
      * @hide
+     * @deprecated use {@link UriGrantsManager#clearGrantedUriPermissions(String)} instead.
      */
+    @Deprecated
     public void clearGrantedUriPermissions(String packageName) {
-        try {
-            getService().clearGrantedUriPermissions(packageName,
-                    mContext.getUserId());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        ((UriGrantsManager) mContext.getSystemService(Context.URI_GRANTS_SERVICE))
+                .clearGrantedUriPermissions(packageName);
     }
 
     /**
@@ -2759,6 +2635,7 @@
          * persistent system app.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int FLAG_PERSISTENT = 1<<1;
 
         /**
@@ -2766,6 +2643,7 @@
          * persistent system app.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int FLAG_HAS_ACTIVITIES = 1<<2;
 
         /**
@@ -2773,6 +2651,7 @@
          * {@link #FLAG_CANT_SAVE_STATE}.
          * @hide
          */
+        @UnsupportedAppUsage
         public int flags;
 
         /**
@@ -2868,6 +2747,7 @@
          *
          * @hide
          */
+        @TestApi
         public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170;
 
         /**
@@ -2926,6 +2806,7 @@
          * will be passed to a client, use {@link #procStateToImportanceForClient}.
          * @hide
          */
+        @UnsupportedAppUsage
         public static @Importance int procStateToImportance(int procState) {
             if (procState == PROCESS_STATE_NONEXISTENT) {
                 return IMPORTANCE_GONE;
@@ -3078,6 +2959,7 @@
          * Current process state, as per PROCESS_STATE_* constants.
          * @hide
          */
+        @UnsupportedAppUsage
         public int processState;
 
         /**
@@ -3385,6 +3267,13 @@
      * <p><b>Note: this method is only intended for debugging or building
      * a user-facing process management UI.</b></p>
      *
+     * <p>As of {@link android.os.Build.VERSION_CODES#Q Android Q}, for regular apps this method
+     * will only return information about the memory info for the processes running as the
+     * caller's uid; no other process memory info is available and will be zero.
+     * Also of {@link android.os.Build.VERSION_CODES#Q Android Q} the sample rate allowed
+     * by this API is significantly limited, if called faster the limit you will receive the
+     * same data as the previous call.</p>
+     *
      * @param pids The pids of the processes whose memory usage is to be
      * retrieved.
      * @return Returns an array of memory information, one for each
@@ -3466,6 +3355,7 @@
      * it allowing them to break other applications by stopping their
      * services, removing their alarms, etc.
      */
+    @UnsupportedAppUsage
     public void forceStopPackageAsUser(String packageName, int userId) {
         try {
             getService().forceStopPackage(packageName, userId);
@@ -3478,7 +3368,7 @@
      * @see #forceStopPackageAsUser(String, int)
      * @hide
      */
-    @SystemApi
+    @SystemApi @TestApi
     @RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)
     public void forceStopPackage(String packageName) {
         forceStopPackageAsUser(packageName, mContext.getUserId());
@@ -3642,6 +3532,7 @@
     }*/
 
     /** @hide */
+    @UnsupportedAppUsage
     public static int checkComponentPermission(String permission, int uid,
             int owningUid, boolean exported) {
         // Root, system server get to do everything.
@@ -3749,6 +3640,7 @@
      * @param userid the user's id. Zero indicates the default user.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean switchUser(int userid) {
         try {
             return getService().switchUser(userid);
@@ -3792,6 +3684,7 @@
      * @param userId the user's id. Zero indicates the default user.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isUserRunning(int userId) {
         try {
             return getService().isUserRunning(userId, 0);
@@ -3923,6 +3816,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static IActivityManager getService() {
         return IActivityManagerSingleton.get();
     }
@@ -3931,6 +3825,7 @@
         return ActivityTaskManager.getService();
     }
 
+    @UnsupportedAppUsage
     private static final Singleton<IActivityManager> IActivityManagerSingleton =
             new Singleton<IActivityManager>() {
                 @Override
@@ -4100,6 +3995,19 @@
     }
 
     /**
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.CHANGE_CONFIGURATION)
+    public void scheduleApplicationInfoChanged(List<String> packages, int userId) {
+        try {
+            getService().scheduleApplicationInfoChanged(packages, userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * The AppTask allows you to manage your own application's tasks.
      * See {@link android.app.ActivityManager#getAppTasks()}
      */
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index e5cfe84..87366db 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -18,20 +18,13 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.ComponentName;
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
-import android.content.res.Configuration;
-import android.os.Bundle;
+import android.content.pm.UserInfo;
 import android.os.IBinder;
-import android.os.SystemClock;
-import android.service.voice.IVoiceInteractionSession;
-import android.util.SparseIntArray;
 import android.view.RemoteAnimationAdapter;
 
-import com.android.internal.app.IVoiceInteractor;
-
 import java.util.ArrayList;
 import java.util.List;
 
@@ -49,13 +42,6 @@
     public static final int ALLOW_FULL_ONLY = 2;
 
     /**
-     * Grant Uri permissions from one app to another. This method only extends
-     * permission grants if {@code callingUid} has permission to them.
-     */
-    public abstract void grantUriPermissionFromIntent(int callingUid, String targetPkg,
-            Intent intent, int targetUserId);
-
-    /**
      * Verify that calling app has access to the given provider.
      */
     public abstract String checkContentProviderAccess(String authority, int userId);
@@ -213,4 +199,31 @@
      * Returns {@code true} if {@code uid} is running an activity from {@code packageName}.
      */
     public abstract boolean hasRunningActivity(int uid, @Nullable String packageName);
+
+    public abstract void updateOomAdj();
+    public abstract void sendForegroundProfileChanged(int userId);
+
+    /**
+     * Returns whether the given user requires credential entry at this time. This is used to
+     * intercept activity launches for work apps when the Work Challenge is present.
+     */
+    public abstract boolean shouldConfirmCredentials(int userId);
+
+    /**
+     * @return The intent used to launch the home activity.
+     */
+    public abstract Intent getHomeIntent();
+
+    public abstract int[] getCurrentProfileIds();
+    public abstract UserInfo getCurrentUser();
+    public abstract void ensureNotSpecialUser(int userId);
+    public abstract boolean isCurrentProfile(int userId);
+    public abstract boolean hasStartedUserState(int userId);
+    public abstract void finishUserSwitch(Object uss);
+
+    /** Schedule the execution of all pending app GCs. */
+    public abstract void scheduleAppGcs();
+
+    /** Gets the task id for a given activity. */
+    public abstract int getTaskIdForActivity(@NonNull IBinder token, boolean onlyRoot);
 }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 4c558f3..37509e1 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -15,6 +15,7 @@
  */
 
 package android.app;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.os.IBinder;
 
@@ -30,6 +31,7 @@
      *
      * @deprecated use IActivityManager.Stub.asInterface instead.
      */
+    @UnsupportedAppUsage
     static public IActivityManager asInterface(IBinder obj) {
         return IActivityManager.Stub.asInterface(obj);
     }
@@ -39,6 +41,7 @@
      *
      * @deprecated use ActivityManager.getService instead.
      */
+    @UnsupportedAppUsage
     static public IActivityManager getDefault() {
         return ActivityManager.getService();
     }
@@ -48,6 +51,7 @@
      *
      * @deprecated use ActivityManagerInternal.isSystemReady instead.
      */
+    @UnsupportedAppUsage
     static public boolean isSystemReady() {
         return ActivityManager.isSystemReady();
     }
@@ -55,6 +59,7 @@
     /**
      * @deprecated use ActivityManager.broadcastStickyIntent instead.
      */
+    @UnsupportedAppUsage
     static public void broadcastStickyIntent(Intent intent, String permission, int userId) {
         broadcastStickyIntent(intent, permission, AppOpsManager.OP_NONE, userId);
     }
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 89408cc..63c61d3 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -25,6 +25,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -302,7 +303,6 @@
     private int mResultCode;
     private int mExitCoordinatorIndex;
     private PendingIntent mUsageTimeReport;
-    private boolean mLockTaskMode = false;
     private int mLaunchDisplayId = INVALID_DISPLAY;
     @WindowConfiguration.WindowingMode
     private int mLaunchWindowingMode = WINDOWING_MODE_UNDEFINED;
@@ -310,6 +310,7 @@
     private int mLaunchActivityType = ACTIVITY_TYPE_UNDEFINED;
     private int mLaunchTaskId = -1;
     private int mSplitScreenCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+    private boolean mLockTaskMode = false;
     private boolean mDisallowEnterPictureInPictureWhileLaunching;
     private boolean mTaskOverlay;
     private boolean mTaskOverlayCanResume;
@@ -357,6 +358,7 @@
      * supply these options as the options Bundle when starting an activity.
      * @hide
      */
+    @UnsupportedAppUsage
     public static ActivityOptions makeCustomAnimation(Context context,
             int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {
         ActivityOptions opts = new ActivityOptions();
@@ -582,6 +584,7 @@
      * thumbnails are aspect scaled to/from a new location.
      * @hide
      */
+    @UnsupportedAppUsage
     public static ActivityOptions makeMultiThumbFutureAspectScaleAnimation(Context context,
             Handler handler, IAppTransitionAnimationSpecsFuture specsFuture,
             OnAnimationStartedListener listener, boolean scaleUp) {
@@ -847,6 +850,7 @@
      * @hide
      */
     @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
+    @UnsupportedAppUsage
     public static ActivityOptions makeRemoteAnimation(
             RemoteAnimationAdapter remoteAnimationAdapter) {
         final ActivityOptions opts = new ActivityOptions();
@@ -946,7 +950,7 @@
             mAnimationFinishedListener = IRemoteCallback.Stub.asInterface(
                     opts.getBinder(KEY_ANIMATION_FINISHED_LISTENER));
         }
-        mRotationAnimationHint = opts.getInt(KEY_ROTATION_ANIMATION_HINT);
+        mRotationAnimationHint = opts.getInt(KEY_ROTATION_ANIMATION_HINT, -1);
         mAppVerificationBundle = opts.getBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE);
         if (opts.containsKey(KEY_SPECS_FUTURE)) {
             mSpecsFuture = IAppTransitionAnimationSpecsFuture.Stub.asInterface(opts.getBinder(
@@ -956,14 +960,15 @@
     }
 
     /**
-     * Sets the bounds (window size) that the activity should be launched in.
+     * Sets the bounds (window size and position) that the activity should be launched in.
      * Rect position should be provided in pixels and in screen coordinates.
-     * Set to null explicitly for fullscreen.
+     * Set to {@code null} to explicitly launch fullscreen.
      * <p>
-     * <strong>NOTE:<strong/> This value is ignored on devices that don't have
+     * <strong>NOTE:</strong> This value is ignored on devices that don't have
      * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or
      * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
-     * @param screenSpacePixelRect Launch bounds to use for the activity or null for fullscreen.
+     * @param screenSpacePixelRect launch bounds or {@code null} for fullscreen
+     * @return {@code this} {@link ActivityOptions} instance
      */
     public ActivityOptions setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
         mLaunchBounds = screenSpacePixelRect != null ? new Rect(screenSpacePixelRect) : null;
@@ -1278,6 +1283,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setSplitScreenCreateMode(int splitScreenCreateMode) {
         mSplitScreenCreateMode = splitScreenCreateMode;
     }
@@ -1442,17 +1448,37 @@
                 b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
                 break;
         }
-        b.putBoolean(KEY_LOCK_TASK_MODE, mLockTaskMode);
-        b.putInt(KEY_LAUNCH_DISPLAY_ID, mLaunchDisplayId);
-        b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode);
-        b.putInt(KEY_LAUNCH_ACTIVITY_TYPE, mLaunchActivityType);
-        b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
-        b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
-        b.putBoolean(KEY_TASK_OVERLAY_CAN_RESUME, mTaskOverlayCanResume);
-        b.putBoolean(KEY_AVOID_MOVE_TO_FRONT, mAvoidMoveToFront);
-        b.putInt(KEY_SPLIT_SCREEN_CREATE_MODE, mSplitScreenCreateMode);
-        b.putBoolean(KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING,
-                mDisallowEnterPictureInPictureWhileLaunching);
+        if (mLockTaskMode) {
+            b.putBoolean(KEY_LOCK_TASK_MODE, mLockTaskMode);
+        }
+        if (mLaunchDisplayId != INVALID_DISPLAY) {
+            b.putInt(KEY_LAUNCH_DISPLAY_ID, mLaunchDisplayId);
+        }
+        if (mLaunchWindowingMode != WINDOWING_MODE_UNDEFINED) {
+            b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode);
+        }
+        if (mLaunchActivityType != ACTIVITY_TYPE_UNDEFINED) {
+            b.putInt(KEY_LAUNCH_ACTIVITY_TYPE, mLaunchActivityType);
+        }
+        if (mLaunchTaskId != -1) {
+            b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
+        }
+        if (mTaskOverlay) {
+            b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
+        }
+        if (mTaskOverlayCanResume) {
+            b.putBoolean(KEY_TASK_OVERLAY_CAN_RESUME, mTaskOverlayCanResume);
+        }
+        if (mAvoidMoveToFront) {
+            b.putBoolean(KEY_AVOID_MOVE_TO_FRONT, mAvoidMoveToFront);
+        }
+        if (mSplitScreenCreateMode != SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT) {
+            b.putInt(KEY_SPLIT_SCREEN_CREATE_MODE, mSplitScreenCreateMode);
+        }
+        if (mDisallowEnterPictureInPictureWhileLaunching) {
+            b.putBoolean(KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING,
+                    mDisallowEnterPictureInPictureWhileLaunching);
+        }
         if (mAnimSpecs != null) {
             b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs);
         }
@@ -1462,7 +1488,9 @@
         if (mSpecsFuture != null) {
             b.putBinder(KEY_SPECS_FUTURE, mSpecsFuture.asBinder());
         }
-        b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint);
+        if (mRotationAnimationHint != -1) {
+            b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint);
+        }
         if (mAppVerificationBundle != null) {
             b.putBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE, mAppVerificationBundle);
         }
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 398644af..af8aa4e 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -29,6 +29,8 @@
 import android.os.ServiceManager;
 import android.util.Singleton;
 
+import java.util.List;
+
 /**
  * This class gives information about, and interacts with activities and their containers like task,
  * stacks, and displays.
@@ -204,6 +206,19 @@
     }
 
     /**
+     * Removes all visible recent tasks from the system.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.REMOVE_TASKS)
+    public void removeAllVisibleRecentTasks() {
+        try {
+            getService().removeAllVisibleRecentTasks();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Return the maximum number of recents entries that we will maintain and show.
      * @hide
      */
@@ -250,4 +265,140 @@
                 && Resources.getSystem().getBoolean(
                 com.android.internal.R.bool.config_supportsSplitScreenMultiWindow);
     }
+
+    /**
+     * Moves the top activity in the input stackId to the pinned stack.
+     * @param stackId Id of stack to move the top activity to pinned stack.
+     * @param bounds Bounds to use for pinned stack.
+     * @return True if the top activity of stack was successfully moved to the pinned stack.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) {
+        try {
+            return getService().moveTopActivityToPinnedStack(stackId, bounds);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Start to enter lock task mode for given task by system(UI).
+     * @param taskId Id of task to lock.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void startSystemLockTaskMode(int taskId) {
+        try {
+            getService().startSystemLockTaskMode(taskId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Stop lock task mode by system(UI).
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void stopSystemLockTaskMode() {
+        try {
+            getService().stopSystemLockTaskMode();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Move task to stack with given id.
+     * @param taskId Id of the task to move.
+     * @param stackId Id of the stack for task moving.
+     * @param toTop Whether the given task should shown to top of stack.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
+        try {
+            getService().moveTaskToStack(taskId, stackId, toTop);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Resize the input stack id to the given bounds with animate setting.
+     * @param stackId Id of the stack to resize.
+     * @param bounds Bounds to resize the stack to or {@code null} for fullscreen.
+     * @param animate Whether we should play an animation for resizing stack.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void resizeStack(int stackId, Rect bounds, boolean animate) {
+        try {
+            getService().resizeStack(stackId, bounds, false, false, animate /* animate */,
+                    -1 /* animationDuration */);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Resize task to given bounds.
+     * @param taskId Id of task to resize.
+     * @param bounds Bounds to resize task.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void resizeTask(int taskId, Rect bounds) {
+        try {
+            getService().resizeTask(taskId, bounds, RESIZE_MODE_SYSTEM);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Resize docked stack & its task to given stack & task bounds.
+     * @param stackBounds Bounds to resize stack.
+     * @param taskBounds Bounds to resize task.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void resizeDockedStack(Rect stackBounds, Rect taskBounds) {
+        try {
+            getService().resizeDockedStack(stackBounds, taskBounds, null, null, null);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * List all activity stacks information.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public String listAllStacks() {
+        final List<ActivityManager.StackInfo> stacks;
+        try {
+            stacks = getService().getAllStackInfos();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        final StringBuilder sb = new StringBuilder();
+        if (stacks != null) {
+            for (ActivityManager.StackInfo info : stacks) {
+                sb.append(info).append("\n");
+            }
+        }
+        return sb.toString();
+    }
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f3c6731..9120701 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -27,6 +27,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.app.backup.BackupAgent;
@@ -35,6 +36,7 @@
 import android.app.servertransaction.ActivityRelaunchItem;
 import android.app.servertransaction.ActivityResultItem;
 import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.ClientTransactionItem;
 import android.app.servertransaction.PendingTransactionActions;
 import android.app.servertransaction.PendingTransactionActions.StopInfo;
 import android.app.servertransaction.TransactionExecutor;
@@ -147,6 +149,7 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.Preconditions;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.org.conscrypt.OpenSSLSocketImpl;
 import com.android.org.conscrypt.TrustedCertificateStore;
@@ -176,6 +179,7 @@
 import java.text.DateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -247,42 +251,63 @@
     @GuardedBy("mNetworkPolicyLock")
     private long mNetworkBlockSeq = INVALID_PROC_STATE_SEQ;
 
+    @UnsupportedAppUsage
     private ContextImpl mSystemContext;
     private ContextImpl mSystemUiContext;
 
+    @UnsupportedAppUsage
     static volatile IPackageManager sPackageManager;
 
+    @UnsupportedAppUsage
     final ApplicationThread mAppThread = new ApplicationThread();
+    @UnsupportedAppUsage
     final Looper mLooper = Looper.myLooper();
+    @UnsupportedAppUsage
     final H mH = new H();
     final Executor mExecutor = new HandlerExecutor(mH);
+    @UnsupportedAppUsage
     final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
+    /** The activities to be truly destroyed (not include relaunch). */
+    final Map<IBinder, ClientTransactionItem> mActivitiesToBeDestroyed =
+            Collections.synchronizedMap(new ArrayMap<IBinder, ClientTransactionItem>());
     // List of new activities (via ActivityRecord.nextIdle) that should
     // be reported when next we idle.
     ActivityClientRecord mNewActivities = null;
     // Number of activities that are currently visible on-screen.
+    @UnsupportedAppUsage
     int mNumVisibleActivities = 0;
     ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
     private int mLastSessionId;
+    @UnsupportedAppUsage
     final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
+    @UnsupportedAppUsage
     AppBindData mBoundApplication;
     Profiler mProfiler;
+    @UnsupportedAppUsage
     int mCurDefaultDisplayDpi;
+    @UnsupportedAppUsage
     boolean mDensityCompatMode;
+    @UnsupportedAppUsage
     Configuration mConfiguration;
     Configuration mCompatConfiguration;
+    @UnsupportedAppUsage
     Application mInitialApplication;
+    @UnsupportedAppUsage
     final ArrayList<Application> mAllApplications
             = new ArrayList<Application>();
     // set of instantiated backup agents, keyed by package name
     final ArrayMap<String, BackupAgent> mBackupAgents = new ArrayMap<String, BackupAgent>();
     /** Reference to singleton {@link ActivityThread} */
+    @UnsupportedAppUsage
     private static volatile ActivityThread sCurrentActivityThread;
+    @UnsupportedAppUsage
     Instrumentation mInstrumentation;
     String mInstrumentationPackageName = null;
+    @UnsupportedAppUsage
     String mInstrumentationAppDir = null;
     String[] mInstrumentationSplitAppDirs = null;
     String mInstrumentationLibDir = null;
+    @UnsupportedAppUsage
     String mInstrumentedAppDir = null;
     String[] mInstrumentedSplitAppDirs = null;
     String mInstrumentedLibDir = null;
@@ -302,16 +327,20 @@
     // or window manager or anything that depends on them while holding this lock.
     // These LoadedApk are only valid for the userId that we're running as.
     @GuardedBy("mResourcesManager")
+    @UnsupportedAppUsage
     final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<>();
     @GuardedBy("mResourcesManager")
+    @UnsupportedAppUsage
     final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<>();
     @GuardedBy("mResourcesManager")
     final ArrayList<ActivityClientRecord> mRelaunchingActivities = new ArrayList<>();
     @GuardedBy("mResourcesManager")
+    @UnsupportedAppUsage
     Configuration mPendingConfiguration = null;
     // An executor that performs multi-step transactions.
     private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
 
+    @UnsupportedAppUsage
     private final ResourcesManager mResourcesManager;
 
     private static final class ProviderKey {
@@ -339,12 +368,16 @@
     }
 
     // The lock of mProviderMap protects the following variables.
+    @UnsupportedAppUsage
     final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
         = new ArrayMap<ProviderKey, ProviderClientRecord>();
+    @UnsupportedAppUsage
     final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap
         = new ArrayMap<IBinder, ProviderRefCount>();
+    @UnsupportedAppUsage
     final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders
         = new ArrayMap<IBinder, ProviderClientRecord>();
+    @UnsupportedAppUsage
     final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName
             = new ArrayMap<ComponentName, ProviderClientRecord>();
 
@@ -361,26 +394,32 @@
     final GcIdler mGcIdler = new GcIdler();
     boolean mGcIdlerScheduled = false;
 
+    @UnsupportedAppUsage
     static volatile Handler sMainThreadHandler;  // set once in main()
 
     Bundle mCoreSettings = null;
 
     /** Activity client record, used for bookkeeping for the real {@link Activity} instance. */
     public static final class ActivityClientRecord {
+        @UnsupportedAppUsage
         public IBinder token;
         int ident;
+        @UnsupportedAppUsage
         Intent intent;
         String referrer;
         IVoiceInteractor voiceInteractor;
         Bundle state;
         PersistableBundle persistentState;
+        @UnsupportedAppUsage
         Activity activity;
         Window window;
         Activity parent;
         String embeddedID;
         Activity.NonConfigurationInstances lastNonConfigurationInstances;
         // TODO(lifecycler): Use mLifecycleState instead.
+        @UnsupportedAppUsage
         boolean paused;
+        @UnsupportedAppUsage
         boolean stopped;
         boolean hideForNow;
         Configuration newConfig;
@@ -394,8 +433,11 @@
 
         ProfilerInfo profilerInfo;
 
+        @UnsupportedAppUsage
         ActivityInfo activityInfo;
+        @UnsupportedAppUsage
         CompatibilityInfo compatInfo;
+        @UnsupportedAppUsage
         public LoadedApk packageInfo;
 
         List<ResultInfo> pendingResults;
@@ -407,12 +449,14 @@
 
         Window mPendingRemoveWindow;
         WindowManager mPendingRemoveWindowManager;
+        @UnsupportedAppUsage
         boolean mPreserveWindow;
 
         @LifecycleState
         private int mLifecycleState = PRE_ON_CREATE;
 
         @VisibleForTesting
+        @UnsupportedAppUsage
         public ActivityClientRecord() {
             this.isForward = false;
             init();
@@ -548,8 +592,11 @@
 
     final class ProviderClientRecord {
         final String[] mNames;
+        @UnsupportedAppUsage
         final IContentProvider mProvider;
+        @UnsupportedAppUsage
         final ContentProvider mLocalProvider;
+        @UnsupportedAppUsage
         final ContentProviderHolder mHolder;
 
         ProviderClientRecord(String[] names, IContentProvider provider,
@@ -569,8 +616,11 @@
             this.intent = intent;
         }
 
+        @UnsupportedAppUsage
         Intent intent;
+        @UnsupportedAppUsage
         ActivityInfo info;
+        @UnsupportedAppUsage
         CompatibilityInfo compatInfo;
         public String toString() {
             return "ReceiverData{intent=" + intent + " packageName=" +
@@ -592,9 +642,13 @@
     }
 
     static final class CreateServiceData {
+        @UnsupportedAppUsage
         IBinder token;
+        @UnsupportedAppUsage
         ServiceInfo info;
+        @UnsupportedAppUsage
         CompatibilityInfo compatInfo;
+        @UnsupportedAppUsage
         Intent intent;
         public String toString() {
             return "CreateServiceData{token=" + token + " className="
@@ -604,7 +658,9 @@
     }
 
     static final class BindServiceData {
+        @UnsupportedAppUsage
         IBinder token;
+        @UnsupportedAppUsage
         Intent intent;
         boolean rebind;
         public String toString() {
@@ -613,10 +669,12 @@
     }
 
     static final class ServiceArgsData {
+        @UnsupportedAppUsage
         IBinder token;
         boolean taskRemoved;
         int startId;
         int flags;
+        @UnsupportedAppUsage
         Intent args;
         public String toString() {
             return "ServiceArgsData{token=" + token + " startId=" + startId
@@ -625,20 +683,28 @@
     }
 
     static final class AppBindData {
+        @UnsupportedAppUsage
         LoadedApk info;
+        @UnsupportedAppUsage
         String processName;
+        @UnsupportedAppUsage
         ApplicationInfo appInfo;
+        @UnsupportedAppUsage
         List<ProviderInfo> providers;
         ComponentName instrumentationName;
+        @UnsupportedAppUsage
         Bundle instrumentationArgs;
         IInstrumentationWatcher instrumentationWatcher;
         IUiAutomationConnection instrumentationUiAutomationConnection;
         int debugMode;
         boolean enableBinderTracking;
         boolean trackAllocation;
+        @UnsupportedAppUsage
         boolean restrictedBackupMode;
+        @UnsupportedAppUsage
         boolean persistent;
         Configuration config;
+        @UnsupportedAppUsage
         CompatibilityInfo compatInfo;
         String buildSerial;
 
@@ -1350,14 +1416,69 @@
             IoUtils.closeQuietly(pfd);
         }
 
-        private void dumpDatabaseInfo(ParcelFileDescriptor pfd, String[] args) {
+        private File getDatabasesDir(Context context) {
+            // There's no simple way to get the databases/ path, so do it this way.
+            return context.getDatabasePath("a").getParentFile();
+        }
+
+        private void dumpDatabaseInfo(ParcelFileDescriptor pfd, String[] args, boolean isSystem) {
             PrintWriter pw = new FastPrintWriter(
                     new FileOutputStream(pfd.getFileDescriptor()));
             PrintWriterPrinter printer = new PrintWriterPrinter(pw);
             SQLiteDebug.dump(printer, args);
+
+            if (isSystem) {
+                dumpDatabaseFileSizes(pw, Environment.getDataSystemDirectory(), true);
+                dumpDatabaseFileSizes(pw, Environment.getDataSystemDeDirectory(), true);
+                dumpDatabaseFileSizes(pw, Environment.getDataSystemCeDirectory(), true);
+            } else {
+                Context context = getApplication();
+                if (context != null) {
+                    dumpDatabaseFileSizes(pw,
+                            getDatabasesDir(context.createDeviceProtectedStorageContext()),
+                            false);
+                    dumpDatabaseFileSizes(pw,
+                            getDatabasesDir(context.createCredentialProtectedStorageContext()),
+                            false);
+                }
+            }
             pw.flush();
         }
 
+        private void dumpDatabaseFileSizes(PrintWriter pw, File dir, boolean isSystem) {
+            final File[] files = dir.listFiles();
+            if (files == null || files.length == 0) {
+                return;
+            }
+            Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName()));
+
+            boolean needHeader = true;
+            for (File f : files) {
+                if (isSystem) {
+                    // If it's the system server, the directory contains other files too, so
+                    // filter by file extensions.
+                    // (If it's an app, just print all files because they may not use *.db
+                    // extension.)
+                    final String name = f.getName();
+                    if (!(name.endsWith(".db") || name.endsWith(".db-wal")
+                            || name.endsWith(".db-journal"))) {
+                        continue;
+                    }
+                }
+                if (needHeader) {
+                    pw.println();
+                    pw.println("Database files in " + dir.getAbsolutePath() + ":");
+                    needHeader = false;
+                }
+
+                pw.print("  ");
+                pw.print(f.getName());
+                pw.print("  ");
+                pw.print(f.length());
+                pw.println(" bytes");
+            }
+        }
+
         @Override
         public void dumpDbInfo(final ParcelFileDescriptor pfd, final String[] args) {
             if (mSystemThread) {
@@ -1378,14 +1499,14 @@
                     @Override
                     public void run() {
                         try {
-                            dumpDatabaseInfo(dup, args);
+                            dumpDatabaseInfo(dup, args, true);
                         } finally {
                             IoUtils.closeQuietly(dup);
                         }
                     }
                 });
             } else {
-                dumpDatabaseInfo(pfd, args);
+                dumpDatabaseInfo(pfd, args, false);
                 IoUtils.closeQuietly(pfd);
             }
         }
@@ -1556,16 +1677,24 @@
 
     class H extends Handler {
         public static final int BIND_APPLICATION        = 110;
+        @UnsupportedAppUsage
         public static final int EXIT_APPLICATION        = 111;
+        @UnsupportedAppUsage
         public static final int RECEIVER                = 113;
+        @UnsupportedAppUsage
         public static final int CREATE_SERVICE          = 114;
+        @UnsupportedAppUsage
         public static final int SERVICE_ARGS            = 115;
+        @UnsupportedAppUsage
         public static final int STOP_SERVICE            = 116;
 
         public static final int CONFIGURATION_CHANGED   = 118;
         public static final int CLEAN_UP_CONTEXT        = 119;
+        @UnsupportedAppUsage
         public static final int GC_WHEN_IDLE            = 120;
+        @UnsupportedAppUsage
         public static final int BIND_SERVICE            = 121;
+        @UnsupportedAppUsage
         public static final int UNBIND_SERVICE          = 122;
         public static final int DUMP_SERVICE            = 123;
         public static final int LOW_MEMORY              = 124;
@@ -1573,21 +1702,26 @@
         public static final int CREATE_BACKUP_AGENT     = 128;
         public static final int DESTROY_BACKUP_AGENT    = 129;
         public static final int SUICIDE                 = 130;
+        @UnsupportedAppUsage
         public static final int REMOVE_PROVIDER         = 131;
         public static final int ENABLE_JIT              = 132;
         public static final int DISPATCH_PACKAGE_BROADCAST = 133;
+        @UnsupportedAppUsage
         public static final int SCHEDULE_CRASH          = 134;
         public static final int DUMP_HEAP               = 135;
         public static final int DUMP_ACTIVITY           = 136;
         public static final int SLEEPING                = 137;
         public static final int SET_CORE_SETTINGS       = 138;
         public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
+        @UnsupportedAppUsage
         public static final int DUMP_PROVIDER           = 141;
         public static final int UNSTABLE_PROVIDER_DIED  = 142;
         public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
         public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
+        @UnsupportedAppUsage
         public static final int INSTALL_PROVIDER        = 145;
         public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
+        @UnsupportedAppUsage
         public static final int ENTER_ANIMATION_COMPLETE = 149;
         public static final int START_BINDER_TRACKING = 150;
         public static final int STOP_BINDER_TRACKING_AND_DUMP = 151;
@@ -1876,6 +2010,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static ActivityThread currentActivityThread() {
         return sCurrentActivityThread;
     }
@@ -1890,23 +2025,27 @@
                 ? am.getApplication().getOpPackageName() : null;
     }
 
+    @UnsupportedAppUsage
     public static String currentPackageName() {
         ActivityThread am = currentActivityThread();
         return (am != null && am.mBoundApplication != null)
             ? am.mBoundApplication.appInfo.packageName : null;
     }
 
+    @UnsupportedAppUsage
     public static String currentProcessName() {
         ActivityThread am = currentActivityThread();
         return (am != null && am.mBoundApplication != null)
             ? am.mBoundApplication.processName : null;
     }
 
+    @UnsupportedAppUsage
     public static Application currentApplication() {
         ActivityThread am = currentActivityThread();
         return am != null ? am.mInitialApplication : null;
     }
 
+    @UnsupportedAppUsage
     public static IPackageManager getPackageManager() {
         if (sPackageManager != null) {
             //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
@@ -1944,10 +2083,12 @@
                 displayId, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader());
     }
 
+    @UnsupportedAppUsage
     final Handler getHandler() {
         return mH;
     }
 
+    @UnsupportedAppUsage
     public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
             int flags) {
         return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());
@@ -2002,6 +2143,7 @@
         return null;
     }
 
+    @UnsupportedAppUsage
     public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
             int flags) {
         boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
@@ -2029,11 +2171,13 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
             CompatibilityInfo compatInfo) {
         return getPackageInfo(ai, compatInfo, null, false, true, false);
     }
 
+    @UnsupportedAppUsage
     public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
         synchronized (mResourcesManager) {
             WeakReference<LoadedApk> ref;
@@ -2093,15 +2237,18 @@
         }
     }
 
+    @UnsupportedAppUsage
     ActivityThread() {
         mResourcesManager = ResourcesManager.getInstance();
     }
 
+    @UnsupportedAppUsage
     public ApplicationThread getApplicationThread()
     {
         return mAppThread;
     }
 
+    @UnsupportedAppUsage
     public Instrumentation getInstrumentation()
     {
         return mInstrumentation;
@@ -2116,6 +2263,7 @@
         return mProfiler.profileFile;
     }
 
+    @UnsupportedAppUsage
     public Looper getLooper() {
         return mLooper;
     }
@@ -2124,14 +2272,17 @@
         return mExecutor;
     }
 
+    @UnsupportedAppUsage
     public Application getApplication() {
         return mInitialApplication;
     }
 
+    @UnsupportedAppUsage
     public String getProcessName() {
         return mBoundApplication.processName;
     }
 
+    @UnsupportedAppUsage
     public ContextImpl getSystemContext() {
         synchronized (this) {
             if (mSystemContext == null) {
@@ -2167,6 +2318,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void scheduleGcIdler() {
         if (!mGcIdlerScheduled) {
             mGcIdlerScheduled = true;
@@ -2663,6 +2815,7 @@
         proto.end(asToken);
     }
 
+    @UnsupportedAppUsage
     public void registerOnActivityPausedListener(Activity activity,
             OnActivityPausedListener listener) {
         synchronized (mOnPauseListeners) {
@@ -2675,6 +2828,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void unregisterOnActivityPausedListener(Activity activity,
             OnActivityPausedListener listener) {
         synchronized (mOnPauseListeners) {
@@ -2696,6 +2850,7 @@
         return aInfo;
     }
 
+    @UnsupportedAppUsage
     public final Activity startActivityNow(Activity parent, String id,
         Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
         Activity.NonConfigurationInstances lastNonConfigurationInstances) {
@@ -2726,8 +2881,10 @@
         return performLaunchActivity(r, null /* customIntent */);
     }
 
+    @UnsupportedAppUsage
     public final Activity getActivity(IBinder token) {
-        return mActivities.get(token).activity;
+        final ActivityClientRecord activityRecord = mActivities.get(token);
+        return activityRecord != null ? activityRecord.activity : null;
     }
 
     @Override
@@ -2735,6 +2892,7 @@
         return mActivities.get(token);
     }
 
+    @UnsupportedAppUsage
     public final void sendActivityResult(
             IBinder token, String id, int requestCode,
             int resultCode, Intent data) {
@@ -3073,6 +3231,10 @@
     }
 
     private void reportSizeConfigurations(ActivityClientRecord r) {
+        if (mActivitiesToBeDestroyed.containsKey(r.token)) {
+            // Size configurations of a destroyed activity is meaningless.
+            return;
+        }
         Configuration[] configurations = r.activity.getResources().getSizeConfigurations();
         if (configurations == null) {
             return;
@@ -3112,6 +3274,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void performNewIntents(IBinder token, List<ReferrerIntent> intents, boolean andPause) {
         final ActivityClientRecord r = mActivities.get(token);
         if (r == null) {
@@ -3332,6 +3495,7 @@
         return sCurrentBroadcastIntent.get();
     }
 
+    @UnsupportedAppUsage
     private void handleReceiver(ReceiverData data) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
@@ -3503,6 +3667,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void handleCreateService(CreateServiceData data) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
@@ -3821,6 +3986,13 @@
             // We didn't actually resume the activity, so skipping any follow-up actions.
             return;
         }
+        if (mActivitiesToBeDestroyed.containsKey(token)) {
+            // Although the activity is resumed, it is going to be destroyed. So the following
+            // UI operations are unnecessary and also prevents exception because its token may
+            // be gone that window manager cannot recognize it. All necessary cleanup actions
+            // performed below will be done while handling destruction.
+            return;
+        }
 
         final Activity a = r.activity;
 
@@ -4038,6 +4210,7 @@
     }
 
     /** Called from {@link LocalActivityManager}. */
+    @UnsupportedAppUsage
     final void performStopActivity(IBinder token, boolean saveState, String reason) {
         ActivityClientRecord r = mActivities.get(token);
         performStopActivityInner(r, null /* stopInfo */, false /* keepShown */, saveState,
@@ -4474,6 +4647,11 @@
     }
 
     @Override
+    public Map<IBinder, ClientTransactionItem> getActivitiesToBeDestroyed() {
+        return mActivitiesToBeDestroyed;
+    }
+
+    @Override
     public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
             boolean getNonConfigInstance, String reason) {
         ActivityClientRecord r = performDestroyActivity(token, finishing,
@@ -5147,6 +5325,16 @@
         }
     }
 
+    /**
+     * Updates the application info.
+     *
+     * This only works in the system process. Must be called on the main thread.
+     */
+    public void handleSystemApplicationInfoChanged(@NonNull ApplicationInfo ai) {
+        Preconditions.checkState(mSystemThread, "Must only be called in the system process");
+        handleApplicationInfoChanged(ai);
+    }
+
     void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
         // Updates triggered by package installation go through a package update
         // receiver. Here we try to capture ApplicationInfo changes that are
@@ -5539,6 +5727,7 @@
         LocaleList.setDefault(new LocaleList(bestLocale, newLocaleList));
     }
 
+    @UnsupportedAppUsage
     private void handleBindApplication(AppBindData data) {
         // Register the UI Thread as a sensitive thread to the runtime.
         VMRuntime.registerSensitiveThread();
@@ -5928,6 +6117,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void installContentProviders(
             Context context, List<ProviderInfo> providers) {
         final ArrayList<ContentProviderHolder> results = new ArrayList<>();
@@ -5957,6 +6147,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public final IContentProvider acquireProvider(
             Context c, String auth, int userId, boolean stable) {
         final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
@@ -6071,6 +6262,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public final IContentProvider acquireExistingProvider(
             Context c, String auth, int userId, boolean stable) {
         synchronized (mProviderMap) {
@@ -6101,6 +6293,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public final boolean releaseProvider(IContentProvider provider, boolean stable) {
         if (provider == null) {
             return false;
@@ -6233,6 +6426,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
         synchronized (mProviderMap) {
             handleUnstableProviderDiedLocked(provider, fromClient);
@@ -6334,6 +6528,7 @@
      * and returns the existing provider.  This can happen due to concurrent
      * attempts to acquire the same provider.
      */
+    @UnsupportedAppUsage
     private ContentProviderHolder installProvider(Context context,
             ContentProviderHolder holder, ProviderInfo info,
             boolean noisy, boolean noReleaseNeeded, boolean stable) {
@@ -6481,6 +6676,7 @@
         System.exit(0);
     }
 
+    @UnsupportedAppUsage
     private void attach(boolean system, long startSeq) {
         sCurrentActivityThread = this;
         mSystemThread = system;
@@ -6565,6 +6761,7 @@
         ViewRootImpl.addConfigCallback(configChangedCallback);
     }
 
+    @UnsupportedAppUsage
     public static ActivityThread systemMain() {
         // The system process on low-memory devices do not get to use hardware
         // accelerated drawing, since this can add too much overhead to the
@@ -6579,6 +6776,7 @@
         return thread;
     }
 
+    @UnsupportedAppUsage
     public final void installSystemProviders(List<ProviderInfo> providers) {
         if (providers != null) {
             installContentProviders(mInitialApplication, providers);
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index c7fa33d..c879db8 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager.StackInfo;
 import android.content.Context;
 import android.content.Intent;
@@ -74,6 +75,7 @@
     private final CloseGuard mGuard = CloseGuard.get();
     private boolean mOpened; // Protected by mGuard.
 
+    @UnsupportedAppUsage
     public ActivityView(Context context) {
         this(context, null /* attrs */);
     }
@@ -156,6 +158,7 @@
      * @see StateCallback
      * @see #startActivity(PendingIntent)
      */
+    @UnsupportedAppUsage
     public void startActivity(@NonNull Intent intent) {
         final ActivityOptions options = prepareActivityOptions();
         getContext().startActivity(intent, options.toBundle());
@@ -198,6 +201,7 @@
      * @see StateCallback
      * @see #startActivity(Intent)
      */
+    @UnsupportedAppUsage
     public void startActivity(@NonNull PendingIntent pendingIntent) {
         final ActivityOptions options = prepareActivityOptions();
         try {
@@ -231,6 +235,7 @@
      *
      * @see StateCallback
      */
+    @UnsupportedAppUsage
     public void release() {
         if (mVirtualDisplay == null) {
             throw new IllegalStateException(
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index f76f911..ec4c4db 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
@@ -129,8 +130,10 @@
             "android.app.action.NEXT_ALARM_CLOCK_CHANGED";
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final long WINDOW_EXACT = 0;
     /** @hide */
+    @UnsupportedAppUsage
     public static final long WINDOW_HEURISTIC = -1;
 
     /**
@@ -138,6 +141,7 @@
      * other alarms.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int FLAG_STANDALONE = 1<<0;
 
     /**
@@ -145,6 +149,7 @@
      * is, for example, an alarm for an alarm clock.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int FLAG_WAKE_FROM_IDLE = 1<<1;
 
     /**
@@ -165,6 +170,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED = 1<<3;
 
     /**
@@ -174,8 +180,10 @@
      * avoids scheduling any further alarms until the marker alarm is executed.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int FLAG_IDLE_UNTIL = 1<<4;
 
+    @UnsupportedAppUsage
     private final IAlarmManager mService;
     private final Context mContext;
     private final String mPackageName;
@@ -628,6 +636,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void set(@AlarmType int type, long triggerAtMillis, long windowMillis,
             long intervalMillis, String tag, OnAlarmListener listener, Handler targetHandler,
             WorkSource workSource) {
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 07b4b9c..dbc8c5d 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -21,6 +21,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.ResourceId;
@@ -69,6 +70,7 @@
  * </div>
  */
 public class AlertDialog extends Dialog implements DialogInterface {
+    @UnsupportedAppUsage
     private AlertController mAlert;
 
     /**
@@ -449,6 +451,7 @@
     }
 
     public static class Builder {
+        @UnsupportedAppUsage
         private final AlertController.AlertParams P;
 
         /**
@@ -1049,6 +1052,7 @@
          * @deprecated Set the padding on the view itself.
          */
         @Deprecated
+        @UnsupportedAppUsage
         public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop,
                 int viewSpacingRight, int viewSpacingBottom) {
             P.mView = view;
@@ -1080,6 +1084,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public Builder setRecycleOnMeasureEnabled(boolean enabled) {
             P.mRecycleOnMeasure = enabled;
             return this;
diff --git a/core/java/android/app/AppGlobals.java b/core/java/android/app/AppGlobals.java
index 2b6db8b..1f737b6 100644
--- a/core/java/android/app/AppGlobals.java
+++ b/core/java/android/app/AppGlobals.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.IPackageManager;
 
 /**
@@ -27,6 +28,7 @@
      * Return the first Application object made in the process.
      * NOTE: Only works on the main thread.
      */
+    @UnsupportedAppUsage
     public static Application getInitialApplication() {
         return ActivityThread.currentApplication();
     }
@@ -35,6 +37,7 @@
      * Return the package name of the first .apk loaded into the process.
      * NOTE: Only works on the main thread.
      */
+    @UnsupportedAppUsage
     public static String getInitialPackage() {
         return ActivityThread.currentPackageName();
     }
@@ -43,6 +46,7 @@
      * Return the raw interface to the package manager.
      * @return The package manager.
      */
+    @UnsupportedAppUsage
     public static IPackageManager getPackageManager() {
         return ActivityThread.getPackageManager();
     }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8b33963..fd92174 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -22,6 +22,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.media.AudioAttributes.AttributeUsage;
@@ -75,6 +76,7 @@
      */
 
     final Context mContext;
+    @UnsupportedAppUsage
     final IAppOpsService mService;
     final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers = new ArrayMap<>();
     final ArrayMap<OnOpActiveChangedListener, IAppOpsActiveCallback> mActiveWatchers =
@@ -191,168 +193,246 @@
     //  - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
 
     /** @hide No operation specified. */
+    @UnsupportedAppUsage
     public static final int OP_NONE = -1;
     /** @hide Access to coarse location information. */
+    @UnsupportedAppUsage
     public static final int OP_COARSE_LOCATION = 0;
     /** @hide Access to fine location information. */
+    @UnsupportedAppUsage
     public static final int OP_FINE_LOCATION = 1;
     /** @hide Causing GPS to run. */
+    @UnsupportedAppUsage
     public static final int OP_GPS = 2;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_VIBRATE = 3;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_READ_CONTACTS = 4;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_WRITE_CONTACTS = 5;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_READ_CALL_LOG = 6;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_WRITE_CALL_LOG = 7;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_READ_CALENDAR = 8;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_WRITE_CALENDAR = 9;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_WIFI_SCAN = 10;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_POST_NOTIFICATION = 11;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_NEIGHBORING_CELLS = 12;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_CALL_PHONE = 13;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_READ_SMS = 14;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_WRITE_SMS = 15;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_RECEIVE_SMS = 16;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_RECEIVE_EMERGECY_SMS = 17;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_RECEIVE_MMS = 18;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_RECEIVE_WAP_PUSH = 19;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_SEND_SMS = 20;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_READ_ICC_SMS = 21;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_WRITE_ICC_SMS = 22;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_WRITE_SETTINGS = 23;
     /** @hide Required to draw on top of other apps. */
     @TestApi
     public static final int OP_SYSTEM_ALERT_WINDOW = 24;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_ACCESS_NOTIFICATIONS = 25;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_CAMERA = 26;
     /** @hide */
     @TestApi
     public static final int OP_RECORD_AUDIO = 27;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_PLAY_AUDIO = 28;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_READ_CLIPBOARD = 29;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_WRITE_CLIPBOARD = 30;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_TAKE_MEDIA_BUTTONS = 31;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_TAKE_AUDIO_FOCUS = 32;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_AUDIO_MASTER_VOLUME = 33;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_AUDIO_VOICE_VOLUME = 34;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_AUDIO_RING_VOLUME = 35;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_AUDIO_MEDIA_VOLUME = 36;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_AUDIO_ALARM_VOLUME = 37;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_WAKE_LOCK = 40;
     /** @hide Continually monitoring location data. */
+    @UnsupportedAppUsage
     public static final int OP_MONITOR_LOCATION = 41;
     /** @hide Continually monitoring location data with a relatively high power request. */
+    @UnsupportedAppUsage
     public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
     /** @hide Retrieve current usage stats via {@link UsageStatsManager}. */
+    @UnsupportedAppUsage
     public static final int OP_GET_USAGE_STATS = 43;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_MUTE_MICROPHONE = 44;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_TOAST_WINDOW = 45;
     /** @hide Capture the device's display contents and/or audio */
+    @UnsupportedAppUsage
     public static final int OP_PROJECT_MEDIA = 46;
     /** @hide Activate a VPN connection without user intervention. */
+    @UnsupportedAppUsage
     public static final int OP_ACTIVATE_VPN = 47;
     /** @hide Access the WallpaperManagerAPI to write wallpapers. */
+    @UnsupportedAppUsage
     public static final int OP_WRITE_WALLPAPER = 48;
     /** @hide Received the assist structure from an app. */
+    @UnsupportedAppUsage
     public static final int OP_ASSIST_STRUCTURE = 49;
     /** @hide Received a screenshot from assist. */
+    @UnsupportedAppUsage
     public static final int OP_ASSIST_SCREENSHOT = 50;
     /** @hide Read the phone state. */
+    @UnsupportedAppUsage
     public static final int OP_READ_PHONE_STATE = 51;
     /** @hide Add voicemail messages to the voicemail content provider. */
+    @UnsupportedAppUsage
     public static final int OP_ADD_VOICEMAIL = 52;
     /** @hide Access APIs for SIP calling over VOIP or WiFi. */
+    @UnsupportedAppUsage
     public static final int OP_USE_SIP = 53;
     /** @hide Intercept outgoing calls. */
+    @UnsupportedAppUsage
     public static final int OP_PROCESS_OUTGOING_CALLS = 54;
     /** @hide User the fingerprint API. */
+    @UnsupportedAppUsage
     public static final int OP_USE_FINGERPRINT = 55;
     /** @hide Access to body sensors such as heart rate, etc. */
+    @UnsupportedAppUsage
     public static final int OP_BODY_SENSORS = 56;
     /** @hide Read previously received cell broadcast messages. */
+    @UnsupportedAppUsage
     public static final int OP_READ_CELL_BROADCASTS = 57;
     /** @hide Inject mock location into the system. */
+    @UnsupportedAppUsage
     public static final int OP_MOCK_LOCATION = 58;
     /** @hide Read external storage. */
+    @UnsupportedAppUsage
     public static final int OP_READ_EXTERNAL_STORAGE = 59;
     /** @hide Write external storage. */
+    @UnsupportedAppUsage
     public static final int OP_WRITE_EXTERNAL_STORAGE = 60;
     /** @hide Turned on the screen. */
+    @UnsupportedAppUsage
     public static final int OP_TURN_SCREEN_ON = 61;
     /** @hide Get device accounts. */
+    @UnsupportedAppUsage
     public static final int OP_GET_ACCOUNTS = 62;
     /** @hide Control whether an application is allowed to run in the background. */
+    @UnsupportedAppUsage
     public static final int OP_RUN_IN_BACKGROUND = 63;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_AUDIO_ACCESSIBILITY_VOLUME = 64;
     /** @hide Read the phone number. */
+    @UnsupportedAppUsage
     public static final int OP_READ_PHONE_NUMBERS = 65;
     /** @hide Request package installs through package installer */
+    @UnsupportedAppUsage
     public static final int OP_REQUEST_INSTALL_PACKAGES = 66;
     /** @hide Enter picture-in-picture. */
+    @UnsupportedAppUsage
     public static final int OP_PICTURE_IN_PICTURE = 67;
     /** @hide Instant app start foreground service. */
+    @UnsupportedAppUsage
     public static final int OP_INSTANT_APP_START_FOREGROUND = 68;
     /** @hide Answer incoming phone calls */
+    @UnsupportedAppUsage
     public static final int OP_ANSWER_PHONE_CALLS = 69;
     /** @hide Run jobs when in background */
+    @UnsupportedAppUsage
     public static final int OP_RUN_ANY_IN_BACKGROUND = 70;
     /** @hide Change Wi-Fi connectivity state */
+    @UnsupportedAppUsage
     public static final int OP_CHANGE_WIFI_STATE = 71;
     /** @hide Request package deletion through package installer */
+    @UnsupportedAppUsage
     public static final int OP_REQUEST_DELETE_PACKAGES = 72;
     /** @hide Bind an accessibility service. */
+    @UnsupportedAppUsage
     public static final int OP_BIND_ACCESSIBILITY_SERVICE = 73;
     /** @hide Continue handover of a call from another app */
+    @UnsupportedAppUsage
     public static final int OP_ACCEPT_HANDOVER = 74;
     /** @hide Create and Manage IPsec Tunnels */
+    @UnsupportedAppUsage
     public static final int OP_MANAGE_IPSEC_TUNNELS = 75;
     /** @hide Any app start foreground service. */
+    @UnsupportedAppUsage
     public static final int OP_START_FOREGROUND = 76;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int OP_BLUETOOTH_SCAN = 77;
     /** @hide Use the face authentication API. */
     public static final int OP_USE_FACE = 78;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int _NUM_OP = 79;
 
     /** Access to coarse location information. */
@@ -916,6 +996,7 @@
      * This optionally maps a permission to an operation.  If there
      * is no permission associated with an operation, it is null.
      */
+    @UnsupportedAppUsage
     private static String[] sOpPerms = new String[] {
             android.Manifest.permission.ACCESS_COARSE_LOCATION,
             android.Manifest.permission.ACCESS_FINE_LOCATION,
@@ -1404,6 +1485,7 @@
      * Retrieve the op switch that controls the given operation.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int opToSwitch(int op) {
         return sOpToSwitch[op];
     }
@@ -1412,6 +1494,7 @@
      * Retrieve a non-localized name for the operation, for debugging output.
      * @hide
      */
+    @UnsupportedAppUsage
     public static String opToName(int op) {
         if (op == OP_NONE) return "NONE";
         return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
@@ -1507,6 +1590,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public PackageOps(String packageName, int uid, List<OpEntry> entries) {
             mPackageName = packageName;
             mUid = uid;
@@ -1621,6 +1705,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public int getOp() {
             return mOp;
         }
@@ -1642,6 +1727,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public long getTime() {
             return maxTime(mTimes, 0, _NUM_UID_STATE);
         }
@@ -1814,6 +1900,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
+    @UnsupportedAppUsage
     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
         try {
             return mService.getPackagesForOps(ops);
@@ -1944,6 +2031,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
+    @UnsupportedAppUsage
     public void setRestriction(int code, @AttributeUsage int usage, int mode,
             String[] exceptionPackages) {
         try {
@@ -1956,6 +2044,7 @@
 
     /** @hide */
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
+    @UnsupportedAppUsage
     public void resetAllModes() {
         try {
             mService.resetAllModes(mContext.getUserId(), null);
@@ -2356,6 +2445,7 @@
      * @throws SecurityException If the app has been configured to crash on this op.
      * @hide
      */
+    @UnsupportedAppUsage
     public int checkOp(int op, int uid, String packageName) {
         try {
             int mode = mService.checkOperation(op, uid, packageName);
@@ -2373,6 +2463,7 @@
      * returns {@link #MODE_ERRORED}.
      * @hide
      */
+    @UnsupportedAppUsage
     public int checkOpNoThrow(int op, int uid, String packageName) {
         try {
             int mode = mService.checkOperation(op, uid, packageName);
@@ -2443,6 +2534,7 @@
      * @throws SecurityException If the app has been configured to crash on this op.
      * @hide
      */
+    @UnsupportedAppUsage
     public int noteOp(int op, int uid, String packageName) {
         final int mode = noteOpNoThrow(op, uid, packageName);
         if (mode == MODE_ERRORED) {
@@ -2469,6 +2561,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int noteProxyOp(int op, String proxiedPackageName) {
         int mode = noteProxyOpNoThrow(op, proxiedPackageName);
         if (mode == MODE_ERRORED) {
@@ -2487,7 +2580,7 @@
      */
     public int noteProxyOpNoThrow(int op, String proxiedPackageName) {
         try {
-            return mService.noteProxyOperation(op, mContext.getOpPackageName(),
+            return mService.noteProxyOperation(op, Process.myUid(), mContext.getOpPackageName(),
                     Binder.getCallingUid(), proxiedPackageName);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -2499,6 +2592,7 @@
      * returns {@link #MODE_ERRORED}.
      * @hide
      */
+    @UnsupportedAppUsage
     public int noteOpNoThrow(int op, int uid, String packageName) {
         try {
             return mService.noteOperation(op, uid, packageName);
@@ -2508,11 +2602,13 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int noteOp(int op) {
         return noteOp(op, Process.myUid(), mContext.getOpPackageName());
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static IBinder getToken(IAppOpsService service) {
         synchronized (AppOpsManager.class) {
             if (sToken != null) {
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 24c5d23..f5d5e6e 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -18,12 +18,55 @@
 
 import android.util.SparseIntArray;
 
+import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.TriFunction;
+
 /**
  * App ops service local interface.
  *
  * @hide Only for use within the system server.
  */
 public abstract class AppOpsManagerInternal {
+    /** Interface to override app ops checks via composition */
+    public interface CheckOpsDelegate {
+        /**
+         * Allows overriding check operation behavior.
+         *
+         * @param code The op code to check.
+         * @param uid The UID for which to check.
+         * @param packageName The package for which to check.
+         * @param superImpl The super implementation.
+         * @return The app op check result.
+         */
+        int checkOperation(int code, int uid, String packageName,
+                TriFunction<Integer, Integer, String, Integer> superImpl);
+
+        /**
+         * Allows overriding check audio operation behavior.
+         *
+         * @param code The op code to check.
+         * @param usage The audio op usage.
+         * @param uid The UID for which to check.
+         * @param packageName The package for which to check.
+         * @param superImpl The super implementation.
+         * @return The app op check result.
+         */
+        int checkAudioOperation(int code, int usage, int uid, String packageName,
+                QuadFunction<Integer, Integer, Integer, String, Integer> superImpl);
+
+        /**
+         * Allows overriding note operation behavior.
+         *
+         * @param code The op code to note.
+         * @param uid The UID for which to note.
+         * @param packageName The package for which to note.
+         * @param superImpl The super implementation.
+         * @return The app op note result.
+         */
+        int noteOperation(int code, int uid, String packageName,
+                TriFunction<Integer, Integer, String, Integer> superImpl);
+    }
+
     /**
      * Set the currently configured device and profile owners.  Specifies the package uid (value)
      * that has been configured for each user (key) that has one.  These will be allowed privileged
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 4531f53..636366d 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -17,6 +17,9 @@
 package android.app;
 
 import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentCallbacks;
 import android.content.ComponentCallbacks2;
 import android.content.Context;
@@ -48,23 +51,27 @@
  */
 public class Application extends ContextWrapper implements ComponentCallbacks2 {
     private static final String TAG = "Application";
+    @UnsupportedAppUsage
     private ArrayList<ComponentCallbacks> mComponentCallbacks =
             new ArrayList<ComponentCallbacks>();
+    @UnsupportedAppUsage
     private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
             new ArrayList<ActivityLifecycleCallbacks>();
+    @UnsupportedAppUsage
     private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null;
 
     /** @hide */
+    @UnsupportedAppUsage
     public LoadedApk mLoadedApk;
 
     public interface ActivityLifecycleCallbacks {
-        void onActivityCreated(Activity activity, Bundle savedInstanceState);
-        void onActivityStarted(Activity activity);
-        void onActivityResumed(Activity activity);
-        void onActivityPaused(Activity activity);
-        void onActivityStopped(Activity activity);
-        void onActivitySaveInstanceState(Activity activity, Bundle outState);
-        void onActivityDestroyed(Activity activity);
+        void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState);
+        void onActivityStarted(@NonNull Activity activity);
+        void onActivityResumed(@NonNull Activity activity);
+        void onActivityPaused(@NonNull Activity activity);
+        void onActivityStopped(@NonNull Activity activity);
+        void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState);
+        void onActivityDestroyed(@NonNull Activity activity);
     }
 
     /**
@@ -208,12 +215,15 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     /* package */ final void attach(Context context) {
         attachBaseContext(context);
         mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
     }
 
-    /* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
+    @UnsupportedAppUsage
+    /* package */ void dispatchActivityCreated(@NonNull Activity activity,
+            @Nullable Bundle savedInstanceState) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
             for (int i=0; i<callbacks.length; i++) {
@@ -223,7 +233,8 @@
         }
     }
 
-    /* package */ void dispatchActivityStarted(Activity activity) {
+    @UnsupportedAppUsage
+    /* package */ void dispatchActivityStarted(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
             for (int i=0; i<callbacks.length; i++) {
@@ -232,7 +243,8 @@
         }
     }
 
-    /* package */ void dispatchActivityResumed(Activity activity) {
+    @UnsupportedAppUsage
+    /* package */ void dispatchActivityResumed(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
             for (int i=0; i<callbacks.length; i++) {
@@ -241,7 +253,8 @@
         }
     }
 
-    /* package */ void dispatchActivityPaused(Activity activity) {
+    @UnsupportedAppUsage
+    /* package */ void dispatchActivityPaused(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
             for (int i=0; i<callbacks.length; i++) {
@@ -250,7 +263,8 @@
         }
     }
 
-    /* package */ void dispatchActivityStopped(Activity activity) {
+    @UnsupportedAppUsage
+    /* package */ void dispatchActivityStopped(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
             for (int i=0; i<callbacks.length; i++) {
@@ -259,7 +273,9 @@
         }
     }
 
-    /* package */ void dispatchActivitySaveInstanceState(Activity activity, Bundle outState) {
+    @UnsupportedAppUsage
+    /* package */ void dispatchActivitySaveInstanceState(@NonNull Activity activity,
+            @NonNull Bundle outState) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
             for (int i=0; i<callbacks.length; i++) {
@@ -269,7 +285,8 @@
         }
     }
 
-    /* package */ void dispatchActivityDestroyed(Activity activity) {
+    @UnsupportedAppUsage
+    /* package */ void dispatchActivityDestroyed(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
             for (int i=0; i<callbacks.length; i++) {
@@ -288,6 +305,7 @@
         return callbacks;
     }
 
+    @UnsupportedAppUsage
     private Object[] collectActivityLifecycleCallbacks() {
         Object[] callbacks = null;
         synchronized (mActivityLifecycleCallbacks) {
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index e645261..8874554 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -29,6 +29,7 @@
 import android.provider.Settings;
 import android.util.Printer;
 import android.util.Slog;
+
 import com.android.internal.util.FastPrintWriter;
 
 import java.io.PrintWriter;
@@ -333,6 +334,12 @@
         public String stackTrace;
 
         /**
+         * Crash tag for some context.
+         * @hide
+         */
+        public String crashTag;
+
+        /**
          * Create an uninitialized instance of CrashInfo.
          */
         public CrashInfo() {
@@ -416,6 +423,7 @@
             throwMethodName = in.readString();
             throwLineNumber = in.readInt();
             stackTrace = in.readString();
+            crashTag = in.readString();
         }
 
         /**
@@ -430,6 +438,7 @@
             dest.writeString(throwMethodName);
             dest.writeInt(throwLineNumber);
             dest.writeString(stackTrace);
+            dest.writeString(crashTag);
             int total = dest.dataPosition()-start;
             if (Binder.CHECK_PARCEL_SIZE && total > 20*1024) {
                 Slog.d("Error", "ERR: exClass=" + exceptionClassName);
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 0ed50f2..30d6bee 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.GraphicsEnvironment;
 import android.os.Trace;
@@ -29,6 +30,7 @@
 
 /** @hide */
 public class ApplicationLoaders {
+    @UnsupportedAppUsage
     public static ApplicationLoaders getDefault() {
         return gApplicationLoaders;
     }
@@ -134,6 +136,7 @@
         baseDexClassLoader.addNativePath(libPaths);
     }
 
+    @UnsupportedAppUsage
     private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<>();
 
     private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 344610a..264029b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.annotation.XmlRes;
 import android.content.ComponentName;
@@ -342,9 +343,15 @@
     }
 
     @Override
-    public boolean isPermissionReviewModeEnabled() {
+    public boolean arePermissionsIndividuallyControlled() {
         return mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_permissionReviewRequired);
+                com.android.internal.R.bool.config_permissionsIndividuallyControlled);
+    }
+
+    @Override
+    public boolean isWirelessConsentModeEnabled() {
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_wirelessConsentRequired);
     }
 
     @Override
@@ -693,6 +700,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public boolean shouldShowRequestPermissionRationale(String permission) {
         try {
             return mPM.shouldShowRequestPermissionRationale(permission,
@@ -1525,6 +1533,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     static void configurationChanged() {
         synchronized (sSync) {
             sIconCache.clear();
@@ -1532,6 +1541,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     protected ApplicationPackageManager(ContextImpl context,
                               IPackageManager pm) {
         mContext = context;
@@ -2023,6 +2033,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app) {
         final StorageManager storage = mContext.getSystemService(StorageManager.class);
         return getPackageCurrentVolume(app, storage);
@@ -2176,6 +2187,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
         deletePackageAsUser(packageName, observer, flags, getUserId());
     }
@@ -2300,6 +2312,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void getPackageSizeInfoAsUser(String packageName, int userHandle,
             IPackageStatsObserver observer) {
         final String msg = "Shame on you for calling the hidden API "
@@ -2743,6 +2756,7 @@
     }
 
     private final ContextImpl mContext;
+    @UnsupportedAppUsage
     private final IPackageManager mPM;
 
     /** Assume locked until we hear otherwise */
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index d9c7cf3..b5295d1 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -16,6 +16,7 @@
 package android.app;
 
 import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.ClientTransactionItem;
 import android.app.servertransaction.PendingTransactionActions;
 import android.app.servertransaction.TransactionExecutor;
 import android.content.Intent;
@@ -29,6 +30,7 @@
 import com.android.internal.content.ReferrerIntent;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * Defines operations that a {@link android.app.servertransaction.ClientTransaction} or its items
@@ -64,6 +66,8 @@
 
     abstract void sendMessage(int what, Object obj);
 
+    /** Get activity instance for the token. */
+    public abstract Activity getActivity(IBinder token);
 
     // Prepare phase related logic and handlers. Methods that inform about about pending changes or
     // do other internal bookkeeping.
@@ -78,6 +82,9 @@
     // Execute phase related logic and handlers. Methods here execute actual lifecycle transactions
     // and deliver callbacks.
 
+    /** Get activity and its corresponding transaction item which are going to destroy. */
+    public abstract Map<IBinder, ClientTransactionItem> getActivitiesToBeDestroyed();
+
     /** Destroy the activity. */
     public abstract void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
             boolean getNonConfigInstance, String reason);
diff --git a/core/java/android/app/ContentProviderHolder.java b/core/java/android/app/ContentProviderHolder.java
index f9998f4..1098990 100644
--- a/core/java/android/app/ContentProviderHolder.java
+++ b/core/java/android/app/ContentProviderHolder.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProviderNative;
 import android.content.IContentProvider;
 import android.content.pm.ProviderInfo;
@@ -29,11 +30,15 @@
  * @hide
  */
 public class ContentProviderHolder implements Parcelable {
+    @UnsupportedAppUsage
     public final ProviderInfo info;
+    @UnsupportedAppUsage
     public IContentProvider provider;
     public IBinder connection;
+    @UnsupportedAppUsage
     public boolean noReleaseNeeded;
 
+    @UnsupportedAppUsage
     public ContentProviderHolder(ProviderInfo _info) {
         info = _info;
     }
@@ -68,6 +73,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     private ContentProviderHolder(Parcel source) {
         info = ProviderInfo.CREATOR.createFromParcel(source);
         provider = ContentProviderNative.asInterface(
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 82088dc..bbaaee8 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentProvider;
@@ -80,6 +81,8 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 
+import dalvik.system.BlockGuard;
+
 import libcore.io.Memory;
 
 import java.io.File;
@@ -154,36 +157,50 @@
      * Map from package name, to preference name, to cached preferences.
      */
     @GuardedBy("ContextImpl.class")
+    @UnsupportedAppUsage
     private static ArrayMap<String, ArrayMap<File, SharedPreferencesImpl>> sSharedPrefsCache;
 
     /**
      * Map from preference name to generated path.
      */
     @GuardedBy("ContextImpl.class")
+    @UnsupportedAppUsage
     private ArrayMap<String, File> mSharedPrefsPaths;
 
+    @UnsupportedAppUsage
     final @NonNull ActivityThread mMainThread;
+    @UnsupportedAppUsage
     final @NonNull LoadedApk mPackageInfo;
+    @UnsupportedAppUsage
     private @Nullable ClassLoader mClassLoader;
 
     private final @Nullable IBinder mActivityToken;
 
     private final @NonNull UserHandle mUser;
 
+    @UnsupportedAppUsage
     private final ApplicationContentResolver mContentResolver;
 
+    @UnsupportedAppUsage
     private final String mBasePackageName;
+    @UnsupportedAppUsage
     private final String mOpPackageName;
 
     private final @NonNull ResourcesManager mResourcesManager;
+    @UnsupportedAppUsage
     private @NonNull Resources mResources;
     private @Nullable Display mDisplay; // may be null if default display
 
+    @UnsupportedAppUsage
     private final int mFlags;
 
+    @UnsupportedAppUsage
     private Context mOuterContext;
+    @UnsupportedAppUsage
     private int mThemeResource = 0;
+    @UnsupportedAppUsage
     private Resources.Theme mTheme = null;
+    @UnsupportedAppUsage
     private PackageManager mPackageManager;
     private Context mReceiverRestrictedContext = null;
 
@@ -198,6 +215,7 @@
     @GuardedBy("mSync")
     private File mDatabasesDir;
     @GuardedBy("mSync")
+    @UnsupportedAppUsage
     private File mPreferencesDir;
     @GuardedBy("mSync")
     private File mFilesDir;
@@ -209,6 +227,7 @@
     private File mCodeCacheDir;
 
     // The system service cache for the system services that are cached per-ContextImpl.
+    @UnsupportedAppUsage
     final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
 
     static final int STATE_UNINITIALIZED = 0;
@@ -233,6 +252,7 @@
     @ServiceInitializationState
     final int[] mServiceInitializationStateArray = new int[mServiceCache.length];
 
+    @UnsupportedAppUsage
     static ContextImpl getImpl(Context context) {
         Context nextContext;
         while ((context instanceof ContextWrapper) &&
@@ -544,6 +564,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private File getPreferencesDir() {
         synchronized (mSync) {
             if (mPreferencesDir == null) {
@@ -2218,6 +2239,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public Display getDisplay() {
         if (mDisplay == null) {
             return mResourcesManager.getAdjustedDisplay(Display.DEFAULT_DISPLAY,
@@ -2315,6 +2337,7 @@
         mIsAutofillCompatEnabled = autofillCompatEnabled;
     }
 
+    @UnsupportedAppUsage
     static ContextImpl createSystemContext(ActivityThread mainThread) {
         LoadedApk packageInfo = new LoadedApk(mainThread);
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
@@ -2338,6 +2361,7 @@
         return context;
     }
 
+    @UnsupportedAppUsage
     static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
@@ -2346,6 +2370,7 @@
         return context;
     }
 
+    @UnsupportedAppUsage
     static ContextImpl createActivityContext(ActivityThread mainThread,
             LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
             Configuration overrideConfiguration) {
@@ -2460,6 +2485,7 @@
         mPackageInfo.installSystemApplicationInfo(info, classLoader);
     }
 
+    @UnsupportedAppUsage
     final void scheduleFinalCleanup(String who, String what) {
         mMainThread.scheduleContextCleanup(this, who, what);
     }
@@ -2469,6 +2495,7 @@
         mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
     }
 
+    @UnsupportedAppUsage
     final Context getReceiverRestrictedContext() {
         if (mReceiverRestrictedContext != null) {
             return mReceiverRestrictedContext;
@@ -2476,15 +2503,18 @@
         return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
     }
 
+    @UnsupportedAppUsage
     final void setOuterContext(Context context) {
         mOuterContext = context;
     }
 
+    @UnsupportedAppUsage
     final Context getOuterContext() {
         return mOuterContext;
     }
 
     @Override
+    @UnsupportedAppUsage
     public IBinder getActivityToken() {
         return mActivityToken;
     }
@@ -2521,7 +2551,11 @@
 
     private File makeFilename(File base, String name) {
         if (name.indexOf(File.separatorChar) < 0) {
-            return new File(base, name);
+            final File res = new File(base, name);
+            // We report as filesystem access here to give us the best shot at
+            // detecting apps that will pass the path down to native code.
+            BlockGuard.getVmPolicy().onPathAccess(res.getPath());
+            return res;
         }
         throw new IllegalArgumentException(
                 "File " + name + " contains a path separator");
@@ -2561,6 +2595,7 @@
     // ----------------------------------------------------------------------
 
     private static final class ApplicationContentResolver extends ContentResolver {
+        @UnsupportedAppUsage
         private final ActivityThread mMainThread;
 
         public ApplicationContentResolver(Context context, ActivityThread mainThread) {
@@ -2569,6 +2604,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         protected IContentProvider acquireProvider(Context context, String auth) {
             return mMainThread.acquireProvider(context,
                     ContentProvider.getAuthorityWithoutUserId(auth),
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index bd55a06..37a05f0 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
@@ -47,6 +48,7 @@
     private static final String MONTH = "month";
     private static final String DAY = "day";
 
+    @UnsupportedAppUsage
     private final DatePicker mDatePicker;
 
     private OnDateSetListener mDateSetListener;
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 6557ac4..b7bac52 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -24,6 +24,7 @@
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -93,11 +94,14 @@
 public class Dialog implements DialogInterface, Window.Callback,
         KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback {
     private static final String TAG = "Dialog";
+    @UnsupportedAppUsage
     private Activity mOwnerActivity;
 
     private final WindowManager mWindowManager;
 
+    @UnsupportedAppUsage
     final Context mContext;
+    @UnsupportedAppUsage
     final Window mWindow;
 
     View mDecor;
@@ -110,22 +114,30 @@
     protected boolean mCancelable = true;
 
     private String mCancelAndDismissTaken;
+    @UnsupportedAppUsage
     private Message mCancelMessage;
+    @UnsupportedAppUsage
     private Message mDismissMessage;
+    @UnsupportedAppUsage
     private Message mShowMessage;
 
+    @UnsupportedAppUsage
     private OnKeyListener mOnKeyListener;
 
     private boolean mCreated = false;
+    @UnsupportedAppUsage
     private boolean mShowing = false;
     private boolean mCanceled = false;
 
+    @UnsupportedAppUsage
     private final Handler mHandler = new Handler();
 
     private static final int DISMISS = 0x43;
+    @UnsupportedAppUsage
     private static final int CANCEL = 0x44;
     private static final int SHOW = 0x45;
 
+    @UnsupportedAppUsage
     private final Handler mListenersHandler;
 
     private SearchEvent mSearchEvent;
@@ -361,6 +373,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void dismissDialog() {
         if (mDecor == null || !mShowing) {
             return;
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index 3a355d9..bfc15c2 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
@@ -182,11 +183,15 @@
     int mTheme = 0;
     boolean mCancelable = true;
     boolean mShowsDialog = true;
+    @UnsupportedAppUsage
     int mBackStackId = -1;
 
     Dialog mDialog;
+    @UnsupportedAppUsage
     boolean mViewDestroyed;
+    @UnsupportedAppUsage
     boolean mDismissed;
+    @UnsupportedAppUsage
     boolean mShownByMe;
 
     public DialogFragment() {
@@ -236,6 +241,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public void showAllowingStateLoss(FragmentManager manager, String tag) {
         mDismissed = false;
         mShownByMe = true;
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index b444f17..35999a2 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -329,6 +330,7 @@
      * columns to request from DownloadProvider.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String[] UNDERLYING_COLUMNS = new String[] {
         Downloads.Impl._ID,
         Downloads.Impl._DATA + " AS " + COLUMN_LOCAL_FILENAME,
@@ -381,6 +383,7 @@
         @Deprecated
         public static final int NETWORK_BLUETOOTH = 1 << 2;
 
+        @UnsupportedAppUsage
         private Uri mUri;
         private Uri mDestinationUri;
         private List<Pair<String, String>> mRequestHeaders = new ArrayList<Pair<String, String>>();
@@ -860,6 +863,7 @@
          * @return this object
          * @hide
          */
+        @UnsupportedAppUsage
         public Query setOnlyIncludeVisibleInDownloadsUi(boolean value) {
             mOnlyIncludeVisibleInDownloadsUi = value;
             return this;
@@ -875,6 +879,7 @@
          * @return this object
          * @hide
          */
+        @UnsupportedAppUsage
         public Query orderBy(String column, int direction) {
             if (direction != ORDER_ASCENDING && direction != ORDER_DESCENDING) {
                 throw new IllegalArgumentException("Invalid direction: " + direction);
@@ -996,6 +1001,7 @@
      * /my_downloads URIs, for clients that have permission to do so.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setAccessAllDownloads(boolean accessAllDownloads) {
         if (accessAllDownloads) {
             mBaseUri = Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI;
@@ -1005,6 +1011,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public void setAccessFilename(boolean accessFilename) {
         mAccessFilename = accessFilename;
     }
@@ -1439,6 +1446,7 @@
     /**
      * Get a parameterized SQL WHERE clause to select a bunch of IDs.
      */
+    @UnsupportedAppUsage
     static String getWhereClauseForIds(long[] ids) {
         StringBuilder whereClause = new StringBuilder();
         whereClause.append("(");
@@ -1456,6 +1464,7 @@
     /**
      * Get the selection args for a clause returned by {@link #getWhereClauseForIds(long[])}.
      */
+    @UnsupportedAppUsage
     static String[] getWhereArgsForIds(long[] ids) {
         String[] whereArgs = new String[ids.length];
         return getWhereArgsForIds(ids, whereArgs);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 8e8270a..9f4157f 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.Intent;
@@ -263,6 +264,7 @@
  */
 @Deprecated
 public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener {
+    @UnsupportedAppUsage
     private static final ArrayMap<String, Class<?>> sClassMap =
             new ArrayMap<String, Class<?>>();
 
@@ -279,13 +281,16 @@
     int mState = INITIALIZING;
 
     // When instantiated from saved state, this is the saved state.
+    @UnsupportedAppUsage
     Bundle mSavedFragmentState;
     SparseArray<Parcelable> mSavedViewState;
 
     // Index into active fragment array.
+    @UnsupportedAppUsage
     int mIndex = -1;
 
     // Internal unique name for this fragment;
+    @UnsupportedAppUsage
     String mWho;
 
     // Construction arguments;
@@ -301,6 +306,7 @@
     int mTargetRequestCode;
 
     // True if the fragment is in the list of added fragments.
+    @UnsupportedAppUsage
     boolean mAdded;
 
     // If set this fragment is being removed from its activity.
@@ -325,12 +331,15 @@
     // The fragment manager we are associated with.  Set as soon as the
     // fragment is used in a transaction; cleared after it has been removed
     // from all transactions.
+    @UnsupportedAppUsage
     FragmentManagerImpl mFragmentManager;
 
     // Activity this fragment is attached to.
+    @UnsupportedAppUsage
     FragmentHostCallback mHost;
 
     // Private fragment manager for child fragments inside of this one.
+    @UnsupportedAppUsage
     FragmentManagerImpl mChildFragmentManager;
 
     // For use when restoring fragment state and descendant fragments are retained.
@@ -343,6 +352,7 @@
     // The optional identifier for this fragment -- either the container ID if it
     // was dynamically added to the view hierarchy, or the ID supplied in
     // layout.
+    @UnsupportedAppUsage
     int mFragmentId;
 
     // When a fragment is being dynamically added to the view hierarchy, this
@@ -380,6 +390,7 @@
     ViewGroup mContainer;
 
     // The View generated for this fragment.
+    @UnsupportedAppUsage
     View mView;
 
     // Whether this fragment should defer starting until after other fragments
@@ -390,6 +401,7 @@
     boolean mUserVisibleHint = true;
 
     LoaderManagerImpl mLoaderManager;
+    @UnsupportedAppUsage
     boolean mLoadersStarted;
     boolean mCheckedForLoaderManager;
 
diff --git a/core/java/android/app/FragmentController.java b/core/java/android/app/FragmentController.java
index 40bc248..9316be7 100644
--- a/core/java/android/app/FragmentController.java
+++ b/core/java/android/app/FragmentController.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.Bundle;
@@ -43,6 +44,7 @@
  */
 @Deprecated
 public class FragmentController {
+    @UnsupportedAppUsage
     private final FragmentHostCallback<?> mHost;
 
     /**
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
index b48817b..1a12fdc 100644
--- a/core/java/android/app/FragmentHostCallback.java
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -56,6 +57,7 @@
     private LoaderManagerImpl mLoaderManager;
     private boolean mCheckedForLoaderManager;
     /** Whether or not the fragment host loader manager was started */
+    @UnsupportedAppUsage
     private boolean mLoadersStarted;
 
     public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 708450f..5e7921b 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -22,6 +22,7 @@
 import android.animation.AnimatorSet;
 import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
@@ -688,7 +689,9 @@
     boolean mExecutingActions;
 
     int mNextFragmentIndex = 0;
+    @UnsupportedAppUsage
     SparseArray<Fragment> mActive;
+    @UnsupportedAppUsage
     final ArrayList<Fragment> mAdded = new ArrayList<>();
     ArrayList<BackStackRecord> mBackStack;
     ArrayList<Fragment> mCreatedMenus;
@@ -708,6 +711,7 @@
     Fragment mPrimaryNav;
     
     boolean mNeedMenuInvalidate;
+    @UnsupportedAppUsage
     boolean mStateSaved;
     boolean mDestroyed;
     String mNoTransactionsBecause;
@@ -1097,6 +1101,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     Animator loadAnimator(Fragment fragment, int transit, boolean enter,
             int transitionStyle) {
         Animator animObj = fragment.onCreateAnimator(transit, enter, fragment.getNextAnim());
@@ -2976,6 +2981,7 @@
         return 0;
     }
 
+    @UnsupportedAppUsage
     public void noteStateNotSaved() {
         mSavedNonConfig = null;
         mStateSaved = false;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 49d3fffc..16360b3 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -243,12 +243,6 @@
     boolean isTopActivityImmersive();
     void crashApplication(int uid, int initialPid, in String packageName, int userId, in String message);
     String getProviderMimeType(in Uri uri, int userId);
-    IBinder newUriPermissionOwner(in String name);
-    void grantUriPermissionFromOwner(in IBinder owner, int fromUid, in String targetPkg,
-            in Uri uri, int mode, int sourceUserId, int targetUserId);
-    void revokeUriPermissionFromOwner(in IBinder owner, in Uri uri, int mode, int userId);
-    int checkGrantUriPermission(int callingUid, in String targetPkg, in Uri uri,
-            int modeFlags, int userId);
     // Cause the specified process to dump the specified heap.
     boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
             boolean runGc, in String path, in ParcelFileDescriptor fd,
@@ -268,7 +262,7 @@
     void showBootMessage(in CharSequence msg, boolean always);
     void killAllBackgroundProcesses();
     ContentProviderHolder getContentProviderExternal(in String name, int userId,
-            in IBinder token);
+            in IBinder token, String tag);
     void removeContentProviderExternal(in String name, in IBinder token);
     // Get memory information about the calling process.
     void getMyMemoryState(out ActivityManager.RunningAppProcessInfo outInfo);
@@ -331,7 +325,6 @@
      */
     void requestWifiBugReport(in String shareTitle, in String shareDescription);
 
-    long inputDispatchingTimedOut(int pid, boolean aboveSystem, in String reason);
     void clearPendingBackup();
     Intent getIntentForIntentSender(in IIntentSender sender);
     // This is not public because you need to be very careful in how you
@@ -363,9 +356,6 @@
     ActivityManager.StackInfo getFocusedStackInfo();
     void restart();
     void performIdleMaintenance();
-    void takePersistableUriPermission(in Uri uri, int modeFlags, String toPackage, int userId);
-    void releasePersistableUriPermission(in Uri uri, int modeFlags, String toPackage, int userId);
-    ParceledListSlice getPersistedUriPermissions(in String packageName, boolean incoming);
     void appNotRespondingViaProvider(in IBinder connection);
     Rect getTaskBounds(int taskId);
     boolean setProcessMemoryTrimLevel(in String process, int uid, int level);
@@ -393,7 +383,6 @@
     void setDumpHeapDebugLimit(in String processName, int uid, long maxMemSize,
             in String reportPackage);
     void dumpHeapFinished(in String path);
-    void setVoiceKeepAwake(in IVoiceInteractionSession session, boolean keepAwake);
     void updateLockTaskPackages(int userId, in String[] packages);
     void noteAlarmStart(in IIntentSender sender, in WorkSource workSource, int sourceUid, in String tag);
     void noteAlarmFinish(in IIntentSender sender, in WorkSource workSource, int sourceUid, in String tag);
@@ -442,12 +431,6 @@
     void resizeDockedStack(in Rect dockedBounds, in Rect tempDockedTaskBounds,
             in Rect tempDockedTaskInsetBounds,
             in Rect tempOtherTaskBounds, in Rect tempOtherTaskInsetBounds);
-    // Gets the URI permissions granted to an arbitrary package (or all packages if null)
-    // NOTE: this is different from getPersistedUriPermissions(), which returns the URIs the package
-    // granted to another packages (instead of those granted to it).
-    ParceledListSlice getGrantedUriPermissions(in String packageName, int userId);
-    // Clears the URI permissions granted to an arbitrary package.
-    void clearGrantedUriPermissions(in String packageName, int userId);
     boolean isAppForeground(int uid);
     void removeStack(int stackId);
     void makePackageIdle(String packageName, int userId);
@@ -499,4 +482,19 @@
      *  user unlock progress.
      */
     boolean startUserInBackgroundWithListener(int userid, IProgressListener unlockProgressListener);
+
+    /**
+     * Method for the shell UID to start deletating its permission identity to an
+     * active instrumenation. The shell can delegate permissions only to one active
+     * instrumentation at a time. An active instrumentation is one running and
+     * started from the shell.
+     */
+    void startDelegateShellPermissionIdentity(int uid);
+
+    /**
+     * Method for the shell UID to stop deletating its permission identity to an
+     * active instrumenation. An active instrumentation is one running and
+     * started from the shell.
+     */
+    void stopDelegateShellPermissionIdentity();
 }
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 1eb187e..46664c6 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -128,7 +128,7 @@
             in boolean stopProfiling);
     void activityResumed(in IBinder token);
     void activityPaused(in IBinder token);
-    oneway void activityStopped(in IBinder token, in Bundle state,
+    void activityStopped(in IBinder token, in Bundle state,
             in PersistableBundle persistentState, in CharSequence description);
     oneway void activityDestroyed(in IBinder token);
     void activityRelaunched(in IBinder token);
@@ -139,6 +139,7 @@
     ComponentName getCallingActivity(in IBinder token);
     void setFocusedTask(int taskId);
     boolean removeTask(int taskId);
+    void removeAllVisibleRecentTasks();
     List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);
     List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum, int ignoreActivityType,
             int ignoreWindowingMode);
@@ -196,7 +197,6 @@
     void startInPlaceAnimationOnFrontMostApplication(in Bundle opts);
     void registerTaskStackListener(in ITaskStackListener listener);
     void unregisterTaskStackListener(in ITaskStackListener listener);
-    int createStackOnDisplay(int displayId);
     void setTaskResizeable(int taskId, int resizeableMode);
     void exitFreeformMode(in IBinder token);
     void resizeTask(int taskId, in Rect bounds, int resizeMode);
@@ -421,4 +421,5 @@
     void stopAppSwitches();
     void resumeAppSwitches();
     void setActivityController(in IActivityController watcher, boolean imAMonkey);
+    void setVoiceKeepAwake(in IVoiceInteractionSession session, boolean keepAwake);
 }
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 3aeef14..4517446 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.app.backup.IBackupCallback;
 import android.app.backup.IBackupManager;
 import android.os.ParcelFileDescriptor;
  
@@ -55,7 +56,7 @@
     void doBackup(in ParcelFileDescriptor oldState,
             in ParcelFileDescriptor data,
             in ParcelFileDescriptor newState,
-            long quotaBytes, int token, IBackupManager callbackBinder, int transportFlags);
+            long quotaBytes, IBackupCallback callbackBinder, int transportFlags);
 
     /**
      * Restore an entire data snapshot to the application.
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index cd12710..3171e3e 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -43,7 +43,7 @@
     void cancelAllNotifications(String pkg, int userId);
 
     void clearData(String pkg, int uid, boolean fromApp);
-    void enqueueToast(String pkg, ITransientNotification callback, int duration);
+    void enqueueToast(String pkg, ITransientNotification callback, int duration, int displayId);
     void cancelToast(String pkg, ITransientNotification callback);
     void finishToken(String pkg, ITransientNotification callback);
 
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index d01938b..ac4bf7d 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -47,7 +47,8 @@
             in ParcelFileDescriptor source);
     void grantRuntimePermission(String packageName, String permission, int userId);
     void revokeRuntimePermission(String packageName, String permission, int userId);
-
+    void adoptShellPermissionIdentity(int uid);
+    void dropShellPermissionIdentity();
     // Called from the system process.
     oneway void shutdown();
 }
diff --git a/core/java/android/app/IUriGrantsManager.aidl b/core/java/android/app/IUriGrantsManager.aidl
new file mode 100644
index 0000000..928c627
--- /dev/null
+++ b/core/java/android/app/IUriGrantsManager.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.pm.ParceledListSlice;
+import android.net.Uri;
+import android.os.IBinder;
+
+/**
+ * Interface for managing an app's permission to access a particular URI.
+ * {@hide}
+ */
+interface IUriGrantsManager {
+    void takePersistableUriPermission(in Uri uri, int modeFlags, String toPackage, int userId);
+    void releasePersistableUriPermission(in Uri uri, int modeFlags, String toPackage, int userId);
+    void grantUriPermissionFromOwner(in IBinder owner, int fromUid, in String targetPkg,
+            in Uri uri, int mode, int sourceUserId, int targetUserId);
+    /**
+     * Gets the URI permissions granted to an arbitrary package (or all packages if null)
+     * NOTE: this is different from getPersistedUriPermissions(), which returns the URIs the package
+     * granted to another packages (instead of those granted to it).
+     */
+    ParceledListSlice getGrantedUriPermissions(in String packageName, int userId);
+    /** Clears the URI permissions granted to an arbitrary package. */
+    void clearGrantedUriPermissions(in String packageName, int userId);
+    ParceledListSlice getPersistedUriPermissions(in String packageName, boolean incoming);
+}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 34be41b6..34c2282 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
@@ -1313,7 +1314,8 @@
      * @param activity The activity being restored.
      * @param savedInstanceState The previously saved state being restored.
      */
-    public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
+    public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
+            @NonNull Bundle savedInstanceState) {
         activity.performRestoreInstanceState(savedInstanceState);
     }
 
@@ -1322,11 +1324,12 @@
      * method.  The default implementation simply calls through to that method.
      *
      * @param activity The activity being restored.
-     * @param savedInstanceState The previously saved state being restored.
+     * @param savedInstanceState The previously saved state being restored (or null).
      * @param persistentState The previously persisted state (or null)
      */
-    public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
-            PersistableBundle persistentState) {
+    public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
+            @Nullable Bundle savedInstanceState,
+            @Nullable PersistableBundle persistentState) {
         activity.performRestoreInstanceState(savedInstanceState, persistentState);
     }
 
@@ -1335,11 +1338,12 @@
      * The default implementation simply calls through to that method.
      *
      * @param activity The activity being created.
-     * @param icicle The previously frozen state (or null) to pass through to
+     * @param savedInstanceState The previously saved state (or null) to pass through to
      *               onPostCreate().
      */
-    public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
-        activity.onPostCreate(icicle);
+    public void callActivityOnPostCreate(@NonNull Activity activity,
+            @Nullable Bundle savedInstanceState) {
+        activity.onPostCreate(savedInstanceState);
     }
 
     /**
@@ -1347,12 +1351,14 @@
      * The default implementation simply calls through to that method.
      *
      * @param activity The activity being created.
-     * @param icicle The previously frozen state (or null) to pass through to
+     * @param savedInstanceState The previously frozen state (or null) to pass through to
      *               onPostCreate().
+     * @param persistentState The previously persisted state (or null)
      */
-    public void callActivityOnPostCreate(Activity activity, Bundle icicle,
-            PersistableBundle persistentState) {
-        activity.onPostCreate(icicle, persistentState);
+    public void callActivityOnPostCreate(@NonNull Activity activity,
+            @Nullable Bundle savedInstanceState,
+            @Nullable PersistableBundle persistentState) {
+        activity.onPostCreate(savedInstanceState, persistentState);
     }
 
     /**
@@ -1369,6 +1375,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
         final String oldReferrer = activity.mReferrer;
         try {
@@ -1439,7 +1446,8 @@
      * @param activity The activity being saved.
      * @param outState The bundle to pass to the call.
      */
-    public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
+    public void callActivityOnSaveInstanceState(@NonNull Activity activity,
+            @NonNull Bundle outState) {
         activity.performSaveInstanceState(outState);
     }
 
@@ -1450,8 +1458,8 @@
      * @param outState The bundle to pass to the call.
      * @param outPersistentState The persistent bundle to pass to the call.
      */
-    public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
-            PersistableBundle outPersistentState) {
+    public void callActivityOnSaveInstanceState(@NonNull Activity activity,
+            @NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
         activity.performSaveInstanceState(outState, outPersistentState);
     }
 
@@ -1632,6 +1640,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public ActivityResult execStartActivity(
             Context who, IBinder contextThread, IBinder token, Activity target,
             Intent intent, int requestCode, Bundle options) {
@@ -1685,6 +1694,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public void execStartActivities(Context who, IBinder contextThread,
             IBinder token, Activity target, Intent[] intents, Bundle options) {
         execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
@@ -1703,6 +1713,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int execStartActivitiesAsUser(Context who, IBinder contextThread,
             IBinder token, Activity target, Intent[] intents, Bundle options,
             int userId) {
@@ -1774,6 +1785,7 @@
      * 
      * {@hide}
      */
+    @UnsupportedAppUsage
     public ActivityResult execStartActivity(
         Context who, IBinder contextThread, IBinder token, String target,
         Intent intent, int requestCode, Bundle options) {
@@ -1841,6 +1853,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public ActivityResult execStartActivity(
             Context who, IBinder contextThread, IBinder token, String resultWho,
             Intent intent, int requestCode, Bundle options, UserHandle user) {
@@ -1886,6 +1899,7 @@
      * Special version!
      * @hide
      */
+    @UnsupportedAppUsage
     public ActivityResult execStartActivityAsCaller(
             Context who, IBinder contextThread, IBinder token, Activity target,
             Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity,
@@ -1932,6 +1946,7 @@
      * Special version!
      * @hide
      */
+    @UnsupportedAppUsage
     public void execStartActivityFromAppTask(
             Context who, IBinder contextThread, IAppTask appTask,
             Intent intent, Bundle options) {
@@ -1991,6 +2006,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void checkStartActivityResult(int res, Object intent) {
         if (!ActivityManager.isStartResultFatalError(res)) {
             return;
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 95ec24c..11c747f 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.annotation.Nullable;
 import android.content.Intent;
@@ -62,6 +63,7 @@
  */
 public abstract class IntentService extends Service {
     private volatile Looper mServiceLooper;
+    @UnsupportedAppUsage
     private volatile ServiceHandler mServiceHandler;
     private String mName;
     private boolean mRedelivery;
diff --git a/core/java/android/app/JobSchedulerImpl.java b/core/java/android/app/JobSchedulerImpl.java
index 4ac44f7..5494e2a 100644
--- a/core/java/android/app/JobSchedulerImpl.java
+++ b/core/java/android/app/JobSchedulerImpl.java
@@ -17,16 +17,15 @@
 // in android.app so ContextImpl has package access
 package android.app;
 
+import android.app.job.IJobScheduler;
 import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
-import android.app.job.IJobScheduler;
+import android.app.job.JobSnapshot;
 import android.app.job.JobWorkItem;
-import android.content.Intent;
 import android.os.RemoteException;
 
 import java.util.List;
 
-
 /**
  * Concrete implementation of the JobScheduler interface
  * @hide 
@@ -98,4 +97,22 @@
             return null;
         }
     }
+
+    @Override
+    public List<JobInfo> getStartedJobs() {
+        try {
+            return mBinder.getStartedJobs();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public List<JobSnapshot> getAllJobSnapshots() {
+        try {
+            return mBinder.getAllJobSnapshots();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
 }
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 9ceecd9..3085fe5 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -22,6 +22,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.trust.ITrustManager;
 import android.content.Context;
 import android.content.Intent;
@@ -414,6 +415,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isDeviceLocked(int userId) {
         try {
             return mTrustManager.isDeviceLocked(userId);
@@ -439,6 +441,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isDeviceSecure(int userId) {
         try {
             return mTrustManager.isDeviceSecure(userId);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 494b547..ddd9441 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -73,12 +74,14 @@
 import java.util.Objects;
 
 final class IntentReceiverLeaked extends AndroidRuntimeException {
+    @UnsupportedAppUsage
     public IntentReceiverLeaked(String msg) {
         super(msg);
     }
 }
 
 final class ServiceConnectionLeaked extends AndroidRuntimeException {
+    @UnsupportedAppUsage
     public ServiceConnectionLeaked(String msg) {
         super(msg);
     }
@@ -93,36 +96,52 @@
     static final boolean DEBUG = false;
     private static final String PROPERTY_NAME_APPEND_NATIVE = "pi.append_native_lib_paths";
 
+    @UnsupportedAppUsage
     private final ActivityThread mActivityThread;
+    @UnsupportedAppUsage
     final String mPackageName;
+    @UnsupportedAppUsage
     private ApplicationInfo mApplicationInfo;
+    @UnsupportedAppUsage
     private String mAppDir;
+    @UnsupportedAppUsage
     private String mResDir;
     private String[] mOverlayDirs;
+    @UnsupportedAppUsage
     private String mDataDir;
+    @UnsupportedAppUsage
     private String mLibDir;
+    @UnsupportedAppUsage
     private File mDataDirFile;
     private File mDeviceProtectedDataDirFile;
     private File mCredentialProtectedDataDirFile;
+    @UnsupportedAppUsage
     private final ClassLoader mBaseClassLoader;
     private final boolean mSecurityViolation;
     private final boolean mIncludeCode;
     private final boolean mRegisterPackage;
+    @UnsupportedAppUsage
     private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
     /** WARNING: This may change. Don't hold external references to it. */
+    @UnsupportedAppUsage
     Resources mResources;
+    @UnsupportedAppUsage
     private ClassLoader mClassLoader;
+    @UnsupportedAppUsage
     private Application mApplication;
 
     private String[] mSplitNames;
     private String[] mSplitAppDirs;
+    @UnsupportedAppUsage
     private String[] mSplitResDirs;
     private String[] mSplitClassLoaderNames;
 
+    @UnsupportedAppUsage
     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
         = new ArrayMap<>();
     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
         = new ArrayMap<>();
+    @UnsupportedAppUsage
     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
         = new ArrayMap<>();
     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
@@ -236,10 +255,12 @@
         return mAppComponentFactory;
     }
 
+    @UnsupportedAppUsage
     public String getPackageName() {
         return mPackageName;
     }
 
+    @UnsupportedAppUsage
     public ApplicationInfo getApplicationInfo() {
         return mApplicationInfo;
     }
@@ -252,6 +273,7 @@
         return mSecurityViolation;
     }
 
+    @UnsupportedAppUsage
     public CompatibilityInfo getCompatibilityInfo() {
         return mDisplayAdjustments.getCompatibilityInfo();
     }
@@ -804,6 +826,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public ClassLoader getClassLoader() {
         synchronized (this) {
             if (mClassLoader == null) {
@@ -972,6 +995,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public String getAppDir() {
         return mAppDir;
     }
@@ -980,6 +1004,7 @@
         return mLibDir;
     }
 
+    @UnsupportedAppUsage
     public String getResDir() {
         return mResDir;
     }
@@ -988,10 +1013,12 @@
         return mSplitAppDirs;
     }
 
+    @UnsupportedAppUsage
     public String[] getSplitResDirs() {
         return mSplitResDirs;
     }
 
+    @UnsupportedAppUsage
     public String[] getOverlayDirs() {
         return mOverlayDirs;
     }
@@ -1000,6 +1027,7 @@
         return mDataDir;
     }
 
+    @UnsupportedAppUsage
     public File getDataDirFile() {
         return mDataDirFile;
     }
@@ -1012,10 +1040,12 @@
         return mCredentialProtectedDataDirFile;
     }
 
+    @UnsupportedAppUsage
     public AssetManager getAssets() {
         return getResources().getAssets();
     }
 
+    @UnsupportedAppUsage
     public Resources getResources() {
         if (mResources == null) {
             final String[] splitPaths;
@@ -1034,6 +1064,7 @@
         return mResources;
     }
 
+    @UnsupportedAppUsage
     public Application makeApplication(boolean forceDefaultAppClass,
             Instrumentation instrumentation) {
         if (mApplication != null) {
@@ -1102,6 +1133,7 @@
         return app;
     }
 
+    @UnsupportedAppUsage
     private void rewriteRValues(ClassLoader cl, String packageName, int id) {
         final Class<?> rClazz;
         try {
@@ -1324,7 +1356,9 @@
         }
 
         final IIntentReceiver.Stub mIIntentReceiver;
+        @UnsupportedAppUsage
         final BroadcastReceiver mReceiver;
+        @UnsupportedAppUsage
         final Context mContext;
         final Handler mActivityThread;
         final Instrumentation mInstrumentation;
@@ -1448,10 +1482,12 @@
             return mLocation;
         }
 
+        @UnsupportedAppUsage
         BroadcastReceiver getIntentReceiver() {
             return mReceiver;
         }
 
+        @UnsupportedAppUsage
         IIntentReceiver getIIntentReceiver() {
             return mIIntentReceiver;
         }
@@ -1489,6 +1525,7 @@
 
     }
 
+    @UnsupportedAppUsage
     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
             Context context, Handler handler, int flags) {
         synchronized (mServices) {
@@ -1566,7 +1603,9 @@
 
     static final class ServiceDispatcher {
         private final ServiceDispatcher.InnerConnection mIServiceConnection;
+        @UnsupportedAppUsage
         private final ServiceConnection mConnection;
+        @UnsupportedAppUsage
         private final Context mContext;
         private final Handler mActivityThread;
         private final ServiceConnectionLeaked mLocation;
@@ -1582,6 +1621,7 @@
         }
 
         private static class InnerConnection extends IServiceConnection.Stub {
+            @UnsupportedAppUsage
             final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
 
             InnerConnection(LoadedApk.ServiceDispatcher sd) {
@@ -1600,6 +1640,7 @@
         private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
             = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
 
+        @UnsupportedAppUsage
         ServiceDispatcher(ServiceConnection conn,
                 Context context, Handler activityThread, int flags) {
             mIServiceConnection = new InnerConnection(this);
@@ -1645,6 +1686,7 @@
             return mConnection;
         }
 
+        @UnsupportedAppUsage
         IServiceConnection getIServiceConnection() {
             return mIServiceConnection;
         }
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index e297719..a52fb1a 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.servertransaction.PendingTransactionActions;
 import android.content.Intent;
@@ -73,18 +74,23 @@
     /** Thread our activities are running in. */
     private final ActivityThread mActivityThread;
     /** The containing activity that owns the activities we create. */
+    @UnsupportedAppUsage
     private final Activity mParent;
 
     /** The activity that is currently resumed. */
+    @UnsupportedAppUsage
     private LocalActivityRecord mResumed;
     /** id -> record of all known activities. */
+    @UnsupportedAppUsage
     private final Map<String, LocalActivityRecord> mActivities
             = new HashMap<String, LocalActivityRecord>();
     /** array of all known activities for easy iterating. */
+    @UnsupportedAppUsage
     private final ArrayList<LocalActivityRecord> mActivityArray
             = new ArrayList<LocalActivityRecord>();
 
     /** True if only one activity can be resumed at a time */
+    @UnsupportedAppUsage
     private boolean mSingleMode;
     
     /** Set to true once we find out the container is finishing. */
@@ -111,6 +117,7 @@
         mSingleMode = singleMode;
     }
 
+    @UnsupportedAppUsage
     private void moveToState(LocalActivityRecord r, int desiredState) {
         if (r.curState == RESTORED || r.curState == DESTROYED) {
             // startActivity() has not yet been called, so nothing to do.
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index ca663fd..25eb958 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -70,6 +71,7 @@
     private NativeContentView mNativeContentView;
     private InputMethodManager mIMM;
 
+    @UnsupportedAppUsage
     private long mNativeHandle;
     
     private InputQueue mCurInputQueue;
@@ -85,6 +87,7 @@
 
     private boolean mDestroyed;
     
+    @UnsupportedAppUsage
     private native long loadNativeCode(String path, String funcname, MessageQueue queue,
             String internalDataPath, String obbPath, String externalDataPath, int sdkVersion,
             AssetManager assetMgr, byte[] savedState, ClassLoader classLoader, String libraryPath);
@@ -312,18 +315,22 @@
         }
     }
 
+    @UnsupportedAppUsage
     void setWindowFlags(int flags, int mask) {
         getWindow().setFlags(flags, mask);
     }
     
+    @UnsupportedAppUsage
     void setWindowFormat(int format) {
         getWindow().setFormat(format);
     }
 
+    @UnsupportedAppUsage
     void showIme(int mode) {
         mIMM.showSoftInput(mNativeContentView, mode);
     }
 
+    @UnsupportedAppUsage
     void hideIme(int mode) {
         mIMM.hideSoftInputFromWindow(mNativeContentView.getWindowToken(), mode);
     }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 05bf6bf..9dca061 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -27,6 +27,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -202,6 +203,11 @@
      */
     private static final int MAX_REPLY_HISTORY = 5;
 
+    /**
+     * Maximum numbers of action buttons in a notification.
+     * @hide
+     */
+    public static final int MAX_ACTION_BUTTONS = 3;
 
     /**
      * If the notification contained an unsent draft for a RemoteInput when the user clicked on it,
@@ -868,6 +874,7 @@
      */
     public String category;
 
+    @UnsupportedAppUsage
     private String mGroupKey;
 
     /**
@@ -913,6 +920,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public ArraySet<PendingIntent> allPendingIntents;
 
     /**
@@ -1252,9 +1260,12 @@
      */
     public static final String EXTRA_FOREGROUND_APPS = "android.foregroundApps";
 
+    @UnsupportedAppUsage
     private Icon mSmallIcon;
+    @UnsupportedAppUsage
     private Icon mLargeIcon;
 
+    @UnsupportedAppUsage
     private String mChannelId;
     private long mTimeout;
 
@@ -1406,6 +1417,7 @@
         public static final int SEMANTIC_ACTION_CALL = 10;
 
         private final Bundle mExtras;
+        @UnsupportedAppUsage
         private Icon mIcon;
         private final RemoteInput[] mRemoteInputs;
         private boolean mAllowGeneratedReplies = true;
@@ -2060,6 +2072,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public Notification(Context context, int icon, CharSequence tickerText, long when,
             CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
     {
@@ -3072,6 +3085,7 @@
      * Used when notifying to clean up legacy small icons.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSmallIcon(Icon icon) {
         mSmallIcon = icon;
     }
@@ -3088,6 +3102,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isGroupSummary() {
         return mGroupKey != null && (flags & FLAG_GROUP_SUMMARY) != 0;
     }
@@ -3095,6 +3110,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isGroupChild() {
         return mGroupKey != null && (flags & FLAG_GROUP_SUMMARY) == 0;
     }
@@ -3151,8 +3167,6 @@
         public static final String EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT
                 = "android.rebuild.hudViewActionCount";
 
-        private static final int MAX_ACTION_BUTTONS = 3;
-
         private static final boolean USE_ONLY_TITLE_IN_LOW_PRIORITY_SUMMARY =
                 SystemProperties.getBoolean("notifications.only_title", true);
 
@@ -3173,6 +3187,7 @@
         private Notification mN;
         private Bundle mUserExtras = new Bundle();
         private Style mStyle;
+        @UnsupportedAppUsage
         private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
         private ArrayList<Person> mPersonList = new ArrayList<>();
         private ContrastColorUtil mColorUtil;
@@ -4473,9 +4488,9 @@
                 mTextColorsAreForBackground = backgroundColor;
                 if (!hasForegroundColor() || !isColorized()) {
                     mPrimaryTextColor = ContrastColorUtil.resolvePrimaryColor(mContext,
-                            backgroundColor);
+                            backgroundColor, mInNightMode);
                     mSecondaryTextColor = ContrastColorUtil.resolveSecondaryColor(mContext,
-                            backgroundColor);
+                            backgroundColor, mInNightMode);
                     if (backgroundColor != COLOR_DEFAULT && isColorized()) {
                         mPrimaryTextColor = ContrastColorUtil.findAlphaToMeetContrast(
                                 mPrimaryTextColor, backgroundColor, 4.5);
@@ -4790,6 +4805,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public String loadHeaderAppName() {
             CharSequence name = null;
             final PackageManager pm = mContext.getPackageManager();
@@ -5116,6 +5132,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public RemoteViews makePublicContentView() {
             return makePublicView(false /* ambient */);
         }
@@ -5260,7 +5277,7 @@
                     // background color
                     background = outResultColor[0].getDefaultColor();
                     int textColor = ContrastColorUtil.resolvePrimaryColor(mContext,
-                            background);
+                            background, mInNightMode);
                     button.setTextColor(R.id.action0, textColor);
                     rippleColor = textColor;
                 } else if (mN.color != COLOR_DEFAULT && !isColorized() && mTintActionButtons) {
@@ -5440,7 +5457,7 @@
                     com.android.internal.R.color.notification_material_background_color);
             if (mN.color == COLOR_DEFAULT) {
                 ensureColors();
-                color = ContrastColorUtil.resolveDefaultColor(mContext, background);
+                color = ContrastColorUtil.resolveDefaultColor(mContext, background, mInNightMode);
             } else {
                 color = ContrastColorUtil.resolveContrastColor(mContext, mN.color,
                         background, mInNightMode);
@@ -5459,7 +5476,8 @@
             }
             int background = mContext.getColor(
                     com.android.internal.R.color.notification_material_background_color);
-            mNeutralColor = ContrastColorUtil.resolveDefaultColor(mContext, background);
+            mNeutralColor = ContrastColorUtil.resolveDefaultColor(mContext, background,
+                    mInNightMode);
             if (Color.alpha(mNeutralColor) < 255) {
                 // alpha doesn't go well for color filters, so let's blend it manually
                 mNeutralColor = ContrastColorUtil.compositeColors(mNeutralColor, background);
@@ -5659,6 +5677,7 @@
             return clone;
         }
 
+        @UnsupportedAppUsage
         private int getBaseLayoutResource() {
             return R.layout.notification_template_material_base;
         }
@@ -7162,8 +7181,8 @@
         }
 
         public static final class Message {
-
-            static final String KEY_TEXT = "text";
+            /** @hide */
+            public static final String KEY_TEXT = "text";
             static final String KEY_TIMESTAMP = "time";
             static final String KEY_SENDER = "sender";
             static final String KEY_SENDER_PERSON = "sender_person";
@@ -7749,6 +7768,7 @@
          * @hide
          */
         @Override
+        @UnsupportedAppUsage
         public Notification buildStyled(Notification wip) {
             super.buildStyled(wip);
             if (wip.category == null) {
@@ -7830,10 +7850,13 @@
 
             // If the action buttons should not be tinted, then just use the default
             // notification color. Otherwise, just use the passed-in color.
+            Configuration currentConfig = mBuilder.mContext.getResources().getConfiguration();
+            boolean inNightMode = (currentConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+                    == Configuration.UI_MODE_NIGHT_YES;
             int tintColor = mBuilder.shouldTintActionButtons() || mBuilder.isColorized()
                     ? color
                     : ContrastColorUtil.resolveColor(mBuilder.mContext,
-                            Notification.COLOR_DEFAULT);
+                            Notification.COLOR_DEFAULT, inNightMode);
 
             button.setDrawableTint(R.id.action0, false, tintColor,
                     PorterDuff.Mode.SRC_ATOP);
@@ -7853,8 +7876,8 @@
             final int N = mActionsToShowInCompact == null
                     ? 0
                     : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT);
+            view.removeAllViews(com.android.internal.R.id.media_actions);
             if (N > 0) {
-                view.removeAllViews(com.android.internal.R.id.media_actions);
                 for (int i = 0; i < N; i++) {
                     if (i >= numActions) {
                         throw new IllegalArgumentException(String.format(
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 1ad3054..848def6 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -17,6 +17,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.NotificationManager.Importance;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -38,6 +39,7 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.Arrays;
 
 /**
@@ -132,6 +134,7 @@
     private static final boolean DEFAULT_DELETED = false;
     private static final boolean DEFAULT_SHOW_BADGE = true;
 
+    @UnsupportedAppUsage
     private final String mId;
     private String mName;
     private String mDesc;
@@ -299,6 +302,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setBlockableSystem(boolean blockableSystem) {
         mBlockableSystem = blockableSystem;
     }
@@ -601,6 +605,13 @@
     /**
      * @hide
      */
+    public boolean isImportanceLocked() {
+        return (mUserLockedFields & USER_LOCKED_IMPORTANCE) != 0;
+    }
+
+    /**
+     * @hide
+     */
     public void populateFromXmlForRestore(XmlPullParser parser, Context context) {
         populateFromXml(parser, true, context);
     }
@@ -942,6 +953,32 @@
         return result;
     }
 
+    /** @hide */
+    public void dump(PrintWriter pw, String prefix, boolean redacted) {
+        String redactedName = redacted ? TextUtils.trimToLengthWithEllipsis(mName, 3) : mName;
+        String output = "NotificationChannel{"
+                + "mId='" + mId + '\''
+                + ", mName=" + redactedName
+                + ", mDescription=" + (!TextUtils.isEmpty(mDesc) ? "hasDescription " : "")
+                + ", mImportance=" + mImportance
+                + ", mBypassDnd=" + mBypassDnd
+                + ", mLockscreenVisibility=" + mLockscreenVisibility
+                + ", mSound=" + mSound
+                + ", mLights=" + mLights
+                + ", mLightColor=" + mLightColor
+                + ", mVibration=" + Arrays.toString(mVibration)
+                + ", mUserLockedFields=" + Integer.toHexString(mUserLockedFields)
+                + ", mFgServiceShown=" + mFgServiceShown
+                + ", mVibrationEnabled=" + mVibrationEnabled
+                + ", mShowBadge=" + mShowBadge
+                + ", mDeleted=" + mDeleted
+                + ", mGroup='" + mGroup + '\''
+                + ", mAudioAttributes=" + mAudioAttributes
+                + ", mBlockableSystem=" + mBlockableSystem
+                + '}';
+        pw.println(prefix + output);
+    }
+
     @Override
     public String toString() {
         return "NotificationChannel{"
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index 0fa3c7f..17c5cba 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -17,6 +17,7 @@
 
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -49,6 +50,7 @@
     private static final String ATT_ID = "id";
     private static final String ATT_BLOCKED = "blocked";
 
+    @UnsupportedAppUsage
     private final String mId;
     private CharSequence mName;
     private String mDescription;
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index f6dc5d1..4b25b8b 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Notification.Builder;
 import android.content.ComponentName;
 import android.content.Context;
@@ -308,9 +309,11 @@
      */
     public static final int IMPORTANCE_MAX = 5;
 
+    @UnsupportedAppUsage
     private static INotificationManager sService;
 
     /** @hide */
+    @UnsupportedAppUsage
     static public INotificationManager getService()
     {
         if (sService != null) {
@@ -321,12 +324,14 @@
         return sService;
     }
 
+    @UnsupportedAppUsage
     /*package*/ NotificationManager(Context context, Handler handler)
     {
         mContext = context;
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static NotificationManager from(Context context) {
         return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
     }
@@ -373,6 +378,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
     {
         INotificationManager service = getService();
@@ -438,6 +444,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void cancelAsUser(String tag, int id, UserHandle user)
     {
         INotificationManager service = getService();
@@ -666,6 +673,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setZenMode(int mode, Uri conditionId, String reason) {
         INotificationManager service = getService();
         try {
@@ -690,6 +698,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public ZenModeConfig getZenModeConfig() {
         INotificationManager service = getService();
         try {
diff --git a/core/java/android/app/PackageDeleteObserver.java b/core/java/android/app/PackageDeleteObserver.java
index 9b83ec1..20ae84c 100644
--- a/core/java/android/app/PackageDeleteObserver.java
+++ b/core/java/android/app/PackageDeleteObserver.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.content.pm.IPackageDeleteObserver2;
 
diff --git a/core/java/android/app/PackageInstallObserver.java b/core/java/android/app/PackageInstallObserver.java
index ff28679..507ebe5 100644
--- a/core/java/android/app/PackageInstallObserver.java
+++ b/core/java/android/app/PackageInstallObserver.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.content.pm.IPackageInstallObserver2;
 import android.os.Bundle;
@@ -59,6 +60,7 @@
      *            basic outcome
      * @hide
      */
+    @UnsupportedAppUsage
     public void onPackageInstalled(String basePackageName, int returnCode, String msg,
             Bundle extras) {
     }
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index bdaf80e..75d95b2 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.IIntentReceiver;
 import android.content.IIntentSender;
@@ -274,6 +275,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void setOnMarshaledListener(OnMarshaledListener listener) {
         sOnMarshaledListener.set(listener);
     }
@@ -362,6 +364,7 @@
      * Note that UserHandle.CURRENT will be interpreted at the time the
      * activity is started, not when the pending intent is created.
      */
+    @UnsupportedAppUsage
     public static PendingIntent getActivityAsUser(Context context, int requestCode,
             @NonNull Intent intent, int flags, Bundle options, UserHandle user) {
         String packageName = context.getPackageName();
@@ -557,6 +560,7 @@
      * Note that UserHandle.CURRENT will be interpreted at the time the
      * broadcast is sent, not when the pending intent is created.
      */
+    @UnsupportedAppUsage
     public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
             Intent intent, int flags, UserHandle userHandle) {
         String packageName = context.getPackageName();
@@ -1084,6 +1088,7 @@
      * @hide
      * Check whether this PendingIntent will launch an Activity.
      */
+    @UnsupportedAppUsage
     public boolean isActivity() {
         try {
             return ActivityManager.getService()
@@ -1110,6 +1115,7 @@
      * @hide
      * Return the Intent of this PendingIntent.
      */
+    @UnsupportedAppUsage
     public Intent getIntent() {
         try {
             return ActivityManager.getService()
@@ -1123,6 +1129,7 @@
      * @hide
      * Return descriptive tag for this PendingIntent.
      */
+    @UnsupportedAppUsage
     public String getTag(String prefix) {
         try {
             return ActivityManager.getService()
diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java
index cbe8bb9..adcc495 100644
--- a/core/java/android/app/PictureInPictureArgs.java
+++ b/core/java/android/app/PictureInPictureArgs.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -137,6 +138,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public PictureInPictureArgs() {
     }
 
@@ -173,6 +175,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setAspectRatio(float aspectRatio) {
         // Temporary workaround
         mAspectRatio = new Rational((int) (aspectRatio * 1000000000), 1000000000);
@@ -182,6 +185,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setActions(List<RemoteAction> actions) {
         if (mUserActions != null) {
             mUserActions = null;
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index af55788..cb72d4d 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -20,6 +20,7 @@
 import static android.content.Context.WINDOW_SERVICE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.hardware.display.DisplayManager;
@@ -300,6 +301,7 @@
         return dm.equalsPhysical(getResources().getDisplayMetrics());
     }
 
+    @UnsupportedAppUsage
     private static Context createPresentationContext(
             Context outerContext, Display display, int theme) {
         if (outerContext == null) {
diff --git a/core/java/android/app/ProgressDialog.java b/core/java/android/app/ProgressDialog.java
index 8a083eb..1b10fd7 100644
--- a/core/java/android/app/ProgressDialog.java
+++ b/core/java/android/app/ProgressDialog.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.R;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
@@ -63,10 +64,13 @@
      */
     public static final int STYLE_HORIZONTAL = 1;
     
+    @UnsupportedAppUsage
     private ProgressBar mProgress;
+    @UnsupportedAppUsage
     private TextView mMessageView;
     
     private int mProgressStyle = STYLE_SPINNER;
+    @UnsupportedAppUsage
     private TextView mProgressNumber;
     private String mProgressNumberFormat;
     private TextView mProgressPercent;
diff --git a/core/java/android/app/QueuedWork.java b/core/java/android/app/QueuedWork.java
index 56338f5..7626539 100644
--- a/core/java/android/app/QueuedWork.java
+++ b/core/java/android/app/QueuedWork.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -70,6 +71,7 @@
 
     /** Finishers {@link #addFinisher added} and not yet {@link #removeFinisher removed} */
     @GuardedBy("sLock")
+    @UnsupportedAppUsage
     private static final LinkedList<Runnable> sFinishers = new LinkedList<>();
 
     /** {@link #getHandler() Lazily} created handler */
@@ -96,6 +98,7 @@
      *
      * @return the handler
      */
+    @UnsupportedAppUsage
     private static Handler getHandler() {
         synchronized (sLock) {
             if (sHandler == null) {
@@ -121,6 +124,7 @@
      *
      * @param finisher The runnable to add as finisher
      */
+    @UnsupportedAppUsage
     public static void addFinisher(Runnable finisher) {
         synchronized (sLock) {
             sFinishers.add(finisher);
@@ -132,6 +136,7 @@
      *
      * @param finisher The runnable to remove.
      */
+    @UnsupportedAppUsage
     public static void removeFinisher(Runnable finisher) {
         synchronized (sLock) {
             sFinishers.remove(finisher);
@@ -212,6 +217,7 @@
      * @param work The new runnable to process
      * @param shouldDelay If the message should be delayed
      */
+    @UnsupportedAppUsage
     public static void queue(Runnable work, boolean shouldDelay) {
         Handler handler = getHandler();
 
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 30256b4..2d9fbf97 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
@@ -76,18 +77,21 @@
      * The global configuration upon which all Resources are based. Multi-window Resources
      * apply their overrides to this configuration.
      */
+    @UnsupportedAppUsage
     private final Configuration mResConfiguration = new Configuration();
 
     /**
      * A mapping of ResourceImpls and their configurations. These are heavy weight objects
      * which should be reused as much as possible.
      */
+    @UnsupportedAppUsage
     private final ArrayMap<ResourcesKey, WeakReference<ResourcesImpl>> mResourceImpls =
             new ArrayMap<>();
 
     /**
      * A list of Resource references that can be reused.
      */
+    @UnsupportedAppUsage
     private final ArrayList<WeakReference<Resources>> mResourceReferences = new ArrayList<>();
 
     private static class ApkKey {
@@ -121,10 +125,13 @@
         }
     }
 
+    private static final boolean ENABLE_APK_ASSETS_CACHE = false;
+
     /**
      * The ApkAssets we are caching and intend to hold strong references to.
      */
-    private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets = new LruCache<>(3);
+    private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets =
+            (ENABLE_APK_ASSETS_CACHE) ? new LruCache<>(3) : null;
 
     /**
      * The ApkAssets that are being referenced in the wild that we can reuse, even if they aren't
@@ -144,6 +151,7 @@
      * Each Activity may has a base override configuration that is applied to each Resources object,
      * which in turn may have their own override configuration specified.
      */
+    @UnsupportedAppUsage
     private final WeakHashMap<IBinder, ActivityResources> mActivityResourceReferences =
             new WeakHashMap<>();
 
@@ -153,6 +161,7 @@
     private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>>
             mAdjustedDisplays = new ArrayMap<>();
 
+    @UnsupportedAppUsage
     public static ResourcesManager getInstance() {
         synchronized (ResourcesManager.class) {
             if (sResourcesManager == null) {
@@ -310,9 +319,12 @@
     private @NonNull ApkAssets loadApkAssets(String path, boolean sharedLib, boolean overlay)
             throws IOException {
         final ApkKey newKey = new ApkKey(path, sharedLib, overlay);
-        ApkAssets apkAssets = mLoadedApkAssets.get(newKey);
-        if (apkAssets != null) {
-            return apkAssets;
+        ApkAssets apkAssets = null;
+        if (mLoadedApkAssets != null) {
+            apkAssets = mLoadedApkAssets.get(newKey);
+            if (apkAssets != null) {
+                return apkAssets;
+            }
         }
 
         // Optimistically check if this ApkAssets exists somewhere else.
@@ -320,7 +332,10 @@
         if (apkAssetsRef != null) {
             apkAssets = apkAssetsRef.get();
             if (apkAssets != null) {
-                mLoadedApkAssets.put(newKey, apkAssets);
+                if (mLoadedApkAssets != null) {
+                    mLoadedApkAssets.put(newKey, apkAssets);
+                }
+
                 return apkAssets;
             } else {
                 // Clean up the reference.
@@ -335,7 +350,11 @@
         } else {
             apkAssets = ApkAssets.loadFromPath(path, false /*system*/, sharedLib);
         }
-        mLoadedApkAssets.put(newKey, apkAssets);
+
+        if (mLoadedApkAssets != null) {
+            mLoadedApkAssets.put(newKey, apkAssets);
+        }
+
         mCachedApkAssets.put(newKey, new WeakReference<>(apkAssets));
         return apkAssets;
     }
@@ -349,6 +368,7 @@
      * @return a new AssetManager.
     */
     @VisibleForTesting
+    @UnsupportedAppUsage
     protected @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key) {
         final AssetManager.Builder builder = new AssetManager.Builder();
 
@@ -434,18 +454,22 @@
 
             pw.println("ResourcesManager:");
             pw.increaseIndent();
-            pw.print("cached apks: total=");
-            pw.print(mLoadedApkAssets.size());
-            pw.print(" created=");
-            pw.print(mLoadedApkAssets.createCount());
-            pw.print(" evicted=");
-            pw.print(mLoadedApkAssets.evictionCount());
-            pw.print(" hit=");
-            pw.print(mLoadedApkAssets.hitCount());
-            pw.print(" miss=");
-            pw.print(mLoadedApkAssets.missCount());
-            pw.print(" max=");
-            pw.print(mLoadedApkAssets.maxSize());
+            if (mLoadedApkAssets != null) {
+                pw.print("cached apks: total=");
+                pw.print(mLoadedApkAssets.size());
+                pw.print(" created=");
+                pw.print(mLoadedApkAssets.createCount());
+                pw.print(" evicted=");
+                pw.print(mLoadedApkAssets.evictionCount());
+                pw.print(" hit=");
+                pw.print(mLoadedApkAssets.hitCount());
+                pw.print(" miss=");
+                pw.print(mLoadedApkAssets.missCount());
+                pw.print(" max=");
+                pw.print(mLoadedApkAssets.maxSize());
+            } else {
+                pw.print("cached apks: 0 [cache disabled]");
+            }
             pw.println();
 
             pw.print("total apks: ");
@@ -1065,6 +1089,7 @@
      * @param assetPath The main asset path for which to add the library asset path.
      * @param libAsset The library asset path to add.
      */
+    @UnsupportedAppUsage
     public void appendLibAssetForMainAssetPath(String assetPath, String libAsset) {
         synchronized (this) {
             // Record which ResourcesImpl need updating
diff --git a/core/java/android/app/ResultInfo.java b/core/java/android/app/ResultInfo.java
index d5af08a..4335488 100644
--- a/core/java/android/app/ResultInfo.java
+++ b/core/java/android/app/ResultInfo.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -26,11 +27,15 @@
  * {@hide}
  */
 public class ResultInfo implements Parcelable {
+    @UnsupportedAppUsage
     public final String mResultWho;
+    @UnsupportedAppUsage
     public final int mRequestCode;
     public final int mResultCode;
+    @UnsupportedAppUsage
     public final Intent mData;
 
+    @UnsupportedAppUsage
     public ResultInfo(String resultWho, int requestCode, int resultCode,
             Intent data) {
         mResultWho = resultWho;
@@ -60,6 +65,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<ResultInfo> CREATOR
             = new Parcelable.Creator<ResultInfo>() {
         public ResultInfo createFromParcel(Parcel in) {
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 4abca9a..4a45150 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -17,6 +17,7 @@
 package android.app;
 
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -312,6 +313,7 @@
      * 
      * @param working true to show spinner, false to hide spinner
      */
+    @UnsupportedAppUsage
     public void setWorking(boolean working) {
         mWorkingSpinner.setAlpha(working ? 255 : 0);
         mWorkingSpinner.setVisible(working, false);
@@ -373,6 +375,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     static boolean isLandscapeMode(Context context) {
         return context.getResources().getConfiguration().orientation
                 == Configuration.ORIENTATION_LANDSCAPE;
@@ -517,6 +520,7 @@
     /**
      * Launch a search for the text in the query text field.
      */
+    @UnsupportedAppUsage
     public void launchQuerySearch() {
         launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null);
     }
@@ -529,6 +533,7 @@
      * @param actionMsg The message for the action key that was pressed,
      *        or <code>null</code> if none.
      */
+    @UnsupportedAppUsage
     protected void launchQuerySearch(int actionKey, String actionMsg) {
         String query = mSearchAutoComplete.getText().toString();
         String action = Intent.ACTION_SEARCH;
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index ed6d2f5..9539f34 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -530,6 +531,7 @@
      * current search engine does not support voice search.
      * @hide
      */
+    @UnsupportedAppUsage
     public final static String DISABLE_VOICE_SEARCH
             = "android.search.DISABLE_VOICE_SEARCH";
 
@@ -545,8 +547,10 @@
     /* package */ OnDismissListener mDismissListener = null;
     /* package */ OnCancelListener mCancelListener = null;
 
+    @UnsupportedAppUsage
     private SearchDialog mSearchDialog;
 
+    @UnsupportedAppUsage
     /*package*/ SearchManager(Context context, Handler handler) throws ServiceNotFoundException {
         mContext = context;
         mHandler = handler;
@@ -609,6 +613,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void startSearch(String initialQuery,
                             boolean selectInitialQuery,
                             ComponentName launchActivity,
@@ -710,6 +715,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public ComponentName getWebSearchActivity() {
         try {
             return mService.getWebSearchActivity();
@@ -770,6 +776,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isVisible() {
         return mSearchDialog == null? false : mSearchDialog.isShowing();
     }
@@ -866,6 +873,7 @@
      *
      * @hide because SearchableInfo is not part of the API.
      */
+    @UnsupportedAppUsage
     public Cursor getSuggestions(SearchableInfo searchable, String query) {
         return getSuggestions(searchable, query, -1);
     }
@@ -881,6 +889,7 @@
      *
      * @hide because SearchableInfo is not part of the API.
      */
+    @UnsupportedAppUsage
     public Cursor getSuggestions(SearchableInfo searchable, String query, int limit) {
         if (searchable == null) {
             return null;
@@ -970,6 +979,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void launchAssist(Bundle args) {
         try {
             if (mService == null) {
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index a952915..ae6d32a 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -20,6 +20,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -249,6 +250,7 @@
      * @return Returns a context related to the searchable activity
      * @hide
      */
+    @UnsupportedAppUsage
     public Context getActivityContext(Context context) {
         return createActivityContext(context, mSearchActivity);
     }
@@ -278,6 +280,7 @@
      * @return Returns a context related to the suggestion provider
      * @hide
      */
+    @UnsupportedAppUsage
     public Context getProviderContext(Context context, Context activityContext) {
         Context theirContext = null;
         if (mSearchActivity.getPackageName().equals(mSuggestProviderPackage)) {
@@ -307,6 +310,7 @@
      * @param cName The component name of the searchable activity
      * @throws IllegalArgumentException if the searchability info is invalid or insufficient
      */
+    @UnsupportedAppUsage
     private SearchableInfo(Context activityContext, AttributeSet attr, final ComponentName cName) {
         mSearchActivity = cName;
         
@@ -450,6 +454,7 @@
          * Gets the action message to use for queries.
          * @see android.R.styleable#SearchableActionKey_queryActionMsg
          */
+        @UnsupportedAppUsage
         public String getQueryActionMsg() {
             return mQueryActionMsg;
         }
@@ -458,6 +463,7 @@
          * Gets the action message to use for suggestions.
          * @see android.R.styleable#SearchableActionKey_suggestActionMsg
          */
+        @UnsupportedAppUsage
         public String getSuggestActionMsg() {
             return mSuggestActionMsg;
         }
@@ -466,6 +472,7 @@
          * Gets the name of the column to get the suggestion action message from.
          * @see android.R.styleable#SearchableActionKey_suggestActionMsgColumn
          */
+        @UnsupportedAppUsage
         public String getSuggestActionMsgColumn() {
             return mSuggestActionMsgColumn;
         }
@@ -490,6 +497,7 @@
      *
      * @hide ActionKeyInfo is hidden
      */
+    @UnsupportedAppUsage
     public ActionKeyInfo findActionKey(int keyCode) {
         if (mActionKeys == null) {
             return null;
@@ -623,6 +631,7 @@
      *
      * @hide deprecated functionality
      */
+    @UnsupportedAppUsage
     public int getLabelId() {
         return mLabelId;
     }
@@ -647,6 +656,7 @@
      *
      * @hide deprecated functionality
      */
+    @UnsupportedAppUsage
     public int getIconId() {
         return mIconId;
     }
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index ea0fd75..67acfe9 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -658,6 +659,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public final void setForeground(boolean isForeground) {
         Log.w(TAG, "setForeground: ignoring old API call on " + getClass().getName());
     }
@@ -750,6 +752,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public final void attach(
             Context context,
             ActivityThread thread, String className, IBinder token,
@@ -777,10 +780,16 @@
     }
 
     // set by the thread after the constructor and before onCreate(Bundle icicle) is called.
+    @UnsupportedAppUsage
     private ActivityThread mThread = null;
+    @UnsupportedAppUsage
     private String mClassName = null;
+    @UnsupportedAppUsage
     private IBinder mToken = null;
+    @UnsupportedAppUsage
     private Application mApplication = null;
+    @UnsupportedAppUsage
     private IActivityManager mActivityManager = null;
+    @UnsupportedAppUsage
     private boolean mStartCompatibility = false;
 }
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 6ac15a5..0f8976f 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.SharedPreferences;
 import android.os.FileUtils;
 import android.os.Looper;
@@ -63,6 +64,7 @@
     //  - acquire SharedPreferencesImpl.mLock before EditorImpl.mLock
     //  - acquire mWritingToDiskLock before EditorImpl.mLock
 
+    @UnsupportedAppUsage
     private final File mFile;
     private final File mBackupFile;
     private final int mMode;
@@ -103,6 +105,7 @@
     private final ExponentiallyBucketedHistogram mSyncTimes = new ExponentiallyBucketedHistogram(16);
     private int mNumSync = 0;
 
+    @UnsupportedAppUsage
     SharedPreferencesImpl(File file, int mode) {
         mFile = file;
         mBackupFile = makeBackupFile(file);
@@ -113,6 +116,7 @@
         startLoadFromDisk();
     }
 
+    @UnsupportedAppUsage
     private void startLoadFromDisk() {
         synchronized (mLock) {
             mLoaded = false;
@@ -195,6 +199,7 @@
         return new File(prefsFile.getPath() + ".bak");
     }
 
+    @UnsupportedAppUsage
     void startReloadIfChangedUnexpectedly() {
         synchronized (mLock) {
             // TODO: wait for any pending writes to disk?
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index c8a8313..2718bfa 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
@@ -39,11 +40,13 @@
 @SystemService(Context.STATUS_BAR_SERVICE)
 public class StatusBarManager {
 
+    @UnsupportedAppUsage
     public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND;
     public static final int DISABLE_NOTIFICATION_ICONS = View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS;
     public static final int DISABLE_NOTIFICATION_ALERTS
             = View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS;
     @Deprecated
+    @UnsupportedAppUsage
     public static final int DISABLE_NOTIFICATION_TICKER
             = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER;
     public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO;
@@ -57,6 +60,7 @@
     public static final int DISABLE_NAVIGATION = 
             View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_RECENT;
 
+    @UnsupportedAppUsage
     public static final int DISABLE_NONE = 0x00000000;
 
     public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS
@@ -107,14 +111,18 @@
     public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1;
     public static final int CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = 2;
 
+    @UnsupportedAppUsage
     private Context mContext;
     private IStatusBarService mService;
+    @UnsupportedAppUsage
     private IBinder mToken = new Binder();
 
+    @UnsupportedAppUsage
     StatusBarManager(Context context) {
         mContext = context;
     }
 
+    @UnsupportedAppUsage
     private synchronized IStatusBarService getService() {
         if (mService == null) {
             mService = IStatusBarService.Stub.asInterface(
@@ -130,6 +138,7 @@
      * Disable some features in the status bar.  Pass the bitwise-or of the DISABLE_* flags.
      * To re-enable everything, pass {@link #DISABLE_NONE}.
      */
+    @UnsupportedAppUsage
     public void disable(int what) {
         try {
             final int userId = Binder.getCallingUserHandle().getIdentifier();
@@ -163,6 +172,7 @@
     /**
      * Expand the notifications panel.
      */
+    @UnsupportedAppUsage
     public void expandNotificationsPanel() {
         try {
             final IStatusBarService svc = getService();
@@ -177,6 +187,7 @@
     /**
      * Collapse the notifications and settings panels.
      */
+    @UnsupportedAppUsage
     public void collapsePanels() {
         try {
             final IStatusBarService svc = getService();
@@ -191,6 +202,7 @@
     /**
      * Expand the settings panel.
      */
+    @UnsupportedAppUsage
     public void expandSettingsPanel() {
         expandSettingsPanel(null);
     }
@@ -198,6 +210,7 @@
     /**
      * Expand the settings panel and open a subPanel, pass null to just open the settings panel.
      */
+    @UnsupportedAppUsage
     public void expandSettingsPanel(String subPanel) {
         try {
             final IStatusBarService svc = getService();
@@ -209,6 +222,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) {
         try {
             final IStatusBarService svc = getService();
@@ -221,6 +235,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void removeIcon(String slot) {
         try {
             final IStatusBarService svc = getService();
@@ -232,6 +247,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void setIconVisibility(String slot, boolean visible) {
         try {
             final IStatusBarService svc = getService();
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index b432baa..003f364 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -226,6 +226,14 @@
                         ctx.getOuterContext(), ctx.mMainThread.getHandler());
             }});
 
+        registerService(Context.URI_GRANTS_SERVICE, UriGrantsManager.class,
+                new CachedServiceFetcher<UriGrantsManager>() {
+            @Override
+            public UriGrantsManager createService(ContextImpl ctx) {
+                return new UriGrantsManager(
+                        ctx.getOuterContext(), ctx.mMainThread.getHandler());
+            }});
+
         registerService(Context.ALARM_SERVICE, AlarmManager.class,
                 new CachedServiceFetcher<AlarmManager>() {
             @Override
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
new file mode 100644
index 0000000..78ec8a1
--- /dev/null
+++ b/core/java/android/app/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "imports": [
+    {
+      "path": "frameworks/base/services/core/java/com/android/server/am"
+    },
+    {
+      "path": "frameworks/base/services/core/java/com/android/server/wm"
+    }
+  ]
+}
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
new file mode 100644
index 0000000..077b177
--- /dev/null
+++ b/core/java/android/app/TaskInfo.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Stores information about a particular Task.
+ */
+public class TaskInfo {
+    private static final String TAG = "TaskInfo";
+
+    /**
+     * The id of the user the task was running as.
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public int userId;
+
+    /**
+     * The id of the ActivityStack that currently contains this task.
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public int stackId;
+
+    /**
+     * The identifier for this task.
+     */
+    public int taskId;
+
+    /**
+     * Whether or not this task has any running activities.
+     */
+    public boolean isRunning;
+
+    /**
+     * The base intent of the task (generally the intent that launched the task). This intent can
+     * be used to relaunch the task (if it is no longer running) or brought to the front if it is.
+     */
+    public Intent baseIntent;
+
+    /**
+     * The component of the first activity in the task, can be considered the "application" of this
+     * task.
+     */
+    public ComponentName baseActivity;
+
+    /**
+     * The component of the top activity in the task, currently showing to the user.
+     */
+    public ComponentName topActivity;
+
+    /**
+     * The component of the target activity if this task was started from an activity alias.
+     * Otherwise, this is null.
+     */
+    public ComponentName origActivity;
+
+    /**
+     * The component of the activity that started this task (may be the component of the activity
+     * alias).
+     * @hide
+     */
+    public ComponentName realActivity;
+
+    /**
+     * The number of activities in this task (including running).
+     */
+    public int numActivities;
+
+    /**
+     * The last time this task was active since boot (including time spent in sleep).
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public long lastActiveTime;
+
+    /**
+     * The recent activity values for the highest activity in the stack to have set the values.
+     * {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.
+     */
+    public ActivityManager.TaskDescription taskDescription;
+
+    /**
+     * True if the task can go in the split-screen primary stack.
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public boolean supportsSplitScreenMultiWindow;
+
+    /**
+     * The resize mode of the task. See {@link ActivityInfo#resizeMode}.
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public int resizeMode;
+
+    /**
+     * The current configuration of the task.
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public final Configuration configuration = new Configuration();
+
+    TaskInfo() {
+        // Do nothing
+    }
+
+    private TaskInfo(Parcel source) {
+        readFromParcel(source);
+    }
+
+    /**
+     * @param reducedResolution
+     * @return
+     * @hide
+     */
+    public ActivityManager.TaskSnapshot getTaskSnapshot(boolean reducedResolution) {
+        try {
+            return ActivityManager.getService().getTaskSnapshot(taskId, reducedResolution);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get task snapshot, taskId=" + taskId, e);
+            return null;
+        }
+    }
+
+    /**
+     * Reads the TaskInfo from a parcel.
+     */
+    void readFromParcel(Parcel source) {
+        userId = source.readInt();
+        stackId = source.readInt();
+        taskId = source.readInt();
+        isRunning = source.readBoolean();
+        baseIntent = source.readInt() != 0
+                ? Intent.CREATOR.createFromParcel(source)
+                : null;
+        baseActivity = ComponentName.readFromParcel(source);
+        topActivity = ComponentName.readFromParcel(source);
+        origActivity = ComponentName.readFromParcel(source);
+        realActivity = ComponentName.readFromParcel(source);
+
+        numActivities = source.readInt();
+        lastActiveTime = source.readLong();
+
+        taskDescription = source.readInt() != 0
+                ? ActivityManager.TaskDescription.CREATOR.createFromParcel(source)
+                : null;
+        supportsSplitScreenMultiWindow = source.readBoolean();
+        resizeMode = source.readInt();
+        configuration.readFromParcel(source);
+    }
+
+    /**
+     * Writes the TaskInfo to a parcel.
+     */
+    void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(userId);
+        dest.writeInt(stackId);
+        dest.writeInt(taskId);
+        dest.writeBoolean(isRunning);
+
+        if (baseIntent != null) {
+            dest.writeInt(1);
+            baseIntent.writeToParcel(dest, 0);
+        } else {
+            dest.writeInt(0);
+        }
+        ComponentName.writeToParcel(baseActivity, dest);
+        ComponentName.writeToParcel(topActivity, dest);
+        ComponentName.writeToParcel(origActivity, dest);
+        ComponentName.writeToParcel(realActivity, dest);
+
+        dest.writeInt(numActivities);
+        dest.writeLong(lastActiveTime);
+
+        if (taskDescription != null) {
+            dest.writeInt(1);
+            taskDescription.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+        dest.writeBoolean(supportsSplitScreenMultiWindow);
+        dest.writeInt(resizeMode);
+        configuration.writeToParcel(dest, flags);
+    }
+
+    @Override
+    public String toString() {
+        return "TaskInfo{userId=" + userId + " stackId=" + stackId + " taskId=" + taskId
+                + " isRunning=" + isRunning
+                + " baseIntent=" + baseIntent + " baseActivity=" + baseActivity
+                + " topActivity=" + topActivity + " origActivity=" + origActivity
+                + " realActivity=" + realActivity
+                + " numActivities=" + numActivities
+                + " lastActiveTime=" + lastActiveTime
+                + " supportsSplitScreenMultiWindow=" + supportsSplitScreenMultiWindow
+                + " resizeMode=" + resizeMode;
+    }
+}
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 895d12a..e23352a 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager.TaskSnapshot;
 import android.content.ComponentName;
 import android.os.RemoteException;
@@ -27,40 +28,49 @@
  */
 public abstract class TaskStackListener extends ITaskStackListener.Stub {
     @Override
+    @UnsupportedAppUsage
     public void onTaskStackChanged() throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onActivityPinned(String packageName, int userId, int taskId, int stackId)
             throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onActivityUnpinned() throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onPinnedActivityRestartAttempt(boolean clearedTask) throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onPinnedStackAnimationStarted() throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onPinnedStackAnimationEnded() throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onActivityForcedResizable(String packageName, int taskId, int reason)
             throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onActivityDismissingDockedStack() throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
     }
 
@@ -69,10 +79,12 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onTaskRemoved(int taskId) throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onTaskMovedToFront(int taskId) throws RemoteException {
     }
 
@@ -86,15 +98,18 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation)
             throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onTaskProfileLocked(int taskId, int userId) throws RemoteException {
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) throws RemoteException {
     }
 }
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index 8686944..1b281d5 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
@@ -43,6 +44,7 @@
     private static final String MINUTE = "minute";
     private static final String IS_24_HOUR = "is24hour";
 
+    @UnsupportedAppUsage
     private final TimePicker mTimePicker;
     private final OnTimeSetListener mTimeSetListener;
 
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 5662aea..dbb6c3d 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -23,6 +23,7 @@
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -33,6 +34,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -50,6 +52,7 @@
 import android.view.accessibility.IAccessibilityInteractionConnection;
 
 import com.android.internal.util.function.pooled.PooledLambda;
+
 import libcore.io.IoUtils;
 
 import java.io.IOException;
@@ -190,6 +193,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public UiAutomation(Looper looper, IUiAutomationConnection connection) {
         if (looper == null) {
             throw new IllegalArgumentException("Looper cannot be null!");
@@ -206,6 +210,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void connect() {
         connect(0);
     }
@@ -277,6 +282,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void disconnect() {
         synchronized (mLock) {
             if (mIsConnecting) {
@@ -347,6 +353,46 @@
     }
 
     /**
+     * Adopt the permission identity of the shell UID. This allows you to call APIs protected
+     * permissions which normal apps cannot hold but are granted to the shell UID. If you
+     * already adopted the shell permission identity this method would be a no-op.
+     * Note that your permission state becomes that of the shell UID and it is not a
+     * combination of your and the shell UID permissions.
+     *
+     * @see #dropShellPermissionIdentity()
+     */
+    public void adoptShellPermissionIdentity() {
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+        }
+        try {
+            // Calling out without a lock held.
+            mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid());
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error executing adopting shell permission identity!", re);
+        }
+    }
+
+    /**
+     * Drop the shell permission identity adopted by a previous call to
+     * {@link #adoptShellPermissionIdentity()}. If you did not adopt the shell permission
+     * identity this method would be a no-op.
+     *
+     * @see #adoptShellPermissionIdentity()
+     */
+    public void dropShellPermissionIdentity() {
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+        }
+        try {
+            // Calling out without a lock held.
+            mUiAutomationConnection.dropShellPermissionIdentity();
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error executing dropping shell permission identity!", re);
+        }
+    }
+
+    /**
      * Performs a global action. Such an action can be performed at any moment
      * regardless of the current application or user location in that application.
      * For example going back, going home, opening recents, etc.
@@ -999,6 +1045,8 @@
      *
      * @param command The command to execute.
      * @return A file descriptor to the standard output stream.
+     *
+     * @see #adoptShellPermissionIdentity()
      */
     public ParcelFileDescriptor executeShellCommand(String command) {
         synchronized (mLock) {
@@ -1081,22 +1129,6 @@
         return result;
     }
 
-    private static float getDegreesForRotation(int value) {
-        switch (value) {
-            case Surface.ROTATION_90: {
-                return 360f - 90f;
-            }
-            case Surface.ROTATION_180: {
-                return 360f - 180f;
-            }
-            case Surface.ROTATION_270: {
-                return 360f - 270f;
-            } default: {
-                return 0;
-            }
-        }
-    }
-
     private boolean isConnectedLocked() {
         return mConnectionId != CONNECTION_ID_UNDEFINED;
     }
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index d3828ab..b406d9e 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -18,6 +18,7 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.IAccessibilityServiceClient;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.IPackageManager;
 import android.graphics.Bitmap;
@@ -30,6 +31,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.util.Log;
 import android.view.IWindowManager;
 import android.view.InputEvent;
 import android.view.SurfaceControl;
@@ -37,7 +39,6 @@
 import android.view.WindowContentFrameStats;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.IAccessibilityManager;
-import android.util.Log;
 
 import libcore.io.IoUtils;
 
@@ -71,6 +72,9 @@
     private final IPackageManager mPackageManager = IPackageManager.Stub
             .asInterface(ServiceManager.getService("package"));
 
+    private final IActivityManager mActivityManager = IActivityManager.Stub
+            .asInterface(ServiceManager.getService("activity"));
+
     private final Object mLock = new Object();
 
     private final Binder mToken = new Binder();
@@ -274,6 +278,36 @@
         }
     }
 
+    @Override
+    public void adoptShellPermissionIdentity(int uid) throws RemoteException {
+        synchronized (mLock) {
+            throwIfCalledByNotTrustedUidLocked();
+            throwIfShutdownLocked();
+            throwIfNotConnectedLocked();
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mActivityManager.startDelegateShellPermissionIdentity(uid);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void dropShellPermissionIdentity() throws RemoteException {
+        synchronized (mLock) {
+            throwIfCalledByNotTrustedUidLocked();
+            throwIfShutdownLocked();
+            throwIfNotConnectedLocked();
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mActivityManager.stopDelegateShellPermissionIdentity();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     public class Repeater implements Runnable {
         // Continuously read readFrom and write back to writeTo until EOF is encountered
         private final InputStream readFrom;
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 0da5e24..4f172a4 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.RemoteException;
@@ -126,6 +127,7 @@
 
     private IUiModeManager mService;
 
+    @UnsupportedAppUsage
     /*package*/ UiModeManager() throws ServiceNotFoundException {
         mService = IUiModeManager.Stub.asInterface(
                 ServiceManager.getServiceOrThrow(Context.UI_MODE_SERVICE));
diff --git a/core/java/android/app/UriGrantsManager.java b/core/java/android/app/UriGrantsManager.java
new file mode 100644
index 0000000..5096f73
--- /dev/null
+++ b/core/java/android/app/UriGrantsManager.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app;
+
+import android.annotation.Nullable;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.content.pm.ParceledListSlice;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Singleton;
+
+/**
+ * Class for managing an app's permission to access a particular {@link android.net.Uri}.
+ *
+ * @hide
+ */
+@SystemService(Context.URI_GRANTS_SERVICE)
+public class UriGrantsManager {
+
+    private final Context mContext;
+
+    UriGrantsManager(Context context, Handler handler) {
+        mContext = context;
+    }
+
+    /** @hide */
+    public static IUriGrantsManager getService() {
+        return IUriGrantsManagerSingleton.get();
+    }
+
+    private static final Singleton<IUriGrantsManager> IUriGrantsManagerSingleton =
+            new Singleton<IUriGrantsManager>() {
+                @Override
+                protected IUriGrantsManager create() {
+                    final IBinder b = ServiceManager.getService(Context.URI_GRANTS_SERVICE);
+                    return IUriGrantsManager.Stub.asInterface(b);
+                }
+            };
+
+    /**
+     * Permits an application to clear the persistent URI permissions granted to another.
+     *
+     * <p>Typically called by Settings, requires {@code CLEAR_APP_GRANTED_URI_PERMISSIONS}.
+     *
+     * @param packageName application to clear its granted permissions
+     *
+     * @hide
+     */
+    public void clearGrantedUriPermissions(String packageName) {
+        try {
+            getService().clearGrantedUriPermissions(packageName, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Permits an application to get the persistent URI permissions granted to another.
+     *
+     * <p>Typically called by Settings or DocumentsUI, requires
+     * {@code GET_APP_GRANTED_URI_PERMISSIONS}.
+     *
+     * @param packageName application to look for the granted permissions, or {@code null} to get
+     * granted permissions for all applications
+     * @return list of granted URI permissions
+     *
+     * @hide
+     */
+    public ParceledListSlice<GrantedUriPermission> getGrantedUriPermissions(
+            @Nullable String packageName) {
+        try {
+            @SuppressWarnings("unchecked")
+            final ParceledListSlice<GrantedUriPermission> castedList = getService()
+                    .getGrantedUriPermissions(packageName, mContext.getUserId());
+            return castedList;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+}
diff --git a/core/java/android/app/UserSwitchObserver.java b/core/java/android/app/UserSwitchObserver.java
index c0f7a4c..25b243d 100644
--- a/core/java/android/app/UserSwitchObserver.java
+++ b/core/java/android/app/UserSwitchObserver.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index e118edd..6248e7c 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -6,6 +6,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.RemoteException;
@@ -50,6 +51,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private final IVrManager mService;
     private Map<VrStateCallback, CallbackEntry> mCallbackMap = new ArrayMap<>();
 
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
index 626b3be..ace814a 100644
--- a/core/java/android/app/WallpaperColors.java
+++ b/core/java/android/app/WallpaperColors.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -233,6 +234,7 @@
      * @see WallpaperColors#fromDrawable(Drawable)
      * @hide
      */
+    @UnsupportedAppUsage
     public WallpaperColors(@NonNull Color primaryColor, @Nullable Color secondaryColor,
             @Nullable Color tertiaryColor, int colorHints) {
 
@@ -347,6 +349,7 @@
      * @return True if dark text is supported.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getColorHints() {
         return mColorHints;
     }
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index 35a1789..9873a81 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -315,12 +315,13 @@
     }
 
     /**
-     * Returns whether a wallpaper was optimized or not for ambient mode.
+     * Returns whether a wallpaper was optimized or not for ambient mode and can be drawn in there.
      *
-     * @return {@code true} if wallpaper can draw in ambient mode.
-     * @hide
+     * @see WallpaperService.Engine#onAmbientModeChanged(boolean, boolean)
+     * @see WallpaperService.Engine#isInAmbientMode()
+     * @return {@code true} if wallpaper can draw when in ambient mode.
      */
-    public boolean getSupportsAmbientMode() {
+    public boolean supportsAmbientMode() {
         return mSupportsAmbientMode;
     }
 
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 6ad6c25..2a263d6 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -493,6 +494,7 @@
     }
 
     private static final Object sSync = new Object[0];
+    @UnsupportedAppUsage
     private static Globals sGlobals;
 
     static void initGlobals(IWallpaperManager service, Looper looper) {
@@ -517,6 +519,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public IWallpaperManager getIWallpaperManager() {
         return sGlobals.mService;
     }
@@ -820,6 +823,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap getBitmap() {
         return getBitmap(false);
     }
@@ -831,6 +835,7 @@
      * @see Bitmap.Config#HARDWARE
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap getBitmap(boolean hardware) {
         return getBitmapAsUser(mContext.getUserId(), hardware);
     }
@@ -886,6 +891,7 @@
      * @param userId Owner of the wallpaper or UserHandle.USER_ALL.
      * @hide
      */
+    @UnsupportedAppUsage
     public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,
             @NonNull Handler handler, int userId) {
         sGlobals.addOnColorsChangedListener(listener, handler, userId);
@@ -939,6 +945,7 @@
      * @return {@link WallpaperColors} or null if colors are unknown.
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable WallpaperColors getWallpaperColors(int which, int userId) {
         return sGlobals.getWallpaperColors(which, userId);
     }
@@ -958,6 +965,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public ParcelFileDescriptor getWallpaperFile(@SetWallpaperFlags int which, int userId) {
         if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
             throw new IllegalArgumentException("Must request exactly one kind of wallpaper");
@@ -1280,6 +1288,7 @@
      * requires permission {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
      * @hide
      */
+    @UnsupportedAppUsage
     public int setBitmap(Bitmap fullImage, Rect visibleCropHint,
             boolean allowBackup, @SetWallpaperFlags int which, int userId)
             throws IOException {
@@ -1670,6 +1679,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
+    @UnsupportedAppUsage
     public boolean setWallpaperComponent(ComponentName name, int userId) {
         if (sGlobals.mService == null) {
             Log.w(TAG, "WallpaperService not running");
@@ -1847,6 +1857,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static InputStream openDefaultWallpaper(Context context, @SetWallpaperFlags int which) {
         final String whichProp;
         final int defaultResId;
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index aea767e..e6fb5dc 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -575,7 +575,8 @@
      * @hide
      */
     public boolean isAlwaysOnTop() {
-        return mWindowingMode == WINDOWING_MODE_PINNED || mAlwaysOnTop == ALWAYS_ON_TOP_ON;
+        return mWindowingMode == WINDOWING_MODE_PINNED
+                || (mWindowingMode == WINDOWING_MODE_FREEFORM && mAlwaysOnTop == ALWAYS_ON_TOP_ON);
     }
 
     /**
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 5fbe5b3..5fe1af0 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -17,6 +17,7 @@
 package android.app.admin;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -180,6 +181,7 @@
     /** @hide */
     public static class PolicyInfo {
         public final int ident;
+        @UnsupportedAppUsage
         public final String tag;
         public final int label;
         public final int description;
@@ -479,6 +481,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public ArrayList<PolicyInfo> getUsedPolicies() {
         ArrayList<PolicyInfo> res = new ArrayList<PolicyInfo>();
         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 5e7f1e4..aa021a2 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -30,6 +30,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
 import android.app.Activity;
@@ -72,6 +73,7 @@
 import android.security.keystore.KeyAttestationException;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.ParcelableKeyGenParameterSpec;
+import android.security.keystore.StrongBoxUnavailableException;
 import android.service.restrictions.RestrictionsReceiver;
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
@@ -1136,6 +1138,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
             = "android.app.action.DEVICE_POLICY_MANAGER_STATE_CHANGED";
 
@@ -1774,6 +1777,13 @@
     public static final int ID_TYPE_MEID = 8;
 
     /**
+     * Service-specific error code for {@link #generateKeyPair}:
+     * Indicates the call has failed due to StrongBox unavailability.
+     * @hide
+     */
+    public static final int KEY_GEN_STRONGBOX_UNAVAILABLE = 1;
+
+    /**
      * Specifies that the calling app should be granted access to the installed credentials
      * immediately. Otherwise, access to the credentials will be gated by user approval.
      * For use with {@link #installKeyPair(ComponentName, PrivateKey, Certificate[], String, int)}
@@ -1859,6 +1869,7 @@
      * @see #getActiveAdmins()
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable List<ComponentName> getActiveAdminsAsUser(int userId) {
         if (mService != null) {
             try {
@@ -1886,6 +1897,7 @@
      * or uninstalled.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean packageHasActiveAdmins(String packageName, int userId) {
         if (mService != null) {
             try {
@@ -2121,6 +2133,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getPasswordQuality(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -2186,6 +2199,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getPasswordMinimumLength(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -2255,6 +2269,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getPasswordMinimumUpperCase(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -2324,6 +2339,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getPasswordMinimumLowerCase(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -2392,6 +2408,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getPasswordMinimumLetters(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -2460,6 +2477,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getPasswordMinimumNumeric(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -2527,6 +2545,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getPasswordMinimumSymbols(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -2595,6 +2614,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getPasswordMinimumNonLetter(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -2746,6 +2766,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getPasswordHistoryLength(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -2872,6 +2893,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCurrentFailedPasswordAttempts(int userHandle) {
         if (mService != null) {
             try {
@@ -2952,6 +2974,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -3224,6 +3247,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public long getMaximumTimeToLock(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -3297,6 +3321,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public long getRequiredStrongAuthTimeout(@Nullable ComponentName admin, @UserIdInt int userId) {
         if (mService != null) {
             try {
@@ -3485,6 +3510,7 @@
      *            of the device admin that sets the proxy.
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable ComponentName setGlobalProxy(@NonNull ComponentName admin, Proxy proxySpec,
             List<String> exclusionList ) {
         throwIfParentInstance("setGlobalProxy");
@@ -3819,6 +3845,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getStorageEncryptionStatus(int userHandle) {
         if (mService != null) {
             try {
@@ -4153,8 +4180,11 @@
      * Called by a device or profile owner, or delegated certificate installer, to generate a
      * new private/public key pair. If the device supports key generation via secure hardware,
      * this method is useful for creating a key in KeyChain that never left the secure hardware.
-     *
      * Access to the key is controlled the same way as in {@link #installKeyPair}.
+     *
+     * <p>Because this method might take several seconds to complete, it should only be called from
+     * a worker thread. This method returns {@code null} when called from the main thread.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
      *            {@code null} if calling from a delegated certificate installer.
      * @param algorithm The key generation algorithm, see {@link java.security.KeyPairGenerator}.
@@ -4187,6 +4217,8 @@
      *         {@code keySpec} does not contain an attestation challenge.
      * @throws UnsupportedOperationException if Device ID attestation was requested but the
      *         underlying hardware does not support it.
+     * @throws StrongBoxUnavailableException if the use of StrongBox for key generation was
+     *         specified in {@code keySpec} but the device does not have one.
      * @see KeyGenParameterSpec.Builder#setAttestationChallenge(byte[])
      */
     public AttestedKeyPair generateKeyPair(@Nullable ComponentName admin,
@@ -4227,6 +4259,15 @@
         } catch (InterruptedException e) {
             Log.w(TAG, "Interrupted while generating key", e);
             Thread.currentThread().interrupt();
+        } catch (ServiceSpecificException e) {
+            Log.w(TAG, String.format("Key Generation failure: %d", e.errorCode));
+            switch (e.errorCode) {
+                case KEY_GEN_STRONGBOX_UNAVAILABLE:
+                    throw new StrongBoxUnavailableException("No StrongBox for key generation.");
+                default:
+                    throw new RuntimeException(
+                            String.format("Unknown error while generating key: %d", e.errorCode));
+            }
         }
         return null;
     }
@@ -4542,6 +4583,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public boolean getCameraDisabled(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -4797,6 +4839,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public int getKeyguardDisabledFeatures(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
@@ -4811,6 +4854,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing,
             int userHandle) {
         if (mService != null) {
@@ -4825,6 +4869,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing) {
         setActiveAdmin(policyReceiver, refreshing, myUserId());
     }
@@ -4845,6 +4890,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setActivePasswordState(PasswordMetrics metrics, int userHandle) {
         if (mService != null) {
             try {
@@ -4871,6 +4917,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void reportFailedPasswordAttempt(int userHandle) {
         if (mService != null) {
             try {
@@ -4884,6 +4931,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void reportSuccessfulPasswordAttempt(int userHandle) {
         if (mService != null) {
             try {
@@ -5512,6 +5560,7 @@
      * @see #getProfileOwner()
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable ComponentName getProfileOwnerAsUser(final int userId)
             throws IllegalArgumentException {
         if (mService != null) {
@@ -5630,6 +5679,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDefaultSmsApplication(@NonNull ComponentName admin, String packageName) {
         throwIfParentInstance("setDefaultSmsApplication");
         if (mService != null) {
@@ -5845,6 +5895,7 @@
     }
 
     /** @hide per-user version */
+    @UnsupportedAppUsage
     public @Nullable List<PersistableBundle> getTrustAgentConfiguration(
             @Nullable ComponentName admin, @NonNull ComponentName agent, int userHandle) {
         if (mService != null) {
@@ -7700,6 +7751,9 @@
      * LockTask mode will be registered, but will only take effect when the device leaves LockTask
      * mode.
      *
+     * <p>This policy does not have any effect while on the lock screen, where the status bar will
+     * not be disabled. Using LockTask instead of this method is recommended.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param disabled {@code true} disables the status bar, {@code false} reenables it.
      * @return {@code false} if attempting to disable the status bar failed. {@code true} otherwise.
@@ -8811,6 +8865,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void throwIfParentInstance(String functionName) {
         if (mParentInstance) {
             throw new SecurityException(functionName + " cannot be called on the parent instance");
@@ -8893,6 +8948,7 @@
      *         mandatory or {@code null} if backups are not mandatory.
      * @hide
      */
+    @UnsupportedAppUsage
     public ComponentName getMandatoryBackupTransport() {
         throwIfParentInstance("getMandatoryBackupTransport");
         try {
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 38b4f8f..170c802 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -476,6 +477,7 @@
          * Constructor used by native classes to generate SecurityEvent instances.
          * @hide
          */
+        @UnsupportedAppUsage
         /* package */ SecurityEvent(byte[] data) {
             this(0, data);
         }
diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index 2a451ff..bcd5f6c 100644
--- a/core/java/android/app/admin/SystemUpdatePolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -76,9 +76,7 @@
  * </code></pre>
  *
  * <h3>Developer guide</h3>
- * To learn more about managing system updates, read
- * <a href="{@docRoot}/work/dpc/security.html#control_remote_software_updates">Control remote
- * software updates</a>.
+ * To learn more, read <a href="{@docRoot}work/dpc/system-updates">Manage system updates</a>.
  *
  * @see DevicePolicyManager#setSystemUpdatePolicy
  * @see DevicePolicyManager#getSystemUpdatePolicy
diff --git a/core/java/android/app/assist/AssistContent.java b/core/java/android/app/assist/AssistContent.java
index 1c9f573..bdbce52 100644
--- a/core/java/android/app/assist/AssistContent.java
+++ b/core/java/android/app/assist/AssistContent.java
@@ -1,5 +1,6 @@
 package android.app.assist;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ClipData;
 import android.content.Intent;
 import android.net.Uri;
@@ -13,12 +14,18 @@
  * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}.
  */
 public class AssistContent implements Parcelable {
+    @UnsupportedAppUsage
     private boolean mIsAppProvidedIntent = false;
     private boolean mIsAppProvidedWebUri = false;
+    @UnsupportedAppUsage
     private Intent mIntent;
+    @UnsupportedAppUsage
     private String mStructuredData;
+    @UnsupportedAppUsage
     private ClipData mClipData;
+    @UnsupportedAppUsage
     private Uri mUri;
+    @UnsupportedAppUsage
     private final Bundle mExtras;
 
     public AssistContent() {
@@ -148,6 +155,7 @@
         return mExtras;
     }
 
+    @UnsupportedAppUsage
     AssistContent(Parcel in) {
         if (in.readInt() != 0) {
             mIntent = Intent.CREATOR.createFromParcel(in);
@@ -166,6 +174,7 @@
         mIsAppProvidedWebUri = in.readInt() == 1;
     }
 
+    @UnsupportedAppUsage
     void writeToParcelInternal(Parcel dest, int flags) {
         if (mIntent != null) {
             dest.writeInt(1);
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index ef41b10..173b766 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -41,18 +41,23 @@
 import java.util.List;
 
 /**
- * Assist data automatically created by the platform's implementation of assist and autofill.
+ * <p>This API automatically creates assist data from the platform's
+ * implementation of assist and autofill.
  *
  * <p>The structure is used for assist purposes when created by
  * {@link android.app.Activity#onProvideAssistData}, {@link View#onProvideStructure(ViewStructure)},
  * or {@link View#onProvideVirtualStructure(ViewStructure)}.
  *
- * <p>The structure is used for autofill purposes when created by
+ * <p>The structure is also used for autofill purposes when created by
  * {@link View#onProvideAutofillStructure(ViewStructure, int)},
  * or {@link View#onProvideAutofillVirtualStructure(ViewStructure, int)}.
  *
- * <p>For performance reasons, some properties of the assist data might be available just for assist
- * or autofill purposes; in those case, the property availability will be document in its javadoc.
+ * <p>For performance reasons, some properties of the assist data might only be available for
+ * assist or autofill purposes. In those cases, a property's availability will be documented
+ * in its javadoc.
+ *
+ * <p>To learn about using Autofill in your app, read the
+ * <a href="/guide/topics/text/autofill">Autofill Framework</a> guides.
  */
 public class AssistStructure implements Parcelable {
     static final String TAG = "AssistStructure";
@@ -620,7 +625,7 @@
         String mIdType;
         String mIdEntry;
 
-        // TODO: once we have more flags, it might be better to store the individual
+        // TODO(b/37567426): once we have more flags, it might be better to store the individual
         // fields (viewId and childId) of the field.
         AutofillId mAutofillId;
         @View.AutofillType int mAutofillType = View.AUTOFILL_TYPE_NONE;
@@ -664,7 +669,7 @@
         static final int FLAGS_CONTEXT_CLICKABLE = 0x00004000;
         static final int FLAGS_OPAQUE = 0x00008000;
 
-        // TODO: autofill data is made of many fields and ideally we should verify
+        // TODO(b/37567426): autofill data is made of many fields and ideally we should verify
         // one-by-one to optimize what's sent over, but there isn't enough flag bits for that, we'd
         // need to create a 'flags2' or 'autoFillFlags' field and add these flags there.
         // So, to keep thinkg simpler for now, let's just use on flag for all of them...
@@ -2167,13 +2172,13 @@
         if (autofillId == null) {
             Log.i(TAG, prefix + " NO autofill ID");
         } else {
-            Log.i(TAG, prefix + "Autofill info: id= " + autofillId
+            Log.i(TAG, prefix + "  Autofill info: id= " + autofillId
                     + ", type=" + node.getAutofillType()
                     + ", options=" + Arrays.toString(node.getAutofillOptions())
                     + ", hints=" + Arrays.toString(node.getAutofillHints())
                     + ", value=" + node.getAutofillValue()
                     + ", sanitized=" + node.isSanitized()
-                    + ", importantFor=" + node.getImportantForAutofill());
+                    + ", important=" + node.getImportantForAutofill());
         }
 
         final int NCHILDREN = node.getChildCount();
@@ -2237,6 +2242,22 @@
         return mWindowNodes.get(index);
     }
 
+    // TODO(b/35708678): temporary method that disable one-way warning flag on binder.
+    /** @hide */
+    public void ensureDataForAutofill() {
+        if (mHaveData) {
+            return;
+        }
+        mHaveData = true;
+        Binder.allowBlocking(mReceiveChannel);
+        try {
+            ParcelTransferReader reader = new ParcelTransferReader(mReceiveChannel);
+            reader.go();
+        } finally {
+            Binder.defaultBlocking(mReceiveChannel);
+        }
+    }
+
     /** @hide */
     public void ensureData() {
         if (mHaveData) {
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index ec2cf0c..097dd9c 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -941,11 +941,13 @@
         private static final String TAG = "BackupServiceBinder";
 
         @Override
-        public void doBackup(ParcelFileDescriptor oldState,
+        public void doBackup(
+                ParcelFileDescriptor oldState,
                 ParcelFileDescriptor data,
                 ParcelFileDescriptor newState,
-                long quotaBytes, int token, IBackupManager callbackBinder, int transportFlags)
-                throws RemoteException {
+                long quotaBytes,
+                IBackupCallback callbackBinder,
+                int transportFlags) throws RemoteException {
             // Ensure that we're running with the app's normal permission level
             long ident = Binder.clearCallingIdentity();
 
@@ -969,7 +971,7 @@
 
                 Binder.restoreCallingIdentity(ident);
                 try {
-                    callbackBinder.opComplete(token, 0);
+                    callbackBinder.operationComplete(0);
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
diff --git a/core/java/android/app/backup/BackupDataInput.java b/core/java/android/app/backup/BackupDataInput.java
index 26f9e3e..2a98ca7 100644
--- a/core/java/android/app/backup/BackupDataInput.java
+++ b/core/java/android/app/backup/BackupDataInput.java
@@ -17,6 +17,7 @@
 package android.app.backup;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -67,7 +68,9 @@
     private boolean mHeaderReady;
 
     private static class EntityHeader {
+        @UnsupportedAppUsage
         String key;
+        @UnsupportedAppUsage
         int dataSize;
     }
 
diff --git a/core/java/android/app/backup/BackupDataInputStream.java b/core/java/android/app/backup/BackupDataInputStream.java
index 94c7845..0888066 100644
--- a/core/java/android/app/backup/BackupDataInputStream.java
+++ b/core/java/android/app/backup/BackupDataInputStream.java
@@ -16,6 +16,7 @@
 
 package android.app.backup;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.InputStream;
 import java.io.IOException;
 
@@ -37,7 +38,9 @@
  */
 public class BackupDataInputStream extends InputStream {
 
+    @UnsupportedAppUsage
     String key;
+    @UnsupportedAppUsage
     int dataSize;
 
     BackupDataInput mData;
diff --git a/core/java/android/app/backup/BackupDataOutput.java b/core/java/android/app/backup/BackupDataOutput.java
index 5a66f34..01961e7 100644
--- a/core/java/android/app/backup/BackupDataOutput.java
+++ b/core/java/android/app/backup/BackupDataOutput.java
@@ -17,6 +17,7 @@
 package android.app.backup;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.ParcelFileDescriptor;
 
 import java.io.FileDescriptor;
@@ -67,6 +68,7 @@
     private final long mQuota;
     private final int mTransportFlags;
 
+    @UnsupportedAppUsage
     long mBackupWriter;
 
     /**
diff --git a/core/java/android/app/backup/BackupHelperDispatcher.java b/core/java/android/app/backup/BackupHelperDispatcher.java
index 6811532..e9acdbf 100644
--- a/core/java/android/app/backup/BackupHelperDispatcher.java
+++ b/core/java/android/app/backup/BackupHelperDispatcher.java
@@ -16,6 +16,7 @@
 
 package android.app.backup;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
@@ -29,7 +30,9 @@
     private static final String TAG = "BackupHelperDispatcher";
 
     private static class Header {
+        @UnsupportedAppUsage
         int chunkSize; // not including the header
+        @UnsupportedAppUsage
         String keyPrefix;
     }
 
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 912baf9..c6086f1 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -20,6 +20,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -192,8 +193,10 @@
     public static final int ERROR_TRANSPORT_INVALID = -2;
 
     private Context mContext;
+    @UnsupportedAppUsage
     private static IBackupManager sService;
 
+    @UnsupportedAppUsage
     private static void checkServiceBinder() {
         if (sService == null) {
             sService = IBackupManager.Stub.asInterface(
diff --git a/core/java/android/app/backup/FileBackupHelperBase.java b/core/java/android/app/backup/FileBackupHelperBase.java
index 4ed5197..0caab98 100644
--- a/core/java/android/app/backup/FileBackupHelperBase.java
+++ b/core/java/android/app/backup/FileBackupHelperBase.java
@@ -16,6 +16,7 @@
 
 package android.app.backup;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
@@ -101,6 +102,7 @@
         return (result == 0);
     }
 
+    @UnsupportedAppUsage
     public void writeNewStateDescription(ParcelFileDescriptor fd) {
         int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
         // TODO: Do something with the error.
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index b7a8da5..9a595b2 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -16,6 +16,7 @@
 
 package android.app.backup;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.XmlResourceParser;
@@ -90,6 +91,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     static public native int backupToTar(String packageName, String domain,
             String linkdomain, String rootpath, String path, FullBackupDataOutput output);
 
diff --git a/core/java/android/app/backup/FullBackupDataOutput.java b/core/java/android/app/backup/FullBackupDataOutput.java
index 18f4283..0ce8653 100644
--- a/core/java/android/app/backup/FullBackupDataOutput.java
+++ b/core/java/android/app/backup/FullBackupDataOutput.java
@@ -1,5 +1,6 @@
 package android.app.backup;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.ParcelFileDescriptor;
 
 /**
@@ -9,6 +10,7 @@
  */
 public class FullBackupDataOutput {
     // Currently a name-scoping shim around BackupDataOutput
+    @UnsupportedAppUsage
     private final BackupDataOutput mData;
     private final long mQuota;
     private final int mTransportFlags;
@@ -65,14 +67,17 @@
     }
 
     /** @hide - used only internally to the backup manager service's stream construction */
+    @UnsupportedAppUsage
     public FullBackupDataOutput(ParcelFileDescriptor fd) {
         this(fd, /*quota=*/ -1, /*transportFlags=*/ 0);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public BackupDataOutput getData() { return mData; }
 
     /** @hide - used for measurement pass */
+    @UnsupportedAppUsage
     public void addSize(long size) {
         if (size > 0) {
             mSize += size;
diff --git a/core/java/android/app/backup/IBackupCallback.aidl b/core/java/android/app/backup/IBackupCallback.aidl
new file mode 100644
index 0000000..9582a58
--- /dev/null
+++ b/core/java/android/app/backup/IBackupCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.backup;
+
+import android.app.backup.IBackupManager;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Callback interface made for responding to one-way calls from the system.
+ *
+ * @hide
+ */
+oneway interface IBackupCallback {
+    void operationComplete(long result);
+}
diff --git a/core/java/android/app/backup/SharedPreferencesBackupHelper.java b/core/java/android/app/backup/SharedPreferencesBackupHelper.java
index 939616b..302a8ef 100644
--- a/core/java/android/app/backup/SharedPreferencesBackupHelper.java
+++ b/core/java/android/app/backup/SharedPreferencesBackupHelper.java
@@ -51,8 +51,8 @@
  *     // identify the SharedPreferenceBackupHelper's data.
  *     static final String MY_PREFS_BACKUP_KEY = "myprefs";
  *
- *     // Simply allocate a helper and install it
- *     void onCreate() {
+ *     // Allocate a helper and install it.
+ *     public void onCreate() {
  *         SharedPreferencesBackupHelper helper =
  *                 new SharedPreferencesBackupHelper(this, PREFS_DISPLAY, PREFS_SCORES);
  *         addHelper(MY_PREFS_BACKUP_KEY, helper);
@@ -117,7 +117,7 @@
      */
     public void restoreEntity(BackupDataInputStream data) {
         Context context = mContext;
-        
+
         String key = data.getKey();
         if (DEBUG) Log.d(TAG, "got entity '" + key + "' size=" + data.size());
 
diff --git a/core/java/android/app/job/IJobScheduler.aidl b/core/java/android/app/job/IJobScheduler.aidl
index e94da0c..53b33c2 100644
--- a/core/java/android/app/job/IJobScheduler.aidl
+++ b/core/java/android/app/job/IJobScheduler.aidl
@@ -17,6 +17,7 @@
 package android.app.job;
 
 import android.app.job.JobInfo;
+import android.app.job.JobSnapshot;
 import android.app.job.JobWorkItem;
 
  /**
@@ -31,4 +32,6 @@
     void cancelAll();
     List<JobInfo> getAllPendingJobs();
     JobInfo getPendingJob(int jobId);
+    List<JobInfo> getStartedJobs();
+    List<JobSnapshot> getAllJobSnapshots();
 }
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 02afcc7..9baa16f 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -29,6 +29,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ClipData;
 import android.content.ComponentName;
 import android.net.NetworkRequest;
@@ -202,6 +203,7 @@
      * JobInfo priority if it is smaller).
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int PRIORITY_FOREGROUND_APP = 30;
 
     /**
@@ -240,6 +242,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int FLAG_WILL_BE_FOREGROUND = 1 << 0;
 
     /**
@@ -282,11 +285,13 @@
      */
     public static final int CONSTRAINT_FLAG_STORAGE_NOT_LOW = 1 << 3;
 
+    @UnsupportedAppUsage
     private final int jobId;
     private final PersistableBundle extras;
     private final Bundle transientExtras;
     private final ClipData clipData;
     private final int clipGrantFlags;
+    @UnsupportedAppUsage
     private final ComponentName service;
     private final int constraintFlags;
     private final TriggerContentUri[] triggerContentUris;
@@ -306,6 +311,7 @@
     private final long initialBackoffMillis;
     private final int backoffPolicy;
     private final int priority;
+    @UnsupportedAppUsage
     private final int flags;
 
     /**
@@ -1009,12 +1015,14 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public Builder setPriority(int priority) {
             mPriority = priority;
             return this;
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public Builder setFlags(int flags) {
             mFlags = flags;
             return this;
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index d67f11b..578a9ae 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.job.IJobCallback;
 import android.content.ClipData;
 import android.net.Network;
@@ -59,11 +60,13 @@
         }
     }
 
+    @UnsupportedAppUsage
     private final int jobId;
     private final PersistableBundle extras;
     private final Bundle transientExtras;
     private final ClipData clipData;
     private final int clipGrantFlags;
+    @UnsupportedAppUsage
     private final IBinder callback;
     private final boolean overrideDeadlineExpired;
     private final Uri[] mTriggeredContentUris;
@@ -273,6 +276,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public IJobCallback getCallback() {
         return IJobCallback.Stub.asInterface(callback);
     }
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index 0deb2e1..08b1c2b 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -172,4 +172,20 @@
      *     if the supplied job ID does not correspond to any job.
      */
     public abstract @Nullable JobInfo getPendingJob(int jobId);
-}
+
+    /**
+     * <b>For internal system callers only!</b>
+     * Returns a list of all currently-executing jobs.
+     * @hide
+     */
+    public abstract List<JobInfo> getStartedJobs();
+
+    /**
+     * <b>For internal system callers only!</b>
+     * Returns a snapshot of the state of all jobs known to the system.
+     *
+     * <p class="note">This is a slow operation, so it should be called sparingly.
+     * @hide
+     */
+    public abstract List<JobSnapshot> getAllJobSnapshots();
+}
\ No newline at end of file
diff --git a/core/java/android/app/job/JobSnapshot.aidl b/core/java/android/app/job/JobSnapshot.aidl
new file mode 100644
index 0000000..d40f4e3
--- /dev/null
+++ b/core/java/android/app/job/JobSnapshot.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.job;
+
+parcelable JobSnapshot;
diff --git a/core/java/android/app/job/JobSnapshot.java b/core/java/android/app/job/JobSnapshot.java
new file mode 100644
index 0000000..ceeaab7
--- /dev/null
+++ b/core/java/android/app/job/JobSnapshot.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.job;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Current-state snapshot of a scheduled job.  These snapshots are not used in apps;
+ * they exist only within the system process across the local call surface where JobStatus
+ * is not directly accessible at build time.
+ *
+ * Constraints that the underlying job does not require are always reported as
+ * being currently satisfied.
+ * @hide
+ */
+public class JobSnapshot implements Parcelable {
+    private final JobInfo mJob;
+    private final int mSatisfiedConstraints;
+    private final boolean mIsRunnable;
+
+    public JobSnapshot(JobInfo info, int satisfiedMask, boolean runnable) {
+        mJob = info;
+        mSatisfiedConstraints = satisfiedMask;
+        mIsRunnable = runnable;
+    }
+
+    public JobSnapshot(Parcel in) {
+        mJob = JobInfo.CREATOR.createFromParcel(in);
+        mSatisfiedConstraints = in.readInt();
+        mIsRunnable = in.readBoolean();
+    }
+
+    private boolean satisfied(int flag) {
+        return (mSatisfiedConstraints & flag) != 0;
+    }
+
+    /**
+     * Returning JobInfo bound to this snapshot
+     * @return JobInfo of this snapshot
+     */
+    public JobInfo getJobInfo() {
+        return mJob;
+    }
+
+    /**
+     * Is this job actually runnable at this moment?
+     */
+    public boolean isRunnable() {
+        return mIsRunnable;
+    }
+
+    /**
+     * @see JobInfo.Builder#setRequiresCharging(boolean)
+     */
+    public boolean isChargingSatisfied() {
+        return !mJob.isRequireCharging()
+                || satisfied(JobInfo.CONSTRAINT_FLAG_CHARGING);
+    }
+
+    /**
+     * @see JobInfo.Builder#setRequiresBatteryNotLow(boolean)
+     */
+    public boolean isBatteryNotLowSatisfied() {
+        return !mJob.isRequireBatteryNotLow()
+                || satisfied(JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW);
+    }
+
+    /**
+     * @see JobInfo.Builder#setRequiresDeviceIdle(boolean)
+     */
+    public boolean isRequireDeviceIdleSatisfied() {
+        return !mJob.isRequireDeviceIdle()
+                || satisfied(JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE);
+    }
+
+    public boolean isRequireStorageNotLowSatisfied() {
+        return !mJob.isRequireStorageNotLow()
+                || satisfied(JobInfo.CONSTRAINT_FLAG_STORAGE_NOT_LOW);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        mJob.writeToParcel(out, flags);
+        out.writeInt(mSatisfiedConstraints);
+        out.writeBoolean(mIsRunnable);
+    }
+
+    public static final Creator<JobSnapshot> CREATOR = new Creator<JobSnapshot>() {
+        @Override
+        public JobSnapshot createFromParcel(Parcel in) {
+            return new JobSnapshot(in);
+        }
+
+        @Override
+        public JobSnapshot[] newArray(int size) {
+            return new JobSnapshot[size];
+        }
+    };
+}
diff --git a/core/java/android/app/job/JobWorkItem.java b/core/java/android/app/job/JobWorkItem.java
index 995f522..bfc6df2 100644
--- a/core/java/android/app/job/JobWorkItem.java
+++ b/core/java/android/app/job/JobWorkItem.java
@@ -19,6 +19,7 @@
 import static android.app.job.JobInfo.NETWORK_BYTES_UNKNOWN;
 
 import android.annotation.BytesLong;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -29,11 +30,15 @@
  * {@link JobParameters#dequeueWork() JobParameters.dequeueWork} for more details.
  */
 final public class JobWorkItem implements Parcelable {
+    @UnsupportedAppUsage
     final Intent mIntent;
     final long mNetworkDownloadBytes;
     final long mNetworkUploadBytes;
+    @UnsupportedAppUsage
     int mDeliveryCount;
+    @UnsupportedAppUsage
     int mWorkId;
+    @UnsupportedAppUsage
     Object mGrants;
 
     /**
@@ -219,6 +224,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     JobWorkItem(Parcel in) {
         if (in.readInt() != 0) {
             mIntent = Intent.CREATOR.createFromParcel(in);
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index 08ad2f0..2a33342 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -26,6 +26,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -164,7 +165,6 @@
         ObjectPool.recycle(this);
     }
 
-
     // Parcelable implementation
 
     /** Write to Parcel. */
@@ -237,4 +237,23 @@
         result = 31 * result + Objects.hashCode(mLifecycleStateRequest);
         return result;
     }
+
+    /** Dump transaction items callback items and final lifecycle state request. */
+    public void dump(String prefix, PrintWriter pw) {
+        pw.append(prefix).println("ClientTransaction{");
+        pw.append(prefix).print("  callbacks=[");
+        final int size = mActivityCallbacks != null ? mActivityCallbacks.size() : 0;
+        if (size > 0) {
+            pw.println();
+            for (int i = 0; i < size; i++) {
+                pw.append(prefix).append("    ").println(mActivityCallbacks.get(i).toString());
+            }
+            pw.append(prefix).println("  ]");
+        } else {
+            pw.println("]");
+        }
+        pw.append(prefix).append("  stateRequest=").println(mLifecycleStateRequest != null
+                ? mLifecycleStateRequest.toString() : null);
+        pw.append(prefix).println("}");
+    }
 }
diff --git a/core/java/android/app/servertransaction/DestroyActivityItem.java b/core/java/android/app/servertransaction/DestroyActivityItem.java
index b443166..5941486 100644
--- a/core/java/android/app/servertransaction/DestroyActivityItem.java
+++ b/core/java/android/app/servertransaction/DestroyActivityItem.java
@@ -33,6 +33,11 @@
     private int mConfigChanges;
 
     @Override
+    public void preExecute(ClientTransactionHandler client, IBinder token) {
+        client.getActivitiesToBeDestroyed().put(token, this);
+    }
+
+    @Override
     public void execute(ClientTransactionHandler client, IBinder token,
             PendingTransactionActions pendingActions) {
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 43a2b4c..20e0da3 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -24,7 +24,11 @@
 import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
 import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
+import static android.app.servertransaction.TransactionExecutorHelper.getShortActivityName;
+import static android.app.servertransaction.TransactionExecutorHelper.getStateName;
 import static android.app.servertransaction.TransactionExecutorHelper.lastCallbackRequestingState;
+import static android.app.servertransaction.TransactionExecutorHelper.tId;
+import static android.app.servertransaction.TransactionExecutorHelper.transactionToString;
 
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
@@ -35,6 +39,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * Class that manages transaction execution in the correct order.
@@ -62,25 +67,47 @@
      * either remain in the initial state, or last state needed by a callback.
      */
     public void execute(ClientTransaction transaction) {
+        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
+
         final IBinder token = transaction.getActivityToken();
-        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
+        if (token != null) {
+            final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed =
+                    mTransactionHandler.getActivitiesToBeDestroyed();
+            final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
+            if (destroyItem != null) {
+                if (transaction.getLifecycleStateRequest() == destroyItem) {
+                    // It is going to execute the transaction that will destroy activity with the
+                    // token, so the corresponding to-be-destroyed record can be removed.
+                    activitiesToBeDestroyed.remove(token);
+                }
+                if (mTransactionHandler.getActivityClient(token) == null) {
+                    // The activity has not been created but has been requested to destroy, so all
+                    // transactions for the token are just like being cancelled.
+                    Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n"
+                            + transactionToString(transaction, mTransactionHandler));
+                    return;
+                }
+            }
+        }
+
+        if (DEBUG_RESOLVER) Slog.d(TAG, transactionToString(transaction, mTransactionHandler));
 
         executeCallbacks(transaction);
 
         executeLifecycleState(transaction);
         mPendingActions.clear();
-        log("End resolving transaction");
+        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
     }
 
     /** Cycle through all states requested by callbacks and execute them at proper times. */
     @VisibleForTesting
     public void executeCallbacks(ClientTransaction transaction) {
         final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
-        if (callbacks == null) {
+        if (callbacks == null || callbacks.isEmpty()) {
             // No callbacks to execute, return early.
             return;
         }
-        log("Resolving callbacks");
+        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callbacks in transaction");
 
         final IBinder token = transaction.getActivityToken();
         ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
@@ -97,12 +124,12 @@
         final int size = callbacks.size();
         for (int i = 0; i < size; ++i) {
             final ClientTransactionItem item = callbacks.get(i);
-            log("Resolving callback: " + item);
+            if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
             final int postExecutionState = item.getPostExecutionState();
             final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
                     item.getPostExecutionState());
             if (closestPreExecutionState != UNDEFINED) {
-                cycleToPath(r, closestPreExecutionState);
+                cycleToPath(r, closestPreExecutionState, transaction);
             }
 
             item.execute(mTransactionHandler, token, mPendingActions);
@@ -116,7 +143,7 @@
                 // Skip the very last transition and perform it by explicit state request instead.
                 final boolean shouldExcludeLastTransition =
                         i == lastCallbackRequestingState && finalState == postExecutionState;
-                cycleToPath(r, postExecutionState, shouldExcludeLastTransition);
+                cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);
             }
         }
     }
@@ -128,10 +155,14 @@
             // No lifecycle request, return early.
             return;
         }
-        log("Resolving lifecycle state: " + lifecycleItem);
 
         final IBinder token = transaction.getActivityToken();
         final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
+        if (DEBUG_RESOLVER) {
+            Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
+                    + lifecycleItem + " for activity: "
+                    + getShortActivityName(token, mTransactionHandler));
+        }
 
         if (r == null) {
             // Ignore requests for non-existent client records for now.
@@ -139,7 +170,7 @@
         }
 
         // Cycle to the state right before the final requested state.
-        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
+        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
 
         // Execute the final transition with proper parameters.
         lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
@@ -148,8 +179,8 @@
 
     /** Transition the client between states. */
     @VisibleForTesting
-    public void cycleToPath(ActivityClientRecord r, int finish) {
-        cycleToPath(r, finish, false /* excludeLastState */);
+    public void cycleToPath(ActivityClientRecord r, int finish, ClientTransaction transaction) {
+        cycleToPath(r, finish, false /* excludeLastState */, transaction);
     }
 
     /**
@@ -157,20 +188,30 @@
      * sequence. This is used when resolving lifecycle state request, when the last transition must
      * be performed with some specific parameters.
      */
-    private void cycleToPath(ActivityClientRecord r, int finish,
-            boolean excludeLastState) {
+    private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
+            ClientTransaction transaction) {
         final int start = r.getLifecycleState();
-        log("Cycle from: " + start + " to: " + finish + " excludeLastState:" + excludeLastState);
+        if (DEBUG_RESOLVER) {
+            Slog.d(TAG, tId(transaction) + "Cycle activity: "
+                    + getShortActivityName(r.token, mTransactionHandler)
+                    + " from: " + getStateName(start) + " to: " + getStateName(finish)
+                    + " excludeLastState: " + excludeLastState);
+        }
         final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
-        performLifecycleSequence(r, path);
+        performLifecycleSequence(r, path, transaction);
     }
 
     /** Transition the client through previously initialized state sequence. */
-    private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
+    private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
+            ClientTransaction transaction) {
         final int size = path.size();
         for (int i = 0, state; i < size; i++) {
             state = path.get(i);
-            log("Transitioning to state: " + state);
+            if (DEBUG_RESOLVER) {
+                Slog.d(TAG, tId(transaction) + "Transitioning activity: "
+                        + getShortActivityName(r.token, mTransactionHandler)
+                        + " to state: " + getStateName(state));
+            }
             switch (state) {
                 case ON_CREATE:
                     mTransactionHandler.handleLaunchActivity(r, mPendingActions,
@@ -206,8 +247,4 @@
             }
         }
     }
-
-    private static void log(String message) {
-        if (DEBUG_RESOLVER) Slog.d(TAG, message);
-    }
 }
diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
index 01b13a2..0ea8c3c 100644
--- a/core/java/android/app/servertransaction/TransactionExecutorHelper.java
+++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
@@ -26,11 +26,16 @@
 import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
 import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
 
+import android.app.Activity;
 import android.app.ActivityThread.ActivityClientRecord;
+import android.app.ClientTransactionHandler;
+import android.os.IBinder;
 import android.util.IntArray;
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.List;
 
 /**
@@ -243,4 +248,73 @@
 
         return lastRequestingCallback;
     }
+
+    /** Dump transaction to string. */
+    static String transactionToString(ClientTransaction transaction,
+            ClientTransactionHandler transactionHandler) {
+        final StringWriter stringWriter = new StringWriter();
+        final PrintWriter pw = new PrintWriter(stringWriter);
+        final String prefix = tId(transaction);
+        transaction.dump(prefix, pw);
+        pw.append(prefix + "Target activity: ")
+                .println(getActivityName(transaction.getActivityToken(), transactionHandler));
+        return stringWriter.toString();
+    }
+
+    /** @return A string in format "tId:<transaction hashcode> ". */
+    static String tId(ClientTransaction transaction) {
+        return "tId:" + transaction.hashCode() + " ";
+    }
+
+    /** Get activity string name for provided token. */
+    static String getActivityName(IBinder token, ClientTransactionHandler transactionHandler) {
+        final Activity activity = getActivityForToken(token, transactionHandler);
+        if (activity != null) {
+            return activity.getComponentName().getClassName();
+        }
+        return "Not found for token: " + token;
+    }
+
+    /** Get short activity class name for provided token. */
+    static String getShortActivityName(IBinder token, ClientTransactionHandler transactionHandler) {
+        final Activity activity = getActivityForToken(token, transactionHandler);
+        if (activity != null) {
+            return activity.getComponentName().getShortClassName();
+        }
+        return "Not found for token: " + token;
+    }
+
+    private static Activity getActivityForToken(IBinder token,
+            ClientTransactionHandler transactionHandler) {
+        if (token == null) {
+            return null;
+        }
+        return transactionHandler.getActivity(token);
+    }
+
+    /** Get lifecycle state string name. */
+    static String getStateName(int state) {
+        switch (state) {
+            case UNDEFINED:
+                return "UNDEFINED";
+            case PRE_ON_CREATE:
+                return "PRE_ON_CREATE";
+            case ON_CREATE:
+                return "ON_CREATE";
+            case ON_START:
+                return "ON_START";
+            case ON_RESUME:
+                return "ON_RESUME";
+            case ON_PAUSE:
+                return "ON_PAUSE";
+            case ON_STOP:
+                return "ON_STOP";
+            case ON_DESTROY:
+                return "ON_DESTROY";
+            case ON_RESTART:
+                return "ON_RESTART";
+            default:
+                throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
+        }
+    }
 }
diff --git a/core/java/android/app/slice/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl
index 69852f3..6f73d02 100644
--- a/core/java/android/app/slice/ISliceManager.aidl
+++ b/core/java/android/app/slice/ISliceManager.aidl
@@ -33,7 +33,7 @@
     // Perms.
     void grantSlicePermission(String callingPkg, String toPkg, in Uri uri);
     void revokeSlicePermission(String callingPkg, String toPkg, in Uri uri);
-    int checkSlicePermission(in Uri uri, String pkg, int pid, int uid,
+    int checkSlicePermission(in Uri uri, String callingPkg, String pkg, int pid, int uid,
             in String[] autoGrantPermissions);
     void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices);
 }
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 26498e8..955093d 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -430,7 +430,8 @@
      */
     public @PermissionResult int checkSlicePermission(@NonNull Uri uri, int pid, int uid) {
         try {
-            return mService.checkSlicePermission(uri, null, pid, uid, null);
+            return mService.checkSlicePermission(uri, mContext.getPackageName(), null, pid, uid,
+                    null);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -487,7 +488,8 @@
             if (pkg == null) {
                 throw new SecurityException("No pkg specified");
             }
-            int result = mService.checkSlicePermission(uri, pkg, pid, uid, autoGrantPermissions);
+            int result = mService.checkSlicePermission(uri, mContext.getPackageName(), pkg, pid,
+                    uid, autoGrantPermissions);
             if (result == PERMISSION_DENIED) {
                 throw new SecurityException("User " + uid + " does not have slice permission for "
                         + uri + ".");
diff --git a/core/java/android/app/timezone/RulesState.aidl b/core/java/android/app/timezone/RulesState.aidl
index f789120..665220d 100644
--- a/core/java/android/app/timezone/RulesState.aidl
+++ b/core/java/android/app/timezone/RulesState.aidl
@@ -14,4 +14,6 @@
  * limitations under the License.
  */
 
+package android.app.timezone;
+
 parcelable RulesState;
\ No newline at end of file
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index fb27bed..27abdcf 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -19,6 +19,7 @@
 import android.Manifest;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.hardware.biometrics.BiometricSourceType;
 import android.os.Handler;
@@ -74,6 +75,7 @@
      *
      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
      */
+    @UnsupportedAppUsage
     public void reportUnlockAttempt(boolean successful, int userId) {
         try {
             mService.reportUnlockAttempt(successful, userId);
diff --git a/core/java/android/app/usage/ConfigurationStats.java b/core/java/android/app/usage/ConfigurationStats.java
index 080216c..dff9b61 100644
--- a/core/java/android/app/usage/ConfigurationStats.java
+++ b/core/java/android/app/usage/ConfigurationStats.java
@@ -15,6 +15,7 @@
  */
 package android.app.usage;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Configuration;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -28,31 +29,37 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public Configuration mConfiguration;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long mBeginTimeStamp;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long mEndTimeStamp;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long mLastTimeActive;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long mTotalTimeActive;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int mActivationCount;
 
     /**
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 9f46f20..59ae334 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.usage.NetworkStats.Bucket;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -121,6 +122,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public NetworkStatsManager(Context context) throws ServiceNotFoundException {
         this(context, INetworkStatsService.Stub.asInterface(
                 ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 3e90af3..9f22ad1 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -17,6 +17,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Configuration;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -177,27 +178,32 @@
         /**
          * {@hide}
          */
+        @UnsupportedAppUsage
         public String mPackage;
 
         /**
          * {@hide}
          */
+        @UnsupportedAppUsage
         public String mClass;
 
         /**
          * {@hide}
          */
+        @UnsupportedAppUsage
         public long mTimeStamp;
 
         /**
          * {@hide}
          */
+        @UnsupportedAppUsage
         public int mEventType;
 
         /**
          * Only present for {@link #CONFIGURATION_CHANGE} event types.
          * {@hide}
          */
+        @UnsupportedAppUsage
         public Configuration mConfiguration;
 
         /**
@@ -380,24 +386,30 @@
     }
 
     // Only used when creating the resulting events. Not used for reading/unparceling.
+    @UnsupportedAppUsage
     private List<Event> mEventsToWrite = null;
 
     // Only used for reading/unparceling events.
+    @UnsupportedAppUsage
     private Parcel mParcel = null;
+    @UnsupportedAppUsage
     private final int mEventCount;
 
+    @UnsupportedAppUsage
     private int mIndex = 0;
 
     /*
      * In order to save space, since ComponentNames will be duplicated everywhere,
      * we use a map and index into it.
      */
+    @UnsupportedAppUsage
     private String[] mStringPool;
 
     /**
      * Construct the iterator from a parcel.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public UsageEvents(Parcel in) {
         byte[] bytes = in.readBlob();
         Parcel data = Parcel.obtain();
@@ -482,6 +494,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private int findStringIndex(String str) {
         final int index = Arrays.binarySearch(mStringPool, str);
         if (index < 0) {
@@ -493,6 +506,7 @@
     /**
      * Writes a single event to the parcel. Modify this when updating {@link Event}.
      */
+    @UnsupportedAppUsage
     private void writeEventToParcel(Event event, Parcel p, int flags) {
         final int packageIndex;
         if (event.mPackage != null) {
@@ -536,6 +550,7 @@
     /**
      * Reads a single event from the parcel. Modify this when updating {@link Event}.
      */
+    @UnsupportedAppUsage
     private void readEventFromParcel(Parcel p, Event eventOut) {
         final int packageIndex = p.readInt();
         if (packageIndex >= 0) {
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 2b14841..0659a23 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -17,6 +17,7 @@
 package android.app.usage;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -31,32 +32,38 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public String mPackageName;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long mBeginTimeStamp;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long mEndTimeStamp;
 
     /**
      * Last time used by the user with an explicit action (notification, activity launch).
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long mLastTimeUsed;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long mTotalTimeInForeground;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int mLaunchCount;
 
     /**
@@ -67,6 +74,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int mLastEvent;
 
     /**
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 72d209a..0994332 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -21,6 +21,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
@@ -231,9 +232,12 @@
     @SystemApi
     public static final String EXTRA_TIME_USED = "android.app.usage.extra.TIME_USED";
 
+    @UnsupportedAppUsage
     private static final UsageEvents sEmptyResults = new UsageEvents();
 
+    @UnsupportedAppUsage
     private final Context mContext;
+    @UnsupportedAppUsage
     private final IUsageStatsManager mService;
 
     /**
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 49cc498..f003d4b 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
@@ -53,14 +54,17 @@
     static final int HANDLE_UPDATE = 1;
     static final int HANDLE_PROVIDER_CHANGED = 2;
     static final int HANDLE_PROVIDERS_CHANGED = 3;
+    @UnsupportedAppUsage
     static final int HANDLE_VIEW_DATA_CHANGED = 4;
 
     final static Object sServiceLock = new Object();
+    @UnsupportedAppUsage
     static IAppWidgetService sService;
     static boolean sServiceInitialized = false;
     private DisplayMetrics mDisplayMetrics;
 
     private String mContextOpPackageName;
+    @UnsupportedAppUsage
     private final Handler mHandler;
     private final int mHostId;
     private final Callbacks mCallbacks;
@@ -156,6 +160,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public AppWidgetHost(Context context, int hostId, OnClickHandler handler, Looper looper) {
         mContextOpPackageName = context.getOpPackageName();
         mHostId = hostId;
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index ab0eb92..a9187b6 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -16,6 +16,7 @@
 
 package android.appwidget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -70,7 +71,9 @@
     Context mContext;
     Context mRemoteContext;
 
+    @UnsupportedAppUsage
     int mAppWidgetId;
+    @UnsupportedAppUsage
     AppWidgetProviderInfo mInfo;
     View mView;
     int mViewMode = VIEW_MODE_NOINIT;
@@ -174,6 +177,7 @@
         return getDefaultPaddingForWidget(context, appInfo, padding);
     }
 
+    @UnsupportedAppUsage
     private static Rect getDefaultPaddingForWidget(Context context, ApplicationInfo appInfo,
             Rect padding) {
         if (padding == null) {
@@ -284,6 +288,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
             int maxHeight, boolean ignorePadding) {
         if (newOptions == null) {
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 20248b9..dbc1c19 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -23,6 +23,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.IServiceConnection;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -463,6 +464,7 @@
 
     private final Context mContext;
     private final String mPackageName;
+    @UnsupportedAppUsage
     private final IAppWidgetService mService;
     private final DisplayMetrics mDisplayMetrics;
 
@@ -816,6 +818,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
         if (mService == null) {
             return Collections.emptyList();
@@ -842,6 +845,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
             @Nullable UserHandle profile, @Nullable String packageName) {
         if (mService == null) {
@@ -902,6 +906,7 @@
      *                      provider for this AppWidget.
      * @hide
      */
+    @UnsupportedAppUsage
     public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
         if (mService == null) {
             return;
@@ -924,6 +929,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
         if (mService == null) {
             return;
@@ -1094,6 +1100,7 @@
      * @see Context#getServiceDispatcher(ServiceConnection, Handler, int)
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean bindRemoteViewsService(Context context, int appWidgetId, Intent intent,
             IServiceConnection connection, @Context.BindServiceFlags int flags) {
         if (mService == null) {
@@ -1139,6 +1146,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private boolean bindAppWidgetIdIfAllowed(int appWidgetId, int profileId,
             ComponentName provider, Bundle options) {
         if (mService == null) {
diff --git a/core/java/android/appwidget/AppWidgetManagerInternal.java b/core/java/android/appwidget/AppWidgetManagerInternal.java
index 7ab3d8b..5694ca8 100644
--- a/core/java/android/appwidget/AppWidgetManagerInternal.java
+++ b/core/java/android/appwidget/AppWidgetManagerInternal.java
@@ -16,12 +16,9 @@
 
 package android.appwidget;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.ArraySet;
 
-import java.util.Set;
-
 /**
  * App widget manager local system service interface.
  *
@@ -36,4 +33,13 @@
      * @return Whether the UID hosts widgets from the package.
      */
     public abstract @Nullable ArraySet<String> getHostedWidgetPackages(int uid);
+
+    /**
+     * Execute the widget-related work of unlocking a user.  This is intentionally
+     * invoked just <em>before</em> the boot-completed broadcast is issued, after
+     * the data-related work of unlock has completed.
+     *
+     * @param userId The user that is being unlocked.
+     */
+    public abstract void unlockUser(int userId);
 }
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 6dd85ca..53315cc 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -270,6 +271,7 @@
     public int widgetFeatures;
 
     /** @hide */
+    @UnsupportedAppUsage
     public ActivityInfo providerInfo;
 
     public AppWidgetProviderInfo() {
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 94fd138..d21f76d 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -21,6 +21,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -29,6 +30,7 @@
 import android.os.IBinder;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -117,6 +119,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_ACTIVE_DEVICE_CHANGED =
             "android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED";
 
@@ -137,6 +140,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_CODEC_CONFIG_CHANGED =
             "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED";
 
@@ -160,6 +164,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
 
     /**
@@ -167,6 +172,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
 
     /**
@@ -174,6 +180,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int OPTIONAL_CODECS_SUPPORTED = 1;
 
     /**
@@ -182,6 +189,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
 
     /**
@@ -189,6 +197,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
 
     /**
@@ -196,6 +205,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
 
     private Context mContext;
@@ -261,13 +271,14 @@
         ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
         intent.setComponent(comp);
         if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
-                mContext.getUser())) {
+                UserHandle.CURRENT_OR_SELF)) {
             Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
             return false;
         }
         return true;
     }
 
+    @UnsupportedAppUsage
     /*package*/ void close() {
         mServiceListener = null;
         IBluetoothManager mgr = mAdapter.getBluetoothManager();
@@ -315,6 +326,7 @@
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
         try {
@@ -357,6 +369,7 @@
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
         try {
@@ -460,6 +473,7 @@
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setActiveDevice(@Nullable BluetoothDevice device) {
         if (DBG) log("setActiveDevice(" + device + ")");
         try {
@@ -490,6 +504,7 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     @Nullable
+    @UnsupportedAppUsage
     public BluetoothDevice getActiveDevice() {
         if (VDBG) log("getActiveDevice()");
         try {
@@ -556,6 +571,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
+    @UnsupportedAppUsage
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
         try {
@@ -671,6 +687,7 @@
      * @return the current codec status
      * @hide
      */
+    @UnsupportedAppUsage
     public BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
         try {
@@ -698,6 +715,7 @@
      * @param codecConfig the codec configuration preference
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCodecConfigPreference(BluetoothDevice device,
                                          BluetoothCodecConfig codecConfig) {
         if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
@@ -723,6 +741,7 @@
      * active A2DP Bluetooth device.
      * @hide
      */
+    @UnsupportedAppUsage
     public void enableOptionalCodecs(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")");
         enableDisableOptionalCodecs(device, true);
@@ -735,6 +754,7 @@
      * active A2DP Bluetooth device.
      * @hide
      */
+    @UnsupportedAppUsage
     public void disableOptionalCodecs(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")");
         enableDisableOptionalCodecs(device, false);
@@ -775,6 +795,7 @@
      * OPTIONAL_CODECS_SUPPORTED.
      * @hide
      */
+    @UnsupportedAppUsage
     public int supportsOptionalCodecs(BluetoothDevice device) {
         try {
             mServiceLock.readLock().lock();
@@ -799,6 +820,7 @@
      * OPTIONAL_CODECS_PREF_DISABLED.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getOptionalCodecsEnabled(BluetoothDevice device) {
         try {
             mServiceLock.readLock().lock();
@@ -824,6 +846,7 @@
      * OPTIONAL_CODECS_PREF_DISABLED.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
         try {
             if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
@@ -854,6 +877,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String stateToString(int state) {
         switch (state) {
             case STATE_DISCONNECTED:
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index 13f0aaf..fda2f89 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -278,6 +279,7 @@
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
         final IBluetoothA2dpSink service = mService;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 1b9e27c..4c655b5 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -23,6 +23,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.bluetooth.le.BluetoothLeAdvertiser;
 import android.bluetooth.le.BluetoothLeScanner;
@@ -445,6 +446,12 @@
      */
     public static final int IO_CAPABILITY_UNKNOWN = 255;
 
+    /** @hide */
+    @IntDef({IO_CAPABILITY_OUT, IO_CAPABILITY_IO, IO_CAPABILITY_IN, IO_CAPABILITY_NONE,
+            IO_CAPABILITY_KBDISP})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface IoCapability {}
+
     /**
      * Broadcast Action: The local Bluetooth adapter has started the remote
      * device discovery process.
@@ -633,6 +640,7 @@
     private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
 
     private final IBluetoothManager mManagerService;
+    @UnsupportedAppUsage
     private IBluetooth mService;
     private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
 
@@ -988,6 +996,7 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     @AdapterState
+    @UnsupportedAppUsage
     public int getLeState() {
         int state = BluetoothAdapter.STATE_OFF;
 
@@ -1098,6 +1107,7 @@
      * @return true to indicate adapter shutdown has begun, or false on immediate error
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean disable(boolean persist) {
 
         try {
@@ -1149,6 +1159,7 @@
      * @return true to indicate that the config file was successfully cleared
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean factoryReset() {
         try {
             mServiceLock.readLock().lock();
@@ -1172,6 +1183,7 @@
      * @return the UUIDs supported by the local Bluetooth Adapter.
      * @hide
      */
+    @UnsupportedAppUsage
     public ParcelUuid[] getUuids() {
         if (getState() != STATE_ON) {
             return null;
@@ -1286,6 +1298,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    @IoCapability
     public int getIoCapability() {
         if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
         try {
@@ -1313,7 +1326,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public boolean setIoCapability(int capability) {
+    public boolean setIoCapability(@IoCapability int capability) {
         if (getState() != STATE_ON) return false;
         try {
             mServiceLock.readLock().lock();
@@ -1336,6 +1349,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    @IoCapability
     public int getLeIoCapability() {
         if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
         try {
@@ -1363,7 +1377,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public boolean setLeIoCapability(int capability) {
+    public boolean setLeIoCapability(@IoCapability int capability) {
         if (getState() != STATE_ON) return false;
         try {
             mServiceLock.readLock().lock();
@@ -1438,6 +1452,7 @@
      * @return true if the scan mode was set, false otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setScanMode(@ScanMode int mode, int duration) {
         if (getState() != STATE_ON) {
             return false;
@@ -1456,6 +1471,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean setScanMode(int mode) {
         if (getState() != STATE_ON) {
             return false;
@@ -1465,6 +1481,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getDiscoverableTimeout() {
         if (getState() != STATE_ON) {
             return -1;
@@ -1483,6 +1500,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDiscoverableTimeout(int timeout) {
         if (getState() != STATE_ON) {
             return;
@@ -2007,6 +2025,7 @@
      * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
      * @hide
      */
+    @UnsupportedAppUsage
     public int getConnectionState() {
         if (getState() != STATE_ON) {
             return BluetoothAdapter.STATE_DISCONNECTED;
@@ -2094,6 +2113,7 @@
      * permissions, or channel in use.
      * @hide
      */
+    @UnsupportedAppUsage
     public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
             boolean min16DigitPin) throws IOException {
         BluetoothServerSocket socket =
@@ -2206,6 +2226,7 @@
      * permissions, or channel in use.
      * @hide
      */
+    @UnsupportedAppUsage
     public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)
             throws IOException {
         return createNewRfcommSocketAndRecord(name, uuid, false, true);
@@ -2749,6 +2770,7 @@
         return true;
     }
 
+    @UnsupportedAppUsage
     /*package*/ IBluetoothManager getBluetoothManager() {
         return mManagerService;
     }
@@ -2756,6 +2778,7 @@
     private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks =
             new ArrayList<IBluetoothManagerCallback>();
 
+    @UnsupportedAppUsage
     /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
         synchronized (mProxyServiceStateCallbacks) {
             if (cb == null) {
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index f22ea6e..3a78cbd 100755
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -16,6 +16,8 @@
 
 package android.bluetooth;
 
+import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -63,6 +65,7 @@
     private final int mClass;
 
     /** @hide */
+    @UnsupportedAppUsage
     public BluetoothClass(int classInt) {
         mClass = classInt;
     }
@@ -291,6 +294,7 @@
      *
      * @hide
      */
+    @TestApi
     public int getClassOfDevice() {
         return mClass;
     }
@@ -322,8 +326,10 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROFILE_HEADSET = 0;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int PROFILE_A2DP = 1;
     /** @hide */
     public static final int PROFILE_OPP = 2;
@@ -346,6 +352,7 @@
      * @return True if this device might support specified profile.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean doesClassMatch(int profile) {
         if (profile == PROFILE_A2DP) {
             if (hasService(Service.RENDER)) {
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index e3a6e06..79c0a3a 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,34 +33,58 @@
     // Add an entry for each source codec here.
     // NOTE: The values should be same as those listed in the following file:
     //   hardware/libhardware/include/hardware/bt_av.h
+    @UnsupportedAppUsage
     public static final int SOURCE_CODEC_TYPE_SBC = 0;
+    @UnsupportedAppUsage
     public static final int SOURCE_CODEC_TYPE_AAC = 1;
+    @UnsupportedAppUsage
     public static final int SOURCE_CODEC_TYPE_APTX = 2;
+    @UnsupportedAppUsage
     public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
+    @UnsupportedAppUsage
     public static final int SOURCE_CODEC_TYPE_LDAC = 4;
+    @UnsupportedAppUsage
     public static final int SOURCE_CODEC_TYPE_MAX = 5;
 
+    @UnsupportedAppUsage
     public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
 
+    @UnsupportedAppUsage
     public static final int CODEC_PRIORITY_DISABLED = -1;
+    @UnsupportedAppUsage
     public static final int CODEC_PRIORITY_DEFAULT = 0;
+    @UnsupportedAppUsage
     public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
 
+    @UnsupportedAppUsage
     public static final int SAMPLE_RATE_NONE = 0;
+    @UnsupportedAppUsage
     public static final int SAMPLE_RATE_44100 = 0x1 << 0;
+    @UnsupportedAppUsage
     public static final int SAMPLE_RATE_48000 = 0x1 << 1;
+    @UnsupportedAppUsage
     public static final int SAMPLE_RATE_88200 = 0x1 << 2;
+    @UnsupportedAppUsage
     public static final int SAMPLE_RATE_96000 = 0x1 << 3;
+    @UnsupportedAppUsage
     public static final int SAMPLE_RATE_176400 = 0x1 << 4;
+    @UnsupportedAppUsage
     public static final int SAMPLE_RATE_192000 = 0x1 << 5;
 
+    @UnsupportedAppUsage
     public static final int BITS_PER_SAMPLE_NONE = 0;
+    @UnsupportedAppUsage
     public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
+    @UnsupportedAppUsage
     public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
+    @UnsupportedAppUsage
     public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
 
+    @UnsupportedAppUsage
     public static final int CHANNEL_MODE_NONE = 0;
+    @UnsupportedAppUsage
     public static final int CHANNEL_MODE_MONO = 0x1 << 0;
+    @UnsupportedAppUsage
     public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
 
     private final int mCodecType;
@@ -72,6 +97,7 @@
     private final long mCodecSpecific3;
     private final long mCodecSpecific4;
 
+    @UnsupportedAppUsage
     public BluetoothCodecConfig(int codecType, int codecPriority,
             int sampleRate, int bitsPerSample,
             int channelMode, long codecSpecific1,
@@ -276,6 +302,7 @@
      *
      * @return the codec type
      */
+    @UnsupportedAppUsage
     public int getCodecType() {
         return mCodecType;
     }
@@ -296,6 +323,7 @@
      *
      * @return the codec priority
      */
+    @UnsupportedAppUsage
     public int getCodecPriority() {
         return mCodecPriority;
     }
@@ -307,6 +335,7 @@
      *
      * @param codecPriority the codec priority
      */
+    @UnsupportedAppUsage
     public void setCodecPriority(int codecPriority) {
         mCodecPriority = codecPriority;
     }
@@ -324,6 +353,7 @@
      *
      * @return the codec sample rate
      */
+    @UnsupportedAppUsage
     public int getSampleRate() {
         return mSampleRate;
     }
@@ -338,6 +368,7 @@
      *
      * @return the codec bits per sample
      */
+    @UnsupportedAppUsage
     public int getBitsPerSample() {
         return mBitsPerSample;
     }
@@ -351,6 +382,7 @@
      *
      * @return the codec channel mode
      */
+    @UnsupportedAppUsage
     public int getChannelMode() {
         return mChannelMode;
     }
@@ -360,6 +392,7 @@
      *
      * @return a codec specific value1.
      */
+    @UnsupportedAppUsage
     public long getCodecSpecific1() {
         return mCodecSpecific1;
     }
@@ -369,6 +402,7 @@
      *
      * @return a codec specific value2
      */
+    @UnsupportedAppUsage
     public long getCodecSpecific2() {
         return mCodecSpecific2;
     }
@@ -378,6 +412,7 @@
      *
      * @return a codec specific value3
      */
+    @UnsupportedAppUsage
     public long getCodecSpecific3() {
         return mCodecSpecific3;
     }
@@ -387,6 +422,7 @@
      *
      * @return a codec specific value4
      */
+    @UnsupportedAppUsage
     public long getCodecSpecific4() {
         return mCodecSpecific4;
     }
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 3a05e70..78560d2 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -37,6 +38,7 @@
      * This extra represents the current codec status of the A2DP
      * profile.
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_CODEC_STATUS =
             "android.bluetooth.codec.extra.CODEC_STATUS";
 
@@ -137,6 +139,7 @@
      *
      * @return the current codec configuration
      */
+    @UnsupportedAppUsage
     public BluetoothCodecConfig getCodecConfig() {
         return mCodecConfig;
     }
@@ -146,6 +149,7 @@
      *
      * @return an array with the codecs local capabilities
      */
+    @UnsupportedAppUsage
     public BluetoothCodecConfig[] getCodecsLocalCapabilities() {
         return mCodecsLocalCapabilities;
     }
@@ -155,6 +159,7 @@
      *
      * @return an array with the codecs selectable capabilities
      */
+    @UnsupportedAppUsage
     public BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
         return mCodecsSelectableCapabilities;
     }
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 7a6b72e..818a749 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Parcel;
@@ -115,6 +116,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_DISAPPEARED =
             "android.bluetooth.device.action.DISAPPEARED";
 
@@ -186,6 +188,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_ALIAS_CHANGED =
             "android.bluetooth.device.action.ALIAS_CHANGED";
 
@@ -306,6 +309,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON";
 
     /**
@@ -346,6 +350,7 @@
 
     /** @hide */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_SDP_RECORD =
             "android.bluetooth.device.action.SDP_RECORD";
 
@@ -390,6 +395,7 @@
             "android.bluetooth.device.action.PAIRING_REQUEST";
     /** @hide */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_PAIRING_CANCEL =
             "android.bluetooth.device.action.PAIRING_CANCEL";
 
@@ -481,6 +487,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int UNBOND_REASON_AUTH_FAILED = 1;
 
     /**
@@ -489,6 +496,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int UNBOND_REASON_AUTH_REJECTED = 2;
 
     /**
@@ -503,6 +511,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
 
     /**
@@ -510,6 +519,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
 
     /**
@@ -517,6 +527,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int UNBOND_REASON_AUTH_TIMEOUT = 6;
 
     /**
@@ -524,6 +535,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7;
 
     /**
@@ -532,6 +544,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8;
 
     /**
@@ -610,6 +623,7 @@
             "android.bluetooth.device.extra.SDP_RECORD";
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final String EXTRA_SDP_SEARCH_STATUS =
             "android.bluetooth.device.extra.SDP_SEARCH_STATUS";
     /**
@@ -720,6 +734,7 @@
     private final String mAddress;
 
     /*package*/
+    @UnsupportedAppUsage
     static IBluetooth getService() {
         synchronized (BluetoothDevice.class) {
             if (sService == null) {
@@ -763,6 +778,7 @@
      * @throws IllegalArgumentException address is invalid
      * @hide
      */
+    @UnsupportedAppUsage
     /*package*/ BluetoothDevice(String address) {
         getService();  // ensures sService is initialized
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
@@ -887,6 +903,7 @@
      * @return the Bluetooth alias, or null if no alias or there was a problem
      * @hide
      */
+    @UnsupportedAppUsage
     public String getAlias() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -911,6 +928,7 @@
      * @return true on success, false on error
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setAlias(String alias) {
         final IBluetooth service = sService;
         if (service == null) {
@@ -934,6 +952,7 @@
      * @see #getAlias()
      * @see #getName()
      */
+    @UnsupportedAppUsage
     public String getAliasName() {
         String name = getAlias();
         if (name == null) {
@@ -952,6 +971,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
+    @UnsupportedAppUsage
     public int getBatteryLevel() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1010,6 +1030,7 @@
      * @throws IllegalArgumentException if an invalid transport was specified
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean createBond(int transport) {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1063,6 +1084,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean isBondingInitiatedLocally() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1355,6 +1377,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean setPasskey(int passkey) {
         //TODO(BT)
         /*
@@ -1395,6 +1418,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean cancelPairingUserInput() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1410,6 +1434,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean isBluetoothDock() {
         // TODO(BT)
         /*
@@ -1435,6 +1460,7 @@
      * #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getPhonebookAccessPermission() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1479,6 +1505,7 @@
      * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getMessageAccessPermission() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1501,6 +1528,7 @@
      * @return Whether the value has been successfully set.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setMessageAccessPermission(int value) {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1543,6 +1571,7 @@
      * @return Whether the value has been successfully set.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setSimAccessPermission(int value) {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1581,6 +1610,7 @@
      * permissions
      * @hide
      */
+    @UnsupportedAppUsage
     public BluetoothSocket createRfcommSocket(int channel) throws IOException {
         if (!isBluetoothEnabled()) {
             Log.e(TAG, "Bluetooth is not enabled");
@@ -1733,6 +1763,7 @@
      * permissions.
      * @hide
      */
+    @UnsupportedAppUsage
     public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
         if (!isBluetoothEnabled()) {
             Log.e(TAG, "Bluetooth is not enabled");
@@ -1752,6 +1783,7 @@
      * permissions.
      * @hide
      */
+    @UnsupportedAppUsage
     public BluetoothSocket createScoSocket() throws IOException {
         if (!isBluetoothEnabled()) {
             Log.e(TAG, "Bluetooth is not enabled");
@@ -1769,6 +1801,7 @@
      * @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin.
      * @hide
      */
+    @UnsupportedAppUsage
     public static byte[] convertPinToBytes(String pin) {
         if (pin == null) {
             return null;
@@ -1900,6 +1933,7 @@
      * operations.
      * @hide
      */
+    @UnsupportedAppUsage
     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
             BluetoothGattCallback callback, int transport,
             boolean opportunistic, int phy, Handler handler) {
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 457119d..78248ef 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
@@ -41,16 +42,23 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
+    @UnsupportedAppUsage
     private IBluetoothGatt mService;
+    @UnsupportedAppUsage
     private volatile BluetoothGattCallback mCallback;
     private Handler mHandler;
+    @UnsupportedAppUsage
     private int mClientIf;
     private BluetoothDevice mDevice;
+    @UnsupportedAppUsage
     private boolean mAutoConnect;
+    @UnsupportedAppUsage
     private int mAuthRetryState;
     private int mConnState;
     private final Object mStateLock = new Object();
+    @UnsupportedAppUsage
     private Boolean mDeviceBusy = false;
+    @UnsupportedAppUsage
     private int mTransport;
     private int mPhy;
     private boolean mOpportunistic;
@@ -810,6 +818,7 @@
     /**
      * Unregister the current application and callbacks.
      */
+    @UnsupportedAppUsage
     private void unregisterApp() {
         if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
         if (mService == null || mClientIf == 0) return;
@@ -845,6 +854,7 @@
      * automatically connect as soon as the remote device becomes available (true).
      * @return true, if the connection attempt was initiated successfully
      */
+    @UnsupportedAppUsage
     /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
             Handler handler) {
         if (DBG) {
@@ -1407,6 +1417,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean refresh() {
         if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
         if (mService == null || mClientIf == 0) return false;
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index 243ad35..6d46b3a 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -15,6 +15,7 @@
  */
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.ParcelUuid;
 import android.os.Parcelable;
@@ -182,6 +183,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected int mInstance;
 
     /**
@@ -218,6 +220,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected BluetoothGattService mService;
 
     /**
@@ -381,6 +384,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     /*package*/ void setService(BluetoothGattService service) {
         mService = service;
     }
@@ -464,6 +468,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setKeySize(int keySize) {
         mKeySize = keySize;
     }
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index 217a5ab..3ffbb9e 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.ParcelUuid;
 import android.os.Parcelable;
@@ -100,6 +101,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected int mInstance;
 
     /**
@@ -114,6 +116,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected BluetoothGattCharacteristic mCharacteristic;
 
     /**
@@ -205,6 +208,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     /*package*/ void setCharacteristic(BluetoothGattCharacteristic characteristic) {
         mCharacteristic = characteristic;
     }
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index ce1dc1c..8e740ee 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -15,6 +15,7 @@
  */
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.ParcelUuid;
 import android.os.Parcelable;
@@ -48,6 +49,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected BluetoothDevice mDevice;
 
     /**
@@ -265,6 +267,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setInstanceId(int instanceId) {
         mInstanceId = instanceId;
     }
@@ -382,6 +385,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setAdvertisePreferred(boolean advertisePreferred) {
         mAdvertisePreferred = advertisePreferred;
     }
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 0c91a20..636b1b9 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -22,6 +22,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Binder;
@@ -110,6 +111,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_ACTIVE_DEVICE_CHANGED =
             "android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED";
 
@@ -401,6 +403,7 @@
      * results once close() has been called. Multiple invocations of close()
      * are ok.
      */
+    @UnsupportedAppUsage
     /*package*/ void close() {
         if (VDBG) log("close()");
 
@@ -602,6 +605,7 @@
      * @return priority of the device
      * @hide
      */
+    @UnsupportedAppUsage
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
         final IBluetoothHeadset service = mService;
@@ -719,6 +723,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getAudioState(BluetoothDevice device) {
         if (VDBG) log("getAudioState");
         final IBluetoothHeadset service = mService;
@@ -846,6 +851,7 @@
      * @return false if there was some error such as there is no active headset
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean connectAudio() {
         final IBluetoothHeadset service = mService;
         if (service != null && isEnabled()) {
@@ -872,6 +878,7 @@
      * @return false if audio is not connected, or on error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean disconnectAudio() {
         final IBluetoothHeadset service = mService;
         if (service != null && isEnabled()) {
@@ -909,6 +916,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    @UnsupportedAppUsage
     public boolean startScoUsingVirtualVoiceCall() {
         if (DBG) log("startScoUsingVirtualVoiceCall()");
         final IBluetoothHeadset service = mService;
@@ -938,6 +946,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    @UnsupportedAppUsage
     public boolean stopScoUsingVirtualVoiceCall() {
         if (DBG) log("stopScoUsingVirtualVoiceCall()");
         final IBluetoothHeadset service = mService;
@@ -962,6 +971,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
             int type) {
         final IBluetoothHeadset service = mService;
@@ -1060,6 +1070,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
+    @UnsupportedAppUsage
     public boolean setActiveDevice(@Nullable BluetoothDevice device) {
         if (DBG) {
             Log.d(TAG, "setActiveDevice: " + device);
@@ -1089,6 +1100,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.BLUETOOTH)
+    @UnsupportedAppUsage
     public BluetoothDevice getActiveDevice() {
         if (VDBG) {
             Log.d(TAG, "getActiveDevice");
@@ -1163,6 +1175,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     private boolean isEnabled() {
         return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 397b906..ec18d42 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -476,6 +477,7 @@
      * @return <code>true</code> if command has been issued successfully; <code>false</code>
      * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent.
      */
+    @UnsupportedAppUsage
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
         final IBluetoothHeadsetClient service = mService;
@@ -498,6 +500,7 @@
      * @return <code>true</code> if command has been issued successfully; <code>false</code>
      * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent.
      */
+    @UnsupportedAppUsage
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
         final IBluetoothHeadsetClient service = mService;
@@ -720,6 +723,7 @@
      * @return <code>true</code> if command has been issued successfully; <code>false</code>
      * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
      */
+    @UnsupportedAppUsage
     public boolean acceptCall(BluetoothDevice device, int flag) {
         if (DBG) log("acceptCall()");
         final IBluetoothHeadsetClient service = mService;
@@ -766,6 +770,7 @@
      * #EXTRA_AG_FEATURE_REJECT_CALL}. This method invocation will fail silently when feature is not
      * supported.</p>
      */
+    @UnsupportedAppUsage
     public boolean rejectCall(BluetoothDevice device) {
         if (DBG) log("rejectCall()");
         final IBluetoothHeadsetClient service = mService;
@@ -943,6 +948,7 @@
      *
      * Note: This is an internal function and shouldn't be exposed
      */
+    @UnsupportedAppUsage
     public int getAudioState(BluetoothDevice device) {
         if (VDBG) log("getAudioState");
         final IBluetoothHeadsetClient service = mService;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
index d46b2e3..e02a2f4 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -143,6 +144,7 @@
      *
      * @return call id.
      */
+    @UnsupportedAppUsage
     public int getId() {
         return mId;
     }
@@ -162,6 +164,7 @@
      *
      * @return state of this particular phone call.
      */
+    @UnsupportedAppUsage
     public int getState() {
         return mState;
     }
@@ -171,6 +174,7 @@
      *
      * @return string representing phone number.
      */
+    @UnsupportedAppUsage
     public String getNumber() {
         return mNumber;
     }
@@ -189,6 +193,7 @@
      *
      * @return <code>true</code> if call is a multi party call, <code>false</code> otherwise.
      */
+    @UnsupportedAppUsage
     public boolean isMultiParty() {
         return mMultiParty;
     }
@@ -198,6 +203,7 @@
      *
      * @return <code>true</code> if its outgoing call, <code>false</code> otherwise.
      */
+    @UnsupportedAppUsage
     public boolean isOutgoing() {
         return mOutgoing;
     }
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 159e165..606f00a 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -21,6 +21,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -108,6 +109,7 @@
      * receive.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_ACTIVE_DEVICE_CHANGED =
             "android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED";
 
@@ -401,6 +403,7 @@
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setActiveDevice(@Nullable BluetoothDevice device) {
         if (DBG) log("setActiveDevice(" + device + ")");
         try {
@@ -432,6 +435,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
+    @UnsupportedAppUsage
     public List<BluetoothDevice> getActiveDevices() {
         if (VDBG) log("getActiveDevices()");
         try {
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 0fa1d5d..98c23c6 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -233,6 +234,7 @@
      * @param device Remote Bluetooth Device
      * @return false on error, true otherwise
      */
+    @UnsupportedAppUsage
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
         final IBluetoothMap service = mService;
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 4f21d93..183be5f 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -358,6 +359,7 @@
      * @param deliveredIntent intent issued when message is delivered
      * @return true if the message is enqueued, false on error
      */
+    @UnsupportedAppUsage
     public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
             PendingIntent sentIntent, PendingIntent deliveredIntent) {
         if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 9f401eb..58be732 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -129,6 +130,7 @@
      * Create a BluetoothPan proxy object for interacting with the local
      * Bluetooth Service which handles the Pan profile
      */
+    @UnsupportedAppUsage
     /*package*/ BluetoothPan(Context context, ServiceListener l) {
         mContext = context;
         mServiceListener = l;
@@ -142,6 +144,7 @@
         doBind();
     }
 
+    @UnsupportedAppUsage
     boolean doBind() {
         Intent intent = new Intent(IBluetoothPan.class.getName());
         ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
@@ -154,6 +157,7 @@
         return true;
     }
 
+    @UnsupportedAppUsage
     /*package*/ void close() {
         if (VDBG) log("close()");
 
@@ -236,6 +240,7 @@
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
         final IBluetoothPan service = mPanService;
@@ -276,6 +281,7 @@
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
         final IBluetoothPan service = mPanService;
@@ -348,6 +354,7 @@
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
+    @UnsupportedAppUsage
     public void setBluetoothTethering(boolean value) {
         if (DBG) log("setBluetoothTethering(" + value + ")");
         final IBluetoothPan service = mPanService;
@@ -360,6 +367,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public boolean isTetheringOn() {
         if (VDBG) log("isTetheringOn()");
         final IBluetoothPan service = mPanService;
@@ -392,14 +400,17 @@
         }
     };
 
+    @UnsupportedAppUsage
     private boolean isEnabled() {
         return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
+    @UnsupportedAppUsage
     private static boolean isValidDevice(BluetoothDevice device) {
         return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
+    @UnsupportedAppUsage
     private static void log(String msg) {
         Log.d(TAG, msg);
     }
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index c60e9e0..ae264e1 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.annotation.SdkConstant;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -281,6 +282,7 @@
      */
     // TODO: This is currently being used by SettingsLib and will be used in the future.
     // TODO: Must specify target device. Implement this in the service.
+    @UnsupportedAppUsage
     public boolean disconnect(BluetoothDevice device) {
         log("disconnect()");
         final IBluetoothPbap service = mService;
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 6aeb94d..9777b5c 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -20,6 +20,7 @@
 import android.Manifest;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 
 import java.util.List;
 
@@ -85,6 +86,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     int PAN = 5;
 
     /**
@@ -122,6 +124,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     int A2DP_SINK = 11;
 
     /**
@@ -129,6 +132,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     int AVRCP_CONTROLLER = 12;
 
     /**
@@ -192,6 +196,7 @@
      *
      * @hide
      **/
+    @UnsupportedAppUsage
     int PRIORITY_AUTO_CONNECT = 1000;
 
     /**
@@ -217,6 +222,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     int PRIORITY_UNDEFINED = -1;
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index c51e39a..1b73206 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -280,6 +281,7 @@
      * @return false on error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
         final IBluetoothSap service = mService;
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index ebb7f18..ba4b5a5 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.ParcelUuid;
 import android.util.Log;
@@ -69,6 +70,7 @@
 
     private static final String TAG = "BluetoothServerSocket";
     private static final boolean DBG = false;
+    @UnsupportedAppUsage
     /*package*/ final BluetoothSocket mSocket;
     private Handler mHandler;
     private int mMessage;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 09a5b59..780f896 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.LocalSocket;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelUuid;
@@ -110,6 +111,7 @@
     public static final int TYPE_L2CAP_LE = 4;
 
     /*package*/ static final int EBADFD = 77;
+    @UnsupportedAppUsage
     /*package*/ static final int EADDRINUSE = 98;
 
     /*package*/ static final int SEC_FLAG_ENCRYPT = 1;
@@ -129,10 +131,13 @@
     private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */
     private boolean mAuthMitm = false;   /* when true Man-in-the-middle protection will be enabled*/
     private boolean mMin16DigitPin = false; /* Minimum 16 digit pin for sec mode 2 connections */
+    @UnsupportedAppUsage
     private ParcelFileDescriptor mPfd;
+    @UnsupportedAppUsage
     private LocalSocket mSocket;
     private InputStream mSocketIS;
     private OutputStream mSocketOS;
+    @UnsupportedAppUsage
     private int mPort;  /* RFCOMM channel or L2CAP psm */
     private int mFd;
     private String mServiceName;
@@ -517,6 +522,7 @@
      *
      * @throws IOException if an i/o error occurs.
      */
+    @UnsupportedAppUsage
     /*package*/ void flush() throws IOException {
         if (mSocketOS == null) throw new IOException("flush is called on null OutputStream");
         if (VDBG) Log.d(TAG, "flush: " + mSocketOS);
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 605dbd2..fdbfec0 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.ParcelUuid;
 
 import java.nio.ByteBuffer;
@@ -37,16 +38,20 @@
      * The following 128 bit values are calculated as:
      *  uuid * 2^96 + BASE_UUID
      */
+    @UnsupportedAppUsage
     public static final ParcelUuid AudioSink =
             ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid AudioSource =
             ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
+    @UnsupportedAppUsage
     public static final ParcelUuid AdvAudioDist =
             ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB");
+    @UnsupportedAppUsage
     public static final ParcelUuid HSP =
             ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid HSP_AG =
             ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB");
+    @UnsupportedAppUsage
     public static final ParcelUuid Handsfree =
             ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid Handsfree_AG =
@@ -55,20 +60,24 @@
             ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid AvrcpTarget =
             ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB");
+    @UnsupportedAppUsage
     public static final ParcelUuid ObexObjectPush =
             ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
     public static final ParcelUuid Hid =
             ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb");
+    @UnsupportedAppUsage
     public static final ParcelUuid Hogp =
             ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb");
     public static final ParcelUuid PANU =
             ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB");
+    @UnsupportedAppUsage
     public static final ParcelUuid NAP =
             ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid BNEP =
             ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid PBAP_PCE =
             ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB");
+    @UnsupportedAppUsage
     public static final ParcelUuid PBAP_PSE =
             ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid MAP =
@@ -92,10 +101,12 @@
     /** Length of bytes for 128 bit UUID */
     public static final int UUID_BYTES_128_BIT = 16;
 
+    @UnsupportedAppUsage
     public static final ParcelUuid[] RESERVED_UUIDS = {
             AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
             ObexObjectPush, PANU, NAP, MAP, MNS, MAS, SAP};
 
+    @UnsupportedAppUsage
     public static boolean isAudioSource(ParcelUuid uuid) {
         return uuid.equals(AudioSource);
     }
@@ -104,6 +115,7 @@
         return uuid.equals(AudioSink);
     }
 
+    @UnsupportedAppUsage
     public static boolean isAdvAudioDist(ParcelUuid uuid) {
         return uuid.equals(AdvAudioDist);
     }
@@ -120,6 +132,7 @@
         return uuid.equals(AvrcpController);
     }
 
+    @UnsupportedAppUsage
     public static boolean isAvrcpTarget(ParcelUuid uuid) {
         return uuid.equals(AvrcpTarget);
     }
@@ -162,6 +175,7 @@
      * @param uuidArray - Array of ParcelUuids
      * @param uuid
      */
+    @UnsupportedAppUsage
     public static boolean isUuidPresent(ParcelUuid[] uuidArray, ParcelUuid uuid) {
         if ((uuidArray == null || uuidArray.length == 0) && uuid == null) {
             return true;
@@ -183,6 +197,7 @@
      * @param uuidA - List of ParcelUuids
      * @param uuidB - List of ParcelUuids
      */
+    @UnsupportedAppUsage
     public static boolean containsAnyUuid(ParcelUuid[] uuidA, ParcelUuid[] uuidB) {
         if (uuidA == null && uuidB == null) return true;
 
@@ -330,6 +345,7 @@
      * @param parcelUuid
      * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise.
      */
+    @UnsupportedAppUsage
     public static boolean is16BitUuid(ParcelUuid parcelUuid) {
         UUID uuid = parcelUuid.getUuid();
         if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
@@ -345,6 +361,7 @@
      * @param parcelUuid
      * @return true if the parcelUuid can be converted to 32 bit uuid, false otherwise.
      */
+    @UnsupportedAppUsage
     public static boolean is32BitUuid(ParcelUuid parcelUuid) {
         UUID uuid = parcelUuid.getUuid();
         if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 0fb4ba1..13c5ff6 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -411,7 +411,14 @@
         try {
             gatt = mBluetoothManager.getBluetoothGatt();
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
+            Log.e(TAG, "Failed to get Bluetooth GATT - ", e);
+            postStartSetFailure(handler, callback,
+                    AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+            return;
+        }
+
+        if (gatt == null) {
+            Log.e(TAG, "Bluetooth GATT is null");
             postStartSetFailure(handler, callback,
                     AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
             return;
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 347fc4d..ac126ae 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -275,7 +275,9 @@
     }
 
     /**
-     * Stops an ongoing Bluetooth LE scan started using a PendingIntent.
+     * Stops an ongoing Bluetooth LE scan started using a PendingIntent. When creating the
+     * PendingIntent parameter, please do not use the FLAG_CANCEL_CURRENT flag. Otherwise, the stop
+     * scan may have no effect.
      *
      * @param callbackIntent The PendingIntent that was used to start the scan.
      * @see #startScan(List, ScanSettings, PendingIntent)
@@ -441,8 +443,8 @@
                 if (status == BluetoothGatt.GATT_SUCCESS) {
                     try {
                         if (mScannerId == -1) {
-                            // Registration succeeds after timeout, unregister client.
-                            mBluetoothGatt.unregisterClient(scannerId);
+                            // Registration succeeds after timeout, unregister scanner.
+                            mBluetoothGatt.unregisterScanner(scannerId);
                         } else {
                             mScannerId = scannerId;
                             mBluetoothGatt.startScan(mScannerId, mSettings, mFilters,
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 04dd060..07ed18d 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -17,6 +17,7 @@
 package android.bluetooth.le;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.bluetooth.BluetoothUuid;
 import android.os.ParcelUuid;
 import android.util.ArrayMap;
@@ -174,6 +175,7 @@
      * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response.
      * @hide
      */
+    @UnsupportedAppUsage
     public static ScanRecord parseFromBytes(byte[] scanRecord) {
         if (scanRecord == null) {
             return null;
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
index 922224a..db54f08 100644
--- a/core/java/android/companion/AssociationRequest.java
+++ b/core/java/android/companion/AssociationRequest.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.provider.OneTimeUseBuilder;
@@ -59,12 +60,14 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean isSingleDevice() {
         return mSingleDevice;
     }
 
     /** @hide */
     @NonNull
+    @UnsupportedAppUsage
     public List<DeviceFilter<?>> getDeviceFilters() {
         return mDeviceFilters;
     }
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
index 84e1536..7507e17 100644
--- a/core/java/android/companion/BluetoothDeviceFilter.java
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -25,6 +25,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.bluetooth.BluetoothDevice;
 import android.os.Parcel;
 import android.os.ParcelUuid;
@@ -99,6 +100,7 @@
 
     /** @hide */
     @Nullable
+    @UnsupportedAppUsage
     public String getAddress() {
         return mAddress;
     }
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
index 4ee38fe..bd507a6 100644
--- a/core/java/android/companion/BluetoothDeviceFilterUtils.java
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.le.ScanFilter;
 import android.net.wifi.ScanResult;
@@ -124,14 +125,17 @@
         Log.i(LOG_TAG, getDeviceDisplayNameInternal(device) + (result ? " ~ " : " !~ ") + criteria);
     }
 
+    @UnsupportedAppUsage
     public static String getDeviceDisplayNameInternal(@NonNull BluetoothDevice device) {
         return firstNotEmpty(device.getAliasName(), device.getAddress());
     }
 
+    @UnsupportedAppUsage
     public static String getDeviceDisplayNameInternal(@NonNull ScanResult device) {
         return firstNotEmpty(device.SSID, device.BSSID);
     }
 
+    @UnsupportedAppUsage
     public static String getDeviceMacAddress(@NonNull Parcelable device) {
         if (device instanceof BluetoothDevice) {
             return ((BluetoothDevice) device).getAddress();
diff --git a/core/java/android/companion/BluetoothLeDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java
index 7fb768c..1de931e 100644
--- a/core/java/android/companion/BluetoothLeDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLeDeviceFilter.java
@@ -25,6 +25,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.le.ScanFilter;
 import android.bluetooth.le.ScanRecord;
@@ -92,6 +93,7 @@
 
     /** @hide */
     @NonNull
+    @UnsupportedAppUsage
     public ScanFilter getScanFilter() {
         return mScanFilter;
     }
diff --git a/core/java/android/companion/DeviceFilter.java b/core/java/android/companion/DeviceFilter.java
index 10135a4..dc7cf82 100644
--- a/core/java/android/companion/DeviceFilter.java
+++ b/core/java/android/companion/DeviceFilter.java
@@ -19,6 +19,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 
 import java.lang.annotation.Retention;
@@ -44,9 +45,11 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     boolean matches(D device);
 
     /** @hide */
+    @UnsupportedAppUsage
     String getDeviceDisplayName(D device);
 
     /**  @hide */
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index c44e356..bb7d5e4 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.OperationCanceledException;
@@ -128,6 +129,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private final Executor mExecutor;
 
     volatile LoadTask mTask;
@@ -354,6 +356,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void waitForLoader() {
         LoadTask task = mTask;
         if (task != null) {
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 58a9183..b55fe76 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.IActivityManager;
@@ -43,6 +44,7 @@
  *
  */
 public abstract class BroadcastReceiver {
+    @UnsupportedAppUsage
     private PendingResult mPendingResult;
     private boolean mDebugUnregister;
 
@@ -69,20 +71,32 @@
         /** @hide */
         public static final int TYPE_UNREGISTERED = 2;
 
+        @UnsupportedAppUsage
         final int mType;
+        @UnsupportedAppUsage
         final boolean mOrderedHint;
+        @UnsupportedAppUsage
         final boolean mInitialStickyHint;
+        @UnsupportedAppUsage
         final IBinder mToken;
+        @UnsupportedAppUsage
         final int mSendingUser;
+        @UnsupportedAppUsage
         final int mFlags;
 
+        @UnsupportedAppUsage
         int mResultCode;
+        @UnsupportedAppUsage
         String mResultData;
+        @UnsupportedAppUsage
         Bundle mResultExtras;
+        @UnsupportedAppUsage
         boolean mAbortBroadcast;
+        @UnsupportedAppUsage
         boolean mFinished;
 
         /** @hide */
+        @UnsupportedAppUsage
         public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type,
                 boolean ordered, boolean sticky, IBinder token, int userId, int flags) {
             mResultCode = resultCode;
@@ -595,6 +609,7 @@
     /**
      * For internal use to set the result data that is active. @hide
      */
+    @UnsupportedAppUsage
     public final void setPendingResult(PendingResult result) {
         mPendingResult = result;
     }
@@ -602,6 +617,7 @@
     /**
      * For internal use to set the result data that is active. @hide
      */
+    @UnsupportedAppUsage
     public final PendingResult getPendingResult() {
         return mPendingResult;
     }
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 94e1e2d..2b7ea66 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -21,6 +21,7 @@
 import static android.content.ContentResolver.SCHEME_CONTENT;
 import static android.content.ContentResolver.SCHEME_FILE;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.graphics.Bitmap;
 import android.net.Uri;
@@ -197,6 +198,7 @@
         final CharSequence mText;
         final String mHtmlText;
         final Intent mIntent;
+        @UnsupportedAppUsage
         Uri mUri;
 
         /** @hide */
@@ -912,6 +914,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public Bitmap getIcon() {
         return mIcon;
     }
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index 73b6eb2..3fe17840 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -82,6 +83,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public ClipboardManager(Context context, Handler handler) throws ServiceNotFoundException {
         mContext = context;
         mHandler = handler;
@@ -93,6 +95,9 @@
      * Sets the current primary clip on the clipboard.  This is the clip that
      * is involved in normal cut and paste operations.
      *
+     * <em>If the application is not the default IME or does not have input focus this will have
+     * no effect.</em>
+     *
      * @param clip The clipped data item to set.
      * @see #getPrimaryClip()
      * @see #clearPrimaryClip()
@@ -110,6 +115,9 @@
     /**
      * Clears any current primary clip on the clipboard.
      *
+     * <em>If the application is not the default IME or does not have input focus this will have
+     * no effect.</em>
+     *
      * @see #setPrimaryClip(ClipData)
      */
     public void clearPrimaryClip() {
@@ -123,6 +131,9 @@
     /**
      * Returns the current primary clip on the clipboard.
      *
+     * <em>If the application is not the default IME or does not have input focus this return
+     * {@code null}.</em>
+     *
      * @see #setPrimaryClip(ClipData)
      */
     public @Nullable ClipData getPrimaryClip() {
@@ -137,6 +148,9 @@
      * Returns a description of the current primary clip on the clipboard
      * but not a copy of its data.
      *
+     * <em>If the application is not the default IME or does not have input focus this return
+     * {@code null}.</em>
+     *
      * @see #setPrimaryClip(ClipData)
      */
     public @Nullable ClipDescription getPrimaryClipDescription() {
@@ -149,6 +163,9 @@
 
     /**
      * Returns true if there is currently a primary clip on the clipboard.
+     *
+     * <em>If the application is not the default IME or the does not have input focus this will
+     * return {@code false}.</em>
      */
     public boolean hasPrimaryClip() {
         try {
@@ -221,6 +238,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void reportPrimaryClipChanged() {
         Object[] listeners;
 
diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java
index fc58533..54e6342 100644
--- a/core/java/android/content/ComponentName.java
+++ b/core/java/android/content/ComponentName.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -229,12 +230,14 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void appendShortString(StringBuilder sb, String packageName, String className) {
         sb.append(packageName).append('/');
         appendShortClassName(sb, packageName, className);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void printShortString(PrintWriter pw, String packageName, String className) {
         pw.print(packageName);
         pw.print('/');
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index cdeaea3..085d77d 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -21,9 +21,11 @@
 import static android.app.AppOpsManager.MODE_ERRORED;
 import static android.app.AppOpsManager.MODE_IGNORED;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Trace.TRACE_TAG_DATABASE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.AppOpsManager;
 import android.content.pm.PathPermission;
 import android.content.pm.ProviderInfo;
@@ -42,6 +44,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.text.TextUtils;
@@ -105,15 +108,21 @@
      *       MockContentProvider.
      */
 
+    @UnsupportedAppUsage
     private Context mContext = null;
     private int mMyUid;
 
     // Since most Providers have only one authority, we keep both a String and a String[] to improve
     // performance.
+    @UnsupportedAppUsage
     private String mAuthority;
+    @UnsupportedAppUsage
     private String[] mAuthorities;
+    @UnsupportedAppUsage
     private String mReadPermission;
+    @UnsupportedAppUsage
     private String mWritePermission;
+    @UnsupportedAppUsage
     private PathPermission[] mPathPermissions;
     private boolean mExported;
     private boolean mNoPerms;
@@ -154,6 +163,7 @@
      * in the test, which is available via {@link #getPathPermissions()}.
      * @hide
      */
+    @UnsupportedAppUsage
     public ContentProvider(
             Context context,
             String readPermission,
@@ -178,6 +188,7 @@
      * ContentProvider instance.  Otherwise returns {@code null}.
      * @hide
      */
+    @UnsupportedAppUsage
     public static ContentProvider coerceToLocalContentProvider(
             IContentProvider abstractInterface) {
         if (abstractInterface instanceof Transport) {
@@ -235,6 +246,7 @@
                 // Return an empty cursor for all columns.
                 return new MatrixCursor(cursor.getColumnNames(), 0);
             }
+            Trace.traceBegin(TRACE_TAG_DATABASE, "query");
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.query(
@@ -242,6 +254,7 @@
                         CancellationSignal.fromTransport(cancellationSignal));
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -249,7 +262,12 @@
         public String getType(Uri uri) {
             validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            return ContentProvider.this.getType(uri);
+            Trace.traceBegin(TRACE_TAG_DATABASE, "getType");
+            try {
+                return ContentProvider.this.getType(uri);
+            } finally {
+                Trace.traceEnd(TRACE_TAG_DATABASE);
+            }
         }
 
         @Override
@@ -260,11 +278,13 @@
             if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return rejectInsert(uri, initialValues);
             }
+            Trace.traceBegin(TRACE_TAG_DATABASE, "insert");
             final String original = setCallingPackage(callingPkg);
             try {
                 return maybeAddUserId(ContentProvider.this.insert(uri, initialValues), userId);
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -275,11 +295,13 @@
             if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return 0;
             }
+            Trace.traceBegin(TRACE_TAG_DATABASE, "bulkInsert");
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.bulkInsert(uri, initialValues);
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -312,6 +334,7 @@
                     }
                 }
             }
+            Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch");
             final String original = setCallingPackage(callingPkg);
             try {
                 ContentProviderResult[] results = ContentProvider.this.applyBatch(operations);
@@ -326,6 +349,7 @@
                 return results;
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -336,11 +360,13 @@
             if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return 0;
             }
+            Trace.traceBegin(TRACE_TAG_DATABASE, "delete");
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.delete(uri, selection, selectionArgs);
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -352,11 +378,13 @@
             if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return 0;
             }
+            Trace.traceBegin(TRACE_TAG_DATABASE, "update");
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.update(uri, values, selection, selectionArgs);
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -367,12 +395,14 @@
             validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(callingPkg, uri, mode, callerToken);
+            Trace.traceBegin(TRACE_TAG_DATABASE, "openFile");
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.openFile(
                         uri, mode, CancellationSignal.fromTransport(cancellationSignal));
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -383,12 +413,14 @@
             validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(callingPkg, uri, mode, null);
+            Trace.traceBegin(TRACE_TAG_DATABASE, "openAssetFile");
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.openAssetFile(
                         uri, mode, CancellationSignal.fromTransport(cancellationSignal));
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -396,11 +428,13 @@
         public Bundle call(
                 String callingPkg, String method, @Nullable String arg, @Nullable Bundle extras) {
             Bundle.setDefusable(extras, true);
+            Trace.traceBegin(TRACE_TAG_DATABASE, "call");
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.call(method, arg, extras);
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -408,7 +442,12 @@
         public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
             validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
+            Trace.traceBegin(TRACE_TAG_DATABASE, "getStreamTypes");
+            try {
+                return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
+            } finally {
+                Trace.traceEnd(TRACE_TAG_DATABASE);
+            }
         }
 
         @Override
@@ -418,12 +457,14 @@
             validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(callingPkg, uri, "r", null);
+            Trace.traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile");
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.openTypedAssetFile(
                         uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal));
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -440,11 +481,13 @@
             if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return null;
             }
+            Trace.traceBegin(TRACE_TAG_DATABASE, "canonicalize");
             final String original = setCallingPackage(callingPkg);
             try {
                 return maybeAddUserId(ContentProvider.this.canonicalize(uri), userId);
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -456,11 +499,13 @@
             if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return null;
             }
+            Trace.traceBegin(TRACE_TAG_DATABASE, "uncanonicalize");
             final String original = setCallingPackage(callingPkg);
             try {
                 return maybeAddUserId(ContentProvider.this.uncanonicalize(uri), userId);
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -472,12 +517,14 @@
             if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
+            Trace.traceBegin(TRACE_TAG_DATABASE, "refresh");
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.refresh(uri, args,
                         CancellationSignal.fromTransport(cancellationSignal));
             } finally {
                 setCallingPackage(original);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -849,6 +896,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public final void setAppOps(int readOp, int writeOp) {
         if (!mNoPerms) {
             mTransport.mReadOp = readOp;
@@ -1868,6 +1916,7 @@
      * @return the Binder object for this provider
      * @hide
      */
+    @UnsupportedAppUsage
     public IContentProvider getIContentProvider() {
         return mTransport;
     }
@@ -1877,6 +1926,7 @@
      * when directly instantiating the provider for testing.
      * @hide
      */
+    @UnsupportedAppUsage
     public void attachInfoForTesting(Context context, ProviderInfo info) {
         attachInfo(context, info, true);
     }
@@ -2096,6 +2146,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static Uri maybeAddUserId(Uri uri, int userId) {
         if (uri == null) return null;
         if (userId != UserHandle.USER_CURRENT
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 2d490a0..04be572 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.database.CrossProcessCursorWrapper;
 import android.database.Cursor;
@@ -39,6 +40,8 @@
 
 import dalvik.system.CloseGuard;
 
+import libcore.io.IoUtils;
+
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -68,7 +71,9 @@
     private static Handler sAnrHandler;
 
     private final ContentResolver mContentResolver;
+    @UnsupportedAppUsage
     private final IContentProvider mContentProvider;
+    @UnsupportedAppUsage
     private final String mPackageName;
     private final boolean mStable;
 
@@ -560,14 +565,17 @@
         return ContentProvider.coerceToLocalContentProvider(mContentProvider);
     }
 
+    /**
+     * Closes the given object quietly, ignoring any checked exceptions. Does
+     * nothing if the given object is {@code null}.
+     */
+    public static void closeQuietly(ContentProviderClient client) {
+        IoUtils.closeQuietly(client);
+    }
+
     /** {@hide} */
     public static void releaseQuietly(ContentProviderClient client) {
-        if (client != null) {
-            try {
-                client.release();
-            } catch (Exception ignored) {
-            }
-        }
+        IoUtils.closeQuietly(client);
     }
 
     private class NotRespondingRunnable implements Runnable {
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index d428a3a..6bede13 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.database.BulkCursorDescriptor;
 import android.database.BulkCursorToCursorAdaptor;
@@ -50,6 +51,7 @@
      * Cast a Binder object into a content resolver interface, generating
      * a proxy if needed.
      */
+    @UnsupportedAppUsage
     static public IContentProvider asInterface(IBinder obj)
     {
         if (obj == null) {
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 8f3a317..e3d9b19 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProvider;
 import android.database.Cursor;
 import android.net.Uri;
@@ -35,16 +36,22 @@
  */
 public class ContentProviderOperation implements Parcelable {
     /** @hide exposed for unit tests */
+    @UnsupportedAppUsage
     public final static int TYPE_INSERT = 1;
     /** @hide exposed for unit tests */
+    @UnsupportedAppUsage
     public final static int TYPE_UPDATE = 2;
     /** @hide exposed for unit tests */
+    @UnsupportedAppUsage
     public final static int TYPE_DELETE = 3;
     /** @hide exposed for unit tests */
     public final static int TYPE_ASSERT = 4;
 
+    @UnsupportedAppUsage
     private final int mType;
+    @UnsupportedAppUsage
     private final Uri mUri;
+    @UnsupportedAppUsage
     private final String mSelection;
     private final String[] mSelectionArgs;
     private final ContentValues mValues;
@@ -218,6 +225,7 @@
     }
 
     /** @hide exposed for unit tests */
+    @UnsupportedAppUsage
     public int getType() {
         return mType;
     }
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index af09f15..5867a9c 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -22,10 +22,12 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.AppGlobals;
+import android.app.UriGrantsManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
@@ -260,6 +262,13 @@
      */
     public static final String QUERY_ARG_SQL_SORT_ORDER = "android:query-arg-sql-sort-order";
 
+    /** {@hide} */
+    public static final String QUERY_ARG_SQL_GROUP_BY = "android:query-arg-sql-group-by";
+    /** {@hide} */
+    public static final String QUERY_ARG_SQL_HAVING = "android:query-arg-sql-having";
+    /** {@hide} */
+    public static final String QUERY_ARG_SQL_LIMIT = "android:query-arg-sql-limit";
+
     /**
      * Specifies the list of columns against which to sort results. When first column values
      * are identical, records are then sorted based on second column values, and so on.
@@ -429,6 +438,7 @@
     public static final String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
     /** @hide */
     public static final int SYNC_ERROR_AUTHENTICATION = 2;
@@ -485,6 +495,7 @@
     public static final int SYNC_OBSERVER_TYPE_PENDING = 1<<1;
     public static final int SYNC_OBSERVER_TYPE_ACTIVE = 1<<2;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SYNC_OBSERVER_TYPE_STATUS = 1<<3;
     /** @hide */
     public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
@@ -567,6 +578,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     protected abstract IContentProvider acquireProvider(Context c, String name);
 
     /**
@@ -576,17 +588,22 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected IContentProvider acquireExistingProvider(Context c, String name) {
         return acquireProvider(c, name);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public abstract boolean releaseProvider(IContentProvider icp);
     /** @hide */
+    @UnsupportedAppUsage
     protected abstract IContentProvider acquireUnstableProvider(Context c, String name);
     /** @hide */
+    @UnsupportedAppUsage
     public abstract boolean releaseUnstableProvider(IContentProvider icp);
     /** @hide */
+    @UnsupportedAppUsage
     public abstract void unstableProviderDied(IContentProvider icp);
 
     /** @hide */
@@ -1520,7 +1537,9 @@
      * @hide
      */
     public class OpenResourceIdResult {
+        @UnsupportedAppUsage
         public Resources r;
+        @UnsupportedAppUsage
         public int id;
     }
 
@@ -1529,6 +1548,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
         String authority = uri.getAuthority();
         Resources r;
@@ -1774,6 +1794,7 @@
      * @return The ContentProvider for the given URI, or null if no content provider is found.
      * @hide
      */
+    @UnsupportedAppUsage
     public final IContentProvider acquireProvider(Uri uri) {
         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
             return null;
@@ -1793,6 +1814,7 @@
      * @return The ContentProvider for the given URI, or null if no content provider is found.
      * @hide
      */
+    @UnsupportedAppUsage
     public final IContentProvider acquireExistingProvider(Uri uri) {
         if (!SCHEME_CONTENT.equals(uri.getScheme())) {
             return null;
@@ -1807,6 +1829,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public final IContentProvider acquireProvider(String name) {
         if (name == null) {
             return null;
@@ -1835,6 +1858,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public final IContentProvider acquireUnstableProvider(String name) {
         if (name == null) {
             return null;
@@ -1968,6 +1992,7 @@
     }
 
     /** @hide - designated user version */
+    @UnsupportedAppUsage
     public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
             ContentObserver observer, @UserIdInt int userHandle) {
         try {
@@ -2136,7 +2161,7 @@
             @Intent.AccessUriMode int modeFlags) {
         Preconditions.checkNotNull(uri, "uri");
         try {
-            ActivityManager.getService().takePersistableUriPermission(
+            UriGrantsManager.getService().takePersistableUriPermission(
                     ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
                     resolveUserId(uri));
         } catch (RemoteException e) {
@@ -2147,12 +2172,13 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void takePersistableUriPermission(@NonNull String toPackage, @NonNull Uri uri,
             @Intent.AccessUriMode int modeFlags) {
         Preconditions.checkNotNull(toPackage, "toPackage");
         Preconditions.checkNotNull(uri, "uri");
         try {
-            ActivityManager.getService().takePersistableUriPermission(
+            UriGrantsManager.getService().takePersistableUriPermission(
                     ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage,
                     resolveUserId(uri));
         } catch (RemoteException e) {
@@ -2172,7 +2198,7 @@
             @Intent.AccessUriMode int modeFlags) {
         Preconditions.checkNotNull(uri, "uri");
         try {
-            ActivityManager.getService().releasePersistableUriPermission(
+            UriGrantsManager.getService().releasePersistableUriPermission(
                     ContentProvider.getUriWithoutUserId(uri), modeFlags, /* toPackage= */ null,
                     resolveUserId(uri));
         } catch (RemoteException e) {
@@ -2192,7 +2218,7 @@
      */
     public @NonNull List<UriPermission> getPersistedUriPermissions() {
         try {
-            return ActivityManager.getService()
+            return UriGrantsManager.getService()
                     .getPersistedUriPermissions(mPackageName, true).getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -2208,7 +2234,7 @@
      */
     public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() {
         try {
-            return ActivityManager.getService()
+            return UriGrantsManager.getService()
                     .getPersistedUriPermissions(mPackageName, false).getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -2781,6 +2807,7 @@
      * @return the SyncStatusInfo for the authority, or null if none exists
      * @hide
      */
+    @UnsupportedAppUsage
     public static SyncStatusInfo getSyncStatus(Account account, String authority) {
         try {
             return getContentService().getSyncStatus(account, authority, null);
@@ -2793,6 +2820,7 @@
      * @see #getSyncStatus(Account, String)
      * @hide
      */
+    @UnsupportedAppUsage
     public static SyncStatusInfo getSyncStatusAsUser(Account account, String authority,
             @UserIdInt int userId) {
         try {
@@ -3035,6 +3063,7 @@
     public static final String CONTENT_SERVICE_NAME = "content";
 
     /** @hide */
+    @UnsupportedAppUsage
     public static IContentService getContentService() {
         if (sContentService != null) {
             return sContentService;
@@ -3045,13 +3074,17 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public String getPackageName() {
         return mPackageName;
     }
 
+    @UnsupportedAppUsage
     private static volatile IContentService sContentService;
+    @UnsupportedAppUsage
     private final Context mContext;
 
+    @UnsupportedAppUsage
     final String mPackageName;
     final int mTargetSdkVersion;
 
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
index 6f93798..06d0f66 100644
--- a/core/java/android/content/ContentValues.java
+++ b/core/java/android/content/ContentValues.java
@@ -16,13 +16,18 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.ArrayMap;
 import android.util.Log;
 
+import com.android.internal.util.Preconditions;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -32,16 +37,21 @@
 public final class ContentValues implements Parcelable {
     public static final String TAG = "ContentValues";
 
-    /** Holds the actual values */
+    /**
+     * @hide
+     * @deprecated kept around for lame people doing reflection
+     */
+    @Deprecated
+    @UnsupportedAppUsage
     private HashMap<String, Object> mValues;
 
+    private final ArrayMap<String, Object> mMap;
+
     /**
      * Creates an empty set of values using the default initial size
      */
     public ContentValues() {
-        // Choosing a default size of 8 based on analysis of typical
-        // consumption by applications.
-        mValues = new HashMap<String, Object>(8);
+        mMap = new ArrayMap<>();
     }
 
     /**
@@ -50,7 +60,8 @@
      * @param size the initial size of the set of values
      */
     public ContentValues(int size) {
-        mValues = new HashMap<String, Object>(size, 1.0f);
+        Preconditions.checkArgumentNonnegative(size);
+        mMap = new ArrayMap<>(size);
     }
 
     /**
@@ -59,18 +70,25 @@
      * @param from the values to copy
      */
     public ContentValues(ContentValues from) {
-        mValues = new HashMap<String, Object>(from.mValues);
+        Objects.requireNonNull(from);
+        mMap = new ArrayMap<>(from.mMap);
     }
 
     /**
-     * Creates a set of values copied from the given HashMap. This is used
-     * by the Parcel unmarshalling code.
-     *
-     * @param values the values to start with
-     * {@hide}
+     * @hide
+     * @deprecated kept around for lame people doing reflection
      */
-    private ContentValues(HashMap<String, Object> values) {
-        mValues = values;
+    @Deprecated
+    @UnsupportedAppUsage
+    private ContentValues(HashMap<String, Object> from) {
+        mMap = new ArrayMap<>();
+        mMap.putAll(from);
+    }
+
+    /** {@hide} */
+    private ContentValues(Parcel in) {
+        mMap = new ArrayMap<>(in.readInt());
+        in.readArrayMap(mMap, null);
     }
 
     @Override
@@ -78,12 +96,17 @@
         if (!(object instanceof ContentValues)) {
             return false;
         }
-        return mValues.equals(((ContentValues) object).mValues);
+        return mMap.equals(((ContentValues) object).mMap);
+    }
+
+    /** {@hide} */
+    public ArrayMap<String, Object> getValues() {
+        return mMap;
     }
 
     @Override
     public int hashCode() {
-        return mValues.hashCode();
+        return mMap.hashCode();
     }
 
     /**
@@ -93,7 +116,7 @@
      * @param value the data for the value to put
      */
     public void put(String key, String value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -102,7 +125,7 @@
      * @param other the ContentValues from which to copy
      */
     public void putAll(ContentValues other) {
-        mValues.putAll(other.mValues);
+        mMap.putAll(other.mMap);
     }
 
     /**
@@ -112,7 +135,7 @@
      * @param value the data for the value to put
      */
     public void put(String key, Byte value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -122,7 +145,7 @@
      * @param value the data for the value to put
      */
     public void put(String key, Short value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -132,7 +155,7 @@
      * @param value the data for the value to put
      */
     public void put(String key, Integer value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -142,7 +165,7 @@
      * @param value the data for the value to put
      */
     public void put(String key, Long value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -152,7 +175,7 @@
      * @param value the data for the value to put
      */
     public void put(String key, Float value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -162,7 +185,7 @@
      * @param value the data for the value to put
      */
     public void put(String key, Double value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -172,7 +195,7 @@
      * @param value the data for the value to put
      */
     public void put(String key, Boolean value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -182,7 +205,7 @@
      * @param value the data for the value to put
      */
     public void put(String key, byte[] value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -191,7 +214,7 @@
      * @param key the name of the value to make null
      */
     public void putNull(String key) {
-        mValues.put(key, null);
+        mMap.put(key, null);
     }
 
     /**
@@ -200,7 +223,7 @@
      * @return the number of values
      */
     public int size() {
-        return mValues.size();
+        return mMap.size();
     }
 
     /**
@@ -211,7 +234,7 @@
      * TODO: consider exposing this new method publicly
      */
     public boolean isEmpty() {
-        return mValues.isEmpty();
+        return mMap.isEmpty();
     }
 
     /**
@@ -220,14 +243,14 @@
      * @param key the name of the value to remove
      */
     public void remove(String key) {
-        mValues.remove(key);
+        mMap.remove(key);
     }
 
     /**
      * Removes all values.
      */
     public void clear() {
-        mValues.clear();
+        mMap.clear();
     }
 
     /**
@@ -237,7 +260,7 @@
      * @return {@code true} if the value is present, {@code false} otherwise
      */
     public boolean containsKey(String key) {
-        return mValues.containsKey(key);
+        return mMap.containsKey(key);
     }
 
     /**
@@ -249,7 +272,7 @@
      *         was previously added with the given {@code key}
      */
     public Object get(String key) {
-        return mValues.get(key);
+        return mMap.get(key);
     }
 
     /**
@@ -259,7 +282,7 @@
      * @return the String for the value
      */
     public String getAsString(String key) {
-        Object value = mValues.get(key);
+        Object value = mMap.get(key);
         return value != null ? value.toString() : null;
     }
 
@@ -270,7 +293,7 @@
      * @return the Long value, or {@code null} if the value is missing or cannot be converted
      */
     public Long getAsLong(String key) {
-        Object value = mValues.get(key);
+        Object value = mMap.get(key);
         try {
             return value != null ? ((Number) value).longValue() : null;
         } catch (ClassCastException e) {
@@ -295,7 +318,7 @@
      * @return the Integer value, or {@code null} if the value is missing or cannot be converted
      */
     public Integer getAsInteger(String key) {
-        Object value = mValues.get(key);
+        Object value = mMap.get(key);
         try {
             return value != null ? ((Number) value).intValue() : null;
         } catch (ClassCastException e) {
@@ -320,7 +343,7 @@
      * @return the Short value, or {@code null} if the value is missing or cannot be converted
      */
     public Short getAsShort(String key) {
-        Object value = mValues.get(key);
+        Object value = mMap.get(key);
         try {
             return value != null ? ((Number) value).shortValue() : null;
         } catch (ClassCastException e) {
@@ -345,7 +368,7 @@
      * @return the Byte value, or {@code null} if the value is missing or cannot be converted
      */
     public Byte getAsByte(String key) {
-        Object value = mValues.get(key);
+        Object value = mMap.get(key);
         try {
             return value != null ? ((Number) value).byteValue() : null;
         } catch (ClassCastException e) {
@@ -370,7 +393,7 @@
      * @return the Double value, or {@code null} if the value is missing or cannot be converted
      */
     public Double getAsDouble(String key) {
-        Object value = mValues.get(key);
+        Object value = mMap.get(key);
         try {
             return value != null ? ((Number) value).doubleValue() : null;
         } catch (ClassCastException e) {
@@ -395,7 +418,7 @@
      * @return the Float value, or {@code null} if the value is missing or cannot be converted
      */
     public Float getAsFloat(String key) {
-        Object value = mValues.get(key);
+        Object value = mMap.get(key);
         try {
             return value != null ? ((Number) value).floatValue() : null;
         } catch (ClassCastException e) {
@@ -420,7 +443,7 @@
      * @return the Boolean value, or {@code null} if the value is missing or cannot be converted
      */
     public Boolean getAsBoolean(String key) {
-        Object value = mValues.get(key);
+        Object value = mMap.get(key);
         try {
             return (Boolean) value;
         } catch (ClassCastException e) {
@@ -448,7 +471,7 @@
      *         {@code byte[]}
      */
     public byte[] getAsByteArray(String key) {
-        Object value = mValues.get(key);
+        Object value = mMap.get(key);
         if (value instanceof byte[]) {
             return (byte[]) value;
         } else {
@@ -462,7 +485,7 @@
      * @return a set of all of the keys and values
      */
     public Set<Map.Entry<String, Object>> valueSet() {
-        return mValues.entrySet();
+        return mMap.entrySet();
     }
 
     /**
@@ -471,30 +494,31 @@
      * @return a set of all of the keys
      */
     public Set<String> keySet() {
-        return mValues.keySet();
+        return mMap.keySet();
     }
 
     public static final Parcelable.Creator<ContentValues> CREATOR =
             new Parcelable.Creator<ContentValues>() {
-        @SuppressWarnings({"deprecation", "unchecked"})
+        @Override
         public ContentValues createFromParcel(Parcel in) {
-            // TODO - what ClassLoader should be passed to readHashMap?
-            HashMap<String, Object> values = in.readHashMap(null);
-            return new ContentValues(values);
+            return new ContentValues(in);
         }
 
+        @Override
         public ContentValues[] newArray(int size) {
             return new ContentValues[size];
         }
     };
 
+    @Override
     public int describeContents() {
         return 0;
     }
 
-    @SuppressWarnings("deprecation")
+    @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeMap(mValues);
+        parcel.writeInt(mMap.size());
+        parcel.writeArrayMap(mMap);
     }
 
     /**
@@ -502,8 +526,9 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void putStringArrayList(String key, ArrayList<String> value) {
-        mValues.put(key, value);
+        mMap.put(key, value);
     }
 
     /**
@@ -512,8 +537,9 @@
      */
     @SuppressWarnings("unchecked")
     @Deprecated
+    @UnsupportedAppUsage
     public ArrayList<String> getStringArrayList(String key) {
-        return (ArrayList<String>) mValues.get(key);
+        return (ArrayList<String>) mMap.get(key);
     }
 
     /**
@@ -523,7 +549,7 @@
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        for (String name : mValues.keySet()) {
+        for (String name : mMap.keySet()) {
             String value = getAsString(name);
             if (sb.length() > 0) sb.append(" ");
             sb.append(name + "=" + value);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c515bce..a352e84 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -31,6 +31,7 @@
 import android.annotation.StyleableRes;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.IApplicationThread;
@@ -654,6 +655,7 @@
 
     /** @hide Needed for some internal implementation...  not public because
      * you can't assume this actually means anything. */
+    @UnsupportedAppUsage
     public int getThemeResId() {
         return 0;
     }
@@ -722,6 +724,7 @@
     public abstract String getPackageName();
 
     /** @hide Return the name of the base context this context is derived from. */
+    @UnsupportedAppUsage
     public abstract String getBasePackageName();
 
     /** @hide Return the package name that should be used for app ops calls from
@@ -764,6 +767,7 @@
      * @deprecated use {@link #getSharedPreferencesPath(String)}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public File getSharedPrefsFile(String name) {
         return getSharedPreferencesPath(name);
     }
@@ -1697,6 +1701,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+    @UnsupportedAppUsage
     public void startActivityAsUser(@RequiresPermission Intent intent, UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
@@ -1743,6 +1748,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+    @UnsupportedAppUsage
     public void startActivityAsUser(@RequiresPermission Intent intent, @Nullable Bundle options,
             UserHandle userId) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -1761,6 +1767,7 @@
      *          for building it manually.
      * @hide
      */
+    @UnsupportedAppUsage
     public void startActivityForResult(
             @NonNull String who, Intent intent, int requestCode, @Nullable Bundle options) {
         throw new RuntimeException("This method is only implemented for Activity-based Contexts. "
@@ -1772,6 +1779,7 @@
      * {@link #startActivityForResult(String, Intent, int, Bundle)}.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean canStartActivityForResult() {
         return false;
     }
@@ -2039,6 +2047,7 @@
      * of an associated app op as per {@link android.app.AppOpsManager}.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void sendBroadcast(Intent intent,
             String receiverPermission, int appOp);
 
@@ -2165,6 +2174,7 @@
      * of an associated app op as per {@link android.app.AppOpsManager}.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void sendOrderedBroadcast(Intent intent,
             String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
             Handler scheduler, int initialCode, String initialData,
@@ -2240,6 +2250,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+    @UnsupportedAppUsage
     public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, @Nullable String receiverPermission, int appOp);
 
@@ -2285,6 +2296,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+    @UnsupportedAppUsage
     public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
             @Nullable String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
             @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2297,6 +2309,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+    @UnsupportedAppUsage
     public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
             @Nullable String receiverPermission, int appOp, @Nullable Bundle options,
             BroadcastReceiver resultReceiver, @Nullable Handler scheduler, int initialCode,
@@ -2689,6 +2702,7 @@
      */
     @Nullable
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+    @UnsupportedAppUsage
     public abstract Intent registerReceiverAsUser(BroadcastReceiver receiver,
             UserHandle user, IntentFilter filter, @Nullable String broadcastPermission,
             @Nullable Handler scheduler);
@@ -2836,6 +2850,7 @@
      */
     @Nullable
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+    @UnsupportedAppUsage
     public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
 
     /**
@@ -2923,6 +2938,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+    @UnsupportedAppUsage
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
             Handler handler, UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -3340,6 +3356,16 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.app.UriGrantsManager} for interacting with the global system state.
+     *
+     * @see #getSystemService(String)
+     * @see android.app.UriGrantsManager
+     * @hide
+     */
+    public static final String URI_GRANTS_SERVICE = "uri_grants";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.app.AlarmManager} for receiving intents at a
      * time of your choosing.
      *
@@ -3405,6 +3431,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String COUNTRY_DETECTOR = "country_detector";
 
     /**
@@ -3474,6 +3501,7 @@
      * @see android.app.StatusBarManager
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String STATUS_BAR_SERVICE = "statusbar";
 
     /**
@@ -3620,6 +3648,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String ETHERNET_SERVICE = "ethernet";
 
     /**
@@ -4275,6 +4304,7 @@
 
     /** @hide */
     @PackageManager.PermissionResult
+    @UnsupportedAppUsage
     public abstract int checkPermission(@NonNull String permission, int pid, int uid,
             IBinder callerToken);
 
@@ -4767,6 +4797,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract Context createApplicationContext(ApplicationInfo application,
             @CreatePackageOptions int flags) throws PackageManager.NameNotFoundException;
 
@@ -4912,6 +4943,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract Display getDisplay();
 
     /**
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index bae99b8..1cc398e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.content.pm.ApplicationInfo;
@@ -54,6 +55,7 @@
  * the original Context.
  */
 public class ContextWrapper extends Context {
+    @UnsupportedAppUsage
     Context mBase;
 
     public ContextWrapper(Context base) {
@@ -123,6 +125,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public int getThemeResId() {
         return mBase.getThemeResId();
     }
@@ -144,6 +147,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public String getBasePackageName() {
         return mBase.getBasePackageName();
     }
@@ -381,6 +385,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public void startActivityAsUser(Intent intent, UserHandle user) {
         mBase.startActivityAsUser(intent, user);
     }
@@ -647,6 +652,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public Intent registerReceiverAsUser(
         BroadcastReceiver receiver, UserHandle user, IntentFilter filter,
         String broadcastPermission, Handler scheduler) {
@@ -676,12 +682,14 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public ComponentName startServiceAsUser(Intent service, UserHandle user) {
         return mBase.startServiceAsUser(service, user);
     }
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
         return mBase.startForegroundServiceAsUser(service, user);
     }
@@ -861,6 +869,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public Context createApplicationContext(ApplicationInfo application,
             int flags) throws PackageManager.NameNotFoundException {
         return mBase.createApplicationContext(application, flags);
@@ -904,6 +913,7 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     public Display getDisplay() {
         return mBase.getDisplay();
     }
diff --git a/core/java/android/content/CursorEntityIterator.java b/core/java/android/content/CursorEntityIterator.java
index 18437e5..2c630d2 100644
--- a/core/java/android/content/CursorEntityIterator.java
+++ b/core/java/android/content/CursorEntityIterator.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.database.Cursor;
 import android.os.RemoteException;
 
@@ -33,6 +34,7 @@
      * first Entity, if there are any.
      * @param cursor the cursor that contains the rows that make up the entities
      */
+    @UnsupportedAppUsage
     public CursorEntityIterator(Cursor cursor) {
         mIsClosed = false;
         mCursor = cursor;
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index 5a08636..4e46d571 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.CancellationSignal;
@@ -44,6 +45,7 @@
  */
 @Deprecated
 public class CursorLoader extends AsyncTaskLoader<Cursor> {
+    @UnsupportedAppUsage
     final ForceLoadContentObserver mObserver;
 
     Uri mUri;
@@ -53,6 +55,7 @@
     String mSortOrder;
 
     Cursor mCursor;
+    @UnsupportedAppUsage
     CancellationSignal mCancellationSignal;
 
     /* Runs on a worker thread */
diff --git a/core/java/android/content/Entity.java b/core/java/android/content/Entity.java
index 607cb3f..b9473e0 100644
--- a/core/java/android/content/Entity.java
+++ b/core/java/android/content/Entity.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 
 import java.util.ArrayList;
@@ -28,7 +29,9 @@
  * corresponds to that RawContact. The uri refers to the Data table uri for each row.
  */
 public final class Entity {
+    @UnsupportedAppUsage
     final private ContentValues mValues;
+    @UnsupportedAppUsage
     final private ArrayList<NamedContentValues> mSubValues;
 
     public Entity(ContentValues values) {
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 66087fb..d814e67 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.net.Uri;
@@ -39,12 +40,16 @@
             @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
             throws RemoteException;
     public String getType(Uri url) throws RemoteException;
+    @UnsupportedAppUsage
     public Uri insert(String callingPkg, Uri url, ContentValues initialValues)
             throws RemoteException;
+    @UnsupportedAppUsage
     public int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues)
             throws RemoteException;
+    @UnsupportedAppUsage
     public int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
             throws RemoteException;
+    @UnsupportedAppUsage
     public int update(String callingPkg, Uri url, ContentValues values, String selection,
             String[] selectionArgs) throws RemoteException;
     public ParcelFileDescriptor openFile(
@@ -57,6 +62,7 @@
     public ContentProviderResult[] applyBatch(String callingPkg,
             ArrayList<ContentProviderOperation> operations)
                     throws RemoteException, OperationApplicationException;
+    @UnsupportedAppUsage
     public Bundle call(
             String callingPkg, String method, @Nullable String arg, @Nullable Bundle extras)
             throws RemoteException;
@@ -74,8 +80,10 @@
             Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException;
 
     /* IPC constants */
+    @UnsupportedAppUsage
     static final String descriptor = "android.content.IContentProvider";
 
+    @UnsupportedAppUsage
     static final int QUERY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
     static final int GET_TYPE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
     static final int INSERT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 2;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 78738e9..8c2b76f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -26,6 +26,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
@@ -2027,6 +2028,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_ALARM_CHANGED = "android.intent.action.ALARM_CHANGED";
 
     /**
@@ -2248,6 +2250,7 @@
      * <p>Includes the following extras:
      * <ul>
      * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages which have been suspended
+     * <li> {@link #EXTRA_CHANGED_UID_LIST} is the set of uids which have been suspended
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent
@@ -2260,6 +2263,7 @@
      * <p>Includes the following extras:
      * <ul>
      * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages which have been unsuspended
+     * <li> {@link #EXTRA_CHANGED_UID_LIST} is the set of uids which have been unsuspended
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent
@@ -3254,6 +3258,7 @@
      * {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String ACTION_USER_SWITCHED =
             "android.intent.action.USER_SWITCHED";
 
@@ -5740,6 +5745,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x04000000;
     /**
      * Set when this broadcast is for a boot upgrade, a special mode that
@@ -5906,6 +5912,7 @@
     private ComponentName mComponent;
     private int mFlags;
     private ArraySet<String> mCategories;
+    @UnsupportedAppUsage
     private Bundle mExtras;
     private Rect mSourceBounds;
     private Intent mSelector;
@@ -6573,6 +6580,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static Intent parseCommandArgs(ShellCommand cmd, CommandOptionHandler optionHandler)
             throws URISyntaxException {
         Intent intent = new Intent();
@@ -6957,6 +6965,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void printIntentArgsHelp(PrintWriter pw, String prefix) {
         final String[] lines = new String[] {
                 "<INTENT> specifications include these flags and arguments:",
@@ -7234,6 +7243,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public void setAllowFds(boolean allowFds) {
         if (mExtras != null) {
             mExtras.setAllowFds(allowFds);
@@ -7259,6 +7269,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public Object getExtra(String name) {
         return getExtra(name, null);
     }
@@ -7697,6 +7708,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public IBinder getIBinderExtra(String name) {
         return mExtras == null ? null : mExtras.getIBinder(name);
     }
@@ -7717,6 +7729,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public Object getExtra(String name, Object defaultValue) {
         Object result = defaultValue;
         if (mExtras != null) {
@@ -7789,6 +7802,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean isExcludingStopped() {
         return (mFlags&(FLAG_EXCLUDE_STOPPED_PACKAGES|FLAG_INCLUDE_STOPPED_PACKAGES))
                 == FLAG_EXCLUDE_STOPPED_PACKAGES;
@@ -7938,6 +7952,7 @@
      * there are no matches.
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable ComponentName resolveSystemService(@NonNull PackageManager pm,
             @PackageManager.ComponentInfoFlags int flags) {
         if (mComponent != null) {
@@ -8947,6 +8962,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public @NonNull Intent putExtra(String name, IBinder value) {
         if (mExtras == null) {
             mExtras = new Bundle();
@@ -9514,6 +9530,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public String toInsecureString() {
         StringBuilder b = new StringBuilder(128);
 
@@ -10163,6 +10180,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void prepareToLeaveProcess(Context context) {
         final boolean leavingPackage = (mComponent == null)
                 || !Objects.equals(mComponent.getPackageName(), context.getPackageName());
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index cec3bad..212e132 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -271,7 +272,9 @@
     public static final String SCHEME_HTTPS = "https";
 
     private int mPriority;
+    @UnsupportedAppUsage
     private int mOrder;
+    @UnsupportedAppUsage
     private final ArrayList<String> mActions;
     private ArrayList<String> mCategories = null;
     private ArrayList<String> mDataSchemes = null;
@@ -536,6 +539,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public final void setAutoVerify(boolean autoVerify) {
         mVerifyState &= ~STATE_VERIFY_AUTO;
         if (autoVerify) mVerifyState |= STATE_VERIFY_AUTO;
@@ -651,6 +655,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public final boolean isVerified() {
         if ((mVerifyState & STATE_NEED_VERIFY_CHECKED) == STATE_NEED_VERIFY_CHECKED) {
             return ((mVerifyState & STATE_NEED_VERIFY) == STATE_NEED_VERIFY);
@@ -806,6 +811,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public final boolean hasExactDataType(String type) {
         return mDataTypes != null && mDataTypes.contains(type);
     }
@@ -1071,6 +1077,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public final boolean hasDataSchemeSpecificPart(PatternMatcher ssp) {
         if (mDataSchemeSpecificParts == null) {
             return false;
@@ -1154,6 +1161,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public final boolean hasDataAuthority(AuthorityEntry auth) {
         if (mDataAuthorities == null) {
             return false;
@@ -1250,6 +1258,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public final boolean hasDataPath(PatternMatcher path) {
         if (mDataPaths == null) {
             return false;
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index ff127df..bfd1a43 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -55,6 +56,7 @@
  * {@link android.app.PendingIntent#getIntentSender() PendingIntent.getIntentSender()}.
  */
 public class IntentSender implements Parcelable {
+    @UnsupportedAppUsage
     private final IIntentSender mTarget;
     IBinder mWhitelistToken;
 
@@ -356,6 +358,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public IIntentSender getTarget() {
         return mTarget;
     }
@@ -366,6 +369,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public IntentSender(IIntentSender target) {
         mTarget = target;
     }
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index b463ec6..33395ec 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.pm.ApplicationInfo;
@@ -402,6 +403,7 @@
     private static final String TAG_RESTRICTION = "restriction";
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private final IRestrictionsManager mService;
 
     /**
diff --git a/core/java/android/content/SearchRecentSuggestionsProvider.java b/core/java/android/content/SearchRecentSuggestionsProvider.java
index d6f7d97..8ee7b9e 100644
--- a/core/java/android/content/SearchRecentSuggestionsProvider.java
+++ b/core/java/android/content/SearchRecentSuggestionsProvider.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.SearchManager;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
@@ -115,6 +116,7 @@
     private UriMatcher mUriMatcher;
     
     private String mSuggestSuggestionClause;
+    @UnsupportedAppUsage
     private String[] mSuggestionProjection;
 
     /**
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index 6ef7fd2..ff77676 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.text.TextUtils;
 import android.os.Parcelable;
 import android.os.Parcel;
@@ -29,10 +30,15 @@
     public final String authority;
     public final String accountType;
     public final boolean isKey;
+    @UnsupportedAppUsage
     private final boolean userVisible;
+    @UnsupportedAppUsage
     private final boolean supportsUploading;
+    @UnsupportedAppUsage
     private final boolean isAlwaysSyncable;
+    @UnsupportedAppUsage
     private final boolean allowParallelSyncs;
+    @UnsupportedAppUsage
     private final String settingsActivity;
     private final String packageName;
 
@@ -79,6 +85,7 @@
         this.packageName = packageName;
     }
 
+    @UnsupportedAppUsage
     private SyncAdapterType(String authority, String accountType) {
         if (TextUtils.isEmpty(authority)) {
             throw new IllegalArgumentException("the authority must not be empty: " + authority);
diff --git a/core/java/android/content/SyncAdaptersCache.java b/core/java/android/content/SyncAdaptersCache.java
index ccd7994..d4e5217 100644
--- a/core/java/android/content/SyncAdaptersCache.java
+++ b/core/java/android/content/SyncAdaptersCache.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.RegisteredServicesCache;
 import android.content.pm.XmlSerializerAndParser;
 import android.content.res.Resources;
@@ -51,6 +52,7 @@
     private SparseArray<ArrayMap<String,String[]>> mAuthorityToSyncAdapters
             = new SparseArray<>();
 
+    @UnsupportedAppUsage
     public SyncAdaptersCache(Context context) {
         super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, sSerializer);
     }
diff --git a/core/java/android/content/SyncContext.java b/core/java/android/content/SyncContext.java
index cc914c0..50d1dc9 100644
--- a/core/java/android/content/SyncContext.java
+++ b/core/java/android/content/SyncContext.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.IBinder;
@@ -29,6 +30,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public SyncContext(ISyncContext syncContextInterface) {
         mSyncContext = syncContextInterface;
         mLastHeartbeatSendTime = 0;
@@ -42,6 +44,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setStatusText(String message) {
         updateHeartbeat();
     }
diff --git a/core/java/android/content/SyncInfo.java b/core/java/android/content/SyncInfo.java
index ab3c30b..7ebf922 100644
--- a/core/java/android/content/SyncInfo.java
+++ b/core/java/android/content/SyncInfo.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.accounts.Account;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,6 +33,7 @@
     private static final Account REDACTED_ACCOUNT = new Account("*****", "*****");
 
     /** @hide */
+    @UnsupportedAppUsage
     public final int authorityId;
 
     /**
@@ -63,6 +65,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public SyncInfo(int authorityId, Account account, String authority, long startTime) {
         this.authorityId = authorityId;
         this.account = account;
@@ -92,6 +95,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     SyncInfo(Parcel parcel) {
         authorityId = parcel.readInt();
         account = parcel.readParcelable(Account.class.getClassLoader());
@@ -100,6 +104,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final Creator<SyncInfo> CREATOR = new Creator<SyncInfo>() {
         public SyncInfo createFromParcel(Parcel in) {
             return new SyncInfo(in);
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 74d2f11..fd12d7a 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.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -29,10 +30,13 @@
 public class SyncRequest implements Parcelable {
     private static final String TAG = "SyncRequest";
     /** Account to pass to the sync adapter. Can be null. */
+    @UnsupportedAppUsage
     private final Account mAccountToSync;
     /** Authority string that corresponds to a ContentProvider. */
+    @UnsupportedAppUsage
     private final String mAuthority;
     /** Bundle containing user info as well as sync settings. */
+    @UnsupportedAppUsage
     private final Bundle mExtras;
     /** Don't allow this sync request on metered networks. */
     private final boolean mDisallowMetered;
@@ -44,8 +48,10 @@
     /**
      * Specifies a point in the future at which the sync must have been scheduled to run.
      */
+    @UnsupportedAppUsage
     private final long mSyncRunTimeSecs;
     /** Periodic versus one-off. */
+    @UnsupportedAppUsage
     private final boolean mIsPeriodic;
     /** Service versus provider. */
     private final boolean mIsAuthority;
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index 2d521e9..a9065ca 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -37,6 +38,7 @@
      */
     private static final int SOURCE_COUNT = 6;
 
+    @UnsupportedAppUsage
     public final int authorityId;
 
     /**
@@ -117,13 +119,21 @@
     public final Stats todayStats = new Stats();
     public final Stats yesterdayStats = new Stats();
 
+    @UnsupportedAppUsage
     public long lastSuccessTime;
+    @UnsupportedAppUsage
     public int lastSuccessSource;
+    @UnsupportedAppUsage
     public long lastFailureTime;
+    @UnsupportedAppUsage
     public int lastFailureSource;
+    @UnsupportedAppUsage
     public String lastFailureMesg;
+    @UnsupportedAppUsage
     public long initialFailureTime;
+    @UnsupportedAppUsage
     public boolean pending;
+    @UnsupportedAppUsage
     public boolean initialize;
 
     public final long[] perSourceLastSuccessTimes = new long[SOURCE_COUNT];
@@ -131,15 +141,18 @@
 
   // Warning: It is up to the external caller to ensure there are
   // no race conditions when accessing this list
+  @UnsupportedAppUsage
   private ArrayList<Long> periodicSyncTimes;
 
     private final ArrayList<Long> mLastEventTimes = new ArrayList<>();
     private final ArrayList<String> mLastEvents = new ArrayList<>();
 
+    @UnsupportedAppUsage
     public SyncStatusInfo(int authorityId) {
         this.authorityId = authorityId;
     }
 
+    @UnsupportedAppUsage
     public int getLastFailureMesgAsInt(int def) {
         final int i = ContentResolver.syncErrorStringToInt(lastFailureMesg);
         if (i > 0) {
@@ -205,6 +218,7 @@
         parcel.writeLongArray(perSourceLastFailureTimes);
     }
 
+    @UnsupportedAppUsage
     public SyncStatusInfo(Parcel parcel) {
         int version = parcel.readInt();
         if (version != VERSION && version != 1) {
@@ -309,6 +323,7 @@
         System.arraycopy(from, 0, to, 0, to.length);
     }
 
+    @UnsupportedAppUsage
     public void setPeriodicSyncTime(int index, long when) {
         // The list is initialized lazily when scheduling occurs so we need to make sure
         // we initialize elements < index to zero (zero is ignore for scheduling purposes)
@@ -316,6 +331,7 @@
         periodicSyncTimes.set(index, when);
     }
 
+    @UnsupportedAppUsage
     public long getPeriodicSyncTime(int index) {
         if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
             return periodicSyncTimes.get(index);
@@ -324,6 +340,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void removePeriodicSyncTime(int index) {
         if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
             periodicSyncTimes.remove(index);
@@ -383,6 +400,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final Creator<SyncStatusInfo> CREATOR = new Creator<SyncStatusInfo>() {
         public SyncStatusInfo createFromParcel(Parcel in) {
             return new SyncStatusInfo(in);
@@ -393,6 +411,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     private void ensurePeriodicSyncTimeSize(int index) {
         if (periodicSyncTimes == null) {
             periodicSyncTimes = new ArrayList<Long>(0);
diff --git a/core/java/android/content/UndoManager.java b/core/java/android/content/UndoManager.java
index fb21641..f6a0d77 100644
--- a/core/java/android/content/UndoManager.java
+++ b/core/java/android/content/UndoManager.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.ParcelableParcel;
@@ -86,6 +87,7 @@
      */
     public static final int MERGE_MODE_ANY = 2;
 
+    @UnsupportedAppUsage
     public UndoOwner getOwner(String tag, Object data) {
         if (tag == null) {
             throw new NullPointerException("tag can't be null");
@@ -122,6 +124,7 @@
      * Flatten the current undo state into a Parcel object, which can later be restored
      * with {@link #restoreInstanceState(android.os.Parcel, java.lang.ClassLoader)}.
      */
+    @UnsupportedAppUsage
     public void saveInstanceState(Parcel p) {
         if (mUpdateCount > 0) {
             throw new IllegalStateException("Can't save state while updating");
@@ -170,6 +173,7 @@
      * associated with each {@link UndoOwner}, which requires separate calls to
      * {@link #getOwner(String, Object)} to re-associate the owner with its data.
      */
+    @UnsupportedAppUsage
     public void restoreInstanceState(Parcel p, ClassLoader loader) {
         if (mUpdateCount > 0) {
             throw new IllegalStateException("Can't save state while updating");
@@ -230,6 +234,7 @@
      * @param count Number of undo states to pop.
      * @return Returns the number of undo states that were actually popped.
      */
+    @UnsupportedAppUsage
     public int undo(UndoOwner[] owners, int count) {
         if (mWorking != null) {
             throw new IllegalStateException("Can't be called during an update");
@@ -267,6 +272,7 @@
      * @param count Number of undo states to pop.
      * @return Returns the number of undo states that were actually redone.
      */
+    @UnsupportedAppUsage
     public int redo(UndoOwner[] owners, int count) {
         if (mWorking != null) {
             throw new IllegalStateException("Can't be called during an update");
@@ -295,10 +301,12 @@
      * useful for editors to know whether they should be generating new undo state
      * when they see edit operations happening.
      */
+    @UnsupportedAppUsage
     public boolean isInUndo() {
         return mInUndo;
     }
 
+    @UnsupportedAppUsage
     public int forgetUndos(UndoOwner[] owners, int count) {
         if (count < 0) {
             count = mUndos.size();
@@ -320,6 +328,7 @@
         return removed;
     }
 
+    @UnsupportedAppUsage
     public int forgetRedos(UndoOwner[] owners, int count) {
         if (count < 0) {
             count = mRedos.size();
@@ -346,6 +355,7 @@
      * @param owners If non-null, only those states containing an operation with one of
      * the owners supplied here will be counted.
      */
+    @UnsupportedAppUsage
     public int countUndos(UndoOwner[] owners) {
         if (owners == null) {
             return mUndos.size();
@@ -365,6 +375,7 @@
      * @param owners If non-null, only those states containing an operation with one of
      * the owners supplied here will be counted.
      */
+    @UnsupportedAppUsage
     public int countRedos(UndoOwner[] owners) {
         if (owners == null) {
             return mRedos.size();
@@ -404,6 +415,7 @@
      * they are all matched by a later call to {@link #endUpdate}.
      * @param label Optional user-visible label for this new undo state.
      */
+    @UnsupportedAppUsage
     public void beginUpdate(CharSequence label) {
         if (mInUndo) {
             throw new IllegalStateException("Can't being update while performing undo/redo");
@@ -436,6 +448,7 @@
      * Forcibly set a new for the new undo state being built within a {@link #beginUpdate}.
      * Any existing label will be replaced with this one.
      */
+    @UnsupportedAppUsage
     public void setUndoLabel(CharSequence label) {
         if (mWorking == null) {
             throw new IllegalStateException("Must be called during an update");
@@ -510,6 +523,7 @@
      * @param mergeMode May be either {@link #MERGE_MODE_NONE}, {@link #MERGE_MODE_UNIQUE},
      * or {@link #MERGE_MODE_ANY}.
      */
+    @UnsupportedAppUsage
     public <T extends UndoOperation> T getLastOperation(Class<T> clazz, UndoOwner owner,
             int mergeMode) {
         if (mWorking == null) {
@@ -539,6 +553,7 @@
      * @param mergeMode May be either {@link #MERGE_MODE_NONE}, {@link #MERGE_MODE_UNIQUE},
      * or {@link #MERGE_MODE_ANY}.
      */
+    @UnsupportedAppUsage
     public void addOperation(UndoOperation<?> op, int mergeMode) {
         if (mWorking == null) {
             throw new IllegalStateException("Must be called during an update");
@@ -565,6 +580,7 @@
      * Finish the creation of an undo state, matching a previous call to
      * {@link #beginUpdate}.
      */
+    @UnsupportedAppUsage
     public void endUpdate() {
         if (mWorking == null) {
             throw new IllegalStateException("Must be called during an update");
@@ -613,6 +629,7 @@
      * @return Returns an integer identifier for the committed undo state, which
      * can later be used to try to uncommit the state to perform further edits on it.
      */
+    @UnsupportedAppUsage
     public int commitState(UndoOwner owner) {
         if (mWorking != null && mWorking.hasData()) {
             if (owner == null || mWorking.hasOperation(owner)) {
diff --git a/core/java/android/content/UndoOperation.java b/core/java/android/content/UndoOperation.java
index 1ff32d4..a425486 100644
--- a/core/java/android/content/UndoOperation.java
+++ b/core/java/android/content/UndoOperation.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -34,6 +35,7 @@
      * @param owner Who owns the data being modified by this undo state; must be
      * returned by {@link UndoManager#getOwner(String, Object) UndoManager.getOwner}.
      */
+    @UnsupportedAppUsage
     public UndoOperation(UndoOwner owner) {
         mOwner = owner;
     }
@@ -41,6 +43,7 @@
     /**
      * Construct from a Parcel.
      */
+    @UnsupportedAppUsage
     protected UndoOperation(Parcel src, ClassLoader loader) {
     }
 
diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java
index 8db82a8..208bc01 100644
--- a/core/java/android/content/UriMatcher.java
+++ b/core/java/android/content/UriMatcher.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 
 import java.util.ArrayList;
@@ -277,6 +278,8 @@
 
     private int mCode;
     private final int mWhich;
+    @UnsupportedAppUsage
     private final String mText;
+    @UnsupportedAppUsage
     private ArrayList<UriMatcher> mChildren;
 }
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index edacbb0..07b23d1 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -107,11 +108,13 @@
     /**
      * Package name of the overlay package
      */
+    @UnsupportedAppUsage
     public final String packageName;
 
     /**
      * Package name of the target package
      */
+    @UnsupportedAppUsage
     public final String targetPackageName;
 
     /**
@@ -127,6 +130,7 @@
     /**
      * The state of this OverlayInfo as defined by the STATE_* constants in this class.
      */
+    @UnsupportedAppUsage
     public final @State int state;
 
     /**
@@ -251,6 +255,7 @@
      *
      * @return true if the overlay is enabled, else false.
      */
+    @UnsupportedAppUsage
     public boolean isEnabled() {
         switch (state) {
             case STATE_ENABLED:
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index dcf8c77..5926af6 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -222,6 +223,7 @@
      * See {@link android.R.attr#resizeableActivity}.
      * @hide
      */
+    @UnsupportedAppUsage
     public int resizeMode = RESIZE_MODE_RESIZEABLE;
 
     /**
@@ -355,6 +357,7 @@
      * {@link android.R.attr#showForAllUsers} attribute.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int FLAG_SHOW_FOR_ALL_USERS = 0x0400;
     /**
      * Bit in {@link #flags} corresponding to an immersive activity
@@ -476,6 +479,7 @@
      * this activity is launched into such a container a SecurityException will be
      * thrown. Set from the {@link android.R.attr#allowEmbedded} attribute.
      */
+    @UnsupportedAppUsage
     public static final int FLAG_ALLOW_EMBEDDED = 0x80000000;
 
     /**
@@ -816,6 +820,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static @NativeConfig int activityInfoConfigJavaToNative(@Config int input) {
         int output = 0;
         for (int i = 0; i < CONFIG_NATIVE_BITS.length; i++) {
@@ -1047,11 +1052,13 @@
      * Returns true if the activity supports picture-in-picture.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean supportsPictureInPicture() {
         return (flags & FLAG_SUPPORTS_PICTURE_IN_PICTURE) != 0;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isResizeableMode(int mode) {
         return mode == RESIZE_MODE_RESIZEABLE
                 || mode == RESIZE_MODE_FORCE_RESIZEABLE
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 3120421..b7a5352 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
@@ -127,6 +128,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int fullBackupContent = 0;
 
     /**
@@ -477,6 +479,7 @@
      *
      * {@hide}
      */
+    @TestApi
     public static final int PRIVATE_FLAG_PRIVILEGED = 1<<3;
 
     /**
@@ -612,6 +615,13 @@
     public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
 
     /**
+     * Value for {@link #privateFlags}: whether this app is pre-installed on the
+     * google partition of the system image.
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_PRODUCT_SERVICES = 1 << 21;
+
+    /**
      * Value for {@link #privateFlags}: whether this app is signed with the
      * platform key.
      * @hide
@@ -636,6 +646,7 @@
             PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE,
             PRIVATE_FLAG_PRIVILEGED,
             PRIVATE_FLAG_PRODUCT,
+            PRIVATE_FLAG_PRODUCT_SERVICES,
             PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
             PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY,
             PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
@@ -649,6 +660,7 @@
      * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
      * @hide
      */
+    @TestApi
     public @ApplicationInfoPrivateFlags int privateFlags;
 
     /**
@@ -702,8 +714,10 @@
     public UUID storageUuid;
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public String scanSourceDir;
     /** {@hide} */
+    @UnsupportedAppUsage
     public String scanPublicSourceDir;
 
     /**
@@ -769,6 +783,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public String[] resourceDirs;
 
     /**
@@ -845,6 +860,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String secondaryNativeLibraryDir;
 
     /**
@@ -856,6 +872,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String nativeLibraryRootDir;
 
     /**
@@ -875,6 +892,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public String primaryCpuAbi;
 
     /**
@@ -884,6 +902,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public String secondaryCpuAbi;
 
     /**
@@ -923,6 +942,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public int versionCode;
 
     /**
@@ -958,12 +978,14 @@
      * For convenient access to the current enabled setting of this app.
      * @hide
      */
+    @UnsupportedAppUsage
     public int enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 
     /**
      * For convenient access to package's install location.
      * @hide
      */
+    @UnsupportedAppUsage
     public int installLocation = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
 
     /**
@@ -1372,6 +1394,7 @@
      * @return true if "supportsRtl" has been set to true in the AndroidManifest
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean hasRtlSupport() {
         return (flags & FLAG_SUPPORTS_RTL) == FLAG_SUPPORTS_RTL;
     }
@@ -1400,7 +1423,9 @@
             return sCollator.compare(sa.toString(), sb.toString());
         }
 
+        @UnsupportedAppUsage
         private final Collator   sCollator = Collator.getInstance();
+        @UnsupportedAppUsage
         private PackageManager   mPM;
     }
 
@@ -1639,6 +1664,7 @@
      * 
      * @hide
      */
+    @UnsupportedAppUsage
     public void disableCompatibilityMode() {
         flags |= (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS |
                 FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS |
@@ -1763,6 +1789,7 @@
         return pm.getDefaultActivityIcon();
     }
     
+    @UnsupportedAppUsage
     private boolean isPackageUnavailable(PackageManager pm) {
         try {
             return pm.getPackageInfo(packageName, 0) == null;
@@ -1798,6 +1825,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean isForwardLocked() {
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
     }
@@ -1868,6 +1896,11 @@
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
     }
 
+    /** @hide */
+    public boolean isProductServices() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
+    }
+
     /**
      * Returns whether or not this application was installed as a virtual preload.
      */
@@ -1898,10 +1931,14 @@
     /** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; }
     /** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; }
 
-    /** {@hide} */ public String getCodePath() { return scanSourceDir; }
+    /** {@hide} */
+    @UnsupportedAppUsage
+    public String getCodePath() { return scanSourceDir; }
     /** {@hide} */ public String getBaseCodePath() { return sourceDir; }
     /** {@hide} */ public String[] getSplitCodePaths() { return splitSourceDirs; }
     /** {@hide} */ public String getResourcePath() { return scanPublicSourceDir; }
-    /** {@hide} */ public String getBaseResourcePath() { return publicSourceDir; }
+    /** {@hide} */
+    @UnsupportedAppUsage
+    public String getBaseResourcePath() { return publicSourceDir; }
     /** {@hide} */ public String[] getSplitResourcePaths() { return splitPublicSourceDirs; }
 }
diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java
index 5877a09..a3e5d6d 100644
--- a/core/java/android/content/pm/BaseParceledListSlice.java
+++ b/core/java/android/content/pm/BaseParceledListSlice.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -132,6 +133,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public List<T> getList() {
         return mList;
     }
@@ -205,6 +207,7 @@
 
     protected abstract void writeElement(T parcelable, Parcel reply, int callFlags);
 
+    @UnsupportedAppUsage
     protected abstract void writeParcelableCreator(T parcelable, Parcel dest);
 
     protected abstract Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader);
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 0269b6c..29612c2 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
@@ -162,6 +163,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public ComponentName getComponentName() {
         return new ComponentName(packageName, name);
     }
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index e9c9588..1451431 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -35,6 +36,7 @@
 
     private final PackageManager mPm;
 
+    @UnsupportedAppUsage
     private ActivityInfo mActivityInfo;
     private ComponentName mComponentName;
     private UserHandle mUser;
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index fa423e2..46877ca 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -23,6 +23,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
@@ -135,7 +136,9 @@
             "android.content.pm.extra.PIN_ITEM_REQUEST";
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private final ILauncherApps mService;
+    @UnsupportedAppUsage
     private final PackageManager mPm;
     private final UserManager mUserManager;
 
@@ -1055,6 +1058,7 @@
                 shortcut.getUserId());
     }
 
+    @UnsupportedAppUsage
     private void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
             @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
             int userId) {
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 5d8122f..d9d1777 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -297,6 +298,7 @@
      * the {@link android.R.attr#installLocation} attribute.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int INSTALL_LOCATION_UNSPECIFIED = -1;
 
     /**
@@ -329,6 +331,7 @@
     public boolean isStub;
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean coreApp;
 
     /** @hide */
@@ -346,6 +349,7 @@
      * Package name of target package, or null.
      * @hide
      */
+    @UnsupportedAppUsage
     public String overlayTarget;
 
     /**
@@ -483,6 +487,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     private PackageInfo(Parcel source) {
         packageName = source.readString();
         splitNames = source.createStringArray();
diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java
index bbf020d..e0e67b9 100644
--- a/core/java/android/content/pm/PackageInfoLite.java
+++ b/core/java/android/content/pm/PackageInfoLite.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -115,6 +116,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<PackageInfoLite> CREATOR
             = new Parcelable.Creator<PackageInfoLite>() {
         public PackageInfoLite createFromParcel(Parcel source) {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 2f3bf63..316ace16 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -23,6 +23,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.content.Intent;
@@ -121,8 +122,7 @@
             "android.content.pm.action.SESSION_COMMITTED";
 
     /** {@hide} */
-    public static final String
-            ACTION_CONFIRM_PERMISSIONS = "android.content.pm.action.CONFIRM_PERMISSIONS";
+    public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
 
     /**
      * An integer session ID that an operation is working with.
@@ -788,6 +788,7 @@
         }
 
         /** {@hide} */
+        @UnsupportedAppUsage
         public void addProgress(float progress) {
             try {
                 mSession.addClientProgress(progress);
@@ -1090,26 +1091,33 @@
         public static final int UID_UNKNOWN = -1;
 
         /** {@hide} */
+        @UnsupportedAppUsage
         public int mode = MODE_INVALID;
         /** {@hide} */
+        @UnsupportedAppUsage
         public int installFlags;
         /** {@hide} */
         public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
         /** {@hide} */
         public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
         /** {@hide} */
+        @UnsupportedAppUsage
         public long sizeBytes = -1;
         /** {@hide} */
+        @UnsupportedAppUsage
         public String appPackageName;
         /** {@hide} */
+        @UnsupportedAppUsage
         public Bitmap appIcon;
         /** {@hide} */
+        @UnsupportedAppUsage
         public String appLabel;
         /** {@hide} */
         public long appIconLastModified = -1;
         /** {@hide} */
         public Uri originatingUri;
         /** {@hide} */
+        @UnsupportedAppUsage
         public int originatingUid = UID_UNKNOWN;
         /** {@hide} */
         public Uri referrerUri;
@@ -1427,29 +1435,40 @@
     public static class SessionInfo implements Parcelable {
 
         /** {@hide} */
+        @UnsupportedAppUsage
         public int sessionId;
         /** {@hide} */
+        @UnsupportedAppUsage
         public String installerPackageName;
         /** {@hide} */
+        @UnsupportedAppUsage
         public String resolvedBaseCodePath;
         /** {@hide} */
+        @UnsupportedAppUsage
         public float progress;
         /** {@hide} */
+        @UnsupportedAppUsage
         public boolean sealed;
         /** {@hide} */
+        @UnsupportedAppUsage
         public boolean active;
 
         /** {@hide} */
+        @UnsupportedAppUsage
         public int mode;
         /** {@hide} */
         public @InstallReason int installReason;
         /** {@hide} */
+        @UnsupportedAppUsage
         public long sizeBytes;
         /** {@hide} */
+        @UnsupportedAppUsage
         public String appPackageName;
         /** {@hide} */
+        @UnsupportedAppUsage
         public Bitmap appIcon;
         /** {@hide} */
+        @UnsupportedAppUsage
         public CharSequence appLabel;
 
         /** {@hide} */
@@ -1466,6 +1485,7 @@
         public int installFlags;
 
         /** {@hide} */
+        @UnsupportedAppUsage
         public SessionInfo() {
         }
 
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 14d3f91..0c70a3d 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -22,6 +22,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -103,6 +104,7 @@
     private static volatile boolean sForceSafeLabels = false;
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static void setForceSafeLabels(boolean forceSafeLabels) {
         sForceSafeLabels = forceSafeLabels;
     }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 721063a..4f39ec0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -29,6 +29,7 @@
 import android.annotation.StringRes;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.annotation.XmlRes;
 import android.app.ActivityManager;
@@ -724,6 +725,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int INSTALL_REPLACE_EXISTING = 0x00000002;
 
     /**
@@ -1317,6 +1319,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int NO_NATIVE_LIBRARIES = -114;
 
     /** {@hide} */
@@ -1541,6 +1544,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final int MOVE_INTERNAL = 0x00000001;
 
     /**
@@ -1549,6 +1553,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final int MOVE_EXTERNAL_MEDIA = 0x00000002;
 
     /** {@hide} */
@@ -2937,6 +2942,7 @@
      *
      * @hide
      */
+    @TestApi
     public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
 
     /**
@@ -2948,6 +2954,7 @@
      *
      * @hide
      */
+    @TestApi
     public static final String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared";
 
     /**
@@ -3088,6 +3095,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
+    @UnsupportedAppUsage
     public abstract PackageInfo getPackageInfoAsUser(String packageName,
             @PackageInfoFlags int flags, @UserIdInt int userId) throws NameNotFoundException;
 
@@ -3217,6 +3225,7 @@
      *             found on the system.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract int getPackageUidAsUser(String packageName, @UserIdInt int userId)
             throws NameNotFoundException;
 
@@ -3234,6 +3243,7 @@
      *             found on the system.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract int getPackageUidAsUser(String packageName, @PackageInfoFlags int flags,
             @UserIdInt int userId) throws NameNotFoundException;
 
@@ -3267,12 +3277,19 @@
             @PermissionInfoFlags int flags) throws NameNotFoundException;
 
     /**
-     * Returns true if Permission Review Mode is enabled, false otherwise.
+     * Returns true if some permissions are individually controlled
      *
      * @hide
      */
     @TestApi
-    public abstract boolean isPermissionReviewModeEnabled();
+    public abstract boolean arePermissionsIndividuallyControlled();
+
+    /**
+     * Returns true if wireless consent mode is enabled
+     *
+     * @hide
+     */
+    public abstract boolean isWirelessConsentModeEnabled();
 
     /**
      * Retrieve all of the information we know about a particular group of
@@ -3321,6 +3338,7 @@
             @ApplicationInfoFlags int flags) throws NameNotFoundException;
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract ApplicationInfo getApplicationInfoAsUser(String packageName,
             @ApplicationInfoFlags int flags, @UserIdInt int userId) throws NameNotFoundException;
 
@@ -3580,6 +3598,7 @@
      *
      * @hide
      */
+    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
     public abstract void grantRuntimePermission(@NonNull String packageName,
@@ -3606,6 +3625,7 @@
      *
      * @hide
      */
+    @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
     public abstract void revokeRuntimePermission(@NonNull String packageName,
@@ -3661,6 +3681,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract boolean shouldShowRequestPermissionRationale(String permission);
 
     /**
@@ -3672,6 +3693,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Intent buildRequestPermissionsIntent(@NonNull String[] permissions) {
         if (ArrayUtils.isEmpty(permissions)) {
            throw new IllegalArgumentException("permission cannot be null or empty");
@@ -3772,6 +3794,7 @@
      *             found on the system.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract int getUidForSharedUser(String sharedUserName)
             throws NameNotFoundException;
 
@@ -4099,6 +4122,7 @@
      *         containing something else, such as the activity resolver.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract ResolveInfo resolveActivityAsUser(Intent intent, @ResolveInfoFlags int flags,
             @UserIdInt int userId);
 
@@ -4137,6 +4161,7 @@
      *         empty list is returned.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
             @ResolveInfoFlags int flags, @UserIdInt int userId);
 
@@ -4202,12 +4227,14 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent,
             @ResolveInfoFlags int flags, @UserIdInt int userId);
 
 
     /** {@hide} */
     @Deprecated
+    @UnsupportedAppUsage
     public List<ResolveInfo> queryBroadcastReceivers(Intent intent,
             @ResolveInfoFlags int flags, @UserIdInt int userId) {
         final String msg = "Shame on you for calling the hidden API "
@@ -4265,6 +4292,7 @@
      *         empty list or null is returned.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract List<ResolveInfo> queryIntentServicesAsUser(Intent intent,
             @ResolveInfoFlags int flags, @UserIdInt int userId);
 
@@ -4280,6 +4308,7 @@
      *         no matching services, an empty list or null is returned.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract List<ResolveInfo> queryIntentContentProvidersAsUser(
             Intent intent, @ResolveInfoFlags int flags, @UserIdInt int userId);
 
@@ -4323,6 +4352,7 @@
      *         provider. If a provider was not found, returns null.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract ProviderInfo resolveContentProviderAsUser(String name,
             @ComponentInfoFlags int flags, @UserIdInt int userId);
 
@@ -4684,6 +4714,7 @@
      * @return the drawable or null if no drawable is required.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract Drawable getUserBadgeForDensity(UserHandle user, int density);
 
     /**
@@ -4700,6 +4731,7 @@
      * @return the drawable or null if no drawable is required.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density);
 
     /**
@@ -4813,6 +4845,7 @@
             throws NameNotFoundException;
 
     /** @hide */
+    @UnsupportedAppUsage
     public abstract Resources getResourcesForApplicationAsUser(String appPackageName,
             @UserIdInt int userId) throws NameNotFoundException;
 
@@ -4876,6 +4909,7 @@
             Manifest.permission.INSTALL_EXISTING_PACKAGES,
             Manifest.permission.INSTALL_PACKAGES,
             Manifest.permission.INTERACT_ACROSS_USERS_FULL})
+    @UnsupportedAppUsage
     public abstract int installExistingPackageAsUser(String packageName, @UserIdInt int userId)
             throws NameNotFoundException;
 
@@ -5108,6 +5142,7 @@
      * @hide
      */
     @RequiresPermission(Manifest.permission.DELETE_PACKAGES)
+    @UnsupportedAppUsage
     public abstract void deletePackage(String packageName, IPackageDeleteObserver observer,
             @DeleteFlags int flags);
 
@@ -5129,6 +5164,7 @@
     @RequiresPermission(anyOf = {
             Manifest.permission.DELETE_PACKAGES,
             Manifest.permission.INTERACT_ACROSS_USERS_FULL})
+    @UnsupportedAppUsage
     public abstract void deletePackageAsUser(@NonNull String packageName,
             IPackageDeleteObserver observer, @DeleteFlags int flags, @UserIdInt int userId);
 
@@ -5155,6 +5191,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void clearApplicationUserData(String packageName,
             IPackageDataObserver observer);
     /**
@@ -5173,6 +5210,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void deleteApplicationCacheFiles(String packageName,
             IPackageDataObserver observer);
 
@@ -5194,6 +5232,7 @@
      *            callback is desired.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void deleteApplicationCacheFilesAsUser(String packageName, int userId,
             IPackageDataObserver observer);
 
@@ -5219,11 +5258,13 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {
         freeStorageAndNotify(null, freeStorageSize, observer);
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract void freeStorageAndNotify(String volumeUuid, long freeStorageSize,
             IPackageDataObserver observer);
 
@@ -5250,11 +5291,13 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void freeStorage(long freeStorageSize, IntentSender pi) {
         freeStorage(null, freeStorageSize, pi);
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi);
 
     /**
@@ -5277,6 +5320,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public abstract void getPackageSizeInfoAsUser(String packageName, @UserIdInt int userId,
             IPackageStatsObserver observer);
 
@@ -5288,6 +5332,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
         getPackageSizeInfoAsUser(packageName, getUserId(), observer);
     }
@@ -5348,6 +5393,7 @@
             to.
      * @hide
      */
+    @UnsupportedAppUsage
     public void addPreferredActivityAsUser(IntentFilter filter, int match,
             ComponentName[] set, ComponentName activity, @UserIdInt int userId) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -5375,6 +5421,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public abstract void replacePreferredActivity(IntentFilter filter, int match,
             ComponentName[] set, ComponentName activity);
 
@@ -5382,6 +5429,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void replacePreferredActivityAsUser(IntentFilter filter, int match,
            ComponentName[] set, ComponentName activity, @UserIdInt int userId) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -5423,6 +5471,7 @@
      * default, if any.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract ComponentName getHomeActivities(List<ResolveInfo> outActivities);
 
     /**
@@ -5489,6 +5538,7 @@
      * @param userId Ther userId of the user whose restrictions are to be flushed.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void flushPackageRestrictionsAsUser(int userId);
 
     /**
@@ -5498,6 +5548,7 @@
      * or by installing it, such as with {@link #installExistingPackage(String)}
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
             UserHandle userHandle);
 
@@ -5506,6 +5557,7 @@
      * @see #setApplicationHiddenSettingAsUser(String, boolean, UserHandle)
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract boolean getApplicationHiddenSettingAsUser(String packageName,
             UserHandle userHandle);
 
@@ -5544,11 +5596,13 @@
      *        application's AndroidManifest.xml.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract KeySet getKeySetByAlias(String packageName, String alias);
 
     /** Return the signing {@link KeySet} for this application.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract KeySet getSigningKeySet(String packageName);
 
     /**
@@ -5558,6 +5612,7 @@
      * Compare to {@link #isSignedByExactly(String packageName, KeySet ks)}.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract boolean isSignedBy(String packageName, KeySet ks);
 
     /**
@@ -5566,6 +5621,7 @@
      * {@link #isSignedBy(String packageName, KeySet ks)}.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract boolean isSignedByExactly(String packageName, KeySet ks);
 
     /**
@@ -5628,6 +5684,7 @@
      * @throws IllegalArgumentException if the package was not found.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract boolean isPackageSuspendedForUser(String packageName, int userId);
 
     /**
@@ -5636,10 +5693,8 @@
      * @return {@code true} if the given package is suspended, {@code false} otherwise
      * @throws NameNotFoundException if the package could not be found.
      *
-     * @see #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle, String)
-     * @hide
+     * @see #isPackageSuspended()
      */
-    @SystemApi
     public boolean isPackageSuspended(String packageName) throws NameNotFoundException {
         throw new UnsupportedOperationException("isPackageSuspended not implemented");
     }
@@ -5719,18 +5774,24 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract int getMoveStatus(int moveId);
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract void registerMoveCallback(MoveCallback callback, Handler handler);
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract void unregisterMoveCallback(MoveCallback callback);
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract int movePackage(String packageName, VolumeInfo vol);
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app);
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract @NonNull List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app);
 
     /** {@hide} */
@@ -5754,6 +5815,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract boolean isUpgrade();
 
     /**
@@ -5775,6 +5837,7 @@
      *            {@link #ONLY_IF_NO_MATCH_FOUND}.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId,
             int targetUserId, int flags);
 
@@ -5785,22 +5848,27 @@
      * @param sourceUserId The source user id.
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void clearCrossProfileIntentFilters(int sourceUserId);
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo);
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo);
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public abstract boolean isPackageAvailable(String packageName);
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static String installStatusToString(int status, String msg) {
         final String str = installStatusToString(status);
         if (msg != null) {
@@ -5811,6 +5879,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static String installStatusToString(int status) {
         switch (status) {
             case INSTALL_SUCCEEDED: return "INSTALL_SUCCEEDED";
@@ -5921,6 +5990,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static String deleteStatusToString(int status) {
         switch (status) {
             case DELETE_SUCCEEDED: return "DELETE_SUCCEEDED";
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index f30b3fe..20e1454e 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -29,9 +29,13 @@
 import android.os.PersistableBundle;
 import android.util.SparseArray;
 
+import com.android.internal.util.function.TriFunction;
+
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
+import java.util.function.BiFunction;
 
 /**
  * Package manager local system service interface.
@@ -45,6 +49,7 @@
     public static final int PACKAGE_VERIFIER = 3;
     public static final int PACKAGE_BROWSER = 4;
     public static final int PACKAGE_SYSTEM_TEXT_CLASSIFIER = 5;
+    public static final int PACKAGE_PERMISSION_CONTROLLER = 6;
     @IntDef(value = {
         PACKAGE_SYSTEM,
         PACKAGE_SETUP_WIZARD,
@@ -52,6 +57,7 @@
         PACKAGE_VERIFIER,
         PACKAGE_BROWSER,
         PACKAGE_SYSTEM_TEXT_CLASSIFIER,
+        PACKAGE_PERMISSION_CONTROLLER,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface KnownPackage {}
@@ -64,6 +70,32 @@
         void onPackageRemoved(@NonNull String packageName);
     }
 
+    /** Interface to override permission checks via composition */
+    public interface CheckPermissionDelegate {
+        /**
+         * Allows overriding check permission behavior.
+         *
+         * @param permName The permission to check.
+         * @param pkgName The package for which to check.
+         * @param userId The user for which to check.
+         * @param superImpl The super implementation.
+         * @return The check permission result.
+         */
+        int checkPermission(String permName, String pkgName, int userId,
+                TriFunction<String, String, Integer, Integer> superImpl);
+
+        /**
+         * Allows overriding check UID permission behavior.
+         *
+         * @param permName The permission to check.
+         * @param uid The UID for which to check.
+         * @param superImpl The super implementation.
+         * @return The check permission result.
+         */
+        int checkUidPermission(String permName, int uid,
+                BiFunction<String, Integer, Integer> superImpl);
+    }
+
     /**
      * Provider for package names.
      */
@@ -617,15 +649,57 @@
     public abstract boolean isDataRestoreSafe(@NonNull Signature restoringFromSig,
             @NonNull String packageName);
 
-
     /**
-     * Returns true if the the signing information for {@code clientUid} is sufficient to gain
-     * access gated by {@code capability}.  This can happen if the two UIDs have the same signing
-     * information, if the signing information {@code clientUid} indicates that it has the signing
-     * certificate for {@code serverUid} in its signing history (if it was previously signed by it),
-     * or if the signing certificate for {@code clientUid} is in ths signing history for {@code
-     * serverUid} and with the {@code capability} specified.
+     * Returns {@code true} if the the signing information for {@code clientUid} is sufficient
+     * to gain access gated by {@code capability}.  This can happen if the two UIDs have the
+     * same signing information, if the signing information {@code clientUid} indicates that
+     * it has the signing certificate for {@code serverUid} in its signing history (if it was
+     * previously signed by it), or if the signing certificate for {@code clientUid} is in the
+     * signing history for {@code serverUid} and with the {@code capability} specified.
      */
     public abstract boolean hasSignatureCapability(int serverUid, int clientUid,
             @PackageParser.SigningDetails.CertCapabilities int capability);
+
+    /**
+     * Get the delegate to influence permission checking.
+     *
+     * @return The delegate instance or null to clear.
+     */
+    public abstract @Nullable CheckPermissionDelegate getCheckPermissionDelegate();
+
+    /**
+     * Set a delegate to influence permission checking.
+     *
+     * @param delegate A delegate instance or null to clear.
+     */
+    public abstract void setCheckPermissionDelegate(@Nullable CheckPermissionDelegate delegate);
+
+    /**
+     * Get appIds of all available apps which specified android:sharedUserId in the manifest.
+     *
+     * @return a SparseArray mapping from appId to it's sharedUserId.
+     */
+    public abstract SparseArray<String> getAppsWithSharedUserIds();
+
+    /**
+     * Return if device is currently in a "core" boot environment, typically
+     * used to support full-disk encryption. Only apps marked with
+     * {@code coreApp} attribute are available.
+     */
+    public abstract boolean isOnlyCoreApps();
+
+    /**
+     * Make a best-effort attempt to provide the requested free disk space by
+     * deleting cached files.
+     *
+     * @throws IOException if the request was unable to be fulfilled.
+     */
+    public abstract void freeStorage(String volumeUuid, long bytes, int storageFlags)
+            throws IOException;
+
+    /** Returns {@code true} if the specified component is enabled and matches the given flags. */
+    public abstract boolean isEnabledAndMatches(@NonNull ComponentInfo info, int flags, int userId);
+
+    /** Returns {@code true} if the given user requires extra badging for icons. */
+    public abstract boolean userNeedsBadging(int userId);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 54d383a..83757c4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -46,6 +46,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -244,7 +245,9 @@
 
     /** @hide */
     public static class NewPermissionInfo {
+        @UnsupportedAppUsage
         public final String name;
+        @UnsupportedAppUsage
         public final int sdkVersion;
         public final int fileVersion;
 
@@ -277,6 +280,7 @@
      * granted during a platform update.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
         new PackageParser.NewPermissionInfo[] {
             new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
@@ -322,6 +326,7 @@
     private String[] mSeparateProcesses;
     private boolean mOnlyCoreApps;
     private DisplayMetrics mMetrics;
+    @UnsupportedAppUsage
     private Callback mCallback;
     private File mCacheDir;
 
@@ -389,9 +394,11 @@
      * Lightweight parsed details about a single package.
      */
     public static class PackageLite {
+        @UnsupportedAppUsage
         public final String packageName;
         public final int versionCode;
         public final int versionCodeMajor;
+        @UnsupportedAppUsage
         public final int installLocation;
         public final VerifierInfo[] verifiers;
 
@@ -547,11 +554,13 @@
 
     private static final String TAG = "PackageParser";
 
+    @UnsupportedAppUsage
     public PackageParser() {
         mMetrics = new DisplayMetrics();
         mMetrics.setToDefaults();
     }
 
+    @UnsupportedAppUsage
     public void setSeparateProcesses(String[] procs) {
         mSeparateProcesses = procs;
     }
@@ -631,6 +640,7 @@
      * @param p the parsed package.
      * @param flags indicating which optional information is included.
      */
+    @UnsupportedAppUsage
     public static PackageInfo generatePackageInfo(PackageParser.Package p,
             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
             Set<String> grantedPermissions, PackageUserState state) {
@@ -665,6 +675,7 @@
         return checkUseInstalledOrHidden(0, state, null);
     }
 
+    @UnsupportedAppUsage
     public static PackageInfo generatePackageInfo(PackageParser.Package p,
             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
             Set<String> grantedPermissions, PackageUserState state, int userId) {
@@ -891,6 +902,7 @@
      *
      * @see PackageParser#parsePackage(File, int)
      */
+    @UnsupportedAppUsage
     public static PackageLite parsePackageLite(File packageFile, int flags)
             throws PackageParserException {
         if (packageFile.isDirectory()) {
@@ -1015,6 +1027,7 @@
      *
      * @see #parsePackageLite(File, int)
      */
+    @UnsupportedAppUsage
     public Package parsePackage(File packageFile, int flags, boolean useCaches)
             throws PackageParserException {
         Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
@@ -1045,6 +1058,7 @@
     /**
      * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
      */
+    @UnsupportedAppUsage
     public Package parsePackage(File packageFile, int flags) throws PackageParserException {
         return parsePackage(packageFile, flags, false /* useCaches */);
     }
@@ -1292,6 +1306,7 @@
      *             be marked private.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
         final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
         if (mOnlyCoreApps) {
@@ -1488,6 +1503,7 @@
      * populating {@link Package#mSigningDetails}. Also asserts that all APK
      * contents are signed correctly and consistently.
      */
+    @UnsupportedAppUsage
     public static void collectCertificates(Package pkg, boolean skipVerify)
             throws PackageParserException {
         collectCertificatesInternal(pkg, skipVerify);
@@ -1516,6 +1532,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
             throws PackageParserException {
         final String apkPath = apkFile.getAbsolutePath();
@@ -1885,6 +1902,7 @@
      * @throws XmlPullParserException
      * @throws IOException
      */
+    @UnsupportedAppUsage
     private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
             String[] outError) throws XmlPullParserException, IOException {
         final String splitName;
@@ -1982,7 +2000,7 @@
         String str = sa.getNonConfigurationString(
                 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
         if (str != null && str.length() > 0) {
-            String nameError = validateName(str, true, false);
+            String nameError = validateName(str, true, true);
             if (nameError != null && !"android".equals(pkg.packageName)) {
                 outError[0] = "<manifest> specifies bad sharedUserId name \""
                     + str + "\": " + nameError;
@@ -2507,6 +2525,49 @@
         if (pkg.applicationInfo.usesCompatibilityMode()) {
             adjustPackageToBeUnresizeableAndUnpipable(pkg);
         }
+
+        // If the storage model feature flag is disabled, we need to fiddle
+        // around with permission definitions to return us to pre-Q behavior.
+        // STOPSHIP(b/112545973): remove once feature enabled by default
+        if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+            if ("android".equals(pkg.packageName)) {
+                final ArraySet<String> newGroups = new ArraySet<>();
+                newGroups.add(android.Manifest.permission_group.MEDIA_AURAL);
+                newGroups.add(android.Manifest.permission_group.MEDIA_VISUAL);
+
+                for (int i = pkg.permissionGroups.size() - 1; i >= 0; i--) {
+                    final PermissionGroup pg = pkg.permissionGroups.get(i);
+                    if (newGroups.contains(pg.info.name)) {
+                        pkg.permissionGroups.remove(i);
+                    }
+                }
+
+                final ArraySet<String> newPermissions = new ArraySet<>();
+                newPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO);
+                newPermissions.add(android.Manifest.permission.WRITE_MEDIA_AUDIO);
+                newPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO);
+                newPermissions.add(android.Manifest.permission.WRITE_MEDIA_VIDEO);
+                newPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES);
+                newPermissions.add(android.Manifest.permission.WRITE_MEDIA_IMAGES);
+                newPermissions.add(android.Manifest.permission.ACCESS_MEDIA_LOCATION);
+                newPermissions.add(android.Manifest.permission.WRITE_OBB);
+
+                final ArraySet<String> dangerousPermissions = new ArraySet<>();
+                dangerousPermissions.add(android.Manifest.permission.READ_EXTERNAL_STORAGE);
+                dangerousPermissions.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
+
+                for (int i = pkg.permissions.size() - 1; i >= 0; i--) {
+                    final Permission p = pkg.permissions.get(i);
+                    if (newPermissions.contains(p.info.name)) {
+                        pkg.permissions.remove(i);
+                    } else if (dangerousPermissions.contains(p.info.name)) {
+                        p.info.protectionLevel &= ~PermissionInfo.PROTECTION_MASK_BASE;
+                        p.info.protectionLevel |= PermissionInfo.PROTECTION_DANGEROUS;
+                    }
+                }
+            }
+        }
+
         return pkg;
     }
 
@@ -3344,6 +3405,7 @@
      * When adding new features, carefully consider if they should also be
      * supported by split APKs.
      */
+    @UnsupportedAppUsage
     private boolean parseBaseApplication(Package owner, Resources res,
             XmlResourceParser parser, int flags, String[] outError)
         throws XmlPullParserException, IOException {
@@ -5701,6 +5763,7 @@
         }
 
         @Nullable
+        @UnsupportedAppUsage
         public final Signature[] signatures;
         @SignatureSchemeVersion
         public final int signatureSchemeVersion;
@@ -6166,28 +6229,33 @@
             private Signature[] mPastSigningCertificates;
             private int[] mPastSigningCertificatesFlags;
 
+            @UnsupportedAppUsage
             public Builder() {
             }
 
             /** get signing certificates used to sign the current APK */
+            @UnsupportedAppUsage
             public Builder setSignatures(Signature[] signatures) {
                 mSignatures = signatures;
                 return this;
             }
 
             /** set the signature scheme version used to sign the APK */
+            @UnsupportedAppUsage
             public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
                 mSignatureSchemeVersion = signatureSchemeVersion;
                 return this;
             }
 
             /** set the signing certificates by which the APK proved it can be authenticated */
+            @UnsupportedAppUsage
             public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
                 mPastSigningCertificates = pastSigningCertificates;
                 return this;
             }
 
             /** set the flags for the {@code pastSigningCertificates} */
+            @UnsupportedAppUsage
             public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
                 mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
                 return this;
@@ -6216,6 +6284,7 @@
                 }
             }
             /** build a {@code SigningDetails} object */
+            @UnsupportedAppUsage
             public SigningDetails build()
                     throws CertificateException {
                 checkInvariants();
@@ -6231,6 +6300,7 @@
      */
     public final static class Package implements Parcelable {
 
+        @UnsupportedAppUsage
         public String packageName;
 
         // The package name declared in the manifest as the package can be
@@ -6274,18 +6344,28 @@
         public boolean baseHardwareAccelerated;
 
         // For now we only support one application per package.
+        @UnsupportedAppUsage
         public ApplicationInfo applicationInfo = new ApplicationInfo();
 
+        @UnsupportedAppUsage
         public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
+        @UnsupportedAppUsage
         public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
+        @UnsupportedAppUsage
         public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
+        @UnsupportedAppUsage
         public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
+        @UnsupportedAppUsage
         public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
+        @UnsupportedAppUsage
         public final ArrayList<Service> services = new ArrayList<Service>(0);
+        @UnsupportedAppUsage
         public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
 
+        @UnsupportedAppUsage
         public final ArrayList<String> requestedPermissions = new ArrayList<String>();
 
+        @UnsupportedAppUsage
         public ArrayList<String> protectedBroadcasts;
 
         public Package parentPackage;
@@ -6294,11 +6374,14 @@
         public String staticSharedLibName = null;
         public long staticSharedLibVersion = 0;
         public ArrayList<String> libraryNames = null;
+        @UnsupportedAppUsage
         public ArrayList<String> usesLibraries = null;
         public ArrayList<String> usesStaticLibraries = null;
         public long[] usesStaticLibrariesVersions = null;
         public String[][] usesStaticLibrariesCertDigests = null;
+        @UnsupportedAppUsage
         public ArrayList<String> usesOptionalLibraries = null;
+        @UnsupportedAppUsage
         public String[] usesLibraryFiles = null;
 
         public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
@@ -6308,9 +6391,11 @@
         public ArrayList<String> mAdoptPermissions = null;
 
         // We store the application meta-data independently to avoid multiple unwanted references
+        @UnsupportedAppUsage
         public Bundle mAppMetaData = null;
 
         // The version code declared for this package.
+        @UnsupportedAppUsage
         public int mVersionCode;
 
         // The major version code declared for this package.
@@ -6322,19 +6407,24 @@
         }
 
         // The version name declared for this package.
+        @UnsupportedAppUsage
         public String mVersionName;
 
         // The shared user id that this package wants to use.
+        @UnsupportedAppUsage
         public String mSharedUserId;
 
         // The shared user label that this package wants to use.
+        @UnsupportedAppUsage
         public int mSharedUserLabel;
 
         // Signatures that were read from the package.
+        @UnsupportedAppUsage
         @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
 
         // For use by package manager service for quick lookup of
         // preferred up order.
+        @UnsupportedAppUsage
         public int mPreferredOrder = 0;
 
         // For use by package manager to keep track of when a package was last used.
@@ -6348,17 +6438,21 @@
         // public boolean mSetStopped = false;
 
         // Additional data supplied by callers.
+        @UnsupportedAppUsage
         public Object mExtras;
 
         // Applications hardware preferences
+        @UnsupportedAppUsage
         public ArrayList<ConfigurationInfo> configPreferences = null;
 
         // Applications requested features
+        @UnsupportedAppUsage
         public ArrayList<FeatureInfo> reqFeatures = null;
 
         // Applications requested feature groups
         public ArrayList<FeatureGroupInfo> featureGroups = null;
 
+        @UnsupportedAppUsage
         public int installLocation;
 
         public boolean coreApp;
@@ -6383,7 +6477,9 @@
         /**
          * Data used to feed the KeySetManagerService
          */
+        @UnsupportedAppUsage
         public ArraySet<String> mUpgradeKeySets;
+        @UnsupportedAppUsage
         public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
 
         /**
@@ -6409,6 +6505,7 @@
         /** Whether or not the package is a stub and must be replaced by the full version. */
         public boolean isStub;
 
+        @UnsupportedAppUsage
         public Package(String packageName) {
             this.packageName = packageName;
             this.manifestPackageName = packageName;
@@ -6606,6 +6703,7 @@
             return paths;
         }
 
+        @UnsupportedAppUsage
         public void setPackageName(String newName) {
             packageName = newName;
             applicationInfo.packageName = newName;
@@ -6687,6 +6785,11 @@
         }
 
         /** @hide */
+        public boolean isProductServices() {
+            return applicationInfo.isProductServices();
+        }
+
+        /** @hide */
         public boolean isPrivileged() {
             return applicationInfo.isPrivilegedApp();
         }
@@ -7094,10 +7197,14 @@
     }
 
     public static abstract class Component<II extends IntentInfo> {
+        @UnsupportedAppUsage
         public final ArrayList<II> intents;
+        @UnsupportedAppUsage
         public final String className;
 
+        @UnsupportedAppUsage
         public Bundle metaData;
+        @UnsupportedAppUsage
         public Package owner;
         /** The order of this component in relation to its peers */
         public int order;
@@ -7160,6 +7267,7 @@
             componentShortName = clone.componentShortName;
         }
 
+        @UnsupportedAppUsage
         public ComponentName getComponentName() {
             if (componentName != null) {
                 return componentName;
@@ -7263,8 +7371,11 @@
     }
 
     public final static class Permission extends Component<IntentInfo> implements Parcelable {
+        @UnsupportedAppUsage
         public final PermissionInfo info;
+        @UnsupportedAppUsage
         public boolean tree;
+        @UnsupportedAppUsage
         public PermissionGroup group;
 
         public Permission(Package _owner) {
@@ -7272,6 +7383,7 @@
             info = new PermissionInfo();
         }
 
+        @UnsupportedAppUsage
         public Permission(Package _owner, PermissionInfo _info) {
             super(_owner);
             info = _info;
@@ -7330,6 +7442,7 @@
     }
 
     public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
+        @UnsupportedAppUsage
         public final PermissionGroupInfo info;
 
         public PermissionGroup(Package _owner) {
@@ -7420,6 +7533,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
             PackageUserState state) {
         return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
@@ -7475,6 +7589,7 @@
         ai.resourceDirs = state.overlayPaths;
     }
 
+    @UnsupportedAppUsage
     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
             PackageUserState state, int userId) {
         if (p == null) return null;
@@ -7532,6 +7647,7 @@
         return ai;
     }
 
+    @UnsupportedAppUsage
     public static final PermissionInfo generatePermissionInfo(
             Permission p, int flags) {
         if (p == null) return null;
@@ -7543,6 +7659,7 @@
         return pi;
     }
 
+    @UnsupportedAppUsage
     public static final PermissionGroupInfo generatePermissionGroupInfo(
             PermissionGroup pg, int flags) {
         if (pg == null) return null;
@@ -7555,6 +7672,7 @@
     }
 
     public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
+        @UnsupportedAppUsage
         public final ActivityInfo info;
         private boolean mHasMaxAspectRatio;
 
@@ -7638,6 +7756,7 @@
         };
     }
 
+    @UnsupportedAppUsage
     public static final ActivityInfo generateActivityInfo(Activity a, int flags,
             PackageUserState state, int userId) {
         if (a == null) return null;
@@ -7669,6 +7788,7 @@
     }
 
     public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
+        @UnsupportedAppUsage
         public final ServiceInfo info;
 
         public Service(final ParseComponentArgs args, final ServiceInfo _info) {
@@ -7728,6 +7848,7 @@
         };
     }
 
+    @UnsupportedAppUsage
     public static final ServiceInfo generateServiceInfo(Service s, int flags,
             PackageUserState state, int userId) {
         if (s == null) return null;
@@ -7746,7 +7867,9 @@
     }
 
     public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
+        @UnsupportedAppUsage
         public final ProviderInfo info;
+        @UnsupportedAppUsage
         public boolean syncable;
 
         public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
@@ -7756,6 +7879,7 @@
             syncable = false;
         }
 
+        @UnsupportedAppUsage
         public Provider(Provider existingProvider) {
             super(existingProvider);
             this.info = existingProvider.info;
@@ -7822,6 +7946,7 @@
         };
     }
 
+    @UnsupportedAppUsage
     public static final ProviderInfo generateProviderInfo(Provider p, int flags,
             PackageUserState state, int userId) {
         if (p == null) return null;
@@ -7846,6 +7971,7 @@
 
     public final static class Instrumentation extends Component<IntentInfo> implements
             Parcelable {
+        @UnsupportedAppUsage
         public final InstrumentationInfo info;
 
         public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
@@ -7903,6 +8029,7 @@
         };
     }
 
+    @UnsupportedAppUsage
     public static final InstrumentationInfo generateInstrumentationInfo(
             Instrumentation i, int flags) {
         if (i == null) return null;
@@ -7915,14 +8042,21 @@
     }
 
     public static abstract class IntentInfo extends IntentFilter {
+        @UnsupportedAppUsage
         public boolean hasDefault;
+        @UnsupportedAppUsage
         public int labelRes;
+        @UnsupportedAppUsage
         public CharSequence nonLocalizedLabel;
+        @UnsupportedAppUsage
         public int icon;
+        @UnsupportedAppUsage
         public int logo;
+        @UnsupportedAppUsage
         public int banner;
         public int preferred;
 
+        @UnsupportedAppUsage
         protected IntentInfo() {
         }
 
@@ -7951,6 +8085,7 @@
     }
 
     public final static class ActivityIntentInfo extends IntentInfo {
+        @UnsupportedAppUsage
         public Activity activity;
 
         public ActivityIntentInfo(Activity _activity) {
@@ -7973,6 +8108,7 @@
     }
 
     public final static class ServiceIntentInfo extends IntentInfo {
+        @UnsupportedAppUsage
         public Service service;
 
         public ServiceIntentInfo(Service _service) {
@@ -7995,6 +8131,7 @@
     }
 
     public static final class ProviderIntentInfo extends IntentInfo {
+        @UnsupportedAppUsage
         public Provider provider;
 
         public ProviderIntentInfo(Provider provider) {
@@ -8019,6 +8156,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
         sCompatibilityModeEnabled = compatibilityModeEnabled;
     }
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index 27b3506..f70ec39 100644
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.usage.StorageStatsManager;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -37,6 +38,7 @@
     public String packageName;
 
     /** @hide */
+    @UnsupportedAppUsage
     public int userHandle;
 
     /** Size of the code (e.g., APK) */
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index de173c4..248d523 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -28,6 +28,7 @@
 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.BaseBundle;
 import android.os.PersistableBundle;
 import android.util.ArraySet;
@@ -67,6 +68,7 @@
 
     public String[] overlayPaths;
 
+    @UnsupportedAppUsage
     public PackageUserState() {
         installed = true;
         hidden = false;
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
index d12e884..2eef165 100644
--- a/core/java/android/content/pm/ParceledListSlice.java
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -31,6 +32,7 @@
  * @hide
  */
 public class ParceledListSlice<T extends Parcelable> extends BaseParceledListSlice<T> {
+    @UnsupportedAppUsage
     public ParceledListSlice(List<T> list) {
         super(list);
     }
@@ -59,6 +61,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     protected void writeParcelableCreator(T parcelable, Parcel dest) {
         dest.writeParcelableCreator((Parcelable) parcelable);
     }
@@ -69,6 +72,7 @@
     }
 
     @SuppressWarnings("unchecked")
+    @UnsupportedAppUsage
     public static final Parcelable.ClassLoaderCreator<ParceledListSlice> CREATOR =
             new Parcelable.ClassLoaderCreator<ParceledListSlice>() {
         public ParceledListSlice createFromParcel(Parcel in) {
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 535ef00..60c06a1 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -322,6 +323,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static String protectionToString(int level) {
         String protLevel = "????";
         switch (level & PROTECTION_MASK_BASE) {
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 020e8c2..a8c3b88 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.Manifest;
+import android.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -145,6 +146,7 @@
     private RegisteredServicesCacheListener<V> mListener;
     private Handler mHandler;
 
+    @UnsupportedAppUsage
     public RegisteredServicesCache(Context context, String interfaceName, String metaDataName,
             String attributeName, XmlSerializerAndParser<V> serializerAndParser) {
         mContext = context;
@@ -299,9 +301,12 @@
      * to bind to the service.
      */
     public static class ServiceInfo<V> {
+        @UnsupportedAppUsage
         public final V type;
         public final ComponentInfo componentInfo;
+        @UnsupportedAppUsage
         public final ComponentName componentName;
+        @UnsupportedAppUsage
         public final int uid;
 
         /** @hide */
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index fc2eba2..701c5db 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.IntentFilter;
 import android.graphics.drawable.Drawable;
@@ -149,6 +150,7 @@
      * If not equal to UserHandle.USER_CURRENT, then the intent will be forwarded to this user.
      * @hide
      */
+    @UnsupportedAppUsage
     public int targetUserId;
 
     /**
@@ -169,14 +171,17 @@
     /**
      * @hide Target comes from system process?
      */
+    @UnsupportedAppUsage
     public boolean system;
 
     /**
      * @hide Does the associated IntentFilter comes from a Browser ?
      */
+    @UnsupportedAppUsage
     public boolean handleAllWebDataURI;
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public ComponentInfo getComponentInfo() {
         if (activityInfo != null) return activityInfo;
         if (serviceInfo != null) return serviceInfo;
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index ea476b0..546c213 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.app.TaskStackBuilder;
 import android.content.ComponentName;
@@ -1242,6 +1243,7 @@
      * @hide
      */
     @Nullable
+    @UnsupportedAppUsage
     public Icon getIcon() {
         return mIcon;
     }
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 25e0ccd..60ac1f0 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -19,8 +19,8 @@
 import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
-import android.app.Activity;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.content.Intent;
@@ -29,256 +29,23 @@
 import android.os.Build.VERSION_CODES;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.UserHandle;
 
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.List;
 
 /**
- * The ShortcutManager performs operations on an app's set of <em>shortcuts</em>. The
- * {@link ShortcutInfo} class contains information about each of the shortcuts themselves.
+ * <p><code>ShortcutManager</code> executes operations on an app's set of <i>shortcuts</i>, which
+ * represent specific tasks and actions that users can perform within your app. This page lists
+ * components of the <code>ShortcutManager</code> class that you can use to create and manage
+ * sets of shortcuts.
  *
- * <p>An app's shortcuts represent specific tasks and actions that users can perform within your
- * app. When a user selects a shortcut in the currently-active launcher, your app opens an activity
- * other than the app's starting activity, provided that the currently-active launcher supports app
- * shortcuts.</p>
+ * <p>To learn about methods that retrieve information about a single shortcut&mdash;including
+ * identifiers, type, and status&mdash;read the <code>
+ * <a href="/reference/android/content/pm/ShortcutInfo.html">ShortcutInfo</a></code> reference.
  *
- * <p>The types of shortcuts that you create for your app depend on the app's key use cases. For
- * example, an email app may publish the "compose new email" shortcut, which allows the app to
- * directly open the compose activity.</p>
- *
- * <p class="note"><b>Note:</b> Only main activities&mdash;activities that handle the
- * {@link Intent#ACTION_MAIN} action and the {@link Intent#CATEGORY_LAUNCHER} category&mdash;can
- * have shortcuts. If an app has multiple main activities, you need to define the set of shortcuts
- * for <em>each</em> activity.
- *
- * <p>This page discusses the implementation details of the <code>ShortcutManager</code> class. For
- * definitions of key terms and guidance on performing operations on shortcuts within your app, see
- * the <a href="/guide/topics/ui/shortcuts.html">App Shortcuts</a> feature guide.
- *
- * <h3>Shortcut characteristics</h3>
- *
- * This section describes in-depth details about each shortcut type's usage and availability.
- *
- * <p class="note"><b>Important security note:</b> All shortcut information is stored in
- * <a href="/training/articles/direct-boot.html">credential encrypted storage</a>, so your app
- * cannot access a user's shortcuts until after they've unlocked the device.
- *
- * <h4>Static and dynamic shortcuts</h4>
- *
- * <p>Static shortcuts and dynamic shortcuts are shown in a supported launcher when the user
- * performs a specific gesture. On currently-supported launchers, the gesture is a long-press on the
- * app's launcher icon, but the actual gesture may be different on other launcher apps.
- *
- * <p>The {@link LauncherApps} class provides APIs for launcher apps to access shortcuts.
- *
- * <h4>Pinned shortcuts</h4>
- *
- * <p>Because pinned shortcuts appear in the launcher itself, they're always visible. A pinned
- * shortcut is removed from the launcher only in the following situations:
- * <ul>
- *     <li>The user removes it.
- *     <li>The publisher app associated with the shortcut is uninstalled.
- *     <li>The user selects <b>Clear data</b> from the publisher app's <i>Storage</i> screen, within
- *     the system's <b>Settings</b> app.
- * </ul>
- *
- * <p>Because the system performs
- * <a href="/guide/topics/ui/shortcuts.html#backup-and-restore">backup and restore</a> on pinned
- * shortcuts automatically, these shortcuts' IDs should contain either stable, constant strings or
- * server-side identifiers, rather than identifiers generated locally that might not make sense on
- * other devices.
- *
- * <h3>Shortcut display order</h3>
- *
- * <p>When the launcher displays an app's shortcuts, they should appear in the following order:
- *
- * <ol>
- *   <li><b>Static shortcuts:</b> Shortcuts whose {@link ShortcutInfo#isDeclaredInManifest()} method
- *   returns {@code true}.</li>
- *   <li><b>Dynamic shortcuts:</b> Shortcuts whose {@link ShortcutInfo#isDynamic()} method returns
- *   {@code true}.</li>
- * </ol>
- *
- * <p>Within each shortcut type (static and dynamic), shortcuts are sorted in order of increasing
- * rank according to {@link ShortcutInfo#getRank()}.</p>
- *
- * <h4>Shortcut ranks</h4>
- *
- * <p>Shortcut ranks are non-negative, sequential integers that determine the order in which
- * shortcuts appear, assuming that the shortcuts are all in the same category. You can update ranks
- * of existing shortcuts when you call {@link #updateShortcuts(List)},
- * {@link #addDynamicShortcuts(List)}, or {@link #setDynamicShortcuts(List)}.
- *
- * <p class="note"><b>Note:</b> Ranks are auto-adjusted so that they're unique for each type of
- * shortcut (static or dynamic). For example, if there are 3 dynamic shortcuts with ranks 0, 1 and
- * 2, adding another dynamic shortcut with a rank of 1 represents a request to place this shortcut
- * at the second position. In response, the third and fourth shortcuts move closer to the bottom of
- * the shortcut list, with their ranks changing to 2 and 3, respectively.
- *
- * <h3>Options for static shortcuts</h3>
- *
- * The following list includes descriptions for the different attributes within a static shortcut.
- * You must provide a value for {@code android:shortcutId} and {@code android:shortcutShortLabel};
- * all other values are optional.
- *
- * <dl>
- *   <dt>{@code android:shortcutId}</dt>
- *   <dd><p>A string literal, which represents the shortcut when a {@code ShortcutManager} object
- *   performs operations on it.</p>
- *   <p class="note"><b>Note: </b>You cannot set this attribute's value to a resource string, such
- *   as <code>@string/foo</code>.</p>
- *   </dd>
- *
- *   <dt>{@code android:enabled}</dt>
- *   <dd><p>Whether the user can interact with the shortcut from a supported launcher.</p>
- *   <p>The default value is {@code true}. If you set it to {@code false}, you should also set
- *   {@code android:shortcutDisabledMessage} to a message that explains why you've disabled the
- *   shortcut. If you don't think you need to provide such a message, it's easiest to just remove
- *   the shortcut from the XML file entirely, rather than changing the values of the shortcut's
- *   {@code android:enabled} and {@code android:shortcutDisabledMessage} attributes.
- *   </dd>
- *
- *   <dt>{@code android:icon}</dt>
- *   <dd><p>The <a href="/topic/performance/graphics/index.html">bitmap</a> or
- *   <a href="/guide/practices/ui_guidelines/icon_design_adaptive.html">adaptive icon</a> that the
- *   launcher uses when displaying the shortcut to the user. This value can be either the path to an
- *   image or the resource file that contains the image. Use adaptive icons whenever possible to
- *   improve performance and consistency.</p>
- *   <p class="note"><b>Note: </b>Shortcut icons cannot include
- *   <a href="/training/material/drawables.html#DrawableTint">tints</a>.
- *   </dd>
- *
- *   <dt>{@code android:shortcutShortLabel}</dt>
- *   <dd><p>A concise phrase that describes the shortcut's purpose. For more information, see
- *   {@link ShortcutInfo.Builder#setShortLabel(CharSequence)}.</p>
- *   <p class="note"><b>Note: </b>This attribute's value must be a resource string, such as
- *   <code>@string/shortcut_short_label</code>.</p>
- *   </dd>
- *
- *   <dt>{@code android:shortcutLongLabel}</dt>
- *   <dd><p>An extended phrase that describes the shortcut's purpose. If there's enough space, the
- *   launcher displays this value instead of {@code android:shortcutShortLabel}. For more
- *   information, see {@link ShortcutInfo.Builder#setLongLabel(CharSequence)}.</p>
- *   <p class="note"><b>Note: </b>This attribute's value must be a resource string, such as
- *   <code>@string/shortcut_long_label</code>.</p>
- *   </dd>
- *
- *   <dt>{@code android:shortcutDisabledMessage}</dt>
- *   <dd><p>The message that appears in a supported launcher when the user attempts to launch a
- *   disabled shortcut. The message should explain to the user why the shortcut is now disabled.
- *   This attribute's value has no effect if {@code android:enabled} is {@code true}.</p>
- *   <p class="note"><b>Note: </b>This attribute's value must be a resource string, such as
- *   <code>@string/shortcut_disabled_message</code>.</p>
- *   </dd>
- * </dl>
- *
- * <h3>Inner elements that define static shortcuts</h3>
- *
- * <p>The XML file that lists an app's static shortcuts supports the following elements inside each
- * {@code <shortcut>} element. You must include an {@code intent} inner element for each
- * static shortcut that you define.</p>
- *
- * <dl>
- *   <dt>{@code intent}</dt>
- *   <dd><p>The action that the system launches when the user selects the shortcut. This intent must
- *   provide a value for the {@code android:action} attribute.</p>
- *   <p>You can provide multiple intents for a single shortcut. If you do so, the last defined
- *   activity is launched, and the other activities are placed in the
- *   <a href="/guide/components/tasks-and-back-stack.html">back stack</a>. See
- *   <a href="/guide/topics/ui/shortcuts.html#static">Using Static Shortcuts</a> and the
- *   {@link android.app.TaskStackBuilder} class reference for details.</p>
- *   <p class="note"><b>Note:</b> This {@code intent} element cannot include string resources.</p>
- *   <p>To learn more about how to configure intents, see
- *   <a href="{@docRoot}guide/topics/ui/settings.html#Intents">Using intents</a>.</p>
- *   </dd>
- *
- *   <dt>{@code categories}</dt>
- *   <dd><p>Provides a grouping for the types of actions that your app's shortcuts perform, such as
- *   creating new chat messages.</p>
- *   <p>For a list of supported shortcut categories, see the {@link ShortcutInfo} class reference
- *   for a list of supported shortcut categories.
- *   </dd>
- * </dl>
- *
- * <h3>Updating shortcuts</h3>
- *
- * <p>Each app's launcher icon can contain at most {@link #getMaxShortcutCountPerActivity()} number
- * of static and dynamic shortcuts combined. There is no limit to the number of pinned shortcuts
- * that an app can create, though.
- *
- * <p>When a dynamic shortcut is pinned, even when the publisher removes it as a dynamic shortcut,
- * the pinned shortcut is still visible and launchable.  This allows an app to have more than
- * {@link #getMaxShortcutCountPerActivity()} number of shortcuts.
- *
- * <p>As an example, suppose {@link #getMaxShortcutCountPerActivity()} is 5:
- * <ol>
- *     <li>A chat app publishes 5 dynamic shortcuts for the 5 most recent
- *     conversations (c1, c2, ..., c5).
- *
- *     <li>The user pins all 5 of the shortcuts.
- *
- *     <li>Later, the user has started 3 additional conversations (c6, c7, and c8), so the publisher
- *     app re-publishes its dynamic shortcuts. The new dynamic shortcut list is: c4, c5, ..., c8.
- *     <p>The publisher app has to remove c1, c2, and c3 because it can't have more than 5 dynamic
- *     shortcuts. However, c1, c2, and c3 are still pinned shortcuts that the user can access and
- *     launch.
- *     <p>At this point, the user can access a total of 8 shortcuts that link to activities in the
- *     publisher app, including the 3 pinned shortcuts, even though an app can have at most 5
- *     dynamic shortcuts.
- *
- *     <li>The app can use {@link #updateShortcuts(List)} to update <em>any</em> of the existing
- *     8 shortcuts, when, for example, the chat peers' icons have changed.
- *     <p>The {@link #addDynamicShortcuts(List)} and {@link #setDynamicShortcuts(List)} methods
- *     can also be used to update existing shortcuts with the same IDs, but they <b>cannot</b> be
- *     used for updating non-dynamic, pinned shortcuts because these 2 methods try to convert the
- *     given lists of shortcuts to dynamic shortcuts.
- * </ol>
- *
- * <h3>Shortcut intents</h3>
- *
- * <p>
- * Dynamic shortcuts can be published with any set of {@link Intent#addFlags Intent} flags.
- * Typically, {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} is specified, possibly along with other
- * flags; otherwise, if the app is already running, the app is simply brought to
- * the foreground, and the target activity might not appear.
- *
- * <p>Static shortcuts <b>cannot</b> have custom intent flags.
- * The first intent of a static shortcut will always have {@link Intent#FLAG_ACTIVITY_NEW_TASK}
- * and {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} set. This means, when the app is already running, all
- * the existing activities in your app are destroyed when a static shortcut is launched.
- * If this behavior is not desirable, you can use a <em>trampoline activity</em>, or an invisible
- * activity that starts another activity in {@link Activity#onCreate}, then calls
- * {@link Activity#finish()}:
- * <ol>
- *     <li>In the <code>AndroidManifest.xml</code> file, the trampoline activity should include the
- *     attribute assignment {@code android:taskAffinity=""}.
- *     <li>In the shortcuts resource file, the intent within the static shortcut should reference
- *     the trampoline activity.
- * </ol>
- *
- * <h3>Rate limiting</h3>
- *
- * <p>When <a href="/guide/topics/ui/shortcuts.html#rate-limit">rate limiting</a> is active,
- * {@link #isRateLimitingActive()} returns {@code true}.
- *
- * <p>Rate limiting is reset upon certain events, so even background apps can call these APIs until
- * the rate limit is reached again. These events include the following:
- * <ul>
- *   <li>An app comes to the foreground.
- *   <li>The system locale changes.
- *   <li>The user performs the <a href="/guide/topics/ui/notifiers/notifications.html#direct">inline
- *   reply</a> action on a notification.
- * </ul>
- *
- * <h3>Handling system locale changes</h3>
- *
- * <p>Apps should update dynamic and pinned shortcuts when they receive the
- * {@link Intent#ACTION_LOCALE_CHANGED} broadcast, indicating that the system locale has changed.
- * <p>When the system locale changes, <a href="/guide/topics/ui/shortcuts.html#rate-limit">rate
- * limiting</a> is reset, so even background apps can add and update dynamic shortcuts until the
- * rate limit is reached again.
+ * <p>For guidance about using shortcuts, see
+ * <a href="/guide/topics/ui/shortcuts/index.html">App shortcuts</a>.
  *
  * <h3>Retrieving class instances</h3>
  * <!-- Provides a heading for the content filled in by the @SystemService annotation below -->
@@ -288,6 +55,7 @@
     private static final String TAG = "ShortcutManager";
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private final IShortcutService mService;
 
     /**
@@ -458,8 +226,9 @@
     }
 
     /**
-     * Disable pinned shortcuts.  For more details, see the Javadoc for the {@link ShortcutManager}
-     * class.
+     * Disable pinned shortcuts.  For more details, read
+     * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts">
+     * Disable shortcuts</a>.
      *
      * @throws IllegalArgumentException If trying to disable immutable shortcuts.
      *
@@ -498,7 +267,9 @@
     /**
      * Disable pinned shortcuts, showing the user a custom error message when they try to select
      * the disabled shortcuts.
-     * For more details, see the Javadoc for the {@link ShortcutManager} class.
+     * For more details, read
+     * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts">
+     * Disable shortcuts</a>.
      *
      * @throws IllegalArgumentException If trying to disable immutable shortcuts.
      *
@@ -586,7 +357,8 @@
     /**
      * Return {@code true} when rate-limiting is active for the caller app.
      *
-     * <p>See the class level javadoc for details.
+     * <p>For details, see <a href="/guide/topics/ui/shortcuts/managing-shortcuts#rate-limiting">
+     * Rate limiting</a>.
      *
      * @throws IllegalStateException when the user is locked.
      */
@@ -632,7 +404,9 @@
      * Apps that publish shortcuts should call this method whenever the user
      * selects the shortcut containing the given ID or when the user completes
      * an action in the app that is equivalent to selecting the shortcut.
-     * For more details, see the Javadoc for the {@link ShortcutManager} class
+     * For more details, read about
+     * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#track-usage">
+     * tracking shortcut usage</a>.
      *
      * <p>The information is accessible via {@link UsageStatsManager#queryEvents}
      * Typically, launcher apps use this information to build a prediction model
@@ -700,7 +474,9 @@
      * @param resultIntent If not null, this intent will be sent when the shortcut is pinned.
      *    Use {@link android.app.PendingIntent#getIntentSender()} to create an {@link IntentSender}.
      *    To avoid background execution limits, use an unexported, manifest-declared receiver.
-     *    For more details, see the overview documentation for the {@link ShortcutManager} class.
+     *    For more details, see
+     *    <a href="/guide/topics/ui/shortcuts/creating-shortcuts.html#pinned">
+     *    Creating pinned shortcuts</a>.
      *
      * @return {@code TRUE} if the launcher supports this feature.  Note the API will return without
      *    waiting for the user to respond, so getting {@code TRUE} from this API does *not* mean
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index a2a14ed..e58ca60 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -170,6 +171,7 @@
      *             certificate; shouldn't happen.
      * @hide
      */
+    @UnsupportedAppUsage
     public PublicKey getPublicKey() throws CertificateException {
         final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
         final ByteArrayInputStream bais = new ByteArrayInputStream(mSignature);
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index f34b590..b75ed35 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemProperties;
@@ -41,6 +42,7 @@
      * Primary user. Only one user can have this flag set. It identifies the first human user
      * on a device.
      */
+    @UnsupportedAppUsage
     public static final int FLAG_PRIMARY = 0x00000001;
 
     /**
@@ -94,12 +96,19 @@
 
     public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL;
 
+    @UnsupportedAppUsage
     public int id;
+    @UnsupportedAppUsage
     public int serialNumber;
+    @UnsupportedAppUsage
     public String name;
+    @UnsupportedAppUsage
     public String iconPath;
+    @UnsupportedAppUsage
     public int flags;
+    @UnsupportedAppUsage
     public long creationTime;
+    @UnsupportedAppUsage
     public long lastLoggedInTime;
     public String lastLoggedInFingerprint;
     /**
@@ -107,19 +116,24 @@
      * If this user is a child user, it would be its parent user id.
      * Otherwise, it would be {@link #NO_PROFILE_GROUP_ID}.
      */
+    @UnsupportedAppUsage
     public int profileGroupId;
     public int restrictedProfileParentId;
     /** Which profile badge color/label to use. */
     public int profileBadge;
 
     /** User is only partially created. */
+    @UnsupportedAppUsage
     public boolean partial;
+    @UnsupportedAppUsage
     public boolean guestToRemove;
 
+    @UnsupportedAppUsage
     public UserInfo(int id, String name, int flags) {
         this(id, name, null, flags);
     }
 
+    @UnsupportedAppUsage
     public UserInfo(int id, String name, String iconPath, int flags) {
         this.id = id;
         this.name = name;
@@ -129,26 +143,32 @@
         this.restrictedProfileParentId = NO_PROFILE_GROUP_ID;
     }
 
+    @UnsupportedAppUsage
     public boolean isPrimary() {
         return (flags & FLAG_PRIMARY) == FLAG_PRIMARY;
     }
 
+    @UnsupportedAppUsage
     public boolean isAdmin() {
         return (flags & FLAG_ADMIN) == FLAG_ADMIN;
     }
 
+    @UnsupportedAppUsage
     public boolean isGuest() {
         return (flags & FLAG_GUEST) == FLAG_GUEST;
     }
 
+    @UnsupportedAppUsage
     public boolean isRestricted() {
         return (flags & FLAG_RESTRICTED) == FLAG_RESTRICTED;
     }
 
+    @UnsupportedAppUsage
     public boolean isManagedProfile() {
         return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE;
     }
 
+    @UnsupportedAppUsage
     public boolean isEnabled() {
         return (flags & FLAG_DISABLED) != FLAG_DISABLED;
     }
@@ -238,6 +258,7 @@
         profileBadge = orig.profileBadge;
     }
 
+    @UnsupportedAppUsage
     public UserHandle getUserHandle() {
         return new UserHandle(id);
     }
@@ -267,6 +288,7 @@
         dest.writeInt(profileBadge);
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<UserInfo> CREATOR
             = new Parcelable.Creator<UserInfo>() {
         public UserInfo createFromParcel(Parcel source) {
diff --git a/core/java/android/content/pm/VerifierInfo.java b/core/java/android/content/pm/VerifierInfo.java
index 0a2b283..b4e72e6 100644
--- a/core/java/android/content/pm/VerifierInfo.java
+++ b/core/java/android/content/pm/VerifierInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -43,6 +44,7 @@
      *            not be {@code null} or empty.
      * @throws IllegalArgumentException if either argument is null or empty.
      */
+    @UnsupportedAppUsage
     public VerifierInfo(String packageName, PublicKey publicKey) {
         if (packageName == null || packageName.length() == 0) {
             throw new IllegalArgumentException("packageName must not be null or empty");
diff --git a/core/java/android/content/pm/XmlSerializerAndParser.java b/core/java/android/content/pm/XmlSerializerAndParser.java
index 20cb61c..6d24800 100644
--- a/core/java/android/content/pm/XmlSerializerAndParser.java
+++ b/core/java/android/content/pm/XmlSerializerAndParser.java
@@ -20,10 +20,13 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.IOException;
 
 /** @hide */
 public interface XmlSerializerAndParser<T> {
+    @UnsupportedAppUsage
     void writeAsXml(T item, XmlSerializer out) throws IOException;
+    @UnsupportedAppUsage
     T createFromXml(XmlPullParser parser) throws IOException, XmlPullParserException;
 }
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index 9de8be3..dc1d052 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -16,6 +16,7 @@
 package android.content.res;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
@@ -125,6 +126,7 @@
         mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
     }
 
+    @UnsupportedAppUsage
     public @NonNull String getAssetPath() {
         synchronized (this) {
             return nativeGetAssetPath(mNativePtr);
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java
index be41036..b6cbf08 100644
--- a/core/java/android/content/res/AssetFileDescriptor.java
+++ b/core/java/android/content/res/AssetFileDescriptor.java
@@ -16,6 +16,7 @@
 
 package android.content.res;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
@@ -40,8 +41,11 @@
      */
     public static final long UNKNOWN_LENGTH = -1;
     
+    @UnsupportedAppUsage
     private final ParcelFileDescriptor mFd;
+    @UnsupportedAppUsage
     private final long mStartOffset;
+    @UnsupportedAppUsage
     private final long mLength;
     private final Bundle mExtras;
 
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 2895342..0350eff 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration.NativeConfig;
 import android.os.ParcelFileDescriptor;
@@ -65,6 +66,7 @@
     private static final ApkAssets[] sEmptyApkAssets = new ApkAssets[0];
 
     // Not private for LayoutLib's BridgeAssetManager.
+    @UnsupportedAppUsage
     @GuardedBy("sSync") static AssetManager sSystem = null;
 
     @GuardedBy("sSync") private static ApkAssets[] sSystemApkAssets = new ApkAssets[0];
@@ -95,6 +97,7 @@
     @GuardedBy("this") private final long[] mOffsets = new long[2];
 
     // Pointer to native implementation, stuffed inside a long.
+    @UnsupportedAppUsage
     @GuardedBy("this") private long mObject;
 
     // The loaded asset paths.
@@ -152,6 +155,7 @@
      * use by applications.
      * @hide
      */
+    @UnsupportedAppUsage
     public AssetManager() {
         final ApkAssets[] assets;
         synchronized (sSync) {
@@ -249,6 +253,7 @@
      * system assets (no application assets).
      * @hide
      */
+    @UnsupportedAppUsage
     public static AssetManager getSystem() {
         synchronized (sSync) {
             createSystemAssetsInZygoteLocked();
@@ -328,6 +333,7 @@
      * returns a 0-length array.
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull ApkAssets[] getApkAssets() {
         synchronized (this) {
             if (mOpen) {
@@ -362,6 +368,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public int addAssetPath(String path) {
         return addAssetPathInternal(path, false /*overlay*/, false /*appAsLib*/);
     }
@@ -371,6 +378,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public int addAssetPathAsSharedLibrary(String path) {
         return addAssetPathInternal(path, false /*overlay*/, true /*appAsLib*/);
     }
@@ -380,6 +388,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public int addOverlayPath(String path) {
         return addAssetPathInternal(path, true /*overlay*/, false /*appAsLib*/);
     }
@@ -457,6 +466,7 @@
      * @return {@code true} if the data was loaded into {@code outValue},
      *         {@code false} otherwise
      */
+    @UnsupportedAppUsage
     boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
             boolean resolveRefs) {
         Preconditions.checkNotNull(outValue, "outValue");
@@ -486,6 +496,7 @@
      * @param resId the resource identifier to load
      * @return the string value, or {@code null}
      */
+    @UnsupportedAppUsage
     @Nullable CharSequence getResourceText(@StringRes int resId) {
         synchronized (this) {
             final TypedValue outValue = mValue;
@@ -504,6 +515,7 @@
      * @param bagEntryId the index into the bag to load
      * @return the string value, or {@code null}
      */
+    @UnsupportedAppUsage
     @Nullable CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) {
         synchronized (this) {
             ensureValidLocked();
@@ -665,6 +677,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     @Nullable String getResourceName(@AnyRes int resId) {
         synchronized (this) {
             ensureValidLocked();
@@ -672,6 +685,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     @Nullable String getResourcePackageName(@AnyRes int resId) {
         synchronized (this) {
             ensureValidLocked();
@@ -679,6 +693,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     @Nullable String getResourceTypeName(@AnyRes int resId) {
         synchronized (this) {
             ensureValidLocked();
@@ -686,6 +701,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     @Nullable String getResourceEntryName(@AnyRes int resId) {
         synchronized (this) {
             ensureValidLocked();
@@ -693,6 +709,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     @AnyRes int getResourceIdentifier(@NonNull String name, @Nullable String defType,
             @Nullable String defPackage) {
         synchronized (this) {
@@ -804,6 +821,7 @@
      * @see #open(String)
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull InputStream openNonAsset(@NonNull String fileName) throws IOException {
         return openNonAsset(0, fileName, ACCESS_STREAMING);
     }
@@ -824,6 +842,7 @@
      * @see #open(String, int)
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull InputStream openNonAsset(@NonNull String fileName, int accessMode)
             throws IOException {
         return openNonAsset(0, fileName, accessMode);
@@ -836,6 +855,7 @@
      * @param fileName Name of the asset to retrieve.
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName)
             throws IOException {
         return openNonAsset(cookie, fileName, ACCESS_STREAMING);
@@ -849,6 +869,7 @@
      * @param accessMode Desired access mode for retrieving the data.
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName, int accessMode)
             throws IOException {
         Preconditions.checkNotNull(fileName, "fileName");
@@ -970,6 +991,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void applyStyle(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
             @Nullable XmlBlock.Parser parser, @NonNull int[] inAttrs, long outValuesAddress,
             long outIndicesAddress) {
@@ -984,6 +1006,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
             @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues,
             @NonNull int[] outIndices) {
@@ -999,6 +1022,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     boolean retrieveAttributes(@NonNull XmlBlock.Parser parser, @NonNull int[] inAttrs,
             @NonNull int[] outValues, @NonNull int[] outIndices) {
         Preconditions.checkNotNull(parser, "parser");
@@ -1014,6 +1038,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     long createTheme() {
         synchronized (this) {
             ensureValidLocked();
@@ -1066,6 +1091,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public final int getAssetInt() {
             throw new UnsupportedOperationException();
         }
@@ -1073,6 +1099,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public final long getNativeAsset() {
             return mAssetNativePtr;
         }
@@ -1169,6 +1196,7 @@
      * instantiate a new AssetManager class to see the new data.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isUpToDate() {
         for (ApkAssets apkAssets : getApkAssets()) {
             if (!apkAssets.isUpToDate()) {
@@ -1228,6 +1256,7 @@
      * applications.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setConfiguration(int mcc, int mnc, @Nullable String locale, int orientation,
             int touchscreen, int density, int keyboard, int keyboardHidden, int navigation,
             int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp,
@@ -1244,6 +1273,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public SparseArray<String> getAssignedPackageIdentifiers() {
         synchronized (this) {
             ensureValidLocked();
@@ -1367,6 +1397,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static native int getGlobalAssetCount();
 
     /**
@@ -1377,5 +1408,6 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static native int getGlobalAssetManagerCount();
 }
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index faf2381..16b9726 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -30,6 +30,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.MathUtils;
@@ -132,16 +133,21 @@
     private static final SparseArray<WeakReference<ColorStateList>> sCache = new SparseArray<>();
 
     /** Lazily-created factory for this color state list. */
+    @UnsupportedAppUsage
     private ColorStateListFactory mFactory;
 
     private int[][] mThemeAttrs;
     private @Config int mChangingConfigurations;
 
+    @UnsupportedAppUsage
     private int[][] mStateSpecs;
+    @UnsupportedAppUsage
     private int[] mColors;
+    @UnsupportedAppUsage
     private int mDefaultColor;
     private boolean mIsOpaque;
 
+    @UnsupportedAppUsage
     private ColorStateList() {
         // Not publicly instantiable.
     }
@@ -394,6 +400,7 @@
      * @hide only for resource preloading
      */
     @Override
+    @UnsupportedAppUsage
     public boolean canApplyTheme() {
         return mThemeAttrs != null;
     }
@@ -474,6 +481,7 @@
      * @hide only for resource preloading
      */
     @Override
+    @UnsupportedAppUsage
     public ColorStateList obtainForTheme(Theme t) {
         if (t == null || !canApplyTheme()) {
             return this;
@@ -579,6 +587,7 @@
      * @return the states in this {@link ColorStateList}
      * @hide
      */
+    @UnsupportedAppUsage
     public int[][] getStates() {
         return mStateSpecs;
     }
@@ -590,6 +599,7 @@
      * @return the colors in this {@link ColorStateList}
      * @hide
      */
+    @UnsupportedAppUsage
     public int[] getColors() {
         return mColors;
     }
@@ -634,6 +644,7 @@
     /**
      * Updates the default color and opacity.
      */
+    @UnsupportedAppUsage
     private void onColorsChanged() {
         int defaultColor = DEFAULT_COLOR;
         boolean isOpaque = true;
@@ -677,6 +688,7 @@
     private static class ColorStateListFactory extends ConstantState<ComplexColor> {
         private final ColorStateList mSrc;
 
+        @UnsupportedAppUsage
         public ColorStateListFactory(ColorStateList src) {
             mSrc = src;
         }
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 781e235..1ca7b13 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.res;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ApplicationInfo;
 import android.graphics.Canvas;
 import android.graphics.PointF;
@@ -38,6 +39,7 @@
  */
 public class CompatibilityInfo implements Parcelable {
     /** default compatibility info object for compatible applications */
+    @UnsupportedAppUsage
     public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() {
     };
 
@@ -92,6 +94,7 @@
     /**
      * Application's scale.
      */
+    @UnsupportedAppUsage
     public final float applicationScale;
 
     /**
@@ -99,6 +102,7 @@
      */
     public final float applicationInvertedScale;
 
+    @UnsupportedAppUsage
     public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
             boolean forceCompat) {
         int compatFlags = 0;
@@ -259,6 +263,7 @@
         applicationInvertedScale = invertedScale;
     }
 
+    @UnsupportedAppUsage
     private CompatibilityInfo() {
         this(NEVER_NEEDS_COMPAT, DisplayMetrics.DENSITY_DEVICE,
                 1.0f,
@@ -268,10 +273,12 @@
     /**
      * @return true if the scaling is required
      */
+    @UnsupportedAppUsage
     public boolean isScalingRequired() {
         return (mCompatibilityFlags&SCALING_REQUIRED) != 0;
     }
     
+    @UnsupportedAppUsage
     public boolean supportsScreen() {
         return (mCompatibilityFlags&NEEDS_SCREEN_COMPAT) == 0;
     }
@@ -292,6 +299,7 @@
      * Returns the translator which translates the coordinates in compatibility mode.
      * @param params the window's parameter
      */
+    @UnsupportedAppUsage
     public Translator getTranslator() {
         return isScalingRequired() ? new Translator() : null;
     }
@@ -301,7 +309,9 @@
      * @hide
      */
     public class Translator {
+        @UnsupportedAppUsage
         final public float applicationScale;
+        @UnsupportedAppUsage
         final public float applicationInvertedScale;
         
         private Rect mContentInsetsBuffer = null;
@@ -321,6 +331,7 @@
         /**
          * Translate the screen rect to the application frame.
          */
+        @UnsupportedAppUsage
         public void translateRectInScreenToAppWinFrame(Rect rect) {
             rect.scale(applicationInvertedScale);
         }
@@ -328,6 +339,7 @@
         /**
          * Translate the region in window to screen. 
          */
+        @UnsupportedAppUsage
         public void translateRegionInWindowToScreen(Region transparentRegion) {
             transparentRegion.scale(applicationScale);
         }
@@ -335,6 +347,7 @@
         /**
          * Apply translation to the canvas that is necessary to draw the content.
          */
+        @UnsupportedAppUsage
         public void translateCanvas(Canvas canvas) {
             if (applicationScale == 1.5f) {
                 /*  When we scale for compatibility, we can put our stretched
@@ -361,6 +374,7 @@
         /**
          * Translate the motion event captured on screen to the application's window.
          */
+        @UnsupportedAppUsage
         public void translateEventInScreenToAppWindow(MotionEvent event) {
             event.scale(applicationInvertedScale);
         }
@@ -369,6 +383,7 @@
          * Translate the window's layout parameter, from application's view to
          * Screen's view.
          */
+        @UnsupportedAppUsage
         public void translateWindowLayout(WindowManager.LayoutParams params) {
             params.scale(applicationScale);
         }
@@ -376,6 +391,7 @@
         /**
          * Translate a Rect in application's window to screen.
          */
+        @UnsupportedAppUsage
         public void translateRectInAppWindowToScreen(Rect rect) {
             rect.scale(applicationScale);
         }
@@ -383,6 +399,7 @@
         /**
          * Translate a Rect in screen coordinates into the app window's coordinates.
          */
+        @UnsupportedAppUsage
         public void translateRectInScreenToAppWindow(Rect rect) {
             rect.scale(applicationInvertedScale);
         }
@@ -410,6 +427,7 @@
          * Translate the content insets in application window to Screen. This uses
          * the internal buffer for content insets to avoid extra object allocation.
          */
+        @UnsupportedAppUsage
         public Rect getTranslatedContentInsets(Rect contentInsets) {
             if (mContentInsetsBuffer == null) mContentInsetsBuffer = new Rect();
             mContentInsetsBuffer.set(contentInsets);
@@ -488,6 +506,7 @@
      * @param outDm If non-null the width and height will be set to their scaled values.
      * @return Returns the scaling factor for the window.
      */
+    @UnsupportedAppUsage
     public static float computeCompatibleScaling(DisplayMetrics dm, DisplayMetrics outDm) {
         final int width = dm.noncompatWidthPixels;
         final int height = dm.noncompatHeightPixels;
@@ -593,6 +612,7 @@
         dest.writeFloat(applicationInvertedScale);
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<CompatibilityInfo> CREATOR
             = new Parcelable.Creator<CompatibilityInfo>() {
         @Override
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 193e56e..f7aea97 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -44,6 +44,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.WindowConfiguration;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
@@ -127,6 +128,7 @@
      * questionable whether this is the right way to expose the functionality.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean userSetLocale;
 
 
@@ -793,6 +795,7 @@
     /**
      * @hide Internal book-keeping.
      */
+    @UnsupportedAppUsage
     public int seq;
 
     /** @hide */
@@ -1207,6 +1210,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     @Deprecated public void makeDefault() {
         setToDefaults();
     }
@@ -1978,6 +1982,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String resourceQualifierString(Configuration config) {
         return resourceQualifierString(config, null);
     }
@@ -2264,6 +2269,7 @@
      * This is fine for device configurations as no member is ever undefined.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static Configuration generateDelta(Configuration base, Configuration change) {
         final Configuration delta = new Configuration();
         if (base.fontScale != change.fontScale) {
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index 70290c4..3af395a 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -16,6 +16,7 @@
 
 package android.content.res;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 
 /**
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
index 7b27fac..d4f0ca5 100644
--- a/core/java/android/content/res/DrawableCache.java
+++ b/core/java/android/content/res/DrawableCache.java
@@ -16,6 +16,7 @@
 
 package android.content.res;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.drawable.Drawable;
 
 /**
@@ -31,6 +32,7 @@
      * @return a new instance of the resource, or {@code null} if not in
      *         the cache
      */
+    @UnsupportedAppUsage
     public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
         final Drawable.ConstantState entry = get(key, theme);
         if (entry != null) {
diff --git a/core/java/android/content/res/ObbInfo.java b/core/java/android/content/res/ObbInfo.java
index b653f9f..452fdce 100644
--- a/core/java/android/content/res/ObbInfo.java
+++ b/core/java/android/content/res/ObbInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.res;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -53,6 +54,7 @@
      * 
      * @hide
      */
+    @UnsupportedAppUsage
     public byte[] salt;
 
     // Only allow things in this package to instantiate.
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 7adea6a8..43e1612 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -39,6 +39,7 @@
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
 import android.annotation.StyleableRes;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.XmlRes;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
@@ -102,22 +103,28 @@
     private static final Object sSync = new Object();
 
     // Used by BridgeResources in layoutlib
+    @UnsupportedAppUsage
     static Resources mSystem = null;
 
+    @UnsupportedAppUsage
     private ResourcesImpl mResourcesImpl;
 
     // Pool of TypedArrays targeted to this Resources object.
+    @UnsupportedAppUsage
     final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
 
     /** Used to inflate drawable objects from XML. */
+    @UnsupportedAppUsage
     private DrawableInflater mDrawableInflater;
 
     /** Lock object used to protect access to {@link #mTmpValue}. */
     private final Object mTmpValueLock = new Object();
 
     /** Single-item pool used to minimize TypedValue allocations. */
+    @UnsupportedAppUsage
     private TypedValue mTmpValue = new TypedValue();
 
+    @UnsupportedAppUsage
     final ClassLoader mClassLoader;
 
     /**
@@ -149,6 +156,7 @@
      * @return A theme resource identifier
      * @hide
      */
+    @UnsupportedAppUsage
     public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
         return selectSystemTheme(curTheme, targetSdkVersion,
                 com.android.internal.R.style.Theme,
@@ -236,6 +244,7 @@
      *                    class loader
      * @hide
      */
+    @UnsupportedAppUsage
     public Resources(@Nullable ClassLoader classLoader) {
         mClassLoader = classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
     }
@@ -243,6 +252,7 @@
     /**
      * Only for creating the System resources.
      */
+    @UnsupportedAppUsage
     private Resources() {
         this(null);
 
@@ -261,6 +271,7 @@
      * and updates all Theme references to new implementations as well.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setImpl(ResourcesImpl impl) {
         if (impl == mResourcesImpl) {
             return;
@@ -284,6 +295,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public ResourcesImpl getImpl() {
         return mResourcesImpl;
     }
@@ -299,6 +311,7 @@
      * @return the inflater used to create drawable objects
      * @hide Pending API finalization.
      */
+    @UnsupportedAppUsage
     public final DrawableInflater getDrawableInflater() {
         if (mDrawableInflater == null) {
             mDrawableInflater = new DrawableInflater(this, mClassLoader);
@@ -642,8 +655,7 @@
      *           tool. This integer encodes the package, type, and resource
      *           entry. The value 0 is an invalid identifier.
      * 
-     * @return Resource dimension value multiplied by the appropriate 
-     * metric.
+     * @return Resource dimension value multiplied by the appropriate metric to convert to pixels.
      * 
      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
      *
@@ -892,6 +904,7 @@
     }
 
     @NonNull
+    @UnsupportedAppUsage
     Drawable loadDrawable(@NonNull TypedValue value, int id, int density, @Nullable Theme theme)
             throws NotFoundException {
         return mResourcesImpl.loadDrawable(this, value, id, density, theme);
@@ -903,8 +916,10 @@
      *           tool. This integer encodes the package, type, and resource
      *           entry. The value 0 is an invalid identifier.
      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
-     * 
+     *
+     * @deprecated Prefer {@link android.graphics.drawable.AnimatedImageDrawable}.
      */
+    @Deprecated
     public Movie getMovie(@RawRes int id) throws NotFoundException {
         final InputStream is = openRawResource(id);
         final Movie movie = Movie.decodeStream(is);
@@ -1116,6 +1131,7 @@
      *         not exist or is not a floating-point value.
      * @hide Pending API council approval.
      */
+    @UnsupportedAppUsage
     public float getFloat(int id) {
         final TypedValue value = obtainTempTypedValue();
         try {
@@ -1390,6 +1406,7 @@
      * retrieve XML attributes with style and theme information applied.
      */
     public final class Theme {
+        @UnsupportedAppUsage
         private ResourcesImpl.ThemeImpl mThemeImpl;
 
         private Theme() {
@@ -1553,6 +1570,7 @@
          * @hide
          */
         @NonNull
+        @UnsupportedAppUsage
         public TypedArray resolveAttributes(@NonNull int[] values, @NonNull int[] attrs) {
             return mThemeImpl.resolveAttributes(this, values, attrs);
         }
@@ -1842,6 +1860,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics,
             CompatibilityInfo compat) {
         if (mSystem != null) {
@@ -1862,6 +1881,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public DisplayAdjustments getDisplayAdjustments() {
         return mResourcesImpl.getDisplayAdjustments();
     }
@@ -1888,6 +1908,7 @@
      * @return compatibility info.
      * @hide
      */
+    @UnsupportedAppUsage
     public CompatibilityInfo getCompatibilityInfo() {
         return mResourcesImpl.getCompatibilityInfo();
     }
@@ -1897,6 +1918,7 @@
      * @hide
      */
     @VisibleForTesting
+    @UnsupportedAppUsage
     public void setCompatibilityInfo(CompatibilityInfo ci) {
         if (ci != null) {
             mResourcesImpl.updateConfiguration(null, null, ci);
@@ -2134,6 +2156,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public LongSparseArray<ConstantState> getPreloadedDrawables() {
         return mResourcesImpl.getPreloadedDrawables();
     }
@@ -2147,6 +2170,7 @@
      * @throws NotFoundException if the file could not be loaded
      */
     @NonNull
+    @UnsupportedAppUsage
     XmlResourceParser loadXmlResourceParser(@AnyRes int id, @NonNull String type)
             throws NotFoundException {
         final TypedValue value = obtainTempTypedValue();
@@ -2175,6 +2199,7 @@
      * @throws NotFoundException if the file could not be loaded
      */
     @NonNull
+    @UnsupportedAppUsage
     XmlResourceParser loadXmlResourceParser(String file, int id, int assetCookie,
                                             String type) throws NotFoundException {
         return mResourcesImpl.loadXmlResourceParser(file, id, assetCookie, type);
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 8c98067..dfa30a2 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -1,17 +1,17 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.res;
 
@@ -25,6 +25,7 @@
 import android.annotation.RawRes;
 import android.annotation.StyleRes;
 import android.annotation.StyleableRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.AssetManager.AssetInputStream;
@@ -34,6 +35,7 @@
 import android.graphics.ImageDecoder;
 import android.graphics.Typeface;
 import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.ColorStateListDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.DrawableContainer;
 import android.icu.text.PluralRules;
@@ -79,7 +81,9 @@
 
     static final String TAG_PRELOAD = TAG + ".preload";
 
+    @UnsupportedAppUsage
     private static final boolean TRACE_FOR_PRELOAD = false; // Do we still need it?
+    @UnsupportedAppUsage
     private static final boolean TRACE_FOR_MISS_PRELOAD = false; // Do we still need it?
 
     public static final boolean TRACE_FOR_DETAILED_PRELOAD =
@@ -96,28 +100,37 @@
     private static final Object sSync = new Object();
 
     private static boolean sPreloaded;
+    @UnsupportedAppUsage
     private boolean mPreloading;
 
     // Information about preloaded resources.  Note that they are not
     // protected by a lock, because while preloading in zygote we are all
     // single-threaded, and after that these are immutable.
+    @UnsupportedAppUsage
     private static final LongSparseArray<Drawable.ConstantState>[] sPreloadedDrawables;
+    @UnsupportedAppUsage
     private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
             = new LongSparseArray<>();
+    @UnsupportedAppUsage
     private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
             sPreloadedComplexColors = new LongSparseArray<>();
 
     /** Lock object used to protect access to caches and configuration. */
+    @UnsupportedAppUsage
     private final Object mAccessLock = new Object();
 
     // These are protected by mAccessLock.
     private final Configuration mTmpConfig = new Configuration();
+    @UnsupportedAppUsage
     private final DrawableCache mDrawableCache = new DrawableCache();
+    @UnsupportedAppUsage
     private final DrawableCache mColorDrawableCache = new DrawableCache();
     private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache =
             new ConfigurationBoundResourceCache<>();
+    @UnsupportedAppUsage
     private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
             new ConfigurationBoundResourceCache<>();
+    @UnsupportedAppUsage
     private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
             new ConfigurationBoundResourceCache<>();
 
@@ -138,12 +151,14 @@
     private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[XML_BLOCK_CACHE_SIZE];
 
 
+    @UnsupportedAppUsage
     final AssetManager mAssets;
     private final DisplayMetrics mMetrics = new DisplayMetrics();
     private final DisplayAdjustments mDisplayAdjustments;
 
     private PluralRules mPluralRule;
 
+    @UnsupportedAppUsage
     private final Configuration mConfiguration = new Configuration();
 
     static {
@@ -163,6 +178,7 @@
      * @param displayAdjustments this resource's Display override and compatibility info.
      *                           Must not be null.
      */
+    @UnsupportedAppUsage
     public ResourcesImpl(@NonNull AssetManager assets, @Nullable DisplayMetrics metrics,
             @Nullable Configuration config, @NonNull DisplayAdjustments displayAdjustments) {
         mAssets = assets;
@@ -176,10 +192,12 @@
         return mDisplayAdjustments;
     }
 
+    @UnsupportedAppUsage
     public AssetManager getAssets() {
         return mAssets;
     }
 
+    @UnsupportedAppUsage
     DisplayMetrics getDisplayMetrics() {
         if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
                 + "x" + mMetrics.heightPixels + " " + mMetrics.density);
@@ -207,6 +225,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
             throws NotFoundException {
         boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
@@ -828,10 +847,15 @@
             stack.push(id);
             try {
                 if (file.endsWith(".xml")) {
-                    final XmlResourceParser rp = loadXmlResourceParser(
-                            file, id, value.assetCookie, "drawable");
-                    dr = Drawable.createFromXmlForDensity(wrapper, rp, density, null);
-                    rp.close();
+                    if (file.startsWith("res/color/")) {
+                        ColorStateList csl = loadColorStateList(wrapper, value, id, null);
+                        dr = (csl != null ? new ColorStateListDrawable(csl) : null);
+                    } else {
+                        final XmlResourceParser rp = loadXmlResourceParser(
+                                file, id, value.assetCookie, "drawable");
+                        dr = Drawable.createFromXmlForDensity(wrapper, rp, density, null);
+                        rp.close();
+                    }
                 } else {
                     final InputStream is = mAssets.openNonAsset(
                             value.assetCookie, file, AssetManager.ACCESS_STREAMING);
@@ -1325,9 +1349,11 @@
                 @StyleableRes int[] attrs,
                 @AttrRes int defStyleAttr,
                 @StyleRes int defStyleRes) {
+            Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "obtainStyledAttributes");
+            TypedArray array;
             synchronized (mKey) {
                 final int len = attrs.length;
-                final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
+                array = TypedArray.obtain(wrapper.getResources(), len);
 
                 // XXX note that for now we only work with compiled XML files.
                 // To support generic XML files we will need to manually parse
@@ -1338,8 +1364,9 @@
                         array.mDataAddress, array.mIndicesAddress);
                 array.mTheme = wrapper;
                 array.mXml = parser;
-                return array;
             }
+            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+            return array;
         }
 
         @NonNull
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index b03ed1e..1db2dd8 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.text.TextUtils;
 
 import java.util.Arrays;
@@ -26,9 +27,11 @@
 /** @hide */
 public final class ResourcesKey {
     @Nullable
+    @UnsupportedAppUsage
     public final String mResDir;
 
     @Nullable
+    @UnsupportedAppUsage
     public final String[] mSplitResDirs;
 
     @Nullable
@@ -47,6 +50,7 @@
 
     private final int mHash;
 
+    @UnsupportedAppUsage
     public ResourcesKey(@Nullable String resDir,
                         @Nullable String[] splitResDirs,
                         @Nullable String[] overlayDirs,
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index 5cfc41f..b5ec0f9 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -16,6 +16,7 @@
 
 package android.content.res;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Color;
 import android.text.*;
 import android.text.style.*;
@@ -59,6 +60,7 @@
                 + ": " + nativeGetSize(mNative));
     }
 
+    @UnsupportedAppUsage
     public CharSequence get(int idx) {
         synchronized (this) {
             if (mStrings != null) {
@@ -478,6 +480,7 @@
      *  are doing!  The given native object must exist for the entire lifetime
      *  of this newly creating StringBlock.
      */
+    @UnsupportedAppUsage
     StringBlock(long obj, boolean useSparse) {
         mNative = obj;
         mUseSparse = useSparse;
diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java
index f1b1e74..06cafdb 100644
--- a/core/java/android/content/res/ThemedResourceCache.java
+++ b/core/java/android/content/res/ThemedResourceCache.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.Resources.Theme;
 import android.content.res.Resources.ThemeKey;
@@ -32,6 +33,7 @@
  * @param <T> type of data to cache
  */
 abstract class ThemedResourceCache<T> {
+    @UnsupportedAppUsage
     private ArrayMap<ThemeKey, LongSparseArray<WeakReference<T>>> mThemedEntries;
     private LongSparseArray<WeakReference<T>> mUnthemedEntries;
     private LongSparseArray<WeakReference<T>> mNullThemedEntries;
@@ -116,6 +118,7 @@
      *
      * @param configChanges a bitmask of configuration changes
      */
+    @UnsupportedAppUsage
     public void onConfigurationChange(@Config int configChanges) {
         prune(configChanges);
     }
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index cbb3c6d..30d2d5f 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -20,6 +20,7 @@
 import android.annotation.ColorInt;
 import android.annotation.Nullable;
 import android.annotation.StyleableRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
 import android.graphics.Typeface;
@@ -70,19 +71,29 @@
     static final int STYLE_CHANGING_CONFIGURATIONS = 4;
     static final int STYLE_DENSITY = 5;
 
+    @UnsupportedAppUsage
     private final Resources mResources;
+    @UnsupportedAppUsage
     private DisplayMetrics mMetrics;
+    @UnsupportedAppUsage
     private AssetManager mAssets;
 
+    @UnsupportedAppUsage
     private boolean mRecycled;
 
+    @UnsupportedAppUsage
     /*package*/ XmlBlock.Parser mXml;
+    @UnsupportedAppUsage
     /*package*/ Resources.Theme mTheme;
+    @UnsupportedAppUsage
     /*package*/ int[] mData;
     /*package*/ long mDataAddress;
+    @UnsupportedAppUsage
     /*package*/ int[] mIndices;
     /*package*/ long mIndicesAddress;
+    @UnsupportedAppUsage
     /*package*/ int mLength;
+    @UnsupportedAppUsage
     /*package*/ TypedValue mValue = new TypedValue();
 
     private void resize(int len) {
@@ -276,6 +287,7 @@
      * @throws RuntimeException if the TypedArray has already been recycled.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getNonConfigurationString(@StyleableRes int index,
             @Config int allowedChangingConfigs) {
         if (mRecycled) {
@@ -1165,6 +1177,7 @@
      * @hide
      */
     @Nullable
+    @UnsupportedAppUsage
     public int[] extractThemeAttrs() {
         return extractThemeAttrs(null);
     }
@@ -1173,6 +1186,7 @@
      * @hide
      */
     @Nullable
+    @UnsupportedAppUsage
     public int[] extractThemeAttrs(@Nullable int[] scrap) {
         if (mRecycled) {
             throw new RuntimeException("Cannot make calls to a recycled instance!");
@@ -1244,6 +1258,7 @@
         return changingConfig;
     }
 
+    @UnsupportedAppUsage
     private boolean getValueAt(int index, TypedValue outValue) {
         final int[] data = mData;
         final int type = data[index + STYLE_TYPE];
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index d4ccffb..4e1159a 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -17,6 +17,7 @@
 package android.content.res;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.util.TypedValue;
 
 import com.android.internal.util.XmlUtils;
@@ -37,6 +38,7 @@
 final class XmlBlock implements AutoCloseable {
     private static final boolean DEBUG=false;
 
+    @UnsupportedAppUsage
     public XmlBlock(byte[] data) {
         mAssets = null;
         mNative = nativeCreate(data, 0, data.length);
@@ -69,6 +71,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public XmlResourceParser newParser() {
         synchronized (this) {
             if (mNative != 0) {
@@ -462,7 +465,9 @@
             return mStrings.get(id);
         }
 
+        @UnsupportedAppUsage
         /*package*/ long mParseState;
+        @UnsupportedAppUsage
         private final XmlBlock mBlock;
         private boolean mStarted = false;
         private boolean mDecNextDepth = false;
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index 76fa008..c6c2aa5 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -16,6 +16,7 @@
 
 package android.database;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.net.Uri;
 import android.os.Bundle;
@@ -68,6 +69,7 @@
     @Deprecated
     protected ContentResolver mContentResolver;
 
+    @UnsupportedAppUsage
     private Uri mNotifyUri;
 
     private final Object mSelfObserverLock = new Object();
@@ -77,6 +79,7 @@
     private final DataSetObservable mDataSetObservable = new DataSetObservable();
     private final ContentObservable mContentObservable = new ContentObservable();
 
+    @UnsupportedAppUsage
     private Bundle mExtras = Bundle.EMPTY;
 
     /* -------------------------------------------------------- */
diff --git a/core/java/android/database/AbstractWindowedCursor.java b/core/java/android/database/AbstractWindowedCursor.java
index 083485f..a988f068 100644
--- a/core/java/android/database/AbstractWindowedCursor.java
+++ b/core/java/android/database/AbstractWindowedCursor.java
@@ -16,6 +16,8 @@
 
 package android.database;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * A base class for Cursors that store their data in {@link CursorWindow}s.
  * <p>
@@ -179,6 +181,7 @@
      * Closes the cursor window and sets {@link #mWindow} to null.
      * @hide
      */
+    @UnsupportedAppUsage
     protected void closeWindow() {
         if (mWindow != null) {
             mWindow.close();
@@ -193,6 +196,7 @@
      * @param name The window name.
      * @hide
      */
+    @UnsupportedAppUsage
     protected void clearOrCreateWindow(String name) {
         if (mWindow == null) {
             mWindow = new CursorWindow(name);
@@ -203,6 +207,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     protected void onDeactivateOrClose() {
         super.onDeactivateOrClose();
         closeWindow();
diff --git a/core/java/android/database/ContentObserver.java b/core/java/android/database/ContentObserver.java
index 5f01e30..798b783 100644
--- a/core/java/android/database/ContentObserver.java
+++ b/core/java/android/database/ContentObserver.java
@@ -16,6 +16,7 @@
 
 package android.database;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.UserHandle;
@@ -59,6 +60,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public IContentObserver releaseContentObserver() {
         synchronized (mLock) {
             final Transport oldTransport = mTransport;
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index a748f4d..d9443d9 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -17,6 +17,7 @@
 package android.database;
 
 import android.annotation.BytesLong;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.database.sqlite.SQLiteClosable;
 import android.database.sqlite.SQLiteException;
@@ -45,12 +46,14 @@
     private static final String STATS_TAG = "CursorWindowStats";
 
     // This static member will be evaluated when first used.
+    @UnsupportedAppUsage
     private static int sCursorWindowSize = -1;
 
     /**
      * The native CursorWindow object pointer.  (FOR INTERNAL USE ONLY)
      * @hide
      */
+    @UnsupportedAppUsage
     public long mWindowPtr;
 
     private int mStartPos;
@@ -744,6 +747,7 @@
         dispose();
     }
 
+    @UnsupportedAppUsage
     private static final LongSparseArray<Integer> sWindowToPidMap = new LongSparseArray<Integer>();
 
     private void recordNewWindow(int pid, long window) {
@@ -765,6 +769,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private String printStats() {
         StringBuilder buff = new StringBuilder();
         int myPid = Process.myPid();
diff --git a/core/java/android/database/CursorWrapper.java b/core/java/android/database/CursorWrapper.java
index 63a2792..0d27dfb 100644
--- a/core/java/android/database/CursorWrapper.java
+++ b/core/java/android/database/CursorWrapper.java
@@ -16,6 +16,7 @@
 
 package android.database;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.net.Uri;
 import android.os.Bundle;
@@ -26,6 +27,7 @@
  */
 public class CursorWrapper implements Cursor {
     /** @hide */
+    @UnsupportedAppUsage
     protected final Cursor mCursor;
 
     /**
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 3d019f0..f78b484 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -16,6 +16,8 @@
 
 package android.database;
 
+import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.OperationApplicationException;
@@ -34,6 +36,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.util.ArrayUtils;
+
 import java.io.FileNotFoundException;
 import java.io.PrintStream;
 import java.text.Collator;
@@ -216,6 +220,92 @@
     }
 
     /**
+     * Bind the given selection with the given selection arguments.
+     * <p>
+     * Internally assumes that '?' is only ever used for arguments, and doesn't
+     * appear as a literal or escaped value.
+     * <p>
+     * This method is typically useful for trusted code that needs to cook up a
+     * fully-bound selection.
+     *
+     * @hide
+     */
+    public static @Nullable String bindSelection(@Nullable String selection,
+            @Nullable Object... selectionArgs) {
+        if (selection == null) return null;
+        // If no arguments provided, so we can't bind anything
+        if (ArrayUtils.isEmpty(selectionArgs)) return selection;
+        // If no bindings requested, so we can shortcut
+        if (selection.indexOf('?') == -1) return selection;
+
+        // Track the chars immediately before and after each bind request, to
+        // decide if it needs additional whitespace added
+        char before = ' ';
+        char after = ' ';
+
+        int argIndex = 0;
+        final int len = selection.length();
+        final StringBuilder res = new StringBuilder(len);
+        for (int i = 0; i < len; ) {
+            char c = selection.charAt(i++);
+            if (c == '?') {
+                // Assume this bind request is guarded until we find a specific
+                // trailing character below
+                after = ' ';
+
+                // Sniff forward to see if the selection is requesting a
+                // specific argument index
+                int start = i;
+                for (; i < len; i++) {
+                    c = selection.charAt(i);
+                    if (c < '0' || c > '9') {
+                        after = c;
+                        break;
+                    }
+                }
+                if (start != i) {
+                    argIndex = Integer.parseInt(selection.substring(start, i)) - 1;
+                }
+
+                // Manually bind the argument into the selection, adding
+                // whitespace when needed for clarity
+                final Object arg = selectionArgs[argIndex++];
+                if (before != ' ' && before != '=') res.append(' ');
+                switch (DatabaseUtils.getTypeOfObject(arg)) {
+                    case Cursor.FIELD_TYPE_NULL:
+                        res.append("NULL");
+                        break;
+                    case Cursor.FIELD_TYPE_INTEGER:
+                        res.append(((Number) arg).longValue());
+                        break;
+                    case Cursor.FIELD_TYPE_FLOAT:
+                        res.append(((Number) arg).doubleValue());
+                        break;
+                    case Cursor.FIELD_TYPE_BLOB:
+                        throw new IllegalArgumentException("Blobs not supported");
+                    case Cursor.FIELD_TYPE_STRING:
+                    default:
+                        if (arg instanceof Boolean) {
+                            // Provide compatibility with legacy applications which may pass
+                            // Boolean values in bind args.
+                            res.append(((Boolean) arg).booleanValue() ? 1 : 0);
+                        } else {
+                            res.append('\'');
+                            res.append(arg.toString());
+                            res.append('\'');
+                        }
+                        break;
+                }
+                if (after != ' ') res.append(' ');
+            } else {
+                res.append(c);
+                before = c;
+            }
+        }
+        return res.toString();
+    }
+
+    /**
      * Returns data type of the given object's value.
      *<p>
      * Returned values are
@@ -232,6 +322,7 @@
      * @return object value type
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getTypeOfObject(Object obj) {
         if (obj == null) {
             return Cursor.FIELD_TYPE_NULL;
@@ -760,6 +851,7 @@
      * the requested row.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int cursorPickFillWindowStartPosition(
             int cursorPosition, int cursorWindowCapacity) {
         return Math.max(cursorPosition - cursorWindowCapacity / 3, 0);
diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java
index 5e107f2..5033296 100644
--- a/core/java/android/database/MatrixCursor.java
+++ b/core/java/android/database/MatrixCursor.java
@@ -16,6 +16,7 @@
 
 package android.database;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.ArrayList;
 
 /**
@@ -26,7 +27,9 @@
 public class MatrixCursor extends AbstractCursor {
 
     private final String[] columnNames;
+    @UnsupportedAppUsage
     private Object[] data;
+    @UnsupportedAppUsage
     private int rowCount = 0;
     private final int columnCount;
 
@@ -61,6 +64,7 @@
     /**
      * Gets value at the given column for the current row.
      */
+    @UnsupportedAppUsage
     private Object get(int column) {
         if (column < 0 || column >= columnCount) {
             throw new CursorIndexOutOfBoundsException("Requested column: "
diff --git a/core/java/android/database/OWNERS b/core/java/android/database/OWNERS
index 84e81e4..7e19942 100644
--- a/core/java/android/database/OWNERS
+++ b/core/java/android/database/OWNERS
@@ -1,2 +1,3 @@
-fkupolov@google.com
-omakoto@google.com
\ No newline at end of file
+omakoto@google.com
+jsharkey@android.com
+yamasani@google.com
diff --git a/core/java/android/database/RedactingCursor.java b/core/java/android/database/RedactingCursor.java
new file mode 100644
index 0000000..6322d56
--- /dev/null
+++ b/core/java/android/database/RedactingCursor.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database;
+
+import android.annotation.NonNull;
+import android.util.SparseArray;
+
+import java.util.Map;
+
+/**
+ * Cursor that offers to redact values of requested columns.
+ *
+ * @hide
+ */
+public class RedactingCursor extends CrossProcessCursorWrapper {
+    private final SparseArray<Object> mRedactions;
+
+    private RedactingCursor(@NonNull Cursor cursor, SparseArray<Object> redactions) {
+        super(cursor);
+        mRedactions = redactions;
+    }
+
+    /**
+     * Create a wrapped instance of the given {@link Cursor} which redacts the
+     * requested columns so they always return specific values when accessed.
+     * <p>
+     * If a redacted column appears multiple times in the underlying cursor, all
+     * instances will be redacted. If none of the redacted columns appear in the
+     * given cursor, the given cursor will be returned untouched to improve
+     * performance.
+     */
+    public static Cursor create(@NonNull Cursor cursor, @NonNull Map<String, Object> redactions) {
+        final SparseArray<Object> internalRedactions = new SparseArray<>();
+
+        final String[] columns = cursor.getColumnNames();
+        for (int i = 0; i < columns.length; i++) {
+            if (redactions.containsKey(columns[i])) {
+                internalRedactions.put(i, redactions.get(columns[i]));
+            }
+        }
+
+        if (internalRedactions.size() == 0) {
+            return cursor;
+        } else {
+            return new RedactingCursor(cursor, internalRedactions);
+        }
+    }
+
+    @Override
+    public void fillWindow(int position, CursorWindow window) {
+        // Fill window directly to ensure data is redacted
+        DatabaseUtils.cursorFillWindow(this, position, window);
+    }
+
+    @Override
+    public CursorWindow getWindow() {
+        // Returning underlying window risks leaking redacted data
+        return null;
+    }
+
+    @Override
+    public Cursor getWrappedCursor() {
+        throw new UnsupportedOperationException(
+                "Returning underlying cursor risks leaking redacted data");
+    }
+
+    @Override
+    public double getDouble(int columnIndex) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            return (double) mRedactions.valueAt(i);
+        } else {
+            return super.getDouble(columnIndex);
+        }
+    }
+
+    @Override
+    public float getFloat(int columnIndex) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            return (float) mRedactions.valueAt(i);
+        } else {
+            return super.getFloat(columnIndex);
+        }
+    }
+
+    @Override
+    public int getInt(int columnIndex) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            return (int) mRedactions.valueAt(i);
+        } else {
+            return super.getInt(columnIndex);
+        }
+    }
+
+    @Override
+    public long getLong(int columnIndex) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            return (long) mRedactions.valueAt(i);
+        } else {
+            return super.getLong(columnIndex);
+        }
+    }
+
+    @Override
+    public short getShort(int columnIndex) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            return (short) mRedactions.valueAt(i);
+        } else {
+            return super.getShort(columnIndex);
+        }
+    }
+
+    @Override
+    public String getString(int columnIndex) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            return (String) mRedactions.valueAt(i);
+        } else {
+            return super.getString(columnIndex);
+        }
+    }
+
+    @Override
+    public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            buffer.data = ((String) mRedactions.valueAt(i)).toCharArray();
+            buffer.sizeCopied = buffer.data.length;
+        } else {
+            super.copyStringToBuffer(columnIndex, buffer);
+        }
+    }
+
+    @Override
+    public byte[] getBlob(int columnIndex) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            return (byte[]) mRedactions.valueAt(i);
+        } else {
+            return super.getBlob(columnIndex);
+        }
+    }
+
+    @Override
+    public int getType(int columnIndex) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            return DatabaseUtils.getTypeOfObject(mRedactions.valueAt(i));
+        } else {
+            return super.getType(columnIndex);
+        }
+    }
+
+    @Override
+    public boolean isNull(int columnIndex) {
+        final int i = mRedactions.indexOfKey(columnIndex);
+        if (i >= 0) {
+            return mRedactions.valueAt(i) == null;
+        } else {
+            return super.isNull(columnIndex);
+        }
+    }
+}
diff --git a/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java b/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
index f28c70f..2af06e1 100644
--- a/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
+++ b/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
@@ -16,6 +16,8 @@
 
 package android.database.sqlite;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * An exception that indicates that garbage-collector is finalizing a database object
  * that is not explicitly closed
@@ -25,6 +27,7 @@
     private static final String s = "Application did not close the cursor or database object " +
             "that was opened here";
 
+    @UnsupportedAppUsage
     public DatabaseObjectNotClosedException() {
         super(s);
     }
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
index adfbc6e..d6a71da 100644
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ b/core/java/android/database/sqlite/SQLiteClosable.java
@@ -16,6 +16,7 @@
 
 package android.database.sqlite;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.Closeable;
 
 /**
@@ -24,6 +25,7 @@
  * This class implements a primitive reference counting scheme for database objects.
  */
 public abstract class SQLiteClosable implements Closeable {
+    @UnsupportedAppUsage
     private int mReferenceCount = 1;
 
     /**
diff --git a/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java b/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
index 5bf3a7c..06c069c 100644
--- a/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
+++ b/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
@@ -41,6 +41,7 @@
     private static volatile boolean sFlagsSet;
     private static volatile boolean sCompatibilityWalSupported;
     private static volatile String sWALSyncMode;
+    private static volatile long sTruncateSize = -1;
     // This flag is used to avoid recursive initialization due to circular dependency on Settings
     private static volatile boolean sCallingGlobalSettings;
 
@@ -71,6 +72,19 @@
         return sWALSyncMode;
     }
 
+    /**
+     * Override {@link com.android.internal.R.integer#db_wal_truncate_size}.
+     *
+     * @return the value set in the global setting, or -1 if a value is not set.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static long getTruncateSize() {
+        initIfNeeded();
+        return sTruncateSize;
+    }
+
     private static void initIfNeeded() {
         if (sInitialized || sCallingGlobalSettings) {
             return;
@@ -115,6 +129,7 @@
         sCompatibilityWalSupported = parser.getBoolean("compatibility_wal_supported",
                 SQLiteGlobal.isCompatibilityWalSupported());
         sWALSyncMode = parser.getString("wal_syncmode", SQLiteGlobal.getWALSyncMode());
+        sTruncateSize = parser.getInt("truncate_size", -1);
         Log.i(TAG, "Read compatibility WAL flags: compatibility_wal_supported="
                 + sCompatibilityWalSupported + ", wal_syncmode=" + sWALSyncMode);
         sFlagsSet = true;
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 101fb82..5c4f16a 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -19,6 +19,7 @@
 import android.database.Cursor;
 import android.database.CursorWindow;
 import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDebug.Consts;
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.os.CancellationSignal;
 import android.os.OperationCanceledException;
@@ -32,12 +33,12 @@
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 
+import java.io.File;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.Map;
 
-
 /**
  * Represents a SQLite database connection.
  * Each connection wraps an instance of a native <code>sqlite3</code> object.
@@ -208,10 +209,15 @@
     }
 
     private void open() {
-        mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags,
-                mConfiguration.label,
-                SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME,
-                mConfiguration.lookasideSlotSize, mConfiguration.lookasideSlotCount);
+        final int cookie = mRecentOperations.beginOperation("open", null, null);
+        try {
+            mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags,
+                    mConfiguration.label,
+                    SQLiteDebug.Consts.DEBUG_SQL_STATEMENTS, SQLiteDebug.Consts.DEBUG_SQL_TIME,
+                    mConfiguration.lookasideSlotSize, mConfiguration.lookasideSlotCount);
+        } finally {
+            mRecentOperations.endOperation(cookie);
+        }
         setPageSize();
         setForeignKeyModeFromConfiguration();
         setWalModeFromConfiguration();
@@ -303,6 +309,7 @@
                 } else {
                     setSyncMode(SQLiteGlobal.getWALSyncMode());
                 }
+                maybeTruncateWalFile();
             } else {
                 setJournalMode(mConfiguration.journalMode == null
                         ? SQLiteGlobal.getDefaultJournalMode() : mConfiguration.journalMode);
@@ -312,6 +319,40 @@
         }
     }
 
+    /**
+     * If the WAL file exists and larger than a threshold, truncate it by executing
+     * PRAGMA wal_checkpoint.
+     */
+    private void maybeTruncateWalFile() {
+        final long threshold = SQLiteGlobal.getWALTruncateSize();
+        if (DEBUG) {
+            Log.d(TAG, "Truncate threshold=" + threshold);
+        }
+        if (threshold == 0) {
+            return;
+        }
+
+        final File walFile = new File(mConfiguration.path + "-wal");
+        if (!walFile.isFile()) {
+            return;
+        }
+        final long size = walFile.length();
+        if (size < threshold) {
+            if (DEBUG) {
+                Log.d(TAG, walFile.getAbsolutePath() + " " + size + " bytes: No need to truncate");
+            }
+            return;
+        }
+
+        Log.i(TAG, walFile.getAbsolutePath() + " " + size + " bytes: Bigger than "
+                + threshold + "; truncating");
+        try {
+            executeForString("PRAGMA wal_checkpoint(TRUNCATE)", null, null);
+        } catch (SQLiteException e) {
+            Log.w(TAG, "Failed to truncate the -wal file", e);
+        }
+    }
+
     private void setSyncMode(String newValue) {
         String value = executeForString("PRAGMA synchronous", null, null);
         if (!canonicalizeSyncMode(value).equalsIgnoreCase(
@@ -609,7 +650,9 @@
                 applyBlockGuardPolicy(statement);
                 attachCancellationSignal(cancellationSignal);
                 try {
-                    return nativeExecuteForLong(mConnectionPtr, statement.mStatementPtr);
+                    long ret = nativeExecuteForLong(mConnectionPtr, statement.mStatementPtr);
+                    mRecentOperations.setResult(ret);
+                    return ret;
                 } finally {
                     detachCancellationSignal(cancellationSignal);
                 }
@@ -652,7 +695,9 @@
                 applyBlockGuardPolicy(statement);
                 attachCancellationSignal(cancellationSignal);
                 try {
-                    return nativeExecuteForString(mConnectionPtr, statement.mStatementPtr);
+                    String ret = nativeExecuteForString(mConnectionPtr, statement.mStatementPtr);
+                    mRecentOperations.setResult(ret);
+                    return ret;
                 } finally {
                     detachCancellationSignal(cancellationSignal);
                 }
@@ -1091,7 +1136,7 @@
         printer.println("  isPrimaryConnection: " + mIsPrimaryConnection);
         printer.println("  onlyAllowReadOnlyOperations: " + mOnlyAllowReadOnlyOperations);
 
-        mRecentOperations.dump(printer, verbose);
+        mRecentOperations.dump(printer);
 
         if (verbose) {
             mPreparedStatementCache.dump(printer);
@@ -1312,12 +1357,17 @@
         private int mIndex;
         private int mGeneration;
         private final SQLiteConnectionPool mPool;
+        private long mResultLong = Long.MIN_VALUE;
+        private String mResultString;
 
         OperationLog(SQLiteConnectionPool pool) {
             mPool = pool;
         }
 
         public int beginOperation(String kind, String sql, Object[] bindArgs) {
+            mResultLong = Long.MIN_VALUE;
+            mResultString = null;
+
             synchronized (mOperations) {
                 final int index = (mIndex + 1) % MAX_RECENT_OPERATIONS;
                 Operation operation = mOperations[index];
@@ -1335,6 +1385,9 @@
                 operation.mStartTime = SystemClock.uptimeMillis();
                 operation.mKind = kind;
                 operation.mSql = sql;
+                operation.mPath = mPool.getPath();
+                operation.mResultLong = Long.MIN_VALUE;
+                operation.mResultString = null;
                 if (bindArgs != null) {
                     if (operation.mBindArgs == null) {
                         operation.mBindArgs = new ArrayList<Object>();
@@ -1390,6 +1443,14 @@
             }
         }
 
+        public void setResult(long longResult) {
+            mResultLong = longResult;
+        }
+
+        public void setResult(String stringResult) {
+            mResultString = stringResult;
+        }
+
         private boolean endOperationDeferLogLocked(int cookie) {
             final Operation operation = getOperationLocked(cookie);
             if (operation != null) {
@@ -1401,7 +1462,7 @@
                 operation.mFinished = true;
                 final long execTime = operation.mEndTime - operation.mStartTime;
                 mPool.onStatementExecuted(execTime);
-                return SQLiteDebug.DEBUG_LOG_SLOW_QUERIES && SQLiteDebug.shouldLogSlowQuery(
+                return SQLiteDebug.Consts.DEBUG_LOG_SLOW_QUERIES && SQLiteDebug.shouldLogSlowQuery(
                         execTime);
             }
             return false;
@@ -1409,8 +1470,10 @@
 
         private void logOperationLocked(int cookie, String detail) {
             final Operation operation = getOperationLocked(cookie);
+            operation.mResultLong = mResultLong;
+            operation.mResultString = mResultString;
             StringBuilder msg = new StringBuilder();
-            operation.describe(msg, false);
+            operation.describe(msg, true);
             if (detail != null) {
                 msg.append(", ").append(detail);
             }
@@ -1440,7 +1503,7 @@
             }
         }
 
-        public void dump(Printer printer, boolean verbose) {
+        public void dump(Printer printer) {
             synchronized (mOperations) {
                 printer.println("  Most recently executed operations:");
                 int index = mIndex;
@@ -1457,7 +1520,7 @@
                         String formattedStartTime = opDF.format(new Date(operation.mStartWallTime));
                         msg.append(formattedStartTime);
                         msg.append("] ");
-                        operation.describe(msg, verbose);
+                        operation.describe(msg, false); // Never dump bingargs in a bugreport
                         printer.println(msg.toString());
 
                         if (index > 0) {
@@ -1491,8 +1554,11 @@
         public boolean mFinished;
         public Exception mException;
         public int mCookie;
+        public String mPath;
+        public long mResultLong; // MIN_VALUE means "value not set".
+        public String mResultString;
 
-        public void describe(StringBuilder msg, boolean verbose) {
+        public void describe(StringBuilder msg, boolean allowDetailedLog) {
             msg.append(mKind);
             if (mFinished) {
                 msg.append(" took ").append(mEndTime - mStartTime).append("ms");
@@ -1504,7 +1570,9 @@
             if (mSql != null) {
                 msg.append(", sql=\"").append(trimSqlForDisplay(mSql)).append("\"");
             }
-            if (verbose && mBindArgs != null && mBindArgs.size() != 0) {
+            final boolean dumpDetails = allowDetailedLog && Consts.DEBUG_LOG_DETAILED
+                    && mBindArgs != null && mBindArgs.size() != 0;
+            if (dumpDetails) {
                 msg.append(", bindArgs=[");
                 final int count = mBindArgs.size();
                 for (int i = 0; i < count; i++) {
@@ -1524,9 +1592,16 @@
                 }
                 msg.append("]");
             }
+            msg.append(", path=").append(mPath);
             if (mException != null) {
                 msg.append(", exception=\"").append(mException.getMessage()).append("\"");
             }
+            if (mResultLong != Long.MIN_VALUE) {
+                msg.append(", result=").append(mResultLong);
+            }
+            if (mResultString != null) {
+                msg.append(", result=\"").append(mResultString).append("\"");
+            }
         }
 
         private String getStatus() {
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index e519302..3ee348b 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -1183,6 +1183,10 @@
         return "SQLiteConnectionPool: " + mConfiguration.path;
     }
 
+    public String getPath() {
+        return mConfiguration.path;
+    }
+
     private static final class ConnectionWaiter {
         public ConnectionWaiter mNext;
         public Thread mThread;
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index 13e6f71..e3c4098 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -16,6 +16,7 @@
 
 package android.database.sqlite;
 
+import android.annotation.UnsupportedAppUsage;
 import android.database.AbstractWindowedCursor;
 import android.database.CursorWindow;
 import android.database.DatabaseUtils;
@@ -39,12 +40,14 @@
     static final int NO_COUNT = -1;
 
     /** The name of the table to edit */
+    @UnsupportedAppUsage
     private final String mEditTable;
 
     /** The names of the columns in the rows */
     private final String[] mColumns;
 
     /** The query object for the cursor */
+    @UnsupportedAppUsage
     private final SQLiteQuery mQuery;
 
     /** The compiled query this cursor came from */
@@ -139,6 +142,7 @@
         return mCount;
     }
 
+    @UnsupportedAppUsage
     private void fillWindow(int requiredPos) {
         clearOrCreateWindow(getDatabase().getPath());
         try {
diff --git a/core/java/android/database/sqlite/SQLiteCustomFunction.java b/core/java/android/database/sqlite/SQLiteCustomFunction.java
index 02f3284..ec20458 100644
--- a/core/java/android/database/sqlite/SQLiteCustomFunction.java
+++ b/core/java/android/database/sqlite/SQLiteCustomFunction.java
@@ -16,13 +16,17 @@
 
 package android.database.sqlite;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Describes a custom SQL function.
  *
  * @hide
  */
 public final class SQLiteCustomFunction {
+    @UnsupportedAppUsage
     public final String name;
+    @UnsupportedAppUsage
     public final int numArgs;
     public final SQLiteDatabase.CustomFunction callback;
 
@@ -47,6 +51,7 @@
 
     // Called from native.
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void dispatchCallback(String[] args) {
         callback.callback(args);
     }
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 6adae25..01557c5 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -20,6 +20,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.content.ContentValues;
 import android.database.Cursor;
@@ -91,6 +92,7 @@
     // Thread-local for database sessions that belong to this database.
     // Each thread has its own database session.
     // INVARIANT: Immutable.
+    @UnsupportedAppUsage
     private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal
             .withInitial(this::createSession);
 
@@ -124,12 +126,14 @@
 
     // The database configuration.
     // INVARIANT: Guarded by mLock.
+    @UnsupportedAppUsage
     private final SQLiteDatabaseConfiguration mConfigurationLocked;
 
     // The connection pool for the database, null when closed.
     // The pool itself is thread-safe, but the reference to it can only be acquired
     // when the lock is held.
     // INVARIANT: Guarded by mLock.
+    @UnsupportedAppUsage
     private SQLiteConnectionPool mConnectionPoolLocked;
 
     // True if the database has attached databases.
@@ -189,7 +193,9 @@
      */
     public static final int CONFLICT_NONE = 0;
 
-    private static final String[] CONFLICT_VALUES = new String[]
+    /** {@hide} */
+    @UnsupportedAppUsage
+    public static final String[] CONFLICT_VALUES = new String[]
             {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
 
     /**
@@ -399,6 +405,7 @@
      * @throws IllegalStateException if the thread does not yet have a session and
      * the database is not open.
      */
+    @UnsupportedAppUsage
     SQLiteSession getThreadSession() {
         return mThreadSession.get(); // initialValue() throws if database closed
     }
@@ -542,6 +549,7 @@
         beginTransaction(transactionListener, false);
     }
 
+    @UnsupportedAppUsage
     private void beginTransaction(SQLiteTransactionListener transactionListener,
             boolean exclusive) {
         acquireReference();
@@ -729,6 +737,7 @@
         return openDatabase(path.getPath(), openParams);
     }
 
+    @UnsupportedAppUsage
     private static SQLiteDatabase openDatabase(@NonNull String path,
             @NonNull OpenParams openParams) {
         Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
@@ -838,6 +847,7 @@
      * @see #isReadOnly()
      * @hide
      */
+    @UnsupportedAppUsage
     public void reopenReadWrite() {
         synchronized (mLock) {
             throwIfNotOpenLocked();
@@ -1748,7 +1758,8 @@
         executeSql(sql, bindArgs);
     }
 
-    private int executeSql(String sql, Object[] bindArgs) throws SQLException {
+    /** {@hide} */
+    public int executeSql(String sql, Object[] bindArgs) throws SQLException {
         acquireReference();
         try {
             final int statementType = DatabaseUtils.getSqlStatementType(sql);
@@ -2137,6 +2148,7 @@
         return dbStatsList;
     }
 
+    @UnsupportedAppUsage
     private void collectDbStats(ArrayList<DbStats> dbStatsList) {
         synchronized (mLock) {
             if (mConnectionPoolLocked != null) {
@@ -2145,6 +2157,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static ArrayList<SQLiteDatabase> getActiveDatabases() {
         ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>();
         synchronized (sActiveDatabases) {
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index bb62268..48f1021 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -16,6 +16,7 @@
 
 package android.database.sqlite;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.ArrayList;
 import java.util.Locale;
 import java.util.regex.Pattern;
@@ -67,6 +68,7 @@
      *
      * Default is 25.
      */
+    @UnsupportedAppUsage
     public int maxSqlCacheSize;
 
     /**
diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java
index d392521..1c66204 100644
--- a/core/java/android/database/sqlite/SQLiteDebug.java
+++ b/core/java/android/database/sqlite/SQLiteDebug.java
@@ -18,6 +18,7 @@
 
 import android.annotation.TestApi;
 import android.os.Build;
+import android.os.Process;
 import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Printer;
@@ -34,35 +35,53 @@
     private static native void nativeGetPagerStats(PagerStats stats);
 
     /**
-     * Controls the printing of informational SQL log messages.
+     * Inner class to avoid getting the value frozen in zygote.
      *
-     * Enable using "adb shell setprop log.tag.SQLiteLog VERBOSE".
+     * {@hide}
      */
-    public static final boolean DEBUG_SQL_LOG =
-            Log.isLoggable("SQLiteLog", Log.VERBOSE);
+    public static final class Consts {
+        /**
+         * Controls the printing of informational SQL log messages.
+         *
+         * Enable using "adb shell setprop log.tag.SQLiteLog VERBOSE".
+         */
+        public static final boolean DEBUG_SQL_LOG =
+                Log.isLoggable("SQLiteLog", Log.VERBOSE);
 
-    /**
-     * Controls the printing of SQL statements as they are executed.
-     *
-     * Enable using "adb shell setprop log.tag.SQLiteStatements VERBOSE".
-     */
-    public static final boolean DEBUG_SQL_STATEMENTS =
-            Log.isLoggable("SQLiteStatements", Log.VERBOSE);
+        /**
+         * Controls the printing of SQL statements as they are executed.
+         *
+         * Enable using "adb shell setprop log.tag.SQLiteStatements VERBOSE".
+         */
+        public static final boolean DEBUG_SQL_STATEMENTS =
+                Log.isLoggable("SQLiteStatements", Log.VERBOSE);
 
-    /**
-     * Controls the printing of wall-clock time taken to execute SQL statements
-     * as they are executed.
-     *
-     * Enable using "adb shell setprop log.tag.SQLiteTime VERBOSE".
-     */
-    public static final boolean DEBUG_SQL_TIME =
-            Log.isLoggable("SQLiteTime", Log.VERBOSE);
+        /**
+         * Controls the printing of wall-clock time taken to execute SQL statements
+         * as they are executed.
+         *
+         * Enable using "adb shell setprop log.tag.SQLiteTime VERBOSE".
+         */
+        public static final boolean DEBUG_SQL_TIME =
+                Log.isLoggable("SQLiteTime", Log.VERBOSE);
 
-    /**
-     * True to enable database performance testing instrumentation.
-     * @hide
-     */
-    public static final boolean DEBUG_LOG_SLOW_QUERIES = Build.IS_DEBUGGABLE;
+
+        /**
+         * True to enable database performance testing instrumentation.
+         */
+        public static final boolean DEBUG_LOG_SLOW_QUERIES = Build.IS_DEBUGGABLE;
+
+        private static final String SLOW_QUERY_THRESHOLD_PROP = "db.log.slow_query_threshold";
+
+        private static final String SLOW_QUERY_THRESHOLD_UID_PROP =
+                SLOW_QUERY_THRESHOLD_PROP + "." + Process.myUid();
+
+        /**
+         * Whether to add detailed information to slow query log.
+         */
+        public static final boolean DEBUG_LOG_DETAILED = Build.IS_DEBUGGABLE
+                && SystemProperties.getBoolean("db.log.detailed", false);
+    }
 
     private SQLiteDebug() {
     }
@@ -75,14 +94,19 @@
      * be considered slow.  If the value does not exist or is negative, then no queries will
      * be considered slow.
      *
+     * To enable it for a specific UID, "db.log.slow_query_threshold.UID" could also be used.
+     *
      * This value can be changed dynamically while the system is running.
      * For example, "adb shell setprop db.log.slow_query_threshold 200" will
      * log all queries that take 200ms or longer to run.
      * @hide
      */
-    public static final boolean shouldLogSlowQuery(long elapsedTimeMillis) {
-        int slowQueryMillis = SystemProperties.getInt("db.log.slow_query_threshold", -1);
-        return slowQueryMillis >= 0 && elapsedTimeMillis >= slowQueryMillis;
+    public static boolean shouldLogSlowQuery(long elapsedTimeMillis) {
+        final int slowQueryMillis = Math.min(
+                SystemProperties.getInt(Consts.SLOW_QUERY_THRESHOLD_PROP, Integer.MAX_VALUE),
+                SystemProperties.getInt(Consts.SLOW_QUERY_THRESHOLD_UID_PROP,
+                        Integer.MAX_VALUE));
+        return elapsedTimeMillis >= slowQueryMillis;
     }
 
     /**
diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java
index d6d9764..67e5f65 100644
--- a/core/java/android/database/sqlite/SQLiteGlobal.java
+++ b/core/java/android/database/sqlite/SQLiteGlobal.java
@@ -39,11 +39,18 @@
 public final class SQLiteGlobal {
     private static final String TAG = "SQLiteGlobal";
 
+    /** @hide */
+    public static final String SYNC_MODE_FULL = "FULL";
+
     private static final Object sLock = new Object();
+
     private static int sDefaultPageSize;
 
     private static native int nativeReleaseMemory();
 
+    /** @hide */
+    public static volatile String sDefaultSyncMode;
+
     private SQLiteGlobal() {
     }
 
@@ -103,6 +110,11 @@
      * Gets the default database synchronization mode when WAL is not in use.
      */
     public static String getDefaultSyncMode() {
+        // Use the FULL synchronous mode for system processes by default.
+        String defaultMode = sDefaultSyncMode;
+        if (defaultMode != null) {
+            return defaultMode;
+        }
         return SystemProperties.get("debug.sqlite.syncmode",
                 Resources.getSystem().getString(
                 com.android.internal.R.string.db_default_sync_mode));
@@ -112,6 +124,11 @@
      * Gets the database synchronization mode when in WAL mode.
      */
     public static String getWALSyncMode() {
+        // Use the FULL synchronous mode for system processes by default.
+        String defaultMode = sDefaultSyncMode;
+        if (defaultMode != null) {
+            return defaultMode;
+        }
         return SystemProperties.get("debug.sqlite.wal.syncmode",
                 Resources.getSystem().getString(
                 com.android.internal.R.string.db_wal_sync_mode));
@@ -147,4 +164,21 @@
                         com.android.internal.R.integer.db_default_idle_connection_timeout));
     }
 
+    /**
+     * When opening a database, if the WAL file is larger than this size, we'll truncate it.
+     *
+     * (If it's 0, we do not truncate.)
+     *
+     * @hide
+     */
+    public static long getWALTruncateSize() {
+        final long setting = SQLiteCompatibilityWalFlags.getTruncateSize();
+        if (setting >= 0) {
+            return setting;
+        }
+        return SystemProperties.getInt("debug.sqlite.wal.truncatesize",
+                Resources.getSystem().getInteger(
+                        com.android.internal.R.integer.db_wal_truncate_size));
+    }
+
 }
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 7ff6635..1377806 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -19,6 +19,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.database.DatabaseErrorHandler;
 import android.database.SQLException;
@@ -52,6 +53,7 @@
     private static final String TAG = SQLiteOpenHelper.class.getSimpleName();
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private final String mName;
     private final int mNewVersion;
     private final int mMinimumSupportedVersion;
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 26e8c31..8304133 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -16,6 +16,7 @@
 
 package android.database.sqlite;
 
+import android.annotation.UnsupportedAppUsage;
 import android.database.DatabaseUtils;
 import android.os.CancellationSignal;
 
@@ -31,10 +32,12 @@
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
     private final SQLiteDatabase mDatabase;
+    @UnsupportedAppUsage
     private final String mSql;
     private final boolean mReadOnly;
     private final String[] mColumnNames;
     private final int mNumParameters;
+    @UnsupportedAppUsage
     private final Object[] mBindArgs;
 
     SQLiteProgram(SQLiteDatabase db, String sql, Object[] bindArgs,
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index c6c676f..b705ebb 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -16,17 +16,27 @@
 
 package android.database.sqlite;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
+import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
+import android.os.Build;
 import android.os.CancellationSignal;
 import android.os.OperationCanceledException;
 import android.provider.BaseColumns;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 
+import libcore.util.EmptyArray;
+
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Set;
 import java.util.regex.Pattern;
 
@@ -34,15 +44,17 @@
  * This is a convenience class that helps build SQL queries to be sent to
  * {@link SQLiteDatabase} objects.
  */
-public class SQLiteQueryBuilder
-{
+public class SQLiteQueryBuilder {
     private static final String TAG = "SQLiteQueryBuilder";
     private static final Pattern sLimitPattern =
             Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?");
 
     private Map<String, String> mProjectionMap = null;
+    @UnsupportedAppUsage
     private String mTables = "";
+    @UnsupportedAppUsage
     private StringBuilder mWhereClause = null;  // lazily created
+    @UnsupportedAppUsage
     private boolean mDistinct;
     private SQLiteDatabase.CursorFactory mFactory;
     private boolean mStrict;
@@ -91,13 +103,10 @@
      *
      * @param inWhere the chunk of text to append to the WHERE clause.
      */
-    public void appendWhere(CharSequence inWhere) {
+    public void appendWhere(@NonNull CharSequence inWhere) {
         if (mWhereClause == null) {
             mWhereClause = new StringBuilder(inWhere.length() + 16);
         }
-        if (mWhereClause.length() == 0) {
-            mWhereClause.append('(');
-        }
         mWhereClause.append(inWhere);
     }
 
@@ -111,17 +120,35 @@
      * @param inWhere the chunk of text to append to the WHERE clause. it will be escaped
      * to avoid SQL injection attacks
      */
-    public void appendWhereEscapeString(String inWhere) {
+    public void appendWhereEscapeString(@NonNull String inWhere) {
         if (mWhereClause == null) {
             mWhereClause = new StringBuilder(inWhere.length() + 16);
         }
-        if (mWhereClause.length() == 0) {
-            mWhereClause.append('(');
-        }
         DatabaseUtils.appendEscapedSQLString(mWhereClause, inWhere);
     }
 
     /**
+     * Add a standalone chunk to the {@code WHERE} clause of this query.
+     * <p>
+     * This method differs from {@link #appendWhere(CharSequence)} in that it
+     * automatically appends {@code AND} to any existing {@code WHERE} clause
+     * already under construction before appending the given standalone
+     * expression wrapped in parentheses.
+     *
+     * @param inWhere the standalone expression to append to the {@code WHERE}
+     *            clause. It will be wrapped in parentheses when it's appended.
+     */
+    public void appendWhereStandalone(@NonNull CharSequence inWhere) {
+        if (mWhereClause == null) {
+            mWhereClause = new StringBuilder(inWhere.length() + 16);
+        }
+        if (mWhereClause.length() > 0) {
+            mWhereClause.append(" AND ");
+        }
+        mWhereClause.append('(').append(inWhere).append(')');
+    }
+
+    /**
      * Sets the projection map for the query.  The projection map maps
      * from column names that the caller passes into query to database
      * column names. This is useful for renaming columns as well as
@@ -376,6 +403,11 @@
             return null;
         }
 
+        final String sql;
+        final String unwrappedSql = buildQuery(
+                projectionIn, selection, groupBy, having,
+                sortOrder, limit);
+
         if (mStrict && selection != null && selection.length() > 0) {
             // Validate the user-supplied selection to detect syntactic anomalies
             // in the selection string that could indicate a SQL injection attempt.
@@ -384,25 +416,165 @@
             // originally specified. An attacker cannot create an expression that
             // would escape the SQL expression while maintaining balanced parentheses
             // in both the wrapped and original forms.
-            String sqlForValidation = buildQuery(projectionIn, "(" + selection + ")", groupBy,
+
+            // NOTE: The ordering of the below operations is important; we must
+            // execute the wrapped query to ensure the untrusted clause has been
+            // fully isolated.
+
+            // Validate the unwrapped query
+            db.validateSql(unwrappedSql, cancellationSignal); // will throw if query is invalid
+
+            // Execute wrapped query for extra protection
+            final String wrappedSql = buildQuery(projectionIn, wrap(selection), groupBy,
                     having, sortOrder, limit);
-            db.validateSql(sqlForValidation, cancellationSignal); // will throw if query is invalid
+            sql = wrappedSql;
+        } else {
+            // Execute unwrapped query
+            sql = unwrappedSql;
         }
 
-        String sql = buildQuery(
-                projectionIn, selection, groupBy, having,
-                sortOrder, limit);
-
+        final String[] sqlArgs = selectionArgs;
         if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "Performing query: " + sql);
+            if (Build.IS_DEBUGGABLE) {
+                Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs));
+            } else {
+                Log.d(TAG, sql);
+            }
         }
         return db.rawQueryWithFactory(
-                mFactory, sql, selectionArgs,
+                mFactory, sql, sqlArgs,
                 SQLiteDatabase.findEditTable(mTables),
                 cancellationSignal); // will throw if query is invalid
     }
 
     /**
+     * Perform an update by combining all current settings and the
+     * information passed into this method.
+     *
+     * @param db the database to update on
+     * @param selection A filter declaring which rows to return,
+     *   formatted as an SQL WHERE clause (excluding the WHERE
+     *   itself). Passing null will return all rows for the given URL.
+     * @param selectionArgs You may include ?s in selection, which
+     *   will be replaced by the values from selectionArgs, in order
+     *   that they appear in the selection. The values will be bound
+     *   as Strings.
+     * @return the number of rows updated
+     */
+    public int update(@NonNull SQLiteDatabase db, @NonNull ContentValues values,
+            @Nullable String selection, @Nullable String[] selectionArgs) {
+        Objects.requireNonNull(mTables, "No tables defined");
+        Objects.requireNonNull(db, "No database defined");
+        Objects.requireNonNull(values, "No values defined");
+
+        final String sql;
+        final String unwrappedSql = buildUpdate(values, selection);
+
+        if (mStrict) {
+            // Validate the user-supplied selection to detect syntactic anomalies
+            // in the selection string that could indicate a SQL injection attempt.
+            // The idea is to ensure that the selection clause is a valid SQL expression
+            // by compiling it twice: once wrapped in parentheses and once as
+            // originally specified. An attacker cannot create an expression that
+            // would escape the SQL expression while maintaining balanced parentheses
+            // in both the wrapped and original forms.
+
+            // NOTE: The ordering of the below operations is important; we must
+            // execute the wrapped query to ensure the untrusted clause has been
+            // fully isolated.
+
+            // Validate the unwrapped query
+            db.validateSql(unwrappedSql, null); // will throw if query is invalid
+
+            // Execute wrapped query for extra protection
+            final String wrappedSql = buildUpdate(values, wrap(selection));
+            sql = wrappedSql;
+        } else {
+            // Execute unwrapped query
+            sql = unwrappedSql;
+        }
+
+        if (selectionArgs == null) {
+            selectionArgs = EmptyArray.STRING;
+        }
+        final ArrayMap<String, Object> rawValues = values.getValues();
+        final int valuesLength = rawValues.size();
+        final Object[] sqlArgs = new Object[valuesLength + selectionArgs.length];
+        for (int i = 0; i < sqlArgs.length; i++) {
+            if (i < valuesLength) {
+                sqlArgs[i] = rawValues.valueAt(i);
+            } else {
+                sqlArgs[i] = selectionArgs[i - valuesLength];
+            }
+        }
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (Build.IS_DEBUGGABLE) {
+                Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs));
+            } else {
+                Log.d(TAG, sql);
+            }
+        }
+        return db.executeSql(sql, sqlArgs);
+    }
+
+    /**
+     * Perform a delete by combining all current settings and the
+     * information passed into this method.
+     *
+     * @param db the database to delete on
+     * @param selection A filter declaring which rows to return,
+     *   formatted as an SQL WHERE clause (excluding the WHERE
+     *   itself). Passing null will return all rows for the given URL.
+     * @param selectionArgs You may include ?s in selection, which
+     *   will be replaced by the values from selectionArgs, in order
+     *   that they appear in the selection. The values will be bound
+     *   as Strings.
+     * @return the number of rows deleted
+     */
+    public int delete(@NonNull SQLiteDatabase db, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        Objects.requireNonNull(mTables, "No tables defined");
+        Objects.requireNonNull(db, "No database defined");
+
+        final String sql;
+        final String unwrappedSql = buildDelete(selection);
+
+        if (mStrict) {
+            // Validate the user-supplied selection to detect syntactic anomalies
+            // in the selection string that could indicate a SQL injection attempt.
+            // The idea is to ensure that the selection clause is a valid SQL expression
+            // by compiling it twice: once wrapped in parentheses and once as
+            // originally specified. An attacker cannot create an expression that
+            // would escape the SQL expression while maintaining balanced parentheses
+            // in both the wrapped and original forms.
+
+            // NOTE: The ordering of the below operations is important; we must
+            // execute the wrapped query to ensure the untrusted clause has been
+            // fully isolated.
+
+            // Validate the unwrapped query
+            db.validateSql(unwrappedSql, null); // will throw if query is invalid
+
+            // Execute wrapped query for extra protection
+            final String wrappedSql = buildDelete(wrap(selection));
+            sql = wrappedSql;
+        } else {
+            // Execute unwrapped query
+            sql = unwrappedSql;
+        }
+
+        final String[] sqlArgs = selectionArgs;
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (Build.IS_DEBUGGABLE) {
+                Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs));
+            } else {
+                Log.d(TAG, sql);
+            }
+        }
+        return db.executeSql(sql, sqlArgs);
+    }
+
+    /**
      * Construct a SELECT statement suitable for use in a group of
      * SELECT statements that will be joined through UNION operators
      * in buildUnionQuery.
@@ -434,28 +606,10 @@
             String[] projectionIn, String selection, String groupBy,
             String having, String sortOrder, String limit) {
         String[] projection = computeProjection(projectionIn);
-
-        StringBuilder where = new StringBuilder();
-        boolean hasBaseWhereClause = mWhereClause != null && mWhereClause.length() > 0;
-
-        if (hasBaseWhereClause) {
-            where.append(mWhereClause.toString());
-            where.append(')');
-        }
-
-        // Tack on the user's selection, if present.
-        if (selection != null && selection.length() > 0) {
-            if (hasBaseWhereClause) {
-                where.append(" AND ");
-            }
-
-            where.append('(');
-            where.append(selection);
-            where.append(')');
-        }
+        String where = computeWhere(selection);
 
         return buildQueryString(
-                mDistinct, mTables, projection, where.toString(),
+                mDistinct, mTables, projection, where,
                 groupBy, having, sortOrder, limit);
     }
 
@@ -472,6 +626,42 @@
         return buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit);
     }
 
+    /** {@hide} */
+    public String buildUpdate(ContentValues values, String selection) {
+        if (values == null || values.isEmpty()) {
+            throw new IllegalArgumentException("Empty values");
+        }
+
+        StringBuilder sql = new StringBuilder(120);
+        sql.append("UPDATE ");
+        sql.append(mTables);
+        sql.append(" SET ");
+
+        final ArrayMap<String, Object> rawValues = values.getValues();
+        for (int i = 0; i < rawValues.size(); i++) {
+            if (i > 0) {
+                sql.append(',');
+            }
+            sql.append(rawValues.keyAt(i));
+            sql.append("=?");
+        }
+
+        final String where = computeWhere(selection);
+        appendClause(sql, " WHERE ", where);
+        return sql.toString();
+    }
+
+    /** {@hide} */
+    public String buildDelete(String selection) {
+        StringBuilder sql = new StringBuilder(120);
+        sql.append("DELETE FROM ");
+        sql.append(mTables);
+
+        final String where = computeWhere(selection);
+        appendClause(sql, " WHERE ", where);
+        return sql.toString();
+    }
+
     /**
      * Construct a SELECT statement suitable for use in a group of
      * SELECT statements that will be joined through UNION operators
@@ -596,6 +786,7 @@
         return query.toString();
     }
 
+    @UnsupportedAppUsage
     private String[] computeProjection(String[] projectionIn) {
         if (projectionIn != null && projectionIn.length > 0) {
             if (mProjectionMap != null) {
@@ -645,4 +836,37 @@
         }
         return null;
     }
+
+    private @Nullable String computeWhere(@Nullable String selection) {
+        final boolean hasInternal = !TextUtils.isEmpty(mWhereClause);
+        final boolean hasExternal = !TextUtils.isEmpty(selection);
+
+        if (hasInternal || hasExternal) {
+            final StringBuilder where = new StringBuilder();
+            if (hasInternal) {
+                where.append('(').append(mWhereClause).append(')');
+            }
+            if (hasInternal && hasExternal) {
+                where.append(" AND ");
+            }
+            if (hasExternal) {
+                where.append('(').append(selection).append(')');
+            }
+            return where.toString();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Wrap given argument in parenthesis, unless it's {@code null} or
+     * {@code ()}, in which case return it verbatim.
+     */
+    private @Nullable String wrap(@Nullable String arg) {
+        if (TextUtils.isEmpty(arg)) {
+            return arg;
+        } else {
+            return "(" + arg + ")";
+        }
+    }
 }
diff --git a/core/java/android/database/sqlite/SQLiteSession.java b/core/java/android/database/sqlite/SQLiteSession.java
index d80ab1f..a9ac9e7 100644
--- a/core/java/android/database/sqlite/SQLiteSession.java
+++ b/core/java/android/database/sqlite/SQLiteSession.java
@@ -16,6 +16,7 @@
 
 package android.database.sqlite;
 
+import android.annotation.UnsupportedAppUsage;
 import android.database.CursorWindow;
 import android.database.DatabaseUtils;
 import android.os.CancellationSignal;
@@ -291,6 +292,7 @@
      * @see #yieldTransaction
      * @see #endTransaction
      */
+    @UnsupportedAppUsage
     public void beginTransaction(int transactionMode,
             SQLiteTransactionListener transactionListener, int connectionFlags,
             CancellationSignal cancellationSignal) {
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index b1092d76..8f8f676 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -16,6 +16,7 @@
 
 package android.database.sqlite;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.ParcelFileDescriptor;
 
 /**
@@ -27,6 +28,7 @@
  * </p>
  */
 public final class SQLiteStatement extends SQLiteProgram {
+    @UnsupportedAppUsage
     SQLiteStatement(SQLiteDatabase db, String sql, Object[] bindArgs) {
         super(db, sql, bindArgs, null);
     }
diff --git a/core/java/android/database/sqlite/SqliteWrapper.java b/core/java/android/database/sqlite/SqliteWrapper.java
index b019618..e317164 100644
--- a/core/java/android/database/sqlite/SqliteWrapper.java
+++ b/core/java/android/database/sqlite/SqliteWrapper.java
@@ -17,6 +17,7 @@
 
 package android.database.sqlite;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -44,6 +45,7 @@
         return e.getMessage().equals(SQLITE_EXCEPTION_DETAIL_MESSAGE);
     }
 
+    @UnsupportedAppUsage
     public static void checkSQLiteException(Context context, SQLiteException e) {
         if (isLowMemory(e)) {
             Toast.makeText(context, com.android.internal.R.string.low_memory,
@@ -53,6 +55,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static Cursor query(Context context, ContentResolver resolver, Uri uri,
             String[] projection, String selection, String[] selectionArgs, String sortOrder) {
         try {
@@ -73,6 +76,7 @@
             return false;
         }
     }
+    @UnsupportedAppUsage
     public static int update(Context context, ContentResolver resolver, Uri uri,
             ContentValues values, String where, String[] selectionArgs) {
         try {
@@ -84,6 +88,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static int delete(Context context, ContentResolver resolver, Uri uri,
             String where, String[] selectionArgs) {
         try {
@@ -95,6 +100,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static Uri insert(Context context, ContentResolver resolver,
             Uri uri, ContentValues values) {
         try {
diff --git a/core/java/android/ddm/DdmHandleAppName.java b/core/java/android/ddm/DdmHandleAppName.java
index 7e39e47..9560787 100644
--- a/core/java/android/ddm/DdmHandleAppName.java
+++ b/core/java/android/ddm/DdmHandleAppName.java
@@ -16,6 +16,7 @@
 
 package android.ddm;
 
+import android.annotation.UnsupportedAppUsage;
 import org.apache.harmony.dalvik.ddmc.Chunk;
 import org.apache.harmony.dalvik.ddmc.ChunkHandler;
 import org.apache.harmony.dalvik.ddmc.DdmServer;
@@ -69,6 +70,7 @@
      * before or after DDMS connects.  For the latter we need to send up
      * an APNM message.
      */
+    @UnsupportedAppUsage
     public static void setAppName(String name, int userId) {
         if (name == null || name.length() == 0)
             return;
@@ -79,6 +81,7 @@
         sendAPNM(name, userId);
     }
 
+    @UnsupportedAppUsage
     public static String getAppName() {
         return mAppName;
     }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 22e1f45..8e96f56 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.app.AppOpsManager;
 import android.content.Context;
@@ -164,6 +165,7 @@
     private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400;
     private static final int CAMERA_MSG_FOCUS_MOVE       = 0x800;
 
+    @UnsupportedAppUsage
     private long mNativeContext; // accessed by native methods
     private EventHandler mEventHandler;
     private ShutterCallback mShutterCallback;
@@ -236,6 +238,7 @@
      * Camera HAL device API version 1.0
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int CAMERA_HAL_API_VERSION_1_0 = 0x100;
 
     /**
@@ -451,6 +454,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static Camera openLegacy(int cameraId, int halVersion) {
         if (halVersion < CAMERA_HAL_API_VERSION_1_0) {
             throw new IllegalArgumentException("Invalid HAL version " + halVersion);
@@ -604,6 +608,7 @@
         release();
     }
 
+    @UnsupportedAppUsage
     private native final int native_setup(Object camera_this, int cameraId, int halVersion,
                                            String packageName);
 
@@ -716,6 +721,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public native final void setPreviewSurface(Surface surface) throws IOException;
 
     /**
@@ -839,6 +845,7 @@
      * FIXME: Unhide before release
      * @hide
      */
+    @UnsupportedAppUsage
     public native final boolean previewEnabled();
 
     /**
@@ -1012,11 +1019,13 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public final void addRawImageCallbackBuffer(byte[] callbackBuffer)
     {
         addCallbackBuffer(callbackBuffer, CAMERA_MSG_RAW_IMAGE);
     }
 
+    @UnsupportedAppUsage
     private final void addCallbackBuffer(byte[] callbackBuffer, int msgType)
     {
         // CAMERA_MSG_VIDEO_FRAME may be allowed in the future.
@@ -1263,6 +1272,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static void postEventFromNative(Object camera_ref,
                                             int what, int arg1, int arg2, Object obj)
     {
@@ -2075,7 +2085,9 @@
         mDetailedErrorCallback = cb;
     }
 
+    @UnsupportedAppUsage
     private native final void native_setParameters(String params);
+    @UnsupportedAppUsage
     private native final String native_getParameters();
 
     /**
@@ -2124,6 +2136,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static Parameters getEmptyParameters() {
         Camera camera = new Camera();
         return camera.new Parameters();
@@ -2658,6 +2671,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public void copyFrom(Parameters other) {
             if (other == null) {
                 throw new NullPointerException("other must not be null");
@@ -2689,6 +2703,7 @@
          * @deprecated
          */
         @Deprecated
+        @UnsupportedAppUsage
         public void dump() {
             Log.e(TAG, "dump: size=" + mMap.size());
             for (String k : mMap.keySet()) {
@@ -4407,6 +4422,7 @@
         // Splits a comma delimited string to an ArrayList of Area objects.
         // Example string: "(-10,-10,0,0,300),(0,0,10,10,700)". Return null if
         // the passing string is null or the size is 0 or (0,0,0,0,0).
+        @UnsupportedAppUsage
         private ArrayList<Area> splitArea(String str) {
             if (str == null || str.charAt(0) != '('
                     || str.charAt(str.length() - 1) != ')') {
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index 9aa3f40..c17aabb 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.LongDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -89,6 +90,7 @@
     public static final int S_UI8        = 0x35;
 
     // Note: do not rename, this field is used by native code
+    @UnsupportedAppUsage
     private long mNativeObject;
 
     // Invoked on destruction
@@ -182,6 +184,7 @@
      * Private use only. See {@link #create(int, int, int, int, long)}. May also be
      * called from JNI using an already allocated native <code>HardwareBuffer</code>.
      */
+    @UnsupportedAppUsage
     private HardwareBuffer(long nativeObject) {
         mNativeObject = nativeObject;
 
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 7297426..4aa6fab 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -18,6 +18,7 @@
 package android.hardware;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 
 /**
@@ -504,6 +505,7 @@
      *
      * @hide Expected to be used internally for always on display.
      */
+    @UnsupportedAppUsage
     public static final int TYPE_PICK_UP_GESTURE = 25;
 
     /**
@@ -543,6 +545,7 @@
      * @hide Expected to be used internally for auto-rotate and speaker rotation.
      *
      */
+    @UnsupportedAppUsage
     public static final int TYPE_DEVICE_ORIENTATION = 27;
 
     /**
@@ -891,6 +894,7 @@
     private String  mStringType;
     private String  mRequiredPermission;
     private int     mMaxDelay;
+    @UnsupportedAppUsage
     private int     mFlags;
     private int     mId;
 
@@ -1014,6 +1018,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getHandle() {
         return mHandle;
     }
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index bbd04a3..8c910b2 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -16,6 +16,8 @@
 
 package android.hardware;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * This class represents a {@link android.hardware.Sensor Sensor} event and
  * holds information such as the sensor's type, the time-stamp, accuracy and of
@@ -649,6 +651,7 @@
      */
     public long timestamp;
 
+    @UnsupportedAppUsage
     SensorEvent(int valueSize) {
         values = new float[valueSize];
     }
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index cbddc91..3250428 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Build;
 import android.os.Handler;
@@ -368,6 +369,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public SensorManager() {
     }
 
diff --git a/core/java/android/hardware/SerialManager.java b/core/java/android/hardware/SerialManager.java
index 610f6a5..571c3cc 100644
--- a/core/java/android/hardware/SerialManager.java
+++ b/core/java/android/hardware/SerialManager.java
@@ -17,6 +17,7 @@
 package android.hardware;
 
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -46,6 +47,7 @@
      *
      * @return names of available serial ports
      */
+    @UnsupportedAppUsage
     public String[] getSerialPorts() {
         try {
             return mService.getSerialPorts();
@@ -65,6 +67,7 @@
      * @param speed at which to open the serial port
      * @return the serial port
      */
+    @UnsupportedAppUsage
     public SerialPort openSerialPort(String name, int speed) throws IOException {
         try {
             ParcelFileDescriptor pfd = mService.openSerialPort(name);
diff --git a/core/java/android/hardware/SerialPort.java b/core/java/android/hardware/SerialPort.java
index 5d83d9c..78ac3c0 100644
--- a/core/java/android/hardware/SerialPort.java
+++ b/core/java/android/hardware/SerialPort.java
@@ -16,6 +16,7 @@
 
 package android.hardware;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.ParcelFileDescriptor;
 
 import java.io.FileDescriptor;
@@ -31,6 +32,7 @@
     private static final String TAG = "SerialPort";
 
     // used by the JNI code
+    @UnsupportedAppUsage
     private int mNativeContext;
     private final String mName;
     private ParcelFileDescriptor mFileDescriptor;
@@ -59,6 +61,7 @@
     /**
      * Closes the serial port
      */
+    @UnsupportedAppUsage
     public void close() throws IOException {
         if (mFileDescriptor != null) {
             mFileDescriptor.close();
@@ -102,6 +105,7 @@
      * @param buffer to write
      * @param length number of bytes to write
      */
+    @UnsupportedAppUsage
     public void write(ByteBuffer buffer, int length) throws IOException {
         if (buffer.isDirect()) {
             native_write_direct(buffer, length);
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 1174cb6..7abfabf 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -16,6 +16,7 @@
 
 package android.hardware;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -758,10 +759,13 @@
             if (sensor == null) throw new NullPointerException();
             return nativeDisableSensor(mNativeSensorEventQueue, sensor.getHandle());
         }
+        @UnsupportedAppUsage
         protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
                 long timestamp);
+        @UnsupportedAppUsage
         protected abstract void dispatchFlushCompleteEvent(int handle);
 
+        @UnsupportedAppUsage
         protected void dispatchAdditionalInfoEvent(
                 int handle, int type, int serial, float[] floatValues, int[] intValues) {
             // default implementation is do nothing
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index a037289..5cf8f45 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -19,6 +19,10 @@
 
 /**
  * Interface containing all of the biometric modality agnostic constants.
+ *
+ * NOTE: The error messages must be consistent between BiometricConstants, Biometric*Constants,
+ *       and the frameworks/support/biometric/.../BiometricConstants files.
+ *
  * @hide
  */
 public interface BiometricConstants {
@@ -106,6 +110,13 @@
     int BIOMETRIC_ERROR_HW_NOT_PRESENT = 12;
 
     /**
+     * The user pressed the negative button. This is a placeholder that is currently only used
+     * by the support library.
+     * @hide
+     */
+    int BIOMETRIC_ERROR_NEGATIVE_BUTTON = 13;
+
+    /**
      * @hide
      */
     int BIOMETRIC_ERROR_VENDOR_BASE = 1000;
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index 008601c..4aa1e76 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -20,6 +20,10 @@
 
 /**
  * Interface containing all of the face-specific constants.
+ *
+ * NOTE: The error messages must be consistent between BiometricConstants, Biometric*Constants,
+ *       and the frameworks/support/biometric/.../BiometricConstants files.
+ *
  * @hide
  */
 public interface BiometricFaceConstants {
@@ -31,27 +35,32 @@
      * The hardware is unavailable. Try again later.
      */
     public static final int FACE_ERROR_HW_UNAVAILABLE = 1;
+
     /**
      * Error state returned when the sensor was unable to process the current image.
      */
     public static final int FACE_ERROR_UNABLE_TO_PROCESS = 2;
+
     /**
      * Error state returned when the current request has been running too long. This is intended to
      * prevent programs from waiting for the face authentication sensor indefinitely. The timeout is
      * platform and sensor-specific, but is generally on the order of 30 seconds.
      */
     public static final int FACE_ERROR_TIMEOUT = 3;
+
     /**
      * Error state returned for operations like enrollment; the operation cannot be completed
      * because there's not enough storage remaining to complete the operation.
      */
     public static final int FACE_ERROR_NO_SPACE = 4;
+
     /**
      * The operation was canceled because the face authentication sensor is unavailable. For
      * example, this may happen when the user is switched, the device is locked or another pending
      * operation prevents or disables it.
      */
     public static final int FACE_ERROR_CANCELED = 5;
+
     /**
      * The {@link FaceManager#remove} call failed. Typically this will happen when the
      * provided face id was incorrect.
@@ -59,11 +68,13 @@
      * @hide
      */
     public static final int FACE_ERROR_UNABLE_TO_REMOVE = 6;
+
     /**
      * The operation was canceled because the API is locked out due to too many attempts.
      * This occurs after 5 failed attempts, and lasts for 30 seconds.
      */
     public static final int FACE_ERROR_LOCKOUT = 7;
+
     /**
      * Hardware vendors may extend this list if there are conditions that do not fall under one of
      * the above categories. Vendors are responsible for providing error strings for these errors.
@@ -80,22 +91,33 @@
      * (PIN/Pattern/Password)
      */
     public static final int FACE_ERROR_LOCKOUT_PERMANENT = 9;
+
     /**
      * The user canceled the operation. Upon receiving this, applications should use alternate
      * authentication (e.g. a password). The application should also provide the means to return
      * to face authentication, such as a "use face authentication" button.
      */
     public static final int FACE_ERROR_USER_CANCELED = 10;
+
     /**
      * The user does not have a face enrolled.
      */
     public static final int FACE_ERROR_NOT_ENROLLED = 11;
+
     /**
      * The device does not have a face sensor. This message will propagate if the calling app
      * ignores the result from PackageManager.hasFeature(FEATURE_FACE) and calls
      * this API anyway. Apps should always check for the feature before calling this API.
      */
     public static final int FACE_ERROR_HW_NOT_PRESENT = 12;
+
+    /**
+     * The user pressed the negative button. This is a placeholder that is currently only used
+     * by the support library.
+     * @hide
+     */
+    public static final int FACE_ERROR_NEGATIVE_BUTTON = 13;
+
     /**
      * @hide
      */
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 638f525..d583d78 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -20,6 +20,10 @@
 
 /**
  * Interface containing all of the fingerprint-specific constants.
+ *
+ * NOTE: The error messages must be consistent between BiometricConstants, Biometric*Constants,
+ *       and the frameworks/support/biometric/.../BiometricConstants files.
+ *
  * @hide
  */
 public interface BiometricFingerprintConstants {
@@ -107,6 +111,13 @@
     public static final int FINGERPRINT_ERROR_HW_NOT_PRESENT = 12;
 
     /**
+     * The user pressed the negative button. This is a placeholder that is currently only used
+     * by the support library.
+     * @hide
+     */
+    public static final int FINGERPRINT_ERROR_NEGATIVE_BUTTON = 13;
+
+    /**
      * @hide
      */
     public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index bad418a..02bcff5 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -69,6 +69,7 @@
      * @hide
      */
     public static final int HIDE_DIALOG_DELAY = 2000; // ms
+
     /**
      * @hide
      */
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 32c6898..35584ae 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.impl.PublicKey;
 import android.hardware.camera2.impl.SyntheticKey;
@@ -72,6 +73,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Key(String name, Class<T> type, long vendorId) {
             mKey = new CameraMetadataNative.Key<T>(name,  type, vendorId);
         }
@@ -90,6 +92,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Key(String name, Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name,  type);
         }
@@ -99,6 +102,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Key(String name, TypeReference<T> typeReference) {
             mKey = new CameraMetadataNative.Key<T>(name,  typeReference);
         }
@@ -168,6 +172,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public CameraMetadataNative.Key<T> getNativeKey() {
             return mKey;
         }
@@ -180,6 +185,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private final CameraMetadataNative mProperties;
     private List<CameraCharacteristics.Key<?>> mKeys;
     private List<CaptureRequest.Key<?>> mAvailableRequestKeys;
@@ -1249,7 +1255,9 @@
      * <p>If this device is the largest or only camera device with a given facing, then this
      * position will be <code>(0, 0, 0)</code>; a camera device with a lens optical center located 3 cm
      * from the main sensor along the +X axis (to the right from the user's perspective) will
-     * report <code>(0.03, 0, 0)</code>.</p>
+     * report <code>(0.03, 0, 0)</code>.  Note that this means that, for many computer vision
+     * applications, the position needs to be negated to convert it to a translation from the
+     * camera to the origin.</p>
      * <p>To transform a pixel coordinates between two cameras facing the same direction, first
      * the source camera {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} must be corrected for.  Then the source
      * camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs to be applied, followed by the
@@ -1261,7 +1269,8 @@
      * <p>To compare this against a real image from the destination camera, the destination camera
      * image then needs to be corrected for radial distortion before comparison or sampling.</p>
      * <p>When {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is GYROSCOPE, then this position is relative to
-     * the center of the primary gyroscope on the device.</p>
+     * the center of the primary gyroscope on the device. The axis definitions are the same as
+     * with PRIMARY_CAMERA.</p>
      * <p><b>Units</b>: Meters</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
@@ -1293,13 +1302,15 @@
      * </code></pre>
      * <p>which can then be combined with the camera pose rotation
      * <code>R</code> and translation <code>t</code> ({@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} and
-     * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respective) to calculate the
+     * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respectively) to calculate the
      * complete transform from world coordinates to pixel
      * coordinates:</p>
-     * <pre><code>P = [ K 0   * [ R t
-     *      0 1 ]     0 1 ]
+     * <pre><code>P = [ K 0   * [ R -Rt
+     *      0 1 ]      0 1 ]
      * </code></pre>
-     * <p>and with <code>p_w</code> being a point in the world coordinate system
+     * <p>(Note the negation of poseTranslation when mapping from camera
+     * to world coordinates, and multiplication by the rotation).</p>
+     * <p>With <code>p_w</code> being a point in the world coordinate system
      * and <code>p_s</code> being a point in the camera active pixel array
      * coordinate system, and with the mapping including the
      * homogeneous division by z:</p>
@@ -1321,6 +1332,13 @@
      * activeArraySize rectangle), to determine the final pixel
      * coordinate of the world point for processed (non-RAW)
      * output buffers.</p>
+     * <p>For camera devices, the center of pixel <code>(x,y)</code> is located at
+     * coordinate <code>(x + 0.5, y + 0.5)</code>.  So on a device with a
+     * precorrection active array of size <code>(10,10)</code>, the valid pixel
+     * indices go from <code>(0,0)-(9,9)</code>, and an perfectly-built camera would
+     * have an optical center at the exact center of the pixel grid, at
+     * coordinates <code>(5.0, 5.0)</code>, which is the top-left corner of pixel
+     * <code>(5,5)</code>.</p>
      * <p><b>Units</b>:
      * Pixels in the
      * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
@@ -3136,12 +3154,26 @@
      * the following code snippet can be used:</p>
      * <pre><code>// Returns true if the device supports the required hardware level, or better.
      * boolean isHardwareLevelSupported(CameraCharacteristics c, int requiredLevel) {
+     *     final int[] sortedHwLevels = {
+     *         CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
+     *         CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL,
+     *         CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
+     *         CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
+     *         CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3
+     *     };
      *     int deviceLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
-     *     if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
-     *         return requiredLevel == deviceLevel;
+     *     if (requiredLevel == deviceLevel) {
+     *         return true;
      *     }
-     *     // deviceLevel is not LEGACY, can use numerical sort
-     *     return requiredLevel &lt;= deviceLevel;
+     *
+     *     for (int sortedlevel : sortedHwLevels) {
+     *         if (sortedlevel == requiredLevel) {
+     *             return true;
+     *         } else if (sortedlevel == deviceLevel) {
+     *             return false;
+     *         }
+     *     }
+     *     return false; // Should never reach here
      * }
      * </code></pre>
      * <p>At a high level, the levels are:</p>
@@ -3155,6 +3187,8 @@
      *   post-processing settings, and image capture at a high rate.</li>
      * <li><code>LEVEL_3</code> devices additionally support YUV reprocessing and RAW image capture, along
      *   with additional output stream configurations.</li>
+     * <li><code>EXTERNAL</code> devices are similar to <code>LIMITED</code> devices with exceptions like some sensor or
+     *   lens information not reorted or less stable framerates.</li>
      * </ul>
      * <p>See the individual level enums for full descriptions of the supported capabilities.  The
      * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} entry describes the device's capabilities at a
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index f47d464..ce88697 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -44,19 +44,27 @@
  * {@link android.Manifest.permission#CAMERA Camera} permission in its manifest
  * in order to access camera devices.</p>
  *
- * <p>A given camera device may provide support at one of two levels: limited or
- * full. If a device only supports the limited level, then Camera2 exposes a
- * feature set that is roughly equivalent to the older
+ * <p>A given camera device may provide support at one of several levels defined
+ * in {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}.
+ * If a device supports {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} level,
+ * the camera device is running in backward compatibility mode and has minimum camera2 API support.
+ * If a device supports the {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}
+ * level, then Camera2 exposes a feature set that is roughly equivalent to the older
  * {@link android.hardware.Camera Camera} API, although with a cleaner and more
- * efficient interface.  Devices that implement the full level of support
+ * efficient interface.
+ * If a device supports the {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL EXTERNAL}
+ * level, then the device is a removable camera that provides similar but slightly less features
+ * as the {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} level.
+ * Devices that implement the {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} or
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_3 LEVEL3} level of support
  * provide substantially improved capabilities over the older camera
- * API. Applications that target the limited level devices will run unchanged on
- * the full-level devices; if your application requires a full-level device for
+ * API. If your application requires a full-level device for
  * proper operation, declare the "android.hardware.camera.level.full" feature in your
  * manifest.</p>
  *
  * @see CameraManager#openCamera
  * @see android.Manifest.permission#CAMERA
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
  */
 public abstract class CameraDevice implements AutoCloseable {
 
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 1275a85..caa99d5 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -819,11 +819,11 @@
      * camera in the list of supported camera devices.</p>
      * <p>This capability requires the camera device to support the following:</p>
      * <ul>
-     * <li>This camera device must list the following static metadata entries in {@link android.hardware.camera2.CameraCharacteristics }:<ul>
-     * <li>android.logicalMultiCamera.physicalIds</li>
-     * <li>{@link CameraCharacteristics#LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE android.logicalMultiCamera.sensorSyncType}</li>
-     * </ul>
-     * </li>
+     * <li>The IDs of underlying physical cameras are returned via
+     *   {@link android.hardware.camera2.CameraCharacteristics#getPhysicalCameraIds }.</li>
+     * <li>This camera device must list static metadata
+     *   {@link CameraCharacteristics#LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE android.logicalMultiCamera.sensorSyncType} in
+     *   {@link android.hardware.camera2.CameraCharacteristics }.</li>
      * <li>The underlying physical cameras' static metadata must list the following entries,
      *   so that the application can correlate pixels from the physical streams:<ul>
      * <li>{@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference}</li>
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index aca77a5..4a20468 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.impl.PublicKey;
 import android.hardware.camera2.impl.SyntheticKey;
@@ -107,6 +108,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Key(String name, Class<T> type, long vendorId) {
             mKey = new CameraMetadataNative.Key<T>(name, type, vendorId);
         }
@@ -116,6 +118,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Key(String name, Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name, type);
         }
@@ -125,6 +128,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Key(String name, TypeReference<T> typeReference) {
             mKey = new CameraMetadataNative.Key<T>(name, typeReference);
         }
@@ -194,6 +198,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public CameraMetadataNative.Key<T> getNativeKey() {
             return mKey;
         }
@@ -223,6 +228,7 @@
     private static final ArraySet<Surface> mEmptySurfaceSet = new ArraySet<Surface>();
 
     private String mLogicalCameraId;
+    @UnsupportedAppUsage
     private CameraMetadataNative mLogicalCameraSettings;
     private final HashMap<String, CameraMetadataNative> mPhysicalCameraSettings =
             new HashMap<String, CameraMetadataNative>();
@@ -598,6 +604,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public Collection<Surface> getTargets() {
         return Collections.unmodifiableCollection(mSurfaceSet);
     }
@@ -886,6 +893,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public void setPartOfCHSRequestList(boolean partOfCHSList) {
             mRequest.mIsPartOfCHSRequestList = partOfCHSList;
         }
@@ -2522,7 +2530,7 @@
      * outputs will crop horizontally (pillarbox), and 16:9
      * streams will match exactly. These additional crops will
      * be centered within the crop region.</p>
-     * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height
+     * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, the width and height
      * of the crop region cannot be set to be smaller than
      * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and
      * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p>
@@ -2863,8 +2871,14 @@
             new Key<Integer>("android.statistics.lensShadingMapMode", int.class);
 
     /**
-     * <p>A control for selecting whether OIS position information is included in output
-     * result metadata.</p>
+     * <p>A control for selecting whether optical stabilization (OIS) position
+     * information is included in output result metadata.</p>
+     * <p>Since optical image stabilization generally involves motion much faster than the duration
+     * of individualq image exposure, multiple OIS samples can be included for a single capture
+     * result. For example, if the OIS reporting operates at 200 Hz, a typical camera operating
+     * at 30fps may have 6-7 OIS samples per capture result. This information can be combined
+     * with the rolling shutter skew to account for lens motion during image exposure in
+     * post-processing algorithms.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li>
@@ -3264,14 +3278,28 @@
      * any correction at all would slow down capture rate.  Every output stream will have a
      * similar amount of enhancement applied.</p>
      * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
-     * applied to any RAW output. Metadata coordinates such as face rectangles or metering
-     * regions are also not affected by correction.</p>
+     * applied to any RAW output.</p>
      * <p>This control will be on by default on devices that support this control. Applications
      * disabling distortion correction need to pay extra attention with the coordinate system of
      * metering regions, crop region, and face rectangles. When distortion correction is OFF,
      * metadata coordinates follow the coordinate system of
      * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata
-     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
+     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.  The
+     * camera device will map these metadata fields to match the corrected image produced by the
+     * camera device, for both capture requests and results.  However, this mapping is not very
+     * precise, since rectangles do not generally map to rectangles when corrected.  Only linear
+     * scaling between the active array and precorrection active array coordinates is
+     * performed. Applications that require precise correction of metadata need to undo that
+     * linear scaling, and apply a more complete correction that takes into the account the app's
+     * own requirements.</p>
+     * <p>The full list of metadata that is affected in this way by distortion correction is:</p>
+     * <ul>
+     * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li>
+     * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li>
+     * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li>
+     * </ul>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
@@ -3282,10 +3310,15 @@
      * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
+     * @see CaptureRequest#CONTROL_AE_REGIONS
+     * @see CaptureRequest#CONTROL_AF_REGIONS
+     * @see CaptureRequest#CONTROL_AWB_REGIONS
      * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES
      * @see CameraCharacteristics#LENS_DISTORTION
+     * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
+     * @see CaptureResult#STATISTICS_FACES
      * @see #DISTORTION_CORRECTION_MODE_OFF
      * @see #DISTORTION_CORRECTION_MODE_FAST
      * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d003f9a..3c6c11d 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.impl.CaptureResultExtras;
 import android.hardware.camera2.impl.PublicKey;
@@ -78,6 +79,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Key(String name, Class<T> type, long vendorId) {
             mKey = new CameraMetadataNative.Key<T>(name, type, vendorId);
         }
@@ -96,6 +98,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Key(String name, Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name, type);
         }
@@ -105,6 +108,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Key(String name, TypeReference<T> typeReference) {
             mKey = new CameraMetadataNative.Key<T>(name, typeReference);
         }
@@ -174,6 +178,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public CameraMetadataNative.Key<T> getNativeKey() {
             return mKey;
         }
@@ -184,6 +189,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private final CameraMetadataNative mResults;
     private final CaptureRequest mRequest;
     private final int mSequenceId;
@@ -2852,7 +2858,9 @@
      * <p>If this device is the largest or only camera device with a given facing, then this
      * position will be <code>(0, 0, 0)</code>; a camera device with a lens optical center located 3 cm
      * from the main sensor along the +X axis (to the right from the user's perspective) will
-     * report <code>(0.03, 0, 0)</code>.</p>
+     * report <code>(0.03, 0, 0)</code>.  Note that this means that, for many computer vision
+     * applications, the position needs to be negated to convert it to a translation from the
+     * camera to the origin.</p>
      * <p>To transform a pixel coordinates between two cameras facing the same direction, first
      * the source camera {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} must be corrected for.  Then the source
      * camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs to be applied, followed by the
@@ -2864,7 +2872,8 @@
      * <p>To compare this against a real image from the destination camera, the destination camera
      * image then needs to be corrected for radial distortion before comparison or sampling.</p>
      * <p>When {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is GYROSCOPE, then this position is relative to
-     * the center of the primary gyroscope on the device.</p>
+     * the center of the primary gyroscope on the device. The axis definitions are the same as
+     * with PRIMARY_CAMERA.</p>
      * <p><b>Units</b>: Meters</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
@@ -2896,13 +2905,15 @@
      * </code></pre>
      * <p>which can then be combined with the camera pose rotation
      * <code>R</code> and translation <code>t</code> ({@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} and
-     * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respective) to calculate the
+     * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respectively) to calculate the
      * complete transform from world coordinates to pixel
      * coordinates:</p>
-     * <pre><code>P = [ K 0   * [ R t
-     *      0 1 ]     0 1 ]
+     * <pre><code>P = [ K 0   * [ R -Rt
+     *      0 1 ]      0 1 ]
      * </code></pre>
-     * <p>and with <code>p_w</code> being a point in the world coordinate system
+     * <p>(Note the negation of poseTranslation when mapping from camera
+     * to world coordinates, and multiplication by the rotation).</p>
+     * <p>With <code>p_w</code> being a point in the world coordinate system
      * and <code>p_s</code> being a point in the camera active pixel array
      * coordinate system, and with the mapping including the
      * homogeneous division by z:</p>
@@ -2924,6 +2935,13 @@
      * activeArraySize rectangle), to determine the final pixel
      * coordinate of the world point for processed (non-RAW)
      * output buffers.</p>
+     * <p>For camera devices, the center of pixel <code>(x,y)</code> is located at
+     * coordinate <code>(x + 0.5, y + 0.5)</code>.  So on a device with a
+     * precorrection active array of size <code>(10,10)</code>, the valid pixel
+     * indices go from <code>(0,0)-(9,9)</code>, and an perfectly-built camera would
+     * have an optical center at the exact center of the pixel grid, at
+     * coordinates <code>(5.0, 5.0)</code>, which is the top-left corner of pixel
+     * <code>(5,5)</code>.</p>
      * <p><b>Units</b>:
      * Pixels in the
      * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
@@ -3188,7 +3206,7 @@
      * outputs will crop horizontally (pillarbox), and 16:9
      * streams will match exactly. These additional crops will
      * be centered within the crop region.</p>
-     * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height
+     * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, the width and height
      * of the crop region cannot be set to be smaller than
      * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and
      * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p>
@@ -4077,8 +4095,14 @@
             new Key<Integer>("android.statistics.lensShadingMapMode", int.class);
 
     /**
-     * <p>A control for selecting whether OIS position information is included in output
-     * result metadata.</p>
+     * <p>A control for selecting whether optical stabilization (OIS) position
+     * information is included in output result metadata.</p>
+     * <p>Since optical image stabilization generally involves motion much faster than the duration
+     * of individualq image exposure, multiple OIS samples can be included for a single capture
+     * result. For example, if the OIS reporting operates at 200 Hz, a typical camera operating
+     * at 30fps may have 6-7 OIS samples per capture result. This information can be combined
+     * with the rolling shutter skew to account for lens motion during image exposure in
+     * post-processing algorithms.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li>
@@ -4112,11 +4136,15 @@
     /**
      * <p>An array of shifts of OIS samples, in x direction.</p>
      * <p>The array contains the amount of shifts in x direction, in pixels, based on OIS samples.
-     * A positive value is a shift from left to right in active array coordinate system. For
-     * example, if the optical center is (1000, 500) in active array coordinates, a shift of
-     * (3, 0) puts the new optical center at (1003, 500).</p>
+     * A positive value is a shift from left to right in the pre-correction active array
+     * coordinate system. For example, if the optical center is (1000, 500) in pre-correction
+     * active array coordinates, a shift of (3, 0) puts the new optical center at (1003, 500).</p>
      * <p>The number of shifts must match the number of timestamps in
      * android.statistics.oisTimestamps.</p>
+     * <p>The OIS samples are not affected by whether lens distortion correction is enabled (on
+     * supporting devices). They are always reported in pre-correction active array coordinates,
+     * since the scaling of OIS shifts would depend on the specific spot on the sensor the shift
+     * is needed.</p>
      * <p><b>Units</b>: Pixels in active array.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * @hide
@@ -4127,11 +4155,15 @@
     /**
      * <p>An array of shifts of OIS samples, in y direction.</p>
      * <p>The array contains the amount of shifts in y direction, in pixels, based on OIS samples.
-     * A positive value is a shift from top to bottom in active array coordinate system. For
-     * example, if the optical center is (1000, 500) in active array coordinates, a shift of
-     * (0, 5) puts the new optical center at (1000, 505).</p>
+     * A positive value is a shift from top to bottom in pre-correction active array coordinate
+     * system. For example, if the optical center is (1000, 500) in active array coordinates, a
+     * shift of (0, 5) puts the new optical center at (1000, 505).</p>
      * <p>The number of shifts must match the number of timestamps in
      * android.statistics.oisTimestamps.</p>
+     * <p>The OIS samples are not affected by whether lens distortion correction is enabled (on
+     * supporting devices). They are always reported in pre-correction active array coordinates,
+     * since the scaling of OIS shifts would depend on the specific spot on the sensor the shift
+     * is needed.</p>
      * <p><b>Units</b>: Pixels in active array.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * @hide
@@ -4140,15 +4172,21 @@
             new Key<float[]>("android.statistics.oisYShifts", float[].class);
 
     /**
-     * <p>An array of OIS samples.</p>
+     * <p>An array of optical stabilization (OIS) position samples.</p>
      * <p>Each OIS sample contains the timestamp and the amount of shifts in x and y direction,
      * in pixels, of the OIS sample.</p>
-     * <p>A positive value for a shift in x direction is a shift from left to right in active array
-     * coordinate system. For example, if the optical center is (1000, 500) in active array
-     * coordinates, a shift of (3, 0) puts the new optical center at (1003, 500).</p>
-     * <p>A positive value for a shift in y direction is a shift from top to bottom in active array
-     * coordinate system. For example, if the optical center is (1000, 500) in active array
-     * coordinates, a shift of (0, 5) puts the new optical center at (1000, 505).</p>
+     * <p>A positive value for a shift in x direction is a shift from left to right in the
+     * pre-correction active array coordinate system. For example, if the optical center is
+     * (1000, 500) in pre-correction active array coordinates, a shift of (3, 0) puts the new
+     * optical center at (1003, 500).</p>
+     * <p>A positive value for a shift in y direction is a shift from top to bottom in
+     * pre-correction active array coordinate system. For example, if the optical center is
+     * (1000, 500) in active array coordinates, a shift of (0, 5) puts the new optical center at
+     * (1000, 505).</p>
+     * <p>The OIS samples are not affected by whether lens distortion correction is enabled (on
+     * supporting devices). They are always reported in pre-correction active array coordinates,
+     * since the scaling of OIS shifts would depend on the specific spot on the sensor the shift
+     * is needed.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
     @PublicKey
@@ -4578,14 +4616,28 @@
      * any correction at all would slow down capture rate.  Every output stream will have a
      * similar amount of enhancement applied.</p>
      * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
-     * applied to any RAW output. Metadata coordinates such as face rectangles or metering
-     * regions are also not affected by correction.</p>
+     * applied to any RAW output.</p>
      * <p>This control will be on by default on devices that support this control. Applications
      * disabling distortion correction need to pay extra attention with the coordinate system of
      * metering regions, crop region, and face rectangles. When distortion correction is OFF,
      * metadata coordinates follow the coordinate system of
      * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata
-     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
+     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.  The
+     * camera device will map these metadata fields to match the corrected image produced by the
+     * camera device, for both capture requests and results.  However, this mapping is not very
+     * precise, since rectangles do not generally map to rectangles when corrected.  Only linear
+     * scaling between the active array and precorrection active array coordinates is
+     * performed. Applications that require precise correction of metadata need to undo that
+     * linear scaling, and apply a more complete correction that takes into the account the app's
+     * own requirements.</p>
+     * <p>The full list of metadata that is affected in this way by distortion correction is:</p>
+     * <ul>
+     * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li>
+     * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li>
+     * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li>
+     * </ul>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
@@ -4596,10 +4648,15 @@
      * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
+     * @see CaptureRequest#CONTROL_AE_REGIONS
+     * @see CaptureRequest#CONTROL_AF_REGIONS
+     * @see CaptureRequest#CONTROL_AWB_REGIONS
      * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES
      * @see CameraCharacteristics#LENS_DISTORTION
+     * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
+     * @see CaptureResult#STATISTICS_FACES
      * @see #DISTORTION_CORRECTION_MODE_OFF
      * @see #DISTORTION_CORRECTION_MODE_FAST
      * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 4baf263..0610d7a 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -16,6 +16,7 @@
 
 package android.hardware.camera2.impl;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.ImageFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -231,6 +232,7 @@
          *
          * @return The tag numeric value corresponding to the string
          */
+        @UnsupportedAppUsage
         public final int getTag() {
             if (!mHasTag) {
                 mTag = CameraMetadataNative.getTag(mName, mVendorId);
@@ -747,6 +749,9 @@
         if (faceDetectMode == null) {
             Log.w(TAG, "Face detect mode metadata is null, assuming the mode is SIMPLE");
             faceDetectMode = CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE;
+        } else if (faceDetectMode > CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL) {
+            // Face detect mode is larger than FULL, assuming the mode is FULL
+            faceDetectMode = CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL;
         } else {
             if (faceDetectMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_OFF) {
                 return new Face[0];
@@ -1185,6 +1190,7 @@
         return true;
     }
 
+    @UnsupportedAppUsage
     private long mMetadataPtr; // native CameraMetadata*
 
     private native long nativeAllocate();
@@ -1199,13 +1205,16 @@
     private native synchronized boolean nativeIsEmpty();
     private native synchronized int nativeGetEntryCount();
 
+    @UnsupportedAppUsage
     private native synchronized byte[] nativeReadValues(int tag);
     private native synchronized void nativeWriteValues(int tag, byte[] src);
     private native synchronized void nativeDump() throws IOException; // dump to ALOGD
 
     private native synchronized ArrayList nativeGetAllVendorKeys(Class keyClass);
+    @UnsupportedAppUsage
     private native synchronized int nativeGetTagFromKeyLocal(String keyName)
             throws IllegalArgumentException;
+    @UnsupportedAppUsage
     private native synchronized int nativeGetTypeFromTagLocal(int tag)
             throws IllegalArgumentException;
     private static native int nativeGetTagFromKey(String keyName, long vendorId)
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 5423ca9..8822f71 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -781,6 +781,7 @@
                     CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE                   ,
                     CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE                       ,
                     CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE                    ,
+                    CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE    ,
                     CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE                    ,
                     CameraCharacteristics.SENSOR_ORIENTATION                              ,
                     CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES     ,
@@ -941,11 +942,12 @@
         // Use the largest jpeg size (by area) for both active array and pixel array
         Size largestJpegSize = getLargestSupportedJpegSizeByArea(p);
         /*
-         * sensor.info.activeArraySize
+         * sensor.info.activeArraySize, and preCorrectionActiveArraySize
          */
         {
             Rect activeArrayRect = ParamsUtils.createRect(largestJpegSize);
             m.set(SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArrayRect);
+            m.set(SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, activeArrayRect);
         }
 
         /*
diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
index 9247844..d3c4505 100644
--- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -16,6 +16,7 @@
 
 package android.hardware.camera2.utils;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.legacy.LegacyCameraDevice;
 import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException;
@@ -77,6 +78,7 @@
      *
      * @throws IllegalArgumentException if the surface is already abandoned.
      */
+    @UnsupportedAppUsage
     public static Size getSurfaceSize(Surface surface) {
         try {
             return LegacyCameraDevice.getSurfaceSize(surface);
diff --git a/core/java/android/hardware/camera2/utils/TypeReference.java b/core/java/android/hardware/camera2/utils/TypeReference.java
index 24ce124..d9ba31b 100644
--- a/core/java/android/hardware/camera2/utils/TypeReference.java
+++ b/core/java/android/hardware/camera2/utils/TypeReference.java
@@ -16,6 +16,7 @@
 
 package android.hardware.camera2.utils;
 
+import android.annotation.UnsupportedAppUsage;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.ParameterizedType;
@@ -55,6 +56,7 @@
      *
      * @see TypeReference
      */
+    @UnsupportedAppUsage
     protected TypeReference() {
         ParameterizedType thisType = (ParameterizedType)getClass().getGenericSuperclass();
 
@@ -136,6 +138,7 @@
      *
      * @throws IllegalArgumentException if {@code type} had any type variables
      */
+    @UnsupportedAppUsage
     public static TypeReference<?> createSpecializedTypeReference(Type type) {
         return new SpecializedBaseTypeReference(type);
     }
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index b182fa2..d51e896 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -23,6 +23,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.KeyguardManager;
 import android.content.Context;
 import android.graphics.Point;
@@ -62,6 +63,7 @@
      * </p>
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED =
             "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED";
 
@@ -69,6 +71,7 @@
      * Contains a {@link WifiDisplayStatus} object.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_WIFI_DISPLAY_STATUS =
             "android.hardware.display.extra.WIFI_DISPLAY_STATUS";
 
@@ -437,6 +440,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void startWifiDisplayScan() {
         mGlobal.startWifiDisplayScan();
     }
@@ -449,6 +453,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void stopWifiDisplayScan() {
         mGlobal.stopWifiDisplayScan();
     }
@@ -466,16 +471,19 @@
      * @param deviceAddress The MAC address of the device to which we should connect.
      * @hide
      */
+    @UnsupportedAppUsage
     public void connectWifiDisplay(String deviceAddress) {
         mGlobal.connectWifiDisplay(deviceAddress);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void pauseWifiDisplay() {
         mGlobal.pauseWifiDisplay();
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void resumeWifiDisplay() {
         mGlobal.resumeWifiDisplay();
     }
@@ -485,6 +493,7 @@
      * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
      * @hide
      */
+    @UnsupportedAppUsage
     public void disconnectWifiDisplay() {
         mGlobal.disconnectWifiDisplay();
     }
@@ -504,6 +513,7 @@
      * or empty if no alias should be used.
      * @hide
      */
+    @UnsupportedAppUsage
     public void renameWifiDisplay(String deviceAddress, String alias) {
         mGlobal.renameWifiDisplay(deviceAddress, alias);
     }
@@ -519,6 +529,7 @@
      * @param deviceAddress The MAC address of the device to forget.
      * @hide
      */
+    @UnsupportedAppUsage
     public void forgetWifiDisplay(String deviceAddress) {
         mGlobal.forgetWifiDisplay(deviceAddress);
     }
@@ -531,6 +542,7 @@
      * @return The current Wifi display status.
      * @hide
      */
+    @UnsupportedAppUsage
     public WifiDisplayStatus getWifiDisplayStatus() {
         return mGlobal.getWifiDisplayStatus();
     }
@@ -785,7 +797,8 @@
         void onDisplayRemoved(int displayId);
 
         /**
-         * Called whenever the properties of a logical display have changed.
+         * Called whenever the properties of a logical {@link android.view.Display},
+         * such as size and density, have changed.
          *
          * @param displayId The id of the logical display that changed.
          */
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index d968a3e..7304ab4 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -16,6 +16,7 @@
 
 package android.hardware.display;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
@@ -66,10 +67,12 @@
     public static final int EVENT_DISPLAY_CHANGED = 2;
     public static final int EVENT_DISPLAY_REMOVED = 3;
 
+    @UnsupportedAppUsage
     private static DisplayManagerGlobal sInstance;
 
     private final Object mLock = new Object();
 
+    @UnsupportedAppUsage
     private final IDisplayManager mDm;
 
     private DisplayManagerCallback mCallback;
@@ -91,6 +94,7 @@
      * @return The display manager instance, may be null early in system startup
      * before the display manager has been fully initialized.
      */
+    @UnsupportedAppUsage
     public static DisplayManagerGlobal getInstance() {
         synchronized (DisplayManagerGlobal.class) {
             if (sInstance == null) {
@@ -110,6 +114,7 @@
      * @return Information about the specified display, or null if it does not exist.
      * This object belongs to an internal cache and should be treated as if it were immutable.
      */
+    @UnsupportedAppUsage
     public DisplayInfo getDisplayInfo(int displayId) {
         try {
             synchronized (mLock) {
@@ -146,6 +151,7 @@
      *
      * @return An array containing all display ids.
      */
+    @UnsupportedAppUsage
     public int[] getDisplayIds() {
         try {
             synchronized (mLock) {
@@ -209,6 +215,7 @@
      * @param displayId The logical display id.
      * @return The display object, or null if there is no display with the given id.
      */
+    @UnsupportedAppUsage
     public Display getRealDisplay(int displayId) {
         return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
     }
@@ -337,6 +344,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void disconnectWifiDisplay() {
         try {
             mDm.disconnectWifiDisplay();
@@ -369,6 +377,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public WifiDisplayStatus getWifiDisplayStatus() {
         try {
             return mDm.getWifiDisplayStatus();
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 504f840..7840fd0 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -23,6 +23,7 @@
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.Surface;
 import android.view.SurfaceControl;
 
 /**
@@ -62,6 +63,15 @@
     public abstract boolean isProximitySensorAvailable();
 
     /**
+     * Take a screenshot of the specified display into the provided {@link Surface}.
+     *
+     * @param displayId The display id to take the screenshot of.
+     * @param outSurface The {@link Surface} to take the screenshot into.
+     * @return True if the screenshot is taken.
+     */
+    public abstract boolean screenshot(int displayId, Surface outSurface);
+
+    /**
      * Returns information about the specified logical display.
      *
      * @param displayId The logical display id.
diff --git a/core/java/android/hardware/display/WifiDisplay.java b/core/java/android/hardware/display/WifiDisplay.java
index bb32c19..12486e8 100644
--- a/core/java/android/hardware/display/WifiDisplay.java
+++ b/core/java/android/hardware/display/WifiDisplay.java
@@ -16,6 +16,7 @@
 
 package android.hardware.display;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -76,6 +77,7 @@
     /**
      * Gets the MAC address of the Wifi display device.
      */
+    @UnsupportedAppUsage
     public String getDeviceAddress() {
         return mDeviceAddress;
     }
@@ -83,6 +85,7 @@
     /**
      * Gets the name of the Wifi display device.
      */
+    @UnsupportedAppUsage
     public String getDeviceName() {
         return mDeviceName;
     }
@@ -94,6 +97,7 @@
      * provided by the user when renaming the device.
      * </p>
      */
+    @UnsupportedAppUsage
     public String getDeviceAlias() {
         return mDeviceAlias;
     }
@@ -101,6 +105,7 @@
     /**
      * Returns true if device is available, false otherwise.
      */
+    @UnsupportedAppUsage
     public boolean isAvailable() {
         return mIsAvailable;
     }
@@ -108,6 +113,7 @@
     /**
      * Returns true if device can be connected to (not in use), false otherwise.
      */
+    @UnsupportedAppUsage
     public boolean canConnect() {
         return mCanConnect;
     }
@@ -115,6 +121,7 @@
     /**
      * Returns true if device has been remembered, false otherwise.
      */
+    @UnsupportedAppUsage
     public boolean isRemembered() {
         return mIsRemembered;
     }
@@ -136,6 +143,7 @@
      * Returns true if the two displays have the same identity (address, name and alias).
      * This method does not compare the current status of the displays.
      */
+    @UnsupportedAppUsage
     public boolean equals(WifiDisplay other) {
         return other != null
                 && mDeviceAddress.equals(other.mDeviceAddress)
diff --git a/core/java/android/hardware/display/WifiDisplayStatus.java b/core/java/android/hardware/display/WifiDisplayStatus.java
index b645662..c267834 100644
--- a/core/java/android/hardware/display/WifiDisplayStatus.java
+++ b/core/java/android/hardware/display/WifiDisplayStatus.java
@@ -16,6 +16,7 @@
 
 package android.hardware.display;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -34,7 +35,9 @@
     private final int mFeatureState;
     private final int mScanState;
     private final int mActiveDisplayState;
+    @UnsupportedAppUsage
     private final WifiDisplay mActiveDisplay;
+    @UnsupportedAppUsage
     private final WifiDisplay[] mDisplays;
 
     /** Session info needed for Miracast Certification */
@@ -47,18 +50,23 @@
     /** Feature state: Wifi display is turned off in settings. */
     public static final int FEATURE_STATE_OFF = 2;
     /** Feature state: Wifi display is turned on in settings. */
+    @UnsupportedAppUsage
     public static final int FEATURE_STATE_ON = 3;
 
     /** Scan state: Not currently scanning. */
+    @UnsupportedAppUsage
     public static final int SCAN_STATE_NOT_SCANNING = 0;
     /** Scan state: Currently scanning. */
     public static final int SCAN_STATE_SCANNING = 1;
 
     /** Display state: Not connected. */
+    @UnsupportedAppUsage
     public static final int DISPLAY_STATE_NOT_CONNECTED = 0;
     /** Display state: Connecting to active display. */
+    @UnsupportedAppUsage
     public static final int DISPLAY_STATE_CONNECTING = 1;
     /** Display state: Connected to active display. */
+    @UnsupportedAppUsage
     public static final int DISPLAY_STATE_CONNECTED = 2;
 
     public static final Creator<WifiDisplayStatus> CREATOR = new Creator<WifiDisplayStatus>() {
@@ -117,6 +125,7 @@
      * connecting to displays have been met.
      * </p>
      */
+    @UnsupportedAppUsage
     public int getFeatureState() {
         return mFeatureState;
     }
@@ -126,6 +135,7 @@
      *
      * @return One of: {@link #SCAN_STATE_NOT_SCANNING} or {@link #SCAN_STATE_SCANNING}.
      */
+    @UnsupportedAppUsage
     public int getScanState() {
         return mScanState;
     }
@@ -136,6 +146,7 @@
      * @return One of: {@link #DISPLAY_STATE_NOT_CONNECTED}, {@link #DISPLAY_STATE_CONNECTING},
      * or {@link #DISPLAY_STATE_CONNECTED}.
      */
+    @UnsupportedAppUsage
     public int getActiveDisplayState() {
         return mActiveDisplayState;
     }
@@ -144,6 +155,7 @@
      * Gets the Wifi display that is currently active.  It may be connecting or
      * connected.
      */
+    @UnsupportedAppUsage
     public WifiDisplay getActiveDisplay() {
         return mActiveDisplay;
     }
@@ -153,6 +165,7 @@
      * Wifi displays as reported by the most recent scan, and all remembered
      * Wifi displays (not necessarily available at the time).
      */
+    @UnsupportedAppUsage
     public WifiDisplay[] getDisplays() {
         return mDisplays;
     }
diff --git a/core/java/android/hardware/face/Face.java b/core/java/android/hardware/face/Face.java
index 6a508ac..d6724d7 100644
--- a/core/java/android/hardware/face/Face.java
+++ b/core/java/android/hardware/face/Face.java
@@ -26,47 +26,13 @@
  * @hide
  */
 public final class Face extends BiometricAuthenticator.Identifier {
-    private CharSequence mName;
-    private int mFaceId;
-    private long mDeviceId; // physical device this face is associated with
 
     public Face(CharSequence name, int faceId, long deviceId) {
-        mName = name;
-        mFaceId = faceId;
-        mDeviceId = deviceId;
+        super(name, faceId, deviceId);
     }
 
     private Face(Parcel in) {
-        mName = in.readString();
-        mFaceId = in.readInt();
-        mDeviceId = in.readLong();
-    }
-
-    /**
-     * Gets the human-readable name for the given fingerprint.
-     * @return name given to finger
-     */
-    public CharSequence getName() {
-        return mName;
-    }
-
-    /**
-     * Gets the device-specific finger id.  Used by Settings to map a name to a specific
-     * fingerprint template.
-     * @return device-specific id for this finger
-     * @hide
-     */
-    public int getFaceId() {
-        return mFaceId;
-    }
-
-    /**
-     * Device this face belongs to.
-     *
-     * @hide
-     */
-    public long getDeviceId() {
-        return mDeviceId;
+        super(in.readString(), in.readInt(), in.readLong());
     }
 
     /**
@@ -83,9 +49,9 @@
      * @param flags Additional flags about how the object should be written.
      */
     public void writeToParcel(Parcel out, int flags) {
-        out.writeString(mName.toString());
-        out.writeInt(mFaceId);
-        out.writeLong(mDeviceId);
+        out.writeString(getName().toString());
+        out.writeInt(getBiometricId());
+        out.writeLong(getDeviceId());
     }
 
     public static final Parcelable.Creator<Face> CREATOR = new Parcelable.Creator<Face>() {
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 3ed6228..6a3dd7d 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -418,7 +418,7 @@
             try {
                 mRemovalCallback = callback;
                 mRemovalFace = face;
-                mService.remove(mToken, face.getFaceId(), userId, mServiceReceiver);
+                mService.remove(mToken, face.getBiometricId(), userId, mServiceReceiver);
             } catch (RemoteException e) {
                 Log.w(TAG, "Remote exception in remove: ", e);
                 if (callback != null) {
@@ -796,6 +796,18 @@
          */
         public void onAuthenticationAcquired(int acquireInfo) {
         }
+
+        /**
+         * @hide
+         * @param result
+         */
+        @Override
+        public void onAuthenticationSucceeded(BiometricAuthenticator.AuthenticationResult result) {
+            onAuthenticationSucceeded(new AuthenticationResult(
+                    result.getCryptoObject(),
+                    (Face) result.getId(), result.getUserId()));
+        }
+
     }
 
     /**
@@ -836,10 +848,8 @@
          * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
          *
          * @param remaining The number of remaining steps
-         * @param vendorMsg Vendor feedback about the current enroll attempt. Use it to customize
-         *                  the GUI according to vendor's requirements.
          */
-        public void onEnrollmentProgress(int remaining, long vendorMsg) {
+        public void onEnrollmentProgress(int remaining) {
         }
     }
 
@@ -869,7 +879,7 @@
          *
          * @param face The face template that was removed.
          */
-        public void onRemovalSucceeded(Face face) {
+        public void onRemovalSucceeded(Face face, int remaining) {
         }
     }
 
@@ -920,7 +930,7 @@
         public void handleMessage(android.os.Message msg) {
             switch (msg.what) {
                 case MSG_ENROLL_RESULT:
-                    sendEnrollResult((EnrollResultMsg) msg.obj);
+                    sendEnrollResult((Face) msg.obj, msg.arg1 /* remaining */);
                     break;
                 case MSG_ACQUIRED:
                     sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */,
@@ -937,13 +947,13 @@
                             msg.arg2 /* vendorCode */);
                     break;
                 case MSG_REMOVED:
-                    sendRemovedResult((Face) msg.obj);
+                    sendRemovedResult((Face) msg.obj, msg.arg1 /* remaining */);
                     break;
             }
         }
     };
 
-    private void sendRemovedResult(Face face) {
+    private void sendRemovedResult(Face face, int remaining) {
         if (mRemovalCallback == null) {
             return;
         }
@@ -951,9 +961,7 @@
             Log.e(TAG, "Received MSG_REMOVED, but face is null");
             return;
         }
-
-
-        mRemovalCallback.onRemovalSucceeded(face);
+        mRemovalCallback.onRemovalSucceeded(face, remaining);
     }
 
     private void sendErrorResult(long deviceId, int errMsgId, int vendorCode) {
@@ -972,11 +980,9 @@
         }
     }
 
-    private void sendEnrollResult(EnrollResultMsg faceWrapper) {
+    private void sendEnrollResult(Face face, int remaining) {
         if (mEnrollmentCallback != null) {
-            int remaining = faceWrapper.getRemaining();
-            long vendorMsg = faceWrapper.getVendorMsg();
-            mEnrollmentCallback.onEnrollmentProgress(remaining, vendorMsg);
+            mEnrollmentCallback.onEnrollmentProgress(remaining);
         }
     }
 
@@ -1010,28 +1016,4 @@
             mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg);
         }
     }
-
-    private class EnrollResultMsg {
-        private final Face mFace;
-        private final int mRemaining;
-        private final long mVendorMsg;
-
-        EnrollResultMsg(Face face, int remaining, long vendorMsg) {
-            mFace = face;
-            mRemaining = remaining;
-            mVendorMsg = vendorMsg;
-        }
-
-        Face getFace() {
-            return mFace;
-        }
-
-        long getVendorMsg() {
-            return mVendorMsg;
-        }
-
-        int getRemaining() {
-            return mRemaining;
-        }
-    }
 }
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 9192652..15868f1 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -27,6 +27,7 @@
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -189,6 +190,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public Fingerprint getFingerprint() { return mFingerprint; }
 
         /**
@@ -718,6 +720,7 @@
      * @hide
      */
     @RequiresPermission(USE_FINGERPRINT)
+    @UnsupportedAppUsage
     public List<Fingerprint> getEnrolledFingerprints(int userId) {
         if (mService != null) try {
             return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
@@ -734,6 +737,7 @@
      * @hide
      */
     @RequiresPermission(USE_FINGERPRINT)
+    @UnsupportedAppUsage
     public List<Fingerprint> getEnrolledFingerprints() {
         return getEnrolledFingerprints(mContext.getUserId());
     }
@@ -801,6 +805,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long getAuthenticatorId() {
         if (mService != null) {
             try {
@@ -1157,24 +1162,9 @@
         @Override // binder call
         public void onError(long deviceId, int error, int vendorCode) {
             if (mExecutor != null) {
-                // BiometricPrompt case
-                if (error == FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED
-                        || error == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
-                    // User tapped somewhere to cancel, or authentication was cancelled by the app
-                    // or got kicked out. The prompt is already gone, so send the error immediately.
-                    mExecutor.execute(() -> {
-                        sendErrorResult(deviceId, error, vendorCode);
-                    });
-                } else {
-                    // User got an error that needs to be displayed on the dialog, post a delayed
-                    // runnable on the FingerprintManager handler that sends the error message after
-                    // FingerprintDialog.HIDE_DIALOG_DELAY to send the error to the application.
-                    mHandler.postDelayed(() -> {
-                        mExecutor.execute(() -> {
-                            sendErrorResult(deviceId, error, vendorCode);
-                        });
-                    }, BiometricPrompt.HIDE_DIALOG_DELAY);
-                }
+                mExecutor.execute(() -> {
+                    sendErrorResult(deviceId, error, vendorCode);
+                });
             } else {
                 mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();
             }
diff --git a/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java b/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java
new file mode 100644
index 0000000..9bebbd2
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.hdmi;
+
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.RemoteException;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+
+/**
+ * HdmiAudioSystemClient represents HDMI-CEC logical device of type Audio System in the Android
+ * system which acts as an audio system device such as sound bar.
+ *
+ * <p>HdmiAudioSystemClient provides methods that control, get information from TV/Display device
+ * connected through HDMI bus.
+ *
+ * @hide
+ */
+public final class HdmiAudioSystemClient extends HdmiClient {
+    private static final String TAG = "HdmiAudioSystemClient";
+
+    private static final int REPORT_AUDIO_STATUS_INTERVAL_MS = 500;
+
+    private final Handler mHandler;
+    private boolean mCanSendAudioStatus = true;
+    private boolean mPendingReportAudioStatus;
+
+    private int mLastVolume;
+    private int mLastMaxVolume;
+    private boolean mLastIsMute;
+
+    @VisibleForTesting(visibility = Visibility.PACKAGE)
+    public HdmiAudioSystemClient(IHdmiControlService service) {
+        this(service, null);
+    }
+
+    @VisibleForTesting(visibility = Visibility.PACKAGE)
+    public HdmiAudioSystemClient(IHdmiControlService service, @Nullable Handler handler) {
+        super(service);
+        mHandler = handler == null ? new Handler() : handler;
+    }
+
+    /** @hide */
+    // TODO(b/110094868): unhide and add @SystemApi for Q
+    @Override
+    public int getDeviceType() {
+        return HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM;
+    }
+
+    /**
+     * Sends a Report Audio Status HDMI CEC command to TV devices when necessary.
+     *
+     * According to HDMI CEC specification, an audio system can report its audio status when System
+     * Audio Mode is on, so that the TV can display the audio status of external amplifier.
+     *
+     * @hide
+     */
+    public void sendReportAudioStatusCecCommand(boolean isMuteAdjust, int volume, int maxVolume,
+            boolean isMute) {
+        if (isMuteAdjust) {
+            // always report audio status when it's muted/unmuted
+            try {
+                mService.reportAudioStatus(getDeviceType(), volume, maxVolume, isMute);
+            } catch (RemoteException e) {
+                // do nothing. Reporting audio status is optional.
+            }
+            return;
+        }
+
+        mLastVolume = volume;
+        mLastMaxVolume = maxVolume;
+        mLastIsMute = isMute;
+        if (mCanSendAudioStatus) {
+            try {
+                mService.reportAudioStatus(getDeviceType(), volume, maxVolume, isMute);
+                mCanSendAudioStatus = false;
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (mPendingReportAudioStatus) {
+                            // report audio status if there is any pending message
+                            try {
+                                mService.reportAudioStatus(getDeviceType(), mLastVolume,
+                                        mLastMaxVolume, mLastIsMute);
+                                mHandler.postDelayed(this, REPORT_AUDIO_STATUS_INTERVAL_MS);
+                            }  catch (RemoteException e) {
+                                mCanSendAudioStatus = true;
+                            } finally {
+                                mPendingReportAudioStatus = false;
+                            }
+                        } else {
+                            mCanSendAudioStatus = true;
+                        }
+                    }
+                }, REPORT_AUDIO_STATUS_INTERVAL_MS);
+            } catch (RemoteException e) {
+                // do nothing. Reporting audio status is optional.
+            }
+        } else {
+            // if audio status cannot be sent, send it latter
+            mPendingReportAudioStatus = true;
+        }
+    }
+}
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index e34423c..72a6ffe 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -22,10 +22,10 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.pm.PackageManager;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -262,6 +262,8 @@
     private final boolean mHasPlaybackDevice;
     // True if we have a logical device of type TV hosted in the system.
     private final boolean mHasTvDevice;
+    // True if we have a logical device of type audio system hosted in the system.
+    private final boolean mHasAudioSystemDevice;
 
     /**
      * {@hide} - hide this constructor because it has a parameter of type IHdmiControlService,
@@ -280,6 +282,7 @@
         }
         mHasTvDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_TV);
         mHasPlaybackDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PLAYBACK);
+        mHasAudioSystemDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
     }
 
     private static boolean hasDeviceType(int[] types, int type) {
@@ -301,6 +304,7 @@
      * @return {@link HdmiClient} instance. {@code null} on failure.
      * See {@link HdmiDeviceInfo#DEVICE_PLAYBACK}
      * See {@link HdmiDeviceInfo#DEVICE_TV}
+     * See {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM}
      */
     @Nullable
     @SuppressLint("Doclava125")
@@ -313,6 +317,8 @@
                 return mHasTvDevice ? new HdmiTvClient(mService) : null;
             case HdmiDeviceInfo.DEVICE_PLAYBACK:
                 return mHasPlaybackDevice ? new HdmiPlaybackClient(mService) : null;
+            case HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM:
+                return mHasAudioSystemDevice ? new HdmiAudioSystemClient(mService) : null;
             default:
                 return null;
         }
@@ -349,6 +355,24 @@
     }
 
     /**
+     * Gets an object that represents an HDMI-CEC logical device of type audio system on the system.
+     *
+     * <p>Used to send HDMI control messages to other devices like TV through HDMI bus. It is also
+     * possible to communicate with other logical devices hosted in the same system if the system is
+     * configured to host more than one type of HDMI-CEC logical devices.
+     *
+     * @return {@link HdmiAudioSystemClient} instance. {@code null} on failure.
+     *
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    @Nullable
+    @SuppressLint("Doclava125")
+    public HdmiAudioSystemClient getAudioSystemClient() {
+        return (HdmiAudioSystemClient) getClient(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+    }
+
+    /**
      * Controls standby mode of the system. It will also try to turn on/off the connected devices if
      * necessary.
      *
diff --git a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
index 874b0c6..df231e6 100644
--- a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
+++ b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
@@ -23,7 +23,8 @@
 /**
  * HdmiPlaybackClient represents HDMI-CEC logical device of type Playback
  * in the Android system which acts as a playback device such as set-top box.
- * It provides with methods that control, get information from TV/Display device
+ *
+ * <p>HdmiPlaybackClient provides methods that control, get information from TV/Display device
  * connected through HDMI bus.
  *
  * @hide
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index a336e5c..f33a137 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -29,8 +29,9 @@
 
 /**
  * HdmiTvClient represents HDMI-CEC logical device of type TV in the Android system
- * which acts as TV/Display. It provides with methods that manage, interact with other
- * devices on the CEC bus.
+ * which acts as TV/Display.
+ *
+ * <p>HdmiTvClient provides methods that manage, interact with other devices on the CEC bus.
  *
  * @hide
  */
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 67e2d18..2b8d00b 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -72,4 +72,5 @@
     void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data);
     void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener);
     void setStandbyMode(boolean isStandbyModeOn);
+    void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute);
 }
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 6ae7a14..6ca5f0c 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -20,6 +20,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.IInputForwarder;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -64,6 +65,7 @@
 
     private static InputManager sInstance;
 
+    @UnsupportedAppUsage
     private final IInputManager mIm;
 
     // Guarded by mInputDevicesLock
@@ -181,6 +183,7 @@
      * Waits for the event to be delivered to the application and handled.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;  // see InputDispatcher.h
 
     /** @hide */
@@ -223,6 +226,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static InputManager getInstance() {
         synchronized (InputManager.class) {
             if (sInstance == null) {
@@ -866,6 +870,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean injectInputEvent(InputEvent event, int mode) {
         if (event == null) {
             throw new IllegalArgumentException("event must not be null");
@@ -891,6 +896,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPointerIconType(int iconId) {
         try {
             mIm.setPointerIconType(iconId);
@@ -938,6 +944,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public IInputForwarder createInputForwarder(int displayId) {
         try {
             return mIm.createInputForwarder(displayId);
@@ -1191,8 +1198,8 @@
          * @hide
          */
         @Override
-        public void vibrate(int uid, String opPkg,
-                VibrationEffect effect, AudioAttributes attributes) {
+        public void vibrate(int uid, String opPkg, VibrationEffect effect,
+                String reason, AudioAttributes attributes) {
             long[] pattern;
             int repeat;
             if (effect instanceof VibrationEffect.OneShot) {
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 0a21083..2335203 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -102,7 +102,7 @@
     /**
      * Sends a message to a nanoapp through the Context Hub Service.
      *
-     * This function returns TRANSACTION_SUCCESS if the message has reached the HAL, but
+     * This function returns RESULT_SUCCESS if the message has reached the HAL, but
      * does not guarantee delivery of the message to the target nanoapp.
      *
      * @param message the message object to send
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index de13c81..12d0531 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -549,7 +549,7 @@
      * Set a callback to receive messages from the context hub
      *
      * @param callback Callback object
-     * @param handler Handler object
+     * @param handler Handler object, if null uses the Handler of the main Looper
      *
      * @see Callback
      *
@@ -568,7 +568,7 @@
                 return -1;
             }
             mCallback = callback;
-            mCallbackHandler = handler;
+            mCallbackHandler = (handler == null) ? new Handler(mMainLooper) : handler;
         }
         return 0;
     }
@@ -722,26 +722,31 @@
         return 0;
     }
 
+    /**
+     * Invokes the ContextHubManager.Callback callback registered with the ContextHubManager.
+     *
+     * @param hubId The ID of the Context Hub the message came from
+     * @param nanoAppId The instance ID of the nanoapp the message came from
+     * @param message The message to provide the callback
+     */
+    private synchronized void invokeOnMessageReceiptCallback(
+            int hubId, int nanoAppId, ContextHubMessage message) {
+        if (mCallback != null) {
+            mCallback.onMessageReceipt(hubId, nanoAppId, message);
+        }
+    }
+
     private final IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
         @Override
-        public void onMessageReceipt(final int hubId, final int nanoAppId,
-                final ContextHubMessage message) {
-            if (mCallback != null) {
-                synchronized(this) {
-                    final Callback callback = mCallback;
-                    Handler handler = mCallbackHandler == null ?
-                            new Handler(mMainLooper) : mCallbackHandler;
-                    handler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            callback.onMessageReceipt(hubId, nanoAppId, message);
-                        }
-                    });
-                }
-            } else if (mLocalCallback != null) {
-                // we always ensure that mCallback takes precedence, because mLocalCallback is only
-                // for internal compatibility
-                synchronized (this) {
+        public void onMessageReceipt(
+                final int hubId, final int nanoAppId, final ContextHubMessage message) {
+            synchronized (ContextHubManager.this) {
+                if (mCallback != null) {
+                    mCallbackHandler.post(
+                            () -> invokeOnMessageReceiptCallback(hubId, nanoAppId, message));
+                } else if (mLocalCallback != null) {
+                    // We always ensure that mCallback takes precedence, because mLocalCallback is
+                    // only for internal compatibility
                     mLocalCallback.onMessageReceipt(hubId, nanoAppId, message);
                 }
             }
diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java
index 66dd9fc..23d8d01 100644
--- a/core/java/android/hardware/location/GeofenceHardware.java
+++ b/core/java/android/hardware/location/GeofenceHardware.java
@@ -16,6 +16,7 @@
 package android.hardware.location;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.location.Location;
 import android.os.Build;
 import android.os.RemoteException;
@@ -168,6 +169,7 @@
                     GeofenceHardwareMonitorCallbackWrapper>();
 
     /** @hide */
+    @UnsupportedAppUsage
     public GeofenceHardware(IGeofenceHardware service) {
         mService = service;
     }
diff --git a/core/java/android/hardware/location/NanoAppFilter.java b/core/java/android/hardware/location/NanoAppFilter.java
index 4d8e734..562065e 100644
--- a/core/java/android/hardware/location/NanoAppFilter.java
+++ b/core/java/android/hardware/location/NanoAppFilter.java
@@ -85,7 +85,7 @@
         mAppId = in.readLong();
         mAppVersion = in.readInt();
         mVersionRestrictionMask = in.readInt();
-        mAppIdVendorMask = in.readInt();
+        mAppIdVendorMask = in.readLong();
     }
 
     public int describeContents() {
@@ -93,7 +93,6 @@
     }
 
     public void writeToParcel(Parcel out, int flags) {
-
         out.writeLong(mAppId);
         out.writeInt(mAppVersion);
         out.writeInt(mVersionRestrictionMask);
diff --git a/core/java/android/hardware/radio/RadioManager.aidl b/core/java/android/hardware/radio/RadioManager.aidl
index 8a39388..34c05d8 100644
--- a/core/java/android/hardware/radio/RadioManager.aidl
+++ b/core/java/android/hardware/radio/RadioManager.aidl
@@ -20,6 +20,9 @@
 parcelable RadioManager.BandConfig;
 
 /** @hide */
+parcelable RadioManager.BandDescriptor;
+
+/** @hide */
 parcelable RadioManager.ModuleProperties;
 
 /** @hide */
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index dde8a33..007f4bc 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -24,6 +24,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.media.AudioFormat;
 import android.os.Handler;
 import android.os.Parcel;
@@ -72,6 +73,7 @@
      ****************************************************************************/
     public static class ModuleProperties implements Parcelable {
         /** Unique module ID provided by the native service */
+        @UnsupportedAppUsage
         public final int id;
 
         /** human readable voice detection engine implementor */
@@ -81,12 +83,14 @@
         public final String description;
 
         /** Unique voice engine Id (changes with each version) */
+        @UnsupportedAppUsage
         public final UUID uuid;
 
         /** Voice detection engine version */
         public final int version;
 
         /** Maximum number of active sound models */
+        @UnsupportedAppUsage
         public final int maxSoundModels;
 
         /** Maximum number of key phrases */
@@ -114,6 +118,7 @@
          * recognition callback event */
         public final boolean returnsTriggerInEvent;
 
+        @UnsupportedAppUsage
         ModuleProperties(int id, String implementor, String description,
                 String uuid, int version, int maxSoundModels, int maxKeyphrases,
                 int maxUsers, int recognitionModes, boolean supportsCaptureTransition,
@@ -225,15 +230,18 @@
         public static final int TYPE_GENERIC_SOUND = 1;
 
         /** Unique sound model identifier */
+        @UnsupportedAppUsage
         public final UUID uuid;
 
         /** Sound model type (e.g. TYPE_KEYPHRASE); */
         public final int type;
 
         /** Unique sound model vendor identifier */
+        @UnsupportedAppUsage
         public final UUID vendorUuid;
 
         /** Opaque data. For use by vendor implementation and enrollment application */
+        @UnsupportedAppUsage
         public final byte[] data;
 
         public SoundModel(UUID uuid, UUID vendorUuid, int type, byte[] data) {
@@ -289,21 +297,27 @@
      ****************************************************************************/
     public static class Keyphrase implements Parcelable {
         /** Unique identifier for this keyphrase */
+        @UnsupportedAppUsage
         public final int id;
 
         /** Recognition modes supported for this key phrase in the model */
+        @UnsupportedAppUsage
         public final int recognitionModes;
 
         /** Locale of the keyphrase. JAVA Locale string e.g en_US */
+        @UnsupportedAppUsage
         public final String locale;
 
         /** Key phrase text */
+        @UnsupportedAppUsage
         public final String text;
 
         /** Users this key phrase has been trained for. countains sound trigger specific user IDs
          * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}. */
+        @UnsupportedAppUsage
         public final int[] users;
 
+        @UnsupportedAppUsage
         public Keyphrase(int id, int recognitionModes, String locale, String text, int[] users) {
             this.id = id;
             this.recognitionModes = recognitionModes;
@@ -412,8 +426,10 @@
      ****************************************************************************/
     public static class KeyphraseSoundModel extends SoundModel implements Parcelable {
         /** Key phrases in this sound model */
+        @UnsupportedAppUsage
         public final Keyphrase[] keyphrases; // keyword phrases in model
 
+        @UnsupportedAppUsage
         public KeyphraseSoundModel(
                 UUID uuid, UUID vendorUuid, byte[] data, Keyphrase[] keyphrases) {
             super(uuid, vendorUuid, TYPE_KEYPHRASE, data);
@@ -511,6 +527,7 @@
             }
         };
 
+        @UnsupportedAppUsage
         public GenericSoundModel(UUID uuid, UUID vendorUuid, byte[] data) {
             super(uuid, vendorUuid, TYPE_GENERIC_SOUND, data);
         }
@@ -606,6 +623,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public final int status;
         /**
          *
@@ -613,12 +631,14 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public final int soundModelHandle;
         /**
          * True if it is possible to capture audio from this utterance buffered by the hardware
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public final boolean captureAvailable;
         /**
          * Audio session ID to be used when capturing the utterance with an AudioRecord
@@ -626,6 +646,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public final int captureSession;
         /**
          * Delay in ms between end of model detection and start of audio available for capture.
@@ -659,9 +680,11 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public final byte[] data;
 
         /** @hide */
+        @UnsupportedAppUsage
         public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
                 int captureSession, int captureDelayMs, int capturePreambleMs,
                 boolean triggerInData, AudioFormat captureFormat, byte[] data) {
@@ -865,6 +888,7 @@
     public static class RecognitionConfig implements Parcelable {
         /** True if the DSP should capture the trigger sound and make it available for further
          * capture. */
+        @UnsupportedAppUsage
         public final boolean captureRequested;
         /**
          * True if the service should restart listening after the DSP triggers.
@@ -873,11 +897,14 @@
         public final boolean allowMultipleTriggers;
         /** List of all keyphrases in the sound model for which recognition should be performed with
          * options for each keyphrase. */
+        @UnsupportedAppUsage
         public final KeyphraseRecognitionExtra keyphrases[];
         /** Opaque data for use by system applications who know about voice engine internals,
          * typically during enrollment. */
+        @UnsupportedAppUsage
         public final byte[] data;
 
+        @UnsupportedAppUsage
         public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
                 KeyphraseRecognitionExtra[] keyphrases, byte[] data) {
             this.captureRequested = captureRequested;
@@ -938,9 +965,12 @@
      * @hide
      */
     public static class ConfidenceLevel implements Parcelable {
+        @UnsupportedAppUsage
         public final int userId;
+        @UnsupportedAppUsage
         public final int confidenceLevel;
 
+        @UnsupportedAppUsage
         public ConfidenceLevel(int userId, int confidenceLevel) {
             this.userId = userId;
             this.confidenceLevel = confidenceLevel;
@@ -1014,19 +1044,24 @@
      */
     public static class KeyphraseRecognitionExtra implements Parcelable {
         /** The keyphrase ID */
+        @UnsupportedAppUsage
         public final int id;
 
         /** Recognition modes matched for this event */
+        @UnsupportedAppUsage
         public final int recognitionModes;
 
         /** Confidence level for mode RECOGNITION_MODE_VOICE_TRIGGER when user identification
          * is not performed */
+        @UnsupportedAppUsage
         public final int coarseConfidenceLevel;
 
         /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
          * be recognized (RecognitionConfig) */
+        @UnsupportedAppUsage
         public final ConfidenceLevel[] confidenceLevels;
 
+        @UnsupportedAppUsage
         public KeyphraseRecognitionExtra(int id, int recognitionModes, int coarseConfidenceLevel,
                 ConfidenceLevel[] confidenceLevels) {
             this.id = id;
@@ -1114,8 +1149,10 @@
      */
     public static class KeyphraseRecognitionEvent extends RecognitionEvent implements Parcelable {
         /** Indicates if the key phrase is present in the buffered audio available for capture */
+        @UnsupportedAppUsage
         public final KeyphraseRecognitionExtra[] keyphraseExtras;
 
+        @UnsupportedAppUsage
         public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
                int captureSession, int captureDelayMs, int capturePreambleMs,
                boolean triggerInData, AudioFormat captureFormat, byte[] data,
@@ -1236,6 +1273,7 @@
      * @hide
      */
     public static class GenericRecognitionEvent extends RecognitionEvent implements Parcelable {
+        @UnsupportedAppUsage
         public GenericRecognitionEvent(int status, int soundModelHandle,
                 boolean captureAvailable, int captureSession, int captureDelayMs,
                 int capturePreambleMs, boolean triggerInData, AudioFormat captureFormat,
@@ -1305,6 +1343,7 @@
         /** New sound model data */
         public final byte[] data;
 
+        @UnsupportedAppUsage
         SoundModelEvent(int status, int soundModelHandle, byte[] data) {
             this.status = status;
             this.soundModelHandle = soundModelHandle;
@@ -1405,6 +1444,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static native int listModules(ArrayList <ModuleProperties> modules);
 
     /**
@@ -1418,6 +1458,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static SoundTriggerModule attachModule(int moduleId,
                                                   StatusListener listener,
                                                   Handler handler) {
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index e23a2bb..838765b 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -16,6 +16,7 @@
 
 package android.hardware.soundtrigger;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -28,8 +29,10 @@
  * @hide
  */
 public class SoundTriggerModule {
+    @UnsupportedAppUsage
     private long mNativeContext;
 
+    @UnsupportedAppUsage
     private int mId;
     private NativeEventHandlerDelegate mEventHandlerDelegate;
 
@@ -56,6 +59,7 @@
      * Detach from this module. The {@link SoundTrigger.StatusListener} callback will not be called
      * anymore and associated resources will be released.
      * */
+    @UnsupportedAppUsage
     public native void detach();
 
     /**
@@ -73,6 +77,7 @@
      *         service fails
      *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
      */
+    @UnsupportedAppUsage
     public native int loadSoundModel(SoundTrigger.SoundModel model, int[] soundModelHandle);
 
     /**
@@ -87,6 +92,7 @@
      *         - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
      *         service fails
      */
+    @UnsupportedAppUsage
     public native int unloadSoundModel(int soundModelHandle);
 
     /**
@@ -106,6 +112,7 @@
      *         service fails
      *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
      */
+    @UnsupportedAppUsage
     public native int startRecognition(int soundModelHandle, SoundTrigger.RecognitionConfig config);
 
     /**
@@ -121,6 +128,7 @@
      *         service fails
      *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
      */
+    @UnsupportedAppUsage
     public native int stopRecognition(int soundModelHandle);
 
     private class NativeEventHandlerDelegate {
@@ -181,6 +189,7 @@
     }
 
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private static void postEventFromNative(Object module_ref,
                                             int what, int arg1, int arg2, Object obj) {
         SoundTriggerModule module = (SoundTriggerModule)((WeakReference)module_ref).get();
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index 1e98301..26c5a95 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import com.android.internal.util.Preconditions;
@@ -60,6 +61,7 @@
     private @Nullable Parcelable[] mConfigurations;
 
     /** All interfaces on the device. Initialized on first call to getInterfaceList */
+    @UnsupportedAppUsage
     private @Nullable UsbInterface[] mInterfaces;
 
     /**
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 9e5174a..71297c1 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Build;
 import android.os.ParcelFileDescriptor;
@@ -46,6 +47,7 @@
     private Context mContext;
 
     // used by the JNI code
+    @UnsupportedAppUsage
     private long mNativeContext;
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 46142e3..3141be4 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -87,6 +88,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final String ACTION_USB_STATE =
             "android.hardware.usb.action.USB_STATE";
 
@@ -163,6 +165,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final String USB_CONNECTED = "connected";
 
     /**
@@ -189,6 +192,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final String USB_DATA_UNLOCKED = "unlocked";
 
     /**
@@ -197,6 +201,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final String USB_FUNCTION_NONE = "none";
 
     /**
@@ -363,6 +368,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public UsbManager(Context context, IUsbManager service) {
         mContext = context;
         mService = service;
@@ -645,6 +651,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public boolean isFunctionEnabled(String function) {
         try {
             return mService.isFunctionEnabled(function);
@@ -693,6 +700,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setCurrentFunction(String functions, boolean usbDataUnlocked) {
         try {
             mService.setCurrentFunction(functions, usbDataUnlocked);
@@ -774,6 +782,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public UsbPort[] getPorts() {
         if (mService == null) {
             return null;
@@ -793,6 +802,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public UsbPortStatus getPortStatus(UsbPort port) {
         Preconditions.checkNotNull(port, "port must not be null");
 
@@ -822,6 +832,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPortRoles(UsbPort port, int powerRole, int dataRole) {
         Preconditions.checkNotNull(port, "port must not be null");
         UsbPort.checkRoles(powerRole, dataRole);
diff --git a/core/java/android/hardware/usb/UsbPortStatus.java b/core/java/android/hardware/usb/UsbPortStatus.java
index 5c0e81a..2cd8209 100644
--- a/core/java/android/hardware/usb/UsbPortStatus.java
+++ b/core/java/android/hardware/usb/UsbPortStatus.java
@@ -16,6 +16,7 @@
 
 package android.hardware.usb;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -47,6 +48,7 @@
      *
      * @return True if there is anything connected to the port.
      */
+    @UnsupportedAppUsage
     public boolean isConnected() {
         return mCurrentMode != 0;
     }
@@ -57,6 +59,7 @@
      * @return The current mode: {@link UsbPort#MODE_DFP}, {@link UsbPort#MODE_UFP},
      * or 0 if nothing is connected.
      */
+    @UnsupportedAppUsage
     public int getCurrentMode() {
         return mCurrentMode;
     }
@@ -67,6 +70,7 @@
      * @return The current power role: {@link UsbPort#POWER_ROLE_SOURCE},
      * {@link UsbPort#POWER_ROLE_SINK}, or 0 if nothing is connected.
      */
+    @UnsupportedAppUsage
     public int getCurrentPowerRole() {
         return mCurrentPowerRole;
     }
@@ -77,6 +81,7 @@
      * @return The current data role: {@link UsbPort#DATA_ROLE_HOST},
      * {@link UsbPort#DATA_ROLE_DEVICE}, or 0 if nothing is connected.
      */
+    @UnsupportedAppUsage
     public int getCurrentDataRole() {
         return mCurrentDataRole;
     }
@@ -90,12 +95,14 @@
      * @param dataRole The data role to check: either {@link UsbPort#DATA_ROLE_HOST}
      * or {@link UsbPort#DATA_ROLE_DEVICE}, or 0 if no data role.
      */
+    @UnsupportedAppUsage
     public boolean isRoleCombinationSupported(int powerRole, int dataRole) {
         return (mSupportedRoleCombinations &
                 UsbPort.combineRolesAsBit(powerRole, dataRole)) != 0;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getSupportedRoleCombinations() {
         return mSupportedRoleCombinations;
     }
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index f59c87e..7abf3e9 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -17,6 +17,7 @@
 package android.hardware.usb;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.util.Log;
 
@@ -47,14 +48,17 @@
     static final int MAX_USBFS_BUFFER_SIZE = 16384;
 
     // used by the JNI code
+    @UnsupportedAppUsage
     private long mNativeContext;
 
     private UsbEndpoint mEndpoint;
 
     /** The buffer that is currently being read / written */
+    @UnsupportedAppUsage
     private ByteBuffer mBuffer;
 
     /** The amount of data to read / write when using {@link #queue} */
+    @UnsupportedAppUsage
     private int mLength;
 
     // for client use
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 431c651..46671b2 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -28,6 +28,7 @@
 import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.Dialog;
 import android.content.Context;
@@ -343,10 +344,12 @@
 
     InputMethodManager mImm;
     
+    @UnsupportedAppUsage
     int mTheme = 0;
     
     LayoutInflater mInflater;
     TypedArray mThemeAttrs;
+    @UnsupportedAppUsage
     View mRootView;
     SoftInputWindow mWindow;
     boolean mInitialized;
@@ -378,8 +381,10 @@
 
     boolean mFullscreenApplied;
     boolean mIsFullscreen;
+    @UnsupportedAppUsage
     View mExtractView;
     boolean mExtractViewHidden;
+    @UnsupportedAppUsage
     ExtractEditText mExtractEditText;
     ViewGroup mExtractAccessories;
     View mExtractAction;
@@ -402,6 +407,7 @@
      */
     boolean mShouldClearInsetOfPreviousIme;
 
+    @UnsupportedAppUsage
     final Insets mTmpInsets = new Insets();
     final int[] mTmpLocation = new int[2];
 
@@ -811,6 +817,7 @@
             mService.getContentResolver().unregisterContentObserver(this);
         }
 
+        @UnsupportedAppUsage
         private boolean shouldShowImeWithHardKeyboard() {
             // Lazily initialize as needed.
             if (mShowImeWithHardKeyboard == ShowImeWithHardKeyboardType.UNKNOWN) {
@@ -850,6 +857,7 @@
             return "SettingsObserver{mShowImeWithHardKeyboard=" + mShowImeWithHardKeyboard  + "}";
         }
     }
+    @UnsupportedAppUsage
     private SettingsObserver mSettingsObserver;
 
     /**
@@ -2492,6 +2500,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void onExtractedDeleteText(int start, int end) {
         InputConnection conn = getCurrentInputConnection();
         if (conn != null) {
@@ -2504,6 +2513,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void onExtractedReplaceText(int start, int end, CharSequence text) {
         InputConnection conn = getCurrentInputConnection();
         if (conn != null) {
@@ -2515,6 +2525,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void onExtractedSetSpan(Object span, int start, int end, int flags) {
         InputConnection conn = getCurrentInputConnection();
         if (conn != null) {
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index a5490ef..ec5f050 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -18,6 +18,7 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.XmlRes;
 import android.content.Context;
 import android.content.res.Resources;
@@ -110,18 +111,21 @@
     private int mKeyHeight;
     
     /** Total height of the keyboard, including the padding and keys */
+    @UnsupportedAppUsage
     private int mTotalHeight;
     
     /** 
      * Total width of the keyboard, including left side gaps and keys, but not any gaps on the
      * right side.
      */
+    @UnsupportedAppUsage
     private int mTotalWidth;
     
     /** List of keys in this keyboard */
     private List<Key> mKeys;
     
     /** List of modifier keys such as Shift & Alt, if any */
+    @UnsupportedAppUsage
     private List<Key> mModifierKeys;
     
     /** Width of the screen available to fit the keyboard */
@@ -623,6 +627,7 @@
         rows.add(row);
     }
 
+    @UnsupportedAppUsage
     final void resize(int newWidth, int newHeight) {
         int numRows = rows.size();
         for (int rowIndex = 0; rowIndex < numRows; ++rowIndex) {
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 16c1f6d..9ca8049 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -16,6 +16,7 @@
 
 package android.inputmethodservice;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -133,6 +134,7 @@
 
     private Keyboard mKeyboard;
     private int mCurrentKeyIndex = NOT_A_KEY;
+    @UnsupportedAppUsage
     private int mLabelTextSize;
     private int mKeyTextSize;
     private int mKeyTextColor;
@@ -140,6 +142,7 @@
     private int mShadowColor;
     private float mBackgroundDimAmount;
 
+    @UnsupportedAppUsage
     private TextView mPreviewText;
     private PopupWindow mPreviewPopup;
     private int mPreviewTextSizeLarge;
@@ -217,6 +220,7 @@
     private float mOldPointerX;
     private float mOldPointerY;
 
+    @UnsupportedAppUsage
     private Drawable mKeyBackground;
 
     private static final int REPEAT_INTERVAL = 50; // ~20 keys per second
@@ -910,6 +914,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void showKey(final int keyIndex) {
         final PopupWindow previewPopup = mPreviewPopup;
         final Key[] keys = mKeys;
@@ -1052,6 +1057,7 @@
                 key.x + key.width + mPaddingLeft, key.y + key.height + mPaddingTop);
     }
 
+    @UnsupportedAppUsage
     private boolean openPopupIfRequired(MotionEvent me) {
         // Check if we have a popup layout specified first.
         if (mPopupLayout == 0) {
@@ -1357,6 +1363,7 @@
         return true;
     }
 
+    @UnsupportedAppUsage
     private boolean repeatKey() {
         Key key = mKeys[mRepeatKeyIndex];
         detectAndSendKey(mCurrentKey, key.x, key.y, mLastTapTime);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 104134a..fb916d3 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -22,6 +22,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -311,6 +312,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String INET_CONDITION_ACTION =
             "android.net.conn.INET_CONDITION_ACTION";
 
@@ -325,6 +327,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_TETHER_STATE_CHANGED =
             "android.net.conn.TETHER_STATE_CHANGED";
 
@@ -333,6 +336,7 @@
      * gives a String[] listing all the interfaces configured for
      * tethering and currently available for tethering.
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
 
     /**
@@ -347,6 +351,7 @@
      * gives a String[] listing all the interfaces currently tethered
      * (ie, has DHCPv4 support and packets potentially forwarded/NATed)
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
 
     /**
@@ -355,6 +360,7 @@
      * failed.  Use {@link #getLastTetherError} to find the error code
      * for any interfaces listed here.
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_ERRORED_TETHER = "erroredArray";
 
     /**
@@ -459,6 +465,7 @@
      * The absence of a connection type.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int TYPE_NONE        = -1;
 
     /**
@@ -575,6 +582,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final int TYPE_MOBILE_FOTA = 10;
 
     /**
@@ -583,6 +591,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final int TYPE_MOBILE_IMS  = 11;
 
     /**
@@ -591,6 +600,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final int TYPE_MOBILE_CBS  = 12;
 
     /**
@@ -600,6 +610,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final int TYPE_WIFI_P2P    = 13;
 
     /**
@@ -608,6 +619,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final int TYPE_MOBILE_IA = 14;
 
     /**
@@ -617,6 +629,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final int TYPE_MOBILE_EMERGENCY = 15;
 
     /**
@@ -625,6 +638,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final int TYPE_PROXY = 16;
 
     /**
@@ -707,6 +721,7 @@
      */
     public static final String PRIVATE_DNS_DEFAULT_MODE_FALLBACK = PRIVATE_DNS_MODE_OPPORTUNISTIC;
 
+    @UnsupportedAppUsage
     private final IConnectivityManager mService;
     /**
      * A kludge to facilitate static access where a Context pointer isn't available, like in the
@@ -743,6 +758,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static String getNetworkTypeName(int type) {
         switch (type) {
           case TYPE_NONE:
@@ -797,6 +813,7 @@
      * {@hide}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static boolean isNetworkTypeMobile(int networkType) {
         switch (networkType) {
             case TYPE_MOBILE:
@@ -1010,6 +1027,7 @@
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
+    @UnsupportedAppUsage
     public NetworkInfo getActiveNetworkInfoForUid(int uid) {
         return getActiveNetworkInfoForUid(uid, false);
     }
@@ -1107,6 +1125,7 @@
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public Network getNetworkForType(int networkType) {
         try {
             return mService.getNetworkForType(networkType);
@@ -1135,6 +1154,7 @@
      * the Networks that applications run by the given user will use by default.
      * @hide
      */
+    @UnsupportedAppUsage
     public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
         try {
             return mService.getDefaultNetworkCapabilitiesForUser(userId);
@@ -1153,6 +1173,7 @@
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public LinkProperties getActiveLinkProperties() {
         try {
             return mService.getActiveLinkProperties();
@@ -1177,6 +1198,7 @@
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public LinkProperties getLinkProperties(int networkType) {
         try {
             return mService.getLinkPropertiesForType(networkType);
@@ -1332,6 +1354,7 @@
         return 1;
     }
 
+    @UnsupportedAppUsage
     private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) {
         if (networkType == TYPE_MOBILE) {
             switch (feature) {
@@ -1495,6 +1518,7 @@
         };
     }
 
+    @UnsupportedAppUsage
     private static final HashMap<NetworkCapabilities, LegacyRequest> sLegacyRequests =
             new HashMap<>();
 
@@ -1523,6 +1547,7 @@
         Log.d(TAG, "expireRequest with " + ourSeqNum + ", " + sequenceNum);
     }
 
+    @UnsupportedAppUsage
     private NetworkRequest requestNetworkForFeatureLocked(NetworkCapabilities netCap) {
         int delay = -1;
         int type = legacyTypeForNetworkCapabilities(netCap);
@@ -1552,6 +1577,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private boolean removeRequestForFeature(NetworkCapabilities netCap) {
         final LegacyRequest l;
         synchronized (sLegacyRequests) {
@@ -1619,10 +1645,13 @@
     /** @hide */
     public static class PacketKeepaliveCallback {
         /** The requested keepalive was successfully started. */
+        @UnsupportedAppUsage
         public void onStarted() {}
         /** The keepalive was successfully stopped. */
+        @UnsupportedAppUsage
         public void onStopped() {}
         /** An error occurred. */
+        @UnsupportedAppUsage
         public void onError(int error) {}
     }
 
@@ -1689,6 +1718,7 @@
             mLooper.quit();
         }
 
+        @UnsupportedAppUsage
         public void stop() {
             try {
                 mService.stopKeepalive(mNetwork, mSlot);
@@ -1744,6 +1774,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PacketKeepalive startNattKeepalive(
             Network network, int intervalSeconds, PacketKeepaliveCallback callback,
             InetAddress srcAddr, int srcPort, InetAddress dstAddr) {
@@ -1805,6 +1836,7 @@
      *             {@link #bindProcessToNetwork} API.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) {
         checkLegacyRoutingApiAccess();
         try {
@@ -1848,12 +1880,14 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setBackgroundDataSetting(boolean allowBackgroundData) {
         // ignored
     }
 
     /** {@hide} */
     @Deprecated
+    @UnsupportedAppUsage
     public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
         try {
             return mService.getActiveNetworkQuotaInfo();
@@ -1867,6 +1901,7 @@
      * @deprecated Talk to TelephonyManager directly
      */
     @Deprecated
+    @UnsupportedAppUsage
     public boolean getMobileDataEnabled() {
         IBinder b = ServiceManager.getService(Context.TELEPHONY_SERVICE);
         if (b != null) {
@@ -1986,6 +2021,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static ConnectivityManager from(Context context) {
         return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
     }
@@ -2036,6 +2072,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     private static ConnectivityManager getInstance() {
         if (getInstanceOrNull() == null) {
             throw new IllegalStateException("No ConnectivityManager yet constructed");
@@ -2052,6 +2089,7 @@
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public String[] getTetherableIfaces() {
         try {
             return mService.getTetherableIfaces();
@@ -2068,6 +2106,7 @@
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public String[] getTetheredIfaces() {
         try {
             return mService.getTetheredIfaces();
@@ -2090,6 +2129,7 @@
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public String[] getTetheringErroredIfaces() {
         try {
             return mService.getTetheringErroredIfaces();
@@ -2136,6 +2176,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int tether(String iface) {
         try {
             String pkgName = mContext.getOpPackageName();
@@ -2164,6 +2205,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int untether(String iface) {
         try {
             String pkgName = mContext.getOpPackageName();
@@ -2317,6 +2359,7 @@
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public String[] getTetherableUsbRegexs() {
         try {
             return mService.getTetherableUsbRegexs();
@@ -2336,6 +2379,7 @@
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public String[] getTetherableWifiRegexs() {
         try {
             return mService.getTetherableWifiRegexs();
@@ -2355,6 +2399,7 @@
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public String[] getTetherableBluetoothRegexs() {
         try {
             return mService.getTetherableBluetoothRegexs();
@@ -2380,6 +2425,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int setUsbTethering(boolean enable) {
         try {
             String pkgName = mContext.getOpPackageName();
@@ -2426,6 +2472,7 @@
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public int getLastTetherError(String iface) {
         try {
             return mService.getLastTetherError(iface);
@@ -2579,6 +2626,7 @@
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @UnsupportedAppUsage
     public boolean isNetworkSupported(int networkType) {
         try {
             return mService.isNetworkSupported(networkType);
@@ -2680,6 +2728,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
+    @UnsupportedAppUsage
     public void setAirplaneMode(boolean enable) {
         try {
             mService.setAirplaneMode(enable);
@@ -2689,6 +2738,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public void registerNetworkFactory(Messenger messenger, String name) {
         try {
             mService.registerNetworkFactory(messenger, name);
@@ -2698,6 +2748,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public void unregisterNetworkFactory(Messenger messenger) {
         try {
             mService.unregisterNetworkFactory(messenger);
@@ -3786,6 +3837,7 @@
      * @deprecated This is strictly for legacy usage to support {@link #startUsingNetworkFeature}.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static boolean setProcessDefaultNetworkForHostResolution(Network network) {
         return NetworkUtils.bindProcessToNetworkForHostResolution(
                 network == null ? NETID_UNSET : network.netId);
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 8c5f603..b5d8226 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.NetworkUtils;
 import android.os.Parcel;
 import android.text.TextUtils;
@@ -33,25 +34,32 @@
 public class DhcpResults extends StaticIpConfiguration {
     private static final String TAG = "DhcpResults";
 
+    @UnsupportedAppUsage
     public Inet4Address serverAddress;
 
     /** Vendor specific information (from RFC 2132). */
+    @UnsupportedAppUsage
     public String vendorInfo;
 
+    @UnsupportedAppUsage
     public int leaseDuration;
 
     /** Link MTU option. 0 means unset. */
+    @UnsupportedAppUsage
     public int mtu;
 
+    @UnsupportedAppUsage
     public DhcpResults() {
         super();
     }
 
+    @UnsupportedAppUsage
     public DhcpResults(StaticIpConfiguration source) {
         super(source);
     }
 
     /** copy constructor */
+    @UnsupportedAppUsage
     public DhcpResults(DhcpResults source) {
         super(source);
 
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index ecccda5..7256502 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
@@ -66,6 +67,7 @@
          * @param iface Ethernet interface name
          * @param isAvailable {@code true} if Ethernet port exists.
          */
+        @UnsupportedAppUsage
         void onAvailabilityChanged(String iface, boolean isAvailable);
     }
 
@@ -84,6 +86,7 @@
      * Get Ethernet configuration.
      * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
      */
+    @UnsupportedAppUsage
     public IpConfiguration getConfiguration(String iface) {
         try {
             return mService.getConfiguration(iface);
@@ -95,6 +98,7 @@
     /**
      * Set Ethernet configuration.
      */
+    @UnsupportedAppUsage
     public void setConfiguration(String iface, IpConfiguration config) {
         try {
             mService.setConfiguration(iface, config);
@@ -106,6 +110,7 @@
     /**
      * Indicates whether the system currently has one or more Ethernet interfaces.
      */
+    @UnsupportedAppUsage
     public boolean isAvailable() {
         return getAvailableInterfaces().length > 0;
     }
@@ -115,6 +120,7 @@
      *
      * @param iface Ethernet interface name
      */
+    @UnsupportedAppUsage
     public boolean isAvailable(String iface) {
         try {
             return mService.isAvailable(iface);
@@ -128,6 +134,7 @@
      * @param listener A {@link Listener} to add.
      * @throws IllegalArgumentException If the listener is null.
      */
+    @UnsupportedAppUsage
     public void addListener(Listener listener) {
         if (listener == null) {
             throw new IllegalArgumentException("listener must not be null");
@@ -145,6 +152,7 @@
     /**
      * Returns an array of available Ethernet interface names.
      */
+    @UnsupportedAppUsage
     public String[] getAvailableInterfaces() {
         try {
             return mService.getAvailableInterfaces();
@@ -158,6 +166,7 @@
      * @param listener A {@link Listener} to remove.
      * @throws IllegalArgumentException If the listener is null.
      */
+    @UnsupportedAppUsage
     public void removeListener(Listener listener) {
         if (listener == null) {
             throw new IllegalArgumentException("listener must not be null");
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index 34cde08..b274155 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -45,6 +46,7 @@
         return builder.toString();
     }
 
+    @UnsupportedAppUsage
     public Iterable<String> getFlags() {
         return mFlags;
     }
@@ -54,11 +56,13 @@
         return mFlags.contains(flag);
     }
 
+    @UnsupportedAppUsage
     public void clearFlag(String flag) {
         validateFlag(flag);
         mFlags.remove(flag);
     }
 
+    @UnsupportedAppUsage
     public void setFlag(String flag) {
         validateFlag(flag);
         mFlags.add(flag);
@@ -67,6 +71,7 @@
     /**
      * Set flags to mark interface as up.
      */
+    @UnsupportedAppUsage
     public void setInterfaceUp() {
         mFlags.remove(FLAG_DOWN);
         mFlags.add(FLAG_UP);
@@ -75,6 +80,7 @@
     /**
      * Set flags to mark interface as down.
      */
+    @UnsupportedAppUsage
     public void setInterfaceDown() {
         mFlags.remove(FLAG_UP);
         mFlags.add(FLAG_DOWN);
@@ -92,6 +98,7 @@
         return mAddr;
     }
 
+    @UnsupportedAppUsage
     public void setLinkAddress(LinkAddress addr) {
         mAddr = addr;
     }
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
index fe69f296..3319f33 100644
--- a/core/java/android/net/IpConfiguration.java
+++ b/core/java/android/net/IpConfiguration.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.StaticIpConfiguration;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -32,8 +33,9 @@
     public enum IpAssignment {
         /* Use statically configured IP settings. Configuration can be accessed
          * with staticIpConfiguration */
+        @UnsupportedAppUsage
         STATIC,
-        /* Use dynamically configured IP settigns */
+        /* Use dynamically configured IP settings */
         DHCP,
         /* no IP details are assigned, this is used to indicate
          * that any existing IP settings should be retained */
@@ -47,6 +49,7 @@
     public enum ProxySettings {
         /* No proxy is to be used. Any existing proxy settings
          * should be cleared. */
+        @UnsupportedAppUsage
         NONE,
         /* Use statically configured proxy. Configuration can be accessed
          * with httpProxy. */
@@ -61,6 +64,7 @@
 
     public ProxySettings proxySettings;
 
+    @UnsupportedAppUsage
     public ProxyInfo httpProxy;
 
     private void init(IpAssignment ipAssignment,
@@ -79,6 +83,7 @@
         init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null);
     }
 
+    @UnsupportedAppUsage
     public IpConfiguration(IpAssignment ipAssignment,
                            ProxySettings proxySettings,
                            StaticIpConfiguration staticIpConfiguration,
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index bcfe938..1bc0d32 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -25,6 +25,7 @@
 import static android.system.OsConstants.RT_SCOPE_SITE;
 import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Pair;
@@ -54,11 +55,13 @@
     /**
      * IPv4 or IPv6 address.
      */
+    @UnsupportedAppUsage
     private InetAddress address;
 
     /**
      * Prefix length.
      */
+    @UnsupportedAppUsage
     private int prefixLength;
 
     /**
@@ -112,6 +115,7 @@
      * @return true if the address is IPv6.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isIPv6() {
         return address instanceof Inet6Address;
     }
@@ -163,6 +167,7 @@
      * @param prefixLength The prefix length.
      * @hide
      */
+    @UnsupportedAppUsage
     public LinkAddress(InetAddress address, int prefixLength) {
         this(address, prefixLength, 0, 0);
         this.scope = scopeForUnicastAddress(address);
@@ -185,6 +190,7 @@
      * @param string The string to parse.
      * @hide
      */
+    @UnsupportedAppUsage
     public LinkAddress(String address) {
         this(address, 0, 0);
         this.scope = scopeForUnicastAddress(this.address);
@@ -255,6 +261,7 @@
      * otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isSameAddressAs(LinkAddress other) {
         return address.equals(other.address) && prefixLength == other.prefixLength;
     }
@@ -278,6 +285,7 @@
      * TODO: Delete all callers and remove in favour of getPrefixLength().
      * @hide
      */
+    @UnsupportedAppUsage
     public int getNetworkPrefixLength() {
         return getPrefixLength();
     }
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index bd2db92..1b9a66c 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -48,6 +49,7 @@
  */
 public final class LinkProperties implements Parcelable {
     // The interface described by the network link.
+    @UnsupportedAppUsage
     private String mIfaceName;
     private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>();
     private ArrayList<InetAddress> mDnses = new ArrayList<>();
@@ -103,9 +105,13 @@
      * @hide
      */
     public enum ProvisioningChange {
+        @UnsupportedAppUsage
         STILL_NOT_PROVISIONED,
+        @UnsupportedAppUsage
         LOST_PROVISIONING,
+        @UnsupportedAppUsage
         GAINED_PROVISIONING,
+        @UnsupportedAppUsage
         STILL_PROVISIONED,
     }
 
@@ -114,6 +120,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static ProvisioningChange compareProvisioning(
             LinkProperties before, LinkProperties after) {
         if (before.isProvisioned() && after.isProvisioned()) {
@@ -154,12 +161,14 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public LinkProperties() {
     }
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public LinkProperties(LinkProperties source) {
         if (source != null) {
             mIfaceName = source.mIfaceName;
@@ -186,6 +195,7 @@
      * @param iface The name of the network interface used for this link.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setInterfaceName(String iface) {
         mIfaceName = iface;
         ArrayList<RouteInfo> newRoutes = new ArrayList<>(mRoutes.size());
@@ -207,6 +217,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public List<String> getAllInterfaceNames() {
         List<String> interfaceNames = new ArrayList<>(mStackedLinks.size() + 1);
         if (mIfaceName != null) interfaceNames.add(mIfaceName);
@@ -226,6 +237,7 @@
      * @return An unmodifiable {@link List} of {@link InetAddress} for this link.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<InetAddress> getAddresses() {
         List<InetAddress> addresses = new ArrayList<>();
         for (LinkAddress linkAddress : mLinkAddresses) {
@@ -238,6 +250,7 @@
      * Returns all the addresses on this link and all the links stacked above it.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<InetAddress> getAllAddresses() {
         List<InetAddress> addresses = new ArrayList<>();
         for (LinkAddress linkAddress : mLinkAddresses) {
@@ -265,6 +278,7 @@
      * @return true if {@code address} was added or updated, false otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean addLinkAddress(LinkAddress address) {
         if (address == null) {
             return false;
@@ -315,6 +329,7 @@
      * Returns all the addresses on this link and all the links stacked above it.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<LinkAddress> getAllLinkAddresses() {
         List<LinkAddress> addresses = new ArrayList<>(mLinkAddresses);
         for (LinkProperties stacked: mStackedLinks.values()) {
@@ -331,6 +346,7 @@
      *                  object.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLinkAddresses(Collection<LinkAddress> addresses) {
         mLinkAddresses.clear();
         for (LinkAddress address: addresses) {
@@ -345,6 +361,7 @@
      * @return true if the DNS server was added, false if it was already present.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean addDnsServer(InetAddress dnsServer) {
         if (dnsServer != null && !mDnses.contains(dnsServer)) {
             mDnses.add(dnsServer);
@@ -360,6 +377,7 @@
      * @return true if the DNS server was removed, false if it did not exist.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean removeDnsServer(InetAddress dnsServer) {
         if (dnsServer != null) {
             return mDnses.remove(dnsServer);
@@ -374,6 +392,7 @@
      * @param dnsServers The {@link Collection} of DNS servers to set in this object.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDnsServers(Collection<InetAddress> dnsServers) {
         mDnses.clear();
         for (InetAddress dnsServer: dnsServers) {
@@ -510,6 +529,7 @@
      *                domains to search when resolving host names on this link.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDomains(String domains) {
         mDomains = domains;
     }
@@ -532,6 +552,7 @@
      * @param mtu The MTU to use for this link.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setMtu(int mtu) {
         mMtu = mtu;
     }
@@ -543,6 +564,7 @@
      * @return The mtu value set for this link.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getMtu() {
         return mMtu;
     }
@@ -555,6 +577,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setTcpBufferSizes(String tcpBufferSizes) {
         mTcpBufferSizes = tcpBufferSizes;
     }
@@ -566,6 +589,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getTcpBufferSizes() {
         return mTcpBufferSizes;
     }
@@ -589,6 +613,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean addRoute(RouteInfo route) {
         if (route != null) {
             String routeIface = route.getInterface();
@@ -615,6 +640,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean removeRoute(RouteInfo route) {
         return route != null &&
                 Objects.equals(mIfaceName, route.getInterface()) &&
@@ -645,6 +671,7 @@
      * Returns all the routes on this link and all the links stacked above it.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<RouteInfo> getAllRoutes() {
         List<RouteInfo> routes = new ArrayList<>(mRoutes);
         for (LinkProperties stacked: mStackedLinks.values()) {
@@ -661,6 +688,7 @@
      * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setHttpProxy(ProxyInfo proxy) {
         mHttpProxy = proxy;
     }
@@ -685,6 +713,7 @@
      * @return true if the link was stacked, false otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean addStackedLink(LinkProperties link) {
         if (link != null && link.getInterfaceName() != null) {
             mStackedLinks.put(link.getInterfaceName(), link);
@@ -715,6 +744,7 @@
      * Returns all the links stacked on top of this link.
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull List<LinkProperties> getStackedLinks() {
         if (mStackedLinks.isEmpty()) {
             return Collections.emptyList();
@@ -730,6 +760,7 @@
      * Clears this object to its initial state.
      * @hide
      */
+    @UnsupportedAppUsage
     public void clear() {
         mIfaceName = null;
         mLinkAddresses.clear();
@@ -831,6 +862,7 @@
      * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean hasIPv4Address() {
         for (LinkAddress address : mLinkAddresses) {
             if (address.getAddress() instanceof Inet4Address) {
@@ -858,6 +890,7 @@
      * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean hasGlobalIPv6Address() {
         for (LinkAddress address : mLinkAddresses) {
           if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) {
@@ -873,6 +906,7 @@
      * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean hasIPv4DefaultRoute() {
         for (RouteInfo r : mRoutes) {
             if (r.isIPv4Default()) {
@@ -888,6 +922,7 @@
      * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean hasIPv6DefaultRoute() {
         for (RouteInfo r : mRoutes) {
             if (r.isIPv6Default()) {
@@ -903,6 +938,7 @@
      * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean hasIPv4DnsServer() {
         for (InetAddress ia : mDnses) {
             if (ia instanceof Inet4Address) {
@@ -918,6 +954,7 @@
      * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean hasIPv6DnsServer() {
         for (InetAddress ia : mDnses) {
             if (ia instanceof Inet6Address) {
@@ -947,6 +984,7 @@
      * @return {@code true} if the link is provisioned, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isIPv6Provisioned() {
         return (hasGlobalIPv6Address() &&
                 hasIPv6DefaultRoute() &&
@@ -960,6 +998,7 @@
      * @return {@code true} if the link is provisioned, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isProvisioned() {
         return (isIPv4Provisioned() || isIPv6Provisioned());
     }
@@ -971,6 +1010,7 @@
      *         {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isReachable(InetAddress ip) {
         final List<RouteInfo> allRoutes = getAllRoutes();
         // If we don't have a route to this IP address, it's not reachable.
@@ -1008,6 +1048,7 @@
      * @return {@code true} if both are identical, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isIdenticalInterfaceName(LinkProperties target) {
         return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
     }
@@ -1019,6 +1060,7 @@
      * @return {@code true} if both are identical, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isIdenticalAddresses(LinkProperties target) {
         Collection<InetAddress> targetAddresses = target.getAddresses();
         Collection<InetAddress> sourceAddresses = getAddresses();
@@ -1033,6 +1075,7 @@
      * @return {@code true} if both are identical, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isIdenticalDnses(LinkProperties target) {
         Collection<InetAddress> targetDnses = target.getDnsServers();
         String targetDomains = target.getDomains();
@@ -1080,6 +1123,7 @@
      * @return {@code true} if both are identical, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isIdenticalRoutes(LinkProperties target) {
         Collection<RouteInfo> targetRoutes = target.getRoutes();
         return (mRoutes.size() == targetRoutes.size()) ?
@@ -1093,6 +1137,7 @@
      * @return {@code true} if both are identical, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isIdenticalHttpProxy(LinkProperties target) {
         return getHttpProxy() == null ? target.getHttpProxy() == null :
                 getHttpProxy().equals(target.getHttpProxy());
@@ -1105,6 +1150,7 @@
      * @return {@code true} if both are identical, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isIdenticalStackedLinks(LinkProperties target) {
         if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) {
             return false;
diff --git a/core/java/android/net/LinkQualityInfo.java b/core/java/android/net/LinkQualityInfo.java
index 9c8e61d..b6f8825 100644
--- a/core/java/android/net/LinkQualityInfo.java
+++ b/core/java/android/net/LinkQualityInfo.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -189,6 +190,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPacketCount(long packetCount) {
         mPacketCount = packetCount;
     }
@@ -204,6 +206,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPacketErrorCount(long packetErrorCount) {
         mPacketErrorCount = packetErrorCount;
     }
@@ -265,6 +268,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLastDataSampleTime(long lastDataSampleTime) {
         mLastDataSampleTime = lastDataSampleTime;
     }
@@ -280,6 +284,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDataSampleDuration(int dataSampleDuration) {
         mDataSampleDuration = dataSampleDuration;
     }
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index 8afa1ed..6a2031b 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.Closeable;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -30,6 +31,7 @@
  */
 public class LocalSocket implements Closeable {
 
+    @UnsupportedAppUsage
     private final LocalSocketImpl impl;
     /** false if impl.create() needs to be called */
     private volatile boolean implCreated;
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index 6e4a231..fe7632c 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.system.ErrnoException;
 import android.system.Int32Ref;
 import android.system.Os;
@@ -47,8 +48,10 @@
 
     // These fields are accessed by native code;
     /** file descriptor array received during a previous read */
+    @UnsupportedAppUsage
     FileDescriptor[] inboundFileDescriptors;
     /** file descriptor array that should be written during next write */
+    @UnsupportedAppUsage
     FileDescriptor[] outboundFileDescriptors;
 
     /**
@@ -207,6 +210,7 @@
     /**
      * Create a new instance.
      */
+    @UnsupportedAppUsage
     /*package*/ LocalSocketImpl()
     {
     }
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 74d6470..98f3567 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -50,6 +51,7 @@
      * The MacAddress zero MAC address.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final MacAddress ALL_ZEROS_ADDRESS = new MacAddress(0);
 
     /** @hide */
diff --git a/core/java/android/net/MobileLinkQualityInfo.java b/core/java/android/net/MobileLinkQualityInfo.java
index a01fc80..06c739d 100644
--- a/core/java/android/net/MobileLinkQualityInfo.java
+++ b/core/java/android/net/MobileLinkQualityInfo.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 
 /**
@@ -93,6 +94,7 @@
      * returns mobile network type as defined by {@link android.telephony.TelephonyManager}
      * @return network type or {@link android.net.LinkQualityInfo#UNKNOWN_INT}
      */
+    @UnsupportedAppUsage
     public int getMobileNetworkType() {
         return mMobileNetworkType;
     }
@@ -100,6 +102,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setMobileNetworkType(int mobileNetworkType) {
         mMobileNetworkType = mobileNetworkType;
     }
@@ -115,6 +118,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRssi(int Rssi) {
         mRssi = Rssi;
     }
@@ -130,6 +134,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setGsmErrorRate(int gsmErrorRate) {
         mGsmErrorRate = gsmErrorRate;
     }
@@ -145,6 +150,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaDbm(int cdmaDbm) {
         mCdmaDbm = cdmaDbm;
     }
@@ -160,6 +166,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaEcio(int cdmaEcio) {
         mCdmaEcio = cdmaEcio;
     }
@@ -175,6 +182,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setEvdoDbm(int evdoDbm) {
         mEvdoDbm = evdoDbm;
     }
@@ -190,6 +198,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setEvdoEcio(int evdoEcio) {
         mEvdoEcio = evdoEcio;
     }
@@ -205,6 +214,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setEvdoSnr(int evdoSnr) {
         mEvdoSnr = evdoSnr;
     }
@@ -220,6 +230,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLteSignalStrength(int lteSignalStrength) {
         mLteSignalStrength = lteSignalStrength;
     }
@@ -235,6 +246,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLteRsrp(int lteRsrp) {
         mLteRsrp = lteRsrp;
     }
@@ -250,6 +262,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLteRsrq(int lteRsrq) {
         mLteRsrq = lteRsrq;
     }
@@ -265,6 +278,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLteRssnr(int lteRssnr) {
         mLteRssnr = lteRssnr;
     }
@@ -280,6 +294,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLteCqi(int lteCqi) {
         mLteCqi = lteCqi;
     }
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 512e35e..142023d 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.system.ErrnoException;
@@ -59,6 +60,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public final int netId;
 
     // Objects used to perform per-network operations such as getSocketFactory
@@ -103,6 +105,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public Network(int netId) {
         this.netId = netId;
     }
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 52a2354..114b423 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.net.ConnectivityManager.PacketKeepalive;
 import android.os.Bundle;
@@ -351,6 +352,7 @@
     /**
      * Called by the bearer code when it has new NetworkInfo data.
      */
+    @UnsupportedAppUsage
     public void sendNetworkInfo(NetworkInfo networkInfo) {
         queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
     }
@@ -372,7 +374,7 @@
         if (score < 0) {
             throw new IllegalArgumentException("Score must be >= 0");
         }
-        queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
+        queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED,  score, 0);
     }
 
     /**
@@ -387,7 +389,7 @@
      * {@link #saveAcceptUnvalidated} to respect the user's choice.
      */
     public void explicitlySelected(boolean acceptUnvalidated) {
-        queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED, acceptUnvalidated);
+        queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED, acceptUnvalidated ? 1 : 0, 0);
     }
 
     /**
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 72b4bfd..fd1e5f2 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.net.ConnectivityManager.NetworkCallback;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -56,6 +57,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public NetworkCapabilities() {
         clearAll();
         mNetworkCapabilities = DEFAULT_CAPABILITIES;
@@ -103,6 +105,7 @@
      * Represents the network's capabilities.  If any are specified they will be satisfied
      * by any Network that matches all of them.
      */
+    @UnsupportedAppUsage
     private long mNetworkCapabilities;
 
     /**
@@ -371,6 +374,7 @@
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
+    @UnsupportedAppUsage
     public NetworkCapabilities addCapability(@NetCapability int capability) {
         checkValidCapability(capability);
         mNetworkCapabilities |= 1 << capability;
@@ -407,6 +411,7 @@
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
+    @UnsupportedAppUsage
     public NetworkCapabilities removeCapability(@NetCapability int capability) {
         checkValidCapability(capability);
         final long mask = ~(1 << capability);
@@ -659,6 +664,7 @@
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
+    @UnsupportedAppUsage
     public NetworkCapabilities addTransportType(@Transport int transportType) {
         checkValidTransportType(transportType);
         mTransportTypes |= 1 << transportType;
@@ -898,6 +904,7 @@
      *         specifier. See {@link #setNetworkSpecifier}.
      * @hide
      */
+    @UnsupportedAppUsage
     public NetworkSpecifier getNetworkSpecifier() {
         return mNetworkSpecifier;
     }
@@ -930,6 +937,7 @@
      * Signal strength. This is a signed integer, and higher values indicate better signal.
      * The exact units are bearer-dependent. For example, Wi-Fi uses RSSI.
      */
+    @UnsupportedAppUsage
     private int mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
 
     /**
@@ -945,6 +953,7 @@
      * @param signalStrength the bearer-specific signal strength.
      * @hide
      */
+    @UnsupportedAppUsage
     public NetworkCapabilities setSignalStrength(int signalStrength) {
         mSignalStrength = signalStrength;
         return this;
@@ -955,6 +964,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean hasSignalStrength() {
         return mSignalStrength > SIGNAL_STRENGTH_UNSPECIFIED;
     }
@@ -965,6 +975,7 @@
      * @return The bearer-specific signal strength.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getSignalStrength() {
         return mSignalStrength;
     }
@@ -1544,6 +1555,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static String transportNamesOf(@Transport int[] types) {
         StringJoiner joiner = new StringJoiner("|");
         if (types != null) {
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index e2f8d1a..010d72f 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
@@ -106,6 +107,7 @@
     private int mRefCount = 0;
     private Messenger mMessenger = null;
 
+    @UnsupportedAppUsage
     public NetworkFactory(Looper looper, Context context, String logTag,
             NetworkCapabilities filter) {
         super(looper);
@@ -287,6 +289,7 @@
         sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest));
     }
 
+    @UnsupportedAppUsage
     public void setScoreFilter(int score) {
         sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
     }
@@ -304,6 +307,7 @@
         Log.d(LOG_TAG, s);
     }
 
+    @UnsupportedAppUsage
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         pw.println(toString());
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 999771a..d912dd10 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -129,6 +130,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public NetworkInfo(int type, int subtype, String typeName, String subtypeName) {
         if (!ConnectivityManager.isNetworkTypeValid(type)
                 && type != ConnectivityManager.TYPE_NONE) {
@@ -143,6 +145,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public NetworkInfo(NetworkInfo source) {
         if (source != null) {
             synchronized (source) {
@@ -209,6 +212,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSubtype(int subtype, String subtypeName) {
         synchronized (this) {
             mSubtype = subtype;
@@ -317,6 +321,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setIsAvailable(boolean isAvailable) {
         synchronized (this) {
             mIsAvailable = isAvailable;
@@ -347,6 +352,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setFailover(boolean isFailover) {
         synchronized (this) {
             mIsFailover = isFailover;
@@ -377,6 +383,7 @@
      */
     @VisibleForTesting
     @Deprecated
+    @UnsupportedAppUsage
     public void setRoaming(boolean isRoaming) {
         synchronized (this) {
             mIsRoaming = isRoaming;
@@ -422,6 +429,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) {
         synchronized (this) {
             this.mDetailedState = detailedState;
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index e84c85e..f8973eb 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.BackupUtils;
@@ -49,14 +50,19 @@
     public static final long LIMIT_DISABLED = -1;
     public static final long SNOOZE_NEVER = -1;
 
+    @UnsupportedAppUsage
     public NetworkTemplate template;
     public RecurrenceRule cycleRule;
+    @UnsupportedAppUsage
     public long warningBytes = WARNING_DISABLED;
+    @UnsupportedAppUsage
     public long limitBytes = LIMIT_DISABLED;
     public long lastWarningSnooze = SNOOZE_NEVER;
     public long lastLimitSnooze = SNOOZE_NEVER;
     public long lastRapidSnooze = SNOOZE_NEVER;
+    @UnsupportedAppUsage
     @Deprecated public boolean metered = true;
+    @UnsupportedAppUsage
     public boolean inferred = false;
 
     private static final long DEFAULT_MTU = 1500;
@@ -77,6 +83,7 @@
     }
 
     @Deprecated
+    @UnsupportedAppUsage
     public NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone,
             long warningBytes, long limitBytes, long lastWarningSnooze, long lastLimitSnooze,
             boolean metered, boolean inferred) {
@@ -143,6 +150,7 @@
     /**
      * Test if given measurement is over {@link #warningBytes}.
      */
+    @UnsupportedAppUsage
     public boolean isOverWarning(long totalBytes) {
         return warningBytes != WARNING_DISABLED && totalBytes >= warningBytes;
     }
@@ -151,6 +159,7 @@
      * Test if given measurement is near enough to {@link #limitBytes} to be
      * considered over-limit.
      */
+    @UnsupportedAppUsage
     public boolean isOverLimit(long totalBytes) {
         // over-estimate, since kernel will trigger limit once first packet
         // trips over limit.
@@ -161,6 +170,7 @@
     /**
      * Clear any existing snooze values, setting to {@link #SNOOZE_NEVER}.
      */
+    @UnsupportedAppUsage
     public void clearSnooze() {
         lastWarningSnooze = SNOOZE_NEVER;
         lastLimitSnooze = SNOOZE_NEVER;
@@ -175,6 +185,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public int compareTo(NetworkPolicy another) {
         if (another == null || another.limitBytes == LIMIT_DISABLED) {
             // other value is missing or disabled; we win
@@ -225,6 +236,7 @@
                 .append("}").toString();
     }
 
+    @UnsupportedAppUsage
     public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() {
         @Override
         public NetworkPolicy createFromParcel(Parcel in) {
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 75fd77e..d5fb2e7 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.GET_SIGNATURES;
 
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
@@ -121,6 +122,7 @@
     public static final int OVERRIDE_CONGESTED = 1 << 1;
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private INetworkPolicyManager mService;
 
     public NetworkPolicyManager(Context context, INetworkPolicyManager service) {
@@ -131,6 +133,7 @@
         mService = service;
     }
 
+    @UnsupportedAppUsage
     public static NetworkPolicyManager from(Context context) {
         return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE);
     }
@@ -141,6 +144,7 @@
      * @param policy should be {@link #POLICY_NONE} or any combination of {@code POLICY_} flags,
      *     although it is not validated.
      */
+    @UnsupportedAppUsage
     public void setUidPolicy(int uid, int policy) {
         try {
             mService.setUidPolicy(uid, policy);
@@ -181,6 +185,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public int getUidPolicy(int uid) {
         try {
             return mService.getUidPolicy(uid);
@@ -189,6 +194,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public int[] getUidsWithPolicy(int policy) {
         try {
             return mService.getUidsWithPolicy(policy);
@@ -197,6 +203,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void registerListener(INetworkPolicyListener listener) {
         try {
             mService.registerListener(listener);
@@ -205,6 +212,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void unregisterListener(INetworkPolicyListener listener) {
         try {
             mService.unregisterListener(listener);
@@ -221,6 +229,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public NetworkPolicy[] getNetworkPolicies() {
         try {
             return mService.getNetworkPolicies(mContext.getOpPackageName());
@@ -229,6 +238,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void setRestrictBackground(boolean restrictBackground) {
         try {
             mService.setRestrictBackground(restrictBackground);
@@ -237,6 +247,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public boolean getRestrictBackground() {
         try {
             return mService.getRestrictBackground();
diff --git a/core/java/android/net/NetworkQuotaInfo.java b/core/java/android/net/NetworkQuotaInfo.java
index b95f1d9..e7182f7 100644
--- a/core/java/android/net/NetworkQuotaInfo.java
+++ b/core/java/android/net/NetworkQuotaInfo.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -36,14 +37,17 @@
     public NetworkQuotaInfo(Parcel in) {
     }
 
+    @UnsupportedAppUsage
     public long getEstimatedBytes() {
         return 0;
     }
 
+    @UnsupportedAppUsage
     public long getSoftLimitBytes() {
         return NO_LIMIT;
     }
 
+    @UnsupportedAppUsage
     public long getHardLimitBytes() {
         return NO_LIMIT;
     }
@@ -57,6 +61,7 @@
     public void writeToParcel(Parcel out, int flags) {
     }
 
+    @UnsupportedAppUsage
     public static final Creator<NetworkQuotaInfo> CREATOR = new Creator<NetworkQuotaInfo>() {
         @Override
         public NetworkQuotaInfo createFromParcel(Parcel in) {
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 16c2342..04b6b44 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.net.NetworkCapabilities.NetCapability;
 import android.net.NetworkCapabilities.Transport;
 import android.os.Parcel;
@@ -38,6 +39,7 @@
      * The {@link NetworkCapabilities} that define this request.
      * @hide
      */
+    @UnsupportedAppUsage
     public final @NonNull NetworkCapabilities networkCapabilities;
 
     /**
@@ -46,6 +48,7 @@
      * the request.
      * @hide
      */
+    @UnsupportedAppUsage
     public final int requestId;
 
     /**
@@ -53,6 +56,7 @@
      * Causes CONNECTIVITY_ACTION broadcasts to be sent.
      * @hide
      */
+    @UnsupportedAppUsage
     public final int legacyType;
 
     /**
@@ -241,6 +245,7 @@
          * @return The builder to facilitate chaining.
          * @hide
          */
+        @UnsupportedAppUsage
         public Builder clearCapabilities() {
             mNetworkCapabilities.clearAll();
             return this;
@@ -339,6 +344,7 @@
          * @param signalStrength the bearer-specific signal strength.
          * @hide
          */
+        @UnsupportedAppUsage
         public Builder setSignalStrength(int signalStrength) {
             mNetworkCapabilities.setSignalStrength(signalStrength);
             return this;
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index 321f971..c545ee2 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Slog;
@@ -33,6 +34,7 @@
     public final NetworkInfo networkInfo;
     public final LinkProperties linkProperties;
     public final NetworkCapabilities networkCapabilities;
+    @UnsupportedAppUsage
     public final Network network;
     public final String subscriberId;
     public final String networkId;
@@ -58,6 +60,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public NetworkState(Parcel in) {
         networkInfo = in.readParcelable(null);
         linkProperties = in.readParcelable(null);
@@ -82,6 +85,7 @@
         out.writeString(networkId);
     }
 
+    @UnsupportedAppUsage
     public static final Creator<NetworkState> CREATOR = new Creator<NetworkState>() {
         @Override
         public NetworkState createFromParcel(Parcel in) {
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index edf9bc1..e270fc2 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -110,25 +111,43 @@
      * generated.
      */
     private long elapsedRealtime;
+    @UnsupportedAppUsage
     private int size;
+    @UnsupportedAppUsage
     private int capacity;
+    @UnsupportedAppUsage
     private String[] iface;
+    @UnsupportedAppUsage
     private int[] uid;
+    @UnsupportedAppUsage
     private int[] set;
+    @UnsupportedAppUsage
     private int[] tag;
+    @UnsupportedAppUsage
     private int[] metered;
+    @UnsupportedAppUsage
     private int[] roaming;
+    @UnsupportedAppUsage
     private int[] defaultNetwork;
+    @UnsupportedAppUsage
     private long[] rxBytes;
+    @UnsupportedAppUsage
     private long[] rxPackets;
+    @UnsupportedAppUsage
     private long[] txBytes;
+    @UnsupportedAppUsage
     private long[] txPackets;
+    @UnsupportedAppUsage
     private long[] operations;
 
     public static class Entry {
+        @UnsupportedAppUsage
         public String iface;
+        @UnsupportedAppUsage
         public int uid;
+        @UnsupportedAppUsage
         public int set;
+        @UnsupportedAppUsage
         public int tag;
         /**
          * Note that this is only populated w/ the default value when read from /proc or written
@@ -148,12 +167,17 @@
          * getSummary().
          */
         public int defaultNetwork;
+        @UnsupportedAppUsage
         public long rxBytes;
+        @UnsupportedAppUsage
         public long rxPackets;
+        @UnsupportedAppUsage
         public long txBytes;
+        @UnsupportedAppUsage
         public long txPackets;
         public long operations;
 
+        @UnsupportedAppUsage
         public Entry() {
             this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
         }
@@ -240,6 +264,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public NetworkStats(long elapsedRealtime, int initialSize) {
         this.elapsedRealtime = elapsedRealtime;
         this.size = 0;
@@ -263,6 +288,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public NetworkStats(Parcel parcel) {
         elapsedRealtime = parcel.readLong();
         size = parcel.readInt();
@@ -399,6 +425,7 @@
     /**
      * Return specific stats entry.
      */
+    @UnsupportedAppUsage
     public Entry getValues(int i, Entry recycle) {
         final Entry entry = recycle != null ? recycle : new Entry();
         entry.iface = iface[i];
@@ -432,6 +459,7 @@
         return SystemClock.elapsedRealtime() - elapsedRealtime;
     }
 
+    @UnsupportedAppUsage
     public int size() {
         return size;
     }
@@ -460,6 +488,7 @@
      * {@link #findIndex(String, int, int, int, int)} is unable to find match. Can
      * also be used to subtract values from existing rows.
      */
+    @UnsupportedAppUsage
     public NetworkStats combineValues(Entry entry) {
         final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered,
                 entry.roaming, entry.defaultNetwork);
@@ -479,6 +508,7 @@
     /**
      * Combine all values from another {@link NetworkStats} into this object.
      */
+    @UnsupportedAppUsage
     public void combineAllValues(NetworkStats another) {
         NetworkStats.Entry entry = null;
         for (int i = 0; i < another.size; i++) {
@@ -564,6 +594,7 @@
     /**
      * Return list of unique UIDs known by this data structure.
      */
+    @UnsupportedAppUsage
     public int[] getUniqueUids() {
         final SparseBooleanArray uids = new SparseBooleanArray();
         for (int uid : this.uid) {
@@ -582,6 +613,7 @@
      * Return total bytes represented by this snapshot object, usually used when
      * checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
      */
+    @UnsupportedAppUsage
     public long getTotalBytes() {
         final Entry entry = getTotal(null);
         return entry.rxBytes + entry.txBytes;
@@ -590,6 +622,7 @@
     /**
      * Return total of all fields represented by this snapshot object.
      */
+    @UnsupportedAppUsage
     public Entry getTotal(Entry recycle) {
         return getTotal(recycle, null, UID_ALL, false);
     }
@@ -598,6 +631,7 @@
      * Return total of all fields represented by this snapshot object matching
      * the requested {@link #uid}.
      */
+    @UnsupportedAppUsage
     public Entry getTotal(Entry recycle, int limitUid) {
         return getTotal(recycle, null, limitUid, false);
     }
@@ -610,6 +644,7 @@
         return getTotal(recycle, limitIface, UID_ALL, false);
     }
 
+    @UnsupportedAppUsage
     public Entry getTotalIncludingTags(Entry recycle) {
         return getTotal(recycle, null, UID_ALL, true);
     }
@@ -1085,6 +1120,7 @@
         return 0;
     }
 
+    @UnsupportedAppUsage
     public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
         @Override
         public NetworkStats createFromParcel(Parcel in) {
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index a13ad65..d53e032 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -30,6 +30,7 @@
 
 import static com.android.internal.util.ArrayUtils.total;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.service.NetworkStatsHistoryBucketProto;
@@ -89,16 +90,23 @@
     public static class Entry {
         public static final long UNKNOWN = -1;
 
+        @UnsupportedAppUsage
         public long bucketDuration;
+        @UnsupportedAppUsage
         public long bucketStart;
         public long activeTime;
+        @UnsupportedAppUsage
         public long rxBytes;
+        @UnsupportedAppUsage
         public long rxPackets;
+        @UnsupportedAppUsage
         public long txBytes;
+        @UnsupportedAppUsage
         public long txPackets;
         public long operations;
     }
 
+    @UnsupportedAppUsage
     public NetworkStatsHistory(long bucketDuration) {
         this(bucketDuration, 10, FIELD_ALL);
     }
@@ -125,6 +133,7 @@
         recordEntireHistory(existing);
     }
 
+    @UnsupportedAppUsage
     public NetworkStatsHistory(Parcel in) {
         bucketDuration = in.readLong();
         bucketStart = readLongArray(in);
@@ -210,6 +219,7 @@
         return 0;
     }
 
+    @UnsupportedAppUsage
     public int size() {
         return bucketCount;
     }
@@ -218,6 +228,7 @@
         return bucketDuration;
     }
 
+    @UnsupportedAppUsage
     public long getStart() {
         if (bucketCount > 0) {
             return bucketStart[0];
@@ -226,6 +237,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public long getEnd() {
         if (bucketCount > 0) {
             return bucketStart[bucketCount - 1] + bucketDuration;
@@ -245,6 +257,7 @@
      * Return index of bucket that contains or is immediately before the
      * requested time.
      */
+    @UnsupportedAppUsage
     public int getIndexBefore(long time) {
         int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
         if (index < 0) {
@@ -272,6 +285,7 @@
     /**
      * Return specific stats entry.
      */
+    @UnsupportedAppUsage
     public Entry getValues(int i, Entry recycle) {
         final Entry entry = recycle != null ? recycle : new Entry();
         entry.bucketStart = bucketStart[i];
@@ -373,6 +387,7 @@
      * Record an entire {@link NetworkStatsHistory} into this history. Usually
      * for combining together stats for external reporting.
      */
+    @UnsupportedAppUsage
     public void recordEntireHistory(NetworkStatsHistory input) {
         recordHistory(input, Long.MIN_VALUE, Long.MAX_VALUE);
     }
@@ -509,6 +524,7 @@
      * Return interpolated data usage across the requested range. Interpolates
      * across buckets, so values may be rounded slightly.
      */
+    @UnsupportedAppUsage
     public Entry getValues(long start, long end, Entry recycle) {
         return getValues(start, end, Long.MAX_VALUE, recycle);
     }
@@ -517,6 +533,7 @@
      * Return interpolated data usage across the requested range. Interpolates
      * across buckets, so values may be rounded slightly.
      */
+    @UnsupportedAppUsage
     public Entry getValues(long start, long end, long now, Entry recycle) {
         final Entry entry = recycle != null ? recycle : new Entry();
         entry.bucketDuration = end - start;
@@ -701,6 +718,7 @@
         return writer.toString();
     }
 
+    @UnsupportedAppUsage
     public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
         @Override
         public NetworkStatsHistory createFromParcel(Parcel in) {
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 74233fd..bb75c63 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -34,6 +34,7 @@
 import static android.net.NetworkStats.ROAMING_YES;
 import static android.net.wifi.WifiInfo.removeDoubleQuotes;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.BackupUtils;
@@ -96,6 +97,7 @@
      * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
      * the given IMSI.
      */
+    @UnsupportedAppUsage
     public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
         return new NetworkTemplate(MATCH_MOBILE, subscriberId, null);
     }
@@ -104,6 +106,7 @@
      * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
      * regardless of IMSI.
      */
+    @UnsupportedAppUsage
     public static NetworkTemplate buildTemplateMobileWildcard() {
         return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
     }
@@ -112,11 +115,13 @@
      * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
      * regardless of SSID.
      */
+    @UnsupportedAppUsage
     public static NetworkTemplate buildTemplateWifiWildcard() {
         return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
     }
 
     @Deprecated
+    @UnsupportedAppUsage
     public static NetworkTemplate buildTemplateWifi() {
         return buildTemplateWifiWildcard();
     }
@@ -133,6 +138,7 @@
      * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
      * networks together.
      */
+    @UnsupportedAppUsage
     public static NetworkTemplate buildTemplateEthernet() {
         return new NetworkTemplate(MATCH_ETHERNET, null, null);
     }
@@ -173,6 +179,7 @@
     private final int mRoaming;
     private final int mDefaultNetwork;
 
+    @UnsupportedAppUsage
     public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
         this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
     }
@@ -293,10 +300,12 @@
         }
     }
 
+    @UnsupportedAppUsage
     public int getMatchRule() {
         return mMatchRule;
     }
 
+    @UnsupportedAppUsage
     public String getSubscriberId() {
         return mSubscriberId;
     }
@@ -460,6 +469,7 @@
      * active merge set [A,B], we'd return a new template that primarily matches
      * A, but also matches B.
      */
+    @UnsupportedAppUsage
     public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
         if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) {
             // Requested template subscriber is part of the merge group; return
@@ -471,6 +481,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
         @Override
         public NetworkTemplate createFromParcel(Parcel in) {
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 9a5d502..34e9476 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -16,11 +16,13 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.util.Log;
 import android.util.Pair;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -43,6 +45,7 @@
     /**
      * Attaches a socket filter that accepts DHCP packets to the given socket.
      */
+    @UnsupportedAppUsage
     public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;
 
     /**
@@ -50,6 +53,7 @@
      * @param fd the socket's {@link FileDescriptor}.
      * @param packetType the hardware address type, one of ARPHRD_*.
      */
+    @UnsupportedAppUsage
     public native static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException;
 
     /**
@@ -60,6 +64,7 @@
      * @param fd the socket's {@link FileDescriptor}.
      * @param packetType the hardware address type, one of ARPHRD_*.
      */
+    @UnsupportedAppUsage
     public native static void attachControlPacketFilter(FileDescriptor fd, int packetType)
             throws SocketException;
 
@@ -108,6 +113,7 @@
      * this socket will go directly to the underlying network, so its traffic will not be
      * forwarded through the VPN.
      */
+    @UnsupportedAppUsage
     public static boolean protectFromVpn(FileDescriptor fd) {
         return protectFromVpn(fd.getInt$());
     }
@@ -126,51 +132,135 @@
     public native static boolean queryUserAccess(int uid, int netId);
 
     /**
-     * Convert a IPv4 address from an integer to an InetAddress.
-     * @param hostAddress an int corresponding to the IPv4 address in network byte order
+     * Add an entry into the ARP cache.
      */
+    public static void addArpEntry(Inet4Address ipv4Addr, MacAddress ethAddr, String ifname,
+            FileDescriptor fd) throws IOException {
+        addArpEntry(ethAddr.toByteArray(), ipv4Addr.getAddress(), ifname, fd);
+    }
+
+    private static native void addArpEntry(byte[] ethAddr, byte[] netAddr, String ifname,
+            FileDescriptor fd) throws IOException;
+
+    /**
+     * @see #intToInet4AddressHTL(int)
+     * @deprecated Use either {@link #intToInet4AddressHTH(int)}
+     *             or {@link #intToInet4AddressHTL(int)}
+     */
+    @Deprecated
+    @UnsupportedAppUsage
     public static InetAddress intToInetAddress(int hostAddress) {
-        byte[] addressBytes = { (byte)(0xff & hostAddress),
-                                (byte)(0xff & (hostAddress >> 8)),
-                                (byte)(0xff & (hostAddress >> 16)),
-                                (byte)(0xff & (hostAddress >> 24)) };
+        return intToInet4AddressHTL(hostAddress);
+    }
+
+    /**
+     * Convert a IPv4 address from an integer to an InetAddress (0x04030201 -> 1.2.3.4)
+     *
+     * <p>This method uses the higher-order int bytes as the lower-order IPv4 address bytes,
+     * which is an unusual convention. Consider {@link #intToInet4AddressHTH(int)} instead.
+     * @param hostAddress an int coding for an IPv4 address, where higher-order int byte is
+     *                    lower-order IPv4 address byte
+     */
+    public static Inet4Address intToInet4AddressHTL(int hostAddress) {
+        return intToInet4AddressHTH(Integer.reverseBytes(hostAddress));
+    }
+
+    /**
+     * Convert a IPv4 address from an integer to an InetAddress (0x01020304 -> 1.2.3.4)
+     * @param hostAddress an int coding for an IPv4 address
+     */
+    public static Inet4Address intToInet4AddressHTH(int hostAddress) {
+        byte[] addressBytes = { (byte) (0xff & (hostAddress >> 24)),
+                (byte) (0xff & (hostAddress >> 16)),
+                (byte) (0xff & (hostAddress >> 8)),
+                (byte) (0xff & hostAddress) };
 
         try {
-           return InetAddress.getByAddress(addressBytes);
+            return (Inet4Address) InetAddress.getByAddress(addressBytes);
         } catch (UnknownHostException e) {
-           throw new AssertionError();
+            throw new AssertionError();
         }
     }
 
     /**
-     * Convert a IPv4 address from an InetAddress to an integer
-     * @param inetAddr is an InetAddress corresponding to the IPv4 address
-     * @return the IP address as an integer in network byte order
+     * @see #inet4AddressToIntHTL(Inet4Address)
+     * @deprecated Use either {@link #inet4AddressToIntHTH(Inet4Address)}
+     *             or {@link #inet4AddressToIntHTL(Inet4Address)}
      */
+    @Deprecated
     public static int inetAddressToInt(Inet4Address inetAddr)
             throws IllegalArgumentException {
-        byte [] addr = inetAddr.getAddress();
-        return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
-                ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
+        return inet4AddressToIntHTL(inetAddr);
     }
 
     /**
-     * Convert a network prefix length to an IPv4 netmask integer
-     * @param prefixLength
-     * @return the IPv4 netmask as an integer in network byte order
+     * Convert an IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x01020304)
+     *
+     * <p>This conversion can help order IP addresses: considering the ordering
+     * 192.0.2.1 < 192.0.2.2 < ..., resulting ints will follow that ordering if read as unsigned
+     * integers with {@link Integer#toUnsignedLong}.
+     * @param inetAddr is an InetAddress corresponding to the IPv4 address
+     * @return the IP address as integer
      */
+    public static int inet4AddressToIntHTH(Inet4Address inetAddr)
+            throws IllegalArgumentException {
+        byte [] addr = inetAddr.getAddress();
+        return ((addr[0] & 0xff) << 24) | ((addr[1] & 0xff) << 16)
+                | ((addr[2] & 0xff) << 8) | (addr[3] & 0xff);
+    }
+
+    /**
+     * Convert a IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x04030201)
+     *
+     * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes,
+     * which is an unusual convention. Consider {@link #inet4AddressToIntHTH(Inet4Address)} instead.
+     * @param inetAddr is an InetAddress corresponding to the IPv4 address
+     * @return the IP address as integer
+     */
+    public static int inet4AddressToIntHTL(Inet4Address inetAddr) {
+        return Integer.reverseBytes(inet4AddressToIntHTH(inetAddr));
+    }
+
+    /**
+     * @see #prefixLengthToV4NetmaskIntHTL(int)
+     * @deprecated Use either {@link #prefixLengthToV4NetmaskIntHTH(int)}
+     *             or {@link #prefixLengthToV4NetmaskIntHTL(int)}
+     */
+    @Deprecated
+    @UnsupportedAppUsage
     public static int prefixLengthToNetmaskInt(int prefixLength)
             throws IllegalArgumentException {
+        return prefixLengthToV4NetmaskIntHTL(prefixLength);
+    }
+
+    /**
+     * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0xffff8000)
+     * @return the IPv4 netmask as an integer
+     */
+    public static int prefixLengthToV4NetmaskIntHTH(int prefixLength)
+            throws IllegalArgumentException {
         if (prefixLength < 0 || prefixLength > 32) {
             throw new IllegalArgumentException("Invalid prefix length (0 <= prefix <= 32)");
         }
-        int value = 0xffffffff << (32 - prefixLength);
-        return Integer.reverseBytes(value);
+        // (int)a << b is equivalent to a << (b & 0x1f): can't shift by 32 (-1 << 32 == -1)
+        return prefixLength == 0 ? 0 : 0xffffffff << (32 - prefixLength);
+    }
+
+    /**
+     * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0x0080ffff).
+     *
+     * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes,
+     * which is an unusual convention. Consider {@link #prefixLengthToV4NetmaskIntHTH(int)} instead.
+     * @return the IPv4 netmask as an integer
+     */
+    public static int prefixLengthToV4NetmaskIntHTL(int prefixLength)
+            throws IllegalArgumentException {
+        return Integer.reverseBytes(prefixLengthToV4NetmaskIntHTH(prefixLength));
     }
 
     /**
      * Convert a IPv4 netmask integer to a prefix length
-     * @param netmask as an integer in network byte order
+     * @param netmask as an integer (0xff000000 for a /8 subnet)
      * @return the network prefix length
      */
     public static int netmaskIntToPrefixLength(int netmask) {
@@ -184,6 +274,7 @@
      * @throws IllegalArgumentException the specified netmask was not contiguous.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int netmaskToPrefixLength(Inet4Address netmask) {
         // inetAddressToInt returns an int in *network* byte order.
         int i = Integer.reverseBytes(inetAddressToInt(netmask));
@@ -204,6 +295,7 @@
      * @return the InetAddress
      * @hide
      */
+    @UnsupportedAppUsage
     public static InetAddress numericToInetAddress(String addrString)
             throws IllegalArgumentException {
         return InetAddress.parseNumericAddress(addrString);
@@ -278,6 +370,7 @@
     /**
      * Returns the implicit netmask of an IPv4 address, as was the custom before 1993.
      */
+    @UnsupportedAppUsage
     public static int getImplicitNetmask(Inet4Address address) {
         int firstByte = address.getAddress()[0] & 0xff;  // Convert to an unsigned value.
         if (firstByte < 128) {
@@ -316,6 +409,28 @@
     }
 
     /**
+     * Get a prefix mask as Inet4Address for a given prefix length.
+     *
+     * <p>For example 20 -> 255.255.240.0
+     */
+    public static Inet4Address getPrefixMaskAsInet4Address(int prefixLength)
+            throws IllegalArgumentException {
+        return intToInet4AddressHTH(prefixLengthToV4NetmaskIntHTH(prefixLength));
+    }
+
+    /**
+     * Get the broadcast address for a given prefix.
+     *
+     * <p>For example 192.168.0.1/24 -> 192.168.0.255
+     */
+    public static Inet4Address getBroadcastAddress(Inet4Address addr, int prefixLength)
+            throws IllegalArgumentException {
+        final int intBroadcastAddr = inet4AddressToIntHTH(addr)
+                | ~prefixLengthToV4NetmaskIntHTH(prefixLength);
+        return intToInet4AddressHTH(intBroadcastAddr);
+    }
+
+    /**
      * Check if IP address type is consistent between two InetAddress.
      * @return true if both are the same type.  False otherwise.
      */
@@ -368,6 +483,7 @@
      * @param addr a string representing an ip addr
      * @return a string propertly trimmed
      */
+    @UnsupportedAppUsage
     public static String trimV4AddrZeros(String addr) {
         if (addr == null) return null;
         String[] octets = addr.split("\\.");
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 3cd37bf..fee91fbb 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -1,8 +1,20 @@
 set noparent
 
+codewiz@google.com
 ek@google.com
 jsharkey@android.com
 jchalard@google.com
 lorenzo@google.com
+reminv@google.com
 satk@google.com
 silberst@google.com
+
+per-file SSL*=flooey@google.com
+per-file SSL*=narayan@google.com
+per-file SSL*=tobiast@google.com
+per-file Uri*=flooey@google.com
+per-file Uri*=narayan@google.com
+per-file Uri*=tobiast@google.com
+per-file Url*=flooey@google.com
+per-file Url*=narayan@google.com
+per-file Url*=tobiast@google.com
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index e3551b0..4600942 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.Log;
@@ -106,6 +107,7 @@
      *         A null value means that no host is to be used.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final java.net.Proxy getProxy(Context ctx, String url) {
         String host = "";
         if ((url != null) && !isLocalHost(host)) {
@@ -239,6 +241,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final void setHttpProxySystemProperty(ProxyInfo p) {
         String host = null;
         String port = null;
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index 5f5e623..e926fda 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -17,6 +17,7 @@
 package android.net;
 
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -91,6 +92,7 @@
      * Create a ProxyProperties that points at a HTTP Proxy.
      * @hide
      */
+    @UnsupportedAppUsage
     public ProxyInfo(String host, int port, String exclList) {
         mHost = host;
         mPort = port;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 90a2460..3e73d3d 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -55,6 +56,7 @@
     /**
      * The gateway address for this route.
      */
+    @UnsupportedAppUsage
     private final InetAddress mGateway;
 
     /**
@@ -79,6 +81,7 @@
 
     // Derived data members.
     // TODO: remove these.
+    @UnsupportedAppUsage
     private final boolean mIsHost;
     private final boolean mHasGateway;
 
@@ -160,6 +163,7 @@
     /**
      *  @hide
      */
+    @UnsupportedAppUsage
     public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
         this(destination, gateway, iface, RTN_UNICAST);
     }
@@ -167,6 +171,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
         this(destination == null ? null :
                 new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
@@ -197,6 +202,7 @@
      *
      * TODO: Remove this.
      */
+    @UnsupportedAppUsage
     public RouteInfo(LinkAddress destination, InetAddress gateway) {
         this(destination, gateway, null);
     }
@@ -208,6 +214,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public RouteInfo(InetAddress gateway) {
         this((IpPrefix) null, gateway, null);
     }
@@ -258,6 +265,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private boolean isHost() {
         return (mDestination.getAddress() instanceof Inet4Address &&
                 mDestination.getPrefixLength() == 32) ||
@@ -355,6 +363,7 @@
      * @return {@code true} if a gateway is specified
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean hasGateway() {
         return mHasGateway;
     }
@@ -379,6 +388,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
         if ((routes == null) || (dest == null)) return null;
 
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 1f53587..31494d9 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.SystemProperties;
 import android.util.Log;
 
@@ -73,17 +74,23 @@
  * Updating Your Security Provider to Protect Against SSL Exploits</a>
  * for further information.</p>
  *
- * <p>One way to verify the server's identity is to use
+ * <p>The recommended way to verify the server's identity is to use
  * {@link HttpsURLConnection#getDefaultHostnameVerifier()} to get a
  * {@link HostnameVerifier} to verify the certificate hostname.
  *
+ * <p><b>Warning</b>: Some methods on this class return connected sockets and some return
+ * unconnected sockets.  For the methods that return connected sockets, setting
+ * connection- or handshake-related properties on those sockets will have no effect.
+ *
  * <p>On development devices, "setprop socket.relaxsslcheck yes" bypasses all
  * SSL certificate and hostname checks for testing purposes.  This setting
  * requires root access.
  */
 public class SSLCertificateSocketFactory extends SSLSocketFactory {
+    @UnsupportedAppUsage
     private static final String TAG = "SSLCertificateSocketFactory";
 
+    @UnsupportedAppUsage
     private static final TrustManager[] INSECURE_TRUST_MANAGER = new TrustManager[] {
         new X509TrustManager() {
             public X509Certificate[] getAcceptedIssuers() { return null; }
@@ -92,16 +99,26 @@
         }
     };
 
+    @UnsupportedAppUsage
     private SSLSocketFactory mInsecureFactory = null;
+    @UnsupportedAppUsage
     private SSLSocketFactory mSecureFactory = null;
+    @UnsupportedAppUsage
     private TrustManager[] mTrustManagers = null;
+    @UnsupportedAppUsage
     private KeyManager[] mKeyManagers = null;
+    @UnsupportedAppUsage
     private byte[] mNpnProtocols = null;
+    @UnsupportedAppUsage
     private byte[] mAlpnProtocols = null;
+    @UnsupportedAppUsage
     private PrivateKey mChannelIdPrivateKey = null;
 
+    @UnsupportedAppUsage
     private final int mHandshakeTimeoutMillis;
+    @UnsupportedAppUsage
     private final SSLClientSessionCache mSessionCache;
+    @UnsupportedAppUsage
     private final boolean mSecure;
 
     /** @deprecated Use {@link #getDefault(int)} instead. */
@@ -110,6 +127,7 @@
         this(handshakeTimeoutMillis, null, true);
     }
 
+    @UnsupportedAppUsage
     private SSLCertificateSocketFactory(
             int handshakeTimeoutMillis, SSLSessionCache cache, boolean secure) {
         mHandshakeTimeoutMillis = handshakeTimeoutMillis;
@@ -197,6 +215,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void verifyHostname(Socket socket, String hostname) throws IOException {
         if (!(socket instanceof SSLSocket)) {
             throw new IllegalArgumentException("Attempt to verify non-SSL socket");
@@ -218,6 +237,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private SSLSocketFactory makeSocketFactory(
             KeyManager[] keyManagers, TrustManager[] trustManagers) {
         try {
@@ -231,11 +251,13 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static boolean isSslCheckRelaxed() {
         return RoSystemProperties.DEBUGGABLE &&
             SystemProperties.getBoolean("socket.relaxsslcheck", false);
     }
 
+    @UnsupportedAppUsage
     private synchronized SSLSocketFactory getDelegate() {
         // Relax the SSL check if instructed (for this factory, or systemwide)
         if (!mSecure || isSslCheckRelaxed()) {
@@ -307,6 +329,7 @@
      *     must be non-empty and of length less than 256.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setAlpnProtocols(byte[][] protocols) {
         this.mAlpnProtocols = toLengthPrefixedList(protocols);
     }
@@ -361,6 +384,7 @@
      * @throws IllegalArgumentException if the socket was not created by this factory.
      * @hide
      */
+    @UnsupportedAppUsage
     public byte[] getAlpnSelectedProtocol(Socket socket) {
         return castToOpenSSLSocket(socket).getAlpnSelectedProtocol();
     }
@@ -386,6 +410,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setChannelIdPrivateKey(PrivateKey privateKey) {
         mChannelIdPrivateKey = privateKey;
     }
@@ -425,11 +450,13 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSoWriteTimeout(Socket socket, int writeTimeoutMilliseconds)
             throws SocketException {
         castToOpenSSLSocket(socket).setSoWriteTimeout(writeTimeoutMilliseconds);
     }
 
+    @UnsupportedAppUsage
     private static OpenSSLSocketImpl castToOpenSSLSocket(Socket socket) {
         if (!(socket instanceof OpenSSLSocketImpl)) {
             throw new IllegalArgumentException("Socket not created by this factory: "
@@ -442,8 +469,10 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This method verifies the peer's certificate hostname after connecting
-     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
+     * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's
+     * certificate hostname after connecting; if this instance was created with
+     * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i>
+     * instead.
      */
     @Override
     public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException {
@@ -459,7 +488,7 @@
     }
 
     /**
-     * Creates a new socket which is not connected to any remote host.
+     * Creates a new socket which is <i>not connected</i> to any remote host.
      * You must use {@link Socket#connect} to connect the socket.
      *
      * <p class="caution"><b>Warning:</b> Hostname verification is not performed
@@ -479,6 +508,8 @@
     /**
      * {@inheritDoc}
      *
+     * <p>This method returns a socket that is <i>not connected</i>.
+     *
      * <p class="caution"><b>Warning:</b> Hostname verification is not performed
      * with this method.  You MUST verify the server's identity after connecting
      * the socket to avoid man-in-the-middle attacks.</p>
@@ -498,6 +529,8 @@
     /**
      * {@inheritDoc}
      *
+     * <p>This method returns a socket that is <i>not connected</i>.
+     *
      * <p class="caution"><b>Warning:</b> Hostname verification is not performed
      * with this method.  You MUST verify the server's identity after connecting
      * the socket to avoid man-in-the-middle attacks.</p>
@@ -515,8 +548,10 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This method verifies the peer's certificate hostname after connecting
-     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
+     * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's
+     * certificate hostname after connecting; if this instance was created with
+     * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i>
+     * instead.
      */
     @Override
     public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
@@ -536,8 +571,10 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This method verifies the peer's certificate hostname after connecting
-     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
+     * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's
+     * certificate hostname after connecting; if this instance was created with
+     * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i>
+     * instead.
      */
     @Override
     public Socket createSocket(String host, int port) throws IOException {
diff --git a/core/java/android/net/SSLSessionCache.java b/core/java/android/net/SSLSessionCache.java
index 65db2c3..9667e82 100644
--- a/core/java/android/net/SSLSessionCache.java
+++ b/core/java/android/net/SSLSessionCache.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.util.Log;
 
@@ -39,6 +40,7 @@
  */
 public final class SSLSessionCache {
     private static final String TAG = "SSLSessionCache";
+    @UnsupportedAppUsage
     /* package */ final SSLClientSessionCache mSessionCache;
 
     /**
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index ddf63ca..10c0ce2 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.SystemClock;
 import android.util.Log;
 
@@ -175,6 +176,7 @@
     }
 
     @Deprecated
+    @UnsupportedAppUsage
     public boolean requestTime(String host, int timeout) {
         Log.w(TAG, "Shame on you for calling the hidden API requestTime()!");
         return false;
@@ -185,6 +187,7 @@
      *
      * @return time value computed from NTP server response.
      */
+    @UnsupportedAppUsage
     public long getNtpTime() {
         return mNtpTime;
     }
@@ -195,6 +198,7 @@
      *
      * @return reference clock corresponding to the NTP time.
      */
+    @UnsupportedAppUsage
     public long getNtpTimeReference() {
         return mNtpTimeReference;
     }
@@ -204,6 +208,7 @@
      *
      * @return round trip time in milliseconds.
      */
+    @UnsupportedAppUsage
     public long getRoundTripTime() {
         return mRoundTripTime;
     }
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 58b1b88..3aa56b9 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.LinkAddress;
 import android.os.Parcelable;
 import android.os.Parcel;
@@ -46,11 +47,16 @@
  * @hide
  */
 public class StaticIpConfiguration implements Parcelable {
+    @UnsupportedAppUsage
     public LinkAddress ipAddress;
+    @UnsupportedAppUsage
     public InetAddress gateway;
+    @UnsupportedAppUsage
     public final ArrayList<InetAddress> dnsServers;
+    @UnsupportedAppUsage
     public String domains;
 
+    @UnsupportedAppUsage
     public StaticIpConfiguration() {
         dnsServers = new ArrayList<InetAddress>();
     }
@@ -80,6 +86,7 @@
      * route to the gateway as well. This configuration is arguably invalid, but it used to work
      * in K and earlier, and other OSes appear to accept it.
      */
+    @UnsupportedAppUsage
     public List<RouteInfo> getRoutes(String iface) {
         List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
         if (ipAddress != null) {
diff --git a/core/java/android/net/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java
index cb7f6bf..b5d12f9 100644
--- a/core/java/android/net/StringNetworkSpecifier.java
+++ b/core/java/android/net/StringNetworkSpecifier.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -29,6 +30,7 @@
     /**
      * Arbitrary string used to pass (additional) information to the network factory.
      */
+    @UnsupportedAppUsage
     public final String specifier;
 
     public StringNetworkSpecifier(String specifier) {
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 40d53b7..a463afa 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -19,6 +19,7 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.DownloadManager;
 import android.app.backup.BackupManager;
 import android.app.usage.NetworkStatsManager;
@@ -141,6 +142,7 @@
 
     private static INetworkStatsService sStatsService;
 
+    @UnsupportedAppUsage
     private synchronized static INetworkStatsService getStatsService() {
         if (sStatsService == null) {
             sStatsService = INetworkStatsService.Stub.asInterface(
@@ -329,6 +331,14 @@
 
     /**
      * Remove any statistics parameters from the given {@link Socket}.
+     * <p>
+     * In Android 8.1 (API level 27) and lower, a socket is automatically
+     * untagged when it's sent to another process using binder IPC with a
+     * {@code ParcelFileDescriptor} container. In Android 9.0 (API level 28)
+     * and higher, the socket tag is kept when the socket is sent to another
+     * process using binder IPC. You can mimic the previous behavior by
+     * calling {@code untagSocket()} before sending the socket to another
+     * process.
      */
     public static void untagSocket(Socket socket) throws SocketException {
         SocketTagger.get().untag(socket);
@@ -528,6 +538,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static long getMobileTcpRxPackets() {
         long total = 0;
         for (String iface : getMobileIfaces()) {
@@ -543,6 +554,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static long getMobileTcpTxPackets() {
         long total = 0;
         for (String iface : getMobileIfaces()) {
@@ -576,6 +588,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static long getTxBytes(String iface) {
         try {
             return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES);
@@ -585,6 +598,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static long getRxBytes(String iface) {
         try {
             return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES);
@@ -940,6 +954,7 @@
      * Interfaces are never removed from this list, so counters should always be
      * monotonic.
      */
+    @UnsupportedAppUsage
     private static String[] getMobileIfaces() {
         try {
             return getStatsService().getMobileIfaces();
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 0fb84b7..9bcc600 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.os.Environment;
 import android.os.Parcel;
@@ -24,8 +25,6 @@
 import android.os.StrictMode;
 import android.util.Log;
 
-import libcore.net.UriCodec;
-
 import java.io.File;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
@@ -135,6 +134,7 @@
     /**
      * Prevents external subclassing.
      */
+    @UnsupportedAppUsage
     private Uri() {}
 
     /**
@@ -378,6 +378,7 @@
      * to logs and other places where PII should be avoided.
      * @hide
      */
+    @UnsupportedAppUsage
     public String toSafeString() {
         String scheme = getScheme();
         String ssp = getSchemeSpecificPart();
@@ -1959,7 +1960,8 @@
         if (s == null) {
             return null;
         }
-        return UriCodec.decode(s, false, StandardCharsets.UTF_8, false);
+        return UriCodec.decode(
+                s, false /* convertPlus */, StandardCharsets.UTF_8, false /* throwOnFailure */);
     }
 
     /**
@@ -2332,6 +2334,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Uri getCanonicalUri() {
         if ("file".equals(getScheme())) {
             final String canonicalPath;
diff --git a/core/java/android/net/UriCodec.java b/core/java/android/net/UriCodec.java
new file mode 100644
index 0000000..e1470e0
--- /dev/null
+++ b/core/java/android/net/UriCodec.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import java.net.URISyntaxException;
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * Decodes “application/x-www-form-urlencoded” content.
+ *
+ * @hide
+ */
+public final class UriCodec {
+
+    private UriCodec() {}
+
+    /**
+     * Interprets a char as hex digits, returning a number from -1 (invalid char) to 15 ('f').
+     */
+    private static int hexCharToValue(char c) {
+        if ('0' <= c && c <= '9') {
+            return c - '0';
+        }
+        if ('a' <= c && c <= 'f') {
+            return 10 + c - 'a';
+        }
+        if ('A' <= c && c <= 'F') {
+            return 10 + c - 'A';
+        }
+        return -1;
+    }
+
+    private static URISyntaxException unexpectedCharacterException(
+            String uri, String name, char unexpected, int index) {
+        String nameString = (name == null) ? "" :  " in [" + name + "]";
+        return new URISyntaxException(
+                uri, "Unexpected character" + nameString + ": " + unexpected, index);
+    }
+
+    private static char getNextCharacter(String uri, int index, int end, String name)
+             throws URISyntaxException {
+        if (index >= end) {
+            String nameString = (name == null) ? "" :  " in [" + name + "]";
+            throw new URISyntaxException(
+                    uri, "Unexpected end of string" + nameString, index);
+        }
+        return uri.charAt(index);
+    }
+
+    /**
+     * Decode a string according to the rules of this decoder.
+     *
+     * - if {@code convertPlus == true} all ‘+’ chars in the decoded output are converted to ‘ ‘
+     *   (white space)
+     * - if {@code throwOnFailure == true}, an {@link IllegalArgumentException} is thrown for
+     *   invalid inputs. Else, U+FFFd is emitted to the output in place of invalid input octets.
+     */
+    public static String decode(
+            String s, boolean convertPlus, Charset charset, boolean throwOnFailure) {
+        StringBuilder builder = new StringBuilder(s.length());
+        appendDecoded(builder, s, convertPlus, charset, throwOnFailure);
+        return builder.toString();
+    }
+
+    /**
+     * Character to be output when there's an error decoding an input.
+     */
+    private static final char INVALID_INPUT_CHARACTER = '\ufffd';
+
+    private static void appendDecoded(
+            StringBuilder builder,
+            String s,
+            boolean convertPlus,
+            Charset charset,
+            boolean throwOnFailure) {
+        CharsetDecoder decoder = charset.newDecoder()
+                .onMalformedInput(CodingErrorAction.REPLACE)
+                .replaceWith("\ufffd")
+                .onUnmappableCharacter(CodingErrorAction.REPORT);
+        // Holds the bytes corresponding to the escaped chars being read (empty if the last char
+        // wasn't a escaped char).
+        ByteBuffer byteBuffer = ByteBuffer.allocate(s.length());
+        int i = 0;
+        while (i < s.length()) {
+            char c = s.charAt(i);
+            i++;
+            switch (c) {
+                case '+':
+                    flushDecodingByteAccumulator(
+                            builder, decoder, byteBuffer, throwOnFailure);
+                    builder.append(convertPlus ? ' ' : '+');
+                    break;
+                case '%':
+                    // Expect two characters representing a number in hex.
+                    byte hexValue = 0;
+                    for (int j = 0; j < 2; j++) {
+                        try {
+                            c = getNextCharacter(s, i, s.length(), null /* name */);
+                        } catch (URISyntaxException e) {
+                            // Unexpected end of input.
+                            if (throwOnFailure) {
+                                throw new IllegalArgumentException(e);
+                            } else {
+                                flushDecodingByteAccumulator(
+                                        builder, decoder, byteBuffer, throwOnFailure);
+                                builder.append(INVALID_INPUT_CHARACTER);
+                                return;
+                            }
+                        }
+                        i++;
+                        int newDigit = hexCharToValue(c);
+                        if (newDigit < 0) {
+                            if (throwOnFailure) {
+                                throw new IllegalArgumentException(
+                                        unexpectedCharacterException(s, null /* name */, c, i - 1));
+                            } else {
+                                flushDecodingByteAccumulator(
+                                        builder, decoder, byteBuffer, throwOnFailure);
+                                builder.append(INVALID_INPUT_CHARACTER);
+                                break;
+                            }
+                        }
+                        hexValue = (byte) (hexValue * 0x10 + newDigit);
+                    }
+                    byteBuffer.put(hexValue);
+                    break;
+                default:
+                    flushDecodingByteAccumulator(builder, decoder, byteBuffer, throwOnFailure);
+                    builder.append(c);
+            }
+        }
+        flushDecodingByteAccumulator(builder, decoder, byteBuffer, throwOnFailure);
+    }
+
+    private static void flushDecodingByteAccumulator(
+            StringBuilder builder,
+            CharsetDecoder decoder,
+            ByteBuffer byteBuffer,
+            boolean throwOnFailure) {
+        if (byteBuffer.position() == 0) {
+            return;
+        }
+        byteBuffer.flip();
+        try {
+            builder.append(decoder.decode(byteBuffer));
+        } catch (CharacterCodingException e) {
+            if (throwOnFailure) {
+                throw new IllegalArgumentException(e);
+            } else {
+                builder.append(INVALID_INPUT_CHARACTER);
+            }
+        } finally {
+            // Use the byte buffer to write again.
+            byteBuffer.flip();
+            byteBuffer.limit(byteBuffer.capacity());
+        }
+    }
+}
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 712576f..f0c0462 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -21,6 +21,7 @@
 
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.app.Service;
@@ -440,7 +441,9 @@
     public class Builder {
 
         private final VpnConfig mConfig = new VpnConfig();
+        @UnsupportedAppUsage
         private final List<LinkAddress> mAddresses = new ArrayList<LinkAddress>();
+        @UnsupportedAppUsage
         private final List<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
 
         public Builder() {
diff --git a/core/java/android/net/WebAddress.java b/core/java/android/net/WebAddress.java
index 24d4eb8..8026d76 100644
--- a/core/java/android/net/WebAddress.java
+++ b/core/java/android/net/WebAddress.java
@@ -19,6 +19,7 @@
 import static android.util.Patterns.GOOD_IRI_CHAR;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 
 import java.util.Locale;
 import java.util.regex.Matcher;
@@ -45,9 +46,13 @@
 @SystemApi
 public class WebAddress {
 
+    @UnsupportedAppUsage
     private String mScheme;
+    @UnsupportedAppUsage
     private String mHost;
+    @UnsupportedAppUsage
     private int mPort;
+    @UnsupportedAppUsage
     private String mPath;
     private String mAuthInfo;
 
@@ -147,16 +152,19 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public String getScheme() {
       return mScheme;
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public void setHost(String host) {
       mHost = host;
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public String getHost() {
       return mHost;
     }
@@ -167,16 +175,19 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public int getPort() {
       return mPort;
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public void setPath(String path) {
       mPath = path;
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public String getPath() {
       return mPath;
     }
@@ -187,6 +198,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public String getAuthInfo() {
       return mAuthInfo;
     }
diff --git a/core/java/android/net/http/HttpResponseCache.java b/core/java/android/net/http/HttpResponseCache.java
index 729aff0..7da76d1 100644
--- a/core/java/android/net/http/HttpResponseCache.java
+++ b/core/java/android/net/http/HttpResponseCache.java
@@ -16,9 +16,8 @@
 
 package android.net.http;
 
-import com.android.okhttp.Cache;
-import com.android.okhttp.AndroidShimResponseCache;
-import com.android.okhttp.OkCacheContainer;
+import com.android.okhttp.internalandroidapi.AndroidResponseCacheAdapter;
+import com.android.okhttp.internalandroidapi.HasCacheHolder;
 
 import java.io.Closeable;
 import java.io.File;
@@ -149,12 +148,12 @@
  *       } catch (Exception httpResponseCacheNotAvailable) {
  *       }}</pre>
  */
-public final class HttpResponseCache extends ResponseCache implements Closeable, OkCacheContainer {
+public final class HttpResponseCache extends ResponseCache implements HasCacheHolder, Closeable {
 
-    private final AndroidShimResponseCache delegate;
+    private final AndroidResponseCacheAdapter mDelegate;
 
-    private HttpResponseCache(AndroidShimResponseCache delegate) {
-        this.delegate = delegate;
+    private HttpResponseCache(AndroidResponseCacheAdapter delegate) {
+        mDelegate = delegate;
     }
 
     /**
@@ -184,30 +183,33 @@
         ResponseCache installed = ResponseCache.getDefault();
         if (installed instanceof HttpResponseCache) {
             HttpResponseCache installedResponseCache = (HttpResponseCache) installed;
+            CacheHolder cacheHolder = installedResponseCache.getCacheHolder();
             // don't close and reopen if an equivalent cache is already installed
-            AndroidShimResponseCache trueResponseCache = installedResponseCache.delegate;
-            if (trueResponseCache.isEquivalent(directory, maxSize)) {
+            if (cacheHolder.isEquivalent(directory, maxSize)) {
                 return installedResponseCache;
             } else {
                 // The HttpResponseCache that owns this object is about to be replaced.
-                trueResponseCache.close();
+                installedResponseCache.close();
             }
         }
 
-        AndroidShimResponseCache trueResponseCache =
-                AndroidShimResponseCache.create(directory, maxSize);
-        HttpResponseCache newResponseCache = new HttpResponseCache(trueResponseCache);
-        ResponseCache.setDefault(newResponseCache);
-        return newResponseCache;
+        CacheHolder cacheHolder = CacheHolder.create(directory, maxSize);
+        AndroidResponseCacheAdapter androidResponseCacheAdapter =
+                new AndroidResponseCacheAdapter(cacheHolder);
+        HttpResponseCache responseCache = new HttpResponseCache(androidResponseCacheAdapter);
+        ResponseCache.setDefault(responseCache);
+        return responseCache;
     }
 
-    @Override public CacheResponse get(URI uri, String requestMethod,
+    @Override
+    public CacheResponse get(URI uri, String requestMethod,
             Map<String, List<String>> requestHeaders) throws IOException {
-        return delegate.get(uri, requestMethod, requestHeaders);
+        return mDelegate.get(uri, requestMethod, requestHeaders);
     }
 
-    @Override public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
-        return delegate.put(uri, urlConnection);
+    @Override
+    public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
+        return mDelegate.put(uri, urlConnection);
     }
 
     /**
@@ -217,7 +219,7 @@
      */
     public long size() {
         try {
-            return delegate.size();
+            return mDelegate.getSize();
         } catch (IOException e) {
             // This can occur if the cache failed to lazily initialize.
             return -1;
@@ -229,7 +231,7 @@
      * its data.
      */
     public long maxSize() {
-        return delegate.maxSize();
+        return mDelegate.getMaxSize();
     }
 
     /**
@@ -239,7 +241,7 @@
      */
     public void flush() {
         try {
-            delegate.flush();
+            mDelegate.flush();
         } catch (IOException ignored) {
         }
     }
@@ -249,7 +251,7 @@
      * supply a response or validate a locally cached response.
      */
     public int getNetworkCount() {
-        return delegate.getNetworkCount();
+        return mDelegate.getNetworkCount();
     }
 
     /**
@@ -258,7 +260,7 @@
      * validated over the network.
      */
     public int getHitCount() {
-        return delegate.getHitCount();
+        return mDelegate.getHitCount();
     }
 
     /**
@@ -267,18 +269,19 @@
      * to handle a redirects and retries.
      */
     public int getRequestCount() {
-        return delegate.getRequestCount();
+        return mDelegate.getRequestCount();
     }
 
     /**
      * Uninstalls the cache and releases any active resources. Stored contents
      * will remain on the filesystem.
      */
-    @Override public void close() throws IOException {
+    @Override
+    public void close() throws IOException {
         if (ResponseCache.getDefault() == this) {
             ResponseCache.setDefault(null);
         }
-        delegate.close();
+        mDelegate.close();
     }
 
     /**
@@ -288,13 +291,12 @@
         if (ResponseCache.getDefault() == this) {
             ResponseCache.setDefault(null);
         }
-        delegate.delete();
+        mDelegate.delete();
     }
 
     /** @hide Needed for OkHttp integration. */
     @Override
-    public Cache getCache() {
-        return delegate.getCache();
+    public CacheHolder getCacheHolder() {
+        return mDelegate.getCacheHolder();
     }
-
 }
diff --git a/core/java/android/net/http/OWNERS b/core/java/android/net/http/OWNERS
new file mode 100644
index 0000000..6b8c9ed
--- /dev/null
+++ b/core/java/android/net/http/OWNERS
@@ -0,0 +1,3 @@
+flooey@google.com
+narayan@google.com
+tobiast@google.com
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index 4c0f418..6fcd6eb 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -16,8 +16,7 @@
 
 package android.net.http;
 
-import com.android.internal.util.HexDump;
-
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Bundle;
 import android.text.format.DateFormat;
@@ -25,6 +24,9 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.internal.util.HexDump;
+import com.android.org.bouncycastle.asn1.x509.X509Name;
+
 import java.io.ByteArrayInputStream;
 import java.math.BigInteger;
 import java.security.MessageDigest;
@@ -39,8 +41,6 @@
 import java.util.Date;
 import java.util.Vector;
 
-import com.android.org.bouncycastle.asn1.x509.X509Name;
-
 /**
  * SSL certificate info (certificate details) class
  */
@@ -78,6 +78,7 @@
      * be available, and saveState and restoreState can be simplified
      * to be unconditional.
      */
+    @UnsupportedAppUsage
     private final X509Certificate mX509Certificate;
 
     /**
@@ -248,8 +249,17 @@
     }
 
     /**
+     * @return The {@code X509Certificate} used to create this {@code SslCertificate} or
+     * {@code null} if no certificate was provided.
+     */
+    public X509Certificate getX509Certificate() {
+        return mX509Certificate;
+    }
+
+    /**
      * Convenience for UI presentation, not intended as public API.
      */
+    @UnsupportedAppUsage
     private static String getSerialNumber(X509Certificate x509Certificate) {
         if (x509Certificate == null) {
             return "";
@@ -264,6 +274,7 @@
     /**
      * Convenience for UI presentation, not intended as public API.
      */
+    @UnsupportedAppUsage
     private static String getDigest(X509Certificate x509Certificate, String algorithm) {
         if (x509Certificate == null) {
             return "";
@@ -447,6 +458,7 @@
      *
      * @hide Used by Browser and Settings
      */
+    @UnsupportedAppUsage
     public View inflateCertificateView(Context context) {
         LayoutInflater factory = LayoutInflater.from(context);
 
diff --git a/core/java/android/net/http/SslError.java b/core/java/android/net/http/SslError.java
index 1cd73d2..fad6689 100644
--- a/core/java/android/net/http/SslError.java
+++ b/core/java/android/net/http/SslError.java
@@ -16,6 +16,7 @@
 
 package android.net.http;
 
+import android.annotation.UnsupportedAppUsage;
 import java.security.cert.X509Certificate;
 
 /**
@@ -67,16 +68,19 @@
      * The SSL error set bitfield (each individual error is a bit index;
      * multiple individual errors can be OR-ed)
      */
+    @UnsupportedAppUsage
     int mErrors;
 
     /**
      * The SSL certificate associated with the error set
      */
+    @UnsupportedAppUsage
     final SslCertificate mCertificate;
 
     /**
      * The URL associated with the error set.
      */
+    @UnsupportedAppUsage
     final String mUrl;
 
     /**
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index ad4588f..5dabf35 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -17,6 +17,7 @@
 package android.net.metrics;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -47,13 +48,20 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface Flags {}
 
+    @UnsupportedAppUsage
     public long lifetime;       // Maximum computed lifetime of the program in seconds
+    @UnsupportedAppUsage
     public long actualLifetime; // Effective program lifetime in seconds
+    @UnsupportedAppUsage
     public int filteredRas;     // Number of RAs filtered by the APF program
+    @UnsupportedAppUsage
     public int currentRas;      // Total number of current RAs at generation time
+    @UnsupportedAppUsage
     public int programLength;   // Length of the APF program in bytes
+    @UnsupportedAppUsage
     public int flags;           // Bitfield compound of FLAG_* constants
 
+    @UnsupportedAppUsage
     public ApfProgramEvent() {
     }
 
@@ -99,6 +107,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     public static @Flags int flagsFor(boolean hasIPv4, boolean multicastFilterOn) {
         int bitfield = 0;
         if (hasIPv4) {
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index 76a781d..bb2a35c 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -16,6 +16,7 @@
 
 package android.net.metrics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -26,26 +27,37 @@
 public final class ApfStats implements Parcelable {
 
     /** time interval in milliseconds these stastistics covers. */
+    @UnsupportedAppUsage
     public long durationMs;
     /** number of received RAs. */
+    @UnsupportedAppUsage
     public int receivedRas;
     /** number of received RAs matching a known RA. */
+    @UnsupportedAppUsage
     public int matchingRas;
     /** number of received RAs ignored due to the MAX_RAS limit. */
+    @UnsupportedAppUsage
     public int droppedRas;
     /** number of received RAs with a minimum lifetime of 0. */
+    @UnsupportedAppUsage
     public int zeroLifetimeRas;
     /** number of received RAs that could not be parsed. */
+    @UnsupportedAppUsage
     public int parseErrors;
     /** number of APF program updates from receiving RAs.. */
+    @UnsupportedAppUsage
     public int programUpdates;
     /** total number of APF program updates. */
+    @UnsupportedAppUsage
     public int programUpdatesAll;
     /** number of APF program updates from allowing multicast traffic. */
+    @UnsupportedAppUsage
     public int programUpdatesAllowingMulticast;
     /** maximum APF program size advertised by hardware. */
+    @UnsupportedAppUsage
     public int maxProgramSize;
 
+    @UnsupportedAppUsage
     public ApfStats() {
     }
 
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index c5b78a5..98a7d7e 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -16,6 +16,7 @@
 
 package android.net.metrics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -34,6 +35,7 @@
     public final String msg;
     public final int durationMs;
 
+    @UnsupportedAppUsage
     public DhcpClientEvent(String msg, int durationMs) {
         this.msg = msg;
         this.durationMs = durationMs;
diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java
index 8b77197..c6c06f0 100644
--- a/core/java/android/net/metrics/DhcpErrorEvent.java
+++ b/core/java/android/net/metrics/DhcpErrorEvent.java
@@ -16,6 +16,7 @@
 
 package android.net.metrics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -33,25 +34,41 @@
     public static final int DHCP_ERROR = 4;
     public static final int MISC_ERROR = 5;
 
+    @UnsupportedAppUsage
     public static final int L2_TOO_SHORT               = makeErrorCode(L2_ERROR, 1);
+    @UnsupportedAppUsage
     public static final int L2_WRONG_ETH_TYPE          = makeErrorCode(L2_ERROR, 2);
 
+    @UnsupportedAppUsage
     public static final int L3_TOO_SHORT               = makeErrorCode(L3_ERROR, 1);
+    @UnsupportedAppUsage
     public static final int L3_NOT_IPV4                = makeErrorCode(L3_ERROR, 2);
+    @UnsupportedAppUsage
     public static final int L3_INVALID_IP              = makeErrorCode(L3_ERROR, 3);
 
+    @UnsupportedAppUsage
     public static final int L4_NOT_UDP                 = makeErrorCode(L4_ERROR, 1);
+    @UnsupportedAppUsage
     public static final int L4_WRONG_PORT              = makeErrorCode(L4_ERROR, 2);
 
+    @UnsupportedAppUsage
     public static final int BOOTP_TOO_SHORT            = makeErrorCode(DHCP_ERROR, 1);
+    @UnsupportedAppUsage
     public static final int DHCP_BAD_MAGIC_COOKIE      = makeErrorCode(DHCP_ERROR, 2);
+    @UnsupportedAppUsage
     public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3);
+    @UnsupportedAppUsage
     public static final int DHCP_NO_MSG_TYPE           = makeErrorCode(DHCP_ERROR, 4);
+    @UnsupportedAppUsage
     public static final int DHCP_UNKNOWN_MSG_TYPE      = makeErrorCode(DHCP_ERROR, 5);
+    @UnsupportedAppUsage
     public static final int DHCP_NO_COOKIE             = makeErrorCode(DHCP_ERROR, 6);
 
+    @UnsupportedAppUsage
     public static final int BUFFER_UNDERFLOW           = makeErrorCode(MISC_ERROR, 1);
+    @UnsupportedAppUsage
     public static final int RECEIVE_ERROR              = makeErrorCode(MISC_ERROR, 2);
+    @UnsupportedAppUsage
     public static final int PARSING_ERROR              = makeErrorCode(MISC_ERROR, 3);
 
     // error code byte format (MSB to LSB):
@@ -61,6 +78,7 @@
     // byte 3: optional code
     public final int errorCode;
 
+    @UnsupportedAppUsage
     public DhcpErrorEvent(int errorCode) {
         this.errorCode = errorCode;
     }
@@ -90,6 +108,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     public static int errorCodeWithOption(int errorCode, int option) {
         return (0xFFFF0000 & errorCode) | (0xFF & option);
     }
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index 4e57efa..998f4ba 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -16,6 +16,7 @@
 
 package android.net.metrics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.ConnectivityMetricsEvent;
 import android.net.IIpConnectivityMetrics;
 import android.os.Parcelable;
@@ -37,6 +38,7 @@
 
     private IIpConnectivityMetrics mService;
 
+    @UnsupportedAppUsage
     public IpConnectivityLog() {
     }
 
@@ -104,6 +106,7 @@
      * @param data is a Parcelable instance representing the event.
      * @return true if the event was successfully logged.
      */
+    @UnsupportedAppUsage
     public boolean log(String ifname, Parcelable data) {
         ConnectivityMetricsEvent ev = makeEv(data);
         ev.ifname = ifname;
@@ -130,6 +133,7 @@
      * @param data is a Parcelable instance representing the event.
      * @return true if the event was successfully logged.
      */
+    @UnsupportedAppUsage
     public boolean log(Parcelable data) {
         return log(makeEv(data));
     }
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index f8a63ce..c47650f 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -17,6 +17,7 @@
 package android.net.metrics;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -53,6 +54,7 @@
     public final @EventType int eventType;
     public final long durationMs;
 
+    @UnsupportedAppUsage
     public IpManagerEvent(@EventType int eventType, long duration) {
         this.eventType = eventType;
         this.durationMs = duration;
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
index 019c2c5..715c95e 100644
--- a/core/java/android/net/metrics/IpReachabilityEvent.java
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -16,6 +16,7 @@
 
 package android.net.metrics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -48,6 +49,7 @@
     // byte 3: when byte 2 == PROBE, errno code from RTNetlink or IpReachabilityMonitor.
     public final int eventType;
 
+    @UnsupportedAppUsage
     public IpReachabilityEvent(int eventType) {
         this.eventType = eventType;
     }
@@ -80,6 +82,7 @@
     /**
      * Returns the NUD failure event type code corresponding to the given conditions.
      */
+    @UnsupportedAppUsage
     public static int nudFailureEventType(boolean isFromProbe, boolean isProvisioningLost) {
         if (isFromProbe) {
             return isProvisioningLost ? PROVISIONING_LOST : NUD_FAILED;
diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java
index 3249f80..c41881c 100644
--- a/core/java/android/net/metrics/RaEvent.java
+++ b/core/java/android/net/metrics/RaEvent.java
@@ -16,6 +16,7 @@
 
 package android.net.metrics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -101,39 +102,47 @@
         long rdnssLifetime           = NO_LIFETIME;
         long dnsslLifetime           = NO_LIFETIME;
 
+        @UnsupportedAppUsage
         public Builder() {
         }
 
+        @UnsupportedAppUsage
         public RaEvent build() {
             return new RaEvent(routerLifetime, prefixValidLifetime, prefixPreferredLifetime,
                     routeInfoLifetime, rdnssLifetime, dnsslLifetime);
         }
 
+        @UnsupportedAppUsage
         public Builder updateRouterLifetime(long lifetime) {
             routerLifetime = updateLifetime(routerLifetime, lifetime);
             return this;
         }
 
+        @UnsupportedAppUsage
         public Builder updatePrefixValidLifetime(long lifetime) {
             prefixValidLifetime = updateLifetime(prefixValidLifetime, lifetime);
             return this;
         }
 
+        @UnsupportedAppUsage
         public Builder updatePrefixPreferredLifetime(long lifetime) {
             prefixPreferredLifetime = updateLifetime(prefixPreferredLifetime, lifetime);
             return this;
         }
 
+        @UnsupportedAppUsage
         public Builder updateRouteInfoLifetime(long lifetime) {
             routeInfoLifetime = updateLifetime(routeInfoLifetime, lifetime);
             return this;
         }
 
+        @UnsupportedAppUsage
         public Builder updateRdnssLifetime(long lifetime) {
             rdnssLifetime = updateLifetime(rdnssLifetime, lifetime);
             return this;
         }
 
+        @UnsupportedAppUsage
         public Builder updateDnsslLifetime(long lifetime) {
             dnsslLifetime = updateLifetime(dnsslLifetime, lifetime);
             return this;
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 1ad0929..12c2305 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -37,6 +37,7 @@
     public static final int PROBE_HTTPS     = 2;
     public static final int PROBE_PAC       = 3;
     public static final int PROBE_FALLBACK  = 4;
+    public static final int PROBE_PRIVDNS   = 5;
 
     public static final int DNS_FAILURE = 0;
     public static final int DNS_SUCCESS = 1;
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index bccaf60..9ba17ed 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -17,6 +17,7 @@
 package android.net.nsd;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 import android.os.Parcel;
 import android.text.TextUtils;
@@ -185,6 +186,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setAttribute(String key, byte[] value) {
         if (TextUtils.isEmpty(key)) {
             throw new IllegalArgumentException("Key cannot be empty");
diff --git a/core/java/android/nfc/ErrorCodes.java b/core/java/android/nfc/ErrorCodes.java
index 3adcdc3..98e31ad 100644
--- a/core/java/android/nfc/ErrorCodes.java
+++ b/core/java/android/nfc/ErrorCodes.java
@@ -16,6 +16,8 @@
 
 package android.nfc;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * This class defines all the error codes that can be returned by the service
  * and producing an exception on the application level. These are needed since
@@ -25,6 +27,7 @@
  */
 public class ErrorCodes {
 
+    @UnsupportedAppUsage
     public static boolean isError(int code) {
         if (code < 0) {
             return true;
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 093a9b4..b0090ca 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -16,6 +16,7 @@
 
 package android.nfc;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Parcel;
@@ -279,6 +280,7 @@
 
     private final short mTnf;
     private final byte[] mType;
+    @UnsupportedAppUsage
     private final byte[] mId;
     private final byte[] mPayload;
 
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 958063a..abfa133 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -16,6 +16,7 @@
 
 package android.nfc;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.Application;
 import android.content.ContentProvider;
@@ -45,6 +46,7 @@
     static final String TAG = NfcAdapter.TAG;
     static final Boolean DBG = false;
 
+    @UnsupportedAppUsage
     final NfcAdapter mAdapter;
 
     // All objects in the lists are protected by this
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index c3f23a1..21fed48 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -20,6 +20,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.ActivityThread;
 import android.app.OnActivityPausedListener;
@@ -325,6 +326,7 @@
     // Final after first constructor, except for
     // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
     // recovery
+    @UnsupportedAppUsage
     static INfcAdapter sService;
     static INfcTag sTagService;
     static INfcCardEmulation sCardEmulationService;
@@ -490,6 +492,7 @@
      * or throws if NFC is not available.
      * @hide
      */
+    @UnsupportedAppUsage
     public static synchronized NfcAdapter getNfcAdapter(Context context) {
         if (!sIsInitialized) {
             sHasNfcFeature = hasNfcFeature();
@@ -593,6 +596,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static NfcAdapter getDefaultAdapter() {
         // introduced in API version 9 (GB 2.3)
         // deprecated in API version 10 (GB 2.3.3)
@@ -615,6 +619,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public Context getContext() {
         return mContext;
     }
@@ -623,6 +628,7 @@
      * Returns the binder interface to the service.
      * @hide
      */
+    @UnsupportedAppUsage
     public INfcAdapter getService() {
         isEnabled();  // NOP call to recover sService if it is stale
         return sService;
@@ -676,6 +682,7 @@
      * NFC service dead - attempt best effort recovery
      * @hide
      */
+    @UnsupportedAppUsage
     public void attemptDeadServiceRecovery(Exception e) {
         Log.e(TAG, "NFC service dead - attempting to recover", e);
         INfcAdapter service = getServiceInterface();
@@ -746,6 +753,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getAdapterState() {
         try {
             return sService.getState();
@@ -1227,6 +1235,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
             int flags) {
         if (activity == null) {
@@ -1862,6 +1871,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public INfcAdapterExtras getNfcAdapterExtrasInterface() {
         if (mContext == null) {
             throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java
index 50d6745..71199c9 100644
--- a/core/java/android/nfc/NfcManager.java
+++ b/core/java/android/nfc/NfcManager.java
@@ -17,6 +17,7 @@
 package android.nfc;
 
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 
 /**
@@ -44,6 +45,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public NfcManager(Context context) {
         NfcAdapter adapter;
         context = context.getApplicationContext();
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 154d5a1..ce684cf 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -16,6 +16,7 @@
 
 package android.nfc;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.nfc.tech.IsoDep;
 import android.nfc.tech.MifareClassic;
@@ -110,6 +111,7 @@
  * <p>
  */
 public final class Tag implements Parcelable {
+    @UnsupportedAppUsage
     final byte[] mId;
     final int[] mTechList;
     final String[] mTechStringList;
@@ -235,6 +237,7 @@
      * For use by NfcService only.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getServiceHandle() {
         return mServiceHandle;
     }
@@ -355,6 +358,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public INfcTag getTagService() {
         return mTagService;
     }
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
index 78a9401..63776c4 100644
--- a/core/java/android/nfc/cardemulation/AidGroup.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -24,6 +24,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -45,8 +46,11 @@
 
     static final String TAG = "AidGroup";
 
+    @UnsupportedAppUsage
     final List<String> aids;
+    @UnsupportedAppUsage
     final String category;
+    @UnsupportedAppUsage
     final String description;
 
     /**
@@ -79,6 +83,7 @@
         this.description = null;
     }
 
+    @UnsupportedAppUsage
     AidGroup(String category, String description) {
         this.aids = new ArrayList<String>();
         this.category = category;
@@ -88,6 +93,7 @@
     /**
      * @return the category of this AID group
      */
+    @UnsupportedAppUsage
     public String getCategory() {
         return category;
     }
@@ -95,6 +101,7 @@
     /**
      * @return the list of AIDs in this group
      */
+    @UnsupportedAppUsage
     public List<String> getAids() {
         return aids;
     }
@@ -124,6 +131,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<AidGroup> CREATOR =
             new Parcelable.Creator<AidGroup>() {
 
@@ -144,6 +152,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     static public AidGroup createFromXml(XmlPullParser parser) throws XmlPullParserException, IOException {
         String category = null;
         ArrayList<String> aids = new ArrayList<String>();
@@ -185,6 +194,7 @@
         return group;
     }
 
+    @UnsupportedAppUsage
     public void writeAsXml(XmlSerializer out) throws IOException {
         out.startTag(null, "aid-group");
         out.attribute(null, "category", category);
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 218e4f2..e8d801c 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -16,6 +16,7 @@
 
 package android.nfc.cardemulation;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -54,6 +55,7 @@
     /**
      * The service that implements this
      */
+    @UnsupportedAppUsage
     final ResolveInfo mService;
 
     /**
@@ -69,11 +71,13 @@
     /**
      * Mapping from category to static AID group
      */
+    @UnsupportedAppUsage
     final HashMap<String, AidGroup> mStaticAidGroups;
 
     /**
      * Mapping from category to dynamic AID group
      */
+    @UnsupportedAppUsage
     final HashMap<String, AidGroup> mDynamicAidGroups;
 
     /**
@@ -99,6 +103,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
             ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
             boolean requiresUnlock, int bannerResource, int uid,
@@ -120,6 +125,7 @@
         this.mSettingsActivityName = settingsActivityName;
     }
 
+    @UnsupportedAppUsage
     public ApduServiceInfo(PackageManager pm, ResolveInfo info, boolean onHost) throws
             XmlPullParserException, IOException {
         ServiceInfo si = info.serviceInfo;
@@ -374,18 +380,22 @@
         return (mStaticAidGroups.containsKey(category) || mDynamicAidGroups.containsKey(category));
     }
 
+    @UnsupportedAppUsage
     public boolean isOnHost() {
         return mOnHost;
     }
 
+    @UnsupportedAppUsage
     public boolean requiresUnlock() {
         return mRequiresDeviceUnlock;
     }
 
+    @UnsupportedAppUsage
     public String getDescription() {
         return mDescription;
     }
 
+    @UnsupportedAppUsage
     public int getUid() {
         return mUid;
     }
@@ -411,6 +421,7 @@
         return mService.loadIcon(pm);
     }
 
+    @UnsupportedAppUsage
     public Drawable loadBanner(PackageManager pm) {
         Resources res;
         try {
@@ -426,6 +437,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public String getSettingsActivityName() { return mSettingsActivityName; }
 
     @Override
@@ -483,6 +495,7 @@
         dest.writeString(mSettingsActivityName);
     };
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<ApduServiceInfo> CREATOR =
             new Parcelable.Creator<ApduServiceInfo>() {
         @Override
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 221abed..9cf7de5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -247,8 +247,10 @@
      *   - Deferred job metrics.
      * New in version 32:
      *   - Ambient display properly output in data dump.
+     * New in version 33:
+     *   - Fixed bug in min learned capacity updating process.
      */
-    static final int CHECKIN_VERSION = 32;
+    static final int CHECKIN_VERSION = 33;
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ac87105..b9d9007 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -21,10 +21,9 @@
 import android.util.ExceptionUtils;
 import android.util.Log;
 import android.util.Slog;
-import android.util.SparseIntArray;
 
-import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.BinderInternal;
+import com.android.internal.os.BinderInternal.CallSession;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
@@ -35,12 +34,7 @@
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * Base class for a remotable object, the core part of a lightweight
@@ -99,6 +93,11 @@
     private static volatile TransactionTracker sTransactionTracker = null;
 
     /**
+     * Global observer for this process.
+     */
+    private static BinderInternal.Observer sObserver = null;
+
+    /**
      * Guestimate of native memory associated with a Binder.
      */
     private static final int NATIVE_ALLOCATION_SIZE = 500;
@@ -112,6 +111,7 @@
                 Binder.class.getClassLoader(), getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
     }
 
+
     // Transaction tracking code.
 
     /**
@@ -157,6 +157,15 @@
         return sTransactionTracker;
     }
 
+    /**
+     * Get the binder transaction observer for this process.
+     *
+     * @hide
+     */
+    public static void setObserver(@Nullable BinderInternal.Observer observer) {
+        sObserver = observer;
+    }
+
     /** {@hide} */
     static volatile boolean sWarnOnBlocking = false;
 
@@ -397,9 +406,28 @@
     public static final native void blockUntilThreadAvailable();
 
     /**
-     * Default constructor initializes the object.
+     * Default constructor just initializes the object.
+     *
+     * If you're creating a Binder token (a Binder object without an attached interface),
+     * you should use {@link #Binder(String)} instead.
      */
     public Binder() {
+        this(null);
+    }
+
+    /**
+     * Constructor for creating a raw Binder object (token) along with a descriptor.
+     *
+     * The descriptor of binder objects usually specifies the interface they are implementing.
+     * In case of binder tokens, no interface is implemented, and the descriptor can be used
+     * as a sort of tag to help identify the binder token. This will help identify remote
+     * references to these objects more easily when debugging.
+     *
+     * @param descriptor Used to identify the creator of this token, for example the class name.
+     * Instead of creating multiple tokens with the same descriptor, consider adding a suffix to
+     * help identify them.
+     */
+    public Binder(@Nullable String descriptor)  {
         mObject = getNativeBBinderHolder();
         NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject);
 
@@ -411,6 +439,7 @@
                     klass.getCanonicalName());
             }
         }
+        mDescriptor = descriptor;
     }
 
     /**
@@ -551,6 +580,20 @@
     }
 
     /**
+     * Resolves a transaction code to a human readable name.
+     *
+     * <p>Default implementation is a stub that returns null.
+     * <p>AIDL generated code will return the original method name.
+     *
+     * @param transactionCode The code to resolve.
+     * @return A human readable name.
+     * @hide
+     */
+    public @Nullable String getTransactionName(int transactionCode) {
+        return null;
+    }
+
+    /**
      * Implemented to call the more convenient version
      * {@link #dump(FileDescriptor, PrintWriter, String[])}.
      */
@@ -713,8 +756,10 @@
     // Entry point from android_util_Binder.cpp's onTransact
     private boolean execTransact(int code, long dataObj, long replyObj,
             int flags) {
-        BinderCallsStats binderCallsStats = BinderCallsStats.getInstance();
-        BinderCallsStats.CallSession callSession = binderCallsStats.callStarted(this, code);
+        // Make sure the observer won't change while processing a transaction.
+        final BinderInternal.Observer observer = sObserver;
+        final CallSession callSession =
+                observer != null ? observer.callStarted(this, code) : null;
         Parcel data = Parcel.obtain(dataObj);
         Parcel reply = Parcel.obtain(replyObj);
         // theoretically, we should call transact, which will call onTransact,
@@ -730,7 +775,9 @@
             }
             res = onTransact(code, data, reply, flags);
         } catch (RemoteException|RuntimeException e) {
-            binderCallsStats.callThrewException(callSession);
+            if (observer != null) {
+                observer.callThrewException(callSession, e);
+            }
             if (LOG_RUNTIME_EXCEPTION) {
                 Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
             }
@@ -762,448 +809,10 @@
         // to the main transaction loop to wait for another incoming transaction.  Either
         // way, strict mode begone!
         StrictMode.clearGatheredViolations();
-        binderCallsStats.callEnded(callSession, requestSizeBytes, replySizeBytes);
+        if (observer != null) {
+            observer.callEnded(callSession, requestSizeBytes, replySizeBytes);
+        }
 
         return res;
     }
 }
-
-/**
- * Java proxy for a native IBinder object.
- * Allocated and constructed by the native javaObjectforIBinder function. Never allocated
- * directly from Java code.
- */
-final class BinderProxy implements IBinder {
-    // See android_util_Binder.cpp for the native half of this.
-
-    // Assume the process-wide default value when created
-    volatile boolean mWarnOnBlocking = Binder.sWarnOnBlocking;
-
-    /*
-     * Map from longs to BinderProxy, retaining only a WeakReference to the BinderProxies.
-     * We roll our own only because we need to lazily remove WeakReferences during accesses
-     * to avoid accumulating junk WeakReference objects. WeakHashMap isn't easily usable
-     * because we want weak values, not keys.
-     * Our hash table is never resized, but the number of entries is unlimited;
-     * performance degrades as occupancy increases significantly past MAIN_INDEX_SIZE.
-     * Not thread-safe. Client ensures there's a single access at a time.
-     */
-    private static final class ProxyMap {
-        private static final int LOG_MAIN_INDEX_SIZE = 8;
-        private static final int MAIN_INDEX_SIZE = 1 <<  LOG_MAIN_INDEX_SIZE;
-        private static final int MAIN_INDEX_MASK = MAIN_INDEX_SIZE - 1;
-        // Debuggable builds will throw an AssertionError if the number of map entries exceeds:
-        private static final int CRASH_AT_SIZE = 20_000;
-
-        /**
-         * We next warn when we exceed this bucket size.
-         */
-        private int mWarnBucketSize = 20;
-
-        /**
-         * Increment mWarnBucketSize by WARN_INCREMENT each time we warn.
-         */
-        private static final int WARN_INCREMENT = 10;
-
-        /**
-         * Hash function tailored to native pointers.
-         * Returns a value < MAIN_INDEX_SIZE.
-         */
-        private static int hash(long arg) {
-            return ((int) ((arg >> 2) ^ (arg >> (2 + LOG_MAIN_INDEX_SIZE)))) & MAIN_INDEX_MASK;
-        }
-
-        /**
-         * Return the total number of pairs in the map.
-         */
-        private int size() {
-            int size = 0;
-            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
-                if (a != null) {
-                    size += a.size();
-                }
-            }
-            return size;
-        }
-
-        /**
-         * Return the total number of pairs in the map containing values that have
-         * not been cleared. More expensive than the above size function.
-         */
-        private int unclearedSize() {
-            int size = 0;
-            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
-                if (a != null) {
-                    for (WeakReference<BinderProxy> ref : a) {
-                        if (ref.get() != null) {
-                            ++size;
-                        }
-                    }
-                }
-            }
-            return size;
-        }
-
-        /**
-         * Remove ith entry from the hash bucket indicated by hash.
-         */
-        private void remove(int hash, int index) {
-            Long[] keyArray = mMainIndexKeys[hash];
-            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[hash];
-            int size = valueArray.size();  // KeyArray may have extra elements.
-            // Move last entry into empty slot, and truncate at end.
-            if (index != size - 1) {
-                keyArray[index] = keyArray[size - 1];
-                valueArray.set(index, valueArray.get(size - 1));
-            }
-            valueArray.remove(size - 1);
-            // Just leave key array entry; it's unused. We only trust the valueArray size.
-        }
-
-        /**
-         * Look up the supplied key. If we have a non-cleared entry for it, return it.
-         */
-        BinderProxy get(long key) {
-            int myHash = hash(key);
-            Long[] keyArray = mMainIndexKeys[myHash];
-            if (keyArray == null) {
-                return null;
-            }
-            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
-            int bucketSize = valueArray.size();
-            for (int i = 0; i < bucketSize; ++i) {
-                long foundKey = keyArray[i];
-                if (key == foundKey) {
-                    WeakReference<BinderProxy> wr = valueArray.get(i);
-                    BinderProxy bp = wr.get();
-                    if (bp != null) {
-                        return bp;
-                    } else {
-                        remove(myHash, i);
-                        return null;
-                    }
-                }
-            }
-            return null;
-        }
-
-        private int mRandom;  // A counter used to generate a "random" index. World's 2nd worst RNG.
-
-        /**
-         * Add the key-value pair to the map.
-         * Requires that the indicated key is not already in the map.
-         */
-        void set(long key, @NonNull BinderProxy value) {
-            int myHash = hash(key);
-            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
-            if (valueArray == null) {
-                valueArray = mMainIndexValues[myHash] = new ArrayList<>();
-                mMainIndexKeys[myHash] = new Long[1];
-            }
-            int size = valueArray.size();
-            WeakReference<BinderProxy> newWr = new WeakReference<>(value);
-            // First look for a cleared reference.
-            // This ensures that ArrayList size is bounded by the maximum occupancy of
-            // that bucket.
-            for (int i = 0; i < size; ++i) {
-                if (valueArray.get(i).get() == null) {
-                    valueArray.set(i, newWr);
-                    Long[] keyArray = mMainIndexKeys[myHash];
-                    keyArray[i] = key;
-                    if (i < size - 1) {
-                        // "Randomly" check one of the remaining entries in [i+1, size), so that
-                        // needlessly long buckets are eventually pruned.
-                        int rnd = Math.floorMod(++mRandom, size - (i + 1));
-                        if (valueArray.get(i + 1 + rnd).get() == null) {
-                            remove(myHash, i + 1 + rnd);
-                        }
-                    }
-                    return;
-                }
-            }
-            valueArray.add(size, newWr);
-            Long[] keyArray = mMainIndexKeys[myHash];
-            if (keyArray.length == size) {
-                // size >= 1, since we initially allocated one element
-                Long[] newArray = new Long[size + size / 2 + 2];
-                System.arraycopy(keyArray, 0, newArray, 0, size);
-                newArray[size] = key;
-                mMainIndexKeys[myHash] = newArray;
-            } else {
-                keyArray[size] = key;
-            }
-            if (size >= mWarnBucketSize) {
-                final int totalSize = size();
-                Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size
-                        + " total = " + totalSize);
-                mWarnBucketSize += WARN_INCREMENT;
-                if (Build.IS_DEBUGGABLE && totalSize >= CRASH_AT_SIZE) {
-                    // Use the number of uncleared entries to determine whether we should
-                    // really report a histogram and crash. We don't want to fundamentally
-                    // change behavior for a debuggable process, so we GC only if we are
-                    // about to crash.
-                    final int totalUnclearedSize = unclearedSize();
-                    if (totalUnclearedSize >= CRASH_AT_SIZE) {
-                        dumpProxyInterfaceCounts();
-                        dumpPerUidProxyCounts();
-                        Runtime.getRuntime().gc();
-                        throw new AssertionError("Binder ProxyMap has too many entries: "
-                                + totalSize + " (total), " + totalUnclearedSize + " (uncleared), "
-                                + unclearedSize() + " (uncleared after GC). BinderProxy leak?");
-                    } else if (totalSize > 3 * totalUnclearedSize / 2) {
-                        Log.v(Binder.TAG, "BinderProxy map has many cleared entries: "
-                                + (totalSize - totalUnclearedSize) + " of " + totalSize
-                                + " are cleared");
-                    }
-                }
-            }
-        }
-
-        /**
-         * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps.
-         */
-        private void dumpProxyInterfaceCounts() {
-            Map<String, Integer> counts = new HashMap<>();
-            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
-                if (a != null) {
-                    for (WeakReference<BinderProxy> weakRef : a) {
-                        BinderProxy bp = weakRef.get();
-                        String key;
-                        if (bp == null) {
-                            key = "<cleared weak-ref>";
-                        } else {
-                            try {
-                                key = bp.getInterfaceDescriptor();
-                            } catch (Throwable t) {
-                                key = "<exception during getDescriptor>";
-                            }
-                        }
-                        Integer i = counts.get(key);
-                        if (i == null) {
-                            counts.put(key, 1);
-                        } else {
-                            counts.put(key, i + 1);
-                        }
-                    }
-                }
-            }
-            Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
-                    new Map.Entry[counts.size()]);
-            Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b)
-                    -> b.getValue().compareTo(a.getValue()));
-            Log.v(Binder.TAG, "BinderProxy descriptor histogram (top ten):");
-            int printLength = Math.min(10, sorted.length);
-            for (int i = 0; i < printLength; i++) {
-                Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i].getKey() + " x"
-                        + sorted[i].getValue());
-            }
-        }
-
-        /**
-         * Dump per uid binder proxy counts to the logcat.
-         */
-        private void dumpPerUidProxyCounts() {
-            SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts();
-            if (counts.size() == 0) return;
-            Log.d(Binder.TAG, "Per Uid Binder Proxy Counts:");
-            for (int i = 0; i < counts.size(); i++) {
-                final int uid = counts.keyAt(i);
-                final int binderCount = counts.valueAt(i);
-                Log.d(Binder.TAG, "UID : " + uid + "  count = " + binderCount);
-            }
-        }
-
-        // Corresponding ArrayLists in the following two arrays always have the same size.
-        // They contain no empty entries. However WeakReferences in the values ArrayLists
-        // may have been cleared.
-
-        // mMainIndexKeys[i][j] corresponds to mMainIndexValues[i].get(j) .
-        // The values ArrayList has the proper size(), the corresponding keys array
-        // is always at least the same size, but may be larger.
-        // If either a particular keys array, or the corresponding values ArrayList
-        // are null, then they both are.
-        private final Long[][] mMainIndexKeys = new Long[MAIN_INDEX_SIZE][];
-        private final ArrayList<WeakReference<BinderProxy>>[] mMainIndexValues =
-                new ArrayList[MAIN_INDEX_SIZE];
-    }
-
-    private static ProxyMap sProxyMap = new ProxyMap();
-
-    /**
-      * Dump proxy debug information.
-      *
-      * Note: this method is not thread-safe; callers must serialize with other
-      * accesses to sProxyMap, in particular {@link #getInstance(long, long)}.
-      *
-      * @hide
-      */
-    private static void dumpProxyDebugInfo() {
-        if (Build.IS_DEBUGGABLE) {
-            sProxyMap.dumpProxyInterfaceCounts();
-            // Note that we don't call dumpPerUidProxyCounts(); this is because this
-            // method may be called as part of the uid limit being hit, and calling
-            // back into the UID tracking code would cause us to try to acquire a mutex
-            // that is held during that callback.
-        }
-    }
-
-    /**
-     * Return a BinderProxy for IBinder.
-     * This method is thread-hostile!  The (native) caller serializes getInstance() calls using
-     * gProxyLock.
-     * If we previously returned a BinderProxy bp for the same iBinder, and bp is still
-     * in use, then we return the same bp.
-     *
-     * @param nativeData C++ pointer to (possibly still empty) BinderProxyNativeData.
-     * Takes ownership of nativeData iff <result>.mNativeData == nativeData, or if
-     * we exit via an exception.  If neither applies, it's the callers responsibility to
-     * recycle nativeData.
-     * @param iBinder C++ pointer to IBinder. Does not take ownership of referenced object.
-     */
-    private static BinderProxy getInstance(long nativeData, long iBinder) {
-        BinderProxy result;
-        try {
-            result = sProxyMap.get(iBinder);
-            if (result != null) {
-                return result;
-            }
-            result = new BinderProxy(nativeData);
-        } catch (Throwable e) {
-            // We're throwing an exception (probably OOME); don't drop nativeData.
-            NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
-                    nativeData);
-            throw e;
-        }
-        NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
-        // The registry now owns nativeData, even if registration threw an exception.
-        sProxyMap.set(iBinder, result);
-        return result;
-    }
-
-    private BinderProxy(long nativeData) {
-        mNativeData = nativeData;
-    }
-
-    /**
-     * Guestimate of native memory associated with a BinderProxy.
-     * This includes the underlying IBinder, associated DeathRecipientList, and KeyedVector
-     * that points back to us. We guess high since it includes a GlobalRef, which
-     * may be in short supply.
-     */
-    private static final int NATIVE_ALLOCATION_SIZE = 1000;
-
-    // Use a Holder to allow static initialization of BinderProxy in the boot image, and
-    // to avoid some initialization ordering issues.
-    private static class NoImagePreloadHolder {
-        public static final long sNativeFinalizer = getNativeFinalizer();
-        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                BinderProxy.class.getClassLoader(), sNativeFinalizer, NATIVE_ALLOCATION_SIZE);
-    }
-
-    public native boolean pingBinder();
-    public native boolean isBinderAlive();
-
-    public IInterface queryLocalInterface(String descriptor) {
-        return null;
-    }
-
-    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
-        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
-
-        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
-            // For now, avoid spamming the log by disabling after we've logged
-            // about this interface at least once
-            mWarnOnBlocking = false;
-            Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
-                    new Throwable());
-        }
-
-        final boolean tracingEnabled = Binder.isTracingEnabled();
-        if (tracingEnabled) {
-            final Throwable tr = new Throwable();
-            Binder.getTransactionTracker().addTrace(tr);
-            StackTraceElement stackTraceElement = tr.getStackTrace()[1];
-            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
-                    stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
-        }
-        try {
-            return transactNative(code, data, reply, flags);
-        } finally {
-            if (tracingEnabled) {
-                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
-            }
-        }
-    }
-
-    private static native long getNativeFinalizer();
-    public native String getInterfaceDescriptor() throws RemoteException;
-    public native boolean transactNative(int code, Parcel data, Parcel reply,
-            int flags) throws RemoteException;
-    public native void linkToDeath(DeathRecipient recipient, int flags)
-            throws RemoteException;
-    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
-
-    public void dump(FileDescriptor fd, String[] args) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeFileDescriptor(fd);
-        data.writeStringArray(args);
-        try {
-            transact(DUMP_TRANSACTION, data, reply, 0);
-            reply.readException();
-        } finally {
-            data.recycle();
-            reply.recycle();
-        }
-    }
-
-    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeFileDescriptor(fd);
-        data.writeStringArray(args);
-        try {
-            transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
-        } finally {
-            data.recycle();
-            reply.recycle();
-        }
-    }
-
-    public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ShellCallback callback,
-            ResultReceiver resultReceiver) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeFileDescriptor(in);
-        data.writeFileDescriptor(out);
-        data.writeFileDescriptor(err);
-        data.writeStringArray(args);
-        ShellCallback.writeToParcel(callback, data);
-        resultReceiver.writeToParcel(data, 0);
-        try {
-            transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
-            reply.readException();
-        } finally {
-            data.recycle();
-            reply.recycle();
-        }
-    }
-
-    private static final void sendDeathNotice(DeathRecipient recipient) {
-        if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
-        try {
-            recipient.binderDied();
-        }
-        catch (RuntimeException exc) {
-            Log.w("BinderNative", "Uncaught exception from death notification",
-                    exc);
-        }
-    }
-
-    /**
-     * C++ pointer to BinderProxyNativeData. That consists of strong pointers to the
-     * native IBinder object, and a DeathRecipientList.
-     */
-    private final long mNativeData;
-}
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
new file mode 100644
index 0000000..591370f
--- /dev/null
+++ b/core/java/android/os/BinderProxy.java
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+import android.util.Log;
+import android.util.SparseIntArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BinderInternal;
+
+import libcore.util.NativeAllocationRegistry;
+
+import java.io.FileDescriptor;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Java proxy for a native IBinder object.
+ * Allocated and constructed by the native javaObjectforIBinder function. Never allocated
+ * directly from Java code.
+ *
+ * @hide
+ */
+public final class BinderProxy implements IBinder {
+    // See android_util_Binder.cpp for the native half of this.
+
+    // Assume the process-wide default value when created
+    volatile boolean mWarnOnBlocking = Binder.sWarnOnBlocking;
+
+    /*
+     * Map from longs to BinderProxy, retaining only a WeakReference to the BinderProxies.
+     * We roll our own only because we need to lazily remove WeakReferences during accesses
+     * to avoid accumulating junk WeakReference objects. WeakHashMap isn't easily usable
+     * because we want weak values, not keys.
+     * Our hash table is never resized, but the number of entries is unlimited;
+     * performance degrades as occupancy increases significantly past MAIN_INDEX_SIZE.
+     * Not thread-safe. Client ensures there's a single access at a time.
+     */
+    private static final class ProxyMap {
+        private static final int LOG_MAIN_INDEX_SIZE = 8;
+        private static final int MAIN_INDEX_SIZE = 1 <<  LOG_MAIN_INDEX_SIZE;
+        private static final int MAIN_INDEX_MASK = MAIN_INDEX_SIZE - 1;
+        // Debuggable builds will throw an AssertionError if the number of map entries exceeds:
+        private static final int CRASH_AT_SIZE = 20_000;
+
+        /**
+         * We next warn when we exceed this bucket size.
+         */
+        private int mWarnBucketSize = 20;
+
+        /**
+         * Increment mWarnBucketSize by WARN_INCREMENT each time we warn.
+         */
+        private static final int WARN_INCREMENT = 10;
+
+        /**
+         * Hash function tailored to native pointers.
+         * Returns a value < MAIN_INDEX_SIZE.
+         */
+        private static int hash(long arg) {
+            return ((int) ((arg >> 2) ^ (arg >> (2 + LOG_MAIN_INDEX_SIZE)))) & MAIN_INDEX_MASK;
+        }
+
+        /**
+         * Return the total number of pairs in the map.
+         */
+        private int size() {
+            int size = 0;
+            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+                if (a != null) {
+                    size += a.size();
+                }
+            }
+            return size;
+        }
+
+        /**
+         * Return the total number of pairs in the map containing values that have
+         * not been cleared. More expensive than the above size function.
+         */
+        private int unclearedSize() {
+            int size = 0;
+            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+                if (a != null) {
+                    for (WeakReference<BinderProxy> ref : a) {
+                        if (ref.get() != null) {
+                            ++size;
+                        }
+                    }
+                }
+            }
+            return size;
+        }
+
+        /**
+         * Remove ith entry from the hash bucket indicated by hash.
+         */
+        private void remove(int hash, int index) {
+            Long[] keyArray = mMainIndexKeys[hash];
+            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[hash];
+            int size = valueArray.size();  // KeyArray may have extra elements.
+            // Move last entry into empty slot, and truncate at end.
+            if (index != size - 1) {
+                keyArray[index] = keyArray[size - 1];
+                valueArray.set(index, valueArray.get(size - 1));
+            }
+            valueArray.remove(size - 1);
+            // Just leave key array entry; it's unused. We only trust the valueArray size.
+        }
+
+        /**
+         * Look up the supplied key. If we have a non-cleared entry for it, return it.
+         */
+        BinderProxy get(long key) {
+            int myHash = hash(key);
+            Long[] keyArray = mMainIndexKeys[myHash];
+            if (keyArray == null) {
+                return null;
+            }
+            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
+            int bucketSize = valueArray.size();
+            for (int i = 0; i < bucketSize; ++i) {
+                long foundKey = keyArray[i];
+                if (key == foundKey) {
+                    WeakReference<BinderProxy> wr = valueArray.get(i);
+                    BinderProxy bp = wr.get();
+                    if (bp != null) {
+                        return bp;
+                    } else {
+                        remove(myHash, i);
+                        return null;
+                    }
+                }
+            }
+            return null;
+        }
+
+        private int mRandom;  // A counter used to generate a "random" index. World's 2nd worst RNG.
+
+        /**
+         * Add the key-value pair to the map.
+         * Requires that the indicated key is not already in the map.
+         */
+        void set(long key, @NonNull BinderProxy value) {
+            int myHash = hash(key);
+            ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
+            if (valueArray == null) {
+                valueArray = mMainIndexValues[myHash] = new ArrayList<>();
+                mMainIndexKeys[myHash] = new Long[1];
+            }
+            int size = valueArray.size();
+            WeakReference<BinderProxy> newWr = new WeakReference<>(value);
+            // First look for a cleared reference.
+            // This ensures that ArrayList size is bounded by the maximum occupancy of
+            // that bucket.
+            for (int i = 0; i < size; ++i) {
+                if (valueArray.get(i).get() == null) {
+                    valueArray.set(i, newWr);
+                    Long[] keyArray = mMainIndexKeys[myHash];
+                    keyArray[i] = key;
+                    if (i < size - 1) {
+                        // "Randomly" check one of the remaining entries in [i+1, size), so that
+                        // needlessly long buckets are eventually pruned.
+                        int rnd = Math.floorMod(++mRandom, size - (i + 1));
+                        if (valueArray.get(i + 1 + rnd).get() == null) {
+                            remove(myHash, i + 1 + rnd);
+                        }
+                    }
+                    return;
+                }
+            }
+            valueArray.add(size, newWr);
+            Long[] keyArray = mMainIndexKeys[myHash];
+            if (keyArray.length == size) {
+                // size >= 1, since we initially allocated one element
+                Long[] newArray = new Long[size + size / 2 + 2];
+                System.arraycopy(keyArray, 0, newArray, 0, size);
+                newArray[size] = key;
+                mMainIndexKeys[myHash] = newArray;
+            } else {
+                keyArray[size] = key;
+            }
+            if (size >= mWarnBucketSize) {
+                final int totalSize = size();
+                Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size
+                        + " total = " + totalSize);
+                mWarnBucketSize += WARN_INCREMENT;
+                if (Build.IS_DEBUGGABLE && totalSize >= CRASH_AT_SIZE) {
+                    // Use the number of uncleared entries to determine whether we should
+                    // really report a histogram and crash. We don't want to fundamentally
+                    // change behavior for a debuggable process, so we GC only if we are
+                    // about to crash.
+                    final int totalUnclearedSize = unclearedSize();
+                    if (totalUnclearedSize >= CRASH_AT_SIZE) {
+                        dumpProxyInterfaceCounts();
+                        dumpPerUidProxyCounts();
+                        Runtime.getRuntime().gc();
+                        throw new AssertionError("Binder ProxyMap has too many entries: "
+                                + totalSize + " (total), " + totalUnclearedSize + " (uncleared), "
+                                + unclearedSize() + " (uncleared after GC). BinderProxy leak?");
+                    } else if (totalSize > 3 * totalUnclearedSize / 2) {
+                        Log.v(Binder.TAG, "BinderProxy map has many cleared entries: "
+                                + (totalSize - totalUnclearedSize) + " of " + totalSize
+                                + " are cleared");
+                    }
+                }
+            }
+        }
+
+        private InterfaceCount[] getSortedInterfaceCounts(int maxToReturn) {
+            if (maxToReturn < 0) {
+                throw new IllegalArgumentException("negative interface count");
+            }
+
+            Map<String, Integer> counts = new HashMap<>();
+            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+                if (a != null) {
+                    for (WeakReference<BinderProxy> weakRef : a) {
+                        BinderProxy bp = weakRef.get();
+                        String key;
+                        if (bp == null) {
+                            key = "<cleared weak-ref>";
+                        } else {
+                            try {
+                                key = bp.getInterfaceDescriptor();
+                                if ((key == null || key.isEmpty()) && !bp.isBinderAlive()) {
+                                    key = "<proxy to dead node>";
+                                }
+                            } catch (Throwable t) {
+                                key = "<exception during getDescriptor>";
+                            }
+                        }
+                        Integer i = counts.get(key);
+                        if (i == null) {
+                            counts.put(key, 1);
+                        } else {
+                            counts.put(key, i + 1);
+                        }
+                    }
+                }
+            }
+            Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
+                    new Map.Entry[counts.size()]);
+
+            Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b)
+                    -> b.getValue().compareTo(a.getValue()));
+
+            int returnCount = Math.min(maxToReturn, sorted.length);
+            InterfaceCount[] ifaceCounts = new InterfaceCount[returnCount];
+            for (int i = 0; i < returnCount; i++) {
+                ifaceCounts[i] = new InterfaceCount(sorted[i].getKey(), sorted[i].getValue());
+            }
+            return ifaceCounts;
+        }
+
+        static final int MAX_NUM_INTERFACES_TO_DUMP = 10;
+
+        /**
+         * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps.
+         */
+        private void dumpProxyInterfaceCounts() {
+            final InterfaceCount[] sorted = getSortedInterfaceCounts(MAX_NUM_INTERFACES_TO_DUMP);
+
+            Log.v(Binder.TAG, "BinderProxy descriptor histogram "
+                    + "(top " + Integer.toString(MAX_NUM_INTERFACES_TO_DUMP) + "):");
+            for (int i = 0; i < sorted.length; i++) {
+                Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i]);
+            }
+        }
+
+        /**
+         * Dump per uid binder proxy counts to the logcat.
+         */
+        private void dumpPerUidProxyCounts() {
+            SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts();
+            if (counts.size() == 0) return;
+            Log.d(Binder.TAG, "Per Uid Binder Proxy Counts:");
+            for (int i = 0; i < counts.size(); i++) {
+                final int uid = counts.keyAt(i);
+                final int binderCount = counts.valueAt(i);
+                Log.d(Binder.TAG, "UID : " + uid + "  count = " + binderCount);
+            }
+        }
+
+        // Corresponding ArrayLists in the following two arrays always have the same size.
+        // They contain no empty entries. However WeakReferences in the values ArrayLists
+        // may have been cleared.
+
+        // mMainIndexKeys[i][j] corresponds to mMainIndexValues[i].get(j) .
+        // The values ArrayList has the proper size(), the corresponding keys array
+        // is always at least the same size, but may be larger.
+        // If either a particular keys array, or the corresponding values ArrayList
+        // are null, then they both are.
+        private final Long[][] mMainIndexKeys = new Long[MAIN_INDEX_SIZE][];
+        private final ArrayList<WeakReference<BinderProxy>>[] mMainIndexValues =
+                new ArrayList[MAIN_INDEX_SIZE];
+    }
+
+    @GuardedBy("sProxyMap")
+    private static final ProxyMap sProxyMap = new ProxyMap();
+
+    /**
+     * Simple pair-value class to store number of binder proxy interfaces live in this process.
+     */
+    public static final class InterfaceCount {
+        private final String mInterfaceName;
+        private final int mCount;
+
+        InterfaceCount(String interfaceName, int count) {
+            mInterfaceName = interfaceName;
+            mCount = count;
+        }
+
+        @Override
+        public String toString() {
+            return mInterfaceName + " x" + Integer.toString(mCount);
+        }
+    }
+
+    /**
+     * Get a sorted array with entries mapping proxy interface names to the number
+     * of live proxies with those names.
+     *
+     * @param num maximum number of proxy interface counts to return. Use
+     *            Integer.MAX_VALUE to retrieve all
+     * @hide
+     */
+    public static InterfaceCount[] getSortedInterfaceCounts(int num) {
+        synchronized (sProxyMap) {
+            return sProxyMap.getSortedInterfaceCounts(num);
+        }
+    }
+
+    /**
+     * Dump proxy debug information.
+     *
+     * @hide
+     */
+    public static void dumpProxyDebugInfo() {
+        if (Build.IS_DEBUGGABLE) {
+            synchronized (sProxyMap) {
+                sProxyMap.dumpProxyInterfaceCounts();
+                sProxyMap.dumpPerUidProxyCounts();
+            }
+        }
+    }
+
+    /**
+     * Return a BinderProxy for IBinder.
+     * If we previously returned a BinderProxy bp for the same iBinder, and bp is still
+     * in use, then we return the same bp.
+     *
+     * @param nativeData C++ pointer to (possibly still empty) BinderProxyNativeData.
+     * Takes ownership of nativeData iff <result>.mNativeData == nativeData, or if
+     * we exit via an exception.  If neither applies, it's the callers responsibility to
+     * recycle nativeData.
+     * @param iBinder C++ pointer to IBinder. Does not take ownership of referenced object.
+     */
+    private static BinderProxy getInstance(long nativeData, long iBinder) {
+        BinderProxy result;
+        synchronized (sProxyMap) {
+            try {
+                result = sProxyMap.get(iBinder);
+                if (result != null) {
+                    return result;
+                }
+                result = new BinderProxy(nativeData);
+            } catch (Throwable e) {
+                // We're throwing an exception (probably OOME); don't drop nativeData.
+                NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
+                        nativeData);
+                throw e;
+            }
+            NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
+            // The registry now owns nativeData, even if registration threw an exception.
+            sProxyMap.set(iBinder, result);
+        }
+        return result;
+    }
+
+    private BinderProxy(long nativeData) {
+        mNativeData = nativeData;
+    }
+
+    /**
+     * Guestimate of native memory associated with a BinderProxy.
+     * This includes the underlying IBinder, associated DeathRecipientList, and KeyedVector
+     * that points back to us. We guess high since it includes a GlobalRef, which
+     * may be in short supply.
+     */
+    private static final int NATIVE_ALLOCATION_SIZE = 1000;
+
+    // Use a Holder to allow static initialization of BinderProxy in the boot image, and
+    // to avoid some initialization ordering issues.
+    private static class NoImagePreloadHolder {
+        public static final long sNativeFinalizer = getNativeFinalizer();
+        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                BinderProxy.class.getClassLoader(), sNativeFinalizer, NATIVE_ALLOCATION_SIZE);
+    }
+
+    /**
+     * @return false if the hosting process is gone, otherwise whatever the remote returns
+     */
+    public native boolean pingBinder();
+
+    /**
+     * @return false if the hosting process is gone
+     */
+    public native boolean isBinderAlive();
+
+    /**
+     * Retrieve a local interface - always null in case of a proxy
+     */
+    public IInterface queryLocalInterface(String descriptor) {
+        return null;
+    }
+
+    /**
+     * Perform a binder transaction on a proxy.
+     *
+     * @param code The action to perform.  This should
+     * be a number between {@link #FIRST_CALL_TRANSACTION} and
+     * {@link #LAST_CALL_TRANSACTION}.
+     * @param data Marshalled data to send to the target.  Must not be null.
+     * If you are not sending any data, you must create an empty Parcel
+     * that is given here.
+     * @param reply Marshalled data to be received from the target.  May be
+     * null if you are not interested in the return value.
+     * @param flags Additional operation flags.  Either 0 for a normal
+     * RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
+     *
+     * @return
+     * @throws RemoteException
+     */
+    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
+        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
+
+        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
+            // For now, avoid spamming the log by disabling after we've logged
+            // about this interface at least once
+            mWarnOnBlocking = false;
+            Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
+                    new Throwable());
+        }
+
+        final boolean tracingEnabled = Binder.isTracingEnabled();
+        if (tracingEnabled) {
+            final Throwable tr = new Throwable();
+            Binder.getTransactionTracker().addTrace(tr);
+            StackTraceElement stackTraceElement = tr.getStackTrace()[1];
+            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
+                    stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
+        }
+        try {
+            return transactNative(code, data, reply, flags);
+        } finally {
+            if (tracingEnabled) {
+                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
+            }
+        }
+    }
+
+    /* Returns the native free function */
+    private static native long getNativeFinalizer();
+    /**
+     *  See {@link IBinder#getInterfaceDescriptor()}
+     */
+    public native String getInterfaceDescriptor() throws RemoteException;
+
+    /**
+     * Native implementation of transact() for proxies
+     */
+    public native boolean transactNative(int code, Parcel data, Parcel reply,
+            int flags) throws RemoteException;
+    /**
+     * See {@link IBinder#linkToDeath(DeathRecipient, int)}
+     */
+    public native void linkToDeath(DeathRecipient recipient, int flags)
+            throws RemoteException;
+    /**
+     * See {@link IBinder#unlinkToDeath}
+     */
+    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
+
+    /**
+     * Perform a dump on the remote object
+     *
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param args additional arguments to the dump request.
+     * @throws RemoteException
+     */
+    public void dump(FileDescriptor fd, String[] args) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeFileDescriptor(fd);
+        data.writeStringArray(args);
+        try {
+            transact(DUMP_TRANSACTION, data, reply, 0);
+            reply.readException();
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
+    }
+
+    /**
+     * Perform an asynchronous dump on the remote object
+     *
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param args additional arguments to the dump request.
+     * @throws RemoteException
+     */
+    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeFileDescriptor(fd);
+        data.writeStringArray(args);
+        try {
+            transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
+    }
+
+    /**
+     * See {@link IBinder#shellCommand(FileDescriptor, FileDescriptor, FileDescriptor,
+     * String[], ShellCallback, ResultReceiver)}
+     *
+     * @param in The raw file descriptor that an input data stream can be read from.
+     * @param out The raw file descriptor that normal command messages should be written to.
+     * @param err The raw file descriptor that command error messages should be written to.
+     * @param args Command-line arguments.
+     * @param callback Optional callback to the caller's shell to perform operations in it.
+     * @param resultReceiver Called when the command has finished executing, with the result code.
+     * @throws RemoteException
+     */
+    public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeFileDescriptor(in);
+        data.writeFileDescriptor(out);
+        data.writeFileDescriptor(err);
+        data.writeStringArray(args);
+        ShellCallback.writeToParcel(callback, data);
+        resultReceiver.writeToParcel(data, 0);
+        try {
+            transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
+            reply.readException();
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
+    }
+
+    private static void sendDeathNotice(DeathRecipient recipient) {
+        if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
+        try {
+            recipient.binderDied();
+        } catch (RuntimeException exc) {
+            Log.w("BinderNative", "Uncaught exception from death notification",
+                    exc);
+        }
+    }
+
+    /**
+     * C++ pointer to BinderProxyNativeData. That consists of strong pointers to the
+     * native IBinder object, and a DeathRecipientList.
+     */
+    private final long mNativeData;
+}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 80c534c..6bd2e76 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -165,6 +165,11 @@
     public static final String[] SUPPORTED_64_BIT_ABIS =
             getStringList("ro.product.cpu.abilist64", ",");
 
+    /** {@hide} */
+    @TestApi
+    public static boolean is64BitAbi(String abi) {
+        return VMRuntime.is64BitAbi(abi);
+    }
 
     static {
         /*
@@ -626,7 +631,8 @@
          * October 2013: Android 4.4, KitKat, another tasty treat.
          *
          * <p>Applications targeting this or a later release will get these
-         * new changes in behavior:</p>
+         * new changes in behavior. For more information about this release, see the
+         * <a href="/about/versions/kitkat/">Android KitKat overview</a>.</p>
          * <ul>
          * <li> The default result of
          * {@link android.preference.PreferenceActivity#isValidFragment(String)
@@ -676,7 +682,8 @@
          * November 2014: Lollipop.  A flat one with beautiful shadows.  But still tasty.
          *
          * <p>Applications targeting this or a later release will get these
-         * new changes in behavior:</p>
+         * new changes in behavior.  For more information about this release, see the
+         * <a href="/about/versions/lollipop/">Android Lollipop overview</a>.</p>
          * <ul>
          * <li> {@link android.content.Context#bindService Context.bindService} now
          * requires an explicit Intent, and will throw an exception if given an implicit
@@ -705,6 +712,8 @@
 
         /**
          * March 2015: Lollipop with an extra sugar coating on the outside!
+         * For more information about this release, see the
+         * <a href="/about/versions/android-5.1">Android 5.1 APIs</a>.
          */
         public static final int LOLLIPOP_MR1 = 22;
 
@@ -712,7 +721,8 @@
          * M is for Marshmallow!
          *
          * <p>Applications targeting this or a later release will get these
-         * new changes in behavior:</p>
+         * new changes in behavior. For more information about this release, see the
+         * <a href="/about/versions/marshmallow/">Android 6.0 Marshmallow overview</a>.</p>
          * <ul>
          * <li> Runtime permissions.  Dangerous permissions are no longer granted at
          * install time, but must be requested by the application at runtime through
@@ -743,7 +753,8 @@
          * N is for Nougat.
          *
          * <p>Applications targeting this or a later release will get these
-         * new changes in behavior:</p>
+         * new changes in behavior. For more information about this release, see
+         * the <a href="/about/versions/nougat/">Android Nougat overview</a>.</p>
          * <ul>
          * <li> {@link android.app.DownloadManager.Request#setAllowedNetworkTypes
          * DownloadManager.Request.setAllowedNetworkTypes}
@@ -793,7 +804,9 @@
         public static final int N = 24;
 
         /**
-         * N MR1: Nougat++.
+         * N MR1: Nougat++. For more information about this release, see
+         * <a href="/about/versions/nougat/android-7.1">Android 7.1 for
+         * Developers</a>.
          */
         public static final int N_MR1 = 25;
 
@@ -801,7 +814,8 @@
          * O.
          *
          * <p>Applications targeting this or a later release will get these
-         * new changes in behavior:</p>
+         * new changes in behavior. For more information about this release, see
+         * the <a href="/about/versions/oreo/">Android Oreo overview</a>.</p>
          * <ul>
          * <li><a href="{@docRoot}about/versions/oreo/background.html">Background execution limits</a>
          * are applied to the application.</li>
@@ -890,13 +904,16 @@
          * O MR1.
          *
          * <p>Applications targeting this or a later release will get these
-         * new changes in behavior:</p>
+         * new changes in behavior. For more information about this release, see
+         * <a href="/about/versions/oreo/android-8.1">Android 8.1 features and
+         * APIs</a>.</p>
          * <ul>
          * <li>Apps exporting and linking to apk shared libraries must explicitly
          * enumerate all signing certificates in a consistent order.</li>
          * <li>{@link android.R.attr#screenOrientation} can not be used to request a fixed
          * orientation if the associated activity is not fullscreen and opaque.</li>
          * </ul>
+         *
          */
         public static final int O_MR1 = 27;
 
@@ -904,7 +921,8 @@
          * P.
          *
          * <p>Applications targeting this or a later release will get these
-         * new changes in behavior:</p>
+         * new changes in behavior. For more information about this release, see the
+         * <a href="/about/versions/pie/">Android 9 Pie overview</a>.</p>
          * <ul>
          * <li>{@link android.app.Service#startForeground Service.startForeground} requires
          * that apps hold the permission
@@ -912,6 +930,7 @@
          * <li>{@link android.widget.LinearLayout} will always remeasure weighted children,
          * even if there is no excess space.</li>
          * </ul>
+         *
          */
         public static final int P = 28;
 
@@ -1109,8 +1128,7 @@
      * @removed
      */
     @SystemApi
-    public static final boolean PERMISSIONS_REVIEW_REQUIRED =
-            SystemProperties.getInt("ro.permission_review_required", 0) == 1;
+    public static final boolean PERMISSIONS_REVIEW_REQUIRED = true;
 
     /**
      * Returns the version string for the radio firmware.  May return
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index e606964..aba81af 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -321,6 +321,45 @@
         }
 
         /**
+         * @hide Copy contents from another object.
+         */
+        public void set(MemoryInfo other) {
+            dalvikPss = other.dalvikPss;
+            dalvikSwappablePss = other.dalvikSwappablePss;
+            dalvikRss = other.dalvikRss;
+            dalvikPrivateDirty = other.dalvikPrivateDirty;
+            dalvikSharedDirty = other.dalvikSharedDirty;
+            dalvikPrivateClean = other.dalvikPrivateClean;
+            dalvikSharedClean = other.dalvikSharedClean;
+            dalvikSwappedOut = other.dalvikSwappedOut;
+            dalvikSwappedOutPss = other.dalvikSwappedOutPss;
+
+            nativePss = other.nativePss;
+            nativeSwappablePss = other.nativeSwappablePss;
+            nativeRss = other.nativeRss;
+            nativePrivateDirty = other.nativePrivateDirty;
+            nativeSharedDirty = other.nativeSharedDirty;
+            nativePrivateClean = other.nativePrivateClean;
+            nativeSharedClean = other.nativeSharedClean;
+            nativeSwappedOut = other.nativeSwappedOut;
+            nativeSwappedOutPss = other.nativeSwappedOutPss;
+
+            otherPss = other.otherPss;
+            otherSwappablePss = other.otherSwappablePss;
+            otherRss = other.otherRss;
+            otherPrivateDirty = other.otherPrivateDirty;
+            otherSharedDirty = other.otherSharedDirty;
+            otherPrivateClean = other.otherPrivateClean;
+            otherSharedClean = other.otherSharedClean;
+            otherSwappedOut = other.otherSwappedOut;
+            otherSwappedOutPss = other.otherSwappedOutPss;
+
+            hasSwappedOutPss = other.hasSwappedOutPss;
+
+            System.arraycopy(other.otherStats, 0, otherStats, 0, otherStats.length);
+        }
+
+        /**
          * Return total PSS memory usage in kB.
          */
         public int getTotalPss() {
@@ -1752,13 +1791,13 @@
     public static native long getPss();
 
     /**
-     * Retrieves the PSS memory used by the process as given by the
-     * smaps.  Optionally supply a long array of 2 entries to also
-     * receive the Uss and SwapPss of the process, and another array to also
-     * retrieve the separate memtrack size.
+     * Retrieves the PSS memory used by the process as given by the smaps. Optionally supply a long
+     * array of up to 3 entries to also receive (up to 3 values in order): the Uss and SwapPss and
+     * Rss (only filled in as of {@link android.os.Build.VERSION_CODES#P}) of the process, and
+     * another array to also retrieve the separate memtrack size.
      * @hide
      */
-    public static native long getPss(int pid, long[] outUssSwapPss, long[] outMemtrack);
+    public static native long getPss(int pid, long[] outUssSwapPssRss, long[] outMemtrack);
 
     /** @hide */
     public static final int MEMINFO_TOTAL = 0;
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 213260f..347f60f 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -33,6 +33,8 @@
 public class Environment {
     private static final String TAG = "Environment";
 
+    // NOTE: keep credential-protected paths in sync with StrictMode.java
+
     private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE";
     private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
     private static final String ENV_ANDROID_DATA = "ANDROID_DATA";
@@ -43,6 +45,7 @@
     private static final String ENV_ODM_ROOT = "ODM_ROOT";
     private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
     private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT";
+    private static final String ENV_PRODUCT_SERVICES_ROOT = "PRODUCT_SERVICES_ROOT";
 
     /** {@hide} */
     public static final String DIR_ANDROID = "Android";
@@ -65,6 +68,8 @@
     private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
     private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
     private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product");
+    private static final File DIR_PRODUCT_SERVICES_ROOT = getDirectory(ENV_PRODUCT_SERVICES_ROOT,
+                                                           "/product_services");
 
     private static UserEnvironment sCurrentUser;
     private static boolean sUserRequired;
@@ -149,6 +154,7 @@
     }
 
     /** {@hide} */
+    @TestApi
     public static File getStorageDirectory() {
         return DIR_ANDROID_STORAGE;
     }
@@ -193,6 +199,16 @@
     }
 
     /**
+     * Return root directory of the "product_services" partition holding middleware
+     * services if any. If present, the partition is mounted read-only.
+     *
+     * @hide
+     */
+    public static File getProductServicesDirectory() {
+        return DIR_PRODUCT_SERVICES_ROOT;
+    }
+
+    /**
      * Return the system directory for a user. This is for use by system
      * services to store files relating to the user. This directory will be
      * automatically deleted when the user is removed.
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 88d6e84..3a3d9ea 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -53,32 +53,35 @@
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Objects;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
 import java.util.zip.CRC32;
 import java.util.zip.CheckedInputStream;
 
 /**
- * Tools for managing files.  Not for public consumption.
- * @hide
+ * Utility methods useful for working with files.
  */
 public class FileUtils {
     private static final String TAG = "FileUtils";
 
-    public static final int S_IRWXU = 00700;
-    public static final int S_IRUSR = 00400;
-    public static final int S_IWUSR = 00200;
-    public static final int S_IXUSR = 00100;
+    /** {@hide} */ public static final int S_IRWXU = 00700;
+    /** {@hide} */ public static final int S_IRUSR = 00400;
+    /** {@hide} */ public static final int S_IWUSR = 00200;
+    /** {@hide} */ public static final int S_IXUSR = 00100;
 
-    public static final int S_IRWXG = 00070;
-    public static final int S_IRGRP = 00040;
-    public static final int S_IWGRP = 00020;
-    public static final int S_IXGRP = 00010;
+    /** {@hide} */ public static final int S_IRWXG = 00070;
+    /** {@hide} */ public static final int S_IRGRP = 00040;
+    /** {@hide} */ public static final int S_IWGRP = 00020;
+    /** {@hide} */ public static final int S_IXGRP = 00010;
 
-    public static final int S_IRWXO = 00007;
-    public static final int S_IROTH = 00004;
-    public static final int S_IWOTH = 00002;
-    public static final int S_IXOTH = 00001;
+    /** {@hide} */ public static final int S_IRWXO = 00007;
+    /** {@hide} */ public static final int S_IROTH = 00004;
+    /** {@hide} */ public static final int S_IWOTH = 00002;
+    /** {@hide} */ public static final int S_IXOTH = 00001;
+
+    private FileUtils() {
+    }
 
     /** Regular expression for safe filenames: no spaces or metacharacters.
       *
@@ -90,10 +93,14 @@
 
     private static final File[] EMPTY = new File[0];
 
-    private static final boolean ENABLE_COPY_OPTIMIZATIONS = true;
+    // non-final so it can be toggled by Robolectric's ShadowFileUtils
+    private static boolean sEnableCopyOptimizations = true;
 
     private static final long COPY_CHECKPOINT_BYTES = 524288;
 
+    /**
+     * Listener that is called periodically as progress is made.
+     */
     public interface ProgressListener {
         public void onProgress(long progress);
     }
@@ -105,6 +112,7 @@
      * @param uid to apply through {@code chown}, or -1 to leave unchanged
      * @param gid to apply through {@code chown}, or -1 to leave unchanged
      * @return 0 on success, otherwise errno.
+     * @hide
      */
     public static int setPermissions(File path, int mode, int uid, int gid) {
         return setPermissions(path.getAbsolutePath(), mode, uid, gid);
@@ -117,6 +125,7 @@
      * @param uid to apply through {@code chown}, or -1 to leave unchanged
      * @param gid to apply through {@code chown}, or -1 to leave unchanged
      * @return 0 on success, otherwise errno.
+     * @hide
      */
     public static int setPermissions(String path, int mode, int uid, int gid) {
         try {
@@ -145,6 +154,7 @@
      * @param uid to apply through {@code chown}, or -1 to leave unchanged
      * @param gid to apply through {@code chown}, or -1 to leave unchanged
      * @return 0 on success, otherwise errno.
+     * @hide
      */
     public static int setPermissions(FileDescriptor fd, int mode, int uid, int gid) {
         try {
@@ -166,7 +176,14 @@
         return 0;
     }
 
-    public static void copyPermissions(File from, File to) throws IOException {
+    /**
+     * Copy the owner UID, owner GID, and mode bits from one file to another.
+     *
+     * @param from File where attributes should be copied from.
+     * @param to File where attributes should be copied to.
+     * @hide
+     */
+    public static void copyPermissions(@NonNull File from, @NonNull File to) throws IOException {
         try {
             final StructStat stat = Os.stat(from.getAbsolutePath());
             Os.chmod(to.getAbsolutePath(), stat.st_mode);
@@ -177,8 +194,10 @@
     }
 
     /**
-     * Return owning UID of given path, otherwise -1.
+     * @deprecated use {@link Os#stat(String)} instead.
+     * @hide
      */
+    @Deprecated
     public static int getUid(String path) {
         try {
             return Os.stat(path).st_uid;
@@ -190,6 +209,8 @@
     /**
      * Perform an fsync on the given FileOutputStream.  The stream at this
      * point must be flushed but not yet closed.
+     *
+     * @hide
      */
     public static boolean sync(FileOutputStream stream) {
         try {
@@ -204,6 +225,7 @@
 
     /**
      * @deprecated use {@link #copy(File, File)} instead.
+     * @hide
      */
     @Deprecated
     public static boolean copyFile(File srcFile, File destFile) {
@@ -217,6 +239,7 @@
 
     /**
      * @deprecated use {@link #copy(File, File)} instead.
+     * @hide
      */
     @Deprecated
     public static void copyFileOrThrow(File srcFile, File destFile) throws IOException {
@@ -227,6 +250,7 @@
 
     /**
      * @deprecated use {@link #copy(InputStream, OutputStream)} instead.
+     * @hide
      */
     @Deprecated
     public static boolean copyToFile(InputStream inputStream, File destFile) {
@@ -240,6 +264,7 @@
 
     /**
      * @deprecated use {@link #copy(InputStream, OutputStream)} instead.
+     * @hide
      */
     @Deprecated
     public static void copyToFileOrThrow(InputStream in, File destFile) throws IOException {
@@ -265,7 +290,7 @@
      * @return number of bytes copied.
      */
     public static long copy(@NonNull File from, @NonNull File to) throws IOException {
-        return copy(from, to, null, null);
+        return copy(from, to, null, null, null);
     }
 
     /**
@@ -274,16 +299,17 @@
      * Attempts to use several optimization strategies to copy the data in the
      * kernel before falling back to a userspace copy as a last resort.
      *
-     * @param listener to be periodically notified as the copy progresses.
      * @param signal to signal if the copy should be cancelled early.
+     * @param executor that listener events should be delivered via.
+     * @param listener to be periodically notified as the copy progresses.
      * @return number of bytes copied.
      */
     public static long copy(@NonNull File from, @NonNull File to,
-            @Nullable ProgressListener listener, @Nullable CancellationSignal signal)
-            throws IOException {
+            @Nullable CancellationSignal signal, @Nullable Executor executor,
+            @Nullable ProgressListener listener) throws IOException {
         try (FileInputStream in = new FileInputStream(from);
                 FileOutputStream out = new FileOutputStream(to)) {
-            return copy(in, out, listener, signal);
+            return copy(in, out, signal, executor, listener);
         }
     }
 
@@ -296,7 +322,7 @@
      * @return number of bytes copied.
      */
     public static long copy(@NonNull InputStream in, @NonNull OutputStream out) throws IOException {
-        return copy(in, out, null, null);
+        return copy(in, out, null, null, null);
     }
 
     /**
@@ -305,22 +331,23 @@
      * Attempts to use several optimization strategies to copy the data in the
      * kernel before falling back to a userspace copy as a last resort.
      *
-     * @param listener to be periodically notified as the copy progresses.
      * @param signal to signal if the copy should be cancelled early.
+     * @param executor that listener events should be delivered via.
+     * @param listener to be periodically notified as the copy progresses.
      * @return number of bytes copied.
      */
     public static long copy(@NonNull InputStream in, @NonNull OutputStream out,
-            @Nullable ProgressListener listener, @Nullable CancellationSignal signal)
-            throws IOException {
-        if (ENABLE_COPY_OPTIMIZATIONS) {
+            @Nullable CancellationSignal signal, @Nullable Executor executor,
+            @Nullable ProgressListener listener) throws IOException {
+        if (sEnableCopyOptimizations) {
             if (in instanceof FileInputStream && out instanceof FileOutputStream) {
                 return copy(((FileInputStream) in).getFD(), ((FileOutputStream) out).getFD(),
-                        listener, signal);
+                        signal, executor, listener);
             }
         }
 
         // Worse case fallback to userspace
-        return copyInternalUserspace(in, out, listener, signal);
+        return copyInternalUserspace(in, out, signal, executor, listener);
     }
 
     /**
@@ -333,7 +360,7 @@
      */
     public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out)
             throws IOException {
-        return copy(in, out, null, null);
+        return copy(in, out, null, null, null);
     }
 
     /**
@@ -342,14 +369,15 @@
      * Attempts to use several optimization strategies to copy the data in the
      * kernel before falling back to a userspace copy as a last resort.
      *
-     * @param listener to be periodically notified as the copy progresses.
      * @param signal to signal if the copy should be cancelled early.
+     * @param executor that listener events should be delivered via.
+     * @param listener to be periodically notified as the copy progresses.
      * @return number of bytes copied.
      */
     public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out,
-            @Nullable ProgressListener listener, @Nullable CancellationSignal signal)
-            throws IOException {
-        return copy(in, out, listener, signal, Long.MAX_VALUE);
+            @Nullable CancellationSignal signal, @Nullable Executor executor,
+            @Nullable ProgressListener listener) throws IOException {
+        return copy(in, out, Long.MAX_VALUE, signal, executor, listener);
     }
 
     /**
@@ -358,22 +386,24 @@
      * Attempts to use several optimization strategies to copy the data in the
      * kernel before falling back to a userspace copy as a last resort.
      *
-     * @param listener to be periodically notified as the copy progresses.
-     * @param signal to signal if the copy should be cancelled early.
      * @param count the number of bytes to copy.
+     * @param signal to signal if the copy should be cancelled early.
+     * @param executor that listener events should be delivered via.
+     * @param listener to be periodically notified as the copy progresses.
      * @return number of bytes copied.
+     * @hide
      */
-    public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out,
-            @Nullable ProgressListener listener, @Nullable CancellationSignal signal, long count)
-            throws IOException {
-        if (ENABLE_COPY_OPTIMIZATIONS) {
+    public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out, long count,
+            @Nullable CancellationSignal signal, @Nullable Executor executor,
+            @Nullable ProgressListener listener) throws IOException {
+        if (sEnableCopyOptimizations) {
             try {
                 final StructStat st_in = Os.fstat(in);
                 final StructStat st_out = Os.fstat(out);
                 if (S_ISREG(st_in.st_mode) && S_ISREG(st_out.st_mode)) {
-                    return copyInternalSendfile(in, out, listener, signal, count);
+                    return copyInternalSendfile(in, out, count, signal, executor, listener);
                 } else if (S_ISFIFO(st_in.st_mode) || S_ISFIFO(st_out.st_mode)) {
-                    return copyInternalSplice(in, out, listener, signal, count);
+                    return copyInternalSplice(in, out, count, signal, executor, listener);
                 }
             } catch (ErrnoException e) {
                 throw e.rethrowAsIOException();
@@ -381,15 +411,17 @@
         }
 
         // Worse case fallback to userspace
-        return copyInternalUserspace(in, out, listener, signal, count);
+        return copyInternalUserspace(in, out, count, signal, executor, listener);
     }
 
     /**
      * Requires one of input or output to be a pipe.
+     *
+     * @hide
      */
     @VisibleForTesting
-    public static long copyInternalSplice(FileDescriptor in, FileDescriptor out,
-            ProgressListener listener, CancellationSignal signal, long count)
+    public static long copyInternalSplice(FileDescriptor in, FileDescriptor out, long count,
+            CancellationSignal signal, Executor executor, ProgressListener listener)
             throws ErrnoException {
         long progress = 0;
         long checkpoint = 0;
@@ -405,24 +437,32 @@
                 if (signal != null) {
                     signal.throwIfCanceled();
                 }
-                if (listener != null) {
-                    listener.onProgress(progress);
+                if (executor != null && listener != null) {
+                    final long progressSnapshot = progress;
+                    executor.execute(() -> {
+                        listener.onProgress(progressSnapshot);
+                    });
                 }
                 checkpoint = 0;
             }
         }
-        if (listener != null) {
-            listener.onProgress(progress);
+        if (executor != null && listener != null) {
+            final long progressSnapshot = progress;
+            executor.execute(() -> {
+                listener.onProgress(progressSnapshot);
+            });
         }
         return progress;
     }
 
     /**
      * Requires both input and output to be a regular file.
+     *
+     * @hide
      */
     @VisibleForTesting
-    public static long copyInternalSendfile(FileDescriptor in, FileDescriptor out,
-            ProgressListener listener, CancellationSignal signal, long count)
+    public static long copyInternalSendfile(FileDescriptor in, FileDescriptor out, long count,
+            CancellationSignal signal, Executor executor, ProgressListener listener)
             throws ErrnoException {
         long progress = 0;
         long checkpoint = 0;
@@ -437,33 +477,52 @@
                 if (signal != null) {
                     signal.throwIfCanceled();
                 }
-                if (listener != null) {
-                    listener.onProgress(progress);
+                if (executor != null && listener != null) {
+                    final long progressSnapshot = progress;
+                    executor.execute(() -> {
+                        listener.onProgress(progressSnapshot);
+                    });
                 }
                 checkpoint = 0;
             }
         }
-        if (listener != null) {
-            listener.onProgress(progress);
+        if (executor != null && listener != null) {
+            final long progressSnapshot = progress;
+            executor.execute(() -> {
+                listener.onProgress(progressSnapshot);
+            });
         }
         return progress;
     }
 
+    /** {@hide} */
+    @Deprecated
     @VisibleForTesting
     public static long copyInternalUserspace(FileDescriptor in, FileDescriptor out,
-            ProgressListener listener, CancellationSignal signal, long count) throws IOException {
+            ProgressListener listener, CancellationSignal signal, long count)
+            throws IOException {
+        return copyInternalUserspace(in, out, count, signal, Runnable::run, listener);
+    }
+
+    /** {@hide} */
+    @VisibleForTesting
+    public static long copyInternalUserspace(FileDescriptor in, FileDescriptor out, long count,
+            CancellationSignal signal, Executor executor, ProgressListener listener)
+            throws IOException {
         if (count != Long.MAX_VALUE) {
             return copyInternalUserspace(new SizedInputStream(new FileInputStream(in), count),
-                    new FileOutputStream(out), listener, signal);
+                    new FileOutputStream(out), signal, executor, listener);
         } else {
             return copyInternalUserspace(new FileInputStream(in),
-                    new FileOutputStream(out), listener, signal);
+                    new FileOutputStream(out), signal, executor, listener);
         }
     }
 
+    /** {@hide} */
     @VisibleForTesting
     public static long copyInternalUserspace(InputStream in, OutputStream out,
-            ProgressListener listener, CancellationSignal signal) throws IOException {
+            CancellationSignal signal, Executor executor, ProgressListener listener)
+            throws IOException {
         long progress = 0;
         long checkpoint = 0;
         byte[] buffer = new byte[8192];
@@ -479,14 +538,20 @@
                 if (signal != null) {
                     signal.throwIfCanceled();
                 }
-                if (listener != null) {
-                    listener.onProgress(progress);
+                if (executor != null && listener != null) {
+                    final long progressSnapshot = progress;
+                    executor.execute(() -> {
+                        listener.onProgress(progressSnapshot);
+                    });
                 }
                 checkpoint = 0;
             }
         }
-        if (listener != null) {
-            listener.onProgress(progress);
+        if (executor != null && listener != null) {
+            final long progressSnapshot = progress;
+            executor.execute(() -> {
+                listener.onProgress(progressSnapshot);
+            });
         }
         return progress;
     }
@@ -494,6 +559,7 @@
     /**
      * Check if a filename is "safe" (no metacharacters or spaces).
      * @param file  The file to check
+     * @hide
      */
     public static boolean isFilenameSafe(File file) {
         // Note, we check whether it matches what's known to be safe,
@@ -509,6 +575,7 @@
      * @param ellipsis to add of the file was truncated (can be null)
      * @return the contents of the file, possibly truncated
      * @throws IOException if something goes wrong reading the file
+     * @hide
      */
     public static String readTextFile(File file, int max, String ellipsis) throws IOException {
         InputStream input = new FileInputStream(file);
@@ -563,13 +630,16 @@
         }
     }
 
+    /** {@hide} */
     public static void stringToFile(File file, String string) throws IOException {
         stringToFile(file.getAbsolutePath(), string);
     }
 
-    /*
+    /**
      * Writes the bytes given in {@code content} to the file whose absolute path
      * is {@code filename}.
+     *
+     * @hide
      */
     public static void bytesToFile(String filename, byte[] content) throws IOException {
         if (filename.startsWith("/proc/")) {
@@ -592,18 +662,23 @@
      * @param filename
      * @param string
      * @throws IOException
+     * @hide
      */
     public static void stringToFile(String filename, String string) throws IOException {
         bytesToFile(filename, string.getBytes(StandardCharsets.UTF_8));
     }
 
     /**
-     * Computes the checksum of a file using the CRC32 checksum routine.
-     * The value of the checksum is returned.
+     * Computes the checksum of a file using the CRC32 checksum routine. The
+     * value of the checksum is returned.
      *
-     * @param file  the file to checksum, must not be null
+     * @param file the file to checksum, must not be null
      * @return the checksum value or an exception is thrown.
+     * @deprecated this is a weak hashing algorithm, and should not be used due
+     *             to its potential for collision.
+     * @hide
      */
+    @Deprecated
     public static long checksumCrc32(File file) throws FileNotFoundException, IOException {
         CRC32 checkSummer = new CRC32();
         CheckedInputStream cis = null;
@@ -632,6 +707,7 @@
      * @param minCount Always keep at least this many files.
      * @param minAgeMs Always keep files younger than this age, in milliseconds.
      * @return if any files were deleted.
+     * @hide
      */
     public static boolean deleteOlderFiles(File dir, int minCount, long minAgeMs) {
         if (minCount < 0 || minAgeMs < 0) {
@@ -673,6 +749,8 @@
      * Both files <em>must</em> have been resolved using
      * {@link File#getCanonicalFile()} to avoid symlink or path traversal
      * attacks.
+     *
+     * @hide
      */
     public static boolean contains(File[] dirs, File file) {
         for (File dir : dirs) {
@@ -690,12 +768,15 @@
      * Both files <em>must</em> have been resolved using
      * {@link File#getCanonicalFile()} to avoid symlink or path traversal
      * attacks.
+     *
+     * @hide
      */
     public static boolean contains(File dir, File file) {
         if (dir == null || file == null) return false;
         return contains(dir.getAbsolutePath(), file.getAbsolutePath());
     }
 
+    /** {@hide} */
     public static boolean contains(String dirPath, String filePath) {
         if (dirPath.equals(filePath)) {
             return true;
@@ -706,6 +787,7 @@
         return filePath.startsWith(dirPath);
     }
 
+    /** {@hide} */
     public static boolean deleteContentsAndDir(File dir) {
         if (deleteContents(dir)) {
             return dir.delete();
@@ -714,6 +796,7 @@
         }
     }
 
+    /** {@hide} */
     public static boolean deleteContents(File dir) {
         File[] files = dir.listFiles();
         boolean success = true;
@@ -743,6 +826,8 @@
 
     /**
      * Check if given filename is valid for an ext4 filesystem.
+     *
+     * @hide
      */
     public static boolean isValidExtFilename(String name) {
         return (name != null) && name.equals(buildValidExtFilename(name));
@@ -751,6 +836,8 @@
     /**
      * Mutate the given filename to make it valid for an ext4 filesystem,
      * replacing any invalid characters with "_".
+     *
+     * @hide
      */
     public static String buildValidExtFilename(String name) {
         if (TextUtils.isEmpty(name) || ".".equals(name) || "..".equals(name)) {
@@ -792,6 +879,8 @@
 
     /**
      * Check if given filename is valid for a FAT filesystem.
+     *
+     * @hide
      */
     public static boolean isValidFatFilename(String name) {
         return (name != null) && name.equals(buildValidFatFilename(name));
@@ -800,6 +889,8 @@
     /**
      * Mutate the given filename to make it valid for a FAT filesystem,
      * replacing any invalid characters with "_".
+     *
+     * @hide
      */
     public static String buildValidFatFilename(String name) {
         if (TextUtils.isEmpty(name) || ".".equals(name) || "..".equals(name)) {
@@ -820,6 +911,7 @@
         return res.toString();
     }
 
+    /** {@hide} */
     @VisibleForTesting
     public static String trimFilename(String str, int maxBytes) {
         final StringBuilder res = new StringBuilder(str);
@@ -827,6 +919,7 @@
         return res.toString();
     }
 
+    /** {@hide} */
     private static void trimFilename(StringBuilder res, int maxBytes) {
         byte[] raw = res.toString().getBytes(StandardCharsets.UTF_8);
         if (raw.length > maxBytes) {
@@ -839,12 +932,14 @@
         }
     }
 
+    /** {@hide} */
     public static String rewriteAfterRename(File beforeDir, File afterDir, String path) {
         if (path == null) return null;
         final File result = rewriteAfterRename(beforeDir, afterDir, new File(path));
         return (result != null) ? result.getAbsolutePath() : null;
     }
 
+    /** {@hide} */
     public static String[] rewriteAfterRename(File beforeDir, File afterDir, String[] paths) {
         if (paths == null) return null;
         final String[] result = new String[paths.length];
@@ -858,6 +953,8 @@
      * Given a path under the "before" directory, rewrite it to live under the
      * "after" directory. For example, {@code /before/foo/bar.txt} would become
      * {@code /after/foo/bar.txt}.
+     *
+     * @hide
      */
     public static File rewriteAfterRename(File beforeDir, File afterDir, File file) {
         if (file == null || beforeDir == null || afterDir == null) return null;
@@ -869,6 +966,7 @@
         return null;
     }
 
+    /** {@hide} */
     private static File buildUniqueFileWithExtension(File parent, String name, String ext)
             throws FileNotFoundException {
         File file = buildFile(parent, name, ext);
@@ -895,6 +993,7 @@
      * 'example.txt' or 'example (1).txt', etc.
      *
      * @throws FileNotFoundException
+     * @hide
      */
     public static File buildUniqueFile(File parent, String mimeType, String displayName)
             throws FileNotFoundException {
@@ -905,6 +1004,8 @@
     /**
      * Generates a unique file name under the given parent directory, keeping
      * any extension intact.
+     *
+     * @hide
      */
     public static File buildUniqueFile(File parent, String displayName)
             throws FileNotFoundException {
@@ -929,6 +1030,8 @@
      * If the display name doesn't have an extension that matches the requested MIME type, the
      * extension is regarded as a part of filename and default extension for that MIME type is
      * appended.
+     *
+     * @hide
      */
     public static String[] splitFileName(String mimeType, String displayName) {
         String name;
@@ -975,6 +1078,7 @@
         return new String[] { name, ext };
     }
 
+    /** {@hide} */
     private static File buildFile(File parent, String name, String ext) {
         if (TextUtils.isEmpty(ext)) {
             return new File(parent, name);
@@ -983,6 +1087,7 @@
         }
     }
 
+    /** {@hide} */
     public static @NonNull String[] listOrEmpty(@Nullable File dir) {
         if (dir == null) return EmptyArray.STRING;
         final String[] res = dir.list();
@@ -993,6 +1098,7 @@
         }
     }
 
+    /** {@hide} */
     public static @NonNull File[] listFilesOrEmpty(@Nullable File dir) {
         if (dir == null) return EMPTY;
         final File[] res = dir.listFiles();
@@ -1003,6 +1109,7 @@
         }
     }
 
+    /** {@hide} */
     public static @NonNull File[] listFilesOrEmpty(@Nullable File dir, FilenameFilter filter) {
         if (dir == null) return EMPTY;
         final File[] res = dir.listFiles(filter);
@@ -1013,6 +1120,7 @@
         }
     }
 
+    /** {@hide} */
     public static @Nullable File newFileOrNull(@Nullable String path) {
         return (path != null) ? new File(path) : null;
     }
@@ -1021,6 +1129,8 @@
      * Creates a directory with name {@code name} under an existing directory {@code baseDir}.
      * Returns a {@code File} object representing the directory on success, {@code null} on
      * failure.
+     *
+     * @hide
      */
     public static @Nullable File createDir(File baseDir, String name) {
         final File dir = new File(baseDir, name);
@@ -1036,6 +1146,8 @@
      * Round the given size of a storage device to a nice round power-of-two
      * value, such as 256MB or 32GB. This avoids showing weird values like
      * "29.5GB" in UI.
+     *
+     * @hide
      */
     public static long roundStorageSize(long size) {
         long val = 1;
@@ -1050,6 +1162,23 @@
         return val * pow;
     }
 
+    /**
+     * Closes the given object quietly, ignoring any checked exceptions. Does
+     * nothing if the given object is {@code null}.
+     */
+    public static void closeQuietly(@Nullable AutoCloseable closeable) {
+        IoUtils.closeQuietly(closeable);
+    }
+
+    /**
+     * Closes the given object quietly, ignoring any checked exceptions. Does
+     * nothing if the given object is {@code null}.
+     */
+    public static void closeQuietly(@Nullable FileDescriptor fd) {
+        IoUtils.closeQuietly(fd);
+    }
+
+    /** {@hide} */
     @VisibleForTesting
     public static class MemoryPipe extends Thread implements AutoCloseable {
         private final FileDescriptor[] pipe;
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 405651e..6a5bb1c 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -232,6 +232,14 @@
      * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jstring)] is out of range
      */
     public native final void putString(long offset, String x);
+    /**
+     * Writes a native handle (without duplicating the underlying file descriptors) at an offset.
+     *
+     * @param offset location to write value
+     * @param x a {@link NativeHandle} instance to write
+     * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jobject)] is out of range
+     */
+    public native final void putNativeHandle(long offset, NativeHandle x);
 
     /**
      * Put a boolean array contiguously at an offset in the blob.
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 0eb62c95..7a51db2 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -115,6 +115,13 @@
      * @param val to write
      */
     public native final void writeString(String val);
+    /**
+     * Writes a native handle (without duplicating the underlying
+     * file descriptors) to the end of the parcel.
+     *
+     * @param val to write
+     */
+    public native final void writeNativeHandle(NativeHandle val);
 
     /**
      * Writes an array of boolean values to the end of the parcel.
@@ -159,6 +166,11 @@
      * @param val to write
      */
     private native final void writeStringVector(String[] val);
+    /**
+     * Writes an array of native handles to the end of the parcel.
+     * @param val array of {@link NativeHandle} objects to write
+     */
+    private native final void writeNativeHandleVector(NativeHandle[] val);
 
     /**
      * Helper method to write a list of Booleans to val.
@@ -267,6 +279,14 @@
     }
 
     /**
+     * Helper method to write a list of native handles to the end of the parcel.
+     * @param val list of {@link NativeHandle} objects to write
+     */
+    public final void writeNativeHandleVector(ArrayList<NativeHandle> val) {
+        writeNativeHandleVector(val.toArray(new NativeHandle[val.size()]));
+    }
+
+    /**
      * Write a hwbinder object to the end of the parcel.
      * @param binder value to write
      */
@@ -328,6 +348,30 @@
      * @throws IllegalArgumentException if the parcel has no more data
      */
     public native final String readString();
+    /**
+     * Reads a native handle (without duplicating the underlying file
+     * descriptors) from the parcel. These file descriptors will only
+     * be open for the duration that the binder window is open. If they
+     * are needed further, you must call {@link NativeHandle#dup()}.
+     *
+     * @return a {@link NativeHandle} instance parsed from the parcel
+     * @throws IllegalArgumentException if the parcel has no more data
+     */
+    public native final NativeHandle readNativeHandle();
+    /**
+     * Reads an embedded native handle (without duplicating the underlying
+     * file descriptors) from the parcel. These file descriptors will only
+     * be open for the duration that the binder window is open. If they
+     * are needed further, you must call {@link NativeHandle#dup()}. You
+     * do not need to call close on the NativeHandle returned from this.
+     *
+     * @param parentHandle handle from which to read the embedded object
+     * @param offset offset into parent
+     * @return a {@link NativeHandle} instance parsed from the parcel
+     * @throws IllegalArgumentException if the parcel has no more data
+     */
+    public native final NativeHandle readEmbeddedNativeHandle(
+            long parentHandle, long offset);
 
     /**
      * Reads an array of boolean values from the parcel.
@@ -377,6 +421,12 @@
      * @throws IllegalArgumentException if the parcel has no more data
      */
     private native final String[] readStringVectorAsArray();
+    /**
+     * Reads an array of native handles from the parcel.
+     * @return array of {@link NativeHandle} objects
+     * @throws IllegalArgumentException if the parcel has no more data
+     */
+    private native final NativeHandle[] readNativeHandleAsArray();
 
     /**
      * Convenience method to read a Boolean vector as an ArrayList.
@@ -465,6 +515,15 @@
     }
 
     /**
+     * Convenience method to read a vector of native handles as an ArrayList.
+     * @return array of {@link NativeHandle} objects.
+     * @throws IllegalArgumentException if the parcel has no more data
+     */
+    public final ArrayList<NativeHandle> readNativeHandleVector() {
+        return new ArrayList<NativeHandle>(Arrays.asList(readNativeHandleAsArray()));
+    }
+
+    /**
      * Reads a strong binder value from the parcel.
      * @return binder object read from parcel or null if no binder can be read
      * @throws IllegalArgumentException if the parcel has no more data
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 31dbafa..20ca19b 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -372,11 +372,6 @@
     void stopClatd(String interfaceName);
 
     /**
-     * Determine whether the clatd (464xlat) service has been started on the given interface.
-     */
-    boolean isClatdStarted(String interfaceName);
-
-    /**
      * Start listening for mobile activity state changes.
      */
     void registerNetworkActivityListener(INetworkActivityListener listener);
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 13e4e38..7ceeb52 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -56,6 +56,7 @@
     void shutdown(boolean confirm, String reason, boolean wait);
     void crash(String message);
     int getLastShutdownReason();
+    int getLastSleepReason();
 
     void setStayOnSetting(int val);
     void boostScreenBrightness(long time);
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index e59c3ae..e8b3ca6 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -23,7 +23,8 @@
 {
     boolean hasVibrator();
     boolean hasAmplitudeControl();
-    void vibrate(int uid, String opPkg, in VibrationEffect effect, int usageHint, IBinder token);
+    void vibrate(int uid, String opPkg, in VibrationEffect effect, int usageHint, String reason,
+            IBinder token);
     void cancelVibrate(IBinder token);
 }
 
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index b303e10..455d8ed 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -349,7 +349,7 @@
     }
 
     /**
-     * Retrieve the a {@link android.os.Handler Handler} implementation that
+     * Retrieve the {@link android.os.Handler Handler} implementation that
      * will receive this message. The object must implement
      * {@link android.os.Handler#handleMessage(android.os.Message)
      * Handler.handleMessage()}. Each Handler has its own name-space for
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index b1c33c2..7c2ecc5 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.TestApi;
 import android.os.MessageQueueProto;
 import android.util.Log;
 import android.util.Printer;
@@ -458,6 +459,7 @@
      *
      * @hide
      */
+    @TestApi
     public int postSyncBarrier() {
         return postSyncBarrier(SystemClock.uptimeMillis());
     }
@@ -501,6 +503,7 @@
      *
      * @hide
      */
+    @TestApi
     public void removeSyncBarrier(int token) {
         // Remove a sync barrier token from the queue.
         // If the queue is no longer stalled by a barrier then wake it.
diff --git a/core/java/android/os/NativeHandle.java b/core/java/android/os/NativeHandle.java
new file mode 100644
index 0000000..fbecc8e
--- /dev/null
+++ b/core/java/android/os/NativeHandle.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.system.ErrnoException;
+import android.system.Os;
+
+import java.io.Closeable;
+import java.io.FileDescriptor;
+
+/**
+ * Collection representing a set of open file descriptors and an opaque data stream.
+ *
+ * @hide
+ */
+@SystemApi
+public final class NativeHandle implements Closeable {
+    // whether this object owns mFds
+    private boolean mOwn = false;
+    private FileDescriptor[] mFds;
+    private int[] mInts;
+
+    /**
+     * Constructs a {@link NativeHandle} object containing
+     * zero file descriptors and an empty data stream.
+     */
+    public NativeHandle() {
+        this(new FileDescriptor[0], new int[0], false);
+    }
+
+    /**
+     * Constructs a {@link NativeHandle} object containing the given
+     * {@link FileDescriptor} object and an empty data stream.
+     */
+    public NativeHandle(@NonNull FileDescriptor descriptor, boolean own) {
+        this(new FileDescriptor[] {descriptor}, new int[0], own);
+    }
+
+    /**
+     * Convenience method for creating a list of file descriptors.
+     *
+     * @hide
+     */
+    private static FileDescriptor[] createFileDescriptorArray(@NonNull int[] fds) {
+        FileDescriptor[] list = new FileDescriptor[fds.length];
+        for (int i = 0; i < fds.length; i++) {
+            FileDescriptor descriptor = new FileDescriptor();
+            descriptor.setInt$(fds[i]);
+            list[i] = descriptor;
+        }
+        return list;
+    }
+
+    /**
+     * Convenience method for instantiating a {@link NativeHandle} from JNI. It does
+     * not take ownership of the int[] params. It does not dupe the FileDescriptors.
+     *
+     * @hide
+     */
+    private NativeHandle(@NonNull int[] fds, @NonNull int[] ints, boolean own) {
+        this(createFileDescriptorArray(fds), ints, own);
+    }
+
+    /**
+     * Instantiate an opaque {@link NativeHandle} from fds and integers.
+     *
+     * @param own whether the fds are owned by this object and should be closed
+     */
+    public NativeHandle(@NonNull FileDescriptor[] fds, @NonNull int[] ints, boolean own) {
+        mFds = fds.clone();
+        mInts = ints.clone();
+        mOwn = own;
+    }
+
+    /**
+     * Returns whether this {@link NativeHandle} object contains a single file
+     * descriptor and nothing else.
+     *
+     * @return a boolean value
+     */
+    public boolean hasSingleFileDescriptor() {
+        return mFds.length == 1 && mInts.length == 0;
+    }
+
+    /**
+     * Explicitly duplicate NativeHandle (this dups all file descritptors).
+     *
+     * If this method is called, this must also be explicitly closed with
+     * {@link #close()}.
+     */
+    public NativeHandle dup() throws java.io.IOException {
+        FileDescriptor[] fds = new FileDescriptor[mFds.length];
+        try {
+            for (int i = 0; i < mFds.length; i++) {
+                fds[i] = Os.dup(mFds[i]);
+            }
+        } catch (ErrnoException e) {
+            e.rethrowAsIOException();
+        }
+        return new NativeHandle(fds, mInts, true /*own*/);
+    }
+
+    /**
+     * Closes the file descriptors if they are owned by this object.
+     *
+     * This also invalidates the object.
+     */
+    @Override
+    public void close() throws java.io.IOException {
+        if (!mOwn) {
+            return;
+        }
+
+        try {
+            for (FileDescriptor fd : mFds) {
+                Os.close(fd);
+            }
+        } catch (ErrnoException e) {
+            e.rethrowAsIOException();
+        }
+
+        mOwn = false;
+        mFds = null;
+        mInts = null;
+    }
+
+    /**
+     * Returns the underlying lone file descriptor.
+     *
+     * @return a {@link FileDescriptor} object
+     * @throws IllegalStateException if this object contains either zero or
+     *         more than one file descriptor, or a non-empty data stream.
+     */
+    public FileDescriptor getFileDescriptor() {
+        if (!hasSingleFileDescriptor()) {
+            throw new IllegalStateException(
+                    "NativeHandle is not single file descriptor. Contents must"
+                    + " be retreived through getFileDescriptors and getInts.");
+        }
+
+        return mFds[0];
+    }
+
+    /**
+     * Convenience method for fetching this object's file descriptors from JNI.
+     * @return a mutable copy of the underlying file descriptors (as an int[])
+     *
+     * @hide
+     */
+    private int[] getFdsAsIntArray() {
+        int numFds = mFds.length;
+        int[] fds = new int[numFds];
+
+        for (int i = 0; i < numFds; i++) {
+            fds[i] = mFds[i].getInt$();
+        }
+
+        return fds;
+    }
+
+    /**
+     * Fetch file descriptors.
+     *
+     * @return the fds.
+     */
+    public FileDescriptor[] getFileDescriptors() {
+        return mFds;
+    }
+
+    /**
+     * Fetch opaque ints. Note: This object retains ownership of the data.
+     *
+     * @return the opaque data stream.
+     */
+    public int[] getInts() {
+        return mInts;
+    }
+}
diff --git a/core/java/android/os/NullVibrator.java b/core/java/android/os/NullVibrator.java
index b8bdc89..1d0f9d3 100644
--- a/core/java/android/os/NullVibrator.java
+++ b/core/java/android/os/NullVibrator.java
@@ -44,8 +44,8 @@
     }
 
     @Override
-    public void vibrate(int uid, String opPkg,
-            VibrationEffect effect, AudioAttributes attributes) {
+    public void vibrate(int uid, String opPkg, VibrationEffect effect,
+            String reason, AudioAttributes attributes) {
     }
 
     @Override
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 3d4ce61..7e7666a 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -39,7 +39,6 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -1465,7 +1464,6 @@
      * {@link #readParcelableList(List, ClassLoader)} if required.
      *
      * @see #readParcelableList(List, ClassLoader)
-     * @hide
      */
     public final <T extends Parcelable> void writeParcelableList(@Nullable List<T> val, int flags) {
         if (val == null) {
@@ -2101,19 +2099,6 @@
         }
     }
 
-    /** @deprecated use {@link android.system.Os#open(String, int, int)} */
-    @Deprecated
-    static native FileDescriptor openFileDescriptor(String file, int mode)
-            throws FileNotFoundException;
-
-    /** @deprecated use {@link android.system.Os#dup(FileDescriptor)} */
-    @Deprecated
-    static native FileDescriptor dupFileDescriptor(FileDescriptor orig) throws IOException;
-
-    /** @deprecated use {@link android.system.Os#close(FileDescriptor)} */
-    @Deprecated
-    static native void closeFileDescriptor(FileDescriptor desc) throws IOException;
-
     /**
      * Read a byte value from the parcel at the current dataPosition().
      */
@@ -2570,7 +2555,6 @@
      * list was {@code null}, {@code list} is cleared.
      *
      * @see #writeParcelableList(List, int)
-     * @hide
      */
     @NonNull
     public final <T extends Parcelable> List<T> readParcelableList(@NonNull List<T> list,
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 7556f09..c9edc53 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -188,7 +188,13 @@
         }
         mWrapped = null;
         mFd = fd;
+        IoUtils.setFdOwner(mFd, this);
+
         mCommFd = commChannel;
+        if (mCommFd != null) {
+            IoUtils.setFdOwner(mCommFd, this);
+        }
+
         mGuard.open("close");
     }
 
@@ -682,8 +688,7 @@
             if (mClosed) {
                 throw new IllegalStateException("Already closed");
             }
-            final int fd = getFd();
-            mFd.setInt$(-1);
+            int fd = IoUtils.acquireRawFd(mFd);
             writeCommStatusAndClose(Status.DETACHED, null);
             mClosed = true;
             mGuard.close();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 9c25848..89a5def 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -397,6 +397,23 @@
     public static final int GO_TO_SLEEP_REASON_ACCESSIBILITY = 7;
 
     /**
+     * @hide
+     */
+    public static String sleepReasonToString(int sleepReason) {
+        switch (sleepReason) {
+            case GO_TO_SLEEP_REASON_APPLICATION: return "application";
+            case GO_TO_SLEEP_REASON_DEVICE_ADMIN: return "device_admin";
+            case GO_TO_SLEEP_REASON_TIMEOUT: return "timeout";
+            case GO_TO_SLEEP_REASON_LID_SWITCH: return "lid_switch";
+            case GO_TO_SLEEP_REASON_POWER_BUTTON: return "power_button";
+            case GO_TO_SLEEP_REASON_HDMI: return "hdmi";
+            case GO_TO_SLEEP_REASON_SLEEP_BUTTON: return "sleep_button";
+            case GO_TO_SLEEP_REASON_ACCESSIBILITY: return "accessibility";
+            default: return Integer.toString(sleepReason);
+        }
+    }
+
+    /**
      * Go to sleep flag: Skip dozing state and directly go to full sleep.
      * @hide
      */
@@ -961,7 +978,6 @@
      *
      * @hide Requires signature permission.
      */
-    @TestApi
     public void nap(long time) {
         try {
             mService.nap(time);
@@ -1311,6 +1327,22 @@
     }
 
     /**
+     * Returns the reason the device last went to sleep (i.e. the last value of
+     * the second argument of {@link #goToSleep(long, int, int) goToSleep}).
+     *
+     * @return One of the {@code GO_TO_SLEEP_REASON_*} constants.
+     *
+     * @hide
+     */
+    public int getLastSleepReason() {
+        try {
+            return mService.getLastSleepReason();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
      * This broadcast is only sent to registered receivers.
      */
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 7ce7c92..7caf0b1 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -492,10 +492,11 @@
                                   String instructionSet,
                                   String appDataDir,
                                   String invokeWith,
+                                  String packageName,
                                   String[] zygoteArgs) {
         return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
-                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
+                    abi, instructionSet, appDataDir, invokeWith, packageName, zygoteArgs);
     }
 
     /** @hide */
@@ -509,10 +510,11 @@
                                   String instructionSet,
                                   String appDataDir,
                                   String invokeWith,
+                                  String packageName,
                                   String[] zygoteArgs) {
         return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
-                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
+                    abi, instructionSet, appDataDir, invokeWith, packageName, zygoteArgs);
     }
 
     /**
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index 2773da5..94441ca 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -18,9 +18,9 @@
 
 import android.util.Slog;
 
-import java.io.IOException;
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.IOException;
 
 /**
  * This class provides access to the centralized jni bindings for
@@ -79,6 +79,13 @@
     public static final native String getPeerContext(FileDescriptor fd);
 
     /**
+     * Get the security context of a file descriptor of a file.
+     * @param fd FileDescriptor of a file.
+     * @return a String representing the file descriptor security context.
+     */
+    public static final native String getFileContext(FileDescriptor fd);
+
+    /**
      * Gets the security context of the current process.
      * @return a String representing the security context of the current process.
      */
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index d4d3dc8..59ea28f 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -120,6 +120,15 @@
         mStorage.write(bytes, 0, bytes.length);
     }
 
+    /**
+     * Adds a boolean by adding either a 1 or 0 to the output.
+     */
+    public void writeBoolean(boolean val) {
+        int toWrite = val ? 1 : 0;
+        mStorage.write(EVENT_TYPE_INT);
+        write4Bytes(toWrite);
+    }
+
     private StatsLogEventWrapper(Parcel in) {
         readFromParcel(in);
     }
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index ea76c9a3..5ff6e55 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -31,8 +31,10 @@
 import android.content.pm.PackageManager;
 import android.net.TrafficStats;
 import android.net.Uri;
+import android.os.storage.IStorageManager;
 import android.os.strictmode.CleartextNetworkViolation;
 import android.os.strictmode.ContentUriWithoutPermissionViolation;
+import android.os.strictmode.CredentialProtectedWhileLockedViolation;
 import android.os.strictmode.CustomViolation;
 import android.os.strictmode.DiskReadViolation;
 import android.os.strictmode.DiskWriteViolation;
@@ -284,6 +286,8 @@
     private static final int DETECT_VM_NON_SDK_API_USAGE = 1 << 9;
     /** @hide */
     private static final int DETECT_VM_IMPLICIT_DIRECT_BOOT = 1 << 10;
+    /** @hide */
+    private static final int DETECT_VM_CREDENTIAL_PROTECTED_WHILE_LOCKED = 1 << 11;
 
     /** @hide */
     private static final int DETECT_VM_ALL = 0x0000ffff;
@@ -577,6 +581,7 @@
              *
              * @hide
              */
+            @TestApi
             public Builder detectExplicitGc() {
                 // TODO(b/3400644): Un-hide this for next API update
                 // TODO(b/3400644): Un-hide ExplicitGcViolation for next API update
@@ -859,6 +864,9 @@
                     detectContentUriWithoutPermission();
                     detectUntaggedSockets();
                 }
+                if (targetSdk >= Build.VERSION_CODES.Q) {
+                    detectCredentialProtectedWhileLocked();
+                }
 
                 // TODO: Decide whether to detect non SDK API usage beyond a certain API level.
                 // TODO: enable detectImplicitDirectBoot() once system is less noisy
@@ -994,6 +1002,28 @@
             }
 
             /**
+             * Detect access to filesystem paths stored in credential protected
+             * storage areas while the user is locked.
+             * <p>
+             * When a user is locked, credential protected storage is
+             * unavailable, and files stored in these locations appear to not
+             * exist, which can result in subtle app bugs if they assume default
+             * behaviors or empty states. Instead, apps should store data needed
+             * while a user is locked under device protected storage areas.
+             *
+             * @see Context#createCredentialProtectedStorageContext()
+             * @see Context#createDeviceProtectedStorageContext()
+             */
+            public Builder detectCredentialProtectedWhileLocked() {
+                return enable(DETECT_VM_CREDENTIAL_PROTECTED_WHILE_LOCKED);
+            }
+
+            /** @hide */
+            public Builder permitCredentialProtectedWhileLocked() {
+                return disable(DETECT_VM_CREDENTIAL_PROTECTED_WHILE_LOCKED);
+            }
+
+            /**
              * Crashes the whole process on violation. This penalty runs at the end of all enabled
              * penalties so you'll still get your logging or other violations before the process
              * dies.
@@ -1154,6 +1184,16 @@
         androidPolicy.setThreadPolicyMask(threadPolicyMask);
     }
 
+    private static void setBlockGuardVmPolicy(@VmPolicyMask int vmPolicyMask) {
+        // We only need to install BlockGuard for a small subset of VM policies
+        vmPolicyMask &= DETECT_VM_CREDENTIAL_PROTECTED_WHILE_LOCKED;
+        if (vmPolicyMask != 0) {
+            BlockGuard.setVmPolicy(VM_ANDROID_POLICY);
+        } else {
+            BlockGuard.setVmPolicy(BlockGuard.LAX_VM_POLICY);
+        }
+    }
+
     // Sets up CloseGuard in Dalvik/libcore
     private static void setCloseGuardEnabled(boolean enabled) {
         if (!(CloseGuard.getReporter() instanceof AndroidCloseGuardReporter)) {
@@ -1741,6 +1781,34 @@
         }
     }
 
+    private static final BlockGuard.VmPolicy VM_ANDROID_POLICY = new BlockGuard.VmPolicy() {
+        @Override
+        public void onPathAccess(String path) {
+            if (path == null) return;
+
+            // NOTE: keep credential-protected paths in sync with Environment.java
+            if (path.startsWith("/data/user/")
+                    || path.startsWith("/data/media/")
+                    || path.startsWith("/data/system_ce/")
+                    || path.startsWith("/data/misc_ce/")
+                    || path.startsWith("/data/vendor_ce/")
+                    || path.startsWith("/storage/emulated/")) {
+                final int second = path.indexOf('/', 1);
+                final int third = path.indexOf('/', second + 1);
+                final int fourth = path.indexOf('/', third + 1);
+                if (fourth == -1) return;
+
+                try {
+                    final int userId = Integer.parseInt(path.substring(third + 1, fourth));
+                    onCredentialProtectedPathAccess(path, userId);
+                } catch (NumberFormatException ignored) {
+                }
+            } else if (path.startsWith("/data/data/")) {
+                onCredentialProtectedPathAccess(path, UserHandle.USER_SYSTEM);
+            }
+        }
+    };
+
     /**
      * In the common case, as set by conditionallyEnableDebugLogging, we're just dropboxing any
      * violations but not showing a dialog, not loggging, and not killing the process. In these
@@ -1814,6 +1882,7 @@
     }
 
     /** @hide */
+    @TestApi
     public static void conditionallyCheckInstanceCounts() {
         VmPolicy policy = getVmPolicy();
         int policySize = policy.classInstanceLimit.size();
@@ -1907,6 +1976,8 @@
                 VMRuntime.setNonSdkApiUsageConsumer(null);
                 VMRuntime.setDedupeHiddenApiWarnings(true);
             }
+
+            setBlockGuardVmPolicy(sVmPolicy.mask);
         }
     }
 
@@ -1970,6 +2041,11 @@
     }
 
     /** @hide */
+    public static boolean vmCredentialProtectedWhileLockedEnabled() {
+        return (sVmPolicy.mask & DETECT_VM_CREDENTIAL_PROTECTED_WHILE_LOCKED) != 0;
+    }
+
+    /** @hide */
     public static void onSqliteObjectLeaked(String message, Throwable originStack) {
         onVmPolicyViolation(new SqliteObjectLeakedViolation(message, originStack));
     }
@@ -2005,10 +2081,6 @@
     }
 
     /** @hide */
-    public static final String CLEARTEXT_DETECTED_MSG =
-            "Detected cleartext network traffic from UID ";
-
-    /** @hide */
     public static void onCleartextNetworkDetected(byte[] firstPacket) {
         byte[] rawAddr = null;
         if (firstPacket != null) {
@@ -2024,7 +2096,7 @@
         }
 
         final int uid = android.os.Process.myUid();
-        String msg = CLEARTEXT_DETECTED_MSG + uid;
+        String msg = "Detected cleartext network traffic from UID " + uid;
         if (rawAddr != null) {
             try {
                 msg += " to " + InetAddress.getByAddress(rawAddr);
@@ -2046,6 +2118,42 @@
         onVmPolicyViolation(new ImplicitDirectBootViolation());
     }
 
+    /** Assume locked until we hear otherwise */
+    private static volatile boolean sUserKeyUnlocked = false;
+
+    private static boolean isUserKeyUnlocked(int userId) {
+        final IStorageManager storage = IStorageManager.Stub
+                .asInterface(ServiceManager.getService("mount"));
+        if (storage != null) {
+            try {
+                return storage.isUserKeyUnlocked(userId);
+            } catch (RemoteException ignored) {
+            }
+        }
+        return false;
+    }
+
+    /** @hide */
+    private static void onCredentialProtectedPathAccess(String path, int userId) {
+        // We can cache the unlocked state for the userId we're running as,
+        // since any relocking of that user will always result in our
+        // process being killed to release any CE FDs we're holding onto.
+        if (userId == UserHandle.myUserId()) {
+            if (sUserKeyUnlocked) {
+                return;
+            } else if (isUserKeyUnlocked(userId)) {
+                sUserKeyUnlocked = true;
+                return;
+            }
+        } else if (isUserKeyUnlocked(userId)) {
+            return;
+        }
+
+        onVmPolicyViolation(new CredentialProtectedWhileLockedViolation(
+                "Accessed credential protected path " + path + " while user " + userId
+                        + " was locked"));
+    }
+
     // Map from VM violation fingerprint to uptime millis.
     private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<>();
 
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 7d3ba6a..fb34a52 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -96,6 +96,7 @@
      */
     @NonNull
     @SystemApi
+    @TestApi
     public static String get(@NonNull String key) {
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get(key);
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index f776c17..c989197 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -67,14 +67,14 @@
     }
 
     @Override
-    public void vibrate(int uid, String opPkg,
-            VibrationEffect effect, AudioAttributes attributes) {
+    public void vibrate(int uid, String opPkg, VibrationEffect effect,
+            String reason, AudioAttributes attributes) {
         if (mService == null) {
             Log.w(TAG, "Failed to vibrate; no vibrator service.");
             return;
         }
         try {
-            mService.vibrate(uid, opPkg, effect, usageForAttributes(attributes), mToken);
+            mService.vibrate(uid, opPkg, effect, usageForAttributes(attributes), reason, mToken);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to vibrate.", e);
         }
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 583f060..a967b3d 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -288,6 +288,19 @@
     }
 
     /**
+     * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate
+     * string creation for trace sections that require formatting. It is not necessary
+     * to guard all Trace method calls as they internally already check this. However it is
+     * recommended to use this to prevent creating any temporary objects that would then be
+     * passed to those methods to reduce runtime cost when tracing isn't enabled.
+     *
+     * @return true if tracing is currently enabled, false otherwise
+     */
+    public static boolean isEnabled() {
+        return isTagEnabled(TRACE_TAG_APP);
+    }
+
+    /**
      * Writes a trace message to indicate that a given section of code has begun. This call must
      * be followed by a corresponding call to {@link #endSection()} on the same thread.
      *
@@ -319,4 +332,42 @@
             nativeTraceEnd(TRACE_TAG_APP);
         }
     }
+
+    /**
+     * Writes a trace message to indicate that a given section of code has
+     * begun. Must be followed by a call to {@link #endAsyncSection(String, int)} with the same
+     * methodName and cookie. Unlike {@link #beginSection(String)} and {@link #endSection()},
+     * asynchronous events do not need to be nested. The name and cookie used to
+     * begin an event must be used to end it.
+     *
+     * @param methodName The method name to appear in the trace.
+     * @param cookie Unique identifier for distinguishing simultaneous events
+     */
+    public static void beginAsyncSection(String methodName, int cookie) {
+        asyncTraceBegin(TRACE_TAG_APP, methodName, cookie);
+    }
+
+    /**
+     * Writes a trace message to indicate that the current method has ended.
+     * Must be called exactly once for each call to {@link #beginAsyncSection(String, int)}
+     * using the same name and cookie.
+     *
+     * @param methodName The method name to appear in the trace.
+     * @param cookie Unique identifier for distinguishing simultaneous events
+     */
+    public static void endAsyncSection(String methodName, int cookie) {
+        asyncTraceEnd(TRACE_TAG_APP, methodName, cookie);
+    }
+
+    /**
+     * Writes trace message to indicate the value of a given counter.
+     *
+     * @param counterName The counter name to appear in the trace.
+     * @param counterValue The counter value.
+     */
+    public static void setCounter(String counterName, int counterValue) {
+        if (isTagEnabled(TRACE_TAG_APP)) {
+            nativeTraceCounter(TRACE_TAG_APP, counterName, counterValue);
+        }
+    }
 }
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 91c69fb..01d85c6 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -54,6 +54,7 @@
      * @see #get(int)
      * @hide
      */
+    @TestApi
     public static final int EFFECT_CLICK = Effect.CLICK;
 
     /**
@@ -62,6 +63,7 @@
      * @see #get(int)
      * @hide
      */
+    @TestApi
     public static final int EFFECT_DOUBLE_CLICK = Effect.DOUBLE_CLICK;
 
     /**
@@ -69,6 +71,7 @@
      * @see #get(int)
      * @hide
      */
+    @TestApi
     public static final int EFFECT_TICK = Effect.TICK;
 
     /**
@@ -76,6 +79,7 @@
      * @see #get(int)
      * @hide
      */
+    @TestApi
     public static final int EFFECT_THUD = Effect.THUD;
 
     /**
@@ -83,6 +87,7 @@
      * @see #get(int)
      * @hide
      */
+    @TestApi
     public static final int EFFECT_POP = Effect.POP;
 
     /**
@@ -90,8 +95,20 @@
      * @see #get(int)
      * @hide
      */
+    @TestApi
     public static final int EFFECT_HEAVY_CLICK = Effect.HEAVY_CLICK;
 
+    /** {@hide} */
+    @TestApi
+    public static final int EFFECT_STRENGTH_LIGHT = EffectStrength.LIGHT;
+
+    /** {@hide} */
+    @TestApi
+    public static final int EFFECT_STRENGTH_MEDIUM = EffectStrength.MEDIUM;
+
+    /** {@hide} */
+    @TestApi
+    public static final int EFFECT_STRENGTH_STRONG = EffectStrength.STRONG;
 
     /**
      * Ringtone patterns. They may correspond with the device's ringtone audio, or may just be a
@@ -307,6 +324,7 @@
      *
      * @hide
      */
+    @TestApi
     public abstract long getDuration();
 
     /**
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index d2d8f1e..b5aeba0 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -248,17 +248,17 @@
 
     @RequiresPermission(android.Manifest.permission.VIBRATE)
     public void vibrate(VibrationEffect vibe, AudioAttributes attributes) {
-        vibrate(Process.myUid(), mPackageName, vibe, attributes);
+        vibrate(Process.myUid(), mPackageName, vibe, null, attributes);
     }
 
     /**
-     * Like {@link #vibrate(VibrationEffect, AudioAttributes)}, but allowing the caller to specify
-     * that the vibration is owned by someone else.
+     * Like {@link #vibrate(int, String, VibrationEffect, AudioAttributes)}, but allows the
+     * caller to specify the vibration is owned by someone else and set reason for vibration.
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE)
-    public abstract void vibrate(int uid, String opPkg,
-            VibrationEffect vibe, AudioAttributes attributes);
+    public abstract void vibrate(int uid, String opPkg, VibrationEffect vibe,
+            String reason, AudioAttributes attributes);
 
     /**
      * Turn the vibrator off.
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 3270719..2299ab2 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -2,6 +2,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.os.WorkSourceProto;
 import android.provider.Settings;
@@ -83,6 +84,7 @@
     }
 
     /** @hide */
+    @TestApi
     public WorkSource(int uid) {
         mNum = 1;
         mUids = new int[] { uid, 0 };
@@ -127,16 +129,19 @@
     }
 
     /** @hide */
+    @TestApi
     public int size() {
         return mNum;
     }
 
     /** @hide */
+    @TestApi
     public int get(int index) {
         return mUids[index];
     }
 
     /** @hide */
+    @TestApi
     public String getName(int index) {
         return mNames != null ? mNames[index] : null;
     }
@@ -328,6 +333,7 @@
      *     to be aware of internal differences.
      */
     @Deprecated
+    @TestApi
     public WorkSource[] setReturningDiffs(WorkSource other) {
         synchronized (sTmpWorkSource) {
             sNewbWork = null;
@@ -379,6 +385,7 @@
      * @deprecated meant for unit testing use only. Will be removed in a future API revision.
      */
     @Deprecated
+    @TestApi
     public WorkSource addReturningNewbs(WorkSource other) {
         synchronized (sTmpWorkSource) {
             sNewbWork = null;
@@ -388,6 +395,7 @@
     }
 
     /** @hide */
+    @TestApi
     public boolean add(int uid) {
         if (mNum <= 0) {
             mNames = null;
@@ -407,6 +415,7 @@
     }
 
     /** @hide */
+    @TestApi
     public boolean add(int uid, String name) {
         if (mNum <= 0) {
             insert(0, uid, name);
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 021e72f..732d3778 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -227,12 +227,13 @@
                                                   String instructionSet,
                                                   String appDataDir,
                                                   String invokeWith,
+                                                  String packageName,
                                                   String[] zygoteArgs) {
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
-                    zygoteArgs);
+                    packageName, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -366,6 +367,7 @@
                                                       String appDataDir,
                                                       String invokeWith,
                                                       boolean startChildZygote,
+                                                      String packageName,
                                                       String[] extraArgs)
                                                       throws ZygoteStartFailedEx {
         ArrayList<String> argsForZygote = new ArrayList<String>();
@@ -382,7 +384,10 @@
             argsForZygote.add("--mount-external-read");
         } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
             argsForZygote.add("--mount-external-write");
+        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
+            argsForZygote.add("--mount-external-full");
         }
+
         argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
 
         // --setgroups is a comma-separated list
@@ -426,6 +431,10 @@
             argsForZygote.add("--start-child-zygote");
         }
 
+        if (packageName != null) {
+            argsForZygote.add("--package-name=" + packageName);
+        }
+
         argsForZygote.add(processClass);
 
         if (extraArgs != null) {
@@ -733,7 +742,7 @@
             result = startViaZygote(processClass, niceName, uid, gid,
                     gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
                     abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
-                    true /* startChildZygote */, extraArgs);
+                    true /* startChildZygote */, null /* packageName */, extraArgs);
         } catch (ZygoteStartFailedEx ex) {
             throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
         }
diff --git a/core/java/android/os/health/HealthKeys.java b/core/java/android/os/health/HealthKeys.java
index 842def3..5d60411 100644
--- a/core/java/android/os/health/HealthKeys.java
+++ b/core/java/android/os/health/HealthKeys.java
@@ -16,10 +16,8 @@
 
 package android.os.health;
 
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.annotation.TestApi;
 
-import java.lang.annotation.Annotation;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -32,6 +30,7 @@
  *
  * @hide
  */
+@TestApi
 public class HealthKeys {
 
     /**
@@ -81,6 +80,7 @@
      *
      * @hide
      */
+    @TestApi
     public static class Constants {
         private final String mDataType;
         private final int[][] mKeys = new int[TYPE_COUNT][];
diff --git a/core/java/android/os/health/HealthStats.java b/core/java/android/os/health/HealthStats.java
index 90d89c5..74ce515 100644
--- a/core/java/android/os/health/HealthStats.java
+++ b/core/java/android/os/health/HealthStats.java
@@ -16,6 +16,7 @@
 
 package android.os.health;
 
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArrayMap;
@@ -126,6 +127,7 @@
      *
      * @hide
      */
+    @TestApi
     public HealthStats(Parcel in) {
         int count;
 
diff --git a/core/java/android/os/health/HealthStatsParceler.java b/core/java/android/os/health/HealthStatsParceler.java
index 28b3694..d358a2e 100644
--- a/core/java/android/os/health/HealthStatsParceler.java
+++ b/core/java/android/os/health/HealthStatsParceler.java
@@ -16,6 +16,7 @@
 
 package android.os.health;
 
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArrayMap;
@@ -35,6 +36,7 @@
  * reuse them.
  * @hide
  */
+@TestApi
 public class HealthStatsParceler implements Parcelable {
     private HealthStatsWriter mWriter;
     private HealthStats mHealthStats;
diff --git a/core/java/android/os/health/HealthStatsWriter.java b/core/java/android/os/health/HealthStatsWriter.java
index 351836b..d4d10b0 100644
--- a/core/java/android/os/health/HealthStatsWriter.java
+++ b/core/java/android/os/health/HealthStatsWriter.java
@@ -16,6 +16,7 @@
 
 package android.os.health;
 
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArrayMap;
@@ -31,6 +32,7 @@
  *
  * @hide
  */
+@TestApi
 public class HealthStatsWriter {
     private final HealthKeys.Constants mConstants;
 
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 55a202f..5c2d41e 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -187,4 +187,6 @@
     void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) = 78;
     void runIdleMaintenance() = 79;
     void abortIdleMaintenance() = 80;
+    String translateAppToSystem(String path, String packageName, int userId) = 81;
+    String translateSystemToApp(String path, String packageName, int userId) = 82;
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index aeced951..5a1ea68 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -71,6 +71,8 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.Preconditions;
 
+import dalvik.system.BlockGuard;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
@@ -122,6 +124,8 @@
     public static final String PROP_SDCARDFS = "persist.sys.sdcardfs";
     /** {@hide} */
     public static final String PROP_VIRTUAL_DISK = "persist.sys.virtual_disk";
+    /** {@hide} */
+    public static final String PROP_ISOLATED_STORAGE = "persist.sys.isolated_storage";
 
     /** {@hide} */
     public static final String UUID_PRIVATE_INTERNAL = null;
@@ -1131,6 +1135,7 @@
 
     /** {@hide} */
     public void mkdirs(File file) {
+        BlockGuard.getVmPolicy().onPathAccess(file.getAbsolutePath());
         try {
             mStorageManager.mkdirs(mContext.getOpPackageName(), file.getAbsolutePath());
         } catch (RemoteException e) {
@@ -1481,6 +1486,36 @@
         return path;
     }
 
+    /**
+     * Translate given shared storage path from a path in an app sandbox
+     * namespace to a path in the system namespace.
+     *
+     * @hide
+     */
+    public File translateAppToSystem(File file, String packageName) {
+        try {
+            return new File(mStorageManager.translateAppToSystem(file.getAbsolutePath(),
+                    packageName, mContext.getUserId()));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Translate given shared storage path from a path in the system namespace
+     * to a path in an app sandbox namespace.
+     *
+     * @hide
+     */
+    public File translateSystemToApp(File file, String packageName) {
+        try {
+            return new File(mStorageManager.translateSystemToApp(file.getAbsolutePath(),
+                    packageName, mContext.getUserId()));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** {@hide} */
     @VisibleForTesting
     public @NonNull ParcelFileDescriptor openProxyFileDescriptor(
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index d102b19..d850e27 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -79,4 +79,18 @@
      * @return The mount mode.
      */
     public abstract int getExternalStorageMountMode(int uid, String packageName);
+
+    /**
+     * Mount external storage for the given package.
+     *
+     * <p> This will involve calling into vold to setup appropriate bind mounts.
+     *
+     * @param packageName The package for which external storage will be mounted.
+     * @param appId The appId for the given package.
+     * @param sharedUserId The sharedUserId for given package if it specified
+     *      {@code android:sharedUserId} in the manifest, otherwise {@code null}
+     * @param userId
+     */
+    public abstract void mountExternalStorageForApp(String packageName, int appId,
+            String sharedUserId, int userId);
 }
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index fd5a22a..9880142 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -17,6 +17,7 @@
 package android.os.storage;
 
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
@@ -162,6 +163,7 @@
      * @return the mount path
      * @hide
      */
+    @TestApi
     public String getPath() {
         return mPath.toString();
     }
diff --git a/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java b/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java
new file mode 100644
index 0000000..12503f6
--- /dev/null
+++ b/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.strictmode;
+
+import android.content.Context;
+
+/**
+ * Subclass of {@code Violation} that is used when a process accesses filesystem
+ * paths stored in credential protected storage areas while the user is locked.
+ * <p>
+ * When a user is locked, credential protected storage is unavailable, and files
+ * stored in these locations appear to not exist, which can result in subtle app
+ * bugs if they assume default behaviors or empty states. Instead, apps should
+ * store data needed while a user is locked under device protected storage
+ * areas.
+ *
+ * @see Context#createCredentialProtectedStorageContext()
+ * @see Context#createDeviceProtectedStorageContext()
+ */
+public final class CredentialProtectedWhileLockedViolation extends Violation {
+    /** @hide */
+    public CredentialProtectedWhileLockedViolation(String message) {
+        super(message);
+    }
+}
diff --git a/core/java/android/os/strictmode/ExplicitGcViolation.java b/core/java/android/os/strictmode/ExplicitGcViolation.java
index c7480f9..583ed1a 100644
--- a/core/java/android/os/strictmode/ExplicitGcViolation.java
+++ b/core/java/android/os/strictmode/ExplicitGcViolation.java
@@ -15,11 +15,14 @@
  */
 package android.os.strictmode;
 
+import android.annotation.TestApi;
+
 /**
  * See #{@link android.os.StrictMode.ThreadPolicy.Builder#detectExplicitGc()}.
  *
  * @hide
  */
+@TestApi
 public final class ExplicitGcViolation extends Violation {
     /** @hide */
     public ExplicitGcViolation() {
diff --git a/core/java/android/os/strictmode/ImplicitDirectBootViolation.java b/core/java/android/os/strictmode/ImplicitDirectBootViolation.java
index d7877ca..e52e212 100644
--- a/core/java/android/os/strictmode/ImplicitDirectBootViolation.java
+++ b/core/java/android/os/strictmode/ImplicitDirectBootViolation.java
@@ -26,12 +26,8 @@
  */
 public final class ImplicitDirectBootViolation extends Violation {
     /** @hide */
-    public static final String MESSAGE =
-            "Implicitly relying on automatic Direct Boot filtering; request explicit"
-                    + " filtering with PackageManager.MATCH_DIRECT_BOOT flags";
-
-    /** @hide */
     public ImplicitDirectBootViolation() {
-        super(MESSAGE);
+        super("Implicitly relying on automatic Direct Boot filtering; request explicit"
+                + " filtering with PackageManager.MATCH_DIRECT_BOOT flags");
     }
 }
diff --git a/core/java/android/os/strictmode/UntaggedSocketViolation.java b/core/java/android/os/strictmode/UntaggedSocketViolation.java
index 836a8b9..3b1ef25 100644
--- a/core/java/android/os/strictmode/UntaggedSocketViolation.java
+++ b/core/java/android/os/strictmode/UntaggedSocketViolation.java
@@ -17,12 +17,8 @@
 
 public final class UntaggedSocketViolation extends Violation {
     /** @hide */
-    public static final String MESSAGE =
-            "Untagged socket detected; use"
-                    + " TrafficStats.setThreadSocketTag() to track all network usage";
-
-    /** @hide */
     public UntaggedSocketViolation() {
-        super(MESSAGE);
+        super("Untagged socket detected; use TrafficStats.setThreadSocketTag() to "
+                + "track all network usage");
     }
 }
diff --git a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
index 2931627f..e0bffae 100644
--- a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
+++ b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
@@ -17,6 +17,7 @@
 package android.permissionpresenterservice;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
@@ -80,6 +81,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void onRevokeRuntimePermission(String packageName, String permissionName);
 
     @Override
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index ed29f74..4b5a7b4 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -20,6 +20,7 @@
 import android.annotation.CallSuper;
 import android.annotation.DrawableRes;
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
@@ -53,19 +54,27 @@
 public abstract class DialogPreference extends Preference implements
         DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
         PreferenceManager.OnActivityDestroyListener {
+    @UnsupportedAppUsage
     private AlertDialog.Builder mBuilder;
 
+    @UnsupportedAppUsage
     private CharSequence mDialogTitle;
+    @UnsupportedAppUsage
     private CharSequence mDialogMessage;
+    @UnsupportedAppUsage
     private Drawable mDialogIcon;
+    @UnsupportedAppUsage
     private CharSequence mPositiveButtonText;
+    @UnsupportedAppUsage
     private CharSequence mNegativeButtonText;
     private int mDialogLayoutResId;
 
     /** The dialog, if it is showing. */
+    @UnsupportedAppUsage
     private Dialog mDialog;
 
     /** Which button was clicked. */
+    @UnsupportedAppUsage
     private int mWhichButtonClicked;
 
     /** Dismiss the dialog on the UI thread, but not inline with handlers */
diff --git a/core/java/android/preference/EditTextPreference.java b/core/java/android/preference/EditTextPreference.java
index 9467c22..4d2ac67 100644
--- a/core/java/android/preference/EditTextPreference.java
+++ b/core/java/android/preference/EditTextPreference.java
@@ -17,6 +17,7 @@
 package android.preference;
 
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.TypedArray;
@@ -46,6 +47,7 @@
     /**
      * The edit text shown in the dialog.
      */
+    @UnsupportedAppUsage
     private EditText mEditText;
     
     private String mText;
diff --git a/core/java/android/preference/ListPreference.java b/core/java/android/preference/ListPreference.java
index f9323ed..c0c71af 100644
--- a/core/java/android/preference/ListPreference.java
+++ b/core/java/android/preference/ListPreference.java
@@ -17,6 +17,7 @@
 package android.preference;
 
 import android.annotation.ArrayRes;
+import android.annotation.UnsupportedAppUsage;
 import android.app.AlertDialog.Builder;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -41,6 +42,7 @@
     private CharSequence[] mEntryValues;
     private String mValue;
     private String mSummary;
+    @UnsupportedAppUsage
     private int mClickedDialogEntryIndex;
     private boolean mValueSet;
 
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 4306bc4..98b69a8 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -21,6 +21,7 @@
 import android.annotation.LayoutRes;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -116,6 +117,7 @@
     private int mOrder = DEFAULT_ORDER;
     private CharSequence mTitle;
     private int mTitleRes;
+    @UnsupportedAppUsage
     private CharSequence mSummary;
     /**
      * mIconResId is overridden by mIcon, if mIcon is specified.
@@ -144,7 +146,9 @@
      */
     private boolean mShouldDisableView = true;
 
+    @UnsupportedAppUsage
     private int mLayoutResId = com.android.internal.R.layout.preference;
+    @UnsupportedAppUsage
     private int mWidgetLayoutResId;
 
     private OnPreferenceChangeInternalListener mListener;
@@ -974,6 +978,7 @@
      *
      * @return A unique ID for this Preference.
      */
+    @UnsupportedAppUsage
     long getId() {
         return mId;
     }
@@ -1126,6 +1131,7 @@
      *            processing). May be {@code null}.
      * @hide
      */
+    @UnsupportedAppUsage
     public void performClick(PreferenceScreen preferenceScreen) {
 
         if (!isEnabled()) {
@@ -1161,6 +1167,7 @@
      * @return True if the Preference handled the key. Returns false by default.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         return false;
     }
@@ -1281,6 +1288,7 @@
      * @param listener The listener.
      * @see #notifyChanged()
      */
+    @UnsupportedAppUsage
     final void setOnPreferenceChangeInternalListener(OnPreferenceChangeInternalListener listener) {
         mListener = listener;
     }
@@ -1399,6 +1407,7 @@
      * @param dependent The dependent Preference that will be enabled/disabled
      *            according to the state of this Preference.
      */
+    @UnsupportedAppUsage
     private void registerDependent(Preference dependent) {
         if (mDependents == null) {
             mDependents = new ArrayList<Preference>();
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 02fa7ed..8ed2605 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -19,6 +19,7 @@
 import android.animation.LayoutTransition;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.XmlRes;
 import android.app.Fragment;
 import android.app.FragmentBreadCrumbs;
@@ -79,7 +80,7 @@
  * <li>On a small screen it may display only the headers as a single list when first launched.
  * Selecting one of the header items will only show the PreferenceFragment of that header (on
  * Android N and lower a new Activity is launched).
- * <li>On a large screen in may display both the headers and current PreferenceFragment together as
+ * <li>On a large screen it may display both the headers and current PreferenceFragment together as
  * panes. Selecting a header item switches to showing the correct PreferenceFragment for that item.
  * </ul>
  *
@@ -198,6 +199,7 @@
 
     private FrameLayout mListFooter;
 
+    @UnsupportedAppUsage
     private ViewGroup mPrefsContainer;
 
     // Backup of the original activity title. This is used when navigating back to the headers list
@@ -215,6 +217,7 @@
 
     // --- State for old mode when showing a single preference list
 
+    @UnsupportedAppUsage
     private PreferenceManager mPreferenceManager;
 
     private Bundle mSavedInstanceState;
@@ -739,6 +742,7 @@
      * Returns the Header list
      * @hide
      */
+    @UnsupportedAppUsage
     public List<Header> getHeaders() {
         return mHeaders;
     }
@@ -1441,6 +1445,7 @@
      * Binding late is preferred as any custom preference types created in
      * {@link #onCreate(Bundle)} are able to have their views recycled.
      */
+    @UnsupportedAppUsage
     private void postBindPreferences() {
         if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
         mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
@@ -1469,6 +1474,7 @@
         return mPreferenceManager;
     }
 
+    @UnsupportedAppUsage
     private void requirePreferenceManager() {
         if (mPreferenceManager == null) {
             if (mAdapter == null) {
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index 4c556ef..548895e 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -17,6 +17,7 @@
 package android.preference;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.XmlRes;
 import android.app.Activity;
 import android.app.Fragment;
@@ -113,6 +114,7 @@
 
     private static final String PREFERENCES_TAG = "android:preferences";
 
+    @UnsupportedAppUsage
     private PreferenceManager mPreferenceManager;
     private ListView mList;
     private boolean mHavePrefs;
@@ -402,6 +404,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public ListView getListView() {
         ensureList();
         return mList;
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index 6095e6f..c76c8d3 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.XmlRes;
 import android.app.Activity;
 import android.content.Context;
@@ -67,6 +68,7 @@
      * Fragment that owns this instance.
      */
     @Nullable
+    @UnsupportedAppUsage
     private PreferenceFragment mFragment;
 
     /**
@@ -90,6 +92,7 @@
      * Cached shared preferences.
      */
     @Nullable
+    @UnsupportedAppUsage
     private SharedPreferences mSharedPreferences;
 
     /**
@@ -152,6 +155,7 @@
      * List of activity destroy listeners.
      */
     @Nullable
+    @UnsupportedAppUsage
     private List<OnActivityDestroyListener> mActivityDestroyListeners;
 
     /**
@@ -161,11 +165,13 @@
     @Nullable
     private List<DialogInterface> mPreferencesScreens;
 
+    @UnsupportedAppUsage
     private OnPreferenceTreeClickListener mOnPreferenceTreeClickListener;
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public PreferenceManager(Activity activity, int firstRequestCode) {
         mActivity = activity;
         mNextRequestCode = firstRequestCode;
@@ -181,6 +187,7 @@
      * should be used ANY time a preference will be displayed, since some preference
      * types need an Activity for managed queries.
      */
+    @UnsupportedAppUsage
     /*package*/ PreferenceManager(Context context) {
         init(context);
     }
@@ -194,6 +201,7 @@
     /**
      * Sets the owning preference fragment
      */
+    @UnsupportedAppUsage
     void setFragment(PreferenceFragment fragment) {
         mFragment = fragment;
     }
@@ -202,6 +210,7 @@
      * Returns the owning preference fragment, if any.
      */
     @Nullable
+    @UnsupportedAppUsage
     PreferenceFragment getFragment() {
         return mFragment;
     }
@@ -260,6 +269,7 @@
      * @return The root hierarchy (if one was not provided, the new hierarchy's
      *         root).
      */
+    @UnsupportedAppUsage
     PreferenceScreen inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences) {
         final List<ResolveInfo> activities = queryIntentActivities(queryIntent);
         final HashSet<String> inflatedRes = new HashSet<String>();
@@ -315,6 +325,7 @@
      *         root).
      * @hide
      */
+    @UnsupportedAppUsage
     public PreferenceScreen inflateFromResource(Context context, @XmlRes int resId,
             PreferenceScreen rootPreferences) {
         // Block commits
@@ -546,6 +557,7 @@
      * @return The {@link PreferenceScreen} object that is at the root of the hierarchy.
      */
     @Nullable
+    @UnsupportedAppUsage
     PreferenceScreen getPreferenceScreen() {
         return mPreferenceScreen;
     }
@@ -556,6 +568,7 @@
      * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
      * @return Whether the {@link PreferenceScreen} given is different than the previous.
      */
+    @UnsupportedAppUsage
     boolean setPreferences(PreferenceScreen preferenceScreen) {
         if (preferenceScreen != mPreferenceScreen) {
             mPreferenceScreen = preferenceScreen;
@@ -670,6 +683,7 @@
      *         has been set, this method returns {@code null}.
      * @see #shouldCommit()
      */
+    @UnsupportedAppUsage
     SharedPreferences.Editor getEditor() {
         if (mPreferenceDataStore != null) {
             return null;
@@ -695,10 +709,12 @@
      *
      * @return Whether the client should commit.
      */
+    @UnsupportedAppUsage
     boolean shouldCommit() {
         return !mNoCommit;
     }
 
+    @UnsupportedAppUsage
     private void setNoCommit(boolean noCommit) {
         if (!noCommit && mEditor != null) {
             try {
@@ -725,6 +741,7 @@
      * @see #mContext
      */
     @Nullable
+    @UnsupportedAppUsage
     Activity getActivity() {
         return mActivity;
     }
@@ -744,6 +761,7 @@
      *
      * @see OnActivityResultListener
      */
+    @UnsupportedAppUsage
     void registerOnActivityResultListener(OnActivityResultListener listener) {
         synchronized (this) {
             if (mActivityResultListeners == null) {
@@ -761,6 +779,7 @@
      *
      * @see OnActivityResultListener
      */
+    @UnsupportedAppUsage
     void unregisterOnActivityResultListener(OnActivityResultListener listener) {
         synchronized (this) {
             if (mActivityResultListeners != null) {
@@ -772,6 +791,7 @@
     /**
      * Called by the {@link PreferenceManager} to dispatch a subactivity result.
      */
+    @UnsupportedAppUsage
     void dispatchActivityResult(int requestCode, int resultCode, Intent data) {
         List<OnActivityResultListener> list;
 
@@ -794,6 +814,7 @@
      * @see OnActivityStopListener
      * @hide
      */
+    @UnsupportedAppUsage
     public void registerOnActivityStopListener(OnActivityStopListener listener) {
         synchronized (this) {
             if (mActivityStopListeners == null) {
@@ -812,6 +833,7 @@
      * @see OnActivityStopListener
      * @hide
      */
+    @UnsupportedAppUsage
     public void unregisterOnActivityStopListener(OnActivityStopListener listener) {
         synchronized (this) {
             if (mActivityStopListeners != null) {
@@ -824,6 +846,7 @@
      * Called by the {@link PreferenceManager} to dispatch the activity stop
      * event.
      */
+    @UnsupportedAppUsage
     void dispatchActivityStop() {
         List<OnActivityStopListener> list;
 
@@ -843,6 +866,7 @@
      *
      * @see OnActivityDestroyListener
      */
+    @UnsupportedAppUsage
     void registerOnActivityDestroyListener(OnActivityDestroyListener listener) {
         synchronized (this) {
             if (mActivityDestroyListeners == null) {
@@ -860,6 +884,7 @@
      *
      * @see OnActivityDestroyListener
      */
+    @UnsupportedAppUsage
     void unregisterOnActivityDestroyListener(OnActivityDestroyListener listener) {
         synchronized (this) {
             if (mActivityDestroyListeners != null) {
@@ -872,6 +897,7 @@
      * Called by the {@link PreferenceManager} to dispatch the activity destroy
      * event.
      */
+    @UnsupportedAppUsage
     void dispatchActivityDestroy() {
         List<OnActivityDestroyListener> list = null;
 
@@ -899,6 +925,7 @@
      * @return A unique request code that will never be used by anyone other
      *         than the caller of this method.
      */
+    @UnsupportedAppUsage
     int getNextRequestCode() {
         synchronized (this) {
             return mNextRequestCode++;
diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java
index 2305b05..dd00a53 100644
--- a/core/java/android/preference/PreferenceScreen.java
+++ b/core/java/android/preference/PreferenceScreen.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -89,10 +90,12 @@
 public final class PreferenceScreen extends PreferenceGroup implements AdapterView.OnItemClickListener,
         DialogInterface.OnDismissListener {
 
+    @UnsupportedAppUsage
     private ListAdapter mRootAdapter;
     
     private Dialog mDialog;
 
+    @UnsupportedAppUsage
     private ListView mListView;
 
     private int mLayoutResId = com.android.internal.R.layout.preference_list_fragment;
@@ -103,6 +106,7 @@
      * Do NOT use this constructor, use {@link PreferenceManager#createPreferenceScreen(Context)}.
      * @hide-
      */
+    @UnsupportedAppUsage
     public PreferenceScreen(Context context, AttributeSet attrs) {
         super(context, attrs, com.android.internal.R.attr.preferenceScreenStyle);
 
diff --git a/core/java/android/preference/RingtonePreference.java b/core/java/android/preference/RingtonePreference.java
index a76bb09..cd751cd 100644
--- a/core/java/android/preference/RingtonePreference.java
+++ b/core/java/android/preference/RingtonePreference.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
@@ -49,6 +50,7 @@
     private boolean mShowDefault;
     private boolean mShowSilent;
     
+    @UnsupportedAppUsage
     private int mRequestCode;
 
     public RingtonePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
diff --git a/core/java/android/preference/SeekBarDialogPreference.java b/core/java/android/preference/SeekBarDialogPreference.java
index eeb69a3..a8e5992 100644
--- a/core/java/android/preference/SeekBarDialogPreference.java
+++ b/core/java/android/preference/SeekBarDialogPreference.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
@@ -47,6 +48,7 @@
         this(context, attrs, defStyleAttr, 0);
     }
 
+    @UnsupportedAppUsage
     public SeekBarDialogPreference(Context context, AttributeSet attrs) {
         this(context, attrs, R.attr.seekBarDialogPreferenceStyle);
     }
diff --git a/core/java/android/preference/SeekBarPreference.java b/core/java/android/preference/SeekBarPreference.java
index 1fabf3d..cd35f3d 100644
--- a/core/java/android/preference/SeekBarPreference.java
+++ b/core/java/android/preference/SeekBarPreference.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.os.Parcel;
@@ -55,14 +56,17 @@
         setLayoutResource(layoutResId);
     }
 
+    @UnsupportedAppUsage
     public SeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
         this(context, attrs, defStyleAttr, 0);
     }
 
+    @UnsupportedAppUsage
     public SeekBarPreference(Context context, AttributeSet attrs) {
         this(context, attrs, com.android.internal.R.attr.seekBarPreferenceStyle);
     }
 
+    @UnsupportedAppUsage
     public SeekBarPreference(Context context) {
         this(context, null);
     }
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 0ed2526..e8daf21 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -54,12 +55,15 @@
         void onMuted(boolean muted, boolean zenMuted);
     }
 
+    @UnsupportedAppUsage
     private final Context mContext;
     private final H mUiHandler = new H();
     private final Callback mCallback;
     private final Uri mDefaultUri;
+    @UnsupportedAppUsage
     private final AudioManager mAudioManager;
     private final NotificationManager mNotificationManager;
+    @UnsupportedAppUsage
     private final int mStreamType;
     private final int mMaxStreamVolume;
     private boolean mAffectedByRingerMode;
@@ -68,19 +72,24 @@
 
     private Handler mHandler;
     private Observer mVolumeObserver;
+    @UnsupportedAppUsage
     private int mOriginalStreamVolume;
     private int mLastAudibleStreamVolume;
     // When the old handler is destroyed and a new one is created, there could be a situation where
     // this is accessed at the same time in different handlers. So, access to this field needs to be
     // synchronized.
     @GuardedBy("this")
+    @UnsupportedAppUsage
     private Ringtone mRingtone;
+    @UnsupportedAppUsage
     private int mLastProgress = -1;
     private boolean mMuted;
+    @UnsupportedAppUsage
     private SeekBar mSeekBar;
     private int mVolumeBeforeMute = -1;
     private int mRingerMode;
     private int mZenMode;
+    private boolean mPlaySample;
 
     private static final int MSG_SET_STREAM_VOLUME = 0;
     private static final int MSG_START_SAMPLE = 1;
@@ -93,7 +102,17 @@
     private boolean mAllowMedia;
     private boolean mAllowRinger;
 
+    @UnsupportedAppUsage
     public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback) {
+        this(context, streamType, defaultUri, callback, true /* playSample */);
+    }
+
+    public SeekBarVolumizer(
+            Context context,
+            int streamType,
+            Uri defaultUri,
+            Callback callback,
+            boolean playSample) {
         mContext = context;
         mAudioManager = context.getSystemService(AudioManager.class);
         mNotificationManager = context.getSystemService(NotificationManager.class);
@@ -116,6 +135,7 @@
         mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType);
         mLastAudibleStreamVolume = mAudioManager.getLastAudibleStreamVolume(mStreamType);
         mMuted = mAudioManager.isStreamMute(mStreamType);
+        mPlaySample = playSample;
         if (mCallback != null) {
             mCallback.onMuted(mMuted, isZenMuted());
         }
@@ -190,13 +210,19 @@
                         AudioManager.FLAG_SHOW_UI_WARNINGS);
                 break;
             case MSG_START_SAMPLE:
-                onStartSample();
+                if (mPlaySample) {
+                    onStartSample();
+                }
                 break;
             case MSG_STOP_SAMPLE:
-                onStopSample();
+                if (mPlaySample) {
+                    onStopSample();
+                }
                 break;
             case MSG_INIT_SAMPLE:
-                onInitSample();
+                if (mPlaySample) {
+                    onInitSample();
+                }
                 break;
             default:
                 Log.e(TAG, "invalid SeekBarVolumizer message: "+msg.what);
@@ -258,6 +284,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void stop() {
         if (mHandler == null) return;  // already stopped
         postStopSample();
@@ -277,7 +304,7 @@
         mHandler.sendEmptyMessage(MSG_INIT_SAMPLE);
         mVolumeObserver = new Observer(mHandler);
         mContext.getContentResolver().registerContentObserver(
-                System.getUriFor(System.VOLUME_SETTINGS[mStreamType]),
+                System.getUriFor(System.VOLUME_SETTINGS_INT[mStreamType]),
                 false, mVolumeObserver);
         mReceiver.setListening(true);
     }
diff --git a/core/java/android/preference/SwitchPreference.java b/core/java/android/preference/SwitchPreference.java
index aa8674e..1ec18bb 100644
--- a/core/java/android/preference/SwitchPreference.java
+++ b/core/java/android/preference/SwitchPreference.java
@@ -17,6 +17,7 @@
 package android.preference;
 
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -37,6 +38,7 @@
  * @attr ref android.R.styleable#SwitchPreference_disableDependentsState
  */
 public class SwitchPreference extends TwoStatePreference {
+    @UnsupportedAppUsage
     private final Listener mListener = new Listener();
 
     // Switch text for on and off states
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index 7037aca..2079a63 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -17,6 +17,7 @@
 package android.preference;
 
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.TypedArray;
@@ -193,6 +194,7 @@
      * Sync a summary view contained within view's subhierarchy with the correct summary text.
      * @param view View where a summary should be located
      */
+    @UnsupportedAppUsage
     void syncSummaryView(View view) {
         // Sync the summary view
         TextView summaryView = (TextView) view.findViewById(com.android.internal.R.id.summary);
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index 8a66c24..ea1d1eb 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -33,6 +34,7 @@
  */
 public class VolumePreference extends SeekBarDialogPreference implements
         PreferenceManager.OnActivityStopListener, View.OnKeyListener, SeekBarVolumizer.Callback {
+    @UnsupportedAppUsage
     private int mStreamType;
 
     /** May be null if the dialog isn't visible. */
@@ -52,6 +54,7 @@
         this(context, attrs, defStyleAttr, 0);
     }
 
+    @UnsupportedAppUsage
     public VolumePreference(Context context, AttributeSet attrs) {
         this(context, attrs, R.attr.seekBarDialogPreferenceStyle);
     }
@@ -196,7 +199,9 @@
     }
 
     public static class VolumeStore {
+        @UnsupportedAppUsage
         public int volume = -1;
+        @UnsupportedAppUsage
         public int originalVolume = -1;
     }
 
diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java
index 2bb7c2e..d1b6efc 100644
--- a/core/java/android/print/PrintDocumentAdapter.java
+++ b/core/java/android/print/PrintDocumentAdapter.java
@@ -16,6 +16,7 @@
 
 package android.print;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.ParcelFileDescriptor;
@@ -260,6 +261,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public WriteResultCallback() {
             /* do nothing - hide constructor */
         }
@@ -304,6 +306,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public LayoutResultCallback() {
             /* do nothing - hide constructor */
         }
diff --git a/core/java/android/print/PrintFileDocumentAdapter.java b/core/java/android/print/PrintFileDocumentAdapter.java
index a5f9305..eb4b315 100644
--- a/core/java/android/print/PrintFileDocumentAdapter.java
+++ b/core/java/android/print/PrintFileDocumentAdapter.java
@@ -118,7 +118,7 @@
         protected Void doInBackground(Void... params) {
             try (InputStream in = new FileInputStream(mFile);
                     OutputStream out = new FileOutputStream(mDestination.getFileDescriptor())) {
-                FileUtils.copy(in, out, null, mCancellationSignal);
+                FileUtils.copy(in, out, mCancellationSignal, null, null);
             } catch (OperationCanceledException e) {
                 // Ignored; already handled below
             } catch (IOException e) {
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 138477e..41f261b 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.os.Bundle;
@@ -549,6 +550,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PrintDocumentInfo getDocumentInfo() {
         return mDocumentInfo;
     }
@@ -639,6 +641,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Bundle getAdvancedOptions() {
         return mAdvancedOptions;
     }
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index e436bc6..e1ede93 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -22,6 +22,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.Application.ActivityLifecycleCallbacks;
 import android.content.ComponentName;
@@ -311,6 +312,7 @@
      * @param listener The listener to add.
      * @hide
      */
+    @UnsupportedAppUsage
     public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) {
         if (mService == null) {
             Log.w(LOG_TAG, "Feature android.software.print not available");
diff --git a/core/java/android/print/PrinterId.java b/core/java/android/print/PrinterId.java
index ff9c0df..659e56f 100644
--- a/core/java/android/print/PrinterId.java
+++ b/core/java/android/print/PrinterId.java
@@ -17,6 +17,7 @@
 package android.print;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -57,6 +58,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull ComponentName getServiceName() {
         return mServiceName;
     }
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index 67c6fb9..6427af6 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -15,12 +15,16 @@
  */
 package android.provider;
 
+import android.annotation.IntDef;
 import android.annotation.WorkerThread;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Bundle;
 import android.telecom.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * <p>
  * The contract between the blockednumber provider and applications. Contains definitions for
@@ -220,6 +224,63 @@
     public static final String RES_NUMBER_IS_BLOCKED = "blocked";
 
     /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            prefix = { "STATUS_" },
+            value = {STATUS_NOT_BLOCKED, STATUS_BLOCKED_IN_LIST, STATUS_BLOCKED_RESTRICTED,
+                    STATUS_BLOCKED_UNKNOWN_NUMBER, STATUS_BLOCKED_PAYPHONE,
+                    STATUS_BLOCKED_NOT_IN_CONTACTS})
+    public @interface BlockStatus {}
+
+    /**
+     * Integer reason code used with {@link #RES_BLOCK_STATUS} to indicate that a call was not
+     * blocked.
+     * @hide
+     */
+    public static final int STATUS_NOT_BLOCKED = 0;
+
+    /**
+     * Integer reason code used with {@link #RES_BLOCK_STATUS} to indicate that a call was blocked
+     * because it is in the list of blocked numbers maintained by the provider.
+     * @hide
+     */
+    public static final int STATUS_BLOCKED_IN_LIST = 1;
+
+    /**
+     * Integer reason code used with {@link #RES_BLOCK_STATUS} to indicate that a call was blocked
+     * because it is from a restricted number.
+     * @hide
+     */
+    public static final int STATUS_BLOCKED_RESTRICTED = 2;
+
+    /**
+     * Integer reason code used with {@link #RES_BLOCK_STATUS} to indicate that a call was blocked
+     * because it is from an unknown number.
+     * @hide
+     */
+    public static final int STATUS_BLOCKED_UNKNOWN_NUMBER = 3;
+
+    /**
+     * Integer reason code used with {@link #RES_BLOCK_STATUS} to indicate that a call was blocked
+     * because it is from a pay phone.
+     * @hide
+     */
+    public static final int STATUS_BLOCKED_PAYPHONE = 4;
+
+    /**
+     * Integer reason code used with {@link #RES_BLOCK_STATUS} to indicate that a call was blocked
+     * because it is from a number not in the users contacts.
+     * @hide
+     */
+    public static final int STATUS_BLOCKED_NOT_IN_CONTACTS = 5;
+
+    /**
+     * Integer reason indicating whether a call was blocked, and if so why.
+     * @hide
+     */
+    public static final String RES_BLOCK_STATUS = "block_status";
+
+    /** @hide */
     public static final String RES_NUM_ROWS_DELETED = "num_deleted";
 
     /** @hide */
@@ -411,19 +472,23 @@
          * @param context the context of the caller.
          * @param phoneNumber the number to check.
          * @param extras the extra attribute of the number.
-         * @return {@code true} if should block the number. {@code false} otherwise.
+         * @return result code indicating if the number should be blocked, and if so why.
+         *         Valid values are: {@link #STATUS_NOT_BLOCKED}, {@link #STATUS_BLOCKED_IN_LIST},
+         *         {@link #STATUS_BLOCKED_NOT_IN_CONTACTS}, {@link #STATUS_BLOCKED_PAYPHONE},
+         *         {@link #STATUS_BLOCKED_RESTRICTED}, {@link #STATUS_BLOCKED_UNKNOWN_NUMBER}.
          */
-        public static boolean shouldSystemBlockNumber(Context context, String phoneNumber,
+        public static int shouldSystemBlockNumber(Context context, String phoneNumber,
                 Bundle extras) {
             try {
                 final Bundle res = context.getContentResolver().call(
                         AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, extras);
-                return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
+                return res != null ? res.getInt(RES_BLOCK_STATUS, STATUS_NOT_BLOCKED) :
+                        BlockedNumberContract.STATUS_NOT_BLOCKED;
             } catch (NullPointerException | IllegalArgumentException ex) {
                 // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if
                 // either of these happen.
                 Log.w(null, "shouldSystemBlockNumber: provider not ready.");
-                return false;
+                return BlockedNumberContract.STATUS_NOT_BLOCKED;
             }
         }
 
@@ -504,6 +569,28 @@
         }
 
         /**
+         * Converts a block status constant to a string equivalent for logging.
+         * @hide
+         */
+        public static String blockStatusToString(int blockStatus) {
+            switch (blockStatus) {
+                case STATUS_NOT_BLOCKED:
+                    return "not blocked";
+                case STATUS_BLOCKED_IN_LIST:
+                    return "blocked - in list";
+                case STATUS_BLOCKED_RESTRICTED:
+                    return "blocked - restricted";
+                case STATUS_BLOCKED_UNKNOWN_NUMBER:
+                    return "blocked - unknown";
+                case STATUS_BLOCKED_PAYPHONE:
+                    return "blocked - payphone";
+                case STATUS_BLOCKED_NOT_IN_CONTACTS:
+                    return "blocked - not in contacts";
+            }
+            return "unknown";
+        }
+
+        /**
          * Represents the current status of
          * {@link #shouldSystemBlockNumber(Context, String, Bundle)}. If emergency services
          * have been contacted recently, {@link #isSuppressed} is {@code true}, and blocking
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 7d05522..30021b4 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -218,6 +219,7 @@
      *  the string.
      *  @hide pending API council approval
      */
+    @UnsupportedAppUsage
     public static final void sendString(Context c,
                                         String stringToSend,
                                         String chooserDialogTitle) {
@@ -323,6 +325,7 @@
      *  @hide pending API council approval
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final String[] getVisitedHistory(ContentResolver cr) {
         return new String[0];
     }
diff --git a/core/java/android/provider/BrowserContract.java b/core/java/android/provider/BrowserContract.java
index 118b5eb..57dde66 100644
--- a/core/java/android/provider/BrowserContract.java
+++ b/core/java/android/provider/BrowserContract.java
@@ -17,6 +17,7 @@
 package android.provider;
 
 import android.accounts.Account;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
 import android.content.ContentResolver;
@@ -46,6 +47,7 @@
     public static final String AUTHORITY = "com.android.browser";
 
     /** A content:// style uri to the authority for the browser provider */
+    @UnsupportedAppUsage
     public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
 
     /**
@@ -251,6 +253,7 @@
         /**
          * The content:// style URI for this table
          */
+        @UnsupportedAppUsage
         public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "bookmarks");
 
         /**
@@ -300,6 +303,7 @@
          * The content:// style URI for the default folder
          * @hide
          */
+        @UnsupportedAppUsage
         public static final Uri CONTENT_URI_DEFAULT_FOLDER =
                 Uri.withAppendedPath(CONTENT_URI, "folder");
 
@@ -320,6 +324,7 @@
          * @param folderId the ID of the folder to point to
          * @hide
          */
+        @UnsupportedAppUsage
         public static final Uri buildFolderUri(long folderId) {
             return ContentUris.withAppendedId(CONTENT_URI_DEFAULT_FOLDER, folderId);
         }
@@ -407,6 +412,7 @@
         /**
          * Directory under {@link Bookmarks#CONTENT_URI}
          */
+        @UnsupportedAppUsage
         public static final Uri CONTENT_URI =
                 AUTHORITY_URI.buildUpon().appendPath("accounts").build();
 
@@ -444,6 +450,7 @@
         /**
          * The content:// style URI for this table
          */
+        @UnsupportedAppUsage
         public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "history");
 
         /**
@@ -573,6 +580,7 @@
         /**
          * The content:// style URI for this table
          */
+        @UnsupportedAppUsage
         public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "images");
 
         /**
@@ -673,6 +681,7 @@
         /**
          * The content:// style URI for this table
          */
+        @UnsupportedAppUsage
         public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "combined");
 
         /**
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index d9ce57a..a8f3665 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -19,6 +19,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -1664,6 +1665,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static String[] PROVIDER_WRITABLE_COLUMNS = new String[] {
                 ACCOUNT_NAME,
                 ACCOUNT_TYPE,
@@ -2288,6 +2290,7 @@
          *         if no such alarm exists.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final long findNextAlarmTime(ContentResolver cr, long millis) {
             String selection = ALARM_TIME + ">=" + millis;
             // TODO: construct an explicit SQL query so that we can add
@@ -2321,6 +2324,7 @@
          * @param manager the AlarmManager
          * @hide
          */
+        @UnsupportedAppUsage
         public static final void rescheduleMissedAlarms(ContentResolver cr,
                 Context context, AlarmManager manager) {
             // Get all the alerts that have been scheduled but have not fired
@@ -2377,6 +2381,7 @@
          *            epoch
          * @hide
          */
+        @UnsupportedAppUsage
         public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) {
             if (DEBUG) {
                 Time time = new Time();
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 70de09e..bc72c4e 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -17,6 +17,7 @@
 
 package android.provider;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -609,6 +610,7 @@
          *        as they don't have permissions.
          * {@hide}
          */
+        @UnsupportedAppUsage
         public static Uri addCall(CallerInfo ci, Context context, String number,
                 String postDialDigits, String viaNumber, int presentation, int callType,
                 int features, PhoneAccountHandle accountHandle, long start, int duration,
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index f7409d0..112329e 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -187,8 +188,7 @@
     /**
      * A boolean parameter for {@link Contacts#CONTENT_STREQUENT_URI} and
      * {@link Contacts#CONTENT_STREQUENT_FILTER_URI}, which requires the ContactsProvider to
-     * return only phone-related results. For example, frequently contacted person list should
-     * include persons contacted via phone (not email, sms, etc.)
+     * return only phone-related results.
      */
     public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only";
 
@@ -870,13 +870,23 @@
         /**
          * The number of times a contact has been contacted
          * <P>Type: INTEGER</P>
+         *
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}. This column
+         * always contains 0.
          */
+        @Deprecated
         public static final String TIMES_CONTACTED = "times_contacted";
 
         /**
          * The last time a contact was contacted.
          * <P>Type: INTEGER</P>
+         *
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}. This column
+         * always contains 0.
          */
+        @Deprecated
         public static final String LAST_TIME_CONTACTED = "last_time_contacted";
 
         /** @hide Raw value. */
@@ -1313,8 +1323,7 @@
      * of the newly inserted raw contact.</dd>
      * <dt><b>Update</b></dt>
      * <dd>Only certain columns of Contact are modifiable:
-     * {@link #TIMES_CONTACTED}, {@link #LAST_TIME_CONTACTED}, {@link #STARRED},
-     * {@link #CUSTOM_RINGTONE}, {@link #SEND_TO_VOICEMAIL}. Changing any of
+     * {@link #STARRED}, {@link #CUSTOM_RINGTONE}, {@link #SEND_TO_VOICEMAIL}. Changing any of
      * these columns on the Contact also changes them on all constituent raw
      * contacts.</dd>
      * <dt><b>Delete</b></dt>
@@ -1415,27 +1424,6 @@
      * </tr>
      * <tr>
      * <td>int</td>
-     * <td>{@link #TIMES_CONTACTED}</td>
-     * <td>read/write</td>
-     * <td>The number of times the contact has been contacted. See
-     * {@link #markAsContacted}. When raw contacts are aggregated, this field is
-     * computed automatically as the maximum number of times contacted among all
-     * constituent raw contacts. Setting this field automatically changes the
-     * corresponding field on all constituent raw contacts.</td>
-     * </tr>
-     * <tr>
-     * <td>long</td>
-     * <td>{@link #LAST_TIME_CONTACTED}</td>
-     * <td>read/write</td>
-     * <td>The timestamp of the last time the contact was contacted. See
-     * {@link #markAsContacted}. Setting this field also automatically
-     * increments {@link #TIMES_CONTACTED}. When raw contacts are aggregated,
-     * this field is computed automatically as the latest time contacted of all
-     * constituent raw contacts. Setting this field automatically changes the
-     * corresponding field on all constituent raw contacts.</td>
-     * </tr>
-     * <tr>
-     * <td>int</td>
      * <td>{@link #STARRED}</td>
      * <td>read/write</td>
      * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise.
@@ -1532,6 +1520,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final Uri CORP_CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI,
                 "contacts_corp");
 
@@ -1696,16 +1685,12 @@
          * @param resolver the ContentResolver to use
          * @param contactId the person who was contacted
          *
-         * @deprecated The class DataUsageStatUpdater of the Android support library should
-         *     be used instead.
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}. This method
+         * is no-op.
          */
         @Deprecated
         public static void markAsContacted(ContentResolver resolver, long contactId) {
-            Uri uri = ContentUris.withAppendedId(CONTENT_URI, contactId);
-            ContentValues values = new ContentValues();
-            // TIMES_CONTACTED will be incremented when LAST_TIME_CONTACTED is modified.
-            values.put(LR_LAST_TIME_CONTACTED, System.currentTimeMillis());
-            resolver.update(uri, values, null, null);
         }
 
         /**
@@ -1727,15 +1712,21 @@
 
         /**
          * The content:// style URI for this table joined with useful data from
-         * {@link ContactsContract.Data}, filtered to include only starred contacts
-         * and the most frequently contacted contacts.
+         * {@link ContactsContract.Data}, filtered to include only starred contacts.
+         * Frequent contacts are no longer included in the result as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}.
          */
         public static final Uri CONTENT_STREQUENT_URI = Uri.withAppendedPath(
                 CONTENT_URI, "strequent");
 
         /**
          * The content:// style URI for showing a list of frequently contacted people.
+         *
+         * @deprecated Frequent contacts are no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}.
+         * This URI always returns an empty cursor.
          */
+        @Deprecated
         public static final Uri CONTENT_FREQUENT_URI = Uri.withAppendedPath(
                 CONTENT_URI, "frequent");
 
@@ -2024,6 +2015,7 @@
             /**
              * @hide
              */
+            @UnsupportedAppUsage
             public static final Builder builder() {
                 return new Builder();
             }
@@ -2631,27 +2623,6 @@
      * </tr>
      * <tr>
      * <td>int</td>
-     * <td>{@link #TIMES_CONTACTED}</td>
-     * <td>read/write</td>
-     * <td>The number of times the contact has been contacted. To have an effect
-     * on the corresponding value of the aggregate contact, this field
-     * should be set at the time the raw contact is inserted.
-     * After that, this value is typically updated via
-     * {@link ContactsContract.Contacts#markAsContacted}.</td>
-     * </tr>
-     * <tr>
-     * <td>long</td>
-     * <td>{@link #LAST_TIME_CONTACTED}</td>
-     * <td>read/write</td>
-     * <td>The timestamp of the last time the contact was contacted. To have an effect
-     * on the corresponding value of the aggregate contact, this field
-     * should be set at the time the raw contact is inserted.
-     * After that, this value is typically updated via
-     * {@link ContactsContract.Contacts#markAsContacted}.
-     * </td>
-     * </tr>
-     * <tr>
-     * <td>int</td>
      * <td>{@link #STARRED}</td>
      * <td>read/write</td>
      * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise.
@@ -4286,10 +4257,22 @@
      * Columns in the Data_Usage_Stat table
      */
     protected interface DataUsageStatColumns {
-        /** The last time (in milliseconds) this {@link Data} was used. */
+        /**
+         * The last time (in milliseconds) this {@link Data} was used.
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}.
+         * This column always contains 0.
+         */
+        @Deprecated
         public static final String LAST_TIME_USED = "last_time_used";
 
-        /** The number of times the referenced {@link Data} has been used. */
+        /**
+         * The number of times the referenced {@link Data} has been used.
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}.
+         * This column always contains 0.
+         */
+        @Deprecated
         public static final String TIMES_USED = "times_used";
 
         /** @hide Raw value. */
@@ -4765,18 +4748,6 @@
      * </tr>
      * <tr>
      * <td>int</td>
-     * <td>{@link #TIMES_CONTACTED}</td>
-     * <td>read-only</td>
-     * <td>See {@link ContactsContract.Contacts}.</td>
-     * </tr>
-     * <tr>
-     * <td>long</td>
-     * <td>{@link #LAST_TIME_CONTACTED}</td>
-     * <td>read-only</td>
-     * <td>See {@link ContactsContract.Contacts}.</td>
-     * </tr>
-     * <tr>
-     * <td>int</td>
      * <td>{@link #STARRED}</td>
      * <td>read-only</td>
      * <td>See {@link ContactsContract.Contacts}.</td>
@@ -5221,18 +5192,6 @@
      * </tr>
      * <tr>
      * <td>int</td>
-     * <td>{@link #TIMES_CONTACTED}</td>
-     * <td>read-only</td>
-     * <td>See {@link ContactsContract.Contacts}.</td>
-     * </tr>
-     * <tr>
-     * <td>long</td>
-     * <td>{@link #LAST_TIME_CONTACTED}</td>
-     * <td>read-only</td>
-     * <td>See {@link ContactsContract.Contacts}.</td>
-     * </tr>
-     * <tr>
-     * <td>int</td>
      * <td>{@link #STARRED}</td>
      * <td>read-only</td>
      * <td>See {@link ContactsContract.Contacts}.</td>
@@ -6145,6 +6104,7 @@
              * @hide
              */
             @Deprecated
+            @UnsupportedAppUsage
             public static final CharSequence getDisplayLabel(Context context, int type,
                     CharSequence label) {
                 return getTypeLabel(context.getResources(), type, label);
@@ -8305,7 +8265,12 @@
      * boolean successful = resolver.delete(DataUsageFeedback.DELETE_USAGE_URI, null, null) > 0;
      * </pre>
      * </p>
+     *
+     * @deprecated Contacts affinity information is no longer supported as of
+     * Android version {@link android.os.Build.VERSION_CODES#Q}.
+     * Both update and delete calls are always ignored.
      */
+    @Deprecated
     public static final class DataUsageFeedback {
 
         /**
@@ -8522,6 +8487,7 @@
          * Constructs the QuickContacts intent.
          * @hide
          */
+        @UnsupportedAppUsage
         public static Intent composeQuickContactsIntent(Context context, Rect target,
                 Uri lookupUri, int mode, String[] excludeMimes) {
             // When launching from an Activiy, we don't want to start a new task, but otherwise
@@ -8925,10 +8891,6 @@
          * +<phone>", etc. If you must show the prefix text in the Contacts App, please use a
          * different DATA# column, and update your contacts.xml to point to this new column. </em>
          * </li>
-         * <li>Everytime the user sends a message to a contact, your app may choose to update the
-         * {@link ContactOptionsColumns#TIMES_CONTACTED} entry through DataUsageFeedback class.
-         * Doing this will allow Voice Assistant to bias speech recognition to contacts frequently
-         * contacted, this is particularly useful for contact names that are hard to pronounce.</li>
          * </ul>
          * If the app chooses not to integrate with the Contacts Provider (in particular, when
          * either METADATA_ACCOUNT_TYPE or METADATA_MIMETYPE field is missing), Voice Assistant
diff --git a/core/java/android/provider/ContactsInternal.java b/core/java/android/provider/ContactsInternal.java
index 362eba9..69c4b9b 100644
--- a/core/java/android/provider/ContactsInternal.java
+++ b/core/java/android/provider/ContactsInternal.java
@@ -15,6 +15,7 @@
  */
 package android.provider;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.admin.DevicePolicyManager;
 import android.content.ActivityNotFoundException;
 import android.content.ContentUris;
@@ -54,6 +55,7 @@
     /**
      * Called by {@link ContactsContract} to star Quick Contact, possibly on the managed profile.
      */
+    @UnsupportedAppUsage
     public static void startQuickContactWithErrorToast(Context context, Intent intent) {
         final Uri uri = intent.getData();
 
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index a80dced..b12d9cf 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -23,6 +23,7 @@
 import static com.android.internal.util.Preconditions.checkCollectionNotEmpty;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -100,7 +101,8 @@
     public static final String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
 
     /** {@hide} */
-    public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
+    @Deprecated
+    public static final String EXTRA_PACKAGE_NAME = Intent.EXTRA_PACKAGE_NAME;
 
     /** {@hide} */
     public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
@@ -635,6 +637,7 @@
          * @see #COLUMN_FLAGS
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int FLAG_ADVANCED = 1 << 17;
 
         /**
@@ -698,6 +701,7 @@
     public static final String EXTRA_RESULT = "result";
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static final String METHOD_CREATE_DOCUMENT = "android:createDocument";
     /** {@hide} */
     public static final String METHOD_RENAME_DOCUMENT = "android:renameDocument";
@@ -733,11 +737,13 @@
 
     private static final String PATH_ROOT = "root";
     private static final String PATH_RECENT = "recent";
+    @UnsupportedAppUsage
     private static final String PATH_DOCUMENT = "document";
     private static final String PATH_CHILDREN = "children";
     private static final String PATH_SEARCH = "search";
     // TODO(b/72055774): make private again once ScopedAccessProvider is refactored
     /** {@hide} */
+    @UnsupportedAppUsage
     public static final String PATH_TREE = "tree";
 
     private static final String PARAM_QUERY = "query";
@@ -1021,6 +1027,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static Uri setManageMode(Uri uri) {
         return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
     }
@@ -1064,6 +1071,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static Bitmap getDocumentThumbnail(
             ContentProviderClient client, Uri documentUri, Point size, CancellationSignal signal)
             throws RemoteException, IOException {
@@ -1319,6 +1327,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static Uri moveDocument(ContentProviderClient client, Uri sourceDocumentUri,
             Uri sourceParentDocumentUri, Uri targetParentDocumentUri) throws RemoteException {
         final Bundle in = new Bundle();
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index a2c5a92..e5fd29c 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.DownloadManager;
 import android.content.Context;
 import android.net.NetworkPolicyManager;
@@ -88,6 +89,7 @@
         /**
          * The content:// URI to access downloads owned by the caller's UID.
          */
+        @UnsupportedAppUsage
         public static final Uri CONTENT_URI =
                 Uri.parse("content://downloads/my_downloads");
 
@@ -95,6 +97,7 @@
          * The content URI for accessing all downloads across all UIDs (requires the
          * ACCESS_ALL_DOWNLOADS permission).
          */
+        @UnsupportedAppUsage
         public static final Uri ALL_DOWNLOADS_CONTENT_URI =
                 Uri.parse("content://downloads/all_downloads");
 
@@ -105,6 +108,7 @@
          * The content URI for accessing publicly accessible downloads (i.e., it requires no
          * permissions to access this downloaded file)
          */
+        @UnsupportedAppUsage
         public static final Uri PUBLICLY_ACCESSIBLE_DOWNLOADS_URI =
                 Uri.parse("content://downloads/" + PUBLICLY_ACCESSIBLE_DOWNLOADS_URI_SEGMENT);
 
@@ -134,6 +138,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init/Read</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_URI = "uri";
 
         /**
@@ -163,6 +168,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_FILE_NAME_HINT = "hint";
 
         /**
@@ -178,6 +184,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init/Read</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_MIME_TYPE = "mimetype";
 
         /**
@@ -186,6 +193,7 @@
          * <P>Type: INTEGER</P>
          * <P>Owner can Init</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_DESTINATION = "destination";
 
         /**
@@ -195,6 +203,7 @@
          * <P>Type: INTEGER</P>
          * <P>Owner can Init/Read/Write</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_VISIBILITY = "visibility";
 
         /**
@@ -231,6 +240,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init/Read</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_NOTIFICATION_PACKAGE = "notificationpackage";
 
         /**
@@ -241,6 +251,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init/Read</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_NOTIFICATION_CLASS = "notificationclass";
 
         /**
@@ -249,6 +260,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_NOTIFICATION_EXTRAS = "notificationextras";
 
         /**
@@ -258,6 +270,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_COOKIE_DATA = "cookiedata";
 
         /**
@@ -274,6 +287,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_REFERER = "referer";
 
         /**
@@ -311,6 +325,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init/Read/Write</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_TITLE = "title";
 
         /**
@@ -320,6 +335,7 @@
          * <P>Type: TEXT</P>
          * <P>Owner can Init/Read/Write</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_DESCRIPTION = "description";
 
         /**
@@ -328,6 +344,7 @@
          * <P>Type: BOOLEAN</P>
          * <P>Owner can Init/Read</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_IS_PUBLIC_API = "is_public_api";
 
         /**
@@ -336,6 +353,7 @@
          * <P>Type: INTEGER</P>
          * <P>Owner can Init/Read</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_ALLOWED_NETWORK_TYPES = "allowed_network_types";
 
         /**
@@ -344,6 +362,7 @@
          * <P>Type: BOOLEAN</P>
          * <P>Owner can Init/Read</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_ALLOW_ROAMING = "allow_roaming";
 
         /**
@@ -360,6 +379,7 @@
          * <P>Type: INTEGER</P>
          * <P>Owner can Init/Read</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI = "is_visible_in_downloads_ui";
 
         /**
@@ -376,6 +396,7 @@
          * <P>Type: BOOLEAN</P>
          * <P>Owner can Read</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_DELETED = "deleted";
 
         /**
@@ -392,6 +413,7 @@
          * It can take the values: null or 0(not scanned), 1(scanned), 2 (not scannable).
          * <P>Type: TEXT</P>
          */
+        @UnsupportedAppUsage
         public static final String COLUMN_MEDIA_SCANNED = "scanned";
 
         /**
@@ -465,6 +487,7 @@
          * immediately after they are used, and are kept around by the download
          * manager as long as space is available.
          */
+        @UnsupportedAppUsage
         public static final int DESTINATION_CACHE_PARTITION_PURGEABLE = 2;
 
         /**
@@ -478,6 +501,7 @@
          * This download will be saved to the location given by the file URI in
          * {@link #COLUMN_FILE_NAME_HINT}.
          */
+        @UnsupportedAppUsage
         public static final int DESTINATION_FILE_URI = 4;
 
         /**
@@ -525,6 +549,7 @@
         /**
          * Returns whether the status is a success (i.e. 2xx).
          */
+        @UnsupportedAppUsage
         public static boolean isStatusSuccess(int status) {
             return (status >= 200 && status < 300);
         }
@@ -532,6 +557,7 @@
         /**
          * Returns whether the status is an error (i.e. 4xx or 5xx).
          */
+        @UnsupportedAppUsage
         public static boolean isStatusError(int status) {
             return (status >= 400 && status < 600);
         }
@@ -556,6 +582,7 @@
          * @param visibility the value of {@link #COLUMN_VISIBILITY}.
          * @return true if the notification should be displayed. false otherwise.
          */
+        @UnsupportedAppUsage
         public static boolean isNotificationToBeDisplayed(int visibility) {
             return visibility == DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED ||
                     visibility == DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION;
@@ -565,6 +592,7 @@
          * Returns whether the download has completed (either with success or
          * error).
          */
+        @UnsupportedAppUsage
         public static boolean isStatusCompleted(int status) {
             return (status >= 200 && status < 300) || (status >= 400 && status < 600);
         }
@@ -795,6 +823,7 @@
              * Prefix for ContentValues keys that contain HTTP header lines, to be passed to
              * DownloadProvider.insert().
              */
+            @UnsupportedAppUsage
             public static final String INSERT_KEY_PREFIX = "http_header_";
         }
     }
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 4b45e32..189b7b4 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -16,8 +16,12 @@
 
 package android.provider;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
+import android.content.ClipData;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -25,22 +29,23 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.UriPermission;
+import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteException;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
-import android.media.MiniThumbFile;
-import android.media.ThumbnailUtils;
+import android.graphics.Point;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Environment;
-import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.service.media.CameraPrewarmService;
+import android.util.ArrayMap;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
+
 import libcore.io.IoUtils;
 
 import java.io.File;
@@ -49,7 +54,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -455,6 +459,7 @@
          * <P>Type: INTEGER (boolean)</P>
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String IS_DRM = "is_drm";
 
         /**
@@ -466,6 +471,12 @@
          * The height of the image/video in pixels.
          */
         public static final String HEIGHT = "height";
+
+        /**
+         * Package that contributed this media.
+         * @hide
+         */
+        public static final String OWNER_PACKAGE_NAME = "owner_package_name";
      }
 
     /**
@@ -506,6 +517,7 @@
          * For use only by the MTP implementation.
          * @hide
          */
+        @UnsupportedAppUsage
         public static Uri getMtpObjectsUri(String volumeName) {
             return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
                     "/object");
@@ -515,6 +527,7 @@
          * For use only by the MTP implementation.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final Uri getMtpObjectsUri(String volumeName,
                 long fileId) {
             return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
@@ -525,6 +538,7 @@
          * Used to implement the MTP GetObjectReferences and SetObjectReferences commands.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final Uri getMtpReferencesUri(String volumeName,
                 long fileId) {
             return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
@@ -549,6 +563,7 @@
              * <P>Type: INTEGER</P>
              * @hide
              */
+            @UnsupportedAppUsage
             public static final String STORAGE_ID = "storage_id";
 
             /**
@@ -556,6 +571,7 @@
              * <P>Type: INTEGER</P>
              * @hide
              */
+            @UnsupportedAppUsage
             public static final String FORMAT = "format";
 
             /**
@@ -611,178 +627,79 @@
         }
     }
 
+    /** @hide */
+    public static class ThumbnailConstants {
+        public static final int MINI_KIND = 1;
+        public static final int FULL_SCREEN_KIND = 2;
+        public static final int MICRO_KIND = 3;
+
+        public static final Point MINI_SIZE = new Point(512, 384);
+        public static final Point MICRO_SIZE = new Point(96, 96);
+    }
+
     /**
      * This class is used internally by Images.Thumbnails and Video.Thumbnails, it's not intended
      * to be accessed elsewhere.
      */
     private static class InternalThumbnails implements BaseColumns {
-        private static final int MINI_KIND = 1;
-        private static final int FULL_SCREEN_KIND = 2;
-        private static final int MICRO_KIND = 3;
-        private static final String[] PROJECTION = new String[] {_ID, MediaColumns.DATA};
-        static final int DEFAULT_GROUP_ID = 0;
-        private static final Object sThumbBufLock = new Object();
-        private static byte[] sThumbBuf;
-
-        private static Bitmap getMiniThumbFromFile(
-                Cursor c, Uri baseUri, ContentResolver cr, BitmapFactory.Options options) {
-            Bitmap bitmap = null;
-            Uri thumbUri = null;
-            try {
-                long thumbId = c.getLong(0);
-                String filePath = c.getString(1);
-                thumbUri = ContentUris.withAppendedId(baseUri, thumbId);
-                ParcelFileDescriptor pfdInput = cr.openFileDescriptor(thumbUri, "r");
-                bitmap = BitmapFactory.decodeFileDescriptor(
-                        pfdInput.getFileDescriptor(), null, options);
-                pfdInput.close();
-            } catch (FileNotFoundException ex) {
-                Log.e(TAG, "couldn't open thumbnail " + thumbUri + "; " + ex);
-            } catch (IOException ex) {
-                Log.e(TAG, "couldn't open thumbnail " + thumbUri + "; " + ex);
-            } catch (OutOfMemoryError ex) {
-                Log.e(TAG, "failed to allocate memory for thumbnail "
-                        + thumbUri + "; " + ex);
-            }
-            return bitmap;
-        }
+        /**
+         * Currently outstanding thumbnail requests that can be cancelled.
+         */
+        @GuardedBy("sPending")
+        private static ArrayMap<Uri, CancellationSignal> sPending = new ArrayMap<>();
 
         /**
-         * This method cancels the thumbnail request so clients waiting for getThumbnail will be
-         * interrupted and return immediately. Only the original process which made the getThumbnail
-         * requests can cancel their own requests.
+         * Make a blocking request to obtain the given thumbnail, generating it
+         * if needed.
          *
-         * @param cr ContentResolver
-         * @param origId original image or video id. use -1 to cancel all requests.
-         * @param groupId the same groupId used in getThumbnail
-         * @param baseUri the base URI of requested thumbnails
+         * @see #cancelThumbnail(ContentResolver, Uri)
          */
-        static void cancelThumbnailRequest(ContentResolver cr, long origId, Uri baseUri,
-                long groupId) {
-            Uri cancelUri = baseUri.buildUpon().appendQueryParameter("cancel", "1")
-                    .appendQueryParameter("orig_id", String.valueOf(origId))
-                    .appendQueryParameter("group_id", String.valueOf(groupId)).build();
-            Cursor c = null;
-            try {
-                c = cr.query(cancelUri, PROJECTION, null, null, null);
+        static @Nullable Bitmap getThumbnail(@NonNull ContentResolver cr, @NonNull Uri uri,
+                int kind, @Nullable BitmapFactory.Options opts) {
+            final Bundle openOpts = new Bundle();
+            if (kind == ThumbnailConstants.MICRO_KIND) {
+                openOpts.putParcelable(ContentResolver.EXTRA_SIZE, ThumbnailConstants.MICRO_SIZE);
+            } else if (kind == ThumbnailConstants.MINI_KIND) {
+                openOpts.putParcelable(ContentResolver.EXTRA_SIZE, ThumbnailConstants.MINI_SIZE);
+            } else {
+                throw new IllegalArgumentException("Unsupported kind: " + kind);
             }
-            finally {
-                if (c != null) c.close();
+
+            CancellationSignal signal = null;
+            synchronized (sPending) {
+                signal = sPending.get(uri);
+                if (signal == null) {
+                    signal = new CancellationSignal();
+                    sPending.put(uri, signal);
+                }
             }
-        }
 
-        /**
-         * This method ensure thumbnails associated with origId are generated and decode the byte
-         * stream from database (MICRO_KIND) or file (MINI_KIND).
-         *
-         * Special optimization has been done to avoid further IPC communication for MICRO_KIND
-         * thumbnails.
-         *
-         * @param cr ContentResolver
-         * @param origId original image or video id
-         * @param kind could be MINI_KIND or MICRO_KIND
-         * @param options this is only used for MINI_KIND when decoding the Bitmap
-         * @param baseUri the base URI of requested thumbnails
-         * @param groupId the id of group to which this request belongs
-         * @return Bitmap bitmap of specified thumbnail kind
-         */
-        static Bitmap getThumbnail(ContentResolver cr, long origId, long groupId, int kind,
-                BitmapFactory.Options options, Uri baseUri, boolean isVideo) {
-            Bitmap bitmap = null;
-            // Log.v(TAG, "getThumbnail: origId="+origId+", kind="+kind+", isVideo="+isVideo);
-            // If the magic is non-zero, we simply return thumbnail if it does exist.
-            // querying MediaProvider and simply return thumbnail.
-            MiniThumbFile thumbFile = MiniThumbFile.instance(
-                    isVideo ? Video.Media.EXTERNAL_CONTENT_URI : Images.Media.EXTERNAL_CONTENT_URI);
-            Cursor c = null;
-            try {
-                long magic = thumbFile.getMagic(origId);
-                if (magic != 0) {
-                    if (kind == MICRO_KIND) {
-                        synchronized (sThumbBufLock) {
-                            if (sThumbBuf == null) {
-                                sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
-                            }
-                            if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) {
-                                bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length);
-                                if (bitmap == null) {
-                                    Log.w(TAG, "couldn't decode byte array.");
-                                }
-                            }
-                        }
-                        return bitmap;
-                    } else if (kind == MINI_KIND) {
-                        String column = isVideo ? "video_id=" : "image_id=";
-                        c = cr.query(baseUri, PROJECTION, column + origId, null, null);
-                        if (c != null && c.moveToFirst()) {
-                            bitmap = getMiniThumbFromFile(c, baseUri, cr, options);
-                            if (bitmap != null) {
-                                return bitmap;
-                            }
-                        }
-                    }
-                }
-
-                Uri blockingUri = baseUri.buildUpon().appendQueryParameter("blocking", "1")
-                        .appendQueryParameter("orig_id", String.valueOf(origId))
-                        .appendQueryParameter("group_id", String.valueOf(groupId)).build();
-                if (c != null) c.close();
-                c = cr.query(blockingUri, PROJECTION, null, null, null);
-                // This happens when original image/video doesn't exist.
-                if (c == null) return null;
-
-                // Assuming thumbnail has been generated, at least original image exists.
-                if (kind == MICRO_KIND) {
-                    synchronized (sThumbBufLock) {
-                        if (sThumbBuf == null) {
-                            sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
-                        }
-                        Arrays.fill(sThumbBuf, (byte)0);
-                        if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) {
-                            bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length);
-                            if (bitmap == null) {
-                                Log.w(TAG, "couldn't decode byte array.");
-                            }
-                        }
-                    }
-                } else if (kind == MINI_KIND) {
-                    if (c.moveToFirst()) {
-                        bitmap = getMiniThumbFromFile(c, baseUri, cr, options);
-                    }
-                } else {
-                    throw new IllegalArgumentException("Unsupported kind: " + kind);
-                }
-
-                // We probably run out of space, so create the thumbnail in memory.
-                if (bitmap == null) {
-                    Log.v(TAG, "Create the thumbnail in memory: origId=" + origId
-                            + ", kind=" + kind + ", isVideo="+isVideo);
-                    Uri uri = Uri.parse(
-                            baseUri.buildUpon().appendPath(String.valueOf(origId))
-                                    .toString().replaceFirst("thumbnails", "media"));
-                    if (c != null) c.close();
-                    c = cr.query(uri, PROJECTION, null, null, null);
-                    if (c == null || !c.moveToFirst()) {
-                        return null;
-                    }
-                    String filePath = c.getString(1);
-                    if (filePath != null) {
-                        if (isVideo) {
-                            bitmap = ThumbnailUtils.createVideoThumbnail(filePath, kind);
-                        } else {
-                            bitmap = ThumbnailUtils.createImageThumbnail(filePath, kind);
-                        }
-                    }
-                }
-            } catch (SQLiteException ex) {
-                Log.w(TAG, ex);
+            try (AssetFileDescriptor afd = cr.openTypedAssetFileDescriptor(uri,
+                    "image/*", openOpts, signal)) {
+                return BitmapFactory.decodeFileDescriptor(afd.getFileDescriptor(), null, opts);
+            } catch (IOException e) {
+                Log.w(TAG, "Failed to obtain thumbnail for " + uri, e);
+                return null;
             } finally {
-                if (c != null) c.close();
-                // To avoid file descriptor leak in application process.
-                thumbFile.deactivate();
-                thumbFile = null;
+                synchronized (sPending) {
+                    sPending.remove(uri);
+                }
             }
-            return bitmap;
+        }
+
+        /**
+         * This method cancels the thumbnail request so clients waiting for
+         * {@link #getThumbnail} will be interrupted and return immediately.
+         * Only the original process which made the request can cancel their own
+         * requests.
+         */
+        static void cancelThumbnail(@NonNull ContentResolver cr, @NonNull Uri uri) {
+            synchronized (sPending) {
+                final CancellationSignal signal = sPending.get(uri);
+                if (signal != null) {
+                    signal.cancel();
+                }
+            }
         }
     }
 
@@ -916,48 +833,6 @@
                 }
             }
 
-            private static final Bitmap StoreThumbnail(
-                    ContentResolver cr,
-                    Bitmap source,
-                    long id,
-                    float width, float height,
-                    int kind) {
-                // create the matrix to scale it
-                Matrix matrix = new Matrix();
-
-                float scaleX = width / source.getWidth();
-                float scaleY = height / source.getHeight();
-
-                matrix.setScale(scaleX, scaleY);
-
-                Bitmap thumb = Bitmap.createBitmap(source, 0, 0,
-                                                   source.getWidth(),
-                                                   source.getHeight(), matrix,
-                                                   true);
-
-                ContentValues values = new ContentValues(4);
-                values.put(Images.Thumbnails.KIND,     kind);
-                values.put(Images.Thumbnails.IMAGE_ID, (int)id);
-                values.put(Images.Thumbnails.HEIGHT,   thumb.getHeight());
-                values.put(Images.Thumbnails.WIDTH,    thumb.getWidth());
-
-                Uri url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values);
-
-                try {
-                    OutputStream thumbOut = cr.openOutputStream(url);
-
-                    thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut);
-                    thumbOut.close();
-                    return thumb;
-                }
-                catch (FileNotFoundException ex) {
-                    return null;
-                }
-                catch (IOException ex) {
-                    return null;
-                }
-            }
-
             /**
              * Insert an image and create a thumbnail for it.
              *
@@ -990,12 +865,9 @@
                         }
 
                         long id = ContentUris.parseId(url);
-                        // Wait until MINI_KIND thumbnail is generated.
-                        Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id,
-                                Images.Thumbnails.MINI_KIND, null);
-                        // This is for backward compatibility.
-                        Bitmap microThumb = StoreThumbnail(cr, miniThumb, id, 50F, 50F,
-                                Images.Thumbnails.MICRO_KIND);
+                        // Block until we've generated common thumbnails
+                        Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null);
+                        Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MICRO_KIND, null);
                     } else {
                         Log.e(TAG, "Failed to create thumbnail, removing original");
                         cr.delete(url, null, null);
@@ -1085,8 +957,9 @@
              * @param origId original image id
              */
             public static void cancelThumbnailRequest(ContentResolver cr, long origId) {
-                InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI,
-                        InternalThumbnails.DEFAULT_GROUP_ID);
+                final Uri uri = ContentUris.withAppendedId(
+                        Images.Media.EXTERNAL_CONTENT_URI, origId);
+                InternalThumbnails.cancelThumbnail(cr, uri);
             }
 
             /**
@@ -1102,9 +975,9 @@
              */
             public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind,
                     BitmapFactory.Options options) {
-                return InternalThumbnails.getThumbnail(cr, origId,
-                        InternalThumbnails.DEFAULT_GROUP_ID, kind, options,
-                        EXTERNAL_CONTENT_URI, false);
+                final Uri uri = ContentUris.withAppendedId(
+                        Images.Media.EXTERNAL_CONTENT_URI, origId);
+                return InternalThumbnails.getThumbnail(cr, uri, kind, options);
             }
 
             /**
@@ -1117,7 +990,7 @@
              * @param groupId the same groupId used in getThumbnail.
              */
             public static void cancelThumbnailRequest(ContentResolver cr, long origId, long groupId) {
-                InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI, groupId);
+                cancelThumbnailRequest(cr, origId);
             }
 
             /**
@@ -1134,8 +1007,7 @@
              */
             public static Bitmap getThumbnail(ContentResolver cr, long origId, long groupId,
                     int kind, BitmapFactory.Options options) {
-                return InternalThumbnails.getThumbnail(cr, origId, groupId, kind, options,
-                        EXTERNAL_CONTENT_URI, false);
+                return getThumbnail(cr, origId, kind, options);
             }
 
             /**
@@ -1193,9 +1065,9 @@
              */
             public static final String KIND = "kind";
 
-            public static final int MINI_KIND = 1;
-            public static final int FULL_SCREEN_KIND = 2;
-            public static final int MICRO_KIND = 3;
+            public static final int MINI_KIND = ThumbnailConstants.MINI_KIND;
+            public static final int FULL_SCREEN_KIND = ThumbnailConstants.FULL_SCREEN_KIND;
+            public static final int MICRO_KIND = ThumbnailConstants.MICRO_KIND;
             /**
              * The blob raw data of thumbnail
              * <P>Type: DATA STREAM</P>
@@ -2155,8 +2027,9 @@
              * @param origId original video id
              */
             public static void cancelThumbnailRequest(ContentResolver cr, long origId) {
-                InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI,
-                        InternalThumbnails.DEFAULT_GROUP_ID);
+                final Uri uri = ContentUris.withAppendedId(
+                        Video.Media.EXTERNAL_CONTENT_URI, origId);
+                InternalThumbnails.cancelThumbnail(cr, uri);
             }
 
             /**
@@ -2172,9 +2045,9 @@
              */
             public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind,
                     BitmapFactory.Options options) {
-                return InternalThumbnails.getThumbnail(cr, origId,
-                        InternalThumbnails.DEFAULT_GROUP_ID, kind, options,
-                        EXTERNAL_CONTENT_URI, true);
+                final Uri uri = ContentUris.withAppendedId(
+                        Video.Media.EXTERNAL_CONTENT_URI, origId);
+                return InternalThumbnails.getThumbnail(cr, uri, kind, options);
             }
 
             /**
@@ -2191,8 +2064,7 @@
              */
             public static Bitmap getThumbnail(ContentResolver cr, long origId, long groupId,
                     int kind, BitmapFactory.Options options) {
-                return InternalThumbnails.getThumbnail(cr, origId, groupId, kind, options,
-                        EXTERNAL_CONTENT_URI, true);
+                return getThumbnail(cr, origId, kind, options);
             }
 
             /**
@@ -2205,7 +2077,7 @@
              * @param groupId the same groupId used in getThumbnail.
              */
             public static void cancelThumbnailRequest(ContentResolver cr, long origId, long groupId) {
-                InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI, groupId);
+                cancelThumbnailRequest(cr, origId);
             }
 
             /**
@@ -2263,9 +2135,9 @@
              */
             public static final String KIND = "kind";
 
-            public static final int MINI_KIND = 1;
-            public static final int FULL_SCREEN_KIND = 2;
-            public static final int MICRO_KIND = 3;
+            public static final int MINI_KIND = ThumbnailConstants.MINI_KIND;
+            public static final int FULL_SCREEN_KIND = ThumbnailConstants.FULL_SCREEN_KIND;
+            public static final int MICRO_KIND = ThumbnailConstants.MICRO_KIND;
 
             /**
              * The width of the thumbnal
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a7fcaff..bffed8d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -37,6 +37,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.app.ActivityThread;
 import android.app.AppOpsManager;
@@ -374,6 +375,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_TRUSTED_CREDENTIALS_USER =
             "com.android.settings.TRUSTED_CREDENTIALS_USER";
 
@@ -684,6 +686,7 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String ACTION_USER_DICTIONARY_INSERT =
             "com.android.settings.USER_DICTIONARY_INSERT";
 
@@ -1451,7 +1454,9 @@
     public static final String ACTION_APP_NOTIFICATION_REDACTION
             = "android.settings.ACTION_APP_NOTIFICATION_REDACTION";
 
-    /** @hide */ public static final String EXTRA_APP_UID = "app_uid";
+    /** @hide */
+    @UnsupportedAppUsage
+    public static final String EXTRA_APP_UID = "app_uid";
 
     /**
      * Activity Action: Show a dialog with disabled by policy message.
@@ -1951,6 +1956,7 @@
         @GuardedBy("mLock")
         private final Uri mUri;
         @GuardedBy("mLock")
+        @UnsupportedAppUsage
         private IContentProvider mContentProvider;
 
         public ContentProviderHolder(Uri uri) {
@@ -1988,6 +1994,7 @@
         private final HashMap<String, String> mValues = new HashMap<>();
 
         private final Uri mUri;
+        @UnsupportedAppUsage
         private final ContentProviderHolder mProviderHolder;
 
         // The method we'll call (or null, to not use) on the provider
@@ -2027,6 +2034,7 @@
             return true;
         }
 
+        @UnsupportedAppUsage
         public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
             final boolean isSelf = (userHandle == UserHandle.myUserId());
             int currentGeneration = -1;
@@ -2244,15 +2252,18 @@
         public static final Uri CONTENT_URI =
             Uri.parse("content://" + AUTHORITY + "/system");
 
+        @UnsupportedAppUsage
         private static final ContentProviderHolder sProviderHolder =
                 new ContentProviderHolder(CONTENT_URI);
 
+        @UnsupportedAppUsage
         private static final NameValueCache sNameValueCache = new NameValueCache(
                 CONTENT_URI,
                 CALL_METHOD_GET_SYSTEM,
                 CALL_METHOD_PUT_SYSTEM,
                 sProviderHolder);
 
+        @UnsupportedAppUsage
         private static final HashSet<String> MOVED_TO_SECURE;
         static {
             MOVED_TO_SECURE = new HashSet<>(30);
@@ -2289,7 +2300,9 @@
             MOVED_TO_SECURE.add(Secure.INSTALL_NON_MARKET_APPS);
         }
 
+        @UnsupportedAppUsage
         private static final HashSet<String> MOVED_TO_GLOBAL;
+        @UnsupportedAppUsage
         private static final HashSet<String> MOVED_TO_SECURE_THEN_GLOBAL;
         static {
             MOVED_TO_GLOBAL = new HashSet<>();
@@ -2375,6 +2388,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static String getStringForUser(ContentResolver resolver, String name,
                 int userHandle) {
             if (MOVED_TO_SECURE.contains(name)) {
@@ -2402,6 +2416,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static boolean putStringForUser(ContentResolver resolver, String name, String value,
                 int userHandle) {
             if (MOVED_TO_SECURE.contains(name)) {
@@ -2456,6 +2471,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static int getIntForUser(ContentResolver cr, String name, int def, int userHandle) {
             String v = getStringForUser(cr, name, userHandle);
             try {
@@ -2489,6 +2505,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static int getIntForUser(ContentResolver cr, String name, int userHandle)
                 throws SettingNotFoundException {
             String v = getStringForUser(cr, name, userHandle);
@@ -2517,6 +2534,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static boolean putIntForUser(ContentResolver cr, String name, int value,
                 int userHandle) {
             return putStringForUser(cr, name, Integer.toString(value), userHandle);
@@ -2935,6 +2953,7 @@
          * {@hide}
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String AIRPLANE_MODE_TOGGLEABLE_RADIOS =
                 Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS;
 
@@ -3214,6 +3233,7 @@
          * or less (<0.0 >-1.0) bright.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String SCREEN_AUTO_BRIGHTNESS_ADJ = "screen_auto_brightness_adj";
 
         private static final Validator SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR =
@@ -3404,6 +3424,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String MASTER_MONO = "master_mono";
 
         private static final Validator MASTER_MONO_VALIDATOR = BOOLEAN_VALIDATOR;
@@ -3440,6 +3461,7 @@
          * Kept for use by legacy database upgrade code in DatabaseHelper.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String VIBRATE_IN_SILENT = "vibrate_in_silent";
 
         private static final Validator VIBRATE_IN_SILENT_VALIDATOR = BOOLEAN_VALIDATOR;
@@ -3742,6 +3764,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY =
                 "hide_rotation_lock_toggle_for_accessibility";
 
@@ -3797,6 +3820,7 @@
          * boolean (1 or 0).
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String HEARING_AID = "hearing_aid";
 
         /** @hide */
@@ -3811,6 +3835,7 @@
          * 3 = HCO
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String TTY_MODE = "tty_mode";
 
         /** @hide */
@@ -3850,6 +3875,7 @@
          * pending. The value is boolean (1 or 0).
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
 
         /** @hide */
@@ -3861,6 +3887,7 @@
          * 1 = yes
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String POINTER_LOCATION = "pointer_location";
 
         /** @hide */
@@ -3872,6 +3899,7 @@
          * 1 = yes
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String SHOW_TOUCHES = "show_touches";
 
         /** @hide */
@@ -3907,6 +3935,7 @@
          * @hide
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String DOCK_SOUNDS_ENABLED = Global.DOCK_SOUNDS_ENABLED;
 
         private static final Validator DOCK_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
@@ -3915,6 +3944,7 @@
          * Whether to play sounds when the keyguard is shown and dismissed.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String LOCKSCREEN_SOUNDS_ENABLED = "lockscreen_sounds_enabled";
 
         /** @hide */
@@ -3943,6 +3973,7 @@
          * @hide
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String DESK_DOCK_SOUND = Global.DESK_DOCK_SOUND;
 
         /**
@@ -3951,6 +3982,7 @@
          * @hide
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String DESK_UNDOCK_SOUND = Global.DESK_UNDOCK_SOUND;
 
         /**
@@ -3959,6 +3991,7 @@
          * @hide
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String CAR_DOCK_SOUND = Global.CAR_DOCK_SOUND;
 
         /**
@@ -3967,6 +4000,7 @@
          * @hide
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String CAR_UNDOCK_SOUND = Global.CAR_UNDOCK_SOUND;
 
         /**
@@ -3975,6 +4009,7 @@
          * @hide
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String LOCK_SOUND = Global.LOCK_SOUND;
 
         /**
@@ -3983,6 +4018,7 @@
          * @hide
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String UNLOCK_SOUND = Global.UNLOCK_SOUND;
 
         /**
@@ -4048,6 +4084,7 @@
          *   +7 = fastest
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String POINTER_SPEED = "pointer_speed";
 
         /** @hide */
@@ -4112,6 +4149,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String[] SETTINGS_TO_BACKUP = {
             STAY_ON_WHILE_PLUGGED_IN,   // moved to global
             WIFI_USE_STATIC_IP,
@@ -4161,7 +4199,8 @@
             NOTIFICATION_VIBRATION_INTENSITY,
             HAPTIC_FEEDBACK_INTENSITY,
             DISPLAY_COLOR_MODE,
-            ALARM_ALERT
+            ALARM_ALERT,
+            NOTIFICATION_LIGHT_PULSE,
         };
 
         /**
@@ -4181,6 +4220,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final Set<String> PUBLIC_SETTINGS = new ArraySet<>();
         static {
             PUBLIC_SETTINGS.add(END_BUTTON_BEHAVIOR);
@@ -4235,6 +4275,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final Set<String> PRIVATE_SETTINGS = new ArraySet<>();
         static {
             PRIVATE_SETTINGS.add(WIFI_USE_STATIC_IP);
@@ -4286,6 +4327,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
         static {
             VALIDATORS.put(STAY_ON_WHILE_PLUGGED_IN, STAY_ON_WHILE_PLUGGED_IN_VALIDATOR);
@@ -4364,12 +4406,14 @@
             VALIDATORS.put(WIFI_STATIC_DNS1, WIFI_STATIC_DNS1_VALIDATOR);
             VALIDATORS.put(WIFI_STATIC_DNS2, WIFI_STATIC_DNS2_VALIDATOR);
             VALIDATORS.put(SHOW_BATTERY_PERCENT, SHOW_BATTERY_PERCENT_VALIDATOR);
+            VALIDATORS.put(NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR);
         }
 
         /**
          * These entries are considered common between the personal and the managed profile,
          * since the managed profile doesn't get to change them.
          */
+        @UnsupportedAppUsage
         private static final Set<String> CLONE_TO_MANAGED_PROFILE = new ArraySet<>();
         static {
             CLONE_TO_MANAGED_PROFILE.add(DATE_FORMAT);
@@ -4708,10 +4752,12 @@
         public static final Uri CONTENT_URI =
             Uri.parse("content://" + AUTHORITY + "/secure");
 
+        @UnsupportedAppUsage
         private static final ContentProviderHolder sProviderHolder =
                 new ContentProviderHolder(CONTENT_URI);
 
         // Populated lazily, guarded by class object:
+        @UnsupportedAppUsage
         private static final NameValueCache sNameValueCache = new NameValueCache(
                 CONTENT_URI,
                 CALL_METHOD_GET_SECURE,
@@ -4721,7 +4767,9 @@
         private static ILockSettings sLockSettings = null;
 
         private static boolean sIsSystemProcess;
+        @UnsupportedAppUsage
         private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
+        @UnsupportedAppUsage
         private static final HashSet<String> MOVED_TO_GLOBAL;
         static {
             MOVED_TO_LOCK_SETTINGS = new HashSet<>(3);
@@ -4865,6 +4913,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static String getStringForUser(ContentResolver resolver, String name,
                 int userHandle) {
             if (MOVED_TO_GLOBAL.contains(name)) {
@@ -4919,12 +4968,14 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static boolean putStringForUser(ContentResolver resolver, String name, String value,
                 int userHandle) {
             return putStringForUser(resolver, name, value, null, false, userHandle);
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static boolean putStringForUser(@NonNull ContentResolver resolver,
                 @NonNull String name, @Nullable String value, @Nullable String tag,
                 boolean makeDefault, @UserIdInt int userHandle) {
@@ -5080,6 +5131,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static int getIntForUser(ContentResolver cr, String name, int def, int userHandle) {
             if (LOCATION_MODE.equals(name)) {
                 // Map from to underlying location provider storage API to location mode
@@ -5149,6 +5201,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static boolean putIntForUser(ContentResolver cr, String name, int value,
                 int userHandle) {
             return putStringForUser(cr, name, Integer.toString(value), userHandle);
@@ -5173,6 +5226,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static long getLongForUser(ContentResolver cr, String name, long def,
                 int userHandle) {
             String valString = getStringForUser(cr, name, userHandle);
@@ -5236,6 +5290,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static boolean putLongForUser(ContentResolver cr, String name, long value,
                 int userHandle) {
             return putStringForUser(cr, name, Long.toString(value), userHandle);
@@ -5789,6 +5844,7 @@
          * subject to current DeviceAdmin policy limits.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String LOCK_SCREEN_LOCK_AFTER_TIMEOUT = "lock_screen_lock_after_timeout";
 
 
@@ -5830,6 +5886,7 @@
          * @deprecated
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
             "lock_screen_owner_info_enabled";
 
@@ -5838,6 +5895,7 @@
          * in their full "private" form (same as when the device is unlocked).
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS =
                 "lock_screen_allow_private_notifications";
 
@@ -6015,6 +6073,7 @@
          * Whether the hush gesture has ever been used
          * @hide
          */
+        @SystemApi
         public static final String HUSH_GESTURE_USED = "hush_gesture_used";
 
         private static final Validator HUSH_GESTURE_USED_VALIDATOR = BOOLEAN_VALIDATOR;
@@ -6023,12 +6082,73 @@
          * Number of times the user has manually clicked the ringer toggle
          * @hide
          */
+        @SystemApi
         public static final String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
 
         private static final Validator MANUAL_RINGER_TOGGLE_COUNT_VALIDATOR =
                 NON_NEGATIVE_INTEGER_VALIDATOR;
 
         /**
+         * Whether to play a sound for charging events.
+         * @hide
+         */
+        public static final String CHARGING_SOUNDS_ENABLED = "charging_sounds_enabled";
+
+        /**
+         * Whether to vibrate for wireless charging events.
+         * @hide
+         */
+        public static final String CHARGING_VIBRATION_ENABLED = "charging_vibration_enabled";
+
+        /**
+         * If 0, turning on dnd manually will last indefinitely.
+         * Else if non-negative, turning on dnd manually will last for this many minutes.
+         * Else (if negative), turning on dnd manually will surface a dialog that prompts
+         * user to specify a duration.
+         * @hide
+         */
+        public static final String ZEN_DURATION = "zen_duration";
+
+        private static final Validator ZEN_DURATION_VALIDATOR = ANY_INTEGER_VALIDATOR;
+
+        /** @hide */ public static final int ZEN_DURATION_PROMPT = -1;
+        /** @hide */ public static final int ZEN_DURATION_FOREVER = 0;
+
+        /**
+         * If nonzero, will show the zen upgrade notification when the user toggles DND on/off.
+         * @hide
+         */
+        public static final String SHOW_ZEN_UPGRADE_NOTIFICATION = "show_zen_upgrade_notification";
+
+        /**
+         * If nonzero, will show the zen update settings suggestion.
+         * @hide
+         */
+        public static final String SHOW_ZEN_SETTINGS_SUGGESTION = "show_zen_settings_suggestion";
+
+        /**
+         * If nonzero, zen has not been updated to reflect new changes.
+         * @hide
+         */
+        public static final String ZEN_SETTINGS_UPDATED = "zen_settings_updated";
+
+        /**
+         * If nonzero, zen setting suggestion has been viewed by user
+         * @hide
+         */
+        public static final String ZEN_SETTINGS_SUGGESTION_VIEWED =
+                "zen_settings_suggestion_viewed";
+
+        /**
+         * Whether the in call notification is enabled to play sound during calls.  The value is
+         * boolean (1 or 0).
+         * @hide
+         */
+        public static final String IN_CALL_NOTIFICATION_ENABLED = "in_call_notification_enabled";
+
+        private static final Validator IN_CALL_NOTIFICATION_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
          * Uri of the slice that's presented on the keyguard.
          * Defaults to a slice with the date and next alarm.
          *
@@ -6269,6 +6389,7 @@
          * @see android.graphics.Typeface
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ACCESSIBILITY_CAPTIONING_TYPEFACE =
                 "accessibility_captioning_typeface";
 
@@ -6302,6 +6423,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED =
                 "accessibility_display_daltonizer_enabled";
 
@@ -6320,6 +6442,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ACCESSIBILITY_DISPLAY_DALTONIZER =
                 "accessibility_display_daltonizer";
 
@@ -6333,6 +6456,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ACCESSIBILITY_AUTOCLICK_ENABLED =
                 "accessibility_autoclick_enabled";
 
@@ -6358,6 +6482,7 @@
          * (0 = false, 1 = true)
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ACCESSIBILITY_LARGE_POINTER_ICON =
                 "accessibility_large_pointer_icon";
 
@@ -6368,6 +6493,7 @@
          * The timeout for considering a press to be a long press in milliseconds.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String LONG_PRESS_TIMEOUT = "long_press_timeout";
 
         private static final Validator LONG_PRESS_TIMEOUT_VALIDATOR =
@@ -6388,6 +6514,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ENABLED_PRINT_SERVICES =
             "enabled_print_services";
 
@@ -6746,6 +6873,7 @@
          * Type: int ( 0 = disabled, 1 = enabled )
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String BACKUP_ENABLED = "backup_enabled";
 
         /**
@@ -6754,6 +6882,7 @@
          * Type: int ( 0 = disabled, 1 = enabled )
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String BACKUP_AUTO_RESTORE = "backup_auto_restore";
 
         /**
@@ -6761,12 +6890,14 @@
          * Type: int ( 0 = unprovisioned, 1 = fully provisioned )
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String BACKUP_PROVISIONED = "backup_provisioned";
 
         /**
          * Component of the transport to use for backup/restore.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String BACKUP_TRANSPORT = "backup_transport";
 
         /**
@@ -6944,6 +7075,7 @@
          * Also prevents ANRs and crash dialogs from being suppressed.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ANR_SHOW_BACKGROUND = "anr_show_background";
 
         /**
@@ -6963,6 +7095,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
 
         /**
@@ -6971,6 +7104,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String PACKAGE_VERIFIER_USER_CONSENT =
             "package_verifier_user_consent";
 
@@ -6980,10 +7114,9 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String SELECTED_SPELL_CHECKER = "selected_spell_checker";
 
-        private static final Validator SELECTED_SPELL_CHECKER_VALIDATOR = COMPONENT_NAME_VALIDATOR;
-
         /**
          * {@link android.view.textservice.SpellCheckerSubtype#hashCode()} of the selected subtype
          * of the selected spell checker service which is one of the services managed by the text
@@ -6991,12 +7124,10 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String SELECTED_SPELL_CHECKER_SUBTYPE =
                 "selected_spell_checker_subtype";
 
-        private static final Validator SELECTED_SPELL_CHECKER_SUBTYPE_VALIDATOR =
-                ANY_INTEGER_VALIDATOR;
-
         /**
          * Whether spell checker is enabled or not.
          *
@@ -7004,8 +7135,6 @@
          */
         public static final String SPELL_CHECKER_ENABLED = "spell_checker_enabled";
 
-        private static final Validator SPELL_CHECKER_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
-
         /**
          * What happens when the user presses the Power button while in-call
          * and the screen is on.<br/>
@@ -7015,6 +7144,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String INCALL_POWER_BUTTON_BEHAVIOR = "incall_power_button_behavior";
 
         private static final Validator INCALL_POWER_BUTTON_BEHAVIOR_VALIDATOR =
@@ -7081,6 +7211,7 @@
          * Whether the device should doze if configured.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String DOZE_ENABLED = "doze_enabled";
 
         private static final Validator DOZE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
@@ -7097,9 +7228,9 @@
          * Whether the device should pulse on pick up gesture.
          * @hide
          */
-        public static final String DOZE_PULSE_ON_PICK_UP = "doze_pulse_on_pick_up";
+        public static final String DOZE_PICK_UP_GESTURE = "doze_pulse_on_pick_up";
 
-        private static final Validator DOZE_PULSE_ON_PICK_UP_VALIDATOR = BOOLEAN_VALIDATOR;
+        private static final Validator DOZE_PICK_UP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether the device should pulse on long press gesture.
@@ -7111,9 +7242,17 @@
          * Whether the device should pulse on double tap gesture.
          * @hide
          */
-        public static final String DOZE_PULSE_ON_DOUBLE_TAP = "doze_pulse_on_double_tap";
+        public static final String DOZE_DOUBLE_TAP_GESTURE = "doze_pulse_on_double_tap";
 
-        private static final Validator DOZE_PULSE_ON_DOUBLE_TAP_VALIDATOR = BOOLEAN_VALIDATOR;
+        private static final Validator DOZE_DOUBLE_TAP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
+         * Whether the device should pulse on reach gesture.
+         * @hide
+         */
+        public static final String DOZE_REACH_GESTURE = "doze_reach_gesture";
+
+        private static final Validator DOZE_REACH_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * The current night mode that has been selected by the user.  Owned
@@ -7124,35 +7263,6 @@
         public static final String UI_NIGHT_MODE = "ui_night_mode";
 
         /**
-         * The current device UI theme mode effect SystemUI and Launcher.<br/>
-         * <b>Values:</b><br/>
-         * 0 - The mode that theme will controlled by wallpaper color.<br/>
-         * 1 - The mode that will always light theme.<br/>
-         * 2 - The mode that will always dark theme.<br/>
-         *
-         * @hide
-         */
-        public static final String THEME_MODE = "theme_mode";
-
-        /**
-         * THEME_MODE value for wallpaper mode.
-         * @hide
-         */
-        public static final int THEME_MODE_WALLPAPER = 0;
-
-        /**
-         * THEME_MODE value for light theme mode.
-         * @hide
-         */
-        public static final int THEME_MODE_LIGHT = 1;
-
-        /**
-         * THEME_MODE value for dark theme mode.
-         * @hide
-         */
-        public static final int THEME_MODE_DARK = 2;
-
-        /**
          * Whether screensavers are enabled.
          * @hide
          */
@@ -7200,6 +7310,7 @@
          * The default NFC payment component
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
 
         private static final Validator NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR =
@@ -7215,12 +7326,14 @@
          * Specifies the package name currently configured to be the primary sms application
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String SMS_DEFAULT_APPLICATION = "sms_default_application";
 
         /**
          * Specifies the package name currently configured to be the default dialer application
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String DIALER_DEFAULT_APPLICATION = "dialer_default_application";
 
         /**
@@ -7322,6 +7435,7 @@
          * {@link NotificationManager#isNotificationListenerAccessGranted(ComponentName)}.
          */
         @Deprecated
+        @UnsupportedAppUsage
         public static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
 
         private static final Validator ENABLED_NOTIFICATION_LISTENERS_VALIDATOR =
@@ -7358,6 +7472,7 @@
         private static final Validator SYNC_PARENT_SOUNDS_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /** @hide */
+        @UnsupportedAppUsage
         public static final String IMMERSIVE_MODE_CONFIRMATIONS = "immersive_mode_confirmations";
 
         /**
@@ -7400,6 +7515,7 @@
          * This preference enables notification display on the lockscreen.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS =
                 "lock_screen_show_notifications";
 
@@ -7458,6 +7574,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ASSISTANT = "assistant";
 
         /**
@@ -7535,6 +7652,15 @@
         public static final String FLASHLIGHT_ENABLED = "flashlight_enabled";
 
         /**
+         * Whether or not face unlock is allowed on Keyguard.
+         * @hide
+         */
+        public static final String FACE_UNLOCK_KEYGUARD_ENABLED = "face_unlock_keyguard_enabled";
+
+        private static final Validator FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
+        /**
          * Whether the assist gesture should be enabled.
          *
          * @hide
@@ -7907,6 +8033,7 @@
          *
          * @hide
          */
+        @SystemApi
         public static final String VOLUME_HUSH_GESTURE = "volume_hush_gesture";
 
         /** @hide */ public static final int VOLUME_HUSH_OFF = 0;
@@ -7957,6 +8084,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String[] SETTINGS_TO_BACKUP = {
             BUGREPORT_IN_POWER_MENU,                            // moved to global
             ALLOW_MOCK_LOCATION,
@@ -7998,9 +8126,6 @@
             WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,            // moved to global
             WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,               // moved to global
             WIFI_NUM_OPEN_NETWORKS_KEPT,                        // moved to global
-            SELECTED_SPELL_CHECKER,
-            SELECTED_SPELL_CHECKER_SUBTYPE,
-            SPELL_CHECKER_ENABLED,
             MOUNT_PLAY_NOTIFICATION_SND,
             MOUNT_UMS_AUTOSTART,
             MOUNT_UMS_PROMPT,
@@ -8029,10 +8154,12 @@
             QS_TILES,
             DOZE_ENABLED,
             DOZE_ALWAYS_ON,
-            DOZE_PULSE_ON_PICK_UP,
-            DOZE_PULSE_ON_DOUBLE_TAP,
+            DOZE_PICK_UP_GESTURE,
+            DOZE_DOUBLE_TAP_GESTURE,
+            DOZE_REACH_GESTURE,
             NFC_PAYMENT_DEFAULT_COMPONENT,
             AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
+            FACE_UNLOCK_KEYGUARD_ENABLED,
             ASSIST_GESTURE_ENABLED,
             ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
             ASSIST_GESTURE_WAKE_ENABLED,
@@ -8048,6 +8175,16 @@
             VOLUME_HUSH_GESTURE,
             MANUAL_RINGER_TOGGLE_COUNT,
             HUSH_GESTURE_USED,
+            IN_CALL_NOTIFICATION_ENABLED,
+            LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
+            LOCK_SCREEN_SHOW_NOTIFICATIONS,
+            ZEN_DURATION,
+            SHOW_ZEN_UPGRADE_NOTIFICATION,
+            SHOW_ZEN_SETTINGS_SUGGESTION,
+            ZEN_SETTINGS_UPDATED,
+            ZEN_SETTINGS_SUGGESTION_VIEWED,
+            CHARGING_SOUNDS_ENABLED,
+            CHARGING_VIBRATION_ENABLED,
         };
 
         /**
@@ -8124,10 +8261,6 @@
             VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
                     WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR);
             VALIDATORS.put(WIFI_NUM_OPEN_NETWORKS_KEPT, WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR);
-            VALIDATORS.put(SELECTED_SPELL_CHECKER, SELECTED_SPELL_CHECKER_VALIDATOR);
-            VALIDATORS.put(SELECTED_SPELL_CHECKER_SUBTYPE,
-                    SELECTED_SPELL_CHECKER_SUBTYPE_VALIDATOR);
-            VALIDATORS.put(SPELL_CHECKER_ENABLED, SPELL_CHECKER_ENABLED_VALIDATOR);
             VALIDATORS.put(MOUNT_PLAY_NOTIFICATION_SND, MOUNT_PLAY_NOTIFICATION_SND_VALIDATOR);
             VALIDATORS.put(MOUNT_UMS_AUTOSTART, MOUNT_UMS_AUTOSTART_VALIDATOR);
             VALIDATORS.put(MOUNT_UMS_PROMPT, MOUNT_UMS_PROMPT_VALIDATOR);
@@ -8165,11 +8298,13 @@
             VALIDATORS.put(QS_TILES, QS_TILES_VALIDATOR);
             VALIDATORS.put(DOZE_ENABLED, DOZE_ENABLED_VALIDATOR);
             VALIDATORS.put(DOZE_ALWAYS_ON, DOZE_ALWAYS_ON_VALIDATOR);
-            VALIDATORS.put(DOZE_PULSE_ON_PICK_UP, DOZE_PULSE_ON_PICK_UP_VALIDATOR);
-            VALIDATORS.put(DOZE_PULSE_ON_DOUBLE_TAP, DOZE_PULSE_ON_DOUBLE_TAP_VALIDATOR);
+            VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR);
+            VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR);
+            VALIDATORS.put(DOZE_REACH_GESTURE, DOZE_REACH_GESTURE_VALIDATOR);
             VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
             VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
                     AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
+            VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
             VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR);
             VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
                     ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR);
@@ -8193,6 +8328,16 @@
                     ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES_VALIDATOR); //legacy restore setting
             VALIDATORS.put(HUSH_GESTURE_USED, HUSH_GESTURE_USED_VALIDATOR);
             VALIDATORS.put(MANUAL_RINGER_TOGGLE_COUNT, MANUAL_RINGER_TOGGLE_COUNT_VALIDATOR);
+            VALIDATORS.put(IN_CALL_NOTIFICATION_ENABLED, IN_CALL_NOTIFICATION_ENABLED_VALIDATOR);
+            VALIDATORS.put(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(LOCK_SCREEN_SHOW_NOTIFICATIONS, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(ZEN_DURATION, ZEN_DURATION_VALIDATOR);
+            VALIDATORS.put(SHOW_ZEN_UPGRADE_NOTIFICATION, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(SHOW_ZEN_SETTINGS_SUGGESTION, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(ZEN_SETTINGS_UPDATED, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR);
         }
 
         /**
@@ -8220,7 +8365,6 @@
             CLONE_TO_MANAGED_PROFILE.add(ACCESSIBILITY_ENABLED);
             CLONE_TO_MANAGED_PROFILE.add(ALLOW_MOCK_LOCATION);
             CLONE_TO_MANAGED_PROFILE.add(ALLOWED_GEOLOCATION_ORIGINS);
-            CLONE_TO_MANAGED_PROFILE.add(AUTOFILL_SERVICE);
             CLONE_TO_MANAGED_PROFILE.add(DEFAULT_INPUT_METHOD);
             CLONE_TO_MANAGED_PROFILE.add(ENABLED_ACCESSIBILITY_SERVICES);
             CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
@@ -8458,6 +8602,7 @@
          * @hide
          * No longer used. Should be removed once all dependencies have been updated.
          */
+        @UnsupportedAppUsage
         public static final String ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED =
                 "enable_accessibility_global_gesture_enabled";
 
@@ -8666,16 +8811,20 @@
 
         /**
          * Whether to play a sound for charging events.
+         * @deprecated Use {@link android.provider.Settings.Secure#CHARGING_SOUNDS_ENABLED} instead
          * @hide
          */
+        @Deprecated
         public static final String CHARGING_SOUNDS_ENABLED = "charging_sounds_enabled";
 
         private static final Validator CHARGING_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether to vibrate for wireless charging events.
+         * @deprecated Use {@link android.provider.Settings.Secure#CHARGING_VIBRATION_ENABLED}
          * @hide
          */
+        @Deprecated
         public static final String CHARGING_VIBRATION_ENABLED = "charging_vibration_enabled";
 
         private static final Validator CHARGING_VIBRATION_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
@@ -9044,6 +9193,7 @@
         * ConnectivityManager for more info.
         * @hide
         */
+       @UnsupportedAppUsage
        public static final String MOBILE_DATA = "mobile_data";
 
        /**
@@ -9130,6 +9280,7 @@
         * scorer app, external network scores will neither be requested nor accepted.
         * @hide
         */
+       @UnsupportedAppUsage
        public static final String NETWORK_SCORER_APP = "network_scorer_app";
 
         /**
@@ -9163,6 +9314,19 @@
        /** {@hide} */
        public static final String STORAGE_BENCHMARK_INTERVAL = "storage_benchmark_interval";
 
+        /**
+         * Whether or not Settings should enable psd API.
+         * {@hide}
+         */
+        public static final String SETTINGS_USE_PSD_API = "settings_use_psd_api";
+
+        /**
+         * Whether or not Settings should enable external provider API.
+         * {@hide}
+         */
+        public static final String SETTINGS_USE_EXTERNAL_PROVIDER_API =
+                "settings_use_external_provider_api";
+
        /**
         * Sample validity in seconds to configure for the system DNS resolver.
         * {@hide}
@@ -9207,6 +9371,7 @@
         * 0 = do not verify apps before installation
         * @hide
         */
+       @UnsupportedAppUsage
        public static final String PACKAGE_VERIFIER_ENABLE = "package_verifier_enable";
 
        /** Timeout for package verification.
@@ -9452,6 +9617,7 @@
         * by the system).
         * @hide
         */
+       @UnsupportedAppUsage
        public static final String WEBVIEW_PROVIDER = "webview_provider";
 
        /**
@@ -9770,6 +9936,18 @@
                 "recommended_network_evaluator_cache_expiry_ms";
 
         /**
+         * Whether wifi scan throttle is enabled or not.
+         * This is intended to be used via adb commands or a menu in developer option to turn off
+         * the default wifi scan throttling mechanism for apps.
+         *
+         * Type: int (0 for false, 1 for true)
+         * @hide
+         */
+        public static final String WIFI_SCAN_THROTTLE_ENABLED = "wifi_scan_throttle_enabled";
+
+        private static final Validator WIFI_SCAN_THROTTLE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
         * Settings to allow BLE scans to be enabled even when Bluetooth is turned off for
         * connectivity.
         * @hide
@@ -9829,6 +10007,7 @@
         *
         * @hide
         */
+       @UnsupportedAppUsage
        public static final String WIFI_SAVED_STATE = "wifi_saved_state";
 
        /**
@@ -9869,6 +10048,7 @@
         * the setting needs to be set to 0 to disable it.
         * @hide
         */
+       @UnsupportedAppUsage
        public static final String WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED =
                "wifi_watchdog_poor_network_test_enabled";
 
@@ -10577,6 +10757,15 @@
         public static final String ACTIVITY_MANAGER_CONSTANTS = "activity_manager_constants";
 
         /**
+         * Feature flag to enable or disable the activity starts logging feature.
+         * Type: int (0 for false, 1 for true)
+         * Default: 0
+         * @hide
+         */
+        public static final String ACTIVITY_STARTS_LOGGING_ENABLED
+                = "activity_starts_logging_enabled";
+
+        /**
          * App ops specific settings.
          * This is encoded as a key=value list, separated by commas. Ex:
          *
@@ -10989,6 +11178,8 @@
          * proc_state_cpu_times_read_delay_ms (long)
          * external_stats_collection_rate_limit_ms (long)
          * battery_level_collection_delay_ms (long)
+         * max_history_files (int)
+         * max_history_buffer_kb (int)
          * </pre>
          *
          * <p>
@@ -11312,6 +11503,7 @@
          * See RIL_PreferredNetworkType in ril.h
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String PREFERRED_NETWORK_MODE =
                 "preferred_network_mode";
 
@@ -11693,12 +11885,21 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ZEN_MODE = "zen_mode";
 
-        /** @hide */ public static final int ZEN_MODE_OFF = 0;
-        /** @hide */ public static final int ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
-        /** @hide */ public static final int ZEN_MODE_NO_INTERRUPTIONS = 2;
-        /** @hide */ public static final int ZEN_MODE_ALARMS = 3;
+        /** @hide */
+        @UnsupportedAppUsage
+        public static final int ZEN_MODE_OFF = 0;
+        /** @hide */
+        @UnsupportedAppUsage
+        public static final int ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
+        /** @hide */
+        @UnsupportedAppUsage
+        public static final int ZEN_MODE_NO_INTERRUPTIONS = 2;
+        /** @hide */
+        @UnsupportedAppUsage
+        public static final int ZEN_MODE_ALARMS = 3;
 
         /** @hide */ public static String zenModeToString(int mode) {
             if (mode == ZEN_MODE_IMPORTANT_INTERRUPTIONS) return "ZEN_MODE_IMPORTANT_INTERRUPTIONS";
@@ -11731,32 +11932,47 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String ZEN_MODE_CONFIG_ETAG = "zen_mode_config_etag";
 
         /**
-         * If 0, turning on dnd manually will last indefinitely.
-         * Else if non-negative, turning on dnd manually will last for this many minutes.
-         * Else (if negative), turning on dnd manually will surface a dialog that prompts
-         * user to specify a duration.
+         * @deprecated Use {@link android.provider.Settings.Secure#ZEN_DURATION} instead
          * @hide
          */
+        @Deprecated
         public static final String ZEN_DURATION = "zen_duration";
 
         private static final Validator ZEN_DURATION_VALIDATOR = ANY_INTEGER_VALIDATOR;
 
-        /** @hide */ public static final int ZEN_DURATION_PROMPT = -1;
-        /** @hide */ public static final int ZEN_DURATION_FOREVER = 0;
+        /**
+         * @deprecated Use {@link android.provider.Settings.Secure#ZEN_DURATION_PROMPT} instead
+         * @hide
+         */
+        @Deprecated
+        public static final int ZEN_DURATION_PROMPT = -1;
+
+        /**
+         * @deprecated Use {@link android.provider.Settings.Secure#ZEN_DURATION_FOREVER} instead
+         * @hide
+         */
+        @Deprecated
+        public static final int ZEN_DURATION_FOREVER = 0;
 
         /**
          * Defines global heads up toggle.  One of HEADS_UP_OFF, HEADS_UP_ON.
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String HEADS_UP_NOTIFICATIONS_ENABLED =
                 "heads_up_notifications_enabled";
 
-        /** @hide */ public static final int HEADS_UP_OFF = 0;
-        /** @hide */ public static final int HEADS_UP_ON = 1;
+        /** @hide */
+        @UnsupportedAppUsage
+        public static final int HEADS_UP_OFF = 0;
+        /** @hide */
+        @UnsupportedAppUsage
+        public static final int HEADS_UP_ON = 1;
 
         /**
          * The name of the device
@@ -11778,6 +11994,7 @@
          * Type: int (0 for false, 1 for true)
          * @hide
          */
+        @UnsupportedAppUsage
         public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt";
 
         /**
@@ -12080,6 +12297,33 @@
                 "autofill_compat_mode_allowed_packages";
 
         /**
+         * Level of autofill logging.
+         *
+         * <p>Valid values are
+         * {@link android.view.autofill.AutofillManager#NO_LOGGING},
+         * {@link android.view.autofill.AutofillManager#FLAG_ADD_CLIENT_DEBUG}, or
+         * {@link android.view.autofill.AutofillManager#FLAG_ADD_CLIENT_VERBOSE}.
+         *
+         * @hide
+         */
+        public static final String AUTOFILL_LOGGING_LEVEL = "autofill_logging_level";
+
+        /**
+         * Maximum number of partitions that can be allowed in an autofill session.
+         *
+         * @hide
+         */
+        public static final String AUTOFILL_MAX_PARTITIONS_SIZE = "autofill_max_partitions_size";
+
+        /**
+         * Maximum number of visible datasets in the Autofill dataset picker UI, or {@code 0} to use
+         * the default value from resources.
+         *
+         * @hide
+         */
+        public static final String AUTOFILL_MAX_VISIBLE_DATASETS = "autofill_max_visible_datasets";
+
+        /**
          * Exemptions to the hidden API blacklist.
          *
          * @hide
@@ -12223,6 +12467,7 @@
             VALIDATORS.put(SOFT_AP_TIMEOUT_ENABLED, SOFT_AP_TIMEOUT_ENABLED_VALIDATOR);
             VALIDATORS.put(WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON,
                     WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR);
+            VALIDATORS.put(WIFI_SCAN_THROTTLE_ENABLED, WIFI_SCAN_THROTTLE_ENABLED_VALIDATOR);
             VALIDATORS.put(APP_AUTO_RESTRICTION_ENABLED, APP_AUTO_RESTRICTION_ENABLED_VALIDATOR);
             VALIDATORS.put(ZEN_DURATION, ZEN_DURATION_VALIDATOR);
             VALIDATORS.put(CHARGING_VIBRATION_ENABLED, CHARGING_VIBRATION_ENABLED_VALIDATOR);
@@ -12249,10 +12494,12 @@
         public static final String[] LEGACY_RESTORE_SETTINGS = {
         };
 
+        @UnsupportedAppUsage
         private static final ContentProviderHolder sProviderHolder =
                 new ContentProviderHolder(CONTENT_URI);
 
         // Populated lazily, guarded by class object:
+        @UnsupportedAppUsage
         private static final NameValueCache sNameValueCache = new NameValueCache(
                     CONTENT_URI,
                     CALL_METHOD_GET_GLOBAL,
@@ -12260,10 +12507,19 @@
                     sProviderHolder);
 
         // Certain settings have been moved from global to the per-user secure namespace
+        @UnsupportedAppUsage
         private static final HashSet<String> MOVED_TO_SECURE;
         static {
-            MOVED_TO_SECURE = new HashSet<>(1);
-            MOVED_TO_SECURE.add(Settings.Global.INSTALL_NON_MARKET_APPS);
+            MOVED_TO_SECURE = new HashSet<>(8);
+            MOVED_TO_SECURE.add(Global.INSTALL_NON_MARKET_APPS);
+            MOVED_TO_SECURE.add(Global.ZEN_DURATION);
+            MOVED_TO_SECURE.add(Global.SHOW_ZEN_UPGRADE_NOTIFICATION);
+            MOVED_TO_SECURE.add(Global.SHOW_ZEN_SETTINGS_SUGGESTION);
+            MOVED_TO_SECURE.add(Global.ZEN_SETTINGS_UPDATED);
+            MOVED_TO_SECURE.add(Global.ZEN_SETTINGS_SUGGESTION_VIEWED);
+            MOVED_TO_SECURE.add(Global.CHARGING_SOUNDS_ENABLED);
+            MOVED_TO_SECURE.add(Global.CHARGING_VIBRATION_ENABLED);
+
         }
 
         /** @hide */
@@ -12288,6 +12544,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static String getStringForUser(ContentResolver resolver, String name,
                 int userHandle) {
             if (MOVED_TO_SECURE.contains(name)) {
@@ -12414,6 +12671,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static boolean putStringForUser(ContentResolver resolver,
                 String name, String value, int userHandle) {
             return putStringForUser(resolver, name, value, null, false, userHandle);
@@ -12668,6 +12926,7 @@
           * The supported values are 0 = disable or 1 = enable prompt.
           * @hide
           */
+        @UnsupportedAppUsage
         public static final String MULTI_SIM_VOICE_PROMPT = "multi_sim_voice_prompt";
 
         /**
@@ -12697,6 +12956,7 @@
           * iccId,appType,appId,activationStatus,3gppIndex,3gpp2Index
           * @hide
          */
+        @UnsupportedAppUsage
         public static final String[] MULTI_SIM_USER_PREFERRED_SUBS = {"user_preferred_sub1",
                 "user_preferred_sub2","user_preferred_sub3"};
 
@@ -12854,6 +13114,7 @@
          * Supported keys:
          * compatibility_wal_supported      (boolean)
          * wal_syncmode       (String)
+         * truncate_size      (int)
          *
          * @hide
          */
@@ -12939,28 +13200,37 @@
          */
         public static final String SHOW_MUTE_IN_CRASH_DIALOG = "show_mute_in_crash_dialog";
 
+
         /**
          * If nonzero, will show the zen upgrade notification when the user toggles DND on/off.
          * @hide
+         * @deprecated - Use {@link android.provider.Settings.Secure#SHOW_ZEN_UPGRADE_NOTIFICATION}
          */
+        @Deprecated
         public static final String SHOW_ZEN_UPGRADE_NOTIFICATION = "show_zen_upgrade_notification";
 
         /**
          * If nonzero, will show the zen update settings suggestion.
          * @hide
+         * @deprecated - Use {@link android.provider.Settings.Secure#SHOW_ZEN_SETTINGS_SUGGESTION}
          */
+        @Deprecated
         public static final String SHOW_ZEN_SETTINGS_SUGGESTION = "show_zen_settings_suggestion";
 
         /**
          * If nonzero, zen has not been updated to reflect new changes.
+         * @deprecated - Use {@link android.provider.Settings.Secure#ZEN_SETTINGS_UPDATED}
          * @hide
          */
+        @Deprecated
         public static final String ZEN_SETTINGS_UPDATED = "zen_settings_updated";
 
         /**
-         * If nonzero, zen setting suggestion has beem viewed by user
+         * If nonzero, zen setting suggestion has been viewed by user
          * @hide
+         * @deprecated - Use {@link android.provider.Settings.Secure#ZEN_SETTINGS_SUGGESTION_VIEWED}
          */
+        @Deprecated
         public static final String ZEN_SETTINGS_SUGGESTION_VIEWED =
                 "zen_settings_suggestion_viewed";
 
@@ -13011,6 +13281,21 @@
          */
         public static final String GNSS_HAL_LOCATION_REQUEST_DURATION_MILLIS =
                 "gnss_hal_location_request_duration_millis";
+
+        /**
+         * Binder call stats settings.
+         *
+         * The following strings are supported as keys:
+         * <pre>
+         *     enabled              (boolean)
+         *     detailed_tracking    (boolean)
+         *     upload_data          (boolean)
+         *     sampling_interval    (int)
+         * </pre>
+         *
+         * @hide
+         */
+        public static final String BINDER_CALLS_STATS = "binder_calls_stats";
     }
 
     /**
@@ -13027,6 +13312,7 @@
         /**
          * The content:// style URL for this table
          */
+        @UnsupportedAppUsage
         public static final Uri CONTENT_URI =
             Uri.parse("content://" + AUTHORITY + "/bookmarks");
 
@@ -13135,6 +13421,7 @@
          *            cleared (the bookmark is not removed).
          * @return The unique content URL for the new bookmark entry.
          */
+        @UnsupportedAppUsage
         public static Uri add(ContentResolver cr,
                                            Intent intent,
                                            String title,
@@ -13233,6 +13520,7 @@
      * callingPackage, a negative result will be returned.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isCallingPackageAllowedToWriteSettings(Context context, int uid,
             String callingPackage, boolean throwException) {
         return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid,
@@ -13289,6 +13577,7 @@
      * a negative result will be returned.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isCallingPackageAllowedToDrawOverlays(Context context, int uid,
             String callingPackage, boolean throwException) {
         return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid,
@@ -13319,6 +13608,7 @@
      * OP_WRITE_SETTINGS
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isCallingPackageAllowedToPerformAppOpsProtectedOperation(Context context,
             int uid, String callingPackage, boolean throwException, int appOpsOpCode, String[]
             permissions, boolean makeNote) {
diff --git a/core/java/android/security/KeystoreArguments.java b/core/java/android/security/KeystoreArguments.java
index 16054e5..7d85ca7 100644
--- a/core/java/android/security/KeystoreArguments.java
+++ b/core/java/android/security/KeystoreArguments.java
@@ -16,6 +16,7 @@
 
 package android.security;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,6 +28,7 @@
 public class KeystoreArguments implements Parcelable {
     public byte[][] args;
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<KeystoreArguments> CREATOR = new
             Parcelable.Creator<KeystoreArguments>() {
                 public KeystoreArguments createFromParcel(Parcel in) {
@@ -41,6 +43,7 @@
         args = null;
     }
 
+    @UnsupportedAppUsage
     public KeystoreArguments(byte[][] args) {
         this.args = args;
     }
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
index 2b3ccbc..c104671 100644
--- a/core/java/android/security/keymaster/ExportResult.java
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -16,6 +16,7 @@
 
 package android.security.keymaster;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,6 +28,7 @@
     public final int resultCode;
     public final byte[] exportData;
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<ExportResult> CREATOR = new
             Parcelable.Creator<ExportResult>() {
                 public ExportResult createFromParcel(Parcel in) {
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 89300d1..555863e 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -16,6 +16,7 @@
 
 package android.security.keymaster;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -44,6 +45,7 @@
                 }
             };
 
+    @UnsupportedAppUsage
     public KeyCharacteristics() {}
 
     protected KeyCharacteristics(Parcel in) {
@@ -61,6 +63,7 @@
         hwEnforced.writeToParcel(out, flags);
     }
 
+    @UnsupportedAppUsage
     public void readFromParcel(Parcel in) {
         swEnforced = KeymasterArguments.CREATOR.createFromParcel(in);
         hwEnforced = KeymasterArguments.CREATOR.createFromParcel(in);
diff --git a/core/java/android/security/keymaster/KeymasterArguments.java b/core/java/android/security/keymaster/KeymasterArguments.java
index e862252..5aa0f91 100644
--- a/core/java/android/security/keymaster/KeymasterArguments.java
+++ b/core/java/android/security/keymaster/KeymasterArguments.java
@@ -16,6 +16,7 @@
 
 package android.security.keymaster;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -40,6 +41,7 @@
 
     private List<KeymasterArgument> mArguments;
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<KeymasterArguments> CREATOR = new
             Parcelable.Creator<KeymasterArguments>() {
                 @Override
@@ -53,6 +55,7 @@
                 }
             };
 
+    @UnsupportedAppUsage
     public KeymasterArguments() {
         mArguments = new ArrayList<KeymasterArgument>();
     }
@@ -66,6 +69,7 @@
      *
      * @throws IllegalArgumentException if {@code tag} is not an enum tag.
      */
+    @UnsupportedAppUsage
     public void addEnum(int tag, int value) {
         int tagType = KeymasterDefs.getTagType(tag);
         if ((tagType != KeymasterDefs.KM_ENUM) && (tagType != KeymasterDefs.KM_ENUM_REP)) {
@@ -137,6 +141,7 @@
      * @throws IllegalArgumentException if {@code tag} is not an unsigned 32-bit int tag or if
      *         {@code value} is outside of the permitted range [0; 2^32).
      */
+    @UnsupportedAppUsage
     public void addUnsignedInt(int tag, long value) {
         int tagType = KeymasterDefs.getTagType(tag);
         if ((tagType != KeymasterDefs.KM_UINT) && (tagType != KeymasterDefs.KM_UINT_REP)) {
@@ -173,6 +178,7 @@
      * @throws IllegalArgumentException if {@code tag} is not an unsigned 64-bit long tag or if
      *         {@code value} is outside of the permitted range [0; 2^64).
      */
+    @UnsupportedAppUsage
     public void addUnsignedLong(int tag, BigInteger value) {
         int tagType = KeymasterDefs.getTagType(tag);
         if ((tagType != KeymasterDefs.KM_ULONG) && (tagType != KeymasterDefs.KM_ULONG_REP)) {
@@ -358,6 +364,7 @@
         out.writeTypedList(mArguments);
     }
 
+    @UnsupportedAppUsage
     public void readFromParcel(Parcel in) {
         in.readTypedList(mArguments, KeymasterArgument.CREATOR);
     }
diff --git a/core/java/android/security/keymaster/KeymasterBlob.java b/core/java/android/security/keymaster/KeymasterBlob.java
index cd36870..0659a22 100644
--- a/core/java/android/security/keymaster/KeymasterBlob.java
+++ b/core/java/android/security/keymaster/KeymasterBlob.java
@@ -16,6 +16,7 @@
 
 package android.security.keymaster;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -28,6 +29,7 @@
     public KeymasterBlob(byte[] blob) {
         this.blob = blob;
     }
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<KeymasterBlob> CREATOR = new
             Parcelable.Creator<KeymasterBlob>() {
                 public KeymasterBlob createFromParcel(Parcel in) {
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index 4c962ec..2943211 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -16,6 +16,7 @@
 
 package android.security.keymaster;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -33,6 +34,7 @@
     public final byte[] output;
     public final KeymasterArguments outParams;
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<OperationResult> CREATOR = new
             Parcelable.Creator<OperationResult>() {
                 @Override
diff --git a/core/java/android/security/net/config/ManifestConfigSource.java b/core/java/android/security/net/config/ManifestConfigSource.java
index 79115a5..b885e72 100644
--- a/core/java/android/security/net/config/ManifestConfigSource.java
+++ b/core/java/android/security/net/config/ManifestConfigSource.java
@@ -75,7 +75,7 @@
                 // should use the network security config.
                 boolean usesCleartextTraffic =
                         (mApplicationInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0
-                        && mApplicationInfo.targetSandboxVersion < 2;
+                        && !mApplicationInfo.isInstantApp();
                 source = new DefaultConfigSource(usesCleartextTraffic, mApplicationInfo);
             }
             mConfigSource = source;
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index 52f48ef..57068fa 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -185,7 +185,7 @@
                 .addCertificatesEntryRef(
                         new CertificatesEntryRef(SystemCertificateSource.getInstance(), false));
         final boolean cleartextTrafficPermitted = info.targetSdkVersion < Build.VERSION_CODES.P
-                && info.targetSandboxVersion < 2;
+                && !info.isInstantApp();
         builder.setCleartextTrafficPermitted(cleartextTrafficPermitted);
         // Applications targeting N and above must opt in into trusting the user added certificate
         // store.
diff --git a/core/java/android/security/net/config/RootTrustManager.java b/core/java/android/security/net/config/RootTrustManager.java
index 2a30f11..d8936d9 100644
--- a/core/java/android/security/net/config/RootTrustManager.java
+++ b/core/java/android/security/net/config/RootTrustManager.java
@@ -21,6 +21,7 @@
 import java.security.cert.X509Certificate;
 import java.util.List;
 
+import android.annotation.UnsupportedAppUsage;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLSession;
@@ -121,6 +122,7 @@
      * This interface is used by conscrypt and android.net.http.X509TrustManagerExtensions do not
      * modify without modifying those callers.
      */
+    @UnsupportedAppUsage
     public List<X509Certificate> checkServerTrusted(X509Certificate[] certs, String authType,
             String hostname) throws CertificateException {
         if (hostname == null && mConfig.hasPerDomainConfigs()) {
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
index 1cd76d2..e5e1c92 100644
--- a/core/java/android/service/autofill/AutofillFieldClassificationService.java
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -65,16 +65,36 @@
     /**
      * Manifest metadata key for the resource string containing the name of the default field
      * classification algorithm.
+     *
+     * @deprecated Use {@link #RESOURCE_DEFAULT_ALGORITHM} instead.
      */
+    @Deprecated
     public static final String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM =
             "android.autofill.field_classification.default_algorithm";
+
     /**
      * Manifest metadata key for the resource string array containing the names of all field
      * classification algorithms provided by the service.
+     *
+     * @deprecated Use {@link #RESOURCE_AVAILABLE_ALGORITHMS} instead.
      */
+    @Deprecated
     public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS =
             "android.autofill.field_classification.available_algorithms";
 
+    /**
+     * Name of the resource string containing the name of the default field
+     * classification algorithm.
+     */
+    public static final String RESOURCE_DEFAULT_ALGORITHM =
+            "autofill_field_classification_default_algorithm";
+
+   /**
+    * Name of the resource string array containing the names of all field
+    * classification algorithms provided by the service.
+    */
+    public static final String RESOURCE_AVAILABLE_ALGORITHMS =
+            "autofill_field_classification_available_algorithms";
 
     /** {@hide} **/
     public static final String EXTRA_SCORES = "scores";
diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java
index fb468a8..b1ae7a5 100644
--- a/core/java/android/service/autofill/CustomDescription.java
+++ b/core/java/android/service/autofill/CustomDescription.java
@@ -20,11 +20,13 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Pair;
+import android.util.SparseArray;
 import android.widget.RemoteViews;
 
 import com.android.internal.util.Preconditions;
@@ -90,11 +92,13 @@
     private final RemoteViews mPresentation;
     private final ArrayList<Pair<Integer, InternalTransformation>> mTransformations;
     private final ArrayList<Pair<InternalValidator, BatchUpdates>> mUpdates;
+    private final SparseArray<InternalOnClickAction> mActions;
 
     private CustomDescription(Builder builder) {
         mPresentation = builder.mPresentation;
         mTransformations = builder.mTransformations;
         mUpdates = builder.mUpdates;
+        mActions = builder.mActions;
     }
 
     /** @hide */
@@ -115,6 +119,13 @@
         return mUpdates;
     }
 
+    /** @hide */
+    @Nullable
+    @TestApi
+    public SparseArray<InternalOnClickAction> getActions() {
+        return mActions;
+    }
+
     /**
      * Builder for {@link CustomDescription} objects.
      */
@@ -124,6 +135,7 @@
         private boolean mDestroyed;
         private ArrayList<Pair<Integer, InternalTransformation>> mTransformations;
         private ArrayList<Pair<InternalValidator, BatchUpdates>> mUpdates;
+        private SparseArray<InternalOnClickAction> mActions;
 
         /**
          * Default constructor.
@@ -157,9 +169,12 @@
          *
          * @param id view id of the children view.
          * @param transformation an implementation provided by the Android System.
+         *
          * @return this builder.
+         *
          * @throws IllegalArgumentException if {@code transformation} is not a class provided
          * by the Android System.
+         * @throws IllegalStateException if {@link #build()} was already called.
          */
         public Builder addChild(int id, @NonNull Transformation transformation) {
             throwIfDestroyed();
@@ -250,8 +265,10 @@
          * is satisfied.
          *
          * @return this builder
+         *
          * @throws IllegalArgumentException if {@code condition} is not a class provided
          * by the Android System.
+         * @throws IllegalStateException if {@link #build()} was already called.
          */
         public Builder batchUpdate(@NonNull Validator condition, @NonNull BatchUpdates updates) {
             throwIfDestroyed();
@@ -266,6 +283,58 @@
         }
 
         /**
+         * Sets an action to be applied to the {@link RemoteViews presentation template} when the
+         * child view with the given {@code id} is clicked.
+         *
+         * <p>Typically used when the presentation uses a masked field (like {@code ****}) for
+         * sensitive fields like passwords or credit cards numbers, but offers a an icon that the
+         * user can tap to show the value for that field.
+         *
+         * <p>Example:
+         *
+         * <pre class="prettyprint">
+         * customDescriptionBuilder
+         *   .addChild(R.id.password_plain, new CharSequenceTransformation
+         *      .Builder(passwordId, Pattern.compile("^(.*)$"), "$1").build())
+         *   .addOnClickAction(R.id.showIcon, new VisibilitySetterAction
+         *     .Builder(R.id.hideIcon, View.VISIBLE)
+         *     .setVisibility(R.id.showIcon, View.GONE)
+         *     .setVisibility(R.id.password_plain, View.VISIBLE)
+         *     .setVisibility(R.id.password_masked, View.GONE)
+         *     .build())
+         *   .addOnClickAction(R.id.hideIcon, new VisibilitySetterAction
+         *     .Builder(R.id.showIcon, View.VISIBLE)
+         *     .setVisibility(R.id.hideIcon, View.GONE)
+         *     .setVisibility(R.id.password_masked, View.VISIBLE)
+         *     .setVisibility(R.id.password_plain, View.GONE)
+         *     .build());
+         * </pre>
+         *
+         * <p><b>Note:</b> Currently only one action can be applied to a child; if this method
+         * is called multiple times passing the same {@code id}, only the last call will be used.
+         *
+         * @param id resource id of the child view.
+         * @param action action to be performed.
+         *
+         * @return this builder
+         *
+         * @throws IllegalArgumentException if {@code action} is not a class provided
+         * by the Android System.
+         * @throws IllegalStateException if {@link #build()} was already called.
+         */
+        public Builder addOnClickAction(int id, @NonNull OnClickAction action) {
+            throwIfDestroyed();
+            Preconditions.checkArgument((action instanceof InternalOnClickAction),
+                    "not provided by Android System: " + action);
+            if (mActions == null) {
+                mActions = new SparseArray<InternalOnClickAction>();
+            }
+            mActions.put(id, (InternalOnClickAction) action);
+
+            return this;
+        }
+
+        /**
          * Creates a new {@link CustomDescription} instance.
          */
         public CustomDescription build() {
@@ -294,6 +363,8 @@
                     .append(mTransformations == null ? "N/A" : mTransformations.size())
                 .append(", updates=")
                     .append(mUpdates == null ? "N/A" : mUpdates.size())
+                .append(", actions=")
+                    .append(mActions == null ? "N/A" : mActions.size())
                 .append("]").toString();
     }
 
@@ -339,6 +410,19 @@
             dest.writeParcelableArray(conditions, flags);
             dest.writeParcelableArray(updates, flags);
         }
+        if (mActions == null) {
+            dest.writeIntArray(null);
+        } else {
+            final int size = mActions.size();
+            final int[] ids = new int[size];
+            final InternalOnClickAction[] values = new InternalOnClickAction[size];
+            for (int i = 0; i < size; i++) {
+                ids[i] = mActions.keyAt(i);
+                values[i] = mActions.valueAt(i);
+            }
+            dest.writeIntArray(ids);
+            dest.writeParcelableArray(values, flags);
+        }
     }
     public static final Parcelable.Creator<CustomDescription> CREATOR =
             new Parcelable.Creator<CustomDescription>() {
@@ -351,13 +435,13 @@
             if (parentPresentation == null) return null;
 
             final Builder builder = new Builder(parentPresentation);
-            final int[] ids = parcel.createIntArray();
-            if (ids != null) {
+            final int[] transformationIds = parcel.createIntArray();
+            if (transformationIds != null) {
                 final InternalTransformation[] values =
                     parcel.readParcelableArray(null, InternalTransformation.class);
-                final int size = ids.length;
+                final int size = transformationIds.length;
                 for (int i = 0; i < size; i++) {
-                    builder.addChild(ids[i], values[i]);
+                    builder.addChild(transformationIds[i], values[i]);
                 }
             }
             final InternalValidator[] conditions =
@@ -369,6 +453,15 @@
                     builder.batchUpdate(conditions[i], updates[i]);
                 }
             }
+            final int[] actionIds = parcel.createIntArray();
+            if (actionIds != null) {
+                final InternalOnClickAction[] values =
+                    parcel.readParcelableArray(null, InternalOnClickAction.class);
+                final int size = actionIds.length;
+                for (int i = 0; i < size; i++) {
+                    builder.addOnClickAction(actionIds[i], values[i]);
+                }
+            }
             return builder.build();
         }
 
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index 5211767..f8408be 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -33,8 +33,13 @@
 import java.util.regex.Pattern;
 
 /**
- * A dataset object represents a group of fields (key / value pairs) used to autofill parts of a
- * screen.
+ * <p>A <code>Dataset</code> object represents a group of fields (key / value pairs) used
+ * to autofill parts of a screen.
+ *
+ * <p>For more information about the role of datasets in the autofill workflow, read
+ * <a href="/guide/topics/text/autofill-services">Build autofill services</a> and the
+ * <code><a href="/reference/android/service/autofill/AutofillService">AutofillService</a></code>
+ * documentation.
  *
  * <a name="BasicUsage"></a>
  * <h3>Basic usage</h3>
@@ -88,10 +93,6 @@
  *   <li>All other datasets are hidden.
  * </ol>
  *
- * <a name="MoreInfo"></a>
- * <h3>More information</h3>
- * <p>See {@link android.service.autofill.AutofillService} for more information and examples about
- * the role of datasets in the autofill workflow.
  */
 public final class Dataset implements Parcelable {
 
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 0257891..1695c13 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -21,8 +21,11 @@
 import android.os.RemoteException;
 
 /**
- * Handles autofill requests from the {@link AutofillService} into the {@link Activity} being
- * autofilled.
+ * <p><code>FillCallback</code> handles autofill requests from the {@link AutofillService} into
+ * the {@link Activity} being autofilled.
+ *
+ * <p>To learn about using Autofill services in your app, read
+ * <a href="/guide/topics/text/autofill-services">Build autofill services</a>.
  */
 public final class FillCallback {
     private final IFillCallback mCallback;
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 33619ac..4bd6e5c 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -65,12 +65,18 @@
      */
     public static final int FLAG_MANUAL_REQUEST = 0x1;
 
+    /**
+     * Indicates this request was made using
+     * <a href="AutofillService.html#CompatibilityMode">compatibility mode</a>.
+     */
+    public static final int FLAG_COMPATIBILITY_MODE_REQUEST = 0x2;
+
     /** @hide */
     public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
 
     /** @hide */
     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
-            FLAG_MANUAL_REQUEST
+            FLAG_MANUAL_REQUEST, FLAG_COMPATIBILITY_MODE_REQUEST
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface RequestFlags{}
@@ -93,7 +99,8 @@
     public FillRequest(int id, @NonNull ArrayList<FillContext> contexts,
             @Nullable Bundle clientState, @RequestFlags int flags) {
         mId = id;
-        mFlags = Preconditions.checkFlagsArgument(flags, FLAG_MANUAL_REQUEST);
+        mFlags = Preconditions.checkFlagsArgument(flags,
+                FLAG_MANUAL_REQUEST | FLAG_COMPATIBILITY_MODE_REQUEST);
         mContexts = Preconditions.checkCollectionElementsNotNull(contexts, "contexts");
         mClientState = clientState;
     }
diff --git a/core/java/android/service/autofill/InternalOnClickAction.java b/core/java/android/service/autofill/InternalOnClickAction.java
new file mode 100644
index 0000000..6602f2d
--- /dev/null
+++ b/core/java/android/service/autofill/InternalOnClickAction.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.os.Parcelable;
+import android.view.ViewGroup;
+
+/**
+ * Superclass of all {@link OnClickAction} the system understands. As this is not public, all public
+ * subclasses have to implement {@link OnClickAction} again.
+ *
+ * @hide
+ */
+@TestApi
+public abstract class InternalOnClickAction implements OnClickAction, Parcelable {
+
+    /**
+     * Applies the action to the children of the {@code rootView} when clicked.
+     */
+    public abstract void onClick(@NonNull ViewGroup rootView);
+}
diff --git a/core/java/android/service/autofill/InternalSanitizer.java b/core/java/android/service/autofill/InternalSanitizer.java
index d77e41e..ccffc70 100644
--- a/core/java/android/service/autofill/InternalSanitizer.java
+++ b/core/java/android/service/autofill/InternalSanitizer.java
@@ -35,8 +35,6 @@
      *
      * @return sanitized value or {@code null} if value could not be sanitized (for example: didn't
      * match regex, it's an invalid type, regex failed, etc).
-     *
-     * @hide
      */
     @Nullable
     public abstract AutofillValue sanitize(@NonNull AutofillValue value);
diff --git a/core/java/android/service/autofill/InternalTransformation.java b/core/java/android/service/autofill/InternalTransformation.java
index c9864a0..0dba2b9 100644
--- a/core/java/android/service/autofill/InternalTransformation.java
+++ b/core/java/android/service/autofill/InternalTransformation.java
@@ -44,8 +44,6 @@
      * @param finder object used to find the value of a field in the screen.
      * @param template the {@link RemoteViews presentation template}.
      * @param childViewId resource id of the child view inside the template.
-     *
-     * @hide
      */
     abstract void apply(@NonNull ValueFinder finder, @NonNull RemoteViews template,
             int childViewId) throws Exception;
@@ -58,8 +56,6 @@
      * @param template the {@link RemoteViews presentation template}.
      * @param transformations map of resource id of the child view inside the template to
      * transformation.
-     *
-     * @hide
      */
     public static boolean batchApply(@NonNull ValueFinder finder, @NonNull RemoteViews template,
             @NonNull ArrayList<Pair<Integer, InternalTransformation>> transformations) {
diff --git a/core/java/android/service/autofill/InternalValidator.java b/core/java/android/service/autofill/InternalValidator.java
index e08bb6c..4bea98d 100644
--- a/core/java/android/service/autofill/InternalValidator.java
+++ b/core/java/android/service/autofill/InternalValidator.java
@@ -33,9 +33,6 @@
      *
      * @param finder object used to find the value of a field in the screen.
      * @return {@code true} if the contents are valid, {@code false} otherwise.
-     *
-     * @hide
      */
-    @TestApi
     public abstract boolean isValid(@NonNull ValueFinder finder);
 }
diff --git a/core/java/android/service/autofill/OnClickAction.java b/core/java/android/service/autofill/OnClickAction.java
new file mode 100644
index 0000000..7439b00
--- /dev/null
+++ b/core/java/android/service/autofill/OnClickAction.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.autofill;
+
+/**
+ * Class used to define an action to be performed when a child view in a
+ * {@link android.widget.RemoteViews presentation} is clicked.
+ *
+ * <p>Typically used to switch the visibility of other views in a
+ * {@link CustomDescription custom save UI}.
+ */
+public interface OnClickAction {
+}
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 4943fc8..b845250 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -119,7 +119,8 @@
  *
  * <p>But it is only triggered when all conditions below are met:
  * <ul>
- *   <li>The {@link SaveInfo} associated with the {@link FillResponse} is not {@code null}.
+ *   <li>The {@link SaveInfo} associated with the {@link FillResponse} is not {@code null} neither
+ *       has the {@link #FLAG_DELAY_SAVE} flag.
  *   <li>The {@link AutofillValue}s of all required views (as set by the {@code requiredIds} passed
  *       to the {@link SaveInfo.Builder} constructor are not empty.
  *   <li>The {@link AutofillValue} of at least one view (be it required or optional) has changed
@@ -234,10 +235,26 @@
      */
     public static final int FLAG_DONT_SAVE_ON_FINISH = 0x2;
 
+    /**
+     * Don't trigger the autofill save UI when the autofill context associated with the response
+     * associated with this {@link SaveInfo} is {@link AutofillManager#commit() committed},
+     * but keep its {@link FillContext} so it's delivered in a future
+     * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback) save request} of an
+     * activity belonging to the same task.
+     *
+     * <p>This flag should be used when the service detects that the application uses
+     * multiple screens to implement an autofillable workflow (for example, one screen for the
+     * username field, another for password).
+     */
+    // TODO(b/112051762): improve documentation: add example, document relationship with other
+    // flagss, etc...
+    public static final int FLAG_DELAY_SAVE = 0x4;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
             FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE,
-            FLAG_DONT_SAVE_ON_FINISH
+            FLAG_DONT_SAVE_ON_FINISH,
+            FLAG_DELAY_SAVE
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface SaveInfoFlags{}
@@ -410,14 +427,15 @@
          * Sets flags changing the save behavior.
          *
          * @param flags {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE},
-         * {@link #FLAG_DONT_SAVE_ON_FINISH}, or {@code 0}.
+         * {@link #FLAG_DONT_SAVE_ON_FINISH}, {@link #FLAG_DELAY_SAVE}, or {@code 0}.
          * @return This builder.
          */
         public @NonNull Builder setFlags(@SaveInfoFlags int flags) {
             throwIfDestroyed();
 
             mFlags = Preconditions.checkFlagsArgument(flags,
-                    FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE | FLAG_DONT_SAVE_ON_FINISH);
+                    FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE | FLAG_DONT_SAVE_ON_FINISH
+                            | FLAG_DELAY_SAVE);
             return this;
         }
 
@@ -663,14 +681,16 @@
          * Builds a new {@link SaveInfo} instance.
          *
          * @throws IllegalStateException if no
-         * {@link #SaveInfo.Builder(int, AutofillId[]) required ids}
-         * or {@link #setOptionalIds(AutofillId[]) optional ids} were set
+         * {@link #SaveInfo.Builder(int, AutofillId[]) required ids},
+         * or {@link #setOptionalIds(AutofillId[]) optional ids}, or {@link #FLAG_DELAY_SAVE}
+         * were set
          */
         public SaveInfo build() {
             throwIfDestroyed();
             Preconditions.checkState(
-                    !ArrayUtils.isEmpty(mRequiredIds) || !ArrayUtils.isEmpty(mOptionalIds),
-                    "must have at least one required or optional id");
+                    !ArrayUtils.isEmpty(mRequiredIds) || !ArrayUtils.isEmpty(mOptionalIds)
+                            || (mFlags & FLAG_DELAY_SAVE) != 0,
+                    "must have at least one required or optional id or FLAG_DELAYED_SAVE");
             mDestroyed = true;
             return new SaveInfo(this);
         }
diff --git a/core/java/android/service/autofill/SaveRequest.java b/core/java/android/service/autofill/SaveRequest.java
index 4f85e6b..c9b5b55 100644
--- a/core/java/android/service/autofill/SaveRequest.java
+++ b/core/java/android/service/autofill/SaveRequest.java
@@ -52,6 +52,12 @@
     }
 
     /**
+     * Gets the contexts associated with each previous fill request.
+     *
+     * <p><b>Note:</b> Starting on Android {@link android.os.Build.VERSION_CODES#Q}, it could also
+     * include contexts from requests whose {@link SaveInfo} had the
+     * {@link SaveInfo#FLAG_DELAY_SAVE} flag.
+     *
      * @return The contexts associated with each previous fill request.
      */
     public @NonNull List<FillContext> getFillContexts() {
diff --git a/core/java/android/service/autofill/UserData.java b/core/java/android/service/autofill/UserData.java
index 55aecdd..fccb85b 100644
--- a/core/java/android/service/autofill/UserData.java
+++ b/core/java/android/service/autofill/UserData.java
@@ -145,6 +145,9 @@
 
         // Non-persistent array used to limit the number of unique ids.
         private final ArraySet<String> mUniqueCategoryIds;
+        // Non-persistent array used to ignore duplaicated value/category pairs.
+        private final ArraySet<String> mUniqueValueCategoryPairs;
+
 
         /**
          * Creates a new builder for the user data used for <a href="#FieldClassification">field
@@ -185,6 +188,7 @@
             final int maxUserDataSize = getMaxUserDataSize();
             mCategoryIds = new ArrayList<>(maxUserDataSize);
             mValues = new ArrayList<>(maxUserDataSize);
+            mUniqueValueCategoryPairs = new ArraySet<>(maxUserDataSize);
             mUniqueCategoryIds = new ArraySet<>(getMaxCategoryCount());
 
             addMapping(value, categoryId);
@@ -222,7 +226,8 @@
          * @throws IllegalStateException if:
          * <ul>
          *   <li>{@link #build()} already called</li>
-         *   <li>the {@code value} has already been added</li>
+         *   <li>the {@code value} has already been added (<b>Note: </b> this restriction was
+         *   lifted on Android {@link android.os.Build.VERSION_CODES#Q} and later)</li>
          *   <li>the number of unique {@code categoryId} values added so far is more than
          *       {@link UserData#getMaxCategoryCount()}</li>
          *   <li>the number of {@code values} added so far is is more than
@@ -248,12 +253,8 @@
                 // New category - check size
                 Preconditions.checkState(mUniqueCategoryIds.size() < getMaxCategoryCount(),
                         "already added " + mUniqueCategoryIds.size() + " unique category ids");
-
             }
 
-            Preconditions.checkState(!mValues.contains(value),
-                    // Don't include value on message because it could contain PII
-                    "already has entry with same value");
             Preconditions.checkState(mValues.size() < getMaxUserDataSize(),
                     "already added " + mValues.size() + " elements");
             addMapping(value, categoryId);
@@ -262,9 +263,16 @@
         }
 
         private void addMapping(@NonNull String value, @NonNull String categoryId) {
+            final String pair = value + ":" + categoryId;
+            if (mUniqueValueCategoryPairs.contains(pair)) {
+                // Don't include value on message because it could contain PII
+                Log.w(TAG, "Ignoring entry with same value / category");
+                return;
+            }
             mCategoryIds.add(categoryId);
             mValues.add(value);
             mUniqueCategoryIds.add(categoryId);
+            mUniqueValueCategoryPairs.add(pair);
         }
 
         private String checkNotEmpty(@NonNull String name, @Nullable String value) {
diff --git a/core/java/android/service/autofill/VisibilitySetterAction.java b/core/java/android/service/autofill/VisibilitySetterAction.java
new file mode 100644
index 0000000..9f977d7
--- /dev/null
+++ b/core/java/android/service/autofill/VisibilitySetterAction.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import static android.view.autofill.Helper.sDebug;
+import static android.view.autofill.Helper.sVerbose;
+
+import android.annotation.IdRes;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Slog;
+import android.util.SparseIntArray;
+import android.view.View;
+import android.view.View.Visibility;
+import android.view.ViewGroup;
+import android.widget.RemoteViews;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Action used to change the visibility of other child view in a {@link CustomDescription}
+ * {@link RemoteViews presentation template}.
+ *
+ * <p>See {@link CustomDescription.Builder#addOnClickAction(int, OnClickAction)} for more details.
+ */
+public final class VisibilitySetterAction extends InternalOnClickAction implements
+        OnClickAction, Parcelable {
+    private static final String TAG = "VisibilitySetterAction";
+
+    @NonNull private final SparseIntArray mVisibilities;
+
+    private VisibilitySetterAction(@NonNull Builder builder) {
+        mVisibilities = builder.mVisibilities;
+    }
+
+    /** @hide */
+    @Override
+    public void onClick(@NonNull ViewGroup rootView) {
+        for (int i = 0; i < mVisibilities.size(); i++) {
+            final int id = mVisibilities.keyAt(i);
+            final View child = rootView.findViewById(id);
+            if (child == null) {
+                Slog.w(TAG, "Skipping view id " + id + " because it's not found on " + rootView);
+                continue;
+            }
+            final int visibility = mVisibilities.valueAt(i);
+            if (sVerbose) {
+                Slog.v(TAG, "Changing visibility of view " + child + " from "
+                        + child.getVisibility() + " to  " + visibility);
+            }
+            child.setVisibility(visibility);
+        }
+    }
+
+    /**
+     * Builder for {@link VisibilitySetterAction} objects.
+     */
+    public static class Builder {
+        private final SparseIntArray mVisibilities = new SparseIntArray();
+        private boolean mDestroyed;
+
+        /**
+         * Creates a new builder for an action that change the visibility of one child view.
+         *
+         * @param id view resource id of the children view.
+         * @param visibility one of {@link View#VISIBLE}, {@link View#INVISIBLE}, or
+         *            {@link View#GONE}.
+         * @throws IllegalArgumentException if visibility is not one of {@link View#VISIBLE},
+         * {@link View#INVISIBLE}, or {@link View#GONE}.
+         */
+        public Builder(@IdRes int id, @Visibility int visibility) {
+            setVisibility(id, visibility);
+        }
+
+        /**
+         * Sets the action to changes the visibility of a child view.
+         *
+         * @param id view resource id of the children view.
+         * @param visibility one of {@link View#VISIBLE}, {@link View#INVISIBLE}, or
+         *            {@link View#GONE}.
+         * @throws IllegalArgumentException if visibility is not one of {@link View#VISIBLE},
+         * {@link View#INVISIBLE}, or {@link View#GONE}.
+         */
+        public Builder setVisibility(@IdRes int id, @Visibility int visibility) {
+            throwIfDestroyed();
+            switch (visibility) {
+                case View.VISIBLE:
+                case View.INVISIBLE:
+                case View.GONE:
+                    mVisibilities.put(id, visibility);
+                    return this;
+            }
+            throw new IllegalArgumentException("Invalid visibility: " + visibility);
+        }
+
+        /**
+         * Creates a new {@link VisibilitySetterAction} instance.
+         */
+        public VisibilitySetterAction build() {
+            throwIfDestroyed();
+            mDestroyed = true;
+            return new VisibilitySetterAction(this);
+        }
+
+        private void throwIfDestroyed() {
+            Preconditions.checkState(!mDestroyed, "Already called build()");
+        }
+    }
+
+    /////////////////////////////////////
+    // Object "contract" methods. //
+    /////////////////////////////////////
+    @Override
+    public String toString() {
+        if (!sDebug) return super.toString();
+
+        return "VisibilitySetterAction: [" + mVisibilities + "]";
+    }
+
+    /////////////////////////////////////
+    // Parcelable "contract" methods. //
+    /////////////////////////////////////
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeSparseIntArray(mVisibilities);
+    }
+
+    public static final Parcelable.Creator<VisibilitySetterAction> CREATOR =
+            new Parcelable.Creator<VisibilitySetterAction>() {
+        @Override
+        public VisibilitySetterAction createFromParcel(Parcel parcel) {
+            // Always go through the builder to ensure the data ingested by
+            // the system obeys the contract of the builder to avoid attacks
+            final SparseIntArray visibilities = parcel.readSparseIntArray();
+            Builder builder = null;
+            for (int i = 0; i < visibilities.size(); i++) {
+                final int id = visibilities.keyAt(i);
+                final int visibility = visibilities.valueAt(i);
+                if (builder == null) {
+                    builder = new Builder(id, visibility);
+                } else {
+                    builder.setVisibility(id, visibility);
+                }
+            }
+            return builder == null ? null : builder.build();
+        }
+
+        @Override
+        public VisibilitySetterAction[] newArray(int size) {
+            return new VisibilitySetterAction[size];
+        }
+    };
+}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 2b114d5..15b2aae 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.app.AlarmManager;
 import android.app.Service;
 import android.content.Intent;
@@ -601,6 +602,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setWindowless(boolean windowless) {
         mWindowless = windowless;
     }
@@ -624,6 +626,7 @@
      * @see #startDozing
      * @hide For use by system UI components only.
      */
+    @UnsupportedAppUsage
     public boolean canDoze() {
         return mCanDoze;
     }
@@ -657,6 +660,7 @@
      * @see #stopDozing
      * @hide For use by system UI components only.
      */
+    @UnsupportedAppUsage
     public void startDozing() {
         if (mCanDoze && !mDozing) {
             mDozing = true;
@@ -690,6 +694,7 @@
      * @see #startDozing
      * @hide For use by system UI components only.
      */
+    @UnsupportedAppUsage
     public void stopDozing() {
         if (mDozing) {
             mDozing = false;
@@ -711,6 +716,7 @@
      * @see #setDozing(boolean)
      * @hide For use by system UI components only.
      */
+    @UnsupportedAppUsage
     public boolean isDozing() {
         return mDozing;
     }
@@ -767,6 +773,7 @@
      *
      * @hide For use by system UI components only.
      */
+    @UnsupportedAppUsage
     public void setDozeScreenState(int state) {
         if (mDozeScreenState != state) {
             mDozeScreenState = state;
@@ -785,6 +792,7 @@
      * @see #setDozeScreenBrightness
      * @hide For use by system UI components only.
      */
+    @UnsupportedAppUsage
     public int getDozeScreenBrightness() {
         return mDozeScreenBrightness;
     }
@@ -816,6 +824,7 @@
      *
      * @hide For use by system UI components only.
      */
+    @UnsupportedAppUsage
     public void setDozeScreenBrightness(int brightness) {
         if (brightness != PowerManager.BRIGHTNESS_DEFAULT) {
             brightness = clampAbsoluteBrightness(brightness);
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java
index 4bbee61..4a39782 100644
--- a/core/java/android/service/euicc/EuiccProfileInfo.java
+++ b/core/java/android/service/euicc/EuiccProfileInfo.java
@@ -18,6 +18,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.service.carrier.CarrierIdentifier;
@@ -143,6 +144,7 @@
      * @deprecated - Do not use.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public EuiccProfileInfo(String iccid, @Nullable UiccAccessRule[] accessRules,
             @Nullable String nickname) {
         if (!TextUtils.isDigitsOnly(iccid)) {
diff --git a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java b/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
index e2171ae..bd91ca0 100644
--- a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
+++ b/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
@@ -17,6 +17,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.euicc.DownloadableSubscription;
@@ -49,6 +50,7 @@
      * @deprecated - Do no use. Use getResult() instead.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public final int result;
 
     @Nullable
diff --git a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
index 1edb539..71f1d22 100644
--- a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
+++ b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
@@ -17,6 +17,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.euicc.DownloadableSubscription;
@@ -46,6 +47,7 @@
      * @deprecated - Do no use. Use getResult() instead.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public final int result;
 
     @Nullable
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 7348cf6..518f8ed 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -65,6 +65,30 @@
     public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
 
     /**
+     * Data type: ArrayList of {@link android.app.Notification.Action}.
+     * Used to suggest extra actions for a notification.
+     */
+    public static final String KEY_SMART_ACTIONS = "key_smart_actions";
+
+    /**
+     * Data type: ArrayList of {@link CharSequence}.
+     * Used to suggest smart replies for a notification.
+     */
+    public static final String KEY_SMART_REPLIES = "key_smart_replies";
+
+    /**
+     * Data type: int, one of importance values e.g.
+     * {@link android.app.NotificationManager#IMPORTANCE_MIN}.
+     *
+     * If used from
+     * {@link NotificationAssistantService#onNotificationEnqueued(StatusBarNotification)}, it can
+     * block a notification from appearing or silence it. If used from
+     * {@link NotificationAssistantService#adjustNotification(Adjustment)}, it can visually
+     * demote a notification.
+     */
+    public static final String KEY_IMPORTANCE = "key_importance";
+
+    /**
      * Create a notification adjustment.
      *
      * @param pkg The package of the notification.
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index b6c6bdc..5a7a83f 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -151,14 +151,14 @@
     @Override
     public String toString() {
         return new StringBuilder(Condition.class.getSimpleName()).append('[')
-            .append("id=").append(id)
-            .append(",summary=").append(summary)
-            .append(",line1=").append(line1)
-            .append(",line2=").append(line2)
-            .append(",icon=").append(icon)
-            .append(",state=").append(stateToString(state))
-            .append(",flags=").append(flags)
-            .append(']').toString();
+                .append("state=").append(stateToString(state))
+                .append(",id=").append(id)
+                .append(",summary=").append(summary)
+                .append(",line1=").append(line1)
+                .append(",line2=").append(line2)
+                .append(",icon=").append(icon)
+                .append(",flags=").append(flags)
+                .append(']').toString();
     }
 
     /** @hide */
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index c388367..d8bd002 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -18,6 +18,7 @@
 
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
+import android.content.pm.ParceledListSlice;
 import android.os.UserHandle;
 import android.service.notification.NotificationStats;
 import android.service.notification.IStatusBarNotificationHolder;
@@ -43,6 +44,7 @@
     void onNotificationChannelGroupModification(String pkgName, in UserHandle user, in NotificationChannelGroup group, int modificationType);
 
     // assistants only
-    void onNotificationEnqueued(in IStatusBarNotificationHolder notificationHolder);
+    void onNotificationEnqueuedWithChannel(in IStatusBarNotificationHolder notificationHolder, in NotificationChannel channel);
     void onNotificationSnoozedUntilContext(in IStatusBarNotificationHolder notificationHolder, String snoozeCriterionId);
+    void onNotificationsSeen(in List<String> keys);
 }
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 18e0ab0..3b820ca 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -19,6 +19,9 @@
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.app.NotificationChannel;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Handler;
@@ -34,6 +37,22 @@
 
 /**
  * A service that helps the user manage notifications.
+ * <p>
+ * Only one notification assistant can be active at a time. Unlike notification listener services,
+ * assistant services can additionally modify certain aspects about notifications
+ * (see {@link Adjustment}) before they are posted.
+ *<p>
+ * A note about managed profiles: Unlike {@link NotificationListenerService listener services},
+ * NotificationAssistantServices are allowed to run in managed profiles
+ * (see {@link DevicePolicyManager#isManagedProfile(ComponentName)}), so they can access the
+ * information they need to create good {@link Adjustment adjustments}. To maintain the contract
+ * with {@link NotificationListenerService}, an assistant service will receive all of the
+ * callbacks from {@link NotificationListenerService} for the current user, managed profiles of
+ * that user, and ones that affect all users. However,
+ * {@link #onNotificationEnqueued(StatusBarNotification)} will only be called for notifications
+ * sent to the current user, and {@link Adjustment adjuments} will only be accepted for the
+ * current user.
+ *
  * @hide
  */
 @SystemApi
@@ -84,7 +103,22 @@
      * @param sbn the new notification
      * @return an adjustment or null to take no action, within 100ms.
      */
-    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn);
+    public Adjustment onNotificationEnqueued(StatusBarNotification sbn) {
+        return null;
+    }
+
+    /**
+     * A notification was posted by an app. Called before post.
+     *
+     * @param sbn the new notification
+     * @param channel the channel the notification was posted to
+     * @return an adjustment or null to take no action, within 100ms.
+     */
+    public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
+            NotificationChannel channel) {
+        return onNotificationEnqueued(sbn);
+    }
+
 
     /**
      * Implement this method to learn when notifications are removed, how they were interacted with
@@ -115,6 +149,14 @@
     }
 
     /**
+     * Implement this to know when a user has seen notifications, as triggered by
+     * {@link #setNotificationsShown(String[])}.
+     */
+    public void onNotificationsSeen(List<String> keys) {
+
+    }
+
+    /**
      * 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.
@@ -168,7 +210,8 @@
 
     private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper {
         @Override
-        public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder) {
+        public void onNotificationEnqueuedWithChannel(IStatusBarNotificationHolder sbnHolder,
+                NotificationChannel channel) {
             StatusBarNotification sbn;
             try {
                 sbn = sbnHolder.get();
@@ -179,14 +222,14 @@
 
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = sbn;
+            args.arg2 = channel;
             mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED,
                     args).sendToTarget();
         }
 
         @Override
         public void onNotificationSnoozedUntilContext(
-                IStatusBarNotificationHolder sbnHolder, String snoozeCriterionId)
-                throws RemoteException {
+                IStatusBarNotificationHolder sbnHolder, String snoozeCriterionId) {
             StatusBarNotification sbn;
             try {
                 sbn = sbnHolder.get();
@@ -201,11 +244,20 @@
             mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_SNOOZED,
                     args).sendToTarget();
         }
+
+        @Override
+        public void onNotificationsSeen(List<String> keys) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = keys;
+            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATIONS_SEEN,
+                    args).sendToTarget();
+        }
     }
 
     private final class MyHandler extends Handler {
         public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1;
         public static final int MSG_ON_NOTIFICATION_SNOOZED = 2;
+        public static final int MSG_ON_NOTIFICATIONS_SEEN = 3;
 
         public MyHandler(Looper looper) {
             super(looper, null, false);
@@ -217,8 +269,9 @@
                 case MSG_ON_NOTIFICATION_ENQUEUED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     StatusBarNotification sbn = (StatusBarNotification) args.arg1;
+                    NotificationChannel channel = (NotificationChannel) args.arg2;
                     args.recycle();
-                    Adjustment adjustment = onNotificationEnqueued(sbn);
+                    Adjustment adjustment = onNotificationEnqueued(sbn, channel);
                     if (adjustment != null) {
                         if (!isBound()) return;
                         try {
@@ -239,6 +292,13 @@
                     onNotificationSnoozedUntilContext(sbn, snoozeCriterionId);
                     break;
                 }
+                case MSG_ON_NOTIFICATIONS_SEEN: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    List<String> keys = (List<String>) args.arg1;
+                    args.recycle();
+                    onNotificationsSeen(keys);
+                    break;
+                }
             }
         }
     }
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index a7d70d0..1b588f4 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.INotificationManager;
 import android.app.Notification;
@@ -93,6 +94,7 @@
  */
 public abstract class NotificationListenerService extends Service {
 
+    @UnsupportedAppUsage
     private final String TAG = getClass().getSimpleName();
 
     /**
@@ -274,9 +276,11 @@
 
     private final Object mLock = new Object();
 
+    @UnsupportedAppUsage
     private Handler mHandler;
 
     /** @hide */
+    @UnsupportedAppUsage
     protected NotificationListenerWrapper mWrapper = null;
     private boolean isConnected = false;
 
@@ -286,6 +290,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected INotificationManager mNoMan;
 
     /**
@@ -507,6 +512,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     protected final INotificationManager getNotificationInterface() {
         if (mNoMan == null) {
             mNoMan = INotificationManager.Stub.asInterface(
@@ -1065,6 +1071,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     protected boolean isBound() {
         if (mWrapper == null) {
             Log.w(TAG, "Notification listener service not yet bound.");
@@ -1318,7 +1325,14 @@
         }
 
         @Override
-        public void onNotificationEnqueued(IStatusBarNotificationHolder notificationHolder)
+        public void onNotificationEnqueuedWithChannel(
+                IStatusBarNotificationHolder notificationHolder, NotificationChannel channel)
+                throws RemoteException {
+            // no-op in the listener
+        }
+
+        @Override
+        public void onNotificationsSeen(List<String> keys)
                 throws RemoteException {
             // no-op in the listener
         }
@@ -1426,6 +1440,8 @@
         private boolean mShowBadge;
         private @UserSentiment int mUserSentiment = USER_SENTIMENT_NEUTRAL;
         private boolean mHidden;
+        private ArrayList<Notification.Action> mSmartActions;
+        private ArrayList<CharSequence> mSmartReplies;
 
         public Ranking() {}
 
@@ -1461,6 +1477,7 @@
          * no such preference has been expressed.
          * @hide
          */
+        @UnsupportedAppUsage
         public int getVisibilityOverride() {
             return mVisibilityOverride;
         }
@@ -1556,6 +1573,20 @@
         }
 
         /**
+         * @hide
+         */
+        public List<Notification.Action> getSmartActions() {
+            return mSmartActions;
+        }
+
+        /**
+         * @hide
+         */
+        public List<CharSequence> getSmartReplies() {
+            return mSmartReplies;
+        }
+
+        /**
          * Returns whether this notification can be displayed as a badge.
          *
          * @return true if the notification can be displayed as a badge, false otherwise.
@@ -1583,7 +1614,8 @@
                 CharSequence explanation, String overrideGroupKey,
                 NotificationChannel channel, ArrayList<String> overridePeople,
                 ArrayList<SnoozeCriterion> snoozeCriteria, boolean showBadge,
-                int userSentiment, boolean hidden) {
+                int userSentiment, boolean hidden, ArrayList<Notification.Action> smartActions,
+                ArrayList<CharSequence> smartReplies) {
             mKey = key;
             mRank = rank;
             mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
@@ -1599,6 +1631,8 @@
             mShowBadge = showBadge;
             mUserSentiment = userSentiment;
             mHidden = hidden;
+            mSmartActions = smartActions;
+            mSmartReplies = smartReplies;
         }
 
         /**
@@ -1648,6 +1682,8 @@
         private ArrayMap<String, Boolean> mShowBadge;
         private ArrayMap<String, Integer> mUserSentiment;
         private ArrayMap<String, Boolean> mHidden;
+        private ArrayMap<String, ArrayList<Notification.Action>> mSmartActions;
+        private ArrayMap<String, ArrayList<CharSequence>> mSmartReplies;
 
         private RankingMap(NotificationRankingUpdate rankingUpdate) {
             mRankingUpdate = rankingUpdate;
@@ -1676,7 +1712,8 @@
                     getVisibilityOverride(key), getSuppressedVisualEffects(key),
                     getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key),
                     getChannel(key), getOverridePeople(key), getSnoozeCriteria(key),
-                    getShowBadge(key), getUserSentiment(key), getHidden(key));
+                    getShowBadge(key), getUserSentiment(key), getHidden(key), getSmartActions(key),
+                    getSmartReplies(key));
             return rank >= 0;
         }
 
@@ -1814,6 +1851,24 @@
             return hidden == null ? false : hidden.booleanValue();
         }
 
+        private ArrayList<Notification.Action> getSmartActions(String key) {
+            synchronized (this) {
+                if (mSmartActions == null) {
+                    buildSmartActions();
+                }
+            }
+            return mSmartActions.get(key);
+        }
+
+        private ArrayList<CharSequence> getSmartReplies(String key) {
+            synchronized (this) {
+                if (mSmartReplies == null) {
+                    buildSmartReplies();
+                }
+            }
+            return mSmartReplies.get(key);
+        }
+
         // Locked by 'this'
         private void buildRanksLocked() {
             String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -1831,23 +1886,41 @@
             Collections.addAll(mIntercepted, dndInterceptedKeys);
         }
 
+        private ArrayMap<String, Integer> buildIntMapFromBundle(Bundle bundle) {
+            ArrayMap<String, Integer> newMap = new ArrayMap<>(bundle.size());
+            for (String key : bundle.keySet()) {
+                newMap.put(key, bundle.getInt(key));
+            }
+            return newMap;
+        }
+
+        private ArrayMap<String, String> buildStringMapFromBundle(Bundle bundle) {
+            ArrayMap<String, String> newMap = new ArrayMap<>(bundle.size());
+            for (String key : bundle.keySet()) {
+                newMap.put(key, bundle.getString(key));
+            }
+            return newMap;
+        }
+
+        private ArrayMap<String, Boolean> buildBooleanMapFromBundle(Bundle bundle) {
+            ArrayMap<String, Boolean> newMap = new ArrayMap<>(bundle.size());
+            for (String key : bundle.keySet()) {
+                newMap.put(key, bundle.getBoolean(key));
+            }
+            return newMap;
+        }
+
         // Locked by 'this'
         private void buildVisibilityOverridesLocked() {
-            Bundle visibilityBundle = mRankingUpdate.getVisibilityOverrides();
-            mVisibilityOverrides = new ArrayMap<>(visibilityBundle.size());
-            for (String key: visibilityBundle.keySet()) {
-               mVisibilityOverrides.put(key, visibilityBundle.getInt(key));
-            }
+            mVisibilityOverrides = buildIntMapFromBundle(mRankingUpdate.getVisibilityOverrides());
         }
 
         // Locked by 'this'
         private void buildSuppressedVisualEffectsLocked() {
-            Bundle suppressedBundle = mRankingUpdate.getSuppressedVisualEffects();
-            mSuppressedVisualEffects = new ArrayMap<>(suppressedBundle.size());
-            for (String key: suppressedBundle.keySet()) {
-                mSuppressedVisualEffects.put(key, suppressedBundle.getInt(key));
-            }
+            mSuppressedVisualEffects =
+                buildIntMapFromBundle(mRankingUpdate.getSuppressedVisualEffects());
         }
+
         // Locked by 'this'
         private void buildImportanceLocked() {
             String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -1861,20 +1934,13 @@
 
         // Locked by 'this'
         private void buildImportanceExplanationLocked() {
-            Bundle explanationBundle = mRankingUpdate.getImportanceExplanation();
-            mImportanceExplanation = new ArrayMap<>(explanationBundle.size());
-            for (String key: explanationBundle.keySet()) {
-                mImportanceExplanation.put(key, explanationBundle.getString(key));
-            }
+            mImportanceExplanation =
+                buildStringMapFromBundle(mRankingUpdate.getImportanceExplanation());
         }
 
         // Locked by 'this'
         private void buildOverrideGroupKeys() {
-            Bundle overrideGroupKeys = mRankingUpdate.getOverrideGroupKeys();
-            mOverrideGroupKeys = new ArrayMap<>(overrideGroupKeys.size());
-            for (String key: overrideGroupKeys.keySet()) {
-                mOverrideGroupKeys.put(key, overrideGroupKeys.getString(key));
-            }
+            mOverrideGroupKeys = buildStringMapFromBundle(mRankingUpdate.getOverrideGroupKeys());
         }
 
         // Locked by 'this'
@@ -1906,28 +1972,34 @@
 
         // Locked by 'this'
         private void buildShowBadgeLocked() {
-            Bundle showBadge = mRankingUpdate.getShowBadge();
-            mShowBadge = new ArrayMap<>(showBadge.size());
-            for (String key : showBadge.keySet()) {
-                mShowBadge.put(key, showBadge.getBoolean(key));
-            }
+            mShowBadge = buildBooleanMapFromBundle(mRankingUpdate.getShowBadge());
         }
 
         // Locked by 'this'
         private void buildUserSentimentLocked() {
-            Bundle userSentiment = mRankingUpdate.getUserSentiment();
-            mUserSentiment = new ArrayMap<>(userSentiment.size());
-            for (String key : userSentiment.keySet()) {
-                mUserSentiment.put(key, userSentiment.getInt(key));
-            }
+            mUserSentiment = buildIntMapFromBundle(mRankingUpdate.getUserSentiment());
         }
 
         // Locked by 'this'
         private void buildHiddenLocked() {
-            Bundle hidden = mRankingUpdate.getHidden();
-            mHidden = new ArrayMap<>(hidden.size());
-            for (String key : hidden.keySet()) {
-                mHidden.put(key, hidden.getBoolean(key));
+            mHidden = buildBooleanMapFromBundle(mRankingUpdate.getHidden());
+        }
+
+        // Locked by 'this'
+        private void buildSmartActions() {
+            Bundle smartActions = mRankingUpdate.getSmartActions();
+            mSmartActions = new ArrayMap<>(smartActions.size());
+            for (String key : smartActions.keySet()) {
+                mSmartActions.put(key, smartActions.getParcelableArrayList(key));
+            }
+        }
+
+        // Locked by 'this'
+        private void buildSmartReplies() {
+            Bundle smartReplies = mRankingUpdate.getSmartReplies();
+            mSmartReplies = new ArrayMap<>(smartReplies.size());
+            for (String key : smartReplies.keySet()) {
+                mSmartReplies.put(key, smartReplies.getCharSequenceArrayList(key));
             }
         }
 
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index 00c47ec..c67fad0 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -37,12 +37,15 @@
     private final Bundle mShowBadge;
     private final Bundle mUserSentiment;
     private final Bundle mHidden;
+    private final Bundle mSmartActions;
+    private final Bundle mSmartReplies;
 
     public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
             Bundle visibilityOverrides, Bundle suppressedVisualEffects,
             int[] importance, Bundle explanation, Bundle overrideGroupKeys,
             Bundle channels, Bundle overridePeople, Bundle snoozeCriteria,
-            Bundle showBadge, Bundle userSentiment, Bundle hidden) {
+            Bundle showBadge, Bundle userSentiment, Bundle hidden, Bundle smartActions,
+            Bundle smartReplies) {
         mKeys = keys;
         mInterceptedKeys = interceptedKeys;
         mVisibilityOverrides = visibilityOverrides;
@@ -56,6 +59,8 @@
         mShowBadge = showBadge;
         mUserSentiment = userSentiment;
         mHidden = hidden;
+        mSmartActions = smartActions;
+        mSmartReplies = smartReplies;
     }
 
     public NotificationRankingUpdate(Parcel in) {
@@ -73,6 +78,8 @@
         mShowBadge = in.readBundle();
         mUserSentiment = in.readBundle();
         mHidden = in.readBundle();
+        mSmartActions = in.readBundle();
+        mSmartReplies = in.readBundle();
     }
 
     @Override
@@ -95,6 +102,8 @@
         out.writeBundle(mShowBadge);
         out.writeBundle(mUserSentiment);
         out.writeBundle(mHidden);
+        out.writeBundle(mSmartActions);
+        out.writeBundle(mSmartReplies);
     }
 
     public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -159,4 +168,12 @@
     public Bundle getHidden() {
         return mHidden;
     }
+
+    public Bundle getSmartActions() {
+        return mSmartActions;
+    }
+
+    public Bundle getSmartReplies() {
+        return mSmartReplies;
+    }
 }
diff --git a/core/java/android/service/notification/NotificationStats.java b/core/java/android/service/notification/NotificationStats.java
index 76d5328..e5f3dfb 100644
--- a/core/java/android/service/notification/NotificationStats.java
+++ b/core/java/android/service/notification/NotificationStats.java
@@ -71,6 +71,37 @@
      */
     public static final int DISMISSAL_SHADE = 3;
 
+    /** @hide */
+    @IntDef(prefix = { "DISMISS_SENTIMENT_" }, value = {
+            DISMISS_SENTIMENT_UNKNOWN, DISMISS_SENTIMENT_NEGATIVE, DISMISS_SENTIMENT_NEUTRAL,
+            DISMISS_SENTIMENT_POSITIVE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DismissalSentiment {}
+
+    /**
+     * No information is available about why this notification was dismissed, or the notification
+     * isn't dismissed yet.
+     */
+    public static final int DISMISS_SENTIMENT_UNKNOWN = -1000;
+    /**
+     * The user indicated while dismissing that they did not like the notification.
+     */
+    public static final int DISMISS_SENTIMENT_NEGATIVE = 0;
+    /**
+     * The user didn't indicate one way or another how they felt about the notification while
+     * dismissing it.
+     */
+    public static final int DISMISS_SENTIMENT_NEUTRAL = 1;
+    /**
+     * The user indicated while dismissing that they did like the notification.
+     */
+    public static final int DISMISS_SENTIMENT_POSITIVE = 2;
+
+
+    private @DismissalSentiment
+    int mDismissalSentiment = DISMISS_SENTIMENT_UNKNOWN;
+
     public NotificationStats() {
     }
 
@@ -82,6 +113,7 @@
         mViewedSettings = in.readByte() != 0;
         mInteracted = in.readByte() != 0;
         mDismissalSurface = in.readInt();
+        mDismissalSentiment = in.readInt();
     }
 
     @Override
@@ -93,6 +125,7 @@
         dest.writeByte((byte) (mViewedSettings ? 1 : 0));
         dest.writeByte((byte) (mInteracted ? 1 : 0));
         dest.writeInt(mDismissalSurface);
+        dest.writeInt(mDismissalSentiment);
     }
 
     @Override
@@ -212,6 +245,21 @@
         mDismissalSurface = dismissalSurface;
     }
 
+    /**
+     * Records whether the user indicated how they felt about a notification before or
+     * during dismissal.
+     */
+    public void setDismissalSentiment(@DismissalSentiment int dismissalSentiment) {
+        mDismissalSentiment = dismissalSentiment;
+    }
+
+    /**
+     * Returns how the user indicated they felt about a notification before or during dismissal.
+     */
+    public @DismissalSentiment int getDismissalSentiment() {
+        return mDismissalSentiment;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
diff --git a/core/java/android/service/notification/ScheduleCalendar.java b/core/java/android/service/notification/ScheduleCalendar.java
index 8b7946c..6ed966e 100644
--- a/core/java/android/service/notification/ScheduleCalendar.java
+++ b/core/java/android/service/notification/ScheduleCalendar.java
@@ -70,10 +70,10 @@
             }
             // only allow alarms in the future
             if (nextAlarm > now) {
-                // store earliest alarm
-                if (mSchedule.nextAlarm == 0) {
+                if (mSchedule.nextAlarm == 0 || mSchedule.nextAlarm < now) {
                     mSchedule.nextAlarm = nextAlarm;
                 } else {
+                    // store earliest alarm
                     mSchedule.nextAlarm = Math.min(mSchedule.nextAlarm, nextAlarm);
                 }
             } else if (mSchedule.nextAlarm < now) {
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index d1ebc6e..dd97d52 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -16,6 +16,7 @@
 
 package android.service.notification;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.content.Context;
@@ -30,18 +31,26 @@
  * the status bar and any {@link android.service.notification.NotificationListenerService}s.
  */
 public class StatusBarNotification implements Parcelable {
+    @UnsupportedAppUsage
     private final String pkg;
+    @UnsupportedAppUsage
     private final int id;
+    @UnsupportedAppUsage
     private final String tag;
     private final String key;
     private String groupKey;
     private String overrideGroupKey;
 
+    @UnsupportedAppUsage
     private final int uid;
     private final String opPkg;
+    @UnsupportedAppUsage
     private final int initialPid;
+    @UnsupportedAppUsage
     private final Notification notification;
+    @UnsupportedAppUsage
     private final UserHandle user;
+    @UnsupportedAppUsage
     private final long postTime;
 
     private Context mContext; // used for inflation & icon expansion
@@ -269,16 +278,19 @@
     }
 
     /** The notifying app's calling uid. @hide */
+    @UnsupportedAppUsage
     public int getUid() {
         return uid;
     }
 
     /** The package used for AppOps tracking. @hide */
+    @UnsupportedAppUsage
     public String getOpPkg() {
         return opPkg;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getInitialPid() {
         return initialPid;
     }
@@ -346,6 +358,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public Context getPackageContext(Context context) {
         if (mContext == null) {
             try {
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 5546e80..f90eb14 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -20,6 +20,7 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.NotificationManager;
@@ -145,6 +146,7 @@
     private static final String RULE_ATT_CREATION_TIME = "creationTime";
     private static final String RULE_ATT_ENABLER = "enabler";
 
+    @UnsupportedAppUsage
     public boolean allowAlarms = DEFAULT_ALLOW_ALARMS;
     public boolean allowMedia = DEFAULT_ALLOW_MEDIA;
     public boolean allowSystem = DEFAULT_ALLOW_SYSTEM;
@@ -161,8 +163,10 @@
     public int version;
 
     public ZenRule manualRule;
+    @UnsupportedAppUsage
     public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>();
 
+    @UnsupportedAppUsage
     public ZenModeConfig() { }
 
     public ZenModeConfig(Parcel source) {
@@ -240,11 +244,29 @@
                 .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom))
                 .append(",suppressedVisualEffects=").append(suppressedVisualEffects)
                 .append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd)
-                .append(",automaticRules=").append(automaticRules)
-                .append(",manualRule=").append(manualRule)
+                .append(",\nautomaticRules=").append(rulesToString())
+                .append(",\nmanualRule=").append(manualRule)
                 .append(']').toString();
     }
 
+    private String rulesToString() {
+        if (automaticRules.isEmpty()) {
+            return "{}";
+        }
+
+        StringBuilder buffer = new StringBuilder(automaticRules.size() * 28);
+        buffer.append('{');
+        for (int i = 0; i < automaticRules.size(); i++) {
+            if (i > 0) {
+                buffer.append(",\n");
+            }
+            Object value = automaticRules.valueAt(i);
+            buffer.append(value);
+        }
+        buffer.append('}');
+        return buffer.toString();
+    }
+
     private Diff diff(ZenModeConfig to) {
         final Diff d = new Diff();
         if (to == null) {
@@ -498,7 +520,7 @@
                     Boolean allowWhenScreenOff = unsafeBoolean(parser, ALLOW_ATT_SCREEN_OFF);
                     if (allowWhenScreenOff != null) {
                         readSuppressedEffects = true;
-                        if (allowWhenScreenOff) {
+                        if (!allowWhenScreenOff) {
                             rt.suppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS
                                     | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
                         }
@@ -506,7 +528,7 @@
                     Boolean allowWhenScreenOn = unsafeBoolean(parser, ALLOW_ATT_SCREEN_ON);
                     if (allowWhenScreenOn != null) {
                         readSuppressedEffects = true;
-                        if (allowWhenScreenOn) {
+                        if (!allowWhenScreenOn) {
                             rt.suppressedVisualEffects |= SUPPRESSED_EFFECT_PEEK;
                         }
                     }
@@ -1007,12 +1029,31 @@
         return true;
     }
 
+    /**
+     * Returns whether the conditionId is a valid ScheduleCondition.
+     * If allowNever is true, this will return true even if the ScheduleCondition never occurs.
+     */
+    public static boolean isValidScheduleConditionId(Uri conditionId, boolean allowNever) {
+        ScheduleInfo info;
+        try {
+            info = tryParseScheduleConditionId(conditionId);
+        } catch (NullPointerException | ArrayIndexOutOfBoundsException e) {
+            return false;
+        }
+
+        if (info == null || (!allowNever && (info.days == null || info.days.length == 0))) {
+            return false;
+        }
+        return true;
+    }
+
+    @UnsupportedAppUsage
     public static ScheduleInfo tryParseScheduleConditionId(Uri conditionId) {
         final boolean isSchedule =  conditionId != null
-                && conditionId.getScheme().equals(Condition.SCHEME)
-                && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY)
+                && Condition.SCHEME.equals(conditionId.getScheme())
+                && ZenModeConfig.SYSTEM_AUTHORITY.equals(conditionId.getAuthority())
                 && conditionId.getPathSegments().size() == 1
-                && conditionId.getPathSegments().get(0).equals(ZenModeConfig.SCHEDULE_PATH);
+                && ZenModeConfig.SCHEDULE_PATH.equals(conditionId.getPathSegments().get(0));
         if (!isSchedule) return null;
         final int[] start = tryParseHourAndMinute(conditionId.getQueryParameter("start"));
         final int[] end = tryParseHourAndMinute(conditionId.getQueryParameter("end"));
@@ -1032,10 +1073,15 @@
     }
 
     public static class ScheduleInfo {
+        @UnsupportedAppUsage
         public int[] days;
+        @UnsupportedAppUsage
         public int startHour;
+        @UnsupportedAppUsage
         public int startMinute;
+        @UnsupportedAppUsage
         public int endHour;
+        @UnsupportedAppUsage
         public int endMinute;
         public boolean exitAtAlarm;
         public long nextAlarm;
@@ -1110,10 +1156,10 @@
 
     public static EventInfo tryParseEventConditionId(Uri conditionId) {
         final boolean isEvent = conditionId != null
-                && conditionId.getScheme().equals(Condition.SCHEME)
-                && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY)
+                && Condition.SCHEME.equals(conditionId.getScheme())
+                && ZenModeConfig.SYSTEM_AUTHORITY.equals(conditionId.getAuthority())
                 && conditionId.getPathSegments().size() == 1
-                && conditionId.getPathSegments().get(0).equals(EVENT_PATH);
+                && EVENT_PATH.equals(conditionId.getPathSegments().get(0));
         if (!isEvent) return null;
         final EventInfo rt = new EventInfo();
         rt.userId = tryParseInt(conditionId.getQueryParameter("userId"), UserHandle.USER_NULL);
@@ -1253,14 +1299,20 @@
     }
 
     public static class ZenRule implements Parcelable {
+        @UnsupportedAppUsage
         public boolean enabled;
+        @UnsupportedAppUsage
         public boolean snoozing;         // user manually disabled this instance
+        @UnsupportedAppUsage
         public String name;              // required for automatic
+        @UnsupportedAppUsage
         public int zenMode;
+        @UnsupportedAppUsage
         public Uri conditionId;          // required for automatic
         public Condition condition;      // optional
         public ComponentName component;  // optional
         public String id;                // required for automatic (unique)
+        @UnsupportedAppUsage
         public long creationTime;        // required for automatic
         public String enabler;          // package name, only used for manual rules.
 
@@ -1322,14 +1374,14 @@
         @Override
         public String toString() {
             return new StringBuilder(ZenRule.class.getSimpleName()).append('[')
-                    .append("enabled=").append(enabled)
+                    .append("id=").append(id)
+                    .append(",enabled=").append(String.valueOf(enabled).toUpperCase())
                     .append(",snoozing=").append(snoozing)
                     .append(",name=").append(name)
                     .append(",zenMode=").append(Global.zenModeToString(zenMode))
                     .append(",conditionId=").append(conditionId)
                     .append(",condition=").append(condition)
                     .append(",component=").append(component)
-                    .append(",id=").append(id)
                     .append(",creationTime=").append(creationTime)
                     .append(",enabler=").append(enabler)
                     .append(']').toString();
@@ -1420,14 +1472,13 @@
                     && Objects.equals(other.condition, condition)
                     && Objects.equals(other.component, component)
                     && Objects.equals(other.id, id)
-                    && other.creationTime == creationTime
                     && Objects.equals(other.enabler, enabler);
         }
 
         @Override
         public int hashCode() {
             return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
-                    component, id, creationTime, enabler);
+                    component, id, enabler);
         }
 
         public boolean isAutomaticActive() {
@@ -1461,7 +1512,7 @@
             final int N = lines.size();
             for (int i = 0; i < N; i++) {
                 if (i > 0) {
-                    sb.append(',');
+                    sb.append(",\n");
                 }
                 sb.append(lines.get(i));
             }
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 76d89ef..bd953ca 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.content.Intent;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
@@ -266,6 +267,7 @@
          * @hide
          */
         @Nullable
+        @UnsupportedAppUsage
         public Integer getCaptureSession() {
             if (mCaptureAvailable) {
                 return mCaptureSession;
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 8f79bcf..0bbc07e 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -17,6 +17,7 @@
 package android.service.voice;
 
 import android.annotation.SdkConstant;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
@@ -294,6 +295,7 @@
       * @return true if the keyphrase and locale combination is supported, false otherwise.
       * @hide
       */
+    @UnsupportedAppUsage
     public final boolean isKeyphraseAndLocaleSupportedForHotword(String keyphrase, Locale locale) {
         if (mKeyphraseEnrollmentInfo == null) {
             return false;
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index cd177c4..26223f7 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -109,6 +109,12 @@
      */
     public static final int SHOW_SOURCE_ACTIVITY = 1<<4;
 
+    /**
+     * Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked
+     * from a physical button.
+     */
+    public static final int SHOW_SOURCE_PUSH_TO_TALK = 1 << 5;
+
     final Context mContext;
     final HandlerCaller mHandlerCaller;
 
diff --git a/core/java/android/service/vr/VrListenerService.java b/core/java/android/service/vr/VrListenerService.java
index fa3d065..3c38495 100644
--- a/core/java/android/service/vr/VrListenerService.java
+++ b/core/java/android/service/vr/VrListenerService.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SdkConstant;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.Service;
 import android.content.ComponentName;
@@ -139,6 +140,7 @@
      * @see android.R.attr#enableVrMode
      * @hide
      */
+    @UnsupportedAppUsage
     public void onCurrentVrActivityChanged(
             ComponentName component, boolean running2dInVr, int pid) {
         // Override to implement. Default to old behaviour of sending null for 2D.
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index c48b6d1..2846730 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -19,8 +19,10 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
 import android.app.WallpaperColors;
+import android.app.WallpaperInfo;
 import android.app.WallpaperManager;
 import android.content.Context;
 import android.content.Intent;
@@ -108,6 +110,7 @@
     private static final int MSG_VISIBILITY_CHANGED = 10010;
     private static final int MSG_WALLPAPER_OFFSETS = 10020;
     private static final int MSG_WALLPAPER_COMMAND = 10025;
+    @UnsupportedAppUsage
     private static final int MSG_WINDOW_RESIZED = 10030;
     private static final int MSG_WINDOW_MOVED = 10035;
     private static final int MSG_TOUCH_EVENT = 10040;
@@ -190,6 +193,7 @@
 
         final Object mLock = new Object();
         boolean mOffsetMessageEnqueued;
+        @UnsupportedAppUsage
         float mPendingXOffset;
         float mPendingYOffset;
         float mPendingXOffsetStep;
@@ -436,8 +440,7 @@
 
         /**
          * Returns true if this engine is running in ambient mode -- that is,
-         * it is being shown in low power mode, in always on display.
-         * @hide
+         * it is being shown in low power mode, on always on display.
          */
         public boolean isInAmbientMode() {
             return mIsInAmbientMode;
@@ -479,6 +482,7 @@
         }
 
         /** {@hide} */
+        @UnsupportedAppUsage
         public void setFixedSizeAllowed(boolean allowed) {
             mFixedSizeAllowed = allowed;
         }
@@ -563,10 +567,12 @@
          * Called when the device enters or exits ambient mode.
          *
          * @param inAmbientMode {@code true} if in ambient mode.
-         * @param animated {@code true} if you'll have te opportunity of animating your transition
-         *                 {@code false} when the screen will blank and the wallpaper should be
-         *                 set to ambient mode immediately.
-         * @hide
+         * @param animated {@code true} if you'll have the opportunity of animating your transition
+         *                 {@code false} when the wallpaper should present its ambient version
+         *                 immediately.
+         *
+         * @see #isInAmbientMode()
+         * @see WallpaperInfo#supportsAmbientMode()
          */
         public void onAmbientModeChanged(boolean inAmbientMode, boolean animated) {
         }
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 6f1bd78..83f14d1 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -20,6 +20,7 @@
 import android.annotation.RawRes;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -668,8 +669,10 @@
     }
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private Connection mConnectingServiceConnection;
     private Connection mServiceConnection;
+    @UnsupportedAppUsage
     private OnInitListener mInitListener;
     // Written from an unspecified application thread, read from
     // a binder thread.
@@ -686,6 +689,7 @@
     private final Map<CharSequence, Uri> mUtterances;
     private final Bundle mParams = new Bundle();
     private final TtsEngines mEnginesHelper;
+    @UnsupportedAppUsage
     private volatile String mCurrentEngine = null;
 
     /**
@@ -1425,6 +1429,7 @@
      * @return the engine currently in use by this TextToSpeech instance.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getCurrentEngine() {
         return mCurrentEngine;
     }
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index a8c3453..a7b280b 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -30,6 +30,7 @@
 
 import static android.provider.Settings.Secure.getString;
 
+import android.annotation.UnsupportedAppUsage;
 import android.provider.Settings;
 import android.speech.tts.TextToSpeech.Engine;
 import android.speech.tts.TextToSpeech.EngineInfo;
@@ -101,6 +102,7 @@
         sNormalizeCountry = Collections.unmodifiableMap(normalizeCountry);
     }
 
+    @UnsupportedAppUsage
     public TtsEngines(Context ctx) {
         mContext = ctx;
     }
@@ -155,6 +157,7 @@
      *
      * @return A list of engine info objects. The list can be empty, but never {@code null}.
      */
+    @UnsupportedAppUsage
     public List<EngineInfo> getEngines() {
         PackageManager pm = mContext.getPackageManager();
         Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE);
@@ -194,6 +197,7 @@
     /**
      * @return an intent that can launch the settings activity for a given tts engine.
      */
+    @UnsupportedAppUsage
     public Intent getSettingsIntent(String engine) {
         PackageManager pm = mContext.getPackageManager();
         Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE);
@@ -327,6 +331,7 @@
      * @param engineName the engine to return the locale for.
      * @return the locale preference for this engine. Will be non null.
      */
+    @UnsupportedAppUsage
     public Locale getLocalePrefForEngine(String engineName) {
         return getLocalePrefForEngine(engineName,
                 getString(mContext.getContentResolver(), Settings.Secure.TTS_DEFAULT_LOCALE));
@@ -376,6 +381,7 @@
      * country codes ({@link Locale#getISO3Language()} and {@link Locale#getISO3Country()}),
      * if it fails to do so, we return null.
      */
+    @UnsupportedAppUsage
     public Locale parseLocaleString(String localeString) {
         String language = "", country = "", variant = "";
         if (!TextUtils.isEmpty(localeString)) {
@@ -436,6 +442,7 @@
      * This method tries to convert three-letter language and country codes into their two-letter
      * equivalents. If it fails to do so, it keeps the value from the TTS locale.
      */
+    @UnsupportedAppUsage
     public static Locale normalizeTTSLocale(Locale ttsLocale) {
         String language = ttsLocale.getLanguage();
         if (!TextUtils.isEmpty(language)) {
@@ -514,6 +521,7 @@
      * the passed locale is null, an empty string will be serialized; that empty string, when
      * read back, will evaluate to {@link Locale#getDefault()}.
      */
+    @UnsupportedAppUsage
     public synchronized void updateLocalePrefForEngine(String engineName, Locale newLocale) {
         final String prefList = Settings.Secure.getString(mContext.getContentResolver(),
                 Settings.Secure.TTS_DEFAULT_LOCALE);
diff --git a/core/java/android/text/AndroidBidi.java b/core/java/android/text/AndroidBidi.java
index 72383cf..bb7fb44 100644
--- a/core/java/android/text/AndroidBidi.java
+++ b/core/java/android/text/AndroidBidi.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.annotation.UnsupportedAppUsage;
 import android.icu.lang.UCharacter;
 import android.icu.lang.UCharacterDirection;
 import android.icu.lang.UProperty;
@@ -61,6 +62,7 @@
     /**
      * Runs the bidi algorithm on input text.
      */
+    @UnsupportedAppUsage
     public static int bidi(int dir, char[] chs, byte[] chInfo) {
         if (chs == null || chInfo == null) {
             throw new NullPointerException();
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index fc1bfef..2b33fae 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Path;
@@ -321,6 +322,7 @@
      * if boring.
      * @hide
      */
+    @UnsupportedAppUsage
     public static Metrics isBoring(CharSequence text, TextPaint paint,
             TextDirectionHeuristic textDir, Metrics metrics) {
         final int textLength = text.length();
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index febca7ec9..c46c831 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -20,6 +20,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.text.style.ReplacementSpan;
@@ -353,6 +354,7 @@
      * @deprecated Use {@link Builder} instead.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public DynamicLayout(@NonNull CharSequence base, @NonNull CharSequence display,
                          @NonNull TextPaint paint,
                          @IntRange(from = 0) int width,
@@ -944,6 +946,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int[] getBlockEndLines() {
         return mBlockEndLines;
     }
@@ -951,6 +954,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int[] getBlockIndices() {
         return mBlockIndices;
     }
@@ -973,6 +977,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getNumberOfBlocks() {
         return mNumberOfBlocks;
     }
@@ -980,6 +985,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getIndexFirstChangedBlock() {
         return mIndexFirstChangedBlock;
     }
@@ -987,6 +993,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setIndexFirstChangedBlock(int i) {
         mIndexFirstChangedBlock = i;
     }
@@ -1169,6 +1176,7 @@
 
     private Rect mTempRect = new Rect();
 
+    @UnsupportedAppUsage
     private static StaticLayout sStaticLayout = null;
     private static StaticLayout.Builder sBuilder = null;
 
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 7386e3e..9e0fee33 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontVariationAxis;
 import android.net.Uri;
 
@@ -43,6 +44,7 @@
     /**
      * Returns the ordered list of families included in the system fonts.
      */
+    @UnsupportedAppUsage
     public @NonNull Family[] getFamilies() {
         return mFamilies;
     }
@@ -89,6 +91,7 @@
         /**
          * Returns the index to be used to access this font when accessing a TTC file.
          */
+        @UnsupportedAppUsage
         public int getTtcIndex() {
             return mTtcIndex;
         }
@@ -96,6 +99,7 @@
         /**
          * Returns the list of axes associated to this font.
          */
+        @UnsupportedAppUsage
         public @NonNull FontVariationAxis[] getAxes() {
             return mAxes;
         }
@@ -103,6 +107,7 @@
         /**
          * Returns the weight value for this font.
          */
+        @UnsupportedAppUsage
         public int getWeight() {
             return mWeight;
         }
@@ -110,6 +115,7 @@
         /**
          * Returns whether this font is italic.
          */
+        @UnsupportedAppUsage
         public boolean isItalic() {
             return mIsItalic;
         }
@@ -224,6 +230,7 @@
         /**
          * Returns the name given by the system to this font family.
          */
+        @UnsupportedAppUsage
         public @Nullable String getName() {
             return mName;
         }
@@ -231,6 +238,7 @@
         /**
          * Returns the list of fonts included in this family.
          */
+        @UnsupportedAppUsage
         public @Nullable Font[] getFonts() {
             return mFonts;
         }
@@ -245,6 +253,7 @@
         /**
          * Returns the font variant for this family, e.g. "elegant" or "compact". May be null.
          */
+        @UnsupportedAppUsage
         public @Variant int getVariant() {
             return mVariant;
         }
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index c3aac74..18f8db2 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.app.Application;
 import android.content.res.Resources;
@@ -628,6 +629,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static void withinStyle(StringBuilder out, CharSequence text,
                                     int start, int end) {
         for (int i = start; i < end; i++) {
diff --git a/core/java/android/text/InputFilter.java b/core/java/android/text/InputFilter.java
index a507f2b..a9a7b2f 100644
--- a/core/java/android/text/InputFilter.java
+++ b/core/java/android/text/InputFilter.java
@@ -17,6 +17,7 @@
 package android.text;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 
 import com.android.internal.util.Preconditions;
 
@@ -164,6 +165,7 @@
      * greater than the specified length.
      */
     public static class LengthFilter implements InputFilter {
+        @UnsupportedAppUsage
         private final int mMax;
 
         public LengthFilter(int max) {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 2367d63..33c977b 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.IntRange;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Path;
@@ -49,9 +50,9 @@
 public abstract class Layout {
     /** @hide */
     @IntDef(prefix = { "BREAK_STRATEGY_" }, value = {
-            BREAK_STRATEGY_SIMPLE,
-            BREAK_STRATEGY_HIGH_QUALITY,
-            BREAK_STRATEGY_BALANCED
+            NativeLineBreaker.BREAK_STRATEGY_SIMPLE,
+            NativeLineBreaker.BREAK_STRATEGY_HIGH_QUALITY,
+            NativeLineBreaker.BREAK_STRATEGY_BALANCED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface BreakStrategy {}
@@ -62,19 +63,20 @@
      * before it (which yields a more consistent user experience when editing), but layout may not
      * be the highest quality.
      */
-    public static final int BREAK_STRATEGY_SIMPLE = 0;
+    public static final int BREAK_STRATEGY_SIMPLE = NativeLineBreaker.BREAK_STRATEGY_SIMPLE;
 
     /**
      * Value for break strategy indicating high quality line breaking, including automatic
      * hyphenation and doing whole-paragraph optimization of line breaks.
      */
-    public static final int BREAK_STRATEGY_HIGH_QUALITY = 1;
+    public static final int BREAK_STRATEGY_HIGH_QUALITY =
+            NativeLineBreaker.BREAK_STRATEGY_HIGH_QUALITY;
 
     /**
      * Value for break strategy indicating balanced line breaking. The breaks are chosen to
      * make all lines as close to the same length as possible, including automatic hyphenation.
      */
-    public static final int BREAK_STRATEGY_BALANCED = 2;
+    public static final int BREAK_STRATEGY_BALANCED = NativeLineBreaker.BREAK_STRATEGY_BALANCED;
 
     /** @hide */
     @IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = {
@@ -92,29 +94,32 @@
      * layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used
      * as suggestions for potential line breaks.
      */
-    public static final int HYPHENATION_FREQUENCY_NONE = 0;
+    public static final int HYPHENATION_FREQUENCY_NONE =
+            NativeLineBreaker.HYPHENATION_FREQUENCY_NONE;
 
     /**
      * Value for hyphenation frequency indicating a light amount of automatic hyphenation, which
      * is a conservative default. Useful for informal cases, such as short sentences or chat
      * messages.
      */
-    public static final int HYPHENATION_FREQUENCY_NORMAL = 1;
+    public static final int HYPHENATION_FREQUENCY_NORMAL =
+            NativeLineBreaker.HYPHENATION_FREQUENCY_NORMAL;
 
     /**
      * Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical
      * in typography. Useful for running text and where it's important to put the maximum amount of
      * text in a screen with limited space.
      */
-    public static final int HYPHENATION_FREQUENCY_FULL = 2;
+    public static final int HYPHENATION_FREQUENCY_FULL =
+            NativeLineBreaker.HYPHENATION_FREQUENCY_FULL;
 
     private static final ParagraphStyle[] NO_PARA_SPANS =
         ArrayUtils.emptyArray(ParagraphStyle.class);
 
     /** @hide */
     @IntDef(prefix = { "JUSTIFICATION_MODE_" }, value = {
-            JUSTIFICATION_MODE_NONE,
-            JUSTIFICATION_MODE_INTER_WORD
+            NativeLineBreaker.JUSTIFICATION_MODE_NONE,
+            NativeLineBreaker.JUSTIFICATION_MODE_INTER_WORD
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface JustificationMode {}
@@ -122,12 +127,13 @@
     /**
      * Value for justification mode indicating no justification.
      */
-    public static final int JUSTIFICATION_MODE_NONE = 0;
+    public static final int JUSTIFICATION_MODE_NONE = NativeLineBreaker.JUSTIFICATION_MODE_NONE;
 
     /**
      * Value for justification mode indicating the text is justified by stretching word spacing.
      */
-    public static final int JUSTIFICATION_MODE_INTER_WORD = 1;
+    public static final int JUSTIFICATION_MODE_INTER_WORD =
+            NativeLineBreaker.JUSTIFICATION_MODE_INTER_WORD;
 
     /*
      * Line spacing multiplier for default line spacing.
@@ -411,6 +417,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void drawText(Canvas canvas, int firstLine, int lastLine) {
         int previousLineBottom = getLineTop(firstLine);
         int previousLineEnd = getLineStart(firstLine);
@@ -578,6 +585,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void drawBackground(Canvas canvas, Path highlight, Paint highlightPaint,
             int cursorOffsetVertical, int firstLine, int lastLine) {
         // First, draw LineBackgroundSpans.
@@ -658,6 +666,7 @@
      * @return The range of lines that need to be drawn, possibly empty.
      * @hide
      */
+    @UnsupportedAppUsage
     public long getLineRangeForDraw(Canvas canvas) {
         int dtop, dbottom;
 
@@ -928,6 +937,7 @@
      * @return true if at a level boundary
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isLevelBoundary(int offset) {
         int line = getLineForOffset(offset);
         Directions dirs = getLineDirections(line);
@@ -1134,6 +1144,7 @@
      * optionally clamp it so that it doesn't exceed the width of the layout.
      * @hide
      */
+    @UnsupportedAppUsage
     public float getPrimaryHorizontal(int offset, boolean clamped) {
         boolean trailing = primaryIsTrailingPrevious(offset);
         return getHorizontal(offset, trailing, clamped);
@@ -1153,6 +1164,7 @@
      * optionally clamp it so that it doesn't exceed the width of the layout.
      * @hide
      */
+    @UnsupportedAppUsage
     public float getSecondaryHorizontal(int offset, boolean clamped) {
         boolean trailing = primaryIsTrailingPrevious(offset);
         return getHorizontal(offset, !trailing, clamped);
@@ -1594,10 +1606,11 @@
         }
 
         float get(final int offset) {
-            if (mHorizontals == null) {
+            final int index = offset - mLineStartOffset;
+            if (mHorizontals == null || index < 0 || index >= mHorizontals.length) {
                 return getHorizontal(offset, mPrimary);
             } else {
-                return mHorizontals[offset - mLineStartOffset];
+                return mHorizontals[index];
             }
         }
     }
@@ -1783,6 +1796,7 @@
      * only robust for left-aligned displays.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean shouldClampCursor(int line) {
         // Only clamp cursor position in left-aligned displays.
         switch (getParagraphAlignment(line)) {
@@ -2435,6 +2449,7 @@
     }
 
     private CharSequence mText;
+    @UnsupportedAppUsage
     private TextPaint mPaint;
     private TextPaint mWorkPaint = new TextPaint();
     private int mWidth;
@@ -2460,6 +2475,7 @@
 
     /* package */ static final int DIR_REQUEST_LTR = 1;
     /* package */ static final int DIR_REQUEST_RTL = -1;
+    @UnsupportedAppUsage
     /* package */ static final int DIR_REQUEST_DEFAULT_LTR = 2;
     /* package */ static final int DIR_REQUEST_DEFAULT_RTL = -2;
 
@@ -2473,8 +2489,10 @@
         ALIGN_OPPOSITE,
         ALIGN_CENTER,
         /** @hide */
+        @UnsupportedAppUsage
         ALIGN_LEFT,
         /** @hide */
+        @UnsupportedAppUsage
         ALIGN_RIGHT,
     }
 
@@ -2482,11 +2500,13 @@
 
     /** @hide */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @UnsupportedAppUsage
     public static final Directions DIRS_ALL_LEFT_TO_RIGHT =
         new Directions(new int[] { 0, RUN_LENGTH_MASK });
 
     /** @hide */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @UnsupportedAppUsage
     public static final Directions DIRS_ALL_RIGHT_TO_LEFT =
         new Directions(new int[] { 0, RUN_LENGTH_MASK | RUN_RTL_FLAG });
 
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index c2c3182..9bf8cd2 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -30,10 +30,6 @@
 import android.text.style.ReplacementSpan;
 import android.util.Pools.SynchronizedPool;
 
-import dalvik.annotation.optimization.CriticalNative;
-
-import libcore.util.NativeAllocationRegistry;
-
 import java.util.Arrays;
 
 /**
@@ -62,9 +58,6 @@
 public class MeasuredParagraph {
     private static final char OBJECT_REPLACEMENT_CHARACTER = '\uFFFC';
 
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-            MeasuredParagraph.class.getClassLoader(), nGetReleaseFunc(), 1024);
-
     private MeasuredParagraph() {}  // Use build static functions instead.
 
     private static final SynchronizedPool<MeasuredParagraph> sPool = new SynchronizedPool<>(1);
@@ -128,24 +121,7 @@
     private @Nullable IntArray mFontMetrics = new IntArray(4 * 4);
 
     // The native MeasuredParagraph.
-    // See getNativePtr comments.
-    // Do not modify these members directly. Use bindNativeObject/unbindNativeObject instead.
-    private /* Maybe Zero */ long mNativePtr = 0;
-    private @Nullable Runnable mNativeObjectCleaner;
-
-    // Associate the native object to this Java object.
-    private void bindNativeObject(/* Non Zero*/ long nativePtr) {
-        mNativePtr = nativePtr;
-        mNativeObjectCleaner = sRegistry.registerNativeAllocation(this, nativePtr);
-    }
-
-    // Decouple the native object from this Java object and release the native object.
-    private void unbindNativeObject() {
-        if (mNativePtr != 0) {
-            mNativeObjectCleaner.run();
-            mNativePtr = 0;
-        }
-    }
+    private @Nullable NativeMeasuredParagraph mNativeMeasuredParagraph;
 
     // Following two objects are for avoiding object allocation.
     private @NonNull TextPaint mCachedPaint = new TextPaint();
@@ -173,7 +149,7 @@
         mWidths.clear();
         mFontMetrics.clear();
         mSpanEndCache.clear();
-        unbindNativeObject();
+        mNativeMeasuredParagraph = null;
     }
 
     /**
@@ -267,10 +243,10 @@
      * Returns the native ptr of the MeasuredParagraph.
      *
      * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
-     * Returns 0 in other cases.
+     * Returns null in other cases.
      */
-    public /* Maybe Zero */ long getNativePtr() {
-        return mNativePtr;
+    public NativeMeasuredParagraph getNativeMeasuredParagraph() {
+        return mNativeMeasuredParagraph;
     }
 
     /**
@@ -283,7 +259,7 @@
      * @param end the exclusive end offset of the target region in the text
      */
     public float getWidth(int start, int end) {
-        if (mNativePtr == 0) {
+        if (mNativeMeasuredParagraph == null) {
             // We have result in Java.
             final float[] widths = mWidths.getRawArray();
             float r = 0.0f;
@@ -293,7 +269,7 @@
             return r;
         } else {
             // We have result in native.
-            return nGetWidth(mNativePtr, start, end);
+            return mNativeMeasuredParagraph.getWidth(start, end);
         }
     }
 
@@ -305,7 +281,16 @@
      */
     public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
             @NonNull Rect bounds) {
-        nGetBounds(mNativePtr, mCopiedBuffer, start, end, bounds);
+        mNativeMeasuredParagraph.getBounds(mCopiedBuffer, start, end, bounds);
+    }
+
+    /**
+     * Returns a width of the character at the offset.
+     *
+     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
+     */
+    public float getCharWidthAt(@IntRange(from = 0) int offset) {
+        return mNativeMeasuredParagraph.getCharWidthAt(offset);
     }
 
     /**
@@ -364,7 +349,7 @@
         if (mt.mSpanned == null) {
             // No style change by MetricsAffectingSpan. Just measure all text.
             mt.applyMetricsAffectingSpan(
-                    paint, null /* spans */, start, end, 0 /* native static layout ptr */);
+                    paint, null /* spans */, start, end, null /* native builder ptr */);
         } else {
             // There may be a MetricsAffectingSpan. Split into span transitions and apply styles.
             int spanEnd;
@@ -374,7 +359,7 @@
                         MetricAffectingSpan.class);
                 spans = TextUtils.removeEmptySpans(spans, mt.mSpanned, MetricAffectingSpan.class);
                 mt.applyMetricsAffectingSpan(
-                        paint, spans, spanStart, spanEnd, 0 /* native static layout ptr */);
+                        paint, spans, spanStart, spanEnd, null /* native builder ptr */);
             }
         }
         return mt;
@@ -406,25 +391,16 @@
             @Nullable MeasuredParagraph recycle) {
         final MeasuredParagraph mt = recycle == null ? obtain() : recycle;
         mt.resetAndAnalyzeBidi(text, start, end, textDir);
+        final NativeMeasuredParagraph.Builder builder = new NativeMeasuredParagraph.Builder();
         if (mt.mTextLength == 0) {
             // Need to build empty native measured text for StaticLayout.
             // TODO: Stop creating empty measured text for empty lines.
-            long nativeBuilderPtr = nInitBuilder();
-            try {
-                mt.bindNativeObject(
-                        nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer,
-                              computeHyphenation, computeLayout));
-            } finally {
-                nFreeBuilder(nativeBuilderPtr);
-            }
-            return mt;
-        }
-
-        long nativeBuilderPtr = nInitBuilder();
-        try {
+            mt.mNativeMeasuredParagraph = builder.build(mt.mCopiedBuffer, computeHyphenation,
+                        computeLayout);
+        } else {
             if (mt.mSpanned == null) {
                 // No style change by MetricsAffectingSpan. Just measure all text.
-                mt.applyMetricsAffectingSpan(paint, null /* spans */, start, end, nativeBuilderPtr);
+                mt.applyMetricsAffectingSpan(paint, null /* spans */, start, end, builder);
                 mt.mSpanEndCache.append(end);
             } else {
                 // There may be a MetricsAffectingSpan. Split into span transitions and apply
@@ -437,15 +413,12 @@
                             MetricAffectingSpan.class);
                     spans = TextUtils.removeEmptySpans(spans, mt.mSpanned,
                                                        MetricAffectingSpan.class);
-                    mt.applyMetricsAffectingSpan(paint, spans, spanStart, spanEnd,
-                                                 nativeBuilderPtr);
+                    mt.applyMetricsAffectingSpan(paint, spans, spanStart, spanEnd, builder);
                     mt.mSpanEndCache.append(spanEnd);
                 }
             }
-            mt.bindNativeObject(nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer,
-                      computeHyphenation, computeLayout));
-        } finally {
-            nFreeBuilder(nativeBuilderPtr);
+            mt.mNativeMeasuredParagraph = builder.build(mt.mCopiedBuffer, computeHyphenation,
+                    computeLayout);
         }
 
         return mt;
@@ -517,13 +490,13 @@
     private void applyReplacementRun(@NonNull ReplacementSpan replacement,
                                      @IntRange(from = 0) int start,  // inclusive, in copied buffer
                                      @IntRange(from = 0) int end,  // exclusive, in copied buffer
-                                     /* Maybe Zero */ long nativeBuilderPtr) {
+                                     @Nullable NativeMeasuredParagraph.Builder builder) {
         // Use original text. Shouldn't matter.
         // TODO: passing uninitizlied FontMetrics to developers. Do we need to keep this for
         //       backward compatibility? or Should we initialize them for getFontMetricsInt?
         final float width = replacement.getSize(
                 mCachedPaint, mSpanned, start + mTextStart, end + mTextStart, mCachedFm);
-        if (nativeBuilderPtr == 0) {
+        if (builder == null) {
             // Assigns all width to the first character. This is the same behavior as minikin.
             mWidths.set(start, width);
             if (end > start + 1) {
@@ -531,24 +504,22 @@
             }
             mWholeWidth += width;
         } else {
-            nAddReplacementRun(nativeBuilderPtr, mCachedPaint.getNativeInstance(), start, end,
-                               width);
+            builder.addReplacementRun(mCachedPaint, start, end, width);
         }
     }
 
     private void applyStyleRun(@IntRange(from = 0) int start,  // inclusive, in copied buffer
                                @IntRange(from = 0) int end,  // exclusive, in copied buffer
-                               /* Maybe Zero */ long nativeBuilderPtr) {
+                               @Nullable NativeMeasuredParagraph.Builder builder) {
 
         if (mLtrWithoutBidi) {
             // If the whole text is LTR direction, just apply whole region.
-            if (nativeBuilderPtr == 0) {
+            if (builder == null) {
                 mWholeWidth += mCachedPaint.getTextRunAdvances(
                         mCopiedBuffer, start, end - start, start, end - start, false /* isRtl */,
                         mWidths.getRawArray(), start);
             } else {
-                nAddStyleRun(nativeBuilderPtr, mCachedPaint.getNativeInstance(), start, end,
-                        false /* isRtl */);
+                builder.addStyleRun(mCachedPaint, start, end, false /* isRtl */);
             }
         } else {
             // If there is multiple bidi levels, split into individual bidi level and apply style.
@@ -558,14 +529,13 @@
             for (int levelStart = start, levelEnd = start + 1;; ++levelEnd) {
                 if (levelEnd == end || mLevels.get(levelEnd) != level) {  // transition point
                     final boolean isRtl = (level & 0x1) != 0;
-                    if (nativeBuilderPtr == 0) {
+                    if (builder == null) {
                         final int levelLength = levelEnd - levelStart;
                         mWholeWidth += mCachedPaint.getTextRunAdvances(
                                 mCopiedBuffer, levelStart, levelLength, levelStart, levelLength,
                                 isRtl, mWidths.getRawArray(), levelStart);
                     } else {
-                        nAddStyleRun(nativeBuilderPtr, mCachedPaint.getNativeInstance(), levelStart,
-                                levelEnd, isRtl);
+                        builder.addStyleRun(mCachedPaint, levelStart, levelEnd, isRtl);
                     }
                     if (levelEnd == end) {
                         break;
@@ -582,12 +552,12 @@
             @Nullable MetricAffectingSpan[] spans,
             @IntRange(from = 0) int start,  // inclusive, in original text buffer
             @IntRange(from = 0) int end,  // exclusive, in original text buffer
-            /* Maybe Zero */ long nativeBuilderPtr) {
+            @Nullable NativeMeasuredParagraph.Builder builder) {
         mCachedPaint.set(paint);
         // XXX paint should not have a baseline shift, but...
         mCachedPaint.baselineShift = 0;
 
-        final boolean needFontMetrics = nativeBuilderPtr != 0;
+        final boolean needFontMetrics = builder != null;
 
         if (needFontMetrics && mCachedFm == null) {
             mCachedFm = new Paint.FontMetricsInt();
@@ -610,15 +580,14 @@
         final int startInCopiedBuffer = start - mTextStart;
         final int endInCopiedBuffer = end - mTextStart;
 
-        if (nativeBuilderPtr != 0) {
+        if (builder != null) {
             mCachedPaint.getFontMetricsInt(mCachedFm);
         }
 
         if (replacement != null) {
-            applyReplacementRun(replacement, startInCopiedBuffer, endInCopiedBuffer,
-                                nativeBuilderPtr);
+            applyReplacementRun(replacement, startInCopiedBuffer, endInCopiedBuffer, builder);
         } else {
-            applyStyleRun(startInCopiedBuffer, endInCopiedBuffer, nativeBuilderPtr);
+            applyStyleRun(startInCopiedBuffer, endInCopiedBuffer, builder);
         }
 
         if (needFontMetrics) {
@@ -689,59 +658,6 @@
      * This only works if the MeasuredParagraph is computed with buildForStaticLayout.
      */
     public @IntRange(from = 0) int getMemoryUsage() {
-        return nGetMemoryUsage(mNativePtr);
+        return mNativeMeasuredParagraph.getMemoryUsage();
     }
-
-    private static native /* Non Zero */ long nInitBuilder();
-
-    /**
-     * Apply style to make native measured text.
-     *
-     * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
-     * @param paintPtr The native paint pointer to be applied.
-     * @param start The start offset in the copied buffer.
-     * @param end The end offset in the copied buffer.
-     * @param isRtl True if the text is RTL.
-     */
-    private static native void nAddStyleRun(/* Non Zero */ long nativeBuilderPtr,
-                                            /* Non Zero */ long paintPtr,
-                                            @IntRange(from = 0) int start,
-                                            @IntRange(from = 0) int end,
-                                            boolean isRtl);
-
-    /**
-     * Apply ReplacementRun to make native measured text.
-     *
-     * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
-     * @param paintPtr The native paint pointer to be applied.
-     * @param start The start offset in the copied buffer.
-     * @param end The end offset in the copied buffer.
-     * @param width The width of the replacement.
-     */
-    private static native void nAddReplacementRun(/* Non Zero */ long nativeBuilderPtr,
-                                                  /* Non Zero */ long paintPtr,
-                                                  @IntRange(from = 0) int start,
-                                                  @IntRange(from = 0) int end,
-                                                  @FloatRange(from = 0) float width);
-
-    private static native long nBuildNativeMeasuredParagraph(/* Non Zero */ long nativeBuilderPtr,
-                                                 @NonNull char[] text,
-                                                 boolean computeHyphenation,
-                                                 boolean computeLayout);
-
-    private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr);
-
-    @CriticalNative
-    private static native float nGetWidth(/* Non Zero */ long nativePtr,
-                                         @IntRange(from = 0) int start,
-                                         @IntRange(from = 0) int end);
-
-    @CriticalNative
-    private static native /* Non Zero */ long nGetReleaseFunc();
-
-    @CriticalNative
-    private static native int nGetMemoryUsage(/* Non Zero */ long nativePtr);
-
-    private static native void nGetBounds(long nativePtr, char[] buf, int start, int end,
-            Rect rect);
 }
diff --git a/core/java/android/text/NativeLineBreaker.java b/core/java/android/text/NativeLineBreaker.java
new file mode 100644
index 0000000..2bcfa5f
--- /dev/null
+++ b/core/java/android/text/NativeLineBreaker.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import android.annotation.FloatRange;
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
+
+import libcore.util.NativeAllocationRegistry;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A native implementation of the line breaker.
+ * TODO: Consider to make this class public.
+ * @hide
+ */
+public class NativeLineBreaker {
+    @IntDef(prefix = { "BREAK_STRATEGY_" }, value = {
+            BREAK_STRATEGY_SIMPLE,
+            BREAK_STRATEGY_HIGH_QUALITY,
+            BREAK_STRATEGY_BALANCED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BreakStrategy {}
+
+    /**
+     * Value for break strategy indicating simple line breaking. Automatic hyphens are not added
+     * (though soft hyphens are respected), and modifying text generally doesn't affect the layout
+     * before it (which yields a more consistent user experience when editing), but layout may not
+     * be the highest quality.
+     */
+    public static final int BREAK_STRATEGY_SIMPLE = 0;
+
+    /**
+     * Value for break strategy indicating high quality line breaking, including automatic
+     * hyphenation and doing whole-paragraph optimization of line breaks.
+     */
+    public static final int BREAK_STRATEGY_HIGH_QUALITY = 1;
+
+    /**
+     * Value for break strategy indicating balanced line breaking. The breaks are chosen to
+     * make all lines as close to the same length as possible, including automatic hyphenation.
+     */
+    public static final int BREAK_STRATEGY_BALANCED = 2;
+
+    @IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = {
+            HYPHENATION_FREQUENCY_NORMAL,
+            HYPHENATION_FREQUENCY_FULL,
+            HYPHENATION_FREQUENCY_NONE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface HyphenationFrequency {}
+
+    /**
+     * Value for hyphenation frequency indicating no automatic hyphenation. Useful
+     * for backward compatibility, and for cases where the automatic hyphenation algorithm results
+     * in incorrect hyphenation. Mid-word breaks may still happen when a word is wider than the
+     * layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used
+     * as suggestions for potential line breaks.
+     */
+    public static final int HYPHENATION_FREQUENCY_NONE = 0;
+
+    /**
+     * Value for hyphenation frequency indicating a light amount of automatic hyphenation, which
+     * is a conservative default. Useful for informal cases, such as short sentences or chat
+     * messages.
+     */
+    public static final int HYPHENATION_FREQUENCY_NORMAL = 1;
+
+    /**
+     * Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical
+     * in typography. Useful for running text and where it's important to put the maximum amount of
+     * text in a screen with limited space.
+     */
+    public static final int HYPHENATION_FREQUENCY_FULL = 2;
+
+    @IntDef(prefix = { "JUSTIFICATION_MODE_" }, value = {
+            JUSTIFICATION_MODE_NONE,
+            JUSTIFICATION_MODE_INTER_WORD
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface JustificationMode {}
+
+    /**
+     * Value for justification mode indicating no justification.
+     */
+    public static final int JUSTIFICATION_MODE_NONE = 0;
+
+    /**
+     * Value for justification mode indicating the text is justified by stretching word spacing.
+     */
+    public static final int JUSTIFICATION_MODE_INTER_WORD = 1;
+
+    /**
+     * A builder class of NativeLineBreaker.
+     */
+    public static class Builder {
+        private @BreakStrategy int mBreakStrategy = BREAK_STRATEGY_SIMPLE;
+        private @HyphenationFrequency int mHyphenationFrequency = HYPHENATION_FREQUENCY_NONE;
+        private @JustificationMode int mJustified = JUSTIFICATION_MODE_NONE;
+        private @Nullable int[] mIndents = null;
+
+        /**
+         * Construct a builder class.
+         */
+        public Builder() {}
+
+        /**
+         * Set break strategy.
+         */
+        public Builder setBreakStrategy(@BreakStrategy int breakStrategy) {
+            mBreakStrategy = breakStrategy;
+            return this;
+        }
+
+        /**
+         * Set hyphenation frequency.
+         */
+        public Builder setHyphenationFrequency(@HyphenationFrequency int hyphenationFrequency) {
+            mHyphenationFrequency = hyphenationFrequency;
+            return this;
+        }
+
+        /**
+         * Set whether the text is justified.
+         */
+        public Builder setJustified(@JustificationMode int justified) {
+            mJustified = justified;
+            return this;
+        }
+
+        /**
+         * Set indents for entire text.
+         *
+         * Sets the total (left + right) indents in pixel per lines.
+         */
+        public Builder setIndents(@Nullable int[] indents) {
+            mIndents = indents;
+            return this;
+        }
+
+        /**
+         * Returns the NativeLineBreaker with given parameters.
+         */
+        NativeLineBreaker build() {
+            return new NativeLineBreaker(mBreakStrategy, mHyphenationFrequency, mJustified,
+                    mIndents);
+        }
+    }
+
+    /**
+     * Line breaking constraints for single paragraph.
+     */
+    public static class ParagraphConstraints {
+        private @FloatRange(from = 0.0f) float mWidth = 0;
+        private @FloatRange(from = 0.0f) float mFirstWidth = 0;
+        private @IntRange(from = 0) int mFirstWidthLineCount = 0;
+        private @Nullable int[] mVariableTabStops = null;
+        private @IntRange(from = 0) int mDefaultTabStop = 0;
+
+        public ParagraphConstraints() {}
+
+        /**
+         * Set width for this paragraph.
+         */
+        public void setWidth(@FloatRange(from = 0.0f) float width) {
+            mWidth = width;
+        }
+
+        /**
+         * Set indent for this paragraph.
+         *
+         * @param firstWidth the line width of the starting of the paragraph
+         * @param firstWidthLineCount the number of lines that applies the firstWidth
+         */
+        public void setIndent(@FloatRange(from = 0.0f) float firstWidth,
+                @IntRange(from = 0) int firstWidthLineCount) {
+            mFirstWidth = firstWidth;
+            mFirstWidthLineCount = firstWidthLineCount;
+        }
+
+        /**
+         * Set tab stops for this paragraph.
+         *
+         * @param tabStops the array of pixels of tap stopping position
+         * @param defaultTabStop pixels of the default tab stopping position
+         */
+        public void setTabStops(@Nullable int[] tabStops, @IntRange(from = 0) int defaultTabStop) {
+            mVariableTabStops = tabStops;
+            mDefaultTabStop = defaultTabStop;
+        }
+
+        /**
+         * Return the width for this paragraph in pixels.
+         */
+        public @FloatRange(from = 0.0f) float getWidth() {
+            return mWidth;
+        }
+
+        /**
+         * Return the first line's width for this paragraph in pixel.
+         *
+         * @see #setIndent(float, int)
+         */
+        public @FloatRange(from = 0.0f) float getFirstWidth() {
+            return mFirstWidth;
+        }
+
+        /**
+         * Return the number of lines to apply the first line's width.
+         *
+         * @see #setIndent(float, int)
+         */
+        public @IntRange(from = 0) int getFirstWidthLineCount() {
+            return mFirstWidthLineCount;
+        }
+
+        /**
+         * Returns the array of tab stops in pixels.
+         *
+         * @see #setTabStops(int[], int)
+         */
+        public @Nullable int[] getTabStops() {
+            return mVariableTabStops;
+        }
+
+        /**
+         * Returns the default tab stops in pixels.
+         *
+         * @see #setTabStop(int[], int)
+         */
+        public @IntRange(from = 0) int getDefaultTabStop() {
+            return mDefaultTabStop;
+        }
+    }
+
+    /**
+     * A result object of a line breaking
+     */
+    public static class LineBreaks {
+        public int breakCount;
+        private static final int INITIAL_SIZE = 16;
+        public int[] breaks = new int[INITIAL_SIZE];
+        public float[] widths = new float[INITIAL_SIZE];
+        public float[] ascents = new float[INITIAL_SIZE];
+        public float[] descents = new float[INITIAL_SIZE];
+        // TODO: Introduce Hyphenator for explaining the meaning of flags.
+        public int[] flags = new int[INITIAL_SIZE];
+        // breaks, widths, and flags should all have the same length
+    }
+
+    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+            NativeLineBreaker.class.getClassLoader(), nGetReleaseFunc(), 64);
+
+    private final long mNativePtr;
+
+    /**
+     * Use Builder instead.
+     */
+    private NativeLineBreaker(@BreakStrategy int breakStrategy,
+            @HyphenationFrequency int hyphenationFrequency, @JustificationMode int justify,
+            @Nullable int[] indents) {
+        mNativePtr = nInit(breakStrategy, hyphenationFrequency,
+                justify == JUSTIFICATION_MODE_INTER_WORD, indents);
+        sRegistry.registerNativeAllocation(this, mNativePtr);
+    }
+
+    /**
+     * Break paragraph into lines.
+     *
+     * The result is filled to out param.
+     *
+     * @param measuredPara a result of the text measurement
+     * @param constraints for a single paragraph
+     * @param lineNumber a line number of this paragraph
+     * @param out object to set line break information for the given paragraph
+     */
+    public void computeLineBreaks(
+            @NonNull NativeMeasuredParagraph measuredPara,
+            @NonNull ParagraphConstraints constraints,
+            @IntRange(from = 0) int lineNumber,
+            @NonNull LineBreaks out) {
+        out.breakCount = nComputeLineBreaks(
+                mNativePtr,
+
+                // Inputs
+                measuredPara.getChars(),
+                measuredPara.getNativePtr(),
+                measuredPara.getChars().length,
+                constraints.mFirstWidth,
+                constraints.mFirstWidthLineCount,
+                constraints.mWidth,
+                constraints.mVariableTabStops,
+                constraints.mDefaultTabStop,
+                lineNumber,
+
+                // Outputs
+                out,
+                out.breaks.length,
+                out.breaks,
+                out.widths,
+                out.ascents,
+                out.descents,
+                out.flags);
+
+    }
+
+    @FastNative
+    private static native long nInit(@BreakStrategy int breakStrategy,
+            @HyphenationFrequency int hyphenationFrequency, boolean isJustified,
+            @Nullable int[] indents);
+
+    @CriticalNative
+    private static native long nGetReleaseFunc();
+
+    // populates LineBreaks and returns the number of breaks found
+    //
+    // the arrays inside the LineBreaks objects are passed in as well
+    // to reduce the number of JNI calls in the common case where the
+    // arrays do not have to be resized
+    // The individual character widths will be returned in charWidths. The length of
+    // charWidths must be at least the length of the text.
+    private static native int nComputeLineBreaks(
+            /* non zero */ long nativePtr,
+
+            // Inputs
+            @NonNull char[] text,
+            /* Non Zero */ long measuredTextPtr,
+            @IntRange(from = 0) int length,
+            @FloatRange(from = 0.0f) float firstWidth,
+            @IntRange(from = 0) int firstWidthLineCount,
+            @FloatRange(from = 0.0f) float restWidth,
+            @Nullable int[] variableTabStops,
+            int defaultTabStop,
+            @IntRange(from = 0) int indentsOffset,
+
+            // Outputs
+            @NonNull LineBreaks recycle,
+            @IntRange(from  = 0) int recycleLength,
+            @NonNull int[] recycleBreaks,
+            @NonNull float[] recycleWidths,
+            @NonNull float[] recycleAscents,
+            @NonNull float[] recycleDescents,
+            @NonNull int[] recycleFlags);
+}
diff --git a/core/java/android/text/NativeMeasuredParagraph.java b/core/java/android/text/NativeMeasuredParagraph.java
new file mode 100644
index 0000000..bfdccca
--- /dev/null
+++ b/core/java/android/text/NativeMeasuredParagraph.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.graphics.Paint;
+import android.graphics.Rect;
+
+import dalvik.annotation.optimization.CriticalNative;
+
+import libcore.util.NativeAllocationRegistry;
+
+/**
+ * A native implementation of measured paragraph.
+ * TODO: Consider to make this class public.
+ * @hide
+ */
+public class NativeMeasuredParagraph {
+    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+            NativeMeasuredParagraph.class.getClassLoader(), nGetReleaseFunc(), 1024);
+
+    private long mNativePtr;
+    private @NonNull char[] mChars;
+
+    // Use builder instead.
+    private NativeMeasuredParagraph(long ptr, @NonNull char[] chars) {
+        mNativePtr = ptr;
+        mChars = chars;
+    }
+
+    /**
+     * Returns a characters of this paragraph.
+     */
+    public char[] getChars() {
+        return mChars;
+    }
+
+    /**
+     * Returns a width of the given region
+     */
+    public float getWidth(int start, int end) {
+        return nGetWidth(mNativePtr, start, end);
+    }
+
+    /**
+     * Returns a memory usage of the native object.
+     */
+    public int getMemoryUsage() {
+        return nGetMemoryUsage(mNativePtr);
+    }
+
+    /**
+     * Fills the boundary box of the given region
+     */
+    public void getBounds(char[] buf, int start, int end, Rect rect) {
+        nGetBounds(mNativePtr, buf, start, end, rect);
+    }
+
+    /**
+     * Returns the width of the character at the given offset
+     */
+    public float getCharWidthAt(int offset) {
+        return nGetCharWidthAt(mNativePtr, offset);
+    }
+
+    /**
+     * Returns a native pointer of the underlying native object.
+     */
+    public long getNativePtr() {
+        return mNativePtr;
+    }
+
+    @CriticalNative
+    private static native float nGetWidth(/* Non Zero */ long nativePtr,
+                                         @IntRange(from = 0) int start,
+                                         @IntRange(from = 0) int end);
+
+    @CriticalNative
+    private static native /* Non Zero */ long nGetReleaseFunc();
+
+    @CriticalNative
+    private static native int nGetMemoryUsage(/* Non Zero */ long nativePtr);
+
+    private static native void nGetBounds(long nativePtr, char[] buf, int start, int end,
+            Rect rect);
+
+    @CriticalNative
+    private static native float nGetCharWidthAt(long nativePtr, int offset);
+
+    /**
+     * A builder for the NativeMeasuredParagraph
+     */
+    public static class Builder {
+        private final long mNativePtr;
+
+        public Builder() {
+            mNativePtr = nInitBuilder();
+        }
+
+        /**
+         * Apply styles to given range
+         */
+        public void addStyleRun(@NonNull Paint paint, int start, int end, boolean isRtl) {
+            nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl);
+        }
+
+        /**
+         * Tells native that the given range is replaced with the object of given width.
+         */
+        public void addReplacementRun(@NonNull Paint paint, int start, int end, float width) {
+            nAddReplacementRun(mNativePtr, paint.getNativeInstance(), start, end, width);
+        }
+
+        /**
+         * Build the NativeMeasuredParagraph
+         */
+        public NativeMeasuredParagraph build(char[] text, boolean computeHyphenation,
+                boolean computeLayout) {
+            try {
+                long ptr = nBuildNativeMeasuredParagraph(mNativePtr, text, computeHyphenation,
+                        computeLayout);
+                NativeMeasuredParagraph res = new NativeMeasuredParagraph(ptr, text);
+                sRegistry.registerNativeAllocation(res, ptr);
+                return res;
+            } finally {
+                nFreeBuilder(mNativePtr);
+            }
+        }
+
+        private static native /* Non Zero */ long nInitBuilder();
+
+        /**
+         * Apply style to make native measured text.
+         *
+         * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
+         * @param paintPtr The native paint pointer to be applied.
+         * @param start The start offset in the copied buffer.
+         * @param end The end offset in the copied buffer.
+         * @param isRtl True if the text is RTL.
+         */
+        private static native void nAddStyleRun(/* Non Zero */ long nativeBuilderPtr,
+                                                /* Non Zero */ long paintPtr,
+                                                @IntRange(from = 0) int start,
+                                                @IntRange(from = 0) int end,
+                                                boolean isRtl);
+        /**
+         * Apply ReplacementRun to make native measured text.
+         *
+         * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
+         * @param paintPtr The native paint pointer to be applied.
+         * @param start The start offset in the copied buffer.
+         * @param end The end offset in the copied buffer.
+         * @param width The width of the replacement.
+         */
+        private static native void nAddReplacementRun(/* Non Zero */ long nativeBuilderPtr,
+                                                      /* Non Zero */ long paintPtr,
+                                                      @IntRange(from = 0) int start,
+                                                      @IntRange(from = 0) int end,
+                                                      @FloatRange(from = 0) float width);
+
+        private static native long nBuildNativeMeasuredParagraph(
+                /* Non Zero */ long nativeBuilderPtr,
+                @NonNull char[] text,
+                boolean computeHyphenation,
+                boolean computeLayout);
+
+        private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr);
+    }
+}
diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java
index 369f357..b7ea012 100644
--- a/core/java/android/text/PrecomputedText.java
+++ b/core/java/android/text/PrecomputedText.java
@@ -437,7 +437,6 @@
     public boolean canUseMeasuredResult(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
             @NonNull TextDirectionHeuristic textDir, @NonNull TextPaint paint,
             @Layout.BreakStrategy int strategy, @Layout.HyphenationFrequency int frequency) {
-        final TextPaint mtPaint = mParams.getTextPaint();
         return mStart == start
             && mEnd == end
             && mParams.isSameTextMetricsInternal(paint, textDir, strategy, frequency);
@@ -519,6 +518,21 @@
     }
 
     /**
+     * Returns a width of a character at offset
+     *
+     * @param offset an offset of the text.
+     * @return a width of the character.
+     * @hide
+     */
+    public float getCharWidthAt(@IntRange(from = 0) int offset) {
+        Preconditions.checkArgument(0 <= offset && offset < mText.length(), "invalid offset");
+        final int paraIndex = findParaIndex(offset);
+        final int paraStart = getParagraphStart(paraIndex);
+        final int paraEnd = getParagraphEnd(paraIndex);
+        return getMeasuredParagraph(paraIndex).getCharWidthAt(offset - paraStart);
+    }
+
+    /**
      * Returns the size of native PrecomputedText memory usage.
      *
      * Note that this is not guaranteed to be accurate. Must be used only for testing purposes.
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 5256e47..68199a4 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -17,6 +17,7 @@
 package android.text;
 
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 
 import java.text.BreakIterator;
 
@@ -448,6 +449,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static boolean moveToPreceding(
             Spannable text, PositionIterator iter, boolean extendSelection) {
         final int offset = iter.preceding(getSelectionEnd(text));
@@ -462,6 +464,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static boolean moveToFollowing(
             Spannable text, PositionIterator iter, boolean extendSelection) {
         final int offset = iter.following(getSelectionEnd(text));
diff --git a/core/java/android/text/SpanSet.java b/core/java/android/text/SpanSet.java
index 00f1493..362825a 100644
--- a/core/java/android/text/SpanSet.java
+++ b/core/java/android/text/SpanSet.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.annotation.UnsupportedAppUsage;
 import java.lang.reflect.Array;
 import java.util.Arrays;
 
@@ -32,6 +33,7 @@
     private final Class<? extends E> classType;
 
     int numberOfSpans;
+    @UnsupportedAppUsage
     E[] spans;
     int[] spanStarts;
     int[] spanEnds;
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 41a9c45..9d841e8 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -17,6 +17,7 @@
 package android.text;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.BaseCanvas;
 import android.graphics.Paint;
 import android.util.Log;
@@ -595,6 +596,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     private void sendToSpanWatchers(int replaceStart, int replaceEnd, int nbNewChars) {
         for (int i = 0; i < mSpanCount; i++) {
             int spanFlags = mSpanFlags[i];
@@ -861,6 +863,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public <T> T[] getSpans(int queryStart, int queryEnd, @Nullable Class<T> kind,
             boolean sortByInsertionOrder) {
         if (kind == null) return (T[]) ArrayUtils.emptyArray(Object.class);
@@ -1230,6 +1233,7 @@
      * [start, end[ range.
      * @hide
      */
+    @UnsupportedAppUsage
     public String substring(int start, int end) {
         char[] buf = new char[end - start];
         getChars(start, end, buf, 0);
@@ -1765,18 +1769,26 @@
 
     private InputFilter[] mFilters = NO_FILTERS;
 
+    @UnsupportedAppUsage
     private char[] mText;
+    @UnsupportedAppUsage
     private int mGapStart;
+    @UnsupportedAppUsage
     private int mGapLength;
 
+    @UnsupportedAppUsage
     private Object[] mSpans;
+    @UnsupportedAppUsage
     private int[] mSpanStarts;
+    @UnsupportedAppUsage
     private int[] mSpanEnds;
     private int[] mSpanMax;  // see calcMax() for an explanation of what this array stores
+    @UnsupportedAppUsage
     private int[] mSpanFlags;
     private int[] mSpanOrder;  // store the order of span insertion
     private int mSpanInsertCount;  // counter for the span insertion
 
+    @UnsupportedAppUsage
     private int mSpanCount;
     private IdentityHashMap<Object, Integer> mIndexOfSpan;
     private int mLowWaterMark;  // indices below this have not been touched
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index bcc2fda..7acd539 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -21,6 +21,7 @@
 
 import libcore.util.EmptyArray;
 
+import android.annotation.UnsupportedAppUsage;
 import java.lang.reflect.Array;
 
 /* package */ abstract class SpannableStringInternal
@@ -50,6 +51,7 @@
      *
      * Due to backward compatibility reasons, we copy even NoCopySpan by default
      */
+    @UnsupportedAppUsage
     /* package */ SpannableStringInternal(CharSequence source, int start, int end) {
         this(source, start, end, false /* ignoreNoCopySpan */);
     }
@@ -148,6 +150,7 @@
      *
      * @return True if excluded, false if included.
      */
+    @UnsupportedAppUsage
     private final boolean isOutOfCopyRange(int start, int end, int spanStart, int spanEnd) {
         if (spanStart > end || spanEnd < start) return true;
         if (spanStart != spanEnd && start != end) {
@@ -174,14 +177,17 @@
         mText.getChars(start, end, dest, off);
     }
 
+    @UnsupportedAppUsage
     /* package */ void setSpan(Object what, int start, int end, int flags) {
         setSpan(what, start, end, flags, true/*enforceParagraph*/);
     }
 
+    @UnsupportedAppUsage
     private boolean isIndexFollowsNextLine(int index) {
         return index != 0 && index != length() && charAt(index - 1) != '\n';
     }
 
+    @UnsupportedAppUsage
     private void setSpan(Object what, int start, int end, int flags, boolean enforceParagraph) {
         int nstart = start;
         int nend = end;
@@ -248,6 +254,7 @@
             sendSpanAdded(what, nstart, nend);
     }
 
+    @UnsupportedAppUsage
     /* package */ void removeSpan(Object what) {
         removeSpan(what, 0 /* flags */);
     }
@@ -281,6 +288,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public int getSpanStart(Object what) {
         int count = mSpanCount;
         Object[] spans = mSpans;
@@ -295,6 +303,7 @@
         return -1;
     }
 
+    @UnsupportedAppUsage
     public int getSpanEnd(Object what) {
         int count = mSpanCount;
         Object[] spans = mSpans;
@@ -309,6 +318,7 @@
         return -1;
     }
 
+    @UnsupportedAppUsage
     public int getSpanFlags(Object what) {
         int count = mSpanCount;
         Object[] spans = mSpans;
@@ -323,6 +333,7 @@
         return 0; 
     }
 
+    @UnsupportedAppUsage
     public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) {
         int count = 0;
 
@@ -404,6 +415,7 @@
         return (T[]) nret;
     }
 
+    @UnsupportedAppUsage
     public int nextSpanTransition(int start, int limit, Class kind) {
         int count = mSpanCount;
         Object[] spans = mSpans;
@@ -426,6 +438,7 @@
         return limit;
     }
 
+    @UnsupportedAppUsage
     private void sendSpanAdded(Object what, int start, int end) {
         SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
         int n = recip.length;
@@ -435,6 +448,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void sendSpanRemoved(Object what, int start, int end) {
         SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
         int n = recip.length;
@@ -444,6 +458,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void sendSpanChanged(Object what, int s, int e, int st, int en) {
         SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en),
                                        SpanWatcher.class);
@@ -454,10 +469,12 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static String region(int start, int end) {
         return "(" + start + " ... " + end + ")";
     }
 
+    @UnsupportedAppUsage
     private void checkRange(final String operation, int start, int end) {
         if (end < start) {
             throw new IndexOutOfBoundsException(operation + " " +
@@ -534,25 +551,36 @@
      *
      * Due to backward compatibility reasons, we copy even NoCopySpan by default
      */
+    @UnsupportedAppUsage
     private void copySpans(Spanned src, int start, int end) {
         copySpans(src, start, end, false);
     }
 
+    @UnsupportedAppUsage
     private void copySpans(SpannableStringInternal src, int start, int end) {
         copySpans(src, start, end, false);
     }
 
 
 
+    @UnsupportedAppUsage
     private String mText;
+    @UnsupportedAppUsage
     private Object[] mSpans;
+    @UnsupportedAppUsage
     private int[] mSpanData;
+    @UnsupportedAppUsage
     private int mSpanCount;
 
+    @UnsupportedAppUsage
     /* package */ static final Object[] EMPTY = new Object[0];
 
+    @UnsupportedAppUsage
     private static final int START = 0;
+    @UnsupportedAppUsage
     private static final int END = 1;
+    @UnsupportedAppUsage
     private static final int FLAGS = 2;
+    @UnsupportedAppUsage
     private static final int COLUMNS = 3;
 }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 4b78aa2..128f860 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -20,8 +20,8 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
-import android.text.AutoGrowArray.FloatArray;
 import android.text.style.LeadingMarginSpan;
 import android.text.style.LeadingMarginSpan.LeadingMarginSpan2;
 import android.text.style.LineHeightSpan;
@@ -32,9 +32,6 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
-import dalvik.annotation.optimization.CriticalNative;
-import dalvik.annotation.optimization.FastNative;
-
 import java.util.Arrays;
 
 /**
@@ -57,7 +54,7 @@
      *
      *   - Create MeasuredParagraph by MeasuredParagraph.buildForStaticLayout which measures in
      *     native.
-     *   - Run nComputeLineBreaks() to obtain line breaks for the paragraph.
+     *   - Run NativeLineBreaker.computeLineBreaks() to obtain line breaks for the paragraph.
      *
      * After all paragraphs, call finish() to release expensive buffers.
      */
@@ -317,10 +314,17 @@
         /**
          * Set break strategy, useful for selecting high quality or balanced paragraph
          * layout options. The default is {@link Layout#BREAK_STRATEGY_SIMPLE}.
+         * <p/>
+         * Enabling hyphenation with either using {@link Layout#HYPHENATION_FREQUENCY_NORMAL} or
+         * {@link Layout#HYPHENATION_FREQUENCY_FULL} while line breaking is set to one of
+         * {@link Layout#BREAK_STRATEGY_BALANCED}, {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}
+         * improves the structure of text layout however has performance impact and requires more
+         * time to do the text layout.
          *
          * @param breakStrategy break strategy for paragraph layout
          * @return this builder, useful for chaining
          * @see android.widget.TextView#setBreakStrategy
+         * @see #setHyphenationFrequency(int)
          */
         @NonNull
         public Builder setBreakStrategy(@BreakStrategy int breakStrategy) {
@@ -333,10 +337,17 @@
          * possible values are defined in {@link Layout}, by constants named with the pattern
          * {@code HYPHENATION_FREQUENCY_*}. The default is
          * {@link Layout#HYPHENATION_FREQUENCY_NONE}.
+         * <p/>
+         * Enabling hyphenation with either using {@link Layout#HYPHENATION_FREQUENCY_NORMAL} or
+         * {@link Layout#HYPHENATION_FREQUENCY_FULL} while line breaking is set to one of
+         * {@link Layout#BREAK_STRATEGY_BALANCED}, {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}
+         * improves the structure of text layout however has performance impact and requires more
+         * time to do the text layout.
          *
          * @param hyphenationFrequency hyphenation frequency for the paragraph
          * @return this builder, useful for chaining
          * @see android.widget.TextView#setHyphenationFrequency
+         * @see #setBreakStrategy(int)
          */
         @NonNull
         public Builder setHyphenationFrequency(@HyphenationFrequency int hyphenationFrequency) {
@@ -472,6 +483,7 @@
      * @deprecated Use {@link Builder} instead.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public StaticLayout(CharSequence source, int bufstart, int bufend,
                         TextPaint paint, int outerwidth,
                         Alignment align, TextDirectionHeuristic textDir,
@@ -586,8 +598,7 @@
         float ellipsizedWidth = b.mEllipsizedWidth;
         TextUtils.TruncateAt ellipsize = b.mEllipsize;
         final boolean addLastLineSpacing = b.mAddLastLineLineSpacing;
-        LineBreaks lineBreaks = new LineBreaks();  // TODO: move to builder to avoid allocation costs
-        FloatArray widths = new FloatArray();
+        NativeLineBreaker.LineBreaks lineBreaks = new NativeLineBreaker.LineBreaks();
 
         mLineCount = 0;
         mEllipsized = false;
@@ -615,11 +626,16 @@
             indents = null;
         }
 
-        final long nativePtr = nInit(
-                b.mBreakStrategy, b.mHyphenationFrequency,
+        final NativeLineBreaker lineBreaker = new NativeLineBreaker.Builder()
+                .setBreakStrategy(b.mBreakStrategy)
+                .setHyphenationFrequency(b.mHyphenationFrequency)
                 // TODO: Support more justification mode, e.g. letter spacing, stretching.
-                b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE,
-                indents);
+                .setJustified(b.mJustificationMode)
+                .setIndents(indents)
+                .build();
+
+        NativeLineBreaker.ParagraphConstraints constraints =
+                new NativeLineBreaker.ParagraphConstraints();
 
         PrecomputedText.ParagraphInfo[] paragraphInfo = null;
         final Spanned spanned = (source instanceof Spanned) ? (Spanned) source : null;
@@ -639,243 +655,215 @@
                     bufEnd, false /* computeLayout */);
         }
 
-        try {
-            for (int paraIndex = 0; paraIndex < paragraphInfo.length; paraIndex++) {
-                final int paraStart = paraIndex == 0
-                        ? bufStart : paragraphInfo[paraIndex - 1].paragraphEnd;
-                final int paraEnd = paragraphInfo[paraIndex].paragraphEnd;
+        for (int paraIndex = 0; paraIndex < paragraphInfo.length; paraIndex++) {
+            final int paraStart = paraIndex == 0
+                    ? bufStart : paragraphInfo[paraIndex - 1].paragraphEnd;
+            final int paraEnd = paragraphInfo[paraIndex].paragraphEnd;
 
-                int firstWidthLineCount = 1;
-                int firstWidth = outerWidth;
-                int restWidth = outerWidth;
+            int firstWidthLineCount = 1;
+            int firstWidth = outerWidth;
+            int restWidth = outerWidth;
 
-                LineHeightSpan[] chooseHt = null;
+            LineHeightSpan[] chooseHt = null;
+            if (spanned != null) {
+                LeadingMarginSpan[] sp = getParagraphSpans(spanned, paraStart, paraEnd,
+                        LeadingMarginSpan.class);
+                for (int i = 0; i < sp.length; i++) {
+                    LeadingMarginSpan lms = sp[i];
+                    firstWidth -= sp[i].getLeadingMargin(true);
+                    restWidth -= sp[i].getLeadingMargin(false);
 
-                if (spanned != null) {
-                    LeadingMarginSpan[] sp = getParagraphSpans(spanned, paraStart, paraEnd,
-                            LeadingMarginSpan.class);
-                    for (int i = 0; i < sp.length; i++) {
-                        LeadingMarginSpan lms = sp[i];
-                        firstWidth -= sp[i].getLeadingMargin(true);
-                        restWidth -= sp[i].getLeadingMargin(false);
+                    // LeadingMarginSpan2 is odd.  The count affects all
+                    // leading margin spans, not just this particular one
+                    if (lms instanceof LeadingMarginSpan2) {
+                        LeadingMarginSpan2 lms2 = (LeadingMarginSpan2) lms;
+                        firstWidthLineCount = Math.max(firstWidthLineCount,
+                                lms2.getLeadingMarginLineCount());
+                    }
+                }
 
-                        // LeadingMarginSpan2 is odd.  The count affects all
-                        // leading margin spans, not just this particular one
-                        if (lms instanceof LeadingMarginSpan2) {
-                            LeadingMarginSpan2 lms2 = (LeadingMarginSpan2) lms;
-                            firstWidthLineCount = Math.max(firstWidthLineCount,
-                                    lms2.getLeadingMarginLineCount());
-                        }
+                chooseHt = getParagraphSpans(spanned, paraStart, paraEnd, LineHeightSpan.class);
+
+                if (chooseHt.length == 0) {
+                    chooseHt = null; // So that out() would not assume it has any contents
+                } else {
+                    if (chooseHtv == null || chooseHtv.length < chooseHt.length) {
+                        chooseHtv = ArrayUtils.newUnpaddedIntArray(chooseHt.length);
                     }
 
-                    chooseHt = getParagraphSpans(spanned, paraStart, paraEnd, LineHeightSpan.class);
+                    for (int i = 0; i < chooseHt.length; i++) {
+                        int o = spanned.getSpanStart(chooseHt[i]);
 
-                    if (chooseHt.length == 0) {
-                        chooseHt = null; // So that out() would not assume it has any contents
+                        if (o < paraStart) {
+                            // starts in this layout, before the
+                            // current paragraph
+
+                            chooseHtv[i] = getLineTop(getLineForOffset(o));
+                        } else {
+                            // starts in this paragraph
+
+                            chooseHtv[i] = v;
+                        }
+                    }
+                }
+            }
+            // tab stop locations
+            int[] variableTabStops = null;
+            if (spanned != null) {
+                TabStopSpan[] spans = getParagraphSpans(spanned, paraStart,
+                        paraEnd, TabStopSpan.class);
+                if (spans.length > 0) {
+                    int[] stops = new int[spans.length];
+                    for (int i = 0; i < spans.length; i++) {
+                        stops[i] = spans[i].getTabStop();
+                    }
+                    Arrays.sort(stops, 0, stops.length);
+                    variableTabStops = stops;
+                }
+            }
+
+            final MeasuredParagraph measuredPara = paragraphInfo[paraIndex].measured;
+            final char[] chs = measuredPara.getChars();
+            final int[] spanEndCache = measuredPara.getSpanEndCache().getRawArray();
+            final int[] fmCache = measuredPara.getFontMetrics().getRawArray();
+
+            constraints.setWidth(restWidth);
+            constraints.setIndent(firstWidth, firstWidthLineCount);
+            constraints.setTabStops(variableTabStops, TAB_INCREMENT);
+
+            lineBreaker.computeLineBreaks(measuredPara.getNativeMeasuredParagraph(),
+                    constraints, mLineCount, lineBreaks);
+            int breakCount = lineBreaks.breakCount;
+            final int[] breaks = lineBreaks.breaks;
+            final float[] lineWidths = lineBreaks.widths;
+            final float[] ascents = lineBreaks.ascents;
+            final float[] descents = lineBreaks.descents;
+            final int[] flags = lineBreaks.flags;
+
+            final int remainingLineCount = mMaximumVisibleLineCount - mLineCount;
+            final boolean ellipsisMayBeApplied = ellipsize != null
+                    && (ellipsize == TextUtils.TruncateAt.END
+                        || (mMaximumVisibleLineCount == 1
+                                && ellipsize != TextUtils.TruncateAt.MARQUEE));
+            if (0 < remainingLineCount && remainingLineCount < breakCount
+                    && ellipsisMayBeApplied) {
+                // Calculate width
+                float width = 0;
+                int flag = 0;  // XXX May need to also have starting hyphen edit
+                for (int i = remainingLineCount - 1; i < breakCount; i++) {
+                    if (i == breakCount - 1) {
+                        width += lineWidths[i];
                     } else {
-                        if (chooseHtv == null || chooseHtv.length < chooseHt.length) {
-                            chooseHtv = ArrayUtils.newUnpaddedIntArray(chooseHt.length);
-                        }
-
-                        for (int i = 0; i < chooseHt.length; i++) {
-                            int o = spanned.getSpanStart(chooseHt[i]);
-
-                            if (o < paraStart) {
-                                // starts in this layout, before the
-                                // current paragraph
-
-                                chooseHtv[i] = getLineTop(getLineForOffset(o));
-                            } else {
-                                // starts in this paragraph
-
-                                chooseHtv[i] = v;
-                            }
+                        for (int j = (i == 0 ? 0 : breaks[i - 1]); j < breaks[i]; j++) {
+                            width += measuredPara.getCharWidthAt(j - paraStart);
                         }
                     }
+                    flag |= flags[i] & TAB_MASK;
+                }
+                // Treat the last line and overflowed lines as a single line.
+                breaks[remainingLineCount - 1] = breaks[breakCount - 1];
+                lineWidths[remainingLineCount - 1] = width;
+                flags[remainingLineCount - 1] = flag;
+
+                breakCount = remainingLineCount;
+            }
+
+            // here is the offset of the starting character of the line we are currently
+            // measuring
+            int here = paraStart;
+
+            int fmTop = 0, fmBottom = 0, fmAscent = 0, fmDescent = 0;
+            int fmCacheIndex = 0;
+            int spanEndCacheIndex = 0;
+            int breakIndex = 0;
+            for (int spanStart = paraStart, spanEnd; spanStart < paraEnd; spanStart = spanEnd) {
+                // retrieve end of span
+                spanEnd = spanEndCache[spanEndCacheIndex++];
+
+                // retrieve cached metrics, order matches above
+                fm.top = fmCache[fmCacheIndex * 4 + 0];
+                fm.bottom = fmCache[fmCacheIndex * 4 + 1];
+                fm.ascent = fmCache[fmCacheIndex * 4 + 2];
+                fm.descent = fmCache[fmCacheIndex * 4 + 3];
+                fmCacheIndex++;
+
+                if (fm.top < fmTop) {
+                    fmTop = fm.top;
+                }
+                if (fm.ascent < fmAscent) {
+                    fmAscent = fm.ascent;
+                }
+                if (fm.descent > fmDescent) {
+                    fmDescent = fm.descent;
+                }
+                if (fm.bottom > fmBottom) {
+                    fmBottom = fm.bottom;
                 }
 
-                // tab stop locations
-                int[] variableTabStops = null;
-                if (spanned != null) {
-                    TabStopSpan[] spans = getParagraphSpans(spanned, paraStart,
-                            paraEnd, TabStopSpan.class);
-                    if (spans.length > 0) {
-                        int[] stops = new int[spans.length];
-                        for (int i = 0; i < spans.length; i++) {
-                            stops[i] = spans[i].getTabStop();
-                        }
-                        Arrays.sort(stops, 0, stops.length);
-                        variableTabStops = stops;
-                    }
+                // skip breaks ending before current span range
+                while (breakIndex < breakCount && paraStart + breaks[breakIndex] < spanStart) {
+                    breakIndex++;
                 }
 
-                final MeasuredParagraph measuredPara = paragraphInfo[paraIndex].measured;
-                final char[] chs = measuredPara.getChars();
-                final int[] spanEndCache = measuredPara.getSpanEndCache().getRawArray();
-                final int[] fmCache = measuredPara.getFontMetrics().getRawArray();
-                // TODO: Stop keeping duplicated width copy in native and Java.
-                widths.resize(chs.length);
+                while (breakIndex < breakCount && paraStart + breaks[breakIndex] <= spanEnd) {
+                    int endPos = paraStart + breaks[breakIndex];
 
-                // measurement has to be done before performing line breaking
-                // but we don't want to recompute fontmetrics or span ranges the
-                // second time, so we cache those and then use those stored values
+                    boolean moreChars = (endPos < bufEnd);
 
-                int breakCount = nComputeLineBreaks(
-                        nativePtr,
+                    final int ascent = fallbackLineSpacing
+                            ? Math.min(fmAscent, Math.round(ascents[breakIndex]))
+                            : fmAscent;
+                    final int descent = fallbackLineSpacing
+                            ? Math.max(fmDescent, Math.round(descents[breakIndex]))
+                            : fmDescent;
 
-                        // Inputs
-                        chs,
-                        measuredPara.getNativePtr(),
-                        paraEnd - paraStart,
-                        firstWidth,
-                        firstWidthLineCount,
-                        restWidth,
-                        variableTabStops,
-                        TAB_INCREMENT,
-                        mLineCount,
+                    v = out(source, here, endPos,
+                            ascent, descent, fmTop, fmBottom,
+                            v, spacingmult, spacingadd, chooseHt, chooseHtv, fm,
+                            flags[breakIndex], needMultiply, measuredPara, bufEnd,
+                            includepad, trackpad, addLastLineSpacing, chs,
+                            paraStart, ellipsize, ellipsizedWidth, lineWidths[breakIndex],
+                            paint, moreChars);
 
-                        // Outputs
-                        lineBreaks,
-                        lineBreaks.breaks.length,
-                        lineBreaks.breaks,
-                        lineBreaks.widths,
-                        lineBreaks.ascents,
-                        lineBreaks.descents,
-                        lineBreaks.flags,
-                        widths.getRawArray());
-
-                final int[] breaks = lineBreaks.breaks;
-                final float[] lineWidths = lineBreaks.widths;
-                final float[] ascents = lineBreaks.ascents;
-                final float[] descents = lineBreaks.descents;
-                final int[] flags = lineBreaks.flags;
-
-                final int remainingLineCount = mMaximumVisibleLineCount - mLineCount;
-                final boolean ellipsisMayBeApplied = ellipsize != null
-                        && (ellipsize == TextUtils.TruncateAt.END
-                            || (mMaximumVisibleLineCount == 1
-                                    && ellipsize != TextUtils.TruncateAt.MARQUEE));
-                if (0 < remainingLineCount && remainingLineCount < breakCount
-                        && ellipsisMayBeApplied) {
-                    // Calculate width and flag.
-                    float width = 0;
-                    int flag = 0; // XXX May need to also have starting hyphen edit
-                    for (int i = remainingLineCount - 1; i < breakCount; i++) {
-                        if (i == breakCount - 1) {
-                            width += lineWidths[i];
-                        } else {
-                            for (int j = (i == 0 ? 0 : breaks[i - 1]); j < breaks[i]; j++) {
-                                width += widths.get(j);
-                            }
-                        }
-                        flag |= flags[i] & TAB_MASK;
-                    }
-                    // Treat the last line and overflowed lines as a single line.
-                    breaks[remainingLineCount - 1] = breaks[breakCount - 1];
-                    lineWidths[remainingLineCount - 1] = width;
-                    flags[remainingLineCount - 1] = flag;
-
-                    breakCount = remainingLineCount;
-                }
-
-                // here is the offset of the starting character of the line we are currently
-                // measuring
-                int here = paraStart;
-
-                int fmTop = 0, fmBottom = 0, fmAscent = 0, fmDescent = 0;
-                int fmCacheIndex = 0;
-                int spanEndCacheIndex = 0;
-                int breakIndex = 0;
-                for (int spanStart = paraStart, spanEnd; spanStart < paraEnd; spanStart = spanEnd) {
-                    // retrieve end of span
-                    spanEnd = spanEndCache[spanEndCacheIndex++];
-
-                    // retrieve cached metrics, order matches above
-                    fm.top = fmCache[fmCacheIndex * 4 + 0];
-                    fm.bottom = fmCache[fmCacheIndex * 4 + 1];
-                    fm.ascent = fmCache[fmCacheIndex * 4 + 2];
-                    fm.descent = fmCache[fmCacheIndex * 4 + 3];
-                    fmCacheIndex++;
-
-                    if (fm.top < fmTop) {
+                    if (endPos < spanEnd) {
+                        // preserve metrics for current span
                         fmTop = fm.top;
-                    }
-                    if (fm.ascent < fmAscent) {
-                        fmAscent = fm.ascent;
-                    }
-                    if (fm.descent > fmDescent) {
-                        fmDescent = fm.descent;
-                    }
-                    if (fm.bottom > fmBottom) {
                         fmBottom = fm.bottom;
+                        fmAscent = fm.ascent;
+                        fmDescent = fm.descent;
+                    } else {
+                        fmTop = fmBottom = fmAscent = fmDescent = 0;
                     }
 
-                    // skip breaks ending before current span range
-                    while (breakIndex < breakCount && paraStart + breaks[breakIndex] < spanStart) {
-                        breakIndex++;
+                    here = endPos;
+                    breakIndex++;
+
+                    if (mLineCount >= mMaximumVisibleLineCount && mEllipsized) {
+                        return;
                     }
-
-                    while (breakIndex < breakCount && paraStart + breaks[breakIndex] <= spanEnd) {
-                        int endPos = paraStart + breaks[breakIndex];
-
-                        boolean moreChars = (endPos < bufEnd);
-
-                        final int ascent = fallbackLineSpacing
-                                ? Math.min(fmAscent, Math.round(ascents[breakIndex]))
-                                : fmAscent;
-                        final int descent = fallbackLineSpacing
-                                ? Math.max(fmDescent, Math.round(descents[breakIndex]))
-                                : fmDescent;
-                        v = out(source, here, endPos,
-                                ascent, descent, fmTop, fmBottom,
-                                v, spacingmult, spacingadd, chooseHt, chooseHtv, fm,
-                                flags[breakIndex], needMultiply, measuredPara, bufEnd,
-                                includepad, trackpad, addLastLineSpacing, chs, widths.getRawArray(),
-                                paraStart, ellipsize, ellipsizedWidth, lineWidths[breakIndex],
-                                paint, moreChars);
-
-                        if (endPos < spanEnd) {
-                            // preserve metrics for current span
-                            fmTop = fm.top;
-                            fmBottom = fm.bottom;
-                            fmAscent = fm.ascent;
-                            fmDescent = fm.descent;
-                        } else {
-                            fmTop = fmBottom = fmAscent = fmDescent = 0;
-                        }
-
-                        here = endPos;
-                        breakIndex++;
-
-                        if (mLineCount >= mMaximumVisibleLineCount && mEllipsized) {
-                            return;
-                        }
-                    }
-                }
-
-                if (paraEnd == bufEnd) {
-                    break;
                 }
             }
 
-            if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE)
-                    && mLineCount < mMaximumVisibleLineCount) {
-                final MeasuredParagraph measuredPara =
-                        MeasuredParagraph.buildForBidi(source, bufEnd, bufEnd, textDir, null);
-                paint.getFontMetricsInt(fm);
-                v = out(source,
-                        bufEnd, bufEnd, fm.ascent, fm.descent,
-                        fm.top, fm.bottom,
-                        v,
-                        spacingmult, spacingadd, null,
-                        null, fm, 0,
-                        needMultiply, measuredPara, bufEnd,
-                        includepad, trackpad, addLastLineSpacing, null,
-                        null, bufStart, ellipsize,
-                        ellipsizedWidth, 0, paint, false);
+            if (paraEnd == bufEnd) {
+                break;
             }
-        } finally {
-            nFinish(nativePtr);
+        }
+
+        if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE)
+                && mLineCount < mMaximumVisibleLineCount) {
+            final MeasuredParagraph measuredPara =
+                    MeasuredParagraph.buildForBidi(source, bufEnd, bufEnd, textDir, null);
+            paint.getFontMetricsInt(fm);
+            v = out(source,
+                    bufEnd, bufEnd, fm.ascent, fm.descent,
+                    fm.top, fm.bottom,
+                    v,
+                    spacingmult, spacingadd, null,
+                    null, fm, 0,
+                    needMultiply, measuredPara, bufEnd,
+                    includepad, trackpad, addLastLineSpacing, null,
+                    bufStart, ellipsize,
+                    ellipsizedWidth, 0, paint, false);
         }
     }
 
@@ -884,7 +872,7 @@
             final LineHeightSpan[] chooseHt, final int[] chooseHtv, final Paint.FontMetricsInt fm,
             final int flags, final boolean needMultiply, @NonNull final MeasuredParagraph measured,
             final int bufEnd, final boolean includePad, final boolean trackPad,
-            final boolean addLastLineLineSpacing, final char[] chs, final float[] widths,
+            final boolean addLastLineLineSpacing, final char[] chs,
             final int widthStart, final TextUtils.TruncateAt ellipsize, final float ellipsisWidth,
             final float textWidth, final TextPaint paint, final boolean moreChars) {
         final int j = mLineCount;
@@ -942,7 +930,7 @@
                     (!firstLine && (currentLineIsTheLastVisibleOne || !moreChars) &&
                             ellipsize == TextUtils.TruncateAt.END);
             if (doEllipsis) {
-                calculateEllipsis(start, end, widths, widthStart,
+                calculateEllipsis(start, end, measured, widthStart,
                         ellipsisWidth, ellipsize, j,
                         textWidth, paint, forceEllipsis);
             }
@@ -1026,7 +1014,7 @@
     }
 
     private void calculateEllipsis(int lineStart, int lineEnd,
-                                   float[] widths, int widthStart,
+                                   MeasuredParagraph measured, int widthStart,
                                    float avail, TextUtils.TruncateAt where,
                                    int line, float textWidth, TextPaint paint,
                                    boolean forceEllipsis) {
@@ -1050,9 +1038,10 @@
                 int i;
 
                 for (i = len; i > 0; i--) {
-                    float w = widths[i - 1 + lineStart - widthStart];
+                    float w = measured.getCharWidthAt(i - 1 + lineStart - widthStart);
                     if (w + sum + ellipsisWidth > avail) {
-                        while (i < len && widths[i + lineStart - widthStart] == 0.0f) {
+                        while (i < len
+                                && measured.getCharWidthAt(i + lineStart - widthStart) == 0.0f) {
                             i++;
                         }
                         break;
@@ -1074,7 +1063,7 @@
             int i;
 
             for (i = 0; i < len; i++) {
-                float w = widths[i + lineStart - widthStart];
+                float w = measured.getCharWidthAt(i + lineStart - widthStart);
 
                 if (w + sum + ellipsisWidth > avail) {
                     break;
@@ -1097,10 +1086,12 @@
 
                 float ravail = (avail - ellipsisWidth) / 2;
                 for (right = len; right > 0; right--) {
-                    float w = widths[right - 1 + lineStart - widthStart];
+                    float w = measured.getCharWidthAt(right - 1 + lineStart - widthStart);
 
                     if (w + rsum > ravail) {
-                        while (right < len && widths[right + lineStart - widthStart] == 0.0f) {
+                        while (right < len
+                                && measured.getCharWidthAt(right + lineStart - widthStart)
+                                    == 0.0f) {
                             right++;
                         }
                         break;
@@ -1110,7 +1101,7 @@
 
                 float lavail = avail - ellipsisWidth - rsum;
                 for (left = 0; left < right; left++) {
-                    float w = widths[left + lineStart - widthStart];
+                    float w = measured.getCharWidthAt(left + lineStart - widthStart);
 
                     if (w + lsum > lavail) {
                         break;
@@ -1294,6 +1285,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getHeight(boolean cap) {
         if (cap && mLineCount > mMaximumVisibleLineCount && mMaxLineHeight == -1
                 && Log.isLoggable(TAG, Log.WARN)) {
@@ -1306,49 +1298,10 @@
                 ? mMaxLineHeight : super.getHeight();
     }
 
-    @FastNative
-    private static native long nInit(
-            @BreakStrategy int breakStrategy,
-            @HyphenationFrequency int hyphenationFrequency,
-            boolean isJustified,
-            @Nullable int[] indents);
-
-    @CriticalNative
-    private static native void nFinish(long nativePtr);
-
-    // populates LineBreaks and returns the number of breaks found
-    //
-    // the arrays inside the LineBreaks objects are passed in as well
-    // to reduce the number of JNI calls in the common case where the
-    // arrays do not have to be resized
-    // The individual character widths will be returned in charWidths. The length of charWidths must
-    // be at least the length of the text.
-    private static native int nComputeLineBreaks(
-            /* non zero */ long nativePtr,
-
-            // Inputs
-            @NonNull char[] text,
-            /* Non Zero */ long measuredTextPtr,
-            @IntRange(from = 0) int length,
-            @FloatRange(from = 0.0f) float firstWidth,
-            @IntRange(from = 0) int firstWidthLineCount,
-            @FloatRange(from = 0.0f) float restWidth,
-            @Nullable int[] variableTabStops,
-            int defaultTabStop,
-            @IntRange(from = 0) int indentsOffset,
-
-            // Outputs
-            @NonNull LineBreaks recycle,
-            @IntRange(from  = 0) int recycleLength,
-            @NonNull int[] recycleBreaks,
-            @NonNull float[] recycleWidths,
-            @NonNull float[] recycleAscents,
-            @NonNull float[] recycleDescents,
-            @NonNull int[] recycleFlags,
-            @NonNull float[] charWidths);
-
+    @UnsupportedAppUsage
     private int mLineCount;
     private int mTopPadding, mBottomPadding;
+    @UnsupportedAppUsage
     private int mColumns;
     private int mEllipsizedWidth;
 
@@ -1376,11 +1329,15 @@
     private static final int DESCENT = 2;
     private static final int EXTRA = 3;
     private static final int HYPHEN = 4;
+    @UnsupportedAppUsage
     private static final int ELLIPSIS_START = 5;
     private static final int ELLIPSIS_COUNT = 6;
 
+    @UnsupportedAppUsage
     private int[] mLines;
+    @UnsupportedAppUsage
     private Directions[] mLineDirections;
+    @UnsupportedAppUsage
     private int mMaximumVisibleLineCount = Integer.MAX_VALUE;
 
     private static final int START_MASK = 0x1FFFFFFF;
@@ -1396,14 +1353,18 @@
 
     private static final int DEFAULT_MAX_LINE_HEIGHT = -1;
 
-    // This is used to return three arrays from a single JNI call when
-    // performing line breaking
+    // Unused, here because of gray list private API accesses.
     /*package*/ static class LineBreaks {
         private static final int INITIAL_SIZE = 16;
+        @UnsupportedAppUsage
         public int[] breaks = new int[INITIAL_SIZE];
+        @UnsupportedAppUsage
         public float[] widths = new float[INITIAL_SIZE];
+        @UnsupportedAppUsage
         public float[] ascents = new float[INITIAL_SIZE];
+        @UnsupportedAppUsage
         public float[] descents = new float[INITIAL_SIZE];
+        @UnsupportedAppUsage
         public int[] flags = new int[INITIAL_SIZE]; // hasTab
         // breaks, widths, and flags should all have the same length
     }
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index b1a44ae..9667b106 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Paint.FontMetricsInt;
@@ -50,6 +51,7 @@
     private static final boolean DEBUG = false;
 
     private TextPaint mPaint;
+    @UnsupportedAppUsage
     private CharSequence mText;
     private int mStart;
     private int mLen;
@@ -59,6 +61,7 @@
     private TabStops mTabs;
     private char[] mChars;
     private boolean mCharsValid;
+    @UnsupportedAppUsage
     private Spanned mSpanned;
     private PrecomputedText mComputed;
 
@@ -73,16 +76,20 @@
 
     private final TextPaint mWorkPaint = new TextPaint();
     private final TextPaint mActivePaint = new TextPaint();
+    @UnsupportedAppUsage
     private final SpanSet<MetricAffectingSpan> mMetricAffectingSpanSpanSet =
             new SpanSet<MetricAffectingSpan>(MetricAffectingSpan.class);
+    @UnsupportedAppUsage
     private final SpanSet<CharacterStyle> mCharacterStyleSpanSet =
             new SpanSet<CharacterStyle>(CharacterStyle.class);
+    @UnsupportedAppUsage
     private final SpanSet<ReplacementSpan> mReplacementSpanSpanSet =
             new SpanSet<ReplacementSpan>(ReplacementSpan.class);
 
     private final DecorationInfo mDecorationInfo = new DecorationInfo();
     private final ArrayList<DecorationInfo> mDecorations = new ArrayList<>();
 
+    @UnsupportedAppUsage
     private static final TextLine[] sCached = new TextLine[3];
 
     /**
@@ -91,6 +98,7 @@
      * @return an uninitialized TextLine
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @UnsupportedAppUsage
     public static TextLine obtain() {
         TextLine tl;
         synchronized (sCached) {
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
index 5234fa9..7bcc685 100644
--- a/core/java/android/text/TextPaint.java
+++ b/core/java/android/text/TextPaint.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
 
 /**
@@ -39,11 +40,13 @@
      * @hide
      */
     @ColorInt
+    @UnsupportedAppUsage
     public int underlineColor = 0;
     /**
      * Thickness of the underline, in pixels.
      * @hide
      */
+    @UnsupportedAppUsage
     public float underlineThickness;
 
     public TextPaint() {
@@ -98,6 +101,7 @@
      * @param thickness underline thickness
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUnderlineText(int color, float thickness) {
         underlineColor = color;
         underlineThickness = thickness;
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 6b2f802..e31e928 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.PluralsRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.icu.lang.UCharacter;
@@ -1194,6 +1195,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         END_SMALL
     }
 
@@ -1733,6 +1735,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isPrintableAsciiOnly(final CharSequence str) {
         final int len = str.length();
         for (int i = 0; i < len; i++) {
@@ -1958,6 +1961,7 @@
      * @see #unpackRangeEndFromLong(long)
      * @hide
      */
+    @UnsupportedAppUsage
     public static long packRangeInLong(int start, int end) {
         return (((long) start) << 32) | end;
     }
@@ -1968,6 +1972,7 @@
      * @see #packRangeInLong(int, int)
      * @hide
      */
+    @UnsupportedAppUsage
     public static int unpackRangeStartFromLong(long range) {
         return (int) (range >>> 32);
     }
@@ -1978,6 +1983,7 @@
      * @see #packRangeInLong(int, int)
      * @hide
      */
+    @UnsupportedAppUsage
     public static int unpackRangeEndFromLong(long range) {
         return (int) (range & 0x00000000FFFFFFFFL);
     }
@@ -2091,6 +2097,25 @@
         return (T) text.subSequence(0, size);
     }
 
+    /**
+     * Trims the {@code text} to the first {@code size} characters and adds an ellipsis if the
+     * resulting string is shorter than the input. This will result in an output string which is
+     * longer than {@code size} for most inputs.
+     *
+     * @param size length of the result, should be greater than 0
+     *
+     * @hide
+     */
+    @Nullable
+    public static <T extends CharSequence> T trimToLengthWithEllipsis(@Nullable T text,
+            @IntRange(from = 1) int size) {
+        T trimmed = trimToSize(text, size);
+        if (trimmed.length() < text.length()) {
+            trimmed = (T) (trimmed.toString() + "...");
+        }
+        return trimmed;
+    }
+
     private static Object sLock = new Object();
 
     private static char[] sTemp = null;
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 94025ef..3c8de94 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -17,6 +17,7 @@
 package android.text.format;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -178,6 +179,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean is24HourFormat(Context context, int userHandle) {
         final String value = Settings.System.getStringForUser(context.getContentResolver(),
                 Settings.System.TIME_12_24, userHandle);
@@ -270,6 +272,7 @@
      * @param context the application context
      * @hide
      */
+    @UnsupportedAppUsage
     public static String getTimeFormatString(Context context) {
         return getTimeFormatString(context, context.getUserId());
     }
@@ -281,6 +284,7 @@
      * @param userHandle the user handle of the user to query the format for
      * @hide
      */
+    @UnsupportedAppUsage
     public static String getTimeFormatString(Context context, int userHandle) {
         final LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
         return is24HourFormat(context, userHandle) ? d.timeFormat_Hm : d.timeFormat_hm;
@@ -379,6 +383,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean hasSeconds(CharSequence inFormat) {
         return hasDesignator(inFormat, SECONDS);
     }
@@ -392,6 +397,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean hasDesignator(CharSequence inFormat, char designator) {
         if (inFormat == null) return false;
 
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index e19b2c7..e94b800 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -16,6 +16,7 @@
 
 package android.text.format;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -361,6 +362,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static CharSequence formatDuration(long millis) {
         return formatDuration(millis, LENGTH_LONG);
     }
@@ -376,6 +378,7 @@
      * the briefest form available (e.g. "2h").
      * @hide
      */
+    @UnsupportedAppUsage
     public static CharSequence formatDuration(long millis, int abbrev) {
         final FormatWidth width;
         switch (abbrev) {
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index de86a66..077d12d 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.icu.text.MeasureFormat;
@@ -114,6 +115,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static BytesResult formatBytes(Resources res, long sizeBytes, int flags) {
         final int unit = ((flags & FLAG_IEC_UNITS) != 0) ? 1024 : 1000;
         final boolean isNegative = (sizeBytes < 0);
@@ -216,6 +218,7 @@
      * @return the formatted elapsed time
      * @hide
      */
+    @UnsupportedAppUsage
     public static String formatShortElapsedTime(Context context, long millis) {
         long secondsLong = millis / 1000;
 
@@ -271,6 +274,7 @@
      * @return the formatted elapsed time
      * @hide
      */
+    @UnsupportedAppUsage
     public static String formatShortElapsedTimeRoundingUpToMinutes(Context context, long millis) {
         long minutesRoundedUp = (millis + MILLIS_PER_MINUTE - 1) / MILLIS_PER_MINUTE;
 
diff --git a/core/java/android/text/method/AllCapsTransformationMethod.java b/core/java/android/text/method/AllCapsTransformationMethod.java
index c807e7d..5a7c98d 100644
--- a/core/java/android/text/method/AllCapsTransformationMethod.java
+++ b/core/java/android/text/method/AllCapsTransformationMethod.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.Rect;
 import android.text.Spanned;
@@ -38,6 +39,7 @@
     private boolean mEnabled;
     private Locale mLocale;
 
+    @UnsupportedAppUsage
     public AllCapsTransformationMethod(@NonNull Context context) {
         mLocale = context.getResources().getConfiguration().getLocales().get(0);
     }
diff --git a/core/java/android/text/method/HideReturnsTransformationMethod.java b/core/java/android/text/method/HideReturnsTransformationMethod.java
index c6a90ca..e753754 100644
--- a/core/java/android/text/method/HideReturnsTransformationMethod.java
+++ b/core/java/android/text/method/HideReturnsTransformationMethod.java
@@ -16,6 +16,8 @@
 
 package android.text.method;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * This transformation method causes any carriage return characters (\r)
  * to be hidden by displaying them as zero-width non-breaking space
@@ -48,5 +50,6 @@
         return sInstance;
     }
 
+    @UnsupportedAppUsage
     private static HideReturnsTransformationMethod sInstance;
 }
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index 549f8b3..a0c44a8 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -16,6 +16,7 @@
 
 package android.text.method;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.text.Layout;
 import android.text.NoCopySpan;
@@ -274,6 +275,7 @@
         return sInstance;
     }
 
+    @UnsupportedAppUsage
     private static LinkMovementMethod sInstance;
     private static Object FROM_BELOW = new NoCopySpan.Concrete();
 }
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index c3c7302..ec7ed34b 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -16,6 +16,7 @@
 
 package android.text.method;
 
+import android.annotation.UnsupportedAppUsage;
 import android.text.Editable;
 import android.text.NoCopySpan;
 import android.text.Spannable;
@@ -361,6 +362,7 @@
      * Start selecting text.
      * @hide pending API review
      */
+    @UnsupportedAppUsage
     public static void startSelecting(View view, Spannable content) {
         content.setSpan(SELECTING, 0, 0, PRESSED);
     }
@@ -370,6 +372,7 @@
      * call {@link android.text.Selection#setSelection} too.
      * @hide pending API review
      */
+    @UnsupportedAppUsage
     public static void stopSelecting(View view, Spannable content) {
         content.removeSpan(SELECTING);
     }
diff --git a/core/java/android/text/method/PasswordTransformationMethod.java b/core/java/android/text/method/PasswordTransformationMethod.java
index 4485e38..479fdf4 100644
--- a/core/java/android/text/method/PasswordTransformationMethod.java
+++ b/core/java/android/text/method/PasswordTransformationMethod.java
@@ -16,6 +16,7 @@
 
 package android.text.method;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.SystemClock;
@@ -261,6 +262,8 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static PasswordTransformationMethod sInstance;
+    @UnsupportedAppUsage
     private static char DOT = '\u2022';
 }
diff --git a/core/java/android/text/method/TransformationMethod2.java b/core/java/android/text/method/TransformationMethod2.java
index ef00ecd..0bf401a 100644
--- a/core/java/android/text/method/TransformationMethod2.java
+++ b/core/java/android/text/method/TransformationMethod2.java
@@ -15,6 +15,8 @@
  */
 package android.text.method;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * TransformationMethod2 extends the TransformationMethod interface
  * and adds the ability to relax restrictions of TransformationMethod.
@@ -29,5 +31,6 @@
      * @param allowLengthChanges true to allow the transformation to change the length
      *                           of the input string.
      */
+    @UnsupportedAppUsage
     public void setLengthChangesAllowed(boolean allowLengthChanges);
 }
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index 33e96a8..313567a 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -17,6 +17,7 @@
 package android.text.method;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.icu.lang.UCharacter;
 import android.icu.lang.UProperty;
 import android.icu.text.BreakIterator;
@@ -52,10 +53,12 @@
      * Constructs a new WordIterator for the specified locale.
      * @param locale The locale to be used for analyzing the text.
      */
+    @UnsupportedAppUsage
     public WordIterator(Locale locale) {
         mIterator = BreakIterator.getWordInstance(locale);
     }
 
+    @UnsupportedAppUsage
     public void setCharSequence(@NonNull CharSequence charSequence, int start, int end) {
         if (0 <= start && end <= charSequence.length()) {
             mCharSeq = charSequence;
@@ -68,6 +71,7 @@
     }
 
     /** {@inheritDoc} */
+    @UnsupportedAppUsage
     public int preceding(int offset) {
         checkOffsetIsValid(offset);
         while (true) {
@@ -79,6 +83,7 @@
     }
 
     /** {@inheritDoc} */
+    @UnsupportedAppUsage
     public int following(int offset) {
         checkOffsetIsValid(offset);
         while (true) {
@@ -90,6 +95,7 @@
     }
 
     /** {@inheritDoc} */
+    @UnsupportedAppUsage
     public boolean isBoundary(int offset) {
         checkOffsetIsValid(offset);
         return mIterator.isBoundary(offset);
@@ -102,6 +108,7 @@
      * @param offset the given start position to search from.
      * @return the position of the last boundary preceding the given offset.
      */
+    @UnsupportedAppUsage
     public int nextBoundary(int offset) {
         checkOffsetIsValid(offset);
         return mIterator.following(offset);
@@ -114,6 +121,7 @@
      * @param offset the given start position to search from.
      * @return the position of the last boundary preceding the given offset.
      */
+    @UnsupportedAppUsage
     public int prevBoundary(int offset) {
         checkOffsetIsValid(offset);
         return mIterator.preceding(offset);
@@ -131,6 +139,7 @@
      *
      * @throws IllegalArgumentException is offset is not valid.
      */
+    @UnsupportedAppUsage
     public int getBeginning(int offset) {
         // TODO: Check if usage of this can be updated to getBeginning(offset, true) if
         // so this method can be removed.
@@ -150,6 +159,7 @@
      *
      * @throws IllegalArgumentException is offset is not valid.
      */
+    @UnsupportedAppUsage
     public int getEnd(int offset) {
         // TODO: Check if usage of this can be updated to getEnd(offset, true), if
         // so this method can be removed.
@@ -170,6 +180,7 @@
      *
      * @throws IllegalArgumentException is offset is not valid.
      */
+    @UnsupportedAppUsage
     public int getPrevWordBeginningOnTwoWordsBoundary(int offset) {
         return getBeginning(offset, true);
     }
@@ -188,6 +199,7 @@
      *
      * @throws IllegalArgumentException is offset is not valid.
      */
+    @UnsupportedAppUsage
     public int getNextWordEndOnTwoWordBoundary(int offset) {
         return getEnd(offset, true);
     }
@@ -268,6 +280,7 @@
      *
      * @param offset the offset to search from.
      */
+    @UnsupportedAppUsage
     public int getPunctuationBeginning(int offset) {
         checkOffsetIsValid(offset);
         while (offset != BreakIterator.DONE && !isPunctuationStartBoundary(offset)) {
@@ -284,6 +297,7 @@
      *
      * @param offset the offset to search from.
      */
+    @UnsupportedAppUsage
     public int getPunctuationEnd(int offset) {
         checkOffsetIsValid(offset);
         while (offset != BreakIterator.DONE && !isPunctuationEndBoundary(offset)) {
@@ -300,6 +314,7 @@
      * @param offset the offset to check from.
      * @return Whether the offset is after a punctuation character.
      */
+    @UnsupportedAppUsage
     public boolean isAfterPunctuation(int offset) {
         if (mStart < offset && offset <= mEnd) {
             final int codePoint = Character.codePointBefore(mCharSeq, offset);
@@ -315,6 +330,7 @@
      * @param offset the offset to check from.
      * @return Whether the offset is at a punctuation character.
      */
+    @UnsupportedAppUsage
     public boolean isOnPunctuation(int offset) {
         if (mStart <= offset && offset < mEnd) {
             final int codePoint = Character.codePointAt(mCharSeq, offset);
diff --git a/core/java/android/text/style/BulletSpan.java b/core/java/android/text/style/BulletSpan.java
index 70175c8..679698bb 100644
--- a/core/java/android/text/style/BulletSpan.java
+++ b/core/java/android/text/style/BulletSpan.java
@@ -21,10 +21,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Px;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Path.Direction;
 import android.os.Parcel;
 import android.text.Layout;
 import android.text.ParcelableSpan;
@@ -70,12 +69,14 @@
     private static final int STANDARD_COLOR = 0;
 
     @Px
+    @UnsupportedAppUsage
     private final int mGapWidth;
     @Px
     private final int mBulletRadius;
-    private Path mBulletPath = null;
     @ColorInt
+    @UnsupportedAppUsage
     private final int mColor;
+    @UnsupportedAppUsage
     private final boolean mWantColor;
 
     /**
@@ -224,19 +225,7 @@
             final float yPosition = (top + bottom) / 2f;
             final float xPosition = x + dir * mBulletRadius;
 
-            if (canvas.isHardwareAccelerated()) {
-                if (mBulletPath == null) {
-                    mBulletPath = new Path();
-                    mBulletPath.addCircle(0.0f, 0.0f, mBulletRadius, Direction.CW);
-                }
-
-                canvas.save();
-                canvas.translate(xPosition, yPosition);
-                canvas.drawPath(mBulletPath, paint);
-                canvas.restore();
-            } else {
-                canvas.drawCircle(xPosition, yPosition, mBulletRadius, paint);
-            }
+            canvas.drawCircle(xPosition, yPosition, mBulletRadius, paint);
 
             if (mWantColor) {
                 paint.setColor(oldcolor);
diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java
index 1b16f33..be772af 100644
--- a/core/java/android/text/style/DynamicDrawableSpan.java
+++ b/core/java/android/text/style/DynamicDrawableSpan.java
@@ -19,6 +19,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
@@ -78,6 +79,7 @@
 
     protected final int mVerticalAlignment;
 
+    @UnsupportedAppUsage
     private WeakReference<Drawable> mDrawableRef;
 
     /**
diff --git a/core/java/android/text/style/EasyEditSpan.java b/core/java/android/text/style/EasyEditSpan.java
index 305b3306..bfb2873 100644
--- a/core/java/android/text/style/EasyEditSpan.java
+++ b/core/java/android/text/style/EasyEditSpan.java
@@ -17,6 +17,7 @@
 package android.text.style;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.os.Parcel;
 import android.text.ParcelableSpan;
@@ -115,6 +116,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isDeleteEnabled() {
         return mDeleteEnabled;
     }
@@ -124,6 +126,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDeleteEnabled(boolean value) {
         mDeleteEnabled = value;
     }
@@ -133,6 +136,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PendingIntent getPendingIntent() {
         return mPendingIntent;
     }
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 95f0b43..d4edde9 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -19,6 +19,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -57,6 +58,7 @@
 public class ImageSpan extends DynamicDrawableSpan {
 
     @Nullable
+    @UnsupportedAppUsage
     private Drawable mDrawable;
     @Nullable
     private Uri mContentUri;
diff --git a/core/java/android/text/style/SpellCheckSpan.java b/core/java/android/text/style/SpellCheckSpan.java
index 10275c2..6ffde38 100644
--- a/core/java/android/text/style/SpellCheckSpan.java
+++ b/core/java/android/text/style/SpellCheckSpan.java
@@ -16,6 +16,7 @@
 
 package android.text.style;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.text.ParcelableSpan;
 import android.text.TextUtils;
@@ -31,18 +32,22 @@
 
     private boolean mSpellCheckInProgress;
 
+    @UnsupportedAppUsage
     public SpellCheckSpan() {
         mSpellCheckInProgress = false;
     }
 
+    @UnsupportedAppUsage
     public SpellCheckSpan(Parcel src) {
         mSpellCheckInProgress = (src.readInt() != 0);
     }
 
+    @UnsupportedAppUsage
     public void setSpellCheckInProgress(boolean inProgress) {
         mSpellCheckInProgress = inProgress;
     }
 
+    @UnsupportedAppUsage
     public boolean isSpellCheckInProgress() {
         return mSpellCheckInProgress;
     }
diff --git a/core/java/android/text/style/SuggestionRangeSpan.java b/core/java/android/text/style/SuggestionRangeSpan.java
index c1943d5..d958dde 100644
--- a/core/java/android/text/style/SuggestionRangeSpan.java
+++ b/core/java/android/text/style/SuggestionRangeSpan.java
@@ -16,6 +16,7 @@
 
 package android.text.style;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.text.ParcelableSpan;
 import android.text.TextPaint;
@@ -30,11 +31,13 @@
 public class SuggestionRangeSpan extends CharacterStyle implements ParcelableSpan {
     private int mBackgroundColor;
 
+    @UnsupportedAppUsage
     public SuggestionRangeSpan() {
         // 0 is a fully transparent black. Has to be set using #setBackgroundColor
         mBackgroundColor = 0;
     }
 
+    @UnsupportedAppUsage
     public SuggestionRangeSpan(Parcel src) {
         mBackgroundColor = src.readInt();
     }
@@ -64,6 +67,7 @@
         return TextUtils.SUGGESTION_RANGE_SPAN;
     }
 
+    @UnsupportedAppUsage
     public void setBackgroundColor(int backgroundColor) {
         mBackgroundColor = backgroundColor;
     }
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 1b00db2..5210447 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
@@ -99,7 +100,9 @@
     private final String mNotificationTargetPackageName;
     private final int mHashCode;
 
+    @UnsupportedAppUsage
     private float mEasyCorrectUnderlineThickness;
+    @UnsupportedAppUsage
     private int mEasyCorrectUnderlineColor;
 
     private float mMisspelledUnderlineThickness;
@@ -264,6 +267,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getNotificationTargetClassName() {
         return mNotificationTargetClassName;
     }
@@ -368,6 +372,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getUnderlineColor() {
         // The order here should match what is used in updateDrawState
         final boolean misspelled = (mFlags & FLAG_MISSPELLED) != 0;
@@ -390,6 +395,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void notifySelection(Context context, String original, int index) {
         final Intent intent = new Intent();
 
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index f3d39de..f4dad62 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
@@ -35,6 +36,7 @@
 import com.android.i18n.phonenumbers.PhoneNumberMatch;
 import com.android.i18n.phonenumbers.PhoneNumberUtil;
 import com.android.i18n.phonenumbers.PhoneNumberUtil.Leniency;
+import com.android.internal.annotations.GuardedBy;
 
 import libcore.util.EmptyArray;
 
@@ -63,6 +65,10 @@
  *  does not have a URL scheme prefix, the supplied scheme will be prepended to
  *  create <code>http://example.com</code> when the clickable URL link is
  *  created.
+ *
+ * @see MatchFilter
+ * @see TransformFilter
+ * @see UrlSpanFactory
  */
 
 public class Linkify {
@@ -218,6 +224,44 @@
     }
 
     /**
+     * Factory class to create {@link URLSpan}s. While adding spans to a {@link Spannable},
+     * {@link Linkify} will call {@link UrlSpanFactory#create(String)} function to create a
+     * {@link URLSpan}.
+     *
+     * @see #addLinks(Spannable, int, UrlSpanFactory)
+     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter,
+     * UrlSpanFactory)
+     */
+    public static class UrlSpanFactory {
+        private static final Object sInstanceLock = new Object();
+
+        @GuardedBy("sInstanceLock")
+        private static volatile UrlSpanFactory sInstance = null;
+
+        private static synchronized UrlSpanFactory getInstance() {
+            if (sInstance == null) {
+                synchronized (sInstanceLock) {
+                    if (sInstance == null) {
+                        sInstance = new UrlSpanFactory();
+                    }
+                }
+            }
+            return sInstance;
+        }
+
+        /**
+         * Factory function that will called by {@link Linkify} in order to create a
+         * {@link URLSpan}.
+         *
+         * @param url URL found
+         * @return a URLSpan instance
+         */
+        public URLSpan create(final String url) {
+            return new URLSpan(url);
+        }
+    }
+
+    /**
      *  Scans the text of the provided Spannable and turns all occurrences
      *  of the link types indicated in the mask into clickable links.
      *  If the mask is nonzero, it also removes any existing URLSpans
@@ -228,24 +272,55 @@
      *  @param mask Mask to define which kinds of links will be searched.
      *
      *  @return True if at least one link is found and applied.
+     *
+     * @see #addLinks(Spannable, int, UrlSpanFactory)
      */
     public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) {
-        return addLinks(text, mask, null);
+        return addLinks(text, mask, null, null);
     }
 
+    /**
+     *  Scans the text of the provided Spannable and turns all occurrences
+     *  of the link types indicated in the mask into clickable links.
+     *  If the mask is nonzero, it also removes any existing URLSpans
+     *  attached to the Spannable, to avoid problems if you call it
+     *  repeatedly on the same text.
+     *
+     *  @param text Spannable whose text is to be marked-up with links
+     *  @param mask mask to define which kinds of links will be searched
+     *  @param urlSpanFactory factory class used to create {@link URLSpan}s
+     *  @return True if at least one link is found and applied.
+     */
+    public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask,
+            @Nullable UrlSpanFactory urlSpanFactory) {
+        return addLinks(text, mask, null, urlSpanFactory);
+    }
+
+    /**
+     *  Scans the text of the provided Spannable and turns all occurrences of the link types
+     *  indicated in the mask into clickable links. If the mask is nonzero, it also removes any
+     *  existing URLSpans attached to the Spannable, to avoid problems if you call it repeatedly
+     *  on the same text.
+     *
+     * @param text Spannable whose text is to be marked-up with links
+     * @param mask mask to define which kinds of links will be searched
+     * @param context Context to be used while identifying phone numbers
+     * @param urlSpanFactory factory class used to create {@link URLSpan}s
+     * @return true if at least one link is found and applied.
+     */
     private static boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask,
-            @Nullable Context context) {
+            @Nullable Context context, @Nullable UrlSpanFactory urlSpanFactory) {
         if (mask == 0) {
             return false;
         }
 
-        URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
+        final URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
 
         for (int i = old.length - 1; i >= 0; i--) {
             text.removeSpan(old[i]);
         }
 
-        ArrayList<LinkSpec> links = new ArrayList<LinkSpec>();
+        final ArrayList<LinkSpec> links = new ArrayList<LinkSpec>();
 
         if ((mask & WEB_URLS) != 0) {
             gatherLinks(links, text, Patterns.AUTOLINK_WEB_URL,
@@ -274,7 +349,7 @@
         }
 
         for (LinkSpec link: links) {
-            applyLink(link.url, link.start, link.end, text);
+            applyLink(link.url, link.start, link.end, text, urlSpanFactory);
         }
 
         return true;
@@ -290,6 +365,8 @@
      *  @param mask Mask to define which kinds of links will be searched.
      *
      *  @return True if at least one link is found and applied.
+     *
+     *  @see #addLinks(Spannable, int, UrlSpanFactory)
      */
     public static final boolean addLinks(@NonNull TextView text, @LinkifyMask int mask) {
         if (mask == 0) {
@@ -299,7 +376,7 @@
         final Context context = text.getContext();
         final CharSequence t = text.getText();
         if (t instanceof Spannable) {
-            if (addLinks((Spannable) t, mask, context)) {
+            if (addLinks((Spannable) t, mask, context, null)) {
                 addLinkMovementMethod(text);
                 return true;
             }
@@ -308,7 +385,7 @@
         } else {
             SpannableString s = SpannableString.valueOf(t);
 
-            if (addLinks(s, mask, context)) {
+            if (addLinks(s, mask, context, null)) {
                 addLinkMovementMethod(text);
                 text.setText(s);
 
@@ -403,6 +480,8 @@
      *  @param pattern      Regex pattern to be used for finding links
      *  @param scheme       URL scheme string (eg <code>http://</code>) to be
      *                      prepended to the links that do not start with this scheme.
+     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter,
+     * UrlSpanFactory)
      */
     public static final boolean addLinks(@NonNull Spannable text, @NonNull Pattern pattern,
             @Nullable String scheme) {
@@ -423,6 +502,8 @@
      * @param transformFilter Filter to allow the client code to update the link found.
      *
      * @return True if at least one link is found and applied.
+     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter,
+     * UrlSpanFactory)
      */
     public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
             @Nullable String scheme, @Nullable MatchFilter matchFilter,
@@ -446,10 +527,39 @@
      * @param transformFilter Filter to allow the client code to update the link found.
      *
      * @return True if at least one link is found and applied.
+     *
+     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter,
+     * UrlSpanFactory)
      */
     public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
-            @Nullable  String defaultScheme, @Nullable String[] schemes,
+            @Nullable String defaultScheme, @Nullable String[] schemes,
             @Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) {
+        return addLinks(spannable, pattern, defaultScheme, schemes, matchFilter, transformFilter,
+                null);
+    }
+
+    /**
+     * Applies a regex to a Spannable turning the matches into links.
+     *
+     * @param spannable       spannable whose text is to be marked-up with links.
+     * @param pattern         regex pattern to be used for finding links.
+     * @param defaultScheme   the default scheme to be prepended to links if the link does not
+     *                        start with one of the <code>schemes</code> given.
+     * @param schemes         array of schemes (eg <code>http://</code>) to check if the link found
+     *                        contains a scheme. Passing a null or empty value means prepend
+     *                        defaultScheme
+     *                        to all links.
+     * @param matchFilter     the filter that is used to allow the client code additional control
+     *                        over which pattern matches are to be converted into links.
+     * @param transformFilter filter to allow the client code to update the link found.
+     * @param urlSpanFactory  factory class used to create {@link URLSpan}s
+     *
+     * @return True if at least one link is found and applied.
+     */
+    public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
+            @Nullable String defaultScheme, @Nullable String[] schemes,
+            @Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter,
+            @Nullable UrlSpanFactory urlSpanFactory) {
         final String[] schemesCopy;
         if (defaultScheme == null) defaultScheme = "";
         if (schemes == null || schemes.length < 1) {
@@ -478,7 +588,7 @@
             if (allowed) {
                 String url = makeUrl(m.group(0), schemesCopy, m, transformFilter);
 
-                applyLink(url, start, end, spannable);
+                applyLink(url, start, end, spannable, urlSpanFactory);
                 hasMatches = true;
             }
         }
@@ -486,9 +596,12 @@
         return hasMatches;
     }
 
-    private static final void applyLink(String url, int start, int end, Spannable text) {
-        URLSpan span = new URLSpan(url);
-
+    private static void applyLink(String url, int start, int end, Spannable text,
+            @Nullable UrlSpanFactory urlSpanFactory) {
+        if (urlSpanFactory == null) {
+            urlSpanFactory = UrlSpanFactory.getInstance();
+        }
+        final URLSpan span = urlSpanFactory.create(url);
         text.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
     }
 
@@ -542,6 +655,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static void gatherTelLinks(ArrayList<LinkSpec> links, Spannable s,
             @Nullable Context context) {
         PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
diff --git a/core/java/android/transition/Scene.java b/core/java/android/transition/Scene.java
index 15ad7de..2c858cd 100644
--- a/core/java/android/transition/Scene.java
+++ b/core/java/android/transition/Scene.java
@@ -35,7 +35,8 @@
     private int mLayoutId = -1;
     private ViewGroup mSceneRoot;
     private View mLayout; // alternative to layoutId
-    Runnable mEnterAction, mExitAction;
+    Runnable mEnterAction;
+    Runnable mExitAction;
 
     /**
      * Returns a Scene described by the resource file associated with the given
@@ -265,4 +266,4 @@
     boolean isCreatedFromLayoutResource() {
         return (mLayoutId > 0);
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index f1e937e..5108a79 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -18,6 +18,7 @@
 
 import libcore.util.EmptyArray;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.Collection;
 import java.util.ConcurrentModificationException;
 import java.util.Map;
@@ -70,16 +71,19 @@
     /**
      * Maximum number of entries to have in array caches.
      */
+    @UnsupportedAppUsage
     private static final int CACHE_SIZE = 10;
 
     /**
      * Special hash array value that indicates the container is immutable.
      */
+    @UnsupportedAppUsage
     static final int[] EMPTY_IMMUTABLE_INTS = new int[0];
 
     /**
      * @hide Special immutable empty ArrayMap.
      */
+    @UnsupportedAppUsage
     public static final ArrayMap EMPTY = new ArrayMap<>(-1);
 
     /**
@@ -88,14 +92,21 @@
      * The first entry in the array is a pointer to the next array in the
      * list; the second entry is a pointer to the int[] hash code array for it.
      */
+    @UnsupportedAppUsage
     static Object[] mBaseCache;
+    @UnsupportedAppUsage
     static int mBaseCacheSize;
+    @UnsupportedAppUsage
     static Object[] mTwiceBaseCache;
+    @UnsupportedAppUsage
     static int mTwiceBaseCacheSize;
 
     final boolean mIdentityHashCode;
+    @UnsupportedAppUsage
     int[] mHashes;
+    @UnsupportedAppUsage
     Object[] mArray;
+    @UnsupportedAppUsage
     int mSize;
     MapCollections<K, V> mCollections;
 
@@ -111,6 +122,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     int indexOf(Object key, int hash) {
         final int N = mSize;
 
@@ -149,6 +161,7 @@
         return ~end;
     }
 
+    @UnsupportedAppUsage
     int indexOfNull() {
         final int N = mSize;
 
@@ -187,6 +200,7 @@
         return ~end;
     }
 
+    @UnsupportedAppUsage
     private void allocArrays(final int size) {
         if (mHashes == EMPTY_IMMUTABLE_INTS) {
             throw new UnsupportedOperationException("ArrayMap is immutable");
@@ -225,6 +239,7 @@
         mArray = new Object[size<<1];
     }
 
+    @UnsupportedAppUsage
     private static void freeArrays(final int[] hashes, final Object[] array, final int size) {
         if (hashes.length == (BASE_SIZE*2)) {
             synchronized (ArrayMap.class) {
@@ -378,6 +393,7 @@
                 : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
     }
 
+    @UnsupportedAppUsage
     int indexOfValue(Object value) {
         final int N = mSize*2;
         final Object[] array = mArray;
@@ -535,6 +551,7 @@
      * The array must already be large enough to contain the item.
      * @hide
      */
+    @UnsupportedAppUsage
     public void append(K key, V value) {
         int index = mSize;
         final int hash = key == null ? 0
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 2eea7df..526a950 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -18,6 +18,7 @@
 
 import libcore.util.EmptyArray;
 
+import android.annotation.UnsupportedAppUsage;
 import java.lang.reflect.Array;
 import java.util.Collection;
 import java.util.Iterator;
@@ -70,11 +71,15 @@
     static int sTwiceBaseCacheSize;
 
     final boolean mIdentityHashCode;
+    @UnsupportedAppUsage
     int[] mHashes;
+    @UnsupportedAppUsage
     Object[] mArray;
+    @UnsupportedAppUsage
     int mSize;
     MapCollections<E, E> mCollections;
 
+    @UnsupportedAppUsage
     private int indexOf(Object key, int hash) {
         final int N = mSize;
 
@@ -113,6 +118,7 @@
         return ~end;
     }
 
+    @UnsupportedAppUsage
     private int indexOfNull() {
         final int N = mSize;
 
@@ -151,6 +157,7 @@
         return ~end;
     }
 
+    @UnsupportedAppUsage
     private void allocArrays(final int size) {
         if (size == (BASE_SIZE * 2)) {
             synchronized (ArraySet.class) {
@@ -208,6 +215,7 @@
         mArray = new Object[size];
     }
 
+    @UnsupportedAppUsage
     private static void freeArrays(final int[] hashes, final Object[] array, final int size) {
         if (hashes.length == (BASE_SIZE * 2)) {
             synchronized (ArraySet.class) {
@@ -282,6 +290,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public ArraySet(Collection<E> set) {
         this();
         if (set != null) {
diff --git a/core/java/android/util/Base64.java b/core/java/android/util/Base64.java
index 1f2a5a7..ecc0c9c 100644
--- a/core/java/android/util/Base64.java
+++ b/core/java/android/util/Base64.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.UnsupportedEncodingException;
 
 /**
@@ -737,5 +738,6 @@
         }
     }
 
+    @UnsupportedAppUsage
     private Base64() { }   // don't instantiate
 }
diff --git a/core/java/android/util/Base64OutputStream.java b/core/java/android/util/Base64OutputStream.java
index 4535d1c..230a3a5 100644
--- a/core/java/android/util/Base64OutputStream.java
+++ b/core/java/android/util/Base64OutputStream.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.FilterOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -57,6 +58,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Base64OutputStream(OutputStream out, int flags, boolean encode) {
         super(out);
         this.flags = flags;
@@ -117,8 +119,10 @@
                 out.flush();
             }
         } catch (IOException e) {
-            if (thrown != null) {
+            if (thrown == null) {
                 thrown = e;
+            } else {
+                thrown.addSuppressed(e);
             }
         }
 
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index 46e3169..e87fcff 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.PrintWriter;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
@@ -108,6 +109,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void buildShortClassTag(Object cls, StringBuilder out) {
         if (cls == null) {
             out.append("null");
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 13de172..b092fcf 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.SystemProperties;
 
 
@@ -172,6 +173,7 @@
      *             density for a specific display.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static int DENSITY_DEVICE = getDeviceDensity();
 
     /**
@@ -234,12 +236,14 @@
      * being applied.
      * @hide
      */
+    @UnsupportedAppUsage
     public int noncompatWidthPixels;
     /**
      * The reported display height prior to any compatibility mode scaling
      * being applied.
      * @hide
      */
+    @UnsupportedAppUsage
     public int noncompatHeightPixels;
     /**
      * The reported display density prior to any compatibility mode scaling
@@ -252,6 +256,7 @@
      * being applied.
      * @hide
      */
+    @UnsupportedAppUsage
     public int noncompatDensityDpi;
     /**
      * The reported scaled density prior to any compatibility mode scaling
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 92f218b..65d825a 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -17,6 +17,7 @@
 package android.util;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 
 import java.io.BufferedReader;
 import java.io.FileReader;
@@ -82,6 +83,7 @@
         private static final byte FLOAT_TYPE = 4;
 
         /** @param data containing event, read from the system */
+        @UnsupportedAppUsage
         /*package*/ Event(byte[] data) {
             mBuffer = ByteBuffer.wrap(data);
             mBuffer.order(ByteOrder.nativeOrder());
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 6b7b89c..a7f14b6 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -33,6 +33,8 @@
 
     public static final String FFLAG_PREFIX = "sys.fflag.";
     public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override.";
+    public static final String PERSIST_PREFIX = "persist." + FFLAG_OVERRIDE_PREFIX;
+    public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
 
     private static final Map<String, String> DEFAULT_FLAGS;
     static {
@@ -42,6 +44,8 @@
         DEFAULT_FLAGS.put("settings_audio_switcher", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
         DEFAULT_FLAGS.put("settings_dynamic_homepage", "false");
+        DEFAULT_FLAGS.put("settings_mobile_network_v2", "false");
+        DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "true");
     }
 
     /**
diff --git a/core/java/android/util/Half.java b/core/java/android/util/Half.java
index 84c2e83..5718d99 100644
--- a/core/java/android/util/Half.java
+++ b/core/java/android/util/Half.java
@@ -20,8 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
-import sun.misc.FloatingDecimal;
-
 /**
  * <p>The {@code Half} class is a wrapper and a utility class to manipulate half-precision 16-bit
  * <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a>
@@ -1026,7 +1024,7 @@
      *         half-precision float value
      */
     public static @HalfFloat short parseHalf(@NonNull String s) throws NumberFormatException {
-        return toHalf(FloatingDecimal.parseFloat(s));
+        return toHalf(Float.parseFloat(s));
     }
 
     /**
diff --git a/core/java/android/util/IconDrawableFactory.java b/core/java/android/util/IconDrawableFactory.java
index 6a6c2ce..d90b65e 100644
--- a/core/java/android/util/IconDrawableFactory.java
+++ b/core/java/android/util/IconDrawableFactory.java
@@ -15,6 +15,7 @@
  */
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -52,6 +53,7 @@
         return appInfo.isInstantApp() || mUm.isManagedProfile(userId);
     }
 
+    @UnsupportedAppUsage
     public Drawable getBadgedIcon(ApplicationInfo appInfo) {
         return getBadgedIcon(appInfo, UserHandle.getUserId(appInfo.uid));
     }
@@ -60,6 +62,7 @@
         return getBadgedIcon(appInfo, appInfo, userId);
     }
 
+    @UnsupportedAppUsage
     public Drawable getBadgedIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo,
             @UserIdInt int userId) {
         Drawable icon = mPm.loadUnbadgedItemIcon(itemInfo, appInfo);
@@ -107,6 +110,7 @@
         return Resources.getSystem().getColor(resourceId, null);
     }
 
+    @UnsupportedAppUsage
     public static IconDrawableFactory newInstance(Context context) {
         return new IconDrawableFactory(context, true);
     }
diff --git a/core/java/android/util/IntArray.java b/core/java/android/util/IntArray.java
index 3617aa7..5a74ec0 100644
--- a/core/java/android/util/IntArray.java
+++ b/core/java/android/util/IntArray.java
@@ -18,9 +18,11 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
-import java.util.Arrays;
+
 import libcore.util.EmptyArray;
 
+import java.util.Arrays;
+
 /**
  * Implements a growing array of int primitives.
  *
@@ -102,7 +104,7 @@
         ensureCapacity(1);
         int rightSegment = mSize - index;
         mSize++;
-        checkBounds(index);
+        ArrayUtils.checkBounds(mSize, index);
 
         if (rightSegment != 0) {
             // Move by 1 all values from the right of 'index'
@@ -175,7 +177,7 @@
      * Returns the value at the specified position in this array.
      */
     public int get(int index) {
-        checkBounds(index);
+        ArrayUtils.checkBounds(mSize, index);
         return mValues[index];
     }
 
@@ -183,7 +185,7 @@
      * Sets the value at the specified position in this array.
      */
     public void set(int index, int value) {
-        checkBounds(index);
+        ArrayUtils.checkBounds(mSize, index);
         mValues[index] = value;
     }
 
@@ -205,7 +207,7 @@
      * Removes the value at the specified index from this array.
      */
     public void remove(int index) {
-        checkBounds(index);
+        ArrayUtils.checkBounds(mSize, index);
         System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1);
         mSize--;
     }
@@ -223,10 +225,4 @@
     public int[] toArray() {
         return Arrays.copyOf(mValues, mSize);
     }
-
-    private void checkBounds(int index) {
-        if (index < 0 || mSize <= index) {
-            throw new ArrayIndexOutOfBoundsException(mSize, index);
-        }
-    }
 }
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index eb84479f..adfa4fc 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.time.LocalDateTime;
@@ -31,11 +32,13 @@
     private final Deque<String> mLog;
     private final int mMaxLines;
 
+    @UnsupportedAppUsage
     public LocalLog(int maxLines) {
         mMaxLines = Math.max(0, maxLines);
         mLog = new ArrayDeque<>(mMaxLines);
     }
 
+    @UnsupportedAppUsage
     public void log(String msg) {
         if (mMaxLines <= 0) {
             return;
@@ -50,6 +53,7 @@
         mLog.add(logLine);
     }
 
+    @UnsupportedAppUsage
     public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         Iterator<String> itr = mLog.iterator();
         while (itr.hasNext()) {
@@ -69,6 +73,7 @@
         ReadOnlyLocalLog(LocalLog log) {
             mLog = log;
         }
+        @UnsupportedAppUsage
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             mLog.dump(fd, pw, args);
         }
@@ -77,6 +82,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public ReadOnlyLocalLog readOnlyLocalLog() {
         return new ReadOnlyLocalLog(this);
     }
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 2499afb..50779031 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.DeadSystemException;
 
 import com.android.internal.os.RuntimeInit;
@@ -302,6 +303,7 @@
         return wtf(LOG_ID_MAIN, tag, msg, tr, false, false);
     }
 
+    @UnsupportedAppUsage
     static int wtf(int logId, @Nullable String tag, @Nullable String msg, @Nullable Throwable tr,
             boolean localStack, boolean system) {
         TerribleFailure what = new TerribleFailure(msg, tr);
@@ -380,8 +382,9 @@
     /** @hide */ public static final int LOG_ID_SYSTEM = 3;
     /** @hide */ public static final int LOG_ID_CRASH = 4;
 
-    /** @hide */ public static native int println_native(int bufID,
-            int priority, String tag, String msg);
+    /** @hide */
+    @UnsupportedAppUsage
+    public static native int println_native(int bufID, int priority, String tag, String msg);
 
     /**
      * Return the maximum payload the log daemon accepts without truncation.
diff --git a/core/java/android/util/LogWriter.java b/core/java/android/util/LogWriter.java
index ce30631..b062ace 100644
--- a/core/java/android/util/LogWriter.java
+++ b/core/java/android/util/LogWriter.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.Writer;
 
 /** @hide */
@@ -37,6 +38,7 @@
      * {@link android.util.Log#ERROR Log.ERROR}.
      * @param tag A string tag to associate with each printed log statement.
      */
+    @UnsupportedAppUsage
     public LogWriter(int priority, String tag) {
         mPriority = priority;
         mTag = tag;
diff --git a/core/java/android/util/LongArray.java b/core/java/android/util/LongArray.java
index fa98096..6f4aa52 100644
--- a/core/java/android/util/LongArray.java
+++ b/core/java/android/util/LongArray.java
@@ -17,6 +17,7 @@
 package android.util;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
@@ -44,6 +45,7 @@
     /**
      * Creates an empty LongArray with the default initial capacity.
      */
+    @UnsupportedAppUsage
     public LongArray() {
         this(10);
     }
@@ -102,11 +104,12 @@
      *
      * @throws IndexOutOfBoundsException when index &lt; 0 || index &gt; size()
      */
+    @UnsupportedAppUsage
     public void add(int index, long value) {
         ensureCapacity(1);
         int rightSegment = mSize - index;
         mSize++;
-        checkBounds(index);
+        ArrayUtils.checkBounds(mSize, index);
 
         if (rightSegment != 0) {
             // Move by 1 all values from the right of 'index'
@@ -165,8 +168,9 @@
     /**
      * Returns the value at the specified position in this array.
      */
+    @UnsupportedAppUsage
     public long get(int index) {
-        checkBounds(index);
+        ArrayUtils.checkBounds(mSize, index);
         return mValues[index];
     }
 
@@ -174,7 +178,7 @@
      * Sets the value at the specified position in this array.
      */
     public void set(int index, long value) {
-        checkBounds(index);
+        ArrayUtils.checkBounds(mSize, index);
         mValues[index] = value;
     }
 
@@ -196,7 +200,7 @@
      * Removes the value at the specified index from this array.
      */
     public void remove(int index) {
-        checkBounds(index);
+        ArrayUtils.checkBounds(mSize, index);
         System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1);
         mSize--;
     }
@@ -204,6 +208,7 @@
     /**
      * Returns the number of values in this array.
      */
+    @UnsupportedAppUsage
     public int size() {
         return mSize;
     }
@@ -215,12 +220,6 @@
         return Arrays.copyOf(mValues, mSize);
     }
 
-    private void checkBounds(int index) {
-        if (index < 0 || mSize <= index) {
-            throw new ArrayIndexOutOfBoundsException(mSize, index);
-        }
-    }
-
     /**
      * Test if each element of {@code a} equals corresponding element from {@code b}
      */
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index a361457..d5af922 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -19,6 +19,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
+import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
 /**
@@ -45,8 +46,11 @@
  * @hide
  */
 public class LongSparseLongArray implements Cloneable {
+    @UnsupportedAppUsage
     private long[] mKeys;
+    @UnsupportedAppUsage
     private long[] mValues;
+    @UnsupportedAppUsage
     private int mSize;
 
     /**
diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java
index 4015488..f04e7cb 100644
--- a/core/java/android/util/LruCache.java
+++ b/core/java/android/util/LruCache.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
@@ -60,6 +61,7 @@
  * Support Package</a> for earlier releases.
  */
 public class LruCache<K, V> {
+    @UnsupportedAppUsage
     private final LinkedHashMap<K, V> map;
 
     /** Size of this cache in units. Not necessarily the number of elements. */
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index b2e24c3..37bb597 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * A class that contains utility methods related to numbers.
  *
@@ -28,10 +30,12 @@
     private MathUtils() {
     }
 
+    @UnsupportedAppUsage
     public static float abs(float v) {
         return v > 0 ? v : -v;
     }
 
+    @UnsupportedAppUsage
     public static int constrain(int amount, int low, int high) {
         return amount < low ? low : (amount > high ? high : amount);
     }
@@ -40,6 +44,7 @@
         return amount < low ? low : (amount > high ? high : amount);
     }
 
+    @UnsupportedAppUsage
     public static float constrain(float amount, float low, float high) {
         return amount < low ? low : (amount > high ? high : amount);
     }
@@ -64,6 +69,7 @@
         return a > b ? a : b;
     }
 
+    @UnsupportedAppUsage
     public static float max(int a, int b) {
         return a > b ? a : b;
     }
@@ -153,6 +159,7 @@
         return (float) Math.tan(angle);
     }
 
+    @UnsupportedAppUsage
     public static float lerp(float start, float stop, float amount) {
         return start + (stop - start) * amount;
     }
@@ -187,6 +194,21 @@
     }
 
     /**
+     * Perform Hermite interpolation between two values.
+     * Eg:
+     *   smoothStep(0, 0.5f, 0.5f) = 1f
+     *   smoothStep(0, 0.5f, 0.25f) = 0.5f
+     *
+     * @param start Left edge.
+     * @param end Right edge.
+     * @param x A value between {@code start} and {@code end}.
+     * @return A number between 0 and 1 representing where {@code x} is in the interpolation.
+     */
+    public static float smoothStep(float start, float end, float x) {
+        return constrain((x - start) / (end - start), 0f, 1f);
+    }
+
+    /**
      * Returns the sum of the two parameters, or throws an exception if the resulting sum would
      * cause an overflow or underflow.
      * @throws IllegalArgumentException when overflow or underflow would occur.
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index bf33519..d5bec0f 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -20,9 +20,10 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 
-import libcore.io.IoUtils;
 import dalvik.system.CloseGuard;
 
+import libcore.io.IoUtils;
+
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.UUID;
@@ -56,7 +57,7 @@
 
     private final boolean mIsOwner;
     private final long mMemoryAddr;
-    private int mFd = -1;
+    private ParcelFileDescriptor mFd;
 
     /**
      * Creates a new instance.
@@ -71,8 +72,8 @@
         }
         mIsOwner = true;
         final String name = UUID.randomUUID().toString();
-        mFd = nativeCreate(name, size);
-        mMemoryAddr = nativeOpen(mFd, mIsOwner);
+        mFd = ParcelFileDescriptor.adoptFd(nativeCreate(name, size));
+        mMemoryAddr = nativeOpen(mFd.getFd(), mIsOwner);
         mCloseGuard.open("close");
     }
 
@@ -82,8 +83,8 @@
         if (pfd == null) {
             throw new IOException("No backing file descriptor");
         }
-        mFd = pfd.detachFd();
-        mMemoryAddr = nativeOpen(mFd, mIsOwner);
+        mFd = ParcelFileDescriptor.adoptFd(pfd.detachFd());
+        mMemoryAddr = nativeOpen(mFd.getFd(), mIsOwner);
         mCloseGuard.open("close");
     }
 
@@ -105,7 +106,7 @@
     public int get(int index) throws IOException {
         enforceNotClosed();
         enforceValidIndex(index);
-        return nativeGet(mFd, mMemoryAddr, index);
+        return nativeGet(mFd.getFd(), mMemoryAddr, index);
     }
 
     /**
@@ -121,7 +122,7 @@
         enforceNotClosed();
         enforceWritable();
         enforceValidIndex(index);
-        nativeSet(mFd, mMemoryAddr, index, value);
+        nativeSet(mFd.getFd(), mMemoryAddr, index, value);
     }
 
     /**
@@ -131,7 +132,7 @@
      */
     public int size() throws IOException {
         enforceNotClosed();
-        return nativeSize(mFd);
+        return nativeSize(mFd.getFd());
     }
 
     /**
@@ -142,8 +143,9 @@
     @Override
     public void close() throws IOException {
         if (!isClosed()) {
-            nativeClose(mFd, mMemoryAddr, mIsOwner);
-            mFd = -1;
+            nativeClose(mFd.getFd(), mMemoryAddr, mIsOwner);
+            mFd.close();
+            mFd = null;
             mCloseGuard.close();
         }
     }
@@ -152,7 +154,7 @@
      * @return Whether this array is closed and shouldn't be used.
      */
     public boolean isClosed() {
-        return mFd == -1;
+        return mFd == null;
     }
 
     @Override
@@ -175,13 +177,8 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
-        try {
-            // Don't let writing to a parcel to close our fd - plz
-            parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } finally {
-            pfd.detachFd();
-        }
+        // Don't let writing to a parcel to close our fd - plz
+        parcel.writeParcelable(mFd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
     }
 
     @Override
@@ -195,13 +192,13 @@
         if (getClass() != obj.getClass()) {
             return false;
         }
-        MemoryIntArray other = (MemoryIntArray) obj;
-        return mFd == other.mFd;
+
+        return false;
     }
 
     @Override
     public int hashCode() {
-        return mFd;
+        return mFd.hashCode();
     }
 
     private void enforceNotClosed() {
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 30d7b6c..da566c9 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
@@ -56,6 +57,7 @@
         mTimeout = timeout;
     }
 
+    @UnsupportedAppUsage
     public static synchronized NtpTrustedTime getInstance(Context context) {
         if (sSingleton == null) {
             final Resources res = context.getResources();
@@ -80,6 +82,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public boolean forceRefresh() {
         // We can't do this at initialization time: ConnectivityService might not be running yet.
         synchronized (this) {
@@ -126,6 +129,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public boolean hasCache() {
         return mHasCache;
     }
@@ -149,6 +153,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public long currentTimeMillis() {
         if (!mHasCache) {
             throw new IllegalStateException("Missing authoritative time source");
@@ -160,11 +165,13 @@
         return mCachedNtpTime + getCacheAge();
     }
 
+    @UnsupportedAppUsage
     public long getCachedNtpTime() {
         if (LOGD) Log.d(TAG, "getCachedNtpTime() cache hit");
         return mCachedNtpTime;
     }
 
+    @UnsupportedAppUsage
     public long getCachedNtpTimeReference() {
         return mCachedNtpElapsedRealtime;
     }
diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java
index 6f314d0..5342d5d 100644
--- a/core/java/android/util/PathParser.java
+++ b/core/java/android/util/PathParser.java
@@ -14,6 +14,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Path;
 
 import dalvik.annotation.optimization.FastNative;
@@ -28,6 +29,7 @@
      * @param pathString The string representing a path, the same as "d" string in svg file.
      * @return the generated Path object.
      */
+    @UnsupportedAppUsage
     public static Path createPathFromPathData(String pathString) {
         if (pathString == null) {
             throw new IllegalArgumentException("Path string can not be null.");
diff --git a/core/java/android/util/Pools.java b/core/java/android/util/Pools.java
index f0b7e01..e242fe5 100644
--- a/core/java/android/util/Pools.java
+++ b/core/java/android/util/Pools.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Helper class for crating pools of objects. An example use looks like this:
  * <pre>
@@ -52,6 +54,7 @@
         /**
          * @return An instance from the pool if such, null otherwise.
          */
+        @UnsupportedAppUsage
         public T acquire();
 
         /**
@@ -62,6 +65,7 @@
          *
          * @throws IllegalStateException If the instance is already in the pool.
          */
+        @UnsupportedAppUsage
         public boolean release(T instance);
     }
 
@@ -75,6 +79,7 @@
      * @param <T> The pooled type.
      */
     public static class SimplePool<T> implements Pool<T> {
+        @UnsupportedAppUsage
         private final Object[] mPool;
 
         private int mPoolSize;
@@ -86,6 +91,7 @@
          *
          * @throws IllegalArgumentException If the max pool size is less than zero.
          */
+        @UnsupportedAppUsage
         public SimplePool(int maxPoolSize) {
             if (maxPoolSize <= 0) {
                 throw new IllegalArgumentException("The max pool size must be > 0");
@@ -95,6 +101,7 @@
 
         @Override
         @SuppressWarnings("unchecked")
+        @UnsupportedAppUsage
         public T acquire() {
             if (mPoolSize > 0) {
                 final int lastPooledIndex = mPoolSize - 1;
@@ -107,6 +114,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public boolean release(T instance) {
             if (isInPool(instance)) {
                 throw new IllegalStateException("Already in the pool!");
@@ -151,11 +159,13 @@
         }
 
         /** @see #SynchronizedPool(int, Object)  */
+        @UnsupportedAppUsage
         public SynchronizedPool(int maxPoolSize) {
             this(maxPoolSize, new Object());
         }
 
         @Override
+        @UnsupportedAppUsage
         public T acquire() {
             synchronized (mLock) {
                 return super.acquire();
@@ -163,6 +173,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public boolean release(T element) {
             synchronized (mLock) {
                 return super.release(element);
diff --git a/core/java/android/util/Rational.java b/core/java/android/util/Rational.java
index 80d26d9..39e8b14 100644
--- a/core/java/android/util/Rational.java
+++ b/core/java/android/util/Rational.java
@@ -17,6 +17,7 @@
 
 import static com.android.internal.util.Preconditions.*;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.IOException;
 import java.io.InvalidObjectException;
 
@@ -74,7 +75,9 @@
      * Do not change the order of these fields or add new instance fields to maintain the
      * Serializable compatibility across API revisions.
      */
+    @UnsupportedAppUsage
     private final int mNumerator;
+    @UnsupportedAppUsage
     private final int mDenominator;
 
     /**
diff --git a/core/java/android/util/RecurrenceRule.java b/core/java/android/util/RecurrenceRule.java
index 9c89876..209a5912 100644
--- a/core/java/android/util/RecurrenceRule.java
+++ b/core/java/android/util/RecurrenceRule.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -49,6 +50,7 @@
     @VisibleForTesting
     public static Clock sClock = Clock.systemDefaultZone();
 
+    @UnsupportedAppUsage
     public final ZonedDateTime start;
     public final ZonedDateTime end;
     public final Period period;
@@ -65,6 +67,7 @@
     }
 
     @Deprecated
+    @UnsupportedAppUsage
     public static RecurrenceRule buildRecurringMonthly(int dayOfMonth, ZoneId zone) {
         // Assume we started last January, since it has all possible days
         final ZonedDateTime now = ZonedDateTime.now(sClock).withZoneSameInstant(zone);
diff --git a/core/java/android/util/Singleton.java b/core/java/android/util/Singleton.java
index 8a38bdb..33135e6 100644
--- a/core/java/android/util/Singleton.java
+++ b/core/java/android/util/Singleton.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Singleton helper class for lazily initialization.
  *
@@ -24,10 +26,12 @@
  * @hide
  */
 public abstract class Singleton<T> {
+    @UnsupportedAppUsage
     private T mInstance;
 
     protected abstract T create();
 
+    @UnsupportedAppUsage
     public final T get() {
         synchronized (this) {
             if (mInstance == null) {
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index 58a2703..c9fc3f2 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * @hide
  */
@@ -24,6 +26,7 @@
     private Slog() {
     }
 
+    @UnsupportedAppUsage
     public static int v(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_SYSTEM, Log.VERBOSE, tag, msg);
     }
@@ -33,15 +36,18 @@
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int d(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_SYSTEM, Log.DEBUG, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int d(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_SYSTEM, Log.DEBUG, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int i(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_SYSTEM, Log.INFO, tag, msg);
     }
@@ -51,10 +57,12 @@
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int w(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_SYSTEM, Log.WARN, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int w(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_SYSTEM, Log.WARN, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
@@ -64,10 +72,12 @@
         return Log.println_native(Log.LOG_ID_SYSTEM, Log.WARN, tag, Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int e(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_SYSTEM, Log.ERROR, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int e(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_SYSTEM, Log.ERROR, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
@@ -78,6 +88,7 @@
      * will always be handled asynchronously.  Primarily for use by coding running within
      * the system process.
      */
+    @UnsupportedAppUsage
     public static int wtf(String tag, String msg) {
         return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null, false, true);
     }
@@ -94,6 +105,7 @@
      * will always be handled asynchronously.  Primarily for use by coding running within
      * the system process.
      */
+    @UnsupportedAppUsage
     public static int wtfStack(String tag, String msg) {
         return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null, true, true);
     }
@@ -112,10 +124,12 @@
      * and will always be handled asynchronously.  Primarily for use by coding running within
      * the system process.
      */
+    @UnsupportedAppUsage
     public static int wtf(String tag, String msg, Throwable tr) {
         return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, tr, false, true);
     }
 
+    @UnsupportedAppUsage
     public static int println(int priority, String tag, String msg) {
         return Log.println_native(Log.LOG_ID_SYSTEM, priority, tag, msg);
     }
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index b3400ef..aa5ca353 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -19,42 +19,48 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
+import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
 /**
- * SparseArrays map integers to Objects.  Unlike a normal array of Objects,
- * there can be gaps in the indices.  It is intended to be more memory efficient
- * than using a HashMap to map Integers to Objects, both because it avoids
+ * <code>SparseArray</code> maps integers to Objects and, unlike a normal array of Objects,
+ * its indices can contain gaps. <code>SparseArray</code> is intended to be more memory-efficient
+ * than a
+ * <a href="/reference/java/util/HashMap"><code>HashMap</code></a>, because it avoids
  * auto-boxing keys and its data structure doesn't rely on an extra entry object
  * for each mapping.
  *
  * <p>Note that this container keeps its mappings in an array data structure,
- * using a binary search to find keys.  The implementation is not intended to be appropriate for
+ * using a binary search to find keys. The implementation is not intended to be appropriate for
  * data structures
- * that may contain large numbers of items.  It is generally slower than a traditional
- * HashMap, since lookups require a binary search and adds and removes require inserting
- * and deleting entries in the array.  For containers holding up to hundreds of items,
- * the performance difference is not significant, less than 50%.</p>
+ * that may contain large numbers of items. It is generally slower than a
+ * <code>HashMap</code> because lookups require a binary search,
+ * and adds and removes require inserting
+ * and deleting entries in the array. For containers holding up to hundreds of items,
+ * the performance difference is less than 50%.
  *
  * <p>To help with performance, the container includes an optimization when removing
  * keys: instead of compacting its array immediately, it leaves the removed entry marked
- * as deleted.  The entry can then be re-used for the same key, or compacted later in
- * a single garbage collection step of all removed entries.  This garbage collection will
- * need to be performed at any time the array needs to be grown or the the map size or
- * entry values are retrieved.</p>
+ * as deleted. The entry can then be re-used for the same key or compacted later in
+ * a single garbage collection of all removed entries. This garbage collection
+ * must be performed whenever the array needs to be grown, or when the map size or
+ * entry values are retrieved.
  *
  * <p>It is possible to iterate over the items in this container using
  * {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
- * <code>keyAt(int)</code> with ascending values of the index will return the
- * keys in ascending order, or the values corresponding to the keys in ascending
- * order in the case of <code>valueAt(int)</code>.</p>
+ * <code>keyAt(int)</code> with ascending values of the index returns the
+ * keys in ascending order. In the case of <code>valueAt(int)</code>, the
+ * values corresponding to the keys are returned in ascending order.
  */
 public class SparseArray<E> implements Cloneable {
     private static final Object DELETED = new Object();
     private boolean mGarbage = false;
 
+    @UnsupportedAppUsage
     private int[] mKeys;
+    @UnsupportedAppUsage
     private Object[] mValues;
+    @UnsupportedAppUsage
     private int mSize;
 
     /**
@@ -333,7 +339,7 @@
 
     /**
      * Returns an index for which {@link #valueAt} would return the
-     * specified key, or a negative number if no keys map to the
+     * specified value, 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
@@ -357,7 +363,7 @@
 
     /**
      * Returns an index for which {@link #valueAt} would return the
-     * specified key, or a negative number if no keys map to the
+     * specified value, 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
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index 68d347c..9c6b969 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -19,6 +19,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
+import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
 /**
@@ -303,7 +304,10 @@
         return buffer.toString();
     }
 
+    @UnsupportedAppUsage
     private int[] mKeys;
+    @UnsupportedAppUsage
     private boolean[] mValues;
+    @UnsupportedAppUsage
     private int mSize;
 }
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 3b832dd..1954753 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -21,6 +21,7 @@
 
 import java.util.Arrays;
 
+import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
 /**
@@ -45,8 +46,11 @@
  * order in the case of <code>valueAt(int)</code>.</p>
  */
 public class SparseIntArray implements Cloneable {
+    @UnsupportedAppUsage
     private int[] mKeys;
+    @UnsupportedAppUsage
     private int[] mValues;
+    @UnsupportedAppUsage
     private int mSize;
 
     /**
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 05b613c..0e25038 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.SystemClock;
 
 import libcore.util.TimeZoneFinder;
@@ -248,6 +249,7 @@
     }
 
     /** @hide Just for debugging; not internationalized. */
+    @UnsupportedAppUsage
     public static void formatDuration(long duration, PrintWriter pw, int fieldLen) {
         synchronized (sFormatSync) {
             int len = formatDurationLocked(duration, fieldLen);
@@ -264,6 +266,7 @@
     }
 
     /** @hide Just for debugging; not internationalized. */
+    @UnsupportedAppUsage
     public static void formatDuration(long duration, PrintWriter pw) {
         formatDuration(duration, pw, 0);
     }
@@ -297,6 +300,7 @@
      * @return String representation of the time.
      * @hide
      */
+    @UnsupportedAppUsage
     public static String logTimeOfDay(long millis) {
         Calendar c = Calendar.getInstance();
         if (millis >= 0) {
diff --git a/core/java/android/util/TrustedTime.java b/core/java/android/util/TrustedTime.java
index 263d782..c78665d 100644
--- a/core/java/android/util/TrustedTime.java
+++ b/core/java/android/util/TrustedTime.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Interface that provides trusted time information, possibly coming from an NTP
  * server. Implementations may cache answers until {@link #forceRefresh()}.
@@ -27,17 +29,20 @@
      * Force update with an external trusted time source, returning {@code true}
      * when successful.
      */
+    @UnsupportedAppUsage
     public boolean forceRefresh();
 
     /**
      * Check if this instance has cached a response from a trusted time source.
      */
+    @UnsupportedAppUsage
     public boolean hasCache();
 
     /**
      * Return time since last trusted time source contact, or
      * {@link Long#MAX_VALUE} if never contacted.
      */
+    @UnsupportedAppUsage
     public long getCacheAge();
 
     /**
@@ -51,5 +56,6 @@
      * Return current time similar to {@link System#currentTimeMillis()},
      * possibly using a cached authoritative time source.
      */
+    @UnsupportedAppUsage
     public long currentTimeMillis();
 }
diff --git a/core/java/android/util/Xml.java b/core/java/android/util/Xml.java
index 041e8a8..e3b8fec 100644
--- a/core/java/android/util/Xml.java
+++ b/core/java/android/util/Xml.java
@@ -16,27 +16,27 @@
 
 package android.util;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.UnsupportedEncodingException;
-import org.apache.harmony.xml.ExpatReader;
-import org.kxml2.io.KXmlParser;
+import libcore.util.XmlObjectFactory;
+
 import org.xml.sax.ContentHandler;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.XMLReader;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
 import org.xmlpull.v1.XmlSerializer;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+
 /**
  * XML utility methods.
  */
 public class Xml {
-    /** @hide */ public Xml() {}
+    private Xml() {}
 
     /**
      * {@link org.xmlpull.v1.XmlPullParser} "relaxed" feature name.
@@ -52,7 +52,7 @@
     public static void parse(String xml, ContentHandler contentHandler)
             throws SAXException {
         try {
-            XMLReader reader = new ExpatReader();
+            XMLReader reader = XmlObjectFactory.newXMLReader();
             reader.setContentHandler(contentHandler);
             reader.parse(new InputSource(new StringReader(xml)));
         } catch (IOException e) {
@@ -66,7 +66,7 @@
      */
     public static void parse(Reader in, ContentHandler contentHandler)
             throws IOException, SAXException {
-        XMLReader reader = new ExpatReader();
+        XMLReader reader = XmlObjectFactory.newXMLReader();
         reader.setContentHandler(contentHandler);
         reader.parse(new InputSource(in));
     }
@@ -77,7 +77,7 @@
      */
     public static void parse(InputStream in, Encoding encoding,
             ContentHandler contentHandler) throws IOException, SAXException {
-        XMLReader reader = new ExpatReader();
+        XMLReader reader = XmlObjectFactory.newXMLReader();
         reader.setContentHandler(contentHandler);
         InputSource source = new InputSource(in);
         source.setEncoding(encoding.expatName);
@@ -89,7 +89,7 @@
      */
     public static XmlPullParser newPullParser() {
         try {
-            KXmlParser parser = new KXmlParser();
+            XmlPullParser parser = XmlObjectFactory.newXmlPullParser();
             parser.setFeature(XmlPullParser.FEATURE_PROCESS_DOCDECL, true);
             parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
             return parser;
@@ -102,25 +102,7 @@
      * Creates a new xml serializer.
      */
     public static XmlSerializer newSerializer() {
-        try {
-            return XmlSerializerFactory.instance.newSerializer();
-        } catch (XmlPullParserException e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    /** Factory for xml serializers. Initialized on demand. */
-    static class XmlSerializerFactory {
-        static final String TYPE
-                = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer";
-        static final XmlPullParserFactory instance;
-        static {
-            try {
-                instance = XmlPullParserFactory.newInstance(TYPE, null);
-            } catch (XmlPullParserException e) {
-                throw new AssertionError(e);
-            }
-        }
+        return XmlObjectFactory.newXmlSerializer();
     }
 
     /**
diff --git a/core/java/android/util/jar/StrictJarFile.java b/core/java/android/util/jar/StrictJarFile.java
index bc4a19d..11aee2f 100644
--- a/core/java/android/util/jar/StrictJarFile.java
+++ b/core/java/android/util/jar/StrictJarFile.java
@@ -390,6 +390,7 @@
     public static class ZipInflaterInputStream extends InflaterInputStream {
         private final ZipEntry entry;
         private long bytesRead = 0;
+        private boolean closed;
 
         public ZipInflaterInputStream(InputStream is, Inflater inf, int bsize, ZipEntry entry) {
             super(is, inf, bsize);
@@ -424,6 +425,12 @@
             }
             return super.available() == 0 ? 0 : (int) (entry.getSize() - bytesRead);
         }
+
+        @Override
+        public void close() throws IOException {
+            super.close();
+            closed = true;
+        }
     }
 
     /**
diff --git a/core/java/android/util/jar/StrictJarManifest.java b/core/java/android/util/jar/StrictJarManifest.java
index dbb466c..faec099 100644
--- a/core/java/android/util/jar/StrictJarManifest.java
+++ b/core/java/android/util/jar/StrictJarManifest.java
@@ -44,6 +44,9 @@
 
     private static final byte[] VALUE_SEPARATOR = new byte[] { ':', ' ' };
 
+    /** The attribute name "Name". */
+    static final Attributes.Name ATTRIBUTE_NAME_NAME = new Attributes.Name("Name");
+
     private final Attributes mainAttributes;
     private final HashMap<String, Attributes> entries;
 
@@ -276,7 +279,7 @@
         Iterator<String> i = manifest.getEntries().keySet().iterator();
         while (i.hasNext()) {
             String key = i.next();
-            writeEntry(out, Attributes.Name.NAME, key, encoder, buffer);
+            writeEntry(out, ATTRIBUTE_NAME_NAME, key, encoder, buffer);
             Attributes attributes = manifest.entries.get(key);
             Iterator<?> entries = attributes.keySet().iterator();
             while (entries.hasNext()) {
diff --git a/core/java/android/util/jar/StrictJarManifestReader.java b/core/java/android/util/jar/StrictJarManifestReader.java
index 9881bb0..b17abc8 100644
--- a/core/java/android/util/jar/StrictJarManifestReader.java
+++ b/core/java/android/util/jar/StrictJarManifestReader.java
@@ -58,7 +58,7 @@
     public void readEntries(Map<String, Attributes> entries, Map<String, StrictJarManifest.Chunk> chunks) throws IOException {
         int mark = pos;
         while (readHeader()) {
-            if (!Attributes.Name.NAME.equals(name)) {
+            if (!StrictJarManifest.ATTRIBUTE_NAME_NAME.equals(name)) {
                 throw new IOException("Entry is not named");
             }
             String entryNameValue = value;
diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java
index ca54bef..9f7560c 100644
--- a/core/java/android/view/AccessibilityIterators.java
+++ b/core/java/android/view/AccessibilityIterators.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Configuration;
 
 import java.text.BreakIterator;
@@ -45,6 +46,7 @@
      */
     public static abstract class AbstractTextSegmentIterator implements TextSegmentIterator {
 
+        @UnsupportedAppUsage
         protected String mText;
 
         private final int[] mSegment = new int[2];
diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java
index 353b4c2..cd7e67e 100644
--- a/core/java/android/view/ActionProvider.java
+++ b/core/java/android/view/ActionProvider.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.util.Log;
 
@@ -218,6 +219,7 @@
     /**
      * @hide Internal use only
      */
+    @UnsupportedAppUsage
     public void setSubUiVisibilityListener(SubUiVisibilityListener listener) {
         mSubUiVisibilityListener = listener;
     }
@@ -240,6 +242,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void reset() {
         mVisibilityListener = null;
         mSubUiVisibilityListener = null;
diff --git a/core/java/android/view/AppTransitionAnimationSpec.java b/core/java/android/view/AppTransitionAnimationSpec.java
index 86a5fb7..6585e40 100644
--- a/core/java/android/view/AppTransitionAnimationSpec.java
+++ b/core/java/android/view/AppTransitionAnimationSpec.java
@@ -1,5 +1,6 @@
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.os.Parcel;
@@ -18,6 +19,7 @@
     public final GraphicBuffer buffer;
     public final Rect rect;
 
+    @UnsupportedAppUsage
     public AppTransitionAnimationSpec(int taskId, GraphicBuffer buffer, Rect rect) {
         this.taskId = taskId;
         this.rect = rect;
diff --git a/core/java/android/view/BatchedInputEventReceiver.java b/core/java/android/view/BatchedInputEventReceiver.java
index b1d28e0..61ccac9 100644
--- a/core/java/android/view/BatchedInputEventReceiver.java
+++ b/core/java/android/view/BatchedInputEventReceiver.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Looper;
 
 /**
@@ -26,6 +27,7 @@
     Choreographer mChoreographer;
     private boolean mBatchedInputScheduled;
 
+    @UnsupportedAppUsage
     public BatchedInputEventReceiver(
             InputChannel inputChannel, Looper looper, Choreographer choreographer) {
         super(inputChannel, looper);
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index f8cfd0d..ce16ffc 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -20,6 +20,7 @@
 import static android.view.DisplayEventReceiver.VSYNC_SOURCE_SURFACE_FLINGER;
 
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.hardware.display.DisplayManagerGlobal;
 import android.os.Handler;
 import android.os.Looper;
@@ -130,6 +131,7 @@
             };
 
     // Enable/disable vsync for animations and drawing.
+    @UnsupportedAppUsage
     private static final boolean USE_VSYNC = SystemProperties.getBoolean(
             "debug.choreographer.vsync", true);
 
@@ -151,6 +153,7 @@
         public String toString() { return "FRAME_CALLBACK_TOKEN"; }
     };
 
+    @UnsupportedAppUsage
     private final Object mLock = new Object();
 
     private final Looper mLooper;
@@ -159,15 +162,19 @@
     // The display event receiver can only be accessed by the looper thread to which
     // it is attached.  We take care to ensure that we post message to the looper
     // if appropriate when interacting with the display event receiver.
+    @UnsupportedAppUsage
     private final FrameDisplayEventReceiver mDisplayEventReceiver;
 
     private CallbackRecord mCallbackPool;
 
+    @UnsupportedAppUsage
     private final CallbackQueue[] mCallbackQueues;
 
     private boolean mFrameScheduled;
     private boolean mCallbacksRunning;
+    @UnsupportedAppUsage
     private long mLastFrameTimeNanos;
+    @UnsupportedAppUsage
     private long mFrameIntervalNanos;
     private boolean mDebugPrintNextFrameTimeDelta;
     private int mFPSDivisor = 1;
@@ -265,6 +272,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static Choreographer getSfInstance() {
         return sSfThreadInstance.get();
     }
@@ -556,6 +564,7 @@
      * @throws IllegalStateException if no frame is in progress.
      * @hide
      */
+    @UnsupportedAppUsage
     public long getFrameTime() {
         return getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
     }
@@ -568,6 +577,7 @@
      * @throws IllegalStateException if no frame is in progress.
      * @hide
      */
+    @UnsupportedAppUsage
     public long getFrameTimeNanos() {
         synchronized (mLock) {
             if (!mCallbacksRunning) {
@@ -627,6 +637,7 @@
         ThreadedRenderer.setFPSDivisor(divisor);
     }
 
+    @UnsupportedAppUsage
     void doFrame(long frameTimeNanos, int frame) {
         final long startNanos;
         synchronized (mLock) {
@@ -792,6 +803,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void scheduleVsyncLocked() {
         mDisplayEventReceiver.scheduleVsync();
     }
@@ -942,6 +954,7 @@
         public Object action; // Runnable or FrameCallback
         public Object token;
 
+        @UnsupportedAppUsage
         public void run(long frameTimeNanos) {
             if (token == FRAME_CALLBACK_TOKEN) {
                 ((FrameCallback)action).doFrame(frameTimeNanos);
@@ -978,6 +991,7 @@
             return callbacks;
         }
 
+        @UnsupportedAppUsage
         public void addCallbackLocked(long dueTime, Object action, Object token) {
             CallbackRecord callback = obtainCallbackLocked(dueTime, action, token);
             CallbackRecord entry = mHead;
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index d3cc175..c77500a 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.res.AssetManager;
@@ -28,10 +29,14 @@
  * wrapped context.
  */
 public class ContextThemeWrapper extends ContextWrapper {
+    @UnsupportedAppUsage
     private int mThemeResource;
+    @UnsupportedAppUsage
     private Resources.Theme mTheme;
+    @UnsupportedAppUsage
     private LayoutInflater mInflater;
     private Configuration mOverrideConfiguration;
+    @UnsupportedAppUsage
     private Resources mResources;
 
     /**
@@ -143,6 +148,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public int getThemeResId() {
         return mThemeResource;
     }
@@ -186,6 +192,7 @@
         theme.applyStyle(resId, true);
     }
 
+    @UnsupportedAppUsage
     private void initializeTheme() {
         final boolean first = mTheme == null;
         if (first) {
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 20f8066..4d96fc3 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.UnsupportedAppUsage;
 import android.app.KeyguardManager;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -79,6 +80,7 @@
     private final Resources mResources;
     private DisplayAdjustments mDisplayAdjustments;
 
+    @UnsupportedAppUsage
     private DisplayInfo mDisplayInfo; // never null
     private boolean mIsValid;
 
@@ -231,6 +233,7 @@
      * Display type: Unknown display type.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int TYPE_UNKNOWN = 0;
 
     /**
@@ -243,12 +246,14 @@
      * Display type: HDMI display.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int TYPE_HDMI = 2;
 
     /**
      * Display type: WiFi display.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int TYPE_WIFI = 3;
 
     /**
@@ -261,6 +266,7 @@
      * Display type: Virtual display.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int TYPE_VIRTUAL = 5;
 
     /**
@@ -459,6 +465,7 @@
      * @return True if the display is still valid.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean getDisplayInfo(DisplayInfo outDisplayInfo) {
         synchronized (this) {
             updateDisplayInfoLocked();
@@ -506,6 +513,7 @@
      * @see #TYPE_VIRTUAL
      * @hide
      */
+    @UnsupportedAppUsage
     public int getType() {
         return mType;
     }
@@ -517,6 +525,7 @@
      * @return The display address.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getAddress() {
         return mAddress;
     }
@@ -543,6 +552,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getOwnerPackageName() {
         return mOwnerPackageName;
     }
@@ -553,6 +563,7 @@
      * @return The display adjustments holder, or null if none is required.
      * @hide
      */
+    @UnsupportedAppUsage
     public DisplayAdjustments getDisplayAdjustments() {
         if (mResources != null) {
             final DisplayAdjustments currentAdjustements = mResources.getDisplayAdjustments();
@@ -676,6 +687,7 @@
      * mostly for wallpapers.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getMaximumSizeDimension() {
         synchronized (this) {
             updateDisplayInfoLocked();
@@ -1184,6 +1196,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public Mode(int modeId, int width, int height, float refreshRate) {
             mModeId = modeId;
             mWidth = width;
@@ -1360,6 +1373,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public HdrCapabilities(int[] supportedHdrTypes, float maxLuminance,
                 float maxAverageLuminance, float minLuminance) {
             mSupportedHdrTypes = supportedHdrTypes;
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
index 790029b..da4d92fa 100644
--- a/core/java/android/view/DisplayAdjustments.java
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 
@@ -28,6 +29,7 @@
     private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
     private Configuration mConfiguration;
 
+    @UnsupportedAppUsage
     public DisplayAdjustments() {
     }
 
@@ -42,6 +44,7 @@
                 ? daj.mConfiguration : Configuration.EMPTY);
     }
 
+    @UnsupportedAppUsage
     public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
         if (this == DEFAULT_DISPLAY_ADJUSTMENTS) {
             throw new IllegalArgumentException(
@@ -67,6 +70,7 @@
         mConfiguration.setTo(configuration != null ? configuration : Configuration.EMPTY);
     }
 
+    @UnsupportedAppUsage
     public Configuration getConfiguration() {
         return mConfiguration;
     }
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index 47bda53..5f80d31 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -29,6 +29,7 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
+import android.graphics.Region.Op;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -324,15 +325,11 @@
      *
      * @hide
      */
+    @VisibleForTesting
     public static DisplayCutout fromBoundingRect(int left, int top, int right, int bottom) {
-        Path path = new Path();
-        path.reset();
-        path.moveTo(left, top);
-        path.lineTo(left, bottom);
-        path.lineTo(right, bottom);
-        path.lineTo(right, top);
-        path.close();
-        return fromBounds(path);
+        Region r = Region.obtain();
+        r.set(left, top, right, bottom);
+        return fromBounds(r);
     }
 
     /**
@@ -340,26 +337,19 @@
      *
      * @hide
      */
-    public static DisplayCutout fromBounds(Path path) {
-        RectF clipRect = new RectF();
-        path.computeBounds(clipRect, false /* unused */);
-        Region clipRegion = Region.obtain();
-        clipRegion.set((int) clipRect.left, (int) clipRect.top,
-                (int) clipRect.right, (int) clipRect.bottom);
-
-        Region bounds = new Region();
-        bounds.setPath(path, clipRegion);
-        clipRegion.recycle();
-        return new DisplayCutout(ZERO_RECT, bounds, false /* copyArguments */);
+    public static DisplayCutout fromBounds(Region region) {
+        return new DisplayCutout(ZERO_RECT, region, false /* copyArguments */);
     }
 
     /**
-     * Creates the bounding path according to @android:string/config_mainBuiltInDisplayCutout.
+     * Creates the display cutout according to
+     * @android:string/config_mainBuiltInDisplayCutoutRectApproximation, which is the closest
+     * rectangle-base approximation of the cutout.
      *
      * @hide
      */
-    public static DisplayCutout fromResources(Resources res, int displayWidth, int displayHeight) {
-        return fromSpec(res.getString(R.string.config_mainBuiltInDisplayCutout),
+    public static DisplayCutout fromResourcesRectApproximation(Resources res, int displayWidth, int displayHeight) {
+        return fromSpec(res.getString(R.string.config_mainBuiltInDisplayCutoutRectApproximation),
                 displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT);
     }
 
@@ -369,7 +359,8 @@
      * @hide
      */
     public static Path pathFromResources(Resources res, int displayWidth, int displayHeight) {
-        return pathAndDisplayCutoutFromSpec(res.getString(R.string.config_mainBuiltInDisplayCutout),
+        return pathAndDisplayCutoutFromSpec(
+                res.getString(R.string.config_mainBuiltInDisplayCutout),
                 displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT).first;
     }
 
@@ -417,6 +408,7 @@
         }
 
         final Path p;
+        final Region r = Region.obtain();
         try {
             p = PathParser.createPathFromPathData(spec);
         } catch (Throwable e) {
@@ -431,6 +423,11 @@
         m.postTranslate(offsetX, 0);
         p.transform(m);
 
+        final Rect tmpRect = new Rect();
+        toRectAndAddToRegion(p, r, tmpRect);
+        final int topInset = tmpRect.bottom;
+
+        final int bottomInset;
         if (bottomSpec != null) {
             final Path bottomPath;
             try {
@@ -443,9 +440,17 @@
             m.postTranslate(0, displayHeight);
             bottomPath.transform(m);
             p.addPath(bottomPath);
+            toRectAndAddToRegion(bottomPath, r, tmpRect);
+            bottomInset = displayHeight - tmpRect.top;
+        } else {
+            bottomInset = 0;
         }
 
-        final Pair<Path, DisplayCutout> result = new Pair<>(p, fromBounds(p));
+        // Reuse tmpRect as the inset rect we store into the DisplayCutout instance.
+        tmpRect.set(0, topInset, 0, bottomInset);
+        final DisplayCutout cutout = new DisplayCutout(tmpRect, r, false /* copyArguments */);
+
+        final Pair<Path, DisplayCutout> result = new Pair<>(p, cutout);
         synchronized (CACHE_LOCK) {
             sCachedSpec = spec;
             sCachedDisplayWidth = displayWidth;
@@ -456,6 +461,13 @@
         return result;
     }
 
+    private static void toRectAndAddToRegion(Path p, Region inoutRegion, Rect inoutRect) {
+        final RectF rectF = new RectF();
+        p.computeBounds(rectF, false /* unused */);
+        rectF.round(inoutRect);
+        inoutRegion.op(inoutRect, Op.UNION);
+    }
+
     private static Region boundingRectsToRegion(List<Rect> rects) {
         Region result = Region.obtain();
         if (rects != null) {
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index cb98c88..edd3f1a 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.util.Log;
@@ -56,6 +57,7 @@
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
+    @UnsupportedAppUsage
     private long mReceiverPtr;
 
     // We keep a reference message queue object here so that it is not
@@ -73,6 +75,7 @@
      *
      * @param looper The looper to use when invoking callbacks.
      */
+    @UnsupportedAppUsage
     public DisplayEventReceiver(Looper looper) {
         this(looper, VSYNC_SOURCE_APP);
     }
@@ -137,6 +140,7 @@
      * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_MAIN}.
      * @param frame The frame number.  Increases by one for each vertical sync interval.
      */
+    @UnsupportedAppUsage
     public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
     }
 
@@ -149,6 +153,7 @@
      * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_HDMI}.
      * @param connected True if the display is connected, false if it disconnected.
      */
+    @UnsupportedAppUsage
     public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
     }
 
@@ -156,6 +161,7 @@
      * Schedules a single vertical sync pulse to be delivered when the next
      * display frame begins.
      */
+    @UnsupportedAppUsage
     public void scheduleVsync() {
         if (mReceiverPtr == 0) {
             Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
@@ -167,12 +173,14 @@
 
     // Called from native code.
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
         onVsync(timestampNanos, builtInDisplayId, frame);
     }
 
     // Called from native code.
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void dispatchHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
         onHotplug(timestampNanos, builtInDisplayId, connected);
     }
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 2421ba4..34bcbdd 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -23,6 +23,7 @@
 import static android.view.DisplayInfoProto.NAME;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
@@ -116,6 +117,7 @@
      * Represents the usable size of the display which may be smaller than the
      * physical size when the system is emulating a smaller display.
      */
+    @UnsupportedAppUsage
     public int logicalWidth;
 
     /**
@@ -123,6 +125,7 @@
      * Represents the usable size of the display which may be smaller than the
      * physical size when the system is emulating a smaller display.
      */
+    @UnsupportedAppUsage
     public int logicalHeight;
 
     /**
@@ -155,6 +158,7 @@
      * @hide
      */
     @Nullable
+    @UnsupportedAppUsage
     public DisplayCutout displayCutout;
 
     /**
@@ -168,6 +172,7 @@
      * </p>
      */
     @Surface.Rotation
+    @UnsupportedAppUsage
     public int rotation;
 
     /**
@@ -275,6 +280,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     public DisplayInfo() {
     }
 
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index df4d5c4..4b946d7 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Bitmap;
 import android.graphics.CanvasProperty;
 import android.graphics.Paint;
@@ -39,7 +40,7 @@
     // view hierarchy because display lists are generated recursively.
     private static final int POOL_LIMIT = 25;
 
-    private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
+    public static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
 
     private static final SynchronizedPool<DisplayListCanvas> sPool =
             new SynchronizedPool<>(POOL_LIMIT);
@@ -155,6 +156,7 @@
      *
      * @param drawGLFunction A native function pointer
      */
+    @UnsupportedAppUsage
     public void callDrawGLFunction2(long drawGLFunction) {
         nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction, null);
     }
@@ -171,6 +173,7 @@
      * any references to the functor, just that the reference from this specific
      * canvas's display list has been released.
      */
+    @UnsupportedAppUsage
     public void drawGLFunctor2(long drawGLFunctor, @Nullable Runnable releasedCallback) {
         nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunctor, releasedCallback);
     }
@@ -184,6 +187,7 @@
      *
      * @param renderNode The RenderNode to draw.
      */
+    @UnsupportedAppUsage
     public void drawRenderNode(RenderNode renderNode) {
         nDrawRenderNode(mNativeCanvasWrapper, renderNode.mNativeRenderNode);
     }
@@ -205,6 +209,7 @@
     // Drawing
     ///////////////////////////////////////////////////////////////////////////
 
+    @UnsupportedAppUsage
     public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
             CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
         nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index 2c9f871..bd4dda2 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.os.Parcel;
@@ -129,7 +130,9 @@
 
     int mAction;
     float mX, mY;
+    @UnsupportedAppUsage
     ClipDescription mClipDescription;
+    @UnsupportedAppUsage
     ClipData mClipData;
     IDragAndDropPermissions mDragAndDropPermissions;
 
@@ -313,6 +316,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static DragEvent obtain(DragEvent source) {
         return obtain(source.mAction, source.mX, source.mY, source.mLocalState,
                 source.mClipDescription, source.mClipData, source.mDragAndDropPermissions,
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 358a2d1..dcdef3e 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -249,6 +250,7 @@
         Index.INTENDED_VSYNC, Index.FRAME_COMPLETED,
     };
 
+    @UnsupportedAppUsage
     /* package */ final long[] mTimingData;
 
     /**
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
index 9e81de0..597089b 100644
--- a/core/java/android/view/FrameMetricsObserver.java
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Looper;
 import android.os.MessageQueue;
 
@@ -31,10 +32,12 @@
  * @hide
  */
 public class FrameMetricsObserver {
+    @UnsupportedAppUsage
     private MessageQueue mMessageQueue;
 
     private WeakReference<Window> mWindow;
 
+    @UnsupportedAppUsage
     private FrameMetrics mFrameMetrics;
 
     /* package */ Window.OnFrameMetricsAvailableListener mListener;
@@ -63,6 +66,7 @@
 
     // Called by native on the provided Handler
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void notifyDataAvailable(int dropCount) {
         final Window window = mWindow.get();
         if (window != null) {
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index bc2953e..3ee5f1f 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
@@ -216,12 +217,15 @@
         }
     }
 
+    @UnsupportedAppUsage
     private int mTouchSlopSquare;
     private int mDoubleTapTouchSlopSquare;
     private int mDoubleTapSlopSquare;
+    @UnsupportedAppUsage
     private int mMinimumFlingVelocity;
     private int mMaximumFlingVelocity;
 
+    @UnsupportedAppUsage
     private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();
     private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
     private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
@@ -233,6 +237,7 @@
     private static final int TAP = 3;
 
     private final Handler mHandler;
+    @UnsupportedAppUsage
     private final OnGestureListener mListener;
     private OnDoubleTapListener mDoubleTapListener;
     private OnContextClickListener mContextClickListener;
@@ -241,6 +246,7 @@
     private boolean mDeferConfirmSingleTap;
     private boolean mInLongPress;
     private boolean mInContextClick;
+    @UnsupportedAppUsage
     private boolean mAlwaysInTapRegion;
     private boolean mAlwaysInBiggerTapRegion;
     private boolean mIgnoreNextUpEvent;
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index d1b96ba..fa7b067 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -15,6 +15,7 @@
  */
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.widget.FrameLayout;
@@ -91,6 +92,7 @@
         host.transformMatrixToLocal(matrix);
     }
 
+    @UnsupportedAppUsage
     public static GhostView addGhost(View view, ViewGroup viewGroup, Matrix matrix) {
         if (!(view.getParent() instanceof ViewGroup)) {
             throw new IllegalArgumentException("Ghosted views must be parented by a ViewGroup");
@@ -131,10 +133,12 @@
         return ghostView;
     }
 
+    @UnsupportedAppUsage
     public static GhostView addGhost(View view, ViewGroup viewGroup) {
         return addGhost(view, viewGroup, null);
     }
 
+    @UnsupportedAppUsage
     public static void removeGhost(View view) {
         GhostView ghostView = view.mGhostView;
         if (ghostView != null) {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 131fe13..0398b8f 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -223,10 +223,12 @@
 
     /**
      * Determine the preferred edge of the screen to pin the compact options menu against.
-     * @return a Gravity value for the options menu panel
+     *
+     * @param displayId Id of the display where the menu window currently resides.
+     * @return a Gravity value for the options menu panel.
      * @hide
      */
-    int getPreferredOptionsPanelGravity();
+    int getPreferredOptionsPanelGravity(int displayId);
 
     /**
      * Lock the device orientation to the specified rotation, or to the
@@ -421,8 +423,8 @@
     boolean isWindowTraceEnabled();
 
     /**
-     * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
-     * on the next user activity.
+     * Requests that the WindowManager sends
+     * WindowManagerPolicyConstants#ACTION_USER_ACTIVITY_NOTIFICATION on the next user activity.
      */
     void requestUserActivityNotification();
 
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index f868a00..bedfa9f 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -37,15 +37,10 @@
  * {@hide}
  */
 interface IWindowSession {
-    int add(IWindow window, int seq, in WindowManager.LayoutParams attrs,
-            in int viewVisibility, out Rect outContentInsets, out Rect outStableInsets,
-            out InputChannel outInputChannel);
     int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             in int viewVisibility, in int layerStackId, out Rect outFrame,
             out Rect outContentInsets, out Rect outStableInsets, out Rect outOutsets,
             out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel);
-    int addWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
-            in int viewVisibility, out Rect outContentInsets, out Rect outStableInsets);
     int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             in int viewVisibility, in int layerStackId, out Rect outContentInsets,
             out Rect outStableInsets);
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index de195ae..b2dd6ac 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Slog;
@@ -32,6 +33,7 @@
     
     private static final boolean DEBUG = false;
     
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<InputChannel> CREATOR
             = new Parcelable.Creator<InputChannel>() {
         public InputChannel createFromParcel(Parcel source) {
@@ -46,6 +48,7 @@
     };
     
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private long mPtr; // used by native code
     
     private static native InputChannel[] nativeOpenInputChannelPair(String name);
@@ -63,6 +66,7 @@
      * It can be initialized by reading from a Parcel or by transferring the state of
      * another input channel into this one.
      */
+    @UnsupportedAppUsage
     public InputChannel() {
     }
 
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 8405d9e..7295259 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -18,6 +18,7 @@
 
 import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
@@ -53,6 +54,7 @@
     private final int mProductId;
     private final String mDescriptor;
     private final InputDeviceIdentifier mIdentifier;
+    @UnsupportedAppUsage
     private final boolean mIsExternal;
     private final int mSources;
     private final int mKeyboardType;
@@ -405,6 +407,7 @@
     };
 
     // Called by native code.
+    @UnsupportedAppUsage
     private InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
             int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
             KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
@@ -608,6 +611,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isExternal() {
         return mIsExternal;
     }
@@ -739,6 +743,7 @@
     }
 
     // Called from native code.
+    @UnsupportedAppUsage
     private void addMotionRange(int axis, int source,
             float min, float max, float flat, float fuzz, float resolution) {
         mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz, resolution));
diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java
index 1f2aab9..c2848d4 100644
--- a/core/java/android/view/InputEvent.java
+++ b/core/java/android/view/InputEvent.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -95,6 +96,19 @@
     }
 
     /**
+     * Gets the display id of the event.
+     * @return The display id associated with the event.
+     * @hide
+     */
+    public abstract int getDisplayId();
+
+    /**
+     * Modifies the display id associated with the event
+     * @param displayId
+     * @hide
+     */
+    public abstract void setDisplayId(int displayId);
+    /**
      * Copies the event.
      *
      * @return A deep copy of the event.
@@ -214,6 +228,7 @@
      * @return The unique sequence number of this event.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getSequenceNumber() {
         return mSeq;
     }
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index 7e8ec04..e4b1a8d 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.util.Log;
 
@@ -115,6 +116,7 @@
      * @param caller The object to which the verifier is attached.
      * @param flags Flags to the verifier, or 0 if none.
      */
+    @UnsupportedAppUsage
     public InputEventConsistencyVerifier(Object caller, int flags) {
         this(caller, flags, null);
     }
@@ -135,6 +137,7 @@
      * Determines whether the instrumentation should be enabled.
      * @return True if it should be enabled.
      */
+    @UnsupportedAppUsage
     public static boolean isInstrumentationEnabled() {
         return IS_ENG_BUILD;
     }
@@ -319,6 +322,7 @@
      * where a subclass dispatching method delegates to its superclass's dispatching method
      * and both dispatching methods call into the consistency verifier.
      */
+    @UnsupportedAppUsage
     public void onTouchEvent(MotionEvent event, int nestingLevel) {
         if (!startEvent(event, nestingLevel, EVENT_TYPE_TOUCH)) {
             return;
@@ -579,6 +583,7 @@
      * where a subclass dispatching method delegates to its superclass's dispatching method
      * and both dispatching methods call into the consistency verifier.
      */
+    @UnsupportedAppUsage
     public void onUnhandledEvent(InputEvent event, int nestingLevel) {
         if (nestingLevel != mLastNestingLevel) {
             return;
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 20ab539..7260a65 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.util.Log;
@@ -113,6 +114,7 @@
      *
      * @param event The input event that was received.
      */
+    @UnsupportedAppUsage
     public void onInputEvent(InputEvent event) {
         finishInputEvent(event, false);
     }
@@ -180,6 +182,7 @@
 
     // Called from native code.
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void dispatchInputEvent(int seq, InputEvent event) {
         mSeqMap.put(event.getSequenceNumber(), seq);
         onInputEvent(event);
@@ -187,6 +190,7 @@
 
     // Called from native code.
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void dispatchBatchedInputEventPending() {
         onBatchedInputEventPending();
     }
diff --git a/core/java/android/view/InputEventSender.java b/core/java/android/view/InputEventSender.java
index b25fb65..c5f4c23 100644
--- a/core/java/android/view/InputEventSender.java
+++ b/core/java/android/view/InputEventSender.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.util.Log;
@@ -137,6 +138,7 @@
 
     // Called from native code.
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void dispatchInputEventFinished(int seq, boolean handled) {
         onInputEventFinished(seq, handled);
     }
diff --git a/core/java/android/view/InputFilter.java b/core/java/android/view/InputFilter.java
index 0ab4dc0..3aaf31e 100644
--- a/core/java/android/view/InputFilter.java
+++ b/core/java/android/view/InputFilter.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -117,6 +118,7 @@
      *
      * @param looper The looper to run callbacks on.
      */
+    @UnsupportedAppUsage
     public InputFilter(Looper looper) {
         mH = new H(looper);
     }
@@ -186,6 +188,7 @@
      * @param event The input event that was received.
      * @param policyFlags The input event policy flags.
      */
+    @UnsupportedAppUsage
     public void onInputEvent(InputEvent event, int policyFlags) {
         sendInputEvent(event, policyFlags);
     }
diff --git a/core/java/android/view/InputQueue.java b/core/java/android/view/InputQueue.java
index 582ae79..69ebc46 100644
--- a/core/java/android/view/InputQueue.java
+++ b/core/java/android/view/InputQueue.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.util.LongSparseArray;
@@ -100,6 +101,7 @@
         mActiveEventArray.put(id, event);
     }
 
+    @UnsupportedAppUsage
     private void finishInputEvent(long id, boolean handled) {
         int index = mActiveEventArray.indexOfKey(id);
         if (index >= 0) {
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index b7b56e8..989bf67 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.hardware.input.InputManager;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -307,6 +308,7 @@
     }
 
     // Called from native
+    @UnsupportedAppUsage
     private KeyCharacterMap(long ptr) {
         mPtr = ptr;
     }
@@ -748,7 +750,9 @@
 
         private FallbackAction next;
 
+        @UnsupportedAppUsage
         public int keyCode;
+        @UnsupportedAppUsage
         public int metaState;
 
         private FallbackAction() {
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 35546f8..8641d7f 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -16,8 +16,11 @@
 
 package android.view;
 
+import static android.view.Display.INVALID_DISPLAY;
+
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.method.MetaKeyKeyListener;
@@ -835,6 +838,7 @@
 
     // Symbolic names of all metakeys in bit order from least significant to most significant.
     // Accordingly there are exactly 32 values in this table.
+    @UnsupportedAppUsage
     private static final String[] META_SYMBOLIC_NAMES = new String[] {
         "META_SHIFT_ON",
         "META_ALT_ON",
@@ -888,6 +892,7 @@
      */
     public static final int ACTION_UP               = 1;
     /**
+     * @deprecated No longer used by the input system.
      * {@link #getAction} value: multiple duplicate key events have
      * occurred in a row, or a complex string is being delivered.  If the
      * key code is not {#link {@link #KEYCODE_UNKNOWN} then the
@@ -896,6 +901,7 @@
      * Otherwise, if the key code is {@link #KEYCODE_UNKNOWN}, then
      * this is a sequence of characters as returned by {@link #getCharacters}.
      */
+    @Deprecated
     public static final int ACTION_MULTIPLE         = 2;
 
     /**
@@ -903,6 +909,7 @@
      * Reserved for use by {@link MetaKeyKeyListener} for a published constant in its API.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int META_CAP_LOCKED = 0x100;
 
     /**
@@ -910,6 +917,7 @@
      * Reserved for use by {@link MetaKeyKeyListener} for a published constant in its API.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int META_ALT_LOCKED = 0x200;
 
     /**
@@ -917,6 +925,7 @@
      * Reserved for use by {@link MetaKeyKeyListener} for a published constant in its API.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int META_SYM_LOCKED = 0x400;
 
     /**
@@ -925,6 +934,7 @@
      * in its API that is currently being retained for legacy reasons.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int META_SELECTING = 0x800;
 
     /**
@@ -1244,16 +1254,28 @@
 
     private KeyEvent mNext;
 
+    @UnsupportedAppUsage
     private int mDeviceId;
+    @UnsupportedAppUsage
     private int mSource;
+    private int mDisplayId;
+    @UnsupportedAppUsage
     private int mMetaState;
+    @UnsupportedAppUsage
     private int mAction;
+    @UnsupportedAppUsage
     private int mKeyCode;
+    @UnsupportedAppUsage
     private int mScanCode;
+    @UnsupportedAppUsage
     private int mRepeatCount;
+    @UnsupportedAppUsage
     private int mFlags;
+    @UnsupportedAppUsage
     private long mDownTime;
+    @UnsupportedAppUsage
     private long mEventTime;
+    @UnsupportedAppUsage
     private String mCharacters;
 
     public interface Callback {
@@ -1473,6 +1495,7 @@
         mScanCode = scancode;
         mFlags = flags;
         mSource = source;
+        mDisplayId = INVALID_DISPLAY;
     }
 
     /**
@@ -1497,6 +1520,7 @@
         mDeviceId = deviceId;
         mFlags = flags;
         mSource = InputDevice.SOURCE_KEYBOARD;
+        mDisplayId = INVALID_DISPLAY;
     }
 
     /**
@@ -1511,6 +1535,7 @@
         mMetaState = origEvent.mMetaState;
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
+        mDisplayId = origEvent.mDisplayId;
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         mCharacters = origEvent.mCharacters;
@@ -1537,6 +1562,7 @@
         mMetaState = origEvent.mMetaState;
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
+        mDisplayId = origEvent.mDisplayId;
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         mCharacters = origEvent.mCharacters;
@@ -1564,7 +1590,7 @@
      */
     public static KeyEvent obtain(long downTime, long eventTime, int action,
             int code, int repeat, int metaState,
-            int deviceId, int scancode, int flags, int source, String characters) {
+            int deviceId, int scancode, int flags, int source, int displayId, String characters) {
         KeyEvent ev = obtain();
         ev.mDownTime = downTime;
         ev.mEventTime = eventTime;
@@ -1576,11 +1602,27 @@
         ev.mScanCode = scancode;
         ev.mFlags = flags;
         ev.mSource = source;
+        ev.mDisplayId = displayId;
         ev.mCharacters = characters;
         return ev;
     }
 
     /**
+     * Obtains a (potentially recycled) key event.
+     *
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public static KeyEvent obtain(long downTime, long eventTime, int action,
+            int code, int repeat, int metaState,
+            int deviceId, int scancode, int flags, int source, String characters) {
+        return obtain(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode,
+                flags, source, INVALID_DISPLAY, characters);
+    }
+
+    /**
+
+    /**
      * Obtains a (potentially recycled) copy of another key event.
      *
      * @hide
@@ -1597,6 +1639,7 @@
         ev.mScanCode = other.mScanCode;
         ev.mFlags = other.mFlags;
         ev.mSource = other.mSource;
+        ev.mDisplayId = other.mDisplayId;
         ev.mCharacters = other.mCharacters;
         return ev;
     }
@@ -1615,6 +1658,7 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     public final void recycle() {
         super.recycle();
         mCharacters = null;
@@ -1683,6 +1727,7 @@
         mMetaState = origEvent.mMetaState;
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
+        mDisplayId = origEvent.mDisplayId;
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         // Don't copy mCharacters, since one way or the other we'll lose it
@@ -1734,6 +1779,7 @@
      * @deprecated
      * @hide
      */
+    @UnsupportedAppUsage
     @Deprecated public final boolean isDown() {
         return mAction == ACTION_DOWN;
     }
@@ -1795,6 +1841,7 @@
     /** Whether key will, by default, trigger a click on the focused view.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final boolean isConfirmKey(int keyCode) {
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_CENTER:
@@ -1917,6 +1964,18 @@
         mSource = source;
     }
 
+    /** @hide */
+    @Override
+    public final int getDisplayId() {
+        return mDisplayId;
+    }
+
+    /** @hide */
+    @Override
+    public final void setDisplayId(int displayId) {
+        mDisplayId = displayId;
+    }
+
     /**
      * <p>Returns the state of the meta keys.</p>
      *
@@ -1985,6 +2044,7 @@
     }
 
     // Mask of all modifier key meta states.  Specifically excludes locked keys like caps lock.
+    @UnsupportedAppUsage
     private static final int META_MODIFIER_MASK =
             META_SHIFT_ON | META_SHIFT_LEFT_ON | META_SHIFT_RIGHT_ON
             | META_ALT_ON | META_ALT_LEFT_ON | META_ALT_RIGHT_ON
@@ -1993,19 +2053,23 @@
             | META_SYM_ON | META_FUNCTION_ON;
 
     // Mask of all lock key meta states.
+    @UnsupportedAppUsage
     private static final int META_LOCK_MASK =
             META_CAPS_LOCK_ON | META_NUM_LOCK_ON | META_SCROLL_LOCK_ON;
 
     // Mask of all valid meta states.
+    @UnsupportedAppUsage
     private static final int META_ALL_MASK = META_MODIFIER_MASK | META_LOCK_MASK;
 
     // Mask of all synthetic meta states that are reserved for API compatibility with
     // historical uses in MetaKeyKeyListener.
+    @UnsupportedAppUsage
     private static final int META_SYNTHETIC_MASK =
             META_CAP_LOCKED | META_ALT_LOCKED | META_SYM_LOCKED | META_SELECTING;
 
     // Mask of all meta states that are not valid use in specifying a modifier key.
     // These bits are known to be used for purposes other than specifying modifiers.
+    @UnsupportedAppUsage
     private static final int META_INVALID_MODIFIER_MASK =
             META_LOCK_MASK | META_SYNTHETIC_MASK;
 
@@ -2438,7 +2502,10 @@
      *
      * @return Returns a String of 1 or more characters associated with
      * the event.
+     *
+     * @deprecated no longer used by the input system.
      */
+    @Deprecated
     public final String getCharacters() {
         return mCharacters;
     }
@@ -2852,6 +2919,7 @@
         msg.append(", downTime=").append(mDownTime);
         msg.append(", deviceId=").append(mDeviceId);
         msg.append(", source=0x").append(Integer.toHexString(mSource));
+        msg.append(", displayId=").append(mDisplayId);
         msg.append(" }");
         return msg.toString();
     }
@@ -2883,6 +2951,9 @@
      * such as "KEYCODE_A", "KEYCODE_DPAD_UP", or an equivalent numeric constant
      * such as "1001" if unknown.
      *
+     * This function is intended to be used mostly for debugging, logging, and testing. It is not
+     * locale-specific and is not intended to be used in a user-facing manner.
+     *
      * @param keyCode The key code.
      * @return The symbolic name of the specified keycode.
      *
@@ -2983,6 +3054,7 @@
     private KeyEvent(Parcel in) {
         mDeviceId = in.readInt();
         mSource = in.readInt();
+        mDisplayId = in.readInt();
         mAction = in.readInt();
         mKeyCode = in.readInt();
         mRepeatCount = in.readInt();
@@ -2991,6 +3063,7 @@
         mFlags = in.readInt();
         mDownTime = in.readLong();
         mEventTime = in.readLong();
+        mCharacters = in.readString();
     }
 
     @Override
@@ -2999,6 +3072,7 @@
 
         out.writeInt(mDeviceId);
         out.writeInt(mSource);
+        out.writeInt(mDisplayId);
         out.writeInt(mAction);
         out.writeInt(mKeyCode);
         out.writeInt(mRepeatCount);
@@ -3007,5 +3081,6 @@
         out.writeInt(mFlags);
         out.writeLong(mDownTime);
         out.writeLong(mEventTime);
+        out.writeString(mCharacters);
     }
 }
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 47b8d92..c520a99 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -19,6 +19,7 @@
 import android.annotation.LayoutRes;
 import android.annotation.Nullable;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -76,20 +77,28 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected final Context mContext;
 
     // these are optional, set by the caller
+    @UnsupportedAppUsage
     private boolean mFactorySet;
+    @UnsupportedAppUsage
     private Factory mFactory;
+    @UnsupportedAppUsage
     private Factory2 mFactory2;
+    @UnsupportedAppUsage
     private Factory2 mPrivateFactory;
     private Filter mFilter;
 
+    @UnsupportedAppUsage
     final Object[] mConstructorArgs = new Object[2];
 
+    @UnsupportedAppUsage
     static final Class<?>[] mConstructorSignature = new Class[] {
             Context.class, AttributeSet.class};
 
+    @UnsupportedAppUsage
     private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
             new HashMap<String, Constructor<? extends View>>();
 
@@ -105,6 +114,7 @@
 
     private static final String ATTR_LAYOUT = "layout";
 
+    @UnsupportedAppUsage
     private static final int[] ATTRS_THEME = new int[] {
             com.android.internal.R.attr.theme };
 
@@ -327,6 +337,7 @@
     /**
      * @hide for use by framework
      */
+    @UnsupportedAppUsage
     public void setPrivateFactory(Factory2 factory) {
         if (mPrivateFactory == null) {
             mPrivateFactory = factory;
@@ -726,6 +737,7 @@
      * argument and should be used for everything except {@code &gt;include>}
      * tag parsing.
      */
+    @UnsupportedAppUsage
     private View createViewFromTag(View parent, String name, Context context, AttributeSet attrs) {
         return createViewFromTag(parent, name, context, attrs, false);
     }
@@ -745,6 +757,7 @@
      *                        attribute (if set) for the view being inflated,
      *                        {@code false} otherwise
      */
+    @UnsupportedAppUsage
     View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
             boolean ignoreThemeAttr) {
         if (name.equals("view")) {
@@ -893,6 +906,7 @@
         consumeChildElements(parser);
     }
 
+    @UnsupportedAppUsage
     private void parseInclude(XmlPullParser parser, Context context, View parent,
             AttributeSet attrs) throws XmlPullParserException, IOException {
         int type;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 9148c27..29c58dc 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -19,6 +19,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Matrix;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1441,6 +1442,7 @@
     }
 
     // Private value for history pos that obtains the current sample.
+    @UnsupportedAppUsage
     private static final int HISTORY_CURRENT = -0x80000000;
 
     private static final int MAX_RECYCLED = 10;
@@ -1469,6 +1471,7 @@
     }
 
     // Pointer to the native MotionEvent object that contains the actual data.
+    @UnsupportedAppUsage
     private long mNativePtr;
 
     private MotionEvent mNext;
@@ -1502,6 +1505,7 @@
     @FastNative
     private static native long nativeGetEventTimeNanos(long nativePtr, int historyPos);
     @FastNative
+    @UnsupportedAppUsage
     private static native float nativeGetRawAxisValue(long nativePtr,
             int axis, int pointerIndex, int historyPos);
     @FastNative
@@ -1590,6 +1594,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     static private MotionEvent obtain() {
         final MotionEvent ev;
         synchronized (gRecyclerLock) {
@@ -1886,6 +1891,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public MotionEvent copy() {
         return obtain(this);
     }
@@ -1918,6 +1924,7 @@
      * @param scale The scale factor to apply.
      * @hide
      */
+    @UnsupportedAppUsage
     public final void scale(float scale) {
         if (scale != 1.0f) {
             nativeScale(mNativePtr, scale);
@@ -1943,11 +1950,14 @@
     }
 
     /** @hide */
+    @Override
     public int getDisplayId() {
         return nativeGetDisplayId(mNativePtr);
     }
 
     /** @hide */
+    @TestApi
+    @Override
     public void setDisplayId(int displayId) {
         nativeSetDisplayId(mNativePtr, displayId);
     }
@@ -2066,6 +2076,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public final void setDownTime(long downTime) {
         nativeSetDownTimeNanos(mNativePtr, downTime * NS_PER_MS);
     }
@@ -2097,6 +2108,7 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     public final long getEventTimeNano() {
         return nativeGetEventTimeNanos(mNativePtr, HISTORY_CURRENT);
     }
@@ -3096,6 +3108,7 @@
      * @return True if batching was performed or false if batching was not possible.
      * @hide
      */
+    @UnsupportedAppUsage
     public final boolean addBatch(MotionEvent event) {
         final int action = nativeGetAction(mNativePtr);
         if (action != ACTION_MOVE && action != ACTION_HOVER_MOVE) {
@@ -3210,6 +3223,7 @@
      * Gets an integer where each pointer id present in the event is marked as a bit.
      * @hide
      */
+    @UnsupportedAppUsage
     public final int getPointerIdBits() {
         int idBits = 0;
         final int pointerCount = nativeGetPointerCount(mNativePtr);
@@ -3223,6 +3237,7 @@
      * Splits a motion event such that it includes only a subset of pointer ids.
      * @hide
      */
+    @UnsupportedAppUsage
     public final MotionEvent split(int idBits) {
         MotionEvent ev = obtain();
         synchronized (gSharedTempLock) {
@@ -3533,7 +3548,9 @@
      */
     public static final class PointerCoords {
         private static final int INITIAL_PACKED_AXIS_VALUES = 8;
+        @UnsupportedAppUsage
         private long mPackedAxisBits;
+        @UnsupportedAppUsage
         private float[] mPackedAxisValues;
 
         /**
@@ -3553,6 +3570,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static PointerCoords[] createArray(int size) {
             PointerCoords[] array = new PointerCoords[size];
             for (int i = 0; i < size; i++) {
@@ -3846,6 +3864,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static PointerProperties[] createArray(int size) {
             PointerProperties[] array = new PointerProperties[size];
             for (int i = 0; i < size; i++) {
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index a3676ba..81da76d 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.AppOpsManager;
 import android.app.Notification;
 import android.content.Context;
@@ -85,6 +86,7 @@
         this(context, null);
     }
 
+    @UnsupportedAppUsage
     public NotificationHeaderView(Context context, @Nullable AttributeSet attrs) {
         this(context, attrs, 0);
     }
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 8cb46b7..dc097a1 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.XmlRes;
 import android.content.Context;
 import android.content.res.Resources;
@@ -145,14 +146,20 @@
     private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>();
     private static boolean sUseLargeIcons = false;
 
+    @UnsupportedAppUsage
     private final int mType;
     private int mSystemIconResourceId;
+    @UnsupportedAppUsage
     private Bitmap mBitmap;
+    @UnsupportedAppUsage
     private float mHotSpotX;
+    @UnsupportedAppUsage
     private float mHotSpotY;
     // The bitmaps for the additional frame of animated pointer icon. Note that the first frame
     // will be stored in mBitmap.
+    @UnsupportedAppUsage
     private Bitmap mBitmapFrames[];
+    @UnsupportedAppUsage
     private int mDurationPerFrame;
 
     private PointerIcon(int type) {
@@ -312,6 +319,7 @@
      * @throws IllegalArgumentException if context is null.
      * @hide
      */
+    @UnsupportedAppUsage
     public PointerIcon load(@NonNull Context context) {
         if (context == null) {
             throw new IllegalArgumentException("context must not be null");
diff --git a/core/java/android/view/RecordingCanvas.java b/core/java/android/view/RecordingCanvas.java
index 18cc10f..3364483 100644
--- a/core/java/android/view/RecordingCanvas.java
+++ b/core/java/android/view/RecordingCanvas.java
@@ -515,7 +515,7 @@
                             contextStart - paraStart,
                             contextEnd - contextStart,
                             x, y, isRtl, paint.getNativeInstance(),
-                            mp.getNativePtr());
+                            mp.getNativeMeasuredParagraph().getNativePtr());
                     return;
                 }
             }
@@ -536,9 +536,6 @@
             @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset,
             int indexCount, @NonNull Paint paint) {
         checkRange(verts.length, vertOffset, vertexCount);
-        if (isHardwareAccelerated()) {
-            return;
-        }
         if (texs != null) {
             checkRange(texs.length, texOffset, vertexCount);
         }
diff --git a/core/java/android/view/RemoteAnimationAdapter.java b/core/java/android/view/RemoteAnimationAdapter.java
index a864e55..3c9ce78 100644
--- a/core/java/android/view/RemoteAnimationAdapter.java
+++ b/core/java/android/view/RemoteAnimationAdapter.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityOptions;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -61,6 +62,7 @@
      * @param statusBarTransitionDelay The desired delay for all visual animations in the
      *        status bar caused by this app animation in millis.
      */
+    @UnsupportedAppUsage
     public RemoteAnimationAdapter(IRemoteAnimationRunner runner, long duration,
             long statusBarTransitionDelay) {
         mRunner = runner;
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index d2240e1..beb1c1d 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.WindowConfiguration;
 import android.app.WindowConfiguration.ActivityType;
 import android.os.Parcel;
@@ -36,6 +37,7 @@
 
     private final SparseArray<RemoteAnimationAdapterEntry> mTransitionAnimationMap;
 
+    @UnsupportedAppUsage
     public RemoteAnimationDefinition() {
         mTransitionAnimationMap = new SparseArray<>();
     }
@@ -48,6 +50,7 @@
      *                           parameter is involved in the transition.
      * @param adapter The adapter that described how to run the remote animation.
      */
+    @UnsupportedAppUsage
     public void addRemoteAnimation(@TransitionType int transition,
             @ActivityType int activityTypeFilter, RemoteAnimationAdapter adapter) {
         mTransitionAnimationMap.put(transition,
@@ -61,6 +64,7 @@
      * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
      * @param adapter The adapter that described how to run the remote animation.
      */
+    @UnsupportedAppUsage
     public void addRemoteAnimation(@TransitionType int transition, RemoteAnimationAdapter adapter) {
         addRemoteAnimation(transition, ACTIVITY_TYPE_UNDEFINED, adapter);
     }
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index 5b2cc81..567b279 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -16,18 +16,19 @@
 
 package android.view;
 
-import static android.app.RemoteAnimationTargetProto.CLIP_RECT;
-import static android.app.RemoteAnimationTargetProto.CONTENT_INSETS;
-import static android.app.RemoteAnimationTargetProto.IS_TRANSLUCENT;
-import static android.app.RemoteAnimationTargetProto.LEASH;
-import static android.app.RemoteAnimationTargetProto.MODE;
-import static android.app.RemoteAnimationTargetProto.POSITION;
-import static android.app.RemoteAnimationTargetProto.PREFIX_ORDER_INDEX;
-import static android.app.RemoteAnimationTargetProto.SOURCE_CONTAINER_BOUNDS;
-import static android.app.RemoteAnimationTargetProto.TASK_ID;
-import static android.app.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;
+import static android.view.RemoteAnimationTargetProto.CLIP_RECT;
+import static android.view.RemoteAnimationTargetProto.CONTENT_INSETS;
+import static android.view.RemoteAnimationTargetProto.IS_TRANSLUCENT;
+import static android.view.RemoteAnimationTargetProto.LEASH;
+import static android.view.RemoteAnimationTargetProto.MODE;
+import static android.view.RemoteAnimationTargetProto.POSITION;
+import static android.view.RemoteAnimationTargetProto.PREFIX_ORDER_INDEX;
+import static android.view.RemoteAnimationTargetProto.SOURCE_CONTAINER_BOUNDS;
+import static android.view.RemoteAnimationTargetProto.TASK_ID;
+import static android.view.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.app.WindowConfiguration;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -66,21 +67,25 @@
     /**
      * The {@link Mode} to describe whether this app is opening or closing.
      */
+    @UnsupportedAppUsage
     public final @Mode int mode;
 
     /**
      * The id of the task this app belongs to.
      */
+    @UnsupportedAppUsage
     public final int taskId;
 
     /**
      * The {@link SurfaceControl} object to actually control the transform of the app.
      */
+    @UnsupportedAppUsage
     public final SurfaceControl leash;
 
     /**
      * Whether the app is translucent and may reveal apps behind.
      */
+    @UnsupportedAppUsage
     public final boolean isTranslucent;
 
     /**
@@ -89,11 +94,13 @@
      * anything that extends beyond these bounds will not have any effect. This implies that any
      * clip-rect animation should likely stop at these bounds.
      */
+    @UnsupportedAppUsage
     public final Rect clipRect;
 
     /**
      * The insets of the main app window.
      */
+    @UnsupportedAppUsage
     public final Rect contentInsets;
 
     /**
@@ -101,6 +108,7 @@
      * to preserve original z-layer order in the hierarchy tree assuming no "boosting" needs to
      * happen.
      */
+    @UnsupportedAppUsage
     public final int prefixOrderIndex;
 
     /**
@@ -108,6 +116,7 @@
      * is modified from the controlling app, any animation transform needs to be offset by this
      * amount.
      */
+    @UnsupportedAppUsage
     public final Point position;
 
     /**
@@ -115,16 +124,19 @@
      * of the leash is modified from the controlling app, it needs to take the source container
      * bounds into account when calculating the crop.
      */
+    @UnsupportedAppUsage
     public final Rect sourceContainerBounds;
 
     /**
      * The window configuration for the target.
      */
+    @UnsupportedAppUsage
     public final WindowConfiguration windowConfiguration;
 
     /**
      * Whether the task is not presented in Recents UI.
      */
+    @UnsupportedAppUsage
     public boolean isNotInRecents;
 
     public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index e10eeb0..fcea0c3 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -16,8 +16,10 @@
 
 package android.view;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Matrix;
 import android.graphics.Outline;
 import android.graphics.Paint;
@@ -29,6 +31,9 @@
 
 import libcore.util.NativeAllocationRegistry;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * <p>A display list records a series of graphics related operations and can replay
  * them later. Display lists are usually built by recording operations on a
@@ -168,6 +173,7 @@
      *
      * @return A new RenderNode.
      */
+    @UnsupportedAppUsage
     public static RenderNode create(String name, @Nullable View owningView) {
         return new RenderNode(name, owningView);
     }
@@ -207,6 +213,7 @@
      * @see #end(DisplayListCanvas)
      * @see #isValid()
      */
+    @UnsupportedAppUsage
     public DisplayListCanvas start(int width, int height) {
         return DisplayListCanvas.obtain(this, width, height);
     }
@@ -227,6 +234,7 @@
      * @see #start(int, int)
      * @see #isValid()
      */
+    @UnsupportedAppUsage
     public void end(DisplayListCanvas canvas) {
         long displayList = canvas.finishRecording();
         nSetDisplayList(mNativeRenderNode, displayList);
@@ -238,6 +246,7 @@
      * during destruction of hardware resources, to ensure that we do not hold onto
      * obsolete resources after related resources are gone.
      */
+    @UnsupportedAppUsage
     public void discardDisplayList() {
         nSetDisplayList(mNativeRenderNode, 0);
     }
@@ -248,6 +257,7 @@
      *
      * @return boolean true if the display list is able to be replayed, false otherwise.
      */
+    @UnsupportedAppUsage
     public boolean isValid() {
         return nIsValid(mNativeRenderNode);
     }
@@ -294,6 +304,7 @@
      *
      * @param clipToBounds true if the display list should clip to its bounds
      */
+    @UnsupportedAppUsage
     public boolean setClipToBounds(boolean clipToBounds) {
         return nSetClipToBounds(mNativeRenderNode, clipToBounds);
     }
@@ -305,6 +316,7 @@
      * @param shouldProject true if the display list should be projected onto a
      *            containing volume.
      */
+    @UnsupportedAppUsage
     public boolean setProjectBackwards(boolean shouldProject) {
         return nSetProjectBackwards(mNativeRenderNode, shouldProject);
     }
@@ -445,10 +457,30 @@
      * @see android.view.View#hasOverlappingRendering()
      * @see #hasOverlappingRendering()
      */
+    @UnsupportedAppUsage
     public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) {
         return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering);
     }
 
+    /** @hide */
+    @IntDef({USAGE_BACKGROUND})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface UsageHint {}
+
+    /** The default usage hint */
+    public static final int USAGE_UNKNOWN = 0;
+
+    /** Usage is background content */
+    public static final int USAGE_BACKGROUND = 1;
+
+    /**
+     * Provides a hint on what this RenderNode's display list content contains. This hint is used
+     * for automatic content transforms to improve accessibility or similar.
+     */
+    public void setUsageHint(@UsageHint int usageHint) {
+        nSetUsageHint(mNativeRenderNode, usageHint);
+    }
+
     /**
      * Indicates whether the content of this display list overlaps.
      *
@@ -765,6 +797,7 @@
      * @see View#setRight(int)
      * @see View#setBottom(int)
      */
+    @UnsupportedAppUsage
     public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) {
         return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
     }
@@ -777,6 +810,7 @@
      *
      * @see View#offsetLeftAndRight(int)
      */
+    @UnsupportedAppUsage
     public boolean offsetLeftAndRight(int offset) {
         return nOffsetLeftAndRight(mNativeRenderNode, offset);
     }
@@ -797,6 +831,7 @@
      * Outputs the display list to the log. This method exists for use by
      * tools to output display lists for selected nodes to the log.
      */
+    @UnsupportedAppUsage
     public void output() {
         nOutput(mNativeRenderNode);
     }
@@ -948,6 +983,8 @@
     private static native boolean nSetHasOverlappingRendering(long renderNode,
             boolean hasOverlappingRendering);
     @CriticalNative
+    private static native void nSetUsageHint(long renderNode, int usageHint);
+    @CriticalNative
     private static native boolean nSetElevation(long renderNode, float lift);
     @CriticalNative
     private static native boolean nSetTranslationX(long renderNode, float translationX);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index d26a2f6..e48bcfd 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.CanvasProperty;
 import android.graphics.Paint;
 import android.util.SparseIntArray;
@@ -103,10 +104,12 @@
     private long mStartDelay = 0;
     private long mStartTime;
 
+    @UnsupportedAppUsage
     public static int mapViewPropertyToRenderProperty(int viewProperty) {
         return sViewPropertyAnimatorMap.get(viewProperty);
     }
 
+    @UnsupportedAppUsage
     public RenderNodeAnimator(int property, float finalValue) {
         mRenderProperty = property;
         mFinalValue = finalValue;
@@ -114,6 +117,7 @@
         init(nCreateAnimator(property, finalValue));
     }
 
+    @UnsupportedAppUsage
     public RenderNodeAnimator(CanvasProperty<Float> property, float finalValue) {
         init(nCreateCanvasPropertyFloatAnimator(
                 property.getNativeContainer(), finalValue));
@@ -128,6 +132,7 @@
      *            {@link #PAINT_STROKE_WIDTH}
      * @param finalValue The target value for the property
      */
+    @UnsupportedAppUsage
     public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, float finalValue) {
         init(nCreateCanvasPropertyPaintAnimator(
                 property.getNativeContainer(), paintField, finalValue));
@@ -275,6 +280,7 @@
         throw new UnsupportedOperationException();
     }
 
+    @UnsupportedAppUsage
     public void setTarget(View view) {
         mViewTarget = view;
         setTarget(mViewTarget.mRenderNode);
@@ -295,6 +301,7 @@
         mTarget.addAnimator(this);
     }
 
+    @UnsupportedAppUsage
     public void setStartValue(float startValue) {
         checkMutable();
         nSetStartValue(mNativePtr.get(), startValue);
@@ -479,6 +486,7 @@
     }
 
     // Called by native
+    @UnsupportedAppUsage
     private static void callOnFinished(RenderNodeAnimator animator) {
         animator.onFinished();
     }
diff --git a/core/java/android/view/RoundScrollbarRenderer.java b/core/java/android/view/RoundScrollbarRenderer.java
index 1348510..df9e23e 100644
--- a/core/java/android/view/RoundScrollbarRenderer.java
+++ b/core/java/android/view/RoundScrollbarRenderer.java
@@ -31,13 +31,14 @@
     private static final int MAX_SCROLLBAR_ANGLE_SWIPE = 16;
     private static final int MIN_SCROLLBAR_ANGLE_SWIPE = 6;
     private static final float WIDTH_PERCENTAGE = 0.02f;
-    private static final int DEFAULT_THUMB_COLOR = 0x4CFFFFFF;
-    private static final int DEFAULT_TRACK_COLOR = 0x26FFFFFF;
+    private static final int DEFAULT_THUMB_COLOR = 0xFFE8EAED;
+    private static final int DEFAULT_TRACK_COLOR = 0x4CFFFFFF;
 
     private final Paint mThumbPaint = new Paint();
     private final Paint mTrackPaint = new Paint();
     private final RectF mRect = new RectF();
     private final View mParent;
+    private final int mMaskThickness;
 
     public RoundScrollbarRenderer(View parent) {
         // Paints for the round scrollbar.
@@ -52,6 +53,12 @@
         mTrackPaint.setStyle(Paint.Style.STROKE);
 
         mParent = parent;
+
+        // Fetch the resource indicating the thickness of CircularDisplayMask, rounding in the same
+        // way WindowManagerService.showCircularMask does. The scroll bar is inset by this amount so
+        // that it doesn't get clipped.
+        mMaskThickness = parent.getContext().getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.circular_display_mask_thickness);
     }
 
     public void drawRoundScrollbars(Canvas canvas, float alpha, Rect bounds) {
@@ -82,13 +89,13 @@
         startAngle = clamp(startAngle, -SCROLLBAR_ANGLE_RANGE / 2,
                 SCROLLBAR_ANGLE_RANGE / 2 - sweepAngle);
 
-        // Draw the track and the scroll bar.
+        // Draw the track and the thumb.
+        float inset = thumbWidth / 2 + mMaskThickness;
         mRect.set(
-                bounds.left - thumbWidth / 2,
-                bounds.top,
-                bounds.right - thumbWidth / 2,
-                bounds.bottom);
-
+                bounds.left + inset,
+                bounds.top + inset,
+                bounds.right - inset,
+                bounds.bottom - inset);
         canvas.drawArc(mRect, -SCROLLBAR_ANGLE_RANGE / 2, SCROLLBAR_ANGLE_RANGE, false,
                 mTrackPaint);
         canvas.drawArc(mRect, startAngle, sweepAngle, false, mThumbPaint);
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 9787494..c189afe 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Build;
@@ -123,6 +124,7 @@
     }
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private final OnScaleGestureListener mListener;
 
     private float mFocusX;
@@ -141,7 +143,9 @@
     private long mCurrTime;
     private long mPrevTime;
     private boolean mInProgress;
+    @UnsupportedAppUsage
     private int mSpanSlop;
+    @UnsupportedAppUsage
     private int mMinSpan;
 
     private final Handler mHandler;
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index df81a31..427f570 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.CompatibilityInfo.Translator;
 import android.graphics.Canvas;
 import android.graphics.GraphicBuffer;
@@ -60,6 +61,7 @@
             throws OutOfResourcesException;
     private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas);
 
+    @UnsupportedAppUsage
     private static native void nativeRelease(long nativeObject);
     private static native boolean nativeIsValid(long nativeObject);
     private static native boolean nativeIsConsumerRunningBehind(long nativeObject);
@@ -102,9 +104,13 @@
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
     // Guarded state.
+    @UnsupportedAppUsage
     final Object mLock = new Object(); // protects the native state
+    @UnsupportedAppUsage
     private String mName;
+    @UnsupportedAppUsage
     long mNativeObject; // package scope only for SurfaceControl access
+    @UnsupportedAppUsage
     private long mLockedObject;
     private int mGenerationId; // incremented each time mNativeObject changes
     private final Canvas mCanvas = new CompatibleCanvas();
@@ -172,6 +178,7 @@
      * Create an empty surface, which will later be filled in by readFromParcel().
      * @hide
      */
+    @UnsupportedAppUsage
     public Surface() {
     }
 
@@ -203,6 +210,7 @@
     }
 
     /* called from android_view_Surface_createFromIGraphicBufferProducer() */
+    @UnsupportedAppUsage
     private Surface(long nativeObject) {
         synchronized (mLock) {
             setNativeObjectLocked(nativeObject);
@@ -245,6 +253,7 @@
      * called from the process that created the service.
      * @hide
      */
+    @UnsupportedAppUsage
     public void destroy() {
         release();
     }
@@ -293,6 +302,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long getNextFrameNumber() {
         synchronized (mLock) {
             checkNotReleasedLocked();
@@ -485,6 +495,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void copyFrom(SurfaceControl other) {
         if (other == null) {
             throw new IllegalArgumentException("other must not be null");
@@ -544,6 +555,7 @@
      * @deprecated
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void transferFrom(Surface other) {
         if (other == null) {
             throw new IllegalArgumentException("other must not be null");
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index ed8b005..d9c8f30 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -28,6 +28,7 @@
 import static android.view.SurfaceControlProto.NAME;
 
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Bitmap;
 import android.graphics.GraphicBuffer;
 import android.graphics.Matrix;
@@ -179,6 +180,7 @@
     /**
      * Surface creation flag: Surface is created hidden
      */
+    @UnsupportedAppUsage
     public static final int HIDDEN = 0x00000004;
 
     /**
@@ -720,6 +722,7 @@
      */
 
     /** start a transaction */
+    @UnsupportedAppUsage
     public static void openTransaction() {
         synchronized (SurfaceControl.class) {
             if (sGlobalTransaction == null) {
@@ -756,6 +759,7 @@
     }
 
     /** end a transaction */
+    @UnsupportedAppUsage
     public static void closeTransaction() {
         closeTransaction(false);
     }
@@ -811,6 +815,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void setLayer(int zorder) {
         checkNotReleased();
         synchronized(SurfaceControl.class) {
@@ -825,6 +830,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void setPosition(float x, float y) {
         checkNotReleased();
         synchronized(SurfaceControl.class) {
@@ -846,6 +852,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void hide() {
         checkNotReleased();
         synchronized(SurfaceControl.class) {
@@ -853,6 +860,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void show() {
         checkNotReleased();
         synchronized(SurfaceControl.class) {
@@ -986,16 +994,26 @@
      * Describes the properties of a physical display known to surface flinger.
      */
     public static final class PhysicalDisplayInfo {
+        @UnsupportedAppUsage
         public int width;
+        @UnsupportedAppUsage
         public int height;
+        @UnsupportedAppUsage
         public float refreshRate;
+        @UnsupportedAppUsage
         public float density;
+        @UnsupportedAppUsage
         public float xDpi;
+        @UnsupportedAppUsage
         public float yDpi;
+        @UnsupportedAppUsage
         public boolean secure;
+        @UnsupportedAppUsage
         public long appVsyncOffsetNanos;
+        @UnsupportedAppUsage
         public long presentationDeadlineNanos;
 
+        @UnsupportedAppUsage
         public PhysicalDisplayInfo() {
         }
 
@@ -1055,6 +1073,7 @@
         nativeSetDisplayPowerMode(displayToken, mode);
     }
 
+    @UnsupportedAppUsage
     public static SurfaceControl.PhysicalDisplayInfo[] getDisplayConfigs(IBinder displayToken) {
         if (displayToken == null) {
             throw new IllegalArgumentException("displayToken must not be null");
@@ -1097,6 +1116,7 @@
         return nativeSetActiveColorMode(displayToken, colorMode);
     }
 
+    @UnsupportedAppUsage
     public static void setDisplayProjection(IBinder displayToken,
             int orientation, Rect layerStackRect, Rect displayRect) {
         synchronized (SurfaceControl.class) {
@@ -1105,12 +1125,14 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
         synchronized (SurfaceControl.class) {
             sGlobalTransaction.setDisplayLayerStack(displayToken, layerStack);
         }
     }
 
+    @UnsupportedAppUsage
     public static void setDisplaySurface(IBinder displayToken, Surface surface) {
         synchronized (SurfaceControl.class) {
             sGlobalTransaction.setDisplaySurface(displayToken, surface);
@@ -1130,6 +1152,7 @@
         return nativeGetHdrCapabilities(displayToken);
     }
 
+    @UnsupportedAppUsage
     public static IBinder createDisplay(String name, boolean secure) {
         if (name == null) {
             throw new IllegalArgumentException("name must not be null");
@@ -1137,6 +1160,7 @@
         return nativeCreateDisplay(name, secure);
     }
 
+    @UnsupportedAppUsage
     public static void destroyDisplay(IBinder displayToken) {
         if (displayToken == null) {
             throw new IllegalArgumentException("displayToken must not be null");
@@ -1144,6 +1168,7 @@
         nativeDestroyDisplay(displayToken);
     }
 
+    @UnsupportedAppUsage
     public static IBinder getBuiltInDisplay(int builtInDisplayId) {
         return nativeGetBuiltInDisplay(builtInDisplayId);
     }
@@ -1229,6 +1254,7 @@
      * if an error occurs. Make sure to call Bitmap.recycle() as soon as
      * possible, once its content is not needed anymore.
      */
+    @UnsupportedAppUsage
     public static Bitmap screenshot(Rect sourceCrop, int width, int height,
             int minLayer, int maxLayer, boolean useIdentityTransform,
             int rotation) {
@@ -1272,6 +1298,7 @@
      * if an error occurs. Make sure to call Bitmap.recycle() as soon as
      * possible, once its content is not needed anymore.
      */
+    @UnsupportedAppUsage
     public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
         // TODO: should take the display as a parameter
         IBinder displayToken = SurfaceControl.getBuiltInDisplay(
@@ -1285,6 +1312,7 @@
                 false, rotation);
     }
 
+    @UnsupportedAppUsage
     private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
             int width, int height, int minLayer, int maxLayer, boolean allLayers,
             boolean useIdentityTransform) {
@@ -1334,6 +1362,7 @@
         private final ArrayMap<SurfaceControl, Point> mResizedSurfaces = new ArrayMap<>();
         Runnable mFreeNativeResources;
 
+        @UnsupportedAppUsage
         public Transaction() {
             mNativeObject = nativeCreateTransaction();
             mFreeNativeResources
@@ -1344,6 +1373,7 @@
          * Apply the transaction, clearing it's state, and making it usable
          * as a new transaction.
          */
+        @UnsupportedAppUsage
         public void apply() {
             apply(false);
         }
@@ -1378,24 +1408,28 @@
             mResizedSurfaces.clear();
         }
 
+        @UnsupportedAppUsage
         public Transaction show(SurfaceControl sc) {
             sc.checkNotReleased();
             nativeSetFlags(mNativeObject, sc.mNativeObject, 0, SURFACE_HIDDEN);
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction hide(SurfaceControl sc) {
             sc.checkNotReleased();
             nativeSetFlags(mNativeObject, sc.mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction setPosition(SurfaceControl sc, float x, float y) {
             sc.checkNotReleased();
             nativeSetPosition(mNativeObject, sc.mNativeObject, x, y);
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction setSize(SurfaceControl sc, int w, int h) {
             sc.checkNotReleased();
             mResizedSurfaces.put(sc, new Point(w, h));
@@ -1403,6 +1437,7 @@
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction setLayer(SurfaceControl sc, int z) {
             sc.checkNotReleased();
             nativeSetLayer(mNativeObject, sc.mNativeObject, z);
@@ -1423,12 +1458,14 @@
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction setAlpha(SurfaceControl sc, float alpha) {
             sc.checkNotReleased();
             nativeSetAlpha(mNativeObject, sc.mNativeObject, alpha);
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction setMatrix(SurfaceControl sc,
                 float dsdx, float dtdx, float dtdy, float dsdy) {
             sc.checkNotReleased();
@@ -1437,6 +1474,7 @@
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction setMatrix(SurfaceControl sc, Matrix matrix, float[] float9) {
             matrix.getValues(float9);
             setMatrix(sc, float9[MSCALE_X], float9[MSKEW_Y],
@@ -1445,6 +1483,7 @@
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
             sc.checkNotReleased();
             if (crop != null) {
@@ -1457,6 +1496,7 @@
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction setFinalCrop(SurfaceControl sc, Rect crop) {
             sc.checkNotReleased();
             if (crop != null) {
@@ -1475,6 +1515,7 @@
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction deferTransactionUntil(SurfaceControl sc, IBinder handle,
                 long frameNumber) {
             if (frameNumber < 0) {
@@ -1485,6 +1526,7 @@
             return this;
         }
 
+        @UnsupportedAppUsage
         public Transaction deferTransactionUntilSurface(SurfaceControl sc, Surface barrierSurface,
                 long frameNumber) {
             if (frameNumber < 0) {
@@ -1527,6 +1569,7 @@
          * Sets a color for the Surface.
          * @param color A float array with three values to represent r, g, b in range [0..1]
          */
+        @UnsupportedAppUsage
         public Transaction setColor(SurfaceControl sc, @Size(3) float[] color) {
             sc.checkNotReleased();
             nativeSetColor(mNativeObject, sc.mNativeObject, color);
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
index ee08bf7..a4fa12a 100644
--- a/core/java/android/view/SurfaceSession.java
+++ b/core/java/android/view/SurfaceSession.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * An instance of this class represents a connection to the surface
  * flinger, from which you can create one or more Surface instances that will
@@ -24,6 +26,7 @@
  */
 public final class SurfaceSession {
     // Note: This field is accessed by native code.
+    @UnsupportedAppUsage
     private long mNativeClient; // SurfaceComposerClient*
 
     private static native long nativeCreate();
@@ -32,6 +35,7 @@
     private static native void nativeKill(long ptr);
 
     /** Create a new connection with the surface flinger. */
+    @UnsupportedAppUsage
     public SurfaceSession() {
         mNativeClient = nativeCreate();
     }
@@ -62,6 +66,7 @@
      * Unlike destroy(), after this call any surfaces that were created
      * from the session will no longer work.
      */
+    @UnsupportedAppUsage
     public void kill() {
         nativeKill(mNativeClient);
     }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index db34856..6319a8f 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -20,6 +20,7 @@
 import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER;
 import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.CompatibilityInfo.Translator;
 import android.content.res.Configuration;
@@ -98,13 +99,17 @@
     private static final String TAG = "SurfaceView";
     private static final boolean DEBUG = false;
 
+    @UnsupportedAppUsage
     final ArrayList<SurfaceHolder.Callback> mCallbacks
             = new ArrayList<SurfaceHolder.Callback>();
 
     final int[] mLocation = new int[2];
 
+    @UnsupportedAppUsage
     final ReentrantLock mSurfaceLock = new ReentrantLock();
+    @UnsupportedAppUsage
     final Surface mSurface = new Surface();       // Current surface in use
+    @UnsupportedAppUsage
     boolean mDrawingStopped = true;
     // We use this to track if the application has produced a frame
     // in to the Surface. Up until that point, we should be careful not to punch
@@ -123,6 +128,7 @@
 
     int mSubLayer = APPLICATION_MEDIA_SUBLAYER;
 
+    @UnsupportedAppUsage
     boolean mIsCreating = false;
     private volatile boolean mRtHandlingPositionUpdates = false;
 
@@ -134,6 +140,7 @@
                     }
             };
 
+    @UnsupportedAppUsage
     private final ViewTreeObserver.OnPreDrawListener mDrawListener =
             new ViewTreeObserver.OnPreDrawListener() {
                 @Override
@@ -151,15 +158,20 @@
     boolean mViewVisibility = false;
     boolean mWindowStopped = false;
 
+    @UnsupportedAppUsage
     int mRequestedWidth = -1;
+    @UnsupportedAppUsage
     int mRequestedHeight = -1;
     /* Set SurfaceView's format to 565 by default to maintain backward
      * compatibility with applications assuming this format.
      */
+    @UnsupportedAppUsage
     int mRequestedFormat = PixelFormat.RGB_565;
 
+    @UnsupportedAppUsage
     boolean mHaveFrame = false;
     boolean mSurfaceCreated = false;
+    @UnsupportedAppUsage
     long mLastLockTime = 0;
 
     boolean mVisible = false;
@@ -167,7 +179,9 @@
     int mWindowSpaceTop = -1;
     int mSurfaceWidth = -1;
     int mSurfaceHeight = -1;
+    @UnsupportedAppUsage
     int mFormat = -1;
+    @UnsupportedAppUsage
     final Rect mSurfaceFrame = new Rect();
     int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
     private Translator mTranslator;
@@ -340,6 +354,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     protected boolean setFrame(int left, int top, int right, int bottom) {
         boolean result = super.setFrame(left, top, right, bottom);
         updateSurface();
@@ -579,7 +594,7 @@
                                     0.0f, 0.0f,
                                     mScreenRect.height() / (float) mSurfaceHeight);
                         }
-                        if (sizeChanged) {
+                        if (sizeChanged && !creating) {
                             mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);
                         }
                     } finally {
@@ -814,6 +829,7 @@
      * Called by native by a Rendering Worker thread to update the window position
      * @hide
      */
+    @UnsupportedAppUsage
     public final void updateSurfacePosition_renderWorker(long frameNumber,
             int left, int top, int right, int bottom) {
         if (mSurfaceControl == null) {
@@ -854,6 +870,7 @@
      * draw tree. UI thread is blocked at this point.
      * @hide
      */
+    @UnsupportedAppUsage
     public final void surfacePositionLost_uiRtSync(long frameNumber) {
         if (DEBUG) {
             Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
@@ -909,6 +926,7 @@
      * @return true if the surface has dimensions that are fixed in size
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isFixedSize() {
         return (mRequestedWidth != -1 || mRequestedHeight != -1);
     }
@@ -928,6 +946,7 @@
         mSurfaceControl.setBackgroundColor(bgColor);
     }
 
+    @UnsupportedAppUsage
     private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
         private static final String LOG_TAG = "SurfaceHolder";
 
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 371794045..997e48fe 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -106,11 +107,14 @@
 public class TextureView extends View {
     private static final String LOG_TAG = "TextureView";
 
+    @UnsupportedAppUsage
     private TextureLayer mLayer;
+    @UnsupportedAppUsage
     private SurfaceTexture mSurface;
     private SurfaceTextureListener mListener;
     private boolean mHadSurface;
 
+    @UnsupportedAppUsage
     private boolean mOpaque = true;
 
     private final Matrix mMatrix = new Matrix();
@@ -118,6 +122,7 @@
 
     private final Object[] mLock = new Object[0];
     private boolean mUpdateLayer;
+    @UnsupportedAppUsage
     private boolean mUpdateSurface;
 
     private Canvas mCanvas;
@@ -125,6 +130,7 @@
 
     private final Object[] mNativeWindowLock = new Object[0];
     // Set by native code, do not write!
+    @UnsupportedAppUsage
     private long mNativeWindow;
 
     /**
@@ -217,6 +223,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     protected void onDetachedFromWindowInternal() {
         destroyHardwareLayer();
         releaseSurfaceTexture();
@@ -227,11 +234,13 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     protected void destroyHardwareResources() {
         super.destroyHardwareResources();
         destroyHardwareLayer();
     }
 
+    @UnsupportedAppUsage
     private void destroyHardwareLayer() {
         if (mLayer != null) {
             mLayer.detachSurfaceTexture();
@@ -786,6 +795,7 @@
         mListener = listener;
     }
 
+    @UnsupportedAppUsage
     private final SurfaceTexture.OnFrameAvailableListener mUpdateListener =
             new SurfaceTexture.OnFrameAvailableListener() {
         @Override
@@ -839,7 +849,9 @@
         public void onSurfaceTextureUpdated(SurfaceTexture surface);
     }
 
+    @UnsupportedAppUsage
     private native void nCreateNativeWindow(SurfaceTexture surface);
+    @UnsupportedAppUsage
     private native void nDestroyNativeWindow();
 
     private static native boolean nLockCanvas(long nativeWindow, Canvas canvas, Rect dirty);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2f975b6..6737839 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -276,6 +277,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void setupDiskCache(File cacheDir) {
         ThreadedRenderer.setupShadersDiskCache(
                 new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
@@ -719,6 +721,7 @@
      * @param placeFront If true, the render node will be placed in front of the content node,
      *                   otherwise behind the content node.
      */
+    @UnsupportedAppUsage
     public void addRenderNode(RenderNode node, boolean placeFront) {
         nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
     }
@@ -727,6 +730,7 @@
      * Only especially added render nodes can be removed.
      * @param node The node which was added via addRenderNode which should get removed again.
      */
+    @UnsupportedAppUsage
     public void removeRenderNode(RenderNode node) {
         nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
     }
@@ -736,6 +740,7 @@
      * nodes will get drawn and the content remains untouched.
      * @param node The node to be drawn.
      */
+    @UnsupportedAppUsage
     public void drawRenderNode(RenderNode node) {
         nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
     }
@@ -749,6 +754,7 @@
      * @param right The right side of the protected bounds.
      * @param bottom The bottom side of the protected bounds.
      */
+    @UnsupportedAppUsage
     public void setContentDrawBounds(int left, int top, int right, int bottom) {
         nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
     }
@@ -929,6 +935,7 @@
      * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
      * not the RenderNode from a View.
      **/
+    @UnsupportedAppUsage
     public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
         return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
     }
@@ -955,6 +962,10 @@
         nSetDebuggingEnabled(enable);
     }
 
+    void allocateBuffers(Surface surface) {
+        nAllocateBuffers(mNativeProxy, surface);
+    }
+
     @Override
     protected void finalize() throws Throwable {
         try {
@@ -1243,4 +1254,5 @@
     private static native void nSetDebuggingEnabled(boolean enabled);
     private static native void nSetIsolatedProcess(boolean enabled);
     private static native void nSetContextPriority(int priority);
+    private static native void nAllocateBuffers(long nativeProxy, Surface window);
 }
diff --git a/core/java/android/view/TouchDelegate.java b/core/java/android/view/TouchDelegate.java
index d6c43e8..b361ab4 100644
--- a/core/java/android/view/TouchDelegate.java
+++ b/core/java/android/view/TouchDelegate.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 
 /**
@@ -51,6 +52,7 @@
     /**
      * True if the delegate had been targeted on a down event (intersected mBounds).
      */
+    @UnsupportedAppUsage
     private boolean mDelegateTargeted;
 
     /**
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 22b5cca..7154f2b 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.Pools.SynchronizedPool;
 
 /**
@@ -68,6 +69,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static VelocityTracker obtain(String strategy) {
         if (strategy == null) {
             return obtain();
@@ -235,21 +237,25 @@
         /**
          * Polynomial coefficients describing motion in X.
          */
+        @UnsupportedAppUsage
         public final float[] xCoeff = new float[MAX_DEGREE + 1];
 
         /**
          * Polynomial coefficients describing motion in Y.
          */
+        @UnsupportedAppUsage
         public final float[] yCoeff = new float[MAX_DEGREE + 1];
 
         /**
          * Polynomial degree, or zero if only position information is available.
          */
+        @UnsupportedAppUsage
         public int degree;
 
         /**
          * Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit).
          */
+        @UnsupportedAppUsage
         public float confidence;
 
         /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 546ea87..9bc53ed 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -35,6 +35,7 @@
 import android.annotation.Size;
 import android.annotation.TestApi;
 import android.annotation.UiThread;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ClipData;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -777,6 +778,7 @@
 @UiThread
 public class View implements Drawable.Callback, KeyEvent.Callback,
         AccessibilityEventSource {
+    @UnsupportedAppUsage
     private static final boolean DBG = false;
 
     /** @hide */
@@ -799,6 +801,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
 
     /**
@@ -2157,6 +2160,7 @@
     /**
      * Map used to store views' tags.
      */
+    @UnsupportedAppUsage
     private SparseArray<Object> mKeyedTags;
 
     /**
@@ -2175,6 +2179,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "measurement")
+    @UnsupportedAppUsage
     int mMeasuredWidth;
 
     /**
@@ -2182,6 +2187,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "measurement")
+    @UnsupportedAppUsage
     int mMeasuredHeight;
 
     /**
@@ -2193,6 +2199,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     boolean mRecreateDisplayList = false;
 
     /**
@@ -2219,6 +2226,7 @@
     private int mAutofillViewId = NO_ID;
 
     // ID for accessibility purposes. This ID must be unique for every window
+    @UnsupportedAppUsage
     private int mAccessibilityViewId = NO_ID;
 
     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
@@ -2230,6 +2238,7 @@
      * @see #setTag(Object)
      * @see #getTag()
      */
+    @UnsupportedAppUsage
     protected Object mTag = null;
 
     // for mPrivateFlags:
@@ -3522,6 +3531,7 @@
      * Flag to make the status bar not expandable.  Unless you also
      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
      */
+    @UnsupportedAppUsage
     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
 
     /**
@@ -3576,6 +3586,7 @@
      * Flag to hide only the home button.  Don't use this
      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
      */
+    @UnsupportedAppUsage
     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
 
     /**
@@ -3587,6 +3598,7 @@
      * Flag to hide only the back button. Don't use this
      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
      */
+    @UnsupportedAppUsage
     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
 
     /**
@@ -3609,6 +3621,7 @@
      * Flag to hide only the recent apps button. Don't use this
      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
      */
+    @UnsupportedAppUsage
     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
 
     /**
@@ -3640,6 +3653,7 @@
      *
      * Flag to specify that the navigation bar is displayed in transient mode.
      */
+    @UnsupportedAppUsage
     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
 
     /**
@@ -3813,11 +3827,13 @@
      *
      * @see #getParent()
      */
+    @UnsupportedAppUsage
     protected ViewParent mParent;
 
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     AttachInfo mAttachInfo;
 
     /**
@@ -3836,8 +3852,11 @@
     }, formatToHexString = true)
 
     /* @hide */
+    @UnsupportedAppUsage
     public int mPrivateFlags;
+    @UnsupportedAppUsage
     int mPrivateFlags2;
+    @UnsupportedAppUsage
     int mPrivateFlags3;
 
     /**
@@ -3949,6 +3968,7 @@
      * laid out.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected ViewGroup.LayoutParams mLayoutParams;
 
     /**
@@ -3956,6 +3976,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(formatToHexString = true)
+    @UnsupportedAppUsage
     int mViewFlags;
 
     static class TransformationInfo {
@@ -3993,6 +4014,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public TransformationInfo mTransformationInfo;
 
     /**
@@ -4009,6 +4031,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "layout")
+    @UnsupportedAppUsage
     protected int mLeft;
     /**
      * The distance in pixels from the left edge of this view's parent
@@ -4016,6 +4039,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "layout")
+    @UnsupportedAppUsage
     protected int mRight;
     /**
      * The distance in pixels from the top edge of this view's parent
@@ -4023,6 +4047,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "layout")
+    @UnsupportedAppUsage
     protected int mTop;
     /**
      * The distance in pixels from the top edge of this view's parent
@@ -4030,6 +4055,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "layout")
+    @UnsupportedAppUsage
     protected int mBottom;
 
     /**
@@ -4038,6 +4064,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "scrolling")
+    @UnsupportedAppUsage
     protected int mScrollX;
     /**
      * The offset, in pixels, by which the content of this view is scrolled
@@ -4045,6 +4072,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "scrolling")
+    @UnsupportedAppUsage
     protected int mScrollY;
 
     /**
@@ -4053,6 +4081,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "padding")
+    @UnsupportedAppUsage
     protected int mPaddingLeft = 0;
     /**
      * The right padding in pixels, that is the distance in pixels between the
@@ -4060,6 +4089,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "padding")
+    @UnsupportedAppUsage
     protected int mPaddingRight = 0;
     /**
      * The top padding in pixels, that is the distance in pixels between the
@@ -4067,6 +4097,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "padding")
+    @UnsupportedAppUsage
     protected int mPaddingTop;
     /**
      * The bottom padding in pixels, that is the distance in pixels between the
@@ -4074,6 +4105,7 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(category = "padding")
+    @UnsupportedAppUsage
     protected int mPaddingBottom;
 
     /**
@@ -4199,6 +4231,7 @@
     private LongSparseLongArray mMeasureCache;
 
     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
+    @UnsupportedAppUsage
     private Drawable mBackground;
     private TintInfo mBackgroundTint;
 
@@ -4216,6 +4249,7 @@
      */
     private RenderNode mBackgroundRenderNode;
 
+    @UnsupportedAppUsage
     private int mBackgroundResource;
     private boolean mBackgroundSizeChanged;
 
@@ -4266,6 +4300,7 @@
          * This field should be made private, so it is hidden from the SDK.
          * {@hide}
          */
+        @UnsupportedAppUsage
         protected OnFocusChangeListener mOnFocusChangeListener;
 
         /**
@@ -4285,6 +4320,7 @@
          * This field should be made private, so it is hidden from the SDK.
          * {@hide}
          */
+        @UnsupportedAppUsage
         public OnClickListener mOnClickListener;
 
         /**
@@ -4292,6 +4328,7 @@
          * This field should be made private, so it is hidden from the SDK.
          * {@hide}
          */
+        @UnsupportedAppUsage
         protected OnLongClickListener mOnLongClickListener;
 
         /**
@@ -4306,16 +4343,22 @@
          * This field should be made private, so it is hidden from the SDK.
          * {@hide}
          */
+        @UnsupportedAppUsage
         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
 
+        @UnsupportedAppUsage
         private OnKeyListener mOnKeyListener;
 
+        @UnsupportedAppUsage
         private OnTouchListener mOnTouchListener;
 
+        @UnsupportedAppUsage
         private OnHoverListener mOnHoverListener;
 
+        @UnsupportedAppUsage
         private OnGenericMotionListener mOnGenericMotionListener;
 
+        @UnsupportedAppUsage
         private OnDragListener mOnDragListener;
 
         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
@@ -4327,6 +4370,7 @@
         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
     }
 
+    @UnsupportedAppUsage
     ListenerInfo mListenerInfo;
 
     private static class TooltipInfo {
@@ -4405,10 +4449,13 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(deepExport = true)
+    @UnsupportedAppUsage
     protected Context mContext;
 
+    @UnsupportedAppUsage
     private final Resources mResources;
 
+    @UnsupportedAppUsage
     private ScrollabilityCache mScrollCache;
 
     private int[] mDrawableState = null;
@@ -4464,6 +4511,7 @@
     boolean mDefaultFocusHighlightEnabled = true;
 
     private CheckForLongPress mPendingCheckForLongPress;
+    @UnsupportedAppUsage
     private CheckForTap mPendingCheckForTap = null;
     private PerformClick mPerformClick;
     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
@@ -4476,6 +4524,7 @@
      * a long press could be performed before the tap is checked, in which case the tap's action
      * should not be invoked.
      */
+    @UnsupportedAppUsage
     private boolean mHasPerformedLongPress;
 
     /**
@@ -4497,6 +4546,7 @@
      * of this view to at least this amount.
      */
     @ViewDebug.ExportedProperty(category = "measurement")
+    @UnsupportedAppUsage
     private int mMinHeight;
 
     /**
@@ -4504,6 +4554,7 @@
      * of this view to at least this amount.
      */
     @ViewDebug.ExportedProperty(category = "measurement")
+    @UnsupportedAppUsage
     private int mMinWidth;
 
     /**
@@ -4531,6 +4582,7 @@
     /**
      * Object that handles automatic animation of view properties.
      */
+    @UnsupportedAppUsage
     private ViewPropertyAnimator mAnimator = null;
 
     /**
@@ -4599,6 +4651,7 @@
     /**
      * Position of the vertical scroll bar.
      */
+    @UnsupportedAppUsage
     private int mVerticalScrollbarPosition;
 
     /**
@@ -4692,8 +4745,11 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean mCachingFailed;
+    @UnsupportedAppUsage
     private Bitmap mDrawingCache;
+    @UnsupportedAppUsage
     private Bitmap mUnscaledDrawingCache;
 
     /**
@@ -4703,6 +4759,7 @@
      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
      * cleanup.
      */
+    @UnsupportedAppUsage
     final RenderNode mRenderNode;
 
     /**
@@ -4714,6 +4771,7 @@
     /**
      * Delegate for injecting accessibility functionality.
      */
+    @UnsupportedAppUsage
     AccessibilityDelegate mAccessibilityDelegate;
 
     /**
@@ -4775,6 +4833,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     String mStartActivityRequestWho;
 
     @Nullable
@@ -5670,6 +5729,7 @@
     /**
      * Non-public constructor for use in testing
      */
+    @UnsupportedAppUsage
     View() {
         mResources = null;
         mRenderNode = RenderNode.create(getClass().getName(), this);
@@ -5993,6 +6053,7 @@
      * @param a the styled attributes set to initialize the scrollbars from
      * @hide
      */
+    @UnsupportedAppUsage
     protected void initializeScrollbarsInternal(TypedArray a) {
         initScrollCache();
 
@@ -6085,6 +6146,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private ScrollabilityCache getScrollCache() {
         initScrollCache();
         return mScrollCache;
@@ -6140,6 +6202,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     boolean isOnScrollbarThumb(float x, float y) {
         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
     }
@@ -6199,6 +6262,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     boolean isDraggingScrollBar() {
         return mScrollCache != null
                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
@@ -6287,6 +6351,7 @@
                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
     }
 
+    @UnsupportedAppUsage
     ListenerInfo getListenerInfo() {
         if (mListenerInfo != null) {
             return mListenerInfo;
@@ -6811,6 +6876,7 @@
      * @param requestCode The request code to use.
      * @hide
      */
+    @UnsupportedAppUsage
     public void startActivityForResult(Intent intent, int requestCode) {
         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
@@ -7547,7 +7613,7 @@
      */
     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
-                && !TextUtils.isEmpty(getAccessibilityPaneTitle())) {
+                && isAccessibilityPane()) {
             event.getText().add(getAccessibilityPaneTitle());
         }
     }
@@ -7594,6 +7660,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         event.setSource(this);
         event.setClassName(getAccessibilityClassName());
@@ -7709,6 +7776,7 @@
      * @param outRect The output location
      * @hide
      */
+    @UnsupportedAppUsage
     public void getBoundsOnScreen(Rect outRect) {
         getBoundsOnScreen(outRect, false);
     }
@@ -7720,6 +7788,7 @@
      * @param clipToParent Whether to clip child bounds to the parent ones.
      * @hide
      */
+    @UnsupportedAppUsage
     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
         if (mAttachInfo == null) {
             return;
@@ -8747,14 +8816,10 @@
         info.setContentDescription(getContentDescription());
 
         info.setEnabled(isEnabled());
-        info.setClickable(isClickable());
-        info.setFocusable(isFocusable());
         info.setScreenReaderFocusable(isScreenReaderFocusable());
         info.setFocused(isFocused());
         info.setAccessibilityFocused(isAccessibilityFocused());
         info.setSelected(isSelected());
-        info.setLongClickable(isLongClickable());
-        info.setContextClickable(isContextClickable());
         info.setLiveRegion(getAccessibilityLiveRegion());
         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
             info.setTooltipText(mTooltipInfo.mTooltipText);
@@ -8947,6 +9012,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isVisibleToUser() {
         return isVisibleToUser(null);
     }
@@ -8968,6 +9034,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected boolean isVisibleToUser(Rect boundInView) {
         if (mAttachInfo != null) {
             // Attached to invisible window means this view is not visible.
@@ -9008,8 +9075,6 @@
      * composition. For more details see {@link AccessibilityDelegate}.
      *
      * @return The delegate, or null if none set.
-     *
-     * @hide
      */
     public AccessibilityDelegate getAccessibilityDelegate() {
         return mAccessibilityDelegate;
@@ -9077,6 +9142,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getAccessibilityViewId() {
         if (mAccessibilityViewId == NO_ID) {
             mAccessibilityViewId = sNextAccessibilityViewId++;
@@ -9296,6 +9362,7 @@
      * @hide pending API council approval
      */
     @CallSuper
+    @UnsupportedAppUsage
     protected void onFocusLost() {
         resetPressedState();
     }
@@ -9821,6 +9888,7 @@
      * @hide
      * @param location an array of two integers in which to hold the coordinates
      */
+    @UnsupportedAppUsage
     public void getLocationInSurface(@Size(2) int[] location) {
         getLocationInWindow(location);
         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
@@ -9854,6 +9922,7 @@
      * @return
      */
     @Deprecated
+    @UnsupportedAppUsage
     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
                 outLocalInsets);
@@ -9929,6 +9998,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean fitsSystemWindows() {
         return getFitsSystemWindows();
     }
@@ -9955,6 +10025,7 @@
      * For use by PhoneWindow to make its own system window fitting optional.
      * @hide
      */
+    @UnsupportedAppUsage
     public void makeOptionalFitsSystemWindows() {
         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
     }
@@ -10299,6 +10370,7 @@
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "layout")
+    @UnsupportedAppUsage
     public boolean isLayoutRtl() {
         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
     }
@@ -10629,6 +10701,7 @@
      * @see #onProvideVirtualStructure
      * @attr ref android.R.styleable#View_assistBlocked
      */
+    @UnsupportedAppUsage
     public void setAssistBlocked(boolean enabled) {
         if (enabled) {
             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
@@ -11318,6 +11391,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean requestAccessibilityFocus() {
         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
@@ -11347,6 +11421,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void clearAccessibilityFocus() {
         clearAccessibilityFocusNoCallbacks(0);
 
@@ -11861,6 +11936,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean includeForAccessibility() {
         if (mAttachInfo != null) {
             return (mAttachInfo.mAccessibilityFetchFlags
@@ -11907,6 +11983,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
             return;
@@ -11966,6 +12043,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
             return;
@@ -12069,6 +12147,7 @@
     *
     * @hide
     */
+    @UnsupportedAppUsage
     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
         if (isNestedScrollingEnabled()
                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
@@ -12246,6 +12325,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public CharSequence getIterableTextForAccessibility() {
         return getContentDescription();
     }
@@ -12309,6 +12389,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public TextSegmentIterator getIteratorForGranularity(int granularity) {
         switch (granularity) {
             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
@@ -12755,6 +12836,7 @@
      * @return True if the event was handled by the view, false otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public final boolean dispatchPointerEvent(MotionEvent event) {
         if (event.isTouchEvent()) {
             return dispatchTouchEvent(event);
@@ -12963,7 +13045,7 @@
                 }
             }
         }
-        if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
+        if (isAccessibilityPane()) {
             if (isVisible != oldVisible) {
                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
@@ -13028,6 +13110,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void getWindowDisplayFrame(Rect outRect) {
         if (mAttachInfo != null) {
             try {
@@ -13890,6 +13973,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isInScrollingContainer() {
         ViewParent p = getParent();
         while (p != null && p instanceof ViewGroup) {
@@ -13913,6 +13997,7 @@
     /**
      * Remove the pending click action
      */
+    @UnsupportedAppUsage
     private void removePerformClickCallback() {
         if (mPerformClick != null) {
             removeCallbacks(mPerformClick);
@@ -14011,6 +14096,7 @@
      * @param flags Constant indicating the value which should be set
      * @param mask Constant indicating the bit range that should be changed
      */
+    @UnsupportedAppUsage
     void setFlags(int flags, int mask) {
         final boolean accessibilityEnabled =
                 AccessibilityManager.getInstance(mContext).isEnabled();
@@ -14549,10 +14635,12 @@
      *
      * @return True if the transform matrix is the identity matrix, false otherwise.
      */
+    @UnsupportedAppUsage
     final boolean hasIdentityMatrix() {
         return mRenderNode.hasIdentityMatrix();
     }
 
+    @UnsupportedAppUsage
     void ensureTransformationInfo() {
         if (mTransformationInfo == null) {
             mTransformationInfo = new TransformationInfo();
@@ -14567,6 +14655,7 @@
      * @return The inverse of the current matrix of this view.
      * @hide
      */
+    @UnsupportedAppUsage
     public final Matrix getInverseMatrix() {
         ensureTransformationInfo();
         if (mTransformationInfo.mInverseMatrix == null) {
@@ -15079,6 +15168,7 @@
      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
      *         the new value for the alpha property is different from the old value
      */
+    @UnsupportedAppUsage
     boolean setAlphaNoInvalidation(float alpha) {
         ensureTransformationInfo();
         if (mTransformationInfo.mAlpha != alpha) {
@@ -15113,6 +15203,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setTransitionAlpha(float alpha) {
         ensureTransformationInfo();
         if (mTransformationInfo.mTransitionAlpha != alpha) {
@@ -15144,6 +15235,7 @@
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "drawing")
+    @UnsupportedAppUsage
     public float getTransitionAlpha() {
         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
     }
@@ -15629,6 +15721,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setAnimationMatrix(Matrix matrix) {
         invalidateViewProperty(true, false);
         mRenderNode.setAnimationMatrix(matrix);
@@ -15903,6 +15996,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean pointInView(float localX, float localY, float slop) {
         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
                 localY < ((mBottom - mTop) + slop);
@@ -16402,6 +16496,7 @@
      *            dimensions have not changed.
      * @hide
      */
+    @UnsupportedAppUsage
     public void invalidate(boolean invalidateCache) {
         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
     }
@@ -16491,6 +16586,7 @@
      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
      * list properties are not being used in this view
      */
+    @UnsupportedAppUsage
     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
         if (!isHardwareAccelerated()
                 || !mRenderNode.isValid()
@@ -16542,6 +16638,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected void invalidateParentCaches() {
         if (mParent instanceof View) {
             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
@@ -16557,6 +16654,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected void invalidateParentIfNeeded() {
         if (isHardwareAccelerated() && mParent instanceof View) {
             ((View) mParent).invalidate(true);
@@ -16593,6 +16691,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected void computeOpaqueFlags() {
         // Opaque if:
         //   - Has a background
@@ -16651,6 +16750,7 @@
      * @return The view root, or null if none.
      * @hide
      */
+    @UnsupportedAppUsage
     public ViewRootImpl getViewRootImpl() {
         if (mAttachInfo != null) {
             return mAttachInfo.mViewRootImpl;
@@ -16661,6 +16761,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public ThreadedRenderer getThreadedRenderer() {
         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
     }
@@ -17151,6 +17252,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected void recomputePadding() {
         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
     }
@@ -17754,6 +17856,7 @@
      * @see #computeHorizontalScrollOffset()
      * @hide
      */
+    @UnsupportedAppUsage
     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
             int l, int t, int r, int b) {
         scrollBar.setBounds(l, t, r, b);
@@ -17773,6 +17876,7 @@
      * @see #computeVerticalScrollOffset()
      * @hide
      */
+    @UnsupportedAppUsage
     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
             int l, int t, int r, int b) {
         scrollBar.setBounds(l, t, r, b);
@@ -17791,6 +17895,7 @@
      * Caller is responsible for calling requestLayout if necessary.
      * (This allows addViewInLayout to not request a new layout.)
      */
+    @UnsupportedAppUsage
     void assignParent(ViewParent parent) {
         if (mParent == null) {
             mParent = parent;
@@ -17873,6 +17978,7 @@
      *
      * @hide
      */
+    @TestApi
     public void resetRtlProperties() {
         resetResolvedLayoutDirection();
         resetResolvedTextDirection();
@@ -17935,6 +18041,7 @@
     /**
      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
      */
+    @UnsupportedAppUsage
     private boolean hasRtlSupport() {
         return mContext.getApplicationInfo().hasRtlSupport();
     }
@@ -18054,6 +18161,7 @@
      *
      * @hide
      */
+    @TestApi
     public void resetResolvedLayoutDirection() {
         // Reset the current resolved bits
         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
@@ -18080,6 +18188,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     boolean isPaddingResolved() {
         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
     }
@@ -18090,6 +18199,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void resolvePadding() {
         final int resolvedLayoutDirection = getLayoutDirection();
 
@@ -18153,6 +18263,7 @@
      *
      * @hide
      */
+    @TestApi
     public void resetResolvedPadding() {
         resetResolvedPaddingInternal();
     }
@@ -18186,6 +18297,7 @@
      * @hide
      */
     @CallSuper
+    @UnsupportedAppUsage
     protected void onDetachedFromWindowInternal() {
         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
@@ -18294,6 +18406,7 @@
      * communicate with the window manager.
      * @return the session object to communicate with the window manager
      */
+    @UnsupportedAppUsage
     /*package*/ IWindowSession getWindowSession() {
         return mAttachInfo != null ? mAttachInfo.mSession : null;
     }
@@ -18319,6 +18432,7 @@
      * @param info the {@link android.view.View.AttachInfo} to associated with
      *        this view
      */
+    @UnsupportedAppUsage
     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
         mAttachInfo = info;
         if (mOverlay != null) {
@@ -18383,6 +18497,7 @@
         notifyEnterOrExitForAutoFillIfNeeded(true);
     }
 
+    @UnsupportedAppUsage
     void dispatchDetachedFromWindow() {
         AttachInfo info = mAttachInfo;
         if (info != null) {
@@ -18888,6 +19003,7 @@
      * @hide
      */
     @CallSuper
+    @UnsupportedAppUsage
     protected void destroyHardwareResources() {
         if (mOverlay != null) {
             mOverlay.getOverlayView().destroyHardwareResources();
@@ -19023,6 +19139,7 @@
      * @hide
      */
     @NonNull
+    @UnsupportedAppUsage
     public RenderNode updateDisplayListIfDirty() {
         final RenderNode renderNode = mRenderNode;
         if (!canHaveDisplayList()) {
@@ -19093,6 +19210,7 @@
         return renderNode;
     }
 
+    @UnsupportedAppUsage
     private void resetDisplayList() {
         mRenderNode.discardDisplayList();
         if (mBackgroundRenderNode != null) {
@@ -19493,6 +19611,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
         int width = mRight - mLeft;
         int height = mBottom - mTop;
@@ -20381,6 +20500,7 @@
      *
      * @param canvas Canvas on which to draw the background
      */
+    @UnsupportedAppUsage
     private void drawBackground(Canvas canvas) {
         final Drawable background = mBackground;
         if (background == null) {
@@ -20442,6 +20562,7 @@
     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
         if (renderNode == null) {
             renderNode = RenderNode.create(drawable.getClass().getName(), this);
+            renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
         }
 
         final Rect bounds = drawable.getBounds();
@@ -20769,6 +20890,7 @@
      *         previous ones
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected boolean setFrame(int left, int top, int right, int bottom) {
         boolean changed = false;
 
@@ -20836,6 +20958,7 @@
      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
         setFrame(left, top, right, bottom);
     }
@@ -21022,6 +21145,7 @@
     /**
      * @hide
      */
+    @TestApi
     protected void resetResolvedDrawables() {
         resetResolvedDrawablesInternal();
     }
@@ -22021,6 +22145,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected void internalSetPadding(int left, int top, int right, int bottom) {
         mUserPaddingLeft = left;
         mUserPaddingRight = right;
@@ -22215,6 +22340,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void resetPaddingToInitialValues() {
         if (isRtlCompatibilityMode()) {
             mPaddingLeft = mUserPaddingLeftInitial;
@@ -22394,6 +22520,7 @@
      * @return false if the transformation could not be applied
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean toGlobalMotionEvent(MotionEvent ev) {
         final AttachInfo info = mAttachInfo;
         if (info == null) {
@@ -22415,6 +22542,7 @@
      * @return false if the transformation could not be applied
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean toLocalMotionEvent(MotionEvent ev) {
         final AttachInfo info = mAttachInfo;
         if (info == null) {
@@ -22435,6 +22563,7 @@
      * @param m input matrix to modify
      * @hide
      */
+    @UnsupportedAppUsage
     public void transformMatrixToGlobal(Matrix m) {
         final ViewParent parent = mParent;
         if (parent instanceof View) {
@@ -22461,6 +22590,7 @@
      * @param m input matrix to modify
      * @hide
      */
+    @UnsupportedAppUsage
     public void transformMatrixToLocal(Matrix m) {
         final ViewParent parent = mParent;
         if (parent instanceof View) {
@@ -22487,6 +22617,7 @@
             @ViewDebug.IntToString(from = 0, to = "x"),
             @ViewDebug.IntToString(from = 1, to = "y")
     })
+    @UnsupportedAppUsage
     public int[] getLocationOnScreen() {
         int[] location = new int[2];
         getLocationOnScreen(location);
@@ -22667,6 +22798,7 @@
      * @param accessibilityId The searched accessibility id.
      * @return The found view.
      */
+    @UnsupportedAppUsage
     final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
         if (accessibilityId < 0) {
             return null;
@@ -22803,6 +22935,7 @@
      * @param isRoot true if the view belongs to the root namespace, false
      *        otherwise
      */
+    @TestApi
     public void setIsRootNamespace(boolean isRoot) {
         if (isRoot) {
             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
@@ -22816,6 +22949,7 @@
      *
      * @return true if the view belongs to the root namespace, false otherwise
      */
+    @UnsupportedAppUsage
     public boolean isRootNamespace() {
         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
     }
@@ -22919,6 +23053,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setTagInternal(int key, Object tag) {
         if ((key >>> 24) != 0x1) {
             throw new IllegalArgumentException("The key must be a framework-specific "
@@ -22942,6 +23077,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void debug() {
         debug(0);
     }
@@ -22955,6 +23091,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected void debug(int depth) {
         String output = debugIndent(depth - 1);
 
@@ -23577,6 +23714,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean gatherTransparentRegion(Region region) {
         final AttachInfo attachInfo = mAttachInfo;
         if (region != null && attachInfo != null) {
@@ -23804,6 +23942,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDisabledSystemUiVisibility(int flags) {
         if (mAttachInfo != null) {
             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
@@ -23844,6 +23983,7 @@
      * </div>
      */
     public static class DragShadowBuilder {
+        @UnsupportedAppUsage
         private final WeakReference<View> mView;
 
         /**
@@ -24271,6 +24411,7 @@
      * it is ever exposed at all.
      * @hide
      */
+    @UnsupportedAppUsage
     public void onCloseSystemDialogs(String reason) {
     }
 
@@ -24289,6 +24430,7 @@
      * Drawable that are not transparent.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
         if (DBG) {
             Log.i("View", "Getting transparent region for: " + this);
@@ -24784,6 +24926,7 @@
      * @return The vertical scroll scale factor.
      * @hide
      */
+    @UnsupportedAppUsage
     protected float getVerticalScrollFactor() {
         if (mVerticalScrollFactor == 0) {
             TypedValue outValue = new TypedValue();
@@ -24804,6 +24947,7 @@
      * @return The horizontal scroll scale factor.
      * @hide
      */
+    @UnsupportedAppUsage
     protected float getHorizontalScrollFactor() {
         // TODO: Should use something else.
         return getVerticalScrollFactor();
@@ -24838,6 +24982,7 @@
             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
     })
+    @UnsupportedAppUsage
     public int getRawTextDirection() {
         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
     }
@@ -25024,6 +25169,7 @@
      *
      * @hide
      */
+    @TestApi
     public void resetResolvedTextDirection() {
         // Reset any previous text direction resolution
         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
@@ -25075,6 +25221,7 @@
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
     })
     @TextAlignment
+    @UnsupportedAppUsage
     public int getRawTextAlignment() {
         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
     }
@@ -25261,6 +25408,7 @@
      *
      * @hide
      */
+    @TestApi
     public void resetResolvedTextAlignment() {
         // Reset any previous text alignment resolution
         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
@@ -25763,6 +25911,7 @@
          *
          * @hide internal use only for compatibility with system widgets and older apps
          */
+        @UnsupportedAppUsage
         public static int makeSafeMeasureSpec(int size, int mode) {
             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
                 return 0;
@@ -26314,11 +26463,16 @@
             private static final SynchronizedPool<InvalidateInfo> sPool =
                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
 
+            @UnsupportedAppUsage
             View target;
 
+            @UnsupportedAppUsage
             int left;
+            @UnsupportedAppUsage
             int top;
+            @UnsupportedAppUsage
             int right;
+            @UnsupportedAppUsage
             int bottom;
 
             public static InvalidateInfo obtain() {
@@ -26332,8 +26486,10 @@
             }
         }
 
+        @UnsupportedAppUsage
         final IWindowSession mSession;
 
+        @UnsupportedAppUsage
         final IWindow mWindow;
 
         final IBinder mWindowToken;
@@ -26364,16 +26520,19 @@
          * constants declared by {@link View} (there are more display states than
          * screen states).
          */
+        @UnsupportedAppUsage
         int mDisplayState = Display.STATE_UNKNOWN;
 
         /**
          * Scale factor used by the compatibility mode
          */
+        @UnsupportedAppUsage
         float mApplicationScale;
 
         /**
          * Indicates whether the application is in compatibility mode
          */
+        @UnsupportedAppUsage
         boolean mScalingRequired;
 
         /**
@@ -26403,6 +26562,7 @@
          * of the screen decorations, these are the current insets for the
          * content of the window.
          */
+        @UnsupportedAppUsage
         final Rect mContentInsets = new Rect();
 
         /**
@@ -26410,6 +26570,7 @@
          * of the screen decorations, these are the current insets for the
          * actual visible parts of the window.
          */
+        @UnsupportedAppUsage
         final Rect mVisibleInsets = new Rect();
 
         /**
@@ -26417,6 +26578,7 @@
          * of the screen decorations, these are the current insets for the
          * stable system windows.
          */
+        @UnsupportedAppUsage
         final Rect mStableInsets = new Rect();
 
         final DisplayCutout.ParcelableWrapper mDisplayCutout =
@@ -26442,6 +26604,7 @@
          * be given to the window manager when changed to be used in laying
          * out windows behind it.
          */
+        @UnsupportedAppUsage
         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
                 = new ViewTreeObserver.InternalInsetsInfo();
 
@@ -26455,14 +26618,17 @@
          * used to determine if the window can be resized or must be panned
          * to adjust for a soft input area.
          */
+        @UnsupportedAppUsage
         final ArrayList<View> mScrollContainers = new ArrayList<View>();
 
+        @UnsupportedAppUsage
         final KeyEvent.DispatcherState mKeyDispatchState
                 = new KeyEvent.DispatcherState();
 
         /**
          * Indicates whether the view's window currently has the focus.
          */
+        @UnsupportedAppUsage
         boolean mHasWindowFocus;
 
         /**
@@ -26473,11 +26639,13 @@
         /**
          * Indicates the time at which drawing started to occur.
          */
+        @UnsupportedAppUsage
         long mDrawingTime;
 
         /**
          * Indicates whether the view's window is currently in touch mode.
          */
+        @UnsupportedAppUsage
         boolean mInTouchMode;
 
         /**
@@ -26490,6 +26658,7 @@
          * Indicates that ViewAncestor should trigger a global layout change
          * the next time it performs a traversal
          */
+        @UnsupportedAppUsage
         boolean mRecomputeGlobalAttributes;
 
         /**
@@ -26500,6 +26669,7 @@
         /**
          * Set during a traveral if any views want to keep the screen on.
          */
+        @UnsupportedAppUsage
         boolean mKeepScreenOn;
 
         /**
@@ -26537,11 +26707,13 @@
         /**
          * Set if the visibility of any views has changed.
          */
+        @UnsupportedAppUsage
         boolean mViewVisibilityChanged;
 
         /**
          * Set to true if a view has been scrolled.
          */
+        @UnsupportedAppUsage
         boolean mViewScrollChanged;
 
         /**
@@ -26577,6 +26749,7 @@
          * The view tree observer used to dispatch global events like
          * layout, pre-draw, touch mode change, etc.
          */
+        @UnsupportedAppUsage
         final ViewTreeObserver mTreeObserver;
 
         /**
@@ -26593,6 +26766,7 @@
          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
          * handler can be used to pump events in the UI events queue.
          */
+        @UnsupportedAppUsage
         final Handler mHandler;
 
         /**
@@ -26755,8 +26929,10 @@
 
         public int scrollBarSize;
         public int scrollBarMinTouchTarget;
+        @UnsupportedAppUsage
         public ScrollBarDrawable scrollBar;
         public float[] interpolatorValues;
+        @UnsupportedAppUsage
         public View host;
 
         public final Paint paint;
@@ -26778,6 +26954,7 @@
         /**
          * The current state of the scrollbars: ON, OFF, or FADING
          */
+        @UnsupportedAppUsage
         public int state = OFF;
 
         private int mLastColor;
@@ -26896,6 +27073,7 @@
      * Remove the pending callback for sending a
      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
      */
+    @UnsupportedAppUsage
     private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) {
         if (callback == null || !callback.mIsPending) return;
         removeCallbacks(callback);
@@ -27210,6 +27388,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
             return host.createAccessibilityNodeInfoInternal();
         }
@@ -27478,6 +27657,7 @@
     /**
      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
      */
+    @UnsupportedAppUsage
     public void setTooltip(@Nullable CharSequence tooltipText) {
         setTooltipText(tooltipText);
     }
@@ -27527,6 +27707,7 @@
         return true;
     }
 
+    @UnsupportedAppUsage
     void hideTooltip() {
         if (mTooltipInfo == null) {
             return;
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 7a9de45..767cd33 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.AppGlobals;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -224,6 +225,7 @@
     /**
      * The coefficient of friction applied to flings/scrolls.
      */
+    @UnsupportedAppUsage
     private static final float SCROLL_FRICTION = 0.015f;
 
     /**
@@ -299,15 +301,19 @@
     private final int mMaximumDrawingCacheSize;
     private final int mOverscrollDistance;
     private final int mOverflingDistance;
+    @UnsupportedAppUsage
     private final boolean mFadingMarqueeEnabled;
     private final long mGlobalActionsKeyTimeout;
     private final float mVerticalScrollFactor;
     private final float mHorizontalScrollFactor;
     private final boolean mShowMenuShortcutsWhenKeyboardPresent;
 
+    @UnsupportedAppUsage
     private boolean sHasPermanentMenuKey;
+    @UnsupportedAppUsage
     private boolean sHasPermanentMenuKeySet;
 
+    @UnsupportedAppUsage
     static final SparseArray<ViewConfiguration> sConfigurations =
             new SparseArray<ViewConfiguration>(2);
 
@@ -589,6 +595,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getDoubleTapMinTime() {
         return DOUBLE_TAP_MIN_TIME;
     }
@@ -609,6 +616,7 @@
      * to a hover movement gesture.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getHoverTapSlop() {
         return HOVER_TAP_SLOP;
     }
@@ -662,6 +670,7 @@
      * potential double tap event
      * @hide
      */
+    @UnsupportedAppUsage
     public int getScaledDoubleTapTouchSlop() {
         return mDoubleTapTouchSlop;
     }
@@ -682,6 +691,7 @@
      *       for clients that still use its deprecated constructor.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static int getDoubleTapSlop() {
         return DOUBLE_TAP_SLOP;
     }
@@ -857,6 +867,7 @@
      *   the global actions dialog.
      * @hide
      */
+    @TestApi
     public long getDeviceGlobalActionKeyTimeout() {
         return mGlobalActionsKeyTimeout;
     }
@@ -928,6 +939,7 @@
      * @hide
      * @return Whether or not marquee should use fading edges.
      */
+    @UnsupportedAppUsage
     public boolean isFadingMarqueeEnabled() {
         return mFadingMarqueeEnabled;
     }
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index e4c595b..8dd0347 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -372,6 +373,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static long getViewInstanceCount() {
         return Debug.countInstancesOfClass(View.class);
     }
@@ -383,6 +385,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static long getViewRootImplCount() {
         return Debug.countInstancesOfClass(ViewRootImpl.class);
     }
@@ -434,6 +437,7 @@
     public static void stopHierarchyTracing() {
     }
 
+    @UnsupportedAppUsage
     static void dispatchCommand(View view, String command, String parameters,
             OutputStream clientStream) throws IOException {
 
@@ -803,6 +807,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static void dump(View root, boolean skipChildren, boolean includeProperties,
             OutputStream clientStream) throws IOException {
         BufferedWriter out = null;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d0539ae..0119d2e 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -24,6 +24,7 @@
 import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.annotation.UiThread;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ClipData;
 import android.content.Context;
 import android.content.Intent;
@@ -120,6 +121,7 @@
 public abstract class ViewGroup extends View implements ViewParent, ViewManager {
     private static final String TAG = "ViewGroup";
 
+    @UnsupportedAppUsage
     private static final boolean DBG = false;
 
     /**
@@ -128,6 +130,7 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected ArrayList<View> mDisappearingChildren;
 
     /**
@@ -136,9 +139,11 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected OnHierarchyChangeListener mOnHierarchyChangeListener;
 
     // The view contained within this ViewGroup that has or contains focus.
+    @UnsupportedAppUsage
     private View mFocused;
     // The view contained within this ViewGroup (excluding nested keyboard navigation clusters)
     // that is or contains a default-focus view.
@@ -183,6 +188,7 @@
     private Animation.AnimationListener mAnimationListener;
 
     // First touch target in the linked list of touch targets.
+    @UnsupportedAppUsage
     private TouchTarget mFirstTouchTarget;
 
     // For debugging only.  You can see these in hierarchyviewer.
@@ -230,6 +236,7 @@
             @ViewDebug.FlagToString(mask = FLAG_PADDING_NOT_NULL, equals = FLAG_PADDING_NOT_NULL,
                     name = "PADDING_NOT_NULL")
     }, formatToHexString = true)
+    @UnsupportedAppUsage
     protected int mGroupFlags;
 
     /**
@@ -290,6 +297,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected static final int FLAG_USE_CHILD_DRAWING_ORDER = 0x400;
 
     /**
@@ -303,6 +311,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected static final int FLAG_SUPPORT_STATIC_TRANSFORMATIONS = 0x800;
 
     // UNUSED FLAG VALUE: 0x1000;
@@ -356,6 +365,7 @@
      * When set, this ViewGroup should not intercept touch events.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected static final int FLAG_DISALLOW_INTERCEPT = 0x80000;
 
     /**
@@ -418,6 +428,7 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected int mPersistentDrawingCache;
 
     /**
@@ -530,9 +541,11 @@
     private static final int CHILD_TOP_INDEX = 1;
 
     // Child views of this ViewGroup
+    @UnsupportedAppUsage
     private View[] mChildren;
     // Number of valid children in the mChildren array, the rest should be null or not
     // considered as children
+    @UnsupportedAppUsage
     private int mChildrenCount;
 
     // Whether layout calls are currently being suppressed, controlled by calls to
@@ -1480,6 +1493,7 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     public void makeOptionalFitsSystemWindows() {
         super.makeOptionalFitsSystemWindows();
         final int count = mChildrenCount;
@@ -1508,6 +1522,7 @@
      * @param newVisibility The new visibility value (GONE, INVISIBLE, or VISIBLE).
      * @hide
      */
+    @UnsupportedAppUsage
     protected void onChildVisibilityChanged(View child, int oldVisibility, int newVisibility) {
         if (mTransition != null) {
             if (newVisibility == VISIBLE) {
@@ -2907,6 +2922,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void cancelTouchTarget(View view) {
         TouchTarget predecessor = null;
         TouchTarget target = mFirstTouchTarget;
@@ -2955,6 +2971,7 @@
      * Child must not be null.
      * @hide
      */
+    @UnsupportedAppUsage
     protected boolean isTransformedTouchPointInView(float x, float y, View child,
             PointF outLocalPoint) {
         final float[] point = getTempPoint();
@@ -2971,6 +2988,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void transformPointToViewLocal(float[] point, View child) {
         point[0] += mScrollX - child.mLeft;
         point[1] += mScrollY - child.mTop;
@@ -3392,6 +3410,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
         mGroupFlags |= FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW;
         super.dispatchAttachedToWindow(info, visibility);
@@ -3634,6 +3653,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
         if (getAccessibilityNodeProvider() != null) {
@@ -3740,6 +3760,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     void dispatchDetachedFromWindow() {
         // If we still have a touch target, we are still in the process of
         // dispatching motion events to a child; we need to get rid of that
@@ -4281,6 +4302,7 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     protected void dispatchGetDisplayList() {
         final int count = mChildrenCount;
         final View[] children = mChildren;
@@ -4660,6 +4682,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void addTransientView(View view, int index) {
         if (index < 0 || view == null) {
             return;
@@ -4702,6 +4725,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void removeTransientView(View view) {
         if (mTransientViews == null) {
             return;
@@ -4731,6 +4755,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTransientViewCount() {
         return mTransientIndices == null ? 0 : mTransientIndices.size();
     }
@@ -4764,6 +4789,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public View getTransientView(int position) {
         if (mTransientViews == null || position >= mTransientViews.size()) {
             return null;
@@ -4922,6 +4948,7 @@
         mOnHierarchyChangeListener = listener;
     }
 
+    @UnsupportedAppUsage
     void dispatchViewAdded(View child) {
         onViewAdded(child);
         if (mOnHierarchyChangeListener != null) {
@@ -4938,6 +4965,7 @@
     public void onViewAdded(View child) {
     }
 
+    @UnsupportedAppUsage
     void dispatchViewRemoved(View child) {
         onViewRemoved(child);
         if (mOnHierarchyChangeListener != null) {
@@ -6088,6 +6116,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void offsetChildrenTopAndBottom(int offset) {
         final int count = mChildrenCount;
         final View[] children = mChildren;
@@ -7006,6 +7035,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void suppressLayout(boolean suppress) {
         mSuppressLayout = suppress;
         if (!suppress) {
@@ -7303,6 +7333,7 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     public void resolvePadding() {
         super.resolvePadding();
         int count = getChildCount();
@@ -7345,6 +7376,7 @@
     /**
      * @hide
      */
+    @TestApi
     @Override
     public void resetResolvedLayoutDirection() {
         super.resetResolvedLayoutDirection();
@@ -7361,6 +7393,7 @@
     /**
      * @hide
      */
+    @TestApi
     @Override
     public void resetResolvedTextDirection() {
         super.resetResolvedTextDirection();
@@ -7377,6 +7410,7 @@
     /**
      * @hide
      */
+    @TestApi
     @Override
     public void resetResolvedTextAlignment() {
         super.resetResolvedTextAlignment();
@@ -7393,6 +7427,7 @@
     /**
      * @hide
      */
+    @TestApi
     @Override
     public void resetResolvedPadding() {
         super.resetResolvedPadding();
@@ -7409,6 +7444,7 @@
     /**
      * @hide
      */
+    @TestApi
     @Override
     protected void resetResolvedDrawables() {
         super.resetResolvedDrawables();
@@ -7745,6 +7781,7 @@
          * Used internally by MarginLayoutParams.
          * @hide
          */
+        @UnsupportedAppUsage
         LayoutParams() {
         }
 
@@ -7885,6 +7922,7 @@
          * to this field.
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @UnsupportedAppUsage
         private int startMargin = DEFAULT_MARGIN_RELATIVE;
 
         /**
@@ -7893,6 +7931,7 @@
          * to this field.
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @UnsupportedAppUsage
         private int endMargin = DEFAULT_MARGIN_RELATIVE;
 
         /**
@@ -8122,6 +8161,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public void setMarginsRelative(int start, int top, int end, int bottom) {
             startMargin = start;
             topMargin = top;
@@ -8345,6 +8385,7 @@
         public static final int ALL_POINTER_IDS = -1; // all ones
 
         // The touched child view.
+        @UnsupportedAppUsage
         public View child;
 
         // The combined bit mask of pointer ids for all pointers captured by the target.
@@ -8353,6 +8394,7 @@
         // The next target in the target list.
         public TouchTarget next;
 
+        @UnsupportedAppUsage
         private TouchTarget() {
         }
 
@@ -8621,7 +8663,7 @@
          * Compare two views based on their bounds. Use the bounds of their children to break ties.
          *
          * @param holder1 Holder of first view to compare
-         * @param holder2 Holder of second view to compare. Must have the same root at holder1.
+         * @param holder2 Holder of second view to compare. Must have the same root as holder1.
          * @return The compare result, with equality if no good comparison was found.
          */
         private static int compareBoundsOfTree(
@@ -8714,6 +8756,7 @@
 
         private void clear() {
             mView = null;
+            mRoot = null;
             mLocation.set(0, 0, 0, 0);
         }
     }
@@ -8749,6 +8792,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
         super.encodeProperties(encoder);
 
diff --git a/core/java/android/view/ViewHierarchyEncoder.java b/core/java/android/view/ViewHierarchyEncoder.java
index 8770216..d5716bf 100644
--- a/core/java/android/view/ViewHierarchyEncoder.java
+++ b/core/java/android/view/ViewHierarchyEncoder.java
@@ -2,6 +2,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
@@ -90,6 +91,7 @@
         endPropertyMap();
     }
 
+    @UnsupportedAppUsage
     public void addProperty(@NonNull String name, boolean v) {
         writeShort(createPropertyIndex(name));
         writeBoolean(v);
@@ -100,16 +102,19 @@
         writeShort(s);
     }
 
+    @UnsupportedAppUsage
     public void addProperty(@NonNull String name, int v) {
         writeShort(createPropertyIndex(name));
         writeInt(v);
     }
 
+    @UnsupportedAppUsage
     public void addProperty(@NonNull String name, float v) {
         writeShort(createPropertyIndex(name));
         writeFloat(v);
     }
 
+    @UnsupportedAppUsage
     public void addProperty(@NonNull String name, @Nullable String s) {
         writeShort(createPropertyIndex(name));
         writeString(s);
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 21123c1..e23c687 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -17,6 +17,7 @@
 
 import android.animation.LayoutTransition;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -55,6 +56,7 @@
      * of the overlay
      * @return
      */
+    @UnsupportedAppUsage
     ViewGroup getOverlayView() {
         return mOverlayViewGroup;
     }
@@ -94,6 +96,7 @@
         mOverlayViewGroup.clear();
     }
 
+    @UnsupportedAppUsage
     boolean isEmpty() {
         return mOverlayViewGroup.isEmpty();
     }
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 6c84b63..e3e2069 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -109,11 +109,6 @@
     private ValueAnimator mTempValueAnimator;
 
     /**
-     * A RenderThread-driven backend that may intercept startAnimation
-     */
-    private ViewPropertyAnimatorRT mRTBackend;
-
-    /**
      * This listener is the mechanism by which the underlying Animator causes changes to the
      * properties currently being animated, as well as the cleanup after an animation is
      * complete.
@@ -434,9 +429,6 @@
         mPendingOnStartAction = null;
         mPendingOnEndAction = null;
         mView.removeCallbacks(mAnimationStarter);
-        if (mRTBackend != null) {
-            mRTBackend.cancelAll();
-        }
     }
 
     /**
@@ -859,9 +851,6 @@
      * value accordingly.
      */
     private void startAnimation() {
-        if (mRTBackend != null && mRTBackend.startAnimation(this)) {
-            return;
-        }
         mView.setHasTransientState(true);
         ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
         ArrayList<NameValuesHolder> nameValueList =
diff --git a/core/java/android/view/ViewPropertyAnimatorRT.java b/core/java/android/view/ViewPropertyAnimatorRT.java
deleted file mode 100644
index de96887..0000000
--- a/core/java/android/view/ViewPropertyAnimatorRT.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.animation.TimeInterpolator;
-import android.view.ViewPropertyAnimator.NameValuesHolder;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-
-import com.android.internal.view.animation.FallbackLUTInterpolator;
-
-import java.util.ArrayList;
-
-
-/**
- * This is a RenderThread driven backend for ViewPropertyAnimator.
- */
-class ViewPropertyAnimatorRT {
-
-    private static final Interpolator sLinearInterpolator = new LinearInterpolator();
-
-    private final View mView;
-
-    private RenderNodeAnimator mAnimators[] = new RenderNodeAnimator[RenderNodeAnimator.LAST_VALUE + 1];
-
-    ViewPropertyAnimatorRT(View view) {
-        mView = view;
-    }
-
-    /**
-     * @return true if ViewPropertyAnimatorRT handled the animation,
-     *         false if ViewPropertyAnimator needs to handle it
-     */
-    public boolean startAnimation(ViewPropertyAnimator parent) {
-        cancelAnimators(parent.mPendingAnimations);
-        if (!canHandleAnimator(parent)) {
-            return false;
-        }
-        doStartAnimation(parent);
-        return true;
-    }
-
-    public void cancelAll() {
-        for (int i = 0; i < mAnimators.length; i++) {
-            if (mAnimators[i] != null) {
-                mAnimators[i].cancel();
-                mAnimators[i] = null;
-            }
-        }
-    }
-
-    private void doStartAnimation(ViewPropertyAnimator parent) {
-        int size = parent.mPendingAnimations.size();
-
-        long startDelay = parent.getStartDelay();
-        long duration = parent.getDuration();
-        TimeInterpolator interpolator = parent.getInterpolator();
-        if (interpolator == null) {
-            // Documented to be LinearInterpolator in ValueAnimator.setInterpolator
-            interpolator = sLinearInterpolator;
-        }
-        if (!RenderNodeAnimator.isNativeInterpolator(interpolator)) {
-            interpolator = new FallbackLUTInterpolator(interpolator, duration);
-        }
-        for (int i = 0; i < size; i++) {
-            NameValuesHolder holder = parent.mPendingAnimations.get(i);
-            int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);
-
-            final float finalValue = holder.mFromValue + holder.mDeltaValue;
-            RenderNodeAnimator animator = new RenderNodeAnimator(property, finalValue);
-            animator.setStartDelay(startDelay);
-            animator.setDuration(duration);
-            animator.setInterpolator(interpolator);
-            animator.setTarget(mView);
-            animator.start();
-
-            mAnimators[property] = animator;
-        }
-
-        parent.mPendingAnimations.clear();
-    }
-
-    private boolean canHandleAnimator(ViewPropertyAnimator parent) {
-        // TODO: Can we eliminate this entirely?
-        // If RenderNode.animatorProperties() can be toggled to point at staging
-        // instead then RNA can be used as the animators for software as well
-        // as the updateListener fallback paths. If this can be toggled
-        // at the top level somehow, combined with requiresUiRedraw, we could
-        // ensure that RT does not self-animate, allowing for safe driving of
-        // the animators from the UI thread using the same mechanisms
-        // ViewPropertyAnimator does, just with everything sitting on a single
-        // animator subsystem instead of multiple.
-
-        if (parent.getUpdateListener() != null) {
-            return false;
-        }
-        if (parent.getListener() != null) {
-            // TODO support
-            return false;
-        }
-        if (!mView.isHardwareAccelerated()) {
-            // TODO handle this maybe?
-            return false;
-        }
-        if (parent.hasActions()) {
-            return false;
-        }
-        // Here goes nothing...
-        return true;
-    }
-
-    private void cancelAnimators(ArrayList<NameValuesHolder> mPendingAnimations) {
-        int size = mPendingAnimations.size();
-        for (int i = 0; i < size; i++) {
-            NameValuesHolder holder = mPendingAnimations.get(i);
-            int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);
-            if (mAnimators[property] != null) {
-                mAnimators[property].cancel();
-                mAnimators[property] = null;
-            }
-        }
-    }
-
-}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ea9bd85..1351f6f1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.View.PFLAG_DRAW_ANIMATION;
 import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
@@ -30,6 +31,7 @@
 import android.animation.LayoutTransition;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.ResourcesManager;
@@ -170,6 +172,7 @@
      */
     static final int MAX_TRACKBALL_DELAY = 250;
 
+    @UnsupportedAppUsage
     static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
 
     static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList();
@@ -233,7 +236,9 @@
      */
     @GuardedBy("mWindowCallbacks")
     final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
+    @UnsupportedAppUsage
     final Context mContext;
+    @UnsupportedAppUsage
     final IWindowSession mWindowSession;
     @NonNull Display mDisplay;
     final DisplayManager mDisplayManager;
@@ -255,6 +260,7 @@
 
     int mSeq;
 
+    @UnsupportedAppUsage
     View mView;
 
     View mAccessibilityFocusedHost;
@@ -287,6 +293,7 @@
 
     // Set to true if the owner of this window is in the stopped state,
     // so the window should no longer be active.
+    @UnsupportedAppUsage
     boolean mStopped = false;
 
     // Set to true if the owner of this window is in ambient mode,
@@ -306,8 +313,11 @@
     final Region mTransparentRegion;
     final Region mPreviousTransparentRegion;
 
+    @UnsupportedAppUsage
     int mWidth;
+    @UnsupportedAppUsage
     int mHeight;
+    @UnsupportedAppUsage
     Rect mDirty;
     public boolean mIsAnimating;
 
@@ -321,10 +331,12 @@
 
     CompatibilityInfo.Translator mTranslator;
 
+    @UnsupportedAppUsage
     final View.AttachInfo mAttachInfo;
     InputChannel mInputChannel;
     InputQueue.Callback mInputQueueCallback;
     InputQueue mInputQueue;
+    @UnsupportedAppUsage
     FallbackEventHandler mFallbackEventHandler;
     Choreographer mChoreographer;
 
@@ -389,8 +401,10 @@
 
     // These can be accessed by any thread, must be protected with a lock.
     // Surface can never be reassigned or cleared (use Surface.clear()).
+    @UnsupportedAppUsage
     public final Surface mSurface = new Surface();
 
+    @UnsupportedAppUsage
     boolean mAdded;
     boolean mAddedTouchMode;
 
@@ -425,6 +439,7 @@
     boolean mScrollMayChange;
     @SoftInputModeFlags
     int mSoftInputMode;
+    @UnsupportedAppUsage
     WeakReference<View> mLastScrolledFocus;
     int mScrollY;
     int mCurScrollY;
@@ -555,6 +570,7 @@
     }
 
     /** Add static config callback to be notified about global config changes. */
+    @UnsupportedAppUsage
     public static void addConfigCallback(ConfigChangedCallback callback) {
         synchronized (sConfigCallbacks) {
             sConfigCallbacks.add(callback);
@@ -891,6 +907,7 @@
         return (mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE) != 0;
     }
 
+    @UnsupportedAppUsage
     public int getWindowFlags() {
         return mWindowAttributes.flags;
     }
@@ -930,6 +947,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void detachFunctor(long functor) {
         if (mAttachInfo.mThreadedRenderer != null) {
             // Fence so that any pending invokeFunctor() messages will be processed
@@ -947,6 +965,7 @@
      *                          has invoked. If false, the functor may be invoked
      *                          asynchronously.
      */
+    @UnsupportedAppUsage
     public static void invokeFunctor(long functor, boolean waitForCompletion) {
         ThreadedRenderer.invokeFunctor(functor, waitForCompletion);
     }
@@ -980,6 +999,7 @@
         mNextRtFrameCallback = callback;
     }
 
+    @UnsupportedAppUsage
     private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
         mAttachInfo.mHardwareAccelerated = false;
         mAttachInfo.mHardwareAccelerationRequested = false;
@@ -1040,6 +1060,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public View getView() {
         return mView;
     }
@@ -1192,13 +1213,30 @@
 
         // Get new instance of display based on current display adjustments. It may be updated later
         // if moving between the displays also involved a configuration change.
-        mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId,
-            mView.getResources());
+        updateInternalDisplay(displayId, mView.getResources());
         mAttachInfo.mDisplayState = mDisplay.getState();
         // Internal state updated, now notify the view hierarchy.
         mView.dispatchMovedToDisplay(mDisplay, config);
     }
 
+    /**
+     * Updates {@link #mDisplay} to the display object corresponding to {@param displayId}.
+     * Uses DEFAULT_DISPLAY if there isn't a display object in the system corresponding
+     * to {@param displayId}.
+     */
+    private void updateInternalDisplay(int displayId, Resources resources) {
+        final Display preferredDisplay =
+                ResourcesManager.getInstance().getAdjustedDisplay(displayId, resources);
+        if (preferredDisplay == null) {
+            // Fallback to use default display.
+            Slog.w(TAG, "Cannot get desired display with Id: " + displayId);
+            mDisplay = ResourcesManager.getInstance()
+                    .getAdjustedDisplay(DEFAULT_DISPLAY, resources);
+        } else {
+            mDisplay = preferredDisplay;
+        }
+    }
+
     void pokeDrawLockIfNeeded() {
         final int displayState = mAttachInfo.mDisplayState;
         if (mView != null && mAdded && mTraversalScheduled
@@ -1241,6 +1279,7 @@
         invalidate();
     }
 
+    @UnsupportedAppUsage
     void invalidate() {
         mDirty.set(0, 0, mWidth, mHeight);
         if (!mWillDrawSoon) {
@@ -1422,6 +1461,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void scheduleTraversals() {
         if (!mTraversalScheduled) {
             mTraversalScheduled = true;
@@ -2101,7 +2141,7 @@
                                         & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
                                     // Don't pre-allocate if transparent regions
                                     // are requested as they may not be needed
-                                    mSurface.allocateBuffers();
+                                    mAttachInfo.mThreadedRenderer.allocateBuffers(mSurface);
                                 }
                             } catch (OutOfResourcesException e) {
                                 handleOutOfResourcesException(e);
@@ -3097,13 +3137,27 @@
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
 
         boolean usingAsyncReport = false;
-        if (mReportNextDraw && mAttachInfo.mThreadedRenderer != null
-                && mAttachInfo.mThreadedRenderer.isEnabled()) {
-            usingAsyncReport = true;
-            mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> {
-                // TODO: Use the frame number
-                pendingDrawFinished();
-            });
+        if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
+            ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
+                    .captureFrameCommitCallbacks();
+            if (mReportNextDraw) {
+                usingAsyncReport = true;
+                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> {
+                    // TODO: Use the frame number
+                    pendingDrawFinished();
+                    if (commitCallbacks != null) {
+                        for (int i = 0; i < commitCallbacks.size(); i++) {
+                            commitCallbacks.get(i).run();
+                        }
+                    }
+                });
+            } else if (commitCallbacks != null && commitCallbacks.size() > 0) {
+                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> {
+                    for (int i = 0; i < commitCallbacks.size(); i++) {
+                        commitCallbacks.get(i).run();
+                    }
+                });
+            }
         }
 
         try {
@@ -3643,6 +3697,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public View getAccessibilityFocusedHost() {
         return mAccessibilityFocusedHost;
     }
@@ -3650,6 +3705,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public AccessibilityNodeInfo getAccessibilityFocusedVirtualView() {
         return mAccessibilityFocusedVirtualView;
     }
@@ -3906,8 +3962,7 @@
         // Handle configuration change.
         if (mForceNextConfigUpdate || mLastConfigurationFromResources.diff(config) != 0) {
             // Update the display with new DisplayAdjustments.
-            mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(
-                    mDisplay.getDisplayId(), localResources);
+            updateInternalDisplay(mDisplay.getDisplayId(), localResources);
 
             final int lastLayoutDirection = mLastConfigurationFromResources.getLayoutDirection();
             final int currentLayoutDirection = config.getLayoutDirection();
@@ -4267,6 +4322,7 @@
      * @param inTouchMode Whether we want to be in touch mode.
      * @return True if the touch mode changed and focus changed was changed as a result
      */
+    @UnsupportedAppUsage
     boolean ensureTouchMode(boolean inTouchMode) {
         if (DBG) Log.d("touchmode", "ensureTouchMode(" + inTouchMode + "), current "
                 + "touch mode is " + mAttachInfo.mInTouchMode);
@@ -6262,6 +6318,7 @@
     }
 
     /* drag/drop */
+    @UnsupportedAppUsage
     void setLocalDragState(Object obj) {
         mLocalDragState = obj;
     }
@@ -6409,6 +6466,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void getLastTouchPoint(Point outLocation) {
         outLocation.x = (int) mLastTouchPoint.x;
         outLocation.y = (int) mLastTouchPoint.y;
@@ -6807,6 +6865,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
             Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
             MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
@@ -6971,10 +7030,12 @@
         }
     }
 
+    @UnsupportedAppUsage
     void enqueueInputEvent(InputEvent event) {
         enqueueInputEvent(event, null, 0, false);
     }
 
+    @UnsupportedAppUsage
     void enqueueInputEvent(InputEvent event,
             InputEventReceiver receiver, int flags, boolean processImmediately) {
         adjustInputEventForCompatibility(event);
@@ -7315,6 +7376,7 @@
         mInvalidateOnAnimationRunnable.addViewRect(info);
     }
 
+    @UnsupportedAppUsage
     public void cancelInvalidate(View view) {
         mHandler.removeMessages(MSG_INVALIDATE, view);
         // fixme: might leak the AttachInfo.InvalidateInfo objects instead of returning
@@ -7323,10 +7385,12 @@
         mInvalidateOnAnimationRunnable.removeView(view);
     }
 
+    @UnsupportedAppUsage
     public void dispatchInputEvent(InputEvent event) {
         dispatchInputEvent(event, null);
     }
 
+    @UnsupportedAppUsage
     public void dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = event;
@@ -7342,6 +7406,7 @@
         mHandler.sendMessage(msg);
     }
 
+    @UnsupportedAppUsage
     public void dispatchKeyFromIme(KeyEvent event) {
         Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY_FROM_IME, event);
         msg.setAsynchronous(true);
@@ -7360,6 +7425,7 @@
      * Note that it is the responsibility of the caller of this API to recycle the InputEvent it
      * passes in.
      */
+    @UnsupportedAppUsage
     public void dispatchUnhandledInputEvent(InputEvent event) {
         if (event instanceof MotionEvent) {
             event = MotionEvent.obtain((MotionEvent) event);
@@ -8062,6 +8128,7 @@
     }
 
     public static final class CalledFromWrongThreadException extends AndroidRuntimeException {
+        @UnsupportedAppUsage
         public CalledFromWrongThreadException(String msg) {
             super(msg);
         }
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 3f7ab2a..38dcdd3 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -33,9 +33,14 @@
 import java.util.List;
 
 /**
- * Container for storing additional per-view data generated by {@link View#onProvideStructure
+ * <p><code>ViewStructure</code> is a container for storing additional
+ * per-view data generated by {@link View#onProvideStructure
  * View.onProvideStructure} and {@link View#onProvideAutofillStructure
  * View.onProvideAutofillStructure}.
+ *
+ * <p>To learn more about using Autofill in your app, read the
+ * <a href="/guide/topics/text/autofill">Autofill Framework</a> guides.
+ *
  */
 public abstract class ViewStructure {
 
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 0973d0a..f7c9a0b 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -16,6 +16,10 @@
 
 package android.view;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -39,14 +43,18 @@
     private CopyOnWriteArrayList<OnWindowFocusChangeListener> mOnWindowFocusListeners;
     private CopyOnWriteArrayList<OnWindowAttachListener> mOnWindowAttachListeners;
     private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
+    @UnsupportedAppUsage
     private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
     private CopyOnWriteArrayList<OnEnterAnimationCompleteListener>
             mOnEnterAnimationCompleteListeners;
 
     // Non-recursive listeners use CopyOnWriteArray
     // Any listener invoked from ViewRootImpl.performTraversals() should not be recursive
+    @UnsupportedAppUsage
     private CopyOnWriteArray<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
+    @UnsupportedAppUsage
     private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
+    @UnsupportedAppUsage
     private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners;
     private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners;
     private CopyOnWriteArray<OnWindowShownListener> mOnWindowShownListeners;
@@ -56,6 +64,9 @@
     private ArrayList<OnDrawListener> mOnDrawListeners;
     private static boolean sIllegalOnDrawModificationIsFatal;
 
+    // These listeners are one-shot
+    private ArrayList<Runnable> mOnFrameCommitListeners;
+
     /** Remains false until #dispatchOnWindowShown() is called. If a listener registers after
      * that the listener will be immediately called. */
     private boolean mWindowShown;
@@ -209,12 +220,14 @@
          * Offsets from the frame of the window at which the content of
          * windows behind it should be placed.
          */
+        @UnsupportedAppUsage
         public final Rect contentInsets = new Rect();
 
         /**
          * Offsets from the frame of the window at which windows behind it
          * are visible.
          */
+        @UnsupportedAppUsage
         public final Rect visibleInsets = new Rect();
 
         /**
@@ -222,6 +235,7 @@
          * Only used when {@link #setTouchableInsets(int)} is called with
          * the option {@link #TOUCHABLE_INSETS_REGION}.
          */
+        @UnsupportedAppUsage
         public final Region touchableRegion = new Region();
 
         /**
@@ -246,6 +260,7 @@
          * Option for {@link #setTouchableInsets(int)}: the area inside of
          * the provided touchable region in {@link #touchableRegion} can be touched.
          */
+        @UnsupportedAppUsage
         public static final int TOUCHABLE_INSETS_REGION = 3;
 
         /**
@@ -253,10 +268,12 @@
          * {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT},
          * {@link #TOUCHABLE_INSETS_VISIBLE}, or {@link #TOUCHABLE_INSETS_REGION}.
          */
+        @UnsupportedAppUsage
         public void setTouchableInsets(int val) {
             mTouchableInsets = val;
         }
 
+        @UnsupportedAppUsage
         int mTouchableInsets;
 
         void reset() {
@@ -294,6 +311,7 @@
                     touchableRegion.equals(other.touchableRegion);
         }
 
+        @UnsupportedAppUsage
         void set(InternalInsetsInfo other) {
             contentInsets.set(other.contentInsets);
             visibleInsets.set(other.visibleInsets);
@@ -393,6 +411,14 @@
             }
         }
 
+        if (observer.mOnFrameCommitListeners != null) {
+            if (mOnFrameCommitListeners != null) {
+                mOnFrameCommitListeners.addAll(observer.captureFrameCommitCallbacks());
+            } else {
+                mOnFrameCommitListeners = observer.captureFrameCommitCallbacks();
+            }
+        }
+
         if (observer.mOnTouchModeChangeListeners != null) {
             if (mOnTouchModeChangeListeners != null) {
                 mOnTouchModeChangeListeners.addAll(observer.mOnTouchModeChangeListeners);
@@ -713,6 +739,49 @@
     }
 
     /**
+     * Adds a frame commit callback. This callback will be invoked when the current rendering
+     * content has been rendered into a frame and submitted to the swap chain. The frame may
+     * not currently be visible on the display when this is invoked, but it has been submitted.
+     * This callback is useful in combination with {@link PixelCopy} to capture the current
+     * rendered content of the UI reliably.
+     *
+     * Note: Only works with hardware rendering. Does nothing otherwise.
+     *
+     * @param callback The callback to invoke when the frame is committed.
+     */
+    @TestApi
+    public void registerFrameCommitCallback(@NonNull Runnable callback) {
+        checkIsAlive();
+        if (mOnFrameCommitListeners == null) {
+            mOnFrameCommitListeners = new ArrayList<>();
+        }
+        mOnFrameCommitListeners.add(callback);
+    }
+
+    @Nullable ArrayList<Runnable> captureFrameCommitCallbacks() {
+        ArrayList<Runnable> ret = mOnFrameCommitListeners;
+        mOnFrameCommitListeners = null;
+        return ret;
+    }
+
+    /**
+     * Attempts to remove the given callback from the list of pending frame complete callbacks.
+     *
+     * @param callback The callback to remove
+     * @return Whether or not the callback was removed. If this returns true the callback will
+     *         not be invoked. If false is returned then the callback was either never added
+     *         or may already be pending execution and was unable to be removed
+     */
+    @TestApi
+    public boolean unregisterFrameCommitCallback(@NonNull Runnable callback) {
+        checkIsAlive();
+        if (mOnFrameCommitListeners == null) {
+            return false;
+        }
+        return mOnFrameCommitListeners.remove(callback);
+    }
+
+    /**
      * Register a callback to be invoked when a view has been scrolled.
      *
      * @param listener The callback to add
@@ -791,6 +860,7 @@
      * We are not yet ready to commit to this API and support it, so
      * @hide
      */
+    @UnsupportedAppUsage
     public void addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener listener) {
         checkIsAlive();
 
@@ -814,6 +884,7 @@
      * We are not yet ready to commit to this API and support it, so
      * @hide
      */
+    @UnsupportedAppUsage
     public void removeOnComputeInternalInsetsListener(OnComputeInternalInsetsListener victim) {
         checkIsAlive();
         if (mOnComputeInternalInsetsListeners == null) {
@@ -913,6 +984,7 @@
     /**
      * Notifies registered listeners that focus has changed.
      */
+    @UnsupportedAppUsage
     final void dispatchOnGlobalFocusChange(View oldFocus, View newFocus) {
         // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
         // perform the dispatching. The iterator is a safe guard against listeners that
@@ -1024,6 +1096,7 @@
      *
      * @param inTouchMode True if the touch mode is now enabled, false otherwise.
      */
+    @UnsupportedAppUsage
     final void dispatchOnTouchModeChanged(boolean inTouchMode) {
         final CopyOnWriteArrayList<OnTouchModeChangeListener> listeners =
                 mOnTouchModeChangeListeners;
@@ -1037,6 +1110,7 @@
     /**
      * Notifies registered listeners that something has scrolled.
      */
+    @UnsupportedAppUsage
     final void dispatchOnScrollChanged() {
         // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
         // perform the dispatching. The iterator is a safe guard against listeners that
@@ -1059,6 +1133,7 @@
     /**
      * Returns whether there are listeners for computing internal insets.
      */
+    @UnsupportedAppUsage
     final boolean hasComputeInternalInsetsListeners() {
         final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
                 mOnComputeInternalInsetsListeners;
@@ -1068,6 +1143,7 @@
     /**
      * Calls all listeners to compute the current insets.
      */
+    @UnsupportedAppUsage
     final void dispatchOnComputeInternalInsets(InternalInsetsInfo inoutInfo) {
         // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
         // perform the dispatching. The iterator is a safe guard against listeners that
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 78e4204..f436962 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -25,6 +25,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.app.WindowConfiguration;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -150,6 +151,7 @@
      * Max value used as a feature ID
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int FEATURE_MAX = FEATURE_ACTIVITY_TRANSITIONS;
 
     /**
@@ -267,18 +269,25 @@
      */
     public static final int DECOR_CAPTION_SHADE_DARK = 2;
 
+    @UnsupportedAppUsage
     private final Context mContext;
 
+    @UnsupportedAppUsage
     private TypedArray mWindowStyle;
+    @UnsupportedAppUsage
     private Callback mCallback;
     private OnWindowDismissedCallback mOnWindowDismissedCallback;
     private OnWindowSwipeDismissedCallback mOnWindowSwipeDismissedCallback;
     private WindowControllerCallback mWindowControllerCallback;
     private OnRestrictedCaptionAreaChangedListener mOnRestrictedCaptionAreaChangedListener;
     private Rect mRestrictedCaptionAreaRect;
+    @UnsupportedAppUsage
     private WindowManager mWindowManager;
+    @UnsupportedAppUsage
     private IBinder mAppToken;
+    @UnsupportedAppUsage
     private String mAppName;
+    @UnsupportedAppUsage
     private boolean mHardwareAccelerated;
     private Window mContainer;
     private Window mActiveChild;
@@ -288,7 +297,9 @@
     private boolean mSetCloseOnTouchOutside = false;
     private int mForcedWindowFlags = 0;
 
+    @UnsupportedAppUsage
     private int mFeatures;
+    @UnsupportedAppUsage
     private int mLocalFeatures;
 
     private boolean mHaveWindowFormat = false;
@@ -297,12 +308,14 @@
 
     private boolean mHasSoftInputMode = false;
 
+    @UnsupportedAppUsage
     private boolean mDestroyed;
 
     private boolean mOverlayWithDecorCaptionEnabled = false;
     private boolean mCloseOnSwipeEnabled = false;
 
     // The current window attributes.
+    @UnsupportedAppUsage
     private final WindowManager.LayoutParams mWindowAttributes =
         new WindowManager.LayoutParams();
 
@@ -729,6 +742,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public final boolean isDestroyed() {
         return mDestroyed;
     }
@@ -854,7 +868,7 @@
     }
 
     /**
-     * Set an observer to collect frame stats for each frame rendererd in this window.
+     * Set an observer to collect frame stats for each frame rendered in this window.
      *
      * Must be in hardware rendering mode.
      */
@@ -1066,6 +1080,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void addPrivateFlags(int flags) {
         setPrivateFlags(flags, flags);
     }
@@ -1116,6 +1131,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected void setNeedsMenuKey(int value) {
         final WindowManager.LayoutParams attrs = getAttributes();
         attrs.needsMenuKey = value;
@@ -1236,12 +1252,14 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setCloseOnTouchOutside(boolean close) {
         mCloseOnTouchOutside = close;
         mSetCloseOnTouchOutside = true;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setCloseOnTouchOutsideIfNotSet(boolean close) {
         if (!mSetCloseOnTouchOutside) {
             mCloseOnTouchOutside = close;
@@ -1250,9 +1268,11 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public abstract void alwaysReadCloseOnTouchAttr();
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
         final boolean isOutside =
                 event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(context, event)
diff --git a/core/java/android/view/WindowAnimationFrameStats.java b/core/java/android/view/WindowAnimationFrameStats.java
index c60b96c..0233c86 100644
--- a/core/java/android/view/WindowAnimationFrameStats.java
+++ b/core/java/android/view/WindowAnimationFrameStats.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -47,6 +48,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void init(long refreshPeriodNano, long[] framesPresentedTimeNano) {
         mRefreshPeriodNano = refreshPeriodNano;
         mFramesPresentedTimeNano = framesPresentedTimeNano;
diff --git a/core/java/android/view/WindowContentFrameStats.java b/core/java/android/view/WindowContentFrameStats.java
index c6da2fb..96878e9 100644
--- a/core/java/android/view/WindowContentFrameStats.java
+++ b/core/java/android/view/WindowContentFrameStats.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -60,6 +61,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void init(long refreshPeriodNano, long[] framesPostedTimeNano,
             long[] framesPresentedTimeNano, long[] framesReadyTimeNano) {
         mRefreshPeriodNano = refreshPeriodNano;
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index fbd8141..8628da3 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -18,6 +18,7 @@
 package android.view;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 
 import com.android.internal.util.Preconditions;
@@ -69,6 +70,7 @@
      * since it would allow them to inadvertently consume unknown insets by returning it.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final WindowInsets CONSUMED;
 
     static {
@@ -115,6 +117,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public WindowInsets(Rect systemWindowInsets) {
         this(systemWindowInsets, null, null, false, false, null);
     }
@@ -124,6 +127,7 @@
      * to the existing fitSystemWindows method and other similar internals.
      * @hide
      */
+    @UnsupportedAppUsage
     public Rect getSystemWindowInsets() {
         if (mTempRect == null) {
             mTempRect = new Rect();
@@ -578,6 +582,7 @@
      *
      * @hide pending API
      */
+    @UnsupportedAppUsage
     public WindowInsets inset(int left, int top, int right, int bottom) {
         Preconditions.checkArgumentNonnegative(left);
         Preconditions.checkArgumentNonnegative(top);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 4d7b73c..0404df0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -50,6 +50,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.KeyguardManager;
 import android.app.Presentation;
 import android.content.Context;
@@ -674,6 +675,7 @@
          * is a big ugly hack so:
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW + 4;
 
         /**
@@ -826,6 +828,7 @@
          * In multiuser systems shows only on the owning user's window.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;
 
         /**
@@ -901,6 +904,7 @@
          * In multiuser systems shows on all users' windows.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26;
 
         /**
@@ -1391,6 +1395,7 @@
          *
          * {@hide}
          */
+        @UnsupportedAppUsage
         public static final int FLAG_SLIPPERY = 0x20000000;
 
         /**
@@ -1554,6 +1559,7 @@
          * to determine its default behavior.
          *
          * {@hide} */
+        @UnsupportedAppUsage
         public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
 
         /**
@@ -1692,6 +1698,15 @@
         public static final int PRIVATE_FLAG_IS_SCREEN_DECOR = 0x00400000;
 
         /**
+         * Flag to indicate that the status bar window is in a state such that it forces showing
+         * the navigation bar unless the navigation bar window is explicitly set to
+         * {@link View#GONE}.
+         * It only takes effects if this is set by {@link LayoutParams#TYPE_STATUS_BAR}.
+         * @hide
+         */
+        public static final int PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION = 0x00800000;
+
+        /**
          * Control flags that are private to the platform.
          * @hide
          */
@@ -1779,7 +1794,11 @@
                 @ViewDebug.FlagToString(
                         mask = PRIVATE_FLAG_IS_SCREEN_DECOR,
                         equals = PRIVATE_FLAG_IS_SCREEN_DECOR,
-                        name = "IS_SCREEN_DECOR")
+                        name = "IS_SCREEN_DECOR"),
+                @ViewDebug.FlagToString(
+                        mask = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION,
+                        equals = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION,
+                        name = "STATUS_FORCE_SHOW_NAVIGATION")
         })
         @TestApi
         public int privateFlags;
@@ -1800,6 +1819,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int NEEDS_MENU_SET_TRUE = 1;
 
         /**
@@ -1808,6 +1828,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int NEEDS_MENU_SET_FALSE = 2;
 
         /**
@@ -1821,6 +1842,7 @@
          *
          * {@hide}
          */
+        @UnsupportedAppUsage
         public int needsMenuKey = NEEDS_MENU_UNSET;
 
         /**
@@ -2225,6 +2247,7 @@
          * The ui visibility as requested by the views in this hierarchy.
          * the combined value should be systemUiVisibility | subtreeSystemUiVisibility.
          */
+        @UnsupportedAppUsage
         public int subtreeSystemUiVisibility;
 
         /**
@@ -2234,6 +2257,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public boolean hasSystemUiListeners;
 
 
@@ -2385,6 +2409,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004;
 
         /**
@@ -2395,6 +2420,7 @@
          * @see #INPUT_FEATURE_DISABLE_USER_ACTIVITY
          * @hide
          */
+        @UnsupportedAppUsage
         public int inputFeatures;
 
         /**
@@ -2410,6 +2436,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public long userActivityTimeout = -1;
 
         /**
@@ -2441,6 +2468,7 @@
          *
          * @hide
          */
+        @UnsupportedAppUsage
         public long hideTimeoutMilliseconds = -1;
 
         /**
@@ -3111,6 +3139,7 @@
          * Backup the layout parameters used in compatibility mode.
          * @see LayoutParams#restore()
          */
+        @UnsupportedAppUsage
         void backup() {
             int[] backup = mCompatibilityParamsBackup;
             if (backup == null) {
@@ -3127,6 +3156,7 @@
          * Restore the layout params' coordinates, size and gravity
          * @see LayoutParams#backup()
          */
+        @UnsupportedAppUsage
         void restore() {
             int[] backup = mCompatibilityParamsBackup;
             if (backup != null) {
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 08c2d0b..d810067 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.animation.ValueAnimator;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.content.ComponentCallbacks2;
 import android.content.Context;
@@ -131,14 +132,21 @@
     public static final int ADD_INVALID_DISPLAY = -9;
     public static final int ADD_INVALID_TYPE = -10;
 
+    @UnsupportedAppUsage
     private static WindowManagerGlobal sDefaultWindowManager;
+    @UnsupportedAppUsage
     private static IWindowManager sWindowManagerService;
+    @UnsupportedAppUsage
     private static IWindowSession sWindowSession;
 
+    @UnsupportedAppUsage
     private final Object mLock = new Object();
 
+    @UnsupportedAppUsage
     private final ArrayList<View> mViews = new ArrayList<View>();
+    @UnsupportedAppUsage
     private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
+    @UnsupportedAppUsage
     private final ArrayList<WindowManager.LayoutParams> mParams =
             new ArrayList<WindowManager.LayoutParams>();
     private final ArraySet<View> mDyingViews = new ArraySet<View>();
@@ -148,10 +156,12 @@
     private WindowManagerGlobal() {
     }
 
+    @UnsupportedAppUsage
     public static void initialize() {
         getWindowManagerService();
     }
 
+    @UnsupportedAppUsage
     public static WindowManagerGlobal getInstance() {
         synchronized (WindowManagerGlobal.class) {
             if (sDefaultWindowManager == null) {
@@ -161,6 +171,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static IWindowManager getWindowManagerService() {
         synchronized (WindowManagerGlobal.class) {
             if (sWindowManagerService == null) {
@@ -179,6 +190,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static IWindowSession getWindowSession() {
         synchronized (WindowManagerGlobal.class) {
             if (sWindowSession == null) {
@@ -201,12 +213,14 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static IWindowSession peekWindowSession() {
         synchronized (WindowManagerGlobal.class) {
             return sWindowSession;
         }
     }
 
+    @UnsupportedAppUsage
     public String[] getViewRootNames() {
         synchronized (mLock) {
             final int numRoots = mRoots.size();
@@ -218,6 +232,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public ArrayList<ViewRootImpl> getRootViews(IBinder token) {
         ArrayList<ViewRootImpl> views = new ArrayList<>();
         synchronized (mLock) {
@@ -264,6 +279,7 @@
         return null;
     }
 
+    @UnsupportedAppUsage
     public View getRootView(String name) {
         synchronized (mLock) {
             for (int i = mRoots.size() - 1; i >= 0; --i) {
@@ -385,6 +401,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void removeView(View view, boolean immediate) {
         if (view == null) {
             throw new IllegalArgumentException("view must not be null");
@@ -500,6 +517,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     public void trimMemory(int level) {
         if (ThreadedRenderer.isAvailable()) {
             if (shouldDestroyEglContext(level)) {
@@ -647,6 +665,7 @@
 }
 
 final class WindowLeaked extends AndroidRuntimeException {
+    @UnsupportedAppUsage
     public WindowLeaked(String msg) {
         super(msg);
     }
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index a8722f1..2339d35 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.Region;
 import android.os.Bundle;
@@ -54,6 +55,7 @@
  * @hide
  */
 public final class WindowManagerImpl implements WindowManager {
+    @UnsupportedAppUsage
     private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
     private final Context mContext;
     private final Window mParentWindow;
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index da5a1cd..5d59e42 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -306,6 +306,11 @@
 
                 final int oldChildCount = oldInfo.getChildCount();
                 for (int i = 0; i < oldChildCount; i++) {
+                    final long oldChildId = oldInfo.getChildId(i);
+                    // If the child is no longer present, remove the sub-tree.
+                    if (newChildrenIds == null || newChildrenIds.indexOf(oldChildId) < 0) {
+                        clearSubTreeLocked(windowId, oldChildId);
+                    }
                     if (nodes.get(sourceId) == null) {
                         // We've removed (and thus recycled) this node because it was its own
                         // ancestor (the app gave us bad data), we can't continue using it.
@@ -313,11 +318,6 @@
                         clearNodesForWindowLocked(windowId);
                         return;
                     }
-                    final long oldChildId = oldInfo.getChildId(i);
-                    // If the child is no longer present, remove the sub-tree.
-                    if (newChildrenIds == null || newChildrenIds.indexOf(oldChildId) < 0) {
-                        clearSubTreeLocked(windowId, oldChildId);
-                    }
                 }
 
                 // Also be careful if the parent has changed since the new
@@ -336,7 +336,13 @@
             AccessibilityNodeInfo clone = AccessibilityNodeInfo.obtain(info);
             nodes.put(sourceId, clone);
             if (clone.isAccessibilityFocused()) {
+                if (mAccessibilityFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID
+                        && mAccessibilityFocus != sourceId) {
+                    refreshCachedNodeLocked(windowId, mAccessibilityFocus);
+                }
                 mAccessibilityFocus = sourceId;
+            } else if (mAccessibilityFocus == sourceId) {
+                mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
             }
             if (clone.isFocused()) {
                 mInputFocus = sourceId;
@@ -418,20 +424,28 @@
      *
      * @param nodes The nodes in the hosting window.
      * @param rootNodeId The id of the root to evict.
+     *
+     * @return {@code true} if the cache was cleared
      */
-    private void clearSubTreeRecursiveLocked(LongSparseArray<AccessibilityNodeInfo> nodes,
+    private boolean clearSubTreeRecursiveLocked(LongSparseArray<AccessibilityNodeInfo> nodes,
             long rootNodeId) {
         AccessibilityNodeInfo current = nodes.get(rootNodeId);
         if (current == null) {
-            return;
+            // The node isn't in the cache, but its descendents might be.
+            clear();
+            return true;
         }
         nodes.remove(rootNodeId);
         final int childCount = current.getChildCount();
         for (int i = 0; i < childCount; i++) {
             final long childNodeId = current.getChildId(i);
-            clearSubTreeRecursiveLocked(nodes, childNodeId);
+            if (clearSubTreeRecursiveLocked(nodes, childNodeId)) {
+                current.recycle();
+                return true;
+            }
         }
         current.recycle();
+        return false;
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index a6b8eb3..3eca854 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -17,6 +17,7 @@
 package android.view.accessibility;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -755,10 +756,12 @@
     private static final SynchronizedPool<AccessibilityEvent> sPool =
             new SynchronizedPool<>(MAX_POOL_SIZE);
 
+    @UnsupportedAppUsage
     private @EventType int mEventType;
     private CharSequence mPackageName;
     private long mEventTime;
     int mMovementGranularity;
+    @UnsupportedAppUsage
     int mAction;
     int mContentChangeTypes;
     int mWindowChangeTypes;
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index d60c481..4db6f4f 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -17,6 +17,7 @@
 package android.view.accessibility;
 
 import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -112,6 +113,7 @@
     /**
      * @return The client for the current thread.
      */
+    @UnsupportedAppUsage
     public static AccessibilityInteractionClient getInstance() {
         final long threadId = Thread.currentThread().getId();
         return getInstanceForThread(threadId);
@@ -190,6 +192,7 @@
      *
      * @param message The message.
      */
+    @UnsupportedAppUsage
     public void setSameThreadMessage(Message message) {
         synchronized (mInstanceLock) {
             mSameThreadMessage = message;
@@ -625,6 +628,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     public void clearCache() {
         sAccessibilityCache.clear();
     }
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index cbb23f1..c59c491 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -25,6 +25,7 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -88,6 +89,7 @@
     public static final int DALTONIZER_DISABLED = -1;
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final int DALTONIZER_SIMULATE_MONOCHROMACY = 0;
 
     /** @hide */
@@ -112,30 +114,39 @@
     public static final String ACTION_CHOOSE_ACCESSIBILITY_BUTTON =
             "com.android.internal.intent.action.CHOOSE_ACCESSIBILITY_BUTTON";
 
+    @UnsupportedAppUsage
     static final Object sInstanceSync = new Object();
 
+    @UnsupportedAppUsage
     private static AccessibilityManager sInstance;
 
+    @UnsupportedAppUsage
     private final Object mLock = new Object();
 
+    @UnsupportedAppUsage
     private IAccessibilityManager mService;
 
+    @UnsupportedAppUsage
     final int mUserId;
 
+    @UnsupportedAppUsage
     final Handler mHandler;
 
     final Handler.Callback mCallback;
 
+    @UnsupportedAppUsage
     boolean mIsEnabled;
 
     int mRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK;
 
     boolean mIsTouchExplorationEnabled;
 
+    @UnsupportedAppUsage
     boolean mIsHighTextContrastEnabled;
 
     AccessibilityPolicy mAccessibilityPolicy;
 
+    @UnsupportedAppUsage
     private final ArrayMap<AccessibilityStateChangeListener, Handler>
             mAccessibilityStateChangeListeners = new ArrayMap<>();
 
@@ -318,6 +329,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static AccessibilityManager getInstance(Context context) {
         synchronized (sInstanceSync) {
             if (sInstance == null) {
@@ -430,6 +442,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isHighTextContrastEnabled() {
         synchronized (mLock) {
             IAccessibilityManager service = getServiceLocked();
@@ -916,6 +929,7 @@
      *
      * @param stateFlags The state flags.
      */
+    @UnsupportedAppUsage
     private void setStateLocked(int stateFlags) {
         final boolean enabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
         final boolean touchExplorationEnabled =
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index e8e6537..a3fa2ce 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -25,6 +25,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -601,22 +602,14 @@
 
     private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
 
-    private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
-
     private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
 
     private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
 
-    private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
-
-    private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
-
     private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
 
     private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
 
-    private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
-
     private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
 
     private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
@@ -631,8 +624,6 @@
 
     private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
 
-    private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
-
     private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000;
 
     private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 0x0080000;
@@ -662,6 +653,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getAccessibilityViewId(long accessibilityNodeId) {
         return (int) accessibilityNodeId;
     }
@@ -675,6 +667,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getVirtualDescendantId(long accessibilityNodeId) {
         return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
                 >> VIRTUAL_DESCENDANT_ID_SHIFT);
@@ -702,10 +695,12 @@
 
     private static final AccessibilityNodeInfo DEFAULT = new AccessibilityNodeInfo();
 
+    @UnsupportedAppUsage
     private boolean mSealed;
 
     // Data.
     private int mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+    @UnsupportedAppUsage
     private long mSourceNodeId = UNDEFINED_NODE_ID;
     private long mParentNodeId = UNDEFINED_NODE_ID;
     private long mLabelForId = UNDEFINED_NODE_ID;
@@ -731,6 +726,7 @@
     private String mViewIdResourceName;
     private ArrayList<String> mExtraDataKeys;
 
+    @UnsupportedAppUsage
     private LongArray mChildNodeIds;
     private ArrayList<AccessibilityAction> mActions;
 
@@ -865,6 +861,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean refresh(Bundle arguments, boolean bypassCache) {
         enforceSealed();
         if (!canPerformRequestOverConnection(mSourceNodeId)) {
@@ -1168,6 +1165,16 @@
         mActions.add(action);
     }
 
+    private boolean hasActionWithId(int actionId) {
+        List<AccessibilityAction> actions = getActionList();
+        for (int i = 0; i < actions.size(); i++) {
+            if (actions.get(i).getId() == actionId) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Adds an action that can be performed on the node.
      * <p>
@@ -1767,7 +1774,7 @@
      * @return True if the node is focusable.
      */
     public boolean isFocusable() {
-        return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
+        return hasActionWithId(ACTION_FOCUS) || hasActionWithId(ACTION_CLEAR_FOCUS);
     }
 
     /**
@@ -1781,10 +1788,11 @@
      * @param focusable True if the node is focusable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
+     * @deprecated Use {@link #addAction(AccessibilityAction)}
+     * with {@link AccessibilityAction#ACTION_FOCUS}
      */
-    public void setFocusable(boolean focusable) {
-        setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
-    }
+    @Deprecated
+    public void setFocusable(boolean focusable) { }
 
     /**
      * Gets whether this node is focused.
@@ -1892,7 +1900,7 @@
      * @return True if the node is clickable.
      */
     public boolean isClickable() {
-        return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
+        return hasActionWithId(ACTION_CLICK);
     }
 
     /**
@@ -1906,10 +1914,11 @@
      * @param clickable True if the node is clickable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
+     * @deprecated Use {@link #addAction(AccessibilityAction)}
+     * with {@link AccessibilityAction#ACTION_CLICK}
      */
-    public void setClickable(boolean clickable) {
-        setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
-    }
+    @Deprecated
+    public void setClickable(boolean clickable) { }
 
     /**
      * Gets whether this node is long clickable.
@@ -1917,7 +1926,7 @@
      * @return True if the node is long clickable.
      */
     public boolean isLongClickable() {
-        return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
+        return hasActionWithId(ACTION_LONG_CLICK);
     }
 
     /**
@@ -1931,10 +1940,11 @@
      * @param longClickable True if the node is long clickable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
+     * @deprecated Use {@link #addAction(AccessibilityAction)}
+     * with {@link AccessibilityAction#ACTION_LONG_CLICK}
      */
-    public void setLongClickable(boolean longClickable) {
-        setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
-    }
+    @Deprecated
+    public void setLongClickable(boolean longClickable) { }
 
     /**
      * Gets whether this node is enabled.
@@ -1992,7 +2002,13 @@
      * @return True if the node is scrollable, false otherwise.
      */
     public boolean isScrollable() {
-        return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
+        return hasActionWithId(ACTION_SCROLL_BACKWARD)
+                || hasActionWithId(ACTION_SCROLL_FORWARD)
+                || hasActionWithId(R.id.accessibilityActionScrollToPosition)
+                || hasActionWithId(R.id.accessibilityActionScrollUp)
+                || hasActionWithId(R.id.accessibilityActionScrollDown)
+                || hasActionWithId(R.id.accessibilityActionScrollLeft)
+                || hasActionWithId(R.id.accessibilityActionScrollRight);
     }
 
     /**
@@ -2006,9 +2022,11 @@
      * @param scrollable True if the node is scrollable, false otherwise.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
+     * @deprecated Use {@link #addAction(AccessibilityAction)}
      */
+    @Deprecated
+
     public void setScrollable(boolean scrollable) {
-        setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
     }
 
     /**
@@ -2199,7 +2217,7 @@
      * @return True if the node is context clickable.
      */
     public boolean isContextClickable() {
-        return getBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE);
+        return hasActionWithId(R.id.accessibilityActionContextClick);
     }
 
     /**
@@ -2212,10 +2230,11 @@
      *
      * @param contextClickable True if the node is context clickable.
      * @throws IllegalStateException If called from an AccessibilityService.
+     * @deprecated Use {@link #addAction(AccessibilityAction)}
+     * with {@link AccessibilityAction#ACTION_CONTEXT_CLICK}
      */
-    public void setContextClickable(boolean contextClickable) {
-        setBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE, contextClickable);
-    }
+    @Deprecated
+    public void setContextClickable(boolean contextClickable) { }
 
     /**
      * Gets the node's live region mode.
@@ -2309,7 +2328,7 @@
      * @return If the node can be dismissed.
      */
     public boolean isDismissable() {
-        return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE);
+        return hasActionWithId(ACTION_DISMISS);
     }
 
     /**
@@ -2321,10 +2340,11 @@
      * </p>
      *
      * @param dismissable If the node can be dismissed.
+     * @deprecated Use {@link #addAction(AccessibilityAction)}
+     * with {@link AccessibilityAction#ACTION_DISMISS}
      */
-    public void setDismissable(boolean dismissable) {
-        setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
-    }
+    @Deprecated
+    public void setDismissable(boolean dismissable) { }
 
     /**
      * Returns whether the node originates from a view considered important for accessibility.
@@ -3008,6 +3028,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long getSourceNodeId() {
         return mSourceNodeId;
     }
@@ -3019,6 +3040,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSealed(boolean sealed) {
         mSealed = sealed;
     }
@@ -3030,6 +3052,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isSealed() {
         return mSealed;
     }
@@ -3915,7 +3938,8 @@
      * </li>
      * <li><strong>Overriden standard actions</strong> - These are actions that override
      * standard actions to customize them. For example, an app may add a label to the
-     * standard {@link #ACTION_CLICK} action to announce that this action clears browsing history.
+     * standard {@link #ACTION_CLICK} action to indicate to the user that this action clears
+     * browsing history.
      * </ul>
      * </p>
      * <p>
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 0a709f8..b382a18 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -19,6 +19,7 @@
 import static com.android.internal.util.CollectionUtils.isEmpty;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 import android.view.View;
 
@@ -82,6 +83,7 @@
     private AccessibilityRecord mNext;
     private boolean mIsInPool;
 
+    @UnsupportedAppUsage
     boolean mSealed;
     int mBooleanProperties = 0;
     int mCurrentItemIndex = UNDEFINED;
@@ -98,6 +100,7 @@
 
     int mAddedCount= UNDEFINED;
     int mRemovedCount = UNDEFINED;
+    @UnsupportedAppUsage
     long mSourceNodeId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
     int mSourceWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
 
@@ -625,7 +628,7 @@
     }
 
     /**
-     * Sets the text before a change.
+     * Gets the text before a change.
      *
      * @return The text before the change.
      */
@@ -696,6 +699,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long getSourceNodeId() {
         return mSourceNodeId;
     }
diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java
index d6455e7..c42e9fe 100644
--- a/core/java/android/view/accessibility/CaptioningManager.java
+++ b/core/java/android/view/accessibility/CaptioningManager.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -286,6 +287,7 @@
         public static final CaptionStyle DEFAULT;
 
         /** @hide */
+        @UnsupportedAppUsage
         public static final CaptionStyle[] PRESETS;
 
         /** @hide */
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 64686dd..87b7b05 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -19,6 +19,7 @@
 import android.annotation.AnimRes;
 import android.annotation.ColorInt;
 import android.annotation.InterpolatorRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.RectF;
@@ -183,6 +184,7 @@
     /**
      * The animation listener to be notified when the animation starts, ends or repeats.
      */
+    @UnsupportedAppUsage
     AnimationListener mListener;
 
     /**
@@ -211,9 +213,13 @@
     private boolean mMore = true;
     private boolean mOneMoreTime = true;
 
+    @UnsupportedAppUsage
     RectF mPreviousRegion = new RectF();
+    @UnsupportedAppUsage
     RectF mRegion = new RectF();
+    @UnsupportedAppUsage
     Transformation mTransformation = new Transformation();
+    @UnsupportedAppUsage
     Transformation mPreviousTransformation = new Transformation();
 
     private final CloseGuard guard = CloseGuard.get();
@@ -322,6 +328,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void detach() {
         if (mStarted && !mEnded) {
             mEnded = true;
@@ -1046,6 +1053,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void getInvalidateRegion(int left, int top, int right, int bottom,
             RectF invalidate, Transformation transformation) {
 
@@ -1077,6 +1085,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void initializeInvalidateRegion(int left, int top, int right, int bottom) {
         final RectF region = mPreviousRegion;
         region.set(left, top, right, bottom);
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 29f8442..c877b9c 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -19,6 +19,7 @@
 import android.annotation.AnimRes;
 import android.annotation.InterpolatorRes;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
@@ -157,6 +158,7 @@
         return createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser));
     }
 
+    @UnsupportedAppUsage
     private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
             AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
 
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
index 8eb5b5c..58da04d 100644
--- a/core/java/android/view/animation/Transformation.java
+++ b/core/java/android/view/animation/Transformation.java
@@ -17,6 +17,7 @@
 package android.view.animation;
 
 import android.annotation.FloatRange;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 
@@ -238,6 +239,7 @@
      * Print short string, to optimize dumping.
      * @hide
      */
+    @UnsupportedAppUsage
     public void printShortString(PrintWriter pw) {
         pw.print("{alpha="); pw.print(mAlpha);
         pw.print(" matrix=");
diff --git a/core/java/android/view/animation/TranslateAnimation.java b/core/java/android/view/animation/TranslateAnimation.java
index 216022b..6c040d4 100644
--- a/core/java/android/view/animation/TranslateAnimation.java
+++ b/core/java/android/view/animation/TranslateAnimation.java
@@ -16,6 +16,7 @@
 
 package android.view.animation;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -34,13 +35,17 @@
     private int mToYType = ABSOLUTE;
 
     /** @hide */
+    @UnsupportedAppUsage
     protected float mFromXValue = 0.0f;
     /** @hide */
+    @UnsupportedAppUsage
     protected float mToXValue = 0.0f;
 
     /** @hide */
+    @UnsupportedAppUsage
     protected float mFromYValue = 0.0f;
     /** @hide */
+    @UnsupportedAppUsage
     protected float mToYValue = 0.0f;
 
     /** @hide */
diff --git a/core/java/android/view/animation/TranslateYAnimation.java b/core/java/android/view/animation/TranslateYAnimation.java
index 714558d..a6e0ccb 100644
--- a/core/java/android/view/animation/TranslateYAnimation.java
+++ b/core/java/android/view/animation/TranslateYAnimation.java
@@ -16,6 +16,7 @@
 
 package android.view.animation;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Matrix;
 
 /**
@@ -38,6 +39,7 @@
     /**
      * Constructor. Passes in 0 for the x parameters of TranslateAnimation
      */
+    @UnsupportedAppUsage
     public TranslateYAnimation(int fromYType, float fromYValue, int toYType, float toYValue) {
         super(ABSOLUTE, 0, ABSOLUTE, 0, fromYType, fromYValue, toYType, toYValue);
     }
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 8f28102..9419e93 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -34,6 +34,7 @@
 import android.content.pm.ResolveInfo;
 import android.graphics.Rect;
 import android.metrics.LogMaker;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcelable;
@@ -57,6 +58,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.os.IResultReceiver;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
 
@@ -72,16 +74,23 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 //TODO: use java.lang.ref.Cleaner once Android supports Java 9
 import sun.misc.Cleaner;
 
 /**
- * The {@link AutofillManager} provides ways for apps and custom views to integrate with the
- * Autofill Framework lifecycle.
+ * <p>The {@link AutofillManager} class provides ways for apps and custom views to
+ * integrate with the Autofill Framework lifecycle.
+ *
+ * <p>To learn about using Autofill in your app, read
+ * the <a href="/guide/topics/text/autofill">Autofill Framework</a> guides.
+ *
+ * <h3 id="autofill-lifecycle">Autofill lifecycle</h3>
  *
  * <p>The autofill lifecycle starts with the creation of an autofill context associated with an
- * activity context; the autofill context is created when one of the following methods is called for
+ * activity context. The autofill context is created when one of the following methods is called for
  * the first time in an activity context, and the current user has an enabled autofill service:
  *
  * <ul>
@@ -90,7 +99,7 @@
  *   <li>{@link #requestAutofill(View)}
  * </ul>
  *
- * <p>Tipically, the context is automatically created when the first view of the activity is
+ * <p>Typically, the context is automatically created when the first view of the activity is
  * focused because {@code View.onFocusChanged()} indirectly calls
  * {@link #notifyViewEntered(View)}. App developers can call {@link #requestAutofill(View)} to
  * explicitly create it (for example, a custom view developer could offer a contextual menu action
@@ -134,7 +143,9 @@
  * shows an autofill save UI if the value of savable views have changed. If the user selects the
  * option to Save, the current value of the views is then sent to the autofill service.
  *
- * <p>It is safe to call into its methods from any thread.
+ * <h3 id="additional-notes">Additional notes</h3>
+ *
+ * <p>It is safe to call <code>AutofillManager</code> methods from any thread.
  */
 @SystemService(Context.AUTOFILL_MANAGER_SERVICE)
 @RequiresFeature(PackageManager.FEATURE_AUTOFILL)
@@ -199,10 +210,17 @@
     /** @hide */ public static final int ACTION_VIEW_EXITED = 3;
     /** @hide */ public static final int ACTION_VALUE_CHANGED = 4;
 
-
+    /** @hide */ public static final int NO_LOGGING = 0;
     /** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED = 0x1;
     /** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2;
     /** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4;
+    /** @hide */
+    public static final int DEFAULT_LOGGING_LEVEL = Build.IS_DEBUGGABLE
+            ? AutofillManager.FLAG_ADD_CLIENT_DEBUG
+            : AutofillManager.NO_LOGGING;
+
+    /** @hide */
+    public static final int DEFAULT_MAX_PARTITIONS_SIZE = 10;
 
     /** Which bits in an authentication id are used for the dataset id */
     private static final int AUTHENTICATION_ID_DATASET_ID_MASK = 0xFFFF;
@@ -572,10 +590,11 @@
 
                 final AutofillClient client = getClient();
                 if (client != null) {
+                    final SyncResultReceiver receiver = new SyncResultReceiver();
                     try {
-                        final boolean sessionWasRestored = mService.restoreSession(mSessionId,
-                                client.autofillClientGetActivityToken(),
-                                mServiceClient.asBinder());
+                        mService.restoreSession(mSessionId, client.autofillClientGetActivityToken(),
+                                mServiceClient.asBinder(), receiver);
+                        final boolean sessionWasRestored = receiver.getIntResult() == 1;
 
                         if (!sessionWasRestored) {
                             Log.w(TAG, "Session " + mSessionId + " could not be restored");
@@ -691,7 +710,9 @@
      */
     @Nullable public FillEventHistory getFillEventHistory() {
         try {
-            return mService.getFillEventHistory();
+            final SyncResultReceiver receiver = new SyncResultReceiver();
+            mService.getFillEventHistory(receiver);
+            return receiver.getObjectResult(SyncResultReceiver.TYPE_PARCELABLE);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return null;
@@ -1242,8 +1263,10 @@
     public boolean hasEnabledAutofillServices() {
         if (mService == null) return false;
 
+        final SyncResultReceiver receiver = new SyncResultReceiver();
         try {
-            return mService.isServiceEnabled(mContext.getUserId(), mContext.getPackageName());
+            mService.isServiceEnabled(mContext.getUserId(), mContext.getPackageName(), receiver);
+            return receiver.getIntResult() == 1;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1257,8 +1280,10 @@
     public ComponentName getAutofillServiceComponentName() {
         if (mService == null) return null;
 
+        final SyncResultReceiver receiver = new SyncResultReceiver();
         try {
-            return mService.getAutofillServiceComponentName();
+            mService.getAutofillServiceComponentName(receiver);
+            return receiver.getObjectResult(SyncResultReceiver.TYPE_PARCELABLE);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1281,7 +1306,9 @@
      */
     @Nullable public String getUserDataId() {
         try {
-            return mService.getUserDataId();
+            final SyncResultReceiver receiver = new SyncResultReceiver();
+            mService.getUserDataId(receiver);
+            return receiver.getObjectResult(SyncResultReceiver.TYPE_STRING);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return null;
@@ -1301,7 +1328,9 @@
      */
     @Nullable public UserData getUserData() {
         try {
-            return mService.getUserData();
+            final SyncResultReceiver receiver = new SyncResultReceiver();
+            mService.getUserData(receiver);
+            return receiver.getObjectResult(SyncResultReceiver.TYPE_PARCELABLE);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return null;
@@ -1337,8 +1366,10 @@
      * the user.
      */
     public boolean isFieldClassificationEnabled() {
+        final SyncResultReceiver receiver = new SyncResultReceiver();
         try {
-            return mService.isFieldClassificationEnabled();
+            mService.isFieldClassificationEnabled(receiver);
+            return receiver.getIntResult() == 1;
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return false;
@@ -1358,8 +1389,10 @@
      */
     @Nullable
     public String getDefaultFieldClassificationAlgorithm() {
+        final SyncResultReceiver receiver = new SyncResultReceiver();
         try {
-            return mService.getDefaultFieldClassificationAlgorithm();
+            mService.getDefaultFieldClassificationAlgorithm(receiver);
+            return receiver.getObjectResult(SyncResultReceiver.TYPE_STRING);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return null;
@@ -1376,9 +1409,11 @@
      */
     @NonNull
     public List<String> getAvailableFieldClassificationAlgorithms() {
-        final String[] algorithms;
+        final SyncResultReceiver receiver = new SyncResultReceiver();
         try {
-            algorithms = mService.getAvailableFieldClassificationAlgorithms();
+            mService.getAvailableFieldClassificationAlgorithms(receiver);
+            final String[] algorithms = receiver
+                .getObjectResult(SyncResultReceiver.TYPE_STRING_ARRAY);
             return algorithms != null ? Arrays.asList(algorithms) : Collections.emptyList();
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
@@ -1399,8 +1434,10 @@
     public boolean isAutofillSupported() {
         if (mService == null) return false;
 
+        final SyncResultReceiver receiver = new SyncResultReceiver();
         try {
-            return mService.isServiceSupported(mContext.getUserId());
+            mService.isServiceSupported(mContext.getUserId(), receiver);
+            return receiver.getIntResult() == 1;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1521,10 +1558,12 @@
             final AutofillClient client = getClient();
             if (client == null) return; // NOTE: getClient() already logged it..
 
-            mSessionId = mService.startSession(client.autofillClientGetActivityToken(),
+            final SyncResultReceiver receiver = new SyncResultReceiver();
+            mService.startSession(client.autofillClientGetActivityToken(),
                     mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
                     mCallback != null, flags, client.autofillClientGetComponentName(),
-                    isCompatibilityModeEnabledLocked());
+                    isCompatibilityModeEnabledLocked(), receiver);
+            mSessionId = receiver.getIntResult();
             if (mSessionId != NO_SESSION) {
                 mState = STATE_ACTIVE;
             }
@@ -1602,7 +1641,9 @@
             mServiceClient = new AutofillManagerClient(this);
             try {
                 final int userId = mContext.getUserId();
-                final int flags = mService.addClient(mServiceClient, userId);
+                final SyncResultReceiver receiver = new SyncResultReceiver();
+                mService.addClient(mServiceClient, userId, receiver);
+                final int flags = receiver.getIntResult();
                 mEnabled = (flags & FLAG_ADD_CLIENT_ENABLED) != 0;
                 sDebug = (flags & FLAG_ADD_CLIENT_DEBUG) != 0;
                 sVerbose = (flags & FLAG_ADD_CLIENT_VERBOSE) != 0;
@@ -1923,7 +1964,7 @@
                         mFillableIds.add(id);
                     }
                     if (sVerbose) {
-                        Log.v(TAG, "setTrackedViews(): fillableIds=" + fillableIds
+                        Log.v(TAG, "setTrackedViews(): fillableIds=" + Arrays.toString(fillableIds)
                                 + ", mFillableIds" + mFillableIds);
                     }
                 }
@@ -2118,7 +2159,11 @@
         pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId);
         pw.print(pfx); pw.print("state: "); pw.println(getStateAsStringLocked());
         pw.print(pfx); pw.print("context: "); pw.println(mContext);
-        pw.print(pfx); pw.print("client: "); pw.println(getClient());
+        final AutofillClient client = getClient();
+        if (client != null) {
+            pw.print(pfx); pw.print("client: "); pw.print(client);
+            pw.print(" ("); pw.print(client.autofillClientGetActivityToken()); pw.println(')');
+        }
         pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled);
         pw.print(pfx); pw.print("hasService: "); pw.println(mService != null);
         pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null);
@@ -2138,8 +2183,24 @@
         pw.print(pfx); pw.print("entered ids: "); pw.println(mEnteredIds);
         pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId);
         pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish);
-        pw.print(pfx); pw.print("compat mode enabled: "); pw.println(
-                isCompatibilityModeEnabledLocked());
+        pw.print(pfx); pw.print("compat mode enabled: ");
+        synchronized (mLock) {
+            if (mCompatibilityBridge != null) {
+                final String pfx2 = pfx + "  ";
+                pw.println("true");
+                pw.print(pfx2); pw.print("windowId: ");
+                pw.println(mCompatibilityBridge.mFocusedWindowId);
+                pw.print(pfx2); pw.print("nodeId: ");
+                pw.println(mCompatibilityBridge.mFocusedNodeId);
+                pw.print(pfx2); pw.print("virtualId: ");
+                pw.println(AccessibilityNodeInfo
+                        .getVirtualDescendantId(mCompatibilityBridge.mFocusedNodeId));
+                pw.print(pfx2); pw.print("focusedBounds: ");
+                pw.println(mCompatibilityBridge.mFocusedBounds);
+            } else {
+                pw.println("false");
+            }
+        }
         pw.print(pfx); pw.print("debug: "); pw.print(sDebug);
         pw.print(" verbose: "); pw.println(sVerbose);
     }
@@ -2273,7 +2334,15 @@
         @Override
         public AccessibilityEvent onAccessibilityEvent(AccessibilityEvent event,
                 boolean accessibilityEnabled, int relevantEventTypes) {
-            switch (event.getEventType()) {
+            final int type = event.getEventType();
+            if (sVerbose) {
+                // NOTE: this is waaay spammy, but that's life.
+                Log.v(TAG, "onAccessibilityEvent(" + AccessibilityEvent.eventTypeToString(type)
+                        + "): virtualId="
+                        + AccessibilityNodeInfo.getVirtualDescendantId(event.getSourceNodeId())
+                        + ", client=" + getClient());
+            }
+            switch (type) {
                 case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
                     synchronized (mLock) {
                         if (mFocusedWindowId == event.getWindowId()
@@ -2818,4 +2887,104 @@
             }
         }
     }
+
+    /**
+     * @hide
+     */
+    public static final class SyncResultReceiver extends IResultReceiver.Stub {
+
+        private static final String EXTRA = "EXTRA";
+
+        /**
+         * How long to block waiting for {@link IResultReceiver} callbacks when calling server.
+         */
+        private static final long BINDER_TIMEOUT_MS = 5000;
+
+        private static final int TYPE_STRING = 0;
+        private static final int TYPE_STRING_ARRAY = 1;
+        private static final int TYPE_PARCELABLE = 2;
+
+        private final CountDownLatch mLatch  = new CountDownLatch(1);
+        private int mResult;
+        private Bundle mBundle;
+
+        private void waitResult() {
+            try {
+                if (!mLatch.await(BINDER_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    throw new IllegalStateException("Not called in " + BINDER_TIMEOUT_MS + "ms");
+                }
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+            }
+        }
+
+        /**
+         * Gets the result from an operation that returns an {@code int}.
+         */
+        int getIntResult() {
+            waitResult();
+            return mResult;
+        }
+
+        /**
+         * Gets the result from an operation that returns an {@code Object}.
+         *
+         * @param type type of expected object.
+         */
+        @Nullable
+        @SuppressWarnings("unchecked")
+        <T> T getObjectResult(int type) {
+            waitResult();
+            if (mBundle == null) {
+                return null;
+            }
+            switch (type) {
+                case TYPE_STRING:
+                    return (T) mBundle.getString(EXTRA);
+                case TYPE_STRING_ARRAY:
+                    return (T) mBundle.getStringArray(EXTRA);
+                case TYPE_PARCELABLE:
+                    return (T) mBundle.getParcelable(EXTRA);
+                default:
+                    throw new IllegalArgumentException("unsupported type: " + type);
+            }
+        }
+
+        @Override
+        public void send(int resultCode, Bundle resultData) {
+            mResult = resultCode;
+            mBundle = resultData;
+            mLatch.countDown();
+        }
+
+        /**
+         * Creates a bundle for a {@code String} value.
+         */
+        @NonNull
+        public static Bundle bundleFor(@Nullable String value) {
+            final Bundle bundle = new Bundle();
+            bundle.putString(EXTRA, value);
+            return bundle;
+        }
+
+        /**
+         * Creates a bundle for a {@code String[]} value.
+         */
+        @NonNull
+        public static Bundle bundleFor(@Nullable String[] value) {
+            final Bundle bundle = new Bundle();
+            bundle.putStringArray(EXTRA, value);
+            return bundle;
+        }
+
+        /**
+         * Creates a bundle for a {@code Parcelable} value.
+         */
+        @NonNull
+        public static Bundle bundleFor(@Nullable Parcelable value) {
+            final Bundle bundle = new Bundle();
+            bundle.putParcelable(EXTRA, value);
+            return bundle;
+        }
+    }
 }
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 6b26f23..26aeba5 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -28,41 +28,39 @@
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.view.autofill.IAutoFillManagerClient;
+import com.android.internal.os.IResultReceiver;
 
 /**
  * Mediator between apps being auto-filled and auto-fill service implementations.
  *
  * {@hide}
  */
- // TODO(b/73536867) STOPSHIP : this whole interface should be either oneway or not, and we're
- // gradually converting the methods (as some of them return a value form the server and must be
- // refactored).
-interface IAutoFillManager {
+oneway interface IAutoFillManager {
     // Returns flags: FLAG_ADD_CLIENT_ENABLED | FLAG_ADD_CLIENT_DEBUG | FLAG_ADD_CLIENT_VERBOSE
-    int addClient(in IAutoFillManagerClient client, int userId);
+    void addClient(in IAutoFillManagerClient client, int userId, in IResultReceiver result);
     void removeClient(in IAutoFillManagerClient client, int userId);
-    int startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId,
-            in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags,
-            in ComponentName componentName, boolean compatMode);
-    FillEventHistory getFillEventHistory();
-    boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback);
-    oneway void updateSession(int sessionId, in AutofillId id, in Rect bounds,
-            in AutofillValue value, int action, int flags, int userId);
-    oneway void setAutofillFailure(int sessionId, in List<AutofillId> ids, int userId);
-    oneway void finishSession(int sessionId, int userId);
-    oneway void cancelSession(int sessionId, int userId);
-    oneway void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId,
-            int userId);
-    oneway void setHasCallback(int sessionId, int userId, boolean hasIt);
+    void startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId,
+        in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags,
+        in ComponentName componentName, boolean compatMode, in IResultReceiver result);
+    void getFillEventHistory(in IResultReceiver result);
+    void restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback,
+        in IResultReceiver result);
+    void updateSession(int sessionId, in AutofillId id, in Rect bounds,
+        in AutofillValue value, int action, int flags, int userId);
+    void setAutofillFailure(int sessionId, in List<AutofillId> ids, int userId);
+    void finishSession(int sessionId, int userId);
+    void cancelSession(int sessionId, int userId);
+    void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId, int userId);
+    void setHasCallback(int sessionId, int userId, boolean hasIt);
     void disableOwnedAutofillServices(int userId);
-    boolean isServiceSupported(int userId);
-    boolean isServiceEnabled(int userId, String packageName);
+    void isServiceSupported(int userId, in IResultReceiver result);
+    void isServiceEnabled(int userId, String packageName, in IResultReceiver result);
     void onPendingSaveUi(int operation, IBinder token);
-    UserData getUserData();
-    String getUserDataId();
+    void getUserData(in IResultReceiver result);
+    void getUserDataId(in IResultReceiver result);
     void setUserData(in UserData userData);
-    boolean isFieldClassificationEnabled();
-    ComponentName getAutofillServiceComponentName();
-    String[] getAvailableFieldClassificationAlgorithms();
-    String getDefaultFieldClassificationAlgorithm();
+    void isFieldClassificationEnabled(in IResultReceiver result);
+    void getAutofillServiceComponentName(in IResultReceiver result);
+    void getAvailableFieldClassificationAlgorithms(in IResultReceiver result);
+    void getDefaultFieldClassificationAlgorithm(in IResultReceiver result);
 }
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 372362f..04028ae 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -17,6 +17,7 @@
 package android.view.inputmethod;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -94,6 +95,7 @@
     /**
      * An array-like container of the subtypes.
      */
+    @UnsupportedAppUsage
     private final InputMethodSubtypeArray mSubtypes;
 
     private final boolean mIsAuxIme;
@@ -445,6 +447,7 @@
      * Return whether or not this ime is a default ime or not.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isDefault(Context context) {
         if (mForceDefault) {
             return true;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index bb93af5..7762ecf 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -24,6 +24,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
@@ -223,6 +224,7 @@
 
     static final String PENDING_EVENT_COUNTER = "aq:imm";
 
+    @UnsupportedAppUsage
     static InputMethodManager sInstance;
 
     /**
@@ -270,11 +272,13 @@
     /** @hide */
     public static final int SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES = 2;
 
+    @UnsupportedAppUsage
     final IInputMethodManager mService;
     final Looper mMainLooper;
 
     // For scheduling work on the main thread.  This also serves as our
     // global lock.
+    @UnsupportedAppUsage
     final H mH;
 
     // Our generic input connection if the current target does not have its own.
@@ -302,16 +306,19 @@
      * This is the root view of the overall window that currently has input
      * method focus.
      */
+    @UnsupportedAppUsage
     View mCurRootView;
     /**
      * This is the view that should currently be served by an input method,
      * regardless of the state of setting that up.
      */
+    @UnsupportedAppUsage
     View mServedView;
     /**
      * This is then next view that will be served by the input method, when
      * we get around to updating things.
      */
+    @UnsupportedAppUsage
     View mNextServedView;
     /**
      * This is set when we are in the process of connecting, to determine
@@ -327,6 +334,7 @@
     /**
      * The InputConnection that was last retrieved from the served view.
      */
+    @UnsupportedAppUsage
     ControlledInputConnectionWrapper mServedInputConnectionWrapper;
     /**
      * The completions that were last provided by the served view.
@@ -334,7 +342,9 @@
     CompletionInfo[] mCompletions;
 
     // Cursor position on the screen.
+    @UnsupportedAppUsage
     Rect mTmpCursorRect = new Rect();
+    @UnsupportedAppUsage
     Rect mCursorRect = new Rect();
     int mCursorSelStart;
     int mCursorSelEnd;
@@ -377,10 +387,12 @@
     /**
      * ID of the method we are bound to.
      */
+    @UnsupportedAppUsage
     String mCurId;
     /**
      * The actual instance of the method to make calls on it.
      */
+    @UnsupportedAppUsage
     IInputMethodSession mCurMethod;
     InputChannel mCurChannel;
     ImeInputEventSender mCurSender;
@@ -677,6 +689,7 @@
      * doesn't already exist.
      * @hide
      */
+    @UnsupportedAppUsage
     public static InputMethodManager getInstance() {
         synchronized (InputMethodManager.class) {
             if (sInstance == null) {
@@ -695,16 +708,19 @@
      * if it exists.
      * @hide
      */
+    @UnsupportedAppUsage
     public static InputMethodManager peekInstance() {
         return sInstance;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public IInputMethodClient getClient() {
         return mClient;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public IInputContext getInputContext() {
         return mIInputContext;
     }
@@ -816,6 +832,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
         try {
             mService.registerSuggestionSpansForNotification(spans);
@@ -825,6 +842,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
         try {
             mService.notifySuggestionPicked(span, originalString, index);
@@ -930,6 +948,7 @@
     /**
      * Disconnect any existing input connection, clearing the served view.
      */
+    @UnsupportedAppUsage
     void finishInputLocked() {
         mNextServedView = null;
         if (mServedView != null) {
@@ -1094,6 +1113,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
         try {
             Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed "
@@ -1414,6 +1434,7 @@
      * input method started before.
      * @hide
      */
+    @UnsupportedAppUsage
     public void windowDismissed(IBinder appWindowToken) {
         checkFocus();
         synchronized (mH) {
@@ -1428,6 +1449,7 @@
      * Call this when a view receives focus.
      * @hide
      */
+    @UnsupportedAppUsage
     public void focusIn(View view) {
         synchronized (mH) {
             focusInLocked(view);
@@ -1458,6 +1480,7 @@
      * Call this when a view loses focus.
      * @hide
      */
+    @UnsupportedAppUsage
     public void focusOut(View view) {
         synchronized (mH) {
             if (DEBUG) Log.v(TAG, "focusOut: view=" + dumpViewInfo(view)
@@ -1502,6 +1525,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void checkFocus() {
         if (checkFocusNoStartInput(false)) {
             startInputInner(InputMethodClient.START_INPUT_REASON_CHECK_FOCUS, null, 0, 0, 0);
@@ -1549,6 +1573,7 @@
         return true;
     }
 
+    @UnsupportedAppUsage
     void closeCurrentInput() {
         try {
             mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
@@ -1616,6 +1641,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void onPreWindowFocus(View rootView, boolean hasWindowFocus) {
         synchronized (mH) {
             if (rootView == null) {
@@ -1719,6 +1745,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isCursorAnchorInfoEnabled() {
         synchronized (mH) {
             final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
@@ -1734,6 +1761,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUpdateCursorAnchorInfoMode(int flags) {
         synchronized (mH) {
             mRequestUpdateCursorAnchorInfoMonitorMode = flags;
@@ -2243,6 +2271,7 @@
      * Notify that a user took some action with this input method.
      * @hide
      */
+    @UnsupportedAppUsage
     public void notifyUserAction() {
         synchronized (mH) {
             if (mLastSentUserActionNotificationSequenceNumber ==
@@ -2311,6 +2340,7 @@
      * @return The current height of the input method window.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getInputMethodWindowVisibleHeight() {
         synchronized (mH) {
             try {
diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
index 6a748ce..8dd0dcd 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
@@ -16,6 +16,7 @@
 
 package android.view.inputmethod;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.util.Slog;
 
@@ -49,6 +50,7 @@
      * @param subtypes A list of {@link InputMethodSubtype} from which
      * {@link InputMethodSubtypeArray} will be created.
      */
+    @UnsupportedAppUsage
     public InputMethodSubtypeArray(final List<InputMethodSubtype> subtypes) {
         if (subtypes == null) {
             mCount = 0;
diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java
index 10191e0..16eb5af 100644
--- a/core/java/android/view/textclassifier/SystemTextClassifier.java
+++ b/core/java/android/view/textclassifier/SystemTextClassifier.java
@@ -30,6 +30,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 
 import java.util.concurrent.CountDownLatch;
@@ -162,6 +163,17 @@
         }
     }
 
+    @Override
+    public void dump(@NonNull IndentingPrintWriter printWriter) {
+        printWriter.println("SystemTextClassifier:");
+        printWriter.increaseIndent();
+        printWriter.printPair("mFallback", mFallback);
+        printWriter.printPair("mPackageName", mPackageName);
+        printWriter.printPair("mSessionId", mSessionId);
+        printWriter.decreaseIndent();
+        printWriter.println();
+    }
+
     /**
      * Attempts to initialize a new classification session.
      *
diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java
index 21b5603..2fc7422 100644
--- a/core/java/android/view/textclassifier/TextClassificationConstants.java
+++ b/core/java/android/view/textclassifier/TextClassificationConstants.java
@@ -20,6 +20,8 @@
 import android.util.KeyValueListParser;
 import android.util.Slog;
 
+import com.android.internal.util.IndentingPrintWriter;
+
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -241,4 +243,25 @@
     private static List<String> parseEntityList(String listStr) {
         return Collections.unmodifiableList(Arrays.asList(listStr.split(ENTITY_LIST_DELIMITER)));
     }
+
+    void dump(IndentingPrintWriter pw) {
+        pw.println("TextClassificationConstants:");
+        pw.increaseIndent();
+        pw.printPair("isLocalTextClassifierEnabled", mLocalTextClassifierEnabled);
+        pw.printPair("isSystemTextClassifierEnabled", mSystemTextClassifierEnabled);
+        pw.printPair("isModelDarkLaunchEnabled", mModelDarkLaunchEnabled);
+        pw.printPair("isSmartSelectionEnabled", mSmartSelectionEnabled);
+        pw.printPair("isSmartTextShareEnabled", mSmartTextShareEnabled);
+        pw.printPair("isSmartLinkifyEnabled", mSmartLinkifyEnabled);
+        pw.printPair("isSmartSelectionAnimationEnabled", mSmartSelectionAnimationEnabled);
+        pw.printPair("getSuggestSelectionMaxRangeLength", mSuggestSelectionMaxRangeLength);
+        pw.printPair("getClassifyTextMaxRangeLength", mClassifyTextMaxRangeLength);
+        pw.printPair("getGenerateLinksMaxTextLength", mGenerateLinksMaxTextLength);
+        pw.printPair("getGenerateLinksLogSampleRate", mGenerateLinksLogSampleRate);
+        pw.printPair("getEntityListDefault", mEntityListDefault);
+        pw.printPair("getEntityListNotEditable", mEntityListNotEditable);
+        pw.printPair("getEntityListEditable", mEntityListEditable);
+        pw.decreaseIndent();
+        pw.println();
+    }
 }
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index dc1194b..ed86206 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.os.ServiceManager;
@@ -27,6 +28,7 @@
 import android.view.textclassifier.TextClassifier.TextClassifierType;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 
 import java.lang.ref.WeakReference;
@@ -107,6 +109,7 @@
      * @see TextClassifier#SYSTEM
      * @hide
      */
+    @UnsupportedAppUsage
     public TextClassifier getTextClassifier(@TextClassifierType int type) {
         switch (type) {
             case TextClassifier.LOCAL:
@@ -246,6 +249,13 @@
                 : mContext;
     }
 
+    /** @hide **/
+    public void dump(IndentingPrintWriter pw) {
+        getLocalTextClassifier().dump(pw);
+        getSystemTextClassifier().dump(pw);
+        getSettings().dump(pw);
+    }
+
     /** @hide */
     public static TextClassificationConstants getSettings(Context context) {
         Preconditions.checkNotNull(context);
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 24f531d..9692579 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringDef;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.os.LocaleList;
 import android.os.Looper;
@@ -34,6 +35,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
@@ -212,6 +214,7 @@
 
     // TODO: Remove once apps can build against the latest sdk.
     /** @hide */
+    @UnsupportedAppUsage
     default TextSelection suggestSelection(
             @NonNull CharSequence text,
             @IntRange(from = 0) int selectionStartIndex,
@@ -291,6 +294,7 @@
 
     // TODO: Remove once apps can build against the latest sdk.
     /** @hide */
+    @UnsupportedAppUsage
     default TextClassification classifyText(
             @NonNull CharSequence text,
             @IntRange(from = 0) int startIndex,
@@ -332,6 +336,7 @@
 
     // TODO: Remove once apps can build against the latest sdk.
     /** @hide */
+    @UnsupportedAppUsage
     default TextLinks generateLinks(
             @NonNull CharSequence text, @Nullable TextLinks.Options options) {
         if (options == null) {
@@ -390,6 +395,11 @@
         return false;
     }
 
+    /** @hide **/
+    default void dump(@NonNull IndentingPrintWriter printWriter) {
+
+    }
+
     /**
      * Configuration object for specifying what entities to identify.
      *
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 6e5751a..29339e9 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -41,6 +41,7 @@
 import android.provider.ContactsContract;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 
 import java.io.File;
@@ -439,6 +440,24 @@
         return builder.setId(createId(text, start, end)).build();
     }
 
+    @Override
+    public void dump(@NonNull IndentingPrintWriter printWriter) {
+        synchronized (mLock) {
+            listAllModelsLocked();
+            printWriter.println("TextClassifierImpl:");
+            printWriter.increaseIndent();
+            printWriter.println("Model file(s):");
+            printWriter.increaseIndent();
+            for (ModelFile modelFile : mAllModelFiles) {
+                printWriter.println(modelFile.toString());
+            }
+            printWriter.decreaseIndent();
+            printWriter.printPair("mFallback", mFallback);
+            printWriter.decreaseIndent();
+            printWriter.println();
+        }
+    }
+
     /**
      * Closes the ParcelFileDescriptor and logs any errors that occur.
      */
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index e7faf14..1cac3ed 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -20,6 +20,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.LocaleList;
 import android.os.Parcel;
@@ -652,6 +653,7 @@
 
         private String mCallingPackageName;
 
+        @UnsupportedAppUsage
         public Options() {
             this(null, null);
         }
diff --git a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
index f7d75cd..b530ddf 100644
--- a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
+++ b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.metrics.LogMaker;
 import android.util.Log;
@@ -99,6 +100,7 @@
     private boolean mSmartSelectionTriggered;
     private String mModelName;
 
+    @UnsupportedAppUsage
     public SmartSelectionEventTracker(@NonNull Context context, @WidgetType int widgetType) {
         mWidgetType = widgetType;
         mWidgetVersion = null;
@@ -117,6 +119,7 @@
      *
      * @param event the selection event
      */
+    @UnsupportedAppUsage
     public void logEvent(@NonNull SelectionEvent event) {
         Preconditions.checkNotNull(event);
 
@@ -440,6 +443,7 @@
          *
          * @param start  the word index of the selected word
          */
+        @UnsupportedAppUsage
         public static SelectionEvent selectionStarted(int start) {
             return new SelectionEvent(
                     start, start + 1, EventType.SELECTION_STARTED,
@@ -453,6 +457,7 @@
          * @param start  the start word (inclusive) index of the selection
          * @param end  the end word (exclusive) index of the selection
          */
+        @UnsupportedAppUsage
         public static SelectionEvent selectionModified(int start, int end) {
             return new SelectionEvent(
                     start, end, EventType.SELECTION_MODIFIED,
@@ -468,6 +473,7 @@
          * @param classification  the TextClassification object returned by the TextClassifier that
          *      classified the selected text
          */
+        @UnsupportedAppUsage
         public static SelectionEvent selectionModified(
                 int start, int end, @NonNull TextClassification classification) {
             final String entityType = classification.getEntityCount() > 0
@@ -487,6 +493,7 @@
          * @param selection  the TextSelection object returned by the TextClassifier for the
          *      specified selection
          */
+        @UnsupportedAppUsage
         public static SelectionEvent selectionModified(
                 int start, int end, @NonNull TextSelection selection) {
             final boolean smartSelection = getSourceClassifier(selection.getId())
@@ -515,6 +522,7 @@
          * @param end  the end word (exclusive) index of the selection
          * @param actionType  the action that was performed on the selection
          */
+        @UnsupportedAppUsage
         public static SelectionEvent selectionAction(
                 int start, int end, @ActionType int actionType) {
             return new SelectionEvent(
@@ -532,6 +540,7 @@
          * @param classification  the TextClassification object returned by the TextClassifier that
          *      classified the selected text
          */
+        @UnsupportedAppUsage
         public static SelectionEvent selectionAction(
                 int start, int end, @ActionType int actionType,
                 @NonNull TextClassification classification) {
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 886f5c8..9733701 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -16,6 +16,7 @@
 
 package android.view.textservice;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -97,6 +98,7 @@
     private final InternalListener mInternalListener;
     private final ITextServicesManager mTextServicesManager;
     private final SpellCheckerInfo mSpellCheckerInfo;
+    @UnsupportedAppUsage
     private final SpellCheckerSessionListener mSpellCheckerSessionListener;
     private final SpellCheckerSessionListenerImpl mSpellCheckerSessionListenerImpl;
 
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 6644a85..4c6862c 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -17,6 +17,7 @@
 package android.view.textservice;
 
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -85,6 +86,7 @@
      * Retrieve the global TextServicesManager instance, creating it if it doesn't already exist.
      * @hide
      */
+    @UnsupportedAppUsage
     public static TextServicesManager getInstance() {
         synchronized (TextServicesManager.class) {
             if (sInstance == null) {
@@ -192,6 +194,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public SpellCheckerInfo[] getEnabledSpellCheckers() {
         try {
             final SpellCheckerInfo[] retval = mService.getEnabledSpellCheckers();
@@ -207,6 +210,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public SpellCheckerInfo getCurrentSpellChecker() {
         try {
             // Passing null as a locale for ICS
@@ -219,6 +223,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
             boolean allowImplicitlySelectedSubtype) {
         try {
@@ -231,6 +236,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isSpellCheckerEnabled() {
         try {
             return mService.isSpellCheckerEnabled();
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index fc76029..563e00e 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 import java.io.File;
 import java.io.IOException;
@@ -50,22 +51,37 @@
     @Deprecated
     public static class CacheResult {
         // these fields are saved to the database
+        @UnsupportedAppUsage
         int httpStatusCode;
+        @UnsupportedAppUsage
         long contentLength;
+        @UnsupportedAppUsage
         long expires;
+        @UnsupportedAppUsage
         String expiresString;
+        @UnsupportedAppUsage
         String localPath;
+        @UnsupportedAppUsage
         String lastModified;
+        @UnsupportedAppUsage
         String etag;
+        @UnsupportedAppUsage
         String mimeType;
+        @UnsupportedAppUsage
         String location;
+        @UnsupportedAppUsage
         String encoding;
+        @UnsupportedAppUsage
         String contentdisposition;
+        @UnsupportedAppUsage
         String crossDomain;
 
         // these fields are NOT saved to the database
+        @UnsupportedAppUsage
         InputStream inStream;
+        @UnsupportedAppUsage
         OutputStream outStream;
+        @UnsupportedAppUsage
         File outFile;
 
         /**
@@ -73,6 +89,7 @@
          *
          * @return the status code of this cache entry
          */
+        @UnsupportedAppUsage
         public int getHttpStatusCode() {
             return httpStatusCode;
         }
@@ -82,6 +99,7 @@
          *
          * @return the content length of this cache entry
          */
+        @UnsupportedAppUsage
         public long getContentLength() {
             return contentLength;
         }
@@ -93,6 +111,7 @@
          *
          * @return the path of the file used to store this cache entry
          */
+        @UnsupportedAppUsage
         public String getLocalPath() {
             return localPath;
         }
@@ -103,6 +122,7 @@
          *
          * @return the expiry date of this cache entry
          */
+        @UnsupportedAppUsage
         public long getExpires() {
             return expires;
         }
@@ -113,6 +133,7 @@
          * @return the expiry date of this cache entry
          *
          */
+        @UnsupportedAppUsage
         public String getExpiresString() {
             return expiresString;
         }
@@ -123,6 +144,7 @@
          *
          * @return the date at which this cache entry was last modified
          */
+        @UnsupportedAppUsage
         public String getLastModified() {
             return lastModified;
         }
@@ -132,6 +154,7 @@
          *
          * @return the entity tag of this cache entry
          */
+        @UnsupportedAppUsage
         public String getETag() {
             return etag;
         }
@@ -141,6 +164,7 @@
          *
          * @return the MIME type of this cache entry
          */
+        @UnsupportedAppUsage
         public String getMimeType() {
             return mimeType;
         }
@@ -151,6 +175,7 @@
          *
          * @return the HTTP 'Location' header for this cache entry
          */
+        @UnsupportedAppUsage
         public String getLocation() {
             return location;
         }
@@ -160,6 +185,7 @@
          *
          * @return the encoding of this cache entry
          */
+        @UnsupportedAppUsage
         public String getEncoding() {
             return encoding;
         }
@@ -171,6 +197,7 @@
          * @return the HTTP 'Content-Disposition' header for this cache entry
          *
          */
+        @UnsupportedAppUsage
         public String getContentDisposition() {
             return contentdisposition;
         }
@@ -182,6 +209,7 @@
          *
          * @return an input stream to the content of this cache entry
          */
+        @UnsupportedAppUsage
         public InputStream getInputStream() {
             return inStream;
         }
@@ -194,6 +222,7 @@
          * @return an output stream to the content of this cache entry
          */
         // Note that this is always null for objects returned by getCacheFile()!
+        @UnsupportedAppUsage
         public OutputStream getOutputStream() {
             return outStream;
         }
@@ -204,6 +233,7 @@
          *
          * @param stream an input stream to the content of this cache entry
          */
+        @UnsupportedAppUsage
         public void setInputStream(InputStream stream) {
             this.inStream = stream;
         }
@@ -213,6 +243,7 @@
          *
          * @param encoding the encoding of this cache entry
          */
+        @UnsupportedAppUsage
         public void setEncoding(String encoding) {
             this.encoding = encoding;
         }
@@ -235,6 +266,7 @@
      */
     @Deprecated
     @Nullable
+    @UnsupportedAppUsage
     public static File getCacheFileBaseDir() {
         return null;
     }
@@ -246,6 +278,7 @@
      * @deprecated This method no longer has any effect and always returns {@code false}.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static boolean cacheDisabled() {
         return false;
     }
@@ -259,6 +292,7 @@
      * @deprecated This method no longer has any effect and always returns {@code false}.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static boolean startCacheTransaction() {
         return false;
     }
@@ -271,6 +305,7 @@
      * @deprecated This method no longer has any effect and always returns {@code false}.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static boolean endCacheTransaction() {
         return false;
     }
@@ -290,6 +325,7 @@
      */
     @Deprecated
     @Nullable
+    @UnsupportedAppUsage
     public static CacheResult getCacheFile(String url,
             Map<String, String> headers) {
         return null;
@@ -304,10 +340,12 @@
      * @deprecated Access to the HTTP cache will be removed in a future release.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static void saveCacheFile(String url, CacheResult cacheResult) {
         saveCacheFile(url, 0, cacheResult);
     }
 
+    @UnsupportedAppUsage
     static void saveCacheFile(String url, long postIdentifier,
             CacheResult cacheRet) {
         try {
diff --git a/core/java/android/webkit/ConsoleMessage.java b/core/java/android/webkit/ConsoleMessage.java
index a9c351a..6051956 100644
--- a/core/java/android/webkit/ConsoleMessage.java
+++ b/core/java/android/webkit/ConsoleMessage.java
@@ -16,6 +16,8 @@
 
 package android.webkit;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Public class representing a JavaScript console message from WebCore. This could be a issued
  * by a call to one of the <code>console</code> logging functions (e.g.
@@ -34,9 +36,13 @@
         DEBUG
     };
 
+    @UnsupportedAppUsage
     private MessageLevel mLevel;
+    @UnsupportedAppUsage
     private String mMessage;
+    @UnsupportedAppUsage
     private String mSourceId;
+    @UnsupportedAppUsage
     private int mLineNumber;
 
     public ConsoleMessage(String message, String sourceId, int lineNumber, MessageLevel msgLevel) {
diff --git a/core/java/android/webkit/JsResult.java b/core/java/android/webkit/JsResult.java
index d36ab418..5bf6aab 100644
--- a/core/java/android/webkit/JsResult.java
+++ b/core/java/android/webkit/JsResult.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 
 /**
  * An instance of this class is passed as a parameter in various {@link WebChromeClient} action
@@ -34,6 +35,7 @@
         public void onJsResultComplete(JsResult result);
     }
     // This is the caller of the prompt and is the object that is waiting.
+    @UnsupportedAppUsage
     private final ResultReceiver mReceiver;
     // This is a basic result of a confirm or prompt dialog.
     private boolean mResult;
diff --git a/core/java/android/webkit/PluginData.java b/core/java/android/webkit/PluginData.java
index 88fc9b7..8aeeb1c 100644
--- a/core/java/android/webkit/PluginData.java
+++ b/core/java/android/webkit/PluginData.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.InputStream;
 import java.util.Map;
 
@@ -69,6 +70,7 @@
      * deprecated, so is this class.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public PluginData(
             InputStream stream,
             long length,
@@ -90,6 +92,7 @@
      * deprecated, so is this class.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public InputStream getInputStream() {
         return mStream;
     }
@@ -104,6 +107,7 @@
      * deprecated, so is this class.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public long getContentLength() {
         return mContentLength;
     }
@@ -121,6 +125,7 @@
      * deprecated, so is this class.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public Map<String, String[]> getHeaders() {
         return mHeaders;
     }
@@ -135,6 +140,7 @@
      * deprecated, so is this class.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public int getStatusCode() {
         return mStatusCode;
     }
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index ed122a6..5d704cb 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.net.ParseException;
 import android.net.Uri;
 import android.net.WebAddress;
@@ -139,6 +140,7 @@
     /**
      * @return {@code true} if the url is correctly URL encoded
      */
+    @UnsupportedAppUsage
     static boolean verifyURLEncoding(String url) {
         int count = url.length();
         if (count == 0) {
@@ -181,6 +183,7 @@
      * @return {@code true} if the url is a resource file.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isResourceUrl(String url) {
         return (null != url) && url.startsWith(RESOURCE_BASE);
     }
@@ -398,6 +401,7 @@
      * Unfortunately some servers do not quote the value so to maintain
      * consistent behaviour with other browsers, we allow unquoted values too.
      */
+    @UnsupportedAppUsage
     static String parseContentDisposition(String contentDisposition) {
         try {
             Matcher m = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition);
diff --git a/core/java/android/webkit/UrlInterceptHandler.java b/core/java/android/webkit/UrlInterceptHandler.java
index 0a6e51f..f23aae6b 100644
--- a/core/java/android/webkit/UrlInterceptHandler.java
+++ b/core/java/android/webkit/UrlInterceptHandler.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.webkit.CacheManager.CacheResult;
 import android.webkit.PluginData;
 
@@ -44,6 +45,7 @@
      */
     @Deprecated
     @Nullable
+    @UnsupportedAppUsage
     CacheResult service(String url, @Nullable Map<String, String> headers);
 
     /**
@@ -60,5 +62,6 @@
      */
     @Deprecated
     @Nullable
+    @UnsupportedAppUsage
     PluginData getPluginData(String url, @Nullable Map<String, String> headers);
 }
diff --git a/core/java/android/webkit/UrlInterceptRegistry.java b/core/java/android/webkit/UrlInterceptRegistry.java
index 700d6d9..eeb28d7 100644
--- a/core/java/android/webkit/UrlInterceptRegistry.java
+++ b/core/java/android/webkit/UrlInterceptRegistry.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.webkit.CacheManager.CacheResult;
 import android.webkit.PluginData;
 import android.webkit.UrlInterceptHandler;
@@ -55,6 +56,7 @@
      * deprecated, so is this class.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static synchronized void setUrlInterceptDisabled(boolean disabled) {
         mDisabled = disabled;
     }
@@ -85,6 +87,7 @@
      * deprecated, so is this class.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static synchronized boolean registerHandler(
             UrlInterceptHandler handler) {
         if (!getHandlers().contains(handler)) {
@@ -106,6 +109,7 @@
      * deprecated, so is this class.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static synchronized boolean unregisterHandler(
             UrlInterceptHandler handler) {
         return getHandlers().remove(handler);
@@ -152,6 +156,7 @@
      */
     @Deprecated
     @Nullable
+    @UnsupportedAppUsage
     public static synchronized PluginData getPluginData(
             String url, Map<String, String> headers) {
         if (urlInterceptDisabled()) {
diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java
index 7bc7b07..aae3056 100644
--- a/core/java/android/webkit/WebResourceResponse.java
+++ b/core/java/android/webkit/WebResourceResponse.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 
 import java.io.InputStream;
 import java.io.StringBufferInputStream;
@@ -29,9 +30,11 @@
  * response when the WebView requests a particular resource.
  */
 public class WebResourceResponse {
+    @UnsupportedAppUsage
     private boolean mImmutable;
     private String mMimeType;
     private String mEncoding;
+    @UnsupportedAppUsage
     private int mStatusCode;
     private String mReasonPhrase;
     private Map<String, String> mResponseHeaders;
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index a085395..c30edd3 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 
 import java.lang.annotation.ElementType;
@@ -92,6 +93,7 @@
         TextSize(int size) {
             value = size;
         }
+        @UnsupportedAppUsage
         int value;
     }
 
@@ -579,6 +581,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setUseDoubleTree(boolean use) {
         // Specified to do nothing, so no need for derived classes to override.
     }
@@ -591,6 +594,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public boolean getUseDoubleTree() {
         // Returns false unconditionally, so no need for derived classes to override.
         return false;
@@ -1004,6 +1008,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setPluginsPath(String pluginsPath) {
         // Specified to do nothing, so no need for derived classes to override.
     }
@@ -1201,6 +1206,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public String getPluginsPath() {
         // Unconditionally returns empty string, so no need for derived classes to override.
         return "";
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index 03b94e7..3fa1b01 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 
 /**
@@ -65,5 +66,6 @@
     protected void onSyncInit() {
     }
 
+    @UnsupportedAppUsage
     abstract void syncFromRamToFlash();
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index d1a0f77..f343a52 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.Intent;
@@ -70,280 +71,25 @@
 import java.util.Map;
 
 /**
- * <p>A View that displays web pages. This class is the basis upon which you
- * can roll your own web browser or simply display some online content within your Activity.
- * It uses the WebKit rendering engine to display
- * web pages and includes methods to navigate forward and backward
- * through a history, zoom in and out, perform text searches and more.
- *
- * <p>Note that, in order for your Activity to access the Internet and load web pages
- * in a WebView, you must add the {@code INTERNET} permissions to your
- * Android Manifest file:
- *
- * <pre>
- * {@code <uses-permission android:name="android.permission.INTERNET" />}
- * </pre>
- *
- * <p>This must be a child of the <a
- * href="{@docRoot}guide/topics/manifest/manifest-element.html">{@code <manifest>}</a>
- * element.
- *
- * <p>For more information, read
- * <a href="{@docRoot}guide/webapps/webview.html">Building Web Apps in WebView</a>.
+ * A View that displays web pages.
  *
  * <h3>Basic usage</h3>
  *
- * <p>By default, a WebView provides no browser-like widgets, does not
- * enable JavaScript and web page errors are ignored. If your goal is only
- * to display some HTML as a part of your UI, this is probably fine;
- * the user won't need to interact with the web page beyond reading
- * it, and the web page won't need to interact with the user. If you
- * actually want a full-blown web browser, then you probably want to
- * invoke the Browser application with a URL Intent rather than show it
- * with a WebView. For example:
- * <pre>
- * Uri uri = Uri.parse("https://www.example.com");
- * Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- * startActivity(intent);
- * </pre>
- * <p>See {@link android.content.Intent} for more information.
  *
- * <p>To provide a WebView in your own Activity, include a {@code <WebView>} in your layout,
- * or set the entire Activity window as a WebView during {@link
- * android.app.Activity#onCreate(Bundle) onCreate()}:
+ * <p>In most cases, we recommend using a standard web browser, like Chrome, to deliver
+ * content to the user. To learn more about web browsers, read the guide on
+ * <a href="/guide/components/intents-common#Browser">
+ * invoking a browser with an intent</a>.
  *
- * <pre class="prettyprint">
- * WebView webview = new WebView(this);
- * setContentView(webview);
- * </pre>
+ * <p>WebView objects allow you to display web content as part of your activity layout, but
+ * lack some of the features of fully-developed browsers. A WebView is useful when
+ * you need increased control over the UI and advanced configuration options that will allow
+ * you to embed web pages in a specially-designed environment for your app.
  *
- * <p>Then load the desired web page:
- *
- * <pre>
- * // Simplest usage: note that an exception will NOT be thrown
- * // if there is an error loading this page (see below).
- * webview.loadUrl("https://example.com/");
- *
- * // OR, you can also load from an HTML string:
- * String summary = "&lt;html>&lt;body>You scored &lt;b>192&lt;/b> points.&lt;/body>&lt;/html>";
- * webview.loadData(summary, "text/html", null);
- * // ... although note that there are restrictions on what this HTML can do.
- * // See {@link #loadData(String,String,String)} and {@link
- * #loadDataWithBaseURL(String,String,String,String,String)} for more info.
- * // Also see {@link #loadData(String,String,String)} for information on encoding special
- * // characters.
- * </pre>
- *
- * <p>A WebView has several customization points where you can add your
- * own behavior. These are:
- *
- * <ul>
- *   <li>Creating and setting a {@link android.webkit.WebChromeClient} subclass.
- *       This class is called when something that might impact a
- *       browser UI happens, for instance, progress updates and
- *       JavaScript alerts are sent here (see <a
- * href="{@docRoot}guide/webapps/debugging.html">Debugging Web Apps</a>).
- *   </li>
- *   <li>Creating and setting a {@link android.webkit.WebViewClient} subclass.
- *       It will be called when things happen that impact the
- *       rendering of the content, eg, errors or form submissions. You
- *       can also intercept URL loading here (via {@link
- * android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String)
- * shouldOverrideUrlLoading()}).</li>
- *   <li>Modifying the {@link android.webkit.WebSettings}, such as
- * enabling JavaScript with {@link android.webkit.WebSettings#setJavaScriptEnabled(boolean)
- * setJavaScriptEnabled()}. </li>
- *   <li>Injecting Java objects into the WebView using the
- *       {@link android.webkit.WebView#addJavascriptInterface} method. This
- *       method allows you to inject Java objects into a page's JavaScript
- *       context, so that they can be accessed by JavaScript in the page.</li>
- * </ul>
- *
- * <p>Here's a more complicated example, showing error handling,
- *    settings, and progress notification:
- *
- * <pre class="prettyprint">
- * // Let's display the progress in the activity title bar, like the
- * // browser app does.
- * getWindow().requestFeature(Window.FEATURE_PROGRESS);
- *
- * webview.getSettings().setJavaScriptEnabled(true);
- *
- * final Activity activity = this;
- * webview.setWebChromeClient(new WebChromeClient() {
- *   public void onProgressChanged(WebView view, int progress) {
- *     // Activities and WebViews measure progress with different scales.
- *     // The progress meter will automatically disappear when we reach 100%
- *     activity.setProgress(progress * 1000);
- *   }
- * });
- * webview.setWebViewClient(new WebViewClient() {
- *   public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
- *     Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show();
- *   }
- * });
- *
- * webview.loadUrl("https://developer.android.com/");
- * </pre>
- *
- * <h3>Zoom</h3>
- *
- * <p>To enable the built-in zoom, set
- * {@link #getSettings() WebSettings}.{@link WebSettings#setBuiltInZoomControls(boolean)}
- * (introduced in API level {@link android.os.Build.VERSION_CODES#CUPCAKE}).
- *
- * <p class="note"><b>Note:</b> Using zoom if either the height or width is set to
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} may lead to undefined behavior
- * and should be avoided.
- *
- * <h3>Cookie and window management</h3>
- *
- * <p>For obvious security reasons, your application has its own
- * cache, cookie store etc.&mdash;it does not share the Browser
- * application's data.
- *
- * <p>By default, requests by the HTML to open new windows are
- * ignored. This is {@code true} whether they be opened by JavaScript or by
- * the target attribute on a link. You can customize your
- * {@link WebChromeClient} to provide your own behavior for opening multiple windows,
- * and render them in whatever manner you want.
- *
- * <p>The standard behavior for an Activity is to be destroyed and
- * recreated when the device orientation or any other configuration changes. This will cause
- * the WebView to reload the current page. If you don't want that, you
- * can set your Activity to handle the {@code orientation} and {@code keyboardHidden}
- * changes, and then just leave the WebView alone. It'll automatically
- * re-orient itself as appropriate. Read <a
- * href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a> for
- * more information about how to handle configuration changes during runtime.
- *
- *
- * <h3>Building web pages to support different screen densities</h3>
- *
- * <p>The screen density of a device is based on the screen resolution. A screen with low density
- * has fewer available pixels per inch, where a screen with high density
- * has more &mdash; sometimes significantly more &mdash; pixels per inch. The density of a
- * screen is important because, other things being equal, a UI element (such as a button) whose
- * height and width are defined in terms of screen pixels will appear larger on the lower density
- * screen and smaller on the higher density screen.
- * For simplicity, Android collapses all actual screen densities into three generalized densities:
- * high, medium, and low.
- * <p>By default, WebView scales a web page so that it is drawn at a size that matches the default
- * appearance on a medium density screen. So, it applies 1.5x scaling on a high density screen
- * (because its pixels are smaller) and 0.75x scaling on a low density screen (because its pixels
- * are bigger).
- * Starting with API level {@link android.os.Build.VERSION_CODES#ECLAIR}, WebView supports DOM, CSS,
- * and meta tag features to help you (as a web developer) target screens with different screen
- * densities.
- * <p>Here's a summary of the features you can use to handle different screen densities:
- * <ul>
- * <li>The {@code window.devicePixelRatio} DOM property. The value of this property specifies the
- * default scaling factor used for the current device. For example, if the value of {@code
- * window.devicePixelRatio} is "1.0", then the device is considered a medium density (mdpi) device
- * and default scaling is not applied to the web page; if the value is "1.5", then the device is
- * considered a high density device (hdpi) and the page content is scaled 1.5x; if the
- * value is "0.75", then the device is considered a low density device (ldpi) and the content is
- * scaled 0.75x.</li>
- * <li>The {@code -webkit-device-pixel-ratio} CSS media query. Use this to specify the screen
- * densities for which this style sheet is to be used. The corresponding value should be either
- * "0.75", "1", or "1.5", to indicate that the styles are for devices with low density, medium
- * density, or high density screens, respectively. For example:
- * <pre>
- * &lt;link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:1.5)" href="hdpi.css" /&gt;</pre>
- * <p>The {@code hdpi.css} stylesheet is only used for devices with a screen pixel ratio of 1.5,
- * which is the high density pixel ratio.
- * </li>
- * </ul>
- *
- * <h3>HTML5 Video support</h3>
- *
- * <p>In order to support inline HTML5 video in your application you need to have hardware
- * acceleration turned on.
- *
- * <h3>Full screen support</h3>
- *
- * <p>In order to support full screen &mdash; for video or other HTML content &mdash; you need to set a
- * {@link android.webkit.WebChromeClient} and implement both
- * {@link WebChromeClient#onShowCustomView(View, WebChromeClient.CustomViewCallback)}
- * and {@link WebChromeClient#onHideCustomView()}. If the implementation of either of these two methods is
- * missing then the web contents will not be allowed to enter full screen. Optionally you can implement
- * {@link WebChromeClient#getVideoLoadingProgressView()} to customize the View displayed whilst a video
- * is loading.
- *
- * <h3>HTML5 Geolocation API support</h3>
- *
- * <p>For applications targeting Android N and later releases
- * (API level > {@link android.os.Build.VERSION_CODES#M}) the geolocation api is only supported on
- * secure origins such as https. For such applications requests to geolocation api on non-secure
- * origins are automatically denied without invoking the corresponding
- * {@link WebChromeClient#onGeolocationPermissionsShowPrompt(String, GeolocationPermissions.Callback)}
- * method.
- *
- * <h3>Layout size</h3>
- * <p>
- * It is recommended to set the WebView layout height to a fixed value or to
- * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} instead of using
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.
- * When using {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}
- * for the height none of the WebView's parents should use a
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} layout height since that could result in
- * incorrect sizing of the views.
- *
- * <p>Setting the WebView's height to {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
- * enables the following behaviors:
- * <ul>
- * <li>The HTML body layout height is set to a fixed value. This means that elements with a height
- * relative to the HTML body may not be sized correctly. </li>
- * <li>For applications targeting {@link android.os.Build.VERSION_CODES#KITKAT} and earlier SDKs the
- * HTML viewport meta tag will be ignored in order to preserve backwards compatibility. </li>
- * </ul>
- *
- * <p>
- * Using a layout width of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} is not
- * supported. If such a width is used the WebView will attempt to use the width of the parent
- * instead.
- *
- * <h3>Metrics</h3>
- *
- * <p>
- * WebView may upload anonymous diagnostic data to Google when the user has consented. This data
- * helps Google improve WebView. Data is collected on a per-app basis for each app which has
- * instantiated a WebView. An individual app can opt out of this feature by putting the following
- * tag in its manifest's {@code <application>} element:
- * <pre>
- * &lt;manifest&gt;
- *     &lt;application&gt;
- *         ...
- *         &lt;meta-data android:name=&quot;android.webkit.WebView.MetricsOptOut&quot;
- *             android:value=&quot;true&quot; /&gt;
- *     &lt;/application&gt;
- * &lt;/manifest&gt;
- * </pre>
- * <p>
- * Data will only be uploaded for a given app if the user has consented AND the app has not opted
- * out.
- *
- * <h3>Safe Browsing</h3>
- *
- * <p>
- * With Safe Browsing, WebView will block malicious URLs and present a warning UI to the user to
- * allow them to navigate back safely or proceed to the malicious page.
- * <p>
- * Safe Browsing is enabled by default on devices which support it. If your app needs to disable
- * Safe Browsing for all WebViews, it can do so in the manifest's {@code <application>} element:
- * <p>
- * <pre>
- * &lt;manifest&gt;
- *     &lt;application&gt;
- *         ...
- *         &lt;meta-data android:name=&quot;android.webkit.WebView.EnableSafeBrowsing&quot;
- *             android:value=&quot;false&quot; /&gt;
- *     &lt;/application&gt;
- * &lt;/manifest&gt;
- * </pre>
- *
- * <p>
- * Otherwise, see {@link WebSettings#setSafeBrowsingEnabled}.
+ * <p>To learn more about WebView and alternatives for serving web content, read the
+ * documentation on
+ * <a href="/guide/webapps/">
+ * Web-based content</a>.
  *
  */
 // Implementation notes.
@@ -362,6 +108,7 @@
     // Throwing an exception for incorrect thread usage if the
     // build target is JB MR2 or newer. Defaults to false, and is
     // set in the WebView constructor.
+    @UnsupportedAppUsage
     private static volatile boolean sEnforceThreadChecking = false;
 
     /**
@@ -644,6 +391,7 @@
      * @hide This is used internally by dumprendertree, as it requires the JavaScript interfaces to
      *       be added synchronously, before a subsequent loadUrl call takes effect.
      */
+    @UnsupportedAppUsage
     protected WebView(Context context, AttributeSet attrs, int defStyleAttr,
             Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
         this(context, attrs, defStyleAttr, 0, javaScriptInterfaces, privateBrowsing);
@@ -653,6 +401,7 @@
      * @hide
      */
     @SuppressWarnings("deprecation")  // for super() call into deprecated base class constructor.
+    @UnsupportedAppUsage
     protected WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes,
             Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
         super(context, attrs, defStyleAttr, defStyleRes);
@@ -730,6 +479,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public int getVisibleTitleHeight() {
         checkThread();
         return mProvider.getVisibleTitleHeight();
@@ -834,6 +584,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static void enablePlatformNotifications() {
         // noop
     }
@@ -846,6 +597,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static void disablePlatformNotifications() {
         // noop
     }
@@ -855,6 +607,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void freeMemoryForTests() {
         getFactory().getStatics().freeMemoryForTests();
     }
@@ -899,6 +652,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public boolean savePicture(Bundle b, final File dest) {
         checkThread();
         return mProvider.savePicture(b, dest);
@@ -916,6 +670,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public boolean restorePicture(Bundle b, File src) {
         checkThread();
         return mProvider.restorePicture(b, src);
@@ -1530,6 +1285,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getTouchIconUrl() {
         return mProvider.getTouchIconUrl();
     }
@@ -1562,6 +1318,7 @@
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "webview")
+    @UnsupportedAppUsage
     public int getContentWidth() {
         return mProvider.getContentWidth();
     }
@@ -1612,6 +1369,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isPaused() {
         return mProvider.isPaused();
     }
@@ -2121,6 +1879,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static synchronized PluginList getPluginList() {
         return new PluginList();
     }
@@ -2188,6 +1947,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void refreshPlugins(boolean reloadOpenPages) {
         checkThread();
     }
@@ -2200,6 +1960,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void emulateShiftHeld() {
         checkThread();
     }
@@ -2260,6 +2021,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public View getZoomControls() {
         checkThread();
         return mProvider.getZoomControls();
@@ -2335,6 +2097,7 @@
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void debugDump() {
         checkThread();
     }
@@ -2620,6 +2383,7 @@
     }
 
     // Only used by android.webkit.FindActionModeCallback.
+    @UnsupportedAppUsage
     void notifyFindDialogDismissed() {
         checkThread();
         mProvider.notifyFindDialogDismissed();
@@ -2629,6 +2393,7 @@
     // Private internal stuff
     //-------------------------------------------------------------------------
 
+    @UnsupportedAppUsage
     private WebViewProvider mProvider;
 
     /**
@@ -2672,12 +2437,15 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static WebViewFactoryProvider getFactory() {
         return WebViewFactory.getProvider();
     }
 
+    @UnsupportedAppUsage
     private final Looper mWebViewThread = Looper.myLooper();
 
+    @UnsupportedAppUsage
     private void checkThread() {
         // Ignore mWebViewThread == null because this can be called during in the super class
         // constructor, before this class's own constructor has even started.
@@ -2958,6 +2726,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
             int l, int t, int r, int b) {
         mProvider.getViewDelegate().onDrawVerticalScrollBar(canvas, scrollBar, l, t, r, b);
@@ -3029,6 +2798,7 @@
 
     /** @hide */
     @Override
+    @UnsupportedAppUsage
     protected boolean setFrame(int left, int top, int right, int bottom) {
         return mProvider.getViewDelegate().setFrame(left, top, right, bottom);
     }
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index f686b66..bdd7a09 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -31,18 +31,25 @@
 public class WebViewClient {
 
     /**
-     * Give the host application a chance to take over the control when a new
-     * url is about to be loaded in the current WebView. If WebViewClient is not
-     * provided, by default WebView will ask Activity Manager to choose the
-     * proper handler for the url. If WebViewClient is provided, return {@code true}
-     * means the host application handles the url, while return {@code false} means the
-     * current WebView handles the url.
-     * This method is not called for requests using the POST "method".
+     * Give the host application a chance to take control when a URL is about to be loaded in the
+     * current WebView. If a WebViewClient is not provided, by default WebView will ask Activity
+     * Manager to choose the proper handler for the URL. If a WebViewClient is provided, returning
+     * {@code true} causes the current WebView to abort loading the URL, while returning
+     * {@code false} causes the WebView to continue loading the URL as usual.
+     *
+     * <p class="note"><b>Note:</b> Do not call {@link WebView#loadUrl(String)} with the same
+     * URL and then return {@code true}. This unnecessarily cancels the current load and starts a
+     * new load with the same URL. The correct way to continue loading a given URL is to simply
+     * return {@code false}, without calling {@link WebView#loadUrl(String)}.
+     *
+     * <p class="note"><b>Note:</b> This method is not called for POST requests.
+     *
+     * <p class="note"><b>Note:</b> This method may be called for subframes and with non-HTTP(S)
+     * schemes; calling {@link WebView#loadUrl(String)} with such a URL will fail.
      *
      * @param view The WebView that is initiating the callback.
-     * @param url The url to be loaded.
-     * @return {@code true} if the host application wants to leave the current WebView
-     *         and handle the url itself, otherwise return {@code false}.
+     * @param url The URL to be loaded.
+     * @return {@code true} to cancel the current load, otherwise return {@code false}.
      * @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest)
      *             shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead.
      */
@@ -52,26 +59,25 @@
     }
 
     /**
-     * Give the host application a chance to take over the control when a new
-     * url is about to be loaded in the current WebView. If WebViewClient is not
-     * provided, by default WebView will ask Activity Manager to choose the
-     * proper handler for the url. If WebViewClient is provided, return {@code true}
-     * means the host application handles the url, while return {@code false} means the
-     * current WebView handles the url.
+     * Give the host application a chance to take control when a URL is about to be loaded in the
+     * current WebView. If a WebViewClient is not provided, by default WebView will ask Activity
+     * Manager to choose the proper handler for the URL. If a WebViewClient is provided, returning
+     * {@code true} causes the current WebView to abort loading the URL, while returning
+     * {@code false} causes the WebView to continue loading the URL as usual.
      *
-     * <p>Notes:
-     * <ul>
-     * <li>This method is not called for requests using the POST &quot;method&quot;.</li>
-     * <li>This method is also called for subframes with non-http schemes, thus it is
-     * strongly disadvised to unconditionally call {@link WebView#loadUrl(String)}
-     * with the request's url from inside the method and then return {@code true},
-     * as this will make WebView to attempt loading a non-http url, and thus fail.</li>
-     * </ul>
+     * <p class="note"><b>Note:</b> Do not call {@link WebView#loadUrl(String)} with the request's
+     * URL and then return {@code true}. This unnecessarily cancels the current load and starts a
+     * new load with the same URL. The correct way to continue loading a given URL is to simply
+     * return {@code false}, without calling {@link WebView#loadUrl(String)}.
+     *
+     * <p class="note"><b>Note:</b> This method is not called for POST requests.
+     *
+     * <p class="note"><b>Note:</b> This method may be called for subframes and with non-HTTP(S)
+     * schemes; calling {@link WebView#loadUrl(String)} with such a URL will fail.
      *
      * @param view The WebView that is initiating the callback.
      * @param request Object containing the details of the request.
-     * @return {@code true} if the host application wants to leave the current WebView
-     *         and handle the url itself, otherwise return {@code false}.
+     * @return {@code true} to cancel the current load, otherwise return {@code false}.
      */
     public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
         return shouldOverrideUrlLoading(view, request.getUrl().toString());
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index f067091..ba66571 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.app.Application;
 import android.app.ResourcesManager;
@@ -45,6 +46,7 @@
 @SystemApi
 public final class WebViewDelegate {
 
+    @UnsupportedAppUsage
     /* package */ WebViewDelegate() { }
 
     /**
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index e0ccda9..e9a9e8f 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.Application;
@@ -59,8 +60,10 @@
 
     // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
     // same provider.
+    @UnsupportedAppUsage
     private static WebViewFactoryProvider sProviderInstance;
     private static final Object sProviderLock = new Object();
+    @UnsupportedAppUsage
     private static PackageInfo sPackageInfo;
     private static Boolean sWebViewSupported;
     private static boolean sWebViewDisabled;
@@ -222,6 +225,7 @@
         return loadNativeRet;
     }
 
+    @UnsupportedAppUsage
     static WebViewFactoryProvider getProvider() {
         synchronized (sProviderLock) {
             // For now the main purpose of this function (and the factory abstraction) is to keep
@@ -359,6 +363,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static Context getWebViewContextAndSetProvider() throws MissingWebViewPackageException {
         Application initialApplication = AppGlobals.getInitialApplication();
         try {
@@ -428,6 +433,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static Class<WebViewFactoryProvider> getProviderClass() {
         Context webViewContext = null;
         Application initialApplication = AppGlobals.getInitialApplication();
@@ -509,6 +515,7 @@
     private static String WEBVIEW_UPDATE_SERVICE_NAME = "webviewupdate";
 
     /** @hide */
+    @UnsupportedAppUsage
     public static IWebViewUpdateService getUpdateService() {
         if (isWebViewSupported()) {
             return getUpdateServiceUnchecked();
diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java
index b0e9f01..1704757 100644
--- a/core/java/android/webkit/WebViewProviderInfo.java
+++ b/core/java/android/webkit/WebViewProviderInfo.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.Signature;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -56,6 +57,7 @@
             }
         };
 
+    @UnsupportedAppUsage
     private WebViewProviderInfo(Parcel in) {
         packageName = in.readString();
         description = in.readString();
diff --git a/core/java/android/webkit/WebViewProviderResponse.java b/core/java/android/webkit/WebViewProviderResponse.java
index c0aeb59..0edcb6f 100644
--- a/core/java/android/webkit/WebViewProviderResponse.java
+++ b/core/java/android/webkit/WebViewProviderResponse.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.PackageInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -56,6 +57,7 @@
         out.writeInt(status);
     }
 
+    @UnsupportedAppUsage
     public final PackageInfo packageInfo;
     public final int status;
 }
diff --git a/core/java/android/webkit/WebViewUpdateService.java b/core/java/android/webkit/WebViewUpdateService.java
index 629891c..12d3221 100644
--- a/core/java/android/webkit/WebViewUpdateService.java
+++ b/core/java/android/webkit/WebViewUpdateService.java
@@ -17,6 +17,7 @@
 package android.webkit;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.RemoteException;
 
 /**
@@ -25,6 +26,7 @@
 @SystemApi
 public final class WebViewUpdateService {
 
+    @UnsupportedAppUsage
     private WebViewUpdateService () {}
 
     /**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 97b62a8..07096e8 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -20,6 +20,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -248,6 +249,7 @@
     /**
      * Controls CHOICE_MODE_MULTIPLE_MODAL. null when inactive.
      */
+    @UnsupportedAppUsage
     ActionMode mChoiceActionMode;
 
     /**
@@ -276,16 +278,19 @@
     /**
      * Controls how the next layout will happen
      */
+    @UnsupportedAppUsage
     int mLayoutMode = LAYOUT_NORMAL;
 
     /**
      * Should be used by subclasses to listen to changes in the dataset
      */
+    @UnsupportedAppUsage
     AdapterDataSetObserver mDataSetObserver;
 
     /**
      * The adapter containing the data to be displayed by this view
      */
+    @UnsupportedAppUsage
     ListAdapter mAdapter;
 
     /**
@@ -311,22 +316,26 @@
     /**
      * The drawable used to draw the selector
      */
+    @UnsupportedAppUsage
     Drawable mSelector;
 
     /**
      * The current position of the selector in the list.
      */
+    @UnsupportedAppUsage
     int mSelectorPosition = INVALID_POSITION;
 
     /**
      * Defines the selector's location and dimension at drawing time
      */
+    @UnsupportedAppUsage
     Rect mSelectorRect = new Rect();
 
     /**
      * The data set used to store unused views that should be reused during the next layout
      * to avoid creating new ones
      */
+    @UnsupportedAppUsage
     final RecycleBin mRecycler = new RecycleBin();
 
     /**
@@ -337,6 +346,7 @@
     /**
      * The selection's top padding
      */
+    @UnsupportedAppUsage
     int mSelectionTopPadding = 0;
 
     /**
@@ -347,6 +357,7 @@
     /**
      * The selection's bottom padding
      */
+    @UnsupportedAppUsage
     int mSelectionBottomPadding = 0;
 
     /**
@@ -379,6 +390,7 @@
     /**
      * The position of the view that received the down motion event
      */
+    @UnsupportedAppUsage
     int mMotionPosition;
 
     /**
@@ -399,12 +411,14 @@
     /**
      * The Y value associated with the the down motion event
      */
+    @UnsupportedAppUsage
     int mMotionY;
 
     /**
      * One of TOUCH_MODE_REST, TOUCH_MODE_DOWN, TOUCH_MODE_TAP, TOUCH_MODE_SCROLL, or
      * TOUCH_MODE_DONE_WAITING
      */
+    @UnsupportedAppUsage
     int mTouchMode = TOUCH_MODE_REST;
 
     /**
@@ -420,16 +434,19 @@
     /**
      * Determines speed during touch scrolling
      */
+    @UnsupportedAppUsage
     private VelocityTracker mVelocityTracker;
 
     /**
      * Handles one frame of a fling
      */
+    @UnsupportedAppUsage
     private FlingRunnable mFlingRunnable;
 
     /**
      * Handles scrolling between positions within the list.
      */
+    @UnsupportedAppUsage
     AbsPositionScroller mPositionScroller;
 
     /**
@@ -463,11 +480,13 @@
     /**
      * Optional callback to notify client when scroll position has changed
      */
+    @UnsupportedAppUsage
     private OnScrollListener mOnScrollListener;
 
     /**
      * Keeps track of our accessory window
      */
+    @UnsupportedAppUsage
     PopupWindow mPopup;
 
     /**
@@ -501,6 +520,7 @@
      */
     int mResurrectToPosition = INVALID_POSITION;
 
+    @UnsupportedAppUsage
     private ContextMenuInfo mContextMenuInfo = null;
 
     /**
@@ -547,11 +567,13 @@
     /**
      * The last CheckForLongPress runnable we posted, if any
      */
+    @UnsupportedAppUsage
     private CheckForLongPress mPendingCheckForLongPress;
 
     /**
      * The last CheckForTap runnable we posted, if any
      */
+    @UnsupportedAppUsage
     private CheckForTap mPendingCheckForTap;
 
     /**
@@ -590,6 +612,7 @@
     /**
      * The select child's view (from the adapter's getView) is enabled.
      */
+    @UnsupportedAppUsage
     private boolean mIsChildViewEnabled;
 
     /**
@@ -606,6 +629,7 @@
     /**
      * Helper object that renders and controls the fast scroll thumb.
      */
+    @UnsupportedAppUsage
     private FastScroller mFastScroll;
 
     /**
@@ -616,6 +640,7 @@
 
     private boolean mGlobalLayoutListenerAddedFilter;
 
+    @UnsupportedAppUsage
     private int mTouchSlop;
     private float mDensityScale;
 
@@ -627,6 +652,7 @@
     private Runnable mClearScrollingCache;
     Runnable mPositionScrollAfterLayout;
     private int mMinimumVelocity;
+    @UnsupportedAppUsage
     private int mMaximumVelocity;
     private float mVelocityScale = 1.0f;
 
@@ -651,6 +677,7 @@
      * ID of the active pointer. This is used to retain consistency during
      * drags/flings if multiple pointers are used.
      */
+    @UnsupportedAppUsage
     private int mActivePointerId = INVALID_POINTER;
 
     /**
@@ -662,11 +689,13 @@
     /**
      * Maximum distance to overscroll by during edge effects
      */
+    @UnsupportedAppUsage
     int mOverscrollDistance;
 
     /**
      * Maximum distance to overfling during edge effects
      */
+    @UnsupportedAppUsage
     int mOverflingDistance;
 
     // These two EdgeGlows are always set and used together.
@@ -675,11 +704,13 @@
     /**
      * Tracks the state of the top edge glow.
      */
+    @UnsupportedAppUsage
     private EdgeEffect mEdgeGlowTop;
 
     /**
      * Tracks the state of the bottom edge glow.
      */
+    @UnsupportedAppUsage
     private EdgeEffect mEdgeGlowBottom;
 
     /**
@@ -781,7 +812,7 @@
          * @param firstVisibleItem the index of the first visible cell (ignore if
          *        visibleItemCount == 0)
          * @param visibleItemCount the number of visible cells
-         * @param totalItemCount the number of items in the list adaptor
+         * @param totalItemCount the number of items in the list adapter
          */
         public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                 int totalItemCount);
@@ -1418,6 +1449,7 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     protected boolean isVerticalScrollBarHidden() {
         return isFastScrollEnabled();
     }
@@ -1469,6 +1501,7 @@
     /**
      * Notify our scroll listener (if there is one) of a change in scroll state
      */
+    @UnsupportedAppUsage
     void invokeOnItemScrollListener() {
         if (mFastScroll != null) {
             mFastScroll.onScroll(mFirstPosition, getChildCount(), mItemCount);
@@ -1691,7 +1724,9 @@
 
     static class SavedState extends BaseSavedState {
         long selectedId;
+        @UnsupportedAppUsage
         long firstId;
+        @UnsupportedAppUsage
         int viewTop;
         int position;
         int height;
@@ -2228,6 +2263,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private boolean canScrollUp() {
         boolean canScrollUp;
         // 0th element is not visible
@@ -2244,6 +2280,7 @@
         return canScrollUp;
     }
 
+    @UnsupportedAppUsage
     private boolean canScrollDown() {
         boolean canScrollDown;
         int count = getChildCount();
@@ -2571,6 +2608,7 @@
         positionSelector(position, sel, false, -1, -1);
     }
 
+    @UnsupportedAppUsage
     private void positionSelector(int position, View sel, boolean manageHotspot, float x, float y) {
         final boolean positionChanged = position != mSelectorPosition;
         if (position != INVALID_POSITION) {
@@ -2857,6 +2895,7 @@
         mScrollDown = down;
     }
 
+    @UnsupportedAppUsage
     void updateSelectorState() {
         final Drawable selector = mSelector;
         if (selector != null && selector.isStateful()) {
@@ -3219,6 +3258,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     boolean performLongPress(final View child,
             final int longPressPosition, final long longPressId) {
         return performLongPress(
@@ -3229,6 +3269,7 @@
                 CheckForLongPress.INVALID_COORD);
     }
 
+    @UnsupportedAppUsage
     boolean performLongPress(final View child,
             final int longPressPosition, final long longPressId, float x, float y) {
         // CHOICE_MODE_MULTIPLE_MODAL takes over long press.
@@ -4337,13 +4378,14 @@
                 translateX = 0;
                 translateY = 0;
             }
+            mEdgeGlowTop.setSize(width, height);
+            mEdgeGlowBottom.setSize(width, height);
             if (!mEdgeGlowTop.isFinished()) {
                 final int restoreCount = canvas.save();
                 canvas.clipRect(translateX, translateY,
                          translateX + width ,translateY + mEdgeGlowTop.getMaxHeight());
                 final int edgeY = Math.min(0, scrollY + mFirstPositionDistanceGuess) + translateY;
                 canvas.translate(translateX, edgeY);
-                mEdgeGlowTop.setSize(width, height);
                 if (mEdgeGlowTop.draw(canvas)) {
                     invalidateTopGlow();
                 }
@@ -4358,7 +4400,6 @@
                         - (clipToPadding ? mPaddingBottom : 0);
                 canvas.translate(edgeX, edgeY);
                 canvas.rotate(180, width, 0);
-                mEdgeGlowBottom.setSize(width, height);
                 if (mEdgeGlowBottom.draw(canvas)) {
                     invalidateBottomGlow();
                 }
@@ -4555,6 +4596,7 @@
      *
      * @param newState The new scroll state.
      */
+    @UnsupportedAppUsage
     void reportScrollStateChange(int newState) {
         if (newState != mLastScrollState) {
             if (mOnScrollListener != null) {
@@ -4574,6 +4616,7 @@
         /**
          * Tracks the decay of a fling scroll
          */
+        @UnsupportedAppUsage
         private final OverScroller mScroller;
 
         /**
@@ -4618,6 +4661,7 @@
             mScroller = new OverScroller(getContext());
         }
 
+        @UnsupportedAppUsage
         void start(int initialVelocity) {
             int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0;
             mLastFlingY = initialY;
@@ -4695,6 +4739,7 @@
             postOnAnimation(this);
         }
 
+        @UnsupportedAppUsage
         void endFling() {
             mTouchMode = TOUCH_MODE_REST;
 
@@ -4949,6 +4994,7 @@
         smoothScrollBy(distance, duration, false, false);
     }
 
+    @UnsupportedAppUsage
     void smoothScrollBy(int distance, int duration, boolean linear,
             boolean suppressEndFlingStateChangeCall) {
         if (mFlingRunnable == null) {
@@ -5091,6 +5137,7 @@
      * @param incrementalDeltaY Change in deltaY from the previous event.
      * @return true if we're already at the beginning/end of the list and have nothing to do.
      */
+    @UnsupportedAppUsage
     boolean trackMotionScroll(int deltaY, int incrementalDeltaY) {
         final int childCount = getChildCount();
         if (childCount == 0) {
@@ -5326,6 +5373,7 @@
      * @param y Where the user touched
      * @return The position of the first (or only) item in the row containing y
      */
+    @UnsupportedAppUsage
     abstract int findMotionRow(int y);
 
     /**
@@ -5358,6 +5406,7 @@
      * If there is a selection returns false.
      * Otherwise resurrects the selection and returns true if resurrected.
      */
+    @UnsupportedAppUsage
     boolean resurrectSelectionIfNeeded() {
         if (mSelectedPosition < 0 && resurrectSelection()) {
             updateSelectorState();
@@ -6522,6 +6571,7 @@
             @ViewDebug.IntToString(from = ITEM_VIEW_TYPE_IGNORE, to = "ITEM_VIEW_TYPE_IGNORE"),
             @ViewDebug.IntToString(from = ITEM_VIEW_TYPE_HEADER_OR_FOOTER, to = "ITEM_VIEW_TYPE_HEADER_OR_FOOTER")
         })
+        @UnsupportedAppUsage
         int viewType;
 
         /**
@@ -6549,6 +6599,7 @@
          * scrap heap.
          * @hide
          */
+        @UnsupportedAppUsage
         int scrappedFromPosition;
 
         /**
@@ -6617,6 +6668,7 @@
      * @see android.widget.AbsListView.RecyclerListener
      */
     class RecycleBin {
+        @UnsupportedAppUsage
         private RecyclerListener mRecyclerListener;
 
         /**
@@ -6698,6 +6750,7 @@
         /**
          * Clears the scrap heap.
          */
+        @UnsupportedAppUsage
         void clear() {
             if (mViewTypeCount == 1) {
                 final ArrayList<View> scrap = mCurrentScrap;
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 61a5873..a85c585 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
@@ -43,6 +44,7 @@
 public abstract class AbsSeekBar extends ProgressBar {
     private final Rect mTempRect = new Rect();
 
+    @UnsupportedAppUsage
     private Drawable mThumb;
     private ColorStateList mThumbTintList = null;
     private PorterDuff.Mode mThumbTintMode = null;
@@ -56,17 +58,20 @@
     private boolean mHasTickMarkTintMode = false;
 
     private int mThumbOffset;
+    @UnsupportedAppUsage
     private boolean mSplitTrack;
 
     /**
      * On touch, this offset plus the scaled value from the position of the
      * touch will form the progress value. Usually 0.
      */
+    @UnsupportedAppUsage
     float mTouchProgressOffset;
 
     /**
      * Whether this is user seekable.
      */
+    @UnsupportedAppUsage
     boolean mIsUserSeekable = true;
 
     /**
@@ -76,10 +81,12 @@
     private int mKeyProgressIncrement = 1;
 
     private static final int NO_ALPHA = 0xFF;
+    @UnsupportedAppUsage
     private float mDisabledAlpha;
 
     private int mScaledTouchSlop;
     private float mTouchDownX;
+    @UnsupportedAppUsage
     private boolean mIsDragging;
 
     public AbsSeekBar(Context context) {
@@ -729,6 +736,7 @@
     /**
      * Draw the thumb.
      */
+    @UnsupportedAppUsage
     void drawThumb(Canvas canvas) {
         if (mThumb != null) {
             final int saveCount = canvas.save();
@@ -834,6 +842,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void trackTouchEvent(MotionEvent event) {
         final int x = Math.round(event.getX());
         final int y = Math.round(event.getY());
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 46269c6..eb20a76 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -22,6 +22,7 @@
 import android.animation.PropertyValuesHolder;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -586,6 +587,7 @@
      * Dismiss all popup menus - overflow and submenus.
      * @return true if popups were dismissed, false otherwise. (This can be because none were open.)
      */
+    @UnsupportedAppUsage
     public boolean dismissPopupMenus() {
         boolean result = hideOverflowMenu();
         result |= hideSubMenus();
@@ -608,6 +610,7 @@
     /**
      * @return true if the overflow menu is currently showing
      */
+    @UnsupportedAppUsage
     public boolean isOverflowMenuShowing() {
         return mOverflowPopup != null && mOverflowPopup.isShowing();
     }
@@ -766,6 +769,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public Parcelable onSaveInstanceState() {
         SavedState state = new SavedState();
         state.openSubMenuId = mOpenSubMenuId;
@@ -773,6 +777,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void onRestoreInstanceState(Parcelable state) {
         SavedState saved = (SavedState) state;
         if (saved.openSubMenuId > 0) {
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index c4bbdb0..7e58622 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
@@ -564,6 +565,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean isOverflowReserved() {
         return mReserveOverflow;
     }
@@ -655,6 +657,7 @@
      * Must be called before the first call to getMenu()
      * @hide
      */
+    @UnsupportedAppUsage
     public void setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) {
         mActionMenuPresenterCallback = pcb;
         mMenuBuilderCallback = mcb;
@@ -664,6 +667,7 @@
      * Returns the current menu or null if one has not yet been configured.
      * @hide Internal use only for action bar integration
      */
+    @UnsupportedAppUsage
     public MenuBuilder peekMenu() {
         return mMenu;
     }
@@ -697,6 +701,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean isOverflowMenuShowPending() {
         return mPresenter != null && mPresenter.isOverflowMenuShowPending();
     }
@@ -714,6 +719,7 @@
      * @hide Private LinearLayout (superclass) API. Un-hide if LinearLayout API is made public.
      */
     @Override
+    @UnsupportedAppUsage
     protected boolean hasDividerBeforeChildAt(int childIndex) {
         if (childIndex == 0) {
             return false;
@@ -736,6 +742,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setExpandedActionViewsExclusive(boolean exclusive) {
         mPresenter.setExpandedActionViewsExclusive(exclusive);
     }
@@ -783,6 +790,7 @@
 
     /** @hide */
     public interface ActionMenuChildView {
+        @UnsupportedAppUsage
         public boolean needsDividerBefore();
         public boolean needsDividerAfter();
     }
@@ -790,25 +798,31 @@
     public static class LayoutParams extends LinearLayout.LayoutParams {
         /** @hide */
         @ViewDebug.ExportedProperty(category = "layout")
+        @UnsupportedAppUsage
         public boolean isOverflowButton;
 
         /** @hide */
         @ViewDebug.ExportedProperty(category = "layout")
+        @UnsupportedAppUsage
         public int cellsUsed;
 
         /** @hide */
         @ViewDebug.ExportedProperty(category = "layout")
+        @UnsupportedAppUsage
         public int extraPixels;
 
         /** @hide */
         @ViewDebug.ExportedProperty(category = "layout")
+        @UnsupportedAppUsage
         public boolean expandable;
 
         /** @hide */
         @ViewDebug.ExportedProperty(category = "layout")
+        @UnsupportedAppUsage
         public boolean preventEdgeOffset;
 
         /** @hide */
+        @UnsupportedAppUsage
         public boolean expanded;
 
         public LayoutParams(Context c, AttributeSet attrs) {
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index 75c857c..f5bf759 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -339,6 +340,7 @@
      *
      * @return The model.
      */
+    @UnsupportedAppUsage
     public static ActivityChooserModel get(Context context, String historyFileName) {
         synchronized (sRegistryLock) {
             ActivityChooserModel dataModel = sDataModelRegistry.get(historyFileName);
@@ -376,6 +378,7 @@
      *
      * @param intent The intent.
      */
+    @UnsupportedAppUsage
     public void setIntent(Intent intent) {
         synchronized (mInstanceLock) {
             if (mIntent == intent) {
@@ -405,6 +408,7 @@
      *
      * @see #setIntent(Intent)
      */
+    @UnsupportedAppUsage
     public int getActivityCount() {
         synchronized (mInstanceLock) {
             ensureConsistentState();
@@ -420,6 +424,7 @@
      * @see ActivityResolveInfo
      * @see #setIntent(Intent)
      */
+    @UnsupportedAppUsage
     public ResolveInfo getActivity(int index) {
         synchronized (mInstanceLock) {
             ensureConsistentState();
@@ -467,6 +472,7 @@
      * @see HistoricalRecord
      * @see OnChooseActivityListener
      */
+    @UnsupportedAppUsage
     public Intent chooseActivity(int index) {
         synchronized (mInstanceLock) {
             if (mIntent == null) {
@@ -507,6 +513,7 @@
      *
      * @param listener The listener.
      */
+    @UnsupportedAppUsage
     public void setOnChooseActivityListener(OnChooseActivityListener listener) {
         synchronized (mInstanceLock) {
             mActivityChoserModelPolicy = listener;
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 121a8c5..58715ee 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -323,6 +324,7 @@
      *
      * @param drawable The drawable.
      */
+    @UnsupportedAppUsage
     public void setExpandActivityOverflowButtonDrawable(Drawable drawable) {
         mExpandActivityOverflowButtonImage.setImageDrawable(drawable);
     }
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 6c19256..dd6c923 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.database.DataSetObserver;
 import android.os.Parcelable;
@@ -68,6 +69,7 @@
      * The position of the first child displayed
      */
     @ViewDebug.ExportedProperty(category = "scrolling")
+    @UnsupportedAppUsage
     int mFirstPosition = 0;
 
     /**
@@ -79,6 +81,7 @@
     /**
      * Position from which to start looking for mSyncRowId
      */
+    @UnsupportedAppUsage
     int mSyncPosition;
 
     /**
@@ -94,6 +97,7 @@
     /**
      * True if we need to sync to mSyncRowId
      */
+    @UnsupportedAppUsage
     boolean mNeedSync = false;
 
     /**
@@ -131,11 +135,13 @@
     /**
      * The listener that receives notifications when an item is selected.
      */
+    @UnsupportedAppUsage
     OnItemSelectedListener mOnItemSelectedListener;
 
     /**
      * The listener that receives notifications when an item is clicked.
      */
+    @UnsupportedAppUsage
     OnItemClickListener mOnItemClickListener;
 
     /**
@@ -146,6 +152,7 @@
     /**
      * True if the data has changed since the last layout
      */
+    @UnsupportedAppUsage
     boolean mDataChanged;
 
     /**
@@ -153,17 +160,20 @@
      * during the next layout.
      */
     @ViewDebug.ExportedProperty(category = "list")
+    @UnsupportedAppUsage
     int mNextSelectedPosition = INVALID_POSITION;
 
     /**
      * The item id of the item to select during the next layout.
      */
+    @UnsupportedAppUsage
     long mNextSelectedRowId = INVALID_ROW_ID;
 
     /**
      * The position within the adapter's data set of the currently selected item.
      */
     @ViewDebug.ExportedProperty(category = "list")
+    @UnsupportedAppUsage
     int mSelectedPosition = INVALID_POSITION;
 
     /**
@@ -201,6 +211,7 @@
     /**
      * The last selected position we used when notifying
      */
+    @UnsupportedAppUsage
     int mOldSelectedPosition = INVALID_POSITION;
 
     /**
@@ -293,7 +304,7 @@
 
     /**
      * @return The callback to be invoked with an item in this AdapterView has
-     *         been clicked, or null id no callback has been set.
+     *         been clicked, or null if no callback has been set.
      */
     @Nullable
     public final OnItemClickListener getOnItemClickListener() {
@@ -365,7 +376,7 @@
 
     /**
      * @return The callback to be invoked with an item in this AdapterView has
-     *         been clicked and held, or null id no callback as been set.
+     *         been clicked and held, or null if no callback has been set.
      */
     public final OnItemLongClickListener getOnItemLongClickListener() {
         return mOnItemLongClickListener;
@@ -900,6 +911,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void selectionChanged() {
         // We're about to post or run the selection notifier, so we don't need
         // a pending notifier.
@@ -1217,6 +1229,7 @@
      * Utility to keep mSelectedPosition and mSelectedRowId in sync
      * @param position Our current position
      */
+    @UnsupportedAppUsage
     void setSelectedPositionInt(int position) {
         mSelectedPosition = position;
         mSelectedRowId = getItemIdAtPosition(position);
@@ -1227,6 +1240,7 @@
      * @param position Intended value for mSelectedPosition the next time we go
      * through layout
      */
+    @UnsupportedAppUsage
     void setNextSelectedPositionInt(int position) {
         mNextSelectedPosition = position;
         mNextSelectedRowId = getItemIdAtPosition(position);
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index bde5f7f..795b034 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -46,8 +47,11 @@
 public class AnalogClock extends View {
     private Time mCalendar;
 
+    @UnsupportedAppUsage
     private Drawable mHourHand;
+    @UnsupportedAppUsage
     private Drawable mMinuteHand;
+    @UnsupportedAppUsage
     private Drawable mDial;
 
     private int mDialWidth;
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index e6f948f..b754d84 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -16,6 +16,7 @@
 */
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -257,6 +258,7 @@
         mNewPermPrefix = mContext.getText(R.string.perms_new_perm_prefix);
     }
 
+    @UnsupportedAppUsage
     public AppSecurityPermissions(Context context, String packageName) {
         this(context);
         mPackageName = packageName;
@@ -418,6 +420,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public int getPermissionCount() {
         return getPermissionCount(WHICH_ALL);
     }
@@ -438,6 +441,7 @@
         return N;
     }
 
+    @UnsupportedAppUsage
     public View getPermissionsView() {
         return getPermissionsView(WHICH_ALL, false);
     }
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index f18f217..c3c2c0d 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -21,6 +21,7 @@
 import android.annotation.LayoutRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.util.Log;
@@ -77,6 +78,7 @@
      * used by the filter (see {@link #getFilter()} to make a synchronized copy of
      * the original array of data.
      */
+    @UnsupportedAppUsage
     private final Object mLock = new Object();
 
     private final LayoutInflater mInflater;
@@ -99,6 +101,7 @@
      * Contains the list of objects that represent the data of this ArrayAdapter.
      * The content of this list is referred to as "the array" in the documentation.
      */
+    @UnsupportedAppUsage
     private List<T> mObjects;
 
     /**
@@ -121,6 +124,7 @@
 
     // A copy of the original mObjects array, initialized from and then used instead as soon as
     // the mFilter ArrayFilter is used. mObjects will then only contain the filtered values.
+    @UnsupportedAppUsage
     private ArrayList<T> mOriginalValues;
     private ArrayFilter mFilter;
 
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 49741d4..71d13a9 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.DrawableRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -102,10 +103,13 @@
     /** Context used to inflate the popup window or dialog. */
     private final Context mPopupContext;
 
+    @UnsupportedAppUsage
     private final ListPopupWindow mPopup;
+    @UnsupportedAppUsage
     private final PassThroughClickListener mPassThroughClickListener;
 
     private CharSequence mHintText;
+    @UnsupportedAppUsage
     private TextView mHintView;
     private int mHintResource;
 
@@ -132,6 +136,7 @@
     // Set to false when the list is hidden to prevent asynchronous updates to popup the list again.
     private boolean mPopupCanBeUpdated = true;
 
+    @UnsupportedAppUsage
     private PopupDataSetObserver mObserver;
 
     /**
@@ -528,6 +533,7 @@
      *
      * @hide Pending API council approval
      */
+    @UnsupportedAppUsage
     public void setDropDownAnimationStyle(int animationStyle) {
         mPopup.setAnimationStyle(animationStyle);
     }
@@ -566,6 +572,7 @@
      *
      * @hide Pending API council approval
      */
+    @UnsupportedAppUsage
     public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
         mPopup.setDropDownAlwaysVisible(dropDownAlwaysVisible);
     }
@@ -587,6 +594,7 @@
      *
      * @hide Pending API council approval
      */
+    @UnsupportedAppUsage
     public void setDropDownDismissedOnCompletion(boolean dropDownDismissedOnCompletion) {
         mDropDownDismissedOnCompletion = dropDownDismissedOnCompletion;
     }
@@ -866,6 +874,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void doBeforeTextChanged() {
         if (mBlockCompletion) return;
 
@@ -875,6 +884,7 @@
         if (DEBUG) Log.v(TAG, "before text changed: open=" + mOpenBefore);
     }
 
+    @UnsupportedAppUsage
     void doAfterTextChanged() {
         if (mBlockCompletion) return;
 
@@ -1171,6 +1181,7 @@
      *
      * @hide internal used only by SearchDialog
      */
+    @UnsupportedAppUsage
     public void showDropDownAfterLayout() {
         mPopup.postShow();
     }
@@ -1181,6 +1192,7 @@
      * the background.
      * @hide internal used only here and SearchDialog
      */
+    @UnsupportedAppUsage
     public void ensureImeVisible(boolean visible) {
         mPopup.setInputMethodMode(visible
                 ? ListPopupWindow.INPUT_METHOD_NEEDED : ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
@@ -1192,6 +1204,7 @@
     /**
      * @hide internal used only here and SearchDialog
      */
+    @UnsupportedAppUsage
     public boolean isInputMethodNotNeeded() {
         return mPopup.getInputMethodMode() == ListPopupWindow.INPUT_METHOD_NOT_NEEDED;
     }
@@ -1225,6 +1238,7 @@
      *
      * @hide used only by SearchDialog
      */
+    @UnsupportedAppUsage
     public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
         mPopup.setForceIgnoreOutsideTouch(forceIgnoreOutsideTouch);
     }
diff --git a/core/java/android/widget/BaseAdapter.java b/core/java/android/widget/BaseAdapter.java
index 5838cc1..7b9365b 100644
--- a/core/java/android/widget/BaseAdapter.java
+++ b/core/java/android/widget/BaseAdapter.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.database.DataSetObservable;
 import android.database.DataSetObserver;
 import android.view.View;
@@ -29,6 +30,7 @@
  * specialized {@link SpinnerAdapter} interface).
  */
 public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
+    @UnsupportedAppUsage
     private final DataSetObservable mDataSetObservable = new DataSetObservable();
     private CharSequence[] mAutofillOptions;
 
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index db50e34..2ff815d 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -72,6 +73,7 @@
     private static final int MODE_HOLO = 0;
     private static final int MODE_MATERIAL = 1;
 
+    @UnsupportedAppUsage
     private final CalendarViewDelegate mDelegate;
 
     /**
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 92bfd56..1472b01 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -19,6 +19,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
@@ -53,6 +54,7 @@
     private boolean mChecked;
 
     private int mCheckMarkResource;
+    @UnsupportedAppUsage
     private Drawable mCheckMarkDrawable;
     private ColorStateList mCheckMarkTintList = null;
     private PorterDuff.Mode mCheckMarkTintMode = null;
@@ -61,6 +63,7 @@
 
     private int mBasePadding;
     private int mCheckMarkWidth;
+    @UnsupportedAppUsage
     private int mCheckMarkGravity = Gravity.END;
 
     private boolean mNeedRequestlayout;
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 0762b15..8d09489 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -19,6 +19,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
@@ -59,14 +60,17 @@
     private static final String LOG_TAG = CompoundButton.class.getSimpleName();
 
     private boolean mChecked;
+    @UnsupportedAppUsage
     private boolean mBroadcasting;
 
+    @UnsupportedAppUsage
     private Drawable mButtonDrawable;
     private ColorStateList mButtonTintList = null;
     private PorterDuff.Mode mButtonTintMode = null;
     private boolean mHasButtonTint = false;
     private boolean mHasButtonTintMode = false;
 
+    @UnsupportedAppUsage
     private OnCheckedChangeListener mOnCheckedChangeListener;
     private OnCheckedChangeListener mOnCheckedChangeWidgetListener;
 
diff --git a/core/java/android/widget/CursorAdapter.java b/core/java/android/widget/CursorAdapter.java
index 9fb98db..cc8b5500 100644
--- a/core/java/android/widget/CursorAdapter.java
+++ b/core/java/android/widget/CursorAdapter.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.content.Context;
 import android.content.res.Resources;
@@ -43,6 +44,7 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected boolean mDataValid;
     /**
      * This field should be made private, so it is hidden from the SDK.
@@ -53,11 +55,13 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected Cursor mCursor;
     /**
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected Context mContext;
     /**
      * Context used for {@link #getDropDownView(int, View, ViewGroup)}.
@@ -68,16 +72,19 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected int mRowIDColumn;
     /**
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected ChangeObserver mChangeObserver;
     /**
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected DataSetObserver mDataSetObserver;
     /**
      * This field should be made private, so it is hidden from the SDK.
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index b2b93fa..df53795 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -114,6 +115,7 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface DatePickerMode {}
 
+    @UnsupportedAppUsage
     private final DatePickerDelegate mDelegate;
 
     @DatePickerMode
@@ -329,6 +331,7 @@
      * @param callback the callback, may be null
      * @hide
      */
+    @UnsupportedAppUsage
     public void setValidationCallback(@Nullable ValidationCallback callback) {
         mDelegate.setValidationCallback(callback);
     }
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index dba74b1..f88a4e2 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -502,6 +503,7 @@
                 || mCurrentDate.get(Calendar.DAY_OF_MONTH) != dayOfMonth);
     }
 
+    @UnsupportedAppUsage
     private void setDate(int year, int month, int dayOfMonth) {
         mCurrentDate.set(year, month, dayOfMonth);
         resetAutofilledValue();
@@ -512,6 +514,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void updateSpinners() {
         // set the spinner ranges respecting the min and max dates
         if (mCurrentDate.equals(mMinDate)) {
@@ -564,6 +567,7 @@
     /**
      * Updates the calendar view with the current date.
      */
+    @UnsupportedAppUsage
     private void updateCalendarView() {
         mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
     }
@@ -572,6 +576,7 @@
     /**
      * Notifies the listener, if such, for a change in the selected date.
      */
+    @UnsupportedAppUsage
     private void notifyDateChanged() {
         mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
         if (mOnDateChangedListener != null) {
@@ -627,6 +632,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void updateInputState() {
         // Make sure that if the user changes the value and the IME is active
         // for one of the inputs if this widget, the IME is closed. If the user
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index 621a745..bf2762a 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -22,6 +22,7 @@
 import static android.text.format.DateUtils.YEAR_IN_MILLIS;
 import static android.text.format.Time.getJulianDay;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -30,7 +31,6 @@
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.database.ContentObserver;
-import android.icu.util.Calendar;
 import android.os.Handler;
 import android.text.format.Time;
 import android.util.AttributeSet;
@@ -41,6 +41,7 @@
 
 import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
 
@@ -76,6 +77,7 @@
         this(context, null);
     }
 
+    @UnsupportedAppUsage
     public DateTimeView(Context context, AttributeSet attrs) {
         super(context, attrs);
         final TypedArray a = context.obtainStyledAttributes(attrs,
@@ -124,6 +126,7 @@
     }
 
     @android.view.RemotableViewMethod
+    @UnsupportedAppUsage
     public void setTime(long time) {
         Time t = new Time();
         t.set(time);
@@ -149,6 +152,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void update() {
         if (mTime == null || getVisibility() == GONE) {
             return;
@@ -301,7 +305,7 @@
      */
     private long computeNextMidnight(TimeZone timeZone) {
         Calendar c = Calendar.getInstance();
-        c.setTimeZone(libcore.icu.DateUtilsBridge.icuTimeZone(timeZone));
+        c.setTimeZone(timeZone);
         c.add(Calendar.DAY_OF_MONTH, 1);
         c.set(Calendar.HOUR_OF_DAY, 0);
         c.set(Calendar.MINUTE, 0);
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index f9f5901..7e42862 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.ColorInt;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -79,6 +80,7 @@
     private static final float RADIUS_FACTOR = 0.6f;
 
     private float mGlowAlpha;
+    @UnsupportedAppUsage
     private float mGlowScaleY;
 
     private float mGlowAlphaStart;
@@ -106,6 +108,7 @@
     private float mPullDistance;
 
     private final Rect mBounds = new Rect();
+    @UnsupportedAppUsage
     private final Paint mPaint = new Paint();
     private float mRadius;
     private float mBaseGlowScale;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 058736a..47ce90b 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
 import android.app.RemoteAction;
@@ -201,7 +202,9 @@
     SelectionModifierCursorController mSelectionModifierCursorController;
     // Action mode used when text is selected or when actions on an insertion cursor are triggered.
     private ActionMode mTextActionMode;
+    @UnsupportedAppUsage
     private boolean mInsertionControllerEnabled;
+    @UnsupportedAppUsage
     private boolean mSelectionControllerEnabled;
 
     private final boolean mHapticTextHandleEnabled;
@@ -268,6 +271,7 @@
     boolean mDiscardNextActionUp;
     boolean mIgnoreActionUpEvent;
 
+    @UnsupportedAppUsage
     private long mShowCursor;
     private boolean mRenderCursorRegardlessTiming;
     private Blink mBlink;
@@ -289,6 +293,7 @@
     private boolean mShowErrorAfterAttach;
 
     boolean mInBatchEditControllers;
+    @UnsupportedAppUsage
     boolean mShowSoftInputOnFocus = true;
     private boolean mPreserveSelection;
     private boolean mRestartActionModeOnNextRefresh;
@@ -304,8 +309,11 @@
 
     Drawable mDrawableForCursor = null;
 
+    @UnsupportedAppUsage
     private Drawable mSelectHandleLeft;
+    @UnsupportedAppUsage
     private Drawable mSelectHandleRight;
+    @UnsupportedAppUsage
     private Drawable mSelectHandleCenter;
 
     // Global listener that detects changes in the global position of the TextView
@@ -318,6 +326,7 @@
     Callback mCustomInsertionActionModeCallback;
 
     // Set when this TextView gained focus with some text selected. Will start selection mode.
+    @UnsupportedAppUsage
     boolean mCreatedWithASelection;
 
     // Indicates the current tap state (first tap, double tap, or triple click).
@@ -2024,6 +2033,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void invalidateTextDisplayList() {
         if (mTextRenderNodes != null) {
             for (int i = 0; i < mTextRenderNodes.length; i++) {
@@ -6299,6 +6309,7 @@
 
     static class InputContentType {
         int imeOptions = EditorInfo.IME_NULL;
+        @UnsupportedAppUsage
         String privateImeOptions;
         CharSequence imeActionLabel;
         int imeActionId;
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index 8d9848d..33d1539 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -18,6 +18,7 @@
 
 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -127,15 +128,18 @@
     private static final long PACKED_POSITION_INT_MASK_GROUP = 0x7FFFFFFF;
 
     /** Serves as the glue/translator between a ListView and an ExpandableListView */
+    @UnsupportedAppUsage
     private ExpandableListConnector mConnector;
 
     /** Gives us Views through group+child positions */
     private ExpandableListAdapter mAdapter;
 
     /** Left bound for drawing the indicator. */
+    @UnsupportedAppUsage
     private int mIndicatorLeft;
 
     /** Right bound for drawing the indicator. */
+    @UnsupportedAppUsage
     private int mIndicatorRight;
 
     /** Start bound for drawing the indicator. */
@@ -180,6 +184,7 @@
     private static final int INDICATOR_UNDEFINED = -2;
 
     /** The indicator drawn next to a group. */
+    @UnsupportedAppUsage
     private Drawable mGroupIndicator;
 
     /** The indicator drawn next to a child. */
@@ -200,6 +205,7 @@
             {R.attr.state_expanded, R.attr.state_empty};
 
     /** States for the group where the 0th bit is expanded and 1st bit is empty. */
+    @UnsupportedAppUsage
     private static final int[][] GROUP_STATE_SETS = {
          EMPTY_STATE_SET, // 00
          GROUP_EXPANDED_STATE_SET, // 01
@@ -212,6 +218,7 @@
             {R.attr.state_last};
 
     /** Drawable to be used as a divider when it is adjacent to any children */
+    @UnsupportedAppUsage
     private Drawable mChildDivider;
 
     // Bounds of the indicator to be drawn
@@ -793,6 +800,7 @@
         void onGroupCollapse(int groupPosition);
     }
 
+    @UnsupportedAppUsage
     private OnGroupCollapseListener mOnGroupCollapseListener;
 
     public void setOnGroupCollapseListener(
@@ -811,6 +819,7 @@
         void onGroupExpand(int groupPosition);
     }
 
+    @UnsupportedAppUsage
     private OnGroupExpandListener mOnGroupExpandListener;
 
     public void setOnGroupExpandListener(
@@ -837,6 +846,7 @@
                 long id);
     }
 
+    @UnsupportedAppUsage
     private OnGroupClickListener mOnGroupClickListener;
 
     public void setOnGroupClickListener(OnGroupClickListener onGroupClickListener) {
@@ -864,6 +874,7 @@
                 int childPosition, long id);
     }
 
+    @UnsupportedAppUsage
     private OnChildClickListener mOnChildClickListener;
 
     public void setOnChildClickListener(OnChildClickListener onChildClickListener) {
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 198bf27..2c09185 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -23,6 +23,7 @@
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
@@ -98,13 +99,16 @@
 
     private final Rect mTempBounds = new Rect();
     private final Rect mTempMargins = new Rect();
+    @UnsupportedAppUsage
     private final Rect mContainerRect = new Rect();
 
     private final AbsListView mList;
     private final ViewGroupOverlay mOverlay;
     private final TextView mPrimaryText;
     private final TextView mSecondaryText;
+    @UnsupportedAppUsage
     private final ImageView mThumbImage;
+    @UnsupportedAppUsage
     private final ImageView mTrackImage;
     private final View mPreviewImage;
     /**
@@ -114,6 +118,7 @@
     private final int[] mPreviewResId = new int[2];
 
     /** The minimum touch target size in pixels. */
+    @UnsupportedAppUsage
     private final int mMinimumTouchTarget;
 
     /**
@@ -133,7 +138,9 @@
     /** Theme-specified text color. Used only if text appearance is not set. */
     private ColorStateList mTextColor;
 
+    @UnsupportedAppUsage
     private Drawable mThumbDrawable;
+    @UnsupportedAppUsage
     private Drawable mTrackDrawable;
     private int mTextAppearance;
     private int mThumbPosition;
@@ -161,6 +168,7 @@
     private int mFirstVisibleItem;
 
     /** The number of headers at the top of the view. */
+    @UnsupportedAppUsage
     private int mHeaderCount;
 
     /** The index of the current section. */
@@ -170,6 +178,7 @@
     private int mScrollbarPosition = -1;
 
     /** Whether the list is long enough to need a fast scroller. */
+    @UnsupportedAppUsage
     private boolean mLongList;
 
     private Object[] mSections;
@@ -245,6 +254,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     public FastScroller(AbsListView listView, int styleResId) {
         mList = listView;
         mOldItemCount = listView.getCount();
@@ -392,6 +402,7 @@
     /**
      * Removes this FastScroller overlay from the host view.
      */
+    @UnsupportedAppUsage
     public void remove() {
         mOverlay.remove(mTrackImage);
         mOverlay.remove(mThumbImage);
@@ -507,6 +518,7 @@
         return mWidth;
     }
 
+    @UnsupportedAppUsage
     public void onSizeChanged(int w, int h, int oldw, int oldh) {
         updateLayout();
     }
@@ -816,6 +828,7 @@
         mThumbRange = max - min;
     }
 
+    @UnsupportedAppUsage
     private void setState(int state) {
         mList.removeCallbacks(mDeferHide);
 
@@ -1380,6 +1393,7 @@
         cancelFling();
     }
 
+    @UnsupportedAppUsage
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (!isEnabled()) {
             return false;
@@ -1449,6 +1463,7 @@
         return null;
     }
 
+    @UnsupportedAppUsage
     public boolean onTouchEvent(MotionEvent me) {
         if (!isEnabled()) {
             return false;
diff --git a/core/java/android/widget/Filter.java b/core/java/android/widget/Filter.java
index d901540..16f4ee2 100644
--- a/core/java/android/widget/Filter.java
+++ b/core/java/android/widget/Filter.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -65,6 +66,7 @@
      * @param delayer The delayer.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDelayer(Delayer delayer) {
         synchronized (mLock) {
             mDelayer = delayer;
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index dc8ee01..865f520 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
@@ -58,18 +59,23 @@
     private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START;
 
     @ViewDebug.ExportedProperty(category = "measurement")
+    @UnsupportedAppUsage
     boolean mMeasureAllChildren = false;
 
     @ViewDebug.ExportedProperty(category = "padding")
+    @UnsupportedAppUsage
     private int mForegroundPaddingLeft = 0;
 
     @ViewDebug.ExportedProperty(category = "padding")
+    @UnsupportedAppUsage
     private int mForegroundPaddingTop = 0;
 
     @ViewDebug.ExportedProperty(category = "padding")
+    @UnsupportedAppUsage
     private int mForegroundPaddingRight = 0;
 
     @ViewDebug.ExportedProperty(category = "padding")
+    @UnsupportedAppUsage
     private int mForegroundPaddingBottom = 0;
 
     private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 7655f3d..ea1bfc2 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -75,6 +76,7 @@
     /**
      * Horizontal spacing between items.
      */
+    @UnsupportedAppUsage
     private int mSpacing = 0;
 
     /**
@@ -103,21 +105,25 @@
     /**
      * Helper for detecting touch gestures.
      */
+    @UnsupportedAppUsage
     private GestureDetector mGestureDetector;
 
     /**
      * The position of the item that received the user's down touch.
      */
+    @UnsupportedAppUsage
     private int mDownTouchPosition;
 
     /**
      * The view of the item that received the user's down touch.
      */
+    @UnsupportedAppUsage
     private View mDownTouchView;
     
     /**
      * Executes the delta scrolls from a fling or scroll movement. 
      */
+    @UnsupportedAppUsage
     private FlingRunnable mFlingRunnable = new FlingRunnable();
 
     /**
@@ -143,6 +149,7 @@
     /**
      * The currently selected item's child.
      */
+    @UnsupportedAppUsage
     private View mSelectedChild;
     
     /**
@@ -380,6 +387,7 @@
      * 
      * @param deltaX Change in X from the previous event.
      */
+    @UnsupportedAppUsage
     void trackMotionScroll(int deltaX) {
 
         if (getChildCount() == 0) {
@@ -472,6 +480,7 @@
     /**
      * @return The center of this Gallery.
      */
+    @UnsupportedAppUsage
     private int getCenterOfGallery() {
         return (getWidth() - mPaddingLeft - mPaddingRight) / 2 + mPaddingLeft;
     }
@@ -479,6 +488,7 @@
     /**
      * @return The center of the given view.
      */
+    @UnsupportedAppUsage
     private static int getCenterOfView(View view) {
         return view.getLeft() + view.getWidth() / 2;
     }
@@ -696,6 +706,7 @@
         updateSelectedItemMetadata();
     }
 
+    @UnsupportedAppUsage
     private void fillToGalleryLeft() {
         if (mIsRtl) {
             fillToGalleryLeftRtl();
@@ -767,6 +778,7 @@
         }
     }
     
+    @UnsupportedAppUsage
     private void fillToGalleryRight() {
         if (mIsRtl) {
             fillToGalleryRightRtl();
@@ -851,6 +863,7 @@
      *        building from left to right)?
      * @return A view that has been added to the gallery
      */
+    @UnsupportedAppUsage
     private View makeAndAddView(int position, int offset, int x, boolean fromLeft) {
 
         View child;
@@ -1289,6 +1302,7 @@
         return super.onKeyUp(keyCode, event);
     }
     
+    @UnsupportedAppUsage
     boolean moveDirection(int direction) {
         direction = isLayoutRtl() ? -direction : direction;
         int targetPosition = mSelectedPosition + direction;
@@ -1468,6 +1482,7 @@
             removeCallbacks(this);
         }
         
+        @UnsupportedAppUsage
         public void startUsingVelocity(int initialVelocity) {
             if (initialVelocity == 0) return;
             
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 4b76c18..13c086c 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -31,6 +31,7 @@
 import static java.lang.Math.min;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -2797,6 +2798,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     static final Alignment UNDEFINED_ALIGNMENT = new Alignment() {
         @Override
         int getGravityOffset(View view, int cellDelta) {
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 1ec9b2f..9ccd321 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
@@ -106,14 +107,21 @@
      */
     public static final int AUTO_FIT = -1;
 
+    @UnsupportedAppUsage
     private int mNumColumns = AUTO_FIT;
 
+    @UnsupportedAppUsage
     private int mHorizontalSpacing = 0;
+    @UnsupportedAppUsage
     private int mRequestedHorizontalSpacing;
+    @UnsupportedAppUsage
     private int mVerticalSpacing = 0;
     private int mStretchMode = STRETCH_COLUMN_WIDTH;
+    @UnsupportedAppUsage
     private int mColumnWidth;
+    @UnsupportedAppUsage
     private int mRequestedColumnWidth;
+    @UnsupportedAppUsage
     private int mRequestedNumColumns;
 
     private View mReferenceView = null;
@@ -300,6 +308,7 @@
      * @return The view that is currently selected, if it happens to be in the
      *         range that we draw.
      */
+    @UnsupportedAppUsage
     private View fillDown(int pos, int nextTop) {
         View selectedView = null;
 
@@ -399,6 +408,7 @@
      *
      * @return The view that is currently selected
      */
+    @UnsupportedAppUsage
     private View fillUp(int pos, int nextBottom) {
         View selectedView = null;
 
@@ -965,6 +975,7 @@
         return sel;
     }
 
+    @UnsupportedAppUsage
     private boolean determineColumns(int availableSpace) {
         final int requestedHorizontalSpacing = mRequestedHorizontalSpacing;
         final int stretchMode = mStretchMode;
@@ -1884,6 +1895,7 @@
      * Goes to the next or previous item according to the order set by the
      * adapter.
      */
+    @UnsupportedAppUsage
     boolean sequenceScroll(int direction) {
         int selectedPosition = mSelectedPosition;
         int numColumns = mNumColumns;
diff --git a/core/java/android/widget/HeaderViewListAdapter.java b/core/java/android/widget/HeaderViewListAdapter.java
index f9d8f92..10d50b8 100644
--- a/core/java/android/widget/HeaderViewListAdapter.java
+++ b/core/java/android/widget/HeaderViewListAdapter.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.database.DataSetObserver;
 import android.view.View;
 import android.view.ViewGroup;
@@ -31,11 +32,14 @@
  */
 public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {
 
+    @UnsupportedAppUsage
     private final ListAdapter mAdapter;
 
     // These two ArrayList are assumed to NOT be null.
     // They are indeed created when declared in ListView and then shared.
+    @UnsupportedAppUsage
     ArrayList<ListView.FixedViewInfo> mHeaderViewInfos;
+    @UnsupportedAppUsage
     ArrayList<ListView.FixedViewInfo> mFooterViewInfos;
 
     // Used as a placeholder in case the provided info views are indeed null.
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 0bf2460..bf9dffd 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -76,13 +77,17 @@
     private long mLastScroll;
 
     private final Rect mTempRect = new Rect();
+    @UnsupportedAppUsage
     private OverScroller mScroller;
+    @UnsupportedAppUsage
     private EdgeEffect mEdgeGlowLeft;
+    @UnsupportedAppUsage
     private EdgeEffect mEdgeGlowRight;
 
     /**
      * Position of the last motion event.
      */
+    @UnsupportedAppUsage
     private int mLastMotionX;
 
     /**
@@ -96,6 +101,7 @@
      * layout is dirty. This prevents the scroll from being wrong if the child has not been
      * laid out before requesting focus.
      */
+    @UnsupportedAppUsage
     private View mChildToScrollTo = null;
 
     /**
@@ -103,11 +109,13 @@
      * not the same as 'is being flinged', which can be checked by
      * mScroller.isFinished() (flinging begins when the user lifts his finger).
      */
+    @UnsupportedAppUsage
     private boolean mIsBeingDragged = false;
 
     /**
      * Determines speed during touch scrolling
      */
+    @UnsupportedAppUsage
     private VelocityTracker mVelocityTracker;
 
     /**
@@ -126,7 +134,9 @@
     private int mMinimumVelocity;
     private int mMaximumVelocity;
 
+    @UnsupportedAppUsage
     private int mOverscrollDistance;
+    @UnsupportedAppUsage
     private int mOverflingDistance;
 
     private float mHorizontalScrollFactor;
@@ -437,6 +447,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void recycleVelocityTracker() {
         if (mVelocityTracker != null) {
             mVelocityTracker.recycle();
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 51e481d..0fef9a5 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -96,13 +97,18 @@
     private static final String LOG_TAG = "ImageView";
 
     // settable by the client
+    @UnsupportedAppUsage
     private Uri mUri;
+    @UnsupportedAppUsage
     private int mResource = 0;
     private Matrix mMatrix;
     private ScaleType mScaleType;
     private boolean mHaveFrame = false;
+    @UnsupportedAppUsage
     private boolean mAdjustViewBounds = false;
+    @UnsupportedAppUsage
     private int mMaxWidth = Integer.MAX_VALUE;
+    @UnsupportedAppUsage
     private int mMaxHeight = Integer.MAX_VALUE;
 
     // these are applied to the drawable
@@ -110,11 +116,14 @@
     private boolean mHasColorFilter = false;
     private Xfermode mXfermode;
     private boolean mHasXfermode = false;
+    @UnsupportedAppUsage
     private int mAlpha = 255;
     private boolean mHasAlpha = false;
     private final int mViewAlphaScale = 256;
 
+    @UnsupportedAppUsage
     private Drawable mDrawable = null;
+    @UnsupportedAppUsage
     private BitmapDrawable mRecycleableBitmapDrawable = null;
     private ColorStateList mDrawableTintList = null;
     private PorterDuff.Mode mDrawableTintMode = null;
@@ -124,14 +133,18 @@
     private int[] mState = null;
     private boolean mMergeState = false;
     private int mLevel = 0;
+    @UnsupportedAppUsage
     private int mDrawableWidth;
+    @UnsupportedAppUsage
     private int mDrawableHeight;
+    @UnsupportedAppUsage
     private Matrix mDrawMatrix = null;
 
     // Avoid allocations...
     private final RectF mTempSrc = new RectF();
     private final RectF mTempDst = new RectF();
 
+    @UnsupportedAppUsage
     private boolean mCropToPadding;
 
     private int mBaseline = -1;
@@ -485,6 +498,7 @@
     }
 
     /** @hide **/
+    @UnsupportedAppUsage
     public Runnable setImageResourceAsync(@DrawableRes int resId) {
         Drawable d = null;
         if (resId != 0) {
@@ -540,6 +554,7 @@
     }
 
     /** @hide **/
+    @UnsupportedAppUsage
     public Runnable setImageURIAsync(@Nullable Uri uri) {
         if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) {
             Drawable d = uri == null ? null : getDrawableFromUri(uri);
@@ -899,6 +914,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void resolveUri() {
         if (mDrawable != null) {
             return;
@@ -974,6 +990,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void updateDrawable(Drawable d) {
         if (d != mRecycleableBitmapDrawable && mRecycleableBitmapDrawable != null) {
             mRecycleableBitmapDrawable.setBitmap(null);
@@ -1018,6 +1035,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void resizeFromDrawable() {
         final Drawable d = mDrawable;
         if (d != null) {
@@ -1049,6 +1067,7 @@
         Matrix.ScaleToFit.END
     };
 
+    @UnsupportedAppUsage
     private static Matrix.ScaleToFit scaleTypeToScaleToFit(ScaleType st)  {
         // ScaleToFit enum to their corresponding Matrix.ScaleToFit values
         return sS2FArray[st.nativeInt - 1];
@@ -1313,6 +1332,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void animateTransform(Matrix matrix) {
         if (mDrawable == null) {
             return;
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 40f9652..452e903 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -188,27 +189,35 @@
             @ViewDebug.FlagToString(mask = Gravity.RELATIVE_LAYOUT_DIRECTION,
                 equals = Gravity.RELATIVE_LAYOUT_DIRECTION, name = "RELATIVE")
         }, formatToHexString = true)
+    @UnsupportedAppUsage
     private int mGravity = Gravity.START | Gravity.TOP;
 
     @ViewDebug.ExportedProperty(category = "measurement")
+    @UnsupportedAppUsage
     private int mTotalLength;
 
     @ViewDebug.ExportedProperty(category = "layout")
     private float mWeightSum;
 
     @ViewDebug.ExportedProperty(category = "layout")
+    @UnsupportedAppUsage
     private boolean mUseLargestChild;
 
+    @UnsupportedAppUsage
     private int[] mMaxAscent;
+    @UnsupportedAppUsage
     private int[] mMaxDescent;
 
     private static final int VERTICAL_GRAVITY_COUNT = 4;
 
     private static final int INDEX_CENTER_VERTICAL = 0;
+    @UnsupportedAppUsage
     private static final int INDEX_TOP = 1;
+    @UnsupportedAppUsage
     private static final int INDEX_BOTTOM = 2;
     private static final int INDEX_FILL = 3;
 
+    @UnsupportedAppUsage
     private Drawable mDivider;
     private int mDividerWidth;
     private int mDividerHeight;
@@ -2062,6 +2071,7 @@
 
         /** @hide */
         @Override
+        @UnsupportedAppUsage
         protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
             super.encodeProperties(encoder);
 
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index adf366a..f9564b4 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
@@ -67,6 +68,7 @@
 
     private Context mContext;
     private ListAdapter mAdapter;
+    @UnsupportedAppUsage
     private DropDownListView mDropDownList;
 
     private int mDropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -115,6 +117,7 @@
 
     private boolean mModal;
 
+    @UnsupportedAppUsage
     PopupWindow mPopup;
 
     /**
@@ -310,6 +313,7 @@
      *
      * @hide Used only by AutoCompleteTextView to handle some internal special cases.
      */
+    @UnsupportedAppUsage
     public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
         mForceIgnoreOutsideTouch = forceIgnoreOutsideTouch;
     }
@@ -325,6 +329,7 @@
      *
      * @hide Only used by AutoCompleteTextView under special conditions.
      */
+    @UnsupportedAppUsage
     public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
         mDropDownAlwaysVisible = dropDownAlwaysVisible;
     }
@@ -334,6 +339,7 @@
      *
      * @hide Only used by AutoCompleteTextView under special conditions.
      */
+    @UnsupportedAppUsage
     public boolean isDropDownAlwaysVisible() {
         return mDropDownAlwaysVisible;
     }
@@ -898,6 +904,7 @@
      *
      * @param max Max number of items that can be visible and still allow the list to expand.
      */
+    @UnsupportedAppUsage
     void setListItemExpandMax(int max) {
         mListItemExpandMaximum = max;
     }
@@ -1093,6 +1100,7 @@
      *
      * @return the content's height or -1 if content already exists
      */
+    @UnsupportedAppUsage
     private int buildDropDown() {
         ViewGroup dropDownView;
         int otherHeights = 0;
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index fc9e8e7..ee04bcf 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -19,6 +19,7 @@
 import android.annotation.IdRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
@@ -181,10 +182,14 @@
         public boolean isSelectable;
     }
 
+    @UnsupportedAppUsage
     ArrayList<FixedViewInfo> mHeaderViewInfos = Lists.newArrayList();
+    @UnsupportedAppUsage
     ArrayList<FixedViewInfo> mFooterViewInfos = Lists.newArrayList();
 
+    @UnsupportedAppUsage
     Drawable mDivider;
+    @UnsupportedAppUsage
     int mDividerHeight;
 
     Drawable mOverScrollHeader;
@@ -196,6 +201,7 @@
     private boolean mHeaderDividersEnabled;
     private boolean mFooterDividersEnabled;
 
+    @UnsupportedAppUsage
     private boolean mAreAllItemsSelectable = true;
 
     private boolean mItemsCanFocus = false;
@@ -772,6 +778,7 @@
      * @return The view that is currently selected, if it happens to be in the
      *         range that we draw.
      */
+    @UnsupportedAppUsage
     private View fillDown(int pos, int nextTop) {
         View selectedView = null;
 
@@ -806,6 +813,7 @@
      *
      * @return The view that is currently selected
      */
+    @UnsupportedAppUsage
     private View fillUp(int pos, int nextBottom) {
         View selectedView = null;
 
@@ -1382,6 +1390,7 @@
      *            startPosition is 0).
      * @return The height of this ListView with the given children.
      */
+    @UnsupportedAppUsage
     final int measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition,
             int maxHeight, int disallowPartialChildPosition) {
         final ListAdapter adapter = mAdapter;
@@ -1477,6 +1486,7 @@
      * @return The selected view, or null if the selected view is outside the
      *         visible area.
      */
+    @UnsupportedAppUsage
     private View fillSpecific(int position, int top) {
         boolean tempIsSelected = position == mSelectedPosition;
         View temp = makeAndAddView(position, top, true, mListPadding.left, tempIsSelected);
@@ -1523,6 +1533,7 @@
      *
      * @param childCount Number of children
      */
+    @UnsupportedAppUsage
     private void correctTooHigh(int childCount) {
         // First see if the last item is visible. If it is not, it is OK for the
         // top of the list to be pushed up.
@@ -1572,6 +1583,7 @@
      *
      * @param childCount Number of children
      */
+    @UnsupportedAppUsage
     private void correctTooLow(int childCount) {
         // First see if the first item is visible. If it is not, it is OK for the
         // bottom of the list to be pushed down.
@@ -1967,6 +1979,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     boolean trackMotionScroll(int deltaY, int incrementalDeltaY) {
         final boolean result = super.trackMotionScroll(deltaY, incrementalDeltaY);
         removeUnusedFixedViews(mHeaderViewInfos);
@@ -2000,6 +2013,7 @@
      * @param child a direct child of this list.
      * @return Whether child is a header or footer view.
      */
+    @UnsupportedAppUsage
     private boolean isDirectChildHeaderOrFooter(View child) {
         final ArrayList<FixedViewInfo> headers = mHeaderViewInfos;
         final int numHeaders = headers.size();
@@ -2034,6 +2048,7 @@
      *                 otherwise
      * @return the view that was added
      */
+    @UnsupportedAppUsage
     private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
             boolean selected) {
         if (!mDataChanged) {
@@ -2195,6 +2210,7 @@
      * @param position the position of the item to select
      */
     @Override
+    @UnsupportedAppUsage
     void setSelectionInt(int position) {
         setNextSelectedPositionInt(position);
         boolean awakeScrollbars = false;
@@ -2229,6 +2245,7 @@
      *         down. Returns {@link #INVALID_POSITION} if nothing can be found.
      */
     @Override
+    @UnsupportedAppUsage
     int lookForSelectablePosition(int position, boolean lookDown) {
         final ListAdapter adapter = mAdapter;
         if (adapter == null || isInTouchMode()) {
@@ -2636,6 +2653,7 @@
      *
      * @return whether selection was moved
      */
+    @UnsupportedAppUsage
     boolean arrowScroll(int direction) {
         try {
             mInLayout = true;
@@ -3235,6 +3253,7 @@
      *
      * @param amount The amount (positive or negative) to scroll.
      */
+    @UnsupportedAppUsage
     private void scrollListItemsBy(int amount) {
         offsetChildrenTopAndBottom(amount);
 
@@ -4001,6 +4020,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     int getHeightForPosition(int position) {
         final int height = super.getHeightForPosition(position);
         if (shouldAdjustHeightForDivider(position)) {
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 11054c8..5734171 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -76,10 +76,10 @@
     private final int mWindowHeight;
     // The zoom applied to the view region copied to the magnifier window.
     private final float mZoom;
-    // The width of the bitmaps where the magnifier content is copied.
-    private final int mBitmapWidth;
-    // The height of the bitmaps where the magnifier content is copied.
-    private final int mBitmapHeight;
+    // The width of the content that will be copied to the magnifier.
+    private final int mSourceWidth;
+    // The height of the content that will be copied to the magnifier.
+    private final int mSourceHeight;
     // The elevation of the window containing the magnifier.
     private final float mWindowElevation;
     // The corner radius of the window containing the magnifier.
@@ -91,15 +91,14 @@
     // The center coordinates of the window containing the magnifier.
     private final Point mWindowCoords = new Point();
     // The center coordinates of the content to be magnified,
-    // which can potentially contain a region outside the magnified view.
-    private final Point mCenterZoomCoords = new Point();
-    // The center coordinates of the content to be magnified,
     // clamped inside the visible region of the magnified view.
     private final Point mClampedCenterZoomCoords = new Point();
     // Variables holding previous states, used for detecting redundant calls and invalidation.
     private final Point mPrevStartCoordsInSurface = new Point(
             NONEXISTENT_PREVIOUS_CONFIG_VALUE, NONEXISTENT_PREVIOUS_CONFIG_VALUE);
-    private final PointF mPrevPosInView = new PointF(
+    private final PointF mPrevShowSourceCoords = new PointF(
+            NONEXISTENT_PREVIOUS_CONFIG_VALUE, NONEXISTENT_PREVIOUS_CONFIG_VALUE);
+    private final PointF mPrevShowWindowCoords = new PointF(
             NONEXISTENT_PREVIOUS_CONFIG_VALUE, NONEXISTENT_PREVIOUS_CONFIG_VALUE);
     // Rectangle defining the view surface area we pixel copy content from.
     private final Rect mPixelCopyRequestRect = new Rect();
@@ -120,8 +119,8 @@
         mWindowElevation = context.getResources().getDimension(R.dimen.magnifier_elevation);
         mWindowCornerRadius = getDeviceDefaultDialogCornerRadius();
         mZoom = context.getResources().getFloat(R.dimen.magnifier_zoom_scale);
-        mBitmapWidth = Math.round(mWindowWidth / mZoom);
-        mBitmapHeight = Math.round(mWindowHeight / mZoom);
+        mSourceWidth = Math.round(mWindowWidth / mZoom);
+        mSourceHeight = Math.round(mWindowHeight / mZoom);
         // The view's surface coordinates will not be updated until the magnifier is first shown.
         mViewCoordinatesInSurface = new int[2];
     }
@@ -148,25 +147,50 @@
     /**
      * Shows the magnifier on the screen.
      *
-     * @param xPosInView horizontal coordinate of the center point of the magnifier source relative
-     *        to the view. The lower end is clamped to 0 and the higher end is clamped to the view
-     *        width.
-     * @param yPosInView vertical coordinate of the center point of the magnifier source
-     *        relative to the view. The lower end is clamped to 0 and the higher end is clamped to
-     *        the view height.
+     * @param sourceCenterX horizontal coordinate of the center point of the source rectangle that
+     *        will be magnified and copied to the magnifier, relative to the view.
+     *        The parameter is clamped such that the copy rectangle fits inside [0, view width].
+     * @param sourceCenterY vertical coordinate of the center point of the source rectangle that
+     *        will be magnified and copied to the magnifier, relative to the view.
+     *        The parameter is clamped such that the copy rectangle fits inside [0, view height].
      */
-    public void show(@FloatRange(from = 0) float xPosInView,
-            @FloatRange(from = 0) float yPosInView) {
-        xPosInView = Math.max(0, Math.min(xPosInView, mView.getWidth()));
-        yPosInView = Math.max(0, Math.min(yPosInView, mView.getHeight()));
+    public void show(@FloatRange(from = 0) float sourceCenterX,
+            @FloatRange(from = 0) float sourceCenterY) {
+        final int verticalOffset = mView.getContext().getResources()
+                .getDimensionPixelSize(R.dimen.magnifier_offset);
+        show(sourceCenterX, sourceCenterY, sourceCenterX, sourceCenterY - verticalOffset);
+    }
+
+    /**
+     * Shows the magnifier on the screen at a position
+     * that is independent from its content position.
+     *
+     * @param sourceCenterX horizontal coordinate of the center point of the source rectangle that
+     *        will be magnified and copied to the magnifier, relative to the view.
+     *        The parameter is clamped such that the copy rectangle fits inside [0, view width].
+     * @param sourceCenterY vertical coordinate of the center point of the source rectangle that
+     *        will be magnified and copied to the magnifier, relative to the view.
+     *        The parameter is clamped such that the copy rectangle fits inside [0, view height].
+     * @param magnifierCenterX horizontal coordinate of the center point of the magnifier window
+     *        relative to the view. As the magnifier can be arbitrarily positioned, this can be
+     *        negative or larger than the view width.
+     * @param magnifierCenterY vertical coordinate of the center point of the magnifier window
+     *        relative to the view. As the magnifier can be arbitrarily positioned, this can be
+     *        negative or larger than the view height.
+     */
+    public void show(@FloatRange(from = 0) float sourceCenterX,
+            @FloatRange(from = 0) float sourceCenterY,
+            float magnifierCenterX, float magnifierCenterY) {
+        sourceCenterX = Math.max(0, Math.min(sourceCenterX, mView.getWidth()));
+        sourceCenterY = Math.max(0, Math.min(sourceCenterY, mView.getHeight()));
 
         obtainSurfaces();
-        obtainContentCoordinates(xPosInView, yPosInView);
-        obtainWindowCoordinates();
+        obtainContentCoordinates(sourceCenterX, sourceCenterY);
+        obtainWindowCoordinates(magnifierCenterX, magnifierCenterY);
 
-        final int startX = mClampedCenterZoomCoords.x - mBitmapWidth / 2;
-        final int startY = mClampedCenterZoomCoords.y - mBitmapHeight / 2;
-        if (xPosInView != mPrevPosInView.x || yPosInView != mPrevPosInView.y) {
+        final int startX = mClampedCenterZoomCoords.x - mSourceWidth / 2;
+        final int startY = mClampedCenterZoomCoords.y - mSourceHeight / 2;
+        if (sourceCenterX != mPrevShowSourceCoords.x || sourceCenterY != mPrevShowSourceCoords.y) {
             if (mWindow == null) {
                 synchronized (mLock) {
                     mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
@@ -177,9 +201,24 @@
                 }
             }
             performPixelCopy(startX, startY, true /* update window position */);
-            mPrevPosInView.x = xPosInView;
-            mPrevPosInView.y = yPosInView;
+        } else if (magnifierCenterX != mPrevShowWindowCoords.x
+                || magnifierCenterY != mPrevShowWindowCoords.y) {
+            final Point windowCoords = getCurrentClampedWindowCoordinates();
+            final InternalPopupWindow currentWindowInstance = mWindow;
+            sPixelCopyHandlerThread.getThreadHandler().post(() -> {
+                if (mWindow != currentWindowInstance) {
+                    // The magnifier was dismissed (and maybe shown again) in the meantime.
+                    return;
+                }
+                synchronized (mLock) {
+                    mWindow.setContentPositionForNextDraw(windowCoords.x, windowCoords.y);
+                }
+            });
         }
+        mPrevShowSourceCoords.x = sourceCenterX;
+        mPrevShowSourceCoords.y = sourceCenterY;
+        mPrevShowWindowCoords.x = magnifierCenterX;
+        mPrevShowWindowCoords.y = magnifierCenterY;
     }
 
     /**
@@ -191,8 +230,10 @@
                 mWindow.destroy();
                 mWindow = null;
             }
-            mPrevPosInView.x = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
-            mPrevPosInView.y = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
+            mPrevShowSourceCoords.x = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
+            mPrevShowSourceCoords.y = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
+            mPrevShowWindowCoords.x = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
+            mPrevShowWindowCoords.y = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
             mPrevStartCoordsInSurface.x = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
             mPrevStartCoordsInSurface.y = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
         }
@@ -296,19 +337,17 @@
      * magnifier. These are relative to the surface the content is copied from.
      */
     private void obtainContentCoordinates(final float xPosInView, final float yPosInView) {
-        final float posX;
-        final float posY;
         mView.getLocationInSurface(mViewCoordinatesInSurface);
+        final int zoomCenterX;
+        final int zoomCenterY;
         if (mView instanceof SurfaceView) {
             // No offset required if the backing Surface matches the size of the SurfaceView.
-            posX = xPosInView;
-            posY = yPosInView;
+            zoomCenterX = Math.round(xPosInView);
+            zoomCenterY = Math.round(yPosInView);
         } else {
-            posX = xPosInView + mViewCoordinatesInSurface[0];
-            posY = yPosInView + mViewCoordinatesInSurface[1];
+            zoomCenterX = Math.round(xPosInView + mViewCoordinatesInSurface[0]);
+            zoomCenterY = Math.round(yPosInView + mViewCoordinatesInSurface[1]);
         }
-        mCenterZoomCoords.x = Math.round(posX);
-        mCenterZoomCoords.y = Math.round(posY);
 
         // Clamp the x location to avoid magnifying content which does not belong
         // to the magnified view. This will not take into account overlapping views.
@@ -323,18 +362,29 @@
             // If we copy content from a SurfaceView, clamp coordinates relative to it.
             viewVisibleRegion.offset(-mViewCoordinatesInSurface[0], -mViewCoordinatesInSurface[1]);
         }
-        mClampedCenterZoomCoords.x = Math.max(viewVisibleRegion.left + mBitmapWidth / 2, Math.min(
-                mCenterZoomCoords.x, viewVisibleRegion.right - mBitmapWidth / 2));
-        mClampedCenterZoomCoords.y = mCenterZoomCoords.y;
+        mClampedCenterZoomCoords.x = Math.max(viewVisibleRegion.left + mSourceWidth / 2, Math.min(
+                zoomCenterX, viewVisibleRegion.right - mSourceWidth / 2));
+        mClampedCenterZoomCoords.y = zoomCenterY;
     }
 
-    private void obtainWindowCoordinates() {
-        // Compute the position of the magnifier window. Again, this has to be relative to the
-        // surface of the magnified view, as this surface is the parent of the magnifier surface.
-        final int verticalOffset = mView.getContext().getResources().getDimensionPixelSize(
-                R.dimen.magnifier_offset);
-        mWindowCoords.x = mCenterZoomCoords.x - mWindowWidth / 2;
-        mWindowCoords.y = mCenterZoomCoords.y - mWindowHeight / 2 - verticalOffset;
+    /**
+     * Computes the coordinates of the top left corner of the magnifier window.
+     * These are relative to the surface the magnifier window is attached to.
+     */
+    private void obtainWindowCoordinates(final float xWindowPos, final float yWindowPos) {
+        final int windowCenterX;
+        final int windowCenterY;
+        if (mView instanceof SurfaceView) {
+            // No offset required if the backing Surface matches the size of the SurfaceView.
+            windowCenterX = Math.round(xWindowPos);
+            windowCenterY = Math.round(yWindowPos);
+        } else {
+            windowCenterX = Math.round(xWindowPos + mViewCoordinatesInSurface[0]);
+            windowCenterY = Math.round(yWindowPos + mViewCoordinatesInSurface[1]);
+        }
+
+        mWindowCoords.x = windowCenterX - mWindowWidth / 2;
+        mWindowCoords.y = windowCenterY - mWindowHeight / 2;
         if (mParentSurface != mContentCopySurface) {
             mWindowCoords.x += mViewCoordinatesInSurface[0];
             mWindowCoords.y += mViewCoordinatesInSurface[1];
@@ -348,34 +398,21 @@
         }
         // Clamp copy coordinates inside the surface to avoid displaying distorted content.
         final int clampedStartXInSurface = Math.max(0,
-                Math.min(startXInSurface, mContentCopySurface.mWidth - mBitmapWidth));
+                Math.min(startXInSurface, mContentCopySurface.mWidth - mSourceWidth));
         final int clampedStartYInSurface = Math.max(0,
-                Math.min(startYInSurface, mContentCopySurface.mHeight - mBitmapHeight));
-
+                Math.min(startYInSurface, mContentCopySurface.mHeight - mSourceHeight));
         // Clamp window coordinates inside the parent surface, to avoid displaying
         // the magnifier out of screen or overlapping with system insets.
-        final Rect windowBounds;
-        if (mParentSurface.mIsMainWindowSurface) {
-            final Rect systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
-            windowBounds = new Rect(systemInsets.left, systemInsets.top,
-                     mParentSurface.mWidth - systemInsets.right,
-                    mParentSurface.mHeight - systemInsets.bottom);
-        } else {
-            windowBounds = new Rect(0, 0, mParentSurface.mWidth, mParentSurface.mHeight);
-        }
-        final int windowCoordsX = Math.max(windowBounds.left,
-                Math.min(windowBounds.right - mWindowWidth, mWindowCoords.x));
-        final int windowCoordsY = Math.max(windowBounds.top,
-                Math.min(windowBounds.bottom - mWindowHeight, mWindowCoords.y));
+        final Point windowCoords = getCurrentClampedWindowCoordinates();
 
         // Perform the pixel copy.
         mPixelCopyRequestRect.set(clampedStartXInSurface,
                 clampedStartYInSurface,
-                clampedStartXInSurface + mBitmapWidth,
-                clampedStartYInSurface + mBitmapHeight);
+                clampedStartXInSurface + mSourceWidth,
+                clampedStartYInSurface + mSourceHeight);
         final InternalPopupWindow currentWindowInstance = mWindow;
         final Bitmap bitmap =
-                Bitmap.createBitmap(mBitmapWidth, mBitmapHeight, Bitmap.Config.ARGB_8888);
+                Bitmap.createBitmap(mSourceWidth, mSourceHeight, Bitmap.Config.ARGB_8888);
         PixelCopy.request(mContentCopySurface.mSurface, mPixelCopyRequestRect, bitmap,
                 result -> {
                     synchronized (mLock) {
@@ -385,7 +422,7 @@
                         }
                         if (updateWindowPosition) {
                             // TODO: pull the position update outside #performPixelCopy
-                            mWindow.setContentPositionForNextDraw(windowCoordsX, windowCoordsY);
+                            mWindow.setContentPositionForNextDraw(windowCoords.x, windowCoords.y);
                         }
                         mWindow.updateContent(bitmap);
                     }
@@ -396,6 +433,28 @@
     }
 
     /**
+     * Clamp window coordinates inside the surface the magnifier is attached to, to avoid
+     * displaying the magnifier out of screen or overlapping with system insets.
+     * @return the current window coordinates, after they are clamped inside the parent surface
+     */
+    private Point getCurrentClampedWindowCoordinates() {
+        final Rect windowBounds;
+        if (mParentSurface.mIsMainWindowSurface) {
+            final Rect systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
+            windowBounds = new Rect(systemInsets.left, systemInsets.top,
+                    mParentSurface.mWidth - systemInsets.right,
+                    mParentSurface.mHeight - systemInsets.bottom);
+        } else {
+            windowBounds = new Rect(0, 0, mParentSurface.mWidth, mParentSurface.mHeight);
+        }
+        final int windowCoordsX = Math.max(windowBounds.left,
+                Math.min(windowBounds.right - mWindowWidth, mWindowCoords.x));
+        final int windowCoordsY = Math.max(windowBounds.top,
+                Math.min(windowBounds.bottom - mWindowHeight, mWindowCoords.y));
+        return new Point(windowCoordsX, windowCoordsY);
+    }
+
+    /**
      * Contains a surface and metadata corresponding to it.
      */
     private static class SurfaceInfo {
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 8e04f1c..82d77c5 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
@@ -68,16 +69,29 @@
  */
 public class MediaController extends FrameLayout {
 
+    @UnsupportedAppUsage
     private MediaPlayerControl mPlayer;
+    @UnsupportedAppUsage
     private final Context mContext;
+    @UnsupportedAppUsage
     private View mAnchor;
+    @UnsupportedAppUsage
     private View mRoot;
+    @UnsupportedAppUsage
     private WindowManager mWindowManager;
+    @UnsupportedAppUsage
     private Window mWindow;
+    @UnsupportedAppUsage
     private View mDecor;
+    @UnsupportedAppUsage
     private WindowManager.LayoutParams mDecorLayoutParams;
+    @UnsupportedAppUsage
     private ProgressBar mProgress;
-    private TextView mEndTime, mCurrentTime;
+    @UnsupportedAppUsage
+    private TextView mEndTime;
+    @UnsupportedAppUsage
+    private TextView mCurrentTime;
+    @UnsupportedAppUsage
     private boolean mShowing;
     private boolean mDragging;
     private static final int sDefaultTimeout = 3000;
@@ -87,10 +101,15 @@
     private View.OnClickListener mNextListener, mPrevListener;
     StringBuilder mFormatBuilder;
     Formatter mFormatter;
+    @UnsupportedAppUsage
     private ImageButton mPauseButton;
+    @UnsupportedAppUsage
     private ImageButton mFfwdButton;
+    @UnsupportedAppUsage
     private ImageButton mRewButton;
+    @UnsupportedAppUsage
     private ImageButton mNextButton;
+    @UnsupportedAppUsage
     private ImageButton mPrevButton;
     private CharSequence mPlayDescription;
     private CharSequence mPauseDescription;
@@ -535,6 +554,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     private void updatePausePlay() {
         if (mRoot == null || mPauseButton == null)
             return;
@@ -568,6 +588,7 @@
     // The second scenario involves the user operating the scroll ball, in this
     // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
     // we will simply apply the updated position without suspending regular updates.
+    @UnsupportedAppUsage
     private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
         @Override
         public void onStartTrackingTouch(SeekBar bar) {
@@ -641,6 +662,7 @@
         return MediaController.class.getName();
     }
 
+    @UnsupportedAppUsage
     private final View.OnClickListener mRewListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
@@ -653,6 +675,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     private final View.OnClickListener mFfwdListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index d98b865..b6ed22c 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -19,6 +19,7 @@
 import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -98,6 +99,7 @@
     /**
      * The number of items show in the selector wheel.
      */
+    @UnsupportedAppUsage
     private static final int SELECTOR_WHEEL_ITEM_COUNT = 3;
 
     /**
@@ -108,6 +110,7 @@
     /**
      * The index of the middle selector item.
      */
+    @UnsupportedAppUsage
     private static final int SELECTOR_MIDDLE_ITEM_INDEX = SELECTOR_WHEEL_ITEM_COUNT / 2;
 
     /**
@@ -204,6 +207,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static final Formatter getTwoDigitFormatter() {
         return sTwoDigitFormatter;
     }
@@ -221,6 +225,7 @@
     /**
      * The text for showing the current value.
      */
+    @UnsupportedAppUsage
     private final EditText mInputText;
 
     /**
@@ -231,6 +236,7 @@
     /**
      * The min height of this widget.
      */
+    @UnsupportedAppUsage
     private final int mMinHeight;
 
     /**
@@ -241,6 +247,7 @@
     /**
      * The max width of this widget.
      */
+    @UnsupportedAppUsage
     private final int mMinWidth;
 
     /**
@@ -256,6 +263,7 @@
     /**
      * The height of the text.
      */
+    @UnsupportedAppUsage
     private final int mTextSize;
 
     /**
@@ -276,6 +284,7 @@
     /**
      * Upper value of the range of numbers allowed for the NumberPicker
      */
+    @UnsupportedAppUsage
     private int mMaxValue;
 
     /**
@@ -286,6 +295,7 @@
     /**
      * Listener to be notified upon current value change.
      */
+    @UnsupportedAppUsage
     private OnValueChangeListener mOnValueChangeListener;
 
     /**
@@ -311,11 +321,13 @@
     /**
      * The selector indices whose value are show by the selector.
      */
+    @UnsupportedAppUsage
     private final int[] mSelectorIndices = new int[SELECTOR_WHEEL_ITEM_COUNT];
 
     /**
      * The {@link Paint} for drawing the selector.
      */
+    @UnsupportedAppUsage
     private final Paint mSelectorWheelPaint;
 
     /**
@@ -341,6 +353,7 @@
     /**
      * The {@link Scroller} responsible for flinging the selector.
      */
+    @UnsupportedAppUsage
     private final Scroller mFlingScroller;
 
     /**
@@ -402,6 +415,7 @@
     /**
      * @see ViewConfiguration#getScaledMaximumFlingVelocity()
      */
+    @UnsupportedAppUsage
     private int mMaximumFlingVelocity;
 
     /**
@@ -422,11 +436,13 @@
     /**
      * Divider for showing item to be selected while scrolling
      */
+    @UnsupportedAppUsage
     private final Drawable mSelectionDivider;
 
     /**
      * The height of the selection divider.
      */
+    @UnsupportedAppUsage
     private final int mSelectionDividerHeight;
 
     /**
@@ -1715,6 +1731,7 @@
      * Resets the selector indices and clear the cached string representation of
      * these indices.
      */
+    @UnsupportedAppUsage
     private void initializeSelectorWheelIndices() {
         mSelectorIndexToStringCache.clear();
         int[] selectorIndices = mSelectorIndices;
@@ -1766,6 +1783,7 @@
      *
      * @param increment True to increment, false to decrement.
      */
+     @UnsupportedAppUsage
      private void changeValueByOne(boolean increment) {
         if (mHasSelectorWheel) {
             hideSoftInput();
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index e4b2930..5c79d21 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -1,11 +1 @@
-per-file TextView.java = siyamed@google.com
-per-file TextView.java = nona@google.com
-per-file TextView.java = clarabayarri@google.com
-
-per-file EditText.java = siyamed@google.com
-per-file EditText.java = nona@google.com
-per-file EditText.java = clarabayarri@google.com
-
-per-file Editor.java = siyamed@google.com
-per-file Editor.java = nona@google.com
-per-file Editor.java = clarabayarri@google.com
+per-file TextView.java, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index 9938789..e7a96be 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.hardware.SensorManager;
 import android.util.Log;
@@ -32,8 +33,10 @@
     private int mMode;
 
     private final SplineOverScroller mScrollerX;
+    @UnsupportedAppUsage
     private final SplineOverScroller mScrollerY;
 
+    @UnsupportedAppUsage
     private Interpolator mInterpolator;
 
     private final boolean mFlywheel;
@@ -68,6 +71,7 @@
      * @param flywheel If true, successive fling motions will keep on increasing scroll speed.
      * @hide
      */
+    @UnsupportedAppUsage
     public OverScroller(Context context, Interpolator interpolator, boolean flywheel) {
         if (interpolator == null) {
             mInterpolator = new Scroller.ViscousFluidInterpolator();
@@ -116,6 +120,7 @@
         this(context, interpolator, flywheel);
     }
 
+    @UnsupportedAppUsage
     void setInterpolator(Interpolator interpolator) {
         if (interpolator == null) {
             mInterpolator = new Scroller.ViscousFluidInterpolator();
@@ -250,6 +255,7 @@
      *             to begin a new animation.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void extendDuration(int extend) {
         mScrollerX.extendDuration(extend);
         mScrollerY.extendDuration(extend);
@@ -530,6 +536,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isScrollingInDirection(float xvel, float yvel) {
         final int dx = mScrollerX.mFinal - mScrollerX.mStart;
         final int dy = mScrollerY.mFinal - mScrollerY.mStart;
@@ -551,6 +558,7 @@
         private int mVelocity;
 
         // Current velocity
+        @UnsupportedAppUsage
         private float mCurrVelocity;
 
         // Constant current deceleration
diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java
index 59bbc3b..d82e56c 100644
--- a/core/java/android/widget/PopupMenu.java
+++ b/core/java/android/widget/PopupMenu.java
@@ -18,6 +18,7 @@
 
 import android.annotation.MenuRes;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.view.Gravity;
 import android.view.Menu;
@@ -39,9 +40,11 @@
  * it.
  */
 public class PopupMenu {
+    @UnsupportedAppUsage
     private final Context mContext;
     private final MenuBuilder mMenu;
     private final View mAnchor;
+    @UnsupportedAppUsage
     private final MenuPopupHelper mPopup;
 
     private OnMenuItemClickListener mMenuItemClickListener;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 9553cf5..0da47fd 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -24,6 +24,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
@@ -141,7 +142,9 @@
     private final int[] mTmpAppLocation = new int[2];
     private final Rect mTempRect = new Rect();
 
+    @UnsupportedAppUsage
     private Context mContext;
+    @UnsupportedAppUsage
     private WindowManager mWindowManager;
 
     /**
@@ -150,17 +153,22 @@
      */
     private WeakReference<View> mParentRootView;
 
+    @UnsupportedAppUsage
     private boolean mIsShowing;
     private boolean mIsTransitioningToDismiss;
+    @UnsupportedAppUsage
     private boolean mIsDropdown;
 
     /** View that handles event dispatch and content transitions. */
+    @UnsupportedAppUsage
     private PopupDecorView mDecorView;
 
     /** View that holds the background and may animate during a transition. */
+    @UnsupportedAppUsage
     private View mBackgroundView;
 
     /** The contents of the popup. May be identical to the background view. */
+    @UnsupportedAppUsage
     private View mContentView;
 
     private boolean mFocusable;
@@ -171,39 +179,52 @@
     private boolean mOutsideTouchable = false;
     private boolean mClippingEnabled = true;
     private int mSplitTouchEnabled = -1;
+    @UnsupportedAppUsage
     private boolean mLayoutInScreen;
     private boolean mClipToScreen;
     private boolean mAllowScrollingAnchorParent = true;
     private boolean mLayoutInsetDecor = false;
+    @UnsupportedAppUsage
     private boolean mNotTouchModal;
     private boolean mAttachedInDecor = true;
     private boolean mAttachedInDecorSet = false;
 
+    @UnsupportedAppUsage
     private OnTouchListener mTouchInterceptor;
 
+    @UnsupportedAppUsage
     private int mWidthMode;
     private int mWidth = LayoutParams.WRAP_CONTENT;
+    @UnsupportedAppUsage
     private int mLastWidth;
+    @UnsupportedAppUsage
     private int mHeightMode;
     private int mHeight = LayoutParams.WRAP_CONTENT;
+    @UnsupportedAppUsage
     private int mLastHeight;
 
     private float mElevation;
 
     private Drawable mBackground;
+    @UnsupportedAppUsage
     private Drawable mAboveAnchorBackgroundDrawable;
+    @UnsupportedAppUsage
     private Drawable mBelowAnchorBackgroundDrawable;
 
     private Transition mEnterTransition;
     private Transition mExitTransition;
     private Rect mEpicenterBounds;
 
+    @UnsupportedAppUsage
     private boolean mAboveAnchor;
+    @UnsupportedAppUsage
     private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
 
+    @UnsupportedAppUsage
     private OnDismissListener mOnDismissListener;
     private boolean mIgnoreCheekPress = false;
 
+    @UnsupportedAppUsage
     private int mAnimationStyle = ANIMATION_STYLE_DEFAULT;
 
     private int mGravity = Gravity.NO_GRAVITY;
@@ -238,10 +259,12 @@
                 }
             };
 
+    @UnsupportedAppUsage
     private WeakReference<View> mAnchor;
     private WeakReference<View> mAnchorRoot;
     private boolean mIsAnchorRootAttached;
 
+    @UnsupportedAppUsage
     private final OnScrollChangedListener mOnScrollChangedListener = this::alignToAnchor;
 
     private final View.OnLayoutChangeListener mOnLayoutChangeListener =
@@ -250,6 +273,7 @@
     private int mAnchorXoff;
     private int mAnchorYoff;
     private int mAnchoredGravity;
+    @UnsupportedAppUsage
     private boolean mOverlapAnchor;
 
     private boolean mPopupViewInitialLayoutDirectionInherited;
@@ -466,6 +490,7 @@
      * @see #getTransitionEpicenter()
      * @hide
      */
+    @UnsupportedAppUsage
     public void setEpicenterBounds(Rect bounds) {
         mEpicenterBounds = bounds;
     }
@@ -845,6 +870,7 @@
      * @param enabled True to clip to the screen.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setClipToScreenEnabled(boolean enabled) {
         mClipToScreen = enabled;
     }
@@ -855,6 +881,7 @@
      *
      * @param enabled True to scroll the anchor's parent when more room is desired by the popup.
      */
+    @UnsupportedAppUsage
     void setAllowScrollingAnchorParent(boolean enabled) {
         mAllowScrollingAnchorParent = enabled;
     }
@@ -914,6 +941,7 @@
      * @param enabled true if the popup should always be positioned in screen coordinates
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLayoutInScreenEnabled(boolean enabled) {
         mLayoutInScreen = enabled;
     }
@@ -960,6 +988,7 @@
      *                the way that decor views behave for full-screen windows.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setLayoutInsetDecor(boolean enabled) {
         mLayoutInsetDecor = enabled;
     }
@@ -996,6 +1025,7 @@
      * other windows behind it.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setTouchModal(boolean touchModal) {
         mNotTouchModal = !touchModal;
     }
@@ -1181,6 +1211,7 @@
      * @hide Internal use only. Applications should use
      *       {@link #showAtLocation(View, int, int, int)} instead.
      */
+    @UnsupportedAppUsage
     public void showAtLocation(IBinder token, int gravity, int x, int y) {
         if (isShowing() || mContentView == null) {
             return;
@@ -1285,6 +1316,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     protected final void updateAboveAnchor(boolean aboveAnchor) {
         if (aboveAnchor != mAboveAnchor) {
             mAboveAnchor = aboveAnchor;
@@ -1328,6 +1360,7 @@
      *
      * @param p the layout parameters of the popup's content view
      */
+    @UnsupportedAppUsage
     private void preparePopup(WindowManager.LayoutParams p) {
         if (mContentView == null || mContext == null || mWindowManager == null) {
             throw new IllegalStateException("You must specify a valid content view by "
@@ -1421,6 +1454,7 @@
      *
      * @param p the layout parameters of the popup's content view
      */
+    @UnsupportedAppUsage
     private void invokePopup(WindowManager.LayoutParams p) {
         if (mContext != null) {
             p.packageName = mContext.getPackageName();
@@ -1464,6 +1498,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected final WindowManager.LayoutParams createPopupLayoutParams(IBinder token) {
         final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
 
@@ -1552,6 +1587,7 @@
         return curFlags;
     }
 
+    @UnsupportedAppUsage
     private int computeAnimationResource() {
         if (mAnimationStyle == ANIMATION_STYLE_DEFAULT) {
             if (mIsDropdown) {
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index e7c3a47..1fc72f5 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -20,6 +20,7 @@
 import android.annotation.InterpolatorRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
@@ -167,9 +168,12 @@
     /** Duration of smooth progress animations. */
     private static final int PROGRESS_ANIM_DURATION = 80;
 
+    @UnsupportedAppUsage
     int mMinWidth;
     int mMaxWidth;
+    @UnsupportedAppUsage
     int mMinHeight;
+    @UnsupportedAppUsage
     int mMaxHeight;
 
     private int mProgress;
@@ -180,8 +184,11 @@
     private boolean mMaxInitialized;
 
     private int mBehavior;
+    @UnsupportedAppUsage
     private int mDuration;
+    @UnsupportedAppUsage
     private boolean mIndeterminate;
+    @UnsupportedAppUsage
     private boolean mOnlyIndeterminate;
     private Transformation mTransformation;
     private AlphaAnimation mAnimation;
@@ -189,6 +196,7 @@
 
     private Drawable mIndeterminateDrawable;
     private Drawable mProgressDrawable;
+    @UnsupportedAppUsage
     private Drawable mCurrentDrawable;
     private ProgressTintInfo mProgressTintInfo;
 
@@ -206,6 +214,7 @@
     /** Value used to track progress animation, in the range [0...1]. */
     private float mVisualProgress;
 
+    @UnsupportedAppUsage
     boolean mMirrorForRtl = false;
 
     private boolean mAggregatedIsVisible;
@@ -424,6 +433,7 @@
      * Converts a drawable to a tiled version of itself. It will recursively
      * traverse layer and state list drawables.
      */
+    @UnsupportedAppUsage
     private Drawable tileify(Drawable drawable, boolean clip) {
         // TODO: This is a terrible idea that potentially destroys any drawable
         // that extends any of these classes. We *really* need to remove this.
@@ -1347,6 +1357,7 @@
         // Stub method.
     }
 
+    @UnsupportedAppUsage
     private synchronized void refreshProgress(int id, int progress, boolean fromUser,
             boolean animate) {
         if (mUiThreadId == Thread.currentThread().getId()) {
@@ -1401,6 +1412,7 @@
     }
 
     @android.view.RemotableViewMethod
+    @UnsupportedAppUsage
     synchronized boolean setProgressInternal(int progress, boolean fromUser, boolean animate) {
         if (mIndeterminate) {
             // Not applicable.
@@ -1599,6 +1611,7 @@
     /**
      * <p>Start the indeterminate progress animation.</p>
      */
+    @UnsupportedAppUsage
     void startAnimation() {
         if (getVisibility() != VISIBLE || getWindowVisibility() != VISIBLE) {
             return;
@@ -1638,6 +1651,7 @@
     /**
      * <p>Stop the indeterminate progress animation.</p>
      */
+    @UnsupportedAppUsage
     void stopAnimation() {
         mHasAnimation = false;
         if (mIndeterminateDrawable instanceof Animatable) {
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index 8f6b0d5..c1a217c 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.AsyncQueryHandler;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -46,6 +47,7 @@
     private Uri mContactUri;
     private String mContactEmail;
     private String mContactPhone;
+    @UnsupportedAppUsage
     private Drawable mOverlay;
     private QueryHandler mQueryHandler;
     private Drawable mDefaultAvatar;
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index c987147..327a5c1 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.IdRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -60,9 +61,11 @@
     // holds the checked id; the selection is empty by default
     private int mCheckedId = -1;
     // tracks children radio buttons checked state
+    @UnsupportedAppUsage
     private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
     // when true, mOnCheckedChangeListener discards events
     private boolean mProtectFromCheckedChange = false;
+    @UnsupportedAppUsage
     private OnCheckedChangeListener mOnCheckedChangeListener;
     private PassThroughHierarchyChangeListener mPassThroughListener;
 
diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java
index 70b70bc..d343d49 100644
--- a/core/java/android/widget/RatingBar.java
+++ b/core/java/android/widget/RatingBar.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.shapes.RectShape;
@@ -79,6 +80,7 @@
 
     private int mProgressOnStartTracking;
 
+    @UnsupportedAppUsage
     private OnRatingBarChangeListener mOnRatingBarChangeListener;
 
     public RatingBar(Context context, AttributeSet attrs, int defStyleAttr) {
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index bbdf15c..74051e2 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -19,6 +19,7 @@
 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
@@ -203,6 +204,7 @@
 
     private View mBaselineView = null;
 
+    @UnsupportedAppUsage
     private int mGravity = Gravity.START | Gravity.TOP;
     private final Rect mContentBounds = new Rect();
     private final Rect mSelfBounds = new Rect();
@@ -1247,7 +1249,14 @@
         private int[] mRules = new int[VERB_COUNT];
         private int[] mInitialRules = new int[VERB_COUNT];
 
-        private int mLeft, mTop, mRight, mBottom;
+        @UnsupportedAppUsage
+        private int mLeft;
+        @UnsupportedAppUsage
+        private int mTop;
+        @UnsupportedAppUsage
+        private int mRight;
+        @UnsupportedAppUsage
+        private int mBottom;
 
         /**
          * Whether this view had any relative rules modified following the most
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 22c840b..35ff6cc 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -16,12 +16,11 @@
 
 package android.widget;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
 import android.annotation.ColorInt;
 import android.annotation.DimenRes;
 import android.annotation.NonNull;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
 import android.app.Application;
@@ -159,22 +158,26 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public ApplicationInfo mApplication;
 
     /**
      * The resource ID of the layout file. (Added to the parcel)
      */
+    @UnsupportedAppUsage
     private final int mLayoutId;
 
     /**
      * An array of actions to perform on the view tree once it has been
      * inflated
      */
+    @UnsupportedAppUsage
     private ArrayList<Action> mActions;
 
     /**
      * Maps bitmaps to unique indicies to avoid Bitmap duplication.
      */
+    @UnsupportedAppUsage
     private BitmapCache mBitmapCache;
 
     /**
@@ -208,6 +211,7 @@
      * RemoteViews.
      */
     private RemoteViews mLandscape = null;
+    @UnsupportedAppUsage
     private RemoteViews mPortrait = null;
 
     /**
@@ -358,28 +362,12 @@
     /** @hide */
     public static class OnClickHandler {
 
-        private int mEnterAnimationId;
-
-        public boolean onClickHandler(View view, PendingIntent pendingIntent,
-                Intent fillInIntent) {
-            return onClickHandler(view, pendingIntent, fillInIntent, WINDOWING_MODE_UNDEFINED);
-        }
-
-        public boolean onClickHandler(View view, PendingIntent pendingIntent,
-                Intent fillInIntent, int windowingMode) {
+        @UnsupportedAppUsage
+        public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) {
             try {
                 // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
                 Context context = view.getContext();
-                ActivityOptions opts;
-                if (mEnterAnimationId != 0) {
-                    opts = ActivityOptions.makeCustomAnimation(context, mEnterAnimationId, 0);
-                } else {
-                    opts = ActivityOptions.makeBasic();
-                }
-
-                if (windowingMode != WINDOWING_MODE_UNDEFINED) {
-                    opts.setLaunchWindowingMode(windowingMode);
-                }
+                ActivityOptions opts = getActivityOptions(context);
                 context.startIntentSender(
                         pendingIntent.getIntentSender(), fillInIntent,
                         Intent.FLAG_ACTIVITY_NEW_TASK,
@@ -395,8 +383,26 @@
             return true;
         }
 
-        public void setEnterAnimationId(int enterAnimationId) {
-            mEnterAnimationId = enterAnimationId;
+        /** @hide */
+        protected ActivityOptions getActivityOptions(Context context) {
+            if (context.getResources().getBoolean(
+                    com.android.internal.R.bool.config_overrideRemoteViewsActivityTransition)) {
+                TypedArray windowStyle = context.getTheme().obtainStyledAttributes(
+                        com.android.internal.R.styleable.Window);
+                int windowAnimations = windowStyle.getResourceId(
+                        com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
+                TypedArray windowAnimationStyle = context.obtainStyledAttributes(
+                        windowAnimations, com.android.internal.R.styleable.WindowAnimation);
+                int enterAnimationId = windowAnimationStyle.getResourceId(com.android.internal.R
+                        .styleable.WindowAnimation_activityOpenRemoteViewsEnterAnimation, 0);
+                windowStyle.recycle();
+                windowAnimationStyle.recycle();
+
+                if (enterAnimationId != 0) {
+                    return ActivityOptions.makeCustomAnimation(context, enterAnimationId, 0);
+                }
+            }
+            return ActivityOptions.makeBasic();
         }
     }
 
@@ -422,6 +428,7 @@
             // Do nothing
         }
 
+        @UnsupportedAppUsage
         public int mergeBehavior() {
             return MERGE_REPLACE;
         }
@@ -457,6 +464,7 @@
             // Nothing to visit by default
         }
 
+        @UnsupportedAppUsage
         int viewId;
     }
 
@@ -489,6 +497,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void mergeRemoteViews(RemoteViews newRv) {
         if (newRv == null) return;
         // We first copy the new RemoteViews, as the process of merging modifies the way the actions
@@ -764,6 +773,7 @@
             return SET_PENDING_INTENT_TEMPLATE_TAG;
         }
 
+        @UnsupportedAppUsage
         PendingIntent pendingIntentTemplate;
     }
 
@@ -963,6 +973,7 @@
             return SET_ON_CLICK_PENDING_INTENT_TAG;
         }
 
+        @UnsupportedAppUsage
         PendingIntent pendingIntent;
     }
 
@@ -1154,6 +1165,7 @@
 
     private static class BitmapCache {
 
+        @UnsupportedAppUsage
         ArrayList<Bitmap> mBitmaps;
         int mBitmapMemory = -1;
 
@@ -1205,7 +1217,9 @@
 
     private class BitmapReflectionAction extends Action {
         int bitmapId;
+        @UnsupportedAppUsage
         Bitmap bitmap;
+        @UnsupportedAppUsage
         String methodName;
 
         BitmapReflectionAction(int viewId, String methodName, Bitmap bitmap) {
@@ -1271,8 +1285,10 @@
         static final int COLOR_STATE_LIST = 15;
         static final int ICON = 16;
 
+        @UnsupportedAppUsage
         String methodName;
         int type;
+        @UnsupportedAppUsage
         Object value;
 
         ReflectionAction(int viewId, String methodName, int type, Object value) {
@@ -1565,6 +1581,7 @@
      * ViewGroup methods that are related to adding Views.
      */
     private class ViewGroupActionAdd extends Action {
+        @UnsupportedAppUsage
         private RemoteViews mNestedViews;
         private int mIndex;
 
@@ -2421,6 +2438,7 @@
      * setting on click extras and setting on click pending intents. The former is enabled,
      * and the latter disabled when this flag is true.
      */
+    @UnsupportedAppUsage
     void setIsWidgetCollectionChild(boolean isWidgetCollectionChild) {
         mIsWidgetCollectionChild = isWidgetCollectionChild;
     }
@@ -2447,6 +2465,7 @@
      * Returns an estimate of the bitmap heap memory usage for this RemoteViews.
      */
     /** @hide */
+    @UnsupportedAppUsage
     public int estimateMemoryUsage() {
         return mBitmapCache.getBitmapMemory();
     }
@@ -2494,6 +2513,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void addView(int viewId, RemoteViews nestedView, int index) {
         addAction(new ViewGroupActionAdd(viewId, nestedView, index));
     }
@@ -2941,6 +2961,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRemoteAdapter(int viewId, ArrayList<RemoteViews> list, int viewTypeCount) {
         addAction(new SetRemoteViewsAdapterList(viewId, list, viewTypeCount));
     }
@@ -3302,8 +3323,6 @@
         RemoteViews rvToApply = getRemoteViewsToApply(context);
 
         View result = inflateView(context, rvToApply, parent);
-        loadTransitionOverride(context, handler);
-
         rvToApply.performApply(result, parent, handler);
 
         return result;
@@ -3333,24 +3352,6 @@
         return v;
     }
 
-    private static void loadTransitionOverride(Context context,
-            RemoteViews.OnClickHandler handler) {
-        if (handler != null && context.getResources().getBoolean(
-                com.android.internal.R.bool.config_overrideRemoteViewsActivityTransition)) {
-            TypedArray windowStyle = context.getTheme().obtainStyledAttributes(
-                    com.android.internal.R.styleable.Window);
-            int windowAnimations = windowStyle.getResourceId(
-                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
-            TypedArray windowAnimationStyle = context.obtainStyledAttributes(
-                    windowAnimations, com.android.internal.R.styleable.WindowAnimation);
-            handler.setEnterAnimationId(windowAnimationStyle.getResourceId(
-                    com.android.internal.R.styleable.
-                            WindowAnimation_activityOpenRemoteViewsEnterAnimation, 0));
-            windowStyle.recycle();
-            windowAnimationStyle.recycle();
-        }
-    }
-
     /**
      * Implement this interface to receive a callback when
      * {@link #applyAsync} or {@link #reapplyAsync} is finished.
@@ -3423,7 +3424,6 @@
             mHandler = handler;
 
             mResult = result;
-            loadTransitionOverride(context, handler);
         }
 
         @Override
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index e5ae0ca..d17c7c5 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.app.IServiceConnection;
 import android.appwidget.AppWidgetHostView;
@@ -99,6 +100,7 @@
     private final Executor mAsyncViewLoadExecutor;
 
     private OnClickHandler mRemoteViewsOnClickHandler;
+    @UnsupportedAppUsage
     private final FixedSizeRemoteViewsCache mCache;
     private int mVisibleWindowLowerBound;
     private int mVisibleWindowUpperBound;
@@ -107,6 +109,7 @@
     // loaded.
     private RemoteViewsFrameLayoutRefSet mRequestedViews;
 
+    @UnsupportedAppUsage
     private final HandlerThread mWorkerThread;
     // items may be interrupted within the normally processed queues
     private final Handler mMainHandler;
@@ -869,14 +872,17 @@
         }
     }
 
+    @UnsupportedAppUsage
     public boolean isDataReady() {
         return mDataReady;
     }
 
+    @UnsupportedAppUsage
     public void setRemoteViewsOnClickHandler(OnClickHandler handler) {
         mRemoteViewsOnClickHandler = handler;
     }
 
+    @UnsupportedAppUsage
     public void saveRemoteViewsCache() {
         final RemoteViewsCacheKey key = new RemoteViewsCacheKey(
                 new Intent.FilterComparison(mIntent), mAppWidgetId);
@@ -1021,6 +1027,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public Intent getRemoteViewsServiceIntent() {
         return mIntent;
     }
@@ -1067,6 +1074,7 @@
      * views are currently being displayed. This allows for certain optimizations and preloading
      * which  wouldn't otherwise be possible.
      */
+    @UnsupportedAppUsage
     public void setVisibleRangeHint(int lowerBound, int upperBound) {
         mVisibleWindowLowerBound = lowerBound;
         mVisibleWindowUpperBound = upperBound;
diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java
index 2ae38c9..e91f87e 100644
--- a/core/java/android/widget/ScrollBarDrawable.java
+++ b/core/java/android/widget/ScrollBarDrawable.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
@@ -35,6 +36,7 @@
 public class ScrollBarDrawable extends Drawable implements Drawable.Callback {
     private Drawable mVerticalTrack;
     private Drawable mHorizontalTrack;
+    @UnsupportedAppUsage
     private Drawable mVerticalThumb;
     private Drawable mHorizontalThumb;
 
@@ -224,6 +226,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void setVerticalThumbDrawable(Drawable thumb) {
         if (mVerticalThumb != null) {
             mVerticalThumb.setCallback(null);
@@ -242,6 +245,7 @@
         mVerticalTrack = track;
     }
 
+    @UnsupportedAppUsage
     public void setHorizontalThumbDrawable(Drawable thumb) {
         if (mHorizontalThumb != null) {
             mHorizontalThumb.setCallback(null);
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 97d32f1..4658d73 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -81,16 +82,21 @@
 
     private static final String TAG = "ScrollView";
 
+    @UnsupportedAppUsage
     private long mLastScroll;
 
     private final Rect mTempRect = new Rect();
+    @UnsupportedAppUsage
     private OverScroller mScroller;
+    @UnsupportedAppUsage
     private EdgeEffect mEdgeGlowTop;
+    @UnsupportedAppUsage
     private EdgeEffect mEdgeGlowBottom;
 
     /**
      * Position of the last motion event.
      */
+    @UnsupportedAppUsage
     private int mLastMotionY;
 
     /**
@@ -104,6 +110,7 @@
      * layout is dirty. This prevents the scroll from being wrong if the child has not been
      * laid out before requesting focus.
      */
+    @UnsupportedAppUsage
     private View mChildToScrollTo = null;
 
     /**
@@ -111,11 +118,13 @@
      * not the same as 'is being flinged', which can be checked by
      * mScroller.isFinished() (flinging begins when the user lifts his finger).
      */
+    @UnsupportedAppUsage
     private boolean mIsBeingDragged = false;
 
     /**
      * Determines speed during touch scrolling
      */
+    @UnsupportedAppUsage
     private VelocityTracker mVelocityTracker;
 
     /**
@@ -131,10 +140,13 @@
     private boolean mSmoothScrollingEnabled = true;
 
     private int mTouchSlop;
+    @UnsupportedAppUsage
     private int mMinimumVelocity;
     private int mMaximumVelocity;
 
+    @UnsupportedAppUsage
     private int mOverscrollDistance;
+    @UnsupportedAppUsage
     private int mOverflingDistance;
 
     private float mVerticalScrollFactor;
@@ -159,6 +171,7 @@
      * These are no-ops on user builds.
      */
     private StrictMode.Span mScrollStrictSpan = null;  // aka "drag"
+    @UnsupportedAppUsage
     private StrictMode.Span mFlingStrictSpan = null;
 
     /**
@@ -294,6 +307,7 @@
     /**
      * @return Returns true this ScrollView can be scrolled
      */
+    @UnsupportedAppUsage
     private boolean canScroll() {
         View child = getChildAt(0);
         if (child != null) {
@@ -1644,6 +1658,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void endDrag() {
         mIsBeingDragged = false;
 
diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java
index 357c9c3..229eaf0 100644
--- a/core/java/android/widget/Scroller.java
+++ b/core/java/android/widget/Scroller.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.hardware.SensorManager;
 import android.os.Build;
@@ -60,6 +61,7 @@
  * }</pre>
  */
 public class Scroller  {
+    @UnsupportedAppUsage
     private final Interpolator mInterpolator;
 
     private int mMode;
@@ -77,6 +79,7 @@
     private int mCurrX;
     private int mCurrY;
     private long mStartTime;
+    @UnsupportedAppUsage
     private int mDuration;
     private float mDurationReciprocal;
     private float mDeltaX;
@@ -94,7 +97,9 @@
     private static final int SCROLL_MODE = 0;
     private static final int FLING_MODE = 1;
 
+    @UnsupportedAppUsage
     private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9));
+    @UnsupportedAppUsage
     private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1)
     private static final float START_TENSION = 0.5f;
     private static final float END_TENSION = 1.0f;
@@ -105,10 +110,12 @@
     private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1];
     private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1];
 
+    @UnsupportedAppUsage
     private float mDeceleration;
     private final float mPpi;
 
     // A context-specific coefficient adjusted to physical values.
+    @UnsupportedAppUsage
     private float mPhysicalCoeff;
 
     static {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 225497b..5b5950d 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -19,6 +19,7 @@
 import static android.widget.SuggestionsAdapter.getColumnString;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
@@ -105,13 +106,20 @@
      */
     private static final String IME_OPTION_NO_MICROPHONE = "nm";
 
+    @UnsupportedAppUsage
     private final SearchAutoComplete mSearchSrcTextView;
+    @UnsupportedAppUsage
     private final View mSearchEditFrame;
+    @UnsupportedAppUsage
     private final View mSearchPlate;
+    @UnsupportedAppUsage
     private final View mSubmitArea;
+    @UnsupportedAppUsage
     private final ImageView mSearchButton;
     private final ImageView mGoButton;
+    @UnsupportedAppUsage
     private final ImageView mCloseButton;
+    @UnsupportedAppUsage
     private final ImageView mVoiceButton;
     private final View mDropDownAnchor;
 
@@ -125,6 +133,7 @@
     private final ImageView mCollapsedIcon;
 
     /** Drawable used as an EditText hint. */
+    @UnsupportedAppUsage
     private final Drawable mSearchHintIcon;
 
     // Resources used by SuggestionsAdapter to display suggestions.
@@ -137,24 +146,33 @@
 
     private final CharSequence mDefaultQueryHint;
 
+    @UnsupportedAppUsage
     private OnQueryTextListener mOnQueryChangeListener;
     private OnCloseListener mOnCloseListener;
     private OnFocusChangeListener mOnQueryTextFocusChangeListener;
     private OnSuggestionListener mOnSuggestionListener;
     private OnClickListener mOnSearchClickListener;
 
+    @UnsupportedAppUsage
     private boolean mIconifiedByDefault;
+    @UnsupportedAppUsage
     private boolean mIconified;
+    @UnsupportedAppUsage
     private CursorAdapter mSuggestionsAdapter;
     private boolean mSubmitButtonEnabled;
     private CharSequence mQueryHint;
     private boolean mQueryRefinement;
+    @UnsupportedAppUsage
     private boolean mClearingFocus;
     private int mMaxWidth;
+    @UnsupportedAppUsage
     private boolean mVoiceButtonEnabled;
     private CharSequence mOldQueryText;
+    @UnsupportedAppUsage
     private CharSequence mUserQuery;
+    @UnsupportedAppUsage
     private boolean mExpandedInActionView;
+    @UnsupportedAppUsage
     private int mCollapsedImeOptions;
 
     private SearchableInfo mSearchable;
@@ -853,6 +871,7 @@
                 .getDimensionPixelSize(R.dimen.search_view_preferred_height);
     }
 
+    @UnsupportedAppUsage
     private void updateViewsVisibility(final boolean collapsed) {
         mIconified = collapsed;
         // Visibility of views that are visible when collapsed
@@ -898,6 +917,7 @@
         return (mSubmitButtonEnabled || mVoiceButtonEnabled) && !isIconified();
     }
 
+    @UnsupportedAppUsage
     private void updateSubmitButton(boolean hasText) {
         int visibility = GONE;
         if (mSubmitButtonEnabled && isSubmitAreaEnabled() && hasFocus()
@@ -907,6 +927,7 @@
         mGoButton.setVisibility(visibility);
     }
 
+    @UnsupportedAppUsage
     private void updateSubmitArea() {
         int visibility = GONE;
         if (isSubmitAreaEnabled()
@@ -962,6 +983,7 @@
         setQuery(queryText);
     }
 
+    @UnsupportedAppUsage
     private final OnClickListener mOnClickListener = new OnClickListener() {
 
         public void onClick(View v) {
@@ -1270,6 +1292,7 @@
         mSearchSrcTextView.dismissDropDown();
     }
 
+    @UnsupportedAppUsage
     private void onCloseClicked() {
         CharSequence text = mSearchSrcTextView.getText();
         if (TextUtils.isEmpty(text)) {
@@ -1467,6 +1490,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
 
         /**
@@ -1566,6 +1590,7 @@
     /**
      * Sets the text in the query box, without updating the suggestions.
      */
+    @UnsupportedAppUsage
     private void setQuery(CharSequence query) {
         mSearchSrcTextView.setText(query, true);
         // Move the cursor to the end
@@ -1892,6 +1917,7 @@
             mThreshold = getThreshold();
         }
 
+        @UnsupportedAppUsage
         public SearchAutoComplete(Context context, AttributeSet attrs) {
             super(context, attrs);
             mThreshold = getThreshold();
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index f9aced0..e8cf1e8 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -69,6 +70,7 @@
         void onStopTrackingTouch(SeekBar seekBar);
     }
 
+    @UnsupportedAppUsage
     private OnSeekBarChangeListener mOnSeekBarChangeListener;
 
     public SeekBar(Context context) {
@@ -88,6 +90,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     void onProgressRefresh(float scale, boolean fromUser, int progress) {
         super.onProgressRefresh(scale, fromUser, progress);
 
diff --git a/core/java/android/widget/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java
index 9190117..a27354d 100644
--- a/core/java/android/widget/SimpleAdapter.java
+++ b/core/java/android/widget/SimpleAdapter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IdRes;
 import android.annotation.LayoutRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.Uri;
@@ -58,6 +59,7 @@
     private String[] mFrom;
     private ViewBinder mViewBinder;
 
+    @UnsupportedAppUsage
     private List<? extends Map<String, ?>> mData;
 
     private int mResource;
diff --git a/core/java/android/widget/SimpleCursorAdapter.java b/core/java/android/widget/SimpleCursorAdapter.java
index 3dd0a95..b670e6c 100644
--- a/core/java/android/widget/SimpleCursorAdapter.java
+++ b/core/java/android/widget/SimpleCursorAdapter.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
@@ -51,12 +52,14 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected int[] mFrom;
     /**
      * A list of View ids representing the views to which the data must be bound.
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected int[] mTo;
 
     private int mStringConversionColumn = -1;
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
index 9f48397..8011c3a 100644
--- a/core/java/android/widget/SlidingDrawer.java
+++ b/core/java/android/widget/SlidingDrawer.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.R;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -104,14 +105,17 @@
 
     private final Rect mFrame = new Rect();
     private final Rect mInvalidate = new Rect();
+    @UnsupportedAppUsage
     private boolean mTracking;
     private boolean mLocked;
 
+    @UnsupportedAppUsage
     private VelocityTracker mVelocityTracker;
 
     private boolean mVertical;
     private boolean mExpanded;
     private int mBottomOffset;
+    @UnsupportedAppUsage
     private int mTopOffset;
     private int mHandleHeight;
     private int mHandleWidth;
@@ -125,6 +129,7 @@
     private float mAnimationPosition;
     private long mAnimationLastTime;
     private long mCurrentAnimationTime;
+    @UnsupportedAppUsage
     private int mTouchDelta;
     private boolean mAnimating;
     private boolean mAllowSingleTap;
@@ -555,6 +560,7 @@
         stopTracking(notifyScrollListener);
     }
 
+    @UnsupportedAppUsage
     private void prepareTracking(int position) {
         mTracking = true;
         mVelocityTracker = VelocityTracker.obtain();
@@ -646,6 +652,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void prepareContent() {
         if (mAnimating) {
             return;
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index ddf0e74..1705ba8 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -19,6 +19,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.Widget;
 import android.app.AlertDialog;
 import android.content.Context;
@@ -93,11 +94,13 @@
     private final Context mPopupContext;
 
     /** Forwarding listener used to implement drag-to-open. */
+    @UnsupportedAppUsage
     private ForwardingListener mForwardingListener;
 
     /** Temporary holder for setAdapter() calls from the super constructor. */
     private SpinnerAdapter mTempAdapter;
 
+    @UnsupportedAppUsage
     private SpinnerPopup mPopup;
     int mDropDownWidth;
 
@@ -584,6 +587,7 @@
     /**
      * @hide internal use only
      */
+    @UnsupportedAppUsage
     public void setOnItemClickListenerInt(OnItemClickListener l) {
         super.setOnItemClickListener(l);
     }
@@ -1069,6 +1073,7 @@
         /**
          * @return true if the popup is showing, false otherwise.
          */
+        @UnsupportedAppUsage
         public boolean isShowing();
 
         /**
@@ -1099,6 +1104,7 @@
             }
         }
 
+        @UnsupportedAppUsage
         public boolean isShowing() {
             return mPopup != null ? mPopup.isShowing() : false;
         }
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 604575f..8bfc151 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -93,12 +94,14 @@
     private static final int SERIF = 2;
     private static final int MONOSPACE = 3;
 
+    @UnsupportedAppUsage
     private Drawable mThumbDrawable;
     private ColorStateList mThumbTintList = null;
     private PorterDuff.Mode mThumbTintMode = null;
     private boolean mHasThumbTint = false;
     private boolean mHasThumbTintMode = false;
 
+    @UnsupportedAppUsage
     private Drawable mTrackDrawable;
     private ColorStateList mTrackTintList = null;
     private PorterDuff.Mode mTrackTintMode = null;
@@ -106,6 +109,7 @@
     private boolean mHasTrackTintMode = false;
 
     private int mThumbTextPadding;
+    @UnsupportedAppUsage
     private int mSwitchMinWidth;
     private int mSwitchPadding;
     private boolean mSplitTrack;
@@ -127,18 +131,21 @@
      * Width required to draw the switch track and thumb. Includes padding and
      * optical bounds for both the track and thumb.
      */
+    @UnsupportedAppUsage
     private int mSwitchWidth;
 
     /**
      * Height required to draw the switch track and thumb. Includes padding and
      * optical bounds for both the track and thumb.
      */
+    @UnsupportedAppUsage
     private int mSwitchHeight;
 
     /**
      * Width of the thumb's content region. Does not include padding or
      * optical bounds.
      */
+    @UnsupportedAppUsage
     private int mThumbWidth;
 
     /** Left bound for drawing the switch track and thumb. */
@@ -155,7 +162,9 @@
 
     private TextPaint mTextPaint;
     private ColorStateList mTextColors;
+    @UnsupportedAppUsage
     private Layout mOnLayout;
+    @UnsupportedAppUsage
     private Layout mOffLayout;
     private TransformationMethod2 mSwitchTransformationMethod;
     private ObjectAnimator mPositionAnimator;
@@ -1050,6 +1059,7 @@
         mPositionAnimator.start();
     }
 
+    @UnsupportedAppUsage
     private void cancelPositionAnimator() {
         if (mPositionAnimator != null) {
             mPositionAnimator.cancel();
@@ -1065,6 +1075,7 @@
      *
      * @param position new position between [0,1]
      */
+    @UnsupportedAppUsage
     private void setThumbPosition(float position) {
         mThumbPosition = position;
         invalidate();
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 8696d0d..b1fcbc3 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.LocalActivityManager;
 import android.content.Context;
 import android.content.Intent;
@@ -54,11 +55,13 @@
     private static final int TABWIDGET_LOCATION_BOTTOM = 3;
     private TabWidget mTabWidget;
     private FrameLayout mTabContent;
+    @UnsupportedAppUsage
     private List<TabSpec> mTabSpecs = new ArrayList<TabSpec>(2);
     /**
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @UnsupportedAppUsage
     protected int mCurrentTab = -1;
     private View mCurrentView = null;
     /**
@@ -66,6 +69,7 @@
      * {@hide}
      */
     protected LocalActivityManager mLocalActivityManager = null;
+    @UnsupportedAppUsage
     private OnTabChangeListener mOnTabChangeListener;
     private OnKeyListener mTabKeyListener;
 
@@ -504,7 +508,9 @@
 
         private final @NonNull String mTag;
 
+        @UnsupportedAppUsage
         private IndicatorStrategy mIndicatorStrategy;
+        @UnsupportedAppUsage
         private ContentStrategy mContentStrategy;
 
         /**
@@ -767,6 +773,7 @@
             mIntent = intent;
         }
 
+        @UnsupportedAppUsage
         public View getContentView() {
             if (mLocalActivityManager == null) {
                 throw new IllegalStateException("Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?");
@@ -796,6 +803,7 @@
             return mLaunchedView;
         }
 
+        @UnsupportedAppUsage
         public void tabClosed() {
             if (mLaunchedView != null) {
                 mLaunchedView.setVisibility(View.GONE);
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index f8b6837..a90741b4 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -18,6 +18,7 @@
 
 import android.annotation.DrawableRes;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -59,6 +60,7 @@
     private OnTabSelectionChanged mSelectionChangedListener;
 
     // This value will be set to 0 as soon as the first tab is added to TabHost.
+    @UnsupportedAppUsage
     private int mSelectedTab = -1;
 
     @Nullable
@@ -67,6 +69,7 @@
     @Nullable
     private Drawable mRightStrip;
 
+    @UnsupportedAppUsage
     private boolean mDrawBottomStrips = true;
     private boolean mStripMoved;
 
@@ -541,6 +544,7 @@
      * Provides a way for {@link TabHost} to be notified that the user clicked
      * on a tab indicator.
      */
+    @UnsupportedAppUsage
     void setTabSelectionListener(OnTabSelectionChanged listener) {
         mSelectionChangedListener = listener;
     }
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index d8a9cca..4865808 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -485,6 +486,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public CharSequence getFormat() {
         return mFormat;
     }
@@ -623,6 +625,7 @@
     /**
      * Update the displayed time if this view and its ancestors and window is visible
      */
+    @UnsupportedAppUsage
     private void onTimeChanged() {
         // mShouldRunTicker always equals the last value passed into onVisibilityAggregated
         if (mShouldRunTicker) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9a60065..31b1d99 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -34,6 +34,7 @@
 import android.annotation.Size;
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.XmlRes;
 import android.app.Activity;
 import android.app.PendingIntent;
@@ -365,6 +366,7 @@
      */
     private static final int MARQUEE_FADE_SWITCH_SHOW_FADE = 2;
 
+    @UnsupportedAppUsage
     private static final int LINES = 1;
     private static final int EMS = LINES;
     private static final int PIXELS = 2;
@@ -414,14 +416,23 @@
     private ColorStateList mHintTextColor;
     private ColorStateList mLinkTextColor;
     @ViewDebug.ExportedProperty(category = "text")
+    @UnsupportedAppUsage
     private int mCurTextColor;
+    @UnsupportedAppUsage
     private int mCurHintTextColor;
     private boolean mFreezesText;
 
+    @UnsupportedAppUsage
     private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
+    @UnsupportedAppUsage
     private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
 
-    private float mShadowRadius, mShadowDx, mShadowDy;
+    @UnsupportedAppUsage
+    private float mShadowRadius;
+    @UnsupportedAppUsage
+    private float mShadowDx;
+    @UnsupportedAppUsage
+    private float mShadowDy;
     private int mShadowColor;
 
     private boolean mPreDrawRegistered;
@@ -622,11 +633,15 @@
         }
     }
 
+    @UnsupportedAppUsage
     Drawables mDrawables;
 
+    @UnsupportedAppUsage
     private CharWrapper mCharWrapper;
 
+    @UnsupportedAppUsage
     private Marquee mMarquee;
+    @UnsupportedAppUsage
     private boolean mRestartMarquee;
 
     private int mMarqueeRepeatLimit = 3;
@@ -638,37 +653,49 @@
      * extensively in the same layout. This mode indicates how the marquee
      * is currently being shown, if applicable. (mEllipsize will == MARQUEE)
      */
+    @UnsupportedAppUsage
     private int mMarqueeFadeMode = MARQUEE_FADE_NORMAL;
 
     /**
      * When mMarqueeFadeMode is not MARQUEE_FADE_NORMAL, this stores
      * the layout that should be used when the mode switches.
      */
+    @UnsupportedAppUsage
     private Layout mSavedMarqueeModeLayout;
 
     // Do not update following mText/mSpannable/mPrecomputed except for setTextInternal()
     @ViewDebug.ExportedProperty(category = "text")
+    @UnsupportedAppUsage
     private @Nullable CharSequence mText;
     private @Nullable Spannable mSpannable;
     private @Nullable PrecomputedText mPrecomputed;
 
+    @UnsupportedAppUsage
     private CharSequence mTransformed;
+    @UnsupportedAppUsage
     private BufferType mBufferType = BufferType.NORMAL;
 
     private CharSequence mHint;
+    @UnsupportedAppUsage
     private Layout mHintLayout;
 
     private MovementMethod mMovement;
 
     private TransformationMethod mTransformation;
+    @UnsupportedAppUsage
     private boolean mAllowTransformationLengthChange;
+    @UnsupportedAppUsage
     private ChangeWatcher mChangeWatcher;
 
+    @UnsupportedAppUsage
     private ArrayList<TextWatcher> mListeners;
 
     // display attributes
+    @UnsupportedAppUsage
     private final TextPaint mTextPaint;
+    @UnsupportedAppUsage
     private boolean mUserSetTextScaleX;
+    @UnsupportedAppUsage
     private Layout mLayout;
     private boolean mLocalesChanged = false;
 
@@ -680,34 +707,51 @@
     /* package */ boolean mUseFallbackLineSpacing;
 
     @ViewDebug.ExportedProperty(category = "text")
+    @UnsupportedAppUsage
     private int mGravity = Gravity.TOP | Gravity.START;
+    @UnsupportedAppUsage
     private boolean mHorizontallyScrolling;
 
     private int mAutoLinkMask;
     private boolean mLinksClickable = true;
 
+    @UnsupportedAppUsage
     private float mSpacingMult = 1.0f;
+    @UnsupportedAppUsage
     private float mSpacingAdd = 0.0f;
 
     private int mBreakStrategy;
     private int mHyphenationFrequency;
     private int mJustificationMode;
 
+    @UnsupportedAppUsage
     private int mMaximum = Integer.MAX_VALUE;
+    @UnsupportedAppUsage
     private int mMaxMode = LINES;
+    @UnsupportedAppUsage
     private int mMinimum = 0;
+    @UnsupportedAppUsage
     private int mMinMode = LINES;
 
+    @UnsupportedAppUsage
     private int mOldMaximum = mMaximum;
+    @UnsupportedAppUsage
     private int mOldMaxMode = mMaxMode;
 
+    @UnsupportedAppUsage
     private int mMaxWidth = Integer.MAX_VALUE;
+    @UnsupportedAppUsage
     private int mMaxWidthMode = PIXELS;
+    @UnsupportedAppUsage
     private int mMinWidth = 0;
+    @UnsupportedAppUsage
     private int mMinWidthMode = PIXELS;
 
+    @UnsupportedAppUsage
     private boolean mSingleLine;
+    @UnsupportedAppUsage
     private int mDesiredHeightAtMeasure = -1;
+    @UnsupportedAppUsage
     private boolean mIncludePad = true;
     private int mDeferScroll = -1;
 
@@ -717,9 +761,16 @@
     private Scroller mScroller;
     private TextPaint mTempTextPaint;
 
-    private BoringLayout.Metrics mBoring, mHintBoring;
-    private BoringLayout mSavedLayout, mSavedHintLayout;
+    @UnsupportedAppUsage
+    private BoringLayout.Metrics mBoring;
+    @UnsupportedAppUsage
+    private BoringLayout.Metrics mHintBoring;
+    @UnsupportedAppUsage
+    private BoringLayout mSavedLayout;
+    @UnsupportedAppUsage
+    private BoringLayout mSavedHintLayout;
 
+    @UnsupportedAppUsage
     private TextDirectionHeuristic mTextDir;
 
     private InputFilter[] mFilters = NO_FILTERS;
@@ -728,21 +779,28 @@
 
     // It is possible to have a selection even when mEditor is null (programmatically set, like when
     // a link is pressed). These highlight-related fields do not go in mEditor.
+    @UnsupportedAppUsage
     int mHighlightColor = 0x6633B5E5;
     private Path mHighlightPath;
+    @UnsupportedAppUsage
     private final Paint mHighlightPaint;
+    @UnsupportedAppUsage
     private boolean mHighlightPathBogus = true;
 
     // Although these fields are specific to editable text, they are not added to Editor because
     // they are defined by the TextView's style and are theme-dependent.
+    @UnsupportedAppUsage
     int mCursorDrawableRes;
     // These six fields, could be moved to Editor, since we know their default values and we
     // could condition the creation of the Editor to a non standard value. This is however
     // brittle since the hardcoded values here (such as
     // com.android.internal.R.drawable.text_select_handle_left) would have to be updated if the
     // default style is modified.
+    @UnsupportedAppUsage
     int mTextSelectHandleLeftRes;
+    @UnsupportedAppUsage
     int mTextSelectHandleRightRes;
+    @UnsupportedAppUsage
     int mTextSelectHandleRes;
     int mTextEditSuggestionItemLayout;
     int mTextEditSuggestionContainerLayout;
@@ -752,6 +810,7 @@
      * {@link EditText} specific data, created on demand when one of the Editor fields is used.
      * See {@link #createEditorIfNeeded()}.
      */
+    @UnsupportedAppUsage
     private Editor mEditor;
 
     private static final int DEVICE_PROVISIONED_UNKNOWN = 0;
@@ -2231,6 +2290,7 @@
      * @return the {@link android.text.Layout} that is currently being used to
      * display the hint text. This can be null.
      */
+    @UnsupportedAppUsage
     final Layout getHintLayout() {
         return mHintLayout;
     }
@@ -3451,7 +3511,7 @@
         ColorStateList mTextColor = null;
         ColorStateList mTextColorHint = null;
         ColorStateList mTextColorLink = null;
-        int mTextSize = 0;
+        int mTextSize = -1;
         String mFontFamily = null;
         Typeface mFontTypeface = null;
         boolean mFontFamilyExplicit = false;
@@ -3662,7 +3722,7 @@
             setHighlightColor(attributes.mTextColorHighlight);
         }
 
-        if (attributes.mTextSize != 0) {
+        if (attributes.mTextSize != -1) {
             setRawTextSize(attributes.mTextSize, true /* shouldRequestLayout */);
         }
 
@@ -3880,6 +3940,7 @@
                 shouldRequestLayout);
     }
 
+    @UnsupportedAppUsage
     private void setRawTextSize(float size, boolean shouldRequestLayout) {
         if (size != mTextPaint.getTextSize()) {
             mTextPaint.setTextSize(size);
@@ -4106,9 +4167,16 @@
      * TextView is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}, and the default value for
      * EditText is {@link Layout#BREAK_STRATEGY_SIMPLE}, the latter to avoid the
      * text "dancing" when being edited.
+     * <p/>
+     * Enabling hyphenation with either using {@link Layout#HYPHENATION_FREQUENCY_NORMAL} or
+     * {@link Layout#HYPHENATION_FREQUENCY_FULL} while line breaking is set to one of
+     * {@link Layout#BREAK_STRATEGY_BALANCED}, {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}
+     * improves the structure of text layout however has performance impact and requires more time
+     * to do the text layout.
      *
      * @attr ref android.R.styleable#TextView_breakStrategy
      * @see #getBreakStrategy()
+     * @see #setHyphenationFrequency(int)
      */
     public void setBreakStrategy(@Layout.BreakStrategy int breakStrategy) {
         mBreakStrategy = breakStrategy;
@@ -4134,12 +4202,26 @@
     /**
      * Sets the frequency of automatic hyphenation to use when determining word breaks.
      * The default value for both TextView and {@link EditText} is
-     * {@link Layout#HYPHENATION_FREQUENCY_NORMAL}.
-     * Note that the default hyphenation frequency value is set from the theme.
+     * {@link Layout#HYPHENATION_FREQUENCY_NONE}. Note that the default hyphenation frequency value
+     * is set from the theme.
+     * <p/>
+     * Enabling hyphenation with either using {@link Layout#HYPHENATION_FREQUENCY_NORMAL} or
+     * {@link Layout#HYPHENATION_FREQUENCY_FULL} while line breaking is set to one of
+     * {@link Layout#BREAK_STRATEGY_BALANCED}, {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}
+     * improves the structure of text layout however has performance impact and requires more time
+     * to do the text layout.
+     * <p/>
+     * Note: Before Android Q, in the theme hyphenation frequency is set to
+     * {@link Layout#HYPHENATION_FREQUENCY_NORMAL}. The default value is changed into
+     * {@link Layout#HYPHENATION_FREQUENCY_NONE} on Q.
      *
-     * @param hyphenationFrequency The hyphenation frequency to use.
+     * @param hyphenationFrequency the hyphenation frequency to use, one of
+     *                             {@link Layout#HYPHENATION_FREQUENCY_NONE},
+     *                             {@link Layout#HYPHENATION_FREQUENCY_NORMAL},
+     *                             {@link Layout#HYPHENATION_FREQUENCY_FULL}
      * @attr ref android.R.styleable#TextView_hyphenationFrequency
      * @see #getHyphenationFrequency()
+     * @see #getBreakStrategy()
      */
     public void setHyphenationFrequency(@Layout.HyphenationFrequency int hyphenationFrequency) {
         mHyphenationFrequency = hyphenationFrequency;
@@ -4751,6 +4833,7 @@
      * @attr ref android.R.styleable#TextView_scrollHorizontally
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean getHorizontallyScrolling() {
         return mHorizontallyScrolling;
     }
@@ -5612,6 +5695,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void setText(CharSequence text, BufferType type,
                          boolean notifyBefore, int oldlen) {
         mTextSetFromXmlOrResourceId = false;
@@ -5957,6 +6041,7 @@
         return mHint;
     }
 
+    @UnsupportedAppUsage
     boolean isSingleLine() {
         return mSingleLine;
     }
@@ -6125,6 +6210,7 @@
         return locales.get(0);
     }
 
+    @UnsupportedAppUsage
     private void setInputType(int type, boolean direct) {
         final int cls = type & EditorInfo.TYPE_MASK_CLASS;
         KeyListener input;
@@ -6601,6 +6687,7 @@
         return getMeasuredHeight() - padding + opticalInsets.top + opticalInsets.bottom;
     }
 
+    @UnsupportedAppUsage
     int getVerticalOffset(boolean forceNormal) {
         int voffset = 0;
         final int gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
@@ -6973,7 +7060,8 @@
     public boolean hasOverlappingRendering() {
         // horizontal fading edge causes SaveLayerAlpha, which doesn't support alpha modulation
         return ((getBackground() != null && getBackground().getCurrent() != null)
-                || mSpannable != null || hasSelection() || isHorizontalFadingEdgeEnabled());
+                || mSpannable != null || hasSelection() || isHorizontalFadingEdgeEnabled()
+                || mShadowColor != 0);
     }
 
     /**
@@ -7067,6 +7155,7 @@
         return drawableState;
     }
 
+    @UnsupportedAppUsage
     private Path getUpdatedHighlightPath() {
         Path highlight = null;
         Paint highlightPaint = mHighlightPaint;
@@ -8109,6 +8198,7 @@
 
     /** @hide */
     @VisibleForTesting
+    @UnsupportedAppUsage
     public void nullLayouts() {
         if (mLayout instanceof BoringLayout && mSavedLayout == null) {
             mSavedLayout = (BoringLayout) mLayout;
@@ -8129,6 +8219,7 @@
      * Make a new Layout based on the already-measured size of the view,
      * on the assumption that it was measured correctly at some point.
      */
+    @UnsupportedAppUsage
     private void assumeLayout() {
         int width = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();
 
@@ -8146,6 +8237,7 @@
                       physicalWidth, false);
     }
 
+    @UnsupportedAppUsage
     private Layout.Alignment getLayoutAlignment() {
         Layout.Alignment alignment;
         switch (getTextAlignment()) {
@@ -8204,6 +8296,7 @@
      * {@hide}
      */
     @VisibleForTesting
+    @UnsupportedAppUsage
     public void makeNewLayout(int wantWidth, int hintWidth,
                                  BoringLayout.Metrics boring,
                                  BoringLayout.Metrics hintBoring,
@@ -8428,6 +8521,7 @@
         return result;
     }
 
+    @UnsupportedAppUsage
     private boolean compressText(float width) {
         if (isHardwareAccelerated()) return false;
 
@@ -8896,6 +8990,7 @@
      * Check whether entirely new text requires a new view layout
      * or merely a new text layout.
      */
+    @UnsupportedAppUsage
     private void checkForRelayout() {
         // If we have a fixed width, we can just swap in a new text layout
         // if the text height stays the same or if the view height is fixed.
@@ -8970,6 +9065,7 @@
     /**
      * Returns true if anything changed.
      */
+    @UnsupportedAppUsage
     private boolean bringTextIntoView() {
         Layout layout = isShowingHint() ? mHintLayout : mLayout;
         int line = 0;
@@ -9338,6 +9434,7 @@
         return getCompoundPaddingLeft() - mScrollX;
     }
 
+    @UnsupportedAppUsage
     int viewportToContentVerticalOffset() {
         int offset = getExtendedPaddingTop() - mScrollY;
         if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
@@ -9623,6 +9720,7 @@
                         && mSavedMarqueeModeLayout.getLineWidth(0) > width));
     }
 
+    @UnsupportedAppUsage
     private void startMarquee() {
         // Do not ellipsize EditText
         if (getKeyListener() != null) return;
@@ -9665,6 +9763,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void startStopMarquee(boolean start) {
         if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
             if (start) {
@@ -10209,6 +10308,7 @@
      * @return True iff this TextView contains a text that can be edited, or if this is
      * a selectable TextView.
      */
+    @UnsupportedAppUsage
     boolean isTextEditable() {
         return mText instanceof Editable && onCheckIsTextEditor() && isEnabled();
     }
@@ -10471,6 +10571,7 @@
                 || (isTextSelectable() && mText instanceof Spannable && isEnabled());
     }
 
+    @UnsupportedAppUsage
     private Locale getTextServicesLocale(boolean allowNullLocale) {
         // Start fetching the text services locale asynchronously.
         updateTextServicesLocaleAsync();
@@ -10550,6 +10651,7 @@
         });
     }
 
+    @UnsupportedAppUsage
     private void updateTextServicesLocaleLocked() {
         final TextServicesManager textServicesManager = (TextServicesManager)
                 mContext.getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
@@ -11228,6 +11330,7 @@
      *         be {@code null} if no text is set
      */
     @Nullable
+    @UnsupportedAppUsage
     private CharSequence getTextForAccessibility() {
         // If the text is empty, we must be showing the hint text.
         if (TextUtils.isEmpty(mText)) {
@@ -11365,6 +11468,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     CharSequence getTransformedText(int start, int end) {
         return removeSuggestionSpans(mTransformed.subSequence(start, end));
     }
@@ -11666,6 +11770,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected void stopTextActionMode() {
         if (mEditor != null) {
             mEditor.stopTextActionMode();
@@ -11729,6 +11834,7 @@
         return mDeviceProvisionedState == DEVICE_PROVISIONED_YES;
     }
 
+    @UnsupportedAppUsage
     boolean canPaste() {
         return (mText instanceof Editable
                 && mEditor != null && mEditor.mKeyListener != null
@@ -11868,6 +11974,7 @@
         return x;
     }
 
+    @UnsupportedAppUsage
     int getLineAtCoordinate(float y) {
         y -= getTotalPaddingTop();
         // Clamp the position to inside of the view.
@@ -11944,6 +12051,7 @@
      * @return the current {@link TextDirectionHeuristic}.
      * @hide
      */
+    @UnsupportedAppUsage
     protected TextDirectionHeuristic getTextDirectionHeuristic() {
         if (hasPasswordTransformationMethod()) {
             // passwords fields should be LTR
@@ -12055,6 +12163,7 @@
      * Deletes the range of text [start, end[.
      * @hide
      */
+    @UnsupportedAppUsage
     protected void deleteText_internal(int start, int end) {
         ((Editable) mText).delete(start, end);
     }
@@ -12095,6 +12204,7 @@
      * Also note that for performance reasons, the mEditor is created when needed, but not
      * reset when no more edit-specific fields are needed.
      */
+    @UnsupportedAppUsage
     private void createEditorIfNeeded() {
         if (mEditor == null) {
             mEditor = new Editor(this);
@@ -12105,6 +12215,7 @@
      * @hide
      */
     @Override
+    @UnsupportedAppUsage
     public CharSequence getIterableTextForAccessibility() {
         return mText;
     }
@@ -12214,6 +12325,7 @@
     public static class SavedState extends BaseSavedState {
         int selStart = -1;
         int selEnd = -1;
+        @UnsupportedAppUsage
         CharSequence text;
         boolean frozenWithFocus;
         CharSequence error;
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index cfec3f2..6a5c8cc 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -20,6 +20,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -84,6 +85,7 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface TimePickerMode {}
 
+    @UnsupportedAppUsage
     private final TimePickerDelegate mDelegate;
 
     @TimePickerMode
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index d74a60e..3fbc819 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.annotation.UnsupportedAppUsage;
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
 import android.content.Context;
@@ -93,7 +94,9 @@
     public static final int LENGTH_LONG = 1;
 
     final Context mContext;
+    @UnsupportedAppUsage
     final TN mTN;
+    @UnsupportedAppUsage
     int mDuration;
     View mNextView;
 
@@ -133,9 +136,10 @@
         String pkg = mContext.getOpPackageName();
         TN tn = mTN;
         tn.mNextView = mNextView;
+        final int displayId = mContext.getDisplay().getDisplayId();
 
         try {
-            service.enqueueToast(pkg, tn, mDuration);
+            service.enqueueToast(pkg, tn, mDuration, displayId);
         } catch (RemoteException e) {
             // Empty
         }
@@ -252,6 +256,7 @@
      * Gets the LayoutParams for the Toast window.
      * @hide
      */
+    @UnsupportedAppUsage
     public WindowManager.LayoutParams getWindowParams() {
         return mTN.mParams;
     }
@@ -335,8 +340,10 @@
     // the proper ordering of these system-wide.
     // =======================================================================================
 
+    @UnsupportedAppUsage
     private static INotificationManager sService;
 
+    @UnsupportedAppUsage
     static private INotificationManager getService() {
         if (sService != null) {
             return sService;
@@ -346,6 +353,7 @@
     }
 
     private static class TN extends ITransientNotification.Stub {
+        @UnsupportedAppUsage
         private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
 
         private static final int SHOW = 0;
@@ -353,13 +361,18 @@
         private static final int CANCEL = 2;
         final Handler mHandler;
 
+        @UnsupportedAppUsage
         int mGravity;
-        int mX, mY;
+        int mX;
+        @UnsupportedAppUsage
+        int mY;
         float mHorizontalMargin;
         float mVerticalMargin;
 
 
+        @UnsupportedAppUsage
         View mView;
+        @UnsupportedAppUsage
         View mNextView;
         int mDuration;
 
@@ -430,6 +443,7 @@
          * schedule handleShow into the right thread
          */
         @Override
+        @UnsupportedAppUsage
         public void show(IBinder windowToken) {
             if (localLOGV) Log.v(TAG, "SHOW: " + this);
             mHandler.obtainMessage(SHOW, windowToken).sendToTarget();
@@ -520,6 +534,7 @@
             accessibilityManager.sendAccessibilityEvent(event);
         }
 
+        @UnsupportedAppUsage
         public void handleHide() {
             if (localLOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView);
             if (mView != null) {
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 79c1902..1bbd7e8 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -24,6 +24,7 @@
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -133,8 +134,10 @@
     private static final String TAG = "Toolbar";
 
     private ActionMenuView mMenuView;
+    @UnsupportedAppUsage
     private TextView mTitleTextView;
     private TextView mSubtitleTextView;
+    @UnsupportedAppUsage
     private ImageButton mNavButtonView;
     private ImageView mLogoView;
 
@@ -157,9 +160,13 @@
 
     private int mMaxButtonHeight;
 
+    @UnsupportedAppUsage
     private int mTitleMarginStart;
+    @UnsupportedAppUsage
     private int mTitleMarginEnd;
+    @UnsupportedAppUsage
     private int mTitleMarginTop;
+    @UnsupportedAppUsage
     private int mTitleMarginBottom;
 
     private RtlSpacingHelper mContentInsets;
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 58a2b0f..14881eb 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -84,6 +85,7 @@
 
     // all possible internal states
     private static final int STATE_ERROR = -1;
+    @UnsupportedAppUsage
     private static final int STATE_IDLE = 0;
     private static final int STATE_PREPARING = 1;
     private static final int STATE_PREPARED = 2;
@@ -94,7 +96,9 @@
     private final Vector<Pair<InputStream, MediaFormat>> mPendingSubtitleTracks = new Vector<>();
 
     // settable by the client
+    @UnsupportedAppUsage
     private Uri mUri;
+    @UnsupportedAppUsage
     private Map<String, String> mHeaders;
 
     // mCurrentState is a VideoView object's current state.
@@ -102,20 +106,28 @@
     // For instance, regardless the VideoView object's current state,
     // calling pause() intends to bring the object to a target state
     // of STATE_PAUSED.
+    @UnsupportedAppUsage
     private int mCurrentState = STATE_IDLE;
+    @UnsupportedAppUsage
     private int mTargetState = STATE_IDLE;
 
     // All the stuff we need for playing and showing a video
+    @UnsupportedAppUsage
     private SurfaceHolder mSurfaceHolder = null;
+    @UnsupportedAppUsage
     private MediaPlayer mMediaPlayer = null;
     private int mAudioSession;
+    @UnsupportedAppUsage
     private int mVideoWidth;
+    @UnsupportedAppUsage
     private int mVideoHeight;
     private int mSurfaceWidth;
     private int mSurfaceHeight;
+    @UnsupportedAppUsage
     private MediaController mMediaController;
     private OnCompletionListener mOnCompletionListener;
     private MediaPlayer.OnPreparedListener mOnPreparedListener;
+    @UnsupportedAppUsage
     private int mCurrentBufferPercentage;
     private OnErrorListener mOnErrorListener;
     private OnInfoListener mOnInfoListener;
@@ -462,6 +474,7 @@
             }
     };
 
+    @UnsupportedAppUsage
     MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
         public void onPrepared(MediaPlayer mp) {
             mCurrentState = STATE_PREPARED;
@@ -551,6 +564,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     private MediaPlayer.OnErrorListener mErrorListener =
         new MediaPlayer.OnErrorListener() {
         public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
@@ -655,6 +669,7 @@
         mOnInfoListener = l;
     }
 
+    @UnsupportedAppUsage
     SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
     {
         public void surfaceChanged(SurfaceHolder holder, int format,
@@ -690,6 +705,7 @@
     /*
      * release the media player in any state
      */
+    @UnsupportedAppUsage
     private void release(boolean cleartargetstate) {
         if (mMediaPlayer != null) {
             mMediaPlayer.reset();
diff --git a/core/java/android/widget/VideoView2.java b/core/java/android/widget/VideoView2.java
index 388eae2..0724294a 100644
--- a/core/java/android/widget/VideoView2.java
+++ b/core/java/android/widget/VideoView2.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
@@ -202,6 +203,7 @@
      * @throws IllegalStateException if interal MediaSession is not created yet.
      * @hide  TODO: remove
      */
+    @UnsupportedAppUsage
     public MediaController getMediaController() {
         return mProvider.getMediaController_impl();
     }
@@ -285,6 +287,7 @@
      *
      * @hide TODO remove
      */
+    @UnsupportedAppUsage
     public void setVideoPath(String path) {
         mProvider.setVideoPath_impl(path);
     }
@@ -380,6 +383,7 @@
      * @hide
      */
     @VisibleForTesting
+    @UnsupportedAppUsage
     public void setOnViewTypeChangedListener(OnViewTypeChangedListener l) {
         mProvider.setOnViewTypeChangedListener_impl(l);
     }
@@ -410,6 +414,7 @@
          * <li>{@link #VIEW_TYPE_TEXTUREVIEW}
          * </ul>
          */
+        @UnsupportedAppUsage
         void onViewTypeChanged(View view, @ViewType int viewType);
     }
 
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
index 1580f51..598a407 100644
--- a/core/java/android/widget/ViewAnimator.java
+++ b/core/java/android/widget/ViewAnimator.java
@@ -18,6 +18,7 @@
 
 
 import android.annotation.AnimRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -36,7 +37,9 @@
  */
 public class ViewAnimator extends FrameLayout {
 
+    @UnsupportedAppUsage
     int mWhichChild = 0;
+    @UnsupportedAppUsage
     boolean mFirstTime = true;
 
     boolean mAnimateFirstTime = true;
@@ -147,6 +150,7 @@
      * @param animate Whether or not to use the in and out animations, defaults
      *            to true.
      */
+    @UnsupportedAppUsage
     void showOnly(int childIndex, boolean animate) {
         final int count = getChildCount();
         for (int i = 0; i < count; i++) {
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index e769d71..5e72b2e 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -47,6 +48,7 @@
     private boolean mRunning = false;
     private boolean mStarted = false;
     private boolean mVisible = false;
+    @UnsupportedAppUsage
     private boolean mUserPresent = true;
 
     public ViewFlipper(Context context) {
@@ -168,6 +170,7 @@
      *            addition to queuing future flips. If omitted, defaults to
      *            true.
      */
+    @UnsupportedAppUsage
     private void updateRunning(boolean flipNow) {
         boolean running = mVisible && mStarted && mUserPresent;
         if (running != mRunning) {
diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java
index 66c052b..dd6a27b8f 100644
--- a/core/java/android/widget/ZoomControls.java
+++ b/core/java/android/widget/ZoomControls.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.Widget;
 import android.content.Context;
 import android.util.AttributeSet;
@@ -33,7 +34,9 @@
 @Widget
 public class ZoomControls extends LinearLayout {
 
+    @UnsupportedAppUsage
     private final ZoomButton mZoomIn;
+    @UnsupportedAppUsage
     private final ZoomButton mZoomOut;
         
     public ZoomControls(Context context) {
diff --git a/core/java/com/android/internal/annotations/GuardedBy.java b/core/java/com/android/internal/annotations/GuardedBy.java
index fc61945..0e63214 100644
--- a/core/java/com/android/internal/annotations/GuardedBy.java
+++ b/core/java/com/android/internal/annotations/GuardedBy.java
@@ -23,10 +23,10 @@
 
 /**
  * Annotation type used to mark a method or field that can only be accessed when
- * holding the referenced lock.
+ * holding the referenced locks.
  */
 @Target({ ElementType.FIELD, ElementType.METHOD })
 @Retention(RetentionPolicy.CLASS)
 public @interface GuardedBy {
-    String value();
+    String[] value();
 }
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 7321721..d7031ea 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -21,6 +21,7 @@
 import com.android.internal.R;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -71,9 +72,11 @@
     private final DialogInterface mDialogInterface;
     protected final Window mWindow;
 
+    @UnsupportedAppUsage
     private CharSequence mTitle;
     protected CharSequence mMessage;
     protected ListView mListView;
+    @UnsupportedAppUsage
     private View mView;
 
     private int mViewLayoutResId;
@@ -107,8 +110,10 @@
     private MovementMethod mMessageMovementMethod;
     @Layout.HyphenationFrequency
     private Integer mMessageHyphenationFrequency;
+    @UnsupportedAppUsage
     private View mCustomTitleView;
 
+    @UnsupportedAppUsage
     private boolean mForceInverseBackground;
 
     private ListAdapter mAdapter;
@@ -198,6 +203,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     protected AlertController(Context context, DialogInterface di, Window window) {
         mContext = context;
         mDialogInterface = di;
@@ -258,6 +264,7 @@
         installContent();
     }
 
+    @UnsupportedAppUsage
     public void installContent() {
         int contentView = selectContentView();
         mWindow.setContentView(contentView);
@@ -275,6 +282,7 @@
         return mAlertDialogLayout;
     }
 
+    @UnsupportedAppUsage
     public void setTitle(CharSequence title) {
         mTitle = title;
         if (mTitleView != null) {
@@ -285,10 +293,12 @@
     /**
      * @see AlertDialog.Builder#setCustomTitle(View)
      */
+    @UnsupportedAppUsage
     public void setCustomTitle(View customTitleView) {
         mCustomTitleView = customTitleView;
     }
 
+    @UnsupportedAppUsage
     public void setMessage(CharSequence message) {
         mMessage = message;
         if (mMessageView != null) {
@@ -323,6 +333,7 @@
     /**
      * Set the view to display in the dialog.
      */
+    @UnsupportedAppUsage
     public void setView(View view) {
         mView = view;
         mViewLayoutResId = 0;
@@ -362,6 +373,7 @@
      * @param listener The {@link DialogInterface.OnClickListener} to use.
      * @param msg The {@link Message} to be sent when clicked.
      */
+    @UnsupportedAppUsage
     public void setButton(int whichButton, CharSequence text,
             DialogInterface.OnClickListener listener, Message msg) {
 
@@ -397,6 +409,7 @@
      * @param resId the resource identifier of the drawable to use as the icon,
      *            or 0 for no icon
      */
+    @UnsupportedAppUsage
     public void setIcon(int resId) {
         mIcon = null;
         mIconId = resId;
@@ -416,6 +429,7 @@
      *
      * @param icon the drawable to use as the icon or null for no icon
      */
+    @UnsupportedAppUsage
     public void setIcon(Drawable icon) {
         mIcon = icon;
         mIconId = 0;
@@ -446,10 +460,12 @@
         mForceInverseBackground = forceInverseBackground;
     }
 
+    @UnsupportedAppUsage
     public ListView getListView() {
         return mListView;
     }
 
+    @UnsupportedAppUsage
     public Button getButton(int whichButton) {
         switch (whichButton) {
             case DialogInterface.BUTTON_POSITIVE:
@@ -464,11 +480,13 @@
     }
 
     @SuppressWarnings({"UnusedDeclaration"})
+    @UnsupportedAppUsage
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         return mScrollView != null && mScrollView.executeKeyEvent(event);
     }
 
     @SuppressWarnings({"UnusedDeclaration"})
+    @UnsupportedAppUsage
     public boolean onKeyUp(int keyCode, KeyEvent event) {
         return mScrollView != null && mScrollView.executeKeyEvent(event);
     }
@@ -932,10 +950,12 @@
 
         boolean mRecycleOnMeasure = true;
 
+        @UnsupportedAppUsage
         public RecycleListView(Context context) {
             this(context, null);
         }
 
+        @UnsupportedAppUsage
         public RecycleListView(Context context, AttributeSet attrs) {
             super(context, attrs);
 
@@ -964,44 +984,74 @@
     }
 
     public static class AlertParams {
+        @UnsupportedAppUsage
         public final Context mContext;
+        @UnsupportedAppUsage
         public final LayoutInflater mInflater;
 
+        @UnsupportedAppUsage
         public int mIconId = 0;
+        @UnsupportedAppUsage
         public Drawable mIcon;
         public int mIconAttrId = 0;
+        @UnsupportedAppUsage
         public CharSequence mTitle;
+        @UnsupportedAppUsage
         public View mCustomTitleView;
+        @UnsupportedAppUsage
         public CharSequence mMessage;
+        @UnsupportedAppUsage
         public CharSequence mPositiveButtonText;
+        @UnsupportedAppUsage
         public DialogInterface.OnClickListener mPositiveButtonListener;
+        @UnsupportedAppUsage
         public CharSequence mNegativeButtonText;
+        @UnsupportedAppUsage
         public DialogInterface.OnClickListener mNegativeButtonListener;
+        @UnsupportedAppUsage
         public CharSequence mNeutralButtonText;
+        @UnsupportedAppUsage
         public DialogInterface.OnClickListener mNeutralButtonListener;
+        @UnsupportedAppUsage
         public boolean mCancelable;
+        @UnsupportedAppUsage
         public DialogInterface.OnCancelListener mOnCancelListener;
+        @UnsupportedAppUsage
         public DialogInterface.OnDismissListener mOnDismissListener;
+        @UnsupportedAppUsage
         public DialogInterface.OnKeyListener mOnKeyListener;
+        @UnsupportedAppUsage
         public CharSequence[] mItems;
+        @UnsupportedAppUsage
         public ListAdapter mAdapter;
+        @UnsupportedAppUsage
         public DialogInterface.OnClickListener mOnClickListener;
         public int mViewLayoutResId;
+        @UnsupportedAppUsage
         public View mView;
         public int mViewSpacingLeft;
         public int mViewSpacingTop;
         public int mViewSpacingRight;
         public int mViewSpacingBottom;
         public boolean mViewSpacingSpecified = false;
+        @UnsupportedAppUsage
         public boolean[] mCheckedItems;
+        @UnsupportedAppUsage
         public boolean mIsMultiChoice;
+        @UnsupportedAppUsage
         public boolean mIsSingleChoice;
+        @UnsupportedAppUsage
         public int mCheckedItem = -1;
+        @UnsupportedAppUsage
         public DialogInterface.OnMultiChoiceClickListener mOnCheckboxClickListener;
+        @UnsupportedAppUsage
         public Cursor mCursor;
+        @UnsupportedAppUsage
         public String mLabelColumn;
+        @UnsupportedAppUsage
         public String mIsCheckedColumn;
         public boolean mForceInverseBackground;
+        @UnsupportedAppUsage
         public AdapterView.OnItemSelectedListener mOnItemSelectedListener;
         public OnPrepareListViewListener mOnPrepareListViewListener;
         public boolean mRecycleOnMeasure = true;
@@ -1019,12 +1069,14 @@
             void onPrepareListView(ListView listView);
         }
 
+        @UnsupportedAppUsage
         public AlertParams(Context context) {
             mContext = context;
             mCancelable = true;
             mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         }
 
+        @UnsupportedAppUsage
         public void apply(AlertController dialog) {
             if (mCustomTitleView != null) {
                 dialog.setCustomTitle(mCustomTitleView);
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 0ed9724..768dddd 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -33,7 +33,7 @@
     void stopWatchingMode(IAppOpsCallback callback);
     IBinder getToken(IBinder clientToken);
     int permissionToOpCode(String permission);
-    int noteProxyOperation(int code, String proxyPackageName,
+    int noteProxyOperation(int code, int proxyUid, String proxyPackageName,
                 int callingUid, String callingPackageName);
 
     // Remaining methods are only used in Java.
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index abb9321..8cfe1c1 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -16,6 +16,10 @@
 
 package com.android.internal.app;
 
+import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
+
+import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
@@ -23,8 +27,10 @@
 import android.app.AppGlobals;
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -32,12 +38,11 @@
 import android.os.UserManager;
 import android.util.Slog;
 import android.widget.Toast;
-
 import com.android.internal.annotations.VisibleForTesting;
-
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
-
-import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
+import java.util.Set;
 
 /**
  * This is used in conjunction with
@@ -45,7 +50,6 @@
  * be passed in and out of a managed profile.
  */
 public class IntentForwarderActivity extends Activity  {
-
     public static String TAG = "IntentForwarderActivity";
 
     public static String FORWARD_INTENT_TO_PARENT
@@ -54,6 +58,11 @@
     public static String FORWARD_INTENT_TO_MANAGED_PROFILE
             = "com.android.internal.app.ForwardIntentToManagedProfile";
 
+    private static final Set<String> ALLOWED_TEXT_MESSAGE_SCHEMES
+            = new HashSet<>(Arrays.asList("sms", "smsto", "mms", "mmsto"));
+
+    private static final String TEL_SCHEME = "tel";
+
     private Injector mInjector;
 
     @Override
@@ -94,19 +103,8 @@
                 newIntent.prepareToLeaveUser(callingUserId);
             }
 
-            final android.content.pm.ResolveInfo ri =
-                    mInjector.getPackageManager().resolveActivityAsUser(
-                            newIntent,
-                            MATCH_DEFAULT_ONLY,
-                            targetUserId);
-
-            // Don't show the disclosure if next activity is ResolverActivity or ChooserActivity
-            // as those will already have shown work / personal as neccesary etc.
-            final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null ||
-                    !"android".equals(ri.activityInfo.packageName) ||
-                    !(ResolverActivity.class.getName().equals(ri.activityInfo.name)
-                            || ChooserActivity.class.getName().equals(ri.activityInfo.name));
-
+            final ResolveInfo ri = mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY,
+                    targetUserId);
             try {
                 startActivityAsCaller(newIntent, null, false, targetUserId);
             } catch (RuntimeException e) {
@@ -125,8 +123,8 @@
                         + ActivityThread.currentProcessName(), e);
             }
 
-            if (shouldShowDisclosure) {
-                Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show();
+            if (shouldShowDisclosure(ri, intentReceived)) {
+                mInjector.showToast(userMessageId, Toast.LENGTH_LONG);
             }
         } else {
             Slog.wtf(TAG, "the intent: " + intentReceived + " cannot be forwarded from user "
@@ -135,6 +133,43 @@
         finish();
     }
 
+    private boolean shouldShowDisclosure(@Nullable ResolveInfo ri, Intent intent) {
+        if (ri == null || ri.activityInfo == null) {
+            return true;
+        }
+        if (ri.activityInfo.applicationInfo.isSystemApp()
+                && (isDialerIntent(intent) || isTextMessageIntent(intent))) {
+            return false;
+        }
+        return !isTargetResolverOrChooserActivity(ri.activityInfo);
+    }
+
+    private boolean isTextMessageIntent(Intent intent) {
+        return (Intent.ACTION_SENDTO.equals(intent.getAction()) || isViewActionIntent(intent))
+                && ALLOWED_TEXT_MESSAGE_SCHEMES.contains(intent.getScheme());
+    }
+
+    private boolean isDialerIntent(Intent intent) {
+        return Intent.ACTION_DIAL.equals(intent.getAction())
+                || Intent.ACTION_CALL.equals(intent.getAction())
+                || Intent.ACTION_CALL_PRIVILEGED.equals(intent.getAction())
+                || Intent.ACTION_CALL_EMERGENCY.equals(intent.getAction())
+                || (isViewActionIntent(intent) && TEL_SCHEME.equals(intent.getScheme()));
+    }
+
+    private boolean isViewActionIntent(Intent intent) {
+        return Intent.ACTION_VIEW.equals(intent.getAction())
+                && intent.hasCategory(Intent.CATEGORY_BROWSABLE);
+    }
+
+    private boolean isTargetResolverOrChooserActivity(ActivityInfo activityInfo) {
+        if (!"android".equals(activityInfo.packageName)) {
+            return false;
+        }
+        return ResolverActivity.class.getName().equals(activityInfo.name)
+            || ChooserActivity.class.getName().equals(activityInfo.name);
+    }
+
     /**
      * Check whether the intent can be forwarded to target user. Return the intent used for
      * forwarding if it can be forwarded, {@code null} otherwise.
@@ -242,6 +277,16 @@
         public PackageManager getPackageManager() {
             return IntentForwarderActivity.this.getPackageManager();
         }
+
+        @Override
+        public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
+            return getPackageManager().resolveActivityAsUser(intent, flags, userId);
+        }
+
+        @Override
+        public void showToast(int messageId, int duration) {
+            Toast.makeText(IntentForwarderActivity.this, getString(messageId), duration).show();
+        }
     }
 
     public interface Injector {
@@ -250,5 +295,9 @@
         UserManager getUserManager();
 
         PackageManager getPackageManager();
+
+        ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId);
+
+        void showToast(@StringRes int messageId, int duration);
     }
 }
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index d247013..1d997f5 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -21,6 +21,7 @@
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 
+import java.io.Serializable;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.IllformedLocaleException;
@@ -31,7 +32,7 @@
     private static final HashMap<String, LocaleInfo> sLocaleCache = new HashMap<>();
     private static boolean sFullyInitialized = false;
 
-    public static class LocaleInfo {
+    public static class LocaleInfo implements Serializable {
         private static final int SUGGESTION_TYPE_NONE = 0;
         private static final int SUGGESTION_TYPE_SIM = 1 << 0;
         private static final int SUGGESTION_TYPE_CFG = 1 << 1;
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 1b3faf5..119f30d 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -33,6 +33,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Dialog;
@@ -79,6 +80,7 @@
     private ActionBarOverlayLayout mOverlayLayout;
     private ActionBarContainer mContainerView;
     private DecorToolbar mDecorToolbar;
+    @UnsupportedAppUsage
     private ActionBarContextView mContextView;
     private ActionBarContainer mSplitView;
     private View mContentView;
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
new file mode 100644
index 0000000..115ba18
--- /dev/null
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app.procstats;
+
+
+import android.os.Parcel;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.service.procstats.ProcessStatsAssociationStateProto;
+import android.service.procstats.ProcessStatsStateProto;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Objects;
+
+public final class AssociationState {
+    private static final String TAG = "ProcessStats";
+    private static final boolean DEBUG = false;
+
+    private final ProcessStats mProcessStats;
+    private final ProcessStats.PackageState mPackageState;
+    private final String mProcessName;
+    private final String mName;
+
+    public final class SourceState {
+        final SourceKey mKey;
+        int mProcStateSeq = -1;
+        int mProcState = ProcessStats.STATE_NOTHING;
+        boolean mInTrackingList;
+        int mNesting;
+        int mCount;
+        long mStartUptime;
+        long mDuration;
+        long mTrackingUptime;
+        int mActiveCount;
+        int mActiveProcState = ProcessStats.STATE_NOTHING;
+        long mActiveStartUptime;
+        long mActiveDuration;
+        DurationsTable mDurations;
+
+        SourceState(SourceKey key) {
+            mKey = key;
+        }
+
+        public AssociationState getAssociationState() {
+            return AssociationState.this;
+        }
+
+        public String getProcessName() {
+            return mKey.mProcess;
+        }
+
+        public int getUid() {
+            return mKey.mUid;
+        }
+
+        public void trackProcState(int procState, int seq, long now) {
+            procState = ProcessState.PROCESS_STATE_TO_STATE[procState];
+            if (seq != mProcStateSeq) {
+                mProcStateSeq = seq;
+                mProcState = procState;
+            } else if (procState < mProcState) {
+                mProcState = procState;
+            }
+            if (procState < ProcessStats.STATE_HOME) {
+                // If the proc state has become better than cached, then we want to
+                // start tracking it to count when it is actually active.  If it drops
+                // down to cached, we will clean it up when we later evaluate all currently
+                // tracked associations in ProcessStats.updateTrackingAssociationsLocked().
+                if (!mInTrackingList) {
+                    mInTrackingList = true;
+                    mTrackingUptime = now;
+                    mProcessStats.mTrackingAssociations.add(this);
+                }
+            }
+        }
+
+        public void stop() {
+            mNesting--;
+            if (mNesting == 0) {
+                mDuration += SystemClock.uptimeMillis() - mStartUptime;
+                mNumActive--;
+                stopTracking(SystemClock.uptimeMillis());
+            }
+        }
+
+        void startActive(long now) {
+            if (mInTrackingList) {
+                if (mActiveStartUptime == 0) {
+                    mActiveStartUptime = now;
+                    mActiveCount++;
+                }
+                if (mActiveProcState != mProcState) {
+                    if (mActiveProcState != ProcessStats.STATE_NOTHING) {
+                        // Currently active proc state changed, need to store the duration
+                        // so far and switch tracking to the new proc state.
+                        final long duration = mActiveDuration + now - mActiveStartUptime;
+                        if (duration != 0) {
+                            if (mDurations == null) {
+                                makeDurations();
+                            }
+                            mDurations.addDuration(mActiveProcState, duration);
+                            mActiveDuration = 0;
+                        }
+                        mActiveStartUptime = now;
+                    }
+                    mActiveProcState = mProcState;
+                }
+            } else {
+                Slog.wtf(TAG, "startActive while not tracking: " + this);
+            }
+        }
+
+        void stopActive(long now) {
+            if (mActiveStartUptime != 0) {
+                if (!mInTrackingList) {
+                    Slog.wtf(TAG, "stopActive while not tracking: " + this);
+                }
+                final long duration = mActiveDuration + now - mActiveStartUptime;
+                if (mDurations != null) {
+                    mDurations.addDuration(mActiveProcState, duration);
+                } else {
+                    mActiveDuration = duration;
+                }
+                mActiveStartUptime = 0;
+            }
+        }
+
+        void makeDurations() {
+            mDurations = new DurationsTable(mProcessStats.mTableData);
+        }
+
+        void stopTracking(long now) {
+            stopActive(now);
+            if (mInTrackingList) {
+                mInTrackingList = false;
+                mProcState = ProcessStats.STATE_NOTHING;
+                // Do a manual search for where to remove, since these objects will typically
+                // be towards the end of the array.
+                final ArrayList<SourceState> list = mProcessStats.mTrackingAssociations;
+                for (int i = list.size() - 1; i >= 0; i--) {
+                    if (list.get(i) == this) {
+                        list.remove(i);
+                        return;
+                    }
+                }
+                Slog.wtf(TAG, "Stop tracking didn't find in tracking list: " + this);
+            }
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder(64);
+            sb.append("SourceState{").append(Integer.toHexString(System.identityHashCode(this)))
+                    .append(" ").append(mKey.mProcess).append("/").append(mKey.mUid);
+            if (mProcState != ProcessStats.STATE_NOTHING) {
+                sb.append(" ").append(DumpUtils.STATE_NAMES[mProcState]).append(" #")
+                        .append(mProcStateSeq);
+            }
+            sb.append("}");
+            return sb.toString();
+        }
+    }
+
+    private final static class SourceKey {
+        /**
+         * UID, consider this final.  Not final just to avoid a temporary object during lookup.
+         */
+        int mUid;
+
+        /**
+         * Process name, consider this final.  Not final just to avoid a temporary object during
+         * lookup.
+         */
+        String mProcess;
+
+        SourceKey(int uid, String process) {
+            mUid = uid;
+            mProcess = process;
+        }
+
+        public boolean equals(Object o) {
+            if (!(o instanceof SourceKey)) {
+                return false;
+            }
+            SourceKey s = (SourceKey) o;
+            return s.mUid == mUid && Objects.equals(s.mProcess, mProcess);
+        }
+
+        @Override
+        public int hashCode() {
+            return Integer.hashCode(mUid) ^ (mProcess == null ? 0 : mProcess.hashCode());
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder(64);
+            sb.append("SourceKey{");
+            UserHandle.formatUid(sb, mUid);
+            sb.append(' ');
+            sb.append(mProcess);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    /**
+     * All known sources for this target component...  uid -> process name -> source state.
+     */
+    private final ArrayMap<SourceKey, SourceState> mSources = new ArrayMap<>();
+
+    private final SourceKey mTmpSourceKey = new SourceKey(0, null);
+
+    private ProcessState mProc;
+
+    private int mNumActive;
+
+    public AssociationState(ProcessStats processStats, ProcessStats.PackageState packageState,
+            String name, String processName, ProcessState proc) {
+        mProcessStats = processStats;
+        mPackageState = packageState;
+        mName = name;
+        mProcessName = processName;
+        mProc = proc;
+    }
+
+    public int getUid() {
+        return mPackageState.mUid;
+    }
+
+    public String getPackage() {
+        return mPackageState.mPackageName;
+    }
+
+    public String getProcessName() {
+        return mProcessName;
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public ProcessState getProcess() {
+        return mProc;
+    }
+
+    public void setProcess(ProcessState proc) {
+        mProc = proc;
+    }
+
+    public SourceState startSource(int uid, String processName) {
+        mTmpSourceKey.mUid = uid;
+        mTmpSourceKey.mProcess = processName;
+        SourceState src = mSources.get(mTmpSourceKey);
+        if (src == null) {
+            SourceKey key = new SourceKey(uid, processName);
+            src = new SourceState(key);
+            mSources.put(key, src);
+        }
+        src.mNesting++;
+        if (src.mNesting == 1) {
+            src.mCount++;
+            src.mStartUptime = SystemClock.uptimeMillis();
+            mNumActive++;
+        }
+        return src;
+    }
+
+    public void add(AssociationState other) {
+        for (int isrc = other.mSources.size() - 1; isrc >= 0; isrc--) {
+            final SourceKey key = other.mSources.keyAt(isrc);
+            final SourceState otherSrc = other.mSources.valueAt(isrc);
+            SourceState mySrc = mSources.get(key);
+            if (mySrc == null) {
+                mySrc = new SourceState(key);
+                mSources.put(key, mySrc);
+            }
+            mySrc.mCount += otherSrc.mCount;
+            mySrc.mDuration += otherSrc.mDuration;
+            mySrc.mActiveCount += otherSrc.mActiveCount;
+            if (otherSrc.mActiveDuration != 0 || otherSrc.mDurations != null) {
+                // Only need to do anything if the other one has some duration data.
+                if (mySrc.mDurations != null) {
+                    // If the target already has multiple durations, just add in whatever
+                    // we have in the other.
+                    if (otherSrc.mDurations != null) {
+                        mySrc.mDurations.addDurations(otherSrc.mDurations);
+                    } else {
+                        mySrc.mDurations.addDuration(otherSrc.mActiveProcState,
+                                otherSrc.mActiveDuration);
+                    }
+                } else if (otherSrc.mDurations != null) {
+                    // The other one has multiple durations, but we don't.  Expand to
+                    // multiple durations and copy over.
+                    mySrc.makeDurations();
+                    mySrc.mDurations.addDurations(otherSrc.mDurations);
+                    if (mySrc.mActiveDuration != 0) {
+                        mySrc.mDurations.addDuration(mySrc.mActiveProcState, mySrc.mActiveDuration);
+                        mySrc.mActiveDuration = 0;
+                        mySrc.mActiveProcState = ProcessStats.STATE_NOTHING;
+                    }
+                } else if (mySrc.mActiveDuration != 0) {
+                    // Both have a single inline duration...  we can either add them together,
+                    // or need to expand to multiple durations.
+                    if (mySrc.mActiveProcState == otherSrc.mActiveProcState) {
+                        mySrc.mDuration += otherSrc.mDuration;
+                    } else {
+                        // The two have durations with different proc states, need to turn
+                        // in to multiple durations.
+                        mySrc.makeDurations();
+                        mySrc.mDurations.addDuration(mySrc.mActiveProcState, mySrc.mActiveDuration);
+                        mySrc.mDurations.addDuration(otherSrc.mActiveProcState,
+                                otherSrc.mActiveDuration);
+                        mySrc.mActiveDuration = 0;
+                        mySrc.mActiveProcState = ProcessStats.STATE_NOTHING;
+                    }
+                } else {
+                    // The other one has a duration, and we know the target doesn't.  Copy over.
+                    mySrc.mActiveProcState = otherSrc.mActiveProcState;
+                    mySrc.mActiveDuration = otherSrc.mActiveDuration;
+                }
+            }
+        }
+    }
+
+    public boolean isInUse() {
+        return mNumActive > 0;
+    }
+
+    public void resetSafely(long now) {
+        if (!isInUse()) {
+            mSources.clear();
+        } else {
+            // We have some active sources...  clear out everything but those.
+            for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) {
+                SourceState src = mSources.valueAt(isrc);
+                if (src.mNesting > 0) {
+                    src.mCount = 1;
+                    src.mStartUptime = now;
+                    src.mDuration = 0;
+                    if (src.mActiveStartUptime > 0) {
+                        src.mActiveCount = 1;
+                        src.mActiveStartUptime = now;
+                    } else {
+                        src.mActiveCount = 0;
+                    }
+                    src.mActiveDuration = 0;
+                    src.mDurations = null;
+                } else {
+                    mSources.removeAt(isrc);
+                }
+            }
+        }
+    }
+
+    public void writeToParcel(ProcessStats stats, Parcel out, long nowUptime) {
+        final int NSRC = mSources.size();
+        out.writeInt(NSRC);
+        for (int isrc = 0; isrc < NSRC; isrc++) {
+            final SourceKey key = mSources.keyAt(isrc);
+            final SourceState src = mSources.valueAt(isrc);
+            out.writeInt(key.mUid);
+            stats.writeCommonString(out, key.mProcess);
+            out.writeInt(src.mCount);
+            out.writeLong(src.mDuration);
+            out.writeInt(src.mActiveCount);
+            if (src.mDurations != null) {
+                out.writeInt(1);
+                src.mDurations.writeToParcel(out);
+            } else {
+                out.writeInt(0);
+                out.writeInt(src.mActiveProcState);
+                out.writeLong(src.mActiveDuration);
+            }
+        }
+    }
+
+    /**
+     * Returns non-null if all else fine, else a String that describes the error that
+     * caused it to fail.
+     */
+    public String readFromParcel(ProcessStats stats, Parcel in, int parcelVersion) {
+        final int NSRC = in.readInt();
+        if (NSRC < 0 || NSRC > 100000) {
+            return "Association with bad src count: " + NSRC;
+        }
+        for (int isrc = 0; isrc < NSRC; isrc++) {
+            final int uid = in.readInt();
+            final String procName = stats.readCommonString(in, parcelVersion);
+            final SourceKey key = new SourceKey(uid, procName);
+            final SourceState src = new SourceState(key);
+            src.mCount = in.readInt();
+            src.mDuration = in.readLong();
+            src.mActiveCount = in.readInt();
+            if (in.readInt() != 0) {
+                src.makeDurations();
+                if (!src.mDurations.readFromParcel(in)) {
+                    return "Duration table corrupt: " + key + " <- " + src;
+                }
+            } else {
+                src.mActiveProcState = in.readInt();
+                src.mActiveDuration = in.readLong();
+            }
+            mSources.put(key, src);
+        }
+        return null;
+    }
+
+    public void commitStateTime(long nowUptime) {
+        if (isInUse()) {
+            for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) {
+                SourceState src = mSources.valueAt(isrc);
+                if (src.mNesting > 0) {
+                    src.mDuration += nowUptime - src.mStartUptime;
+                    src.mStartUptime = nowUptime;
+                }
+                if (src.mActiveStartUptime > 0) {
+                    final long duration = src.mActiveDuration + nowUptime - src.mActiveStartUptime;
+                    if (src.mDurations != null) {
+                        src.mDurations.addDuration(src.mActiveProcState, duration);
+                    } else {
+                        src.mActiveDuration = duration;
+                    }
+                    src.mActiveStartUptime = nowUptime;
+                }
+            }
+        }
+    }
+
+    public void dumpStats(PrintWriter pw, String prefix, String prefixInner, String headerPrefix,
+            long now, long totalTime, boolean dumpDetails, boolean dumpAll) {
+        if (dumpAll) {
+            pw.print(prefix);
+            pw.print("mNumActive=");
+            pw.println(mNumActive);
+        }
+        final int NSRC = mSources.size();
+        for (int isrc = 0; isrc < NSRC; isrc++) {
+            final SourceKey key = mSources.keyAt(isrc);
+            final SourceState src = mSources.valueAt(isrc);
+            pw.print(prefixInner);
+            pw.print("<- ");
+            pw.print(key.mProcess);
+            pw.print(" / ");
+            UserHandle.formatUid(pw, key.mUid);
+            pw.println(":");
+            pw.print(prefixInner);
+            pw.print("   Total count ");
+            pw.print(src.mCount);
+            long duration = src.mDuration;
+            if (src.mNesting > 0) {
+                duration += now - src.mStartUptime;
+            }
+            if (dumpAll) {
+                pw.print(": Duration ");
+                TimeUtils.formatDuration(duration, pw);
+                pw.print(" / ");
+            } else {
+                pw.print(": time ");
+            }
+            DumpUtils.printPercent(pw, (double)duration/(double)totalTime);
+            if (src.mNesting > 0) {
+                pw.print(" (running");
+                if (src.mProcState != ProcessStats.STATE_NOTHING) {
+                    pw.print(" / ");
+                    pw.print(DumpUtils.STATE_NAMES[src.mProcState]);
+                    pw.print(" #");
+                    pw.print(src.mProcStateSeq);
+                }
+                pw.print(")");
+            }
+            pw.println();
+            if (src.mActiveCount > 0 || src.mDurations != null || src.mActiveDuration != 0
+                    || src.mActiveStartUptime != 0) {
+                pw.print(prefixInner);
+                pw.print("   Active count ");
+                pw.print(src.mActiveCount);
+                if (dumpDetails) {
+                    if (dumpAll) {
+                        pw.print(src.mDurations != null ? " (multi-field)" : " (inline)");
+                    }
+                    pw.println(":");
+                    dumpTime(pw, prefixInner, src, totalTime, now, dumpDetails, dumpAll);
+                } else {
+                    pw.print(": ");
+                    dumpActiveDurationSummary(pw, src, totalTime, now, dumpAll);
+                    pw.println();
+                }
+            }
+            if (dumpAll) {
+                if (src.mInTrackingList) {
+                    pw.print(prefixInner);
+                    pw.print("   mInTrackingList=");
+                    pw.println(src.mInTrackingList);
+                }
+                if (src.mProcState != ProcessStats.STATE_NOTHING) {
+                    pw.print(prefixInner);
+                    pw.print("   mProcState=");
+                    pw.print(DumpUtils.STATE_NAMES[src.mProcState]);
+                    pw.print(" mProcStateSeq=");
+                    pw.println(src.mProcStateSeq);
+                }
+            }
+        }
+    }
+
+    void dumpActiveDurationSummary(PrintWriter pw, final SourceState src, long totalTime,
+            long now, boolean dumpAll) {
+        long duration = dumpTime(null, null, src, totalTime, now, false, false);
+        final boolean isRunning = duration < 0;
+        if (isRunning) {
+            duration = -duration;
+        }
+        if (dumpAll) {
+            pw.print("Duration ");
+            TimeUtils.formatDuration(duration, pw);
+            pw.print(" / ");
+        } else {
+            pw.print("time ");
+        }
+        DumpUtils.printPercent(pw, (double) duration / (double) totalTime);
+        if (src.mActiveStartUptime > 0) {
+            pw.print(" (running)");
+        }
+        pw.println();
+    }
+
+    long dumpTime(PrintWriter pw, String prefix, final SourceState src, long overallTime, long now,
+            boolean dumpDetails, boolean dumpAll) {
+        long totalTime = 0;
+        boolean isRunning = false;
+        for (int iprocstate = 0; iprocstate < ProcessStats.STATE_COUNT; iprocstate++) {
+            long time;
+            if (src.mDurations != null) {
+                time = src.mDurations.getValueForId((byte)iprocstate);
+            } else {
+                time = src.mActiveProcState == iprocstate ? src.mDuration : 0;
+            }
+            final String running;
+            if (src.mActiveStartUptime != 0 && src.mActiveProcState == iprocstate) {
+                running = " (running)";
+                isRunning = true;
+                time += now - src.mActiveStartUptime;
+            } else {
+                running = null;
+            }
+            if (time != 0) {
+                if (pw != null) {
+                    pw.print(prefix);
+                    pw.print("  ");
+                    pw.print(DumpUtils.STATE_LABELS[iprocstate]);
+                    pw.print(": ");
+                    if (dumpAll) {
+                        pw.print("Duration ");
+                        TimeUtils.formatDuration(time, pw);
+                        pw.print(" / ");
+                    } else {
+                        pw.print("time ");
+                    }
+                    DumpUtils.printPercent(pw, (double) time / (double) overallTime);
+                    if (running != null) {
+                        pw.print(running);
+                    }
+                    pw.println();
+                }
+                totalTime += time;
+            }
+        }
+        if (totalTime != 0 && pw != null) {
+            pw.print(prefix);
+            pw.print("  ");
+            pw.print(DumpUtils.STATE_LABEL_TOTAL);
+            pw.print(": ");
+            if (dumpAll) {
+                pw.print("Duration ");
+                TimeUtils.formatDuration(totalTime, pw);
+                pw.print(" / ");
+            } else {
+                pw.print("time ");
+            }
+            DumpUtils.printPercent(pw, (double) totalTime / (double) overallTime);
+            pw.println();
+        }
+        return isRunning ? -totalTime : totalTime;
+    }
+
+    public void dumpTimesCheckin(PrintWriter pw, String pkgName, int uid, long vers,
+            String associationName, long now) {
+        final int NSRC = mSources.size();
+        for (int isrc = 0; isrc < NSRC; isrc++) {
+            final SourceKey key = mSources.keyAt(isrc);
+            final SourceState src = mSources.valueAt(isrc);
+            pw.print("pkgasc");
+            pw.print(",");
+            pw.print(pkgName);
+            pw.print(",");
+            pw.print(uid);
+            pw.print(",");
+            pw.print(vers);
+            pw.print(",");
+            pw.print(associationName);
+            pw.print(",");
+            pw.print(key.mProcess);
+            pw.print(",");
+            pw.print(key.mUid);
+            pw.print(",");
+            pw.print(src.mCount);
+            long duration = src.mDuration;
+            if (src.mNesting > 0) {
+                duration += now - src.mStartUptime;
+            }
+            pw.print(",");
+            pw.print(duration);
+            pw.print(",");
+            pw.print(src.mActiveCount);
+            final long timeNow = src.mActiveStartUptime != 0 ? (now-src.mActiveStartUptime) : 0;
+            if (src.mDurations != null) {
+                final int N = src.mDurations.getKeyCount();
+                for (int i=0; i<N; i++) {
+                    final int dkey = src.mDurations.getKeyAt(i);
+                    duration = src.mDurations.getValue(dkey);
+                    if (dkey == src.mActiveProcState) {
+                        duration += timeNow;
+                    }
+                    final int procState = SparseMappingTable.getIdFromKey(dkey);
+                    pw.print(",");
+                    DumpUtils.printArrayEntry(pw, DumpUtils.STATE_TAGS,  procState, 1);
+                    pw.print(':');
+                    pw.print(duration);
+                }
+            } else {
+                duration = src.mActiveDuration + timeNow;
+                if (duration != 0) {
+                    pw.print(",");
+                    DumpUtils.printArrayEntry(pw, DumpUtils.STATE_TAGS,  src.mActiveProcState, 1);
+                    pw.print(':');
+                    pw.print(duration);
+                }
+            }
+            pw.println();
+        }
+    }
+
+    public void writeToProto(ProtoOutputStream proto, long fieldId, long now) {
+        final long token = proto.start(fieldId);
+
+        proto.write(ProcessStatsAssociationStateProto.COMPONENT_NAME, mName);
+        final int NSRC = mSources.size();
+        for (int isrc = 0; isrc < NSRC; isrc++) {
+            final SourceKey key = mSources.keyAt(isrc);
+            final SourceState src = mSources.valueAt(isrc);
+            final long sourceToken = proto.start(ProcessStatsAssociationStateProto.SOURCES);
+            proto.write(ProcessStatsAssociationStateProto.Source.PROCESS, key.mProcess);
+            proto.write(ProcessStatsAssociationStateProto.Source.UID, key.mUid);
+            proto.write(ProcessStatsAssociationStateProto.Source.TOTAL_COUNT, src.mCount);
+            long duration = src.mDuration;
+            if (src.mNesting > 0) {
+                duration += now - src.mStartUptime;
+            }
+            proto.write(ProcessStatsAssociationStateProto.Source.TOTAL_DURATION_MS, duration);
+            if (src.mActiveCount != 0) {
+                proto.write(ProcessStatsAssociationStateProto.Source.ACTIVE_COUNT,
+                        src.mActiveCount);
+            }
+            final long timeNow = src.mActiveStartUptime != 0 ? (now-src.mActiveStartUptime) : 0;
+            if (src.mDurations != null) {
+                final int N = src.mDurations.getKeyCount();
+                for (int i=0; i<N; i++) {
+                    final int dkey = src.mDurations.getKeyAt(i);
+                    duration = src.mDurations.getValue(dkey);
+                    if (dkey == src.mActiveProcState) {
+                        duration += timeNow;
+                    }
+                    final int procState = SparseMappingTable.getIdFromKey(dkey);
+                    DumpUtils.printProcStateDurationProto(proto,
+                            ProcessStatsAssociationStateProto.Source.ACTIVE_STATES,
+                            procState, duration);
+                }
+            } else {
+                duration = src.mActiveDuration + timeNow;
+                if (duration != 0) {
+                    DumpUtils.printProcStateDurationProto(proto,
+                            ProcessStatsAssociationStateProto.Source.ACTIVE_STATES,
+                            src.mActiveProcState, duration);
+                }
+            }
+            proto.end(sourceToken);
+        }
+
+        proto.end(token);
+    }
+
+    public String toString() {
+        return "AssociationState{" + Integer.toHexString(System.identityHashCode(this))
+                + " " + mName + " pkg=" + mPackageState.mPackageName + " proc="
+                + Integer.toHexString(System.identityHashCode(mProc)) + "}";
+    }
+}
diff --git a/core/java/com/android/internal/app/procstats/DumpUtils.java b/core/java/com/android/internal/app/procstats/DumpUtils.java
index e38a844..701391d 100644
--- a/core/java/com/android/internal/app/procstats/DumpUtils.java
+++ b/core/java/com/android/internal/app/procstats/DumpUtils.java
@@ -16,38 +16,24 @@
 
 package com.android.internal.app.procstats;
 
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.service.procstats.ProcessStatsProto;
-import android.text.format.DateFormat;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.DebugUtils;
-import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
+import android.service.procstats.ProcessStatsStateProto;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
 import static com.android.internal.app.procstats.ProcessStats.*;
 
-import java.io.IOException;
-import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Objects;
 
 /**
  * Utilities for dumping.
  */
 public final class DumpUtils {
     public static final String[] STATE_NAMES;
+    public static final String[] STATE_LABELS;
+    public static final String STATE_LABEL_TOTAL;
+    public static final String STATE_LABEL_CACHED;
     public static final String[] STATE_NAMES_CSV;
     static final String[] STATE_TAGS;
     static final int[] STATE_PROTO_ENUMS;
@@ -55,68 +41,86 @@
     // Make the mapping easy to update.
     static {
         STATE_NAMES = new String[STATE_COUNT];
-        STATE_NAMES[STATE_PERSISTENT] = "Persist";
-        STATE_NAMES[STATE_TOP] = "Top";
-        STATE_NAMES[STATE_IMPORTANT_FOREGROUND] = "ImpFg";
-        STATE_NAMES[STATE_IMPORTANT_BACKGROUND] = "ImpBg";
-        STATE_NAMES[STATE_BACKUP] = "Backup";
-        STATE_NAMES[STATE_SERVICE] = "Service";
-        STATE_NAMES[STATE_SERVICE_RESTARTING] = "ServRst";
-        STATE_NAMES[STATE_RECEIVER] = "Receivr";
-        STATE_NAMES[STATE_HEAVY_WEIGHT] = "HeavyWt";
-        STATE_NAMES[STATE_HOME] = "Home";
-        STATE_NAMES[STATE_LAST_ACTIVITY] = "LastAct";
-        STATE_NAMES[STATE_CACHED_ACTIVITY] = "CchAct";
-        STATE_NAMES[STATE_CACHED_ACTIVITY_CLIENT] = "CchCAct";
-        STATE_NAMES[STATE_CACHED_EMPTY] = "CchEmty";
+        STATE_NAMES[STATE_PERSISTENT]               = "Persist";
+        STATE_NAMES[STATE_TOP]                      = "Top";
+        STATE_NAMES[STATE_IMPORTANT_FOREGROUND]     = "ImpFg";
+        STATE_NAMES[STATE_IMPORTANT_BACKGROUND]     = "ImpBg";
+        STATE_NAMES[STATE_BACKUP]                   = "Backup";
+        STATE_NAMES[STATE_SERVICE]                  = "Service";
+        STATE_NAMES[STATE_SERVICE_RESTARTING]       = "ServRst";
+        STATE_NAMES[STATE_RECEIVER]                 = "Receivr";
+        STATE_NAMES[STATE_HEAVY_WEIGHT]             = "HeavyWt";
+        STATE_NAMES[STATE_HOME]                     = "Home";
+        STATE_NAMES[STATE_LAST_ACTIVITY]            = "LastAct";
+        STATE_NAMES[STATE_CACHED_ACTIVITY]          = "CchAct";
+        STATE_NAMES[STATE_CACHED_ACTIVITY_CLIENT]   = "CchCAct";
+        STATE_NAMES[STATE_CACHED_EMPTY]             = "CchEmty";
+
+        STATE_LABELS = new String[STATE_COUNT];
+        STATE_LABELS[STATE_PERSISTENT]              = "Persistent";
+        STATE_LABELS[STATE_TOP]                     = "       Top";
+        STATE_LABELS[STATE_IMPORTANT_FOREGROUND]    = "    Imp Fg";
+        STATE_LABELS[STATE_IMPORTANT_BACKGROUND]    = "    Imp Bg";
+        STATE_LABELS[STATE_BACKUP]                  = "    Backup";
+        STATE_LABELS[STATE_SERVICE]                 = "   Service";
+        STATE_LABELS[STATE_SERVICE_RESTARTING]      = "Service Rs";
+        STATE_LABELS[STATE_RECEIVER]                = "  Receiver";
+        STATE_LABELS[STATE_HEAVY_WEIGHT]            = " Heavy Wgt";
+        STATE_LABELS[STATE_HOME]                    = "    (Home)";
+        STATE_LABELS[STATE_LAST_ACTIVITY]           = "(Last Act)";
+        STATE_LABELS[STATE_CACHED_ACTIVITY]         = " (Cch Act)";
+        STATE_LABELS[STATE_CACHED_ACTIVITY_CLIENT]  = "(Cch CAct)";
+        STATE_LABELS[STATE_CACHED_EMPTY]            = "(Cch Emty)";
+        STATE_LABEL_CACHED                          = "  (Cached)";
+        STATE_LABEL_TOTAL                           = "     TOTAL";
 
         STATE_NAMES_CSV = new String[STATE_COUNT];
-        STATE_NAMES_CSV[STATE_PERSISTENT] = "pers";
-        STATE_NAMES_CSV[STATE_TOP] = "top";
-        STATE_NAMES_CSV[STATE_IMPORTANT_FOREGROUND] = "impfg";
-        STATE_NAMES_CSV[STATE_IMPORTANT_BACKGROUND] = "impbg";
-        STATE_NAMES_CSV[STATE_BACKUP] = "backup";
-        STATE_NAMES_CSV[STATE_SERVICE] = "service";
-        STATE_NAMES_CSV[STATE_SERVICE_RESTARTING] = "service-rs";
-        STATE_NAMES_CSV[STATE_RECEIVER] = "receiver";
-        STATE_NAMES_CSV[STATE_HEAVY_WEIGHT] = "heavy";
-        STATE_NAMES_CSV[STATE_HOME] = "home";
-        STATE_NAMES_CSV[STATE_LAST_ACTIVITY] = "lastact";
-        STATE_NAMES_CSV[STATE_CACHED_ACTIVITY] = "cch-activity";
-        STATE_NAMES_CSV[STATE_CACHED_ACTIVITY_CLIENT] = "cch-aclient";
-        STATE_NAMES_CSV[STATE_CACHED_EMPTY] = "cch-empty";
+        STATE_NAMES_CSV[STATE_PERSISTENT]               = "pers";
+        STATE_NAMES_CSV[STATE_TOP]                      = "top";
+        STATE_NAMES_CSV[STATE_IMPORTANT_FOREGROUND]     = "impfg";
+        STATE_NAMES_CSV[STATE_IMPORTANT_BACKGROUND]     = "impbg";
+        STATE_NAMES_CSV[STATE_BACKUP]                   = "backup";
+        STATE_NAMES_CSV[STATE_SERVICE]                  = "service";
+        STATE_NAMES_CSV[STATE_SERVICE_RESTARTING]       = "service-rs";
+        STATE_NAMES_CSV[STATE_RECEIVER]                 = "receiver";
+        STATE_NAMES_CSV[STATE_HEAVY_WEIGHT]             = "heavy";
+        STATE_NAMES_CSV[STATE_HOME]                     = "home";
+        STATE_NAMES_CSV[STATE_LAST_ACTIVITY]            = "lastact";
+        STATE_NAMES_CSV[STATE_CACHED_ACTIVITY]          = "cch-activity";
+        STATE_NAMES_CSV[STATE_CACHED_ACTIVITY_CLIENT]   = "cch-aclient";
+        STATE_NAMES_CSV[STATE_CACHED_EMPTY]             = "cch-empty";
 
         STATE_TAGS = new String[STATE_COUNT];
-        STATE_TAGS[STATE_PERSISTENT] = "p";
-        STATE_TAGS[STATE_TOP] = "t";
-        STATE_TAGS[STATE_IMPORTANT_FOREGROUND] = "f";
-        STATE_TAGS[STATE_IMPORTANT_BACKGROUND] = "b";
-        STATE_TAGS[STATE_BACKUP] = "u";
-        STATE_TAGS[STATE_SERVICE] = "s";
-        STATE_TAGS[STATE_SERVICE_RESTARTING] = "x";
-        STATE_TAGS[STATE_RECEIVER] = "r";
-        STATE_TAGS[STATE_HEAVY_WEIGHT] = "w";
-        STATE_TAGS[STATE_HOME] = "h";
-        STATE_TAGS[STATE_LAST_ACTIVITY] = "l";
-        STATE_TAGS[STATE_CACHED_ACTIVITY] = "a";
-        STATE_TAGS[STATE_CACHED_ACTIVITY_CLIENT] = "c";
-        STATE_TAGS[STATE_CACHED_EMPTY] = "e";
+        STATE_TAGS[STATE_PERSISTENT]                = "p";
+        STATE_TAGS[STATE_TOP]                       = "t";
+        STATE_TAGS[STATE_IMPORTANT_FOREGROUND]      = "f";
+        STATE_TAGS[STATE_IMPORTANT_BACKGROUND]      = "b";
+        STATE_TAGS[STATE_BACKUP]                    = "u";
+        STATE_TAGS[STATE_SERVICE]                   = "s";
+        STATE_TAGS[STATE_SERVICE_RESTARTING]        = "x";
+        STATE_TAGS[STATE_RECEIVER]                  = "r";
+        STATE_TAGS[STATE_HEAVY_WEIGHT]              = "w";
+        STATE_TAGS[STATE_HOME]                      = "h";
+        STATE_TAGS[STATE_LAST_ACTIVITY]             = "l";
+        STATE_TAGS[STATE_CACHED_ACTIVITY]           = "a";
+        STATE_TAGS[STATE_CACHED_ACTIVITY_CLIENT]    = "c";
+        STATE_TAGS[STATE_CACHED_EMPTY]              = "e";
 
         STATE_PROTO_ENUMS = new int[STATE_COUNT];
-        STATE_PROTO_ENUMS[STATE_PERSISTENT] = ProcessStatsProto.State.PERSISTENT;
-        STATE_PROTO_ENUMS[STATE_TOP] = ProcessStatsProto.State.TOP;
-        STATE_PROTO_ENUMS[STATE_IMPORTANT_FOREGROUND] = ProcessStatsProto.State.IMPORTANT_FOREGROUND;
-        STATE_PROTO_ENUMS[STATE_IMPORTANT_BACKGROUND] = ProcessStatsProto.State.IMPORTANT_BACKGROUND;
-        STATE_PROTO_ENUMS[STATE_BACKUP] = ProcessStatsProto.State.BACKUP;
-        STATE_PROTO_ENUMS[STATE_SERVICE] = ProcessStatsProto.State.SERVICE;
-        STATE_PROTO_ENUMS[STATE_SERVICE_RESTARTING] = ProcessStatsProto.State.SERVICE_RESTARTING;
-        STATE_PROTO_ENUMS[STATE_RECEIVER] = ProcessStatsProto.State.RECEIVER;
-        STATE_PROTO_ENUMS[STATE_HEAVY_WEIGHT] = ProcessStatsProto.State.HEAVY_WEIGHT;
-        STATE_PROTO_ENUMS[STATE_HOME] = ProcessStatsProto.State.HOME;
-        STATE_PROTO_ENUMS[STATE_LAST_ACTIVITY] = ProcessStatsProto.State.LAST_ACTIVITY;
-        STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY] = ProcessStatsProto.State.CACHED_ACTIVITY;
-        STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY_CLIENT] = ProcessStatsProto.State.CACHED_ACTIVITY_CLIENT;
-        STATE_PROTO_ENUMS[STATE_CACHED_EMPTY] = ProcessStatsProto.State.CACHED_EMPTY;
+        STATE_PROTO_ENUMS[STATE_PERSISTENT] = ProcessStatsStateProto.PERSISTENT;
+        STATE_PROTO_ENUMS[STATE_TOP] = ProcessStatsStateProto.TOP;
+        STATE_PROTO_ENUMS[STATE_IMPORTANT_FOREGROUND] = ProcessStatsStateProto.IMPORTANT_FOREGROUND;
+        STATE_PROTO_ENUMS[STATE_IMPORTANT_BACKGROUND] = ProcessStatsStateProto.IMPORTANT_BACKGROUND;
+        STATE_PROTO_ENUMS[STATE_BACKUP] = ProcessStatsStateProto.BACKUP;
+        STATE_PROTO_ENUMS[STATE_SERVICE] = ProcessStatsStateProto.SERVICE;
+        STATE_PROTO_ENUMS[STATE_SERVICE_RESTARTING] = ProcessStatsStateProto.SERVICE_RESTARTING;
+        STATE_PROTO_ENUMS[STATE_RECEIVER] = ProcessStatsStateProto.RECEIVER;
+        STATE_PROTO_ENUMS[STATE_HEAVY_WEIGHT] = ProcessStatsStateProto.HEAVY_WEIGHT;
+        STATE_PROTO_ENUMS[STATE_HOME] = ProcessStatsStateProto.HOME;
+        STATE_PROTO_ENUMS[STATE_LAST_ACTIVITY] = ProcessStatsStateProto.LAST_ACTIVITY;
+        STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY] = ProcessStatsStateProto.CACHED_ACTIVITY;
+        STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY_CLIENT] = ProcessStatsStateProto.CACHED_ACTIVITY_CLIENT;
+        STATE_PROTO_ENUMS[STATE_CACHED_EMPTY] = ProcessStatsStateProto.CACHED_EMPTY;
     }
 
     public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
@@ -134,8 +138,8 @@
     };
 
     static final int[] ADJ_SCREEN_PROTO_ENUMS = new int[] {
-            ProcessStatsProto.State.OFF,
-            ProcessStatsProto.State.ON
+            ProcessStatsStateProto.OFF,
+            ProcessStatsStateProto.ON
     };
 
     static final String[] ADJ_MEM_TAGS = new String[] {
@@ -143,10 +147,10 @@
     };
 
     static final int[] ADJ_MEM_PROTO_ENUMS = new int[] {
-            ProcessStatsProto.State.NORMAL,
-            ProcessStatsProto.State.MODERATE,
-            ProcessStatsProto.State.LOW,
-            ProcessStatsProto.State.CRITICAL
+            ProcessStatsStateProto.NORMAL,
+            ProcessStatsStateProto.MODERATE,
+            ProcessStatsStateProto.LOW,
+            ProcessStatsStateProto.CRITICAL
     };
 
     static final String CSV_SEP = "\t";
@@ -166,7 +170,7 @@
                 pw.print("SOff/");
                 break;
             case ADJ_SCREEN_ON:
-                pw.print("SOn /");
+                pw.print(" SOn/");
                 break;
             default:
                 pw.print("????/");
@@ -201,11 +205,11 @@
                 if (sep != 0) pw.print(sep);
                 break;
             case ADJ_MEM_FACTOR_MODERATE:
-                pw.print("Mod ");
+                pw.print(" Mod");
                 if (sep != 0) pw.print(sep);
                 break;
             case ADJ_MEM_FACTOR_LOW:
-                pw.print("Low ");
+                pw.print(" Low");
                 if (sep != 0) pw.print(sep);
                 break;
             case ADJ_MEM_FACTOR_CRITICAL:
@@ -260,6 +264,23 @@
         printArrayEntry(pw, ADJ_MEM_TAGS, state, 1);
     }
 
+    public static void printProcStateAdjTagProto(ProtoOutputStream proto, long screenId, long memId,
+            int state) {
+        state = printProto(proto, screenId, ADJ_SCREEN_PROTO_ENUMS,
+                state, ADJ_SCREEN_MOD * STATE_COUNT);
+        printProto(proto, memId, ADJ_MEM_PROTO_ENUMS, state, STATE_COUNT);
+    }
+
+    public static void printProcStateDurationProto(ProtoOutputStream proto, long fieldId,
+            int procState, long duration) {
+        final long stateToken = proto.start(fieldId);
+        DumpUtils.printProto(proto, ProcessStatsStateProto.PROCESS_STATE,
+                DumpUtils.STATE_PROTO_ENUMS, procState, 1);
+        proto.write(ProcessStatsStateProto.DURATION_MS, duration);
+        proto.end(stateToken);
+
+    }
+
     public static void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
         pw.print(',');
         printProcStateTag(pw, state);
@@ -362,12 +383,13 @@
         }
     }
 
-    public static void dumpProcessSummaryLocked(PrintWriter pw, String prefix,
+    public static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, String header,
             ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates,
             long now, long totalTime) {
         for (int i=procs.size()-1; i>=0; i--) {
             final ProcessState proc = procs.get(i);
-            proc.dumpSummary(pw, prefix, screenStates, memStates, procStates, now, totalTime);
+            proc.dumpSummary(pw, prefix, header, screenStates, memStates, procStates, now,
+                    totalTime);
         }
     }
 
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 65bd48f..d7f4736 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -20,11 +20,13 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.procstats.ProcessStatsProto;
+import android.service.procstats.ProcessStatsStateProto;
 import android.util.ArrayMap;
 import android.util.DebugUtils;
 import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Slog;
+import android.util.SparseLongArray;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
@@ -62,8 +64,6 @@
 
 import java.io.PrintWriter;
 import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
 
 public final class ProcessState {
     private static final String TAG = "ProcessStats";
@@ -71,7 +71,7 @@
     private static final boolean DEBUG_PARCEL = false;
 
     // Map from process states to the states we track.
-    private static final int[] PROCESS_STATE_TO_STATE = new int[] {
+    static final int[] PROCESS_STATE_TO_STATE = new int[] {
         STATE_PERSISTENT,               // ActivityManager.PROCESS_STATE_PERSISTENT
         STATE_PERSISTENT,               // ActivityManager.PROCESS_STATE_PERSISTENT_UI
         STATE_TOP,                      // ActivityManager.PROCESS_STATE_TOP
@@ -127,14 +127,18 @@
     private final long mVersion;
     private final DurationsTable mDurations;
     private final PssTable mPssTable;
+    private final long[] mTotalRunningPss = new long[ProcessStats.PSS_COUNT];
 
     private ProcessState mCommonProcess;
-    private int mCurState = STATE_NOTHING;
+    private int mCurCombinedState = STATE_NOTHING;
     private long mStartTime;
 
     private int mLastPssState = STATE_NOTHING;
     private long mLastPssTime;
 
+    private long mTotalRunningStartTime;
+    private long mTotalRunningDuration;
+
     private boolean mActive;
     private int mNumActiveServices;
     private int mNumStartedServices;
@@ -180,8 +184,11 @@
         mPackage = pkg;
         mUid = uid;
         mVersion = vers;
-        mCurState = commonProcess.mCurState;
+        mCurCombinedState = commonProcess.mCurCombinedState;
         mStartTime = now;
+        if (mCurCombinedState != STATE_NOTHING) {
+            mTotalRunningStartTime = now;
+        }
         mDurations = new DurationsTable(commonProcess.mStats.mTableData);
         mPssTable = new PssTable(commonProcess.mStats.mTableData);
     }
@@ -190,6 +197,8 @@
         ProcessState pnew = new ProcessState(this, mPackage, mUid, mVersion, mName, now);
         pnew.mDurations.addDurations(mDurations);
         pnew.mPssTable.copyFrom(mPssTable, PSS_COUNT);
+        System.arraycopy(mTotalRunningPss, 0, pnew.mTotalRunningPss, 0, ProcessStats.PSS_COUNT);
+        pnew.mTotalRunningDuration = getTotalRunningDuration(now);
         pnew.mNumExcessiveCpu = mNumExcessiveCpu;
         pnew.mNumCachedKill = mNumCachedKill;
         pnew.mMinCachedKillPss = mMinCachedKillPss;
@@ -235,7 +244,7 @@
     public void setMultiPackage(boolean val) {
         mMultiPackage = val;
     }
-    
+
     public int getDurationsBucketCount() {
         return mDurations.getKeyCount();
     }
@@ -243,6 +252,10 @@
     public void add(ProcessState other) {
         mDurations.addDurations(other.mDurations);
         mPssTable.mergeStats(other.mPssTable);
+        // Note that we don't touch mTotalRunningPss, because in current use
+        // 'other' is older stats that are being added in to these newer ones.
+        // So the newer ones keep track of the total running time, which is always
+        // the right thing over whatever was in older stats.
         mNumExcessiveCpu += other.mNumExcessiveCpu;
         if (other.mNumCachedKill > 0) {
             addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss,
@@ -277,6 +290,10 @@
         out.writeInt(mMultiPackage ? 1 : 0);
         mDurations.writeToParcel(out);
         mPssTable.writeToParcel(out);
+        for (int i = 0; i < ProcessStats.PSS_COUNT; i++) {
+            out.writeLong(mTotalRunningPss[i]);
+        }
+        out.writeLong(getTotalRunningDuration(now));
         out.writeInt(0);  // was mNumExcessiveWake
         out.writeInt(mNumExcessiveCpu);
         out.writeInt(mNumCachedKill);
@@ -300,6 +317,10 @@
         if (!mPssTable.readFromParcel(in)) {
             return false;
         }
+        for (int i = 0; i < ProcessStats.PSS_COUNT; i++) {
+            mTotalRunningPss[i] = in.readLong();
+        }
+        mTotalRunningDuration = in.readLong();
         in.readInt(); // was mNumExcessiveWake
         mNumExcessiveCpu = in.readInt();
         mNumCachedKill = in.readInt();
@@ -324,7 +345,7 @@
 
     public boolean isInUse() {
         return mActive || mNumActiveServices > 0 || mNumStartedServices > 0
-                || mCurState != STATE_NOTHING;
+                || mCurCombinedState != STATE_NOTHING;
     }
 
     public boolean isActive() {
@@ -333,8 +354,9 @@
 
     public boolean hasAnyData() {
         return !(mDurations.getKeyCount() == 0
-                && mCurState == STATE_NOTHING
-                && mPssTable.getKeyCount() == 0);
+                && mCurCombinedState == STATE_NOTHING
+                && mPssTable.getKeyCount() == 0
+                && mTotalRunningPss[PSS_SAMPLE_COUNT] == 0);
     }
 
     /**
@@ -355,7 +377,7 @@
         }
 
         // First update the common process.
-        mCommonProcess.setState(state, now);
+        mCommonProcess.setCombinedState(state, now);
 
         // If the common process is not multi-package, there is nothing else to do.
         if (!mCommonProcess.mMultiPackage) {
@@ -364,26 +386,45 @@
 
         if (pkgList != null) {
             for (int ip=pkgList.size()-1; ip>=0; ip--) {
-                pullFixedProc(pkgList, ip).setState(state, now);
+                pullFixedProc(pkgList, ip).setCombinedState(state, now);
             }
         }
     }
 
-    public void setState(int state, long now) {
+    public void setCombinedState(int state, long now) {
         ensureNotDead();
-        if (!mDead && (mCurState != state)) {
+        if (!mDead && (mCurCombinedState != state)) {
             //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
             commitStateTime(now);
-            mCurState = state;
+            if (state == STATE_NOTHING) {
+                // We are transitioning to a no longer running state... stop counting run time.
+                mTotalRunningDuration += now - mTotalRunningStartTime;
+                mTotalRunningStartTime = 0;
+            } else if (mCurCombinedState == STATE_NOTHING) {
+                // We previously weren't running...  now starting again, clear out total
+                // running info.
+                mTotalRunningDuration = 0;
+                mTotalRunningStartTime = now;
+                for (int i = ProcessStats.PSS_COUNT - 1; i >= 0; i--) {
+                    mTotalRunningPss[i] = 0;
+                }
+            }
+            mCurCombinedState = state;
         }
     }
 
+    public int getCombinedState() {
+        return mCurCombinedState;
+    }
+
     public void commitStateTime(long now) {
-        if (mCurState != STATE_NOTHING) {
+        if (mCurCombinedState != STATE_NOTHING) {
             long dur = now - mStartTime;
             if (dur > 0) {
-                mDurations.addDuration(mCurState, dur);
+                mDurations.addDuration(mCurCombinedState, dur);
             }
+            mTotalRunningDuration += now - mTotalRunningStartTime;
+            mTotalRunningStartTime = now;
         }
         mStartTime = now;
     }
@@ -430,8 +471,8 @@
             mCommonProcess.incStartedServices(memFactor, now, serviceName);
         }
         mNumStartedServices++;
-        if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) {
-            setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
+        if (mNumStartedServices == 1 && mCurCombinedState == STATE_NOTHING) {
+            setCombinedState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
         }
     }
 
@@ -446,8 +487,8 @@
             mCommonProcess.decStartedServices(memFactor, now, serviceName);
         }
         mNumStartedServices--;
-        if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
-            setState(STATE_NOTHING, now);
+        if (mNumStartedServices == 0 && (mCurCombinedState %STATE_COUNT) == STATE_SERVICE_RESTARTING) {
+            setCombinedState(STATE_NOTHING, now);
         } else if (mNumStartedServices < 0) {
             Slog.wtfStack(TAG, "Proc started services underrun: pkg="
                     + mPackage + " uid=" + mUid + " name=" + mName);
@@ -481,16 +522,18 @@
                 break;
         }
         if (!always) {
-            if (mLastPssState == mCurState && SystemClock.uptimeMillis()
+            if (mLastPssState == mCurCombinedState && SystemClock.uptimeMillis()
                     < (mLastPssTime+(30*1000))) {
                 return;
             }
         }
-        mLastPssState = mCurState;
+        mLastPssState = mCurCombinedState;
         mLastPssTime = SystemClock.uptimeMillis();
-        if (mCurState != STATE_NOTHING) {
+        if (mCurCombinedState != STATE_NOTHING) {
             // First update the common process.
-            mCommonProcess.mPssTable.mergeStats(mCurState, 1, pss, pss, pss, uss, uss, uss,
+            mCommonProcess.mPssTable.mergeStats(mCurCombinedState, 1, pss, pss, pss, uss, uss, uss,
+                    rss, rss, rss);
+            PssTable.mergeStats(mCommonProcess.mTotalRunningPss, 0, 1, pss, pss, pss, uss, uss, uss,
                     rss, rss, rss);
 
             // If the common process is not multi-package, there is nothing else to do.
@@ -500,7 +543,10 @@
 
             if (pkgList != null) {
                 for (int ip=pkgList.size()-1; ip>=0; ip--) {
-                    pullFixedProc(pkgList, ip).mPssTable.mergeStats(mCurState, 1,
+                    ProcessState fixedProc = pullFixedProc(pkgList, ip);
+                    fixedProc.mPssTable.mergeStats(mCurCombinedState, 1,
+                            pss, pss, pss, uss, uss, uss, rss, rss, rss);
+                    PssTable.mergeStats(fixedProc.mTotalRunningPss, 0, 1,
                             pss, pss, pss, uss, uss, uss, rss, rss, rss);
                 }
             }
@@ -580,7 +626,7 @@
         ProcessStateHolder holder = pkgList.valueAt(index);
         ProcessState proc = holder.state;
         if (mDead && proc.mCommonProcess != proc) {
-            // Somehow we are contining to use a process state that is dead, because
+            // Somehow we are continuing to use a process state that is dead, because
             // it was not being told it was active during the last commit.  We can recover
             // from this by generating a fresh new state, but this is bad because we
             // are losing whatever data we had in the old process state.
@@ -600,26 +646,31 @@
                         + pkgList.keyAt(index) + "/" + proc.mUid
                         + " for multi-proc " + proc.mName);
             }
-            PackageState pkg = vpkg.get(proc.mVersion);
-            if (pkg == null) {
+            PackageState expkg = vpkg.get(proc.mVersion);
+            if (expkg == null) {
                 throw new IllegalStateException("No existing package "
                         + pkgList.keyAt(index) + "/" + proc.mUid
                         + " for multi-proc " + proc.mName + " version " + proc.mVersion);
             }
             String savedName = proc.mName;
-            proc = pkg.mProcesses.get(proc.mName);
+            proc = expkg.mProcesses.get(proc.mName);
             if (proc == null) {
                 throw new IllegalStateException("Didn't create per-package process "
-                        + savedName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid);
+                        + savedName + " in pkg " + expkg.mPackageName + "/" + expkg.mUid);
             }
             holder.state = proc;
         }
         return proc;
     }
 
+    public long getTotalRunningDuration(long now) {
+        return mTotalRunningDuration +
+                (mTotalRunningStartTime != 0 ? (now - mTotalRunningStartTime) : 0);
+    }
+
     public long getDuration(int state, long now) {
         long time = mDurations.getValueForId((byte)state);
-        if (mCurState == state) {
+        if (mCurCombinedState == state) {
             time += now - mStartTime;
         }
         return time;
@@ -667,7 +718,7 @@
 
     /**
      * Sums up the PSS data and adds it to 'data'.
-     * 
+     *
      * @param data The aggregate data is added here.
      * @param now SystemClock.uptimeMillis()
      */
@@ -724,7 +775,7 @@
             final int key = mDurations.getKeyAt(i);
             final int type = SparseMappingTable.getIdFromKey(key);
             long time = mDurations.getValue(key);
-            if (mCurState == type) {
+            if (mCurCombinedState == type) {
                 time += now - mStartTime;
             }
             final int procState = type % STATE_COUNT;
@@ -769,46 +820,50 @@
         return totalTime;
     }
 
-    public void dumpSummary(PrintWriter pw, String prefix,
+    public void dumpSummary(PrintWriter pw, String prefix, String header,
             int[] screenStates, int[] memStates, int[] procStates,
             long now, long totalTime) {
         pw.print(prefix);
         pw.print("* ");
+        if (header != null) {
+            pw.print(header);
+        }
         pw.print(mName);
         pw.print(" / ");
         UserHandle.formatUid(pw, mUid);
         pw.print(" / v");
         pw.print(mVersion);
         pw.println(":");
-        dumpProcessSummaryDetails(pw, prefix, "         TOTAL: ", screenStates, memStates,
-                procStates, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "    Persistent: ", screenStates, memStates,
-                new int[] { STATE_PERSISTENT }, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "           Top: ", screenStates, memStates,
-                new int[] {STATE_TOP}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "        Imp Fg: ", screenStates, memStates,
-                new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "        Imp Bg: ", screenStates, memStates,
-                new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "        Backup: ", screenStates, memStates,
-                new int[] {STATE_BACKUP}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "     Heavy Wgt: ", screenStates, memStates,
-                new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "       Service: ", screenStates, memStates,
-                new int[] {STATE_SERVICE}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "    Service Rs: ", screenStates, memStates,
-                new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "      Receiver: ", screenStates, memStates,
-                new int[] {STATE_RECEIVER}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "         Heavy: ", screenStates, memStates,
-                new int[] {STATE_HOME}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "        (Home): ", screenStates, memStates,
-                new int[] {STATE_HOME}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "    (Last Act): ", screenStates, memStates,
-                new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true);
-        dumpProcessSummaryDetails(pw, prefix, "      (Cached): ", screenStates, memStates,
-                new int[] {STATE_CACHED_ACTIVITY, STATE_CACHED_ACTIVITY_CLIENT,
-                        STATE_CACHED_EMPTY}, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABEL_TOTAL,
+                screenStates, memStates, procStates, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_PERSISTENT],
+                screenStates, memStates, new int[] { STATE_PERSISTENT }, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_TOP],
+                screenStates, memStates, new int[] {STATE_TOP}, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_IMPORTANT_FOREGROUND],
+                screenStates, memStates, new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime,
+                true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_IMPORTANT_BACKGROUND],
+                screenStates, memStates, new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime,
+                true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_BACKUP],
+                screenStates, memStates, new int[] {STATE_BACKUP}, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_SERVICE],
+                screenStates, memStates, new int[] {STATE_SERVICE}, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_SERVICE_RESTARTING],
+                screenStates, memStates, new int[] {STATE_SERVICE_RESTARTING}, now, totalTime,
+                true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_RECEIVER],
+                screenStates, memStates, new int[] {STATE_RECEIVER}, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_HEAVY_WEIGHT],
+                screenStates, memStates, new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_HOME],
+                screenStates, memStates, new int[] {STATE_HOME}, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABELS[STATE_LAST_ACTIVITY],
+                screenStates, memStates, new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true);
+        dumpProcessSummaryDetails(pw, prefix, DumpUtils.STATE_LABEL_CACHED,
+                screenStates, memStates, new int[] {STATE_CACHED_ACTIVITY,
+                        STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY}, now, totalTime, true);
     }
 
     public void dumpProcessState(PrintWriter pw, String prefix,
@@ -824,8 +879,9 @@
                     final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
                     long time = mDurations.getValueForId((byte)bucket);
                     String running = "";
-                    if (mCurState == bucket) {
+                    if (mCurCombinedState == bucket) {
                         running = " (running)";
+                        time += now - mStartTime;
                     }
                     if (time != 0) {
                         pw.print(prefix);
@@ -839,7 +895,7 @@
                                     printedMem != imem ? imem : STATE_NOTHING, '/');
                             printedMem = imem;
                         }
-                        pw.print(DumpUtils.STATE_NAMES[procStates[ip]]); pw.print(": ");
+                        pw.print(DumpUtils.STATE_LABELS[procStates[ip]]); pw.print(": ");
                         TimeUtils.formatDuration(time, pw); pw.println(running);
                         totalTime += time;
                     }
@@ -854,14 +910,15 @@
             if (memStates.length > 1) {
                 DumpUtils.printMemLabel(pw, STATE_NOTHING, '/');
             }
-            pw.print("TOTAL  : ");
+            pw.print(DumpUtils.STATE_LABEL_TOTAL);
+            pw.print(": ");
             TimeUtils.formatDuration(totalTime, pw);
             pw.println();
         }
     }
 
     public void dumpPss(PrintWriter pw, String prefix,
-            int[] screenStates, int[] memStates, int[] procStates) {
+            int[] screenStates, int[] memStates, int[] procStates, long now) {
         boolean printedHeader = false;
         int printedScreen = -1;
         for (int is=0; is<screenStates.length; is++) {
@@ -871,52 +928,51 @@
                     final int iscreen = screenStates[is];
                     final int imem = memStates[im];
                     final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
-                    long count = getPssSampleCount(bucket);
-                    if (count > 0) {
-                        if (!printedHeader) {
-                            pw.print(prefix);
-                            pw.print("PSS/USS (");
-                            pw.print(mPssTable.getKeyCount());
-                            pw.println(" entries):");
-                            printedHeader = true;
-                        }
-                        pw.print(prefix);
-                        pw.print("  ");
-                        if (screenStates.length > 1) {
-                            DumpUtils.printScreenLabel(pw,
-                                    printedScreen != iscreen ? iscreen : STATE_NOTHING);
-                            printedScreen = iscreen;
-                        }
-                        if (memStates.length > 1) {
-                            DumpUtils.printMemLabel(pw,
-                                    printedMem != imem ? imem : STATE_NOTHING, '/');
-                            printedMem = imem;
-                        }
-                        pw.print(DumpUtils.STATE_NAMES[procStates[ip]]); pw.print(": ");
-                        pw.print(count);
-                        pw.print(" samples ");
-                        DebugUtils.printSizeValue(pw, getPssMinimum(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssAverage(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssMaximum(bucket) * 1024);
-                        pw.print(" / ");
-                        DebugUtils.printSizeValue(pw, getPssUssMinimum(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssUssAverage(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssUssMaximum(bucket) * 1024);
-                        pw.print(" / ");
-                        DebugUtils.printSizeValue(pw, getPssRssMinimum(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssRssAverage(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssRssMaximum(bucket) * 1024);
-                        pw.println();
+                    final int key = mPssTable.getKey((byte)bucket);
+                    if (key == SparseMappingTable.INVALID_KEY) {
+                        continue;
                     }
+                    final long[] table = mPssTable.getArrayForKey(key);
+                    final int tableOffset = SparseMappingTable.getIndexFromKey(key);
+                    if (!printedHeader) {
+                        pw.print(prefix);
+                        pw.print("PSS/USS (");
+                        pw.print(mPssTable.getKeyCount());
+                        pw.println(" entries):");
+                        printedHeader = true;
+                    }
+                    pw.print(prefix);
+                    pw.print("  ");
+                    if (screenStates.length > 1) {
+                        DumpUtils.printScreenLabel(pw,
+                                printedScreen != iscreen ? iscreen : STATE_NOTHING);
+                        printedScreen = iscreen;
+                    }
+                    if (memStates.length > 1) {
+                        DumpUtils.printMemLabel(pw,
+                                printedMem != imem ? imem : STATE_NOTHING, '/');
+                        printedMem = imem;
+                    }
+                    pw.print(DumpUtils.STATE_LABELS[procStates[ip]]); pw.print(": ");
+                    dumpPssSamples(pw, table, tableOffset);
+                    pw.println();
                 }
             }
         }
+        final long totalRunningDuration = getTotalRunningDuration(now);
+        if (totalRunningDuration != 0) {
+            pw.print(prefix);
+            pw.print("Cur time ");
+            TimeUtils.formatDuration(totalRunningDuration, pw);
+            if (mTotalRunningStartTime != 0) {
+                pw.print(" (running)");
+            }
+            if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
+                pw.print(": ");
+                dumpPssSamples(pw, mTotalRunningPss, 0);
+            }
+            pw.println();
+        }
         if (mNumExcessiveCpu != 0) {
             pw.print(prefix); pw.print("Killed for excessive CPU use: ");
                     pw.print(mNumExcessiveCpu); pw.println(" times");
@@ -930,6 +986,28 @@
         }
     }
 
+    public static void dumpPssSamples(PrintWriter pw, long[] table, int offset) {
+        DebugUtils.printSizeValue(pw, table[offset + PSS_MINIMUM] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_AVERAGE] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_MAXIMUM] * 1024);
+        pw.print("/");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_USS_MINIMUM] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_USS_AVERAGE] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_USS_MAXIMUM] * 1024);
+        pw.print("/");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_RSS_MINIMUM] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_RSS_AVERAGE] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_RSS_MAXIMUM] * 1024);
+        pw.print(" over ");
+        pw.print(table[offset + PSS_SAMPLE_COUNT]);
+    }
+
     private void dumpProcessSummaryDetails(PrintWriter pw, String prefix,
             String label, int[] screenStates, int[] memStates, int[] procStates,
             long now, long totalTime, boolean full) {
@@ -943,7 +1021,9 @@
                 pw.print(prefix);
             }
             if (label != null) {
+                pw.print("  ");
                 pw.print(label);
+                pw.print(": ");
             }
             totals.print(pw, totalTime, full);
             if (prefix != null) {
@@ -1105,6 +1185,21 @@
             dumpAllPssCheckin(pw);
             pw.println();
         }
+        if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
+            pw.print("pkgrun,");
+            pw.print(pkgName);
+            pw.print(",");
+            pw.print(uid);
+            pw.print(",");
+            pw.print(vers);
+            pw.print(",");
+            pw.print(DumpUtils.collapseString(pkgName, itemName));
+            pw.print(",");
+            pw.print(getTotalRunningDuration(now));
+            pw.print(",");
+            dumpPssSamplesCheckin(pw, mTotalRunningPss, 0);
+            pw.println();
+        }
         if (mNumExcessiveCpu > 0 || mNumCachedKill > 0) {
             pw.print("pkgkills,");
             pw.print(pkgName);
@@ -1147,6 +1242,17 @@
             dumpAllPssCheckin(pw);
             pw.println();
         }
+        if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
+            pw.print("procrun,");
+            pw.print(procName);
+            pw.print(",");
+            pw.print(uid);
+            pw.print(",");
+            pw.print(getTotalRunningDuration(now));
+            pw.print(",");
+            dumpPssSamplesCheckin(pw, mTotalRunningPss, 0);
+            pw.println();
+        }
         if (mNumExcessiveCpu > 0 || mNumCachedKill > 0) {
             pw.print("kills,");
             pw.print(procName);
@@ -1174,14 +1280,14 @@
             final int key = mDurations.getKeyAt(i);
             final int type = SparseMappingTable.getIdFromKey(key);
             long time = mDurations.getValue(key);
-            if (mCurState == type) {
+            if (mCurCombinedState == type) {
                 didCurState = true;
                 time += now - mStartTime;
             }
             DumpUtils.printProcStateTagAndValue(pw, type, time);
         }
-        if (!didCurState && mCurState != STATE_NOTHING) {
-            DumpUtils.printProcStateTagAndValue(pw, mCurState, now - mStartTime);
+        if (!didCurState && mCurCombinedState != STATE_NOTHING) {
+            DumpUtils.printProcStateTagAndValue(pw, mCurCombinedState, now - mStartTime);
         }
     }
 
@@ -1193,28 +1299,33 @@
             pw.print(',');
             DumpUtils.printProcStateTag(pw, type);
             pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_SAMPLE_COUNT));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_MINIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_AVERAGE));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_MAXIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_USS_MINIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_USS_AVERAGE));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_USS_MAXIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_RSS_MINIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_RSS_AVERAGE));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_RSS_MAXIMUM));
+            dumpPssSamplesCheckin(pw, mPssTable.getArrayForKey(key),
+                    SparseMappingTable.getIndexFromKey(key));
         }
     }
 
+    public static void dumpPssSamplesCheckin(PrintWriter pw, long[] table, int offset) {
+        pw.print(table[offset + PSS_SAMPLE_COUNT]);
+        pw.print(':');
+        pw.print(table[offset + PSS_MINIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_AVERAGE]);
+        pw.print(':');
+        pw.print(table[offset + PSS_MAXIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_USS_MINIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_USS_AVERAGE]);
+        pw.print(':');
+        pw.print(table[offset + PSS_USS_MAXIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_RSS_MINIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_RSS_AVERAGE]);
+        pw.print(':');
+        pw.print(table[offset + PSS_RSS_MAXIMUM]);
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
@@ -1242,67 +1353,66 @@
         }
 
         // Group proc stats by type (screen state + mem state + process state)
-        Map<Integer, Long> durationByState = new HashMap<>();
+        SparseLongArray durationByState = new SparseLongArray();
         boolean didCurState = false;
         for (int i=0; i<mDurations.getKeyCount(); i++) {
             final int key = mDurations.getKeyAt(i);
             final int type = SparseMappingTable.getIdFromKey(key);
             long time = mDurations.getValue(key);
-            if (mCurState == type) {
+            if (mCurCombinedState == type) {
                 didCurState = true;
                 time += now - mStartTime;
             }
             durationByState.put(type, time);
         }
-        if (!didCurState && mCurState != STATE_NOTHING) {
-            durationByState.put(mCurState, now - mStartTime);
+        if (!didCurState && mCurCombinedState != STATE_NOTHING) {
+            durationByState.put(mCurCombinedState, now - mStartTime);
         }
 
         for (int i=0; i<mPssTable.getKeyCount(); i++) {
             final int key = mPssTable.getKeyAt(i);
             final int type = SparseMappingTable.getIdFromKey(key);
-            if (!durationByState.containsKey(type)) {
+            if (durationByState.indexOfKey(type) < 0) {
                 // state without duration should not have stats!
                 continue;
             }
             final long stateToken = proto.start(ProcessStatsProto.STATES);
             DumpUtils.printProcStateTagProto(proto,
-                    ProcessStatsProto.State.SCREEN_STATE,
-                    ProcessStatsProto.State.MEMORY_STATE,
-                    ProcessStatsProto.State.PROCESS_STATE,
+                    ProcessStatsStateProto.SCREEN_STATE,
+                    ProcessStatsStateProto.MEMORY_STATE,
+                    ProcessStatsStateProto.PROCESS_STATE,
                     type);
 
             long duration = durationByState.get(type);
-            durationByState.remove(type); // remove the key since it is already being dumped.
-            proto.write(ProcessStatsProto.State.DURATION_MS, duration);
+            durationByState.delete(type); // remove the key since it is already being dumped.
+            proto.write(ProcessStatsStateProto.DURATION_MS, duration);
 
-            proto.write(ProcessStatsProto.State.SAMPLE_SIZE, mPssTable.getValue(key, PSS_SAMPLE_COUNT));
-            ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.PSS,
-                    mPssTable.getValue(key, PSS_MINIMUM),
-                    mPssTable.getValue(key, PSS_AVERAGE),
-                    mPssTable.getValue(key, PSS_MAXIMUM));
-            ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.USS,
-                    mPssTable.getValue(key, PSS_USS_MINIMUM),
-                    mPssTable.getValue(key, PSS_USS_AVERAGE),
-                    mPssTable.getValue(key, PSS_USS_MAXIMUM));
-            ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.RSS,
-                    mPssTable.getValue(key, PSS_RSS_MINIMUM),
-                    mPssTable.getValue(key, PSS_RSS_AVERAGE),
-                    mPssTable.getValue(key, PSS_RSS_MAXIMUM));
+            mPssTable.writeStatsToProtoForKey(proto, key);
 
             proto.end(stateToken);
         }
 
-        for (Map.Entry<Integer, Long> entry : durationByState.entrySet()) {
+        for (int i = 0; i < durationByState.size(); i++) {
             final long stateToken = proto.start(ProcessStatsProto.STATES);
             DumpUtils.printProcStateTagProto(proto,
-                    ProcessStatsProto.State.SCREEN_STATE,
-                    ProcessStatsProto.State.MEMORY_STATE,
-                    ProcessStatsProto.State.PROCESS_STATE,
-                    entry.getKey());
-            proto.write(ProcessStatsProto.State.DURATION_MS, entry.getValue());
+                    ProcessStatsStateProto.SCREEN_STATE,
+                    ProcessStatsStateProto.MEMORY_STATE,
+                    ProcessStatsStateProto.PROCESS_STATE,
+                    durationByState.keyAt(i));
+            proto.write(ProcessStatsStateProto.DURATION_MS, durationByState.valueAt(i));
             proto.end(stateToken);
         }
+
+        final long totalRunningDuration = getTotalRunningDuration(now);
+        if (totalRunningDuration > 0) {
+            final long stateToken = proto.start(ProcessStatsProto.TOTAL_RUNNING_STATE);
+            proto.write(ProcessStatsStateProto.DURATION_MS, totalRunningDuration);
+            if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
+                PssTable.writeStatsToProto(proto, mTotalRunningPss, 0);
+            }
+            proto.end(stateToken);
+        }
+
         proto.end(token);
     }
 }
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index d35bddd..b6624a2 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -16,12 +16,14 @@
 
 package com.android.internal.app.procstats;
 
+import android.content.ComponentName;
 import android.os.Debug;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.service.procstats.ProcessStatsPackageProto;
 import android.service.procstats.ProcessStatsSectionProto;
 import android.text.format.DateFormat;
 import android.util.ArrayMap;
@@ -46,8 +48,8 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Objects;
-import java.util.regex.Pattern;
 import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public final class ProcessStats implements Parcelable {
     public static final String TAG = "ProcessStats";
@@ -157,7 +159,7 @@
     };
 
     // Current version of the parcel format.
-    private static final int PARCEL_VERSION = 27;
+    private static final int PARCEL_VERSION = 34;
     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
     private static final int MAGIC = 0x50535454;
 
@@ -168,6 +170,8 @@
     public final ProcessMap<LongSparseArray<PackageState>> mPackages = new ProcessMap<>();
     public final ProcessMap<ProcessState> mProcesses = new ProcessMap<>();
 
+    public final ArrayList<AssociationState.SourceState> mTrackingAssociations = new ArrayList<>();
+
     public final long[] mMemFactorDurations = new long[ADJ_COUNT];
     public int mMemFactor = STATE_NOTHING;
     public long mStartTime;
@@ -250,6 +254,7 @@
                     final PackageState otherState = versions.valueAt(iv);
                     final int NPROCS = otherState.mProcesses.size();
                     final int NSRVS = otherState.mServices.size();
+                    final int NASCS = otherState.mAssociations.size();
                     for (int iproc=0; iproc<NPROCS; iproc++) {
                         ProcessState otherProc = otherState.mProcesses.valueAt(iproc);
                         if (otherProc.getCommonProcess() != otherProc) {
@@ -277,6 +282,14 @@
                                 otherSvc.getProcessName(), otherSvc.getName());
                         thisSvc.add(otherSvc);
                     }
+                    for (int iasc=0; iasc<NASCS; iasc++) {
+                        AssociationState otherAsc = otherState.mAssociations.valueAt(iasc);
+                        if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
+                                + " association " + otherAsc.getName());
+                        AssociationState thisAsc = getAssociationStateLocked(pkgName, uid, vers,
+                                otherAsc.getProcessName(), otherAsc.getName());
+                        thisAsc.add(otherAsc);
+                    }
                 }
             }
         }
@@ -478,7 +491,16 @@
                             pkgState.mServices.removeAt(isvc);
                         }
                     }
-                    if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) {
+                    for (int iasc=pkgState.mAssociations.size()-1; iasc>=0; iasc--) {
+                        final AssociationState as = pkgState.mAssociations.valueAt(iasc);
+                        if (as.isInUse()) {
+                            as.resetSafely(now);
+                        } else {
+                            pkgState.mAssociations.removeAt(iasc);
+                        }
+                    }
+                    if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0
+                            && pkgState.mAssociations.size() <= 0) {
                         vpkgs.removeAt(iv);
                     }
                 }
@@ -708,7 +730,7 @@
         }
     }
 
-    private void writeCommonString(Parcel out, String name) {
+    void writeCommonString(Parcel out, String name) {
         Integer index = mCommonStringToIndex.get(name);
         if (index != null) {
             out.writeInt(index);
@@ -720,7 +742,7 @@
         out.writeString(name);
     }
 
-    private String readCommonString(Parcel in, int version) {
+    String readCommonString(Parcel in, int version) {
         if (version <= 9) {
             return in.readString();
         }
@@ -791,6 +813,10 @@
                     for (int isvc=0; isvc<NSRVS; isvc++) {
                         pkgState.mServices.valueAt(isvc).commitStateTime(now);
                     }
+                    final int NASCS = pkgState.mAssociations.size();
+                    for (int iasc=0; iasc<NASCS; iasc++) {
+                        pkgState.mAssociations.valueAt(iasc).commitStateTime(now);
+                    }
                 }
             }
         }
@@ -874,6 +900,14 @@
                         writeCommonString(out, svc.getProcessName());
                         svc.writeToParcel(out, now);
                     }
+                    final int NASCS = pkgState.mAssociations.size();
+                    out.writeInt(NASCS);
+                    for (int iasc=0; iasc<NASCS; iasc++) {
+                        writeCommonString(out, pkgState.mAssociations.keyAt(iasc));
+                        final AssociationState asc = pkgState.mAssociations.valueAt(iasc);
+                        writeCommonString(out, asc.getProcessName());
+                        asc.writeToParcel(this, out, now);
+                    }
                 }
             }
         }
@@ -1078,7 +1112,7 @@
                 while (NVERS > 0) {
                     NVERS--;
                     final long vers = in.readLong();
-                    PackageState pkgState = new PackageState(pkgName, uid);
+                    PackageState pkgState = new PackageState(this, pkgName, uid, vers);
                     LongSparseArray<PackageState> vpkg = mPackages.get(pkgName, uid);
                     if (vpkg == null) {
                         vpkg = new LongSparseArray<>();
@@ -1157,6 +1191,34 @@
                                 + serviceName + " " + uid + " " + serv);
                         pkgState.mServices.put(serviceName, serv);
                     }
+                    int NASCS = in.readInt();
+                    if (NASCS < 0) {
+                        mReadError = "bad package association count: " + NASCS;
+                        return;
+                    }
+                    while (NASCS > 0) {
+                        NASCS--;
+                        String associationName = readCommonString(in, version);
+                        if (associationName == null) {
+                            mReadError = "bad package association name";
+                            return;
+                        }
+                        String processName = readCommonString(in, version);
+                        AssociationState asc = hadData
+                                ? pkgState.mAssociations.get(associationName) : null;
+                        if (asc == null) {
+                            asc = new AssociationState(this, pkgState, associationName,
+                                    processName, null);
+                        }
+                        String errorMsg = asc.readFromParcel(this, in, version);
+                        if (errorMsg != null) {
+                            mReadError = errorMsg;
+                            return;
+                        }
+                        if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " association: "
+                                + associationName + " " + uid + " " + asc);
+                        pkgState.mAssociations.put(associationName, asc);
+                    }
                 }
             }
         }
@@ -1183,33 +1245,38 @@
     public PackageState getPackageStateLocked(String packageName, int uid, long vers) {
         LongSparseArray<PackageState> vpkg = mPackages.get(packageName, uid);
         if (vpkg == null) {
-            vpkg = new LongSparseArray<PackageState>();
+            vpkg = new LongSparseArray<>();
             mPackages.put(packageName, uid, vpkg);
         }
         PackageState as = vpkg.get(vers);
         if (as != null) {
             return as;
         }
-        as = new PackageState(packageName, uid);
+        as = new PackageState(this, packageName, uid, vers);
         vpkg.put(vers, as);
         return as;
     }
 
     public ProcessState getProcessStateLocked(String packageName, int uid, long vers,
             String processName) {
-        final PackageState pkgState = getPackageStateLocked(packageName, uid, vers);
+        return getProcessStateLocked(getPackageStateLocked(packageName, uid, vers), processName);
+    }
+
+    public ProcessState getProcessStateLocked(PackageState pkgState, String processName) {
         ProcessState ps = pkgState.mProcesses.get(processName);
         if (ps != null) {
             return ps;
         }
-        ProcessState commonProc = mProcesses.get(processName, uid);
+        ProcessState commonProc = mProcesses.get(processName, pkgState.mUid);
         if (commonProc == null) {
-            commonProc = new ProcessState(this, packageName, uid, vers, processName);
-            mProcesses.put(processName, uid, commonProc);
+            commonProc = new ProcessState(this, pkgState.mPackageName, pkgState.mUid,
+                    pkgState.mVersionCode, processName);
+            mProcesses.put(processName, pkgState.mUid, commonProc);
             if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
         }
         if (!commonProc.isMultiPackage()) {
-            if (packageName.equals(commonProc.getPackage()) && vers == commonProc.getVersion()) {
+            if (pkgState.mPackageName.equals(commonProc.getPackage())
+                    && pkgState.mVersionCode == commonProc.getVersion()) {
                 // This common process is not in use by multiple packages, and
                 // is for the calling package, so we can just use it directly.
                 ps = commonProc;
@@ -1228,7 +1295,7 @@
                 // First let's make a copy of the current process state and put
                 // that under the now unique state for its original package name.
                 final PackageState commonPkgState = getPackageStateLocked(commonProc.getPackage(),
-                        uid, commonProc.getVersion());
+                        pkgState.mUid, commonProc.getVersion());
                 if (commonPkgState != null) {
                     ProcessState cloned = commonProc.clone(now);
                     if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.getPackage()
@@ -1245,18 +1312,31 @@
                             Slog.d(TAG, "GETPROC leaving proc of " + ss);
                         }
                     }
+                    // Also update active associations.
+                    for (int i=commonPkgState.mAssociations.size()-1; i>=0; i--) {
+                        AssociationState as = commonPkgState.mAssociations.valueAt(i);
+                        if (as.getProcess() == commonProc) {
+                            if (DEBUG) Slog.d(TAG, "GETPROC switching association to cloned: "
+                                    + as);
+                            as.setProcess(cloned);
+                        } else if (DEBUG) {
+                            Slog.d(TAG, "GETPROC leaving proc of " + as);
+                        }
+                    }
                 } else {
                     Slog.w(TAG, "Cloning proc state: no package state " + commonProc.getPackage()
-                            + "/" + uid + " for proc " + commonProc.getName());
+                            + "/" + pkgState.mUid + " for proc " + commonProc.getName());
                 }
                 // And now make a fresh new process state for the new package name.
-                ps = new ProcessState(commonProc, packageName, uid, vers, processName, now);
+                ps = new ProcessState(commonProc, pkgState.mPackageName, pkgState.mUid,
+                        pkgState.mVersionCode, processName, now);
                 if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
             }
         } else {
             // The common process is for multiple packages, we need to create a
             // separate object for the per-package data.
-            ps = new ProcessState(commonProc, packageName, uid, vers, processName,
+            ps = new ProcessState(commonProc, pkgState.mPackageName, pkgState.mUid,
+                    pkgState.mVersionCode, processName,
                     SystemClock.uptimeMillis());
             if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
         }
@@ -1281,8 +1361,58 @@
         return ss;
     }
 
+    public AssociationState getAssociationStateLocked(String packageName, int uid, long vers,
+            String processName, String className) {
+        final ProcessStats.PackageState pkgs = getPackageStateLocked(packageName, uid, vers);
+        AssociationState as = pkgs.mAssociations.get(className);
+        if (as != null) {
+            if (DEBUG) Slog.d(TAG, "GETASC: returning existing " + as);
+            return as;
+        }
+        final ProcessState procs = processName != null
+                ? getProcessStateLocked(packageName, uid, vers, processName) : null;
+        as = new AssociationState(this, pkgs, className, processName, procs);
+        pkgs.mAssociations.put(className, as);
+        if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + procs);
+        return as;
+    }
+
+    public void updateTrackingAssociationsLocked(int curSeq, long now) {
+        final int NUM = mTrackingAssociations.size();
+        for (int i = NUM - 1; i >= 0; i--) {
+            final AssociationState.SourceState act = mTrackingAssociations.get(i);
+            if (act.mProcStateSeq != curSeq || act.mProcState >= ProcessStats.STATE_HOME) {
+                // If this association did not get touched the last time we computed
+                // process states, or its state ended up down in cached, then we no
+                // longer have a reason to track it at all.
+                act.stopActive(now);
+                act.mInTrackingList = false;
+                act.mProcState = ProcessStats.STATE_NOTHING;
+                mTrackingAssociations.remove(i);
+            } else {
+                final ProcessState proc = act.getAssociationState().getProcess();
+                if (proc != null) {
+                    final int procState = proc.getCombinedState() % STATE_COUNT;
+                    if (act.mProcState == procState) {
+                        act.startActive(now);
+                    } else {
+                        act.stopActive(now);
+                        if (act.mProcState < procState) {
+                            Slog.w(TAG, "Tracking association " + act + " whose proc state "
+                                    + act.mProcState + " is better than process " + proc
+                                    + " proc state " + procState);
+                        }
+                    }
+                } else {
+                    Slog.wtf(TAG, "Tracking association without process: " + act
+                            + " in " + act.getAssociationState());
+                }
+            }
+        }
+    }
+
     public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
-            boolean dumpAll, boolean activeOnly) {
+            boolean dumpDetails, boolean dumpAll, boolean activeOnly) {
         long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
                 mStartTime, now);
         boolean sepNeeded = false;
@@ -1304,6 +1434,7 @@
                     final PackageState pkgState = vpkgs.valueAt(iv);
                     final int NPROCS = pkgState.mProcesses.size();
                     final int NSRVS = pkgState.mServices.size();
+                    final int NASCS = pkgState.mAssociations.size();
                     final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
                     if (!pkgMatch) {
                         boolean procMatch = false;
@@ -1318,7 +1449,7 @@
                             continue;
                         }
                     }
-                    if (NPROCS > 0 || NSRVS > 0) {
+                    if (NPROCS > 0 || NSRVS > 0 || NASCS > 0) {
                         if (!printedHeader) {
                             if (sepNeeded) pw.println();
                             pw.println("Per-Package Stats:");
@@ -1353,7 +1484,7 @@
                             proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
                                     ALL_PROC_STATES, now);
                             proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
-                                    ALL_PROC_STATES);
+                                    ALL_PROC_STATES, now);
                             proc.dumpInternalLocked(pw, "        ", dumpAll);
                         }
                     } else {
@@ -1368,7 +1499,7 @@
                             }
                             procs.add(proc);
                         }
-                        DumpUtils.dumpProcessSummaryLocked(pw, "      ", procs,
+                        DumpUtils.dumpProcessSummaryLocked(pw, "      ", "Prc ", procs,
                                 ALL_SCREEN_ADJ, ALL_MEM_ADJ, NON_CACHED_PROC_STATES,
                                 now, totalTime);
                     }
@@ -1378,14 +1509,14 @@
                             continue;
                         }
                         if (activeOnly && !svc.isInUse()) {
-                            pw.print("      (Not active: ");
+                            pw.print("      (Not active service: ");
                                     pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
                             continue;
                         }
                         if (dumpAll) {
                             pw.print("      Service ");
                         } else {
-                            pw.print("      * ");
+                            pw.print("      * Svc ");
                         }
                         pw.print(pkgState.mServices.keyAt(isvc));
                         pw.println(":");
@@ -1393,6 +1524,27 @@
                         svc.dumpStats(pw, "        ", "          ", "    ",
                                 now, totalTime, dumpSummary, dumpAll);
                     }
+                    for (int iasc=0; iasc<NASCS; iasc++) {
+                        AssociationState asc = pkgState.mAssociations.valueAt(iasc);
+                        if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) {
+                            continue;
+                        }
+                        if (activeOnly && !asc.isInUse()) {
+                            pw.print("      (Not active association: ");
+                            pw.print(pkgState.mAssociations.keyAt(iasc)); pw.println(")");
+                            continue;
+                        }
+                        if (dumpAll) {
+                            pw.print("      Association ");
+                        } else {
+                            pw.print("      * Asc ");
+                        }
+                        pw.print(pkgState.mAssociations.keyAt(iasc));
+                        pw.println(":");
+                        pw.print("        Process: "); pw.println(asc.getProcessName());
+                        asc.dumpStats(pw, "        ", "          ", "    ",
+                                now, totalTime, dumpDetails, dumpAll);
+                    }
                 }
             }
         }
@@ -1407,7 +1559,7 @@
                 int uid = uids.keyAt(iu);
                 numTotalProcs++;
                 final ProcessState proc = uids.valueAt(iu);
-                if (proc.hasAnyData()) {
+                if (!proc.hasAnyData()) {
                     continue;
                 }
                 if (!proc.isMultiPackage()) {
@@ -1436,21 +1588,68 @@
                         pw.print(" entries)"); pw.println(":");
                 proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
                         ALL_PROC_STATES, now);
-                proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES);
+                proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES, now);
                 proc.dumpInternalLocked(pw, "        ", dumpAll);
             }
         }
+
         if (dumpAll) {
-            pw.println();
+            if (sepNeeded) {
+                pw.println();
+            }
+            sepNeeded = true;
             pw.print("  Total procs: "); pw.print(numShownProcs);
                     pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
+            if (mTrackingAssociations.size() > 0) {
+                pw.println();
+                pw.println("Tracking associations:");
+                for (int i = 0; i < mTrackingAssociations.size(); i++) {
+                    final AssociationState.SourceState src = mTrackingAssociations.get(i);
+                    final AssociationState asc = src.getAssociationState();
+                    pw.print("  #");
+                    pw.print(i);
+                    pw.print(": ");
+                    pw.print(asc.getProcessName());
+                    pw.print("/");
+                    UserHandle.formatUid(pw, asc.getUid());
+                    pw.print(" <- ");
+                    pw.print(src.getProcessName());
+                    pw.print("/");
+                    UserHandle.formatUid(pw, src.getUid());
+                    pw.println(":");
+                    pw.print("    Tracking for: ");
+                    TimeUtils.formatDuration(now - src.mTrackingUptime, pw);
+                    pw.println();
+                    pw.print("    Component: ");
+                    pw.print(new ComponentName(asc.getPackage(), asc.getName())
+                            .flattenToShortString());
+                    pw.println();
+                    pw.print("    Proc state: ");
+                    if (src.mProcState != ProcessStats.STATE_NOTHING) {
+                        pw.print(DumpUtils.STATE_NAMES[src.mProcState]);
+                    } else {
+                        pw.print("--");
+                    }
+                    pw.print(" #");
+                    pw.println(src.mProcStateSeq);
+                    pw.print("    Process: ");
+                    pw.println(asc.getProcess());
+                    if (src.mActiveCount > 0) {
+                        pw.print("    Active count ");
+                        pw.print(src.mActiveCount);
+                        pw.print(": ");
+                        asc.dumpActiveDurationSummary(pw, src, totalTime, now, dumpAll);
+                        pw.println();
+                    }
+                }
+            }
         }
 
         if (sepNeeded) {
             pw.println();
         }
         if (dumpSummary) {
-            pw.println("Summary:");
+            pw.println("Process summary:");
             dumpSummaryLocked(pw, reqPackage, now, activeOnly);
         } else {
             dumpTotalsLocked(pw, now);
@@ -1466,13 +1665,15 @@
             pw.print("  mRunning="); pw.println(mRunning);
         }
 
-        dumpFragmentationLocked(pw);
+        if (reqPackage == null) {
+            dumpFragmentationLocked(pw);
+        }
     }
 
     public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
         long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
                 mStartTime, now);
-        dumpFilteredSummaryLocked(pw, null, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
+        dumpFilteredSummaryLocked(pw, null, "  ", null, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
                 ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
         pw.println();
         dumpTotalsLocked(pw, now);
@@ -1607,7 +1808,7 @@
         pw.println();
     }
 
-    void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
+    void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix, String prcLabel,
             int[] screenStates, int[] memStates, int[] procStates,
             int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
         ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
@@ -1617,7 +1818,7 @@
                 pw.println();
                 pw.println(header);
             }
-            DumpUtils.dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates,
+            DumpUtils.dumpProcessSummaryLocked(pw, prefix, prcLabel, procs, screenStates, memStates,
                     sortProcStates, now, totalTime);
         }
     }
@@ -1708,6 +1909,7 @@
                     final PackageState pkgState = vpkgs.valueAt(iv);
                     final int NPROCS = pkgState.mProcesses.size();
                     final int NSRVS = pkgState.mServices.size();
+                    final int NASCS = pkgState.mAssociations.size();
                     for (int iproc=0; iproc<NPROCS; iproc++) {
                         ProcessState proc = pkgState.mProcesses.valueAt(iproc);
                         proc.dumpPackageProcCheckin(pw, pkgName, uid, vers,
@@ -1719,6 +1921,12 @@
                         final ServiceState svc = pkgState.mServices.valueAt(isvc);
                         svc.dumpTimesCheckin(pw, pkgName, uid, vers, serviceName, now);
                     }
+                    for (int iasc=0; iasc<NASCS; iasc++) {
+                        final String associationName = DumpUtils.collapseString(pkgName,
+                                pkgState.mAssociations.keyAt(iasc));
+                        final AssociationState asc = pkgState.mAssociations.valueAt(iasc);
+                        asc.dumpTimesCheckin(pw, pkgName, uid, vers, associationName, now);
+                    }
                 }
             }
         }
@@ -1806,10 +2014,8 @@
     }
 
     public void writeToProto(ProtoOutputStream proto, long fieldId, long now) {
-        final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
-                mPackages.getMap();
-
         final long token = proto.start(fieldId);
+
         proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
         proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
                 mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
@@ -1834,22 +2040,38 @@
             proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_PARTIAL);
         }
 
-        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
+        final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
         for (int ip=0; ip<procMap.size(); ip++) {
-            String procName = procMap.keyAt(ip);
-            SparseArray<ProcessState> uids = procMap.valueAt(ip);
+            final String procName = procMap.keyAt(ip);
+            final SparseArray<ProcessState> uids = procMap.valueAt(ip);
             for (int iu=0; iu<uids.size(); iu++) {
                 final int uid = uids.keyAt(iu);
                 final ProcessState procState = uids.valueAt(iu);
-                procState.writeToProto(proto, ProcessStatsSectionProto.PROCESS_STATS, procName, uid, now);
+                procState.writeToProto(proto, ProcessStatsSectionProto.PROCESS_STATS, procName,
+                        uid, now);
             }
         }
+
+        final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
+                mPackages.getMap();
+        for (int ip = 0; ip < pkgMap.size(); ip++) {
+            final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
+            for (int iu = 0; iu < uids.size(); iu++) {
+                final LongSparseArray<PackageState> vers = uids.valueAt(iu);
+                for (int iv = 0; iv < vers.size(); iv++) {
+                    final PackageState pkgState = vers.valueAt(iv);
+                    pkgState.writeToProto(proto, ProcessStatsSectionProto.PACKAGE_STATS, now);
+                }
+            }
+        }
+
         proto.end(token);
     }
 
     final public static class ProcessStateHolder {
         public final long appVersion;
         public ProcessState state;
+        public PackageState pkg;
 
         public ProcessStateHolder(long _appVersion) {
             appVersion = _appVersion;
@@ -1857,16 +2079,62 @@
     }
 
     public static final class PackageState {
-        public final ArrayMap<String, ProcessState> mProcesses
-                = new ArrayMap<String, ProcessState>();
-        public final ArrayMap<String, ServiceState> mServices
-                = new ArrayMap<String, ServiceState>();
+        public final ProcessStats mProcessStats;
+        public final ArrayMap<String, ProcessState> mProcesses = new ArrayMap<>();
+        public final ArrayMap<String, ServiceState> mServices = new ArrayMap<>();
+        public final ArrayMap<String, AssociationState> mAssociations = new ArrayMap<>();
         public final String mPackageName;
         public final int mUid;
+        public final long mVersionCode;
 
-        public PackageState(String packageName, int uid) {
+        public PackageState(ProcessStats procStats, String packageName, int uid, long versionCode) {
+            mProcessStats = procStats;
             mUid = uid;
             mPackageName = packageName;
+            mVersionCode = versionCode;
+        }
+
+        public AssociationState getAssociationStateLocked(ProcessState proc, String className) {
+            AssociationState as = mAssociations.get(className);
+            if (as != null) {
+                if (DEBUG) Slog.d(TAG, "GETASC: returning existing " + as);
+                if (proc != null) {
+                    as.setProcess(proc);
+                }
+                return as;
+            }
+            as = new AssociationState(mProcessStats, this, className, proc.getName(),
+                    proc);
+            mAssociations.put(className, as);
+            if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + proc.getName());
+            return as;
+        }
+
+        public void writeToProto(ProtoOutputStream proto, long fieldId, long now) {
+            final long token = proto.start(fieldId);
+
+            proto.write(ProcessStatsPackageProto.PACKAGE, mPackageName);
+            proto.write(ProcessStatsPackageProto.UID, mUid);
+            proto.write(ProcessStatsPackageProto.VERSION, mVersionCode);
+
+            for (int ip = 0; ip < mProcesses.size(); ip++) {
+                final String procName = mProcesses.keyAt(ip);
+                final ProcessState procState = mProcesses.valueAt(ip);
+                procState.writeToProto(proto, ProcessStatsPackageProto.PROCESS_STATS, procName,
+                        mUid, now);
+            }
+
+            for (int is = 0; is < mServices.size(); is++) {
+                final ServiceState serviceState = mServices.valueAt(is);
+                serviceState.writeToProto(proto, ProcessStatsPackageProto.PROCESS_STATS, now);
+            }
+
+            for (int ia=0; ia<mAssociations.size(); ia++) {
+                final AssociationState ascState = mAssociations.valueAt(ia);
+                ascState.writeToProto(proto, ProcessStatsPackageProto.ASSOCIATION_STATS, now);
+            }
+
+            proto.end(token);
         }
     }
 
diff --git a/core/java/com/android/internal/app/procstats/PssTable.java b/core/java/com/android/internal/app/procstats/PssTable.java
index 1e7c566..fc93c3a 100644
--- a/core/java/com/android/internal/app/procstats/PssTable.java
+++ b/core/java/com/android/internal/app/procstats/PssTable.java
@@ -28,6 +28,10 @@
 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MAXIMUM;
 import static com.android.internal.app.procstats.ProcessStats.PSS_COUNT;
 
+import android.service.procstats.ProcessStatsStateProto;
+import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
+
 /**
  * Class to accumulate PSS data.
  */
@@ -46,18 +50,17 @@
     public void mergeStats(PssTable that) {
         final int N = that.getKeyCount();
         for (int i=0; i<N; i++) {
-            final int key = that.getKeyAt(i);
-            final int state = SparseMappingTable.getIdFromKey(key);
-            mergeStats(state, (int)that.getValue(key, PSS_SAMPLE_COUNT),
-                    that.getValue(key, PSS_MINIMUM),
-                    that.getValue(key, PSS_AVERAGE),
-                    that.getValue(key, PSS_MAXIMUM),
-                    that.getValue(key, PSS_USS_MINIMUM),
-                    that.getValue(key, PSS_USS_AVERAGE),
-                    that.getValue(key, PSS_USS_MAXIMUM),
-                    that.getValue(key, PSS_RSS_MINIMUM),
-                    that.getValue(key, PSS_RSS_AVERAGE),
-                    that.getValue(key, PSS_RSS_MAXIMUM));
+            final int thatKey = that.getKeyAt(i);
+            final int state = SparseMappingTable.getIdFromKey(thatKey);
+
+            final int key = getOrAddKey((byte)state, PSS_COUNT);
+            final long[] stats = getArrayForKey(key);
+            final int statsIndex = SparseMappingTable.getIndexFromKey(key);
+
+            final long[] thatStats = that.getArrayForKey(thatKey);
+            final int thatStatsIndex = SparseMappingTable.getIndexFromKey(thatKey);
+
+            mergeStats(stats, statsIndex, thatStats, thatStatsIndex);
         }
     }
 
@@ -68,64 +71,100 @@
     public void mergeStats(int state, int inCount, long minPss, long avgPss, long maxPss,
             long minUss, long avgUss, long maxUss, long minRss, long avgRss, long maxRss) {
         final int key = getOrAddKey((byte)state, PSS_COUNT);
-        final long count = getValue(key, PSS_SAMPLE_COUNT);
+        final long[] stats = getArrayForKey(key);
+        final int statsIndex = SparseMappingTable.getIndexFromKey(key);
+        mergeStats(stats, statsIndex, inCount, minPss, avgPss, maxPss, minUss, avgUss, maxUss,
+                minRss, avgRss, maxRss);
+    }
+
+    public static void mergeStats(final long[] stats, final int statsIndex,
+            final long[] thatStats, int thatStatsIndex) {
+        mergeStats(stats, statsIndex, (int)thatStats[thatStatsIndex + PSS_SAMPLE_COUNT],
+                thatStats[thatStatsIndex + PSS_MINIMUM],
+                thatStats[thatStatsIndex + PSS_AVERAGE],
+                thatStats[thatStatsIndex + PSS_MAXIMUM],
+                thatStats[thatStatsIndex + PSS_USS_MINIMUM],
+                thatStats[thatStatsIndex + PSS_USS_AVERAGE],
+                thatStats[thatStatsIndex + PSS_USS_MAXIMUM],
+                thatStats[thatStatsIndex + PSS_RSS_MINIMUM],
+                thatStats[thatStatsIndex + PSS_RSS_AVERAGE],
+                thatStats[thatStatsIndex + PSS_RSS_MAXIMUM]);
+    }
+
+    public static void mergeStats(final long[] stats, final int statsIndex, final int inCount,
+            final long minPss, final long avgPss, final long maxPss,
+            final long minUss, final long avgUss, final long maxUss,
+            final long minRss, final long avgRss, final long maxRss) {
+        final long count = stats[statsIndex + PSS_SAMPLE_COUNT];
         if (count == 0) {
-            setValue(key, PSS_SAMPLE_COUNT, inCount);
-            setValue(key, PSS_MINIMUM, minPss);
-            setValue(key, PSS_AVERAGE, avgPss);
-            setValue(key, PSS_MAXIMUM, maxPss);
-            setValue(key, PSS_USS_MINIMUM, minUss);
-            setValue(key, PSS_USS_AVERAGE, avgUss);
-            setValue(key, PSS_USS_MAXIMUM, maxUss);
-            setValue(key, PSS_RSS_MINIMUM, minRss);
-            setValue(key, PSS_RSS_AVERAGE, avgRss);
-            setValue(key, PSS_RSS_MAXIMUM, maxRss);
+            stats[statsIndex + PSS_SAMPLE_COUNT] = inCount;
+            stats[statsIndex + PSS_MINIMUM] = minPss;
+            stats[statsIndex + PSS_AVERAGE] = avgPss;
+            stats[statsIndex + PSS_MAXIMUM] = maxPss;
+            stats[statsIndex + PSS_USS_MINIMUM] = minUss;
+            stats[statsIndex + PSS_USS_AVERAGE] = avgUss;
+            stats[statsIndex + PSS_USS_MAXIMUM] = maxUss;
+            stats[statsIndex + PSS_RSS_MINIMUM] = minRss;
+            stats[statsIndex + PSS_RSS_AVERAGE] = avgRss;
+            stats[statsIndex + PSS_RSS_MAXIMUM] = maxRss;
         } else {
-            setValue(key, PSS_SAMPLE_COUNT, count + inCount);
+            stats[statsIndex + PSS_SAMPLE_COUNT] = count + inCount;
 
-            long val;
-
-            val = getValue(key, PSS_MINIMUM);
-            if (val > minPss) {
-                setValue(key, PSS_MINIMUM, minPss);
+            if (stats[statsIndex + PSS_MINIMUM] > minPss) {
+                stats[statsIndex + PSS_MINIMUM] = minPss;
             }
 
-            val = getValue(key, PSS_AVERAGE);
-            setValue(key, PSS_AVERAGE,
-                    (long)(((val*(double)count)+(avgPss*(double)inCount)) / (count+inCount)));
+            stats[statsIndex + PSS_AVERAGE] = (long)(((stats[statsIndex + PSS_AVERAGE]
+                    * (double)count) + (avgPss * (double)inCount)) / (count + inCount));
 
-            val = getValue(key, PSS_MAXIMUM);
-            if (val < maxPss) {
-                setValue(key, PSS_MAXIMUM, maxPss);
+            if (stats[statsIndex + PSS_MAXIMUM] < maxPss) {
+                stats[statsIndex + PSS_MAXIMUM] = maxPss;
             }
 
-            val = getValue(key, PSS_USS_MINIMUM);
-            if (val > minUss) {
-                setValue(key, PSS_USS_MINIMUM, minUss);
+            if (stats[statsIndex + PSS_USS_MINIMUM] > minUss) {
+                stats[statsIndex + PSS_USS_MINIMUM] = minUss;
             }
 
-            val = getValue(key, PSS_USS_AVERAGE);
-            setValue(key, PSS_USS_AVERAGE,
-                    (long)(((val*(double)count)+(avgUss*(double)inCount)) / (count+inCount)));
+            stats[statsIndex + PSS_USS_AVERAGE] = (long)(((stats[statsIndex + PSS_USS_AVERAGE]
+                    * (double)count) + (avgUss * (double)inCount)) / (count + inCount));
 
-            val = getValue(key, PSS_USS_MAXIMUM);
-            if (val < maxUss) {
-                setValue(key, PSS_USS_MAXIMUM, maxUss);
+            if (stats[statsIndex + PSS_USS_MAXIMUM] < maxUss) {
+                stats[statsIndex + PSS_USS_MAXIMUM] = maxUss;
             }
 
-            val = getValue(key, PSS_RSS_MINIMUM);
-            if (val > minUss) {
-                setValue(key, PSS_RSS_MINIMUM, minUss);
+            if (stats[statsIndex + PSS_RSS_MINIMUM] > minRss) {
+                stats[statsIndex + PSS_RSS_MINIMUM] = minRss;
             }
 
-            val = getValue(key, PSS_RSS_AVERAGE);
-            setValue(key, PSS_RSS_AVERAGE,
-                    (long)(((val*(double)count)+(avgUss*(double)inCount)) / (count+inCount)));
+            stats[statsIndex + PSS_RSS_AVERAGE] = (long)(((stats[statsIndex + PSS_RSS_AVERAGE]
+                    * (double)count) + (avgRss * (double)inCount)) / (count + inCount));
 
-            val = getValue(key, PSS_RSS_MAXIMUM);
-            if (val < maxUss) {
-                setValue(key, PSS_RSS_MAXIMUM, maxUss);
+            if (stats[statsIndex + PSS_RSS_MAXIMUM] < maxRss) {
+                stats[statsIndex + PSS_RSS_MAXIMUM] = maxRss;
             }
         }
     }
+
+    public void writeStatsToProtoForKey(ProtoOutputStream proto, int key) {
+        final long[] stats = getArrayForKey(key);
+        final int statsIndex = SparseMappingTable.getIndexFromKey(key);
+        writeStatsToProto(proto, stats, statsIndex);
+    }
+
+    public static void writeStatsToProto(ProtoOutputStream proto, final long[] stats,
+            final int statsIndex) {
+        proto.write(ProcessStatsStateProto.SAMPLE_SIZE, stats[statsIndex + PSS_SAMPLE_COUNT]);
+        ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.PSS,
+                stats[statsIndex + PSS_MINIMUM],
+                stats[statsIndex + PSS_AVERAGE],
+                stats[statsIndex + PSS_MAXIMUM]);
+        ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.USS,
+                stats[statsIndex + PSS_USS_MINIMUM],
+                stats[statsIndex + PSS_USS_AVERAGE],
+                stats[statsIndex + PSS_USS_MAXIMUM]);
+        ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.RSS,
+                stats[statsIndex + PSS_RSS_MINIMUM],
+                stats[statsIndex + PSS_RSS_AVERAGE],
+                stats[statsIndex + PSS_RSS_MAXIMUM]);
+    }
 }
diff --git a/core/java/com/android/internal/app/procstats/ServiceState.java b/core/java/com/android/internal/app/procstats/ServiceState.java
index 650de2ea..16975a4 100644
--- a/core/java/com/android/internal/app/procstats/ServiceState.java
+++ b/core/java/com/android/internal/app/procstats/ServiceState.java
@@ -18,30 +18,20 @@
 
 
 import android.os.Parcel;
-import android.os.Parcelable;
 import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.text.format.DateFormat;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.DebugUtils;
-import android.util.Log;
+import android.service.procstats.ProcessStatsProto;
+import android.service.procstats.ProcessStatsServiceStateProto;
+import android.service.procstats.ProcessStatsStateProto;
 import android.util.Slog;
-import android.util.SparseArray;
+import android.util.SparseLongArray;
 import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
 
-import com.android.internal.app.procstats.ProcessStats;
+import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT;
 import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING;
 
-import java.io.IOException;
-import java.io.InputStream;
 import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Objects;
 
 public final class ServiceState {
     private static final String TAG = "ProcessStats";
@@ -51,7 +41,8 @@
     public static final int SERVICE_STARTED = 1;
     public static final int SERVICE_BOUND = 2;
     public static final int SERVICE_EXEC = 3;
-    public static final int SERVICE_COUNT = 4;
+    public static final int SERVICE_FOREGROUND = 4;
+    public static final int SERVICE_COUNT = 5;
 
     private final String mPackage;
     private final String mProcessName;
@@ -79,6 +70,10 @@
     private int mExecState = STATE_NOTHING;
     private long mExecStartTime;
 
+    private int mForegroundCount;
+    private int mForegroundState = STATE_NOTHING;
+    private long mForegroundStartTime;
+
     public ServiceState(ProcessStats processStats, String pkg, String name,
             String processName, ProcessState proc) {
         mPackage = pkg;
@@ -121,6 +116,9 @@
             if (mExecState != ProcessStats.STATE_NOTHING) {
                 setExecuting(true, memFactor, now);
             }
+            if (mForegroundState != ProcessStats.STATE_NOTHING) {
+                setForeground(true, memFactor, now);
+            }
         }
     }
 
@@ -133,7 +131,8 @@
                 // There was already an old owner, reset this object for its
                 // new owner.
                 mOwner = newOwner;
-                if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
+                if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING
+                        || mForegroundState != STATE_NOTHING) {
                     long now = SystemClock.uptimeMillis();
                     if (mStarted) {
                         if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
@@ -153,6 +152,12 @@
                                 + mPackage + " service=" + mName + " proc=" + mProc);
                         setExecuting(false, 0, now);
                     }
+                    if (mForegroundState != STATE_NOTHING) {
+                        if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
+                                + " from " + mOwner + " while foreground: pkg="
+                                + mPackage + " service=" + mName + " proc=" + mProc);
+                        setForeground(false, 0, now);
+                    }
                 }
             }
         }
@@ -161,7 +166,8 @@
     public void clearCurrentOwner(Object owner, boolean silently) {
         if (mOwner == owner) {
             mProc.decActiveServices(mName);
-            if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
+            if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING
+                    || mForegroundState != STATE_NOTHING) {
                 long now = SystemClock.uptimeMillis();
                 if (mStarted) {
                     if (!silently) {
@@ -187,6 +193,14 @@
                     }
                     setExecuting(false, 0, now);
                 }
+                if (mForegroundState != STATE_NOTHING) {
+                    if (!silently) {
+                        Slog.wtfStack(TAG, "Service owner " + owner
+                                + " cleared while foreground: pkg=" + mPackage + " service="
+                                + mName + " proc=" + mProc);
+                    }
+                    setForeground(false, 0, now);
+                }
             }
             mOwner = null;
         }
@@ -206,6 +220,7 @@
         mStartedCount += other.mStartedCount;
         mBoundCount += other.mBoundCount;
         mExecCount += other.mExecCount;
+        mForegroundCount += other.mForegroundCount;
     }
 
     public void resetSafely(long now) {
@@ -214,7 +229,9 @@
         mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0;
         mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0;
         mExecCount = mExecState != STATE_NOTHING ? 1 : 0;
-        mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now;
+        mForegroundCount = mForegroundState != STATE_NOTHING ? 1 : 0;
+        mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime =
+                mForegroundStartTime = now;
     }
 
     public void writeToParcel(Parcel out, long now) {
@@ -223,6 +240,7 @@
         out.writeInt(mStartedCount);
         out.writeInt(mBoundCount);
         out.writeInt(mExecCount);
+        out.writeInt(mForegroundCount);
     }
 
     public boolean readFromParcel(Parcel in) {
@@ -233,6 +251,7 @@
         mStartedCount = in.readInt();
         mBoundCount = in.readInt();
         mExecCount = in.readInt();
+        mForegroundCount = in.readInt();
         return true;
     }
 
@@ -257,11 +276,17 @@
                     now - mExecStartTime);
             mExecStartTime = now;
         }
+        if (mForegroundState != STATE_NOTHING) {
+            mDurations.addDuration(SERVICE_FOREGROUND + (mForegroundState*SERVICE_COUNT),
+                    now - mForegroundStartTime);
+            mForegroundStartTime = now;
+        }
     }
 
     private void updateRunning(int memFactor, long now) {
         final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
-                || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING;
+                || mExecState != STATE_NOTHING || mForegroundState != STATE_NOTHING)
+                ? memFactor : STATE_NOTHING;
         if (mRunState != state) {
             if (mRunState != STATE_NOTHING) {
                 mDurations.addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT),
@@ -348,6 +373,24 @@
         }
     }
 
+    public void setForeground(boolean foreground, int memFactor, long now) {
+        if (mOwner == null) {
+            Slog.wtf(TAG, "Foregrounding service " + this + " without owner");
+        }
+        final int state = foreground ? memFactor : STATE_NOTHING;
+        if (mForegroundState != state) {
+            if (mForegroundState != STATE_NOTHING) {
+                mDurations.addDuration(SERVICE_FOREGROUND + (mForegroundState*SERVICE_COUNT),
+                        now - mForegroundStartTime);
+            } else if (foreground) {
+                mForegroundCount++;
+            }
+            mForegroundState = state;
+            mForegroundStartTime = now;
+            updateRunning(memFactor, now);
+        }
+    }
+
     public long getDuration(int opType, int curState, long startTime, int memFactor,
             long now) {
         int state = opType + (memFactor*SERVICE_COUNT);
@@ -366,6 +409,9 @@
         dumpStats(pw, prefix, prefixInner, headerPrefix, "Started",
                 mStartedCount, ServiceState.SERVICE_STARTED, mStartedState,
                 mStartedStartTime, now, totalTime, !dumpSummary || dumpAll);
+        dumpStats(pw, prefix, prefixInner, headerPrefix, "Foreground",
+                mForegroundCount, ServiceState.SERVICE_FOREGROUND, mForegroundState,
+                mForegroundStartTime, now, totalTime, !dumpSummary || dumpAll);
         dumpStats(pw, prefix, prefixInner, headerPrefix, "Bound",
                 mBoundCount, ServiceState.SERVICE_BOUND, mBoundState,
                 mBoundStartTime, now, totalTime, !dumpSummary || dumpAll);
@@ -393,11 +439,19 @@
                 pw.print(" op count "); pw.print(count); pw.println(":");
                 dumpTime(pw, prefixInner, serviceType, state, startTime, now);
             } else {
-                long myTime = dumpTime(null, null, serviceType, state, startTime, now);
+                long myTime = dumpTimeInternal(null, null, serviceType, state, startTime, now,
+                        true);
                 pw.print(prefix); pw.print(headerPrefix); pw.print(header);
                 pw.print(" count "); pw.print(count);
                 pw.print(" / time ");
+                boolean isRunning = myTime < 0;
+                if (isRunning) {
+                    myTime = -myTime;
+                }
                 DumpUtils.printPercent(pw, (double)myTime/(double)totalTime);
+                if (isRunning) {
+                    pw.print(" (running)");
+                }
                 pw.println();
             }
         }
@@ -405,8 +459,14 @@
 
     public long dumpTime(PrintWriter pw, String prefix,
             int serviceType, int curState, long curStartTime, long now) {
+        return dumpTimeInternal(pw, prefix, serviceType, curState, curStartTime, now, false);
+    }
+
+    long dumpTimeInternal(PrintWriter pw, String prefix,
+            int serviceType, int curState, long curStartTime, long now, boolean negativeIfRunning) {
         long totalTime = 0;
         int printedScreen = -1;
+        boolean isRunning = false;
         for (int iscreen=0; iscreen<ProcessStats.ADJ_COUNT; iscreen+=ProcessStats.ADJ_SCREEN_MOD) {
             int printedMem = -1;
             for (int imem=0; imem<ProcessStats.ADJ_MEM_FACTOR_COUNT; imem++) {
@@ -415,6 +475,7 @@
                 String running = "";
                 if (curState == state && pw != null) {
                     running = " (running)";
+                    isRunning = true;
                 }
                 if (time != 0) {
                     if (pw != null) {
@@ -438,7 +499,7 @@
             TimeUtils.formatDuration(totalTime, pw);
             pw.println();
         }
-        return totalTime;
+        return (isRunning && negativeIfRunning) ? -totalTime : totalTime;
     }
 
     public void dumpTimesCheckin(PrintWriter pw, String pkgName, int uid, long vers,
@@ -447,6 +508,9 @@
                 ServiceState.SERVICE_RUN, mRunCount, mRunState, mRunStartTime, now);
         dumpTimeCheckin(pw, "pkgsvc-start", pkgName, uid, vers, serviceName,
                 ServiceState.SERVICE_STARTED, mStartedCount, mStartedState, mStartedStartTime, now);
+        dumpTimeCheckin(pw, "pkgsvc-fg", pkgName, uid, vers, serviceName,
+                ServiceState.SERVICE_FOREGROUND, mForegroundCount, mForegroundState,
+                mForegroundStartTime, now);
         dumpTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, vers, serviceName,
                 ServiceState.SERVICE_BOUND, mBoundCount, mBoundState, mBoundStartTime, now);
         dumpTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, vers, serviceName,
@@ -493,10 +557,70 @@
         pw.println();
     }
 
+    public void writeToProto(ProtoOutputStream proto, long fieldId, long now) {
+        final long token = proto.start(fieldId);
+        proto.write(ProcessStatsServiceStateProto.SERVICE_NAME, mName);
+        writeTypeToProto(proto, ProcessStatsServiceStateProto.RUNNING_OP,
+                ServiceState.SERVICE_RUN, mRunCount, mRunState, mRunStartTime, now);
+        writeTypeToProto(proto, ProcessStatsServiceStateProto.STARTED_OP,
+                ServiceState.SERVICE_STARTED, mStartedCount, mStartedState, mStartedStartTime, now);
+        writeTypeToProto(proto, ProcessStatsServiceStateProto.FOREGROUND_OP,
+                ServiceState.SERVICE_FOREGROUND, mForegroundCount, mForegroundState,
+                mForegroundStartTime, now);
+        writeTypeToProto(proto, ProcessStatsServiceStateProto.BOUND_OP,
+                ServiceState.SERVICE_BOUND, mBoundCount, mBoundState, mBoundStartTime, now);
+        writeTypeToProto(proto, ProcessStatsServiceStateProto.EXECUTING_OP,
+                ServiceState.SERVICE_EXEC, mExecCount, mExecState, mExecStartTime, now);
+        proto.end(token);
+    }
+
+    public void writeTypeToProto(ProtoOutputStream proto, long fieldId, int serviceType,
+            int opCount, int curState, long curStartTime, long now) {
+        if (opCount <= 0) {
+            return;
+        }
+        final long token = proto.start(fieldId);
+
+        proto.write(ProcessStatsServiceStateProto.OperationInfo.COUNT, opCount);
+        boolean didCurState = false;
+        final int N = mDurations.getKeyCount();
+        for (int i=0; i<N; i++) {
+            final int key = mDurations.getKeyAt(i);
+            long time = mDurations.getValue(key);
+            int type = SparseMappingTable.getIdFromKey(key);
+            int memFactor = type / ServiceState.SERVICE_COUNT;
+            type %= ServiceState.SERVICE_COUNT;
+            if (type != serviceType) {
+                continue;
+            }
+            if (curState == memFactor) {
+                didCurState = true;
+                time += now - curStartTime;
+            }
+            final long stateToken = proto.start(ProcessStatsServiceStateProto.OperationInfo.STATES);
+            DumpUtils.printProcStateAdjTagProto(proto,
+                    ProcessStatsStateProto.SCREEN_STATE,
+                    ProcessStatsStateProto.MEMORY_STATE,
+                    type);
+            proto.write(ProcessStatsStateProto.DURATION_MS, time);
+            proto.end(stateToken);
+        }
+        if (!didCurState && curState != STATE_NOTHING) {
+            final long stateToken = proto.start(ProcessStatsServiceStateProto.OperationInfo.STATES);
+            DumpUtils.printProcStateAdjTagProto(proto,
+                    ProcessStatsStateProto.SCREEN_STATE,
+                    ProcessStatsStateProto.MEMORY_STATE,
+                    curState);
+            proto.write(ProcessStatsStateProto.DURATION_MS, now - curStartTime);
+            proto.end(stateToken);
+        }
+
+        proto.end(token);
+    }
 
     public String toString() {
         return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
                 + " " + mName + " pkg=" + mPackage + " proc="
-                + Integer.toHexString(System.identityHashCode(this)) + "}";
+                + Integer.toHexString(System.identityHashCode(mProc)) + "}";
     }
 }
diff --git a/core/java/com/android/internal/app/procstats/SparseMappingTable.java b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
index 91b2054..6b8703d 100644
--- a/core/java/com/android/internal/app/procstats/SparseMappingTable.java
+++ b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
@@ -175,7 +175,6 @@
          * Get the value for the given key and offset from that key.
          *
          * @param key   A key as obtained from getKey or getOrAddKey.
-         * @param value The value to set.
          */
         public long getValue(int key) {
             return getValue(key, 0);
@@ -187,7 +186,6 @@
          * @param key   A key as obtained from getKey or getOrAddKey.
          * @param index The offset from that key.  Must be less than the count
          *              provided to getOrAddKey when the space was allocated.
-         * @param value The value to set.
          *
          * @return the value, or 0 in case of an error
          */
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index f4b7032..d0f0272 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -32,10 +32,9 @@
 import android.system.Os;
 import android.system.StructStat;
 import android.util.ArrayMap;
+import android.util.Base64;
 import android.util.Log;
 
-import com.android.org.bouncycastle.util.encoders.Base64;
-
 import libcore.io.IoUtils;
 
 import java.io.BufferedOutputStream;
@@ -323,7 +322,7 @@
         BackupDataInput changeSet = new BackupDataInput(data.getFileDescriptor());
         while (changeSet.readNextHeader()) {
             String key = changeSet.getKey();
-            String base64Key = new String(Base64.encode(key.getBytes()));
+            String base64Key = new String(Base64.encode(key.getBytes(), Base64.NO_WRAP));
             int dataSize = changeSet.getDataSize();
             if (DEBUG) {
                 Log.v(TAG, "  Delta operation key " + key + "   size " + dataSize
@@ -705,7 +704,7 @@
 
         public DecodedFilename(File f) {
             file = f;
-            key = new String(Base64.decode(f.getName()));
+            key = new String(Base64.decode(f.getName(), Base64.DEFAULT));
         }
 
         @Override
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index f89a9d9..0c6f832 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -374,8 +374,12 @@
         final File parent = getFileForDocId(parentDocumentId);
         final MatrixCursor result = new DirectoryCursor(
                 resolveProjection(projection), parentDocumentId, parent);
-        for (File file : parent.listFiles()) {
-            includeFile(result, null, file);
+        if (parent.isDirectory()) {
+            for (File file : FileUtils.listFilesOrEmpty(parent)) {
+                includeFile(result, null, file);
+            }
+        } else {
+            Log.w(TAG, "parentDocumentId '" + parentDocumentId + "' is not Directory");
         }
         return result;
     }
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 3f8fd9b..c928f3f 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -70,10 +71,12 @@
 
     String[] mTempArray = new String[1];
 
+    @UnsupportedAppUsage
     public void register(Context context, Looper thread, boolean externalStorage) {
         register(context, thread, null, externalStorage);
     }
 
+    @UnsupportedAppUsage
     public void register(Context context, Looper thread, UserHandle user,
             boolean externalStorage) {
         register(context, user, externalStorage,
@@ -107,6 +110,7 @@
         return mRegisteredHandler;
     }
 
+    @UnsupportedAppUsage
     public void unregister() {
         if (mRegisteredContext == null) {
             throw new IllegalStateException("Not registered");
@@ -134,6 +138,7 @@
     /**
      * Called when a package is really removed (and not replaced).
      */
+    @UnsupportedAppUsage
     public void onPackageRemoved(String packageName, int uid) {
     }
 
@@ -167,6 +172,7 @@
      * default implementation returns true if this is a change to the entire
      * package.
      */
+    @UnsupportedAppUsage
     public boolean onPackageChanged(String packageName, int uid, String[] components) {
         if (components != null) {
             for (String name : components) {
@@ -246,6 +252,7 @@
         return mAppearingPackages != null;
     }
     
+    @UnsupportedAppUsage
     public int isPackageDisappearing(String packageName) {
         if (mDisappearingPackages != null) {
             for (int i=mDisappearingPackages.length-1; i>=0; i--) {
@@ -265,6 +272,7 @@
         return mChangeType == PACKAGE_UPDATING;
     }
 
+    @UnsupportedAppUsage
     public boolean isPackageModified(String packageName) {
         if (mModifiedPackages != null) {
             for (int i=mModifiedPackages.length-1; i>=0; i--) {
diff --git a/core/java/com/android/internal/content/ReferrerIntent.java b/core/java/com/android/internal/content/ReferrerIntent.java
index 76dcc9b..6d05f7e 100644
--- a/core/java/com/android/internal/content/ReferrerIntent.java
+++ b/core/java/com/android/internal/content/ReferrerIntent.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.content;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.os.Parcel;
 
@@ -25,8 +26,10 @@
  * Subclass of Intent that also contains referrer (as a package name) information.
  */
 public class ReferrerIntent extends Intent {
+    @UnsupportedAppUsage
     public final String mReferrer;
 
+    @UnsupportedAppUsage
     public ReferrerIntent(Intent baseIntent, String referrer) {
         super(baseIntent);
         mReferrer = referrer;
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 07bb453..8728367 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -36,17 +36,10 @@
 
     public boolean enabled(int user) {
         return pulseOnNotificationEnabled(user)
-                || pulseOnPickupEnabled(user)
-                || pulseOnDoubleTapEnabled(user)
                 || pulseOnLongPressEnabled(user)
                 || alwaysOnEnabled(user);
     }
 
-    public boolean available() {
-        return pulseOnNotificationAvailable() || pulseOnPickupAvailable()
-                || pulseOnDoubleTapAvailable();
-    }
-
     public boolean pulseOnNotificationEnabled(int user) {
         return boolSettingDefaultOn(Settings.Secure.DOZE_ENABLED, user) && pulseOnNotificationAvailable();
     }
@@ -55,36 +48,33 @@
         return ambientDisplayAvailable();
     }
 
-    public boolean pulseOnPickupEnabled(int user) {
-        boolean settingEnabled = boolSettingDefaultOn(Settings.Secure.DOZE_PULSE_ON_PICK_UP, user);
-        return (settingEnabled || alwaysOnEnabled(user)) && pulseOnPickupAvailable();
+    public boolean pickupGestureEnabled(int user) {
+        return boolSettingDefaultOn(Settings.Secure.DOZE_PICK_UP_GESTURE, user)
+                && dozePickupSensorAvailable();
     }
 
-    public boolean pulseOnPickupAvailable() {
-        return dozePulsePickupSensorAvailable() && ambientDisplayAvailable();
-    }
-
-    public boolean dozePulsePickupSensorAvailable() {
+    public boolean dozePickupSensorAvailable() {
         return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup);
     }
 
-    public boolean pulseOnPickupCanBeModified(int user) {
-        return !alwaysOnEnabled(user);
-    }
-
-    public boolean pulseOnDoubleTapEnabled(int user) {
-        return boolSettingDefaultOn(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, user)
-                && pulseOnDoubleTapAvailable();
-    }
-
-    public boolean pulseOnDoubleTapAvailable() {
-        return doubleTapSensorAvailable() && ambientDisplayAvailable();
+    public boolean doubleTapGestureEnabled(int user) {
+        return boolSettingDefaultOn(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, user)
+                && doubleTapSensorAvailable();
     }
 
     public boolean doubleTapSensorAvailable() {
         return !TextUtils.isEmpty(doubleTapSensorType());
     }
 
+    public boolean reachGestureEnabled(int user) {
+        return boolSettingDefaultOn(Settings.Secure.DOZE_REACH_GESTURE, user)
+                && reachGestureAvailable();
+    }
+
+    public boolean reachGestureAvailable() {
+        return !TextUtils.isEmpty(reachSensorType());
+    }
+
     public String doubleTapSensorType() {
         return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
     }
@@ -93,6 +83,10 @@
         return mContext.getResources().getString(R.string.config_dozeLongPressSensorType);
     }
 
+    public String reachSensorType() {
+        return mContext.getResources().getString(R.string.config_dozeReachSensorType);
+    }
+
     public boolean pulseOnLongPressEnabled(int user) {
         return pulseOnLongPressAvailable() && boolSettingDefaultOff(
                 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, user);
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index a482929..e99e39e 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -15,6 +15,7 @@
  */
 package com.android.internal.logging;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.metrics.LogMaker;
 import android.os.Build;
@@ -47,6 +48,7 @@
     public static final int VIEW_UNKNOWN = MetricsEvent.VIEW_UNKNOWN;
     public static final int LOGTAG = EventLogTags.SYSUI_MULTI_ACTION;
 
+    @UnsupportedAppUsage
     public void write(LogMaker content) {
         if (content.getType() == MetricsEvent.TYPE_UNKNOWN) {
             content.setType(MetricsEvent.TYPE_ACTION);
diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java
index d6f6d0b..9ee9710 100644
--- a/core/java/com/android/internal/net/LegacyVpnInfo.java
+++ b/core/java/com/android/internal/net/LegacyVpnInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.net.NetworkInfo;
 import android.os.Parcel;
@@ -38,7 +39,9 @@
     public static final int STATE_TIMEOUT = 4;
     public static final int STATE_FAILED = 5;
 
+    @UnsupportedAppUsage
     public String key;
+    @UnsupportedAppUsage
     public int state = -1;
     public PendingIntent intent;
 
@@ -54,6 +57,7 @@
         out.writeParcelable(intent, flags);
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<LegacyVpnInfo> CREATOR =
             new Parcelable.Creator<LegacyVpnInfo>() {
         @Override
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index c4d08c7..d1c2799 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -194,7 +194,7 @@
                 reader.finishLine();
             }
         } catch (NullPointerException|NumberFormatException e) {
-            throw new ProtocolException("problem parsing stats", e);
+            throw protocolExceptionWithCause("problem parsing stats", e);
         } finally {
             IoUtils.closeQuietly(reader);
             StrictMode.setThreadPolicy(savedPolicy);
@@ -244,7 +244,7 @@
                 reader.finishLine();
             }
         } catch (NullPointerException|NumberFormatException e) {
-            throw new ProtocolException("problem parsing stats", e);
+            throw protocolExceptionWithCause("problem parsing stats", e);
         } finally {
             IoUtils.closeQuietly(reader);
             StrictMode.setThreadPolicy(savedPolicy);
@@ -341,7 +341,7 @@
                 reader.finishLine();
             }
         } catch (NullPointerException|NumberFormatException e) {
-            throw new ProtocolException("problem parsing idx " + idx, e);
+            throw protocolExceptionWithCause("problem parsing idx " + idx, e);
         } finally {
             IoUtils.closeQuietly(reader);
             StrictMode.setThreadPolicy(savedPolicy);
@@ -378,4 +378,10 @@
 
     @VisibleForTesting
     public static native int nativeReadNetworkStatsDev(NetworkStats stats);
+
+    private static ProtocolException protocolExceptionWithCause(String message, Throwable cause) {
+        ProtocolException pe = new ProtocolException(message);
+        pe.initCause(cause);
+        return pe;
+    }
 }
diff --git a/core/java/com/android/internal/net/OWNERS b/core/java/com/android/internal/net/OWNERS
index ef44ef7..050cb5c 100644
--- a/core/java/com/android/internal/net/OWNERS
+++ b/core/java/com/android/internal/net/OWNERS
@@ -1,7 +1,9 @@
 set noparent
 
+codewiz@google.com
 ek@google.com
 jchalard@google.com
 jsharkey@android.com
 lorenzo@google.com
+reminv@google.com
 satk@google.com
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 921f1fe..fd03b3f 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -35,6 +36,7 @@
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -195,4 +197,37 @@
             return new VpnConfig[size];
         }
     };
+
+    @Override
+    public String toString() {
+        return new StringBuilder()
+                .append("VpnConfig")
+                .append("{ user=").append(user)
+                .append(", interface=").append(interfaze)
+                .append(", session=").append(session)
+                .append(", mtu=").append(mtu)
+                .append(", addresses=").append(toString(addresses))
+                .append(", routes=").append(toString(routes))
+                .append(", dns=").append(toString(dnsServers))
+                .append(", searchDomains=").append(toString(searchDomains))
+                .append(", allowedApps=").append(toString(allowedApplications))
+                .append(", disallowedApps=").append(toString(disallowedApplications))
+                .append(", configureIntent=").append(configureIntent)
+                .append(", startTime=").append(startTime)
+                .append(", legacy=").append(legacy)
+                .append(", blocking=").append(blocking)
+                .append(", allowBypass=").append(allowBypass)
+                .append(", allowIPv4=").append(allowIPv4)
+                .append(", allowIPv6=").append(allowIPv6)
+                .append(", underlyingNetworks=").append(Arrays.toString(underlyingNetworks))
+                .append("}")
+                .toString();
+    }
+
+    static <T> String toString(List<T> ls) {
+        if (ls == null) {
+            return "null";
+        }
+        return Arrays.toString(ls.toArray());
+    }
 }
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index b46bfef..bc4b5fe 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.net;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -45,10 +46,15 @@
     public static final int TYPE_MAX = 5;
 
     // Entity fields.
+    @UnsupportedAppUsage
     public final String key;           // -1
+    @UnsupportedAppUsage
     public String name = "";           // 0
+    @UnsupportedAppUsage
     public int type = TYPE_PPTP;       // 1
+    @UnsupportedAppUsage
     public String server = "";         // 2
+    @UnsupportedAppUsage
     public String username = "";       // 3
     public String password = "";       // 4
     public String dnsServers = "";     // 5
@@ -63,12 +69,14 @@
     public String ipsecServerCert = "";// 14
 
     // Helper fields.
+    @UnsupportedAppUsage
     public boolean saveLogin = false;
 
     public VpnProfile(String key) {
         this.key = key;
     }
 
+    @UnsupportedAppUsage
     public VpnProfile(Parcel in) {
         key = in.readString();
         name = in.readString();
@@ -110,6 +118,7 @@
         out.writeInt(saveLogin ? 1 : 0);
     }
 
+    @UnsupportedAppUsage
     public static VpnProfile decode(String key, byte[] value) {
         try {
             if (key == null) {
diff --git a/core/java/com/android/internal/os/AtomicFile.java b/core/java/com/android/internal/os/AtomicFile.java
index 5a83f33..e177fe3 100644
--- a/core/java/com/android/internal/os/AtomicFile.java
+++ b/core/java/com/android/internal/os/AtomicFile.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.FileUtils;
 import android.util.Log;
 
@@ -44,15 +45,18 @@
     private final File mBaseName;
     private final File mBackupName;
     
+    @UnsupportedAppUsage
     public AtomicFile(File baseName) {
         mBaseName = baseName;
         mBackupName = new File(baseName.getPath() + ".bak");
     }
     
+    @UnsupportedAppUsage
     public File getBaseFile() {
         return mBaseName;
     }
     
+    @UnsupportedAppUsage
     public FileOutputStream startWrite() throws IOException {
         // Rename the current file so it may be used as a backup during the next read
         if (mBaseName.exists()) {
@@ -86,6 +90,7 @@
         return str;
     }
     
+    @UnsupportedAppUsage
     public void finishWrite(FileOutputStream str) {
         if (str != null) {
             FileUtils.sync(str);
@@ -98,6 +103,7 @@
         }
     }
     
+    @UnsupportedAppUsage
     public void failWrite(FileOutputStream str) {
         if (str != null) {
             FileUtils.sync(str);
@@ -111,6 +117,7 @@
         }
     }
     
+    @UnsupportedAppUsage
     public FileOutputStream openAppend() throws IOException {
         try {
             return new FileOutputStream(mBaseName, true);
@@ -119,6 +126,7 @@
         }
     }
     
+    @UnsupportedAppUsage
     public void truncate() throws IOException {
         try {
             FileOutputStream fos = new FileOutputStream(mBaseName);
@@ -139,6 +147,7 @@
         mBackupName.delete();
     }
 
+    @UnsupportedAppUsage
     public FileInputStream openRead() throws FileNotFoundException {
         if (mBackupName.exists()) {
             mBaseName.delete();
@@ -147,6 +156,7 @@
         return new FileInputStream(mBaseName);
     }
     
+    @UnsupportedAppUsage
     public byte[] readFully() throws IOException {
         FileInputStream stream = openRead();
         try {
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index 5abc6d4..0baf73c 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -15,6 +15,7 @@
  */
 package com.android.internal.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.BatteryStats.Uid;
 
 import java.util.List;
@@ -23,8 +24,11 @@
  * Contains power usage of an application, system service, or hardware type.
  */
 public class BatterySipper implements Comparable<BatterySipper> {
+    @UnsupportedAppUsage
     public int userId;
+    @UnsupportedAppUsage
     public Uid uidObj;
+    @UnsupportedAppUsage
     public DrainType drainType;
 
     /**
@@ -53,6 +57,7 @@
     /**
      * Total power before smearing
      */
+    @UnsupportedAppUsage
     public double totalPowerMah;
 
     /**
@@ -65,6 +70,7 @@
     /**
      * Generic usage time in milliseconds.
      */
+    @UnsupportedAppUsage
     public long usageTimeMs;
 
     /**
@@ -76,12 +82,17 @@
     public long audioTimeMs;
     public long bluetoothRunningTimeMs;
     public long cameraTimeMs;
+    @UnsupportedAppUsage
     public long cpuFgTimeMs;
+    @UnsupportedAppUsage
     public long cpuTimeMs;
     public long flashlightTimeMs;
+    @UnsupportedAppUsage
     public long gpsTimeMs;
     public long videoTimeMs;
+    @UnsupportedAppUsage
     public long wakeLockTimeMs;
+    @UnsupportedAppUsage
     public long wifiRunningTimeMs;
 
     public long mobileRxPackets;
@@ -99,7 +110,9 @@
     public long btTxBytes;
     public double percent;
     public double noCoveragePercent;
+    @UnsupportedAppUsage
     public String[] mPackages;
+    @UnsupportedAppUsage
     public String packageWithHighestDrain;
 
     // Measured in mAh (milli-ampere per hour).
@@ -107,6 +120,7 @@
     public double audioPowerMah;
     public double bluetoothPowerMah;
     public double cameraPowerMah;
+    @UnsupportedAppUsage
     public double cpuPowerMah;
     public double flashlightPowerMah;
     public double gpsPowerMah;
@@ -118,6 +132,7 @@
 
     public enum DrainType {
         AMBIENT_DISPLAY,
+        @UnsupportedAppUsage
         APP,
         BLUETOOTH,
         CAMERA,
@@ -133,6 +148,7 @@
         WIFI,
     }
 
+    @UnsupportedAppUsage
     public BatterySipper(DrainType drainType, Uid uid, double value) {
         this.totalPowerMah = value;
         this.drainType = drainType;
@@ -162,10 +178,12 @@
     /**
      * Gets a list of packages associated with the current user
      */
+    @UnsupportedAppUsage
     public String[] getPackages() {
         return mPackages;
     }
 
+    @UnsupportedAppUsage
     public int getUid() {
         // Bail out if the current sipper is not an App sipper.
         if (uidObj == null) {
@@ -177,6 +195,7 @@
     /**
      * Add stats from other to this BatterySipper.
      */
+    @UnsupportedAppUsage
     public void add(BatterySipper other) {
         totalPowerMah += other.totalPowerMah;
         usageTimeMs += other.usageTimeMs;
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index a6b29c5..ead98e7 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -31,6 +32,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SELinux;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -74,9 +76,11 @@
     final private boolean mCollectBatteryBroadcast;
     final private boolean mWifiOnly;
 
+    @UnsupportedAppUsage
     private IBatteryStats mBatteryInfo;
     private BatteryStats mStats;
     private Intent mBatteryBroadcast;
+    @UnsupportedAppUsage
     private PowerProfile mPowerProfile;
 
     private String[] mSystemPackageArray;
@@ -86,6 +90,7 @@
     /**
      * List of apps using power.
      */
+    @UnsupportedAppUsage
     private final List<BatterySipper> mUsageList = new ArrayList<>();
 
     /**
@@ -165,14 +170,17 @@
                 profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX) != 0;
     }
 
+    @UnsupportedAppUsage
     public BatteryStatsHelper(Context context) {
         this(context, true);
     }
 
+    @UnsupportedAppUsage
     public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast) {
         this(context, collectBatteryBroadcast, checkWifiOnly(context));
     }
 
+    @UnsupportedAppUsage
     public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast, boolean wifiOnly) {
         mContext = context;
         mCollectBatteryBroadcast = collectBatteryBroadcast;
@@ -240,6 +248,7 @@
                 ServiceManager.getService(BatteryStats.SERVICE_NAME)));
     }
 
+    @UnsupportedAppUsage
     public static void dropFile(Context context, String fname) {
         makeFilePath(context, fname).delete();
     }
@@ -249,10 +258,12 @@
     }
 
     /** Clears the current stats and forces recreating for future use. */
+    @UnsupportedAppUsage
     public void clearStats() {
         mStats = null;
     }
 
+    @UnsupportedAppUsage
     public BatteryStats getStats() {
         if (mStats == null) {
             load();
@@ -260,6 +271,7 @@
         return mStats;
     }
 
+    @UnsupportedAppUsage
     public Intent getBatteryBroadcast() {
         if (mBatteryBroadcast == null && mCollectBatteryBroadcast) {
             load();
@@ -276,6 +288,7 @@
         mStats = stats;
     }
 
+    @UnsupportedAppUsage
     public void create(Bundle icicle) {
         if (icicle != null) {
             mStats = sStatsXfer;
@@ -286,6 +299,7 @@
         mPowerProfile = new PowerProfile(mContext);
     }
 
+    @UnsupportedAppUsage
     public void storeState() {
         sStatsXfer = mStats;
         sBatteryBroadcastXfer = mBatteryBroadcast;
@@ -322,6 +336,7 @@
     /**
      * Refreshes the power usage list.
      */
+    @UnsupportedAppUsage
     public void refreshStats(int statsType, int asUser) {
         SparseArray<UserHandle> users = new SparseArray<>(1);
         users.put(asUser, new UserHandle(asUser));
@@ -331,6 +346,7 @@
     /**
      * Refreshes the power usage list.
      */
+    @UnsupportedAppUsage
     public void refreshStats(int statsType, List<UserHandle> asUsers) {
         final int n = asUsers.size();
         SparseArray<UserHandle> users = new SparseArray<>(n);
@@ -344,6 +360,7 @@
     /**
      * Refreshes the power usage list.
      */
+    @UnsupportedAppUsage
     public void refreshStats(int statsType, SparseArray<UserHandle> asUsers) {
         refreshStats(statsType, asUsers, SystemClock.elapsedRealtime() * 1000,
                 SystemClock.uptimeMillis() * 1000);
@@ -782,6 +799,7 @@
         return bs;
     }
 
+    @UnsupportedAppUsage
     public List<BatterySipper> getUsageList() {
         return mUsageList;
     }
@@ -798,6 +816,7 @@
         return mStatsType;
     }
 
+    @UnsupportedAppUsage
     public double getMaxPower() {
         return mMaxPower;
     }
@@ -806,6 +825,7 @@
         return mMaxRealPower;
     }
 
+    @UnsupportedAppUsage
     public double getTotalPower() {
         return mTotalPower;
     }
@@ -1016,6 +1036,7 @@
         mServicepackageArray = array;
     }
 
+    @UnsupportedAppUsage
     private void load() {
         if (mBatteryInfo == null) {
             return;
@@ -1031,6 +1052,10 @@
         try {
             ParcelFileDescriptor pfd = service.getStatisticsStream();
             if (pfd != null) {
+                if (false) {
+                    Log.d(TAG, "selinux context: "
+                            + SELinux.getFileContext(pfd.getFileDescriptor()));
+                }
                 try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
                     byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor()));
                     Parcel parcel = Parcel.obtain();
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
new file mode 100644
index 0000000..24ad751
--- /dev/null
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.os.StatFs;
+import android.os.SystemClock;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ParseUtils;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * BatteryStatsHistory encapsulates battery history files.
+ * Battery history record is appended into buffer {@link #mHistoryBuffer} and backed up into
+ * {@link #mActiveFile}.
+ * When {@link #mHistoryBuffer} size reaches {@link BatteryStatsImpl.Constants#MAX_HISTORY_BUFFER},
+ * current mActiveFile is closed and a new mActiveFile is open.
+ * History files are under directory /data/system/battery-history/.
+ * History files have name battery-history-<num>.bin. The file number <num> starts from zero and
+ * grows sequentially.
+ * The mActiveFile is always the highest numbered history file.
+ * The lowest number file is always the oldest file.
+ * The highest number file is always the newest file.
+ * The file number grows sequentially and we never skip number.
+ * When count of history files exceeds {@link BatteryStatsImpl.Constants#MAX_HISTORY_FILES},
+ * the lowest numbered file is deleted and a new file is open.
+ *
+ * All interfaces in BatteryStatsHistory should only be called by BatteryStatsImpl and protected by
+ * locks on BatteryStatsImpl object.
+ */
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class BatteryStatsHistory {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "BatteryStatsHistory";
+    public static final String HISTORY_DIR = "battery-history";
+    public static final String FILE_SUFFIX = ".bin";
+    private static final int MIN_FREE_SPACE = 100 * 1024 * 1024;
+
+    private final BatteryStatsImpl mStats;
+    private final Parcel mHistoryBuffer;
+    private final File mHistoryDir;
+    /**
+     * The active history file that the history buffer is backed up into.
+     */
+    private AtomicFile mActiveFile;
+    /**
+     * A list of history files with incremental indexes.
+     */
+    private final List<Integer> mFileNumbers = new ArrayList<>();
+
+    /**
+     * A list of small history parcels, used when BatteryStatsImpl object is created from
+     * deserialization of a parcel, such as Settings app or checkin file.
+     */
+    private List<Parcel> mHistoryParcels = null;
+
+    /**
+     * When iterating history files, the current file index.
+     */
+    private int mCurrentFileIndex;
+    /**
+     * When iterating history files, the current file parcel.
+     */
+    private Parcel mCurrentParcel;
+    /**
+     * When iterating history file, the current parcel's Parcel.dataSize().
+     */
+    private int mCurrentParcelEnd;
+    /**
+     * When iterating history files, the current record count.
+     */
+    private int mRecordCount = 0;
+    /**
+     * Used when BatteryStatsImpl object is created from deserialization of a parcel,
+     * such as Settings app or checkin file, to iterate over history parcels.
+     */
+    private int mParcelIndex = 0;
+
+    /**
+     * Constructor
+     * @param stats BatteryStatsImpl object.
+     * @param systemDir typically /data/system
+     * @param historyBuffer The in-memory history buffer.
+     */
+    public BatteryStatsHistory(BatteryStatsImpl stats, File systemDir, Parcel historyBuffer) {
+        mStats = stats;
+        mHistoryBuffer = historyBuffer;
+        mHistoryDir = new File(systemDir, HISTORY_DIR);
+        mHistoryDir.mkdirs();
+        if (!mHistoryDir.exists()) {
+            Slog.wtf(TAG, "HistoryDir does not exist:" + mHistoryDir.getPath());
+        }
+
+        final Set<Integer> dedup = new ArraySet<>();
+        // scan directory, fill mFileNumbers and mActiveFile.
+        mHistoryDir.listFiles(new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                final int b = name.lastIndexOf(FILE_SUFFIX);
+                if (b <= 0) {
+                    return false;
+                }
+                final Integer c =
+                        ParseUtils.parseInt(name.substring(0, b), -1);
+                if (c != -1) {
+                    dedup.add(c);
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+        });
+        if (!dedup.isEmpty()) {
+            mFileNumbers.addAll(dedup);
+            Collections.sort(mFileNumbers);
+        } else {
+            // No file found, default to have file 0.
+            mFileNumbers.add(0);
+        }
+        createActiveFile();
+    }
+
+    /**
+     * 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
+     */
+    public BatteryStatsHistory(BatteryStatsImpl stats, Parcel historyBuffer) {
+        mStats = stats;
+        mHistoryDir = null;
+        mHistoryBuffer = historyBuffer;
+    }
+    /**
+     * The highest numbered history file is active file that mHistoryBuffer is backed up into.
+     * If file does not exists, truncate() creates a empty file.
+     */
+    private void createActiveFile() {
+        final AtomicFile file = getFile(mFileNumbers.get(mFileNumbers.size() - 1));
+        if (DEBUG) {
+            Slog.d(TAG, "activeHistoryFile:" + file.getBaseFile().getPath());
+        }
+        if (!file.exists()) {
+            try {
+                file.truncate();
+            } catch (IOException e) {
+                Slog.e(TAG, "Error creating history file "+ file.getBaseFile().getPath(), e);
+            }
+        }
+        mActiveFile = file;
+    }
+
+    /**
+     * Create history AtomicFile from file number.
+     * @param num file number.
+     * @return AtomicFile object.
+     */
+    private AtomicFile getFile(int num) {
+        return new AtomicFile(
+                new File(mHistoryDir,  num + FILE_SUFFIX));
+    }
+
+    /**
+     * When {@link #mHistoryBuffer} reaches {@link BatteryStatsImpl.Constants#MAX_HISTORY_BUFFER},
+     * create next history file.
+     */
+    public void createNextFile() {
+        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;
+        mFileNumbers.add(next);
+        createActiveFile();
+
+        // if free disk space is less than 100MB, delete oldest history file.
+        if (!hasFreeDiskSpace()) {
+            int oldest = mFileNumbers.remove(0);
+            getFile(oldest).delete();
+        }
+
+        // if there are more history files than allowed, delete oldest history files.
+        // MAX_HISTORY_FILES can be updated by GService config at run time.
+        while (mFileNumbers.size() > mStats.mConstants.MAX_HISTORY_FILES) {
+            int oldest = mFileNumbers.get(0);
+            getFile(oldest).delete();
+            mFileNumbers.remove(0);
+        }
+    }
+
+    /**
+     * Delete all existing history files. Active history file start from number 0 again.
+     */
+    public void resetAllFiles() {
+        for (Integer i : mFileNumbers) {
+            getFile(i).delete();
+        }
+        mFileNumbers.clear();
+        mFileNumbers.add(0);
+        createActiveFile();
+    }
+
+    /**
+     * Start iterating history files and history buffer.
+     * @return always return true.
+     */
+    public boolean startIteratingHistory() {
+        mRecordCount = 0;
+        mCurrentFileIndex = 0;
+        mCurrentParcel = null;
+        mCurrentParcelEnd = 0;
+        mParcelIndex = 0;
+        return true;
+    }
+
+    /**
+     * Finish iterating history files and history buffer.
+     */
+    public void finishIteratingHistory() {
+        // setDataPosition so mHistoryBuffer Parcel can be written.
+        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
+        if (DEBUG) {
+            Slog.d(TAG, "Battery history records iterated: " + mRecordCount);
+        }
+    }
+
+    /**
+     * When iterating history files and history buffer, always start from the lowest numbered
+     * history file, when reached the mActiveFile (highest numbered history file), do not read from
+     * mActiveFile, read from history buffer instead because the buffer has more updated data.
+     * @param out a history item.
+     * @return The parcel that has next record. null if finished all history files and history
+     *         buffer
+     */
+    public Parcel getNextParcel(BatteryStats.HistoryItem out) {
+        if (mRecordCount == 0) {
+            // reset out if it is the first record.
+            out.clear();
+        }
+        ++mRecordCount;
+
+        // First iterate through all records in current parcel.
+        if (mCurrentParcel != null)
+        {
+            if (mCurrentParcel.dataPosition() < mCurrentParcelEnd) {
+                // There are more records in current parcel.
+                return mCurrentParcel;
+            } else if (mHistoryBuffer == mCurrentParcel) {
+                // finished iterate through all history files and history buffer.
+                return null;
+            } else if (mHistoryParcels == null
+                    || !mHistoryParcels.contains(mCurrentParcel)) {
+                // current parcel is from history file.
+                mCurrentParcel.recycle();
+            }
+        }
+
+        // Try next available history file.
+        // skip the last file because its data is in history buffer.
+        while (mCurrentFileIndex < mFileNumbers.size() - 1) {
+            mCurrentParcel = null;
+            mCurrentParcelEnd = 0;
+            final Parcel p = Parcel.obtain();
+            AtomicFile file = getFile(mFileNumbers.get(mCurrentFileIndex++));
+            if (readFileToParcel(p, file)) {
+                int bufSize = p.readInt();
+                int curPos = p.dataPosition();
+                mCurrentParcelEnd = curPos + bufSize;
+                mCurrentParcel = p;
+                if (curPos < mCurrentParcelEnd) {
+                    return mCurrentParcel;
+                }
+            } else {
+                p.recycle();
+            }
+        }
+
+        // mHistoryParcels is created when BatteryStatsImpl object is created from deserialization
+        // of a parcel, such as Settings app or checkin file.
+        if (mHistoryParcels != null) {
+            while (mParcelIndex < mHistoryParcels.size()) {
+                final Parcel p = mHistoryParcels.get(mParcelIndex++);
+                if (!skipHead(p)) {
+                    continue;
+                }
+                final int bufSize = p.readInt();
+                final int curPos = p.dataPosition();
+                mCurrentParcelEnd = curPos + bufSize;
+                mCurrentParcel = p;
+                if (curPos < mCurrentParcelEnd) {
+                    return mCurrentParcel;
+                }
+            }
+        }
+
+        // finished iterator through history files (except the last one), now history buffer.
+        if (mHistoryBuffer.dataSize() <= 0) {
+            // buffer is empty.
+            return null;
+        }
+        mHistoryBuffer.setDataPosition(0);
+        mCurrentParcel = mHistoryBuffer;
+        mCurrentParcelEnd = mCurrentParcel.dataSize();
+        return mCurrentParcel;
+    }
+
+    /**
+     * Read history file into a parcel.
+     * @param out the Parcel read into.
+     * @param file the File to read from.
+     * @return true if success, false otherwise.
+     */
+    public boolean readFileToParcel(Parcel out, AtomicFile file) {
+        byte[] raw = null;
+        try {
+            final long start = SystemClock.uptimeMillis();
+            raw = file.readFully();
+            if (DEBUG) {
+                Slog.d(TAG, "readFileToParcel:" + file.getBaseFile().getPath()
+                        + " duration ms:" + (SystemClock.uptimeMillis() - start));
+            }
+        } catch(Exception e) {
+            Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
+            return false;
+        }
+        out.unmarshall(raw, 0, raw.length);
+        out.setDataPosition(0);
+        return skipHead(out);
+    }
+
+    /**
+     * Skip the header part of history parcel.
+     * @param p history parcel to skip head.
+     * @return true if version match, false if not.
+     */
+    private boolean skipHead(Parcel p) {
+        p.setDataPosition(0);
+        final int version = p.readInt();
+        if (version != mStats.VERSION) {
+            return false;
+        }
+        // skip historyBaseTime field.
+        p.readLong();
+        return true;
+    }
+
+    /**
+     * Read all history files and serialize into a big Parcel. This is to send history files to
+     * Settings app since Settings app can not access /data/system directory.
+     * Checkin file also call this method.
+     * @param out the output parcel
+     */
+    public void writeToParcel(Parcel out) {
+        final long start = SystemClock.uptimeMillis();
+        out.writeInt(mFileNumbers.size() - 1);
+        for(int i = 0;  i < mFileNumbers.size() - 1; i++) {
+            AtomicFile file = getFile(mFileNumbers.get(i));
+            byte[] raw = new byte[0];
+            try {
+                raw = file.readFully();
+            } catch(Exception e) {
+                Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
+            }
+            out.writeByteArray(raw);
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start));
+        }
+    }
+
+    /**
+     * This is for Settings app, when Settings app receives big history parcel, it call
+     * this method to parse it into list of parcels.
+     * Checkin file also call this method.
+     * @param in the input parcel.
+     */
+    public void readFromParcel(Parcel in) {
+        final long start = SystemClock.uptimeMillis();
+        mHistoryParcels = new ArrayList<>();
+        final int count = in.readInt();
+        for(int i = 0; i < count; i++) {
+            byte[] temp = in.createByteArray();
+            if (temp.length == 0) {
+                continue;
+            }
+            Parcel p = Parcel.obtain();
+            p.unmarshall(temp, 0, temp.length);
+            p.setDataPosition(0);
+            mHistoryParcels.add(p);
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "readFromParcel duration ms:" + (SystemClock.uptimeMillis() - start));
+        }
+    }
+
+    /**
+     * @return true if there is more than 100MB free disk space left.
+     */
+    private boolean hasFreeDiskSpace() {
+        final StatFs stats = new StatFs(mHistoryDir.getAbsolutePath());
+        return stats.getAvailableBytes() > MIN_FREE_SPACE;
+    }
+
+    public List<Integer> getFilesNumbers() {
+        return mFileNumbers;
+    }
+
+    public AtomicFile getActiveFile() {
+        return mActiveFile;
+    }
+
+    /**
+     * @return the total size of all history files and history buffer.
+     */
+    public int getHistoryUsedSize() {
+        int ret = 0;
+        for(int i = 0; i < mFileNumbers.size() - 1; i++) {
+            ret += getFile(mFileNumbers.get(i)).getBaseFile().length();
+        }
+        ret += mHistoryBuffer.dataSize();
+        if (mHistoryParcels != null) {
+            for(int i = 0; i < mHistoryParcels.size(); i++) {
+                ret += mHistoryParcels.get(i).dataSize();
+            }
+        }
+        return ret;
+    }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index d7db2e2..07f74f0 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.UidTraffic;
@@ -36,7 +37,6 @@
 import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.Build;
-import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBatteryPropertiesRegistrar;
 import android.os.Looper;
@@ -90,7 +90,6 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.JournaledFile;
 import com.android.internal.util.XmlUtils;
 
 import libcore.util.EmptyArray;
@@ -110,7 +109,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -140,35 +141,18 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 177 + (USE_OLD_HISTORY ? 1000 : 0);
-
-    // Maximum number of items we will record in the history.
-    private static final int MAX_HISTORY_ITEMS;
-
-    // No, really, THIS is the maximum number of items we will record in the history.
-    private static final int MAX_MAX_HISTORY_ITEMS;
+    static final int VERSION = 185 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // The maximum number of names wakelocks we will keep track of
     // per uid; once the limit is reached, we batch the remaining wakelocks
     // in to one common name.
     private static final int MAX_WAKELOCKS_PER_UID;
 
-    static final int MAX_HISTORY_BUFFER; // 256KB
-    static final int MAX_MAX_HISTORY_BUFFER; // 320KB
-
     static {
         if (ActivityManager.isLowRamDeviceStatic()) {
-            MAX_HISTORY_ITEMS = 800;
-            MAX_MAX_HISTORY_ITEMS = 1200;
             MAX_WAKELOCKS_PER_UID = 40;
-            MAX_HISTORY_BUFFER = 96*1024;  // 96KB
-            MAX_MAX_HISTORY_BUFFER = 128*1024; // 128KB
         } else {
-            MAX_HISTORY_ITEMS = 4000;
-            MAX_MAX_HISTORY_ITEMS = 6000;
             MAX_WAKELOCKS_PER_UID = 200;
-            MAX_HISTORY_BUFFER = 512*1024;  // 512KB
-            MAX_MAX_HISTORY_BUFFER = 640*1024;  // 640KB
         }
     }
 
@@ -189,7 +173,7 @@
 
     protected Clocks mClocks;
 
-    private final JournaledFile mFile;
+    private final AtomicFile mStatsFile;
     public final AtomicFile mCheckinFile;
     public final AtomicFile mDailyFile;
 
@@ -229,6 +213,15 @@
     public boolean mPerProcStateCpuTimesAvailable = true;
 
     /**
+     * When per process state cpu times tracking is off, cpu times in KernelSingleUidTimeReader are
+     * not updated. So, when the setting is turned on later, we would end up with huge cpu time
+     * deltas. This flag tracks the case where tracking is turned on from off so that we won't
+     * end up attributing the huge deltas to wrong buckets.
+     */
+    @GuardedBy("this")
+    private boolean mIsPerProcessStateCpuDataStale;
+
+    /**
      * Uids for which per-procstate cpu times need to be updated.
      *
      * Contains uid -> procState mappings.
@@ -401,7 +394,7 @@
             }
             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
             // compute deltas since it might result in mis-attributing cpu times to wrong states.
-            if (mKernelSingleUidTimeReader.hasStaleData()) {
+            if (mIsPerProcessStateCpuDataStale) {
                 mPendingUids.clear();
                 return;
             }
@@ -484,9 +477,9 @@
                     mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs();
             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
             // compute deltas since it might result in mis-attributing cpu times to wrong states.
-            if (mKernelSingleUidTimeReader.hasStaleData()) {
+            if (mIsPerProcessStateCpuDataStale) {
                 mKernelSingleUidTimeReader.setAllUidsCpuTimesMs(allUidCpuFreqTimesMs);
-                mKernelSingleUidTimeReader.markDataAsStale(false);
+                mIsPerProcessStateCpuDataStale = false;
                 mPendingUids.clear();
                 return;
             }
@@ -610,8 +603,11 @@
     // In order to do this, we must refresh each timer whenever the number of active timers
     // changes.
     @VisibleForTesting
+    @UnsupportedAppUsage
     protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
+    @UnsupportedAppUsage
     final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
+    @UnsupportedAppUsage
     final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
     final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
     final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
@@ -632,11 +628,11 @@
 
     // These are the objects that will want to do something when the device
     // is unplugged from power.
-    protected final TimeBase mOnBatteryTimeBase = new TimeBase();
+    protected final TimeBase mOnBatteryTimeBase = new TimeBase(true);
 
     // These are the objects that will want to do something when the device
     // is unplugged from power *and* the screen is off or doze.
-    protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
+    protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
 
     // Set to true when we want to distribute CPU across wakelocks for the next
     // CPU update, even if we aren't currently running wake locks.
@@ -663,13 +659,14 @@
     int mNextHistoryTagIdx = 0;
     int mNumHistoryTagChars = 0;
     int mHistoryBufferLastPos = -1;
-    boolean mHistoryOverflow = false;
     int mActiveHistoryStates = 0xffffffff;
     int mActiveHistoryStates2 = 0xffffffff;
     long mLastHistoryElapsedRealtime = 0;
     long mTrackRunningHistoryElapsedRealtime = 0;
     long mTrackRunningHistoryUptime = 0;
 
+    final BatteryStatsHistory mBatteryStatsHistory;
+
     final HistoryItem mHistoryCur = new HistoryItem();
 
     HistoryItem mHistory;
@@ -963,7 +960,7 @@
     protected PowerProfile mPowerProfile;
 
     @GuardedBy("this")
-    private final Constants mConstants;
+    final Constants mConstants;
 
     /*
      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
@@ -989,6 +986,7 @@
      */
     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
 
+    @UnsupportedAppUsage
     public Map<String, ? extends Timer> getKernelWakelockStats() {
         return mKernelWakelockStats;
     }
@@ -1047,9 +1045,10 @@
 
     public BatteryStatsImpl(Clocks clocks) {
         init(clocks);
-        mFile = null;
+        mStatsFile = null;
         mCheckinFile = null;
         mDailyFile = null;
+        mBatteryStatsHistory = null;
         mHandler = null;
         mPlatformIdleStateCallback = null;
         mUserInfoProvider = null;
@@ -1061,15 +1060,29 @@
         mClocks = clocks;
     }
 
+    /**
+     * TimeBase observer.
+     */
     public interface TimeBaseObs {
         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
+
+        /**
+         * Reset the observer's state, returns true if the timer/counter is inactive
+         * so it can be destroyed.
+         * @param detachIfReset detach if true, no-op if false.
+         * @return Returns true if the timer/counter is inactive and can be destroyed.
+         */
+        boolean reset(boolean detachIfReset);
+        /**
+         * Detach the observer from TimeBase.
+         */
+        void detach();
     }
 
     // methods are protected not private to be VisibleForTesting
     public static class TimeBase {
-        protected final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
-
+        protected final Collection<TimeBaseObs> mObservers;
         protected long mUptime;
         protected long mRealtime;
 
@@ -1110,15 +1123,29 @@
                     sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
             pw.println(sb.toString());
         }
+        /**
+         * The mObservers of TimeBase in BatteryStatsImpl object can contain up to 20k entries.
+         * The mObservers of TimeBase in BatteryStatsImpl.Uid object only contains a few or tens of
+         * entries.
+         * mObservers must have good performance on add(), remove(), also be memory efficient.
+         * This is why we provide isLongList parameter for long and short list user cases.
+         * @param isLongList If true, use HashSet for mObservers list.
+         *                   If false, use ArrayList for mObservers list.
+        */
+        public TimeBase(boolean isLongList) {
+            mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
+        }
+
+        public TimeBase() {
+            this(false);
+        }
 
         public void add(TimeBaseObs observer) {
             mObservers.add(observer);
         }
 
         public void remove(TimeBaseObs observer) {
-            if (!mObservers.remove(observer)) {
-                Slog.wtf(TAG, "Removed unknown observer: " + observer);
-            }
+            mObservers.remove(observer);
         }
 
         public boolean hasObserver(TimeBaseObs observer) {
@@ -1211,19 +1238,24 @@
                     mRealtimeStart = realtime;
                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
-
-                    for (int i = mObservers.size() - 1; i >= 0; i--) {
-                        mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
+                    // Normally we do not use Iterator in framework code to avoid alloc/dealloc
+                    // Iterator object, here is an exception because mObservers' type is Collection
+                    // instead of list.
+                    final Iterator<TimeBaseObs> iter = mObservers.iterator();
+                    while (iter.hasNext()) {
+                        iter.next().onTimeStarted(realtime, batteryUptime, batteryRealtime);
                     }
                 } else {
                     mPastUptime += uptime - mUptimeStart;
                     mPastRealtime += realtime - mRealtimeStart;
-
                     long batteryUptime = getUptime(uptime);
                     long batteryRealtime = getRealtime(realtime);
-
-                    for (int i = mObservers.size() - 1; i >= 0; i--) {
-                        mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
+                    // Normally we do not use Iterator in framework code to avoid alloc/dealloc
+                    // Iterator object, here is an exception because mObservers' type is Collection
+                    // instead of list.
+                    final Iterator<TimeBaseObs> iter = mObservers.iterator();
+                    while (iter.hasNext()) {
+                        iter.next().onTimeStopped(realtime, batteryUptime, batteryRealtime);
                     }
                 }
                 return true;
@@ -1271,6 +1303,7 @@
      * State for keeping track of counting information.
      */
     public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
+        @UnsupportedAppUsage
         final AtomicInteger mCount = new AtomicInteger();
         final TimeBase mTimeBase;
         int mLoadedCount;
@@ -1371,15 +1404,18 @@
         /**
          * Clear state of this counter.
          */
-        void reset(boolean detachIfReset) {
+        @Override
+        public boolean reset(boolean detachIfReset) {
             mCount.set(0);
             mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
             if (detachIfReset) {
                 detach();
             }
+            return true;
         }
 
-        void detach() {
+        @Override
+        public void detach() {
             mTimeBase.remove(this);
         }
 
@@ -1475,15 +1511,18 @@
         /**
          * Clear state of this counter.
          */
-        public void reset(boolean detachIfReset) {
+        @Override
+        public boolean reset(boolean detachIfReset) {
             fillArray(mCounts, 0);
             fillArray(mLoadedCounts, 0);
             fillArray(mUnpluggedCounts, 0);
             if (detachIfReset) {
                 detach();
             }
+            return true;
         }
 
+        @Override
         public void detach() {
             mTimeBase.remove(this);
         }
@@ -1646,14 +1685,17 @@
         /**
          * Clear state of this counter.
          */
-        public void reset(boolean detachIfReset) {
+        @Override
+        public boolean reset(boolean detachIfReset) {
             mCount = 0;
             mLoadedCount = mUnpluggedCount = 0;
             if (detachIfReset) {
                 detach();
             }
+            return true;
         }
 
+        @Override
         public void detach() {
             mTimeBase.remove(this);
         }
@@ -1754,6 +1796,7 @@
          * Clear state of this timer.  Returns true if the timer is inactive
          * so can be completely dropped.
          */
+        @Override
         public boolean reset(boolean detachIfReset) {
             mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0;
             mCount = mLoadedCount = mLastCount = 0;
@@ -1763,6 +1806,7 @@
             return true;
         }
 
+        @Override
         public void detach() {
             mTimeBase.remove(this);
         }
@@ -1815,6 +1859,7 @@
          * @param out the Parcel to be written to.
          * @param timer a Timer, or null.
          */
+        @UnsupportedAppUsage
         public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
             if (timer == null) {
                 out.writeInt(0); // indicates null
@@ -1826,6 +1871,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
             long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
             if (which == STATS_SINCE_UNPLUGGED) {
@@ -1838,6 +1884,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public int getCountLocked(int which) {
             int val = computeCurrentCountLocked();
             if (which == STATS_SINCE_UNPLUGGED) {
@@ -2613,6 +2660,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public void detach() {
             super.detach();
             if (mTimerPool != null) {
@@ -3154,8 +3202,13 @@
     }
 
     private void readHistoryTag(int index, HistoryTag tag) {
-        tag.string = mReadHistoryStrings[index];
-        tag.uid = mReadHistoryUids[index];
+        if (index < mReadHistoryStrings.length) {
+            tag.string = mReadHistoryStrings[index];
+            tag.uid = mReadHistoryUids[index];
+        } else {
+            tag.string = null;
+            tag.uid = 0;
+        }
         tag.poolIdx = index;
     }
 
@@ -3674,6 +3727,13 @@
         mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
     }
 
+    public void createFakeHistoryEvents(long numEvents) {
+        for(long i = 0; i < numEvents; i++) {
+            noteWifiOnLocked();
+            noteWifiOffLocked();
+        }
+    }
+
     void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) {
         if (!mHaveBatteryLevel || !mRecordingHistory) {
             return;
@@ -3736,74 +3796,32 @@
             }
             mHistoryLastWritten.setTo(mHistoryLastLastWritten);
         }
-
-        boolean recordResetDueToOverflow = false;
         final int dataSize = mHistoryBuffer.dataSize();
-        if (dataSize >= MAX_MAX_HISTORY_BUFFER*3) {
-            // Clients can't deal with history buffers this large. This only
-            // really happens when the device is on charger and interacted with
-            // for long periods of time, like in retail mode. Since the device is
-            // most likely charged, when unplugged, stats would have reset anyways.
-            // Reset the stats and mark that we overflowed.
-            // b/32540341
-            resetAllStatsLocked();
 
-            // Mark that we want to set *OVERFLOW* event and the RESET:START
-            // events.
-            recordResetDueToOverflow = true;
-
-        } else if (dataSize >= MAX_HISTORY_BUFFER) {
-            if (!mHistoryOverflow) {
-                mHistoryOverflow = true;
-                addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
-                addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
-                return;
+        if (dataSize >= mConstants.MAX_HISTORY_BUFFER) {
+            //open a new history file.
+            final long start = SystemClock.uptimeMillis();
+            writeHistoryLocked(true);
+            if (DEBUG) {
+                Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
+                        + (SystemClock.uptimeMillis() - start));
             }
-
-            // After overflow, we allow various bit-wise states to settle to 0.
-            boolean writeAnyway = false;
-            final int curStates = cur.states & HistoryItem.SETTLE_TO_ZERO_STATES
-                    & mActiveHistoryStates;
-            if (mHistoryLastWritten.states != curStates) {
-                // mActiveHistoryStates keeps track of which bits in .states are now being
-                // forced to 0.
-                int old = mActiveHistoryStates;
-                mActiveHistoryStates &= curStates | ~HistoryItem.SETTLE_TO_ZERO_STATES;
-                writeAnyway |= old != mActiveHistoryStates;
-            }
-            final int curStates2 = cur.states2 & HistoryItem.SETTLE_TO_ZERO_STATES2
-                    & mActiveHistoryStates2;
-            if (mHistoryLastWritten.states2 != curStates2) {
-                // mActiveHistoryStates2 keeps track of which bits in .states2 are now being
-                // forced to 0.
-                int old = mActiveHistoryStates2;
-                mActiveHistoryStates2 &= curStates2 | ~HistoryItem.SETTLE_TO_ZERO_STATES2;
-                writeAnyway |= old != mActiveHistoryStates2;
-            }
-
-            // Once we've reached the maximum number of items, we only
-            // record changes to the battery level and the most interesting states.
-            // Once we've reached the maximum maximum number of items, we only
-            // record changes to the battery level.
-            if (!writeAnyway && mHistoryLastWritten.batteryLevel == cur.batteryLevel &&
-                    (dataSize >= MAX_MAX_HISTORY_BUFFER
-                            || ((mHistoryLastWritten.states^cur.states)
-                                    & HistoryItem.MOST_INTERESTING_STATES) == 0
-                            || ((mHistoryLastWritten.states2^cur.states2)
-                                    & HistoryItem.MOST_INTERESTING_STATES2) == 0)) {
-                return;
-            }
+            mBatteryStatsHistory.createNextFile();
+            mHistoryBuffer.setDataSize(0);
+            mHistoryBuffer.setDataPosition(0);
+            mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
+            mHistoryBufferLastPos = -1;
+            final long elapsedRealtime = mClocks.elapsedRealtime();
+            final long uptime = mClocks.uptimeMillis();
+            startRecordingHistory(elapsedRealtime, uptime, false);
 
             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
             return;
         }
 
-        if (dataSize == 0 || recordResetDueToOverflow) {
+        if (dataSize == 0) {
             // The history is currently empty; we need it to start with a time stamp.
             cur.currentTime = System.currentTimeMillis();
-            if (recordResetDueToOverflow) {
-                addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
-            }
             addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
         }
         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
@@ -3891,26 +3909,6 @@
 
         mChangedStates = 0;
         mChangedStates2 = 0;
-
-        if (mNumHistoryItems == MAX_HISTORY_ITEMS
-                || mNumHistoryItems == MAX_MAX_HISTORY_ITEMS) {
-            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_OVERFLOW, cur);
-        }
-
-        if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
-            // Once we've reached the maximum number of items, we only
-            // record changes to the battery level and the most interesting states.
-            // Once we've reached the maximum maximum number of items, we only
-            // record changes to the battery level.
-            if (mHistoryEnd != null && mHistoryEnd.batteryLevel
-                    == cur.batteryLevel &&
-                    (mNumHistoryItems >= MAX_MAX_HISTORY_ITEMS
-                            || ((mHistoryEnd.states^(cur.states&mActiveHistoryStates))
-                                    & HistoryItem.MOST_INTERESTING_STATES) == 0)) {
-                return;
-            }
-        }
-
         addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
     }
 
@@ -3965,14 +3963,13 @@
 
         mHistoryBuffer.setDataSize(0);
         mHistoryBuffer.setDataPosition(0);
-        mHistoryBuffer.setDataCapacity(MAX_HISTORY_BUFFER / 2);
+        mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
         mHistoryLastLastWritten.clear();
         mHistoryLastWritten.clear();
         mHistoryTagPool.clear();
         mNextHistoryTagIdx = 0;
         mNumHistoryTagChars = 0;
         mHistoryBufferLastPos = -1;
-        mHistoryOverflow = false;
         mActiveHistoryStates = 0xffffffff;
         mActiveHistoryStates2 = 0xffffffff;
     }
@@ -4021,7 +4018,9 @@
         try {
             IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(
                     ServiceManager.getService("batteryproperties"));
-            registrar.scheduleUpdate();
+            if (registrar != null) {
+                registrar.scheduleUpdate();
+            }
         } catch (RemoteException e) {
             // Ignore.
         }
@@ -4942,6 +4941,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void noteScreenBrightnessLocked(int brightness) {
         // Bin the brightness.
         int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
@@ -4965,6 +4965,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void noteUserActivityLocked(int uid, int event) {
         if (mOnBatteryInternal) {
             uid = mapUid(uid);
@@ -5199,6 +5200,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void notePhoneOnLocked() {
         if (!mPhoneOn) {
             final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -5212,6 +5214,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void notePhoneOffLocked() {
         if (mPhoneOn) {
             final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -5381,12 +5384,14 @@
         updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw);
     }
 
+    @UnsupportedAppUsage
     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
         // Bin the strength.
         int bin = signalStrength.getLevel();
         updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin);
     }
 
+    @UnsupportedAppUsage
     public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
         // BatteryStats uses 0 to represent no network type.
         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
@@ -5445,6 +5450,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void noteAudioOnLocked(int uid) {
         uid = mapUid(uid);
         final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -5460,6 +5466,7 @@
         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
     }
 
+    @UnsupportedAppUsage
     public void noteAudioOffLocked(int uid) {
         if (mAudioOnNesting == 0) {
             return;
@@ -5477,6 +5484,7 @@
         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
     }
 
+    @UnsupportedAppUsage
     public void noteVideoOnLocked(int uid) {
         uid = mapUid(uid);
         final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -5492,6 +5500,7 @@
         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
     }
 
+    @UnsupportedAppUsage
     public void noteVideoOffLocked(int uid) {
         if (mVideoOnNesting == 0) {
             return;
@@ -5967,6 +5976,7 @@
 
     int mWifiFullLockNesting = 0;
 
+    @UnsupportedAppUsage
     public void noteFullWifiLockAcquiredLocked(int uid) {
         final long elapsedRealtime = mClocks.elapsedRealtime();
         final long uptime = mClocks.uptimeMillis();
@@ -5980,6 +5990,7 @@
         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
     }
 
+    @UnsupportedAppUsage
     public void noteFullWifiLockReleasedLocked(int uid) {
         final long elapsedRealtime = mClocks.elapsedRealtime();
         final long uptime = mClocks.uptimeMillis();
@@ -6035,6 +6046,7 @@
 
     int mWifiMulticastNesting = 0;
 
+    @UnsupportedAppUsage
     public void noteWifiMulticastEnabledLocked(int uid) {
         uid = mapUid(uid);
         final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -6055,6 +6067,7 @@
         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
     }
 
+    @UnsupportedAppUsage
     public void noteWifiMulticastDisabledLocked(int uid) {
         uid = mapUid(uid);
         final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -6251,6 +6264,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
         return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
@@ -6267,6 +6281,7 @@
         return mScreenDozeTimer.getCountLocked(which);
     }
 
+    @UnsupportedAppUsage
     @Override public long getScreenBrightnessTime(int brightnessBin,
             long elapsedRealtimeUs, int which) {
         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
@@ -6376,6 +6391,7 @@
         return (long) energyUsedMaMs;
     }
 
+    @UnsupportedAppUsage
     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
@@ -6384,12 +6400,14 @@
         return mPhoneOnTimer.getCountLocked(which);
     }
 
+    @UnsupportedAppUsage
     @Override public long getPhoneSignalStrengthTime(int strengthBin,
             long elapsedRealtimeUs, int which) {
         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
                 elapsedRealtimeUs, which);
     }
 
+    @UnsupportedAppUsage
     @Override public long getPhoneSignalScanningTime(
             long elapsedRealtimeUs, int which) {
         return mPhoneSignalScanningTimer.getTotalTimeLocked(
@@ -6400,6 +6418,7 @@
         return mPhoneSignalScanningTimer;
     }
 
+    @UnsupportedAppUsage
     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
         return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
     }
@@ -6408,12 +6427,14 @@
         return mPhoneSignalStrengthsTimer[strengthBin];
     }
 
+    @UnsupportedAppUsage
     @Override public long getPhoneDataConnectionTime(int dataType,
             long elapsedRealtimeUs, int which) {
         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
                 elapsedRealtimeUs, which);
     }
 
+    @UnsupportedAppUsage
     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
     }
@@ -6422,6 +6443,7 @@
         return mPhoneDataConnectionsTimer[dataType];
     }
 
+    @UnsupportedAppUsage
     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
@@ -6452,6 +6474,7 @@
         return mWifiMulticastWakelockTimer.getCountLocked(which);
     }
 
+    @UnsupportedAppUsage
     @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
         return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
@@ -6460,6 +6483,7 @@
         return mWifiActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
 
+    @UnsupportedAppUsage
     @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
         return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
@@ -6557,6 +6581,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public long getNetworkActivityBytes(int type, int which) {
         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
             return mNetworkByteActivityCounters[type].getCountLocked(which);
@@ -6599,42 +6624,74 @@
         return mOnBattery;
     }
 
+    @UnsupportedAppUsage
     @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
         return mUidStats;
     }
 
-    private static void detachTimerIfNotNull(BatteryStatsImpl.Timer timer) {
-        if (timer != null) {
-            timer.detach();
-        }
-    }
-
-    private static boolean resetTimerIfNotNull(BatteryStatsImpl.Timer timer,
-            boolean detachIfReset) {
-        if (timer != null) {
-            return timer.reset(detachIfReset);
+    private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset) {
+        if (t != null) {
+            return t.reset(detachIfReset);
         }
         return true;
     }
 
-    private static boolean resetTimerIfNotNull(DualTimer timer, boolean detachIfReset) {
-        if (timer != null) {
-            return timer.reset(detachIfReset);
+    private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset) {
+        if (t != null) {
+            boolean ret = true;
+            for (int i = 0; i < t.length; i++) {
+                ret &= resetIfNotNull(t[i], detachIfReset);
+            }
+            return ret;
         }
         return true;
     }
 
-    private static void detachLongCounterIfNotNull(LongSamplingCounter counter) {
-        if (counter != null) {
-            counter.detach();
+    private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset) {
+        if (t != null) {
+            boolean ret = true;
+            for (int i = 0; i < t.length; i++) {
+                ret &= resetIfNotNull(t[i], detachIfReset);
+            }
+            return ret;
         }
+        return true;
     }
 
-    private static void resetLongCounterIfNotNull(LongSamplingCounter counter,
+    private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
             boolean detachIfReset) {
         if (counter != null) {
             counter.reset(detachIfReset);
         }
+        return true;
+    }
+
+    private static <T extends TimeBaseObs> void detachIfNotNull(T t) {
+        if (t != null) {
+            t.detach();
+        }
+    }
+
+    private static <T extends TimeBaseObs> void detachIfNotNull(T[] t) {
+        if (t != null) {
+            for (int i = 0; i < t.length; i++) {
+                detachIfNotNull(t[i]);
+            }
+        }
+    }
+
+    private static <T extends TimeBaseObs> void detachIfNotNull(T[][] t) {
+        if (t != null) {
+            for (int i = 0; i < t.length; i++) {
+                detachIfNotNull(t[i]);
+            }
+        }
+    }
+
+    private static void detachIfNotNull(ControllerActivityCounterImpl counter) {
+        if (counter != null) {
+            counter.detach();
+        }
     }
 
     /**
@@ -6667,7 +6724,7 @@
         int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
         StopwatchTimer[] mWifiBatchedScanTimer;
 
-        boolean mWifiMulticastEnabled;
+        int mWifiMulticastWakelockCount;
         StopwatchTimer mWifiMulticastTimer;
 
         StopwatchTimer mAudioTurnedOnTimer;
@@ -6814,11 +6871,12 @@
             mBsi = bsi;
             mUid = uid;
 
-            mOnBatteryBackgroundTimeBase = new TimeBase();
+            /* Observer list of TimeBase object in Uid is short */
+            mOnBatteryBackgroundTimeBase = new TimeBase(false);
             mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
                     mBsi.mClocks.elapsedRealtime() * 1000);
-
-            mOnBatteryScreenOffBackgroundTimeBase = new TimeBase();
+            /* Observer list of TimeBase object in Uid is short */
+            mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
             mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
                     mBsi.mClocks.elapsedRealtime() * 1000);
 
@@ -6957,6 +7015,7 @@
             }
             if (mProcStateTimeMs[procState] == null
                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
+                detachIfNotNull(mProcStateTimeMs[procState]);
                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
                         mBsi.mOnBatteryTimeBase);
             }
@@ -6970,6 +7029,7 @@
             }
             if (mProcStateScreenOffTimeMs[procState] == null
                     || mProcStateScreenOffTimeMs[procState].getSize() != cpuTimesMs.length) {
+                detachIfNotNull(mProcStateScreenOffTimeMs[procState]);
                 mProcStateScreenOffTimeMs[procState] = new LongSamplingCounterArray(
                         mBsi.mOnBatteryScreenOffTimeBase);
             }
@@ -6982,6 +7042,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
             return mWakelockStats.getMap();
         }
@@ -7007,11 +7068,13 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
             return mSensorStats;
         }
 
         @Override
+        @UnsupportedAppUsage
         public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
             return mProcessStats;
         }
@@ -7022,6 +7085,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public int getUid() {
             return mUid;
         }
@@ -7119,8 +7183,7 @@
 
         @Override
         public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
-            if (!mWifiMulticastEnabled) {
-                mWifiMulticastEnabled = true;
+            if (mWifiMulticastWakelockCount == 0) {
                 if (mWifiMulticastTimer == null) {
                     mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
                             WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
@@ -7130,12 +7193,17 @@
                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED__STATE__ON);
             }
+            mWifiMulticastWakelockCount++;
         }
 
         @Override
         public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
-            if (mWifiMulticastEnabled) {
-                mWifiMulticastEnabled = false;
+            if (mWifiMulticastWakelockCount == 0) {
+                return;
+            }
+
+            mWifiMulticastWakelockCount--;
+            if (mWifiMulticastWakelockCount == 0) {
                 mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
                 StatsLog.write_non_chained(
                         StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null,
@@ -7409,6 +7477,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
             if (mWifiRunningTimer == null) {
                 return 0;
@@ -7425,6 +7494,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public long getWifiScanTime(long elapsedRealtimeUs, int which) {
             if (mWifiScanTimer == null) {
                 return 0;
@@ -7574,6 +7644,7 @@
         void makeProcessState(int i, Parcel in) {
             if (i < 0 || i >= NUM_PROCESS_STATE) return;
 
+            detachIfNotNull(mProcessStateTimer[i]);
             if (in == null) {
                 mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
                         mBsi.mOnBatteryTimeBase);
@@ -7637,6 +7708,7 @@
                 collected = new ArrayList<StopwatchTimer>();
                 mBsi.mWifiBatchedScanTimers.put(i, collected);
             }
+            detachIfNotNull(mWifiBatchedScanTimer[i]);
             if (in == null) {
                 mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
                         collected, mBsi.mOnBatteryTimeBase);
@@ -7648,6 +7720,7 @@
 
 
         void initUserActivityLocked() {
+            detachIfNotNull(mUserActivityCounters);
             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
@@ -7816,13 +7889,17 @@
         }
 
         void initNetworkActivityLocked() {
+            detachIfNotNull(mNetworkByteActivityCounters);
             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
+            detachIfNotNull(mNetworkPacketActivityCounters);
             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
                 mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
                 mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
             }
+            detachIfNotNull(mMobileRadioActiveTime);
             mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+            detachIfNotNull(mMobileRadioActiveCount);
             mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
         }
 
@@ -7859,30 +7936,25 @@
             }
             if (mWifiMulticastTimer != null) {
                 active |= !mWifiMulticastTimer.reset(false);
-                active |= mWifiMulticastEnabled;
+                active |= (mWifiMulticastWakelockCount > 0);
             }
 
-            active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false);
-            active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false);
-            active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
-            active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
-            active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
-            active |= !resetTimerIfNotNull(mForegroundServiceTimer, false);
-            active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false);
-            active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
-            active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false);
-            if (mBluetoothScanResultCounter != null) {
-                mBluetoothScanResultCounter.reset(false);
-            }
-            if (mBluetoothScanResultBgCounter != null) {
-                mBluetoothScanResultBgCounter.reset(false);
-            }
+            active |= !resetIfNotNull(mAudioTurnedOnTimer, false);
+            active |= !resetIfNotNull(mVideoTurnedOnTimer, false);
+            active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false);
+            active |= !resetIfNotNull(mCameraTurnedOnTimer, false);
+            active |= !resetIfNotNull(mForegroundActivityTimer, false);
+            active |= !resetIfNotNull(mForegroundServiceTimer, false);
+            active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false);
+            active |= !resetIfNotNull(mBluetoothScanTimer, false);
+            active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false);
+
+            resetIfNotNull(mBluetoothScanResultCounter, false);
+            resetIfNotNull(mBluetoothScanResultBgCounter, false);
 
             if (mProcessStateTimer != null) {
                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
-                    if (mProcessStateTimer[i] != null) {
-                        active |= !mProcessStateTimer[i].reset(false);
-                    }
+                    active |= !resetIfNotNull(mProcessStateTimer[i], false);
                 }
                 active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
             }
@@ -7895,75 +7967,37 @@
                 }
             }
 
-            if (mUserActivityCounters != null) {
-                for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
-                    mUserActivityCounters[i].reset(false);
-                }
-            }
+            resetIfNotNull(mUserActivityCounters, false);
 
-            if (mNetworkByteActivityCounters != null) {
-                for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
-                    mNetworkByteActivityCounters[i].reset(false);
-                    mNetworkPacketActivityCounters[i].reset(false);
-                }
-                mMobileRadioActiveTime.reset(false);
-                mMobileRadioActiveCount.reset(false);
-            }
+            resetIfNotNull(mNetworkByteActivityCounters, false);
+            resetIfNotNull(mNetworkPacketActivityCounters, false);
+            resetIfNotNull(mMobileRadioActiveTime, false);
+            resetIfNotNull(mMobileRadioActiveCount, false);
 
-            if (mWifiControllerActivity != null) {
-                mWifiControllerActivity.reset(false);
-            }
+            resetIfNotNull(mWifiControllerActivity, false);
+            resetIfNotNull(mBluetoothControllerActivity, false);
+            resetIfNotNull(mModemControllerActivity, false);
 
-            if (mBluetoothControllerActivity != null) {
-                mBluetoothControllerActivity.reset(false);
-            }
+            resetIfNotNull(mUserCpuTime, false);
+            resetIfNotNull(mSystemCpuTime, false);
 
-            if (mModemControllerActivity != null) {
-                mModemControllerActivity.reset(false);
-            }
+            resetIfNotNull(mCpuClusterSpeedTimesUs, false);
 
-            mUserCpuTime.reset(false);
-            mSystemCpuTime.reset(false);
+            resetIfNotNull(mCpuFreqTimeMs, false);
+            resetIfNotNull(mScreenOffCpuFreqTimeMs, false);
 
-            if (mCpuClusterSpeedTimesUs != null) {
-                for (LongSamplingCounter[] speeds : mCpuClusterSpeedTimesUs) {
-                    if (speeds != null) {
-                        for (LongSamplingCounter speed : speeds) {
-                            if (speed != null) {
-                                speed.reset(false);
-                            }
-                        }
-                    }
-                }
-            }
 
-            if (mCpuFreqTimeMs != null) {
-                mCpuFreqTimeMs.reset(false);
-            }
-            if (mScreenOffCpuFreqTimeMs != null) {
-                mScreenOffCpuFreqTimeMs.reset(false);
-            }
+            resetIfNotNull(mCpuActiveTimeMs, false);
+            resetIfNotNull(mCpuClusterTimesMs, false);
 
-            mCpuActiveTimeMs.reset(false);
-            mCpuClusterTimesMs.reset(false);
+            resetIfNotNull(mProcStateTimeMs, false);
 
-            if (mProcStateTimeMs != null) {
-                for (LongSamplingCounterArray counters : mProcStateTimeMs) {
-                    if (counters != null) {
-                        counters.reset(false);
-                    }
-                }
-            }
-            if (mProcStateScreenOffTimeMs != null) {
-                for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
-                    if (counters != null) {
-                        counters.reset(false);
-                    }
-                }
-            }
+            resetIfNotNull(mProcStateScreenOffTimeMs, false);
 
-            resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
-            resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);
+            resetIfNotNull(mMobileRadioApWakeupCount, false);
+
+            resetIfNotNull(mWifiRadioApWakeupCount, false);
+
 
             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
             for (int iw=wakeStats.size()-1; iw>=0; iw--) {
@@ -7999,16 +8033,12 @@
             mJobStats.cleanup();
             mJobCompletions.clear();
 
-            mJobsDeferredEventCount.reset(false);
-            mJobsDeferredCount.reset(false);
-            mJobsFreshnessTimeMs.reset(false);
-            for (int ij = 0; ij < JOB_FRESHNESS_BUCKETS.length; ij++) {
-                if (mJobsFreshnessBuckets[ij] != null) {
-                    mJobsFreshnessBuckets[ij].reset(false);
-                }
-            }
+            resetIfNotNull(mJobsDeferredEventCount, false);
+            resetIfNotNull(mJobsDeferredCount, false);
+            resetIfNotNull(mJobsFreshnessTimeMs, false);
+            resetIfNotNull(mJobsFreshnessBuckets, false);
 
-            for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
+            for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
                 Sensor s = mSensorStats.valueAt(ise);
                 if (s.reset()) {
                     mSensorStats.removeAt(ise);
@@ -8017,173 +8047,135 @@
                 }
             }
 
-            for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
+            for (int ip = mProcessStats.size() - 1; ip >= 0; ip--) {
                 Proc proc = mProcessStats.valueAt(ip);
                 proc.detach();
             }
             mProcessStats.clear();
-            if (mPids.size() > 0) {
-                for (int i=mPids.size()-1; i>=0; i--) {
-                    Pid pid = mPids.valueAt(i);
-                    if (pid.mWakeNesting > 0) {
-                        active = true;
-                    } else {
-                        mPids.removeAt(i);
-                    }
+
+            for (int i = mPids.size() - 1; i >= 0; i--) {
+                Pid pid = mPids.valueAt(i);
+                if (pid.mWakeNesting > 0) {
+                    active = true;
+                } else {
+                    mPids.removeAt(i);
                 }
             }
-            if (mPackageStats.size() > 0) {
-                Iterator<Map.Entry<String, Pkg>> it = mPackageStats.entrySet().iterator();
-                while (it.hasNext()) {
-                    Map.Entry<String, Pkg> pkgEntry = it.next();
-                    Pkg p = pkgEntry.getValue();
-                    p.detach();
-                    if (p.mServiceStats.size() > 0) {
-                        Iterator<Map.Entry<String, Pkg.Serv>> it2
-                                = p.mServiceStats.entrySet().iterator();
-                        while (it2.hasNext()) {
-                            Map.Entry<String, Pkg.Serv> servEntry = it2.next();
-                            servEntry.getValue().detach();
-                        }
-                    }
-                }
-                mPackageStats.clear();
+
+
+            for(int i = mPackageStats.size() - 1; i >= 0; i--) {
+                Pkg p = mPackageStats.valueAt(i);
+                p.detach();
             }
+            mPackageStats.clear();
 
             mLastStepUserTime = mLastStepSystemTime = 0;
             mCurStepUserTime = mCurStepSystemTime = 0;
 
-            if (!active) {
-                if (mWifiRunningTimer != null) {
-                    mWifiRunningTimer.detach();
-                }
-                if (mFullWifiLockTimer != null) {
-                    mFullWifiLockTimer.detach();
-                }
-                if (mWifiScanTimer != null) {
-                    mWifiScanTimer.detach();
-                }
-                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
-                    if (mWifiBatchedScanTimer[i] != null) {
-                        mWifiBatchedScanTimer[i].detach();
-                    }
-                }
-                if (mWifiMulticastTimer != null) {
-                    mWifiMulticastTimer.detach();
-                }
-                if (mAudioTurnedOnTimer != null) {
-                    mAudioTurnedOnTimer.detach();
-                    mAudioTurnedOnTimer = null;
-                }
-                if (mVideoTurnedOnTimer != null) {
-                    mVideoTurnedOnTimer.detach();
-                    mVideoTurnedOnTimer = null;
-                }
-                if (mFlashlightTurnedOnTimer != null) {
-                    mFlashlightTurnedOnTimer.detach();
-                    mFlashlightTurnedOnTimer = null;
-                }
-                if (mCameraTurnedOnTimer != null) {
-                    mCameraTurnedOnTimer.detach();
-                    mCameraTurnedOnTimer = null;
-                }
-                if (mForegroundActivityTimer != null) {
-                    mForegroundActivityTimer.detach();
-                    mForegroundActivityTimer = null;
-                }
-                if (mForegroundServiceTimer != null) {
-                    mForegroundServiceTimer.detach();
-                    mForegroundServiceTimer = null;
-                }
-                if (mAggregatedPartialWakelockTimer != null) {
-                    mAggregatedPartialWakelockTimer.detach();
-                    mAggregatedPartialWakelockTimer = null;
-                }
-                if (mBluetoothScanTimer != null) {
-                    mBluetoothScanTimer.detach();
-                    mBluetoothScanTimer = null;
-                }
-                if (mBluetoothUnoptimizedScanTimer != null) {
-                    mBluetoothUnoptimizedScanTimer.detach();
-                    mBluetoothUnoptimizedScanTimer = null;
-                }
-                if (mBluetoothScanResultCounter != null) {
-                    mBluetoothScanResultCounter.detach();
-                    mBluetoothScanResultCounter = null;
-                }
-                if (mBluetoothScanResultBgCounter != null) {
-                    mBluetoothScanResultBgCounter.detach();
-                    mBluetoothScanResultBgCounter = null;
-                }
-                if (mUserActivityCounters != null) {
-                    for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
-                        mUserActivityCounters[i].detach();
-                    }
-                }
-                if (mNetworkByteActivityCounters != null) {
-                    for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
-                        mNetworkByteActivityCounters[i].detach();
-                        mNetworkPacketActivityCounters[i].detach();
-                    }
-                }
+            return !active;
+        }
 
-                if (mWifiControllerActivity != null) {
-                    mWifiControllerActivity.detach();
-                }
+        /**
+         * This method MUST be called whenever the Uid object is destructed, otherwise it is a
+         * memory leak in {@link TimeBase#mObservers} list.
+         * Typically the Uid object is destructed when it is removed from
+         * {@link BatteryStatsImpl#mUidStats}
+         */
+        void detachFromTimeBase() {
+            detachIfNotNull(mWifiRunningTimer);
+            detachIfNotNull(mFullWifiLockTimer);
+            detachIfNotNull(mWifiScanTimer);
+            detachIfNotNull(mWifiBatchedScanTimer);
+            detachIfNotNull(mWifiMulticastTimer);
+            detachIfNotNull(mAudioTurnedOnTimer);
+            detachIfNotNull(mVideoTurnedOnTimer);
+            detachIfNotNull(mFlashlightTurnedOnTimer);
 
-                if (mBluetoothControllerActivity != null) {
-                    mBluetoothControllerActivity.detach();
-                }
+            detachIfNotNull(mCameraTurnedOnTimer);
+            detachIfNotNull(mForegroundActivityTimer);
+            detachIfNotNull(mForegroundServiceTimer);
 
-                if (mModemControllerActivity != null) {
-                    mModemControllerActivity.detach();
-                }
+            detachIfNotNull(mAggregatedPartialWakelockTimer);
 
-                mPids.clear();
+            detachIfNotNull(mBluetoothScanTimer);
+            detachIfNotNull(mBluetoothUnoptimizedScanTimer);
+            detachIfNotNull(mBluetoothScanResultCounter);
+            detachIfNotNull(mBluetoothScanResultBgCounter);
 
-                mUserCpuTime.detach();
-                mSystemCpuTime.detach();
+            detachIfNotNull(mProcessStateTimer);
 
-                if (mCpuClusterSpeedTimesUs != null) {
-                    for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeedTimesUs) {
-                        if (cpuSpeeds != null) {
-                            for (LongSamplingCounter c : cpuSpeeds) {
-                                if (c != null) {
-                                    c.detach();
-                                }
-                            }
-                        }
-                    }
-                }
+            detachIfNotNull(mVibratorOnTimer);
 
-                if (mCpuFreqTimeMs != null) {
-                    mCpuFreqTimeMs.detach();
-                }
-                if (mScreenOffCpuFreqTimeMs != null) {
-                    mScreenOffCpuFreqTimeMs.detach();
-                }
-                mCpuActiveTimeMs.detach();
-                mCpuClusterTimesMs.detach();
+            detachIfNotNull(mUserActivityCounters);
 
-                if (mProcStateTimeMs != null) {
-                    for (LongSamplingCounterArray counters : mProcStateTimeMs) {
-                        if (counters != null) {
-                            counters.detach();
-                        }
-                    }
-                }
-                if (mProcStateScreenOffTimeMs != null) {
-                    for (LongSamplingCounterArray counters : mProcStateScreenOffTimeMs) {
-                        if (counters != null) {
-                            counters.detach();
-                        }
-                    }
-                }
-                detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
-                detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
+            detachIfNotNull(mNetworkByteActivityCounters);
+            detachIfNotNull(mNetworkPacketActivityCounters);
+
+            detachIfNotNull(mMobileRadioActiveTime);
+            detachIfNotNull(mMobileRadioActiveCount);
+            detachIfNotNull(mMobileRadioApWakeupCount);
+            detachIfNotNull(mWifiRadioApWakeupCount);
+
+            detachIfNotNull(mWifiControllerActivity);
+            detachIfNotNull(mBluetoothControllerActivity);
+            detachIfNotNull(mModemControllerActivity);
+
+            mPids.clear();
+
+            detachIfNotNull(mUserCpuTime);
+            detachIfNotNull(mSystemCpuTime);
+
+            detachIfNotNull(mCpuClusterSpeedTimesUs);
+
+            detachIfNotNull(mCpuActiveTimeMs);
+            detachIfNotNull(mCpuFreqTimeMs);
+
+            detachIfNotNull(mScreenOffCpuFreqTimeMs);
+
+            detachIfNotNull(mCpuClusterTimesMs);
+
+            detachIfNotNull(mProcStateTimeMs);
+
+            detachIfNotNull(mProcStateScreenOffTimeMs);
+
+            final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
+            for (int iw = wakeStats.size() - 1; iw >= 0; iw--) {
+                Wakelock wl = wakeStats.valueAt(iw);
+                wl.detachFromTimeBase();
+            }
+            final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
+            for (int is = syncStats.size() - 1; is >= 0; is--) {
+                DualTimer timer = syncStats.valueAt(is);
+                detachIfNotNull(timer);
+            }
+            final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap();
+            for (int ij = jobStats.size() - 1; ij >= 0; ij--) {
+                DualTimer timer = jobStats.valueAt(ij);
+                detachIfNotNull(timer);
             }
 
-            return !active;
+            detachIfNotNull(mJobsDeferredEventCount);
+            detachIfNotNull(mJobsDeferredCount);
+            detachIfNotNull(mJobsFreshnessTimeMs);
+            detachIfNotNull(mJobsFreshnessBuckets);
+
+
+            for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) {
+                Sensor s = mSensorStats.valueAt(ise);
+                s.detachFromTimeBase();
+            }
+
+            for (int ip= mProcessStats.size() - 1; ip >= 0; ip--) {
+                Proc proc = mProcessStats.valueAt(ip);
+                proc.detach();
+            }
+            mProcessStats.clear();
+
+            for(int i = mPackageStats.size() - 1; i >= 0; i--) {
+                Pkg p = mPackageStats.valueAt(i);
+                p.detach();
+            }
+            mPackageStats.clear();
         }
 
         void writeJobCompletionsToParcelLocked(Parcel out) {
@@ -8602,7 +8594,7 @@
                     mWifiBatchedScanTimer[i] = null;
                 }
             }
-            mWifiMulticastEnabled = false;
+            mWifiMulticastWakelockCount = 0;
             if (in.readInt() != 0) {
                 mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
                         mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
@@ -8906,35 +8898,24 @@
 
             boolean reset() {
                 boolean wlactive = false;
-                if (mTimerFull != null) {
-                    wlactive |= !mTimerFull.reset(false);
-                }
-                if (mTimerPartial != null) {
-                    wlactive |= !mTimerPartial.reset(false);
-                }
-                if (mTimerWindow != null) {
-                    wlactive |= !mTimerWindow.reset(false);
-                }
-                if (mTimerDraw != null) {
-                    wlactive |= !mTimerDraw.reset(false);
-                }
+
+                wlactive |= !resetIfNotNull(mTimerFull,false);
+                wlactive |= !resetIfNotNull(mTimerPartial,false);
+                wlactive |= !resetIfNotNull(mTimerWindow,false);
+                wlactive |= !resetIfNotNull(mTimerDraw,false);
+
                 if (!wlactive) {
-                    if (mTimerFull != null) {
-                        mTimerFull.detach();
-                        mTimerFull = null;
-                    }
-                    if (mTimerPartial != null) {
-                        mTimerPartial.detach();
-                        mTimerPartial = null;
-                    }
-                    if (mTimerWindow != null) {
-                        mTimerWindow.detach();
-                        mTimerWindow = null;
-                    }
-                    if (mTimerDraw != null) {
-                        mTimerDraw.detach();
-                        mTimerDraw = null;
-                    }
+                    detachIfNotNull(mTimerFull);
+                    mTimerFull = null;
+
+                    detachIfNotNull(mTimerPartial);
+                    mTimerPartial = null;
+
+                    detachIfNotNull(mTimerWindow);
+                    mTimerWindow = null;
+
+                    detachIfNotNull(mTimerDraw);
+                    mTimerDraw = null;
                 }
                 return !wlactive;
             }
@@ -8959,6 +8940,7 @@
             }
 
             @Override
+            @UnsupportedAppUsage
             public Timer getWakeTime(int type) {
                 switch (type) {
                 case WAKE_TYPE_FULL: return mTimerFull;
@@ -8968,6 +8950,13 @@
                 default: throw new IllegalArgumentException("type = " + type);
                 }
             }
+
+            public void detachFromTimeBase() {
+                detachIfNotNull(mTimerPartial);
+                detachIfNotNull(mTimerFull);
+                detachIfNotNull(mTimerWindow);
+                detachIfNotNull(mTimerDraw);
+            }
         }
 
         public static class Sensor extends BatteryStats.Uid.Sensor {
@@ -9021,6 +9010,7 @@
             }
 
             @Override
+            @UnsupportedAppUsage
             public Timer getSensorTime() {
                 return mTimer;
             }
@@ -9034,9 +9024,14 @@
             }
 
             @Override
+            @UnsupportedAppUsage
             public int getHandle() {
                 return mHandle;
             }
+
+            public void  detachFromTimeBase() {
+                detachIfNotNull(mTimer);
+            }
         }
 
         /**
@@ -9168,7 +9163,16 @@
             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             }
 
-            void detach() {
+            @Override
+            public boolean reset(boolean detachIfReset) {
+                if (detachIfReset) {
+                    this.detach();
+                }
+                return true;
+            }
+
+            @Override
+            public void detach() {
                 mActive = false;
                 mBsi.mOnBatteryTimeBase.remove(this);
             }
@@ -9277,6 +9281,7 @@
                 readExcessivePowerFromParcelLocked(in);
             }
 
+            @UnsupportedAppUsage
             public void addCpuTimeLocked(int utime, int stime) {
                 addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning());
             }
@@ -9288,10 +9293,12 @@
                 }
             }
 
+            @UnsupportedAppUsage
             public void addForegroundTimeLocked(long ttime) {
                 mForegroundTime += ttime;
             }
 
+            @UnsupportedAppUsage
             public void incStartsLocked() {
                 mStarts++;
             }
@@ -9310,6 +9317,7 @@
             }
 
             @Override
+            @UnsupportedAppUsage
             public long getUserTime(int which) {
                 long val = mUserTime;
                 if (which == STATS_CURRENT) {
@@ -9321,6 +9329,7 @@
             }
 
             @Override
+            @UnsupportedAppUsage
             public long getSystemTime(int which) {
                 long val = mSystemTime;
                 if (which == STATS_CURRENT) {
@@ -9332,6 +9341,7 @@
             }
 
             @Override
+            @UnsupportedAppUsage
             public long getForegroundTime(int which) {
                 long val = mForegroundTime;
                 if (which == STATS_CURRENT) {
@@ -9343,6 +9353,7 @@
             }
 
             @Override
+            @UnsupportedAppUsage
             public int getStarts(int which) {
                 int val = mStarts;
                 if (which == STATS_CURRENT) {
@@ -9407,8 +9418,23 @@
             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             }
 
-            void detach() {
+            @Override
+            public boolean reset(boolean detachIfReset) {
+                if (detachIfReset) {
+                    this.detach();
+                }
+                return true;
+            }
+
+            @Override
+            public void detach() {
                 mBsi.mOnBatteryScreenOffTimeBase.remove(this);
+                for (int j = mWakeupAlarms.size() - 1; j >= 0; j--) {
+                    detachIfNotNull(mWakeupAlarms.valueAt(j));
+                }
+                for (int j = mServiceStats.size() - 1; j >= 0; j--) {
+                    detachIfNotNull(mServiceStats.valueAt(j));
+                }
             }
 
             void readFromParcelLocked(Parcel in) {
@@ -9589,9 +9615,18 @@
                         long baseRealtime) {
                 }
 
+                @Override
+                public boolean reset(boolean detachIfReset) {
+                    if (detachIfReset) {
+                        this.detach();
+                    }
+                    return true;
+                }
+
                 /**
                  * Remove this Serv as a listener from the time base.
                  */
+                @Override
                 public void detach() {
                     mBsi.mOnBatteryTimeBase.remove(this);
                 }
@@ -9643,6 +9678,7 @@
                     return mStartTime + batteryUptime - mRunningSince;
                 }
 
+                @UnsupportedAppUsage
                 public void startLaunchedLocked() {
                     if (!mLaunched) {
                         mLaunches++;
@@ -9651,6 +9687,7 @@
                     }
                 }
 
+                @UnsupportedAppUsage
                 public void stopLaunchedLocked() {
                     if (mLaunched) {
                         long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
@@ -9663,6 +9700,7 @@
                     }
                 }
 
+                @UnsupportedAppUsage
                 public void startRunningLocked() {
                     if (!mRunning) {
                         mStarts++;
@@ -9671,6 +9709,7 @@
                     }
                 }
 
+                @UnsupportedAppUsage
                 public void stopRunningLocked() {
                     if (mRunning) {
                         long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
@@ -9683,6 +9722,7 @@
                     }
                 }
 
+                @UnsupportedAppUsage
                 public BatteryStatsImpl getBatteryStats() {
                     return mBsi;
                 }
@@ -10081,11 +10121,13 @@
             UserInfoProvider userInfoProvider) {
         init(clocks);
 
-        if (systemDir != null) {
-            mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
-                    new File(systemDir, "batterystats.bin.tmp"));
+
+        if (systemDir == null) {
+            mStatsFile = null;
+            mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
         } else {
-            mFile = null;
+            mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
+            mBatteryStatsHistory = new BatteryStatsHistory(this, systemDir, mHistoryBuffer);
         }
         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
@@ -10180,19 +10222,21 @@
         mUserInfoProvider = userInfoProvider;
     }
 
+    @UnsupportedAppUsage
     public BatteryStatsImpl(Parcel p) {
         this(new SystemClocks(), p);
     }
 
     public BatteryStatsImpl(Clocks clocks, Parcel p) {
         init(clocks);
-        mFile = null;
+        mStatsFile = null;
         mCheckinFile = null;
         mDailyFile = null;
         mHandler = null;
         mExternalSync = null;
         mConstants = new Constants(mHandler);
         clearHistoryLocked();
+        mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer);
         readFromParcel(p);
         mPlatformIdleStateCallback = null;
     }
@@ -10309,8 +10353,6 @@
                                 stream = mDailyFile.startWrite();
                                 memStream.writeTo(stream);
                                 stream.flush();
-                                FileUtils.sync(stream);
-                                stream.close();
                                 mDailyFile.finishWrite(stream);
                                 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
                                         "batterystats-daily",
@@ -10614,21 +10656,17 @@
     }
 
     public int getHistoryTotalSize() {
-        return MAX_HISTORY_BUFFER;
+        return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES;
     }
 
     public int getHistoryUsedSize() {
-        return mHistoryBuffer.dataSize();
+        return mBatteryStatsHistory.getHistoryUsedSize();
     }
 
     @Override
+    @UnsupportedAppUsage
     public boolean startIteratingHistoryLocked() {
-        if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
-                + " pos=" + mHistoryBuffer.dataPosition());
-        if (mHistoryBuffer.dataSize() <= 0) {
-            return false;
-        }
-        mHistoryBuffer.setDataPosition(0);
+        mBatteryStatsHistory.startIteratingHistory();
         mReadOverflow = false;
         mIteratingHistory = true;
         mReadHistoryStrings = new String[mHistoryTagPool.size()];
@@ -10667,19 +10705,15 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public boolean getNextHistoryLocked(HistoryItem out) {
-        final int pos = mHistoryBuffer.dataPosition();
-        if (pos == 0) {
-            out.clear();
-        }
-        boolean end = pos >= mHistoryBuffer.dataSize();
-        if (end) {
+        Parcel p = mBatteryStatsHistory.getNextParcel(out);
+        if (p == null) {
             return false;
         }
-
         final long lastRealtime = out.time;
         final long lastWalltime = out.currentTime;
-        readHistoryDelta(mHistoryBuffer, out);
+        readHistoryDelta(p, out);
         if (out.cmd != HistoryItem.CMD_CURRENT_TIME
                 && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
             out.currentTime = lastWalltime + (out.time - lastRealtime);
@@ -10689,9 +10723,10 @@
 
     @Override
     public void finishIteratingHistoryLocked() {
+        mBatteryStatsHistory.finishIteratingHistory();
         mIteratingHistory = false;
-        mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
         mReadHistoryStrings = null;
+        mReadHistoryUids = null;
     }
 
     @Override
@@ -10704,6 +10739,7 @@
         return mStartCount;
     }
 
+    @UnsupportedAppUsage
     public boolean isOnBattery() {
         return mOnBattery;
     }
@@ -10859,6 +10895,7 @@
 
         for (int i=0; i<mUidStats.size(); i++) {
             if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
+                mUidStats.valueAt(i).detachFromTimeBase();
                 mUidStats.remove(mUidStats.keyAt(i));
                 i--;
             }
@@ -10916,6 +10953,8 @@
         initDischarge();
 
         clearHistoryLocked();
+        mBatteryStatsHistory.resetAllFiles();
+
         mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
     }
 
@@ -12163,11 +12202,13 @@
             }
             final Uid u = getUidStatsLocked(uid);
             if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
+                detachIfNotNull(u.mCpuFreqTimeMs);
                 u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
             }
             u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs, onBattery);
             if (u.mScreenOffCpuFreqTimeMs == null ||
                     u.mScreenOffCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) {
+                detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
                 u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
                         mOnBatteryScreenOffTimeBase);
             }
@@ -12176,6 +12217,7 @@
             if (perClusterTimesAvailable) {
                 if (u.mCpuClusterSpeedTimesUs == null ||
                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
+                    detachIfNotNull(u.mCpuClusterSpeedTimesUs);
                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
                 }
                 if (numWakelocks > 0 && mWakeLockAllocationsUs == null) {
@@ -12187,6 +12229,7 @@
                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
+                        detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
                         u.mCpuClusterSpeedTimesUs[cluster]
                                 = new LongSamplingCounter[speedsInCluster];
                     }
@@ -12224,6 +12267,7 @@
                 final Uid u = partialTimers.get(i).mUid;
                 if (u.mCpuClusterSpeedTimesUs == null ||
                         u.mCpuClusterSpeedTimesUs.length != numClusters) {
+                    detachIfNotNull(u.mCpuClusterSpeedTimesUs);
                     u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
                 }
 
@@ -12231,6 +12275,7 @@
                     final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(cluster);
                     if (u.mCpuClusterSpeedTimesUs[cluster] == null ||
                             u.mCpuClusterSpeedTimesUs[cluster].length != speedsInCluster) {
+                        detachIfNotNull(u.mCpuClusterSpeedTimesUs[cluster]);
                         u.mCpuClusterSpeedTimesUs[cluster]
                                 = new LongSamplingCounter[speedsInCluster];
                     }
@@ -12340,9 +12385,7 @@
             boolean reset = false;
             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
                     || level >= 90
-                    || (mDischargeCurrentLevel < 20 && level >= 80)
-                    || (getHighDischargeAmountSinceCharge() >= 200
-                            && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
+                    || (mDischargeCurrentLevel < 20 && level >= 80))) {
                 Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
                         + " dischargeLevel=" + mDischargeCurrentLevel
                         + " lowAmount=" + getLowDischargeAmountSinceCharge()
@@ -12364,8 +12407,6 @@
                                     stream = mCheckinFile.startWrite();
                                     stream.write(parcel.marshall());
                                     stream.flush();
-                                    FileUtils.sync(stream);
-                                    stream.close();
                                     mCheckinFile.finishWrite(stream);
                                     com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
                                             "batterystats-checkin",
@@ -12453,7 +12494,7 @@
             mModStepMode = 0;
         }
         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
-            if (mFile != null) {
+            if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
                 writeAsyncLocked();
             }
         }
@@ -12694,7 +12735,7 @@
         if (mMinLearnedBatteryCapacity == -1) {
             mMinLearnedBatteryCapacity = chargeFullUAh;
         } else {
-            Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
+            mMinLearnedBatteryCapacity = Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
         }
         mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
     }
@@ -12719,10 +12760,12 @@
         }
     }
 
+    @UnsupportedAppUsage
     public long getAwakeTimeBattery() {
         return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
     }
 
+    @UnsupportedAppUsage
     public long getAwakeTimePlugged() {
         return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
     }
@@ -12748,11 +12791,13 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public long computeBatteryUptime(long curTime, int which) {
         return mOnBatteryTimeBase.computeUptime(curTime, which);
     }
 
     @Override
+    @UnsupportedAppUsage
     public long computeBatteryRealtime(long curTime, int which) {
         return mOnBatteryTimeBase.computeRealtime(curTime, which);
     }
@@ -12806,6 +12851,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public long computeBatteryTimeRemaining(long curTime) {
         if (!mOnBattery) {
             return -1;
@@ -13004,11 +13050,13 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public long getBatteryRealtime(long curTime) {
         return mOnBatteryTimeBase.getRealtime(curTime);
     }
 
     @Override
+    @UnsupportedAppUsage
     public int getDischargeStartLevel() {
         synchronized(this) {
             return getDischargeStartLevelLocked();
@@ -13020,6 +13068,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public int getDischargeCurrentLevel() {
         synchronized(this) {
             return getDischargeCurrentLevelLocked();
@@ -13053,6 +13102,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public int getDischargeAmount(int which) {
         int dischargeAmount = which == STATS_SINCE_CHARGED
                 ? getHighDischargeAmountSinceCharge()
@@ -13064,6 +13114,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public int getDischargeAmountScreenOn() {
         synchronized(this) {
             int val = mDischargeAmountScreenOn;
@@ -13088,6 +13139,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public int getDischargeAmountScreenOff() {
         synchronized(this) {
             int val = mDischargeAmountScreenOff;
@@ -13140,6 +13192,7 @@
     /**
      * Retrieve the statistics object for a particular uid, creating if needed.
      */
+    @UnsupportedAppUsage
     public Uid getUidStatsLocked(int uid) {
         Uid u = mUidStats.get(uid);
         if (u == null) {
@@ -13172,13 +13225,24 @@
         mUidStats.put(lastUidForUser, null);
         final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
         final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
+        for (int i = firstIndex; i <= lastIndex; i++) {
+            final Uid uid = mUidStats.valueAt(i);
+            if (uid != null) {
+                uid.detachFromTimeBase();
+            }
+        }
         mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
     }
 
     /**
      * Remove the statistics object for a particular uid.
      */
+    @UnsupportedAppUsage
     public void removeUidStatsLocked(int uid) {
+        final Uid u = mUidStats.get(uid);
+        if (u != null) {
+            u.detachFromTimeBase();
+        }
         mUidStats.remove(uid);
         mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime()));
     }
@@ -13187,6 +13251,7 @@
      * Retrieve the statistics object for a particular process, creating
      * if needed.
      */
+    @UnsupportedAppUsage
     public Uid.Proc getProcessStatsLocked(int uid, String name) {
         uid = mapUid(uid);
         Uid u = getUidStatsLocked(uid);
@@ -13197,6 +13262,7 @@
      * Retrieve the statistics object for a particular process, creating
      * if needed.
      */
+    @UnsupportedAppUsage
     public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
         uid = mapUid(uid);
         Uid u = getUidStatsLocked(uid);
@@ -13207,6 +13273,7 @@
      * Retrieve the statistics object for a particular service, creating
      * if needed.
      */
+    @UnsupportedAppUsage
     public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
         uid = mapUid(uid);
         Uid u = getUidStatsLocked(uid);
@@ -13244,14 +13311,20 @@
                 = "external_stats_collection_rate_limit_ms";
         public static final String KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS
                 = "battery_level_collection_delay_ms";
+        public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
+        public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
 
-        private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = true;
+        private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = false;
         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
         private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 10_000;
         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
+        private static final int DEFAULT_MAX_HISTORY_FILES = 32;
+        private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
+        private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
+        private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
 
         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
@@ -13262,12 +13335,21 @@
                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
         public long BATTERY_LEVEL_COLLECTION_DELAY_MS
                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
+        public int MAX_HISTORY_FILES;
+        public int MAX_HISTORY_BUFFER; /*Bytes*/
 
         private ContentResolver mResolver;
         private final KeyValueListParser mParser = new KeyValueListParser(',');
 
         public Constants(Handler handler) {
             super(handler);
+            if (ActivityManager.isLowRamDeviceStatic()) {
+                MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE;
+                MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB * 1024;
+            } else {
+                MAX_HISTORY_FILES = DEFAULT_MAX_HISTORY_FILES;
+                MAX_HISTORY_BUFFER = DEFAULT_MAX_HISTORY_BUFFER_KB * 1024;
+            }
         }
 
         public void startObserving(ContentResolver resolver) {
@@ -13313,13 +13395,23 @@
                 BATTERY_LEVEL_COLLECTION_DELAY_MS = mParser.getLong(
                         KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS,
                         DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS);
+
+                MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
+                        ActivityManager.isLowRamDeviceStatic() ?
+                                DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
+                        : DEFAULT_MAX_HISTORY_FILES);
+                MAX_HISTORY_BUFFER = mParser.getInt(KEY_MAX_HISTORY_BUFFER_KB,
+                        ActivityManager.isLowRamDeviceStatic() ?
+                                DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
+                                : DEFAULT_MAX_HISTORY_BUFFER_KB)
+                        * 1024;
             }
         }
 
         private void updateTrackCpuTimesByProcStateLocked(boolean wasEnabled, boolean isEnabled) {
             TRACK_CPU_TIMES_BY_PROC_STATE = isEnabled;
             if (isEnabled && !wasEnabled) {
-                mKernelSingleUidTimeReader.markDataAsStale(true);
+                mIsPerProcessStateCpuDataStale = true;
                 mExternalSync.scheduleCpuSyncDueToSettingChange();
 
                 mNumSingleUidCpuTimeReads = 0;
@@ -13366,6 +13458,10 @@
             pw.println(EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS);
             pw.print(KEY_BATTERY_LEVEL_COLLECTION_DELAY_MS); pw.print("=");
             pw.println(BATTERY_LEVEL_COLLECTION_DELAY_MS);
+            pw.print(KEY_MAX_HISTORY_FILES); pw.print("=");
+            pw.println(MAX_HISTORY_FILES);
+            pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
+            pw.println(MAX_HISTORY_BUFFER/1024);
         }
     }
 
@@ -13417,20 +13513,22 @@
         }
     }
 
-    Parcel mPendingWrite = null;
     final ReentrantLock mWriteLock = new ReentrantLock();
 
     public void writeAsyncLocked() {
-        writeLocked(false);
+        writeStatsLocked(false);
+        writeHistoryLocked(false);
     }
 
     public void writeSyncLocked() {
-        writeLocked(true);
+        writeStatsLocked(true);
+        writeHistoryLocked(true);
     }
 
-    void writeLocked(boolean sync) {
-        if (mFile == null) {
-            Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
+    void writeStatsLocked(boolean sync) {
+        if (mStatsFile == null) {
+            Slog.w(TAG,
+                    "writeStatsLocked: no file associated with this instance");
             return;
         }
 
@@ -13438,90 +13536,140 @@
             return;
         }
 
-        Parcel out = Parcel.obtain();
-        writeSummaryToParcel(out, true);
-        mLastWriteTime = mClocks.elapsedRealtime();
-
-        if (mPendingWrite != null) {
-            mPendingWrite.recycle();
+        final Parcel p = Parcel.obtain();
+        final long start = SystemClock.uptimeMillis();
+        writeSummaryToParcel(p, false/*history is in separate file*/);
+        if (DEBUG) {
+            Slog.d(TAG, "writeSummaryToParcel duration ms:"
+                    + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
         }
-        mPendingWrite = out;
+        mLastWriteTime = mClocks.elapsedRealtime();
+        writeParcelToFileLocked(p, mStatsFile, sync);
+    }
 
+    void writeHistoryLocked(boolean sync) {
+        if (mBatteryStatsHistory.getActiveFile() == null) {
+            Slog.w(TAG,
+                    "writeHistoryLocked: no history file associated with this instance");
+            return;
+        }
+
+        if (mShuttingDown) {
+            return;
+        }
+
+        Parcel p = Parcel.obtain();
+        final long start = SystemClock.uptimeMillis();
+        writeHistoryBuffer(p, true, true);
+        if (DEBUG) {
+            Slog.d(TAG, "writeHistoryBuffer duration ms:"
+                    + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
+        }
+        writeParcelToFileLocked(p, mBatteryStatsHistory.getActiveFile(), sync);
+    }
+
+    void writeParcelToFileLocked(Parcel p, AtomicFile file, boolean sync) {
         if (sync) {
-            commitPendingDataToDisk();
+            commitPendingDataToDisk(p, file);
         } else {
             BackgroundThread.getHandler().post(new Runnable() {
                 @Override public void run() {
-                    commitPendingDataToDisk();
+                    commitPendingDataToDisk(p, file);
                 }
             });
         }
     }
 
-    public void commitPendingDataToDisk() {
-        final Parcel next;
-        synchronized (this) {
-            next = mPendingWrite;
-            mPendingWrite = null;
-            if (next == null) {
-                return;
-            }
-        }
-
+    private void commitPendingDataToDisk(Parcel p, AtomicFile file) {
         mWriteLock.lock();
+        FileOutputStream fos = null;
         try {
             final long startTime = SystemClock.uptimeMillis();
-            FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
-            stream.write(next.marshall());
-            stream.flush();
-            FileUtils.sync(stream);
-            stream.close();
-            mFile.commit();
+            fos = file.startWrite();
+            fos.write(p.marshall());
+            fos.flush();
+            file.finishWrite(fos);
+            if (DEBUG) {
+                Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath()
+                        + " duration ms:" + (SystemClock.uptimeMillis() - startTime)
+                        + " bytes:" + p.dataSize());
+            }
             com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
                     "batterystats", SystemClock.uptimeMillis() - startTime);
         } catch (IOException e) {
-            Slog.w("BatteryStats", "Error writing battery statistics", e);
-            mFile.rollback();
+            Slog.w(TAG, "Error writing battery statistics", e);
+            file.failWrite(fos);
         } finally {
-            next.recycle();
+            p.recycle();
             mWriteLock.unlock();
         }
     }
 
+    @UnsupportedAppUsage
     public void readLocked() {
         if (mDailyFile != null) {
             readDailyStatsLocked();
         }
 
-        if (mFile == null) {
-            Slog.w("BatteryStats", "readLocked: no file associated with this instance");
+        if (mStatsFile == null) {
+            Slog.w(TAG, "readLocked: no file associated with this instance");
+            return;
+        }
+
+        if (mBatteryStatsHistory.getActiveFile() == null) {
+            Slog.w(TAG,
+                    "readLocked: no history file associated with this instance");
             return;
         }
 
         mUidStats.clear();
 
+        Parcel stats = Parcel.obtain();
         try {
-            File file = mFile.chooseForRead();
-            if (!file.exists()) {
-                return;
+            final long start = SystemClock.uptimeMillis();
+            byte[] raw = mStatsFile.readFully();
+            stats.unmarshall(raw, 0, raw.length);
+            stats.setDataPosition(0);
+            readSummaryFromParcel(stats);
+            if (DEBUG) {
+                Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
+                        + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
+                        - start));
             }
-            FileInputStream stream = new FileInputStream(file);
-
-            byte[] raw = BatteryStatsHelper.readFully(stream);
-            Parcel in = Parcel.obtain();
-            in.unmarshall(raw, 0, raw.length);
-            in.setDataPosition(0);
-            stream.close();
-
-            readSummaryFromParcel(in);
-        } catch(Exception e) {
-            Slog.e("BatteryStats", "Error reading battery statistics", e);
+        } catch (Exception e) {
+            Slog.e(TAG, "Error reading battery statistics", e);
             resetAllStatsLocked();
+        } finally {
+            stats.recycle();
+        }
+
+        Parcel history = Parcel.obtain();
+        try {
+            final long start = SystemClock.uptimeMillis();
+            byte[] raw = mBatteryStatsHistory.getActiveFile().readFully();
+            if (raw.length > 0) {
+                history.unmarshall(raw, 0, raw.length);
+                history.setDataPosition(0);
+                readHistoryBuffer(history, true);
+            }
+            if (DEBUG) {
+                Slog.d(TAG, "readLocked history file::"
+                        + mBatteryStatsHistory.getActiveFile().getBaseFile().getPath()
+                        + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
+                        - start));
+            }
+        } catch (Exception e) {
+            Slog.e(TAG, "Error reading battery history", e);
+            clearHistoryLocked();
+            mBatteryStatsHistory.resetAllFiles();
+        } finally {
+            history.recycle();
         }
 
         mEndPlatformVersion = Build.ID;
 
-        if (mHistoryBuffer.dataPosition() > 0) {
+        if (mHistoryBuffer.dataPosition() > 0
+                || mBatteryStatsHistory.getFilesNumbers().size() > 1) {
             mRecordingHistory = true;
             final long elapsedRealtime = mClocks.elapsedRealtime();
             final long uptime = mClocks.uptimeMillis();
@@ -13539,37 +13687,22 @@
         return 0;
     }
 
-    void readHistory(Parcel in, boolean andOldHistory) throws ParcelFormatException {
+    void  readHistoryBuffer(Parcel in, boolean andOldHistory) throws ParcelFormatException {
+        final int version = in.readInt();
+        if (version != VERSION) {
+            Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
+                    + ", expected " + VERSION + "; erasing old stats");
+            return;
+        }
+
         final long historyBaseTime = in.readLong();
 
         mHistoryBuffer.setDataSize(0);
         mHistoryBuffer.setDataPosition(0);
-        mHistoryTagPool.clear();
-        mNextHistoryTagIdx = 0;
-        mNumHistoryTagChars = 0;
-
-        int numTags = in.readInt();
-        for (int i=0; i<numTags; i++) {
-            int idx = in.readInt();
-            String str = in.readString();
-            if (str == null) {
-                throw new ParcelFormatException("null history tag string");
-            }
-            int uid = in.readInt();
-            HistoryTag tag = new HistoryTag();
-            tag.string = str;
-            tag.uid = uid;
-            tag.poolIdx = idx;
-            mHistoryTagPool.put(tag, idx);
-            if (idx >= mNextHistoryTagIdx) {
-                mNextHistoryTagIdx = idx+1;
-            }
-            mNumHistoryTagChars += tag.string.length() + 1;
-        }
 
         int bufSize = in.readInt();
         int curPos = in.dataPosition();
-        if (bufSize >= (MAX_MAX_HISTORY_BUFFER*3)) {
+        if (bufSize >= (mConstants.MAX_HISTORY_BUFFER*100)) {
             throw new ParcelFormatException("File corrupt: history data buffer too large " +
                     bufSize);
         } else if ((bufSize&~3) != bufSize) {
@@ -13626,7 +13759,7 @@
         }
     }
 
-    void writeHistory(Parcel out, boolean inclData, boolean andOldHistory) {
+    void writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory) {
         if (DEBUG_HISTORY) {
             StringBuilder sb = new StringBuilder(128);
             sb.append("****************** WRITING mHistoryBaseTime: ");
@@ -13635,19 +13768,14 @@
             TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb);
             Slog.i(TAG, sb.toString());
         }
+        out.writeInt(VERSION);
         out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime);
         if (!inclData) {
             out.writeInt(0);
             out.writeInt(0);
             return;
         }
-        out.writeInt(mHistoryTagPool.size());
-        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
-            HistoryTag tag = ent.getKey();
-            out.writeInt(ent.getValue());
-            out.writeString(tag.string);
-            out.writeInt(tag.uid);
-        }
+
         out.writeInt(mHistoryBuffer.dataSize());
         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
@@ -13678,7 +13806,34 @@
             return;
         }
 
-        readHistory(in, true);
+        boolean inclHistory = in.readBoolean();
+        if (inclHistory) {
+            readHistoryBuffer(in, true);
+            mBatteryStatsHistory.readFromParcel(in);
+        }
+
+        mHistoryTagPool.clear();
+        mNextHistoryTagIdx = 0;
+        mNumHistoryTagChars = 0;
+
+        int numTags = in.readInt();
+        for (int i=0; i<numTags; i++) {
+            int idx = in.readInt();
+            String str = in.readString();
+            if (str == null) {
+                throw new ParcelFormatException("null history tag string");
+            }
+            int uid = in.readInt();
+            HistoryTag tag = new HistoryTag();
+            tag.string = str;
+            tag.uid = uid;
+            tag.poolIdx = idx;
+            mHistoryTagPool.put(tag, idx);
+            if (idx >= mNextHistoryTagIdx) {
+                mNextHistoryTagIdx = idx+1;
+            }
+            mNumHistoryTagChars += tag.string.length() + 1;
+        }
 
         mStartCount = in.readInt();
         mUptime = in.readLong();
@@ -13880,7 +14035,7 @@
                     u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
                 }
             }
-            u.mWifiMulticastEnabled = false;
+            u.mWifiMulticastWakelockCount = 0;
             if (in.readInt() != 0) {
                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
             }
@@ -13957,7 +14112,7 @@
                 if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
                     throw new ParcelFormatException("Incompatible cpu cluster arrangement");
                 }
-
+                detachIfNotNull(u.mCpuClusterSpeedTimesUs);
                 u.mCpuClusterSpeedTimesUs = new LongSamplingCounter[numClusters][];
                 for (int cluster = 0; cluster < numClusters; cluster++) {
                     if (in.readInt() != 0) {
@@ -13981,11 +14136,14 @@
                     }
                 }
             } else {
+                detachIfNotNull(u.mCpuClusterSpeedTimesUs);
                 u.mCpuClusterSpeedTimesUs = null;
             }
 
+            detachIfNotNull(u.mCpuFreqTimeMs);
             u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
                     in, mOnBatteryTimeBase);
+            detachIfNotNull(u.mScreenOffCpuFreqTimeMs);
             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
                     in, mOnBatteryScreenOffTimeBase);
 
@@ -13994,6 +14152,7 @@
 
             int length = in.readInt();
             if (length == Uid.NUM_PROCESS_STATE) {
+                detachIfNotNull(u.mProcStateTimeMs);
                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
                 for (int procState = 0; procState < length; ++procState) {
                     u.mProcStateTimeMs[procState]
@@ -14001,10 +14160,12 @@
                                     in, mOnBatteryTimeBase);
                 }
             } else {
+                detachIfNotNull(u.mProcStateTimeMs);
                 u.mProcStateTimeMs = null;
             }
             length = in.readInt();
             if (length == Uid.NUM_PROCESS_STATE) {
+                detachIfNotNull(u.mProcStateScreenOffTimeMs);
                 u.mProcStateScreenOffTimeMs = new LongSamplingCounterArray[length];
                 for (int procState = 0; procState < length; ++procState) {
                     u.mProcStateScreenOffTimeMs[procState]
@@ -14012,20 +14173,25 @@
                                     in, mOnBatteryScreenOffTimeBase);
                 }
             } else {
+                detachIfNotNull(u.mProcStateScreenOffTimeMs);
                 u.mProcStateScreenOffTimeMs = null;
             }
 
             if (in.readInt() != 0) {
+                detachIfNotNull(u.mMobileRadioApWakeupCount);
                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
                 u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
             } else {
+                detachIfNotNull(u.mMobileRadioApWakeupCount);
                 u.mMobileRadioApWakeupCount = null;
             }
 
             if (in.readInt() != 0) {
+                detachIfNotNull(u.mWifiRadioApWakeupCount);
                 u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
                 u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in);
             } else {
+                detachIfNotNull(u.mWifiRadioApWakeupCount);
                 u.mWifiRadioApWakeupCount = null;
             }
 
@@ -14061,6 +14227,7 @@
             u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
             u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
             u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
+            detachIfNotNull(u.mJobsFreshnessBuckets);
             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                 if (in.readInt() != 0) {
                     u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
@@ -14101,9 +14268,10 @@
             }
             for (int ip = 0; ip < NP; ip++) {
                 String pkgName = in.readString();
+                detachIfNotNull(u.mPackageStats.get(pkgName));
                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
                 final int NWA = in.readInt();
-                if (NWA > 1000) {
+                if (NWA > 10000) {
                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
                 }
                 p.mWakeupAlarms.clear();
@@ -14114,7 +14282,7 @@
                     p.mWakeupAlarms.put(tag, c);
                 }
                 NS = in.readInt();
-                if (NS > 1000) {
+                if (NS > 10000) {
                     throw new ParcelFormatException("File corrupt: too many services " + NS);
                 }
                 for (int is = 0; is < NS; is++) {
@@ -14146,7 +14314,19 @@
 
         out.writeInt(VERSION);
 
-        writeHistory(out, inclHistory, true);
+        out.writeBoolean(inclHistory);
+        if (inclHistory) {
+            writeHistoryBuffer(out, true, true);
+            mBatteryStatsHistory.writeToParcel(out);
+        }
+
+        out.writeInt(mHistoryTagPool.size());
+        for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
+            HistoryTag tag = ent.getKey();
+            out.writeInt(ent.getValue());
+            out.writeString(tag.string);
+            out.writeInt(tag.uid);
+        }
 
         out.writeInt(mStartCount);
         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
@@ -14644,7 +14824,8 @@
             throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
         }
 
-        readHistory(in, false);
+        readHistoryBuffer(in, false);
+        mBatteryStatsHistory.readFromParcel(in);
 
         mStartCount = in.readInt();
         mStartClockTime = in.readLong();
@@ -14873,7 +15054,8 @@
 
         out.writeInt(MAGIC);
 
-        writeHistory(out, true, false);
+        writeHistoryBuffer(out, true, false);
+        mBatteryStatsHistory.writeToParcel(out);
 
         out.writeInt(mStartCount);
         out.writeLong(startClockTime);
@@ -15047,6 +15229,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
         new Parcelable.Creator<BatteryStatsImpl>() {
         public BatteryStatsImpl createFromParcel(Parcel in) {
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index fbb99e4..4aa30f6 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -16,23 +16,39 @@
 
 package com.android.internal.os;
 
+import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
 import android.os.Binder;
+import android.os.OsProtoEnums;
+import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.format.DateFormat;
 import android.util.ArrayMap;
+import android.util.Pair;
+import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
+import com.android.internal.os.BinderInternal.CallSession;
+import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Queue;
+import java.util.Random;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.function.ToDoubleFunction;
 
@@ -40,127 +56,335 @@
  * Collects statistics about CPU time spent per binder call across multiple dimensions, e.g.
  * per thread, uid or call description.
  */
-public class BinderCallsStats {
+public class BinderCallsStats implements BinderInternal.Observer {
+    public static final boolean ENABLED_DEFAULT = false;
+    public static final boolean DETAILED_TRACKING_DEFAULT = true;
+    public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 100;
+
+    private static final String TAG = "BinderCallsStats";
     private static final int CALL_SESSIONS_POOL_SIZE = 100;
     private static final int PERIODIC_SAMPLING_INTERVAL = 10;
-    private static final BinderCallsStats sInstance = new BinderCallsStats();
+    private static final int MAX_EXCEPTION_COUNT_SIZE = 50;
+    private static final String EXCEPTION_COUNT_OVERFLOW_NAME = "overflow";
 
-    private volatile boolean mDetailedTracking = false;
+    // Whether to collect all the data: cpu + exceptions + reply/request sizes.
+    private boolean mDetailedTracking = DETAILED_TRACKING_DEFAULT;
+    // Sampling period to control how often to track CPU usage. 1 means all calls, 100 means ~1 out
+    // of 100 requests.
+    private int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT;
     @GuardedBy("mLock")
     private final SparseArray<UidEntry> mUidEntries = new SparseArray<>();
+    @GuardedBy("mLock")
+    private final ArrayMap<String, Integer> mExceptionCounts = new ArrayMap<>();
     private final Queue<CallSession> mCallSessionsPool = new ConcurrentLinkedQueue<>();
     private final Object mLock = new Object();
+    private final Random mRandom;
     private long mStartTime = System.currentTimeMillis();
-    @GuardedBy("mLock")
-    private UidEntry mSampledEntries = new UidEntry(-1);
 
-    private BinderCallsStats() {
-    }
-
-    @VisibleForTesting
-    public BinderCallsStats(boolean detailedTracking) {
-        mDetailedTracking = detailedTracking;
-    }
-
-    public CallSession callStarted(Binder binder, int code) {
-        return callStarted(binder.getClass().getName(), code);
-    }
-
-    private CallSession callStarted(String className, int code) {
-        CallSession s = mCallSessionsPool.poll();
-        if (s == null) {
-            s = new CallSession();
+    // State updated by the broadcast receiver below.
+    private boolean mScreenInteractive;
+    private boolean mCharging;
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case Intent.ACTION_BATTERY_CHANGED:
+                    mCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
+                    break;
+                case Intent.ACTION_SCREEN_ON:
+                    mScreenInteractive = true;
+                    break;
+                case Intent.ACTION_SCREEN_OFF:
+                    mScreenInteractive = false;
+                    break;
+            }
         }
-        s.callStat.className = className;
-        s.callStat.msg = code;
+    };
+
+    /** Injector for {@link BinderCallsStats}. */
+    public static class Injector {
+        public Random getRandomGenerator() {
+            return new Random();
+        }
+    }
+
+    public BinderCallsStats(Injector injector) {
+        this.mRandom = injector.getRandomGenerator();
+    }
+
+    public void systemReady(Context context) {
+        registerBroadcastReceiver(context);
+        setInitialState(queryScreenInteractive(context), queryIsCharging());
+    }
+
+    /**
+     * Listens for screen/battery state changes.
+     */
+    @VisibleForTesting
+    public void registerBroadcastReceiver(Context context) {
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        context.registerReceiver(mBroadcastReceiver, filter);
+    }
+
+    /**
+     * Sets the battery/screen initial state.
+     *
+     * This has to be updated *after* the broadcast receiver is installed.
+     */
+    @VisibleForTesting
+    public void setInitialState(boolean isScreenInteractive, boolean isCharging) {
+        this.mScreenInteractive = isScreenInteractive;
+        this.mCharging = isCharging;
+        // Data collected previously was not accurate since the battery/screen state was not set.
+        reset();
+    }
+
+    private boolean queryIsCharging() {
+        final BatteryManagerInternal batteryManager =
+                LocalServices.getService(BatteryManagerInternal.class);
+        if (batteryManager == null) {
+            Slog.wtf(TAG, "BatteryManager null while starting BinderCallsStatsService");
+            // Default to true to not collect any data.
+            return true;
+        } else {
+            return batteryManager.getPlugType() != OsProtoEnums.BATTERY_PLUGGED_NONE;
+        }
+    }
+
+    private boolean queryScreenInteractive(Context context) {
+        final PowerManager powerManager = context.getSystemService(PowerManager.class);
+        final boolean screenInteractive;
+        if (powerManager == null) {
+            Slog.wtf(TAG, "PowerManager null while starting BinderCallsStatsService",
+                    new Throwable());
+            return true;
+        } else {
+            return powerManager.isInteractive();
+        }
+    }
+
+    @Override
+    @Nullable
+    public CallSession callStarted(Binder binder, int code) {
+        if (mCharging) {
+            return null;
+        }
+
+        final CallSession s = obtainCallSession();
+        s.binderClass = binder.getClass();
+        s.transactionCode = code;
         s.exceptionThrown = false;
         s.cpuTimeStarted = -1;
         s.timeStarted = -1;
-
-        synchronized (mLock) {
-            if (mDetailedTracking) {
-                s.cpuTimeStarted = getThreadTimeMicro();
-                s.timeStarted = getElapsedRealtimeMicro();
-            } else {
-                s.sampledCallStat = mSampledEntries.getOrCreate(s.callStat);
-                if (s.sampledCallStat.callCount % PERIODIC_SAMPLING_INTERVAL == 0) {
-                    s.cpuTimeStarted = getThreadTimeMicro();
-                    s.timeStarted = getElapsedRealtimeMicro();
-                }
-            }
+        if (shouldRecordDetailedData()) {
+            s.cpuTimeStarted = getThreadTimeMicro();
+            s.timeStarted = getElapsedRealtimeMicro();
         }
         return s;
     }
 
-    public void callEnded(CallSession s, int parcelRequestSize, int parcelReplySize) {
-        Preconditions.checkNotNull(s);
-        synchronized (mLock) {
-            long duration;
-            long latencyDuration;
-            if (mDetailedTracking) {
-                duration = getThreadTimeMicro() - s.cpuTimeStarted;
-                latencyDuration = getElapsedRealtimeMicro() - s.timeStarted;
-            } else {
-                CallStat cs = s.sampledCallStat;
-                // Non-negative time signals beginning of the new sampling interval
-                if (s.cpuTimeStarted >= 0) {
-                    duration = getThreadTimeMicro() - s.cpuTimeStarted;
-                    latencyDuration = getElapsedRealtimeMicro() - s.timeStarted;
-                } else {
-                    // callCount is always incremented, but time only once per sampling interval
-                    long samplesCount = cs.callCount / PERIODIC_SAMPLING_INTERVAL + 1;
-                    duration = cs.cpuTimeMicros / samplesCount;
-                    latencyDuration = cs.latencyMicros / samplesCount;
-                }
-            }
+    private CallSession obtainCallSession() {
+        CallSession s = mCallSessionsPool.poll();
+        return s == null ? new CallSession() : s;
+    }
 
-            int callingUid = getCallingUid();
-
-            UidEntry uidEntry = mUidEntries.get(callingUid);
-            if (uidEntry == null) {
-                uidEntry = new UidEntry(callingUid);
-                mUidEntries.put(callingUid, uidEntry);
-            }
-
-            if (mDetailedTracking) {
-                // Find CallStat entry and update its total time
-                CallStat callStat = uidEntry.getOrCreate(s.callStat);
-                callStat.callCount++;
-                callStat.cpuTimeMicros += duration;
-                callStat.latencyMicros += latencyDuration;
-                callStat.exceptionCount += s.exceptionThrown ? 1 : 0;
-                callStat.maxLatencyMicros = Math.max(callStat.maxLatencyMicros, latencyDuration);
-                callStat.maxRequestSizeBytes =
-                        Math.max(callStat.maxRequestSizeBytes, parcelRequestSize);
-                callStat.maxReplySizeBytes =
-                        Math.max(callStat.maxReplySizeBytes, parcelReplySize);
-            } else {
-                // update sampled timings in the beginning of each interval
-                if (s.cpuTimeStarted >= 0) {
-                    s.sampledCallStat.cpuTimeMicros += duration;
-                    s.sampledCallStat.latencyMicros += latencyDuration;
-                }
-                s.sampledCallStat.callCount++;
-            }
-
-            uidEntry.cpuTimeMicros += duration;
-            uidEntry.callCount++;
+    @Override
+    public void callEnded(@Nullable CallSession s, int parcelRequestSize, int parcelReplySize) {
+        if (s == null) {
+            return;
         }
+
+        processCallEnded(s, parcelRequestSize, parcelReplySize);
+
         if (mCallSessionsPool.size() < CALL_SESSIONS_POOL_SIZE) {
             mCallSessionsPool.add(s);
         }
     }
 
-    /**
-     * Called if an exception is thrown while executing the binder transaction.
-     *
-     * <li>BinderCallsStats#callEnded will be called afterwards.
-     * <li>Do not throw an exception in this method, it will swallow the original exception thrown
-     * by the binder transaction.
-     */
-    public void callThrewException(CallSession s) {
-        Preconditions.checkNotNull(s);
+    private void processCallEnded(CallSession s, int parcelRequestSize, int parcelReplySize) {
+        // Non-negative time signals we need to record data for this call.
+        final boolean recordCall = s.cpuTimeStarted >= 0;
+        final long duration;
+        final long latencyDuration;
+        if (recordCall) {
+            duration = getThreadTimeMicro() - s.cpuTimeStarted;
+            latencyDuration = getElapsedRealtimeMicro() - s.timeStarted;
+        } else {
+            duration = 0;
+            latencyDuration = 0;
+        }
+        final int callingUid = getCallingUid();
+
+        synchronized (mLock) {
+            // This was already checked in #callStart but check again while synchronized.
+            if (mCharging) {
+                return;
+            }
+
+            final UidEntry uidEntry = getUidEntry(callingUid);
+            uidEntry.callCount++;
+
+            if (recordCall) {
+                uidEntry.cpuTimeMicros += duration;
+                uidEntry.recordedCallCount++;
+
+                final CallStat callStat = uidEntry.getOrCreate(
+                        s.binderClass, s.transactionCode, mScreenInteractive);
+                callStat.callCount++;
+                callStat.recordedCallCount++;
+                callStat.cpuTimeMicros += duration;
+                callStat.maxCpuTimeMicros = Math.max(callStat.maxCpuTimeMicros, duration);
+                callStat.latencyMicros += latencyDuration;
+                callStat.maxLatencyMicros =
+                        Math.max(callStat.maxLatencyMicros, latencyDuration);
+                if (mDetailedTracking) {
+                    callStat.exceptionCount += s.exceptionThrown ? 1 : 0;
+                    callStat.maxRequestSizeBytes =
+                            Math.max(callStat.maxRequestSizeBytes, parcelRequestSize);
+                    callStat.maxReplySizeBytes =
+                            Math.max(callStat.maxReplySizeBytes, parcelReplySize);
+                }
+            } else {
+                // Only record the total call count if we already track data for this key.
+                // It helps to keep the memory usage down when sampling is enabled.
+                final CallStat callStat = uidEntry.get(
+                        s.binderClass, s.transactionCode, mScreenInteractive);
+                if (callStat != null) {
+                    callStat.callCount++;
+                }
+            }
+        }
+    }
+
+    private UidEntry getUidEntry(int uid) {
+        UidEntry uidEntry = mUidEntries.get(uid);
+        if (uidEntry == null) {
+            uidEntry = new UidEntry(uid);
+            mUidEntries.put(uid, uidEntry);
+        }
+        return uidEntry;
+    }
+
+    @Override
+    public void callThrewException(@Nullable CallSession s, Exception exception) {
+        if (s == null) {
+            return;
+        }
         s.exceptionThrown = true;
+        try {
+            String className = exception.getClass().getName();
+            synchronized (mLock) {
+                if (mExceptionCounts.size() >= MAX_EXCEPTION_COUNT_SIZE) {
+                    className = EXCEPTION_COUNT_OVERFLOW_NAME;
+                }
+                final Integer count = mExceptionCounts.get(className);
+                mExceptionCounts.put(className, count == null ? 1 : count + 1);
+            }
+        } catch (RuntimeException e) {
+            // Do not propagate the exception. We do not want to swallow original exception.
+            Slog.wtf(TAG, "Unexpected exception while updating mExceptionCounts");
+        }
+    }
+
+    @Nullable
+    private Method getDefaultTransactionNameMethod(Class<? extends Binder> binder) {
+        try {
+            return binder.getMethod("getDefaultTransactionName", int.class);
+        } catch (NoSuchMethodException e) {
+            // The method might not be present for stubs not generated with AIDL.
+            return null;
+        }
+    }
+
+    @Nullable
+    private String resolveTransactionCode(Method getDefaultTransactionName, int transactionCode) {
+        if (getDefaultTransactionName == null) {
+            return null;
+        }
+
+        try {
+            return (String) getDefaultTransactionName.invoke(null, transactionCode);
+        } catch (IllegalAccessException | InvocationTargetException | ClassCastException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * This method is expensive to call.
+     */
+    public ArrayList<ExportedCallStat> getExportedCallStats() {
+        // We do not collect all the data if detailed tracking is off.
+        if (!mDetailedTracking) {
+            return new ArrayList<ExportedCallStat>();
+        }
+
+        ArrayList<ExportedCallStat> resultCallStats = new ArrayList<>();
+        synchronized (mLock) {
+            final int uidEntriesSize = mUidEntries.size();
+            for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++){
+                final UidEntry entry = mUidEntries.valueAt(entryIdx);
+                for (CallStat stat : entry.getCallStatsList()) {
+                    ExportedCallStat exported = new ExportedCallStat();
+                    exported.uid = entry.uid;
+                    exported.className = stat.binderClass.getName();
+                    exported.binderClass = stat.binderClass;
+                    exported.transactionCode = stat.transactionCode;
+                    exported.screenInteractive = stat.screenInteractive;
+                    exported.cpuTimeMicros = stat.cpuTimeMicros;
+                    exported.maxCpuTimeMicros = stat.maxCpuTimeMicros;
+                    exported.latencyMicros = stat.latencyMicros;
+                    exported.maxLatencyMicros = stat.maxLatencyMicros;
+                    exported.recordedCallCount = stat.recordedCallCount;
+                    exported.callCount = stat.callCount;
+                    exported.maxRequestSizeBytes = stat.maxRequestSizeBytes;
+                    exported.maxReplySizeBytes = stat.maxReplySizeBytes;
+                    exported.exceptionCount = stat.exceptionCount;
+                    resultCallStats.add(exported);
+                }
+            }
+        }
+
+        // Resolve codes outside of the lock since it can be slow.
+        ExportedCallStat previous = null;
+        // Cache the previous method/transaction code.
+        Method getDefaultTransactionName = null;
+        String previousMethodName = null;
+        resultCallStats.sort(BinderCallsStats::compareByBinderClassAndCode);
+        for (ExportedCallStat exported : resultCallStats) {
+            final boolean isClassDifferent = previous == null
+                    || !previous.className.equals(exported.className);
+            if (isClassDifferent) {
+                getDefaultTransactionName = getDefaultTransactionNameMethod(exported.binderClass);
+            }
+
+            final boolean isCodeDifferent = previous == null
+                    || previous.transactionCode != exported.transactionCode;
+            final String methodName;
+            if (isClassDifferent || isCodeDifferent) {
+                String resolvedCode = resolveTransactionCode(
+                        getDefaultTransactionName, exported.transactionCode);
+                methodName = resolvedCode == null
+                        ? String.valueOf(exported.transactionCode)
+                        : resolvedCode;
+            } else {
+                methodName = previousMethodName;
+            }
+            previousMethodName = methodName;
+            exported.methodName = methodName;
+        }
+
+        return resultCallStats;
+    }
+
+    /** @hide */
+    public ArrayMap<String, Integer> getExportedExceptionStats() {
+        synchronized (mLock) {
+            return new ArrayMap(mExceptionCounts);
+        }
     }
 
     public void dump(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
@@ -171,84 +395,91 @@
 
     private void dumpLocked(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
         long totalCallsCount = 0;
+        long totalRecordedCallsCount = 0;
         long totalCpuTime = 0;
         pw.print("Start time: ");
         pw.println(DateFormat.format("yyyy-MM-dd HH:mm:ss", mStartTime));
-        List<UidEntry> entries = new ArrayList<>();
+        pw.println("Sampling interval period: " + mPeriodicSamplingInterval);
+        final List<UidEntry> entries = new ArrayList<>();
 
-        int uidEntriesSize = mUidEntries.size();
+        final int uidEntriesSize = mUidEntries.size();
         for (int i = 0; i < uidEntriesSize; i++) {
             UidEntry e = mUidEntries.valueAt(i);
             entries.add(e);
             totalCpuTime += e.cpuTimeMicros;
+            totalRecordedCallsCount += e.recordedCallCount;
             totalCallsCount += e.callCount;
         }
 
         entries.sort(Comparator.<UidEntry>comparingDouble(value -> value.cpuTimeMicros).reversed());
-        String datasetSizeDesc = verbose ? "" : "(top 90% by cpu time) ";
-        StringBuilder sb = new StringBuilder();
-        if (mDetailedTracking) {
-            pw.println("Per-UID raw data " + datasetSizeDesc
-                    + "(uid, call_desc, cpu_time_micros, latency_time_micros, "
-                    + "max_latency_time_micros, exception_count, max_request_size_bytes, "
-                    + "max_reply_size_bytes, call_count):");
-            List<UidEntry> topEntries = verbose ? entries
-                    : getHighestValues(entries, value -> value.cpuTimeMicros, 0.9);
-            for (UidEntry uidEntry : topEntries) {
-                for (CallStat e : uidEntry.getCallStatsList()) {
-                    sb.setLength(0);
-                    sb.append("    ")
-                            .append(uidEntry.uid).append(",").append(e)
-                            .append(',').append(e.cpuTimeMicros)
-                            .append(',').append(e.latencyMicros)
-                            .append(',').append(e.maxLatencyMicros)
-                            .append(',').append(e.exceptionCount)
-                            .append(',').append(e.maxRequestSizeBytes)
-                            .append(',').append(e.maxReplySizeBytes)
-                            .append(',').append(e.callCount);
-                    pw.println(sb);
-                }
-            }
-            pw.println();
-        } else {
-            pw.println("Sampled stats " + datasetSizeDesc
-                    + "(call_desc, cpu_time, call_count, exception_count):");
-            List<CallStat> sampledStatsList = mSampledEntries.getCallStatsList();
-            // Show all if verbose, otherwise 90th percentile
-            if (!verbose) {
-                sampledStatsList = getHighestValues(sampledStatsList,
-                        value -> value.cpuTimeMicros, 0.9);
-            }
-            for (CallStat e : sampledStatsList) {
-                sb.setLength(0);
-                sb.append("    ").append(e)
-                        .append(',').append(e.cpuTimeMicros * PERIODIC_SAMPLING_INTERVAL)
-                        .append(',').append(e.callCount)
-                        .append(',').append(e.exceptionCount);
-                pw.println(sb);
-            }
-            pw.println();
+        final String datasetSizeDesc = verbose ? "" : "(top 90% by cpu time) ";
+        final StringBuilder sb = new StringBuilder();
+        final List<UidEntry> topEntries = verbose ? entries
+                : getHighestValues(entries, value -> value.cpuTimeMicros, 0.9);
+        pw.println("Per-UID raw data " + datasetSizeDesc
+                + "(package/uid, call_desc, screen_interactive, "
+                + "cpu_time_micros, max_cpu_time_micros, "
+                + "latency_time_micros, max_latency_time_micros, exception_count, "
+                + "max_request_size_bytes, max_reply_size_bytes, recorded_call_count, "
+                + "call_count):");
+        final List<ExportedCallStat> exportedCallStats = getExportedCallStats();
+        exportedCallStats.sort(BinderCallsStats::compareByCpuDesc);
+        for (ExportedCallStat e : exportedCallStats) {
+            sb.setLength(0);
+            sb.append("    ")
+                    .append(uidToString(e.uid, appIdToPkgNameMap))
+                    .append(',').append(e.className)
+                    .append('#').append(e.methodName)
+                    .append(',').append(e.screenInteractive)
+                    .append(',').append(e.cpuTimeMicros)
+                    .append(',').append(e.maxCpuTimeMicros)
+                    .append(',').append(e.latencyMicros)
+                    .append(',').append(e.maxLatencyMicros)
+                    .append(',').append(mDetailedTracking ? e.exceptionCount : '_')
+                    .append(',').append(mDetailedTracking ? e.maxRequestSizeBytes : '_')
+                    .append(',').append(mDetailedTracking ? e.maxReplySizeBytes : '_')
+                    .append(',').append(e.recordedCallCount)
+                    .append(',').append(e.callCount);
+            pw.println(sb);
         }
+        pw.println();
         pw.println("Per-UID Summary " + datasetSizeDesc
-                + "(cpu_time, % of total cpu_time, call_count, exception_count, package/uid):");
-        List<UidEntry> summaryEntries = verbose ? entries
+                + "(cpu_time, % of total cpu_time, recorded_call_count, call_count, package/uid):");
+        final List<UidEntry> summaryEntries = verbose ? entries
                 : getHighestValues(entries, value -> value.cpuTimeMicros, 0.9);
         for (UidEntry entry : summaryEntries) {
             String uidStr = uidToString(entry.uid, appIdToPkgNameMap);
-            pw.println(String.format("  %10d %3.0f%% %8d %3d %s",
-                    entry.cpuTimeMicros, 100d * entry.cpuTimeMicros / totalCpuTime, entry.callCount,
-                    entry.exceptionCount, uidStr));
+            pw.println(String.format("  %10d %3.0f%% %8d %8d %s",
+                        entry.cpuTimeMicros, 100d * entry.cpuTimeMicros / totalCpuTime,
+                        entry.recordedCallCount, entry.callCount, uidStr));
         }
         pw.println();
         pw.println(String.format("  Summary: total_cpu_time=%d, "
-                        + "calls_count=%d, avg_call_cpu_time=%.0f",
-                totalCpuTime, totalCallsCount, (double)totalCpuTime / totalCallsCount));
+                    + "calls_count=%d, avg_call_cpu_time=%.0f",
+                    totalCpuTime, totalCallsCount, (double)totalCpuTime / totalRecordedCallsCount));
+        pw.println();
+
+        pw.println("Exceptions thrown (exception_count, class_name):");
+        final List<Pair<String, Integer>> exceptionEntries = new ArrayList<>();
+        // We cannot use new ArrayList(Collection) constructor because MapCollections does not
+        // implement toArray method.
+        mExceptionCounts.entrySet().iterator().forEachRemaining(
+                (e) -> exceptionEntries.add(Pair.create(e.getKey(), e.getValue())));
+        exceptionEntries.sort((e1, e2) -> Integer.compare(e2.second, e1.second));
+        for (Pair<String, Integer> entry : exceptionEntries) {
+            pw.println(String.format("  %6d %s", entry.second, entry.first));
+        }
+
+        if (mPeriodicSamplingInterval != 1) {
+            pw.println("");
+            pw.println("/!\\ Displayed data is sampled. See sampling interval at the top.");
+        }
     }
 
     private static String uidToString(int uid, Map<Integer, String> pkgNameMap) {
-        int appId = UserHandle.getAppId(uid);
-        String pkgName = pkgNameMap == null ? null : pkgNameMap.get(appId);
-        String uidStr = UserHandle.formatUid(uid);
+        final int appId = UserHandle.getAppId(uid);
+        final String pkgName = pkgNameMap == null ? null : pkgNameMap.get(appId);
+        final String uidStr = UserHandle.formatUid(uid);
         return pkgName == null ? uidStr : pkgName + '/' + uidStr;
     }
 
@@ -260,48 +491,106 @@
         return Binder.getCallingUid();
     }
 
-    private long getElapsedRealtimeMicro() {
+    protected long getElapsedRealtimeMicro() {
         return SystemClock.elapsedRealtimeNanos() / 1000;
     }
 
-    public static BinderCallsStats getInstance() {
-        return sInstance;
+    private boolean shouldRecordDetailedData() {
+        return mRandom.nextInt() % mPeriodicSamplingInterval == 0;
     }
 
+    /**
+     * Sets to true to collect all the data.
+     */
     public void setDetailedTracking(boolean enabled) {
-        if (enabled != mDetailedTracking) {
-            reset();
-            mDetailedTracking = enabled;
+        synchronized (mLock) {
+            if (enabled != mDetailedTracking) {
+                mDetailedTracking = enabled;
+                reset();
+            }
+        }
+    }
+
+    public void setSamplingInterval(int samplingInterval) {
+        synchronized (mLock) {
+            if (samplingInterval != mPeriodicSamplingInterval) {
+                mPeriodicSamplingInterval = samplingInterval;
+                reset();
+            }
         }
     }
 
     public void reset() {
         synchronized (mLock) {
             mUidEntries.clear();
-            mSampledEntries.mCallStats.clear();
+            mExceptionCounts.clear();
             mStartTime = System.currentTimeMillis();
         }
     }
 
-    @VisibleForTesting
-    public static class CallStat {
+    /**
+     * Aggregated data by uid/class/method to be sent through WestWorld.
+     */
+    public static class ExportedCallStat {
+        public int uid;
         public String className;
-        public int msg;
+        public String methodName;
+        public boolean screenInteractive;
         public long cpuTimeMicros;
+        public long maxCpuTimeMicros;
         public long latencyMicros;
         public long maxLatencyMicros;
+        public long callCount;
+        public long recordedCallCount;
         public long maxRequestSizeBytes;
         public long maxReplySizeBytes;
-        public long callCount;
         public long exceptionCount;
 
-        CallStat() {
-        }
+        // Used internally.
+        Class<? extends Binder> binderClass;
+        int transactionCode;
+    }
 
-        CallStat(String className, int msg) {
-            this.className = className;
-            this.msg = msg;
+    @VisibleForTesting
+    public static class CallStat {
+        public Class<? extends Binder> binderClass;
+        public int transactionCode;
+        // True if the screen was interactive when the call ended.
+        public boolean screenInteractive;
+        // Number of calls for which we collected data for. We do not record data for all the calls
+        // when sampling is on.
+        public long recordedCallCount;
+        // Roughly the real number of total calls. We only track only track the API call count once
+        // at least one non-sampled count happened.
+        public long callCount;
+        // Total CPU of all for all the recorded calls.
+        // Approximate total CPU usage can be computed by
+        // cpuTimeMicros * callCount / recordedCallCount
+        public long cpuTimeMicros;
+        public long maxCpuTimeMicros;
+        // Total latency of all for all the recorded calls.
+        // Approximate average latency can be computed by
+        // latencyMicros * callCount / recordedCallCount
+        public long latencyMicros;
+        public long maxLatencyMicros;
+        // The following fields are only computed if mDetailedTracking is set.
+        public long maxRequestSizeBytes;
+        public long maxReplySizeBytes;
+        public long exceptionCount;
+
+        CallStat(Class<? extends Binder> binderClass, int transactionCode,
+                boolean screenInteractive) {
+            this.binderClass = binderClass;
+            this.transactionCode = transactionCode;
+            this.screenInteractive = screenInteractive;
         }
+    }
+
+    /** Key used to store CallStat object in a Map. */
+    public static class CallStatKey {
+        public Class<? extends Binder> binderClass;
+        public int transactionCode;
+        private boolean screenInteractive;
 
         @Override
         public boolean equals(Object o) {
@@ -309,52 +598,64 @@
                 return true;
             }
 
-            CallStat callStat = (CallStat) o;
-
-            return msg == callStat.msg && (className.equals(callStat.className));
+            final CallStatKey key = (CallStatKey) o;
+            return transactionCode == key.transactionCode
+                    && screenInteractive == key.screenInteractive
+                    && (binderClass.equals(key.binderClass));
         }
 
         @Override
         public int hashCode() {
-            int result = className.hashCode();
-            result = 31 * result + msg;
+            int result = binderClass.hashCode();
+            result = 31 * result + transactionCode;
+            result = 31 * result + (screenInteractive ? 1231 : 1237);
             return result;
         }
-
-        @Override
-        public String toString() {
-            return className + "/" + msg;
-        }
     }
 
-    public static class CallSession {
-        long cpuTimeStarted;
-        long timeStarted;
-        boolean exceptionThrown;
-        final CallStat callStat = new CallStat();
-        CallStat sampledCallStat;
-    }
 
     @VisibleForTesting
     public static class UidEntry {
         int uid;
-        public long cpuTimeMicros;
+        // Number of calls for which we collected data for. We do not record data for all the calls
+        // when sampling is on.
+        public long recordedCallCount;
+        // Real number of total calls.
         public long callCount;
-        public int exceptionCount;
+        // Total CPU of all for all the recorded calls.
+        // Approximate total CPU usage can be computed by
+        // cpuTimeMicros * callCount / recordedCallCount
+        public long cpuTimeMicros;
 
         UidEntry(int uid) {
             this.uid = uid;
         }
 
         // Aggregate time spent per each call name: call_desc -> cpu_time_micros
-        Map<CallStat, CallStat> mCallStats = new ArrayMap<>();
+        private Map<CallStatKey, CallStat> mCallStats = new ArrayMap<>();
+        private CallStatKey mTempKey = new CallStatKey();
 
-        CallStat getOrCreate(CallStat callStat) {
-            CallStat mapCallStat = mCallStats.get(callStat);
+        @Nullable
+        CallStat get(Class<? extends Binder> binderClass, int transactionCode,
+                boolean screenInteractive) {
+            // Use a global temporary key to avoid creating new objects for every lookup.
+            mTempKey.binderClass = binderClass;
+            mTempKey.transactionCode = transactionCode;
+            mTempKey.screenInteractive = screenInteractive;
+            return mCallStats.get(mTempKey);
+        }
+
+        CallStat getOrCreate(Class<? extends Binder> binderClass, int transactionCode,
+                boolean screenInteractive) {
+            CallStat mapCallStat = get(binderClass, transactionCode, screenInteractive);
             // Only create CallStat if it's a new entry, otherwise update existing instance
             if (mapCallStat == null) {
-                mapCallStat = new CallStat(callStat.className, callStat.msg);
-                mCallStats.put(mapCallStat, mapCallStat);
+                mapCallStat = new CallStat(binderClass, transactionCode, screenInteractive);
+                CallStatKey key = new CallStatKey();
+                key.binderClass = binderClass;
+                key.transactionCode = transactionCode;
+                key.screenInteractive = screenInteractive;
+                mCallStats.put(key, mapCallStat);
             }
             return mapCallStat;
         }
@@ -362,17 +663,8 @@
         /**
          * Returns list of calls sorted by CPU time
          */
-        public List<CallStat> getCallStatsList() {
-            List<CallStat> callStats = new ArrayList<>(mCallStats.keySet());
-            callStats.sort((o1, o2) -> {
-                if (o1.cpuTimeMicros < o2.cpuTimeMicros) {
-                    return 1;
-                } else if (o1.cpuTimeMicros > o2.cpuTimeMicros) {
-                    return -1;
-                }
-                return 0;
-            });
-            return callStats;
+        public Collection<CallStat> getCallStatsList() {
+            return mCallStats.values();
         }
 
         @Override
@@ -406,8 +698,8 @@
     }
 
     @VisibleForTesting
-    public UidEntry getSampledEntries() {
-        return mSampledEntries;
+    public ArrayMap<String, Integer> getExceptionCounts() {
+        return mExceptionCounts;
     }
 
     @VisibleForTesting
@@ -431,4 +723,21 @@
         return result;
     }
 
+    @VisibleForTesting
+    public BroadcastReceiver getBroadcastReceiver() {
+        return mBroadcastReceiver;
+    }
+
+    private static int compareByCpuDesc(
+            ExportedCallStat a, ExportedCallStat b) {
+        return Long.compare(b.cpuTimeMicros, a.cpuTimeMicros);
+    }
+
+    private static int compareByBinderClassAndCode(
+            ExportedCallStat a, ExportedCallStat b) {
+        int result = a.className.compareTo(b.className);
+        return result != 0
+                ? result
+                : Integer.compare(a.transactionCode, b.transactionCode);
+    }
 }
diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java
index 5bddd2f..0155067 100644
--- a/core/java/com/android/internal/os/BinderInternal.java
+++ b/core/java/com/android/internal/os/BinderInternal.java
@@ -17,6 +17,7 @@
 package com.android.internal.os;
 
 import android.annotation.NonNull;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.SystemClock;
@@ -33,7 +34,7 @@
 
 /**
  * Private and debugging Binder APIs.
- * 
+ *
  * @see IBinder
  */
 public class BinderInternal {
@@ -70,18 +71,62 @@
     }
 
     /**
+     * A session used by {@link Observer} in order to keep track of some data.
+     */
+    public static class CallSession {
+        // Binder interface descriptor.
+        public Class<? extends Binder> binderClass;
+        // Binder transaction code.
+        public int transactionCode;
+        // CPU time at the beginning of the call.
+        long cpuTimeStarted;
+        // System time at the beginning of the call.
+        long timeStarted;
+        // Should be set to one when an exception is thrown.
+        boolean exceptionThrown;
+    }
+
+    /**
+     * Allows to track various steps of an API call.
+     */
+    public interface Observer {
+        /**
+         * Called when a binder call starts.
+         *
+         * @return a CallSession to pass to the callEnded method.
+         */
+        CallSession callStarted(Binder binder, int code);
+
+        /**
+         * Called when a binder call stops.
+         *
+         * <li>This method will be called even when an exception is thrown.
+         */
+        void callEnded(CallSession s, int parcelRequestSize, int parcelReplySize);
+
+        /**
+         * Called if an exception is thrown while executing the binder transaction.
+         *
+         * <li>BinderCallsStats#callEnded will be called afterwards.
+         * <li>Do not throw an exception in this method, it will swallow the original exception
+         * thrown by the binder transaction.
+         */
+        public void callThrewException(CallSession s, Exception exception);
+    }
+
+    /**
      * Add the calling thread to the IPC thread pool.  This function does
      * not return until the current process is exiting.
      */
     public static final native void joinThreadPool();
-    
+
     /**
      * Return the system time (as reported by {@link SystemClock#uptimeMillis
      * SystemClock.uptimeMillis()}) that the last garbage collection occurred
      * in this process.  This is not for general application use, and the
      * meaning of "when a garbage collection occurred" will change as the
      * garbage collector evolves.
-     * 
+     *
      * @return Returns the time as per {@link SystemClock#uptimeMillis
      * SystemClock.uptimeMillis()} of the last garbage collection.
      */
@@ -95,7 +140,7 @@
      * other services.
      */
     public static final native IBinder getContextObject();
-    
+
     /**
      * Special for system process to not allow incoming calls to run at
      * background scheduling priority.
@@ -104,14 +149,14 @@
     public static final native void disableBackgroundScheduling(boolean disable);
 
     public static final native void setMaxThreads(int numThreads);
-    
+
     static native final void handleGc();
-    
+
     public static void forceGc(String reason) {
         EventLog.writeEvent(2741, reason);
         VMRuntime.getRuntime().requestConcurrentGC();
     }
-    
+
     static void forceBinderGc() {
         forceGc("Binder");
     }
diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java
index 67fbe5e..d08930b 100644
--- a/core/java/com/android/internal/os/FuseAppLoop.java
+++ b/core/java/com/android/internal/os/FuseAppLoop.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.ProxyFileDescriptorCallback;
 import android.os.Handler;
 import android.os.Message;
@@ -226,6 +227,7 @@
 
     // Called by JNI.
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void onCommand(int command, long unique, long inode, long offset, int size,
             byte[] data) {
         synchronized (mLock) {
@@ -254,6 +256,7 @@
 
     // Called by JNI.
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private byte[] onOpen(long unique, long inode) {
         synchronized (mLock) {
             try {
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index ae7c5f2..c8bfa1b 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -16,11 +16,18 @@
 
 package com.android.internal.os;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 
+/**
+ * @deprecated Use {@link com.android.internal.util.function.pooled.PooledLambda#obtainMessage}
+ *      to achieve the same effect of storing multiple values in a message with the added typesafety
+ *      and code continuity benefits.
+ */
+@Deprecated
 public class HandlerCaller {
     final Looper mMainLooper;
     final Handler mH;
@@ -82,6 +89,7 @@
         mH.removeMessages(what, obj);
     }
     
+    @UnsupportedAppUsage
     public void sendMessage(Message msg) {
         mH.sendMessage(msg);
     }
@@ -106,6 +114,7 @@
         return args;
     }
 
+    @UnsupportedAppUsage
     public Message obtainMessage(int what) {
         return mH.obtainMessage(what);
     }
@@ -121,6 +130,7 @@
         return mH.obtainMessage(what, arg1 ? 1 : 0, 0, args);
     }
     
+    @UnsupportedAppUsage
     public Message obtainMessageO(int what, Object arg1) {
         return mH.obtainMessage(what, 0, 0, arg1);
     }
@@ -133,6 +143,7 @@
         return mH.obtainMessage(what, arg1, arg2);
     }
     
+    @UnsupportedAppUsage
     public Message obtainMessageIO(int what, int arg1, Object arg2) {
         return mH.obtainMessage(what, arg1, 0, arg2);
     }
@@ -149,6 +160,7 @@
         return mH.obtainMessage(what, arg1, arg2, args);
     }
     
+    @UnsupportedAppUsage
     public Message obtainMessageIOO(int what, int arg1, Object arg2, Object arg3) {
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg2;
@@ -183,6 +195,7 @@
         return mH.obtainMessage(what, arg1, arg2, args);
     }
 
+    @UnsupportedAppUsage
     public Message obtainMessageOO(int what, Object arg1, Object arg2) {
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg1;
@@ -190,6 +203,7 @@
         return mH.obtainMessage(what, 0, 0, args);
     }
     
+    @UnsupportedAppUsage
     public Message obtainMessageOOO(int what, Object arg1, Object arg2, Object arg3) {
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg1;
diff --git a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
index 4283917..ad62852 100644
--- a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
@@ -53,8 +53,6 @@
     private int mReadErrorCounter;
     @GuardedBy("this")
     private boolean mSingleUidCpuTimesAvailable = true;
-    @GuardedBy("this")
-    private boolean mHasStaleData;
     // We use the freq count obtained from /proc/uid_time_in_state to decide how many longs
     // to read from each /proc/uid/<uid>/time_in_state. On the first read, verify if this is
     // correct and if not, set {@link #mSingleUidCpuTimesAvailable} to false. This flag will
@@ -196,18 +194,6 @@
         return deltaTimesMs;
     }
 
-    public void markDataAsStale(boolean hasStaleData) {
-        synchronized (this) {
-            mHasStaleData = hasStaleData;
-        }
-    }
-
-    public boolean hasStaleData() {
-        synchronized (this) {
-            return mHasStaleData;
-        }
-    }
-
     public void setAllUidsCpuTimesMs(SparseArray<long[]> allUidsCpuTimesMs) {
         synchronized (this) {
             mLastUidCpuTimeMs.clear();
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 246a50f..997b722 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -17,6 +17,7 @@
 package com.android.internal.os;
 
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -57,22 +58,27 @@
      *               + core_power.cluster1 * num running cores in cluster 1
      */
     public static final String POWER_CPU_SUSPEND = "cpu.suspend";
+    @UnsupportedAppUsage
     public static final String POWER_CPU_IDLE = "cpu.idle";
+    @UnsupportedAppUsage
     public static final String POWER_CPU_ACTIVE = "cpu.active";
 
     /**
      * Power consumption when WiFi driver is scanning for networks.
      */
+    @UnsupportedAppUsage
     public static final String POWER_WIFI_SCAN = "wifi.scan";
 
     /**
      * Power consumption when WiFi driver is on.
      */
+    @UnsupportedAppUsage
     public static final String POWER_WIFI_ON = "wifi.on";
 
     /**
      * Power consumption when WiFi driver is transmitting/receiving.
      */
+    @UnsupportedAppUsage
     public static final String POWER_WIFI_ACTIVE = "wifi.active";
 
     //
@@ -101,6 +107,7 @@
     /**
      * Power consumption when GPS is on.
      */
+    @UnsupportedAppUsage
     public static final String POWER_GPS_ON = "gps.on";
 
     /**
@@ -115,6 +122,7 @@
      * @deprecated
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final String POWER_BLUETOOTH_ON = "bluetooth.on";
 
     /**
@@ -131,6 +139,7 @@
      * @deprecated
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at";
 
     /**
@@ -141,27 +150,32 @@
     /**
      * Power consumption when screen is on, not including the backlight power.
      */
+    @UnsupportedAppUsage
     public static final String POWER_SCREEN_ON = "screen.on";
 
     /**
      * Power consumption when cell radio is on but not on a call.
      */
+    @UnsupportedAppUsage
     public static final String POWER_RADIO_ON = "radio.on";
 
     /**
      * Power consumption when cell radio is hunting for a signal.
      */
+    @UnsupportedAppUsage
     public static final String POWER_RADIO_SCANNING = "radio.scanning";
 
     /**
      * Power consumption when talking on the phone.
      */
+    @UnsupportedAppUsage
     public static final String POWER_RADIO_ACTIVE = "radio.active";
 
     /**
      * Power consumption at full backlight brightness. If the backlight is at
      * 50% brightness, then this should be multiplied by 0.5
      */
+    @UnsupportedAppUsage
     public static final String POWER_SCREEN_FULL = "screen.full";
 
     /**
@@ -224,6 +238,7 @@
     private static final Object sLock = new Object();
 
     @VisibleForTesting
+    @UnsupportedAppUsage
     public PowerProfile(Context context) {
         this(context, false);
     }
@@ -371,6 +386,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public int getNumCpuClusters() {
         return mCpuClusters.length;
     }
@@ -379,6 +395,7 @@
         return mCpuClusters[cluster].numCpus;
     }
 
+    @UnsupportedAppUsage
     public int getNumSpeedStepsInCpuCluster(int cluster) {
         if (cluster < 0 || cluster >= mCpuClusters.length) {
             return 0; // index out of bound
@@ -442,6 +459,7 @@
      * @param type the subsystem type
      * @return the average current in milliAmps.
      */
+    @UnsupportedAppUsage
     public double getAveragePower(String type) {
         return getAveragePowerOrDefault(type, 0);
     }
@@ -455,6 +473,7 @@
      *              If there is no data for multiple levels, the level is ignored.
      * @return the average current in milliAmps.
      */
+    @UnsupportedAppUsage
     public double getAveragePower(String type, int level) {
         if (sPowerItemMap.containsKey(type)) {
             return sPowerItemMap.get(type);
@@ -478,6 +497,7 @@
      *
      * @return the battery capacity in mAh
      */
+    @UnsupportedAppUsage
     public double getBatteryCapacity() {
         return getAveragePower(POWER_BATTERY_CAPACITY);
     }
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index a9cd5c8..e37e650 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -30,14 +30,13 @@
 import android.util.Slog;
 import com.android.internal.logging.AndroidConfig;
 import com.android.server.NetworkManagementSocketTagger;
+import dalvik.system.RuntimeHooks;
 import dalvik.system.VMRuntime;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Objects;
-import java.util.TimeZone;
 import java.util.logging.LogManager;
-import org.apache.harmony.luni.internal.util.TimezoneGetter;
 
 /**
  * Main entry point for runtime initialization.  Not for
@@ -195,19 +194,13 @@
          * the default handler, but not the pre handler.
          */
         LoggingHandler loggingHandler = new LoggingHandler();
-        Thread.setUncaughtExceptionPreHandler(loggingHandler);
+        RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
         Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
 
         /*
-         * Install a TimezoneGetter subclass for ZoneInfo.db
+         * Install a time zone supplier that uses the Android persistent time zone system property.
          */
-        TimezoneGetter.setInstance(new TimezoneGetter() {
-            @Override
-            public String getId() {
-                return SystemProperties.get("persist.sys.timezone");
-            }
-        });
-        TimeZone.setDefault(null);
+        RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone"));
 
         /*
          * Sets handler for java.util.logging to use Android log facilities.
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index d9aa325..b9d53c1 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.os;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Helper class for passing more arguments though a message
  * and avoiding allocation of a custom class for wrapping the
@@ -40,8 +42,11 @@
     static final int WAIT_FINISHED = 2;
     int mWaitState = WAIT_NONE;
 
+    @UnsupportedAppUsage
     public Object arg1;
+    @UnsupportedAppUsage
     public Object arg2;
+    @UnsupportedAppUsage
     public Object arg3;
     public Object arg4;
     public Object arg5;
@@ -50,7 +55,9 @@
     public Object arg8;
     public Object arg9;
     public int argi1;
+    @UnsupportedAppUsage
     public int argi2;
+    @UnsupportedAppUsage
     public int argi3;
     public int argi4;
     public int argi5;
@@ -60,6 +67,7 @@
         /* do nothing - reduce visibility */
     }
 
+    @UnsupportedAppUsage
     public static SomeArgs obtain() {
         synchronized (sPoolLock) {
             if (sPoolSize > 0) {
@@ -85,6 +93,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void recycle() {
         if (mInPool) {
             throw new IllegalStateException("Already recycled.");
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 4ee950a..927322e 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -81,6 +81,8 @@
     public static final int MOUNT_EXTERNAL_READ = IVold.REMOUNT_MODE_READ;
     /** Read-write external storage should be mounted. */
     public static final int MOUNT_EXTERNAL_WRITE = IVold.REMOUNT_MODE_WRITE;
+    /** Read-write external storage should be mounted instead of package sandbox */
+    public static final int MOUNT_EXTERNAL_FULL = IVold.REMOUNT_MODE_FULL;
 
     private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
 
@@ -132,13 +134,14 @@
      */
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) {
+          int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
+          String packageName) {
         VM_HOOKS.preFork();
         // Resets nice priority for zygote process.
         resetNicePriority();
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
-                  fdsToIgnore, startChildZygote, instructionSet, appDataDir);
+                  fdsToIgnore, startChildZygote, instructionSet, appDataDir, packageName);
         // Enable tracing as soon as possible for the child process.
         if (pid == 0) {
             Trace.setTracingEnabled(true, runtimeFlags);
@@ -152,7 +155,8 @@
 
     native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int runtimeFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir);
+          int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
+          String packageName);
 
     /**
      * Called to do any initialization before starting an application.
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 12761b9..b60b43a 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -239,7 +239,7 @@
         pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                 parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                 parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
-                parsedArgs.instructionSet, parsedArgs.appDataDir);
+                parsedArgs.instructionSet, parsedArgs.appDataDir, parsedArgs.packageName);
 
         try {
             if (pid == 0) {
@@ -426,6 +426,9 @@
         /** from --invoke-with */
         String invokeWith;
 
+        /** from --package-name */
+        String packageName;
+
         /**
          * Any args after and including the first non-option arg
          * (or after a '--')
@@ -641,7 +644,9 @@
                     mountExternal = Zygote.MOUNT_EXTERNAL_READ;
                 } else if (arg.equals("--mount-external-write")) {
                     mountExternal = Zygote.MOUNT_EXTERNAL_WRITE;
-                } else if (arg.equals("--query-abi-list")) {
+                } else if (arg.equals("--mount-external-full")) {
+                    mountExternal = Zygote.MOUNT_EXTERNAL_FULL;
+                }  else if (arg.equals("--query-abi-list")) {
                     abiListQuery = true;
                 } else if (arg.equals("--get-pid")) {
                     pidQuery = true;
@@ -674,6 +679,8 @@
                                 "Invalid log sampling rate: " + rateStr, nfe);
                     }
                     expectRuntimeArgs = false;
+                } else if (arg.startsWith("--package-name=")) {
+                    packageName = arg.substring(arg.indexOf('=') + 1);
                 } else {
                     break;
                 }
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index da19560..8f87f91 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -21,9 +21,6 @@
 
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.icu.impl.CacheValue;
-import android.icu.text.DecimalFormatSymbols;
-import android.icu.util.ULocale;
 import android.opengl.EGL14;
 import android.os.Build;
 import android.os.Environment;
@@ -122,9 +119,9 @@
 
     static void preload(TimingsTraceLog bootTimingsTraceLog) {
         Log.d(TAG, "begin preload");
-        bootTimingsTraceLog.traceBegin("BeginIcuCachePinning");
-        beginIcuCachePinning();
-        bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning
+        bootTimingsTraceLog.traceBegin("BeginPreload");
+        beginPreload();
+        bootTimingsTraceLog.traceEnd(); // BeginPreload
         bootTimingsTraceLog.traceBegin("PreloadClasses");
         preloadClasses();
         bootTimingsTraceLog.traceEnd(); // PreloadClasses
@@ -142,7 +139,7 @@
         // Ask the WebViewFactory to do any initialization that must run in the zygote process,
         // for memory sharing purposes.
         WebViewFactory.prepareWebViewInZygote();
-        endIcuCachePinning();
+        endPreload();
         warmUpJcaProviders();
         Log.d(TAG, "end preload");
 
@@ -156,27 +153,16 @@
         preload(new TimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK));
     }
 
-    private static void beginIcuCachePinning() {
-        // Pin ICU data in memory from this point that would normally be held by soft references.
-        // Without this, any references created immediately below or during class preloading
-        // would be collected when the Zygote GC runs in gcAndFinalize().
-        Log.i(TAG, "Installing ICU cache reference pinning...");
+    private static void beginPreload() {
+        Log.i(TAG, "Calling ZygoteHooks.beginPreload()");
 
-        CacheValue.setStrength(CacheValue.Strength.STRONG);
-
-        Log.i(TAG, "Preloading ICU data...");
-        // Explicitly exercise code to cache data apps are likely to need.
-        ULocale[] localesToPin = { ULocale.ROOT, ULocale.US, ULocale.getDefault() };
-        for (ULocale uLocale : localesToPin) {
-            new DecimalFormatSymbols(uLocale);
-        }
+        ZygoteHooks.onBeginPreload();
     }
 
-    private static void endIcuCachePinning() {
-        // All cache references created by ICU from this point will be soft.
-        CacheValue.setStrength(CacheValue.Strength.SOFT);
+    private static void endPreload() {
+        ZygoteHooks.onEndPreload();
 
-        Log.i(TAG, "Uninstalled ICU cache reference pinning...");
+        Log.i(TAG, "Called ZygoteHooks.endPreload()");
     }
 
     private static void preloadSharedLibraries() {
@@ -436,15 +422,8 @@
      * softly- and final-reachable objects, along with any other garbage.
      * This is only useful just before a fork().
      */
-    /*package*/ static void gcAndFinalize() {
-        final VMRuntime runtime = VMRuntime.getRuntime();
-
-        /* runFinalizationSync() lets finalizers be called in Zygote,
-         * which doesn't have a HeapWorker thread.
-         */
-        System.gc();
-        runtime.runFinalizationSync();
-        System.gc();
+    private static void gcAndFinalize() {
+        ZygoteHooks.gcAndFinalize();
     }
 
     /**
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index ac7dc8e2..8751517 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -19,15 +19,54 @@
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.WindowManager.LayoutParams.*;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
+import android.app.KeyguardManager;
 import android.app.SearchManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
+import android.media.session.MediaController;
 import android.media.session.MediaSessionManager;
-import android.os.UserHandle;
-
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
 import android.text.TextUtils;
+import android.transition.Scene;
+import android.transition.Transition;
+import android.transition.TransitionInflater;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.util.AndroidRuntimeException;
+import android.util.EventLog;
+import android.util.Log;
+import android.util.SparseArray;
+import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.IRotationWatcher.Stub;
@@ -52,6 +91,13 @@
 import android.view.ViewRootImpl.ActivityConfigCallback;
 import android.view.Window;
 import android.view.WindowManager;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
 import com.android.internal.R;
 import com.android.internal.view.menu.ContextMenuBuilder;
 import com.android.internal.view.menu.IconMenuPresenter;
@@ -64,43 +110,6 @@
 import com.android.internal.widget.DecorContentParent;
 import com.android.internal.widget.SwipeDismissLayout;
 
-import android.app.ActivityManager;
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.media.session.MediaController;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.Settings;
-import android.transition.Scene;
-import android.transition.Transition;
-import android.transition.TransitionInflater;
-import android.transition.TransitionManager;
-import android.transition.TransitionSet;
-import android.util.AndroidRuntimeException;
-import android.util.EventLog;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.TypedValue;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
@@ -1377,7 +1386,8 @@
      */
     private int getOptionsPanelGravity() {
         try {
-            return WindowManagerHolder.sWindowManager.getPreferredOptionsPanelGravity();
+            return WindowManagerHolder.sWindowManager.getPreferredOptionsPanelGravity(
+                    getContext().getDisplay().getDisplayId());
         } catch (RemoteException ex) {
             Log.e(TAG, "Couldn't getOptionsPanelGravity; using default", ex);
             return Gravity.CENTER | Gravity.BOTTOM;
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 2790324..616520f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -140,14 +140,14 @@
 
     void showShutdownUi(boolean isReboot, String reason);
 
-    // Used to show the dialog when FingerprintService starts authentication
-    void showFingerprintDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
-    // Used to hide the dialog when a finger is authenticated
-    void onFingerprintAuthenticated();
+    // Used to show the dialog when BiometricService starts authentication
+    void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
+    // Used to hide the dialog when a biometric is authenticated
+    void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
-    void onFingerprintHelp(String message);
+    void onBiometricHelp(String message);
     // Used to set a message - the dialog will dismiss after a certain amount of time
-    void onFingerprintError(String error);
-    // Used to hide the fingerprint dialog when the authenticationclient is stopped
-    void hideFingerprintDialog();
+    void onBiometricError(String error);
+    // Used to hide the biometric dialog when the AuthenticationClient is stopped
+    void hideBiometricDialog();
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 159d49b..b3af147 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -60,7 +60,7 @@
             int uid, int initialPid, String message, int userId);
     void onClearAllNotifications(int userId);
     void onNotificationClear(String pkg, String tag, int id, int userId, String key,
-            int dismissalSurface, in NotificationVisibility nv);
+            int dismissalSurface, int dismissalSentiment, in NotificationVisibility nv);
     void onNotificationVisibilityChanged( in NotificationVisibility[] newlyVisibleKeys,
             in NotificationVisibility[] noLongerVisibleKeys);
     void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded);
@@ -90,14 +90,14 @@
     void showPinningEnterExitToast(boolean entering);
     void showPinningEscapeToast();
 
-    // Used to show the dialog when FingerprintService starts authentication
-    void showFingerprintDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
-    // Used to hide the dialog when a finger is authenticated
-    void onFingerprintAuthenticated();
+    // Used to show the dialog when BiometricService starts authentication
+    void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
+    // Used to hide the dialog when a biometric is authenticated
+    void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
-    void onFingerprintHelp(String message);
+    void onBiometricHelp(String message);
     // Used to set a message - the dialog will dismiss after a certain amount of time
-    void onFingerprintError(String error);
-    // Used to hide the fingerprint dialog when the authenticationclient is stopped
-    void hideFingerprintDialog();
+    void onBiometricError(String error);
+    // Used to hide the biometric dialog when the AuthenticationClient is stopped
+    void hideBiometricDialog();
 }
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 621619c..4b66267 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -308,6 +308,23 @@
         return array;
     }
 
+    @SuppressWarnings("unchecked")
+    public static @NonNull <T> T[] concatElements(Class<T> kind, @Nullable T[] a, @Nullable T[] b) {
+        final int an = (a != null) ? a.length : 0;
+        final int bn = (b != null) ? b.length : 0;
+        if (an == 0 && bn == 0) {
+            if (kind == String.class) {
+                return (T[]) EmptyArray.STRING;
+            } else if (kind == Object.class) {
+                return (T[]) EmptyArray.OBJECT;
+            }
+        }
+        final T[] res = (T[]) Array.newInstance(kind, an + bn);
+        if (an > 0) System.arraycopy(a, 0, res, 0, an);
+        if (bn > 0) System.arraycopy(b, 0, res, an, bn);
+        return res;
+    }
+
     /**
      * Adds value to given array if not already present, providing set-like
      * behavior.
@@ -626,4 +643,17 @@
     public static @NonNull String[] defeatNullable(@Nullable String[] val) {
         return (val != null) ? val : EmptyArray.STRING;
     }
+
+    /**
+     * Throws {@link ArrayIndexOutOfBoundsException} if the index is out of bounds.
+     *
+     * @param len length of the array. Must be non-negative
+     * @param index the index to check
+     * @throws ArrayIndexOutOfBoundsException if the {@code index} is out of bounds of the array
+     */
+    public static void checkBounds(int len, int index) {
+        if (index < 0 || len <= index) {
+            throw new ArrayIndexOutOfBoundsException("length=" + len + "; index=" + index);
+        }
+    }
 }
diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java
index e760f25..69297b5 100644
--- a/core/java/com/android/internal/util/AsyncChannel.java
+++ b/core/java/com/android/internal/util/AsyncChannel.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.util;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -105,6 +106,7 @@
      * msg.obj  == the AsyncChannel
      * msg.replyTo == dstMessenger if successful
      */
+    @UnsupportedAppUsage
     public static final int CMD_CHANNEL_HALF_CONNECTED = BASE + 0;
 
     /**
@@ -114,6 +116,7 @@
      *
      * msg.replyTo = srcMessenger.
      */
+    @UnsupportedAppUsage
     public static final int CMD_CHANNEL_FULL_CONNECTION = BASE + 1;
 
     /**
@@ -159,6 +162,7 @@
         sCmdToString[CMD_CHANNEL_DISCONNECT - BASE] = "CMD_CHANNEL_DISCONNECT";
         sCmdToString[CMD_CHANNEL_DISCONNECTED - BASE] = "CMD_CHANNEL_DISCONNECTED";
     }
+    @UnsupportedAppUsage
     protected static String cmdToString(int cmd) {
         cmd -= BASE;
         if ((cmd >= 0) && (cmd < sCmdToString.length)) {
@@ -169,6 +173,7 @@
     }
 
     /** Successful status always 0, !0 is an unsuccessful status */
+    @UnsupportedAppUsage
     public static final int STATUS_SUCCESSFUL = 0;
 
     /** Error attempting to bind on a connect */
@@ -204,6 +209,7 @@
     /**
      * AsyncChannel constructor
      */
+    @UnsupportedAppUsage
     public AsyncChannel() {
     }
 
@@ -255,6 +261,7 @@
      *
      * @return STATUS_SUCCESSFUL on success any other value is an error.
      */
+    @UnsupportedAppUsage
     public int connectSync(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
         if (DBG) log("halfConnectSync srcHandler to the dstMessenger  E");
 
@@ -370,6 +377,7 @@
      * @param srcHandler
      * @param dstMessenger
      */
+    @UnsupportedAppUsage
     public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
         if (DBG) log("connect srcHandler to the dstMessenger  E");
 
@@ -392,6 +400,7 @@
      * @param srcHandler
      * @param dstMessenger
      */
+    @UnsupportedAppUsage
     public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
         if (DBG) log("connected srcHandler to the dstMessenger  E");
 
@@ -446,6 +455,7 @@
     /**
      * Disconnect
      */
+    @UnsupportedAppUsage
     public void disconnect() {
         if ((mConnection != null) && (mSrcContext != null)) {
             mSrcContext.unbindService(mConnection);
@@ -475,6 +485,7 @@
      *
      * @param msg
      */
+    @UnsupportedAppUsage
     public void sendMessage(Message msg) {
         msg.replyTo = mSrcMessenger;
         try {
@@ -489,6 +500,7 @@
      *
      * @param what
      */
+    @UnsupportedAppUsage
     public void sendMessage(int what) {
         Message msg = Message.obtain();
         msg.what = what;
@@ -501,6 +513,7 @@
      * @param what
      * @param arg1
      */
+    @UnsupportedAppUsage
     public void sendMessage(int what, int arg1) {
         Message msg = Message.obtain();
         msg.what = what;
@@ -515,6 +528,7 @@
      * @param arg1
      * @param arg2
      */
+    @UnsupportedAppUsage
     public void sendMessage(int what, int arg1, int arg2) {
         Message msg = Message.obtain();
         msg.what = what;
@@ -531,6 +545,7 @@
      * @param arg2
      * @param obj
      */
+    @UnsupportedAppUsage
     public void sendMessage(int what, int arg1, int arg2, Object obj) {
         Message msg = Message.obtain();
         msg.what = what;
@@ -559,6 +574,7 @@
      * @param srcMsg
      * @param dstMsg
      */
+    @UnsupportedAppUsage
     public void replyToMessage(Message srcMsg, Message dstMsg) {
         try {
             dstMsg.replyTo = mSrcMessenger;
@@ -575,6 +591,7 @@
      * @param srcMsg
      * @param what
      */
+    @UnsupportedAppUsage
     public void replyToMessage(Message srcMsg, int what) {
         Message msg = Message.obtain();
         msg.what = what;
@@ -588,6 +605,7 @@
      * @param what
      * @param arg1
      */
+    @UnsupportedAppUsage
     public void replyToMessage(Message srcMsg, int what, int arg1) {
         Message msg = Message.obtain();
         msg.what = what;
@@ -620,6 +638,7 @@
      * @param arg2
      * @param obj
      */
+    @UnsupportedAppUsage
     public void replyToMessage(Message srcMsg, int what, int arg1, int arg2, Object obj) {
         Message msg = Message.obtain();
         msg.what = what;
@@ -636,6 +655,7 @@
      * @param what
      * @param obj
      */
+    @UnsupportedAppUsage
     public void replyToMessage(Message srcMsg, int what, Object obj) {
         Message msg = Message.obtain();
         msg.what = what;
@@ -649,6 +669,7 @@
      * @param msg to send
      * @return reply message or null if an error.
      */
+    @UnsupportedAppUsage
     public Message sendMessageSynchronously(Message msg) {
         Message resultMsg = SyncMessenger.sendMessageSynchronously(mDstMessenger, msg);
         return resultMsg;
@@ -690,6 +711,7 @@
      * @param arg2
      * @return reply message or null if an error.
      */
+    @UnsupportedAppUsage
     public Message sendMessageSynchronously(int what, int arg1, int arg2) {
         Message msg = Message.obtain();
         msg.what = what;
diff --git a/core/java/com/android/internal/util/ContrastColorUtil.java b/core/java/com/android/internal/util/ContrastColorUtil.java
index 60dd86b..16ca4fc 100644
--- a/core/java/com/android/internal/util/ContrastColorUtil.java
+++ b/core/java/com/android/internal/util/ContrastColorUtil.java
@@ -454,9 +454,12 @@
     /**
      * Resolves {@param color} to an actual color if it is {@link Notification#COLOR_DEFAULT}
      */
-    public static int resolveColor(Context context, int color) {
+    public static int resolveColor(Context context, int color, boolean defaultBackgroundIsDark) {
         if (color == Notification.COLOR_DEFAULT) {
-            return context.getColor(com.android.internal.R.color.notification_default_color_light);
+            int res = defaultBackgroundIsDark
+                    ? com.android.internal.R.color.notification_default_color_dark
+                    : com.android.internal.R.color.notification_default_color_light;
+            return context.getColor(res);
         }
         return color;
     }
@@ -486,7 +489,7 @@
      */
     public static int resolveContrastColor(Context context, int notificationColor,
             int backgroundColor, boolean isDark) {
-        final int resolvedColor = resolveColor(context, notificationColor);
+        final int resolvedColor = resolveColor(context, notificationColor, isDark);
 
         int color = resolvedColor;
         color = ContrastColorUtil.ensureTextContrast(color, backgroundColor, isDark);
@@ -520,7 +523,8 @@
     }
 
     public static int resolveAmbientColor(Context context, int notificationColor) {
-        final int resolvedColor = resolveColor(context, notificationColor);
+        final int resolvedColor = resolveColor(context, notificationColor,
+                true /* defaultBackgroundIsDark */);
 
         int color = resolvedColor;
         color = ContrastColorUtil.ensureTextContrastOnBlack(color);
@@ -538,8 +542,9 @@
         return color;
     }
 
-    public static int resolvePrimaryColor(Context context, int backgroundColor) {
-        boolean useDark = shouldUseDark(backgroundColor);
+    public static int resolvePrimaryColor(Context context, int backgroundColor,
+                                          boolean defaultBackgroundIsDark) {
+        boolean useDark = shouldUseDark(backgroundColor, defaultBackgroundIsDark);
         if (useDark) {
             return context.getColor(
                     com.android.internal.R.color.notification_primary_text_color_light);
@@ -549,8 +554,9 @@
         }
     }
 
-    public static int resolveSecondaryColor(Context context, int backgroundColor) {
-        boolean useDark = shouldUseDark(backgroundColor);
+    public static int resolveSecondaryColor(Context context, int backgroundColor,
+                                            boolean defaultBackgroundIsDark) {
+        boolean useDark = shouldUseDark(backgroundColor, defaultBackgroundIsDark);
         if (useDark) {
             return context.getColor(
                     com.android.internal.R.color.notification_secondary_text_color_light);
@@ -560,8 +566,9 @@
         }
     }
 
-    public static int resolveDefaultColor(Context context, int backgroundColor) {
-        boolean useDark = shouldUseDark(backgroundColor);
+    public static int resolveDefaultColor(Context context, int backgroundColor,
+                                          boolean defaultBackgroundIsDark) {
+        boolean useDark = shouldUseDark(backgroundColor, defaultBackgroundIsDark);
         if (useDark) {
             return context.getColor(
                     com.android.internal.R.color.notification_default_color_light);
@@ -591,12 +598,11 @@
         return ColorUtilsFromCompat.LABToColor(result[0], result[1], result[2]);
     }
 
-    private static boolean shouldUseDark(int backgroundColor) {
-        boolean useDark = backgroundColor == Notification.COLOR_DEFAULT;
-        if (!useDark) {
-            useDark = ColorUtilsFromCompat.calculateLuminance(backgroundColor) > 0.5;
+    private static boolean shouldUseDark(int backgroundColor, boolean defaultBackgroundIsDark) {
+        if (backgroundColor == Notification.COLOR_DEFAULT) {
+            return !defaultBackgroundIsDark;
         }
-        return useDark;
+        return ColorUtilsFromCompat.calculateLuminance(backgroundColor) > 0.5;
     }
 
     public static double calculateLuminance(int backgroundColor) {
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 7fd83bc..f6d80a5 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -34,9 +34,18 @@
 /**
  * Helper functions for dumping the state of system services.
  * Test:
- atest /android/pi-dev/frameworks/base/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
+ atest FrameworksCoreTests:DumpUtilsTest
  */
 public final class DumpUtils {
+
+    /**
+     * List of component names that should be dumped in the bug report critical section.
+     *
+     * @hide
+     */
+    public static final ComponentName[] CRITICAL_SECTION_COMPONENTS = {
+            new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")
+    };
     private static final String TAG = "DumpUtils";
     private static final boolean DEBUG = false;
 
@@ -213,6 +222,45 @@
     }
 
     /**
+     * Return whether a package should be dumped in the critical section.
+     */
+    private static boolean isCriticalPackage(@Nullable ComponentName cname) {
+        if (cname == null) {
+            return false;
+        }
+
+        for (int i = 0; i < CRITICAL_SECTION_COMPONENTS.length; i++) {
+            if (cname.equals(CRITICAL_SECTION_COMPONENTS[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return whether a package name is considered to be part of the platform and in the critical
+     * section.
+     *
+     * @hide
+     */
+    public static boolean isPlatformCriticalPackage(@Nullable ComponentName.WithComponentName wcn) {
+        return (wcn != null) && isPlatformPackage(wcn.getComponentName()) &&
+                isCriticalPackage(wcn.getComponentName());
+    }
+
+    /**
+     * Return whether a package name is considered to be part of the platform but not in the the
+     * critical section.
+     *
+     * @hide
+     */
+    public static boolean isPlatformNonCriticalPackage(
+            @Nullable ComponentName.WithComponentName wcn) {
+        return (wcn != null) && isPlatformPackage(wcn.getComponentName()) &&
+                !isCriticalPackage(wcn.getComponentName());
+    }
+
+    /**
      * Used for dumping providers and services. Return a predicate for a given filter string.
      * @hide
      */
@@ -238,6 +286,16 @@
             return DumpUtils::isNonPlatformPackage;
         }
 
+        // Dump all platform-critical?
+        if ("all-platform-critical".equals(filterString)) {
+            return DumpUtils::isPlatformCriticalPackage;
+        }
+
+        // Dump all platform-non-critical?
+        if ("all-platform-non-critical".equals(filterString)) {
+            return DumpUtils::isPlatformNonCriticalPackage;
+        }
+
         // Is the filter a component name? If so, do an exact match.
         final ComponentName filterCname = ComponentName.unflattenFromString(filterString);
         if (filterCname != null) {
diff --git a/core/java/com/android/internal/util/FastPrintWriter.java b/core/java/com/android/internal/util/FastPrintWriter.java
index cc2c4cf..981fbaa 100644
--- a/core/java/com/android/internal/util/FastPrintWriter.java
+++ b/core/java/com/android/internal/util/FastPrintWriter.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.util;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.Log;
 import android.util.Printer;
 
@@ -77,6 +78,7 @@
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
      */
+    @UnsupportedAppUsage
     public FastPrintWriter(OutputStream out) {
         this(out, false, 8192);
     }
diff --git a/core/java/com/android/internal/util/IndentingPrintWriter.java b/core/java/com/android/internal/util/IndentingPrintWriter.java
index e453866..03a555e 100644
--- a/core/java/com/android/internal/util/IndentingPrintWriter.java
+++ b/core/java/com/android/internal/util/IndentingPrintWriter.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.util;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.PrintWriter;
 import java.io.Writer;
 import java.util.Arrays;
@@ -47,6 +48,7 @@
 
     private char[] mSingleChar = new char[1];
 
+    @UnsupportedAppUsage
     public IndentingPrintWriter(Writer writer, String singleIndent) {
         this(writer, singleIndent, -1);
     }
@@ -72,12 +74,14 @@
         return this;
     }
 
+    @UnsupportedAppUsage
     public IndentingPrintWriter increaseIndent() {
         mIndentBuilder.append(mSingleIndent);
         mCurrentIndent = null;
         return this;
     }
 
+    @UnsupportedAppUsage
     public IndentingPrintWriter decreaseIndent() {
         mIndentBuilder.delete(0, mSingleIndent.length());
         mCurrentIndent = null;
diff --git a/core/java/com/android/internal/util/JournaledFile.java b/core/java/com/android/internal/util/JournaledFile.java
index 5372fc0..258db2a 100644
--- a/core/java/com/android/internal/util/JournaledFile.java
+++ b/core/java/com/android/internal/util/JournaledFile.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 import java.io.File;
 import java.io.IOException;
 
@@ -33,6 +35,7 @@
     File mTemp;
     boolean mWriting;
 
+    @UnsupportedAppUsage
     public JournaledFile(File real, File temp) {
         mReal = real;
         mTemp = temp;
@@ -44,6 +47,7 @@
      * it to the real one.  If there is both a real file and a temp one, assumes that the
      * temp one isn't fully written and deletes it.
      */
+    @UnsupportedAppUsage
     public File chooseForRead() {
         File result;
         if (mReal.exists()) {
@@ -68,6 +72,7 @@
      * <p>
      * Call {@link #commit} to commit the changes, or {@link #rollback} to forget the changes.
      */
+    @UnsupportedAppUsage
     public File chooseForWrite() {
         if (mWriting) {
             throw new IllegalStateException("uncommitted write already in progress");
@@ -95,6 +100,7 @@
     /**
      * Commit changes.
      */
+    @UnsupportedAppUsage
     public void commit() {
         if (!mWriting) {
             throw new IllegalStateException("no file to commit");
@@ -106,6 +112,7 @@
     /**
      * Roll back changes.
      */
+    @UnsupportedAppUsage
     public void rollback() {
         if (!mWriting) {
             throw new IllegalStateException("no file to roll back");
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 3188d30..5da587b 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.util;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Bitmap.CompressFormat;
@@ -48,6 +49,7 @@
 
     private static final String STRING_ARRAY_SEPARATOR = ":";
 
+    @UnsupportedAppUsage
     public static void skipCurrentTag(XmlPullParser parser)
             throws XmlPullParserException, IOException {
         int outerDepth = parser.getDepth();
@@ -71,6 +73,7 @@
         return defaultValue;
     }
 
+    @UnsupportedAppUsage
     public static final boolean
     convertValueToBoolean(CharSequence value, boolean defaultValue)
     {
@@ -87,6 +90,7 @@
         return result;
     }
 
+    @UnsupportedAppUsage
     public static final int
     convertValueToInt(CharSequence charSeq, int defaultValue)
     {
@@ -183,6 +187,7 @@
      * @see #writeValueXml
      * @see #readMapXml
      */
+    @UnsupportedAppUsage
     public static final void writeMapXml(Map val, OutputStream out)
             throws XmlPullParserException, java.io.IOException {
         XmlSerializer serializer = new FastXmlSerializer();
@@ -732,6 +737,7 @@
      * #see #writeMapXml
      */
     @SuppressWarnings("unchecked")
+    @UnsupportedAppUsage
     public static final HashMap<String, ?> readMapXml(InputStream in)
     throws XmlPullParserException, java.io.IOException
     {
@@ -1550,6 +1556,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
     {
         int type;
@@ -1568,6 +1575,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
     {
         int type;
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 7178a0d..e3490f1 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.view;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 import android.hardware.input.InputManager;
 import android.os.Bundle;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 28291ae..189c8d5 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -67,10 +68,12 @@
 
     @GuardedBy("mLock")
     @Nullable
+    @UnsupportedAppUsage
     private InputConnection mInputConnection;
 
     private Looper mMainLooper;
     private Handler mH;
+    @UnsupportedAppUsage
     private Object mLock = new Object();
     @GuardedBy("mLock")
     private boolean mFinished = false;
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index f76eddf..06726bd 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -30,8 +30,6 @@
 /**
  * Public interface to the global input method manager, used by all client
  * applications.
- * You need to update BridgeIInputMethodManager.java as well when changing
- * this file.
  */
 interface IInputMethodManager {
     // TODO: Use ParceledListSlice instead
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index f05bd32..9d4383f 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -19,6 +19,7 @@
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.ServiceConnection;
@@ -151,6 +152,7 @@
     /**
      * The input method service.
      */
+    @UnsupportedAppUsage
     public final IInputMethodSession method;
 
     /**
@@ -230,6 +232,7 @@
     /**
      * Used to make this class parcelable.
      */
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<InputBindResult> CREATOR =
             new Parcelable.Creator<InputBindResult>() {
         @Override
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index e9472fa..13425e5 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -77,7 +77,11 @@
             final Point size = new Point();
             final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
             try {
-                wm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, size);
+                final Display display = context.getDisplay();
+                final int displayId = display != null
+                        ? display.getDisplayId()
+                        : Display.DEFAULT_DISPLAY;
+                wm.getInitialDisplaySize(displayId, size);
                 return size.x < size.y ?
                         Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
             } catch (RemoteException e) {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 92e1d80..eb94db3 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.view.menu;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -224,6 +225,7 @@
         updateTextButtonVisibility();
     }
 
+    @UnsupportedAppUsage
     public boolean hasText() {
         return !TextUtils.isEmpty(getText());
     }
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 48485e0..0e07ca7 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -18,6 +18,7 @@
 
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -64,6 +65,7 @@
         0, /* SELECTED_ALTERNATIVE */
     };
 
+    @UnsupportedAppUsage
     private final Context mContext;
     private final Resources mResources;
 
@@ -173,6 +175,7 @@
          * @param item The menu item that is selected
          * @return whether the menu item selection was handled
          */
+        @UnsupportedAppUsage
         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
         
         /**
@@ -180,6 +183,7 @@
          * 
          * @param menu the menu that has changed modes
          */
+        @UnsupportedAppUsage
         public void onMenuModeChange(MenuBuilder menu);
     }
 
@@ -190,6 +194,7 @@
         public boolean invokeItem(MenuItemImpl item);
     }
 
+    @UnsupportedAppUsage
     public MenuBuilder(Context context) {
         mContext = context;
         mResources = context.getResources();
@@ -205,6 +210,7 @@
         setShortcutsVisibleInner(true);
     }
     
+    @UnsupportedAppUsage
     public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
         mDefaultShowAsAction = defaultShowAsAction;
         return this;
@@ -217,6 +223,7 @@
      *
      * @param presenter The presenter to add
      */
+    @UnsupportedAppUsage
     public void addMenuPresenter(MenuPresenter presenter) {
         addMenuPresenter(presenter, mContext);
     }
@@ -230,6 +237,7 @@
      * @param presenter The presenter to add
      * @param menuContext The context used to inflate menu items
      */
+    @UnsupportedAppUsage
     public void addMenuPresenter(MenuPresenter presenter, Context menuContext) {
         mPresenters.add(new WeakReference<MenuPresenter>(presenter));
         presenter.initForMenu(menuContext, this);
@@ -242,6 +250,7 @@
      *
      * @param presenter The presenter to remove
      */
+    @UnsupportedAppUsage
     public void removeMenuPresenter(MenuPresenter presenter) {
         for (WeakReference<MenuPresenter> ref : mPresenters) {
             final MenuPresenter item = ref.get();
@@ -401,6 +410,7 @@
         return ACTION_VIEW_STATES_KEY;
     }
 
+    @UnsupportedAppUsage
     public void setCallback(Callback cb) {
         mCallback = cb;
     }
@@ -768,6 +778,7 @@
         return mResources;
     }
     
+    @UnsupportedAppUsage
     public Context getContext() {
         return mContext;
     }
@@ -1004,6 +1015,7 @@
      * {@link #startDispatchingItemsChanged()} is called. Useful when
      * many menu operations are going to be performed as a batch.
      */
+    @UnsupportedAppUsage
     public void stopDispatchingItemsChanged() {
         if (!mPreventDispatchingItemsChanged) {
             mPreventDispatchingItemsChanged = true;
@@ -1011,6 +1023,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void startDispatchingItemsChanged() {
         mPreventDispatchingItemsChanged = false;
 
@@ -1041,6 +1054,7 @@
     }
 
     @NonNull
+    @UnsupportedAppUsage
     public ArrayList<MenuItemImpl> getVisibleItems() {
         if (!mIsVisibleItemsStale) return mVisibleItems;
 
@@ -1131,6 +1145,7 @@
         return mActionItems;
     }
     
+    @UnsupportedAppUsage
     public ArrayList<MenuItemImpl> getNonActionItems() {
         flagActionItems();
         return mNonActionItems;
@@ -1235,10 +1250,12 @@
         return this;
     }
     
+    @UnsupportedAppUsage
     public CharSequence getHeaderTitle() {
         return mHeaderTitle;
     }
     
+    @UnsupportedAppUsage
     public Drawable getHeaderIcon() {
         return mHeaderIcon;
     }
@@ -1251,6 +1268,7 @@
      * Gets the root menu (if this is a submenu, find its root menu).
      * @return The root menu.
      */
+    @UnsupportedAppUsage
     public MenuBuilder getRootMenu() {
         return this;
     }
@@ -1262,10 +1280,12 @@
      * 
      * @param menuInfo The extra menu information to add.
      */
+    @UnsupportedAppUsage
     public void setCurrentMenuInfo(ContextMenuInfo menuInfo) {
         mCurrentMenuInfo = menuInfo;
     }
 
+    @UnsupportedAppUsage
     void setOptionalIconsVisible(boolean visible) {
         mOptionalIconsVisible = visible;
     }
@@ -1296,6 +1316,7 @@
         return expanded;
     }
 
+    @UnsupportedAppUsage
     public boolean collapseItemActionView(MenuItemImpl item) {
         if (mPresenters.isEmpty() || mExpandedItem != item) return false;
 
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 0c5ea63..994a9c1 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -19,6 +19,7 @@
 import com.android.internal.view.menu.MenuView.ItemView;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
@@ -67,6 +68,7 @@
      * needed (if the Drawable isn't already obtained--only one of the two is
      * needed).
      */
+    @UnsupportedAppUsage
     private int mIconResId = NO_ICON;
 
     private ColorStateList mIconTintList = null;
@@ -139,6 +141,7 @@
      *
      * @return true if the invocation was handled, false otherwise
      */
+    @UnsupportedAppUsage
     public boolean invoke() {
         if (mClickListener != null &&
             mClickListener.onMenuItemClick(this)) {
@@ -565,6 +568,7 @@
         return this;
     }
 
+    @UnsupportedAppUsage
     public void setExclusiveCheckable(boolean exclusive) {
         mFlags = (mFlags & ~EXCLUSIVE) | (exclusive ? EXCLUSIVE : 0);
     }
@@ -638,6 +642,7 @@
         return mTitle != null ? mTitle.toString() : null;
     }
 
+    @UnsupportedAppUsage
     void setMenuInfo(ContextMenuInfo menuInfo) {
         mMenuInfo = menuInfo;
     }
@@ -657,14 +662,17 @@
         return mMenu.getOptionalIconsVisible();
     }
 
+    @UnsupportedAppUsage
     public boolean isActionButton() {
         return (mFlags & IS_ACTION) == IS_ACTION;
     }
 
+    @UnsupportedAppUsage
     public boolean requestsActionButton() {
         return (mShowAsAction & SHOW_AS_ACTION_IF_ROOM) == SHOW_AS_ACTION_IF_ROOM;
     }
 
+    @UnsupportedAppUsage
     public boolean requiresActionButton() {
         return (mShowAsAction & SHOW_AS_ACTION_ALWAYS) == SHOW_AS_ACTION_ALWAYS;
     }
@@ -806,6 +814,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     public void setActionViewExpanded(boolean isExpanded) {
         mIsActionViewExpanded = isExpanded;
         mMenu.onItemsChanged(false);
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 324f923..e6d3460 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -22,6 +22,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -49,16 +50,19 @@
     // Mutable cached popup menu properties.
     private View mAnchorView;
     private int mDropDownGravity = Gravity.START;
+    @UnsupportedAppUsage
     private boolean mForceShowIcon;
     private Callback mPresenterCallback;
 
     private MenuPopup mPopup;
     private OnDismissListener mOnDismissListener;
 
+    @UnsupportedAppUsage
     public MenuPopupHelper(@NonNull Context context, @NonNull MenuBuilder menu) {
         this(context, menu, null, false, com.android.internal.R.attr.popupMenuStyle, 0);
     }
 
+    @UnsupportedAppUsage
     public MenuPopupHelper(@NonNull Context context, @NonNull MenuBuilder menu,
             @NonNull View anchorView) {
         this(context, menu, anchorView, false, com.android.internal.R.attr.popupMenuStyle, 0);
@@ -92,6 +96,7 @@
       *
       * @param anchor the view to which the popup window should be anchored
       */
+    @UnsupportedAppUsage
     public void setAnchorView(@NonNull View anchor) {
         mAnchorView = anchor;
     }
@@ -105,6 +110,7 @@
      * @param forceShowIcon {@code true} to force icons to be shown, or
      *                  {@code false} for icons to be optionally shown
      */
+    @UnsupportedAppUsage
     public void setForceShowIcon(boolean forceShowIcon) {
         mForceShowIcon = forceShowIcon;
         if (mPopup != null) {
@@ -119,6 +125,7 @@
       *
       * @param gravity alignment of the popup relative to the anchor
       */
+    @UnsupportedAppUsage
     public void setGravity(int gravity) {
         mDropDownGravity = gravity;
     }
@@ -130,6 +137,7 @@
         return mDropDownGravity;
     }
 
+    @UnsupportedAppUsage
     public void show() {
         if (!tryShow()) {
             throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
@@ -143,6 +151,7 @@
     }
 
     @NonNull
+    @UnsupportedAppUsage
     public MenuPopup getPopup() {
         if (mPopup == null) {
             mPopup = createPopup();
@@ -156,6 +165,7 @@
      * @return {@code true} if the popup was shown or was already showing prior to calling this
      *         method, {@code false} otherwise
      */
+    @UnsupportedAppUsage
     public boolean tryShow() {
         if (isShowing()) {
             return true;
@@ -280,6 +290,7 @@
      * Dismisses the popup, if showing.
      */
     @Override
+    @UnsupportedAppUsage
     public void dismiss() {
         if (isShowing()) {
             mPopup.dismiss();
diff --git a/core/java/com/android/internal/view/menu/MenuPresenter.java b/core/java/com/android/internal/view/menu/MenuPresenter.java
index 65bdc09..c5df8ad 100644
--- a/core/java/com/android/internal/view/menu/MenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/MenuPresenter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Parcelable;
 import android.view.ViewGroup;
@@ -47,6 +48,7 @@
          * @return true if the Callback will handle presenting the submenu, false if
          *         the presenter should attempt to do so.
          */
+        @UnsupportedAppUsage
         public boolean onOpenSubMenu(MenuBuilder subMenu);
     }
 
diff --git a/core/java/com/android/internal/view/menu/MenuView.java b/core/java/com/android/internal/view/menu/MenuView.java
index 407caae..67a5530 100644
--- a/core/java/com/android/internal/view/menu/MenuView.java
+++ b/core/java/com/android/internal/view/menu/MenuView.java
@@ -19,6 +19,7 @@
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuItemImpl;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.drawable.Drawable;
 
 /**
@@ -40,6 +41,7 @@
      * Returns the default animations to be used for this menu when entering/exiting.
      * @return A resource ID for the default animations to be used for this menu.
      */
+    @UnsupportedAppUsage
     public int getWindowAnimations();
     
     /**
@@ -61,6 +63,7 @@
          * Gets the item data that this view is displaying.
          * @return the item data, or null if there is not one
          */
+        @UnsupportedAppUsage
         public MenuItemImpl getItemData();
         
         /**
diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
index 897440e..cf6d974 100644
--- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.view.menu;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.view.Menu;
@@ -67,11 +68,13 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void setCallback(Callback callback) {
         mParentMenu.setCallback(callback);
     }
 
     @Override
+    @UnsupportedAppUsage
     public MenuBuilder getRootMenu() {
         return mParentMenu.getRootMenu();
     }
diff --git a/core/java/com/android/internal/widget/CachingIconView.java b/core/java/com/android/internal/widget/CachingIconView.java
index f3b6552..35bff6d 100644
--- a/core/java/com/android/internal/widget/CachingIconView.java
+++ b/core/java/com/android/internal/widget/CachingIconView.java
@@ -18,6 +18,7 @@
 
 import android.annotation.DrawableRes;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
@@ -44,6 +45,7 @@
     private boolean mForceHidden;
     private int mDesiredVisibility;
 
+    @UnsupportedAppUsage
     public CachingIconView(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
     }
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index 64b1f24..0c8613b 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -111,14 +111,16 @@
             final int childHeight = child.getMeasuredHeight();
             int newHeight = Math.max(totalHeight, totalHeight + childHeight + lp.topMargin +
                     lp.bottomMargin + spacing);
-            first = false;
             int measureType = MessagingChild.MEASURED_NORMAL;
             if (messagingChild != null) {
                 measureType = messagingChild.getMeasuredType();
                 linesRemaining -= messagingChild.getConsumedLines();
             }
-            boolean isShortened = measureType == MessagingChild.MEASURED_SHORTENED;
-            boolean isTooSmall = measureType == MessagingChild.MEASURED_TOO_SMALL;
+
+            // We never measure the first item as too small, we want to at least show something.
+            boolean isTooSmall = measureType == MessagingChild.MEASURED_TOO_SMALL && !first;
+            boolean isShortened = measureType == MessagingChild.MEASURED_SHORTENED
+                    || measureType == MessagingChild.MEASURED_TOO_SMALL && first;
             if (newHeight <= targetHeight && !isTooSmall) {
                 totalHeight = newHeight;
                 measuredWidth = Math.max(measuredWidth,
@@ -131,6 +133,7 @@
             } else {
                 break;
             }
+            first = false;
         }
 
         setMeasuredDimension(
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 311bfac..5d48ab9 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -20,6 +20,7 @@
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -67,6 +68,7 @@
 
     private static final int FADE_DURATION = 200;
 
+    @UnsupportedAppUsage
     public ScrollingTabContainerView(Context context) {
         super(context);
         setHorizontalScrollBarEnabled(false);
@@ -134,6 +136,7 @@
         return mTabSpinner != null && mTabSpinner.getParent() == this;
     }
 
+    @UnsupportedAppUsage
     public void setAllowCollapse(boolean allowCollapse) {
         mAllowCollapse = allowCollapse;
     }
@@ -169,6 +172,7 @@
         return false;
     }
 
+    @UnsupportedAppUsage
     public void setTabSelected(int position) {
         mSelectedTabIndex = position;
         final int tabCount = mTabLayout.getChildCount();
@@ -220,6 +224,7 @@
         mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
     }
 
+    @UnsupportedAppUsage
     public void animateToVisibility(int visibility) {
         if (mVisibilityAnim != null) {
             mVisibilityAnim.cancel();
@@ -244,6 +249,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void animateToTab(final int position) {
         final View tabView = mTabLayout.getChildAt(position);
         if (mTabSelector != null) {
@@ -293,6 +299,7 @@
         return tabView;
     }
 
+    @UnsupportedAppUsage
     public void addTab(ActionBar.Tab tab, boolean setSelected) {
         TabView tabView = createTabView(mContext, tab, false);
         mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0,
@@ -308,6 +315,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void addTab(ActionBar.Tab tab, int position, boolean setSelected) {
         final TabView tabView = createTabView(mContext, tab, false);
         mTabLayout.addView(tabView, position, new LinearLayout.LayoutParams(
@@ -323,6 +331,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void updateTab(int position) {
         ((TabView) mTabLayout.getChildAt(position)).update();
         if (mTabSpinner != null) {
@@ -333,6 +342,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void removeTabAt(int position) {
         mTabLayout.removeViewAt(position);
         if (mTabSpinner != null) {
@@ -343,6 +353,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void removeAllTabs() {
         mTabLayout.removeAllViews();
         if (mTabSpinner != null) {
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 95534e2..621d5a6 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -258,13 +258,13 @@
 
         // Start watching for new tombstone files; will record them as they occur.
         // This gets registered with the singleton file observer thread.
-        sTombstoneObserver = new FileObserver(TOMBSTONE_DIR.getPath(), FileObserver.CLOSE_WRITE) {
+        sTombstoneObserver = new FileObserver(TOMBSTONE_DIR.getPath(), FileObserver.CREATE) {
             @Override
             public void onEvent(int event, String path) {
                 HashMap<String, Long> timestamps = readTimestamps();
                 try {
                     File file = new File(TOMBSTONE_DIR, path);
-                    if (file.isFile()) {
+                    if (file.isFile() && file.getName().startsWith("tombstone_")) {
                         addFileToDropBox(db, timestamps, headers, file.getPath(), LOG_SIZE,
                                 TAG_TOMBSTONE);
                     }
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index c5be8e4..0a787b9 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -169,6 +169,10 @@
     final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
     final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
 
+    final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppPermissions = new ArrayMap<>();
+    final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppDenyPermissions =
+            new ArrayMap<>();
+
     final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
 
     public static SystemConfig getInstance() {
@@ -276,6 +280,14 @@
         return mProductPrivAppDenyPermissions.get(packageName);
     }
 
+    public ArraySet<String> getProductServicesPrivAppPermissions(String packageName) {
+        return mProductServicesPrivAppPermissions.get(packageName);
+    }
+
+    public ArraySet<String> getProductServicesPrivAppDenyPermissions(String packageName) {
+        return mProductServicesPrivAppDenyPermissions.get(packageName);
+    }
+
     public Map<String, Boolean> getOemPermissions(String packageName) {
         final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
         if (oemPermissions != null) {
@@ -326,6 +338,17 @@
                 Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
         readPermissions(Environment.buildPath(
                 Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
+
+        // Allow /product_services to customize system configs around libs, features, permissions
+        // and apps.
+        int productServicesPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
+                ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+        readPermissions(Environment.buildPath(
+                Environment.getProductServicesDirectory(), "etc", "sysconfig"),
+                productServicesPermissionFlag);
+        readPermissions(Environment.buildPath(
+                Environment.getProductServicesDirectory(), "etc", "permissions"),
+                productServicesPermissionFlag);
     }
 
     void readPermissions(File libraryDir, int permissionFlag) {
@@ -659,22 +682,27 @@
                     }
                     XmlUtils.skipCurrentTag(parser);
                 } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
-                    // privapp permissions from system, vendor and product partitions are stored
-                    // separately. This is to prevent xml files in the vendor partition from
-                    // granting permissions to priv apps in the system partition and vice
-                    // versa.
+                    // privapp permissions from system, vendor, product and product_services
+                    // partitions are stored separately. This is to prevent xml files in the vendor
+                    // partition from granting permissions to priv apps in the system partition and
+                    // vice versa.
                     boolean vendor = permFile.toPath().startsWith(
-                            Environment.getVendorDirectory().toPath())
+                            Environment.getVendorDirectory().toPath() + "/")
                             || permFile.toPath().startsWith(
-                                Environment.getOdmDirectory().toPath());
+                                Environment.getOdmDirectory().toPath() + "/");
                     boolean product = permFile.toPath().startsWith(
-                            Environment.getProductDirectory().toPath());
+                            Environment.getProductDirectory().toPath() + "/");
+                    boolean productServices = permFile.toPath().startsWith(
+                            Environment.getProductServicesDirectory().toPath() + "/");
                     if (vendor) {
                         readPrivAppPermissions(parser, mVendorPrivAppPermissions,
                                 mVendorPrivAppDenyPermissions);
                     } else if (product) {
                         readPrivAppPermissions(parser, mProductPrivAppPermissions,
                                 mProductPrivAppDenyPermissions);
+                    } else if (productServices) {
+                        readPrivAppPermissions(parser, mProductServicesPrivAppPermissions,
+                                mProductServicesPrivAppDenyPermissions);
                     } else {
                         readPrivAppPermissions(parser, mPrivAppPermissions,
                                 mPrivAppDenyPermissions);
diff --git a/core/java/com/android/server/net/OWNERS b/core/java/com/android/server/net/OWNERS
index ce50558..7311eee 100644
--- a/core/java/com/android/server/net/OWNERS
+++ b/core/java/com/android/server/net/OWNERS
@@ -1,6 +1,8 @@
 set noparent
 
+codewiz@google.com
 ek@google.com
 jchalard@google.com
 lorenzo@google.com
+reminv@google.com
 satk@google.com
diff --git a/core/java/org/apache/http/conn/ssl/AbstractVerifier.java b/core/java/org/apache/http/conn/ssl/AbstractVerifier.java
index b9349b39..36d6e22 100644
--- a/core/java/org/apache/http/conn/ssl/AbstractVerifier.java
+++ b/core/java/org/apache/http/conn/ssl/AbstractVerifier.java
@@ -46,6 +46,7 @@
 import java.util.logging.Logger;
 import java.util.logging.Level;
 
+import android.annotation.UnsupportedAppUsage;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSocket;
@@ -76,6 +77,7 @@
      * Looks like we're the only implementation guarding against this.
      * Firefox, Curl, Sun Java 1.4, 5, 6 don't bother with this check.
      */
+    @UnsupportedAppUsage
     private final static String[] BAD_COUNTRY_2LDS =
           { "ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
             "lg", "ne", "net", "or", "org" };
diff --git a/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
index 250932b..65be161 100644
--- a/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
+++ b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
@@ -36,6 +36,7 @@
 import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
 
+import android.annotation.UnsupportedAppUsage;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
@@ -174,9 +175,13 @@
         return NoPreloadHolder.DEFAULT_FACTORY;
     }
 
+    @UnsupportedAppUsage
     private final SSLContext sslcontext;
+    @UnsupportedAppUsage
     private final javax.net.ssl.SSLSocketFactory socketfactory;
+    @UnsupportedAppUsage
     private final HostNameResolver nameResolver;
+    @UnsupportedAppUsage
     private X509HostnameVerifier hostnameVerifier = BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
 
     public SSLSocketFactory(
@@ -233,6 +238,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public SSLSocketFactory(javax.net.ssl.SSLSocketFactory socketfactory) {
         super();
         this.sslcontext = null;
@@ -245,6 +251,7 @@
      * This constructor is used exclusively to instantiate the factory for
      * {@link #getSocketFactory getSocketFactory}.
      */
+    @UnsupportedAppUsage
     private SSLSocketFactory() {
         super();
         this.sslcontext = null;
@@ -252,6 +259,7 @@
         this.nameResolver = null;
     }
 
+    @UnsupportedAppUsage
     private static KeyManager[] createKeyManagers(final KeyStore keystore, final String password)
         throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
         if (keystore == null) {
@@ -263,6 +271,7 @@
         return kmfactory.getKeyManagers(); 
     }
 
+    @UnsupportedAppUsage
     private static TrustManager[] createTrustManagers(final KeyStore keystore)
         throws KeyStoreException, NoSuchAlgorithmException { 
         if (keystore == null) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index d4903d8..bb8ee14 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -84,8 +84,8 @@
         "android_view_VelocityTracker.cpp",
         "android_text_AndroidCharacter.cpp",
         "android_text_Hyphenator.cpp",
+        "android_text_LineBreaker.cpp",
         "android_text_MeasuredParagraph.cpp",
-        "android_text_StaticLayout.cpp",
         "android_os_Debug.cpp",
         "android_os_GraphicsEnvironment.cpp",
         "android_os_HidlSupport.cpp",
@@ -93,6 +93,7 @@
         "android_os_HwBlob.cpp",
         "android_os_HwParcel.cpp",
         "android_os_HwRemoteBinder.cpp",
+        "android_os_NativeHandle.cpp",
         "android_os_MemoryFile.cpp",
         "android_os_MessageQueue.cpp",
         "android_os_Parcel.cpp",
@@ -126,7 +127,6 @@
         "android/graphics/Camera.cpp",
         "android/graphics/CanvasProperty.cpp",
         "android/graphics/ColorFilter.cpp",
-        "android/graphics/DrawFilter.cpp",
         "android/graphics/FontFamily.cpp",
         "android/graphics/FontUtils.cpp",
         "android/graphics/CreateJavaOutputStreamAdaptor.cpp",
@@ -143,6 +143,7 @@
         "android/graphics/NinePatch.cpp",
         "android/graphics/NinePatchPeeker.cpp",
         "android/graphics/Paint.cpp",
+        "android/graphics/PaintFilter.cpp",
         "android/graphics/Path.cpp",
         "android/graphics/PathMeasure.cpp",
         "android/graphics/PathEffect.cpp",
@@ -154,6 +155,8 @@
         "android/graphics/Typeface.cpp",
         "android/graphics/Utils.cpp",
         "android/graphics/YuvToJpegEncoder.cpp",
+        "android/graphics/fonts/Font.cpp",
+        "android/graphics/fonts/FontFamily.cpp",
         "android/graphics/pdf/PdfDocument.cpp",
         "android/graphics/pdf/PdfEditor.cpp",
         "android/graphics/pdf/PdfRenderer.cpp",
@@ -220,7 +223,6 @@
         "external/skia/src/image",
         "external/skia/src/images",
         "frameworks/base/media/jni",
-        "libcore/include",
         "system/media/camera/include",
         "system/media/private/camera/include",
     ],
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index bd2a8de..6b55ed6 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -140,6 +140,8 @@
 extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
 extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env);
 extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env);
+extern int register_android_graphics_fonts_Font(JNIEnv* env);
+extern int register_android_graphics_fonts_FontFamily(JNIEnv* env);
 extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
 extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
 extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
@@ -166,6 +168,7 @@
 extern int register_android_os_HwBlob(JNIEnv *env);
 extern int register_android_os_HwParcel(JNIEnv *env);
 extern int register_android_os_HwRemoteBinder(JNIEnv *env);
+extern int register_android_os_NativeHandle(JNIEnv *env);
 extern int register_android_os_MessageQueue(JNIEnv* env);
 extern int register_android_os_Parcel(JNIEnv* env);
 extern int register_android_os_SELinux(JNIEnv* env);
@@ -183,7 +186,7 @@
 extern int register_android_text_AndroidCharacter(JNIEnv *env);
 extern int register_android_text_Hyphenator(JNIEnv *env);
 extern int register_android_text_MeasuredParagraph(JNIEnv* env);
-extern int register_android_text_StaticLayout(JNIEnv *env);
+extern int register_android_text_LineBreaker(JNIEnv *env);
 extern int register_android_opengl_classes(JNIEnv *env);
 extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
 extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
@@ -1334,7 +1337,7 @@
     REG_JNI(register_android_text_AndroidCharacter),
     REG_JNI(register_android_text_Hyphenator),
     REG_JNI(register_android_text_MeasuredParagraph),
-    REG_JNI(register_android_text_StaticLayout),
+    REG_JNI(register_android_text_LineBreaker),
     REG_JNI(register_android_view_InputDevice),
     REG_JNI(register_android_view_KeyCharacterMap),
     REG_JNI(register_android_os_Process),
@@ -1346,6 +1349,7 @@
     REG_JNI(register_android_os_HwBlob),
     REG_JNI(register_android_os_HwParcel),
     REG_JNI(register_android_os_HwRemoteBinder),
+    REG_JNI(register_android_os_NativeHandle),
     REG_JNI(register_android_os_VintfObject),
     REG_JNI(register_android_os_VintfRuntimeInfo),
     REG_JNI(register_android_nio_utils),
@@ -1406,6 +1410,8 @@
     REG_JNI(register_android_graphics_YuvImage),
     REG_JNI(register_android_graphics_drawable_AnimatedVectorDrawable),
     REG_JNI(register_android_graphics_drawable_VectorDrawable),
+    REG_JNI(register_android_graphics_fonts_Font),
+    REG_JNI(register_android_graphics_fonts_FontFamily),
     REG_JNI(register_android_graphics_pdf_PdfDocument),
     REG_JNI(register_android_graphics_pdf_PdfEditor),
     REG_JNI(register_android_graphics_pdf_PdfRenderer),
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index ce79049..a365a56 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -1,12 +1,6 @@
 # Camera
-per-file *Camera*,*camera* = cychen@google.com
-per-file *Camera*,*camera* = epeev@google.com
-per-file *Camera*,*camera* = etalvala@google.com
-per-file *Camera*,*camera* = shuzhenwang@google.com
-per-file *Camera*,*camera* = yinchiayeh@google.com
-per-file *Camera*,*camera* = zhijunhe@google.com
+per-file *Camera*,*camera* = cychen@google.com, epeev@google.com, etalvala@google.com
+per-file *Camera*,*camera* = shuzhenwang@google.com, yinchiayeh@google.com, zhijunhe@google.com
 
 # Connectivity
-per-file android_net_*=ek@google.com
-per-file android_net_*=lorenzo@google.com
-per-file android_net_*=satk@google.com
+per-file android_net_* = ek@google.com, lorenzo@google.com, satk@google.com
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index e5aea97..8083a6a 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -310,177 +310,17 @@
 using namespace android;
 using namespace android::bitmap;
 
-///////////////////////////////////////////////////////////////////////////////
-// Conversions to/from SkColor, for get/setPixels, and the create method, which
-// is basically like setPixels
-
-typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
-                              int x, int y);
-
-static void FromColor_F16(void* dst, const SkColor src[], int width,
-                          int, int) {
-    uint64_t* d = (uint64_t*)dst;
-
-    for (int i = 0; i < width; i++) {
-        *d++ = SkColor4f::FromColor(*src++).premul().toF16();
-    }
-}
-
-static void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
-                          int, int) {
-    uint64_t* d = (uint64_t*)dst;
-
-    for (int i = 0; i < width; i++) {
-        const SkColor4f color = SkColor4f::FromColor(*src++);
-        uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
-        scratch[0] = SkFloatToHalf(color.fR);
-        scratch[1] = SkFloatToHalf(color.fG);
-        scratch[2] = SkFloatToHalf(color.fB);
-        scratch[3] = SkFloatToHalf(color.fA);
-    }
-}
-
-static void FromColor_D32(void* dst, const SkColor src[], int width,
-                          int, int) {
-    SkPMColor* d = (SkPMColor*)dst;
-
-    for (int i = 0; i < width; i++) {
-        *d++ = SkPreMultiplyColor(*src++);
-    }
-}
-
-static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
-                          int, int) {
-    // Needed to thwart the unreachable code detection from clang.
-    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
-
-    // SkColor's ordering may be different from SkPMColor
-    if (sk_color_ne_zero) {
-        memcpy(dst, src, width * sizeof(SkColor));
-        return;
-    }
-
-    // order isn't same, repack each pixel manually
-    SkPMColor* d = (SkPMColor*)dst;
-    for (int i = 0; i < width; i++) {
-        SkColor c = *src++;
-        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
-                                   SkColorGetG(c), SkColorGetB(c));
-    }
-}
-
-static void FromColor_D565(void* dst, const SkColor src[], int width,
-                           int x, int y) {
-    uint16_t* d = (uint16_t*)dst;
-
-    DITHER_565_SCAN(y);
-    for (int stop = x + width; x < stop; x++) {
-        SkColor c = *src++;
-        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
-                                DITHER_VALUE(x));
-    }
-}
-
-static void FromColor_D4444(void* dst, const SkColor src[], int width,
-                            int x, int y) {
-    SkPMColor16* d = (SkPMColor16*)dst;
-
-    DITHER_4444_SCAN(y);
-    for (int stop = x + width; x < stop; x++) {
-        SkPMColor pmc = SkPreMultiplyColor(*src++);
-        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
-//        *d++ = SkPixel32ToPixel4444(pmc);
-    }
-}
-
-static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
-                            int x, int y) {
-    SkPMColor16* d = (SkPMColor16*)dst;
-
-    DITHER_4444_SCAN(y);
-    for (int stop = x + width; x < stop; x++) {
-        SkColor c = *src++;
-
-        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
-        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
-                                            SkColorGetG(c), SkColorGetB(c));
-        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
-//        *d++ = SkPixel32ToPixel4444(pmc);
-    }
-}
-
-static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
-    uint8_t* d = (uint8_t*)dst;
-
-    for (int stop = x + width; x < stop; x++) {
-        *d++ = SkColorGetA(*src++);
-    }
-}
-
-// can return NULL
-static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
-    switch (bitmap.colorType()) {
-        case kN32_SkColorType:
-            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
-        case kARGB_4444_SkColorType:
-            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
-                    FromColor_D4444_Raw;
-        case kRGB_565_SkColorType:
-            return FromColor_D565;
-        case kAlpha_8_SkColorType:
-            return FromColor_DA8;
-        case kRGBA_F16_SkColorType:
-            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
-        default:
-            break;
-    }
-    return NULL;
-}
-
 bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
-        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
-    void* dst = dstBitmap.getPixels();
-    FromColorProc proc = ChooseFromColorProc(dstBitmap);
-
-    if (NULL == dst || NULL == proc) {
-        return false;
-    }
-
+        int x, int y, int width, int height, SkBitmap* dstBitmap) {
     const jint* array = env->GetIntArrayElements(srcColors, NULL);
     const SkColor* src = (const SkColor*)array + srcOffset;
 
-    // reset to to actual choice from caller
-    dst = dstBitmap.getAddr(x, y);
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo srcInfo = SkImageInfo::Make(
+            width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
+    SkPixmap srcPM(srcInfo, src, srcStride * 4);
 
-    SkColorSpace* colorSpace = dstBitmap.colorSpace();
-    if (dstBitmap.colorType() == kRGBA_F16_SkColorType ||
-            GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
-        // now copy/convert each scanline
-        for (int y = 0; y < height; y++) {
-            proc(dst, src, width, x, y);
-            src += srcStride;
-            dst = (char*)dst + dstBitmap.rowBytes();
-        }
-    } else {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
-
-        std::unique_ptr<SkColor[]> row(new SkColor[width]);
-
-        // now copy/convert each scanline
-        for (int y = 0; y < height; y++) {
-            memcpy(row.get(), src, sizeof(SkColor) * width);
-            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
-                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
-                    SkAlphaType::kUnpremul_SkAlphaType);
-
-            proc(dst, row.get(), width, x, y);
-            src += srcStride;
-            dst = (char*)dst + dstBitmap.rowBytes();
-        }
-    }
-
-    dstBitmap.notifyPixelsChanged();
+    dstBitmap->writePixels(srcPM, x, y);
 
     env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
     return true;
@@ -488,90 +328,6 @@
 
 //////////////////// ToColor procs
 
-typedef void (*ToColorProc)(SkColor dst[], const void* src, int width);
-
-static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    uint64_t* s = (uint64_t*)src;
-    do {
-        *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
-    } while (--width != 0);
-}
-
-static void ToColor_F16_Raw(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    uint64_t* s = (uint64_t*)src;
-    do {
-        *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
-    } while (--width != 0);
-}
-
-static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor* s = (const SkPMColor*)src;
-    do {
-        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
-    } while (--width != 0);
-}
-
-static void ToColor_S32_Raw(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor* s = (const SkPMColor*)src;
-    do {
-        SkPMColor c = *s++;
-        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
-                                SkGetPackedG32(c), SkGetPackedB32(c));
-    } while (--width != 0);
-}
-
-static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor* s = (const SkPMColor*)src;
-    do {
-        SkPMColor c = *s++;
-        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
-                               SkGetPackedB32(c));
-    } while (--width != 0);
-}
-
-static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor16* s = (const SkPMColor16*)src;
-    do {
-        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
-    } while (--width != 0);
-}
-
-static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor16* s = (const SkPMColor16*)src;
-    do {
-        SkPMColor c = SkPixel4444ToPixel32(*s++);
-        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
-                                SkGetPackedG32(c), SkGetPackedB32(c));
-    } while (--width != 0);
-}
-
-static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor16* s = (const SkPMColor16*)src;
-    do {
-        SkPMColor c = SkPixel4444ToPixel32(*s++);
-        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
-                               SkGetPackedB32(c));
-    } while (--width != 0);
-}
-
-static void ToColor_S565(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const uint16_t* s = (const uint16_t*)src;
-    do {
-        uint16_t c = *s++;
-        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
-                                SkPacked16ToB32(c));
-    } while (--width != 0);
-}
-
 static void ToColor_SA8(SkColor dst[], const void* src, int width) {
     SkASSERT(width > 0);
     const uint8_t* s = (const uint8_t*)src;
@@ -581,52 +337,6 @@
     } while (--width != 0);
 }
 
-// can return NULL
-static ToColorProc ChooseToColorProc(const SkBitmap& src) {
-    switch (src.colorType()) {
-        case kN32_SkColorType:
-            switch (src.alphaType()) {
-                case kOpaque_SkAlphaType:
-                    return ToColor_S32_Opaque;
-                case kPremul_SkAlphaType:
-                    return ToColor_S32_Alpha;
-                case kUnpremul_SkAlphaType:
-                    return ToColor_S32_Raw;
-                default:
-                    return NULL;
-            }
-        case kARGB_4444_SkColorType:
-            switch (src.alphaType()) {
-                case kOpaque_SkAlphaType:
-                    return ToColor_S4444_Opaque;
-                case kPremul_SkAlphaType:
-                    return ToColor_S4444_Alpha;
-                case kUnpremul_SkAlphaType:
-                    return ToColor_S4444_Raw;
-                default:
-                    return NULL;
-            }
-        case kRGB_565_SkColorType:
-            return ToColor_S565;
-        case kAlpha_8_SkColorType:
-            return ToColor_SA8;
-        case kRGBA_F16_SkColorType:
-            switch (src.alphaType()) {
-                case kOpaque_SkAlphaType:
-                    return ToColor_F16_Raw;
-                case kPremul_SkAlphaType:
-                    return ToColor_F16_Alpha;
-                case kUnpremul_SkAlphaType:
-                    return ToColor_F16_Raw;
-                default:
-                    return NULL;
-            }
-        default:
-            break;
-    }
-    return NULL;
-}
-
 static void ToF16_SA8(void* dst, const void* src, int width) {
     SkASSERT(width > 0);
     uint64_t* d = (uint64_t*)dst;
@@ -673,8 +383,8 @@
     SkBitmap bitmap;
     sk_sp<SkColorSpace> colorSpace;
 
-    if (colorType != kN32_SkColorType || xyzD50 == nullptr || transferParameters == nullptr) {
-        colorSpace = GraphicsJNI::colorSpaceForType(colorType);
+    if (xyzD50 == nullptr || transferParameters == nullptr) {
+        colorSpace = SkColorSpace::MakeSRGB();
     } else {
         SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
         SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
@@ -691,7 +401,7 @@
     }
 
     if (jColors != NULL) {
-        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
+        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, &bitmap);
     }
 
     return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
@@ -1268,7 +978,7 @@
     if (!bitmapHolder.valid()) return JNI_TRUE;
 
     SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
-    return GraphicsJNI::isColorSpaceSRGB(colorSpace);
+    return colorSpace == nullptr || colorSpace->isSRGB();
 }
 
 static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) {
@@ -1327,29 +1037,13 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
 
-    ToColorProc proc = ChooseToColorProc(bitmap);
-    if (NULL == proc) {
-        return 0;
-    }
-    const void* src = bitmap.getAddr(x, y);
-    if (NULL == src) {
-        return 0;
-    }
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo dstInfo = SkImageInfo::Make(
+            1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
 
-    SkColor dst[1];
-    proc(dst, src, 1);
-
-    SkColorSpace* colorSpace = bitmap.colorSpace();
-    if (bitmap.colorType() != kRGBA_F16_SkColorType &&
-            !GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
-        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
-                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
-                SkAlphaType::kUnpremul_SkAlphaType);
-    }
-
-    return static_cast<jint>(dst[0]);
+    SkColor dst;
+    bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
+    return static_cast<jint>(dst);
 }
 
 static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
@@ -1358,42 +1052,12 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
 
-    ToColorProc proc = ChooseToColorProc(bitmap);
-    if (NULL == proc) {
-        return;
-    }
-    const void* src = bitmap.getAddr(x, y);
-    if (NULL == src) {
-        return;
-    }
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo dstInfo = SkImageInfo::Make(
+            width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
 
     jint* dst = env->GetIntArrayElements(pixelArray, NULL);
-    SkColor* d = (SkColor*)dst + offset;
-
-    SkColorSpace* colorSpace = bitmap.colorSpace();
-    if (bitmap.colorType() == kRGBA_F16_SkColorType ||
-            GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
-        while (--height >= 0) {
-            proc(d, src, width);
-            d += stride;
-            src = (void*)((const char*)src + bitmap.rowBytes());
-        }
-    } else {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
-
-        while (--height >= 0) {
-            proc(d, src, width);
-
-            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
-                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
-                    SkAlphaType::kUnpremul_SkAlphaType);
-
-            d += stride;
-            src = (void*)((const char*)src + bitmap.rowBytes());
-        }
-    }
-
+    bitmap.readPixels(dstInfo, dst + offset, stride * 4, x, y);
     env->ReleaseIntArrayElements(pixelArray, dst, 0);
 }
 
@@ -1404,27 +1068,13 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
     SkColor color = static_cast<SkColor>(colorHandle);
-    if (NULL == bitmap.getPixels()) {
-        return;
-    }
 
-    FromColorProc proc = ChooseFromColorProc(bitmap);
-    if (NULL == proc) {
-        return;
-    }
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo srcInfo = SkImageInfo::Make(
+            1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
+    SkPixmap srcPM(srcInfo, &color, srcInfo.minRowBytes());
 
-    SkColorSpace* colorSpace = bitmap.colorSpace();
-    if (bitmap.colorType() != kRGBA_F16_SkColorType &&
-            !GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
-        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
-                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
-                SkAlphaType::kUnpremul_SkAlphaType);
-    }
-
-    proc(bitmap.getAddr(x, y), &color, 1, x, y);
-    bitmap.notifyPixelsChanged();
+    bitmap.writePixels(srcPM, x, y);
 }
 
 static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
@@ -1433,7 +1083,7 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
     GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
-            x, y, width, height, bitmap);
+            x, y, width, height, &bitmap);
 }
 
 static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 685fcaf..9ae05f4 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -360,7 +360,7 @@
     // use the default.
     SkImageInfo bitmapInfo = decodeInfo;
     if (decodeInfo.colorSpace() && decodeInfo.colorSpace()->isSRGB()) {
-        bitmapInfo = bitmapInfo.makeColorSpace(GraphicsJNI::colorSpaceForType(decodeColorType));
+        bitmapInfo = bitmapInfo.makeColorSpace(decodeInfo.refColorSpace());
     }
 
     if (decodeColorType == kGray_8_SkColorType) {
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index 76d6851..da95497 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -96,10 +96,12 @@
 }
 
 static void Camera_applyToCanvas(JNIEnv* env, jobject obj, jlong canvasHandle) {
-    SkCanvas* canvas = reinterpret_cast<android::Canvas*>(canvasHandle)->asSkCanvas();
+    android::Canvas* canvas = reinterpret_cast<android::Canvas*>(canvasHandle);
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
-    v->applyToCanvas(canvas);
+    SkMatrix matrix;
+    v->getMatrix(&matrix);
+    canvas->concat(matrix);
 }
 
 static jfloat Camera_dotWithNormal(JNIEnv* env, jobject obj,
diff --git a/core/jni/android/graphics/DrawFilter.cpp b/core/jni/android/graphics/DrawFilter.cpp
deleted file mode 100644
index c1dc0dd..0000000
--- a/core/jni/android/graphics/DrawFilter.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/* libs/android_runtime/android/graphics/ColorFilter.cpp
-**
-** 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.
-*/
-
-// This file was generated from the C++ include file: SkColorFilter.h
-// Any changes made to this file will be discarded by the build.
-// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, 
-// or one of the auxilary file specifications in device/tools/gluemaker.
-
-#include "jni.h"
-#include "GraphicsJNI.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include "core_jni_helpers.h"
-
-#include "SkDrawFilter.h"
-#include "SkPaintFlagsDrawFilter.h"
-#include "SkPaint.h"
-
-namespace android {
-
-// Custom version of SkPaintFlagsDrawFilter that also calls setFilterQuality.
-class CompatFlagsDrawFilter : public SkPaintFlagsDrawFilter {
-public:
-    CompatFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags,
-            SkFilterQuality desiredQuality)
-    : SkPaintFlagsDrawFilter(clearFlags, setFlags)
-    , fDesiredQuality(desiredQuality) {
-    }
-
-    virtual bool filter(SkPaint* paint, Type type) {
-        SkPaintFlagsDrawFilter::filter(paint, type);
-        paint->setFilterQuality(fDesiredQuality);
-        return true;
-    }
-
-private:
-    const SkFilterQuality fDesiredQuality;
-};
-
-// Returns whether flags contains FILTER_BITMAP_FLAG. If flags does, remove it.
-static inline bool hadFiltering(jint& flags) {
-    // Equivalent to the Java Paint's FILTER_BITMAP_FLAG.
-    static const uint32_t sFilterBitmapFlag = 0x02;
-
-    const bool result = (flags & sFilterBitmapFlag) != 0;
-    flags &= ~sFilterBitmapFlag;
-    return result;
-}
-
-class SkDrawFilterGlue {
-public:
-
-    static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkDrawFilter* obj = reinterpret_cast<SkDrawFilter*>(objHandle);
-        SkSafeUnref(obj);
-    }
-
-    static jlong CreatePaintFlagsDF(JNIEnv* env, jobject clazz,
-                                    jint clearFlags, jint setFlags) {
-        if (clearFlags | setFlags) {
-            // Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no
-            // longer has a Skia equivalent flag (instead it corresponds to
-            // calling setFilterQuality), and keep track of which group(s), if
-            // any, had the flag set.
-            const bool turnFilteringOn = hadFiltering(setFlags);
-            const bool turnFilteringOff = hadFiltering(clearFlags);
-
-            SkDrawFilter* filter;
-            if (turnFilteringOn) {
-                // Turning filtering on overrides turning it off.
-                filter = new CompatFlagsDrawFilter(clearFlags, setFlags,
-                        kLow_SkFilterQuality);
-            } else if (turnFilteringOff) {
-                filter = new CompatFlagsDrawFilter(clearFlags, setFlags,
-                        kNone_SkFilterQuality);
-            } else {
-                filter = new SkPaintFlagsDrawFilter(clearFlags, setFlags);
-            }
-            return reinterpret_cast<jlong>(filter);
-        } else {
-            return NULL;
-        }
-    }
-};
-
-static const JNINativeMethod drawfilter_methods[] = {
-    {"nativeDestructor", "(J)V", (void*) SkDrawFilterGlue::finalizer}
-};
-
-static const JNINativeMethod paintflags_methods[] = {
-    {"nativeConstructor","(II)J", (void*) SkDrawFilterGlue::CreatePaintFlagsDF}
-};
-
-int register_android_graphics_DrawFilter(JNIEnv* env) {
-    int result = RegisterMethodsOrDie(env, "android/graphics/DrawFilter", drawfilter_methods,
-                                      NELEM(drawfilter_methods));
-    result |= RegisterMethodsOrDie(env, "android/graphics/PaintFlagsDrawFilter", paintflags_methods,
-                                   NELEM(paintflags_methods));
-    
-    return 0;
-}
-
-}
diff --git a/core/jni/android/graphics/FontUtils.h b/core/jni/android/graphics/FontUtils.h
index 9eaaa49..9f6462e 100644
--- a/core/jni/android/graphics/FontUtils.h
+++ b/core/jni/android/graphics/FontUtils.h
@@ -20,6 +20,8 @@
 #include <jni.h>
 #include <memory>
 
+#include <minikin/Font.h>
+
 namespace minikin {
 class FontFamily;
 }  // namespace minikin
@@ -31,6 +33,11 @@
   std::shared_ptr<minikin::FontFamily> family;
 };
 
+struct FontWrapper {
+  FontWrapper(minikin::Font&& font) : font(std::move(font)) {}
+  minikin::Font font;
+};
+
 // Utility wrapper for java.util.List
 class ListHelper {
 public:
diff --git a/core/jni/android/graphics/GraphicBuffer.cpp b/core/jni/android/graphics/GraphicBuffer.cpp
index ae6fd38..344e22c 100644
--- a/core/jni/android/graphics/GraphicBuffer.cpp
+++ b/core/jni/android/graphics/GraphicBuffer.cpp
@@ -196,8 +196,7 @@
     SkBitmap bitmap;
     bitmap.setInfo(SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(),
                                      convertPixelFormat(buffer->getPixelFormat()),
-                                     kPremul_SkAlphaType,
-                                     GraphicsJNI::defaultColorSpace()),
+                                     kPremul_SkAlphaType),
                    bytesCount);
 
     if (buffer->getWidth() > 0 && buffer->getHeight() > 0) {
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 5d65aee..26af15e 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -454,31 +454,6 @@
     return wrapper;
 }
 
-sk_sp<SkColorSpace> GraphicsJNI::defaultColorSpace() {
-#ifdef ANDROID_ENABLE_LINEAR_BLENDING
-    return SkColorSpace::MakeSRGB();
-#else
-    return nullptr;
-#endif
-}
-
-sk_sp<SkColorSpace> GraphicsJNI::linearColorSpace() {
-    return SkColorSpace::MakeSRGBLinear();
-}
-
-sk_sp<SkColorSpace> GraphicsJNI::colorSpaceForType(SkColorType type) {
-    switch (type) {
-        case kRGBA_F16_SkColorType:
-            return linearColorSpace();
-        default:
-            return defaultColorSpace();
-    }
-}
-
-bool GraphicsJNI::isColorSpaceSRGB(SkColorSpace* colorSpace) {
-    return colorSpace == nullptr || colorSpace->isSRGB();
-}
-
 SkColorSpaceTransferFn GraphicsJNI::getNativeTransferParameters(JNIEnv* env, jobject transferParams) {
     SkColorSpaceTransferFn p;
     p.fA = (float) env->GetDoubleField(transferParams, gTransferParams_aFieldID);
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 7825f1d..cee3c46 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -102,12 +102,7 @@
     */
     static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
             int srcStride, int x, int y, int width, int height,
-            const SkBitmap& dstBitmap);
-
-    static sk_sp<SkColorSpace> defaultColorSpace();
-    static sk_sp<SkColorSpace> linearColorSpace();
-    static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
-    static bool isColorSpaceSRGB(SkColorSpace* colorSpace);
+            SkBitmap* dstBitmap);
 
     static SkColorSpaceTransferFn getNativeTransferParameters(JNIEnv* env, jobject transferParams);
     static SkMatrix44 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50);
diff --git a/core/jni/android/graphics/PaintFilter.cpp b/core/jni/android/graphics/PaintFilter.cpp
new file mode 100644
index 0000000..182b22b
--- /dev/null
+++ b/core/jni/android/graphics/PaintFilter.cpp
@@ -0,0 +1,124 @@
+/* libs/android_runtime/android/graphics/ColorFilter.cpp
+**
+** 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.
+*/
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "core_jni_helpers.h"
+
+#include "hwui/PaintFilter.h"
+#include "SkPaint.h"
+
+namespace android {
+
+class PaintFlagsFilter : public PaintFilter {
+public:
+    PaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags) {
+        fClearFlags = static_cast<uint16_t>(clearFlags & SkPaint::kAllFlags);
+        fSetFlags = static_cast<uint16_t>(setFlags & SkPaint::kAllFlags);
+    }
+    void filter(SkPaint* paint) override {
+        paint->setFlags((paint->getFlags() & ~fClearFlags) | fSetFlags);
+    }
+
+private:
+    uint16_t fClearFlags;
+    uint16_t fSetFlags;
+};
+
+// Custom version of PaintFlagsDrawFilter that also calls setFilterQuality.
+class CompatPaintFlagsFilter : public PaintFlagsFilter {
+public:
+    CompatPaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags, SkFilterQuality desiredQuality)
+    : PaintFlagsFilter(clearFlags, setFlags)
+    , fDesiredQuality(desiredQuality) {
+    }
+
+    virtual void filter(SkPaint* paint) {
+        PaintFlagsFilter::filter(paint);
+        paint->setFilterQuality(fDesiredQuality);
+    }
+
+private:
+    const SkFilterQuality fDesiredQuality;
+};
+
+// Returns whether flags contains FILTER_BITMAP_FLAG. If flags does, remove it.
+static inline bool hadFiltering(jint& flags) {
+    // Equivalent to the Java Paint's FILTER_BITMAP_FLAG.
+    static const uint32_t sFilterBitmapFlag = 0x02;
+
+    const bool result = (flags & sFilterBitmapFlag) != 0;
+    flags &= ~sFilterBitmapFlag;
+    return result;
+}
+
+class PaintFilterGlue {
+public:
+
+    static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
+        PaintFilter* obj = reinterpret_cast<PaintFilter*>(objHandle);
+        SkSafeUnref(obj);
+    }
+
+    static jlong CreatePaintFlagsFilter(JNIEnv* env, jobject clazz,
+                                        jint clearFlags, jint setFlags) {
+        if (clearFlags | setFlags) {
+            // Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no
+            // longer has a Skia equivalent flag (instead it corresponds to
+            // calling setFilterQuality), and keep track of which group(s), if
+            // any, had the flag set.
+            const bool turnFilteringOn = hadFiltering(setFlags);
+            const bool turnFilteringOff = hadFiltering(clearFlags);
+
+            PaintFilter* filter;
+            if (turnFilteringOn) {
+                // Turning filtering on overrides turning it off.
+                filter = new CompatPaintFlagsFilter(clearFlags, setFlags,
+                        kLow_SkFilterQuality);
+            } else if (turnFilteringOff) {
+                filter = new CompatPaintFlagsFilter(clearFlags, setFlags,
+                        kNone_SkFilterQuality);
+            } else {
+                filter = new PaintFlagsFilter(clearFlags, setFlags);
+            }
+            return reinterpret_cast<jlong>(filter);
+        } else {
+            return NULL;
+        }
+    }
+};
+
+static const JNINativeMethod drawfilter_methods[] = {
+    {"nativeDestructor", "(J)V", (void*) PaintFilterGlue::finalizer}
+};
+
+static const JNINativeMethod paintflags_methods[] = {
+    {"nativeConstructor","(II)J", (void*) PaintFilterGlue::CreatePaintFlagsFilter}
+};
+
+int register_android_graphics_DrawFilter(JNIEnv* env) {
+    int result = RegisterMethodsOrDie(env, "android/graphics/DrawFilter", drawfilter_methods,
+                                      NELEM(drawfilter_methods));
+    result |= RegisterMethodsOrDie(env, "android/graphics/PaintFlagsDrawFilter", paintflags_methods,
+                                   NELEM(paintflags_methods));
+
+    return 0;
+}
+
+}
diff --git a/core/jni/android/graphics/fonts/Font.cpp b/core/jni/android/graphics/fonts/Font.cpp
new file mode 100644
index 0000000..2d1d7a0
--- /dev/null
+++ b/core/jni/android/graphics/fonts/Font.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Minikin"
+
+#include <nativehelper/JNIHelp.h>
+#include <core_jni_helpers.h>
+
+#include "SkData.h"
+#include "SkFontMgr.h"
+#include "SkRefCnt.h"
+#include "SkTypeface.h"
+#include "GraphicsJNI.h"
+#include <nativehelper/ScopedUtfChars.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_util_AssetManager.h>
+#include <androidfw/AssetManager2.h>
+#include "Utils.h"
+#include "FontUtils.h"
+
+#include <hwui/MinikinSkia.h>
+#include <hwui/Typeface.h>
+#include <utils/FatVector.h>
+#include <minikin/FontFamily.h>
+
+#include <memory>
+
+namespace android {
+
+struct NativeFontBuilder {
+    std::vector<minikin::FontVariation> axes;
+};
+
+static inline NativeFontBuilder* toBuilder(jlong ptr) {
+    return reinterpret_cast<NativeFontBuilder*>(ptr);
+}
+
+static inline Asset* toAsset(jlong ptr) {
+    return reinterpret_cast<Asset*>(ptr);
+}
+
+static void releaseAsset(jlong asset) {
+    delete toAsset(asset);
+}
+
+static void releaseFont(jlong font) {
+    delete reinterpret_cast<FontWrapper*>(font);
+}
+
+static void release_global_ref(const void* /*data*/, void* context) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (env == nullptr) {
+        JavaVMAttachArgs args;
+        args.version = JNI_VERSION_1_4;
+        args.name = "release_font_data";
+        args.group = nullptr;
+        jint result = AndroidRuntime::getJavaVM()->AttachCurrentThread(&env, &args);
+        if (result != JNI_OK) {
+            ALOGE("failed to attach to thread to release global ref.");
+            return;
+        }
+    }
+
+    jobject obj = reinterpret_cast<jobject>(context);
+    env->DeleteGlobalRef(obj);
+}
+
+// Regular JNI
+static jlong Font_Builder_getNativeAsset(
+    JNIEnv* env, jobject clazz, jobject assetMgr, jstring path, jboolean isAsset, jint cookie) {
+    NPE_CHECK_RETURN_ZERO(env, assetMgr);
+    NPE_CHECK_RETURN_ZERO(env, path);
+
+    Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, assetMgr);
+    if (mgr == nullptr) {
+        return 0;
+    }
+
+    ScopedUtfChars str(env, path);
+    if (str.c_str() == nullptr) {
+        return 0;
+    }
+
+    std::unique_ptr<Asset> asset;
+    {
+      ScopedLock<AssetManager2> locked_mgr(*mgr);
+      if (isAsset) {
+          asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
+      } else if (cookie > 0) {
+          // Valid java cookies are 1-based, but AssetManager cookies are 0-based.
+          asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
+                  Asset::ACCESS_BUFFER);
+      } else {
+          asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
+      }
+    }
+
+    return reinterpret_cast<jlong>(asset.release());
+}
+
+// Regular JNI
+static jobject Font_Builder_getAssetBuffer(JNIEnv* env, jobject clazz, jlong nativeAsset) {
+    Asset* asset = toAsset(nativeAsset);
+    return env->NewDirectByteBuffer(const_cast<void*>(asset->getBuffer(false)), asset->getLength());
+}
+
+// CriticalNative
+static jlong Font_Builder_getReleaseNativeAssetFunc() {
+    return reinterpret_cast<jlong>(&releaseAsset);
+}
+
+// Regular JNI
+static jlong Font_Builder_initBuilder(JNIEnv*, jobject) {
+    return reinterpret_cast<jlong>(new NativeFontBuilder());
+}
+
+// Critical Native
+static void Font_Builder_addAxis(jlong builderPtr, jint tag, jfloat value) {
+    toBuilder(builderPtr)->axes.emplace_back(static_cast<minikin::AxisTag>(tag), value);
+}
+
+// Regular JNI
+static jlong Font_Builder_build(JNIEnv* env, jobject clazz, jlong builderPtr, jobject buffer,
+        jint weight, jboolean italic, jint ttcIndex) {
+    NPE_CHECK_RETURN_ZERO(env, buffer);
+    std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
+    const void* fontPtr = env->GetDirectBufferAddress(buffer);
+    if (fontPtr == nullptr) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
+        return 0;
+    }
+    jlong fontSize = env->GetDirectBufferCapacity(buffer);
+    if (fontSize <= 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "buffer size must not be zero or negative");
+        return 0;
+    }
+    jobject fontRef = MakeGlobalRefOrDie(env, buffer);
+    sk_sp<SkData> data(SkData::MakeWithProc(fontPtr, fontSize,
+            release_global_ref, reinterpret_cast<void*>(fontRef)));
+
+    uirenderer::FatVector<SkFontArguments::Axis, 2> skiaAxes;
+    for (const auto& axis : builder->axes) {
+        skiaAxes.emplace_back(SkFontArguments::Axis{axis.axisTag, axis.value});
+    }
+
+    std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(std::move(data)));
+
+    SkFontArguments params;
+    params.setCollectionIndex(ttcIndex);
+    params.setAxes(skiaAxes.data(), skiaAxes.size());
+
+    sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
+    sk_sp<SkTypeface> face(fm->makeFromStream(std::move(fontData), params));
+    if (face == nullptr) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "Failed to create internal object. maybe invalid font data.");
+        return 0;
+    }
+    std::shared_ptr<minikin::MinikinFont> minikinFont =
+            std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize, ttcIndex,
+                    builder->axes);
+    minikin::Font font = minikin::Font::Builder(minikinFont).setWeight(weight)
+                    .setSlant(static_cast<minikin::FontStyle::Slant>(italic)).build();
+    return reinterpret_cast<jlong>(new FontWrapper(std::move(font)));
+}
+
+// Critical Native
+static jlong Font_Builder_getReleaseNativeFont() {
+    return reinterpret_cast<jlong>(releaseFont);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const JNINativeMethod gFontBuilderMethods[] = {
+    { "nInitBuilder", "()J", (void*) Font_Builder_initBuilder },
+    { "nAddAxis", "(JIF)V", (void*) Font_Builder_addAxis },
+    { "nBuild", "(JLjava/nio/ByteBuffer;IZI)J", (void*) Font_Builder_build },
+    { "nGetReleaseNativeFont", "()J", (void*) Font_Builder_getReleaseNativeFont },
+
+    { "nGetNativeAsset", "(Landroid/content/res/AssetManager;Ljava/lang/String;ZI)J",
+      (void*) Font_Builder_getNativeAsset },
+    { "nGetAssetBuffer", "(J)Ljava/nio/ByteBuffer;", (void*) Font_Builder_getAssetBuffer },
+    { "nGetReleaseNativeAssetFunc", "()J", (void*) Font_Builder_getReleaseNativeAssetFunc },
+};
+
+int register_android_graphics_fonts_Font(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, "android/graphics/fonts/Font$Builder", gFontBuilderMethods,
+            NELEM(gFontBuilderMethods));
+}
+
+}
diff --git a/core/jni/android/graphics/fonts/FontFamily.cpp b/core/jni/android/graphics/fonts/FontFamily.cpp
new file mode 100644
index 0000000..767e068
--- /dev/null
+++ b/core/jni/android/graphics/fonts/FontFamily.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Minikin"
+
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <core_jni_helpers.h>
+
+#include "FontUtils.h"
+
+#include <minikin/FontFamily.h>
+#include <minikin/LocaleList.h>
+
+#include <memory>
+
+namespace android {
+
+struct NativeFamilyBuilder {
+    std::vector<minikin::Font> fonts;
+};
+
+static inline NativeFamilyBuilder* toBuilder(jlong ptr) {
+    return reinterpret_cast<NativeFamilyBuilder*>(ptr);
+}
+
+static inline FontWrapper* toFontWrapper(jlong ptr) {
+    return reinterpret_cast<FontWrapper*>(ptr);
+}
+
+static void releaseFontFamily(jlong family) {
+    delete reinterpret_cast<FontFamilyWrapper*>(family);
+}
+
+// Regular JNI
+static jlong FontFamily_Builder_initBuilder(JNIEnv*, jobject) {
+    return reinterpret_cast<jlong>(new NativeFamilyBuilder());
+}
+
+// Critical Native
+static void FontFamily_Builder_addFont(jlong builderPtr, jlong fontPtr) {
+    toBuilder(builderPtr)->fonts.push_back(toFontWrapper(fontPtr)->font);
+}
+
+// Regular JNI
+static jlong FontFamily_Builder_build(JNIEnv* env, jobject clazz, jlong builderPtr,
+            jstring langTags, jint variant) {
+    std::unique_ptr<NativeFamilyBuilder> builder(toBuilder(builderPtr));
+    uint32_t localeId;
+    if (langTags == nullptr) {
+        localeId = minikin::registerLocaleList("");
+    } else {
+        ScopedUtfChars str(env, langTags);
+        localeId = minikin::registerLocaleList(str.c_str());
+    }
+    std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
+            localeId, static_cast<minikin::FamilyVariant>(variant), std::move(builder->fonts));
+    if (family->getCoverage().length() == 0) {
+        // No coverage means minikin rejected given font for some reasons.
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "Failed to create internal object. maybe invalid font data");
+        return 0;
+    }
+    return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
+}
+
+// CriticalNative
+static jlong FontFamily_Builder_GetReleaseFunc() {
+    return reinterpret_cast<jlong>(releaseFontFamily);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const JNINativeMethod gFontFamilyBuilderMethods[] = {
+    { "nInitBuilder", "()J", (void*) FontFamily_Builder_initBuilder },
+    { "nAddFont", "(JJ)V", (void*) FontFamily_Builder_addFont },
+    { "nBuild", "(JLjava/lang/String;I)J", (void*) FontFamily_Builder_build },
+
+    { "nGetReleaseNativeFamily", "()J", (void*) FontFamily_Builder_GetReleaseFunc },
+};
+
+int register_android_graphics_fonts_FontFamily(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, "android/graphics/fonts/FontFamily$Builder",
+            gFontFamilyBuilderMethods, NELEM(gFontFamilyBuilderMethods));
+}
+
+}
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 484b33f..eba4c50 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -22,13 +22,13 @@
 #include <androidfw/ResourceTypes.h>
 #include <hwui/Canvas.h>
 #include <hwui/Paint.h>
+#include <hwui/PaintFilter.h>
 #include <hwui/Typeface.h>
 #include <minikin/Layout.h>
 #include <nativehelper/ScopedPrimitiveArray.h>
 #include <nativehelper/ScopedStringChars.h>
 
 #include "Bitmap.h"
-#include "SkDrawFilter.h"
 #include "SkGraphics.h"
 #include "SkRegion.h"
 #include "SkVertices.h"
@@ -320,9 +320,12 @@
                          jintArray jcolors, jint colorIndex,
                          jshortArray jindices, jint indexIndex,
                          jint indexCount, jlong paintHandle) {
+
+    const int vertexCount = floatCount >> 1;  // 2 floats per SkPoint
+
     AutoJavaFloatArray  vertA(env, jverts, vertIndex + floatCount);
     AutoJavaFloatArray  texA(env, jtexs, texIndex + floatCount);
-    AutoJavaIntArray    colorA(env, jcolors, colorIndex + floatCount);
+    AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
     AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
 
     const float* verts = vertA.ptr() + vertIndex;
@@ -337,7 +340,6 @@
         indices = (const uint16_t*)(indexA.ptr() + indexIndex);
     }
 
-    int vertexCount = floatCount >> 1;  // 2 floats per SkPoint
     SkVertices::VertexMode mode = static_cast<SkVertices::VertexMode>(modeHandle);
     const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawVertices(SkVertices::MakeCopy(mode, vertexCount,
@@ -460,7 +462,7 @@
         return;
     }
 
-    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
+    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, &bitmap)) {
         return;
     }
 
@@ -582,8 +584,9 @@
     env->ReleaseStringChars(text, jchars);
 }
 
-static void setDrawFilter(jlong canvasHandle, jlong filterHandle) {
-    get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
+static void setPaintFilter(jlong canvasHandle, jlong filterHandle) {
+    PaintFilter* paintFilter = reinterpret_cast<PaintFilter*>(filterHandle);
+    get_canvas(canvasHandle)->setPaintFilter(sk_ref_sp(paintFilter));
 }
 
 static void freeCaches(JNIEnv* env, jobject) {
@@ -633,7 +636,7 @@
     {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
     {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
     {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
-    {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
+    {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setPaintFilter},
 };
 
 // If called from Canvas these are regular JNI
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 0ba9a8c..c977437 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -1748,19 +1748,20 @@
             }
         }
 
-
-        size_t listSize = builder.getSize();
-        uint8_t opcodeListBuf[listSize];
-        err = builder.buildOpList(opcodeListBuf);
-        if (err == OK) {
-            BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf,
-                    TIFF_IFD_0), env, TAG_OPCODELIST2, writer);
-        } else {
-            ALOGE("%s: Could not build list of opcodes for distortion correction and lens shading"
-                    "map.", __FUNCTION__);
-            jniThrowRuntimeException(env, "failed to construct opcode list for distortion"
-                    " correction and lens shading map");
-            return nullptr;
+        if (builder.getCount() > 0) {
+            size_t listSize = builder.getSize();
+            uint8_t opcodeListBuf[listSize];
+            err = builder.buildOpList(opcodeListBuf);
+            if (err == OK) {
+                BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_OPCODELIST2, listSize,
+                        opcodeListBuf, TIFF_IFD_0), env, TAG_OPCODELIST2, writer);
+            } else {
+                ALOGE("%s: Could not build list of opcodes for lens shading map and bad pixel "
+                        "correction.", __FUNCTION__);
+                jniThrowRuntimeException(env, "failed to construct opcode list for lens shading "
+                        "map and bad pixel correction");
+                return nullptr;
+            }
         }
     }
 
@@ -1846,18 +1847,20 @@
             }
         }
 
-        size_t listSize = builder.getSize();
-        uint8_t opcodeListBuf[listSize];
-        err = builder.buildOpList(opcodeListBuf);
-        if (err == OK) {
-            BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_OPCODELIST3, listSize, opcodeListBuf,
-                    TIFF_IFD_0), env, TAG_OPCODELIST3, writer);
-        } else {
-            ALOGE("%s: Could not build list of opcodes for distortion correction and lens shading"
-                    "map.", __FUNCTION__);
-            jniThrowRuntimeException(env, "failed to construct opcode list for distortion"
-                    " correction and lens shading map");
-            return nullptr;
+        if (builder.getCount() > 0) {
+            size_t listSize = builder.getSize();
+            uint8_t opcodeListBuf[listSize];
+            err = builder.buildOpList(opcodeListBuf);
+            if (err == OK) {
+                BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_OPCODELIST3, listSize,
+                        opcodeListBuf, TIFF_IFD_0), env, TAG_OPCODELIST3, writer);
+            } else {
+                ALOGE("%s: Could not build list of opcodes for distortion correction.",
+                        __FUNCTION__);
+                jniThrowRuntimeException(env, "failed to construct opcode list for distortion"
+                        " correction");
+                return nullptr;
+            }
         }
     }
 
@@ -1968,8 +1971,14 @@
         tagsToMove.add(TAG_DEFAULTSCALE);
         tagsToMove.add(TAG_DEFAULTCROPORIGIN);
         tagsToMove.add(TAG_DEFAULTCROPSIZE);
-        tagsToMove.add(TAG_OPCODELIST2);
-        tagsToMove.add(TAG_OPCODELIST3);
+
+        if (nullptr != writer->getEntry(TAG_OPCODELIST2, TIFF_IFD_0).get()) {
+            tagsToMove.add(TAG_OPCODELIST2);
+        }
+
+        if (nullptr != writer->getEntry(TAG_OPCODELIST3, TIFF_IFD_0).get()) {
+            tagsToMove.add(TAG_OPCODELIST3);
+        }
 
         if (moveEntries(writer, TIFF_IFD_0, TIFF_IFD_SUB1, tagsToMove) != OK) {
             jniThrowException(env, "java/lang/IllegalStateException", "Failed to move entries");
diff --git a/core/jni/android_media_MediaMetricsJNI.h b/core/jni/android_media_MediaMetricsJNI.h
index 16081b4..b3cb4d2 100644
--- a/core/jni/android_media_MediaMetricsJNI.h
+++ b/core/jni/android_media_MediaMetricsJNI.h
@@ -17,7 +17,6 @@
 #ifndef _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
 #define _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
 
-#include <android_runtime/AndroidRuntime.h>
 #include <jni.h>
 #include <nativehelper/JNIHelp.h>
 #include <media/MediaAnalyticsItem.h>
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 823f1cc..9b138eb 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -323,6 +323,55 @@
     return (jboolean) !queryUserAccess(uid, netId);
 }
 
+static bool checkLenAndCopy(JNIEnv* env, const jbyteArray& addr, int len, void* dst)
+{
+    if (env->GetArrayLength(addr) != len) {
+        return false;
+    }
+    env->GetByteArrayRegion(addr, 0, len, reinterpret_cast<jbyte*>(dst));
+    return true;
+}
+
+static void android_net_utils_addArpEntry(JNIEnv *env, jobject thiz, jbyteArray ethAddr,
+        jbyteArray ipv4Addr, jstring ifname, jobject javaFd)
+{
+    struct arpreq req = {};
+    struct sockaddr_in& netAddrStruct = *reinterpret_cast<sockaddr_in*>(&req.arp_pa);
+    struct sockaddr& ethAddrStruct = req.arp_ha;
+
+    ethAddrStruct.sa_family = ARPHRD_ETHER;
+    if (!checkLenAndCopy(env, ethAddr, ETH_ALEN, ethAddrStruct.sa_data)) {
+        jniThrowException(env, "java/io/IOException", "Invalid ethAddr length");
+        return;
+    }
+
+    netAddrStruct.sin_family = AF_INET;
+    if (!checkLenAndCopy(env, ipv4Addr, sizeof(in_addr), &netAddrStruct.sin_addr)) {
+        jniThrowException(env, "java/io/IOException", "Invalid ipv4Addr length");
+        return;
+    }
+
+    int ifLen = env->GetStringLength(ifname);
+    // IFNAMSIZ includes the terminating NULL character
+    if (ifLen >= IFNAMSIZ) {
+        jniThrowException(env, "java/io/IOException", "ifname too long");
+        return;
+    }
+    env->GetStringUTFRegion(ifname, 0, ifLen, req.arp_dev);
+
+    req.arp_flags = ATF_COM;  // Completed entry (ha valid)
+    int fd = jniGetFDFromFileDescriptor(env, javaFd);
+    if (fd < 0) {
+        jniThrowExceptionFmt(env, "java/io/IOException", "Invalid file descriptor");
+        return;
+    }
+    // See also: man 7 arp
+    if (ioctl(fd, SIOCSARP, &req)) {
+        jniThrowExceptionFmt(env, "java/io/IOException", "ioctl error: %s", strerror(errno));
+        return;
+    }
+}
+
 
 // ----------------------------------------------------------------------------
 
@@ -337,6 +386,7 @@
     { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
     { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
     { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
+    { "addArpEntry", "([B[BLjava/lang/String;Ljava/io/FileDescriptor;)V", (void*) android_net_utils_addArpEntry },
     { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
     { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
     { "attachControlPacketFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachControlPacketFilter },
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 638b3ea..26367c2 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -602,7 +602,7 @@
 
     struct graphics_memory_pss graphics_mem;
     if (read_memtrack_memory(pid, &graphics_mem) == 0) {
-        pss = uss = memtrack = graphics_mem.graphics + graphics_mem.gl + graphics_mem.other;
+        pss = uss = rss = memtrack = graphics_mem.graphics + graphics_mem.gl + graphics_mem.other;
     }
 
     {
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 4ecfd4b..dfa5de6 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -29,7 +29,8 @@
 }
 
 void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
-    android_namespace_t* appNamespace = android::FindNamespaceByClassLoader(env, classLoader);
+    android::NativeLoaderNamespace* appNamespace = android::FindNativeLoaderNamespaceByClassLoader(
+        env, classLoader);
     ScopedUtfChars layerPathsChars(env, layerPaths);
     android::GraphicsEnv::getInstance().setLayerPaths(appNamespace, layerPathsChars.c_str());
 }
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 08d9527..163b86b 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -33,6 +33,7 @@
 #include <hidl/ServiceManagement.h>
 #include <hidl/Status.h>
 #include <hidl/HidlTransportSupport.h>
+#include <hwbinder/IPCThreadState.h>
 #include <hwbinder/ProcessState.h>
 #include <nativehelper/ScopedLocalRef.h>
 #include <nativehelper/ScopedUtfChars.h>
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index bb916d2..cb55618 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -21,6 +21,7 @@
 #include "android_os_HwBlob.h"
 
 #include "android_os_HwParcel.h"
+#include "android_os_NativeHandle.h"
 
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
@@ -31,6 +32,7 @@
 #include "core_jni_helpers.h"
 
 using android::AndroidRuntime;
+using android::hardware::hidl_handle;
 using android::hardware::hidl_string;
 
 #define PACKAGE_PATH    "android/os"
@@ -82,6 +84,7 @@
 JHwBlob::JHwBlob(JNIEnv *env, jobject thiz, size_t size)
     : mBuffer(nullptr),
       mSize(size),
+      mType(BlobType::GENERIC),
       mOwnsBuffer(true),
       mHandle(0) {
     if (size > 0) {
@@ -159,6 +162,15 @@
     return mSize;
 }
 
+void JHwBlob::specializeBlobTo(BlobType type) {
+    CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));
+    mType = type;
+}
+
+JHwBlob::BlobType JHwBlob::type() const {
+    return mType;
+}
+
 status_t JHwBlob::putBlob(size_t offset, const sp<JHwBlob> &blob) {
     size_t index = mSubBlobs.add();
     BlobInfo *info = &mSubBlobs.editItemAt(index);
@@ -172,42 +184,52 @@
 }
 
 status_t JHwBlob::writeToParcel(hardware::Parcel *parcel) const {
-    size_t handle;
+    CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));
+
+    size_t handle = 0;
     status_t err = parcel->writeBuffer(data(), size(), &handle);
 
     if (err != OK) {
         return err;
     }
 
-    for (size_t i = 0; i < mSubBlobs.size(); ++i) {
-        const BlobInfo &info = mSubBlobs[i];
-
-        err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);
-
-        if (err != OK) {
-            return err;
-        }
-    }
-
-    return OK;
+    return writeSubBlobsToParcel(parcel, handle);
 }
 
 status_t JHwBlob::writeEmbeddedToParcel(
         hardware::Parcel *parcel,
         size_t parentHandle,
         size_t parentOffset) const {
-    size_t handle;
-    status_t err = parcel->writeEmbeddedBuffer(
-            data(), size(), &handle, parentHandle, parentOffset);
+    size_t handle = 0;
+    status_t err = OK;
+
+    switch (mType) {
+        case BlobType::GENERIC: {
+            err = parcel->writeEmbeddedBuffer(data(), size(), &handle, parentHandle, parentOffset);
+            break;
+        }
+        case BlobType::NATIVE_HANDLE: {
+            err = parcel->writeEmbeddedNativeHandle(
+                    static_cast<const native_handle *>(data()), parentHandle, parentOffset);
+
+            CHECK(mSubBlobs.empty());
+            break;
+        }
+        default: { err = INVALID_OPERATION; }
+    }
 
     if (err != OK) {
         return err;
     }
 
+    return writeSubBlobsToParcel(parcel, handle);
+}
+
+status_t JHwBlob::writeSubBlobsToParcel(hardware::Parcel *parcel,
+        size_t parentHandle) const {
     for (size_t i = 0; i < mSubBlobs.size(); ++i) {
         const BlobInfo &info = mSubBlobs[i];
-
-        err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);
+        status_t err = info.mBlob->writeEmbeddedToParcel(parcel, parentHandle, info.mOffset);
 
         if (err != OK) {
             return err;
@@ -252,7 +274,7 @@
     }
 }
 
-static jlong JHwBlob_native_init(JNIEnv *env) {
+static jlong JHwBlob_native_init(JNIEnv *env, jclass /*clazz*/) {
     JHwBlob::InitClass(env);
 
     return reinterpret_cast<jlong>(&releaseNativeContext);
@@ -456,6 +478,31 @@
     blob->putBlob(offset + hidl_string::kOffsetOfBuffer, subBlob);
 }
 
+static void JHwBlob_native_putNativeHandle(JNIEnv *env, jobject thiz,
+        jlong offset, jobject jHandle) {
+    std::unique_ptr<native_handle_t, int(*)(native_handle_t*)> nativeHandle(
+            JNativeHandle::MakeCppNativeHandle(env, jHandle, nullptr /* storage */),
+            native_handle_delete);
+
+    size_t size = 0;
+    if (nativeHandle != nullptr) {
+        size = sizeof(native_handle_t) + nativeHandle->numFds * sizeof(int)
+               + nativeHandle->numInts * sizeof(int);
+    }
+
+    ScopedLocalRef<jobject> subBlobObj(env, JHwBlob::NewObject(env, size));
+    sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, subBlobObj.get());
+    subBlob->specializeBlobTo(JHwBlob::BlobType::NATIVE_HANDLE);
+    subBlob->write(0 /* offset */, nativeHandle.get(), size);
+
+    hidl_handle cppHandle;
+    cppHandle.setTo(static_cast<native_handle_t *>(subBlob->data()), false /* shouldOwn */);
+
+    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+    blob->write(offset, &cppHandle, sizeof(cppHandle));
+    blob->putBlob(offset + hidl_handle::kOffsetOfNativeHandle, subBlob);
+}
+
 #define DEFINE_BLOB_ARRAY_PUTTER(Suffix,Type,NewType)                          \
 static void JHwBlob_native_put ## Suffix ## Array(                             \
         JNIEnv *env, jobject thiz, jlong offset, Type ## Array array) {        \
@@ -563,6 +610,8 @@
     { "putFloat", "(JF)V", (void *)JHwBlob_native_putFloat },
     { "putDouble", "(JD)V", (void *)JHwBlob_native_putDouble },
     { "putString", "(JLjava/lang/String;)V", (void *)JHwBlob_native_putString },
+    { "putNativeHandle", "(JL" PACKAGE_PATH "/NativeHandle;)V",
+        (void*)JHwBlob_native_putNativeHandle },
 
     { "putBoolArray", "(J[Z)V", (void *)JHwBlob_native_putBoolArray },
     { "putInt8Array", "(J[B)V", (void *)JHwBlob_native_putInt8Array },
diff --git a/core/jni/android_os_HwBlob.h b/core/jni/android_os_HwBlob.h
index 6b1db63..69a1b16 100644
--- a/core/jni/android_os_HwBlob.h
+++ b/core/jni/android_os_HwBlob.h
@@ -27,6 +27,11 @@
 namespace android {
 
 struct JHwBlob : public RefBase {
+    enum class BlobType {
+        GENERIC,
+        NATIVE_HANDLE,
+    };
+
     static void InitClass(JNIEnv *env);
 
     static sp<JHwBlob> SetNativeContext(
@@ -54,6 +59,9 @@
 
     size_t size() const;
 
+    void specializeBlobTo(BlobType type);
+    BlobType type() const;
+
     status_t putBlob(size_t offset, const sp<JHwBlob> &blob);
 
     status_t writeToParcel(hardware::Parcel *parcel) const;
@@ -74,12 +82,15 @@
 
     void *mBuffer;
     size_t mSize;
+    BlobType mType;
     bool mOwnsBuffer;
 
     size_t mHandle;
 
     Vector<BlobInfo> mSubBlobs;
 
+    status_t writeSubBlobsToParcel(hardware::Parcel *parcel, size_t parentHandle) const;
+
     DISALLOW_COPY_AND_ASSIGN(JHwBlob);
 };
 
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 061349a..7221ca1 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -22,6 +22,7 @@
 
 #include "android_os_HwBinder.h"
 #include "android_os_HwBlob.h"
+#include "android_os_NativeHandle.h"
 #include "android_os_HwRemoteBinder.h"
 
 #include <nativehelper/JNIHelp.h>
@@ -34,6 +35,7 @@
 
 using android::AndroidRuntime;
 
+using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 
@@ -436,6 +438,18 @@
     signalExceptionForError(env, err);
 }
 
+static void JHwParcel_native_writeNativeHandle(JNIEnv *env, jobject thiz, jobject valObj) {
+    sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+
+    EphemeralStorage *storage = impl->getStorage();
+    native_handle_t *handle = JNativeHandle::MakeCppNativeHandle(env, valObj, storage);
+
+    hardware::Parcel *parcel = impl->getParcel();
+    status_t err = parcel->writeNativeHandleNoDup(handle);
+
+    signalExceptionForError(env, err);
+}
+
 #define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type)                               \
 static void JHwParcel_native_write ## Suffix ## Vector(                        \
         JNIEnv *env, jobject thiz, Type ## Array valObj) {                     \
@@ -524,12 +538,96 @@
     signalExceptionForError(env, err);
 }
 
+template<typename T>
+static void WriteHidlVector(JNIEnv *env, jobject thiz, const hidl_vec<T> &vec) {
+    hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+    size_t parentHandle;
+    status_t err = parcel->writeBuffer(&vec, sizeof(vec), &parentHandle);
+
+    if (err == OK) {
+        size_t childHandle;
+        err = ::android::hardware::writeEmbeddedToParcel(
+                vec,
+                parcel,
+                parentHandle,
+                0 /* parentOffset */,
+                &childHandle);
+
+        for (size_t i = 0; (err == OK) && (i < vec.size()); ++i) {
+            err = ::android::hardware::writeEmbeddedToParcel(
+                    vec[i],
+                    parcel,
+                    childHandle,
+                    i * sizeof(T));
+        }
+    }
+
+    signalExceptionForError(env, err);
+}
+
+static void JHwParcel_native_writeStringVector(
+        JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
+    if (arrayObj == nullptr) {
+        jniThrowException(env, "java/lang/NullPointerException", nullptr);
+        return;
+    }
+
+    sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+    EphemeralStorage *storage = impl->getStorage();
+
+    void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_string>));
+    hidl_vec<hidl_string> *vec = new (vecPtr) hidl_vec<hidl_string>();
+
+    jsize len = env->GetArrayLength(arrayObj);
+    hidl_string *strings = storage->allocStringArray(len);
+    vec->setToExternal(strings, len, false /* shouldOwn */);
+
+    for (jsize i = 0; i < len; ++i) {
+        ScopedLocalRef<jstring> stringObj(env, (jstring) env->GetObjectArrayElement(arrayObj, i));
+
+        const hidl_string *s = storage->allocTemporaryString(env, stringObj.get());
+        strings[i].setToExternal(s->c_str(), s->size());
+    }
+
+    WriteHidlVector(env, thiz, *vec);
+}
+
+static void JHwParcel_native_writeNativeHandleVector(
+        JNIEnv *env, jobject thiz, jobjectArray jHandleArray) {
+    if (jHandleArray == nullptr) {
+        jniThrowException(env, "java/lang/NullPointerException", nullptr);
+        return;
+    }
+
+    sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+    EphemeralStorage *storage = impl->getStorage();
+
+    void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_handle>));
+    hidl_vec<hidl_handle> *vec = new (vecPtr) hidl_vec<hidl_handle>();
+
+    jsize len = env->GetArrayLength(jHandleArray);
+    hidl_handle *handles = static_cast<hidl_handle *>(
+            storage->allocTemporaryStorage(len * sizeof(hidl_handle)));
+
+    vec->setToExternal(handles, len, false /* shouldOwn */);
+    for (jsize i = 0; i < len; i++) {
+        ScopedLocalRef<jobject> jHandle(env, env->GetObjectArrayElement(jHandleArray, i));
+
+        native_handle_t* handle = JNativeHandle::MakeCppNativeHandle(env, jHandle.get(), storage);
+
+        new (&(handles[i])) hidl_handle();
+        handles[i].setTo(handle, false /* shouldOwn */);
+    }
+
+    WriteHidlVector(env, thiz, *vec);
+}
+
 static void JHwParcel_native_writeStrongBinder(
         JNIEnv *env, jobject thiz, jobject binderObj) {
     sp<hardware::IBinder> binder;
     if (binderObj != NULL) {
-        ScopedLocalRef<jclass> hwBinderKlass(
-                env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
+        ScopedLocalRef<jclass> hwBinderKlass(env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
 
         ScopedLocalRef<jclass> hwRemoteBinderKlass(
                 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
@@ -587,6 +685,37 @@
     return MakeStringObjFromHidlString(env, *s);
 }
 
+static jobject ReadNativeHandle(JNIEnv *env, jobject thiz, jboolean embedded,
+        jlong parentHandle, jlong offset) {
+    hardware::Parcel *parcel =
+            JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+    const native_handle_t *handle = nullptr;
+    status_t err = OK;
+
+    if (embedded) {
+        err = parcel->readNullableEmbeddedNativeHandle(parentHandle, offset, &handle);
+    } else {
+        err = parcel->readNullableNativeHandleNoDup(&handle);
+    }
+
+    if (err != OK) {
+        signalExceptionForError(env, err);
+        return nullptr;
+    }
+
+    return JNativeHandle::MakeJavaNativeHandleObj(env, handle);
+}
+
+static jobject JHwParcel_native_readNativeHandle(JNIEnv *env, jobject thiz) {
+    return ReadNativeHandle(env, thiz, false /*embedded*/, 0L /*parentHandle*/, 0L /*offset*/);
+}
+
+static jobject JHwParcel_native_readEmbeddedNativeHandle(
+        JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
+    return ReadNativeHandle(env, thiz, true /*embedded*/, parentHandle, offset);
+}
+
 #define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType)                       \
 static Type ## Array JHwParcel_native_read ## Suffix ## Vector(                \
         JNIEnv *env, jobject thiz) {                                           \
@@ -630,10 +759,8 @@
 DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
 DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
 
-static jbooleanArray JHwParcel_native_readBoolVector(
-        JNIEnv *env, jobject thiz) {
-    hardware::Parcel *parcel =
-        JHwParcel::GetNativeContext(env, thiz)->getParcel();
+static jbooleanArray JHwParcel_native_readBoolVector(JNIEnv *env, jobject thiz) {
+    hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
     size_t parentHandle;
 
@@ -692,101 +819,62 @@
     return arrayObj;
 }
 
-static jobjectArray JHwParcel_native_readStringVector(
-        JNIEnv *env, jobject thiz) {
-    typedef hidl_vec<hidl_string> string_vec;
+template<typename T>
+static const hidl_vec<T> *ReadHidlVector(JNIEnv *env, jobject thiz) {
+    const hidl_vec<T> *vec;
 
-    hardware::Parcel *parcel =
-        JHwParcel::GetNativeContext(env, thiz)->getParcel();
+    hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
     size_t parentHandle;
-
-    const string_vec *vec;
-    status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
-            reinterpret_cast<const void **>(&vec));
-
-    if (err != OK) {
-        signalExceptionForError(env, err);
-        return NULL;
-    }
-
-    size_t childHandle;
-    err = ::android::hardware::readEmbeddedFromParcel(
-            const_cast<string_vec &>(*vec),
-            *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
-
-    for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
-        err = android::hardware::readEmbeddedFromParcel(
-                    const_cast<hidl_string &>((*vec)[i]),
-                    *parcel,
-                    childHandle,
-                    i * sizeof(hidl_string) /* parentOffset */);
-    }
-
-    if (err != OK) {
-        signalExceptionForError(env, err);
-        return NULL;
-    }
-
-    return MakeStringArray(env, &(*vec)[0], vec->size());
-}
-
-static void JHwParcel_native_writeStringVector(
-        JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
-    typedef hidl_vec<hidl_string> string_vec;
-
-    if (arrayObj == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
-        return;
-    }
-
-    jsize len = env->GetArrayLength(arrayObj);
-
-    sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
-
-    void *vecPtr =
-        impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
-
-    string_vec *vec = new (vecPtr) string_vec;
-
-    hidl_string *strings = impl->getStorage()->allocStringArray(len);
-    vec->setToExternal(strings, len);
-
-    for (jsize i = 0; i < len; ++i) {
-        ScopedLocalRef<jstring> stringObj(
-                env,
-                (jstring)env->GetObjectArrayElement(arrayObj, i));
-
-        const hidl_string *s =
-            impl->getStorage()->allocTemporaryString(env, stringObj.get());
-
-        strings[i].setToExternal(s->c_str(), s->size());
-    }
-
-    hardware::Parcel *parcel = impl->getParcel();
-
-    size_t parentHandle;
-    status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
+    status_t err = parcel->readBuffer(sizeof(hidl_vec<T>),
+            &parentHandle, reinterpret_cast<const void **>(&vec));
 
     if (err == OK) {
         size_t childHandle;
-        err = ::android::hardware::writeEmbeddedToParcel(
-                *vec,
-                parcel,
-                parentHandle,
+        err = ::android::hardware::readEmbeddedFromParcel(
+                const_cast<hidl_vec<T> &>(*vec),
+                *parcel, parentHandle,
                 0 /* parentOffset */,
                 &childHandle);
 
-        for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
-            err = ::android::hardware::writeEmbeddedToParcel(
-                    (*vec)[i],
-                    parcel,
+        for (size_t i = 0; (err == OK) && (i < vec->size()); i++) {
+            err = android::hardware::readEmbeddedFromParcel(
+                    const_cast<T &>((*vec)[i]),
+                    *parcel,
                     childHandle,
-                    i * sizeof(hidl_string));
+                    i * sizeof(T) /* parentOffset */);
         }
     }
 
-    signalExceptionForError(env, err);
+    if (err != OK) {
+        signalExceptionForError(env, err);
+        return nullptr;
+    }
+
+    return vec;
+}
+
+static jobjectArray JHwParcel_native_readStringVector(
+        JNIEnv *env, jobject thiz) {
+    const hidl_vec<hidl_string> *vec = ReadHidlVector<hidl_string>(env, thiz);
+    return MakeStringArray(env, &(*vec)[0], vec->size());
+}
+
+static jobjectArray JHwParcel_native_readNativeHandleVector(
+        JNIEnv *env, jobject thiz) {
+    const hidl_vec<hidl_handle> *vec = ReadHidlVector<hidl_handle>(env, thiz);
+
+    jsize length = vec->size();
+    jobjectArray objArray = JNativeHandle::AllocJavaNativeHandleObjArray(
+            env, length);
+
+    for (jsize i = 0; i < length; i++) {
+        jobject jHandle = JNativeHandle::MakeJavaNativeHandleObj(env, (*vec)[i].getNativeHandle());
+
+        env->SetObjectArrayElement(objArray, i, jHandle);
+    }
+
+    return objArray;
 }
 
 static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
@@ -890,6 +978,9 @@
     { "writeString", "(Ljava/lang/String;)V",
         (void *)JHwParcel_native_writeString },
 
+    { "writeNativeHandle", "(L" PACKAGE_PATH "/NativeHandle;)V",
+        (void *)JHwParcel_native_writeNativeHandle },
+
     { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
     { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
     { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
@@ -903,6 +994,9 @@
     { "writeStringVector", "([Ljava/lang/String;)V",
         (void *)JHwParcel_native_writeStringVector },
 
+    { "writeNativeHandleVector", "([L" PACKAGE_PATH "/NativeHandle;)V",
+        (void *)JHwParcel_native_writeNativeHandleVector },
+
     { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
         (void *)JHwParcel_native_writeStrongBinder },
 
@@ -920,6 +1014,12 @@
     { "readString", "()Ljava/lang/String;",
         (void *)JHwParcel_native_readString },
 
+    { "readNativeHandle", "()L" PACKAGE_PATH "/NativeHandle;",
+        (void *)JHwParcel_native_readNativeHandle },
+
+    { "readEmbeddedNativeHandle", "(JJ)L" PACKAGE_PATH "/NativeHandle;",
+        (void *)JHwParcel_native_readEmbeddedNativeHandle },
+
     { "readBoolVectorAsArray", "()[Z",
         (void *)JHwParcel_native_readBoolVector },
 
@@ -944,6 +1044,9 @@
     { "readStringVectorAsArray", "()[Ljava/lang/String;",
         (void *)JHwParcel_native_readStringVector },
 
+    { "readNativeHandleAsArray", "()[L" PACKAGE_PATH "/NativeHandle;",
+        (void *)JHwParcel_native_readNativeHandleVector },
+
     { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
         (void *)JHwParcel_native_readStrongBinder },
 
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index ca5e1e4..f8f841c 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -189,8 +189,7 @@
 void HwBinderDeathRecipientList::remove(const sp<HwBinderDeathRecipient>& recipient) {
     AutoMutex _l(mLock);
 
-    List< sp<HwBinderDeathRecipient> >::iterator iter;
-    for (iter = mList.begin(); iter != mList.end(); iter++) {
+    for (auto iter = mList.begin(); iter != mList.end(); iter++) {
         if (*iter == recipient) {
             mList.erase(iter);
             return;
@@ -201,12 +200,13 @@
 sp<HwBinderDeathRecipient> HwBinderDeathRecipientList::find(jobject recipient) {
     AutoMutex _l(mLock);
 
-    for (const sp<HwBinderDeathRecipient>& deathRecipient : mList) {
-        if (deathRecipient->matches(recipient)) {
-            return deathRecipient;
+    for(auto iter = mList.rbegin(); iter != mList.rend(); iter++) {
+        if ((*iter)->matches(recipient)) {
+            return (*iter);
         }
     }
-    return NULL;
+
+    return nullptr;
 }
 
 Mutex& HwBinderDeathRecipientList::lock() {
diff --git a/core/jni/android_os_HwRemoteBinder.h b/core/jni/android_os_HwRemoteBinder.h
index 63aad0a..4b5a4c8 100644
--- a/core/jni/android_os_HwRemoteBinder.h
+++ b/core/jni/android_os_HwRemoteBinder.h
@@ -20,9 +20,9 @@
 #include <android-base/macros.h>
 #include <hwbinder/Binder.h>
 #include <jni.h>
-#include <utils/List.h>
 #include <utils/Mutex.h>
 #include <utils/RefBase.h>
+#include <vector>
 
 namespace android {
 
@@ -33,7 +33,7 @@
 class HwBinderDeathRecipient;
 
 class HwBinderDeathRecipientList : public RefBase {
-    List< sp<HwBinderDeathRecipient> > mList;
+    std::vector<sp<HwBinderDeathRecipient>> mList;
     Mutex mLock;
 
 public:
@@ -42,6 +42,8 @@
 
     void add(const sp<HwBinderDeathRecipient>& recipient);
     void remove(const sp<HwBinderDeathRecipient>& recipient);
+
+    // finds the most recently added matching death recipient
     sp<HwBinderDeathRecipient> find(jobject recipient);
 
     Mutex& lock();  // Use with care; specifically for mutual exclusion during binder death
diff --git a/core/jni/android_os_NativeHandle.cpp b/core/jni/android_os_NativeHandle.cpp
new file mode 100644
index 0000000..770fdb0
--- /dev/null
+++ b/core/jni/android_os_NativeHandle.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android_os_NativeHandle.h"
+
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+
+#include "core_jni_helpers.h"
+
+#define PACKAGE_PATH    "android/os"
+#define CLASS_NAME      "NativeHandle"
+#define CLASS_PATH      PACKAGE_PATH "/" CLASS_NAME
+
+namespace android {
+
+static struct {
+    jclass clazz;
+    jmethodID constructID;  // NativeHandle(int[] fds, int[] ints, boolean owns)
+
+    jmethodID getFdsID;  // int[] NativeHandle.getFds()
+    jmethodID getIntsID;  // int[] NativeHandle.getInts()
+} gNativeHandleFields;
+
+jobject JNativeHandle::MakeJavaNativeHandleObj(
+        JNIEnv *env, const native_handle_t *handle) {
+    if (handle == nullptr) { return nullptr; }
+
+    const int numFds = handle->numFds;
+    ScopedLocalRef<jintArray> fds(env, env->NewIntArray(numFds));
+    env->SetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0]));
+
+    const int numInts = handle->numInts;
+    ScopedLocalRef<jintArray> ints(env, env->NewIntArray(numInts));
+    env->SetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds]));
+
+    return env->NewObject(gNativeHandleFields.clazz,
+            gNativeHandleFields.constructID, fds.get(), ints.get(), false /*own*/);
+}
+
+native_handle_t *JNativeHandle::MakeCppNativeHandle(
+        JNIEnv *env, jobject jHandle, EphemeralStorage *storage) {
+    if (jHandle == nullptr) { return nullptr; }
+
+    if (!env->IsInstanceOf(jHandle, gNativeHandleFields.clazz)) {
+        jniThrowException(env, "java/lang/ClassCastException",
+                "jHandle must be an instance of NativeHandle.");
+        return nullptr;
+    }
+
+    ScopedLocalRef<jintArray> fds(env, (jintArray) env->CallObjectMethod(
+            jHandle, gNativeHandleFields.getFdsID));
+
+    ScopedLocalRef<jintArray> ints(env, (jintArray) env->CallObjectMethod(
+            jHandle, gNativeHandleFields.getIntsID));
+
+    const int numFds = (int) env->GetArrayLength(fds.get());
+    const int numInts = (int) env->GetArrayLength(ints.get());
+
+    native_handle_t *handle = (storage == nullptr)
+            ? native_handle_create(numFds, numInts)
+            : storage->allocTemporaryNativeHandle(numFds, numInts);
+
+    if (handle != nullptr) {
+        env->GetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0]));
+        env->GetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds]));
+    } else {
+        jniThrowException(env, "java/lang/OutOfMemoryError",
+                "Failed to allocate memory for native_handle_t.");
+    }
+
+    return handle;
+}
+
+jobjectArray JNativeHandle::AllocJavaNativeHandleObjArray(JNIEnv *env, jsize length) {
+    return env->NewObjectArray(length, gNativeHandleFields.clazz, nullptr);
+}
+
+int register_android_os_NativeHandle(JNIEnv *env) {
+    jclass clazz = FindClassOrDie(env, CLASS_PATH);
+    gNativeHandleFields.clazz = MakeGlobalRefOrDie(env, clazz);
+
+    gNativeHandleFields.constructID = GetMethodIDOrDie(env, clazz, "<init>", "([I[IZ)V");
+    gNativeHandleFields.getFdsID = GetMethodIDOrDie(env, clazz, "getFdsAsIntArray", "()[I");
+    gNativeHandleFields.getIntsID = GetMethodIDOrDie(env, clazz, "getInts", "()[I");
+
+    return 0;
+}
+
+}
diff --git a/core/jni/android_os_NativeHandle.h b/core/jni/android_os_NativeHandle.h
new file mode 100644
index 0000000..bbe3ebc
--- /dev/null
+++ b/core/jni/android_os_NativeHandle.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_OS_NATIVE_HANDLE_H
+#define ANDROID_OS_NATIVE_HANDLE_H
+
+#include "hwbinder/EphemeralStorage.h"
+
+#include <cutils/native_handle.h>
+#include <jni.h>
+
+namespace android {
+
+struct JNativeHandle {
+
+    /**
+     * Returns a Java NativeHandle object representing the parameterized
+     * native_handle_t instance.
+     */
+    static jobject MakeJavaNativeHandleObj(JNIEnv *env, const native_handle_t *handle);
+
+    /**
+     * Returns a heap-allocated native_handle_t instance representing the
+     * parameterized Java object. Note that if no valid EphemeralStorage*
+     * parameter is supplied (storage is nullptr), the return value must
+     * be explicitly deallocated (using native_handle_delete).
+     */
+    static native_handle_t* MakeCppNativeHandle(JNIEnv *env, jobject jHandle,
+            EphemeralStorage *storage);
+
+    /**
+     * Returns an (uninitialized) array of Java NativeHandle objects.
+     */
+    static jobjectArray AllocJavaNativeHandleObjArray(JNIEnv *env, jsize length);
+};
+
+}
+
+#endif  // ANDROID_OS_NATIVE_HANDLE_H
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 5e2cd40..7ef06dc 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -336,8 +336,13 @@
                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
                 if (a2) {
                     const void* data = parcel->readInplace(len);
-                    memcpy(a2, data, len);
+                    if (data) {
+                        memcpy(a2, data, len);
+                    }
                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
+                    if (!data) {
+                        ret = NULL;
+                    }
                 }
             }
         }
@@ -360,9 +365,14 @@
         jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)dest, 0);
         if (ar) {
             const void* data = parcel->readInplace(len);
-            memcpy(ar, data, len);
+            if (data) {
+                memcpy(ar, data, len);
+                ret = JNI_TRUE;
+            } else {
+                ret = JNI_FALSE;
+            }
+
             env->ReleasePrimitiveArrayCritical((jarray)dest, ar, 0);
-            ret = JNI_TRUE;
         }
     }
     return ret;
@@ -470,90 +480,6 @@
     return NULL;
 }
 
-static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jclass clazz,
-                                                    jstring name, jint mode)
-{
-    if (name == NULL) {
-        jniThrowNullPointerException(env, NULL);
-        return NULL;
-    }
-    ScopedUtfChars name8(env, name);
-    if (name8.c_str() == NULL) {
-        return NULL;
-    }
-
-    int flags=0;
-    switch (mode&0x30000000) {
-        case 0:
-        case 0x10000000:
-            flags = O_RDONLY;
-            break;
-        case 0x20000000:
-            flags = O_WRONLY;
-            break;
-        case 0x30000000:
-            flags = O_RDWR;
-            break;
-    }
-
-    if (mode&0x08000000) flags |= O_CREAT;
-    if (mode&0x04000000) flags |= O_TRUNC;
-    if (mode&0x02000000) flags |= O_APPEND;
-
-    int realMode = S_IRWXU|S_IRWXG;
-    if (mode&0x00000001) realMode |= S_IROTH;
-    if (mode&0x00000002) realMode |= S_IWOTH;
-
-    int fd = open(name8.c_str(), flags, realMode);
-    if (fd < 0) {
-        jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
-        return NULL;
-    }
-    jobject object = jniCreateFileDescriptor(env, fd);
-    if (object == NULL) {
-        close(fd);
-    }
-    return object;
-}
-
-static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jclass clazz, jobject orig)
-{
-    if (orig == NULL) {
-        jniThrowNullPointerException(env, NULL);
-        return NULL;
-    }
-    int origfd = jniGetFDFromFileDescriptor(env, orig);
-    if (origfd < 0) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
-        return NULL;
-    }
-
-    int fd = dup(origfd);
-    if (fd < 0) {
-        jniThrowIOException(env, errno);
-        return NULL;
-    }
-    jobject object = jniCreateFileDescriptor(env, fd);
-    if (object == NULL) {
-        close(fd);
-    }
-    return object;
-}
-
-static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
-{
-    if (object == NULL) {
-        jniThrowNullPointerException(env, NULL);
-        return;
-    }
-    int fd = jniGetFDFromFileDescriptor(env, object);
-    if (fd >= 0) {
-        jniSetFileDescriptorOfFD(env, object, -1);
-        //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
-        close(fd);
-    }
-}
-
 static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
 {
     Parcel* parcel = new Parcel();
@@ -796,10 +722,6 @@
     {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
     {"nativeReadFileDescriptor",  "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
 
-    {"openFileDescriptor",        "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
-    {"dupFileDescriptor",         "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
-    {"closeFileDescriptor",       "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
-
     {"nativeCreate",              "()J", (void*)android_os_Parcel_create},
     {"nativeFreeBuffer",          "(J)J", (void*)android_os_Parcel_freeBuffer},
     {"nativeDestroy",             "(J)V", (void*)android_os_Parcel_destroy},
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 6778b29..8cb1078 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -60,6 +60,41 @@
     return (security_getenforce() == 1) ? true : false;
 }
 
+static jstring getFdConInner(JNIEnv *env, jobject fileDescriptor, bool isSocket) {
+    if (isSELinuxDisabled) {
+        return NULL;
+    }
+
+    if (fileDescriptor == NULL) {
+        jniThrowNullPointerException(env,
+                "Trying to check security context of a null FileDescriptor.");
+        return NULL;
+    }
+
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    if (env->ExceptionCheck()) {
+        ALOGE("getFdCon => getFD for %p failed", fileDescriptor);
+        return NULL;
+    }
+
+    security_context_t tmp = NULL;
+    int ret;
+    if (isSocket) {
+        ret = getpeercon(fd, &tmp);
+    } else{
+        ret = fgetfilecon(fd, &tmp);
+    }
+    Unique_SecurityContext context(tmp);
+
+    ScopedLocalRef<jstring> contextStr(env, NULL);
+    if (ret != -1) {
+        contextStr.reset(env->NewStringUTF(context.get()));
+    }
+
+    ALOGV("getFdCon(%d) => %s", fd, context.get());
+    return contextStr.release();
+}
+
 /*
  * Function: getPeerCon
  * Purpose: retrieves security context of peer socket
@@ -69,33 +104,19 @@
  * Exceptions: NullPointerException if fileDescriptor object is NULL
  */
 static jstring getPeerCon(JNIEnv *env, jobject, jobject fileDescriptor) {
-    if (isSELinuxDisabled) {
-        return NULL;
-    }
+    return getFdConInner(env, fileDescriptor, true);
+}
 
-    if (fileDescriptor == NULL) {
-        jniThrowNullPointerException(env,
-                "Trying to check security context of a null peer socket.");
-        return NULL;
-    }
-
-    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (env->ExceptionCheck()) {
-        ALOGE("getPeerCon => getFD for %p failed", fileDescriptor);
-        return NULL;
-    }
-
-    security_context_t tmp = NULL;
-    int ret = getpeercon(fd, &tmp);
-    Unique_SecurityContext context(tmp);
-
-    ScopedLocalRef<jstring> contextStr(env, NULL);
-    if (ret != -1) {
-        contextStr.reset(env->NewStringUTF(context.get()));
-    }
-
-    ALOGV("getPeerCon(%d) => %s", fd, context.get());
-    return contextStr.release();
+/*
+ * Function: getFdCon
+ * Purpose: retrieves security context of a file descriptor.
+ * Parameters:
+ *        fileDescriptor: a FileDescriptor object
+ * Returns: jstring representing the security_context of socket or NULL if error
+ * Exceptions: NullPointerException if fileDescriptor object is NULL
+ */
+static jstring getFdCon(JNIEnv *env, jobject, jobject fileDescriptor) {
+    return getFdConInner(env, fileDescriptor, false);
 }
 
 /*
@@ -326,6 +347,7 @@
     { "getContext"               , "()Ljava/lang/String;"                         , (void*)getCon           },
     { "getFileContext"           , "(Ljava/lang/String;)Ljava/lang/String;"       , (void*)getFileCon       },
     { "getPeerContext"           , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getPeerCon       },
+    { "getFileContext"           , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getFdCon         },
     { "getPidContext"            , "(I)Ljava/lang/String;"                        , (void*)getPidCon        },
     { "isSELinuxEnforced"        , "()Z"                                          , (void*)isSELinuxEnforced},
     { "isSELinuxEnabled"         , "()Z"                                          , (void*)isSELinuxEnabled },
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index 4f4e5da..f7dab42 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -14,93 +14,80 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Trace"
-// #define LOG_NDEBUG 0
-
-#include <inttypes.h>
+#include <jni.h>
 
 #include <cutils/trace.h>
-#include <utils/String8.h>
 #include <log/log.h>
-
 #include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include <nativehelper/ScopedStringChars.h>
+
+#include <array>
 
 namespace android {
 
-static void sanitizeString(String8& utf8Chars) {
-    size_t size = utf8Chars.size();
-    char* str = utf8Chars.lockBuffer(size);
+inline static void sanitizeString(char* str, size_t size) {
     for (size_t i = 0; i < size; i++) {
         char c = str[i];
         if (c == '\0' || c == '\n' || c == '|') {
             str[i] = ' ';
         }
     }
-    utf8Chars.unlockBuffer();
 }
 
-static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv* env, jclass clazz) {
+inline static void getString(JNIEnv* env, jstring jstring, char* outBuffer, jsize maxSize) {
+    jsize size = std::min(env->GetStringLength(jstring), maxSize);
+    env->GetStringUTFRegion(jstring, 0, size, outBuffer);
+    sanitizeString(outBuffer, size);
+    outBuffer[size] = '\0';
+}
+
+template<typename F>
+inline static void withString(JNIEnv* env, jstring jstr, F callback) {
+    std::array<char, 1024> buffer;
+    getString(env, jstr, buffer.data(), buffer.size());
+    callback(buffer.data());
+}
+
+static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv*, jclass) {
     return atrace_get_enabled_tags();
 }
 
-static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass clazz,
+static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass,
         jlong tag, jstring nameStr, jint value) {
-    ScopedUtfChars name(env, nameStr);
-
-    ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, name.c_str(), value);
-    atrace_int(tag, name.c_str(), value);
+    withString(env, nameStr, [tag, value](char* str) {
+        atrace_int(tag, str, value);
+    });
 }
 
-static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass clazz,
+static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass,
         jlong tag, jstring nameStr) {
-    ScopedStringChars jchars(env, nameStr);
-    String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size());
-    sanitizeString(utf8Chars);
-
-    ALOGV("%s: %" PRId64 " %s", __FUNCTION__, tag, utf8Chars.string());
-    atrace_begin(tag, utf8Chars.string());
+    withString(env, nameStr, [tag](char* str) {
+        atrace_begin(tag, str);
+    });
 }
 
-static void android_os_Trace_nativeTraceEnd(JNIEnv* env, jclass clazz,
-        jlong tag) {
-
-    ALOGV("%s: %" PRId64, __FUNCTION__, tag);
+static void android_os_Trace_nativeTraceEnd(JNIEnv*, jclass, jlong tag) {
     atrace_end(tag);
 }
 
-static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass clazz,
+static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass,
         jlong tag, jstring nameStr, jint cookie) {
-    ScopedStringChars jchars(env, nameStr);
-    String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size());
-    sanitizeString(utf8Chars);
-
-    ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie);
-    atrace_async_begin(tag, utf8Chars.string(), cookie);
+    withString(env, nameStr, [tag, cookie](char* str) {
+        atrace_async_begin(tag, str, cookie);
+    });
 }
 
-static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass clazz,
+static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass,
         jlong tag, jstring nameStr, jint cookie) {
-    ScopedStringChars jchars(env, nameStr);
-    String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size());
-    sanitizeString(utf8Chars);
-
-    ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie);
-    atrace_async_end(tag, utf8Chars.string(), cookie);
+    withString(env, nameStr, [tag, cookie](char* str) {
+        atrace_async_end(tag, str, cookie);
+    });
 }
 
-static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv* env,
-        jclass clazz, jboolean allowed) {
-    ALOGV("%s: %d", __FUNCTION__, allowed);
-
+static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv*, jclass, jboolean allowed) {
     atrace_set_debuggable(allowed);
 }
 
-static void android_os_Trace_nativeSetTracingEnabled(JNIEnv* env,
-        jclass clazz, jboolean enabled) {
-    ALOGV("%s: %d", __FUNCTION__, enabled);
-
+static void android_os_Trace_nativeSetTracingEnabled(JNIEnv*, jclass, jboolean enabled) {
     atrace_set_tracing_enabled(enabled);
 }
 
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index e8ef349..e64d2af 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -96,7 +96,7 @@
     return toJavaStringArray(env, cStrings);
 }
 
-static jint verify(JNIEnv* env, jobjectArray packageInfo, android::vintf::DisabledChecks checks) {
+static jint verify(JNIEnv* env, jobjectArray packageInfo, android::vintf::CheckFlags::Type checks) {
     std::vector<std::string> cPackageInfo;
     if (packageInfo) {
         size_t count = env->GetArrayLength(packageInfo);
@@ -116,11 +116,11 @@
 }
 
 static jint android_os_VintfObject_verify(JNIEnv* env, jclass, jobjectArray packageInfo) {
-    return verify(env, packageInfo, ::android::vintf::ENABLE_ALL_CHECKS);
+    return verify(env, packageInfo, ::android::vintf::CheckFlags::ENABLE_ALL_CHECKS);
 }
 
 static jint android_os_VintfObject_verifyWithoutAvb(JNIEnv* env, jclass) {
-    return verify(env, nullptr, ::android::vintf::DISABLE_AVB_CHECK);
+    return verify(env, nullptr, ::android::vintf::CheckFlags::DISABLE_AVB_CHECK);
 }
 
 static jobjectArray android_os_VintfObject_getHalNamesAndVersions(JNIEnv* env, jclass) {
@@ -150,7 +150,7 @@
     }
     jobject jMap = env->NewObject(gHashMapClazz, gHashMapInit);
     for (const auto &vndk : manifest->vendorNdks()) {
-        std::string key = vndk.version();
+        const std::string& key = vndk.version();
         env->CallObjectMethod(jMap, gHashMapPut,
                 env->NewStringUTF(key.c_str()), toJavaStringArray(env, vndk.libraries()));
     }
diff --git a/core/jni/android_text_LineBreaker.cpp b/core/jni/android_text_LineBreaker.cpp
new file mode 100644
index 0000000..dac108e
--- /dev/null
+++ b/core/jni/android_text_LineBreaker.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LineBreaker"
+
+#include "unicode/locid.h"
+#include "unicode/brkiter.h"
+#include "utils/misc.h"
+#include "utils/Log.h"
+#include <nativehelper/ScopedStringChars.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/JNIHelp.h>
+#include "core_jni_helpers.h"
+#include "scoped_nullable_primitive_array.h"
+#include <cstdint>
+#include <vector>
+#include <list>
+#include <algorithm>
+
+#include "SkPaint.h"
+#include "SkTypeface.h"
+#include <hwui/MinikinSkia.h>
+#include <hwui/MinikinUtils.h>
+#include <hwui/Paint.h>
+#include <minikin/FontCollection.h>
+#include <minikin/AndroidLineBreakerHelper.h>
+#include <minikin/MinikinFont.h>
+
+namespace android {
+
+struct JLineBreaksID {
+    jfieldID breaks;
+    jfieldID widths;
+    jfieldID ascents;
+    jfieldID descents;
+    jfieldID flags;
+};
+
+static jclass gLineBreaks_class;
+static JLineBreaksID gLineBreaks_fieldID;
+
+static inline std::vector<float> jintArrayToFloatVector(JNIEnv* env, jintArray javaArray) {
+    if (javaArray == nullptr) {
+         return std::vector<float>();
+    } else {
+        ScopedIntArrayRO intArr(env, javaArray);
+        return std::vector<float>(intArr.get(), intArr.get() + intArr.size());
+    }
+}
+
+static inline minikin::android::StaticLayoutNative* toNative(jlong ptr) {
+    return reinterpret_cast<minikin::android::StaticLayoutNative*>(ptr);
+}
+
+// set text and set a number of parameters for creating a layout (width, tabstops, strategy,
+// hyphenFrequency)
+static jlong nInit(JNIEnv* env, jclass /* unused */,
+        jint breakStrategy, jint hyphenationFrequency, jboolean isJustified, jintArray indents) {
+    return reinterpret_cast<jlong>(new minikin::android::StaticLayoutNative(
+            static_cast<minikin::BreakStrategy>(breakStrategy),
+            static_cast<minikin::HyphenationFrequency>(hyphenationFrequency),
+            isJustified,
+            jintArrayToFloatVector(env, indents)));
+}
+
+static void nFinish(jlong nativePtr) {
+    delete toNative(nativePtr);
+}
+
+// CriticalNative
+static jlong nGetReleaseFunc() {
+    return reinterpret_cast<jlong>(nFinish);
+}
+
+static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks,
+                        jfloatArray recycleWidths, jfloatArray recycleAscents,
+                        jfloatArray recycleDescents, jintArray recycleFlags,
+                        jint recycleLength, const minikin::LineBreakResult& result) {
+    const size_t nBreaks = result.breakPoints.size();
+    if ((size_t)recycleLength < nBreaks) {
+        // have to reallocate buffers
+        recycleBreaks = env->NewIntArray(nBreaks);
+        recycleWidths = env->NewFloatArray(nBreaks);
+        recycleAscents = env->NewFloatArray(nBreaks);
+        recycleDescents = env->NewFloatArray(nBreaks);
+        recycleFlags = env->NewIntArray(nBreaks);
+
+        env->SetObjectField(recycle, gLineBreaks_fieldID.breaks, recycleBreaks);
+        env->SetObjectField(recycle, gLineBreaks_fieldID.widths, recycleWidths);
+        env->SetObjectField(recycle, gLineBreaks_fieldID.ascents, recycleAscents);
+        env->SetObjectField(recycle, gLineBreaks_fieldID.descents, recycleDescents);
+        env->SetObjectField(recycle, gLineBreaks_fieldID.flags, recycleFlags);
+    }
+    // copy data
+    env->SetIntArrayRegion(recycleBreaks, 0, nBreaks, result.breakPoints.data());
+    env->SetFloatArrayRegion(recycleWidths, 0, nBreaks, result.widths.data());
+    env->SetFloatArrayRegion(recycleAscents, 0, nBreaks, result.ascents.data());
+    env->SetFloatArrayRegion(recycleDescents, 0, nBreaks, result.descents.data());
+    env->SetIntArrayRegion(recycleFlags, 0, nBreaks, result.flags.data());
+}
+
+static jint nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr,
+        // Inputs
+        jcharArray javaText,
+        jlong measuredTextPtr,
+        jint length,
+        jfloat firstWidth,
+        jint firstWidthLineCount,
+        jfloat restWidth,
+        jintArray variableTabStops,
+        jint defaultTabStop,
+        jint indentsOffset,
+
+        // Outputs
+        jobject recycle,
+        jint recycleLength,
+        jintArray recycleBreaks,
+        jfloatArray recycleWidths,
+        jfloatArray recycleAscents,
+        jfloatArray recycleDescents,
+        jintArray recycleFlags,
+        jfloatArray charWidths) {
+
+    minikin::android::StaticLayoutNative* builder = toNative(nativePtr);
+
+    ScopedCharArrayRO text(env, javaText);
+    ScopedNullableIntArrayRO tabStops(env, variableTabStops);
+
+    minikin::U16StringPiece u16Text(text.get(), length);
+    minikin::MeasuredText* measuredText = reinterpret_cast<minikin::MeasuredText*>(measuredTextPtr);
+    minikin::LineBreakResult result = builder->computeBreaks(
+            u16Text, *measuredText, firstWidth, firstWidthLineCount, restWidth, indentsOffset,
+            tabStops.get(), tabStops.size(), defaultTabStop);
+
+    recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleAscents, recycleDescents,
+            recycleFlags, recycleLength, result);
+
+    return static_cast<jint>(result.breakPoints.size());
+}
+
+static const JNINativeMethod gMethods[] = {
+    // Fast Natives
+    {"nInit", "("
+        "I"  // breakStrategy
+        "I"  // hyphenationFrequency
+        "Z"  // isJustified
+        "[I"  // indents
+        ")J", (void*) nInit},
+
+    // Critical Natives
+    {"nGetReleaseFunc", "()J", (void*) nGetReleaseFunc},
+
+    // Regular JNI
+    {"nComputeLineBreaks", "("
+        "J"  // nativePtr
+
+        // Inputs
+        "[C"  // text
+        "J"  // MeasuredParagraph ptr.
+        "I"  // length
+        "F"  // firstWidth
+        "I"  // firstWidthLineCount
+        "F"  // restWidth
+        "[I"  // variableTabStops
+        "I"  // defaultTabStop
+        "I"  // indentsOffset
+
+        // Outputs
+        "Landroid/text/NativeLineBreaker$LineBreaks;"  // recycle
+        "I"  // recycleLength
+        "[I"  // recycleBreaks
+        "[F"  // recycleWidths
+        "[F"  // recycleAscents
+        "[F"  // recycleDescents
+        "[I"  // recycleFlags
+        ")I", (void*) nComputeLineBreaks}
+};
+
+int register_android_text_LineBreaker(JNIEnv* env)
+{
+    gLineBreaks_class = MakeGlobalRefOrDie(env,
+            FindClassOrDie(env, "android/text/NativeLineBreaker$LineBreaks"));
+
+    gLineBreaks_fieldID.breaks = GetFieldIDOrDie(env, gLineBreaks_class, "breaks", "[I");
+    gLineBreaks_fieldID.widths = GetFieldIDOrDie(env, gLineBreaks_class, "widths", "[F");
+    gLineBreaks_fieldID.ascents = GetFieldIDOrDie(env, gLineBreaks_class, "ascents", "[F");
+    gLineBreaks_fieldID.descents = GetFieldIDOrDie(env, gLineBreaks_class, "descents", "[F");
+    gLineBreaks_fieldID.flags = GetFieldIDOrDie(env, gLineBreaks_class, "flags", "[I");
+
+    return RegisterMethodsOrDie(env, "android/text/NativeLineBreaker",
+                                gMethods, NELEM(gMethods));
+}
+
+}
diff --git a/core/jni/android_text_MeasuredParagraph.cpp b/core/jni/android_text_MeasuredParagraph.cpp
index 41a81ac..18f509c 100644
--- a/core/jni/android_text_MeasuredParagraph.cpp
+++ b/core/jni/android_text_MeasuredParagraph.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "MeasuredParagraph"
 
 #include "GraphicsJNI.h"
-#include "ScopedIcuLocale.h"
 #include "unicode/locid.h"
 #include "unicode/brkiter.h"
 #include "utils/misc.h"
@@ -110,6 +109,10 @@
     return r;
 }
 
+static jfloat nGetCharWidthAt(jlong ptr, jint offset) {
+    return toMeasuredParagraph(ptr)->widths[offset];
+}
+
 // Regular JNI
 static void nGetBounds(JNIEnv* env, jobject, jlong ptr, jcharArray javaText, jint start, jint end,
                        jobject bounds) {
@@ -139,23 +142,29 @@
     return static_cast<jint>(toMeasuredParagraph(ptr)->getMemoryUsage());
 }
 
-static const JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMTBuilderMethods[] = {
     // MeasuredParagraphBuilder native functions.
     {"nInitBuilder", "()J", (void*) nInitBuilder},
     {"nAddStyleRun", "(JJIIZ)V", (void*) nAddStyleRun},
     {"nAddReplacementRun", "(JJIIF)V", (void*) nAddReplacementRun},
     {"nBuildNativeMeasuredParagraph", "(J[CZZ)J", (void*) nBuildNativeMeasuredParagraph},
     {"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
+};
 
+static const JNINativeMethod gMTMethods[] = {
     // MeasuredParagraph native functions.
     {"nGetWidth", "(JII)F", (void*) nGetWidth},  // Critical Natives
     {"nGetBounds", "(J[CIILandroid/graphics/Rect;)V", (void*) nGetBounds},  // Regular JNI
     {"nGetReleaseFunc", "()J", (void*) nGetReleaseFunc},  // Critical Natives
     {"nGetMemoryUsage", "(J)I", (void*) nGetMemoryUsage},  // Critical Native
+    {"nGetCharWidthAt", "(JI)F", (void*) nGetCharWidthAt},  // Critical Native
 };
 
 int register_android_text_MeasuredParagraph(JNIEnv* env) {
-    return RegisterMethodsOrDie(env, "android/text/MeasuredParagraph", gMethods, NELEM(gMethods));
+    return RegisterMethodsOrDie(env, "android/text/NativeMeasuredParagraph",
+            gMTMethods, NELEM(gMTMethods))
+        + RegisterMethodsOrDie(env, "android/text/NativeMeasuredParagraph$Builder",
+            gMTBuilderMethods, NELEM(gMTBuilderMethods));
 }
 
 }
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
deleted file mode 100644
index ad84858..0000000
--- a/core/jni/android_text_StaticLayout.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "StaticLayout"
-
-#include "ScopedIcuLocale.h"
-#include "unicode/locid.h"
-#include "unicode/brkiter.h"
-#include "utils/misc.h"
-#include "utils/Log.h"
-#include <nativehelper/ScopedStringChars.h>
-#include <nativehelper/ScopedPrimitiveArray.h>
-#include <nativehelper/JNIHelp.h>
-#include "core_jni_helpers.h"
-#include "scoped_nullable_primitive_array.h"
-#include <cstdint>
-#include <vector>
-#include <list>
-#include <algorithm>
-
-#include "SkPaint.h"
-#include "SkTypeface.h"
-#include <hwui/MinikinSkia.h>
-#include <hwui/MinikinUtils.h>
-#include <hwui/Paint.h>
-#include <minikin/FontCollection.h>
-#include <minikin/AndroidLineBreakerHelper.h>
-#include <minikin/MinikinFont.h>
-
-namespace android {
-
-struct JLineBreaksID {
-    jfieldID breaks;
-    jfieldID widths;
-    jfieldID ascents;
-    jfieldID descents;
-    jfieldID flags;
-};
-
-static jclass gLineBreaks_class;
-static JLineBreaksID gLineBreaks_fieldID;
-
-static inline std::vector<float> jintArrayToFloatVector(JNIEnv* env, jintArray javaArray) {
-    if (javaArray == nullptr) {
-         return std::vector<float>();
-    } else {
-        ScopedIntArrayRO intArr(env, javaArray);
-        return std::vector<float>(intArr.get(), intArr.get() + intArr.size());
-    }
-}
-
-static inline minikin::android::StaticLayoutNative* toNative(jlong ptr) {
-    return reinterpret_cast<minikin::android::StaticLayoutNative*>(ptr);
-}
-
-// set text and set a number of parameters for creating a layout (width, tabstops, strategy,
-// hyphenFrequency)
-static jlong nInit(JNIEnv* env, jclass /* unused */,
-        jint breakStrategy, jint hyphenationFrequency, jboolean isJustified, jintArray indents) {
-    return reinterpret_cast<jlong>(new minikin::android::StaticLayoutNative(
-            static_cast<minikin::BreakStrategy>(breakStrategy),
-            static_cast<minikin::HyphenationFrequency>(hyphenationFrequency),
-            isJustified,
-            jintArrayToFloatVector(env, indents)));
-}
-
-// CriticalNative
-static void nFinish(jlong nativePtr) {
-    delete toNative(nativePtr);
-}
-
-static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks,
-                        jfloatArray recycleWidths, jfloatArray recycleAscents,
-                        jfloatArray recycleDescents, jintArray recycleFlags,
-                        jint recycleLength, const minikin::LineBreakResult& result) {
-    const size_t nBreaks = result.breakPoints.size();
-    if ((size_t)recycleLength < nBreaks) {
-        // have to reallocate buffers
-        recycleBreaks = env->NewIntArray(nBreaks);
-        recycleWidths = env->NewFloatArray(nBreaks);
-        recycleAscents = env->NewFloatArray(nBreaks);
-        recycleDescents = env->NewFloatArray(nBreaks);
-        recycleFlags = env->NewIntArray(nBreaks);
-
-        env->SetObjectField(recycle, gLineBreaks_fieldID.breaks, recycleBreaks);
-        env->SetObjectField(recycle, gLineBreaks_fieldID.widths, recycleWidths);
-        env->SetObjectField(recycle, gLineBreaks_fieldID.ascents, recycleAscents);
-        env->SetObjectField(recycle, gLineBreaks_fieldID.descents, recycleDescents);
-        env->SetObjectField(recycle, gLineBreaks_fieldID.flags, recycleFlags);
-    }
-    // copy data
-    env->SetIntArrayRegion(recycleBreaks, 0, nBreaks, result.breakPoints.data());
-    env->SetFloatArrayRegion(recycleWidths, 0, nBreaks, result.widths.data());
-    env->SetFloatArrayRegion(recycleAscents, 0, nBreaks, result.ascents.data());
-    env->SetFloatArrayRegion(recycleDescents, 0, nBreaks, result.descents.data());
-    env->SetIntArrayRegion(recycleFlags, 0, nBreaks, result.flags.data());
-}
-
-static jint nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr,
-        // Inputs
-        jcharArray javaText,
-        jlong measuredTextPtr,
-        jint length,
-        jfloat firstWidth,
-        jint firstWidthLineCount,
-        jfloat restWidth,
-        jintArray variableTabStops,
-        jint defaultTabStop,
-        jint indentsOffset,
-
-        // Outputs
-        jobject recycle,
-        jint recycleLength,
-        jintArray recycleBreaks,
-        jfloatArray recycleWidths,
-        jfloatArray recycleAscents,
-        jfloatArray recycleDescents,
-        jintArray recycleFlags,
-        jfloatArray charWidths) {
-
-    minikin::android::StaticLayoutNative* builder = toNative(nativePtr);
-
-    ScopedCharArrayRO text(env, javaText);
-    ScopedNullableIntArrayRO tabStops(env, variableTabStops);
-
-    minikin::U16StringPiece u16Text(text.get(), length);
-    minikin::MeasuredText* measuredText = reinterpret_cast<minikin::MeasuredText*>(measuredTextPtr);
-    minikin::LineBreakResult result = builder->computeBreaks(
-            u16Text, *measuredText, firstWidth, firstWidthLineCount, restWidth, indentsOffset,
-            tabStops.get(), tabStops.size(), defaultTabStop);
-
-    recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleAscents, recycleDescents,
-            recycleFlags, recycleLength, result);
-
-    env->SetFloatArrayRegion(charWidths, 0, measuredText->widths.size(),
-                             measuredText->widths.data());
-
-    return static_cast<jint>(result.breakPoints.size());
-}
-
-static const JNINativeMethod gMethods[] = {
-    // Fast Natives
-    {"nInit", "("
-        "I"  // breakStrategy
-        "I"  // hyphenationFrequency
-        "Z"  // isJustified
-        "[I"  // indents
-        ")J", (void*) nInit},
-
-    // Critical Natives
-    {"nFinish", "(J)V", (void*) nFinish},
-
-    // Regular JNI
-    {"nComputeLineBreaks", "("
-        "J"  // nativePtr
-
-        // Inputs
-        "[C"  // text
-        "J"  // MeasuredParagraph ptr.
-        "I"  // length
-        "F"  // firstWidth
-        "I"  // firstWidthLineCount
-        "F"  // restWidth
-        "[I"  // variableTabStops
-        "I"  // defaultTabStop
-        "I"  // indentsOffset
-
-        // Outputs
-        "Landroid/text/StaticLayout$LineBreaks;"  // recycle
-        "I"  // recycleLength
-        "[I"  // recycleBreaks
-        "[F"  // recycleWidths
-        "[F"  // recycleAscents
-        "[F"  // recycleDescents
-        "[I"  // recycleFlags
-        "[F"  // charWidths
-        ")I", (void*) nComputeLineBreaks}
-};
-
-int register_android_text_StaticLayout(JNIEnv* env)
-{
-    gLineBreaks_class = MakeGlobalRefOrDie(env,
-            FindClassOrDie(env, "android/text/StaticLayout$LineBreaks"));
-
-    gLineBreaks_fieldID.breaks = GetFieldIDOrDie(env, gLineBreaks_class, "breaks", "[I");
-    gLineBreaks_fieldID.widths = GetFieldIDOrDie(env, gLineBreaks_class, "widths", "[F");
-    gLineBreaks_fieldID.ascents = GetFieldIDOrDie(env, gLineBreaks_class, "ascents", "[F");
-    gLineBreaks_fieldID.descents = GetFieldIDOrDie(env, gLineBreaks_class, "descents", "[F");
-    gLineBreaks_fieldID.flags = GetFieldIDOrDie(env, gLineBreaks_class, "flags", "[I");
-
-    return RegisterMethodsOrDie(env, "android/text/StaticLayout", gMethods, NELEM(gMethods));
-}
-
-}
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index fa9f445..830ca83 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -179,6 +179,10 @@
         argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
       }
 
+      if (stat(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR, &st) == 0) {
+        argv[argc++] = AssetManager::PRODUCT_SERVICES_OVERLAY_DIR;
+      }
+
       // Finally, invoke idmap (if any overlay directory exists)
       if (argc > 5) {
         execv(AssetManager::IDMAP_BIN, (char* const*)argv);
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index c3ba9ba..ecad6c0 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -108,7 +108,6 @@
     jclass mClass;
     jmethodID mGetInstance;
     jmethodID mSendDeathNotice;
-    jmethodID mDumpProxyDebugInfo;
 
     // Object state.
     jfieldID mNativeData;  // Field holds native pointer to BinderProxyNativeData.
@@ -155,9 +154,8 @@
 static constexpr int32_t PROXY_WARN_INTERVAL = 5000;
 static constexpr uint32_t GC_INTERVAL = 1000;
 
-// Protected by gProxyLock. We warn if this gets too large.
-static int32_t gNumProxies = 0;
-static int32_t gProxiesWarned = 0;
+static std::atomic<uint32_t> gNumProxies(0);
+static std::atomic<uint32_t> gProxiesWarned(0);
 
 // Number of GlobalRefs held by JavaBBinders.
 static std::atomic<uint32_t> gNumLocalRefsCreated(0);
@@ -632,12 +630,6 @@
     return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData);
 }
 
-static Mutex gProxyLock;
-
-// We may cache a single BinderProxyNativeData node to avoid repeat allocation.
-// All fields are null. Protected by gProxyLock.
-static BinderProxyNativeData *gNativeDataCache;
-
 // If the argument is a JavaBBinder, return the Java object that was used to create it.
 // Otherwise return a BinderProxy for the IBinder. If a previous call was passed the
 // same IBinder, and the original BinderProxy is still alive, return the same BinderProxy.
@@ -652,36 +644,31 @@
         return object;
     }
 
-    // For the rest of the function we will hold this lock, to serialize
-    // looking/creation/destruction of Java proxies for native Binder proxies.
-    AutoMutex _l(gProxyLock);
+    BinderProxyNativeData* nativeData = new BinderProxyNativeData();
+    nativeData->mOrgue = new DeathRecipientList;
+    nativeData->mObject = val;
 
-    BinderProxyNativeData* nativeData = gNativeDataCache;
-    if (nativeData == nullptr) {
-        nativeData = new BinderProxyNativeData();
-    }
-    // gNativeDataCache is now logically empty.
     jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
             gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
     if (env->ExceptionCheck()) {
         // In the exception case, getInstance still took ownership of nativeData.
-        gNativeDataCache = nullptr;
         return NULL;
     }
     BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
     if (actualNativeData == nativeData) {
-        // New BinderProxy; we still have exclusive access.
-        nativeData->mOrgue = new DeathRecipientList;
-        nativeData->mObject = val;
-        gNativeDataCache = nullptr;
-        ++gNumProxies;
-        if (gNumProxies >= gProxiesWarned + PROXY_WARN_INTERVAL) {
-            ALOGW("Unexpectedly many live BinderProxies: %d\n", gNumProxies);
-            gProxiesWarned = gNumProxies;
+        // Created a new Proxy
+        uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed);
+        uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed);
+        if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) {
+            // Multiple threads can get here, make sure only one of them gets to
+            // update the warn counter.
+            if (gProxiesWarned.compare_exchange_strong(numLastWarned,
+                        numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) {
+                ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies);
+            }
         }
     } else {
-        // nativeData wasn't used. Reuse it the next time.
-        gNativeDataCache = nativeData;
+        delete nativeData;
     }
 
     return object;
@@ -959,8 +946,7 @@
 
 jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz)
 {
-    AutoMutex _l(gProxyLock);
-    return gNumProxies;
+    return gNumProxies.load();
 }
 
 jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz)
@@ -1007,18 +993,6 @@
 static void android_os_BinderInternal_proxyLimitcallback(int uid)
 {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    {
-        // Calls into BinderProxy must be serialized
-        AutoMutex _l(gProxyLock);
-        env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
-                                    gBinderProxyOffsets.mDumpProxyDebugInfo);
-    }
-    if (env->ExceptionCheck()) {
-        ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
-        report_exception(env, excep.get(),
-            "*** Uncaught exception in dumpProxyDebugInfo");
-    }
-
     env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
                               gBinderInternalOffsets.mProxyLimitCallback,
                               uid);
@@ -1367,9 +1341,6 @@
 
 static void BinderProxy_destroy(void* rawNativeData)
 {
-    // Don't race with construction/initialization
-    AutoMutex _l(gProxyLock);
-
     BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData;
     LOGDEATH("Destroying BinderProxy: binder=%p drl=%p\n",
             nativeData->mObject.get(), nativeData->mOrgue.get());
@@ -1408,8 +1379,6 @@
             "(JJ)Landroid/os/BinderProxy;");
     gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
             "(Landroid/os/IBinder$DeathRecipient;)V");
-    gBinderProxyOffsets.mDumpProxyDebugInfo = GetStaticMethodIDOrDie(env, clazz, "dumpProxyDebugInfo",
-            "()V");
     gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
 
     clazz = FindClassOrDie(env, "java/lang/Class");
diff --git a/core/jni/android_util_MemoryIntArray.cpp b/core/jni/android_util_MemoryIntArray.cpp
index 2dfbe3e..b68f9ec 100644
--- a/core/jni/android_util_MemoryIntArray.cpp
+++ b/core/jni/android_util_MemoryIntArray.cpp
@@ -142,8 +142,6 @@
         jniThrowException(env, "java/io/IOException", "ashmem unpinning failed");
         return;
     }
-
-    close(fd);
 }
 
 static jint android_util_MemoryIntArray_get(JNIEnv* env, jobject clazz,
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 095252c..10da892 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -114,8 +114,8 @@
 
     uint32_t publishedSeq = mNextPublishedSeq++;
     status_t status = mInputPublisher.publishKeyEvent(publishedSeq,
-            event->getDeviceId(), event->getSource(), event->getAction(), event->getFlags(),
-            event->getKeyCode(), event->getScanCode(), event->getMetaState(),
+            event->getDeviceId(), event->getSource(), event->getDisplayId(), event->getAction(),
+            event->getFlags(), event->getKeyCode(), event->getScanCode(), event->getMetaState(),
             event->getRepeatCount(), event->getDownTime(), event->getEventTime());
     if (status) {
         ALOGW("Failed to send key event on channel '%s'.  status=%d",
@@ -135,8 +135,7 @@
     for (size_t i = 0; i <= event->getHistorySize(); i++) {
         publishedSeq = mNextPublishedSeq++;
         status_t status = mInputPublisher.publishMotionEvent(publishedSeq,
-                event->getDeviceId(), event->getSource(),
-                event->getDisplayId(),
+                event->getDeviceId(), event->getSource(), event->getDisplayId(),
                 event->getAction(), event->getActionButton(), event->getFlags(),
                 event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
                 event->getXOffset(), event->getYOffset(),
diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp
index 8a6e745..f010772 100644
--- a/core/jni/android_view_KeyEvent.cpp
+++ b/core/jni/android_view_KeyEvent.cpp
@@ -39,6 +39,7 @@
 
     jfieldID mDeviceId;
     jfieldID mSource;
+    jfieldID mDisplayId;
     jfieldID mMetaState;
     jfieldID mAction;
     jfieldID mKeyCode;
@@ -65,6 +66,7 @@
             event->getScanCode(),
             event->getFlags(),
             event->getSource(),
+            event->getDisplayId(),
             NULL);
     if (env->ExceptionCheck()) {
         ALOGE("An exception occurred while obtaining a key event.");
@@ -79,6 +81,7 @@
         KeyEvent* event) {
     jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
     jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
+    jint displayId = env->GetIntField(eventObj, gKeyEventClassInfo.mDisplayId);
     jint metaState = env->GetIntField(eventObj, gKeyEventClassInfo.mMetaState);
     jint action = env->GetIntField(eventObj, gKeyEventClassInfo.mAction);
     jint keyCode = env->GetIntField(eventObj, gKeyEventClassInfo.mKeyCode);
@@ -88,7 +91,8 @@
     jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
     jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
 
-    event->initialize(deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
+    event->initialize(deviceId, source, displayId, action, flags, keyCode, scanCode, metaState,
+            repeatCount,
             milliseconds_to_nanoseconds(downTime),
             milliseconds_to_nanoseconds(eventTime));
     return OK;
@@ -131,12 +135,14 @@
     gKeyEventClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
 
     gKeyEventClassInfo.obtain = GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz,
-            "obtain", "(JJIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
+            "obtain", "(JJIIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
     gKeyEventClassInfo.recycle = GetMethodIDOrDie(env, gKeyEventClassInfo.clazz,
             "recycle", "()V");
 
     gKeyEventClassInfo.mDeviceId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDeviceId", "I");
     gKeyEventClassInfo.mSource = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mSource", "I");
+    gKeyEventClassInfo.mDisplayId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDisplayId",
+                                                    "I");
     gKeyEventClassInfo.mMetaState = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mMetaState",
                                                     "I");
     gKeyEventClassInfo.mAction = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mAction", "I");
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 22bbc3c..46b19bd 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -222,6 +222,11 @@
             RenderNode::GENERIC);
 }
 
+static void android_view_RenderNode_setUsageHint(jlong renderNodePtr, jint usageHint) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->setUsageHint(static_cast<UsageHint>(usageHint));
+}
+
 static jboolean android_view_RenderNode_setElevation(jlong renderNodePtr, float elevation) {
     return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z);
 }
@@ -614,6 +619,7 @@
     { "nSetAlpha",             "(JF)Z",  (void*) android_view_RenderNode_setAlpha },
     { "nSetHasOverlappingRendering", "(JZ)Z",
             (void*) android_view_RenderNode_setHasOverlappingRendering },
+    { "nSetUsageHint",    "(JI)V", (void*) android_view_RenderNode_setUsageHint },
     { "nSetElevation",         "(JF)Z",  (void*) android_view_RenderNode_setElevation },
     { "nSetTranslationX",      "(JF)Z",  (void*) android_view_RenderNode_setTranslationX },
     { "nSetTranslationY",      "(JF)Z",  (void*) android_view_RenderNode_setTranslationY },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index f70cf07..f512ce4 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -332,8 +332,7 @@
     SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
                                          convertPixelFormat(outBuffer.format),
                                          outBuffer.format == PIXEL_FORMAT_RGBX_8888
-                                                 ? kOpaque_SkAlphaType : kPremul_SkAlphaType,
-                                         GraphicsJNI::defaultColorSpace());
+                                                 ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
 
     SkBitmap bitmap;
     ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 5b4b5f2..02d6adb 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -446,7 +446,7 @@
 
     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
     Rect crop(l, t, r, b);
-    transaction->setCrop(ctrl, crop);
+    transaction->setCrop_legacy(ctrl, crop);
 }
 
 static void nativeSetFinalCrop(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -456,7 +456,7 @@
 
     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
     Rect crop(l, t, r, b);
-    transaction->setFinalCrop(ctrl, crop);
+    transaction->setFinalCrop_legacy(ctrl, crop);
 }
 
 static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -799,7 +799,7 @@
 
     {
         auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
-        transaction->deferTransactionUntil(ctrl, handle, frameNumber);
+        transaction->deferTransactionUntil_legacy(ctrl, handle, frameNumber);
     }
 }
 
@@ -811,7 +811,7 @@
     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
     sp<Surface> barrier = reinterpret_cast<Surface *>(surfaceObject);
 
-    transaction->deferTransactionUntil(ctrl, barrier, frameNumber);
+    transaction->deferTransactionUntil_legacy(ctrl, barrier, frameNumber);
 }
 
 static void nativeReparentChildren(JNIEnv* env, jclass clazz, jlong transactionObj,
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 2921b37..15319ad 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -94,8 +94,7 @@
         default:
             break;
     }
-    return SkImageInfo::Make(buffer.width, buffer.height, colorType, alphaType,
-            GraphicsJNI::defaultColorSpace());
+    return SkImageInfo::Make(buffer.width, buffer.height, colorType, alphaType);
 }
 
 /**
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 497b289..4a17742 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -1054,6 +1054,13 @@
     Properties::contextPriority = contextPriority;
 }
 
+static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jobject jsurface) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
+    proxy->allocateBuffers(surface);
+}
+
 // ----------------------------------------------------------------------------
 // FrameMetricsObserver
 // ----------------------------------------------------------------------------
@@ -1166,6 +1173,7 @@
     { "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
     { "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
     { "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
+    { "nAllocateBuffers", "(JLandroid/view/Surface;)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
 };
 
 static JavaVM* mJvm = nullptr;
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index cc2646c..dc04269 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -27,6 +27,7 @@
 
 #include <zlib.h>
 
+#include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
@@ -567,7 +568,14 @@
         return 0;
     }
 
-    ZipFileRO* zipFile = ZipFileRO::openFd(fd, debugFilePath.c_str());
+    int dupedFd = dup(fd);
+    if (dupedFd == -1) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                             "Failed to dup FileDescriptor: %s", strerror(errno));
+        return 0;
+    }
+
+    ZipFileRO* zipFile = ZipFileRO::openFd(dupedFd, debugFilePath.c_str());
 
     return reinterpret_cast<jlong>(zipFile);
 }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index caf4e4b4..364393e 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -24,6 +24,7 @@
 #include <sstream>
 #include <string>
 
+#include <android/fdsan.h>
 #include <fcntl.h>
 #include <grp.h>
 #include <inttypes.h>
@@ -45,6 +46,7 @@
 #include <unistd.h>
 
 #include "android-base/logging.h"
+#include <android-base/properties.h>
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
 #include <cutils/fs.h>
@@ -68,14 +70,17 @@
 namespace {
 
 using android::String8;
+using android::base::StringAppendF;
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
+using android::base::GetBoolProperty;
 
 #define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
                               append(StringPrintf(__VA_ARGS__))
 
 static pid_t gSystemServerPid = 0;
 
+static const char kIsolatedStorage[] = "persist.sys.isolated_storage";
 static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
 static jclass gZygoteClass;
 static jmethodID gCallPostForkChildHooks;
@@ -88,6 +93,7 @@
   MOUNT_EXTERNAL_DEFAULT = 1,
   MOUNT_EXTERNAL_READ = 2,
   MOUNT_EXTERNAL_WRITE = 3,
+  MOUNT_EXTERNAL_FULL = 4,
 };
 
 static void RuntimeAbort(JNIEnv* env, int line, const char* msg) {
@@ -376,10 +382,32 @@
     return 0;
 }
 
+static bool createPkgSandbox(uid_t uid, const char* package_name, std::string& pkg_sandbox_dir,
+        std::string* error_msg) {
+    // Create /mnt/user/0/package/<package-name>
+    userid_t user_id = multiuser_get_user_id(uid);
+    StringAppendF(&pkg_sandbox_dir, "/%d", user_id);
+    if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0751, AID_ROOT, AID_ROOT) != 0) {
+        *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str());
+        return false;
+    }
+    StringAppendF(&pkg_sandbox_dir, "/package");
+    if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
+        *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str());
+        return false;
+    }
+    StringAppendF(&pkg_sandbox_dir, "/%s", package_name);
+    if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0755, uid, uid) != 0) {
+        *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str());
+        return false;
+    }
+    return true;
+}
+
 // Create a private mount namespace and bind mount appropriate emulated
 // storage for the given user.
 static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
-        bool force_mount_namespace, std::string* error_msg) {
+        bool force_mount_namespace, std::string* error_msg, const char* package_name) {
     // See storage config details at http://source.android.com/tech/storage/
 
     String8 storageSource;
@@ -389,7 +417,7 @@
         storageSource = "/mnt/runtime/read";
     } else if (mount_mode == MOUNT_EXTERNAL_WRITE) {
         storageSource = "/mnt/runtime/write";
-    } else if (!force_mount_namespace) {
+    } else if (mount_mode != MOUNT_EXTERNAL_FULL && !force_mount_namespace) {
         // Sane default of no storage visible
         return true;
     }
@@ -405,27 +433,69 @@
         return true;
     }
 
-    if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
-            NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
-        *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
-                                  storageSource.string(),
-                                  strerror(errno));
-        return false;
-    }
+    if (GetBoolProperty(kIsolatedStorage, false)) {
+        if (mount_mode == MOUNT_EXTERNAL_FULL) {
+            storageSource = "/mnt/runtime/write";
+            if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
+                    NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
+                *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
+                                          storageSource.string(),
+                                          strerror(errno));
+                return false;
+            }
 
-    // Mount user-specific symlink helper into place
-    userid_t user_id = multiuser_get_user_id(uid);
-    const String8 userSource(String8::format("/mnt/user/%d", user_id));
-    if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
-        *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", userSource.string());
-        return false;
-    }
-    if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
-            NULL, MS_BIND, NULL)) == -1) {
-        *error_msg = CREATE_ERROR("Failed to mount %s to /storage/self: %s",
-                                  userSource.string(),
-                                  strerror(errno));
-        return false;
+            // Mount user-specific symlink helper into place
+            userid_t user_id = multiuser_get_user_id(uid);
+            const String8 userSource(String8::format("/mnt/user/%d", user_id));
+            if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
+                *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", userSource.string());
+                return false;
+            }
+            if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
+                    NULL, MS_BIND, NULL)) == -1) {
+                *error_msg = CREATE_ERROR("Failed to mount %s to /storage/self: %s",
+                                          userSource.string(),
+                                          strerror(errno));
+                return false;
+            }
+        } else {
+            if (package_name == nullptr) {
+                return true;
+            }
+            std::string pkgSandboxDir("/mnt/user");
+            if (!createPkgSandbox(uid, package_name, pkgSandboxDir, error_msg)) {
+                return false;
+            }
+            if (TEMP_FAILURE_RETRY(mount(pkgSandboxDir.c_str(), "/storage",
+                    nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
+                *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
+                        pkgSandboxDir.c_str(), strerror(errno));
+                return false;
+            }
+        }
+    } else {
+        if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
+                NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
+            *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
+                                      storageSource.string(),
+                                      strerror(errno));
+            return false;
+        }
+
+        // Mount user-specific symlink helper into place
+        userid_t user_id = multiuser_get_user_id(uid);
+        const String8 userSource(String8::format("/mnt/user/%d", user_id));
+        if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
+            *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", userSource.string());
+            return false;
+        }
+        if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
+                NULL, MS_BIND, NULL)) == -1) {
+            *error_msg = CREATE_ERROR("Failed to mount %s to /storage/self: %s",
+                                      userSource.string(),
+                                      strerror(errno));
+            return false;
+        }
     }
 
     return true;
@@ -541,7 +611,7 @@
                              jlong permittedCapabilities, jlong effectiveCapabilities,
                              jint mount_external, jstring java_se_info, jstring java_se_name,
                              bool is_system_server, bool is_child_zygote, jstring instructionSet,
-                             jstring dataDir) {
+                             jstring dataDir, jstring packageName) {
   std::string error_msg;
 
   auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
@@ -591,7 +661,18 @@
     ALOGW("Native bridge will not be used because dataDir == NULL.");
   }
 
-  if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg)) {
+  ScopedUtfChars* package_name = nullptr;
+  const char* package_name_c_str = nullptr;
+  if (packageName != nullptr) {
+    package_name = new ScopedUtfChars(env, packageName);
+    package_name_c_str = package_name->c_str();
+  } else if (is_system_server) {
+    package_name_c_str = "android";
+  }
+  bool success = MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg,
+      package_name_c_str);
+  delete package_name;
+  if (!success) {
     ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno));
     if (errno == ENOTCONN || errno == EROFS) {
       // When device is actively encrypting, we get ENOTCONN here
@@ -791,6 +872,8 @@
     fail_fn(error_msg);
   }
 
+  android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level();
+
   pid_t pid = fork();
 
   if (pid == 0) {
@@ -807,6 +890,9 @@
     if (!gOpenFdTable->ReopenOrDetach(&error_msg)) {
       fail_fn(error_msg);
     }
+
+    // Turn fdsan back on.
+    android_fdsan_set_error_level(fdsan_error_level);
   }
 
   // We blocked SIGCHLD prior to a fork, we unblock it here.
@@ -850,7 +936,7 @@
         jint runtime_flags, jobjectArray rlimits,
         jint mount_external, jstring se_info, jstring se_name,
         jintArray fdsToClose, jintArray fdsToIgnore, jboolean is_child_zygote,
-        jstring instructionSet, jstring appDataDir) {
+        jstring instructionSet, jstring appDataDir, jstring packageName) {
     jlong capabilities = 0;
 
     // Grant CAP_WAKE_ALARM to the Bluetooth process.
@@ -903,7 +989,7 @@
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                        capabilities, capabilities,
                        mount_external, se_info, se_name, false,
-                       is_child_zygote == JNI_TRUE, instructionSet, appDataDir);
+                       is_child_zygote == JNI_TRUE, instructionSet, appDataDir, packageName);
     }
     return pid;
 }
@@ -917,7 +1003,7 @@
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                        permittedCapabilities, effectiveCapabilities,
                        MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true,
-                       false, NULL, NULL);
+                       false, NULL, NULL, nullptr);
   } else if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -931,12 +1017,16 @@
           RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
       }
 
-      // Assign system_server to the correct memory cgroup.
-      // Not all devices mount /dev/memcg so check for the file first
-      // to avoid unnecessarily printing errors and denials in the logs.
-      if (!access("/dev/memcg/system/tasks", F_OK) &&
+      bool low_ram_device = GetBoolProperty("ro.config.low_ram", false);
+      bool per_app_memcg = GetBoolProperty("ro.config.per_app_memcg", low_ram_device);
+      if (per_app_memcg) {
+          // Assign system_server to the correct memory cgroup.
+          // Not all devices mount /dev/memcg so check for the file first
+          // to avoid unnecessarily printing errors and denials in the logs.
+          if (!access("/dev/memcg/system/tasks", F_OK) &&
                 !WriteStringToFile(StringPrintf("%d", pid), "/dev/memcg/system/tasks")) {
-        ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid);
+              ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid);
+          }
       }
   }
   return pid;
@@ -994,7 +1084,7 @@
     { "nativeSecurityInit", "()V",
       (void *) com_android_internal_os_Zygote_nativeSecurityInit },
     { "nativeForkAndSpecialize",
-      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
+      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index c5904e0..f56f7ec 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -87,13 +87,17 @@
   static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
   static const char* kSystemProductOverlayDir = "/system/product/overlay/";
   static const char* kProductOverlayDir = "/product/overlay";
+  static const char* kSystemProductServicesOverlayDir = "/system/product_services/overlay/";
+  static const char* kProductServicesOverlayDir = "/product_services/overlay";
   static const char* kApkSuffix = ".apk";
 
   if ((android::base::StartsWith(path, kOverlayDir)
        || android::base::StartsWith(path, kOverlaySubdir)
        || android::base::StartsWith(path, kVendorOverlayDir)
        || android::base::StartsWith(path, kSystemProductOverlayDir)
-       || android::base::StartsWith(path, kProductOverlayDir))
+       || android::base::StartsWith(path, kProductOverlayDir)
+       || android::base::StartsWith(path, kSystemProductServicesOverlayDir)
+       || android::base::StartsWith(path, kProductServicesOverlayDir))
       && android::base::EndsWith(path, kApkSuffix)
       && path.find("/../") == std::string::npos) {
     return true;
diff --git a/core/jni/hwbinder/EphemeralStorage.cpp b/core/jni/hwbinder/EphemeralStorage.cpp
index 3b18f2b..95bb42e 100644
--- a/core/jni/hwbinder/EphemeralStorage.cpp
+++ b/core/jni/hwbinder/EphemeralStorage.cpp
@@ -71,6 +71,17 @@
     return s;
 }
 
+native_handle_t *EphemeralStorage::allocTemporaryNativeHandle(
+        int numFds, int numInts) {
+    Item item;
+    item.mType = TYPE_NATIVE_HANDLE;
+    item.mObj = nullptr;
+    item.mPtr = native_handle_create(numFds, numInts);
+    mItems.push_back(item);
+
+    return static_cast<native_handle_t*>(item.mPtr);
+}
+
 #define DEFINE_ALLOC_VECTOR_METHODS(Suffix,Type,NewType)                       \
 const hidl_vec<Type> *EphemeralStorage::allocTemporary ## Suffix ## Vector(    \
         JNIEnv *env, Type ## Array arrayObj) {                                 \
@@ -145,6 +156,13 @@
             DEFINE_RELEASE_ARRAY_CASE(Float,jfloat,Float)
             DEFINE_RELEASE_ARRAY_CASE(Double,jdouble,Double)
 
+            case TYPE_NATIVE_HANDLE:
+            {
+                int err = native_handle_delete(static_cast<native_handle_t *>(item.mPtr));
+                CHECK(err == 0);
+                break;
+            }
+
             default:
                 CHECK(!"Should not be here");
         }
diff --git a/core/jni/hwbinder/EphemeralStorage.h b/core/jni/hwbinder/EphemeralStorage.h
index f07c782..55ef741 100644
--- a/core/jni/hwbinder/EphemeralStorage.h
+++ b/core/jni/hwbinder/EphemeralStorage.h
@@ -43,6 +43,8 @@
     const ::android::hardware::hidl_string *allocTemporaryString(
             JNIEnv *env, jstring stringObj);
 
+    native_handle_t *allocTemporaryNativeHandle(int numFds, int numInts);
+
     DECLARE_ALLOC_METHODS(Int8,jbyte)
     DECLARE_ALLOC_METHODS(Int16,jshort)
     DECLARE_ALLOC_METHODS(Int32,jint)
@@ -61,6 +63,7 @@
         TYPE_Int64_ARRAY,
         TYPE_Float_ARRAY,
         TYPE_Double_ARRAY,
+        TYPE_NATIVE_HANDLE,
     };
 
     struct Item {
diff --git a/core/proto/android/app/alarmmanager.proto b/core/proto/android/app/alarmmanager.proto
index 53be1ee..58df922 100644
--- a/core/proto/android/app/alarmmanager.proto
+++ b/core/proto/android/app/alarmmanager.proto
@@ -53,5 +53,5 @@
     // This value is UTC wall clock time in milliseconds, as returned by
     // System#currentTimeMillis() for example.
     optional int64 trigger_time_ms = 1;
-    optional android.app.PendingIntentProto show_intent = 2;
+    optional PendingIntentProto show_intent = 2;
 }
diff --git a/core/proto/android/app/notification.proto b/core/proto/android/app/notification.proto
index c7e313a..a6f13d7 100644
--- a/core/proto/android/app/notification.proto
+++ b/core/proto/android/app/notification.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.app";
 option java_multiple_files = true;
 
 package android.app;
diff --git a/core/proto/android/app/notification_channel.proto b/core/proto/android/app/notification_channel.proto
index d3808e8..75cc18b 100644
--- a/core/proto/android/app/notification_channel.proto
+++ b/core/proto/android/app/notification_channel.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.app";
 option java_multiple_files = true;
 
 package android.app;
@@ -29,8 +28,11 @@
 message NotificationChannelProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // Notification Channel ID. Provided by the app.
     optional string id = 1 [ (android.privacy).dest = DEST_EXPLICIT ];
+    // User-visible Notification Channel name. Provided by the app.
     optional string name = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
+    // User-visible Notification Channel description. Provided by the app.
     optional string description = 3 [ (android.privacy).dest = DEST_EXPLICIT ];
     optional int32 importance = 4;
     optional bool can_bypass_dnd = 5;
@@ -49,6 +51,7 @@
     optional bool show_badge = 13;
     // Default is false.
     optional bool is_deleted = 14;
+    // Provided by the app but will match a NotificationChannelGroup id.
     optional string group = 15 [ (android.privacy).dest = DEST_EXPLICIT ];
     optional android.media.AudioAttributesProto audio_attributes = 16;
     // If this is a blockable system notification channel.
diff --git a/core/proto/android/app/notification_channel_group.proto b/core/proto/android/app/notification_channel_group.proto
index 7b270d7..4fb27b0 100644
--- a/core/proto/android/app/notification_channel_group.proto
+++ b/core/proto/android/app/notification_channel_group.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.app";
 option java_multiple_files = true;
 
 package android.app;
@@ -29,9 +28,12 @@
 message NotificationChannelGroupProto {
     option (.android.msg_privacy).dest = DEST_EXPLICIT;
 
+    // Notification Channel Group ID. Provided by the app.
     optional string id = 1;
+    // User-visible Notification Channel Group name.
     optional string name = 2;
+    // User-visible Notification Channel Group description.
     optional string description = 3;
     optional bool is_blocked = 4;
-    repeated android.app.NotificationChannelProto channels = 5;
+    repeated NotificationChannelProto channels = 5;
 }
diff --git a/core/proto/android/app/notificationmanager.proto b/core/proto/android/app/notificationmanager.proto
index e991688..27204cc 100644
--- a/core/proto/android/app/notificationmanager.proto
+++ b/core/proto/android/app/notificationmanager.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.app";
 option java_multiple_files = true;
 
 package android.app;
@@ -42,9 +41,10 @@
         REPEAT_CALLERS = 5;
         // Alarms are prioritized.
         ALARMS = 6;
-        // Media, system, game (catch-all for non-never suppressible sounds) are
-        // prioritized.
-        MEDIA_SYSTEM_OTHER = 7;
+        // Media, game, voice navigation are prioritized.
+        MEDIA = 7;
+        // System (catch-all for non-never suppressible sounds) are prioritized.
+        SYSTEM = 8;
     }
     repeated Category priority_categories = 1;
 
@@ -64,10 +64,32 @@
         // Whether notifications suppressed by DND should not interrupt visually
         // (e.g. with notification lights or by turning the screen on) when the
         // screen is off.
-        SCREEN_OFF = 1;
+        // FULL_SCREEN_INTENT, AMBIENT, and LIGHTS should be used instead.
+        SCREEN_OFF = 1 [deprecated = true];
         // Whether notifications suppressed by DND should not interrupt visually
         // when the screen is on (e.g. by peeking onto the screen).
-        SCREEN_ON = 2;
+        // PEEK should be used instead of ON.
+        SCREEN_ON = 2 [deprecated = true];
+        // Whether full screen intents} from notifications intercepted by DND
+        // are blocked.
+        FULL_SCREEN_INTENT = 3;
+        // Whether lights from notifications intercepted by DND are blocked.
+        LIGHTS = 4;
+        // Whether notifications intercepted by DND are prevented from peeking.
+        PEEK = 5;
+        // Whether notifications intercepted by DND are prevented from
+        // appearing in the status bar, on devices that support status bars.
+        STATUS_BAR = 6;
+        // Whether badges from notifications intercepted by DND are blocked on
+        // devices that support badging.
+        BADGE = 7;
+        // Whether notification intercepted by DND are prevented from appearing
+        // on ambient displays on devices that support ambient display.
+        AMBIENT = 8;
+        // Whether notification intercepted by DND are prevented from appearing
+        // in notification list views like the notification shade or lockscreen
+        // on devices that support those views.
+        NOTIFICATION_LIST = 9;
     }
     repeated SuppressedVisualEffect suppressed_visual_effects = 4;
 }
diff --git a/core/proto/android/app/profilerinfo.proto b/core/proto/android/app/profilerinfo.proto
index 6b28318..20fa3ad 100644
--- a/core/proto/android/app/profilerinfo.proto
+++ b/core/proto/android/app/profilerinfo.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.app";
 option java_multiple_files = true;
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
@@ -28,10 +27,12 @@
 message ProfilerInfoProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // Name of profile output file.
     optional string profile_file = 1;
     optional int32 profile_fd = 2;
     optional int32 sampling_interval = 3;
     optional bool auto_stop_profiler = 4;
     optional bool streaming_output = 5;
+    // Denotes an agent (and its parameters) to attach for profiling.
     optional string agent = 6;
 }
diff --git a/core/proto/android/app/window_configuration.proto b/core/proto/android/app/window_configuration.proto
index c9f3986..2d15552 100644
--- a/core/proto/android/app/window_configuration.proto
+++ b/core/proto/android/app/window_configuration.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.app";
 option java_multiple_files = true;
 
 package android.app;
diff --git a/core/proto/android/content/clipdata.proto b/core/proto/android/content/clipdata.proto
index cbc00a7..4f1c308 100644
--- a/core/proto/android/content/clipdata.proto
+++ b/core/proto/android/content/clipdata.proto
@@ -27,7 +27,7 @@
 message ClipDataProto {
     option (.android.msg_privacy).dest = DEST_LOCAL;
 
-    optional android.content.ClipDescriptionProto description = 1;
+    optional ClipDescriptionProto description = 1;
 
     // Custom dump of an android.graphics.Bitmap object.
     message Icon {
@@ -46,8 +46,8 @@
             string html_text = 1;
             string text = 2;
             string uri = 3;
-            android.content.IntentProto intent = 4;
-            bool nothing = 5;
+            IntentProto intent = 4;
+            bool nothing = 5 [ (.android.privacy).dest = DEST_AUTOMATIC ];
         }
     }
     repeated Item items = 3;
diff --git a/core/proto/android/content/component_name.proto b/core/proto/android/content/component_name.proto
index 4e49cf2..232d685 100644
--- a/core/proto/android/content/component_name.proto
+++ b/core/proto/android/content/component_name.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.content";
 option java_multiple_files = true;
 
 package android.content;
diff --git a/core/proto/android/content/configuration.proto b/core/proto/android/content/configuration.proto
index 5755c59..06f9735 100644
--- a/core/proto/android/content/configuration.proto
+++ b/core/proto/android/content/configuration.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.content";
 option java_multiple_files = true;
 
 package android.content;
diff --git a/core/proto/android/content/featureinfo.proto b/core/proto/android/content/featureinfo.proto
index 6878f0e..87bf404 100644
--- a/core/proto/android/content/featureinfo.proto
+++ b/core/proto/android/content/featureinfo.proto
@@ -18,7 +18,6 @@
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
-option java_package = "android.content.pm";
 option java_multiple_files = true;
 
 package android.content.pm;
diff --git a/core/proto/android/content/intent.proto b/core/proto/android/content/intent.proto
index 3b2c4fc..99ed687 100644
--- a/core/proto/android/content/intent.proto
+++ b/core/proto/android/content/intent.proto
@@ -17,7 +17,6 @@
 syntax = "proto2";
 package android.content;
 
-option java_package = "android.content";
 option java_multiple_files = true;
 
 import "frameworks/base/core/proto/android/content/component_name.proto";
@@ -58,8 +57,9 @@
     optional string package = 6;
     optional ComponentNameProto component = 7;
     optional string source_bounds = 8;
-    optional string clip_data = 9 [ (.android.privacy).dest = DEST_EXPLICIT ];
+    optional string clip_data = 9 [ (.android.privacy).dest = DEST_LOCAL ];
     optional string extras = 10 [ (.android.privacy).dest = DEST_LOCAL ];
+    // UserHandle value (similar to user_id in other protos).
     optional int32 content_user_hint = 11;
     optional string selector = 12;
 }
@@ -70,6 +70,13 @@
 
     repeated string actions = 1;
     repeated string categories = 2;
+    // https://developer.android.com/guide/topics/manifest/data-element#scheme:
+    // The scheme part of a URI. This is the minimal essential attribute for
+    // specifying a URI; at least one scheme attribute must be set for the filter,
+    // or none of the other URI attributes are meaningful. A scheme is specified
+    // without the trailing colon (for example, http, rather than http:). If the
+    // filter has a data type set (the mimeType attribute) but no scheme, the
+    // content: and file: schemes are assumed.
     repeated string data_schemes = 3  [ (.android.privacy).dest = DEST_EXPLICIT ];
     repeated android.os.PatternMatcherProto data_scheme_specs = 4;
     repeated AuthorityEntryProto data_authorities = 5;
diff --git a/core/proto/android/content/locale.proto b/core/proto/android/content/locale.proto
index 87b555c..86743bf 100644
--- a/core/proto/android/content/locale.proto
+++ b/core/proto/android/content/locale.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.content";
 option java_multiple_files = true;
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
diff --git a/core/proto/android/content/package_item_info.proto b/core/proto/android/content/package_item_info.proto
index 6e99bec..ebb2fa6 100644
--- a/core/proto/android/content/package_item_info.proto
+++ b/core/proto/android/content/package_item_info.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.content.pm";
 option java_multiple_files = true;
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
@@ -72,20 +71,43 @@
         optional int32 requires_smallest_width_dp = 3;
         optional int32 compatible_width_limit_dp = 4;
         optional int32 largest_width_limit_dp = 5;
+        // String retrieved from the seinfo tag found in selinux policy. This value
+        // can be set through the mac_permissions.xml policy construct. This value
+        // is used for setting an SELinux security context on the process as well as
+        // its data directory.
         optional string seinfo = 6;
+        // The seinfo tag generated per-user. This value may change based upon the
+        // user's configuration. For example, when an instant app is installed for a
+        // user. It is an error if this field is ever null when trying to
+        // start a new process.
         optional string seinfo_user = 7;
+        // Full path to the device-protected directory assigned to the package for
+        // its persistent data.
         optional string device_protected_data_dir = 8;
+        // Full path to the credential-protected directory assigned to the package
+        // for its persistent data.
         optional string credential_protected_data_dir = 9;
+        // Paths to all shared libraries this application is linked against. This
+        // field is only set if the  PackageManager.GET_SHARED_LIBRARY_FILES} flag
+        // was used when retrieving the structure.
         repeated string shared_library_files = 10;
         optional string manage_space_activity_name = 11;
         optional int32 description_res = 12;
         optional int32 ui_options = 13;
         optional bool supports_rtl = 14;
         oneof full_backup_content {
+            // An optional attribute that indicates the app supports automatic backup
+            // of app data. 0 is the default and means the app's entire data folder +
+            // managed external storage will be backed up; Any negative value
+            // indicates the app does not support full-data backup, though it may
+            // still want to participate via the traditional key/value backup API; A
+            // positive number specifies an xml resource in which the application has
+            // defined its backup include/exclude criteria. The data in this field is
+            // of the format "@xml/<number>".
             string content = 15;
             bool is_full_backup = 16;
         }
-        optional int32 networkSecurity_config_res = 17;
+        optional int32 network_security_config_res = 17;
         optional int32 category = 18;
     }
     optional Detail detail = 17;
diff --git a/core/proto/android/media/audioattributes.proto b/core/proto/android/media/audioattributes.proto
index ef04720..d679d9c 100644
--- a/core/proto/android/media/audioattributes.proto
+++ b/core/proto/android/media/audioattributes.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.media";
 option java_multiple_files = true;
 
 package android.media;
diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto
index 0970bd5..a4167c1 100644
--- a/core/proto/android/os/batterystats.proto
+++ b/core/proto/android/os/batterystats.proto
@@ -788,7 +788,7 @@
     message UserActivity {
         option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-        optional android.os.PowerManagerProto.UserActivityEvent name = 1;
+        optional PowerManagerProto.UserActivityEvent name = 1;
         optional int32 count = 2;
     };
     repeated UserActivity user_activity = 23;
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 5f6b6cc..8f28970 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -18,7 +18,6 @@
 option java_multiple_files = true;
 
 import "frameworks/base/core/proto/android/os/backtrace.proto";
-import "frameworks/base/core/proto/android/os/batterystats.proto";
 import "frameworks/base/core/proto/android/os/batterytype.proto";
 import "frameworks/base/core/proto/android/os/cpufreq.proto";
 import "frameworks/base/core/proto/android/os/cpuinfo.proto";
diff --git a/core/proto/android/os/looper.proto b/core/proto/android/os/looper.proto
index dce65d3..b9b8cf5 100644
--- a/core/proto/android/os/looper.proto
+++ b/core/proto/android/os/looper.proto
@@ -28,5 +28,5 @@
     // the thread name, usually set by developers.
     optional string thread_name = 1;
     optional int64 thread_id = 2;
-    optional android.os.MessageQueueProto queue = 3;
+    optional MessageQueueProto queue = 3;
 }
diff --git a/core/proto/android/os/message.proto b/core/proto/android/os/message.proto
index 048d031..8aaec70 100644
--- a/core/proto/android/os/message.proto
+++ b/core/proto/android/os/message.proto
@@ -23,15 +23,21 @@
 message MessageProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // Targeted delivery time of the message.
     optional int64 when = 1;
     // Name of callback class.
     optional string callback = 2;
-    // User-defined message code so that the recipient can identify what this
+    // App-defined message code so that the recipient can identify what this
     // message is about.
     optional int32 what = 3;
+    // Lower-cost alternative to using setData() if the app only needs to store a few integer values.
     optional int32 arg1 = 4;
+    // Lower-cost alternative to using setData() if the app only needs to store a few integer values.
     optional int32 arg2 = 5;
-    // String representation of an arbitrary object to send to the recipient.
+    // String representation of an arbitrary object to send to the Handler.  When
+    // using android.os.Messenger to send the message across processes, this will
+    // only be populated if it contains a Parcelable of a framework class (not one
+    // implemented by the application).
     optional string obj = 6 [ (.android.privacy).dest = DEST_EXPLICIT ];
     // Name of target class.
     optional string target = 7;
diff --git a/core/proto/android/os/messagequeue.proto b/core/proto/android/os/messagequeue.proto
index 4bfcb81..61bbee7 100644
--- a/core/proto/android/os/messagequeue.proto
+++ b/core/proto/android/os/messagequeue.proto
@@ -25,7 +25,7 @@
 message MessageQueueProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    repeated android.os.MessageProto messages = 1;
+    repeated MessageProto messages = 1;
     optional bool is_polling_locked = 2;
     optional bool is_quitting = 3;
 }
diff --git a/core/proto/android/os/pagetypeinfo.proto b/core/proto/android/os/pagetypeinfo.proto
index 0b8a5da..65e7139 100644
--- a/core/proto/android/os/pagetypeinfo.proto
+++ b/core/proto/android/os/pagetypeinfo.proto
@@ -49,8 +49,11 @@
 
         optional int32 node = 1;
 
+        // Memory zone.
         optional string zone = 2;
 
+        // Migration type (Unmovable, Reclaimable, Movable, Reserve, CMA, and
+        // Isolate).
         optional string type = 3;
 
         // order level starts from 0 for 4KB to page_block_order defined above, e.g. 10 for 4096KB
@@ -64,6 +67,7 @@
 
         optional int32 node = 1;
 
+        // Memory zone.
         optional string zone = 2;
 
         optional int32 unmovable = 3;
diff --git a/core/proto/android/os/procrank.proto b/core/proto/android/os/procrank.proto
index ff7515e..f7edaf4 100644
--- a/core/proto/android/os/procrank.proto
+++ b/core/proto/android/os/procrank.proto
@@ -15,18 +15,17 @@
  */
 
 syntax = "proto2";
+package android.os;
+
 option java_multiple_files = true;
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
-package android.os;
-
-//Memory usage of running processes
+// Memory usage of running processes
 message ProcrankProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     // Currently running process
-    // Next Tag: 11
     message Process {
         option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -59,11 +58,12 @@
 
         // process command
         optional string cmdline = 10;
+
+        // Next Tag: 11
     }
     repeated Process processes = 1;
 
     // Summary
-    // Next Tag: 3
     message Summary {
         option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -83,6 +83,8 @@
             optional string raw_text = 1;
         }
         optional Ram ram = 3;
+
+        // Next Tag: 4
     }
     optional Summary summary = 2;
 }
diff --git a/core/proto/android/os/ps.proto b/core/proto/android/os/ps.proto
index 0ab92d7..e032b57 100644
--- a/core/proto/android/os/ps.proto
+++ b/core/proto/android/os/ps.proto
@@ -52,7 +52,7 @@
         // and ps is not displaying threads.
         optional string wchan = 8;
         // Memory address of the process.
-        optional string addr = 9;
+        optional string addr = 9 [ (android.privacy).dest = DEST_LOCAL ];
 
         enum ProcessStateCode {
             STATE_UNKNOWN = 0;
diff --git a/core/proto/android/os/system_properties.proto b/core/proto/android/os/system_properties.proto
index c5f7d0e..a41edf3 100644
--- a/core/proto/android/os/system_properties.proto
+++ b/core/proto/android/os/system_properties.proto
@@ -194,7 +194,7 @@
     message Log {
         option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-        optional string tag_WifiHAL = 1;
+        optional string tag_wifi_hal = 1;
         optional string tag_stats_log = 2;
 
         // Next Tag: 3
@@ -237,7 +237,7 @@
         optional bool  adb_secure = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional string arch = 2;
         optional bool   audio_ignore_effects = 3;
-        optional bool   audio_monitorRotation = 4;
+        optional bool   audio_monitor_rotation = 4;
         optional string baseband = 5;
         optional string board_platform = 6;
 
@@ -249,9 +249,13 @@
             repeated string boottime = 5;
             optional string console = 6;
             optional int32  fake_battery = 7;
+            // The name of the hardware (from the kernel command line or /proc). It
+            // SHOULD be reasonably human-readable.
             optional string hardware = 8;
             optional string hardware_color = 9;
             optional string hardware_revision = 10;
+            // SKU is for small variants such as device color, targeted market,
+            // ram/rom size, etc.
             optional string hardware_sku = 11;
             optional string keymaster = 12;
             optional string mode = 13;
@@ -292,27 +296,60 @@
         message Build {
             option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+            // Date of the platform build.
             optional string date = 1;
+            // UTC timstamp of build data.
             optional int64  date_utc = 2;
             optional string description = 3;
+            // A build ID string meant for displaying to the user.
             optional string display_id = 4;
+            // A string that uniquely identifies the host the build was built on, in
+            // human-readable format. Only makes sense for internal engineering
+            // builds.
             optional string host = 5;
+            // Unique id of this android platform build. An identifier chosen by the
+            // device implementer to refer to a specific release, in human-readable
+            // format. This field can be the same as
+            // android.os.Build.VERSION.INCREMENTAL, but SHOULD be a value
+            // sufficiently meaningful for end users to distinguish between software
+            // builds.
             optional string id = 6;
+            // Product name.
             optional string product = 7;
             optional bool   system_root_image = 8;
+            // Tags of the buid, e.g. dev-keys, release-keys.
             optional string tags = 9;
+            // Type of the build, e.g. eng, userdebug, user.
             optional string type = 10;
+            // Name of the user (an engineer or a build bot) that built the image. For
+            // production builds, this is from the build bot but some OEMs might use a
+            // real username. Only makes sense for internal engineering builds.
             optional string user = 11;
 
             message Version {
                 option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+                // The base OS build the product is based on. A value representing the
+                // FINGERPRINT parameter of the build that is otherwise identical to
+                // this build except for the patches provided in the Android Public
+                // Security Bulletin.
                 optional string base_os = 1;
                 optional string codename = 2;
+                // A value chosen by the device implementer designating the specific
+                // build of the currently-executing Android system, in human-readable
+                // format. This value MUST NOT be reused for different builds made
+                // available to end users. A typical use of this field is to indicate
+                // which build number or source-control change identifier was used to
+                // generate the build.
                 optional string incremental = 3;
                 optional int32  preview_sdk = 4;
+                // The version of the currently-executing Android system, in
+                // human-readable format.
                 optional string release = 5;
+                // The version of the currently-executing Android system, in a format
+                // accessible to third-party application code.
                 optional int32  sdk = 6;
+                // A value indicating the security patch level of a build.
                 optional string security_patch = 7;
 
                 // Next Tag: 8
@@ -324,8 +361,11 @@
         optional Build build = 11;
 
         optional bool   camera_notify_nfc = 12  [ (android.privacy).dest = DEST_AUTOMATIC ];
+        // Carrier name on the phone.
         optional string carrier = 13;
+        // Is dataroaming enabled.
         optional bool   com_android_dataroaming = 14  [ (android.privacy).dest = DEST_AUTOMATIC ];
+        // does it provide mobiledata.
         optional bool   com_android_prov_mobiledata = 15  [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional string com_google_clientidbase = 16;
 
@@ -346,6 +386,7 @@
         optional string crypto_state = 21;
         optional string crypto_type = 22;
         optional string dalvik_vm_native_bridge = 23;
+        // Is this build debuggable.
         optional bool   debuggable = 24;
         optional string frp_pst = 25;
         optional string gfx_driver_0 = 26;
@@ -353,8 +394,8 @@
         message Hardware {
             option (android.msg_privacy).dest = DEST_LOCAL;
 
-            optional string value = 1; // value of ro.hardware itself
-
+            // value of ro.hardware itself
+            optional string value = 1;
             optional string activity_recognition = 2;
             optional string audio = 3;
             optional string audio_policy = 4;
@@ -403,21 +444,30 @@
         optional int32  oem_unlock_supported = 30;
         optional int32  opengles_version = 31;
 
+        // The product of the device.
         message Product {
             option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+            // Name of the product.
             optional string board = 1;
+            // Brand of the product.
             optional string brand = 2;
             optional string cpu_abi = 3;
             repeated string cpu_abilist = 4;
             repeated string cpu_abilist32 = 5;
             repeated string cpu_abilist64 = 6;
+            // Device name.
             optional string device = 7;
+            // The first api level when the phone is launched.
             optional int32  first_api_level = 8;
+            // Manufacturer of the product.
             optional string manufacturer = 9;
+            // Marketing name of the phone.
             optional string model = 10;
+            // Name of the product.
             optional string name = 11;
 
+            // Vendor related information about the product.
             message Vendor {
                 option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -441,6 +491,7 @@
 
         message Telephony {
             optional bool  call_ring_multiple = 1;
+            // CDMA subscription number.
             optional int32 default_cdma_sub = 2;
             optional int32 default_network = 3;
         }
@@ -456,6 +507,7 @@
         }
         optional Vendor vendor = 41;
 
+        // Vendor Native Development Kit version.
         optional string vndk_version = 42;
         optional int32  vts_coverage = 43;
         optional string zygote = 44;
@@ -492,7 +544,7 @@
     }
     optional Sys sys = 24;
 
-    optional int32  telephony_lteOnCdmaDevice = 25;
+    optional int32  telephony_lte_on_cdma_device = 25;
     optional int32  tombstoned_max_tombstone_count = 26;
     optional string vold_decrypt = 27;
     optional int32  vold_post_fs_data_done = 28;
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 04e5658..f9f725a 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -97,7 +97,18 @@
     }
     optional Auto auto = 16;
 
-    optional SettingProto autofill_compat_mode_allowed_packages = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    reserved 17; // Used to be autofill_compat_mode_allowed_packages
+
+    message Autofill {
+      option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+      optional SettingProto compat_mode_allowed_packages = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+      optional SettingProto logging_level = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+      optional SettingProto max_partitions_size = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+      optional SettingProto max_visible_datasets = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    }
+    optional Autofill autofill = 140;
+
     optional SettingProto backup_agent_timeout_parameters = 18;
 
     message Battery {
@@ -383,6 +394,8 @@
 
         // App allowed to load GPU debug layers.
         optional SettingProto debug_app = 1;
+        // Ordered GPU debug layer list
+        // i.e. <layer1>:<layer2>:...:<layerN>
         optional SettingProto debug_layers = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Gpu gpu = 59;
@@ -734,7 +747,7 @@
 
         optional SettingProto car_dock = 1;
         optional SettingProto car_undock = 2;
-        optional SettingProto charging_sounds_enabled = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        reserved 3; // Moved to secure settings Sound.charging_sounds_enabled
         optional SettingProto charging_started = 4;
         optional SettingProto desk_dock = 5;
         optional SettingProto desk_undock = 6;
@@ -910,6 +923,12 @@
         optional SettingProto connected_mac_randomization_enabled = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto max_dhcp_retry_count = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto mobile_data_transition_wakelock_timeout_ms = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        // Controls whether WiFi configurations created by a Device Owner app should
+        // be locked down (that is, be editable or removable only by the Device
+        // Owner App, not even by Settings app). This setting takes integer values.
+        // Non-zero values mean that the Device Owner-created configurations are
+        // locked down. Value of zero means they are not. Default value in the
+        // absence of actual value to this setting is 0.
         optional SettingProto device_owner_configs_lockdown = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto frequency_band = 29 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto p2p_device_name = 30;
@@ -930,12 +949,8 @@
         optional SettingProto mode = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto mode_ringer_level = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto mode_config_etag = 3;
-        // If 0, turning on dnd manually will last indefinitely. Else if
-        // non-negative, turning on dnd manually will last for this many minutes.
-        // Else (if negative), turning on dnd manually will surface a dialog that
-        // prompts user to specify a duration.
-        optional SettingProto duration = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
-        optional SettingProto show_zen_upgrade_notification = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        reserved 4; // Moved to secure settings Zen.duration
+        reserved 5; // Moved to secure settings Zen.show_zen_upgrade_notification
     }
     optional Zen zen = 138;
 
@@ -943,5 +958,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 140;
+    // Next tag = 141;
 }
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 237efd8..6e661e1 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -144,6 +144,10 @@
         optional SettingProto provisioned = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto transport = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto manager_constants = 5;
+        // Local transport parameters so we can configure it for tests.
+        // This is encoded as a key=value list, separated by commas.
+        // The following keys are supported:
+        //   fake_encryption_flag  (boolean)
         optional SettingProto local_transport_parameters = 6;
         optional SettingProto packages_to_clear_data_before_full_restore = 7;
     }
@@ -300,6 +304,7 @@
         optional SettingProto enabled_policy_access_packages = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto badging = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto show_note_about_notification_hiding = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto in_call_notification_enabled = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Notification notification = 41;
 
@@ -404,6 +409,15 @@
     optional SettingProto skip_first_use_hints = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto sleep_timeout = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto sms_default_application = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+    message Sounds {
+        option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+        optional SettingProto charging_sounds_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto charging_vibration_enabled = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    }
+    optional Sounds sounds = 72;
+
     // Defines whether managed profile ringtones should be synced from its
     // parent profile.
     optional SettingProto sync_parent_sounds = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
@@ -484,7 +498,22 @@
 
     optional SettingProto wake_gesture_enabled = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
+    message Zen {
+        option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+        // If 0, turning on dnd manually will last indefinitely. Else if
+        // non-negative, turning on dnd manually will last for this many minutes.
+        // Else (if negative), turning on dnd manually will surface a dialog that
+        // prompts user to specify a duration.
+        optional SettingProto duration = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto show_zen_upgrade_notification = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto show_zen_settings_suggestion = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto settings_updated = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto settings_suggestion_viewed = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    }
+    optional Zen zen = 71;
+
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 71;
+    // Next tag = 73;
 }
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 9d24588..9d5f0bc 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -28,6 +28,7 @@
 import "frameworks/base/core/proto/android/content/package_item_info.proto";
 import "frameworks/base/core/proto/android/graphics/rect.proto";
 import "frameworks/base/core/proto/android/internal/processstats.proto";
+import "frameworks/base/core/proto/android/os/bundle.proto";
 import "frameworks/base/core/proto/android/os/looper.proto";
 import "frameworks/base/core/proto/android/os/powermanager.proto";
 import "frameworks/base/core/proto/android/server/intentresolver.proto";
@@ -62,11 +63,14 @@
     optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
     repeated ActivityDisplayProto displays = 2;
     optional KeyguardControllerProto keyguard_controller = 3;
+    // TODO(b/111541062): Focused stack and resumed activity are now per-display. Topmost instances
+    // can be obtained from top display and these fields can be removed.
     optional int32 focused_stack_id = 4;
     optional .com.android.server.wm.IdentifierProto resumed_activity = 5;
     // Whether or not the home activity is the recents activity. This is needed for the CTS tests to
     // know what activity types to check for when invoking splitscreen multi-window.
     optional bool is_home_recents_component = 6;
+    repeated .com.android.server.wm.IdentifierProto pending_activities = 7;
 }
 
 /* represents ActivityStackSupervisor.ActivityDisplay */
@@ -76,6 +80,8 @@
     optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
     optional int32 id = 2;
     repeated ActivityStackProto stacks = 3;
+    optional int32 focused_stack_id = 4;
+    optional .com.android.server.wm.IdentifierProto resumed_activity = 5;
 }
 
 message ActivityStackProto {
@@ -158,7 +164,8 @@
     optional BroadcastRecordProto current = 5;
     optional bool linked_to_death = 6;
     repeated BroadcastFilterProto filters = 7;
-    optional string hex_hash = 8; // used to find this ReceiverList object in IntentResolver
+    // Used to find this ReceiverList object in IntentResolver
+    optional string hex_hash = 8;
 }
 
 message ProcessRecordProto {
@@ -185,7 +192,8 @@
 
     optional .android.content.IntentFilterProto intent_filter = 1;
     optional string required_permission = 2;
-    optional string hex_hash = 3; // used to find the BroadcastFilter object in IntentResolver
+    // Used to find the BroadcastFilter object in IntentResolver
+    optional string hex_hash = 3;
     optional int32 owning_user_id = 4;
 }
 
@@ -406,6 +414,7 @@
     message StickyAction {
         option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
+        // The action of the sticky Intent.
         optional string name = 1;
         repeated .android.content.IntentProto intents = 2;
     }
@@ -551,7 +560,7 @@
 message ConnectionRecordProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    // used to find same record, e.g. AppBindRecord has the hex_hash
+    // Used to find same record, e.g. AppBindRecord has the hex_hash
     optional string hex_hash = 1; // cross reference the object and avoid double logging.
     optional int32 user_id = 2;
 
@@ -798,7 +807,11 @@
     optional string profile_file = 6;
     optional string watcher = 7;
     optional string ui_automation_connection = 8;
-    optional string arguments = 9 [ (.android.privacy).dest = DEST_EXPLICIT ];
+    // Arguments as given to the ActiveInstrumentation object in Bundle
+    // toString format.
+    reserved 9; // arguments (in String format).
+    // Arguments as given to the ActiveInstrumentation object.
+    optional .android.os.BundleProto arguments = 10;
 }
 
 // Proto definition of com.android.server.am.UidRecord.java
diff --git a/core/proto/android/server/alarmmanagerservice.proto b/core/proto/android/server/alarmmanagerservice.proto
index eef78d1..b74f28d 100644
--- a/core/proto/android/server/alarmmanagerservice.proto
+++ b/core/proto/android/server/alarmmanagerservice.proto
@@ -228,6 +228,8 @@
 message FilterStatsProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // Tag given to AlarmManager by the app or component scheduling the alarm.
+    // As some of them are app-supplied, some tags may contain PII.
     optional string tag = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
     // The last time this filter when in flight, in terms of elapsed realtime.
     optional int64 last_flight_time_realtime = 2;
@@ -248,6 +250,8 @@
 
     optional int32 uid = 1;
     optional string pkg = 2;
+    // Tag given to AlarmManager by the app or component scheduling the alarm.
+    // As some of them are app-supplied, some tags may contain PII.
     optional string tag = 3 [ (.android.privacy).dest = DEST_EXPLICIT ];
     optional string op = 4;
     // Time when this entry was created, in terms of elapsed realtime.
@@ -263,6 +267,8 @@
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional int32 uid = 1;
+    // Tag given to AlarmManager by the app or component scheduling the alarm.
+    // As some of them are app-supplied, some tags may contain PII.
     optional string tag = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
     optional int64 when_elapsed_ms = 3;
     optional .android.app.AlarmManagerProto.AlarmType alarm_type = 4;
@@ -277,6 +283,8 @@
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional int32 uid = 1;
+    // The operation that caused the wakeup. May be an Intent action or a
+    // listener tag.
     optional string action = 2;
     optional int64 when = 3;
 }
diff --git a/core/proto/android/server/forceappstandbytracker.proto b/core/proto/android/server/forceappstandbytracker.proto
index 8c71b0b..54f30c3 100644
--- a/core/proto/android/server/forceappstandbytracker.proto
+++ b/core/proto/android/server/forceappstandbytracker.proto
@@ -71,7 +71,7 @@
     message ExemptedPackage {
         option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-        optional int32 userId = 1;
+        optional int32 user_id = 1;
         optional string package_name = 2;
     }
 
diff --git a/core/proto/android/server/statlogger.proto b/core/proto/android/server/statlogger.proto
index 46badc4..65b1af7 100644
--- a/core/proto/android/server/statlogger.proto
+++ b/core/proto/android/server/statlogger.proto
@@ -29,7 +29,7 @@
     message Event {
         option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-        optional int32 eventId = 1;
+        optional int32 event_id = 1;
         // Labels are hard-coded in Android framework code.
         optional string label = 2;
         optional int32 count = 3;
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 7467d8f..a8b23dd 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -24,6 +24,7 @@
 import "frameworks/base/core/proto/android/server/surfaceanimator.proto";
 import "frameworks/base/core/proto/android/view/displaycutout.proto";
 import "frameworks/base/core/proto/android/view/displayinfo.proto";
+import "frameworks/base/core/proto/android/view/enums.proto";
 import "frameworks/base/core/proto/android/view/surface.proto";
 import "frameworks/base/core/proto/android/view/windowlayoutparams.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
@@ -47,12 +48,12 @@
     optional AppTransitionProto app_transition = 9;
 }
 
-/* represents DisplayContent */
+/* represents RootWindowContainer object */
 message RootWindowContainerProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional WindowContainerProto window_container = 1;
-    repeated DisplayProto displays = 2;
+    repeated DisplayContentProto displays = 2;
     /* window references in top down z order */
     repeated IdentifierProto windows = 3;
 }
@@ -134,36 +135,12 @@
         APP_STATE_TIMEOUT = 3;
     }
     optional AppState app_transition_state = 1;
-    /* definitions for constants found in {@link com.android.server.wm.AppTransition} */
-    enum TransitionType {
-        TRANSIT_NONE = 0;
-        TRANSIT_UNSET = -1;
-        TRANSIT_ACTIVITY_OPEN = 6;
-        TRANSIT_ACTIVITY_CLOSE = 7;
-        TRANSIT_TASK_OPEN = 8;
-        TRANSIT_TASK_CLOSE = 9;
-        TRANSIT_TASK_TO_FRONT = 10;
-        TRANSIT_TASK_TO_BACK = 11;
-        TRANSIT_WALLPAPER_CLOSE = 12;
-        TRANSIT_WALLPAPER_OPEN = 13;
-        TRANSIT_WALLPAPER_INTRA_OPEN = 14;
-        TRANSIT_WALLPAPER_INTRA_CLOSE = 15;
-        TRANSIT_TASK_OPEN_BEHIND = 16;
-        TRANSIT_TASK_IN_PLACE = 17;
-        TRANSIT_ACTIVITY_RELAUNCH = 18;
-        TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
-        TRANSIT_KEYGUARD_GOING_AWAY = 20;
-        TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
-        TRANSIT_KEYGUARD_OCCLUDE = 22;
-        TRANSIT_KEYGUARD_UNOCCLUDE = 23;
-        TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = 24;
-        TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = 25;
-    }
-    optional TransitionType last_used_app_transition = 2;
+
+    optional .android.view.TransitionTypeEnum last_used_app_transition = 2;
 }
 
-/* represents DisplayContent */
-message DisplayProto {
+/* represents DisplayContent object */
+message DisplayContentProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional WindowContainerProto window_container = 1;
@@ -284,14 +261,16 @@
 
     optional WindowContainerProto window_container = 1;
     optional IdentifierProto identifier = 2;
+    // Unique identifier of a DisplayContent stack.
     optional int32 display_id = 3;
+    // Unique identifier for the task stack.
     optional int32 stack_id = 4;
     optional .android.view.WindowLayoutParamsProto attributes = 5;
     optional .android.graphics.RectProto given_content_insets = 6;
-    optional .android.graphics.RectProto frame = 7;
-    optional .android.graphics.RectProto containing_frame = 8;
-    optional .android.graphics.RectProto parent_frame = 9;
-    optional .android.graphics.RectProto content_frame = 10;
+    optional .android.graphics.RectProto frame = 7 [deprecated=true];
+    optional .android.graphics.RectProto containing_frame = 8 [deprecated=true];
+    optional .android.graphics.RectProto parent_frame = 9 [deprecated=true];
+    optional .android.graphics.RectProto content_frame = 10 [deprecated=true];
     optional .android.graphics.RectProto content_insets = 11;
     optional .android.graphics.RectProto surface_insets = 12;
     optional WindowStateAnimatorProto animator = 13;
@@ -304,21 +283,24 @@
     optional int32 system_ui_visibility = 21;
     optional bool has_surface = 22;
     optional bool is_ready_for_display = 23;
-    optional .android.graphics.RectProto display_frame = 24;
-    optional .android.graphics.RectProto overscan_frame = 25;
-    optional .android.graphics.RectProto visible_frame = 26;
-    optional .android.graphics.RectProto decor_frame = 27;
-    optional .android.graphics.RectProto outset_frame = 28;
+    optional .android.graphics.RectProto display_frame = 24 [deprecated=true];
+    optional .android.graphics.RectProto overscan_frame = 25 [deprecated=true];
+    optional .android.graphics.RectProto visible_frame = 26 [deprecated=true];
+    optional .android.graphics.RectProto decor_frame = 27 [deprecated=true];
+    optional .android.graphics.RectProto outset_frame = 28 [deprecated=true];
     optional .android.graphics.RectProto overscan_insets = 29;
     optional .android.graphics.RectProto visible_insets = 30;
     optional .android.graphics.RectProto stable_insets = 31;
     optional .android.graphics.RectProto outsets = 32;
-    optional .android.view.DisplayCutoutProto cutout = 33;
+    optional .android.view.DisplayCutoutProto cutout = 33 [deprecated=true];
     optional bool remove_on_exit = 34;
     optional bool destroying = 35;
     optional bool removed = 36;
     optional bool is_on_screen = 37;
     optional bool is_visible = 38;
+    optional bool pending_forced_seamless_rotation = 39;
+    optional int64 finished_forced_seamless_rotation_frame = 40;
+    optional WindowFramesProto window_frames = 41;
 }
 
 message IdentifierProto {
@@ -326,6 +308,8 @@
 
     optional int32 hash_code = 1;
     optional int32 user_id = 2;
+    // Either a component name/string (eg: "com.android.settings/.FallbackHome")
+    // or a window title ("NavigationBar").
     optional string title = 3 [ (.android.privacy).dest = DEST_EXPLICIT ];
 }
 
@@ -380,3 +364,19 @@
     optional .android.content.ConfigurationProto full_configuration = 2;
     optional .android.content.ConfigurationProto merged_override_configuration = 3;
 }
+
+/* represents WindowFrames */
+message WindowFramesProto {
+    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional .android.graphics.RectProto containing_frame = 1;
+    optional .android.graphics.RectProto content_frame = 2;
+    optional .android.graphics.RectProto decor_frame = 3;
+    optional .android.graphics.RectProto display_frame = 4;
+    optional .android.graphics.RectProto frame = 5;
+    optional .android.graphics.RectProto outset_frame = 6;
+    optional .android.graphics.RectProto overscan_frame = 7;
+    optional .android.graphics.RectProto parent_frame = 8;
+    optional .android.graphics.RectProto visible_frame = 9;
+    optional .android.view.DisplayCutoutProto cutout = 10;
+}
diff --git a/core/proto/android/service/diskstats.proto b/core/proto/android/service/diskstats.proto
index f55f0e7..1012eb0 100644
--- a/core/proto/android/service/diskstats.proto
+++ b/core/proto/android/service/diskstats.proto
@@ -37,7 +37,7 @@
     }
     // Whether the latency test resulted in an error
     optional bool has_test_error = 1;
-    // If the test errored, error message is contained here, it is just IOException.
+    // If the test encountered an IOException, the error message is logged here.
     optional string error_message = 2;
     // 512B write latency in milliseconds, if the test was successful
     optional int32 write_512b_latency_millis = 3;
diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto
index d75f135..bb32495 100644
--- a/core/proto/android/service/graphicsstats.proto
+++ b/core/proto/android/service/graphicsstats.proto
@@ -46,10 +46,10 @@
     optional int64 stats_start = 3;
     optional int64 stats_end = 4;
 
-    // The aggregated statistics for the package
+    // The aggregated statistics for the package.
     optional GraphicsStatsJankSummaryProto summary = 5;
 
-    // The frame time histogram for the package
+    // The frame time histogram for the package.
     repeated GraphicsStatsHistogramBucketProto histogram = 6;
 }
 
diff --git a/core/proto/android/service/netstats.proto b/core/proto/android/service/netstats.proto
index 29fd195..02d4483 100644
--- a/core/proto/android/service/netstats.proto
+++ b/core/proto/android/service/netstats.proto
@@ -47,6 +47,7 @@
 message NetworkInterfaceProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // Name of the network interface (eg: wlan).
     optional string interface = 1;
 
     optional NetworkIdentitySetProto identities = 2;
@@ -63,11 +64,15 @@
 message NetworkIdentityProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    // Constats from ConnectivityManager.TYPE_*.
+    // Constants from ConnectivityManager.TYPE_*.
     optional int32 type = 1;
 
+    // Full subscriber ID on eng builds. The IMSI is scrubbed on user & userdebug
+    // builds to only include the info about the GSM network operator (the info
+    // that uniquely identifies the subscriber is removed).
     optional string subscriber_id = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
 
+    // Name of the network (eg: MyWifi).
     optional string network_id = 3 [ (android.privacy).dest = DEST_EXPLICIT ];
 
     optional bool roaming = 4;
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index bcd7f29..25059be 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -59,7 +59,7 @@
     }
     optional State state = 2;
     optional int32 flags = 3;
-    optional string channelId = 4 [ (.android.privacy).dest = DEST_EXPLICIT ];
+    optional string channel_id = 4 [ (.android.privacy).dest = DEST_EXPLICIT ];
     optional string sound = 5 [ (.android.privacy).dest = DEST_EXPLICIT ];
     optional .android.media.AudioAttributesProto audio_attributes = 6;
     optional bool can_vibrate = 7;
@@ -88,6 +88,8 @@
 message ManagedServicesProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // Hard-coded string identifying what the service config is for
+    // (eg: "notification assistant" or "notification listener").
     optional string caption = 1;
 
     message ServiceProto {
@@ -147,8 +149,11 @@
 message ConditionProto {
     option (android.msg_privacy).dest = DEST_EXPLICIT;
 
+    // The URI representing the rule being updated.
     optional string id = 1;
+    // A user visible description of the rule state.
     optional string summary = 2;
+    // Android generated strings that detail when ZenMode will end.
     optional string line_1 = 3;
     optional string line_2 = 4;
     optional int32 icon = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
@@ -189,7 +194,8 @@
         (android.privacy).dest = DEST_AUTOMATIC
     ];
 
-    // Required for automatic ZenRules.
+    // Required for automatic ZenRules. The condition's ID, which is the URI
+    // representing the rule being updated.
     optional string condition_id = 8;
     optional ConditionProto condition = 9;
     optional android.content.ComponentNameProto component = 10;
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
index 88bb4a6..4ecf52c 100644
--- a/core/proto/android/service/package.proto
+++ b/core/proto/android/service/package.proto
@@ -48,7 +48,7 @@
     message SharedUserProto {
         option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-        optional int32 user_id = 1;
+        optional int32 uid = 1;
         // Name of the shared UID. eg: android.uid.bluetooth
         optional string name = 2;
     }
diff --git a/core/proto/android/service/print.proto b/core/proto/android/service/print.proto
index 994814b..a449156 100644
--- a/core/proto/android/service/print.proto
+++ b/core/proto/android/service/print.proto
@@ -27,7 +27,7 @@
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     // Each user has a separate printer state
-    repeated PrintUserStateProto userStates = 1;
+    repeated PrintUserStateProto user_states = 1;
 }
 
 message PrintUserStateProto {
@@ -74,7 +74,8 @@
     // Print jobs
     repeated PrintJobInfoProto print_jobs = 1;
 
-    // Files used by these print jobs
+    // Files used by these print jobs. These are auto-generated UUIDs that are
+    // only valid while the print job is processed.
     repeated string print_job_files = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
 
     // Approved print services
@@ -125,7 +126,7 @@
     // The status of the printer
     optional Status status = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
-    // The description of the printer
+    // The description of the printer, set by the user.
     optional string description = 4;
 
     // The capabilities of the printer
@@ -310,7 +311,7 @@
     // Type of content (see PrintDocumentInfo.ContentType)
     optional int32 content_type = 3;
 
-    // The size of the the document
+    // The size of the document
     optional int64 data_size = 4;
 }
 
diff --git a/core/proto/android/service/procstats.proto b/core/proto/android/service/procstats.proto
index 15ede0c..736871f 100644
--- a/core/proto/android/service/procstats.proto
+++ b/core/proto/android/service/procstats.proto
@@ -15,14 +15,14 @@
  */
 
 syntax = "proto2";
+package android.service.procstats;
+
 option java_multiple_files = true;
 option java_outer_classname = "ProcessStatsServiceProto";
 
 import "frameworks/base/core/proto/android/util/common.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
-package android.service.procstats;
-
 /**
  * Data from ProcStatsService Dumpsys
  *
@@ -42,7 +42,7 @@
  * Data model from /frameworks/base/core/java/com/android/internal/app/procstats/ProcessStats.java
  * This proto is defined based on the writeToParcel method.
  *
- * Next Tag: 9
+ * Next Tag: 10
  */
 message ProcessStatsSectionProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -77,9 +77,86 @@
 
     // Stats for each process.
     repeated ProcessStatsProto process_stats = 8;
+
+    // Stats for each package.
+    repeated ProcessStatsPackageProto package_stats = 9;
 }
 
-// Next Tag: 6
+// Next Tag: 10
+message ProcessStatsStateProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    enum ScreenState {
+        SCREEN_UNKNOWN = 0;
+        OFF = 1;
+        ON = 2;
+    }
+    optional ScreenState screen_state = 1;
+
+    enum MemoryState {
+        MEMORY_UNKNOWN = 0;
+        NORMAL = 1;     // normal.
+        MODERATE = 2;   // moderate memory pressure.
+        LOW = 3;        // low memory.
+        CRITICAL = 4;   // critical memory.
+    }
+    optional MemoryState memory_state = 2;
+
+    // this enum list is from frameworks/base/core/java/com/android/internal/app/procstats/ProcessStats.java
+    // and not frameworks/base/core/java/android/app/ActivityManager.java
+    enum ProcessState {
+        PROCESS_UNKNOWN = 0;
+        // Persistent system process.
+        PERSISTENT = 1;
+        // Top activity; actually any visible activity.
+        TOP = 2;
+        // Important foreground process (ime, wallpaper, etc).
+        IMPORTANT_FOREGROUND = 3;
+        // Important background process.
+        IMPORTANT_BACKGROUND = 4;
+        // Performing backup operation.
+        BACKUP = 5;
+        // Background process running a service.
+        SERVICE = 6;
+        // Process not running, but would be if there was enough RAM.
+        SERVICE_RESTARTING = 7;
+        // Process running a receiver.
+        RECEIVER = 8;
+        // Heavy-weight process (currently not used).
+        HEAVY_WEIGHT = 9;
+        // Process hosting home/launcher app when not on top.
+        HOME = 10;
+        // Process hosting the last app the user was in.
+        LAST_ACTIVITY = 11;
+        // Cached process hosting a previous activity.
+        CACHED_ACTIVITY = 12;
+        // Cached process hosting a client activity.
+        CACHED_ACTIVITY_CLIENT = 13;
+        // Cached process that is empty.
+        CACHED_EMPTY = 14;
+    }
+    optional ProcessState process_state = 3;
+
+    // Millisecond uptime duration spent in this state
+    optional int64 duration_ms = 4;
+
+    // Millisecond elapsed realtime duration spent in this state
+    optional int64 realtime_duration_ms = 9;
+
+    // # of samples taken
+    optional int32 sample_size = 5;
+
+    // PSS is memory reserved for this process
+    optional android.util.AggStats pss = 6;
+
+    // USS is memory shared between processes, divided evenly for accounting
+    optional android.util.AggStats uss = 7;
+
+    // RSS is memory resident for this process
+    optional android.util.AggStats rss = 8;
+}
+
+// Next Tag: 7
 message ProcessStatsProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -104,74 +181,103 @@
     }
     optional Kill kill = 3;
 
-    message State {
+    // Time and memory spent in various states.
+    repeated ProcessStatsStateProto states = 5;
+
+    // Total time process has been running...  screen_state, memory_state, and process_state
+    // will not be set.
+    optional ProcessStatsStateProto total_running_state = 6;
+}
+
+// Next Tag: 7
+message ProcessStatsServiceStateProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // Name of service component.
+    optional string service_name = 1;
+
+    // Information about a state the service can be in.
+    message OperationInfo {
         option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-        enum ScreenState {
-            SCREEN_UNKNOWN = 0;
-            OFF = 1;
-            ON = 2;
-        }
-        optional ScreenState screen_state = 1;
+        // Number of times the service was in this operation.
+        optional int32 count = 1;
 
-        enum MemoryState {
-            MEMORY_UNKNOWN = 0;
-            NORMAL = 1;     // normal.
-            MODERATE = 2;   // moderate memory pressure.
-            LOW = 3;        // low memory.
-            CRITICAL = 4;   // critical memory.
-        }
-        optional MemoryState memory_state = 2;
-
-        // this enum list is from frameworks/base/core/java/com/android/internal/app/procstats/ProcessStats.java
-        // and not frameworks/base/core/java/android/app/ActivityManager.java
-        enum ProcessState {
-            PROCESS_UNKNOWN = 0;
-            // Persistent system process.
-            PERSISTENT = 1;
-            // Top activity; actually any visible activity.
-            TOP = 2;
-            // Important foreground process (ime, wallpaper, etc).
-            IMPORTANT_FOREGROUND = 3;
-            // Important background process.
-            IMPORTANT_BACKGROUND = 4;
-            // Performing backup operation.
-            BACKUP = 5;
-            // Background process running a service.
-            SERVICE = 6;
-            // Process not running, but would be if there was enough RAM.
-            SERVICE_RESTARTING = 7;
-            // Process running a receiver.
-            RECEIVER = 8;
-            // Heavy-weight process (currently not used).
-            HEAVY_WEIGHT = 9;
-            // Process hosting home/launcher app when not on top.
-            HOME = 10;
-            // Process hosting the last app the user was in.
-            LAST_ACTIVITY = 11;
-            // Cached process hosting a previous activity.
-            CACHED_ACTIVITY = 12;
-            // Cached process hosting a client activity.
-            CACHED_ACTIVITY_CLIENT = 13;
-            // Cached process that is empty.
-            CACHED_EMPTY = 14;
-        }
-        optional ProcessState process_state = 3;
-
-        // Millisecond duration spent in this state
-        optional int64 duration_ms = 4;
-
-        // # of samples taken
-        optional int32 sample_size = 5;
-
-        // PSS is memory reserved for this process
-        optional android.util.AggStats pss = 6;
-
-        // USS is memory shared between processes, divided evenly for accounting
-        optional android.util.AggStats uss = 7;
-
-        // RSS is memory resident for this process
-        optional android.util.AggStats rss = 8;
+        // Time this operation was active in various states.  process_state will not be set;
+        // includes only uptime, not memory info.
+        repeated ProcessStatsStateProto states = 2;
     }
-    repeated State states = 5;
+
+    // Information about when the service was operating as running (that is how long it was
+    // running for any reason, such as the finer-grained started, bound, and executing times
+    // also reported in this proto).
+    optional OperationInfo running_op = 2;
+
+    // Information about when the service was operating as started.
+    optional OperationInfo started_op = 3;
+
+    // Information about when the service was operating as foreground.
+    optional OperationInfo foreground_op = 4;
+
+    // Information about when the service was operating as bound.
+    optional OperationInfo bound_op = 5;
+
+    // Information about when the service was operating as executing.
+    optional OperationInfo executing_op = 6;
+}
+
+// Next Tag: 7
+message ProcessStatsAssociationStateProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // Name of the target component.
+    optional string component_name = 1;
+
+    // Information on one source in this association.
+    message Source {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        // Name of source process.
+        optional string process = 1;
+
+        // Uid of the source process.
+        optional int32 uid = 2;
+
+        // Total count of the times this association appeared.
+        optional int32 total_count = 3;
+
+        // Millisecond uptime total duration this association was around.
+        optional int64 total_duration_ms = 4;
+
+        // Total count of the times this association became actively impacting its target process.
+        optional int32 active_count = 5;
+
+        // Time association was active in various states.  screen_state and memory_state will not
+        // be set; includes only uptime, not memory info.
+        repeated ProcessStatsStateProto active_states = 6;
+    }
+    repeated Source sources = 3;
+}
+
+// Next Tag: 7
+message ProcessStatsPackageProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // Name of package.
+    optional string package = 1;
+
+    // Uid of the package.
+    optional int32 uid = 2;
+
+    // Version of the package.
+    optional int64 version = 3;
+
+    // Stats for each process running with the package loaded in to it.
+    repeated ProcessStatsProto process_stats = 4;
+
+    // Stats for each of the package's services.
+    repeated ProcessStatsServiceStateProto service_stats = 5;
+
+    // Stats for each association with the package.
+    repeated ProcessStatsAssociationStateProto association_stats = 6;
 }
diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto
index 9f58611..ed040f4 100644
--- a/core/proto/android/service/usb.proto
+++ b/core/proto/android/service/usb.proto
@@ -78,16 +78,24 @@
 
     optional string manufacturer = 1;
     optional string model = 2;
+    // For "classical" USB-accessories the manufacturer bakes this into the
+    // firmware of the device. If an Android phone is configured as accessory, the
+    // app that sets up the accessory side of the connection set this. Either way,
+    // these are part of the detection protocol, and so they cannot be user set or
+    // unique.
     optional string description = 3;
     optional string version = 4;
     optional string uri = 5 [ (android.privacy).dest = DEST_EXPLICIT ];
-    optional string serial = 6 [ (android.privacy).dest = DEST_EXPLICIT ];
+    // Non-resettable hardware ID.
+    optional string serial = 6 [ (android.privacy).dest = DEST_LOCAL ];
 }
 
 message UsbDebuggingManagerProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional bool connected_to_adb = 1;
+    // A workstation that connects to the phone for debugging is identified by
+    // this key.
     optional string last_key_received = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
     optional string user_keys = 3 [ (android.privacy).dest = DEST_LOCAL ];
     optional string system_keys = 4 [ (android.privacy).dest = DEST_LOCAL ];
@@ -105,8 +113,12 @@
 message UsbDeviceProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // Generic USB name, not user-provided.
     optional string name = 1;
+    // ID specific to the vendor, not the device.
     optional int32 vendor_id = 2;
+    // ID of this product type: Each vendor gives each product a unique ID. E.g.
+    // all mice of the same model would have the same ID.
     optional int32 product_id = 3;
     optional int32 class = 4;
     optional int32 subclass = 5;
@@ -114,14 +126,20 @@
     optional string manufacturer_name = 7;
     optional string product_name = 8;
     optional string version = 9;
-    optional string serial_number = 10 [ (android.privacy).dest = DEST_EXPLICIT ];
+    // Non-resettable hardware ID.
+    optional string serial_number = 10 [ (android.privacy).dest = DEST_LOCAL ];
     repeated UsbConfigurationProto configurations = 11;
 }
 
 message UsbConfigurationProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // A single USB device can have several configurations and the app accessing
+    // the USB device can switch between them. At any time only one can be active.
+    // Each configuration can present completely different interfaces end
+    // endpoints, i.e. a completely different behavior.
     optional int32 id = 1;
+    // Hardware-defined name, not set by the user.
     optional string name = 2;
     optional uint32 attributes = 3;
     optional int32 max_power = 4;
@@ -131,6 +149,7 @@
 message UsbInterfaceProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // Hardware defined. This is the id used by the app to identify the interface.
     optional int32 id = 1;
     optional int32 alternate_settings = 2;
     optional string name = 3;
@@ -145,6 +164,7 @@
 
     optional int32 endpoint_number = 1;
     optional android.service.UsbEndPointDirection direction = 2;
+      // The address of the endpoint. Needed to read and write to the endpoint.
     optional int32 address = 3;
     optional android.service.UsbEndPointType type = 4;
     optional uint32 attributes = 5;
@@ -201,6 +221,7 @@
         MODE_DEBUG_ACCESSORY = 8;
     }
 
+    // ID of the port. A device (eg: Chromebooks) might have multiple ports.
     optional string id = 1;
     repeated Mode supported_modes = 2;
 }
@@ -299,6 +320,7 @@
 message UsbProfileGroupSettingsManagerProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // The user id of the personal profile if the device has a work profile.
     optional int32 parent_user_id = 1;
     repeated UsbSettingsDevicePreferenceProto device_preferences = 2;
     repeated UsbSettingsAccessoryPreferenceProto accessory_preferences = 3;
@@ -314,6 +336,7 @@
 message UsbDeviceFilterProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
+    // Mirrors the vendor_id of UsbDeviceProto.
     optional int32 vendor_id = 1;
     optional int32 product_id = 2;
     optional int32 class = 3;
diff --git a/core/proto/android/view/display.proto b/core/proto/android/view/display.proto
index 30046c3..fe8fed6 100644
--- a/core/proto/android/view/display.proto
+++ b/core/proto/android/view/display.proto
@@ -22,6 +22,8 @@
 message DisplayProto {
     enum ColorMode {
         COLOR_MODE_INVALID = -1;
+        // The default or native gamut of the display.
+        COLOR_MODE_DEFAULT = 0;
         COLOR_MODE_BT601_625 = 1;
         COLOR_MODE_BT601_625_UNADJUSTED = 2;
         COLOR_MODE_BT601_525 = 3;
diff --git a/core/proto/android/view/displayinfo.proto b/core/proto/android/view/displayinfo.proto
index 8583955..29757fc 100644
--- a/core/proto/android/view/displayinfo.proto
+++ b/core/proto/android/view/displayinfo.proto
@@ -21,7 +21,8 @@
 
 option java_multiple_files = true;
 
-/* represents DisplayInfo */
+// Represents DisplayInfo. Describes the characteristics of a particular
+// logical display.
 message DisplayInfoProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -29,5 +30,7 @@
     optional int32 logical_height = 2;
     optional int32 app_width = 3;
     optional int32 app_height = 4;
-    optional string name = 5 [ (.android.privacy).dest = DEST_EXPLICIT ];
+    // The human-readable name of the display.
+    // Eg: "Built-in Screen"
+    optional string name = 5;
 }
diff --git a/core/proto/android/view/enums.proto b/core/proto/android/view/enums.proto
index 10785ce..0172e78 100644
--- a/core/proto/android/view/enums.proto
+++ b/core/proto/android/view/enums.proto
@@ -42,3 +42,30 @@
     // CPU is not updating it.
     DISPLAY_STATE_ON_SUSPEND = 6;
 }
+
+// Constants found in android.view.WindowManager.
+enum TransitionTypeEnum {
+    TRANSIT_NONE = 0;
+    TRANSIT_UNSET = -1;
+    TRANSIT_ACTIVITY_OPEN = 6;
+    TRANSIT_ACTIVITY_CLOSE = 7;
+    TRANSIT_TASK_OPEN = 8;
+    TRANSIT_TASK_CLOSE = 9;
+    TRANSIT_TASK_TO_FRONT = 10;
+    TRANSIT_TASK_TO_BACK = 11;
+    TRANSIT_WALLPAPER_CLOSE = 12;
+    TRANSIT_WALLPAPER_OPEN = 13;
+    TRANSIT_WALLPAPER_INTRA_OPEN = 14;
+    TRANSIT_WALLPAPER_INTRA_CLOSE = 15;
+    TRANSIT_TASK_OPEN_BEHIND = 16;
+    TRANSIT_TASK_IN_PLACE = 17;
+    TRANSIT_ACTIVITY_RELAUNCH = 18;
+    TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
+    TRANSIT_KEYGUARD_GOING_AWAY = 20;
+    TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
+    TRANSIT_KEYGUARD_OCCLUDE = 22;
+    TRANSIT_KEYGUARD_UNOCCLUDE = 23;
+    TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = 24;
+    TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = 25;
+    TRANSIT_CRASHING_ACTIVITY_CLOSE = 26;
+}
diff --git a/core/proto/android/view/remote_animation_target.proto b/core/proto/android/view/remote_animation_target.proto
index 9139f25..fb4d5bd 100644
--- a/core/proto/android/view/remote_animation_target.proto
+++ b/core/proto/android/view/remote_animation_target.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option java_package = "android.app";
 option java_multiple_files = true;
 
 package android.view;
@@ -26,7 +25,7 @@
 import "frameworks/base/core/proto/android/view/surfacecontrol.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
-/** Proto representation for RemoteAnimationTarget.java class. */
+/** Proto representation for android.view.RemoteAnimationTarget.java class. */
 message RemoteAnimationTargetProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -35,8 +34,11 @@
     optional .android.view.SurfaceControlProto leash = 3;
     optional bool is_translucent = 4;
     optional .android.graphics.RectProto clip_rect = 5;
-    optional .android.graphics.RectProto contentInsets = 6;
+    optional .android.graphics.RectProto content_insets = 6;
     optional int32 prefix_order_index = 7;
+    // The source position of the app, in screen spaces coordinates. If the
+    // position of the leash is modified from the controlling app, any animation
+    // transform needs to be offset by this amount.
     optional .android.graphics.PointProto position = 8;
     optional .android.graphics.RectProto source_container_bounds = 9;
     optional .android.app.WindowConfigurationProto window_configuration = 10;
diff --git a/core/proto/android/view/windowlayoutparams.proto b/core/proto/android/view/windowlayoutparams.proto
index 586321d..8a011e9 100644
--- a/core/proto/android/view/windowlayoutparams.proto
+++ b/core/proto/android/view/windowlayoutparams.proto
@@ -63,7 +63,7 @@
     }
     optional NeedsMenuState needs_menu_key = 22;
 
-    optional .android.view.DisplayProto.ColorMode color_mode = 23;
+    optional DisplayProto.ColorMode color_mode = 23;
     optional uint32 flags = 24;
     optional uint32 private_flags = 26;
     optional uint32 system_ui_visibility_flags = 27;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e2a5c57..8f176e8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -359,6 +359,7 @@
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_ICON" />
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST" />
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION" />
+    <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW" />
     <protected-broadcast android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
     <protected-broadcast android:name="android.net.wifi.supplicant.STATE_CHANGE" />
     <protected-broadcast android:name="android.net.wifi.p2p.STATE_CHANGED" />
@@ -606,6 +607,14 @@
     <protected-broadcast android:name="android.intent.action.DOCK_IDLE" />
     <protected-broadcast android:name="android.intent.action.DOCK_ACTIVE" />
 
+    <!-- Added in Q -->
+
+    <!-- For CarIdlenessTracker -->
+    <protected-broadcast android:name="com.android.server.jobscheduler.GARAGE_MODE_ON" />
+    <protected-broadcast android:name="com.android.server.jobscheduler.GARAGE_MODE_OFF" />
+    <protected-broadcast android:name="com.android.server.jobscheduler.FORCE_IDLE" />
+    <protected-broadcast android:name="com.android.server.jobscheduler.UNFORCE_IDLE" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
@@ -756,7 +765,8 @@
     <!-- ====================================================================== -->
     <eat-comment />
 
-    <!-- Used for runtime permissions related to the shared external storage. -->
+    <!-- Used for runtime permissions related to the shared external storage.
+         @deprecated replaced by new strongly-typed permission groups in Q. -->
     <permission-group android:name="android.permission-group.STORAGE"
         android:icon="@drawable/perm_group_storage"
         android:label="@string/permgrouplab_storage"
@@ -784,13 +794,13 @@
      grants your app this permission. If you don't need this permission, be sure your <a
      href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
      targetSdkVersion}</a> is 4 or higher.
-     <p>Protection level: dangerous
+     @deprecated replaced by new strongly-typed permission groups in Q.
      -->
     <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
         android:permissionGroup="android.permission-group.STORAGE"
         android:label="@string/permlab_sdcardRead"
         android:description="@string/permdesc_sdcardRead"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="normal" />
 
     <!-- Allows an application to write to external storage.
          <p class="note"><strong>Note:</strong> If <em>both</em> your <a
@@ -805,14 +815,87 @@
          read/write files in your application-specific directories returned by
          {@link android.content.Context#getExternalFilesDir} and
          {@link android.content.Context#getExternalCacheDir}.
-         <p>Protection level: dangerous
+         @deprecated replaced by new strongly-typed permission groups in Q.
     -->
     <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
         android:permissionGroup="android.permission-group.STORAGE"
         android:label="@string/permlab_sdcardWrite"
         android:description="@string/permdesc_sdcardWrite"
+        android:protectionLevel="normal" />
+
+    <!-- Runtime permission controlling access to the user's shared aural media
+         collection. -->
+    <permission-group android:name="android.permission-group.MEDIA_AURAL"
+        android:icon="@drawable/perm_group_aural"
+        android:label="@string/permgrouplab_aural"
+        android:description="@string/permgroupdesc_aural"
+        android:request="@string/permgrouprequest_aural"
+        android:priority="910" />
+
+    <!-- Allows an application to read the user's shared audio collection. -->
+    <permission android:name="android.permission.READ_MEDIA_AUDIO"
+        android:permissionGroup="android.permission-group.MEDIA_AURAL"
+        android:label="@string/permlab_audioRead"
+        android:description="@string/permdesc_audioRead"
         android:protectionLevel="dangerous" />
 
+    <!-- Allows an application to modify the user's shared audio collection. -->
+    <permission android:name="android.permission.WRITE_MEDIA_AUDIO"
+        android:permissionGroup="android.permission-group.MEDIA_AURAL"
+        android:label="@string/permlab_audioWrite"
+        android:description="@string/permdesc_audioWrite"
+        android:protectionLevel="dangerous" />
+
+    <!-- Runtime permission controlling access to the user's shared visual media
+         collection, including images and videos. -->
+    <permission-group android:name="android.permission-group.MEDIA_VISUAL"
+        android:icon="@drawable/perm_group_visual"
+        android:label="@string/permgrouplab_visual"
+        android:description="@string/permgroupdesc_visual"
+        android:request="@string/permgrouprequest_visual"
+        android:priority="920" />
+
+    <!-- Allows an application to read the user's shared images collection. -->
+    <permission android:name="android.permission.READ_MEDIA_IMAGES"
+        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
+        android:label="@string/permlab_imagesRead"
+        android:description="@string/permdesc_imagesRead"
+        android:protectionLevel="dangerous" />
+
+    <!-- Allows an application to modify the user's shared images collection. -->
+    <permission android:name="android.permission.WRITE_MEDIA_IMAGES"
+        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
+        android:label="@string/permlab_imagesWrite"
+        android:description="@string/permdesc_imagesWrite"
+        android:protectionLevel="dangerous" />
+
+    <!-- Allows an application to read the user's shared video collection. -->
+    <permission android:name="android.permission.READ_MEDIA_VIDEO"
+        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
+        android:label="@string/permlab_videoRead"
+        android:description="@string/permdesc_videoRead"
+        android:protectionLevel="dangerous" />
+
+    <!-- Allows an application to modify the user's shared video collection. -->
+    <permission android:name="android.permission.WRITE_MEDIA_VIDEO"
+        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
+        android:label="@string/permlab_videoWrite"
+        android:description="@string/permdesc_videoWrite"
+        android:protectionLevel="dangerous" />
+
+    <!-- Allows an application to access any geographic locations persisted in the
+         user's shared collection. -->
+    <permission android:name="android.permission.ACCESS_MEDIA_LOCATION"
+        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
+        android:label="@string/permlab_mediaLocation"
+        android:description="@string/permdesc_mediaLocation"
+        android:protectionLevel="dangerous" />
+
+    <!-- @hide @SystemApi
+         Allows an application to modify OBB files visible to other apps. -->
+    <permission android:name="android.permission.WRITE_OBB"
+        android:protectionLevel="signature|privileged" />
+
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device location                          -->
     <!-- ====================================================================== -->
@@ -1489,9 +1572,9 @@
         android:protectionLevel="signature|privileged" />
 
     <!-- @hide Allows internal management of Wi-Fi connectivity state when on
-         permission review mode.
+         wireless consent mode.
          <p>Not for use by third-party applications. -->
-    <permission android:name="android.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED"
+    <permission android:name="android.permission.MANAGE_WIFI_WHEN_WIRELESS_CONSENT_REQUIRED"
         android:protectionLevel="signature" />
 
     <!-- #SystemApi @hide Allows an app to bypass Private DNS.
@@ -1590,9 +1673,9 @@
     <permission android:name="android.permission.NFC_HANDOVER_STATUS"
         android:protectionLevel="signature|privileged" />
 
-    <!-- @hide Allows internal management of Bluetooth state when on permission review mode.
+    <!-- @hide Allows internal management of Bluetooth state when on wireless consent mode.
          <p>Not for use by third-party applications. -->
-    <permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED"
+    <permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED"
         android:protectionLevel="signature" />
 
     <!-- ================================== -->
@@ -2068,11 +2151,11 @@
 
     <!-- @SystemApi @TestApi @hide Allows an application to create/manage/remove stacks -->
     <permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
-        android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @TestApi @hide Allows an application to embed other activities -->
     <permission android:name="android.permission.ACTIVITY_EMBEDDING"
-                android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to start any activity, regardless of permission
          protection or exported state.
@@ -2305,7 +2388,7 @@
     <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
         android:protectionLevel="signature" />
 
-    <!-- @SystemApi Allows an application to modify the current configuration, such
+    <!-- @SystemApi @TestApi Allows an application to modify the current configuration, such
          as locale. -->
     <permission android:name="android.permission.CHANGE_CONFIGURATION"
         android:protectionLevel="signature|privileged|development" />
@@ -2332,7 +2415,7 @@
     <permission android:name="android.permission.WRITE_GSERVICES"
         android:protectionLevel="signature|privileged" />
 
-    <!-- @SystemApi Allows an application to call
+    <!-- @SystemApi @TestApi Allows an application to call
         {@link android.app.ActivityManager#forceStopPackage}.
         @hide -->
     <permission android:name="android.permission.FORCE_STOP_PACKAGES"
@@ -2437,7 +2520,8 @@
     <permission android:name="android.permission.ASEC_RENAME"
         android:protectionLevel="signature" />
 
-    <!-- @SystemApi Allows applications to write the apn settings.
+    <!-- @SystemApi Allows applications to write the apn settings and read sensitive fields of
+         an existing apn settings like user and password.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_APN_SETTINGS"
         android:protectionLevel="signature|privileged" />
@@ -3247,6 +3331,13 @@
     <permission android:name="android.permission.MODIFY_AUDIO_ROUTING"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an application to modify what effects are applied to all audio
+         (matching certain criteria) from any application.
+         <p>Not for use by third-party applications.</p>
+         @hide -->
+    <permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"
+        android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows an application to capture video output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
@@ -3499,6 +3590,10 @@
     <permission android:name="android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE"
                 android:protectionLevel="signature" />
 
+    <!-- @hide Internal permission to allows an application to access card content provider. -->
+    <permission android:name="android.permission.WRITE_SETTINGS_HOMEPAGE_DATA"
+                android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows applications to set a live wallpaper.
          @hide XXX Change to signature once the picker is moved to its
          own apk as Ghod Intended. -->
diff --git a/core/res/res/anim/lock_screen_behind_enter_fade_in.xml b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
index e9475f5..ff95aea 100644
--- a/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
+++ b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
@@ -16,7 +16,6 @@
   -->
 
 <alpha xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="#ff000000"
     android:detachWallpaper="true"
     android:shareInterpolator="false"
     android:interpolator="@interpolator/linear"
diff --git a/core/res/res/drawable-hdpi/ic_grayedout_printer.png b/core/res/res/drawable-hdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/core/res/res/drawable-hdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_grayedout_printer.png b/core/res/res/drawable-mdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/core/res/res/drawable-mdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_grayedout_printer.png b/core/res/res/drawable-xhdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/core/res/res/drawable-xhdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/emergency_icon.xml b/core/res/res/drawable/emergency_icon.xml
index b2ffa2b..c142be3 100644
--- a/core/res/res/drawable/emergency_icon.xml
+++ b/core/res/res/drawable/emergency_icon.xml
@@ -18,7 +18,7 @@
         android:height="24.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"
-        android:tint="?attr/colorControlNormal">
+        android:tint="?attr/colorError">
     <path
         android:fillColor="#FF000000"
         android:pathData="M6.8,17.3C5.3,15.9 4.5,14.0 4.5,12.0c0.0,-2.0 0.8,-3.8 2.1,-5.2l1.4,1.4c-1.0,1.0 -1.6,2.4 -1.6,3.8c0.0,1.5 0.6,2.9 1.6,3.9L6.8,17.3z"/>
diff --git a/core/res/res/drawable/ic_faster_emergency.xml b/core/res/res/drawable/ic_faster_emergency.xml
new file mode 100644
index 0000000..680dfce
--- /dev/null
+++ b/core/res/res/drawable/ic_faster_emergency.xml
@@ -0,0 +1,31 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?attr/colorError">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M19,3H5C3.9,3,3.01,3.9,3.01,5L3,19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19L5,19V5h14V19z" />
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M 10.5 17 L 13.5 17 L 13.5 13.5 L 17 13.5 L 17 10.5 L 13.5 10.5 L 13.5 7 L 10.5 7 L 10.5 10.5 L 7 10.5 L 7 13.5 L 10.5 13.5 Z" />
+    <path
+        android:pathData="M0,0h24v24H0V0z" />
+
+</vector>
diff --git a/core/res/res/drawable/perm_group_aural.xml b/core/res/res/drawable/perm_group_aural.xml
new file mode 100644
index 0000000..0465e98
--- /dev/null
+++ b/core/res/res/drawable/perm_group_aural.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<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="M20,2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-2,5h-3v5.5c0,1.38 -1.12,2.5 -2.5,2.5S10,13.88 10,12.5s1.12,-2.5 2.5,-2.5c0.57,0 1.08,0.19 1.5,0.51V5h4v2zM4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6z"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_visual.xml b/core/res/res/drawable/perm_group_visual.xml
new file mode 100644
index 0000000..bf9a0b1
--- /dev/null
+++ b/core/res/res/drawable/perm_group_visual.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<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="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z"/>
+</vector>
diff --git a/core/res/res/layout/resolver_different_item_header.xml b/core/res/res/layout/resolver_different_item_header.xml
index 5889136..7d9ffd7 100644
--- a/core/res/res/layout/resolver_different_item_header.xml
+++ b/core/res/res/layout/resolver_different_item_header.xml
@@ -29,6 +29,5 @@
     android:paddingEnd="16dp"
     android:paddingTop="8dp"
     android:paddingBottom="8dp"
-    android:background="@color/white"
     android:elevation="8dp"
     />
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index 40c9941..373354a 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -30,7 +30,7 @@
         android:layout_height="wrap_content"
         android:layout_alwaysShow="true"
         android:elevation="8dp"
-        android:background="@color/white">
+        android:background="?attr/colorBackgroundFloating">
 
         <TextView
             android:id="@+id/profile_button"
@@ -69,7 +69,7 @@
         android:id="@+id/resolver_list"
         android:clipToPadding="false"
         android:scrollbarStyle="outsideOverlay"
-        android:background="@color/white"
+        android:background="?attr/colorBackgroundFloating"
         android:elevation="8dp"
         android:nestedScrollingEnabled="true"
         android:scrollIndicators="top|bottom"
@@ -78,7 +78,7 @@
     <TextView android:id="@+id/empty"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
-              android:background="@color/white"
+              android:background="?attr/colorBackgroundFloating"
               android:elevation="8dp"
               android:layout_alwaysShow="true"
               android:text="@string/noApplications"
@@ -99,7 +99,7 @@
         android:orientation="horizontal"
         android:layoutDirection="locale"
         android:measureWithLargestChild="true"
-        android:background="@color/white"
+        android:background="?attr/colorBackgroundFloating"
         android:paddingTop="8dp"
         android:paddingBottom="8dp"
         android:paddingStart="12dp"
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 8101183..740a7eb 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -29,7 +29,7 @@
         android:layout_height="wrap_content"
         android:layout_alwaysShow="true"
         android:orientation="vertical"
-        android:background="@color/white"
+        android:background="?attr/colorBackgroundFloating"
         android:elevation="8dp">
 
         <LinearLayout
@@ -111,7 +111,6 @@
             android:paddingBottom="8dp"
             android:paddingStart="12dp"
             android:paddingEnd="12dp"
-            android:background="@color/white"
             android:elevation="8dp">
 
             <Button
@@ -151,7 +150,7 @@
         android:id="@+id/resolver_list"
         android:clipToPadding="false"
         android:scrollbarStyle="outsideOverlay"
-        android:background="@color/white"
+        android:background="?attr/colorBackgroundFloating"
         android:elevation="8dp"
         android:nestedScrollingEnabled="true"
         android:divider="@null" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 5be78cf..e136d2e 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -133,7 +133,7 @@
     <item msgid="4397097370387921767">"%s Wi-Fi-oproep"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Af"</string>
-    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Verkieslik Wi-Fi"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Verkies Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Verkies mobiel"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Net Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nie aangestuur nie"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Vliegtuigmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Vliegtuigmodus is AAN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Vliegtuigmodus is AF"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Batterybespaarder"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Batterybespaarder is AF"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Batterybespaarder is AAN"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Instellings"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Help"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Stembystand"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Liggaamsensors"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"toegang te verkry tot sensordata oor jou lewenstekens"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot sensordata oor jou lewenstekens?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musiek"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"toegang tot jou musiek"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou musiek?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Foto\'s en video\'s"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"toegang tot jou foto\'s en video\'s"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou foto\'s en video\'s?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Venster-inhoud ophaal"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Die inhoud ondersoek van \'n venster waarmee jy interaksie het."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Verken deur raak aanskakel"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Laat die program toe om metodes te benut om vingerafdruksjablone vir gebruik by te voeg en uit te vee."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gebruik vingerafdrukhardeware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Laat die program toe om vingerafdrukhardeware vir stawing te gebruik"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"lees jou musiekversameling"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Laat die program toe om jou musiekversameling te lees."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"wysig jou musiekversameling"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Laat die program toe om jou musiekversameling te wysig."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"lees jou videoversameling"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Laat die program toe om jou videoversameling te lees."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"wysig jou videoversameling"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Laat die program toe om jou videoversameling te wysig."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"lees jou fotoversameling"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Laat die program toe om jou fotoversameling te lees."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"wysig jou fotoversameling"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Laat die program toe om jou fotoversameling te wysig."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"lees liggings in jou mediaversameling"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Laat die program toe om liggings in jou mediaversameling te lees."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Gedeeltelike vingerafdruk is bespeur. Probeer asseblief weer."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kon nie vingerafdruk verwerk nie. Probeer asseblief weer."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Vingerafdruksensor is vuil. Maak dit skoon en probeer weer."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Stoor <xliff:g id="TYPE">%1$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Dateer op na &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Dateer <xliff:g id="TYPE">%1$s</xliff:g> op na &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Dateer <xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> op na &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Dateer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> op na &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Stoor"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nee, dankie"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Dateer op"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"wagwoord"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adres"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredietkaart"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 4c6a469..5a7e643 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"የአውሮፕላን ሁነታ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"የአውሮፕላንሁነታ በርቷል"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"የአውሮፕላንሁነታ ጠፍቷል"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"የባትሪ ኃይል ቆጣቢ"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"የባትሪ ኃይል ቆጣቢ ጠፍቷል"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"የባትሪ ኃይል ቆጣቢ በርቷል"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ቅንብሮች"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"ደግፍ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"የድምጽ እርዳታ"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"የሰውነት ዳሳሾች"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ስለአስፈላጊ ምልክቶችዎ ያሉ የዳሳሽ ውሂብ ይድረሱ"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የሰውነትዎ መሠረታዊ ምልክቶች የዳሳሽ ውሂብ እንዲደርስ ይፈቀድለት?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"ሙዚቃ"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"ሙዚቃዎን መድረስ"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ቀን ሙዚቃዎን እንዲደርስ ይፈቀድለት?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ፎቶዎች እና ቪዲዮዎች"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"የእርስዎን ፎቶዎች እና ቪዲዮዎች መድረስ"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የእርስዎን ፎቶዎች እና ቪዲዮዎች እንዲደርስ ይፈቀድለት?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"የመስኮት ይዘት ሰርስረው ያውጡ"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"መስተጋበር የሚፈጥሩት የመስኮት ይዘት ይመርምሩ።"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"በመንካት ያስሱን ያብሩ"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"መተግበሪያው ጥቅም ላይ እንዲውሉ የጣት አሻራ ቅንብር ደንቦችን ለማከል እና ለመሰረዝ የሚያስችሉ ስልቶችን እንዲያስጀምር ያስችለዋል።"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"የጣት አሻራ ሃርድዌርን ተጠቀም"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"መተግበሪያው የጣት አሻራ ሃርድዌር ለማረጋገጥ ስራ እንዲጠቀም ያስችለዋል"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"የሙዚቃ ስብስብዎን ማንበብ"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"መተግበሪያው የሙዚቃ ስብስብዎን እንዲያነብብ ያስችለዋል።"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"የሙዚቃ ስብስብዎን መቀየር"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"መተግበሪያው የሙዚቃ ስብስብዎን እንዲቀይረው ያስችለዋል።"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"የቪዲዮ ስብስብዎን ማንበብ"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"መተግበሪያው የቪዲዮ ስብስብዎን እንዲያነብብ ያስችለዋል።"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"የቪዲዮ ስብስብዎን መቀየር"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"መተግበሪያው የፎቶ ስብስብዎን እንዲቀይረው ያስችለዋል።"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"የፎቶ ስብስብዎን ማንበብ"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"መተግበሪያው የፎቶ ስብስብዎን እንዲያነብብ ያስችለዋል።"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"የፎቶ ስብስብዎን መቀየር"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"መተግበሪያው የፎቶ ስብስብዎን እንዲቀይረው ያስችለዋል።"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"አካባቢዎችን ከሚዲያ ስብስብዎ ማንበብ"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"መተግበሪያው አካባቢዎችን ከሚዲያ ስብስብዎ እንዲያነብብ ያስችለዋል።"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ከፊል የጣት አሻራ ተገኝቷል። እባክዎ እንደገና ይሞክሩ።"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ጣት አሻራን መስራት አልተቻለም። እባክዎ እንደገና ይሞክሩ።"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"የጣት አሻራ ዳሳሽ ቆሽሿል። እባክዎ ያጽዱት እና እንደገና ይሞክሩ።"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ይቀመጥ?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> እና <xliff:g id="TYPE_1">%2$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ይቀመጡ?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g> እና <xliff:g id="TYPE_2">%3$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ይቀመጡ?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"ወደ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ይዘመን?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ይዘመን?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> እና <xliff:g id="TYPE_1">%2$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ይዘመኑ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g> እና <xliff:g id="TYPE_2">%3$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ይዘመኑ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"አስቀምጥ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"አይ፣ አመሰግናለሁ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"አዘምን"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"የይለፍ ቃል"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"አድራሻ"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ክሬዲት ካርድ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 4c3aa00..d46f758 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -138,7 +138,7 @@
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"إيقاف"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"‏شبكة Wi-Fi مفضّلة"</string>
-    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"مفضَّل للجوّال"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"شبكة بيانات الجوال مفضَّلة"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"‏Wi-Fi فقط"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: لم تتم إعادة التوجيه"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -248,9 +248,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"وضع الطائرة"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"وضع الطائرة قيد التشغيل"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"وضع الطائرة متوقف"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"توفير شحن البطارية"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"توفير شحن البطارية غير مفعّل"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"توفير شحن البطارية مفعّل"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"الإعدادات"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"مساعدة"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"المساعد الصوتي"</string>
@@ -315,6 +312,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"أجهزة استشعار الجسم"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"الوصول إلى بيانات المستشعر حول علاماتك الحيوية"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالدخول إلى بيانات المستشعر حول علاماتك الحيوية؟"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"الموسيقى"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"الوصول إلى الموسيقى"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الموسيقى؟"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"الصور والفيديوهات"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"الوصول إلى صورك وفيديوهاتك"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى صورك وفيديوهاتك؟"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"استرداد محتوى النافذة"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"فحص محتوى نافذة يتم التفاعل معها"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"تشغيل الاستكشاف باللمس"</string>
@@ -509,6 +512,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"للسماح للتطبيق باستدعاء طرق لإضافة نماذج من بصمات الأصابع وحذفها."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"لاستخدام أجهزة بصمة الإصبع"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"للسماح للتطبيق باستخدام أجهزة بصمة الإصبع للمصادقة"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"قراءة مجموعتك الموسيقية"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"للسماح للتطبيق بقراءة مجموعتك الموسيقية."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"تعديل مجموعتك الموسيقية"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"للسماح للتطبيق بتعديل مجموعتك الموسيقية."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"قراءة مجموعة الفيديو التابعة لك"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"للسماح للتطبيق بقراءة مجموعة الفيديوهات التابعة لك."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"تعديل مجموعة الفيديو التابعة لك"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"يسمح للتطبيق بتعديل مجموعة الفيديوهات التابعة لك."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"قراءة مجموعة صورك"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"للسماح للتطبيق بقراءة مجموعة صورك."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"تعديل مجموعة صورك"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"للسماح للتطبيق بتعديل مجموعة صورك."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"قراءة المواقع من مجموعة الوسائط التابعة لك"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"للسماح للتطبيق بقراءة المواقع من مجموعة الوسائط التابعة لك."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"تم اكتشاف بصمة الإصبع بشكل جزئي؛ يرجى إعادة المحاولة."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"تعذرت معالجة بصمة الإصبع. يُرجى إعادة المحاولة."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"جهاز استشعار بصمات الأصابع متسخ، يرجى تنظيفه وإعادة المحاولة."</string>
@@ -2015,8 +2032,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‏هل تريد حفظ <xliff:g id="TYPE">%1$s</xliff:g> في &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;؟"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‏هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> في &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;؟"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‏هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> و<xliff:g id="TYPE_2">%3$s</xliff:g> في &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;؟"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"‏هل تريد التعديل إلى &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;؟"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‏هل تريد تعديل <xliff:g id="TYPE">%1$s</xliff:g> إلى &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;؟"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‏هل تريد تعديل <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> إلى &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;؟"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‏هل تريد تعديل <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> و<xliff:g id="TYPE_2">%3$s</xliff:g> إلى &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;؟"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"حفظ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"لا، شكرًا"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"تعديل"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"كلمة مرور"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"عنوان"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"بطاقة ائتمان"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index edd4f88..10b7da43 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"এয়াৰপ্লেইন ম\'ড"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"এয়াৰপ্লেইন ম\'ড অন কৰা আছে"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"এয়াৰপ্লেইন ম\'ড অফ কৰা আছে"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"বেটাৰি সঞ্চয়কাৰী"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"বেটাৰি সঞ্চয়কাৰী অফ হৈ আছে"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"বেটাৰি সঞ্চয়কাৰী অন হৈ আছে"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ছেটিংসমূহ"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"সহায়"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"কণ্ঠধ্বনিৰে সহায়"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"শৰীৰৰ ছেন্সৰসমূহ"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগসমূহৰ অৱস্থাৰ বিষয়ে ছেন্সৰৰ ডেটা লাভ কৰিব পাৰে"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগসমূহৰ অৱস্থাৰ বিষয়ে ছেন্সৰৰ ডেটা লাভ কৰিবলৈ অনুমতি দিবনে?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"সংগীত"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"আপোনাৰ সংগীত এক্সেছ কৰিবলৈ"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ সংগীত এক্সেছ কৰিবলৈ দিবনে?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ফট\' আৰু ভিডিঅ’সমূহ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"আপোনাৰ ফট’ আৰু ভিডিঅ’সমূহ এক্সেছ কৰিবলৈ"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ ফট’ আৰু ভিডিঅ’সমূহ এক্সেছ কৰিবলৈ দিবনে?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ৱিণ্ড\' সমল বিচাৰি উলিয়াওক"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"আপুনি যোগাযোগ কৰি থকা ৱিণ্ড\'খনৰ সমল পৰীক্ষা কৰক।"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"স্পৰ্শৰদ্বাৰা অন্বেষণ কৰাৰ সুবিধা অন কৰক"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ফিংগাৰপ্ৰিণ্ট টেম্প্লেটসমূহ যোগ কৰা বা মচাৰ পদ্ধতিসমূহ কামত লগাবলৈ নিৰ্দেশ দিবলৈ এপটোক অনুমতি দিয়ে।"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ ব্যৱহাৰ কৰিব পাৰে"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"প্ৰমাণীকৰণৰ বাবে ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ ব্য়ৱহাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"নিজৰ সংগীত সংগ্ৰহ পঢ়িবলৈ"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"এপক আপোনাৰ সংগীত সংগ্ৰহ পঢ়িবলৈ দিয়ে।"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"আপোনাৰ সংগীত সংগ্ৰহ সালসলনি কৰিবলৈ"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"এপক আপোনাৰ সংগীত সংগ্ৰহ সালসলনি কৰিবলৈ দিয়ে।"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"আপোনাৰ ভিডিঅ’ সংগ্ৰহ পঢ়িবলৈ"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"এপক আপোনাৰ ভিডিঅ’ সংগ্ৰহ পঢ়িবলৈ দিয়ে।"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"আপোনাৰ ভিডিঅ’ সংগ্ৰহ সালসলনি কৰিবলৈ"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"এপক আপোনাৰ ভিডিঅ’ সংগ্ৰহ সালসলনি কৰিবলৈ দিয়ে।"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"আপোনাৰ ফট’ সংগ্ৰহ পঢ়িবলৈ"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"এপক আপোনাৰ ফট’ সংগ্ৰহ পঢ়িবলৈ দিয়ে।"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"আপোনাৰ ফট’ সংগ্ৰহ সালসলনি কৰিবলৈ"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"এপক আপোনাৰ ফট’ সংগ্ৰহ সালসলনি কৰিবলৈ দিয়ে।"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"আপোনাৰ মিডিয়া সংগ্ৰহৰ অৱস্থান পঢ়িবলৈ"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"এপক আপোনাৰ মিডিয়া সংগ্ৰহৰ অৱস্থান পঢ়িবলৈ দিয়ে।"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ফিংগাৰপ্ৰিণ্ট আংশিকভাৱে চিনাক্ত কৰা হৈছে। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ফিগাৰপ্ৰিণ্টৰ প্ৰক্ৰিয়া সম্পাদন কৰিবপৰা নগ\'ল। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো লেতেৰা হৈ আছে। অনুগ্ৰহ কৰি পৰিষ্কাৰ কৰি আকৌ চেষ্টা কৰক।"</string>
@@ -1876,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>ক &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;ত ছেভ কৰিবনে?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> আৰু <xliff:g id="TYPE_1">%2$s</xliff:g>ক &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;ত ছেভ কৰিবনে?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, আৰু <xliff:g id="TYPE_2">%3$s</xliff:g>ক &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;ত ছেভ কৰিবনে?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"আপডে’ট কৰি &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; বনাবনে?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>ক আপডে’ট কৰি &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; বনাবনে?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> আৰু <xliff:g id="TYPE_1">%2$s</xliff:g>ক আপডে’ট কৰি &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; বনাবনে?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> আৰু <xliff:g id="TYPE_2">%3$s</xliff:g>ক আপডে’ট কৰি to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; বনাবনে?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ছেভ কৰক"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"নালাগে, ধন্যবাদ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"আপডে’ট কৰক"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"পাছৱৰ্ড"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ঠিকনা"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ক্ৰেডিট কাৰ্ড"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 645c5ca..6464c61 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Təyyarə rejimi"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uçuş rejimi açıqdır"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Təyyarə rejimi qapalıdır"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Batareya qənaəti"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Batareya qənaəti DEAKTİVDİR"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Batareya qənaəti AKTİVDİR"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Ayarlar"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Yardım"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Səs Yardımçısı"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Bədən Sensorları"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"Həyati əlamətlər haqqında sensor dataya daxil olun"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə həyati əlamətlər haqqında sensor dataya daxil olmaq icazəsi verilsin?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musiqi"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"musiqiyə daxil olun"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin musiqiyə daxil olmağına icazə verilsin?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Foto və Videolar"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"foto və videolara daxil olun"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin foto və videolarınıza daxil olmağına icazə verilsin?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Pəncərənin məzmununu əldə edin"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Əlaqədə olduğunuz pəncərənin məzmununu nəzərdən keçirin."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Toxunaraq Kəşf et funksiyasını yandırın"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Proqrama istifadə üçün barmaq izi şablonlarını əlavə etmək və silmək üçün üsullara müraciət etməyə imkan verir."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"barmaq izi avadanlığından istifadə edin"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Proqrama əsilliyi yoxlama üçün barmaq izi avadanlığından istifadə etməyə imkan verir"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"musiqi kolleksiyanızı oxuyun"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Tətbiqin musiqi kolleksiyanızı oxumasına icazə verir."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"musiqi kolleksiyanıza düzəliş edin"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Tətbiqin musiqi kolleksiyanıza düzəliş etməsinə icazə verir."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"video kolleksiyanızı oxuyun"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Tətbiqin video kolleksiyanızı oxumasına icazə verin."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"video kolleksiyanıza düzəliş edin"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Tətbiqin video kolleksiyanıza düzəliş etməsinə icazə verin."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"foto kolleksiyanızı oxuyun"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Tətbiqin foto kolleksiyanızı oxumasına icazə verir."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"foto kolleksiyanıza düzəliş edin"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Tətbiqin foto kolleksiyanıza düzəliş etməsinə icazə verir."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"media kolleksiyanızdan məkanları oxuyun"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Tətbiqin media kolleksiyanızdan məkanları oxumasına icazə verin."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmaq qismən müəyyən olundu. Lütfən, yenidən cəhd edin."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Barmaq izi tanınmadı. Lütfən, yenidən cəhd edin."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Barmaq izi sensoru çirklidir. Lütfən, təmizləyin və yenidən cəhd edin."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;b&gt; etiketində yadda saxlansın?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> və <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; etiketində yadda saxlansın?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> və <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; etiketində yadda saxlansın?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; etiketində yenilənsin?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;b&gt; etiketində yenilənsin?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> və <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; etiketində yenilənsin?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> və <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; etiketində yenilənsin?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Yadda saxlayın"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Xeyr, çox sağ olun"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Yeniləyin"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"parol"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ünvan"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredit kartı"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index a1310a2..4d31b1b 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -239,9 +239,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim rada u avionu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim rada u avionu je UKLJUČEN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim rada u avionu je ISKLJUČEN"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Ušteda baterije"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Ušteda baterije je ISKLJUČENA"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Ušteda baterije je UKLJUČENA"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Podešavanja"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Pomoć"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glasovna pomoć"</string>
@@ -306,6 +303,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Senzori za telo"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"pristupa podacima senzora o vitalnim funkcijama"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Želite li da omogućite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;pristupa podacima senzora o vitalnim funkcijama?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muzika"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"pristup muzici"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Želite li da omogućite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa muzici?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Slike i video snimci"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"pristup slikama i video snimcima"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Želite li da omogućite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa slikama i video snimcima?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"da preuzima sadržaj prozora"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Proverava sadržaj prozora sa kojim ostvarujete interakciju."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"da uključi Istraživanja dodirom"</string>
@@ -500,6 +503,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Dozvoljava aplikaciji da aktivira metode za dodavanje i brisanje šablona otisaka prstiju koji će se koristiti."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"koristi hardver za otiske prstiju"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Dozvoljava aplikaciji da koristi hardver za otiske prstiju radi potvrde autentičnosti"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"čitanje muzičke kolekcije"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Dozvoljava aplikaciji da čita muzičku kolekciju."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"izmena muzičke kolekcije"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Dozvoljava aplikaciji da menja muzičku kolekciju."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"čitanje video kolekcije"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Dozvoljava aplikaciji da čita video kolekciju."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"izmena video kolekcije"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Dozvoljava aplikaciji da menja video kolekciju."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"čitanje kolekcije slika"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Dozvoljava aplikaciji da čita kolekciju slika."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"izmena kolekcije slika"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Dozvoljava aplikaciji da menja kolekciju slika."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"čitanje lokacija iz medijske kolekcije"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Dozvoljava aplikaciji da čita lokacije iz medijske kolekcije."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Otkriven je delimični otisak prsta. Probajte ponovo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nije uspela obrada otiska prsta. Probajte ponovo."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Senzor za otiske prstiju je prljav. Očistite ga i pokušajte ponovo."</string>
@@ -1910,8 +1927,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Želite li da sačuvate stavku <xliff:g id="TYPE">%1$s</xliff:g> u: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> u: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Želite li da ažurirate na &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Želite li da ažurirate stavku <xliff:g id="TYPE">%1$s</xliff:g> na &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Želite li da ažurirate stavke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> na &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Želite li da ažurirate stavke <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> na &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Ažuriraj"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"lozinka"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditna kartica"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index f990bef..77223d7 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -242,9 +242,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Рэжым палёту"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Уключаны рэжым \"У самалёце\""</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Рэжым \"У самалёце\" адключаны"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Эканомія зараду"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Рэжым эканоміі зараду выключаны"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Рэжым эканоміі зараду ўключаны"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Налады"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Дапамога"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Галас. дапамога"</string>
@@ -309,6 +306,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Датчыкі цела"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"атрымліваць з датчыка даныя асноўных фізіялагічных паказчыкаў"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да даных з датчыкаў пра вашы асноўныя фізіялагічныя паказчыкі?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Музыка"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"доступ да музыкі"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да музыкі?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Фота і відэа"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"доступ да фота і відэа"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да фота і відэа?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Атрымліваць змесціва вакна"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Аналізаваць змесціва актыўнага вакна."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Уключаць Азнаямленне дотыкам"</string>
@@ -503,6 +506,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Дазваляе праграме выкарыстоўваць спосабы дадання і выдалення шаблонаў адбіткаў пальцаў для выкарыстання."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"выкарыстоўваць апаратныя сродкі для адбіткаў пальцаў"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дазваляе праграме выкарыстоўваць апаратныя сродкі распазнання адбіткаў пальцаў для аўтэнтыфікацыі"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"паказваць музычную калекцыю"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Праграма зможа паказваць музычную калекцыю."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"змяняць музычную калекцыю"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Праграма зможа змяняць музычную калекцыю."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"паказваць відэакалекцыю"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Праграма зможа паказваць відэакалекцыю."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"змяняць відэакалекцыю"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Праграма зможа змяняць відэакалекцыю."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"паказваць фотакалекцыю"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Праграма зможа паказваць фотакалекцыю."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"змяняць фотакалекцыю"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Праграма зможа змяняць фотакалекцыю."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"паказваць месцазнаходжанне ў калекцыі мультымедыя"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Праграма зможа паказваць месцазнаходжанне ў калекцыі мультымедыя."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Выяўлена частка адбіткаў пальцаў. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не атрымалася апрацаваць адбітак пальца. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Датчык адбіткаў пальцаў брудны. Ачысціце яго і паспрабуйце яшчэ раз."</string>
@@ -1945,8 +1962,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Захаваць <xliff:g id="TYPE">%1$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Захаваць <xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Захаваць <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Абнавіць у &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Абнавіць <xliff:g id="TYPE">%1$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Абнавіць <xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Абнавіць <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Захаваць"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, дзякуй"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Абнавіць"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"пароль"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"адрас"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"крэдытная картка"</string>
@@ -1966,7 +1988,7 @@
     <string name="mmcc_imsi_unknown_in_hlr_msim_template" msgid="5636464607596778986">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> адсутнічае"</string>
     <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"Дзеянні з SIM <xliff:g id="SIMNUMBER">%d</xliff:g> не дазволены"</string>
     <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"Дзеянні з SIM <xliff:g id="SIMNUMBER">%d</xliff:g> не дазволены"</string>
-    <string name="popup_window_default_title" msgid="4874318849712115433">"Выплыўное акно"</string>
+    <string name="popup_window_default_title" msgid="4874318849712115433">"Усплывальнае акно"</string>
     <string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"Ярлык адносіцца да старэйшай версіі праграмы або несумяшчальны з ёю"</string>
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Не атрымалася аднавіць ярлык, бо праграма не падтрымлівае рэзервовае капіраванне і аднаўленне"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 3142833..3fc31f0 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Самолетен режим"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Самолетният режим е ВКЛЮЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Самолетният режим е ИЗКЛЮЧЕН"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Режим за запазване на батерията"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Режимът за запазване на батерията е ИЗКЛЮЧЕН"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Режимът за запазване на батерията е ВКЛЮЧЕН"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Настройки"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Помощ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Гласова помощ"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Телесни сензори"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"достъп до сензорните данни за жизнените ви показатели"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до данните от сензорите за жизнените ви показатели?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Музика"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"достъп до музиката ви"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до музиката ви?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Снимки и видеоклипове"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"достъп до снимките и видеоклиповете ви"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до снимките и видеоклиповете ви?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Извличане на съдържанието от прозореца"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Инспектиране на съдържанието на прозорец, с който взаимодействате."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Включване на изследването чрез докосване"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Разрешава на приложението да извиква начини за добавяне и изтриване на шаблони за отпечатъци, които да се използват."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"използване на хардуера за отпечатъци"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Разрешава на приложението да използва хардуера за отпечатъци с цел удостоверяване"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"да чете музикалната ви колекция"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Разрешава на приложението да чете музикалната ви колекция."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"да променя музикалната ви колекция"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Разрешава на приложението да променя музикалната ви колекция."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"да чете видеоколекцията ви"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Разрешава на приложението да чете видеоколекцията ви."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"да променя видеоколекцията ви"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Разрешава на приложението да променя видеоколекцията ви."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"да чете колекцията ви от снимки"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Разрешава на приложението да чете колекцията ви от снимки."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"да променя колекцията ви от снимки"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Разрешава на приложението да променя колекцията ви от снимки."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"да чете местоположенията от мултимедийната ви колекция"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Разрешава на приложението да чете местоположенията от мултимедийната ви колекция."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Открит е частичен отпечатък. Моля, опитайте отново."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Отпечатъкът не можа да се обработи. Моля, опитайте отново."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Сензорът за отпечатъци е мръсен. Моля, почистете го и опитайте отново."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> да се запази ли в/ъв &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> да се запазят ли в/ъв &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> да се запазят ли в/ъв &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Да се актуализира ли в(ъв) &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> да се актуализира ли в(ъв) &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> да се актуализират ли в(ъв) &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> да се актуализират ли в(ъв) &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Запазване"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, благодаря"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Актуализиране"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"Паролата"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"Адресът"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Кредитната карта"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 410d2c6..e7990ca 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"বিমান মোড"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"বিমান মোড চালু করা আছে"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"বিমান মোড বন্ধ করা আছে"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"ব্যাটারি সেভার"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ব্যাটারি সেভার বন্ধ আছে"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"ব্যাটারি সেভার চালু আছে"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"সেটিংস"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"সহযোগিতা"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ভয়েস সহায়তা"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"বডি সেন্সরগুলি"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"আপনার অত্যাবশ্যক লক্ষণগুলির সম্পর্কে সেন্সর ডেটা অ্যাক্সেস করে"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে সেন্সর থেকে আপনার ভাইটাল সাইনের ডেটা অ্যাক্সেস করতে দেবেন?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"মিউজিক"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"আপনার মিউজিকে অ্যাক্সেস করুন"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার মিউজিকে অ্যাক্সেস দেবেন?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ফটো ও ভিডিও"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"আপনার ফটো ও ভিডিও অ্যাক্সেস করুন"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"আপনার ফটো ও ভিডিওতে &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে অ্যাক্সেস দেবেন?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"উইন্ডোর কন্টেন্ট পুনরুদ্ধার করে"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"আপনি ইন্টারঅ্যাক্ট করছেন এমন একটি উইন্ডোর সামগ্রীকে সযত্নে নিরীক্ষণ করে৷"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"স্পর্শের মাধ্যমে অন্বেষণ করা চালু করুন"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ব্যবহার করার জন্য আঙ্গুলের ছাপের টেম্প্লেটগুলি যোগ করা এবং মোছার পদ্ধতিগুলি গ্রহন করতে অ্যাপ্লিকেশানটিতে অমুমতি দেয়৷"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার ব্যবহার করুন"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"অনুমোদনের জন্য আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার ব্যবহার করতে অ্যাপ্লিকেশানটিতে অনুমতি দেয়"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"আপনার মিউজিক সংগ্রহ পড়ুন"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"অ্যাপকে আপনার মিউজিক সংগ্রহ পড়ার অনুমতি দিন।"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"আপনার মিউজিক সংগ্রহ পরিবর্তন করুন"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"আপনার মিউজিক সংগ্রহ পরিবর্তন করতে অ্যাপকে অনুমতি দিন।"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"আপনার ভিডিও সংগ্রহ পড়ুন"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"অ্যাপকে আপনার ভিডিও সংগ্রহ দেখার অনুমতি দিন।"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"আপনার ভিডিও সংগ্রহ পরিবর্তন করুন"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"আপনার ভিডিও সংগ্রহ পরিবর্তন করতে অ্যাপকে অনুমতি দিন।"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"আপনার ছবি সংগ্রহ পড়ুন"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"আপনার ফটো সংগ্রহ পড়ার অনুমতি অ্যাপকে দিন।"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"আপনার ফটো সংগ্রহ পরিবর্তন করুন"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"অ্যাপকে আপনার ফটো সংগ্রহ পরিবর্তন করার অনুমতি দিন।"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ডিয়া সংগ্রহ থেকে লোকেশন দেখতে দিন"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"আপনার মিডিয়া সংগ্রহ থেকে লোকেশন দেখতে অ্যাপকে অনুমতি দিন।"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"আঙ্গুলের ছাপ আংশিক শনাক্ত করা হয়েছে৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"আঙ্গুলের ছাপ প্রক্রিয়া করা যায়নি৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"আঙ্গুলের ছাপ নেওয়ার সেন্সরটি অপরিস্কার৷ অনুগ্রহ করে পরিষ্কার করে আবার চেষ্টা করুন৷"</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"আঙ্গুলের ছাপ আইকন"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"ফেস যাচাইকরণ হার্ডওয়্যার পরিচালনা করুন"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"ব্যবহার করার জন্য ফেস টেম্পলেট যোগ করা এবং মোছার পদ্ধতি গ্রহণ করতে অ্যাপটিকে অনুমতি দেয়৷"</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"ফেস যাচাইকরণ হার্ডওয়্যার ব্যবহার করুন"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"প্রমাণীকরণের জন্য ফেস যাচাইকরণ হার্ডওয়্যার ব্যবহার করার অনুমতি অ্যাপটিকে দেয়"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"ফেস প্রক্রিয়া করা যায়নি৷ আবার চেষ্টা করুন৷"</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"ফেসটি খুব উজ্জ্বল লাগছে। কম আলোতে চেষ্টা করুন।"</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"ফেসটি খুব অন্ধকার লাগছে। বেশি আলোতে চেষ্টা করুন।"</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"অনুগ্রহ করে ফেস থেকে সেন্সরটি দূরে সরান।"</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"অনুগ্রহ করে ফেসের কাছাকাছি সেন্সরটি আনুন।"</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"অনুগ্রহ করে সেন্সরটি উঁচুতে নিয়ে যান।"</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"অনুগ্রহ করে সেন্সরটি নিচে নিয়ে যান।"</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"অনুগ্রহ করে সেন্সরটি ডান দিকে নিয়ে যান।"</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"অনুগ্রহ করে সেন্সরটি বাঁ দিকে নিয়ে যান।"</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"অনুগ্রহ করে সেন্সরের দিকে তাকান।"</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"কোনও ফেস শনাক্ত করা যায়নি।"</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"ডিভাইসের সামনে ফেসটি স্থির রাখুন।"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"ফেসের হার্ডওয়্যার উপলভ্য নয়৷"</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"ফেসের ছাপ নেওয়ার সময়সীমা শেষ৷ আবার চেষ্টা করুন৷"</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"ফেস স্টোর করা যাবে না।"</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"ফেস অপারেশন বাতিল করা হয়েছে৷"</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"অনেকবার চেষ্টা করা হয়েছে। পরে আবার চেষ্টা করুন।"</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"অনেকবার চেষ্টা করা হয়েছে৷ ফেস যাচাইকরণ বন্ধ আছে।"</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"আবার চেষ্টা করুন।"</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"কোনও ফেস নথিভুক্ত করা হয়নি।"</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"এই ডিভাইসে ফেস যাচাইকরণ সেন্সর নেই"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"<xliff:g id="FACEID">%d</xliff:g> ফেস"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"ফেস আইকন"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"সিঙ্ক সেটিংস পড়ে"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"অ্যাপ্লিকেশানটিকে একটি অ্যাকাউন্টের জন্য সিঙ্ক সেটিংস পড়ার অনুমতি দেয়৷ উদাহরণস্বরূপ, \'পিপল\' অ্যাপ্লিকেশানটি কোনো অ্যাকাউন্টের সাথে সিঙ্ক করা আছে কিনা তা নির্ধারণ করতে পারে৷"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"সমন্বয় চালু এবং বন্ধ করা টগল করুন"</string>
@@ -1140,7 +1130,7 @@
     <string name="aerr_restart" msgid="7581308074153624475">"অ্যাপ্লিকেশানটিকে আবার খুলুন"</string>
     <string name="aerr_report" msgid="5371800241488400617">"মতামত জানান"</string>
     <string name="aerr_close" msgid="2991640326563991340">"বন্ধ করুন"</string>
-    <string name="aerr_mute" msgid="1974781923723235953">"ডিভাইসটি পুনরায় আরম্ভ না হওয়া পর্যন্ত নিঃশব্দ করুন"</string>
+    <string name="aerr_mute" msgid="1974781923723235953">"ডিভাইসটি পুনরায় আরম্ভ না হওয়া পর্যন্ত মিউট করুন"</string>
     <string name="aerr_wait" msgid="3199956902437040261">"অপেক্ষা করুন"</string>
     <string name="aerr_close_app" msgid="3269334853724920302">"অ্যাপ্লিকেশান বন্ধ করুন"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"ওয়াই-ফাই এ ইন্টারনেট অ্যাক্সেস নেই"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"বিকল্পগুলির জন্য আলতো চাপুন"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"আপনার হটস্পট সেটিংসে পরিবর্তনগুলি"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"আপনার হটস্পট ব্যান্ড পরিবর্তন করা হয়েছে।"</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"এই ডিভাইসটি শুধুমাত্র 5GHz এর জন্য আপনার পছন্দ সমর্থন করে না। পরিবর্তে, এই ডিভাইসটি 5GHz ব্যান্ড ব্যবহার করবে।"</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> এ পাল্টানো হয়েছে"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> এ ইন্টারনেট অ্যাক্সেস না থাকলে <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ব্যবহার করা হয়৷ ডেটা চার্জ প্রযোজ্য৷"</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> থেকে <xliff:g id="NEW_NETWORK">%2$s</xliff:g> এ পাল্টানো হয়েছে"</string>
@@ -1906,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> কে &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;এ সংরক্ষণ করবেন?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> এবং <xliff:g id="TYPE_1">%2$s</xliff:g> কে &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; এ সংরক্ষণ করবেন?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, এবং <xliff:g id="TYPE_2">%3$s</xliff:g> কে &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; এ সংরক্ষণ করবেন?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;-তে আপডেট করতে চান?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> থেকে &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;-এ আপডেট করতে চান?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> এবং <xliff:g id="TYPE_1">%2$s</xliff:g>o &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;-এ আপডেট করতে চান?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>,এবং <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; আপডেট করতে চান?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"সেভ করুন"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"না থাক"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"আপডেট করুন"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"পাসওয়ার্ড"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ঠিকানা"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ক্রেডিট কার্ড"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index fa354ae..244af73 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -34,7 +34,7 @@
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problem sa povezivanjem ili nevažeći MMI kôd."</string>
     <string name="mmiFdnError" msgid="5224398216385316471">"Operacija je ograničena samo na brojeve fiksnog biranja."</string>
-    <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"Nije moguće promijeniti postavke za preusmjeravanje poziva s vašeg telefona dok ste u romingu."</string>
+    <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"Nije moguće promijeniti postavke prosljeđivanja poziva s vašeg telefona dok ste u romingu."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Usluga je omogućena."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Usluga je omogućena za:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Usluga je onemogućena."</string>
@@ -61,7 +61,7 @@
     <string name="ClirMmi" msgid="7784673673446833091">"ID odlaznog poziva"</string>
     <string name="ColpMmi" msgid="3065121483740183974">"Identifikacija povezane linije"</string>
     <string name="ColrMmi" msgid="4996540314421889589">"Ograničenje identifikacije povezane linije"</string>
-    <string name="CfMmi" msgid="5123218989141573515">"Preusmjeravanje poziva"</string>
+    <string name="CfMmi" msgid="5123218989141573515">"Prosljeđivanje poziva"</string>
     <string name="CwMmi" msgid="9129678056795016867">"Poziv na čekanju"</string>
     <string name="BaMmi" msgid="455193067926770581">"Zabrana poziva"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"Promjena lozinke"</string>
@@ -89,17 +89,17 @@
     <string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Hitni pozivi su nedostupni"</string>
     <string name="EmergencyCallWarningSummary" msgid="1899692069750260619">"Nije moguće uspostaviti hitne pozive putem Wi‑Fi mreže"</string>
     <string name="notification_channel_network_alert" msgid="4427736684338074967">"Upozorenja"</string>
-    <string name="notification_channel_call_forward" msgid="2419697808481833249">"Preusmjeravanje poziva"</string>
+    <string name="notification_channel_call_forward" msgid="2419697808481833249">"Prosljeđivanje poziva"</string>
     <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Način rada za hitni povratni poziv"</string>
     <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Status prijenosa podataka na mobilnoj mreži"</string>
     <string name="notification_channel_sms" msgid="3441746047346135073">"SMS poruke"</string>
     <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Poruke govorne pošte"</string>
-    <string name="notification_channel_wfc" msgid="2130802501654254801">"WiFi pozivanje"</string>
+    <string name="notification_channel_wfc" msgid="2130802501654254801">"Pozivanje putem WiFi-ja"</string>
     <string name="notification_channel_sim" msgid="4052095493875188564">"Status SIM-a"</string>
-    <string name="peerTtyModeFull" msgid="6165351790010341421">"Ravnopravni uređaj zatražio TTY PUNI način rada"</string>
-    <string name="peerTtyModeHco" msgid="5728602160669216784">"Ravnopravni uređaj zatražio TTY HCO način rada"</string>
-    <string name="peerTtyModeVco" msgid="1742404978686538049">"Ravnopravni uređaj zatražio TTY VCO način rada"</string>
-    <string name="peerTtyModeOff" msgid="3280819717850602205">"Ravnopravni uređaj zatražio TTY ISKLJUČENI način rada"</string>
+    <string name="peerTtyModeFull" msgid="6165351790010341421">"Ravnopravni uređaj zatražio načina rada TTY FULL"</string>
+    <string name="peerTtyModeHco" msgid="5728602160669216784">"Ravnopravni uređaj zatražio načina rada TTY HCO"</string>
+    <string name="peerTtyModeVco" msgid="1742404978686538049">"Ravnopravni uređaj zatražio načina rada TTY VCO"</string>
+    <string name="peerTtyModeOff" msgid="3280819717850602205">"Ravnopravni uređaj zatražio načina rada TTY OFF"</string>
     <string name="serviceClassVoice" msgid="1258393812335258019">"Govorna"</string>
     <string name="serviceClassData" msgid="872456782077937893">"Podatke"</string>
     <string name="serviceClassFAX" msgid="5566624998840486475">"Faks"</string>
@@ -122,16 +122,16 @@
     <string name="roamingText11" msgid="4154476854426920970">"Oznaka da je uređaj u roamingu uključena"</string>
     <string name="roamingText12" msgid="1189071119992726320">"Oznaka da je uređaj u roamingu ugašena"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Traženje usluge"</string>
-    <string name="wfcRegErrorTitle" msgid="3855061241207182194">"Nije moguće postaviti WiFi pozivanje"</string>
+    <string name="wfcRegErrorTitle" msgid="3855061241207182194">"Nije moguće postaviti pozivanje putem WiFi-ja"</string>
   <string-array name="wfcOperatorErrorAlertMessages">
-    <item msgid="3910386316304772394">"Da biste pozivali i slali poruke koristeći WiFi mrežu, prvo zatražite od operatera da postavi tu uslugu. Zatim ponovo uključite WiFi pozivanje u Postavkama. (Kôd greške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+    <item msgid="3910386316304772394">"Da biste pozivali i slali poruke koristeći WiFi mrežu, prvo zatražite od operatera da postavi tu uslugu. Zatim ponovo uključite pozivanje putem WiFi-ja u Postavkama. (Kôd greške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
   </string-array>
   <string-array name="wfcOperatorErrorNotificationMessages">
     <item msgid="7372514042696663278">"Došlo je do problema prilikom registracije pozivanja putem WiFi mreže kod vašeg operatera: <xliff:g id="CODE">%1$s</xliff:g>"</item>
   </string-array>
   <string-array name="wfcSpnFormats">
     <item msgid="6830082633573257149">"%s"</item>
-    <item msgid="4397097370387921767">"WiFi pozivanje preko operatera %s"</item>
+    <item msgid="4397097370387921767">"Pozivanje putem WiFi-ja preko operatera %s"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Isključeno"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferira se WiFi"</string>
@@ -239,9 +239,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način rada u avionu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uključen je način rada u avionu"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Način rada u avionu ugašen"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Ušteda baterije"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Ušteda baterije je ISKLJUČENA"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Ušteda baterije je UKLJUČENA"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Postavke"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Pomoć"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glasovna pomoć"</string>
@@ -306,6 +303,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Tjelesni senzori"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"pristupa podacima senzora o vašim vitalnim funkcijama"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristup senzornim podacima o vašim vitalnim znacima?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muzika"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"pristup muzici"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;da pristupi vašoj muzici?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotografije i videozapisi"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"pristup fotografijama i videozapisima"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupi vašim fotografijama i videozapisima?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Preuzima sadržaj prozora"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Pregleda sadržaj prozora koji trenutno koristite."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Uključi opciju Istraživanje dodirom"</string>
@@ -463,7 +466,7 @@
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"prikaz mrežnih veza"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Omogućava aplikaciji pregled informacija o mrežnim vezama, npr. koje mreže postoje i koje su povezane."</string>
     <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"ima potpuni pristup mreži"</string>
-    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Omogućava aplikaciji kreiranje spojnih tačaka sa mrežom i korištenje prilagođenih mrežnih protokola. Preglednik i druge aplikacije omogućavaju slanje podataka na internet, tako da ovo odobrenje nije potrebno za vršenje te radnje."</string>
+    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Omogućava aplikaciji kreiranje spojnih tačaka s mrežom i korištenje prilagođenih mrežnih protokola. Preglednik i druge aplikacije omogućavaju slanje podataka na internet, tako da ovo odobrenje nije potrebno za vršenje te radnje."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"izmjene povezivanja na mrežu"</string>
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Dozvoljava aplikaciji izmjenu stanja mrežne povezanosti."</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"izmjene podijeljenog povezivanja"</string>
@@ -500,6 +503,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Omogućava aplikaciji da koristi metode za dodavanje i brisanje šablona otisaka prstiju za upotrebu."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"korištenje hardvera za otiske prstiju"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Omogućava aplikaciji da za provjeru vjerodostojnosti koristi hardver za otiske prstiju"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"čitanje muzičke kolekcije"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Omogućava aplikaciji da čita vašu muzičku kolekciju."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"izmjena muzičke kolekcije"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Omogućava aplikaciji da mijenja vašu muzičku kolekciju."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"čitanje kolekcije videozapisa"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Omogućava aplikaciji da čita vašu kolekciju videozapisa."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"izmjena kolekcije videozapisa"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Omogućava aplikaciji da mijenja vašu kolekciju videozapisa."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"čitanje kolekcije fotografija"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Omogućava aplikaciji da čita vašu kolekciju fotografija."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"izmjena kolekcije fotografija"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Omogućava aplikaciji da mijenja vašu kolekciju fotografija."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"čitanje lokacija iz kolekcije medija"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Omogućava aplikaciji da čita lokacije iz vaše kolekcije medija."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Otkriven je djelomičan otisak prsta. Pokušajte ponovo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nije uspjela obrada otiska prsta. Pokušajte ponovo."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Senzor za otisak prsta je prljav. Očistite ga i pokušajte ponovo."</string>
@@ -507,11 +524,11 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Prst je uklonjen presporo. Pokušajte ponovo."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nije prepoznat"</string>
+    <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nije prepoznato"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Otisak prsta je potvrđen"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otisak prsta nije dostupan."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta se ne može pohraniti. Uklonite postojeći otisak prsta."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Pokušajte ponovo."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vrijeme za prepoznavanje otiska prsta je isteklo. Pokušajte ponovo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Korisnik je otkazao radnju s otiskom prsta."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
@@ -524,7 +541,7 @@
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Ikona za otisak prsta"</string>
     <string name="permlab_manageFace" msgid="2137540986007309781">"upravljanje hardverom za autentifikaciju licem"</string>
-    <string name="permdesc_manageFace" msgid="8919637120670185330">"Omogućava aplikaciji da koristi metode za dodavanje i brisanje šablona lica za upotrebu."</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"Omogućava aplikaciji korištenje metoda za dodavanje i brisanje šablona lica za upotrebu."</string>
     <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"upotreba hardvera za autentifikaciju licem"</string>
     <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Omogućava aplikaciji da za autentifikaciju koristi hardver za autentifikaciju licem"</string>
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"Obrada lica nije uspjela. Pokušajte ponovo."</string>
@@ -537,12 +554,12 @@
     <string name="face_acquired_too_right" msgid="1650292067226118760">"Pomjerite senzor udesno."</string>
     <string name="face_acquired_too_left" msgid="2712489669456176505">"Pomjerite senzor ulijevo."</string>
     <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"Gledajte u senzor."</string>
-    <string name="face_acquired_not_detected" msgid="5707782294589511391">"Nije pronađeno lice."</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"Nije pronađeno nijedno lice."</string>
     <string name="face_acquired_not_steady" msgid="3722829465011040042">"Mirno držite lice ispred uređaja."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="6255891785768984615">"Hardver za prepoznavanje lica nije dostupan."</string>
-    <string name="face_error_timeout" msgid="4014326147867150054">"Isteklo vrijeme za prepoznavanje. Pokušajte ponovo."</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"Vrijeme za prepoznavanje lica je isteklo. Pokušajte ponovo."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Nije moguće pohraniti lice."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Prepoznavanje lica je otkazano."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
@@ -1912,8 +1929,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Želite li da se <xliff:g id="TYPE">%1$s</xliff:g> sačuva u &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> sačuvaju u &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, i <xliff:g id="TYPE_2">%3$s</xliff:g> sačuvaju &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Želite li ažurirati na &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Želite li da se <xliff:g id="TYPE">%1$s</xliff:g> ažurira na &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> ažuriraju na &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, i <xliff:g id="TYPE_2">%3$s</xliff:g> ažuriraju na &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Ažuriraj"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"lozinka"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditna kartica"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index ee1673b..2c74e82 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode d\'avió"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode d\'avió activat"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode d\'avió desactivat"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Estalvi de bateria"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"El mode d\'estalvi de bateria està desactivat"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"El mode d\'estalvi de bateria està activat"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Configuració"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assistència"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assist. per veu"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensors corporals"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"accedir a les dades del sensor sobre els signes vitals"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a les dades del sensor de constants vitals?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Música"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"accedir a la teva música"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a la teva música?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotos i vídeos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"accedir a les teves fotos i als teus vídeos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a les teves fotos i als teus vídeos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperar el contingut de la finestra"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecciona el contingut d\'una finestra amb què estàs interaccionant."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Activar Exploració tàctil"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet que l\'aplicació invoqui mètodes per afegir i suprimir plantilles d\'empremtes digitals que es puguin fer servir."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilitzar el maquinari d\'empremtes digitals"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permet que l\'aplicació faci servir maquinari d\'empremtes digitals per a l\'autenticació"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"llegir la teva col·lecció de música"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Permet que l\'aplicació llegeixi la teva col·lecció de música."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modificar la teva col·lecció de música"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permet que l\'aplicació modifiqui la teva col·lecció de música."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"llegir la teva col·lecció de vídeos"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Permet que l\'aplicació llegeixi la teva col·lecció de vídeos."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modificar la teva col·lecció de vídeos"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Permet que l\'aplicació modifiqui la teva col·lecció de vídeos."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"llegir la teva col·lecció de fotos"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Permet que l\'aplicació llegeixi la teva col·lecció de fotos."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modificar la teva col·lecció de fotos"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permet que l\'aplicació modifiqui la teva col·lecció de fotos."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"llegir les ubicacions de les teves col·leccions multimèdia"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permet que l\'aplicació llegeixi les ubicacions de les teves col·leccions multimèdia."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S\'ha detectat una empremta digital parcial. Torna-ho a provar."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No s\'ha pogut processar l\'empremta digital. Torna-ho a provar."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor d\'empremtes digitals està brut. Neteja\'l i torna-ho a provar."</string>
@@ -1103,7 +1120,7 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Utilitza-ho de manera predeterminada per a aquesta acció."</string>
     <string name="use_a_different_app" msgid="8134926230585710243">"Fes servir una altra aplicació"</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Esborra els paràmetres predeterminats a Configuració del sistema &gt; Aplicacions &gt; Baixades."</string>
-    <string name="chooseActivity" msgid="7486876147751803333">"Tria una acció"</string>
+    <string name="chooseActivity" msgid="7486876147751803333">"Selecciona una acció"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Tria una aplicació per al dispositiu USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"No hi ha cap aplicació que pugui dur a terme aquesta acció."</string>
     <string name="aerr_application" msgid="250320989337856518">"S\'ha aturat <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
@@ -1292,9 +1309,9 @@
     <string name="usb_power_notification_message" msgid="4647527153291917218">"S\'està carregant el dispositiu connectat. Toca per veure més opcions."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"S\'ha detectat un accessori d\'àudio analògic"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"El dispositiu connectat no és compatible amb aquest telèfon. Toca per obtenir més informació."</string>
-    <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuració USB activada"</string>
+    <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuració per USB activada"</string>
     <string name="adb_active_notification_message" msgid="7463062450474107752">"Toca per desactivar la depuració per USB"</string>
-    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecciona per desactivar la depuració USB"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecciona per desactivar la depuració per USB"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"S\'està creant l\'informe d\'errors…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vols compartir l\'informe d\'errors?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"S\'està compartint l\'informe d\'errors…"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vols desar <xliff:g id="TYPE">%1$s</xliff:g> a <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vols desar <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vols desar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> a <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Vols actualitzar les dades a &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vols actualitzar <xliff:g id="TYPE">%1$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vols actualitzar <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vols actualitzar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Desa"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, gràcies"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Actualitza"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"contrasenya"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adreça"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"targeta de crèdit"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0d67679..278ab957 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -58,8 +58,8 @@
     </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
-    <string name="ClipMmi" msgid="6952821216480289285">"Příchozí identifikace volajícího"</string>
-    <string name="ClirMmi" msgid="7784673673446833091">"Odchozí identifikace volajícího"</string>
+    <string name="ClipMmi" msgid="6952821216480289285">"Příchozí ID volajícího"</string>
+    <string name="ClirMmi" msgid="7784673673446833091">"Odchozí ID volajícího"</string>
     <string name="ColpMmi" msgid="3065121483740183974">"ID připojené linky"</string>
     <string name="ColrMmi" msgid="4996540314421889589">"Omezení ID připojené linky"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Přesměrování hovorů"</string>
@@ -73,12 +73,12 @@
     <string name="RuacMmi" msgid="7827887459138308886">"Odmítnutí nevyžádaných obtěžujících hovorů"</string>
     <string name="CndMmi" msgid="3116446237081575808">"Doručení volaného čísla"</string>
     <string name="DndMmi" msgid="1265478932418334331">"Nerušit"</string>
-    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Ve výchozím nastavení je identifikace volajícího omezena. Příští hovor: Omezeno"</string>
-    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Ve výchozím nastavení je identifikace volajícího omezena. Příští hovor: Neomezeno"</string>
-    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Ve výchozím nastavení není identifikace volajícího omezena. Příští hovor: Omezeno"</string>
-    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Ve výchozím nastavení není identifikace volajícího omezena. Příští hovor: Neomezeno"</string>
+    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Ve výchozím nastavení je funkce ID volajícího omezena. Příští hovor: Omezeno"</string>
+    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Ve výchozím nastavení je funkce ID volajícího omezena. Příští hovor: Neomezeno"</string>
+    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Ve výchozím nastavení není funkce ID volajícího omezena. Příští hovor: Omezeno"</string>
+    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Ve výchozím nastavení není funkce ID volajícího omezena. Příští hovor: Neomezeno"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"Služba není zřízena."</string>
-    <string name="CLIRPermanent" msgid="3377371145926835671">"Nastavení identifikace volajícího nesmíte měnit."</string>
+    <string name="CLIRPermanent" msgid="3377371145926835671">"Nastavení ID volajícího nesmíte měnit."</string>
     <string name="RestrictedOnDataTitle" msgid="5221736429761078014">"Není k dispozici žádná mobilní datová služba"</string>
     <string name="RestrictedOnEmergencyTitle" msgid="6855466023161191166">"Tísňová volání jsou nedostupná"</string>
     <string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Hlasová volání nejsou k dispozici"</string>
@@ -242,9 +242,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim Letadlo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim Letadlo je ZAPNUTÝ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim Letadlo je VYPNUTÝ"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Spořič baterie"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Spořič baterie je VYPNUTÝ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Spořič baterie je ZAPNUTÝ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Nastavení"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Asistence"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Hlas. asistence"</string>
@@ -309,6 +306,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Tělesné senzory"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"přístup k datům ze snímačů vašich životních funkcí"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k údajům ze snímačů vašich životních funkcí?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Hudba"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"přístup k hudbě"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k hudbě?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotky a videa"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"přístup k fotkám a videím"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k fotkám a videím?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Načítat obsah oken"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Může prozkoumávat obsah oken, se kterými pracujete."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Zapnout funkci Prozkoumání dotykem"</string>
@@ -503,6 +506,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikaci volat metody k přidání a smazání šablon otisků prstů, které budou použity."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"použití hardwaru na čtení otisků prstů"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Umožňuje aplikaci použít k ověření hardware na čtení otisků prstů"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"čtení hudební sbírky"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Umožňuje aplikaci číst vaši hudební sbírku."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"úprava hudební sbírky"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Umožňuje aplikaci upravit vaši hudební sbírku."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"čtení sbírky videí"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Umožňuje aplikaci číst vaši sbírku videí."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"úprava sbírky videí"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Umožňuje aplikaci upravit vaši sbírku videí."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"čtení sbírky fotek"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Umožňuje aplikaci číst vaši sbírku fotek."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"úprava sbírky fotek"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Umožňuje aplikaci upravit vaši sbírku fotek."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"čtení míst ze sbírky médií"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Umožňuje aplikaci číst místa z vaší sbírky médií."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Byla zjištěna jen část otisku prstu. Zkuste to znovu."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Zpracování otisku prstu se nezdařilo. Zkuste to znovu."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Senzor otisků prstů je znečištěn. Vyčistěte jej a zkuste to znovu."</string>
@@ -1338,7 +1355,7 @@
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"Připojené zařízení není s tímto telefonem kompatibilní. Klepnutím zobrazíte další informace."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ladění přes USB připojeno"</string>
     <string name="adb_active_notification_message" msgid="7463062450474107752">"Klepnutím vypnete ladění přes USB"</string>
-    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Vyberte, chcete-li zakázat ladění USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Vyberte, chcete-li zakázat ladění přes USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Vytváření zprávy o chybě…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Sdílet zprávu o chybě?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sdílení zprávy o chybě…"</string>
@@ -1842,7 +1859,7 @@
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
     <string name="toolbar_collapse_description" msgid="2821479483960330739">"Sbalit"</string>
     <string name="zen_mode_feature_name" msgid="5254089399895895004">"Nerušit"</string>
-    <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"Období klidu"</string>
+    <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"Doba klidu"</string>
     <string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"Večer v pracovním týdnu"</string>
     <string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"Víkend"</string>
     <string name="zen_mode_default_events_name" msgid="8158334939013085363">"Událost"</string>
@@ -1923,7 +1940,7 @@
     <string name="app_category_maps" msgid="5878491404538024367">"Mapy a navigace"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivita"</string>
     <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Úložiště zařízení"</string>
-    <string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"Ladění USB"</string>
+    <string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"Ladění přes USB"</string>
     <string name="time_picker_hour_label" msgid="2979075098868106450">"hodina"</string>
     <string name="time_picker_minute_label" msgid="5168864173796598399">"minuta"</string>
     <string name="time_picker_header_text" msgid="143536825321922567">"Nastavení času"</string>
@@ -1945,8 +1962,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Uložit položku <xliff:g id="TYPE">%1$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Uložit položky <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Uložit položky <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Aktualizovat službu &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Aktualizovat položku <xliff:g id="TYPE">%1$s</xliff:g> ve službě &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Aktualizovat položky <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> ve službě &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Aktualizovat položky <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> ve službě &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Uložit"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, děkuji"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Aktualizovat"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"heslo"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"platební karta"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 7f4409b6..32be0d3 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flytilstand"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flytilstand er TIL"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flytilstand er slået FRA"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Batterisparefunktion"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Batterisparefunktion er slået FRA"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Batterisparefunktion er slået TIL"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Indstillinger"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assistance"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Taleassistent"</string>
@@ -270,7 +267,7 @@
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="8836124313744349203">"Skift til personlig profil"</string>
     <string name="managed_profile_label" msgid="8947929265267690522">"Skift til arbejdsprofil"</string>
-    <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktpersoner"</string>
+    <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakter"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"have adgang til dine kontaktpersoner"</string>
     <string name="permgrouprequest_contacts" msgid="6032805601881764300">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til dine kontaktpersoner?"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Placering"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Kropssensorer"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"få adgang til sensordata om dine livstegn"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til sensordata om dine livstegn?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musik"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"adgang til din musik"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til din musik?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Billeder og videoer"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"adgang til dine billeder og videoer"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til dine billeder og videoer?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Hente indholdet i vinduet"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Undersøge indholdet i et vindue, du interagerer med."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktivere Udforsk ved berøring"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Tillader, at appen kan køre metoder til at tilføje og slette fingeraftryksskabeloner"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"bruge fingeraftrykhardware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillader, at appen kan bruge fingeraftrykhardware til godkendelse"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"læse din musiksamling"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Tillader, at appen kan læse din musiksamling."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"ændre din musiksamling"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Tillader, at appen kan ændre din musiksamling."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"læse din videosamling"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Tillader, at appen kan læse din videosamling."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"ændre din videosamling"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Tillader, at appen kan ændre din videosamling."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"læse din billedsamling"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Tillader, at appen kan læse din billedsamling."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"ændre din billedsamling"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Tillader, at appen kan ændre din billedsamling."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"læse placeringer fra din mediesamling"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Tillader, at appen kan læse placeringer fra din mediesamling."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Der blev registreret et delvist fingeraftryk. Prøv igen."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Fingeraftrykket kunne ikke behandles. Prøv igen."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sensoren til registrering af fingeraftryk er beskidt. Tør den af, og prøv igen."</string>
@@ -521,12 +538,12 @@
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Ikon for fingeraftryk"</string>
     <string name="permlab_manageFace" msgid="2137540986007309781">"administrer hardware til ansigtsgenkendelse"</string>
-    <string name="permdesc_manageFace" msgid="8919637120670185330">"Tillader, at appen kan køre metoder til at tilføje og slette ansigtsskabeloner."</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"Tillader, at appen kan bruge metoder til at tilføje og slette ansigtsskabeloner."</string>
     <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"brug hardware til ansigtsgenkendelse"</string>
-    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Tillader, at appen kan bruge hardware til ansigtsgenkendelse"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Tillader, at appen bruger ansigtsgenkendelseshardware til godkendelse"</string>
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"Ansigtet kunne ikke behandles. Prøv igen."</string>
     <string name="face_acquired_too_bright" msgid="610606792381297174">"Ansigtet er for lyst. Prøv i svagere belysning."</string>
-    <string name="face_acquired_too_dark" msgid="7229162716976778371">"Ansigtet er for mørkt. Ryk nærmere en lyskilde."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"Ansigtet er for mørkt. Ryk tættere på en lyskilde."</string>
     <string name="face_acquired_too_close" msgid="1980310037427755293">"Flyt sensoren længere væk fra ansigtet."</string>
     <string name="face_acquired_too_far" msgid="4494571381828850007">"Ryk sensoren tættere på ansigtet."</string>
     <string name="face_acquired_too_high" msgid="228411096134808372">"Flyt sensoren højere op."</string>
@@ -623,7 +640,7 @@
     <string name="policylab_resetPassword" msgid="4934707632423915395">"Skifte skærmlås"</string>
     <string name="policydesc_resetPassword" msgid="1278323891710619128">"Skifter skærmlås"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Låse skærmen"</string>
-    <string name="policydesc_forceLock" msgid="1141797588403827138">"Kontrollerer, hvordan og hvornår skærmen låses."</string>
+    <string name="policydesc_forceLock" msgid="1141797588403827138">"Administrerer, hvordan og hvornår skærmen låses."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Slette alle data"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Slet din tablets data uden varsel ved at gendanne fabriksindstillingerne."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Slet tv\'ets data uden varsel ved at nulstille til fabrinksindstillingerne."</string>
@@ -755,7 +772,7 @@
     <string name="sipAddressTypeHome" msgid="6093598181069359295">"Hjem"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbejde"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Andet"</string>
-    <string name="quick_contacts_not_available" msgid="746098007828579688">"Der blev ikke fundet nogen applikation, som kan vise denne kontaktperson."</string>
+    <string name="quick_contacts_not_available" msgid="746098007828579688">"Der blev ikke fundet nogen applikation, som kan vise denne kontakt."</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Angiv pinkode"</string>
     <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Angiv PUK- og pinkode"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-kode"</string>
@@ -1213,7 +1230,7 @@
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tryk for at se valgmuligheder"</string>
     <string name="wifi_softap_config_change" msgid="8475911871165857607">"Ændringer af dine indstillinger for hotspot"</string>
     <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"Dit hotspotbånd er ændret."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Denne enhed understøtter ikke din præferencer om kun 5 GHz. Denne enhed vil i stedet bruge 5 GHz-båndet, når det er muligt."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Denne enhed understøtter ikke din præference om kun 5 GHz. Denne enhed vil i stedet bruge 5 GHz-båndet, når det er muligt."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"Der blev skiftet til <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"Enheden benytter <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, når der ikke er internetadgang via <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>. Der opkræves muligvis betaling."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"Der blev skiftet fra <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> til <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vil du gemme <xliff:g id="TYPE">%1$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Vil du opdatere til &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vil du opdatere <xliff:g id="TYPE">%1$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vil du opdatere <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vil du opdatere <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Gem"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nej tak"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Opdater"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"adgangskode"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditkort"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 26c0fab..e5b9372 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flugmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flugmodus ist AN."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist AUS."</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Energiesparmodus"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Energiesparmodus ist aus"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Energiesparmodus ist an"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Einstellungen"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assistent"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Sprachassistent"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Körpersensoren"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"auf Sensordaten zu deinen Vitaldaten zugreifen"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf Sensordaten zu deinen Vitalfunktionen zuzugreifen?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musik"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"auf Musik zugreifen"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; Zugriff auf deine Musik gewähren?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotos und Videos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"auf meine Fotos und Videos zugreifen"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; Zugriff auf deine Fotos und Videos gewähren?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Fensterinhalte abrufen"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Die Inhalte eines Fensters, mit dem du interagierst, werden abgerufen."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"\"Tippen &amp; Entdecken\" aktivieren"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Erlaubt der App, Methoden zum Hinzufügen und Löschen zu verwendender Fingerabdruckvorlagen aufzurufen"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Fingerabdruckhardware verwenden"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Erlaubt der App, Fingerabdruckhardware zur Authentifizierung zu verwenden"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"meine Musiksammlung abrufen"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Ermöglicht der App, deine Musiksammlung abzurufen."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"meine Musiksammlung ändern"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Ermöglicht der App, deine Musiksammlung zu ändern."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"meine Videosammlung abrufen"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Ermöglicht der App, deine Videosammlung abzurufen."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"meine Videosammlung ändern"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Ermöglicht der App, deine Videosammlung zu ändern."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"meine Fotosammlung abrufen"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Ermöglicht der App, deine Fotosammlung abzurufen."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"meine Fotosammlung ändern"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Ermöglicht der App, deine Fotosammlung zu ändern."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"Standorte aus meiner Mediensammlung abrufen"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Ermöglicht der App, Standorte aus deiner Mediensammlung abzurufen."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Fingerabdruck teilweise erkannt. Versuche es erneut."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Fingerabdruck konnte nicht verarbeitet werden. Versuche es erneut."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingerabdrucksensor ist verschmutzt. Reinige ihn und versuche es erneut."</string>
@@ -588,13 +605,13 @@
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"Auf Benachrichtigungen zugreifen"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ermöglicht der App das Abrufen, Überprüfen und Löschen von Benachrichtigungen, einschließlich Benachrichtigungen, die von anderen Apps gepostet wurden"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"An Benachrichtigungs-Listener-Dienst binden"</string>
-    <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ermöglicht dem Inhaber, sich an die Oberfläche der obersten Ebene eines Benachrichtigungs-Listener-Dienstes zu binden. Sollte nie für normale Apps benötigt werden."</string>
+    <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ermöglicht dem Eigentümer, sich an die Oberfläche der obersten Ebene eines Benachrichtigungs-Listener-Dienstes zu binden. Sollte nie für normale Apps benötigt werden."</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"An einen Bedingungsproviderdienst binden"</string>
-    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ermöglicht dem Inhaber, sich an die Oberfläche eines Bedingungsproviderdienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ermöglicht dem Eigentümer, sich an die Oberfläche eines Bedingungsproviderdienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
     <string name="permlab_bindDreamService" msgid="4153646965978563462">"An Dream-Dienst binden"</string>
     <string name="permdesc_bindDreamService" msgid="7325825272223347863">"Ermöglicht der App, sich an die Oberfläche eines Dream-Dienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufrufen"</string>
-    <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ermöglicht dem Inhaber, die vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufzurufen. Sollte für normale Apps nie benötigt werden."</string>
+    <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ermöglicht dem Eigentümer, die vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufzurufen. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Informationen zu den Netzwerkbedingungen erfassen"</string>
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Ermöglicht der App, Informationen zu den Netzwerkbedingungen zu erfassen. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"Kalibrierung für Eingabegerät ändern"</string>
@@ -606,9 +623,9 @@
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"DRM-Zertifikate entfernen"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Ermöglicht einer App das Entfernen von DRM-Zertifikaten. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"An einen Mobilfunkanbieter-Messaging-Dienst binden"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Ermöglicht dem Inhaber die Bindung an die Oberfläche eines Mobilfunkanbieter-Messaging-Dienstes auf oberster Ebene. Für normale Apps sollte dies nie erforderlich sein."</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Ermöglicht dem Eigentümer die Bindung an die Oberfläche eines Mobilfunkanbieter-Messaging-Dienstes auf oberster Ebene. Für normale Apps sollte dies nie erforderlich sein."</string>
     <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"An Mobilfunkanbieter-Dienste binden"</string>
-    <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"Ermöglicht dem Inhaber die Bindung an Mobilfunkanbieter-Dienste. Für normale Apps sollte dies nicht erforderlich sein."</string>
+    <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"Ermöglicht dem Eigentümer die Bindung an Mobilfunkanbieter-Dienste. Für normale Apps sollte dies nicht erforderlich sein."</string>
     <string name="permlab_access_notification_policy" msgid="4247510821662059671">"Auf \"Nicht stören\" zugreifen"</string>
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ermöglicht der App Lese- und Schreibzugriff auf die \"Nicht stören\"-Konfiguration"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; speichern?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> und <xliff:g id="TYPE_1">%2$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; speichern?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> und <xliff:g id="TYPE_2">%3$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; speichern?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Über &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; aktualisieren?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> über &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; aktualisieren?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> und <xliff:g id="TYPE_1">%2$s</xliff:g> über &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; aktualisieren?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> und <xliff:g id="TYPE_2">%3$s</xliff:g> über &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; aktualisieren?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Speichern"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nein danke"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Aktualisieren"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"Passwort"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"Adresse"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Kreditkarte"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 6fa6723..482e29f 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Λειτουργία πτήσης"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Η λειτουργία πτήσης είναι ενεργοποιημένη."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Λειτ. πτήσης είναι ανενεργή"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Εξοικονόμηση μπαταρίας"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Η εξοικονόμηση μπαταρίας είναι ΑΠΕΝΕΡΓΟΠΟΙΗΜΕΝΗ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Η Εξοικονόμηση μπαταρίας είναι ΕΝΕΡΓΗ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Ρυθμίσεις"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Βοήθεια"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Φων.υποβοηθ."</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Αισθητήρες σώματος"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας;"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Μουσική"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"πρόσβαση στη μουσική σας"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στη μουσική σας;"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Φωτογραφίες και βίντεο"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"πρόσβαση στις φωτογραφίες και στα βίντεό σας"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στις φωτογραφίες και στα βίντεό σας;"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Ανάκτηση του περιεχομένου του παραθύρου"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Έλεγχος του περιεχομένου ενός παραθύρου με το οποίο αλληλεπιδράτε."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Ενεργοποίηση της \"Εξερεύνησης με άγγιγμα\""</string>
@@ -323,7 +326,7 @@
     <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Επιτρέπει στην εφαρμογή να αναπτύξει ή να συμπτύξει τη γραμμή κατάστασης."</string>
     <string name="permlab_install_shortcut" msgid="4279070216371564234">"εγκαθιστά συντομεύσεις"</string>
     <string name="permdesc_install_shortcut" msgid="8341295916286736996">"Επιτρέπει σε μια εφαρμογή την προσθήκη συντομεύσεων στην Αρχική οθόνη χωρίς την παρέμβαση του χρήστη."</string>
-    <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"καταργεί την εγκατάσταση συντομεύσεων"</string>
+    <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"απεγκατάσταση συντομεύσεων"</string>
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Επιτρέπει στην εφαρμογή την κατάργηση συντομεύσεων από την Αρχική οθόνη χωρίς την παρέμβαση του χρήστη."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"αναδρομολογεί τις εξερχόμενες κλήσεις"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Επιτρέπει στην εφαρμογή να βλέπει τον αριθμό που καλέσατε κατά τη διάρκεια μιας εξερχόμενης κλήσης με επιλογή ανακατεύθυνσης της κλήσης σε έναν διαφορετικό αριθμό ή διακοπής της κλήσης."</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Επιτρέπει στην εφαρμογή να επικαλείται μεθόδους για την προσθήκη και τη διαγραφή προτύπων μοναδικού χαρακτηριστικού για χρήση."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"χρησιμοποιεί τον εξοπλισμό δακτυλικού αποτυπώματος"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί εξοπλισμό μοναδικού χαρακτηριστικού για έλεγχο ταυτότητας"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ανάγνωση της μουσικής συλλογής σας"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Επιτρέπει στην εφαρμογή να διαβάσει τη μουσική συλλογή σας."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"τροποποίηση της μουσικής συλλογής σας"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Επιτρέπει στην εφαρμογή να τροποποιήσει τη μουσική συλλογή σας."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ανάγνωση της συλλογής βίντεό σας"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Επιτρέπει στην εφαρμογή να διαβάσει τη συλλογή βίντεό σας."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"τροποποίηση της συλλογής βίντεό σας"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Επιτρέπει στην εφαρμογή να τροποποιήσει τη συλλογή βίντεό σας."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ανάγνωση της συλλογής φωτογραφιών σας"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Επιτρέπει στην εφαρμογή να διαβάσει τη συλλογή φωτογραφιών σας."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"τροποποίηση της συλλογής φωτογραφιών σας"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Επιτρέπει στην εφαρμογή να τροποποιήσει τη συλλογή φωτογραφιών σας."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ανάγνωση τοποθεσιών από τη συλλογή πολυμέσων σας"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Επιτρέπει στην εφαρμογή να διαβάσει τοποθεσίες από τη συλλογή πολυμέσων σας."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Εντοπίστηκε μερικό μοναδικό χαρακτηριστικό. Δοκιμάστε ξανά."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Δεν ήταν δυνατή η επεξεργασία του μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Ο αισθητήρας μοναδικού χαρακτηριστικού δεν είναι καθαρός. Καθαρίστε τον και δοκιμάστε ξανά."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Αποθήκευση <xliff:g id="TYPE">%1$s</xliff:g> σε &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;;"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g> και <xliff:g id="TYPE_1">%2$s</xliff:g> σε &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;;"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> και <xliff:g id="TYPE_2">%3$s</xliff:g> σε &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;;"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Να γίνει ενημέρωση στο &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;;"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Να γίνει ενημέρωση των δεδομένων <xliff:g id="TYPE">%1$s</xliff:g> στην υπηρεσία &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;;"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Να γίνει ενημέρωση των δεδομένων <xliff:g id="TYPE_0">%1$s</xliff:g> και <xliff:g id="TYPE_1">%2$s</xliff:g> στην υπηρεσία &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;;"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Να γίνει ενημέρωση των δεδομένων <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> και <xliff:g id="TYPE_2">%3$s</xliff:g> στην υπηρεσία &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;;"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Αποθήκευση"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Όχι, ευχαριστώ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Ενημέρωση"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"κωδικός πρόσβασης"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"διεύθυνση"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"πιστωτική κάρτα"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index aca8fe5..19d0916 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Aeroplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Aeroplane mode is ON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Aeroplane mode is OFF"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Battery saver"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Battery saver is OFF"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Battery saver is ON"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Settings"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assist"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Body sensors"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"access sensor data about your vital signs"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Music"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"access your music"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your music?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Photos &amp; Videos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"access your photos &amp; videos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your photos &amp; videos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Retrieve window content"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspect the content of a window that you\'re interacting with."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Turn on Explore by Touch"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Allows the app to invoke methods to add and delete fingerprint templates for use."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Use fingerprint hardware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Allows the app to use fingerprint hardware for authentication"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"read your music collection"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Allows the app to read your music collection."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modify your music collection"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Allows the app to modify your music collection."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"read your video collection"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Allows the app to read your video collection."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modify your video collection"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Allows the app to modify your video collection."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"read your photo collection"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Allows the app to read your photo collection."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modify your photo collection"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Allows the app to modify your photo collection."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"read locations from your media collection"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Allows the app to read locations from your media collection."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingerprint sensor is dirty. Please clean and try again."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Save <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Update to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, thanks"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index f80eae0..1e2e081 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Airplane mode is ON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Airplane mode is OFF"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Battery saver"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Battery saver is OFF"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Battery saver is ON"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Settings"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assist"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Body sensors"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"access sensor data about your vital signs"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Music"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"access your music"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your music?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Photos &amp; Videos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"access your photos &amp; videos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your photos &amp; videos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Retrieve window content"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspect the content of a window that you\'re interacting with."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Turn on Explore by Touch"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Allows the app to invoke methods to add and delete fingerprint templates for use."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Use fingerprint hardware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Allows the app to use fingerprint hardware for authentication"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"read your music collection"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Allows the app to read your music collection."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modify your music collection"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Allows the app to modify your music collection."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"read your video collection"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Allows the app to read your video collection."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modify your video collection"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Allows the app to modify your video collection."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"read your photo collection"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Allows the app to read your photo collection."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modify your photo collection"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Allows the app to modify your photo collection."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"read locations from your media collection"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Allows the app to read locations from your media collection."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingerprint sensor is dirty. Please clean and try again."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Save <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Update to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, thanks"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index aca8fe5..19d0916 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Aeroplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Aeroplane mode is ON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Aeroplane mode is OFF"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Battery saver"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Battery saver is OFF"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Battery saver is ON"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Settings"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assist"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Body sensors"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"access sensor data about your vital signs"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Music"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"access your music"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your music?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Photos &amp; Videos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"access your photos &amp; videos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your photos &amp; videos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Retrieve window content"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspect the content of a window that you\'re interacting with."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Turn on Explore by Touch"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Allows the app to invoke methods to add and delete fingerprint templates for use."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Use fingerprint hardware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Allows the app to use fingerprint hardware for authentication"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"read your music collection"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Allows the app to read your music collection."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modify your music collection"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Allows the app to modify your music collection."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"read your video collection"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Allows the app to read your video collection."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modify your video collection"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Allows the app to modify your video collection."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"read your photo collection"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Allows the app to read your photo collection."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modify your photo collection"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Allows the app to modify your photo collection."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"read locations from your media collection"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Allows the app to read locations from your media collection."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingerprint sensor is dirty. Please clean and try again."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Save <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Update to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, thanks"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index aca8fe5..19d0916 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Aeroplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Aeroplane mode is ON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Aeroplane mode is OFF"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Battery saver"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Battery saver is OFF"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Battery saver is ON"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Settings"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assist"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Body sensors"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"access sensor data about your vital signs"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Music"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"access your music"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your music?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Photos &amp; Videos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"access your photos &amp; videos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your photos &amp; videos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Retrieve window content"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspect the content of a window that you\'re interacting with."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Turn on Explore by Touch"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Allows the app to invoke methods to add and delete fingerprint templates for use."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Use fingerprint hardware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Allows the app to use fingerprint hardware for authentication"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"read your music collection"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Allows the app to read your music collection."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modify your music collection"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Allows the app to modify your music collection."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"read your video collection"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Allows the app to read your video collection."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modify your video collection"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Allows the app to modify your video collection."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"read your photo collection"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Allows the app to read your photo collection."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modify your photo collection"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Allows the app to modify your photo collection."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"read locations from your media collection"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Allows the app to read locations from your media collection."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingerprint sensor is dirty. Please clean and try again."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Save <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Update to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, thanks"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 55c3e9d..68bc261 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‎‎‎Airplane mode‎‏‎‎‏‎"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎Airplane mode is ON‎‏‎‎‏‎"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎Airplane mode is OFF‎‏‎‎‏‎"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎Battery saver‎‏‎‎‏‎"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‎Battery saver is OFF‎‏‎‎‏‎"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‎Battery saver is ON‎‏‎‎‏‎"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‏‎‎Settings‎‏‎‎‏‎"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎Assist‎‏‎‎‏‎"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎Voice Assist‎‏‎‎‏‎"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎Body Sensors‎‏‎‎‏‎"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‏‎access sensor data about your vital signs‎‏‎‎‏‎"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access sensor data about your vital signs?‎‏‎‎‏‎"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎Music‎‏‎‎‏‎"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‎access your music‎‏‎‎‏‎"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your music?‎‏‎‎‏‎"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‎‎‏‎Photos &amp; Videos‎‏‎‎‏‎"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‎‎access your photos &amp; videos‎‏‎‎‏‎"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your photos &amp; videos?‎‏‎‎‏‎"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‎‎Retrieve window content‎‏‎‎‏‎"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎Inspect the content of a window you\'re interacting with.‎‏‎‎‏‎"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎Turn on Explore by Touch‎‏‎‎‏‎"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‎‎Allows the app to invoke methods to add and delete fingerprint templates for use.‎‏‎‎‏‎"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‎use fingerprint hardware‎‏‎‎‏‎"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎Allows the app to use fingerprint hardware for authentication‎‏‎‎‏‎"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎read your music collection‎‏‎‎‏‎"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‏‎Allows the app to read your music collection.‎‏‎‎‏‎"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‎modify your music collection‎‏‎‎‏‎"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎Allows the app to modify your music collection.‎‏‎‎‏‎"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎read your video collection‎‏‎‎‏‎"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎‎Allows the app to read your video collection.‎‏‎‎‏‎"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎‎modify your video collection‎‏‎‎‏‎"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎Allows the app to modify your video collection.‎‏‎‎‏‎"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎read your photo collection‎‏‎‎‏‎"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎Allows the app to read your photo collection.‎‏‎‎‏‎"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‎‏‏‎‎modify your photo collection‎‏‎‎‏‎"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎Allows the app to modify your photo collection.‎‏‎‎‏‎"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎read locations from your media collection‎‏‎‎‏‎"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎Allows the app to read locations from your media collection.‎‏‎‎‏‎"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎Partial fingerprint detected. Please try again.‎‏‎‎‏‎"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎Couldn\'t process fingerprint. Please try again.‎‏‎‎‏‎"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎Fingerprint sensor is dirty. Please clean and try again.‎‏‎‎‏‎"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‎Save ‎‏‎‎‏‏‎<xliff:g id="TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎Save ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%3$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎Save ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="TYPE_2">%3$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%4$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎Update to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‎‏‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%3$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="TYPE_2">%3$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%4$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎Save‎‏‎‎‏‎"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎No thanks‎‏‎‎‏‎"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‏‏‎‎Update‎‏‎‎‏‎"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‎‎‎‎‎password‎‏‎‎‏‎"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎address‎‏‎‎‏‎"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎credit card‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index aa4978a..9969af3 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"El modo avión está Activado"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"El modo avión está Desactivado"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Ahorro de batería"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Ahorro de batería DESACTIVADO"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Ahorro de batería ACTIVADO"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Configuración"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Asistencia"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistente voz"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores corporales"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"acceder a los datos del sensor acerca de tus signos vitales"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a los datos del sensor de tus signos vitales?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Música"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"acceder a tu música"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tu música?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotos y videos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"acceder a tus fotos y videos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tus fotos y videos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperar el contenido de las ventanas"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecciona el contenido de la ventana con la que estés interactuando."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Activar la Exploración táctil"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que la aplicación emplee métodos para agregar y eliminar plantillas de huellas digitales para su uso."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilizar hardware de huellas digitales"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que la aplicación utilice el hardware de huellas digitales para realizar la autenticación."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"leer tu colección de música"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Permite que la app lea tu colección de música."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modificar tu colección de música"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permite que la app modifique tu colección de música."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"leer tu colección de videos"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Permite que la app lea tu colección de videos."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modificar tu colección de videos"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Permite que la app modifique tu colección de videos."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"leer tu colección de fotos"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Permite que la app lea tu colección de fotos."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modificar tu colección de fotos"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que la app modifique tu colección de fotos."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"leer ubicaciones de tu colección de contenido multimedia"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que la app lea las ubicaciones de tu colección de contenido multimedia."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"La huella digital se detectó parcialmente. Vuelve a intentarlo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No se pudo procesar la huella digital. Vuelve a intentarlo."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor de huellas digitales está sucio. Limpia el sensor y vuelve a intentarlo."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"¿Quieres guardar tu <xliff:g id="TYPE">%1$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"¿Quieres guardar tu <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"¿Quieres guardar tu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"¿Quieres actualizar los datos en &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"¿Quieres actualizar tu <xliff:g id="TYPE">%1$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"¿Quieres actualizar tu <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"¿Quieres actualizar tu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, y <xliff:g id="TYPE_2">%3$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Actualizar"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"contraseña"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"dirección"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"tarjeta de crédito"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 95f4412..e40a546 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -34,7 +34,7 @@
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Se ha producido un problema de conexión o el código MMI no es válido."</string>
     <string name="mmiFdnError" msgid="5224398216385316471">"La operación solo es válida para números de marcación fija."</string>
-    <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"No se puede cambiar la configuración de desvío de llamada desde tu teléfono mientras estás en itinerancia."</string>
+    <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"No se puede cambiar la configuración de desvío de llamadas desde tu teléfono mientras estás en itinerancia."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"El servicio se ha habilitado."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Se ha habilitado el servicio para:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"El servicio se ha inhabilitado."</string>
@@ -60,7 +60,7 @@
     <string name="ClirMmi" msgid="7784673673446833091">"ID de emisor de llamada saliente"</string>
     <string name="ColpMmi" msgid="3065121483740183974">"ID de línea conectada"</string>
     <string name="ColrMmi" msgid="4996540314421889589">"Restricción de ID de línea conectada"</string>
-    <string name="CfMmi" msgid="5123218989141573515">"Desvío de llamada"</string>
+    <string name="CfMmi" msgid="5123218989141573515">"Desvío de llamadas"</string>
     <string name="CwMmi" msgid="9129678056795016867">"Llamada en espera"</string>
     <string name="BaMmi" msgid="455193067926770581">"Bloqueo de llamada"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"Cambio de contraseña"</string>
@@ -88,7 +88,7 @@
     <string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Servicio de llamadas de emergencia no disponible"</string>
     <string name="EmergencyCallWarningSummary" msgid="1899692069750260619">"No se pueden hacer llamadas de emergencia por Wi‑Fi"</string>
     <string name="notification_channel_network_alert" msgid="4427736684338074967">"Alertas"</string>
-    <string name="notification_channel_call_forward" msgid="2419697808481833249">"Desvío de llamada"</string>
+    <string name="notification_channel_call_forward" msgid="2419697808481833249">"Desvío de llamadas"</string>
     <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Modo de devolución de llamada de emergencia"</string>
     <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Estado de los datos móviles"</string>
     <string name="notification_channel_sms" msgid="3441746047346135073">"Mensajes SMS"</string>
@@ -133,7 +133,7 @@
     <item msgid="4397097370387921767">"Llamadas Wi-Fi de %s"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desactivado"</string>
-    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferir Wi-Fi"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Dar preferencia a Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferir datos móviles"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Solo conexión Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: No desviada"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo avión activado. Desactivar"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo avión desactivado. Activar"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Ahorro de batería"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Ahorro de batería desactivado"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Ahorro de batería activado"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Ajustes"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Asistencia"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistente voz"</string>
@@ -256,7 +253,7 @@
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas de la red"</string>
     <string name="notification_channel_network_available" msgid="4531717914138179517">"Red disponible"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Estado de la VPN"</string>
-    <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administración del dispositivo"</string>
+    <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administración de dispositivos"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
     <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo para tiendas"</string>
     <string name="notification_channel_usb" msgid="9006850475328924681">"Conexión USB"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores corporales"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"acceder a datos de sensores de tus constantes vitales"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a los datos del sensor sobre tus constantes vitales?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Música"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"acceder a tu música"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tu música?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotos y vídeos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"acceder a tus fotos y vídeos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tus fotos y vídeos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Comprobar el contenido de la ventana"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecciona el contenido de una ventana con la que estés interactuando."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Activar la exploración táctil"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que la aplicación invoque métodos para añadir y eliminar plantillas de huellas digitales y utilizarlas."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizar hardware de huellas digitales"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que la aplicación utilice el hardware de huellas digitales para realizar la autenticación"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"leer tu colección de música"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Permite que la aplicación lea tu colección de música."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modificar tu colección de música"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permite que la aplicación modifique tu colección de música."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"leer tu colección de vídeos"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Permite que la aplicación lea tu colección de vídeos."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modificar tu colección de vídeos"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Permite que la aplicación modifique tu colección de vídeos."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"leer tu colección de fotos"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Permite que la aplicación lea tu colección de fotos."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modificar tu colección de fotos"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que la aplicación modifique tu colección de fotos."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"leer las ubicaciones de tu colección de contenido multimedia"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que la aplicación lea las ubicaciones de tu colección de contenido multimedia."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Se ha detectado una huella digital parcial. Vuelve a intentarlo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No se ha podido procesar la huella digital. Vuelve a intentarlo."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor de huellas digitales está sucio. Límpialo y vuelve a intentarlo."</string>
@@ -521,14 +538,14 @@
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Icono de huella digital"</string>
     <string name="permlab_manageFace" msgid="2137540986007309781">"gestionar el hardware de autenticación facial"</string>
-    <string name="permdesc_manageFace" msgid="8919637120670185330">"Permite a la app invocar métodos para añadir y eliminar plantillas de caras y utilizarlas."</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"Permite que la app use métodos para añadir y suprimir plantillas de caras para su uso."</string>
     <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"usar el hardware de autenticación facial"</string>
     <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Permite que la aplicación utilice el hardware de autenticación facial para autenticarte"</string>
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"No se ha reconocido la cara. Vuelve a intentarlo."</string>
     <string name="face_acquired_too_bright" msgid="610606792381297174">"La cara se ve muy clara. Inténtalo con menos luz."</string>
     <string name="face_acquired_too_dark" msgid="7229162716976778371">"La cara se ve muy oscura. Inténtalo con más luz."</string>
-    <string name="face_acquired_too_close" msgid="1980310037427755293">"Aleja más la cara del sensor."</string>
-    <string name="face_acquired_too_far" msgid="4494571381828850007">"Acerca más la cara al sensor."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"Aleja la cara del sensor."</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"Acerca la cara al sensor."</string>
     <string name="face_acquired_too_high" msgid="228411096134808372">"Coloca el sensor más arriba."</string>
     <string name="face_acquired_too_low" msgid="4539774649296349109">"Coloca el sensor más abajo."</string>
     <string name="face_acquired_too_right" msgid="1650292067226118760">"Mueve el sensor hacia la derecha."</string>
@@ -641,7 +658,7 @@
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Inhabilitar cámaras"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Evitar el uso de las cámaras del dispositivo"</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Inhabilitar algunas funciones del bloqueo de pantalla"</string>
-    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Evita el uso de algunas funciones del bloqueo de pantalla."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Evitar el uso de algunas funciones del bloqueo de pantalla"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Móvil"</item>
@@ -1111,7 +1128,7 @@
     <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> sigue sin funcionar"</string>
     <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> sigue sin funcionar"</string>
     <string name="aerr_restart" msgid="7581308074153624475">"Volver a abrir la aplicación"</string>
-    <string name="aerr_report" msgid="5371800241488400617">"Enviar sugerencias"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Enviar comentarios"</string>
     <string name="aerr_close" msgid="2991640326563991340">"Cerrar"</string>
     <string name="aerr_mute" msgid="1974781923723235953">"Silenciar hasta que se reinicie el dispositivo"</string>
     <string name="aerr_wait" msgid="3199956902437040261">"Esperar"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"¿Guardar <xliff:g id="TYPE">%1$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"¿Quieres actualizar a &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"¿Quieres actualizar <xliff:g id="TYPE">%1$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"¿Quieres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"¿Quieres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Actualizar"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"contraseña"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"dirección"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"tarjeta de crédito"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 6155011..56181c8 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lennurežiim"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lennurežiim on SEES"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lennurežiim on VÄLJAS"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Akusäästja"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Akusäästja on VÄLJA lülitatud"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Akusäästja on SISSE lülitatud"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Seaded"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Abi"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Häälabi"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Kehaandurid"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"juurdepääs anduri andmetele teie eluliste näitajate kohta"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs anduri andmetele teie eluliste näitajate kohta?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muusika"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"Pääseda juurde teie muusikale"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs teie muusikale?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotod ja videod"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"Pääseda juurde teie fotodele ja videotele"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs teie fotodele ja videotele?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Akna sisu toomine"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Kasutatava akna sisu kontrollimine."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Puudutusega sirvimise sisselülitamine"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Võimaldab rakendusel tühistada meetodid kasutatavate sõrmejäljemallide lisamiseks ja kustutamiseks."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"sõrmejälje riistvara kasutamine"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Võimaldab rakendusel autentimiseks kasutada sõrmejälje riistvara"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"Lugeda teie muusikakogu"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Võimaldab rakendusel lugeda teie muusikakogu."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"Muuta teie muusikakogu"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Võimaldab rakendusel muuta teie muusikakogu."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"Lugeda teie videokogu"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Võimaldab rakendusel lugeda teie videokogu."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"Muuta teie videokogu"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Võimaldab rakendusel muuta teie videokogu."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"Lugeda teie fotokogu"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Võimaldab rakendusel lugeda teie fotokogu."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"Muuta teie fotokogu"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Võimaldab rakendusel muuta teie fotokogu."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"Lugeda teie meediakogus olevaid asukohti"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Võimaldab rakendusel lugeda teie meediakogus olevaid asukohti."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Tuvastati osaline sõrmejälg. Proovige uuesti."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Sõrmejälge ei õnnestunud töödelda. Proovige uuesti."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sõrmejäljeandur on must. Puhastage see ja proovige uuesti."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Kas salvestada üksus <xliff:g id="TYPE">%1$s</xliff:g> teenusesse &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Kas salvestada üksused <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> teenusesse &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Kas salvestada üksused <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> teenusesse &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Kas värskendada valikule &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Kas värskendada üksus <xliff:g id="TYPE">%1$s</xliff:g> valikule &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Kas värskendada üksused <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> valikule &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Kas värskendada üksused <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> valikule &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvesta"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Tänan, ei"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Värskenda"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"parool"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"aadress"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"krediitkaart"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index bdf5e6a..5ec5637 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -59,7 +59,7 @@
     <string name="ClipMmi" msgid="6952821216480289285">"Sarrerako deien identifikazio-zerbitzua"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Irteerako deien identifikazio-zerbitzua"</string>
     <string name="ColpMmi" msgid="3065121483740183974">"Konektatutako linearen IDa"</string>
-    <string name="ColrMmi" msgid="4996540314421889589">"Konektatutako linearen ID murrizketa"</string>
+    <string name="ColrMmi" msgid="4996540314421889589">"Konektatutako linearen ID murriztapena"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Dei-desbideratzea"</string>
     <string name="CwMmi" msgid="9129678056795016867">"Deia zain"</string>
     <string name="BaMmi" msgid="455193067926770581">"Deien debekuak"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Hegaldi modua"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Hegaldi modua AKTIBATUTA dago"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Hegaldi modua DESAKTIBATUTA dago"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Bateria-aurrezlea"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"DESAKTIBATUTA dago bateria-aurrezlea"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"AKTIBATUTA dago bateria-aurrezlea"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Ezarpenak"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Lagundu"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ahots-laguntza"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Gorputz-sentsoreak"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"atzitu bizi-konstanteei buruzko sentsorearen datuak"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Bizi-konstanteei buruzko sentsorearen datuak atzitzea baimendu nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musika"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"musika atzitu"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari musika atzitzea baimendu nahi diozu?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Argazkiak eta bideoak"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"argazkiak eta bideoak atzitu"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari argazkiak eta bideoak atzitzea baimendu nahi diozu?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Eskuratu leihoko edukia"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Arakatu irekita daukazun leihoko edukia."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktibatu \"Arakatu ukituta\""</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Erreferentzia-gako digitalen txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"erabili erreferentzia-gako digitalen hardwarea"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autentifikatzeko erreferentzia-gako digitalen hardwarea erabiltzea baimentzen die aplikazioei."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"musika-bilduma irakurri"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Musika-bilduma irakurtzea baimentzen die aplikazioei."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"musika-bilduma aldatu"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Musika-bilduma aldatzea baimentzen die aplikazioei."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"bideo-bilduma irakurri"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Bideo-bilduma irakurtzea baimentzen die aplikazioei."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"bideo-bilduma aldatu"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Bideo-bilduma aldatzea baimentzen die aplikazioei."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"argazki-bilduma irakurri"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Argazki-bilduma irakurtzea baimentzen die aplikazioei."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"argazki-bilduma aldatu"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Argazki-bilduma aldatzea baimentzen die aplikazioei."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"multimedia-edukien bildumako kokapena irakurri"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Multimedia-edukien bildumako kokapena irakurtzea baimentzen die aplikazioei."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hatz-marka digitala ez da osorik hauteman. Saiatu berriro."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Ezin izan da prozesatu hatz-marka. Saiatu berriro."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Hatz-marka digitalen sentsorea zikina dago. Garbi ezazu, eta saiatu berriro."</string>
@@ -525,7 +542,7 @@
     <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"erabili aurpegi bidez autentifikatzeko hardwarea"</string>
     <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Aurpegi bidez autentifikatzeko hardwarea erabiltzea baimentzen dio aplikazioari"</string>
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"Ezin izan da prozesatu aurpegia. Saiatu berriro."</string>
-    <string name="face_acquired_too_bright" msgid="610606792381297174">"Aurpegiak distira gehiegi du. Jarri argi gutxiago."</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"Aurpegiak distira gehiegi du. Murriztu argitasuna."</string>
     <string name="face_acquired_too_dark" msgid="7229162716976778371">"Aurpegia ilunegi dago. Estalgabetu argi-iturburua."</string>
     <string name="face_acquired_too_close" msgid="1980310037427755293">"Urrundu sentsorea aurpegitik."</string>
     <string name="face_acquired_too_far" msgid="4494571381828850007">"Hurbildu sentsorea aurpegira."</string>
@@ -533,17 +550,17 @@
     <string name="face_acquired_too_low" msgid="4539774649296349109">"Eraman sentsorea behera."</string>
     <string name="face_acquired_too_right" msgid="1650292067226118760">"Eraman sentsorea eskuinera."</string>
     <string name="face_acquired_too_left" msgid="2712489669456176505">"Eraman sentsorea ezkerrera."</string>
-    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"Begiratu sentsorea."</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"Begiratu sentsoreari."</string>
     <string name="face_acquired_not_detected" msgid="5707782294589511391">"Ez dugu hauteman aurpegirik."</string>
     <string name="face_acquired_not_steady" msgid="3722829465011040042">"Egon geldi, aurpegia gailuaren aurrean jarrita."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <string name="face_error_hw_not_available" msgid="6255891785768984615">"Aurpegiaren hardwarea ez dago erabilgarri."</string>
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"Aurpegia hautemateko hardwarea ez dago erabilgarri."</string>
     <string name="face_error_timeout" msgid="4014326147867150054">"Gainditu da aurpegiak prozesatzeko denbora-muga. Saiatu berriro."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Ezin da gorde aurpegia."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Utzi da aurpegiaren bidezko eragiketa."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
-    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Saiakera gehiegi egin dituzu. Desgaitu da aurpegiaren autentifikazioa."</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Saiakera gehiegi egin dituzu. Desgaitu egin da autentifikazioa."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Saiatu berriro."</string>
     <string name="face_error_not_enrolled" msgid="9166792142679691323">"Ez dago aurpegirik erregistratuta."</string>
     <string name="face_error_hw_not_present" msgid="4737289254517095671">"Gailu honek ez du aurpegia autentifikatzeko sentsorerik"</string>
@@ -1211,8 +1228,8 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"Ezin da konektatu Internetera Wi-Fi bidez"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Sakatu aukerak ikusteko"</string>
-    <string name="wifi_softap_config_change" msgid="8475911871165857607">"Aldaketak sare publiko eramangarriaren ezarpenetan"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"Aldatu da sare eramangarriaren banda."</string>
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"Aldaketak egin dira sare publikoaren ezarpenetan"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"Aldatu da sare publikoaren banda."</string>
     <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Gailuak ez du onartzen 5 GHz-ko banda soilik erabiltzeko hobespena. Horren ordez, erabilgarri dagoen bakoitzean erabiliko da 5 GHz-ko banda."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> erabiltzen ari zara orain"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> Internetera konektatzeko gauza ez denean, <xliff:g id="NEW_NETWORK">%1$s</xliff:g> erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu."</string>
@@ -1876,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; zerbitzuan gorde nahi duzu?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> eta <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; zerbitzuan gorde nahi dituzu?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; zerbitzuan gorde nahi dituzu?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; zerbitzuan eguneratu nahi duzu?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; zerbitzuan eguneratu nahi duzu?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> eta <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; zerbitzuan eguneratu nahi dituzu?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; zerbitzuan eguneratu nahi dituzu?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Gorde"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ez, eskerrik asko"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Eguneratu"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"pasahitza"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"helbidea"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditu-txartela"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 7c32d33..b64937c 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -221,7 +221,7 @@
     <string name="global_action_logout" msgid="935179188218826050">"پایان جلسه"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"عکس صفحه‌نمایش"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"گرفتن گزارش اشکال"</string>
-    <string name="bugreport_message" msgid="398447048750350456">"این گزارش اطلاعات مربوط به وضعیت دستگاه کنونی شما را جمع‌آوری می‌کند تا به صورت یک پیام رایانامه ارسال شود. از زمان شروع گزارش اشکال تا آماده شدن برای ارسال اندکی زمان می‌برد؛ لطفاً شکیبا باشید."</string>
+    <string name="bugreport_message" msgid="398447048750350456">"این گزارش اطلاعات مربوط به وضعیت دستگاه کنونی شما را جمع‌آوری می‌کند تا به صورت یک پیام ایمیل ارسال شود. از زمان شروع گزارش اشکال تا آماده شدن برای ارسال اندکی زمان می‌برد؛ لطفاً شکیبا باشید."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"گزارش تعاملی"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"در بیشتر شرایط از این گزینه استفاده کنید. به شما امکان ردیابی پیشرفت گزارش و وارد کردن جزئیات بیشتری درباره مشکل را می‌دهد. ممکن است برخی از بخش‌هایی را که کمتر استفاده شده و باعث افزایش طول زمان گزارش می‌شود حذف کند."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"گزارش کامل"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"حالت هواپیما"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"حالت هواپیما روشن است"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"حالت هواپیما خاموش است"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"بهینه‌سازی باتری"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"بهینه‌سازی باتری خاموش است"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"بهینه‌سازی باتری روشن است"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"تنظیمات"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"دستیار"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"دستیار صوتی"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"حسگرهای بدن"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"دسترسی به داده‌های حسگر در رابطه با علائم حیاتی شما"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; اجازه داده شود به داده‌های حسگر مربوط به علائم حیاتی شما دسترسی پیدا کند؟"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"موسیقی"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"دسترسی به موسیقی شما"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به موسیقی شما دسترسی پیدا کند؟"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"عکس و ویدیو"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"دسترسی به عکس‌ها و ویدیوهایتان"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به عکس‌ها و ویدیوهای شما دسترسی پیدا کند؟"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"محتوای پنجره را بازیابی کند"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"محتوای پنجره‌ای را که درحال تعامل با آن هستید بررسی می‌کند."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"فعال‌سازی کاوش لمسی"</string>
@@ -399,7 +402,7 @@
     <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"این برنامه می‌تواند همه رویدادهای تقویم ذخیره‌شده در رایانه لوحی شما را بخواند و داده‌های تقویم شما را به اشتراک بگذارد یا ذخیره کند."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"این برنامه می‌تواند همه رویدادهای تقویم ذخیره‌شده در تلویزیون شما را بخواند و داده‌های تقویم شما را به اشتراک بگذارد یا ذخیره کند."</string>
     <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"این برنامه می‌تواند همه رویدادهای تقویم ذخیره‌شده در تلفن شما را بخواند و داده‌های تقویم شما را به اشتراک بگذارد یا ذخیره کند."</string>
-    <string name="permlab_writeCalendar" msgid="8438874755193825647">"افزودن یا تغییر رویدادهای تقویم و ارسال رایانامه به مهمانان بدون دخالت مالک"</string>
+    <string name="permlab_writeCalendar" msgid="8438874755193825647">"افزودن یا تغییر رویدادهای تقویم و ارسال ایمیل به مهمانان بدون دخالت مالک"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"این برنامه می‌تواند در رایانه لوحی شما رویدادهای تقویم اضافه کند، آن‌ها را حذف کند یا تغییر دهد. این برنامه می‌تواند پیام‌هایی ارسال کند که گویی از طرف مالکان تقویم هستند یا رویدادها را بدون اطلاع مالکان تغییر دهد."</string>
     <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"این برنامه می‌تواند در تلویزیون شما رویدادهای تقویم اضافه کند، آن‌ها را حذف کند یا تغییر دهد. این برنامه می‌تواند پیام‌هایی ارسال کند که گویی از طرف مالکان تقویم هستند یا رویدادها را بدون اطلاع مالکان تغییر دهد."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"این برنامه می‌تواند در تلفن شما رویدادهای تقویم اضافه کند، آن‌ها را حذف کند یا تغییر دهد. این برنامه می‌تواند پیام‌هایی ارسال کند که گویی از طرف مالکان تقویم هستند یا رویدادها را بدون اطلاع مالکان تغییر دهد."</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"به برنامه امکان می‌دهد روش‌هایی را برای افزودن و حذف الگوهای اثر انگشت جهت استفاده، فعال کند."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"استفاده از سخت‌افزار اثر انگشت"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"به برنامه امکان می‌دهد از سخت‌افزار اثر انگشت برای احراز هویت استفاده کند"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"خواندن مجموعه موسیقی شما"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"به برنامه اجازه می‌دهد مجموعه موسیقی‌تان را بخواند."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"تغییر مجموعه موسیقی شما"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"به برنامه اجازه می‌دهد مجموعه موسیقی‌تان را تغییر دهد."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"خواندن مجموعه ویدیوی شما"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"به برنامه اجازه می‌دهد مجموعه ویدیویتان را بخواند."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"تغییر مجموعه ویدیوی شما"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"به برنامه اجازه می‌دهد مجموعه ویدیویتان را تغییر دهد."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"خواندن مجموعه عکس شما"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"به برنامه اجازه می‌دهد مجموعه عکستان را بخواند."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"تغییر مجموعه عکس شما"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"به برنامه اجازه می‌دهد مجموعه عکستان را تغییر دهد."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"خواندن مکان‌ها از مجموعه رسانه شما"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"به برنامه اجازه می‌دهد مکان‌ها را از مجموعه رسانه‌تان بخواند."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"بخشی از اثر انگشت شناسایی شد. لطفاً دوباره امتحان کنید."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"اثرانگشت پردازش نشد. لطفاً دوباره امتحان کنید."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"حسگر اثر انگشت کثیف است. لطفاً آن را تمیز کنید و دوباره امتحان نمایید."</string>
@@ -816,7 +833,7 @@
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"بازگشایی قفل حساب"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"‏تلاش‎های زیادی برای کشیدن الگو صورت گرفته است"</string>
     <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"‏برای بازگشایی قفل، با حساب Google خود وارد سیستم شوید."</string>
-    <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"نام کاربری (رایانامه)"</string>
+    <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"نام کاربری (ایمیل)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"گذرواژه"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ورود به سیستم"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"نام کاربر یا گذرواژه نامعتبر است."</string>
@@ -1041,15 +1058,15 @@
     <string name="copyUrl" msgid="2538211579596067402">"‏کپی URL"</string>
     <string name="selectTextMode" msgid="1018691815143165326">"انتخاب متن"</string>
     <string name="undo" msgid="7905788502491742328">"لغو"</string>
-    <string name="redo" msgid="7759464876566803888">"انجام مجدد"</string>
+    <string name="redo" msgid="7759464876566803888">"بازانجام"</string>
     <string name="autofill" msgid="3035779615680565188">"تکمیل خودکار"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"انتخاب متن"</string>
     <string name="addToDictionary" msgid="4352161534510057874">"افزودن به واژه‌نامه"</string>
     <string name="deleteText" msgid="6979668428458199034">"حذف"</string>
     <string name="inputMethod" msgid="1653630062304567879">"روش ورودی"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"کنش‌های متنی"</string>
-    <string name="email" msgid="4560673117055050403">"رایانامه"</string>
-    <string name="email_desc" msgid="3638665569546416795">"ارسال رایانامه به نشانی انتخابی"</string>
+    <string name="email" msgid="4560673117055050403">"ایمیل"</string>
+    <string name="email_desc" msgid="3638665569546416795">"ارسال ایمیل به نشانی انتخابی"</string>
     <string name="dial" msgid="1253998302767701559">"تماس"</string>
     <string name="dial_desc" msgid="6573723404985517250">"تماس با شماره تلفن انتخابی"</string>
     <string name="map" msgid="5441053548030107189">"نقشه"</string>
@@ -1413,7 +1430,7 @@
     <string name="disable_tether_notification_message" msgid="2913366428516852495">"برای جزئیات، با سرپرستتان تماس بگیرید"</string>
     <string name="back_button_label" msgid="2300470004503343439">"برگشت"</string>
     <string name="next_button_label" msgid="1080555104677992408">"بعدی"</string>
-    <string name="skip_button_label" msgid="1275362299471631819">"پرش"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"رد شدن"</string>
     <string name="no_matches" msgid="8129421908915840737">"مورد منطبقی موجود نیست"</string>
     <string name="find_on_page" msgid="1946799233822820384">"یافتن در صفحه"</string>
     <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
@@ -1569,7 +1586,7 @@
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"پین کدها منطبق نیستند"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"‏تلاش‎های زیادی برای کشیدن الگو صورت گرفته است"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"‏برای بازگشایی قفل، با حساب Google خود وارد سیستم شوید."</string>
-    <string name="kg_login_username_hint" msgid="5718534272070920364">"نام کاربری (رایانامه)"</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"نام کاربری (ایمیل)"</string>
     <string name="kg_login_password_hint" msgid="9057289103827298549">"گذرواژه"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"ورود به سیستم"</string>
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"نام کاربری یا گذرواژه نامعتبر."</string>
@@ -1584,9 +1601,9 @@
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"شما به اشتباه <xliff:g id="NUMBER">%d</xliff:g> بار اقدام به باز کردن قفل رایانه لوحی کرده‌اید. رایانه لوحی اکنون به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"<xliff:g id="NUMBER">%d</xliff:g> دفعه به صورت نادرست سعی کرده‌اید قفل تلویزیون را باز کنید. اکنون تلویزیون به تنظیمات پیش‌فرض کارخانه بازنشانی خواهد شد."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"شما به اشتباه <xliff:g id="NUMBER">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کرده‌اید. این تلفن اکنون به پیش‌فرض کارخانه بازنشانی می‌شود."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"‏شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب رایانامه قفل رایانه لوحی خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"الگوی بازگشایی‌تان را <xliff:g id="NUMBER_0">%1$d</xliff:g> دفعه به صورت نادرست رسم کرده‌اید. <xliff:g id="NUMBER_1">%2$d</xliff:g> پس از \n تلاش ناموفق دیگر، از شما خواسته می‌شود تا با استفاده از یک حساب رایانامه، قفل تلویزیون‌تان را باز کنید.\n پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"‏شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب رایانامه قفل تلفن خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"‏شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل رایانه لوحی خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"الگوی بازگشایی‌تان را <xliff:g id="NUMBER_0">%1$d</xliff:g> دفعه به صورت نادرست رسم کرده‌اید. <xliff:g id="NUMBER_1">%2$d</xliff:g> پس از \n تلاش ناموفق دیگر، از شما خواسته می‌شود تا با استفاده از یک حساب ایمیل، قفل تلویزیون‌تان را باز کنید.\n پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"‏شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل تلفن خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"حذف"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"میزان صدا را به بالاتر از حد توصیه شده افزایش می‌دهید؟\n\nگوش دادن به صداهای بلند برای مدت طولانی می‌تواند به شنوایی‌تان آسیب وارد کند."</string>
@@ -1875,13 +1892,18 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‏<xliff:g id="TYPE">%1$s</xliff:g> در &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ذخیره شود؟"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‏<xliff:g id="TYPE_0">%1$s</xliff:g> و <xliff:g id="TYPE_1">%2$s</xliff:g> در &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ذخیره شوند؟"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‏<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> و <xliff:g id="TYPE_2">%3$s</xliff:g> در &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ذخیره شوند؟"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"‏به &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; به‌روزرسانی شود؟"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‏<xliff:g id="TYPE">%1$s</xliff:g> به &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; به‌روزرسانی شود؟"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‏<xliff:g id="TYPE_0">%1$s</xliff:g> و <xliff:g id="TYPE_1">%2$s</xliff:g> به &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; به‌روزرسانی شود؟"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‏<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g>، و <xliff:g id="TYPE_2">%3$s</xliff:g> به &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; به‌روزرسانی شود؟"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ذخیره"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"نه سپاسگزارم"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"به‌روزرسانی"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"گذرواژه"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"نشانی"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"کارت‌ اعتباری"</string>
     <string name="autofill_save_type_username" msgid="239040540379769562">"نام کاربری"</string>
-    <string name="autofill_save_type_email_address" msgid="5752949432129262174">"نشانی رایانامه"</string>
+    <string name="autofill_save_type_email_address" msgid="5752949432129262174">"نشانی ایمیل"</string>
     <string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"آرام باشید و پناهگاهی در این اطراف پیدا کنید."</string>
     <string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"فوراً مناطق ساحلی و محدوده رودخانه را ترک کنید و به جایی امن، مثل ارتفاعات بروید."</string>
     <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"آرام باشید و پناهگاهی در این اطراف پیدا کنید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index e7a56c4..e13a01f 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lentokonetila"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lentokonetila on KÄYTÖSSÄ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lentokonetila on POIS KÄYTÖSTÄ"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Virransäästö"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Virransäästö on POISSA KÄYTÖSTÄ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Virransäästö on KÄYTÖSSÄ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Asetukset"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Auta"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ääniapuri"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Kehon anturit"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"käyttää anturitietoja elintoiminnoistasi"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; käyttää anturitietoja elintoiminnoistasi?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musiikki"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"käyttää musiikkiasi"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; käyttää musiikkiasi?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Kuvat ja videot"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"käyttää kuvia ja videoita"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; käyttää kuviasi ja videoitasi?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Noutaa ikkunan sisältöä"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Tarkistaa käyttämäsi ikkunan sisältö."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Ottaa kosketuksella tutkimisen käyttöön"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Sallii sovelluksen käyttää menetelmiä, joilla voidaan lisätä tai poistaa sormenjälkimalleja."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"sormenjälkilaitteiston käyttö"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Sallii sovelluksen käyttää sormenjälkilaitteistoa todennukseen."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"lukea musiikkikokoelmaasi"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Antaa sovelluksen lukea musiikkikokoelmaasi."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"muokata musiikkikokoelmaasi"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Antaa sovelluksen muokata musiikkikokoelmaasi."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"lukea videokokoelmaasi"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Antaa sovelluksen lukea videokokoelmaasi."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"muokata videokokoelmaasi"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Antaa sovelluksen muokata videokokoelmaasi."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"lukea kuvakokoelmaasi"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Antaa sovelluksen lukea kuvakokoelmaasi."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"muokata kuvakokoelmaasi"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Antaa sovelluksen muokata kuvakokoelmaasi."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"lukea mediakokoelmasi sijainteja"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Antaa sovelluksen lukea mediakokoelmasi sijainteja."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Sormenjälki havaittiin vain osittain. Yritä uudelleen."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Sormenjäljen käsittely epäonnistui. Yritä uudelleen."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sormenjälkitunnistin on likainen. Puhdista tunnistin ja yritä uudelleen."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Tallennetaanko <xliff:g id="TYPE">%1$s</xliff:g> palveluun &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> palveluun &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> palveluun &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Muutetaanko tämä palvelussa &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Muutetaanko <xliff:g id="TYPE">%1$s</xliff:g>, jonka &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; on tallentanut?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Muutetaanko <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g>, jotka &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; on tallentanut?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Muutetaanko <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g>, jotka &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; on tallentanut?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Tallenna"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ei kiitos"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Muuta"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"salasana"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"osoite"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"luottokortti"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index f0d7776e..2409202 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Le mode Avion est activé."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Le mode Avion est désactivé."</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Économie d\'énergie"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"La fonction Économie d\'énergie est désactivée"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"La fonction Économie d\'énergie est activée"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Paramètres"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assistance"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assist. vocale"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Capteurs corporels"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"accéder aux données des capteurs sur vos signes vitaux"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à accéder aux données des capteurs pour vos signes vitaux?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musique"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"accéder à votre musique"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à votre musique?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Photos et vidéos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"accéder à vos photos et à vos vidéos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à vos photos et à vos videos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Récupérer le contenu d\'une fenêtre"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecter le contenu d\'une fenêtre avec laquelle vous interagissez."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Activer la fonctionnalité Explorer au toucher"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet à l\'application de faire appel à des méthodes d\'ajout et de suppression de modèles d\'empreinte digitale que vous pouvez utiliser."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"utiliser le matériel d\'empreinte digitale"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permet à l\'application d\'utiliser du matériel d\'empreinte digitale pour l\'authentification"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"lire votre collection de musique"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Autorise l\'application à lire votre collection de musique."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modifier votre collection de musique"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Autorise l\'application à modifier votre collection de musique."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"lire votre collection de vidéos"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Autorise l\'application à lire votre collection de vidéos."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modifier votre collection de vidéos"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Autorise l\'application à modifier votre collection de vidéos."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"lire votre collection de photos"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Autorise l\'application à lire votre collection de photos."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modifier votre collection de photos"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Autorise l\'application à modifier votre collection de photos."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"lire les positions issues de votre collection multimédia"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Autorise l\'application à lire les positions indiquées dans votre collection multimédia."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte digitale partielle détectée. Veuillez essayer de nouveau."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossible de traiter les empreintes digitales. Veuillez essayer de nouveau."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Le capteur d\'empreintes digitales est sale. Veuillez le nettoyer et essayer de nouveau."</string>
@@ -1213,7 +1230,7 @@
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Touchez pour afficher les options"</string>
     <string name="wifi_softap_config_change" msgid="8475911871165857607">"Modifications apportées à vos paramètres de point d\'accès"</string>
     <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"La bande de votre point d\'accès a changé."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Cet appareil ne prend pas en charge votre préférence pour le 5 GHz seulement. Au lieu de cela, cet appareil utilisera la bande de 5 GHz lorsqu\'elle sera disponible."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Cet appareil ne prend pas en charge votre préférence pour la bande de 5 GHz seulement. Au lieu de cela, cet appareil utilisera la bande de 5 GHz lorsqu\'elle sera disponible."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"Passé au réseau <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"L\'appareil utilise <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quand <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> n\'a pas d\'accès à Internet. Des frais peuvent s\'appliquer."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"Passé du réseau <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> au <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Mettre à jour vers &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Mettre à jour <xliff:g id="TYPE">%1$s</xliff:g> vers &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Mettre à jour <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> vers &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Mettre à jour <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> vers &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Mettre à jour"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"mot de passe"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"carte de crédit"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index a402285..9c8a7e7 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Le mode Avion est activé."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Le mode Avion est désactivé."</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Économiseur de batterie"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Économiseur de batterie DÉSACTIVÉ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Économiseur de batterie ACTIVÉ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Paramètres"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assistance"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assistance vocale"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Capteurs corporels"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"accéder aux données des capteurs relatives à vos signes vitaux"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Permettre à &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; d\'accéder aux données des capteurs relatives à vos signes vitaux ?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musique"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"accéder à votre musique"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à votre musique ?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Photos et vidéos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"accéder à vos photos et vos vidéos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à vos photos et vidéos ?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Récupérer le contenu d\'une fenêtre"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecte le contenu d\'une fenêtre avec laquelle vous interagissez."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Activer la fonctionnalité Explorer au toucher"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Autoriser l\'application à invoquer des méthodes pour ajouter et supprimer des modèles d\'empreintes digitales"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utiliser le matériel d\'empreintes digitales"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autoriser l\'application à utiliser le matériel d\'empreintes digitales pour l\'authentification"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"consulter votre bibliothèque musicale"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Autorise l\'application à consulter votre bibliothèque musicale."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modifier votre bibliothèque musicale"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Autorise l\'application à modifier votre bibliothèque musicale."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"consulter votre bibliothèque vidéo"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Autorise l\'application à consulter votre bibliothèque vidéo."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modifier votre bibliothèque vidéo"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Autorise l\'application à modifier votre bibliothèque vidéo."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"consulter votre bibliothèque photo"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Autorise l\'application à consulter votre bibliothèque photo."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modifier votre bibliothèque photo"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Autorise l\'application à modifier votre bibliothèque photo."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"consulter des positions issues de votre bibliothèque multimédia"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Autorise l\'application à consulter des positions issues de votre bibliothèque multimédia."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte numérique partiellement détectée. Veuillez réessayer."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossible de reconnaître l\'empreinte numérique. Veuillez réessayer."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Le lecteur d\'empreintes numériques est sale. Veuillez le nettoyer, puis réessayer."</string>
@@ -641,7 +658,7 @@
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Désactiver les appareils photo"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Empêcher l\'utilisation de tous les appareils photos"</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Désact. options du verr. écran"</string>
-    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Empêchez l\'utilisation de certaines fonctionnalités du verrouillage de l\'écran."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Empêcher l\'utilisation de certaines fonctionnalités du verrouillage de l\'écran."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domicile"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -1281,7 +1298,7 @@
     <string name="no_permissions" msgid="7283357728219338112">"Aucune autorisation requise"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"Cela peut engendrer des frais"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="usb_charging_notification_title" msgid="1595122345358177163">"Rechargement via USB de cet appareil"</string>
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"Appareil en charge via USB"</string>
     <string name="usb_supplying_notification_title" msgid="4631045789893086181">"Rechargement via USB de l\'appareil connecté"</string>
     <string name="usb_mtp_notification_title" msgid="4238227258391151029">"Transfert de fichiers via USB activé"</string>
     <string name="usb_ptp_notification_title" msgid="5425857879922006878">"PTP via USB activé"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Faire passer à &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Faire passer <xliff:g id="TYPE">%1$s</xliff:g> à &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Faire passer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> à &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Faire passer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> à &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Mettre à jour"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"mot de passe"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"carte de paiement"</string>
@@ -1897,7 +1919,7 @@
     <string name="mmcc_illegal_ms_msim_template" msgid="5994323296399913454">"Carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> non autorisée"</string>
     <string name="mmcc_illegal_me_msim_template" msgid="5550259730350571826">"Carte SIM <xliff:g id="SIMNUMBER">%d</xliff:g> non autorisée"</string>
     <string name="popup_window_default_title" msgid="4874318849712115433">"Fenêtre pop-up"</string>
-    <string name="slice_more_content" msgid="8504342889413274608">"<xliff:g id="NUMBER">%1$d</xliff:g> autres"</string>
+    <string name="slice_more_content" msgid="8504342889413274608">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="shortcut_restored_on_lower_version" msgid="4860853725206702336">"La version de l\'application est revenue à une version antérieure ou n\'est pas compatible avec cet raccourci"</string>
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Le raccourci ne peut pas être restauré car l\'application n\'accepte pas la sauvegarde et la restauration"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Le raccourci ne peut pas être restauré car la signature de l\'application est différente"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 6424135..27efff8 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -130,7 +130,7 @@
   </string-array>
   <string-array name="wfcSpnFormats">
     <item msgid="6830082633573257149">"%s"</item>
-    <item msgid="4397097370387921767">"Chamadas wifi de %s"</item>
+    <item msgid="4397097370387921767">"Chamadas por wifi de %s"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desactivado"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wifi preferida"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"O modo avión está activado"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"O modo avión está desactivado"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Aforro de batería"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"A función Aforro de batería está DESACTIVADA"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"A función Aforro de batería está ACTIVADA"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Configuración"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Asistencia"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistente voz"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores corporais"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"acceder aos datos do sensor sobre as túas constantes vitais"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda aos datos do sensor sobre as túas constantes vitais?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Música"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"acceder á música"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda á túa música?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotos e vídeos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"acceder ás fotos e aos vídeos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda ás túas fotos e vídeos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperar contido da ventá"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecciona o contido dunha ventá coa que estás interactuando."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Activar a exploración táctil"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que a aplicación invoque métodos para engadir e eliminar modelos de uso de impresión dixital."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"usar hardware de impresión dixital"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que a aplicación utilice hardware de impresión dixital para a autenticación"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ler a túa colección de música"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Permite que a aplicación lea a túa colección de música."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modificar a túa colección de música"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permite que a aplicación modifique a túa colección de música."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ler a túa colección de vídeos"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Permite que a aplicación lea a túa colección de vídeos."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modificar a túa colección de vídeos"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Permite que a aplicación modifique a túa colección de vídeos."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ler a túa colección de fotos"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Permite que a aplicación lea a túa colección de fotos."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modificar a túa colección de fotos"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que a aplicación modifique a túa colección de fotos."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ler localizacións da túa colección multimedia"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que a aplicación lea as localizacións da túa colección multimedia."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Detectouse unha impresión dixital parcial. Téntao de novo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Non se puido procesar a impresión dixital. Téntao de novo."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"O sensor de impresión dixital está sucio. Límpao e téntao de novo."</string>
@@ -525,8 +542,8 @@
     <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"usar hardware de autenticación facial"</string>
     <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Permite que a aplicación utilice hardware facial para a autenticación"</string>
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"Non se puido procesar a cara. Téntao de novo."</string>
-    <string name="face_acquired_too_bright" msgid="610606792381297174">"A cara brilla moito. Proba con menos luz."</string>
-    <string name="face_acquired_too_dark" msgid="7229162716976778371">"A cara está moi escura. Proba con máis luz."</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"A cara vese demasiado brillante. Proba con menos luz."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"A cara vese demasiado escura. Proba con máis luz."</string>
     <string name="face_acquired_too_close" msgid="1980310037427755293">"Afasta o sensor da cara."</string>
     <string name="face_acquired_too_far" msgid="4494571381828850007">"Achega o sensor á cara."</string>
     <string name="face_acquired_too_high" msgid="228411096134808372">"Sube máis o sensor."</string>
@@ -1876,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Queres gardar <xliff:g id="TYPE">%1$s</xliff:g> en: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Queres gardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> en: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Queres gardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> en: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Queres actualizar &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; con estes datos?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Queres actualizar &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; con estes datos (<xliff:g id="TYPE">%1$s</xliff:g>)?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Queres actualizar &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; con estes datos (<xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g>)?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Queres actualizar &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; con estes datos (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>)?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Gardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Non, grazas"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Actualizar"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"contrasinal"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"enderezo"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"tarxeta de crédito"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index a473243..5e6c34d 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"એરપ્લેન મોડ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"એરપ્લેન મોડ ચાલુ છે."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"એરપ્લેન મોડ બંધ છે."</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"બૅટરી સેવર"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"બૅટરી સેવર બંધ છે"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"બૅટરી સેવર ચાલુ છે"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"સેટિંગ્સ"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"સહાય"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"વૉઇસ સહાય"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"બોડી સેન્સર્સ"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"તમારા મહત્વપૂર્ણ ચિહ્નો વિશે સેન્સર ડેટા ઍક્સેસ કરો"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારી મહત્વપૂર્ણ સહી વિશેના સેન્સર ડેટાને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"સંગીત"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"તમારા સંગીતને ઍક્સેસ કરો"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા સંગીતમાં ઍક્સેસ કરવાની મંજૂરી આપવી છે?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ફોટો અને વિડિઓ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"તમારા ફોટો &amp; વિડિઓ ઍક્સેસ કરો"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ને તમારા ફોટો &amp; વિડિઓમાં ઍક્સેસ કરવાની મંજૂરી આપવી છે?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"વિંડો કન્ટેન્ટ પુનઃપ્રાપ્ત કરો"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"તમે જેની સાથે ક્રિયા-પ્રતિક્રિયા કરી રહ્યાં છો તે વિંડોનું કન્ટેન્ટ તપાસો."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"સ્પર્શ કરીને શોધખોળ કરવું ચાલુ કરો"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"એપ્લિકેશનને ઉપયોગ માટે ફિંગરપ્રિન્ટ નમૂના ઉમેરવા અને કાઢી નાખવા માટે પદ્ધતિઓની વિનંતી કરવાની મંજૂરી આપે છે."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ફિંગરપ્રિન્ટ હાર્ડવેરનો ઉપયોગ કરો"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"એપ્લિકેશનને પ્રમાણીકરણ માટે ફિંગરપ્રિન્ટ હાર્ડવેરનો ઉપયોગ કરવાની મંજૂરી આપે છે"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"આપનો સંગીત સંગ્રહ વાંચવો"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"એપને તમારો સંગીત સંગ્રહ વાંચવાની મંજૂરી આપે છે."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"આપનો સંગીત સંગ્રહ સંશોધિત કરવો"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"એપને તમારો સંગીત સંગ્રહ સંશોધિત કરવાની મંજૂરી આપે છે."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"આપનો વીડિઓ સંગ્રહ વાંચવો"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"એપને તમારો વિડિઓ સંગ્રહ વાંચવાની મંજૂરી આપે છે."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"આપનો વિડિઓ સંગ્રહ સંશોધિત કરવો"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"એપને તમારો વિડિઓ સંગ્રહ સંશોધિત કરવાની મંજૂરી આપે છે."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"આપનો ફોટો સંગ્રહ વાંચવો"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"એપને તમારો ફોટો સંગ્રહ વાંચવાની મંજૂરી આપે છે."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"આપનો સંગીત સંગ્રહ સંશોધિત કરવો"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"એપને તમારો ફોટો સંગ્રહ સંશોધિત કરવાની મંજૂરી આપે છે."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"આપના મીડિયા સંગ્રહમાંથી સ્થાનો વાંચવા"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"એપને તમારા મીડિયા સંગ્રહમાંથી સ્થાનો વાંચવાની મંજૂરી આપે છે."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"આંશિક ફિંગરપ્રિન્ટ મળી. કૃપા કરીને ફરી પ્રયાસ કરો."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ફિંગરપ્રિન્ટ પ્રક્રિયા કરી શકાઈ નથી. કૃપા કરીને ફરી પ્રયાસ કરો."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ફિંગરપ્રિન્ટ સેન્સર ગંદું છે. કૃપા કરીને સાફ કરો અને ફરી પ્રયાસ કરો."</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ફિંગરપ્રિન્ટ આયકન"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"ચહેરા પ્રમાણીકરણના હાર્ડવેરને મેનેજ કરો"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"ઍપને ઉપયોગ માટે ચહેરાના નમૂના ઉમેરવા અને ડિલીટ કરવાની પદ્ધતિને રદ કરવાની મંજૂરી આપે છે."</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"ચહેરા પ્રમાણીકરણના હાર્ડવેરનો ઉપયોગ કરો"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"ઍપને પ્રમાણીકરણ માટે ચહેરા પ્રમાણીકરણના હાર્ડવેરનો ઉપયોગ કરવાની મંજૂરી આપે છે"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"ચહેરાની પ્રક્રિયા કરી શકાઈ નથી. ફરી પ્રયાસ કરો."</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"ચહેરો ખૂબ ચળકે છે. કૃપા કરીને ઓછા પ્રકાશવાળા સ્થાનમાં પ્રયાસ કરો."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"ચહેરો ખૂબ શ્યામ છે. કૃપા કરીને પ્રકાશના સૉર્સ ઉઘાડો."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"કૃપા કરીને સેન્સરને ચહેરાથી દૂર ખસેડો."</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"કૃપા કરીને સેન્સરને ચહેરાની નજીક ખસેડો."</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"કૃપા કરીને સેન્સરને ઉપર ખસેડો."</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"કૃપા કરીને સેન્સર નીચે ખસેડો."</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"કૃપા કરીને સેન્સરને જમણી બાજુ ખસેડો."</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"કૃપા કરીને સેન્સરને ડાબી બાજુ ખસેડો."</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"કૃપા કરીને સેન્સરની સામે જુઓ."</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"કોઈ ચહેરો મળ્યો નથી."</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"ઉપકરણની સામે ચહેરો સ્થિર રાખો."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"ચહેરા માટેનું હાર્ડવેર ઉપલબ્ધ નથી."</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"ચહેરા માટેનો સમય સમાપ્ત થયો. ફરી પ્રયાસ કરો."</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"ચહેરો સંગ્રહિત કરી શકાશે નહીં."</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"ચહેરા સંબંધિત કાર્યવાહી રદ કરવામાં આવી છે."</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"ઘણા બધા પ્રયત્નો. થોડા સમય પછી ફરી પ્રયાસ કરો."</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ઘણા બધા પ્રયત્નો. ચહેરાનું પ્રમાણીકરણ બંધ કરવામાં આવ્યું છે."</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"ફરી પ્રયાસ કરો."</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"કોઈ ચહેરાની નોંધણી કરવામાં આવી નથી."</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"આ ઉપકરણમાં ચહેરાના પ્રમાણીકરણ માટે કોઈ સેન્સર નથી"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"ચહેરાનું <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"ચહેરા આઇકન"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"સમન્વયન સેટિંગ્સ વાંચો"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ઍપ્લિકેશનને એકાઉન્ટ માટે સમન્વયન સેટિંગ્સને વાંચવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આ એકાઉન્ટ સાથે લોકો ઍપ્લિકેશન સમન્વયિત થઈ છે કે કેમ તે નિર્ધારિત કરી શકે છે."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"સમન્વયન ચાલુ અને બંધ ટોગલ કરો"</string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"વાઇ-ફાઇને કોઈ ઇન્ટરનેટ ઍક્સેસ નથી"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"વિકલ્પો માટે ટૅપ કરો"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"તમારી હૉટસ્પૉટ સેટિંગને બદલે છે"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"તમારું હૉટસ્પૉટ બેન્ડ બદલાયેલ છે."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"આ ઉપકરણ તમારી ફક્ત 5GHz માટેની પસંદગીને સમર્થન આપતું નથી. તેના બદલે, જ્યારે આ ઉપકરણ જ્યારે 5GHz બેન્ડ ઉપલબ્ધ હશે ત્યારે તેનો ઉપયોગ કરશે."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> પર સ્વિચ કર્યું"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"જ્યારે <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ <xliff:g id="NEW_NETWORK">%1$s</xliff:g>નો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> પરથી <xliff:g id="NEW_NETWORK">%2$s</xliff:g> પર સ્વિચ કર્યું"</string>
@@ -1906,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;માં સાચવીએ?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> અને <xliff:g id="TYPE_1">%2$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;માં સાચવીએ?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> અને <xliff:g id="TYPE_2">%3$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;માં સાચવીએ?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; પર અપડેટ કરવું છે?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; પર અપડેટ કરવું છે?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> અને <xliff:g id="TYPE_1">%2$s</xliff:g> ને &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; પર અપડેટ કરવું છે?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> અને <xliff:g id="TYPE_2">%3$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;પર અપડેટ કરવું છે?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"સાચવો"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ના, આભાર"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"અપડેટ કરો"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"પાસવર્ડ"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"સરનામું"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ક્રેડિટ કાર્ડ"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index e00ade1..a85d6fa 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"हवाई जहाज मोड"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"हवाई जहाज मोड चालू है"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"हवाई जहाज मोड बंद है"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"बैटरी सेवर"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"बैटरी सेवर बंद है"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"बैटरी सेवर चालू है"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"सेटिंग"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"सहायता"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"आवाज़ से डिवाइस का इस्तेमाल"</string>
@@ -303,6 +300,18 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"शरीर संवेदक"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"अपने महत्वपूर्ण संकेतों के बारे में सेंसर डेटा को ऐक्सेस करें"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने स्वास्थ्य से जुड़ी ज़रूरी जानकारी इस्तेमाल करने की अनुमति देना चाहते हैं?"</string>
+    <!-- no translation found for permgrouplab_aural (965607064083134896) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_aural (4870189506255958055) -->
+    <skip />
+    <!-- no translation found for permgrouprequest_aural (6787926123071735620) -->
+    <skip />
+    <!-- no translation found for permgrouplab_visual (8030190588123857921) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_visual (3415827902566663546) -->
+    <skip />
+    <!-- no translation found for permgrouprequest_visual (6907523945030290376) -->
+    <skip />
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"विंडो की सामग्री वापस पाएं"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"उस विंडो की सामग्री की जाँच करें, जिसका आप इस्तेमाल कर रहे हैं."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"छूकर, किसी चीज़ से जुड़ी जानकारी सुनने की सुविधा चालू करें"</string>
@@ -497,6 +506,34 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"उंगली की छाप वाले टेम्पलेट का उपयोग करने के लिए जोड़ने और हटाने हेतु ऐप को विधियां प्रारंभ करने देती है."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"उंगली की छाप के लिए हार्डवेयर का उपयोग करें"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ऐप के प्रमाणीकरण के लिए उंगली की छाप हार्डवेयर का उपयोग करने देती है"</string>
+    <!-- no translation found for permlab_audioRead (6617225220728465565) -->
+    <skip />
+    <!-- no translation found for permdesc_audioRead (5034032570243484805) -->
+    <skip />
+    <!-- no translation found for permlab_audioWrite (2661772059799779292) -->
+    <skip />
+    <!-- no translation found for permdesc_audioWrite (8888544708166230494) -->
+    <skip />
+    <!-- no translation found for permlab_videoRead (9182618678674737229) -->
+    <skip />
+    <!-- no translation found for permdesc_videoRead (7045676429859396194) -->
+    <skip />
+    <!-- no translation found for permlab_videoWrite (128769316366746446) -->
+    <skip />
+    <!-- no translation found for permdesc_videoWrite (5448565757490640841) -->
+    <skip />
+    <!-- no translation found for permlab_imagesRead (3015078545742665304) -->
+    <skip />
+    <!-- no translation found for permdesc_imagesRead (3144263806038695580) -->
+    <skip />
+    <!-- no translation found for permlab_imagesWrite (3391306186247235510) -->
+    <skip />
+    <!-- no translation found for permdesc_imagesWrite (7073662756617474375) -->
+    <skip />
+    <!-- no translation found for permlab_mediaLocation (8675148183726247864) -->
+    <skip />
+    <!-- no translation found for permdesc_mediaLocation (2237023389178865130) -->
+    <skip />
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फ़िंगरप्रिंट की पहचान की गई. कृपया पुनः प्रयास करें."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फ़िंगरप्रिंट संसाधित नहीं हो सका. कृपया पुन: प्रयास करें."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फ़िंगरप्रिंट सेंसर गंदा है. कृपया साफ़ करें और फिर कोशिश करें."</string>
@@ -520,64 +557,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"फ़िंगरप्रिंट आइकॉन"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"चेहरे की पुष्टि करने वाला हार्डवेयर प्रबंधित करें"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"ऐप्लिकेशन को चेहरे के टेम्पलेट इस्तेमाल के तरीके जोड़ने और मिटाने की मंज़ूरी मिलती है."</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"चेहरे की पुष्टि करने वाला हार्डवेयर इस्तेमाल करें"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"ऐप्लिकेशन को चेहरे की पुष्टि करने वाले हार्डवेयर का इस्तेमाल करने की मंज़ूरी मिलती है"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"चेहरे की पहचान नहीं हो पाई. कृपया फिर कोशिश करें."</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"चेहरे पर रोशनी ज़्यादा है. कृपया कम रोशनी में कोशिश करें."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"चेहरे पर रोशनी बहुत कम है. कृपया रोशनी बढ़ाएं."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"कृपया डिवाइस को चेहरे से दूर ले जाएं."</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"कृपया डिवाइस को चेहरे के करीब लाएं."</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"कृपया डिवाइस को ऊपर करें."</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"कृपया डिवाइस को नीचे की ओर ले जाएं."</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"कृपया डिवाइस को चेहरे की दाईं ओर ले जाएं."</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"कृपया डिवाइस को चेहरे के बाईं ओर ले जाएं."</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"कृपया सेंसर की ओर देखें."</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"चेहरे की पहचान नहीं हो पाई."</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"डिवाइस के सामने चेहरे को स्थिर रखें."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"चेहरे की पहचान करने वाला हार्डवेयर मौजूद नहीं है."</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"चेहरे की पहचान का समय खत्म हुआ. फिर से कोशिश करें."</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"चेहरा सेव करने की सीमा पूरी हो गई है."</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"चेहरा पहचानने की कार्रवाई रद्द की गई."</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"कई बार कोशिश की गई. बाद में कोशिश करें."</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"कई बार कोशिश की. चेहरा पहचानने की सुविधा बंद हुई."</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"फिर से कोशिश करें."</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"कोई चेहरा रजिस्टर नहीं किया गया है."</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"इस डिवाइस में चेहरे की पहचान करने वाला सेंसर नहीं है"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"चेहरा <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"चेहरे का आइकॉन"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"समन्वयन सेटिंग पढ़ें"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ऐप्स  को किसी खाते की समन्वयन सेटिंग पढ़ने देता है. उदाहरण के लिए, इससे यह निर्धारित किया जा सकता है कि लोग ऐप्स  किसी खाते के साथ समन्‍वयित है या नहीं."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"समन्‍वयन बंद या चालू टॉगल करें"</string>
@@ -1238,12 +1248,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"वाई-फ़ाई के लिए इंटरनेट नहीं मिल रहा है"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"विकल्पों के लिए टैप करें"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"आपकी हॉटस्पॉट सेटिंग के हिसाब से बदलाव हो गए हैं"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"आपका हॉटस्पॉट बैंड बदल गया है."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"यह डिवाइस सिर्फ़ 5 गीगाहर्ट्ज़ की आपकी पसंद की सेटिंग पर काम नहीं करता, लेकिन जब भी 5 गीगाहर्ट्ज़ बैंड मौजूद होगा, डिवाइस उसका इस्तेमाल करने लगेगा."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> पर ले जाया गया"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> में इंटरनेट की सुविधा नहीं होने पर डिवाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> का इस्तेमाल करता है. इसके लिए शुल्क लिया जा सकता है."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> से <xliff:g id="NEW_NETWORK">%2$s</xliff:g> पर ले जाया गया"</string>
@@ -1905,8 +1912,18 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> को &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; में सेव करें?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> और <xliff:g id="TYPE_1">%2$s</xliff:g> को &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; में सेव करें?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> और <xliff:g id="TYPE_2">%3$s</xliff:g> को &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; में सेव करें?"</string>
+    <!-- no translation found for autofill_update_title (4879673117448810818) -->
+    <skip />
+    <!-- no translation found for autofill_update_title_with_type (339733442087186755) -->
+    <skip />
+    <!-- no translation found for autofill_update_title_with_2types (6321714204167424745) -->
+    <skip />
+    <!-- no translation found for autofill_update_title_with_3types (5866735124066629287) -->
+    <skip />
     <string name="autofill_save_yes" msgid="6398026094049005921">"सेव करें"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"नहीं, धन्यवाद"</string>
+    <!-- no translation found for autofill_update_yes (310358413273276958) -->
+    <skip />
     <string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"पता"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 2b742ae..f24a3c4 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -239,9 +239,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način rada u zrakoplovu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uključen je način rada u zrakoplovu"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Isključen je način rada u zrakoplovu"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Štednja baterije"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Štednja baterije isključena"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Štednja baterije uključena"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Postavke"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Pomoć"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glasovna pomoć"</string>
@@ -306,6 +303,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Biometrijski senzori"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"pristupiti podacima senzora o vašim vitalnim znakovima"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa podacima senzora o vašim vitalnim znakovima?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Glazba"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"pristup glazbi"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa vašoj glazbi?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotografije i videozapisi"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"pristup fotografijama i &amp; videozapisima"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa vašim fotografijama i videozapisima?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Dohvaćati sadržaj prozora"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Pregledat će sadržaj prozora koji upotrebljavate."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Uključiti značajku Istraži dodirom"</string>
@@ -500,6 +503,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Aplikaciji omogućuje pozivanje načina za dodavanje i brisanje predložaka otisaka prstiju koji će se upotrijebiti."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"upotreba hardvera za čitanje otisaka prstiju"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Aplikaciji omogućuje upotrebu hardvera za čitanje otisaka prstiju radi autentifikacije."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"čitanje vaše glazbene zbirke"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Omogućuje aplikaciji čitanje vaše glazbene zbirke."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"izmjena vaše glazbene zbirke"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Omogućuje aplikaciji izmjenu vaše glazbene zbirke."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"čitanje vaše zbirke videozapisa"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Omogućuje aplikaciji čitanje vaše zbirke videozapisa."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"izmjena vaše zbirke videozapisa"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Omogućuje aplikaciji izmjenu vaše kolekcije videozapisa."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"čitanje vaše zbirke fotografija"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Omogućuje aplikaciji čitanje vaše zbirke fotografija."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"izmjena vaše zbirke fotografija"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Omogućuje aplikaciji izmjenu vaše zbirke fotografija."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"čitanje lokacija iz vaše medijske zbirke"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Omogućuje aplikaciji čitanje lokacija iz vaše medijske zbirke."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Otkriven je djelomični otisak prsta. Pokušajte ponovo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Obrada otiska prsta nije uspjela. Pokušajte ponovo."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Senzor otiska prsta nije čist. Očistite ga i pokušajte ponovo."</string>
@@ -1910,8 +1927,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Želite li da se podatak (<xliff:g id="TYPE">%1$s</xliff:g>) spremi na uslugu &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> spreme na uslugu &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> spreme na uslugu &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Želite li ažurirati na &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Želite li polje <xliff:g id="TYPE">%1$s</xliff:g> ažurirati na &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Želite li polja <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> ažurirati na &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Želite li polja <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> ažurirati na &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Spremi"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Ažuriraj"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"zaporku"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresu"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditnu karticu"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 7fb0cbb..e7c1bf2 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Repülőgép üzemmód"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Repülőgép üzemmód bekapcsolva"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Repülőgép üzemmód kikapcsolva"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Akkumulátorkímélő mód"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Akkumulátorkímélő mód kikapcsolva"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Akkumulátorkímélő mód bekapcsolva"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Beállítások"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Segítség"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Hangsegéd"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Testérzékelők"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"az érzékelők által mért, életjelekkel kapcsolatos adatok elérése"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hozzáférjen az életjelekkel kapcsolatos szenzoradatokhoz?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Zene"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"hozzáférés a zenékhez"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt számára, hogy hozzáférjen az Ön zenéihez?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fényképek és videók"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"hozzáférés a fényképekhez és videókhoz"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt számára, hogy hozzáférjen a fotókhoz és videókhoz?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Ablaktartalom lekérdezése"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"A használt ablak tartalmának vizsgálata."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Felfedezés érintéssel bekapcsolása"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Lehetővé teszi az alkalmazás számára a használni kívánt ujjlenyomatsablonok hozzáadására és törlésére szolgáló metódusok indítását."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ujjlenyomat-olvasó hardver használata"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Lehetővé teszi az alkalmazás számára az ujjlenyomat-olvasó hardver hitelesítésre való használatát"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"a zenei gyűjtemény olvasása"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Engedélyezi az alkalmazásnak a zenei gyűjtemény olvasását."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"a zenei gyűjtemény módosítása"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Engedélyezi az alkalmazásnak a zenei gyűjtemény módosítását."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"a videógyűjtemény olvasása"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Engedélyezi az alkalmazásnak a videógyűjtemény olvasását."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"a videógyűjtemény módosítása"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Engedélyezi az alkalmazásnak a videógyűjtemény módosítását."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"a fényképgyűjtemény olvasása"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Engedélyezi az alkalmazásnak a fényképgyűjtemény olvasását."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"a fényképgyűjtemény módosítása"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Engedélyezi az alkalmazásnak a fényképgyűjtemény módosítását."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"helyek olvasása a médiagyűjteményből"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Engedélyezi az alkalmazásnak a helyek médiagyűjteményből való olvasását."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"A rendszer az ujjlenyomatnak csak egy részletét érzékelte. Próbálkozzon újra."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nem sikerült feldolgozni az ujjlenyomatot. Próbálkozzon újra."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Az ujjlenyomat-olvasó koszos. Tisztítsa meg, majd próbálkozzon újra."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Menti a következőt: <xliff:g id="TYPE">%1$s</xliff:g> ide: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Menti a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g> és <xliff:g id="TYPE_1">%2$s</xliff:g> ide: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Menti a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g> ide: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Frissít a következőre: &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Frissíti a következőt: <xliff:g id="TYPE">%1$s</xliff:g> erre: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Frissíti a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g> és <xliff:g id="TYPE_1">%2$s</xliff:g> erre: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Frissíti a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g> erre: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Mentés"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nem, köszönöm"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Frissítés"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"jelszó"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"cím"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"hitelkártya"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 56e00c7..a46d5e6 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -227,8 +227,8 @@
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Ամբողջական զեկույց"</string>
     <string name="bugreport_option_full_summary" msgid="7210859858969115745">"Օգտագործեք այս տարբերակը համակարգի միջամտությունը նվազեցնելու համար՝ երբ սարքը չի արձագանքում կամ շատ դանդաղ է աշխատում, կամ երբ ձեզ հարկավոր են զեկույցի բոլոր բաժինները: Թույլ չի տալիս լրացուցիչ տվյալներ մուտքագրել կամ էկրանի լրացուցիչ պատկերներ ստանալ:"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
-      <item quantity="one">Վրիպակի զեկույցի համար էկրանի պատկերի լուսանկարումը կատարվելու է <xliff:g id="NUMBER_1">%d</xliff:g> վայրկյանից:</item>
-      <item quantity="other">Վրիպակի զեկույցի համար էկրանի պատկերի լուսանկարումը կատարվելու է <xliff:g id="NUMBER_1">%d</xliff:g> վայրկյանից:</item>
+      <item quantity="one">Սքրինշոթը կարվի <xliff:g id="NUMBER_1">%d</xliff:g> վայրկյանից:</item>
+      <item quantity="other">Սքրինշոթը կարվի <xliff:g id="NUMBER_1">%d</xliff:g> վայրկյանից:</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Անձայն ռեժիմ"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ձայնը անջատված է"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Ինքնաթիռի ռեժիմ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Ինքնաթիռի ռեժիմը միացված է"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Ինքնաթիռի ռեժիմը անջատված է"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Մարտկոցի տնտեսում"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Անջատել"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Միացնել"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Կարգավորումներ"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Օգնական"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ձայնային օգնութ"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Մարմնի սենսորներ"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"օգտագործել սենսորների տվյալները ձեր օրգանիզմի վիճակի մասին"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին սենսորից ստանալ ձեր կենսագործունեության հիմնական տվյալները:"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Երաժշտություն"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"երաժշտության հասանելիություն"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Հասանելի դարձնե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին ձեր երաժշտությունը:"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Լուսանկարներ և տեսանյութեր"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"լուսանկարների և տեսանյութերի հասանելիություն"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Հասանելի դարձնե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին ձեր լուսանկարներն ու տեսանյութերը։"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Առբերել պատուհանի բովանդակությունը"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Վերլուծել գործող պատուհանի բովանդակությունը"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Միացնել Հպման միջոցով հետազոտումը"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Հավելվածին թույլ է տալիս կատարել այնպիսի գործառույթներ, որոնց միջոցով կարելի է օգտագործման համար ավելացնել և հեռացնել մատնահետքերի նմուշներ:"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"օգտագործել մատնահետքերի գրանցման սարքը"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Հավելվածին թույլ է տալիս նույնականացման համար օգտագործել մատնահետքերի գրանցման սարքը"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ճանաչել երաժշտական հավաքածուն"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Թույլ է տալիս հավելվածին ճանաչել ձեր երաժշտական հավաքածուն:"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"փոփոխել երաժշտական հավաքածուն"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Թույլ է տալիս հավելվածին փոփոխել ձեր երաժշտական հավաքածուն:"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ճանաչել տեսանյութերի հավաքածուն"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Թույլ է տալիս հավելվածին ճանաչել ձեր տեսանյութերի հավաքածուն:"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"փոփոխել տեսանյութերի հավաքածուն"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Թույլ է տալիս հավելվածին փոփոխել ձեր տեսանյութերի հավաքածուն:"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ճանաչել լուսանկարների հավաքածուն"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Թույլ է տալիս հավելվածին ճանաչել ձեր լուսանկարների հավաքածուն:"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"փոփոխել լուսանկարների հավաքածուն"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Թույլ է տալիս հավելվածին փոփոխել ձեր լուսանկարների հավաքածուն:"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ճանաչել տեղադրության մասին տվյալները մեդիա բովանդակության հավաքածուից"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Թույլ է տալիս հավելվածին ճանաչել տեղադրության մասին տվյալները ձեր մեդիա բովանդակության հավաքածուից:"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Մատնահետքը հայտնաբերվել է մասամբ: Փորձեք նորից:"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Չհաջողվեց մշակել մատնահետքը: Նորից փորձեք:"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Մատնահետքերի սենսորն աղտոտված է: Մաքրեք այն և փորձեք նորից:"</string>
@@ -1100,7 +1117,7 @@
     <string name="whichImageCaptureApplication" msgid="3680261417470652882">"Լուսանկարել այս հավելվածի օգնությամբ"</string>
     <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"Լուսանկարել %1$s հավելվածի օգնությամբ"</string>
     <string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"Լուսանկարել"</string>
-    <string name="alwaysUse" msgid="4583018368000610438">"Օգտագործել լռելյայն այս գործողության համար:"</string>
+    <string name="alwaysUse" msgid="4583018368000610438">"Օգտագործել ըստ կանխադրման այս գործողության համար:"</string>
     <string name="use_a_different_app" msgid="8134926230585710243">"Օգտագործել այլ հավելված"</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Մաքրել լռելյայնը Համակարգի կարգավորումներ &gt; Ծրագրեր &gt;Ներբեռնված էջից:"</string>
     <string name="chooseActivity" msgid="7486876147751803333">"Ընտրել գործողություն"</string>
@@ -1853,7 +1870,7 @@
     <string name="app_category_social" msgid="5842783057834965912">"Սոցցանցեր և հաղորդակցություն"</string>
     <string name="app_category_news" msgid="7496506240743986873">"Նորություններ և ամսագրեր"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Քարտեզներ և նավարկում"</string>
-    <string name="app_category_productivity" msgid="3742083261781538852">"Աշխատանք"</string>
+    <string name="app_category_productivity" msgid="3742083261781538852">"Արդյունավետություն"</string>
     <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Սարքի հիշողություն"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"USB վրիպազերծում"</string>
     <string name="time_picker_hour_label" msgid="2979075098868106450">"ժամ"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Պահե՞լ <xliff:g id="TYPE">%1$s</xliff:g>ը &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ծառայությունում"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Պահե՞լ <xliff:g id="TYPE_0">%1$s</xliff:g>ն ու <xliff:g id="TYPE_1">%2$s</xliff:g>ը &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ծառայությունում"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Պահե՞լ <xliff:g id="TYPE_0">%1$s</xliff:g>ը, <xliff:g id="TYPE_1">%2$s</xliff:g>ն ու <xliff:g id="TYPE_2">%3$s</xliff:g>ը &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ծառայությունում"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Թարմացնե՞լ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ծառայության տվյալները"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Թարմացնե՞լ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ծառայության տվյալները (<xliff:g id="TYPE">%1$s</xliff:g>)"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Թարմացնե՞լ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ծառայության տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g> և <xliff:g id="TYPE_1">%2$s</xliff:g>)"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Թարմացնե՞լ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ծառայության տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> և <xliff:g id="TYPE_2">%3$s</xliff:g>)"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Պահել"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ոչ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Թարմացնել"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"գաղտնաբառ"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"հասցե"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"վարկային քարտ"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 376b651..ed5444d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode pesawat"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode pesawat AKTIF"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode pesawat MATI"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Penghemat baterai"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Penghemat baterai NONAKTIF"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Penghemat baterai AKTIF"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Setelan"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Bantuan"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Bantuan Suara"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensor Tubuh"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"mengakses data sensor tentang tanda-tanda vital"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data sensor tentang tanda-tanda vital Anda?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musik"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"mengakses musik Anda"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; untuk mengakses musik?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Foto &amp; Video"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"mengakses foto &amp; video Anda"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; untuk mengakses foto &amp; video?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Mengambil konten jendela"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Memeriksa konten jendela tempat Anda berinteraksi."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Mengaktifkan Jelajahi dengan Sentuhan"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Mengizinkan aplikasi memanggil metode untuk menambahkan dan menghapus template sidik jari untuk digunakan."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gunakan hardware sidik jari"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Mengizinkan aplikasi untuk menggunakan hardware sidik jari untuk otentikasi"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"membaca koleksi musik Anda"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Mengizinkan aplikasi untuk membaca koleksi musik Anda."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"memodifikasi koleksi musik Anda"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Mengizinkan aplikasi untuk memodifikasi koleksi musik Anda."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"membaca koleksi video Anda"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Mengizinkan aplikasi untuk membaca koleksi video Anda."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"memodifikasi koleksi video Anda"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Mengizinkan aplikasi untuk memodifikasi koleksi video Anda."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"membaca koleksi foto Anda"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Mengizinkan aplikasi untuk membaca koleksi foto Anda."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"memodifikasi koleksi foto Anda"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Mengizinkan aplikasi untuk memodifikasi koleksi foto Anda."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"membaca lokasi dari koleksi media Anda"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Mengizinkan aplikasi untuk membaca lokasi dari koleksi media Anda."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Sebagian sidik jari terdeteksi. Coba lagi."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Tidak dapat memproses sidik jari. Coba lagi."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sensor sidik jari kotor. Bersihkan dan coba lagi."</string>
@@ -521,12 +538,12 @@
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Ikon sidik jari"</string>
     <string name="permlab_manageFace" msgid="2137540986007309781">"kelola hardware autentikasi wajah"</string>
-    <string name="permdesc_manageFace" msgid="8919637120670185330">"Mengizinkan apl meminta metode untuk menambah &amp; menghapus template wajah untuk digunakan."</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"Mengizinkan apl memicu metode untuk menambah &amp; menghapus template wajah untuk digunakan."</string>
     <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"gunakan hardware autentikasi wajah"</string>
     <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Mengizinkan aplikasi untuk menggunakan hardware autentikasi wajah untuk autentikasi"</string>
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"Tidak dapat memproses wajah. Harap coba lagi."</string>
     <string name="face_acquired_too_bright" msgid="610606792381297174">"Wajah terlalu cerah. Coba dengan cahaya lebih redup."</string>
-    <string name="face_acquired_too_dark" msgid="7229162716976778371">"Wajah terlalu gelap. Singkap sumber cahaya."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"Wajah terlalu gelap. Buka sumber cahaya."</string>
     <string name="face_acquired_too_close" msgid="1980310037427755293">"Jauhkan sensor dari wajah."</string>
     <string name="face_acquired_too_far" msgid="4494571381828850007">"Dekatkan sensor ke wajah."</string>
     <string name="face_acquired_too_high" msgid="228411096134808372">"Naikkan sensor."</string>
@@ -538,10 +555,10 @@
     <string name="face_acquired_not_steady" msgid="3722829465011040042">"Pastikan wajah tetap diam di depan perangkat."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <string name="face_error_hw_not_available" msgid="6255891785768984615">"Hardware wajah tidak tersedia."</string>
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"Hardware pemrosesan wajah tidak tersedia."</string>
     <string name="face_error_timeout" msgid="4014326147867150054">"Waktu tunggu wajah habis. Harap coba lagi."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Wajah tidak dapat disimpan."</string>
-    <string name="face_error_canceled" msgid="283945501061931023">"Pengoperasian wajah dibatalkan."</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"Pemrosesan wajah dibatalkan."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Terlalu banyak percobaan. Coba lagi nanti."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Terlalu sering dicoba. Autentikasi wajah dinonaktifkan."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Coba lagi."</string>
@@ -620,14 +637,14 @@
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci tablet atau menghapus semua data pengguna ini jika terlalu banyak sandi salah diketikkan."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci TV atau menghapus semua data pengguna ini jika terlalu banyak sandi salah diketikkan."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci ponsel atau menghapus semua data pengguna ini jika terlalu banyak sandi salah diketikkan."</string>
-    <string name="policylab_resetPassword" msgid="4934707632423915395">"Ubah kunci layar"</string>
+    <string name="policylab_resetPassword" msgid="4934707632423915395">"Mengubah kunci layar"</string>
     <string name="policydesc_resetPassword" msgid="1278323891710619128">"Mengubah kunci layar."</string>
-    <string name="policylab_forceLock" msgid="2274085384704248431">"Kunci layar"</string>
-    <string name="policydesc_forceLock" msgid="1141797588403827138">"Kontrol cara dan kapan layar mengunci."</string>
-    <string name="policylab_wipeData" msgid="3910545446758639713">"Hapus semua data"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Mengunci layar"</string>
+    <string name="policydesc_forceLock" msgid="1141797588403827138">"Mengontrol cara dan kapan layar mengunci."</string>
+    <string name="policylab_wipeData" msgid="3910545446758639713">"Menghapus semua data"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Hapus data tablet tanpa peringatan dengan menyetel ulang data pabrik."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Menghapus data TV tanpa peringatan dengan mengembalikan ke setelan pabrik."</string>
-    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Hapus data ponsel tanpa peringatan dengan menyetel ulang data pabrik."</string>
+    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Menghapus data ponsel tanpa peringatan dengan melakukan reset ke setelan pabrik."</string>
     <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Menghapus data pengguna"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"Menghapus data pengguna ini di tablet ini tanpa peringatan."</string>
     <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"Menghapus data pengguna ini di TV ini tanpa peringatan."</string>
@@ -1213,7 +1230,7 @@
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tap untuk melihat opsi"</string>
     <string name="wifi_softap_config_change" msgid="8475911871165857607">"Perubahan pada setelan hotspot Anda"</string>
     <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"Pita hotspot Anda telah berubah."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Perangkat ini tidak mendukung preferensi Anda, yaitu hanya 5GHz. Sebagai gantinya, perangkat ini akan menggunakan pita 5GHz jika tersedia."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Perangkat ini tidak mendukung preferensi Anda, yaitu hanya 5GHz. Sebagai gantinya, perangkat ini akan menggunakan pita frekuensi 5GHz jika tersedia."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"Dialihkan ke <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"Perangkat menggunakan <xliff:g id="NEW_NETWORK">%1$s</xliff:g> jika <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tidak memiliki akses internet. Tarif mungkin berlaku."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"Dialihkan dari <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ke <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
@@ -1308,7 +1325,7 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap untuk memilih bahasa dan tata letak"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
-    <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Tampilkan di atas aplikasi lain"</string>
+    <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Tampilkan di atas apl lain"</string>
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ditampilkan di atas aplikasi lain"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ditampilkan di atas aplikasi lain"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, tap untuk membuka setelan dan menonaktifkannya."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, dan <xliff:g id="TYPE_2">%3$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Update ke &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, dan <xliff:g id="TYPE_2">%3$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Lain kali"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"sandi"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"alamat"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kartu kredit"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 5f9d508..330b010 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flugstilling"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"KVEIKT er á flugstillingu"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"SLÖKKT er á flugstillingu"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Rafhlöðusparnaður"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Slökkt er á rafhlöðusparnaði"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Kveikt er á rafhlöðusparnaði"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Stillingar"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Aðstoð"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Raddaðstoð"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Líkamsskynjarar"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"aðgangur að skynjaragögnum yfir lífsmörk þín"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að skynjaragögnum yfir lífsmörk þín?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Tónlist"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"fá aðgang að tónlistinni þinni"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að tónlistinni þinni?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Myndir og myndskeið"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"fá aðgang að myndunum og myndskeiðunum þínum"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að myndunum og myndskeiðunum þínum?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Sækja innihald glugga"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Kanna innihald glugga sem þú ert að nota."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Kveikja á snertikönnun"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Gerir forritinu kleift að beita aðferðum til að bæta við og eyða fingrafarasniðmátum til notkunar."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"nota fingrafarabúnað"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Leyfir forritinu að nota fingrafarabúnað til auðkenningar"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"lesa tónlistarsafnið þitt"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Leyfir forritinu að lesa tónlistarsafnið þitt."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"breyta tónlistarsafninu þínu"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Leyfir forritinu að breyta tónlistarsafninu þínu."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"lesa myndskeiðasafnið þitt"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Leyfir forritinu að lesa myndskeiðasafnið þitt."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"breyta myndskeiðasafninu þínu"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Leyfir forritinu að breyta myndskeiðasafninu þínu."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"lesa myndasafnið þitt"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Leyfir forritinu að lesa myndasafnið þitt."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"breyta myndasafninu þínu"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Leyfir forritinu að breyta myndasafninu þínu."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"lesa staðsetningar úr efnissafninu þínu"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Leyfir forritinu að lesa staðsetningar úr efnissafninu þínu."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hluti fingrafars greindist. Reyndu aftur."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Ekki var hægt að vinna úr fingrafarinu. Reyndu aftur."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingrafaraskynjarinn er óhreinn. Hreinsaðu hann og reyndu aftur."</string>
@@ -1876,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vista <xliff:g id="TYPE">%1$s</xliff:g> á &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> á &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> á &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Viltu uppfæra í &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Viltu uppfæra <xliff:g id="TYPE">%1$s</xliff:g> í &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Viltu uppfæra <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> í &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Viltu uppfæra <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> í &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Vista"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nei, takk"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Uppfæra"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"aðgangsorð"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"heimilisfang"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditkort"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 13e8fad..a7c1ae2 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -134,7 +134,7 @@
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Non attiva"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Rete preferita: Wi-Fi"</string>
-    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Modalità preferita: dati mobili"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Rete preferita: dati mobili"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Solo Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: inoltro non effettuato"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modalità aereo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modalità aereo attiva"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modalità aereo non attiva"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Risparmio energetico"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Risparmio energetico disattivato"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Risparmio energetico attivo"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Impostazioni"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assistenza"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensori per il corpo"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"accedere ai dati dei sensori relativi ai tuoi parametri vitali"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere ai dati dei sensori relativi ai parametri vitali?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musica"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"Accesso alla tua musica"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Vuoi consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alla tua musica?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Foto e video"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"Accesso alle tue foto e ai tuoi video"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Vuoi consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alle tue foto e ai tuoi video?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperare contenuti della finestra"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Esaminare i contenuti di una finestra con cui interagisci."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Attivare Esplora al tocco"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Consente all\'app di richiamare metodi per aggiungere e rimuovere modelli di impronte digitali da utilizzare."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizzo di hardware per il riconoscimento delle impronte digitali"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Consente all\'app di utilizzare l\'hardware per il riconoscimento delle impronte digitali per eseguire l\'autenticazione"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"Lettura della tua raccolta musicale"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Consente all\'app di leggere la tua raccolta musicale."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"Modifica della tua raccolta musicale"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Consente all\'app di modificare la tua raccolta musicale."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"Lettura della tua raccolta di video"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Consente all\'app di leggere la tua raccolta di video."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"Modifica della tua raccolta di video"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Consente all\'app di modificare la tua raccolta di video."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"Lettura della tua raccolta di foto"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Consente all\'app di leggere la tua raccolta di foto."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"Modifica della tua raccolta di foto"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Consente all\'app di modificare la tua raccolta di foto."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"Lettura delle posizioni dalla tua raccolta multimediale"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Consente all\'app di leggere le posizioni dalla tua raccolta multimediale."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Rilevata impronta digitale parziale. Riprova."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossibile elaborare l\'impronta digitale. Riprova."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Il sensore di impronte digitali è sporco. Puliscilo e riprova."</string>
@@ -527,13 +544,13 @@
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"Impossibile elaborare il volto. Riprova."</string>
     <string name="face_acquired_too_bright" msgid="610606792381297174">"Volto troppo luminoso. Prova dove c\'è meno luce."</string>
     <string name="face_acquired_too_dark" msgid="7229162716976778371">"Volto troppo scuro. Non coprire la fonte di luce."</string>
-    <string name="face_acquired_too_close" msgid="1980310037427755293">"Allontana i sensori dal volto."</string>
-    <string name="face_acquired_too_far" msgid="4494571381828850007">"Avvicina i sensori al volto."</string>
-    <string name="face_acquired_too_high" msgid="228411096134808372">"Sposta i sensori verso l\'alto."</string>
-    <string name="face_acquired_too_low" msgid="4539774649296349109">"Sposta i sensori verso il basso."</string>
-    <string name="face_acquired_too_right" msgid="1650292067226118760">"Sposta i sensori verso destra."</string>
-    <string name="face_acquired_too_left" msgid="2712489669456176505">"Sposta i sensori verso sinistra."</string>
-    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"Guarda i sensori."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"Allontana il sensore dal volto."</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"Avvicina il sensore al volto."</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"Sposta il sensore verso l\'alto."</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"Sposta il sensore verso il basso."</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"Sposta il sensore verso destra."</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"Sposta il sensore verso sinistra."</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"Guarda il sensore."</string>
     <string name="face_acquired_not_detected" msgid="5707782294589511391">"Nessun volto rilevato."</string>
     <string name="face_acquired_not_steady" msgid="3722829465011040042">"Tieni il volto fermo davanti al dispositivo."</string>
   <string-array name="face_acquired_vendor">
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Salvare <xliff:g id="TYPE">%1$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Salvare <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Salvare <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Vuoi eseguire l\'aggiornamento a &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vuoi eseguire l\'aggiornamento di <xliff:g id="TYPE">%1$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vuoi eseguire l\'aggiornamento di <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vuoi eseguire l\'aggiornamento di <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salva"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, grazie"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Aggiorna"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"indirizzo"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"carta di credito"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 097d791..9a3fe87 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -242,9 +242,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"מצב טיסה"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"מצב טיסה מופעל"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"מצב טיסה כבוי"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"חיסכון בסוללה"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"תכונת החיסכון בסוללה כבויה"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"תכונת החיסכון בסוללה פועלת"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"הגדרות"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"סיוע"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -309,6 +306,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"חיישני גוף"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"גישה אל נתוני חיישנים של הסימנים החיוניים שלך"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה לנתוני חיישנים העוקבים אחר הסימנים החיוניים שלך?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"מוזיקה"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"גישה למוזיקה שלך"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"‏האם לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה למוזיקה שלך?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"תמונות וסרטונים"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"גישה לתמונות ולסרטונים שלך"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"‏האם לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה לתמונות ולסרטונים שלך?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"אחזור תוכן של חלון"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"בדוק את התוכן של חלון שאיתו אתה מבצע אינטראקציה."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"הפעלה של \'גילוי באמצעות מגע\'"</string>
@@ -503,6 +506,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"מאפשר לאפליקציה להפעיל שיטות להוספה ומחיקה של תבניות טביעות אצבעות שבהן ייעשה שימוש."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"חומרה של טביעות אצבעות"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"מאפשר לאפליקציה להשתמש בחומרה של טביעות אצבעות לצורך אימות"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"לקרוא את אוסף המוזיקה שלך"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"מאפשרת לאפליקציה לקרוא את אוסף המוזיקה שלך."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"לשנות את אוסף המוזיקה שלך"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"מאפשרת לאפליקציה לשנות את אוסף המוזיקה שלך."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"לקרוא את אוסף הסרטונים שלך"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"מאפשרת לאפליקציה לקרוא את אוסף הסרטונים שלך."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"לשנות את אוסף הסרטונים שלך"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"מאפשרת לאפליקציה לשנות את אוסף הסרטונים שלך."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"לקרוא את אוסף התמונות שלך"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"מאפשרת לאפליקציה לקרוא את אוסף התמונות שלך."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"לשנות את אוסף התמונות שלך"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"מאפשרת לאפליקציה לשנות את אוסף התמונות שלך."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"לקרוא מיקומים מאוסף המדיה שלך"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"מאפשרת לאפליקציה לקרוא מיקומים מאוסף המדיה שלך."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"זוהתה טביעת אצבע חלקית. נסה שוב."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"לא ניתן היה לעבד את טביעת האצבע. נסה שוב."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"החיישן של טביעות האצבעות מלוכלך. נקה אותו ונסה שוב."</string>
@@ -1945,8 +1962,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‏האם לשמור <xliff:g id="TYPE">%1$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‏האם לשמור <xliff:g id="TYPE_0">%1$s</xliff:g> ו<xliff:g id="TYPE_1">%2$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‏האם לשמור <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ו<xliff:g id="TYPE_2">%3$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"‏האם לעדכן בשירות &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‏האם לעדכן את <xliff:g id="TYPE">%1$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‏האם לעדכן את <xliff:g id="TYPE_0">%1$s</xliff:g> ואת <xliff:g id="TYPE_1">%2$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‏האם לעדכן את <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ו<xliff:g id="TYPE_2">%3$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"שמירה"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"לא, תודה"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"עדכון"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"סיסמה"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"כתובת"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"כרטיס אשראי"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 1c63913..ec2ada4 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"機内モード"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"機内モードON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"機内モードOFF"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"バッテリー セーバー"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"バッテリー セーバー OFF"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"バッテリー セーバー ON"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"設定"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"サポート"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"音声アシスト"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ボディーセンサー"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"バイタルサインに関するセンサーデータへのアクセス"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"バイタルサインに関するセンサーデータへのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"音楽"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"音楽へのアクセス"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"音楽へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"写真と動画"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"写真と動画へのアクセス"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"写真と動画へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ウィンドウコンテンツの取得"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"ユーザーがアクセスしているウィンドウのコンテンツを検査します。"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"タッチガイドの有効化"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"使用する指紋テンプレートの追加や削除を行う方法の呼び出しをアプリに許可します。"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"指紋ハードウェアの使用"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"指紋ハードウェアを認証に使用することをアプリに許可します"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"音楽コレクションの読み取り"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"音楽コレクションの読み取りをアプリに許可します。"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"音楽コレクションの変更"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"音楽コレクションの変更をアプリに許可します。"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"動画コレクションの読み取り"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"動画コレクションの読み取りをアプリに許可します。"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"動画コレクションの変更"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"動画コレクションの変更をアプリに許可します。"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"写真コレクションの読み取り"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"写真コレクションの読み取りをアプリに許可します。"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"写真コレクションの変更"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"写真コレクションの変更をアプリに許可します。"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"メディア コレクションの位置情報の読み取り"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"メディア コレクションの位置情報の読み取りをアプリに許可します。"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"指紋を一部しか検出できませんでした。もう一度お試しください。"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"指紋を処理できませんでした。もう一度お試しください。"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"指紋認証センサーに汚れがあります。汚れを落としてもう一度お試しください。"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; に保存しますか?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; に保存しますか?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; に保存しますか?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; に更新しますか?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; に更新しますか?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g>と<xliff:g id="TYPE_1">%2$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; に更新しますか?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; に更新しますか?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"はい"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"いいえ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"更新"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"パスワード"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"住所"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"クレジット カード"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index c5a9ab2..0a383df 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"თვითმფრინავის რეჟიმი"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"თვითმფრინავის რეჟიმი ჩართულია."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"თვითმფრინავის რეჟიმი გამორთულია."</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"ბატარეის დამზოგი"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ბატარეის დამზოგი გამორთულია"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"ბატარეის დამზოგი ჩართულია"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"პარამეტრები"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"დახმარება"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ხმოვანი ასისტ."</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"სხეულის სენსორები"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"თქვენი სასიცოცხლო ფუნქციების შესახებ სენსორის მონაცემებზე წვდომა"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; თქვენი სასიცოცხლო ფუნქციების შესახებ სენსორის მონაცემებზე წვდომის ნებართვა?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"მუსიკა"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"თქვენს მუსიკაზე წვდომა"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს თქვენს მუსიკაზე წვდომა?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ფოტოები და ვიდეოები"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"თქვენს ფოტოებსა და ვიდეოებზე წვდომა"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს თქვენს ფოტოებსა და ვიდეოებზე წვდომა?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ფანჯრის კონტენტის მოძიება"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"იმ ფანჯრის კონტენტის შემოწმება, რომელშიც მუშაობთ."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"„შეხებით აღმოჩენის“ ჩართვა"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"საშუალებას აძლევს აპლიკაციას დაამატოს ან ამოშალოს გამოსაყენებელი თითის ანაბეჭდის ნიმუშები,"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"თითის ანაბეჭდის აპარატის გამოყენება"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"საშუალებას აძლევს აპლიკაციას გამოიყენოს ავტენთიფიკაციისათვის თითის ანაბეჭდის აპარატი"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"თქვენი მუსიკალური კოლექციის გაცნობა"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"აპი შეძლებს თქვენი მუსიკალური კოლექციის გაცნობას."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"თქვენი მუსიკალური კოლექციის შეცვლა"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"აპი შეძლებს თქვენი მუსიკალური კოლექციის შეცვლას."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"თქვენი ვიდეოკოლექციის გაცნობა"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"აპი შეძლებს თქვენი ვიდეოკოლექციის გაცნობას."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"თქვენი ვიდეოკოლექციის შეცვლა"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"აპი შეძლებს თქვენი ვიდეოკოლექციის შეცვლას."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"თქვენი ფოტოკოლექციის გაცნობა"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"აპი შეძლებს თქვენი ფოტოკოლექციის გაცნობას."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"თქვენი ფოტოკოლექციის შეცვლა"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"აპი შეძლებს თქვენი ფოტოკოლექციის შეცვლას."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"მდებარეობების გაცნობა თქვენი მედიაკოლექციიდან"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"აპი შეძლებს მდებარეობების გაცნობას თქვენი მედიაკოლექციიდან."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"აღმოჩენილია თითის ნაწილობრივი ანაბეჭდი. გთხოვთ, სცადოთ ხელახლა."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"თითის ანაბეჭდი ვერ მუშავდება. გთხოვთ, სცადოთ ხელახლა."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"თითის ანაბეჭდის სენსორი დაბინძურებულია. გთხოვთ, გაასუფთაოთ და სცადოთ ხელახლა."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"გსურთ, შეინახოთ <xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>-ში&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"გსურთ, შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g> და <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>-ში&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"გსურთ, შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, და <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>-ში&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"გსურთ, განაახლოთ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;-ზე?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"გსურთ, განაახლოთ <xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"გსურთ, განაახლოთ <xliff:g id="TYPE_0">%1$s</xliff:g> და <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;-ზე?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"გსურთ, განაახლოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> და <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;-ზე?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"შენახვა"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"არა, გმადლობთ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"განახლება"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"პაროლი"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"მისამართი"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"საკრედიტო ბარათი"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 0c02202..2509958 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Ұшақ режимі"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Ұшақ режимі ҚОСУЛЫ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Ұшақ режимі ӨШІРУЛІ"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Battery saver"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Battery saver ӨШІРУЛІ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Battery saver ҚОСУЛЫ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Параметрлер"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Көмек"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Дауыс көмекшісі"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Дене датчиктері"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ағза күйінің көрсеткіштері туралы сенсор деректеріне қатынасу"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына негізгі физиологиялық көрсеткіштерді көрсететін сенсорлық деректерді пайдалануға рұқсат берілсін бе?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Музыка"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"музыка мазмұнына кіру"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына музыка мазмұнына кіруге рұқсат етілсін бе?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Суреттер және бейнелер"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"суреттер мен бейнелерге кіру"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына суреттер мен бейнелерге кіруге рұқсат етілсін бе?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Терезе мазмұнын оқып отыру"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Ашық тұрған терезе мазмұнын тексеру."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Explore by Touch функциясын қосу"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Қолданбаға пайдаланатын саусақ ізі үлгілерін қосу және жою әдістерін шақыруға мүмкіндік береді."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"саусақ ізі жабдығын пайдалану"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Қолданбаға аутентификацияалу үшін саусақ ізі жабдығын пайдалануға мүмкіндік береді"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"музыка жинағын оқу"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Қолданбаға музыка жинағын оқуға мүмкіндік береді."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"музыка жинағын өзгерту"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Қолданбаға музыка жинағын өзгертуге мүмкіндік береді."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"бейнелер жинағын оқу"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Қолданбаға бейнелер жинағын оқуға мүмкіндік береді."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"бейнелер жинағын өзгерту"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Қолданбаға бейнелер жинағын өзгертуге мүмкіндік береді."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"суреттер жинағын оқу"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Қолданбаға суреттер жинағын оқуға мүмкіндік береді."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"суреттер жинағын өзгерту"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Қолданбаға суреттер жинағын өзгертуге мүмкіндік береді."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"медиамазмұн жинағынан геодеректерді оқу"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Қолданбаға медиамазмұн жинағынан геодеректерді оқуға мүмкіндік береді."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Саусақ ізі ішінара анықталды. Әрекетті қайталаңыз."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Саусақ ізін өңдеу мүмкін емес. Әрекетті қайталаңыз."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Саусақ ізі сенсоры лас. Тазалап, әрекетті қайталаңыз."</string>
@@ -520,14 +537,14 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Саусақ ізі белгішесі"</string>
-    <string name="permlab_manageFace" msgid="2137540986007309781">"бетті аутентификациялау жабдығын басқару"</string>
+    <string name="permlab_manageFace" msgid="2137540986007309781">"бетті тану жабдығын басқару"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"Қолданбаға пайдаланатын бет үлгілерін енгізу және жою әдістерін шақыруға мүмкіндік береді."</string>
-    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"бетті аутентификациялау жабдығын пайдалану"</string>
-    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Қолданбаға бетті аутентификациялау жабдығын қолдануға рұқсат етеді"</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"бетті тану жабдығын пайдалану"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Қолданбаға бетті тану жабдығын қолдануға рұқсат етеді"</string>
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"Бет өңделмеді. Әрекетті қайталаңыз."</string>
     <string name="face_acquired_too_bright" msgid="610606792381297174">"Бет тым ашық түсті болып шықты. Жарықты азайтыңыз."</string>
     <string name="face_acquired_too_dark" msgid="7229162716976778371">"Бет тым күңгірт түсті. Жарық көзін бөгемеңіз."</string>
-    <string name="face_acquired_too_close" msgid="1980310037427755293">"Датчикті беттен алшақ қойыңыз."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"Датчикті беттен алыстатыңыз."</string>
     <string name="face_acquired_too_far" msgid="4494571381828850007">"Датчикті бетке жақындатыңыз."</string>
     <string name="face_acquired_too_high" msgid="228411096134808372">"Датчикті жоғары көтеріңіз."</string>
     <string name="face_acquired_too_low" msgid="4539774649296349109">"Датчикті төмен қарай жылжытыңыз."</string>
@@ -543,11 +560,11 @@
     <string name="face_error_no_space" msgid="8224993703466381314">"Бетті сақтау мүмкін емес."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Бетті танудан бас тартылды."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Тым көп әрекет жасалды. Кейінірек қайталаңыз."</string>
-    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Тым көп әрекет жасалды. Бетті аутентификациялау функциясы өшірілді."</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Тым көп әрекет жасалды. Бетті тану функциясы өшірілді."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Қайталап көріңіз."</string>
     <string name="face_error_not_enrolled" msgid="9166792142679691323">"Ешқандай бет тіркелмеген."</string>
-    <string name="face_error_hw_not_present" msgid="4737289254517095671">"Бұл құрылғыда бетті аутентификациялау датчигі жоқ"</string>
-    <string name="face_name_template" msgid="7004562145809595384">"Бет: <xliff:g id="FACEID">%d</xliff:g>"</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"Бұл құрылғыда бетті тану датчигі жоқ"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"<xliff:g id="FACEID">%d</xliff:g> беті"</string>
   <string-array name="face_error_vendor">
   </string-array>
     <string name="face_icon_content_description" msgid="4024817159806482191">"Бет белгішесі"</string>
@@ -1876,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> \"<xliff:g id="LABEL">%2$s</xliff:g>\" қызметінде сақталсын ба?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> және <xliff:g id="TYPE_1">%2$s</xliff:g> \"<xliff:g id="LABEL">%3$s</xliff:g>\" қызметінде сақталсын ба?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> және <xliff:g id="TYPE_2">%3$s</xliff:g> \"<xliff:g id="LABEL">%4$s</xliff:g>\" қызметінде сақталсын ба?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; қызметінде жаңартылсын ба?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> мәліметі &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; қызметінде жаңартылсын ба?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> және <xliff:g id="TYPE_1">%2$s</xliff:g> мәліметі &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; қызметінде жаңартылсын ба?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> және <xliff:g id="TYPE_2">%3$s</xliff:g> мәліметі &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; қызметінде жаңартылсын ба?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сақтау"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Жоқ, рақмет"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Жаңарту"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"құпия сөз"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"мекенжай"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"несие картасы"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 50344e9..e24c9a0 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -133,8 +133,8 @@
     <item msgid="4397097370387921767">"ការហៅតាមរយៈ Wi-Fi %s"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"បិទ"</string>
-    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"គួរប្រើ Wi-Fi"</string>
-    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"បាន​ជ្រើសរើសប្រើទិន្នន័យចល័ត"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi ជាអាទិភាព"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ទិន្នន័យទូរសព្ទចល័តជាអាទិភាព"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Wi-Fi តែប៉ុណ្ណោះ"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិន​បាន​បញ្ជូន​បន្ត"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ពេល​ជិះ​យន្តហោះ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"បាន​បើក​របៀប​ពេល​ជិះ​យន្ត​ហោះ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បាន​បិទ​របៀបពេលជិះ​យន្តហោះ​"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"កម្មវិធី​សន្សំ​ថ្ម"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"កម្មវិធី​សន្សំ​ថ្ម​បាន​បិទ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"កម្មវិធី​សន្សំថ្មបាន​បើក"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ការ​កំណត់"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"ជំនួយ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ជំនួយសម្លេង"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ឧបករណ៍ចាប់សញ្ញារាងកាយ"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ចូលដំណើរការទិន្នន័យឧបករណ៍ចាប់សញ្ញាអំពីស្ថានភាពសុខភាពរបស់អ្នក"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​ទិន្នន័យឧបករណ៍ចាប់សញ្ញាអំពីស្ថានភាពសុខភាពរបស់អ្នក?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"តន្ត្រី"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"ចូលប្រើ​តន្ត្រី​របស់អ្នក"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"អនុញ្ញាត​ឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​តន្រ្តី​របស់​អ្នក?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"រូបថត និង​វីដេអូ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"ចូលប្រើ​រូបថត និង​វីដេអូ​របស់អ្នក"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"អនុញ្ញាត​ឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​រូបថត និង​វីដេអូ​របស់​អ្នក?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ទាញយក​ខ្លឹមសារ​វិនដូ"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"ពិនិត្យ​ខ្លឹមសារវិនដូ​ដែល​អ្នក​កំពុង​ទាក់ទង​ជា​មួយ។"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"បើក​ការ​រក​មើល​​ដោយ​ប៉ះ"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"អនុញ្ញាតឲ្យកម្មវិធីប្រើវិធីសាស្ត្របន្ថែម និងលុបពុម្ពម្រាមដៃសម្រាប់ប្រើប្រាស់។"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ប្រើផ្នែករឹងស្នាមម្រាមដៃ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"អនុញ្ញាតឲ្យកម្មវិធីប្រើផ្នែករឹងស្នាមម្រាមដៃសម្រាប់ការផ្ទៀងផ្ទាត់"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"អាន​បណ្ដុំ​តន្ត្រី​របស់​អ្នក"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"អនុញ្ញាតឱ្យ​កម្មវិធី​អាន​បណ្ដុំ​តន្រ្តី​របស់​អ្នក។"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"កែប្រែ​បណ្ដុំ​តន្ត្រី​របស់​អ្នក"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"អនុញ្ញាតឱ្យ​កម្មវិធី​កែប្រែ​បណ្ដុំ​តន្រ្តី​របស់​អ្នក។"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"អាន​បណ្ដុំ​វីដេអូ​របស់​អ្នក"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"អនុញ្ញាតឱ្យ​កម្មវិធី​អាន​បណ្ដុំ​វីដេអូ​របស់​អ្នក។"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"កែប្រែ​បណ្ដុំ​វីដេអូ​របស់​អ្នក"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"អនុញ្ញាតឱ្យ​កម្មវិធី​កែប្រែ​បណ្ដុំ​វីដេអូ​របស់​អ្នក។"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"អាន​បណ្ដុំ​រូបថត​របស់​អ្នក"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"អនុញ្ញាតឱ្យ​កម្មវិធី​អាន​បណ្ដុំ​រូបថត​របស់​អ្នក។"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"កែប្រែ​បណ្ដុំ​រូបថត​របស់​អ្នក"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"អនុញ្ញាតឱ្យ​កម្មវិធី​កែប្រែ​បណ្ដុំ​រូបថត​របស់​អ្នក។"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"អាន​ទីតាំង​ពី​បណ្ដុំ​មេឌៀ​របស់​អ្នក"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"អនុញ្ញាតឱ្យ​កម្មវិធី​អាន​ទីតាំង​ពីបណ្ដុំ​មេឌៀ​របស់​អ្នក។"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"បានផ្តិតយកស្នាមម្រាមដៃមិនពេញលក្ខណៈ។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"មិនអាចដំណើរការស្នាមម្រាមដៃបានទេ។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ឧបករណ៍ផ្តិតម្រាមដៃប្រលាក់ហើយ។ សូមសម្អាត ហើយព្យាយាមម្តងទៀត។"</string>
@@ -527,25 +544,25 @@
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"មិនអាចដំណើរការ​ផ្ទៃមុខបានទេ។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="face_acquired_too_bright" msgid="610606792381297174">"ផ្ទៃ​មុខ​ចាំង​ពេក។ សូម​សាកល្បង​នៅកន្លែងដែលមាន​ពន្លឺ​ទាប​ជាងនេះ។"</string>
     <string name="face_acquired_too_dark" msgid="7229162716976778371">"ផ្ទៃ​មុខ​ងងឹត​ពេក។ សូមរកកន្លែង​ដែលមាន​ប្រភពពន្លឺ។"</string>
-    <string name="face_acquired_too_close" msgid="1980310037427755293">"សូម​ផ្លាស់ទីឧបករណ៍​ចាប់សញ្ញា​ឱ្យ​ឆ្ងាយ​ពី​ផ្ទៃ​មុខ​របស់អ្នកជាងនេះ។"</string>
-    <string name="face_acquired_too_far" msgid="4494571381828850007">"សូម​ដាក់​ឧបករណ៍​ចាប់សញ្ញា​ឱ្យនៅជិត​ផ្ទៃ​មុខ​ជាងនេះ។"</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"សូម​ផ្លាស់ទីឧបករណ៍​ចាប់សញ្ញា​ឱ្យ​ឆ្ងាយ​ពី​មុខ​។"</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"សូម​ដាក់​ឧបករណ៍​ចាប់សញ្ញា​ឱ្យនៅជិតមុខ​ជាងនេះ។"</string>
     <string name="face_acquired_too_high" msgid="228411096134808372">"សូម​ផ្លាស់ទី​ឧបករណ៍​ចាប់សញ្ញា​ឱ្យខ្ពស់​ជាងនេះ។"</string>
     <string name="face_acquired_too_low" msgid="4539774649296349109">"សូម​ផ្លាស់ទី​ឧបករណ៍ចាប់សញ្ញា​ឱ្យ​ទាបជាងនេះ។"</string>
     <string name="face_acquired_too_right" msgid="1650292067226118760">"សូម​ផ្លាស់ទី​ឧបករណ៍ចាប់សញ្ញា​ទៅ​ស្ដាំ។"</string>
     <string name="face_acquired_too_left" msgid="2712489669456176505">"សូម​ផ្លាស់ទី​ឧបករណ៍ចាប់សញ្ញា​ទៅឆ្វេង។"</string>
     <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"សូម​មើល​ទៅ​ឧបករណ៍​ចាប់សញ្ញា។"</string>
-    <string name="face_acquired_not_detected" msgid="5707782294589511391">"រកមិន​ឃើញ​ផ្ទៃមុខទេ។"</string>
-    <string name="face_acquired_not_steady" msgid="3722829465011040042">"រក្សាផ្ទៃ​មុខ​របស់អ្នក​ឱ្យ​នឹង​នៅមុខ​ឧបករណ៍​។"</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"រកមិន​ឃើញ​មុខទេ។"</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"រក្សាមុខ​របស់អ្នក​ឱ្យ​នឹង​នៅមុខ​ឧបករណ៍​។"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <string name="face_error_hw_not_available" msgid="6255891785768984615">"មិន​អាច​ប្រើ​ផ្នែករឹង​ផ្ទៃ​មុខ​បានទេ។"</string>
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"មិន​អាច​ប្រើ​ផ្នែករឹង​ចាប់ផ្ទៃ​មុខ​បានទេ។"</string>
     <string name="face_error_timeout" msgid="4014326147867150054">"ការសម្គាល់​ផ្ទៃមុខ​បាន​អស់ម៉ោង។ សូមព្យាយាមម្ដងទៀត។"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"មិន​អាច​រក្សាទុក​ផ្ទៃ​មុខ​បានទេ។"</string>
-    <string name="face_error_canceled" msgid="283945501061931023">"បាន​បោះបង់​ប្រតិបត្តិការ​ផ្ទៃមុខ។"</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"បាន​បោះបង់​ប្រតិបត្តិការចាប់​ផ្ទៃមុខ។"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ព្យាយាមចូលច្រើនពេកហើយ។ បាន​បិទការផ្ទៀងផ្ទាត់​ផ្ទៃ​មុខ។"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"សូមព្យាយាម​ម្ដងទៀត។"</string>
-    <string name="face_error_not_enrolled" msgid="9166792142679691323">"មិន​អាច​ចុះឈ្មោះ​ផ្ទៃ​មុខ​បានទេ។"</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"មិន​អាច​ថត​បញ្ចូលផ្ទៃ​មុខ​បានទេ។"</string>
     <string name="face_error_hw_not_present" msgid="4737289254517095671">"ឧបករណ៍​នេះ​មិន​មាន​ឧបករណ៍​ផ្ទៀងផ្ទាត់​ផ្ទៃមុខ​នោះទេ"</string>
     <string name="face_name_template" msgid="7004562145809595384">"ផ្ទៃមុខទី <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
@@ -1877,8 +1894,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"រក្សាទុក <xliff:g id="TYPE">%1$s</xliff:g> ទៅក្នុង &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"រក្សាទុក <xliff:g id="TYPE_0">%1$s</xliff:g> និង <xliff:g id="TYPE_1">%2$s</xliff:g> ទៅក្នុង &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"រក្សាទុក <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, និង <xliff:g id="TYPE_2">%3$s</xliff:g> ទៅក្នុង &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"ធ្វើ​បច្ចុប្បន្នភាព​ទៅ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"ធ្វើ​បច្ចុប្បន្នភាព <xliff:g id="TYPE">%1$s</xliff:g> ទៅ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"ធ្វើ​បច្ចុប្បន្នភាព <xliff:g id="TYPE_0">%1$s</xliff:g> និង <xliff:g id="TYPE_1">%2$s</xliff:g> ទៅ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"ធ្វើ​បច្ចុប្បន្នភាព <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> និង <xliff:g id="TYPE_2">%3$s</xliff:g> ទៅ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"រក្សាទុក"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ទេ អរគុណ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"ធ្វើ​បច្ចុប្បន្នភាព"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"ពាក្យ​សម្ងាត់"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"អាសយដ្ឋាន"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"បណ្ណ​ឥណទាន"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 59055bb..158a316 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -133,7 +133,7 @@
     <item msgid="4397097370387921767">"%s ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆ"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ಆಫ್"</string>
-    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ವೈ-ಫೈಗೆ ಆದ್ಯತೆ ನೀಡಲಾಗಿದೆ"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ವೈ-ಫೈಗೆ ಆದ್ಯತೆ"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ಮೊಬೈಲ್‌ಗೆ ಆದ್ಯತೆ"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"ವೈ-ಫೈ ಮಾತ್ರ"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ಫಾರ್ವರ್ಡ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ಎರ್‌ಪ್ಲೇನ್ ಮೋಡ್ ಆನ್ ಆಗಿದೆ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"ಎರ್‌ಪ್ಲೇನ್ ಮೋಡ್ ಆಫ್ ಆಗಿದೆ"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"ಬ್ಯಾಟರಿ ಸೇವರ್‌‌"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಆಫ್ ಆಗಿದೆ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"ಬ್ಯಾಟರಿ ಸೇವರ್‌ ಆನ್ ಆಗಿದೆ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"ಸಹಾಯ ಮಾಡು"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ದೇಹ ಸೆನ್ಸರ್‌ಗಳು"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತು ಸೆನ್ಸಾರ್ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತು ಸೆನ್ಸರ್ ಡೇಟಾವನ್ನು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"ಸಂಗೀತ"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"ನಿಮ್ಮ ಸಂಗೀತವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"ನಿಮ್ಮ ಸಂಗೀತವನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ಫೋಟೋಗಳು &amp; ವೀಡಿಯೊಗಳು"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"ನಿಮ್ಮ ಫೋಟೋಗಳು &amp; ವೀಡಿಯೊಗಳನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"ನಿಮ್ಮ ಫೋಟೋಗಳು &amp; ವೀಡಿಯೊಗಳನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ವಿಂಡೋ ವಿಷಯವನ್ನು ಹಿಂಪಡೆಯುತ್ತದೆ"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"ನೀವು ಬಳಸುತ್ತಿರುವ ವಿಂಡೋದ ವಿಷಯ ಪರೀಕ್ಷಿಸುತ್ತದೆ."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ಸ್ಪರ್ಶ-ಎಕ್ಸ್‌ಪ್ಲೋರ್ ಆನ್ ಮಾಡುತ್ತದೆ"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ಬಳಕೆಗೆ ಬೆರಳಚ್ಚು ಟೆಂಪ್ಲೇಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಿ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ನಿಮ್ಮ ಸಂಗೀತ ಸಂಗ್ರಹಣೆಯನ್ನು ಓದಿ"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"ನಿಮ್ಮ ಸಂಗೀತ ಸಂಗ್ರಹಣೆಯನ್ನು ಓದಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"ನಿಮ್ಮ ಸಂಗೀತ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಿ"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"ನಿಮ್ಮ ಸಂಗೀತ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ನಿಮ್ಮ ವೀಡಿಯೊ ಸಂಗ್ರಹಣೆಯನ್ನು ಓದಿ"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"ನಿಮ್ಮ ವೀಡಿಯೊ ಸಂಗ್ರಹಣೆಯನ್ನು ಓದಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"ನಿಮ್ಮ ವೀಡಿಯೊ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಿ"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"ನಿಮ್ಮ ವೀಡಿಯೊ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ನಿಮ್ಮ ಫೋಟೋ ಸಂಗ್ರಹಣೆಯನ್ನು ಓದಿ"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"ನಿಮ್ಮ ಫೋಟೋ ಸಂಗ್ರಹಣೆಯನ್ನು ಓದಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"ನಿಮ್ಮ ಫೋಟೋ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಿ"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ನಿಮ್ಮ ಫೋಟೋ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ನಿಮ್ಮ ಮೀಡಿಯಾ ಸಂಗ್ರಹಣೆಯಿಂದ ಸ್ಥಳಗಳನ್ನು ಓದಿ"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ನಿಮ್ಮ ಮೀಡಿಯಾ ಸಂಗ್ರಹಣೆಯಿಂದ ಸ್ಥಳಗಳನ್ನು ಓದಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ಭಾಗಶಃ ಬೆರಳಚ್ಚು ಪತ್ತೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ಬೆರಳಚ್ಚು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ಬೆರಳಚ್ಚು ಸೆನ್ಸಾರ್ ಕೊಳೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಅದನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ಬೆರಳಚ್ಚು ಐಕಾನ್"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"ಮುಖ ದೃಢೀಕರಣ ಹಾರ್ಡ್‌ವೇರ್‌ ಅನ್ನು ನಿರ್ವಹಿಸಿ"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"ಬಳಕೆಗೆ ಮುಖದ ಟೆಂಪ್ಲೇಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"ಮುಖ ದೃಢೀಕರಣ ಹಾರ್ಡ್‌ವೇರ್‌ ಅನ್ನು ಬಳಸಿ"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"ಧೃಡೀಕರಣಕ್ಕಾಗಿ ಮುಖದ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"ಮುಖವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"ಮುಖವು ತುಂಬಾ ಪ್ರಕಾಶಮಾನವಾಗಿದೆ. ಕಡಿಮೆ ಲೈಟ್‌ನಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"ಮುಖ ತುಂಬಾ ಕಪ್ಪಾಗಿದೆ. ನೇರವಾಗಿ ಬೆಳಕು ಬಿಳುವಂತೆ ಮಾಡಿ."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"ಮುಖದಿಂದ ಸೆನ್ಸರ್ ಅನ್ನು ದೂರ ಸರಿಸಿ."</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"ಸೆನ್ಸರ್ ಅನ್ನು ಮುಖದ ಹತ್ತಿರಕ್ಕೆ ತನ್ನಿ."</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"ಸೆನ್ಸರ್ ಅನ್ನು ಮೇಲಕ್ಕೆ ಸರಿಸಿ."</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"ಸೆನ್ಸರ್ ಅನ್ನು ಕೆಳಕ್ಕೆ ಸರಿಸಿ."</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"ಸೆನ್ಸರ್ ಅನ್ನು ಬಲಕ್ಕೆ ಸರಿಸಿ."</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"ಸೆನ್ಸರ್ ಅನ್ನು ಎಡಕ್ಕೆ ಸರಿಸಿ."</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"ಸೆನ್ಸರ್ ಅನ್ನು ನೋಡಿ."</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"ಯಾವುದೇ ಮುಖ ಪತ್ತೆಯಾಗಿಲ್ಲ."</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"ಸಾಧನದ ಮುಂದೆ ಮುಖವನ್ನು ಸ್ಥಿರವಾಗಿ ಇರಿಸಿ."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"ಮುಖದ ಹಾರ್ಡ್‌ವೇರ್‌ ಲಭ್ಯವಿಲ್ಲ."</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"ಮುಖ ಸಮಯದ ಅವಧಿಯನ್ನು ತಲುಪಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"ಮುಖವನ್ನು ಸಂಗ್ರಹಿಸಲಾಗುವುದಿಲ್ಲ."</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"ಮುಖದ ಕಾರ್ಯಚರಣೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ."</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ಹಲವು ಪ್ರಯತ್ನ. ಮುಖದ ದೃಢೀಕರಣ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"ಯಾವುದೇ ಮುಖವನ್ನು ನೋಂದಣಿ ಮಾಡಿಲ್ಲ."</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"ಈ ಸಾಧನವು ಮುಖ ದೃಢೀಕರಣ ಸೆನ್ಸರ್‌ ಅನ್ನು ಹೊಂದಿಲ್ಲ"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"ಮುಖದ <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"ಮುಖದ ಐಕಾನ್‌"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ರೀಡ್‌ ಮಾಡು"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ಒಂದು ಖಾತೆಯ ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್‍‍ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ಖಾತೆಯೊಂದಿಗೆ ಜನರ ಅಪ್ಲಿಕೇಶನ್ ಸಿಂಕ್ ಮಾಡಲಾಗಿದೆಯೇ ಎಂಬುದನ್ನು ಇದು ನಿರ್ಧರಿಸಬಹುದು."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ಸಿಂಕ್ ಆನ್ ಮತ್ತು ಸಿಂಕ್ ಆಫ್ ಟಾಗಲ್ ಮಾಡಿ"</string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"ವೈ ಫೈ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"ನಿಮ್ಮ ಹಾಟ್‌ಸ್ಪಾಟ್‌ ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಬದಲಾವಣೆಗಳು"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"ನಿಮ್ಮ ಹಾಟ್‌ಸ್ಪಾಟ್‌ ಬ್ಯಾಂಡ್ ಬದಲಾಗಿದೆ."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"ಈ ಸಾಧನವು 5GHz ಗೆ ಮಾತ್ರ ನಿಮ್ಮ ಆದ್ಯತೆಯನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ. ಬದಲಿಗೆ, ಈ ಸಾಧನವು 5GHz ಬ್ಯಾಂಡ್ ಅನ್ನು ಲಭ್ಯವಿರುವಾಗ ಬಳಸುತ್ತದೆ."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ ಹೊಂದಿಲ್ಲದಿರುವಾಗ, ಸಾಧನವು <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ಬಳಸುತ್ತದೆ. ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ರಿಂದ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
@@ -1906,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> ಹಾಗೂ <xliff:g id="TYPE_1">%2$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ಹಾಗೂ <xliff:g id="TYPE_2">%3$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;ಗೆ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವುದೇ?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;ಗೆ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವುದೇ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> ಹಾಗೂ <xliff:g id="TYPE_1">%2$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;ಗೆ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವುದೇ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ಹಾಗೂ <xliff:g id="TYPE_2">%3$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;ಗೆ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವುದೇ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ಉಳಿಸಿ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ಬೇಡ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"ಅಪ್‌ಡೇಟ್"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"ಪಾಸ್‌ವರ್ಡ್"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ವಿಳಾಸ"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8d28671..776f773 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"비행기 모드"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"비행기 모드 사용중"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"비행기 모드 사용중이 아님"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"배터리 세이버"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"배터리 세이버 사용 안함"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"배터리 세이버 사용 중"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"설정"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"지원"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"음성 지원"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"인체 감지 센서"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"생체 신호에 관한 센서 데이터에 액세스"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 생체 신호에 관한 센서 데이터에 액세스하도록 허용하시겠습니까?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"음악"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"음악에 액세스"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 내 음악에 액세스하도록 허용하시겠습니까?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"사진 및 동영상"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"사진 및 동영상에 액세스"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 내 사진 및 동영상에 액세스하도록 허용하시겠습니까?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"창 콘텐츠 가져오기"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"상호작용 중인 창의 콘텐츠를 검사합니다."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"터치하여 탐색 사용"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"사용할 지문 템플릿의 추가 및 삭제 메소드를 앱에서 실행하도록 허용합니다."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"지문 하드웨어 사용"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"앱에서 지문 하드웨어를 인증에 사용하도록 허용합니다."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"음악 컬렉션 읽기"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"앱에서 음악 컬렉션을 읽도록 허용합니다."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"음악 컬렉션 수정"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"앱에서 음악 컬렉션을 수정하도록 허용합니다."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"동영상 컬렉션 읽기"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"앱에서 동영상 컬렉션을 읽도록 허용합니다."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"동영상 컬렉션 수정"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"앱에서 동영상 컬렉션을 수정하도록 허용합니다."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"사진 컬렉션 읽기"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"앱에서 사진 컬렉션을 읽도록 허용합니다."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"사진 컬렉션 수정"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"앱에서 사진 컬렉션을 수정하도록 허용합니다."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"미디어 컬렉션에서 위치 읽기"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"앱에서 미디어 컬렉션의 위치를 읽도록 허용합니다."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"지문이 일부만 인식되었습니다. 다시 시도해 주세요."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"지문을 인식할 수 없습니다. 다시 시도해 주세요."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"지문 센서를 깨끗이 닦고 다시 시도하세요."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;에 저장하시겠습니까?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> 및 <xliff:g id="TYPE_1">%2$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;에 저장하시겠습니까?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;에 저장하시겠습니까?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;(으)로 업데이트하시겠습니까?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;(으)로 업데이트하시겠습니까?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> 및 <xliff:g id="TYPE_1">%2$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;(으)로 업데이트하시겠습니까?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;(으)로 업데이트하시겠습니까?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"저장"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"사용 안함"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"업데이트"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"비밀번호"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"주소"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"신용카드"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index a56fb67..1c1e9a9 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -60,7 +60,7 @@
     <string name="ClirMmi" msgid="7784673673446833091">"Чыгуучу номурду аныктоо"</string>
     <string name="ColpMmi" msgid="3065121483740183974">"Туташкан линия ID-си"</string>
     <string name="ColrMmi" msgid="4996540314421889589">"Туташкан линия ID-син Чектөө"</string>
-    <string name="CfMmi" msgid="5123218989141573515">"Чалууну багыттоо"</string>
+    <string name="CfMmi" msgid="5123218989141573515">"Башка номерге багыттоо"</string>
     <string name="CwMmi" msgid="9129678056795016867">"Чалууну кармап туруу"</string>
     <string name="BaMmi" msgid="455193067926770581">"Чалууга тыюу салуу"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"Сырсөздү өзгөртүү"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Учак режими"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Учак режими КҮЙҮК"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Учак режими ӨЧҮК"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Батареяны үнөмдөгүч"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Батареяны үнөмдөгүч ӨЧҮК"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Батареяны үнөмдөгүч КҮЙҮК"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Жөндөөлөр"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Жардам"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Үн жардамчысы"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Дене сенсорлору"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"организмдин абалына көз салган сенсордун дайындарына мүмкүнчүлүк алуу"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна организмдин абалына көз салган сенсордун дайындарын пайдаланууга уруксат берилсинби?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Музыка"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"музыкага кирүү мүмкүнчүлүгү"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна музыканы пайдаланууга уруксат берилсинби?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Сүрөттөр жана видеолор"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"сүрөттөр менен видеолорго кирүү мүмкүнчүлүгү"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна сүрөттөр менен видеолорду пайдаланууга уруксат берилсинби?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Терезедеги мазмунду алып турат"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Учурда ачылып турган терезедеги маалыматты талдайт."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"\"Сыйпалап изилдөө\" мүмкүнчүлүгүн иштетет"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Колдонмого пайдалануу үчүн манжа изинин үлгүлөрүн кошуу жана жок кылуу мүмкүндүгүн берет."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"манжа изинин аппараттык камсыздоосун колдонуу"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Колдонмого аныктыгын текшерүү үчүн манжа изинин аппараттык камсыздоосун пайдалануу мүмкүндүгүн берет"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"музыка жыйнагыңызды окуу"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Колдонмого музыка жыйнагыңызды окууга мүмкүнчүлүк берет."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"музыка жыйнагыңызды өчүрүү"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Колдонмого музыка жыйнагыңызды өзгөртүүгө мүмкүнчүлүк берет."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"видео жыйнагыңызды окуу"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Колдонмого видео жыйнагыңызды окууга мүмкүнчүлүк берет."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"видео жыйнагыңызды өзгөртүү"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Колдонмого видео жыйнагыңызды өзгөртүүгө мүмкүнчүлүк берет."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"сүрөт жыйнагыңызды окуу"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Колдонмого сүрөт жыйнагыңызды окууга мүмкүнчүлүк берет."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"сүрөт жыйнагыңызды өзгөртүү"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Колдонмого сүрөт жыйнагыңызды өзгөртүүгө мүмкүнчүлүк берет."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"медиа жыйнагыңыз сакталган жерлерди окуу"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Колдонмого медиа жыйнагыңыз сакталган жерлерди окууга мүмкүнчүлүк берет."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Манжа изи жарым-жартылай аныкталды. Кайра аракет кылыңыз."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Манжа изи иштелбей койду. Кайра аракет кылыңыз."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Манжа изинин сенсору кирдеп калган. Тазалап, кайра аракет кылыңыз."</string>
@@ -793,7 +810,7 @@
     <string name="lockscreen_transport_stop_description" msgid="5907083260651210034">"Токтотуу"</string>
     <string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"Артка түрүү"</string>
     <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"Алдыга түрүү"</string>
-    <string name="emergency_calls_only" msgid="6733978304386365407">"Шашылыш чалуу гана"</string>
+    <string name="emergency_calls_only" msgid="6733978304386365407">"Өзгөчө кырдаалда гана чалууга болот"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Тармак кулпуланган"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-карта PUK-бөгөттө."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Колдонуучунун нускамасын караңыз же Кардарларды тейлөө борборуна кайрылыңыз."</string>
@@ -1877,8 +1894,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; кызматында сакталсынбы?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> жана <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; кызматында сакталсынбы?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> жана <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; кызматында сакталсынбы?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; кызматына жаңыртылсынбы?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; кызматына жаңыртылсынбы?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> жана <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; кызматына жаңыртылсынбы?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> жана <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; кызматына жаңыртылсынбы?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сактоо"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Жок, рахмат"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Жаңыртуу"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"сырсөз"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"дарек"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"насыя картасы"</string>
diff --git a/core/res/res/values-land/dimens_permission_controller.xml b/core/res/res/values-land/dimens_permission_controller.xml
new file mode 100644
index 0000000..2146241
--- /dev/null
+++ b/core/res/res/values-land/dimens_permission_controller.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<!-- Landscape dimensions for the permission grant dialog. -->
+<resources>
+    <!-- Assuming the dimension of a sailfish, this yields 95% width in splitscreen and 65% in
+         landscape -->
+    <dimen name="permissionGrantDialogWeight">8.6</dimen>
+    <dimen name="permissionGrantDialogWidth">334dp</dimen>
+</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 64df34d..b17b5ab 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ໂໝດໃນຍົນ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ເປີດໂໝດຢູ່ໃນຍົນແລ້ວ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"ປິດໂໝດໃນຍົນແລ້ວ"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"ຕົວປະຢັດແບັດເຕີຣີ"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ຕົວປະຢັດແບັດເຕີຣີປິດຢູ່"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"ຕົວປະຢັດແບັດເຕີຣີເປີດຢູ່"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"​ການ​ຕັ້ງ​ຄ່າ"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"ຕົວຊ່ວຍ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ຊ່ວຍ​ເຫຼືອ​ທາງ​ສຽງ"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ເຊັນ​ເຊີ​ຮ່າງ​ກາຍ"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ເຂົ້າ​ຫາ​ຂໍ້​ມູນ​ເຊັນ​ເຊີ​ກ່ຽວ​ກັບ​ສັນ​ຍານ​ຊີບ​ຂອງ​ທ່ານ"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີກ່ຽວກັບສັນຍານຊີບຂອງທ່ານບໍ?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"ເພງ"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"ເຂົ້າເຖິງເພງຂອງທ່ານ"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງເພງຂອງທ່ານບໍ?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ຮູບພາບ ແລະ ວິດີໂອ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"ເຂົ້າເຖິງຮູບພາບ ແລະ ວິດີໂອຂອງທ່ານ"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງຮູບພາບ ແລະ ວິດີໂອຂອງທ່ານບໍ?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ດຶງຂໍ້ມູນເນື້ອຫາໃນໜ້າຈໍ"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"ກວດກາເນື້ອຫາຂອງໜ້າຈໍທີ່ທ່ານກຳລັງມີປະຕິສຳພັນນຳ."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ເປີດໃຊ້ \"ການສຳຫຼວດໂດຍສຳຜັດ\""</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ເຮັດ​ໃຫ້​ວິ​ທີ​ການ​ຕ່າງໆ​ເພີ່ມ ແລະ​ລຶບ​ແມ່​ແບບ​ລາຍ​ນີ້ວ​ມື​ສຳ​ລັບ​ການ​ໃຊ້."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ໃຊ້​ຮາດ​ແວ​ລາຍ​ນີ້ວ​ມື"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ນຳ​ໃຊ້​ຮາດ​ແວ​ລາຍ​ນີ້ວ​ມື​ສຳ​ລັບ​ການ​ຮັບ​ຮອງ"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ອ່ານຄໍເລັກຊັນເພງຂອງທ່ານ"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"ອະນຸຍາດໃຫ້ແອັບອ່ານຄໍເລັກຊັນເພງຂອງທ່ານ."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"ແກ້ໄຂຄໍເລັກຊັນເພງຂອງທ່ານ"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຄໍເລັກຊັນເພງຂອງທ່ານ."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ອ່ານຄໍເລັກຊັນວິດີໂອຂອງທ່ານ"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"ອະນຸຍາດໃຫ້ແອັບອ່ານຄໍເລັກຊັນວິດີໂອຂອງທ່ານ."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"ແກ້ໄຂຄໍເລັກຊັນວິດີໂອຂອງທ່ານ"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຄໍເລັກຊັນວິດີໂອຂອງທ່ານ."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ອ່ານຄໍເລັກຊັນຮູບຂອງທ່ານ"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"ອະນຸຍາດໃຫ້ແອັບອ່ານຄໍເລັກຊັນຮູບຂອງທ່ານ."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"ແກ້ໄຂຄໍເລັກຊັນຮູບຂອງທ່ານ"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຄໍເລັກຊັນຮູບຂອງທ່ານ."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ອ່ານສະຖານທີ່ຈາກຄໍເລັກຊັນມີເດຍຂອງທ່ານ"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ອະນຸຍາດໃຫ້ແອັບອ່ານສະຖານທີ່ຈາກຄໍເລັກຊັນມີເດຍຂອງທ່ານ."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ກວດ​ພົບ​ລາຍ​ນີ້ວ​ມື​ບາງ​ສ່ວນ​ແລ້ວ. ກະ​ລຸ​ນາ​ລອງ​ໃໝ່​ອີກ."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ບໍ່​ສາ​ມາດ​ດຳ​ເນີນ​ການ​ລາຍ​ນີ້ວ​ມື​ໄດ້. ກະ​ລຸ​ນາ​ລອງ​ໃໝ່​ອີກ."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ເຊັນ​ເຊີ​ລາຍ​ນີ້ວ​ມື​ເປື້ອນ. ກະ​ລຸ​ນາ​ທຳ​ຄວາມ​ສະ​ອາດ ແລະ​ລອງ​ໃໝ່​ອີກ."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"ບັນທຶກ <xliff:g id="TYPE">%1$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g> ແລະ <xliff:g id="TYPE_1">%2$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ແລະ <xliff:g id="TYPE_2">%3$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"ອັບເດດ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"ອັບເດດ <xliff:g id="TYPE">%1$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"ອັບເດດ <xliff:g id="TYPE_0">%1$s</xliff:g> ແລະ <xliff:g id="TYPE_1">%2$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"ອັບເດດ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ແລະ <xliff:g id="TYPE_2">%3$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ບັນທຶກ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ບໍ່, ຂອບໃຈ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"ອັບເດດ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"​ລະ​ຫັດ​ຜ່ານ"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ທີ່ຢູ່"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ບັດເຄຣດິດ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index f396cca..9409c7d 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -242,9 +242,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lėktuvo režimas"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ĮJUNGTAS lėktuvo režimas"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"lėktuvo režimas IŠJUNGTAS"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Akumuliatoriaus tausojimo priemonė"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Akumuliatoriaus tausojimo priemonė IŠJUNGTA"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Akumuliatoriaus tausojimo priemonė ĮJUNGTA"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Nustatymai"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Pagalba"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -309,6 +306,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Kūno jutikliai"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"pasiekti jutiklių duomenis apie gyvybinius ženklus"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Suteikti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; galimybę pasiekti jutiklių duomenis apie gyvybinius ženklus?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muzika"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"pasiekti muziką"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Suteikti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prieigą prie muzikos?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Nuotraukos ir vaizdo įrašai"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"pasiekti nuotraukas ir vaizdo įrašus"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Suteikti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prieigą prie nuotraukų ir vaizdo įrašų?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Gauti lango turinį"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Tikrinti lango, su kuriuo sąveikaujate, turinį."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Įjungti „Naršyti paliečiant“"</string>
@@ -503,6 +506,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Leidžiama programai aktyvinti metodus, norint pridėti ir ištrinti naudojamus kontrolinių kodų šablonus."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"naudoti kontrolinio kodo aparatinę įrangą"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Leidžiama programai naudoti kontrolinio kodo aparatinę įrangą tapatybei nustatyti"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"skaityti muzikos kolekciją"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Programai leidžiama skaityti muzikos kolekciją."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"keisti muzikos kolekciją"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Programai leidžiama keisti muzikos kolekciją."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"skaityti vaizdo įrašų kolekciją"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Programai leidžiama skaityti vaizdo įrašų kolekciją."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"keisti vaizdo įrašų kolekciją"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Programai leidžiama keisti vaizdo įrašų kolekciją."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"skaityti nuotraukų kolekciją"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Programai leidžiama skaityti nuotraukų kolekciją."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"keisti nuotraukų kolekciją"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Programai leidžiama keisti nuotraukų kolekciją."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"skaityti vietoves iš medijos kolekcijos"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Programai leidžiama skaityti vietoves iš medijos kolekcijos."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Aptiktas dalinis kontrolinis kodas. Bandykite dar kartą."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nepavyko apdoroti kontrolinio kodo. Bandykite dar kartą."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Kontrolinio kodo jutiklis purvinas. Nuvalykite ir bandykite dar kartą."</string>
@@ -1945,8 +1962,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Išsaugoti <xliff:g id="TYPE">%1$s</xliff:g> sistemoje &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g> ir <xliff:g id="TYPE_1">%2$s</xliff:g> sistemoje &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ir <xliff:g id="TYPE_2">%3$s</xliff:g> sistemoje &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Atnaujinti paslaugoje &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Atnaujinti <xliff:g id="TYPE">%1$s</xliff:g> paslaugoje &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Atnaujinti <xliff:g id="TYPE_0">%1$s</xliff:g> ir <xliff:g id="TYPE_1">%2$s</xliff:g> paslaugoje &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Atnaujinti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ir <xliff:g id="TYPE_2">%3$s</xliff:g> paslaugoje &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Išsaugoti"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, ačiū"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Atnaujinti"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"slaptažodį"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresą"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredito kortelę"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index da8644d..272deb3 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -239,9 +239,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lidojuma režīms"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lidojuma režīms ir IESLĒGTS."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lidojuma režīms ir IZSLĒGTS."</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Akumulatora jaudas taupīšanas režīms"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Akumulatora jaudas taupīšanas režīms ir IZSLĒGTS"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Akumulatora jaudas taupīšanas režīms ir IESLĒGTS"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Iestatījumi"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Palīdzība"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Balss palīgs"</string>
@@ -306,6 +303,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Ķermeņa sensori"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"piekļūt sensoru datiem par jūsu veselības rādījumiem"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt sensoru uztvertajiem veselības rādījumiem?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Mūzika"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"Piekļūt jūsu mūzikai"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt jūsu mūzikai?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotoattēli un videoklipi"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"Piekļūt jūsu fotoattēliem un videoklipiem"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt jūsu fotoattēliem videoklipiem?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Izgūt loga saturu."</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Skatīt tā loga saturu, ar kuru mijiedarbojaties."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktivizēt funkciju “Pārlūkot pieskaroties”."</string>
@@ -500,6 +503,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Atļauj lietotnei izsaukt metodes izmantojamo pirkstu nospiedumu veidņu pievienošanai un dzēšanai."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"lietot pirkstu nospiedumu aparatūru"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Atļauj lietotnei izmantot pirkstu nospiedumu aparatūru autentificēšanai."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"Lasīt jūsu mūzikas kolekciju"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Ļauj lietotnei lasīt jūsu mūzikas kolekciju."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"Pārveidot jūsu mūzikas kolekciju"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Ļauj lietotnei pārveidot jūsu mūzikas kolekciju."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"Lasīt jūsu videoklipu kolekciju"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Ļauj lietotnei lasīt jūsu videoklipu kolekciju."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"Pārveidot jūsu videoklipu kolekciju"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Ļauj lietotnei pārveidot jūsu videoklipu kolekciju."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"Lasīt jūsu fotoattēlu kolekciju"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Ļauj lietotnei lasīt jūsu fotoattēlu kolekciju."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"Pārveidot jūsu fotoattēlu kolekciju"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Ļauj lietotnei pārveidot jūsu fotoattēlu kolekciju."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"Lasīt atrašanās vietas no jūsu multivides kolekcijas"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Ļauj lietotnei lasīt atrašanās vietas no jūsu multivides kolekcijas."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Noteikts daļējs pirksta nospiedums. Lūdzu, mēģiniet vēlreiz."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nevarēja apstrādāt pirksta nospiedumu. Lūdzu, mēģiniet vēlreiz."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Pirkstu nospiedumu sensors ir netīrs. Lūdzu, notīriet to un mēģiniet vēlreiz."</string>
@@ -1910,8 +1927,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vai saglabāt vienumu “<xliff:g id="TYPE">%1$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vai saglabāt vienumus “<xliff:g id="TYPE_0">%1$s</xliff:g>” un “<xliff:g id="TYPE_1">%2$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vai saglabāt vienumus “<xliff:g id="TYPE_0">%1$s</xliff:g>”, “<xliff:g id="TYPE_1">%2$s</xliff:g>” un “<xliff:g id="TYPE_2">%3$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Vai atjaunināt pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vai atjaunināt vienumu “<xliff:g id="TYPE">%1$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vai atjaunināt vienumus “<xliff:g id="TYPE_0">%1$s</xliff:g>” un “<xliff:g id="TYPE_1">%2$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vai atjaunināt vienumus “<xliff:g id="TYPE_0">%1$s</xliff:g>”, “<xliff:g id="TYPE_1">%2$s</xliff:g>” un “<xliff:g id="TYPE_2">%3$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Saglabāt"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nē, paldies"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Atjaunināt"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"paroli"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresi"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredītkartes informāciju"</string>
diff --git a/core/res/res/values-mcc214-mnc01/config.xml b/core/res/res/values-mcc214-mnc01/config.xml
index 24150a7..41e24d7 100644
--- a/core/res/res/values-mcc214-mnc01/config.xml
+++ b/core/res/res/values-mcc214-mnc01/config.xml
@@ -40,4 +40,7 @@
       <item>INTERNET,airtelnet.es,,,vodafone,vodafone,,,,,214,01,1,DUN</item>
     </string-array>
 
+    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). -->
+    <bool name="config_safe_media_disable_on_volume_up">false</bool>
+
 </resources>
diff --git a/core/res/res/values-mcc214/config.xml b/core/res/res/values-mcc214/config.xml
new file mode 100644
index 0000000..9410848
--- /dev/null
+++ b/core/res/res/values-mcc214/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <!-- String array containing numbers that shouldn't be logged
+       016 present here for Spain's gender violence number -->
+  <string-array translatable="false" name="unloggable_phone_numbers">
+    <item>016</item>
+  </string-array>
+</resources>
diff --git a/core/res/res/values-mcc222-mnc10/config.xml b/core/res/res/values-mcc222-mnc10/config.xml
index c819de2..0085a1b 100644
--- a/core/res/res/values-mcc222-mnc10/config.xml
+++ b/core/res/res/values-mcc222-mnc10/config.xml
@@ -28,4 +28,8 @@
     <string-array translatable="false" name="config_tether_apndata">
       <item>Tethering Internet,web.omnitel.it,,,,,,,,,222,10,,DUN</item>
     </string-array>
+
+    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). -->
+    <bool name="config_safe_media_disable_on_volume_up">false</bool>
+
 </resources>
diff --git a/core/res/res/values-mcc234-mnc15/config.xml b/core/res/res/values-mcc234-mnc15/config.xml
new file mode 100644
index 0000000..84e779d
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc15/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). -->
+    <bool name="config_safe_media_disable_on_volume_up">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc234-mnc91/config.xml b/core/res/res/values-mcc234-mnc91/config.xml
new file mode 100644
index 0000000..84e779d
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc91/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). -->
+    <bool name="config_safe_media_disable_on_volume_up">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc262-mnc02/config.xml b/core/res/res/values-mcc262-mnc02/config.xml
new file mode 100644
index 0000000..84e779d
--- /dev/null
+++ b/core/res/res/values-mcc262-mnc02/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). -->
+    <bool name="config_safe_media_disable_on_volume_up">false</bool>
+
+</resources>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 8774334..3308128 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -29,8 +29,8 @@
          Or string format of ApnSettingV3.
          note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
     <string-array translatable="false" name="config_tether_apndata">
-        <item>[ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,220,,DUN,IP,IP,true,0,,,,,,,gid,54</item>
-        <item>[ApnSettingV3]Tethered Mobile Internet,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,50</item>
+        <item>[ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,220,,DUN,IP,IP,true,0,,,,,,,gid,5455</item>
+        <item>[ApnSettingV3]Tethered Mobile Internet,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,5043</item>
         <item>[ApnSettingV3]Tethered Public Mobile,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,4D4F</item>
     </string-array>
 
diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml
index 05896b1..bb0d4d5 100644
--- a/core/res/res/values-mcc302-mnc221/config.xml
+++ b/core/res/res/values-mcc302-mnc221/config.xml
@@ -27,9 +27,9 @@
          Or string format of ApnSettingV3.
          note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
     <string-array translatable="false" name="config_tether_apndata">
-        <item>[ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,221,,DUN,,,true,0,,,,,,,gid,54</item>
-        <item>[ApnSettingV3]Tethered PC Mobile,isp.mb.com,,,,,,,,,302,221,,DUN,,,true,0,,,,,,,gid,50</item>
-        <item>[ApnSettingV3]Koodo,sp.koodo.com,,,,,,,,,302,221,,DUN,,,true,0,,,,,,,gid,4B</item>
+        <item>[ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,221,,DUN,,,true,0,,,,,,,gid,5455</item>
+        <item>[ApnSettingV3]Tethered PC Mobile,isp.mb.com,,,,,,,,,302,221,,DUN,,,true,0,,,,,,,gid,5043</item>
+        <item>[ApnSettingV3]Koodo,sp.koodo.com,,,,,,,,,302,221,,DUN,,,true,0,,,,,,,gid,4B4F</item>
     </string-array>
 
     <!-- Values for GPS configuration (Telus) -->
diff --git a/core/res/res/values-mcc334-mnc03/config.xml b/core/res/res/values-mcc334-mnc03/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc334-mnc03/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc334-mnc030/config.xml b/core/res/res/values-mcc334-mnc030/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc334-mnc030/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc704-mnc03/config.xml b/core/res/res/values-mcc704-mnc03/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc704-mnc03/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc706-mnc04/config.xml b/core/res/res/values-mcc706-mnc04/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc706-mnc04/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc712-mnc04/config.xml b/core/res/res/values-mcc712-mnc04/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc712-mnc04/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc716-mnc06/config.xml b/core/res/res/values-mcc716-mnc06/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc716-mnc06/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc716-mnc10/config.xml b/core/res/res/values-mcc716-mnc10/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc716-mnc10/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc716-mnc17/config.xml b/core/res/res/values-mcc716-mnc17/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc716-mnc17/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc722-mnc07/config.xml b/core/res/res/values-mcc722-mnc07/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc722-mnc07/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc732-mnc123/config.xml b/core/res/res/values-mcc732-mnc123/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc732-mnc123/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc740-mnc00/config.xml b/core/res/res/values-mcc740-mnc00/config.xml
new file mode 100644
index 0000000..c0d2b35
--- /dev/null
+++ b/core/res/res/values-mcc740-mnc00/config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+    <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index bc8cb07..b2beb3a 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим на работа во авион"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режимот на работа во авион е вклучен"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режимот на работа во авион е исклучен"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Штедач на батерија"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Штедачот на батерија е ИСКЛУЧЕН"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Штедачот на батерија е ВКЛУЧЕН"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Поставки"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Асистенција"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Гласовна помош"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Телесни сензори"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"пристапува до податоците од сензорите за виталните знаци"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Дали да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до податоците на сензорот за витални знаци?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Музика"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"пристапува до музиката"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Дали да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до музиката?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Фотографии и видеа"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"пристапува до фотографиите и видеата"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Дали да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до фотографиите и видеата?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Преземе содржина на прозорец"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Ја следи содржината на прозорецот со кој се комуницира."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Вклучи „Истражувај со допир“"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Дозволува апликацијата да повика начини за додавање и бришење шаблони на отпечатоци за користење."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"користи хардвер за отпечатоци"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволува апликацијата да користи хардвер за отпечатоци за проверка"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"да ја чита вашата музичка збирка"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Дозволува апликацијата да ја чита вашата музичка збирка."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"да ја менува вашата музичка збирка"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Дозволува апликацијата да ја менува вашата музичка збирка."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"да ја чита вашата збирка на видеа"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Дозволува апликацијата да ја чита вашата збирка на видеа."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"да ја менува вашата збирка на видеа"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Дозволува апликацијата да ја менува вашата збирка на видеа."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"да ја чита вашата збирка на фотографии"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Дозволува апликацијата да ја чита вашата збирка на фотографии."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"да ја менува вашата збирка на фотографии"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Дозволува апликацијата да ја менува вашата збирка на фотографии."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"да чита локации од вашата збирка на аудиовизуелни содржини"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Дозволува апликацијата да чита локации од вашата збирка на аудиовизуелни содржини."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Откриен е делумен отпечаток. Обидете се повторно."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Отпечатокот не можеше да се обработи. Обидете се повторно."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Сензорот за отпечатоци е валкан. Исчистете го и обидете се повторно."</string>
@@ -550,7 +567,7 @@
     <string name="face_name_template" msgid="7004562145809595384">"Лице <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <string name="face_icon_content_description" msgid="4024817159806482191">"Икона за лице"</string>
+    <string name="face_icon_content_description" msgid="4024817159806482191">"Икона"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"чита поставки за синхронизација"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Овозможува апликацијата да ги чита поставките за синхронизирање на сметка. На пример, така може да се утврди дали апликацијата „Луѓе“ е синхронизирана со сметка."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"вклучи и исклучи синхронизација"</string>
@@ -1878,8 +1895,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Да се зачува <xliff:g id="TYPE">%1$s</xliff:g> во &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> во &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> во &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Дали да се ажурира на &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Дали да се ажурира <xliff:g id="TYPE">%1$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Дали да се ажурираат <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Дали да се ажурираат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Зачувај"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, фала"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Ажурирај"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"лозинка"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картичка"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 3c89c2c..81421bb 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ഫ്ലൈറ്റ് മോഡ്"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ഫ്ലൈറ്റ് മോഡ് ഓണാണ്"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"ഫ്ലൈറ്റ് മോഡ് ഓഫാണ്"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"ബാറ്ററി ലാഭിക്കൽ"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ബാറ്ററി സേവർ ഓഫാണ്"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"ബാറ്ററി ലാഭിക്കൽ ഓണാണ്"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ക്രമീകരണം"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"അസിസ്റ്റ്"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"വോയ്‌സ് സഹായം"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ബോഡി സെൻസറുകൾ"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"നിങ്ങളുടെ ജീവാധാര ലക്ഷണങ്ങളെ കുറിച്ചുള്ള സെൻസർ വിവരങ്ങൾ ആക്സസ് ചെയ്യുക"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"നിങ്ങളുടെ ജീവധാരണ ലക്ഷണങ്ങളെ കുറിച്ചുള്ള സെൻസർ ഡാറ്റ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"സംഗീതം"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"നിങ്ങളുടെ സംഗീതം ആക്‌സസ് ചെയ്യുക"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ നിങ്ങളുടെ സംഗീതം ആക്‌സസ് ചെയ്യാൻ അനുവദിക്കണോ?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ഫോട്ടോകളും &amp; വീഡിയോകളും"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"നിങ്ങളുടെ ഫോട്ടോകളും &amp; വീഡിയോകളും"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ നിങ്ങളുടെ ഫോട്ടോകൾ &amp; വീഡിയോകൾ എന്നിവ ആക്‌സസ് ചെയ്യാൻ അനുവദിക്കണോ?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"വിൻഡോ ഉള്ളടക്കം വീണ്ടെടുക്കുക"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"നിങ്ങൾ സംവദിക്കുന്ന ഒരു വിൻഡോയുടെ ഉള്ളടക്കം പരിശോധിക്കുക."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"സ്‌പർശനം വഴി പര്യവേക്ഷണം ചെയ്യുക, ഓണാക്കുക"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ഉപയോഗിക്കാനായി വിരലടയാള ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ ഉപയോഗിക്കുക"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"പ്രാമാണീകരണത്തിനായി വിരലടയാളം ഉപയോഗിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"നിങ്ങളുടെ സംഗീത ശേഖരം റീഡ് ചെയ്യുക"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"നിങ്ങളുടെ സംഗീത ശേഖരം റീഡ് ചെയ്യുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"നിങ്ങളുടെ സംഗീത ശേഖരം പരിഷ്‌കരിക്കുക"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"നിങ്ങളുടെ സംഗീത ശേഖരം പരിഷ്‌ക്കരിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"നിങ്ങളുടെ വീഡിയോ ശേഖരം റീഡ് ചെയ്യുക"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"നിങ്ങളുടെ വീഡിയോ ശേഖരം റീഡ് ചെയ്യുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"നിങ്ങളുടെ വീഡിയോ ശേഖരം പരിഷ്‌കരിക്കുക"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"നിങ്ങളുടെ വീഡിയോ ശേഖരം പരിഷ്‌ക്കരിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"നിങ്ങളുടെ ഫോട്ടോ ശേഖരം റീഡ് ചെയ്യുക"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"നിങ്ങളുടെ ഫോട്ടോ ശേഖരം റീഡ് ചെയ്യുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"നിങ്ങളുടെ ഫോട്ടോ ശേഖരം പരിഷ്‌കരിക്കുക"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"നിങ്ങളുടെ ഫോട്ടോ ശേഖരം പരിഷ്‌ക്കരിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"നിങ്ങളുടെ മീഡിയ ശേഖരത്തിൽ നിന്നും ലൊക്കേഷനുകൾ റീഡ് ചെയ്യുക"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"നിങ്ങളുടെ മീഡിയ ശേഖരത്തിൽ നിന്നും ലൊക്കേഷനുകൾ റീഡ് ചെയ്യുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"വിരലടയാളം ഭാഗികമായി തിരിച്ചറിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"വിരലടയാളം പ്രോസസ്സ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"വിരലടയാള സെൻസറിന് വൃത്തിയില്ല. അത് ശുചിയാക്കി വീണ്ടും ശ്രമിക്കുക."</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"വിരലടയാള ഐക്കൺ"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"മുഖം തിരിച്ചറിയൽ ഹാർഡ്‌വെയർ മാനേജ് ചെയ്യുക"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"ഉപയോഗിക്കാനായി, മുഖത്തിന്റെ ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"മുഖം തിരിച്ചറിയൽ ഹാർഡ്‌വെയർ ഉപയോഗിക്കുക"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"പരിശോധിച്ചുറപ്പിക്കലിനായി മുഖം തിരിച്ചറിയൽ ഹാർഡ്‌വെയർ  ഉപയോഗിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"മുഖം പ്രോസസ്സ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"മുഖം വളരെ തെളിച്ചമുള്ളതാണ്. കുറഞ്ഞ വെളിച്ചത്തിൽ ശ്രമിക്കുക."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"മുഖം വളരെ ഇരുണ്ടതാണ്. പ്രകാശ ലഭ്യത ഉറപ്പാക്കി ശ്രമിക്കുക."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"മുഖത്തിനടുത്തുനിന്ന് സെൻസർ അകലേയ്ക്ക് നീക്കുക."</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"സെൻസർ മുഖത്തിനടുത്തേയ്ക്ക് കൊണ്ടുവരിക."</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"സെൻസർ മുകളിലേക്ക് നീക്കുക."</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"സെൻസർ താഴേയ്ക്ക് നീക്കുക."</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"സെൻസർ വലത്തേയ്ക്ക് നീക്കുക."</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"സെൻസർ ഇടത്തേയ്ക്ക് നീക്കുക."</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"സെൻസറിലേക്ക് നോക്കുക."</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"മുഖം കണ്ടെത്താനായില്ല."</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"ഉപകരണത്തിന് മുന്നിൽ മുഖം ഇളകാതെ നേരെ നിറുത്തുക."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"മുഖത്തിന്റെ ഹാർഡ്‌വെയർ ലഭ്യമല്ല."</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"മുഖം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"മുഖം സൂക്ഷിക്കാനാവില്ല."</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"മുഖത്തിന്റെ പ്രവർത്തനം റദ്ദാക്കി."</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"നിരവധി തവണ ശ്രമിച്ചു. മുഖം തിരിച്ചറിയൽ പ്രവർത്തനരഹിതമാക്കി."</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"ഒരു മുഖവും എൻറോൾ ചെയ്‌തിട്ടില്ല."</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"ഈ ഉപകരണത്തിന് മുഖം തിരിച്ചറിയാനാവുന്ന സെൻസർ ഇല്ല"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"മുഖം <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"മുഖത്തിന്റെ ഐക്കൺ"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യുക"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ഒരു അക്കൗണ്ടിനായി സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഉദാഹരണത്തിന്, ആളുകൾ അപ്ലിക്കേഷൻ ഒരു അക്കൗണ്ടിൽ സമന്വയിപ്പിച്ചിട്ടുണ്ടോയെന്നത് നിർണ്ണയിക്കാൻ ഇതിനാകും."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"സമന്വയം ഓണാക്കുക, ഓഫാക്കുക ടോഗിൾചെയ്യുക"</string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"വൈഫൈയ്ക്ക് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"നിങ്ങളുടെ ഹോട്ട്‌സ്‌പോട്ട് ക്രമീകരണത്തിൽ വരുത്തിയ മാറ്റങ്ങൾ"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"നിങ്ങളുടെ ഹോട്ട്‌സ്‌പോട്ട് ബാൻഡ് മാറി."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"നിങ്ങളുടെ മുൻഗണനയനുസരിച്ചുള്ള, 5GHz മാത്രം എന്നത് ഈ ഉപകരണം പിന്തുണയ്ക്കുന്നില്ല. പകരം, 5GHz ബാൻഡ് ലഭ്യമാകുമ്പോൾ അത് ഉപയോഗിക്കും."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> എന്നതിലേക്ക് മാറി"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>-ന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ലാത്തപ്പോൾ ഉപകരണം <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ഉപയോഗിക്കുന്നു. നിരക്കുകൾ ബാധകമായേക്കാം."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> നെറ്റ്‌വർക്കിൽ നിന്ന് <xliff:g id="NEW_NETWORK">%2$s</xliff:g> നെറ്റ്‌വർക്കിലേക്ക് മാറി"</string>
@@ -1906,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> എന്നതിനെ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> എന്നിവ&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> എന്നിവ&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; എന്നതിലേക്ക് അപ്ഡേറ്റ് ചെയ്യണോ?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> എന്നതിനെ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; എന്നതിലേക്ക് അപ്ഡേറ്റ് ചെയ്യണോ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; എന്നതിലേക്ക് <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> അപ്ഡേറ്റ് ചെയ്യുക?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> എന്നിവയെ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; എന്നതിലേക്ക് അപ്ഡേറ്റ് ചെയ്യണോ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"സംരക്ഷിക്കുക"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"വേണ്ട, നന്ദി"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"അപ്ഡേറ്റ് ചെയ്യുക"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"പാസ്‌വേഡ്"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"വിലാസം"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ക്രെഡിറ്റ് കാർഡ്"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 5caebe1..ddf1bc6 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -133,8 +133,8 @@
     <item msgid="4397097370387921767">"%s Wi-Fi Дуудлага"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Идэвхгүй"</string>
-    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi илүү эрхэмлэдэг"</string>
-    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Давуу эрхтэй мобайл"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi давуу эрхтэй"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Мобайл давуу эрхтэй"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Зөвхөн Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: дамжуулагдаагүй"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Нислэгийн горим"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Нислэгийн горим асав"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Нислэгийн горим унтарсан"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Батарей хэмнэгч"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Тэжээл хэмнэгч УНТРААЛТТАЙ байна"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Тэжээл хэмнэгч АСААЛТТАЙ байна"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Тохиргоо"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Туслах"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Дуут туслах"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Биеийн мэдрэгч"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"таны биеийн байдлын талаарх мэдрэгч бүхий өгөгдөлд нэвтрэх"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны биеийн ерөнхий байдлын үзүүлэлтүүдийн мэдрэгчийн өгөгдөлд хандахыг зөвшөөрөх үү?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Хөгжим"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"хөгжимдөө хандах"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны хөгжимд хандахыг зөвшөөрөх үү?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Зураг &amp; видео"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"зураг &amp; видеондоо хандах"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны зураг &amp; видеонд хандахыг зөвшөөрөх үү?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Цонхны агуулгыг авах"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Таны харилцан үйлчлэх цонхны контентоос шалгах."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Хүрч танихыг асаах"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Хурууны хээний загварыг нэмэх эсвэл усгтах үйлдлийг хийх зөвшөөрлийг програмд олгодог."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"хурууны хээний програм хангамжийг ашиглах"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний апп хамгамжийг ашиглах зөвшөөрлийг аппд олгодог"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"хөгжмийн цуглуулгаа унших"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Таны хөгжмийн цуглуулгыг унших зөвшөөрлийг аппад олгодог."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"хөгжмийн цуглуулгаа тохируулах"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Таны хөгжмийн цуглуулгыг тохируулах зөвшөөрлийг аппад олгодог."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"видео цуглуулгаа унших"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Таны видео цуглуулгыг унших зөвшөөрлийг аппад олгодог."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"видео цуглуулгаа тохируулах"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Таны видео цуглуулгыг тохируулах зөвшөөрлийг аппад олгодог."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"зургийн цуглуулгаа унших"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Таны зургийн цуглуулгыг унших зөвшөөрлийг аппад олгодог."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"зургийн цуглуулгаа тохируулах"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Таны зургийн цуглуулгыг тохируулах зөвшөөрлийг аппад олгодог."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"медиа цуглуулгаасаа байршлыг унших"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Таны медиа цуглуулгаас байршлыг унших зөвшөөрлийг аппад олгодог."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Хурууны хээг дутуу уншуулсан байна. Дахин оролдоно уу."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Хурууны хээ боловсруулж чадахгүй байна. Дахин оролдоно уу."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Хурууны хээ мэдрэгч бохирдсон байна. Та цэвэрлэсний дараагаар дахин оролдоно уу."</string>
@@ -765,7 +782,7 @@
     <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Тайлах PIN-г оруулна уу"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Буруу PIN код."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Тайлах бол Цэсийг дараад 0."</string>
-    <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Яаралтай дугаар"</string>
+    <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Яаралтай тусламжийн дугаар"</string>
     <string name="lockscreen_carrier_default" msgid="6169005837238288522">"Үйлчилгээ байхгүй"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Дэлгэц түгжигдсэн."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Яаралтай дуудлага хийх буюу эсвэл түгжээг тайлах бол цэсийг дарна уу."</string>
@@ -1164,7 +1181,7 @@
     <string name="dump_heap_text" msgid="4809417337240334941">"Энэ үйл явц <xliff:g id="PROC">%1$s</xliff:g> нь үйл ажиллагааны санах ойн хязгаар болох <xliff:g id="SIZE">%2$s</xliff:g> хэмжээг давсан байна. Та хэт их хуримтлагдсан мэдээллийг тэдгээрийн өөрсдийнх нь хөгжүүлэгчтэй хуваалцах боломжтой. Болгоомжтой байгаарай: энэхүү хэт их хуримтлагдсан мэдээлэлд аппликейшнаас нэвтрэх боломжтой таны хувийн мэдээлэл агуулагдсан байж болно."</string>
     <string name="sendText" msgid="5209874571959469142">"Текст илгээх үйлдлийг сонгох"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Хонхны аяны хэмжээ"</string>
-    <string name="volume_music" msgid="5421651157138628171">"Медиа дууны хэмжээ"</string>
+    <string name="volume_music" msgid="5421651157138628171">"Медиа дууны түвшин"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Блютүүтээр тоглож байна"</string>
     <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Хонхны дууг чимээгүй болгов"</string>
     <string name="volume_call" msgid="3941680041282788711">"Ирсэн дуудлагын дууны хэмжээ"</string>
@@ -1175,7 +1192,7 @@
     <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"Блютүүтын хэмжээ"</string>
     <string name="volume_icon_description_ringer" msgid="3326003847006162496">"Хонхны дууны хэмжээ"</string>
     <string name="volume_icon_description_incall" msgid="8890073218154543397">"Дуудлагын дууны хэмжээ"</string>
-    <string name="volume_icon_description_media" msgid="4217311719665194215">"Медиа дууны хэмжээ"</string>
+    <string name="volume_icon_description_media" msgid="4217311719665194215">"Медиа дууны түвшин"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Мэдэгдлийн дууны хэмжээ"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Үндсэн хонхны ая"</string>
     <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Үндсэн (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;-д хадгалах уу?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;-д хадгалах уу?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;-д хадгалах уу?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;-д шинэчлэх үү?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;-д шинэчлэх үү?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;-д шинэчлэх үү?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;-д шинэчлэх үү?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Хадгалах"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Үгүй, баярлалаа"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Шинэчлэх"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"нууц үг"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"хаяг"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредит карт"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 206e0de..c257008 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"विमान मोड"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"विमान मोड चालू आहे"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"विमान मोड बंद आहे"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"बॅटरी बचतकर्ता"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"बॅटरी बचतकर्ता बंद आहे"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"बॅटरी बचतकर्ता सुरू आहे"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"सेटिंग्ज"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"सहाय्यता"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"व्हॉइस सहाय्य"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"शरीर सेन्सर"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"आपल्‍या महत्त्वाच्या मापनांविषयी सेंसर डेटा अॅक्सेस करा"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमच्या महत्त्वाच्या लक्षणांविषयीचा सेन्सर डेटा अॅक्सेस करू द्यायचे?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"संगीत"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"तुमचे संगीत अॅक्सेस करा"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमचे संगीत अॅक्सेस करू द्यायचे का?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"फोटो आणि व्हिडिओ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"तुमचे फोटो आणि व्हिडिओ अॅक्सेस करा"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमचे फोटो आणि व्हिडिओ अॅक्सेस करू द्यायचे का?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"विंडो सामग्री पुनर्प्राप्त करा"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"तुम्ही परस्‍परसंवाद करीत असलेल्‍या विंडोची सामग्री तपासा."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"स्पर्श करून अन्वेषण चालू करा"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"वापर करण्याकरिता फिंगरप्रिंट टेम्पलेट जोडण्यासाठी आणि हटविण्यासाठी पद्धती रद्द करण्यास अॅपला अनुमती देते."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"फिंगरप्रिंट हार्डवेअर वापरा"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"प्रमाणीकरणाकरिता फिंगरप्रिंट हार्डवेअरचा वापर करण्यासाठी अॅपला अनुमती देते"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"तुमचा संगीत संग्रह वाचा"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"अॅपला तुमचा संगीत संग्रह वाचण्याची अनुमती देते."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"तुमच्या संगीत संग्रहामध्ये सुधारणा करा"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"अॅपला तुमच्या संगीत संग्रहामध्ये सुधारणा करण्याची अनुमती देते."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"तुमचा व्हिडिओ संग्रह वाचा"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"अ‍ॅपला तुमचा व्हिडिओ संग्रह वाचण्याची अनुमती देते."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"तुमच्या व्हिडिओ संग्रहामध्ये सुधारणा करा"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"अॅपला तुमच्या व्हिडिओ संग्रहामध्ये सुधारणा करण्याची अनुमती देते."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"तुमचा फोटो संग्रह वाचा"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"अ‍ॅपला तुमचा फोटो संग्रह वाचण्याची अनुमती देते."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"तुमच्या फोटो संग्रहामध्ये सुधारणा करा"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"अॅपला तुमच्या फोटो संग्रहामध्ये सुधारणा करण्याची अनुमती देते."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"तुमच्या मीडिया संग्रहातून स्थाने वाचा"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"अॅपला तुमच्या मीडिया संग्रहामध्येील स्थाने वाचण्यासाठी अनुमती देते."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फिंगरप्रिंट आढळली. कृपया पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फिंगरप्रिंटवर प्रक्रिया करणे शक्य झाले नाही. कृपया पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फिंगरप्रिंट सेन्सर खराब आहे. कृपया साफ करा आणि पुन्हा प्रयत्न करा."</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"फिंगरप्रिंट आयकन"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"चेहरा ऑथेंटिकेशन हार्डवेअर व्यवस्थापित करा"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"अॅपला वापरासाठी चेहरा टेम्पलेट जोडण्याच्या आणि हटवण्याच्या पद्धती जारी करू देते."</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"चेहरा ऑथेंटिकेशन हार्डवेअर वापरा"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"अॅपला चेहरा ऑथेंटिकेशनसाठी ऑथेंटिकेशन हार्डवेअर वापरू देते"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"चेहऱ्यावर प्रक्रिया झाली नाही. पुन्हा प्रयत्न करा."</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"चेहऱ्यावर खूप प्रकाश आहे. कृपया कमी प्रकाशात प्रयत्न करा."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"चेहऱ्यावर खूप अंधार आहे. कृपया प्रकाश स्रोत खुला करा."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"कृपया सेन्सर चेहऱ्यापासून आणखी दूर हलवा."</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"कृपया सेन्सर चेहऱ्याच्या आणखी जवळ आणा."</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"कृपया सेन्सर आणखी वर हलवा."</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"कृपया सेन्सर आणखी खाली हलवा."</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"कृपया सेन्सर उजवीकडे हलवा."</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"कृपया सेन्सर डावीकडे हलवा."</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"कृपया सेन्सरकडे पहा."</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"चेहरा आढळला नाही."</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"डिव्हाइसच्या समोर चेहरा स्थिर ठेवा."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"चेहरा हार्डवेअर उपलब्ध नाही."</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"चेहरा टाइमआउट झाला. पुन्हा प्रयत्न करा."</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"चेहरा स्टोअर केला जाऊ शकत नाही."</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"चेहरा ऑपरेशन रद्द केले गेले."</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"खूप जास्त प्रयत्न केले. नंतर पुन्हा प्रयत्न करा."</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"खूप जास्त प्रयत्न केले. चेहरा ऑथेंटिकेशन बंद केले गेले."</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"पुन्हा प्रयत्न करा."</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"चेहरा नोंदवलेला नाही."</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"या डिव्हाइसमध्ये चेहरा ऑथेंटिकेशन सेन्सर नाही"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"चेहरा <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"चेहरा आयकन"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"सिंक सेटिंग्‍ज वाचा"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"खात्याच्या सिंक सेटिंग्ज वाचण्यासाठी अॅप ला अनुमती देते. उदाहरणार्थ, हे खात्यासह लोकांचा अॅप संकालित केला आहे किंवा नाही हे निर्धारित करू शकते."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"सिंक चालू आणि बंद करा टॉगल करा"</string>
@@ -731,7 +721,7 @@
     <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
     <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"कार्य मोबाईल"</string>
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"कार्य पेजर"</string>
-    <string name="phoneTypeAssistant" msgid="5596772636128562884">"साहाय्यक"</string>
+    <string name="phoneTypeAssistant" msgid="5596772636128562884">"असिस्टंट"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
     <string name="eventTypeCustom" msgid="7837586198458073404">"कस्टम"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"वाढदिवस"</string>
@@ -764,7 +754,7 @@
     <string name="orgTypeOther" msgid="3951781131570124082">"अन्य"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"कस्टम"</string>
     <string name="relationTypeCustom" msgid="3542403679827297300">"कस्टम"</string>
-    <string name="relationTypeAssistant" msgid="6274334825195379076">"साहाय्यक"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"असिस्टंट"</string>
     <string name="relationTypeBrother" msgid="8757913506784067713">"भाऊ"</string>
     <string name="relationTypeChild" msgid="1890746277276881626">"मूल"</string>
     <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"घरातील जोडीदार"</string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"वाय-फाय ला इंटरनेटचा अॅक्सेस नाही"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"पर्यायांसाठी टॅप करा"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"तुमच्या हॉटस्पॉट सेटिंग्जमधील बदल"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"तुमचा हॉटस्पॉट बँड बदलला आहे."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"हे डिव्हाइस तुमच्या फक्त ५GHz साठी प्राधान्याला सपोर्ट करत नाही. त्याऐवजी, हे डिव्हाइस ५GHz बँड उपलब्ध असताना वापरेल."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> वर स्विच केले"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> कडे इंटरनेटचा अॅक्सेस नसताना डिव्हाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> वापरते. शुल्क लागू शकते."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> वरून <xliff:g id="NEW_NETWORK">%2$s</xliff:g> वर स्विच केले"</string>
@@ -1875,7 +1862,7 @@
     <string name="demo_starting_message" msgid="5268556852031489931">"डेमो प्रारंभ करत आहे..."</string>
     <string name="demo_restarting_message" msgid="952118052531642451">"डिव्हाइस रीसेट करत आहे..."</string>
     <string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> अक्षम केले"</string>
-    <string name="conference_call" msgid="3751093130790472426">"परिषद कॉल"</string>
+    <string name="conference_call" msgid="3751093130790472426">"कॉन्फरन्स कॉल"</string>
     <string name="tooltip_popup_title" msgid="5253721848739260181">"टूलटिप"</string>
     <string name="app_category_game" msgid="5431836943981492993">"गेम"</string>
     <string name="app_category_audio" msgid="1659853108734301647">"संगीत आणि ऑडिओ"</string>
@@ -1906,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;मध्ये <xliff:g id="TYPE">%1$s</xliff:g> सेव्ह करायची?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;मध्ये <xliff:g id="TYPE_0">%1$s</xliff:g> आणि <xliff:g id="TYPE_1">%2$s</xliff:g> सेव्ह करायची?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;मध्ये <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g> सेव्ह करायची?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; वर अपडेट करायचे आहे का?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g> &lt;/b&gt; वर अपडेट करायचे आहे का?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> आणि <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; वर अपडेट करायचा आहे का?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g>&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;वर अपडेट करायचा आहे का?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"सेव्ह करा"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"नाही, नको"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"अपडेट करा"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"पत्ता"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 074d27b..939b9a4 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod pesawat"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mod Pesawat DIHIDUPKAN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mod Pesawat DIMATIKAN"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Penjimat bateri"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Penjimat bateri DIMATIKAN"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Penjimat Bateri DIHIDUPKAN"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Tetapan"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Bantu"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Bantuan Suara"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Penderia Badan"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"akses data penderia tentang tanda vital anda"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data penderia tentang tanda vital anda?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muzik"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"akses muzik anda"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses muzik anda?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Foto &amp; Video"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"akses foto &amp; video anda"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto &amp; video anda?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Dapatkan kembali kandungan tetingkap"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Periksa kandungan tetingkap yang berinteraksi dengan anda."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Hidupkan Jelajah melalui Sentuhan"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Membenarkan apl menggunakan kaedah untuk menambahkan dan memadamkan templat cap jari untuk digunakan."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gunakan perkakasan cap jari"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Membenarkan apl menggunakan perkakasan cap jari untuk pengesahan"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"baca koleksi muzik anda"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Membenarkan apl membaca koleksi muzik anda."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"ubah suai koleksi muzik anda"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Membenarkan apl mengubah suai koleksi muzik anda."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"baca koleksi video anda"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Membenarkan apl membaca koleksi video anda."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"ubah suai koleksi video anda"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Membenarkan apl mengubah suai koleksi video anda."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"baca koleksi foto anda"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Membenarkan apl membaca koleksi foto anda."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"ubah suai koleksi foto anda"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Membenarkan apl mengubah suai koleksi foto anda."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"baca lokasi daripada koleksi media anda"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Membenarkan apl membaca lokasi daripada koleksi media anda."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Cap jari separa dikesan. Sila cuba lagi."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Tidak dapat memproses cap jari. Sila cuba lagi."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Penderia cap jari kotor. Sila bersihkan dan cuba lagi."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dan <xliff:g id="TYPE_2">%3$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Kemas kini ke &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Kemas kini <xliff:g id="TYPE">%1$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Kemas kini <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Kemas kini <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dan <xliff:g id="TYPE_2">%3$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Tidak, terima kasih"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Kemas kini"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"kata laluan"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"alamat"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kad kredit"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 19bf212..23a73ff 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -30,7 +30,7 @@
     <string name="untitled" msgid="4638956954852782576">"&lt;ခေါင်းစဉ်မဲ့&gt;"</string>
     <string name="emptyPhoneNumber" msgid="7694063042079676517">"(ဖုန်းနံပါတ်မရှိပါ)"</string>
     <string name="unknownName" msgid="6867811765370350269">"မသိရ"</string>
-    <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"အသံစာပို့စနစ်"</string>
+    <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"အသံမေးလ်"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"ဆက်သွယ်မှုဆိုင်ရာပြသနာ သို့မဟုတ် မမှန်ကန်သောMMIကုတ်"</string>
     <string name="mmiFdnError" msgid="5224398216385316471">"သတ်မှတ်ခေါ်ဆိုနိုင်သောနံပါတ်များထံသာ ကန့်သတ်ထားသည်"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"လေယာဥ်ပျံပေါ်အသုံးပြုသောစနစ်"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"လေယဥ်ပျံပေါ်၌အသုံးပြုသောစနစ်ဖွင့်ထားသည်"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"လေယဥ်ပျံပေါ်၌အသုံးပြုသောစနစ်ပိတ်ထားသည်"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"ဘက်ထရီ ချွေတာမှုစနစ်"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ဘက်ထရီချွေတာခြင်းမုဒ်ကို ပိတ်ထားသည်"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"ဘက်ထရီချွေတာခြင်းမုဒ်ကို ဖွင့်ထားသည်"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ဆက်တင်များ"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"အကူအညီ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"အသံ အကူအညီ"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ခန္ဓာကိုယ် အာရုံခံကိရိယာများ"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"သင်၏ အဓိကကျသော လက္ခဏာများအကြောင်း အာရုံခံကိရိယာဒေတာကို ရယူသုံးစွဲရန်"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင်၏ အရေးကြီးသောလက္ခဏာ အာရုံခံကိရိယာ ဒေတာများကို သုံးခွင့်ပေးလိုပါသလား။"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"တေးဂီတ"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"သင့်တေးဂီတသို့ ဝင်သည်"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင့်တေးဂီတကို ဝင်ခွင့်ပေးလိုပါသလား။"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ဓာတ်ပုံနှင့် ဗီဒီယိုများ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"သင့်ဓာတ်ပုံနှင့် ဗီဒီယိုများသို့ ဝင်သည်"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင့်ဓာတ်ပုံနှင့် ဗီဒီယိုများကို ဝင်ခွင့်ပေးလိုပါသလား။"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ဝင်းဒိုးတွင် ပါရှိသည်များကို ပြန်လည်ရယူရန်"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"သင်အသုံးပြုနေသော ဝင်းဒိုးတွင် ပါရှိသည်များကို ကြည့်ရှုစစ်ဆေးသည်။"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"တို့ထိခြင်းဖြင့် ရှာဖွေမှုကို ဖွင့်ရန်"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"အသုံးပြုရန်အတွက် လက်ဗွေရာပုံစံများကို ပေါင်းထည့်ရန် သို့မဟုတ် ဖျက်ရန်နည်းလမ်းများကို အပ်ဖ်အား အသုံးပြုခွင့်ပြုသည်။"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"လက်ဗွေရာပစ္စည်းကို အသုံးပြုမည်"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"စစ်မှန်ကြောင်းအထောက်အထားပြသခြင်းအတွက် လက်ဗွေရာပစ္စည်းကို အသုံးပြုရန် အပ်ဖ်အားခွင့်ပြုသည်။"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"သင့်တေးဂီတ စုစည်းမှုကို ဖတ်ခြင်း"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"အက်ပ်အား သင့်တေးဂီတစုစည်းမှုကို ဖတ်ခွင့်ပေးသည်။"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"သင့်တေးဂီတ စုစည်းမှုကို ပြုပြင်ခြင်း"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"အက်ပ်အား သင့်တေးဂီတစုစည်းမှုကို ပြုပြင်ခွင့်ပေးသည်။"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"သင့်ဗီဒီယို စုစည်းမှုကို ဖတ်ခြင်း"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"အက်ပ်အား သင့်ဗီဒီယိုစုစည်းမှုကို ဖတ်ခွင့်ပေးသည်။"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"သင့်ဗီဒီယို စုစည်းမှုကို ပြုပြင်ခြင်း"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"အက်ပ်အား သင့်ဗီဒီယိုစုစည်းမှုကို ပြုပြင်ခွင့်ပေးသည်။"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"သင့်ဓာတ်ပုံ စုစည်းမှုကို ဖတ်ခြင်း"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"အက်ပ်အား သင့်ဓာတ်ပုံစုစည်းမှုကို ဖတ်ခွင့်ပေးသည်။"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"သင့်ဓာတ်ပုံ စုစည်းမှုကို ပြုပြင်ခြင်း"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"အက်ပ်အား သင့်ဓာတ်ပုံစုစည်းမှုကို ပြုပြင်ခွင့်ပေးသည်။"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"သင့်မီဒီယာစုစည်းမှုမှ တည်နေရာများကို ဖတ်ခြင်း"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"အက်ပ်အား သင့်မီဒီယာစုစည်းမှုမှ တည်နေရာများကို ဖတ်ခွင့်ပေးသည်။"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"လက်ဗွေရဦ တစ်ပိုင်းတစ်စ တွေ့ရှိသည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"လက်ဗွေရာယူခြင်း မဆောင်ရွက်နိုင်ပါ။ ထပ်မံကြိုးစားပါ။"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"လက်ဗွေရာဖတ်ကိရိယာ ညစ်ပေနေသည်။ ကျေးဇူးပြု၍ ရှင်းလင်းကာ ထပ်မံကြိုးစားပါ။"</string>
@@ -521,26 +538,26 @@
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"လက်ဗွေ အိုင်ကွန်"</string>
     <string name="permlab_manageFace" msgid="2137540986007309781">"မျက်နှာအထောက်အထားစိစစ်ခြင်း စက်ပစ္စည်းကို စီမံပါ"</string>
-    <string name="permdesc_manageFace" msgid="8919637120670185330">"အသုံးပြုရန်အတွက် မျက်နှာပုံစံထည့်ရန် (သို့) ဖျက်ရန်နည်းလမ်းကို အက်ပ်အားသုံးခွင့်ပြုသည်။"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"အသုံးပြုရန်အတွက် မျက်နှာပုံစံထည့်ရန် (သို့) ဖျက်ရန်နည်းလမ်းကို အက်ပ်အား သုံးခွင့်ပြုသည်။"</string>
     <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"မျက်နှာအထောက်အထားစိစစ်ခြင်း စက်ပစ္စည်းကို သုံးပါ"</string>
     <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"အထောက်အထားစိစစ်ရန်အတွက် ဤအက်ပ်အား မျက်နှာအထောက်အထားစိစစ်ခြင်း စက်ပစ္စည်းကိုသုံးခွင့်ပြုသည်"</string>
-    <string name="face_acquired_insufficient" msgid="5901287247766106330">"မျက်နှာကို မဆောင်ရွက်နိုင်ပါ။ ထပ်လုပ်ကြည့်ပါ။"</string>
-    <string name="face_acquired_too_bright" msgid="610606792381297174">"မျက်နှာအလွန်လင်းနေသည်။ အလင်းနည်းနည်းတွင်ထပ်စမ်းပါ။"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"မျက်နှာကို မမှတ်မိပါ။ ထပ်လုပ်ကြည့်ပါ။"</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"မျက်နှာအလွန်လင်းနေသည်။ အလင်းလျှော့ပြီး စမ်းကြည့်ပါ။"</string>
     <string name="face_acquired_too_dark" msgid="7229162716976778371">"မျက်နှာအလွန်မှောင်နေသည်။ ပြတင်းပေါက်ဖွင့်လိုက်ပါ။"</string>
     <string name="face_acquired_too_close" msgid="1980310037427755293">"အာရုံခံကိရိယာကို မျက်နှာနှင့် ခွာလိုက်ပါ။"</string>
-    <string name="face_acquired_too_far" msgid="4494571381828850007">"အာရုံခံကိရိယာကို မျက်နှာနှင့် ကပ်လိုက်ပါ။"</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"အာရုံခံကိရိယာကို မျက်နှာအနီး ရွှေ့လိုက်ပါ။"</string>
     <string name="face_acquired_too_high" msgid="228411096134808372">"အာရုံခံကိရိယာကို ပိုမြင့်အောင်ထားပါ။"</string>
     <string name="face_acquired_too_low" msgid="4539774649296349109">"အာရုံခံကိရိယာကို ပိုနိမ့်အောင်ထားပါ။"</string>
     <string name="face_acquired_too_right" msgid="1650292067226118760">"အာရုံခံကိရိယာကို ညာဘက်သို့ ရွှေ့ပါ။"</string>
     <string name="face_acquired_too_left" msgid="2712489669456176505">"အာရုံခံကိရိယာကို ဘယ်ဘက်သို့ ရွှေ့ပါ။"</string>
     <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"အာရုံခံကိရိယာကို ကြည့်ပါ။"</string>
     <string name="face_acquired_not_detected" msgid="5707782294589511391">"မျက်နှာတစ်ခုမျှ မတွေ့ပါ။"</string>
-    <string name="face_acquired_not_steady" msgid="3722829465011040042">"မျက်နှာကို စက်ပစ္စည်း၏ အရှေ့တွင် အဆင်သင့်ထားပါ။"</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"မျက်နှာကို စက်၏ရှေ့တွင် အဆင်သင့်ထားပါ။"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="6255891785768984615">"မျက်နှာ စက်ပစ္စည်း မရနိုင်ပါ။"</string>
     <string name="face_error_timeout" msgid="4014326147867150054">"မျက်နှာ သက်တမ်းကုန်သွားပါပြီ။ ထပ်စမ်းကြည့်ပါ။"</string>
-    <string name="face_error_no_space" msgid="8224993703466381314">"မျက်နှာကို သိုလှောင်၍မရပါ။"</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"မျက်နှာကို သိမ်း၍မရပါ။"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"မျက်နှာ ဆောင်ရွက်ခြင်းကို ပယ်ဖျက်လိုက်ပါပြီ။"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"အကြိမ်များစွာ စမ်းပြီးပါပြီ။ နောက်မှထပ်စမ်းပါ။"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"အကြိမ်များစွာ စမ်းပြီးပါပြီ။ ပိတ်လိုက်ပါပြီ။"</string>
@@ -1876,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; တွင် သိမ်းဆည်းလိုပါသလား။"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> နှင့် <xliff:g id="TYPE_1">%2$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; တွင် သိမ်းဆည်းလိုပါသလား။"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g>  နှင့် <xliff:g id="TYPE_2">%3$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; တွင် သိမ်းဆည်းလိုပါသလား။"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; သို့ အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; သို့ အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> နှင့် <xliff:g id="TYPE_1">%2$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; သို့ အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g> နှင့် <xliff:g id="TYPE_2">%3$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; သို့ အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"သိမ်းရန်"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"မလိုပါ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"အပ်ဒိတ်လုပ်ရန်"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"စကားဝှက်"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"လိပ်စာ"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ခရက်တစ်ကတ်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 4f643fc..7d3fe48 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flymodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flymodus er på"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flymodus er av"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Batterisparing"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Batterisparing er AV"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Batterisparing er PÅ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Innstillinger"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Hjelp"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Talehjelp"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Kroppssensorer"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"få tilgang til sensordata om de vitale tegnene dine"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til sensordata om de vitale tegnene dine?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musikk"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"få tilgang til musikken din"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til musikken din?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Bilder og videoer"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"få tilgang til bildene og videoene dine"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til bildene og videoene dine?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"hente innhold i vinduer"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Appen analyserer innholdet i vinduer du samhandler med."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"slå på berøringsutforsking"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Lar appen fremkalle metoder for å legge til og slette fingeravtrykkmaler for bruk."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"bruke fingeravtrykkmaskinvare"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Lar appen bruke fingeravtrykkmaskinvare til godkjenning"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"lese musikksamlingen din"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Lar appen lese musikksamlingen din."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"gjøre endringer i musikksamlingen din"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Lar appen gjøre endringer i musikksamlingen din."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"lese videosamlingen din"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Lar appen lese videosamlingen din."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"gjøre endringer i videosamlingen din"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Lar appen gjøre endringer i videosamlingen din."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"lese bildesamlingen din"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Lar appen lese bildesamlingen din."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"gjøre endringer i bildesamlingen din"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Lar appen gjøre endringer i bildesamlingen din."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"lese posisjoner fra mediesamlingen din"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Lar appen lese posisjoner fra mediesamlingen din."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Deler av fingeravtrykket er registrert. Prøv på nytt."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kunne ikke registrere fingeravtrykket. Prøv på nytt."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingeravtrykksensoren er skitten. Rengjør den og prøv på nytt."</string>
@@ -620,14 +637,14 @@
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Overvåker antallet feil passord som er skrevet inn når skjermen låses opp, og låser nettbrettet eller sletter denne brukerens data når for mange feil passord er skrevet inn."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Overvåker antallet feil passord som er skrevet inn når skjermen låses opp, og låser TV-en eller sletter denne brukerens data når for mange feil passord er skrevet inn."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Overvåker antallet feil passord som er skrevet inn når skjermen låses opp, og låser telefonen eller sletter denne brukerens data når for mange feil passord er skrevet inn."</string>
-    <string name="policylab_resetPassword" msgid="4934707632423915395">"Endre skjermlåsen"</string>
-    <string name="policydesc_resetPassword" msgid="1278323891710619128">"Endre skjermlåsen."</string>
-    <string name="policylab_forceLock" msgid="2274085384704248431">"Lås skjermen"</string>
-    <string name="policydesc_forceLock" msgid="1141797588403827138">"Kontrollér hvordan og når skjermen låses."</string>
-    <string name="policylab_wipeData" msgid="3910545446758639713">"Slett alle data"</string>
+    <string name="policylab_resetPassword" msgid="4934707632423915395">"Endring av skjermlåsen"</string>
+    <string name="policydesc_resetPassword" msgid="1278323891710619128">"Kan endre skjermlåsen."</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Låsing av skjermen"</string>
+    <string name="policydesc_forceLock" msgid="1141797588403827138">"Kan kontrollere hvordan og når skjermen låses."</string>
+    <string name="policylab_wipeData" msgid="3910545446758639713">"Sletting av alle data"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Tilbakestill nettbrettets data uten advarsel ved å tilbakestille til fabrikkstandard."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Slett TV-ens data uten advarsel ved å tilbakestille til fabrikkstandard."</string>
-    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Tilbakestill telefonens data uten advarsel, ved å tilbakestille til fabrikkstandard."</string>
+    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Telefonens data kan slettes uten advarsel ved å tilbakestille til fabrikkstandard."</string>
     <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Slett brukerdataene"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"Sletter denne brukerens data på dette nettbrettet uten advarsel."</string>
     <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"Sletter denne brukerens data på denne TV-en uten advarsel."</string>
@@ -640,7 +657,7 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Krev at lagrede appdata krypteres."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Deaktiver kameraer"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Hindre bruk av alle kameraer på enheten."</string>
-    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Deaktiver enkelte skjermlåsfunksjoner"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Deaktivering av skjermlåsfunksjoner"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Forhindrer bruk av enkelte skjermlåsfunksjoner."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjemmenummer"</item>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vil du lagre <xliff:g id="TYPE">%1$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Vil du oppdatere til &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vil du oppdatere <xliff:g id="TYPE">%1$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vil du oppdatere <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vil du oppdatere <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Lagre"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nei takk"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Oppdater"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"passord"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredittkort"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 6d1c926..55e62ff 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"हवाइजहाज मोड"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"हवाइजहाज मोड खुला छ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"हवाइजहाज मोड बन्द छ"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"ब्याट्री सेभर"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ब्याट्री सेभर निष्क्रिय छ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"ब्याट्री सेभर सक्रिय छ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"सेटिङहरू"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"सहायता दिनुहोस्"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"आवाज सहायता"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"शारीरिक सेन्सर"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"तपाईंको महत्त्वपूर्ण संकेत बारे सेन्सर डेटा पहुँच गर्नुहोस्"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई आफ्ना महत्त्वपूर्ण लक्षणहरूसम्बन्धी सेन्सर डेटामाथि पहुँच राख्न दिने हो?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"सङ्गीत"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"आफ्नो सङ्गीतमाथि पहुँच राख्नुहोस्‌"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई तपाईंको सङ्गीतमाथि पहुँच राख्न दिने हो?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"तस्बिर तथा भिडियोहरू"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"आफ्नो तस्बिर &amp; भिडियोहरूमाथि पहुँच राख्नुहोस्‌"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई आफ्नो तस्बिर तथा भिडियोहरूमाथि पहुँच राख्न दिने हो?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"विन्डो सामग्रीको पुनःबहाली गर्नुहोस्।"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"तपाईँको अन्तरक्रिया भइरहेको विन्डोको सामग्रीको निरीक्षण गर्नुहोस्।"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"छोएर गरिने खोजलाई सुचारु गर्नुहोस्"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"अनुप्रयोगलाई प्रयोगको लागि औठाछाप टेम्प्लेट थप्न र मेटाउने तरिका आह्वान गर्न अनुमति दिन्छ।"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"औठाछाप हार्डवेयर प्रयोग गर्नुहोस्"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"अनुप्रयोगलाई प्रमाणीकरणको लागि औठाछाप हार्डवेयर प्रयोग गर्न अनुमति दिन्छ"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"आफ्नो सङ्गीतको सङ्ग्रह पढ्नुहोस्"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"यसले अनुप्रयोगलाई तपाईंको सङ्गीतको सङ्ग्रह पढ्न दिन्छ।"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"आफ्नो सङ्गीतको सङ्ग्रह परिमार्जन गर्नुहोस्"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"यसले अनुप्रयोगलाई तपाईंको सङ्गीतको सङ्ग्रह परिमार्जन गर्न दिन्छ।"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"आफ्नो भिडियोको सङ्ग्रह पढ्नुहोस्"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"यसले अनुप्रयोगलाई तपाईंको भिडियोको सङ्ग्रह पढ्न दिन्छ।"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"आफ्नो भिडियोको सङ्ग्रह परिमार्जन गर्नुहोस्"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"यसले अनुप्रयोगलाई तपाईंको भिडियोको सङ्ग्रह परिमार्जन गर्न दिन्छ।"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"आफ्नो तस्बिरको सङ्ग्रह पढ्नुहोस्"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"यसले अनुप्रयोगलाई तपाईंको तस्बिरको सङ्ग्रह पढ्न दिन्छ।"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"आफ्नो तस्बिरको सङ्ग्रह परिमार्जन गर्नुहोस्"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"यसले अनुप्रयोगलाई तपाईंको तस्बिरको सङ्ग्रह परिमार्जन गर्न दिन्छ।"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"आफ्नो मिडियाको सङ्ग्रहका स्थानहरू पढ्नुहोस्‌"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"यसले अनुप्रयोगलाई तपाईंको मिडिया सङ्ग्रहका स्थानहरू पढ्न दिन्छ।"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक औठाछाप पत्ता लाग्यो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"औठाछाप प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"औँठाछाप सेन्सर फोहोर छ। कृपया सफा गरेर फेरि प्रयास गर्नुहोस्।"</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"फिंगरप्रिन्ट आइकन"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"अनुहार प्रमाणिकरण हार्डवेयर व्यवस्थापन गर्नुहोस्"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"अनुप्रयोगलाई प्रयोगका लागि अनुहार टेम्प्लेट थप्न र मेटाउने तरिका आह्वान गर्न अनुमति दिन्छ।"</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"अनुहार प्रमाणिकरण हार्डवेयर प्रयोग गर्नुहोस्"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"अनुप्रयोगलाई प्रमाणीकरणका लागि अनुहार प्रमाणीकरण हार्डवेयर प्रयोग गर्न अनुमति दिन्छ"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"अनुहार प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"अनुहारमा धेरै उज्यालो छ। कृपया कम प्रकाशमा प्रयास गर्नुहोस्।"</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"अनुहार धेरै गाढा छ। कृपया प्रकाशको स्रोतको थप्नुहोस्‌।"</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"कृपया अनुहारबाट सेन्सरलाई अलिक टाढा सार्नुहोस्।"</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"कृपया अनुहारलाई सेन्सरको नजिक ल्याउनुहोस्।"</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"कृपया सेन्सरलाई माथि सार्नुहोस्।"</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"कृपया सेन्सरलाई तल सार्नुहोस्।"</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"कृपया सेन्सरलाई दायाँतिर सार्नुहोस्।"</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"कृपया सेन्सरलाई बायाँतिर सार्नुहोस्।"</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"कृपया सेन्सरमा हेर्नुहोस्।"</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"अनुहार पत्ता लागेन।"</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"यन्त्रको अगाडि अनुहार स्थिर राख्नुहोस्।"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"अनुहार पहिचान गर्ने हार्डवेयर उपलब्ध छैन।"</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"अनुहारको समय सकिएको छ। फेरि प्रयास गर्नुहोस्‌।"</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"अनुहार भण्डारण गर्न सकिँदैन।"</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"अनुहार पहिचान रद्द गरियो।"</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"धेरैपटक प्रयासहरू भए। पछि फेरि प्रयास गर्नुहोस्‌।"</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"अत्यधिक धेरैपटक गलत प्रयासहरू भए। अनुहार प्रमाणिकरणलाई असक्षम पारियो।"</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"कुनै पनि अनुहार दर्ता गरिएन।"</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"यो यन्त्रमा कुनै अनुहार प्रमाणिकरण सेन्सर छैन"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"अनुहार <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"अनुहारको आइकन"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"समीकरण सेटिङहरू पढ्नुहोस्"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"अनुप्रयोगलाई खाताको लागि सिंक सेटिङहरू पढ्न अनुमति दिन्छ। उदाहरणको लागि यसले व्यक्तिहरको अनुप्रयोग खातासँग सिंक भएको नभएको निर्धारण गर्न सक्दछ।"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"टगल सिंक खुला र बन्द"</string>
@@ -1244,12 +1234,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"Wi-Fi मार्फत इन्टरनेटमाथि पहुँच राख्न सकिँदैन"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"विकल्पहरूका लागि ट्याप गर्नुहोस्"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"तपाईंको हटस्पट सेटिङहरूमा परिवर्तन हुन्छ"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"तपाईंको हटस्पट ब्यान्ड परिवर्तन भएको छ।"</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"यो यन्त्रले तपाईंको 5GHz मात्रको प्राथमिकतालाई समर्थन गर्दैन। बरु, उपलब्ध भएको खण्डमा यो यन्त्रले 5GHz ब्यान्ड प्रयोग गर्छ।"</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> मा बदल्नुहोस्"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> मार्फत इन्टरनेटमाथि पहुँच राख्न नसकेको अवस्थामा यन्त्रले <xliff:g id="NEW_NETWORK">%1$s</xliff:g> प्रयोग गर्दछ। शुल्क लाग्न सक्छ।"</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> बाट <xliff:g id="NEW_NETWORK">%2$s</xliff:g> मा परिवर्तन गरियो"</string>
@@ -1911,8 +1898,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> लाई &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; मा सुरक्षित गर्ने हो?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> र <xliff:g id="TYPE_1">%2$s</xliff:g> लाई  &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; मा सुरक्षित गर्ने हो?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> र <xliff:g id="TYPE_2">%3$s</xliff:g> लाई to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; मा सुरक्षित गर्ने हो?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; मा अद्यावधिक गर्ने हो?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> लाई &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; मा अद्यावधिक गर्ने हो?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> र <xliff:g id="TYPE_1">%2$s</xliff:g> लाई &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; मा अद्यावधिक गर्ने हो?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> र <xliff:g id="TYPE_2">%3$s</xliff:g> लाई to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; मा अद्यावधिक गर्ने हो?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"सुरक्षित गर्नुहोस्"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"पर्दैन, धन्यवाद"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"अद्यावधिक गर्नुहोस्"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ठेगाना"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string>
diff --git a/core/res/res/values-night/colors.xml b/core/res/res/values-night/colors.xml
new file mode 100644
index 0000000..351f8ea
--- /dev/null
+++ b/core/res/res/values-night/colors.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+
+  NOTE: You might also want to edit: packages/SystemUI/res/values-night/colors.xml
+  -->
+<resources>
+    <!-- The primary text color if the text is on top of a dark background.
+    This is also affects colorized notifications with dark backgrounds. -->
+    <color name="notification_primary_text_color_dark">#ddffffff</color>
+
+    <!-- The secondary text color if the text is on top of a dark background. -->
+    <color name="notification_secondary_text_color_dark">#ddffffff</color>
+
+    <color name="notification_default_color_dark">#ddffffff</color>
+
+    <!-- The background color of a notification card. -->
+    <color name="notification_material_background_color">@*android:color/material_grey_900</color>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values-night/themes_device_defaults.xml b/core/res/res/values-night/themes_device_defaults.xml
new file mode 100644
index 0000000..5e3675a
--- /dev/null
+++ b/core/res/res/values-night/themes_device_defaults.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+===============================================================
+                        PLEASE READ
+===============================================================
+This file contains the themes that are the Device Defaults.
+If you want to edit themes to skin your device, do it here.
+We recommend that you do not edit themes.xml and instead edit
+this file.
+
+Editing this file instead of themes.xml will greatly simplify
+merges for future platform versions and CTS compliance will be
+easier.
+===============================================================
+                        PLEASE READ
+===============================================================
+ -->
+<resources>
+
+    <!-- The dark default theme for apps that target API level XX and higher.
+         <p>The DeviceDefault themes are aliases for a specific device’s native look and feel. The
+         DeviceDefault theme family and widget style family offer ways for you to target your app
+         to a device’s native theme with all device customizations intact.</p>
+         <p>For example, when you set your app's {@code targetSdkVersion} to XX or higher, this
+         theme is applied to your application by default. As such, your app might appear with the
+         {@link #Theme_Material Material} styles on one device, but with a different set of styles on
+         another device. This is great if you want your app to fit with the device's native look and
+         feel. If, however, you prefer to keep your UI style the same across all devices, you should
+         apply a specific theme such as {@link #Theme_Material Material} or one of your own design.
+         For more information, read <a
+         href="http://android-developers.blogspot.com/20XX/XX/material-everywhere.html">Material
+         Everywhere</a>.</p>
+         <p>Styles used by the DeviceDefault theme are named using the convention
+         Type.DeviceDefault.Etc (for example, {@code Widget.DeviceDefault.Button} and
+         {@code TextAppearance.DeviceDefault.Widget.PopupMenu.Large}).</p>
+          -->
+    <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
+    <style name="Theme.DeviceDefault.Settings" parent="Theme.DeviceDefault"/>
+</resources>
diff --git a/core/res/res/values-night/themes_permission_controller.xml b/core/res/res/values-night/themes_permission_controller.xml
new file mode 100644
index 0000000..0ad2bdc
--- /dev/null
+++ b/core/res/res/values-night/themes_permission_controller.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<!-- themes for the permission grant dialog. -->
+<resources>
+    <style name="Theme.DeviceDefault.PermissionGrantApp"
+           parent="@style/Theme.DeviceDefault.Panel">
+        <item name="windowIsFloating">false</item>
+        <item name="windowTranslucentStatus">true</item>
+        <item name="backgroundDimEnabled">true</item>
+        <item name="windowAnimationStyle">@style/Animation.Material.Dialog</item>
+    </style>
+
+    <style name="Theme.DeviceDefault.PermissionGrant"
+           parent="@style/Theme.DeviceDefault.Dialog">
+        <item name="titleTextStyle">@style/PermissionGrantTitleMessage</item>
+        <item name="radioButtonStyle">@style/PermissionGrantRadioButton</item>
+        <item name="checkboxStyle">@style/PermissionGrantCheckbox</item>
+        <item name="buttonBarStyle">@style/PermissionGrantButtonBar</item>
+    </style>
+</resources>
diff --git a/core/res/res/values-night/values.xml b/core/res/res/values-night/values.xml
new file mode 100644
index 0000000..4eb2ff3
--- /dev/null
+++ b/core/res/res/values-night/values.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+    <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault">
+        <!-- Color palette -->
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+        <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="colorControlNormal">?attr/textColorPrimary</item>
+        <item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
+
+        <!-- QS panel background -->
+        <item name="colorBackgroundFloating">@color/material_grey_900</item>
+
+        <!-- volume background -->
+        <item name="panelColorBackground">@color/material_grey_800</item>
+    </style>
+
+    <style name="TextAppearance.Material.Notification">
+        <item name="textColor">@color/notification_secondary_text_color_dark</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 15f9dd0..0e13132 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -34,7 +34,7 @@
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Verbindingsprobleem of ongeldige MMI-code."</string>
     <string name="mmiFdnError" msgid="5224398216385316471">"Bewerking is beperkt tot vaste nummers."</string>
-    <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"Kan instellingen voor doorschakelen van oproepen niet wijzigen vanaf je telefoon tijdens roaming."</string>
+    <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"Kan instellingen voor doorschakelen van gesprekken niet wijzigen vanaf je telefoon tijdens roaming."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Service is ingeschakeld."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Service is ingeschakeld voor:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Service is uitgeschakeld."</string>
@@ -60,21 +60,21 @@
     <string name="ClirMmi" msgid="7784673673446833091">"Uitgaande beller-ID"</string>
     <string name="ColpMmi" msgid="3065121483740183974">"ID van verbonden lijn"</string>
     <string name="ColrMmi" msgid="4996540314421889589">"Beperking voor ID van verbonden lijn"</string>
-    <string name="CfMmi" msgid="5123218989141573515">"Oproep doorschakelen"</string>
+    <string name="CfMmi" msgid="5123218989141573515">"Gesprek doorschakelen"</string>
     <string name="CwMmi" msgid="9129678056795016867">"Wisselgesprek"</string>
-    <string name="BaMmi" msgid="455193067926770581">"Oproep blokkeren"</string>
+    <string name="BaMmi" msgid="455193067926770581">"Gesprek blokkeren"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"Wachtwoordwijziging"</string>
     <string name="PinMmi" msgid="3113117780361190304">"Pin-wijziging"</string>
     <string name="CnipMmi" msgid="3110534680557857162">"Nummer van beller beschikbaar"</string>
     <string name="CnirMmi" msgid="3062102121430548731">"Nummer van beller beperkt"</string>
     <string name="ThreeWCMmi" msgid="9051047170321190368">"Driewegs bellen"</string>
-    <string name="RuacMmi" msgid="7827887459138308886">"Ongewenste, vervelende oproepen weigeren"</string>
+    <string name="RuacMmi" msgid="7827887459138308886">"Ongewenste, vervelende gesprekken weigeren"</string>
     <string name="CndMmi" msgid="3116446237081575808">"Weergave van nummer van beller"</string>
     <string name="DndMmi" msgid="1265478932418334331">"Niet storen"</string>
-    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Beller-ID standaard ingesteld op \'beperkt\'. Volgende oproep: beperkt."</string>
-    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Beller-ID standaard ingesteld op \'beperkt\'. Volgende oproep: onbeperkt."</string>
-    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Beller-ID standaard ingesteld op \'onbeperkt\'. Volgende oproep: beperkt."</string>
-    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Beller-ID standaard ingesteld op \'onbeperkt\'. Volgende oproep: onbeperkt."</string>
+    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Beller-ID standaard ingesteld op \'beperkt\'. Volgend gesprek: beperkt."</string>
+    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Beller-ID standaard ingesteld op \'beperkt\'. Volgend gesprek: onbeperkt."</string>
+    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Beller-ID standaard ingesteld op \'onbeperkt\'. Volgend gesprek: beperkt."</string>
+    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Beller-ID standaard ingesteld op \'onbeperkt\'. Volgend gesprek: onbeperkt."</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"Service niet voorzien."</string>
     <string name="CLIRPermanent" msgid="3377371145926835671">"U kunt de instelling voor de beller-ID niet wijzigen."</string>
     <string name="RestrictedOnDataTitle" msgid="5221736429761078014">"Geen service voor mobiele data"</string>
@@ -88,7 +88,7 @@
     <string name="EmergencyCallWarningTitle" msgid="813380189532491336">"Noodoproepen niet beschikbaar"</string>
     <string name="EmergencyCallWarningSummary" msgid="1899692069750260619">"Er kunnen geen noodoproepen worden gemaakt via wifi"</string>
     <string name="notification_channel_network_alert" msgid="4427736684338074967">"Meldingen"</string>
-    <string name="notification_channel_call_forward" msgid="2419697808481833249">"Oproep doorschakelen"</string>
+    <string name="notification_channel_call_forward" msgid="2419697808481833249">"Gesprek doorschakelen"</string>
     <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Modus voor noodoproepen"</string>
     <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Status van mobiele data"</string>
     <string name="notification_channel_sms" msgid="3441746047346135073">"Sms\'jes"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Vliegtuigmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Vliegtuigmodus is AAN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Vliegtuigmodus is UIT"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Batterijbesparing"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Batterijbesparing is UIT"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Batterijbesparing is AAN"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Instellingen"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Helpen"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Spraakassistent"</string>
@@ -298,11 +295,17 @@
     <string name="permgroupdesc_calllog" msgid="3006237336748283775">"gesprekkenlijst lezen en schrijven"</string>
     <string name="permgrouprequest_calllog" msgid="8487355309583773267">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot je gesprekkenlijsten?"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Telefoon"</string>
-    <string name="permgroupdesc_phone" msgid="6234224354060641055">"telefoneren en oproepen beheren"</string>
+    <string name="permgroupdesc_phone" msgid="6234224354060641055">"telefoneren en gesprekken beheren"</string>
     <string name="permgrouprequest_phone" msgid="9166979577750581037">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toestaan om telefoongesprekken te starten en te beheren?"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Lichaamssensoren"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"toegang krijgen tot sensorgegevens over je vitale functies"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot sensorgegevens over je vitale functies?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muziek"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"toegang tot je muziek"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot je muziek?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Foto\'s en video\'s"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"toegang tot je foto\'s en video\'s"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Wil je &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot je foto\'s en video\'s?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Content van vensters ophalen"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"De content inspecteren van een venster waarmee je interactie hebt."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"\'Verkennen via aanraking\' inschakelen"</string>
@@ -325,8 +328,8 @@
     <string name="permdesc_install_shortcut" msgid="8341295916286736996">"Een app toestaan snelkoppelingen aan het startscherm toe te voegen zonder tussenkomst van de gebruiker."</string>
     <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"snelkoppelingen verwijderen"</string>
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"De app toestaan snelkoppelingen van het startscherm te verwijderen zonder tussenkomst van de gebruiker."</string>
-    <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"uitgaande oproepen doorschakelen"</string>
-    <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"De app toestaan het nummer te bekijken dat wordt gekozen voor een uitgaande oproep, met de mogelijkheid de oproep om te leiden naar een ander nummer of de oproep helemaal af te breken."</string>
+    <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"uitgaande gesprekken doorschakelen"</string>
+    <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"De app toestaan het nummer te bekijken dat wordt gekozen voor een uitgaand gesprek, met de mogelijkheid het gesprek om te leiden naar een ander nummer of het gesprek helemaal af te breken."</string>
     <string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"telefoonoproepen beantwoorden"</string>
     <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"Hiermee kan de app een inkomende telefoonoproep beantwoorden."</string>
     <string name="permlab_receiveSms" msgid="8673471768947895082">"tekstberichten (SMS) ontvangen"</string>
@@ -388,11 +391,11 @@
     <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je tv, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke contacten. Met deze toestemming kunnen apps contactgegevens verwijderen."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Hiermee kan de app gegevens wijzigen over de contacten die zijn opgeslagen op je telefoon, inclusief de frequentie waarmee je hebt gebeld, gemaild of op andere manieren hebt gecommuniceerd met specifieke contacten. Met deze toestemming kunnen apps contactgegevens verwijderen."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"gesprekkenlijst lezen"</string>
-    <string name="permdesc_readCallLog" msgid="3204122446463552146">"Deze app kan je oproepgeschiedenis lezen."</string>
+    <string name="permdesc_readCallLog" msgid="3204122446463552146">"Deze app kan je gespreksgeschiedenis lezen."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"gesprekkenlijst schrijven"</string>
-    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Toestaan dat de app het gesprekkenlijst van je tablet aanpast, waaronder gegevens over inkomende en uitgaande oproepen. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen."</string>
-    <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Toestaan dat de app het gesprekkenlijst van je tv aanpast, waaronder gegevens over inkomende en uitgaande oproepen. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen."</string>
-    <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Toestaan dat de app het gesprekkenlijst van je telefoon aanpast, waaronder gegevens over inkomende en uitgaande oproepen. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen."</string>
+    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Toestaan dat de app de gesprekkenlijst van je tablet aanpast, waaronder gegevens over inkomende en uitgaande gesprekken. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen."</string>
+    <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Toestaan dat de app de gesprekkenlijst van je tv aanpast, waaronder gegevens over inkomende en uitgaande gesprekken. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen."</string>
+    <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Toestaan dat de app de gesprekkenlijst van je telefoon aanpast, waaronder gegevens over inkomende en uitgaande gesprekken. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen."</string>
     <string name="permlab_bodySensors" msgid="4683341291818520277">"toegang tot lichaamssensoren (zoals hartslagmeters)"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Hiermee kan de app toegang krijgen tot gegevens van sensoren die je lichamelijke conditie controleren, zoals je hartslag."</string>
     <string name="permlab_readCalendar" msgid="6716116972752441641">"Agenda-afspraken en -gegevens lezen"</string>
@@ -424,13 +427,13 @@
     <string name="permlab_vibrate" msgid="7696427026057705834">"trilling beheren"</string>
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Hiermee kan de app de trilstand beheren."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"telefoonnummers rechtstreeks bellen"</string>
-    <string name="permdesc_callPhone" msgid="3740797576113760827">"Hiermee kan de app zonder je tussenkomst telefoonnummers bellen. Dit kan tot onverwachte kosten of oproepen leiden. De app kan hiermee geen noodnummers bellen. Schadelijke apps kunnen u geld kosten door nummers te bellen zonder om je bevestiging te vragen."</string>
+    <string name="permdesc_callPhone" msgid="3740797576113760827">"Hiermee kan de app zonder je tussenkomst telefoonnummers bellen. Dit kan tot onverwachte kosten of gesprekken leiden. De app kan hiermee geen noodnummers bellen. Schadelijke apps kunnen u geld kosten door nummers te bellen zonder om je bevestiging te vragen."</string>
     <string name="permlab_accessImsCallService" msgid="3574943847181793918">"toegang tot IMS-service voor bellen"</string>
     <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Hiermee kan de app de IMS-service gebruiken om te bellen zonder je tussenkomst."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"telefoonstatus en -identiteit lezen"</string>
-    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Hiermee kan de app toegang krijgen tot de telefoonfuncties van het apparaat, Met deze toestemming kan de app het telefoonnummer en de apparaat-ID\'s bepalen, of een oproep actief is, en het andere telefoonnummer waarmee wordt gebeld."</string>
-    <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"oproepen doorschakelen via het systeem"</string>
-    <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Hiermee kan de app de bijbehorende oproepen doorschakelen via het systeem om de belfunctionaliteit te verbeteren."</string>
+    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Hiermee kan de app toegang krijgen tot de telefoonfuncties van het apparaat, Met deze toestemming kan de app het telefoonnummer en de apparaat-ID\'s bepalen, of een gesprek actief is, en het andere telefoonnummer waarmee wordt gebeld."</string>
+    <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"gesprekken doorschakelen via het systeem"</string>
+    <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Hiermee kan de app de bijbehorende gesprekken doorschakelen via het systeem om de belfunctionaliteit te verbeteren."</string>
     <string name="permlab_acceptHandover" msgid="2661534649736022409">"een gesprek voortzetten vanuit een andere app"</string>
     <string name="permdesc_acceptHandovers" msgid="4570660484220539698">"Hiermee kan de app een gesprek voortzetten dat is gestart in een andere app."</string>
     <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"telefoonnummers lezen"</string>
@@ -490,13 +493,27 @@
     <string name="permlab_nfc" msgid="4423351274757876953">"Near Field Communication regelen"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Hiermee kan de app communiceren met NFC-tags (Near Field Communication), kaarten en lezers."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"je schermvergrendeling uitschakelen"</string>
-    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Hiermee kan de app de toetsenblokkering en bijbehorende wachtwoordbeveiliging uitschakelen. Zo kan de telefoon de toetsenblokkering uitschakelen wanneer er een oproep binnenkomt en de toetsenblokkering weer inschakelen als de oproep is beëindigd."</string>
+    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Hiermee kan de app de toetsenblokkering en bijbehorende wachtwoordbeveiliging uitschakelen. Zo kan de telefoon de toetsenblokkering uitschakelen wanneer je wordt gebeld en de toetsenblokkering weer inschakelen als het gesprek is beëindigd."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"biometrische hardware gebruiken"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Hiermee kan de app biometrische hardware gebruiken voor verificatie"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"Vingerafdrukhardware beheren"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Hiermee kan de app methoden aanroepen om vingerafdruksjablonen toe te voegen en te verwijderen voor gebruik."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Vingerafdrukhardware gebruiken"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Hiermee kan de app vingerafdrukhardware gebruiken voor verificatie"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"je muziekcollectie bekijken"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Hiermee sta je de app toe je muziekcollectie te bekijken."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"je muziekcollectie aanpassen"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Hiermee sta je de app toe je muziekcollectie aan te passen."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"je videocollectie bekijken"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Hiermee sta je de app toe je videocollectie te bekijken."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"je videocollectie aanpassen"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Hiermee sta je de app toe je videocollectie aan te passen."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"je fotocollectie bekijken"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Hiermee sta je de app toe je fotocollectie te bekijken."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"je fotocollectie aanpassen"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Hiermee sta je de app toe je fotocollectie aan te passen."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"locaties van je mediacollecties bekijken"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Hiermee sta je de app toe locaties van je mediacollectie te bekijken."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Gedeeltelijke vingerafdruk gedetecteerd. Probeer het opnieuw."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kan vingerafdruk niet verwerken. Probeer het opnieuw."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"De vingerafdruksensor moet worden schoongemaakt. Probeer het daarna opnieuw."</string>
@@ -565,18 +582,18 @@
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"de content van je SD-kaart aanpassen of verwijderen"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Hiermee kan de app schrijven naar de USB-opslag."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Hiermee kan de app schrijven naar de SD-kaart."</string>
-    <string name="permlab_use_sip" msgid="2052499390128979920">"SIP-oproepen plaatsen/ontvangen"</string>
-    <string name="permdesc_use_sip" msgid="2297804849860225257">"Toestaan dat de app SIP-oproepen plaatst en ontvangt."</string>
+    <string name="permlab_use_sip" msgid="2052499390128979920">"Bellen of gebeld worden via SIP"</string>
+    <string name="permdesc_use_sip" msgid="2297804849860225257">"Toestaan dat de app belt en gebeld wordt via SIP"</string>
     <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"nieuwe telecom-sim-verbindingen registreren"</string>
     <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"Hiermee kan de app nieuwe telecom-sim-verbindingen registreren."</string>
     <string name="permlab_register_call_provider" msgid="108102120289029841">"nieuwe telecomverbindingen registreren"</string>
     <string name="permdesc_register_call_provider" msgid="7034310263521081388">"Hiermee kan de app nieuwe telecomverbindingen registreren."</string>
     <string name="permlab_connection_manager" msgid="1116193254522105375">"telecomverbindingen beheren"</string>
     <string name="permdesc_connection_manager" msgid="5925480810356483565">"Hiermee kan de app telecomverbindingen beheren."</string>
-    <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactie met scherm in actieve oproep"</string>
-    <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Hiermee kan de app bepalen wanneer en hoe de gebruiker het scherm in een actieve oproep te zien krijgt."</string>
+    <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactie met scherm in actief gesprek"</string>
+    <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Hiermee kan de app bepalen wanneer en hoe de gebruiker het scherm in een actief gesprek te zien krijgt."</string>
     <string name="permlab_bind_connection_service" msgid="3557341439297014940">"communicatie met telefonische diensten"</string>
-    <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Hiermee kan de app met telefonische diensten communiceren om oproepen te plaatsen/ontvangen."</string>
+    <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Hiermee kan de app met telefonische diensten communiceren zodat je kunt bellen of gebeld worden."</string>
     <string name="permlab_control_incall_experience" msgid="9061024437607777619">"een gebruikerservaring bieden tijdens een gesprek"</string>
     <string name="permdesc_control_incall_experience" msgid="915159066039828124">"Hiermee kan de app een gebruikerservaring bieden tijdens een gesprek."</string>
     <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"historisch netwerkgebruik lezen"</string>
@@ -621,13 +638,13 @@
     <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de tv vergrendelen of alle gegevens van deze gebruiker wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de telefoon vergrendelen of alle gegevens van deze gebruiker wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string>
     <string name="policylab_resetPassword" msgid="4934707632423915395">"De schermvergrendeling wijzigen"</string>
-    <string name="policydesc_resetPassword" msgid="1278323891710619128">"De schermvergrendeling wijzigen."</string>
+    <string name="policydesc_resetPassword" msgid="1278323891710619128">"Wijzig de schermvergrendeling."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Het scherm vergrendelen"</string>
-    <string name="policydesc_forceLock" msgid="1141797588403827138">"Beheren hoe en wanneer het scherm wordt vergrendeld."</string>
+    <string name="policydesc_forceLock" msgid="1141797588403827138">"Beheer hoe en wanneer het scherm wordt vergrendeld."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Alle gegevens wissen"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"De gegevens van de tablet zonder waarschuwing wissen door de fabrieksinstellingen te herstellen."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"De gegevens van de tv zonder waarschuwing wissen door de fabrieksinstellingen te herstellen."</string>
-    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"De gegevens van de telefoon zonder waarschuwing wissen door de fabrieksinstellingen te herstellen."</string>
+    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Wis de gegevens van de telefoon zonder waarschuwing door de fabrieksinstellingen te herstellen."</string>
     <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Gebruikersgegevens wissen"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"De gegevens van deze gebruiker op deze tablet zonder waarschuwing wissen."</string>
     <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"De gegevens van deze gebruiker op deze tv zonder waarschuwing wissen."</string>
@@ -641,7 +658,7 @@
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Camera\'s uitschakelen"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Het gebruik van alle apparaatcamera\'s voorkomen."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Bepaalde functies voor schermvergrendeling uitschakelen"</string>
-    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Gebruik van bepaalde functies voor schermvergrendeling voorkomen."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Voorkom het gebruik van bepaalde functies voor schermvergrendeling."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Thuis"</item>
     <item msgid="869923650527136615">"Mobiel"</item>
@@ -1167,9 +1184,9 @@
     <string name="volume_music" msgid="5421651157138628171">"Mediavolume"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Afspelen via Bluetooth"</string>
     <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Stille beltoon ingesteld"</string>
-    <string name="volume_call" msgid="3941680041282788711">"Volume inkomende oproep"</string>
+    <string name="volume_call" msgid="3941680041282788711">"Volume inkomend gesprek"</string>
     <string name="volume_bluetooth_call" msgid="2002891926351151534">"Volume tijdens gesprek in Bluetooth-modus"</string>
-    <string name="volume_alarm" msgid="1985191616042689100">"Alarmvolume"</string>
+    <string name="volume_alarm" msgid="1985191616042689100">"Wekkervolume"</string>
     <string name="volume_notification" msgid="2422265656744276715">"Meldingsvolume"</string>
     <string name="volume_unknown" msgid="1400219669770445902">"Volume"</string>
     <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"Bluetooth-volume"</string>
@@ -1516,7 +1533,7 @@
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Delen met"</string>
     <string name="sending" msgid="3245653681008218030">"Verzenden..."</string>
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Browser starten?"</string>
-    <string name="SetupCallDefault" msgid="5834948469253758575">"Oproep accepteren?"</string>
+    <string name="SetupCallDefault" msgid="5834948469253758575">"Gesprek accepteren?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Altijd"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Één keer"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ondersteunt werkprofielen niet"</string>
@@ -1784,11 +1801,11 @@
     <string name="muted_by" msgid="5942954724562097128">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> dempt sommige geluiden"</string>
     <string name="system_error_wipe_data" msgid="6608165524785354962">"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="8086872414744210668">"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="5214333646366591205">"USSD-verzoek gewijzigd in normale oproep"</string>
+    <string name="stk_cc_ussd_to_dial" msgid="5214333646366591205">"USSD-verzoek gewijzigd in normaal gesprek"</string>
     <string name="stk_cc_ussd_to_ss" msgid="4884994189414782605">"USSD-verzoek gewijzigd in SS-verzoek"</string>
     <string name="stk_cc_ussd_to_ussd" msgid="5728637484565449312">"Gewijzigd in nieuw USSD-verzoek"</string>
     <string name="stk_cc_ussd_to_dial_video" msgid="4134455726513175559">"USSD-verzoek gewijzigd in videogesprek"</string>
-    <string name="stk_cc_ss_to_dial" msgid="1360775164651754978">"SS-verzoek gewijzigd in normale oproep"</string>
+    <string name="stk_cc_ss_to_dial" msgid="1360775164651754978">"SS-verzoek gewijzigd in normaal gesprek"</string>
     <string name="stk_cc_ss_to_dial_video" msgid="6577956662913194947">"SS-verzoek gewijzigd in videogesprek"</string>
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-verzoek gewijzigd in USSD-verzoek"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Gewijzigd in nieuw SS-verzoek"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> opslaan in &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> opslaan in &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> opslaan in &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Updaten naar &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> updaten naar &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> updaten naar &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> updaten naar &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Opslaan"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nee, bedankt"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Updaten"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"Wachtwoord"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"Adres"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Creditcard"</string>
@@ -1908,8 +1930,8 @@
     <string name="harmful_app_warning_title" msgid="8982527462829423432">"Schadelijke app gevonden"</string>
     <string name="slices_permission_request" msgid="8484943441501672932">"<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="7867478911006447565">"Bewerken"</string>
-    <string name="volume_dialog_ringer_guidance_vibrate" msgid="8902050240801159042">"Trillen bij oproepen en meldingen"</string>
-    <string name="volume_dialog_ringer_guidance_silent" msgid="2128975224280276122">"Oproepen en meldingen zijn gedempt"</string>
+    <string name="volume_dialog_ringer_guidance_vibrate" msgid="8902050240801159042">"Trillen bij gesprekken en meldingen"</string>
+    <string name="volume_dialog_ringer_guidance_silent" msgid="2128975224280276122">"Gesprekken en meldingen zijn gedempt"</string>
     <string name="notification_channel_system_changes" msgid="5072715579030948646">"Systeemwijzigingen"</string>
     <string name="notification_channel_do_not_disturb" msgid="6766940333105743037">"Niet storen"</string>
     <string name="zen_upgrade_notification_visd_title" msgid="3288313883409759733">"Nieuw: \'Niet storen\' verbergt meldingen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index bf26de0..b3a2c81 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍ ଅନ୍ ଅଛି"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍ ଅଫ୍ ଅଛି"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"ବ୍ୟାଟେରୀ ସେଭର୍"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ବ୍ୟାଟେରୀ ସେଭର୍‌ ଅଫ୍ ଅଛି"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"ବ୍ୟାଟେରୀ ସେଭର୍‌ ଅନ୍‌ ଅଛି"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ସେଟିଙ୍ଗ"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"ସହାୟକ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ଭଏସ୍‌ ସହାୟକ"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ବଡୀ ସେନ୍ସର୍"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ଆପଣଙ୍କ ଗୁରୁତପୂର୍ଣ୍ଣ ସଂକେତଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର୍‍ ଡାଟା ଆକ୍ସେସ୍‍ କରେ"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଆପଣଙ୍କ ଗୁରୁତ୍ୱପୂର୍ଣ୍ଣ ଲକ୍ଷଣଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର୍‍ ଡାଟା ଆକ୍ସେସ୍‍ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"ସଙ୍ଗୀତ"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"ଆପଣଙ୍କ ସଙ୍ଗୀତ ଆକ୍ସେସ୍‍ କରନ୍ତୁ"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"ଆପଣଙ୍କ ସଙ୍ଗୀତକୁ ଆକ୍ସେସ୍‍ କରିବାକୁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ କି?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ଫଟୋ ଏବଂ ଭିଡିଓ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"ଆପଣଙ୍କ ଫଟୋ ଏବଂ ଭିଡିଓ ଆକ୍ସେସ୍‍ କରନ୍ତୁ"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"ଆପଣଙ୍କ ଫଟୋ ଏବଂ ଭିଡିଓକୁ Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ଆକ୍ସେସ୍‍ କରିବାକୁ ଅନୁମତି ଦେବେ କି?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ୱିଣ୍ଡୋ କଣ୍ଟେଣ୍ଟ ହାସଲ କରନ୍ତୁ"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"ଆପଣ କାମ କରୁଥିବା ୱିଣ୍ଡୋର କଣ୍ଟେଣ୍ଟକୁ ଯାଞ୍ଚ କରନ୍ତୁ।"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ସ୍ପର୍ଶ ଦ୍ୱାରା ଏକ୍ସପ୍ଲୋର୍‍ ଅନ୍‍ କରନ୍ତୁ"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ବ୍ୟବହାର କରିବା ପାଇଁ ଆଙ୍ଗୁଠି ଚିହ୍ନ ଯୋଡ଼ିବାକୁ ଓ ଡିଲିଟ୍‍ କରିବାକୁ ଆପକୁ ବିଧି ଆରମ୍ଭ କରିବାକୁ ଦେଇଥାଏ।"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ସ୍ୱୀକୃତି ପାଇଁ ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ଆପଣଙ୍କ ସଙ୍ଗୀତ ସଂଗ୍ରହ ପଢନ୍ତୁ"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"ଆପଣଙ୍କ ସଂଗୃହିତ ସଙ୍ଗୀତ ପଢିବାକୁ ଆପ୍‍ ଅନୁମତି ଦେଇଥାଏ।"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"ଆପଣଙ୍କ ସଙ୍ଗୀତ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"ଆପଣ ଆପଣଙ୍କ ସଙ୍ଗୀତ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ଆପଣଙ୍କ ଭିଡିଓ ସଂଗ୍ରହ ପଢନ୍ତୁ"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"ଆପଣଙ୍କ ଭିଡିଓ ସଂଗ୍ରହ ପଢିବାକୁ ଆପ୍ଲିକେସନ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"ଆପଣଙ୍କ ଭିଡିଓ ସଂଗ୍ରହ ସଂଶୋଧନ କରନ୍ତୁ"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"ଆପଣଙ୍କ ଭିଡିଓ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ଆପଣଙ୍କ ଫଟୋ ସଂଗ୍ରହ ପଢନ୍ତୁ"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"ଆପଣଙ୍କ ଫଟୋ ସଂଗ୍ରହ ପଢିବାକୁ ଆପ୍‍ ଅନୁମତି ଦେଇଥାଏ।"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"ଆପଣଙ୍କ ଫଟୋ ସଂଗ୍ରହକୁ ସଂଶୋଧନ କରନ୍ତୁ"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ଆପଣଙ୍କ ଫଟୋ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍‍ ଅନୁମତି ଦେଇଥାଏ।"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ଆପଣଙ୍କ ମିଡିଆ ସଂଗ୍ରହ ଠାରୁ ଲୋକେସନ୍‍ଗୁଡିକୁ ପଢନ୍ତୁ"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ଆପଣଙ୍କ ମିଡିଆ ସଂଗ୍ରହ ଠାରୁ ଅବସ୍ଥାନଗୁଡିକୁ ପଢିବାକୁ ଆପ୍‍ ଅନୁମତି ଦେଇଥାଏ।"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଂଶିକ ଚିହ୍ନଟ ହେଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପ୍ରୋସେସ୍‍ କରାଯାଇପାରିଲା ନାହିଁ। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ସେନ୍ସର୍‍ ମଇଳା ହୋଇଯାଇଛି। ଦୟାକରି ସଫା କରନ୍ତୁ ଓ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
@@ -1876,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;ରେ ସେଭ୍‍ କରିବେ?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> ଏବଂ <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;ରେ ସେଭ୍‍ କରିବେ?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ଏବଂ <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;ରେ ସେଭ୍‍ କରିବେ?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;କୁ ଅପ୍‍ଡେଟ୍‍ କରିବେ?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;କୁ ଅପ୍‍ଡେଟ୍‍ କରିବେ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> ଏବଂ <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;କୁ ଅପ୍‍ଡେଟ୍‍ କରିବେ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ଏବଂ <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;କୁ ଅପ୍‍ଡେଟ୍‍ କରିବେ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ସେଭ୍‌ କରନ୍ତୁ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ନାଁ, ପଚାରିଥିବାରୁ ଧନ୍ୟବାଦ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"ଅପ୍‍ଡେଟ୍‌ କରନ୍ତୁ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"ପାସୱର୍ଡ୍"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ଠିକଣା"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"କ୍ରେଡିଟ୍ କାର୍ଡ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index dc170c8..d581e6b 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ਏਅਰਪਲੇਨ ਮੋਡ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ਏਅਰਪਲੇਨ ਮੋਡ ਚਾਲੂ ਹੈ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"ਏਅਰਪਲੇਨ ਮੋਡ ਬੰਦ ਹੈ"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"ਬੈਟਰੀ ਸੇਵਰ"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਹੈ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"ਸਹਾਇਤਾ ਕਰੋ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ਸਰੀਰ ਸੰਵੇਦਕ"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ਆਪਣੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਚਿੰਨ੍ਹਾਂ ਬਾਰੇ ਸੰਵੇਦਕ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਲੱਛਣਾਂ ਸੰਬੰਧੀ ਸੈਂਸਰ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"ਸੰਗੀਤ"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"ਤੁਹਾਡੇ ਸੰਗੀਤ ਤੱਕ ਪਹੁੰਚ"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਸੰਗੀਤ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"ਤੁਹਾਡੀਆਂ ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਤੱਕ ਪਹੁੰਚ"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਤੁਹਾਡੀਆਂ ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ਵਿੰਡੋ ਸਮੱਗਰੀ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰਨਾ"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"ਇੱਕ ਵਿੰਡੋ ਦੀ ਸਮੱਗਰੀ ਦੀ ਜਾਂਚ ਕਰੋ, ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਅੰਤਰਕਿਰਿਆ ਕਰ ਰਹੇ ਹੋ"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"\'ਸਪੱਰਸ਼ ਰਾਹੀਂ ਪੜਚੋਲ ਕਰੋ\' ਚਾਲੂ ਕਰਨਾ"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ਐਪ ਨੂੰ ਵਰਤੋਂ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸ਼ਾਮਲ ਕਰਨ ਅਤੇ ਮਿਟਾਉਣ ਦੀਆਂ ਵਿਧੀਆਂ ਦੀ ਬੇਨਤੀ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਵਰਤੋ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ਐਪ ਨੂੰ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ਤੁਹਾਡੇ ਸੰਗੀਤ ਸੰਗ੍ਰਹਿ ਨੂੰ ਪੜ੍ਹਨਾ"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਸੰਗੀਤ ਸੰਗ੍ਰਹਿ ਨੂੰ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"ਤੁਹਾਡੇ ਸੰਗੀਤ ਸੰਗ੍ਰਹਿ ਨੂੰ ਸੋਧਣਾ"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਸੰਗੀਤ ਸੰਗ੍ਰਹਿ ਨੂੰ ਸੋਧਣ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ਤੁਹਾਡੇ ਵੀਡੀਓ ਸੰਗ੍ਰਹਿ ਨੂੰ ਪੜ੍ਹਨਾ"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਵੀਡੀਓ ਸੰਗ੍ਰਹਿ ਨੂੰ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"ਤੁਹਾਡੇ ਵੀਡੀਓ ਸੰਗ੍ਰਹਿ ਨੂੰ ਸੋਧਣਾ"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਵੀਡੀਓ ਸੰਗ੍ਰਹਿ ਨੂੰ ਸੋਧਣ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ਤੁਹਾਡੇ ਫ਼ੋਟੋ ਸੰਗ੍ਰਹਿ ਨੂੰ ਪੜ੍ਹਨਾ"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਟੋ ਸੰਗ੍ਰਹਿ ਨੂੰ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"ਤੁਹਾਡੇ ਫ਼ੋਟੋ ਸੰਗ੍ਰਹਿ ਨੂੰ ਸੋਧਣਾ"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਟੋ ਸੰਗ੍ਰਹਿ ਨੂੰ ਸੋਧਣ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ਤੁਹਾਡੇ ਮੀਡੀਆ ਸੰਗ੍ਰਹਿ ਦੇ ਟਿਕਾਣਿਆਂ ਨੂੰ ਪੜ੍ਹਨਾ"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਮੀਡੀਆ ਸੰਗ੍ਰਹਿ ਦੇ ਟਿਕਾਣਿਆਂ ਨੂੰ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ।"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ਅਧੂਰਾ ਫਿੰਗਰਪ੍ਰਿਟ ਮਿਲਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪ੍ਰਕਿਰਿਆ ਨਹੀਂ ਕਰ ਸਕਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੰਵੇਦਕ ਗੰਦਾ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇਸਨੂੰ ਸਾਫ਼ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਤੀਕ"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਰਨ ਹਾਰਡਵੇਅਰ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"ਐਪ ਨੂੰ ਵਰਤਣ ਲਈ ਚਿਹਰਾ ਟੈਮਪਲੇਟ ਸ਼ਾਮਲ ਕਰਨ ਜਾਂ ਮਿਟਾਉਣ ਦੀਆਂ ਵਿਧੀਆਂ ਦੀ ਬੇਨਤੀ ਕਰਨ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਰਨ ਹਾਰਡਵੇਅਰ ਵਰਤੋ"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"ਐਪ ਨੂੰ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਰਨ ਹਾਰਡਵੇਅਰ ਵਰਤਣ ਦਿੰਦੀ ਹੈ"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"ਚਿਹਰਾ ਬਹੁਤ ਚਮਕਦਾਰ ਹੈ। ਘੱਟ ਰੋਸ਼ਨੀ ਵਿੱਚ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"ਚਿਹਰਾ ਹਨੇਰੇ ਵਿੱਚ ਹੈ। ਚਾਨਣ ਕਰੋ।"</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"ਚਿਹਰੇ ਨੂੰ ਸੈਂਸਰ ਤੋਂ ਦੂਰ ਲਿਜਾਓ।"</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"ਚਿਹਰੇ ਨੂੰ ਸੈਂਸਰ ਦੇ ਨੇੜੇ ਲਿਆਓ।"</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"ਸੈਂਸਰ ਨੂੰ ਉੱਪਰ ਕਰੋ।"</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"ਸੈਂਸਰ ਨੂੰ ਥੱਲੇ ਕਰੋ।"</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"ਸੈਂਸਰ ਨੂੰ ਸੱਜੇ ਪਾਸੇ ਲਿਜਾਓ।"</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"ਸੈਂਸਰ ਨੂੰ ਖੱਬੇ ਪਾਸੇ ਲਿਜਾਓ।"</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"ਕਿਰਪਾ ਕਰਕੇ ਸੈਂਸਰ ਵੱਲ ਦੇਖੋ।"</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"ਕੋਈ ਚਿਹਰਾ ਨਹੀਂ ਦਿਸਿਆ।"</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"ਚਿਹਰੇ ਨੂੰ ਡੀਵਾਈਸ ਦੇ ਸਾਹਮਣੇ ਸਥਿਰ ਰੱਖੋ।"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"ਚਿਹਰਾ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"ਚਿਹਰਾ ਪਛਾਣਨ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋਇਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"ਚਿਹਰੇ ਦੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"ਚਿਹਰਾ ਪਛਾਣਨ ਦੀ ਪ੍ਰਕਿਰਿਆ ਰੱਦ ਕੀਤੀ ਗਈ।"</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਰਨ ਬੰਦ ਹੈ।"</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"ਕੋਈ ਚਿਹਰਾ ਜਾਣਕਾਰੀ ਦਰਜ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"ਇਸ ਡੀਵਾਈਸ ਵਿੱਚ ਕੋਈ ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਰਨ ਸੈਂਸਰ ਨਹੀਂ ਹੈ"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"ਚਿਹਰਾ <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"ਚਿਹਰਾ ਪ੍ਰਤੀਕ"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਹ ਪਤਾ ਕਰ ਸਕਦਾ ਹੈ ਕਿ People ਐਪ ਦਾ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਗਿਆ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ਸਮਕਾਲੀਕਰਨ ਚਾਲੂ ਅਤੇ ਬੰਦ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"ਵਾਈ-ਫਾਈ ਦੀ ਕੋਈ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"ਤੁਹਾਡੀਆਂ ਹੌਟਸਪੌਟ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਬਦਲਾਅ"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"ਤੁਹਾਡਾ ਹੌਟਸਪੌਟ ਬੈਂਡ ਬਦਲ ਗਿਆ ਹੈ।"</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"ਇਹ ਡੀਵਾਈਸ ਸਿਰਫ਼ 5GHz ਦੀ ਤੁਹਾਡੀ ਤਰਜੀਹ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਇਸਦੀ ਬਜਾਏ, ਇਹ ਡੀਵਾਈਸ ਉਪਲਬਧ ਹੋਣ \'ਤੇ 5GHz ਬੈਂਡ ਵਰਤੇਗਾ।"</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"ਬਦਲਕੇ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ਲਿਆਂਦਾ ਗਿਆ"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।"</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ਤੋਂ ਬਦਲਕੇ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> \'ਤੇ ਕੀਤਾ ਗਿਆ"</string>
@@ -1906,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"ਕੀ <xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ਅਤੇ <xliff:g id="TYPE_2">%3$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"ਕੀ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"ਕੀ <xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_2">%3$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ਰੱਖਿਅਤ ਕਰੋ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"ਅੱਪਡੇਟ ਕਰੋ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"ਪਾਸਵਰਡ"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ਪਤਾ"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ਕ੍ਰੈਡਿਟ ਕਾਰਡ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 4b0db4a..6f56e7f 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -136,7 +136,7 @@
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Wył."</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferuj Wi-Fi"</string>
-    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferowane mobilne"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferowane komórkowe"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Tylko Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nieprzekierowane"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -242,9 +242,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Tryb samolotowy"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Tryb samolotowy jest włączony"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Tryb samolotowy jest wyłączony"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Oszczędzanie baterii"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Oszczędzanie baterii WYŁ."</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Oszczędzanie baterii WŁ."</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Ustawienia"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Pomoc"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asystent głosowy"</string>
@@ -309,6 +306,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Czujniki na ciele"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"dostęp do danych czujnika podstawowych funkcji życiowych"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do danych z czujnika podstawowych funkcji życiowych?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muzyka"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"dostęp do muzyki"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do muzyki?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Zdjęcia i filmy"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"dostęp do zdjęć i filmów"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do zdjęć i filmów?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Pobieranie zawartości okna"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Sprawdzanie zawartości okna, z którego korzystasz."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Włączenie czytania dotykiem"</string>
@@ -503,6 +506,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Zezwala aplikacji aktywować metody dodawania i usuwania szablonów odcisków palców."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"używanie czytnika linii papilarnych"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Zezwala aplikacji na używanie czytnika linii papilarnych na potrzeby autoryzacji"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"odczytywanie kolekcji muzyki"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Zezwala aplikacji na odczytywanie kolekcji muzyki."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modyfikowanie kolekcji muzyki"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Zezwala aplikacji na modyfikowanie kolekcji muzyki."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"odczytywanie kolekcji filmów"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Zezwala aplikacji na odczytywanie kolekcji filmów."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modyfikowanie kolekcji filmów"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Zezwala aplikacji na modyfikowanie kolekcji filmów."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"odczytywanie kolekcji zdjęć"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Zezwala aplikacji na odczytywanie kolekcji zdjęć."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modyfikowanie kolekcji zdjęć"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Zezwala aplikacji na modyfikowanie kolekcji zdjęć."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"odczytywanie lokalizacji z kolekcji multimediów"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Zezwala aplikacji na odczytywanie lokalizacji z kolekcji multimediów."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Odcisk palca został odczytany tylko częściowo. Spróbuj ponownie."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nie udało się przetworzyć odcisku palca. Spróbuj ponownie."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Czytnik linii papilarnych jest zabrudzony. Wyczyść go i spróbuj ponownie."</string>
@@ -646,7 +663,7 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Wymaganie szyfrowania przechowywanych danych aplikacji"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Wyłącz aparaty"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Zapobieganie używaniu wszystkich aparatów w urządzeniu"</string>
-    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Wył. niektórych funkcji bl. ekr."</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Wył. funkcji blokady ekranu"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Zapobieganie użyciu niektórych funkcji blokady ekranu."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Dom"</item>
@@ -1945,8 +1962,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> – zapisać w: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> – zapisać w: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> – zapisać w: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Zaktualizować do &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Zaktualizować <xliff:g id="TYPE">%1$s</xliff:g> do &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Zaktualizować <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> do &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Zaktualizować <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, i <xliff:g id="TYPE_2">%3$s</xliff:g> do &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Zapisz"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nie, dziękuję"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Zaktualizuj"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"hasło"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adres"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"karta kredytowa"</string>
diff --git a/core/res/res/values-port/dimens_permission_controller.xml b/core/res/res/values-port/dimens_permission_controller.xml
new file mode 100644
index 0000000..af28713
--- /dev/null
+++ b/core/res/res/values-port/dimens_permission_controller.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<!-- portrait dimensions for the permission grant dialog. -->
+<resources>
+    <!-- This yields 95% width -->
+    <dimen name="permissionGrantDialogWeight">380</dimen>
+    <dimen name="permissionGrantDialogWidth">0dp</dimen>
+</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 16ce8c3..ad68dde 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -33,7 +33,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Correio de voz"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problema de conexão ou código MMI inválido."</string>
-    <string name="mmiFdnError" msgid="5224398216385316471">"A operação é limitada somente a números de chamadas fixas."</string>
+    <string name="mmiFdnError" msgid="5224398216385316471">"A operação é limitada somente a números de discagem fixa."</string>
     <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"Não é possível alterar as configurações de encaminhamento de chamada do seu smartphone em roaming."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"O serviço foi ativado."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"O serviço foi ativado para:"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avião"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo avião ATIVADO"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo avião DESATIVADO"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Economia de bateria"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"A Economia de bateria está DESATIVADA"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"A Economia de bateria está ATIVADA"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Configurações"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assistência"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ajuda de voz"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores corporais"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"acesse dados do sensor sobre seus sinais vitais"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse os dados do sensor sobre seus sinais vitais?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Músicas"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"acessar suas músicas"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse suas músicas?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotos e vídeos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"acessar suas fotos e seus vídeos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse suas fotos e seus vídeos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Acessar conteúdo de uma janela"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspeciona o conteúdo de uma janela com a qual você está interagindo."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Ativar Explorar por toque"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que o app execute métodos para adicionar e excluir modelos de impressão digital para uso."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"usar hardware de impressão digital"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que o app use hardware de impressão digital para autenticação."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ler sua coleção de músicas"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Permite que o app leia sua coleção de músicas."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modificar sua coleção de músicas"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permite que o app modifique sua coleção de músicas."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ler sua coleção de vídeos"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Permite que o app leia sua coleção de vídeos."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modificar sua coleção de vídeos"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Permite que o app modifique sua coleção de vídeos."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ler sua coleção de fotos"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Permite que o app leia sua coleção de fotos."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modificar sua coleção de fotos"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que o app modifique sua coleção de fotos."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ler locais na sua coleção de mídias"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que o app leia os locais na sua coleção de mídias."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Impressão digital parcial detectada. Tente novamente."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Não foi possível processar a impressão digital. Tente novamente."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"O sensor de impressão digital está sujo. Limpe-o e tente novamente."</string>
@@ -1434,7 +1451,7 @@
     <string name="gpsVerifYes" msgid="2346566072867213563">"Sim"</string>
     <string name="gpsVerifNo" msgid="1146564937346454865">"Não"</string>
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"Limite de exclusão excedido"</string>
-    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Há <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> itens excluídos para <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, conta <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. O que você deseja fazer?"</string>
+    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Há <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> itens excluídos para <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, conta <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. O que você quer fazer?"</string>
     <string name="sync_really_delete" msgid="2572600103122596243">"Excluir os itens"</string>
     <string name="sync_undo_deletes" msgid="2941317360600338602">"Desfazer as exclusões"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"Não fazer nada por enquanto"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Atualizar no &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Atualizar <xliff:g id="TYPE">%1$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Atualizar"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"senha"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"endereço"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"cartão de crédito"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index b1c4b3b..631e9f3 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo de avião"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"O modo de voo está ativado"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"O modo de voo está desativado"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Poupança de bateria"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Poupança de bateria DeSATIVADA"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Poupança de bateria ATIVADA"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Definições"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assistência"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assist. de voz"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores de corpo"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"aceder a dados do sensor acerca dos seus sinais vitais"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Pretende permitir que a aplicação &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda aos dados do sensor acerca dos seus sinais vitais?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Música"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"aceder à sua música"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Pretende permitir que a aplicação &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda à sua música?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotos e vídeos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"aceder aos seus vídeos e fotos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Pretende permitir que a aplicação &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda às suas fotos e vídeos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Obter conteúdo da janela"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecionar o conteúdo de uma janela com a qual está a interagir."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Ativar Explorar Através do Toque"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que a aplicação invoque métodos para adicionar e eliminar modelos de impressão digital para utilização."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizar o hardware de impressão digital"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que a aplicação utilize o hardware de impressão digital para autenticação"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ler a sua coleção de música"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Permite que a aplicação leia a sua coleção de música."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modificar a sua coleção de música"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permite que a aplicação modifique a sua coleção de música."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ler a sua coleção de vídeos"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Permite que a aplicação leia a sua coleção de vídeos."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modificar a sua coleção de vídeos"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Permite que a aplicação modifique a sua coleção de vídeos."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ler a sua coleção de fotos"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Permite que a aplicação leia a sua coleção de fotos."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modificar a sua coleção de fotos"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que a aplicação modifique a sua coleção de fotos."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ler as localizações a partir da sua coleção de multimédia"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que a aplicação leia as localizações a partir da sua coleção de multimédia."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Impressão digital detetada. Tente novamente."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Não foi possível processar a impressão digital. Tente novamente."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"O sensor de impressões digitais está sujo. Limpe-o e tente novamente."</string>
@@ -621,13 +638,13 @@
     <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear a TV ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o telemóvel ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
     <string name="policylab_resetPassword" msgid="4934707632423915395">"Alterar o bloqueio de ecrã"</string>
-    <string name="policydesc_resetPassword" msgid="1278323891710619128">"Alterar o bloqueio de ecrã."</string>
+    <string name="policydesc_resetPassword" msgid="1278323891710619128">"Altera o bloqueio de ecrã."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Bloquear o ecrã"</string>
-    <string name="policydesc_forceLock" msgid="1141797588403827138">"Controlar como e quando ocorre o bloqueio do ecrã."</string>
+    <string name="policydesc_forceLock" msgid="1141797588403827138">"Controla como e quando ocorre o bloqueio do ecrã."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Apagar todos os dados"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Apagar os dados do tablet sem avisar através de uma reposição de dados de fábrica."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Apagar os dados da TV sem aviso prévio ao executar uma reposição de dados de fábrica."</string>
-    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Apagar os dados do telemóvel sem avisar através de uma reposição de dados de fábrica."</string>
+    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Apaga os dados do telemóvel sem avisar ao efetuar uma reposição de dados de fábrica."</string>
     <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Apagar os dados do utilizador"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"Apagar os dados deste utilizador neste tablet sem aviso."</string>
     <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"Apagar os dados deste utilizador nesta TV sem aviso."</string>
@@ -641,7 +658,7 @@
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Desativar câmaras"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Evitar a utilização de todas as câmaras do dispositivo."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Desat. funcionalid. bloq. ecrã"</string>
-    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Impeça a utilização de algumas funcionalidades de bloqueio de ecrã."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Impede a utilização de algumas funcionalidades de bloqueio de ecrã."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Móvel"</item>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Pretende guardar <xliff:g id="TYPE">%1$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Pretende atualizar para o &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Pretende atualizar <xliff:g id="TYPE">%1$s</xliff:g> para o &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Pretende atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> para o &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Pretende atualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> para o &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Atualizar"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"palavra-passe"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"endereço"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"cartão de crédito"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 16ce8c3..ad68dde 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -33,7 +33,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Correio de voz"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problema de conexão ou código MMI inválido."</string>
-    <string name="mmiFdnError" msgid="5224398216385316471">"A operação é limitada somente a números de chamadas fixas."</string>
+    <string name="mmiFdnError" msgid="5224398216385316471">"A operação é limitada somente a números de discagem fixa."</string>
     <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"Não é possível alterar as configurações de encaminhamento de chamada do seu smartphone em roaming."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"O serviço foi ativado."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"O serviço foi ativado para:"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avião"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo avião ATIVADO"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo avião DESATIVADO"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Economia de bateria"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"A Economia de bateria está DESATIVADA"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"A Economia de bateria está ATIVADA"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Configurações"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Assistência"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ajuda de voz"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores corporais"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"acesse dados do sensor sobre seus sinais vitais"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse os dados do sensor sobre seus sinais vitais?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Músicas"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"acessar suas músicas"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse suas músicas?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotos e vídeos"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"acessar suas fotos e seus vídeos"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse suas fotos e seus vídeos?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Acessar conteúdo de uma janela"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspeciona o conteúdo de uma janela com a qual você está interagindo."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Ativar Explorar por toque"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que o app execute métodos para adicionar e excluir modelos de impressão digital para uso."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"usar hardware de impressão digital"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que o app use hardware de impressão digital para autenticação."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ler sua coleção de músicas"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Permite que o app leia sua coleção de músicas."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modificar sua coleção de músicas"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permite que o app modifique sua coleção de músicas."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ler sua coleção de vídeos"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Permite que o app leia sua coleção de vídeos."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modificar sua coleção de vídeos"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Permite que o app modifique sua coleção de vídeos."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ler sua coleção de fotos"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Permite que o app leia sua coleção de fotos."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modificar sua coleção de fotos"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que o app modifique sua coleção de fotos."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ler locais na sua coleção de mídias"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que o app leia os locais na sua coleção de mídias."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Impressão digital parcial detectada. Tente novamente."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Não foi possível processar a impressão digital. Tente novamente."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"O sensor de impressão digital está sujo. Limpe-o e tente novamente."</string>
@@ -1434,7 +1451,7 @@
     <string name="gpsVerifYes" msgid="2346566072867213563">"Sim"</string>
     <string name="gpsVerifNo" msgid="1146564937346454865">"Não"</string>
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"Limite de exclusão excedido"</string>
-    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Há <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> itens excluídos para <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, conta <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. O que você deseja fazer?"</string>
+    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Há <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> itens excluídos para <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, conta <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. O que você quer fazer?"</string>
     <string name="sync_really_delete" msgid="2572600103122596243">"Excluir os itens"</string>
     <string name="sync_undo_deletes" msgid="2941317360600338602">"Desfazer as exclusões"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"Não fazer nada por enquanto"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Atualizar no &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Atualizar <xliff:g id="TYPE">%1$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Atualizar"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"senha"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"endereço"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"cartão de crédito"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 2554107..efd68ac 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -239,13 +239,10 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modul Avion este ACTIVAT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modul avion este DEZACTIVAT"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Economisirea energiei"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Economisirea bateriei este dezactivată"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Economisirea bateriei este activată"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Setări"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Asistență"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistent vocal"</string>
-    <string name="global_action_lockdown" msgid="1099326950891078929">"Blocați"</string>
+    <string name="global_action_lockdown" msgid="1099326950891078929">"Blocare strictă"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
     <string name="notification_hidden_text" msgid="6351207030447943784">"Notificare nouă"</string>
     <string name="notification_channel_virtual_keyboard" msgid="6969925135507955575">"Tastatură virtuală"</string>
@@ -306,6 +303,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Senzori corporali"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"acceseze datele de la senzori despre semnele vitale"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze datele de la senzori despre semnele dvs. vitale?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muzică"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"accesați muzica"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să vă acceseze muzica?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotografii și videoclipuri"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"accesați fotografiile și videoclipurile"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să vă acceseze fotografiile și videoclipurile?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Analizează conținutul ferestrei"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspectează conținutul unei ferestre cu care interacționați."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Activează funcția Explorați prin atingere"</string>
@@ -500,6 +503,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite aplicației să invoce metode pentru a adăuga și pentru a șterge șabloane de amprentă pentru utilizare."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"folosește hardware-ul pentru amprentă"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite aplicației să folosească hardware pentru amprentă pentru autentificare"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"citiți colecția de muzică"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Permite aplicației să vă citească colecția de muzică."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modificați colecția de muzică"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permite aplicației să vă modifice colecția de muzică."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"citiți colecția de videoclipuri"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Permite aplicației să vă citească colecția de videoclipuri."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modificați colecția de videoclipuri"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Permite aplicației să vă modifice colecția de videoclipuri."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"citiți colecția de fotografii"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Permite aplicației să vă citească colecția de fotografii."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modificați colecția de fotografii"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite aplicației să vă modifice colecția de fotografii."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"citiți locațiile din colecția media"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite aplicației să citească locațiile din colecția dvs. media."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S-a detectat parțial amprenta. Încercați din nou."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Amprenta nu a putut fi procesată. Încercați din nou."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Senzorul pentru amprente este murdar. Curățați-l și încercați din nou."</string>
@@ -1910,8 +1927,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Salvați <xliff:g id="TYPE">%1$s</xliff:g> în &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g> și <xliff:g id="TYPE_1">%2$s</xliff:g> în &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g> în &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Actualizați la &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Actualizați <xliff:g id="TYPE">%1$s</xliff:g> la &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Actualizați <xliff:g id="TYPE_0">%1$s</xliff:g> și <xliff:g id="TYPE_1">%2$s</xliff:g> la &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Actualizați <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g> la &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvați"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nu, mulțumesc"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Actualizați"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"parolă"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresă"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"card de credit"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a56e9d3..6cc870c 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -242,9 +242,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим полета"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Выключить"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Включить"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Режим энергосбережения"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Выключить"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Включить"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Настройки"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Помощник"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Аудиоподсказки"</string>
@@ -309,6 +306,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Нательные датчики"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"доступ к данным датчиков о состоянии организма"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Разрешить приложению &lt;b&gt;\"<xliff:g id="APP_NAME">%1$s</xliff:g>\"&lt;/b&gt; доступ к данным датчиков о состоянии организма?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Музыка"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"доступ к музыке"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к музыке?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Фото и видео"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"доступ к фото и видео"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к фото и видео?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Получать содержимое окна"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Анализировать содержимое активного окна."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Включать Изучение касанием"</string>
@@ -503,6 +506,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Приложение сможет добавлять и удалять шаблоны отпечатков пальцев."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Использование сканера отпечатков"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Приложение сможет использовать сканер отпечатков пальцев для аутентификации."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"доступ к музыкальной коллекции"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Приложение получит доступ к вашей музыкальной коллекции."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"изменение музыкальной коллекции"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Приложение сможет вносить изменения в вашу музыкальную коллекцию."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"доступ к видеоколлекции"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Приложение получит доступ к вашей видеоколлекции."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"изменение видеоколлекции"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Приложение сможет вносить изменения в вашу видеоколлекцию."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"доступ к фотоколлекции"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Приложение получит доступ к вашей фотоколлекции."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"изменение фотоколлекции"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Приложение сможет вносить изменения в вашу фотоколлекцию."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"доступ к геоданным в медиаколлекции"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Приложение получит доступ к геоданным в вашей медиаколлекции."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Отсканирована только часть пальца. Повторите попытку."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не удалось распознать отпечаток. Повторите попытку."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Очистите сканер и повторите попытку."</string>
@@ -1945,8 +1962,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Сохранить <xliff:g id="TYPE">%1$s</xliff:g> в &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Сохранить <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> в &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Сохранить <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> в &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Обновить данные в &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Обновить данные (<xliff:g id="TYPE">%1$s</xliff:g>) в &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Обновить данные (<xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g>) в &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Обновить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g>) в &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сохранить"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Нет, спасибо"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Обновить"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"Пароль"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"Адрес"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Банковская карта"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index ad1a64d..c263589 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"අහස්යානා ආකාරය"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"අහස්යානා ආකාරය සක්‍රීයයි."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"අහස්යානා අකාරය අක්‍රියයි"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"බැටරි සුරැකුම"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"බැටරි සුරැකුම ක්‍රියාවිරහිතයි"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"බැටරි සුරැකුම ක්‍රියාත්මකයි"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"සැකසීම්"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"සහාය දීම"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"හඬ සහායක"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ශරීර සංවේදක"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ඔබේ ජෛව ලක්ෂණ පිළිබඳ සංවේදක දත්ත වෙත පිවිසෙන්න"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත ඔබගේ ජෛව ලක්ෂණ පිළිබඳ සංවේදක දත්ත වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"සංගීතය"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"ඔබේ සංගීතයට පිවිසෙන්න"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට ඔබගේ දින දර්ශනය වෙත පිවිසීමට ඉඩ දෙන්නද?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ඡායාරූප සහ වීඩියෝ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"ඔබගේ ඡායාරූප සහ වීඩියෝ වෙත පිවිසෙන්න"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට ඔබගේ ඡායාරූප වෙත පිවිසීමට ඉඩ දෙන්නද?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"කවුළු අන්න්තර්ගතය ලබාගන්න"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"ඔබ අන්තර්ක්‍රියාකාරී වන කවුළුවේ අන්තර්ගතය පරීක්ෂා කරන්න."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ස්පර්ශයෙන් ගවේෂණය සක්‍රිය කරන්න"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ඇඟිලි සලකුණු සැකිලි එකතු කිරීමට සහ ඉවත් කිරීමට අදාළ විධික්‍රම භාවිතය සඳහා මෙම යෙදුමට අවසර දෙයි."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ඇඟිලි සලකුණු දෘඩාංග භාවිතා කරන්න."</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"අනන්‍යතාවය තහවුරු කරගැනීමට ඇඟිලි සලකුණු දෘඩාංග භාවිතා කිරීමට මෙම යෙදුමට ඉඩ දෙන්න."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"ඔබගේ සංගීත එකතුව කියවන්න"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"ඔබේ සංගීත එකතුව කියවීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"ඔබගේ සංගීත එකතුව වෙනස් කරන්න"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"ඔබගේ සංගීත එකතුව වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"ඔබේ වීඩියෝ එකතුව කියවන්න"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"ඔබගේ වීඩියෝ එකතුව කියවීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"ඔබේ වීඩියෝ එකතුව වෙනස් කරන්න"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"ඔබගේ වීඩියෝ එකතුව වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"ඔබේ ඡායාරූප එකතුව කියවන්න"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"ඔබගේ ඡායාරූප එකතුව කියවීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"ඔබේ ඡායාරූප එකතුව වෙනස් කරන්න"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ඔබගේ ඡායාරූප එකතුව වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"ඔබගේ මාධ්‍ය එකතුවෙන් ස්ථාන කියවන්න"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ඔබගේ මාධ්‍ය එකතුවෙන් ස්ථාන කියවීමට යෙදුමට ඉඩ දෙයි."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ඇඟිලි සලකුණ අඩ වශයෙන් අනාවරණය කර ගැනිණි. කරුණාකර නැවත උත්සාහ කරන්න."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ඇඟිලි සලකුණ පිරිසැකසීමට නොහැකි විය. කරුණාකර නැවත උත්සාහ කරන්න."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ඇඟිලි සලකුණු සංවේදකය අපිරිසිදුයි. කරුණාකර පිරිසිදු කර නැවත උත්සාහ කරන්න."</string>
@@ -542,7 +559,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"මුහුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"මුහුණ ගබඩා කළ නොහැක."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"මුහුණු මෙහෙයුම අවලංගු කරන ලදී."</string>
-    <string name="face_error_lockout" msgid="3407426963155388504">"උත්සාහයන් ඉතා වැඩි ගණනකි. කරුණාකර පසුව නැවත උත්සාහ කරන්න."</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"උත්සාහයන් ඉතා වැඩි ගණනකි. පසුව නැවත උත්සාහ කරන්න."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"උත්සාහයන් ඉතා වැඩි ගණනකි. මුහුණු සත්‍යාපනය අබල කරන ලදී."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"නැවත උත්සාහ කරන්න."</string>
     <string name="face_error_not_enrolled" msgid="9166792142679691323">"මුහුණක් ඇතුළත් කර නොමැත."</string>
@@ -1877,8 +1894,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; වෙත සුරකින්නද?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> සහ <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; වෙත සුරකින්නද?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, සහ <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; වෙත සුරකින්නද?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; වෙත යාවත්කාලීන කරන්නද?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; වෙත යාවත්කාලීන කරන්නද?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> සහ <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; වෙත යාවත්කාලීන කරන්නද?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, සහ <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; වෙත යාවත්කාලීන කරන්නද?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"සුරකින්න"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"එපා ස්තූතියි"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"යාවත්කාලීන කරන්න"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"මුරපදය"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ලිපිනය"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ණය කාඩ්පත"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 42af270..f3569c9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -135,8 +135,8 @@
     <item msgid="4397097370387921767">"Volanie siete Wi‑Fi %s"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Vypnuté"</string>
-    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Uprednostniť Wi‑Fi"</string>
-    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferujem mobilné dáta"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferovať Wi‑Fi"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferovať mobilné spojenie"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Len Wi‑Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepresmerované"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -242,9 +242,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim v lietadle"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim v lietadle je ZAPNUTÝ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim v lietadle je VYPNUTÝ"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Šetrič batérie"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Šetrič batérie je VYPNUTÝ"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Šetrič batérie je ZAPNUTÝ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Nastavenia"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Pomôcť"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Hlasový asistent"</string>
@@ -309,6 +306,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Telesné senzory"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"prístup k dátam senzorov vašich životných funkcií"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; používať údaje senzorov o vašich životných funkciách?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Hudba"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"prístup k hudbe"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k hudbe?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotky a videá"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"prístup k fotkám a videám"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k fotkám a videám?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Načítať obsah okna"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Môžete preskúmať obsah okna, s ktorým pracujete."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Zapnúť funkciu Preskúmanie dotykom"</string>
@@ -430,7 +433,7 @@
     <string name="permlab_vibrate" msgid="7696427026057705834">"ovládať vibrovanie"</string>
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Umožňuje aplikácii ovládať vibrácie."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"priamo volať na telefónne čísla"</string>
-    <string name="permdesc_callPhone" msgid="3740797576113760827">"Umožňuje aplikácii volať telefónne čísla bez vášho zásahu. V dôsledku toho sa môžu účtovať neočakávané poplatky alebo sa môžu uskutočniť neočakávané hovory. Toto povolenie neumožňuje aplikácii volať na čísla tiesňového volania."</string>
+    <string name="permdesc_callPhone" msgid="3740797576113760827">"Umožňuje aplikácii volať telefónne čísla bez vášho zásahu. V dôsledku toho sa môžu účtovať neočakávané poplatky alebo sa môžu uskutočniť neočakávané hovory. Toto povolenie neumožňuje aplikácii volať na tiesňovú linku."</string>
     <string name="permlab_accessImsCallService" msgid="3574943847181793918">"prístup k službe volania IMS"</string>
     <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Umožňuje aplikácii používať službu okamžitých správ (IMS) na volanie bez intervencie používateľa."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"čítať stav a identitu telefónu"</string>
@@ -503,6 +506,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikácii zavolať metódy, ktoré pridávajú a odstraňujú vzory odtlačkov prstov."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"použiť hardvér na snímanie odtlačkov prstov"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Umožňuje aplikácii používať na overenie totožnosti hardvér na snímanie odtlačkov prstov."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"čítať hudobnú zbierku"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Umožňuje aplikácii čítať hudobnú zbierku."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"upravovať hudobnú zbierku"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Umožňuje aplikácii upravovať hudobnú zbierku."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"čítať zbierku videí"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Umožňuje aplikácii čítať zbierku videí."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"upravovať zbierku videí"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Umožňuje aplikácii upravovať zbierku videí."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"čítať zbierku fotiek"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Umožňuje aplikácii čítať zbierku fotiek."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"upravovať zbierku fotiek"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Umožňuje aplikácii upravovať zbierku fotiek."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"čítať polohy zo zbierky médií"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Umožňuje aplikácii čítať polohy zo zbierky médií."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Podarilo sa rozpoznať iba časť odtlačku prsta. Skúste to znova."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Odtlačok prsta sa nepodarilo spracovať. Skúste to znova."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Snímač odtlačkov je špinavý. Vyčistite ho a skúste to znova."</string>
@@ -771,7 +788,7 @@
     <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Zadajte kód PIN na odomknutie"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Nesprávny kód PIN."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Ak chcete telefón odomknúť, stlačte Menu a následne 0."</string>
-    <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Číslo tiesňovej linky"</string>
+    <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Tiesňová linka"</string>
     <string name="lockscreen_carrier_default" msgid="6169005837238288522">"Žiadny signál"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Obrazovka je uzamknutá."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Ak chcete odomknúť telefón alebo uskutočniť tiesňové volanie, stlačte Menu."</string>
@@ -1945,8 +1962,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Uložiť <xliff:g id="TYPE">%1$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Uložiť <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Uložiť <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Nahrať do služby &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Chcete nahrať <xliff:g id="TYPE">%1$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Chcete nahrať <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Chcete nahrať <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Uložiť"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nie, vďaka"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Aktualizovať"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"heslo"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditná karta"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ecfbec1..0f9d038 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -135,7 +135,7 @@
     <item msgid="4397097370387921767">"Klicanje prek Wi-Fi-ja (%s)"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Izklopljeno"</string>
-    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Prednostno – Wi-Fi"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Prednostno Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Prednostno mobilno"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Samo Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ni posredovano"</string>
@@ -242,9 +242,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način za letalo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Način za letalo je VKLOPLJEN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Način za letalo je IZKLOPLJEN"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Varčevanje z energijo akumulatorja"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Varčevanje z energijo akumulatorja je izklopljeno"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Varčevanje z energijo akumulatorja je vklopljeno"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Nastavitve"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Pomoč"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glas. pomočnik"</string>
@@ -309,6 +306,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Tipala telesnih funkcij"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"dostop do podatkov tipala o vaših vitalnih znakih"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti dostop do podatkov tipala o vitalnih znakih?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Glasba"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"dostop do glasbe"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti dostop do glasbe?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotografije in videoposnetki"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"dostop do fotografij in videoposnetkov"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti dostop do fotografij in videoposnetkov?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Pridobiti vsebino okna"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Preverjanje vsebine okna, ki ga uporabljate."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Vklopiti raziskovanje z dotikom"</string>
@@ -503,6 +506,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Aplikaciji omogoča sprožanje načinov za dodajanje in brisanje predlog s prstnimi odtisi za uporabo."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"uporaba strojne opreme za prstne odtise"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Aplikaciji omogoča uporabo strojne opreme za prstne odtise za preverjanje pristnosti"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"branje glasbene zbirke"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Aplikaciji omogoča branje glasbene zbirke."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"spreminjanje glasbene zbirke"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Aplikaciji omogoča spreminjanje glasbene zbirke."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"branje zbirke videoposnetkov"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Aplikaciji omogoča branje zbirke videoposnetkov."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"spreminjanje zbirke videoposnetkov"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Aplikaciji omogoča spreminjanje zbirke videoposnetkov."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"branje zbirke fotografij"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Aplikaciji omogoča branje zbirke fotografij."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"spreminjanje zbirke fotografij"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Aplikaciji omogoča spreminjanje zbirke fotografij."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"branje lokacij v predstavnostni zbirki"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Aplikaciji omogoča branje lokacij v predstavnostni zbirki."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Zaznan delni prstni odtis. Poskusite znova."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Prstnega odtisa ni bilo mogoče obdelati. Poskusite znova."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Tipalo prstnih odtisov je umazano. Očistite ga in poskusite znova."</string>
@@ -1945,8 +1962,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Želite <xliff:g id="TYPE">%1$s</xliff:g> shraniti pod oznako &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Želite <xliff:g id="TYPE_0">%1$s</xliff:g> in <xliff:g id="TYPE_1">%2$s</xliff:g> shraniti pod oznako &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Želite <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="TYPE_2">%3$s</xliff:g> shraniti pod oznako &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Želite posodobiti na oznako &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Želite <xliff:g id="TYPE">%1$s</xliff:g> posodobiti na oznako &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Želite <xliff:g id="TYPE_0">%1$s</xliff:g> in <xliff:g id="TYPE_1">%2$s</xliff:g> posodobiti na oznako &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Želite <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="TYPE_2">%3$s</xliff:g> posodobiti na oznako &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Shrani"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Posodobi"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"geslo"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"naslov"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditno kartico"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 6ee1c76..17ec70d 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"modaliteti i aeroplanit"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modaliteti i aeroplanit është i AKTIVIZUAR"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modaliteti i aeroplanit është i ÇAKTIVIZUAR"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Kursyesi i baterisë"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"\"Kursyesi i baterisë\" është JOAKTIV."</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"\"Kursyesi i baterisë\" është AKTIV"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Cilësimet"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Ndihma"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ndihma zanore"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensorët e trupit"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"qasu tek të dhënat e sensorëve rreth shenjave të tua jetësore"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te të dhënat e sensorëve rreth shenjave të tua jetësore?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muzika"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"qasu te muzika jote"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te muzika jote?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotografitë dhe videot"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"qasu te fotografitë dhe videot e tua"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te fotografitë dhe videot e tua?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Nxjerrë përmbajtjen e dritares"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspekton përmbajtjen e dritares me të cilën po ndërvepron."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktivizojë funksionin \"Eksploro me prekje\""</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"E lejon aplikacionin që të aktivizojë metoda për të shtuar dhe për të fshirë shabllonet e gjurmës së gishtit për përdorim."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"përdor harduerin e gjurmës së gishtit"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"E lejon aplikacionin që të përdorë harduerin e gjurmës së gishtit për verifikim"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"lexo koleksionin tënd të muzikës"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Lejon aplikacionin të lexojë koleksionin tënd të muzikës"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modifiko koleksionin tënd të muzikës"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Lejon aplikacionin të modifikojë koleksionin tënd të muzikës."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"lexo koleksionin tënd të videove"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Lejon aplikacionin të lexojë koleksionin tënd të videove."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modifiko koleksionin tënd të videove"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Lejon aplikacionin të modifikojë koleksionin tënd të videove."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"lexo koleksionin tënd të fotografive"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Lejon aplikacionin të lexojë koleksionin tënd të fotografive."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modifiko koleksionin tënd të fotografive"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Lejon aplikacionin të modifikojë koleksionin tënd të fotografive."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"lexo vendndodhjet nga koleksioni yt i medias"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Lejon aplikacionin të lexojë vendndodhjet nga koleksioni yt i medias."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"U zbulua një gjurmë gishti e pjesshme. Provo përsëri."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Gjurma e gishtit nuk mund të përpunohej. Provo përsëri."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sensori i gjurmës së gishtit nuk është i pastër. Pastroje dhe provo përsëri."</string>
@@ -1876,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Të ruhet <xliff:g id="TYPE">%1$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Të ruhen <xliff:g id="TYPE_0">%1$s</xliff:g> dhe <xliff:g id="TYPE_1">%2$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Të ruhen <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dhe <xliff:g id="TYPE_2">%3$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Të përditësohet te &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Të përditësohet <xliff:g id="TYPE">%1$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Të përditësohen <xliff:g id="TYPE_0">%1$s</xliff:g> dhe <xliff:g id="TYPE_1">%2$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Të përditësohen <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dhe <xliff:g id="TYPE_2">%3$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Ruaj"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Jo, faleminderit"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Përditëso"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"fjalëkalimi"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"karta e kreditit"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 2bc76a1..517815d 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -239,9 +239,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим рада у авиону"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим рада у авиону је УКЉУЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим рада у авиону је ИСКЉУЧЕН"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Уштеда батерије"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Уштеда батерије је ИСКЉУЧЕНА"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Уштеда батерије је УКЉУЧЕНА"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Подешавања"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Помоћ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Гласовна помоћ"</string>
@@ -306,6 +303,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Сензори за тело"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"приступа подацима сензора о виталним функцијама"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Желите ли да омогућите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;приступа подацима сензора о виталним функцијама?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Музика"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"приступ музици"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Желите ли да омогућите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа музици?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Слике и видео снимци"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"приступ сликама и видео снимцима"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Желите ли да омогућите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа сликама и видео снимцима?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"да преузима садржај прозора"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Проверава садржај прозора са којим остварујете интеракцију."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"да укључи Истраживања додиром"</string>
@@ -500,6 +503,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Дозвољава апликацији да активира методе за додавање и брисање шаблона отисака прстију који ће се користити."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"користи хардвер за отиске прстију"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозвољава апликацији да користи хардвер за отиске прстију ради потврде аутентичности"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"читање музичке колекције"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Дозвољава апликацији да чита музичку колекцију."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"измена музичке колекције"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Дозвољава апликацији да мења музичку колекцију."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"читање видео колекције"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Дозвољава апликацији да чита видео колекцију."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"измена видео колекције"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Дозвољава апликацији да мења видео колекцију."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"читање колекције слика"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Дозвољава апликацији да чита колекцију слика."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"измена колекције слика"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Дозвољава апликацији да мења колекцију слика."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"читање локација из медијске колекције"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Дозвољава апликацији да чита локације из медијске колекције."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Откривен је делимични отисак прста. Пробајте поново."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Није успела обрада отиска прста. Пробајте поново."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Сензор за отиске прстију је прљав. Очистите га и покушајте поново."</string>
@@ -1910,8 +1927,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Желите ли да сачувате ставку <xliff:g id="TYPE">%1$s</xliff:g> у: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> у: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> у: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Желите ли да ажурирате на &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Желите ли да ажурирате ставку <xliff:g id="TYPE">%1$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Желите ли да ажурирате ставке <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Желите ли да ажурирате ставке <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сачувај"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, хвала"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Ажурирај"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"лозинка"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картица"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index a94ce4e..835f198 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flygplansläge"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flygplansläge är AKTIVERAT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flygplansläge är INAKTIVERAT"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Batterisparläge"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Batterisparläget har inaktiverats"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Batterisparläget har aktiverats"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Inställningar"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Hjälp"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Kroppssensorer"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"få åtkomst till sensordata om dina vitalparametrar"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till sensordata om vitalparametrar?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musik"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"åtkomstbehörighet till din musik"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomstbehörighet till din musik?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Foton och videor"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"åtkomstbehörighet till dina foton &amp; videor"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomstbehörighet till dina foton och videor?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Hämta fönsterinnehåll"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Granska innehållet i ett fönster som du interagerar med."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktivera Explore by touch"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Tillåter att appen anropar metoder för att lägga till och radera fingeravtrycksmallar."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"använda maskinvara för fingeravtryck"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillåter att appen använder maskinvara för fingeravtryck vid autentisering"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"läsa av din musiksamling"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Tillåter att appen läser av din musiksamling."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"göra ändringar i din musiksamling"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Tillåter att appen gör ändringar i din musiksamling."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"läsa av din videosamling"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Tillåter att appen läser av din videosamling."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"göra ändringar i din videosamling"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Tillåter att appen gör ändringar i din videosamling."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"läsa av din fotosamling"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Tillåter att appen läser av din fotosamling."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"göra ändringar i din fotosamling"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Tillåter att appen gör ändringar i din fotosamling."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"läsa av platser i din mediesamling"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Tillåter att appen läser av platser i din mediesamling."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Ofullständigt fingeravtryck. Försök igen."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Det gick inte att bearbeta fingeravtrycket. Försök igen."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingeravtryckssensorn är smutsig. Rengör den och försök igen."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vill du spara <xliff:g id="TYPE">%1$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vill du spara <xliff:g id="TYPE_0">%1$s</xliff:g> och <xliff:g id="TYPE_1">%2$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vill du spara <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Vill du uppdatera till &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vill du uppdatera <xliff:g id="TYPE">%1$s</xliff:g> till &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vill du uppdatera <xliff:g id="TYPE_0">%1$s</xliff:g> och <xliff:g id="TYPE_1">%2$s</xliff:g> till &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vill du uppdatera <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g> till &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Spara"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nej tack"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Uppdatera"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"lösenordet"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adressen"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditkortet"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 28916b4..c846f08 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -234,9 +234,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Hali ya ndegeni"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Hali ya ndegeni IMEWASHWA"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Hali ya ndegeni IMEZIMWA"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Kiokoa betri"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Kiokoa betri KIMEZIMWA"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Kiokoa betri KIMEWASHWA"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Mipangilio"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Mapendekezo"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Usaidizi wa Sauti"</string>
@@ -301,6 +298,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Vihisi vya Mwili"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"fikia data ya kitambuzi kuhusu alama zako muhimu"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie data ya vitambuzi kuhusu viashiria muhimu vya mwili wako?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Muziki"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"kufikia muziki wako"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie muziki wako?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Picha na Video"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"kufikia picha na video zako"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie picha na video zako?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Kufikia maudhui ya dirisha"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Kuchunguza maudhui ya dirisha unalotumia."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Kuwasha \'Chunguza kwa Kugusa\'"</string>
@@ -495,6 +498,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Huruhusu programu kuomba njia za kuongeza na kufuta violezo vya kitambulisho kwa matumizi."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"tumia maunzi ya kitambulisho"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Huruhusu programu kutumia maunzi ya kitambulisho kwa uthibitisho"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"kusoma mkusanyiko muziki wako"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Inaruhusu programu kusoma mkusanyiko wako wa muziki."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"kubadilisha mkusanyiko wako wa muziki"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Inaruhusu programu kubadilisha mkusanyiko wako wa muziki."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"kusoma mkusanyiko wa video zako"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Inaruhusu programu kusoma mkusanyiko wa video zako."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"kubadilisha mkusanyiko wa video zako"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Inaruhusu programu kubadilisha mkusanyiko wa video zako."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"kusoma mkusanyiko wa picha zako"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Inaruhusu programu kusoma mkusanyiko wa picha zako."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"kubadilisha mkusanyiko wa picha zako"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Inaruhusu programu kubadilisha mkusanyiko wa picha zako."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"kusoma maeneo kwenye mkusanyiko wa vipengee vyako"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Inaruhusu programu kusoma maeneo kwenye mkusanyiko wa vipengee vyako."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Kitambuzi kimegundua sehemu ya kitambulisho. Tafadhali jaribu tena."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Haikuweza kuchakata kitambulisho. Tafadhali jaribu tena."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Kitambuzi alama ya kidole ni kichafu. Tafadhali kisafishe na ujaribu tena."</string>
@@ -533,7 +550,7 @@
     <string name="face_acquired_too_left" msgid="2712489669456176505">"Tafadhali sogeza kitambuzi kushoto."</string>
     <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"Tafadhali angalia kitambuzi."</string>
     <string name="face_acquired_not_detected" msgid="5707782294589511391">"Haikutambua uso wowote"</string>
-    <string name="face_acquired_not_steady" msgid="3722829465011040042">"Weka uso vizuri mbele ya kifaa."</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"Weka uso wima mbele ya kifaa."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="6255891785768984615">"Maunzi ya uso hayapatikani."</string>
@@ -1209,8 +1226,8 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"Wi-Fi haina muunganisho wa intaneti"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Gusa ili upate chaguo"</string>
-    <string name="wifi_softap_config_change" msgid="8475911871165857607">"Mabadiliko kwenye mipangilio ya mtandao-hewa"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"Bendi ya mtandao-hewa wako imebadilika."</string>
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"Mabadiliko kwenye mipangilio ya mtandao pepe"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"Bendi ya mtandao pepe wako imebadilika."</string>
     <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Kifaa hiki hakitumii mapendeleo yako ya GHz 5 pekee. Badala yake, kifaa hiki kitatumia bendi ya GHz 5 itakapopatikana."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"Sasa inatumia <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"Kifaa hutumia <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wakati <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> haina intaneti. Huenda ukalipishwa."</string>
@@ -1873,8 +1890,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Ungependa kuhifadhi <xliff:g id="TYPE">%1$s</xliff:g> kwenye &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g> na <xliff:g id="TYPE_1">%2$s</xliff:g> kwenye &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, na <xliff:g id="TYPE_2">%3$s</xliff:g> kwenye &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Ungependa kusasisha kuwa &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Ungependa kusasisha <xliff:g id="TYPE">%1$s</xliff:g> kuwa &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Ungependa kusasisha <xliff:g id="TYPE_0">%1$s</xliff:g> na <xliff:g id="TYPE_1">%2$s</xliff:g> kuwa &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Ungependa kusasisha <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> na <xliff:g id="TYPE_2">%3$s</xliff:g> kuwa &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Hifadhi"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Hapana, asante"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Sasisha"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"nenosiri"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"anwani"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kadi ya mikopo"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 958570f..ba58742 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -60,7 +60,7 @@
     <string name="ClirMmi" msgid="7784673673446833091">"வெளிசெல்லும் அழைப்பாளர் ஐடி"</string>
     <string name="ColpMmi" msgid="3065121483740183974">"இணைக்கப்பட்ட லைன் ஐடி"</string>
     <string name="ColrMmi" msgid="4996540314421889589">"இணைக்கப்பட்ட லைன் ஐடியை வரம்பிடல்"</string>
-    <string name="CfMmi" msgid="5123218989141573515">"அழைப்புப் பகிர்வு"</string>
+    <string name="CfMmi" msgid="5123218989141573515">"அழைப்பு திருப்பிவிடுதல்"</string>
     <string name="CwMmi" msgid="9129678056795016867">"அழைப்பு காத்திருப்பு"</string>
     <string name="BaMmi" msgid="455193067926770581">"அழைப்புத் தவிர்ப்பு"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"கடவுச்சொல்லை மாற்று"</string>
@@ -88,7 +88,7 @@
     <string name="EmergencyCallWarningTitle" msgid="813380189532491336">"அவசர அழைப்பைச் செய்ய முடியாது"</string>
     <string name="EmergencyCallWarningSummary" msgid="1899692069750260619">"வைஃபை மூலம் அவசர அழைப்புகளைச் செய்ய முடியாது"</string>
     <string name="notification_channel_network_alert" msgid="4427736684338074967">"விழிப்பூட்டல்கள்"</string>
-    <string name="notification_channel_call_forward" msgid="2419697808481833249">"அழைப்புப் பகிர்வு"</string>
+    <string name="notification_channel_call_forward" msgid="2419697808481833249">"அழைப்பு திருப்பிவிடுதல்"</string>
     <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"அவசரகாலத் திரும்ப அழைக்கும் பயன்முறை"</string>
     <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"மொபைல் டேட்டாவின் நிலை"</string>
     <string name="notification_channel_sms" msgid="3441746047346135073">"SMS செய்திகள்"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"விமானப் பயன்முறை"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"விமானப் பயன்முறை இயக்கத்தில் உள்ளது"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"விமானப் பயன்முறை முடக்கத்தில் உள்ளது"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"பேட்டரி சேமிப்பான்"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"பேட்டரி சேமிப்பான் ஆஃப் செய்யப்பட்டுள்ளது"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"பேட்டரி சேமிப்பான் ஆன் செய்யப்பட்டுள்ளது"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"அமைப்பு"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"உதவி"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"குரல் உதவி"</string>
@@ -275,7 +272,7 @@
     <string name="permgrouprequest_contacts" msgid="6032805601881764300">"தொடர்புகளை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"இருப்பிடம்"</string>
     <string name="permgroupdesc_location" msgid="1346617465127855033">"இந்தச் சாதனத்தின் இருப்பிடத்தை அறிந்து கொள்ள"</string>
-    <string name="permgrouprequest_location" msgid="3788275734953323491">"இந்தச் சாதனத்தின் இருப்பிடத்தை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
+    <string name="permgrouprequest_location" msgid="3788275734953323491">"இந்தச் சாதனத்தின் இருப்பிடத்தை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="permgrouprequestdetail_location" msgid="1113400215566814664">"இந்த ஆப்ஸைப் பயன்படுத்தும் சமயத்தில் மட்டுமே, இது உங்கள் இருப்பிடத்தை அணுகும்."</string>
     <string name="permgroupbackgroundrequest_location" msgid="8461841153030844390">"இதன் இருப்பிடத்தை எப்போதுமே &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; அணுக அனுமதிக்கவா?"</string>
     <string name="permgroupbackgroundrequestdetail_location" msgid="1715668276378108654">"இந்த ஆப்ஸைப் பயன்படுத்தாத சமயங்களில் கூட, இது உங்கள் இருப்பிடத்தை அணுகும்."</string>
@@ -284,7 +281,7 @@
     <string name="permgrouprequest_calendar" msgid="289900767793189421">"கேலெண்டரை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS அனுப்பலாம், வந்த SMSகளைப் பார்க்கலாம்"</string>
-    <string name="permgrouprequest_sms" msgid="7168124215838204719">"மெசேஜ்களை அனுப்பவும், அவற்றைப் பார்க்கவும் &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
+    <string name="permgrouprequest_sms" msgid="7168124215838204719">"மெசேஜ்களை அனுப்பவும், பார்க்கவும் &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"சேமிப்பிடம்"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"உங்கள் சாதனத்தில் உள்ள படங்கள், மீடியா மற்றும் கோப்புகளை அணுக வேண்டும்"</string>
     <string name="permgrouprequest_storage" msgid="7885942926944299560">"உங்கள் சாதனத்திலுள்ள படங்கள், மீடியா, ஃபைல்கள் ஆகியவற்றை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
@@ -299,10 +296,16 @@
     <string name="permgrouprequest_calllog" msgid="8487355309583773267">"உங்கள் மொபைல் அழைப்புப் பதிவுகளை அணுக, &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"ஃபோன்"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"யாரையும் தொலைபேசியில் அழைக்கலாம்"</string>
-    <string name="permgrouprequest_phone" msgid="9166979577750581037">"மொபைல் அழைப்புகள் செய்யவும், அவற்றை நிர்வகிக்கவும், &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
+    <string name="permgrouprequest_phone" msgid="9166979577750581037">"மொபைல் அழைப்புகள் செய்யவும், அவற்றை நிர்வகிக்கவும், &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"உடல் சென்சார்கள்"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"உங்கள் உடல் இயக்கம் பற்றி உணர்விகள் கூறும் தகவலைப் பார்க்கலாம்"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"உங்கள் உடலியக்கக் குறிகள் பற்றிய சென்சார் தரவை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"இசை"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"இசையைக் கேட்கலாம்"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"இசையை அணுக &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"படங்கள் &amp; வீடியோக்கள்"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"படங்கள் &amp; வீடியோக்களைப் பார்க்கலாம்"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"படங்கள் &amp; வீடியோக்களை அணுக &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"சாளர உள்ளடக்கத்தைப் பெறும்"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"நீங்கள் பணியாற்றிக் கொண்டிருக்கும் சாளரத்தின் உள்ளடக்கத்தைப் பார்க்கலாம்."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"தொடுவதன் மூலம் அறிவதை இயக்கும்"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"பயன்படுத்துவதற்காக, கைரேகை டெம்ப்ளேட்களைச் சேர்க்க மற்றும் நீக்குவதற்கான செயல்முறைகளை இயக்குவதற்குப் பயன்பாட்டை அனுமதிக்கும்."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"கைரேகை வன்பொருளைப் பயன்படுத்து"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"அங்கீகரிப்பதற்கு, கைரேகை வன்பொருளைப் பயன்படுத்த, பயன்பாட்டை அனுமதிக்கும்"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"இசைத் தொகுப்பை அணுகுதல்"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"உங்களின் இசைத் தொகுப்பை அணுக ஆப்ஸை அனுமதிக்கும்."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"இசைத் தொகுப்பை மாற்றுதல்"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"உங்களின் இசைத் தொகுப்பை மாற்ற ஆப்ஸை அனுமதிக்கும்."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"வீடியோ தொகுப்பை அணுகுதல்"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"உங்களின் வீடியோ தொகுப்பை அணுக ஆப்ஸை அனுமதிக்கும்."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"வீடியோ தொகுப்பை மாற்றுதல்"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"உங்களின் வீடியோ தொகுப்பை மாற்ற ஆப்ஸை அனுமதிக்கும்."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"படத் தொகுப்பை அணுகுதல்"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"உங்களின் படத் தொகுப்பை அணுக ஆப்ஸை அனுமதிக்கும்."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"படத் தொகுப்பை மாற்றுதல்"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"உங்களின் படத் தொகுப்பை மாற்ற ஆப்ஸை அனுமதிக்கும்."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"மீடியா தொகுப்பிலிருந்து இடங்களை அறிதல்"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"உங்களின் மீடியா தொகுப்பிலிருந்து இடங்களை அறிந்துகொள்ள ஆப்ஸை அனுமதிக்கும்."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"கைரேகையை ஓரளவுதான் கண்டறிய முடிந்தது. மீண்டும் முயலவும்."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"கைரேகையைச் செயலாக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"கைரேகை உணர்வியில் தூசி உள்ளது. சுத்தம் செய்து, முயலவும்."</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"கைரேகை ஐகான்"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"முக அங்கீகாரத்திற்கான வன்பொருளை நிர்வகித்தல்"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"உபயோகிப்பதற்காக முக டெம்ப்ளேட்டுகளை சேர்க்கும்/நீக்கும் முறைகளை இயக்க, ஆப்ஸை அனுமதிக்கும்."</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"முக அங்கீகாரத்திற்கான வன்பொருளைப் பயன்படுத்துதல்"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"அடையாளம் காண்பதற்கு, முக அங்கீகார வன்பொருளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கிறது"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"அடையாளம் காண முடியவில்லை. மீண்டும் முயலவும்."</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"முகம் பிரகாசமாக உள்ளது. குறைந்த ஒளியில் முயலவும்."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"முகம் தெரியவில்லை, வெளிச்சமான இடத்தில் முயலவும்."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"சென்சாரை முகத்திலிருந்து சற்று தொலைவில் நகர்த்துக."</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"சென்சாரை முகத்திற்கு அருகில் கொண்டு வரவும்."</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"சென்சாரை மேலே உயர்த்தவும்."</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"சென்சாரைக் கீழே நகர்த்தவும்."</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"சென்சாரை வலது புறமாக நகர்த்தவும்."</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"சென்சாரை இடது புறமாக நகர்த்தவும்."</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"சென்சாரைப் பார்க்கவும்."</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"முகம் தெரியவில்லை."</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"சாதனத்தின் முன், முகத்தை அசையாமல் காண்பிக்கவும்."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"முக அங்கீகாரத்திற்கான வன்பொருள் இல்லை."</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"முகப் பதிவிற்கான நேரம் முடிந்தது. மீண்டும் முயல்க."</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"முகத்தைச் சேமிக்க இயலாது."</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"முக அங்கீகாரச் செயல்பாடு ரத்துசெய்யப்பட்டது."</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"பலமுறை முயன்றுவிட்டீர்கள். பிறகு முயலவும்."</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"பலமுறை தோல்வி. முக அங்கீகாரம் முடக்கப்பட்டது."</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"மீண்டும் முயலவும்."</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"முகம் எதுவும் பதிவு செய்யப்படவில்லை."</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"இந்தச் சாதனத்தில், முக அங்கீகாரத்திற்கான சென்சார் இல்லை"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"முகம் <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"முக ஐகான்"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ஒத்திசைவு அமைப்புகளைப் படித்தல்"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"கணக்கிற்கான ஒத்திசைவு அமைப்புகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. எடுத்துக்காட்டாக, பீப்பிள் பயன்பாடு கணக்குடன் ஒத்திசைக்கப்பட்டுள்ளதா என்பதை இது தீர்மானிக்கலாம்."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ஒத்திசைவை இயக்குவதையும், முடக்குவதையும் மாற்றுதல்"</string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"வைஃபையில் இண்டர்நெட் அணுகல் இல்லை"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"விருப்பங்களுக்கு, தட்டவும்"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"உங்கள் ஹாட்ஸ்பாட் அமைப்புகளில் செய்யப்பட்டுள்ள மாற்றங்கள்"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"உங்கள் ஹாட்ஸ்பாட்டின் அலைவரிசை மாறிவிட்டது."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"இந்தச் சாதனத்தில், ’5GHz மட்டும்’ எனும் முன்னுரிமைத் தேர்வு ஆதரிக்கப்படவில்லை. எனினும் 5GHz அலைவரிசை கிடைக்கும்போது, சாதனம் அதைப் பயன்படுத்திக்கொள்ளும்."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>க்கு மாற்றப்பட்டது"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> நெட்வொர்க்கில் இண்டர்நெட் அணுகல் இல்லாததால், சாதனமானது <xliff:g id="NEW_NETWORK">%1$s</xliff:g> நெட்வொர்க்கைப் பயன்படுத்துகிறது. கட்டணங்கள் விதிக்கப்படலாம்."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> இலிருந்து <xliff:g id="NEW_NETWORK">%2$s</xliff:g>க்கு மாற்றப்பட்டது"</string>
@@ -1906,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; இல் சேமிக்கவா?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> மற்றும் <xliff:g id="TYPE_1">%2$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; இல் சேமிக்கவா?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ஆகியவற்றை &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; இல் சேமிக்கவா?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; என்பதற்குப் புதுப்பிக்கவா?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; என்பதற்குப் புதுப்பிக்கவா?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> மற்றும் <xliff:g id="TYPE_1">%2$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; என்பதற்குப் புதுப்பிக்கவா?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> மற்றும் <xliff:g id="TYPE_2">%3$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; என்பதற்குப் புதுப்பிக்கவா?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"சேமி"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"வேண்டாம்"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"புதுப்பி"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"கடவுச்சொல்"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"முகவரி"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"கிரெடிட் கார்டு"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index bc21a99..b0d7a4dc 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ఎయిర్‌ప్లేన్ మోడ్"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ఎయిర్‌ప్లేన్ మోడ్ ఆన్‌లో ఉంది"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"ఎయిర్‌ప్లేన్ మోడ్ ఆఫ్‌లో ఉంది"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"బ్యాటరీ సేవర్"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"బ్యాటరీ సేవర్ ఆఫ్‌లో ఉంది"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"బ్యాటరీ సేవర్ ఆన్‌లో ఉంది"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"సెట్టింగ్‌లు"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"సహాయం"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"వాయిస్ అసిస్టెంట్"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"శరీర సెన్సార్‌లు"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాని యాక్సెస్ చేస్తుంది"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాని యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"సంగీతం"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"మీ సంగీతాన్ని యాక్సెస్ చేయండి"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"మీ సంగీతాన్ని యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"ఫోటోలు &amp; వీడియోలు"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"మీ ఫోటోలను &amp; వీడియోలను యాక్సెస్ చేయండి"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"మీ ఫోటోలు &amp; వీడియోలు యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"విండో కంటెంట్‍ను తిరిగి పొందుతుంది"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"మీరు పరస్పర చర్య చేస్తున్న విండో కంటెంట్‌‍ను పరిశీలిస్తుంది."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"తాకడం ద్వారా విశ్లేషణను ప్రారంభిస్తుంది"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్‌లను జోడించే మరియు తొలగించే పద్ధతులను అమలు చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"వేలిముద్ర హార్డ్‌వేర్‌ని ఉపయోగించడానికి అనుమతి"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ప్రామాణీకరణ కోసం వేలిముద్ర హార్డ్‌వేర్‌ను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"మీ సంగీత సేకరణను చదవండి"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"మీ సంగీత సేకరణను చదవడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"మీ సంగీత సేకరణను సవరించండి"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"మీ సంగీత సేకరణని సవరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"మీ వీడియో సేకరణను చదవండి"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"మీ వీడియో సేకరణను చదవడానికి యాప్‌ని అనుమతిస్తుంది."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"మీ వీడియో సేకరణను సవరించండి"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"మీ వీడియో సేకరణను సవరించడానికి యాప్‌ని అనుమతిస్తుంది."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"మీ ఫోటో సేకరణను చదవండి"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"మీ ఫోటో సేకరణను చదవడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"మీ ఫోటో సేకరణను సవరించండి"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"మీ ఫోటో సేకరణను సవరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవండి"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"పాక్షిక వేలిముద్ర గుర్తించబడింది. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"వేలిముద్రను ప్రాసెస్ చేయడం సాధ్యపడలేదు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"వేలిముద్ర సెన్సార్ మురికిగా ఉంది. దయచేసి శుభ్రపరిచి, మళ్లీ ప్రయత్నించండి."</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"వేలిముద్ర చిహ్నం"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"ముఖ ప్రమాణీకరణ హార్డ్‌వేర్‌ను నిర్వహించండి"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"వినియోగం కోసం ముఖ టెంప్లేట్‌లను జోడించే మరియు తొలగించే పద్ధతులను అమలు చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"ముఖ ప్రమాణీకరణ హార్డ్‌వేర్‌ను వాడండి"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"ప్రమాణీకరణ కోసం ముఖ ప్రామాణీకరణ హార్డ్‌వేర్‌ను ఉపయోగించడానికి యాప్‌ని అనుమతిస్తుంది"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"ముఖాన్ని ప్రాసెస్ చేయడం సాధ్యపడలేదు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"ముఖం చాలా ప్రకాశవంతంగా ఉంటుంది. దయచేసి తక్కువ కాంతిలో ప్రయత్నించండి."</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"ముఖం చాలా చీకటిగా ఉంది. దయచేసి కాంతి మూలాన్ని వెతకండి."</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"దయచేసి ముఖం నుండి దూరంగా సెన్సార్‌ను జరపండి."</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"దయచేసి సెన్సార్‌ను ముఖానికి మరింత దగ్గరగా తీసుకురండి."</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"దయచేసి సెన్సార్‌ను ఎక్కువకు జరపండి."</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"దయచేసి సెన్సార్‌ను తక్కువకు జరపండి."</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"దయచేసి సెన్సార్‌ను కుడికి జరపండి."</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"దయచేసి సెన్సార్‌ను ఎడమవైపుకు జరపండి."</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"దయచేసి సెన్సార్‌ను చూడండి."</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"ఎలాంటి ముఖం గుర్తించబడలేదు."</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"పరికరానికి నేరుగా ముఖాన్ని స్థిరంగా ఉంచండి."</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"ముఖ హార్డ్‌వేర్ అందుబాటులో లేదు."</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"ముఖ గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"ముఖం నిల్వ చేయబడదు."</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"ముఖ కార్యకలాపం రద్దయింది."</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"చాలా ఎక్కువ ప్రయత్నాలు చేసారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"చాలా ఎక్కువ ప్రయత్నాలు చేసారు. ముఖ ప్రమాణీకరణ నిలిపివేయబడింది."</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"మళ్లీ ప్రయత్నించండి."</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"ముఖం నమోదు చేయబడలేదు."</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"ఈ పరికరంలో ముఖ ప్రామాణీకరణ సెన్సార్ లేదు"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"ముఖ <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"ముఖ చిహ్నం"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"సమకాలీకరణ సెట్టింగ్‌లను చదవడం"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ఖాతా యొక్క సమకాలీకరణ సెట్టింగ్‌లను చదవడానికి యాప్‌ను అనుమతిస్తుంది. ఉదాహరణకు, వ్యక్తుల యాప్‌ ఖాతాతో సమకాలీకరించబడాలా లేదా అనే విషయాన్ని ఇది నిశ్చయించవచ్చు."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"సమకాలీకరణను ఆన్ మరియు ఆఫ్‌కు టోగుల్ చేయడం"</string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"Wi-Fiకి ఇంటర్నెట్ యాక్సెస్ లేదు"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ఎంపికల కోసం నొక్కండి"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"మీ హాట్‌స్పాట్ సెట్టింగ్‌లకు మార్పులు"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"మీ హాట్‌స్పాట్ బ్యాండ్ మార్చబడింది."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"ఈ పరికరం 5GHz కోసం మాత్రమే మీ ప్రాధాన్యతకు మద్దతు ఇవ్వదు. బదులుగా, ఈ పరికరం అందుబాటులో ఉన్నప్పుడు 5GHz బ్యాండ్‌ను ఉపయోగిస్తుంది."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>కి మార్చబడింది"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"పరికరం <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>కి ఇంటర్నెట్ యాక్సెస్ లేనప్పుడు <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> నుండి <xliff:g id="NEW_NETWORK">%2$s</xliff:g>కి మార్చబడింది"</string>
@@ -1906,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>ని &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;కు సేవ్ చేయాలా?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> మరియు <xliff:g id="TYPE_1">%2$s</xliff:g>లను &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;కు సేవ్ చేయాలా?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> మరియు <xliff:g id="TYPE_2">%3$s</xliff:g>లను &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;కు సేవ్ చేయాలా?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;కు అప్‌డేట్ చేయాలా?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>ని &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;కు అప్‌డేట్ చేయాలా?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> మరియు <xliff:g id="TYPE_1">%2$s</xliff:g>లను &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;కు అప్‌డేట్ చేయాలా?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> మరియు <xliff:g id="TYPE_2">%3$s</xliff:g>లను &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;కు అప్‌డేట్ చేయాలా?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"సేవ్ చేయి"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"వద్దు, ధన్యవాదాలు"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"అప్‌డేట్ చేయి"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"పాస్‌వర్డ్"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"చిరునామా"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"క్రెడిట్ కార్డ్"</string>
diff --git a/core/res/res/values-television/themes_device_defaults.xml b/core/res/res/values-television/themes_device_defaults.xml
index e380a7b..293591a 100644
--- a/core/res/res/values-television/themes_device_defaults.xml
+++ b/core/res/res/values-television/themes_device_defaults.xml
@@ -18,4 +18,5 @@
     <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
     <style name="Theme.DeviceDefault.Autofill" parent="Theme.Material.Autofill" />
     <style name="Theme.DeviceDefault.Autofill.Save" parent="Theme.Material.Autofill.Save" />
+    <style name="Theme.DeviceDefault.Resolver" parent="Theme.Leanback.Resolver" />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 5f96065..07107cb 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"โหมดใช้งานบนเครื่องบิน"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"เปิดโหมดใช้งานบนเครื่องบิน"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"โหมดใช้งานบนเครื่องบินปิดทำงานอยู่"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"โหมดประหยัดแบตเตอรี่"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"ปิดโหมดประหยัดแบตเตอรี่อยู่"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"เปิดโหมดประหยัดแบตเตอรี่อยู่"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"การตั้งค่า"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"ผู้ช่วย"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ตัวช่วยเสียง"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"เซ็นเซอร์ร่างกาย"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"เข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพของคุณ"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพไหม"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"เพลง"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"เข้าถึงเพลง"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงเพลงไหม"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"รูปภาพและวิดีโอ"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"เข้าถึงรูปภาพและวิดีโอ"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงรูปภาพและวิดีโอไหม"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"เรียกข้อมูลเนื้อหาของหน้าต่าง"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"ตรวจสอบเนื้อหาของหน้าต่างที่คุณกำลังโต้ตอบอยู่"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"เปิด \"แตะเพื่อสำรวจ\""</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"อนุญาตให้แอปเรียกใช้วิธีการเพื่อเพิ่มและลบเทมเพลตลายนิ้วมือสำหรับการใช้งาน"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ใช้ฮาร์ดแวร์ลายนิ้วมือ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"อนุญาตให้แอปใช้ฮาร์ดแวร์ลายนิ้วมือเพื่อตรวจสอบสิทธิ์"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"อ่านคอลเล็กชันเพลงของคุณ"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"อนุญาตให้แอปอ่านคอลเล็กชันเพลงของคุณ"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"แก้ไขคอลเล็กชันเพลงของคุณ"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"อนุญาตให้แอปแก้ไขคอลเล็กชันเพลงของคุณ"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"อ่านคอลเล็กชันวิดีโอของคุณ"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"อนุญาตให้แอปอ่านคอลเล็กชันวิดีโอของคุณ"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"แก้ไขคอลเล็กชันวิดีโอของคุณ"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"อนุญาตให้แอปแก้ไขอ่านคอลเล็กชันวิดีโอของคุณ"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"อ่านคอลเล็กชันรูปภาพของคุณ"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"อนุญาตให้แอปอ่านคอลเล็กชันรูปภาพของคุณ"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"แก้ไขคอลเล็กชันรูปภาพของคุณ"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"อนุญาตให้แอปแก้ไขคอลเล็กชันรูปภาพของคุณ"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"อ่านตำแหน่งจากคอลเล็กชันสื่อของคุณ"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"อนุญาตให้แอปอ่านตำแหน่งจากคอลเล็กชันสื่อของคุณ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ตรวจพบลายนิ้วมือเพียงบางส่วน โปรดลองอีกครั้ง"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ไม่สามารถประมวลผลลายนิ้วมือได้ โปรดลองอีกครั้ง"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"เซ็นเซอร์ลายนิ้วมือไม่สะอาด โปรดทำความสะอาดและลองอีกครั้ง"</string>
@@ -1291,7 +1308,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"แตะเพื่อดูตัวเลือกเพิ่มเติม"</string>
     <string name="usb_power_notification_message" msgid="4647527153291917218">"กำลังชาร์จอุปกรณ์ที่เชื่อมต่อ แตะเพื่อดูตัวเลือกเพิ่มเติม"</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"ตรวจพบอุปกรณ์เสริมสำหรับเสียงแบบแอนะล็อก"</string>
-    <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"อุปกรณ์ที่พ่วงไม่สามารถใช้งานร่วมกับโทรศัพท์นี้ แตะเพื่อเรียนรู้เพิ่มเติม"</string>
+    <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"อุปกรณ์ที่พ่วงไม่สามารถใช้งานร่วมกับโทรศัพท์นี้ แตะเพื่อดูข้อมูลเพิ่มเติม"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"เชื่อมต่อการแก้ไขข้อบกพร่องผ่าน USB แล้ว"</string>
     <string name="adb_active_notification_message" msgid="7463062450474107752">"แตะเพื่อปิดการแก้ไขข้อบกพร่อง USB"</string>
     <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"เลือกเพื่อปิดใช้งานการแก้ไขข้อบกพร่อง USB"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"บันทึก <xliff:g id="TYPE">%1$s</xliff:g> ไปยัง &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ใช่ไหม"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"บันทึก <xliff:g id="TYPE_0">%1$s</xliff:g> และ <xliff:g id="TYPE_1">%2$s</xliff:g> ไปยัง &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ใช่ไหม"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"บันทึก <xliff:g id="TYPE_0">%1$s</xliff:g> <xliff:g id="TYPE_1">%2$s</xliff:g> และ <xliff:g id="TYPE_2">%3$s</xliff:g> ไปยัง &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ใช่ไหม"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"อัปเดตเป็น &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ไหม"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"อัปเดต<xliff:g id="TYPE">%1$s</xliff:g>เป็น &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ไหม"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"อัปเดต<xliff:g id="TYPE_0">%1$s</xliff:g>และ<xliff:g id="TYPE_1">%2$s</xliff:g>เป็น &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ไหม"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"อัปเดต<xliff:g id="TYPE_0">%1$s</xliff:g> <xliff:g id="TYPE_1">%2$s</xliff:g> และ<xliff:g id="TYPE_2">%3$s</xliff:g>เป็น &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ไหม"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"บันทึก"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ไม่เป็นไร"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"อัปเดต"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"รหัสผ่าน"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ที่อยู่"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"บัตรเครดิต"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 7586a79..c4b14f7 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Naka-ON ang airplane mode"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Naka-OFF ang airplane mode"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Pangtipid sa baterya"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"NAKA-OFF ang Pangtipid sa baterya"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"NAKA-ON ang Pangtipid sa baterya"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Mga Setting"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Tulong"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Mga Sensor ng Katawan"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"i-access ang data ng sensor tungkol sa iyong vital signs"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang data ng sensor tungkol sa iyong mga vital sign?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musika"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"i-access ang iyong musika"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang iyong musika?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Mga Larawan at Video"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"i-access ang iyong mga larawan at video"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang iyong mga larawan at video?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Kunin ang content ng window"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Siyasatin ang nilalaman ng isang window kung saan ka nakikipag-ugnayan."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"I-on ang Explore by Touch"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Pinapayagan ang app na mag-invoke ng mga paraan upang magdagdag at mag-delete ng mga template ng fingerprint na magagamit."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gamitin ang hardware ng fingerprint"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Pinapayagan ang app na gumamit ng hardware ng fingerprint para sa pagpapatotoo"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"basahin ang iyong koleksyon ng musika"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Pinapayagan ang app na basahin ang iyong koleksyon ng musika."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"baguhin ang iyong koleksyon ng musika"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Pinapayagan ang app na baguhin ang iyong koleksyon ng musika."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"basahin ang iyong koleksyon ng video"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Pinapayagan ang app na basahin ang iyong koleksyon ng video."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"baguhin ang iyong koleksyon ng video"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Pinapayagan ang app na baguhin ang iyong koleksyon ng video."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"basahin ang iyong koleksyon ng larawan"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Pinapayagan ang app na basahin ang iyong koleksyon ng larawan."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"baguhin ang iyong koleksyon ng larawan"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Pinapayagan ang app na baguhin ang iyong koleksyon ng larawan."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"basahin ang mga lokasyon mula sa iyong koleksyon ng media"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Pinapayagan ang app na basahin ang mga lokasyon mula sa iyong koleksyon ng media."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hindi buo ang natukoy na fingerprint. Pakisubukang muli."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Hindi maproseso ang fingerprint. Pakisubukang muli."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Marumi ang sensor ng fingerprint. Pakilinis at subukang muli."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"I-save ang <xliff:g id="TYPE">%1$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g> at <xliff:g id="TYPE_1">%2$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, at <xliff:g id="TYPE_2">%3$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"I-update sa &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"I-update ang <xliff:g id="TYPE">%1$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"I-update ang <xliff:g id="TYPE_0">%1$s</xliff:g> at <xliff:g id="TYPE_1">%2$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"I-update ang <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, at <xliff:g id="TYPE_2">%3$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"I-save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Hindi, salamat na lang"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"I-update"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e15e52d..67991e1 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -133,7 +133,7 @@
     <item msgid="4397097370387921767">"%s Kablosuz Çağrı"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Kapalı"</string>
-    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Kablosuz bağlantı tercih edildi"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Kablosuz bağlantı tercihli"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobil tercihli"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Yalnızca kablosuz"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönlendirilmedi"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Uçak modu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uçak modu AÇIK"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Uçak modu KAPALI"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Pil tasarrufu"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Pil tasarrufu KAPALI"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Pil tasarrufu AÇIK"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Ayarlar"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Asist"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Sesli Yardım"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Vücut Sensörleri"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"hayati belirtilerinizle ilgili sensör verilerine erişme"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının hayati belirtilerinizle ilgili sensör verilerine erişmesine izin verilsin mi?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Müzik"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"müziğinize erişme"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının müziğinize erişmesine izin veriyor musunuz?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Fotoğraflar ve Videolar"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"fotoğraflarınıza ve videolarınıza erişme"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının fotoğraflarınıza ve videolarınıza erişmesine izin veriyor musunuz?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Pencere içeriğini alma"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Etkileşim kurduğunuz pencerenin içeriğini inceler."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Dokunarak Keşfet\'i açma"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Uygulamanın, kullanılacak parmak izi şablonlarını ekleme ve silme yöntemlerini başlatmasına izin verir."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"parmak izi donanımını kullanma"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Uygulamanın kimlik doğrulama için parmak izi donanımını kullanmasına izin verir."</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"müzik koleksiyonunuzu okuma"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Uygulamanın müzik koleksiyonunuzu okumasına izin verir."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"müzik koleksiyonunuzu değiştirme"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Uygulamanın müzik koleksiyonunuzu değiştirmesine izin verir."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"video koleksiyonunuzu okuma"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Uygulamanın video koleksiyonunuzu okumasına izin verir."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"video koleksiyonunuzu değiştirme"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Uygulamanın video koleksiyonunuzu değiştirmesine izin verir."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"fotoğraf koleksiyonunuzu okuma"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Uygulamanın fotoğraf koleksiyonunuzu okumasına izin verir."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"fotoğraf koleksiyonunuzu değiştirme"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Uygulamanın fotoğraf koleksiyonunuzu değiştirmesine izin verir."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"medya koleksiyonunuzdaki konumları okuma"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Uygulamanın medya koleksiyonunuzdaki konumları okumasına izin verir."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Parmak izinin tümü algılanamadı. Lütfen tekrar deneyin."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Parmak izi işlenemedi. Lütfen tekrar deneyin."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Parmak izi sensörü kirli. Lütfen temizleyin ve tekrar deneyin."</string>
@@ -641,7 +658,7 @@
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Kameraları devre dışı bırak"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Tüm cihaz kameralarının kullanımını engelleme."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Ekran kilidinin bazı özelliklerini devre dışı bırakma"</string>
-    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Ekran kilidinin bazı özelliklerinin kullanılmasını önleyin."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Ekran kilidinin bazı özelliklerinin kullanılmasını önleme."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Ev"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -1211,7 +1228,7 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"Kablosuz bağlantının internet erişimi yok"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Seçenekler için dokunun"</string>
-    <string name="wifi_softap_config_change" msgid="8475911871165857607">"Hotspot ayarlarınızı değiştirir"</string>
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"Hotspot ayarlarınız değişti"</string>
     <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"Hotspot bandı değişti."</string>
     <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Bu cihaz yalnızca 5 GHz bandının kullanılmasına yönelik tercihinizi desteklemiyor. Bunun yerine, bu cihaz 5 GHz bandını mevcut olduğunda kullanacak."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ağına geçildi"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; hizmetine kaydedilsin mi?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> ve <xliff:g id="TYPE_1">%2$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; hizmetine kaydedilsin mi?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; hizmetine kaydedilsin mi?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; hizmetine güncellensin mi?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; hizmetine güncellensin mi?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g>  ve <xliff:g id="TYPE_1">%2$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; hizmetine güncellensin mi?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;hizmetine güncellensin mi?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Kaydet"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Hayır, teşekkürler"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Güncelle"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"şifre"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"adres"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredi kartı"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index d9ec3fe..45b8dd4 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -242,9 +242,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим польоту"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим польоту ВВІМК."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим польоту ВИМК."</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Режим енергозбереження"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Режим економії заряду акумулятора ВИМКНЕНО"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Режим економії заряду акумулятора ВВІМКНЕНО"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Налаштування"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Підказки"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Голос. підказки"</string>
@@ -309,6 +306,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Датчики на тілі"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"отримувати доступ до інформації датчиків про ваші життєві показники"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до життєвих показників із датчиків?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Музика"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"доступ до музики"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до музики?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Фото й відео"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"доступ до фото й відео"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до фото й відео?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Отримувати вміст вікна"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Перевіряти вміст вікна, з яким ви взаємодієте."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Увімкнути функцію дослідження дотиком"</string>
@@ -503,6 +506,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Увімкнути в додатку функції для додавання й видалення шаблонів цифрових відбитків."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"використання сканера цифрових відбитків"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволити додатку використовувати апаратне забезпечення для автентифікації"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"розпізнавати колекцію музики"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Додаток зможе розпізнавати вашу колекцію музики."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"змінювати колекцію музики"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Додаток зможе змінювати вашу колекцію музики."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"розпізнавати колекцію відео"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Додаток зможе розпізнавати вашу колекцію відео."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"змінювати колекцію відео"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Додаток зможе змінювати вашу колекцію відео."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"розпізнавати колекцію фотографій"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Додаток зможе розпізнавати вашу колекцію фотографій."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"змінювати колекцію фотографій"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Додаток зможе змінювати вашу колекцію фотографій."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"розпізнавати геодані з колекції медіа-вмісту"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Додаток зможе розпізнавати геодані з вашої колекції медіа-вмісту."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Відбиток розпізнано частково. Повторіть спробу."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не вдалось обробити відбиток. Повторіть спробу."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Датчик відбитків забруднився. Очистьте його та повторіть спробу."</string>
@@ -1945,8 +1962,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Зберегти дані (<xliff:g id="TYPE">%1$s</xliff:g>) у службі &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g>) у службі &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>) у службі &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Оновити дані в сервісі &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Оновити дані (<xliff:g id="TYPE">%1$s</xliff:g>) у сервісі &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Оновити дані (<xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g>) у сервісі &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Оновити дані (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>) у сервісі &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Зберегти"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ні, дякую"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Оновити"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"пароль"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картка"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index ab5125e..fffad9b 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ہوائی جہاز وضع"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ہوائی جہاز وضع آن ہے"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"ہوائی جہاز وضع آف ہے"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"بیٹری سیور"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"بیٹری سیور آف ہے"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"بیٹری سیور آن ہے"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ترتیبات"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"اسسٹ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"باڈی سینسرز"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"اپنی علامات حیات کے متعلق سنسر ڈیٹا تک رسائی حاصل کریں"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے اہم اشاروں کے متعلق سینسر ڈیٹا تک رسائی کی اجازت دیں؟"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"موسیقی"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"اپنی موسیقی تک رسائی حاصل کریں"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کی موسیقی تک رسائی کی اجازت دیں؟"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"تصاویر اور ویڈیوز"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"اپنی تصاویر اور ویڈیوز تک رسائی حاصل کریں"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کی تصاویر اور ویڈیوز تک رسائی کی اجازت دیں؟"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ونڈو مواد بازیافت کرنے کی"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"کسی ایسی ونڈو کے مواد کا معائنہ کریں جس کے ساتھ آپ تعامل کر رہے ہیں۔"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ٹچ کے ذریعے دریافت کریں کو آن کرنے کی"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ایپ کو استعمال کیلئے فنگر پرنٹ کی تمثیلات شامل کرنے اور حذف کرنے کیلئے طریقوں کو کالعدم قرار دینے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"فنگر پرنٹ ہارڈ ویئر استعمال کریں"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ایپ کو توثیق کیلئے فنگر پرنٹ ہارڈ ویئر استعمال کرنے کی اجازت دیتا ہے"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"اپنے موسیقی کا مجموعہ پڑھیں"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"ایپ کو آپ کی موسیقی کا مجموعہ پڑھنے کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"اپنی موسیقی کے مجموعے میں ترمیم کریں"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"ایپ کو آپ کی موسیقی کے مجموعے میں ترمیم کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"اپنی ویڈیو کا مجموعہ پڑھیں"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"ایپ کو آپ کی ویڈیو کا مجموعہ پڑھنے کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"اپنی ویڈیو کے مجموعے میں ترمیم کریں"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"ایپ کو آپ کی ویڈیو کے مجموعے میں ترمیم کرنے کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"اپنی تصویر کا مجموعہ پڑھیں"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"ایپ کو آپ کی تصویر کا مجموعہ پڑھنے کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"اپنی تصویر کے مجموعے میں ترمیم کریں"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ایپ کو آپ کی تصویر کے مجموعے میں ترمیم کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"اپنی میڈيا کے مجموعے سے مقامات پڑھیں"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ایپ کو آپ کی میڈيا کے مجموعے سے مقامات پڑھنے کی اجازت دیتا ہے۔"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"جزوی فنگر پرنٹ کی شناخت ہوئی۔ براہ کرم دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"فنگر پرنٹ پر کارروائی نہیں کی جا سکی۔ براہ کرم دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"فنگر پرنٹ سینسر گندا ہے۔ براہ کرم صاف کریں اور دوبارہ کوشش کریں۔"</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"فنگر پرنٹ آئیکن"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"چہرے کی توثیق کے ہارڈویئر کا نظم کریں"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"ایپ کو چہرے کی تمثیلات شامل اور حذف کرنے کے طریقوں کو کالعدم قرار دینے کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"چہرے کی توثیق کا ہارڈویئر استعمال کریں"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"ایپ کو توثیق کیلئے چہرے کا ہارڈ ویئر استعمال کرنے کی اجازت دیتا ہے"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"چہرے پر کارروائی نہیں ہو سکی۔ دوبارہ کوشش کریں۔"</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"چہرے پر بہت زیادہ روشنی ہے۔ براہ کرم کم روشنی میں کوشش کریں۔"</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"چہرے پر روشنی بہت کم ہے۔ براہ کرم روشنی بڑھائیں۔"</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"براہ کرم سینسر کو چہرے سے تھوڑا دور رکھیں۔"</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"براہ کرم سینسر کو چہرے سے تھوڑا قریب رکھیں۔"</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"براہ کرم سینسر کو تھوڑا اوپر کریں۔"</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"براہ کرم سینسر کو تھوڑا نیچے کریں۔"</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"براہ کرم سینسر کو دائیں طرف کریں۔"</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"براہ کرم سینسر کو بائیں طرف کریں۔"</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"براہ کرم سینسر کی طرف دیکھیں۔"</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"کسی چہرے کا پتہ نہیں چلا۔"</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"آلہ کے سامنے چہرہ سیدھا رکھیں۔"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"چہرے کا ہارڈویئر دستیاب نہیں ہے۔"</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"چہرہ پہچانے کی میعاد ختم ہو گئی۔ دوبارہ کوشش کریں۔"</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"چہرے کو اسٹور نہیں کیا جا سکتا۔"</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"چہرے پر ہونے والی کارروائی منسوخ ہو گئی۔"</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"کافی زیادہ کوششیں کی گئیں۔ دوبارہ کوشش کریں۔"</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"کافی زیادہ کوششیں کی گئیں۔ چہرے کی توثیق منسوخ ہو گئی۔"</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"دوبارہ کوشش کریں۔"</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"کوئی بھی چہرہ مندرج نہیں ہے۔"</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"اس آلہ میں چہرے کی تصدیق کرنے والا سینسر نہیں ہے۔"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"چہرہ <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"چہرے کا آئیکن"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"مطابقت پذیری کی ترتیبات پڑھیں"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"‏ایپ کو کسی اکاؤنٹ کیلئے مطابقت پذیری کی ترتیبات پڑھنے کی اجازت دیتا ہے۔ مثلا، یہ تعین کرسکتا ہے کہ آیا People ایپ کسی اکاؤنٹ کے ساتھ مطابقت پذیر ہے۔"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"مطابقت پذیری آن اور آف ٹوگل کریں"</string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"‏Wi-Fi کو انٹرنیٹ تک رسائی نہیں ہے"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"اختیارات کیلئے تھپتھپائیں"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"اپنے ہاٹ اسپاٹ کی ترتیبات میں تبدیلیاں"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"آپ کا ہاٹ اسپات بینڈ تبدیل ہو گیا۔"</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"‏یہ آلہ صرف 5GHz کے لئے آپ کی ترجیح کا تعاون نہیں کرے گا۔ بلکہ 5GHz بینڈ کے دستیاب ہونے پر اس کا استعمال کرے گا۔"</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> پر سوئچ ہو گیا"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"جب <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> کو انٹرنیٹ تک رسائی نہیں ہوتی ہے تو آلہ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> کا استعمال کرتا ہے۔ چارجز لاگو ہو سکتے ہیں۔"</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> سے <xliff:g id="NEW_NETWORK">%2$s</xliff:g> پر سوئچ ہو گیا"</string>
@@ -1906,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‏<xliff:g id="TYPE">%1$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; میں محفوظ کریں؟"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‏<xliff:g id="TYPE_0">%1$s</xliff:g> اور <xliff:g id="TYPE_1">%2$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; میں محفوظ کریں؟"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‏<xliff:g id="TYPE_0">%1$s</xliff:g>،<xliff:g id="TYPE_1">%2$s</xliff:g>، اور <xliff:g id="TYPE_2">%3$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; میں محفوظ کریں؟"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"‏&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; میں اپ ڈیٹ کریں؟"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‏<xliff:g id="TYPE">%1$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; میں اپ ڈیٹ کریں؟"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‏<xliff:g id="TYPE_0">%1$s</xliff:g> اور <xliff:g id="TYPE_1">%2$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; میں اپ ڈیٹ کریں؟"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‏<xliff:g id="TYPE_0">%1$s</xliff:g>،<xliff:g id="TYPE_1">%2$s</xliff:g>، اور <xliff:g id="TYPE_2">%3$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; میں اپ ڈیٹ کریں؟"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"محفوظ کریں"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"نہیں، شکریہ"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"اپ ڈیٹ کریں"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"پاس ورڈ"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"پتہ"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"کریڈٹ کارڈ"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index e544942..684e78a 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -133,8 +133,8 @@
     <item msgid="4397097370387921767">"%s Wi-Fi qo‘ng‘iroqlar"</item>
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"O‘chiq"</string>
-    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi afzal ko‘rilsin"</string>
-    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobil internet ustivorligi"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi afzalligi"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobil internet afzalligi"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Faqat Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yo‘naltirilmadi"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Parvoz rejimi"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Parvoz usuli yoqilgan"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Parvoz rejimi o‘chirilgan"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Quvvat tejash rejimi"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Quvvat tejash rejimi YOQILMAGAN"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Quvvat tejash rejimi YONIQ"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Sozlamalar"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Yordam"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ovozli yordam"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Tana sezgichlari"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"organizm holati haqidagi sezgich ma’lumotlariga kirish"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun organizm holati haqidagi sezgichlar axborotlariga ruxsat berilsinmi?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Musiqa"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"musiqaga kirish"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun musiqangizga kirishga ruxsat berilsinmi?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Surat va videolar"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"surat va videolarga kirish"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun surat va videolaringizga kirishga ruxsat berilsinmi?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Oynadagi kontentni o‘qiydi"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Joriy oynadagi kontent mazmunini aniqlaydi."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Teginib o‘rganish xizmatini yoqadi"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Ilova foydalanish uchun barmoq izi namunalarini qo‘shish va o‘chirish usullarini qo‘llashi mumkin."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"barmoq izi sensoridan foydalanish"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Ilova haqiqiylikni tekshirish uchun barmoq izi sensoridan foydalanishi mumkin"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"musiqiy to‘plamni o‘qish"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Ilovaga musiqiy to‘plamingizni o‘qishga ruxsat beradi."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"musiqiy to‘plamni o‘zgartirish"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Ilovaga musiqiy to‘plamni o‘zgartirishga ruxsat beradi."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"video to‘plamni o‘qish"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Ilovaga video to‘plamingizni o‘qishga ruxsat beradi."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"video to‘plamni o‘zgartirish"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Ilovaga video to‘plamingizni o‘zgartirishga ruxsat beradi."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"suratlar to‘plamini o‘qish"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Ilovaga suratlar to‘plamingizni o‘qishga ruxsat beradi."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"suratlar to‘plamini o‘zgartirish"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Ilovaga suratlar to‘plamingizni o‘zgartirishga ruxsat beradi."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"multimedia to‘plamidan joylashuv axborotini o‘qish"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Ilovaga multimedia to‘plamingizdan joylashuv axborotini o‘qishga ruxsat beradi."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmoq izi qisman aniqlandi. Qayta urinib ko‘ring."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Barmoq izi aniqlanmadi. Qayta urinib ko‘ring."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Barmoq izi skaneri kirlangan. Uni tozalab, keyin qayta urinib ko‘ring."</string>
@@ -1164,7 +1181,7 @@
     <string name="dump_heap_text" msgid="4809417337240334941">"<xliff:g id="PROC">%1$s</xliff:g> jarayoni o‘zi uchun ajratilgan <xliff:g id="SIZE">%2$s</xliff:g> xotira chegarasidan o‘tib ketdi. Ilova dasturchisi bilan ulashishingiz uchun hip-damp ma’lumotlari yig‘ilib qoldi. Ehtiyot bo\'ling: ushbu hip-dampda ilova uchun foydalanishga ruxsat berilgan shaxsiy ma’lumotlaringiz bo‘lishi mumkin."</string>
     <string name="sendText" msgid="5209874571959469142">"Matn uchun amalni tanlash"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Jiringlaganda tovush balandligi"</string>
-    <string name="volume_music" msgid="5421651157138628171">"Multimedia ovozi"</string>
+    <string name="volume_music" msgid="5421651157138628171">"Multimedia tovushi"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Bluetooth orqali ijro etilmoqda"</string>
     <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Ovozsiz rejim tanlandi"</string>
     <string name="volume_call" msgid="3941680041282788711">"Suhbat vaqtidagi tovush balandligi"</string>
@@ -1175,7 +1192,7 @@
     <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"Bluetooth tovushi"</string>
     <string name="volume_icon_description_ringer" msgid="3326003847006162496">"Rington balandligi"</string>
     <string name="volume_icon_description_incall" msgid="8890073218154543397">"Qo‘ng‘iroq tovushi balandligi"</string>
-    <string name="volume_icon_description_media" msgid="4217311719665194215">"Multimedia ovozi"</string>
+    <string name="volume_icon_description_media" msgid="4217311719665194215">"Multimedia tovushi"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Eslatma tovushi"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standart rington"</string>
     <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Standart (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
@@ -1213,7 +1230,7 @@
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Variantlarni ko‘rsatish uchun bosing"</string>
     <string name="wifi_softap_config_change" msgid="8475911871165857607">"Hotspot sozlamalari o‘zgartirildi"</string>
     <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"Hotspot chastotasi o‘zgartirildi."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Qurilma faqat 5 GGs chastotasida ishlay olmaydi. Imkon qadar bu chastotadan foydalaniladi."</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"Qurilma faqat 5 GGs chastotada ishlay olmaydi. Bu chastotadan imkoniyatga qarab foydalaniladi."</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> tarmog‘iga ulanildi"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"Agar <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tarmoqda internet uzilsa, qurilma <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ga ulanadi. Sarflangan trafik uchun haq olinishi mumkin."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> tarmog‘idan <xliff:g id="NEW_NETWORK">%2$s</xliff:g> tarmog‘iga o‘tildi"</string>
@@ -1876,8 +1893,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; xizmatiga saqlansinmi?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> va <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; xizmatiga saqlansinmi?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> va <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; xizmatiga saqlansinmi?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; xizmatidagi ma’lumot yangilansinmi?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; xizmatida <xliff:g id="TYPE">%1$s</xliff:g> ma’lumotlari yangilansinmi?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; xizmatidagi <xliff:g id="TYPE_0">%1$s</xliff:g> va <xliff:g id="TYPE_1">%2$s</xliff:g> ma’lumotlari yangilansinmi?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; xizmatidagi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> va <xliff:g id="TYPE_2">%3$s</xliff:g> ma’lumotlari yangilansinmi?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Saqlash"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Kerak emas"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Yangilash"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"parol"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"manzil"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredit karta"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 54a7e76..b106ec5 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -134,7 +134,7 @@
   </string-array>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Tắt"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Ưu tiên Wi-Fi"</string>
-    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Được ưu tiên trên thiết bị di động"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Ưu tiên dữ liệu di động"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Chỉ Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Không được chuyển tiếp"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Chế độ trên máy bay"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Chế độ trên máy bay BẬT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Chế độ trên máy bay TẮT"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Trình tiết kiệm pin"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Trình tiết kiệm pin đang TẮT"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Trình tiết kiệm pin đang BẬT"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Cài đặt"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Hỗ trợ"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Trợ lý thoại"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Cảm biến cơ thể"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"truy cập dữ liệu cảm biến về dấu hiệu sinh tồn của bạn"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào dữ liệu cảm biến về các dấu hiệu sinh tồn của bạn?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Nhạc"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"sử dụng nhạc"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Bạn có muốn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sử dụng nhạc không?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Ảnh và video"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"sử dụng ảnh và video"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Bạn có muốn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sử dụng ảnh và video không?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Truy xuất nội dung cửa sổ"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Kiểm tra nội dung của cửa sổ bạn đang tương tác."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Bật Khám phá bằng cách chạm"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Cho phép ứng dụng gọi các phương pháp để thêm và xóa các mẫu vân tay để sử dụng."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"sử dụng phần cứng vân tay"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Cho phép ứng dụng sử dụng phần cứng vân tay để xác thực"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"đọc bộ sưu tập nhạc"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Cho phép ứng dụng này đọc bộ sưu tập nhạc của bạn."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"sửa đổi bộ sưu tập nhạc"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Cho phép ứng dụng này sửa đổi bộ sưu tập nhạc của bạn."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"đọc bộ sưu tập video"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Cho phép ứng dụng này đọc bộ sưu tập video của bạn."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"sửa đổi bộ sưu tập video"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Cho phép ứng dụng này sửa đổi bộ sưu tập video của bạn."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"đọc bộ sưu tập ảnh"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Cho phép ứng dụng này đọc bộ sưu tập ảnh của bạn."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"sửa đổi bộ sưu tập ảnh"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Cho phép ứng dụng này sửa đổi bộ sưu tập ảnh của bạn."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"đọc vị trí từ bộ sưu tập phương tiện"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Cho phép ứng dụng này đọc vị trí từ bộ sưu tập phương tiện của bạn."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Đã phát hiện được một phần vân tay. Vui lòng thử lại."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Không thể xử lý vân tay. Vui lòng thử lại."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Cảm biến vân tay bị bẩn. Hãy làm sạch và thử lại."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Lưu <xliff:g id="TYPE">%1$s</xliff:g> vào &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g> và <xliff:g id="TYPE_1">%2$s</xliff:g> vào &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> và <xliff:g id="TYPE_2">%3$s</xliff:g> vào &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Bạn có muốn cập nhật cho &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; không?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Bạn có muốn cập nhật <xliff:g id="TYPE">%1$s</xliff:g> cho &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; không?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Bạn có muốn cập nhật <xliff:g id="TYPE_0">%1$s</xliff:g> và <xliff:g id="TYPE_1">%2$s</xliff:g> cho &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; không?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Bạn có muốn cập nhật <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> và <xliff:g id="TYPE_2">%3$s</xliff:g> cho &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; không?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Lưu"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Không, cảm ơn"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Cập nhật"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"mật khẩu"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"địa chỉ"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"thẻ tín dụng"</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index 8e82479..a96a96d 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -64,9 +64,8 @@
          Set to true for watch devices. -->
     <bool name="config_focusScrollContainersInTouchMode">true</bool>
 
-    <!-- Enable generic multi-window in order to support Activity in virtual display. -->
-    <bool name="config_supportsMultiWindow">true</bool>
-    <bool name="config_supportsMultiDisplay">true</bool>
+    <bool name="config_supportsMultiWindow">false</bool>
+    <bool name="config_supportsMultiDisplay">false</bool>
     <bool name="config_supportsSplitScreenMultiWindow">false</bool>
 
      <!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER -->
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index e498c03..5aca3ff 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飞行模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"已开启飞行模式"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"未开启飞行模式"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"省电模式"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"省电模式已关闭"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"省电模式已开启"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"设置"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"助手应用"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"语音助理"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"身体传感器"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"访问与您的生命体征相关的传感器数据"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问与您的生命体征相关的传感器数据吗?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"音乐"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"访问您的音乐"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问您的音乐吗?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"照片和视频"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"访问您的照片和视频"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问您的照片和视频吗?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"检索窗口内容"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"检测您正访问的窗口的内容。"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"启用触摸浏览"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"允许该应用调用方法来添加和删除可用的指纹模板。"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"使用指纹硬件"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"允许该应用使用指纹硬件进行身份验证"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"读取您的音乐收藏"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"允许该应用读取您的音乐收藏。"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"修改您的音乐收藏"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"允许该应用修改您的音乐收藏。"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"读取您的视频收藏"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"允许该应用读取您的视频收藏。"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"修改您的视频收藏"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"允许该应用修改您的视频收藏。"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"读取您的照片收藏"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"允许该应用读取您的照片收藏。"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"修改您的照片收藏"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"允许该应用修改您的照片收藏。"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"从您的媒体收藏中读取位置信息"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"允许该应用从您的媒体收藏中读取位置信息。"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"仅检测到部分指纹,请重试。"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"无法处理指纹,请重试。"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"指纹传感器有脏污。请擦拭干净,然后重试。"</string>
@@ -520,64 +537,37 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"指纹图标"</string>
-    <!-- no translation found for permlab_manageFace (2137540986007309781) -->
-    <skip />
-    <!-- no translation found for permdesc_manageFace (8919637120670185330) -->
-    <skip />
-    <!-- no translation found for permlab_useFaceAuthentication (8996134460546804535) -->
-    <skip />
-    <!-- no translation found for permdesc_useFaceAuthentication (5011118722951833089) -->
-    <skip />
-    <!-- no translation found for face_acquired_insufficient (5901287247766106330) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_bright (610606792381297174) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_dark (7229162716976778371) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_close (1980310037427755293) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_far (4494571381828850007) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_high (228411096134808372) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_low (4539774649296349109) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_right (1650292067226118760) -->
-    <skip />
-    <!-- no translation found for face_acquired_too_left (2712489669456176505) -->
-    <skip />
-    <!-- no translation found for face_acquired_poor_gaze (8344973502980415859) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_detected (5707782294589511391) -->
-    <skip />
-    <!-- no translation found for face_acquired_not_steady (3722829465011040042) -->
-    <skip />
+    <string name="permlab_manageFace" msgid="2137540986007309781">"管理人脸身份验证硬件"</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"允许该应用调用方法来添加和删除可用的人脸模板。"</string>
+    <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"使用人脸身份验证硬件"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"允许该应用使用人脸身份验证硬件进行身份验证"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"无法识别此面孔,请重试。"</string>
+    <string name="face_acquired_too_bright" msgid="610606792381297174">"面部太亮,请在光线适中的环境下重试。"</string>
+    <string name="face_acquired_too_dark" msgid="7229162716976778371">"面部太暗,请不要挡住光线。"</string>
+    <string name="face_acquired_too_close" msgid="1980310037427755293">"请将传感器移到距离面孔较远处。"</string>
+    <string name="face_acquired_too_far" msgid="4494571381828850007">"请将传感器靠近面孔。"</string>
+    <string name="face_acquired_too_high" msgid="228411096134808372">"请上移传感器。"</string>
+    <string name="face_acquired_too_low" msgid="4539774649296349109">"请下移传感器。"</string>
+    <string name="face_acquired_too_right" msgid="1650292067226118760">"请右移传感器。"</string>
+    <string name="face_acquired_too_left" msgid="2712489669456176505">"请左移传感器。"</string>
+    <string name="face_acquired_poor_gaze" msgid="8344973502980415859">"请目视传感器。"</string>
+    <string name="face_acquired_not_detected" msgid="5707782294589511391">"未检测到任何面孔。"</string>
+    <string name="face_acquired_not_steady" msgid="3722829465011040042">"请将面孔保持在设备前不动。"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <!-- no translation found for face_error_hw_not_available (6255891785768984615) -->
-    <skip />
-    <!-- no translation found for face_error_timeout (4014326147867150054) -->
-    <skip />
-    <!-- no translation found for face_error_no_space (8224993703466381314) -->
-    <skip />
-    <!-- no translation found for face_error_canceled (283945501061931023) -->
-    <skip />
-    <!-- no translation found for face_error_lockout (3407426963155388504) -->
-    <skip />
-    <!-- no translation found for face_error_lockout_permanent (8198354656746088890) -->
-    <skip />
-    <!-- no translation found for face_error_unable_to_process (238761109287767270) -->
-    <skip />
-    <!-- no translation found for face_error_not_enrolled (9166792142679691323) -->
-    <skip />
-    <!-- no translation found for face_error_hw_not_present (4737289254517095671) -->
-    <skip />
-    <!-- no translation found for face_name_template (7004562145809595384) -->
-    <skip />
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"无法使用面孔识别硬件"</string>
+    <string name="face_error_timeout" msgid="4014326147867150054">"面孔处理操作超时,请重试。"</string>
+    <string name="face_error_no_space" msgid="8224993703466381314">"无法存储面孔。"</string>
+    <string name="face_error_canceled" msgid="283945501061931023">"面孔处理操作已取消。"</string>
+    <string name="face_error_lockout" msgid="3407426963155388504">"尝试次数过多,请稍后重试。"</string>
+    <string name="face_error_lockout_permanent" msgid="8198354656746088890">"尝试次数过多,系统已停用人脸身份验证功能。"</string>
+    <string name="face_error_unable_to_process" msgid="238761109287767270">"请重试。"</string>
+    <string name="face_error_not_enrolled" msgid="9166792142679691323">"未注册任何面孔。"</string>
+    <string name="face_error_hw_not_present" msgid="4737289254517095671">"此设备没有人脸身份验证传感器"</string>
+    <string name="face_name_template" msgid="7004562145809595384">"面孔 <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <!-- no translation found for face_icon_content_description (4024817159806482191) -->
-    <skip />
+    <string name="face_icon_content_description" msgid="4024817159806482191">"面孔图标"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"读取同步设置"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"允许该应用读取某个帐号的同步设置。例如,此权限可确定“联系人”应用是否与某个帐号同步。"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"启用和停用同步"</string>
@@ -1238,12 +1228,9 @@
     <skip />
     <string name="wifi_no_internet" msgid="8938267198124654938">"此 WLAN 网络无法访问互联网"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"点按即可查看相关选项"</string>
-    <!-- no translation found for wifi_softap_config_change (8475911871165857607) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_summary (7601233252456548891) -->
-    <skip />
-    <!-- no translation found for wifi_softap_config_change_detailed (8022936822860678033) -->
-    <skip />
+    <string name="wifi_softap_config_change" msgid="8475911871165857607">"您的热点设置已变更"</string>
+    <string name="wifi_softap_config_change_summary" msgid="7601233252456548891">"您的热点频段已变更。"</string>
+    <string name="wifi_softap_config_change_detailed" msgid="8022936822860678033">"此设备不支持您的偏好设置(仅限 5GHz),而且会在 5GHz 频段可用时使用该频段。"</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"已切换至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
     <string name="network_switch_metered_detail" msgid="775163331794506615">"设备会在<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>无法访问互联网时使用<xliff:g id="NEW_NETWORK">%1$s</xliff:g>(可能需要支付相应的费用)。"</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"已从<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>切换至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
@@ -1905,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"要将<xliff:g id="TYPE">%1$s</xliff:g>保存到&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;吗?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>保存到&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;吗?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>保存到&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;吗?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"要更新到&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;吗?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"要将<xliff:g id="TYPE">%1$s</xliff:g>更新到&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;吗?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>更新到&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;吗?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>更新到&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;吗?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"保存"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"不用了"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"更新"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"密码"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"地址"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"信用卡"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index cb32875..79c9cc4 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飛行模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"飛航模式為 [開啟]"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"飛行模式為 [關閉]"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"省電模式"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"省電模式已關閉"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"省電模式已開啟"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"設定"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"小幫手"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"語音助手"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"人體感應器"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"存取與您生命體徵相關的感應器資料"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取與您身體機能相關的感應器資料嗎?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"音樂"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"存取您的音樂"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"要允許「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」存取您的音樂嗎?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"相片和影片"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"存取您的相片和影片"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"要允許「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」存取您的相片和影片嗎?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"擷取視窗內容"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"檢查您使用中的視窗內容。"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"開啟「輕觸探索」功能"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"允許應用程式調用加入和刪除指紋模板的方法以供使用。"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"使用指紋硬件"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"允許應用程式使用指紋硬件驗證"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"讀取您的音樂收藏"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"允許應用程式讀取您的音樂收藏。"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"修改您的音樂收藏"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"允許應用程式修改您的音樂收藏。"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"讀取您的影片集"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"允許應用程式讀取您的影片集。"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"修改您的影片集"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"允許應用程式修改您的影片集。"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"讀取您的相片集"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"允許應用程式讀取您的相片集。"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"修改您的相片集"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"允許應用程式修改您的相片集。"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"讀取媒體集的位置"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"允許應用程式讀取媒體集的位置。"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"只偵測到部分指紋。請再試一次。"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"無法處理指紋。請再試一次。"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"指紋感應器不乾淨。請清潔後再試一次。"</string>
@@ -1775,7 +1792,7 @@
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"直至您關閉「請勿騷擾」功能"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
     <string name="toolbar_collapse_description" msgid="2821479483960330739">"收合"</string>
-    <string name="zen_mode_feature_name" msgid="5254089399895895004">"請勿干擾"</string>
+    <string name="zen_mode_feature_name" msgid="5254089399895895004">"請勿騷擾"</string>
     <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"休息時間"</string>
     <string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"平日夜間"</string>
     <string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"週末"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存至「&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;」嗎?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>儲存至「&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;」嗎?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>儲存至「&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;」嗎?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"要更新至 &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; 嗎?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"要將<xliff:g id="TYPE">%1$s</xliff:g>更新至 &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; 嗎?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>更新至 &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; 嗎?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>更新至 &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; 嗎?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"更新"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"密碼"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"地址"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"信用卡"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index b6e71cf..5143718 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飛航模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"飛航模式為 [開啟]"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"飛航模式為 [關閉]"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"節約耗電量"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"節約耗電量模式已關閉"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"節約耗電量模式已開啟"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"設定"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"協助"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"語音小幫手"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"人體感應器"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"存取與你生命徵象相關的感應器資料"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取與你生命徵象相關的感應器資料嗎?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"音樂"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"存取你的音樂"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你的音樂嗎?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"相片和影片"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"存取你的相片和影片"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你的相片和影片嗎?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"擷取視窗內容"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"檢查你存取的視窗內容。"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"啟用輕觸探索功能"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"允許應用程式呼叫方法來新增及移除可用的指紋範本"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"使用指紋硬體"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"允許應用程式使用指紋硬體進行驗證"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"讀取你的音樂收藏"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"允許應用程式讀取你的音樂收藏。"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"修改你的音樂收藏"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"允許應用程式修改你的音樂收藏。"</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"讀取你的影片收藏"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"允許應用程式讀取你的影片收藏。"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"修改你的影片收藏"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"允許應用程式修改你的影片收藏。"</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"讀取你的相片收藏"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"允許應用程式讀取你的相片收藏。"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"修改你的相片收藏"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"允許應用程式修改你的相片收藏。"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"讀取你的媒體收藏的位置資訊"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"允許應用程式讀取你的媒體收藏的位置資訊。"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"僅偵測到部分指紋,請再試一次。"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"無法處理指紋,請再試一次。"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"指紋感應器有髒汙。請清潔感應器,然後再試一次。"</string>
@@ -524,7 +541,7 @@
     <string name="permdesc_manageFace" msgid="8919637120670185330">"允許應用程式呼叫方法來新增及移除可用的臉孔範本。"</string>
     <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"使用臉孔驗證硬體"</string>
     <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"允許應用程式使用臉孔驗證硬體進行驗證"</string>
-    <string name="face_acquired_insufficient" msgid="5901287247766106330">"無法處理臉孔,請再試一次。"</string>
+    <string name="face_acquired_insufficient" msgid="5901287247766106330">"無法識別臉孔,請再試一次。"</string>
     <string name="face_acquired_too_bright" msgid="610606792381297174">"臉孔過亮。請移至光線適中的場所,然後再試一次。"</string>
     <string name="face_acquired_too_dark" msgid="7229162716976778371">"臉孔過暗。請增添光源,然後再試一次。"</string>
     <string name="face_acquired_too_close" msgid="1980310037427755293">"請將感應器移到距離臉孔較遠處。"</string>
@@ -538,7 +555,7 @@
     <string name="face_acquired_not_steady" msgid="3722829465011040042">"請將臉孔保持在裝置前方。"</string>
   <string-array name="face_acquired_vendor">
   </string-array>
-    <string name="face_error_hw_not_available" msgid="6255891785768984615">"無法使用臉孔硬體。"</string>
+    <string name="face_error_hw_not_available" msgid="6255891785768984615">"無法使用臉部辨識硬體。"</string>
     <string name="face_error_timeout" msgid="4014326147867150054">"臉孔處理作業逾時,請再試一次。"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"無法儲存臉孔。"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"臉孔處理作業已取消。"</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存到「<xliff:g id="LABEL">%2$s</xliff:g>」嗎?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>儲存到「<xliff:g id="LABEL">%3$s</xliff:g>」嗎?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>儲存到「<xliff:g id="LABEL">%4$s</xliff:g>」嗎?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"要更新「<xliff:g id="LABEL">%1$s</xliff:g>」中的資料嗎?&lt;b&gt;&lt;/b&gt;"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"要更新「<xliff:g id="LABEL">%2$s</xliff:g>」中的<xliff:g id="TYPE">%1$s</xliff:g>嗎?&lt;b&gt;&lt;/b&gt;"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"要更新「<xliff:g id="LABEL">%3$s</xliff:g>」中的<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>嗎?&lt;b&gt;&lt;/b&gt;"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"要更新「<xliff:g id="LABEL">%4$s</xliff:g>」中的<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>嗎?&lt;b&gt;&lt;/b&gt;"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"更新"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"密碼"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"地址"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"信用卡"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 85c63b9..fbe0dc7 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -236,9 +236,6 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Imodi yendiza"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Imodi yendiza IVULIWE"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Imodi yendiza IVALIWE"</string>
-    <string name="global_action_toggle_battery_saver" msgid="708515500418994208">"Isilondolozi sebhethri"</string>
-    <string name="global_action_battery_saver_on_status" msgid="484059130698197787">"Iseva yebhethri SIVALIWE"</string>
-    <string name="global_action_battery_saver_off_status" msgid="75550964969478405">"Isilondolozi sebhethri SIVULIWE"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Izilungiselelo"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Siza"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Isisekeli sezwi"</string>
@@ -303,6 +300,12 @@
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Izinzwa zomzimba"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"finyelela idatha yesizweli mayelana nezimpawu zakho ezibalulekile"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele kudatha yenzwa emayelana nezimpawu zakho ezibalulekile?"</string>
+    <string name="permgrouplab_aural" msgid="965607064083134896">"Umculo"</string>
+    <string name="permgroupdesc_aural" msgid="4870189506255958055">"finyelela umculo wakho"</string>
+    <string name="permgrouprequest_aural" msgid="6787926123071735620">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele umculo wakho?"</string>
+    <string name="permgrouplab_visual" msgid="8030190588123857921">"Izithombe namavidiyo"</string>
+    <string name="permgroupdesc_visual" msgid="3415827902566663546">"finyelela izithombe zakho namavidiyo"</string>
+    <string name="permgrouprequest_visual" msgid="6907523945030290376">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele kuzithombe zakho namavidiyo?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Thola okuqukethwe kwewindi"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Hlola okuqukethwe kwewindi ohlanganyela nalo."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Vula ukuhlola ngokuthinta"</string>
@@ -497,6 +500,20 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Ivumela uhlelo lokusebenza ukuthi libuyisele izindlela zokungeza nokususa izifanekiso zezigxivizo zeminwe ngokusetshenziswa."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"sebenzisa izingxenyekazi zekhompyutha zezigxivizo zeminwe"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Ivumela uhlelo lokusebenza ukuthi lusebenzise izingxenyekazi zekhompyutha zezigxivizo zeminwe ukuze kuqinisekiswe"</string>
+    <string name="permlab_audioRead" msgid="6617225220728465565">"funda iqoqo lakho lomculo"</string>
+    <string name="permdesc_audioRead" msgid="5034032570243484805">"Ivumela uhlelo lokusebenza ukuthi lifunde iqoqo lakho lomculo."</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"lungisa iqoqo lakho lomculo"</string>
+    <string name="permdesc_audioWrite" msgid="8888544708166230494">"Ivumela uhlelo lwakho lokusebenza ukuthi lilungise iqoqo lakho lomculo."</string>
+    <string name="permlab_videoRead" msgid="9182618678674737229">"funda iqoqo lakho levidiyo"</string>
+    <string name="permdesc_videoRead" msgid="7045676429859396194">"Ivumela uhlelo lokusebenza ukuthi lifunde iqoqo lakho levidiyo."</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"lungisa iqoqo lakho levidiyo"</string>
+    <string name="permdesc_videoWrite" msgid="5448565757490640841">"Ivumela uhlelo lwakho lokusebenza ukuthi lilungise iqoqo lakho levidiyo."</string>
+    <string name="permlab_imagesRead" msgid="3015078545742665304">"funda iqoqo lakho lesithombe"</string>
+    <string name="permdesc_imagesRead" msgid="3144263806038695580">"Ivumela uhlelo lokusebenza ukuthi lifunde iqoqo lakho lesithombe."</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"lungisa iqoqo lakho lesithombe"</string>
+    <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Ivumela uhlelo lwakho lokusebenza ukuthi lilungise iqoqo lakho lesithombe."</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"funda izindawo kusukela kuqoqo lakho lemidiya"</string>
+    <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Ivumela uhlelo lokusebenza ukuthi lifunde izindawo kusukela kuqoqo lakho lemidiya."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Izigxivizo zeminwe ezincane zitholiwe. Sicela uzame futhi."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Ayikwazanga ukucubungula izigxivizo zeminwe. Sicela uzame futhi."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Inzwa yezigxivizo zeminwe ingcolile. Sicela uyihlanze uphinde uzame futhi."</string>
@@ -1875,8 +1892,13 @@
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Londoloza i-<xliff:g id="TYPE">%1$s</xliff:g> ku-&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g> ne-<xliff:g id="TYPE_1">%2$s</xliff:g> ku-&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ne-<xliff:g id="TYPE_2">%3$s</xliff:g> ku-&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title" msgid="4879673117448810818">"Buyekezela ku-&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Buyekeza i-<xliff:g id="TYPE">%1$s</xliff:g> ukuya ku-&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Buyekeza i-<xliff:g id="TYPE_0">%1$s</xliff:g> ne-<xliff:g id="TYPE_1">%2$s</xliff:g> ukuya ku-&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Buyekeza i-<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ne-<xliff:g id="TYPE_2">%3$s</xliff:g> ukuya ku-&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Londoloza"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Cha ngiyabonga"</string>
+    <string name="autofill_update_yes" msgid="310358413273276958">"Buyekeza"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"iphasiwedi"</string>
     <string name="autofill_save_type_address" msgid="4936707762193009542">"ikheli"</string>
     <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ikhadi lesikweletu"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d2684ce..2f710bf 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1477,7 +1477,7 @@
              used for, typically, account ID or password input.  It is expected that IMEs
              normally are able to input ASCII even without being told so (such IMEs
              already respect this flag in a sense), but there could be some cases they
-             aren't when, for instance, only non-ASCII input languagaes like Arabic,
+             aren't when, for instance, only non-ASCII input languages like Arabic,
              Greek, Hebrew, Russian are enabled in the IME.  Applications need to be
              aware that the flag is not a guarantee, and not all IMEs will respect it.
              However, it is strongly recommended for IME authors to respect this flag
@@ -3113,6 +3113,9 @@
              the alpha channel of the outlineAmbientShadowColor (typically opaque), and the
              {@link android.R.attr#ambientShadowAlpha} theme attribute. -->
         <attr name="outlineAmbientShadowColor" format="color" />
+
+        <!-- Whether to allow the rendering system to force this View to render as light-on-dark. -->
+        <attr name="allowForceDark" format="boolean" />
     </declare-styleable>
 
     <!-- Attributes that can be assigned to a tag for a particular View. -->
@@ -3161,7 +3164,7 @@
              enabled by a ViewGroup for all its children in specific situations (for
              instance during a scrolling.) This property lets you persist the cache
              in memory after its initial usage. Persisting the cache consumes more
-             memory but may prevent frequent garbage collection is the cache is created
+             memory but may prevent frequent garbage collection if the cache is created
              over and over again. By default the persistence is set to scrolling.
              Deprecated: The view drawing cache was largely made obsolete with the introduction of
              hardware-accelerated rendering in API 11. -->
@@ -7863,8 +7866,7 @@
              wallpaper. -->
         <attr name="showMetadataInPreview" format="boolean" />
 
-        <!-- Wallpapers optimized and capable of drawing in ambient mode will return true.
-            @hide -->
+        <!-- Wallpapers optimized and capable of drawing in ambient mode will return true. -->
         <attr name="supportsAmbientMode" format="boolean" />
 
     </declare-styleable>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 4c96c1b..74663c9 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1358,7 +1358,10 @@
     <!-- Specifies the target sandbox this app wants to use. Higher sandbox versions
          will have increasing levels of security.
 
-         <p>The default value of this attribute is <code>1</code>. -->
+         <p>The default value of this attribute is <code>1</code>.
+         <p>
+         @deprecated The security properties have been moved to
+         {@link android.os.Build.VERSION Build.VERSION} 27 and 28. -->
     <attr name="targetSandboxVersion" format="integer" />
 
     <!-- The user-visible SDK version (ex. 26) of the framework against which the application was
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index aef48fa..289c898 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -551,9 +551,6 @@
          radio is unable to find any MCC information to infer wifi country code from -->
     <bool translatable="false" name="config_wifi_revert_country_code_on_cellular_loss">false</bool>
 
-    <!-- Boolean indicating whether or not wifi firmware debugging is enabled -->
-    <bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">true</bool>
-
     <!-- Integer size limit, in KB, for a single WifiLogger ringbuffer, in default logging mode -->
     <integer translatable="false" name="config_wifi_logger_ring_buffer_default_size_limit_kb">32</integer>
 
@@ -583,18 +580,16 @@
     <integer translatable="false" name="config_wifi_framework_min_rx_rate_for_staying_on_network">16</integer>
     <!-- Integer parameters of the wifi to cellular handover feature
          wifi should not stick to bad networks -->
-    <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz">-82</integer>
-    <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz">-82</integer>
+    <!-- Integer threshold for low network score, should be somewhat less than the entry threshhold -->
+    <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz">-80</integer>
+    <!-- Integer threshold, do not connect to APs with RSSI lower than the entry threshold -->
+    <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz">-77</integer>
     <integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_5GHz">-70</integer>
     <integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_5GHz">-57</integer>
-    <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz">-85</integer>
-    <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz">-85</integer>
+    <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz">-83</integer>
+    <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz">-80</integer>
     <integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz">-73</integer>
     <integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz">-60</integer>
-    <integer translatable="false" name="config_wifi_framework_wifi_score_bad_link_speed_24">6</integer>
-    <integer translatable="false" name="config_wifi_framework_wifi_score_bad_link_speed_5">12</integer>
-    <integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_24">24</integer>
-    <integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_5">36</integer>
 
     <!-- Integer delay in milliseconds before shutting down soft AP when there
          are no connected devices. Framework will enforce a minimum limit on
@@ -670,6 +665,10 @@
     <!-- Boolean indicating whether framework needs to set the tx power limit for meeting SAR requirements -->
     <bool translatable="false" name="config_wifi_framework_enable_sar_tx_power_limit">false</bool>
 
+    <!-- Boolean indicating whether framework should use detection of softAP mode to set the tx
+         power limit for meeting SAR requirements -->
+    <bool translatable="false" name="config_wifi_framework_enable_soft_ap_sar_tx_power_limit">false</bool>
+
     <!-- Boolean indicating whether framework needs to use body proximity to set the tx power limit
          for meeting SAR requirements -->
     <bool translatable="false" name="config_wifi_framework_enable_body_proximity_sar_tx_power_limit">false</bool>
@@ -1869,6 +1868,10 @@
          truncate it after committing the transaction. -->
     <integer name="db_journal_size_limit">524288</integer>
 
+    <!-- When opening a database with WAL enabled and if the wal file already exists and larger
+         than this size in bytes, we'll truncate it. -->
+    <integer name="db_wal_truncate_size">1048576</integer>
+
     <!-- The database synchronization mode when using the default journal mode.
          FULL is safest and preserves durability at the cost of extra fsyncs.
          NORMAL also preserves durability in non-WAL modes and uses checksums to ensure
@@ -2106,6 +2109,9 @@
     <!-- Type of the long press sensor. Empty if long press is not supported. -->
     <string name="config_dozeLongPressSensorType" translatable="false"></string>
 
+    <!-- Type of the reach sensor. Empty if reach is not supported. -->
+    <string name="config_dozeReachSensorType" translatable="false"></string>
+
     <!-- Control whether the always on display mode is available. This should only be enabled on
          devices where the display has been tuned to be power efficient in DOZE and/or DOZE_SUSPEND
          states. -->
@@ -2357,6 +2363,9 @@
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
     <bool name="config_safe_media_volume_enabled">true</bool>
 
+    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). -->
+    <bool name="config_safe_media_disable_on_volume_up">true</bool>
+
     <!-- Set to true if the wifi display supports compositing content stored
          in gralloc protected buffers.  For this to be true, there must exist
          a protected hardware path for surface flinger to composite and send
@@ -2492,6 +2501,7 @@
         <item>com.android.server.notification.VisibilityExtractor</item>
         <!-- Depends on ZenModeExtractor -->
         <item>com.android.server.notification.BadgeExtractor</item>
+        <item>com.android.server.notification.CriticalNotificationExtractor</item>
 
     </string-array>
 
@@ -2730,6 +2740,9 @@
          empty string is passed in -->
     <string name="config_ims_package"/>
 
+    <!-- String array containing numbers that shouldn't be logged. Country-specific. -->
+    <string-array name="unloggable_phone_numbers" />
+
     <!-- Flag specifying whether or not IMS will use the dynamic ImsResolver -->
     <bool name="config_dynamic_bind_ims">false</bool>
 
@@ -2966,11 +2979,23 @@
          -->
     <string translatable="false" name="config_mainBuiltInDisplayCutout"></string>
 
+    <!-- Like config_mainBuiltInDisplayCutout, but this path is used to report the
+         one single bounding rect per device edge to the app via
+         {@link DisplayCutout#getBoundingRect}. Note that this path should try to match the visual
+         appearance of the cutout as much as possible, and may be smaller than
+         config_mainBuiltInDisplayCutout
+         -->
+    <string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation">@string/config_mainBuiltInDisplayCutout</string>
+
     <!-- Whether the display cutout region of the main built-in display should be forced to
          black in software (to avoid aliasing or emulate a cutout that is not physically existent).
          -->
     <bool name="config_fillMainBuiltInDisplayCutout">false</bool>
 
+    <!-- If true, and there is a cutout on the main built in display, the cutout will be masked
+         by shrinking the display such that it does not overlap the cutout area. -->
+    <bool name="config_maskMainBuiltInDisplayCutout">false</bool>
+
     <!-- Ultrasound support for Mic/speaker path -->
     <!-- Whether the default microphone audio source supports near-ultrasound frequencies
          (range of 18 - 21 kHz). -->
@@ -3172,6 +3197,9 @@
     <!-- True if camera app should be pinned via Pinner Service -->
     <bool name="config_pinnerCameraApp">false</bool>
 
+    <!-- True if home app should be pinned via Pinner Service -->
+    <bool name="config_pinnerHomeApp">false</bool>
+
     <!-- Number of days preloaded file cache should be preserved on a device before it can be
          deleted -->
     <integer name="config_keepPreloadsMinDays">7</integer>
@@ -3207,12 +3235,11 @@
     <string-array translatable="false" name="config_defaultFirstUserRestrictions">
     </string-array>
 
-    <!-- Specifies whether the permissions needed by a legacy app should be
-         reviewed before any of its components can run. A legacy app is one
-         with targetSdkVersion < 23, i.e apps using the old permission model.
-         If review is not required, permissions are reviewed before the app
-         is installed. -->
-    <bool name="config_permissionReviewRequired">false</bool>
+    <!-- Specifies whether certain permissions should be individually controlled. -->
+    <bool name="config_permissionsIndividuallyControlled">false</bool>
+
+    <!-- Specifies whether the user has to give consent to manage wireless (wifi + bluetooth). -->
+    <bool name="config_wirelessConsentRequired">false</bool>
 
     <!-- Default value for android:focusableInTouchMode for some framework scrolling containers.
          ListView/GridView are notably absent since this is their default anyway.
@@ -3404,7 +3431,7 @@
     <string-array translatable="false" name="config_batteryPackageTypeService"/>
 
     <!-- Flag indicating whether or not to enable night mode detection. -->
-    <bool name="config_enableNightMode">false</bool>
+    <bool name="config_enableNightMode">true</bool>
 
     <!-- Flag indicating that the actions buttons for a notification should be tinted with by the
          color supplied by the Notification.Builder if present. -->
@@ -3485,6 +3512,20 @@
     <!-- Whether or not swipe up gesture's opt-in setting is available on this device -->
     <bool name="config_swipe_up_gesture_setting_available">false</bool>
 
+    <!-- Applications which are disabled unless matching a particular sku -->
+    <string-array name="config_disableApksUnlessMatchedSku_apk_list" translatable="false" />
+    <string-array name="config_disableApkUnlessMatchedSku_skus_list" translatable="false" />
+
     <!-- Whether or not we should show the option to show battery percentage -->
     <bool name="config_battery_percentage_setting_available">true</bool>
+
+    <!-- Whether or not battery saver should be "sticky" when manually enabled. -->
+    <bool name="config_batterySaverStickyBehaviourDisabled">false</bool>
+
+    <!-- Model of potentially misprovisioned devices. If none is specified in an overlay, an
+         empty string is passed in. -->
+    <string name="config_misprovisionedDeviceModel" translatable="false"></string>
+
+    <!-- Brand value for attestation of misprovisioned device. -->
+    <string name="config_misprovisionedBrandValue" translatable="false"></string>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 471170b..73cb59e 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -61,6 +61,15 @@
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
     <dimen name="status_bar_edge_ignore">5dp</dimen>
 
+    <!-- Default radius of the software rounded corners. -->
+    <dimen name="rounded_corner_radius">0dp</dimen>
+    <!-- Radius of the software rounded corners at the top of the display in its natural
+        orientation. If zero, the value of rounded_corner_radius is used. -->
+    <dimen name="rounded_corner_radius_top">0dp</dimen>
+    <!-- Radius of the software rounded corners at the bottom of the display in its natural
+        orientation. If zero, the value of rounded_corner_radius is used. -->
+    <dimen name="rounded_corner_radius_bottom">0dp</dimen>
+
     <!-- Width of the window of the divider bar used to resize docked stacks. -->
     <dimen name="docked_stack_divider_thickness">48dp</dimen>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6189971..e25bb79 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2907,6 +2907,8 @@
         <public name="opticalInsetTop" />
         <public name="opticalInsetRight" />
         <public name="opticalInsetBottom" />
+        <public name="allowForceDark" />
+        <public name="supportsAmbientMode" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e2">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8847ec8..dfd5e81 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -745,6 +745,22 @@
     <string name="permgrouprequest_sensors">Allow
         &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access sensor data about your vital signs?</string>
 
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_aural">Music</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_aural">access your music</string>
+    <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
+    <string name="permgrouprequest_aural">Allow
+        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your music?</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_visual">Photos &amp; Videos</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_visual">access your photos &amp; videos</string>
+    <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
+    <string name="permgrouprequest_visual">Allow
+        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your photos &amp; videos?</string>
+
     <!-- Title for the capability of an accessibility service to retrieve window content. -->
     <string name="capability_title_canRetrieveWindowContent">Retrieve window content</string>
     <!-- Description for the capability of an accessibility service to retrieve window content. -->
@@ -1349,6 +1365,38 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_useFingerprint">Allows the app to use fingerprint hardware for authentication</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_audioRead">read your music collection</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_audioRead">Allows the app to read your music collection.</string>
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_audioWrite">modify your music collection</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_audioWrite">Allows the app to modify your music collection.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_videoRead">read your video collection</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_videoRead">Allows the app to read your video collection.</string>
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_videoWrite">modify your video collection</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_videoWrite">Allows the app to modify your video collection.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_imagesRead">read your photo collection</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_imagesRead">Allows the app to read your photo collection.</string>
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_imagesWrite">modify your photo collection</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_imagesWrite">Allows the app to modify your photo collection.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_mediaLocation">read locations from your media collection</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_mediaLocation">Allows the app to read locations from your media collection.</string>
+
     <!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
     <string name="fingerprint_acquired_partial">Partial fingerprint detected. Please try again.</string>
     <!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
@@ -1399,11 +1447,11 @@
     <!-- Content description which should be used for the fingerprint icon. -->
     <string name="fingerprint_icon_content_description">Fingerprint icon</string>
 
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50] -->
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=70] -->
     <string name="permlab_manageFace">manage face authentication hardware</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=90] -->
     <string name="permdesc_manageFace">Allows the app to invoke methods to add and delete facial templates for use.</string>
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50] -->
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=70] -->
     <string name="permlab_useFaceAuthentication">use face authentication hardware</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=90] -->
     <string name="permdesc_useFaceAuthentication">Allows the app to use face authentication hardware for authentication</string>
@@ -4936,10 +4984,29 @@
          by an autofill service, and the service does knows what the activity represents, and it represents 3 types of
          data (for example, username, password and credit card info) [CHAR LIMIT=NONE] -->
     <string name="autofill_save_title_with_3types">Save <xliff:g id="type" example="Username">%1$s</xliff:g>, <xliff:g id="type" example="Password">%2$s</xliff:g>, and <xliff:g id="type" example="Credit Card">%3$s</xliff:g> to &lt;b><xliff:g id="label" example="MyPass">%4$s</xliff:g>&lt;/b>?</string>
+
+    <!-- Title for the autofill update dialog shown when the the contents of the activity can be updated
+         by an autofill service, but the service does not know what the activity represents [CHAR LIMIT=NONE] -->
+    <string name="autofill_update_title">Update to &lt;b><xliff:g id="label" example="MyPass">%1$s</xliff:g>&lt;/b>?</string>
+    <!-- Title for the autofill update dialog shown when the the contents of the activity can be updated
+         by an autofill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
+    <string name="autofill_update_title_with_type">Update <xliff:g id="type" example="Credit Card">%1$s</xliff:g> to &lt;b><xliff:g id="label" example="MyPass">%2$s</xliff:g>&lt;/b>?</string>
+    <!-- Title for the autofill update dialog shown when the the contents of the activity can be updated
+         by an autofill service, and the service does knows what the activity represents, and it represents 2 types of
+         data (for example, password and credit card info) [CHAR LIMIT=NONE] -->
+    <string name="autofill_update_title_with_2types">Update <xliff:g id="type" example="Password">%1$s</xliff:g> and <xliff:g id="type" example="Credit Card">%2$s</xliff:g> to &lt;b><xliff:g id="label" example="MyPass">%3$s</xliff:g>&lt;/b>?</string>
+    <!-- Title for the autofill update dialog shown when the the contents of the activity can be updated
+         by an autofill service, and the service does knows what the activity represents, and it represents 3 types of
+         data (for example, username, password and credit card info) [CHAR LIMIT=NONE] -->
+    <string name="autofill_update_title_with_3types">Update <xliff:g id="type" example="Username">%1$s</xliff:g>, <xliff:g id="type" example="Password">%2$s</xliff:g>, and <xliff:g id="type" example="Credit Card">%3$s</xliff:g> to &lt;b><xliff:g id="label" example="MyPass">%4$s</xliff:g>&lt;/b>?</string>
+
+
     <!-- Label for the autofill save button [CHAR LIMIT=NONE] -->
     <string name="autofill_save_yes">Save</string>
     <!-- Label for the autofill cancel button [CHAR LIMIT=NONE] -->
     <string name="autofill_save_no">No thanks</string>
+    <!-- Label for the autofill update button [CHAR LIMIT=NONE] -->
+    <string name="autofill_update_yes">Update</string>
 
     <!-- Label for the type of data being saved for autofill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
     <string name="autofill_save_type_password">password</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 50a6ff3..e1db71f 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -506,13 +506,13 @@
         <item name="textEditSuggestionHighlightStyle">?attr/textEditSuggestionHighlightStyle</item>
         <item name="textCursorDrawable">?attr/textCursorDrawable</item>
         <item name="breakStrategy">high_quality</item>
-        <item name="hyphenationFrequency">normal</item>
+        <item name="hyphenationFrequency">none</item>
     </style>
 
     <style name="Widget.CheckedTextView">
         <item name="textAlignment">viewStart</item>
         <item name="breakStrategy">high_quality</item>
-        <item name="hyphenationFrequency">normal</item>
+        <item name="hyphenationFrequency">none</item>
     </style>
 
     <style name="Widget.TextView.ListSeparator">
@@ -540,7 +540,7 @@
         <item name="textColor">?attr/editTextColor</item>
         <item name="gravity">center_vertical</item>
         <item name="breakStrategy">simple</item>
-        <item name="hyphenationFrequency">normal</item>
+        <item name="hyphenationFrequency">none</item>
         <item name="defaultFocusHighlightEnabled">false</item>
     </style>
 
diff --git a/core/res/res/values/styles_permission_controller.xml b/core/res/res/values/styles_permission_controller.xml
new file mode 100644
index 0000000..339f9c7
--- /dev/null
+++ b/core/res/res/values/styles_permission_controller.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<!-- styles for the permission grant dialog. -->
+<resources>
+    <style name="PermissionGrantDialog">
+        <item name="background">?attr/windowBackground</item>
+        <item name="elevation">?attr/windowElevation</item>
+        <item name="layout_weight">@dimen/permissionGrantDialogWeight</item>
+        <item name="layout_width">@dimen/permissionGrantDialogWidth</item>
+    </style>
+
+    <style name="PermissionGrantTitleIcon">
+        <item name="layout_width">36dp</item>
+        <item name="layout_height">36dp</item>
+        <item name="tint">?attr/colorAccent</item>
+        <item name="scaleType">fitCenter</item>
+    </style>
+
+    <style name="PermissionGrantTitleMessage"
+           parent="@style/TextAppearance.DeviceDefault">
+        <item name="paddingStart">22dp</item>
+        <item name="textSize">20sp</item>
+        <item name="textColor">?attr/textColorPrimary</item>
+    </style>
+
+    <style name="PermissionGrantIndex"
+           parent="@style/TextAppearance.DeviceDefault">
+        <item name="paddingEnd">12dp</item>
+        <item name="singleLine">true</item>
+        <item name="textColor">?attr/textColorSecondary</item>
+    </style>
+
+    <style name="PermissionGrantDescription">
+        <item name="layout_marginTop">20dp</item>
+        <item name="layout_marginStart">24dp</item>
+        <item name="layout_marginBottom">16dp</item>
+        <item name="layout_marginEnd">24dp</item>
+    </style>
+
+    <style name="PermissionGrantContent">
+        <item name="layout_marginStart">16dp</item>
+        <item name="layout_marginEnd">24dp</item>
+    </style>
+
+    <style name="PermissionGrantRadioGroup">
+        <item name="layout_marginStart">8dp</item>
+        <item name="layout_marginTop">-4dp</item>
+    </style>
+
+    <style name="PermissionGrantRadioButton"
+           parent="@style/Widget.DeviceDefault.CompoundButton.RadioButton">
+        <item name="paddingStart">16dp</item>
+        <item name="paddingTop">8dp</item>
+        <item name="paddingBottom">8dp</item>
+        <item name="textSize">16sp</item>
+    </style>
+
+    <style name="PermissionGrantDetailMessage"
+           parent="@style/TextAppearance.DeviceDefault">
+        <item name="layout_marginStart">8dp</item>
+        <item name="layout_marginBottom">4dp</item>
+        <item name="textColor">?attr/textColorPrimary</item>
+        <item name="textSize">16sp</item>
+    </style>
+
+    <style name="PermissionGrantDetailMessageSpace">
+        <item name="layout_height">8dp</item>
+    </style>
+
+    <style name="PermissionGrantCheckbox"
+           parent="@style/Widget.DeviceDefault.CompoundButton.CheckBox">
+        <item name="paddingStart">16dp</item>
+        <item name="textColor">?attr/textColorSecondary</item>
+        <item name="buttonTint">?attr/textColorSecondary</item>
+        <item name="textSize">16sp</item>
+    </style>
+
+    <style name="PermissionGrantButtonBar">
+        <item name="layout_marginStart">24dp</item>
+        <item name="layout_marginEnd">16dp</item>
+        <item name="layout_marginBottom">4dp</item>
+    </style>
+</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6054180..5358830 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -309,6 +309,7 @@
   <java-symbol type="bool" name="config_allowAnimationsInLowPowerMode" />
   <java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
   <java-symbol type="bool" name="config_safe_media_volume_enabled" />
+  <java-symbol type="bool" name="config_safe_media_disable_on_volume_up" />
   <java-symbol type="bool" name="config_camera_sound_forced" />
   <java-symbol type="bool" name="config_dontPreferApn" />
   <java-symbol type="bool" name="config_restartRadioAfterProvisioning" />
@@ -337,6 +338,7 @@
   <java-symbol type="bool" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection" />
   <java-symbol type="bool" name="config_wifi_only_link_same_credential_configurations" />
   <java-symbol type="bool" name="config_wifi_framework_enable_sar_tx_power_limit" />
+  <java-symbol type="bool" name="config_wifi_framework_enable_soft_ap_sar_tx_power_limit" />
   <java-symbol type="bool" name="config_wifi_framework_enable_body_proximity_sar_tx_power_limit" />
   <java-symbol type="string" name="config_wifi_sar_sensor_type" />
   <java-symbol type="integer" name="config_wifi_framework_sar_free_space_event_id" />
@@ -345,7 +347,6 @@
   <java-symbol type="integer" name="config_wifi_framework_sar_near_body_event_id" />
   <java-symbol type="bool" name="config_wifi_enable_disconnection_debounce" />
   <java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
-  <java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
   <java-symbol type="integer" name="config_wifi_logger_ring_buffer_default_size_limit_kb" />
   <java-symbol type="integer" name="config_wifi_logger_ring_buffer_verbose_size_limit_kb" />
   <java-symbol type="bool" name="config_wifi_turn_off_during_emergency_call" />
@@ -393,10 +394,6 @@
   <java-symbol type="integer" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz" />
   <java-symbol type="integer" name="config_wifi_framework_wifi_score_low_rssi_threshold_5GHz" />
   <java-symbol type="integer" name="config_wifi_framework_wifi_score_good_rssi_threshold_5GHz" />
-  <java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_link_speed_24" />
-  <java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_link_speed_5" />
-  <java-symbol type="integer" name="config_wifi_framework_wifi_score_good_link_speed_24" />
-  <java-symbol type="integer" name="config_wifi_framework_wifi_score_good_link_speed_5" />
   <java-symbol type="integer" name="config_wifi_framework_scan_result_rssi_level_patchup_value" />
   <java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
   <java-symbol type="string"  name="config_wifi_random_mac_oui" />
@@ -1339,7 +1336,6 @@
   <java-symbol type="drawable" name="ic_text_dot" />
   <java-symbol type="drawable" name="ic_print" />
   <java-symbol type="drawable" name="ic_print_error" />
-  <java-symbol type="drawable" name="ic_grayedout_printer" />
   <java-symbol type="drawable" name="jog_dial_arrow_long_left_green" />
   <java-symbol type="drawable" name="jog_dial_arrow_long_right_red" />
   <java-symbol type="drawable" name="jog_dial_arrow_short_left_and_right" />
@@ -2240,6 +2236,7 @@
   <java-symbol type="drawable" name="decor_maximize_button_light" />
   <java-symbol type="color" name="decor_button_dark_color" />
   <java-symbol type="color" name="decor_button_light_color" />
+  <java-symbol type="array" name="unloggable_phone_numbers" />
 
   <!-- From TelephonyProvider -->
   <java-symbol type="xml" name="apns" />
@@ -2923,6 +2920,7 @@
   <!-- Pinner Service -->
   <java-symbol type="array" name="config_defaultPinnerServiceFiles" />
   <java-symbol type="bool" name="config_pinnerCameraApp" />
+  <java-symbol type="bool" name="config_pinnerHomeApp" />
 
   <java-symbol type="string" name="config_doubleTouchGestureEnableFile" />
 
@@ -3005,12 +3003,13 @@
   <!-- Default first user restrictions -->
   <java-symbol type="array" name="config_defaultFirstUserRestrictions" />
 
-  <java-symbol type="bool" name="config_permissionReviewRequired" />
+  <java-symbol type="bool" name="config_permissionsIndividuallyControlled" />
+  <java-symbol type="bool" name="config_wirelessConsentRequired" />
 
   <!-- Global actions icons -->
   <java-symbol type="drawable" name="ic_restart" />
   <java-symbol type="drawable" name="ic_screenshot" />
-
+  <java-symbol type="drawable" name="ic_faster_emergency" />
   <java-symbol type="drawable" name="emergency_icon" />
 
   <java-symbol type="array" name="config_convert_to_emergency_number_map" />
@@ -3110,6 +3109,11 @@
   <java-symbol type="plurals" name="autofill_picker_some_suggestions" />
   <java-symbol type="string" name="autofill" />
   <java-symbol type="string" name="autofill_picker_accessibility_title " />
+  <java-symbol type="string" name="autofill_update_title" />
+  <java-symbol type="string" name="autofill_update_title_with_type" />
+  <java-symbol type="string" name="autofill_update_title_with_2types" />
+  <java-symbol type="string" name="autofill_update_title_with_3types" />
+  <java-symbol type="string" name="autofill_update_yes" />
   <java-symbol type="string" name="autofill_save_accessibility_title " />
   <java-symbol type="string" name="autofill_save_title" />
   <java-symbol type="string" name="autofill_save_title_with_type" />
@@ -3258,6 +3262,7 @@
   <java-symbol type="array" name="config_hideWhenDisabled_packageNames" />
 
   <java-symbol type="string" name="config_dozeLongPressSensorType" />
+  <java-symbol type="string" name="config_dozeReachSensorType" />
 
   <java-symbol type="array" name="config_allowedGlobalInstantAppSettings" />
   <java-symbol type="array" name="config_allowedSystemInstantAppSettings" />
@@ -3364,6 +3369,7 @@
 
   <java-symbol type="string" name="global_action_logout" />
   <java-symbol type="string" name="config_mainBuiltInDisplayCutout" />
+  <java-symbol type="string" name="config_mainBuiltInDisplayCutoutRectApproximation" />
   <java-symbol type="drawable" name="messaging_user" />
   <java-symbol type="bool" name="config_fillMainBuiltInDisplayCutout" />
   <java-symbol type="drawable" name="ic_logout" />
@@ -3405,6 +3411,7 @@
   <java-symbol type="string" name="notification_app_name_settings" />
 
   <java-symbol type="integer" name="config_lowBatteryAutoTriggerDefaultLevel" />
+  <java-symbol type="bool" name="config_batterySaverStickyBehaviourDisabled" />
 
   <!-- For car devices -->
   <java-symbol type="string" name="car_loading_profile" />
@@ -3434,4 +3441,14 @@
 
   <java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" />
   <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" />
+
+  <java-symbol type="bool" name="config_maskMainBuiltInDisplayCutout" />
+
+  <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />
+  <java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" />
+
+  <java-symbol type="string" name="config_misprovisionedDeviceModel" />
+  <java-symbol type="string" name="config_misprovisionedBrandValue" />
+
+  <java-symbol type="integer" name="db_wal_truncate_size" />
 </resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 4833816..090f9af 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -306,6 +306,7 @@
         <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.QuickContactBadgeSmall.WindowLarge</item>
         <item name="listPopupWindowStyle">@style/Widget.ListPopupWindow</item>
         <item name="popupMenuStyle">@style/Widget.PopupMenu</item>
+        <item name="popupTheme">@null</item>
         <item name="activityChooserViewStyle">@style/Widget.ActivityChooserView</item>
         <item name="fragmentBreadCrumbsStyle">@style/Widget.FragmentBreadCrumbs</item>
         <item name="contextPopupMenuStyle">?attr/popupMenuStyle</item>
diff --git a/core/res/res/values/themes_holo.xml b/core/res/res/values/themes_holo.xml
index cb5b93d..33832d4 100644
--- a/core/res/res/values/themes_holo.xml
+++ b/core/res/res/values/themes_holo.xml
@@ -296,6 +296,7 @@
         <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.Holo.QuickContactBadgeSmall.WindowLarge</item>
         <item name="listPopupWindowStyle">@style/Widget.Holo.ListPopupWindow</item>
         <item name="popupMenuStyle">@style/Widget.Holo.PopupMenu</item>
+        <item name="popupTheme">@null</item>
         <item name="stackViewStyle">@style/Widget.Holo.StackView</item>
         <item name="activityChooserViewStyle">@style/Widget.Holo.ActivityChooserView</item>
         <item name="fragmentBreadCrumbsStyle">@style/Widget.Holo.FragmentBreadCrumbs</item>
@@ -658,9 +659,11 @@
         <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.Holo.QuickContactBadgeSmall.WindowLarge</item>
         <item name="listPopupWindowStyle">@style/Widget.Holo.Light.ListPopupWindow</item>
         <item name="popupMenuStyle">@style/Widget.Holo.Light.PopupMenu</item>
+        <item name="popupTheme">@null</item>
         <item name="stackViewStyle">@style/Widget.Holo.StackView</item>
         <item name="activityChooserViewStyle">@style/Widget.Holo.Light.ActivityChooserView</item>
         <item name="fragmentBreadCrumbsStyle">@style/Widget.Holo.Light.FragmentBreadCrumbs</item>
+        <item name="contextPopupMenuStyle">?attr/popupMenuStyle</item>
 
         <!-- Preference styles -->
         <item name="preferenceScreenStyle">@style/Preference.Holo.PreferenceScreen</item>
diff --git a/core/res/res/values/themes_leanback.xml b/core/res/res/values/themes_leanback.xml
index 82cf288..f71df9f 100644
--- a/core/res/res/values/themes_leanback.xml
+++ b/core/res/res/values/themes_leanback.xml
@@ -93,4 +93,41 @@
         <item name="textColorPrimary">@color/primary_text_leanback_formwizard_dark</item>
         <item name="windowAnimationStyle">@style/WindowAnimationStyle.Leanback.Setup</item>
     </style>
+
+    <!-- Theme used for the intent picker activity. -->
+    <style name="Theme.Leanback.Resolver" parent="Theme.Material">
+        <item name="windowEnterTransition">@empty</item>
+        <item name="windowExitTransition">@empty</item>
+        <item name="windowIsTranslucent">true</item>
+        <item name="windowNoTitle">true</item>
+        <item name="windowBackground">@color/transparent</item>
+        <item name="backgroundDimEnabled">true</item>
+        <item name="statusBarColor">@color/transparent</item>
+        <item name="windowContentOverlay">@null</item>
+        <item name="colorControlActivated">?attr/colorControlHighlight</item>
+        <item name="listPreferredItemPaddingStart">?attr/dialogPreferredPadding</item>
+        <item name="listPreferredItemPaddingEnd">?attr/dialogPreferredPadding</item>
+
+        <!-- Dialog attributes -->
+        <item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
+        <item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
+
+        <!-- Button styles -->
+        <item name="buttonCornerRadius">@dimen/config_buttonCornerRadius</item>
+        <item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <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>
+
+        <!-- Progress bar attributes -->
+        <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+        <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
+
+        <!-- Toolbar attributes -->
+        <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+      </style>
+
 </resources>
diff --git a/core/res/res/values/themes_permission_controller.xml b/core/res/res/values/themes_permission_controller.xml
new file mode 100644
index 0000000..3bc93cd
--- /dev/null
+++ b/core/res/res/values/themes_permission_controller.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<!-- themes for the permission grant dialog. -->
+<resources>
+    <style name="Theme.DeviceDefault.PermissionGrantApp"
+           parent="@style/Theme.DeviceDefault.Light.Panel">
+        <item name="windowIsFloating">false</item>
+        <item name="windowTranslucentStatus">true</item>
+        <item name="backgroundDimEnabled">true</item>
+        <item name="windowAnimationStyle">@style/Animation.Material.Dialog</item>
+    </style>
+
+    <style name="Theme.DeviceDefault.PermissionGrant"
+           parent="@style/Theme.DeviceDefault.Light.Dialog">
+        <item name="titleTextStyle">@style/PermissionGrantTitleMessage</item>
+        <item name="radioButtonStyle">@style/PermissionGrantRadioButton</item>
+        <item name="checkboxStyle">@style/PermissionGrantCheckbox</item>
+        <item name="buttonBarStyle">@style/PermissionGrantButtonBar</item>
+    </style>
+</resources>
diff --git a/core/tests/HdmiCec/Android.mk b/core/tests/HdmiCec/Android.mk
deleted file mode 100644
index 450068b..0000000
--- a/core/tests/HdmiCec/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Include all test java files
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := HdmiCecTests
-
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
-LOCAL_CERTIFICATE := platform
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/HdmiCec/AndroidManifest.xml b/core/tests/HdmiCec/AndroidManifest.xml
deleted file mode 100644
index 80129d0d..0000000
--- a/core/tests/HdmiCec/AndroidManifest.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-          http://www.apache.org/licenses/LICENSE-2.0
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.test.example.helloworld"
-    android:sharedUserId="android.uid.system" >
-    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:targetPackage="android.test.example.helloworld"
-        android:label="Hello World Test"/>
-</manifest>
diff --git a/core/tests/HdmiCec/AndroidTest.xml b/core/tests/HdmiCec/AndroidTest.xml
deleted file mode 100644
index 5af30fb..0000000
--- a/core/tests/HdmiCec/AndroidTest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-          http://www.apache.org/licenses/LICENSE-2.0
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Runs sample instrumentation test.">
-    <option name="test-suite-tag" value="apct"/>
-    <option name="test-suite-tag" value="apct-instrumentation"/>
-    <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="test-file-name" value="HelloWorldTests.apk"/>
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
-    <option name="test-suite-tag" value="apct"/>
-    <option name="test-tag" value="SampleInstrumentationTest"/>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
-        <option name="package" value="android.test.example.helloworld"/>
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
-    </test>
-</configuration>
diff --git a/core/tests/HdmiCec/HelloWorldTests_HalloWelt.config b/core/tests/HdmiCec/HelloWorldTests_HalloWelt.config
deleted file mode 100644
index 902699b..0000000
--- a/core/tests/HdmiCec/HelloWorldTests_HalloWelt.config
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-          http://www.apache.org/licenses/LICENSE-2.0
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Runs only the HalloWelt test.">
-    <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup" />
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="test-file-name" value="HelloWorldTests.apk" />
-    </target_preparer>
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-tag" value="SampleInstrumentationTest" />
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.test.example.helloworld" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
-        <option name="class" value="android.test.example.helloworld.HelloWorldTest" />
-        <option name="method" value="testHalloWelt" />
-    </test>
-</configuration>
diff --git a/core/tests/HdmiCec/OWNERS b/core/tests/HdmiCec/OWNERS
deleted file mode 100644
index cc016f1..0000000
--- a/core/tests/HdmiCec/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-amyjojo@google.com
-nchalko@google.com
-shubang@google.com
\ No newline at end of file
diff --git a/core/tests/HdmiCec/src/android/test/example/helloworld/HelloWorldTest.java b/core/tests/HdmiCec/src/android/test/example/helloworld/HelloWorldTest.java
deleted file mode 100644
index 09321ad..0000000
--- a/core/tests/HdmiCec/src/android/test/example/helloworld/HelloWorldTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.test.example.helloworld;
-
-import android.support.test.filters.SmallTest;
-import android.util.Log;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class HelloWorldTest {
-    private static final String TAG = HelloWorldTest.class.getSimpleName();
-
-    @BeforeClass
-    public static void beforeClass() {
-        Log.d(TAG, "beforeClass()");
-    }
-
-    @AfterClass
-    public static void afterClass() {
-        Log.d(TAG, "afterClass()");
-    }
-
-    @Before
-    public void before() {
-        Log.d(TAG, "before()");
-    }
-
-    @After
-    public void after() {
-        Log.d(TAG, "after()");
-    }
-
-    @Test
-    @SmallTest
-    public void testHelloWorld() {
-        Log.d(TAG, "testHelloWorld()");
-        Assert.assertNotEquals("Hello", "world");
-    }
-
-    @Test
-    @SmallTest
-    public void testHalloWelt() {
-        Log.d(TAG, "testHalloWelt()");
-        Assert.assertNotEquals("Hallo", "Welt");
-    }
-}
diff --git a/core/tests/benchmarks/src/android/content/res/ResourcesBenchmark.java b/core/tests/benchmarks/src/android/content/res/ResourcesBenchmark.java
deleted file mode 100644
index 426b0dc..0000000
--- a/core/tests/benchmarks/src/android/content/res/ResourcesBenchmark.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import android.util.AttributeSet;
-import android.util.Xml;
-
-import com.android.internal.R;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import com.google.caliper.AfterExperiment;
-import com.google.caliper.BeforeExperiment;
-
-public class ResourcesBenchmark {
-
-    private AssetManager mAsset;
-    private Resources mRes;
-
-    private int mTextId;
-    private int mColorId;
-    private int mIntegerId;
-    private int mLayoutId;
-
-    @BeforeExperiment
-    protected void setUp() {
-        mAsset = new AssetManager();
-        mAsset.addAssetPath("/system/framework/framework-res.apk");
-        mRes = new Resources(mAsset, null, null);
-
-        mTextId = mRes.getIdentifier("cancel", "string", "android");
-        mColorId = mRes.getIdentifier("transparent", "color", "android");
-        mIntegerId = mRes.getIdentifier("config_shortAnimTime", "integer", "android");
-        mLayoutId = mRes.getIdentifier("two_line_list_item", "layout", "android");
-    }
-
-    @AfterExperiment
-    protected void tearDown() {
-        mAsset.close();
-    }
-
-    public void timeGetString(int reps) {
-        for (int i = 0; i < reps; i++) {
-            mRes.getText(mTextId);
-        }
-    }
-
-    public void timeGetColor(int reps) {
-        for (int i = 0; i < reps; i++) {
-            mRes.getColor(mColorId, null);
-        }
-    }
-
-    public void timeGetInteger(int reps) {
-        for (int i = 0; i < reps; i++) {
-            mRes.getInteger(mIntegerId);
-        }
-    }
-
-    public void timeGetLayoutAndTraverse(int reps) throws Exception {
-        for (int i = 0; i < reps; i++) {
-            final XmlResourceParser parser = mRes.getLayout(mLayoutId);
-            try {
-                while (parser.next() != XmlPullParser.END_DOCUMENT) {
-                    // Walk the entire tree
-                }
-            } finally {
-                parser.close();
-            }
-        }
-    }
-}
diff --git a/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java b/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java
index 5989da7..c70fc3c 100644
--- a/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java
+++ b/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java
@@ -54,7 +54,7 @@
         for (int i = 0; i < reps; i++) {
             try (FileInputStream in = new FileInputStream(mSrc);
                     FileOutputStream out = new FileOutputStream(mDest)) {
-                copyInternalUserspace(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE);
+                copyInternalUserspace(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null);
             }
         }
     }
@@ -63,7 +63,7 @@
         for (int i = 0; i < reps; i++) {
             try (FileInputStream in = new FileInputStream(mSrc);
                     FileOutputStream out = new FileOutputStream(mDest)) {
-                copyInternalSendfile(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE);
+                copyInternalSendfile(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null);
             }
         }
     }
@@ -72,7 +72,7 @@
         for (int i = 0; i < reps; i++) {
             try (MemoryPipe in = MemoryPipe.createSource(mData);
                     FileOutputStream out = new FileOutputStream(mDest)) {
-                copyInternalUserspace(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE);
+                copyInternalUserspace(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null);
             }
         }
     }
@@ -81,7 +81,7 @@
         for (int i = 0; i < reps; i++) {
             try (MemoryPipe in = MemoryPipe.createSource(mData);
                     FileOutputStream out = new FileOutputStream(mDest)) {
-                copyInternalSplice(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE);
+                copyInternalSplice(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null);
             }
         }
     }
@@ -90,7 +90,7 @@
         for (int i = 0; i < reps; i++) {
             try (FileInputStream in = new FileInputStream(mSrc);
                     MemoryPipe out = MemoryPipe.createSink(mData)) {
-                copyInternalUserspace(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE);
+                copyInternalUserspace(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null);
             }
         }
     }
@@ -99,7 +99,7 @@
         for (int i = 0; i < reps; i++) {
             try (FileInputStream in = new FileInputStream(mSrc);
                     MemoryPipe out = MemoryPipe.createSink(mData)) {
-                copyInternalSplice(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE);
+                copyInternalSplice(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null);
             }
         }
     }
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index ada0366..b906d84 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -446,7 +446,10 @@
 
         final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
         mContext.registerReceiver(receiver, filter);
-        assertTrue(adapter.enable());
+        // Note: for Wear Local Edition builds, which have Permission Review Mode enabled to
+        // obey China CMIIT, BluetoothAdapter may not startup immediately on methods enable/disable.
+        // So no assertion applied here.
+        adapter.enable();
         boolean success = false;
         try {
             success = completionSemaphore.tryAcquire(ENABLE_DISABLE_TIMEOUT, TimeUnit.MILLISECONDS);
@@ -489,7 +492,10 @@
 
         final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
         mContext.registerReceiver(receiver, filter);
-        assertTrue(adapter.disable());
+        // Note: for Wear Local Edition builds, which have Permission Review Mode enabled to
+        // obey China CMIIT, BluetoothAdapter may not startup immediately on methods enable/disable.
+        // So no assertion applied here.
+        adapter.disable();
         boolean success = false;
         try {
             success = completionSemaphore.tryAcquire(ENABLE_DISABLE_TIMEOUT, TimeUnit.MILLISECONDS);
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 0f019e71..d704957 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1301,6 +1301,11 @@
                 android:process=":MemoryFileProvider">
         </provider>
 
+        <provider android:name="android.content.RedactingProvider"
+                android:authorities="android.content.RedactingProvider"
+                android:process=":RedactingProvider">
+        </provider>
+
         <!-- Application components used for os tests -->
 
         <service android:name="android.os.MessengerService"
@@ -1401,6 +1406,14 @@
         <service android:name="android.content.CrossUserContentService"
                 android:exported="true" />
 
+        <activity android:name="android.app.assist.EmptyLayoutActivity"
+                  android:label="My Title">
+           <intent-filter>
+               <action android:name="android.intent.action.MAIN" />
+               <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+           </intent-filter>
+       </activity>
+
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/ascii.ttc b/core/tests/coretests/assets/fonts_for_family_selection/ascii.ttc
new file mode 100644
index 0000000..e404f2b
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/ascii.ttc
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/ascii_vf.ttf b/core/tests/coretests/assets/fonts_for_family_selection/ascii_vf.ttf
new file mode 100644
index 0000000..792b7d7
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/ascii_vf.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/ascii_vf.ttx b/core/tests/coretests/assets/fonts_for_family_selection/ascii_vf.ttx
new file mode 100644
index 0000000..22b2941
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/ascii_vf.ttx
@@ -0,0 +1,1942 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+    <GlyphID id="2" name="b"/>
+    <GlyphID id="3" name="c"/>
+    <GlyphID id="4" name="d"/>
+    <GlyphID id="5" name="e"/>
+    <GlyphID id="6" name="f"/>
+    <GlyphID id="7" name="g"/>
+    <GlyphID id="8" name="h"/>
+    <GlyphID id="9" name="i"/>
+    <GlyphID id="10" name="j"/>
+    <GlyphID id="11" name="k"/>
+    <GlyphID id="12" name="l"/>
+    <GlyphID id="13" name="m"/>
+    <GlyphID id="14" name="n"/>
+    <GlyphID id="15" name="o"/>
+    <GlyphID id="16" name="p"/>
+    <GlyphID id="17" name="q"/>
+    <GlyphID id="18" name="r"/>
+    <GlyphID id="19" name="s"/>
+    <GlyphID id="20" name="t"/>
+    <GlyphID id="21" name="u"/>
+    <GlyphID id="22" name="v"/>
+    <GlyphID id="23" name="w"/>
+    <GlyphID id="24" name="x"/>
+    <GlyphID id="25" name="y"/>
+    <GlyphID id="26" name="z"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="50"/>
+    <created value="Thu Feb 22 10:04:28 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="100"/>
+    <descent value="0"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="100"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="50" lsb="93"/>
+    <mtx name="a" width="50" lsb="0"/>
+    <mtx name="b" width="50" lsb="0"/>
+    <mtx name="c" width="50" lsb="0"/>
+    <mtx name="d" width="50" lsb="0"/>
+    <mtx name="e" width="50" lsb="0"/>
+    <mtx name="f" width="50" lsb="0"/>
+    <mtx name="g" width="50" lsb="0"/>
+    <mtx name="h" width="50" lsb="0"/>
+    <mtx name="i" width="50" lsb="0"/>
+    <mtx name="j" width="50" lsb="0"/>
+    <mtx name="k" width="50" lsb="0"/>
+    <mtx name="l" width="50" lsb="0"/>
+    <mtx name="m" width="50" lsb="0"/>
+    <mtx name="n" width="50" lsb="0"/>
+    <mtx name="o" width="50" lsb="0"/>
+    <mtx name="p" width="50" lsb="0"/>
+    <mtx name="q" width="50" lsb="0"/>
+    <mtx name="r" width="50" lsb="0"/>
+    <mtx name="s" width="50" lsb="0"/>
+    <mtx name="t" width="50" lsb="0"/>
+    <mtx name="u" width="50" lsb="0"/>
+    <mtx name="v" width="50" lsb="0"/>
+    <mtx name="w" width="50" lsb="0"/>
+    <mtx name="x" width="50" lsb="0"/>
+    <mtx name="y" width="50" lsb="0"/>
+    <mtx name="z" width="50" lsb="0"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="0" platEncID="3" language="0">
+        <map code="0x0061" name="a" /> <!-- a -->
+        <map code="0x0062" name="b" /> <!-- b -->
+        <map code="0x0063" name="c" /> <!-- c -->
+        <map code="0x0064" name="d" /> <!-- d -->
+        <map code="0x0065" name="e" /> <!-- e -->
+        <map code="0x0066" name="f" /> <!-- f -->
+        <map code="0x0067" name="g" /> <!-- g -->
+        <map code="0x0068" name="h" /> <!-- h -->
+        <map code="0x0069" name="i" /> <!-- i -->
+        <map code="0x006A" name="j" /> <!-- j -->
+        <map code="0x006B" name="k" /> <!-- k -->
+        <map code="0x006C" name="l" /> <!-- l -->
+        <map code="0x006D" name="m" /> <!-- m -->
+        <map code="0x006E" name="n" /> <!-- n -->
+        <map code="0x006F" name="o" /> <!-- o -->
+        <map code="0x0070" name="p" /> <!-- p -->
+        <map code="0x0071" name="q" /> <!-- q -->
+        <map code="0x0072" name="r" /> <!-- r -->
+        <map code="0x0073" name="s" /> <!-- s -->
+        <map code="0x0074" name="t" /> <!-- t -->
+        <map code="0x0075" name="u" /> <!-- u -->
+        <map code="0x0076" name="v" /> <!-- v -->
+        <map code="0x0077" name="w" /> <!-- w -->
+        <map code="0x0078" name="x" /> <!-- x -->
+        <map code="0x0079" name="y" /> <!-- y -->
+        <map code="0x007A" name="z" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="b" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="c" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="d" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="e" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="f" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="g" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="h" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="i" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="j" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="k" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="l" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="m" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="n" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="o" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="p" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="q" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="r" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="s" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="t" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="u" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="v" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="w" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="x" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="y" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+    <TTGlyph name="z" xMin="0" yMin="0" xMax="50" yMax="50">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="50" y="25" on="1"/>
+        <pt x="0" y="50" on="1"/>
+      </contour>
+      <instructions />
+    </TTGlyph>
+  </glyf>
+
+  <fvar>
+    <Axis>
+      <!-- Weight axis but no effects to the glyph. -->
+      <AxisTag>wght</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>400.0</DefaultValue>
+      <MaxValue>1000.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <!-- Italic axis but no effects to the glyph. -->
+      <AxisTag>ital</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Asca</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascb</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascc</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascd</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Asce</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascf</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascg</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Asch</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Asci</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascj</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Asck</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascl</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascm</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascn</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Asco</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascp</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascq</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascr</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascs</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Asct</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascu</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascv</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascw</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascx</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascy</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+    <Axis>
+      <AxisTag>Ascz</AxisTag>
+      <Flags>0x0</Flags>
+      <MinValue>0.0</MinValue>
+      <DefaultValue>0.0</DefaultValue>
+      <MaxValue>1.0</MaxValue>
+      <AxisNameID>256</AxisNameID>
+    </Axis>
+  </fvar>
+
+  <HVAR>
+    <Version value="0x00010000"/>
+    <VarStore Format="1">
+      <Format value="1" />
+      <VarRegionList>
+        <Region index="0">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="1">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="2">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="3">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="4">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="5">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="6">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="7">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="8">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="9">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="10">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="11">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="12">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="13">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="14">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="15">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="16">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="17">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="18">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="19">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="20">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="21">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="22">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="23">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="24">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="25">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+        <Region index="26">
+          <VarRegionAxis index="0"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="1"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="2"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="3"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="4"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="5"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="6"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="7"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="8"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="9"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="10"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="11"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="12"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="13"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="14"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="15"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="16"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="17"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="18"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="19"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="20"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="21"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="22"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="23"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="24"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="25"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="26"><StartCoord value="0" /><PeakCoord value="0" /><EndCoord value="1" /></VarRegionAxis>
+          <VarRegionAxis index="27"><StartCoord value="1" /><PeakCoord value="1" /><EndCoord value="1" /></VarRegionAxis>
+        </Region>
+      </VarRegionList>
+      <VarData index="0">
+        <NumShorts value="0" />
+        <VarRegionIndex index="0" value="0" />
+        <VarRegionIndex index="1" value="1" />
+        <VarRegionIndex index="2" value="2" />
+        <VarRegionIndex index="3" value="3" />
+        <VarRegionIndex index="4" value="4" />
+        <VarRegionIndex index="5" value="5" />
+        <VarRegionIndex index="6" value="6" />
+        <VarRegionIndex index="7" value="7" />
+        <VarRegionIndex index="8" value="8" />
+        <VarRegionIndex index="9" value="9" />
+        <VarRegionIndex index="10" value="10" />
+        <VarRegionIndex index="11" value="11" />
+        <VarRegionIndex index="12" value="12" />
+        <VarRegionIndex index="13" value="13" />
+        <VarRegionIndex index="14" value="14" />
+        <VarRegionIndex index="15" value="15" />
+        <VarRegionIndex index="16" value="16" />
+        <VarRegionIndex index="17" value="17" />
+        <VarRegionIndex index="18" value="18" />
+        <VarRegionIndex index="19" value="19" />
+        <VarRegionIndex index="20" value="20" />
+        <VarRegionIndex index="21" value="21" />
+        <VarRegionIndex index="22" value="22" />
+        <VarRegionIndex index="23" value="23" />
+        <VarRegionIndex index="24" value="24" />
+        <VarRegionIndex index="25" value="25" />
+        <VarRegionIndex index="26" value="26" />
+        <Item index="0" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="1" value="[0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="2" value="[0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="3" value="[0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="4" value="[0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="5" value="[0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="6" value="[0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="7" value="[0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="8" value="[0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="9" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="10" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="11" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="12" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="13" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="14" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="15" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="16" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="17" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="18" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="19" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0]" />
+        <Item index="20" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0]" />
+        <Item index="21" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0]" />
+        <Item index="22" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0]" />
+        <Item index="23" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0]" />
+        <Item index="24" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0]" />
+        <Item index="25" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0]" />
+        <Item index="26" value="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100]" />
+      </VarData>
+    </VarStore>
+    <AdvWidthMap>
+      <Map index="0" outer="0" inner="0" />
+      <Map index="1" outer="0" inner="1" />
+      <Map index="2" outer="0" inner="2" />
+      <Map index="3" outer="0" inner="3" />
+      <Map index="4" outer="0" inner="4" />
+      <Map index="5" outer="0" inner="5" />
+      <Map index="6" outer="0" inner="6" />
+      <Map index="7" outer="0" inner="7" />
+      <Map index="8" outer="0" inner="8" />
+      <Map index="9" outer="0" inner="9" />
+      <Map index="10" outer="0" inner="10" />
+      <Map index="11" outer="0" inner="11" />
+      <Map index="12" outer="0" inner="12" />
+      <Map index="13" outer="0" inner="13" />
+      <Map index="14" outer="0" inner="14" />
+      <Map index="15" outer="0" inner="15" />
+      <Map index="16" outer="0" inner="16" />
+      <Map index="17" outer="0" inner="17" />
+      <Map index="18" outer="0" inner="18" />
+      <Map index="19" outer="0" inner="19" />
+      <Map index="20" outer="0" inner="20" />
+      <Map index="21" outer="0" inner="21" />
+      <Map index="22" outer="0" inner="22" />
+      <Map index="23" outer="0" inner="23" />
+      <Map index="24" outer="0" inner="24" />
+      <Map index="25" outer="0" inner="25" />
+      <Map index="26" outer="0" inner="26" />
+    </AdvWidthMap>
+  </HVAR>
+
+  <gvar>
+    <version value="1" />
+    <reserved value="0" />
+    <glyphVariations glyph="a">
+      <tuple>
+        <coord axis="Asca" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="b">
+      <tuple>
+        <coord axis="Ascb" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="c">
+      <tuple>
+        <coord axis="Ascc" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="d">
+      <tuple>
+        <coord axis="Ascd" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="e">
+      <tuple>
+        <coord axis="Asce" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="f">
+      <tuple>
+        <coord axis="Ascf" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="g">
+      <tuple>
+        <coord axis="Ascg" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="h">
+      <tuple>
+        <coord axis="Asch" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="i">
+      <tuple>
+        <coord axis="Asci" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="j">
+      <tuple>
+        <coord axis="Ascj" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="k">
+      <tuple>
+        <coord axis="Asck" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="l">
+      <tuple>
+        <coord axis="Ascl" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="m">
+      <tuple>
+        <coord axis="Ascm" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="n">
+      <tuple>
+        <coord axis="Ascn" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="o">
+      <tuple>
+        <coord axis="Asco" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="p">
+      <tuple>
+        <coord axis="Ascp" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="q">
+      <tuple>
+        <coord axis="Ascq" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="r">
+      <tuple>
+        <coord axis="Ascr" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="s">
+      <tuple>
+        <coord axis="Ascs" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="t">
+      <tuple>
+        <coord axis="Asct" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="u">
+      <tuple>
+        <coord axis="Ascu" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="v">
+      <tuple>
+        <coord axis="Ascv" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="w">
+      <tuple>
+        <coord axis="Ascw" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="x">
+      <tuple>
+        <coord axis="Ascx" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="y">
+      <tuple>
+        <coord axis="Ascy" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+    <glyphVariations glyph="z">
+      <tuple>
+        <coord axis="Ascz" value="1.0" />
+        <delta pt="0" x="0" y="0" />
+        <delta pt="1" x="100" y="0" />
+        <delta pt="2" x="0" y="0" />
+        <!-- deltas for phantom points -->
+        <delta pt="3" x="0" y="0" />  <!-- (left, 0) -->
+        <delta pt="4" x="100" y="0" />  <!-- (right, 0) -->
+        <delta pt="5" x="0" y="0" />  <!-- (0, top) -->
+        <delta pt="6" x="0" y="0" />  <!-- (0, bottom) -->
+      </tuple>
+    </glyphVariations>
+  </gvar>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
+      3 em signal
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_a3em_weight100_upright.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_a3em_weight100_upright.ttf
new file mode 100644
index 0000000..f220eb3
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_a3em_weight100_upright.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_a3em_weight100_upright.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_a3em_weight100_upright.ttx
new file mode 100644
index 0000000..ebedcb6
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_a3em_weight100_upright.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:10 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="100"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="3em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_b3em_weight100_italic.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_b3em_weight100_italic.ttf
new file mode 100644
index 0000000..b9ffb84
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_b3em_weight100_italic.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_b3em_weight100_italic.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_b3em_weight100_italic.ttx
new file mode 100644
index 0000000..def6a29
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_b3em_weight100_italic.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:11 2018"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="100"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="3em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_c3em_weight200_upright.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_c3em_weight200_upright.ttf
new file mode 100644
index 0000000..075b068
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_c3em_weight200_upright.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_c3em_weight200_upright.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_c3em_weight200_upright.ttx
new file mode 100644
index 0000000..d201183
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_c3em_weight200_upright.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:11 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="200"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="3em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_d3em_weight200_italic.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_d3em_weight200_italic.ttf
new file mode 100644
index 0000000..5b47f0d
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_d3em_weight200_italic.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_d3em_weight200_italic.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_d3em_weight200_italic.ttx
new file mode 100644
index 0000000..7c801a0
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_d3em_weight200_italic.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:11 2018"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="200"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="3em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_e3em_weight300_upright.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_e3em_weight300_upright.ttf
new file mode 100644
index 0000000..3e9133b
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_e3em_weight300_upright.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_e3em_weight300_upright.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_e3em_weight300_upright.ttx
new file mode 100644
index 0000000..acb2006
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_e3em_weight300_upright.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:11 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="300"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="3em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_f3em_weight300_italic.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_f3em_weight300_italic.ttf
new file mode 100644
index 0000000..3ba3feb
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_f3em_weight300_italic.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_f3em_weight300_italic.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_f3em_weight300_italic.ttx
new file mode 100644
index 0000000..452ff66
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_f3em_weight300_italic.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:11 2018"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="300"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="3em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_g3em_weight400_upright.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_g3em_weight400_upright.ttf
new file mode 100644
index 0000000..b3175a1
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_g3em_weight400_upright.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_g3em_weight400_upright.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_g3em_weight400_upright.ttx
new file mode 100644
index 0000000..34a638f
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_g3em_weight400_upright.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:11 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="3em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_h3em_weight400_italic.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_h3em_weight400_italic.ttf
new file mode 100644
index 0000000..099c4f1
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_h3em_weight400_italic.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_h3em_weight400_italic.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_h3em_weight400_italic.ttx
new file mode 100644
index 0000000..b18af66
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_h3em_weight400_italic.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:12 2018"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="3em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_i3em_weight500_upright.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_i3em_weight500_upright.ttf
new file mode 100644
index 0000000..b8edcb6
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_i3em_weight500_upright.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_i3em_weight500_upright.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_i3em_weight500_upright.ttx
new file mode 100644
index 0000000..6daf8da
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_i3em_weight500_upright.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:12 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="500"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="3em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_j3em_weight500_italic.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_j3em_weight500_italic.ttf
new file mode 100644
index 0000000..6d7dde9
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_j3em_weight500_italic.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_j3em_weight500_italic.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_j3em_weight500_italic.ttx
new file mode 100644
index 0000000..c5843f0
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_j3em_weight500_italic.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:12 2018"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="500"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="3em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_k3em_weight600_upright.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_k3em_weight600_upright.ttf
new file mode 100644
index 0000000..eb6d7d1
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_k3em_weight600_upright.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_k3em_weight600_upright.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_k3em_weight600_upright.ttx
new file mode 100644
index 0000000..d46059f
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_k3em_weight600_upright.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:12 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="600"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="3em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_l3em_weight600_italic.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_l3em_weight600_italic.ttf
new file mode 100644
index 0000000..f509e94
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_l3em_weight600_italic.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_l3em_weight600_italic.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_l3em_weight600_italic.ttx
new file mode 100644
index 0000000..03073d33d
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_l3em_weight600_italic.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:12 2018"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="600"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="3em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_m3em_weight700_upright.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_m3em_weight700_upright.ttf
new file mode 100644
index 0000000..062f299
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_m3em_weight700_upright.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_m3em_weight700_upright.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_m3em_weight700_upright.ttx
new file mode 100644
index 0000000..ca24fde
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_m3em_weight700_upright.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:12 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="700"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="3em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_n3em_weight700_italic.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_n3em_weight700_italic.ttf
new file mode 100644
index 0000000..fdd0239
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_n3em_weight700_italic.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_n3em_weight700_italic.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_n3em_weight700_italic.ttx
new file mode 100644
index 0000000..468d591
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_n3em_weight700_italic.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:13 2018"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="700"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="3em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_names.txt b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_names.txt
new file mode 100644
index 0000000..986d712
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_names.txt
@@ -0,0 +1,18 @@
+ascii_a3em_weight100_upright.ttf
+ascii_b3em_weight100_italic.ttf
+ascii_c3em_weight200_upright.ttf
+ascii_d3em_weight200_italic.ttf
+ascii_e3em_weight300_upright.ttf
+ascii_f3em_weight300_italic.ttf
+ascii_g3em_weight400_upright.ttf
+ascii_h3em_weight400_italic.ttf
+ascii_i3em_weight500_upright.ttf
+ascii_j3em_weight500_italic.ttf
+ascii_k3em_weight600_upright.ttf
+ascii_l3em_weight600_italic.ttf
+ascii_m3em_weight700_upright.ttf
+ascii_n3em_weight700_italic.ttf
+ascii_o3em_weight800_upright.ttf
+ascii_p3em_weight800_italic.ttf
+ascii_q3em_weight900_upright.ttf
+ascii_r3em_weight900_italic.ttf
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_o3em_weight800_upright.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_o3em_weight800_upright.ttf
new file mode 100644
index 0000000..993e7fa
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_o3em_weight800_upright.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_o3em_weight800_upright.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_o3em_weight800_upright.ttx
new file mode 100644
index 0000000..b8c712f
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_o3em_weight800_upright.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:13 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="800"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="3em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_p3em_weight800_italic.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_p3em_weight800_italic.ttf
new file mode 100644
index 0000000..f0d54f0
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_p3em_weight800_italic.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_p3em_weight800_italic.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_p3em_weight800_italic.ttx
new file mode 100644
index 0000000..5d8ee18
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_p3em_weight800_italic.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:13 2018"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="800"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="3em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_q3em_weight900_upright.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_q3em_weight900_upright.ttf
new file mode 100644
index 0000000..c776c783
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_q3em_weight900_upright.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_q3em_weight900_upright.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_q3em_weight900_upright.ttx
new file mode 100644
index 0000000..169fd73
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_q3em_weight900_upright.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:13 2018"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="900"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="3em" /> <!-- q -->
+        <map code="0x0072" name="1em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_r3em_weight900_italic.ttf b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_r3em_weight900_italic.ttf
new file mode 100644
index 0000000..02f6246
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_r3em_weight900_italic.ttf
Binary files differ
diff --git a/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_r3em_weight900_italic.ttx b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_r3em_weight900_italic.ttx
new file mode 100644
index 0000000..131d7b1
--- /dev/null
+++ b/core/tests/coretests/assets/fonts_for_family_selection/fonts/ascii_r3em_weight900_italic.ttx
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="1em"/>
+    <GlyphID id="2" name="3em"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Thu Feb 15 18:29:13 2018"/>
+    <macStyle value="00000000 00000010"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="0x00010000"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="900"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 00000001"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="1em" width="1000" lsb="93"/>
+    <mtx name="3em" width="3000" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+        <map code="0x0061" name="1em" /> <!-- a -->
+        <map code="0x0062" name="1em" /> <!-- b -->
+        <map code="0x0063" name="1em" /> <!-- c -->
+        <map code="0x0064" name="1em" /> <!-- d -->
+        <map code="0x0065" name="1em" /> <!-- e -->
+        <map code="0x0066" name="1em" /> <!-- f -->
+        <map code="0x0067" name="1em" /> <!-- g -->
+        <map code="0x0068" name="1em" /> <!-- h -->
+        <map code="0x0069" name="1em" /> <!-- i -->
+        <map code="0x006A" name="1em" /> <!-- j -->
+        <map code="0x006B" name="1em" /> <!-- k -->
+        <map code="0x006C" name="1em" /> <!-- l -->
+        <map code="0x006D" name="1em" /> <!-- m -->
+        <map code="0x006E" name="1em" /> <!-- n -->
+        <map code="0x006F" name="1em" /> <!-- o -->
+        <map code="0x0070" name="1em" /> <!-- p -->
+        <map code="0x0071" name="1em" /> <!-- q -->
+        <map code="0x0072" name="3em" /> <!-- r -->
+        <map code="0x0073" name="1em" /> <!-- s -->
+        <map code="0x0074" name="1em" /> <!-- t -->
+        <map code="0x0075" name="1em" /> <!-- u -->
+        <map code="0x0076" name="1em" /> <!-- v -->
+        <map code="0x0077" name="1em" /> <!-- w -->
+        <map code="0x0078" name="1em" /> <!-- x -->
+        <map code="0x0079" name="1em" /> <!-- y -->
+        <map code="0x007A" name="1em" /> <!-- z -->
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="3em" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2018 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/core/tests/coretests/res/layout/empty_layout.xml b/core/tests/coretests/res/layout/empty_layout.xml
new file mode 100644
index 0000000..c208b95
--- /dev/null
+++ b/core/tests/coretests/res/layout/empty_layout.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/parent"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:focusable="true"
+    android:focusableInTouchMode="true"
+    android:orientation="vertical">
+</LinearLayout>
diff --git a/core/tests/coretests/src/android/app/assist/AssistStructureTest.java b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
new file mode 100644
index 0000000..bdb3e08
--- /dev/null
+++ b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.assist;
+
+import static android.view.View.IMPORTANT_FOR_AUTOFILL_AUTO;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.assist.AssistStructure.ViewNode;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Parcel;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Unit test for {@link AssistStructure}.
+ *
+ * <p>To run it: {@code atest app.assist.AssistStructureTest}
+ *
+ * <p>TODO: right now this test is focused in the parcelization of a big object, due to an
+ * upcoming refactoring on the Autofill parcelization that does not use
+ * {@link AssistStructure#ensureData()} to load the structure (which in turn requires calls from
+ * system server to the app). Ideally it should be emprove to:
+ *
+ * <ol>
+ *    <li>Add tests for Assist (to make sure autofill properties are not parcelized).
+ *    <li>Assert all properties and make sure just the relevant properties (for Autofill or Assist)
+ *    are parcelized.
+ *    <li>Add tests for Autofill requests with the {@code FLAG_MANUAL_REQUEST} flag.
+ * </ol>
+ */
+@RunWith(AndroidJUnit4.class)
+public class AssistStructureTest {
+
+    private static final String TAG = "AssistStructureTest";
+
+    private static final boolean FOR_AUTOFILL = true;
+    private static final int NO_FLAGS = 0;
+
+    private static final int BIG_VIEW_SIZE = 10_000_000;
+    private static final char BIG_VIEW_CHAR = '6';
+    private static final String BIG_STRING = repeat(BIG_VIEW_CHAR, BIG_VIEW_SIZE);
+    // Cannot be much big because it could hang test due to blocking GC
+    private static final int NUMBER_SMALL_VIEWS = 10_000;
+
+    private EmptyLayoutActivity mActivity;
+
+    private final ActivityTestRule<EmptyLayoutActivity> mActivityTestRule =
+            new ActivityTestRule<>(EmptyLayoutActivity.class);
+
+    private final Context mContext = InstrumentationRegistry.getTargetContext();
+
+    @Before
+    public void setup() {
+        mActivity = mActivityTestRule.launchActivity(null);
+    }
+
+    @Test
+    public void testParcelizationForAutofill_oneSmallView() {
+        mActivity.addView(newSmallView());
+
+        waitUntilViewsAreLaidOff();
+
+        AssistStructure structure = new AssistStructure(mActivity, FOR_AUTOFILL, NO_FLAGS);
+
+        // Check properties on "original" structure
+        assertStructureWithManySmallViews(structure, 1);
+
+        // Check properties on "cloned" structure
+        AssistStructure clone = cloneThroughParcel(structure);
+        assertStructureWithManySmallViews(clone, 1);
+    }
+
+    @Test
+    public void testParcelizationForAutofill_manySmallViews() {
+        Log.d(TAG, "Adding " + NUMBER_SMALL_VIEWS + " small views");
+
+        for (int i = 1; i <= NUMBER_SMALL_VIEWS; i++) {
+            mActivity.addView(newSmallView());
+        }
+
+        waitUntilViewsAreLaidOff();
+
+        AssistStructure structure = new AssistStructure(mActivity, FOR_AUTOFILL, NO_FLAGS);
+
+        // Check properties on "original" structure
+        assertStructureWithManySmallViews(structure, NUMBER_SMALL_VIEWS);
+
+        // Check properties on "cloned" structure
+        AssistStructure clone = cloneThroughParcel(structure);
+        assertStructureWithManySmallViews(clone, NUMBER_SMALL_VIEWS);
+    }
+
+    private void assertStructureWithManySmallViews(AssistStructure structure, int expectedSize) {
+        int i = 0;
+        try {
+            assertPackageName(structure);
+
+            assertThat(structure.getWindowNodeCount()).isEqualTo(1);
+
+            ViewNode rootView = structure.getWindowNodeAt(0).getRootViewNode();
+            assertThat(rootView.getClassName()).isEqualTo(FrameLayout.class.getName());
+            assertThat(rootView.getChildCount()).isEqualTo(2); // title and parent
+            assertThat(rootView.getAutofillId()).isNotNull();
+            assertThat(rootView.getImportantForAutofill()).isEqualTo(IMPORTANT_FOR_AUTOFILL_AUTO);
+
+            // Title
+            ViewNode title = rootView.getChildAt(0);
+            assertThat(title.getClassName()).isEqualTo(TextView.class.getName());
+            assertThat(title.getChildCount()).isEqualTo(0);
+            assertThat(title.getText().toString()).isEqualTo("My Title");
+            assertThat(title.getAutofillId()).isNotNull();
+
+            // Parent
+            ViewNode parent = rootView.getChildAt(1);
+            assertThat(parent.getClassName()).isEqualTo(LinearLayout.class.getName());
+            assertThat(parent.getChildCount()).isEqualTo(expectedSize);
+            assertThat(parent.getIdEntry()).isEqualTo("parent");
+            assertThat(parent.getAutofillId()).isNotNull();
+
+            // Children
+            for (i = 0; i < expectedSize; i++) {
+                ViewNode smallView = parent.getChildAt(i);
+                assertSmallView(smallView);
+            }
+        } catch (RuntimeException | Error e) {
+            Log.e(TAG, "dumping structure because of error at index #" + i + ": " + e);
+            structure.dump(true);
+            throw e;
+        }
+    }
+
+    @Test
+    public void testParcelizationForAutofill_oneBigView() {
+        Log.d(TAG, "Adding view with " + BIG_VIEW_SIZE + " chars");
+
+        mActivity.addView(newBigView());
+        waitUntilViewsAreLaidOff();
+
+        AssistStructure structure = new AssistStructure(mActivity, FOR_AUTOFILL, NO_FLAGS);
+
+        // Check properties on "original" structure
+        assertStructureWithOneBigView(structure);
+
+        // Check properties on "cloned" structure
+        AssistStructure clone = cloneThroughParcel(structure);
+        assertStructureWithOneBigView(clone);
+    }
+
+    private void assertStructureWithOneBigView(AssistStructure structure) {
+        try {
+            assertPackageName(structure);
+
+            assertThat(structure.getWindowNodeCount()).isEqualTo(1);
+
+            ViewNode rootView = structure.getWindowNodeAt(0).getRootViewNode();
+            assertThat(rootView.getClassName()).isEqualTo(FrameLayout.class.getName());
+            assertThat(rootView.getChildCount()).isEqualTo(2); // title and parent
+            assertThat(rootView.getAutofillId()).isNotNull();
+            assertThat(rootView.getImportantForAutofill()).isEqualTo(IMPORTANT_FOR_AUTOFILL_AUTO);
+
+            // Title
+            ViewNode title = rootView.getChildAt(0);
+            assertThat(title.getClassName()).isEqualTo(TextView.class.getName());
+            assertThat(title.getChildCount()).isEqualTo(0);
+            assertThat(title.getText().toString()).isEqualTo("My Title");
+            assertThat(title.getAutofillId()).isNotNull();
+
+            // Parent
+            ViewNode parent = rootView.getChildAt(1);
+            assertThat(parent.getClassName()).isEqualTo(LinearLayout.class.getName());
+            assertThat(parent.getChildCount()).isEqualTo(1);
+            assertThat(parent.getIdEntry()).isEqualTo("parent");
+            assertThat(parent.getAutofillId()).isNotNull();
+
+            // Children
+            ViewNode bigView = parent.getChildAt(0);
+            assertBigView(bigView);
+        } catch (RuntimeException | Error e) {
+            Log.e(TAG, "dumping structure because of error: " + e);
+            structure.dump(true);
+            throw e;
+        }
+    }
+
+    private EditText newSmallView() {
+        EditText view = new EditText(mContext);
+        view.setText("I AM GROOT");
+        return view;
+    }
+
+    private void assertSmallView(ViewNode view) {
+        assertThat(view.getClassName()).isEqualTo(EditText.class.getName());
+        assertThat(view.getChildCount()).isEqualTo(0);
+        assertThat(view.getIdEntry()).isNull();
+        assertThat(view.getAutofillId()).isNotNull();
+        assertThat(view.getText().toString()).isEqualTo("I AM GROOT");
+    }
+
+    private EditText newBigView() {
+        EditText view = new EditText(mContext);
+        view.setText("Big Hint in Little View");
+        view.setAutofillHints(BIG_STRING);
+        return view;
+    }
+
+    private void assertBigView(ViewNode view) {
+        assertThat(view.getClassName()).isEqualTo(EditText.class.getName());
+        assertThat(view.getChildCount()).isEqualTo(0);
+        assertThat(view.getIdEntry()).isNull();
+        assertThat(view.getAutofillId()).isNotNull();
+        assertThat(view.getText().toString()).isEqualTo("Big Hint in Little View");
+
+        String[] hints = view.getAutofillHints();
+        assertThat(hints.length).isEqualTo(1);
+        String hint = hints[0];
+        // Cannot assert the whole string because it takes too long and crashes the test by ANR
+        assertThat(hint.length()).isEqualTo(BIG_VIEW_SIZE);
+        assertThat(hint.charAt(0)).isEqualTo(BIG_VIEW_CHAR);
+        assertThat(hint.charAt(BIG_VIEW_SIZE - 1)).isEqualTo(BIG_VIEW_CHAR);
+    }
+
+    private void assertPackageName(AssistStructure structure) {
+        assertThat(structure.getActivityComponent()).isEqualTo(
+                new ComponentName("com.android.frameworks.coretests",
+                        "android.app.assist.EmptyLayoutActivity"));
+    }
+
+    private AssistStructure cloneThroughParcel(AssistStructure structure) {
+        Parcel parcel = Parcel.obtain();
+
+        try {
+            // Write to parcel
+            parcel.setDataPosition(0); // Sanity / paranoid check
+            structure.writeToParcel(parcel, NO_FLAGS);
+
+            // Read from parcel
+            parcel.setDataPosition(0);
+            AssistStructure clone = AssistStructure.CREATOR.createFromParcel(parcel);
+            assertThat(clone).isNotNull();
+            return clone;
+        } finally {
+            parcel.recycle();
+        }
+    }
+
+    private void waitUntilViewsAreLaidOff() {
+        // TODO: use a more robust mechanism than just sleeping
+        SystemClock.sleep(3000);
+    }
+
+    // TODO: use some common helper
+    private static String repeat(char c, int size) {
+        StringBuilder builder = new StringBuilder(size);
+        for (int i = 1; i <= size; i++) {
+            builder.append(c);
+        }
+        return builder.toString();
+    }
+}
diff --git a/core/tests/coretests/src/android/app/assist/EmptyLayoutActivity.java b/core/tests/coretests/src/android/app/assist/EmptyLayoutActivity.java
new file mode 100644
index 0000000..f4b6bed
--- /dev/null
+++ b/core/tests/coretests/src/android/app/assist/EmptyLayoutActivity.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.assist;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.WindowManager.LayoutParams;
+import android.widget.LinearLayout;
+
+import com.android.frameworks.coretests.R;
+
+public class EmptyLayoutActivity extends Activity {
+
+    private LinearLayout mParent;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.empty_layout);
+
+        mParent = findViewById(R.id.parent);
+    }
+
+    public void addView(View view) {
+        view.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.WRAP_CONTENT));
+        runOnUiThread(() -> mParent.addView(view));
+    }
+}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index fe58116..a788a93 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -47,6 +47,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.util.ArrayMap;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -56,6 +57,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /** Test {@link TransactionExecutor} logic. */
@@ -232,6 +234,44 @@
     }
 
     @Test
+    public void testDoNotLaunchDestroyedActivity() {
+        final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed = new ArrayMap<>();
+        when(mTransactionHandler.getActivitiesToBeDestroyed()).thenReturn(activitiesToBeDestroyed);
+        // Assume launch transaction is still in queue, so there is no client record.
+        when(mTransactionHandler.getActivityClient(any())).thenReturn(null);
+
+        // An incoming destroy transaction enters binder thread (preExecute).
+        final IBinder token = mock(IBinder.class);
+        final ClientTransaction destroyTransaction = ClientTransaction.obtain(null /* client */,
+                token /* activityToken */);
+        destroyTransaction.setLifecycleStateRequest(
+                DestroyActivityItem.obtain(false /* finished */, 0 /* configChanges */));
+        destroyTransaction.preExecute(mTransactionHandler);
+        // The activity should be added to to-be-destroyed container.
+        assertEquals(1, mTransactionHandler.getActivitiesToBeDestroyed().size());
+
+        // A previous queued launch transaction runs on main thread (execute).
+        final ClientTransaction launchTransaction = ClientTransaction.obtain(null /* client */,
+                token /* activityToken */);
+        final LaunchActivityItem launchItem = spy(LaunchActivityItem.obtain(
+                null /* intent */, 0 /* ident */, null /* info */, null /* curConfig */,
+                null, /* overrideConfig */ null /* compatInfo */, null /* referrer */ ,
+                null /* voiceInteractor */, 0 /* procState */, null /* state */,
+                null /* persistentState */, null /* pendingResults */,
+                null /* pendingNewIntents */, false /* isForward */, null /* profilerInfo */));
+        launchTransaction.addCallback(launchItem);
+        mExecutor.execute(launchTransaction);
+
+        // The launch transaction should not be executed because its token is in the
+        // to-be-destroyed container.
+        verify(launchItem, times(0)).execute(any(), any(), any());
+
+        // After the destroy transaction has been executed, the token should be removed.
+        mExecutor.execute(destroyTransaction);
+        assertEquals(0, mTransactionHandler.getActivitiesToBeDestroyed().size());
+    }
+
+    @Test
     public void testActivityResultRequiredStateResolution() {
         PostExecItem postExecItem = new PostExecItem(ON_RESUME);
 
@@ -243,12 +283,12 @@
         // Verify resolution that should get to onPause
         mClientRecord.setState(ON_RESUME);
         mExecutor.executeCallbacks(transaction);
-        verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_PAUSE));
+        verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_PAUSE), eq(transaction));
 
         // Verify resolution that should get to onStart
         mClientRecord.setState(ON_STOP);
         mExecutor.executeCallbacks(transaction);
-        verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_START));
+        verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_START), eq(transaction));
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/content/RedactingProvider.java b/core/tests/coretests/src/android/content/RedactingProvider.java
new file mode 100644
index 0000000..e2ad448
--- /dev/null
+++ b/core/tests/coretests/src/android/content/RedactingProvider.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.RedactingCursor;
+import android.net.Uri;
+import android.util.ArrayMap;
+
+public class RedactingProvider extends ContentProvider {
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        switch (uri.getLastPathSegment()) {
+            case "missing": {
+                final MatrixCursor cursor = new MatrixCursor(
+                        new String[] { "name", "size", "_data" });
+                cursor.addRow(new Object[] { "foo", 10, "/path/to/foo" });
+                cursor.addRow(new Object[] { "bar", 20, "/path/to/bar" });
+
+                final ArrayMap<String, Object> redactions = new ArrayMap<>();
+                redactions.put("missing", null);
+                return RedactingCursor.create(cursor, redactions);
+            }
+            case "single": {
+                final MatrixCursor cursor = new MatrixCursor(
+                        new String[] { "name", "size", "_data" });
+                cursor.addRow(new Object[] { "foo", 10, "/path/to/foo" });
+                cursor.addRow(new Object[] { "bar", 20, "/path/to/bar" });
+
+                final ArrayMap<String, Object> redactions = new ArrayMap<>();
+                redactions.put("name", null);
+                redactions.put("_data", "/dev/null");
+                return RedactingCursor.create(cursor, redactions);
+            }
+            case "multiple": {
+                final MatrixCursor cursor = new MatrixCursor(
+                        new String[] { "_data", "name", "_data" });
+                cursor.addRow(new Object[] { "/path", "foo", "/path" });
+
+                final ArrayMap<String, Object> redactions = new ArrayMap<>();
+                redactions.put("_data", null);
+                return RedactingCursor.create(cursor, redactions);
+            }
+        }
+
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/core/tests/coretests/src/android/database/DatabaseUtilsTest.java b/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
new file mode 100644
index 0000000..7c206d7
--- /dev/null
+++ b/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database;
+
+import static android.database.DatabaseUtils.bindSelection;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DatabaseUtilsTest {
+    private static final Object[] ARGS = { "baz", 4, null };
+
+    @Test
+    public void testBindSelection_none() throws Exception {
+        assertEquals(null,
+                bindSelection(null, ARGS));
+        assertEquals("",
+                bindSelection("", ARGS));
+        assertEquals("foo=bar",
+                bindSelection("foo=bar", ARGS));
+    }
+
+    @Test
+    public void testBindSelection_normal() throws Exception {
+        assertEquals("foo='baz'",
+                bindSelection("foo=?", ARGS));
+        assertEquals("foo='baz' AND bar=4",
+                bindSelection("foo=? AND bar=?", ARGS));
+        assertEquals("foo='baz' AND bar=4 AND meow=NULL",
+                bindSelection("foo=? AND bar=? AND meow=?", ARGS));
+    }
+
+    @Test
+    public void testBindSelection_whitespace() throws Exception {
+        assertEquals("BETWEEN 5 AND 10",
+                bindSelection("BETWEEN? AND ?", 5, 10));
+        assertEquals("IN 'foo'",
+                bindSelection("IN?", "foo"));
+    }
+
+    @Test
+    public void testBindSelection_indexed() throws Exception {
+        assertEquals("foo=10 AND bar=11 AND meow=1",
+                bindSelection("foo=?10 AND bar=? AND meow=?1",
+                        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
+    }
+}
diff --git a/core/tests/coretests/src/android/database/RedactingCursorTest.java b/core/tests/coretests/src/android/database/RedactingCursorTest.java
new file mode 100644
index 0000000..93998f3
--- /dev/null
+++ b/core/tests/coretests/src/android/database/RedactingCursorTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.net.Uri;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RedactingCursorTest {
+    private Context getContext() {
+        return InstrumentationRegistry.getContext();
+    }
+
+    @Test
+    public void testMissing() throws Exception {
+        final Cursor redacting = getContext().getContentResolver().query(
+                Uri.parse("content://android.content.RedactingProvider/missing"), null, null, null);
+
+        redacting.moveToNext();
+        assertEquals("foo", redacting.getString(0));
+        assertEquals(10, redacting.getInt(1));
+        assertEquals("/path/to/foo", redacting.getString(2));
+        redacting.moveToNext();
+        assertEquals("bar", redacting.getString(0));
+        assertEquals(20, redacting.getInt(1));
+        assertEquals("/path/to/bar", redacting.getString(2));
+    }
+
+    @Test
+    public void testSingle() throws Exception {
+        final Cursor redacting = getContext().getContentResolver().query(
+                Uri.parse("content://android.content.RedactingProvider/single"), null, null, null);
+
+        redacting.moveToNext();
+        assertEquals(null, redacting.getString(0));
+        assertEquals(10, redacting.getInt(1));
+        assertEquals("/dev/null", redacting.getString(2));
+        assertEquals(Cursor.FIELD_TYPE_NULL, redacting.getType(0));
+        assertEquals(Cursor.FIELD_TYPE_INTEGER, redacting.getType(1));
+        assertEquals(Cursor.FIELD_TYPE_STRING, redacting.getType(2));
+        assertTrue(redacting.isNull(0));
+        assertFalse(redacting.isNull(1));
+        assertFalse(redacting.isNull(2));
+
+        redacting.moveToNext();
+        assertEquals(null, redacting.getString(0));
+        assertEquals(20, redacting.getInt(1));
+        assertEquals("/dev/null", redacting.getString(2));
+    }
+
+    @Test
+    public void testMultiple() throws Exception {
+        final Cursor redacting = getContext().getContentResolver().query(
+                Uri.parse("content://android.content.RedactingProvider/multiple"),
+                null, null, null);
+
+        redacting.moveToNext();
+        assertEquals(null, redacting.getString(0));
+        assertEquals("foo", redacting.getString(1));
+        assertEquals(null, redacting.getString(2));
+    }
+}
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
index 230655d..551a58e 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
@@ -62,18 +62,24 @@
         assertTrue(SQLiteCompatibilityWalFlags.areFlagsSet());
         assertFalse(SQLiteCompatibilityWalFlags.isCompatibilityWalSupported());
         assertEquals("OFF", SQLiteCompatibilityWalFlags.getWALSyncMode());
+        assertEquals(-1, SQLiteCompatibilityWalFlags.getTruncateSize());
 
         SQLiteCompatibilityWalFlags.init("wal_syncmode=VALUE");
         assertTrue(SQLiteCompatibilityWalFlags.areFlagsSet());
         assertEquals(SQLiteGlobal.isCompatibilityWalSupported(),
                 SQLiteCompatibilityWalFlags.isCompatibilityWalSupported());
         assertEquals("VALUE", SQLiteCompatibilityWalFlags.getWALSyncMode());
+        assertEquals(-1, SQLiteCompatibilityWalFlags.getTruncateSize());
 
         SQLiteCompatibilityWalFlags.init("compatibility_wal_supported=true");
         assertTrue(SQLiteCompatibilityWalFlags.areFlagsSet());
         assertEquals(SQLiteGlobal.getWALSyncMode(),
                 SQLiteCompatibilityWalFlags.getWALSyncMode());
         assertTrue(SQLiteCompatibilityWalFlags.isCompatibilityWalSupported());
+        assertEquals(-1, SQLiteCompatibilityWalFlags.getTruncateSize());
+
+        SQLiteCompatibilityWalFlags.init("truncate_size=1024");
+        assertEquals(1024, SQLiteCompatibilityWalFlags.getTruncateSize());
 
         SQLiteCompatibilityWalFlags.reset();
         SQLiteCompatibilityWalFlags.init("Invalid value");
diff --git a/core/tests/coretests/src/android/graphics/FontFileUtilTest.java b/core/tests/coretests/src/android/graphics/FontFileUtilTest.java
new file mode 100644
index 0000000..76267b2
--- /dev/null
+++ b/core/tests/coretests/src/android/graphics/FontFileUtilTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.graphics.fonts.FontFileUtil;
+import android.graphics.fonts.FontVariationAxis;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.util.Log;
+import android.util.Pair;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+@SmallTest
+public class FontFileUtilTest {
+    private static final String TAG = "FontFileUtilTest";
+    private static final String CACHE_FILE_PREFIX = ".font";
+
+    private static File getTempFile() {
+        Context ctx = InstrumentationRegistry.getTargetContext();
+        final String prefix = CACHE_FILE_PREFIX;
+        for (int i = 0; i < 100; ++i) {
+            final File file = new File(ctx.getCacheDir(), prefix + i);
+            try {
+                if (file.createNewFile()) {
+                    return file;
+                }
+            } catch (IOException e) {
+                // ignore. Try next file.
+            }
+        }
+        return null;
+    }
+
+    private static ByteBuffer mmap(AssetManager am, String path) {
+        File file = getTempFile();
+        try (InputStream is = am.open(path)) {
+            if (!copyToFile(file, is)) {
+                return null;
+            }
+            return mmap(file);
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to open assets");
+            return null;
+        } finally {
+            file.delete();
+        }
+    }
+
+    private static ByteBuffer mmap(File file) {
+        try (FileInputStream fis = new FileInputStream(file)) {
+            FileChannel channel = fis.getChannel();
+            return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+    private static boolean copyToFile(File file, InputStream is) {
+        try (FileOutputStream os = new FileOutputStream(file, false)) {
+            byte[] buffer = new byte[1024];
+            int readLen;
+            while ((readLen = is.read(buffer)) != -1) {
+                os.write(buffer, 0, readLen);
+            }
+            return true;
+        } catch (IOException e) {
+            Log.e(TAG, "Error copying resource contents to temp file: " + e.getMessage());
+            return false;
+        }
+    }
+
+    @Test
+    public void testRegularFonts() throws IOException {
+        AssetManager am = InstrumentationRegistry.getTargetContext().getAssets();
+        for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) {
+            int weight = style.first.intValue();
+            boolean italic = style.second.booleanValue();
+            String path = FontTestUtil.getFontPathFromStyle(weight, italic);
+
+            ByteBuffer buffer = mmap(am, path);
+            int packed = FontFileUtil.analyzeStyle(buffer, 0, null);
+            assertEquals(path, weight, FontFileUtil.unpackWeight(packed));
+            assertEquals(path, italic, FontFileUtil.unpackItalic(packed));
+        }
+    }
+
+    @Test
+    public void testTtcFont() throws IOException {
+        AssetManager am = InstrumentationRegistry.getTargetContext().getAssets();
+        String path = FontTestUtil.getTtcFontFileInAsset();
+        ByteBuffer buffer = mmap(am, path);
+        for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) {
+            int weight = style.first.intValue();
+            boolean italic = style.second.booleanValue();
+            int ttcIndex = FontTestUtil.getTtcIndexFromStyle(weight, italic);
+
+            int packed = FontFileUtil.analyzeStyle(buffer, ttcIndex, null);
+            assertEquals(path + "#" + ttcIndex, weight, FontFileUtil.unpackWeight(packed));
+            assertEquals(path + "#" + ttcIndex, italic, FontFileUtil.unpackItalic(packed));
+        }
+    }
+
+    @Test
+    public void testVariationFont() throws IOException {
+        AssetManager am = InstrumentationRegistry.getTargetContext().getAssets();
+        String path = FontTestUtil.getVFFontInAsset();
+        ByteBuffer buffer = mmap(am, path);
+        for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) {
+            int weight = style.first.intValue();
+            boolean italic = style.second.booleanValue();
+            String axes = FontTestUtil.getVarSettingsFromStyle(weight, italic);
+
+            int packed = FontFileUtil.analyzeStyle(buffer, 0,
+                    FontVariationAxis.fromFontVariationSettings(axes));
+            assertEquals(path + "#" + axes, weight, FontFileUtil.unpackWeight(packed));
+            assertEquals(path + "#" + axes, italic, FontFileUtil.unpackItalic(packed));
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/graphics/FontTestUtil.java b/core/tests/coretests/src/android/graphics/FontTestUtil.java
new file mode 100644
index 0000000..2becb4b
--- /dev/null
+++ b/core/tests/coretests/src/android/graphics/FontTestUtil.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Provides a utility for testing fonts
+ *
+ * For the purpose of testing font selection of families or fallbacks, this class provies following
+ * regular font files.
+ *
+ * - ascii_a3em_weight100_upright.ttf
+ *   'a' has 3em width and others have 1em width. The metadata has weight=100, non-italic value.
+ * - ascii_b3em_weight100_italic.ttf
+ *   'b' has 3em width and others have 1em width. The metadata has weight=100, italic value.
+ * - ascii_c3em_weight200_upright.ttf
+ *   'c' has 3em width and others have 1em width. The metadata has weight=200, non-italic value.
+ * - ascii_d3em_weight200_italic.ttf
+ *   'd' has 3em width and others have 1em width. The metadata has weight=200, italic value.
+ * - ascii_e3em_weight300_upright.ttf
+ *   'e' has 3em width and others have 1em width. The metadata has weight=300, non-italic value.
+ * - ascii_f3em_weight300_italic.ttf
+ *   'f' has 3em width and others have 1em width. The metadata has weight=300, italic value.
+ * - ascii_g3em_weight400_upright.ttf
+ *   'g' has 3em width and others have 1em width. The metadata has weight=400, non-italic value.
+ * - ascii_h3em_weight400_italic.ttf
+ *   'h' has 3em width and others have 1em width. The metadata has weight=400, italic value.
+ * - ascii_i3em_weight500_upright.ttf
+ *   'i' has 3em width and others have 1em width. The metadata has weight=500, non-italic value.
+ * - ascii_j3em_weight500_italic.ttf
+ *   'j' has 3em width and others have 1em width. The metadata has weight=500, italic value.
+ * - ascii_k3em_weight600_upright.ttf
+ *   'k' has 3em width and others have 1em width. The metadata has weight=600, non-italic value.
+ * - ascii_l3em_weight600_italic.ttf
+ *   'l' has 3em width and others have 1em width. The metadata has weight=600, italic value.
+ * - ascii_m3em_weight700_upright.ttf
+ *   'm' has 3em width and others have 1em width. The metadata has weight=700, non-italic value.
+ * - ascii_n3em_weight700_italic.ttf
+ *   'n' has 3em width and others have 1em width. The metadata has weight=700, italic value.
+ * - ascii_o3em_weight800_upright.ttf
+ *   'o' has 3em width and others have 1em width. The metadata has weight=800, non-italic value.
+ * - ascii_p3em_weight800_italic.ttf
+ *   'p' has 3em width and others have 1em width. The metadata has weight=800, italic value.
+ * - ascii_q3em_weight900_upright.ttf
+ *   'q' has 3em width and others have 1em width. The metadata has weight=900, non-italic value.
+ * - ascii_r3em_weight900_italic.ttf
+ *   'r' has 3em width and others have 1em width. The metadata has weight=900, italic value.
+ *
+ * In addition to above font files, this class provides a font collection file and a variable font
+ * file.
+ * - ascii.ttc
+ *   The collection of above 18 fonts with above order.
+ * - ascii_vf.ttf
+ *   This font supports a-z characters and all characters has 1em width. This font supports 'wght',
+ *   'ital' axes but no effect for the glyph width. This font also supports 'Asc[a-z]' 26 axes which
+ *   makes glyph width 3em. For example, 'Asca 1.0' makes a glyph width of 'a' 3em, 'Ascb 1.0' makes
+ *   a glyph width of 'b' 3em. With these axes, above font can be replicated like
+ *   - 'Asca' 1.0, 'wght' 100.0' is equivalent with ascii_a3em_width100_upright.ttf
+ *   - 'Ascb' 1.0, 'wght' 100.0, 'ital' 1.0' is equivalent with ascii_b3em_width100_italic.ttf
+ */
+public class FontTestUtil {
+    private static final String FAMILY_SELECTION_FONT_PATH_IN_ASSET = "fonts_for_family_selection";
+    private static final List<Pair<Integer, Boolean>> sStyleList;
+    private static final Map<Pair<Integer, Boolean>, String> sFontMap;
+    private static final Map<Pair<Integer, Boolean>, Integer> sTtcMap;
+    private static final Map<Pair<Integer, Boolean>, String> sVariationSettingsMap;
+    private static final String[] sFontList = {  // Same order of ascii.ttc
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_a3em_weight100_upright.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_b3em_weight100_italic.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_c3em_weight200_upright.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_d3em_weight200_italic.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_e3em_weight300_upright.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_f3em_weight300_italic.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_g3em_weight400_upright.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_h3em_weight400_italic.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_i3em_weight500_upright.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_j3em_weight500_italic.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_k3em_weight600_upright.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_l3em_weight600_italic.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_m3em_weight700_upright.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_n3em_weight700_italic.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_o3em_weight800_upright.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_p3em_weight800_italic.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_q3em_weight900_upright.ttf",
+            FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/fonts/ascii_r3em_weight900_italic.ttf",
+    };
+
+    private static final String[] FONT_VARIATION_SETTING_LIST = {
+            "'Asca' 1.0, 'wght' 100.0",
+            "'Ascb' 1.0, 'wght' 100.0, 'ital' 1.0",
+            "'Ascc' 1.0, 'wght' 200.0",
+            "'Ascd' 1.0, 'wght' 200.0, 'ital' 1.0",
+            "'Asce' 1.0, 'wght' 300.0",
+            "'Ascf' 1.0, 'wght' 300.0, 'ital' 1.0",
+            "'Ascg' 1.0, 'wght' 400.0",
+            "'Asch' 1.0, 'wght' 400.0, 'ital' 1.0",
+            "'Asci' 1.0, 'wght' 500.0",
+            "'Ascj' 1.0, 'wght' 500.0, 'ital' 1.0",
+            "'Asck' 1.0, 'wght' 600.0",
+            "'Ascl' 1.0, 'wght' 600.0, 'ital' 1.0",
+            "'Ascm' 1.0, 'wght' 700.0",
+            "'Ascn' 1.0, 'wght' 700.0, 'ital' 1.0",
+            "'Asco' 1.0, 'wght' 800.0",
+            "'Ascp' 1.0, 'wght' 800.0, 'ital' 1.0",
+            "'Ascq' 1.0, 'wght' 900.0",
+            "'Ascr' 1.0, 'wght' 900.0, 'ital' 1.0",
+    };
+
+    static {
+        // Style list with the same order of sFontList.
+        ArrayList<Pair<Integer, Boolean>> styles = new ArrayList<>();
+        styles.add(new Pair<>(100, false));
+        styles.add(new Pair<>(100, true));
+        styles.add(new Pair<>(200, false));
+        styles.add(new Pair<>(200, true));
+        styles.add(new Pair<>(300, false));
+        styles.add(new Pair<>(300, true));
+        styles.add(new Pair<>(400, false));
+        styles.add(new Pair<>(400, true));
+        styles.add(new Pair<>(500, false));
+        styles.add(new Pair<>(500, true));
+        styles.add(new Pair<>(600, false));
+        styles.add(new Pair<>(600, true));
+        styles.add(new Pair<>(700, false));
+        styles.add(new Pair<>(700, true));
+        styles.add(new Pair<>(800, false));
+        styles.add(new Pair<>(800, true));
+        styles.add(new Pair<>(900, false));
+        styles.add(new Pair<>(900, true));
+        sStyleList = Collections.unmodifiableList(styles);
+
+        HashMap<Pair<Integer, Boolean>, String> map = new HashMap<>();
+        HashMap<Pair<Integer, Boolean>, Integer> ttcMap = new HashMap<>();
+        HashMap<Pair<Integer, Boolean>, String> variationMap = new HashMap<>();
+        HashMap<Character, Pair<Integer, Boolean>> reverseMap = new HashMap<>();
+        for (int i = 0; i < sFontList.length; ++i) {
+            map.put(sStyleList.get(i), sFontList[i]);
+            ttcMap.put(sStyleList.get(i), i);
+            variationMap.put(sStyleList.get(i), FONT_VARIATION_SETTING_LIST[i]);
+        }
+        sFontMap = Collections.unmodifiableMap(map);
+        sTtcMap = Collections.unmodifiableMap(ttcMap);
+        sVariationSettingsMap = Collections.unmodifiableMap(variationMap);
+    }
+
+    /**
+     * Returns a path to the font collection file in asset directory.
+     */
+    public static String getTtcFontFileInAsset() {
+        return FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ascii.ttc";
+    }
+
+    /**
+     * Returns a path to the variable font file in asset directory.
+     */
+    public static String getVFFontInAsset() {
+        return FAMILY_SELECTION_FONT_PATH_IN_ASSET + "/ascii_vf.ttf";
+    }
+
+    /**
+     * Returns a ttc index of the specified style.
+     */
+    public static int getTtcIndexFromStyle(int weight, boolean italic) {
+        return sTtcMap.get(new Pair<>(weight, italic)).intValue();
+    }
+
+    /**
+     * Returns a variation settings string of the specified style.
+     */
+    public static String getVarSettingsFromStyle(int weight, boolean italic) {
+        return sVariationSettingsMap.get(new Pair<>(weight, italic));
+    }
+
+    /**
+     * Returns a font path from the specified style.
+     */
+    public static String getFontPathFromStyle(int weight, boolean italic) {
+        return sFontMap.get(new Pair<>(weight, italic));
+    }
+
+    /**
+     * Returns all supported styles.
+     */
+    public static List<Pair<Integer, Boolean>> getAllStyles() {
+        return sStyleList;
+    }
+}
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index eaabdc8..dd34f1f 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -23,9 +23,12 @@
 
 import android.content.Context;
 import android.content.res.AssetManager;
+import android.graphics.fonts.FontFamily;
+import android.graphics.fonts.SystemFonts;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.text.FontConfig;
 import android.util.ArrayMap;
 
 import org.junit.After;
@@ -112,7 +115,9 @@
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
-        Typeface.buildSystemFallback(TEST_FONTS_XML, TEST_FONT_DIR, fontMap, fallbackMap);
+        final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(TEST_FONTS_XML,
+                TEST_FONT_DIR, fallbackMap);
+        Typeface.initSystemDefaultTypefaces(fontMap, fallbackMap, aliases);
     }
 
     @Test
@@ -120,10 +125,14 @@
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
 
-        Typeface.buildSystemFallback(SYSTEM_FONTS_XML, SYSTEM_FONT_DIR, fontMap, fallbackMap);
+        final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(SYSTEM_FONTS_XML,
+                SYSTEM_FONT_DIR, fallbackMap);
 
-        assertFalse(fontMap.isEmpty());
+        assertNotNull(aliases);
         assertFalse(fallbackMap.isEmpty());
+
+        Typeface.initSystemDefaultTypefaces(fontMap, fallbackMap, aliases);
+        assertFalse(fontMap.isEmpty());
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/net/UriCodecTest.java b/core/tests/coretests/src/android/net/UriCodecTest.java
new file mode 100644
index 0000000..7fe9402
--- /dev/null
+++ b/core/tests/coretests/src/android/net/UriCodecTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import junit.framework.TestCase;
+
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Tests for {@link UriCodec}
+ */
+public class UriCodecTest extends TestCase {
+
+    public void testDecode_emptyString_returnsEmptyString() {
+        assertEquals("", UriCodec.decode("",
+                false /* convertPlus */,
+                StandardCharsets.UTF_8,
+                true /* throwOnFailure */));
+    }
+
+    public void testDecode_wrongHexDigit_fails() {
+        try {
+            // %p in the end.
+            UriCodec.decode("ab%2f$%C4%82%25%e0%a1%80%p",
+                    false /* convertPlus */,
+                    StandardCharsets.UTF_8,
+                    true /* throwOnFailure */);
+            fail("Expected URISyntaxException");
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+    }
+
+    public void testDecode_secondHexDigitWrong_fails() {
+        try {
+            // %1p in the end.
+            UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80%1p",
+                    false /* convertPlus */,
+                    StandardCharsets.UTF_8,
+                    true /* throwOnFailure */);
+            fail("Expected URISyntaxException");
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+    }
+
+    public void testDecode_endsWithPercent_fails() {
+        try {
+            // % in the end.
+            UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80%",
+                    false /* convertPlus */,
+                    StandardCharsets.UTF_8,
+                    true /* throwOnFailure */);
+            fail("Expected URISyntaxException");
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+    }
+
+    public void testDecode_dontThrowException_appendsUnknownCharacter() {
+        assertEquals("ab/$\u0102%\u0840\ufffd",
+                UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80%",
+                        false /* convertPlus */,
+                        StandardCharsets.UTF_8,
+                        false /* throwOnFailure */));
+    }
+
+    public void testDecode_convertPlus() {
+        assertEquals("ab/$\u0102% \u0840",
+                UriCodec.decode("ab%2f$%c4%82%25+%e0%a1%80",
+                        true /* convertPlus */,
+                        StandardCharsets.UTF_8,
+                        false /* throwOnFailure */));
+    }
+
+    // Last character needs decoding (make sure we are flushing the buffer with chars to decode).
+    public void testDecode_lastCharacter() {
+        assertEquals("ab/$\u0102%\u0840",
+                UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80",
+                        false /* convertPlus */,
+                        StandardCharsets.UTF_8,
+                        true /* throwOnFailure */));
+    }
+
+    // Check that a second row of encoded characters is decoded properly (internal buffers are
+    // reset properly).
+    public void testDecode_secondRowOfEncoded() {
+        assertEquals("ab/$\u0102%\u0840aa\u0840",
+                UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80aa%e0%a1%80",
+                        false /* convertPlus */,
+                        StandardCharsets.UTF_8,
+                        true /* throwOnFailure */));
+    }
+}
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 0bc3a2d..9c9f11b 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -193,7 +193,7 @@
 
             try (MemoryPipe in = MemoryPipe.createSource(source);
                     FileOutputStream out = new FileOutputStream(dest)) {
-                FileUtils.copy(in.getFD(), out.getFD(), null, null, size);
+                FileUtils.copy(in.getFD(), out.getFD(), size, null, null, null);
             }
 
             actual = readFile(dest);
diff --git a/core/tests/coretests/src/android/os/WorkSourceTest.java b/core/tests/coretests/src/android/os/WorkSourceTest.java
index 952a64d..425ab89 100644
--- a/core/tests/coretests/src/android/os/WorkSourceTest.java
+++ b/core/tests/coretests/src/android/os/WorkSourceTest.java
@@ -378,6 +378,17 @@
         assertEquals(75, ws1.getWorkChains().get(0).getAttributionUid());
     }
 
+    public void testRemove_fromSameWorkSource() {
+        WorkSource ws1 = new WorkSource(50, "foo");
+        WorkSource ws2 = ws1;
+        ws2.add(ws1);
+        assertTrue(ws2.remove(ws1));
+
+        assertEquals(0, ws1.size());
+        assertEquals(50, ws1.get(0));
+        assertEquals("foo", ws1.getName(0));
+    }
+
     public void testTransferWorkChains() {
         WorkSource ws1 = new WorkSource();
         WorkChain wc1 = ws1.createWorkChain().addNode(100, "tag");
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 7d48987..71627ab 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -66,7 +66,6 @@
                     Settings.System.LOCKSCREEN_DISABLED, // ?
                     Settings.System.MEDIA_BUTTON_RECEIVER, // candidate for backup?
                     Settings.System.MUTE_STREAMS_AFFECTED, //  candidate for backup?
-                    Settings.System.NOTIFICATION_LIGHT_PULSE, // candidate for backup?
                     Settings.System.NOTIFICATION_SOUND_CACHE, // internal cache
                     Settings.System.POINTER_LOCATION, // backup candidate?
                     Settings.System.DEBUG_ENABLE_ENHANCED_CALL_BLOCKING, // used for testing only
@@ -98,6 +97,7 @@
     private static final Set<String> BACKUP_BLACKLISTED_GLOBAL_SETTINGS =
             newHashSet(
                     Settings.Global.ACTIVITY_MANAGER_CONSTANTS,
+                    Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED,
                     Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED,
                     Settings.Global.ADB_ENABLED,
                     Settings.Global.ADD_USERS_WHEN_LOCKED,
@@ -120,10 +120,14 @@
                     Settings.Global.ASSISTED_GPS_ENABLED,
                     Settings.Global.AUDIO_SAFE_VOLUME_STATE,
                     Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES,
+                    Settings.Global.AUTOFILL_LOGGING_LEVEL,
+                    Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
+                    Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
                     Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
                     Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
                     Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
                     Settings.Global.BATTERY_STATS_CONSTANTS,
+                    Settings.Global.BINDER_CALLS_STATS,
                     Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE,
                     Settings.Global.BLE_SCAN_LOW_POWER_WINDOW_MS,
                     Settings.Global.BLE_SCAN_LOW_POWER_INTERVAL_MS,
@@ -380,16 +384,14 @@
                     Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL,
                     Settings.Global.SETUP_PREPAID_DETECTION_REDIR_HOST,
                     Settings.Global.SETUP_PREPAID_DETECTION_TARGET_URL,
+                    Settings.Global.SETTINGS_USE_EXTERNAL_PROVIDER_API,
+                    Settings.Global.SETTINGS_USE_PSD_API,
                     Settings.Global.SHORTCUT_MANAGER_CONSTANTS,
                     Settings.Global.SHOW_FIRST_CRASH_DIALOG,
                     Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG,
                     Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
                     Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
                     Settings.Global.SHOW_TEMPERATURE_WARNING,
-                    Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION,
-                    Settings.Global.SHOW_ZEN_SETTINGS_SUGGESTION,
-                    Settings.Global.ZEN_SETTINGS_UPDATED,
-                    Settings.Global.ZEN_SETTINGS_SUGGESTION_VIEWED,
                     Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
                     Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL,
                     Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
@@ -485,6 +487,7 @@
                     Settings.Global.WIFI_SAVED_STATE,
                     Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE,
                     Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,
+                    Settings.Global.WIFI_SCAN_THROTTLE_ENABLED,
                     Settings.Global.WIFI_SCORE_PARAMS,
                     Settings.Global.WIFI_SLEEP_POLICY,
                     Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
@@ -492,8 +495,8 @@
                     Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED,
                     Settings.Global.WIFI_WATCHDOG_ON,
                     Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON,
-                    Settings.Global.WINDOW_ANIMATION_SCALE,
                     Settings.Global.CHARGING_STARTED_SOUND,
+                    Settings.Global.WINDOW_ANIMATION_SCALE,
                     Settings.Global.WTF_IS_FATAL,
                     Settings.Global.ZEN_MODE,
                     Settings.Global.ZEN_MODE_CONFIG_ETAG,
@@ -559,10 +562,8 @@
                  Settings.Secure.LAST_SETUP_SHOWN,
                  Settings.Secure.LOCATION_CHANGER,
                  Settings.Secure.LOCATION_MODE,
-                 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, // Candidate?
                  Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT, // Candidate?
                  Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
-                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, // Candidate?
                  Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
                  Settings.Secure.MANAGED_PROFILE_CONTACT_REMOTE_SEARCH,
                  Settings.Secure.MULTI_PRESS_TIMEOUT,
@@ -596,13 +597,15 @@
                  Settings.Secure.SEARCH_THREAD_KEEPALIVE_SECONDS,
                  Settings.Secure.SEARCH_WEB_RESULTS_OVERRIDE_LIMIT,
                  Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
+                 Settings.Secure.SELECTED_SPELL_CHECKER,  // Intentionally removed in Q
+                 Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE,  // Intentionally removed in Q
                  Settings.Secure.SETTINGS_CLASSNAME,
                  Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, // candidate?
                  Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
                  Settings.Secure.SKIP_FIRST_USE_HINTS, // candidate?
                  Settings.Secure.SLEEP_TIMEOUT,
                  Settings.Secure.SMS_DEFAULT_APPLICATION,
-                 Settings.Secure.THEME_MODE,
+                 Settings.Secure.SPELL_CHECKER_ENABLED,  // Intentionally removed in Q
                  Settings.Secure.TRUST_AGENTS_INITIALIZED,
                  Settings.Secure.TV_INPUT_CUSTOM_LABELS,
                  Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
@@ -705,3 +708,4 @@
     }
 
 }
+
diff --git a/core/tests/coretests/src/android/text/FontFallbackSetup.java b/core/tests/coretests/src/android/text/FontFallbackSetup.java
index ced74ee..6c34043 100644
--- a/core/tests/coretests/src/android/text/FontFallbackSetup.java
+++ b/core/tests/coretests/src/android/text/FontFallbackSetup.java
@@ -19,8 +19,9 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.AssetManager;
-import android.graphics.FontFamily;
 import android.graphics.Typeface;
+import android.graphics.fonts.FontFamily;
+import android.graphics.fonts.SystemFonts;
 import android.support.test.InstrumentationRegistry;
 import android.util.ArrayMap;
 
@@ -73,7 +74,9 @@
         }
 
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
-        Typeface.buildSystemFallback(testFontsXml, mTestFontsDir, mFontMap, fallbackMap);
+        final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(testFontsXml,
+                mTestFontsDir, fallbackMap);
+        Typeface.initSystemDefaultTypefaces(mFontMap, fallbackMap, aliases);
     }
 
     @NonNull
diff --git a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
index 6f1d47d..f3d6013 100644
--- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
+++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import android.content.Context;
 import android.graphics.Typeface;
@@ -72,7 +73,7 @@
         assertEquals(0, mt.getWidths().size());
         assertEquals(0, mt.getSpanEndCache().size());
         assertEquals(0, mt.getFontMetrics().size());
-        assertEquals(0, mt.getNativePtr());
+        assertNull(mt.getNativeMeasuredParagraph());
 
         // Recycle it
         MeasuredParagraph mt2 = MeasuredParagraph.buildForBidi("_VVV_", 1, 4, RTL, mt);
@@ -84,7 +85,7 @@
         assertEquals(0, mt2.getWidths().size());
         assertEquals(0, mt2.getSpanEndCache().size());
         assertEquals(0, mt2.getFontMetrics().size());
-        assertEquals(0, mt2.getNativePtr());
+        assertNull(mt.getNativeMeasuredParagraph());
 
         mt2.recycle();
     }
@@ -106,7 +107,7 @@
         assertEquals(10, mt.getWidths().get(2), 0);
         assertEquals(0, mt.getSpanEndCache().size());
         assertEquals(0, mt.getFontMetrics().size());
-        assertEquals(0, mt.getNativePtr());
+        assertNull(mt.getNativeMeasuredParagraph());
 
         // Recycle it
         MeasuredParagraph mt2 =
@@ -123,7 +124,7 @@
         assertEquals(5, mt2.getWidths().get(2), 0);
         assertEquals(0, mt2.getSpanEndCache().size());
         assertEquals(0, mt2.getFontMetrics().size());
-        assertEquals(0, mt2.getNativePtr());
+        assertNull(mt.getNativeMeasuredParagraph());
 
         mt2.recycle();
     }
@@ -143,7 +144,7 @@
         assertEquals(1, mt.getSpanEndCache().size());
         assertEquals(3, mt.getSpanEndCache().get(0));
         assertNotEquals(0, mt.getFontMetrics().size());
-        assertNotEquals(0, mt.getNativePtr());
+        assertNotNull(mt.getNativeMeasuredParagraph());
 
         // Recycle it
         MeasuredParagraph mt2 =
@@ -158,7 +159,7 @@
         assertEquals(1, mt2.getSpanEndCache().size());
         assertEquals(4, mt2.getSpanEndCache().get(0));
         assertNotEquals(0, mt2.getFontMetrics().size());
-        assertNotEquals(0, mt2.getNativePtr());
+        assertNotNull(mt.getNativeMeasuredParagraph());
 
         mt2.recycle();
     }
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index 870d6b2..72290bf 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -785,4 +785,11 @@
         assertEquals(2, TextUtils.length("  "));
         assertEquals(6, TextUtils.length("Hello!"));
     }
+
+    @Test
+    public void testTrimToLengthWithEllipsis() {
+        assertEquals("ABC...", TextUtils.trimToLengthWithEllipsis("ABCDEF", 3));
+        assertEquals("ABC", TextUtils.trimToLengthWithEllipsis("ABC", 3));
+        assertEquals("", TextUtils.trimToLengthWithEllipsis("", 3));
+    }
 }
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index 15dbbc8..c98e646 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -20,6 +20,7 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.Suppress;
 import android.text.InputType;
 import android.util.KeyUtils;
 import android.view.KeyEvent;
@@ -238,6 +239,7 @@
     }
 
     @Test
+    @Suppress
     public void testEmojiModifier() {
         EditorState state = new EditorState();
 
@@ -267,6 +269,7 @@
     }
 
     @Test
+    @Suppress
     public void testMixedEdgeCases() {
         EditorState state = new EditorState();
 
diff --git a/core/tests/coretests/src/android/util/Base64Test.java b/core/tests/coretests/src/android/util/Base64Test.java
index 3aee583..af608c3 100644
--- a/core/tests/coretests/src/android/util/Base64Test.java
+++ b/core/tests/coretests/src/android/util/Base64Test.java
@@ -18,13 +18,18 @@
 
 import android.support.test.filters.LargeTest;
 
+import junit.framework.TestCase;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.Random;
-import junit.framework.TestCase;
+import java.util.stream.Collectors;
 
 @LargeTest
 public class Base64Test extends TestCase {
@@ -530,4 +535,74 @@
             assertEquals(plain, actual);
         }
     }
+
+    public void testOutputStream_ioExceptionDuringClose() {
+        OutputStream out = new OutputStream() {
+            @Override public void write(int b) throws IOException { }
+            @Override public void close() throws IOException {
+                throw new IOException("close()");
+            }
+        };
+        OutputStream out2 = new Base64OutputStream(out, Base64.DEFAULT);
+        try {
+            out2.close();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testOutputStream_ioExceptionDuringCloseAndWrite() {
+        OutputStream out = new OutputStream() {
+            @Override public void write(int b) throws IOException {
+                throw new IOException("write()");
+            }
+            @Override public void write(byte[] b) throws IOException {
+                throw new IOException("write()");
+            }
+            @Override public void write(byte[] b, int off, int len) throws IOException {
+                throw new IOException("write()");
+            }
+            @Override public void close() throws IOException {
+                throw new IOException("close()");
+            }
+        };
+        OutputStream out2 = new Base64OutputStream(out, Base64.DEFAULT);
+        try {
+            out2.close();
+            fail();
+        } catch (IOException expected) {
+            // Base64OutputStream write()s pending (possibly empty) data
+            // before close(), so the IOE from write() should be thrown and
+            // any later exception suppressed.
+            assertEquals("write()", expected.getMessage());
+            Throwable[] suppressed = expected.getSuppressed();
+            List<String> suppressedMessages = Arrays.asList(suppressed).stream()
+                    .map((e) -> e.getMessage())
+                    .collect(Collectors.toList());
+            assertEquals(Collections.singletonList("close()"), suppressedMessages);
+        }
+    }
+
+    public void testOutputStream_ioExceptionDuringWrite() {
+        OutputStream out = new OutputStream() {
+            @Override public void write(int b) throws IOException {
+                throw new IOException("write()");
+            }
+            @Override public void write(byte[] b) throws IOException {
+                throw new IOException("write()");
+            }
+            @Override public void write(byte[] b, int off, int len) throws IOException {
+                throw new IOException("write()");
+            }
+        };
+        // Base64OutputStream write()s pending (possibly empty) data
+        // before close(), so the IOE from write() should be thrown.
+        OutputStream out2 = new Base64OutputStream(out, Base64.DEFAULT);
+        try {
+            out2.close();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
 }
diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
index 6ee74cb..fe45fe7 100644
--- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java
+++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
@@ -19,6 +19,7 @@
 import static android.view.DisplayCutout.NO_CUTOUT;
 import static android.view.DisplayCutout.fromSpec;
 
+import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.sameInstance;
 import static org.junit.Assert.assertEquals;
@@ -220,6 +221,19 @@
     }
 
     @Test
+    public void fromSpec_setsSafeInsets_top() {
+        DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z", 200, 400, 2f);
+        assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 0)));
+    }
+
+    @Test
+    public void fromSpec_setsSafeInsets_top_and_bottom() {
+        DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z"
+                + "@bottom M -50,0 v -10,0 h 100 v 20 z", 200, 400, 2f);
+        assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 10)));
+    }
+
+    @Test
     public void parcel_unparcel_nocutout() {
         Parcel p = Parcel.obtain();
 
diff --git a/core/tests/coretests/src/android/view/KeyEventTest.java b/core/tests/coretests/src/android/view/KeyEventTest.java
index aabf816..b9d95e5 100644
--- a/core/tests/coretests/src/android/view/KeyEventTest.java
+++ b/core/tests/coretests/src/android/view/KeyEventTest.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import static android.view.Display.INVALID_DISPLAY;
+
 import static org.junit.Assert.assertEquals;
 
 import android.support.test.filters.SmallTest;
@@ -28,12 +30,71 @@
 @RunWith(AndroidJUnit4.class)
 public class KeyEventTest {
 
+    private static final int DOWN_TIME = 50;
+    private static final long EVENT_TIME = 100;
+    private static final int ACTION = KeyEvent.ACTION_DOWN;
+    private static final int KEYCODE = KeyEvent.KEYCODE_0;
+    private static final int REPEAT = 0;
+    private static final int METASTATE = 0;
+    private static final int DEVICE_ID = 0;
+    private static final int SCAN_CODE = 0;
+    private static final int FLAGS = 0;
+    private static final int SOURCE = InputDevice.SOURCE_KEYBOARD;
+    private static final String CHARACTERS = null;
+
     @Test
     public void testObtain() {
-        KeyEvent keyEvent = KeyEvent.obtain(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0,
-                0, 0, 0, 0, 0, InputDevice.SOURCE_KEYBOARD, null);
-        assertEquals(KeyEvent.ACTION_DOWN, keyEvent.getAction());
-        assertEquals(KeyEvent.KEYCODE_0, keyEvent.getKeyCode());
-        assertEquals(InputDevice.SOURCE_KEYBOARD, keyEvent.getSource());
+        KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+                METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, CHARACTERS);
+        assertEquals(DOWN_TIME, keyEvent.getDownTime());
+        assertEquals(EVENT_TIME, keyEvent.getEventTime());
+        assertEquals(ACTION, keyEvent.getAction());
+        assertEquals(KEYCODE, keyEvent.getKeyCode());
+        assertEquals(REPEAT, keyEvent.getRepeatCount());
+        assertEquals(METASTATE, keyEvent.getMetaState());
+        assertEquals(DEVICE_ID, keyEvent.getDeviceId());
+        assertEquals(SCAN_CODE, keyEvent.getScanCode());
+        assertEquals(FLAGS, keyEvent.getFlags());
+        assertEquals(SOURCE, keyEvent.getSource());
+        assertEquals(INVALID_DISPLAY, keyEvent.getDisplayId());
+        assertEquals(CHARACTERS, keyEvent.getCharacters());
+    }
+
+    @Test
+    public void testObtainFromKeyEvent() {
+        KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+                METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, CHARACTERS);
+        KeyEvent keyEvent2 = KeyEvent.obtain(keyEvent);
+        assertEquals(keyEvent.getDownTime(), keyEvent2.getDownTime());
+        assertEquals(keyEvent.getEventTime(), keyEvent2.getEventTime());
+        assertEquals(keyEvent.getAction(), keyEvent2.getAction());
+        assertEquals(keyEvent.getKeyCode(), keyEvent2.getKeyCode());
+        assertEquals(keyEvent.getRepeatCount(), keyEvent2.getRepeatCount());
+        assertEquals(keyEvent.getMetaState(), keyEvent2.getMetaState());
+        assertEquals(keyEvent.getDeviceId(), keyEvent2.getDeviceId());
+        assertEquals(keyEvent.getScanCode(), keyEvent2.getScanCode());
+        assertEquals(keyEvent.getFlags(), keyEvent2.getFlags());
+        assertEquals(keyEvent.getSource(), keyEvent2.getSource());
+        assertEquals(keyEvent.getDisplayId(), keyEvent2.getDisplayId());
+        assertEquals(keyEvent.getCharacters(), keyEvent2.getCharacters());
+    }
+
+    @Test
+    public void testObtainWithDisplayId() {
+        final int displayId = 5;
+        KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+                METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, displayId, CHARACTERS);
+        assertEquals(DOWN_TIME, keyEvent.getDownTime());
+        assertEquals(EVENT_TIME, keyEvent.getEventTime());
+        assertEquals(ACTION, keyEvent.getAction());
+        assertEquals(KEYCODE, keyEvent.getKeyCode());
+        assertEquals(REPEAT, keyEvent.getRepeatCount());
+        assertEquals(METASTATE, keyEvent.getMetaState());
+        assertEquals(DEVICE_ID, keyEvent.getDeviceId());
+        assertEquals(SCAN_CODE, keyEvent.getScanCode());
+        assertEquals(FLAGS, keyEvent.getFlags());
+        assertEquals(SOURCE, keyEvent.getSource());
+        assertEquals(displayId, keyEvent.getDisplayId());
+        assertEquals(CHARACTERS, keyEvent.getCharacters());
     }
 }
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
index 4de8155..7f675ff 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
@@ -300,6 +300,26 @@
     }
 
     @Test
+    public void subTreeChangeEventFromUncachedNode_clearsNodeInCache() {
+        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(CHILD_VIEW_ID, WINDOW_ID_1);
+        long id = nodeInfo.getSourceNodeId();
+        mAccessibilityCache.add(nodeInfo);
+        nodeInfo.recycle();
+
+        AccessibilityEvent event = AccessibilityEvent
+                .obtain(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+        event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
+        event.setSource(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
+
+        mAccessibilityCache.onAccessibilityEvent(event);
+        AccessibilityNodeInfo shouldBeNull = mAccessibilityCache.getNode(WINDOW_ID_1, id);
+        if (shouldBeNull != null) {
+            shouldBeNull.recycle();
+        }
+        assertNull(shouldBeNull);
+    }
+
+    @Test
     public void scrollEvent_clearsNodeAndChild() {
         AccessibilityEvent event = AccessibilityEvent
                 .obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
@@ -481,7 +501,7 @@
     }
 
     @Test
-    public void addNode_whenNodeBeingReplacedIsOwnGrandparent_doesntCrash() {
+    public void addNode_whenNodeBeingReplacedIsOwnGrandparentWithTwoChildren_doesntCrash() {
         AccessibilityNodeInfo parentNodeInfo =
                 getNodeWithA11yAndWindowId(PARENT_VIEW_ID, WINDOW_ID_1);
         parentNodeInfo.addChild(getMockViewWithA11yAndWindowIds(CHILD_VIEW_ID, WINDOW_ID_1));
@@ -505,6 +525,29 @@
     }
 
     @Test
+    public void addNode_whenNodeBeingReplacedIsOwnGrandparentWithOneChild_doesntCrash() {
+        AccessibilityNodeInfo parentNodeInfo =
+                getNodeWithA11yAndWindowId(PARENT_VIEW_ID, WINDOW_ID_1);
+        parentNodeInfo.addChild(getMockViewWithA11yAndWindowIds(CHILD_VIEW_ID, WINDOW_ID_1));
+        AccessibilityNodeInfo childNodeInfo =
+                getNodeWithA11yAndWindowId(CHILD_VIEW_ID, WINDOW_ID_1);
+        childNodeInfo.setParent(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
+        childNodeInfo.addChild(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
+
+        AccessibilityNodeInfo replacementParentNodeInfo =
+                getNodeWithA11yAndWindowId(PARENT_VIEW_ID, WINDOW_ID_1);
+        try {
+            mAccessibilityCache.add(parentNodeInfo);
+            mAccessibilityCache.add(childNodeInfo);
+            mAccessibilityCache.add(replacementParentNodeInfo);
+        } finally {
+            parentNodeInfo.recycle();
+            childNodeInfo.recycle();
+            replacementParentNodeInfo.recycle();
+        }
+    }
+
+    @Test
     public void testCacheCriticalEventList_doesntLackEvents() {
         for (int i = 0; i < 32; i++) {
             int eventType = 1 << i;
@@ -523,6 +566,27 @@
         }
     }
 
+    @Test
+    public void addA11yFocusNodeBeforeFocusClearedEvent_previousA11yFocusNodeGetsRefreshed() {
+        AccessibilityNodeInfo nodeInfo1 = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+        nodeInfo1.setAccessibilityFocused(true);
+        mAccessibilityCache.add(nodeInfo1);
+        AccessibilityNodeInfo nodeInfo2 = getNodeWithA11yAndWindowId(OTHER_VIEW_ID, WINDOW_ID_1);
+        nodeInfo2.setAccessibilityFocused(true);
+        mAccessibilityCache.add(nodeInfo2);
+        AccessibilityEvent event = AccessibilityEvent.obtain(
+                AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+        event.setSource(getMockViewWithA11yAndWindowIds(SINGLE_VIEW_ID, WINDOW_ID_1));
+        mAccessibilityCache.onAccessibilityEvent(event);
+        event.recycle();
+        try {
+            verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo1, true);
+        } finally {
+            nodeInfo1.recycle();
+            nodeInfo2.recycle();
+        }
+    }
+
     private void assertNodeIsRefreshedWithEventType(int eventType, int contentChangeTypes) {
         AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
         mAccessibilityCache.add(nodeInfo);
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index 44b1f08..0dd7685 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -119,6 +119,10 @@
         return false;
     }
 
+    public int getSoftKeyboardShowMode() {
+        return 0;
+    }
+
     public void setSoftKeyboardCallbackEnabled(boolean enabled) {}
 
     public boolean isAccessibilityButtonAvailable() {
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index b18fa74..a2a40e6 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -16,33 +16,6 @@
 
 package com.android.internal.app;
 
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
@@ -51,11 +24,42 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
+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.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
 @RunWith(AndroidJUnit4.class)
 public class IntentForwarderActivityTest {
+
     private static final ComponentName FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME =
             new ComponentName(
                     "android",
@@ -64,12 +68,14 @@
     private static final String TYPE_PLAIN_TEXT = "text/plain";
 
     private static UserInfo MANAGED_PROFILE_INFO = new UserInfo();
+
     static {
         MANAGED_PROFILE_INFO.id = 10;
         MANAGED_PROFILE_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE;
     }
 
     private static UserInfo CURRENT_USER_INFO = new UserInfo();
+
     static {
         CURRENT_USER_INFO.id = UserHandle.myUserId();
         CURRENT_USER_INFO.flags = 0;
@@ -77,22 +83,30 @@
 
     private static IntentForwarderActivity.Injector sInjector;
     private static ComponentName sComponentName;
+    private static String sActivityName;
+    private static String sPackageName;
 
-    @Mock private IPackageManager mIPm;
-    @Mock private PackageManager mPm;
-    @Mock private UserManager mUserManager;
+    @Mock
+    private IPackageManager mIPm;
+    @Mock
+    private PackageManager mPm;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private ApplicationInfo mApplicationInfo;
 
     @Rule
     public ActivityTestRule<IntentForwarderWrapperActivity> mActivityRule =
             new ActivityTestRule<>(IntentForwarderWrapperActivity.class, true, false);
 
     private Context mContext;
+    public static final String PHONE_NUMBER = "123-456-789";
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mContext = InstrumentationRegistry.getTargetContext();
-        sInjector = new TestInjector();
+        sInjector = spy(new TestInjector());
     }
 
     @Test
@@ -252,8 +266,274 @@
         assertEquals(MANAGED_PROFILE_INFO.id, activity.mUserIdActivityLaunchedIn);
     }
 
+    @Test
+    public void shouldSkipDisclosure_notWhitelisted() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_SEND)
+                .setType(TYPE_PLAIN_TEXT);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_withResolverActivity() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        sActivityName = ResolverActivity.class.getName();
+        sPackageName = "android";
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_SEND)
+                .setType(TYPE_PLAIN_TEXT);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_callIntent_call() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_CALL);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_callIntent_callPrivileged() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_CALL_PRIVILEGED);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_callIntent_callEmergency() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_CALL_EMERGENCY);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_callIntent_dial() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_DIAL);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_callIntent_notCallOrDial() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_ALARM_CHANGED);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_callIntent_actionViewTel() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_VIEW)
+                .addCategory(Intent.CATEGORY_BROWSABLE)
+                .setData(Uri.fromParts("tel", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_sms() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_SENDTO)
+                .setData(Uri.fromParts("sms", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_smsto() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_SENDTO)
+                .setData(Uri.fromParts("smsto", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_mms() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_SENDTO)
+                .setData(Uri.fromParts("mms", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_mmsto() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_SENDTO)
+                .setData(Uri.fromParts("mmsto", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_actionViewSms() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_VIEW)
+                .addCategory(Intent.CATEGORY_BROWSABLE)
+                .setData(Uri.fromParts("sms", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_actionViewSmsto() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_VIEW)
+                .addCategory(Intent.CATEGORY_BROWSABLE)
+                .setData(Uri.fromParts("smsto", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_actionViewMms() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_VIEW)
+                .addCategory(Intent.CATEGORY_BROWSABLE)
+                .setData(Uri.fromParts("mms", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_actionViewMmsto() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_VIEW)
+                .addCategory(Intent.CATEGORY_BROWSABLE)
+                .setData(Uri.fromParts("mmsto", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_invalidUri() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_SENDTO)
+                .setData(Uri.fromParts("invalid", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_viewBrowsableIntent_invalidUri() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_VIEW)
+                .addCategory(Intent.CATEGORY_BROWSABLE)
+                .setData(Uri.fromParts("invalid", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_viewBrowsableIntent_normalUrl() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+                .setAction(Intent.ACTION_VIEW)
+                .addCategory(Intent.CATEGORY_BROWSABLE)
+                .setData(Uri.fromParts("http", "apache.org", null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector).showToast(anyInt(), anyInt());
+    }
+
+    private void setupShouldSkipDisclosureTest() throws RemoteException {
+        sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
+        sActivityName = "MyTestActivity";
+        sPackageName = "test.package.name";
+        when(mApplicationInfo.isSystemApp()).thenReturn(true);
+        // Managed profile exists.
+        List<UserInfo> profiles = new ArrayList<>();
+        profiles.add(CURRENT_USER_INFO);
+        profiles.add(MANAGED_PROFILE_INFO);
+        when(mUserManager.getProfiles(anyInt())).thenReturn(profiles);
+        // Intent can be forwarded.
+        when(mIPm.canForwardTo(
+                any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true);
+    }
 
     public static class IntentForwarderWrapperActivity extends IntentForwarderActivity {
+
         private Intent mStartActivityIntent;
         private int mUserIdActivityLaunchedIn;
 
@@ -276,7 +556,7 @@
         }
     }
 
-    class TestInjector implements IntentForwarderActivity.Injector {
+    public class TestInjector implements IntentForwarderActivity.Injector {
 
         @Override
         public IPackageManager getIPackageManager() {
@@ -292,5 +572,21 @@
         public PackageManager getPackageManager() {
             return mPm;
         }
+
+        @Override
+        public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
+            ActivityInfo activityInfo = new ActivityInfo();
+            activityInfo.packageName = sPackageName;
+            activityInfo.name = sActivityName;
+            activityInfo.applicationInfo = mApplicationInfo;
+
+            ResolveInfo resolveInfo = new ResolveInfo();
+            resolveInfo.activityInfo = activityInfo;
+
+            return resolveInfo;
+        }
+
+        @Override
+        public void showToast(int messageId, int duration) {}
     }
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java
new file mode 100644
index 0000000..10a3189
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Test BatteryStatsHistory.
+ */
+@RunWith(AndroidJUnit4.class)
+public class BatteryStatsHistoryTest {
+    private static final int MAX_HISTORY_FILES = 32;
+    private final BatteryStatsImpl mBatteryStatsImpl = new MockBatteryStatsImpl();
+    private final Parcel mHistoryBuffer = Parcel.obtain();
+    private File mSystemDir;
+    private File mHistoryDir;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        Context context = InstrumentationRegistry.getContext();
+        mSystemDir = context.getDataDir();
+        mHistoryDir = new File(mSystemDir, BatteryStatsHistory.HISTORY_DIR);
+        mHistoryDir.delete();
+    }
+
+    @Test
+    public void testConstruct() {
+        BatteryStatsHistory history =
+                new BatteryStatsHistory(mBatteryStatsImpl, mSystemDir, mHistoryBuffer);
+        verifyFileNumbers(history, Arrays.asList(0));
+        verifyActiveFile(history, "0.bin");
+    }
+
+    @Test
+    public void testCreateNextFile() {
+        BatteryStatsHistory history =
+                new BatteryStatsHistory(mBatteryStatsImpl, mSystemDir, mHistoryBuffer);
+
+        List<Integer> fileList = new ArrayList<>();
+        fileList.add(0);
+
+        // create file 1 to 31.
+        for (int i = 1; i < MAX_HISTORY_FILES; i++) {
+            fileList.add(i);
+            history.createNextFile();
+            verifyFileNumbers(history, fileList);
+            verifyActiveFile(history, i + ".bin");
+        }
+
+        // create file 32
+        history.createNextFile();
+        fileList.add(32);
+        fileList.remove(0);
+        // verify file 0 is deleted.
+        verifyFileDeleted("0.bin");
+        verifyFileNumbers(history, fileList);
+        verifyActiveFile(history, "32.bin");
+
+        // create file 33
+        history.createNextFile();
+        // verify file 1 is deleted
+        fileList.add(33);
+        fileList.remove(0);
+        verifyFileDeleted("1.bin");
+        verifyFileNumbers(history, fileList);
+        verifyActiveFile(history, "33.bin");
+
+        assertEquals(0, history.getHistoryUsedSize());
+
+        // create a new BatteryStatsHistory object, it will pick up existing history files.
+        BatteryStatsHistory history2 =
+                new BatteryStatsHistory(mBatteryStatsImpl, mSystemDir, mHistoryBuffer);
+        // verify construct can pick up all files from file system.
+        verifyFileNumbers(history2, fileList);
+        verifyActiveFile(history2, "33.bin");
+
+        history2.resetAllFiles();
+        // verify all existing files are deleted.
+        for (int i = 2; i < 33; ++i) {
+            verifyFileDeleted(i + ".bin");
+        }
+
+        // verify file 0 is created
+        verifyFileNumbers(history2, Arrays.asList(0));
+        verifyActiveFile(history2, "0.bin");
+
+        // create file 1.
+        history2.createNextFile();
+        verifyFileNumbers(history2, Arrays.asList(0, 1));
+        verifyActiveFile(history2, "1.bin");
+    }
+
+    private void verifyActiveFile(BatteryStatsHistory history, String file) {
+        final File expectedFile = new File(mHistoryDir, file);
+        assertEquals(expectedFile.getPath(), history.getActiveFile().getBaseFile().getPath());
+        assertTrue(expectedFile.exists());
+    }
+
+    private void verifyFileNumbers(BatteryStatsHistory history, List<Integer> fileList) {
+        assertEquals(fileList.size(), history.getFilesNumbers().size());
+        for (int i = 0; i < fileList.size(); i++) {
+            assertEquals(fileList.get(i), history.getFilesNumbers().get(i));
+            final File expectedFile =
+                    new File(mHistoryDir, fileList.get(i) + ".bin");
+            assertTrue(expectedFile.exists());
+        }
+    }
+
+    private void verifyFileDeleted(String file) {
+        assertFalse(new File(mHistoryDir, file).exists());
+    }
+}
\ No newline at end of file
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 a8094ea..613de45 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
@@ -24,6 +24,7 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
@@ -302,6 +303,113 @@
         assertArrayEquals(expected, mBatteryStatsImpl.addCpuTimes(timesA, timesB));
     }
 
+    @Test
+    public void testMulticastWakelockAcqRel() {
+        final int testUid = 10032;
+        final int acquireTimeMs = 1000;
+        final int releaseTimeMs = 1005;
+        final int currentTimeMs = 1011;
+
+        mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+
+        // Create a Uid Object
+        final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
+        assertNotNull(u);
+
+        // Acquire and release the lock
+        u.noteWifiMulticastEnabledLocked(acquireTimeMs);
+        u.noteWifiMulticastDisabledLocked(releaseTimeMs);
+
+        // Get the total acquisition time
+        long totalTime = u.getWifiMulticastTime(currentTimeMs*1000,
+                BatteryStats.STATS_SINCE_UNPLUGGED);
+        assertEquals("Miscalculations of Multicast wakelock acquisition time",
+                (releaseTimeMs - acquireTimeMs) * 1000, totalTime);
+    }
+
+    @Test
+    public void testMulticastWakelockAcqNoRel() {
+        final int testUid = 10032;
+        final int acquireTimeMs = 1000;
+        final int currentTimeMs = 1011;
+
+        mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+
+        // Create a Uid Object
+        final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
+        assertNotNull(u);
+
+        // Acquire the lock
+        u.noteWifiMulticastEnabledLocked(acquireTimeMs);
+
+        // Get the total acquisition time
+        long totalTime =  u.getWifiMulticastTime(currentTimeMs*1000,
+                BatteryStats.STATS_SINCE_UNPLUGGED);
+        assertEquals("Miscalculations of Multicast wakelock acquisition time",
+                (currentTimeMs - acquireTimeMs) * 1000, totalTime);
+    }
+
+    @Test
+    public void testMulticastWakelockAcqAcqRelRel() {
+        final int testUid = 10032;
+        final int acquireTimeMs_1 = 1000;
+        final int acquireTimeMs_2 = 1002;
+
+        final int releaseTimeMs_1 = 1005;
+        final int releaseTimeMs_2 = 1009;
+        final int currentTimeMs = 1011;
+
+        mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+
+        // Create a Uid Object
+        final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
+        assertNotNull(u);
+
+        // Acquire and release the lock (twice in nested way)
+        u.noteWifiMulticastEnabledLocked(acquireTimeMs_1);
+        u.noteWifiMulticastEnabledLocked(acquireTimeMs_2);
+
+        u.noteWifiMulticastDisabledLocked(releaseTimeMs_1);
+        u.noteWifiMulticastDisabledLocked(releaseTimeMs_2);
+
+        // Get the total acquisition time
+        long totalTime =  u.getWifiMulticastTime(currentTimeMs*1000,
+                BatteryStats.STATS_SINCE_UNPLUGGED);
+        assertEquals("Miscalculations of Multicast wakelock acquisition time",
+                (releaseTimeMs_2 - acquireTimeMs_1) * 1000, totalTime);
+    }
+
+    @Test
+    public void testMulticastWakelockAcqRelAcqRel() {
+        final int testUid = 10032;
+        final int acquireTimeMs_1 = 1000;
+        final int acquireTimeMs_2 = 1005;
+
+        final int releaseTimeMs_1 = 1002;
+        final int releaseTimeMs_2 = 1009;
+        final int currentTimeMs = 1011;
+
+        mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+
+        // Create a Uid Object
+        final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
+        assertNotNull(u);
+
+        // Acquire and release the lock (twice)
+        u.noteWifiMulticastEnabledLocked(acquireTimeMs_1);
+        u.noteWifiMulticastDisabledLocked(releaseTimeMs_1);
+
+        u.noteWifiMulticastEnabledLocked(acquireTimeMs_2);
+        u.noteWifiMulticastDisabledLocked(releaseTimeMs_2);
+
+        // Get the total acquisition time
+        long totalTime =  u.getWifiMulticastTime(currentTimeMs*1000,
+                BatteryStats.STATS_SINCE_UNPLUGGED);
+        assertEquals("Miscalculations of Multicast wakelock acquisition time",
+                ((releaseTimeMs_1 - acquireTimeMs_1) + (releaseTimeMs_2 - acquireTimeMs_2))
+                * 1000, totalTime);
+    }
+
     private void addIsolatedUid(int parentUid, int childUid) {
         final BatteryStatsImpl.Uid u = mBatteryStatsImpl.getUidStatsLocked(parentUid);
         u.addIsolatedUid(childUid);
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 94492ba..b798042 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -26,6 +26,7 @@
         BatteryStatsDualTimerTest.class,
         BatteryStatsDurationTimerTest.class,
         BatteryStatsHelperTest.class,
+        BatteryStatsHistoryTest.class,
         BatteryStatsImplTest.class,
         BatteryStatsNoteTest.class,
         BatteryStatsSamplingTimerTest.class,
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index b7fef13..ace6b2d 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -16,20 +16,32 @@
 
 package com.android.internal.os;
 
+import static org.junit.Assert.assertEquals;
+
+import android.content.Intent;
+import android.os.BatteryManager;
 import android.os.Binder;
+import android.os.OsProtoEnums;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.util.ArrayMap;
 import android.util.SparseArray;
 
+import com.android.internal.os.BinderInternal.CallSession;
+
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.Arrays;
-import java.util.List;
 
-import static org.junit.Assert.assertEquals;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Random;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -41,9 +53,12 @@
 
     @Test
     public void testDetailedOff() {
-        TestBinderCallsStats bcs = new TestBinderCallsStats(false);
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(false);
+        bcs.setSamplingInterval(5);
+
         Binder binder = new Binder();
-        BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+        CallSession callSession = bcs.callStarted(binder, 1);
         bcs.time += 10;
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
 
@@ -51,51 +66,40 @@
         assertEquals(1, uidEntries.size());
         BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
         Assert.assertNotNull(uidEntry);
+        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
         assertEquals(1, uidEntry.callCount);
+        assertEquals(1, uidEntry.recordedCallCount);
         assertEquals(10, uidEntry.cpuTimeMicros);
-        assertEquals("Detailed tracking off - no entries should be returned",
-                0, uidEntry.getCallStatsList().size());
+        assertEquals(binder.getClass(), callStatsList.get(0).binderClass);
+        assertEquals(1, callStatsList.get(0).transactionCode);
 
-        BinderCallsStats.UidEntry sampledEntries = bcs.getSampledEntries();
-        List<BinderCallsStats.CallStat> sampledCallStatsList = sampledEntries.getCallStatsList();
-        assertEquals(1, sampledCallStatsList.size());
-
-
-        assertEquals(1, sampledCallStatsList.get(0).callCount);
-        assertEquals(10, sampledCallStatsList.get(0).cpuTimeMicros);
-        assertEquals(binder.getClass().getName(), sampledCallStatsList.get(0).className);
-        assertEquals(1, sampledCallStatsList.get(0).msg);
-
+        // CPU usage is sampled, should not be tracked here.
         callSession = bcs.callStarted(binder, 1);
         bcs.time += 20;
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
-
-        uidEntry = bcs.getUidEntries().get(TEST_UID);
         assertEquals(2, uidEntry.callCount);
-        // When sampling is enabled, cpu time is only measured for the first transaction in the
-        // sampling interval, for others an average duration of previous transactions is used as
-        // approximation
-        assertEquals(20, uidEntry.cpuTimeMicros);
-        sampledCallStatsList = sampledEntries.getCallStatsList();
-        assertEquals(1, sampledCallStatsList.size());
+        assertEquals(1, uidEntry.recordedCallCount);
+        assertEquals(10, uidEntry.cpuTimeMicros);
+        assertEquals(1, callStatsList.size());
 
         callSession = bcs.callStarted(binder, 2);
         bcs.time += 50;
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
         uidEntry = bcs.getUidEntries().get(TEST_UID);
         assertEquals(3, uidEntry.callCount);
-
-        // This is the first transaction of a new type, so the real CPU time will be measured
-        assertEquals(70, uidEntry.cpuTimeMicros);
-        sampledCallStatsList = sampledEntries.getCallStatsList();
-        assertEquals(2, sampledCallStatsList.size());
+        assertEquals(1, uidEntry.recordedCallCount);
+        // Still sampled even for another API.
+        callStatsList = new ArrayList(uidEntry.getCallStatsList());
+        assertEquals(1, callStatsList.size());
     }
 
     @Test
     public void testDetailedOn() {
-        TestBinderCallsStats bcs = new TestBinderCallsStats(true);
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+
         Binder binder = new Binder();
-        BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+        CallSession callSession = bcs.callStarted(binder, 1);
         bcs.time += 10;
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
 
@@ -105,17 +109,13 @@
         Assert.assertNotNull(uidEntry);
         assertEquals(1, uidEntry.callCount);
         assertEquals(10, uidEntry.cpuTimeMicros);
-        assertEquals(1, uidEntry.getCallStatsList().size());
+        assertEquals(1, new ArrayList(uidEntry.getCallStatsList()).size());
 
-        BinderCallsStats.UidEntry sampledEntries = bcs.getSampledEntries();
-        assertEquals("Sampling is not used when detailed tracking on",
-                0, bcs.getSampledEntries().getCallStatsList().size());
-
-        List<BinderCallsStats.CallStat> callStatsList = uidEntry.getCallStatsList();
+        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
         assertEquals(1, callStatsList.get(0).callCount);
         assertEquals(10, callStatsList.get(0).cpuTimeMicros);
-        assertEquals(binder.getClass().getName(), callStatsList.get(0).className);
-        assertEquals(1, callStatsList.get(0).msg);
+        assertEquals(binder.getClass(), callStatsList.get(0).binderClass);
+        assertEquals(1, callStatsList.get(0).transactionCode);
 
         callSession = bcs.callStarted(binder, 1);
         bcs.time += 20;
@@ -124,7 +124,7 @@
         uidEntry = bcs.getUidEntries().get(TEST_UID);
         assertEquals(2, uidEntry.callCount);
         assertEquals(30, uidEntry.cpuTimeMicros);
-        callStatsList = uidEntry.getCallStatsList();
+        callStatsList = new ArrayList(uidEntry.getCallStatsList());
         assertEquals(1, callStatsList.size());
 
         callSession = bcs.callStarted(binder, 2);
@@ -135,26 +135,228 @@
 
         // This is the first transaction of a new type, so the real CPU time will be measured
         assertEquals(80, uidEntry.cpuTimeMicros);
-        callStatsList = uidEntry.getCallStatsList();
+        callStatsList = new ArrayList(uidEntry.getCallStatsList());
         assertEquals(2, callStatsList.size());
     }
 
     @Test
-    public void testParcelSize() {
-        TestBinderCallsStats bcs = new TestBinderCallsStats(true);
+    public void testEnableInBetweenCall() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
         Binder binder = new Binder();
-        BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(null, REQUEST_SIZE, REPLY_SIZE);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(0, uidEntries.size());
+    }
+
+    @Test
+    public void testInBetweenCallWhenExceptionThrown() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        Binder binder = new Binder();
+        bcs.callThrewException(null, new IllegalStateException());
+        bcs.callEnded(null, REQUEST_SIZE, REPLY_SIZE);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(0, uidEntries.size());
+    }
+
+    @Test
+    public void testSampling() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(false);
+        bcs.setSamplingInterval(2);
+
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        callSession = bcs.callStarted(binder, 1);
+        bcs.time += 1000;  // shoud be ignored.
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        callSession = bcs.callStarted(binder, 1);
+        bcs.time += 50;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(1, uidEntries.size());
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        Assert.assertNotNull(uidEntry);
+        assertEquals(3, uidEntry.callCount);
+        assertEquals(60 /* 10 + 50 */, uidEntry.cpuTimeMicros);
+
+        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+        assertEquals(1, callStatsList.size());
+        BinderCallsStats.CallStat callStats = callStatsList.get(0);
+        assertEquals(3, callStats.callCount);
+        assertEquals(2, callStats.recordedCallCount);
+        assertEquals(60, callStats.cpuTimeMicros);
+        assertEquals(50, callStats.maxCpuTimeMicros);
+        assertEquals(0, callStats.maxRequestSizeBytes);
+        assertEquals(0, callStats.maxReplySizeBytes);
+    }
+
+    @Test
+    public void testSamplingWithDifferentApis() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(false);
+        bcs.setSamplingInterval(2);
+
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        callSession = bcs.callStarted(binder, 2 /* another method */);
+        bcs.time += 1000;  // shoud be ignored.
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(1, uidEntries.size());
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        assertEquals(2, uidEntry.callCount);
+        assertEquals(1, uidEntry.recordedCallCount);
+        assertEquals(10, uidEntry.cpuTimeMicros);
+
+        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+        assertEquals(1, callStatsList.size());
+
+        BinderCallsStats.CallStat callStats = callStatsList.get(0);
+        assertEquals(1, callStats.callCount);
+        assertEquals(1, callStats.recordedCallCount);
+        assertEquals(10, callStats.cpuTimeMicros);
+        assertEquals(10, callStats.maxCpuTimeMicros);
+    }
+
+    private static class BinderWithGetTransactionName extends Binder {
+        public static String getDefaultTransactionName(int code) {
+            return "resolved";
+        }
+    }
+
+    private static class AnotherBinderWithGetTransactionName extends Binder {
+        public static String getDefaultTransactionName(int code) {
+            return "foo" + code;
+        }
+    }
+
+    @Test
+    public void testTransactionCodeResolved() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new BinderWithGetTransactionName();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        List<BinderCallsStats.ExportedCallStat> callStatsList =
+                bcs.getExportedCallStats();
+        assertEquals("resolved", callStatsList.get(0).methodName);
+    }
+
+    @Test
+    public void testMultipleTransactionCodeResolved() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+
+        Binder binder = new AnotherBinderWithGetTransactionName();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        Binder binder2 = new BinderWithGetTransactionName();
+        callSession = bcs.callStarted(binder2, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        callSession = bcs.callStarted(binder, 2);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        List<BinderCallsStats.ExportedCallStat> callStatsList =
+                bcs.getExportedCallStats();
+        assertEquals("foo1", callStatsList.get(0).methodName);
+        assertEquals(AnotherBinderWithGetTransactionName.class.getName(),
+                callStatsList.get(0).className);
+        assertEquals("foo2", callStatsList.get(1).methodName);
+        assertEquals(AnotherBinderWithGetTransactionName.class.getName(),
+                callStatsList.get(1).className);
+        assertEquals("resolved", callStatsList.get(2).methodName);
+        assertEquals(BinderWithGetTransactionName.class.getName(),
+                callStatsList.get(2).className);
+    }
+
+    @Test
+    public void testResolvingCodeDoesNotThrowWhenMethodNotPresent() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        List<BinderCallsStats.ExportedCallStat> callStatsList =
+                bcs.getExportedCallStats();
+        assertEquals("1", callStatsList.get(0).methodName);
+    }
+
+    @Test
+    public void testParcelSize() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
         bcs.time += 10;
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
 
         List<BinderCallsStats.CallStat> callStatsList =
-                bcs.getUidEntries().get(TEST_UID).getCallStatsList();
+                new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
 
         assertEquals(REQUEST_SIZE, callStatsList.get(0).maxRequestSizeBytes);
         assertEquals(REPLY_SIZE, callStatsList.get(0).maxReplySizeBytes);
     }
 
     @Test
+    public void testMaxCpu() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 50;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        List<BinderCallsStats.CallStat> callStatsList =
+                new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
+
+        assertEquals(50, callStatsList.get(0).maxCpuTimeMicros);
+    }
+
+    @Test
+    public void testMaxLatency() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.elapsedTime += 5;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        callSession = bcs.callStarted(binder, 1);
+        bcs.elapsedTime += 1;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        List<BinderCallsStats.CallStat> callStatsList =
+                new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
+
+        assertEquals(5, callStatsList.get(0).maxLatencyMicros);
+    }
+
+    @Test
     public void testGetHighestValues() {
         List<Integer> list = Arrays.asList(1, 2, 3, 4);
         List<Integer> highestValues = BinderCallsStats
@@ -162,12 +364,222 @@
         assertEquals(Arrays.asList(4, 3, 2), highestValues);
     }
 
+    @Test
+    public void testExceptionCount() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callThrewException(callSession, new IllegalStateException());
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        callSession = bcs.callStarted(binder, 1);
+        bcs.callThrewException(callSession, new IllegalStateException());
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        callSession = bcs.callStarted(binder, 1);
+        bcs.callThrewException(callSession, new RuntimeException());
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        ArrayMap<String, Integer> expected = new ArrayMap<>();
+        expected.put("java.lang.IllegalStateException", 2);
+        expected.put("java.lang.RuntimeException", 1);
+        assertEquals(expected, bcs.getExceptionCounts());
+    }
+
+    @Test
+    public void testDataResetWhenInitialStateSet() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        bcs.setInitialState(true, true);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(0, uidEntries.size());
+    }
+
+    @Test
+    public void testScreenAndChargerInitialStates() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        bcs.setInitialState(true /** screen iteractive */, false);
+
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        List<BinderCallsStats.CallStat> callStatsList =
+                new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
+        assertEquals(true, callStatsList.get(0).screenInteractive);
+    }
+
+    @Test
+    public void testNoDataCollectedOnCharger() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
+                .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
+        bcs.getBroadcastReceiver().onReceive(null, intent);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        assertEquals(0, bcs.getUidEntries().size());
+    }
+
+    @Test
+    public void testScreenOff() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_OFF));
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(1, uidEntries.size());
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        Assert.assertNotNull(uidEntry);
+        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+        assertEquals(false, callStatsList.get(0).screenInteractive);
+    }
+
+    @Test
+    public void testScreenOn() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_ON));
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(1, uidEntries.size());
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        Assert.assertNotNull(uidEntry);
+        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+        assertEquals(true, callStatsList.get(0).screenInteractive);
+    }
+
+    @Test
+    public void testOnCharger() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
+                .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
+        bcs.getBroadcastReceiver().onReceive(null, intent);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        assertEquals(0, bcs.getExportedCallStats().size());
+    }
+
+    @Test
+    public void testOnBattery() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
+                .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_NONE);
+        bcs.getBroadcastReceiver().onReceive(null, intent);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        assertEquals(1, bcs.getExportedCallStats().size());
+    }
+
+    @Test
+    public void testDumpDoesNotThrowException() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callThrewException(callSession, new IllegalStateException());
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        PrintWriter pw = new PrintWriter(new StringWriter());
+        bcs.dump(pw, new HashMap<>(), true);
+    }
+
+    @Test
+    public void testGetExportedStatsWhenDetailedTrackingDisabled() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(false);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        assertEquals(0, bcs.getExportedCallStats().size());
+    }
+
+    @Test
+    public void testGetExportedStatsWhenDetailedTrackingEnabled() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_ON));
+
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.elapsedTime += 20;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        assertEquals(1, bcs.getExportedCallStats().size());
+        BinderCallsStats.ExportedCallStat stat = bcs.getExportedCallStats().get(0);
+        assertEquals(TEST_UID, stat.uid);
+        assertEquals("android.os.Binder", stat.className);
+        assertEquals("1", stat.methodName);
+        assertEquals(true, stat.screenInteractive);
+        assertEquals(10, stat.cpuTimeMicros);
+        assertEquals(10, stat.maxCpuTimeMicros);
+        assertEquals(20, stat.latencyMicros);
+        assertEquals(20, stat.maxLatencyMicros);
+        assertEquals(1, stat.callCount);
+        assertEquals(1, stat.recordedCallCount);
+        assertEquals(REQUEST_SIZE, stat.maxRequestSizeBytes);
+        assertEquals(REPLY_SIZE, stat.maxReplySizeBytes);
+        assertEquals(0, stat.exceptionCount);
+    }
+
+    @Test
+    public void testGetExportedStatsWithoutCalls() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        Binder binder = new Binder();
+        assertEquals(0, bcs.getExportedCallStats().size());
+    }
+
+    @Test
+    public void testGetExportedExceptionsWithoutCalls() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        Binder binder = new Binder();
+        assertEquals(0, bcs.getExceptionCounts().size());
+    }
+
     static class TestBinderCallsStats extends BinderCallsStats {
         int callingUid = TEST_UID;
         long time = 1234;
+        long elapsedTime = 0;
 
-        TestBinderCallsStats(boolean detailedTracking) {
-            super(detailedTracking);
+        TestBinderCallsStats() {
+            // Make random generator not random.
+            super(new Injector() {
+                public Random getRandomGenerator() {
+                    return new Random() {
+                        int mCallCount = 0;
+
+                        public int nextInt() {
+                            return mCallCount++;
+                        }
+                    };
+                }
+            });
+            setSamplingInterval(1);
         }
 
         @Override
@@ -176,6 +588,11 @@
         }
 
         @Override
+        protected long getElapsedRealtimeMicro() {
+            return elapsedTime;
+        }
+
+        @Override
         protected int getCallingUid() {
             return callingUid;
         }
diff --git a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
index 45b19bc..a44b860 100644
--- a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
@@ -15,8 +15,11 @@
  */
 package com.android.internal.util;
 
+import static com.android.internal.util.DumpUtils.CRITICAL_SECTION_COMPONENTS;
 import static com.android.internal.util.DumpUtils.filterRecord;
 import static com.android.internal.util.DumpUtils.isNonPlatformPackage;
+import static com.android.internal.util.DumpUtils.isPlatformCriticalPackage;
+import static com.android.internal.util.DumpUtils.isPlatformNonCriticalPackage;
 import static com.android.internal.util.DumpUtils.isPlatformPackage;
 
 import android.content.ComponentName;
@@ -25,7 +28,7 @@
 
 /**
  * Run with:
- atest /android/pi-dev/frameworks/base/core/tests/coretests/src/com/android/internal/util/DumpTest.java
+ atest FrameworksCoreTests:DumpUtilsTest
  */
 public class DumpUtilsTest extends TestCase {
 
@@ -89,6 +92,32 @@
         assertTrue(isNonPlatformPackage(wcn("com.google.def/abc")));
     }
 
+    public void testIsPlatformCriticalPackage() {
+        for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
+            assertTrue(isPlatformCriticalPackage(() -> componentName));
+            assertTrue(isPlatformPackage(componentName));
+        }
+        assertFalse(isPlatformCriticalPackage(wcn("com.google.p/abc")));
+        assertFalse(isPlatformCriticalPackage(wcn("com.android.def/abc")));
+        assertFalse(isPlatformCriticalPackage(wcn("com.android.abc")));
+        assertFalse(isPlatformCriticalPackage(wcn("com.android")));
+        assertFalse(isPlatformCriticalPackage(wcn(null)));
+        assertFalse(isPlatformCriticalPackage(null));
+    }
+
+    public void testIsPlatformNonCriticalPackage() {
+        for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
+            assertFalse(isPlatformNonCriticalPackage(() -> componentName));
+        }
+        assertTrue(isPlatformNonCriticalPackage(wcn("android/abc")));
+        assertTrue(isPlatformNonCriticalPackage(wcn("android.abc/abc")));
+        assertTrue(isPlatformNonCriticalPackage(wcn("com.android.def/abc")));
+
+        assertFalse(isPlatformNonCriticalPackage(wcn("com.google.def/abc")));
+        assertFalse(isPlatformNonCriticalPackage(wcn(null)));
+        assertFalse(isPlatformNonCriticalPackage(null));
+    }
+
     public void testFilterRecord() {
         assertFalse(filterRecord(null).test(wcn("com.google.p/abc")));
         assertFalse(filterRecord(null).test(wcn("com.android.p/abc")));
@@ -105,6 +134,19 @@
         assertFalse(filterRecord("all-non-platform").test(wcn("com.android.p/abc")));
         assertFalse(filterRecord("all-non-platform").test(wcn(null)));
 
+        for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
+            assertTrue(filterRecord("all-platform-critical").test((() -> componentName)));
+            assertFalse(filterRecord("all-platform-non-critical").test((() -> componentName)));
+            assertTrue(filterRecord("all-platform").test((() -> componentName)));
+        }
+        assertFalse(filterRecord("all-platform-critical").test(wcn("com.google.p/abc")));
+        assertFalse(filterRecord("all-platform-critical").test(wcn("com.android.p/abc")));
+        assertFalse(filterRecord("all-platform-critical").test(wcn(null)));
+
+        assertTrue(filterRecord("all-platform-non-critical").test(wcn("com.android.p/abc")));
+        assertFalse(filterRecord("all-platform-non-critical").test(wcn("com.google.p/abc")));
+        assertFalse(filterRecord("all-platform-non-critical").test(wcn(null)));
+
         // Partial string match.
         assertTrue(filterRecord("abc").test(wcn("com.google.p/.abc")));
         assertFalse(filterRecord("abc").test(wcn("com.google.p/.def")));
diff --git a/core/tests/hdmitests/Android.mk b/core/tests/hdmitests/Android.mk
new file mode 100644
index 0000000..e0d2c09
--- /dev/null
+++ b/core/tests/hdmitests/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test frameworks-base-testutils
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := HdmiCecTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/hdmitests/AndroidManifest.xml b/core/tests/hdmitests/AndroidManifest.xml
new file mode 100644
index 0000000..1460b41
--- /dev/null
+++ b/core/tests/hdmitests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.hardware.hdmi"
+    android:sharedUserId="android.uid.system" >
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.hardware.hdmi"
+        android:label="HDMI CEC Tests"/>
+
+</manifest>
\ No newline at end of file
diff --git a/core/tests/hdmitests/AndroidTest.xml b/core/tests/hdmitests/AndroidTest.xml
new file mode 100644
index 0000000..7ef672d
--- /dev/null
+++ b/core/tests/hdmitests/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<configuration description="Runs HDMI CEC Tests.">
+    <option name="test-suite-tag" value="apct"/>
+    <option name="test-suite-tag" value="apct-instrumentation"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="HdmiCecTests.apk" />
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct"/>
+    <option name="test-tag" value="HdmiTests"/>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.hardware.hdmi" />
+        <option name="hidden-api-checks" value="false"/>
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
new file mode 100644
index 0000000..7b76a08
--- /dev/null
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.hdmi;
+
+import android.os.Handler;
+import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
+import android.util.Log;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link HdmiAudioSystemClient}
+ */
+@RunWith(JUnit4.class)
+@SmallTest
+public class HdmiAudioSystemClientTest {
+    private static final String TAG = "HdmiAudioSystemClientTe";
+
+    private HdmiAudioSystemClient mHdmiAudioSystemClient;
+    private TestLooper mTestLooper;
+    private int mVolume;
+    private int mMaxVolume;
+    private boolean mIsMute;
+
+    @Before
+    public void before() {
+        Log.d(TAG, "before()");
+        IHdmiControlService mService = new TestHdmiControlService();
+        mTestLooper = new TestLooper();
+        mHdmiAudioSystemClient =
+                new HdmiAudioSystemClient(mService, new Handler(mTestLooper.getLooper()));
+        resetVariables();
+    }
+
+    @Test
+    public void testSingleCommand() {
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 50, 100, false);
+        assertAudioStatus(50, 100, false);
+    }
+
+    @Test
+    public void testMultipleCommands_longTimeBetweenCalls() {
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 50, 100, false);
+        assertAudioStatus(50, 100, false);
+        mTestLooper.moveTimeForward(500);
+        mTestLooper.dispatchAll();
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 60, 100, false);
+        assertAudioStatus(60, 100, false);
+    }
+
+    @Test
+    public void testMultipleCommands_shortTimeBetweenCalls() {
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 1, 100, false);
+        assertAudioStatus(1, 100, false);
+
+        mTestLooper.moveTimeForward(100); // current time: 100ms
+        mTestLooper.dispatchAll();
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 10, 100, false);
+        assertAudioStatus(1, 100, false); // command not sent, no change
+
+        mTestLooper.moveTimeForward(100); // current time: 200ms
+        mTestLooper.dispatchAll();
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 20, 100, false);
+        assertAudioStatus(1, 100, false); // command not sent, no change
+
+        mTestLooper.moveTimeForward(300); // current time: 500ms
+        mTestLooper.dispatchAll();
+        assertAudioStatus(20, 100, false); // pending command sent, changed to 20
+
+        mTestLooper.moveTimeForward(100); // current time: 600ms
+        mTestLooper.dispatchAll();
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 60, 100, false);
+        assertAudioStatus(20, 100, false); // command not sent, no change
+
+        mTestLooper.moveTimeForward(200); // current time: 800ms
+        mTestLooper.dispatchAll();
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 80, 100, false);
+        assertAudioStatus(20, 100, false); // command not sent, no change
+
+        mTestLooper.moveTimeForward(200); // current time: 1000ms
+        mTestLooper.dispatchAll();
+        assertAudioStatus(80, 100, false); // command sent, changed to 80
+    }
+
+    @Test
+    public void testMultipleCommands_shortTimeAndReturn() {
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 1, 100, false);
+        assertAudioStatus(1, 100, false);
+
+        mTestLooper.moveTimeForward(100); // current time: 100ms
+        mTestLooper.dispatchAll();
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 20, 100, false);
+        assertAudioStatus(1, 100, false); // command not sent, no change
+
+        mTestLooper.moveTimeForward(100); // current time: 200ms
+        mTestLooper.dispatchAll();
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 1, 100, false);
+        assertAudioStatus(1, 100, false); // command not sent, no change
+
+        mTestLooper.moveTimeForward(300); // current time: 500ms
+        mTestLooper.dispatchAll();
+        assertAudioStatus(1, 100, false); // pending command sent
+    }
+
+    @Test
+    public void testMultipleCommands_muteAdjust() {
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 1, 100, false);
+        assertAudioStatus(1, 100, false);
+
+        mTestLooper.moveTimeForward(100); // current time: 100ms
+        mTestLooper.dispatchAll();
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(true, 10, 100, true);
+        assertAudioStatus(10, 100, true); // mute adjust, command sent, changed to 10
+
+        mTestLooper.moveTimeForward(100); // current time: 200ms
+        mTestLooper.dispatchAll();
+        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(false, 20, 100, false);
+        assertAudioStatus(10, 100, true); // command not sent, no change
+
+        mTestLooper.moveTimeForward(300); // current time: 500ms
+        mTestLooper.dispatchAll();
+        assertAudioStatus(20, 100, false); // pending command sent, changed to 20, unmuted
+    }
+
+    private void assertAudioStatus(int volume, int maxVolume, boolean isMute) {
+        Assert.assertEquals(volume, mVolume);
+        Assert.assertEquals(maxVolume, mMaxVolume);
+        Assert.assertEquals(isMute, mIsMute);
+    }
+
+    private void resetVariables() {
+        mVolume = -1;
+        mMaxVolume = -1;
+        mIsMute = true;
+    }
+
+    private final class TestHdmiControlService extends IHdmiControlService.Stub {
+
+        @Override
+        public int[] getSupportedTypes() {
+            return null;
+        }
+
+        @Override
+        public HdmiDeviceInfo getActiveSource() {
+            return null;
+        }
+
+        @Override
+        public void deviceSelect(final int deviceId, final IHdmiControlCallback callback) {
+        }
+
+        @Override
+        public void portSelect(final int portId, final IHdmiControlCallback callback) {
+        }
+
+        @Override
+        public void sendKeyEvent(final int deviceType, final int keyCode, final boolean isPressed) {
+        }
+
+        @Override
+        public void oneTouchPlay(final IHdmiControlCallback callback) {
+        }
+
+        @Override
+        public void queryDisplayStatus(final IHdmiControlCallback callback) {
+        }
+
+        @Override
+        public void addHotplugEventListener(final IHdmiHotplugEventListener listener) {
+        }
+
+        @Override
+        public void removeHotplugEventListener(final IHdmiHotplugEventListener listener) {
+        }
+
+        @Override
+        public void addDeviceEventListener(final IHdmiDeviceEventListener listener) {
+        }
+
+        @Override
+        public List<HdmiPortInfo> getPortInfo() {
+            return null;
+        }
+
+        @Override
+        public boolean canChangeSystemAudioMode() {
+            return false;
+        }
+
+        @Override
+        public boolean getSystemAudioMode() {
+            return false;
+        }
+
+        @Override
+        public void setSystemAudioMode(final boolean enabled, final IHdmiControlCallback callback) {
+        }
+
+        @Override
+        public void addSystemAudioModeChangeListener(
+                final IHdmiSystemAudioModeChangeListener listener) {
+        }
+
+        @Override
+        public void removeSystemAudioModeChangeListener(
+                final IHdmiSystemAudioModeChangeListener listener) {
+        }
+
+        @Override
+        public void setInputChangeListener(final IHdmiInputChangeListener listener) {
+        }
+
+        @Override
+        public List<HdmiDeviceInfo> getInputDevices() {
+            return null;
+        }
+
+        // Returns all the CEC devices on the bus including system audio, switch,
+        // even those of reserved type.
+        @Override
+        public List<HdmiDeviceInfo> getDeviceList() {
+            return null;
+        }
+
+        @Override
+        public void setSystemAudioVolume(final int oldIndex, final int newIndex,
+                final int maxIndex) {
+        }
+
+        @Override
+        public void setSystemAudioMute(final boolean mute) {
+        }
+
+        @Override
+        public void setArcMode(final boolean enabled) {
+        }
+
+        @Override
+        public void setProhibitMode(final boolean enabled) {
+        }
+
+        @Override
+        public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
+                final int deviceType) {
+        }
+
+        @Override
+        public void sendVendorCommand(final int deviceType, final int targetAddress,
+                final byte[] params, final boolean hasVendorId) {
+        }
+
+        @Override
+        public void sendStandby(final int deviceType, final int deviceId) {
+        }
+
+        @Override
+        public void setHdmiRecordListener(IHdmiRecordListener listener) {
+        }
+
+        @Override
+        public void startOneTouchRecord(final int recorderAddress, final byte[] recordSource) {
+        }
+
+        @Override
+        public void stopOneTouchRecord(final int recorderAddress) {
+        }
+
+        @Override
+        public void startTimerRecording(final int recorderAddress, final int sourceType,
+                final byte[] recordSource) {
+        }
+
+        @Override
+        public void clearTimerRecording(final int recorderAddress, final int sourceType,
+                final byte[] recordSource) {
+        }
+
+        @Override
+        public void sendMhlVendorCommand(final int portId, final int offset, final int length,
+                final byte[] data) {
+        }
+
+        @Override
+        public void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener) {
+        }
+
+        @Override
+        public void setStandbyMode(final boolean isStandbyModeOn) {
+        }
+
+        @Override
+        public void reportAudioStatus(final int deviceType, final int volume, final int maxVolume,
+                final boolean isMute) {
+            mVolume = volume;
+            mMaxVolume = maxVolume;
+            mIsMute = isMute;
+        }
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
index c66a10c..80ab4ea 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
@@ -44,7 +44,7 @@
 include $(BUILD_PACKAGE)
 
 ifndef LOCAL_JACK_ENABLED
-$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES)
 	$(hide) mkdir -p $(dir $@)
 	$(MAINDEXCLASSES) $< 1>$@
 	echo "com/android/multidexlegacyandexception/Test.class" >> $@
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
index c5e112b..cf8fc92 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
@@ -38,7 +38,7 @@
 
 include $(BUILD_PACKAGE)
 
-$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES)
 	$(hide) mkdir -p $(dir $@)
 	$(MAINDEXCLASSES) $< 1>$@
 	echo "com/android/multidexlegacytestapp/Test.class" >> $@
@@ -69,7 +69,7 @@
 
 include $(BUILD_PACKAGE)
 
-$(mainDexList2): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+$(mainDexList2): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES)
 	$(hide) mkdir -p $(dir $@)
 	$(MAINDEXCLASSES) $< 1>$@
 	echo "com/android/multidexlegacytestapp/Test.class" >> $@
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
index a6c5373..2ce50b3 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
@@ -36,7 +36,7 @@
 
 include $(BUILD_PACKAGE)
 
-$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES)
 	$(hide) mkdir -p $(dir $@)
 	$(MAINDEXCLASSES) $< 1>$@
 
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
index da48df9..8b0c750 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
@@ -35,7 +35,7 @@
 
 include $(BUILD_PACKAGE)
 
-$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES)
 	$(hide) mkdir -p $(dir $@)
 	$(MAINDEXCLASSES) $< 1>$@
 	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
index 02b3f53..a36c993 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
@@ -35,7 +35,7 @@
 
 include $(BUILD_PACKAGE)
 
-$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES)
 	$(hide) mkdir -p $(dir $@)
 	$(MAINDEXCLASSES) $< 1>$@
 	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
index 4808684..6b7418c 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
@@ -35,7 +35,7 @@
 
 include $(BUILD_PACKAGE)
 
-$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES)
 	$(hide) mkdir -p $(dir $@)
 	$(MAINDEXCLASSES) $< 1>$@
 	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
diff --git a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
index 57ee2d5..4b14284 100644
--- a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
+++ b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
@@ -21,36 +21,6 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 
-jint android_util_MemoryIntArrayTest_createAshmem(__attribute__((unused)) JNIEnv* env,
-        __attribute__((unused)) jobject clazz,
-        jstring name, jint size)
-{
-
-    if (name == NULL) {
-        return -1;
-    }
-
-    if (size < 0) {
-        return -1;
-    }
-
-    const char* nameStr = env->GetStringUTFChars(name, NULL);
-    const int ashmemSize = sizeof(std::atomic_int) * size;
-    int fd = ashmem_create_region(nameStr, ashmemSize);
-    env->ReleaseStringUTFChars(name, nameStr);
-
-    if (fd < 0) {
-        return -1;
-    }
-
-    int setProtResult = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
-    if (setProtResult < 0) {
-        return -1;
-    }
-
-    return fd;
-}
-
 void android_util_MemoryIntArrayTest_setAshmemSize(__attribute__((unused)) JNIEnv* env,
         __attribute__((unused)) jobject clazz, jint fd, jint size)
 {
diff --git a/core/tests/utiltests/jni/registration.cpp b/core/tests/utiltests/jni/registration.cpp
index 0c84d98..d4fc2fb 100644
--- a/core/tests/utiltests/jni/registration.cpp
+++ b/core/tests/utiltests/jni/registration.cpp
@@ -16,25 +16,14 @@
 
 #include <jni.h>
 
-extern jint android_util_MemoryIntArrayTest_createAshmem(JNIEnv* env,
-        jobject clazz, jstring name, jint size);
 extern void android_util_MemoryIntArrayTest_setAshmemSize(JNIEnv* env,
        jobject clazz, jint fd, jint size);
 
 extern "C" {
-    JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
-            JNIEnv * env, jobject obj, jstring name, jint size);
     JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
             JNIEnv * env, jobject obj, jint fd, jint size);
 };
 
-JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
-        __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
-        jstring name, jint size)
-{
-    return android_util_MemoryIntArrayTest_createAshmem(env, obj, name, size);
-}
-
 JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
         __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
         jint fd, jint size)
diff --git a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
index 85817bb..24b33ef 100644
--- a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
+++ b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
@@ -23,6 +23,7 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.support.test.runner.AndroidJUnit4;
 import libcore.io.IoUtils;
 import org.junit.Test;
@@ -251,13 +252,11 @@
                 // Create a MemoryIntArray to muck with
                 MemoryIntArray array = new MemoryIntArray(1);
 
-                // Create the fd to stuff in the MemoryIntArray
-                final int fd = nativeCreateAshmem("foo", 1);
-
-                // Replace the fd with our ahsmem region
-                Field fdFiled = MemoryIntArray.class.getDeclaredField("mFd");
-                fdFiled.setAccessible(true);
-                fdFiled.set(array, fd);
+                // Grab the internal ashmem fd.
+                Field fdField = MemoryIntArray.class.getDeclaredField("mFd");
+                fdField.setAccessible(true);
+                int fd = ((ParcelFileDescriptor)fdField.get(array)).getFd();
+                assertTrue("fd must be valid", fd != -1);
 
                 CountDownLatch countDownLatch = new CountDownLatch(2);
 
@@ -292,10 +291,9 @@
         }
 
         if (!success) {
-            fail("MemoryIntArray should catch ahshmem size changing under it");
+            fail("MemoryIntArray should catch ashmem size changing under it");
         }
     }
 
-    private native int nativeCreateAshmem(String name, int size);
     private native void nativeSetAshmemSize(int fd, int size);
 }
diff --git a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
index 433d4d2..39bb84a 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
@@ -16,9 +16,10 @@
 
 package com.android.internal.util;
 
-import android.test.MoreAsserts;
+import static com.android.internal.util.ArrayUtils.concatElements;
 
-import java.util.Arrays;
+import static org.junit.Assert.assertArrayEquals;
+
 import junit.framework.TestCase;
 
 /**
@@ -92,29 +93,29 @@
     }
 
     public void testAppendInt() throws Exception {
-        MoreAsserts.assertEquals(new int[] { 1 },
+        assertArrayEquals(new int[] { 1 },
                 ArrayUtils.appendInt(null, 1));
-        MoreAsserts.assertEquals(new int[] { 1 },
+        assertArrayEquals(new int[] { 1 },
                 ArrayUtils.appendInt(new int[] { }, 1));
-        MoreAsserts.assertEquals(new int[] { 1, 2 },
+        assertArrayEquals(new int[] { 1, 2 },
                 ArrayUtils.appendInt(new int[] { 1 }, 2));
-        MoreAsserts.assertEquals(new int[] { 1, 2 },
+        assertArrayEquals(new int[] { 1, 2 },
                 ArrayUtils.appendInt(new int[] { 1, 2 }, 1));
     }
 
     public void testRemoveInt() throws Exception {
         assertNull(ArrayUtils.removeInt(null, 1));
-        MoreAsserts.assertEquals(new int[] { },
+        assertArrayEquals(new int[] { },
                 ArrayUtils.removeInt(new int[] { }, 1));
-        MoreAsserts.assertEquals(new int[] { 1, 2, 3, },
+        assertArrayEquals(new int[] { 1, 2, 3, },
                 ArrayUtils.removeInt(new int[] { 1, 2, 3}, 4));
-        MoreAsserts.assertEquals(new int[] { 2, 3, },
+        assertArrayEquals(new int[] { 2, 3, },
                 ArrayUtils.removeInt(new int[] { 1, 2, 3}, 1));
-        MoreAsserts.assertEquals(new int[] { 1, 3, },
+        assertArrayEquals(new int[] { 1, 3, },
                 ArrayUtils.removeInt(new int[] { 1, 2, 3}, 2));
-        MoreAsserts.assertEquals(new int[] { 1, 2, },
+        assertArrayEquals(new int[] { 1, 2, },
                 ArrayUtils.removeInt(new int[] { 1, 2, 3}, 3));
-        MoreAsserts.assertEquals(new int[] { 2, 3, 1 },
+        assertArrayEquals(new int[] { 2, 3, 1 },
                 ArrayUtils.removeInt(new int[] { 1, 2, 3, 1 }, 1));
     }
 
@@ -129,30 +130,51 @@
     }
 
     public void testAppendLong() throws Exception {
-        MoreAsserts.assertEquals(new long[] { 1 },
+        assertArrayEquals(new long[] { 1 },
                 ArrayUtils.appendLong(null, 1));
-        MoreAsserts.assertEquals(new long[] { 1 },
+        assertArrayEquals(new long[] { 1 },
                 ArrayUtils.appendLong(new long[] { }, 1));
-        MoreAsserts.assertEquals(new long[] { 1, 2 },
+        assertArrayEquals(new long[] { 1, 2 },
                 ArrayUtils.appendLong(new long[] { 1 }, 2));
-        MoreAsserts.assertEquals(new long[] { 1, 2 },
+        assertArrayEquals(new long[] { 1, 2 },
                 ArrayUtils.appendLong(new long[] { 1, 2 }, 1));
     }
 
     public void testRemoveLong() throws Exception {
         assertNull(ArrayUtils.removeLong(null, 1));
-        MoreAsserts.assertEquals(new long[] { },
+        assertArrayEquals(new long[] { },
                 ArrayUtils.removeLong(new long[] { }, 1));
-        MoreAsserts.assertEquals(new long[] { 1, 2, 3, },
+        assertArrayEquals(new long[] { 1, 2, 3, },
                 ArrayUtils.removeLong(new long[] { 1, 2, 3}, 4));
-        MoreAsserts.assertEquals(new long[] { 2, 3, },
+        assertArrayEquals(new long[] { 2, 3, },
                 ArrayUtils.removeLong(new long[] { 1, 2, 3}, 1));
-        MoreAsserts.assertEquals(new long[] { 1, 3, },
+        assertArrayEquals(new long[] { 1, 3, },
                 ArrayUtils.removeLong(new long[] { 1, 2, 3}, 2));
-        MoreAsserts.assertEquals(new long[] { 1, 2, },
+        assertArrayEquals(new long[] { 1, 2, },
                 ArrayUtils.removeLong(new long[] { 1, 2, 3}, 3));
-        MoreAsserts.assertEquals(new long[] { 2, 3, 1 },
+        assertArrayEquals(new long[] { 2, 3, 1 },
                 ArrayUtils.removeLong(new long[] { 1, 2, 3, 1 }, 1));
     }
 
+    public void testConcatEmpty() throws Exception {
+        assertArrayEquals(new Long[] {},
+                concatElements(Long.class, null, null));
+        assertArrayEquals(new Long[] {},
+                concatElements(Long.class, new Long[] {}, null));
+        assertArrayEquals(new Long[] {},
+                concatElements(Long.class, null, new Long[] {}));
+        assertArrayEquals(new Long[] {},
+                concatElements(Long.class, new Long[] {}, new Long[] {}));
+    }
+
+    public void testconcatElements() throws Exception {
+        assertArrayEquals(new Long[] { 1L },
+                concatElements(Long.class, new Long[] { 1L }, new Long[] {}));
+        assertArrayEquals(new Long[] { 1L },
+                concatElements(Long.class, new Long[] {}, new Long[] { 1L }));
+        assertArrayEquals(new Long[] { 1L, 2L },
+                concatElements(Long.class, new Long[] { 1L }, new Long[] { 2L }));
+        assertArrayEquals(new Long[] { 1L, 2L, 3L, 4L },
+                concatElements(Long.class, new Long[] { 1L, 2L }, new Long[] { 3L, 4L }));
+    }
 }
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index f7a3e1a..bbec474 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -1,7 +1 @@
-per-file privapp-permissions-platform.xml = bpoiesz@google.com
-per-file privapp-permissions-platform.xml = fkupolov@google.com
-per-file privapp-permissions-platform.xml = hackbod@android.com
-per-file privapp-permissions-platform.xml = jsharkey@android.com
-per-file privapp-permissions-platform.xml = svetoslavganov@google.com
-per-file privapp-permissions-platform.xml = toddke@google.com
-per-file privapp-permissions-platform.xml = yamasani@google.com
+per-file privapp-permissions-platform.xml = hackbod@android.com, jsharkey@android.com, svetoslavganov@google.com, toddke@google.com, yamasani@google.com
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index 4e09c69..5cfae11 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -38,7 +38,7 @@
   <hidden-api-whitelisted-app package="com.android.launcher3" />
   <hidden-api-whitelisted-app package="com.android.mtp" />
   <hidden-api-whitelisted-app package="com.android.musicfx" />
-  <hidden-api-whitelisted-app package="com.android.packageinstaller" />
+  <hidden-api-whitelisted-app package="com.android.permissioncontroller" />
   <hidden-api-whitelisted-app package="com.android.printservice.recommendation" />
   <hidden-api-whitelisted-app package="com.android.printspooler" />
   <hidden-api-whitelisted-app package="com.android.providers.blockednumber" />
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index b3f05dc..6f52fbd 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -182,11 +182,11 @@
          code to link against. -->
 
     <library name="android.test.base"
-            file="/system/framework/android.test.base.jar" />
+            file="/system/framework/android.test.base.impl.jar" />
     <library name="android.test.mock"
-            file="/system/framework/android.test.mock.jar" />
+            file="/system/framework/android.test.mock.impl.jar" />
     <library name="android.test.runner"
-            file="/system/framework/android.test.runner.jar" />
+            file="/system/framework/android.test.runner.impl.jar" />
 
     <!-- These are the standard packages that are white-listed to always have internet
          access while in power save mode, even if they aren't in the foreground. -->
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 82b6a22..616a8d6 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -126,6 +126,7 @@
     <privapp-permissions package="com.android.omadm.service">
         <permission name="android.permission.CHANGE_CONFIGURATION"/>
         <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
+        <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.WRITE_APN_SETTINGS"/>
@@ -133,13 +134,18 @@
     </privapp-permissions>
 
     <privapp-permissions package="com.android.packageinstaller">
-        <permission name="android.permission.CLEAR_APP_CACHE"/>
         <permission name="android.permission.DELETE_PACKAGES"/>
         <permission name="android.permission.INSTALL_PACKAGES"/>
+        <permission name="android.permission.USE_RESERVED_DISK"/>
+        <permission name="android.permission.MANAGE_USERS"/>
+        <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+    </privapp-permissions>
+
+    <privapp-permissions package="com.android.permissioncontroller">
+        <permission name="android.permission.CLEAR_APP_CACHE"/>
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"/>
         <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
-        <permission name="android.permission.USE_RESERVED_DISK"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.phone">
@@ -330,6 +336,7 @@
         <permission name="android.permission.START_TASKS_FROM_RECENTS" />
         <permission name="android.permission.STOP_APP_SWITCHES"/>
         <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
+        <permission name="android.permission.SUSPEND_APPS" />
         <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
         <permission name="android.permission.USE_RESERVED_DISK"/>
         <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index d0565ca..1ab4c63 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -540,7 +540,7 @@
 }
 
 key BUTTON_MODE {
-    base:                               fallback MENU
+    base:                               fallback HOME
 }
 
 key BUTTON_1 {
diff --git a/data/keyboards/Vendor_045e_Product_02e0.kl b/data/keyboards/Vendor_045e_Product_02e0.kl
index 1012fb1..1dd8e15 100644
--- a/data/keyboards/Vendor_045e_Product_02e0.kl
+++ b/data/keyboards/Vendor_045e_Product_02e0.kl
@@ -56,4 +56,4 @@
 key 0x137    BUTTON_START
 
 # Xbox key
-key 0x8b    HOME
\ No newline at end of file
+key 0x8b    BUTTON_MODE
\ No newline at end of file
diff --git a/data/keyboards/Vendor_054c_Product_0268.kl b/data/keyboards/Vendor_054c_Product_0268.kl
index 7c60137..522db3c 100644
--- a/data/keyboards/Vendor_054c_Product_0268.kl
+++ b/data/keyboards/Vendor_054c_Product_0268.kl
@@ -35,7 +35,7 @@
 key 0x122    BUTTON_THUMBR
 
 # PS key
-key 0x2d0    HOME
+key 0x2d0    BUTTON_MODE
 
 # Left Analog Stick
 axis 0x00    X
diff --git a/data/sounds/AllAudio.mk b/data/sounds/AllAudio.mk
index bf8067c..bb8add1 100644
--- a/data/sounds/AllAudio.mk
+++ b/data/sounds/AllAudio.mk
@@ -234,3 +234,8 @@
     $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
     $(LOCAL_PATH)/effects/ogg/ChargingStarted.ogg:system/media/audio/ui/ChargingStarted.ogg \
     $(LOCAL_PATH)/effects/ogg/InCallNotification.ogg:system/media/audio/ui/InCallNotification.ogg \
+    $(LOCAL_PATH)/effects/ogg/NFCFailure.ogg:system/media/audio/ui/NFCFailure.ogg \
+    $(LOCAL_PATH)/effects/ogg/NFCInitiated.ogg:system/media/audio/ui/NFCInitiated.ogg \
+    $(LOCAL_PATH)/effects/ogg/NFCSuccess.ogg:system/media/audio/ui/NFCSuccess.ogg \
+    $(LOCAL_PATH)/effects/ogg/NFCTransferComplete.ogg:system/media/audio/ui/NFCTransferComplete.ogg \
+    $(LOCAL_PATH)/effects/ogg/NFCTransferInitiated.ogg:system/media/audio/ui/NFCTransferInitiated.ogg \
diff --git a/data/sounds/AudioPackage14.mk b/data/sounds/AudioPackage14.mk
new file mode 100644
index 0000000..c903a2b
--- /dev/null
+++ b/data/sounds/AudioPackage14.mk
@@ -0,0 +1,32 @@
+#
+# Audio Package 14 - P
+#
+# Include this file in a product makefile to include these audio files
+#
+#
+
+LOCAL_PATH := frameworks/base/data/sounds
+
+# Simple files that do not require renaming
+ALARM_FILES := Argon Carbon Helium Krypton Neon Oxygen Osmium Platinum Timer
+NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Titan Tethys
+RINGTONE_FILES := Atria Callisto Dione Ganymede Luna Oberon Phobos Pyxis Sedna Titania Triton \
+	Umbriel
+EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
+	camera_focus Dock Undock Lock Unlock Trusted ChargingStarted InCallNotification \
+	NFCFailure NFCInitiated NFCSuccess NFCTransferComplete NFCTransferInitiated
+MATERIAL_EFFECT_FILES := camera_click VideoRecord WirelessChargingStarted LowBattery VideoStop
+
+PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
+	$(LOCAL_PATH)/alarms/material/ogg/$(fn).ogg:system/media/audio/alarms/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(NOTIFICATION_FILES),\
+	$(LOCAL_PATH)/notifications/material/ogg/$(fn).ogg:system/media/audio/notifications/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(RINGTONE_FILES),\
+	$(LOCAL_PATH)/ringtones/material/ogg/$(fn).ogg:system/media/audio/ringtones/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(EFFECT_FILES),\
+	$(LOCAL_PATH)/effects/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
+PRODUCT_COPY_FILES += $(foreach fn,$(MATERIAL_EFFECT_FILES),\
+	$(LOCAL_PATH)/effects/material/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
diff --git a/data/sounds/README.txt b/data/sounds/README.txt
index 193fd71..db20319 100644
--- a/data/sounds/README.txt
+++ b/data/sounds/README.txt
@@ -31,3 +31,13 @@
 ./effects/ogg/VideoStop_48k.ogg
   unused
 
+NFC
+---
+
+./effects/ogg/NFCFailure.ogg
+./effects/ogg/NFCInitiated.ogg
+./effects/ogg/NFCSuccess.ogg
+./effects/ogg/NFCTransferComplete.ogg
+./effects/ogg/NFCTransferInitiated.ogg
+
+referenced in AudioPackage14.mk (= AudioPackage13.mk + NFC sounds).
diff --git a/data/sounds/effects/ogg/NFCFailure.ogg b/data/sounds/effects/ogg/NFCFailure.ogg
new file mode 100644
index 0000000..e9ee662
--- /dev/null
+++ b/data/sounds/effects/ogg/NFCFailure.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/NFCInitiated.ogg b/data/sounds/effects/ogg/NFCInitiated.ogg
new file mode 100644
index 0000000..a86319f
--- /dev/null
+++ b/data/sounds/effects/ogg/NFCInitiated.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/NFCSuccess.ogg b/data/sounds/effects/ogg/NFCSuccess.ogg
new file mode 100644
index 0000000..39dfd1f
--- /dev/null
+++ b/data/sounds/effects/ogg/NFCSuccess.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/NFCTransferComplete.ogg b/data/sounds/effects/ogg/NFCTransferComplete.ogg
new file mode 100644
index 0000000..f00cd98
--- /dev/null
+++ b/data/sounds/effects/ogg/NFCTransferComplete.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/NFCTransferInitiated.ogg b/data/sounds/effects/ogg/NFCTransferInitiated.ogg
new file mode 100644
index 0000000..7be1bcb
--- /dev/null
+++ b/data/sounds/effects/ogg/NFCTransferInitiated.ogg
Binary files differ
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 97130f1..53e9826 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas.VertexMode;
 import android.text.GraphicsOperations;
 import android.text.MeasuredParagraph;
@@ -44,6 +45,7 @@
      * freed by NativeAllocation.
      * @hide
      */
+    @UnsupportedAppUsage
     protected long mNativeCanvasWrapper;
 
     /**
@@ -501,7 +503,7 @@
                             contextStart - paraStart,
                             contextEnd - contextStart,
                             x, y, isRtl, paint.getNativeInstance(),
-                            mp.getNativePtr());
+                            mp.getNativeMeasuredParagraph().getNativePtr());
                     return;
                 }
             }
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index c6f8415..cea6c1c 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.content.res.ResourcesImpl;
 import android.os.Parcel;
@@ -59,6 +60,7 @@
     private static final long NATIVE_ALLOCATION_SIZE = 32;
 
     // Convenience for JNI access
+    @UnsupportedAppUsage
     private final long mNativePtr;
 
     /**
@@ -75,9 +77,13 @@
      */
     private boolean mRequestPremultiplied;
 
+    @UnsupportedAppUsage
     private byte[] mNinePatchChunk; // may be null
+    @UnsupportedAppUsage
     private NinePatch.InsetStruct mNinePatchInsets; // may be null
+    @UnsupportedAppUsage
     private int mWidth;
+    @UnsupportedAppUsage
     private int mHeight;
     private boolean mRecycled;
 
@@ -99,11 +105,13 @@
      * density when running old apps.
      * @hide
      */
+    @UnsupportedAppUsage
     public static void setDefaultDensity(int density) {
         sDefaultDensity = density;
     }
 
     @SuppressWarnings("deprecation")
+    @UnsupportedAppUsage
     static int getDefaultDensity() {
         if (sDefaultDensity >= 0) {
             return sDefaultDensity;
@@ -117,6 +125,7 @@
      * int (pointer).
      */
     // called from JNI
+    @UnsupportedAppUsage
     Bitmap(long nativeBitmap, int width, int height, int density, boolean requestPremultiplied,
             byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
         if (nativeBitmap == 0) {
@@ -158,6 +167,7 @@
      * width/height values
      */
     @SuppressWarnings("unused") // called from JNI
+    @UnsupportedAppUsage
     void reinit(int width, int height, boolean requestPremultiplied) {
         mWidth = width;
         mHeight = height;
@@ -328,6 +338,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNinePatchChunk(byte[] chunk) {
         mNinePatchChunk = chunk;
     }
@@ -523,6 +534,7 @@
          */
         HARDWARE    (7);
 
+        @UnsupportedAppUsage
         final int nativeInt;
 
         private static Config sConfigs[] = {
@@ -533,6 +545,7 @@
             this.nativeInt = ni;
         }
 
+        @UnsupportedAppUsage
         static Config nativeToConfig(int ni) {
             return sConfigs[ni];
         }
@@ -667,6 +680,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap createAshmemBitmap() {
         checkRecycled("Can't copy a recycled bitmap");
         noteHardwareBitmapSlowCall();
@@ -685,6 +699,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap createAshmemBitmap(Config config) {
         checkRecycled("Can't copy a recycled bitmap");
         noteHardwareBitmapSlowCall();
@@ -703,6 +718,7 @@
      *         currently PIXEL_FORMAT_RGBA_8888 is the only supported format
      * @hide
      */
+    @UnsupportedAppUsage
     public static Bitmap createHardwareBitmap(@NonNull GraphicBuffer graphicBuffer) {
         return nativeCreateHardwareBitmap(graphicBuffer);
     }
@@ -1500,6 +1516,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     static public int scaleFromDensity(int size, int sdensity, int tdensity) {
         if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
             return size;
@@ -2032,6 +2049,7 @@
      * @return {@link GraphicBuffer} which is internally used by hardware bitmap
      * @hide
      */
+    @UnsupportedAppUsage
     public GraphicBuffer createGraphicBufferHandle() {
         return nativeCreateGraphicBufferHandle(mNativePtr);
     }
@@ -2049,6 +2067,7 @@
     private static native Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig);
     private static native long nativeGetNativeFinalizer();
     private static native void nativeRecycle(long nativeBitmap);
+    @UnsupportedAppUsage
     private static native void nativeReconfigure(long nativeBitmap, int width, int height,
                                                  int config, boolean isPremultiplied);
 
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 7ea35e7..adab1a9c 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.os.Trace;
@@ -831,11 +832,15 @@
         return decodeFileDescriptor(fd, null, null);
     }
 
+    @UnsupportedAppUsage
     private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
             Rect padding, Options opts);
+    @UnsupportedAppUsage
     private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
             Rect padding, Options opts);
+    @UnsupportedAppUsage
     private static native Bitmap nativeDecodeAsset(long nativeAsset, Rect padding, Options opts);
+    @UnsupportedAppUsage
     private static native Bitmap nativeDecodeByteArray(byte[] data, int offset,
             int length, Options opts);
     private static native boolean nativeIsSeekable(FileDescriptor fd);
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index 2da27c7..9b5027d 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -15,6 +15,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 
 import java.io.FileDescriptor;
@@ -165,6 +166,7 @@
 
         This can be called from JNI code.
     */
+    @UnsupportedAppUsage
     private BitmapRegionDecoder(long decoder) {
         mNativeBitmapRegionDecoder = decoder;
         mRecycled = false;
@@ -267,6 +269,7 @@
     private static native int nativeGetHeight(long lbm);
     private static native void nativeClean(long lbm);
 
+    @UnsupportedAppUsage
     private static native BitmapRegionDecoder nativeNewInstance(
             byte[] data, int offset, int length, boolean isShareable);
     private static native BitmapRegionDecoder nativeNewInstance(
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 5577f53..bcf7229 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 
 /**
  * Shader used to draw a bitmap as a texture. The bitmap can be repeated or
@@ -28,9 +29,12 @@
      * @hide
      */
     @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
+    @UnsupportedAppUsage
     public Bitmap mBitmap;
 
+    @UnsupportedAppUsage
     private int mTileX;
+    @UnsupportedAppUsage
     private int mTileY;
 
     /**
diff --git a/graphics/java/android/graphics/Camera.java b/graphics/java/android/graphics/Camera.java
index 60588d0..cbd4ead 100644
--- a/graphics/java/android/graphics/Camera.java
+++ b/graphics/java/android/graphics/Camera.java
@@ -16,14 +16,14 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * A camera instance can be used to compute 3D transformations and
  * generate a matrix that can be applied, for instance, on a
  * {@link Canvas}.
  */
 public class Camera {
-    private Matrix mMatrix;
-
     /**
      * Creates a new camera, with empty transformations.
      */
@@ -149,13 +149,7 @@
      * @param canvas The Canvas to set the transform matrix onto
      */
     public void applyToCanvas(Canvas canvas) {
-        if (canvas.isHardwareAccelerated()) {
-            if (mMatrix == null) mMatrix = new Matrix();
-            getMatrix(mMatrix);
-            canvas.concat(mMatrix);
-        } else {
-            nativeApplyToCanvas(canvas.getNativeCanvasWrapper());
-        }
+        nativeApplyToCanvas(canvas.getNativeCanvasWrapper());
     }
 
     public native float dotWithNormal(float dx, float dy, float dz);
@@ -174,5 +168,6 @@
     private native void nativeGetMatrix(long native_matrix);
     private native void nativeApplyToCanvas(long native_canvas);
 
+    @UnsupportedAppUsage
     long native_instance;
 }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index a465eea..ef58c8f 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 
 import dalvik.annotation.optimization.CriticalNative;
@@ -54,6 +55,7 @@
     public static boolean sCompatibilitySetBitmap = false;
 
     /** @hide */
+    @UnsupportedAppUsage
     public long getNativeCanvasWrapper() {
         return mNativeCanvasWrapper;
     }
@@ -62,6 +64,7 @@
     public boolean isRecordingFor(Object o) { return false; }
 
     // may be null
+    @UnsupportedAppUsage
     private Bitmap mBitmap;
 
     // optional field set by the caller
@@ -123,6 +126,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public Canvas(long nativeCanvas) {
         if (nativeCanvas == 0) {
             throw new IllegalStateException();
@@ -141,6 +145,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     protected GL getGL() {
         return null;
     }
@@ -269,6 +274,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setScreenDensity(int density) {
         mScreenDensity = density;
     }
@@ -1263,6 +1269,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void release() {
         mNativeCanvasWrapper = 0;
         if (mFinalizer != null) {
@@ -1276,6 +1283,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void freeCaches() {
         nFreeCaches();
     }
@@ -1285,6 +1293,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void freeTextLayoutCaches() {
         nFreeTextLayoutCaches();
     }
@@ -1591,9 +1600,9 @@
      * Draw the specified circle using the specified paint. If radius is <= 0, then nothing will be
      * drawn. The circle will be filled or framed based on the Style in the paint.
      *
-     * @param cx The x-coordinate of the center of the cirle to be drawn
-     * @param cy The y-coordinate of the center of the cirle to be drawn
-     * @param radius The radius of the cirle to be drawn
+     * @param cx The x-coordinate of the center of the circle to be drawn
+     * @param cy The y-coordinate of the center of the circle to be drawn
+     * @param radius The radius of the circle to be drawn
      * @param paint The paint used to draw the circle
      */
     public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
diff --git a/graphics/java/android/graphics/CanvasProperty.java b/graphics/java/android/graphics/CanvasProperty.java
index ea3886c..1275e08 100644
--- a/graphics/java/android/graphics/CanvasProperty.java
+++ b/graphics/java/android/graphics/CanvasProperty.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import com.android.internal.util.VirtualRefBasePtr;
 
 /**
@@ -26,10 +27,12 @@
 
     private VirtualRefBasePtr mProperty;
 
+    @UnsupportedAppUsage
     public static CanvasProperty<Float> createFloat(float initialValue) {
         return new CanvasProperty<Float>(nCreateFloat(initialValue));
     }
 
+    @UnsupportedAppUsage
     public static CanvasProperty<Paint> createPaint(Paint initialValue) {
         return new CanvasProperty<Paint>(nCreatePaint(initialValue.getNativeInstance()));
     }
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 9201a2e..0f7980c 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 /**
  * A color filter that transforms colors through a 4x5 color matrix. This filter
@@ -26,6 +27,7 @@
  * @see ColorMatrix
  */
 public class ColorMatrixColorFilter extends ColorFilter {
+    @UnsupportedAppUsage
     private final ColorMatrix mMatrix = new ColorMatrix();
 
     /**
@@ -76,6 +78,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setColorMatrix(@Nullable ColorMatrix matrix) {
         discardNativeInstance();
         if (matrix == null) {
@@ -104,6 +107,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setColorMatrixArray(@Nullable float[] array) {
         // called '...Array' so that passing null isn't ambiguous
         discardNativeInstance();
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index c69eb32..229923c 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.graphics.fonts.FontVariationAxis;
 import android.text.TextUtils;
@@ -51,16 +52,19 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public long mNativePtr;
 
     // Points native font family builder. Must be zero after freezing this family.
     private long mBuilderPtr;
 
+    @UnsupportedAppUsage
     public FontFamily() {
         mBuilderPtr = nInitBuilder(null, 0);
         mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
     }
 
+    @UnsupportedAppUsage
     public FontFamily(@Nullable String[] langs, int variant) {
         final String langsString;
         if (langs == null || langs.length == 0) {
@@ -80,6 +84,7 @@
      * @return boolean returns false if some error happens in native code, e.g. broken font file is
      *                 passed, etc.
      */
+    @UnsupportedAppUsage
     public boolean freeze() {
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("This FontFamily is already frozen");
@@ -93,6 +98,7 @@
         return mNativePtr != 0;
     }
 
+    @UnsupportedAppUsage
     public void abortCreation() {
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("This FontFamily is already frozen or abandoned");
@@ -122,6 +128,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes,
             int weight, int italic) {
         if (mBuilderPtr == 0) {
@@ -147,6 +154,7 @@
      *            using the OS/2 table in the font.
      * @return
      */
+    @UnsupportedAppUsage
     public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
             boolean isAsset, int ttcIndex, int weight, int isItalic,
             FontVariationAxis[] axes) {
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 431d0e0..e3e8380 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontVariationAxis;
 import android.text.FontConfig;
 import android.util.Xml;
@@ -37,6 +38,7 @@
 public class FontListParser {
 
     /* Parse fallback list (no names) */
+    @UnsupportedAppUsage
     public static FontConfig parse(InputStream in) throws XmlPullParserException, IOException {
         try {
             XmlPullParser parser = Xml.newPullParser();
diff --git a/graphics/java/android/graphics/GraphicBuffer.java b/graphics/java/android/graphics/GraphicBuffer.java
index 53d2177..7408683 100644
--- a/graphics/java/android/graphics/GraphicBuffer.java
+++ b/graphics/java/android/graphics/GraphicBuffer.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -53,6 +54,7 @@
     private final int mFormat;
     private final int mUsage;
     // Note: do not rename, this field is used by native code
+    @UnsupportedAppUsage
     private final long mNativeObject;
 
     // These two fields are only used by lock/unlockCanvas()
@@ -84,6 +86,7 @@
     /**
      * Private use only. See {@link #create(int, int, int, int)}.
      */
+    @UnsupportedAppUsage
     private GraphicBuffer(int width, int height, int format, int usage, long nativeObject) {
         mWidth = width;
         mHeight = height;
@@ -96,6 +99,7 @@
      * For SurfaceControl JNI.
      * @hide
      */
+    @UnsupportedAppUsage
     public static GraphicBuffer createFromExisting(int width, int height,
             int format, int usage, long unwrappedNativeObject) {
         long nativeObject = nWrapGraphicBuffer(unwrappedNativeObject);
@@ -274,6 +278,7 @@
         nWriteGraphicBufferToParcel(mNativeObject, dest);
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<GraphicBuffer> CREATOR =
             new Parcelable.Creator<GraphicBuffer>() {
         public GraphicBuffer createFromParcel(Parcel in) {
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 098f100..7bed1ac 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -28,6 +28,7 @@
 import android.annotation.Nullable;
 import android.annotation.Px;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.content.ContentResolver;
 import android.content.res.AssetFileDescriptor;
@@ -1856,6 +1857,7 @@
      * Private method called by JNI.
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private int postProcessAndRelease(@NonNull Canvas canvas) {
         try {
             return mPostProcessor.onPostProcess(canvas);
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 43fd270..9546a4a 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 public class ImageFormat {
     /*
      * these constants are chosen to be binary compatible with their previous
@@ -103,6 +105,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int Y8 = 0x20203859;
 
     /**
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index 1578ffb..62a890f 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -22,6 +22,7 @@
 package android.graphics;
 
 import android.annotation.ColorInt;
+import android.annotation.UnsupportedAppUsage;
 
 /**
  * A color filter that can be used to simulate simple lighting effects.
@@ -72,6 +73,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setColorMultiply(@ColorInt int mul) {
         if (mMul != mul) {
             mMul = mul;
@@ -97,6 +99,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setColorAdd(@ColorInt int add) {
         if (mAdd != add) {
             mAdd = add;
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 7139efe..7e6fc35 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 public class LinearGradient extends Shader {
 
@@ -31,15 +32,24 @@
      */
     private int mType;
 
+    @UnsupportedAppUsage
     private float mX0;
+    @UnsupportedAppUsage
     private float mY0;
+    @UnsupportedAppUsage
     private float mX1;
+    @UnsupportedAppUsage
     private float mY1;
+    @UnsupportedAppUsage
     private int[] mColors;
+    @UnsupportedAppUsage
     private float[] mPositions;
+    @UnsupportedAppUsage
     private int mColor0;
+    @UnsupportedAppUsage
     private int mColor1;
 
+    @UnsupportedAppUsage
     private TileMode mTileMode;
 
     /**
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index 486070c..f8cb366 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -21,6 +21,7 @@
 
 import libcore.util.NativeAllocationRegistry;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.PrintWriter;
 
 /**
@@ -39,6 +40,7 @@
     public static final int MPERSP_2 = 8;   //!< use with getValues/setValues
 
     /** @hide */
+    @UnsupportedAppUsage
     public final static Matrix IDENTITY_MATRIX = new Matrix() {
         void oops() {
             throw new IllegalStateException("Matrix can not be modified");
@@ -231,6 +233,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public final long native_instance;
 
     /**
diff --git a/graphics/java/android/graphics/Movie.java b/graphics/java/android/graphics/Movie.java
index 83857be..8162544 100644
--- a/graphics/java/android/graphics/Movie.java
+++ b/graphics/java/android/graphics/Movie.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 
 import java.io.FileInputStream;
@@ -24,9 +25,12 @@
 /**
  * @deprecated Prefer {@link android.graphics.drawable.AnimatedImageDrawable}.
  */
+@Deprecated
 public class Movie {
+    @UnsupportedAppUsage
     private long mNativeMovie;
 
+    @UnsupportedAppUsage
     private Movie(long nativeMovie) {
         if (nativeMovie == 0) {
             throw new RuntimeException("native movie creation failed");
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index b6a209f..800247a 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * The NinePatch class permits drawing a bitmap in nine or more sections.
  * Essentially, it allows the creation of custom graphics that will scale the
@@ -41,6 +43,7 @@
      */
     public static class InsetStruct {
         @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
+        @UnsupportedAppUsage
         InsetStruct(int opticalLeft, int opticalTop, int opticalRight, int opticalBottom,
                 int outlineLeft, int outlineTop, int outlineRight, int outlineBottom,
                 float outlineRadius, int outlineAlpha, float decodeScale) {
@@ -77,6 +80,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private final Bitmap mBitmap;
 
     /**
@@ -84,6 +88,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long mNativeChunk;
 
     private Paint mPaint;
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 1c85df0..98c990a 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -19,6 +19,7 @@
 import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.drawable.Drawable;
 
 import java.lang.annotation.Retention;
@@ -66,6 +67,7 @@
     public Path mPath;
 
     /** @hide */
+    @UnsupportedAppUsage
     public final Rect mRect = new Rect();
     /** @hide */
     public float mRadius = RADIUS_UNDEFINED;
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 42dac38..9dab536 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontVariationAxis;
 import android.os.LocaleList;
 import android.text.GraphicsOperations;
@@ -44,6 +45,7 @@
  */
 public class Paint {
 
+    @UnsupportedAppUsage
     private long mNativePaint;
     private long mNativeShader;
     private long mNativeColorFilter;
@@ -61,6 +63,7 @@
     private MaskFilter  mMaskFilter;
     private PathEffect  mPathEffect;
     private Shader      mShader;
+    @UnsupportedAppUsage
     private Typeface    mTypeface;
     private Xfermode    mXfermode;
 
@@ -618,6 +621,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setCompatibilityScaling(float factor) {
         if (factor == 1.0) {
             mHasCompatScaling = false;
@@ -635,6 +639,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long getNativeInstance() {
         long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance();
         if (newNativeShader != mNativeShader) {
@@ -1718,6 +1723,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setHyphenEdit(int hyphen) {
         nSetHyphenEdit(mNativePaint, hyphen);
     }
@@ -2261,6 +2267,7 @@
      * @see #getTextRunAdvances(String, int, int, int, int, boolean, float[], int)
      * @hide
      */
+    @UnsupportedAppUsage
     public float getTextRunAdvances(char[] chars, int index, int count,
             int contextIndex, int contextCount, boolean isRtl, float[] advances,
             int advancesIndex) {
@@ -2451,6 +2458,7 @@
      * @return the offset of the next position, or -1
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTextRunCursor(char[] text, int contextStart, int contextLength,
             int dir, int offset, int cursorOpt) {
         int contextEnd = contextStart + contextLength;
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 1652f64..405ab0b 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
@@ -46,10 +47,12 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isSimplePath = true;
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public Region rects;
     private Direction mLastDirection = null;
 
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index f2d0227..f7acb11 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.InputStream;
 import java.io.OutputStream;
 
@@ -32,6 +33,7 @@
  */
 public class Picture {
     private PictureCanvas mRecordingCanvas;
+    @UnsupportedAppUsage
     private long mNativePicture;
     private boolean mRequiresHwAcceleration;
 
diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java
index c6b6c66..f291e27 100644
--- a/graphics/java/android/graphics/Point.java
+++ b/graphics/java/android/graphics/Point.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.proto.ProtoOutputStream;
@@ -37,7 +38,7 @@
         this.y = y;
     }
 
-    public Point(Point src) {
+    public Point(@NonNull Point src) {
         this.x = src.x;
         this.y = src.y;
     }
@@ -99,7 +100,7 @@
     }
 
     /** @hide */
-    public void printShortString(PrintWriter pw) {
+    public void printShortString(@NonNull PrintWriter pw) {
         pw.print("["); pw.print(x); pw.print(","); pw.print(y); pw.print("]");
     }
 
@@ -130,7 +131,7 @@
      * @param fieldId           Field Id of the Rect as defined in the parent message
      * @hide
      */
-    public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) {
+    public void writeToProto(@NonNull ProtoOutputStream protoOutputStream, long fieldId) {
         final long token = protoOutputStream.start(fieldId);
         protoOutputStream.write(PointProto.X, x);
         protoOutputStream.write(PointProto.Y, y);
@@ -141,6 +142,7 @@
         /**
          * Return a new point from the data in the specified parcel.
          */
+        @Override
         public Point createFromParcel(Parcel in) {
             Point r = new Point();
             r.readFromParcel(in);
@@ -150,6 +152,7 @@
         /**
          * Return an array of rectangles of the specified size.
          */
+        @Override
         public Point[] newArray(int size) {
             return new Point[size];
         }
@@ -161,7 +164,7 @@
      *
      * @param in The parcel to read the point's coordinates from
      */
-    public void readFromParcel(Parcel in) {
+    public void readFromParcel(@NonNull Parcel in) {
         x = in.readInt();
         y = in.readInt();
     }
diff --git a/graphics/java/android/graphics/PointF.java b/graphics/java/android/graphics/PointF.java
index 8e4288e..a3b4194 100644
--- a/graphics/java/android/graphics/PointF.java
+++ b/graphics/java/android/graphics/PointF.java
@@ -16,10 +16,10 @@
 
 package android.graphics;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-
 /**
  * PointF holds two float coordinates
  */
@@ -34,7 +34,7 @@
         this.y = y; 
     }
     
-    public PointF(Point p) { 
+    public PointF(@NonNull Point p) {
         this.x = p.x;
         this.y = p.y;
     }
@@ -50,7 +50,7 @@
     /**
      * Set the point's x and y coordinates to the coordinates of p
      */
-    public final void set(PointF p) { 
+    public final void set(@NonNull PointF p) {
         this.x = p.x;
         this.y = p.y;
     }
@@ -134,6 +134,7 @@
         /**
          * Return a new point from the data in the specified parcel.
          */
+        @Override
         public PointF createFromParcel(Parcel in) {
             PointF r = new PointF();
             r.readFromParcel(in);
@@ -143,6 +144,7 @@
         /**
          * Return an array of rectangles of the specified size.
          */
+        @Override
         public PointF[] newArray(int size) {
             return new PointF[size];
         }
@@ -154,7 +156,7 @@
      *
      * @param in The parcel to read the point's coordinates from
      */
-    public void readFromParcel(Parcel in) {
+    public void readFromParcel(@NonNull Parcel in) {
         x = in.readFloat();
         y = in.readFloat();
     }
diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java
index d7d3049..fba5043 100644
--- a/graphics/java/android/graphics/PorterDuff.java
+++ b/graphics/java/android/graphics/PorterDuff.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * <p>This class contains the list of alpha compositing and blending modes
  * that can be passed to {@link PorterDuffXfermode}, a specialized implementation
@@ -364,6 +366,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public final int nativeInt;
     }
 
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index 88a6322..6665220 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 
 /**
  * A color filter that can be used to tint the source pixels using a single
@@ -50,6 +51,7 @@
      * @hide
      */
     @ColorInt
+    @UnsupportedAppUsage
     public int getColor() {
         return mColor;
     }
@@ -62,6 +64,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PorterDuff.Mode getMode() {
         return mMode;
     }
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index f4b1191..41d2628 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.ColorInt;
+import android.annotation.UnsupportedAppUsage;
 
 public class RadialGradient extends Shader {
 
@@ -31,14 +32,22 @@
      */
     private int mType;
 
+    @UnsupportedAppUsage
     private float mX;
+    @UnsupportedAppUsage
     private float mY;
+    @UnsupportedAppUsage
     private float mRadius;
+    @UnsupportedAppUsage
     private int[] mColors;
+    @UnsupportedAppUsage
     private float[] mPositions;
+    @UnsupportedAppUsage
     private int mCenterColor;
+    @UnsupportedAppUsage
     private int mEdgeColor;
 
+    @UnsupportedAppUsage
     private TileMode mTileMode;
 
     /**
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 56a6820..4fec33f 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -19,6 +19,7 @@
 import android.annotation.CheckResult;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -206,6 +207,7 @@
      * Print short representation to given writer.
      * @hide
      */
+    @UnsupportedAppUsage
     public void printShortString(@NonNull PrintWriter pw) {
         pw.print('['); pw.print(left); pw.print(',');
         pw.print(top); pw.print("]["); pw.print(right);
@@ -694,6 +696,7 @@
      * Scales up the rect by the given scale.
      * @hide
      */
+    @UnsupportedAppUsage
     public void scale(float scale) {
         if (scale != 1.0f) {
             left = (int) (left * scale + 0.5f);
diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java
index dca6d9e..29d9367 100644
--- a/graphics/java/android/graphics/Region.java
+++ b/graphics/java/android/graphics/Region.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Pools.SynchronizedPool;
@@ -30,6 +32,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public long mNativeRegion;
 
     // the native values for these must match up with the enum in SkRegion.h
@@ -48,6 +51,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public final int nativeInt;
     }
 
@@ -59,14 +63,14 @@
 
     /** Return a copy of the specified region
     */
-    public Region(Region region) {
+    public Region(@NonNull Region region) {
         this(nativeConstructor());
         nativeSetRegion(mNativeRegion, region.mNativeRegion);
     }
 
     /** Return a region set to the specified rectangle
     */
-    public Region(Rect r) {
+    public Region(@NonNull Rect r) {
         mNativeRegion = nativeConstructor();
         nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom);
     }
@@ -86,14 +90,14 @@
 
     /** Set the region to the specified region.
     */
-    public boolean set(Region region) {
+    public boolean set(@NonNull Region region) {
         nativeSetRegion(mNativeRegion, region.mNativeRegion);
         return true;
     }
 
     /** Set the region to the specified rectangle
     */
-    public boolean set(Rect r) {
+    public boolean set(@NonNull Rect r) {
         return nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom);
     }
     
@@ -109,7 +113,7 @@
      * that is identical to the pixels that would be drawn by the path
      * (with no antialiasing).
      */
-    public boolean setPath(Path path, Region clip) {
+    public boolean setPath(@NonNull Path path, @NonNull Region clip) {
         return nativeSetPath(mNativeRegion, path.readOnlyNI(), clip.mNativeRegion);
     }
 
@@ -132,6 +136,7 @@
      * Return a new Rect set to the bounds of the region. If the region is
      * empty, the Rect will be set to [0, 0, 0, 0]
      */
+    @NonNull
     public Rect getBounds() {
         Rect r = new Rect();
         nativeGetBounds(mNativeRegion, r);
@@ -142,7 +147,7 @@
      * Set the Rect to the bounds of the region. If the region is empty, the
      * Rect will be set to [0, 0, 0, 0]
      */
-    public boolean getBounds(Rect r) {
+    public boolean getBounds(@NonNull Rect r) {
         if (r == null) {
             throw new NullPointerException();
         }
@@ -153,6 +158,7 @@
      * Return the boundary of the region as a new Path. If the region is empty,
      * the path will also be empty.
      */
+    @NonNull
     public Path getBoundaryPath() {
         Path path = new Path();
         nativeGetBoundaryPath(mNativeRegion, path.mutateNI());
@@ -163,7 +169,7 @@
      * Set the path to the boundary of the region. If the region is empty, the
      * path will also be empty.
      */
-    public boolean getBoundaryPath(Path path) {
+    public boolean getBoundaryPath(@NonNull Path path) {
         return nativeGetBoundaryPath(mNativeRegion, path.mutateNI());
     }
         
@@ -178,7 +184,7 @@
      * that the rectangle is not contained by this region, but return true is a
      * guarantee that the rectangle is contained by this region.
      */
-    public boolean quickContains(Rect r) {
+    public boolean quickContains(@NonNull Rect r) {
         return quickContains(r.left, r.top, r.right, r.bottom);
     }
 
@@ -196,7 +202,7 @@
      * not intersect the region. Returning false is not a guarantee that they
      * intersect, but returning true is a guarantee that they do not.
      */
-    public boolean quickReject(Rect r) {
+    public boolean quickReject(@NonNull Rect r) {
         return quickReject(r.left, r.top, r.right, r.bottom);
     }
 
@@ -236,6 +242,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void scale(float scale) {
         scale(scale, null);
     }
@@ -247,7 +254,7 @@
      */
     public native void scale(float scale, Region dst);
 
-    public final boolean union(Rect r) {
+    public final boolean union(@NonNull Rect r) {
         return op(r, Op.UNION);
     }
 
@@ -255,7 +262,7 @@
      * Perform the specified Op on this region and the specified rect. Return
      * true if the result of the op is not empty.
      */
-    public boolean op(Rect r, Op op) {
+    public boolean op(@NonNull Rect r, @NonNull Op op) {
         return nativeOp(mNativeRegion, r.left, r.top, r.right, r.bottom,
                         op.nativeInt);
     }
@@ -264,7 +271,7 @@
      * Perform the specified Op on this region and the specified rect. Return
      * true if the result of the op is not empty.
      */
-    public boolean op(int left, int top, int right, int bottom, Op op) {
+    public boolean op(int left, int top, int right, int bottom, @NonNull Op op) {
         return nativeOp(mNativeRegion, left, top, right, bottom,
                         op.nativeInt);
     }
@@ -273,7 +280,7 @@
      * Perform the specified Op on this region and the specified region. Return
      * true if the result of the op is not empty.
      */
-    public boolean op(Region region, Op op) {
+    public boolean op(@NonNull Region region, @NonNull Op op) {
         return op(this, region, op);
     }
 
@@ -281,7 +288,7 @@
      * Set this region to the result of performing the Op on the specified rect
      * and region. Return true if the result is not empty.
      */
-    public boolean op(Rect rect, Region region, Op op) {
+    public boolean op(@NonNull Rect rect, @NonNull Region region, @NonNull Op op) {
         return nativeOp(mNativeRegion, rect, region.mNativeRegion,
                         op.nativeInt);
     }
@@ -290,11 +297,12 @@
      * Set this region to the result of performing the Op on the specified
      * regions. Return true if the result is not empty.
      */
-    public boolean op(Region region1, Region region2, Op op) {
+    public boolean op(@NonNull Region region1, @NonNull Region region2, @NonNull Op op) {
         return nativeOp(mNativeRegion, region1.mNativeRegion,
                         region2.mNativeRegion, op.nativeInt);
     }
 
+    @Override
     public String toString() {
         return nativeToString(mNativeRegion);
     }
@@ -304,6 +312,7 @@
      *
      * @hide
      */
+    @NonNull
     public static Region obtain() {
         Region region = sPool.acquire();
         return (region != null) ? region : new Region();
@@ -316,7 +325,8 @@
      *
      * @hide
      */
-    public static Region obtain(Region other) {
+    @NonNull
+    public static Region obtain(@NonNull Region other) {
         Region region = obtain();
         region.set(other);
         return region;
@@ -327,6 +337,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void recycle() {
         setEmpty();
         sPool.release(this);
@@ -341,6 +352,7 @@
              * @param p    Parcel object to read the region from
              * @return a new region created from the data in the parcel
              */
+            @Override
             public Region createFromParcel(Parcel p) {
                 long ni = nativeCreateFromParcel(p);
                 if (ni == 0) {
@@ -348,11 +360,13 @@
                 }
                 return new Region(ni);
             }
+            @Override
             public Region[] newArray(int size) {
                 return new Region[size];
             }
     };
     
+    @Override
     public int describeContents() {
         return 0;
     }
@@ -362,6 +376,7 @@
      * rebuilt from the parcel by calling CREATOR.createFromParcel().
      * @param p    Parcel object to write the region data into
      */
+    @Override
     public void writeToParcel(Parcel p, int flags) {
         if (!nativeWriteToParcel(mNativeRegion, p)) {
             throw new RuntimeException();
@@ -377,6 +392,7 @@
         return nativeEquals(mNativeRegion, peer.mNativeRegion);
     }
 
+    @Override
     protected void finalize() throws Throwable {
         try {
             nativeDestructor(mNativeRegion);
@@ -395,6 +411,7 @@
 
     /* add dummy parameter so constructor can be called from jni without
        triggering 'not cloneable' exception */
+    @UnsupportedAppUsage
     private Region(long ni, int dummy) {
         this(ni);
     }
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 40288f5..40bcc9e 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -72,6 +73,7 @@
         TileMode(int nativeInt) {
             this.nativeInt = nativeInt;
         }
+        @UnsupportedAppUsage
         final int nativeInt;
     }
 
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 1eebd26..99f440d 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -68,13 +69,17 @@
  */
 public class SurfaceTexture {
     private final Looper mCreatorLooper;
+    @UnsupportedAppUsage
     private Handler mOnFrameAvailableHandler;
 
     /**
      * These fields are used by native code, do not access or modify.
      */
+    @UnsupportedAppUsage
     private long mSurfaceTexture;
+    @UnsupportedAppUsage
     private long mProducer;
+    @UnsupportedAppUsage
     private long mFrameAvailableListener;
 
     private boolean mIsSingleBuffered;
@@ -378,6 +383,7 @@
      * This method is invoked from native code only.
      */
     @SuppressWarnings({"UnusedDeclaration"})
+    @UnsupportedAppUsage
     private static void postEventFromNative(WeakReference<SurfaceTexture> weakSelf) {
         SurfaceTexture st = weakSelf.get();
         if (st != null) {
@@ -405,6 +411,7 @@
     private native void nativeSetDefaultBufferSize(int width, int height);
     private native void nativeUpdateTexImage();
     private native void nativeReleaseTexImage();
+    @UnsupportedAppUsage
     private native int nativeDetachFromGLContext();
     private native int nativeAttachToGLContext(int texName);
     private native void nativeRelease();
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index b6b80b4..f944d85 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 public class SweepGradient extends Shader {
 
@@ -31,11 +32,17 @@
      */
     private int mType;
 
+    @UnsupportedAppUsage
     private float mCx;
+    @UnsupportedAppUsage
     private float mCy;
+    @UnsupportedAppUsage
     private int[] mColors;
+    @UnsupportedAppUsage
     private float[] mPositions;
+    @UnsupportedAppUsage
     private int mColor0;
+    @UnsupportedAppUsage
     private int mColor1;
 
     /**
diff --git a/graphics/java/android/graphics/TableMaskFilter.java b/graphics/java/android/graphics/TableMaskFilter.java
index d0c1438..d81c491 100644
--- a/graphics/java/android/graphics/TableMaskFilter.java
+++ b/graphics/java/android/graphics/TableMaskFilter.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * @hide
  */
@@ -32,6 +34,7 @@
         native_instance = ni;
     }
     
+    @UnsupportedAppUsage
     public static TableMaskFilter CreateClipTable(int min, int max) {
         return new TableMaskFilter(nativeNewClip(min, max));
     }
diff --git a/graphics/java/android/graphics/TemporaryBuffer.java b/graphics/java/android/graphics/TemporaryBuffer.java
index 36a2275..0ae2c70 100644
--- a/graphics/java/android/graphics/TemporaryBuffer.java
+++ b/graphics/java/android/graphics/TemporaryBuffer.java
@@ -16,12 +16,14 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import com.android.internal.util.ArrayUtils;
 
 /**
  * @hide
  */
 public class TemporaryBuffer {
+    @UnsupportedAppUsage
     public static char[] obtain(int len) {
         char[] buf;
 
@@ -37,6 +39,7 @@
         return buf;
     }
 
+    @UnsupportedAppUsage
     public static void recycle(char[] temp) {
         if (temp.length > 1000) return;
 
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 18dd97f..5280642 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -25,15 +25,16 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.graphics.fonts.FontVariationAxis;
+import android.graphics.fonts.SystemFonts;
 import android.net.Uri;
 import android.provider.FontRequest;
 import android.provider.FontsContract;
 import android.text.FontConfig;
 import android.util.ArrayMap;
 import android.util.Base64;
-import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.LruCache;
 import android.util.SparseArray;
@@ -46,12 +47,9 @@
 
 import libcore.util.NativeAllocationRegistry;
 
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.annotation.Retention;
@@ -93,6 +91,7 @@
     /** The NORMAL style of the default monospace typeface. */
     public static final Typeface MONOSPACE;
 
+    @UnsupportedAppUsage
     static Typeface[] sDefaults;
 
     /**
@@ -119,12 +118,19 @@
     private static final Object sDynamicCacheLock = new Object();
 
     static Typeface sDefaultTypeface;
+
+    // Following two fields are not used but left for hiddenapi private list
+    @UnsupportedAppUsage
     static final Map<String, Typeface> sSystemFontMap;
-    static final Map<String, FontFamily[]> sSystemFallbackMap;
+
+    // We cannot support sSystemFallbackMap since we will migrate to public FontFamily API.
+    @UnsupportedAppUsage
+    static final Map<String, FontFamily[]> sSystemFallbackMap = Collections.emptyMap();
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public long native_instance;
 
     /** @hide */
@@ -139,6 +145,7 @@
     public static final int BOLD_ITALIC = 3;
     /** @hide */ public static final int STYLE_MASK = 0x03;
 
+    @UnsupportedAppUsage
     private @Style int mStyle = 0;
 
     /**
@@ -162,6 +169,7 @@
     private int[] mSupportedAxes;
     private static final int[] EMPTY_AXES = {};
 
+    @UnsupportedAppUsage
     private static void setDefault(Typeface t) {
         sDefaultTypeface = t;
         nativeSetDefault(t.native_instance);
@@ -559,11 +567,7 @@
                 return null;
             }
 
-            Typeface base =  sSystemFontMap.get(mFallbackFamilyName);
-            if (base == null) {
-                base = sDefaultTypeface;
-            }
-
+            final Typeface base =  getSystemDefaultTypeface(mFallbackFamilyName);
             if (mWeight == RESOLVE_BY_FONT_TABLE && mItalic == RESOLVE_BY_FONT_TABLE) {
                 return base;
             }
@@ -680,7 +684,7 @@
      * @return The best matching typeface.
      */
     public static Typeface create(String familyName, @Style int style) {
-        return create(sSystemFontMap.get(familyName), style);
+        return create(getSystemDefaultTypeface(familyName), style);
     }
 
     /**
@@ -890,7 +894,10 @@
      * Create a new typeface from an array of font families.
      *
      * @param families array of font families
+     * @deprecated
      */
+    @Deprecated
+    @UnsupportedAppUsage
     private static Typeface createFromFamilies(FontFamily[] families) {
         long[] ptrArray = new long[families.length];
         for (int i = 0; i < families.length; i++) {
@@ -901,9 +908,25 @@
     }
 
     /**
+     * Create a new typeface from an array of android.graphics.fonts.FontFamily.
+     *
+     * @param families array of font families
+     */
+    private static Typeface createFromFamilies(
+            @Nullable android.graphics.fonts.FontFamily[] families) {
+        final long[] ptrArray = new long[families.length];
+        for (int i = 0; i < families.length; ++i) {
+            ptrArray[i] = families[i].getNativePtr();
+        }
+        return new Typeface(nativeCreateFromArray(ptrArray,
+                  RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+    }
+
+    /**
      * This method is used by supportlib-v27.
      * TODO: Remove private API use in supportlib: http://b/72665240
      */
+    @UnsupportedAppUsage
     private static Typeface createFromFamiliesWithDefault(FontFamily[] families, int weight,
                 int italic) {
         return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, weight, italic);
@@ -922,23 +945,22 @@
      *               closest to the regular weight and upright font is used.
      * @param families array of font families
      */
+    @UnsupportedAppUsage
     private static Typeface createFromFamiliesWithDefault(FontFamily[] families,
                 String fallbackName, int weight, int italic) {
-        FontFamily[] fallback = sSystemFallbackMap.get(fallbackName);
-        if (fallback == null) {
-            fallback = sSystemFallbackMap.get(DEFAULT_FAMILY);
-        }
+        android.graphics.fonts.FontFamily[] fallback = SystemFonts.getSystemFallback(fallbackName);
         long[] ptrArray = new long[families.length + fallback.length];
         for (int i = 0; i < families.length; i++) {
             ptrArray[i] = families[i].mNativePtr;
         }
         for (int i = 0; i < fallback.length; i++) {
-            ptrArray[i + families.length] = fallback[i].mNativePtr;
+            ptrArray[i + families.length] = fallback[i].getNativePtr();
         }
         return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
     }
 
     // don't allow clients to call this directly
+    @UnsupportedAppUsage
     private Typeface(long ni) {
         if (ni == 0) {
             throw new RuntimeException("native typeface cannot be made");
@@ -950,193 +972,46 @@
         mWeight = nativeGetWeight(ni);
     }
 
-    private static @Nullable ByteBuffer mmap(String fullPath) {
-        try (FileInputStream file = new FileInputStream(fullPath)) {
-            final FileChannel fileChannel = file.getChannel();
-            final long fontSize = fileChannel.size();
-            return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
-        } catch (IOException e) {
-            Log.e(TAG, "Error mapping font file " + fullPath);
-            return null;
-        }
+    private static Typeface getSystemDefaultTypeface(@NonNull String familyName) {
+        Typeface tf = sSystemFontMap.get(familyName);
+        return tf == null ? Typeface.DEFAULT : tf;
     }
 
-    private static @Nullable FontFamily createFontFamily(
-            String familyName, List<FontConfig.Font> fonts, String[] languageTags, int variant,
-            Map<String, ByteBuffer> cache, String fontDir) {
-        final FontFamily family = new FontFamily(languageTags, variant);
-        for (int i = 0; i < fonts.size(); i++) {
-            final FontConfig.Font font = fonts.get(i);
-            final String fullPath = fontDir + font.getFontName();
-            ByteBuffer buffer = cache.get(fullPath);
-            if (buffer == null) {
-                if (cache.containsKey(fullPath)) {
-                    continue;  // Already failed to mmap. Skip it.
-                }
-                buffer = mmap(fullPath);
-                cache.put(fullPath, buffer);
-                if (buffer == null) {
-                    continue;
-                }
-            }
-            if (!family.addFontFromBuffer(buffer, font.getTtcIndex(), font.getAxes(),
-                    font.getWeight(), font.isItalic() ? STYLE_ITALIC : STYLE_NORMAL)) {
-                Log.e(TAG, "Error creating font " + fullPath + "#" + font.getTtcIndex());
-            }
-        }
-        if (!family.freeze()) {
-            Log.e(TAG, "Unable to load Family: " + familyName + " : "
-                    + Arrays.toString(languageTags));
-            return null;
-        }
-        return family;
-    }
-
-    private static void pushFamilyToFallback(FontConfig.Family xmlFamily,
-            ArrayMap<String, ArrayList<FontFamily>> fallbackMap,
-            Map<String, ByteBuffer> cache,
-            String fontDir) {
-
-        final String[] languageTags = xmlFamily.getLanguages();
-        final int variant = xmlFamily.getVariant();
-
-        final ArrayList<FontConfig.Font> defaultFonts = new ArrayList<>();
-        final ArrayMap<String, ArrayList<FontConfig.Font>> specificFallbackFonts = new ArrayMap<>();
-
-        // Collect default fallback and specific fallback fonts.
-        for (final FontConfig.Font font : xmlFamily.getFonts()) {
-            final String fallbackName = font.getFallbackFor();
-            if (fallbackName == null) {
-                defaultFonts.add(font);
-            } else {
-                ArrayList<FontConfig.Font> fallback = specificFallbackFonts.get(fallbackName);
-                if (fallback == null) {
-                    fallback = new ArrayList<>();
-                    specificFallbackFonts.put(fallbackName, fallback);
-                }
-                fallback.add(font);
-            }
-        }
-
-        final FontFamily defaultFamily = defaultFonts.isEmpty() ? null : createFontFamily(
-                xmlFamily.getName(), defaultFonts, languageTags, variant, cache, fontDir);
-
-        // Insert family into fallback map.
-        for (int i = 0; i < fallbackMap.size(); i++) {
-            final ArrayList<FontConfig.Font> fallback =
-                    specificFallbackFonts.get(fallbackMap.keyAt(i));
-            if (fallback == null) {
-                if (defaultFamily != null) {
-                    fallbackMap.valueAt(i).add(defaultFamily);
-                }
-            } else {
-                final FontFamily family = createFontFamily(
-                        xmlFamily.getName(), fallback, languageTags, variant, cache, fontDir);
-                if (family != null) {
-                    fallbackMap.valueAt(i).add(family);
-                } else if (defaultFamily != null) {
-                    fallbackMap.valueAt(i).add(defaultFamily);
-                } else {
-                    // There is no valid for for default fallback. Ignore.
-                }
-            }
-        }
-    }
-
-    /**
-     * Build the system fallback from xml file.
-     *
-     * @param xmlPath A full path string to the fonts.xml file.
-     * @param fontDir A full path string to the system font directory. This must end with
-     *                slash('/').
-     * @param fontMap An output system font map. Caller must pass empty map.
-     * @param fallbackMap An output system fallback map. Caller must pass empty map.
-     * @hide
-     */
+    /** @hide */
     @VisibleForTesting
+    public static void initSystemDefaultTypefaces(Map<String, Typeface> systemFontMap,
+            Map<String, android.graphics.fonts.FontFamily[]> fallbacks,
+            FontConfig.Alias[] aliases) {
+        for (Map.Entry<String, android.graphics.fonts.FontFamily[]> entry : fallbacks.entrySet()) {
+            systemFontMap.put(entry.getKey(), createFromFamilies(entry.getValue()));
+        }
+
+        for (FontConfig.Alias alias : aliases) {
+            final Typeface base = systemFontMap.get(alias.getToName());
+            final int weight = alias.getWeight();
+            final Typeface newFace = weight == 400 ? base :
+                    new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
+            systemFontMap.put(alias.getName(), newFace);
+        }
+    }
+
+    // Following methods are left for layoutlib
+    // TODO: Remove once layoutlib stop calling buildSystemFallback
+    /** @hide */
     public static void buildSystemFallback(String xmlPath, String fontDir,
             ArrayMap<String, Typeface> fontMap, ArrayMap<String, FontFamily[]> fallbackMap) {
-        try {
-            final FileInputStream fontsIn = new FileInputStream(xmlPath);
-            final FontConfig fontConfig = FontListParser.parse(fontsIn);
-
-            final HashMap<String, ByteBuffer> bufferCache = new HashMap<String, ByteBuffer>();
-            final FontConfig.Family[] xmlFamilies = fontConfig.getFamilies();
-
-            final ArrayMap<String, ArrayList<FontFamily>> fallbackListMap = new ArrayMap<>();
-            // First traverse families which have a 'name' attribute to create fallback map.
-            for (final FontConfig.Family xmlFamily : xmlFamilies) {
-                final String familyName = xmlFamily.getName();
-                if (familyName == null) {
-                    continue;
-                }
-                final FontFamily family = createFontFamily(
-                        xmlFamily.getName(), Arrays.asList(xmlFamily.getFonts()),
-                        xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache, fontDir);
-                if (family == null) {
-                    continue;
-                }
-                final ArrayList<FontFamily> fallback = new ArrayList<>();
-                fallback.add(family);
-                fallbackListMap.put(familyName, fallback);
-            }
-
-            // Then, add fallback fonts to the each fallback map.
-            for (int i = 0; i < xmlFamilies.length; i++) {
-                final FontConfig.Family xmlFamily = xmlFamilies[i];
-                // The first family (usually the sans-serif family) is always placed immediately
-                // after the primary family in the fallback.
-                if (i == 0 || xmlFamily.getName() == null) {
-                    pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache, fontDir);
-                }
-            }
-
-            // Build the font map and fallback map.
-            for (int i = 0; i < fallbackListMap.size(); i++) {
-                final String fallbackName = fallbackListMap.keyAt(i);
-                final List<FontFamily> familyList = fallbackListMap.valueAt(i);
-                final FontFamily[] families = familyList.toArray(new FontFamily[familyList.size()]);
-
-                fallbackMap.put(fallbackName, families);
-                final long[] ptrArray = new long[families.length];
-                for (int j = 0; j < families.length; j++) {
-                    ptrArray[j] = families[j].mNativePtr;
-                }
-                fontMap.put(fallbackName, new Typeface(nativeCreateFromArray(
-                        ptrArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE)));
-            }
-
-            // Insert alias to font maps.
-            for (final FontConfig.Alias alias : fontConfig.getAliases()) {
-                Typeface base = fontMap.get(alias.getToName());
-                Typeface newFace = base;
-                int weight = alias.getWeight();
-                if (weight != 400) {
-                    newFace = new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
-                }
-                fontMap.put(alias.getName(), newFace);
-            }
-        } catch (RuntimeException e) {
-            Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e);
-            // TODO: normal in non-Minikin case, remove or make error when Minikin-only
-        } catch (FileNotFoundException e) {
-            Log.e(TAG, "Error opening " + xmlPath, e);
-        } catch (IOException e) {
-            Log.e(TAG, "Error reading " + xmlPath, e);
-        } catch (XmlPullParserException e) {
-            Log.e(TAG, "XML parse exception for " + xmlPath, e);
-        }
     }
 
     static {
-        final ArrayMap<String, Typeface> systemFontMap = new ArrayMap<>();
-        final ArrayMap<String, FontFamily[]> systemFallbackMap = new ArrayMap<>();
-        buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/", systemFontMap,
-                systemFallbackMap);
+        final HashMap<String, Typeface> systemFontMap = new HashMap<>();
+        initSystemDefaultTypefaces(systemFontMap, SystemFonts.getRawSystemFallbackMap(),
+                SystemFonts.getAliases());
         sSystemFontMap = Collections.unmodifiableMap(systemFontMap);
-        sSystemFallbackMap = Collections.unmodifiableMap(systemFallbackMap);
 
-        setDefault(sSystemFontMap.get(DEFAULT_FAMILY));
+        // We can't assume DEFAULT_FAMILY available on Roboletric.
+        if (sSystemFontMap.containsKey(DEFAULT_FAMILY)) {
+            setDefault(sSystemFontMap.get(DEFAULT_FAMILY));
+        }
 
         // Set up defaults and typefaces exposed in public API
         DEFAULT         = create((String) null, 0);
@@ -1197,7 +1072,9 @@
     // TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[]
     private static native long nativeCreateFromTypefaceWithVariation(
             long native_instance, List<FontVariationAxis> axes);
+    @UnsupportedAppUsage
     private static native long nativeCreateWeightAlias(long native_instance, int weight);
+    @UnsupportedAppUsage
     private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
     private static native int[] nativeGetSupportedAxes(long native_instance);
 
diff --git a/graphics/java/android/graphics/Xfermode.java b/graphics/java/android/graphics/Xfermode.java
index a5da5d0..6f4adfd 100644
--- a/graphics/java/android/graphics/Xfermode.java
+++ b/graphics/java/android/graphics/Xfermode.java
@@ -21,6 +21,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Xfermode is the base class for objects that are called to implement custom
  * "transfer-modes" in the drawing pipeline. The static function Create(Modes)
@@ -30,5 +32,6 @@
  */
 public class Xfermode {
     static final int DEFAULT = PorterDuff.Mode.SRC_OVER.nativeInt;
+    @UnsupportedAppUsage
     int porterDuffMode = DEFAULT;
 }
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index 4f467d9..3aaec31 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -19,6 +19,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -562,6 +563,7 @@
      *  callback, so no need to post.
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void onAnimationEnd() {
         if (mAnimationCallbacks != null) {
             for (Animatable2.AnimationCallback callback : mAnimationCallbacks) {
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index d714ca8..b29fd4d 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.content.res.Resources;
@@ -202,11 +203,13 @@
                 R.styleable.AnimatedRotateDrawable_frameDuration, state.mFrameDuration));
     }
 
+    @UnsupportedAppUsage
     public void setFramesCount(int framesCount) {
         mState.mFramesCount = framesCount;
         mIncrement = 360.0f / mState.mFramesCount;
     }
 
+    @UnsupportedAppUsage
     public void setFramesDuration(int framesDuration) {
         mState.mFrameDuration = framesDuration;
     }
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 3ed6a78..00380c5 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -20,6 +20,7 @@
 import android.animation.TimeInterpolator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -66,6 +67,7 @@
     private static final String ELEMENT_TRANSITION = "transition";
     private static final String ELEMENT_ITEM = "item";
 
+    @UnsupportedAppUsage
     private AnimatedStateListState mState;
 
     /** The currently running transition, if any. */
@@ -558,7 +560,9 @@
 
         int[] mAnimThemeAttrs;
 
+        @UnsupportedAppUsage
         LongSparseLongArray mTransitions;
+        @UnsupportedAppUsage
         SparseIntArray mStateIds;
 
         AnimatedStateListState(@Nullable AnimatedStateListState orig,
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 8e9862c..76f2cfb 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -25,6 +25,7 @@
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.app.Application;
 import android.content.pm.ActivityInfo.Config;
@@ -305,6 +306,7 @@
     private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
 
     /** Local, mutable animator set. */
+    @UnsupportedAppUsage
     private VectorDrawableAnimator mAnimatorSet;
 
     /**
@@ -313,6 +315,7 @@
      */
     private Resources mRes;
 
+    @UnsupportedAppUsage
     private AnimatedVectorDrawableState mAnimatedVectorState;
 
     /** The animator set that is parsed from the xml. */
@@ -641,6 +644,7 @@
      * Force to animate on UI thread.
      * @hide
      */
+    @UnsupportedAppUsage
     public void forceAnimationOnUI() {
         if (mAnimatorSet instanceof VectorDrawableAnimatorRT) {
             VectorDrawableAnimatorRT animator = (VectorDrawableAnimatorRT) mAnimatorSet;
@@ -1771,6 +1775,7 @@
         }
 
         // onFinished: should be called from native
+        @UnsupportedAppUsage
         private static void callOnFinished(VectorDrawableAnimatorRT set, int id) {
             set.onAnimationEnd(id);
         }
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 0fd1741..57764c2 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -24,6 +24,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.Resources.Theme;
@@ -88,6 +89,7 @@
     private AnimationState mAnimationState;
 
     /** The current frame, ranging from 0 to {@link #mAnimationState#getChildCount() - 1} */
+    @UnsupportedAppUsage
     private int mCurFrame = 0;
 
     /** Whether the drawable has an animation callback posted. */
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 99bed60..9761901 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -87,9 +88,11 @@
 
     private final Rect mDstRect = new Rect();   // #updateDstRectAndInsetsIfDirty() sets this
 
+    @UnsupportedAppUsage
     private BitmapState mBitmapState;
     private PorterDuffColorFilter mTintFilter;
 
+    @UnsupportedAppUsage
     private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
 
     private boolean mDstRectAndInsetsDirty = true;
@@ -237,6 +240,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setBitmap(Bitmap bitmap) {
         if (mBitmapState.mBitmap != bitmap) {
             mBitmapState.mBitmap = bitmap;
@@ -692,6 +696,7 @@
     /**
      * @hide only needed by a hack within ProgressBar
      */
+    @UnsupportedAppUsage
     public ColorStateList getTint() {
         return mBitmapState.mTint;
     }
@@ -699,6 +704,7 @@
     /**
      * @hide only needed by a hack within ProgressBar
      */
+    @UnsupportedAppUsage
     public Mode getTintMode() {
         return mBitmapState.mTintMode;
     }
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index d925b6b..31fdb02 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.Resources.Theme;
@@ -58,6 +59,7 @@
 
     private final Rect mTmpRect = new Rect();
 
+    @UnsupportedAppUsage
     private ClipState mState;
 
     ClipDrawable() {
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index a601d6d..18b41fa 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -52,6 +53,7 @@
  * @attr ref android.R.styleable#ColorDrawable_color
  */
 public class ColorDrawable extends Drawable {
+    @UnsupportedAppUsage
     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 
     @ViewDebug.ExportedProperty(deepExport = true, prefix = "state_")
@@ -336,6 +338,7 @@
         int[] mThemeAttrs;
         int mBaseColor; // base color, independent of setAlpha()
         @ViewDebug.ExportedProperty
+        @UnsupportedAppUsage
         int mUseColor;  // basecolor modulated by setAlpha()
         @Config int mChangingConfigurations;
         ColorStateList mTint = null;
diff --git a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
new file mode 100644
index 0000000..40ba5d1
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.graphics.drawable;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.content.pm.ActivityInfo;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.util.MathUtils;
+
+/**
+ * A Drawable that manages a {@link ColorDrawable} to make it stateful and backed by a
+ * {@link ColorStateList}.
+ */
+public class ColorStateListDrawable extends Drawable implements Drawable.Callback {
+    private ColorDrawable mColorDrawable;
+    private ColorStateListDrawableState mState;
+
+    public ColorStateListDrawable() {
+        mState = new ColorStateListDrawableState();
+        initializeColorDrawable();
+    }
+
+    public ColorStateListDrawable(ColorStateList colorStateList) {
+        mState = new ColorStateListDrawableState();
+        initializeColorDrawable();
+        setColorStateList(colorStateList);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        mColorDrawable.draw(canvas);
+    }
+
+    @Override
+    @IntRange(from = 0, to = 255)
+    public int getAlpha() {
+        return mColorDrawable.getAlpha();
+    }
+
+    @Override
+    public boolean isStateful() {
+        return mState.isStateful();
+    }
+
+    @Override
+    public boolean hasFocusStateSpecified() {
+        return mState.hasFocusStateSpecified();
+    }
+
+    @Override
+    public @NonNull Drawable getCurrent() {
+        return mColorDrawable;
+    }
+
+    @Override
+    public void applyTheme(Resources.Theme t) {
+        super.applyTheme(t);
+
+        if (mState.mColor != null) {
+            setColorStateList(mState.mColor.obtainForTheme(t));
+        }
+
+        if (mState.mTint != null) {
+            setTintList(mState.mTint.obtainForTheme(t));
+        }
+    }
+
+    @Override
+    public boolean canApplyTheme() {
+        return super.canApplyTheme() || mState.canApplyTheme();
+    }
+
+    @Override
+    public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
+        mState.mAlpha = alpha;
+        onStateChange(getState());
+    }
+
+    /**
+     * Remove the alpha override, reverting to the alpha defined on each color in the
+     * {@link ColorStateList}.
+     */
+    public void clearAlpha() {
+        mState.mAlpha = -1;
+        onStateChange(getState());
+    }
+
+    @Override
+    public void setTintList(ColorStateList tint) {
+        mState.mTint = tint;
+        mColorDrawable.setTintList(tint);
+        onStateChange(getState());
+    }
+
+    @Override
+    public void setTintMode(PorterDuff.Mode tintMode) {
+        mState.mTintMode = tintMode;
+        mColorDrawable.setTintMode(tintMode);
+        onStateChange(getState());
+    }
+
+    @Override
+    public ColorFilter getColorFilter() {
+        return mColorDrawable.getColorFilter();
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter colorFilter) {
+        mColorDrawable.setColorFilter(colorFilter);
+    }
+
+    @Override
+    public @PixelFormat.Opacity int getOpacity() {
+        return mColorDrawable.getOpacity();
+    }
+
+    @Override
+    protected boolean onStateChange(int[] state) {
+        if (mState.mColor != null) {
+            int color = mState.mColor.getColorForState(state, mState.mColor.getDefaultColor());
+
+            if (mState.mAlpha != -1) {
+                color = color & 0xFFFFFF | MathUtils.constrain(mState.mAlpha, 0, 255) << 24;
+            }
+
+            if (color != mColorDrawable.getColor()) {
+                mColorDrawable.setColor(color);
+                mColorDrawable.setState(state);
+                return true;
+            } else {
+                return mColorDrawable.setState(state);
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public void invalidateDrawable(Drawable who) {
+        final Callback callback = getCallback();
+
+        if (callback != null) {
+            callback.invalidateDrawable(who);
+        }
+    }
+
+    @Override
+    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+        final Callback callback = getCallback();
+
+        if (callback != null) {
+            callback.scheduleDrawable(who, what, when);
+        }
+    }
+
+    @Override
+    public void unscheduleDrawable(Drawable who, Runnable what) {
+        final Callback callback = getCallback();
+
+        if (callback != null) {
+            callback.unscheduleDrawable(who, what);
+        }
+    }
+
+    @Override
+    public ConstantState getConstantState() {
+        return mState;
+    }
+
+    /**
+     * Returns the ColorStateList backing this Drawable, or a new ColorStateList of the default
+     * ColorDrawable color if one hasn't been defined yet.
+     *
+     * @return a ColorStateList
+     */
+    public @NonNull ColorStateList getColorStateList() {
+        if (mState.mColor == null) {
+            return ColorStateList.valueOf(mColorDrawable.getColor());
+        } else {
+            return mState.mColor;
+        }
+    }
+
+    /**
+     * Replace this Drawable's ColorStateList. It is not copied, so changes will propagate on the
+     * next call to {@link #setState(int[])}.
+     *
+     * @param colorStateList A color state list to attach.
+     */
+    public void setColorStateList(ColorStateList colorStateList) {
+        mState.mColor = colorStateList;
+        onStateChange(getState());
+    }
+
+    static final class ColorStateListDrawableState extends ConstantState {
+        ColorStateList mColor = null;
+        ColorStateList mTint = null;
+        int mAlpha = -1;
+        PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE;
+        @ActivityInfo.Config int mChangingConfigurations = 0;
+
+        ColorStateListDrawableState() {
+        }
+
+
+        @Override
+        public Drawable newDrawable() {
+            return new ColorStateListDrawable(this);
+        }
+
+        @Override
+        public @ActivityInfo.Config int getChangingConfigurations() {
+            return mChangingConfigurations
+                    | (mColor != null ? mColor.getChangingConfigurations() : 0)
+                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
+        }
+
+        public boolean isStateful() {
+            return (mColor != null && mColor.isStateful())
+                    || (mTint != null && mTint.isStateful());
+        }
+
+        public boolean hasFocusStateSpecified() {
+            return (mColor != null && mColor.hasFocusStateSpecified())
+                    || (mTint != null && mTint.hasFocusStateSpecified());
+        }
+
+        @Override
+        public boolean canApplyTheme() {
+            return (mColor != null && mColor.canApplyTheme())
+                    || (mTint != null && mTint.canApplyTheme());
+        }
+    }
+
+    private ColorStateListDrawable(ColorStateListDrawableState state) {
+        mState = state;
+        initializeColorDrawable();
+    }
+
+    private void initializeColorDrawable() {
+        mColorDrawable = new ColorDrawable();
+        mColorDrawable.setCallback(this);
+
+        if (mState.mTint != null) {
+            mColorDrawable.setTintList(mState.mTint);
+        }
+
+        if (mState.mTintMode != DEFAULT_TINT_MODE) {
+            mColorDrawable.setTintMode(mState.mTintMode);
+        }
+    }
+}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 986d0c1..e1f7263 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -22,6 +22,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -186,6 +187,7 @@
     private int mLevel = 0;
     private @Config int mChangingConfigurations = 0;
     private Rect mBounds = ZERO_BOUNDS_RECT;  // lazily becomes a new Rect()
+    @UnsupportedAppUsage
     private WeakReference<Callback> mCallback = null;
     private boolean mVisible = true;
 
@@ -204,6 +206,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected int mSrcDensityOverride = 0;
 
     /**
@@ -714,6 +717,7 @@
      *
      * @hide magic!
      */
+    @UnsupportedAppUsage
     public boolean isProjected() {
         return false;
     }
@@ -1389,6 +1393,7 @@
      * @throws XmlPullParserException
      * @throws IOException
      */
+    @UnsupportedAppUsage
     void inflateWithAttributes(@NonNull @SuppressWarnings("unused") Resources r,
             @NonNull @SuppressWarnings("unused") XmlPullParser parser, @NonNull TypedArray attrs,
             @AttrRes int visibleAttr) throws XmlPullParserException, IOException {
@@ -1508,6 +1513,7 @@
      * Ensures the tint filter is consistent with the current tint color and
      * mode.
      */
+    @UnsupportedAppUsage
     @Nullable PorterDuffColorFilter updateTintFilter(@Nullable PorterDuffColorFilter tintFilter,
             @Nullable ColorStateList tint, @Nullable PorterDuff.Mode tintMode) {
         if (tint == null || tintMode == null) {
@@ -1613,6 +1619,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static PorterDuff.Mode parseTintMode(int value, Mode defaultMode) {
         switch (value) {
             case 3: return Mode.SRC_OVER;
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index e7b383a..10f6fae 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -54,9 +55,11 @@
      * to improve the quality at negligible cost.
      */
     private static final boolean DEFAULT_DITHER = true;
+    @UnsupportedAppUsage
     private DrawableContainerState mDrawableContainerState;
     private Rect mHotspotBounds;
     private Drawable mCurrDrawable;
+    @UnsupportedAppUsage
     private Drawable mLastDrawable;
     private int mAlpha = 0xFF;
 
@@ -686,11 +689,13 @@
         @Config int mChildrenChangingConfigurations;
 
         SparseArray<ConstantState> mDrawableFutures;
+        @UnsupportedAppUsage
         Drawable[] mDrawables;
         int mNumChildren;
 
         boolean mVariablePadding = false;
         boolean mCheckedPadding;
+        @UnsupportedAppUsage
         Rect mConstantPadding;
 
         boolean mConstantSize = false;
@@ -720,6 +725,7 @@
         boolean mAutoMirrored;
 
         ColorFilter mColorFilter;
+        @UnsupportedAppUsage
         boolean mHasColorFilter;
 
         ColorStateList mTintList;
@@ -730,6 +736,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         protected DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
                 Resources res) {
             mOwner = owner;
diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java
index 0ee9071..bad3791 100644
--- a/graphics/java/android/graphics/drawable/DrawableInflater.java
+++ b/graphics/java/android/graphics/drawable/DrawableInflater.java
@@ -22,6 +22,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -49,6 +50,7 @@
             new HashMap<>();
 
     private final Resources mRes;
+    @UnsupportedAppUsage
     private final ClassLoader mClassLoader;
 
     /**
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index a907ca5..4ee45bf 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -46,6 +47,7 @@
  * Drawable container with only one child element.
  */
 public abstract class DrawableWrapper extends Drawable implements Drawable.Callback {
+    @UnsupportedAppUsage
     private DrawableWrapperState mState;
     private Drawable mDrawable;
     private boolean mMutated;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 5629389..8740234 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -20,6 +20,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -155,10 +156,14 @@
     private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
     private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
 
+    @UnsupportedAppUsage
     private GradientState mGradientState;
 
+    @UnsupportedAppUsage
     private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    @UnsupportedAppUsage
     private Rect mPadding;
+    @UnsupportedAppUsage
     private Paint mStrokePaint;   // optional, set by the caller
     private ColorFilter mColorFilter;   // optional, set by the caller
     private PorterDuffColorFilter mTintFilter;
@@ -1792,27 +1797,46 @@
 
     final static class GradientState extends ConstantState {
         public @Config int mChangingConfigurations;
+        @UnsupportedAppUsage
         public @Shape int mShape = RECTANGLE;
+        @UnsupportedAppUsage
         public @GradientType int mGradient = LINEAR_GRADIENT;
+        @UnsupportedAppUsage
         public int mAngle = 0;
+        @UnsupportedAppUsage
         public Orientation mOrientation;
+        @UnsupportedAppUsage
         public ColorStateList mSolidColors;
         public ColorStateList mStrokeColors;
+        @UnsupportedAppUsage
         public @ColorInt int[] mGradientColors;
         public @ColorInt int[] mTempColors; // no need to copy
         public float[] mTempPositions; // no need to copy
+        @UnsupportedAppUsage
         public float[] mPositions;
+        @UnsupportedAppUsage
         public int mStrokeWidth = -1; // if >= 0 use stroking.
+        @UnsupportedAppUsage
         public float mStrokeDashWidth = 0.0f;
+        @UnsupportedAppUsage
         public float mStrokeDashGap = 0.0f;
+        @UnsupportedAppUsage
         public float mRadius = 0.0f; // use this if mRadiusArray is null
+        @UnsupportedAppUsage
         public float[] mRadiusArray = null;
+        @UnsupportedAppUsage
         public Rect mPadding = null;
+        @UnsupportedAppUsage
         public int mWidth = -1;
+        @UnsupportedAppUsage
         public int mHeight = -1;
+        @UnsupportedAppUsage
         public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO;
+        @UnsupportedAppUsage
         public float mThicknessRatio = DEFAULT_THICKNESS_RATIO;
+        @UnsupportedAppUsage
         public int mInnerRadius = -1;
+        @UnsupportedAppUsage
         public int mThickness = -1;
         public boolean mDither = false;
         public Insets mOpticalInsets = Insets.NONE;
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 361fe0b..accc081 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -21,6 +21,7 @@
 import android.annotation.IdRes;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -99,6 +100,7 @@
 
     private static final int VERSION_STREAM_SERIALIZER = 1;
 
+    @UnsupportedAppUsage
     private final int mType;
 
     private ColorStateList mTintList;
@@ -115,6 +117,7 @@
 
     // TYPE_RESOURCE: package name
     // TYPE_URI: uri string
+    @UnsupportedAppUsage
     private String          mString1;
 
     // TYPE_RESOURCE: resId
@@ -139,6 +142,7 @@
      * @return The {@link android.graphics.Bitmap} held by this {@link #TYPE_BITMAP} Icon.
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap getBitmap() {
         if (mType != TYPE_BITMAP && mType != TYPE_ADAPTIVE_BITMAP) {
             throw new IllegalStateException("called getBitmap() on " + this);
@@ -154,6 +158,7 @@
      * @return The length of the compressed bitmap byte array held by this {@link #TYPE_DATA} Icon.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDataLength() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataLength() on " + this);
@@ -168,6 +173,7 @@
      * valid compressed bitmap data is found.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDataOffset() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataOffset() on " + this);
@@ -182,6 +188,7 @@
      * bitmap data.
      * @hide
      */
+    @UnsupportedAppUsage
     public byte[] getDataBytes() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataBytes() on " + this);
@@ -195,6 +202,7 @@
      * @return The {@link android.content.res.Resources} for this {@link #TYPE_RESOURCE} Icon.
      * @hide
      */
+    @UnsupportedAppUsage
     public Resources getResources() {
         if (mType != TYPE_RESOURCE) {
             throw new IllegalStateException("called getResources() on " + this);
@@ -560,6 +568,7 @@
      * Version of createWithResource that takes Resources. Do not use.
      * @hide
      */
+    @UnsupportedAppUsage
     public static Icon createWithResource(Resources res, @DrawableRes int resId) {
         if (res == null) {
             throw new IllegalArgumentException("Resource must not be null.");
@@ -692,6 +701,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean hasTint() {
         return (mTintList != null) || (mTintMode != DEFAULT_TINT_MODE);
     }
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index ade4294..bc8a4cb 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -57,6 +58,7 @@
     private final Rect mTmpRect = new Rect();
     private final Rect mTmpInsetRect = new Rect();
 
+    @UnsupportedAppUsage
     private InsetState mState;
 
     /**
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 4725c2c..b4392c8 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -93,6 +94,7 @@
     public static final int INSET_UNDEFINED = Integer.MIN_VALUE;
 
     @NonNull
+    @UnsupportedAppUsage
     LayerState mLayerState;
 
     private int[] mPaddingL;
@@ -428,6 +430,7 @@
      * @param layer The layer to add.
      * @return The index of the layer.
      */
+    @UnsupportedAppUsage
     int addLayer(@NonNull ChildDrawable layer) {
         final LayerState st = mLayerState;
         final int N = st.mChildren != null ? st.mChildren.length : 0;
@@ -1739,6 +1742,7 @@
     /**
      * Ensures the child padding caches are large enough.
      */
+    @UnsupportedAppUsage
     void ensurePadding() {
         final int N = mLayerState.mNumChildren;
         if (mPaddingL != null && mPaddingL.length >= N) {
@@ -1820,6 +1824,7 @@
     }
 
     static class ChildDrawable {
+        @UnsupportedAppUsage
         public Drawable mDrawable;
         public int[] mThemeAttrs;
         public int mDensity = DisplayMetrics.DENSITY_DEFAULT;
@@ -1922,6 +1927,7 @@
         private int[] mThemeAttrs;
 
         int mNumChildren;
+        @UnsupportedAppUsage
         ChildDrawable[] mChildren;
 
         int mDensity;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 7f23cea..b534771 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -70,6 +71,7 @@
     /** Temporary rect used for density scaling. */
     private Rect mTempRect;
 
+    @UnsupportedAppUsage
     private NinePatchState mNinePatchState;
     private PorterDuffColorFilter mTintFilter;
     private Rect mPadding;
@@ -588,6 +590,7 @@
         @Config int mChangingConfigurations;
 
         // Values loaded during inflation.
+        @UnsupportedAppUsage
         NinePatch mNinePatch = null;
         ColorStateList mTint = null;
         Mode mTintMode = DEFAULT_TINT_MODE;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 266a6ac..1540cc2 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -120,6 +121,7 @@
     private final Rect mDirtyBounds = new Rect();
 
     /** Mirrors mLayerState with some extra information. */
+    @UnsupportedAppUsage
     private RippleState mState;
 
     /** The masking layer, e.g. the layer with id R.id.mask. */
@@ -157,6 +159,7 @@
     private Paint mRipplePaint;
 
     /** Target density of the display into which ripples are drawn. */
+    @UnsupportedAppUsage
     private int mDensity;
 
     /** Whether bounds are being overridden. */
@@ -857,6 +860,7 @@
         mMask.draw(canvas);
     }
 
+    @UnsupportedAppUsage
     Paint getRipplePaint() {
         if (mRipplePaint == null) {
             mRipplePaint = new Paint();
@@ -945,6 +949,7 @@
      * @param forceSoftware true if RenderThread animations should be disabled, false otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public void setForceSoftware(boolean forceSoftware) {
         mForceSoftware = forceSoftware;
     }
@@ -975,6 +980,7 @@
 
     static class RippleState extends LayerState {
         int[] mTouchThemeAttrs;
+        @UnsupportedAppUsage
         ColorStateList mColor = ColorStateList.valueOf(Color.MAGENTA);
         int mMaxRadius = RADIUS_AUTO;
 
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index c0dfe77..db5f082 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.content.res.Resources;
@@ -54,6 +55,7 @@
 public class RotateDrawable extends DrawableWrapper {
     private static final int MAX_LEVEL = 10000;
 
+    @UnsupportedAppUsage
     private RotateState mState;
 
     /**
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 51e143b..91ed061 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -66,6 +67,7 @@
 
     private final Rect mTmpRect = new Rect();
 
+    @UnsupportedAppUsage
     private ScaleState mState;
 
     ScaleDrawable() {
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 67c3412..8de8f81 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -63,6 +64,7 @@
 
     private static final boolean DEBUG = false;
 
+    @UnsupportedAppUsage
     private StateListState mStateListState;
     private boolean mMutated;
 
@@ -129,6 +131,7 @@
     /**
      * Updates the constant state from the values in the typed array.
      */
+    @UnsupportedAppUsage
     private void updateStateFromTypedArray(TypedArray a) {
         final StateListState state = mStateListState;
 
@@ -206,6 +209,7 @@
      * @param attrs The attribute set.
      * @return An array of state_ attributes.
      */
+    @UnsupportedAppUsage
     int[] extractStateSet(AttributeSet attrs) {
         int j = 0;
         final int numAttrs = attrs.getAttributeCount();
@@ -329,6 +333,7 @@
             mStateSets = stateSets;
         }
 
+        @UnsupportedAppUsage
         int addStateSet(int[] stateSet, Drawable drawable) {
             final int pos = addChild(drawable);
             mStateSets[pos] = stateSet;
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 3dfd680..276f366 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -65,10 +66,13 @@
     private boolean mReverse;
     private long mStartTimeMillis;
     private int mFrom;
+    @UnsupportedAppUsage
     private int mTo;
     private int mDuration;
     private int mOriginalDuration;
+    @UnsupportedAppUsage
     private int mAlpha = 0;
+    @UnsupportedAppUsage
     private boolean mCrossFade;
 
     /**
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index b5bd97f..7325b85 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -16,6 +16,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.ComplexColor;
@@ -321,6 +322,7 @@
 
     private VectorDrawableState mVectorState;
 
+    @UnsupportedAppUsage
     private PorterDuffColorFilter mTintFilter;
     private ColorFilter mColorFilter;
 
@@ -389,6 +391,7 @@
         mMutated = false;
     }
 
+    @UnsupportedAppUsage
     Object getTargetByName(String name) {
         return mVectorState.mVGTargetsMap.get(name);
     }
@@ -867,6 +870,7 @@
         return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
     }
 
+    @UnsupportedAppUsage
     void setAllowCaching(boolean allowCaching) {
         nSetAllowCaching(mVectorState.getNativeRenderer(), allowCaching);
     }
@@ -1498,6 +1502,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setRotation(float rotation) {
             if (isTreeValid()) {
                 nSetRotation(mNativePtr, rotation);
@@ -1510,6 +1515,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setPivotX(float pivotX) {
             if (isTreeValid()) {
                 nSetPivotX(mNativePtr, pivotX);
@@ -1522,6 +1528,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setPivotY(float pivotY) {
             if (isTreeValid()) {
                 nSetPivotY(mNativePtr, pivotY);
@@ -1558,6 +1565,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setTranslateX(float translateX) {
             if (isTreeValid()) {
                 nSetTranslateX(mNativePtr, translateX);
@@ -1570,6 +1578,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setTranslateY(float translateY) {
             if (isTreeValid()) {
                 nSetTranslateY(mNativePtr, translateY);
@@ -2024,7 +2033,7 @@
                 if (fillColors instanceof  GradientColor) {
                     mFillColors = fillColors;
                     fillGradient = ((GradientColor) fillColors).getShader();
-                } else if (fillColors.isStateful()) {
+                } else if (fillColors.isStateful() || fillColors.canApplyTheme()) {
                     mFillColors = fillColors;
                 } else {
                     mFillColors = null;
@@ -2040,7 +2049,7 @@
                 if (strokeColors instanceof GradientColor) {
                     mStrokeColors = strokeColors;
                     strokeGradient = ((GradientColor) strokeColors).getShader();
-                } else if (strokeColors.isStateful()) {
+                } else if (strokeColors.isStateful() || strokeColors.canApplyTheme()) {
                     mStrokeColors = strokeColors;
                 } else {
                     mStrokeColors = null;
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
new file mode 100644
index 0000000..f0c5199
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.fonts;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.util.TypedValue;
+
+import com.android.internal.util.Preconditions;
+
+import dalvik.annotation.optimization.CriticalNative;
+
+import libcore.util.NativeAllocationRegistry;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * A font class can be used for creating FontFamily.
+ */
+public final class Font {
+    private static final String TAG = "Font";
+
+    private static final int NOT_SPECIFIED = -1;
+    private static final int STYLE_ITALIC = 1;
+    private static final int STYLE_NORMAL = 0;
+
+    /**
+     * A font weight value for the thin weight
+     */
+    public static final int FONT_WEIGHT_THIN = 100;
+
+    /**
+     * A font weight value for the extra-light weight
+     */
+    public static final int FONT_WEIGHT_EXTRA_LIGHT = 200;
+
+    /**
+     * A font weight value for the light weight
+     */
+    public static final int FONT_WEIGHT_LIGHT = 300;
+
+    /**
+     * A font weight value for the normal weight
+     */
+    public static final int FONT_WEIGHT_NORMAL = 400;
+
+    /**
+     * A font weight value for the medium weight
+     */
+    public static final int FONT_WEIGHT_MEDIUM = 500;
+
+    /**
+     * A font weight value for the semi-bold weight
+     */
+    public static final int FONT_WEIGHT_SEMI_BOLD = 600;
+
+    /**
+     * A font weight value for the bold weight.
+     */
+    public static final int FONT_WEIGHT_BOLD = 700;
+
+    /**
+     * A font weight value for the extra-bold weight
+     */
+    public static final int FONT_WEIGHT_EXTRA_BOLD = 800;
+
+    /**
+     * A font weight value for the black weight
+     */
+    public static final int FONT_WEIGHT_BLACK = 900;
+
+    /**
+     * A builder class for creating new Font.
+     */
+    public static class Builder {
+        private static final NativeAllocationRegistry sAssetByteBufferRegistroy =
+                new NativeAllocationRegistry(ByteBuffer.class.getClassLoader(),
+                    nGetReleaseNativeAssetFunc(), 64);
+
+        private static final NativeAllocationRegistry sFontRegistory =
+                new NativeAllocationRegistry(Font.class.getClassLoader(),
+                    nGetReleaseNativeFont(), 64);
+
+        private @Nullable ByteBuffer mBuffer;
+        private @IntRange(from = -1, to = 1000) int mWeight = NOT_SPECIFIED;
+        private @IntRange(from = -1, to = 1) int mItalic = NOT_SPECIFIED;
+        private @IntRange(from = 0) int mTtcIndex = 0;
+        private @Nullable FontVariationAxis[] mAxes = null;
+        private @Nullable IOException mException;
+
+        /**
+         * Constructs a builder with a byte buffer.
+         *
+         * Note that only direct buffer can be used as the source of font data.
+         *
+         * @see ByteBuffer#allocateDirect(int)
+         * @param buffer a byte buffer of a font data
+         */
+        public Builder(@NonNull ByteBuffer buffer) {
+            Preconditions.checkNotNull(buffer, "buffer can not be null");
+            if (!buffer.isDirect()) {
+                throw new IllegalArgumentException(
+                        "Only direct buffer can be used as the source of font data.");
+            }
+            mBuffer = buffer;
+        }
+
+        /**
+         * Constructs a builder with a file path.
+         *
+         * @param path a file path to the font file
+         */
+        public Builder(@NonNull File path) {
+            Preconditions.checkNotNull(path, "path can not be null");
+            try (FileInputStream fis = new FileInputStream(path)) {
+                final FileChannel fc = fis.getChannel();
+                mBuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
+            } catch (IOException e) {
+                mException = e;
+            }
+        }
+
+        /**
+         * Constructs a builder with a file descriptor.
+         *
+         * @param fd a file descriptor
+         */
+        public Builder(@NonNull FileDescriptor fd) {
+            this(fd, 0, -1);
+        }
+
+        /**
+         * Constructs a builder with a file descriptor.
+         *
+         * @param fd a file descriptor
+         * @param offset an offset to of the font data in the file
+         * @param size a size of the font data. If -1 is passed, use until end of the file.
+         */
+        public Builder(@NonNull FileDescriptor fd, @IntRange(from = 0) long offset,
+                @IntRange(from = -1) long size) {
+            try (FileInputStream fis = new FileInputStream(fd)) {
+                final FileChannel fc = fis.getChannel();
+                size = (size == -1) ? fc.size() - offset : size;
+                mBuffer = fc.map(FileChannel.MapMode.READ_ONLY, offset, size);
+            } catch (IOException e) {
+                mException = e;
+            }
+        }
+
+        /**
+         * Constructs a builder from an asset manager and a file path in an asset directory.
+         *
+         * @param am the application's asset manager
+         * @param path the file name of the font data in the asset directory
+         */
+        public Builder(@NonNull AssetManager am, @NonNull String path) {
+            final long nativeAsset = nGetNativeAsset(am, path, true /* is asset */, 0 /* cookie */);
+            if (nativeAsset == 0) {
+                mException = new FileNotFoundException("Unable to open " + path);
+                return;
+            }
+            final ByteBuffer b = nGetAssetBuffer(nativeAsset);
+            sAssetByteBufferRegistroy.registerNativeAllocation(b, nativeAsset);
+            if (b == null) {
+                mException = new FileNotFoundException(path + " not found");
+                return;
+            }
+            mBuffer = b;
+        }
+
+        /**
+         * Constructs a builder from resources.
+         *
+         * Resource ID must points the font file. XML font can not be used here.
+         *
+         * @param res the resource of this application.
+         * @param resId the resource ID of font file.
+         */
+        public Builder(@NonNull Resources res, int resId) {
+            final TypedValue value = new TypedValue();
+            res.getValue(resId, value, true);
+            if (value.string == null) {
+                mException = new FileNotFoundException(resId + " not found");
+                return;
+            }
+            final String str = value.string.toString();
+            if (str.toLowerCase().endsWith(".xml")) {
+                mException = new FileNotFoundException(resId + " must be font file.");
+                return;
+            }
+            final long nativeAsset = nGetNativeAsset(res.getAssets(), str, false /* is asset */,
+                    value.assetCookie);
+            if (nativeAsset == 0) {
+                mException = new FileNotFoundException("Unable to open " + str);
+                return;
+            }
+            final ByteBuffer b = nGetAssetBuffer(nativeAsset);
+            sAssetByteBufferRegistroy.registerNativeAllocation(b, nativeAsset);
+            if (b == null) {
+                mException = new FileNotFoundException(str + " not found");
+                return;
+            }
+            mBuffer = b;
+        }
+
+        /**
+         * Sets weight of the font.
+         *
+         * Tells the system the weight of the given font. If this function is not called, the system
+         * will resolve the weight value by reading font tables.
+         *
+         * Here are pairs of the common names and their values.
+         * <p>
+         *  <table>
+         *  <thead>
+         *  <tr>
+         *  <th align="center">Value</th>
+         *  <th align="center">Name</th>
+         *  <th align="center">Android Definition</th>
+         *  </tr>
+         *  </thead>
+         *  <tbody>
+         *  <tr>
+         *  <td align="center">100</td>
+         *  <td align="center">Thin</td>
+         *  <td align="center">{@link Font#FONT_WEIGHT_THIN}</td>
+         *  </tr>
+         *  <tr>
+         *  <td align="center">200</td>
+         *  <td align="center">Extra Light (Ultra Light)</td>
+         *  <td align="center">{@link Font#FONT_WEIGHT_EXTRA_LIGHT}</td>
+         *  </tr>
+         *  <tr>
+         *  <td align="center">300</td>
+         *  <td align="center">Light</td>
+         *  <td align="center">{@link Font#FONT_WEIGHT_LIGHT}</td>
+         *  </tr>
+         *  <tr>
+         *  <td align="center">400</td>
+         *  <td align="center">Normal (Regular)</td>
+         *  <td align="center">{@link Font#FONT_WEIGHT_NORMAL}</td>
+         *  </tr>
+         *  <tr>
+         *  <td align="center">500</td>
+         *  <td align="center">Medium</td>
+         *  <td align="center">{@link Font#FONT_WEIGHT_MEDIUM}</td>
+         *  </tr>
+         *  <tr>
+         *  <td align="center">600</td>
+         *  <td align="center">Semi Bold (Demi Bold)</td>
+         *  <td align="center">{@link Font#FONT_WEIGHT_SEMI_BOLD}</td>
+         *  </tr>
+         *  <tr>
+         *  <td align="center">700</td>
+         *  <td align="center">Bold</td>
+         *  <td align="center">{@link Font#FONT_WEIGHT_BOLD}</td>
+         *  </tr>
+         *  <tr>
+         *  <td align="center">800</td>
+         *  <td align="center">Extra Bold (Ultra Bold)</td>
+         *  <td align="center">{@link Font#FONT_WEIGHT_EXTRA_BOLD}</td>
+         *  </tr>
+         *  <tr>
+         *  <td align="center">900</td>
+         *  <td align="center">Black (Heavy)</td>
+         *  <td align="center">{@link Font#FONT_WEIGHT_BLACK}</td>
+         *  </tr>
+         *  </tbody>
+         * </p>
+         *
+         * @see Font#FONT_WEIGHT_THIN
+         * @see Font#FONT_WEIGHT_EXTRA_LIGHT
+         * @see Font#FONT_WEIGHT_LIGHT
+         * @see Font#FONT_WEIGHT_NORMAL
+         * @see Font#FONT_WEIGHT_MEDIUM
+         * @see Font#FONT_WEIGHT_SEMI_BOLD
+         * @see Font#FONT_WEIGHT_BOLD
+         * @see Font#FONT_WEIGHT_EXTRA_BOLD
+         * @see Font#FONT_WEIGHT_BLACK
+         * @param weight a weight value
+         * @return this builder
+         */
+        public @NonNull Builder setWeight(@IntRange(from = 1, to = 1000) int weight) {
+            Preconditions.checkArgument(1 <= weight && weight <= 1000);
+            mWeight = weight;
+            return this;
+        }
+
+        /**
+         * Sets italic information of the font.
+         *
+         * Tells the system the style of the given font. If this function is not called, the system
+         * will resolve the style by reading font tables.
+         *
+         * For example, if you want to use italic font as upright font, call {@code
+         * setItalic(false)} explicitly.
+         *
+         * @param italic {@code true} if the font is italic. Otherwise {@code false}.
+         * @return this builder
+         */
+        public @NonNull Builder setItalic(boolean italic) {
+            mItalic = italic ? STYLE_ITALIC : STYLE_NORMAL;
+            return this;
+        }
+
+        /**
+         * Sets an index of the font collection. See {@link android.R.attr#ttcIndex}.
+         *
+         * @param ttcIndex An index of the font collection. If the font source is not font
+         *                 collection, do not call this method or specify 0.
+         * @return this builder
+         */
+        public @NonNull Builder setTtcIndex(@IntRange(from = 0) int ttcIndex) {
+            mTtcIndex = ttcIndex;
+            return this;
+        }
+
+        /**
+         * Sets the font variation settings.
+         *
+         * @param variationSettings see {@link FontVariationAxis#fromFontVariationSettings(String)}
+         * @return this builder
+         * @throws IllegalArgumentException If given string is not a valid font variation settings
+         *                                  format.
+         */
+        public @NonNull Builder setFontVariationSettings(@Nullable String variationSettings) {
+            mAxes = FontVariationAxis.fromFontVariationSettings(variationSettings);
+            return this;
+        }
+
+        /**
+         * Sets the font variation settings.
+         *
+         * @param axes an array of font variation axis tag-value pairs
+         * @return this builder
+         */
+        public @NonNull Builder setFontVariationSettings(@Nullable FontVariationAxis[] axes) {
+            mAxes = axes == null ? null : axes.clone();
+            return this;
+        }
+
+        /**
+         * Creates the font based on the configured values.
+         * @return the Font object
+         */
+        public @Nullable Font build() throws IOException {
+            if (mException != null) {
+                throw new IOException("Failed to read font contents", mException);
+            }
+            if (mWeight == NOT_SPECIFIED || mItalic == NOT_SPECIFIED) {
+                final int packed = FontFileUtil.analyzeStyle(mBuffer, mTtcIndex, mAxes);
+                if (FontFileUtil.isSuccess(packed)) {
+                    if (mWeight == NOT_SPECIFIED) {
+                        mWeight = FontFileUtil.unpackWeight(packed);
+                    }
+                    if (mItalic == NOT_SPECIFIED) {
+                        mItalic = FontFileUtil.unpackItalic(packed) ? STYLE_ITALIC : STYLE_NORMAL;
+                    }
+                } else {
+                    mWeight = 400;
+                    mItalic = STYLE_NORMAL;
+                }
+            }
+            final boolean italic = (mItalic == STYLE_ITALIC);
+            final long builderPtr = nInitBuilder();
+            if (mAxes != null) {
+                for (FontVariationAxis axis : mAxes) {
+                    nAddAxis(builderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
+                }
+            }
+            final long ptr = nBuild(builderPtr, mBuffer, mWeight, italic, mTtcIndex);
+            final Font font = new Font(ptr, mBuffer, mWeight, italic, mTtcIndex, mAxes);
+            sFontRegistory.registerNativeAllocation(font, ptr);
+            return font;
+        }
+
+        /**
+         * Native methods for accessing underlying buffer in Asset
+         */
+        private static native long nGetNativeAsset(
+                @NonNull AssetManager am, @NonNull String path, boolean isAsset, int cookie);
+        private static native ByteBuffer nGetAssetBuffer(long nativeAsset);
+        @CriticalNative
+        private static native long nGetReleaseNativeAssetFunc();
+
+        /**
+         * Native methods for creating Font
+         */
+        private static native long nInitBuilder();
+        @CriticalNative
+        private static native void nAddAxis(long builderPtr, int tag, float value);
+        private static native long nBuild(
+                long builderPtr, ByteBuffer buffer, int weight, boolean italic, int ttcIndex);
+        @CriticalNative
+        private static native long nGetReleaseNativeFont();
+    }
+
+    private final long mNativePtr;  // address of the shared ptr of minikin::Font
+    private final @NonNull ByteBuffer mBuffer;
+    private final @IntRange(from = 0, to = 1000) int mWeight;
+    private final boolean mItalic;
+    private final @IntRange(from = 0) int mTtcIndex;
+    private final @Nullable FontVariationAxis[] mAxes;
+
+    /**
+     * Use Builder instead
+     */
+    private Font(long nativePtr, @NonNull ByteBuffer buffer,
+            @IntRange(from = 0, to = 1000) int weight, boolean italic,
+            @IntRange(from = 0) int ttcIndex, @Nullable FontVariationAxis[] axes) {
+        mBuffer = buffer;
+        mWeight = weight;
+        mItalic = italic;
+        mNativePtr = nativePtr;
+        mTtcIndex = ttcIndex;
+        mAxes = axes;
+    }
+
+    /**
+     * Get a weight value associated with this font.
+     *
+     * @see Builder#setWeight(int)
+     * @return a weight value
+     */
+    public @IntRange(from = 0, to = 1000)int getWeight() {
+        return mWeight;
+    }
+
+    /**
+     * Returns true if this font is marked as italic, otherwise returns false.
+     *
+     * @see Builder#setItalic(boolean)
+     * @return true if italic, otherwise false
+     */
+    public boolean isItalic() {
+        return mItalic;
+    }
+
+    /**
+     * Get a TTC index value associated with this font.
+     *
+     * If TTF/OTF file is provided, this value is always 0.
+     *
+     * @see Builder#setTtcIndex(int)
+     * @return a TTC index value
+     */
+    public @IntRange(from = 0) int getTtcIndex() {
+        return mTtcIndex;
+    }
+
+    /**
+     * Get a font variation settings associated with this font
+     *
+     * @see Builder#setFontVariationSettings(String)
+     * @see Builder#setFontVariationSettings(FontVariationAxis[])
+     * @return font variation settings
+     */
+    public @Nullable FontVariationAxis[] getAxes() {
+        return mAxes == null ? null : mAxes.clone();
+    }
+
+    /** @hide */
+    public long getNativePtr() {
+        return mNativePtr;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (o == null || !(o instanceof Font)) {
+            return false;
+        }
+        Font f = (Font) o;
+        return f.mWeight == mWeight && f.mItalic == mItalic && f.mTtcIndex == mTtcIndex
+                && Arrays.equals(f.mAxes, mAxes) && f.mBuffer.equals(mBuffer);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mWeight, mItalic, mTtcIndex, mAxes, mBuffer);
+    }
+
+    @Override
+    public String toString() {
+        return "Font {weight=" + mWeight + ", italic=" + mItalic + "}";
+    }
+}
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
new file mode 100644
index 0000000..c914ece
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.fonts;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.FontConfig;
+import android.text.TextUtils;
+
+import com.android.internal.util.Preconditions;
+
+import dalvik.annotation.optimization.CriticalNative;
+
+import libcore.util.NativeAllocationRegistry;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+/**
+ * A font family class can be used for creating Typeface.
+ *
+ * <p>
+ * A font family is a bundle of fonts for drawing text in various styles.
+ * For example, you can bundle regular style font and bold style font into a single font family,
+ * then system will select the correct style font from family for drawing.
+ *
+ * <pre>
+ *  FontFamily family = new FontFamily.Builder(new Font.Builder("regular.ttf").build())
+ *      .addFont(new Font.Builder("bold.ttf").build()).build();
+ *  Typeface typeface = new Typeface.Builder2(family).build();
+ *
+ *  SpannableStringBuilder ssb = new SpannableStringBuilder("Hello, World.");
+ *  ssb.setSpan(new StyleSpan(Typeface.Bold), 6, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ *
+ *  textView.setTypeface(typeface);
+ *  textView.setText(ssb);
+ * </pre>
+ *
+ * In this example, "Hello, " is drawn with "regular.ttf", and "World." is drawn with "bold.ttf".
+ *
+ * If there is no font exactly matches with the text style, the system will select the closest font.
+ * </p>
+ *
+ */
+public final class FontFamily {
+    private static final String TAG = "FontFamily";
+
+    /**
+     * A builder class for creating new FontFamily.
+     */
+    public static class Builder {
+        private static final NativeAllocationRegistry sFamilyRegistory =
+                new NativeAllocationRegistry(FontFamily.class.getClassLoader(),
+                    nGetReleaseNativeFamily(), 64);
+
+        private final ArrayList<Font> mFonts = new ArrayList<>();
+        private final HashSet<Integer> mStyleHashSet = new HashSet<>();
+
+        /**
+         * Constructs a builder.
+         *
+         * @param font a font
+         */
+        public Builder(@NonNull Font font) {
+            Preconditions.checkNotNull(font, "font can not be null");
+            mStyleHashSet.add(makeStyleIdentifier(font));
+            mFonts.add(font);
+        }
+
+        /**
+         * Adds different style font to the builder.
+         *
+         * System will select the font if the text style is closest to the font.
+         * If the same style font is already added to the builder, this method will fail with
+         * {@link IllegalArgumentException}.
+         *
+         * Note that system assumes all fonts bundled in FontFamily have the same coverage for the
+         * code points. For example, regular style font and bold style font must have the same code
+         * point coverage, otherwise some character may be shown as tofu.
+         *
+         * @param font a font
+         * @return this builder
+         */
+        public @NonNull Builder addFont(@NonNull Font font) {
+            Preconditions.checkNotNull(font, "font can not be null");
+            if (!mStyleHashSet.add(makeStyleIdentifier(font))) {
+                throw new IllegalArgumentException(font + " has already been added");
+            }
+            mFonts.add(font);
+            return this;
+        }
+
+        /**
+         * Build the font family
+         * @return a font family
+         */
+        public @NonNull FontFamily build() {
+            return build(null, FontConfig.Family.VARIANT_DEFAULT);
+        }
+
+        /** @hide */
+        public @NonNull FontFamily build(@Nullable String[] langTags, int variant) {
+            final long builderPtr = nInitBuilder();
+            for (int i = 0; i < mFonts.size(); ++i) {
+                nAddFont(builderPtr, mFonts.get(i).getNativePtr());
+            }
+            final String langString;
+            if (langTags == null || langTags.length == 0) {
+                langString = null;
+            } else if (langTags.length == 1) {
+                langString = langTags[0];
+            } else {
+                langString = TextUtils.join(",", langTags);
+            }
+
+            final long ptr = nBuild(builderPtr, langString, variant);
+            final FontFamily family = new FontFamily(mFonts, ptr);
+            sFamilyRegistory.registerNativeAllocation(family, ptr);
+            return family;
+        }
+
+        private static int makeStyleIdentifier(@NonNull Font font) {
+            return font.getWeight() | (font.isItalic() ? (1 << 16) : 0);
+        }
+
+        private static native long nInitBuilder();
+        @CriticalNative
+        private static native void nAddFont(long builderPtr, long fontPtr);
+        private static native long nBuild(long builderPtr, String langTags, int variant);
+        @CriticalNative
+        private static native long nGetReleaseNativeFamily();
+    }
+
+    private final ArrayList<Font> mFonts;
+    private final long mNativePtr;
+
+    // Use Builder instead.
+    private FontFamily(@NonNull ArrayList<Font> fonts, long ptr) {
+        mFonts = fonts;
+        mNativePtr = ptr;
+    }
+
+    /**
+     * Returns a font
+     *
+     * @param index an index of the font
+     * @return a registered font
+     */
+    public Font getFont(@IntRange(from = 0) int index) {
+        return mFonts.get(index);
+    }
+
+    /**
+     * Returns the number of fonts in this FontFamily.
+     *
+     * @return the number of fonts registered in this family.
+     */
+    public int getSize() {
+        return mFonts.size();
+    }
+
+    /** @hide */
+    public long getNativePtr() {
+        return mNativePtr;
+    }
+}
diff --git a/graphics/java/android/graphics/fonts/FontFileUtil.java b/graphics/java/android/graphics/fonts/FontFileUtil.java
new file mode 100644
index 0000000..f8b456b
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/FontFileUtil.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.fonts;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Provides a utility for font file operations.
+ * @hide
+ */
+public class FontFileUtil {
+
+    private FontFileUtil() {}  // Do not instanciate
+
+    /**
+     * Unpack the weight value from packed integer.
+     */
+    public static int unpackWeight(int packed) {
+        return packed & 0xFFFF;
+    }
+
+    /**
+     * Unpack the italic value from packed integer.
+     */
+    public static boolean unpackItalic(int packed) {
+        return (packed & 0x10000) != 0;
+    }
+
+    /**
+     * Returns true if the analyzeStyle succeeded
+     */
+    public static boolean isSuccess(int packed) {
+        return packed != ANALYZE_ERROR;
+    }
+
+    private static int pack(@IntRange(from = 0, to = 1000) int weight, boolean italic) {
+        return weight | (italic ? 0x10000 : 0);
+    }
+
+    private static final int SFNT_VERSION_1 = 0x00010000;
+    private static final int SFNT_VERSION_OTTO = 0x4F54544F;
+    private static final int TTC_TAG = 0x74746366;
+    private static final int OS2_TABLE_TAG = 0x4F532F32;
+
+    private static final int ANALYZE_ERROR = 0xFFFFFFFF;
+
+    /**
+     * Analyze the font file returns packed style info
+     */
+    public static final int analyzeStyle(@NonNull ByteBuffer buffer,
+            @IntRange(from = 0) int ttcIndex, @Nullable FontVariationAxis[] varSettings) {
+        int weight = -1;
+        int italic = -1;
+        if (varSettings != null) {
+            for (FontVariationAxis axis :varSettings) {
+                if ("wght".equals(axis.getTag())) {
+                    weight = (int) axis.getStyleValue();
+                } else if ("ital".equals(axis.getTag())) {
+                    italic = (axis.getStyleValue() == 1.0f) ? 1 : 0;
+                }
+            }
+        }
+
+        if (weight != -1 && italic != -1) {
+            // Both weight/italic style are specifeid by variation settings.
+            // No need to look into OS/2 table.
+            // TODO: Good to look HVAR table to check if this font supports wght/ital axes.
+            return pack(weight, italic == 1);
+        }
+
+        ByteOrder originalOrder = buffer.order();
+        buffer.order(ByteOrder.BIG_ENDIAN);
+        try {
+            int fontFileOffset = 0;
+            int magicNumber = buffer.getInt(0);
+            if (magicNumber == TTC_TAG) {
+                // TTC file.
+                if (ttcIndex >= buffer.getInt(8 /* offset to number of fonts in TTC */)) {
+                    return ANALYZE_ERROR;
+                }
+                fontFileOffset = buffer.getInt(
+                    12 /* offset to array of offsets of font files */ + 4 * ttcIndex);
+            }
+            int sfntVersion = buffer.getInt(fontFileOffset);
+
+            if (sfntVersion != SFNT_VERSION_1 && sfntVersion != SFNT_VERSION_OTTO) {
+                return ANALYZE_ERROR;
+            }
+
+            int numTables = buffer.getShort(fontFileOffset + 4 /* offset to number of tables */);
+            int os2TableOffset = -1;
+            for (int i = 0; i < numTables; ++i) {
+                int tableOffset = fontFileOffset + 12 /* size of offset table */
+                        + i * 16 /* size of table record */;
+                if (buffer.getInt(tableOffset) == OS2_TABLE_TAG) {
+                    os2TableOffset = buffer.getInt(tableOffset + 8 /* offset to the table */);
+                    break;
+                }
+            }
+
+            if (os2TableOffset == -1) {
+                // Couldn't find OS/2 table. use regular style
+                return pack(400, false);
+            }
+
+            int weightFromOS2 = buffer.getShort(os2TableOffset + 4 /* offset to weight class */);
+            boolean italicFromOS2 =
+                    (buffer.getShort(os2TableOffset + 62 /* offset to fsSelection */) & 1) != 0;
+            return pack(weight == -1 ? weightFromOS2 : weight,
+                    italic == -1 ? italicFromOS2 : italic == 1);
+        } finally {
+            buffer.order(originalOrder);
+        }
+    }
+}
diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java
index 1b7408a..242cbb8 100644
--- a/graphics/java/android/graphics/fonts/FontVariationAxis.java
+++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java
@@ -18,17 +18,21 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.text.TextUtils;
 
 import java.util.ArrayList;
+import java.util.Objects;
 import java.util.regex.Pattern;
 
 /**
  * Class that holds information about single font variation axis.
  */
 public final class FontVariationAxis {
+    @UnsupportedAppUsage
     private final int mTag;
     private final String mTagString;
+    @UnsupportedAppUsage
     private final float mStyleValue;
 
     /**
@@ -183,5 +187,22 @@
         }
         return TextUtils.join(",", axes);
     }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (o == null || !(o instanceof FontVariationAxis)) {
+            return false;
+        }
+        FontVariationAxis axis = (FontVariationAxis) o;
+        return axis.mTag == mTag && axis.mStyleValue == mStyleValue;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mTag, mStyleValue);
+    }
 }
 
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
new file mode 100644
index 0000000..26b4ec5
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.FontListParser;
+import android.text.FontConfig;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Provides the system font configurations.
+ * @hide
+ */
+public class SystemFonts {
+    private static final String TAG = "SystemFonts";
+    private static final String DEFAULT_FAMILY = "sans-serif";
+
+    private SystemFonts() {}  // Do not instansiate.
+
+    static final Map<String, FontFamily[]> sSystemFallbackMap;
+    static final FontConfig.Alias[] sAliases;
+
+    /**
+     * Returns fallback list for the given family name.
+     *
+     * If no fallback found for the given family name, returns fallback for the default family.
+     *
+     * @param familyName family name, e.g. "serif"
+     */
+    public static @NonNull FontFamily[] getSystemFallback(@Nullable String familyName) {
+        final FontFamily[] families = sSystemFallbackMap.get(familyName);
+        return families == null ? sSystemFallbackMap.get(DEFAULT_FAMILY) : families;
+    }
+
+    /**
+     * Returns raw system fallback map.
+     *
+     * This method is intended to be used only by Typeface static initializer.
+     */
+    public static @NonNull Map<String, FontFamily[]> getRawSystemFallbackMap() {
+        return sSystemFallbackMap;
+    }
+
+    /**
+     * Returns a list of aliases.
+     *
+     * This method is intended to be used only by Typeface static initializer.
+     */
+    public static @NonNull FontConfig.Alias[] getAliases() {
+        return sAliases;
+    }
+
+    private static @Nullable ByteBuffer mmap(@NonNull String fullPath) {
+        try (FileInputStream file = new FileInputStream(fullPath)) {
+            final FileChannel fileChannel = file.getChannel();
+            final long fontSize = fileChannel.size();
+            return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
+        } catch (IOException e) {
+            Log.e(TAG, "Error mapping font file " + fullPath);
+            return null;
+        }
+    }
+
+    private static void pushFamilyToFallback(@NonNull FontConfig.Family xmlFamily,
+            @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackMap,
+            @NonNull Map<String, ByteBuffer> cache,
+            @NonNull String fontDir) {
+
+        final String[] languageTags = xmlFamily.getLanguages();
+        final int variant = xmlFamily.getVariant();
+
+        final ArrayList<FontConfig.Font> defaultFonts = new ArrayList<>();
+        final ArrayMap<String, ArrayList<FontConfig.Font>> specificFallbackFonts = new ArrayMap<>();
+
+        // Collect default fallback and specific fallback fonts.
+        for (final FontConfig.Font font : xmlFamily.getFonts()) {
+            final String fallbackName = font.getFallbackFor();
+            if (fallbackName == null) {
+                defaultFonts.add(font);
+            } else {
+                ArrayList<FontConfig.Font> fallback = specificFallbackFonts.get(fallbackName);
+                if (fallback == null) {
+                    fallback = new ArrayList<>();
+                    specificFallbackFonts.put(fallbackName, fallback);
+                }
+                fallback.add(font);
+            }
+        }
+
+        final FontFamily defaultFamily = defaultFonts.isEmpty() ? null : createFontFamily(
+                xmlFamily.getName(), defaultFonts, languageTags, variant, cache, fontDir);
+
+        // Insert family into fallback map.
+        for (int i = 0; i < fallbackMap.size(); i++) {
+            final ArrayList<FontConfig.Font> fallback =
+                    specificFallbackFonts.get(fallbackMap.keyAt(i));
+            if (fallback == null) {
+                if (defaultFamily != null) {
+                    fallbackMap.valueAt(i).add(defaultFamily);
+                }
+            } else {
+                final FontFamily family = createFontFamily(
+                        xmlFamily.getName(), fallback, languageTags, variant, cache, fontDir);
+                if (family != null) {
+                    fallbackMap.valueAt(i).add(family);
+                } else if (defaultFamily != null) {
+                    fallbackMap.valueAt(i).add(defaultFamily);
+                } else {
+                    // There is no valid for for default fallback. Ignore.
+                }
+            }
+        }
+    }
+
+    private static @Nullable FontFamily createFontFamily(@NonNull String familyName,
+            @NonNull List<FontConfig.Font> fonts,
+            @NonNull String[] languageTags,
+            @FontConfig.Family.Variant int variant,
+            @NonNull Map<String, ByteBuffer> cache,
+            @NonNull String fontDir) {
+        if (fonts.size() == 0) {
+            return null;
+        }
+
+        FontFamily.Builder b = null;
+        for (int i = 0; i < fonts.size(); i++) {
+            final FontConfig.Font fontConfig = fonts.get(i);
+            final String fullPath = fontDir + fontConfig.getFontName();
+            ByteBuffer buffer = cache.get(fullPath);
+            if (buffer == null) {
+                if (cache.containsKey(fullPath)) {
+                    continue;  // Already failed to mmap. Skip it.
+                }
+                buffer = mmap(fullPath);
+                cache.put(fullPath, buffer);
+                if (buffer == null) {
+                    continue;
+                }
+            }
+
+            final Font font;
+            try {
+                font = new Font.Builder(buffer)
+                        .setWeight(fontConfig.getWeight())
+                        .setItalic(fontConfig.isItalic())
+                        .setTtcIndex(fontConfig.getTtcIndex())
+                        .setFontVariationSettings(fontConfig.getAxes())
+                        .build();
+            } catch (IOException e) {
+                throw new RuntimeException(e);  // Never reaches here
+            }
+
+            if (b == null) {
+                b = new FontFamily.Builder(font);
+            } else {
+                b.addFont(font);
+            }
+        }
+        return b == null ? null : b.build(languageTags, variant);
+    }
+
+    /**
+     * Build the system fallback from xml file.
+     *
+     * @param xmlPath A full path string to the fonts.xml file.
+     * @param fontDir A full path string to the system font directory. This must end with
+     *                slash('/').
+     * @param fallbackMap An output system fallback map. Caller must pass empty map.
+     * @return a list of aliases
+     * @hide
+     */
+    @VisibleForTesting
+    public static FontConfig.Alias[] buildSystemFallback(@NonNull String xmlPath,
+            @NonNull String fontDir,
+            @NonNull ArrayMap<String, FontFamily[]> fallbackMap) {
+        try {
+            final FileInputStream fontsIn = new FileInputStream(xmlPath);
+            final FontConfig fontConfig = FontListParser.parse(fontsIn);
+
+            final HashMap<String, ByteBuffer> bufferCache = new HashMap<String, ByteBuffer>();
+            final FontConfig.Family[] xmlFamilies = fontConfig.getFamilies();
+
+            final ArrayMap<String, ArrayList<FontFamily>> fallbackListMap = new ArrayMap<>();
+            // First traverse families which have a 'name' attribute to create fallback map.
+            for (final FontConfig.Family xmlFamily : xmlFamilies) {
+                final String familyName = xmlFamily.getName();
+                if (familyName == null) {
+                    continue;
+                }
+                final FontFamily family = createFontFamily(
+                        xmlFamily.getName(), Arrays.asList(xmlFamily.getFonts()),
+                        xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache, fontDir);
+                if (family == null) {
+                    continue;
+                }
+                final ArrayList<FontFamily> fallback = new ArrayList<>();
+                fallback.add(family);
+                fallbackListMap.put(familyName, fallback);
+            }
+
+            // Then, add fallback fonts to the each fallback map.
+            for (int i = 0; i < xmlFamilies.length; i++) {
+                final FontConfig.Family xmlFamily = xmlFamilies[i];
+                // The first family (usually the sans-serif family) is always placed immediately
+                // after the primary family in the fallback.
+                if (i == 0 || xmlFamily.getName() == null) {
+                    pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache, fontDir);
+                }
+            }
+
+            // Build the font map and fallback map.
+            for (int i = 0; i < fallbackListMap.size(); i++) {
+                final String fallbackName = fallbackListMap.keyAt(i);
+                final List<FontFamily> familyList = fallbackListMap.valueAt(i);
+                final FontFamily[] families = familyList.toArray(new FontFamily[familyList.size()]);
+
+                fallbackMap.put(fallbackName, families);
+            }
+
+            return fontConfig.getAliases();
+        } catch (IOException | XmlPullParserException e) {
+            Log.e(TAG, "Failed initialize system fallbacks.", e);
+            return ArrayUtils.emptyArray(FontConfig.Alias.class);
+        }
+    }
+
+    static {
+        final ArrayMap<String, FontFamily[]> systemFallbackMap = new ArrayMap<>();
+        sAliases = buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/",
+                systemFallbackMap);
+        sSystemFallbackMap = Collections.unmodifiableMap(systemFallbackMap);
+    }
+
+}
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index 4a91705..1836f00 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.Matrix;
@@ -118,6 +119,7 @@
 
     private ParcelFileDescriptor mInput;
 
+    @UnsupportedAppUsage
     private Page mCurrentPage;
 
     /** @hide */
@@ -242,6 +244,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void doClose() {
         if (mCurrentPage != null) {
             mCurrentPage.close();
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 57db20b..7216a22 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -16,6 +16,7 @@
 
 package android.security;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
@@ -172,6 +173,7 @@
 
     private static Credentials singleton;
 
+    @UnsupportedAppUsage
     public static Credentials getInstance() {
         if (singleton == null) {
             singleton = new Credentials();
@@ -179,6 +181,7 @@
         return singleton;
     }
 
+    @UnsupportedAppUsage
     public void unlock(Context context) {
         try {
             Intent intent = new Intent(UNLOCK_ACTION);
@@ -197,6 +200,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void install(Context context, KeyPair pair) {
         try {
             Intent intent = KeyChain.createInstallIntent();
@@ -208,6 +212,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void install(Context context, String type, byte[] value) {
         try {
             Intent intent = KeyChain.createInstallIntent();
diff --git a/keystore/java/android/security/GateKeeper.java b/keystore/java/android/security/GateKeeper.java
index 03df5de..a50ff79 100644
--- a/keystore/java/android/security/GateKeeper.java
+++ b/keystore/java/android/security/GateKeeper.java
@@ -16,6 +16,7 @@
 
 package android.security;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -42,6 +43,7 @@
         return service;
     }
 
+    @UnsupportedAppUsage
     public static long getSecureUserId() throws IllegalStateException {
         try {
             return getService().getSecureUserId(UserHandle.myUserId());
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 030fa60..78dbb6a 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -283,10 +283,16 @@
     public static final int KEY_GEN_NO_KEYSTORE_PROVIDER = 5;
 
     /**
+     * StrongBox unavailable when calling {@link #generateKeyPair}
+     * @hide
+     */
+    public static final int KEY_GEN_STRONGBOX_UNAVAILABLE = 6;
+
+    /**
      * General failure while calling {@link #generateKeyPair}
      * @hide
      */
-    public static final int KEY_GEN_FAILURE = 6;
+    public static final int KEY_GEN_FAILURE = 7;
 
     /**
      * Successful call to {@link #attestKey}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 8502309..0a4ac8c 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -16,6 +16,7 @@
 
 package android.security;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.Application;
@@ -57,6 +58,7 @@
     private static final String TAG = "KeyStore";
 
     // ResponseCodes - see system/security/keystore/include/keystore/keystore.h
+    @UnsupportedAppUsage
     public static final int NO_ERROR = 1;
     public static final int LOCKED = 2;
     public static final int UNINITIALIZED = 3;
@@ -128,7 +130,13 @@
     public static final int FLAG_STRONGBOX = 1 << 4;
 
     // States
-    public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
+    public enum State {
+        @UnsupportedAppUsage
+        UNLOCKED,
+        @UnsupportedAppUsage
+        LOCKED,
+        UNINITIALIZED
+    };
 
     private int mError = NO_ERROR;
 
@@ -142,6 +150,7 @@
         mContext = getApplicationContext();
     }
 
+    @UnsupportedAppUsage
     public static Context getApplicationContext() {
         Application application = ActivityThread.currentApplication();
         if (application == null) {
@@ -151,6 +160,7 @@
         return application;
     }
 
+    @UnsupportedAppUsage
     public static KeyStore getInstance() {
         IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
                 .getService("android.security.keystore"));
@@ -164,6 +174,7 @@
         return mToken;
     }
 
+    @UnsupportedAppUsage
     public State state(int userId) {
         final int ret;
         try {
@@ -181,6 +192,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public State state() {
         return state(UserHandle.myUserId());
     }
@@ -193,6 +205,7 @@
         return get(key, uid, false);
     }
 
+    @UnsupportedAppUsage
     public byte[] get(String key) {
         return get(key, UID_SELF);
     }
@@ -243,6 +256,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public boolean delete(String key) {
         return delete(key, UID_SELF);
     }
@@ -279,6 +293,7 @@
         return list(prefix, UID_SELF);
     }
 
+    @UnsupportedAppUsage
     public boolean reset() {
         try {
             return mBinder.reset() == NO_ERROR;
@@ -329,6 +344,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public boolean unlock(String password) {
         return unlock(UserHandle.getUserId(Process.myUid()), password);
     }
@@ -345,6 +361,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public boolean isEmpty() {
         return isEmpty(UserHandle.myUserId());
     }
@@ -814,6 +831,7 @@
      * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
      * code.
      */
+    @UnsupportedAppUsage
     public static KeyStoreException getKeyStoreException(int errorCode) {
         if (errorCode > 0) {
             // KeyStore layer error
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index 419eb24..953cef7d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -301,6 +301,9 @@
                 KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
                         mRng, (mKeySizeBits + 7) / 8);
         int flags = 0;
+        if (spec.isStrongBoxBacked()) {
+            flags |= KeyStore.FLAG_STRONGBOX;
+        }
         String keyAliasInKeystore = Credentials.USER_PRIVATE_KEY + spec.getKeystoreAlias();
         KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
         boolean success = false;
@@ -314,8 +317,12 @@
                     flags,
                     resultingKeyCharacteristics);
             if (errorCode != KeyStore.NO_ERROR) {
-                throw new ProviderException(
-                        "Keystore operation failed", KeyStore.getKeyStoreException(errorCode));
+                if (errorCode == KeyStore.HARDWARE_TYPE_UNAVAILABLE) {
+                    throw new StrongBoxUnavailableException("Failed to generate key");
+                } else {
+                    throw new ProviderException(
+                            "Keystore operation failed", KeyStore.getKeyStoreException(errorCode));
+                }
             }
             @KeyProperties.KeyAlgorithmEnum String keyAlgorithmJCA;
             try {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index c048e82..c7c9ee4 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -17,6 +17,7 @@
 package android.security.keystore;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.security.KeyStore;
 import android.security.keymaster.ExportResult;
 import android.security.keymaster.KeyCharacteristics;
@@ -156,6 +157,7 @@
      *         by AndroidKeyStore provider.
      * @throws IllegalStateException if the provided primitive is not initialized.
      */
+    @UnsupportedAppUsage
     public static long getKeyStoreOperationHandle(Object cryptoPrimitive) {
         if (cryptoPrimitive == null) {
             throw new NullPointerException();
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index 1be8309..3d2a271 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -22,9 +22,9 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.content.Context;
+import android.content.res.Resources;
 import android.os.Build;
 import android.security.KeyStore;
-import android.security.KeyStoreException;
 import android.security.keymaster.KeymasterArguments;
 import android.security.keymaster.KeymasterCertificateChain;
 import android.security.keymaster.KeymasterDefs;
@@ -117,6 +117,37 @@
     @NonNull public static KeymasterArguments prepareAttestationArguments(Context context,
             @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
             DeviceIdAttestationException {
+        return prepareAttestationArguments(context, idTypes,attestationChallenge, Build.BRAND);
+    }
+
+    /**
+     * Prepares Keymaster Arguments with attestation data for misprovisioned Pixel 2 device.
+     * See http://go/keyAttestationFailure and http://b/69471841 for more info.
+     * @hide should only be used by KeyChain.
+     */
+    @NonNull public static KeymasterArguments prepareAttestationArgumentsIfMisprovisioned(
+            Context context, @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
+            DeviceIdAttestationException {
+        if (!isPotentiallyMisprovisionedDevice(context)) {
+            return null;
+        }
+        Resources resources = context.getResources();
+        String misprovisionedBrand = resources.getString(
+                com.android.internal.R.string.config_misprovisionedBrandValue);
+        return prepareAttestationArguments(
+                    context, idTypes, attestationChallenge, misprovisionedBrand);
+    }
+
+    @NonNull private static boolean isPotentiallyMisprovisionedDevice(Context context) {
+        Resources resources = context.getResources();
+        String misprovisionedModel = resources.getString(
+                com.android.internal.R.string.config_misprovisionedDeviceModel);
+        return (Build.MODEL.equals(misprovisionedModel));
+    }
+
+    @NonNull private static KeymasterArguments prepareAttestationArguments(Context context,
+            @NonNull int[] idTypes, @NonNull byte[] attestationChallenge, String brand) throws
+            DeviceIdAttestationException {
         // Check method arguments, retrieve requested device IDs and prepare attestation arguments.
         if (attestationChallenge == null) {
             throw new NullPointerException("Missing attestation challenge");
@@ -169,7 +200,7 @@
             }
         }
         attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND,
-                Build.BRAND.getBytes(StandardCharsets.UTF_8));
+                brand.getBytes(StandardCharsets.UTF_8));
         attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,
                 Build.DEVICE.getBytes(StandardCharsets.UTF_8));
         attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT,
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 452024c..c4df274 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.KeyguardManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.security.GateKeeper;
@@ -268,6 +269,11 @@
     private final boolean mIsStrongBoxBacked;
     private final boolean mUserConfirmationRequired;
     private final boolean mUnlockedDeviceRequired;
+    /*
+     * ***NOTE***: All new fields MUST also be added to the following:
+     * ParcelableKeyGenParameterSpec class.
+     * The KeyGenParameterSpec.Builder constructor that takes a KeyGenParameterSpec
+     */
 
     /**
      * @hide should be built with Builder
@@ -366,6 +372,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getUid() {
         return mUid;
     }
@@ -640,6 +647,7 @@
      *
      * Returns {@code true} if the attestation certificate will contain a unique ID field.
      */
+    @UnsupportedAppUsage
     public boolean isUniqueIdIncluded() {
         return mUniqueIdIncluded;
     }
@@ -791,6 +799,9 @@
             mUniqueIdIncluded = sourceSpec.isUniqueIdIncluded();
             mUserAuthenticationValidWhileOnBody = sourceSpec.isUserAuthenticationValidWhileOnBody();
             mInvalidatedByBiometricEnrollment = sourceSpec.isInvalidatedByBiometricEnrollment();
+            mIsStrongBoxBacked = sourceSpec.isStrongBoxBacked();
+            mUserConfirmationRequired = sourceSpec.isUserConfirmationRequired();
+            mUnlockedDeviceRequired = sourceSpec.isUnlockedDeviceRequired();
         }
 
         /**
diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
index 911bbf8..8231dc9 100644
--- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
@@ -97,11 +97,14 @@
         out.writeBoolean(mSpec.isRandomizedEncryptionRequired());
         out.writeBoolean(mSpec.isUserAuthenticationRequired());
         out.writeInt(mSpec.getUserAuthenticationValidityDurationSeconds());
+        out.writeBoolean(mSpec.isUserPresenceRequired());
         out.writeByteArray(mSpec.getAttestationChallenge());
         out.writeBoolean(mSpec.isUniqueIdIncluded());
         out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody());
         out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment());
-        out.writeBoolean(mSpec.isUserPresenceRequired());
+        out.writeBoolean(mSpec.isStrongBoxBacked());
+        out.writeBoolean(mSpec.isUserConfirmationRequired());
+        out.writeBoolean(mSpec.isUnlockedDeviceRequired());
     }
 
     private static Date readDateOrNull(Parcel in) {
@@ -114,19 +117,12 @@
     }
 
     private ParcelableKeyGenParameterSpec(Parcel in) {
-        String keystoreAlias = in.readString();
-        int purposes = in.readInt();
-        KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(
-                keystoreAlias, purposes);
-        builder.setUid(in.readInt());
-        // KeySize is -1 by default, if the KeyGenParameterSpec previously parcelled had the default
-        // value, do not set it as this will cause setKeySize to throw.
-        int keySize = in.readInt();
-        if (keySize >= 0) {
-            builder.setKeySize(keySize);
-        }
+        final String keystoreAlias = in.readString();
+        final int purposes = in.readInt();
+        final int uid = in.readInt();
+        final int keySize = in.readInt();
 
-        int keySpecType = in.readInt();
+        final int keySpecType = in.readInt();
         AlgorithmParameterSpec algorithmSpec = null;
         if (keySpecType == ALGORITHM_PARAMETER_SPEC_NONE) {
             algorithmSpec = null;
@@ -141,32 +137,60 @@
             throw new IllegalArgumentException(
                     String.format("Unknown algorithm parameter spec: %d", keySpecType));
         }
-        if (algorithmSpec != null) {
-            builder.setAlgorithmParameterSpec(algorithmSpec);
-        }
-        builder.setCertificateSubject(new X500Principal(in.createByteArray()));
-        builder.setCertificateSerialNumber(new BigInteger(in.createByteArray()));
-        builder.setCertificateNotBefore(new Date(in.readLong()));
-        builder.setCertificateNotAfter(new Date(in.readLong()));
-        builder.setKeyValidityStart(readDateOrNull(in));
-        builder.setKeyValidityForOriginationEnd(readDateOrNull(in));
-        builder.setKeyValidityForConsumptionEnd(readDateOrNull(in));
-        String[] digests = in.createStringArray();
-        if (digests != null) {
-            builder.setDigests(digests);
-        }
-        builder.setEncryptionPaddings(in.createStringArray());
-        builder.setSignaturePaddings(in.createStringArray());
-        builder.setBlockModes(in.createStringArray());
-        builder.setRandomizedEncryptionRequired(in.readBoolean());
-        builder.setUserAuthenticationRequired(in.readBoolean());
-        builder.setUserAuthenticationValidityDurationSeconds(in.readInt());
-        builder.setAttestationChallenge(in.createByteArray());
-        builder.setUniqueIdIncluded(in.readBoolean());
-        builder.setUserAuthenticationValidWhileOnBody(in.readBoolean());
-        builder.setInvalidatedByBiometricEnrollment(in.readBoolean());
-        builder.setUserPresenceRequired(in.readBoolean());
-        mSpec = builder.build();
+
+        final X500Principal certificateSubject = new X500Principal(in.createByteArray());
+        final BigInteger certificateSerialNumber = new BigInteger(in.createByteArray());
+        final Date certificateNotBefore = new Date(in.readLong());
+        final Date certificateNotAfter = new Date(in.readLong());
+        final Date keyValidityStartDate = readDateOrNull(in);
+        final Date keyValidityForOriginationEnd = readDateOrNull(in);
+        final Date keyValidityForConsumptionEnd = readDateOrNull(in);
+        final String[] digests = in.createStringArray();
+        final String[] encryptionPaddings = in.createStringArray();
+        final String[] signaturePaddings = in.createStringArray();
+        final String[] blockModes = in.createStringArray();
+        final boolean randomizedEncryptionRequired = in.readBoolean();
+        final boolean userAuthenticationRequired = in.readBoolean();
+        final int userAuthenticationValidityDurationSeconds = in.readInt();
+        final boolean userPresenceRequired = in.readBoolean();
+        final byte[] attestationChallenge = in.createByteArray();
+        final boolean uniqueIdIncluded = in.readBoolean();
+        final boolean userAuthenticationValidWhileOnBody = in.readBoolean();
+        final boolean invalidatedByBiometricEnrollment = in.readBoolean();
+        final boolean isStrongBoxBacked = in.readBoolean();
+        final boolean userConfirmationRequired = in.readBoolean();
+        final boolean unlockedDeviceRequired = in.readBoolean();
+        // The KeyGenParameterSpec is intentionally not constructed using a Builder here:
+        // The intention is for this class to break if new parameters are added to the
+        // KeyGenParameterSpec constructor (whereas using a builder would silently drop them).
+        mSpec = new KeyGenParameterSpec(
+                keystoreAlias,
+                uid,
+                keySize,
+                algorithmSpec,
+                certificateSubject,
+                certificateSerialNumber,
+                certificateNotBefore,
+                certificateNotAfter,
+                keyValidityStartDate,
+                keyValidityForOriginationEnd,
+                keyValidityForConsumptionEnd,
+                purposes,
+                digests,
+                encryptionPaddings,
+                signaturePaddings,
+                blockModes,
+                randomizedEncryptionRequired,
+                userAuthenticationRequired,
+                userAuthenticationValidityDurationSeconds,
+                userPresenceRequired,
+                attestationChallenge,
+                uniqueIdIncluded,
+                userAuthenticationValidWhileOnBody,
+                invalidatedByBiometricEnrollment,
+                isStrongBoxBacked,
+                userConfirmationRequired,
+                unlockedDeviceRequired);
     }
 
     public static final Creator<ParcelableKeyGenParameterSpec> CREATOR = new Creator<ParcelableKeyGenParameterSpec>() {
diff --git a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
index 254b6be..32f8ec4 100644
--- a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
+++ b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
@@ -77,6 +77,9 @@
                 .setUniqueIdIncluded(true)
                 .setUserAuthenticationValidWhileOnBody(true)
                 .setInvalidatedByBiometricEnrollment(true)
+                .setIsStrongBoxBacked(true)
+                .setUserConfirmationRequired(true)
+                .setUnlockedDeviceRequired(true)
                 .build();
     }
 
@@ -105,6 +108,9 @@
         assertThat(spec.isUniqueIdIncluded(), is(true));
         assertThat(spec.isUserAuthenticationValidWhileOnBody(), is(true));
         assertThat(spec.isInvalidatedByBiometricEnrollment(), is(true));
+        assertThat(spec.isStrongBoxBacked(), is(true));
+        assertThat(spec.isUserConfirmationRequired(), is(true));
+        assertThat(spec.isUnlockedDeviceRequired(), is(true));
     }
 
     private Parcel parcelForReading(ParcelableKeyGenParameterSpec spec) {
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index e39926b..bba36bc 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -136,6 +136,7 @@
         "tests/ByteBucketArray_test.cpp",
         "tests/Config_test.cpp",
         "tests/ConfigLocale_test.cpp",
+        "tests/DynamicRefTable_test.cpp",
         "tests/Idmap_test.cpp",
         "tests/LoadedArsc_test.cpp",
         "tests/ResourceUtils_test.cpp",
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index fc625bb..843c146 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -74,6 +74,7 @@
 const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
 const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
 const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
+const char* AssetManager::PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
 const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
 const char* AssetManager::TARGET_PACKAGE_NAME = "android";
 const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
diff --git a/libs/androidfw/ChunkIterator.cpp b/libs/androidfw/ChunkIterator.cpp
index d8adbe5..8fc3219 100644
--- a/libs/androidfw/ChunkIterator.cpp
+++ b/libs/androidfw/ChunkIterator.cpp
@@ -32,11 +32,30 @@
 
   if (len_ != 0) {
     // Prepare the next chunk.
-    VerifyNextChunk();
+    if (VerifyNextChunkNonFatal()) {
+      VerifyNextChunk();
+    }
   }
   return Chunk(this_chunk);
 }
 
+// TODO(b/111401637) remove this and have full resource file verification
+// Returns false if there was an error.
+bool ChunkIterator::VerifyNextChunkNonFatal() {
+  if (len_ < sizeof(ResChunk_header)) {
+    last_error_ = "not enough space for header";
+    last_error_was_fatal_ = false;
+    return false;
+  }
+  const size_t size = dtohl(next_chunk_->size);
+  if (size > len_) {
+    last_error_ = "chunk size is bigger than given data";
+    last_error_was_fatal_ = false;
+    return false;
+  }
+  return true;
+}
+
 // Returns false if there was an error.
 bool ChunkIterator::VerifyNextChunk() {
   const uintptr_t header_start = reinterpret_cast<uintptr_t>(next_chunk_);
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 04d506a..c2740c9 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -560,7 +560,9 @@
 
   if (iter.HadError()) {
     LOG(ERROR) << iter.GetLastError();
-    return {};
+    if (iter.HadFatalError()) {
+      return {};
+    }
   }
 
   // Flatten and construct the TypeSpecs.
@@ -641,7 +643,9 @@
 
   if (iter.HadError()) {
     LOG(ERROR) << iter.GetLastError();
-    return false;
+    if (iter.HadFatalError()) {
+      return false;
+    }
   }
   return true;
 }
@@ -673,7 +677,9 @@
 
   if (iter.HadError()) {
     LOG(ERROR) << iter.GetLastError();
-    return {};
+    if (iter.HadFatalError()) {
+      return {};
+    }
   }
 
   // Need to force a move for mingw32.
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 861dc0f..402e390 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -6960,6 +6960,11 @@
     uint32_t res = *resId;
     size_t packageId = Res_GETPACKAGE(res) + 1;
 
+    if (!Res_VALIDID(res)) {
+        // Cannot look up a null or invalid id, so no lookup needs to be done.
+        return NO_ERROR;
+    }
+
     if (packageId == APP_PACKAGE_ID && !mAppAsLib) {
         // No lookup needs to be done, app package IDs are absolute.
         return NO_ERROR;
@@ -6993,25 +6998,17 @@
 }
 
 status_t DynamicRefTable::lookupResourceValue(Res_value* value) const {
-    uint8_t resolvedType = Res_value::TYPE_REFERENCE;
-    switch (value->dataType) {
-    case Res_value::TYPE_ATTRIBUTE:
-        resolvedType = Res_value::TYPE_ATTRIBUTE;
-        // fallthrough
-    case Res_value::TYPE_REFERENCE:
-        if (!mAppAsLib) {
-            return NO_ERROR;
-        }
+    uint8_t resolvedType;
 
-        // If the package is loaded as shared library, the resource reference
-        // also need to be fixed.
-        break;
-    case Res_value::TYPE_DYNAMIC_ATTRIBUTE:
+    if (value->dataType == Res_value::TYPE_ATTRIBUTE
+        || value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE) {
         resolvedType = Res_value::TYPE_ATTRIBUTE;
-        // fallthrough
-    case Res_value::TYPE_DYNAMIC_REFERENCE:
-        break;
-    default:
+
+    } else if (value->dataType == Res_value::TYPE_REFERENCE
+               || value->dataType == Res_value::TYPE_DYNAMIC_REFERENCE) {
+        resolvedType = Res_value::TYPE_REFERENCE;
+
+    } else {
         return NO_ERROR;
     }
 
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index 08da731..cdb87bc 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -61,6 +61,7 @@
     static const char* IDMAP_BIN;
     static const char* OVERLAY_DIR;
     static const char* PRODUCT_OVERLAY_DIR;
+    static const char* PRODUCT_SERVICES_OVERLAY_DIR;
     /*
      * If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
      * APKs in OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to
diff --git a/libs/androidfw/include/androidfw/Chunk.h b/libs/androidfw/include/androidfw/Chunk.h
index 89b588e..99a52dc 100644
--- a/libs/androidfw/include/androidfw/Chunk.h
+++ b/libs/androidfw/include/androidfw/Chunk.h
@@ -94,18 +94,27 @@
 
   Chunk Next();
   inline bool HasNext() const { return !HadError() && len_ != 0; };
+  // Returns whether there was an error and processing should stop
   inline bool HadError() const { return last_error_ != nullptr; }
   inline std::string GetLastError() const { return last_error_; }
+  // Returns whether there was an error and processing should stop. For legacy purposes,
+  // some errors are considered "non fatal". Fatal errors stop processing new chunks and
+  // throw away any chunks already processed. Non fatal errors also stop processing new
+  // chunks, but, will retain and use any valid chunks already processed.
+  inline bool HadFatalError() const { return HadError() && last_error_was_fatal_; }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ChunkIterator);
 
   // Returns false if there was an error.
   bool VerifyNextChunk();
+  // Returns false if there was an error. For legacy purposes.
+  bool VerifyNextChunkNonFatal();
 
   const ResChunk_header* next_chunk_;
   size_t len_;
   const char* last_error_;
+  bool last_error_was_fatal_ = true;
 };
 
 }  // namespace android
diff --git a/libs/androidfw/tests/DynamicRefTable_test.cpp b/libs/androidfw/tests/DynamicRefTable_test.cpp
new file mode 100644
index 0000000..df44e34
--- /dev/null
+++ b/libs/androidfw/tests/DynamicRefTable_test.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "androidfw/ResourceTypes.h"
+#include "utils/String8.h"
+
+#include "gtest/gtest.h"
+namespace android {
+
+TEST(DynamicRefTableTest, LookupSharedLibSelfReferences) {
+  // Shared library
+  DynamicRefTable shared_table(0x02, /* appAsLib */ false);
+  shared_table.addMapping(0x00, 0x02);
+  Res_value value;
+  value.dataType = Res_value::TYPE_REFERENCE;
+  value.data = 0x00010000;
+  ASSERT_EQ(shared_table.lookupResourceValue(&value), NO_ERROR);
+  EXPECT_EQ(value.data, 0x02010000);
+
+  // App loaded as a shared library
+  DynamicRefTable shared_app_table(0x02, /* appAsLib */ true);
+  shared_app_table.addMapping(0x7f, 0x02);
+  Res_value value2;
+  value2.dataType = Res_value::TYPE_REFERENCE;
+  value2.data = 0x7f010000;
+  ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR);
+  EXPECT_EQ(value2.data, 0x02010000);
+};
+
+TEST(DynamicRefTableTest, LookupDynamicReferences) {
+  // Shared library
+  DynamicRefTable shared_table(0x2, /* appAsLib */ false);
+  shared_table.addMapping(0x00, 0x02);
+  shared_table.addMapping(0x03, 0x05);
+  Res_value value;
+  value.dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
+  value.data = 0x03010000;
+  ASSERT_EQ(shared_table.lookupResourceValue(&value), NO_ERROR);
+  EXPECT_EQ(value.data, 0x05010000);
+
+  // App loaded as a shared library
+  DynamicRefTable shared_app_table(0x2, /* appAsLib */ true);
+  shared_app_table.addMapping(0x03, 0x05);
+  shared_app_table.addMapping(0x7f, 0x2);
+  Res_value value2;
+  value2.dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
+  value2.data = 0x03010000;
+  ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR);
+  EXPECT_EQ(value2.data, 0x05010000);
+
+  // Regular application
+  DynamicRefTable app_table(0x7f, /* appAsLib */ false);
+  app_table.addMapping(0x03, 0x05);
+  Res_value value3;
+  value3.dataType = Res_value::TYPE_REFERENCE;
+  value3.data = 0x03010000;
+  ASSERT_EQ(app_table.lookupResourceValue(&value3), NO_ERROR);
+  EXPECT_EQ(value3.data, 0x05010000);
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 0db7799..83e90b6 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -48,6 +48,11 @@
         device_uses_hwc2: {
             cflags: ["-DUSE_HWC2"],
         },
+        eng: {
+            lto: {
+                never: true,
+            },
+        },
     },
 }
 
@@ -67,7 +72,6 @@
         "libft2",
         "libminikin",
         "libandroidfw",
-        "libRScpp",
     ],
     static_libs: [
         "libEGL_blobCache",
@@ -198,6 +202,7 @@
         "AnimatorManager.cpp",
         "Caches.cpp",
         "CanvasState.cpp",
+        "CanvasTransform.cpp",
         "ClipArea.cpp",
         "DamageAccumulator.cpp",
         "DeferredLayerUpdater.cpp",
@@ -224,7 +229,6 @@
         "RenderProperties.cpp",
         "ResourceCache.cpp",
         "SkiaCanvas.cpp",
-        "SkiaCanvasProxy.cpp",
         "Snapshot.cpp",
         "Texture.cpp",
         "VectorDrawable.cpp",
@@ -237,7 +241,6 @@
     },
 
     export_include_dirs: ["."],
-    export_shared_lib_headers: ["libRScpp"],
 }
 
 cc_library {
diff --git a/libs/hwui/CanvasTransform.cpp b/libs/hwui/CanvasTransform.cpp
new file mode 100644
index 0000000..1b15dbd
--- /dev/null
+++ b/libs/hwui/CanvasTransform.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CanvasTransform.h"
+#include "utils/Color.h"
+#include "Properties.h"
+
+#include <ui/ColorSpace.h>
+#include <SkColorFilter.h>
+#include <SkPaint.h>
+
+#include <algorithm>
+#include <cmath>
+
+namespace android::uirenderer {
+
+static SkColor makeLight(SkColor color) {
+    Lab lab = sRGBToLab(color);
+    float invertedL = std::min(110 - lab.L, 100.0f);
+    if (invertedL > lab.L) {
+        lab.L = invertedL;
+        return LabToSRGB(lab, SkColorGetA(color));
+    } else {
+        return color;
+    }
+}
+
+static SkColor makeDark(SkColor color) {
+    Lab lab = sRGBToLab(color);
+    float invertedL = std::min(110 - lab.L, 100.0f);
+    if (invertedL < lab.L) {
+        lab.L = invertedL;
+        return LabToSRGB(lab, SkColorGetA(color));
+    } else {
+        return color;
+    }
+}
+
+static SkColor transformColor(ColorTransform transform, SkColor color) {
+    switch (transform) {
+        case ColorTransform::Light:
+            return makeLight(color);
+        case ColorTransform::Dark:
+            return makeDark(color);
+        default:
+            return color;
+    }
+}
+
+static void applyColorTransform(ColorTransform transform, SkPaint& paint) {
+    if (transform == ColorTransform::None) return;
+
+    SkColor newColor = transformColor(transform, paint.getColor());
+    paint.setColor(newColor);
+
+    if (paint.getColorFilter()) {
+        SkBlendMode mode;
+        SkColor color;
+        // TODO: LRU this or something to avoid spamming new color mode filters
+        if (paint.getColorFilter()->asColorMode(&color, &mode)) {
+            color = transformColor(transform, color);
+            paint.setColorFilter(SkColorFilter::MakeModeFilter(color, mode));
+        }
+    }
+}
+
+class ColorFilterCanvas : public SkPaintFilterCanvas {
+public:
+    ColorFilterCanvas(ColorTransform transform, SkCanvas* canvas)
+            : SkPaintFilterCanvas(canvas), mTransform(transform) {}
+
+    bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const override {
+        if (*paint) {
+            applyColorTransform(mTransform, *(paint->writable()));
+        }
+        return true;
+    }
+
+private:
+    ColorTransform mTransform;
+};
+
+std::unique_ptr<SkCanvas> makeTransformCanvas(SkCanvas* inCanvas, ColorTransform transform) {
+    switch (transform) {
+        case ColorTransform::Light:
+            return std::make_unique<ColorFilterCanvas>(ColorTransform::Light, inCanvas);
+        case ColorTransform::Dark:
+            return std::make_unique<ColorFilterCanvas>(ColorTransform::Dark, inCanvas);
+        default:
+            return nullptr;
+    }
+}
+
+std::unique_ptr<SkCanvas> makeTransformCanvas(SkCanvas* inCanvas, UsageHint usageHint) {
+    if (Properties::forceDarkMode) {
+        switch (usageHint) {
+            case UsageHint::Unknown:
+                return makeTransformCanvas(inCanvas, ColorTransform::Light);
+            case UsageHint::Background:
+                return makeTransformCanvas(inCanvas, ColorTransform::Dark);
+        }
+    }
+    return nullptr;
+}
+
+};  // namespace android::uirenderer
\ No newline at end of file
diff --git a/libs/hwui/CanvasTransform.h b/libs/hwui/CanvasTransform.h
new file mode 100644
index 0000000..f71fdfa
--- /dev/null
+++ b/libs/hwui/CanvasTransform.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <SkCanvas.h>
+#include <SkPaintFilterCanvas.h>
+
+#include <memory>
+
+namespace android::uirenderer {
+
+enum class UsageHint {
+    Unknown = 0,
+    Background = 1,
+};
+
+enum class ColorTransform {
+    None,
+    Light,
+    Dark,
+};
+
+std::unique_ptr<SkCanvas> makeTransformCanvas(SkCanvas* inCanvas, ColorTransform transform);
+std::unique_ptr<SkCanvas> makeTransformCanvas(SkCanvas* inCanvas, UsageHint usageHint);
+
+}  // namespace android::uirenderer;
\ No newline at end of file
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index 6408ce6..ab80d3d 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -286,7 +286,7 @@
         eglDestroySyncKHR(display, fence);
     }
 
-    return sk_sp<Bitmap>(new Bitmap(buffer.get(), bitmap.info()));
+    return sk_sp<Bitmap>(new Bitmap(buffer.get(), bitmap.info(), Bitmap::computePalette(bitmap)));
 }
 
 };  // namespace android::uirenderer
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index d284269..17bec19 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -17,6 +17,7 @@
 #include "Properties.h"
 #include "Debug.h"
 #include "DeviceInfo.h"
+#include "SkTraceEventCommon.h"
 
 #include <algorithm>
 #include <cstdlib>
@@ -59,6 +60,7 @@
 bool Properties::filterOutTestOverhead = false;
 bool Properties::disableVsync = false;
 bool Properties::skpCaptureEnabled = false;
+bool Properties::forceDarkMode = false;
 bool Properties::enableRTAnimations = true;
 
 bool Properties::runningInEmulator = false;
@@ -140,8 +142,13 @@
 
     skpCaptureEnabled = debuggingEnabled && property_get_bool(PROPERTY_CAPTURE_SKP_ENABLED, false);
 
+    SkAndroidFrameworkTraceUtil::setEnableTracing(
+            property_get_bool(PROPERTY_SKIA_ATRACE_ENABLED, false));
+
     runningInEmulator = property_get_bool(PROPERTY_QEMU_KERNEL, false);
 
+    forceDarkMode = property_get_bool(PROPERTY_FORCE_DARK, false);
+
     return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw) ||
            (prevDebugStencilClip != debugStencilClip);
 }
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 657f9aa..ea017a7 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -171,6 +171,11 @@
 #define PROPERTY_CAPTURE_SKP_ENABLED "debug.hwui.capture_skp_enabled"
 
 /**
+ * Allows to record Skia drawing commands with systrace.
+ */
+#define PROPERTY_SKIA_ATRACE_ENABLED "debug.hwui.skia_atrace_enabled"
+
+/**
  * Defines how many frames in a sequence to capture.
  */
 #define PROPERTY_CAPTURE_SKP_FRAMES "debug.hwui.capture_skp_frames"
@@ -185,6 +190,8 @@
  */
 #define PROPERTY_QEMU_KERNEL "ro.kernel.qemu"
 
+#define PROPERTY_FORCE_DARK "debug.hwui.force_dark"
+
 ///////////////////////////////////////////////////////////////////////////////
 // Misc
 ///////////////////////////////////////////////////////////////////////////////
@@ -258,6 +265,7 @@
     static bool disableVsync;
 
     static bool skpCaptureEnabled;
+    static bool forceDarkMode;
 
     // For experimentation b/68769804
     ANDROID_API static bool enableRTAnimations;
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index dc962f3..8393288 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -28,6 +28,7 @@
 #include <androidfw/ResourceTypes.h>
 
 #include "AnimatorManager.h"
+#include "CanvasTransform.h"
 #include "Debug.h"
 #include "DisplayList.h"
 #include "Matrix.h"
@@ -208,6 +209,14 @@
 
     void output(std::ostream& output, uint32_t level);
 
+    void setUsageHint(UsageHint usageHint) {
+        mUsageHint = usageHint;
+    }
+
+    UsageHint usageHint() const {
+        return mUsageHint;
+    }
+
 private:
     void computeOrderingImpl(RenderNodeOp* opState,
                              std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
@@ -263,6 +272,8 @@
 
     sp<PositionListener> mPositionListener;
 
+    UsageHint mUsageHint = UsageHint::Unknown;
+
     // METHODS & FIELDS ONLY USED BY THE SKIA RENDERER
 public:
     /**
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index e495744..ff9cf45 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -44,8 +44,8 @@
 }
 
 bool LayerProperties::setColorFilter(SkColorFilter* filter) {
-    if (mColorFilter == filter) return false;
-    SkRefCnt_SafeAssign(mColorFilter, filter);
+    if (mColorFilter.get() == filter) return false;
+    mColorFilter = sk_ref_sp(filter);
     return true;
 }
 
@@ -62,7 +62,7 @@
     setOpaque(other.opaque());
     setAlpha(other.alpha());
     setXferMode(other.xferMode());
-    setColorFilter(other.colorFilter());
+    setColorFilter(other.getColorFilter());
     return *this;
 }
 
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index c024373..0766e3b 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -89,9 +89,7 @@
 
     SkBlendMode xferMode() const { return mMode; }
 
-    bool setColorFilter(SkColorFilter* filter);
-
-    SkColorFilter* colorFilter() const { return mColorFilter; }
+    SkColorFilter* getColorFilter() const { return mColorFilter.get(); }
 
     // Sets alpha, xfermode, and colorfilter from an SkPaint
     // paint may be NULL, in which case defaults will be set
@@ -105,6 +103,7 @@
     LayerProperties();
     ~LayerProperties();
     void reset();
+    bool setColorFilter(SkColorFilter* filter);
 
     // Private since external users should go through properties().effectiveLayerType()
     LayerType type() const { return mType; }
@@ -116,7 +115,7 @@
     bool mOpaque;
     uint8_t mAlpha;
     SkBlendMode mMode;
-    SkColorFilter* mColorFilter = nullptr;
+    sk_sp<SkColorFilter> mColorFilter;
 };
 
 /*
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 7b41f89..17f1a3b 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -21,6 +21,7 @@
 #include "VectorDrawable.h"
 #include "hwui/Bitmap.h"
 #include "hwui/MinikinUtils.h"
+#include "hwui/PaintFilter.h"
 #include "pipeline/skia/AnimatedDrawables.h"
 
 #include <SkAnimatedImage.h>
@@ -28,7 +29,6 @@
 #include <SkColorFilter.h>
 #include <SkColorSpaceXformCanvas.h>
 #include <SkDeque.h>
-#include <SkDrawFilter.h>
 #include <SkDrawable.h>
 #include <SkGraphics.h>
 #include <SkImage.h>
@@ -40,6 +40,8 @@
 #include <SkTextBlob.h>
 
 #include <memory>
+#include <optional>
+#include <utility>
 
 namespace android {
 
@@ -211,7 +213,7 @@
     Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m)
             : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
     Clip(const SkPath& path, SkClipOp op, const SkMatrix& m)
-            : mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {}
+            : mType(Type::Path), mOp(op), mMatrix(m), mPath(std::in_place, path) {}
 
     void apply(SkCanvas* canvas) const {
         canvas->setMatrix(mMatrix);
@@ -223,7 +225,7 @@
                 canvas->clipRRect(mRRect, mOp);
                 break;
             case Type::Path:
-                canvas->clipPath(*mPath.get(), mOp);
+                canvas->clipPath(mPath.value(), mOp);
                 break;
         }
     }
@@ -240,7 +242,7 @@
     SkMatrix mMatrix;
 
     // These are logically a union (tracked separately due to non-POD path).
-    SkTLazy<SkPath> mPath;
+    std::optional<SkPath> mPath;
     SkRRect mRRect;
 };
 
@@ -400,12 +402,12 @@
 // Canvas state operations: Filters
 // ----------------------------------------------------------------------------
 
-SkDrawFilter* SkiaCanvas::getDrawFilter() {
-    return mCanvas->getDrawFilter();
+PaintFilter* SkiaCanvas::getPaintFilter() {
+    return mPaintFilter.get();
 }
 
-void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) {
-    mCanvas->setDrawFilter(drawFilter);
+void SkiaCanvas::setPaintFilter(sk_sp<PaintFilter> paintFilter) {
+    mPaintFilter = std::move(paintFilter);
 }
 
 // ----------------------------------------------------------------------------
@@ -439,8 +441,15 @@
     mCanvas->drawColor(color, mode);
 }
 
+SkiaCanvas::PaintCoW&& SkiaCanvas::filterPaint(PaintCoW&& paint) const {
+    if (mPaintFilter) {
+        mPaintFilter->filter(&paint.writeable());
+    }
+    return std::move(paint);
+}
+
 void SkiaCanvas::drawPaint(const SkPaint& paint) {
-    mCanvas->drawPaint(paint);
+    mCanvas->drawPaint(*filterPaint(paint));
 }
 
 // ----------------------------------------------------------------------------
@@ -457,53 +466,53 @@
         pts[i].set(points[0], points[1]);
         points += 2;
     }
-    mCanvas->drawPoints(mode, count, pts.get(), paint);
+    mCanvas->drawPoints(mode, count, pts.get(), *filterPaint(paint));
 }
 
 void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) {
-    mCanvas->drawPoint(x, y, paint);
+    mCanvas->drawPoint(x, y, *filterPaint(paint));
 }
 
 void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
-    this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode);
+    this->drawPoints(points, count, *filterPaint(paint), SkCanvas::kPoints_PointMode);
 }
 
 void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
                           const SkPaint& paint) {
-    mCanvas->drawLine(startX, startY, stopX, stopY, paint);
+    mCanvas->drawLine(startX, startY, stopX, stopY, *filterPaint(paint));
 }
 
 void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
     if (CC_UNLIKELY(count < 4 || paint.nothingToDraw())) return;
-    this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
+    this->drawPoints(points, count, *filterPaint(paint), SkCanvas::kLines_PointMode);
 }
 
 void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
-    mCanvas->drawRect({left, top, right, bottom}, paint);
+    mCanvas->drawRect({left, top, right, bottom}, *filterPaint(paint));
 }
 
 void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
-    mCanvas->drawRegion(region, paint);
+    mCanvas->drawRegion(region, *filterPaint(paint));
 }
 
 void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
                                const SkPaint& paint) {
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
-    mCanvas->drawRoundRect(rect, rx, ry, paint);
+    mCanvas->drawRoundRect(rect, rx, ry, *filterPaint(paint));
 }
 
 void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
     if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return;
-    mCanvas->drawCircle(x, y, radius, paint);
+    mCanvas->drawCircle(x, y, radius, *filterPaint(paint));
 }
 
 void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
-    mCanvas->drawOval(oval, paint);
+    mCanvas->drawOval(oval, *filterPaint(paint));
 }
 
 void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle,
@@ -511,9 +520,9 @@
     if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
     if (fabs(sweepAngle) >= 360.0f) {
-        mCanvas->drawOval(arc, paint);
+        mCanvas->drawOval(arc, *filterPaint(paint));
     } else {
-        mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
+        mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, *filterPaint(paint));
     }
 }
 
@@ -522,19 +531,19 @@
     if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) {
         return;
     }
-    mCanvas->drawPath(path, paint);
+    mCanvas->drawPath(path, *filterPaint(paint));
 }
 
 void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
-    mCanvas->drawVertices(vertices, mode, paint);
+    mCanvas->drawVertices(vertices, mode, *filterPaint(paint));
 }
 
 // ----------------------------------------------------------------------------
 // Canvas draw operations: Bitmaps
 // ----------------------------------------------------------------------------
 
-const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
-                                     sk_sp<SkColorFilter> colorSpaceFilter) {
+SkiaCanvas::PaintCoW&& SkiaCanvas::filterBitmap(PaintCoW&& paint,
+                                                sk_sp<SkColorFilter> colorSpaceFilter) const {
     /* We don't apply the colorSpace filter if this canvas is already wrapped with
      * a SkColorSpaceXformCanvas since it already takes care of converting the
      * contents of the bitmap into the appropriate colorspace.  The mCanvasWrapper
@@ -542,39 +551,31 @@
      * to have a non-sRGB colorspace.
      */
     if (!mCanvasWrapper && colorSpaceFilter) {
-        if (origPaint) {
-            *tmpPaint = *origPaint;
-        }
-
-        if (tmpPaint->getColorFilter()) {
-            tmpPaint->setColorFilter(
-                    SkColorFilter::MakeComposeFilter(tmpPaint->refColorFilter(), colorSpaceFilter));
-            LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
+        SkPaint& tmpPaint = paint.writeable();
+        if (tmpPaint.getColorFilter()) {
+            tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(tmpPaint.refColorFilter(),
+                                                                     std::move(colorSpaceFilter)));
+            LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter());
         } else {
-            tmpPaint->setColorFilter(colorSpaceFilter);
+            tmpPaint.setColorFilter(std::move(colorSpaceFilter));
         }
-
-        return tmpPaint;
-    } else {
-        return origPaint;
     }
+    return filterPaint(std::move(paint));
 }
 
 void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
-    SkPaint tmpPaint;
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
-    mCanvas->drawImage(image, left, top, addFilter(paint, &tmpPaint, colorFilter));
+    mCanvas->drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter)));
 }
 
 void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
     SkAutoCanvasRestore acr(mCanvas, true);
     mCanvas->concat(matrix);
 
-    SkPaint tmpPaint;
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
-    mCanvas->drawImage(image, 0, 0, addFilter(paint, &tmpPaint, colorFilter));
+    mCanvas->drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter)));
 }
 
 void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
@@ -583,10 +584,9 @@
     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
 
-    SkPaint tmpPaint;
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
-    mCanvas->drawImageRect(image, srcRect, dstRect, addFilter(paint, &tmpPaint, colorFilter),
+    mCanvas->drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)),
                            SkCanvas::kFast_SrcRectConstraint);
 }
 
@@ -665,21 +665,20 @@
 #endif
 
     // cons-up a shader for the bitmap
-    SkPaint tmpPaint;
-    if (paint) {
-        tmpPaint = *paint;
-    }
+    PaintCoW paintCoW(paint);
+    SkPaint& tmpPaint = paintCoW.writeable();
 
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
     sk_sp<SkShader> shader =
             image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
     if (colorFilter) {
-        shader = shader->makeWithColorFilter(colorFilter);
+        shader = shader->makeWithColorFilter(std::move(colorFilter));
     }
-    tmpPaint.setShader(shader);
+    tmpPaint.setShader(std::move(shader));
 
-    mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, tmpPaint);
+    mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate,
+                          *filterPaint(std::move(paintCoW)));
 }
 
 void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft,
@@ -706,10 +705,10 @@
     lattice.fBounds = nullptr;
     SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
 
-    SkPaint tmpPaint;
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
-    mCanvas->drawImageLattice(image.get(), lattice, dst, addFilter(paint, &tmpPaint, colorFilter));
+    mCanvas->drawImageLattice(image.get(), lattice, dst,
+                              filterBitmap(paint, std::move(colorFilter)));
 }
 
 double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) {
@@ -732,6 +731,9 @@
     // glyphs centered or right-aligned; the offset above takes
     // care of all alignment.
     SkPaint paintCopy(paint);
+    if (mPaintFilter) {
+        mPaintFilter->filter(&paintCopy);
+    }
     paintCopy.setTextAlign(SkPaint::kLeft_Align);
     SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
     // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and
@@ -760,6 +762,9 @@
     // glyphs centered or right-aligned; the offsets take care of
     // that portion of the alignment.
     SkPaint paintCopy(paint);
+    if (mPaintFilter) {
+        mPaintFilter->filter(&paintCopy);
+    }
     paintCopy.setTextAlign(SkPaint::kLeft_Align);
     SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
 
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 3efc22a..24b7ec6 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -22,7 +22,9 @@
 #include "hwui/Canvas.h"
 
 #include <SkCanvas.h>
-#include <SkTLazy.h>
+
+#include <cassert>
+#include <optional>
 
 namespace android {
 
@@ -87,8 +89,8 @@
     virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override;
     virtual bool clipPath(const SkPath* path, SkClipOp op) override;
 
-    virtual SkDrawFilter* getDrawFilter() override;
-    virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
+    virtual PaintFilter* getPaintFilter() override;
+    virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) override;
 
     virtual SkCanvasState* captureCanvasState() const override;
 
@@ -158,6 +160,46 @@
                                   const SkPaint& 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; }
+        const SkPaint& operator*() const { assert(mPtr); return *mPtr; }
+        explicit operator bool() { return mPtr != nullptr; }
+    private:
+        const SkPaint* mPtr;
+        std::optional<SkPaint> mStorage;
+    };
+
+    /** 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;
+
 private:
     struct SaveRec {
         int saveCount;
@@ -174,8 +216,15 @@
 
     void drawPoints(const float* points, int count, const SkPaint& paint, SkCanvas::PointMode mode);
 
-    const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
-                             sk_sp<SkColorFilter> colorSpaceFilter);
+    /** Filters the paint for bitmap drawing.
+     *
+     *  After filtering the paint for bitmap drawing,
+     *  also calls filterPaint on the paint.
+     *
+     *  @param paint the paint to filter. Will be initialized with the default
+     *      SkPaint before filtering if filtering is required.
+     */
+    PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter) const;
 
     class Clip;
 
@@ -185,6 +234,7 @@
                                                // unless it is the same as mCanvasOwned.get()
     std::unique_ptr<SkDeque> mSaveStack;       // lazily allocated, tracks partial saves.
     std::vector<Clip> mClipStack;              // tracks persistent clips.
+    sk_sp<PaintFilter> mPaintFilter;
 };
 
 }  // namespace android
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
deleted file mode 100644
index fc009d8..0000000
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ /dev/null
@@ -1,486 +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.
- */
-
-#include "SkiaCanvasProxy.h"
-
-#include <memory>
-
-#include <log/log.h>
-
-#include <SkLatticeIter.h>
-#include <SkPaint.h>
-#include <SkPatchUtils.h>
-#include <SkPath.h>
-#include <SkPixelRef.h>
-#include <SkRRect.h>
-#include <SkRSXform.h>
-#include <SkRect.h>
-#include <SkSurface.h>
-#include <SkTextBlobRunIterator.h>
-#include <SkVertices.h>
-#include "hwui/Bitmap.h"
-
-namespace android {
-namespace uirenderer {
-
-SkiaCanvasProxy::SkiaCanvasProxy(Canvas* canvas, bool filterHwuiCalls)
-        : INHERITED(canvas->width(), canvas->height())
-        , mCanvas(canvas)
-        , mFilterHwuiCalls(filterHwuiCalls) {}
-
-void SkiaCanvasProxy::onDrawPaint(const SkPaint& paint) {
-    mCanvas->drawPaint(paint);
-}
-
-void SkiaCanvasProxy::onDrawPoints(PointMode pointMode, size_t count, const SkPoint pts[],
-                                   const SkPaint& paint) {
-    if (!pts || count == 0) {
-        return;
-    }
-
-    // convert the SkPoints into floats
-    static_assert(sizeof(SkPoint) == sizeof(float) * 2, "SkPoint is no longer two floats");
-    const size_t floatCount = count << 1;
-    const float* floatArray = &pts[0].fX;
-
-    switch (pointMode) {
-        case kPoints_PointMode: {
-            mCanvas->drawPoints(floatArray, floatCount, paint);
-            break;
-        }
-        case kLines_PointMode: {
-            mCanvas->drawLines(floatArray, floatCount, paint);
-            break;
-        }
-        case kPolygon_PointMode: {
-            SkPaint strokedPaint(paint);
-            strokedPaint.setStyle(SkPaint::kStroke_Style);
-
-            SkPath path;
-            for (size_t i = 0; i < count - 1; i++) {
-                path.moveTo(pts[i]);
-                path.lineTo(pts[i + 1]);
-                this->drawPath(path, strokedPaint);
-                path.rewind();
-            }
-            break;
-        }
-        default:
-            LOG_ALWAYS_FATAL("Unknown point type");
-    }
-}
-
-void SkiaCanvasProxy::onDrawOval(const SkRect& rect, const SkPaint& paint) {
-    mCanvas->drawOval(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, paint);
-}
-
-void SkiaCanvasProxy::onDrawRect(const SkRect& rect, const SkPaint& paint) {
-    mCanvas->drawRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, paint);
-}
-
-void SkiaCanvasProxy::onDrawRRect(const SkRRect& roundRect, const SkPaint& paint) {
-    if (!roundRect.isComplex()) {
-        const SkRect& rect = roundRect.rect();
-        SkVector radii = roundRect.getSimpleRadii();
-        mCanvas->drawRoundRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, radii.fX, radii.fY,
-                               paint);
-    } else {
-        SkPath path;
-        path.addRRect(roundRect);
-        mCanvas->drawPath(path, paint);
-    }
-}
-
-void SkiaCanvasProxy::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
-                                bool useCenter, const SkPaint& paint) {
-    mCanvas->drawArc(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, startAngle, sweepAngle,
-                     useCenter, paint);
-}
-
-void SkiaCanvasProxy::onDrawPath(const SkPath& path, const SkPaint& paint) {
-    mCanvas->drawPath(path, paint);
-}
-
-void SkiaCanvasProxy::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
-                                   const SkPaint* paint) {
-    sk_sp<Bitmap> hwuiBitmap = Bitmap::createFrom(bitmap.info(), *bitmap.pixelRef());
-    // HWUI doesn't support extractSubset(), so convert any subsetted bitmap into
-    // a drawBitmapRect(); pass through an un-subsetted bitmap.
-    if (hwuiBitmap && bitmap.dimensions() != hwuiBitmap->info().dimensions()) {
-        SkIPoint origin = bitmap.pixelRefOrigin();
-        mCanvas->drawBitmap(
-                *hwuiBitmap, origin.fX, origin.fY, origin.fX + bitmap.dimensions().width(),
-                origin.fY + bitmap.dimensions().height(), left, top,
-                left + bitmap.dimensions().width(), top + bitmap.dimensions().height(), paint);
-    } else {
-        mCanvas->drawBitmap(*hwuiBitmap, left, top, paint);
-    }
-}
-
-void SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& skBitmap, const SkRect* srcPtr,
-                                       const SkRect& dst, const SkPaint* paint, SrcRectConstraint) {
-    SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(skBitmap.width(), skBitmap.height());
-    // TODO: if bitmap is a subset, do we need to add pixelRefOrigin to src?
-    Bitmap* bitmap = reinterpret_cast<Bitmap*>(skBitmap.pixelRef());
-    mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft, dst.fTop,
-                        dst.fRight, dst.fBottom, paint);
-}
-
-void SkiaCanvasProxy::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
-                                       const SkRect& dst, const SkPaint*) {
-    // TODO make nine-patch drawing a method on Canvas.h
-    SkDEBUGFAIL("SkiaCanvasProxy::onDrawBitmapNine is not yet supported");
-}
-
-void SkiaCanvasProxy::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
-                                  const SkPaint* paint) {
-    SkBitmap skiaBitmap;
-    SkPixmap pixmap;
-    if (image->peekPixels(&pixmap) && skiaBitmap.installPixels(pixmap)) {
-        onDrawBitmap(skiaBitmap, left, top, paint);
-    }
-}
-
-void SkiaCanvasProxy::onDrawImageRect(const SkImage* image, const SkRect* srcPtr, const SkRect& dst,
-                                      const SkPaint* paint, SrcRectConstraint constraint) {
-    SkBitmap skiaBitmap;
-    SkPixmap pixmap;
-    if (image->peekPixels(&pixmap) && skiaBitmap.installPixels(pixmap)) {
-        sk_sp<Bitmap> bitmap = Bitmap::createFrom(skiaBitmap.info(), *skiaBitmap.pixelRef());
-        SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(image->width(), image->height());
-        mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, dst.fLeft,
-                            dst.fTop, dst.fRight, dst.fBottom, paint);
-    }
-}
-
-void SkiaCanvasProxy::onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
-                                      const SkPaint*) {
-    SkDEBUGFAIL("SkiaCanvasProxy::onDrawImageNine is not yet supported");
-}
-
-void SkiaCanvasProxy::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
-                                         const SkRect& dst, const SkPaint* paint) {
-    SkLatticeIter iter(lattice, dst);
-    SkRect srcR, dstR;
-    while (iter.next(&srcR, &dstR)) {
-        onDrawImageRect(image, &srcR, dstR, paint, SkCanvas::kFast_SrcRectConstraint);
-    }
-}
-
-void SkiaCanvasProxy::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
-                                           const SkPaint& paint) {
-    if (mFilterHwuiCalls) {
-        return;
-    }
-    mCanvas->drawVertices(vertices, bmode, paint);
-}
-
-sk_sp<SkSurface> SkiaCanvasProxy::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
-    SkDEBUGFAIL("SkiaCanvasProxy::onNewSurface is not supported");
-    return NULL;
-}
-
-void SkiaCanvasProxy::willSave() {
-    mCanvas->save(android::SaveFlags::MatrixClip);
-}
-
-static inline SaveFlags::Flags saveFlags(SkCanvas::SaveLayerFlags layerFlags) {
-    SaveFlags::Flags saveFlags = 0;
-
-    if (!(layerFlags & SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag)) {
-        saveFlags |= SaveFlags::ClipToLayer;
-    }
-
-    return saveFlags;
-}
-
-SkCanvas::SaveLayerStrategy SkiaCanvasProxy::getSaveLayerStrategy(
-        const SaveLayerRec& saveLayerRec) {
-    SkRect rect;
-    if (saveLayerRec.fBounds) {
-        rect = *saveLayerRec.fBounds;
-    } else if (!mCanvas->getClipBounds(&rect)) {
-        rect = SkRect::MakeEmpty();
-    }
-    mCanvas->saveLayer(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, saveLayerRec.fPaint,
-                       saveFlags(saveLayerRec.fSaveLayerFlags));
-    return SkCanvas::kNoLayer_SaveLayerStrategy;
-}
-
-void SkiaCanvasProxy::willRestore() {
-    mCanvas->restore();
-}
-
-void SkiaCanvasProxy::didConcat(const SkMatrix& matrix) {
-    mCanvas->concat(matrix);
-}
-
-void SkiaCanvasProxy::didSetMatrix(const SkMatrix& matrix) {
-    mCanvas->setMatrix(matrix);
-}
-
-void SkiaCanvasProxy::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
-                                   const SkPaint& paint) {
-    SkPath path;
-    path.addRRect(outer);
-    path.addRRect(inner);
-    path.setFillType(SkPath::kEvenOdd_FillType);
-    this->drawPath(path, paint);
-}
-
-/**
- * Utility class that converts the incoming text & paint from the given encoding
- * into glyphIDs.
- */
-class GlyphIDConverter {
-public:
-    GlyphIDConverter(const void* text, size_t byteLength, const SkPaint& origPaint) {
-        paint = origPaint;
-        if (paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding) {
-            glyphIDs = (uint16_t*)text;
-            count = byteLength >> 1;
-        } else {
-            // ensure space for one glyph per ID given UTF8 encoding.
-            storage.reset(new uint16_t[byteLength]);
-            glyphIDs = storage.get();
-            count = paint.textToGlyphs(text, byteLength, storage.get());
-            paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-        }
-    }
-
-    SkPaint paint;
-    uint16_t* glyphIDs;
-    int count;
-
-private:
-    std::unique_ptr<uint16_t[]> storage;
-};
-
-void SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
-                                 const SkPaint& origPaint) {
-    // convert to glyphIDs if necessary
-    GlyphIDConverter glyphs(text, byteLength, origPaint);
-
-    // compute the glyph positions
-    std::unique_ptr<SkScalar[]> glyphWidths(new SkScalar[glyphs.count]);
-    glyphs.paint.getTextWidths(glyphs.glyphIDs, glyphs.count << 1, glyphWidths.get());
-
-    // compute conservative bounds
-    // NOTE: We could call the faster paint.getFontBounds for a less accurate,
-    //       but even more conservative bounds if this  is too slow.
-    SkRect bounds;
-    glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds);
-
-    // adjust for non-left alignment
-    if (glyphs.paint.getTextAlign() != SkPaint::kLeft_Align) {
-        SkScalar stop = 0;
-        for (int i = 0; i < glyphs.count; i++) {
-            stop += glyphWidths[i];
-        }
-        if (glyphs.paint.getTextAlign() == SkPaint::kCenter_Align) {
-            stop = SkScalarHalf(stop);
-        }
-        if (glyphs.paint.isVerticalText()) {
-            y -= stop;
-        } else {
-            x -= stop;
-        }
-    }
-
-    // setup the first glyph position and adjust bounds if needed
-    int xBaseline = 0;
-    int yBaseline = 0;
-    if (mCanvas->drawTextAbsolutePos()) {
-        bounds.offset(x, y);
-        xBaseline = x;
-        yBaseline = y;
-    }
-
-    static_assert(sizeof(SkPoint) == sizeof(float) * 2, "SkPoint is no longer two floats");
-    auto glyphFunc = [&](uint16_t* text, float* positions) {
-        memcpy(text, glyphs.glyphIDs, glyphs.count * sizeof(uint16_t));
-        size_t posIndex = 0;
-        // setup the first glyph position
-        positions[posIndex++] = xBaseline;
-        positions[posIndex++] = yBaseline;
-        // setup the remaining glyph positions
-        if (glyphs.paint.isVerticalText()) {
-            float yPosition = yBaseline;
-            for (int i = 1; i < glyphs.count; i++) {
-                positions[posIndex++] = xBaseline;
-                yPosition += glyphWidths[i - 1];
-                positions[posIndex++] = yPosition;
-            }
-        } else {
-            float xPosition = xBaseline;
-            for (int i = 1; i < glyphs.count; i++) {
-                xPosition += glyphWidths[i - 1];
-                positions[posIndex++] = xPosition;
-                positions[posIndex++] = yBaseline;
-            }
-        }
-    };
-    mCanvas->drawGlyphs(glyphFunc, glyphs.count, glyphs.paint, x, y, bounds.fLeft, bounds.fTop,
-                        bounds.fRight, bounds.fBottom, 0);
-}
-
-void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
-                                    const SkPaint& origPaint) {
-    // convert to glyphIDs if necessary
-    GlyphIDConverter glyphs(text, byteLength, origPaint);
-
-    // convert to relative positions if necessary
-    int x, y;
-    if (mCanvas->drawTextAbsolutePos()) {
-        x = 0;
-        y = 0;
-    } else {
-        x = pos[0].fX;
-        y = pos[0].fY;
-    }
-
-    // Compute conservative bounds.  If the content has already been processed
-    // by Minikin then it had already computed these bounds.  Unfortunately,
-    // there is no way to capture those bounds as part of the Skia drawPosText
-    // API so we need to do that computation again here.
-    SkRect bounds = SkRect::MakeEmpty();
-    for (int i = 0; i < glyphs.count; i++) {
-        SkRect glyphBounds = SkRect::MakeEmpty();
-        glyphs.paint.measureText(&glyphs.glyphIDs[i], sizeof(uint16_t), &glyphBounds);
-        glyphBounds.offset(pos[i].fX, pos[i].fY);
-        bounds.join(glyphBounds);
-    }
-
-    static_assert(sizeof(SkPoint) == sizeof(float) * 2, "SkPoint is no longer two floats");
-    auto glyphFunc = [&](uint16_t* text, float* positions) {
-        memcpy(text, glyphs.glyphIDs, glyphs.count * sizeof(uint16_t));
-        if (mCanvas->drawTextAbsolutePos()) {
-            memcpy(positions, pos, 2 * glyphs.count * sizeof(float));
-        } else {
-            for (int i = 0, posIndex = 0; i < glyphs.count; i++) {
-                positions[posIndex++] = pos[i].fX - x;
-                positions[posIndex++] = pos[i].fY - y;
-            }
-        }
-    };
-    mCanvas->drawGlyphs(glyphFunc, glyphs.count, glyphs.paint, x, y, bounds.fLeft, bounds.fTop,
-                        bounds.fRight, bounds.fBottom, 0);
-}
-
-void SkiaCanvasProxy::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
-                                     SkScalar constY, const SkPaint& paint) {
-    const size_t pointCount = byteLength >> 1;
-    std::unique_ptr<SkPoint[]> pts(new SkPoint[pointCount]);
-    for (size_t i = 0; i < pointCount; i++) {
-        pts[i].set(xpos[i], constY);
-    }
-    this->onDrawPosText(text, byteLength, pts.get(), paint);
-}
-
-void SkiaCanvasProxy::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
-                                       const SkMatrix* matrix, const SkPaint& origPaint) {
-    SkDEBUGFAIL("SkiaCanvasProxy::onDrawTextOnPath is not supported");
-}
-
-void SkiaCanvasProxy::onDrawTextRSXform(const void* text, size_t byteLength,
-                                        const SkRSXform xform[], const SkRect* cullRect,
-                                        const SkPaint& paint) {
-    GlyphIDConverter glyphs(text, byteLength, paint);  // Just get count
-    SkMatrix localM, currM, origM;
-    mCanvas->getMatrix(&currM);
-    origM = currM;
-    for (int i = 0; i < glyphs.count; i++) {
-        localM.setRSXform(*xform++);
-        currM.setConcat(origM, localM);
-        mCanvas->setMatrix(currM);
-        this->onDrawText((char*)text + (byteLength / glyphs.count * i), byteLength / glyphs.count,
-                         0, 0, paint);
-    }
-    mCanvas->setMatrix(origM);
-}
-
-void SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
-                                     const SkPaint& paint) {
-    SkPaint runPaint = paint;
-
-    SkTextBlobRunIterator it(blob);
-    for (; !it.done(); it.next()) {
-        size_t textLen = it.glyphCount() * sizeof(uint16_t);
-        const SkPoint& offset = it.offset();
-        // applyFontToPaint() always overwrites the exact same attributes,
-        // so it is safe to not re-seed the paint for this reason.
-        it.applyFontToPaint(&runPaint);
-
-        switch (it.positioning()) {
-            case SkTextBlob::kDefault_Positioning:
-                this->drawText(it.glyphs(), textLen, x + offset.x(), y + offset.y(), runPaint);
-                break;
-            case SkTextBlob::kHorizontal_Positioning: {
-                std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
-                for (size_t i = 0; i < it.glyphCount(); i++) {
-                    pts[i].set(x + offset.x() + it.pos()[i], y + offset.y());
-                }
-                this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
-                break;
-            }
-            case SkTextBlob::kFull_Positioning: {
-                std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
-                for (size_t i = 0; i < it.glyphCount(); i++) {
-                    const size_t xIndex = i * 2;
-                    const size_t yIndex = xIndex + 1;
-                    pts[i].set(x + offset.x() + it.pos()[xIndex],
-                               y + offset.y() + it.pos()[yIndex]);
-                }
-                this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
-                break;
-            }
-            default:
-                SK_ABORT("unhandled positioning mode");
-        }
-    }
-}
-
-void SkiaCanvasProxy::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                                  const SkPoint texCoords[4], SkBlendMode bmode,
-                                  const SkPaint& paint) {
-    if (mFilterHwuiCalls) {
-        return;
-    }
-    SkMatrix matrix;
-    mCanvas->getMatrix(&matrix);
-    SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &matrix);
-
-    mCanvas->drawVertices(
-            SkPatchUtils::MakeVertices(cubics, colors, texCoords, lod.width(), lod.height()).get(),
-            bmode, paint);
-}
-
-void SkiaCanvasProxy::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle) {
-    mCanvas->clipRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, op);
-}
-
-void SkiaCanvasProxy::onClipRRect(const SkRRect& roundRect, SkClipOp op, ClipEdgeStyle) {
-    SkPath path;
-    path.addRRect(roundRect);
-    mCanvas->clipPath(&path, op);
-}
-
-void SkiaCanvasProxy::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle) {
-    mCanvas->clipPath(&path, op);
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
deleted file mode 100644
index 360d5a0..0000000
--- a/libs/hwui/SkiaCanvasProxy.h
+++ /dev/null
@@ -1,112 +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.
- */
-
-#ifndef SkiaCanvasProxy_DEFINED
-#define SkiaCanvasProxy_DEFINED
-
-#include <SkCanvas.h>
-#include <cutils/compiler.h>
-
-#include "hwui/Canvas.h"
-
-namespace android {
-namespace uirenderer {
-
-/**
- * This class serves as a proxy between Skia's SkCanvas and Android Framework's
- * Canvas.  The class does not maintain any draw-related state and will pass
- * through most requests directly to the Canvas provided in the constructor.
- *
- * Upon construction it is expected that the provided Canvas has already been
- * prepared for recording and will continue to be in the recording state while
- * this proxy class is being used.
- *
- * If filterHwuiCalls is true, the proxy silently ignores away draw calls that
- * aren't supported by HWUI.
- */
-class ANDROID_API SkiaCanvasProxy : public SkCanvas {
-public:
-    explicit SkiaCanvasProxy(Canvas* canvas, bool filterHwuiCalls = false);
-    virtual ~SkiaCanvasProxy() {}
-
-protected:
-    virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;
-
-    virtual void willSave() override;
-    virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
-    virtual void willRestore() override;
-
-    virtual void didConcat(const SkMatrix&) override;
-    virtual void didSetMatrix(const SkMatrix&) override;
-
-    virtual void onDrawPaint(const SkPaint& paint) override;
-    virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[],
-                              const SkPaint&) override;
-    virtual void onDrawOval(const SkRect&, const SkPaint&) override;
-    virtual void onDrawRect(const SkRect&, const SkPaint&) override;
-    virtual void onDrawRRect(const SkRRect&, const SkPaint&) override;
-    virtual void onDrawPath(const SkPath& path, const SkPaint&) override;
-    virtual void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
-                           const SkPaint&) override;
-    virtual void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
-                              const SkPaint*) override;
-    virtual void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst,
-                                  const SkPaint* paint, SrcRectConstraint) override;
-    virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
-                                  const SkPaint*) override;
-    virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
-    virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
-                                 SrcRectConstraint);
-    virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
-                                 const SkPaint*);
-    virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
-                                    const SkPaint*);
-    virtual void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
-
-    virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
-
-    virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
-                            const SkPaint&) override;
-    virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
-                               const SkPaint&) override;
-    virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
-                                SkScalar constY, const SkPaint&) override;
-    virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
-                                  const SkMatrix* matrix, const SkPaint&) override;
-    virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
-                                   const SkRect* cullRect, const SkPaint& paint);
-    virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
-                                const SkPaint& paint) override;
-
-    virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                             const SkPoint texCoords[4], SkBlendMode,
-                             const SkPaint& paint) override;
-
-    virtual void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
-    virtual void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
-    virtual void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
-
-private:
-    Canvas* mCanvas;
-    bool mFilterHwuiCalls;
-
-    typedef SkCanvas INHERITED;
-};
-
-};  // namespace uirenderer
-};  // namespace android
-
-#endif  // SkiaCanvasProxy_DEFINED
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index b37f2cf..f2766d6 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -39,7 +39,7 @@
     virtual void onError(const std::string& message) = 0;
 
 protected:
-    ~ErrorHandler() {}
+    virtual ~ErrorHandler() {}
 };
 
 class TreeObserver {
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 402fbad..9f82d0f 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -474,14 +474,13 @@
 // Update the given paint with alpha and color filter. Return nullptr if no color filter is
 // specified and root alpha is 1. Otherwise, return updated paint.
 SkPaint* Tree::updatePaint(SkPaint* outPaint, TreeProperties* prop) {
-    if (prop->getRootAlpha() == 1.0f && prop->getColorFilter() == nullptr) {
-        return nullptr;
-    } else {
+    // HWUI always draws VD with bilinear filtering.
+    outPaint->setFilterQuality(kLow_SkFilterQuality);
+    if (prop->getRootAlpha() < 1.0f || prop->getColorFilter() != nullptr) {
         outPaint->setColorFilter(sk_ref_sp(prop->getColorFilter()));
-        outPaint->setFilterQuality(kLow_SkFilterQuality);
         outPaint->setAlpha(prop->getRootAlpha() * 255);
-        return outPaint;
     }
+    return outPaint;
 }
 
 Bitmap& Tree::getBitmapUpdateIfDirty() {
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index e84b9ac..af0ae05 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -59,12 +59,6 @@
         onPropertyChanged();                                          \
         retVal;                                                       \
     })
-#define UPDATE_SKPROP(field, value)                                    \
-    ({                                                                 \
-        bool retVal = ((field) != (value));                            \
-        if ((field) != (value)) SkRefCnt_SafeAssign((field), (value)); \
-        retVal;                                                        \
-    })
 
 /* A VectorDrawable is composed of a tree of nodes.
  * Each node can be a group node, or a path.
@@ -223,29 +217,28 @@
             int fillType = 0; /* non-zero or kWinding_FillType in Skia */
         };
         explicit FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
-        ~FullPathProperties() {
-            SkSafeUnref(fillGradient);
-            SkSafeUnref(strokeGradient);
-        }
+        ~FullPathProperties() {}
         void syncProperties(const FullPathProperties& prop) {
             mPrimitiveFields = prop.mPrimitiveFields;
             mTrimDirty = true;
-            UPDATE_SKPROP(fillGradient, prop.fillGradient);
-            UPDATE_SKPROP(strokeGradient, prop.strokeGradient);
+            fillGradient = prop.fillGradient;
+            strokeGradient = prop.strokeGradient;
             onPropertyChanged();
         }
         void setFillGradient(SkShader* gradient) {
-            if (UPDATE_SKPROP(fillGradient, gradient)) {
+            if (fillGradient.get() != gradient) {
+                fillGradient = sk_ref_sp(gradient);
                 onPropertyChanged();
             }
         }
         void setStrokeGradient(SkShader* gradient) {
-            if (UPDATE_SKPROP(strokeGradient, gradient)) {
+            if (strokeGradient.get() != gradient) {
+                strokeGradient = sk_ref_sp(gradient);
                 onPropertyChanged();
             }
         }
-        SkShader* getFillGradient() const { return fillGradient; }
-        SkShader* getStrokeGradient() const { return strokeGradient; }
+        SkShader* getFillGradient() const { return fillGradient.get(); }
+        SkShader* getStrokeGradient() const { return strokeGradient.get(); }
         float getStrokeWidth() const { return mPrimitiveFields.strokeWidth; }
         void setStrokeWidth(float strokeWidth) {
             VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeWidth, strokeWidth);
@@ -325,8 +318,8 @@
             count,
         };
         PrimitiveFields mPrimitiveFields;
-        SkShader* fillGradient = nullptr;
-        SkShader* strokeGradient = nullptr;
+        sk_sp<SkShader> fillGradient;
+        sk_sp<SkShader> strokeGradient;
     };
 
     // Called from UI thread
@@ -550,8 +543,7 @@
             SkRect bounds;
             int scaledWidth = 0;
             int scaledHeight = 0;
-            SkColorFilter* colorFilter = nullptr;
-            ~NonAnimatableProperties() { SkSafeUnref(colorFilter); }
+            sk_sp<SkColorFilter> colorFilter;
         } mNonAnimatableProperties;
         bool mNonAnimatablePropertiesDirty = true;
 
@@ -561,8 +553,7 @@
         void syncNonAnimatableProperties(const TreeProperties& prop) {
             // Copy over the data that can only be changed in UI thread
             if (mNonAnimatableProperties.colorFilter != prop.mNonAnimatableProperties.colorFilter) {
-                SkRefCnt_SafeAssign(mNonAnimatableProperties.colorFilter,
-                                    prop.mNonAnimatableProperties.colorFilter);
+                mNonAnimatableProperties.colorFilter = prop.mNonAnimatableProperties.colorFilter;
             }
             mNonAnimatableProperties = prop.mNonAnimatableProperties;
         }
@@ -599,12 +590,13 @@
             }
         }
         void setColorFilter(SkColorFilter* filter) {
-            if (UPDATE_SKPROP(mNonAnimatableProperties.colorFilter, filter)) {
+            if (mNonAnimatableProperties.colorFilter.get() != filter) {
+                mNonAnimatableProperties.colorFilter = sk_ref_sp(filter);
                 mNonAnimatablePropertiesDirty = true;
                 mTree->onPropertyChanged(this);
             }
         }
-        SkColorFilter* getColorFilter() const { return mNonAnimatableProperties.colorFilter; }
+        SkColorFilter* getColorFilter() const { return mNonAnimatableProperties.colorFilter.get(); }
 
         float getViewportWidth() const { return mNonAnimatableProperties.viewportWidth; }
         float getViewportHeight() const { return mNonAnimatableProperties.viewportHeight; }
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 007961a..8d4e7e0 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -21,7 +21,8 @@
 
 #include <SkPicture.h>
 #include <SkRefCnt.h>
-#include <SkTLazy.h>
+
+#include <optional>
 
 namespace android {
 
@@ -126,13 +127,13 @@
 
 // Only called on the RenderThread.
 void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
-    SkTLazy<SkPaint> lazyPaint;
+    std::optional<SkPaint> lazyPaint;
     SkAutoCanvasRestore acr(canvas, false);
     if (mProperties.mAlpha != SK_AlphaOPAQUE || mProperties.mColorFilter.get()) {
-        lazyPaint.init();
-        lazyPaint.get()->setAlpha(mProperties.mAlpha);
-        lazyPaint.get()->setColorFilter(mProperties.mColorFilter);
-        lazyPaint.get()->setFilterQuality(kLow_SkFilterQuality);
+        lazyPaint.emplace();
+        lazyPaint->setAlpha(mProperties.mAlpha);
+        lazyPaint->setColorFilter(mProperties.mColorFilter);
+        lazyPaint->setFilterQuality(kLow_SkFilterQuality);
     }
     if (mProperties.mMirrored) {
         canvas->save();
@@ -147,8 +148,8 @@
     if (drawDirectly) {
         // The image is not animating, and never was. Draw directly from
         // mSkAnimatedImage.
-        if (lazyPaint.isValid()) {
-            canvas->saveLayer(mSkAnimatedImage->getBounds(), lazyPaint.get());
+        if (lazyPaint) {
+            canvas->saveLayer(mSkAnimatedImage->getBounds(), &*lazyPaint);
         }
 
         std::unique_lock lock{mImageLock};
@@ -193,7 +194,7 @@
     if (!drawDirectly) {
         // No other thread will modify mCurrentSnap so this should be safe to
         // use without locking.
-        canvas->drawPicture(mSnapshot.mPic, nullptr, lazyPaint.getMaybeNull());
+        canvas->drawPicture(mSnapshot.mPic, nullptr, lazyPaint ? &*lazyPaint : nullptr);
     }
 
     if (finalFrame) {
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index a401b3f..7a8d026 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -17,6 +17,7 @@
 
 #include "Caches.h"
 #include "HardwareBitmapUploader.h"
+#include "Properties.h"
 #include "renderthread/RenderProxy.h"
 #include "utils/Color.h"
 
@@ -34,6 +35,7 @@
 #include <SkToSRGBColorFilter.h>
 
 #include <limits>
+#include <SkHighContrastFilter.h>
 
 namespace android {
 
@@ -195,11 +197,13 @@
     mPixelStorage.ashmem.size = mappedSize;
 }
 
-Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info)
+Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette palette)
         : SkPixelRef(info.width(), info.height(), nullptr,
                      bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride())
         , mInfo(validateAlpha(info))
-        , mPixelStorageType(PixelStorageType::Hardware) {
+        , mPixelStorageType(PixelStorageType::Hardware)
+        , mPalette(palette)
+        , mPaletteGenerationId(getGenerationID()) {
     mPixelStorage.hardware.buffer = buffer;
     buffer->incStrong(buffer);
     setImmutable();  // HW bitmaps are always immutable
@@ -326,7 +330,106 @@
     if (image->colorSpace() != nullptr && !image->colorSpace()->isSRGB()) {
         *outputColorFilter = SkToSRGBColorFilter::Make(image->refColorSpace());
     }
+
+    // TODO: Move this to the canvas (or other?) layer where we have the target lightness
+    // mode and can selectively do the right thing.
+    if (palette() != BitmapPalette::Unknown && uirenderer::Properties::forceDarkMode) {
+        SkHighContrastConfig config;
+        config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertLightness;
+        *outputColorFilter = SkHighContrastFilter::Make(config)->makeComposed(*outputColorFilter);
+    }
     return image;
 }
 
+class MinMaxAverage {
+public:
+
+    void add(float sample) {
+        if (mCount == 0) {
+            mMin = sample;
+            mMax = sample;
+        } else {
+            mMin = std::min(mMin, sample);
+            mMax = std::max(mMax, sample);
+        }
+        mTotal += sample;
+        mCount++;
+    }
+
+    float average() {
+        return mTotal / mCount;
+    }
+
+    float min() {
+        return mMin;
+    }
+
+    float max() {
+        return mMax;
+    }
+
+    float delta() {
+        return mMax - mMin;
+    }
+
+private:
+    float mMin = 0.0f;
+    float mMax = 0.0f;
+    float mTotal = 0.0f;
+    int mCount = 0;
+};
+
+BitmapPalette Bitmap::computePalette(const SkImageInfo& info, const void* addr, size_t rowBytes) {
+    ATRACE_CALL();
+
+    SkPixmap pixmap{info, addr, rowBytes};
+
+    // TODO: This calculation of converting to HSV & tracking min/max is probably overkill
+    // Experiment with something simpler since we just want to figure out if it's "color-ful"
+    // and then the average perceptual lightness.
+
+    MinMaxAverage hue, saturation, value;
+    int sampledCount = 0;
+
+    // Sample a grid of 100 pixels to get an overall estimation of the colors in play
+    const int x_step = std::max(1, pixmap.width() / 10);
+    const int y_step = std::max(1, pixmap.height() / 10);
+    for (int x = 0; x < pixmap.width(); x += x_step) {
+        for (int y = 0; y < pixmap.height(); y += y_step) {
+            SkColor color = pixmap.getColor(x, y);
+            if (!info.isOpaque() && SkColorGetA(color) < 75) {
+                continue;
+            }
+
+            sampledCount++;
+            float hsv[3];
+            SkColorToHSV(color, hsv);
+            hue.add(hsv[0]);
+            saturation.add(hsv[1]);
+            value.add(hsv[2]);
+        }
+    }
+
+    // TODO: Tune the coverage threshold
+    if (sampledCount < 5) {
+        ALOGV("Not enough samples, only found %d for image sized %dx%d, format = %d, alpha = %d",
+              sampledCount, info.width(), info.height(), (int) info.colorType(), (int) info.alphaType());
+        return BitmapPalette::Unknown;
+    }
+
+    ALOGV("samples = %d, hue [min = %f, max = %f, avg = %f]; saturation [min = %f, max = %f, avg = %f]",
+          sampledCount,
+          hue.min(), hue.max(), hue.average(),
+          saturation.min(), saturation.max(), saturation.average());
+
+    if (hue.delta() <= 20 && saturation.delta() <= .1f) {
+        if (value.average() >= .5f) {
+            return BitmapPalette::Light;
+        } else {
+            return BitmapPalette::Dark;
+        }
+    }
+    return BitmapPalette::Unknown;
+}
+
 }  // namespace android
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index dbd4456..d268042 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -34,6 +34,12 @@
     Hardware,
 };
 
+enum class BitmapPalette {
+    Unknown,
+    Light,
+    Dark,
+};
+
 namespace uirenderer {
 namespace renderthread {
 class RenderThread;
@@ -63,7 +69,7 @@
     Bitmap(void* address, void* context, FreeFunc freeFunc, const SkImageInfo& info,
            size_t rowBytes);
     Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes);
-    Bitmap(GraphicBuffer* buffer, const SkImageInfo& info);
+    Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette palette = BitmapPalette::Unknown);
 
     int rowBytesAsPixels() const { return rowBytes() >> mInfo.shiftPerPixel(); }
 
@@ -103,6 +109,20 @@
      */
     sk_sp<SkImage> makeImage(sk_sp<SkColorFilter>* outputColorFilter);
 
+    static BitmapPalette computePalette(const SkImageInfo& info, const void* addr, size_t rowBytes);
+
+    static BitmapPalette computePalette(const SkBitmap& bitmap) {
+        return computePalette(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes());
+    }
+
+    BitmapPalette palette() {
+        if (!isHardware() && mPaletteGenerationId != getGenerationID()) {
+            mPalette = computePalette(info(), pixels(), rowBytes());
+            mPaletteGenerationId = getGenerationID();
+        }
+        return mPalette;
+    }
+
 private:
     virtual ~Bitmap();
     void* getStorage() const;
@@ -111,6 +131,9 @@
 
     const PixelStorageType mPixelStorageType;
 
+    BitmapPalette mPalette = BitmapPalette::Unknown;
+    uint32_t mPaletteGenerationId = -1;
+
     bool mHasHardwareMipMap = false;
 
     union {
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index fb6bd6f..af7f013 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -23,7 +23,7 @@
 #include "Typeface.h"
 #include "pipeline/skia/SkiaRecordingCanvas.h"
 
-#include <SkDrawFilter.h>
+#include "hwui/PaintFilter.h"
 
 namespace android {
 
@@ -40,10 +40,10 @@
 
 void Canvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
     uint32_t flags;
-    SkDrawFilter* drawFilter = getDrawFilter();
-    if (drawFilter) {
+    PaintFilter* paintFilter = getPaintFilter();
+    if (paintFilter) {
         SkPaint paintCopy(paint);
-        drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
+        paintFilter->filter(&paintCopy);
         flags = paintCopy.getFlags();
     } else {
         flags = paint.getFlags();
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 88b12b2..b9af7de2 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -39,6 +39,7 @@
 }
 
 namespace android {
+class PaintFilter;
 
 namespace uirenderer {
 class CanvasPropertyPaint;
@@ -73,7 +74,6 @@
 }  // namespace SaveFlags
 
 namespace uirenderer {
-class SkiaCanvasProxy;
 namespace VectorDrawable {
 class Tree;
 };
@@ -213,8 +213,8 @@
     virtual bool clipPath(const SkPath* path, SkClipOp op) = 0;
 
     // filters
-    virtual SkDrawFilter* getDrawFilter() = 0;
-    virtual void setDrawFilter(SkDrawFilter* drawFilter) = 0;
+    virtual PaintFilter* getPaintFilter() = 0;
+    virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) = 0;
 
     // WebView only
     virtual SkCanvasState* captureCanvasState() const { return nullptr; }
@@ -304,7 +304,6 @@
 
     friend class DrawTextFunctor;
     friend class DrawTextOnPathFunctor;
-    friend class uirenderer::SkiaCanvasProxy;
 };
 
 };  // namespace android
diff --git a/libs/hwui/hwui/PaintFilter.h b/libs/hwui/hwui/PaintFilter.h
new file mode 100644
index 0000000..bf5627e
--- /dev/null
+++ b/libs/hwui/hwui/PaintFilter.h
@@ -0,0 +1,19 @@
+#ifndef ANDROID_GRAPHICS_PAINT_FILTER_H_
+#define ANDROID_GRAPHICS_PAINT_FILTER_H_
+
+class SkPaint;
+
+namespace android {
+
+class PaintFilter : public SkRefCnt {
+public:
+    /**
+     *  Called with the paint that will be used to draw.
+     *  The implementation may modify the paint as they wish.
+     */
+    virtual void filter(SkPaint*) = 0;
+};
+
+} // namespace android
+
+#endif
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 14d31b2..c41f6a6 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -82,7 +82,14 @@
             textureMatrix = textureMatrixInv;
         }
 
-        SkMatrix matrix = SkMatrix::Concat(layerTransform, textureMatrix);
+        SkMatrix matrix;
+        if (dstRect) {
+            // Destination rectangle is set only when we are trying to read back the content
+            // of the layer. In this case we don't want to apply layer transform.
+            matrix = textureMatrix;
+        } else {
+            matrix = SkMatrix::Concat(layerTransform, textureMatrix);
+        }
 
         SkPaint paint;
         paint.setAlpha(layer->getAlpha());
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index c195a8e..ea14d11 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -21,6 +21,8 @@
 #include "SkiaPipeline.h"
 #include "utils/TraceUtils.h"
 
+#include <optional>
+
 namespace android {
 namespace uirenderer {
 namespace skiapipeline {
@@ -156,10 +158,10 @@
                             SkPaint* paint) {
     paint->setFilterQuality(kLow_SkFilterQuality);
     if (alphaMultiplier < 1.0f || properties.alpha() < 255 ||
-        properties.xferMode() != SkBlendMode::kSrcOver || properties.colorFilter() != nullptr) {
+        properties.xferMode() != SkBlendMode::kSrcOver || properties.getColorFilter() != nullptr) {
         paint->setAlpha(properties.alpha() * alphaMultiplier);
         paint->setBlendMode(properties.xferMode());
-        paint->setColorFilter(sk_ref_sp(properties.colorFilter()));
+        paint->setColorFilter(sk_ref_sp(properties.getColorFilter()));
         return true;
     }
     return false;
@@ -171,9 +173,9 @@
 
 protected:
     bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type t) const override {
-        SkTLazy<SkPaint> defaultPaint;
+        std::optional<SkPaint> defaultPaint;
         if (!*paint) {
-            paint->init(*defaultPaint.init());
+            paint->init(defaultPaint.emplace());
         }
         paint->writable()->setAlpha((uint8_t)(*paint)->getAlpha() * mAlpha);
         return true;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index f0da660..b9748af 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -17,6 +17,7 @@
 #include "SkiaRecordingCanvas.h"
 
 #include <SkImagePriv.h>
+#include "CanvasTransform.h"
 #include "Layer.h"
 #include "LayerDrawable.h"
 #include "NinePatchUtils.h"
@@ -44,13 +45,21 @@
     }
 
     mDisplayList->attachRecorder(&mRecorder, SkIRect::MakeWH(width, height));
-    SkiaCanvas::reset(&mRecorder);
+    SkCanvas* canvas = &mRecorder;
+    if (renderNode) {
+        mWrappedCanvas = makeTransformCanvas(&mRecorder, renderNode->usageHint());
+        if (mWrappedCanvas) {
+            canvas = mWrappedCanvas.get();
+        }
+    }
+    SkiaCanvas::reset(canvas);
 }
 
 uirenderer::DisplayList* SkiaRecordingCanvas::finishRecording() {
     // close any existing chunks if necessary
     insertReorderBarrier(false);
     mRecorder.restoreToCount(1);
+    mWrappedCanvas = nullptr;
     return mDisplayList.release();
 }
 
@@ -148,12 +157,45 @@
 // Recording Canvas draw operations: Bitmaps
 // ----------------------------------------------------------------------------
 
+SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint,
+                                                         sk_sp<SkColorFilter> colorSpaceFilter) {
+    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();
+    }
+
+    if (fixBlending || fixAA || colorSpaceFilter) {
+        SkPaint& tmpPaint = paint.writeable();
+
+        if (fixBlending) {
+            tmpPaint.setBlendMode(SkBlendMode::kDstOut);
+        }
+
+        if (colorSpaceFilter) {
+            if (tmpPaint.getColorFilter()) {
+                tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(
+                       tmpPaint.refColorFilter(), std::move(colorSpaceFilter)));
+            } else {
+                tmpPaint.setColorFilter(std::move(colorSpaceFilter));
+            }
+            LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter());
+        }
+
+        // disabling AA on bitmap draws matches legacy HWUI behavior
+        tmpPaint.setAntiAlias(false);
+    }
+
+    return filterPaint(std::move(paint));
+}
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
-    SkPaint tmpPaint;
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
-    mRecorder.drawImage(image, left, top, bitmapPaint(paint, &tmpPaint, colorFilter));
+    mRecorder.drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter)));
     // 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
     // when this function ends.
@@ -166,10 +208,9 @@
     SkAutoCanvasRestore acr(&mRecorder, true);
     concat(matrix);
 
-    SkPaint tmpPaint;
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
-    mRecorder.drawImage(image, 0, 0, bitmapPaint(paint, &tmpPaint, colorFilter));
+    mRecorder.drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter)));
     if (!bitmap.isImmutable() && image.get() && !image->unique()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
@@ -181,10 +222,9 @@
     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
 
-    SkPaint tmpPaint;
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
-    mRecorder.drawImageRect(image, srcRect, dstRect, bitmapPaint(paint, &tmpPaint, colorFilter),
+    mRecorder.drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)),
                             SkCanvas::kFast_SrcRectConstraint);
     if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
         !dstRect.isEmpty()) {
@@ -216,23 +256,15 @@
     lattice.fBounds = nullptr;
     SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
 
-    SkPaint tmpPaint;
+    PaintCoW filteredPaint(paint);
+    // HWUI always draws 9-patches with bilinear filtering, regardless of what is set in the Paint.
+    if (!filteredPaint || filteredPaint->getFilterQuality() != kLow_SkFilterQuality) {
+        filteredPaint.writeable().setFilterQuality(kLow_SkFilterQuality);
+    }
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
-    const SkPaint* filteredPaint = bitmapPaint(paint, &tmpPaint, colorFilter);
-    // Besides kNone, the other three SkFilterQualities are treated the same. And Android's
-    // Java API only supports kLow and kNone anyway.
-    if (!filteredPaint || filteredPaint->getFilterQuality() == kNone_SkFilterQuality) {
-        if (filteredPaint != &tmpPaint) {
-            if (paint) {
-                tmpPaint = *paint;
-            }
-            filteredPaint = &tmpPaint;
-        }
-        tmpPaint.setFilterQuality(kLow_SkFilterQuality);
-    }
-
-    mRecorder.drawImageLattice(image.get(), lattice, dst, filteredPaint);
+    mRecorder.drawImageLattice(image.get(), lattice, dst,
+                               filterBitmap(std::move(filteredPaint), std::move(colorFilter)));
     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 93807a5..50d84d6 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -78,6 +78,7 @@
 private:
     SkLiteRecorder mRecorder;
     std::unique_ptr<SkiaDisplayList> mDisplayList;
+    std::unique_ptr<SkCanvas> mWrappedCanvas;
     StartReorderBarrierDrawable* mCurrentBarrier;
 
     /**
@@ -89,44 +90,7 @@
      */
     void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height);
 
-    inline static const SkPaint* bitmapPaint(const SkPaint* origPaint, SkPaint* tmpPaint,
-                                             sk_sp<SkColorFilter> colorSpaceFilter) {
-        bool fixBlending = false;
-        bool fixAA = false;
-        if (origPaint) {
-            // kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and
-            // older.
-            fixBlending = sApiLevel <= 27 && origPaint->getBlendMode() == SkBlendMode::kClear;
-            fixAA = origPaint->isAntiAlias();
-        }
-
-        if (fixBlending || fixAA || colorSpaceFilter) {
-            if (origPaint) {
-                *tmpPaint = *origPaint;
-            }
-
-            if (fixBlending) {
-                tmpPaint->setBlendMode(SkBlendMode::kDstOut);
-            }
-
-            if (colorSpaceFilter) {
-                if (tmpPaint->getColorFilter()) {
-                    tmpPaint->setColorFilter(SkColorFilter::MakeComposeFilter(
-                            tmpPaint->refColorFilter(), colorSpaceFilter));
-                } else {
-                    tmpPaint->setColorFilter(colorSpaceFilter);
-                }
-                LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
-            }
-
-            // disabling AA on bitmap draws matches legacy HWUI behavior
-            tmpPaint->setAntiAlias(false);
-            return tmpPaint;
-        } else {
-            return origPaint;
-        }
-    }
-
+    PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter);
 };
 
 };  // namespace skiapipeline
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index b07fb2d..bec80b1e 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -134,6 +134,7 @@
     }
 
     contextOptions->fPersistentCache = &skiapipeline::ShaderCache::get();
+    contextOptions->fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
 }
 
 void CacheManager::trimMemory(TrimMemoryMode mode) {
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 6eca8d2..e3807e6 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -85,6 +85,11 @@
             [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
 }
 
+void RenderProxy::allocateBuffers(const sp<Surface>& surface) {
+    mRenderThread.queue().post(
+            [ surf = surface ]() mutable { surf->allocateBuffers(); });
+}
+
 void RenderProxy::updateSurface(const sp<Surface>& surface) {
     mRenderThread.queue().post(
             [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 5668484..c2964a4 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -70,6 +70,7 @@
     ANDROID_API void setName(const char* name);
 
     ANDROID_API void initialize(const sp<Surface>& surface);
+    ANDROID_API void allocateBuffers(const sp<Surface>& surface);
     ANDROID_API void updateSurface(const sp<Surface>& surface);
     ANDROID_API bool pauseSurface(const sp<Surface>& surface);
     ANDROID_API void setStopped(bool stopped);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 3eaf43b..c1284ec 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -189,6 +189,7 @@
     LOG_ALWAYS_FATAL_IF(!glInterface.get());
 
     GrContextOptions options;
+    options.fPreferExternalImagesOverES3 = true;
     options.fDisableDistanceFieldPaths = true;
     cacheManager().configureContext(&options);
     sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 4a1fd9e..62f704b 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -59,7 +59,7 @@
     virtual void doFrame() = 0;
 
 protected:
-    ~IFrameCallback() {}
+    virtual ~IFrameCallback() {}
 };
 
 struct VsyncSource {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 10edf73..1517f57 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -25,6 +25,8 @@
 #include <GrBackendSurface.h>
 #include <GrContext.h>
 #include <GrTypes.h>
+#include <GrTypes.h>
+#include <vk/GrVkExtensions.h>
 #include <vk/GrVkTypes.h>
 
 namespace android {
@@ -62,7 +64,7 @@
     mInstance = VK_NULL_HANDLE;
 }
 
-bool VulkanManager::setupDevice(VkPhysicalDeviceFeatures& deviceFeatures) {
+bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFeatures2& features) {
     VkResult err;
 
     constexpr VkApplicationInfo app_info = {
@@ -128,7 +130,7 @@
     GET_INST_PROC(DestroyInstance);
     GET_INST_PROC(EnumeratePhysicalDevices);
     GET_INST_PROC(GetPhysicalDeviceQueueFamilyProperties);
-    GET_INST_PROC(GetPhysicalDeviceFeatures);
+    GET_INST_PROC(GetPhysicalDeviceFeatures2);
     GET_INST_PROC(CreateDevice);
     GET_INST_PROC(EnumerateDeviceExtensionProperties);
     GET_INST_PROC(CreateAndroidSurfaceKHR);
@@ -217,11 +219,38 @@
         }
     }
 
-    // query to get the physical device properties
-    mGetPhysicalDeviceFeatures(mPhysicalDevice, &deviceFeatures);
+    auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
+        if (device != VK_NULL_HANDLE) {
+            return vkGetDeviceProcAddr(device, proc_name);
+        }
+        return vkGetInstanceProcAddr(instance, proc_name);
+    };
+    grExtensions.init(getProc, mInstance, mPhysicalDevice, instanceExtensions.size(),
+            instanceExtensions.data(), deviceExtensions.size(), deviceExtensions.data());
+
+    memset(&features, 0, sizeof(VkPhysicalDeviceFeatures2));
+    features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+    features.pNext = nullptr;
+
+    // Setup all extension feature structs we may want to use.
+    void** tailPNext = &features.pNext;
+
+    if (grExtensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
+        VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend;
+        blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*) malloc(
+                sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
+        LOG_ALWAYS_FATAL_IF(!blend);
+        blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
+        blend->pNext = nullptr;
+        *tailPNext = blend;
+        tailPNext = &blend->pNext;
+    }
+
+    // query to get the physical device features
+    mGetPhysicalDeviceFeatures2(mPhysicalDevice, &features);
     // this looks like it would slow things down,
     // and we can't depend on it on all platforms
-    deviceFeatures.robustBufferAccess = VK_FALSE;
+    features.features.robustBufferAccess = VK_FALSE;
 
     float queuePriorities[1] = { 0.0 };
 
@@ -247,7 +276,7 @@
 
     const VkDeviceCreateInfo deviceInfo = {
         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,    // sType
-        nullptr,                                 // pNext
+        &features,                               // pNext
         0,                                       // VkDeviceCreateFlags
         queueInfoCount,                          // queueCreateInfoCount
         queueInfo,                               // pQueueCreateInfos
@@ -255,7 +284,7 @@
         nullptr,                                 // ppEnabledLayerNames
         (uint32_t) deviceExtensions.size(),      // extensionCount
         deviceExtensions.data(),                 // ppEnabledExtensionNames
-        &deviceFeatures                          // ppEnabledFeatures
+        nullptr,                                 // ppEnabledFeatures
     };
 
     err = mCreateDevice(mPhysicalDevice, &deviceInfo, nullptr, &mDevice);
@@ -294,41 +323,45 @@
     return true;
 }
 
+static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& features) {
+    // All Vulkan structs that could be part of the features chain will start with the
+    // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
+    // so we can get access to the pNext for the next struct.
+    struct CommonVulkanHeader {
+        VkStructureType sType;
+        void*           pNext;
+    };
+
+    void* pNext = features.pNext;
+    while (pNext) {
+        void* current = pNext;
+        pNext = static_cast<CommonVulkanHeader*>(current)->pNext;
+        free(current);
+    }
+}
+
 void VulkanManager::initialize() {
     if (mDevice != VK_NULL_HANDLE) {
         return;
     }
 
-    std::vector<const char*> instanceExtensions;
-    std::vector<const char*> deviceExtensions;
-    VkPhysicalDeviceFeatures deviceFeatures;
-    LOG_ALWAYS_FATAL_IF(!this->setupDevice(deviceFeatures));
+    GET_PROC(EnumerateInstanceVersion);
+    uint32_t instanceVersion = 0;
+    LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
+    LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));
+
+    GrVkExtensions extensions;
+    VkPhysicalDeviceFeatures2 features;
+    LOG_ALWAYS_FATAL_IF(!this->setupDevice(extensions, features));
 
     mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
 
-    uint32_t extensionFlags = kKHR_surface_GrVkExtensionFlag |
-                              kKHR_android_surface_GrVkExtensionFlag |
-                              kKHR_swapchain_GrVkExtensionFlag;
-
-    uint32_t featureFlags = 0;
-    if (deviceFeatures.geometryShader) {
-        featureFlags |= kGeometryShader_GrVkFeatureFlag;
-    }
-    if (deviceFeatures.dualSrcBlend) {
-        featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
-    }
-    if (deviceFeatures.sampleRateShading) {
-        featureFlags |= kSampleRateShading_GrVkFeatureFlag;
-    }
-
     auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
         if (device != VK_NULL_HANDLE) {
             return vkGetDeviceProcAddr(device, proc_name);
         }
         return vkGetInstanceProcAddr(instance, proc_name);
     };
-    auto interface =
-        sk_make_sp<GrVkInterface>(getProc, mInstance, mDevice, extensionFlags);
 
     GrVkBackendContext backendContext;
     backendContext.fInstance = mInstance;
@@ -336,11 +369,10 @@
     backendContext.fDevice = mDevice;
     backendContext.fQueue = mGraphicsQueue;
     backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
-    backendContext.fMinAPIVersion = VK_MAKE_VERSION(1, 0, 0);
-    backendContext.fExtensions = extensionFlags;
-    backendContext.fFeatures = featureFlags;
-    backendContext.fInterface = std::move(interface);
-    backendContext.fOwnsInstanceAndDevice = false;
+    backendContext.fInstanceVersion = instanceVersion;
+    backendContext.fVkExtensions = &extensions;
+    backendContext.fDeviceFeatures2 = &features;
+    backendContext.fGetProc = std::move(getProc);
 
     // create the command pool for the command buffers
     if (VK_NULL_HANDLE == mCommandPool) {
@@ -363,6 +395,9 @@
     sk_sp<GrContext> grContext(GrContext::MakeVulkan(backendContext, options));
     LOG_ALWAYS_FATAL_IF(!grContext.get());
     mRenderThread.setGrContext(grContext);
+
+    free_features_extensions_structs(features);
+
     DeviceInfo::initialize(mRenderThread.getGrContext()->maxRenderTargetSize());
 
     if (Properties::enablePartialUpdates && Properties::useBufferAge) {
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 9a72706..5524c39 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -17,10 +17,15 @@
 #ifndef VULKANMANAGER_H
 #define VULKANMANAGER_H
 
+#if !defined(VK_USE_PLATFORM_ANDROID_KHR)
+#  define VK_USE_PLATFORM_ANDROID_KHR
+#endif
+#include <vulkan/vulkan.h>
+
 #include <SkSurface.h>
 #include <vk/GrVkBackendContext.h>
 
-#include <vulkan/vulkan.h>
+class GrVkExtensions;
 
 namespace android {
 namespace uirenderer {
@@ -113,7 +118,7 @@
 
     // Sets up the VkInstance and VkDevice objects. Also fills out the passed in
     // VkPhysicalDeviceFeatures struct.
-    bool setupDevice(VkPhysicalDeviceFeatures& deviceFeatures);
+    bool setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&);
 
     void destroyBuffers(VulkanSurface* surface);
 
@@ -153,13 +158,14 @@
     VkPtr<PFN_vkCreateSharedSwapchainsKHR> mCreateSharedSwapchainsKHR;
 
     // Instance Functions
+    VkPtr<PFN_vkEnumerateInstanceVersion> mEnumerateInstanceVersion;
     VkPtr<PFN_vkEnumerateInstanceExtensionProperties> mEnumerateInstanceExtensionProperties;
     VkPtr<PFN_vkCreateInstance> mCreateInstance;
 
     VkPtr<PFN_vkDestroyInstance> mDestroyInstance;
     VkPtr<PFN_vkEnumeratePhysicalDevices> mEnumeratePhysicalDevices;
     VkPtr<PFN_vkGetPhysicalDeviceQueueFamilyProperties> mGetPhysicalDeviceQueueFamilyProperties;
-    VkPtr<PFN_vkGetPhysicalDeviceFeatures> mGetPhysicalDeviceFeatures;
+    VkPtr<PFN_vkGetPhysicalDeviceFeatures2> mGetPhysicalDeviceFeatures2;
     VkPtr<PFN_vkCreateDevice> mCreateDevice;
     VkPtr<PFN_vkEnumerateDeviceExtensionProperties> mEnumerateDeviceExtensionProperties;
 
diff --git a/libs/hwui/tests/macrobench/main.cpp b/libs/hwui/tests/macrobench/main.cpp
index b74d359..e3c97ce 100644
--- a/libs/hwui/tests/macrobench/main.cpp
+++ b/libs/hwui/tests/macrobench/main.cpp
@@ -136,8 +136,6 @@
         gBenchmarkReporter.reset(new benchmark::ConsoleReporter());
     } else if (!strcmp(format, "json")) {
         gBenchmarkReporter.reset(new benchmark::JSONReporter());
-    } else if (!strcmp(format, "csv")) {
-        gBenchmarkReporter.reset(new benchmark::CSVReporter());
     } else {
         fprintf(stderr, "Unknown format '%s'", format);
         return false;
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 75740e8..a3e7859 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -16,8 +16,10 @@
 
 #include "Color.h"
 
-
 #include <utils/Log.h>
+#include <ui/ColorSpace.h>
+
+#include <algorithm>
 #include <cmath>
 
 namespace android {
@@ -107,5 +109,97 @@
     }
 }
 
+template<typename T>
+static constexpr T clamp(T x, T min, T max) {
+    return x < min ? min : x > max ? max : x;
+}
+
+//static const float2 ILLUMINANT_D50_XY = {0.34567f, 0.35850f};
+static const float3 ILLUMINANT_D50_XYZ = {0.964212f, 1.0f, 0.825188f};
+static const mat3 BRADFORD = mat3{
+        float3{ 0.8951f, -0.7502f,  0.0389f},
+        float3{ 0.2664f,  1.7135f, -0.0685f},
+        float3{-0.1614f,  0.0367f,  1.0296f}
+};
+
+static mat3 adaptation(const mat3& matrix, const float3& srcWhitePoint, const float3& dstWhitePoint) {
+    float3 srcLMS = matrix * srcWhitePoint;
+    float3 dstLMS = matrix * dstWhitePoint;
+    return inverse(matrix) * mat3{dstLMS / srcLMS} * matrix;
+}
+
+namespace LabColorSpace {
+
+static constexpr float A = 216.0f / 24389.0f;
+static constexpr float B = 841.0f / 108.0f;
+static constexpr float C = 4.0f / 29.0f;
+static constexpr float D = 6.0f / 29.0f;
+
+float3 toXyz(const Lab& lab) {
+    float3 v { lab.L, lab.a, lab.b };
+    v[0] = clamp(v[0], 0.0f, 100.0f);
+    v[1] = clamp(v[1], -128.0f, 128.0f);
+    v[2] = clamp(v[2], -128.0f, 128.0f);
+
+    float fy = (v[0] + 16.0f) / 116.0f;
+    float fx = fy + (v[1] * 0.002f);
+    float fz = fy - (v[2] * 0.005f);
+    float X = fx > D ? fx * fx * fx : (1.0f / B) * (fx - C);
+    float Y = fy > D ? fy * fy * fy : (1.0f / B) * (fy - C);
+    float Z = fz > D ? fz * fz * fz : (1.0f / B) * (fz - C);
+
+    v[0] = X * ILLUMINANT_D50_XYZ[0];
+    v[1] = Y * ILLUMINANT_D50_XYZ[1];
+    v[2] = Z * ILLUMINANT_D50_XYZ[2];
+
+    return v;
+}
+
+Lab fromXyz(const float3& v) {
+    float X = v[0] / ILLUMINANT_D50_XYZ[0];
+    float Y = v[1] / ILLUMINANT_D50_XYZ[1];
+    float Z = v[2] / ILLUMINANT_D50_XYZ[2];
+
+    float fx = X > A ? pow(X, 1.0f / 3.0f) : B * X + C;
+    float fy = Y > A ? pow(Y, 1.0f / 3.0f) : B * Y + C;
+    float fz = Z > A ? pow(Z, 1.0f / 3.0f) : B * Z + C;
+
+    float L = 116.0f * fy - 16.0f;
+    float a = 500.0f * (fx - fy);
+    float b = 200.0f * (fy - fz);
+
+    return Lab {
+            clamp(L, 0.0f, 100.0f),
+            clamp(a, -128.0f, 128.0f),
+            clamp(b, -128.0f, 128.0f)
+    };
+}
+
+};
+
+Lab sRGBToLab(SkColor color) {
+    auto colorSpace = ColorSpace::sRGB();
+    float3 rgb;
+    rgb.r = SkColorGetR(color) / 255.0f;
+    rgb.g = SkColorGetG(color) / 255.0f;
+    rgb.b = SkColorGetB(color) / 255.0f;
+    float3 xyz = colorSpace.rgbToXYZ(rgb);
+    float3 srcXYZ = ColorSpace::XYZ(float3{colorSpace.getWhitePoint(), 1});
+    xyz = adaptation(BRADFORD, srcXYZ, ILLUMINANT_D50_XYZ) * xyz;
+    return LabColorSpace::fromXyz(xyz);
+}
+
+SkColor LabToSRGB(const Lab& lab, SkAlpha alpha) {
+    auto colorSpace = ColorSpace::sRGB();
+    float3 xyz = LabColorSpace::toXyz(lab);
+    float3 dstXYZ = ColorSpace::XYZ(float3{colorSpace.getWhitePoint(), 1});
+    xyz = adaptation(BRADFORD, ILLUMINANT_D50_XYZ, dstXYZ) * xyz;
+    float3 rgb = colorSpace.xyzToRGB(xyz);
+    return SkColorSetARGB(alpha,
+            static_cast<uint8_t>(rgb.r * 255),
+            static_cast<uint8_t>(rgb.g * 255),
+            static_cast<uint8_t>(rgb.b * 255));
+}
+
 };  // namespace uirenderer
 };  // namespace android
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 2bec1f5..3c13a54 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -114,6 +114,16 @@
 bool transferFunctionCloseToSRGB(const SkColorSpace* colorSpace);
 
 sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace);
+
+struct Lab {
+    float L;
+    float a;
+    float b;
+};
+
+Lab sRGBToLab(SkColor color);
+SkColor LabToSRGB(const Lab& lab, SkAlpha alpha);
+
 } /* namespace uirenderer */
 } /* namespace android */
 
diff --git a/location/java/android/location/Country.java b/location/java/android/location/Country.java
index 7c1485d..6f82b78 100644
--- a/location/java/android/location/Country.java
+++ b/location/java/android/location/Country.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -78,6 +79,7 @@
      *        <li>{@link #COUNTRY_SOURCE_LOCALE}</li>
      *        </ul>
      */
+    @UnsupportedAppUsage
     public Country(final String countryIso, final int source) {
         if (countryIso == null || source < COUNTRY_SOURCE_NETWORK
                 || source > COUNTRY_SOURCE_LOCALE) {
@@ -107,6 +109,7 @@
     /**
      * @return the ISO 3166-1 two letters country code
      */
+    @UnsupportedAppUsage
     public final String getCountryIso() {
         return mCountryIso;
     }
@@ -121,6 +124,7 @@
      *         <li>{@link #COUNTRY_SOURCE_LOCALE}</li>
      *         </ul>
      */
+    @UnsupportedAppUsage
     public final int getSource() {
         return mSource;
     }
diff --git a/location/java/android/location/CountryDetector.java b/location/java/android/location/CountryDetector.java
index ec6dfb7..119d1e0 100644
--- a/location/java/android/location/CountryDetector.java
+++ b/location/java/android/location/CountryDetector.java
@@ -19,6 +19,7 @@
 import java.util.HashMap;
 
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
@@ -87,6 +88,7 @@
      *       create an instance of this class is using the factory
      *       Context.getSystemService.
      */
+    @UnsupportedAppUsage
     public CountryDetector(ICountryDetector service) {
         mService = service;
         mListeners = new HashMap<CountryListener, ListenerTransport>();
@@ -98,6 +100,7 @@
      * @return the country if it is available immediately, otherwise null will
      *         be returned.
      */
+    @UnsupportedAppUsage
     public Country detectCountry() {
         try {
             return mService.detectCountry();
@@ -116,6 +119,7 @@
      *        implement the callback mechanism. If looper is null then the
      *        callbacks will be called on the main thread.
      */
+    @UnsupportedAppUsage
     public void addCountryListener(CountryListener listener, Looper looper) {
         synchronized (mListeners) {
             if (!mListeners.containsKey(listener)) {
@@ -133,6 +137,7 @@
     /**
      * Remove the listener
      */
+    @UnsupportedAppUsage
     public void removeCountryListener(CountryListener listener) {
         synchronized (mListeners) {
             ListenerTransport transport = mListeners.get(listener);
diff --git a/location/java/android/location/CountryListener.java b/location/java/android/location/CountryListener.java
index e36db41..70a83c5 100644
--- a/location/java/android/location/CountryListener.java
+++ b/location/java/android/location/CountryListener.java
@@ -16,6 +16,8 @@
 
 package android.location;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * The listener for receiving the notification when the country is detected or
  * changed
@@ -26,5 +28,6 @@
     /**
      * @param country the changed or detected country.
      */
+    @UnsupportedAppUsage
     void onCountryDetected(Country country);
 }
diff --git a/location/java/android/location/GeocoderParams.java b/location/java/android/location/GeocoderParams.java
index 174fe3e..d90e4b5 100644
--- a/location/java/android/location/GeocoderParams.java
+++ b/location/java/android/location/GeocoderParams.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -53,6 +54,7 @@
     /**
      * returns the Geocoder's locale
      */
+    @UnsupportedAppUsage
     public Locale getLocale() {
         return mLocale;
     }
@@ -60,6 +62,7 @@
     /**
      * returns the package name of the Geocoder's client
      */
+    @UnsupportedAppUsage
     public String getClientPackage() {
         return mPackageName;
     }
diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java
index 5de779a..ed2aa64 100644
--- a/location/java/android/location/Geofence.java
+++ b/location/java/android/location/Geofence.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -98,6 +99,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<Geofence> CREATOR = new Parcelable.Creator<Geofence>() {
         @Override
         public Geofence createFromParcel(Parcel in) {
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index b601cde..d90a597 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.SparseArray;
 
 import java.util.Iterator;
@@ -206,6 +207,7 @@
                 status.mAzimuths);
     }
 
+    @UnsupportedAppUsage
     void setTimeToFirstFix(int ttff) {
         mTimeToFirstFix = ttff;
     }
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 684cafa..70a97e1 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -123,8 +124,10 @@
         }
     };
 
+    @UnsupportedAppUsage
     private String mProvider;
     private long mTime = 0;
+    @UnsupportedAppUsage
     private long mElapsedRealtimeNanos = 0;
     private double mLatitude = 0.0;
     private double mLongitude = 0.0;
@@ -1156,6 +1159,7 @@
      * @param value the Location to attach
      * @hide
      */
+    @UnsupportedAppUsage
     public void setExtraLocation(String key, Location value) {
         if (mExtras == null) {
             mExtras = new Bundle();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 6eb3d8d..b5d9431 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -22,7 +22,6 @@
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 
 import android.Manifest;
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
@@ -30,6 +29,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -42,16 +42,11 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.ArraySet;
 import android.util.Log;
 import com.android.internal.location.ProviderProperties;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Set;
 
 /**
  * This class provides access to the system location services.  These
@@ -74,6 +69,7 @@
     private static final String TAG = "LocationManager";
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private final ILocationManager mService;
     private final GnssMeasurementCallbackTransport mGnssMeasurementCallbackTransport;
     private final GnssNavigationMessageCallbackTransport mGnssNavigationMessageCallbackTransport;
@@ -331,7 +327,7 @@
             Message msg = Message.obtain();
             msg.what = TYPE_LOCATION_CHANGED;
             msg.obj = location;
-            mListenerHandler.sendMessage(msg);
+            sendCallbackMessage(msg);
         }
 
         @Override
@@ -345,7 +341,7 @@
                 b.putBundle("extras", extras);
             }
             msg.obj = b;
-            mListenerHandler.sendMessage(msg);
+            sendCallbackMessage(msg);
         }
 
         @Override
@@ -353,7 +349,7 @@
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_ENABLED;
             msg.obj = provider;
-            mListenerHandler.sendMessage(msg);
+            sendCallbackMessage(msg);
         }
 
         @Override
@@ -361,7 +357,13 @@
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_DISABLED;
             msg.obj = provider;
-            mListenerHandler.sendMessage(msg);
+            sendCallbackMessage(msg);
+        }
+
+        private void sendCallbackMessage(Message msg) {
+            if (!mListenerHandler.sendMessage(msg)) {
+                locationCallbackFinished();
+            }
         }
 
         private void _handleMessage(Message msg) {
@@ -384,6 +386,10 @@
                     mListener.onProviderDisabled((String) msg.obj);
                     break;
             }
+            locationCallbackFinished();
+        }
+
+        private void locationCallbackFinished() {
             try {
                 mService.locationCallbackFinished(this);
             } catch (RemoteException e) {
@@ -730,6 +736,11 @@
      * calling Activity. If a Looper is specified with a {@link LocationListener}
      * then callbacks are made on the supplied Looper thread.
      *
+     * <p> When location callbacks are invoked, the system will hold a wakelock
+     * on your application's behalf for some period of time, but not
+     * indefinitely. If your application requires a long running wakelock
+     * within the location callback, you should acquire it yourself.
+     *
      * <p class="note"> Prior to Jellybean, the minTime parameter was
      * only a hint, and some location provider implementations ignored it.
      * From Jellybean and onwards it is mandatory for Android compatible
@@ -995,6 +1006,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void requestLocationUpdates(LocationRequest request, LocationListener listener,
             Looper looper, PendingIntent intent) {
 
@@ -2319,6 +2331,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean sendNiResponse(int notifId, int userResponse) {
         try {
             return mService.sendNiResponse(notifId, userResponse);
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 96a0817..2d7f7e3 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -17,6 +17,7 @@
 package android.location;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -141,16 +142,26 @@
      */
     private static final double FASTEST_INTERVAL_FACTOR = 6.0;  // 6x
 
+    @UnsupportedAppUsage
     private int mQuality = POWER_LOW;
+    @UnsupportedAppUsage
     private long mInterval = 60 * 60 * 1000;   // 60 minutes
+    @UnsupportedAppUsage
     private long mFastestInterval = (long) (mInterval / FASTEST_INTERVAL_FACTOR);  // 10 minutes
+    @UnsupportedAppUsage
     private boolean mExplicitFastestInterval = false;
+    @UnsupportedAppUsage
     private long mExpireAt = Long.MAX_VALUE;  // no expiry
+    @UnsupportedAppUsage
     private int mNumUpdates = Integer.MAX_VALUE;  // no expiry
+    @UnsupportedAppUsage
     private float mSmallestDisplacement = 0.0f;    // meters
+    @UnsupportedAppUsage
     private WorkSource mWorkSource = null;
+    @UnsupportedAppUsage
     private boolean mHideFromAppOps = false; // True if this request shouldn't be counted by AppOps
 
+    @UnsupportedAppUsage
     private String mProvider = LocationManager.FUSED_PROVIDER;
             // for deprecated APIs that explicitly request a provider
 
@@ -592,12 +603,14 @@
         return mHideFromAppOps;
     }
 
+    @UnsupportedAppUsage
     private static void checkInterval(long millis) {
         if (millis < 0) {
             throw new IllegalArgumentException("invalid interval: " + millis);
         }
     }
 
+    @UnsupportedAppUsage
     private static void checkQuality(int quality) {
         switch (quality) {
             case ACCURACY_FINE:
@@ -612,12 +625,14 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static void checkDisplacement(float meters) {
         if (meters < 0.0f) {
             throw new IllegalArgumentException("invalid displacement: " + meters);
         }
     }
 
+    @UnsupportedAppUsage
     private static void checkProvider(String name) {
         if (name == null) {
             throw new IllegalArgumentException("invalid provider: " + name);
diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java
index 45fdb76..88919f6 100644
--- a/location/java/com/android/internal/location/ProviderRequest.java
+++ b/location/java/com/android/internal/location/ProviderRequest.java
@@ -19,6 +19,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import android.annotation.UnsupportedAppUsage;
 import android.location.LocationRequest;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -27,9 +28,11 @@
 /** @hide */
 public final class ProviderRequest implements Parcelable {
     /** Location reporting is requested (true) */
+    @UnsupportedAppUsage
     public boolean reportLocation = false;
 
     /** The smallest requested interval */
+    @UnsupportedAppUsage
     public long interval = Long.MAX_VALUE;
 
     /**
@@ -45,8 +48,10 @@
      * is a high power slow interval request and a
      * low power fast interval request.
      */
+    @UnsupportedAppUsage
     public List<LocationRequest> locationRequests = new ArrayList<LocationRequest>();
 
+    @UnsupportedAppUsage
     public ProviderRequest() {
     }
 
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 3643ca4..8a02a82 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -18,6 +18,7 @@
 
 import android.os.SystemClock;
 import android.os.connectivity.GpsBatteryStats;
+import android.os.SystemProperties;
 
 import android.text.format.DateUtils;
 import android.util.Base64;
@@ -175,6 +176,7 @@
           = topFourAverageCn0Statistics.getStandardDeviation();
     }
     msg.powerMetrics = mGnssPowerMetrics.buildProto();
+    msg.hardwareRevision = SystemProperties.get("ro.boot.revision", "");
     String s = Base64.encodeToString(GnssLog.toByteArray(msg), Base64.DEFAULT);
     reset();
     return s;
@@ -239,6 +241,7 @@
       s.append("  Energy consumed while on battery (mAh): ").append(
           stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS)).append("\n");
     }
+    s.append("Hardware Version: " + SystemProperties.get("ro.boot.revision", "")).append("\n");
     return s.toString();
   }
 
diff --git a/media/OWNERS b/media/OWNERS
index 182f661..1ae2a7b 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,5 +1,8 @@
 elaurent@google.com
 etalvala@google.com
+gkasten@google.com
+hunga@google.com
+jmtrivi@google.com
 lajos@google.com
 marcone@google.com
 sungsoo@google.com
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java
index efaf224..5088798 100644
--- a/media/java/android/media/AmrInputStream.java
+++ b/media/java/android/media/AmrInputStream.java
@@ -20,6 +20,7 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 
+import android.annotation.UnsupportedAppUsage;
 import android.media.MediaCodec.BufferInfo;
 import android.util.Log;
 
@@ -53,6 +54,7 @@
     /**
      * DO NOT USE - use MediaCodec instead
      */
+    @UnsupportedAppUsage
     public AmrInputStream(InputStream inputStream) {
         Log.w(TAG, "@@@@ AmrInputStream is not a public API @@@@");
         mInputStream = inputStream;
diff --git a/media/java/android/media/AsyncPlayer.java b/media/java/android/media/AsyncPlayer.java
index c1a178a..8ac2655 100644
--- a/media/java/android/media/AsyncPlayer.java
+++ b/media/java/android/media/AsyncPlayer.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.PlayerBase;
 import android.net.Uri;
@@ -248,6 +249,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUsesWakeLock(Context context) {
         if (mWakeLock != null || mThread != null) {
             // if either of these has happened, we've already played something.
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 9152ff2..e8bc622 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -372,11 +373,16 @@
     private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED |
             FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY;
 
+    @UnsupportedAppUsage
     private int mUsage = USAGE_UNKNOWN;
+    @UnsupportedAppUsage
     private int mContentType = CONTENT_TYPE_UNKNOWN;
+    @UnsupportedAppUsage
     private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
+    @UnsupportedAppUsage
     private int mFlags = 0x0;
     private HashSet<String> mTags;
+    @UnsupportedAppUsage
     private String mFormattedTags;
     private Bundle mBundle; // lazy-initialized, may be null
 
@@ -646,6 +652,7 @@
          * @param tag
          * @return the same Builder instance.
          */
+        @UnsupportedAppUsage
         public Builder addTag(String tag) {
             mTags.add(tag);
             return this;
@@ -675,6 +682,7 @@
          * @param streamType
          * @return the same Builder instance.
          */
+        @UnsupportedAppUsage
         public Builder setInternalLegacyStreamType(int streamType) {
             switch(streamType) {
                 case AudioSystem.STREAM_VOICE_CALL:
@@ -1016,6 +1024,7 @@
      * @param aa non-null AudioAttributes.
      * @return a valid stream type for volume control that matches the attributes.
      */
+    @UnsupportedAppUsage
     public static int toLegacyStreamType(@NonNull AudioAttributes aa) {
         return toVolumeStreamType(false /*fromGetVolumeControlStream*/, aa);
     }
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index aea39a3..62b18cb 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.media.AudioSystem;
 
 /**
@@ -36,6 +37,7 @@
     private final int mType;
     private final String mAddress;
 
+    @UnsupportedAppUsage
     AudioDevicePort(AudioHandle handle, String deviceName,
             int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
             int[] formats, AudioGain[] gains, int type, String address) {
@@ -50,6 +52,7 @@
     /**
      * Get the device type (e.g AudioManager.DEVICE_OUT_SPEAKER)
      */
+    @UnsupportedAppUsage
     public int type() {
         return mType;
     }
diff --git a/media/java/android/media/AudioDevicePortConfig.java b/media/java/android/media/AudioDevicePortConfig.java
index e468a53..0c647ea 100644
--- a/media/java/android/media/AudioDevicePortConfig.java
+++ b/media/java/android/media/AudioDevicePortConfig.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * An AudioDevicePortConfig describes a possible configuration of an output or input device
  * (speaker, headphone, microphone ...).
@@ -26,6 +28,7 @@
  */
 
 public class AudioDevicePortConfig extends AudioPortConfig {
+    @UnsupportedAppUsage
     AudioDevicePortConfig(AudioDevicePort devicePort, int samplingRate, int channelMask,
             int format, AudioGainConfig gain) {
         super((AudioPort)devicePort, samplingRate, channelMask, format, gain);
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index e245425..38204a5 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -663,6 +664,7 @@
      */
     // Update sound trigger JNI in core/jni/android_hardware_SoundTrigger.cpp when modifying this
     // constructor
+    @UnsupportedAppUsage
     private AudioFormat(int encoding, int sampleRate, int channelMask, int channelIndexMask) {
         mEncoding = encoding;
         mSampleRate = sampleRate;
@@ -685,8 +687,11 @@
     /** @hide */
     public final static int AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK = 0x1 << 3;
 
+    @UnsupportedAppUsage
     private int mEncoding;
+    @UnsupportedAppUsage
     private int mSampleRate;
+    @UnsupportedAppUsage
     private int mChannelMask;
     private int mChannelIndexMask;
     private int mPropertySetMask;
@@ -1083,6 +1088,7 @@
             ENCODING_AAC_LC,
             ENCODING_DOLBY_TRUEHD,
             ENCODING_E_AC3_JOC,
+            ENCODING_AC4,
     };
 
     /** @hide */
@@ -1093,7 +1099,8 @@
             ENCODING_DTS_HD,
             ENCODING_AAC_LC,
             ENCODING_DOLBY_TRUEHD,
-            ENCODING_E_AC3_JOC }
+            ENCODING_E_AC3_JOC,
+            ENCODING_AC4 }
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface SurroundSoundEncoding {}
@@ -1105,14 +1112,14 @@
      * It is just a default to use if an international name is not available.
      *
      * @param audioFormat a surround format
-     * @return short default name for the format, eg. “AC3” for ENCODING_AC3.
+     * @return short default name for the format.
      */
     public static String toDisplayName(@SurroundSoundEncoding int audioFormat) {
         switch (audioFormat) {
             case ENCODING_AC3:
-                return "Dolby Digital (AC3)";
+                return "Dolby Digital";
             case ENCODING_E_AC3:
-                return "Dolby Digital Plus (E_AC3)";
+                return "Dolby Digital Plus";
             case ENCODING_DTS:
                 return "DTS";
             case ENCODING_DTS_HD:
@@ -1122,7 +1129,9 @@
             case ENCODING_DOLBY_TRUEHD:
                 return "Dolby TrueHD";
             case ENCODING_E_AC3_JOC:
-                return "Dolby Atmos";
+                return "Dolby Atmos in Dolby Digital Plus";
+            case ENCODING_AC4:
+                return "Dolby AC-4";
             default:
                 return "Unknown surround sound format";
         }
diff --git a/media/java/android/media/AudioGain.java b/media/java/android/media/AudioGain.java
index 57709d5..dd129a2 100644
--- a/media/java/android/media/AudioGain.java
+++ b/media/java/android/media/AudioGain.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * The AudioGain describes a gain controller. Gain controllers are exposed by
  * audio ports when the gain is configurable at this port's input or output.
@@ -69,6 +71,7 @@
 
     // The channel mask passed to the constructor is as specified in AudioFormat
     // (e.g. AudioFormat.CHANNEL_OUT_STEREO)
+    @UnsupportedAppUsage
     AudioGain(int index, int mode, int channelMask,
                         int minValue, int maxValue, int defaultValue, int stepValue,
                         int rampDurationMinMs, int rampDurationMaxMs) {
diff --git a/media/java/android/media/AudioGainConfig.java b/media/java/android/media/AudioGainConfig.java
index ea61679..f5ebef8 100644
--- a/media/java/android/media/AudioGainConfig.java
+++ b/media/java/android/media/AudioGainConfig.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * The AudioGainConfig is used by APIs setting or getting values on a given gain
  * controller. It contains a valid configuration (value, channels...) for a gain controller
@@ -26,12 +28,18 @@
  */
 public class AudioGainConfig {
     AudioGain mGain;
+    @UnsupportedAppUsage
     private final int mIndex;
+    @UnsupportedAppUsage
     private final int mMode;
+    @UnsupportedAppUsage
     private final int mChannelMask;
+    @UnsupportedAppUsage
     private final int mValues[];
+    @UnsupportedAppUsage
     private final int mRampDurationMs;
 
+    @UnsupportedAppUsage
     AudioGainConfig(int index, AudioGain gain, int mode, int channelMask,
             int[] values, int rampDurationMs) {
         mIndex = index;
diff --git a/media/java/android/media/AudioHandle.java b/media/java/android/media/AudioHandle.java
index 6493dac..24f81f9 100644
--- a/media/java/android/media/AudioHandle.java
+++ b/media/java/android/media/AudioHandle.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * The AudioHandle is used by the audio framework implementation to
  * uniquely identify a particular component of the routing topology
@@ -23,8 +25,10 @@
  * It is not visible or used at the API.
  */
 class AudioHandle {
+    @UnsupportedAppUsage
     private final int mId;
 
+    @UnsupportedAppUsage
     AudioHandle(int id) {
         mId = id;
     }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 1a282b2..85eac4b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
@@ -154,6 +155,7 @@
      * @see #EXTRA_PREV_VOLUME_STREAM_VALUE
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @UnsupportedAppUsage
     public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
 
     /**
@@ -220,6 +222,7 @@
     /**
      * @hide The stream type for the volume changed intent.
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";
 
     /**
@@ -236,6 +239,7 @@
     /**
      * @hide The volume associated with the stream for the volume changed intent.
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_VOLUME_STREAM_VALUE =
         "android.media.EXTRA_VOLUME_STREAM_VALUE";
 
@@ -342,14 +346,17 @@
     public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
     /** @hide Used to identify the volume of audio streams for phone calls when connected
      *        to bluetooth */
+    @UnsupportedAppUsage
     public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
     /** @hide Used to identify the volume of audio streams for enforced system sounds
      *        in certain countries (e.g camera in Japan) */
+    @UnsupportedAppUsage
     public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED;
     /** Used to identify the volume of audio streams for DTMF Tones */
     public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;
     /** @hide Used to identify the volume of audio streams exclusively transmitted through the
      *        speaker (TTS) of the device */
+    @UnsupportedAppUsage
     public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
     /** Used to identify the volume of audio streams for accessibility prompts */
     public static final int STREAM_ACCESSIBILITY = AudioSystem.STREAM_ACCESSIBILITY;
@@ -675,6 +682,7 @@
      * @hide
      * For test purposes only, will throw NPE with some methods that require a Context.
      */
+    @UnsupportedAppUsage
     public AudioManager() {
         mUseVolumeKeySounds = true;
         mUseFixedVolume = false;
@@ -683,6 +691,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public AudioManager(Context context) {
         setContext(context);
         mUseVolumeKeySounds = getContext().getResources().getBoolean(
@@ -710,6 +719,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static IAudioService getService()
     {
         if (sService != null) {
@@ -880,6 +890,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setMasterMute(boolean mute, int flags) {
         final IAudioService service = getService();
         try {
@@ -914,6 +925,7 @@
      * @see #setRingerMode(int)
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isValidRingerMode(int ringerMode) {
         if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) {
             return false;
@@ -1062,6 +1074,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getLastAudibleStreamVolume(int streamType) {
         final IAudioService service = getService();
         try {
@@ -1222,6 +1235,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isMasterMute() {
         final IAudioService service = getService();
         try {
@@ -1239,6 +1253,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @UnsupportedAppUsage
     public void forceVolumeControlStream(int streamType) {
         final IAudioService service = getService();
         try {
@@ -1531,6 +1546,7 @@
      * @see #stopBluetoothSco()
      * @see #ACTION_SCO_AUDIO_STATE_UPDATED
      */
+    @UnsupportedAppUsage
     public void startBluetoothScoVirtualCall() {
         final IAudioService service = getService();
         try {
@@ -1854,6 +1870,7 @@
      *   display). Note that BT audio sinks are not considered remote devices.
      * @return true if {@link AudioManager#STREAM_MUSIC} is active on a remote device
      */
+    @UnsupportedAppUsage
     public boolean isMusicActiveRemotely() {
         return AudioSystem.isStreamActiveRemotely(STREAM_MUSIC, 0);
     }
@@ -2004,6 +2021,7 @@
     /**
      * @hide Number of sound effects
      */
+    @UnsupportedAppUsage
     public static final int NUM_SOUND_EFFECTS = 10;
 
     /**
@@ -2234,6 +2252,7 @@
      * Map to convert focus event listener IDs, as used in the AudioService audio focus stack,
      * to actual listener objects.
      */
+    @UnsupportedAppUsage
     private final ConcurrentHashMap<String, FocusRequestInfo> mAudioFocusIdListenerMap =
             new ConcurrentHashMap<String, FocusRequestInfo>();
 
@@ -2810,6 +2829,7 @@
      * @param durationHint the type of focus request. AUDIOFOCUS_GAIN_TRANSIENT is recommended so
      *    media applications resume after a call
      */
+    @UnsupportedAppUsage
     public void requestAudioFocusForCall(int streamType, int durationHint) {
         final IAudioService service = getService();
         try {
@@ -2913,6 +2933,7 @@
      * when ringing ends and the call is rejected or not answered.
      * Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}.
      */
+    @UnsupportedAppUsage
     public void abandonAudioFocusForCall() {
         final IAudioService service = getService();
         try {
@@ -3582,6 +3603,7 @@
      *  agent when audio settings are restored and causes the AudioService
      *  to read and apply restored settings.
      */
+    @UnsupportedAppUsage
     public void reloadAudioSettings() {
         final IAudioService service = getService();
         try {
@@ -3620,6 +3642,7 @@
      *
      * @hide pending API Council approval
      */
+    @UnsupportedAppUsage
     public boolean isSilentMode() {
         int ringerMode = getRingerMode();
         boolean silentMode =
@@ -3641,15 +3664,19 @@
      *  such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a
      *  {@link #DEVICE_OUT_WIRED_HEADPHONE}.
      */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE;
     /** @hide
      *  The audio output device code for the built-in speaker */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER;
     /** @hide
      * The audio output device code for a wired headset with attached microphone */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
     /** @hide
      * The audio output device code for a wired headphone without attached microphone */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
     /** @hide
      * The audio output device code for a USB headphone with attached microphone */
@@ -3661,6 +3688,7 @@
      * The audio output device code for Bluetooth SCO Headset Profile (HSP) and
      * Hands-Free Profile (HFP), for voice
      */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET =
             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
     /** @hide
@@ -3669,13 +3697,16 @@
             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
     /** @hide
      * The audio output device code for generic Bluetooth A2DP, for music */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
     /** @hide
      * The audio output device code for Bluetooth A2DP headphones, for music */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES =
             AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
     /** @hide
      * The audio output device code for Bluetooth A2DP external speaker, for music */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER =
             AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
     /** @hide
@@ -3684,16 +3715,19 @@
     public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL;
     /** @hide
      * The audio output device code for HDMI */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_HDMI = AudioSystem.DEVICE_OUT_HDMI;
     /** @hide
      * The audio output device code for an analog wired headset attached via a
      *  docking station
      */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
     /** @hide
      * The audio output device code for a digital wired headset attached via a
      *  docking station
      */
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET;
     /** @hide
      * The audio output device code for a USB audio accessory. The accessory is in USB host
@@ -3872,6 +3906,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int getDevicesForStream(int streamType) {
         switch (streamType) {
         case STREAM_VOICE_CALL:
@@ -3895,6 +3930,7 @@
      * @param name   device name
      * {@hide}
      */
+    @UnsupportedAppUsage
     public void setWiredDeviceConnectionState(int type, int state, String address, String name) {
         final IAudioService service = getService();
         try {
@@ -4079,6 +4115,7 @@
      * a better solution.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getOutputLatency(int streamType) {
         return AudioSystem.getOutputLatency(streamType);
     }
@@ -4150,6 +4187,7 @@
      * Only useful for volume controllers.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRingerModeInternal(int ringerMode) {
         try {
             getService().setRingerModeInternal(ringerMode, getContext().getOpPackageName());
@@ -4162,6 +4200,7 @@
      * Only useful for volume controllers.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getRingerModeInternal() {
         try {
             return getService().getRingerModeInternal();
@@ -4251,6 +4290,7 @@
      * @param ports An AudioPort ArrayList where the list will be returned.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int listAudioPorts(ArrayList<AudioPort> ports) {
         return updateAudioPortCache(ports, null, null);
     }
@@ -4332,6 +4372,7 @@
      *         patch[0] contains the newly created patch
      * @hide
      */
+    @UnsupportedAppUsage
     public static int createAudioPatch(AudioPatch[] patch,
                                  AudioPortConfig[] sources,
                                  AudioPortConfig[] sinks) {
@@ -4349,6 +4390,7 @@
      *         - {@link #ERROR} if patch cannot be released for any other reason.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int releaseAudioPatch(AudioPatch patch) {
         return AudioSystem.releaseAudioPatch(patch);
     }
@@ -4358,6 +4400,7 @@
      * @param patches An AudioPatch array where the list will be returned.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int listAudioPatches(ArrayList<AudioPatch> patches) {
         return updateAudioPortCache(null, patches, null);
     }
@@ -4406,6 +4449,7 @@
      * Register an audio port list update listener.
      * @hide
      */
+    @UnsupportedAppUsage
     public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) {
         sAudioPortEventHandler.init();
         sAudioPortEventHandler.registerListener(l);
@@ -4415,6 +4459,7 @@
      * Unregister an audio port list update listener.
      * @hide
      */
+    @UnsupportedAppUsage
     public void unregisterAudioPortUpdateListener(OnAudioPortUpdateListener l) {
         sAudioPortEventHandler.unregisterListener(l);
     }
diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java
index ba144bf..c4a5c4d 100644
--- a/media/java/android/media/AudioMixPort.java
+++ b/media/java/android/media/AudioMixPort.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * The AudioMixPort is a specialized type of AudioPort
  * describing an audio mix or stream at an input or output stream of the audio
@@ -30,6 +32,7 @@
 
     private final int mIoHandle;
 
+    @UnsupportedAppUsage
     AudioMixPort(AudioHandle handle, int ioHandle, int role, String deviceName,
             int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
             int[] formats, AudioGain[] gains) {
@@ -50,6 +53,7 @@
     /**
      * Get the device type (e.g AudioManager.DEVICE_OUT_SPEAKER)
      */
+    @UnsupportedAppUsage
     public int ioHandle() {
         return mIoHandle;
     }
diff --git a/media/java/android/media/AudioMixPortConfig.java b/media/java/android/media/AudioMixPortConfig.java
index 8eb9ef46..315e46b 100644
--- a/media/java/android/media/AudioMixPortConfig.java
+++ b/media/java/android/media/AudioMixPortConfig.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * An AudioMixPortConfig describes a possible configuration of an output or input mixer.
  * It is used to specify a sink or source when creating a connection with
@@ -26,6 +28,7 @@
 
 public class AudioMixPortConfig extends AudioPortConfig {
 
+    @UnsupportedAppUsage
     AudioMixPortConfig(AudioMixPort mixPort, int samplingRate, int channelMask, int format,
                 AudioGainConfig gain) {
         super((AudioPort)mixPort, samplingRate, channelMask, format, gain);
diff --git a/media/java/android/media/AudioPatch.java b/media/java/android/media/AudioPatch.java
index 6c70213..d1f8006 100644
--- a/media/java/android/media/AudioPatch.java
+++ b/media/java/android/media/AudioPatch.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 
 /**
  * An AudioPatch describes a connection between audio sources and audio sinks.
@@ -29,10 +31,12 @@
  */
 public class AudioPatch {
 
+    @UnsupportedAppUsage
     private final AudioHandle mHandle;
     private final AudioPortConfig[] mSources;
     private final AudioPortConfig[] mSinks;
 
+    @UnsupportedAppUsage
     AudioPatch(AudioHandle patchHandle, AudioPortConfig[] sources, AudioPortConfig[] sinks) {
         mHandle = patchHandle;
         mSources = sources;
@@ -42,6 +46,7 @@
     /**
      * Retrieve the list of sources of this audio patch.
      */
+    @UnsupportedAppUsage
     public AudioPortConfig[] sources() {
         return mSources;
     }
@@ -49,6 +54,7 @@
     /**
      * Retreive the list of sinks of this audio patch.
      */
+    @UnsupportedAppUsage
     public AudioPortConfig[] sinks() {
         return mSinks;
     }
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index 047db19..83eb240 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * An audio port is a node of the audio framework or hardware that can be connected to or
  * disconnect from another audio node to create a specific audio routing configuration.
@@ -66,16 +68,21 @@
     public static final int TYPE_SESSION = 3;
 
 
+    @UnsupportedAppUsage
     AudioHandle mHandle;
+    @UnsupportedAppUsage
     protected final int mRole;
     private final String mName;
     private final int[] mSamplingRates;
     private final int[] mChannelMasks;
     private final int[] mChannelIndexMasks;
     private final int[] mFormats;
+    @UnsupportedAppUsage
     private final AudioGain[] mGains;
+    @UnsupportedAppUsage
     private AudioPortConfig mActiveConfig;
 
+    @UnsupportedAppUsage
     AudioPort(AudioHandle handle, int role, String name,
             int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
             int[] formats, AudioGain[] gains) {
@@ -97,6 +104,7 @@
     /**
      * Get the system unique device ID.
      */
+    @UnsupportedAppUsage
     public int id() {
         return mHandle.id();
     }
@@ -105,6 +113,7 @@
     /**
      * Get the audio port role
      */
+    @UnsupportedAppUsage
     public int role() {
         return mRole;
     }
diff --git a/media/java/android/media/AudioPortConfig.java b/media/java/android/media/AudioPortConfig.java
index f937cc2..45e49a7 100644
--- a/media/java/android/media/AudioPortConfig.java
+++ b/media/java/android/media/AudioPortConfig.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * An AudioPortConfig contains a possible configuration of an audio port chosen
  * among all possible attributes described by an AudioPort.
@@ -30,10 +32,15 @@
  */
 
 public class AudioPortConfig {
+    @UnsupportedAppUsage
     final AudioPort mPort;
+    @UnsupportedAppUsage
     private final int mSamplingRate;
+    @UnsupportedAppUsage
     private final int mChannelMask;
+    @UnsupportedAppUsage
     private final int mFormat;
+    @UnsupportedAppUsage
     private final AudioGainConfig mGain;
 
     // mConfigMask indicates which fields in this configuration should be
@@ -43,8 +50,10 @@
     static final int CHANNEL_MASK = 0x2;
     static final int FORMAT       = 0x4;
     static final int GAIN         = 0x8;
+    @UnsupportedAppUsage
     int mConfigMask;
 
+    @UnsupportedAppUsage
     AudioPortConfig(AudioPort port, int samplingRate, int channelMask, int format,
             AudioGainConfig gain) {
         mPort = port;
@@ -58,6 +67,7 @@
     /**
      * Returns the audio port this AudioPortConfig is issued from.
      */
+    @UnsupportedAppUsage
     public AudioPort port() {
         return mPort;
     }
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index ac3904a..f9a4b1e 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -48,6 +49,7 @@
      * Accessed by native methods: JNI Callback context.
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private long mJniCallback;
 
     void init() {
@@ -170,6 +172,7 @@
     }
 
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private static void postEventFromNative(Object module_ref,
                                             int what, int arg1, int arg2, Object obj) {
         AudioPortEventHandler eventHandler =
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 54800ae..452ba0f 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -29,6 +29,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.os.Binder;
 import android.os.Handler;
@@ -157,18 +158,21 @@
      * Accessed by native methods: provides access to C++ AudioRecord object
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private long mNativeRecorderInJavaObj;
 
     /**
      * Accessed by native methods: provides access to the callback data.
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private long mNativeCallbackCookie;
 
     /**
      * Accessed by native methods: provides access to the JNIDeviceCallback instance.
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private long mNativeDeviceCallback;
 
 
@@ -233,6 +237,7 @@
     /**
      * Looper associated with the thread that creates the AudioRecord instance
      */
+    @UnsupportedAppUsage
     private Looper mInitializationLooper = null;
     /**
      * Size of the native audio buffer.
@@ -245,6 +250,7 @@
     /**
      * AudioAttributes
      */
+    @UnsupportedAppUsage
     private AudioAttributes mAudioAttributes;
     private boolean mIsSubmixFullVolume = false;
 
@@ -1720,6 +1726,7 @@
     // Java methods called from the native side
     //--------------------
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private static void postEventFromNative(Object audiorecord_ref,
             int what, int arg1, int arg2, Object obj) {
         //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
@@ -1746,6 +1753,7 @@
     // Native methods called from the Java side
     //--------------------
 
+    @UnsupportedAppUsage
     private native final int native_setup(Object audiorecord_this,
             Object /*AudioAttributes*/ attributes,
             int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
@@ -1758,6 +1766,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public native final void native_release();
 
     private native final int native_start(int syncEvent, int sessionId);
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
index 984c554..9ada216 100644
--- a/media/java/android/media/AudioRecordingConfiguration.java
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -173,6 +174,7 @@
      * <br>When called without the permission, the result is an empty string.
      * @return the package name
      */
+    @UnsupportedAppUsage
     public String getClientPackageName() { return mClientPackageName; }
 
     /**
@@ -184,6 +186,7 @@
      * <br>The result is -1 without the permission.
      * @return the user id
      */
+    @UnsupportedAppUsage
     public int getClientUid() { return mClientUid; }
 
     /**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 7c893d0..39f3b31 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.media.audiopolicy.AudioMix;
@@ -59,6 +60,7 @@
     public static final int STREAM_BLUETOOTH_SCO = 6;
     /** Used to identify the volume of audio streams for enforced system sounds in certain
      * countries (e.g camera in Japan) */
+    @UnsupportedAppUsage
     public static final int STREAM_SYSTEM_ENFORCED = 7;
     /** Used to identify the volume of audio streams for DTMF tones */
     public static final int STREAM_DTMF = 8;
@@ -74,6 +76,7 @@
 
     // Expose only the getter method publicly so we can change it in the future
     private static final int NUM_STREAM_TYPES = 11;
+    @UnsupportedAppUsage
     public static final int getNumStreamTypes() { return NUM_STREAM_TYPES; }
 
     public static final String[] STREAM_NAMES = new String[] {
@@ -97,6 +100,7 @@
      *           <var>false</var> to turn mute off
      * @return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR
      */
+    @UnsupportedAppUsage
     public static native int muteMicrophone(boolean on);
 
     /*
@@ -104,6 +108,7 @@
      *
      * @return true if microphone is muted, false if it's not
      */
+    @UnsupportedAppUsage
     public static native boolean isMicrophoneMuted();
 
     /* modes for setPhoneState, must match AudioSystem.h audio_mode */
@@ -151,6 +156,7 @@
      *
      * return true if any track playing on this stream is active.
      */
+    @UnsupportedAppUsage
     public static native boolean isStreamActive(int stream, int inPastMs);
 
     /*
@@ -166,6 +172,7 @@
      *
      * return true if any recorder using this source is currently recording
      */
+    @UnsupportedAppUsage
     public static native boolean isSourceActive(int source);
 
     /*
@@ -186,6 +193,7 @@
      * param keyValuePairs  list of parameters key value pairs in the form:
      *    key1=value1;key2=value2;...
      */
+    @UnsupportedAppUsage
     public static native int setParameters(String keyValuePairs);
 
     /*
@@ -196,6 +204,7 @@
      * return value: list of parameters key value pairs in the form:
      *    key1=value1;key2=value2;...
      */
+    @UnsupportedAppUsage
     public static native String getParameters(String keys);
 
     // These match the enum AudioError in frameworks/base/core/jni/android_media_AudioSystem.cpp
@@ -227,6 +236,7 @@
      * Registers a callback to be invoked when an error occurs.
      * @param cb the callback to run
      */
+    @UnsupportedAppUsage
     public static void setErrorCallback(ErrorCallback cb)
     {
         synchronized (AudioSystem.class) {
@@ -237,6 +247,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static void errorCallbackFromNative(int error)
     {
         ErrorCallback errorCallback = null;
@@ -272,6 +283,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static void dynamicPolicyCallbackFromNative(int event, String regId, int val)
     {
         DynamicPolicyCallback cb = null;
@@ -336,6 +348,7 @@
      *     {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int, int[])}
      *     for the description of the record format.
      */
+    @UnsupportedAppUsage
     private static void recordingCallbackFromNative(int event, int uid, int session, int source,
             int[] recordingFormat) {
         AudioRecordingCallback cb = null;
@@ -374,27 +387,45 @@
     public static final int DEVICE_BIT_IN = 0x80000000;
     public static final int DEVICE_BIT_DEFAULT = 0x40000000;
     // output devices, be sure to update AudioManager.java also
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_EARPIECE = 0x1;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_SPEAKER = 0x2;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_WIRED_HEADSET = 0x4;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_WIRED_HEADPHONE = 0x8;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_SCO = 0x10;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_A2DP = 0x80;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
     public static final int DEVICE_OUT_HDMI = DEVICE_OUT_AUX_DIGITAL;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_USB_DEVICE = 0x4000;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_REMOTE_SUBMIX = 0x8000;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_TELEPHONY_TX = 0x10000;
     public static final int DEVICE_OUT_LINE = 0x20000;
     public static final int DEVICE_OUT_HDMI_ARC = 0x40000;
     public static final int DEVICE_OUT_SPDIF = 0x80000;
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_FM = 0x100000;
     public static final int DEVICE_OUT_AUX_LINE = 0x200000;
     public static final int DEVICE_OUT_SPEAKER_SAFE = 0x400000;
@@ -441,6 +472,7 @@
     public static final int DEVICE_OUT_ALL_SCO = (DEVICE_OUT_BLUETOOTH_SCO |
                                                   DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
                                                   DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+    @UnsupportedAppUsage
     public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
                                                   DEVICE_OUT_USB_DEVICE |
                                                   DEVICE_OUT_USB_HEADSET);
@@ -452,31 +484,46 @@
              DEVICE_OUT_SPEAKER);
 
     // input devices
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_COMMUNICATION = DEVICE_BIT_IN | 0x1;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_AMBIENT = DEVICE_BIT_IN | 0x2;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_BUILTIN_MIC = DEVICE_BIT_IN | 0x4;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = DEVICE_BIT_IN | 0x8;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_WIRED_HEADSET = DEVICE_BIT_IN | 0x10;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_AUX_DIGITAL = DEVICE_BIT_IN | 0x20;
     public static final int DEVICE_IN_HDMI = DEVICE_IN_AUX_DIGITAL;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_VOICE_CALL = DEVICE_BIT_IN | 0x40;
     public static final int DEVICE_IN_TELEPHONY_RX = DEVICE_IN_VOICE_CALL;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_BACK_MIC = DEVICE_BIT_IN | 0x80;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_REMOTE_SUBMIX = DEVICE_BIT_IN | 0x100;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_ANLG_DOCK_HEADSET = DEVICE_BIT_IN | 0x200;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_DGTL_DOCK_HEADSET = DEVICE_BIT_IN | 0x400;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_USB_ACCESSORY = DEVICE_BIT_IN | 0x800;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_USB_DEVICE = DEVICE_BIT_IN | 0x1000;
     public static final int DEVICE_IN_FM_TUNER = DEVICE_BIT_IN | 0x2000;
     public static final int DEVICE_IN_TV_TUNER = DEVICE_BIT_IN | 0x4000;
     public static final int DEVICE_IN_LINE = DEVICE_BIT_IN | 0x8000;
     public static final int DEVICE_IN_SPDIF = DEVICE_BIT_IN | 0x10000;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_BLUETOOTH_A2DP = DEVICE_BIT_IN | 0x20000;
     public static final int DEVICE_IN_LOOPBACK = DEVICE_BIT_IN | 0x40000;
     public static final int DEVICE_IN_IP = DEVICE_BIT_IN | 0x80000;
     public static final int DEVICE_IN_BUS = DEVICE_BIT_IN | 0x100000;
     public static final int DEVICE_IN_PROXY = DEVICE_BIT_IN | 0x1000000;
     public static final int DEVICE_IN_USB_HEADSET = DEVICE_BIT_IN | 0x2000000;
+    @UnsupportedAppUsage
     public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
 
     public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
@@ -509,7 +556,9 @@
                                                  DEVICE_IN_USB_HEADSET);
 
     // device states, must match AudioSystem::device_connection_state
+    @UnsupportedAppUsage
     public static final int DEVICE_STATE_UNAVAILABLE = 0;
+    @UnsupportedAppUsage
     public static final int DEVICE_STATE_AVAILABLE = 1;
     private static final int NUM_DEVICE_STATES = 1;
 
@@ -575,6 +624,7 @@
     public static final String DEVICE_IN_PROXY_NAME = "proxy";
     public static final String DEVICE_IN_USB_HEADSET_NAME = "usb_headset";
 
+    @UnsupportedAppUsage
     public static String getOutputDeviceName(int device)
     {
         switch(device) {
@@ -701,15 +751,20 @@
     public static final int PHONE_STATE_INCALL = 2;
 
     // device categories config for setForceUse, must match audio_policy_forced_cfg_t
+    @UnsupportedAppUsage
     public static final int FORCE_NONE = 0;
     public static final int FORCE_SPEAKER = 1;
     public static final int FORCE_HEADPHONES = 2;
     public static final int FORCE_BT_SCO = 3;
     public static final int FORCE_BT_A2DP = 4;
     public static final int FORCE_WIRED_ACCESSORY = 5;
+    @UnsupportedAppUsage
     public static final int FORCE_BT_CAR_DOCK = 6;
+    @UnsupportedAppUsage
     public static final int FORCE_BT_DESK_DOCK = 7;
+    @UnsupportedAppUsage
     public static final int FORCE_ANALOG_DOCK = 8;
+    @UnsupportedAppUsage
     public static final int FORCE_DIGITAL_DOCK = 9;
     public static final int FORCE_NO_BT_A2DP = 10;
     public static final int FORCE_SYSTEM_ENFORCED = 11;
@@ -775,22 +830,32 @@
      * @return command completion status, one of {@link #AUDIO_STATUS_OK},
      *     {@link #AUDIO_STATUS_ERROR} or {@link #AUDIO_STATUS_SERVER_DIED}
      */
+    @UnsupportedAppUsage
     public static native int setDeviceConnectionState(int device, int state,
                                                       String device_address, String device_name);
+    @UnsupportedAppUsage
     public static native int getDeviceConnectionState(int device, String device_address);
     public static native int handleDeviceConfigChange(int device,
                                                       String device_address,
                                                       String device_name);
+    @UnsupportedAppUsage
     public static native int setPhoneState(int state);
+    @UnsupportedAppUsage
     public static native int setForceUse(int usage, int config);
+    @UnsupportedAppUsage
     public static native int getForceUse(int usage);
+    @UnsupportedAppUsage
     public static native int initStreamVolume(int stream, int indexMin, int indexMax);
+    @UnsupportedAppUsage
     public static native int setStreamVolumeIndex(int stream, int index, int device);
     public static native int getStreamVolumeIndex(int stream, int device);
     public static native int setMasterVolume(float value);
     public static native float getMasterVolume();
+    @UnsupportedAppUsage
     public static native int setMasterMute(boolean mute);
+    @UnsupportedAppUsage
     public static native boolean getMasterMute();
+    @UnsupportedAppUsage
     public static native int getDevicesForStream(int stream);
 
     /** @hide returns true if master mono is enabled. */
@@ -799,11 +864,15 @@
     public static native int setMasterMono(boolean mono);
 
     // helpers for android.media.AudioManager.getProperty(), see description there for meaning
+    @UnsupportedAppUsage
     public static native int getPrimaryOutputSamplingRate();
+    @UnsupportedAppUsage
     public static native int getPrimaryOutputFrameCount();
+    @UnsupportedAppUsage
     public static native int getOutputLatency(int stream);
 
     public static native int setLowRamDevice(boolean isLowRamDevice, long totalMemory);
+    @UnsupportedAppUsage
     public static native int checkAudioFlinger();
 
     public static native int listAudioPorts(ArrayList<AudioPort> ports, int[] generation);
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 87b5d43..aaf7dd7 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -30,6 +30,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.content.Context;
 import android.os.Handler;
@@ -351,6 +352,7 @@
      *   {@link AudioManager#STREAM_ALARM}, {@link AudioManager#STREAM_NOTIFICATION}, and
      *   {@link AudioManager#STREAM_DTMF}.
      */
+    @UnsupportedAppUsage
     private int mStreamType = AudioManager.STREAM_MUSIC;
 
     /**
@@ -399,12 +401,14 @@
      * Accessed by native methods: provides access to C++ AudioTrack object.
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     protected long mNativeTrackInJavaObj;
     /**
      * Accessed by native methods: provides access to the JNI data (i.e. resources used by
      * the native AudioTrack object, but not stored in it).
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private long mJniData;
 
 
@@ -692,6 +696,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     /* package */ void deferred_connect(long nativeTrackInJavaObj) {
         if (mState != STATE_INITIALIZED) {
             // Note that for this native_setup, we are providing an already created/initialized
@@ -1501,6 +1506,7 @@
      * a better solution.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getLatency() {
         return native_get_latency();
     }
@@ -3125,6 +3131,7 @@
     // Java methods called from the native side
     //--------------------
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private static void postEventFromNative(Object audiotrack_ref,
             int what, int arg1, int arg2, Object obj) {
         //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
@@ -3192,6 +3199,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public native final void native_release();
 
     private native final void native_start();
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index d303a2e..aa123bd 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.hardware.Camera;
 import android.hardware.Camera.CameraInfo;
 
@@ -495,7 +496,9 @@
     }
 
     // Methods implemented by JNI
+    @UnsupportedAppUsage
     private static native final void native_init();
+    @UnsupportedAppUsage
     private static native final CamcorderProfile native_get_camcorder_profile(
             int cameraId, int quality);
     private static native final boolean native_has_camcorder_profile(
diff --git a/media/java/android/media/DecoderCapabilities.java b/media/java/android/media/DecoderCapabilities.java
index f16cccf..df5e918 100644
--- a/media/java/android/media/DecoderCapabilities.java
+++ b/media/java/android/media/DecoderCapabilities.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.List;
 import java.util.ArrayList;
 
@@ -32,6 +33,7 @@
      *
      */
     public enum VideoDecoder {
+        @UnsupportedAppUsage
         VIDEO_DECODER_WMV,
     };
 
@@ -39,6 +41,7 @@
      * The AudioDecoder class represents the type of an audio decoder
      */
     public enum AudioDecoder {
+        @UnsupportedAppUsage
         AUDIO_DECODER_WMA,
     };
 
@@ -51,6 +54,7 @@
      * Returns the list of video decoder types
      * @see android.media.DecoderCapabilities.VideoDecoder
      */
+    @UnsupportedAppUsage
     public static List<VideoDecoder> getVideoDecoders() {
         List<VideoDecoder> decoderList = new ArrayList<VideoDecoder>();
         int nDecoders = native_get_num_video_decoders();
@@ -64,6 +68,7 @@
      * Returns the list of audio decoder types
      * @see android.media.DecoderCapabilities.AudioDecoder
      */
+    @UnsupportedAppUsage
     public static List<AudioDecoder> getAudioDecoders() {
         List<AudioDecoder> decoderList = new ArrayList<AudioDecoder>();
         int nDecoders = native_get_num_audio_decoders();
diff --git a/media/java/android/media/EncoderCapabilities.java b/media/java/android/media/EncoderCapabilities.java
index 332e360..c09c5fa 100644
--- a/media/java/android/media/EncoderCapabilities.java
+++ b/media/java/android/media/EncoderCapabilities.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.List;
 import java.util.ArrayList;
 
@@ -42,11 +43,20 @@
      */
     static public class VideoEncoderCap {
         // These are not modifiable externally, thus are public accessible
-        public final int mCodec;                                 // @see android.media.MediaRecorder.VideoEncoder
-        public final int mMinBitRate, mMaxBitRate;               // min and max bit rate (bps)
-        public final int mMinFrameRate, mMaxFrameRate;           // min and max frame rate (fps)
-        public final int mMinFrameWidth, mMaxFrameWidth;         // min and max frame width (pixel)
-        public final int mMinFrameHeight, mMaxFrameHeight;       // minn and max frame height (pixel)
+        @UnsupportedAppUsage
+        public final int mCodec;                // @see android.media.MediaRecorder.VideoEncoder
+        public final int mMinBitRate;           // min bit rate (bps)
+        public final int mMaxBitRate;           // max bit rate (bps)
+        public final int mMinFrameRate;         // min frame rate (fps)
+        public final int mMaxFrameRate;         // max frame rate (fps)
+        @UnsupportedAppUsage
+        public final int mMinFrameWidth;        // min frame width (pixel)
+        @UnsupportedAppUsage
+        public final int mMaxFrameWidth;        // max frame width (pixel)
+        @UnsupportedAppUsage
+        public final int mMinFrameHeight;       // min frame height (pixel)
+        @UnsupportedAppUsage
+        public final int mMaxFrameHeight;       // max frame height (pixel)
 
         // Private constructor called by JNI
         private VideoEncoderCap(int codec,
@@ -123,6 +133,7 @@
      * Returns the capabilities of the supported video encoders.
      * @see android.media.EncoderCapabilities.VideoEncoderCap
      */
+    @UnsupportedAppUsage
     public static List<VideoEncoderCap> getVideoEncoders() {
         int nEncoders = native_get_num_video_encoders();
         if (nEncoders == 0) return null;
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index aa45709..2395b24 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -468,6 +469,7 @@
     // See http://www.exiv2.org/makernote.html#R11
     private static final int PEF_MAKER_NOTE_SKIP_SIZE = 6;
 
+    @UnsupportedAppUsage
     private static SimpleDateFormat sFormatter;
 
     // See Exchangeable image file format for digital still cameras: Exif version 2.2.
@@ -1293,14 +1295,17 @@
         sExifPointerTagMap.put(EXIF_POINTER_TAGS[5].number, IFD_TYPE_ORF_IMAGE_PROCESSING); // 8256
     }
 
+    @UnsupportedAppUsage
     private final String mFilename;
     private final FileDescriptor mSeekableFileDescriptor;
     private final AssetManager.AssetInputStream mAssetInputStream;
     private final boolean mIsInputStream;
     private int mMimeType;
+    @UnsupportedAppUsage
     private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
     private Set<Integer> mAttributesOffsets = new HashSet<>(EXIF_TAGS.length);
     private ByteOrder mExifByteOrder = ByteOrder.BIG_ENDIAN;
+    @UnsupportedAppUsage
     private boolean mHasThumbnail;
     // The following values used for indicating a thumbnail position.
     private int mThumbnailOffset;
@@ -2022,6 +2027,7 @@
      * Returns -1 if the date time information if not available.
      * @hide
      */
+    @UnsupportedAppUsage
     public long getDateTime() {
         String dateTimeString = getAttribute(TAG_DATETIME);
         if (dateTimeString == null
@@ -2058,6 +2064,7 @@
      * Returns -1 if the date time information if not available.
      * @hide
      */
+    @UnsupportedAppUsage
     public long getGpsDateTime() {
         String date = getAttribute(TAG_GPS_DATESTAMP);
         String time = getAttribute(TAG_GPS_TIMESTAMP);
@@ -2080,6 +2087,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static float convertRationalLatLonToFloat(String rationalString, String ref) {
         try {
             String [] parts = rationalString.split(",");
@@ -2537,7 +2545,9 @@
                     if (size == 0) {
                         return 0;
                     }
-                    if (position < 0) {
+                    // We don't allow read positions after the available bytes,
+                    // the input stream won't be able to seek back then.
+                    if (position < 0 || position >= in.available()) {
                         return -1;
                     }
                     try {
@@ -2546,6 +2556,13 @@
                             mPosition = position;
                         }
 
+                        // If the read will cause us to go over the available bytes,
+                        // reduce the size so that we stay in the available range.
+                        // Otherwise the input stream may not be able to seek back.
+                        if (mPosition + size > in.available()) {
+                            size = in.available() - (int)mPosition;
+                        }
+
                         int bytesRead = in.read(buffer, offset, size);
                         if (bytesRead >= 0) {
                             mPosition += bytesRead;
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index a768dd3..dff5e9a 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -20,6 +20,7 @@
 import java.lang.AutoCloseable;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
 
@@ -57,6 +58,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected Image() {
     }
 
@@ -378,6 +380,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         protected Plane() {
         }
 
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index 7735e78..b12e647 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -21,6 +21,7 @@
 import java.lang.ref.WeakReference;
 import java.lang.CloneNotSupportedException;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.os.Looper;
 import android.os.Handler;
@@ -127,6 +128,7 @@
      * Accessed by native methods: provides access to C++ JetPlayer object 
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private long mNativePlayerInJavaObj;
 
     
@@ -560,6 +562,7 @@
     // Called exclusively by native code
     //--------------------
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private static void postEventFromNative(Object jetplayer_ref,
             int what, int arg1, int arg2) {
         //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 2207a2a..d45acdf 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.ImageFormat;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
@@ -404,7 +405,7 @@
  <p>
  The codec in turn will return a read-only output buffer via the {@link
  Callback#onOutputBufferAvailable onOutputBufferAvailable} callback in asynchronous mode, or in
- response to a {@link #dequeueOutputBuffer dequeuOutputBuffer} call in synchronous mode. After the
+ response to a {@link #dequeueOutputBuffer dequeueOutputBuffer} call in synchronous mode. After the
  output buffer has been processed, call one of the {@link #releaseOutputBuffer
  releaseOutputBuffer} methods to return the buffer to the codec.
  <p>
@@ -2137,6 +2138,7 @@
      * Thrown when an internal codec error occurs.
      */
     public final static class CodecException extends IllegalStateException {
+        @UnsupportedAppUsage
         CodecException(int errorCode, int actionCode, @Nullable String detailMessage) {
             super(detailMessage);
             mErrorCode = errorCode;
@@ -2805,6 +2807,7 @@
                 index, true /* render */, true /* updatePTS */, renderTimestampNs);
     }
 
+    @UnsupportedAppUsage
     private native final void releaseOutputBuffer(
             int index, boolean render, boolean updatePTS, long timeNs);
 
@@ -3525,6 +3528,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private native final void setParameters(@NonNull String[] keys, @NonNull Object[] values);
 
     /**
@@ -3555,6 +3559,7 @@
     private native final MediaCodecInfo getOwnCodecInfo();
 
     @NonNull
+    @UnsupportedAppUsage
     private native final ByteBuffer[] getBuffers(boolean input);
 
     @Nullable
@@ -3575,6 +3580,7 @@
         native_init();
     }
 
+    @UnsupportedAppUsage
     private long mNativeContext;
 
     /** @hide */
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 62d3dea..ef312d1 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Range;
@@ -1588,6 +1589,7 @@
         private VideoCapabilities() { }
 
         /** @hide */
+        @UnsupportedAppUsage
         public static VideoCapabilities create(
                 MediaFormat info, CodecCapabilities parent) {
             VideoCapabilities caps = new VideoCapabilities();
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 3a0a58e..850be78 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.StringDef;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.os.Handler;
 import android.os.Looper;
@@ -1473,6 +1474,7 @@
          * Get the opaque message data
          */
         @NonNull
+        @UnsupportedAppUsage
         public byte[] getData() { return mData; }
 
         /**
@@ -1481,6 +1483,7 @@
          * certificate server URL obtained from other sources.
          */
         @NonNull
+        @UnsupportedAppUsage
         public String getDefaultUrl() { return mDefaultUrl; }
     }
 
@@ -1497,6 +1500,7 @@
      * @hide - not part of the public API at this time
      */
     @NonNull
+    @UnsupportedAppUsage
     public CertificateRequest getCertificateRequest(
             @CertificateType int certType, @NonNull String certAuthority)
     {
@@ -1518,12 +1522,13 @@
          * Get the wrapped private key data
          */
         @NonNull
+        @UnsupportedAppUsage
         public byte[] getWrappedPrivateKey() {
             if (mWrappedKey == null) {
                 // this should never happen as mWrappedKey is initialized in
                 // JNI after construction of the KeyRequest object. The check
                 // is needed here to guarantee @NonNull annotation.
-                throw new RuntimeException("Cerfificate is not initialized");
+                throw new RuntimeException("Certificate is not initialized");
             }
             return mWrappedKey;
         }
@@ -1532,12 +1537,13 @@
          * Get the PEM-encoded certificate chain
          */
         @NonNull
+        @UnsupportedAppUsage
         public byte[] getContent() {
             if (mCertificateData == null) {
                 // this should never happen as mCertificateData is initialized in
                 // JNI after construction of the KeyRequest object. The check
                 // is needed here to guarantee @NonNull annotation.
-                throw new RuntimeException("Cerfificate is not initialized");
+                throw new RuntimeException("Certificate is not initialized");
             }
             return mCertificateData;
         }
@@ -1565,6 +1571,7 @@
      * @hide - not part of the public API at this time
      */
     @NonNull
+    @UnsupportedAppUsage
     public Certificate provideCertificateResponse(@NonNull byte[] response)
             throws DeniedByServerException {
         return provideProvisionResponseNative(response);
@@ -1587,6 +1594,7 @@
      * @hide - not part of the public API at this time
      */
     @NonNull
+    @UnsupportedAppUsage
     public byte[] signRSA(
             @NonNull byte[] sessionId, @NonNull String algorithm,
             @NonNull byte[] wrappedKey, @NonNull byte[] message) {
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 35937de..3b9b6dd 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.media.DecoderCapabilities;
 import android.media.DecoderCapabilities.VideoDecoder;
 import android.media.DecoderCapabilities.AudioDecoder;
@@ -43,7 +44,9 @@
     public static final int FILE_TYPE_AAC     = 8;
     public static final int FILE_TYPE_MKA     = 9;
     public static final int FILE_TYPE_FLAC    = 10;
+    @UnsupportedAppUsage
     private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
+    @UnsupportedAppUsage
     private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_FLAC;
 
     // MIDI file types
@@ -123,7 +126,9 @@
     public static final int FILE_TYPE_ZIP           = 107;
 
     public static class MediaFileType {
+        @UnsupportedAppUsage
         public final int fileType;
+        @UnsupportedAppUsage
         public final String mimeType;
 
         MediaFileType(int fileType, String mimeType) {
@@ -132,20 +137,25 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static final HashMap<String, MediaFileType> sFileTypeMap
             = new HashMap<String, MediaFileType>();
     private static final HashMap<String, Integer> sMimeTypeMap
             = new HashMap<String, Integer>();
     // maps file extension to MTP format code
+    @UnsupportedAppUsage
     private static final HashMap<String, Integer> sFileTypeToFormatMap
             = new HashMap<String, Integer>();
     // maps mime type to MTP format code
+    @UnsupportedAppUsage
     private static final HashMap<String, Integer> sMimeTypeToFormatMap
             = new HashMap<String, Integer>();
     // maps MTP format code to mime type
+    @UnsupportedAppUsage
     private static final HashMap<Integer, String> sFormatToMimeTypeMap
             = new HashMap<Integer, String>();
 
+    @UnsupportedAppUsage
     static void addFileType(String extension, int fileType, String mimeType) {
         sFileTypeMap.put(extension, new MediaFileType(fileType, mimeType));
         sMimeTypeMap.put(mimeType, Integer.valueOf(fileType));
@@ -277,6 +287,7 @@
         addFileType("MPEG", FILE_TYPE_MP2PS, "video/mp2p");
     }
 
+    @UnsupportedAppUsage
     public static boolean isAudioFileType(int fileType) {
         return ((fileType >= FIRST_AUDIO_FILE_TYPE &&
                 fileType <= LAST_AUDIO_FILE_TYPE) ||
@@ -284,6 +295,7 @@
                 fileType <= LAST_MIDI_FILE_TYPE));
     }
 
+    @UnsupportedAppUsage
     public static boolean isVideoFileType(int fileType) {
         return (fileType >= FIRST_VIDEO_FILE_TYPE &&
                 fileType <= LAST_VIDEO_FILE_TYPE)
@@ -291,6 +303,7 @@
                 fileType <= LAST_VIDEO_FILE_TYPE2);
     }
 
+    @UnsupportedAppUsage
     public static boolean isImageFileType(int fileType) {
         return (fileType >= FIRST_IMAGE_FILE_TYPE &&
                 fileType <= LAST_IMAGE_FILE_TYPE)
@@ -303,16 +316,19 @@
                 fileType <= LAST_RAW_IMAGE_FILE_TYPE);
     }
 
+    @UnsupportedAppUsage
     public static boolean isPlayListFileType(int fileType) {
         return (fileType >= FIRST_PLAYLIST_FILE_TYPE &&
                 fileType <= LAST_PLAYLIST_FILE_TYPE);
     }
 
+    @UnsupportedAppUsage
     public static boolean isDrmFileType(int fileType) {
         return (fileType >= FIRST_DRM_FILE_TYPE &&
                 fileType <= LAST_DRM_FILE_TYPE);
     }
 
+    @UnsupportedAppUsage
     public static MediaFileType getFileType(String path) {
         int lastDot = path.lastIndexOf('.');
         if (lastDot < 0)
@@ -327,6 +343,7 @@
     }
 
     // generates a title based on file name
+    @UnsupportedAppUsage
     public static String getFileTitle(String path) {
         // extract file name after last slash
         int lastSlash = path.lastIndexOf('/');
@@ -344,11 +361,13 @@
         return path;
     }
 
+    @UnsupportedAppUsage
     public static int getFileTypeForMimeType(String mimeType) {
         Integer value = sMimeTypeMap.get(mimeType);
         return (value == null ? 0 : value.intValue());
     }
 
+    @UnsupportedAppUsage
     public static String getMimeTypeForFile(String path) {
         MediaFileType mediaFileType = getFileType(path);
         return (mediaFileType == null ? null : mediaFileType.mimeType);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 7c68b55..d10cbbc 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -143,7 +144,7 @@
      * MIME type for HEIF still image data encoded in HEVC.
      *
      * To decode such an image, {@link MediaCodec} decoder for
-     * {@ #MIMETYPE_VIDEO_HEVC} shall be used. The client needs to form
+     * {@link #MIMETYPE_VIDEO_HEVC} shall be used. The client needs to form
      * the correct {@link #MediaFormat} based on additional information in
      * the track format, and send it to {@link MediaCodec#configure}.
      *
@@ -188,6 +189,7 @@
      */
     public static final String MIMETYPE_TEXT_CEA_708 = "text/cea-708";
 
+    @UnsupportedAppUsage
     private Map<String, Object> mMap;
 
     /**
@@ -946,6 +948,7 @@
         mMap = new HashMap();
     }
 
+    @UnsupportedAppUsage
     /* package private */ Map<String, Object> getMap() {
         return mMap;
     }
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index 6bf52bd..ad25a06 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.NetworkUtils;
 import android.os.IBinder;
 import android.os.StrictMode;
@@ -46,20 +47,28 @@
     // connection timeout - 30 sec
     private static final int CONNECT_TIMEOUT_MS = 30 * 1000;
 
+    @UnsupportedAppUsage
     private long mCurrentOffset = -1;
+    @UnsupportedAppUsage
     private URL mURL = null;
+    @UnsupportedAppUsage
     private Map<String, String> mHeaders = null;
+    @UnsupportedAppUsage
     private HttpURLConnection mConnection = null;
+    @UnsupportedAppUsage
     private long mTotalSize = -1;
     private InputStream mInputStream = null;
 
+    @UnsupportedAppUsage
     private boolean mAllowCrossDomainRedirect = true;
+    @UnsupportedAppUsage
     private boolean mAllowCrossProtocolRedirect = true;
 
     // from com.squareup.okhttp.internal.http
     private final static int HTTP_TEMP_REDIRECT = 307;
     private final static int MAX_REDIRECTS = 20;
 
+    @UnsupportedAppUsage
     public MediaHTTPConnection() {
         CookieHandler cookieHandler = CookieHandler.getDefault();
         if (cookieHandler == null) {
@@ -70,6 +79,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public IBinder connect(String uri, String headers) {
         if (VERBOSE) {
             Log.d(TAG, "connect: uri=" + uri + ", headers=" + headers);
@@ -128,6 +138,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void disconnect() {
         teardownConnection();
         mHeaders = null;
@@ -312,6 +323,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public int readAt(long offset, int size) {
         return native_readAt(offset, size);
     }
@@ -381,6 +393,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public synchronized String getMIMEType() {
         if (mConnection == null) {
             try {
@@ -394,6 +407,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public String getUri() {
         return mURL.toString();
     }
diff --git a/media/java/android/media/MediaHTTPService.java b/media/java/android/media/MediaHTTPService.java
index 3a0e58a..97a0df7 100644
--- a/media/java/android/media/MediaHTTPService.java
+++ b/media/java/android/media/MediaHTTPService.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.IBinder;
 import android.util.Log;
 
@@ -28,10 +30,10 @@
 /** @hide */
 public class MediaHTTPService extends IMediaHTTPService.Stub {
     private static final String TAG = "MediaHTTPService";
-    private List<HttpCookie> mCookies;
+    @Nullable private List<HttpCookie> mCookies;
     private Boolean mCookieStoreInitialized = new Boolean(false);
 
-    public MediaHTTPService(List<HttpCookie> cookies) {
+    public MediaHTTPService(@Nullable List<HttpCookie> cookies) {
         mCookies = cookies;
         Log.v(TAG, "MediaHTTPService(" + this + "): Cookies: " + cookies);
     }
@@ -82,6 +84,7 @@
         return new MediaHTTPConnection();
     }
 
+    @UnsupportedAppUsage
     /* package private */static IBinder createHttpServiceBinderIfNecessary(
             String path) {
         return createHttpServiceBinderIfNecessary(path, null);
diff --git a/media/java/android/media/MediaInserter.java b/media/java/android/media/MediaInserter.java
index dd06921..0749f58 100644
--- a/media/java/android/media/MediaInserter.java
+++ b/media/java/android/media/MediaInserter.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProviderClient;
 import android.content.ContentValues;
 import android.net.Uri;
@@ -67,6 +68,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void flushAll() throws RemoteException {
         flushAllPriority();
         for (Uri tableUri : mRowMap.keySet()){
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 94d4d55..2721ad1 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.StringDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -626,6 +627,7 @@
      * @return The key used by this class or null if no mapping exists
      * @hide
      */
+    @UnsupportedAppUsage
     public static String getKeyFromMetadataEditorKey(int editorKey) {
         return EDITOR_KEY_MAPPING.get(editorKey, null);
     }
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index f9a47a6..57b648e 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
@@ -668,6 +669,7 @@
         return getEmbeddedPicture(EMBEDDED_PICTURE_TYPE_ANY);
     }
 
+    @UnsupportedAppUsage
     private native byte[] getEmbeddedPicture(int pictureType);
 
     /**
@@ -675,9 +677,12 @@
      * allocated internally.
      */
     public native void release();
+    @UnsupportedAppUsage
     private native void native_setup();
+    @UnsupportedAppUsage
     private static native void native_init();
 
+    @UnsupportedAppUsage
     private native final void native_finalize();
 
     @Override
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 205ce8d..c91d4d3 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.media.MediaCodec;
 import android.media.MediaCodec.BufferInfo;
 import dalvik.system.CloseGuard;
@@ -283,8 +284,10 @@
     public @interface Format {}
 
     // All the native functions are listed here.
+    @UnsupportedAppUsage
     private static native long nativeSetup(@NonNull FileDescriptor fd, int format)
             throws IllegalArgumentException, IOException;
+    @UnsupportedAppUsage
     private static native void nativeRelease(long nativeObject);
     private static native void nativeStart(long nativeObject);
     private static native void nativeStop(long nativeObject);
@@ -298,16 +301,22 @@
             int offset, int size, long presentationTimeUs, @MediaCodec.BufferFlag int flags);
 
     // Muxer internal states.
+    @UnsupportedAppUsage
     private static final int MUXER_STATE_UNINITIALIZED  = -1;
     private static final int MUXER_STATE_INITIALIZED    = 0;
+    @UnsupportedAppUsage
     private static final int MUXER_STATE_STARTED        = 1;
+    @UnsupportedAppUsage
     private static final int MUXER_STATE_STOPPED        = 2;
 
+    @UnsupportedAppUsage
     private int mState = MUXER_STATE_UNINITIALIZED;
 
+    @UnsupportedAppUsage
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private int mLastTrackIndex = -1;
 
+    @UnsupportedAppUsage
     private long mNativeObject;
 
     /**
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index ada91be..ed4da22 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -597,6 +598,7 @@
        // FIXME: add link to getMetadata(boolean, boolean)
        {@hide}
      */
+    @UnsupportedAppUsage
     public static final boolean METADATA_ALL = false;
 
     /**
@@ -613,6 +615,7 @@
        // FIXME: add link to getMetadata(boolean, boolean)
        {@hide}
      */
+    @UnsupportedAppUsage
     public static final boolean BYPASS_METADATA_FILTER = false;
 
     static {
@@ -630,6 +633,7 @@
     private long mNativeSurfaceTexture;  // accessed by native methods
     private int mListenerContext; // accessed by native methods
     private SurfaceHolder mSurfaceHolder;
+    @UnsupportedAppUsage
     private EventHandler mEventHandler;
     private PowerManager.WakeLock mWakeLock = null;
     private boolean mScreenOnWhilePlaying;
@@ -710,6 +714,7 @@
      * player.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public Parcel newRequest() {
         Parcel parcel = Parcel.obtain();
         parcel.writeInterfaceToken(IMEDIA_PLAYER);
@@ -730,6 +735,7 @@
      * native player.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public void invoke(Parcel request, Parcel reply) {
         int retcode = native_invoke(request, reply);
         reply.setDataPosition(0);
@@ -1139,11 +1145,13 @@
      * @throws IllegalStateException if it is called in an invalid state
      * @hide pending API council
      */
+    @UnsupportedAppUsage
     public void setDataSource(String path, Map<String, String> headers)
             throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
         setDataSource(path, headers, null);
     }
 
+    @UnsupportedAppUsage
     private void setDataSource(String path, Map<String, String> headers, List<HttpCookie> cookies)
             throws IOException, IllegalArgumentException, SecurityException, IllegalStateException
     {
@@ -1164,6 +1172,7 @@
         setDataSource(path, keys, values, cookies);
     }
 
+    @UnsupportedAppUsage
     private void setDataSource(String path, String[] keys, String[] values,
             List<HttpCookie> cookies)
             throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
@@ -2010,6 +2019,7 @@
      // FIXME: unhide.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public Metadata getMetadata(final boolean update_only,
                                 final boolean apply_filter) {
         Parcel reply = Parcel.obtain();
@@ -2234,6 +2244,7 @@
      * @return true if the parameter is set successfully, false otherwise
      * {@hide}
      */
+    @UnsupportedAppUsage
     private native boolean setParameter(int key, Parcel value);
 
     /**
@@ -2510,10 +2521,10 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mTrackType);
+            dest.writeString(mFormat.getString(MediaFormat.KEY_MIME));
             dest.writeString(getLanguage());
 
             if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-                dest.writeString(mFormat.getString(MediaFormat.KEY_MIME));
                 dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_AUTOSELECT));
                 dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_DEFAULT));
                 dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE));
@@ -2550,6 +2561,7 @@
         /**
          * Used to read a TrackInfo from a Parcel.
          */
+        @UnsupportedAppUsage
         static final Parcelable.Creator<TrackInfo> CREATOR
                 = new Parcelable.Creator<TrackInfo>() {
                     @Override
@@ -2660,6 +2672,7 @@
     private SubtitleController mSubtitleController;
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setSubtitleAnchor(
             SubtitleController controller,
             SubtitleController.Anchor anchor) {
@@ -2764,6 +2777,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void addSubtitleSource(InputStream is, MediaFormat format)
             throws IllegalStateException
     {
@@ -3276,6 +3290,7 @@
      *
      * {@hide} pending API council
      */
+    @UnsupportedAppUsage
     public void setRetransmitEndpoint(InetSocketAddress endpoint)
             throws IllegalStateException, IllegalArgumentException
     {
@@ -3327,6 +3342,7 @@
     private TimeProvider mTimeProvider;
 
     /** @hide */
+    @UnsupportedAppUsage
     public MediaTimeProvider getMediaTimeProvider() {
         if (mTimeProvider == null) {
             mTimeProvider = new TimeProvider(this);
@@ -3723,6 +3739,7 @@
         mOnPreparedListener = listener;
     }
 
+    @UnsupportedAppUsage
     private OnPreparedListener mOnPreparedListener;
 
     /**
@@ -3750,6 +3767,7 @@
         mOnCompletionListener = listener;
     }
 
+    @UnsupportedAppUsage
     private OnCompletionListener mOnCompletionListener;
 
     /**
@@ -3822,6 +3840,7 @@
         mOnSeekCompleteListener = listener;
     }
 
+    @UnsupportedAppUsage
     private OnSeekCompleteListener mOnSeekCompleteListener;
 
     /**
@@ -3883,6 +3902,7 @@
         mOnTimedTextListener = listener;
     }
 
+    @UnsupportedAppUsage
     private OnTimedTextListener mOnTimedTextListener;
 
     /**
@@ -4162,6 +4182,7 @@
         mOnErrorListener = listener;
     }
 
+    @UnsupportedAppUsage
     private OnErrorListener mOnErrorListener;
 
 
@@ -4231,6 +4252,7 @@
      *  JAVA framework to avoid triggering track scanning.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int MEDIA_INFO_EXTERNAL_METADATA_UPDATE = 803;
 
     /** Informs that audio is not playing. Note that playback of the video
@@ -4250,6 +4272,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static final int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
 
     /** Subtitle track was not supported by the media framework.
@@ -4306,6 +4329,7 @@
         mOnInfoListener = listener;
     }
 
+    @UnsupportedAppUsage
     private OnInfoListener mOnInfoListener;
 
     // Modular DRM begin
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 70ef81f..aa78b0d 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -20,6 +20,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.SurfaceTexture;
 import android.net.Uri;
@@ -711,6 +712,12 @@
     public abstract void setNextDataSources(@NonNull List<DataSourceDesc> dsds);
 
     /**
+     * Removes all data sources pending to be played.
+     */
+    // This is an asynchronous call.
+    public abstract void clearNextDataSources();
+
+    /**
      * Gets the current data source as described by a DataSourceDesc.
      *
      * @return the current DataSourceDesc
@@ -787,7 +794,7 @@
      * {@code EventCallback.onCommandLabelReached} will be fired with the
      * given {@code label}.
      *
-     * @see android.media.MediaPlayer2.EventCallback#onCommandLabelReached
+     * @see EventCallback#onCommandLabelReached
      *
      * @param label An application specific Object used to help to identify the completeness
      * of a batch of commands.
@@ -883,15 +890,6 @@
     // This is a synchronous call.
     public abstract void clearPendingCommands();
 
-    /**
-     * Stops playback after playback has been started or paused.
-     *
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
-     * @hide
-     */
-    public void stop() { }
-
     //--------------------------------------------------------------------------
     // Explicit Routing
     //--------------------
@@ -1387,13 +1385,14 @@
     /**
      * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata.
      *
-     * @see android.media.MediaPlayer2#getTrackInfo
+     * @see MediaPlayer2#getTrackInfo
      */
     public abstract static class TrackInfo {
         /**
          * Gets the track type.
          * @return TrackType which indicates if the track is video, audio, timed text.
          */
+        @UnsupportedAppUsage
         public abstract int getTrackType();
 
         /**
@@ -1402,6 +1401,7 @@
          * When the language is unknown or could not be determined,
          * ISO-639-2 language code, "und", is returned.
          */
+        @UnsupportedAppUsage
         public abstract String getLanguage();
 
         /**
@@ -1594,7 +1594,7 @@
      * each individual track can be found by calling {@link #getTrackInfo()} method.
      * @throws IllegalStateException if called in an invalid state.
      *
-     * @see android.media.MediaPlayer2#getTrackInfo
+     * @see MediaPlayer2#getTrackInfo
      */
     // This is an asynchronous call.
     public abstract void selectTrack(int index);
@@ -1611,7 +1611,7 @@
      * each individual track can be found by calling {@link #getTrackInfo()} method.
      * @throws IllegalStateException if called in an invalid state.
      *
-     * @see android.media.MediaPlayer2#getTrackInfo
+     * @see MediaPlayer2#getTrackInfo
      */
     // This is an asynchronous call.
     public abstract void deselectTrack(int index);
@@ -1714,7 +1714,7 @@
          * @param dsd the DataSourceDesc of this data source
          * @param timestamp the new media clock.
          */
-        public void onMediaTimeChanged(
+        public void onMediaTimeDiscontinuity(
                 MediaPlayer2 mp, DataSourceDesc dsd, MediaTimestamp timestamp) { }
 
         /**
@@ -1725,58 +1725,48 @@
          *        {@link #notifyWhenCommandLabelReached(Object)}.
          */
         public void onCommandLabelReached(MediaPlayer2 mp, @NonNull Object label) { }
+
+        /**
+         * Called when when a player subtitle track has new subtitle data available.
+         * @param mp the player that reports the new subtitle data
+         * @param dsd the DataSourceDesc of this data source
+         * @param data the subtitle data
+         */
+        public void onSubtitleData(
+                MediaPlayer2 mp, DataSourceDesc dsd, @NonNull SubtitleData data) { }
     }
 
     /**
      * Sets the callback to be invoked when the media source is ready for playback.
      *
-     * @param eventCallback the callback that will be run
      * @param executor the executor through which the callback should be invoked
+     * @param eventCallback the callback that will be run
      */
     // This is a synchronous call.
-    public abstract void setEventCallback(@NonNull @CallbackExecutor Executor executor,
+    public abstract void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull EventCallback eventCallback);
 
     /**
-     * Clears the {@link EventCallback}.
+     * Unregisters the {@link EventCallback}.
+     *
+     * @param eventCallback the callback to be unregistered
      */
     // This is a synchronous call.
-    public abstract void clearEventCallback();
-
-    /**
-     * Interface definition of a callback to be invoked when a
-     * track has data available.
-     *
-     * @hide
-     */
-    public interface OnSubtitleDataListener
-    {
-        public void onSubtitleData(MediaPlayer2 mp, SubtitleData data);
-    }
-
-    /**
-     * Register a callback to be invoked when a track has data available.
-     *
-     * @param listener the callback that will be run
-     *
-     * @hide
-     */
-    // This is a synchronous call.
-    public void setOnSubtitleDataListener(OnSubtitleDataListener listener) { }
+    public abstract void unregisterEventCallback(EventCallback eventCallback);
 
 
     /* Do not change these values without updating their counterparts
      * in include/media/mediaplayer2.h!
      */
     /** Unspecified media player error.
-     * @see android.media.MediaPlayer2.EventCallback#onError
+     * @see EventCallback#onError
      */
     public static final int MEDIA_ERROR_UNKNOWN = 1;
 
     /** The video is streamed and its container is not valid for progressive
      * playback i.e the video's index (e.g moov atom) is not at the start of the
      * file.
-     * @see android.media.MediaPlayer2.EventCallback#onError
+     * @see EventCallback#onError
      */
     public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;
 
@@ -1792,7 +1782,7 @@
 
     /** Unspecified low-level system error. This value originated from UNKNOWN_ERROR in
      * system/core/include/utils/Errors.h
-     * @see android.media.MediaPlayer2.EventCallback#onError
+     * @see EventCallback#onError
      * @hide
      */
     public static final int MEDIA_ERROR_SYSTEM = -2147483648;
@@ -1813,65 +1803,71 @@
     public @interface MediaError {}
 
     /* Do not change these values without updating their counterparts
-     * in include/media/mediaplayer2.h!
+     * in include/media/MediaPlayer2Types.h!
      */
     /** Unspecified media player info.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_UNKNOWN = 1;
 
-    /** The player switched to this datas source because it is the
-     * next-to-be-played in the playlist.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+    /** The player just started the playback of this datas source.
+     * @see EventCallback#onInfo
      */
-    public static final int MEDIA_INFO_STARTED_AS_NEXT = 2;
+    public static final int MEDIA_INFO_DATA_SOURCE_START = 2;
 
     /** The player just pushed the very first video frame for rendering.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3;
 
     /** The player just rendered the very first audio sample.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_AUDIO_RENDERING_START = 4;
 
     /** The player just completed the playback of this data source.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
-    public static final int MEDIA_INFO_PLAYBACK_COMPLETE = 5;
+    public static final int MEDIA_INFO_DATA_SOURCE_END = 5;
 
-    /** The player just completed the playback of the full playlist.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+    /** The player just completed the playback of all data sources set by {@link #setDataSource},
+     * {@link #setNextDataSource} and {@link #setNextDataSources}.
+     * @see EventCallback#onInfo
      */
-    public static final int MEDIA_INFO_PLAYLIST_END = 6;
+    public static final int MEDIA_INFO_DATA_SOURCE_LIST_END = 6;
+
+    /** The player just completed an iteration of playback loop. This event is sent only when
+     *  looping is enabled by {@link #loopCurrent}.
+     * @see EventCallback#onInfo
+     */
+    public static final int MEDIA_INFO_DATA_SOURCE_REPEAT = 7;
 
     /** The player just prepared a data source.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_PREPARED = 100;
 
     /** The video is too complex for the decoder: it can't decode frames fast
      *  enough. Possibly only the audio plays fine at this stage.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;
 
     /** MediaPlayer2 is temporarily pausing playback internally in order to
      * buffer more data.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_BUFFERING_START = 701;
 
     /** MediaPlayer2 is resuming playback after filling buffers.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_BUFFERING_END = 702;
 
     /** Estimated network bandwidth information (kbps) is available; currently this event fires
      * simultaneously as {@link #MEDIA_INFO_BUFFERING_START} and {@link #MEDIA_INFO_BUFFERING_END}
      * when playing network files.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      * @hide
      */
     public static final int MEDIA_INFO_NETWORK_BANDWIDTH = 703;
@@ -1885,24 +1881,24 @@
      *
      * The {@code extra} parameter in {@code EventCallback.onInfo} is the
      * percentage (0-100) of the content that has been buffered or played thus far.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_BUFFERING_UPDATE = 704;
 
     /** Bad interleaving means that a media has been improperly interleaved or
      * not interleaved at all, e.g has all the video samples first then all the
      * audio ones. Video is playing but a lot of disk seeks may be happening.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_BAD_INTERLEAVING = 800;
 
     /** The media cannot be seeked (e.g live stream)
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_NOT_SEEKABLE = 801;
 
     /** A new set of metadata is available.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_METADATA_UPDATE = 802;
 
@@ -1914,30 +1910,30 @@
 
     /** Informs that audio is not playing. Note that playback of the video
      * is not interrupted.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804;
 
     /** Informs that video is not playing. Note that playback of the audio
      * is not interrupted.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805;
 
     /** Failed to handle timed text track properly.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      *
      * {@hide}
      */
     public static final int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
 
     /** Subtitle track was not supported by the media framework.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;
 
     /** Reading the subtitle track takes too long.
-     * @see android.media.MediaPlayer2.EventCallback#onInfo
+     * @see EventCallback#onInfo
      */
     public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;
 
@@ -1946,11 +1942,11 @@
      */
     @IntDef(flag = false, prefix = "MEDIA_INFO", value = {
             MEDIA_INFO_UNKNOWN,
-            MEDIA_INFO_STARTED_AS_NEXT,
+            MEDIA_INFO_DATA_SOURCE_START,
             MEDIA_INFO_VIDEO_RENDERING_START,
             MEDIA_INFO_AUDIO_RENDERING_START,
-            MEDIA_INFO_PLAYBACK_COMPLETE,
-            MEDIA_INFO_PLAYLIST_END,
+            MEDIA_INFO_DATA_SOURCE_END,
+            MEDIA_INFO_DATA_SOURCE_LIST_END,
             MEDIA_INFO_PREPARED,
             MEDIA_INFO_VIDEO_TRACK_LAGGING,
             MEDIA_INFO_BUFFERING_START,
@@ -1972,129 +1968,129 @@
 
     //--------------------------------------------------------------------------
     /** The player just completed a call {@link #attachAuxEffect}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_ATTACH_AUX_EFFECT = 1;
 
     /** The player just completed a call {@link #deselectTrack}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_DESELECT_TRACK = 2;
 
     /** The player just completed a call {@link #loopCurrent}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_LOOP_CURRENT = 3;
 
     /** The player just completed a call {@link #pause}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_PAUSE = 4;
 
     /** The player just completed a call {@link #play}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_PLAY = 5;
 
     /** The player just completed a call {@link #prepare}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_PREPARE = 6;
 
     /** The player just completed a call {@link #releaseDrm}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_RELEASE_DRM = 12;
 
     /** The player just completed a call {@link #restoreDrmKeys}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_RESTORE_DRM_KEYS = 13;
 
     /** The player just completed a call {@link #seekTo}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SEEK_TO = 14;
 
     /** The player just completed a call {@link #selectTrack}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SELECT_TRACK = 15;
 
     /** The player just completed a call {@link #setAudioAttributes}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_AUDIO_ATTRIBUTES = 16;
 
     /** The player just completed a call {@link #setAudioSessionId}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_AUDIO_SESSION_ID = 17;
 
     /** The player just completed a call {@link #setAuxEffectSendLevel}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL = 18;
 
     /** The player just completed a call {@link #setDataSource}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_DATA_SOURCE = 19;
 
     /** The player just completed a call {@link #setNextDataSource}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_NEXT_DATA_SOURCE = 22;
 
     /** The player just completed a call {@link #setNextDataSources}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_NEXT_DATA_SOURCES = 23;
 
     /** The player just completed a call {@link #setPlaybackParams}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_PLAYBACK_PARAMS = 24;
 
-    /** The player just completed a call {@link #setPlaybackSpeed}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
-     */
-    public static final int CALL_COMPLETED_SET_PLAYBACK_SPEED = 25;
-
     /** The player just completed a call {@link #setPlayerVolume}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_PLAYER_VOLUME = 26;
 
     /** The player just completed a call {@link #setSurface}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_SURFACE = 27;
 
     /** The player just completed a call {@link #setSyncParams}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SET_SYNC_PARAMS = 28;
 
     /** The player just completed a call {@link #skipToNext}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_COMPLETED_SKIP_TO_NEXT = 29;
 
+    /** The player just completed a call {@link #clearNextDataSources}.
+     * @see EventCallback#onCallCompleted
+     */
+    public static final int CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES = 30;
+
     /** The player just completed a call {@link #setBufferingParams}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      * @hide
      */
     public static final int CALL_COMPLETED_SET_BUFFERING_PARAMS = 1001;
 
     /** The player just completed a call {@code setVideoScalingMode}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      * @hide
      */
     public static final int CALL_COMPLETED_SET_VIDEO_SCALING_MODE = 1002;
 
     /** The player just completed a call {@code notifyWhenCommandLabelReached}.
-     * @see android.media.MediaPlayer2.EventCallback#onCommandLabelReached
+     * @see EventCallback#onCommandLabelReached
      * @hide
      */
     public static final int CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED = 1003;
@@ -2124,6 +2120,7 @@
             CALL_COMPLETED_SET_SURFACE,
             CALL_COMPLETED_SET_SYNC_PARAMS,
             CALL_COMPLETED_SKIP_TO_NEXT,
+            CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES,
             CALL_COMPLETED_SET_BUFFERING_PARAMS,
             CALL_COMPLETED_SET_VIDEO_SCALING_MODE,
             CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED
@@ -2132,40 +2129,46 @@
     public @interface CallCompleted {}
 
     /** Status code represents that call is completed without an error.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_STATUS_NO_ERROR = 0;
 
     /** Status code represents that call is ended with an unknown error.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_STATUS_ERROR_UNKNOWN = Integer.MIN_VALUE;
 
     /** Status code represents that the player is not in valid state for the operation.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_STATUS_INVALID_OPERATION = 1;
 
     /** Status code represents that the argument is illegal.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_STATUS_BAD_VALUE = 2;
 
     /** Status code represents that the operation is not allowed.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_STATUS_PERMISSION_DENIED = 3;
 
     /** Status code represents a file or network related operation error.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
     public static final int CALL_STATUS_ERROR_IO = 4;
 
+    /** Status code represents that the call has been skipped. For example, a {@link #seekTo}
+     * request may be skipped if it is followed by another {@link #seekTo} request.
+     * @see EventCallback#onCallCompleted
+     */
+    public static final int CALL_STATUS_SKIPPED = 5;
+
     /** Status code represents that DRM operation is called before preparing a DRM scheme through
      *  {@link #prepareDrm}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
+     * @see EventCallback#onCallCompleted
      */
-    public static final int CALL_STATUS_NO_DRM_SCHEME = 5;
+    public static final int CALL_STATUS_NO_DRM_SCHEME = 6;
 
     /**
      * @hide
@@ -2177,6 +2180,7 @@
             CALL_STATUS_BAD_VALUE,
             CALL_STATUS_PERMISSION_DENIED,
             CALL_STATUS_ERROR_IO,
+            CALL_STATUS_SKIPPED,
             CALL_STATUS_NO_DRM_SCHEME})
     @Retention(RetentionPolicy.SOURCE)
     public @interface CallStatus {}
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 2b61b2e..c06b97b 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -97,7 +97,6 @@
     private long mNativeSurfaceTexture;  // accessed by native methods
     private int mListenerContext; // accessed by native methods
     private SurfaceHolder mSurfaceHolder;
-    private EventHandler mEventHandler;
     private PowerManager.WakeLock mWakeLock = null;
     private boolean mScreenOnWhilePlaying;
     private boolean mStayAwake;
@@ -135,7 +134,7 @@
     //--- guarded by |mDrmLock| end
 
     private HandlerThread mHandlerThread;
-    private final Handler mTaskHandler;
+    private final TaskHandler mTaskHandler;
     private final Object mTaskLock = new Object();
     @GuardedBy("mTaskLock")
     private final List<Task> mPendingTasks = new LinkedList<>();
@@ -149,19 +148,10 @@
      * result in an exception.</p>
      */
     public MediaPlayer2Impl() {
-        Looper looper;
-        if ((looper = Looper.myLooper()) != null) {
-            mEventHandler = new EventHandler(this, looper);
-        } else if ((looper = Looper.getMainLooper()) != null) {
-            mEventHandler = new EventHandler(this, looper);
-        } else {
-            mEventHandler = null;
-        }
-
         mHandlerThread = new HandlerThread("MediaPlayer2TaskThread");
         mHandlerThread.start();
-        looper = mHandlerThread.getLooper();
-        mTaskHandler = new Handler(looper);
+        Looper looper = mHandlerThread.getLooper();
+        mTaskHandler = new TaskHandler(this, looper);
 
         mTimeProvider = new TimeProvider(this);
         mOpenSubtitleSources = new Vector<InputStream>();
@@ -213,8 +203,6 @@
      * playback will continue from where it was paused. If playback had
      * been stopped, or never started before, playback will start at the
      * beginning.
-     *
-     * @throws IllegalStateException if it is called in an invalid state
      */
     @Override
     public void play() {
@@ -236,8 +224,6 @@
      * call prepare(). For streams, you should call prepare(),
      * which returns immediately, rather than blocking until enough data has been
      * buffered.
-     *
-     * @throws IllegalStateException if it is called in an invalid state
      */
     @Override
     public void prepare() {
@@ -253,9 +239,6 @@
 
     /**
      * Pauses playback. Call play() to resume.
-     *
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
      */
     @Override
     public void pause() {
@@ -263,6 +246,22 @@
             @Override
             void process() {
                 stayAwake(false);
+
+                // TODO: remove this block when native code allows prepared -> pause
+                // and sends MEDIA_INFO_DATA_SOURCE_START when pipeline is created.
+                if (getState() == PLAYER_STATE_PREPARED) {
+                    final DataSourceDesc dsd;
+                    synchronized (mSrcLock) {
+                        dsd = mCurrentDSD;
+                    }
+                    synchronized (mEventCbLock) {
+                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                            cb.first.execute(() -> cb.second.onInfo(
+                                    MediaPlayer2Impl.this, dsd, MEDIA_INFO_DATA_SOURCE_START, 0));
+                        }
+                    }
+                }
+
                 _pause();
             }
         });
@@ -361,23 +360,22 @@
      * Sets the data source as described by a DataSourceDesc.
      *
      * @param dsd the descriptor of data source you want to play
-     * @throws IllegalStateException if it is called in an invalid state
-     * @throws NullPointerException if dsd is null
      */
     @Override
     public void setDataSource(@NonNull DataSourceDesc dsd) {
         addTask(new Task(CALL_COMPLETED_SET_DATA_SOURCE, false) {
             @Override
-            void process() {
-                Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
-                // TODO: setDataSource could update exist data source
+            void process() throws IOException {
+                Preconditions.checkArgument(dsd != null, "the DataSourceDesc cannot be null");
+                int state = getState();
+                if (state != PLAYER_STATE_ERROR && state != PLAYER_STATE_IDLE) {
+                    throw new IllegalStateException("called in wrong state " + state);
+                }
+
                 synchronized (mSrcLock) {
                     mCurrentDSD = dsd;
                     mCurrentSrcId = mSrcIdGenerator++;
-                    try {
-                        handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId);
-                    } catch (IOException e) {
-                    }
+                    handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId);
                 }
             }
         });
@@ -388,28 +386,20 @@
      * after current data source is finished.
      *
      * @param dsd the descriptor of data source you want to play after current one
-     * @throws IllegalStateException if it is called in an invalid state
-     * @throws NullPointerException if dsd is null
      */
     @Override
     public void setNextDataSource(@NonNull DataSourceDesc dsd) {
         addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCE, false) {
             @Override
             void process() {
-                Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
+                Preconditions.checkArgument(dsd != null, "the DataSourceDesc cannot be null");
                 synchronized (mSrcLock) {
                     mNextDSDs = new ArrayList<DataSourceDesc>(1);
                     mNextDSDs.add(dsd);
                     mNextSrcId = mSrcIdGenerator++;
                     mNextSourceState = NEXT_SOURCE_STATE_INIT;
-                    mNextSourcePlayPending = false;
                 }
-                int state = getState();
-                if (state != PLAYER_STATE_IDLE) {
-                    synchronized (mSrcLock) {
-                        prepareNextDataSource_l();
-                    }
-                }
+                prepareNextDataSource();
             }
         });
     }
@@ -418,8 +408,6 @@
      * Sets a list of data sources to be played sequentially after current data source is done.
      *
      * @param dsds the list of data sources you want to play after current one
-     * @throws IllegalStateException if it is called in an invalid state
-     * @throws IllegalArgumentException if dsds is null or empty, or contains null DataSourceDesc
      */
     @Override
     public void setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
@@ -440,13 +428,24 @@
                     mNextDSDs = new ArrayList(dsds);
                     mNextSrcId = mSrcIdGenerator++;
                     mNextSourceState = NEXT_SOURCE_STATE_INIT;
-                    mNextSourcePlayPending = false;
                 }
-                int state = getState();
-                if (state != PLAYER_STATE_IDLE) {
-                    synchronized (mSrcLock) {
-                        prepareNextDataSource_l();
+                prepareNextDataSource();
+            }
+        });
+    }
+
+    @Override
+    public void clearNextDataSources() {
+        addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) {
+            @Override
+            void process() {
+                synchronized (mSrcLock) {
+                    if (mNextDSDs != null) {
+                        mNextDSDs.clear();
+                        mNextDSDs = null;
                     }
+                    mNextSrcId = mSrcIdGenerator++;
+                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
                 }
             }
         });
@@ -922,67 +921,100 @@
     private native void nativeHandleDataSourceCallback(
             boolean isCurrent, long srcId, Media2DataSource dataSource);
 
-    // This function shall be called with |mSrcLock| acquired.
-    private void prepareNextDataSource_l() {
-        if (mNextDSDs == null || mNextDSDs.isEmpty()
-                || mNextSourceState != NEXT_SOURCE_STATE_INIT) {
-            // There is no next source or it's in preparing or prepared state.
-            return;
+    /**
+     * @return true if there is a next data source, false otherwise.
+     */
+    // This function should be always called on |mHandlerThread|.
+    private boolean prepareNextDataSource() {
+        if (Looper.myLooper() != mHandlerThread.getLooper()) {
+            Log.e(TAG, "prepareNextDataSource: called on wrong looper");
         }
 
-        try {
-            mNextSourceState = NEXT_SOURCE_STATE_PREPARING;
-            handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId);
-        } catch (Exception e) {
-            Message msg2 = mEventHandler.obtainMessage(
-                    MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
-            final long nextSrcId = mNextSrcId;
-            mEventHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mEventHandler.handleMessage(msg2, nextSrcId);
-                }
-            });
+        boolean hasNextDSD;
+        synchronized (mSrcLock) {
+            hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty());
         }
+
+        int state = getState();
+        if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) {
+            // Current source has not been prepared yet.
+            return hasNextDSD;
+        }
+
+        synchronized (mSrcLock) {
+            if (!hasNextDSD || mNextSourceState != NEXT_SOURCE_STATE_INIT) {
+                // There is no next source or it's in preparing or prepared state.
+                return hasNextDSD;
+            }
+
+            try {
+                mNextSourceState = NEXT_SOURCE_STATE_PREPARING;
+                handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId);
+            } catch (Exception e) {
+                Message msg = mTaskHandler.obtainMessage(
+                        MEDIA_ERROR, MEDIA_ERROR_IO, MEDIA_ERROR_UNKNOWN, null);
+                mTaskHandler.handleMessage(msg, mNextSrcId);
+
+                mNextDSDs.remove(0);
+                // make a new SrcId to obsolete notification for previous one.
+                mNextSrcId = mSrcIdGenerator++;
+                mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                return prepareNextDataSource();
+            }
+        }
+        return hasNextDSD;
     }
 
-    // This function shall be called with |mSrcLock| acquired.
-    private void playNextDataSource_l() {
-        if (mNextDSDs == null || mNextDSDs.isEmpty()) {
-            return;
+    // This function should be always called on |mHandlerThread|.
+    private void playNextDataSource() {
+        if (Looper.myLooper() != mHandlerThread.getLooper()) {
+            Log.e(TAG, "playNextDataSource: called on wrong looper");
         }
 
-        if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
-            // Switch to next source only when it's in prepared state.
-            mCurrentDSD = mNextDSDs.get(0);
-            mCurrentSrcId = mNextSrcId;
-            mBufferedPercentageCurrent.set(mBufferedPercentageNext.get());
-            mNextDSDs.remove(0);
-            mNextSrcId = mSrcIdGenerator++;  // make it different from mCurrentSrcId
-            mBufferedPercentageNext.set(0);
-            mNextSourceState = NEXT_SOURCE_STATE_INIT;
-            mNextSourcePlayPending = false;
+        boolean hasNextDSD = false;
+        synchronized (mSrcLock) {
+            if (mNextDSDs != null && !mNextDSDs.isEmpty()) {
+                hasNextDSD = true;
+                if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
+                    // Switch to next source only when it has been prepared.
+                    mCurrentDSD = mNextDSDs.get(0);
+                    mCurrentSrcId = mNextSrcId;
+                    mBufferedPercentageCurrent.set(mBufferedPercentageNext.get());
+                    mNextDSDs.remove(0);
+                    mNextSrcId = mSrcIdGenerator++;  // make it different from |mCurrentSrcId|
+                    mBufferedPercentageNext.set(0);
+                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
 
-            long srcId = mCurrentSrcId;
-            try {
-                nativePlayNextDataSource(srcId);
-            } catch (Exception e) {
-                Message msg2 = mEventHandler.obtainMessage(
-                        MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
-                mEventHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        mEventHandler.handleMessage(msg2, srcId);
+                    long srcId = mCurrentSrcId;
+                    try {
+                        nativePlayNextDataSource(srcId);
+                    } catch (Exception e) {
+                        Message msg2 = mTaskHandler.obtainMessage(
+                                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
+                        mTaskHandler.handleMessage(msg2, srcId);
+                        // Keep |mNextSourcePlayPending|
+                        hasNextDSD = prepareNextDataSource();
                     }
-                });
-            }
+                    if (hasNextDSD) {
+                        stayAwake(true);
 
-            // Wait for MEDIA2_INFO_STARTED_AS_NEXT to prepare next source.
-        } else {
-            if (mNextSourceState == NEXT_SOURCE_STATE_INIT) {
-                prepareNextDataSource_l();
+                        // Now a new current src is playing.
+                        // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source.
+                        mNextSourcePlayPending = false;
+                    }
+                } else if (mNextSourceState == NEXT_SOURCE_STATE_INIT) {
+                    hasNextDSD = prepareNextDataSource();
+                }
             }
-            mNextSourcePlayPending = true;
+        }
+
+        if (!hasNextDSD) {
+            synchronized (mEventCbLock) {
+                for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                    cb.first.execute(() -> cb.second.onInfo(
+                            MediaPlayer2Impl.this, null, MEDIA_INFO_DATA_SOURCE_LIST_END, 0));
+                }
+            }
         }
     }
 
@@ -998,20 +1030,6 @@
 
     private native int _getAudioStreamType() throws IllegalStateException;
 
-    /**
-     * Stops playback after playback has been started or paused.
-     *
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
-     * #hide
-     */
-    @Override
-    public void stop() {
-        stayAwake(false);
-        _stop();
-    }
-
-    private native void _stop() throws IllegalStateException;
 
     //--------------------------------------------------------------------------
     // Explicit Routing
@@ -1109,7 +1127,7 @@
                 enableNativeRoutingCallbacksLocked(true);
                 mRoutingChangeListeners.put(
                         listener, new NativeRoutingEventHandlerDelegate(this, listener,
-                                handler != null ? handler : mEventHandler));
+                                handler != null ? handler : mTaskHandler));
             }
         }
     }
@@ -1306,7 +1324,7 @@
         addTask(new Task(CALL_COMPLETED_SET_BUFFERING_PARAMS, false) {
             @Override
             void process() {
-                Preconditions.checkNotNull(params, "the BufferingParams cannot be null");
+                Preconditions.checkArgument(params != null, "the BufferingParams cannot be null");
                 _setBufferingParams(params);
             }
         });
@@ -1370,7 +1388,7 @@
         addTask(new Task(CALL_COMPLETED_SET_PLAYBACK_PARAMS, false) {
             @Override
             void process() {
-                Preconditions.checkNotNull(params, "the PlaybackParams cannot be null");
+                Preconditions.checkArgument(params != null, "the PlaybackParams cannot be null");
                 _setPlaybackParams(params);
             }
         });
@@ -1403,7 +1421,7 @@
         addTask(new Task(CALL_COMPLETED_SET_SYNC_PARAMS, false) {
             @Override
             void process() {
-                Preconditions.checkNotNull(params, "the SyncParams cannot be null");
+                Preconditions.checkArgument(params != null, "the SyncParams cannot be null");
                 _setSyncParams(params);
             }
         });
@@ -1629,12 +1647,20 @@
         synchronized (mDrmEventCbLock) {
             mDrmEventCallbackRecords.clear();
         }
+        synchronized (mSrcLock) {
+            if (mNextDSDs != null) {
+                mNextDSDs.clear();
+                mNextDSDs = null;
+            }
+            mNextSrcId = mSrcIdGenerator++;
+            mNextSourceState = NEXT_SOURCE_STATE_INIT;
+        }
 
         stayAwake(false);
         _reset();
         // make sure none of the listeners get called anymore
-        if (mEventHandler != null) {
-            mEventHandler.removeCallbacksAndMessages(null);
+        if (mTaskHandler != null) {
+            mTaskHandler.removeCallbacksAndMessages(null);
         }
 
         synchronized (mIndexTrackPairs) {
@@ -2059,9 +2085,9 @@
     private int mSelectedSubtitleTrackIndex = -1;
     private Vector<InputStream> mOpenSubtitleSources;
 
-    private OnSubtitleDataListener mSubtitleDataListener = new OnSubtitleDataListener() {
+    private EventCallback mSubtitleDataCallback = new EventCallback() {
         @Override
-        public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
+        public void onSubtitleData(MediaPlayer2 mp, DataSourceDesc dsd, SubtitleData data) {
             int index = data.getTrackIndex();
             synchronized (mIndexTrackPairs) {
                 for (Pair<Integer, SubtitleTrack> p : mIndexTrackPairs) {
@@ -2085,7 +2111,7 @@
             }
             mSelectedSubtitleTrackIndex = -1;
         }
-        setOnSubtitleDataListener(null);
+        unregisterEventCallback(mSubtitleDataCallback);
         if (track == null) {
             return;
         }
@@ -2105,7 +2131,8 @@
                 selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, true);
             } catch (IllegalStateException e) {
             }
-            setOnSubtitleDataListener(mSubtitleDataListener);
+            final Executor executor = (runnable) -> mTaskHandler.post(runnable);
+            registerEventCallback(executor, mSubtitleDataCallback);
         }
         // no need to select out-of-band tracks
     }
@@ -2167,9 +2194,9 @@
 
             public void run() {
                 int res = addTrack();
-                if (mEventHandler != null) {
-                    Message m = mEventHandler.obtainMessage(MEDIA_INFO, res, 0, null);
-                    mEventHandler.sendMessage(m);
+                if (mTaskHandler != null) {
+                    Message m = mTaskHandler.obtainMessage(MEDIA_INFO, res, 0, null);
+                    mTaskHandler.sendMessage(m);
                 }
                 thread.getLooper().quitSafely();
             }
@@ -2357,7 +2384,7 @@
         if (!mSubtitleController.hasRendererFor(fFormat)) {
             // test and add not atomic
             Context context = ActivityThread.currentApplication();
-            mSubtitleController.registerRenderer(new SRTRenderer(context, mEventHandler));
+            mSubtitleController.registerRenderer(new SRTRenderer(context, mTaskHandler));
         }
         final SubtitleTrack track = mSubtitleController.addTrack(fFormat);
         synchronized (mIndexTrackPairs) {
@@ -2410,9 +2437,9 @@
 
             public void run() {
                 int res = addTrack();
-                if (mEventHandler != null) {
-                    Message m = mEventHandler.obtainMessage(MEDIA_INFO, res, 0, null);
-                    mEventHandler.sendMessage(m);
+                if (mTaskHandler != null) {
+                    Message m = mTaskHandler.obtainMessage(MEDIA_INFO, res, 0, null);
+                    mTaskHandler.sendMessage(m);
                 }
                 thread.getLooper().quitSafely();
             }
@@ -2628,7 +2655,6 @@
             mTimeProvider.close();
             mTimeProvider = null;
         }
-        mOnSubtitleDataListener = null;
 
         // Modular DRM clean up
         mOnDrmConfigHelper = null;
@@ -2675,10 +2701,10 @@
         return mTimeProvider;
     }
 
-    private class EventHandler extends Handler {
+    private class TaskHandler extends Handler {
         private MediaPlayer2Impl mMediaPlayer;
 
-        public EventHandler(MediaPlayer2Impl mp, Looper looper) {
+        public TaskHandler(MediaPlayer2Impl mp, Looper looper) {
             super(looper);
             mMediaPlayer = mp;
         }
@@ -2696,6 +2722,21 @@
             final int what = msg.arg1;
             final int extra = msg.arg2;
 
+            final DataSourceDesc dsd;
+            boolean isCurrentSrcId = false;
+            boolean isNextSrcId = false;
+            synchronized (mSrcLock) {
+                if (srcId == mCurrentSrcId) {
+                    dsd = mCurrentDSD;
+                    isCurrentSrcId = true;
+                } else if (mNextDSDs != null && !mNextDSDs.isEmpty() && srcId == mNextSrcId) {
+                    dsd = mNextDSDs.get(0);
+                    isNextSrcId = true;
+                } else {
+                    return;
+                }
+            }
+
             switch(msg.what) {
             case MEDIA_PREPARED:
             {
@@ -2710,25 +2751,6 @@
                     sendMessage(msg2);
                 }
 
-                final DataSourceDesc dsd;
-                synchronized (mSrcLock) {
-                    Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
-                            + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
-                    if (srcId == mCurrentSrcId) {
-                        dsd = mCurrentDSD;
-                        prepareNextDataSource_l();
-                    } else if (mNextDSDs != null && !mNextDSDs.isEmpty()
-                            && srcId == mNextSrcId) {
-                        dsd = mNextDSDs.get(0);
-                        mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
-                        if (mNextSourcePlayPending) {
-                            playNextDataSource_l();
-                        }
-                    } else {
-                        dsd = null;
-                    }
-                }
-
                 if (dsd != null) {
                     synchronized (mEventCbLock) {
                         for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
@@ -2737,6 +2759,21 @@
                         }
                     }
                 }
+
+                synchronized (mSrcLock) {
+                    Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
+                            + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
+
+                    if (isCurrentSrcId) {
+                        prepareNextDataSource();
+                    } else if (isNextSrcId) {
+                        mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
+                        if (mNextSourcePlayPending) {
+                            playNextDataSource();
+                        }
+                    }
+                }
+
                 synchronized (mTaskLock) {
                     if (mCurrentTask != null
                             && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
@@ -2771,7 +2808,7 @@
                         synchronized (mEventCbLock) {
                             for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
                                 cb.first.execute(() -> cb.second.onDrmInfo(
-                                        mMediaPlayer, mCurrentDSD, drmInfo));
+                                        mMediaPlayer, dsd, drmInfo));
                             }
                         }
                     }
@@ -2783,22 +2820,25 @@
 
             case MEDIA_PLAYBACK_COMPLETE:
             {
-                final DataSourceDesc dsd = mCurrentDSD;
-                synchronized (mSrcLock) {
-                    if (srcId == mCurrentSrcId) {
+                if (isCurrentSrcId) {
+                    synchronized (mEventCbLock) {
+                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                            cb.first.execute(() -> cb.second.onInfo(
+                                    mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0));
+                        }
+                    }
+                    stayAwake(false);
+
+                    synchronized (mSrcLock) {
+                        mNextSourcePlayPending = true;
+
                         Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
                                 + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
-                        playNextDataSource_l();
                     }
+
+                    playNextDataSource();
                 }
 
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
-                    }
-                }
-                stayAwake(false);
                 return;
             }
 
@@ -2825,21 +2865,18 @@
             {
                 final int percent = msg.arg1;
                 synchronized (mEventCbLock) {
-                    if (srcId == mCurrentSrcId) {
+                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                        cb.first.execute(() -> cb.second.onInfo(
+                                mMediaPlayer, dsd, MEDIA_INFO_BUFFERING_UPDATE,
+                                percent));
+                    }
+                }
+
+                synchronized (mSrcLock) {
+                    if (isCurrentSrcId) {
                         mBufferedPercentageCurrent.set(percent);
-                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                            cb.first.execute(() -> cb.second.onInfo(
-                                    mMediaPlayer, mCurrentDSD, MEDIA_INFO_BUFFERING_UPDATE,
-                                    percent));
-                        }
-                    } else if (srcId == mNextSrcId && !mNextDSDs.isEmpty()) {
+                    } else if (isNextSrcId) {
                         mBufferedPercentageNext.set(percent);
-                        DataSourceDesc nextDSD = mNextDSDs.get(0);
-                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                            cb.first.execute(() -> cb.second.onInfo(
-                                    mMediaPlayer, nextDSD, MEDIA_INFO_BUFFERING_UPDATE,
-                                    percent));
-                        }
                     }
                 }
                 return;
@@ -2875,7 +2912,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onVideoSizeChanged(
-                                mMediaPlayer, mCurrentDSD, width, height));
+                                mMediaPlayer, dsd, width, height));
                     }
                 }
                 return;
@@ -2887,9 +2924,9 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onError(
-                                mMediaPlayer, mCurrentDSD, what, extra));
+                                mMediaPlayer, dsd, what, extra));
                         cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, mCurrentDSD, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+                                mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0));
                     }
                 }
                 stayAwake(false);
@@ -2898,10 +2935,17 @@
 
             case MEDIA_INFO:
             {
+                synchronized (mEventCbLock) {
+                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                        cb.first.execute(() -> cb.second.onInfo(
+                                mMediaPlayer, dsd, what, extra));
+                    }
+                }
+
                 switch (msg.arg1) {
-                    case MEDIA_INFO_STARTED_AS_NEXT:
-                        if (srcId == mCurrentSrcId) {
-                            prepareNextDataSource_l();
+                    case MEDIA_INFO_DATA_SOURCE_START:
+                        if (isCurrentSrcId) {
+                            prepareNextDataSource();
                         }
                         break;
 
@@ -2936,13 +2980,6 @@
                         }
                         break;
                 }
-
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, mCurrentDSD, what, extra));
-                    }
-                }
                 // No real default action so far.
                 return;
             }
@@ -2969,7 +3006,8 @@
 
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onTimedText(mMediaPlayer, mCurrentDSD, text));
+                        cb.first.execute(() -> cb.second.onTimedText(
+                                mMediaPlayer, dsd, text));
                     }
                 }
                 return;
@@ -2977,15 +3015,16 @@
 
             case MEDIA_SUBTITLE_DATA:
             {
-                OnSubtitleDataListener onSubtitleDataListener = mOnSubtitleDataListener;
-                if (onSubtitleDataListener == null) {
-                    return;
-                }
                 if (msg.obj instanceof Parcel) {
                     Parcel parcel = (Parcel) msg.obj;
                     SubtitleData data = new SubtitleData(parcel);
                     parcel.recycle();
-                    onSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
+                    synchronized (mEventCbLock) {
+                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                            cb.first.execute(() -> cb.second.onSubtitleData(
+                                    mMediaPlayer, dsd, data));
+                        }
+                    }
                 }
                 return;
             }
@@ -3004,7 +3043,7 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onTimedMetaDataAvailable(
-                                mMediaPlayer, mCurrentDSD, data));
+                                mMediaPlayer, dsd, data));
                     }
                 }
                 return;
@@ -3038,7 +3077,7 @@
 
     /*
      * Called from native code when an interesting event happens.  This method
-     * just uses the EventHandler system to post the event back to the main app thread.
+     * just uses the TaskHandler system to post the event back to the main app thread.
      * We use a weak reference to the original MediaPlayer2 object so that the native
      * code is safe from the object disappearing from underneath it.  (This is
      * the cookie passed to native_setup().)
@@ -3052,22 +3091,9 @@
         }
 
         switch (what) {
-        case MEDIA_INFO:
-            if (arg1 == MEDIA_INFO_STARTED_AS_NEXT) {
-                new Thread(new Runnable() {
-                    @Override
-                    public void run() {
-                        // this acquires the wakelock if needed, and sets the client side state
-                        mp.play();
-                    }
-                }).start();
-                Thread.yield();
-            }
-            break;
-
         case MEDIA_DRM_INFO:
             // We need to derive mDrmInfoImpl before prepare() returns so processing it here
-            // before the notification is sent to EventHandler below. EventHandler runs in the
+            // before the notification is sent to TaskHandler below. TaskHandler runs in the
             // notification looper so its handleMessage might process the event after prepare()
             // has returned.
             Log.v(TAG, "postEventFromNative MEDIA_DRM_INFO");
@@ -3094,13 +3120,13 @@
 
         }
 
-        if (mp.mEventHandler != null) {
-            Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
+        if (mp.mTaskHandler != null) {
+            Message m = mp.mTaskHandler.obtainMessage(what, arg1, arg2, obj);
 
-            mp.mEventHandler.post(new Runnable() {
+            mp.mTaskHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mp.mEventHandler.handleMessage(m, srcId);
+                    mp.mTaskHandler.handleMessage(m, srcId);
                 }
             });
         }
@@ -3118,7 +3144,7 @@
      * @param executor the executor through which the callback should be invoked
      */
     @Override
-    public void setEventCallback(@NonNull @CallbackExecutor Executor executor,
+    public void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull EventCallback eventCallback) {
         if (eventCallback == null) {
             throw new IllegalArgumentException("Illegal null EventCallback");
@@ -3136,27 +3162,16 @@
      * Clears the {@link EventCallback}.
      */
     @Override
-    public void clearEventCallback() {
+    public void unregisterEventCallback(EventCallback eventCallback) {
         synchronized (mEventCbLock) {
-            mEventCallbackRecords.clear();
+            for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                if (cb.second == eventCallback) {
+                    mEventCallbackRecords.remove(cb);
+                }
+            }
         }
     }
 
-    /**
-     * Register a callback to be invoked when a track has data available.
-     *
-     * @param listener the callback that will be run
-     *
-     * @hide
-     */
-    @Override
-    public void setOnSubtitleDataListener(OnSubtitleDataListener listener) {
-        mOnSubtitleDataListener = listener;
-    }
-
-    private OnSubtitleDataListener mOnSubtitleDataListener;
-
-
     // Modular DRM begin
 
     /**
@@ -4660,7 +4675,12 @@
         public void run() {
             int status = CALL_STATUS_NO_ERROR;
             try {
-                process();
+                if (mMediaCallType != CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED
+                        && getState() == PLAYER_STATE_ERROR) {
+                    status = CALL_STATUS_INVALID_OPERATION;
+                } else {
+                    process();
+                }
             } catch (IllegalStateException e) {
                 status = CALL_STATUS_INVALID_OPERATION;
             } catch (IllegalArgumentException e) {
@@ -4671,6 +4691,8 @@
                 status = CALL_STATUS_ERROR_IO;
             } catch (NoDrmSchemeException e) {
                 status = CALL_STATUS_NO_DRM_SCHEME;
+            } catch (CommandSkippedException e) {
+                status = CALL_STATUS_SKIPPED;
             } catch (Exception e) {
                 status = CALL_STATUS_ERROR_UNKNOWN;
             }
@@ -4704,4 +4726,10 @@
             }
         }
     };
+
+    private final class CommandSkippedException extends RuntimeException {
+        public CommandSkippedException(String detailMessage) {
+            super(detailMessage);
+        }
+    };
 }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index b47b4cd..d4bfd61 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.hardware.Camera;
 import android.os.Bundle;
@@ -97,13 +98,19 @@
     private long mNativeContext;
 
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private Surface mSurface;
 
+    @UnsupportedAppUsage
     private String mPath;
+    @UnsupportedAppUsage
     private FileDescriptor mFd;
     private File mFile;
+    @UnsupportedAppUsage
     private EventHandler mEventHandler;
+    @UnsupportedAppUsage
     private OnErrorListener mOnErrorListener;
+    @UnsupportedAppUsage
     private OnInfoListener mOnInfoListener;
 
     private int mChannelCount;
@@ -942,6 +949,7 @@
     // native implementation
     private native void _setOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
     private native void _setNextOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
+    @UnsupportedAppUsage
     private native void _prepare() throws IllegalStateException, IOException;
 
     /**
@@ -1043,6 +1051,7 @@
         mEventHandler.removeCallbacksAndMessages(null);
     }
 
+    @UnsupportedAppUsage
     private native void native_reset();
 
     /**
@@ -1500,13 +1509,17 @@
      */
     public native void release();
 
+    @UnsupportedAppUsage
     private static native final void native_init();
 
+    @UnsupportedAppUsage
     private native final void native_setup(Object mediarecorder_this,
             String clientName, String opPackageName) throws IllegalStateException;
 
+    @UnsupportedAppUsage
     private native final void native_finalize();
 
+    @UnsupportedAppUsage
     private native void setParameter(String nameValuePair);
 
     /**
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d5afd9a..43bee85 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -786,6 +787,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public RouteInfo getSelectedRoute() {
         return getSelectedRoute(ROUTE_TYPE_ANY);
     }
@@ -939,6 +941,7 @@
     /**
      * @hide internal use
      */
+    @UnsupportedAppUsage
     public void selectRouteInt(int types, RouteInfo route, boolean explicit) {
         selectRouteStatic(types, route, explicit);
     }
@@ -1527,6 +1530,7 @@
      */
     public static class RouteInfo {
         CharSequence mName;
+        @UnsupportedAppUsage
         int mNameResId;
         CharSequence mDescription;
         private CharSequence mStatus;
@@ -1558,7 +1562,9 @@
 
         /** @hide */ public static final int STATUS_NONE = 0;
         /** @hide */ public static final int STATUS_SCANNING = 1;
-        /** @hide */ public static final int STATUS_CONNECTING = 2;
+        /** @hide */
+        @UnsupportedAppUsage
+        public static final int STATUS_CONNECTING = 2;
         /** @hide */ public static final int STATUS_AVAILABLE = 3;
         /** @hide */ public static final int STATUS_NOT_AVAILABLE = 4;
         /** @hide */ public static final int STATUS_IN_USE = 5;
@@ -1675,6 +1681,7 @@
             return getName(context.getResources());
         }
 
+        @UnsupportedAppUsage
         CharSequence getName(Resources res) {
             if (mNameResId != 0) {
                 return res.getText(mNameResId);
@@ -1770,6 +1777,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public int getStatusCode() {
             return mResolvedStatusCode;
         }
@@ -1794,6 +1802,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public boolean matchesTypes(int types) {
             return (mSupportedTypes & types) != 0;
         }
@@ -2024,6 +2033,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public String getDeviceAddress() {
             return mDeviceAddress;
         }
@@ -2048,11 +2058,13 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public boolean isSelected() {
             return this == sStatic.mSelectedRoute;
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public boolean isDefault() {
             return this == sStatic.mDefaultAudioVideo;
         }
@@ -2063,6 +2075,7 @@
         }
 
         /** @hide */
+        @UnsupportedAppUsage
         public void select() {
             selectRouteStatic(mSupportedTypes, this, true);
         }
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 8a757b8..dcacb92 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -62,11 +63,10 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.text.SimpleDateFormat;
 import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.TimeZone;
@@ -125,11 +125,13 @@
 
     private final static String TAG = "MediaScanner";
 
+    @UnsupportedAppUsage
     private static final String[] FILES_PRESCAN_PROJECTION = new String[] {
             Files.FileColumns._ID, // 0
             Files.FileColumns.DATA, // 1
             Files.FileColumns.FORMAT, // 2
             Files.FileColumns.DATE_MODIFIED, // 3
+            Files.FileColumns.MEDIA_TYPE, // 4
     };
 
     private static final String[] ID_PROJECTION = new String[] {
@@ -140,6 +142,7 @@
     private static final int FILES_PRESCAN_PATH_COLUMN_INDEX = 1;
     private static final int FILES_PRESCAN_FORMAT_COLUMN_INDEX = 2;
     private static final int FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX = 3;
+    private static final int FILES_PRESCAN_MEDIA_TYPE_COLUMN_INDEX = 4;
 
     private static final String[] PLAYLIST_MEMBERS_PROJECTION = new String[] {
             Audio.Playlists.Members.PLAYLIST_ID, // 0
@@ -317,14 +320,18 @@
     };
 
     private long mNativeContext;
+    @UnsupportedAppUsage
     private final Context mContext;
+    @UnsupportedAppUsage
     private final String mPackageName;
     private final String mVolumeName;
     private final ContentProviderClient mMediaProvider;
+    @UnsupportedAppUsage
     private final Uri mAudioUri;
     private final Uri mVideoUri;
     private final Uri mImagesUri;
     private final Uri mPlaylistsUri;
+    @UnsupportedAppUsage
     private final Uri mFilesUri;
     private final Uri mFilesUriNoNotify;
     private final boolean mProcessPlaylists;
@@ -347,10 +354,13 @@
     /** Whether the scanner has set a default sound for the alarm ringtone. */
     private boolean mDefaultAlarmSet;
     /** The filename for the default sound for the ringer ringtone. */
+    @UnsupportedAppUsage
     private String mDefaultRingtoneFilename;
     /** The filename for the default sound for the notification ringtone. */
+    @UnsupportedAppUsage
     private String mDefaultNotificationFilename;
     /** The filename for the default sound for the alarm ringtone. */
+    @UnsupportedAppUsage
     private String mDefaultAlarmAlertFilename;
     /**
      * The prefix for system properties that define the default sound for
@@ -362,17 +372,28 @@
     private final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
 
     private static class FileEntry {
+        @UnsupportedAppUsage
         long mRowId;
         String mPath;
         long mLastModified;
         int mFormat;
+        int mMediaType;
+        @UnsupportedAppUsage
         boolean mLastModifiedChanged;
 
+        /** @deprecated kept intact for lame apps using reflection */
+        @Deprecated
+        @UnsupportedAppUsage
         FileEntry(long rowId, String path, long lastModified, int format) {
+            this(rowId, path, lastModified, format, FileColumns.MEDIA_TYPE_NONE);
+        }
+
+        FileEntry(long rowId, String path, long lastModified, int format, int mediaType) {
             mRowId = rowId;
             mPath = path;
             mLastModified = lastModified;
             mFormat = format;
+            mMediaType = mediaType;
             mLastModifiedChanged = false;
         }
 
@@ -391,10 +412,12 @@
     private final ArrayList<PlaylistEntry> mPlaylistEntries = new ArrayList<>();
     private final ArrayList<FileEntry> mPlayLists = new ArrayList<>();
 
+    @UnsupportedAppUsage
     private MediaInserter mMediaInserter;
 
     private DrmManagerClient mDrmManagerClient = null;
 
+    @UnsupportedAppUsage
     public MediaScanner(Context c, String volumeName) {
         native_setup();
         mContext = c;
@@ -458,8 +481,10 @@
                 + Settings.System.ALARM_ALERT);
     }
 
+    @UnsupportedAppUsage
     private final MyMediaScannerClient mClient = new MyMediaScannerClient();
 
+    @UnsupportedAppUsage
     private boolean isDrmEnabled() {
         String prop = SystemProperties.get("drm.service.enabled");
         return prop != null && prop.equals("true");
@@ -475,18 +500,23 @@
         private String mTitle;
         private String mComposer;
         private String mGenre;
+        @UnsupportedAppUsage
         private String mMimeType;
+        @UnsupportedAppUsage
         private int mFileType;
         private int mTrack;
         private int mYear;
         private int mDuration;
+        @UnsupportedAppUsage
         private String mPath;
         private long mDate;
         private long mLastModified;
         private long mFileSize;
         private String mWriter;
         private int mCompilation;
+        @UnsupportedAppUsage
         private boolean mIsDrm;
+        @UnsupportedAppUsage
         private boolean mNoMedia;   // flag to suppress file from appearing in media tables
         private boolean mScanSuccess;
         private int mWidth;
@@ -497,6 +527,7 @@
             mDateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
         }
 
+        @UnsupportedAppUsage
         public FileEntry beginFile(String path, String mimeType, long lastModified,
                 long fileSize, boolean isDirectory, boolean noMedia) {
             mMimeType = mimeType;
@@ -541,7 +572,8 @@
                     entry.mLastModified = lastModified;
                 } else {
                     entry = new FileEntry(0, path, lastModified,
-                            (isDirectory ? MtpConstants.FORMAT_ASSOCIATION : 0));
+                            (isDirectory ? MtpConstants.FORMAT_ASSOCIATION : 0),
+                            FileColumns.MEDIA_TYPE_NONE);
                 }
                 entry.mLastModifiedChanged = true;
             }
@@ -574,6 +606,7 @@
         }
 
         @Override
+        @UnsupportedAppUsage
         public void scanFile(String path, long lastModified, long fileSize,
                 boolean isDirectory, boolean noMedia) {
             // This is the callback funtion from native codes.
@@ -581,6 +614,7 @@
             doScanFile(path, null, lastModified, fileSize, isDirectory, false, noMedia);
         }
 
+        @UnsupportedAppUsage
         public Uri doScanFile(String path, String mimeType, long lastModified,
                 long fileSize, boolean isDirectory, boolean scanAlways, boolean noMedia) {
             Uri result = null;
@@ -689,6 +723,7 @@
             return result;
         }
 
+        @UnsupportedAppUsage
         public void handleStringTag(String name, String value) {
             if (name.equalsIgnoreCase("title") || name.startsWith("title;")) {
                 // Don't trim() here, to preserve the special \001 character
@@ -833,6 +868,7 @@
             return false;
         }
 
+        @UnsupportedAppUsage
         public void setMimeType(String mimeType) {
             if ("audio/mp4".equals(mMimeType) &&
                     mimeType.startsWith("video")) {
@@ -851,6 +887,7 @@
          *
          * @return a map of values
          */
+        @UnsupportedAppUsage
         private ContentValues toValues() {
             ContentValues map = new ContentValues();
 
@@ -907,6 +944,7 @@
             return map;
         }
 
+        @UnsupportedAppUsage
         private Uri endFile(FileEntry entry, boolean ringtones, boolean notifications,
                 boolean alarms, boolean music, boolean podcasts)
                 throws RemoteException {
@@ -1009,14 +1047,21 @@
             }
 
             Uri tableUri = mFilesUri;
+            int mediaType = FileColumns.MEDIA_TYPE_NONE;
             MediaInserter inserter = mMediaInserter;
             if (mScanSuccess && !mNoMedia) {
                 if (MediaFile.isVideoFileType(mFileType)) {
                     tableUri = mVideoUri;
+                    mediaType = FileColumns.MEDIA_TYPE_VIDEO;
                 } else if (MediaFile.isImageFileType(mFileType)) {
                     tableUri = mImagesUri;
+                    mediaType = FileColumns.MEDIA_TYPE_IMAGE;
                 } else if (MediaFile.isAudioFileType(mFileType)) {
                     tableUri = mAudioUri;
+                    mediaType = FileColumns.MEDIA_TYPE_AUDIO;
+                } else if (MediaFile.isPlayListFileType(mFileType)) {
+                    tableUri = mPlaylistsUri;
+                    mediaType = FileColumns.MEDIA_TYPE_PLAYLIST;
                 }
             }
             Uri result = null;
@@ -1079,20 +1124,16 @@
                 // with squashed lower case paths
                 values.remove(MediaStore.MediaColumns.DATA);
 
-                int mediaType = 0;
-                if (mScanSuccess && !MediaScanner.isNoMediaPath(entry.mPath)) {
-                    int fileType = MediaFile.getFileTypeForMimeType(mMimeType);
-                    if (MediaFile.isAudioFileType(fileType)) {
-                        mediaType = FileColumns.MEDIA_TYPE_AUDIO;
-                    } else if (MediaFile.isVideoFileType(fileType)) {
-                        mediaType = FileColumns.MEDIA_TYPE_VIDEO;
-                    } else if (MediaFile.isImageFileType(fileType)) {
-                        mediaType = FileColumns.MEDIA_TYPE_IMAGE;
-                    } else if (MediaFile.isPlayListFileType(fileType)) {
-                        mediaType = FileColumns.MEDIA_TYPE_PLAYLIST;
+                if (mScanSuccess && !mNoMedia) {
+                    // Changing media type must be done as separate update
+                    if (mediaType != entry.mMediaType) {
+                        final ContentValues mediaTypeValues = new ContentValues();
+                        mediaTypeValues.put(FileColumns.MEDIA_TYPE, mediaType);
+                        mMediaProvider.update(ContentUris.withAppendedId(mFilesUri, rowId),
+                                mediaTypeValues, null, null);
                     }
-                    values.put(FileColumns.MEDIA_TYPE, mediaType);
                 }
+
                 mMediaProvider.update(result, values, null, null);
             }
 
@@ -1135,6 +1176,7 @@
             Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1);
         }
 
+        @UnsupportedAppUsage
         private int getFileTypeFromDrm(String path) {
             if (!isDrmEnabled()) {
                 return 0;
@@ -1185,6 +1227,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void prescan(String filePath, boolean prescanFiles) throws RemoteException {
         Cursor c = null;
         String where = null;
@@ -1331,6 +1374,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void postscan(final String[] directories) throws RemoteException {
 
         // handle playlists last, after we know what media files are on the storage.
@@ -1395,6 +1439,7 @@
     }
 
     // this function is used to scan a single file
+    @UnsupportedAppUsage
     public Uri scanSingleFile(String path, String mimeType) {
         try {
             prescan(path, true);
@@ -1467,6 +1512,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static boolean isNoMediaPath(String path) {
         if (path == null) {
             return false;
@@ -1565,6 +1611,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     FileEntry makeEntryFor(String path) {
         String where;
         String[] selectionArgs;
@@ -1577,9 +1624,10 @@
                     where, selectionArgs, null, null);
             if (c.moveToFirst()) {
                 long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
-                int format = c.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
                 long lastModified = c.getLong(FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
-                return new FileEntry(rowId, path, lastModified, format);
+                int format = c.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
+                int mediaType = c.getInt(FILES_PRESCAN_MEDIA_TYPE_COLUMN_INDEX);
+                return new FileEntry(rowId, path, lastModified, format, mediaType);
             }
         } catch (RemoteException e) {
         } finally {
@@ -1900,6 +1948,7 @@
 
     private native void processDirectory(String path, MediaScannerClient client);
     private native boolean processFile(String path, String mimeType, MediaScannerClient client);
+    @UnsupportedAppUsage
     private native void setLocale(String locale);
 
     public native byte[] extractAlbumArt(FileDescriptor fd);
diff --git a/media/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index 4b8f81e..792a2ba 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.util.Log;
 import android.util.MathUtils;
@@ -68,18 +69,22 @@
     /**
      * Indicate whether the media can be paused
      */
+    @UnsupportedAppUsage
     public static final int PAUSE_AVAILABLE         = 1; // Boolean
     /**
      * Indicate whether the media can be backward seeked
      */
+    @UnsupportedAppUsage
     public static final int SEEK_BACKWARD_AVAILABLE = 2; // Boolean
     /**
      * Indicate whether the media can be forward seeked
      */
+    @UnsupportedAppUsage
     public static final int SEEK_FORWARD_AVAILABLE  = 3; // Boolean
     /**
      * Indicate whether the media can be seeked
      */
+    @UnsupportedAppUsage
     public static final int SEEK_AVAILABLE          = 4; // Boolean
 
     // TODO: Should we use numbers compatible with the metadata retriever?
@@ -264,6 +269,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public Metadata() { }
 
     /**
@@ -382,6 +388,7 @@
      * @return false if an error occurred.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean parse(Parcel parcel) {
         if (parcel.dataAvail() < kMetaHeaderSize) {
             Log.e(TAG, "Not enough data " + parcel.dataAvail());
@@ -418,6 +425,7 @@
     /**
      * @return The set of metadata ID found.
      */
+    @UnsupportedAppUsage
     public Set<Integer> keySet() {
         return mKeyToPosMap.keySet();
     }
@@ -425,6 +433,7 @@
     /**
      * @return true if a value is present for the given key.
      */
+    @UnsupportedAppUsage
     public boolean has(final int metadataId) {
         if (!checkMetadataId(metadataId)) {
             throw new IllegalArgumentException("Invalid key: " + metadataId);
@@ -439,6 +448,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public String getString(final int key) {
         checkType(key, STRING_VAL);
         return mParcel.readString();
@@ -447,6 +457,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int getInt(final int key) {
         checkType(key, INTEGER_VAL);
         return mParcel.readInt();
@@ -455,6 +466,7 @@
     /**
      * Get the boolean value indicated by key
      */
+    @UnsupportedAppUsage
     public boolean getBoolean(final int key) {
         checkType(key, BOOLEAN_VAL);
         return mParcel.readInt() == 1;
@@ -463,6 +475,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long getLong(final int key) {
         checkType(key, LONG_VAL);    /**
      * {@hide}
@@ -473,6 +486,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public double getDouble(final int key) {
         checkType(key, DOUBLE_VAL);
         return mParcel.readDouble();
@@ -481,6 +495,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public byte[] getByteArray(final int key) {
         checkType(key, BYTE_ARRAY_VAL);
         return mParcel.createByteArray();
@@ -489,6 +504,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public Date getDate(final int key) {
         checkType(key, DATE_VAL);
         final long timeSinceEpoch = mParcel.readLong();
diff --git a/media/java/android/media/MicrophoneInfo.java b/media/java/android/media/MicrophoneInfo.java
index d6399a4..f805975 100644
--- a/media/java/android/media/MicrophoneInfo.java
+++ b/media/java/android/media/MicrophoneInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.util.Pair;
 
 import java.lang.annotation.Retention;
@@ -163,6 +164,7 @@
     private int mType;
     private int mDirectionality;
 
+    @UnsupportedAppUsage
     MicrophoneInfo(String deviceId, int type, String address, int location,
             int group, int indexInTheGroup, Coordinate3F position,
             Coordinate3F orientation, List<Pair<Float, Float>> frequencyResponse,
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
index 9899367..716e0cb 100644
--- a/media/java/android/media/MiniThumbFile.java
+++ b/media/java/android/media/MiniThumbFile.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Environment;
 import android.util.Log;
@@ -59,6 +60,7 @@
      * We store different types of thumbnails in different files. To remain backward compatibility,
      * we should hashcode of content://media/external/images/media remains the same.
      */
+    @UnsupportedAppUsage
     public static synchronized void reset() {
         for (MiniThumbFile file : sThumbFiles.values()) {
             file.deactivate();
diff --git a/media/java/android/media/PlaybackParams.java b/media/java/android/media/PlaybackParams.java
index b85e4d0..6594dd7 100644
--- a/media/java/android/media/PlaybackParams.java
+++ b/media/java/android/media/PlaybackParams.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -85,16 +86,25 @@
     public static final int AUDIO_STRETCH_MODE_VOICE = 1;
 
     // flags to indicate which params are actually set
+    @UnsupportedAppUsage
     private static final int SET_SPEED               = 1 << 0;
+    @UnsupportedAppUsage
     private static final int SET_PITCH               = 1 << 1;
+    @UnsupportedAppUsage
     private static final int SET_AUDIO_FALLBACK_MODE = 1 << 2;
+    @UnsupportedAppUsage
     private static final int SET_AUDIO_STRETCH_MODE  = 1 << 3;
+    @UnsupportedAppUsage
     private int mSet = 0;
 
     // params
+    @UnsupportedAppUsage
     private int mAudioFallbackMode = AUDIO_FALLBACK_MODE_DEFAULT;
+    @UnsupportedAppUsage
     private int mAudioStretchMode = AUDIO_STRETCH_MODE_DEFAULT;
+    @UnsupportedAppUsage
     private float mPitch = 1.0f;
+    @UnsupportedAppUsage
     private float mSpeed = 1.0f;
 
     public PlaybackParams() {
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 6d32eff..3b51c82 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -820,6 +821,7 @@
      * position updates. The playback position being "readable" is considered from the application's
      * point of view.
      */
+    @UnsupportedAppUsage
     public static int MEDIA_POSITION_READABLE = 1 << 0;
     /**
      * @hide
@@ -827,6 +829,7 @@
      * playback position updates. The playback position being "writable"
      * is considered from the application's point of view.
      */
+    @UnsupportedAppUsage
     public static int MEDIA_POSITION_WRITABLE = 1 << 1;
 
     /** @hide */
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index 90f2163..b6e3276 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -79,6 +80,7 @@
     private int mArtworkHeight = -1;
     private boolean mEnabled = true;
     // synchronized on mInfoLock, for USE_SESSION apis.
+    @UnsupportedAppUsage
     private MediaController mCurrentSession;
 
     /**
@@ -292,6 +294,7 @@
      * @return true if successful
      * @throws IllegalArgumentException
      */
+    @UnsupportedAppUsage
     public boolean setArtworkConfiguration(boolean wantBitmap, int width, int height)
             throws IllegalArgumentException {
         synchronized (mInfoLock) {
@@ -689,6 +692,7 @@
      * Used by AudioManager to access user listener receiving the client update notifications
      * @return
      */
+    @UnsupportedAppUsage
     OnClientUpdateListener getUpdateListener() {
         return mOnClientUpdateListener;
     }
diff --git a/media/java/android/media/RemoteDisplay.java b/media/java/android/media/RemoteDisplay.java
index 5add65a..2be206f 100644
--- a/media/java/android/media/RemoteDisplay.java
+++ b/media/java/android/media/RemoteDisplay.java
@@ -18,6 +18,7 @@
 
 import dalvik.system.CloseGuard;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.view.Surface;
 
@@ -88,6 +89,7 @@
     /**
      * Disconnects the remote display and stops listening for new connections.
      */
+    @UnsupportedAppUsage
     public void dispose() {
         dispose(false);
     }
@@ -125,6 +127,7 @@
     }
 
     // Called from native.
+    @UnsupportedAppUsage
     private void notifyDisplayConnected(final Surface surface,
             final int width, final int height, final int flags, final int session) {
         mHandler.post(new Runnable() {
@@ -136,6 +139,7 @@
     }
 
     // Called from native.
+    @UnsupportedAppUsage
     private void notifyDisplayDisconnected() {
         mHandler.post(new Runnable() {
             @Override
@@ -146,6 +150,7 @@
     }
 
     // Called from native.
+    @UnsupportedAppUsage
     private void notifyDisplayError(final int error) {
         mHandler.post(new Runnable() {
             @Override
diff --git a/media/java/android/media/RemoteDisplayState.java b/media/java/android/media/RemoteDisplayState.java
index 1197f65..f8a4605 100644
--- a/media/java/android/media/RemoteDisplayState.java
+++ b/media/java/android/media/RemoteDisplayState.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -40,8 +41,10 @@
     /**
      * A list of all remote displays.
      */
+    @UnsupportedAppUsage
     public final ArrayList<RemoteDisplayInfo> displays;
 
+    @UnsupportedAppUsage
     public RemoteDisplayState() {
         displays = new ArrayList<RemoteDisplayInfo>();
     }
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index c0468dc9..32aba7f 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -71,9 +72,11 @@
     private final IRingtonePlayer mRemotePlayer;
     private final Binder mRemoteToken;
 
+    @UnsupportedAppUsage
     private MediaPlayer mLocalPlayer;
     private final MyOnCompletionListener mCompletionListener = new MyOnCompletionListener();
 
+    @UnsupportedAppUsage
     private Uri mUri;
     private String mTitle;
 
@@ -87,6 +90,7 @@
     private final Object mPlaybackSettingsLock = new Object();
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public Ringtone(Context context, boolean allowRemote) {
         mContext = context;
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
@@ -298,6 +302,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUri(Uri uri) {
         destroyLocalPlayer();
 
@@ -335,6 +340,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public Uri getUri() {
         return mUri;
     }
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 0dddaf5..66feb1d 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -21,6 +21,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.app.Activity;
 import android.content.ContentProvider;
@@ -244,6 +245,7 @@
     private final Activity mActivity;
     private final Context mContext;
 
+    @UnsupportedAppUsage
     private Cursor mCursor;
 
     private int mType = TYPE_RINGTONE;
@@ -602,6 +604,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private Cursor getInternalRingtones() {
         return query(
                 MediaStore.Audio.Media.INTERNAL_CONTENT_URI, INTERNAL_COLUMNS,
@@ -613,6 +616,7 @@
         return getMediaRingtones(mContext);
     }
 
+    @UnsupportedAppUsage
     private Cursor getMediaRingtones(Context context) {
         if (PackageManager.PERMISSION_GRANTED != context.checkPermission(
                 android.Manifest.permission.READ_EXTERNAL_STORAGE,
@@ -727,6 +731,7 @@
      *            not be set (and the default used instead).
      * @see #getRingtone(Context, Uri)
      */
+    @UnsupportedAppUsage
     private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) {
         try {
             final Ringtone r = new Ringtone(context, true);
diff --git a/media/java/android/media/SubtitleController.java b/media/java/android/media/SubtitleController.java
index fd72b39..1a241af 100644
--- a/media/java/android/media/SubtitleController.java
+++ b/media/java/android/media/SubtitleController.java
@@ -19,6 +19,7 @@
 import java.util.Locale;
 import java.util.Vector;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.MediaPlayer.TrackInfo;
 import android.media.SubtitleTrack.RenderingWidget;
@@ -41,6 +42,7 @@
     private SubtitleTrack mSelectedTrack;
     private boolean mShowing;
     private CaptioningManager mCaptioningManager;
+    @UnsupportedAppUsage
     private Handler mHandler;
 
     private static final int WHAT_SHOW = 1;
@@ -91,6 +93,7 @@
      *
      * @param timeProvider
      */
+    @UnsupportedAppUsage
     public SubtitleController(
             Context context,
             MediaTimeProvider timeProvider,
@@ -300,6 +303,7 @@
     }
 
     /** @hide - must be called from anchor thread */
+    @UnsupportedAppUsage
     public void reset() {
         checkAnchorLooper();
         hide();
@@ -344,6 +348,7 @@
      *
      * Should be called from the anchor's (UI) thread. {@see #Anchor.getSubtitleLooper}
      */
+    @UnsupportedAppUsage
     public void show() {
         processOnAnchor(mHandler.obtainMessage(WHAT_SHOW));
     }
@@ -361,6 +366,7 @@
      *
      * Should be called from the anchor's (UI) thread. {@see #Anchor.getSubtitleLooper}
      */
+    @UnsupportedAppUsage
     public void hide() {
         processOnAnchor(mHandler.obtainMessage(WHAT_HIDE));
     }
@@ -412,6 +418,7 @@
      * @param renderer a {@link SubtitleController.Renderer} object that adds
      *                 support for a subtitle format.
      */
+    @UnsupportedAppUsage
     public void registerRenderer(Renderer renderer) {
         synchronized(mRenderers) {
             // TODO how to get available renderers in the system
diff --git a/media/java/android/media/SubtitleTrack.java b/media/java/android/media/SubtitleTrack.java
index 6c8e323..5596c32 100644
--- a/media/java/android/media/SubtitleTrack.java
+++ b/media/java/android/media/SubtitleTrack.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.media.MediaPlayer.TrackInfo;
 import android.os.Handler;
@@ -677,6 +678,7 @@
          *
          * @param callback update callback
          */
+        @UnsupportedAppUsage
         public void setOnChangedListener(OnChangedListener callback);
 
         /**
@@ -685,6 +687,7 @@
          * @param width width in pixels
          * @param height height in pixels
          */
+        @UnsupportedAppUsage
         public void setSize(int width, int height);
 
         /**
@@ -699,16 +702,19 @@
          *
          * @param c canvas on which to render subtitles
          */
+        @UnsupportedAppUsage
         public void draw(Canvas c);
 
         /**
          * Called when the widget is attached to a window.
          */
+        @UnsupportedAppUsage
         public void onAttachedToWindow();
 
         /**
          * Called when the widget is detached from a window.
          */
+        @UnsupportedAppUsage
         public void onDetachedFromWindow();
 
         /**
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 429ef29..07ab069 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -65,6 +66,7 @@
      * Constant used to indicate the dimension of micro thumbnail.
      * @hide Only used by media framework and media provider internally.
      */
+    @UnsupportedAppUsage
     public static final int TARGET_SIZE_MICRO_THUMBNAIL = 96;
 
     /**
@@ -81,6 +83,7 @@
      *
      * @hide This method is only used by media framework and media provider internally.
      */
+    @UnsupportedAppUsage
     public static Bitmap createImageThumbnail(String filePath, int kind) {
         boolean wantMini = (kind == Images.Thumbnails.MINI_KIND);
         int targetSize = wantMini
@@ -252,6 +255,7 @@
      * For example, BitmapFactory downsamples an image by 2 even though the
      * request is 3. So we round up the sample size to avoid OOM.
      */
+    @UnsupportedAppUsage
     private static int computeSampleSize(BitmapFactory.Options options,
             int minSideLength, int maxNumOfPixels) {
         int initialSize = computeInitialSampleSize(options, minSideLength,
@@ -270,6 +274,7 @@
         return roundedSize;
     }
 
+    @UnsupportedAppUsage
     private static int computeInitialSampleSize(BitmapFactory.Options options,
             int minSideLength, int maxNumOfPixels) {
         double w = options.outWidth;
@@ -337,6 +342,7 @@
         return b;
     }
 
+    @UnsupportedAppUsage
     private static void closeSilently(ParcelFileDescriptor c) {
       if (c == null) return;
       try {
@@ -346,6 +352,7 @@
       }
     }
 
+    @UnsupportedAppUsage
     private static ParcelFileDescriptor makeInputStream(
             Uri uri, ContentResolver cr) {
         try {
@@ -358,6 +365,7 @@
     /**
      * Transform source Bitmap to targeted width and height.
      */
+    @UnsupportedAppUsage
     private static Bitmap transform(Matrix scaler,
             Bitmap source,
             int targetWidth,
@@ -474,6 +482,7 @@
      * The functions returns a SizedThumbnailBitmap,
      * which contains a downsampled bitmap and the thumbnail data in EXIF if exists.
      */
+    @UnsupportedAppUsage
     private static void createThumbnailFromEXIF(String filePath, int targetSize,
             int maxPixels, SizedThumbnailBitmap sizedThumbBitmap) {
         if (filePath == null) return;
diff --git a/media/java/android/media/TimedText.java b/media/java/android/media/TimedText.java
index e6a7e13..ebcea19 100644
--- a/media/java/android/media/TimedText.java
+++ b/media/java/android/media/TimedText.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.util.Log;
@@ -724,6 +725,7 @@
      * List of CharPos, Karaoke, Font, Style, and HyperText, or 3) an instance of
      * Justification.
      */
+    @UnsupportedAppUsage
     private Object getObject(final int key) {
         if (containsKey(key)) {
             return mKeyObjectMap.get(key);
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
index 4661226..c6d5ba3 100644
--- a/media/java/android/media/ToneGenerator.java
+++ b/media/java/android/media/ToneGenerator.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
+
 
 
 /**
@@ -893,5 +895,6 @@
     protected void finalize() { native_finalize(); }
 
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private long mNativeContext; // accessed by native methods
 }
diff --git a/media/java/android/media/TtmlRenderer.java b/media/java/android/media/TtmlRenderer.java
index 9d587b9..34154ce 100644
--- a/media/java/android/media/TtmlRenderer.java
+++ b/media/java/android/media/TtmlRenderer.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -48,6 +49,7 @@
 
     private TtmlRenderingWidget mRenderingWidget;
 
+    @UnsupportedAppUsage
     public TtmlRenderer(Context context) {
         mContext = context;
     }
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index b654214..2f33e75 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -413,16 +414,23 @@
          */
 
         // type of VolumeShaper
+        @UnsupportedAppUsage
         private final int mType;
 
         // valid when mType is TYPE_ID
+        @UnsupportedAppUsage
         private final int mId;
 
         // valid when mType is TYPE_SCALE
+        @UnsupportedAppUsage
         private final int mOptionFlags;
+        @UnsupportedAppUsage
         private final double mDurationMs;
+        @UnsupportedAppUsage
         private final int mInterpolatorType;
+        @UnsupportedAppUsage
         private final float[] mTimes;
+        @UnsupportedAppUsage
         private final float[] mVolumes;
 
         @Override
@@ -565,6 +573,7 @@
          * Direct constructor for VolumeShaper.
          * Use the Builder instead.
          */
+        @UnsupportedAppUsage
         private Configuration(@Type int type,
                 int id,
                 @OptionFlag int optionFlags,
@@ -1124,8 +1133,11 @@
 
         private static final int FLAG_PUBLIC_ALL = FLAG_REVERSE | FLAG_TERMINATE;
 
+        @UnsupportedAppUsage
         private final int mFlags;
+        @UnsupportedAppUsage
         private final int mReplaceId;
+        @UnsupportedAppUsage
         private final float mXOffset;
 
         @Override
@@ -1187,6 +1199,7 @@
             }
         };
 
+        @UnsupportedAppUsage
         private Operation(@Flag int flags, int replaceId, float xOffset) {
             mFlags = flags;
             mReplaceId = replaceId;
@@ -1346,7 +1359,9 @@
      *  Not for public use.
      */
     public static final class State implements Parcelable {
+        @UnsupportedAppUsage
         private float mVolume;
+        @UnsupportedAppUsage
         private float mXOffset;
 
         @Override
@@ -1397,6 +1412,7 @@
             }
         };
 
+        @UnsupportedAppUsage
         /* package */ State(float volume, float xOffset) {
             mVolume = volume;
             mXOffset = xOffset;
diff --git a/media/java/android/media/WebVttRenderer.java b/media/java/android/media/WebVttRenderer.java
index 91c53fa..36458d7 100644
--- a/media/java/android/media/WebVttRenderer.java
+++ b/media/java/android/media/WebVttRenderer.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.text.Layout.Alignment;
 import android.text.SpannableStringBuilder;
@@ -44,6 +45,7 @@
 
     private WebVttRenderingWidget mRenderingWidget;
 
+    @UnsupportedAppUsage
     public WebVttRenderer(Context context) {
         mContext = context;
     }
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 24c595f..1a456f6 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -19,6 +19,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.os.Handler;
 import android.os.Looper;
@@ -400,6 +401,7 @@
      * @hide
      */
 
+    @UnsupportedAppUsage
     public AudioEffect(UUID type, UUID uuid, int priority, int audioSession)
             throws IllegalArgumentException, UnsupportedOperationException,
             RuntimeException {
@@ -629,6 +631,7 @@
      * @see #setParameter(byte[], byte[])
      * @hide
      */
+    @UnsupportedAppUsage
     public int setParameter(int[] param, short[] value)
             throws IllegalStateException {
         if (param.length > 2 || value.length > 2) {
@@ -778,6 +781,7 @@
      * In case of success, the returns the number of meaningful integers in value array.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getParameter(int[] param, int[] value)
             throws IllegalStateException {
         if (param.length > 2 || value.length > 2) {
@@ -846,6 +850,7 @@
      * @see #getParameter(byte[], byte[])
      * @hide
      */
+    @UnsupportedAppUsage
     public int getParameter(int[] param, byte[] value)
             throws IllegalStateException {
         if (param.length > 2) {
@@ -867,6 +872,7 @@
      * In case of failure, the returned value is negative and implementation specific.
      * @hide
      */
+    @UnsupportedAppUsage
     public int command(int cmdCode, byte[] command, byte[] reply)
             throws IllegalStateException {
         checkState("command()");
@@ -1277,6 +1283,7 @@
     /**
     * @hide
     */
+    @UnsupportedAppUsage
     public void checkState(String methodName) throws IllegalStateException {
         synchronized (mStateLock) {
             if (mState != STATE_INITIALIZED) {
diff --git a/media/java/android/media/audiofx/DefaultEffect.java b/media/java/android/media/audiofx/DefaultEffect.java
new file mode 100644
index 0000000..ce087adf
--- /dev/null
+++ b/media/java/android/media/audiofx/DefaultEffect.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audiofx;
+
+/**
+ * DefaultEffect is the base class for controlling default audio effects linked into the
+ * Android audio framework.
+ * <p>DefaultEffects are effects that get attached automatically to all AudioTracks,
+ * AudioRecords, and MediaPlayer instances meeting some criteria.
+ * <p>Applications should not use the DefaultEffect class directly but one of its derived classes
+ * to control specific types of defaults:
+ * <ul>
+ *   <li> {@link android.media.audiofx.SourceDefaultEffect}</li>
+ *   <li> {@link android.media.audiofx.StreamDefaultEffect}</li>
+ * </ul>
+ * <p>Creating a DefaultEffect object will register the corresponding effect engine as a default
+ * for the specified criteria. Whenever an audio session meets the criteria, an AudioEffect will
+ * be created and attached to it using the specified priority.
+ * @hide
+ */
+
+public abstract class DefaultEffect {
+    /**
+     * System wide unique default effect ID.
+     */
+    int mId;
+}
diff --git a/media/java/android/media/audiofx/SourceDefaultEffect.java b/media/java/android/media/audiofx/SourceDefaultEffect.java
new file mode 100644
index 0000000..d7a292e
--- /dev/null
+++ b/media/java/android/media/audiofx/SourceDefaultEffect.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audiofx;
+
+import android.annotation.RequiresPermission;
+import android.app.ActivityThread;
+import android.util.Log;
+import java.util.UUID;
+
+/**
+ * SourceDefaultEffect is a default effect that attaches automatically to all AudioRecord and
+ * MediaRecorder instances of a given source type.
+ * <p>see {@link android.media.audiofx.DefaultEffect} class for more details on default effects.
+ * @hide
+ */
+
+public class SourceDefaultEffect extends DefaultEffect {
+    static {
+        System.loadLibrary("audioeffect_jni");
+    }
+
+    private final static String TAG = "SourceDefaultEffect-JAVA";
+
+    /**
+     * Class constructor.
+     *
+     * @param type type of effect engine to be default. This parameter is ignored if uuid is set,
+     *             and can be set to {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL}
+     *             in that case.
+     * @param uuid unique identifier of a particular effect implementation to be default. This
+     *             parameter can be set to
+     *             {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL}, in which case only
+     *             the type will be used to select the effect.
+     * @param priority the priority level requested by the application for controlling the effect
+     *             engine. As the same engine can be shared by several applications, this parameter
+     *             indicates how much the requesting application needs control of effect parameters.
+     *             The normal priority is 0, above normal is a positive number, below normal a
+     *             negative number.
+     * @param source a MediaRecorder.AudioSource.* constant from
+     *             {@link android.media.MediaRecorder.AudioSource} indicating
+     *             what sources the given effect should attach to by default. Note that similar
+     *             sources may share defaults.
+     *
+     * @throws java.lang.IllegalArgumentException
+     * @throws java.lang.UnsupportedOperationException
+     * @throws java.lang.RuntimeException
+     */
+    @RequiresPermission(value = android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS,
+                        conditional = true)  // Android Things uses an alternate permission.
+    public SourceDefaultEffect(UUID type, UUID uuid, int priority, int source) {
+        int[] id = new int[1];
+        int initResult = native_setup(type.toString(),
+                                      uuid.toString(),
+                                      priority,
+                                      source,
+                                      ActivityThread.currentOpPackageName(),
+                                      id);
+        if (initResult != AudioEffect.SUCCESS) {
+            Log.e(TAG, "Error code " + initResult + " when initializing SourceDefaultEffect");
+            switch (initResult) {
+                case AudioEffect.ERROR_BAD_VALUE:
+                    throw (new IllegalArgumentException(
+                            "Source, type uuid, or implementation uuid not supported."));
+                case AudioEffect.ERROR_INVALID_OPERATION:
+                    throw (new UnsupportedOperationException(
+                            "Effect library not loaded"));
+                default:
+                    throw (new RuntimeException(
+                            "Cannot initialize effect engine for type: " + type
+                            + " Error: " + initResult));
+            }
+        }
+
+        mId = id[0];
+    }
+
+
+    /**
+     * Releases the native SourceDefaultEffect resources. It is a good practice to
+     * release the default effect when done with use as control can be returned to
+     * other applications or the native resources released.
+     */
+    public void release() {
+        native_release(mId);
+    }
+
+    @Override
+    protected void finalize() {
+        release();
+    }
+
+    // ---------------------------------------------------------
+    // Native methods called from the Java side
+    // --------------------
+
+    private native final int native_setup(String type,
+                                          String uuid,
+                                          int priority,
+                                          int source,
+                                          String opPackageName,
+                                          int[] id);
+
+    private native final void native_release(int id);
+}
diff --git a/media/java/android/media/audiofx/StreamDefaultEffect.java b/media/java/android/media/audiofx/StreamDefaultEffect.java
new file mode 100644
index 0000000..9b1a21a
--- /dev/null
+++ b/media/java/android/media/audiofx/StreamDefaultEffect.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audiofx;
+
+import android.annotation.RequiresPermission;
+import android.app.ActivityThread;
+import android.util.Log;
+import java.util.UUID;
+
+/**
+ * StreamDefaultEffect is a default effect that attaches automatically to all AudioTracks and
+ * MediaPlayer instances of a given stream type.
+ * <p>see {@link android.media.audiofx.DefaultEffect} class for more details on default effects.
+ * @hide
+ */
+
+public class StreamDefaultEffect extends DefaultEffect {
+    static {
+        System.loadLibrary("audioeffect_jni");
+    }
+
+    private final static String TAG = "StreamDefaultEffect-JAVA";
+
+    /**
+     * Class constructor.
+     *
+     * @param type type of effect engine to be default. This parameter is ignored if uuid is set,
+     *             and can be set to {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL}
+     *             in that case.
+     * @param uuid unique identifier of a particular effect implementation to be default. This
+     *             parameter can be set to
+     *             {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL}, in which case only
+     *             the type will be used to select the effect.
+     * @param priority the priority level requested by the application for controlling the effect
+     *             engine. As the same engine can be shared by several applications, this parameter
+     *             indicates how much the requesting application needs control of effect parameters.
+     *             The normal priority is 0, above normal is a positive number, below normal a
+     *             negative number.
+     * @param streamUsage a USAGE_* constant from {@link android.media.AudioAttributes} indicating
+     *             what streams the given effect should attach to by default. Note that similar
+     *             usages may share defaults.
+     *
+     * @throws java.lang.IllegalArgumentException
+     * @throws java.lang.UnsupportedOperationException
+     * @throws java.lang.RuntimeException
+     */
+    @RequiresPermission(value = android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS,
+                        conditional = true)  // Android Things uses an alternate permission.
+    public StreamDefaultEffect(UUID type, UUID uuid, int priority, int streamUsage) {
+        int[] id = new int[1];
+        int initResult = native_setup(type.toString(),
+                                      uuid.toString(),
+                                      priority,
+                                      streamUsage,
+                                      ActivityThread.currentOpPackageName(),
+                                      id);
+        if (initResult != AudioEffect.SUCCESS) {
+            Log.e(TAG, "Error code " + initResult + " when initializing StreamDefaultEffect");
+            switch (initResult) {
+                case AudioEffect.ERROR_BAD_VALUE:
+                    throw (new IllegalArgumentException(
+                            "Stream usage, type uuid, or implementation uuid not supported."));
+                case AudioEffect.ERROR_INVALID_OPERATION:
+                    throw (new UnsupportedOperationException(
+                            "Effect library not loaded"));
+                default:
+                    throw (new RuntimeException(
+                            "Cannot initialize effect engine for type: " + type
+                            + " Error: " + initResult));
+            }
+        }
+
+        mId = id[0];
+    }
+
+
+    /**
+     * Releases the native StreamDefaultEffect resources. It is a good practice to
+     * release the default effect when done with use as control can be returned to
+     * other applications or the native resources released.
+     */
+    public void release() {
+        native_release(mId);
+    }
+
+    @Override
+    protected void finalize() {
+        release();
+    }
+
+    // ---------------------------------------------------------
+    // Native methods called from the Java side
+    // --------------------
+
+    private native final int native_setup(String type,
+                                          String uuid,
+                                          int priority,
+                                          int streamUsage,
+                                          String opPackageName,
+                                          int[] id);
+
+    private native final void native_release(int id);
+}
diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
index f2b4fe0..a7bdf4f 100644
--- a/media/java/android/media/audiofx/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -16,6 +16,7 @@
 
 package android.media.audiofx;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.util.Log;
 import java.lang.ref.WeakReference;
@@ -164,6 +165,7 @@
     /**
      * System wide unique Identifier of the visualizer engine used by this Visualizer instance
      */
+    @UnsupportedAppUsage
     private int mId;
 
     /**
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index fca0cc7..8bc1d35 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.media.AudioDeviceInfo;
 import android.media.AudioFormat;
 import android.media.AudioSystem;
@@ -33,17 +34,24 @@
 @SystemApi
 public class AudioMix {
 
+    @UnsupportedAppUsage
     private AudioMixingRule mRule;
+    @UnsupportedAppUsage
     private AudioFormat mFormat;
+    @UnsupportedAppUsage
     private int mRouteFlags;
+    @UnsupportedAppUsage
     private int mMixType = MIX_TYPE_INVALID;
 
     // written by AudioPolicy
     int mMixState = MIX_STATE_DISABLED;
+    @UnsupportedAppUsage
     int mCallbackFlags;
+    @UnsupportedAppUsage
     String mDeviceAddress;
 
     // initialized in constructor, read by AudioPolicyConfig
+    @UnsupportedAppUsage
     final int mDeviceSystemType; // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
 
     /**
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 749a45e..fbee62a 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -17,6 +17,7 @@
 package android.media.audiopolicy;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.media.AudioAttributes;
 import android.os.Parcel;
 import android.util.Log;
@@ -92,8 +93,11 @@
             RULE_EXCLUSION_MASK | RULE_MATCH_UID;
 
     static final class AudioMixMatchCriterion {
+        @UnsupportedAppUsage
         final AudioAttributes mAttr;
+        @UnsupportedAppUsage
         final int mIntProp;
+        @UnsupportedAppUsage
         final int mRule;
 
         /** input parameters must be valid */
@@ -157,6 +161,7 @@
 
     private final int mTargetMixType;
     int getTargetMixType() { return mTargetMixType; }
+    @UnsupportedAppUsage
     private final ArrayList<AudioMixMatchCriterion> mCriteria;
     ArrayList<AudioMixMatchCriterion> getCriteria() { return mCriteria; }
 
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index de22fa3..c4b82c3 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
@@ -130,9 +131,7 @@
     }
 
     /**
-     * Dispatches the media button event as system service to the session. This only effects the
-     * {@link MediaSession.Callback#getCurrentControllerInfo()} and doesn't bypass any permission
-     * check done by the system service.
+     * Dispatches the media button event as system service to the session.
      * <p>
      * Should be only called by the {@link com.android.internal.policy.PhoneWindow} when the
      * foreground activity didn't consume the key from the hardware devices.
@@ -154,7 +153,7 @@
             return false;
         }
         try {
-            return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub,
+            return mSessionBinder.sendMediaButton(mContext.getOpPackageName(), mCbStub,
                     asSystemService, keyEvent);
         } catch (RemoteException e) {
             // System is dead. =(
@@ -163,9 +162,7 @@
     }
 
     /**
-     * Dispatches the volume button event as system service to the session. This only effects the
-     * {@link MediaSession.Callback#getCurrentControllerInfo()} and doesn't bypass any permission
-     * check done by the system service.
+     * Dispatches the volume button event as system service to the session.
      * <p>
      * Should be only called by the {@link com.android.internal.policy.PhoneWindow} when the
      * foreground activity didn't consume the key from the hardware devices.
@@ -189,8 +186,8 @@
                         break;
                 }
                 try {
-                    mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, true, direction,
-                            AudioManager.FLAG_SHOW_UI);
+                    mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, true,
+                            direction, AudioManager.FLAG_SHOW_UI);
                 } catch (RemoteException e) {
                     Log.wtf(TAG, "Error calling adjustVolumeBy", e);
                 }
@@ -200,7 +197,8 @@
                 final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
                         | AudioManager.FLAG_FROM_KEY;
                 try {
-                    mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, true, 0, flags);
+                    mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, true, 0,
+                            flags);
                 } catch (RemoteException e) {
                     Log.wtf(TAG, "Error calling adjustVolumeBy", e);
                 }
@@ -369,7 +367,7 @@
      */
     public void setVolumeTo(int value, int flags) {
         try {
-            mSessionBinder.setVolumeTo(mContext.getPackageName(), mCbStub, value, flags);
+            mSessionBinder.setVolumeTo(mContext.getOpPackageName(), mCbStub, value, flags);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling setVolumeTo.", e);
         }
@@ -390,7 +388,7 @@
      */
     public void adjustVolume(int direction, int flags) {
         try {
-            mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, false, direction,
+            mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, false, direction,
                     flags);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
@@ -457,7 +455,7 @@
             throw new IllegalArgumentException("command cannot be null or empty");
         }
         try {
-            mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
+            mSessionBinder.sendCommand(mContext.getOpPackageName(), mCbStub, command, args, cb);
         } catch (RemoteException e) {
             Log.d(TAG, "Dead object in sendCommand.", e);
         }
@@ -506,6 +504,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean controlsSameSession(MediaController other) {
         if (other == null) return false;
         return mSessionBinder.asBinder() == other.getSessionBinder().asBinder();
@@ -522,7 +521,7 @@
 
         if (!mCbRegistered) {
             try {
-                mSessionBinder.registerCallbackListener(mContext.getPackageName(), mCbStub);
+                mSessionBinder.registerCallbackListener(mContext.getOpPackageName(), mCbStub);
                 mCbRegistered = true;
             } catch (RemoteException e) {
                 Log.e(TAG, "Dead object in registerCallback", e);
@@ -669,7 +668,7 @@
          */
         public void prepare() {
             try {
-                mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
+                mSessionBinder.prepare(mContext.getOpPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare.", e);
             }
@@ -693,7 +692,7 @@
                         "You must specify a non-empty String for prepareFromMediaId.");
             }
             try {
-                mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
+                mSessionBinder.prepareFromMediaId(mContext.getOpPackageName(), mCbStub, mediaId,
                         extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
@@ -720,7 +719,8 @@
                 query = "";
             }
             try {
-                mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query, extras);
+                mSessionBinder.prepareFromSearch(mContext.getOpPackageName(), mCbStub, query,
+                        extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
             }
@@ -744,7 +744,7 @@
                         "You must specify a non-empty Uri for prepareFromUri.");
             }
             try {
-                mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
+                mSessionBinder.prepareFromUri(mContext.getOpPackageName(), mCbStub, uri, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
             }
@@ -755,7 +755,7 @@
          */
         public void play() {
             try {
-                mSessionBinder.play(mContext.getPackageName(), mCbStub);
+                mSessionBinder.play(mContext.getOpPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play.", e);
             }
@@ -774,7 +774,8 @@
                         "You must specify a non-empty String for playFromMediaId.");
             }
             try {
-                mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId, extras);
+                mSessionBinder.playFromMediaId(mContext.getOpPackageName(), mCbStub, mediaId,
+                        extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
             }
@@ -796,7 +797,7 @@
                 query = "";
             }
             try {
-                mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
+                mSessionBinder.playFromSearch(mContext.getOpPackageName(), mCbStub, query, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + query + ").", e);
             }
@@ -815,7 +816,7 @@
                         "You must specify a non-empty Uri for playFromUri.");
             }
             try {
-                mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
+                mSessionBinder.playFromUri(mContext.getOpPackageName(), mCbStub, uri, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + uri + ").", e);
             }
@@ -827,7 +828,7 @@
          */
         public void skipToQueueItem(long id) {
             try {
-                mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
+                mSessionBinder.skipToQueueItem(mContext.getOpPackageName(), mCbStub, id);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
             }
@@ -839,7 +840,7 @@
          */
         public void pause() {
             try {
-                mSessionBinder.pause(mContext.getPackageName(), mCbStub);
+                mSessionBinder.pause(mContext.getOpPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling pause.", e);
             }
@@ -851,7 +852,7 @@
          */
         public void stop() {
             try {
-                mSessionBinder.stop(mContext.getPackageName(), mCbStub);
+                mSessionBinder.stop(mContext.getOpPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling stop.", e);
             }
@@ -864,7 +865,7 @@
          */
         public void seekTo(long pos) {
             try {
-                mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
+                mSessionBinder.seekTo(mContext.getOpPackageName(), mCbStub, pos);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling seekTo.", e);
             }
@@ -876,7 +877,7 @@
          */
         public void fastForward() {
             try {
-                mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
+                mSessionBinder.fastForward(mContext.getOpPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling fastForward.", e);
             }
@@ -887,7 +888,7 @@
          */
         public void skipToNext() {
             try {
-                mSessionBinder.next(mContext.getPackageName(), mCbStub);
+                mSessionBinder.next(mContext.getOpPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling next.", e);
             }
@@ -899,7 +900,7 @@
          */
         public void rewind() {
             try {
-                mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
+                mSessionBinder.rewind(mContext.getOpPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling rewind.", e);
             }
@@ -910,7 +911,7 @@
          */
         public void skipToPrevious() {
             try {
-                mSessionBinder.previous(mContext.getPackageName(), mCbStub);
+                mSessionBinder.previous(mContext.getOpPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling previous.", e);
             }
@@ -925,7 +926,7 @@
          */
         public void setRating(Rating rating) {
             try {
-                mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
+                mSessionBinder.rate(mContext.getOpPackageName(), mCbStub, rating);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling rate.", e);
             }
@@ -960,7 +961,7 @@
                 throw new IllegalArgumentException("CustomAction cannot be null.");
             }
             try {
-                mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
+                mSessionBinder.sendCustomAction(mContext.getOpPackageName(), mCbStub, action, args);
             } catch (RemoteException e) {
                 Log.d(TAG, "Dead object in sendCustomAction.", e);
             }
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index fad7e3f..d43cd30 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -132,6 +133,7 @@
     private final CallbackStub mCbStub;
 
     // Do not change the name of mCallback. Support lib accesses this by using reflection.
+    @UnsupportedAppUsage
     private CallbackMessageHandler mCallback;
     private VolumeProvider mVolumeProvider;
     private PlaybackState mPlaybackState;
@@ -555,6 +557,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getCallingPackage() {
         if (mCallback != null && mCallback.mCurrentControllerInfo != null) {
             return mCallback.mCurrentControllerInfo.getPackageName();
@@ -1304,6 +1307,7 @@
         public static final int UNKNOWN_ID = -1;
 
         private final MediaDescription mDescription;
+        @UnsupportedAppUsage
         private final long mId;
 
         /**
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index 7c3af31..123c4f7 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -16,6 +16,7 @@
 
 package android.media.session;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
 import android.content.ComponentName;
@@ -65,6 +66,7 @@
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
     }
 
+    @UnsupportedAppUsage
     public static MediaSessionLegacyHelper getHelper(Context context) {
         synchronized (sLock) {
             if (sInstance == null) {
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 3f0b6c5..5ade4dd 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -22,6 +22,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.media.AudioManager;
@@ -144,6 +145,7 @@
      * @return A list of controllers for ongoing sessions.
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull List<MediaController> getActiveSessionsForUser(
             @Nullable ComponentName notificationListener, int userId) {
         ArrayList<MediaController> controllers = new ArrayList<MediaController>();
@@ -321,7 +323,7 @@
     private void dispatchMediaKeyEventInternal(boolean asSystemService, @NonNull KeyEvent keyEvent,
             boolean needWakeLock) {
         try {
-            mService.dispatchMediaKeyEvent(mContext.getPackageName(), asSystemService, keyEvent,
+            mService.dispatchMediaKeyEvent(mContext.getOpPackageName(), asSystemService, keyEvent,
                     needWakeLock);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to send key event.", e);
@@ -357,7 +359,7 @@
     private void dispatchVolumeKeyEventInternal(boolean asSystemService, @NonNull KeyEvent keyEvent,
             int stream, boolean musicOnly) {
         try {
-            mService.dispatchVolumeKeyEvent(mContext.getPackageName(), asSystemService, keyEvent,
+            mService.dispatchVolumeKeyEvent(mContext.getOpPackageName(), asSystemService, keyEvent,
                     stream, musicOnly);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to send volume key event.", e);
@@ -378,7 +380,7 @@
      */
     public void dispatchAdjustVolume(int suggestedStream, int direction, int flags) {
         try {
-            mService.dispatchAdjustVolume(mContext.getPackageName(), suggestedStream, direction,
+            mService.dispatchAdjustVolume(mContext.getOpPackageName(), suggestedStream, direction,
                     flags);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to send adjust volume.", e);
@@ -460,7 +462,7 @@
         try {
             List<Bundle> bundles = mService.getSessionTokens(
                     /* activeSessionOnly */ true, /* sessionServiceOnly */ false,
-                    mContext.getPackageName());
+                    mContext.getOpPackageName());
             return toTokenList(bundles);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Cannot communicate with the service.", e);
@@ -483,7 +485,7 @@
         try {
             List<Bundle> bundles = mService.getSessionTokens(
                     /* activeSessionOnly */ false, /* sessionServiceOnly */ true,
-                    mContext.getPackageName());
+                    mContext.getOpPackageName());
             return toTokenList(bundles);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Cannot communicate with the service.", e);
@@ -508,7 +510,7 @@
         try {
             List<Bundle> bundles = mService.getSessionTokens(
                     /* activeSessionOnly */ false, /* sessionServiceOnly */ false,
-                    mContext.getPackageName());
+                    mContext.getOpPackageName());
             return toTokenList(bundles);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Cannot communicate with the service.", e);
@@ -561,7 +563,8 @@
             SessionTokensChangedWrapper wrapper = new SessionTokensChangedWrapper(
                     mContext, executor, listener);
             try {
-                mService.addSessionTokensListener(wrapper.mStub, userId, mContext.getPackageName());
+                mService.addSessionTokensListener(wrapper.mStub, userId,
+                        mContext.getOpPackageName());
                 mSessionTokensListener.put(listener, wrapper);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error in addSessionTokensListener.", e);
@@ -584,7 +587,8 @@
             SessionTokensChangedWrapper wrapper = mSessionTokensListener.remove(listener);
             if (wrapper != null) {
                 try {
-                    mService.removeSessionTokensListener(wrapper.mStub, mContext.getPackageName());
+                    mService.removeSessionTokensListener(wrapper.mStub,
+                            mContext.getOpPackageName());
                 } catch (RemoteException e) {
                     Log.e(TAG, "Error in removeSessionTokensListener.", e);
                 } finally {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index 7969ee7..56e5566 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
@@ -164,6 +165,7 @@
          * @hide
          */
         @Nullable
+        @UnsupportedAppUsage
         public byte[] getData() {
             if (!mTriggerAvailable) {
                 return mData;
@@ -191,6 +193,7 @@
          * @hide
          */
         @Nullable
+        @UnsupportedAppUsage
         public Integer getCaptureSession() {
             if (mCaptureAvailable) {
                 return mCaptureSession;
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index 107ce8e..9eb0c6d 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -23,6 +23,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -239,6 +240,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @UnsupportedAppUsage
     public int loadSoundModel(SoundModel soundModel) {
         if (soundModel == null) {
             return STATUS_ERROR;
@@ -281,6 +283,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @UnsupportedAppUsage
     public int startRecognition(@NonNull UUID soundModelId, @Nullable Bundle params,
         @NonNull ComponentName detectionService, @NonNull RecognitionConfig config) {
         Preconditions.checkNotNull(soundModelId);
@@ -300,6 +303,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @UnsupportedAppUsage
     public int stopRecognition(UUID soundModelId) {
         if (soundModelId == null) {
             return STATUS_ERROR;
@@ -316,6 +320,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @UnsupportedAppUsage
     public int unloadSoundModel(UUID soundModelId) {
         if (soundModelId == null) {
             return STATUS_ERROR;
@@ -333,6 +338,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @UnsupportedAppUsage
     public boolean isRecognitionActive(UUID soundModelId) {
         if (soundModelId == null) {
             return false;
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 74085d3..5cb8fb8 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.StringRes;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -318,6 +319,7 @@
      * Returns the component of the service that implements this TV input.
      * @hide
      */
+    @UnsupportedAppUsage
     public ComponentName getComponent() {
         return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
     }
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 143182f..ec2d9ba 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -888,6 +888,8 @@
                     if (token != null) {
                         session = new Session(token, channel, mService, mUserId, seq,
                                 mSessionCallbackRecordMap);
+                    } else {
+                        mSessionCallbackRecordMap.delete(seq);
                     }
                     record.postSessionCreated(session);
                 }
@@ -2487,7 +2489,7 @@
                 }
             }
             synchronized (mSessionCallbackRecordMap) {
-                mSessionCallbackRecordMap.remove(mSeq);
+                mSessionCallbackRecordMap.delete(mSeq);
             }
         }
 
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index e24124d..d9017b4 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.Service;
 import android.content.Context;
@@ -283,6 +284,7 @@
         private OverlayViewCleanUpTask mOverlayViewCleanUpTask;
         private boolean mOverlayViewEnabled;
         private IBinder mWindowToken;
+        @UnsupportedAppUsage
         private Rect mOverlayFrame;
         private long mStartPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
         private long mCurrentPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index e568ef7..e67b100 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -52,11 +52,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.IntStream;
-import java.util.stream.Stream;
 
 /**
  * MtpDatabase provides an interface for MTP operations that MtpServer can use. To do this, it uses
@@ -267,6 +266,12 @@
                 if (MtpDatabase.this.mServer != null)
                     MtpDatabase.this.mServer.sendObjectRemoved(id);
             }
+
+            @Override
+            public void sendObjectInfoChanged(int id) {
+                if (MtpDatabase.this.mServer != null)
+                    MtpDatabase.this.mServer.sendObjectInfoChanged(id);
+            }
         }, subDirectories == null ? null : Sets.newHashSet(subDirectories));
 
         initDeviceProperties(context);
@@ -453,21 +458,25 @@
     }
 
     private int[] getObjectList(int storageID, int format, int parent) {
-        Stream<MtpStorageManager.MtpObject> objectStream = mManager.getObjects(parent,
+        List<MtpStorageManager.MtpObject> objs = mManager.getObjects(parent,
                 format, storageID);
-        if (objectStream == null) {
+        if (objs == null) {
             return null;
         }
-        return objectStream.mapToInt(MtpStorageManager.MtpObject::getId).toArray();
+        int[] ret = new int[objs.size()];
+        for (int i = 0; i < objs.size(); i++) {
+            ret[i] = objs.get(i).getId();
+        }
+        return ret;
     }
 
     private int getNumObjects(int storageID, int format, int parent) {
-        Stream<MtpStorageManager.MtpObject> objectStream = mManager.getObjects(parent,
+        List<MtpStorageManager.MtpObject> objs = mManager.getObjects(parent,
                 format, storageID);
-        if (objectStream == null) {
+        if (objs == null) {
             return -1;
         }
-        return (int) objectStream.count();
+        return objs.size();
     }
 
     private MtpPropertyList getObjectPropertyList(int handle, int format, int property,
@@ -489,11 +498,12 @@
             // depth 0: single object, depth 1: immediate children
             return new MtpPropertyList(MtpConstants.RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED);
         }
-        Stream<MtpStorageManager.MtpObject> objectStream = Stream.of();
+        List<MtpStorageManager.MtpObject> objs = null;
+        MtpStorageManager.MtpObject thisObj = null;
         if (handle == 0xFFFFFFFF) {
             // All objects are requested
-            objectStream = mManager.getObjects(0, format, 0xFFFFFFFF);
-            if (objectStream == null) {
+            objs = mManager.getObjects(0, format, 0xFFFFFFFF);
+            if (objs == null) {
                 return new MtpPropertyList(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
             }
         } else if (handle != 0) {
@@ -503,7 +513,7 @@
                 return new MtpPropertyList(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
             }
             if (obj.getFormat() == format || format == 0) {
-                objectStream = Stream.of(obj);
+                thisObj = obj;
             }
         }
         if (handle == 0 || depth == 1) {
@@ -511,19 +521,22 @@
                 handle = 0xFFFFFFFF;
             }
             // Get the direct children of root or this object.
-            Stream<MtpStorageManager.MtpObject> childStream = mManager.getObjects(handle, format,
+            objs = mManager.getObjects(handle, format,
                     0xFFFFFFFF);
-            if (childStream == null) {
+            if (objs == null) {
                 return new MtpPropertyList(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
             }
-            objectStream = Stream.concat(objectStream, childStream);
+        }
+        if (objs == null) {
+            objs = new ArrayList<>();
+        }
+        if (thisObj != null) {
+            objs.add(thisObj);
         }
 
         MtpPropertyList ret = new MtpPropertyList(MtpConstants.RESPONSE_OK);
         MtpPropertyGroup propertyGroup;
-        Iterator<MtpStorageManager.MtpObject> iter = objectStream.iterator();
-        while (iter.hasNext()) {
-            MtpStorageManager.MtpObject obj = iter.next();
+        for (MtpStorageManager.MtpObject obj : objs) {
             if (property == 0xffffffff) {
                 // Get all properties supported by this object
                 propertyGroup = mPropertyGroupsByFormat.get(obj.getFormat());
diff --git a/media/java/android/mtp/MtpPropertyList.java b/media/java/android/mtp/MtpPropertyList.java
index ede90da..557f099 100644
--- a/media/java/android/mtp/MtpPropertyList.java
+++ b/media/java/android/mtp/MtpPropertyList.java
@@ -16,6 +16,7 @@
 
 package android.mtp;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -49,6 +50,7 @@
         mStringValues = new ArrayList<>();
     }
 
+    @UnsupportedAppUsage
     public void append(int handle, int property, int type, long value) {
         mObjectHandles.add(handle);
         mPropertyCodes.add(property);
@@ -57,6 +59,7 @@
         mStringValues.add(null);
     }
 
+    @UnsupportedAppUsage
     public void append(int handle, int property, String value) {
         mObjectHandles.add(handle);
         mPropertyCodes.add(property);
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index 8af5ff7..a555d37 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -77,6 +77,10 @@
         native_send_object_removed(handle);
     }
 
+    public void sendObjectInfoChanged(int handle) {
+        native_send_object_info_changed(handle);
+    }
+
     public void sendDevicePropertyChanged(int property) {
         native_send_device_property_changed(property);
     }
@@ -106,6 +110,7 @@
     private native final void native_cleanup();
     private native final void native_send_object_added(int handle);
     private native final void native_send_object_removed(int handle);
+    private native final void native_send_object_info_changed(int handle);
     private native final void native_send_device_property_changed(int property);
     private native final void native_add_storage(MtpStorage storage);
     private native final void native_remove_storage(int storageId);
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index 2625e0c..c714b3c 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -16,6 +16,7 @@
 
 package android.mtp;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.storage.StorageVolume;
 
 /**
@@ -46,6 +47,7 @@
      *
      * @return the storage ID
      */
+    @UnsupportedAppUsage
     public final int getStorageId() {
         return mStorageId;
     }
@@ -55,6 +57,7 @@
      *
      * @return the storage file path
      */
+    @UnsupportedAppUsage
     public final String getPath() {
         return mPath;
     }
diff --git a/media/java/android/mtp/MtpStorageManager.java b/media/java/android/mtp/MtpStorageManager.java
index a36d88d..f14e7d7 100644
--- a/media/java/android/mtp/MtpStorageManager.java
+++ b/media/java/android/mtp/MtpStorageManager.java
@@ -31,10 +31,8 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Objects;
+import java.util.List;
 import java.util.Set;
-import java.util.stream.Stream;
 
 /**
  * MtpStorageManager provides functionality for listing, tracking, and notifying MtpServer of
@@ -57,7 +55,8 @@
 
         MtpObjectObserver(MtpObject object) {
             super(object.getPath().toString(),
-                    MOVED_FROM | MOVED_TO | DELETE | CREATE | IN_ONLYDIR);
+                    MOVED_FROM | MOVED_TO | DELETE | CREATE | IN_ONLYDIR
+                  | CLOSE_WRITE);
             mObject = object;
         }
 
@@ -87,6 +86,10 @@
                     if (mObject.mObserver != null)
                         mObject.mObserver.stopWatching();
                     mObject.mObserver = null;
+                } else if ((event & CLOSE_WRITE) != 0) {
+                    if (sDebug)
+                        Log.i(TAG, "inotify for " + mObject.getPath() + " CLOSE_WRITE: " + path);
+                    handleChangedObject(mObject, path);
                 } else {
                     Log.w(TAG, "Got unrecognized event " + path + " " + event);
                 }
@@ -304,6 +307,11 @@
          * Called when an object is deleted.
          */
         public abstract void sendObjectRemoved(int id);
+
+        /**
+         * Called when an object info is changed.
+         */
+        public abstract void sendObjectInfoChanged(int id);
     }
 
     private MtpNotifier mMtpNotifier;
@@ -358,13 +366,13 @@
      * Clean up resources used by the storage manager.
      */
     public synchronized void close() {
-        Stream<MtpObject> objs = Stream.concat(mRoots.values().stream(),
-                mObjects.values().stream());
-
-        Iterator<MtpObject> iter = objs.iterator();
-        while (iter.hasNext()) {
-            // Close all FileObservers.
-            MtpObject obj = iter.next();
+        for (MtpObject obj : mObjects.values()) {
+            if (obj.getObserver() != null) {
+                obj.getObserver().stopWatching();
+                obj.setObserver(null);
+            }
+        }
+        for (MtpObject obj : mRoots.values()) {
             if (obj.getObserver() != null) {
                 obj.getObserver().stopWatching();
                 obj.setObserver(null);
@@ -495,49 +503,48 @@
      * @param parent object id of the parent. 0 for all objects, 0xFFFFFFFF for all object in root
      * @param format format of returned objects. 0 for any format
      * @param storageId storage id to look in. 0xFFFFFFFF for all storages
-     * @return A stream of matched objects, or null if error
+     * @return A list of matched objects, or null if error
      */
-    public synchronized Stream<MtpObject> getObjects(int parent, int format, int storageId) {
+    public synchronized List<MtpObject> getObjects(int parent, int format, int storageId) {
         boolean recursive = parent == 0;
+        ArrayList<MtpObject> objs = new ArrayList<>();
+        boolean ret = true;
         if (parent == 0xFFFFFFFF)
             parent = 0;
         if (storageId == 0xFFFFFFFF) {
             // query all stores
             if (parent == 0) {
                 // Get the objects of this format and parent in each store.
-                ArrayList<Stream<MtpObject>> streamList = new ArrayList<>();
                 for (MtpObject root : mRoots.values()) {
-                    streamList.add(getObjects(root, format, recursive));
+                    ret &= getObjects(objs, root, format, recursive);
                 }
-                return Stream.of(streamList).flatMap(Collection::stream).reduce(Stream::concat)
-                        .orElseGet(Stream::empty);
+                return ret ? objs : null;
             }
         }
         MtpObject obj = parent == 0 ? getStorageRoot(storageId) : getObject(parent);
         if (obj == null)
             return null;
-        return getObjects(obj, format, recursive);
+        ret = getObjects(objs, obj, format, recursive);
+        return ret ? objs : null;
     }
 
-    private synchronized Stream<MtpObject> getObjects(MtpObject parent, int format, boolean rec) {
+    private synchronized boolean getObjects(List<MtpObject> toAdd, MtpObject parent, int format, boolean rec) {
         Collection<MtpObject> children = getChildren(parent);
         if (children == null)
-            return null;
-        Stream<MtpObject> ret = Stream.of(children).flatMap(Collection::stream);
+            return false;
 
-        if (format != 0) {
-            ret = ret.filter(o -> o.getFormat() == format);
+        for (MtpObject o : children) {
+            if (format == 0 || o.getFormat() == format) {
+                toAdd.add(o);
+            }
         }
+        boolean ret = true;
         if (rec) {
             // Get all objects recursively.
-            ArrayList<Stream<MtpObject>> streamList = new ArrayList<>();
-            streamList.add(ret);
             for (MtpObject o : children) {
                 if (o.isDir())
-                    streamList.add(getObjects(o, format, true));
+                    ret &= getObjects(toAdd, o, format, true);
             }
-            ret = Stream.of(streamList).filter(Objects::nonNull).flatMap(Collection::stream)
-                    .reduce(Stream::concat).orElseGet(Stream::empty);
         }
         return ret;
     }
@@ -736,6 +743,25 @@
             Log.i(TAG, state + " transitioned to " + obj.getState() + " in op " + op);
     }
 
+    private synchronized void handleChangedObject(MtpObject parent, String path) {
+        MtpOperation op = MtpOperation.NONE;
+        MtpObject obj = parent.getChild(path);
+        if (obj != null) {
+            // Only handle files for size change notification event
+            if ((!obj.isDir()) && (obj.getSize() > 0))
+            {
+                MtpObjectState state = obj.getState();
+                op = obj.getOperation();
+                MtpStorageManager.this.mMtpNotifier.sendObjectInfoChanged(obj.getId());
+                if (sDebug)
+                    Log.d(TAG, "sendObjectInfoChanged: id=" + obj.getId() + ",size=" + obj.getSize());
+            }
+        } else {
+            if (sDebug)
+                Log.w(TAG, "object " + path + " null");
+        }
+    }
+
     /**
      * Block the caller until all events currently in the event queue have been
      * read and processed. Used for testing purposes.
@@ -767,12 +793,11 @@
      * @return true iff cache is consistent
      */
     public synchronized boolean checkConsistency() {
-        Stream<MtpObject> objs = Stream.concat(mRoots.values().stream(),
-                mObjects.values().stream());
-        Iterator<MtpObject> iter = objs.iterator();
+        List<MtpObject> objs = new ArrayList<>();
+        objs.addAll(mRoots.values());
+        objs.addAll(mObjects.values());
         boolean ret = true;
-        while (iter.hasNext()) {
-            MtpObject obj = iter.next();
+        for (MtpObject obj : objs) {
             if (!obj.exists()) {
                 Log.w(TAG, "Object doesn't exist " + obj.getPath() + " " + obj.getId());
                 ret = false;
diff --git a/media/java/android/mtp/OWNERS b/media/java/android/mtp/OWNERS
new file mode 100644
index 0000000..7a14b37
--- /dev/null
+++ b/media/java/android/mtp/OWNERS
@@ -0,0 +1,5 @@
+marcone@google.com
+jsharkey@google.com
+jameswei@google.com
+rmojumder@google.com
+
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index ca7ab7e..5a60ac1 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -89,6 +90,7 @@
      * A key for passing the MediaItem to the ResultReceiver in getItem.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String KEY_MEDIA_ITEM = "media_item";
 
     private static final int RESULT_FLAG_OPTION_NOT_HANDLED = 1 << 0;
@@ -149,6 +151,7 @@
         private Object mDebug;
         private boolean mDetachCalled;
         private boolean mSendResultCalled;
+        @UnsupportedAppUsage
         private int mFlags;
 
         Result(Object debug) {
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index ccfdea3..de9a24b 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -100,7 +100,7 @@
         "android.hardware.cas.native@1.0",  // CasManager. VNDK???
         "libandroid_runtime",  // ???
         "libaudioclient",  // for use of AudioTrack, AudioSystem. to be removed
-        "libdrmframework",  // for FileSource, MediaHTTP
+        "libbinder",
         "libgui",  // for VideoFrameScheduler
         "libhidlallocatorutils",
         "libhidlbase",  // VNDK???
@@ -122,7 +122,6 @@
     static_libs: [
         "libbacktrace",
         "libbase",
-        "libbinder",
         "libc_malloc_debug_backtrace",
         "libcrypto",
         "libcutils",
diff --git a/media/jni/android_media_Media2DataSource.cpp b/media/jni/android_media_Media2DataSource.cpp
index bc3f6bd..b3434e9 100644
--- a/media/jni/android_media_Media2DataSource.cpp
+++ b/media/jni/android_media_Media2DataSource.cpp
@@ -20,12 +20,12 @@
 
 #include "android_media_Media2DataSource.h"
 
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/Log.h"
+#include "log/log.h"
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 
 #include <drm/drm_framework_common.h>
+#include <mediaplayer2/JavaVMHelper.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <nativehelper/ScopedLocalRef.h>
 
@@ -56,7 +56,7 @@
 }
 
 JMedia2DataSource::~JMedia2DataSource() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     env->DeleteGlobalRef(mMedia2DataSourceObj);
     env->DeleteGlobalRef(mByteArrayObj);
 }
@@ -75,12 +75,12 @@
         size = kBufferSize;
     }
 
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     jint numread = env->CallIntMethod(mMedia2DataSourceObj, mReadAtMethod,
             (jlong)offset, mByteArrayObj, (jint)0, (jint)size);
     if (env->ExceptionCheck()) {
         ALOGW("An exception occurred in readAt()");
-        LOGW_EX(env);
+        jniLogException(env, ANDROID_LOG_WARN, LOG_TAG);
         env->ExceptionClear();
         mJavaObjStatus = UNKNOWN_ERROR;
         return -1;
@@ -117,11 +117,11 @@
         return OK;
     }
 
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     *size = env->CallLongMethod(mMedia2DataSourceObj, mGetSizeMethod);
     if (env->ExceptionCheck()) {
         ALOGW("An exception occurred in getSize()");
-        LOGW_EX(env);
+        jniLogException(env, ANDROID_LOG_WARN, LOG_TAG);
         env->ExceptionClear();
         // After returning an error, size shouldn't be used by callers.
         *size = UNKNOWN_ERROR;
@@ -142,7 +142,7 @@
 void JMedia2DataSource::close() {
     Mutex::Autolock lock(mLock);
 
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     env->CallVoidMethod(mMedia2DataSourceObj, mCloseMethod);
     // The closed state is effectively the same as an error state.
     mJavaObjStatus = UNKNOWN_ERROR;
diff --git a/media/jni/android_media_Media2HTTPConnection.cpp b/media/jni/android_media_Media2HTTPConnection.cpp
index 60176e3..d02ee06 100644
--- a/media/jni/android_media_Media2HTTPConnection.cpp
+++ b/media/jni/android_media_Media2HTTPConnection.cpp
@@ -18,14 +18,14 @@
 #define LOG_TAG "Media2HTTPConnection-JNI"
 #include <utils/Log.h>
 
+#include <mediaplayer2/JavaVMHelper.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <nativehelper/ScopedLocalRef.h>
 
 #include "android_media_Media2HTTPConnection.h"
 #include "android_util_Binder.h"
 
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/Log.h"
+#include "log/log.h"
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 
@@ -84,7 +84,7 @@
 }
 
 JMedia2HTTPConnection::~JMedia2HTTPConnection() {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    JNIEnv *env = JavaVMHelper::getJNIEnv();
     env->DeleteGlobalRef(mMedia2HTTPConnectionObj);
     env->DeleteGlobalRef(mByteArrayObj);
 }
@@ -101,7 +101,7 @@
         }
     }
 
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     jstring juri = env->NewStringUTF(uri);
     jstring jheaders = env->NewStringUTF(tmp.string());
 
@@ -115,12 +115,12 @@
 }
 
 void JMedia2HTTPConnection::disconnect() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     env->CallVoidMethod(mMedia2HTTPConnectionObj, mDisconnectMethod);
 }
 
 ssize_t JMedia2HTTPConnection::readAt(off64_t offset, void *data, size_t size) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
 
     if (size > kBufferSize) {
         size = kBufferSize;
@@ -141,12 +141,12 @@
 }
 
 off64_t JMedia2HTTPConnection::getSize() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     return (off64_t)(env->CallLongMethod(mMedia2HTTPConnectionObj, mGetSizeMethod));
 }
 
 status_t JMedia2HTTPConnection::getMIMEType(String8 *mimeType) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     jstring jmime = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetMIMETypeMethod);
     jboolean flag = env->ExceptionCheck();
     if (flag) {
@@ -165,7 +165,7 @@
 }
 
 status_t JMedia2HTTPConnection::getUri(String8 *uri) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     jstring juri = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetUriMethod);
     jboolean flag = env->ExceptionCheck();
     if (flag) {
diff --git a/media/jni/android_media_Media2HTTPService.cpp b/media/jni/android_media_Media2HTTPService.cpp
index 382f099..1c63889 100644
--- a/media/jni/android_media_Media2HTTPService.cpp
+++ b/media/jni/android_media_Media2HTTPService.cpp
@@ -21,11 +21,11 @@
 #include "android_media_Media2HTTPConnection.h"
 #include "android_media_Media2HTTPService.h"
 
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/Log.h"
+#include "log/log.h"
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 
+#include <mediaplayer2/JavaVMHelper.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <nativehelper/ScopedLocalRef.h>
 
@@ -46,12 +46,12 @@
 }
 
 JMedia2HTTPService::~JMedia2HTTPService() {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    JNIEnv *env = JavaVMHelper::getJNIEnv();
     env->DeleteGlobalRef(mMedia2HTTPServiceObj);
 }
 
 sp<MediaHTTPConnection> JMedia2HTTPService::makeHTTPConnection() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = JavaVMHelper::getJNIEnv();
     jobject media2HTTPConnectionObj =
         env->CallObjectMethod(mMedia2HTTPServiceObj, mMakeHTTPConnectionMethod);
 
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 54541f0..7cf8828 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -43,27 +43,27 @@
 
 #define FIND_CLASS(var, className) \
     var = env->FindClass(className); \
-    LOG_FATAL_IF(! (var), "Unable to find class " className);
+    LOG_FATAL_IF(! (var), "Unable to find class %s", className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
     var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-    LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
+    LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
 
 #define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
     var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
-    LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
+    LOG_FATAL_IF(! (var), "Unable to find method %s", fieldName);
 
 #define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
     var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
-    LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
+    LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
 
 #define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
     var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
-    LOG_FATAL_IF(! (var), "Unable to find static method " fieldName);
+    LOG_FATAL_IF(! (var), "Unable to find static method %s", fieldName);
 
-#define GET_STATIC_OBJECT_FIELD(var, clazz, fieldName) \
-    var = env->GetStaticObjectField(clazz, fieldName); \
-    LOG_FATAL_IF(! (var), "Unable to find static object field " fieldName);
+#define GET_STATIC_OBJECT_FIELD(var, clazz, fieldId) \
+    var = env->GetStaticObjectField(clazz, fieldId); \
+    LOG_FATAL_IF(! (var), "Unable to find static object field %p", fieldId);
 
 
 struct RequestFields {
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index d166cc3..4265987 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -29,6 +29,7 @@
 #include <media/stagefright/Utils.h>
 #include <media/stagefright/foundation/ByteUtils.h>  // for FOURCC definition
 #include <mediaplayer2/JAudioTrack.h>
+#include <mediaplayer2/JavaVMHelper.h>
 #include <mediaplayer2/mediaplayer2.h>
 #include <stdio.h>
 #include <assert.h>
@@ -39,7 +40,7 @@
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 #include "android/native_window_jni.h"
-#include "android_runtime/Log.h"
+#include "log/log.h"
 #include "utils/Errors.h"  // for status_t
 #include "utils/KeyedVector.h"
 #include "utils/String8.h"
@@ -184,14 +185,14 @@
 JNIMediaPlayer2Listener::~JNIMediaPlayer2Listener()
 {
     // remove global references
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    JNIEnv *env = JavaVMHelper::getJNIEnv();
     env->DeleteGlobalRef(mObject);
     env->DeleteGlobalRef(mClass);
 }
 
 void JNIMediaPlayer2Listener::notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj)
 {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    JNIEnv *env = JavaVMHelper::getJNIEnv();
     if (obj && obj->dataSize() > 0) {
         jobject jParcel = createJavaParcelObject(env);
         if (jParcel != NULL) {
@@ -207,7 +208,7 @@
     }
     if (env->ExceptionCheck()) {
         ALOGW("An exception occurred while notifying an event.");
-        LOGW_EX(env);
+        jniLogException(env, ANDROID_LOG_WARN, LOG_TAG);
         env->ExceptionClear();
     }
 }
@@ -568,18 +569,6 @@
 }
 
 static void
-android_media_MediaPlayer2_stop(JNIEnv *env, jobject thiz)
-{
-    ALOGV("stop");
-    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return;
-    }
-    process_media_player_call( env, thiz, mp->stop(), NULL, NULL );
-}
-
-static void
 android_media_MediaPlayer2_pause(JNIEnv *env, jobject thiz)
 {
     ALOGV("pause");
@@ -1501,7 +1490,6 @@
     {"_setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
     {"_prepare",            "()V",                              (void *)android_media_MediaPlayer2_prepare},
     {"_start",              "()V",                              (void *)android_media_MediaPlayer2_start},
-    {"_stop",               "()V",                              (void *)android_media_MediaPlayer2_stop},
     {"native_getState",     "()I",                              (void *)android_media_MediaPlayer2_getState},
     {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer2_getVideoWidth},
     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer2_getVideoHeight},
@@ -1552,8 +1540,7 @@
 // This function only registers the native methods
 static int register_android_media_MediaPlayer2Impl(JNIEnv *env)
 {
-    return AndroidRuntime::registerNativeMethods(env,
-                "android/media/MediaPlayer2Impl", gMethods, NELEM(gMethods));
+    return jniRegisterNativeMethods(env, "android/media/MediaPlayer2Impl", gMethods, NELEM(gMethods));
 }
 
 jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
@@ -1572,6 +1559,8 @@
         goto bail;
     }
 
+    JavaVMHelper::setJavaVM(vm);
+
     /* success -- return valid version number */
     result = JNI_VERSION_1_4;
 
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index c60590a..39ff04a 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -135,6 +135,18 @@
 }
 
 static void
+android_mtp_MtpServer_send_object_info_changed(JNIEnv *env, jobject thiz, jint handle)
+{
+    Mutex::Autolock autoLock(sMutex);
+
+    MtpServer* server = getMtpServer(env, thiz);
+    if (server)
+        server->sendObjectInfoChanged(handle);
+    else
+        ALOGE("server is null in send_object_info_changed");
+}
+
+static void
 android_mtp_MtpServer_send_device_property_changed(JNIEnv *env, jobject thiz, jint property)
 {
     Mutex::Autolock autoLock(sMutex);
@@ -202,6 +214,7 @@
     {"native_cleanup",              "()V",  (void *)android_mtp_MtpServer_cleanup},
     {"native_send_object_added",    "(I)V", (void *)android_mtp_MtpServer_send_object_added},
     {"native_send_object_removed",  "(I)V", (void *)android_mtp_MtpServer_send_object_removed},
+    {"native_send_object_info_changed",  "(I)V", (void *)android_mtp_MtpServer_send_object_info_changed},
     {"native_send_device_property_changed",  "(I)V",
                                     (void *)android_mtp_MtpServer_send_device_property_changed},
     {"native_add_storage",          "(Landroid/mtp/MtpStorage;)V",
diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp
index 2aca0c1..09c546a 100644
--- a/media/jni/audioeffect/Android.bp
+++ b/media/jni/audioeffect/Android.bp
@@ -3,6 +3,8 @@
 
     srcs: [
         "android_media_AudioEffect.cpp",
+        "android_media_SourceDefaultEffect.cpp",
+        "android_media_StreamDefaultEffect.cpp",
         "android_media_Visualizer.cpp",
     ],
 
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 51b080a3..693bd8b 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "android_media_AudioEffect.h"
+
 #include <stdio.h>
 
 //#define LOG_NDEBUG 0
@@ -71,7 +73,7 @@
 };
 
 
-static jint translateError(int code) {
+jint AudioEffectJni::translateNativeErrorToJava(int code) {
     switch(code) {
     case NO_ERROR:
         return AUDIOEFFECT_SUCCESS;
@@ -81,6 +83,10 @@
         return AUDIOEFFECT_ERROR_NO_INIT;
     case BAD_VALUE:
         return AUDIOEFFECT_ERROR_BAD_VALUE;
+    case NAME_NOT_FOUND:
+        // Name not found means the client tried to create an effect not found on the system,
+        // which is a form of bad value.
+        return AUDIOEFFECT_ERROR_BAD_VALUE;
     case INVALID_OPERATION:
         return AUDIOEFFECT_ERROR_INVALID_OPERATION;
     case NO_MEMORY:
@@ -359,7 +365,7 @@
         goto setup_failure;
     }
 
-    lStatus = translateError(lpAudioEffect->initCheck());
+    lStatus = AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->initCheck());
     if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) {
         ALOGE("AudioEffect initCheck failed %d", lStatus);
         goto setup_failure;
@@ -495,7 +501,7 @@
         return AUDIOEFFECT_ERROR_NO_INIT;
     }
 
-    return (jint) translateError(lpAudioEffect->setEnabled(enabled));
+    return AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->setEnabled(enabled));
 }
 
 static jboolean
@@ -590,7 +596,7 @@
     if (lpValue != NULL) {
         env->ReleasePrimitiveArrayCritical(pJavaValue, lpValue, 0);
     }
-    return (jint) translateError(lStatus);
+    return AudioEffectJni::translateNativeErrorToJava(lStatus);
 }
 
 static jint
@@ -658,7 +664,7 @@
     if (lStatus == NO_ERROR) {
         return vsize;
     }
-    return (jint) translateError(lStatus);
+    return AudioEffectJni::translateNativeErrorToJava(lStatus);
 }
 
 static jint android_media_AudioEffect_native_command(JNIEnv *env, jobject thiz,
@@ -697,11 +703,12 @@
         }
     }
 
-    lStatus = translateError(lpAudioEffect->command((uint32_t)cmdCode,
-                                                    (uint32_t)cmdSize,
-                                                    pCmdData,
-                                                    (uint32_t *)&replySize,
-                                                    pReplyData));
+    lStatus = AudioEffectJni::translateNativeErrorToJava(
+            lpAudioEffect->command((uint32_t)cmdCode,
+                                   (uint32_t)cmdSize,
+                                   pCmdData,
+                                   (uint32_t *)&replySize,
+                                   pReplyData));
 
 command_Exit:
 
@@ -817,21 +824,19 @@
 android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz __unused,
                                                      jint audioSession)
 {
-    effect_descriptor_t *descriptors = new effect_descriptor_t[AudioEffect::kMaxPreProcessing];
+    auto descriptors = std::make_unique<effect_descriptor_t[]>(AudioEffect::kMaxPreProcessing);
     uint32_t numEffects = AudioEffect::kMaxPreProcessing;
 
     status_t status = AudioEffect::queryDefaultPreProcessing((audio_session_t) audioSession,
-                                           descriptors,
+                                           descriptors.get(),
                                            &numEffects);
     if (status != NO_ERROR || numEffects == 0) {
-        delete[] descriptors;
         return NULL;
     }
     ALOGV("queryDefaultPreProcessing() got %d effects", numEffects);
 
     jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL);
     if (ret == NULL) {
-        delete[] descriptors;
         return ret;
     }
 
@@ -868,7 +873,7 @@
         if (jdesc == NULL) {
             ALOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
             env->DeleteLocalRef(ret);
-            return NULL;;
+            return NULL;
         }
 
         env->SetObjectArrayElement(ret, i, jdesc);
@@ -900,6 +905,8 @@
 
 // ----------------------------------------------------------------------------
 
+extern int register_android_media_SourceDefaultEffect(JNIEnv *env);
+extern int register_android_media_StreamDefaultEffect(JNIEnv *env);
 extern int register_android_media_visualizer(JNIEnv *env);
 
 int register_android_media_AudioEffect(JNIEnv *env)
@@ -924,6 +931,16 @@
         goto bail;
     }
 
+    if (register_android_media_SourceDefaultEffect(env) < 0) {
+        ALOGE("ERROR: SourceDefaultEffect native registration failed\n");
+        goto bail;
+    }
+
+    if (register_android_media_StreamDefaultEffect(env) < 0) {
+        ALOGE("ERROR: StreamDefaultEffect native registration failed\n");
+        goto bail;
+    }
+
     if (register_android_media_visualizer(env) < 0) {
         ALOGE("ERROR: Visualizer native registration failed\n");
         goto bail;
@@ -935,4 +952,3 @@
 bail:
     return result;
 }
-
diff --git a/media/jni/audioeffect/android_media_AudioEffect.h b/media/jni/audioeffect/android_media_AudioEffect.h
new file mode 100644
index 0000000..1d7d75d
--- /dev/null
+++ b/media/jni/audioeffect/android_media_AudioEffect.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_MEDIA_AUDIO_EFFECT_H_
+#define _ANDROID_MEDIA_AUDIO_EFFECT_H_
+
+#include <jni.h>
+
+namespace android {
+
+class AudioEffectJni {
+public:
+    // Convert from native error code to AudioEffect.java error code.
+    static jint translateNativeErrorToJava(int code);
+private:
+    // Static methods only, so private constructor.
+    AudioEffectJni() = default;
+};
+
+} // namespace android
+
+#endif // _ANDROID_MEDIA_AUDIO_EFFECT_H_
diff --git a/media/jni/audioeffect/android_media_SourceDefaultEffect.cpp b/media/jni/audioeffect/android_media_SourceDefaultEffect.cpp
new file mode 100644
index 0000000..d244bcb7
--- /dev/null
+++ b/media/jni/audioeffect/android_media_SourceDefaultEffect.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SourceDefaultEffect-JNI"
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include "media/AudioEffect.h"
+
+#include <nativehelper/ScopedUtfChars.h>
+
+#include "android_media_AudioEffect.h"
+
+using namespace android;
+
+static const char* const kClassPathName = "android/media/audiofx/SourceDefaultEffect";
+
+static jint android_media_SourceDefaultEffect_native_setup(JNIEnv *env,
+                                                           jobject /*thiz*/,
+                                                           jstring type,
+                                                           jstring uuid,
+                                                           jint priority,
+                                                           jint source,
+                                                           jstring opPackageName,
+                                                           jintArray jId)
+{
+    ALOGV("android_media_SourceDefaultEffect_native_setup");
+    status_t lStatus = NO_ERROR;
+    jint* nId = NULL;
+    const char *typeStr = NULL;
+    const char *uuidStr = NULL;
+
+    ScopedUtfChars opPackageNameStr(env, opPackageName);
+
+    if (type != NULL) {
+        typeStr = env->GetStringUTFChars(type, NULL);
+        if (typeStr == NULL) {  // Out of memory
+            lStatus = NO_MEMORY;
+            jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+            goto setup_exit;
+        }
+    }
+
+    if (uuid != NULL) {
+        uuidStr = env->GetStringUTFChars(uuid, NULL);
+        if (uuidStr == NULL) {  // Out of memory
+            lStatus = NO_MEMORY;
+            jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+            goto setup_exit;
+        }
+    }
+
+    if (typeStr == NULL && uuidStr == NULL) {
+        lStatus = BAD_VALUE;
+        goto setup_exit;
+    }
+
+    nId = reinterpret_cast<jint *>(env->GetPrimitiveArrayCritical(jId, NULL));
+    if (nId == NULL) {
+        ALOGE("setup: Error retrieving id pointer");
+        lStatus = BAD_VALUE;
+        goto setup_exit;
+    }
+
+    // create the native SourceDefaultEffect.
+    audio_unique_id_t id;
+    lStatus = AudioEffect::addSourceDefaultEffect(typeStr,
+                                                  String16(opPackageNameStr.c_str()),
+                                                  uuidStr,
+                                                  priority,
+                                                  static_cast<audio_source_t>(source),
+                                                  &id);
+    if (lStatus != NO_ERROR) {
+        ALOGE("setup: Error adding SourceDefaultEffect");
+        goto setup_exit;
+    }
+
+    nId[0] = static_cast<jint>(id);
+
+setup_exit:
+    // Final cleanup and return.
+
+    if (nId != NULL) {
+        env->ReleasePrimitiveArrayCritical(jId, nId, 0);
+        nId = NULL;
+    }
+
+    if (uuidStr != NULL) {
+        env->ReleaseStringUTFChars(uuid, uuidStr);
+        uuidStr = NULL;
+    }
+
+    if (typeStr != NULL) {
+        env->ReleaseStringUTFChars(type, typeStr);
+        typeStr = NULL;
+    }
+
+    return AudioEffectJni::translateNativeErrorToJava(lStatus);
+}
+
+static void android_media_SourceDefaultEffect_native_release(JNIEnv */*env*/,
+                                                             jobject /*thiz*/,
+                                                             jint id) {
+    status_t lStatus = AudioEffect::removeSourceDefaultEffect(id);
+    if (lStatus != NO_ERROR) {
+        ALOGW("Error releasing SourceDefaultEffect: %d", lStatus);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+// Dalvik VM type signatures
+static const JNINativeMethod gMethods[] = {
+    {"native_setup",         "(Ljava/lang/String;Ljava/lang/String;IILjava/lang/String;[I)I",
+                                         (void *)android_media_SourceDefaultEffect_native_setup},
+    {"native_release",       "(I)V",      (void *)android_media_SourceDefaultEffect_native_release},
+};
+
+
+// ----------------------------------------------------------------------------
+
+int register_android_media_SourceDefaultEffect(JNIEnv *env)
+{
+    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
diff --git a/media/jni/audioeffect/android_media_StreamDefaultEffect.cpp b/media/jni/audioeffect/android_media_StreamDefaultEffect.cpp
new file mode 100644
index 0000000..accdddb
--- /dev/null
+++ b/media/jni/audioeffect/android_media_StreamDefaultEffect.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "StreamDefaultEffect-JNI"
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include "media/AudioEffect.h"
+
+#include <nativehelper/ScopedUtfChars.h>
+
+#include "android_media_AudioEffect.h"
+
+using namespace android;
+
+static const char* const kClassPathName = "android/media/audiofx/StreamDefaultEffect";
+
+static jint android_media_StreamDefaultEffect_native_setup(JNIEnv *env,
+                                                           jobject /*thiz*/,
+                                                           jstring type,
+                                                           jstring uuid,
+                                                           jint priority,
+                                                           jint streamUsage,
+                                                           jstring opPackageName,
+                                                           jintArray jId)
+{
+    ALOGV("android_media_StreamDefaultEffect_native_setup");
+    status_t lStatus = NO_ERROR;
+    jint* nId = NULL;
+    const char *typeStr = NULL;
+    const char *uuidStr = NULL;
+
+    ScopedUtfChars opPackageNameStr(env, opPackageName);
+
+    if (type != NULL) {
+        typeStr = env->GetStringUTFChars(type, NULL);
+        if (typeStr == NULL) {  // Out of memory
+            lStatus = NO_MEMORY;
+            jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+            goto setup_exit;
+        }
+    }
+
+    if (uuid != NULL) {
+        uuidStr = env->GetStringUTFChars(uuid, NULL);
+        if (uuidStr == NULL) {  // Out of memory
+            lStatus = NO_MEMORY;
+            jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+            goto setup_exit;
+        }
+    }
+
+    if (typeStr == NULL && uuidStr == NULL) {
+        lStatus = BAD_VALUE;
+        goto setup_exit;
+    }
+
+    nId = reinterpret_cast<jint *>(env->GetPrimitiveArrayCritical(jId, NULL));
+    if (nId == NULL) {
+        ALOGE("setup: Error retrieving id pointer");
+        lStatus = BAD_VALUE;
+        goto setup_exit;
+    }
+
+    // create the native StreamDefaultEffect.
+    audio_unique_id_t id;
+    lStatus = AudioEffect::addStreamDefaultEffect(typeStr,
+                                                  String16(opPackageNameStr.c_str()),
+                                                  uuidStr,
+                                                  priority,
+                                                  static_cast<audio_usage_t>(streamUsage),
+                                                  &id);
+    if (lStatus != NO_ERROR) {
+        ALOGE("setup: Error adding StreamDefaultEffect");
+        goto setup_exit;
+    }
+
+    nId[0] = static_cast<jint>(id);
+
+setup_exit:
+    // Final cleanup and return.
+
+    if (nId != NULL) {
+        env->ReleasePrimitiveArrayCritical(jId, nId, 0);
+        nId = NULL;
+    }
+
+    if (uuidStr != NULL) {
+        env->ReleaseStringUTFChars(uuid, uuidStr);
+        uuidStr = NULL;
+    }
+
+    if (typeStr != NULL) {
+        env->ReleaseStringUTFChars(type, typeStr);
+        typeStr = NULL;
+    }
+
+    return AudioEffectJni::translateNativeErrorToJava(lStatus);
+}
+
+static void android_media_StreamDefaultEffect_native_release(JNIEnv */*env*/,
+                                                             jobject /*thiz*/,
+                                                             jint id) {
+    status_t lStatus = AudioEffect::removeStreamDefaultEffect(id);
+    if (lStatus != NO_ERROR) {
+        ALOGW("Error releasing StreamDefaultEffect: %d", lStatus);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+// Dalvik VM type signatures
+static const JNINativeMethod gMethods[] = {
+    {"native_setup",         "(Ljava/lang/String;Ljava/lang/String;IILjava/lang/String;[I)I",
+                                         (void *)android_media_StreamDefaultEffect_native_setup},
+    {"native_release",       "(I)V",      (void *)android_media_StreamDefaultEffect_native_release},
+};
+
+
+// ----------------------------------------------------------------------------
+
+int register_android_media_StreamDefaultEffect(JNIEnv *env)
+{
+    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
diff --git a/media/lib/remotedisplay/Android.bp b/media/lib/remotedisplay/Android.bp
new file mode 100644
index 0000000..1e9320d
--- /dev/null
+++ b/media/lib/remotedisplay/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+droiddoc {
+    name: "com.android.media.remotedisplay.stubs-gen-docs",
+    srcs: [
+        "java/**/*.java",
+    ],
+    args: " -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
+          " -stubpackages com.android.media.remotedisplay " +
+          " -nodocs ",
+    custom_template: "droiddoc-templates-sdk",
+    installable: false,
+}
+
+java_library_static {
+    name: "com.android.media.remotedisplay.stubs",
+    srcs: [
+        ":com.android.media.remotedisplay.stubs-gen-docs",
+    ],
+    sdk_version: "current",
+}
diff --git a/media/lib/remotedisplay/Android.mk b/media/lib/remotedisplay/Android.mk
index 63f9f91..e88c0f1 100644
--- a/media/lib/remotedisplay/Android.mk
+++ b/media/lib/remotedisplay/Android.mk
@@ -42,24 +42,3 @@
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 
 include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.media.remotedisplay.stubs-gen
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_SRC_FILES := $(call all-java-files-under,java)
-LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/com.android.media.remotedisplay.stubs_intermediates/src
-LOCAL_DROIDDOC_OPTIONS:= \
-    -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 \
-    -stubpackages com.android.media.remotedisplay \
-    -nodocs
-LOCAL_UNINSTALLABLE_MODULE := true
-include $(BUILD_DROIDDOC)
-com_android_media_remotedisplay_gen_stamp := $(full_target)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.media.remotedisplay.stubs
-LOCAL_SDK_VERSION := current
-LOCAL_SOURCE_FILES_ALL_GENERATED := true
-LOCAL_ADDITIONAL_DEPENDENCIES := $(com_android_media_remotedisplay_gen_stamp)
-com_android_media_remotedisplay_gen_stamp :=
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java b/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java
index 5f6d45c..7c90b27 100644
--- a/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java
+++ b/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java
@@ -17,6 +17,7 @@
 
 package android.filterfw;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.filterfw.core.AsyncRunner;
 import android.filterfw.core.FilterGraph;
@@ -83,6 +84,7 @@
     /**
      * Create a new GraphEnvironment with default components.
      */
+    @UnsupportedAppUsage
     public GraphEnvironment() {
         super(null);
     }
@@ -128,6 +130,7 @@
      * @param resourceId    The ID of the graph resource to load.
      * @return              A unique ID for the graph.
      */
+    @UnsupportedAppUsage
     public int loadGraph(Context context, int resourceId) {
         // Read the file into a graph
         FilterGraph graph = null;
@@ -180,6 +183,7 @@
                             MODE_SYNCHRONOUS or MODE_ASYNCHRONOUS.
      * @return              A GraphRunner instance for this graph.
      */
+    @UnsupportedAppUsage
     public GraphRunner getRunner(int graphId, int executionMode) {
         switch (executionMode) {
             case MODE_ASYNCHRONOUS:
diff --git a/media/mca/filterfw/java/android/filterfw/core/Filter.java b/media/mca/filterfw/java/android/filterfw/core/Filter.java
index 062b6ba..4f56b92 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Filter.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Filter.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.FilterContext;
 import android.filterfw.core.FilterPort;
 import android.filterfw.core.KeyValueMap;
@@ -69,6 +70,7 @@
     private boolean mLogVerbose;
     private static final String TAG = "Filter";
 
+    @UnsupportedAppUsage
     public Filter(String name) {
         mName = name;
         mFramesToRelease = new HashSet<Frame>();
@@ -81,6 +83,7 @@
     /** Tests to see if a given filter is installed on the system. Requires
      * full filter package name, including filterpack.
      */
+    @UnsupportedAppUsage
     public static final boolean isAvailable(String filterName) {
         ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
         Class filterClass;
@@ -150,6 +153,7 @@
         port.setFrame(frame);
     }
 
+    @UnsupportedAppUsage
     public final void setInputValue(String inputName, Object value) {
         setInputFrame(inputName, wrapInputValue(inputName, value));
     }
diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterContext.java b/media/mca/filterfw/java/android/filterfw/core/FilterContext.java
index 3c79d1b..a19220e 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FilterContext.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FilterContext.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.Filter;
 import android.filterfw.core.Frame;
 import android.filterfw.core.FrameManager;
@@ -36,6 +37,7 @@
     private HashMap<String, Frame> mStoredFrames = new HashMap<String, Frame>();
     private Set<FilterGraph> mGraphs = new HashSet<FilterGraph>();
 
+    @UnsupportedAppUsage
     public FrameManager getFrameManager() {
         return mFrameManager;
     }
@@ -52,6 +54,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public GLEnvironment getGLEnvironment() {
         return mGLEnvironment;
     }
diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java b/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java
index 12f7892..e6ca11f 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java
@@ -30,6 +30,7 @@
 import android.filterpacks.base.FrameBranch;
 import android.filterpacks.base.NullFilter;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.Log;
 
 /**
@@ -75,6 +76,7 @@
         return mFilters.contains(filter);
     }
 
+    @UnsupportedAppUsage
     public Filter getFilter(String name) {
         return mNameMap.get(name);
     }
@@ -160,6 +162,7 @@
         mTypeCheckMode = typeCheckMode;
     }
 
+    @UnsupportedAppUsage
     public void tearDown(FilterContext context) {
         if (!mFilters.isEmpty()) {
             flushFrames();
diff --git a/media/mca/filterfw/java/android/filterfw/core/Frame.java b/media/mca/filterfw/java/android/filterfw/core/Frame.java
index 7dd0783..e880783 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Frame.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Frame.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.FrameFormat;
 import android.filterfw.core.FrameManager;
 import android.graphics.Bitmap;
@@ -54,6 +55,7 @@
         mBindingId = bindingId;
     }
 
+    @UnsupportedAppUsage
     public FrameFormat getFormat() {
         return mFormat;
     }
@@ -94,6 +96,7 @@
 
     public abstract Object getObjectValue();
 
+    @UnsupportedAppUsage
     public abstract void setInts(int[] ints);
 
     public abstract int[] getInts();
@@ -116,12 +119,15 @@
 
     public abstract void setBitmap(Bitmap bitmap);
 
+    @UnsupportedAppUsage
     public abstract Bitmap getBitmap();
 
+    @UnsupportedAppUsage
     public void setTimestamp(long timestamp) {
         mTimestamp = timestamp;
     }
 
+    @UnsupportedAppUsage
     public long getTimestamp() {
         return mTimestamp;
     }
@@ -138,6 +144,7 @@
         return mRefCount;
     }
 
+    @UnsupportedAppUsage
     public Frame release() {
         if (mFrameManager != null) {
             return mFrameManager.releaseFrame(this);
diff --git a/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java b/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java
index 8f619be..eb0ff0a 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.KeyValueMap;
 import android.filterfw.core.MutableFrameFormat;
 
@@ -90,6 +91,7 @@
         return mBytesPerSample / bytesPerSampleOf(mBaseType);
     }
 
+    @UnsupportedAppUsage
     public int getTarget() {
         return mTarget;
     }
@@ -135,10 +137,12 @@
         return (mDimensions != null && mDimensions.length >= 1) ? mDimensions[0] : -1;
     }
 
+    @UnsupportedAppUsage
     public int getWidth() {
         return getLength();
     }
 
+    @UnsupportedAppUsage
     public int getHeight() {
         return (mDimensions != null && mDimensions.length >= 2) ? mDimensions[1] : -1;
     }
@@ -156,6 +160,7 @@
         return mObjectClass;
     }
 
+    @UnsupportedAppUsage
     public MutableFrameFormat mutableCopy() {
         MutableFrameFormat result = new MutableFrameFormat();
         result.setBaseType(getBaseType());
diff --git a/media/mca/filterfw/java/android/filterfw/core/FrameManager.java b/media/mca/filterfw/java/android/filterfw/core/FrameManager.java
index 8d6c483..85c8fcd 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FrameManager.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FrameManager.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.Frame;
 import android.filterfw.core.FrameFormat;
 import android.filterfw.core.MutableFrameFormat;
@@ -28,10 +29,13 @@
 
     private FilterContext mContext;
 
+    @UnsupportedAppUsage
     public abstract Frame newFrame(FrameFormat format);
 
+    @UnsupportedAppUsage
     public abstract Frame newBoundFrame(FrameFormat format, int bindingType, long bindingId);
 
+    @UnsupportedAppUsage
     public Frame duplicateFrame(Frame frame) {
         Frame result = newFrame(frame.getFormat());
         result.setDataFromFrame(frame);
diff --git a/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java b/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java
index 19d564c..e25d6a7 100644
--- a/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java
+++ b/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.NativeAllocatorTag;
 import android.graphics.SurfaceTexture;
 import android.os.Looper;
@@ -66,6 +67,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public boolean isActive() {
         return nativeIsActive();
     }
@@ -78,6 +80,7 @@
         return nativeIsAnyContextActive();
     }
 
+    @UnsupportedAppUsage
     public void activate() {
         if (Looper.myLooper() != null && Looper.myLooper().equals(Looper.getMainLooper())) {
             Log.e("FilterFramework", "Activating GL context in UI thread!");
@@ -87,12 +90,14 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void deactivate() {
         if (mManageContext && !nativeDeactivate()) {
             throw new RuntimeException("Could not deactivate GLEnvironment!");
         }
     }
 
+    @UnsupportedAppUsage
     public void swapBuffers() {
         if (!nativeSwapBuffers()) {
             throw new RuntimeException("Error swapping EGL buffers!");
@@ -117,6 +122,7 @@
         return result;
     }
 
+    @UnsupportedAppUsage
     public int registerSurfaceFromMediaRecorder(MediaRecorder mediaRecorder) {
         int result = nativeAddSurfaceFromMediaRecorder(mediaRecorder);
         if (result < 0) {
@@ -126,18 +132,21 @@
         return result;
     }
 
+    @UnsupportedAppUsage
     public void activateSurfaceWithId(int surfaceId) {
         if (!nativeActivateSurfaceId(surfaceId)) {
             throw new RuntimeException("Could not activate surface " + surfaceId + "!");
         }
     }
 
+    @UnsupportedAppUsage
     public void unregisterSurfaceId(int surfaceId) {
         if (!nativeRemoveSurfaceId(surfaceId)) {
             throw new RuntimeException("Could not unregister surface " + surfaceId + "!");
         }
     }
 
+    @UnsupportedAppUsage
     public void setSurfaceTimestamp(long timestamp) {
         if (!nativeSetSurfaceTimestamp(timestamp)) {
             throw new RuntimeException("Could not set timestamp for current surface!");
diff --git a/media/mca/filterfw/java/android/filterfw/core/GLFrame.java b/media/mca/filterfw/java/android/filterfw/core/GLFrame.java
index 1558cc6..9e3025f 100644
--- a/media/mca/filterfw/java/android/filterfw/core/GLFrame.java
+++ b/media/mca/filterfw/java/android/filterfw/core/GLFrame.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.Frame;
 import android.filterfw.core.FrameFormat;
 import android.filterfw.core.FrameManager;
@@ -223,6 +224,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void setBitmap(Bitmap bitmap) {
         assertFrameMutable();
         assertGLEnvValid();
@@ -283,6 +285,7 @@
         setNativeViewport(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
     }
 
+    @UnsupportedAppUsage
     public void generateMipMap() {
         assertFrameMutable();
         assertGLEnvValid();
@@ -291,6 +294,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void setTextureParameter(int param, int value) {
         assertFrameMutable();
         assertGLEnvValid();
@@ -300,6 +304,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public int getTextureId() {
         return getNativeTextureId();
     }
diff --git a/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java b/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java
index b496c54..250cfaa 100644
--- a/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java
+++ b/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java
@@ -17,6 +17,8 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * @hide
  */
@@ -50,6 +52,7 @@
         mFilterContext = context;
     }
 
+    @UnsupportedAppUsage
     public abstract FilterGraph getGraph();
 
     public FilterContext getContext() {
@@ -81,12 +84,15 @@
     }
 
     /** Starts running the graph. Will open the filters in the graph if they are not already open. */
+    @UnsupportedAppUsage
     public abstract void run();
 
+    @UnsupportedAppUsage
     public abstract void setDoneCallback(OnRunnerDoneListener listener);
     public abstract boolean isRunning();
 
     /** Stops graph execution. As part of stopping, also closes the graph nodes. */
+    @UnsupportedAppUsage
     public abstract void stop();
 
     /** Closes the filters in a graph. Can only be called if the graph is not running. */
@@ -96,5 +102,6 @@
      * Returns the last exception that happened during an asynchronous run. Returns null if
      * there is nothing to report.
      */
+    @UnsupportedAppUsage
     public abstract Exception getError();
 }
diff --git a/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java b/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java
index 8c78975..ae2ad99 100644
--- a/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java
+++ b/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.FrameFormat;
 import android.filterfw.core.KeyValueMap;
 
@@ -31,6 +32,7 @@
         super();
     }
 
+    @UnsupportedAppUsage
     public MutableFrameFormat(int baseType, int target) {
         super(baseType, target);
     }
@@ -44,6 +46,7 @@
         mTarget = target;
     }
 
+    @UnsupportedAppUsage
     public void setBytesPerSample(int bytesPerSample) {
         mBytesPerSample = bytesPerSample;
         mSize = SIZE_UNKNOWN;
@@ -61,6 +64,7 @@
         mSize = SIZE_UNKNOWN;
     }
 
+    @UnsupportedAppUsage
     public void setDimensions(int width, int height) {
         int[] dimensions = new int[2];
         dimensions[0] = width;
diff --git a/media/mca/filterfw/java/android/filterfw/core/Program.java b/media/mca/filterfw/java/android/filterfw/core/Program.java
index 1930648..376c085 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Program.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Program.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.Frame;
 
 /**
@@ -24,14 +25,17 @@
  */
 public abstract class Program {
 
+    @UnsupportedAppUsage
     public abstract void process(Frame[] inputs, Frame output);
 
+    @UnsupportedAppUsage
     public void process(Frame input, Frame output) {
         Frame[] inputs = new Frame[1];
         inputs[0] = input;
         process(inputs, output);
     }
 
+    @UnsupportedAppUsage
     public abstract void setHostValue(String variableName, Object value);
 
     public abstract Object getHostValue(String variableName);
diff --git a/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java b/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java
index a971cb6..f41636e 100644
--- a/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java
+++ b/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.core;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.Frame;
 import android.filterfw.core.NativeAllocatorTag;
 import android.filterfw.core.Program;
@@ -51,6 +52,7 @@
     private ShaderProgram(NativeAllocatorTag tag) {
     }
 
+    @UnsupportedAppUsage
     public ShaderProgram(FilterContext context, String fragmentShader) {
         mGLEnvironment = getGLEnvironment(context);
         allocate(mGLEnvironment, null, fragmentShader);
@@ -69,6 +71,7 @@
         this.setTimer();
     }
 
+    @UnsupportedAppUsage
     public static ShaderProgram createIdentity(FilterContext context) {
         ShaderProgram program = nativeCreateIdentity(getGLEnvironment(context));
         program.setTimer();
@@ -85,6 +88,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void process(Frame[] inputs, Frame output) {
         if (mTimer.LOG_MFF_RUNNING_TIMES) {
           mTimer.start("glFinish");
@@ -129,6 +133,7 @@
     }
 
     @Override
+    @UnsupportedAppUsage
     public void setHostValue(String variableName, Object value) {
         if (!setUniformValue(variableName, value)) {
             throw new RuntimeException("Error setting uniform value for variable '" +
@@ -167,6 +172,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void setSourceRegion(Quad region) {
         setSourceRegion(region.p0.x, region.p0.y,
                         region.p1.x, region.p1.y,
@@ -181,6 +187,7 @@
                         region.p3.x, region.p3.y);
     }
 
+    @UnsupportedAppUsage
     public void setSourceRect(float x, float y, float width, float height) {
         setSourceRegion(x, y, x + width, y, x, y + height, x + width, y + height);
     }
@@ -225,6 +232,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public void setMaximumTileSize(int size) {
         mMaxTileSize = size;
     }
diff --git a/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java b/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java
index d57f47c..ac08730 100644
--- a/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java
+++ b/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.format;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.core.FrameFormat;
 import android.filterfw.core.MutableFrameFormat;
 import android.graphics.Bitmap;
@@ -48,6 +49,7 @@
         return result;
     }
 
+    @UnsupportedAppUsage
     public static MutableFrameFormat create(int width,
                                             int height,
                                             int colorspace,
@@ -59,6 +61,7 @@
                       target);
     }
 
+    @UnsupportedAppUsage
     public static MutableFrameFormat create(int colorspace, int target) {
         return create(FrameFormat.SIZE_UNSPECIFIED,
                       FrameFormat.SIZE_UNSPECIFIED,
@@ -67,6 +70,7 @@
                       target);
     }
 
+    @UnsupportedAppUsage
     public static MutableFrameFormat create(int colorspace) {
         return create(FrameFormat.SIZE_UNSPECIFIED,
                       FrameFormat.SIZE_UNSPECIFIED,
diff --git a/media/mca/filterfw/java/android/filterfw/geometry/Point.java b/media/mca/filterfw/java/android/filterfw/geometry/Point.java
index 4682a0d..d7acf12 100644
--- a/media/mca/filterfw/java/android/filterfw/geometry/Point.java
+++ b/media/mca/filterfw/java/android/filterfw/geometry/Point.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.geometry;
 
+import android.annotation.UnsupportedAppUsage;
 import java.lang.Math;
 
 /**
@@ -24,12 +25,16 @@
  */
 public class Point {
 
+    @UnsupportedAppUsage
     public float x;
+    @UnsupportedAppUsage
     public float y;
 
+    @UnsupportedAppUsage
     public Point() {
     }
 
+    @UnsupportedAppUsage
     public Point(float x, float y) {
         this.x = x;
         this.y = y;
diff --git a/media/mca/filterfw/java/android/filterfw/geometry/Quad.java b/media/mca/filterfw/java/android/filterfw/geometry/Quad.java
index ee092fd..610e5b8 100644
--- a/media/mca/filterfw/java/android/filterfw/geometry/Quad.java
+++ b/media/mca/filterfw/java/android/filterfw/geometry/Quad.java
@@ -17,6 +17,7 @@
 
 package android.filterfw.geometry;
 
+import android.annotation.UnsupportedAppUsage;
 import android.filterfw.geometry.Point;
 
 import java.lang.Float;
@@ -29,14 +30,20 @@
  */
 public class Quad {
 
+    @UnsupportedAppUsage
     public Point p0;
+    @UnsupportedAppUsage
     public Point p1;
+    @UnsupportedAppUsage
     public Point p2;
+    @UnsupportedAppUsage
     public Point p3;
 
+    @UnsupportedAppUsage
     public Quad() {
     }
 
+    @UnsupportedAppUsage
     public Quad(Point p0, Point p1, Point p2, Point p3) {
         this.p0 = p0;
         this.p1 = p1;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
index b2be464..5ab5092 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
@@ -43,6 +43,8 @@
 import android.hardware.camera2.TotalCaptureResult;
 import android.hardware.camera2.params.InputConfiguration;
 import android.hardware.camera2.params.MeteringRectangle;
+import android.hardware.camera2.params.OutputConfiguration;
+import android.hardware.camera2.params.SessionConfiguration;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.location.Location;
 import android.location.LocationManager;
@@ -75,6 +77,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.Executor;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
@@ -694,6 +697,38 @@
     }
 
     /**
+     * Configure a new camera session with output surfaces and initial session parameters.
+     *
+     * @param camera The CameraDevice to be configured.
+     * @param outputSurfaces The surface list that used for camera output.
+     * @param listener The callback CameraDevice will notify when session is available.
+     * @param handler The handler used to notify callbacks.
+     * @param initialRequest Initial request settings to use as session parameters.
+     */
+    public static CameraCaptureSession configureCameraSessionWithParameters(CameraDevice camera,
+            List<Surface> outputSurfaces, BlockingSessionCallback listener,
+            Handler handler, CaptureRequest initialRequest) throws CameraAccessException {
+        List<OutputConfiguration> outConfigurations = new ArrayList<>(outputSurfaces.size());
+        for (Surface surface : outputSurfaces) {
+            outConfigurations.add(new OutputConfiguration(surface));
+        }
+        SessionConfiguration sessionConfig = new SessionConfiguration(
+                SessionConfiguration.SESSION_REGULAR, outConfigurations,
+                new HandlerExecutor(handler), listener);
+        sessionConfig.setSessionParameters(initialRequest);
+        camera.createCaptureSession(sessionConfig);
+
+        CameraCaptureSession session = listener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+        assertFalse("Camera session should not be a reprocessable session",
+                session.isReprocessable());
+        assertFalse("Capture session type must be regular",
+                CameraConstrainedHighSpeedCaptureSession.class.isAssignableFrom(
+                        session.getClass()));
+
+        return session;
+    }
+
+    /**
      * Configure a new camera session with output surfaces and type.
      *
      * @param camera The CameraDevice to be configured.
@@ -1334,6 +1369,20 @@
         }
     }
 
+    public static class HandlerExecutor implements Executor {
+        private final Handler mHandler;
+
+        public HandlerExecutor(Handler handler) {
+            assertNotNull("handler must be valid", handler);
+            mHandler = handler;
+        }
+
+        @Override
+        public void execute(Runnable runCmd) {
+            mHandler.post(runCmd);
+        }
+    }
+
     /**
      * Provide a mock for {@link CameraDevice.StateCallback}.
      *
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
index ddb05f0..8f27fef 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
@@ -58,6 +58,7 @@
 import static com.android.mediaframeworktest.helpers.CameraTestUtils.SimpleCaptureCallback;
 import static com.android.mediaframeworktest.helpers.CameraTestUtils.SimpleImageReaderListener;
 import static com.android.mediaframeworktest.helpers.CameraTestUtils.configureCameraSession;
+import static com.android.mediaframeworktest.helpers.CameraTestUtils.configureCameraSessionWithParameters;
 import static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedVideoSizes;
 import static com.android.mediaframeworktest.helpers.CameraTestUtils.getValueNotNull;
 
@@ -872,7 +873,6 @@
             outputSurfaces.add(mReaderSurface);
         }
         mSessionListener = new BlockingSessionCallback();
-        mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
 
         CaptureRequest.Builder recordingRequestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
@@ -885,7 +885,10 @@
         }
         recordingRequestBuilder.addTarget(mRecordingSurface);
         recordingRequestBuilder.addTarget(mPreviewSurface);
-        mSession.setRepeatingRequest(recordingRequestBuilder.build(), listener, mHandler);
+        CaptureRequest recordingRequest = recordingRequestBuilder.build();
+        mSession = configureCameraSessionWithParameters(mCamera, outputSurfaces, mSessionListener,
+                mHandler, recordingRequest);
+        mSession.setRepeatingRequest(recordingRequest, listener, mHandler);
 
         if (useMediaRecorder) {
             mMediaRecorder.start();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ImageReaderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ImageReaderTest.java
index f6cd990..2cb5704 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ImageReaderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ImageReaderTest.java
@@ -41,6 +41,7 @@
     private Image mImage3;
 
     @Override
+    @SuppressWarnings("CheckReturnValue")
     protected void setUp() throws Exception {
         super.setUp();
 
diff --git a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
index b05242d..566d1c6 100644
--- a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
+++ b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
@@ -37,6 +37,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.UUID;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
@@ -57,6 +58,7 @@
 
     private ArrayList<Integer> objectsAdded;
     private ArrayList<Integer> objectsRemoved;
+    private ArrayList<Integer> objectsInfoChanged;
 
     private File mainStorageDir;
     private File secondaryStorageDir;
@@ -72,15 +74,42 @@
         Log.d(TAG, Thread.currentThread().getStackTrace()[3].getMethodName());
     }
 
+    private static void logMethodValue(String szVar, int iValue)
+    {
+        Log.d(TAG, szVar + "=" + iValue + ": " + Thread.currentThread().getStackTrace()[3].getMethodName());
+    }
+
+    private static void vWriteNewFile(File newFile) {
+        try {
+            new FileOutputStream(newFile).write(new byte[] {0, 0, 0});
+        } catch (IOException e) {
+            Assert.fail();
+        }
+    }
+
     private static File createNewFile(File parent) {
-        return createNewFile(parent, UUID.randomUUID().toString());
+        return createNewFile(parent, "file-" + UUID.randomUUID().toString());
+    }
+
+    private static File createNewFileNonZero(File parent) {
+        return createNewFileNonZero(parent, "file-" + UUID.randomUUID().toString());
     }
 
     private static File createNewFile(File parent, String name) {
+        return createNewFile(parent, name, false);
+    }
+
+    private static File createNewFileNonZero(File parent, String name) {
+        return createNewFile(parent, name, true);
+    }
+
+    private static File createNewFile(File parent, String name, boolean fgNonZero) {
         try {
             File ret = new File(parent, name);
             if (!ret.createNewFile())
                 throw new AssertionError("Failed to create file");
+            if (fgNonZero)
+                vWriteNewFile(ret);     // create non-zero size file
             return ret;
         } catch (IOException e) {
             throw new AssertionError(e.getMessage());
@@ -95,11 +124,12 @@
     }
 
     private static File createNewDir(File parent) {
-        return createNewDir(parent, UUID.randomUUID().toString());
+        return createNewDir(parent, "dir-" + UUID.randomUUID().toString());
     }
 
     @Before
     public void before() {
+        FileUtils.deleteContentsAndDir(TEMP_DIR_FILE);
         Assert.assertTrue(TEMP_DIR_FILE.mkdir());
         mainStorageDir = createNewDir(TEMP_DIR_FILE);
         secondaryStorageDir = createNewDir(TEMP_DIR_FILE);
@@ -111,17 +141,26 @@
 
         objectsAdded = new ArrayList<>();
         objectsRemoved = new ArrayList<>();
+        objectsInfoChanged = new ArrayList<>();
 
         manager = new MtpStorageManager(new MtpStorageManager.MtpNotifier() {
             @Override
             public void sendObjectAdded(int id) {
+                Log.d(TAG, "sendObjectAdded " + id);
                 objectsAdded.add(id);
             }
 
             @Override
             public void sendObjectRemoved(int id) {
+                Log.d(TAG, "sendObjectRemoved " + id);
                 objectsRemoved.add(id);
             }
+
+            @Override
+            public void sendObjectInfoChanged(int id) {
+                Log.d(TAG, "sendObjectInfoChanged: " + id);
+                objectsInfoChanged.add(id);
+            }
         }, null);
 
         mainMtpStorage = manager.addMtpStorage(mainStorage);
@@ -149,9 +188,9 @@
     public void testMtpObjectGetNameNonRoot() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getName(), newFile.getName());
+        Assert.assertEquals(stream.get(0).getName(), newFile.getName());
     }
 
     @Test
@@ -167,9 +206,9 @@
     public void testMtpObjectGetIdNonRoot() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getId(), 1);
+        Assert.assertEquals(stream.get(0).getId(), 1);
     }
 
     @Test
@@ -185,9 +224,9 @@
     public void testMtpObjectIsDirFalse() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir, "TEST123.mp3");
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertFalse(stream.findFirst().get().isDir());
+        Assert.assertFalse(stream.get(0).isDir());
     }
 
     @Test
@@ -195,9 +234,9 @@
     public void testMtpObjectGetFormatDir() {
         logMethodName();
         File newFile = createNewDir(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getFormat(), MtpConstants.FORMAT_ASSOCIATION);
+        Assert.assertEquals(stream.get(0).getFormat(), MtpConstants.FORMAT_ASSOCIATION);
     }
 
     @Test
@@ -205,9 +244,9 @@
     public void testMtpObjectGetFormatNonDir() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir, "TEST123.mp3");
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getFormat(), MtpConstants.FORMAT_MP3);
+        Assert.assertEquals(stream.get(0).getFormat(), MtpConstants.FORMAT_MP3);
     }
 
     @Test
@@ -215,9 +254,9 @@
     public void testMtpObjectGetStorageId() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getStorageId(), mainMtpStorage.getStorageId());
+        Assert.assertEquals(stream.get(0).getStorageId(), mainMtpStorage.getStorageId());
     }
 
     @Test
@@ -225,10 +264,9 @@
     public void testMtpObjectGetLastModified() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getModifiedTime(),
-                newFile.lastModified() / 1000);
+        Assert.assertEquals(stream.get(0).getModifiedTime(), newFile.lastModified() / 1000);
     }
 
     @Test
@@ -236,9 +274,9 @@
     public void testMtpObjectGetParent() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getParent(),
+        Assert.assertEquals(stream.get(0).getParent(),
                 manager.getStorageRoot(mainMtpStorage.getStorageId()));
     }
 
@@ -247,9 +285,9 @@
     public void testMtpObjectGetRoot() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getRoot(),
+        Assert.assertEquals(stream.get(0).getRoot(),
                 manager.getStorageRoot(mainMtpStorage.getStorageId()));
     }
 
@@ -258,9 +296,9 @@
     public void testMtpObjectGetPath() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getPath().toString(), newFile.getPath());
+        Assert.assertEquals(stream.get(0).getPath().toString(), newFile.getPath());
     }
 
     @Test
@@ -273,9 +311,9 @@
         } catch (IOException e) {
             Assert.fail();
         }
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getSize(), 8);
+        Assert.assertEquals(stream.get(0).getSize(), 8);
     }
 
     @Test
@@ -283,9 +321,9 @@
     public void testMtpObjectGetSizeDir() {
         logMethodName();
         File newDir = createNewDir(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getSize(), 0);
+        Assert.assertEquals(stream.get(0).getSize(), 0);
     }
 
     /** MtpStorageManager cache access tests. **/
@@ -304,9 +342,9 @@
     public void testRemoveMtpStorage() {
         logMethodName();
         File newFile = createNewFile(secondaryStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 secondaryMtpStorage.getStorageId());
-        Assert.assertEquals(stream.count(), 1);
+        Assert.assertEquals(stream.size(), 1);
 
         manager.removeMtpStorage(secondaryMtpStorage);
         Assert.assertNull(manager.getStorageRoot(secondaryMtpStorage.getStorageId()));
@@ -377,9 +415,9 @@
         MtpStorageManager.MtpObject parent = manager.getByPath(newDir.getPath());
         Assert.assertNotNull(parent);
 
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(parent.getId(), 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(parent.getId(), 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.count(), 2);
+        Assert.assertEquals(stream.size(), 2);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -393,9 +431,9 @@
         MtpStorageManager.MtpObject parent = manager.getByPath(newDir.getPath());
         Assert.assertNotNull(parent);
 
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(parent.getId(),
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(parent.getId(),
                 MtpConstants.FORMAT_MP3, mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.findFirst().get().getPath().toString(), newMP3File.toString());
+        Assert.assertEquals(stream.get(0).getPath().toString(), newMP3File.toString());
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -407,9 +445,9 @@
         File newFile = createNewFile(mainStorageDir);
         File newMP3File = createNewFile(newDir, "lalala.mp3");
 
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.count(), 2);
+        Assert.assertEquals(stream.size(), 2);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -421,9 +459,9 @@
         File newFile = createNewFile(mainStorageDir);
         File newMP3File = createNewFile(newDir, "lalala.mp3");
 
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.count(), 3);
+        Assert.assertEquals(stream.size(), 3);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -438,8 +476,8 @@
         createNewFile(secondaryStorageDir);
         createNewFile(newDir2, "lalala.mp3");
 
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0, 0, 0xFFFFFFFF);
-        Assert.assertEquals(stream.count(), 6);
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0, 0, 0xFFFFFFFF);
+        Assert.assertEquals(stream.size(), 6);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -454,8 +492,8 @@
         createNewFile(secondaryStorageDir);
         createNewFile(newDir2, "lalala.mp3");
 
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0, 0xFFFFFFFF);
-        Assert.assertEquals(stream.count(), 4);
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0, 0xFFFFFFFF);
+        Assert.assertEquals(stream.size(), 4);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -465,15 +503,20 @@
     @SmallTest
     public void testObjectAdded() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.count(), 0);
+        Assert.assertEquals(stream.size(), 0);
 
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertEquals(manager.getObject(objectsAdded.get(0)).getPath().toString(),
                 newFile.getPath());
+
+        logMethodValue("objectsInfoChanged.size", objectsInfoChanged.size());
+        if (objectsInfoChanged.size() > 0)
+            Assert.assertEquals(objectsAdded.get(0).intValue(), objectsInfoChanged.get(0).intValue());
+
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -481,9 +524,9 @@
     @SmallTest
     public void testObjectAddedDir() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.count(), 0);
+        Assert.assertEquals(stream.size(), 0);
 
         File newDir = createNewDir(mainStorageDir);
         manager.flushEvents();
@@ -491,6 +534,7 @@
         Assert.assertEquals(manager.getObject(objectsAdded.get(0)).getPath().toString(),
                 newDir.getPath());
         Assert.assertTrue(manager.getObject(objectsAdded.get(0)).isDir());
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -498,9 +542,9 @@
     @SmallTest
     public void testObjectAddedRecursiveDir() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.count(), 0);
+        Assert.assertEquals(stream.size(), 0);
 
         File newDir = createNewDir(createNewDir(createNewDir(mainStorageDir)));
         manager.flushEvents();
@@ -508,6 +552,7 @@
         Assert.assertEquals(manager.getObject(objectsAdded.get(2)).getPath().toString(),
                 newDir.getPath());
         Assert.assertTrue(manager.getObject(objectsAdded.get(2)).isDir());
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -516,9 +561,9 @@
     public void testObjectRemoved() {
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.count(), 1);
+        Assert.assertEquals(stream.size(), 1);
 
         Assert.assertTrue(newFile.delete());
         manager.flushEvents();
@@ -531,10 +576,10 @@
     @SmallTest
     public void testObjectMoved() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        File newFile = createNewFileNonZero(mainStorageDir);
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
-        Assert.assertEquals(stream.count(), 1);
+        Assert.assertEquals(stream.size(), 1);
         File toFile = new File(mainStorageDir, "to" + newFile.getName());
 
         Assert.assertTrue(newFile.renameTo(toFile));
@@ -544,6 +589,7 @@
         Assert.assertEquals(manager.getObject(objectsAdded.get(0)).getPath().toString(),
                 toFile.getPath());
         Assert.assertNull(manager.getObject(objectsRemoved.get(0)));
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -555,13 +601,13 @@
     @SmallTest
     public void testSendObjectSuccess() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
         int id = manager.beginSendObject(manager.getStorageRoot(mainMtpStorage.getStorageId()),
                 "newFile", MtpConstants.FORMAT_UNDEFINED);
         Assert.assertEquals(id, 1);
 
-        File newFile = createNewFile(mainStorageDir, "newFile");
+        File newFile = createNewFileNonZero(mainStorageDir, "newFile");
         manager.flushEvents();
         MtpStorageManager.MtpObject obj = manager.getObject(id);
         Assert.assertTrue(manager.endSendObject(obj, true));
@@ -574,7 +620,7 @@
     @SmallTest
     public void testSendObjectSuccessDir() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
         int id = manager.beginSendObject(manager.getStorageRoot(mainMtpStorage.getStorageId()),
                 "newDir", MtpConstants.FORMAT_ASSOCIATION);
@@ -586,11 +632,12 @@
         Assert.assertTrue(manager.endSendObject(obj, true));
         Assert.assertEquals(obj.getPath().toString(), newFile.getPath());
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(obj.getFormat(), MtpConstants.FORMAT_ASSOCIATION);
         Assert.assertTrue(manager.checkConsistency());
 
         // Check that new dir receives events
-        File newerFile = createNewFile(newFile);
+        File newerFile = createNewFileNonZero(newFile);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertEquals(manager.getObject(objectsAdded.get(0)).getPath().toString(),
@@ -601,7 +648,7 @@
     @SmallTest
     public void testSendObjectSuccessDelayed() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
         int id = manager.beginSendObject(manager.getStorageRoot(mainMtpStorage.getStorageId()),
                 "newFile", MtpConstants.FORMAT_UNDEFINED);
@@ -609,7 +656,7 @@
         MtpStorageManager.MtpObject obj = manager.getObject(id);
         Assert.assertTrue(manager.endSendObject(obj, true));
 
-        File newFile = createNewFile(mainStorageDir, "newFile");
+        File newFile = createNewFileNonZero(mainStorageDir, "newFile");
         manager.flushEvents();
         Assert.assertEquals(obj.getPath().toString(), newFile.getPath());
         Assert.assertEquals(objectsAdded.size(), 0);
@@ -620,7 +667,7 @@
     @SmallTest
     public void testSendObjectSuccessDirDelayed() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
         int id = manager.beginSendObject(manager.getStorageRoot(mainMtpStorage.getStorageId()),
                 "newDir", MtpConstants.FORMAT_ASSOCIATION);
@@ -632,11 +679,12 @@
         manager.flushEvents();
         Assert.assertEquals(obj.getPath().toString(), newFile.getPath());
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(obj.getFormat(), MtpConstants.FORMAT_ASSOCIATION);
         Assert.assertTrue(manager.checkConsistency());
 
         // Check that new dir receives events
-        File newerFile = createNewFile(newFile);
+        File newerFile = createNewFileNonZero(newFile);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertEquals(manager.getObject(objectsAdded.get(0)).getPath().toString(),
@@ -647,7 +695,7 @@
     @SmallTest
     public void testSendObjectSuccessDeleted() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
         int id = manager.beginSendObject(manager.getStorageRoot(mainMtpStorage.getStorageId()),
                 "newFile", MtpConstants.FORMAT_UNDEFINED);
@@ -667,7 +715,7 @@
     @SmallTest
     public void testSendObjectFailed() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
         int id = manager.beginSendObject(manager.getStorageRoot(mainMtpStorage.getStorageId()),
                 "newFile", MtpConstants.FORMAT_UNDEFINED);
@@ -682,19 +730,20 @@
     @SmallTest
     public void testSendObjectFailedDeleted() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
         int id = manager.beginSendObject(manager.getStorageRoot(mainMtpStorage.getStorageId()),
                 "newFile", MtpConstants.FORMAT_UNDEFINED);
         Assert.assertEquals(id, 1);
         MtpStorageManager.MtpObject obj = manager.getObject(id);
 
-        File newFile = createNewFile(mainStorageDir, "newFile");
+        File newFile = createNewFileNonZero(mainStorageDir, "newFile");
         Assert.assertTrue(newFile.delete());
         manager.flushEvents();
         Assert.assertTrue(manager.endSendObject(obj, false));
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -702,7 +751,7 @@
     @SmallTest
     public void testSendObjectFailedAdded() {
         logMethodName();
-        Stream<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
+        List<MtpStorageManager.MtpObject> stream = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId());
         int id = manager.beginSendObject(manager.getStorageRoot(mainMtpStorage.getStorageId()),
                 "newFile", MtpConstants.FORMAT_UNDEFINED);
@@ -713,15 +762,21 @@
         manager.flushEvents();
         Assert.assertTrue(manager.endSendObject(obj, false));
         Assert.assertNotEquals(objectsAdded.get(0).intValue(), id);
+        logMethodValue("objectsInfoChanged.size", objectsInfoChanged.size());
+        if (objectsInfoChanged.size() > 0)
+            Assert.assertNotEquals(objectsInfoChanged.get(0).intValue(), id);
         Assert.assertNull(manager.getObject(id));
         Assert.assertEquals(manager.getObject(objectsAdded.get(0)).getPath().toString(),
                 newDir.getPath());
         Assert.assertTrue(manager.checkConsistency());
 
         // Expect events in new dir
-        createNewFile(newDir);
+        createNewFileNonZero(newDir);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 2);
+        logMethodValue("objectsInfoChanged.size", objectsInfoChanged.size());
+        if (objectsInfoChanged.size() == 1)
+            Assert.assertEquals(objectsAdded.get(1).intValue(), objectsInfoChanged.get(0).intValue());
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -731,7 +786,7 @@
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRemoveObject(obj));
 
         Assert.assertTrue(newFile.delete());
@@ -748,7 +803,7 @@
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRemoveObject(obj));
 
         Assert.assertTrue(manager.endRemoveObject(obj, true));
@@ -764,19 +819,19 @@
     public void testRemoveObjectDir() {
         logMethodName();
         File newDir = createNewDir(mainStorageDir);
-        createNewFile(createNewDir(newDir));
+        createNewFileNonZero(createNewDir(newDir));
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         manager.getObjects(obj.getId(), 0, mainMtpStorage.getStorageId());
         Assert.assertTrue(manager.beginRemoveObject(obj));
 
-        createNewFile(newDir);
+        createNewFileNonZero(newDir);
         Assert.assertTrue(FileUtils.deleteContentsAndDir(newDir));
         manager.flushEvents();
         Assert.assertTrue(manager.endRemoveObject(obj, true));
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertEquals(objectsRemoved.size(), 1);
-        Assert.assertEquals(manager.getObjects(0, 0, mainMtpStorage.getStorageId()).count(), 0);
+        Assert.assertEquals(manager.getObjects(0, 0, mainMtpStorage.getStorageId()).size(), 0);
         Assert.assertNull(manager.getObject(obj.getId()));
         Assert.assertTrue(manager.checkConsistency());
     }
@@ -788,14 +843,14 @@
         File newDir = createNewDir(mainStorageDir);
         createNewFile(createNewDir(newDir));
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRemoveObject(obj));
 
         Assert.assertTrue(manager.endRemoveObject(obj, true));
         Assert.assertTrue(FileUtils.deleteContentsAndDir(newDir));
         manager.flushEvents();
         Assert.assertEquals(objectsRemoved.size(), 0);
-        Assert.assertEquals(manager.getObjects(0, 0, mainMtpStorage.getStorageId()).count(), 0);
+        Assert.assertEquals(manager.getObjects(0, 0, mainMtpStorage.getStorageId()).size(), 0);
         Assert.assertNull(manager.getObject(obj.getId()));
         Assert.assertTrue(manager.checkConsistency());
     }
@@ -806,18 +861,21 @@
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         int id = obj.getId();
         Assert.assertTrue(manager.beginRemoveObject(obj));
 
         Assert.assertTrue(newFile.delete());
-        createNewFile(mainStorageDir, newFile.getName());
+        createNewFileNonZero(mainStorageDir, newFile.getName());
         manager.flushEvents();
         Assert.assertTrue(manager.endRemoveObject(obj, true));
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertNull(manager.getObject(id));
         Assert.assertNotEquals(objectsAdded.get(0).intValue(), id);
+        logMethodValue("objectsInfoChanged.size", objectsInfoChanged.size());
+        if (objectsInfoChanged.size() > 0)
+            Assert.assertNotEquals(objectsInfoChanged.get(0).intValue(), objectsAdded.get(0).intValue());
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -827,7 +885,7 @@
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRemoveObject(obj));
 
         Assert.assertTrue(manager.endRemoveObject(obj, false));
@@ -841,7 +899,7 @@
         logMethodName();
         File newDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         manager.getObjects(obj.getId(), 0, mainMtpStorage.getStorageId());
         Assert.assertTrue(manager.beginRemoveObject(obj));
 
@@ -850,6 +908,7 @@
         Assert.assertTrue(manager.endRemoveObject(obj, false));
         Assert.assertEquals(manager.getObject(obj.getId()), obj);
         Assert.assertEquals(objectsAdded.size(), 1);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -859,7 +918,7 @@
         logMethodName();
         File newFile = createNewFile(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRemoveObject(obj));
 
         Assert.assertTrue(newFile.delete());
@@ -875,18 +934,18 @@
     @SmallTest
     public void testCopyObjectSuccess() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         File newDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
                 mainMtpStorage.getStorageId())
-                .filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
+                .stream().filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> !o.isDir()).findFirst().get();
 
         int id = manager.beginCopyObject(fileObj, dirObj);
         Assert.assertNotEquals(id, -1);
-        createNewFile(newDir, newFile.getName());
+        createNewFileNonZero(newDir, newFile.getName());
         manager.flushEvents();
         MtpStorageManager.MtpObject obj = manager.getObject(id);
         Assert.assertTrue(manager.endCopyObject(obj, true));
@@ -900,15 +959,15 @@
         logMethodName();
         File newDirFrom = createNewDir(mainStorageDir);
         File newDirFrom1 = createNewDir(newDirFrom);
-        File newDirFrom2 = createNewFile(newDirFrom1);
-        File delayedFile = createNewFile(newDirFrom);
-        File deletedFile = createNewFile(newDirFrom);
+        File newDirFrom2 = createNewFileNonZero(newDirFrom1);
+        File delayedFile = createNewFileNonZero(newDirFrom);
+        File deletedFile = createNewFileNonZero(newDirFrom);
         File newDirTo = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject toObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> o.getName().equals(newDirTo.getName())).findFirst().get();
         MtpStorageManager.MtpObject fromObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> o.getName().equals(newDirFrom.getName())).findFirst().get();
 
         manager.getObjects(fromObj.getId(), 0, mainMtpStorage.getStorageId());
@@ -916,9 +975,9 @@
         Assert.assertNotEquals(id, -1);
         File copiedDir = createNewDir(newDirTo, newDirFrom.getName());
         File copiedDir1 = createNewDir(copiedDir, newDirFrom1.getName());
-        createNewFile(copiedDir1, newDirFrom2.getName());
-        createNewFile(copiedDir, "extraFile");
-        File toDelete = createNewFile(copiedDir, deletedFile.getName());
+        createNewFileNonZero(copiedDir1, newDirFrom2.getName());
+        createNewFileNonZero(copiedDir, "extraFile");
+        File toDelete = createNewFileNonZero(copiedDir, deletedFile.getName());
         manager.flushEvents();
         Assert.assertTrue(toDelete.delete());
         manager.flushEvents();
@@ -927,19 +986,19 @@
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertEquals(objectsRemoved.size(), 1);
 
-        createNewFile(copiedDir, delayedFile.getName());
+        createNewFileNonZero(copiedDir, delayedFile.getName());
         manager.flushEvents();
         Assert.assertTrue(manager.checkConsistency());
 
         // Expect events in the visited dir, but not the unvisited dir.
-        createNewFile(copiedDir);
-        createNewFile(copiedDir1);
+        createNewFileNonZero(copiedDir);
+        createNewFileNonZero(copiedDir1);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 2);
         Assert.assertEquals(objectsAdded.size(), 2);
 
         // Number of files/dirs created, minus the one that was deleted.
-        Assert.assertEquals(manager.getObjects(0, 0, mainMtpStorage.getStorageId()).count(), 13);
+        Assert.assertEquals(manager.getObjects(0, 0, mainMtpStorage.getStorageId()).size(), 13);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -947,13 +1006,13 @@
     @SmallTest
     public void testCopyObjectFailed() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         File newDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> !o.isDir()).findFirst().get();
 
         int id = manager.beginCopyObject(fileObj, dirObj);
@@ -962,6 +1021,7 @@
         MtpStorageManager.MtpObject obj = manager.getObject(id);
         Assert.assertTrue(manager.endCopyObject(obj, false));
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -969,13 +1029,13 @@
     @SmallTest
     public void testCopyObjectFailedAdded() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         File newDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> !o.isDir()).findFirst().get();
 
         int id = manager.beginCopyObject(fileObj, dirObj);
@@ -989,7 +1049,7 @@
         Assert.assertTrue(manager.checkConsistency());
 
         // Expect events in new dir
-        createNewFile(addedDir);
+        createNewFileNonZero(addedDir);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 2);
         Assert.assertTrue(manager.checkConsistency());
@@ -999,18 +1059,18 @@
     @SmallTest
     public void testCopyObjectFailedDeleted() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         File newDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> !o.isDir()).findFirst().get();
 
         int id = manager.beginCopyObject(fileObj, dirObj);
         Assert.assertNotEquals(id, -1);
-        Assert.assertTrue(createNewFile(newDir, newFile.getName()).delete());
+        Assert.assertTrue(createNewFileNonZero(newDir, newFile.getName()).delete());
         manager.flushEvents();
         MtpStorageManager.MtpObject obj = manager.getObject(id);
         Assert.assertTrue(manager.endCopyObject(obj, false));
@@ -1022,9 +1082,9 @@
     @SmallTest
     public void testRenameObjectSuccess() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRenameObject(obj, "renamed"));
 
         File renamed = new File(mainStorageDir, "renamed");
@@ -1033,6 +1093,7 @@
         Assert.assertTrue(manager.endRenameObject(obj, newFile.getName(), true));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(obj.getPath().toString(), renamed.getPath());
 
@@ -1045,7 +1106,7 @@
         logMethodName();
         File newDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRenameObject(obj, "renamed"));
 
         File renamed = new File(mainStorageDir, "renamed");
@@ -1054,6 +1115,7 @@
         Assert.assertTrue(manager.endRenameObject(obj, newDir.getName(), true));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(obj.getPath().toString(), renamed.getPath());
 
@@ -1063,6 +1125,7 @@
         createNewFile(renamed);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -1072,7 +1135,7 @@
         logMethodName();
         File newDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         manager.getObjects(obj.getId(), 0, mainMtpStorage.getStorageId());
         Assert.assertTrue(manager.beginRenameObject(obj, "renamed"));
 
@@ -1082,13 +1145,14 @@
         Assert.assertTrue(manager.endRenameObject(obj, newDir.getName(), true));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(obj.getPath().toString(), renamed.getPath());
 
         Assert.assertTrue(manager.checkConsistency());
 
         // Expect events since the dir was visited
-        createNewFile(renamed);
+        createNewFileNonZero(renamed);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertTrue(manager.checkConsistency());
@@ -1098,9 +1162,9 @@
     @SmallTest
     public void testRenameObjectDelayed() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRenameObject(obj, "renamed"));
 
         Assert.assertTrue(manager.endRenameObject(obj, newFile.getName(), true));
@@ -1109,6 +1173,7 @@
         manager.flushEvents();
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(obj.getPath().toString(), renamed.getPath());
 
@@ -1121,7 +1186,7 @@
         logMethodName();
         File newDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         manager.getObjects(obj.getId(), 0, mainMtpStorage.getStorageId());
         Assert.assertTrue(manager.beginRenameObject(obj, "renamed"));
 
@@ -1131,13 +1196,14 @@
         manager.flushEvents();
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(obj.getPath().toString(), renamed.getPath());
 
         Assert.assertTrue(manager.checkConsistency());
 
         // Expect events since the dir was visited
-        createNewFile(renamed);
+        createNewFileNonZero(renamed);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertTrue(manager.checkConsistency());
@@ -1147,14 +1213,15 @@
     @SmallTest
     public void testRenameObjectFailed() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRenameObject(obj, "renamed"));
 
         Assert.assertTrue(manager.endRenameObject(obj, newFile.getName(), false));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
 
         Assert.assertTrue(manager.checkConsistency());
@@ -1164,9 +1231,9 @@
     @SmallTest
     public void testRenameObjectFailedOldRemoved() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRenameObject(obj, "renamed"));
 
         Assert.assertTrue(newFile.delete());
@@ -1174,6 +1241,7 @@
         Assert.assertTrue(manager.endRenameObject(obj, newFile.getName(), false));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 1);
 
         Assert.assertTrue(manager.checkConsistency());
@@ -1183,16 +1251,19 @@
     @SmallTest
     public void testRenameObjectFailedNewAdded() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject obj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginRenameObject(obj, "renamed"));
 
-        createNewFile(mainStorageDir, "renamed");
+        createNewFileNonZero(mainStorageDir, "renamed");
         manager.flushEvents();
         Assert.assertTrue(manager.endRenameObject(obj, newFile.getName(), false));
 
         Assert.assertEquals(objectsAdded.size(), 1);
+        logMethodValue("objectsInfoChanged.size", objectsInfoChanged.size());
+        if (objectsInfoChanged.size() > 0)
+            Assert.assertNotEquals(objectsAdded.get(0).intValue(), objectsInfoChanged.get(0).intValue());
         Assert.assertEquals(objectsRemoved.size(), 0);
 
         Assert.assertTrue(manager.checkConsistency());
@@ -1202,13 +1273,13 @@
     @SmallTest
     public void testMoveObjectSuccess() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         File dir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> !o.isDir()).findFirst().get();
         Assert.assertTrue(manager.beginMoveObject(fileObj, dirObj));
 
@@ -1220,6 +1291,7 @@
                 dirObj, newFile.getName(), true));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(fileObj.getPath().toString(), moved.getPath());
 
@@ -1233,10 +1305,10 @@
         File newDir = createNewDir(mainStorageDir);
         File movedDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> o.getName().equals(newDir.getName())).findFirst().get();
         MtpStorageManager.MtpObject movedObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> o.getName().equals(movedDir.getName())).findFirst().get();
         Assert.assertTrue(manager.beginMoveObject(movedObj, dirObj));
 
@@ -1248,6 +1320,7 @@
                 dirObj, movedDir.getName(), true));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(movedObj.getPath().toString(), renamed.getPath());
 
@@ -1257,6 +1330,7 @@
         createNewFile(renamed);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -1267,10 +1341,10 @@
         File newDir = createNewDir(mainStorageDir);
         File movedDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> o.getName().equals(newDir.getName())).findFirst().get();
         MtpStorageManager.MtpObject movedObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> o.getName().equals(movedDir.getName())).findFirst().get();
         manager.getObjects(movedObj.getId(), 0, mainMtpStorage.getStorageId());
         Assert.assertTrue(manager.beginMoveObject(movedObj, dirObj));
@@ -1283,13 +1357,14 @@
                 dirObj, movedDir.getName(), true));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(movedObj.getPath().toString(), renamed.getPath());
 
         Assert.assertTrue(manager.checkConsistency());
 
         // Expect events since the dir was visited
-        createNewFile(renamed);
+        createNewFileNonZero(renamed);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertTrue(manager.checkConsistency());
@@ -1299,13 +1374,13 @@
     @SmallTest
     public void testMoveObjectDelayed() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         File dir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> !o.isDir()).findFirst().get();
         Assert.assertTrue(manager.beginMoveObject(fileObj, dirObj));
 
@@ -1331,10 +1406,10 @@
         File newDir = createNewDir(mainStorageDir);
         File movedDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> o.getName().equals(newDir.getName())).findFirst().get();
         MtpStorageManager.MtpObject movedObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> o.getName().equals(movedDir.getName())).findFirst().get();
         manager.getObjects(movedObj.getId(), 0, mainMtpStorage.getStorageId());
         Assert.assertTrue(manager.beginMoveObject(movedObj, dirObj));
@@ -1348,13 +1423,14 @@
         manager.flushEvents();
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(movedObj.getPath().toString(), renamed.getPath());
 
         Assert.assertTrue(manager.checkConsistency());
 
         // Expect events since the dir was visited
-        createNewFile(renamed);
+        createNewFileNonZero(renamed);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertTrue(manager.checkConsistency());
@@ -1364,13 +1440,13 @@
     @SmallTest
     public void testMoveObjectFailed() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         File dir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> !o.isDir()).findFirst().get();
         Assert.assertTrue(manager.beginMoveObject(fileObj, dirObj));
 
@@ -1379,6 +1455,7 @@
                 dirObj, newFile.getName(), false));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
 
         Assert.assertTrue(manager.checkConsistency());
@@ -1388,13 +1465,13 @@
     @SmallTest
     public void testMoveObjectFailedOldRemoved() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         File dir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> !o.isDir()).findFirst().get();
         Assert.assertTrue(manager.beginMoveObject(fileObj, dirObj));
 
@@ -1405,6 +1482,7 @@
                 dirObj, newFile.getName(), false));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 1);
 
         Assert.assertTrue(manager.checkConsistency());
@@ -1414,17 +1492,17 @@
     @SmallTest
     public void testMoveObjectFailedNewAdded() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         File dir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject dirObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(MtpStorageManager.MtpObject::isDir).findFirst().get();
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId())
+                mainMtpStorage.getStorageId()).stream()
                 .filter(o -> !o.isDir()).findFirst().get();
         Assert.assertTrue(manager.beginMoveObject(fileObj, dirObj));
 
-        createNewFile(dir, newFile.getName());
+        createNewFileNonZero(dir, newFile.getName());
         manager.flushEvents();
         Assert.assertTrue(manager.endMoveObject(
                 manager.getStorageRoot(mainMtpStorage.getStorageId()),
@@ -1440,14 +1518,14 @@
     @SmallTest
     public void testMoveObjectXStorageSuccess() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginMoveObject(fileObj,
                 manager.getStorageRoot(secondaryMtpStorage.getStorageId())));
 
         Assert.assertTrue(newFile.delete());
-        File moved = createNewFile(secondaryStorageDir, newFile.getName());
+        File moved = createNewFileNonZero(secondaryStorageDir, newFile.getName());
         manager.flushEvents();
         Assert.assertTrue(manager.endMoveObject(
                 manager.getStorageRoot(mainMtpStorage.getStorageId()),
@@ -1468,7 +1546,7 @@
         logMethodName();
         File movedDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject movedObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginMoveObject(movedObj,
                 manager.getStorageRoot(secondaryMtpStorage.getStorageId())));
 
@@ -1481,6 +1559,7 @@
                 movedDir.getName(), true));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(manager.getObject(movedObj.getId()).getPath().toString(),
                 moved.getPath());
@@ -1491,6 +1570,7 @@
         createNewFile(moved);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertTrue(manager.checkConsistency());
     }
 
@@ -1500,7 +1580,7 @@
         logMethodName();
         File movedDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject movedObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         manager.getObjects(movedObj.getId(), 0, mainMtpStorage.getStorageId());
         Assert.assertTrue(manager.beginMoveObject(movedObj,
                 manager.getStorageRoot(secondaryMtpStorage.getStorageId())));
@@ -1514,6 +1594,7 @@
                 movedDir.getName(), true));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(manager.getObject(movedObj.getId()).getPath().toString(),
                 moved.getPath());
@@ -1521,7 +1602,7 @@
         Assert.assertTrue(manager.checkConsistency());
 
         // Expect events since the dir was visited
-        createNewFile(moved);
+        createNewFileNonZero(moved);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertTrue(manager.checkConsistency());
@@ -1531,9 +1612,9 @@
     @SmallTest
     public void testMoveObjectXStorageDelayed() {
         logMethodName();
-        File movedFile = createNewFile(mainStorageDir);
+        File movedFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject movedObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginMoveObject(movedObj,
                 manager.getStorageRoot(secondaryMtpStorage.getStorageId())));
 
@@ -1543,7 +1624,7 @@
                 movedFile.getName(), true));
 
         Assert.assertTrue(movedFile.delete());
-        File moved = createNewFile(secondaryStorageDir, movedFile.getName());
+        File moved = createNewFileNonZero(secondaryStorageDir, movedFile.getName());
         manager.flushEvents();
 
         Assert.assertEquals(objectsAdded.size(), 0);
@@ -1560,7 +1641,7 @@
         logMethodName();
         File movedDir = createNewDir(mainStorageDir);
         MtpStorageManager.MtpObject movedObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         manager.getObjects(movedObj.getId(), 0, mainMtpStorage.getStorageId());
         Assert.assertTrue(manager.beginMoveObject(movedObj,
                 manager.getStorageRoot(secondaryMtpStorage.getStorageId())));
@@ -1575,6 +1656,7 @@
         manager.flushEvents();
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
         Assert.assertEquals(manager.getObject(movedObj.getId()).getPath().toString(),
                 moved.getPath());
@@ -1582,7 +1664,7 @@
         Assert.assertTrue(manager.checkConsistency());
 
         // Expect events since the dir was visited
-        createNewFile(moved);
+        createNewFileNonZero(moved);
         manager.flushEvents();
         Assert.assertEquals(objectsAdded.size(), 1);
         Assert.assertTrue(manager.checkConsistency());
@@ -1592,9 +1674,9 @@
     @SmallTest
     public void testMoveObjectXStorageFailed() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginMoveObject(fileObj,
                 manager.getStorageRoot(secondaryMtpStorage.getStorageId())));
 
@@ -1604,6 +1686,7 @@
                 newFile.getName(), false));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 0);
 
         Assert.assertTrue(manager.checkConsistency());
@@ -1613,9 +1696,9 @@
     @SmallTest
     public void testMoveObjectXStorageFailedOldRemoved() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginMoveObject(fileObj,
                 manager.getStorageRoot(secondaryMtpStorage.getStorageId())));
 
@@ -1627,6 +1710,7 @@
                 newFile.getName(), false));
 
         Assert.assertEquals(objectsAdded.size(), 0);
+        Assert.assertEquals(objectsInfoChanged.size(), 0);
         Assert.assertEquals(objectsRemoved.size(), 1);
 
         Assert.assertTrue(manager.checkConsistency());
@@ -1636,13 +1720,13 @@
     @SmallTest
     public void testMoveObjectXStorageFailedNewAdded() {
         logMethodName();
-        File newFile = createNewFile(mainStorageDir);
+        File newFile = createNewFileNonZero(mainStorageDir);
         MtpStorageManager.MtpObject fileObj = manager.getObjects(0xFFFFFFFF, 0,
-                mainMtpStorage.getStorageId()).findFirst().get();
+                mainMtpStorage.getStorageId()).get(0);
         Assert.assertTrue(manager.beginMoveObject(fileObj,
                 manager.getStorageRoot(secondaryMtpStorage.getStorageId())));
 
-        createNewFile(secondaryStorageDir, newFile.getName());
+        createNewFileNonZero(secondaryStorageDir, newFile.getName());
         manager.flushEvents();
         Assert.assertTrue(manager.endMoveObject(
                 manager.getStorageRoot(mainMtpStorage.getStorageId()),
@@ -1654,4 +1738,4 @@
 
         Assert.assertTrue(manager.checkConsistency());
     }
-}
\ No newline at end of file
+}
diff --git a/native/android/OWNERS b/native/android/OWNERS
index 11d4be4..b3f50aa 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -1,11 +1,4 @@
 set noparent
 
-per-file libandroid_net.map.txt=ek@google.com
-per-file libandroid_net.map.txt=jchalard@google.com
-per-file libandroid_net.map.txt=lorenzo@google.com
-per-file libandroid_net.map.txt=satk@google.com
-
-per-file net.c=ek@google.com
-per-file net.c=jchalard@google.com
-per-file net.c=lorenzo@google.com
-per-file net.c=satk@google.com
+per-file libandroid_net.map.txt, net.c = codewiz@google.com, ek@google.com, jchalard@google.com
+per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
index 53ec6c8..728e6e1 100644
--- a/opengl/java/android/opengl/EGL14.java
+++ b/opengl/java/android/opengl/EGL14.java
@@ -18,6 +18,7 @@
 
 package android.opengl;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.SurfaceTexture;
 import android.view.Surface;
 import android.view.SurfaceView;
@@ -163,6 +164,7 @@
     /**
      * {@hide}
      */
+    @UnsupportedAppUsage
     public static native EGLDisplay eglGetDisplay(
         long display_id
     );
diff --git a/opengl/java/android/opengl/GLES20.java b/opengl/java/android/opengl/GLES20.java
index 137f2f5..d66e7ac 100644
--- a/opengl/java/android/opengl/GLES20.java
+++ b/opengl/java/android/opengl/GLES20.java
@@ -19,6 +19,8 @@
 
 package android.opengl;
 
+import android.annotation.UnsupportedAppUsage;
+
 /** OpenGL ES 2.0
  */
 public class GLES20 {
@@ -824,6 +826,7 @@
     // C function void glGetActiveAttrib ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
 
     /** @hide Method is broken, but used to be public (b/6006380) */
+    @UnsupportedAppUsage
     public static native void glGetActiveAttrib(
         int program,
         int index,
@@ -872,6 +875,7 @@
     // C function void glGetActiveUniform ( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name )
 
     /** @hide Method is broken, but used to be public (b/6006380) */
+    @UnsupportedAppUsage
     public static native void glGetActiveUniform(
         int program,
         int index,
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 0f0a7e9d..8a3e6a0 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -16,6 +16,7 @@
 
 package android.opengl;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Trace;
 import android.util.AttributeSet;
@@ -1235,6 +1236,7 @@
         EGLDisplay mEglDisplay;
         EGLSurface mEglSurface;
         EGLConfig mEglConfig;
+        @UnsupportedAppUsage
         EGLContext mEglContext;
 
     }
@@ -1844,6 +1846,7 @@
 
         // End of member variables protected by the sGLThreadManager monitor.
 
+        @UnsupportedAppUsage
         private EglHelper mEglHelper;
 
         /**
@@ -1919,7 +1922,9 @@
 
     private final WeakReference<GLSurfaceView> mThisWeakRef =
             new WeakReference<GLSurfaceView>(this);
+    @UnsupportedAppUsage
     private GLThread mGLThread;
+    @UnsupportedAppUsage
     private Renderer mRenderer;
     private boolean mDetached;
     private EGLConfigChooser mEGLConfigChooser;
diff --git a/opengl/java/javax/microedition/khronos/egl/EGL10.java b/opengl/java/javax/microedition/khronos/egl/EGL10.java
index 612d59c..8a25170 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGL10.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGL10.java
@@ -16,6 +16,7 @@
 
 package javax.microedition.khronos.egl;
 
+import android.annotation.UnsupportedAppUsage;
 import java.lang.String;
 
 public interface EGL10 extends EGL {
@@ -116,6 +117,7 @@
     String      eglQueryString(EGLDisplay display, int name);
     boolean     eglQuerySurface(EGLDisplay display, EGLSurface surface, int attribute, int[] value);
     /** @hide **/
+    @UnsupportedAppUsage
     boolean     eglReleaseThread();
     boolean     eglSwapBuffers(EGLDisplay display, EGLSurface surface);
     boolean     eglTerminate(EGLDisplay display);
diff --git a/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml
index baa4867..d7c56b8 100644
--- a/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml
@@ -28,7 +28,7 @@
     <string name="device_encryption_restore_text" msgid="1570864916855208992">"Insira sua senha de criptografia do dispositivo abaixo."</string>
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Insira sua senha de criptografia do dispositivo abaixo. Ela também será usada para criptografar o arquivo de backup."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Digite uma senha para usar para criptografar os dados de backup por completo. Se isso for deixado em branco, sua senha atual de backup será usada:"</string>
-    <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se você deseja criptografar os dados de backup por completo, digite uma senha abaixo:"</string>
+    <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se você quer criptografar os dados de backup por completo, digite uma senha abaixo:"</string>
     <string name="backup_enc_password_required" msgid="7889652203371654149">"Como seu dispositivo está criptografado, é necessário criptografar seu backup. Insira uma senha abaixo:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Se os dados restaurados forem criptografada, digite a senha abaixo:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Iniciando backup..."</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-pt/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt/strings.xml
index baa4867..d7c56b8 100644
--- a/packages/BackupRestoreConfirmation/res/values-pt/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-pt/strings.xml
@@ -28,7 +28,7 @@
     <string name="device_encryption_restore_text" msgid="1570864916855208992">"Insira sua senha de criptografia do dispositivo abaixo."</string>
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Insira sua senha de criptografia do dispositivo abaixo. Ela também será usada para criptografar o arquivo de backup."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Digite uma senha para usar para criptografar os dados de backup por completo. Se isso for deixado em branco, sua senha atual de backup será usada:"</string>
-    <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se você deseja criptografar os dados de backup por completo, digite uma senha abaixo:"</string>
+    <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se você quer criptografar os dados de backup por completo, digite uma senha abaixo:"</string>
     <string name="backup_enc_password_required" msgid="7889652203371654149">"Como seu dispositivo está criptografado, é necessário criptografar seu backup. Insira uma senha abaixo:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Se os dados restaurados forem criptografada, digite a senha abaixo:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Iniciando backup..."</string>
diff --git a/packages/CaptivePortalLogin/OWNERS b/packages/CaptivePortalLogin/OWNERS
index ce50558..7311eee 100644
--- a/packages/CaptivePortalLogin/OWNERS
+++ b/packages/CaptivePortalLogin/OWNERS
@@ -1,6 +1,8 @@
 set noparent
 
+codewiz@google.com
 ek@google.com
 jchalard@google.com
 lorenzo@google.com
+reminv@google.com
 satk@google.com
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
new file mode 100644
index 0000000..f908595
--- /dev/null
+++ b/packages/CarSystemUI/Android.bp
@@ -0,0 +1,80 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+android_app {
+    name: "CarSystemUI",
+
+    overrides: [
+        "SystemUI",
+    ],
+
+    srcs: [
+        "src/**/*.java",
+        "src/**/I*.aidl",
+    ],
+
+    static_libs: [
+        "SystemUI-core",
+        "SystemUIPluginLib",
+        "SystemUISharedLib",
+        "SettingsLib",
+        "androidx.car_car",
+        "androidx.legacy_legacy-support-v4",
+        "androidx.recyclerview_recyclerview",
+        "androidx.preference_preference",
+        "androidx.appcompat_appcompat",
+        "androidx.mediarouter_mediarouter",
+        "androidx.palette_palette",
+        "androidx.legacy_legacy-preference-v14",
+        "androidx.leanback_leanback",
+        "androidx.slice_slice-core",
+        "androidx.slice_slice-view",
+        "androidx.slice_slice-builders",
+        "androidx.arch.core_core-runtime",
+        "androidx.lifecycle_lifecycle-extensions",
+        "SystemUI-tags",
+        "SystemUI-proto",
+    ],
+
+    libs: [
+        "telephony-common",
+        "android.car",
+    ],
+
+    manifest: "AndroidManifest.xml",
+
+    owner: "google",
+    platform_apis: true,
+    certificate: "platform",
+    privileged: true,
+
+    optimize: {
+        proguard_flags_files: [
+            "proguard.flags",
+        ],
+    },
+    resource_dirs: [
+        "res",
+    ],
+
+
+    dxflags: ["--multi-dex"],
+
+    aaptflags: [
+        "--extra-packages",
+        "com.android.keyguard",
+    ],
+
+}
diff --git a/packages/CarSystemUI/AndroidManifest.xml b/packages/CarSystemUI/AndroidManifest.xml
new file mode 100644
index 0000000..4e8a3a3
--- /dev/null
+++ b/packages/CarSystemUI/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+        package="com.android.systemui"
+        android:sharedUserId="android.uid.systemui"
+        coreApp="true">
+
+
+</manifest>
diff --git a/packages/CarSystemUI/proguard.flags b/packages/CarSystemUI/proguard.flags
new file mode 100644
index 0000000..a81c7e0
--- /dev/null
+++ b/packages/CarSystemUI/proguard.flags
@@ -0,0 +1,3 @@
+-keep class com.android.systemui.CarSystemUIFactory
+
+-include ../SystemUI/proguard.flags
diff --git a/packages/CarSystemUI/res/drawable/car_ic_apps.xml b/packages/CarSystemUI/res/drawable/car_ic_apps.xml
new file mode 100644
index 0000000..13b543b
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_apps.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="33dp"
+    android:height="33dp"
+    android:viewportHeight="33.0"
+    android:viewportWidth="33.0">
+    <path
+        android:fillColor="@color/car_nav_icon_fill_color"
+        android:fillType="evenOdd"
+        android:pathData="M1,20L12,20C12.55,20 13,20.45 13,21L13,32C13,32.55 12.55,33 12,33L1,33C0.45,33 0,32.55 0,32L0,21C0,20.45 0.45,20 1,20ZM21,20L32,20C32.55,20 33,20.45 33,21L33,32C33,32.55 32.55,33 32,33L21,33C20.45,33 20,32.55 20,32L20,21C20,20.45 20.45,20 21,20ZM1,0L12,0C12.55,0 13,0.45 13,1L13,12C13,12.55 12.55,13 12,13L1,13C0.45,13 0,12.55 0,12L0,1C0,0.45 0.45,0 1,0ZM21,0L32,0C32.55,0 33,0.45 33,1L33,12C33,12.55 32.55,13 32,13L21,13C20.45,13 20,12.55 20,12L20,1C20,0.45 20.45,0 21,0Z"
+        android:strokeColor="@color/car_nav_icon_fill_color"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_apps_black.xml b/packages/CarSystemUI/res/drawable/car_ic_apps_black.xml
new file mode 100644
index 0000000..498d366
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_apps_black.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="33dp"
+    android:height="33dp"
+    android:viewportHeight="33.0"
+    android:viewportWidth="33.0">
+    <path
+        android:fillColor="#FF000000"
+        android:fillType="evenOdd"
+        android:pathData="M1,20L12,20C12.55,20 13,20.45 13,21L13,32C13,32.55 12.55,33 12,33L1,33C0.45,33 0,32.55 0,32L0,21C0,20.45 0.45,20 1,20ZM21,20L32,20C32.55,20 33,20.45 33,21L33,32C33,32.55 32.55,33 32,33L21,33C20.45,33 20,32.55 20,32L20,21C20,20.45 20.45,20 21,20ZM1,0L12,0C12.55,0 13,0.45 13,1L13,12C13,12.55 12.55,13 12,13L1,13C0.45,13 0,12.55 0,12L0,1C0,0.45 0.45,0 1,0ZM21,0L32,0C32.55,0 33,0.45 33,1L33,12C33,12.55 32.55,13 32,13L21,13C20.45,13 20,12.55 20,12L20,1C20,0.45 20.45,0 21,0Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_apps_selected.xml b/packages/CarSystemUI/res/drawable/car_ic_apps_selected.xml
new file mode 100644
index 0000000..250bfe8
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_apps_selected.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/car_ic_selection_bg" android:gravity="center"/>
+    <item android:drawable="@drawable/car_ic_apps_black" android:gravity="center"/>
+</layer-list>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_music.xml b/packages/CarSystemUI/res/drawable/car_ic_music.xml
new file mode 100644
index 0000000..8c15494
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_music.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="34dp"
+    android:height="39dp"
+    android:viewportHeight="39.0"
+    android:viewportWidth="34.0">
+    <path
+        android:fillColor="@color/car_nav_icon_fill_color"
+        android:fillType="evenOdd"
+        android:pathData="M23,25L31,23L31,9L12,12L12,38C12,38.45 11.45,39 11,39L1,39C0.55,39 0.01,38.87 0,38.3C0,38.3 0,35.87 0,31C0,30.42 0.62,30.08 1,30L9,28L9,4.85C9,4.36 9.36,3.94 9.84,3.87L32.84,0.19C33.39,0.1 33.9,0.47 33.99,1.01C34,1.07 34,1.12 34,1.17L34,33.06C34,33.51 33.45,34 33,34L23,34C22.55,34 22,33.51 22,33.06L22,26C22,25.61 22.16,25.18 23,25Z"
+        android:strokeColor="@color/car_nav_icon_fill_color"
+        android:strokeWidth="1"/>
+    <path
+        android:fillColor="@color/car_nav_icon_fill_color"
+        android:fillType="evenOdd"
+        android:pathData="M23.57,26.48L23.57,32.42L32.42,32.42L32.42,24.27L23.57,26.48ZM32.42,7.18L32.42,1.85L10.57,5.34L10.57,10.63L32.42,7.18ZM10.42,29.27L9.38,29.53L1.58,31.48C1.58,34.35 1.58,34.45 1.57,36.48C1.58,36.89 1.58,37.2 1.58,37.43L10.42,37.43L10.42,29.27Z"
+        android:strokeColor="@color/car_nav_icon_fill_color"
+        android:strokeWidth="3.15"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_music_black.xml b/packages/CarSystemUI/res/drawable/car_ic_music_black.xml
new file mode 100644
index 0000000..64287a5
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_music_black.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="34dp"
+    android:height="39dp"
+    android:viewportHeight="39.0"
+    android:viewportWidth="34.0">
+    <path
+        android:fillColor="#FF000000"
+        android:fillType="evenOdd"
+        android:pathData="M23,25L31,23L31,9L12,12L12,38C12,38.45 11.45,39 11,39L1,39C0.55,39 0.01,38.87 0,38.3C0,38.3 0,35.87 0,31C0,30.42 0.62,30.08 1,30L9,28L9,4.85C9,4.36 9.36,3.94 9.84,3.87L32.84,0.19C33.39,0.1 33.9,0.47 33.99,1.01C34,1.07 34,1.12 34,1.17L34,33.06C34,33.51 33.45,34 33,34L23,34C22.55,34 22,33.51 22,33.06L22,26C22,25.61 22.16,25.18 23,25Z"
+        android:strokeColor="#FF000000"
+        android:strokeWidth="1"/>
+    <path
+        android:fillColor="#FF000000"
+        android:fillType="evenOdd"
+        android:pathData="M23.57,26.48L23.57,32.42L32.42,32.42L32.42,24.27L23.57,26.48ZM32.42,7.18L32.42,1.85L10.57,5.34L10.57,10.63L32.42,7.18ZM10.42,29.27L9.38,29.53L1.58,31.48C1.58,34.35 1.58,34.45 1.57,36.48C1.58,36.89 1.58,37.2 1.58,37.43L10.42,37.43L10.42,29.27Z"
+        android:strokeColor="#FF000000"
+        android:strokeWidth="3.15"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_music_selected.xml b/packages/CarSystemUI/res/drawable/car_ic_music_selected.xml
new file mode 100644
index 0000000..9703a8c
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_music_selected.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/car_ic_selection_bg" android:gravity="center"/>
+    <item android:drawable="@drawable/car_ic_music_black" android:gravity="center"/>
+</layer-list>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_navigation.xml b/packages/CarSystemUI/res/drawable/car_ic_navigation.xml
new file mode 100644
index 0000000..58667be
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_navigation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="37dp"
+    android:viewportHeight="37.0"
+    android:viewportWidth="32.0">
+    <path
+        android:fillColor="@color/car_nav_icon_fill_color"
+        android:fillType="evenOdd"
+        android:pathData="M16.62,0.61L31.33,35.21C31.55,35.72 31.31,36.3 30.8,36.52C30.48,36.66 30.12,36.62 29.83,36.42L15.7,26.44L1.58,36.42C1.13,36.73 0.5,36.63 0.18,36.18C-0.02,35.89 -0.06,35.53 0.08,35.21L14.78,0.61C15,0.1 15.59,-0.14 16.1,0.08C16.33,0.18 16.52,0.37 16.62,0.61Z"
+        android:strokeColor="@color/car_nav_icon_fill_color"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_navigation_black.xml b/packages/CarSystemUI/res/drawable/car_ic_navigation_black.xml
new file mode 100644
index 0000000..145d4c9
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_navigation_black.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="37dp"
+    android:viewportHeight="37.0"
+    android:viewportWidth="32.0">
+    <path
+        android:fillColor="#FF000000"
+        android:fillType="evenOdd"
+        android:pathData="M16.62,0.61L31.33,35.21C31.55,35.72 31.31,36.3 30.8,36.52C30.48,36.66 30.12,36.62 29.83,36.42L15.7,26.44L1.58,36.42C1.13,36.73 0.5,36.63 0.18,36.18C-0.02,35.89 -0.06,35.53 0.08,35.21L14.78,0.61C15,0.1 15.59,-0.14 16.1,0.08C16.33,0.18 16.52,0.37 16.62,0.61Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_navigation_selected.xml b/packages/CarSystemUI/res/drawable/car_ic_navigation_selected.xml
new file mode 100644
index 0000000..f0174db
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_navigation_selected.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/car_ic_selection_bg" android:gravity="center"/>
+    <item android:drawable="@drawable/car_ic_navigation_black" android:gravity="center"/>
+</layer-list>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/drawable/car_ic_notification.xml b/packages/CarSystemUI/res/drawable/car_ic_notification.xml
new file mode 100644
index 0000000..f96b050
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_notification.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="38dp"
+    android:viewportHeight="38.0"
+    android:viewportWidth="32.0">
+    <path
+        android:fillColor="@color/car_nav_icon_fill_color"
+        android:fillType="evenOdd"
+        android:pathData="M20.62,3.98C25.51,5.85 28.98,10.61 28.98,16.18L28.98,24.95L32,24.95L32,31.22L0,31.22L0,24.95L3.02,24.95L3.02,16.18C3.02,10.61 6.49,5.85 11.38,3.98C11.72,1.73 13.66,0 16,0C18.34,0 20.28,1.73 20.62,3.98ZM11.33,33.3L20.67,33.3C20.67,35.9 18.58,38 16,38C13.42,38 11.33,35.9 11.33,33.3Z"
+        android:strokeColor="@color/car_nav_icon_fill_color"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_notification_black.xml b/packages/CarSystemUI/res/drawable/car_ic_notification_black.xml
new file mode 100644
index 0000000..5f8df88
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_notification_black.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="38dp"
+    android:viewportHeight="38.0"
+    android:viewportWidth="32.0">
+    <path
+        android:fillColor="#000000"
+        android:fillType="evenOdd"
+        android:pathData="M20.62,3.98C25.51,5.85 28.98,10.61 28.98,16.18L28.98,24.95L32,24.95L32,31.22L0,31.22L0,24.95L3.02,24.95L3.02,16.18C3.02,10.61 6.49,5.85 11.38,3.98C11.72,1.73 13.66,0 16,0C18.34,0 20.28,1.73 20.62,3.98ZM11.33,33.3L20.67,33.3C20.67,35.9 18.58,38 16,38C13.42,38 11.33,35.9 11.33,33.3Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_notification_selected.xml b/packages/CarSystemUI/res/drawable/car_ic_notification_selected.xml
new file mode 100644
index 0000000..02eec93
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_notification_selected.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/car_ic_selection_bg" android:gravity="center"/>
+    <item android:drawable="@drawable/car_ic_notification_black" android:gravity="center"/>
+</layer-list>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/drawable/car_ic_overview.xml b/packages/CarSystemUI/res/drawable/car_ic_overview.xml
new file mode 100644
index 0000000..590109a
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_overview.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="39dp"
+    android:height="40dp"
+    android:viewportHeight="40.0"
+    android:viewportWidth="39.0">
+    <path
+        android:fillColor="@color/car_nav_icon_fill_color"
+        android:fillType="evenOdd"
+        android:pathData="M33.4,22.74L33.4,37.74C33.4,38.84 32.51,39.74 31.4,39.74L24.4,39.74L24.4,24.74L14.4,24.74L14.4,39.74L7.4,39.74C6.3,39.74 5.4,38.84 5.4,37.74L5.4,22.74L0.5,22.74C0.22,22.74 0,22.51 0,22.24C0,22.12 0.04,22 0.12,21.91L19.03,0.17C19.21,-0.04 19.52,-0.06 19.73,0.12C19.75,0.14 19.76,0.15 19.78,0.17L38.68,21.91C38.86,22.12 38.84,22.43 38.63,22.62C38.54,22.69 38.43,22.74 38.31,22.74L33.4,22.74Z"
+        android:strokeColor="@color/car_nav_icon_fill_color"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_overview_black.xml b/packages/CarSystemUI/res/drawable/car_ic_overview_black.xml
new file mode 100644
index 0000000..48cff97
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_overview_black.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="39dp"
+    android:height="40dp"
+    android:viewportHeight="40.0"
+    android:viewportWidth="39.0">
+    <path
+        android:fillColor="#FF000000"
+        android:fillType="evenOdd"
+        android:pathData="M33.4,22.74L33.4,37.74C33.4,38.84 32.51,39.74 31.4,39.74L24.4,39.74L24.4,24.74L14.4,24.74L14.4,39.74L7.4,39.74C6.3,39.74 5.4,38.84 5.4,37.74L5.4,22.74L0.5,22.74C0.22,22.74 0,22.51 0,22.24C0,22.12 0.04,22 0.12,21.91L19.03,0.17C19.21,-0.04 19.52,-0.06 19.73,0.12C19.75,0.14 19.76,0.15 19.78,0.17L38.68,21.91C38.86,22.12 38.84,22.43 38.63,22.62C38.54,22.69 38.43,22.74 38.31,22.74L33.4,22.74Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_overview_selected.xml b/packages/CarSystemUI/res/drawable/car_ic_overview_selected.xml
new file mode 100644
index 0000000..18ebf0c
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_overview_selected.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/car_ic_selection_bg" android:gravity="center"/>
+    <item android:drawable="@drawable/car_ic_overview_black" android:gravity="center"/>
+</layer-list>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_phone.xml b/packages/CarSystemUI/res/drawable/car_ic_phone.xml
new file mode 100644
index 0000000..7091670
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_phone.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="40dp"
+    android:height="40dp"
+    android:viewportHeight="40.0"
+    android:viewportWidth="40.0">
+    <path
+        android:fillColor="@color/car_nav_icon_fill_color"
+        android:fillType="nonZero"
+        android:pathData="M21.31,35.75L21.3,35.76L3.46,17.92L0.03,6.25C-0.16,5.32 0.53,3.88 1.41,3.51C6.36,1.25 8.88,0.1 8.95,0.08C10.02,-0.23 11.39,0.39 11.7,1.45L13.76,10.37C13.97,11.1 13.62,11.91 13.07,12.43L8.24,17.25L22.31,31.32L27.13,26.49C27.65,25.94 28.47,25.6 29.19,25.81L38.11,27.87C39.18,28.17 39.79,29.55 39.49,30.61C39.46,30.69 38.32,33.2 36.05,38.16C35.68,39.04 34.25,39.73 33.31,39.53L21.65,36.1C21.51,35.96 21.4,35.84 21.31,35.75Z"
+        android:strokeColor="@color/car_nav_icon_fill_color"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_phone_black.xml b/packages/CarSystemUI/res/drawable/car_ic_phone_black.xml
new file mode 100644
index 0000000..087eebb
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_phone_black.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="40dp"
+    android:height="40dp"
+    android:viewportHeight="40.0"
+    android:viewportWidth="40.0">
+    <path
+        android:fillColor="#FF000000"
+        android:fillType="nonZero"
+        android:pathData="M21.31,35.75L21.3,35.76L3.46,17.92L0.03,6.25C-0.16,5.32 0.53,3.88 1.41,3.51C6.36,1.25 8.88,0.1 8.95,0.08C10.02,-0.23 11.39,0.39 11.7,1.45L13.76,10.37C13.97,11.1 13.62,11.91 13.07,12.43L8.24,17.25L22.31,31.32L27.13,26.49C27.65,25.94 28.47,25.6 29.19,25.81L38.11,27.87C39.18,28.17 39.79,29.55 39.49,30.61C39.46,30.69 38.32,33.2 36.05,38.16C35.68,39.04 34.25,39.73 33.31,39.53L21.65,36.1C21.51,35.96 21.4,35.84 21.31,35.75Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_phone_selected.xml b/packages/CarSystemUI/res/drawable/car_ic_phone_selected.xml
new file mode 100644
index 0000000..197eac0
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_phone_selected.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/car_ic_selection_bg" android:gravity="center"/>
+    <item android:drawable="@drawable/car_ic_phone_black" android:gravity="center"/>
+</layer-list>
diff --git a/packages/CarSystemUI/res/drawable/car_ic_selection_bg.xml b/packages/CarSystemUI/res/drawable/car_ic_selection_bg.xml
new file mode 100644
index 0000000..781beaf
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_ic_selection_bg.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="70dp"
+    android:height="70dp"
+    android:viewportHeight="70.0"
+    android:viewportWidth="70.0">
+    <path
+        android:fillColor="@color/car_accent"
+        android:fillType="evenOdd"
+        android:pathData="M4,0L66,0A4,4 0,0 1,70 4L70,66A4,4 0,0 1,66 70L4,70A4,4 0,0 1,0 66L0,4A4,4 0,0 1,4 0z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/car_seekbar_thumb.xml b/packages/CarSystemUI/res/drawable/car_seekbar_thumb.xml
new file mode 100644
index 0000000..1a9b8a5
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/car_seekbar_thumb.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape android:shape="oval">
+            <padding
+                android:bottom="@dimen/car_padding_1"
+                android:left="@dimen/car_padding_1"
+                android:right="@dimen/car_padding_1"
+                android:top="@dimen/car_padding_1"/>
+            <solid android:color="@android:color/black"/>
+        </shape>
+    </item>
+    <item>
+        <shape android:shape="oval">
+            <solid android:color="@color/car_accent"/>
+            <size
+                android:width="@dimen/car_seekbar_thumb_size"
+                android:height="@dimen/car_seekbar_thumb_size"/>
+        </shape>
+    </item>
+</layer-list>
diff --git a/packages/CarSystemUI/res/drawable/ic_mic_white.xml b/packages/CarSystemUI/res/drawable/ic_mic_white.xml
new file mode 100644
index 0000000..f5a91b5
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/ic_mic_white.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+        android:pathData="M24,28c3.31,0 5.98,-2.69 5.98,-6L30,10c0,-3.32 -2.68,-6 -6,-6 -3.31,0 -6,2.68 -6,6v12c0,3.31 2.69,6 6,6zM34.6,22c0,6 -5.07,10.2 -10.6,10.2 -5.52,0 -10.6,-4.2 -10.6,-10.2L10,22c0,6.83 5.44,12.47 12,13.44L22,42h4v-6.56c6.56,-0.97 12,-6.61 12,-13.44h-3.4z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/packages/CarSystemUI/res/drawable/nav_button_background.xml b/packages/CarSystemUI/res/drawable/nav_button_background.xml
new file mode 100644
index 0000000..376347c
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/nav_button_background.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/nav_bar_ripple_background_color">
+    <item android:id="@android:id/mask">
+        <shape android:shape="rectangle">
+            <solid android:color="?android:colorAccent"/>
+            <corners android:radius="6dp"/>
+        </shape>
+    </item>
+</ripple>
diff --git a/packages/CarSystemUI/res/drawable/notification_material_bg.xml b/packages/CarSystemUI/res/drawable/notification_material_bg.xml
new file mode 100644
index 0000000..03746c8
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/notification_material_bg.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/notification_ripple_untinted_color">
+    <item>
+        <shape xmlns:android="http://schemas.android.com/apk/res/android">
+            <solid android:color="@color/notification_material_background_color"/>
+            <corners
+                android:radius="@dimen/notification_shadow_radius"/>
+        </shape>
+    </item>
+</ripple>
diff --git a/packages/CarSystemUI/res/drawable/notification_material_bg_dim.xml b/packages/CarSystemUI/res/drawable/notification_material_bg_dim.xml
new file mode 100644
index 0000000..03746c8
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/notification_material_bg_dim.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/notification_ripple_untinted_color">
+    <item>
+        <shape xmlns:android="http://schemas.android.com/apk/res/android">
+            <solid android:color="@color/notification_material_background_color"/>
+            <corners
+                android:radius="@dimen/notification_shadow_radius"/>
+        </shape>
+    </item>
+</ripple>
diff --git a/packages/CarSystemUI/res/drawable/volume_dialog_background.xml b/packages/CarSystemUI/res/drawable/volume_dialog_background.xml
new file mode 100644
index 0000000..fa3ca8f
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/volume_dialog_background.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="?android:attr/colorBackgroundFloating"/>
+    <padding
+        android:bottom="5dp"
+        android:left="5dp"
+        android:right="5dp"
+        android:top="5dp"/>
+    <corners android:bottomLeftRadius="20dp"
+        android:bottomRightRadius="20dp"/>
+</shape>
diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
new file mode 100644
index 0000000..b67ce15
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/black"
+    android:orientation="vertical">
+    <LinearLayout
+        android:id="@id/nav_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingStart="20dp"
+        android:paddingEnd="20dp"
+        android:gravity="center">
+
+        <com.android.systemui.statusbar.car.CarFacetButton
+            android:id="@+id/home"
+            style="@style/NavigationBarButton"
+            systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+            systemui:icon="@drawable/car_ic_overview"
+            systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+            systemui:longIntent="intent:#Intent;action=com.google.android.demandspace.START;end"
+            systemui:selectedIcon="@drawable/car_ic_overview_selected"
+            systemui:useMoreIcon="false"
+        />
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"/>
+
+        <com.android.systemui.statusbar.car.CarFacetButton
+            android:id="@+id/maps_nav"
+            style="@style/NavigationBarButton"
+            systemui:categories="android.intent.category.APP_MAPS"
+            systemui:icon="@drawable/car_ic_navigation"
+            systemui:intent="intent:#Intent;component=com.android.car.carlauncher/.CarLauncher;category=android.intent.category.APP_MAPS;launchFlags=0x24000000;end"
+            systemui:selectedIcon="@drawable/car_ic_navigation_selected"
+            systemui:useMoreIcon="false"
+        />
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"/>
+
+        <com.android.systemui.statusbar.car.CarFacetButton
+            android:id="@+id/music_nav"
+            style="@style/NavigationBarButton"
+            systemui:icon="@drawable/car_ic_music"
+            systemui:intent="intent:#Intent;component=com.android.car.media/.MediaActivity;launchFlags=0x14000000;end"
+            systemui:packages="com.android.car.media"
+            systemui:selectedIcon="@drawable/car_ic_music_selected"
+            systemui:useMoreIcon="false"
+        />
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"/>
+
+        <com.android.systemui.statusbar.car.CarFacetButton
+            android:id="@+id/phone_nav"
+            style="@style/NavigationBarButton"
+            systemui:componentNames="com.android.car.dialer/.TelecomActivity"
+            systemui:icon="@drawable/car_ic_phone"
+            systemui:intent="intent:#Intent;component=com.android.car.dialer/.TelecomActivity;launchFlags=0x14000000;end"
+            systemui:selectedIcon="@drawable/car_ic_phone_selected"
+            systemui:useMoreIcon="false"
+        />
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"/>
+
+        <com.android.systemui.statusbar.car.CarFacetButton
+            android:id="@+id/grid_nav"
+            style="@style/NavigationBarButton"
+            systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
+            systemui:icon="@drawable/car_ic_apps"
+            systemui:intent="intent:#Intent;component=com.android.car.carlauncher/.AppGridActivity;launchFlags=0x24000000;end"
+            systemui:selectedIcon="@drawable/car_ic_apps_selected"
+            systemui:useMoreIcon="false"
+        />
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"/>
+
+        <com.android.systemui.statusbar.car.CarFacetButton
+            android:id="@+id/note"
+            style="@style/NavigationBarButton"
+            systemui:icon="@drawable/car_ic_notification"
+            systemui:intent="intent:#Intent;component=com.android.car.notification/.CarNotificationCenterActivity;launchFlags=0x14000000;end"
+            systemui:packages="com.android.car.notification"
+            systemui:selectedIcon="@drawable/car_ic_notification_selected"
+            systemui:useMoreIcon="false"
+        />
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"/>
+
+        <com.android.systemui.statusbar.car.CarFacetButton
+            android:id="@+id/assist"
+            style="@style/NavigationBarButton"
+            systemui:icon="@drawable/ic_mic_white"
+            systemui:intent="intent:#Intent;action=com.google.android.demandspace.START;end"
+            systemui:useMoreIcon="false"
+        />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/lock_screen_nav_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingStart="@dimen/car_keyline_1"
+        android:paddingEnd="@dimen/car_keyline_1"
+        android:gravity="center"
+        android:visibility="gone">
+    </LinearLayout>
+
+</com.android.systemui.statusbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml
new file mode 100644
index 0000000..46e60db
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/black"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:id="@+id/nav_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingStart="@dimen/car_padding_5"
+        android:paddingEnd="@dimen/car_padding_5">
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/home"
+            android:layout_width="@dimen/car_touch_target_size"
+            android:layout_height="match_parent"
+            android:background="?android:attr/selectableItemBackground"
+            android:src="@drawable/car_ic_overview"
+            systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+        />
+    </LinearLayout>
+</com.android.systemui.statusbar.car.CarNavigationBarView>
+
diff --git a/packages/CarSystemUI/res/layout/car_status_bar_header.xml b/packages/CarSystemUI/res/layout/car_status_bar_header.xml
new file mode 100644
index 0000000..e446072
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/car_status_bar_header.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<!-- Extends LinearLayout -->
+<com.android.systemui.qs.car.CarStatusBarHeader
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/header"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/status_bar_height">
+
+    <include layout="@layout/car_top_navigation_bar"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+    />
+</com.android.systemui.qs.car.CarStatusBarHeader>
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
new file mode 100644
index 0000000..7b3333e
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/car_top_bar"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/black"
+    android:orientation="vertical">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1">
+
+        <FrameLayout
+            android:id="@+id/left_hvac_container"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_alignParentStart="true"
+        >
+
+            <com.android.systemui.statusbar.car.CarNavigationButton
+                android:id="@+id/hvacleft"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@null"
+                systemui:broadcast="true"
+                systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+            />
+
+            <com.android.systemui.statusbar.hvac.AnimatedTemperatureView
+                android:id="@+id/lefttext"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:paddingStart="@dimen/car_padding_4"
+                android:paddingEnd="16dp"
+                android:gravity="center_vertical|start"
+                android:minEms="4"
+                android:textAppearance="@style/TextAppearance.Car.Status"
+                systemui:hvacAreaId="49"
+                systemui:hvacMaxText="@string/hvac_max_text"
+                systemui:hvacMaxValue="@dimen/hvac_max_value"
+                systemui:hvacMinText="@string/hvac_min_text"
+                systemui:hvacMinValue="@dimen/hvac_min_value"
+                systemui:hvacPivotOffset="60dp"
+                systemui:hvacPropertyId="358614275"
+                systemui:hvacTempFormat="%.0f\u00B0"
+            />
+        </FrameLayout>
+
+        <FrameLayout
+            android:id="@+id/clock_container"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_centerInParent="true"
+        >
+            <com.android.systemui.statusbar.car.CarNavigationButton
+                android:id="@+id/qs"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@null"
+                systemui:intent="intent:#Intent;component=com.android.car.settings/.common.CarSettingActivity;launchFlags=0x14008000;end"
+            />
+            <com.android.systemui.statusbar.policy.Clock
+                android:id="@+id/clock"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:elevation="5dp"
+                android:singleLine="true"
+                android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+            />
+        </FrameLayout>
+
+        <LinearLayout
+            android:id="@+id/system_icon_area"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_centerHorizontal="true"
+            android:layout_centerVertical="true"
+            android:layout_toEndOf="@+id/clock_container"
+            android:paddingStart="@dimen/car_padding_1"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+        >
+
+            <include
+                layout="@layout/system_icons"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:paddingStart="4dp"
+                android:gravity="center_vertical"
+            />
+        </LinearLayout>
+
+        <FrameLayout
+            android:id="@+id/right_hvac_container"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_alignParentEnd="true"
+        >
+
+            <com.android.systemui.statusbar.car.CarNavigationButton
+                android:id="@+id/hvacright"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@null"
+                systemui:broadcast="true"
+                systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+            />
+
+            <com.android.systemui.statusbar.hvac.AnimatedTemperatureView
+                android:id="@+id/righttext"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:paddingStart="16dp"
+                android:paddingEnd="@dimen/car_padding_4"
+                android:gravity="center_vertical|end"
+                android:minEms="4"
+                android:textAppearance="@style/TextAppearance.Car.Status"
+                systemui:hvacAreaId="68"
+                systemui:hvacMaxText="@string/hvac_max_text"
+                systemui:hvacMaxValue="@dimen/hvac_max_value"
+                systemui:hvacMinText="@string/hvac_min_text"
+                systemui:hvacMinValue="@dimen/hvac_min_value"
+                systemui:hvacPivotOffset="60dp"
+                systemui:hvacPropertyId="358614275"
+                systemui:hvacTempFormat="%.0f\u00B0"
+            />
+        </FrameLayout>
+    </RelativeLayout>
+
+</com.android.systemui.statusbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/layout/car_volume_dialog.xml b/packages/CarSystemUI/res/layout/car_volume_dialog.xml
new file mode 100644
index 0000000..c98740e
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/car_volume_dialog.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<androidx.car.widget.PagedListView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/volume_list"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@android:color/black"
+    android:minWidth="@dimen/volume_dialog_panel_width"
+    android:theme="@style/Theme.Car.DialogListView"
+    app:dividerEndMargin="@dimen/car_keyline_1"
+    app:dividerStartMargin="@dimen/car_keyline_1"
+    app:gutter="none"
+    app:scrollBarEnabled="false"
+    app:showPagedListViewDivider="true"/>
diff --git a/packages/CarSystemUI/res/layout/status_bar_wifi_group.xml b/packages/CarSystemUI/res/layout/status_bar_wifi_group.xml
new file mode 100644
index 0000000..2793e56
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/status_bar_wifi_group.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<com.android.systemui.statusbar.StatusBarWifiView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/wifi_combo"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:gravity="center_vertical">
+
+    <com.android.keyguard.AlphaOptimizedLinearLayout
+        android:id="@+id/wifi_group"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:paddingStart="2dp"
+        android:gravity="center_vertical"
+    >
+        <FrameLayout
+            android:id="@+id/inout_container"
+            android:layout_width="wrap_content"
+            android:layout_height="17dp"
+            android:gravity="center_vertical">
+            <ImageView
+                android:id="@+id/wifi_in"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingEnd="2dp"
+                android:src="@drawable/ic_activity_down"
+                android:visibility="gone"
+            />
+            <ImageView
+                android:id="@+id/wifi_out"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingEnd="2dp"
+                android:src="@drawable/ic_activity_up"
+                android:visibility="gone"
+            />
+        </FrameLayout>
+        <FrameLayout
+            android:id="@+id/wifi_combo"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical">
+            <com.android.systemui.statusbar.AlphaOptimizedImageView
+                android:id="@+id/wifi_signal"
+                android:layout_width="@dimen/status_bar_icon_size"
+                android:layout_height="@dimen/status_bar_icon_size"
+                android:theme="?attr/lightIconTheme"/>
+        </FrameLayout>
+
+        <View
+            android:id="@+id/wifi_signal_spacer"
+            android:layout_width="@dimen/status_bar_wifi_signal_spacer_width"
+            android:layout_height="4dp"
+            android:visibility="gone"/>
+
+        <ViewStub
+            android:id="@+id/connected_device_signals_stub"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout="@layout/connected_device_signal"/>
+
+        <View
+            android:id="@+id/wifi_airplane_spacer"
+            android:layout_width="@dimen/status_bar_airplane_spacer_width"
+            android:layout_height="4dp"
+            android:visibility="gone"
+        />
+    </com.android.keyguard.AlphaOptimizedLinearLayout>
+</com.android.systemui.statusbar.StatusBarWifiView>
diff --git a/packages/CarSystemUI/res/layout/super_status_bar.xml b/packages/CarSystemUI/res/layout/super_status_bar.xml
new file mode 100644
index 0000000..0594dce
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/super_status_bar.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<!-- This is the combined status bar / notification panel window. -->
+<com.android.systemui.statusbar.phone.StatusBarWindowView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:sysui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fitsSystemWindows="true">
+
+    <com.android.systemui.statusbar.BackDropView
+        android:id="@+id/backdrop"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone"
+        sysui:ignoreRightInset="true"
+    >
+        <ImageView android:id="@+id/backdrop_back"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:scaleType="centerCrop"/>
+        <ImageView android:id="@+id/backdrop_front"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:scaleType="centerCrop"
+            android:visibility="invisible"/>
+    </com.android.systemui.statusbar.BackDropView>
+
+    <com.android.systemui.statusbar.ScrimView
+        android:id="@+id/scrim_behind"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:importantForAccessibility="no"
+        sysui:ignoreRightInset="true"
+    />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/status_bar_height"
+        android:orientation="vertical"
+    >
+        <FrameLayout
+            android:id="@+id/status_bar_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+        />
+
+        <include layout="@layout/car_top_navigation_bar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+        />
+    </LinearLayout>
+
+    <include layout="@layout/brightness_mirror"/>
+
+    <ViewStub android:id="@+id/fullscreen_user_switcher_stub"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout="@layout/car_fullscreen_user_switcher"/>
+
+    <include layout="@layout/status_bar_expanded"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="invisible"/>
+
+    <com.android.systemui.statusbar.ScrimView
+        android:id="@+id/scrim_in_front"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:importantForAccessibility="no"
+        sysui:ignoreRightInset="true"
+    />
+
+</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/CarSystemUI/res/layout/system_icons.xml b/packages/CarSystemUI/res/layout/system_icons.xml
new file mode 100644
index 0000000..a7dd65e
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/system_icons.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/system_icons"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center_vertical">
+
+    <com.android.systemui.statusbar.phone.StatusIconContainer
+        android:id="@+id/statusIcons"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:paddingEnd="4dp"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"
+    />
+
+    <com.android.systemui.BatteryMeterView
+        android:id="@+id/battery"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+    />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/values-night/colors.xml b/packages/CarSystemUI/res/values-night/colors.xml
new file mode 100644
index 0000000..dad94a8
--- /dev/null
+++ b/packages/CarSystemUI/res/values-night/colors.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <color name="car_accent">#356FE5</color>
+    <color name="status_bar_background_color">#ff000000</color>
+    <color name="system_bar_background_opaque">#ff0c1013</color>
+
+    <!-- The color of the ripples on the untinted notifications -->
+    <color name="notification_ripple_untinted_color">@color/ripple_material_dark</color>
+</resources>
diff --git a/packages/CarSystemUI/res/values/attrs.xml b/packages/CarSystemUI/res/values/attrs.xml
new file mode 100644
index 0000000..6178738
--- /dev/null
+++ b/packages/CarSystemUI/res/values/attrs.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+
+    <!-- Custom attributes to configure hvac values -->
+    <declare-styleable name="AnimatedTemperatureView">
+        <attr name="hvacAreaId" format="integer"/>
+        <attr name="hvacPropertyId" format="integer"/>
+        <attr name="hvacTempFormat" format="string"/>
+        <!-- how far away the animations should center around -->
+        <attr name="hvacPivotOffset" format="dimension"/>
+        <attr name="hvacMinValue" format="float"/>
+        <attr name="hvacMaxValue" format="float"/>
+        <attr name="hvacMinText" format="string|reference"/>
+        <attr name="hvacMaxText" format="string|reference"/>
+        <attr name="android:gravity"/>
+        <attr name="android:minEms"/>
+        <attr name="android:textAppearance"/>
+    </declare-styleable>
+</resources>
diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml
new file mode 100644
index 0000000..df8f8db
--- /dev/null
+++ b/packages/CarSystemUI/res/values/colors.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <color name="nav_bar_ripple_background_color">#40ffffff</color>
+    <color name="car_accent">#356FE5</color>
+    <!-- colors for user switcher -->
+    <color name="car_user_switcher_background_color">#000000</color>
+    <color name="car_user_switcher_name_text_color">@color/car_body1_light</color>
+    <color name="car_user_switcher_add_user_background_color">#131313</color>
+    <color name="car_nav_icon_fill_color">@color/car_grey_50</color>
+    <!-- colors for seekbar -->
+    <color name="car_seekbar_track_background">#131315</color>
+    <color name="car_seekbar_track_secondary_progress">@color/car_accent</color>
+    <!-- colors for volume dialog tint -->
+    <color name="car_volume_dialog_tint">@color/car_tint_light</color>
+
+    <!-- System ui can't depend on car libs so redefine. -->
+    <color name="car_grey_50">#fffafafa</color>
+
+    <color name="docked_divider_background">@color/car_grey_50</color>
+    <color name="system_bar_background_opaque">#ff172026</color>
+
+    <color name="status_bar_background_color">#33000000</color>
+    <drawable name="system_bar_background">@color/status_bar_background_color</drawable>
+
+    <!-- The scrim color for the background of the notifications shade. -->
+    <color name="scrim_behind_color">#172026</color>
+
+    <!-- The color of the dividing line between grouped notifications. -->
+    <color name="notification_divider_color">@*android:color/notification_action_list</color>
+
+    <!-- The color of the ripples on the untinted notifications -->
+    <color name="notification_ripple_untinted_color">@color/ripple_material_light</color>
+
+    <color name="car_teal_700">#ff00796b</color>
+    <color name="car_grey_300">#ffe0e0e0</color>
+    <color name="car_grey_900">#ff212121</color>
+
+    <color name="keyguard_button_text_color">@android:color/black</color>
+</resources>
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
new file mode 100644
index 0000000..452d61d
--- /dev/null
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<resources>
+    <string name="config_statusBarComponent" translatable="false">
+        com.android.systemui.statusbar.car.CarStatusBar
+    </string>
+    <string name="config_systemUIFactoryComponent" translatable="false">
+        com.android.systemui.CarSystemUIFactory
+    </string>
+    <bool name="config_enableFullscreenUserSwitcher">true</bool>
+
+    <!-- configure which system ui bars should be displayed -->
+    <bool name="config_enableLeftNavigationBar">false</bool>
+    <bool name="config_enableRightNavigationBar">false</bool>
+    <bool name="config_enableBottomNavigationBar">true</bool>
+
+</resources>
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
new file mode 100644
index 0000000..07ecca2
--- /dev/null
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<resources>
+    <!--
+       Note: status bar height and navigation bar heights are defined
+       in frameworks/base/core package and thus will have no effect if
+       set here. See car_product overlay for car specific defaults-->
+
+    <dimen name="status_bar_icon_drawing_size_dark">36dp</dimen>
+    <dimen name="status_bar_icon_drawing_size">36dp</dimen>
+    <dimen name="car_qs_header_system_icons_area_height">96dp</dimen>
+    <!-- The amount by which to scale up the status bar icons. -->
+    <item name="status_bar_icon_scale_factor" format="float" type="dimen">1.75</item>
+
+    <dimen name="car_primary_icon_size">36dp</dimen>
+
+    <!-- dimensions for the car user switcher -->
+    <dimen name="car_user_switcher_name_text_size">@dimen/car_body1_size</dimen>
+    <dimen name="car_user_switcher_vertical_spacing_between_users">124dp</dimen>
+
+    <!--These values represent MIN and MAX for hvac-->
+    <item name="hvac_min_value" format="float" type="dimen">0</item>
+    <item name="hvac_max_value" format="float" type="dimen">126</item>
+
+    <!-- Largest size an avatar might need to be drawn in the user picker, status bar, or
+         quick settings header -->
+    <dimen name="max_avatar_size">128dp</dimen>
+
+    <!-- Standard image button size for volume dialog buttons -->
+    <dimen name="volume_button_size">84dp</dimen>
+    <!-- The maximum width allowed for the volume dialog. For auto, we allow this to span a good
+         deal of the screen. This value accounts for the side margins. -->
+    <dimen name="volume_dialog_panel_width">1920dp</dimen>
+    <dimen name="volume_dialog_side_margin">@dimen/side_margin</dimen>
+
+    <dimen name="volume_dialog_elevation">6dp</dimen>
+
+    <dimen name="volume_dialog_row_margin_end">@dimen/car_keyline_3</dimen>
+
+    <dimen name="volume_dialog_row_padding_end">0dp</dimen>
+
+    <dimen name="line_item_height">128dp</dimen>
+    <dimen name="volume_icon_size">96dp</dimen>
+    <dimen name="side_margin">148dp</dimen>
+    <dimen name="car_keyline_1">24dp</dimen>
+    <dimen name="car_keyline_2">96dp</dimen>
+    <dimen name="car_keyline_3">128dp</dimen>
+</resources>
diff --git a/packages/CarSystemUI/res/values/integers.xml b/packages/CarSystemUI/res/values/integers.xml
new file mode 100644
index 0000000..8b87c74
--- /dev/null
+++ b/packages/CarSystemUI/res/values/integers.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2018, The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<resources>
+    <integer name="user_fullscreen_switcher_num_col">2</integer>
+</resources>
diff --git a/packages/CarSystemUI/res/values/strings.xml b/packages/CarSystemUI/res/values/strings.xml
new file mode 100644
index 0000000..0368e61
--- /dev/null
+++ b/packages/CarSystemUI/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (c) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+    <!-- String to represent lowest setting of an HVAC system [CHAR LIMIT=5]-->
+    <string name="hvac_min_text">Min</string>
+    <!-- String to represent largest setting of an HVAC system [CHAR LIMIT=5]-->
+    <string name="hvac_max_text">Max</string>
+</resources>
diff --git a/packages/CarSystemUI/res/values/styles.xml b/packages/CarSystemUI/res/values/styles.xml
new file mode 100644
index 0000000..7f4544a
--- /dev/null
+++ b/packages/CarSystemUI/res/values/styles.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!-- The style for the volume icons in the volume dialog. This style makes the icon scale to
+         fit its container since auto wants the icon to be larger. The padding is added to make it
+         so the icon does not press along the edges of the dialog. -->
+    <style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless">
+        <item name="android:background">@drawable/btn_borderless_rect</item>
+        <item name="android:scaleType">fitCenter</item>
+        <item name="android:padding">22dp</item>
+    </style>
+
+    <style name="TextAppearance.StatusBar.Clock"
+        parent="@*android:style/TextAppearance.StatusBar.Icon">
+        <item name="android:textSize">42sp</item>
+        <item name="android:fontFamily">sans-serif-regular</item>
+        <item name="android:textColor">@color/car_grey_50</item>
+    </style>
+
+    <style name="TextAppearance.Car.Status">
+        <item name="android:textSize">@dimen/car_body2_size</item>
+        <item name="android:textColor">@color/car_grey_50</item>
+    </style>
+
+    <style name="CarNavigationBarButtonTheme">
+        <item name="android:colorControlHighlight">@color/nav_bar_ripple_background_color</item>
+    </style>
+
+    <style name="Theme.Car.DialogListView" parent="@style/Theme.Car.NoActionBar">
+        <item name="android:colorControlActivated">@color/car_accent</item>
+        <item name="listItemBackgroundColor">@android:color/black</item>
+    </style>
+
+    <style name="NavigationBarButton">
+        <item name="android:layout_height">96dp</item>
+        <item name="android:layout_width">96dp</item>
+        <item name="android:background">@drawable/nav_button_background</item>
+    </style>
+
+</resources>
diff --git a/packages/CarSystemUI/res/xml/car_volume_items.xml b/packages/CarSystemUI/res/xml/car_volume_items.xml
new file mode 100644
index 0000000..8715946
--- /dev/null
+++ b/packages/CarSystemUI/res/xml/car_volume_items.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!--
+  Defines all possible items on car volume settings UI, keyed by usage.
+-->
+<carVolumeItems xmlns:car="http://schemas.android.com/apk/res-auto">
+  <item car:usage="unknown"
+        car:icon="@drawable/car_ic_music"/>
+  <item car:usage="media"
+        car:icon="@drawable/car_ic_music"/>
+  <item car:usage="voice_communication"
+        car:icon="@*android:drawable/ic_audio_ring_notif"/>
+  <item car:usage="voice_communication_signalling"
+        car:icon="@*android:drawable/ic_audio_ring_notif"/>
+  <item car:usage="alarm"
+        car:icon="@drawable/ic_volume_alarm"/>
+  <item car:usage="notification"
+        car:icon="@drawable/car_ic_notification"/>
+  <item car:usage="notification_ringtone"
+        car:icon="@drawable/car_ic_notification"/>
+  <item car:usage="notification_communication_request"
+        car:icon="@drawable/car_ic_notification"/>
+  <item car:usage="notification_communication_instant"
+        car:icon="@drawable/car_ic_notification"/>
+  <item car:usage="notification_communication_delayed"
+        car:icon="@drawable/car_ic_notification"/>
+  <item car:usage="notification_event"
+        car:icon="@drawable/car_ic_notification"/>
+  <item car:usage="assistance_accessibility"
+        car:icon="@drawable/car_ic_notification"/>
+  <item car:usage="assistance_navigation_guidance"
+        car:icon="@drawable/car_ic_navigation"/>
+  <item car:usage="assistance_sonification"
+        car:icon="@drawable/car_ic_notification"/>
+  <item car:usage="game"
+        car:icon="@drawable/car_ic_music"/>
+  <item car:usage="assistant"
+        car:icon="@drawable/car_ic_music"/>
+</carVolumeItems>
+
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
new file mode 100644
index 0000000..dfe5704
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import android.content.Context;
+import android.util.ArrayMap;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.Dependency.DependencyProvider;
+import com.android.systemui.car.CarNotificationEntryManager;
+import com.android.systemui.statusbar.car.CarFacetButtonController;
+import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.car.hvac.HvacController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+
+/**
+ * Class factory to provide car specific SystemUI components.
+ */
+public class CarSystemUIFactory extends SystemUIFactory {
+
+    public StatusBarKeyguardViewManager createStatusBarKeyguardViewManager(Context context,
+        ViewMediatorCallback viewMediatorCallback, LockPatternUtils lockPatternUtils) {
+        return new CarStatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils);
+    }
+
+    @Override
+    public void injectDependencies(ArrayMap<Object, DependencyProvider> providers,
+        Context context) {
+        super.injectDependencies(providers, context);
+        providers.put(NotificationEntryManager.class,
+            () -> new CarNotificationEntryManager(context));
+        providers.put(CarFacetButtonController.class, () -> new CarFacetButtonController(context));
+        providers.put(HvacController.class, () -> new HvacController(context));
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/AnimatedTemperatureView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/AnimatedTemperatureView.java
new file mode 100644
index 0000000..6473f0d
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/AnimatedTemperatureView.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.hvac;
+
+import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.util.AttributeSet;
+import android.util.Property;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextSwitcher;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.car.hvac.TemperatureView;
+
+/**
+ * Simple text display of HVAC properties, It is designed to show mTemperature and is configured in
+ * the XML.
+ * XML properties:
+ * hvacPropertyId - Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (16385)
+ * hvacAreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1)
+ * hvacTempFormat - Example: "%.1f\u00B0" (1 decimal and the degree symbol)
+ * hvacOrientaion = Example: left
+ */
+public class AnimatedTemperatureView extends FrameLayout implements TemperatureView {
+
+    private static final float TEMPERATURE_EQUIVALENT_DELTA = .01f;
+    private static final Property<ColorDrawable, Integer> COLOR_PROPERTY =
+            new Property<ColorDrawable, Integer>(Integer.class, "color") {
+
+                @Override
+                public Integer get(ColorDrawable object) {
+                    return object.getColor();
+                }
+
+                @Override
+                public void set(ColorDrawable object, Integer value) {
+                    object.setColor(value);
+                }
+            };
+
+    static boolean isHorizontal(int gravity) {
+        return Gravity.isHorizontal(gravity)
+                && (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.CENTER_HORIZONTAL;
+    }
+
+    @SuppressLint("RtlHardcoded")
+    static boolean isLeft(int gravity, int layoutDirection) {
+        return Gravity
+                .getAbsoluteGravity(gravity & Gravity.HORIZONTAL_GRAVITY_MASK, layoutDirection)
+                == Gravity.LEFT;
+    }
+
+    static boolean isVertical(int gravity) {
+        return Gravity.isVertical(gravity)
+                && (gravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.CENTER_VERTICAL;
+    }
+
+    static boolean isTop(int gravity) {
+        return (gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.TOP;
+    }
+
+    private final int mAreaId;
+    private final int mPropertyId;
+    private final int mPivotOffset;
+    private final int mGravity;
+    private final int mTextAppearanceRes;
+    private final int mMinEms;
+    private final Rect mPaddingRect;
+    private final float mMinValue;
+    private final float mMaxValue;
+
+    private final ColorDrawable mBackgroundColor;
+
+    private final TemperatureColorStore mColorStore = new TemperatureColorStore();
+    private final TemperatureBackgroundAnimator mBackgroundAnimator;
+    private final TemperatureTextAnimator mTextAnimator;
+
+    public AnimatedTemperatureView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        TypedArray typedArray = context.obtainStyledAttributes(attrs,
+                R.styleable.AnimatedTemperatureView);
+        mAreaId = typedArray.getInt(R.styleable.AnimatedTemperatureView_hvacAreaId, -1);
+        mPropertyId = typedArray.getInt(R.styleable.AnimatedTemperatureView_hvacPropertyId, -1);
+        mPivotOffset =
+                typedArray.getDimensionPixelOffset(
+                        R.styleable.AnimatedTemperatureView_hvacPivotOffset, 0);
+        mGravity = typedArray.getInt(R.styleable.AnimatedTemperatureView_android_gravity,
+                Gravity.START);
+        mTextAppearanceRes =
+                typedArray.getResourceId(R.styleable.AnimatedTemperatureView_android_textAppearance,
+                        0);
+        mMinEms = typedArray.getInteger(R.styleable.AnimatedTemperatureView_android_minEms, 0);
+        mMinValue = typedArray.getFloat(R.styleable.AnimatedTemperatureView_hvacMinValue,
+                Float.NaN);
+        mMaxValue = typedArray.getFloat(R.styleable.AnimatedTemperatureView_hvacMaxValue,
+                Float.NaN);
+
+
+        mPaddingRect =
+                new Rect(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom());
+        setPadding(0, 0, 0, 0);
+
+        setClipChildren(false);
+        setClipToPadding(false);
+
+        // init Views
+        TextSwitcher textSwitcher = new TextSwitcher(context);
+        textSwitcher.setFactory(this::generateTextView);
+        ImageView background = new ImageView(context);
+        mBackgroundColor = new ColorDrawable(Color.TRANSPARENT);
+        background.setImageDrawable(mBackgroundColor);
+        background.setVisibility(View.GONE);
+
+        mBackgroundAnimator = new TemperatureBackgroundAnimator(this, background);
+
+
+        String format = typedArray.getString(R.styleable.AnimatedTemperatureView_hvacTempFormat);
+        format = (format == null) ? "%.1f\u00B0" : format;
+        CharSequence minText = typedArray.getString(
+                R.styleable.AnimatedTemperatureView_hvacMinText);
+        CharSequence maxText = typedArray.getString(
+                R.styleable.AnimatedTemperatureView_hvacMaxText);
+        mTextAnimator = new TemperatureTextAnimator(this, textSwitcher, format, mPivotOffset,
+                minText, maxText);
+
+        addView(background, ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT);
+        addView(textSwitcher, ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT);
+
+        typedArray.recycle();
+    }
+
+
+    private TextView generateTextView() {
+        TextView textView = new TextView(getContext());
+        textView.setTextAppearance(mTextAppearanceRes);
+        textView.setAllCaps(true);
+        textView.setMinEms(mMinEms);
+        textView.setGravity(mGravity);
+        textView.setPadding(mPaddingRect.left, mPaddingRect.top, mPaddingRect.right,
+                mPaddingRect.bottom);
+        textView.getViewTreeObserver()
+                .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        if (isHorizontal(mGravity)) {
+                            if (isLeft(mGravity, getLayoutDirection())) {
+                                textView.setPivotX(-mPivotOffset);
+                            } else {
+                                textView.setPivotX(textView.getWidth() + mPivotOffset);
+                            }
+                        }
+                        textView.getViewTreeObserver().removeOnPreDrawListener(this);
+                        return false;
+                    }
+                });
+        textView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+
+        return textView;
+    }
+
+    /**
+     * Formats the float for display
+     *
+     * @param temp - The current temp or NaN
+     */
+    @Override
+    public void setTemp(float temp) {
+        mTextAnimator.setTemp(temp);
+        if (Float.isNaN(temp)) {
+            mBackgroundAnimator.hideCircle();
+            return;
+        }
+        int color;
+        if (isMinValue(temp)) {
+            color = mColorStore.getMinColor();
+        } else if (isMaxValue(temp)) {
+            color = mColorStore.getMaxColor();
+        } else {
+            color = mColorStore.getColorForTemperature(temp);
+        }
+        if (mBackgroundAnimator.isOpen()) {
+            ObjectAnimator colorAnimator =
+                    ObjectAnimator.ofInt(mBackgroundColor, COLOR_PROPERTY, color);
+            colorAnimator.setEvaluator((fraction, startValue, endValue) -> mColorStore
+                    .lerpColor(fraction, (int) startValue, (int) endValue));
+            colorAnimator.start();
+        } else {
+            mBackgroundColor.setColor(color);
+        }
+
+        mBackgroundAnimator.animateOpen();
+    }
+
+    boolean isMinValue(float temp) {
+        return !Float.isNaN(mMinValue) && isApproxEqual(temp, mMinValue);
+    }
+
+    boolean isMaxValue(float temp) {
+        return !Float.isNaN(mMaxValue) && isApproxEqual(temp, mMaxValue);
+    }
+
+    private boolean isApproxEqual(float left, float right) {
+        return Math.abs(left - right) <= TEMPERATURE_EQUIVALENT_DELTA;
+    }
+
+    int getGravity() {
+        return mGravity;
+    }
+
+    int getPivotOffset() {
+        return mPivotOffset;
+    }
+
+    Rect getPaddingRect() {
+        return mPaddingRect;
+    }
+
+    /**
+     * @return propertiyId  Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (358614275)
+     */
+    @Override
+    public int getPropertyId() {
+        return mPropertyId;
+    }
+
+    /**
+     * @return hvac AreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1)
+     */
+    @Override
+    public int getAreaId() {
+        return mAreaId;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mBackgroundAnimator.stopAnimations();
+    }
+
+}
+
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/TemperatureBackgroundAnimator.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/TemperatureBackgroundAnimator.java
new file mode 100644
index 0000000..3c6d623
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/TemperatureBackgroundAnimator.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.hvac;
+
+import static com.android.systemui.statusbar.hvac.AnimatedTemperatureView.isHorizontal;
+import static com.android.systemui.statusbar.hvac.AnimatedTemperatureView.isLeft;
+import static com.android.systemui.statusbar.hvac.AnimatedTemperatureView.isTop;
+import static com.android.systemui.statusbar.hvac.AnimatedTemperatureView.isVertical;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.annotation.IntDef;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.animation.AnticipateInterpolator;
+import android.widget.ImageView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Controls circular reveal animation of temperature background
+ */
+class TemperatureBackgroundAnimator {
+
+    private static final AnticipateInterpolator ANTICIPATE_INTERPOLATOR =
+            new AnticipateInterpolator();
+    private static final float MAX_OPACITY = .6f;
+
+    private final View mAnimatedView;
+
+    private int mPivotX;
+    private int mPivotY;
+    private int mGoneRadius;
+    private int mOvershootRadius;
+    private int mRestingRadius;
+    private int mBumpRadius;
+
+    @CircleState
+    private int mCircleState;
+
+    private Animator mCircularReveal;
+    private boolean mAnimationsReady;
+
+    @IntDef({CircleState.GONE, CircleState.ENTERING, CircleState.OVERSHOT, CircleState.RESTING,
+            CircleState.RESTED, CircleState.BUMPING, CircleState.BUMPED, CircleState.EXITING})
+    private @interface CircleState {
+        int GONE = 0;
+        int ENTERING = 1;
+        int OVERSHOT = 2;
+        int RESTING = 3;
+        int RESTED = 4;
+        int BUMPING = 5;
+        int BUMPED = 6;
+        int EXITING = 7;
+    }
+
+    TemperatureBackgroundAnimator(
+            AnimatedTemperatureView parent,
+            ImageView animatedView) {
+        mAnimatedView = animatedView;
+        mAnimatedView.setAlpha(0);
+
+        parent.addOnLayoutChangeListener(
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
+                        setupAnimations(parent.getGravity(), parent.getPivotOffset(),
+                                parent.getPaddingRect(), parent.getWidth(), parent.getHeight()));
+    }
+
+    private void setupAnimations(int gravity, int pivotOffset, Rect paddingRect,
+            int width, int height) {
+        int padding;
+        if (isHorizontal(gravity)) {
+            mGoneRadius = pivotOffset;
+            if (isLeft(gravity, mAnimatedView.getLayoutDirection())) {
+                mPivotX = -pivotOffset;
+                padding = paddingRect.right;
+            } else {
+                mPivotX = width + pivotOffset;
+                padding = paddingRect.left;
+            }
+            mPivotY = height / 2;
+            mOvershootRadius = pivotOffset + width;
+        } else if (isVertical(gravity)) {
+            mGoneRadius = pivotOffset;
+            if (isTop(gravity)) {
+                mPivotY = -pivotOffset;
+                padding = paddingRect.bottom;
+            } else {
+                mPivotY = height + pivotOffset;
+                padding = paddingRect.top;
+            }
+            mPivotX = width / 2;
+            mOvershootRadius = pivotOffset + height;
+        } else {
+            mPivotX = width / 2;
+            mPivotY = height / 2;
+            mGoneRadius = 0;
+            if (width > height) {
+                mOvershootRadius = height;
+                padding = Math.max(paddingRect.top, paddingRect.bottom);
+            } else {
+                mOvershootRadius = width;
+                padding = Math.max(paddingRect.left, paddingRect.right);
+            }
+        }
+        mRestingRadius = mOvershootRadius - padding;
+        mBumpRadius = mOvershootRadius - padding / 3;
+        mAnimationsReady = true;
+    }
+
+    boolean isOpen() {
+        return mCircleState != CircleState.GONE;
+    }
+
+    void animateOpen() {
+        if (!mAnimationsReady
+                || !mAnimatedView.isAttachedToWindow()
+                || mCircleState == CircleState.ENTERING) {
+            return;
+        }
+
+        AnimatorSet set = new AnimatorSet();
+        List<Animator> animators = new ArrayList<>();
+        switch (mCircleState) {
+            case CircleState.ENTERING:
+                throw new AssertionError("Should not be able to reach this statement");
+            case CircleState.GONE: {
+                Animator startCircle = createEnterAnimator();
+                markState(startCircle, CircleState.ENTERING);
+                animators.add(startCircle);
+                Animator holdOvershoot = ViewAnimationUtils
+                        .createCircularReveal(mAnimatedView, mPivotX, mPivotY, mOvershootRadius,
+                                mOvershootRadius);
+                holdOvershoot.setDuration(50);
+                markState(holdOvershoot, CircleState.OVERSHOT);
+                animators.add(holdOvershoot);
+                Animator rest = ViewAnimationUtils
+                        .createCircularReveal(mAnimatedView, mPivotX, mPivotY, mOvershootRadius,
+                                mRestingRadius);
+                markState(rest, CircleState.RESTING);
+                animators.add(rest);
+                Animator holdRest = ViewAnimationUtils
+                        .createCircularReveal(mAnimatedView, mPivotX, mPivotY, mRestingRadius,
+                                mRestingRadius);
+                markState(holdRest, CircleState.RESTED);
+                holdRest.setDuration(1000);
+                animators.add(holdRest);
+                Animator exit = createExitAnimator(mRestingRadius);
+                markState(exit, CircleState.EXITING);
+                animators.add(exit);
+            }
+            break;
+            case CircleState.RESTED:
+            case CircleState.RESTING:
+            case CircleState.EXITING:
+            case CircleState.OVERSHOT:
+                int startRadius =
+                        mCircleState == CircleState.OVERSHOT ? mOvershootRadius : mRestingRadius;
+                Animator bump = ViewAnimationUtils
+                        .createCircularReveal(mAnimatedView, mPivotX, mPivotY, startRadius,
+                                mBumpRadius);
+                bump.setDuration(50);
+                markState(bump, CircleState.BUMPING);
+                animators.add(bump);
+                // fallthrough intentional
+            case CircleState.BUMPED:
+            case CircleState.BUMPING:
+                Animator holdBump = ViewAnimationUtils
+                        .createCircularReveal(mAnimatedView, mPivotX, mPivotY, mBumpRadius,
+                                mBumpRadius);
+                holdBump.setDuration(100);
+                markState(holdBump, CircleState.BUMPED);
+                animators.add(holdBump);
+                Animator rest = ViewAnimationUtils
+                        .createCircularReveal(mAnimatedView, mPivotX, mPivotY, mBumpRadius,
+                                mRestingRadius);
+                markState(rest, CircleState.RESTING);
+                animators.add(rest);
+                Animator holdRest = ViewAnimationUtils
+                        .createCircularReveal(mAnimatedView, mPivotX, mPivotY, mRestingRadius,
+                                mRestingRadius);
+                holdRest.setDuration(1000);
+                markState(holdRest, CircleState.RESTED);
+                animators.add(holdRest);
+                Animator exit = createExitAnimator(mRestingRadius);
+                markState(exit, CircleState.EXITING);
+                animators.add(exit);
+                break;
+        }
+        set.playSequentially(animators);
+        set.addListener(new AnimatorListenerAdapter() {
+            private boolean mCanceled = false;
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+                if (mCircularReveal != null) {
+                    mCircularReveal.cancel();
+                }
+                mCircularReveal = animation;
+                mAnimatedView.setVisibility(View.VISIBLE);
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mCanceled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (mCanceled) {
+                    return;
+                }
+                mCircularReveal = null;
+                mCircleState = CircleState.GONE;
+                mAnimatedView.setVisibility(View.GONE);
+            }
+        });
+
+        set.start();
+    }
+
+    private Animator createEnterAnimator() {
+        AnimatorSet animatorSet = new AnimatorSet();
+        Animator circularReveal = ViewAnimationUtils
+                .createCircularReveal(mAnimatedView, mPivotX, mPivotY, mGoneRadius,
+                        mOvershootRadius);
+        Animator fade = ObjectAnimator.ofFloat(mAnimatedView, View.ALPHA, MAX_OPACITY);
+        animatorSet.playTogether(circularReveal, fade);
+        return animatorSet;
+    }
+
+    private Animator createExitAnimator(int startRadius) {
+        AnimatorSet animatorSet = new AnimatorSet();
+        Animator circularHide = ViewAnimationUtils
+                .createCircularReveal(mAnimatedView, mPivotX, mPivotY, startRadius,
+                        (mGoneRadius + startRadius) / 2);
+        circularHide.setInterpolator(ANTICIPATE_INTERPOLATOR);
+        Animator fade = ObjectAnimator.ofFloat(mAnimatedView, View.ALPHA, 0);
+        fade.setStartDelay(50);
+        animatorSet.playTogether(circularHide, fade);
+        return animatorSet;
+    }
+
+    void hideCircle() {
+        if (!mAnimationsReady || mCircleState == CircleState.GONE
+                || mCircleState == CircleState.EXITING) {
+            return;
+        }
+
+        int startRadius;
+        switch (mCircleState) {
+            // Unreachable, but here to exhaust switch cases
+            //noinspection ConstantConditions
+            case CircleState.EXITING:
+                //noinspection ConstantConditions
+            case CircleState.GONE:
+                throw new AssertionError("Should not be able to reach this statement");
+            case CircleState.BUMPED:
+            case CircleState.BUMPING:
+                startRadius = mBumpRadius;
+                break;
+            case CircleState.OVERSHOT:
+                startRadius = mOvershootRadius;
+                break;
+            case CircleState.ENTERING:
+            case CircleState.RESTED:
+            case CircleState.RESTING:
+                startRadius = mRestingRadius;
+                break;
+            default:
+                throw new IllegalStateException("Unknown CircleState: " + mCircleState);
+        }
+
+        Animator hideAnimation = createExitAnimator(startRadius);
+        if (startRadius == mRestingRadius) {
+            hideAnimation.setInterpolator(ANTICIPATE_INTERPOLATOR);
+        }
+        hideAnimation.addListener(new AnimatorListenerAdapter() {
+            private boolean mCanceled = false;
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mCircleState = CircleState.EXITING;
+                if (mCircularReveal != null) {
+                    mCircularReveal.cancel();
+                }
+                mCircularReveal = animation;
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mCanceled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (mCanceled) {
+                    return;
+                }
+                mCircularReveal = null;
+                mCircleState = CircleState.GONE;
+                mAnimatedView.setVisibility(View.GONE);
+            }
+        });
+        hideAnimation.start();
+    }
+
+    void stopAnimations() {
+        if (mCircularReveal != null) {
+            mCircularReveal.end();
+        }
+    }
+
+    private void markState(Animator animator, @CircleState int startState) {
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mCircleState = startState;
+            }
+        });
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/TemperatureColorStore.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/TemperatureColorStore.java
new file mode 100644
index 0000000..a40ffaf
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/TemperatureColorStore.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.hvac;
+
+import android.graphics.Color;
+
+/**
+ * Contains the logic for mapping colors to temperatures
+ */
+class TemperatureColorStore {
+
+    private static class TemperatureColorValue {
+        final float mTemperature;
+        final int mColor;
+
+        private TemperatureColorValue(float temperature, int color) {
+            this.mTemperature = temperature;
+            this.mColor = color;
+        }
+
+        float getTemperature() {
+            return mTemperature;
+        }
+
+        int getColor() {
+            return mColor;
+        }
+    }
+
+    private static TemperatureColorValue tempToColor(float temperature, int color) {
+        return new TemperatureColorValue(temperature, color);
+    }
+
+    private static final int COLOR_COLDEST = 0xFF406DFF;
+    private static final int COLOR_COLD = 0xFF4094FF;
+    private static final int COLOR_NEUTRAL = 0xFFF4F4F4;
+    private static final int COLOR_WARM = 0xFFFF550F;
+    private static final int COLOR_WARMEST = 0xFFFF0000;
+    // must be sorted by temperature
+    private static final TemperatureColorValue[] sTemperatureColorValues =
+            {
+                    // Celsius
+                    tempToColor(19, COLOR_COLDEST),
+                    tempToColor(21, COLOR_COLD),
+                    tempToColor(23, COLOR_NEUTRAL),
+                    tempToColor(25, COLOR_WARM),
+                    tempToColor(27, COLOR_WARMEST),
+
+                    // Switch over
+                    tempToColor(45, COLOR_WARMEST),
+                    tempToColor(45.00001f, COLOR_COLDEST),
+
+                    // Farenheight
+                    tempToColor(66, COLOR_COLDEST),
+                    tempToColor(70, COLOR_COLD),
+                    tempToColor(74, COLOR_NEUTRAL),
+                    tempToColor(76, COLOR_WARM),
+                    tempToColor(80, COLOR_WARMEST)
+            };
+
+    private static final int COLOR_UNSET = Color.BLACK;
+
+    private final float[] mTempHsv1 = new float[3];
+    private final float[] mTempHsv2 = new float[3];
+    private final float[] mTempHsv3 = new float[3];
+
+    int getMinColor() {
+        return COLOR_COLDEST;
+    }
+
+    int getMaxColor() {
+        return COLOR_WARMEST;
+    }
+
+    int getColorForTemperature(float temperature) {
+        if (Float.isNaN(temperature)) {
+            return COLOR_UNSET;
+        }
+        TemperatureColorValue bottomValue = sTemperatureColorValues[0];
+        if (temperature <= bottomValue.getTemperature()) {
+            return bottomValue.getColor();
+        }
+        TemperatureColorValue topValue =
+                sTemperatureColorValues[sTemperatureColorValues.length - 1];
+        if (temperature >= topValue.getTemperature()) {
+            return topValue.getColor();
+        }
+
+        int index = binarySearch(temperature);
+        if (index >= 0) {
+            return sTemperatureColorValues[index].getColor();
+        }
+
+        index = -index - 1; // move to the insertion point
+
+        TemperatureColorValue startValue = sTemperatureColorValues[index - 1];
+        TemperatureColorValue endValue = sTemperatureColorValues[index];
+        float fraction = (temperature - startValue.getTemperature()) / (endValue.getTemperature()
+                - startValue.getTemperature());
+        return lerpColor(fraction, startValue.getColor(), endValue.getColor());
+    }
+
+    int lerpColor(float fraction, int startColor, int endColor) {
+        float[] startHsv = mTempHsv1;
+        Color.colorToHSV(startColor, startHsv);
+        float[] endHsv = mTempHsv2;
+        Color.colorToHSV(endColor, endHsv);
+
+        // If a target color is white/gray, it should use the same hue as the other target
+        if (startHsv[1] == 0) {
+            startHsv[0] = endHsv[0];
+        }
+        if (endHsv[1] == 0) {
+            endHsv[0] = startHsv[0];
+        }
+
+        float[] outColor = mTempHsv3;
+        outColor[0] = hueLerp(fraction, startHsv[0], endHsv[0]);
+        outColor[1] = lerp(fraction, startHsv[1], endHsv[1]);
+        outColor[2] = lerp(fraction, startHsv[2], endHsv[2]);
+
+        return Color.HSVToColor(outColor);
+    }
+
+    private float hueLerp(float fraction, float start, float end) {
+        // If in flat part of curve, no interpolation necessary
+        if (start == end) {
+            return start;
+        }
+
+        // If the hues are more than 180 degrees apart, go the other way around the color wheel
+        // by moving the smaller value above 360
+        if (Math.abs(start - end) > 180f) {
+            if (start < end) {
+                start += 360f;
+            } else {
+                end += 360f;
+            }
+        }
+        // Lerp and ensure the final output is within [0, 360)
+        return lerp(fraction, start, end) % 360f;
+
+    }
+
+    private float lerp(float fraction, float start, float end) {
+        // If in flat part of curve, no interpolation necessary
+        if (start == end) {
+            return start;
+        }
+
+        // If outside bounds, use boundary value
+        if (fraction >= 1) {
+            return end;
+        }
+        if (fraction <= 0) {
+            return start;
+        }
+
+        return (end - start) * fraction + start;
+    }
+
+    private int binarySearch(float temperature) {
+        int low = 0;
+        int high = sTemperatureColorValues.length;
+
+        while (low <= high) {
+            int mid = (low + high) >>> 1;
+            float midVal = sTemperatureColorValues[mid].getTemperature();
+
+            if (midVal < temperature) {
+                low = mid + 1;  // Neither val is NaN, thisVal is smaller
+            } else if (midVal > temperature) {
+                high = mid - 1; // Neither val is NaN, thisVal is larger
+            } else {
+                int midBits = Float.floatToIntBits(midVal);
+                int keyBits = Float.floatToIntBits(temperature);
+                if (midBits == keyBits) {    // Values are equal
+                    return mid;             // Key found
+                } else if (midBits < keyBits) { // (-0.0, 0.0) or (!NaN, NaN)
+                    low = mid + 1;
+                } else {                        /* (0.0, -0.0) or (NaN, !NaN)*/
+                    high = mid - 1;
+                }
+            }
+        }
+        return -(low + 1);  // key not found.
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/TemperatureTextAnimator.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/TemperatureTextAnimator.java
new file mode 100644
index 0000000..8ee5ef6
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/hvac/TemperatureTextAnimator.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.hvac;
+
+import static com.android.systemui.statusbar.hvac.AnimatedTemperatureView.isHorizontal;
+import static com.android.systemui.statusbar.hvac.AnimatedTemperatureView.isLeft;
+
+import android.annotation.NonNull;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.RotateAnimation;
+import android.view.animation.TranslateAnimation;
+import android.widget.TextSwitcher;
+
+/**
+ * Controls animating TemperatureView's text
+ */
+class TemperatureTextAnimator {
+
+    private static final DecelerateInterpolator DECELERATE_INTERPOLATOR =
+            new DecelerateInterpolator();
+    private static final AccelerateDecelerateInterpolator ACCELERATE_DECELERATE_INTERPOLATOR =
+            new AccelerateDecelerateInterpolator();
+
+    private static final int ROTATION_DEGREES = 15;
+    private static final int DURATION_MILLIS = 200;
+
+    private AnimatedTemperatureView mParent;
+    private final TextSwitcher mTextSwitcher;
+    private final String mTempFormat;
+    private final int mPivotOffset;
+    private final CharSequence mMinText;
+    private final CharSequence mMaxText;
+
+    private Animation mTextInAnimationUp;
+    private Animation mTextOutAnimationUp;
+    private Animation mTextInAnimationDown;
+    private Animation mTextOutAnimationDown;
+    private Animation mTextFadeInAnimation;
+    private Animation mTextFadeOutAnimation;
+
+    private float mLastTemp = Float.NaN;
+
+    TemperatureTextAnimator(AnimatedTemperatureView parent, TextSwitcher textSwitcher,
+            String tempFormat, int pivotOffset,
+            CharSequence minText, CharSequence maxText) {
+        mParent = parent;
+        mTextSwitcher = textSwitcher;
+        mTempFormat = tempFormat;
+        mPivotOffset = pivotOffset;
+        mMinText = minText;
+        mMaxText = maxText;
+
+        mParent.addOnLayoutChangeListener(
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
+                        setupAnimations(mParent.getGravity()));
+    }
+
+    void setTemp(float temp) {
+        if (Float.isNaN(temp)) {
+            mTextSwitcher.setInAnimation(mTextFadeInAnimation);
+            mTextSwitcher.setOutAnimation(mTextFadeOutAnimation);
+            mTextSwitcher.setText("--");
+            mLastTemp = temp;
+            return;
+        }
+        boolean isMinValue = mParent.isMinValue(temp);
+        boolean isMaxValue = mParent.isMaxValue(temp);
+        if (Float.isNaN(mLastTemp)) {
+            mTextSwitcher.setInAnimation(mTextFadeInAnimation);
+            mTextSwitcher.setOutAnimation(mTextFadeOutAnimation);
+        } else if (!isMinValue && (isMaxValue || temp > mLastTemp)) {
+            mTextSwitcher.setInAnimation(mTextInAnimationUp);
+            mTextSwitcher.setOutAnimation(mTextOutAnimationUp);
+        } else {
+            mTextSwitcher.setInAnimation(mTextInAnimationDown);
+            mTextSwitcher.setOutAnimation(mTextOutAnimationDown);
+        }
+        CharSequence text;
+        if (isMinValue) {
+            text = mMinText;
+        } else if (isMaxValue) {
+            text = mMaxText;
+        } else {
+            text = String.format(mTempFormat, temp);
+        }
+        mTextSwitcher.setText(text);
+        mLastTemp = temp;
+    }
+
+    private void setupAnimations(int gravity) {
+        mTextFadeInAnimation = createFadeAnimation(true);
+        mTextFadeOutAnimation = createFadeAnimation(false);
+        if (!isHorizontal(gravity)) {
+            mTextInAnimationUp = createTranslateFadeAnimation(true, true);
+            mTextOutAnimationUp = createTranslateFadeAnimation(false, true);
+            mTextInAnimationDown = createTranslateFadeAnimation(true, false);
+            mTextOutAnimationDown = createTranslateFadeAnimation(false, false);
+        } else {
+            boolean isLeft = isLeft(gravity, mTextSwitcher.getLayoutDirection());
+            mTextInAnimationUp = createRotateFadeAnimation(true, isLeft, true);
+            mTextOutAnimationUp = createRotateFadeAnimation(false, isLeft, true);
+            mTextInAnimationDown = createRotateFadeAnimation(true, isLeft, false);
+            mTextOutAnimationDown = createRotateFadeAnimation(false, isLeft, false);
+        }
+    }
+
+    @NonNull
+    private Animation createFadeAnimation(boolean in) {
+        AnimationSet set = new AnimationSet(true);
+        AlphaAnimation alphaAnimation = new AlphaAnimation(in ? 0 : 1, in ? 1 : 0);
+        alphaAnimation.setDuration(DURATION_MILLIS);
+        set.addAnimation(new RotateAnimation(0, 0)); // Undo any previous rotation
+        set.addAnimation(alphaAnimation);
+        return set;
+    }
+
+    @NonNull
+    private Animation createTranslateFadeAnimation(boolean in, boolean up) {
+        AnimationSet set = new AnimationSet(true);
+        set.setInterpolator(ACCELERATE_DECELERATE_INTERPOLATOR);
+        set.setDuration(DURATION_MILLIS);
+        int fromYDelta = in ? (up ? 1 : -1) : 0;
+        int toYDelta = in ? 0 : (up ? -1 : 1);
+        set.addAnimation(
+                new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0,
+                        Animation.RELATIVE_TO_SELF, fromYDelta, Animation.RELATIVE_TO_SELF,
+                        toYDelta));
+        set.addAnimation(new AlphaAnimation(in ? 0 : 1, in ? 1 : 0));
+        return set;
+    }
+
+    @NonNull
+    private Animation createRotateFadeAnimation(boolean in, boolean isLeft, boolean up) {
+        AnimationSet set = new AnimationSet(true);
+        set.setInterpolator(DECELERATE_INTERPOLATOR);
+        set.setDuration(DURATION_MILLIS);
+
+        float degrees = isLeft == up ? -ROTATION_DEGREES : ROTATION_DEGREES;
+        int pivotX = isLeft ? -mPivotOffset : mParent.getWidth() + mPivotOffset;
+        set.addAnimation(
+                new RotateAnimation(in ? -degrees : 0f, in ? 0f : degrees, Animation.ABSOLUTE,
+                        pivotX, Animation.ABSOLUTE, 0f));
+        set.addAnimation(new AlphaAnimation(in ? 0 : 1, in ? 1 : 0));
+        return set;
+    }
+}
diff --git a/packages/CarrierDefaultApp/res/values-kn/strings.xml b/packages/CarrierDefaultApp/res/values-kn/strings.xml
index 73d0764..ea4b09a 100644
--- a/packages/CarrierDefaultApp/res/values-kn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kn/strings.xml
@@ -8,7 +8,7 @@
     <string name="portal_notification_detail" msgid="2295729385924660881">"%s ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="no_data_notification_detail" msgid="3112125343857014825">"ನಿಮಗೆ ಸೇವೆ ಒದಗಿಸುವವರನ್ನು ದಯವಿಟ್ಟು ಸಂಪರ್ಕಿಸಿ %s"</string>
     <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"ಮೊಬೈಲ್ ಡೇಟಾ ಸಂಪರ್ಕವಿಲ್ಲ"</string>
-    <string name="no_mobile_data_connection" msgid="544980465184147010">"%s ಮೂಲಕ ಡೇಟಾ ಅಥವಾ ರೋಮಿಂಗ್ ಪ್ಲ್ಯಾನ್ ಸೇರಿಸಿ"</string>
+    <string name="no_mobile_data_connection" msgid="544980465184147010">"%s ಮೂಲಕ ಡೇಟಾ ಅಥವಾ ರೋಮಿಂಗ್ ಪ್ಲಾನ್ ಸೇರಿಸಿ"</string>
     <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"ಮೊಬೈಲ್ ಡೇಟಾ ಸ್ಥಿತಿ"</string>
     <string name="action_bar_label" msgid="4290345990334377177">"ಮೊಬೈಲ್ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
     <string name="ssl_error_warning" msgid="3127935140338254180">"ನೀವು ಸೇರಬೇಕೆಂದಿರುವ ನೆಟ್‌ವರ್ಕ್, ಭದ್ರತೆ ಸಮಸ್ಯೆಗಳನ್ನು ಹೊಂದಿದೆ."</string>
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index ff70e97..a7217ec 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -55,12 +55,6 @@
             <intent-filter>
                 <action android:name="android.service.autofill.AutofillFieldClassificationService" />
             </intent-filter>
-            <meta-data
-                android:name="android.autofill.field_classification.default_algorithm"
-                android:resource="@string/autofill_field_classification_default_algorithm" />
-            <meta-data
-                android:name="android.autofill.field_classification.available_algorithms"
-                android:resource="@array/autofill_field_classification_available_algorithms" />
         </service>
 
         <library android:name="android.ext.services"/>
diff --git a/packages/ExtServices/src/android/ext/services/notification/AgingHelper.java b/packages/ExtServices/src/android/ext/services/notification/AgingHelper.java
new file mode 100644
index 0000000..5782ea1
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/notification/AgingHelper.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.ext.services.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.ext.services.notification.NotificationCategorizer.Category;
+import android.net.Uri;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import java.util.Set;
+
+public class AgingHelper {
+    private final static String TAG = "AgingHelper";
+    private final boolean DEBUG = false;
+
+    private static final String AGING_ACTION = AgingHelper.class.getSimpleName() + ".EVALUATE";
+    private static final int REQUEST_CODE_AGING = 1;
+    private static final String AGING_SCHEME = "aging";
+    private static final String EXTRA_KEY = "key";
+    private static final String EXTRA_CATEGORY = "category";
+
+    private static final int HOUR_MS = 1000 * 60 * 60;
+    private static final int TWO_HOURS_MS = 2 * HOUR_MS;
+
+    private Context mContext;
+    private NotificationCategorizer mNotificationCategorizer;
+    private AlarmManager mAm;
+    private Callback mCallback;
+
+    // The set of keys we've scheduled alarms for
+    private Set<String> mAging = new ArraySet<>();
+
+    public AgingHelper(Context context, NotificationCategorizer categorizer, Callback callback) {
+        mNotificationCategorizer = categorizer;
+        mContext = context;
+        mAm = mContext.getSystemService(AlarmManager.class);
+        mCallback = callback;
+
+        IntentFilter filter = new IntentFilter(AGING_ACTION);
+        filter.addDataScheme(AGING_SCHEME);
+        mContext.registerReceiver(mBroadcastReceiver, filter);
+    }
+
+    // NAS lifecycle methods
+
+    public void onNotificationSeen(NotificationEntry entry) {
+        // user has strong opinions about this notification. we can't down rank it, so don't bother.
+        if (entry.getChannel().isImportanceLocked()) {
+            return;
+        }
+
+        @Category int category = mNotificationCategorizer.getCategory(entry);
+
+        // already very low
+        if (category == NotificationCategorizer.CATEGORY_MIN) {
+            return;
+        }
+
+        if (entry.hasSeen()) {
+            if (category == NotificationCategorizer.CATEGORY_ONGOING
+                    || category > NotificationCategorizer.CATEGORY_REMINDER) {
+                scheduleAging(entry.getSbn().getKey(), category, TWO_HOURS_MS);
+            } else {
+                scheduleAging(entry.getSbn().getKey(), category, HOUR_MS);
+            }
+
+            mAging.add(entry.getSbn().getKey());
+        }
+    }
+
+    public void onNotificationPosted(NotificationEntry entry) {
+        cancelAging(entry.getSbn().getKey());
+    }
+
+    public void onNotificationRemoved(String key) {
+        cancelAging(key);
+    }
+
+    public void onDestroy() {
+        mContext.unregisterReceiver(mBroadcastReceiver);
+    }
+
+    // Aging
+
+    private void scheduleAging(String key, @Category int category, long duration) {
+        if (mAging.contains(key)) {
+            // already scheduled. Don't reset aging just because the user saw the noti again.
+            return;
+        }
+        final PendingIntent pi = createPendingIntent(key, category);
+        long time = System.currentTimeMillis() + duration;
+        if (DEBUG) Slog.d(TAG, "Scheduling evaluate for " + key + " in ms: " + duration);
+        mAm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pi);
+    }
+
+    private void cancelAging(String key) {
+        final PendingIntent pi = createPendingIntent(key);
+        mAm.cancel(pi);
+        mAging.remove(key);
+    }
+
+    private Intent createBaseIntent(String key) {
+        return new Intent(AGING_ACTION)
+                .setData(new Uri.Builder().scheme(AGING_SCHEME).appendPath(key).build());
+    }
+
+    private Intent createAgingIntent(String key, @Category int category) {
+        Intent intent = createBaseIntent(key);
+        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+                .putExtra(EXTRA_CATEGORY, category)
+                .putExtra(EXTRA_KEY, key);
+        return intent;
+    }
+
+    private PendingIntent createPendingIntent(String key, @Category int category) {
+        return PendingIntent.getBroadcast(mContext,
+                REQUEST_CODE_AGING,
+                createAgingIntent(key, category),
+                PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
+    private PendingIntent createPendingIntent(String key) {
+        return PendingIntent.getBroadcast(mContext,
+                REQUEST_CODE_AGING,
+                createBaseIntent(key),
+                PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
+    private void demote(String key, @Category int category) {
+        int newImportance = IMPORTANCE_MIN;
+        // TODO: Change "aged" importance based on category
+        mCallback.sendAdjustment(key, newImportance);
+    }
+
+    protected interface Callback {
+        void sendAdjustment(String key, int newImportance);
+    }
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DEBUG) {
+                Slog.d(TAG, "Reposting notification");
+            }
+            if (AGING_ACTION.equals(intent.getAction())) {
+                demote(intent.getStringExtra(EXTRA_KEY), intent.getIntExtra(EXTRA_CATEGORY,
+                        NotificationCategorizer.CATEGORY_EVERYTHING_ELSE));
+            }
+        }
+    };
+}
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index fdd6a9c..3333e15 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -16,19 +16,30 @@
 
 package android.ext.services.notification;
 
+import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
+import static android.service.notification.Adjustment.KEY_IMPORTANCE;
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_NEGATIVE;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityThread;
+import android.app.AlarmManager;
 import android.app.INotificationManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.IPackageManager;
 import android.database.ContentObserver;
-import android.ext.services.R;
+import android.ext.services.notification.AgingHelper.Callback;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.service.notification.Adjustment;
@@ -41,6 +52,7 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 
@@ -57,6 +69,7 @@
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -80,15 +93,20 @@
 
     private float mDismissToViewRatioLimit;
     private int mStreakLimit;
+    private SmartActionsHelper mSmartActionsHelper;
+    private NotificationCategorizer mNotificationCategorizer;
+    private AgingHelper mAgingHelper;
 
     // key : impressions tracker
     // TODO: prune deleted channels and apps
-    final ArrayMap<String, ChannelImpressions> mkeyToImpressions = new ArrayMap<>();
-    // SBN key : channel id
-    ArrayMap<String, String> mLiveNotifications = new ArrayMap<>();
+    private final ArrayMap<String, ChannelImpressions> mkeyToImpressions = new ArrayMap<>();
+    // SBN key : entry
+    protected ArrayMap<String, NotificationEntry> mLiveNotifications = new ArrayMap<>();
 
     private Ranking mFakeRanking = null;
     private AtomicFile mFile = null;
+    private IPackageManager mPackageManager;
+    protected SettingsObserver mSettingsObserver;
 
     public Assistant() {
     }
@@ -98,7 +116,13 @@
         super.onCreate();
         // Contexts are correctly hooked up by the creation step, which is required for the observer
         // to be hooked up/initialized.
-        new SettingsObserver(mHandler);
+        mPackageManager = ActivityThread.getPackageManager();
+        mSettingsObserver = new SettingsObserver(mHandler);
+        mSmartActionsHelper = new SmartActionsHelper();
+        mNotificationCategorizer = new NotificationCategorizer();
+        mAgingHelper = new AgingHelper(getContext(),
+                mNotificationCategorizer,
+                new AgingCallback());
     }
 
     private void loadFile() {
@@ -145,7 +169,7 @@
         }
     }
 
-    private void saveFile() throws IOException {
+    private void saveFile() {
         AsyncTask.execute(() -> {
             final FileOutputStream stream;
             try {
@@ -185,17 +209,56 @@
     }
 
     @Override
-    public Adjustment onNotificationEnqueued(StatusBarNotification sbn) {
-        if (DEBUG) Log.i(TAG, "ENQUEUED " + sbn.getKey());
-        return null;
+    public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
+            NotificationChannel channel) {
+        if (DEBUG) Log.i(TAG, "ENQUEUED " + sbn.getKey() + " on " + channel.getId());
+        if (!isForCurrentUser(sbn)) {
+            return null;
+        }
+        NotificationEntry entry = new NotificationEntry(
+                ActivityThread.getPackageManager(), sbn, channel);
+        ArrayList<Notification.Action> actions =
+                mSmartActionsHelper.suggestActions(this, entry);
+        ArrayList<CharSequence> replies = mSmartActionsHelper.suggestReplies(this, entry);
+        return createEnqueuedNotificationAdjustment(entry, actions, replies);
+    }
+
+    /** A convenience helper for creating an adjustment for an SBN. */
+    @Nullable
+    private Adjustment createEnqueuedNotificationAdjustment(
+            @NonNull NotificationEntry entry,
+            @NonNull ArrayList<Notification.Action> smartActions,
+            @NonNull ArrayList<CharSequence> smartReplies) {
+        Bundle signals = new Bundle();
+        if (!smartActions.isEmpty()) {
+            signals.putParcelableArrayList(Adjustment.KEY_SMART_ACTIONS, smartActions);
+        }
+        if (!smartReplies.isEmpty()) {
+            signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies);
+        }
+        if (mNotificationCategorizer.shouldSilence(entry)) {
+            signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
+        }
+
+        return new Adjustment(
+                entry.getSbn().getPackageName(),
+                entry.getSbn().getKey(),
+                signals,
+                "",
+                entry.getSbn().getUserId());
     }
 
     @Override
     public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
         if (DEBUG) Log.i(TAG, "POSTED " + sbn.getKey());
         try {
+            if (!isForCurrentUser(sbn)) {
+                return;
+            }
             Ranking ranking = getRanking(sbn.getKey(), rankingMap);
             if (ranking != null && ranking.getChannel() != null) {
+                NotificationEntry entry = new NotificationEntry(mPackageManager,
+                        sbn, ranking.getChannel());
                 String key = getKey(
                         sbn.getPackageName(), sbn.getUserId(), ranking.getChannel().getId());
                 ChannelImpressions ci = mkeyToImpressions.getOrDefault(key,
@@ -205,7 +268,8 @@
                             sbn.getPackageName(), sbn.getKey(), sbn.getUserId()));
                 }
                 mkeyToImpressions.put(key, ci);
-                mLiveNotifications.put(sbn.getKey(), ranking.getChannel().getId());
+                mLiveNotifications.put(sbn.getKey(), entry);
+                mAgingHelper.onNotificationPosted(entry);
             }
         } catch (Throwable e) {
             Log.e(TAG, "Error occurred processing post", e);
@@ -216,8 +280,11 @@
     public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
             NotificationStats stats, int reason) {
         try {
+            if (!isForCurrentUser(sbn)) {
+                return;
+            }
             boolean updatedImpressions = false;
-            String channelId = mLiveNotifications.remove(sbn.getKey());
+            String channelId = mLiveNotifications.remove(sbn.getKey()).getChannel().getId();
             String key = getKey(sbn.getPackageName(), sbn.getUserId(), channelId);
             synchronized (mkeyToImpressions) {
                 ChannelImpressions ci = mkeyToImpressions.getOrDefault(key,
@@ -249,7 +316,7 @@
                 saveFile();
             }
         } catch (Throwable e) {
-            Slog.e(TAG, "Error occurred processing removal", e);
+            Slog.e(TAG, "Error occurred processing removal of " + sbn, e);
         }
     }
 
@@ -259,6 +326,26 @@
     }
 
     @Override
+    public void onNotificationsSeen(List<String> keys) {
+        try {
+            if (keys == null) {
+                return;
+            }
+
+            for (String key : keys) {
+                NotificationEntry entry = mLiveNotifications.get(key);
+
+                if (entry != null) {
+                    entry.setSeen();
+                    mAgingHelper.onNotificationSeen(entry);
+                }
+            }
+        } catch (Throwable e) {
+            Slog.e(TAG, "Error occurred processing seen", e);
+        }
+    }
+
+    @Override
     public void onListenerConnected() {
         if (DEBUG) Log.i(TAG, "CONNECTED");
         try {
@@ -275,6 +362,17 @@
         }
     }
 
+    @Override
+    public void onListenerDisconnected() {
+        if (mAgingHelper != null) {
+            mAgingHelper.onDestroy();
+        }
+    }
+
+    private boolean isForCurrentUser(StatusBarNotification sbn) {
+        return sbn != null && sbn.getUserId() == UserHandle.myUserId();
+    }
+
     protected String getKey(String pkg, int userId, String channelId) {
         return pkg + "|" + userId + "|" + channelId;
     }
@@ -297,29 +395,40 @@
 
     // for testing
 
-    protected void setFile(AtomicFile file) {
+    @VisibleForTesting
+    public void setFile(AtomicFile file) {
         mFile = file;
     }
 
-    protected void setFakeRanking(Ranking ranking) {
+    @VisibleForTesting
+    public void setFakeRanking(Ranking ranking) {
         mFakeRanking = ranking;
     }
 
-    protected void setNoMan(INotificationManager noMan) {
+    @VisibleForTesting
+    public void setNoMan(INotificationManager noMan) {
         mNoMan = noMan;
     }
 
-    protected void setContext(Context context) {
+    @VisibleForTesting
+    public void setContext(Context context) {
         mSystemContext = context;
     }
 
-    protected ChannelImpressions getImpressions(String key) {
+    @VisibleForTesting
+    public void setPackageManager(IPackageManager pm) {
+        mPackageManager = pm;
+    }
+
+    @VisibleForTesting
+    public ChannelImpressions getImpressions(String key) {
         synchronized (mkeyToImpressions) {
             return mkeyToImpressions.get(key);
         }
     }
 
-    protected void insertImpressions(String key, ChannelImpressions ci) {
+    @VisibleForTesting
+    public void insertImpressions(String key, ChannelImpressions ci) {
         synchronized (mkeyToImpressions) {
             mkeyToImpressions.put(key, ci);
         }
@@ -331,10 +440,24 @@
         return impressions;
     }
 
+    protected final class AgingCallback implements Callback {
+        @Override
+        public void sendAdjustment(String key, int newImportance) {
+            NotificationEntry entry = mLiveNotifications.get(key);
+            if (entry != null) {
+                Bundle bundle = new Bundle();
+                bundle.putInt(KEY_IMPORTANCE, newImportance);
+                Adjustment adjustment = new Adjustment(entry.getSbn().getPackageName(), key, bundle,
+                        "aging", entry.getSbn().getUserId());
+                adjustNotification(adjustment);
+            }
+        }
+    }
+
     /**
      * Observer for updates on blocking helper threshold values.
      */
-    private final class SettingsObserver extends ContentObserver {
+    protected final class SettingsObserver extends ContentObserver {
         private final Uri STREAK_LIMIT_URI =
                 Settings.Global.getUriFor(Settings.Global.BLOCKING_HELPER_STREAK_LIMIT);
         private final Uri DISMISS_TO_VIEW_RATIO_LIMIT_URI =
@@ -378,4 +501,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/ExtServices/src/android/ext/services/notification/NotificationCategorizer.java b/packages/ExtServices/src/android/ext/services/notification/NotificationCategorizer.java
new file mode 100644
index 0000000..1f4ba01
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/notification/NotificationCategorizer.java
@@ -0,0 +1,104 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.ext.services.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+
+import android.annotation.IntDef;
+import android.app.Notification;
+import android.media.AudioAttributes;
+import android.os.Process;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Default categorizer for incoming notifications; used to determine what notifications
+ * should be silenced.
+ */
+// TODO: stop using @hide methods
+public class NotificationCategorizer {
+
+    protected static final int CATEGORY_MIN = -3;
+    protected static final int CATEGORY_EVERYTHING_ELSE = -2;
+    protected static final int CATEGORY_ONGOING = -1;
+    protected static final int CATEGORY_SYSTEM_LOW = 0;
+    protected static final int CATEGORY_EVENT = 1;
+    protected static final int CATEGORY_REMINDER = 2;
+    protected static final int CATEGORY_SYSTEM = 3;
+    protected static final int CATEGORY_PEOPLE = 4;
+    protected static final int CATEGORY_ALARM = 5;
+    protected static final int CATEGORY_CALL = 6;
+
+    /** @hide */
+    @IntDef(prefix = { "CATEGORY_" }, value = {
+            CATEGORY_MIN, CATEGORY_EVERYTHING_ELSE, CATEGORY_ONGOING, CATEGORY_CALL,
+            CATEGORY_SYSTEM_LOW, CATEGORY_EVENT, CATEGORY_REMINDER, CATEGORY_SYSTEM,
+            CATEGORY_PEOPLE, CATEGORY_ALARM
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Category {}
+
+    public boolean shouldSilence(NotificationEntry entry) {
+        return shouldSilence(getCategory(entry));
+    }
+
+    @VisibleForTesting
+    boolean shouldSilence(int category) {
+        return category < CATEGORY_EVENT;
+    }
+
+    public int getCategory(NotificationEntry entry) {
+        if (entry.getChannel() == null) {
+            return CATEGORY_EVERYTHING_ELSE;
+        }
+        if (entry.getChannel().getImportance() == IMPORTANCE_MIN) {
+            return CATEGORY_MIN;
+        }
+        if (entry.isCategory(Notification.CATEGORY_REMINDER)) {
+            return CATEGORY_REMINDER;
+        }
+        if (entry.isCategory(Notification.CATEGORY_EVENT)) {
+            return CATEGORY_EVENT;
+        }
+        if (entry.isCategory(Notification.CATEGORY_ALARM)
+                || entry.isAudioAttributesUsage(AudioAttributes.USAGE_ALARM)) {
+            return CATEGORY_ALARM;
+        }
+        // TODO: check for default phone app
+        if (entry.isCategory(Notification.CATEGORY_CALL)) {
+            return CATEGORY_CALL;
+        }
+        if (entry.involvesPeople()) {
+            return CATEGORY_PEOPLE;
+        }
+        // TODO: is from signature app
+        if (entry.getSbn().getUid() < Process.FIRST_APPLICATION_UID) {
+            if (entry.getImportance() >= IMPORTANCE_HIGH) {
+                return CATEGORY_SYSTEM;
+            } else {
+                return CATEGORY_SYSTEM_LOW;
+            }
+        }
+        if (entry.isOngoing()) {
+            return CATEGORY_ONGOING;
+        }
+        return CATEGORY_EVERYTHING_ELSE;
+    }
+}
diff --git a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
new file mode 100644
index 0000000..8fee822
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.ext.services.notification;
+
+import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.Person;
+import android.app.RemoteInput;
+import android.content.pm.IPackageManager;
+import android.media.AudioAttributes;
+import android.media.AudioSystem;
+import android.os.Build;
+import android.os.RemoteException;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * Holds data about notifications.
+ */
+public class NotificationEntry {
+    static final String TAG = "NotificationEntry";
+
+    private StatusBarNotification mSbn;
+    private final IPackageManager mPackageManager;
+    private int mTargetSdkVersion = Build.VERSION_CODES.N_MR1;
+    private boolean mPreChannelsNotification = true;
+    private AudioAttributes mAttributes;
+    private NotificationChannel mChannel;
+    private int mImportance;
+    private boolean mSeen;
+
+    public NotificationEntry(IPackageManager packageManager, StatusBarNotification sbn,
+            NotificationChannel channel) {
+        mSbn = sbn;
+        mChannel = channel;
+        mPackageManager = packageManager;
+        mPreChannelsNotification = isPreChannelsNotification();
+        mAttributes = calculateAudioAttributes();
+        mImportance = calculateInitialImportance();
+    }
+
+    private boolean isPreChannelsNotification() {
+        try {
+            mTargetSdkVersion = mPackageManager.getApplicationInfo(
+                    mSbn.getPackageName(), 0, mSbn.getUserId()).targetSdkVersion;
+        } catch (RemoteException e) {
+            Log.w(TAG, "Couldn't look up " + mSbn.getPackageName());
+        }
+        if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(getChannel().getId())) {
+            if (mTargetSdkVersion < Build.VERSION_CODES.O) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private AudioAttributes calculateAudioAttributes() {
+        final Notification n = getNotification();
+        AudioAttributes attributes = getChannel().getAudioAttributes();
+        if (attributes == null) {
+            attributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
+        }
+
+        if (mPreChannelsNotification
+                && (getChannel().getUserLockedFields()
+                & NotificationChannel.USER_LOCKED_SOUND) == 0) {
+            if (n.audioAttributes != null) {
+                // prefer audio attributes to stream type
+                attributes = n.audioAttributes;
+            } else if (n.audioStreamType >= 0
+                    && n.audioStreamType < AudioSystem.getNumStreamTypes()) {
+                // the stream type is valid, use it
+                attributes = new AudioAttributes.Builder()
+                        .setInternalLegacyStreamType(n.audioStreamType)
+                        .build();
+            } else if (n.audioStreamType != AudioSystem.STREAM_DEFAULT) {
+                Log.w(TAG, String.format("Invalid stream type: %d", n.audioStreamType));
+            }
+        }
+        return attributes;
+    }
+
+    private int calculateInitialImportance() {
+        final Notification n = getNotification();
+        int importance = getChannel().getImportance();
+        int requestedImportance = IMPORTANCE_DEFAULT;
+
+        // Migrate notification flags to scores
+        if ((n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) {
+            n.priority = Notification.PRIORITY_MAX;
+        }
+
+        n.priority = clamp(n.priority, Notification.PRIORITY_MIN,
+                Notification.PRIORITY_MAX);
+        switch (n.priority) {
+            case Notification.PRIORITY_MIN:
+                requestedImportance = IMPORTANCE_MIN;
+                break;
+            case Notification.PRIORITY_LOW:
+                requestedImportance = IMPORTANCE_LOW;
+                break;
+            case Notification.PRIORITY_DEFAULT:
+                requestedImportance = IMPORTANCE_DEFAULT;
+                break;
+            case Notification.PRIORITY_HIGH:
+            case Notification.PRIORITY_MAX:
+                requestedImportance = IMPORTANCE_HIGH;
+                break;
+        }
+
+        if (mPreChannelsNotification
+                && (importance == IMPORTANCE_UNSPECIFIED
+                || (getChannel().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) == 0)) {
+            if (n.fullScreenIntent != null) {
+                requestedImportance = IMPORTANCE_HIGH;
+            }
+            importance = requestedImportance;
+        }
+
+        return importance;
+    }
+
+    public boolean isCategory(String category) {
+        return Objects.equals(getNotification().category, category);
+    }
+
+    public boolean isAudioAttributesUsage(int usage) {
+        return mAttributes != null && mAttributes.getUsage() == usage;
+    }
+
+    private boolean hasPerson() {
+        // TODO: cache favorite and recent contacts to check contact affinity
+        ArrayList<Person> people = getNotification().extras.getParcelableArrayList(
+                Notification.EXTRA_PEOPLE_LIST);
+        return people != null && !people.isEmpty();
+    }
+
+    protected boolean hasStyle(Class targetStyle) {
+        Class<? extends Notification.Style> style = getNotification().getNotificationStyle();
+        return targetStyle.equals(style);
+    }
+
+    protected boolean isOngoing() {
+        return (getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
+    }
+
+    protected boolean involvesPeople() {
+        return isMessaging()
+                || hasStyle(Notification.InboxStyle.class)
+                || hasPerson();
+    }
+
+    protected boolean isMessaging() {
+        return isCategory(Notification.CATEGORY_MESSAGE)
+                || hasStyle(Notification.MessagingStyle.class)
+                || hasInlineReply();
+    }
+
+    public boolean hasInlineReply() {
+        Notification.Action[] actions = getNotification().actions;
+        if (actions == null) {
+            return false;
+        }
+        for (Notification.Action action : actions) {
+            RemoteInput[] remoteInputs = action.getRemoteInputs();
+            if (remoteInputs == null) {
+                continue;
+            }
+            for (RemoteInput remoteInput : remoteInputs) {
+                if (remoteInput.getAllowFreeFormInput()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public void setSeen() {
+        mSeen = true;
+    }
+
+    public boolean hasSeen() {
+        return mSeen;
+    }
+
+    public StatusBarNotification getSbn() {
+        return mSbn;
+    }
+
+    public Notification getNotification() {
+        return getSbn().getNotification();
+    }
+
+    public NotificationChannel getChannel() {
+        return mChannel;
+    }
+
+    public int getImportance() {
+        return mImportance;
+    }
+
+    private int clamp(int x, int low, int high) {
+        return (x < low) ? low : ((x > high) ? high : x);
+    }
+}
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
new file mode 100644
index 0000000..37a98fd
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -0,0 +1,234 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.ext.services.notification;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.RemoteAction;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.Process;
+import android.os.SystemProperties;
+import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassificationManager;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextLinks;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+public class SmartActionsHelper {
+    private static final ArrayList<Notification.Action> EMPTY_ACTION_LIST = new ArrayList<>();
+    private static final ArrayList<CharSequence> EMPTY_REPLY_LIST = new ArrayList<>();
+
+    // If a notification has any of these flags set, it's inelgibile for actions being added.
+    private static final int FLAG_MASK_INELGIBILE_FOR_ACTIONS =
+            Notification.FLAG_ONGOING_EVENT
+                    | Notification.FLAG_FOREGROUND_SERVICE
+                    | Notification.FLAG_GROUP_SUMMARY
+                    | Notification.FLAG_NO_CLEAR;
+    private static final int MAX_ACTION_EXTRACTION_TEXT_LENGTH = 400;
+    private static final int MAX_ACTIONS_PER_LINK = 1;
+    private static final int MAX_SMART_ACTIONS = Notification.MAX_ACTION_BUTTONS;
+    // Allow us to test out smart reply with dumb suggestions, it is disabled by default.
+    // TODO: Removed this once we have the model.
+    private static final String SYS_PROP_SMART_REPLIES_EXPERIMENT =
+            "persist.sys.smart_replies_experiment";
+
+    SmartActionsHelper() {}
+
+    /**
+     * Adds action adjustments based on the notification contents.
+     *
+     * TODO: Once we have a API in {@link TextClassificationManager} to predict smart actions
+     * from notification text / message, we can replace most of the code here by consuming that API.
+     */
+    @NonNull
+    ArrayList<Notification.Action> suggestActions(
+            @Nullable Context context, @NonNull NotificationEntry entry) {
+        if (!isEligibleForActionAdjustment(entry)) {
+            return EMPTY_ACTION_LIST;
+        }
+        if (context == null) {
+            return EMPTY_ACTION_LIST;
+        }
+        TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class);
+        if (tcm == null) {
+            return EMPTY_ACTION_LIST;
+        }
+        Notification.Action[] actions = entry.getNotification().actions;
+        int numOfExistingActions = actions == null ? 0: actions.length;
+        int maxSmartActions = MAX_SMART_ACTIONS - numOfExistingActions;
+        return suggestActionsFromText(
+                tcm,
+                getMostSalientActionText(entry.getNotification()), maxSmartActions);
+    }
+
+    ArrayList<CharSequence> suggestReplies(
+            @Nullable Context context, @NonNull NotificationEntry entry) {
+        if (!isEligibleForReplyAdjustment(entry)) {
+            return EMPTY_REPLY_LIST;
+        }
+        if (context == null) {
+            return EMPTY_REPLY_LIST;
+        }
+        // TODO: replaced this with our model when it is ready.
+        return new ArrayList<>(Arrays.asList("Yes, please", "No, thanks"));
+    }
+
+    /**
+     * Returns whether a notification is eligible for action adjustments.
+     *
+     * <p>We exclude system notifications, those that get refreshed frequently, or ones that relate
+     * to fundamental phone functionality where any error would result in a very negative user
+     * experience.
+     */
+    private boolean isEligibleForActionAdjustment(@NonNull NotificationEntry entry) {
+        Notification notification = entry.getNotification();
+        String pkg = entry.getSbn().getPackageName();
+        if (!Process.myUserHandle().equals(entry.getSbn().getUser())) {
+            return false;
+        }
+        if (notification.actions != null
+                && notification.actions.length >= Notification.MAX_ACTION_BUTTONS) {
+            return false;
+        }
+        if ((notification.flags & FLAG_MASK_INELGIBILE_FOR_ACTIONS) != 0) {
+            return false;
+        }
+        if (TextUtils.isEmpty(pkg) || pkg.equals("android")) {
+            return false;
+        }
+        // For now, we are only interested in messages.
+        return entry.isMessaging();
+    }
+
+    private boolean isEligibleForReplyAdjustment(@NonNull NotificationEntry entry) {
+        if (!SystemProperties.getBoolean(SYS_PROP_SMART_REPLIES_EXPERIMENT, false)) {
+            return false;
+        }
+        Notification notification = entry.getNotification();
+        if (notification.actions == null) {
+            return false;
+        }
+        return entry.hasInlineReply();
+    }
+
+    /** Returns the text most salient for action extraction in a notification. */
+    @Nullable
+    private CharSequence getMostSalientActionText(@NonNull Notification notification) {
+        /* If it's messaging style, use the most recent message. */
+        Parcelable[] messages = notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES);
+        if (messages != null && messages.length != 0) {
+            Bundle lastMessage = (Bundle) messages[messages.length - 1];
+            CharSequence lastMessageText =
+                    lastMessage.getCharSequence(Notification.MessagingStyle.Message.KEY_TEXT);
+            if (!TextUtils.isEmpty(lastMessageText)) {
+                return lastMessageText;
+            }
+        }
+
+        // Fall back to using the normal text.
+        return notification.extras.getCharSequence(Notification.EXTRA_TEXT);
+    }
+
+    /** Returns a list of actions to act on entities in a given piece of text. */
+    @NonNull
+    private ArrayList<Notification.Action> suggestActionsFromText(
+            @NonNull TextClassificationManager tcm, @Nullable CharSequence text,
+            int maxSmartActions) {
+        if (TextUtils.isEmpty(text)) {
+            return EMPTY_ACTION_LIST;
+        }
+        TextClassifier textClassifier = tcm.getTextClassifier();
+
+        // We want to process only text visible to the user to avoid confusing suggestions, so we
+        // truncate the text to a reasonable length. This is particularly important for e.g.
+        // email apps that sometimes include the text for the entire thread.
+        text = text.subSequence(0, Math.min(text.length(), MAX_ACTION_EXTRACTION_TEXT_LENGTH));
+
+        // Extract all entities.
+        TextLinks.Request textLinksRequest = new TextLinks.Request.Builder(text)
+                .setEntityConfig(
+                        TextClassifier.EntityConfig.createWithHints(
+                                Collections.singletonList(
+                                        TextClassifier.HINT_TEXT_IS_NOT_EDITABLE)))
+                .build();
+        TextLinks links = textClassifier.generateLinks(textLinksRequest);
+        ArrayMap<String, Integer> entityTypeFrequency = getEntityTypeFrequency(links);
+
+        ArrayList<Notification.Action> actions = new ArrayList<>();
+        for (TextLinks.TextLink link : links.getLinks()) {
+            // Ignore any entity type for which we have too many entities. This is to handle the
+            // case where a notification contains e.g. a list of phone numbers. In such cases, the
+            // user likely wants to act on the whole list rather than an individual entity.
+            if (link.getEntityCount() == 0
+                    || entityTypeFrequency.get(link.getEntity(0)) != 1) {
+                continue;
+            }
+
+            // Generate the actions, and add the most prominent ones to the action bar.
+            TextClassification classification =
+                    textClassifier.classifyText(
+                            new TextClassification.Request.Builder(
+                                    text, link.getStart(), link.getEnd()).build());
+            int numOfActions = Math.min(
+                    MAX_ACTIONS_PER_LINK, classification.getActions().size());
+            for (int i = 0; i < numOfActions; ++i) {
+                RemoteAction action = classification.getActions().get(i);
+                actions.add(
+                        new Notification.Action.Builder(
+                                action.getIcon(),
+                                action.getTitle(),
+                                action.getActionIntent())
+                                .build());
+                // We have enough smart actions.
+                if (actions.size() >= maxSmartActions) {
+                    return actions;
+                }
+            }
+        }
+        return actions;
+    }
+
+    /**
+     * Given the links extracted from a piece of text, returns the frequency of each entity
+     * type.
+     */
+    @NonNull
+    private ArrayMap<String, Integer> getEntityTypeFrequency(@NonNull TextLinks links) {
+        ArrayMap<String, Integer> entityTypeCount = new ArrayMap<>();
+        for (TextLinks.TextLink link : links.getLinks()) {
+            if (link.getEntityCount() == 0) {
+                continue;
+            }
+            String entityType = link.getEntity(0);
+            if (entityTypeCount.containsKey(entityType)) {
+                entityTypeCount.put(entityType, entityTypeCount.get(entityType) + 1);
+            } else {
+                entityTypeCount.put(entityType, 1);
+            }
+        }
+        return entityTypeCount;
+    }
+}
diff --git a/packages/ExtServices/tests/AndroidTest.xml b/packages/ExtServices/tests/AndroidTest.xml
new file mode 100644
index 0000000..c3d32de
--- /dev/null
+++ b/packages/ExtServices/tests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs Tests for ExtServices">
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="ExtServicesUnitTests.apk" />
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="framework-base-presubmit" />
+    <option name="test-tag" value="ExtServicesUnitTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.ext.services.tests.unit" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java
new file mode 100644
index 0000000..b023b36
--- /dev/null
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java
@@ -0,0 +1,153 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.ext.services.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.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;
+
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.PendingIntent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.os.Build;
+import android.os.Process;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.testing.TestableContext;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class AgingHelperTest {
+    private String mPkg = "pkg";
+    private int mUid = 2018;
+
+    @Rule
+    public final TestableContext mContext =
+            new TestableContext(InstrumentationRegistry.getTargetContext(), null);
+
+    @Mock
+    private NotificationCategorizer mCategorizer;
+    @Mock
+    private AlarmManager mAlarmManager;
+    @Mock
+    private IPackageManager mPackageManager;
+    @Mock
+    private AgingHelper.Callback mCallback;
+
+    private AgingHelper mAgingHelper;
+
+    private StatusBarNotification generateSbn(String channelId) {
+        Notification n = new Notification.Builder(mContext, channelId)
+                .setContentTitle("foo")
+                .build();
+
+        return new StatusBarNotification(mPkg, mPkg, 0, "tag", mUid, mUid, n,
+                UserHandle.SYSTEM, null, 0);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mPkg = mContext.getPackageName();
+        mUid = Process.myUid();
+
+        ApplicationInfo info = mock(ApplicationInfo.class);
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
+                .thenReturn(info);
+        info.targetSdkVersion = Build.VERSION_CODES.P;
+
+        mContext.addMockSystemService(AlarmManager.class, mAlarmManager);
+
+        mAgingHelper = new AgingHelper(mContext, mCategorizer, mCallback);
+    }
+
+    @Test
+    public void testNoSnoozingOnPost() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        StatusBarNotification sbn = generateSbn(channel.getId());
+        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel);
+
+
+        mAgingHelper.onNotificationPosted(entry);
+        verify(mAlarmManager, never()).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
+    }
+
+    @Test
+    public void testPostResetsSnooze() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        StatusBarNotification sbn = generateSbn(channel.getId());
+        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel);
+
+
+        mAgingHelper.onNotificationPosted(entry);
+        verify(mAlarmManager, times(1)).cancel(any(PendingIntent.class));
+    }
+
+    @Test
+    public void testSnoozingOnSeen() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        StatusBarNotification sbn = generateSbn(channel.getId());
+        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel);
+        entry.setSeen();
+        when(mCategorizer.getCategory(entry)).thenReturn(NotificationCategorizer.CATEGORY_PEOPLE);
+
+        mAgingHelper.onNotificationSeen(entry);
+        verify(mAlarmManager, times(1)).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
+    }
+
+    @Test
+    public void testNoSnoozingOnSeenUserLocked() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+        StatusBarNotification sbn = generateSbn(channel.getId());
+        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel);
+        when(mCategorizer.getCategory(entry)).thenReturn(NotificationCategorizer.CATEGORY_PEOPLE);
+
+        mAgingHelper.onNotificationSeen(entry);
+        verify(mAlarmManager, never()).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
+    }
+
+    @Test
+    public void testNoSnoozingOnSeenAlreadyLow() {
+        NotificationEntry entry = mock(NotificationEntry.class);
+        when(entry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_HIGH));
+        when(entry.getImportance()).thenReturn(IMPORTANCE_MIN);
+
+        mAgingHelper.onNotificationSeen(entry);
+        verify(mAlarmManager, never()).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
+    }
+}
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
index a6b6a6b..2820232 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
@@ -20,8 +20,9 @@
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 
-import static junit.framework.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -33,8 +34,10 @@
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.content.ContentResolver;
-import android.content.IContentProvider;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.os.Build;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.Adjustment;
@@ -47,7 +50,6 @@
 import android.test.ServiceTestCase;
 import android.testing.TestableContext;
 import android.util.AtomicFile;
-import android.util.Xml;
 
 import com.android.internal.util.FastXmlSerializer;
 
@@ -57,7 +59,6 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
 
 import java.io.BufferedInputStream;
@@ -84,6 +85,8 @@
 
     @Mock INotificationManager mNoMan;
     @Mock AtomicFile mFile;
+    @Mock
+    IPackageManager mPackageManager;
 
     Assistant mAssistant;
     Application mApplication;
@@ -117,6 +120,11 @@
         mAssistant = getService();
         mAssistant.setNoMan(mNoMan);
         mAssistant.setFile(mFile);
+        mAssistant.setPackageManager(mPackageManager);
+        ApplicationInfo info = mock(ApplicationInfo.class);
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
+                .thenReturn(info);
+        info.targetSdkVersion = Build.VERSION_CODES.P;
         when(mFile.startWrite()).thenReturn(mock(FileOutputStream.class));
     }
 
@@ -435,14 +443,27 @@
                 Settings.Global.BLOCKING_HELPER_STREAK_LIMIT, newStreakLimit);
 
         // Notify for the settings values we updated.
-        resolver.notifyChange(
-                Settings.Global.getUriFor(Settings.Global.BLOCKING_HELPER_STREAK_LIMIT), null);
-        resolver.notifyChange(
-                Settings.Global.getUriFor(
-                        Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT),
-                null);
+        mAssistant.mSettingsObserver.onChange(false, Settings.Global.getUriFor(
+                Settings.Global.BLOCKING_HELPER_STREAK_LIMIT));
+        mAssistant.mSettingsObserver.onChange(false, Settings.Global.getUriFor(
+                Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT));
 
         // With the new threshold, the blocking helper should be triggered.
         assertEquals(true, ci.shouldTriggerBlock());
     }
+
+    @Test
+    public void testTrimLiveNotifications() {
+        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", null);
+        mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
+
+        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
+
+        assertTrue(mAssistant.mLiveNotifications.containsKey(sbn.getKey()));
+
+        mAssistant.onNotificationRemoved(
+                sbn, mock(RankingMap.class), new NotificationStats(), 0);
+
+        assertFalse(mAssistant.mLiveNotifications.containsKey(sbn.getKey()));
+    }
 }
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/NotificationCategorizerTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationCategorizerTest.java
new file mode 100644
index 0000000..c37392f
--- /dev/null
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationCategorizerTest.java
@@ -0,0 +1,190 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.ext.services.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.os.Process.FIRST_APPLICATION_UID;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.os.Process;
+import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.testing.TestableContext;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class NotificationCategorizerTest {
+    @Mock
+    private NotificationEntry mEntry;
+    @Mock
+    private StatusBarNotification mSbn;
+
+    @Rule
+    public final TestableContext mContext =
+            new TestableContext(InstrumentationRegistry.getContext(), null);
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mEntry.getSbn()).thenReturn(mSbn);
+        when(mSbn.getUid()).thenReturn(Process.myUid());
+        when(mSbn.getPackageName()).thenReturn(mContext.getPackageName());
+    }
+
+    @Test
+    public void testPeopleCategory() {
+        NotificationCategorizer nc = new NotificationCategorizer();
+
+        when(mEntry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_DEFAULT));
+        when(mEntry.involvesPeople()).thenReturn(true);
+
+        assertEquals(NotificationCategorizer.CATEGORY_PEOPLE, nc.getCategory(mEntry));
+        assertFalse(nc.shouldSilence(NotificationCategorizer.CATEGORY_PEOPLE));
+    }
+
+    @Test
+    public void testMin() {
+        NotificationCategorizer nc = new NotificationCategorizer();
+
+        when(mEntry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_MIN));
+        when(mEntry.involvesPeople()).thenReturn(true);
+
+        assertEquals(NotificationCategorizer.CATEGORY_MIN, nc.getCategory(mEntry));
+        assertTrue(nc.shouldSilence(NotificationCategorizer.CATEGORY_MIN));
+    }
+
+    @Test
+    public void testOngoingCategory() {
+        NotificationCategorizer nc = new NotificationCategorizer();
+
+        when(mEntry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_DEFAULT));
+        when(mEntry.isOngoing()).thenReturn(true);
+
+        assertEquals(NotificationCategorizer.CATEGORY_ONGOING, nc.getCategory(mEntry));
+        assertTrue(nc.shouldSilence(NotificationCategorizer.CATEGORY_ONGOING));
+
+        when(mEntry.isOngoing()).thenReturn(false);
+        assertEquals(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE, nc.getCategory(mEntry));
+        assertTrue(nc.shouldSilence(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE));
+    }
+
+    @Test
+    public void testAlarmCategory() {
+        NotificationCategorizer nc = new NotificationCategorizer();
+
+        when(mEntry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_DEFAULT));
+        when(mEntry.isCategory(Notification.CATEGORY_ALARM)).thenReturn(true);
+
+        assertEquals(NotificationCategorizer.CATEGORY_ALARM, nc.getCategory(mEntry));
+        assertFalse(nc.shouldSilence(NotificationCategorizer.CATEGORY_ALARM));
+
+        when(mEntry.isCategory(Notification.CATEGORY_ALARM)).thenReturn(false);
+        assertEquals(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE, nc.getCategory(mEntry));
+        assertTrue(nc.shouldSilence(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE));
+    }
+
+    @Test
+    public void testCallCategory() {
+        NotificationCategorizer nc = new NotificationCategorizer();
+
+        when(mEntry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_DEFAULT));
+        when(mEntry.isCategory(Notification.CATEGORY_CALL)).thenReturn(true);
+
+        assertEquals(NotificationCategorizer.CATEGORY_CALL, nc.getCategory(mEntry));
+        assertFalse(nc.shouldSilence(NotificationCategorizer.CATEGORY_CALL));
+
+        when(mEntry.isCategory(Notification.CATEGORY_CALL)).thenReturn(false);
+        assertEquals(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE, nc.getCategory(mEntry));
+        assertTrue(nc.shouldSilence(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE));
+    }
+
+    @Test
+    public void testReminderCategory() {
+        NotificationCategorizer nc = new NotificationCategorizer();
+
+        when(mEntry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_DEFAULT));
+        when(mEntry.isCategory(Notification.CATEGORY_REMINDER)).thenReturn(true);
+
+        assertEquals(NotificationCategorizer.CATEGORY_REMINDER, nc.getCategory(mEntry));
+        assertFalse(nc.shouldSilence(NotificationCategorizer.CATEGORY_REMINDER));
+
+        when(mEntry.isCategory(Notification.CATEGORY_REMINDER)).thenReturn(false);
+        assertEquals(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE, nc.getCategory(mEntry));
+        assertTrue(nc.shouldSilence(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE));
+    }
+
+    @Test
+    public void testEventCategory() {
+        NotificationCategorizer nc = new NotificationCategorizer();
+
+        when(mEntry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_DEFAULT));
+        when(mEntry.isCategory(Notification.CATEGORY_EVENT)).thenReturn(true);
+
+        assertEquals(NotificationCategorizer.CATEGORY_EVENT, nc.getCategory(mEntry));
+        assertFalse(nc.shouldSilence(NotificationCategorizer.CATEGORY_EVENT));
+
+        when(mEntry.isCategory(Notification.CATEGORY_EVENT)).thenReturn(false);
+        assertEquals(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE, nc.getCategory(mEntry));
+    }
+
+    @Test
+    public void testSystemCategory() {
+        NotificationCategorizer nc = new NotificationCategorizer();
+
+        when(mEntry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_HIGH));
+        when(mEntry.getImportance()).thenReturn(IMPORTANCE_HIGH);
+        when(mSbn.getUid()).thenReturn(FIRST_APPLICATION_UID - 1);
+
+        assertEquals(NotificationCategorizer.CATEGORY_SYSTEM, nc.getCategory(mEntry));
+        assertFalse(nc.shouldSilence(NotificationCategorizer.CATEGORY_SYSTEM));
+
+        when(mSbn.getUid()).thenReturn(FIRST_APPLICATION_UID);
+        assertEquals(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE, nc.getCategory(mEntry));
+    }
+
+    @Test
+    public void testSystemLowCategory() {
+        NotificationCategorizer nc = new NotificationCategorizer();
+
+        when(mEntry.getChannel()).thenReturn(new NotificationChannel("", "", IMPORTANCE_DEFAULT));
+        when(mEntry.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
+        when(mSbn.getUid()).thenReturn(FIRST_APPLICATION_UID - 1);
+
+        assertEquals(NotificationCategorizer.CATEGORY_SYSTEM_LOW, nc.getCategory(mEntry));
+        assertTrue(nc.shouldSilence(NotificationCategorizer.CATEGORY_SYSTEM_LOW));
+
+        when(mSbn.getUid()).thenReturn(FIRST_APPLICATION_UID);
+        assertEquals(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE, nc.getCategory(mEntry));
+    }
+}
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java
new file mode 100644
index 0000000..9223c3d
--- /dev/null
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java
@@ -0,0 +1,201 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.ext.services.notification;
+
+import static android.app.Notification.FLAG_CAN_COLORIZE;
+import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.media.AudioAttributes.USAGE_ALARM;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.Person;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.media.AudioAttributes;
+import android.os.Build;
+import android.os.Process;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.testing.TestableContext;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+public class NotificationEntryTest {
+    private String mPkg = "pkg";
+    private int mUid = 2018;
+    @Mock
+    private IPackageManager mPackageManager;
+    @Mock
+    private ApplicationInfo mAppInfo;
+
+    @Rule
+    public final TestableContext mContext =
+            new TestableContext(InstrumentationRegistry.getContext(), null);
+
+    private StatusBarNotification generateSbn(String channelId) {
+        Notification n = new Notification.Builder(mContext, channelId)
+                .setContentTitle("foo")
+                .build();
+
+        return new StatusBarNotification(mPkg, mPkg, 0, "tag", mUid, mUid, n,
+                UserHandle.SYSTEM, null, 0);
+    }
+
+    private StatusBarNotification generateSbn(Notification n) {
+        return new StatusBarNotification(mPkg, mPkg, 0, "tag", mUid, mUid, n,
+                UserHandle.SYSTEM, null, 0);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mPkg = mContext.getPackageName();
+        mUid = Process.myUid();
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
+                .thenReturn(mAppInfo);
+        mAppInfo.targetSdkVersion = Build.VERSION_CODES.P;
+    }
+
+    @Test
+    public void testHasPerson() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        StatusBarNotification sbn = generateSbn(channel.getId());
+        ArrayList<Person> people = new ArrayList<>();
+        people.add(new Person.Builder().setKey("mailto:testing@android.com").build());
+        sbn.getNotification().extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, people);
+
+        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel);
+        assertTrue(entry.involvesPeople());
+    }
+
+    @Test
+    public void testNotPerson() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        StatusBarNotification sbn = generateSbn(channel.getId());
+        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel);
+        assertFalse(entry.involvesPeople());
+    }
+
+    @Test
+    public void testIsInboxStyle() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+
+        Notification n = new Notification.Builder(mContext, channel.getId())
+                .setStyle(new Notification.InboxStyle())
+                .build();
+        NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel);
+        assertTrue(entry.hasStyle(Notification.InboxStyle.class));
+    }
+
+    @Test
+    public void testIsMessagingStyle() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+
+        Notification n = new Notification.Builder(mContext, channel.getId())
+                .setStyle(new Notification.MessagingStyle(""))
+                .build();
+        NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel);
+        assertTrue(entry.hasStyle(Notification.MessagingStyle.class));
+    }
+
+    @Test
+    public void testIsNotPersonStyle() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+
+        Notification n = new Notification.Builder(mContext, channel.getId())
+                .setStyle(new Notification.BigPictureStyle())
+                .build();
+        NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel);
+        assertFalse(entry.hasStyle(Notification.InboxStyle.class));
+        assertFalse(entry.hasStyle(Notification.MessagingStyle.class));
+    }
+
+    @Test
+    public void testIsAudioAttributes() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        channel.setSound(null, new AudioAttributes.Builder().setUsage(USAGE_ALARM).build());
+
+        NotificationEntry entry = new NotificationEntry(
+                mPackageManager, generateSbn(channel.getId()), channel);
+
+        assertTrue(entry.isAudioAttributesUsage(USAGE_ALARM));
+    }
+
+    @Test
+    public void testIsNotAudioAttributes() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+        NotificationEntry entry = new NotificationEntry(
+                mPackageManager, generateSbn(channel.getId()), channel);
+
+        assertFalse(entry.isAudioAttributesUsage(USAGE_ALARM));
+    }
+
+    @Test
+    public void testIsCategory() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+
+        Notification n = new Notification.Builder(mContext, channel.getId())
+                .setCategory(Notification.CATEGORY_EMAIL)
+                .build();
+        NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel);
+
+        assertTrue(entry.isCategory(Notification.CATEGORY_EMAIL));
+        assertFalse(entry.isCategory(Notification.CATEGORY_MESSAGE));
+    }
+
+    @Test
+    public void testIsOngoing() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+
+        Notification n = new Notification.Builder(mContext, channel.getId())
+                .setFlag(FLAG_FOREGROUND_SERVICE, true)
+                .build();
+        NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel);
+
+        assertTrue(entry.isOngoing());
+    }
+
+    @Test
+    public void testIsNotOngoing() {
+        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+
+        Notification n = new Notification.Builder(mContext, channel.getId())
+                .setFlag(FLAG_CAN_COLORIZE, true)
+                .build();
+        NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel);
+
+        assertFalse(entry.isOngoing());
+    }
+}
diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml
index a17f058..cde66e7 100644
--- a/packages/InputDevices/res/values-es/strings.xml
+++ b/packages/InputDevices/res/values-es/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="8016145283189546017">"Dispositivos de entrada"</string>
+    <string name="app_label" msgid="8016145283189546017">"Dispositivos de introducción de datos"</string>
     <string name="keyboard_layouts_label" msgid="6688773268302087545">"Teclado de Android"</string>
     <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"Inglés (Reino Unido)"</string>
     <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"Inglés (EE.UU.)"</string>
diff --git a/packages/OsuLogin/Android.mk b/packages/OsuLogin/Android.mk
new file mode 100644
index 0000000..f04227b
--- /dev/null
+++ b/packages/OsuLogin/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_USE_AAPT2 := true
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := OsuLogin
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/packages/OsuLogin/AndroidManifest.xml b/packages/OsuLogin/AndroidManifest.xml
new file mode 100644
index 0000000..bc32d10
--- /dev/null
+++ b/packages/OsuLogin/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.hotspot2">
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application
+        android:networkSecurityConfig="@xml/network_security_config"
+        android:enabled="true"
+        android:label="@string/app_name"
+        android:configChanges="keyboardHidden|orientation|screenSize"
+        android:supportsRtl="true">
+        <activity android:name="com.android.hotspot2.osu.OsuLoginActivity">
+            <intent-filter>
+                <action android:name="android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/packages/OsuLogin/OWNERS b/packages/OsuLogin/OWNERS
new file mode 100644
index 0000000..aa7c3e6
--- /dev/null
+++ b/packages/OsuLogin/OWNERS
@@ -0,0 +1,2 @@
+satk@google.com
+etancohen@google.com
diff --git a/packages/OsuLogin/res/layout/osu_web_view.xml b/packages/OsuLogin/res/layout/osu_web_view.xml
new file mode 100644
index 0000000..4eafb39
--- /dev/null
+++ b/packages/OsuLogin/res/layout/osu_web_view.xml
@@ -0,0 +1,13 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <WebView
+        android:id="@+id/webview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentRight="true" />
+
+</FrameLayout>
diff --git a/packages/OsuLogin/res/values/dimens.xml b/packages/OsuLogin/res/values/dimens.xml
new file mode 100644
index 0000000..47c8224
--- /dev/null
+++ b/packages/OsuLogin/res/values/dimens.xml
@@ -0,0 +1,5 @@
+<resources>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/packages/OsuLogin/res/values/strings.xml b/packages/OsuLogin/res/values/strings.xml
new file mode 100644
index 0000000..9fafeef
--- /dev/null
+++ b/packages/OsuLogin/res/values/strings.xml
@@ -0,0 +1,4 @@
+<resources>
+    <!-- application name [CHAR LIMIT=32] -->
+    <string name="app_name">OsuLogin</string>
+</resources>
diff --git a/packages/OsuLogin/res/values/styles.xml b/packages/OsuLogin/res/values/styles.xml
new file mode 100644
index 0000000..f6c2339
--- /dev/null
+++ b/packages/OsuLogin/res/values/styles.xml
@@ -0,0 +1,19 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="@android:style/Theme.DeviceDefault.Settings">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+</resources>
diff --git a/packages/OsuLogin/res/xml/network_security_config.xml b/packages/OsuLogin/res/xml/network_security_config.xml
new file mode 100644
index 0000000..3ef4b84
--- /dev/null
+++ b/packages/OsuLogin/res/xml/network_security_config.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+<base-config cleartextTrafficPermitted="true">
+    <trust-anchors>
+        <certificates src="system" />
+        <certificates src="wfa" />
+    </trust-anchors>
+</base-config>
+</network-security-config>
diff --git a/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java b/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
new file mode 100644
index 0000000..6a48904
--- /dev/null
+++ b/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.hotspot2.osu;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.webkit.WebResourceError;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import com.android.hotspot2.R;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Online Sign Up Login Web View launched during Provision Process of Hotspot 2.0 rel2.
+ */
+public class OsuLoginActivity extends Activity {
+    private static final String TAG = "OsuLogin";
+    private static final boolean DBG = true;
+
+    private String mUrl;
+    private String mHostName;
+    private Network mNetwork;
+    private ConnectivityManager mCm;
+    private ConnectivityManager.NetworkCallback mNetworkCallback;
+    private WifiManager mWifiManager;
+    private WebView mWebView;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (DBG) {
+            Log.d(TAG, "onCreate: Opening OSU Web View");
+        }
+
+        mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+        if (mWifiManager == null) {
+            Log.e(TAG, "Cannot get wifi service");
+            finishAndRemoveTask();
+            return;
+        }
+
+        if (getIntent() == null) {
+            Log.e(TAG, "Intent is null");
+            finishAndRemoveTask();
+            return;
+        }
+
+        mNetwork = getIntent().getParcelableExtra(WifiManager.EXTRA_OSU_NETWORK);
+        if (mNetwork == null) {
+            Log.e(TAG, "Cannot get the network instance for OSU from intent");
+            finishAndRemoveTask();
+            return;
+        }
+
+        mUrl = getIntent().getStringExtra(WifiManager.EXTRA_URL);
+        if (mUrl == null) {
+            Log.e(TAG, "Cannot get OSU server url from intent");
+            finishAndRemoveTask();
+            return;
+        }
+
+        mHostName = getHost(mUrl);
+        if (mHostName == null) {
+            Log.e(TAG, "Cannot get host from the url");
+            finishAndRemoveTask();
+            return;
+        }
+
+        mCm = (ConnectivityManager) getApplicationContext().getSystemService(
+                Context.CONNECTIVITY_SERVICE);
+        if (mCm == null) {
+            Log.e(TAG, "Cannot get connectivity service");
+            finishAndRemoveTask();
+            return;
+        }
+
+        if (!mCm.bindProcessToNetwork(mNetwork)) {
+            Log.e(TAG, "Network is no longer valid");
+            finishAndRemoveTask();
+            return;
+        }
+
+        final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork);
+        if (networkCapabilities == null || !networkCapabilities.hasTransport(
+                NetworkCapabilities.TRANSPORT_WIFI)) {
+            Log.e(TAG, "WiFi is not supported for the Network");
+            finishAndRemoveTask();
+            return;
+        }
+
+        getActionBar().setDisplayShowHomeEnabled(false);
+        setContentView(R.layout.osu_web_view);
+
+        // Exit this app if network disappeared.
+        mNetworkCallback = new ConnectivityManager.NetworkCallback() {
+            @Override
+            public void onLost(Network network) {
+                if (DBG) {
+                    Log.d(TAG, "Lost for the current Network, close the browser");
+                }
+                if (mNetwork.equals(network)) {
+                    finishAndRemoveTask();
+                }
+            }
+        };
+
+        mCm.registerNetworkCallback(
+                new NetworkRequest.Builder().addTransportType(
+                        NetworkCapabilities.TRANSPORT_WIFI).build(),
+                mNetworkCallback);
+
+        mWebView = findViewById(R.id.webview);
+        mWebView.clearCache(true);
+        WebSettings webSettings = mWebView.getSettings();
+        webSettings.setJavaScriptEnabled(true);
+        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
+        webSettings.setUseWideViewPort(true);
+        webSettings.setLoadWithOverviewMode(true);
+        webSettings.setSupportZoom(true);
+        webSettings.setBuiltInZoomControls(true);
+        webSettings.setDisplayZoomControls(false);
+
+        mWebView.setWebViewClient(new OsuWebViewClient());
+        if (DBG) {
+            Log.d(TAG, "OSU Web View to " + mUrl);
+        }
+        mWebView.loadUrl(mUrl);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        // Check if the key event was the Back button.
+        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
+            // If there is a history to move back
+            if (mWebView.canGoBack()){
+                mWebView.goBack();
+                return true;
+            }
+
+            // In case of back key, it needs to disconnect current connection with OSU AP to
+            // abort current Provisioning flow.
+            if (mWifiManager != null) {
+                mWifiManager.disconnect();
+            }
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mNetworkCallback != null) {
+            mCm.unregisterNetworkCallback(mNetworkCallback);
+        }
+        super.onDestroy();
+    }
+
+    private String getHost(String url) {
+        try {
+            return new URL(url).getHost();
+        } catch (MalformedURLException e) {
+            Log.e(TAG, "Invalid URL " + url);
+        }
+        return null;
+    }
+
+    private class OsuWebViewClient extends WebViewClient {
+        boolean mPageError = false;
+
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            // Do not show the page error on UI.
+            if (mPageError) {
+                finishAndRemoveTask();
+            }
+        }
+
+        @Override
+        public void onReceivedError(WebView view, WebResourceRequest request,
+                WebResourceError error) {
+            if (request.isForMainFrame()) {
+                // This happens right after getting HTTP redirect response from an OSU server
+                // since no more Http request is allowed to send to the OSU server.
+                mPageError = true;
+                Log.e(TAG, "onReceived Error for MainFrame: " + error.getErrorCode());
+            }
+         }
+    }
+}
diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp
new file mode 100644
index 0000000..bc06cab
--- /dev/null
+++ b/packages/PackageInstaller/Android.bp
@@ -0,0 +1,14 @@
+android_app {
+    name: "PackageInstaller",
+
+    srcs: ["src/**/*.java"],
+
+    static_libs: [
+        "androidx.leanback_leanback",
+        "xz-java",
+    ],
+
+    certificate: "platform",
+    privileged: true,
+    platform_apis: true,
+}
\ No newline at end of file
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
new file mode 100644
index 0000000..2be9311
--- /dev/null
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.packageinstaller">
+
+    <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
+    <uses-permission android:name="android.permission.DELETE_PACKAGES" />
+    <uses-permission android:name="android.permission.READ_INSTALL_SESSIONS" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" />
+    <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
+    <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
+    <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+
+    <uses-permission android:name="com.google.android.permission.INSTALL_WEARABLE_PACKAGES" />
+
+    <application android:name=".PackageInstallerApplication"
+            android:label="@string/app_name"
+            android:icon="@drawable/ic_app_icon"
+            android:allowBackup="false"
+            android:theme="@style/Theme.AlertDialogActivity"
+            android:supportsRtl="true"
+            android:defaultToDeviceProtectedStorage="true"
+            android:directBootAware="true">
+
+        <receiver android:name=".TemporaryFileManager"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+
+        <activity android:name=".InstallStart"
+                android:theme="@android:style/Theme.Translucent.NoTitleBar"
+                android:exported="true"
+                android:excludeFromRecents="true">
+            <intent-filter android:priority="1">
+                <action android:name="android.intent.action.VIEW" />
+                <action android:name="android.intent.action.INSTALL_PACKAGE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="file" />
+                <data android:scheme="content" />
+                <data android:mimeType="application/vnd.android.package-archive" />
+            </intent-filter>
+            <intent-filter android:priority="1">
+                <action android:name="android.intent.action.INSTALL_PACKAGE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="file" />
+                <data android:scheme="package" />
+                <data android:scheme="content" />
+            </intent-filter>
+            <intent-filter android:priority="1">
+                <action android:name="android.content.pm.action.CONFIRM_INSTALL" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".InstallStaging"
+                android:exported="false" />
+
+        <activity android:name=".DeleteStagedFileOnResult"
+            android:theme="@android:style/Theme.Translucent.NoTitleBar"
+            android:exported="false" />
+
+        <activity android:name=".PackageInstallerActivity"
+                android:exported="false" />
+
+        <activity android:name=".InstallInstalling"
+                android:theme="@style/Theme.AlertDialogActivity.NoAnimation"
+                android:exported="false" />
+
+        <receiver android:name=".InstallEventReceiver"
+                android:permission="android.permission.INSTALL_PACKAGES"
+                android:exported="true">
+            <intent-filter android:priority="1">
+                <action android:name="com.android.packageinstaller.ACTION_INSTALL_COMMIT" />
+            </intent-filter>
+        </receiver>
+
+        <activity android:name=".InstallSuccess"
+                android:theme="@style/Theme.AlertDialogActivity.NoAnimation"
+                android:exported="false" />
+
+        <activity android:name=".InstallFailed"
+                android:theme="@style/Theme.AlertDialogActivity.NoAnimation"
+                android:exported="false" />
+
+        <activity android:name=".UninstallerActivity"
+                android:configChanges="orientation|keyboardHidden|screenSize"
+                android:excludeFromRecents="true"
+                android:noHistory="true">
+            <intent-filter android:priority="1">
+                <action android:name="android.intent.action.DELETE" />
+                <action android:name="android.intent.action.UNINSTALL_PACKAGE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+        </activity>
+
+        <receiver android:name=".UninstallEventReceiver"
+            android:permission="android.permission.INSTALL_PACKAGES"
+            android:exported="true">
+            <intent-filter android:priority="1">
+                <action android:name="com.android.packageinstaller.ACTION_UNINSTALL_COMMIT" />
+            </intent-filter>
+        </receiver>
+
+        <activity android:name=".UninstallUninstalling"
+            android:excludeFromRecents="true"
+            android:exported="false" />
+
+        <receiver android:name=".UninstallFinish"
+                android:exported="false" />
+
+        <activity android:name=".television.UninstallAppProgress"
+                android:configChanges="mnc|mnc|touchscreen|navigation|screenLayout|screenSize|smallestScreenSize|orientation|locale|keyboard|keyboardHidden|fontScale|uiMode|layoutDirection|density"
+                android:exported="false" />
+
+        <!-- Wearable Components -->
+        <service android:name=".wear.WearPackageInstallerService"
+                 android:permission="com.google.android.permission.INSTALL_WEARABLE_PACKAGES"
+                 android:exported="true"/>
+
+        <provider android:name=".wear.WearPackageIconProvider"
+                  android:authorities="com.google.android.packageinstaller.wear.provider"
+                  android:grantUriPermissions="true"
+                  android:exported="true" />
+    </application>
+
+</manifest>
diff --git a/packages/PackageInstaller/CleanSpec.mk b/packages/PackageInstaller/CleanSpec.mk
new file mode 100644
index 0000000..b84e1b6
--- /dev/null
+++ b/packages/PackageInstaller/CleanSpec.mk
@@ -0,0 +1,49 @@
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/test-base/api/android-test-base-removed.txt b/packages/PackageInstaller/MODULE_LICENSE_APACHE2
similarity index 100%
copy from test-base/api/android-test-base-removed.txt
copy to packages/PackageInstaller/MODULE_LICENSE_APACHE2
diff --git a/packages/PackageInstaller/NOTICE b/packages/PackageInstaller/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/packages/PackageInstaller/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-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.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/packages/PackageInstaller/OWNERS b/packages/PackageInstaller/OWNERS
new file mode 100644
index 0000000..252670a
--- /dev/null
+++ b/packages/PackageInstaller/OWNERS
@@ -0,0 +1,7 @@
+svetoslavganov@google.com
+moltmann@google.com
+toddke@google.com
+suprabh@google.com
+
+# For automotive related changes
+rogerxue@google.com
diff --git a/packages/PackageInstaller/res/anim/snackbar_enter.xml b/packages/PackageInstaller/res/anim/snackbar_enter.xml
new file mode 100644
index 0000000..96bf4d2
--- /dev/null
+++ b/packages/PackageInstaller/res/anim/snackbar_enter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shareInterpolator="false">
+    <translate android:fromYDelta="100%" android:toYDelta="0"
+            android:interpolator="@android:interpolator/decelerate_quint"
+            android:duration="250"/>
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:interpolator="@android:interpolator/decelerate_quint"
+            android:duration="250" />
+</set>
diff --git a/packages/PackageInstaller/res/anim/snackbar_exit.xml b/packages/PackageInstaller/res/anim/snackbar_exit.xml
new file mode 100644
index 0000000..9aee177
--- /dev/null
+++ b/packages/PackageInstaller/res/anim/snackbar_exit.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false">
+    <translate android:fromYDelta="0" android:toYDelta="100%"
+            android:interpolator="@android:interpolator/accelerate_quint"
+            android:duration="250"/>
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:interpolator="@android:interpolator/accelerate_quint"
+            android:duration="250"/>
+</set>
diff --git a/packages/PackageInstaller/res/drawable/app_icon_foreground.xml b/packages/PackageInstaller/res/drawable/app_icon_foreground.xml
new file mode 100644
index 0000000..b1f40c1
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/app_icon_foreground.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<inset
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetTop="12dp"
+    android:insetRight="12dp"
+    android:insetBottom="12dp"
+    android:insetLeft="12dp">
+
+    <vector
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+
+        <path
+            android:fillColor="#FFFFFF"
+            android:pathData="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" />
+        <path
+            android:pathData="M0 0h24v24H0z" />
+    </vector>
+</inset>
diff --git a/packages/PackageInstaller/res/drawable/ic_android_92.xml b/packages/PackageInstaller/res/drawable/ic_android_92.xml
new file mode 100644
index 0000000..1d3791c
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/ic_android_92.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="92dp"
+        android:height="92dp"
+        android:viewportWidth="92.0"
+        android:viewportHeight="92.0">
+    <path
+        android:fillColor="#000000"
+        android:pathData="m23,69c0,2.11 1.72,3.83 3.83,3.83h3.83v13.42c0,3.18 2.57,5.75 5.75,5.75 3.18,0 5.75,-2.57 5.75,-5.75L42.17,72.83h7.67v13.42c0,3.18 2.57,5.75 5.75,5.75 3.18,0 5.75,-2.57 5.75,-5.75L61.33,72.83h3.83c2.11,0 3.83,-1.72 3.83,-3.83L69,30.67L23,30.67L23,69zM13.42,30.67c-3.18,0 -5.75,2.57 -5.75,5.75v26.83c0,3.18 2.57,5.75 5.75,5.75 3.18,0 5.75,-2.57 5.75,-5.75L19.17,36.42c0,-3.18 -2.57,-5.75 -5.75,-5.75zM78.58,30.67c-3.18,0 -5.75,2.57 -5.75,5.75v26.83c0,3.18 2.57,5.75 5.75,5.75 3.18,0 5.75,-2.57 5.75,-5.75L84.33,36.42c0,-3.18 -2.57,-5.75 -5.75,-5.75zM59.53,8.28 L64.53,3.28c0.75,-0.75 0.75,-1.95 0,-2.7 -0.75,-0.75 -1.95,-0.75 -2.7,0L56.16,6.23C53.09,4.72 49.66,3.84 46,3.84c-3.68,0 -7.13,0.88 -10.22,2.41L30.09,0.56c-0.75,-0.75 -1.95,-0.75 -2.7,0 -0.75,0.75 -0.75,1.95 0,2.7l5.02,5.02C26.72,12.48 23,19.23 23,26.84h46c0,-7.63 -3.74,-14.37 -9.47,-18.55zM38.33,19.17h-3.83v-3.83h3.83v3.83zM57.5,19.17h-3.83v-3.83h3.83v3.83z"/>
+</vector>
diff --git a/packages/PackageInstaller/res/drawable/ic_app_icon.xml b/packages/PackageInstaller/res/drawable/ic_app_icon.xml
new file mode 100644
index 0000000..82c18e0
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/ic_app_icon.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@*android:color/accent_device_default_light"/>
+    <foreground android:drawable="@drawable/app_icon_foreground"/>
+</adaptive-icon>
\ No newline at end of file
diff --git a/packages/PackageInstaller/res/drawable/ic_done_92.xml b/packages/PackageInstaller/res/drawable/ic_done_92.xml
new file mode 100644
index 0000000..185b274
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/ic_done_92.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="92dp"
+        android:height="92dp"
+        android:viewportWidth="92.0"
+        android:viewportHeight="92.0">
+    <path
+        android:fillColor="#000000"
+        android:pathData="M34.5,61.99 L18.51,46 13.09,51.42 34.5,72.83l46,-46 -5.42,-5.42z"/>
+</vector>
diff --git a/packages/PackageInstaller/res/drawable/ic_error.xml b/packages/PackageInstaller/res/drawable/ic_error.xml
new file mode 100644
index 0000000..28612a1
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/ic_error.xml
@@ -0,0 +1,26 @@
+<?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.
+  -->
+
+<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:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z"
+            android:fillColor="#000000"/>
+</vector>
diff --git a/packages/PackageInstaller/res/drawable/ic_file_download.xml b/packages/PackageInstaller/res/drawable/ic_file_download.xml
new file mode 100644
index 0000000..16c6080
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/ic_file_download.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
+    android:tint="?android:attr/colorControlNormal">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/PackageInstaller/res/drawable/ic_lock.xml b/packages/PackageInstaller/res/drawable/ic_lock.xml
new file mode 100644
index 0000000..396bd98
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/ic_lock.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2015 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48">
+    <path
+        android:pathData="M0 0h48v48H0z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M36 16h-2v-4c0-5.52-4.48-10-10-10S14 6.48 14 12v4h-2c-2.21 0-4 1.79-4 4v20c0
+2.21 1.79 4 4 4h24c2.21 0 4-1.79 4-4V20c0-2.21-1.79-4-4-4zM24 34c-2.21
+0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm6.2-18H17.8v-4c0-3.42 2.78-6.2
+6.2-6.2 3.42 0 6.2 2.78 6.2 6.2v4z" />
+</vector>
diff --git a/packages/PackageInstaller/res/drawable/ic_remove.xml b/packages/PackageInstaller/res/drawable/ic_remove.xml
new file mode 100644
index 0000000..dd46eda
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/ic_remove.xml
@@ -0,0 +1,26 @@
+<?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.
+  -->
+
+<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:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13L7,13v-2h10v2z"
+            android:fillColor="#000000"/>
+</vector>
diff --git a/packages/PackageInstaller/res/drawable/ic_report_problem_92.xml b/packages/PackageInstaller/res/drawable/ic_report_problem_92.xml
new file mode 100644
index 0000000..c90a33e
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/ic_report_problem_92.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="92dp"
+        android:height="92dp"
+        android:viewportWidth="92.0"
+        android:viewportHeight="92.0">
+    <path
+        android:fillColor="#000000"
+        android:pathData="M2,84H90L46,8 2,84zM50,72h-8v-8h8v8zM50,56H42V40h8v16z"/>
+</vector>
diff --git a/packages/PackageInstaller/res/drawable/ic_settings_multiuser.xml b/packages/PackageInstaller/res/drawable/ic_settings_multiuser.xml
new file mode 100644
index 0000000..b24a5d4
--- /dev/null
+++ b/packages/PackageInstaller/res/drawable/ic_settings_multiuser.xml
@@ -0,0 +1,25 @@
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorAccent">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.0,12.0c2.21,0.0 4.0,-1.79 4.0,-4.0s-1.79,-4.0 -4.0,-4.0 -4.0,1.79 -4.0,4.0 1.79,4.0 4.0,4.0zm0.0,2.0c-2.67,0.0 -8.0,1.34 -8.0,4.0l0.0,2.0l16.0,0.0l0.0,-2.0c0.0,-2.66 -5.33,-4.0 -8.0,-4.0z"/>
+</vector>
diff --git a/packages/PackageInstaller/res/layout-television/app_details.xml b/packages/PackageInstaller/res/layout-television/app_details.xml
new file mode 100644
index 0000000..86923c5
--- /dev/null
+++ b/packages/PackageInstaller/res/layout-television/app_details.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!--
+Defines the layout of the application snippet that appears on top of the
+installation screens
+-->
+<!-- The snippet about the application - title, icon -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/app_snippet"
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/actionBarSize"
+        android:orientation="horizontal">
+
+    <ImageView android:id="@+id/app_icon"
+            android:layout_marginLeft="16dp"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:layout_gravity="center_vertical"
+            android:scaleType="fitCenter" />
+
+    <TextView android:id="@+id/app_name"
+            android:layout_gravity="center_vertical"
+            android:layout_marginLeft="32dp"
+            android:layout_marginRight="16dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/titleTextStyle"
+            android:singleLine="true"
+            android:ellipsize="end" />
+
+</LinearLayout>
+
diff --git a/packages/PackageInstaller/res/layout-television/uninstall_progress.xml b/packages/PackageInstaller/res/layout-television/uninstall_progress.xml
new file mode 100644
index 0000000..e24f63b
--- /dev/null
+++ b/packages/PackageInstaller/res/layout-television/uninstall_progress.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+    <include layout="@layout/app_details"
+            android:id="@+id/app_snippet"/>
+
+    <LinearLayout android:id="@+id/progress_view"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:orientation="vertical"
+            android:padding="16dp">
+
+        <ImageView android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="12dp"
+                android:src="@drawable/ic_android_92"
+                android:tint="@color/bigIconColor"
+                android:contentDescription="@null" />
+
+        <ProgressBar android:id="@+id/progress_bar"
+                android:layout_width="250dp"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                style="?android:attr/progressBarStyleHorizontal">
+        </ProgressBar>
+
+        <TextView android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:gravity="center_horizontal"
+                android:text="@string/uninstalling"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    </LinearLayout>
+
+    <!-- Status view is shown after progress view is removed -->
+    <ScrollView android:id="@+id/status_view"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:visibility="gone"
+            android:padding="16dp">
+
+        <TextView android:id="@+id/status_text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="start"
+                android:textAppearance="?android:attr/textAppearanceMedium"/>
+    </ScrollView>
+
+    <LinearLayout android:id="@+id/ok_panel"
+            style="?android:attr/buttonBarStyle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:measureWithLargestChild="true"
+            android:visibility="gone"
+            android:padding="8dip">
+
+        <!-- spacer to push buttons to the right -->
+        <View android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:layout_weight="1" />
+
+        <Button android:id="@+id/device_manager_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:text="@string/manage_device_administrators"
+                android:maxLines="2"
+                style="?android:attr/buttonBarButtonStyle" />
+
+        <Button android:id="@+id/users_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:text="@string/manage_users"
+                android:maxLines="2"
+                style="?android:attr/buttonBarButtonStyle" />
+
+        <Button android:id="@+id/ok_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/ok"
+                android:maxLines="2"
+                style="?android:attr/buttonBarButtonStyle" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/PackageInstaller/res/layout/install_content_view.xml b/packages/PackageInstaller/res/layout/install_content_view.xml
new file mode 100644
index 0000000..5e94a29
--- /dev/null
+++ b/packages/PackageInstaller/res/layout/install_content_view.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:theme="?android:attr/alertDialogTheme"
+    android:paddingTop="8dp"
+    android:paddingLeft="?android:attr/dialogPreferredPadding"
+    android:paddingRight="?android:attr/dialogPreferredPadding">
+
+    <LinearLayout
+        android:id="@+id/staging"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:visibility="invisible">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@android:style/TextAppearance.Material.Subhead"
+            android:text="@string/message_staging" />
+
+        <ProgressBar
+            android:id="@+id/progress_indeterminate"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dp"
+            style="?android:attr/progressBarStyleHorizontal"
+            android:indeterminate="true" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/installing"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:visibility="invisible">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@android:style/TextAppearance.Material.Subhead"
+            android:text="@string/installing" />
+
+        <ProgressBar
+            android:id="@+id/progress"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dp"
+            style="?android:attr/progressBarStyleHorizontal" />
+
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/install_confirm_question"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/install_confirm_question"
+        android:visibility="invisible" />
+
+    <TextView
+        android:id="@+id/install_confirm_question_update"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/install_confirm_question_update"
+        android:visibility="invisible" />
+
+    <TextView
+        android:id="@+id/install_confirm_question_update_system"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/install_confirm_question_update_system"
+        android:visibility="invisible" />
+
+    <TextView
+        android:id="@+id/install_success"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/install_done"
+        android:visibility="invisible" />
+
+    <TextView
+        android:id="@+id/install_failed"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/install_failed"
+        android:visibility="invisible" />
+
+    <TextView
+        android:id="@+id/install_failed_blocked"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/install_failed_blocked"
+        android:visibility="invisible" />
+
+    <TextView
+        android:id="@+id/install_failed_conflict"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/install_failed_conflict"
+        android:visibility="invisible" />
+
+    <TextView
+        android:id="@+id/install_failed_incompatible"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/install_failed_incompatible"
+        android:visibility="invisible" />
+
+    <TextView
+        android:id="@+id/install_failed_invalid_apk"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/install_failed_invalid_apk"
+        android:visibility="invisible" />
+
+</FrameLayout>
diff --git a/packages/PackageInstaller/res/values-af-television/strings.xml b/packages/PackageInstaller/res/values-af-television/strings.xml
new file mode 100644
index 0000000..32cf00f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-af-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Weier en moenie weer vra nie"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Jy kan dit later verander in Instellings &gt; Programme"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Wys stelselprogramme"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Programtoestemmings"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Programtoestemmings"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g>toestemmings"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Bykomende toestemmings"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g>toestemmings"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-af-watch/strings.xml b/packages/PackageInstaller/res/values-af-watch/strings.xml
new file mode 100644
index 0000000..a62540f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-af-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Weier; moenie weer vra nie"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Wys stelselprogramme"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Onveranderbaar"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ja"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Kanselleer"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-af/strings.xml b/packages/PackageInstaller/res/values-af/strings.xml
new file mode 100644
index 0000000..0d41c18
--- /dev/null
+++ b/packages/PackageInstaller/res/values-af/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Pakketinstalleerder"</string>
+    <string name="next" msgid="3057143178373252333">"Volgende"</string>
+    <string name="install" msgid="5896438203900042068">"Installeer"</string>
+    <string name="done" msgid="3889387558374211719">"Klaar"</string>
+    <string name="cancel" msgid="8360346460165114585">"Kanselleer"</string>
+    <string name="installing" msgid="8613631001631998372">"Installeer tans…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installeer tans <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
+    <string name="install_done" msgid="3682715442154357097">"Program geïnstalleer."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Wil jy hierdie program installeer? Dit sal kan ingaan by:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Wil jy hierdie program installeer? Dit vereis nie enige spesiale toegang nie."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Wil jy \'n opdatering vir die bestaande program installeer? Jou bestaande data sal nie verlore gaan nie. Die opgedateerde program sal kan ingaan by:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Wil jy \'n opdatering vir hierdie ingeboude program installeer? Jou bestaande data sal nie verlore gaan nie. Die opgedateerde program sal kan ingaan by:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Wil jy \'n opdatering na hierdie bestaande program installeer? Jou bestaande data sal nie verlore raak nie. Dit vereis nie enige spesiale toegang nie."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Wil jy \'n opdatering na hierdie ingeboude program installeer? Jou bestaande data sal nie verlore raak nie. Dit vereis nie enige spesiale toegang nie."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Program nie geïnstalleer nie."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Die installering van die pakket is geblokkeer."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Program is nie geïnstalleer nie omdat pakket met \'n bestaande pakket bots."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Program is nie geïnstalleer nie omdat dit nie met jou tablet versoenbaar is nie."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Hierdie program is nie met jou TV versoenbaar nie."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Program is nie geïnstalleer nie omdat dit nie met jou foon versoenbaar is nie."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Program is nie geïnstalleer nie omdat pakket ongeldig blyk te wees."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> kon nie op jou tablet geïnstalleer word nie."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> kon nie op jou TV geïnstalleer word nie."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> kon nie op jou foon geïnstalleer word nie."</string>
+    <string name="launch" msgid="4826921505917605463">"Open"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Jou administrateur laat nie toe dat programme wat by onbekende bronne verkry is, geïnstalleer word nie"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Hierdie gebruiker kan nie onbekende programme installeer nie"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Hierdie gebruiker word nie toegelaat om programme te installeer nie"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Bestuur programme"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Geen spasie oor nie"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> kon nie geïnstalleer word nie. Maak \'n bietjie plek en probeer weer."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Program nie gevind nie"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Die program is nie in die lys van geïnstalleerde programme gevind nie."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Nie toegelaat nie"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Die huidige gebruiker mag nie hierdie deïnstallering uitvoer nie."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Fout"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Program kon nie gedeïnstalleer word nie."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Deïnstalleer program"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Deïnstalleer opdatering"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is deel van die volgende program:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Wil jy hierdie program deïnstalleer?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Wil jy hierdie program vir "<b>"alle"</b>" gebruikers deïnstalleer? Die program en sy data sal vir "<b>"alle"</b>" gebruikers op hierdie toestel verwyder word."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Wil jy hierdie program vir die gebruiker <xliff:g id="USERNAME">%1$s</xliff:g> deïnstalleer?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Vervang hierdie program met die fabriekweergawe? Alle data sal verwyder word."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Vervang hierdie program met die fabriekweergawe? Alle data sal verwyder word. Dit beïnvloed alle gebruikers van hierdie toestel, insluitend dié met werkprofiele."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Voer tans deïnstallerings uit"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Mislukte installerings"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Deïnstalleer tans…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Deïnstalleer tans <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Deïnstallering klaar."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Het <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> gedeïnstalleer"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Deïnstallasie onsuksesvol."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Kon nie <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> deïnstalleer nie."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Kan nie aktiewe toesteladministrasieprogram deïnstalleer nie"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Kan nie aktiewe toesteladministrasieprogram vir <xliff:g id="USERNAME">%1$s</xliff:g> deïnstalleer nie"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Dié program word vereis vir sommige gebruikers of profiele en is vir ander gedeïnstalleer"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Hierdie program is nodig vir jou profiel en kan nie gedeïnstalleer word nie."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Jou toesteladministrateur vereis die program; dit kan nie deïnstalleer word nie."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Bestuur toesteladministrasieprogramme"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Bestuur gebruikers"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> kon nie deïnstalleer word nie."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Kon nie die pakket ontleed nie."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nuut"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Alle"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privaatheid"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Toesteltoegang"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Hierdie opdatering vereis geen nuwe toestemmings nie."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Weier"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Meer inligting"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Weier in elk geval"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> van <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; altyd toe om <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Net terwyl program gebruik word"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Altyd"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Weier en moenie weer vra nie"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> is gedeaktiveer"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"alles is gedeaktiveer"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"geen is gedeaktiveer nie"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Laat toe"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Programme"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Programtoestemmings"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Moenie weer vra nie"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Geen toestemmings nie"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Bykomende toestemmings"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Maak programinligting oop"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other">Nog <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Nog <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Hierdie program is vir \'n ouer weergawe van Android ontwerp. As toestemming geweier word, kan dit veroorsaak dat dit nie meer soos beplan funksioneer nie."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"voer \'n onbekende handeling uit"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> uit <xliff:g id="COUNT_1">%2$d</xliff:g> programme toegelaat"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Wys stelsel"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Versteek stelsel"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Geen programme nie"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Ligginginstellings"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> is \'n verskaffer van liggingdienste vir hierdie toestel. Liggingtoegang kan vanuit ligginginstellings verander word."</string>
+    <string name="system_warning" msgid="7103819124542305179">"As jy hierdie toestemming weier, sal basiese kenmerke van jou toestel dalk nie meer soos bedoel werk nie."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Afgedwing deur beleid"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Agtergrondtoegang is gedeaktiveer volgens beleid"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Agtergrondtoegang is geaktiveer volgens beleid"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Voorgrondtoegang is geaktiveer volgens beleid"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Beheer deur administrateur"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Altyd"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Net as program gebruik word"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nooit"</string>
+    <string name="loading" msgid="7811651799620593731">"Laai tans …"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Alle toestemmings"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Ander programvermoëns"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Toestemmingsversoek"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Skermoorlegger bespeur"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Om hierdie toestemminginstelling te verander, moet jy eers die skermoorlegger by Instellings &gt; Programme afskakel"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Maak instellings oop"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Installeer- en deïnstalleerhandelinge word nie in Wear gesteun nie."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Kies waartoe &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang mag kry"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; is opgedateer. Kies waartoe hierdie program toegang mag kry."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Kanselleer"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Gaan voort"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nuwe toestemmings"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Huidige toestemmings"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Voer tans program uit …"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Onbekend"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Jou tablet word vir jou veiligheid nie toegelaat om onbekende programme van hierdie bron af te installeer nie."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Jou TV word vir jou veiligheid nie toegelaat om onbekende programme van hierdie bron af te installeer nie."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Jou foon word vir jou veiligheid nie toegelaat om onbekende programme van hierdie bron af te installeer nie."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Jou foon en persoonlike data is meer kwesbaar vir aanvalle deur onbekende programme. Deur hierdie program te installeer, stem jy in dat jy verantwoordelik is vir enige skade aan jou foon of verlies van data wat uit sy gebruik kan spruit."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Jou tablet en persoonlike data is meer kwesbaar vir aanvalle deur onbekende programme. Deur hierdie program te installeer, stem jy in dat jy verantwoordelik is vir enige skade aan jou tablet of verlies van data wat uit sy gebruik kan spruit."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Jou TV en persoonlike data is meer kwesbaar vir aanvalle deur onbekende programme. Deur hierdie program te installeer, stem jy in dat jy verantwoordelik is vir enige skade aan jou TV of verlies van data wat uit sy gebruik kan spruit."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Gaan voort"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Instellings"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installeer/deïnstalleer Wear-programme"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-am-television/strings.xml b/packages/PackageInstaller/res/values-am-television/strings.xml
new file mode 100644
index 0000000..e4f23c1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-am-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"አይቀበሉና እንደገና ይጠይቁ"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"ይሄንን በኋላ ላይ በቅንብሮችና መተግበሪያዎች ውስጥ ሊቀይሩት ይችላሉ"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"የስርዓት መተግበሪያዎችን አሳይ"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"የመተግበሪያ ፈቃዶች"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"የመተግበሪያ ፈቃዶች"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> ፈቃዶች"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"ተጨማሪ ፈቃዶች"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> ፈቃዶች"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-am-watch/strings.xml b/packages/PackageInstaller/res/values-am-watch/strings.xml
new file mode 100644
index 0000000..1b01ddd
--- /dev/null
+++ b/packages/PackageInstaller/res/values-am-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ከልክል፣ ዳግም አትጠይቅ"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"የስርዓት መተግበሪያዎችን አሳይ"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ሊለወጥ አይችልም"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"አዎ"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"ይቅር"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-am/strings.xml b/packages/PackageInstaller/res/values-am/strings.xml
new file mode 100644
index 0000000..d4c5076
--- /dev/null
+++ b/packages/PackageInstaller/res/values-am/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"ጥቅል ጫኝ"</string>
+    <string name="next" msgid="3057143178373252333">"ቀጣይ"</string>
+    <string name="install" msgid="5896438203900042068">"ጫን"</string>
+    <string name="done" msgid="3889387558374211719">"ተከናውኗል"</string>
+    <string name="cancel" msgid="8360346460165114585">"ይቅር"</string>
+    <string name="installing" msgid="8613631001631998372">"በመጫን ላይ…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ን በመጫን ላይ…"</string>
+    <string name="install_done" msgid="3682715442154357097">"መተግበሪያ ተጭኗል፡፡"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"ይህንን መተግበሪያ መጫን ይፈልጋሉ? ወደዚህ መዳረሻ ያገኛል፦"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"ይህንን መተግበሪያ መጫን ይፈልጋሉ? ምንም የተለየ መዳረሻ አይጠይቅም።"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"ለእዚህ ነባር መተግበሪያ ማዘመኛ መጫን ይፈልጋሉ? የነበረው ውሂብህ አይጠፋም። የዘመነው መተግበሪያ ወደዚህ መዳረሻ ያገኛል፦"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"ለእዚህ አብሮ ለተሰራ መተግበሪያ ማዘመኛ መጫን ይፈልጋሉ? የነበረው ውሂብዎ አይጠፋም። የዘመነው መተግበሪያ ወደዚህ መዳረሻ ያገኛል፦"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"ለዚህ ነባር መተግበሪያ ዝማኔ መጫን ይፈልጋሉ? ነባር ውሂብዎ አይጠፉም። ምንም የተለየ መዳረሻ አይፈልግም።"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"ለዚህ አብሮ ለተሰራ መተግበሪያ ዝማኔ መጫን ይፈልጋሉ? ነባር ውሂብዎ አይጠፉም። ምንም የተለየ መዳረሻ አይፈልግም።"</string>
+    <string name="install_failed" msgid="6579998651498970899">"ትግበራ አልተጫነም።"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ጥቅሉ እንዳይጫን ታግዷል።"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"እንደ ጥቅል ያልተጫነ መተግበሪያ ከነባር ጥቅል ጋር ይጋጫል።"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"እንደ መተግበሪያ ያልተጫነ መተግበሪያ ከጡባዊዎ ጋር ተኳሃኝ አይደለም።"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"ይሄ መተግበሪያ ከእርስዎ ቴሌቪዥን ጋር ተኳሃኝ አይደለም።"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"እንደ መተግበሪያ ያልተጫነ መተግበሪያ ከስልክዎ ጋር ተኳሃኝ አይደለም።"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"እንደ ጥቅል ያልተጫነ መተግበሪያ ልክ ያልሆነ ይመስላል።"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> በዚህ ስልክ ላይ መጫን አልተቻለም።"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> በእርስዎ ቴሌቪዥን ላይ ሊጫን አልቻለም።"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g>በዚህ ስልክ ላይ መጫን አልተቻለም።"</string>
+    <string name="launch" msgid="4826921505917605463">"ክፈት"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"የእርስዎ አስተዳዳሪ ካልታወቁ ምንጮች የመጡ መተግበሪያዎች እንዲጫኑ አይፈቅድም"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"ያልታወቁ መተግበሪያዎች በዚህ ተጠቃሚ ሊጫኑ አይችሉም"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"ይህ ተጠቃሚ መተግበሪያዎችን እንዲጭን አልተፈቀደለትም"</string>
+    <string name="ok" msgid="3468756155452870475">"እሺ"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"መተግበሪያዎች አስተዳድር"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"ቦታ ሞልቷል"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g>ለመጫን አልቻለም። ትንሽ ቦታ አስለቅቅ እና እንደገና ሞክር፡፡"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"ትግበራ አልተገኘም"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"መተግበሪያው በተጫኑ መተግበሪያዎች ዝርዝር ውስጥ አልተገኘም።"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"አይፈቀድም"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"አሁን ያለው ተጠቃሚ ይህን ማራገፍ ሥራ እንዲያከናውን አይፈቀድለትም።"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"ስሕተት"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"መተግበሪያ ሊራገፍ አልተቻለም"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"ትግበራ አራግፍ"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"ማዘመን አራግፍ"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>የሚከተለው ትግበራ አካል ነው፡"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"ይሄን መተግበሪያ ማራገፍ ይፈልጋሉ?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"ይህን መተግበሪያ "<b>"ለሁሉም"</b>" ተጠቃሚዎች መጫን ይፈልጋሉ? መተግበሪያው እና ውሂቡ በመሣሪያው ላይ ካሉ "<b>"ሁሉም"</b>" ተጠቃሚዎች ይሰረዛሉ።"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"ይህን መተግበሪያ ለተጠቃሚ <xliff:g id="USERNAME">%1$s</xliff:g> ማራገፍ ይፈልጋሉ?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ይህ መተግበሪያ በፋብሪክው ስሪት ይተካ? ሁሉም ውሂብ ይወገዳል።"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ይህ መተግበሪያ በፋብሪክው ስሪት ይተካ? ሁሉም ውሂብ ይወገዳል። እነዚያን የሥራ መገለጫዎች ያላቸውን ጨምሮ ሁሉንም በዚህ መሣሪያ ላይ ባሉ ተጠቃሚዎች ላይ ተጽዕኖ ያሳርፍባቸዋል።"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"በማሄድ ላይ ያሉ ማራገፎች"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"ያልተሳኩ ማራገፎች"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"ባለመጫንላይ"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ን በማራገፍ ላይ…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"አራግፍ ተጠናቋል"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ተራግፏል"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"ማራገፍ አልተሳካም፡፡"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ን ማራገፍ ስኬታማ አልነበረም።"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"ገባሪ የመሣሪያ አስተዳደር መተግበሪያን ማራገፍ አይቻልም"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"ለ<xliff:g id="USERNAME">%1$s</xliff:g> ገባሪ የመሣሪያ አስተዳደር መተግበሪያን ማራገፍ አይቻልም"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"ይህ መተግበሪያ ለአንዳንድ ተጠቃሚዎች ወይም መገለጫዎች ያስፈልጋል እና ለሌሎች ተራግፏል"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"ይህ መተግበሪያ ለእርስዎ መገለጫዎ ያስፈልጋል እና ሊራገፍ አይችልም።"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"ይህ መተግበሪያ በመሣሪያዎ አስተዳዳሪ የሚፈለግ እና ሊራገፍ የማይችል ነው።"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"የመሣሪያ አስተዳደር መተግበሪያዎችን ያስተዳድሩ"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ተጠቃሚዎችን ያስተዳድሩ"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g>ማራገፍ አልተቻለም"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"አካታቹን መተንተን ችግር ነበረ።"</string>
+    <string name="newPerms" msgid="6039428254474104210">"አዲስ"</string>
+    <string name="allPerms" msgid="1024385515840703981">"ሁሉም"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"ግላዊነት"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"የመሳሪያ መዳረሻ"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"ይህ ዝማኔ ምንም አዲስ ፈቃድ አያስፈልገውም።"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"ከልክል"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"ተጨማሪ መረጃ"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"ለማንኛውም ከልክል"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> ከ<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g> እንዲከናወን ይፈቀድለት?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"ሁልጊዜ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ወደ <xliff:g id="ACTION">%2$s</xliff:g> ይፈቀድ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"መተግበሪያን በመጠቀም ላይ ሲኮን ብቻ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ሁልጊዜ"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"አትቀበል እና እንደገና አትጠይቅ"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> ተሰናክሏል"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"ሁሉም ተሰናክሏል"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ምንም አልተሰናከለም"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"ፍቀድ"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"መተግበሪያዎች"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"የመተግበሪያ ፈቃዶች"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"ዳግም አትጠይቅ"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"ምንም ፍቃዶች የሉም"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"ተጨማሪ ፈቃዶች"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"የመተግበሪያ መረጃን ክፈት"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"ይህ መተግበሪያ ለAndroid አሮጌ ስሪት የተነደፈ ነበር። ፈቃድ መከልከል እንደሚፈለገው ከእንግዲህ እንዳይሰራ ሊያደርገው ይችላል።"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ያልታወቀ እርምጃ ያከናውናል"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> ከ<xliff:g id="COUNT_1">%2$d</xliff:g> መተግበሪያዎች ተፈቅዶላቸዋል"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"ስርዓትን አሳይ"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"ስርዓትን ደብቅ"</string>
+    <string name="no_apps" msgid="1965493419005012569">"ምንም መተግበሪያዎች የሉም"</string>
+    <string name="location_settings" msgid="1774875730854491297">"የአካባቢ ቅንብሮች"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> የዚህ መሳሪያ አካባቢ አገልግሎቶች አቅራቢ ነው። የአካባቢ መዳረሻ ከአካባቢ ቅንብሮች ሊሻሻል ይችላል።"</string>
+    <string name="system_warning" msgid="7103819124542305179">"ይህን ፍቃድ ከከለከሉ የመሳሪያዎ መሰረታዊ ባህሪያት ከዚህ በኋላ እንደተፈለገው ላይሰሩ ይችላሉ።"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"በመመሪያ ተፈጻሚ የሆነ"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"የጀርባ መዳረሻ በመመሪያ ተሰናክሏል"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"የጀርባ መዳረሻ በመመሪያ ነቅቷል"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"የፊት መዳረሻ በመመሪያ ነቅቷል"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"በአስተዳዳሪ ቁጥጥር የሚደረግበት"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ዘወትር"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"መተግበሪያን በስራ ላይ ሲሆን ብቻ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"በጭራሽ"</string>
+    <string name="loading" msgid="7811651799620593731">"በመጫን ላይ…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"ሁሉም ፍቃዶች"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"ሌሎች የመተግበሪያ ችሎታዎች"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"የፍቃድ ጥያቄ"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"የማያ ገጽ ተደራቢ ተገኝቷል"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ይህን የፍቃድ ቅንብር ለመቀየር መጀመሪያ የማያ ገጽ ተደራቢውን ከቅንብሮች &gt; መተግበሪያዎች ማጥፋት አለብዎ"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"ቅንብሮችን ክፈት"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"በWear ላይ የመጫን/ማራገፍ እርምጃዎች አይደገፉም።"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ምን መድረስ እንደሚችል ይምረጡ"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ተዘምኗል። ይህ መተግበሪያ ምን መድረስ እንደሚችል ይምረጡ።"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"ይቅር"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"ቀጥል"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"አዲስ ፍቃዶች"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"የአሁኖቹ ፍቃዶች"</string>
+    <string name="message_staging" msgid="6151794817691100003">"መተግበሪያን በማዘጋጀት ላይ…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"ያልታወቀ"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"ለእርስዎ ደህንነት ሲባል የእርስዎ ጡባዊ ከዚህ ምንጭ የመጡ ያልታወቁ መተግበሪያዎችን እንዲጭን አልተፈቀደለትም።"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"ለእርስዎ ደህንነት ሲባል የእርስዎ ቴሌቪዥን ከዚህ ምንጭ የመጡ ያልታወቁ መተግበሪያዎችን እንዲጭን አልተፈቀደለትም።"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"ለእርስዎ ደህንነት ሲባል የእርስዎ ስልክ ከዚህ ምንጭ የመጡ ያልታወቁ መተግበሪያዎችን እንዲጭን አልተፈቀደለትም።"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"የእርስዎ ስልክ እና የግል ውሂብ በማይታወቁ መተግበሪያዎች ለሚደርሱ ጥቃቶች በይልበልጥ ተጋላጭ ናቸው። ይህን መተግበሪያ በመጫንዎ በእርስዎ ስልክ ላይ ለሚደርስ ማናቸውም ጉዳት ወይም መተግበሪያውን በመጠቀም ለሚከሰት የውሂብ መጥፋት ኃላፊነቱን እንደሚወስዱ ተስማምተዋል።"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"የእርስዎ ጡባዊ እና የግል ውሂብ በማይታወቁ መተግበሪያዎች ለሚደርሱ ጥቃቶች በይበልጥ ተጋላጭ ናቸው። ይህን መተግበሪያ በመጫንዎ በእርስዎ ጡባዊ ላይ ለሚደርስ ማናቸውም ጉዳት ወይም መተግበሪያውን በመጠቀም ለሚከሰት የውሂብ መጥፋት ኃላፊነቱን እንደሚወስዱ ተስማምተዋል።"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"የእርስዎ ቴሌቪዥን እና የግል ውሂብ በማይታወቁ መተግበሪያዎች ለሚደርሱ ጥቃቶች በይበልጥ ተጋላጭ ናቸው። ይህን መተግበሪያ በመጫንዎ በእርስዎ ቴሌቪዥን ላይ ለሚደርስ ማናቸውም ጉዳት ወይም መተግበሪያውን በመጠቀም ለሚከሰት የውሂብ መጥፋት ኃላፊነቱን እንደሚወስዱ ተስማምተዋል።"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"ቀጥል"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ቅንብሮች"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"የWear መተግበሪያዎችን መጫን/ማራገፍ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ar-television/strings.xml b/packages/PackageInstaller/res/values-ar-television/strings.xml
new file mode 100644
index 0000000..9297b88
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ar-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"رفض وعدم طرح السؤال مرة أخرى"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"‏يمكنك تغيير ذلك لاحقًا من خلال الإعدادات &gt; التطبيقات"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"عرض تطبيقات النظام"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"أذونات التطبيق"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"أذونات التطبيق"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"أذونات <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"أذونات إضافية"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"أذونات <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ar-watch/strings.xml b/packages/PackageInstaller/res/values-ar-watch/strings.xml
new file mode 100644
index 0000000..19930ea
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ar-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"الرفض وعدم السؤال مرة أخرى"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"عرض تطبيقات النظام"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"لا يمكن التغيير"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"نعم"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"إلغاء"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml
new file mode 100644
index 0000000..613481e
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ar/strings.xml
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"أداة تثبيت الحزم"</string>
+    <string name="next" msgid="3057143178373252333">"التالي"</string>
+    <string name="install" msgid="5896438203900042068">"تثبيت"</string>
+    <string name="done" msgid="3889387558374211719">"تم"</string>
+    <string name="cancel" msgid="8360346460165114585">"إلغاء"</string>
+    <string name="installing" msgid="8613631001631998372">"جارٍ التثبيت..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"جارٍ تثبيت <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"تم تثبيت التطبيق."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"هل تريد تثبيت هذا التطبيق؟ سيكون بإمكانه الدخول إلى:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"هل تريد تثبيت هذا التطبيق؟ إنه لا يتطلب أي دخول خاص."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"هل تريد تثبيت تحديث لهذا التطبيق الحالي؟ لن تفقد بياناتك الحالية. سيكون بإمكان التطبيق المحدّث الدخول إلى:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"هل تريد تثبيت تحديث لهذا التطبيق المضمن؟ لن تفقد بياناتك الحالية. سيكون بإمكان التطبيق المحدّث الدخول إلى:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"هل تريد تثبيت تحديث لهذا التطبيق الحالي؟ لن يتم فقد بياناتك الحالية. كما أنه لا يتطلب أي دخول خاص."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"هل تريد تثبيت تحديث لهذا التطبيق المضمن؟ لن يتم فقد بياناتك الحالية. كما أنه لا يتطلب أي دخول خاص."</string>
+    <string name="install_failed" msgid="6579998651498970899">"التطبيق ليس مثبتًا."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"تم حظر تثبيت الحزمة."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"لم يتم تثبيت التطبيق لأن حزمة التثبيت تتعارض مع حزمة حالية."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"لم يتم تثبيت التطبيق لأنه ليس متوافقًا مع جهازك اللوحي."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"هذا التطبيق لا يتوافق مع جهاز التلفزيون."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"لم يتم تثبيت التطبيق لأنه ليس متوافقًا مع هاتفك."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"لم يتم تثبيت التطبيق لأن الحزمة تبدو غير صالحة."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"تعذر تثبيت <xliff:g id="APP_NAME">%1$s</xliff:g> على جهازك اللوحي."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"تعذر تثبيت <xliff:g id="APP_NAME">%1$s</xliff:g> على جهاز التلفزيون."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"تعذر تثبيت <xliff:g id="APP_NAME">%1$s</xliff:g> على هاتفك."</string>
+    <string name="launch" msgid="4826921505917605463">"فتح"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"لا يسمح المشرف بتثبيت التطبيقات التي يتم الحصول عليها من مصادر غير معروفة"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"يتعذر على هذا المستخدم تثبيت التطبيقات غير المعروفة"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"غير مسموح لهذا المستخدم بتثبيت التطبيقات"</string>
+    <string name="ok" msgid="3468756155452870475">"موافق"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"إدارة التطبيقات"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"نفدت مساحة التخزين"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"تعذر تثبيت <xliff:g id="APP_NAME">%1$s</xliff:g> يُرجى تحرير بعض المساحة والمحاولة مرة أخرى."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"لم يتم العثور على التطبيق"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"لم يتم العثور على التطبيق في قائمة التطبيقات المثبتة."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"غير مسموح به"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"غير مسموح للمستخدم الحالي بتنفيذ عملية إلغاء التثبيت هذه."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"الخطأ"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"تعذر إلغاء تثبيت التطبيق."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"إلغاء تثبيت التطبيق"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"إزالة التحديث"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> هو جزء من التطبيق التالي:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"هل تريد إزالة هذا التطبيق؟"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"هل تريد إزالة هذا التطبيق "<b>"لكل"</b>" المستخدمين؟ ستتم إزالة التطبيق وبياناته من "<b>"كل"</b>" المستخدمين على هذا الجهاز."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"هل تريد إزالة هذا التطبيق للمستخدم <xliff:g id="USERNAME">%1$s</xliff:g>؟"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"هل تريد استبدال هذا التطبيق بإصدار المصنع؟ ستتم إزالة جميع البيانات."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"هل تريد استبدال هذا التطبيق بإصدار المصنع؟ ستتم إزالة جميع البيانات. وسيؤثر هذا في جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات شخصية للعمل."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"عمليات إلغاء التثبيت الجارية"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"عمليات إلغاء التثبيت غير الناجحة"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"جارٍ الإزالة..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"جارٍ إلغاء تثبيت <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"انتهت الإزالة."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"تم إلغاء تثبيت <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"تعذّر إلغاء التثبيت."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"لم يتم إلغاء تثبيت <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> بنجاح."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"تعذر إلغاء تثبيت تطبيق مشرف الأجهزة النشطة"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"تعذر إلغاء تثبيت تطبيق مشرف الأجهزة النشطة لدى <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"هذا التطبيق مطلوب لبعض المستخدمين أو الملفات الشخصية وتم إلغاء تثبيته لآخرين."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"هذا التطبيق مطلوب لملفك الشخصي ولا يمكن إلغاء تثبيته."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"مشرف الجهاز يحتاج إلى هذا التطبيق ولا يمكن إزالته."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"إدارة تطبيقات مشرف الجهاز"</string>
+    <string name="manage_users" msgid="3125018886835668847">"إدارة حسابات المستخدمين"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"تعذرت إزالة <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"حدثت مشكلة أثناء تحليل الحزمة."</string>
+    <string name="newPerms" msgid="6039428254474104210">"جديد"</string>
+    <string name="allPerms" msgid="1024385515840703981">"الكل"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"الخصوصية"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"الدخول إلى الجهاز"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"لا يتطلب هذا التحديث أي أذونات جديدة."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"رفض"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"مزيد من المعلومات"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"الرفض على أي حال"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> من <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"‏هل توافق على منح &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; إذن <xliff:g id="ACTION">%2$s</xliff:g>؟"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"‏هل تريد السماح دائمًا للتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بهذا الإجراء: <xliff:g id="ACTION">%2$s</xliff:g>؟"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"أثناء استخدام التطبيق فقط"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"دائمًا"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"رفض وعدم طرح السؤال مرة أخرى"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> إذن غير مفعّل"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"كل الأذونات غير مفعّلة"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ليس هناك أذونات غير مفعّلة"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"سماح"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"التطبيقات"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"أذونات التطبيق"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"عدم السؤال مرة أخرى"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"ما مِن أذونات"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"أذونات إضافية"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"فتح معلومات التطبيق"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+      <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> أذونات أخرى</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> إذنًا آخر</item>
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"‏تم تصميم هذا التطبيق لإصدار قديم من Android. وقد يؤدي رفض الإذن إلى عدم العمل على النحو المطلوب مرة أخرى."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"تنفيذ إجراء غير معروف"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"تم السماح لـ <xliff:g id="COUNT_0">%1$d</xliff:g> من أصل <xliff:g id="COUNT_1">%2$d</xliff:g> تطبيق"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"عرض النظام"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"إخفاء النظام"</string>
+    <string name="no_apps" msgid="1965493419005012569">"ليس هناك أي تطبيقات"</string>
+    <string name="location_settings" msgid="1774875730854491297">"إعدادات الموقع"</string>
+    <string name="location_warning" msgid="8778701356292735971">"يعد <xliff:g id="APP_NAME">%1$s</xliff:g> أحد مقدمي خدمات الموقع لهذا الجهاز. يمكن تعديل إمكانية الوصول إلى الموقع من إعدادات الموقع."</string>
+    <string name="system_warning" msgid="7103819124542305179">"في حال رفض هذا الإذن، قد لا تعمل ميزات أساسية في جهازك على النحو المنشود."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"فرضته إحدى السياسات"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"تمّ إيقاف الوصول إلى الخلفية بواسطة السياسة."</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"تمّ تفعيل الوصول إلى الخلفية بواسطة السياسة."</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"تمّ تفعيل الوصول إلى المقدمة بواسطة السياسة."</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"إعدادات يتحكم فيها المشرف"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"دائمًا"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"أثناء استخدام التطبيق فقط"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"أبدًا"</string>
+    <string name="loading" msgid="7811651799620593731">"جارٍ التحميل..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"كل الأذونات"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"إمكانات التطبيق الأخرى"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"طلب الإذن"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"تم اكتشاف طبقة متراكبة للشاشة"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"لتغيير إعداد هذا الإذن، يتعين عليك أولاً إيقاف الطبقة المتراكبة للشاشة من الإعدادات &gt; التطبيقات"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"فتح الإعدادات"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"‏لا تتوافق إجراءات التثبيت/إلغاء التثبيت مع نظام Android Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"‏اختيار ما تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إليه"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"‏تم تحديث &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;. عليك اختيار ما تريد السماح لهذا التطبيق بالوصول إليه."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"إلغاء"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"متابعة"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"الأذونات الجديدة"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"الأذونات الحالية"</string>
+    <string name="message_staging" msgid="6151794817691100003">"جارٍ الطرح المرحلي للتطبيق…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"غير معروف"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"لأغراض الأمان، غير مسموح لجهازك اللوحي بتثبيت تطبيقات غير معروفة من هذا المصدر."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"لأغراض الأمان، غير مسموح لجهاز التلفزيون الذي تستخدمه بتثبيت تطبيقات غير معروفة من هذا المصدر."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"لأغراض الأمان، غير مسموح لهاتفك بتثبيت تطبيقات غير معروفة من هذا المصدر."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"يعتبر الهاتف والبيانات الشخصية أكثر عرضة لهجوم التطبيقات غير المعروفة. من خلال تثبيت هذا التطبيق، توافق على تحمل مسؤولية أي ضرر يحدث لهاتفك أو فقدان البيانات الذي قد ينتج عن استخدامه."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"يعتبر الجهاز اللوحي والبيانات الشخصية أكثر عرضة لهجوم التطبيقات غير المعروفة. من خلال تثبيت هذا التطبيق، توافق على تحمل مسؤولية أي ضرر يحدث للجهاز اللوحي أو فقدان البيانات الذي قد ينتج عن استخدامه."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"يعتبر جهاز التلفزيون والبيانات الشخصية أكثر عرضة لهجوم التطبيقات غير المعروفة. من خلال تثبيت هذا التطبيق، توافق على تحمل مسؤولية أي ضرر يحدث لجهاز التلفزيون أو فقدان البيانات الذي قد ينتج عن استخدامه."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"متابعة"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"الإعدادات"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"‏تثبيت / إلغاء تثبيت تطبيقات Android Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-as-television/strings.xml b/packages/PackageInstaller/res/values-as-television/strings.xml
new file mode 100644
index 0000000..2aaae1e
--- /dev/null
+++ b/packages/PackageInstaller/res/values-as-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"অস্বীকাৰ কৰক আৰু পুনৰাই নুসুধিব"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"আপুনি ইয়াক পিছত ছেটিংসমূহ &gt; এপসমূহ-লৈ গৈ সলনি কৰিব পাৰিব"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"ছিষ্টেম এপসমূহ দেখুৱাওক"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"এপৰ অনুমতিসমূহ"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"এপৰ অনুমতিসমূহ"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> অনুমতিসমূহ"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"অতিৰিক্ত অনুমতিসমূহ"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> অনুমতিসমূহ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-as-watch/strings.xml b/packages/PackageInstaller/res/values-as-watch/strings.xml
new file mode 100644
index 0000000..3889fc4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-as-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"অস্বীকাৰ কৰক আৰু পুনৰাই নুসুধিব"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"ছিষ্টেম এপসমূহ দেখুৱাওক"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"সলনি কৰিব নোৱাৰি"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"হয়"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"বাতিল কৰক"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-as/strings.xml b/packages/PackageInstaller/res/values-as/strings.xml
new file mode 100644
index 0000000..de2f2d6
--- /dev/null
+++ b/packages/PackageInstaller/res/values-as/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"পেকেজ ইনষ্টলাৰ"</string>
+    <string name="next" msgid="3057143178373252333">"পৰৱৰ্তী"</string>
+    <string name="install" msgid="5896438203900042068">"ইনষ্টল কৰক"</string>
+    <string name="done" msgid="3889387558374211719">"সম্পন্ন হ\'ল"</string>
+    <string name="cancel" msgid="8360346460165114585">"বাতিল কৰক"</string>
+    <string name="installing" msgid="8613631001631998372">"ইনষ্টল কৰি থকা হৈছে…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ইনষ্টল কৰি থকা হৈছে…"</string>
+    <string name="install_done" msgid="3682715442154357097">"এপ্ ইনষ্টল কৰা হ\'ল।"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"আপুনি এই এপ্লিকেশ্বন ইনষ্টল কৰিব বিচাৰেনে? ই এইবোৰ ব্যৱহাৰ কৰিব পাৰিব:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"আপুনি এই এপ্লিকেশ্বন ইনষ্টল কৰিব বিচাৰেনে? ইয়াক ব্য়ৱহাৰ সম্পৰ্কীয় কোনো অনুমতিৰ প্ৰয়োজন নাই।"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"আপুনি পূর্বৰে পৰা থকা এপ্লিকেশ্বন আপডেট কৰিব বিচাৰেনে? আপুনি কোনো পুৰণি ডেটা নেহেৰুৱাই। আপডেট হোৱা এপ্লিকেশ্বনে এইবোৰ ব্যৱহাৰ কৰিব পাৰিব:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"আপুনি এই অন্তনির্মিত এপ্লিকেশ্বন আপডেট কৰিব বিচাৰেনে? আপুনি কোনো পুৰণি ডেটা নেহেৰুৱাই। আপডেট হোৱা এপ্লিকেশ্বনে এইবোৰ ব্যৱহাৰ কৰিব পাৰিব:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"আপুনি পূর্বৰে পৰা থকা এপ্লিকেশ্বন আপডেট কৰিব বিচাৰেনে? আপুনি কোনো পুৰণি ডেটা নেহেৰুৱাব। ব্যৱহাৰৰ বাবে ইয়াক কোনো বিশেষ অনুমতিৰ প্ৰয়োজন নাই৷"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"আপুনি এই অন্তনির্মিত এপ্লিকেশ্বন আপডেট কৰিব বিচাৰেনে? আপুনি নিজৰ পুৰণি ডেটা নেহেৰুৱাব৷ ব্যৱহাৰৰ বাবে ইয়াক কোনো বিশেষ অনুমতিৰ প্ৰয়োজন নাই৷"</string>
+    <string name="install_failed" msgid="6579998651498970899">"এপ্ ইনষ্টল কৰা হোৱা নাই।"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"পেকেজটোৰ ইনষ্টল অৱৰোধ কৰা হৈছে।"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"এপটো ইনষ্টল কৰিব পৰা নহ\'ল কাৰণ ইয়াৰ পেকেজ আৰু পূর্বৰে পৰা উপলব্ধ পেকেজৰ মাজত সমস্যাৰ সৃষ্টি হৈছে।"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"আপোনাৰ টেবলেটৰ সৈতে মিল নথকাৰ বাবে এপটো ইনষ্টল নহ\'ল।"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"আপোনাৰ টিভিত এই এপ্ চলিব নোৱাৰে।"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"আপোনাৰ ফ\'নৰ সৈতে মিল নথকাৰ বাবে এপটো ইনষ্টল নহ\'ল।"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"পেকেজ মান্য নোহোৱাৰ বাবে এপটো ইনষ্টল নহ\'ল।"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক আপোনাৰ টে\'বলেটত ইনষ্টল কৰিব পৰা নগ\'ল৷"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"আপোনাৰ টিভিত <xliff:g id="APP_NAME">%1$s</xliff:g> ইনষ্টল কৰিব পৰা নগ\'ল।"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক আপোনাৰ ফ\'নত ইনষ্টল কৰিব পৰা নগ\'ল৷"</string>
+    <string name="launch" msgid="4826921505917605463">"খোলক"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"আপোনাৰ প্ৰশাসকে অজ্ঞাত উৎসৰ পৰা লাভ কৰা এপ্ ইনষ্টল কৰাৰ অনুমতি দিয়া নাই"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"এই ব্যৱহাৰকাৰীয়ে অজ্ঞাত উৎসৰপৰা লাভ কৰা এপসমূহ ইনষ্টল কৰিব নোৱাৰে"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"এই ব্যৱহাৰকাৰীক এপ্ ইনষ্টল কৰিবলৈ অনুমতি দিয়া হোৱা নাই"</string>
+    <string name="ok" msgid="3468756155452870475">"ঠিক আছে"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"এপসমূহ পৰিচালনা কৰক"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"পৰ্যাপ্ত খালী ঠাই নাই"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক ইনষ্টল কৰিব পৰা নগ\'ল। কিছু খালী ঠাই উলিয়াই পুনৰ চেষ্টা কৰক৷"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"এপ্ পোৱা নগ\'ল"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ইনষ্টল হৈ থকা এপসমূহৰ তালিকাত এই এপটো পোৱা নগ\'ল।"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"অনুমতি দিয়া হোৱা নাই"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"বর্তমানৰ ব্যৱহাৰকাৰীক আনইনষ্টল কৰিবলৈ অনুমতি দিয়া হোৱা নাই।"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"আসোঁৱাহ"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"এপ্ আনইনষ্টল কৰিব পৰা নাযাব।"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"এপ্ আনইনষ্টল কৰক"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"আপডেট আনইনষ্টল কৰক"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> হৈছে তলৰ এপটোৰ এটা অংশ:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"আপুনি এই এপটো আনইনষ্টল কৰিব বিচাৰেনে?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"আপুনি "<b>"সকলো"</b>" ব্যৱহাৰকাৰীৰ বাবে এই এপটো আনইনষ্টল কৰিবলৈ বিচাৰেনে? এপ্লিকেশ্বন আৰু ইয়াৰ ডেটাক ডিভাইচটোত থকা "<b>"সকলো"</b>" ব্যৱহাৰকাৰীৰ পৰা আঁতৰোৱা হ\'ব৷"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"আপুনি ব্যৱহাৰকাৰী <xliff:g id="USERNAME">%1$s</xliff:g>ৰ বাবে এই এপটো আনইনষ্টল কৰিব বিচাৰেনে?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"এই এপটো ফেক্টৰী সংস্কৰণৰ সৈতে সলনি কৰিব বিচাৰেনে? সকলো তথ্য় মচা হ\'ব।"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"এই এপটো ফেক্টৰী সংস্কৰণৰ সৈতে সলনি কৰিব বিচাৰেনে? সকলো তথ্য় মচা হ\'ব। ইয়াৰ প্ৰভাৱ কার্মস্থানৰ প্ৰফাইল থকা ডিভাইচটোৰ ব্য়ৱহাৰকাৰীসকলৰ লগতে অইন সকলো ব্য়ৱহাৰকাৰীৰ ওপৰতো পৰিব।"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"আনইনষ্টল হৈ থকা বস্তুবোৰ"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"আনইনষ্টল কৰিব নোৱাৰা বস্তুবোৰ"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"আনইনষ্টল কৰি থকা হৈছে…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ক আনইনষ্টল কৰি থকা হৈছে…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"আনইনষ্টল কাৰ্যটো সমাপ্ত হ\'ল৷"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনষ্টল কৰা হ\'ল"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"আনইনষ্টল কৰিব পৰা নগ\'ল।"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ক আনইনষ্টল কৰিব পৰা নগ\'ল।"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"ডিভাইচৰ সক্ৰিয় প্ৰশাসক এপ্ আনইনষ্টল কৰিব নোৱাৰি"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g>ৰ সক্ৰিয় ডিভাইচৰ প্ৰশাসকীয় এপ্ আনইনষ্টল কৰিব নোৱাৰি"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"এই এপটো কিছুসংখ্য়ক ব্যৱহাৰকাৰী বা প্ৰ\'ফাইলৰ বাবে প্ৰয়োজনীয় আৰু বাকীসকলৰ বাবে ইয়াক আনইনষ্টল কৰা হৈছে"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"আপোনাৰ প্ৰ\'ফাইলৰ বাবে এই এপৰ প্ৰয়োজন আছে গতিকে আনইনষ্টল কৰিব পৰা নাযায়।"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"আপোনাৰ ডিভাইচৰ প্ৰশাসকে এই এপটো ৰখাটো বাধ্যতামূলক কৰি ৰাখিছে, গতিকে ইয়াক আনইনষ্টল কৰিব পৰা নাযায়।"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"ডিভাইচৰ প্ৰশাসকীয় এপসমূহ পৰিচালনা কৰক"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ব্য়ৱহাৰকাৰীসকলক পৰিচালনা কৰক"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক আনইনষ্টল কৰিব নোৱাৰি৷"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"পেকেজটো পাৰ্ছ কৰোঁতে এটা সমস্যাই দেখা দিছিল।"</string>
+    <string name="newPerms" msgid="6039428254474104210">"নতুন"</string>
+    <string name="allPerms" msgid="1024385515840703981">"সকলো"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"গোপনীয়তা"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"ডিভাইচৰ ব্যৱহাৰ"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"এই আপডেটক কোনো নতুন অনুমতিৰ প্ৰয়োজন নাই।"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"প্ৰত্যাখ্যান কৰক"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"অধিক তথ্য"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"যিহ\'লেও অস্বীকাৰ কৰক"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>ৰ ভিতৰত<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>টা"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক <xliff:g id="ACTION">%2$s</xliff:g>ৰ বাবে অনুমতি দিবনে?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক সদায় <xliff:g id="ACTION">%2$s</xliff:g> কৰাৰ অনুমতি দিবনে?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"এপ্ ব্য়ৱহাৰ কৰি থাকোঁতে মাত্ৰ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"সদায়"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"অস্বীকাৰ কৰক আৰু পুনৰাই নুসুধিব"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g>টা অক্ষম কৰা হ\'ল"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"সকলো অক্ষম কৰা হ\'ল"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"একো অক্ষম কৰা হোৱা নাই"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"অনুমতি দিয়ক"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"এপসমূহ"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"এপক দিয়া অনুমতিসমূহ"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"পুনৰাই নুসুধিব"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"কোনো অনুমতি নাই"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"অতিৰিক্ত অনুমতিসমূহ"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"এপৰ তথ্য় খোলক"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"এই এপটো Androidৰ এটা পুৰণা সংস্কৰণৰ বাবে প্ৰস্তুত কৰা হৈছিল। অনুমতি নিদিলে ই বিচৰাধৰণে কাম নকৰিবও পাৰে।"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"অজ্ঞাত কাৰ্য কৰিব পাৰে"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g>ৰ ভিতৰত<xliff:g id="COUNT_0">%1$d</xliff:g>টা এপক অনুমতি দিয়া হৈছে"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"ছিষ্টেম দেখুৱাওক"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"ছিষ্টেম লুকুৱাওক"</string>
+    <string name="no_apps" msgid="1965493419005012569">"কোনো এপে এই অনুমতি বিচৰা নাই"</string>
+    <string name="location_settings" msgid="1774875730854491297">"অৱস্থান ছেটিংসমূহ"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> এই ডিভাইচৰ অৱস্থান সেৱা প্ৰদানকাৰী। অৱস্থানৰ ছেটিংসমূহত অৱস্থানৰ ব্যৱহাৰ সংশোধন কৰিব পাৰি।"</string>
+    <string name="system_warning" msgid="7103819124542305179">"আপুনি যদি এই অনুমতি প্ৰদান নকৰে, তেন্তে আপোনাৰ ডিভাইচৰ মৌলিক সুবিধাসমূহে বিচৰাধৰণে কাম নকৰিবও পাৰে।"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"নীতিৰ যোগেদি বলৱৎ কৰা"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"নীতি অনুসৰি নেপথ্য় চোৱা সুবিধা অক্ষম কৰা হ’ল"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"নীতি অনুসৰি নেপথ্য় চোৱা সুবিধা সক্ষম কৰা হ’ল"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"নীতি অনুসৰি অগ্ৰভূমি চোৱা সুবিধা সক্ষম কৰা হ’ল"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"প্ৰশাসকে নিয়ন্ত্ৰিত কৰা"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"সদায়"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"এপ্ ব্য়ৱহাৰ কৰি থাকোঁতে মাত্ৰ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"কেতিয়াও নহয়"</string>
+    <string name="loading" msgid="7811651799620593731">"ল\'ড কৰি থকা হৈছে…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"সকলো অনুমতি"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"অন্য এপৰ কার্যক্ষমতাসমূহ"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"অনুমতি বিচাৰি কৰা অনুৰোধ"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"স্ক্ৰীণ অভাৰলে\' চিনাক্ত কৰা হৈছে"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"এই অনুমতিৰ ছেটিং সলনি কৰিবলৈ আপুনি প্ৰথমে ছেটিংসমূহ &gt; এপসমূহ-লৈ গৈ স্ক্ৰীণ অভাৰলে\' অফ কৰিব লাগিব।"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"ছেটিংসমূহ খোলক"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android ৱেৰ"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"ইনষ্টল/আনইনষ্টল কাৰ্য Wearত কৰিব নোৱাৰি।"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক কি কিত প্ৰৱেশ কৰিবলৈ অনুমতি দিব বাছনি কৰক"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; আপডেট কৰা হৈছে। এই এপক কি কিত প্ৰৱেশ কৰিবলৈ অনুমতি দিব বাছনি কৰক।"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"বাতিল কৰক"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"অব্যাহত ৰাখক"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"নতুন অনুমতিসমূহ"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"এপে বর্তমান ব্যৱহাৰ কৰি থকা অনুমতিসমূহ"</string>
+    <string name="message_staging" msgid="6151794817691100003">"এপৰ অন্তিম পর্যায়ৰ পৰীক্ষণ চলি আছে…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"অজ্ঞাত"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"আপোনাৰ টেবলেটটো যাতে সুৰক্ষিত থাকে তাৰ বাবে আপোনাৰ টেবলেটটোক এই উৎসৰ পৰা অজ্ঞাত এপসমূহ ইনষ্টল কৰিবলৈ অনুমতি দিয়া হোৱা নাই।"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"আপোনাৰ টিভিটো যাতে সুৰক্ষিত থাকে তাৰ বাবে আপোনাৰ টিভিটোক এই উৎসৰ পৰা অজ্ঞাত এপসমূহ ইনষ্টল কৰিবলৈ অনুমতি দিয়া হোৱা নাই।"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"আপোনাৰ ফ\'নটো যাতে সুৰক্ষিত থাকে তাৰ বাবে আপোনাৰ ফ\'নটোক এই উৎসৰ পৰা অজ্ঞাত এপসমূহ ইনষ্টল কৰিবলৈ অনুমতি দিয়া হোৱা নাই।"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"আপোনাৰ টিভি আৰু ব্যক্তিগত ডেটা অজ্ঞাত এপৰ আক্ৰমণৰ বলি হোৱাৰ সম্ভাৱনা অধিক। এই এপটো ইনষ্টল কৰি আপুনি ইয়াক ব্যৱহাৰ কৰাৰ ফলত আপোনাৰ ফ\'নত কোনো ক্ষতি হ\'লে বা ডেটা হেৰুৱালে আপুনিয়েই দায়ী হ\'ব বুলি সন্মত।"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"আপোনাৰ টেবলেট আৰু ব্যক্তিগত ডেটা অজ্ঞাত এপৰ আক্ৰমণৰ বলি হোৱাৰ সম্ভাৱনা অধিক। এই এপটো ইনষ্টল কৰি আপুনি ইয়াক ব্যৱহাৰ কৰাৰ ফলত আপোনাৰ টেবলেটত কোনো ক্ষতি হ\'লে বা ডেটা হেৰুৱালে আপুনিয়েই দায়ী হ\'ব বুলি সন্মত।"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"আপোনাৰ টিভি আৰু ব্যক্তিগত ডেটা অজ্ঞাত এপৰ আক্ৰমণৰ বলি হোৱাৰ সম্ভাৱনা অধিক। এই এপটো ইনষ্টল কৰি আপুনি ইয়াক ব্যৱহাৰ কৰাৰ ফলত আপোনাৰ টিভিত কোনো ক্ষতি হ\'লে বা ডেটা হেৰুৱালে আপুনিয়েই দায়ী হ\'ব বুলি সন্মত।"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"অব্যাহত ৰাখক"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ছেটিংবোৰ"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"ৱেৰ এপসমূহ ইনষ্টল/আনইনষ্টল কৰি থকা হৈছে"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-az-television/strings.xml b/packages/PackageInstaller/res/values-az-television/strings.xml
new file mode 100644
index 0000000..92fa527
--- /dev/null
+++ b/packages/PackageInstaller/res/values-az-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Rədd edin və daha soruşmayın"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Bunu sonra Ayarlar vəTətbiqlər bölməsindən dəyişə bilərsiniz"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Sistem tətbiqlərini göstərin"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Tətbiq icazələri"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Tətbiq icazələri"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> icazələri"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Əlavə icazələr"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> icazələri"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-az-watch/strings.xml b/packages/PackageInstaller/res/values-az-watch/strings.xml
new file mode 100644
index 0000000..ef6723b
--- /dev/null
+++ b/packages/PackageInstaller/res/values-az-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Rədd edin, bir daha soruşmayın"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Sistem tətbiqlərini göstərin"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Dəyişdirilə bilməz"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Bəli"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Ləğv edin"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-az/strings.xml b/packages/PackageInstaller/res/values-az/strings.xml
new file mode 100644
index 0000000..d870887
--- /dev/null
+++ b/packages/PackageInstaller/res/values-az/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Paket quraşdırıcı"</string>
+    <string name="next" msgid="3057143178373252333">"Növbəti"</string>
+    <string name="install" msgid="5896438203900042068">"Quraşdır"</string>
+    <string name="done" msgid="3889387558374211719">"Hazırdır"</string>
+    <string name="cancel" msgid="8360346460165114585">"Ləğv et"</string>
+    <string name="installing" msgid="8613631001631998372">"Quraşdırılır..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> quraşdırılır…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Tətbiq quraşdırılıb."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Bu tətbiqi quraşdırmaq istəyirsiniz? Tətbiq buraya giriş əldə edəcək:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Bu tətbiqi quraşdırmaq istəyirsiniz? Hər hansı bir xüsusi keçid tələb etmir."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Bu cari tətbiq güncəllənməsini quraşdırmaq istəyirsiniz? Hazırki datanız itməyəcək. Güncəllənmiş tətbiq aşağıdakılara çıxış əldə edəcək:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Daxili tətbiqdən yenilənməni quraşdırmaq istəyirsiniz? Hazırki datanız itməyəcək. Yenilənmiş tətbiq aşağıdakılara çıxış əldə edəcək:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Bu cari tətbiq güncəllənməsini quraşdırmaq istəyirsiniz? Hazırki datanız itməyəcək. O, xüsusi giriş tələb etmir."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Bu daxili tətbiq güncəllənməsini quraşdırmaq istəyirsiniz? Hazırki datanız itməyəcək. O, xüsusi giriş tələb etmir."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Tətbiq quraşdırılmayıb."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Paket yüklənməyə qarşı blok edildi."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Bu paketin mövcud paket ilə ziddiyəti səbəbiylə tətbiq quraşdırılmadı."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Bu tətbiq planşetinizə uyğun gəlmədiyi üçün tətbiq quraşdırılmadı."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Bu proqram TV-nizlə uyğun gəlmir."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Bu tətbiq telefonunuza uyğun gəlmədiyi üçün tətbiq quraşdırılmadı."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Paket yanlış kimi göründüyü üçün tətbiq quraşdırılmadı."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> planşetinizə yüklənə bilmədi."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> proqramını TV-nizdə quraşdırmaq mümkün olmadı."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> telefonunuza quraşdırıla bilmədi."</string>
+    <string name="launch" msgid="4826921505917605463">"Aç"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Naməlum mənbələrdən əldə edilmiş tətbiqlərin quraşdırılmasına admin tərəfindən icazə verilmir"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Naməlum tətbiqlər bu istifadəçi tərəfindən quraşdırıla bilməz"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Bu istifadəçinin tətbiqi quraşdırmaq üçün icazəsi yoxdur"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Tətbiqləri idarə et"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Boş yer yoxdur"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> quraşdırıla bilməz. Yaddaş üçün yer boşaldıb yenidən təkrar edin."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Tətbiq tapılmadı"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Tətbiq quraşdırılmış tətbiqlər siyahısında tapılmadı."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"İcazə verilmir"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Cari istifadəçiyə bu silinməni həyata keçirməyə icazə verilmir."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Xəta"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Tətbiq sistemdən silinmədi."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Tətbiqi qaldır"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Güncəlləməni sil"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> bu tətbiqin hissəsidir:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Bu tətbiqi aradan qaldırmaq istəyirsiniz mi?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Bu tətbiqi "<b>"bütün"</b>" istifadəçilər üçün silmək istəyirsiz? Tətbiq və onun datası cihazdakı "<b>"bütün"</b>" istifadəçilər üçün silinəcək."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"<xliff:g id="USERNAME">%1$s</xliff:g> adlı istifadəçi üçün bu tətbiqi sistemdən silmək istəyirsiniz?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Tətbiq zavod versiyası ilə əvəz olunsun? Bütün data silinəcək."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Tətbiq zavod versiyası ilə əvəz olunsun? Bütün data silinəcək. Bu, iş profilləri olanlar da daxil olmaqla bu cihazın bütün istifadəçilərinə təsir edir."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"İşləyən sistemlər silinmələr"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Uğursuz olan sistemlər silinmələr"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Silinir..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sistemdən silinir…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Sistemdən silmə tamamlandı."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sistemdən silindi"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Aradan qaldırılma uğursuz oldu."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sistemdən silinməsi uğursuz oldu."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Aktiv cihaz admin tətbiqini sistemdən silmək mümkün olmadı"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> üçün aktiv cihaz admin tətbiqini sistemdən silmək mümkün olmadı"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Bu tətbiq bəzi istifadəçi və profillər tərəfindən tələb olunur və digərləri üçün silinib"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Bu tətbiq profil üçün tələb olunur və silinə bilməz."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Bu tətbiq cihaz administratoru tərəfindən tələb olunur və sistemdən silinə bilməz."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Cihaz admin tətbiqlərini idarə edin"</string>
+    <string name="manage_users" msgid="3125018886835668847">"İstifadəçiləri idarə edin"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> sistemdən silinə bilməz."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Paketin təhlilində problem var idi."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Yeni"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Hamısı"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Məxfilik"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Qurğu icazəsi"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Bu güncəllənmə heç bir icazə istəmir"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Rədd edin"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Daha ətraflı"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Hər bir halda rədd edin"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> icazədən <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> ədəd"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə <xliff:g id="ACTION">%2$s</xliff:g> fəaliyyəti üçün icazə verilsin?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin <xliff:g id="ACTION">%2$s</xliff:g> əməliyyatına daima icazə verilsin?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Ancaq tətbiq istifadəsi zamanı"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Həmişə"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Rədd edin və daha soruşmayın"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> deaktiv edildi"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"hamısı deaktiv edildi"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"heç biri deaktiv edilmədi"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"İcazə verin"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Tətbiqlər"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Tətbiq icazələri"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Bir daha soruşmayın"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"İcazə yoxdur"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Əlavə icazələr"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Tətbiq məlumatını açın"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other">daha <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">daha <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Bu tətbiq köhnə Android versiyası üçün nəzərdə tutulub. İcazəni rədd etmək onun lazımi şəkildə işləməməsinə səbəb ola bilər."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"naməlum əməliyyat etmək"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g> tətbiqdən <xliff:g id="COUNT_0">%1$d</xliff:g> ədədinə icazə var"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Sistemi göstərin"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Sistemi gizlədin"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Tətbiq yoxdur"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Məkan Ayarları"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu cihaz üçün məkan xidmətləri təminatçısıdır. Məkana giriş məkan ayarlarından dəyişdirilə bilər."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Bu icazəni rədd etsəniz, cihazınızın əsas funksiyaları lazımi qaydada işləməyə bilər."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Siyasət tərəfindən tətbiq olunur"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Arxa fon girişi siyasətə əsasən deaktiv edildi"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Arxa fon girişi siyasətə əsasən aktiv edildi"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Ön fon girişi siyasətə əsasən aktiv edildi"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Admin tərəfindən nəzarət olunur"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Həmişə"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Ancaq tətbiq istifadəsi zamanı"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Heç vaxt"</string>
+    <string name="loading" msgid="7811651799620593731">"Yüklənir…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Bütün icazələr"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Digər tətbiq imkanları"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"İcazə sorğusu"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Ekran örtüyü aşkarlandı"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Bu icazə ayarını dəyişdirmək üçün əvvəldə Ayarlar və Tətbiqlər bölməsindən ekran örtüyünü söndürməlisiniz"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Ayarları açın"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Yükləmə/Silmə fəaliyyətləri Wear\'də dəstəklənmir."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin giriş hüququnu seçin"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqi güncəlləndi. Bu tətbiqin giriş hüququnu seçin."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Ləğv edin"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Davam edin"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Yeni icazələr"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Cari icazələr"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Tətbiq hazırlanır..."</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Naməlum"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Təhlükəsizliyiniz üçün planşetə bu mənbədən olan naməlum tətbiqləri quraşdırmağa icazə verilmir."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Təhlükəsizliyiniz üçün TV-yə bu mənbədən olan naməlum tətbiqləri quraşdırmağa icazə verilmir."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Təhlükəsizliyiniz üçün telefona bu mənbədən olan naməlum tətbiqləri quraşdırmağa icazə verilmir."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefon və şəxsi data naməlum tətbiqlərin hücumuna qarşı daha həssasdır. Bu tətbiqi quraşdırmaqla telefona dəyə biləcək zərər və ya onun istifadəsi nəticəsində baş verən data itkisinə görə məsuliyyət daşıdığınızı qəbul edirsiniz."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Planşet və şəxsi data naməlum tətbiqlərin hücumuna qarşı daha həssasdır. Bu tətbiqi quraşdırmaqla planşetə dəyə biləcək zərər və ya onun istifadəsi nəticəsində baş verə biləcək data itkisinə görə məsuliyyət daşıdığınızı qəbul edirsiniz."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Tv və şəxsi data naməlum tətbiqlərin hücumuna qarşı daha həssasdır. Bu tətbiqi quraşdırmaqla Tv\'ə dəyə biləcək zərər və ya onun istifadəsi nəticəsində baş verən data itkisinə görə məsuliyyət daşıdığınızı qəbul edirsiniz."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Davam edin"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Ayarlar"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear tətbiqləri quraşdırılır/silinir"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-b+sr+Latn-television/strings.xml b/packages/PackageInstaller/res/values-b+sr+Latn-television/strings.xml
new file mode 100644
index 0000000..5dce759
--- /dev/null
+++ b/packages/PackageInstaller/res/values-b+sr+Latn-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Odbij i ne pitaj ponovo"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Ovo možete da promenite kasnije u Podešavanjima &gt; Aplikacije"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Prikaži sistemske aplikacije"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Dozvole za aplikacije"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Dozvole za aplikacije"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Dozvole za aplikaciju <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Dodatne dozvole"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Dozvole za aplikaciju <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-b+sr+Latn-watch/strings.xml b/packages/PackageInstaller/res/values-b+sr+Latn-watch/strings.xml
new file mode 100644
index 0000000..63a44db
--- /dev/null
+++ b/packages/PackageInstaller/res/values-b+sr+Latn-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Odbij i ne pitaj ponovo"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Prikaži sistemske aplikacije"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ne može da se promeni"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Da"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Otkaži"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..4d8772f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Upakovani program za instalaciju"</string>
+    <string name="next" msgid="3057143178373252333">"Dalje"</string>
+    <string name="install" msgid="5896438203900042068">"Instaliraj"</string>
+    <string name="done" msgid="3889387558374211719">"Gotovo"</string>
+    <string name="cancel" msgid="8360346460165114585">"Otkaži"</string>
+    <string name="installing" msgid="8613631001631998372">"Instaliranje..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instalira se <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikacija je instalirana."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Želite li da instalirate ovu aplikaciju? Imaće pristup sledećem:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Želite li da instalirate ovu aplikaciju? Ne zahteva poseban pristup."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Želite li da instalirate ažuriranje za ovu postojeću aplikaciju? Postojeći podaci neće biti izgubljeni. Ažurirana aplikacija imaće pristup sledećem:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Želite li da instalirate ažuriranje za ovu ugrađenu aplikaciju? Postojeći podaci neće biti izgubljeni. Ažurirana aplikacija će imati pristup sledećem:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Da li želite da instalirate ažuriranje ove postojeće aplikacije? Postojeći podaci neće biti izgubljeni. Nije potreban poseban pristup."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Da li želite da instalirate ažuriranje ove ugrađene aplikacije? Postojeći podaci neće biti izgubljeni. Nije potreban poseban pristup."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplikacija nije instalirana."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Instaliranje paketa je blokirano."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplikacija nije instalirana jer je paket neusaglašen sa postojećim paketom."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplikacija nije instalirana jer nije kompatibilna sa tabletom."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Ova aplikacija nije kompatibilna sa TV-om."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplikacija nije instalirana jer nije kompatibilna sa telefonom."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplikacija nije instalirana jer je paket nevažeći."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Nije moguće instalirati aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> na tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Nismo uspeli da instaliramo <xliff:g id="APP_NAME">%1$s</xliff:g> na TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Nije moguće instalirati aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> na telefon."</string>
+    <string name="launch" msgid="4826921505917605463">"Otvori"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Administrator ne dozvoljava instaliranje aplikacija dobijenih iz nepoznatih izvora"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Ovaj korisnik ne može da instalira nepoznate aplikacije"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Ovom korisniku nije dozvoljeno da instalira aplikacije"</string>
+    <string name="ok" msgid="3468756155452870475">"Potvrdi"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Upravljanje aplikacijama"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nema više mesta"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Nije moguće instalirati aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>. Oslobodite dodatni prostor i pokušajte ponovo."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplikacija nije pronađena"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplikacija nije pronađena na listi instaliranih aplikacija."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Nije dozvoljeno"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Aktuelnom korisniku nije dozvoljeno da obavi ovo deinstaliranje."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Greška"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Deinstaliranje aplikacije nije uspelo."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Deinstaliranje aplikacije"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Deinstaliranje ažuriranja"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je deo sledeće aplikacije:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Da li želite da deinstalirate ovu aplikaciju?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Da li želite da deinstalirate ovu aplikaciju za "<b>"sve"</b>" korisnike? Aplikacija i podaci koji se na nju odnose biće uklonjeni za "<b>"sve"</b>" korisnike ovog uređaja."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Želite li da deinstalirate ovu aplikaciju za korisnika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Želite li da zamenite ovu aplikaciju fabričkom verzijom? Svi podaci će biti uklonjeni."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Želite li da zamenite ovu aplikaciju fabričkom verzijom? Svi podaci će biti uklonjeni. Ovo utiče na sve korisnike ovog uređaja, uključujući i one sa profilima za Work."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Aktivna deinstaliranja"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Neuspela deinstaliranja"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Deinstaliranje..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> se deinstalira…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Deinstaliranje je završeno."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je deinstalirana"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Deinstaliranje nije uspelo."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Deinstaliranje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nije uspelo."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Ne možete da deinstalirate aplikaciju za aktivnog administratora uređaja"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Ne možete da deinstalirate aplikaciju za aktivnog administratora uređaja za <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Ova aplikacija je potrebna za neke korisnike ili profile, a deinstalirana je za druge"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ova aplikacija je potrebna za vaš profil i ne može da se deinstalira."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ova aplikacija je potrebna administratoru uređaja i ne može da se deinstalira."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Upravljaj aplikacijama za administratore uređaja"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Upravljaj korisnicima"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Nije moguće deinstalirati aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Došlo je do problema pri raščlanjivanju paketa."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Novo"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Sve"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privatnost"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Pristup uređaju"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Ovo ažuriranje ne zahteva nove dozvole."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Odbaci"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Više informacija"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Ipak odbij"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>. od <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Želite li da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Želite li uvek da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Samo dok se aplikacija koristi"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Uvek"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Odbij i ne pitaj ponovo"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"Onemogućenih: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"sve su onemogućene"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"nijedna nije onemogućena"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Dozvoli"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikacije"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Dozvole za aplikacije"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ne pitaj ponovo"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Nema dozvola"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Dodatne dozvole"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Otvori informacije o aplikaciji"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one">još <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">još <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">još <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ova aplikacija je dizajnirana za stariju verziju Android-a. Ako odbijete dozvolu, ona možda više neće pravilno da funkcioniše."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"obavlja nepoznatu radnju"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> od <xliff:g id="COUNT_1">%2$d</xliff:g> aplikacija ima dozvolu"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Prikaži sistemske"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Sakrij sistemske"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nema aplikacija"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Podešavanja lokacije"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> pruža usluge lokacije za ovaj uređaj. Pristup lokaciji možete da izmenite u podešavanjima lokacije."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ako odbijete ovu dozvolu, osnovne funkcije uređaja možda neće više funkcionisati ispravno."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Primenjuje se u skladu sa smernicama"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Pristup u pozadini je onemogućen smernicama"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Pristup u pozadini je omogućen smernicama"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Pristup u prvom planu je omogućen smernicama"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Kontroliše administrator"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Uvek"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Samo dok se aplikacija koristi"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nikada"</string>
+    <string name="loading" msgid="7811651799620593731">"Učitava se…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Sve dozvole"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Ostale mogućnosti aplikacije"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Zahtev za dozvolu"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Otkriven je element koji prekriva sadržaj ekrana"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Da biste promenili podešavanje ove dozvole, prvo treba da isključite element koji prekriva sadržaj ekrana u odeljku Podešavanja &gt; Aplikacije"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Otvori podešavanja"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Radnje Instaliraj/Deinstaliraj nisu podržane u Wear-u."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Izaberite čemu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; može da pristupa"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; je ažurirana. Izaberite čemu ova aplikacija može da pristupa."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Otkaži"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Nastavi"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nove dozvole"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Aktuelne dozvole"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Aplikacija se priprema…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Nepoznato"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Tabletu iz bezbednosnih razloga nije dozvoljeno da instalira nepoznate aplikacije iz ovog izvora."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Televizoru iz bezbednosnih razloga nije dozvoljeno da instalira nepoznate aplikacije iz ovog izvora."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Telefonu iz bezbednosnih razloga nije dozvoljeno da instalira nepoznate aplikacije iz ovog izvora."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefon i lični podaci su podložniji napadu nepoznatih aplikacija. Ako instalirate ovu aplikaciju, prihvatate da ste odgovorni za eventualna oštećenja telefona ili gubitak podataka do kojih može da dođe zbog njenog korišćenja."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tablet i lični podaci su podložniji napadu nepoznatih aplikacija. Ako instalirate ovu aplikaciju, prihvatate da ste odgovorni za eventualna oštećenja tableta ili gubitak podataka do kojih može da dođe zbog njenog korišćenja."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"TV i lični podaci su podložniji napadu nepoznatih aplikacija. Ako instalirate ovu aplikaciju, prihvatate da ste odgovorni za eventualna oštećenja TV-a ili gubitak podataka do kojih može da dođe zbog njenog korišćenja."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Nastavi"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Podešavanja"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instaliranje/deinstaliranje Wear aplikacija"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-be-television/strings.xml b/packages/PackageInstaller/res/values-be-television/strings.xml
new file mode 100644
index 0000000..befb367
--- /dev/null
+++ b/packages/PackageInstaller/res/values-be-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Адхіліць і больш не пытацца"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Пазней гэта можна змянiць у раздзеле «Налады &gt; Праграмы»"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Паказваць сістэмныя праграмы"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Дазволы праграм"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Дазволы праграм"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Дазволы праграмы <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Дадатковыя дазволы"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Дазволы праграмы <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-be-watch/strings.xml b/packages/PackageInstaller/res/values-be-watch/strings.xml
new file mode 100644
index 0000000..99b2ce8a
--- /dev/null
+++ b/packages/PackageInstaller/res/values-be-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Адхіліць, больш не пытацца"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Паказваць сістэмныя праграмы"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Нельга змяніць"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Так"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Скасаваць"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-be/strings.xml b/packages/PackageInstaller/res/values-be/strings.xml
new file mode 100644
index 0000000..1b65e29
--- /dev/null
+++ b/packages/PackageInstaller/res/values-be/strings.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Усталёўшчык пакетаў"</string>
+    <string name="next" msgid="3057143178373252333">"Далей"</string>
+    <string name="install" msgid="5896438203900042068">"Усталяваць"</string>
+    <string name="done" msgid="3889387558374211719">"Гатова"</string>
+    <string name="cancel" msgid="8360346460165114585">"Скасаваць"</string>
+    <string name="installing" msgid="8613631001631998372">"Усталяванне..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Ідзе ўсталяванне <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Прыкладанне ўсталявана."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Усталяваць гэта прыкладанне? Яно атрымае доступ да:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Усталяваць гэта прыкладанне? Яно не патрабуе спецыяльнага доступу."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Усталяваць абнаўленне для гэтага існуючага прыкладання? Існуючыя дадзеныя не будуць страчаны. Абноўленае прыкладанне атрымае доступ да:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Усталяваць абнаўленне для гэтага ўбудаванага прыкладання? Існуючыя дадзеныя не будуць страчаны. Абноўленае прыкладанне атрымае доступ да:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Усталяваць абнаўленне для гэтага прыкладання? Вашы iснуючыя дадзеныя не будуць згублены. Спецыяльны доступ не патрабуецца."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Усталяваць абнаўленне для гэтага ўбудаванага прыкладання? Вашы iснуючыя дадзеныя не будуць згублены. Спецыяльны доступ не патрабуецца."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Прыкладанне не ўсталявана."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Для пакета заблакіравана магчымасць усталявання."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Праграма не ўсталявана, таму што пакет канфліктуе з існуючым пакетам."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Праграма не ўсталявана, таму што яна несумяшчальная з вашым планшэтам."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Гэта праграма несумяшчальная з вашым тэлевізарам."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Праграма не ўсталявана, таму што яна несумяшчальная з вашым тэлефонам."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Праграма не ўсталявана, таму што пакет, магчыма, з\'яўляецца несапраўдным."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"На гэтым планшэце немагчыма ўсталяваць прыкладанне <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"На вашым тэлевізары немагчыма ўсталяваць праграму <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"На гэтым тэлефоне немагчыма ўсталяваць прыкладанне <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="launch" msgid="4826921505917605463">"Адкрыць"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Ваш адміністратар не дазваляе ўсталёўку праграм з невядомых крыніц."</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Гэты карыстальнік не можа ўсталёўваць невядомыя праграмы"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Гэты карыстальнік не можа ўсталёўваць праграмы"</string>
+    <string name="ok" msgid="3468756155452870475">"ОК"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Кіраванне прыкладаннямі"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Не хапае месца"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Немагчыма ўсталяваць прыкладанне <xliff:g id="APP_NAME">%1$s</xliff:g>. Вызваліце месца і паўтарыце спробу."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Прыкладанне не знойдзена"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Прыкладанне не знойдзена ў спісе ўсталяваных прыкладанняў."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Забаронена"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Бягучы карыстальнік не мае дазволу на гэта выдаленне."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Памылка"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Нельга выдаліць праграму."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Выдалiць прыкладанне"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Выдаліць абнаўленні"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> з\'яўляецца часткай наступнага прыкладання:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Выдаліць гэта прыкладанне?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Выдалiць гэта прыкладанне для "<b>"ўсiх"</b>" карыстальнirfў? Прыкладанне i яго дадзеныя будуць выдалены для "<b>"ўсiх"</b>" карыстальнiкаў прылады."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Хочаце выдаліць гэту праграму для карыстальніка <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Замяніць гэту праграму заводскай версіяй? Усе даныя будуць выдалены."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Замяніць гэту праграму заводскай версіяй? Усе даныя будуць выдаленыя. Гэта паўплывае на ўсіх карыстальнікаў гэтай прылады, у тым ліку карыстальнікаў з працоўнымі профілямі."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Актыўныя выдаленні"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Збоі выдалення"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Выдаленне..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> выдаляецца…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Выдаленне завершана"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Выдалена <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Няўдалае выдаленне."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Не атрымалася выдаліць <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Немагчыма выдаліць актыўную праграму адміністратара прылады"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Немагчыма выдаліць актыўную праграму адміністратара прылады для карыстальніка <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Гэта праграма патрабуецца для некаторых карыстальнікаў або профіляў і была выдалена для іншых"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Гэта праграма неабходная для вашага профілю і не можа быць выдалена."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Гэта праграма патрабуецца адміністратару вашай прылады і не можа быць выдалена."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Праграмы адміністратара для кіравання прыладамі"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Кіраванне карыстальнікамі"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Немагчыма выдалiць прыкладанне <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Памылка аналiзу пакета."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Новыя"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Усе"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Прыватнасць"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Доступ да прылады"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Гэтае абнаўленне не патрабуе ніякіх новых дазволаў."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Адмовіць"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Дадатковая iнфармацыя"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Усё роўна адмовіць"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> з <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Дазволіць &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Заўсёды дазваляць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Толькі пры актыўнай праграме"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Заўсёды"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Адхіліць і больш не пытацца"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"Адключана: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"усе адключаны"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"няма адключаных"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Дазволіць"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Праграмы"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Дазволы праграм"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Больш не пытацца"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Няма дазволаў"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Дадатковыя дазволы"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Паказаць звесткі пра праграму"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+      <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> іншых</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> іншага</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Гэта праграма была распрацавана для больш старой версіі Android. Адхіленне дазволу можа прывесці да таго, што яна не будзе працаваць належным чынам."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"выканаць невядомае дзеянне"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> з <xliff:g id="COUNT_1">%2$d</xliff:g> праграм з дазволам"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Паказаць сістэмныя"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Схаваць сістэмныя"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Няма праграм"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Налады месцазнаходжання"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> з\'яўляецца службай вызначэння месцазнаходжання для гэтай прылады. Доступ да вызначэння месцазнаходжання можна змяніць у наладах вызначэння месцазнаходжання."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Калі вы адхіліце гэты дазвол, асноўныя функцыі прылады могуць перастаць працаваць належным чынам."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Ажыццёўлена палітыкай"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Доступ у фонавым рэжыме адключаны згодна з правіламі"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Доступ у фонавым рэжыме ўключаны згодна з правіламі"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Доступ у актыўным рэжыме ўключаны згодна з правіламі"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Кантралюецца адміністратарам"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Заўсёды"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Толькі пры актыўнай праграме"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Ніколі"</string>
+    <string name="loading" msgid="7811651799620593731">"Загрузка..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Усе дазволы"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Іншыя магчымасці праграмы"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Запыт дазволу"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Выяўлены слой экрана"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Каб змяніць гэту наладу дазволу, вы павінны спачатку выключыць слой экрана з меню Налады &gt; Праграмы"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Адкрыць налады"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Дзеянні па ўсталяванні або выдаленні не падтрымліваюцца на Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Выберыце, да чаго дазволіць доступ праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Праграма &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; была абноўлена. Выберыце, да чаго ёй дазволіць доступ."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Скасаваць"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Далей"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Новыя дазволы"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Бягучыя дазволы"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Падрыхтоўка праграмы..."</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Невядома"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"У мэтах бяспекі вашаму планшэту не дазваляецца ўсталёўваць невядомыя праграмы з гэтай крыніцы."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"У мэтах бяспекі вашаму тэлевізару не дазваляецца ўсталёўваць невядомыя праграмы з гэтай крыніцы."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"У мэтах бяспекі вашаму тэлефону не дазваляецца ўсталёўваць невядомыя праграмы з гэтай крыніцы."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Ваш тэлефон і асабістыя даныя больш уразлівыя для нападаў невядомых праграм. Пры ўсталёўцы гэтай праграмы вы згаджаецеся, што несяце адказнасць за любыя пашкоджанні тэлефона ці страту даных, якія могуць адбыцца ў выніку выкарыстання гэтай праграмы."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Ваш планшэт і асабістыя даныя больш уразлівыя для нападаў невядомых праграм. Пры ўсталёўцы гэтай праграмы вы згаджаецеся, што несяце адказнасць за любыя пашкоджанні планшэта ці страту даных, якія могуць адбыцца ў выніку выкарыстання гэтай праграмы."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Ваш тэлевізар і асабістыя даныя больш уразлівыя для нападаў невядомых праграм. Пры ўсталёўцы гэтай праграмы вы згаджаецеся, што несяце адказнасць за любыя пашкоджанні тэлевізара ці страту даных, якія могуць адбыцца ў выніку выкарыстання гэтай праграмы."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Працягнуць"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Налады"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Усталяванне/выдаленне праграм wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-bg-television/strings.xml b/packages/PackageInstaller/res/values-bg-television/strings.xml
new file mode 100644
index 0000000..7429955a
--- /dev/null
+++ b/packages/PackageInstaller/res/values-bg-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Отказване, без повторно запитване"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Можете да промените това по-късно от „Настройки“ &gt; „Приложения“"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Показване на системните приложения"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Разрешения за приложението"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Разрешения за приложението"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Разрешения за <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Допълнителни разрешения"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Разрешения за <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-bg-watch/strings.xml b/packages/PackageInstaller/res/values-bg-watch/strings.xml
new file mode 100644
index 0000000..b71606b
--- /dev/null
+++ b/packages/PackageInstaller/res/values-bg-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Отказ, без повторно запитване"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Показване на системните приложения"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Без промяна"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Да"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Отказ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-bg/strings.xml b/packages/PackageInstaller/res/values-bg/strings.xml
new file mode 100644
index 0000000..30d99eb
--- /dev/null
+++ b/packages/PackageInstaller/res/values-bg/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Инсталираща програма за пакети"</string>
+    <string name="next" msgid="3057143178373252333">"Напред"</string>
+    <string name="install" msgid="5896438203900042068">"Инсталиране"</string>
+    <string name="done" msgid="3889387558374211719">"Готово"</string>
+    <string name="cancel" msgid="8360346460165114585">"Назад"</string>
+    <string name="installing" msgid="8613631001631998372">"Инсталира се..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> се инсталира…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Приложението бе инсталирано."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Искате ли да инсталирате това приложение? То ще получи достъп до:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Искате ли да инсталирате това приложение? То не изисква никакъв специален достъп."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Искате ли да инсталирате актуализация за това съществуващо приложение? Съществуващите ви данни няма да бъдат загубени. Актуализираното приложение ще получи достъп до:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Искате ли да инсталирате актуализация за това вградено приложение? Съществуващите ви данни няма да бъдат загубени. Актуализираното приложение ще получи достъп до:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Искате ли да инсталирате актуализация за това съществуващо приложение? Съществуващите ви данни няма да бъдат загубени. Не се изисква специален достъп."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Искате ли да инсталирате актуализация за това вградено приложение? Съществуващите ви данни няма да бъдат загубени. Не се изисква специален достъп."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Приложението не бе инсталирано."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Инсталирането на пакета бе блокирано."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Приложението не бе инсталирано, тъй като пакетът е в конфликт със съществуващ пакет."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Приложението не бе инсталирано, тъй като не е съвместимо с таблета ви."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Това приложение не е съвместимо с телевизора ви."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Приложението не бе инсталирано, тъй като не е съвместимо с телефона ви."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Приложението не бе инсталирано, тъй като изглежда, че пакетът е невалиден."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> не можа да се инсталира на таблета ви."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> не можа да се инсталира на телевизора ви."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> не можа да се инсталира на телефона ви."</string>
+    <string name="launch" msgid="4826921505917605463">"Отваряне"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Администраторът ви не разрешава инсталирането на приложения, получени от неизвестни източници"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Този потребител не може да инсталира неизвестни приложения"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Този потребител няма разрешение да инсталира приложения"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Управление на приложенията"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Няма място"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> не можа да се инсталира. Освободете място и опитайте отново."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Приложението не бе намерено"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Приложението не бе намерено в списъка с инсталирани приложения."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Няма разрешение"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Текущият потребител няма разрешение да извърши това деинсталиране."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Грешка"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Приложението не можа да бъде деинсталирано."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Деинсталиране на приложението"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Деинсталиране на актуализацията"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> е част от следното приложение:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Искате ли да деинсталирате това приложение?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Искате ли да деинсталирате това приложение за "<b>"всички"</b>" потребители? Приложението и данните му ще бъдат премахнати от "<b>"всички"</b>" потребители на устройството."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Искате ли да деинсталирате това приложение за потребителя <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Това приложение да се замени ли с фабричната версия? Всички данни ще бъдат премахнати."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Това приложение да се замени ли с фабричната версия? Всички данни ще бъдат премахнати. Промяната ще засегне всеки потребител на устройството, включително тези със служебни потребителски профили."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Активни деинсталирания"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Неуспешни деинсталирания"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Деинсталира се..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> се деинсталира…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Деинсталирането завърши."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Деинсталирахте <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Деинсталирането не бе успешно."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Деинсталирането на <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> бе неуспешно."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Активното приложение за администриране на устройството не може да се деинсталира"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Активното приложение за администриране на устройството не може да се деинсталира за <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Това приложение е необходимо за някои потребители или потребителски профили и бе деинсталирано за други."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Това приложение е необходимо за потребителския ви профил и не може да се деинсталира."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Приложението се изисква от администратора на у-вото и не може да се деинсталира."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Управление на прилож. за администриране на у-вото"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Управление на потребителите"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> не можа да се деинсталира."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"При синтактичния анализ на пакета възникна проблем."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Нови"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Всички"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Поверителност"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Достъп до у-вото"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Тази актуализация не изисква нови разрешения."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Отказване"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Още информация"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Отказване въпреки това"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> от <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Разрешаване на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Винаги ли да се разрешава на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Само при използване на приложението"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Винаги"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Отказване, без повторно запитване"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"Деактивирахте <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"всички са деактивирани"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"няма деактивирани"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Разрешаване"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Приложения"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Разрешения за приложения"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Без повторно питане"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Няма разрешения"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Допълнителни разрешения"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Отваряне на информацията за приложението"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Това приложение е създадено за по-стара версия на Android. То може да спре да функционира нормално при отказване на разрешението."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"извършване на неизвестно действие"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> от <xliff:g id="COUNT_1">%2$d</xliff:g> приложения имат разрешение"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Системни приложения"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Скриване на системните"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Няма приложения"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Настройки за местоположението"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> е доставчик на услуги за местоположението за това устройство. Достъпът до местоположението може да бъде променен от съответните настройки."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ако откажете това разрешение, основни функции на устройството ви може да спрат да работят както трябва."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Наложено чрез правило"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Достъпът на заден план е деактивиран от правилата"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Достъпът на заден план е активиран от правилата"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Достъпът на преден план е активиран от правилата"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Контролира се от администратор"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Винаги"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Само при използване на прилож."</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Никога"</string>
+    <string name="loading" msgid="7811651799620593731">"Зарежда се…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Всички разрешения"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Други възможности на приложението"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Заявка за разрешение"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Открито е екранно наслагване"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"За да промените настройката за това разрешение, трябва първо да изключите екранното наслагване от „Настройки“ &gt; „Приложения“"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Отваряне на настройките"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Действията инсталиране и деинсталиране не се поддържат на устройства с Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Изберете до какво да има достъп &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Приложението &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; е актуализирано. Изберете до какво да има достъп."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Отказ"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Напред"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Нови разрешения"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Текущи разрешения"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Приложението се подготвя…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Неизвестно"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"От съображения за сигурност на таблета ви не могат да се инсталират неизвестни приложения от този източник."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"От съображения за сигурност на телевизора ви не могат да се инсталират неизвестни приложения от този източник."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"От съображения за сигурност на телефона ви не могат да се инсталират неизвестни приложения от този източник."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Телефонът и личните ви данни са по-уязвими към атаки от неизвестни приложения. С инсталирането на това приложение приемате, че носите отговорност при евентуална повреда на телефона или загуба на информация вследствие на използването на приложението."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Таблетът и личните ви данни са по-уязвими към атаки от неизвестни приложения. С инсталирането на това приложение приемате, че носите отговорност при евентуална повреда на таблета или загуба на информация вследствие на използването на приложението."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Телевизорът и личните ви данни са по-уязвими към атаки от неизвестни приложения. С инсталирането на това приложение приемате, че носите отговорност при евентуална повреда на телевизора или загуба на информация вследствие на използването на приложението."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Напред"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Настройки"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Инсталир./деинсталир. на прилож. за Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-bn-television/strings.xml b/packages/PackageInstaller/res/values-bn-television/strings.xml
new file mode 100644
index 0000000..a83d7b8
--- /dev/null
+++ b/packages/PackageInstaller/res/values-bn-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"অস্বীকার করুন এবং আবার জিজ্ঞাসা করবেন না"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"আপনি সেটিংস &gt; অ্যাপ্লিকেশান এ এটি পরে পরিবর্তন করতে পারেন"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"সিস্টেম অ্যাপ্লিকেশানগুলি দেখান"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"অ্যাপ্লিকেশনের অনুমতি"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"অ্যাপ্লিকেশনের অনুমতি"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> অনুমতিগুলি"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"অতিরিক্ত অনুমতিগুলি"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> অনুমতিগুলি"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-bn-watch/strings.xml b/packages/PackageInstaller/res/values-bn-watch/strings.xml
new file mode 100644
index 0000000..79a91f4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-bn-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"অস্বীকার করুন, আবার জিজ্ঞাসা করবেন না"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"সিস্টেম অ্যাপ্লিকেশানগুলি দেখান"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"পরিবর্তন করা যাবে না"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"হ্যাঁ"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"বাতিল করুন"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-bn/strings.xml b/packages/PackageInstaller/res/values-bn/strings.xml
new file mode 100644
index 0000000..c66f5bb
--- /dev/null
+++ b/packages/PackageInstaller/res/values-bn/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"প্যাকেজ ইনস্টলার"</string>
+    <string name="next" msgid="3057143178373252333">"পরবর্তী"</string>
+    <string name="install" msgid="5896438203900042068">"ইনস্টল করুন"</string>
+    <string name="done" msgid="3889387558374211719">"সম্পন্ন হয়েছে"</string>
+    <string name="cancel" msgid="8360346460165114585">"বাতিল করুন"</string>
+    <string name="installing" msgid="8613631001631998372">"ইনস্টল করা হচ্ছে…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ইন্সটল করা হচ্ছে…"</string>
+    <string name="install_done" msgid="3682715442154357097">"অ্যাপ্লিকেশান ইনস্টল করা হয়েছে৷"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"আপনি কি এই অ্যাপ্লিকেশানটি ইনস্টল করতে চান? এর মাধ্যমে যেসব জিনিস অ্যাক্সেস করার সুবিধা পাবেন সেগুলি হল:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"আপনি কি এই অ্যাপ্লিকেশানটি ইনস্টল করতে চান? এর জন্য কোনো বিশেষ অ্যাক্সেসের প্রয়োজন নেই৷"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"আপনি কি এই বিদ্যমান অ্যাপ্লিকেশানের একটি আপডেট ইনস্টল করতে চান? আপনার বিদ্যমান ডেটাগুলি একই রকম থাকবে৷ এই আপডেট হওয়া অ্যাপ্লিকেশানটির মাধ্যমে যেসব জিনিস অ্যাক্সেস করার সুবিধা পাবেন সেগুলি হল:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"আপনি কি এই ভেতরে থাকা অ্যাপ্লিকেশানের একটি আপডেট ইনস্টল করতে চান? আপনার বিদ্যমান ডেটাগুলি একই রকম থাকবে৷ এই আপডেট হওয়া অ্যাপ্লিকেশানটির মাধ্যমে যেসব জিনিস অ্যাক্সেস করার সুবিধা পাবেন সেগুলি হল:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"আপনি কি এই বিদ্যমান অ্যাপ্লিকেশানের একটি আপডেট ইনস্টল করতে চান? আপনার বিদ্যমান ডেটাগুলি একই রকম থাকবে৷ এর জন্য কোনো বিশেষ অ্যাক্সেসের প্রয়োজন নেই৷"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"আপনি কি ভেতরে থাকা অ্যাপ্লিকেশানের একটি আপডেট ইনস্টল করতে চান? আপনার বিদ্যমান ডেটাগুলি একই রকম থাকবে৷ এর জন্য কোনো বিশেষ অ্যাক্সেসের প্রয়োজন নেই৷"</string>
+    <string name="install_failed" msgid="6579998651498970899">"অ্যাপ্লিকেশান ইনস্টল করা হয়নি৷"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ইনস্টল হওয়া থেকে প্যাকেজটিকে অবরুদ্ধ করা হয়েছে।"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"কোনো বিদ্যমান প্যাকেজের সাথে এই প্যাকেজটির বিবাদ থাকার ফলে অ্যাপ ইনস্টল করা হয়নি৷"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"অ্যাপটি আপনার ট্যাবলেটের জন্য উপযুক্ত না হওয়ার কারণে এটি ইনস্টল করা হয়নি৷"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"এই অ্যাপ্লিকেশানটি আপনার টিভির জন্য উপযুক্ত নয়৷"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"অ্যাপটি আপনার ফোনের জন্য উপযুক্ত না হওয়ার কারণে এটি ইনস্টল করা হয়নি৷"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"প্যাকেজটি অবৈধ বলে মনে হওয়ার কারণে অ্যাপ ইনস্টল করা হয়নি৷"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> আপনার ট্যাবলেটে ইনস্টল করা যায়নি৷"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g>-কে আপনার টিভিতে ইনস্টল করা যাবে না৷"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> আপনার ফোনে ইনস্টল করা যায়নি৷"</string>
+    <string name="launch" msgid="4826921505917605463">"খুলুন"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"আপনার প্রশাসক অজানা উৎস থেকে প্রাপ্ত অ্যাপ ইনস্টল করার অনুমতি দেয় না"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"এই ব্যবহারকারী অজানা অ্যাপ ইনস্টল করতে পারবেন না"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"এই ব্যবহারকারী অ্যাপ ইনস্টল করার অনুমতি পাননি"</string>
+    <string name="ok" msgid="3468756155452870475">"ঠিক আছে"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"অ্যাপ্লিকেশানগুলির পরিচালনা করুন"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"পর্যাপ্ত জায়গা খালি নেই"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> ইনস্টল করা যায়নি৷ কিছু পরিমাণ জায়গা খালি করে আবার চেষ্টা করুন৷"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"অ্যাপ্লিকেশান পাওয়া যায়নি"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"অ্যাপ্লিকেশানটিকে ইনস্টল করা অ্যাপ্লিকেশানের তালিকাতে পাওয়া যায়নি৷"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"অনুমোদিত নয়"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"বর্তমান ব্যবহারকারী এই আনইনস্টলের কাজটি করার জন্য অনুমোদিত নয়৷"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"ত্রুটি"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"অ্যাপ আনইনস্টল করা গেল না৷"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"অ্যাপ্লিকেশানটিকে আনইনস্টল করুন"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"আপডেট আনইনস্টল করুন"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> হল নিম্নলিখিত অ্যাপ্লিকেশানগুলির অংশ বিশেষ:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"আপনি কি এই অ্যাপ্লিকেশানটিকে আনইনস্টল করতে চান?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"আপনি কি "<b>"সমস্ত"</b>" ব্যবহারকারীর জন্য এই অ্যাপ্লিকেশানটিকে আনইনস্টল করতে চান? এই ডিভাইসের "<b>"সমস্ত"</b>" ব্যবহারকারীর কাছ থেকে অ্যাপ্লিকেশানটি ও এর ডেটা হারিয়ে যাবে৷"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"আপনি কি ব্যবহারকারী <xliff:g id="USERNAME">%1$s</xliff:g> এর জন্য এই অ্যাপ্লিকেশানটি আনইনস্টল করতে চান?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ফ্যাক্টরি সংস্করণের সাথে এই অ্যাপটিকে বদলাবেন? সব ডেটা মুছে যাবে।"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ফ্যাক্টরি সংস্করণের সাথে এই অ্যাপটিকে বদলাবেন? সমস্ত ডেটা মুছে যাবে। এটি এই ডিভাইসের সমস্ত ব্যবহারকারী সহ তাদের কার্যের প্রোফাইলের উপরেও প্রভাব ফেলবে।"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"এগুলি আনইনস্টল করা হচ্ছে"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"এগুলি আনইনস্টল করা যায়নি"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"আনইনস্টল করা হচ্ছে ..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনস্টল করা হচ্ছে…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"আনইনস্টল সমাপ্ত হয়েছে৷"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনস্টল করা হয়েছে"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"আনইনস্টল সফল হয়নি৷"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনস্টল করা গেল না৷"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"সক্রিয় থাকা ডিভাইস প্রশাসক অ্যাপটি আনইনস্টল করা যাবে না"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> এর সক্রিয় থাকা ডিভাইস প্রশাসক অ্যাপটি আনইনস্টল করা যাবে না"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"কিছু ব্যবহারকারী বা প্রোফাইলের জন্য এই অ্যাপ্লিকেশানটি আবশ্যক এবং অন্যদের জন্য আনইনস্টল করা হবে"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"আপনার প্রোফাইলের জন্য এই অ্যাপ্লিকেশানটি প্রয়োজন এবং এটিকে আনইনস্টল করা যাবে না৷"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"আপনার ডিভাইস প্রশাসকের চাহিদা অনুযায়ী এই অ্যাপ্লিকেশানটি আবশ্যক এবং এটি আনইনস্টল করা যাবে না।"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"ডিভাইস প্রশাসক অ্যাপগুলি পরিচালনা করুন"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ব্যবহারকারীদের পরিচালনা করুন"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> আনইনস্টল করা যায়নি৷"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"প্যাকেজটি বিশ্লেষণ করার ক্ষেত্রে একটি সমস্যা হয়েছে৷"</string>
+    <string name="newPerms" msgid="6039428254474104210">"নতুন"</string>
+    <string name="allPerms" msgid="1024385515840703981">"সমস্ত"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"গোপনীয়তা"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"ডিভাইসের অ্যাক্সেস"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"এই আপডেটের জন্য কোনো নতুন অনুমতির প্রয়োজন নেই৷"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"প্রত্যাখ্যান করুন"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"আরও তথ্য"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"যাইহোক অস্বীকার করুন"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> এর <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;কে <xliff:g id="ACTION">%2$s</xliff:g> এর অনুমতি দেবেন?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"<xliff:g id="ACTION">%2$s</xliff:g>-এ সবসময় &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অনুমতি দেবেন?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"অ্যাপটি ব্যবহার করার সময়"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"সবসময়"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"অস্বীকার করুন এবং আবার জিজ্ঞাসা করবেন না"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g>টি অক্ষম করা হয়েছে"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"সমস্ত অক্ষম করা হয়েছে"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"কোনো কিছুই অক্ষম করা হয়নি"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"অনুমতি দিন"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"অ্যাপ"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"অ্যাপ্লিকেশনের অনুমতি"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"আর জিজ্ঞাসা করবেন না"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"কোনো অনুমতি নেই"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"অতিরিক্ত অনুমতিগুলি"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"অ্যাপের তথ্য দেখুন"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"একটি পুরোনো সংস্করণের Android এর জন্য এই অ্যাপ্লিকেশানটি ডিজাইন করা হয়েছিল৷ অনুমতি অস্বীকার করলে এটিকে যে কাজের উদ্দেশ্যে তৈরি করা হয়েছিল সেটি নাও করতে পারে৷"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"কোনো অজানা কার্য সঞ্চালন করুন"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g>টির মধ্যে <xliff:g id="COUNT_0">%1$d</xliff:g>টি অ্যাপ্লিকেশান মঞ্জুরিপ্রাপ্ত"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"সিস্টেম দেখুন"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"সিস্টেম লুকান"</string>
+    <string name="no_apps" msgid="1965493419005012569">"কোনো অ্যাপ্লিকেশান নেই"</string>
+    <string name="location_settings" msgid="1774875730854491297">"লোকেশন সেটিংস"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> এই ডিভাইসের জন্য একটি লোকেশন পরিষেবাগুলি প্রদান করে। লোকেশন সেটিংস থেকে লোকেশনের অ্যাক্সেস পরিবর্তন করা যায়।"</string>
+    <string name="system_warning" msgid="7103819124542305179">"আপনি যদি এই অনুমতিটি অস্বীকার করেন, তবে আপনার ডিভাইসের প্রাথমিক বৈশিষ্ট্যগুলিকে যে কাজের উদ্দেশ্যে তৈরি করা হয়েছিল সেগুলি নাও করতে পারে৷"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"নীতি দ্বারা প্রয়োগ করা হয়েছে"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"নীতির কারণে ব্যাকগ্রাউন্ড অ্যাক্সেস বন্ধ করা আছে"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"নীতির কারণে ব্যাকগ্রাউন্ড অ্যাক্সেস চালু করা আছে"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"নীতির কারণে খুলে রাখা অ্যাপের অ্যাক্সেস চালু করা আছে"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"অ্যাডমিনের দ্বারা নিয়ন্ত্রিত"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"সবসময়"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"অ্যাপটি ব্যবহার করার সময়"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"কখনও না"</string>
+    <string name="loading" msgid="7811651799620593731">"লোড হচ্ছে..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"সমস্ত অনুমতি"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"অন্যান্য অ্যাপ্লিকেশান ক্ষমতা"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"অনুমতির অনুরোধ"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"স্ক্রিন আচ্ছাদন শনাক্ত করা হয়েছে"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"এই অনুমতি সেটিংস পরিবর্তন করতে, আপনাকে প্রথমে সেটিংস &gt; এ গিয়ে অ্যাপ্লিকেশানগুলি থেকে স্ক্রিন ওভারলে বন্ধ করতে হবে"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"সেটিংস খুলুন"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"ওয়েরে ইনস্টল/আনইনস্টল করার কাজগুলি সমর্থিত নয়।"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; কে কোন জিনিসগুলিতে অ্যাক্সেস দেবেন তা বেছে নিন"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; আপডেট করা হয়েছে৷ এই অ্যাপ্লিকেশানটিকে কোন জিনিসগুলিতে অ্যাক্সেস দেবেন তা চয়ন করুন৷"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"বাতিল করুন"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"চালিয়ে যান"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"নতুন অনুমতিগুলি"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"বর্তমান অনুমতিগুলি"</string>
+    <string name="message_staging" msgid="6151794817691100003">"অ্যাপ্লিকেশান স্টেজ করা হচ্ছে..."</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"অজানা"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"আপনার নিরাপত্তার জন্য আপনার ট্যাবলেট কে এই উৎস থেকে আসা অজানা অ্যাপ ইনস্টল করার অনুমতি দেওয়া হয় না।"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"আপনার নিরাপত্তার জন্য আপনার TV কে এই উৎস থেকে আসা অজানা অ্যাপ ইনস্টল করার অনুমতি দেওয়া হয় না।"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"আপনার নিরাপত্তার জন্য আপনার ফোন কে এই উৎস থেকে আসা অজানা অ্যাপ ইনস্টল করার অনুমতি দেওয়া হয় না।"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"অজানা অ্যাপের দ্বারা আপনার ফোন এবং ব্যক্তিগত ডেটা আক্রান্ত হওয়ার সম্ভাবনা বেশি থাকে। এই অ্যাপটি ইনস্টল করার মাধ্যমে আপনি সম্মত হলেন যে এটি ব্যবহারের ফলে আপনার ফোনের বা ডেটার কোনও ক্ষতি হলে তার জন্য আপনিই দায়ী থাকবেন।"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"অজানা অ্যাপের দ্বারা আপনার ট্যাবলেট এবং ব্যক্তিগত ডেটা আক্রান্ত হওয়ার সম্ভাবনা বেশি থাকে। এই অ্যাপটি ইনস্টল করার মাধ্যমে আপনি সম্মত হলেন যে এটি ব্যবহারের ফলে আপনার ট্যাবলেটের বা ডেটার কোনও ক্ষতি হলে তার জন্য আপনিই দায়ী থাকবেন।"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"অজানা অ্যাপের দ্বারা আপনার টিভি এবং ব্যক্তিগত ডেটা আক্রান্ত হওয়ার সম্ভাবনা বেশি থাকে। এই অ্যাপটি ইনস্টল করার মাধ্যমে আপনি সম্মত হলেন যে এটি ব্যবহারের ফলে আপনার টিভি বা ডেটার কোনও ক্ষতি হলে তার জন্য আপনিই দায়ী থাকবেন।"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"চালিয়ে যান"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"সেটিংস"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"ওয়্যার অ্যাপ ইনস্টল/আনইনস্টল করা হচ্ছে"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-bs-television/strings.xml b/packages/PackageInstaller/res/values-bs-television/strings.xml
new file mode 100644
index 0000000..564f2a6
--- /dev/null
+++ b/packages/PackageInstaller/res/values-bs-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Odbij i ne pitaj ponovo"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Ovo možete kasnije promijeniti u odjeljku Postavke &gt; Aplikacije"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Prikaži sistemske aplikacije"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Odobrenja za aplikacije"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Odobrenja za aplikacije"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Odobrenja za: <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Dodatna odobrenja"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Odobrenja za: <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-bs-watch/strings.xml b/packages/PackageInstaller/res/values-bs-watch/strings.xml
new file mode 100644
index 0000000..dcae097
--- /dev/null
+++ b/packages/PackageInstaller/res/values-bs-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Odbij i ne pitaj ponovo"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Prikaži sistemske aplikacije"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ne mijenja se"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Da"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Otkaži"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-bs/strings.xml b/packages/PackageInstaller/res/values-bs/strings.xml
new file mode 100644
index 0000000..3f2c5c3
--- /dev/null
+++ b/packages/PackageInstaller/res/values-bs/strings.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Alat za instaliranje paketa"</string>
+    <string name="next" msgid="3057143178373252333">"Naprijed"</string>
+    <string name="install" msgid="5896438203900042068">"Instaliraj"</string>
+    <string name="done" msgid="3889387558374211719">"Gotovo"</string>
+    <string name="cancel" msgid="8360346460165114585">"Otkaži"</string>
+    <string name="installing" msgid="8613631001631998372">"Instalacija u toku..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instaliranje <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikacija je instalirana."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Želite li instalirati ovu aplikaciju? Ona će dobiti pristup:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Želite li instalirati ovu aplikaciju? Ona ne zahtijeva poseban pristup."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Želite li ažurirati ovu postojeću aplikaciju? Vaši postojeći podaci neće biti izgubljeni. Ažurirana aplikacija će dobiti pristup:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Želite li ažurirati ovu ugrađenu aplikaciju? Vaši postojeći podaci neće biti izgubljeni. Ažurirana aplikacija će dobiti pristup:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Želite li ažurirati ovu postojeću aplikaciju? Vaši postojeći podaci neće biti izgubljeni. Za ovo nije potreban poseban pristup."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Želite li ažurirati ovu ugrađenu aplikaciju? Vaš postojeći podaci neće biti izgubljeni. Nije potreban poseban pristup."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplikacija nije instalirana."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Instaliranje ovog paketa je blokirano."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplikacija nije instalirana jer paket nije usaglašen s postojećim paketom."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplikacija nije instalirana jer nije kompatibilna s vašim tabletom."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Ova aplikacija nije kompatibilna s vašim TV-om."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplikacija nije instalirana jer nije kompatibilna s vašim telefonom."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplikacija nije instalirana jer izgleda da paket nije važeći."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> ne možete instalirati na svoj tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Nije moguće instalirati aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> na vaš TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> ne možete instalirati na svoj telefon."</string>
+    <string name="launch" msgid="4826921505917605463">"Otvori"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Vaš administrator ne dozvoljava instaliranje aplikacija iz nepoznatih izvora."</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Ovaj korisnik ne može instalirati nepoznate aplikacije."</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Ovom korisniku nije dozvoljeno instaliranje aplikacija"</string>
+    <string name="ok" msgid="3468756155452870475">"Uredu"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Upravljaj aplikacijama"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nedostatak prostora"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Ne možete instalirati aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>. Oslobodite prostora u pohrani i pokušajte ponovo."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplikacija nije pronađena"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplikacija nije pronađena na spisku instaliranih aplikacija."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Nije dozvoljeno"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Trenutnom korisniku nije dozvoljeno da izvrši ovu deinstalaciju."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Greška"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Nije bilo moguće deinstalirati aplikaciju."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Uklanjanje aplikacije"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Uklanjanje ažuriranja"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je dio sljedeće aplikacije:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Želite li ukloniti ovu aplikaciju?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Želite li ukloniti ovu aplikaciju za "<b>" sve "</b>" korisnike? Aplikacija i njeni podaci će biti uklonjeni iz "<b>" svih "</b>" korisničkih računa na uređaju."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Želite li ukloniti ovu aplikaciju za korisnika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Želite li ovu aplikaciju zamijeniti s fabričkom verzijom? Svi podaci će biti uklonjeni."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Želite li ovu aplikaciju zamijeniti s fabričkom verzijom? Svi podaci će biti uklonjeni. To će utjecati na sve korisnike uređaja, uključujući i one s radnim profilima."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Tekuća deinstaliranja"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Neuspjela deinstaliranja"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Uklanjanje u toku..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Deinstalacija paketa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Uklanjanje završeno."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Deinstaliran je paket <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Uklanjanje nije uspjelo."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Paket <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nije uspješno deinstaliran."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Nije moguće deinstalirati aktivnu aplikaciju administratora uređaja"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Nije moguće deinstalirati aktivnu aplikaciju administratora uređaja za korisnika <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Ova aplikacija je neophodna nekim korisnicima ili profilima, a kod ostalih je deinstalirana"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ova aplikacija je potrebna za vaš profil i ne može se deinstalirati."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ova aplikacija je potrebna administratoru vašeg uređaja i ne može se ukloniti."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Upravljajte aplikacijama administratora uređaja"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Upravljanje korisnicima"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> se ne može ukloniti."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Došlo je do problema prilikom raščlanjivanja paketa."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Novo"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Sve"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privatnost"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Pristup uređaju"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Za ovo ažuriranje nisu potrebne nova odobrenja."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Odbij"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Više informacija"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Odbij svakako"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> od <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Uvijek dozvoliti da aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Samo dok se koristi aplikacija"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Uvijek"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Odbij i ne pitaj ponovo"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"omogućeno je <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"sve je onemogućeno"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ništa nije onemogućeno"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Dozvoli"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikacije"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Odobrenja za aplikacije"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ne pitaj ponovo"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Nema odobrenja"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Dodatna odobrenja"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Otvori informacije o aplikaciji"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one">još <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">još <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">još <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ova aplikacija je kreirana za stariju verziju Androida. Odbijanje odobrenja može uzrokovati da ona više ne funkcionira onako kako je primarno zamišljeno."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"izvrši nepoznatu radnju"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Aplikacije sa odobrenjem: <xliff:g id="COUNT_0">%1$d</xliff:g> od <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Prikaži sistemske aplikacije"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Sakrij sistemske"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nijedna aplikacija"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Postavke lokacije"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> pruža usluge lokacije za ovaj uređaj. Pristup lokaciji se može izmijeniti u postavkama lokacije."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ukoliko odbijete ovo odobrenje, osnovne funkcije vašeg uređaja možda više neće funkcionirati onako kako je prvobitno zamišljeno."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Nametnuto je pravilima"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Pristup pozadini je onemogućen u skladu s pravilima"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Pristup pozadini je omogućen u skladu s pravilima"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Pristup u prvom planu je omogućen u skladu s pravilima"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Kontrolira administrator"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Uvijek"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Samo dok se koristi aplikacija"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nikada"</string>
+    <string name="loading" msgid="7811651799620593731">"Učitava se…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Sva odobrenja"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Ostale mogućnosti aplikacije"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Zahtjev za odobrenjem"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Otkriven je element koji prekriva sadržaj ekrana"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Da promijenite postavku ovog odobrenja, prvo morate isključiti element koji prekriva sadržaj ekrana u odjeljku Postavke &gt; Aplikacije"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Otvori postavke"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Instaliranje/deinstaliranje nije podržano na Wearu."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Odaberite čemu aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&amp;Lt;/b&gt; može pristupiti"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Aplikacija &amp;Lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&amp;Lt;/b&gt; je ažurirana. Odaberite čemu ova aplikacija može pristupiti."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Otkaži"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Nastavi"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nova odobrenja"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Postojeća odobrenja"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Aplikacija se postavlja…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Nepoznato"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Vašem tabletu iz sigurnosnih razloga nije dopušteno instaliranje nepoznatih aplikacija iz ovog izvora."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Vašem TV-u iz sigurnosnih razloga nije dopušteno instaliranje nepoznatih aplikacija iz ovog izvora."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Vašem telefonu iz sigurnosnih razloga nije dopušteno instaliranje nepoznatih aplikacija iz ovog izvora."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Vaši podaci na telefonu i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, saglasni ste da ste vi odgovorni za bilo kakvu štetu na telefonu ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Vaši podaci na tabletu i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, saglasni ste da ste vi odgovorni za bilo kakvu štetu na tabletu ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Vaši podaci na TV-u i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, saglasni ste da ste vi odgovorni za bilo kakvu štetu na TV-u ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Nastavi"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Postavke"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"(De)instaliranje wear aplikacija"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ca-television/strings.xml b/packages/PackageInstaller/res/values-ca-television/strings.xml
new file mode 100644
index 0000000..7126c41
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ca-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Denega i no m\'ho tornis a preguntar"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Pots canviar-ho més endavant a Configuració &gt; Aplicacions"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Mostra les aplicacions del sistema"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Permisos d\'aplicacions"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Permisos d\'aplicacions"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Permisos: <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Permisos addicionals"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Permisos: <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ca-watch/strings.xml b/packages/PackageInstaller/res/values-ca-watch/strings.xml
new file mode 100644
index 0000000..d289b56
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ca-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Denega i no m\'ho demanis més"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostra les aplicacions del sistema"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"No es pot canviar"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Sí"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancel·la"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ca/strings.xml b/packages/PackageInstaller/res/values-ca/strings.xml
new file mode 100644
index 0000000..62d758c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ca/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Instal·lador de paquets"</string>
+    <string name="next" msgid="3057143178373252333">"Següent"</string>
+    <string name="install" msgid="5896438203900042068">"Instal·la"</string>
+    <string name="done" msgid="3889387558374211719">"Fet"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancel·la"</string>
+    <string name="installing" msgid="8613631001631998372">"S\'està instal·lant..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"S\'està instal·lant <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplicació instal·lada."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Vols instal·lar aquesta aplicació? Tindrà els permisos següents:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Vols instal·lar aquesta aplicació? No requereix cap accés especial."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Vols instal·lar una actualització per a aquesta aplicació? No es perdran les teves dades existents. L\'aplicació actualitzada tindrà els permisos següents:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Vols instal·lar una actualització d\'aquesta aplicació integrada? No es perdran les teves dades. L\'aplicació actualitzada tindrà els permisos següents:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Vols instal·lar una actualització a aquesta aplicació existent? Les dades existents no es perdran. No cal cap tipus d\'accés especial."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Vols instal·lar una actualització a aquesta aplicació integrada? Les teves dades existents no es perdran. No cal cap tipus d\'accés especial."</string>
+    <string name="install_failed" msgid="6579998651498970899">"L\'aplicació no s\'ha instal·lat."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"El paquet s\'ha bloquejat perquè no es pugui instal·lar."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"L\'aplicació no s\'ha instal·lat perquè el paquet entra en conflicte amb un d\'existent."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"L\'aplicació no s\'ha instal·lat perquè no és compatible amb la teva tauleta."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Aquesta aplicació no és compatible amb el teu televisor."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"L\'aplicació no s\'ha instal·lat perquè no és compatible amb el teu telèfon."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"L\'aplicació no s\'ha instal·lat perquè sembla que el paquet no és vàlid."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> no s\'ha pogut instal·lar a la tauleta."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> no s\'ha pogut instal·lar al televisor."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> no s\'ha pogut instal·lar al telèfon."</string>
+    <string name="launch" msgid="4826921505917605463">"Obre"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"L\'administrador no permet instal·lar aplicacions de fonts desconegudes"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Aquest usuari no pot instal·lar aplicacions desconegudes"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Aquest usuari no té permís per instal·lar aplicacions"</string>
+    <string name="ok" msgid="3468756155452870475">"D\'acord"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Gestiona les aplicacions"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Espai esgotat"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"No s\'ha pogut instal·lar <xliff:g id="APP_NAME">%1$s</xliff:g>. Allibera espai i torna-ho a provar."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"No s\'ha trobat l\'aplicació"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"No s\'ha trobat l\'aplicació a la llista d\'aplicacions instal·lades."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Sense autorització"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"L\'usuari actual no té permís per dur a terme aquesta desinstal·lació."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Error"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"No s\'ha pogut desinstal·lar l\'aplicació."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Desinstal·la l\'aplicació"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Desinstal·la l\'actualització"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> forma part de l\'aplicació següent:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Vols desinstal·lar aquesta aplicació?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Vols desinstal·lar aquesta aplicació per a "<b>"tots"</b>" els usuaris? L\'aplicació i les seves dades se suprimiran per a "<b>"tots"</b>" els usuaris del dispositiu."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Vols desinstal·lar aquesta aplicació per a l\'usuari <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Si substitueixes aquesta aplicació per la versió de fàbrica, s\'esborraran totes les dades."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Si substitueixes aquesta aplicació per la versió de fàbrica, s\'esborraran totes les dades. Això afectarà tots els usuaris d\'aquest dispositiu, inclosos els que tinguin un perfil professional."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Desinstal·lacions en curs"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Desinstal·lacions fallides"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"S\'està desinstal·lant..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"S\'està desinstal·lant <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Desinstal·lació finalitzada."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"S\'ha desinstal·lat <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"S\'ha produït un error en la desinstal·lació."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"No s\'ha pogut desinstal·lar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> correctament."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"No es pot desinstal·lar l\'aplicació activa de l\'administrador del dispositiu"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"No es pot desinstal·lar l\'aplicació activa de l\'administrador del dispositiu per a <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"L\'aplicació cal en alguns usuaris o perfils i s\'ha desinstal·lat per a d\'altres"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Aquesta aplicació es necessita per al teu perfil i no es pot desinstal·lar."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"L\'administrador del dispositiu necessita l\'aplicació i no la pots desinstal·lar."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Gestiona aplicacions d\'administració del dispositiu"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Gestiona els usuaris"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> no s\'ha pogut desinstal·lar."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"S\'ha produït un problema en analitzar el paquet."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nous"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Tots"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privadesa"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Accés al dispositiu"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Aquesta actualització no requereix permisos nous."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Denega"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Més informació"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Denega de totes maneres"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Vols permetre a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Només mentre s\'utilitzi l\'aplicació"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Sempre"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Denega i no m\'ho tornis a preguntar"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> permisos desactivats"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"tots els permisos desactivats"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"cap permís desactivat"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Permet"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplicacions"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Permisos d\'aplicacions"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"No m\'ho tornis a preguntar"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Sense permisos"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Més permisos"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Obre la informació de l\'aplicació"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> més</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> més</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Aquesta aplicació es va dissenyar per a una versió anterior d\'Android. És possible que no funcioni com està previst si li denegues el permís."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"dur a terme una acció desconeguda"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> de <xliff:g id="COUNT_1">%2$d</xliff:g> aplicacions permeses"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Mostra aplicacions del sistema"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Amaga aplicacions del sistema"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Cap aplicació"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Configuració d\'ubicació"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> és un proveïdor de serveis d\'ubicació per a aquest dispositiu. L\'accés a la ubicació es pot modificar des de la configuració d\'ubicació."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Si rebutges aquest permís, és possible que funcions bàsiques del dispositiu deixin de funcionar correctament."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Aplicat en funció de la política"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"S\'ha desactivat l\'accés en segon pla per la política"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"S\'ha activat l\'accés en segon pla per la política"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"S\'ha activat l\'accés en primer pla per la política"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlat per l\'administrador"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Sempre"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Només mentre s\'utilitzi l\'app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Mai"</string>
+    <string name="loading" msgid="7811651799620593731">"S\'està carregant..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Tots els permisos"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Altres competències de l\'aplicació"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Sol·licitud de permís"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"S\'ha detectat una superposició de pantalla"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Per canviar la configuració de permisos, cal que desactivis la superposició de pantalla des de Configuració &gt; Aplicacions"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Obre Configuració"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Les accions d\'instal·lar o de desinstal·lar no s\'admeten a Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Tria a què vols que tingui accés &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"S\'ha actualitzat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;. Tria a què vols que tingui accés aquesta aplicació."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancel·la"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continua"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Permisos nous"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Permisos actuals"</string>
+    <string name="message_staging" msgid="6151794817691100003">"S\'està preparant la instal·lació de l\'aplicació…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Desconegut"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Per seguretat, la tauleta no pot instal·lar aplicacions desconegudes d\'aquesta font."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Per seguretat, el televisor no pot instal·lar aplicacions desconegudes d\'aquesta font."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Per seguretat, el telèfon no pot instal·lar aplicacions desconegudes d\'aquesta font."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"El telèfon i les dades personals són més vulnerables als atacs d\'aplicacions desconegudes. En instal·lar aquesta aplicació, acceptes que ets responsable de qualsevol dany que es produeixi al telèfon o de la pèrdua de dades que pugui resultar del seu ús."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"La tauleta i les dades personals són més vulnerables als atacs d\'aplicacions desconegudes. En instal·lar aquesta aplicació, acceptes que ets responsable de qualsevol dany que es produeixi a la tauleta o de la pèrdua de dades que pugui resultar del seu ús."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"El televisor i les dades personals són més vulnerables als atacs d\'aplicacions desconegudes. En instal·lar aquesta aplicació, acceptes que ets responsable de qualsevol dany que es produeixi al televisor o de la pèrdua de dades que pugui resultar del seu ús."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continua"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Configuració"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instal·lant o desinstal·lant aplicacions de Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-cs-television/strings.xml b/packages/PackageInstaller/res/values-cs-television/strings.xml
new file mode 100644
index 0000000..ed2d8dc
--- /dev/null
+++ b/packages/PackageInstaller/res/values-cs-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Odmítnout a již se neptat"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Svoji volbu můžete později změnit v nabídce Nastavení &gt; Aplikace."</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Zobrazit systémové aplikace"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Oprávnění aplikací"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Oprávnění aplikací"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> – oprávnění"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Další oprávnění"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> – oprávnění"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-cs-watch/strings.xml b/packages/PackageInstaller/res/values-cs-watch/strings.xml
new file mode 100644
index 0000000..160d7aa
--- /dev/null
+++ b/packages/PackageInstaller/res/values-cs-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Odmítnout a již se neptat"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Zobrazit systémové aplikace"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nelze změnit"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ano"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Zrušit"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-cs/strings.xml b/packages/PackageInstaller/res/values-cs/strings.xml
new file mode 100644
index 0000000..a64c07a
--- /dev/null
+++ b/packages/PackageInstaller/res/values-cs/strings.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Nástroj k instalaci balíčků"</string>
+    <string name="next" msgid="3057143178373252333">"Další"</string>
+    <string name="install" msgid="5896438203900042068">"Instalovat"</string>
+    <string name="done" msgid="3889387558374211719">"Hotovo"</string>
+    <string name="cancel" msgid="8360346460165114585">"Zrušit"</string>
+    <string name="installing" msgid="8613631001631998372">"Probíhá instalace..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instalace balíčku <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikace je nainstalována."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Chcete tuto aplikaci nainstalovat? Aplikace získá přístup k těmto oprávněním:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Chcete tuto aplikaci nainstalovat? Aplikace nevyžaduje žádná zvláštní oprávnění."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Chcete nainstalovat aktualizaci této existující aplikace? Stávající data nebudou ztracena. Aktualizovaná aplikace získá přístup k následujícímu:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Chcete nainstalovat aktualizaci této integrované aplikace? Stávající data nebudou ztracena. Aktualizovaná aplikace získá přístup k následujícímu:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Chcete nainstalovat aktualizaci této existující aplikace? Vaše existující data nebudou ztracena. Není vyžadován žádný zvláštní přístup."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Chcete nainstalovat aktualizaci této integrované aplikace? Vaše existující data nebudou ztracena. Není vyžadován žádný zvláštní přístup."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplikaci nelze nainstalovat."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Instalace balíčku byla zablokována."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplikaci nelze nainstalovat, protože balíček je v konfliktu se stávajícím balíčkem."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplikaci nelze nainstalovat, protože s tabletem není kompatibilní."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Tato aplikace s vaší televizí není kompatibilní."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplikaci nelze nainstalovat, protože s telefonem není kompatibilní."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplikaci nelze nainstalovat, protože balíček zřejmě není platný."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> do tohoto tabletu nelze nainstalovat."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> se do televize nepodařilo nainstalovat."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> do tohoto telefonu nelze nainstalovat."</string>
+    <string name="launch" msgid="4826921505917605463">"Otevřít"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Váš administrátor nedovoluje instalaci aplikací z neznámých zdrojů"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Tento uživatel nemůže instalovat neznámé aplikace"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Tento uživatel nesmí instalovat aplikace"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Spravovat aplikace"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nedostatek místa"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> nelze nainstalovat. Uvolněte místo v paměti a zkuste to znovu."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplikace nebyla nalezena"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplikaci se nepodařilo najít na seznamu nainstalovaných aplikací."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Není povoleno"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Aktuální uživatel nemá k odinstalaci oprávnění."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Chyba"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Aplikaci nelze odinstalovat."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Odinstalovat aplikaci"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Odinstalovat aktualizaci"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"Činnost <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je součástí následující aplikace:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Chcete tuto aplikaci odinstalovat?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Chcete  tuto aplikaci odinstalovat "<b>"všem"</b>" uživatelům? Aplikace a její údaje budou odstraněny "<b>"všem"</b>" uživatelům tohoto zařízení."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Chcete tuto aplikaci pro uživatele <xliff:g id="USERNAME">%1$s</xliff:g> odinstalovat?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Chcete tuto aplikaci nahradit tovární verzí? Všechna data budou odstraněna."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Chcete tuto aplikaci nahradit tovární verzí? Všechna data budou odstraněna. Tato akce ovlivní všechny uživatele zařízení, včetně uživatelů s pracovním profilem."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Probíhající odinstalace"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Neúspěšné odinstalace"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Probíhá odinstalace..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Odinstalace balíčku <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Odinstalace byla dokončena."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Balíček <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> byl odinstalován"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Odinstalace se nezdařila."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Odinstalace balíčku <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> se nezdařila."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Aktivní aplikaci pro správu zařízení nelze odinstalovat"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Aktivní aplikaci pro správu zařízení uživatele <xliff:g id="USERNAME">%1$s</xliff:g> nelze odinstalovat"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Tato aplikace je u některých uživatelů nebo profilů požadována, u ostatních byla odinstalována."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Tato aplikace je pro váš profil požadována a nelze ji odinstalovat."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Tato aplikace je administrátorem zařízení vyžadována a nelze ji odinstalovat."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Přejít do nastavení aplikací pro správu zařízení"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Správa uživatelů"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> nelze odinstalovat."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Při analýze balíčku došlo k chybě."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nově"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Vše"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Ochrana soukromí"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Přístup k zařízení"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Tato aktualizace nevyžaduje žádná nová oprávnění."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Odmítnout"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Další informace"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Zamítnout"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> z <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Vždy povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Pouze při používání aplikace"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Vždy"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Odmítnout a už se neptat"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"zakázáno (<xliff:g id="COUNT">%1$d</xliff:g>)"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"vše zakázáno"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"nic nezakázáno"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Povolit"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikace"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Oprávnění aplikací"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Příště se neptat"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Žádná oprávnění"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Další oprávnění"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Otevřít informace o aplikaci"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="few">Ještě <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Ještě <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Ještě <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Ještě <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Tato aplikace byla vytvořena pro starší verzi platformy Android. Pokud oprávnění neudělíte, může přestat fungovat podle původního záměru."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"provést neznámou akci"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Povoleno u <xliff:g id="COUNT_0">%1$d</xliff:g> z <xliff:g id="COUNT_1">%2$d</xliff:g> aplikací"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Zobrazit systémové aplikace"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Skrýt systémové aplikace"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Žádné aplikace"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Nastavení polohy"</string>
+    <string name="location_warning" msgid="8778701356292735971">"Služby určování polohy v tomto zařízení poskytuje aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>. Přístup k poloze lze upravit v nastavení polohy."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Pokud toto oprávnění zamítnete, základní funkce zařízení nemusejí fungovat správně."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Vynuceno zásadami"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Přístup na pozadí byl zakázán zásadami"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Přístup na pozadí byl povolen zásadami"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Přístup na popředí byl povolen zásadami"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Spravováno administrátorem"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Vždy"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Pouze při používání aplikace"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nikdy"</string>
+    <string name="loading" msgid="7811651799620593731">"Načítání…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Všechna oprávnění"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Ostatní oprávnění aplikace"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Žádost o oprávnění"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Byla zjištěna překryvná vrstva obrazovky"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Chcete-li změnit nastavení tohoto oprávnění, v Nastavení &gt; Aplikace je třeba nejprve vypnout překryvnou vrstvu obrazovky"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Otevřít nastavení"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Akce instalace/odinstalace nejsou v zařízení Wear podporovány."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Určete, k čemu aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; povolíte přístup"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Aplikace &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; byla aktualizována. Určete, k čemu jí povolíte přístup."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Zrušit"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Pokračovat"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nová oprávnění"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Aktuální oprávnění"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Příprava instalace…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Neznámá aplikace"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Z bezpečnostních důvodů do tabletu není dovoleno instalovat neznámé aplikace z tohoto zdroje."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Z bezpečnostních důvodů do televize není dovoleno instalovat neznámé aplikace z tohoto zdroje."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Z bezpečnostních důvodů do telefonu není dovoleno instalovat neznámé aplikace z tohoto zdroje."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefon a osobní údaje jsou zranitelnější vůči útoku ze strany neznámých aplikací. Instalací této aplikace přijímáte odpovědnost za případné škody na telefonu nebo ztrátu dat, která může být používáním aplikace způsobena."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tablet a osobní údaje jsou zranitelnější vůči útoku ze strany neznámých aplikací. Instalací této aplikace přijímáte odpovědnost za případné škody na tabletu nebo ztrátu dat, která může být používáním aplikace způsobena."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Televize a osobní údaje jsou zranitelnější vůči útoku ze strany neznámých aplikací. Instalací této aplikace přijímáte odpovědnost za případné škody na televizi nebo ztrátu dat, která může být používáním aplikace způsobena."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Pokračovat"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Nastavení"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instalace/odinstalace aplikací pro Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-da-television/strings.xml b/packages/PackageInstaller/res/values-da-television/strings.xml
new file mode 100644
index 0000000..f9c0da2
--- /dev/null
+++ b/packages/PackageInstaller/res/values-da-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Afvis, og spørg ikke igen"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Du kan altid ændre dette i Indstillinger &gt; Apps"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Vis systemapps"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Apptilladelser"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Apptilladelser"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g>-tilladelser"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Flere tilladelser"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g>-tilladelser"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-da-watch/strings.xml b/packages/PackageInstaller/res/values-da-watch/strings.xml
new file mode 100644
index 0000000..616b1c2
--- /dev/null
+++ b/packages/PackageInstaller/res/values-da-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Afvis, og spørg ikke igen"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Vis systemapps"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Kan ikke ændres"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ja"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Annuller"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-da/strings.xml b/packages/PackageInstaller/res/values-da/strings.xml
new file mode 100644
index 0000000..73d03a5
--- /dev/null
+++ b/packages/PackageInstaller/res/values-da/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Pakkeinstallationsprogram"</string>
+    <string name="next" msgid="3057143178373252333">"Næste"</string>
+    <string name="install" msgid="5896438203900042068">"Installer"</string>
+    <string name="done" msgid="3889387558374211719">"Afslut"</string>
+    <string name="cancel" msgid="8360346460165114585">"Annuller"</string>
+    <string name="installing" msgid="8613631001631998372">"Installerer..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installerer <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Appen er installeret."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Vil du installere denne applikation? Den får adgang til følgende:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Vil du installere denne applikation? Den kræver ingen særlig adgang."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Vil du installere en opdatering til den eksisterende app? Du mister ikke dine eksisterende data. Den opdaterede app kan gøre følgende:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Vil du installere en opdatering til den indbyggede app? Du mister ikke dine eksisterende data. Den opdaterede app kan gøre følgende:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Vil du installere en opdatering til denne eksisterende applikation? Dine eksisterende data vil ikke gå tabt. Det kræver ikke nogen særlig adgang."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Vil du installere en opdatering til denne indbyggede applikation? Dine eksisterende data vil ikke gå tabt. Det kræver ikke nogen særlig adgang."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Appen blev ikke installeret."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Pakken blev blokeret i at blive installeret."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Appen blev ikke installeret, da pakken er i strid med en eksisterende pakke."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Appen blev ikke installeret, da den er ikke kompatibel med din tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Denne app er ikke kompatibel med dit fjernsyn."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Appen blev ikke installeret, da den ikke er kompatibel med din telefon."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Appen blev ikke installeret, da pakken ser ud til at være ugyldig."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres på din tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres på dit tv."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres på din telefon."</string>
+    <string name="launch" msgid="4826921505917605463">"Åbn"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Din administrator tillader ikke installation af apps, der hentes fra ukendte kilder"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Denne bruger kan ikke installere ukendte apps"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Denne bruger har ikke tilladelse til at installere apps"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Administrer apps"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Der er ikke mere plads"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres. Frigør noget plads, og prøv igen."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Appen blev ikke fundet"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Appen blev ikke fundet på listen over installerede apps."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Ikke tilladt"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Den nuværende bruger har ikke tilladelse til at udføre denne afinstallation."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Fejl"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Appen kunne ikke afinstalleres."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Afinstaller appen"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Afinstaller opdatering"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> er en del af følgende app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Vil du afinstallere denne app?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Vil du afinstallere denne app for "<b>"alle"</b>" brugere? Applikationen og dens data vil blive fjernet fra "<b>"alle"</b>" brugere på denne enhed."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Vil du afinstallere denne app for brugeren <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Vil du erstatte denne app med fabriksversionen? Alle data fjernes."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Vil du erstatte denne app med fabriksversionen? Alle data fjernes. Dette påvirker alle brugere af denne enhed, herunder de brugere, der har arbejdsprofiler."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Igangværende afinstallationer"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Mislykkede afinstallationer"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Afinstallerer..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Afinstallerer <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Afinstallationen er afsluttet."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> blev afinstalleret"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Afinstallationen mislykkedes."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kunne ikke afinstalleres."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Den aktive app til enhedsadministration kan ikke afinstalleres"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Den aktive app til enhedsadministration for <xliff:g id="USERNAME">%1$s</xliff:g> kan ikke afinstalleres"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Denne app kræves for nogle brugere eller profiler og afinstalleres for andre"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Denne app er nødvendig for din profil og kan ikke afinstalleres."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Denne app er påkrævet af din enhedsadministrator og kan ikke afinstalleres."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Administrer apps til enhedsadministration"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Administrer brugere"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke afinstalleres."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Der opstod et problem med parsing af pakken."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Ny"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Alle"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privatliv"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Adgang til enheden"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Denne opdatering kræver ingen nye tilladelser."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Afvis"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Få flere oplysninger"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Afvis alligevel"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> ud af <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Skal &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; altid have tilladelse til at <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Kun mens appen bruges"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Altid"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Afvis, og spørg ikke igen"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> er deaktiveret"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"alle er deaktiveret"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ingen er deaktiveret"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Tillad"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apps"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Apptilladelser"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Spørg ikke igen"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Ingen tilladelser"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Flere tilladelser"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Åbn appinfo"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> mere</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> mere</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Denne app er udviklet til en ældre version af Android. Hvis du ikke giver den tilladelse, vil den muligvis ikke længere virke efter hensigten."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"udføre en ukendt handling"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> ud af <xliff:g id="COUNT_1">%2$d</xliff:g> apps har tilladelse"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Vis systemapps"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Skjul systemapps"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Ingen apps"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Placeringsindstillinger"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> udbyder placeringstjenester for denne enhed. Adgangen til din placering kan ændres i Placeringsindstillinger."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Hvis du afviser denne tilladelse, vil grundlæggende funktioner på din enhed muligvis ikke længere fungere efter hensigten."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Håndhæves af politik"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Adgang i baggrunden er deaktiveret af en politik"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Adgang i baggrunden er aktiveret af en politik"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Adgang i forgrunden er aktiveret af en politik"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Styres af administratoren"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Altid"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Kun mens appen bruges"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Aldrig"</string>
+    <string name="loading" msgid="7811651799620593731">"Indlæser…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Alle tilladelser"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Andre app-egenskaber"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Anmodning om tilladelse"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Der er registreret skærmoverlejring"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Hvis du vil ændre denne indstilling for tilladelser, skal du først slå skærmoverlejringen fra i Indstillinger &gt; Apps"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Åbn indstillingerne"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Det er ikke muligt at installere/afinstallere på Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Vælg, hvad &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; må få adgang til"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; er blevet opdateret. Vælg, hvad denne app må få adgang til."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Annuller"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Fortsæt"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nye tilladelser"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Aktuelle tilladelser"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Forbereder appen…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Ukendt"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Din tablet har af sikkerhedshensyn ikke tilladelse til at installere ukendte apps fra denne kilde."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Dit fjernsyn har af sikkerhedshensyn ikke tilladelse til at installere ukendte apps fra denne kilde."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Din telefon har af sikkerhedshensyn ikke tilladelse til at installere ukendte apps fra denne kilde."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Din telefon og dine personlige data er mere sårbare over for angreb fra ukendte apps. Når du installerer denne app, accepterer du, at du er ansvarlig for skader på din telefon eller tab af data, der kan skyldes brug af appen."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Din tablet og dine personlige data er mere sårbare over for angreb fra ukendte apps. Når du installerer denne app, accepterer du, at du er ansvarlig for skader på din tablet eller tab af data, der kan skyldes brug af appen."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Dit fjernsyn og dine personlige data er mere sårbare over for angreb fra ukendte apps. Når du installerer denne app, accepterer du, at du er ansvarlig for skader på dit fjernsyn eller tab af data, der kan skyldes brug af appen."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Fortsæt"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Indstillinger"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installerer/afinstallerer Wear-apps"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-de-television/strings.xml b/packages/PackageInstaller/res/values-de-television/strings.xml
new file mode 100644
index 0000000..dc218e4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-de-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Ablehnen und nicht mehr fragen"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Du kannst dies später unter \"Einstellungen &gt; Apps\" ändern."</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"System-Apps anzeigen"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"App-Berechtigungen"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"App-Berechtigungen"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Berechtigungen für <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Zusätzliche Berechtigungen"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Berechtigungen für <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-de-watch/strings.xml b/packages/PackageInstaller/res/values-de-watch/strings.xml
new file mode 100644
index 0000000..5a0b8e1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-de-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Ablehnen &amp; nicht mehr fragen"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"System-Apps anzeigen"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Keine Änderung möglich"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"\"Ja\""</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Abbrechen"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-de/strings.xml b/packages/PackageInstaller/res/values-de/strings.xml
new file mode 100644
index 0000000..5a05c0c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-de/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Paket-Installer"</string>
+    <string name="next" msgid="3057143178373252333">"Weiter"</string>
+    <string name="install" msgid="5896438203900042068">"Installieren"</string>
+    <string name="done" msgid="3889387558374211719">"Fertig"</string>
+    <string name="cancel" msgid="8360346460165114585">"Abbrechen"</string>
+    <string name="installing" msgid="8613631001631998372">"Wird installiert..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> wird installiert…"</string>
+    <string name="install_done" msgid="3682715442154357097">"App wurde installiert."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Möchtest du diese App installieren? Sie erhält dann folgende Berechtigungen:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Möchtest du diese App installieren? Sie benötigt keinen besonderen Zugriff."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Möchtest du ein Update für diese vorhandene App installieren? Deine vorhandenen Daten bleiben erhalten. Die aktualisierte App erhält Zugriff auf:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Möchtest du ein Update für diese integrierte App installieren? Deine vorhandenen Daten bleiben erhalten. Die aktualisierte App erhält Zugriff auf:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Möchtest du ein Update für diese bestehende App installieren? Deine vorhandenen Daten bleiben erhalten. Die App benötigt keine besonderen Zugriffsrechte."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Möchtest du ein Update für diese integrierte App installieren? Deine vorhandenen Daten bleiben erhalten. Die App benötigt keine besonderen Zugriffsrechte."</string>
+    <string name="install_failed" msgid="6579998651498970899">"App wurde nicht installiert."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Die Installation des Pakets wurde blockiert."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Die App wurde nicht installiert, da das Paket in Konflikt mit einem bestehenden Paket steht."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Die App wurde nicht installiert, da sie nicht mit deinem Tablet kompatibel ist."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Diese App ist nicht mit deinem Fernseher kompatibel."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Die App wurde nicht installiert, da sie nicht mit deinem Smartphone kompatibel ist."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Die App wurde nicht installiert, da das Paket offenbar ungültig ist."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> konnte nicht auf deinem Tablet installiert werden."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> konnte nicht auf deinem Fernseher installiert werden."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> konnte nicht auf deinem Telefon installiert werden."</string>
+    <string name="launch" msgid="4826921505917605463">"Öffnen"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Dein Administrator lässt keine Installationen von Apps aus unbekannten Quellen zu"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Dieser Nutzer darf keine unbekannten Apps installieren"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Dieser Nutzer darf keine Apps installieren"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Apps verwalten"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Kein freier Speicher vorhanden"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> konnte nicht installiert werden. Gib Speicherplatz frei und versuche es erneut."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"App nicht gefunden"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Die App wurde nicht in der Liste der installierten Apps gefunden."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Keine Berechtigung"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Der aktuelle Nutzer ist nicht dazu berechtigt, diese Deinstallation auszuführen."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Fehler"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"App konnte nicht deinstalliert werden."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"App deinstallieren"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Update deinstallieren"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> gehört zu folgender App:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Möchtest du diese App deinstallieren?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Möchtest du diese App für "<b>"alle"</b>" Nutzer entfernen? Die App und alle zugehörigen Daten werden für "<b>"alle"</b>" Nutzer des Geräts entfernt."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Möchtest du diese App für den Nutzer <xliff:g id="USERNAME">%1$s</xliff:g> deinstallieren?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Diese App durch die Werksversion ersetzen? Alle Daten werden entfernt."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Diese App durch die Werksversion ersetzen? Alle Daten werden entfernt. Dies betrifft alle Nutzer des Geräts, einschließlich Arbeitsprofilen."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Laufende Deinstallationen"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Fehlgeschlagene Deinstallationen"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Wird deinstalliert..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> wird deinstalliert…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Deinstallation abgeschlossen"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> deinstalliert"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Deinstallation fehlgeschlagen"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Deinstallation von <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> fehlgeschlagen."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Aktive Apps zur Geräteverwaltung können nicht deinstalliert werden"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Die aktive App zur Geräteverwaltung kann nicht für <xliff:g id="USERNAME">%1$s</xliff:g> deinstalliert werden"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Diese App wird für einige Nutzer oder Profile benötigt und wurde für andere deinstalliert"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Diese App wird für dein Profil benötigt und kann nicht deinstalliert werden."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Die App wurde als obligatorisch festgelegt und kann nicht deinstalliert werden."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Apps zur Geräteverwaltung"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Nutzer verwalten"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> konnte nicht deinstalliert werden."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Beim Parsen des Pakets ist ein Problem aufgetreten."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Neu"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Alle"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Datenschutz"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Gerätezugriff"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Für dieses Update sind keine neuen Berechtigungen erforderlich."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Ablehnen"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Weitere Informationen"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Trotzdem ablehnen"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> von <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Zulassen, dass die App &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g> darf?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; immer erlauben zu <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Nur während der App-Nutzung"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Immer"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Ablehnen und nicht mehr fragen"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> deaktiviert"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"Alle deaktiviert"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"Keine deaktiviert"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Zulassen"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apps"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"App-Berechtigungen"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Nicht mehr fragen"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Keine Berechtigungen"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Zusätzliche Berechtigungen"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"App-Info öffnen"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other">Noch <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Noch <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Diese App wurde für eine ältere Version von Android konzipiert. Wenn du keine Berechtigung erteilst, funktioniert die App möglicherweise nicht mehr ordnungsgemäß."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"Unbekannte Aktion durchführen"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> von <xliff:g id="COUNT_1">%2$d</xliff:g> Apps sind berechtigt."</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"System-Apps anzeigen"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"System ausblenden"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Keine Apps"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Standorteinstellungen"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> ist ein Anbieter von Standortdiensten für dieses Gerät. Die Berechtigungen für den Zugriff auf deinen Standort kannst du in den Standorteinstellungen ändern."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Wenn du diese Berechtigung deaktivierst, funktionieren grundlegende Funktionen deines Geräts möglicherweise nicht mehr ordnungsgemäß."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Von Richtlinien durchgesetzt"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Hintergrundzugriff aufgrund der Richtlinie deaktiviert"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Hintergrundzugriff aufgrund der Richtlinie aktiviert"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Vordergrundzugriff aufgrund der Richtlinie aktiviert"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Durch den Administrator verwaltet"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Immer"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Nur während der App-Nutzung"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nie"</string>
+    <string name="loading" msgid="7811651799620593731">"Wird geladen…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Alle Berechtigungen"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Andere App-Funktionen"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Berechtigungsanfrage"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Display-Overlay erkannt"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Um diese Berechtigungseinstellung zu ändern, musst du zunächst das Display-Overlay über \"Einstellungen\" &gt; \"Apps\" deaktivieren."</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Einstellungen öffnen"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Von Android Wear nicht unterstützte Aktionen installieren/deinstallieren."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Worauf darf die App &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; zugreifen?"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Die App &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wurde aktualisiert. Worauf darf diese App zugreifen?"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Abbrechen"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Weiter"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Neue Berechtigungen"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Aktuelle Berechtigungen"</string>
+    <string name="message_staging" msgid="6151794817691100003">"App wird vorbereitet…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Unbekannt"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Aus Sicherheitsgründen kannst du auf dem Tablet keine unbekannten Apps aus dieser Quelle installieren."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Aus Sicherheitsgründen kannst du auf dem Fernseher keine unbekannten Apps aus dieser Quelle installieren."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Aus Sicherheitsgründen kannst du auf dem Smartphone keine unbekannten Apps aus dieser Quelle installieren."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Unbekannte Apps können gefährlich für dein Smartphone und deine personenbezogenen Daten sein. Indem du diese App installierst, erklärst du dich damit einverstanden, dass du die Verantwortung für alle Schäden an deinem Smartphone und jegliche Datenverluste trägst, die aus der Verwendung dieser App entstehen können."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Unbekannte Apps können gefährlich für dein Tablet und deine personenbezogenen Daten sein. Indem du diese App installierst, erklärst du dich damit einverstanden, dass du die Verantwortung für alle Schäden an deinem Tablet und jegliche Datenverluste trägst, die aus der Verwendung dieser App entstehen können."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Unbekannte Apps können gefährlich für deinen Fernseher und deine personenbezogenen Daten sein. Indem du diese App installierst, erklärst du dich damit einverstanden, dass du die Verantwortung für alle Schäden an deinem Fernseher und jegliche Datenverluste trägst, die aus der Verwendung dieser App entstehen können."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Weiter"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Einstellungen"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear-Apps installieren/deinstallieren"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-el-television/strings.xml b/packages/PackageInstaller/res/values-el-television/strings.xml
new file mode 100644
index 0000000..44f77a9
--- /dev/null
+++ b/packages/PackageInstaller/res/values-el-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Απόρριψη και να μην ερωτηθώ ξανά"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Μπορείτε να το αλλάξετε αυτό αργότερα από το μενού Ρυθμίσεις &gt; Εφαρμογές"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Εμφάνιση εφαρμογών συστήματος"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Άδειες εφαρμογών"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Άδειες εφαρμογών"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Άδειες - <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Πρόσθετες άδειες"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Άδειες - <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-el-watch/strings.xml b/packages/PackageInstaller/res/values-el-watch/strings.xml
new file mode 100644
index 0000000..3d923dc
--- /dev/null
+++ b/packages/PackageInstaller/res/values-el-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Απόρριψη και να μην ερωτηθώ ξανά"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Εμφάνιση εφαρμογών συστήματος"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Δεν είναι δυνατή η αλλαγή"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ναι"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Ακύρωση"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-el/strings.xml b/packages/PackageInstaller/res/values-el/strings.xml
new file mode 100644
index 0000000..707f7b1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-el/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Πρόγραμμα εγκατάστασης πακέτου"</string>
+    <string name="next" msgid="3057143178373252333">"Επόμενο"</string>
+    <string name="install" msgid="5896438203900042068">"Εγκατάσταση"</string>
+    <string name="done" msgid="3889387558374211719">"Τέλος"</string>
+    <string name="cancel" msgid="8360346460165114585">"Ακύρωση"</string>
+    <string name="installing" msgid="8613631001631998372">"Εγκατάσταση..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Εγκατάσταση <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Εγκατάσταση εφαρμογής."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Θέλετε να εγκαταστήσετε αυτήν την εφαρμογή; Θα έχει πρόσβαση σε:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Θέλετε να εγκαταστήσετε αυτήν την εφαρμογή; Δεν απαιτείται οποιαδήποτε ειδική πρόσβαση."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Θέλετε να εγκαταστήσετε μια ενημέρωση σε αυτήν την υπάρχουσα εφαρμογή; Τα υπάρχοντα δεδομένα σας δεν θα χαθούν. Η ενημερωμένη εφαρμογή θα έχει πρόσβαση σε:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Θέλετε να εγκαταστήσετε μια ενημέρωση σε αυτήν την ενσωματωμένη εφαρμογή; Τα υπάρχοντα δεδομένα σας δεν θα χαθούν. Η ενημερωμένη εφαρμογή θα έχει πρόσβαση σε:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Θέλετε να εγκαταστήσετε μια ενημέρωση για αυτήν την υπάρχουσα εφαρμογή; Τα υπάρχοντα δεδομένα σας δεν θα χαθούν. Δεν απαιτείται ειδική πρόσβαση."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Θέλετε να εγκαταστήσετε μια ενημέρωση για αυτήν την ενσωματωμένη εφαρμογή; Τα υπάρχοντα δεδομένα σας δεν θα χαθούν. Δεν απαιτείται ειδική πρόσβαση."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Η εφαρμογή δεν έχει εγκατασταθεί."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Η εγκατάσταση του πακέτου αποκλείστηκε."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Η εφαρμογή δεν έχει εγκατασταθεί, επειδή το πακέτο έρχεται σε διένεξη με κάποιο υπάρχον πακέτο."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Η εφαρμογή δεν έχει εγκατασταθεί, επειδή δεν είναι συμβατή με το tablet που χρησιμοποιείτε."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Αυτή η εφαρμογή δεν είναι συμβατή με την τηλεόρασή σας."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Η εφαρμογή δεν έχει εγκατασταθεί, επειδή δεν είναι συμβατή με το τηλέφωνό σας."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Η εφαρμογή δεν έχει εγκατασταθεί, επειδή φαίνεται ότι το πακέτο δεν είναι έγκυρο."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Δεν ήταν δυνατή η εγκατάσταση της εφαρμογής <xliff:g id="APP_NAME">%1$s</xliff:g> στο tablet σας."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν ήταν δυνατό να εγκατασταθεί στην τηλεόρασή σας."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Δεν ήταν δυνατή η εγκατάσταση της εφαρμογής <xliff:g id="APP_NAME">%1$s</xliff:g> στο τηλέφωνό σας."</string>
+    <string name="launch" msgid="4826921505917605463">"Άνοιγμα"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Ο διαχειριστής σας δεν επιτρέπει την εγκατάσταση εφαρμογών που προέρχονται από άγνωστες πηγές"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Δεν είναι δυνατή η εγκατάσταση άγνωστων εφαρμογών από αυτόν τον χρήστη"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Αυτός ο χρήστης δεν έχει δυνατότητα εγκατάστασης εφαρμογών."</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Διαχείριση εφαρμογών"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Δεν υπάρχει χώρος"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Δεν ήταν δυνατή η εγκατάσταση της εφαρμογής <xliff:g id="APP_NAME">%1$s</xliff:g>. Απελευθερώστε λίγο χώρο και προσπαθήστε ξανά."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Δεν βρέθηκε εφαρμογή"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Η εφαρμογή δεν βρέθηκε στη λίστα με τις εγκατεστημένες εφαρμογές."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Δεν επιτρέπεται"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Δεν επιτρέπεται στον τρέχοντα χρήση να εκτελέσει την απεγκατάσταση."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Σφάλμα"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Δεν ήταν δυνατή η απεγκατάσταση της εφαρμογής."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Απεγκατάσταση εφαρμογής"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Απεγκατάσταση ενημέρωσης"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"Η δραστηριότητα <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> αποτελεί τμήμα της ακόλουθης εφαρμογής:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Θέλετε να καταργήσετε την εγκατάσταση αυτής της εφαρμογής;"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Θέλετε να καταργήσετε την εγκατάσταση αυτής της εφαρμογής για "<b>"όλους"</b>" τους χρήστες; Η εφαρμογή και τα δεδομένα της θα καταργηθούν από "<b>"όλους"</b>" τους χρήστες στη συσκευή."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Θέλετε να καταργήσετε την εγκατάσταση αυτής της εφαρμογής για το χρήστη <xliff:g id="USERNAME">%1$s</xliff:g>;"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Αντικατάσταση αυτής της εφαρμογής με την εργοστασιακή έκδοση; Όλα τα δεδομένα θα καταργηθούν."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Αντικατάσταση αυτής της εφαρμογής με την εργοστασιακή έκδοση; Όλα τα δεδομένα θα καταργηθούν. Αυτό επηρεάζει όλους τους χρήστες της συσκευής, συμπεριλαμβανομένων και αυτών με προφίλ εργασίας."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Απεγκαταστάσεις σε εξέλιξη"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Αποτυχημένες απεγκαταστάσεις"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Απεγκατάσταση..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Απεγκατάσταση <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Η κατάργηση εγκατάστασης ολοκληρώθηκε."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Απεγκαταστάθηκε <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Μη επιτυχής κατάργηση εγκατάστασης."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Επιτυχής απεγκατάσταση <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Η κατάργ. εγκατάστ. της ενεργούς εφαρμογής διαχείρισης συσκευής δεν είναι δυνατή"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Η κατάργ. εγκατάστασης της ενεργούς εφαρμογής διαχείρισης συσκευής για τον χρήστη <xliff:g id="USERNAME">%1$s</xliff:g> δεν είναι δυνατή"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Η εφαρμογή απαιτείται για κάποιους χρήστες/προφίλ και απεγκαταστήθηκε για άλλους"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Αυτή η εφαρμογή απαιτείται για το προφίλ σας και δεν είναι δυνατή η απεγκατάστασή της."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Η εφαρμογή απαιτείται από το διαχειριστή και δεν είναι δυνατή η απεγκατάσταση."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Διαχείριση εφαρμογών διαχείρισης συσκευής"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Διαχείριση χρηστών"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Δεν ήταν δυνατή η κατάργηση της εγκατάστασης της εφαρμογής <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Παρουσιάστηκε ένα πρόβλημα κατά την ανάλυση του πακέτου."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Νέο"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Όλα"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Απόρρητο"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Πρόσβαση συσκευής"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Αυτή η ενημέρωση δεν απαιτεί νέες άδειες."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Απόρριψη"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Περισσότερες πληροφορίες"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Απόρριψη"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> από <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να <xliff:g id="ACTION">%2$s</xliff:g>;"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Να επιτρέπεται πάντα στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να <xliff:g id="ACTION">%2$s</xliff:g>;"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Μόνο κατά τη χρήση της εφαρμογής"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Πάντα"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Απόρριψη και να μην ερωτηθώ ξανά"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"έχουν απενεργοποιηθεί <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"έχουν απενεργοποιηθεί όλες"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"δεν έχει απενεργοποιηθεί καμία"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Να επιτρέπεται"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Εφαρμογές"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Δικαιώματα εφ/γών"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Να μην ερωτηθώ ξανά"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Χωρίς δικαιώματα"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Πρόσθετα δικαιώματα"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Άνοιγμα πληροφοριών εφαρμογής"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Η άρνηση άδειας μπορεί να έχει ως αποτέλεσμα να διακοπεί η κανονική λειτουργία της."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"εκτέλεση άγνωστης ενέργειας"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Επιτρέπονται <xliff:g id="COUNT_0">%1$d</xliff:g> από <xliff:g id="COUNT_1">%2$d</xliff:g> εφαρμογές"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Εμφάνιση συστήματος"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Απόκρυψη συστήματος"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Δεν υπάρχουν εφαρμογές"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Ρυθμίσεις τοποθεσίας"</string>
+    <string name="location_warning" msgid="8778701356292735971">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> είναι ο πάροχος των υπηρεσιών τοποθεσίας για τη συγκεκριμένη συσκευή. Μπορείτε να τροποποιήσετε την πρόσβαση τοποθεσίας από τις ρυθμίσεις τοποθεσίας."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Εάν αρνηθείτε να παραχωρήσετε αυτήν την άδεια, η λειτουργία ορισμένων βασικών δυνατοτήτων ενδέχεται να μην είναι η αναμενόμενη."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Επιβάλλεται από την πολιτική"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Η πρόσβαση στο παρασκήνιο απενενεργοποιήθηκε βάσει πολιτικής"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Η πρόσβαση στο παρασκήνιο ενεργοποιήθηκε βάσει πολιτικής"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Η πρόσβαση στο προσκήνιο ενεργοποιήθηκε βάσει πολιτικής"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Ελέγχεται από τον διαχειριστή"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Πάντα"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Μόνο κατά τη χρήση της εφαρμ."</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Ποτέ"</string>
+    <string name="loading" msgid="7811651799620593731">"Γίνεται φόρτωση…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Όλα τα δικαιώματα"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Άλλες δυνατότητες εφαρμογής"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Αίτημα άδειας"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Εντοπίστηκε επικάλυψη οθόνης"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Για να αλλάξετε αυτή τη ρύθμιση άδειας, θα πρέπει πρώτα να απενεργοποιήσετε την επικάλυψη οθόνης από τις Ρυθμίσεις &gt; Εφαρμογές"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Άνοιγμα ρυθμίσεων"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Οι ενέργειες εγκατάστασης/απεγκατάστασης δεν υποστηρίζονται στο Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Επιλέξτε σε τι θα έχει πρόσβαση η εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Η εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ενημερώθηκε. Επιλέξτε σε τι θα έχει πρόσβαση αυτή η εφαρμογή."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Ακύρωση"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Συνέχεια"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Νέες άδειες"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Τρέχουσες άδειες"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Σταδιακή διάθεση εφαρμογής…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Άγνωστη"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Για λόγους ασφάλειας, δεν επιτρέπεται η εγκατάσταση άγνωστων εφαρμογών από αυτήν την πηγή στο tablet σας."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Για λόγους ασφάλειας, δεν επιτρέπεται η εγκατάσταση άγνωστων εφαρμογών από αυτήν την πηγή στην τηλεόρασή σας."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Για λόγους ασφάλειας, δεν επιτρέπεται η εγκατάσταση άγνωστων εφαρμογών από αυτήν την πηγή στο τηλέφωνό σας."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Το τηλέφωνό σας και τα προσωπικά δεδομένα σας είναι πιο ευάλωτα σε επιθέσεις από άγνωστες εφαρμογές. Με την εγκατάσταση αυτής της εφαρμογής, συμφωνείτε ότι είστε υπεύθυνοι για οποιαδήποτε ζημιά στο τηλέφωνο ή απώλεια δεδομένων που μπορεί να προκύψει από τη χρήση τους."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Το tablet σας και τα προσωπικά δεδομένα σας είναι πιο ευάλωτα σε επιθέσεις από άγνωστες εφαρμογές. Με την εγκατάσταση αυτής της εφαρμογής, συμφωνείτε ότι είστε υπεύθυνοι για οποιαδήποτε ζημιά στο tablet ή απώλεια δεδομένων που μπορεί να προκύψει από τη χρήση τους."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Η τηλεόρασή σας και τα προσωπικά δεδομένα σας είναι πιο ευάλωτα σε επιθέσεις από άγνωστες εφαρμογές. Με την εγκατάσταση αυτής της εφαρμογής, συμφωνείτε ότι είστε υπεύθυνοι για οποιαδήποτε ζημιά στην τηλεόρασή ή απώλεια δεδομένων που μπορεί να προκύψει από τη χρήση τους."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Συνέχεια"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Ρυθμίσεις"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Εγκατάσταση/απεγκατάσταση εφαρμογών Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rAU-television/strings.xml b/packages/PackageInstaller/res/values-en-rAU-television/strings.xml
new file mode 100644
index 0000000..663e1d4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rAU-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Deny and don\'t ask again"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"You can change this later in Settings &gt; Apps"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Show system apps"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"App permissions"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"App permissions"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> permissions"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Additional permissions"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> permissions"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rAU-watch/strings.xml b/packages/PackageInstaller/res/values-en-rAU-watch/strings.xml
new file mode 100644
index 0000000..e0d0edbc
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rAU-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Deny, don\'t ask again"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Show system apps"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Can\'t be changed"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Yes"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancel"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rAU/strings.xml b/packages/PackageInstaller/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..ded57bb
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rAU/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Package installer"</string>
+    <string name="next" msgid="3057143178373252333">"Next"</string>
+    <string name="install" msgid="5896438203900042068">"Install"</string>
+    <string name="done" msgid="3889387558374211719">"Done"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancel"</string>
+    <string name="installing" msgid="8613631001631998372">"Installing…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installing <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"App installed."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Do you want to install this application? It will get access to:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Do you want to install this application? It does not require any special access."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Do you want to install an update to this existing application? Your existing data will not be lost. The updated application will get access to:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Do you want to install an update to this built-in application? Your existing data will not be lost. The updated application will get access to:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Do you want to install an update to this existing application? Your existing data will not be lost. It does not require any special access."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Do you want to install an update to this built-in application? Your existing data will not be lost. It does not require any special access."</string>
+    <string name="install_failed" msgid="6579998651498970899">"App not installed."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"The package was blocked from being installed."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"App not installed as package conflicts with an existing package."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"App not installed as app isn\'t compatible with your tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"This app isn\'t compatible with your TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"App not installed as app isn\'t compatible with your phone."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"App not installed as package appears to be invalid."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your phone."</string>
+    <string name="launch" msgid="4826921505917605463">"Open"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Your admin doesn\'t allow installation of apps obtained from unknown sources"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Unknown apps can\'t be installed by this user"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"This user is not allowed to install apps"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Manage apps"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Out of space"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed. Free up some space and try again."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"App not found"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"The app wasn\'t found in the list of installed apps."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Not allowed"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"The current user is not allowed to perform this uninstallation."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Error"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"App could not be uninstalled."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Uninstall app"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Uninstall update"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is part of the following app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Do you want to uninstall this app?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Do you want to uninstall this app for "<b>"all"</b>" users? The application and its data will be removed from "<b>"all"</b>" users on the device."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Do you want to uninstall this app for the user <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Replace this app with the factory version? All data will be removed."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Replace this app with the factory version? All data will be removed. This affects all users of this device, including those with work profiles."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Running uninstalls"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Failed uninstalls"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Uninstalling…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Uninstalling <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Uninstall finished"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Uninstalled <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Uninstall unsuccessful."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Uninstalling <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> unsuccessful."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Can\'t uninstall active device admin app"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Can\'t uninstall active device admin app for <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"This app is required for some users or profiles and was uninstalled for others"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"This app is needed for your profile and can\'t be uninstalled."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"This app is required by your device administrator and can\'t be uninstalled."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Manage device admin apps"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Manage users"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be uninstalled."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"There was a problem while parsing the package."</string>
+    <string name="newPerms" msgid="6039428254474104210">"New"</string>
+    <string name="allPerms" msgid="1024385515840703981">"All"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacy"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Device Access"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"This update requires no new permissions."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Deny"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"More info"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Deny anyway"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> of <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Always allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Only while using app"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Always"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Deny and don’t ask again"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> disabled"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"all disabled"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"none disabled"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Allow"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apps"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"App permissions"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Don\'t ask again"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"No permissions"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Additional permissions"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Open app info"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> more</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> more</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"This app was designed for an older version of Android. Denying permission may cause it to no longer function as intended."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"perform an unknown action"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> of <xliff:g id="COUNT_1">%2$d</xliff:g> apps allowed"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Show system"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Hide system"</string>
+    <string name="no_apps" msgid="1965493419005012569">"No apps"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Location Settings"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> is a provider of location services for this device. Location access can be modified from location settings."</string>
+    <string name="system_warning" msgid="7103819124542305179">"If you deny this permission, basic features of your device may no longer function as intended."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Enforced by policy"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Background access disabled by policy"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Background access enabled by policy"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Foreground access enabled by policy"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlled by admin"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Always"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Only while using app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Never"</string>
+    <string name="loading" msgid="7811651799620593731">"Loading…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"All permissions"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Other app capabilities"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Permission request"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Screen overlay detected"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"To change this permission setting, you first have to turn off the screen overlay from Settings &gt; Apps"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Open settings"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Install/Uninstall actions not supported on Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Choose what to allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; has been updated. Choose what to allow this app to access."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancel"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continue"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"New permissions"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Current permissions"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Staging app…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Unknown"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"For your security, your tablet is not allowed to install unknown apps from this source."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"For your security, your TV is not allowed to install unknown apps from this source."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"For your security, your phone is not allowed to install unknown apps from this source."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Your phone and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your phone or loss of data that may result from its use."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continue"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Settings"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installing/uninstalling Wear apps"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rCA-television/strings.xml b/packages/PackageInstaller/res/values-en-rCA-television/strings.xml
new file mode 100644
index 0000000..663e1d4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rCA-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Deny and don\'t ask again"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"You can change this later in Settings &gt; Apps"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Show system apps"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"App permissions"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"App permissions"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> permissions"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Additional permissions"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> permissions"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rCA-watch/strings.xml b/packages/PackageInstaller/res/values-en-rCA-watch/strings.xml
new file mode 100644
index 0000000..e0d0edbc
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rCA-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Deny, don\'t ask again"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Show system apps"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Can\'t be changed"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Yes"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancel"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rCA/strings.xml b/packages/PackageInstaller/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..ded57bb
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rCA/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Package installer"</string>
+    <string name="next" msgid="3057143178373252333">"Next"</string>
+    <string name="install" msgid="5896438203900042068">"Install"</string>
+    <string name="done" msgid="3889387558374211719">"Done"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancel"</string>
+    <string name="installing" msgid="8613631001631998372">"Installing…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installing <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"App installed."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Do you want to install this application? It will get access to:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Do you want to install this application? It does not require any special access."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Do you want to install an update to this existing application? Your existing data will not be lost. The updated application will get access to:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Do you want to install an update to this built-in application? Your existing data will not be lost. The updated application will get access to:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Do you want to install an update to this existing application? Your existing data will not be lost. It does not require any special access."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Do you want to install an update to this built-in application? Your existing data will not be lost. It does not require any special access."</string>
+    <string name="install_failed" msgid="6579998651498970899">"App not installed."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"The package was blocked from being installed."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"App not installed as package conflicts with an existing package."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"App not installed as app isn\'t compatible with your tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"This app isn\'t compatible with your TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"App not installed as app isn\'t compatible with your phone."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"App not installed as package appears to be invalid."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your phone."</string>
+    <string name="launch" msgid="4826921505917605463">"Open"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Your admin doesn\'t allow installation of apps obtained from unknown sources"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Unknown apps can\'t be installed by this user"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"This user is not allowed to install apps"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Manage apps"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Out of space"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed. Free up some space and try again."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"App not found"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"The app wasn\'t found in the list of installed apps."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Not allowed"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"The current user is not allowed to perform this uninstallation."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Error"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"App could not be uninstalled."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Uninstall app"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Uninstall update"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is part of the following app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Do you want to uninstall this app?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Do you want to uninstall this app for "<b>"all"</b>" users? The application and its data will be removed from "<b>"all"</b>" users on the device."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Do you want to uninstall this app for the user <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Replace this app with the factory version? All data will be removed."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Replace this app with the factory version? All data will be removed. This affects all users of this device, including those with work profiles."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Running uninstalls"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Failed uninstalls"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Uninstalling…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Uninstalling <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Uninstall finished"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Uninstalled <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Uninstall unsuccessful."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Uninstalling <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> unsuccessful."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Can\'t uninstall active device admin app"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Can\'t uninstall active device admin app for <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"This app is required for some users or profiles and was uninstalled for others"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"This app is needed for your profile and can\'t be uninstalled."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"This app is required by your device administrator and can\'t be uninstalled."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Manage device admin apps"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Manage users"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be uninstalled."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"There was a problem while parsing the package."</string>
+    <string name="newPerms" msgid="6039428254474104210">"New"</string>
+    <string name="allPerms" msgid="1024385515840703981">"All"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacy"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Device Access"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"This update requires no new permissions."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Deny"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"More info"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Deny anyway"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> of <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Always allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Only while using app"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Always"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Deny and don’t ask again"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> disabled"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"all disabled"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"none disabled"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Allow"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apps"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"App permissions"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Don\'t ask again"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"No permissions"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Additional permissions"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Open app info"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> more</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> more</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"This app was designed for an older version of Android. Denying permission may cause it to no longer function as intended."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"perform an unknown action"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> of <xliff:g id="COUNT_1">%2$d</xliff:g> apps allowed"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Show system"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Hide system"</string>
+    <string name="no_apps" msgid="1965493419005012569">"No apps"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Location Settings"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> is a provider of location services for this device. Location access can be modified from location settings."</string>
+    <string name="system_warning" msgid="7103819124542305179">"If you deny this permission, basic features of your device may no longer function as intended."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Enforced by policy"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Background access disabled by policy"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Background access enabled by policy"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Foreground access enabled by policy"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlled by admin"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Always"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Only while using app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Never"</string>
+    <string name="loading" msgid="7811651799620593731">"Loading…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"All permissions"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Other app capabilities"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Permission request"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Screen overlay detected"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"To change this permission setting, you first have to turn off the screen overlay from Settings &gt; Apps"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Open settings"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Install/Uninstall actions not supported on Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Choose what to allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; has been updated. Choose what to allow this app to access."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancel"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continue"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"New permissions"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Current permissions"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Staging app…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Unknown"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"For your security, your tablet is not allowed to install unknown apps from this source."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"For your security, your TV is not allowed to install unknown apps from this source."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"For your security, your phone is not allowed to install unknown apps from this source."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Your phone and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your phone or loss of data that may result from its use."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continue"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Settings"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installing/uninstalling Wear apps"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rGB-television/strings.xml b/packages/PackageInstaller/res/values-en-rGB-television/strings.xml
new file mode 100644
index 0000000..663e1d4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rGB-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Deny and don\'t ask again"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"You can change this later in Settings &gt; Apps"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Show system apps"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"App permissions"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"App permissions"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> permissions"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Additional permissions"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> permissions"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rGB-watch/strings.xml b/packages/PackageInstaller/res/values-en-rGB-watch/strings.xml
new file mode 100644
index 0000000..e0d0edbc
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rGB-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Deny, don\'t ask again"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Show system apps"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Can\'t be changed"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Yes"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancel"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rGB/strings.xml b/packages/PackageInstaller/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..ded57bb
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rGB/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Package installer"</string>
+    <string name="next" msgid="3057143178373252333">"Next"</string>
+    <string name="install" msgid="5896438203900042068">"Install"</string>
+    <string name="done" msgid="3889387558374211719">"Done"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancel"</string>
+    <string name="installing" msgid="8613631001631998372">"Installing…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installing <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"App installed."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Do you want to install this application? It will get access to:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Do you want to install this application? It does not require any special access."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Do you want to install an update to this existing application? Your existing data will not be lost. The updated application will get access to:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Do you want to install an update to this built-in application? Your existing data will not be lost. The updated application will get access to:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Do you want to install an update to this existing application? Your existing data will not be lost. It does not require any special access."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Do you want to install an update to this built-in application? Your existing data will not be lost. It does not require any special access."</string>
+    <string name="install_failed" msgid="6579998651498970899">"App not installed."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"The package was blocked from being installed."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"App not installed as package conflicts with an existing package."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"App not installed as app isn\'t compatible with your tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"This app isn\'t compatible with your TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"App not installed as app isn\'t compatible with your phone."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"App not installed as package appears to be invalid."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your phone."</string>
+    <string name="launch" msgid="4826921505917605463">"Open"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Your admin doesn\'t allow installation of apps obtained from unknown sources"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Unknown apps can\'t be installed by this user"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"This user is not allowed to install apps"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Manage apps"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Out of space"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed. Free up some space and try again."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"App not found"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"The app wasn\'t found in the list of installed apps."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Not allowed"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"The current user is not allowed to perform this uninstallation."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Error"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"App could not be uninstalled."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Uninstall app"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Uninstall update"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is part of the following app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Do you want to uninstall this app?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Do you want to uninstall this app for "<b>"all"</b>" users? The application and its data will be removed from "<b>"all"</b>" users on the device."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Do you want to uninstall this app for the user <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Replace this app with the factory version? All data will be removed."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Replace this app with the factory version? All data will be removed. This affects all users of this device, including those with work profiles."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Running uninstalls"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Failed uninstalls"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Uninstalling…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Uninstalling <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Uninstall finished"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Uninstalled <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Uninstall unsuccessful."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Uninstalling <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> unsuccessful."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Can\'t uninstall active device admin app"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Can\'t uninstall active device admin app for <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"This app is required for some users or profiles and was uninstalled for others"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"This app is needed for your profile and can\'t be uninstalled."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"This app is required by your device administrator and can\'t be uninstalled."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Manage device admin apps"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Manage users"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be uninstalled."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"There was a problem while parsing the package."</string>
+    <string name="newPerms" msgid="6039428254474104210">"New"</string>
+    <string name="allPerms" msgid="1024385515840703981">"All"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacy"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Device Access"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"This update requires no new permissions."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Deny"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"More info"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Deny anyway"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> of <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Always allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Only while using app"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Always"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Deny and don’t ask again"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> disabled"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"all disabled"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"none disabled"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Allow"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apps"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"App permissions"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Don\'t ask again"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"No permissions"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Additional permissions"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Open app info"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> more</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> more</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"This app was designed for an older version of Android. Denying permission may cause it to no longer function as intended."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"perform an unknown action"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> of <xliff:g id="COUNT_1">%2$d</xliff:g> apps allowed"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Show system"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Hide system"</string>
+    <string name="no_apps" msgid="1965493419005012569">"No apps"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Location Settings"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> is a provider of location services for this device. Location access can be modified from location settings."</string>
+    <string name="system_warning" msgid="7103819124542305179">"If you deny this permission, basic features of your device may no longer function as intended."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Enforced by policy"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Background access disabled by policy"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Background access enabled by policy"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Foreground access enabled by policy"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlled by admin"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Always"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Only while using app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Never"</string>
+    <string name="loading" msgid="7811651799620593731">"Loading…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"All permissions"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Other app capabilities"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Permission request"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Screen overlay detected"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"To change this permission setting, you first have to turn off the screen overlay from Settings &gt; Apps"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Open settings"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Install/Uninstall actions not supported on Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Choose what to allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; has been updated. Choose what to allow this app to access."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancel"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continue"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"New permissions"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Current permissions"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Staging app…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Unknown"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"For your security, your tablet is not allowed to install unknown apps from this source."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"For your security, your TV is not allowed to install unknown apps from this source."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"For your security, your phone is not allowed to install unknown apps from this source."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Your phone and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your phone or loss of data that may result from its use."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continue"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Settings"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installing/uninstalling Wear apps"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rIN-television/strings.xml b/packages/PackageInstaller/res/values-en-rIN-television/strings.xml
new file mode 100644
index 0000000..663e1d4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rIN-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Deny and don\'t ask again"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"You can change this later in Settings &gt; Apps"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Show system apps"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"App permissions"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"App permissions"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> permissions"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Additional permissions"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> permissions"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rIN-watch/strings.xml b/packages/PackageInstaller/res/values-en-rIN-watch/strings.xml
new file mode 100644
index 0000000..e0d0edbc
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rIN-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Deny, don\'t ask again"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Show system apps"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Can\'t be changed"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Yes"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancel"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rIN/strings.xml b/packages/PackageInstaller/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..ded57bb
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rIN/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Package installer"</string>
+    <string name="next" msgid="3057143178373252333">"Next"</string>
+    <string name="install" msgid="5896438203900042068">"Install"</string>
+    <string name="done" msgid="3889387558374211719">"Done"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancel"</string>
+    <string name="installing" msgid="8613631001631998372">"Installing…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installing <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"App installed."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Do you want to install this application? It will get access to:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Do you want to install this application? It does not require any special access."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Do you want to install an update to this existing application? Your existing data will not be lost. The updated application will get access to:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Do you want to install an update to this built-in application? Your existing data will not be lost. The updated application will get access to:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Do you want to install an update to this existing application? Your existing data will not be lost. It does not require any special access."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Do you want to install an update to this built-in application? Your existing data will not be lost. It does not require any special access."</string>
+    <string name="install_failed" msgid="6579998651498970899">"App not installed."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"The package was blocked from being installed."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"App not installed as package conflicts with an existing package."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"App not installed as app isn\'t compatible with your tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"This app isn\'t compatible with your TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"App not installed as app isn\'t compatible with your phone."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"App not installed as package appears to be invalid."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed on your phone."</string>
+    <string name="launch" msgid="4826921505917605463">"Open"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Your admin doesn\'t allow installation of apps obtained from unknown sources"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Unknown apps can\'t be installed by this user"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"This user is not allowed to install apps"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Manage apps"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Out of space"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be installed. Free up some space and try again."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"App not found"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"The app wasn\'t found in the list of installed apps."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Not allowed"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"The current user is not allowed to perform this uninstallation."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Error"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"App could not be uninstalled."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Uninstall app"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Uninstall update"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is part of the following app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Do you want to uninstall this app?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Do you want to uninstall this app for "<b>"all"</b>" users? The application and its data will be removed from "<b>"all"</b>" users on the device."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Do you want to uninstall this app for the user <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Replace this app with the factory version? All data will be removed."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Replace this app with the factory version? All data will be removed. This affects all users of this device, including those with work profiles."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Running uninstalls"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Failed uninstalls"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Uninstalling…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Uninstalling <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Uninstall finished"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Uninstalled <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Uninstall unsuccessful."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Uninstalling <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> unsuccessful."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Can\'t uninstall active device admin app"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Can\'t uninstall active device admin app for <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"This app is required for some users or profiles and was uninstalled for others"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"This app is needed for your profile and can\'t be uninstalled."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"This app is required by your device administrator and can\'t be uninstalled."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Manage device admin apps"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Manage users"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be uninstalled."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"There was a problem while parsing the package."</string>
+    <string name="newPerms" msgid="6039428254474104210">"New"</string>
+    <string name="allPerms" msgid="1024385515840703981">"All"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacy"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Device Access"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"This update requires no new permissions."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Deny"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"More info"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Deny anyway"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> of <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Always allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Only while using app"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Always"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Deny and don’t ask again"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> disabled"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"all disabled"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"none disabled"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Allow"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apps"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"App permissions"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Don\'t ask again"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"No permissions"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Additional permissions"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Open app info"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> more</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> more</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"This app was designed for an older version of Android. Denying permission may cause it to no longer function as intended."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"perform an unknown action"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> of <xliff:g id="COUNT_1">%2$d</xliff:g> apps allowed"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Show system"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Hide system"</string>
+    <string name="no_apps" msgid="1965493419005012569">"No apps"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Location Settings"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> is a provider of location services for this device. Location access can be modified from location settings."</string>
+    <string name="system_warning" msgid="7103819124542305179">"If you deny this permission, basic features of your device may no longer function as intended."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Enforced by policy"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Background access disabled by policy"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Background access enabled by policy"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Foreground access enabled by policy"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlled by admin"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Always"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Only while using app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Never"</string>
+    <string name="loading" msgid="7811651799620593731">"Loading…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"All permissions"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Other app capabilities"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Permission request"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Screen overlay detected"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"To change this permission setting, you first have to turn off the screen overlay from Settings &gt; Apps"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Open settings"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Install/Uninstall actions not supported on Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Choose what to allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; has been updated. Choose what to allow this app to access."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancel"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continue"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"New permissions"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Current permissions"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Staging app…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Unknown"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"For your security, your tablet is not allowed to install unknown apps from this source."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"For your security, your TV is not allowed to install unknown apps from this source."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"For your security, your phone is not allowed to install unknown apps from this source."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Your phone and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your phone or loss of data that may result from its use."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continue"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Settings"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installing/uninstalling Wear apps"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rXC-television/strings.xml b/packages/PackageInstaller/res/values-en-rXC-television/strings.xml
new file mode 100644
index 0000000..0f9eeb1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rXC-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎Deny and don\'t ask again‎‏‎‎‏‎"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‎‎‎‎You can change this later in Settings &gt; Apps‎‏‎‎‏‎"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>‎‏‎‎‏‏‏‎ / ‎‏‎‎‏‏‎<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎Show system apps‎‏‎‎‏‎"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎App permissions‎‏‎‎‏‎"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎App permissions‎‏‎‎‏‎"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="PERMISSION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ permissions‎‏‎‎‏‎"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎Additional permissions‎‏‎‎‏‎"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERMISSION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ permissions‎‏‎‎‏‎"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rXC-watch/strings.xml b/packages/PackageInstaller/res/values-en-rXC-watch/strings.xml
new file mode 100644
index 0000000..89b2ea2
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rXC-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‏‎‏‎‎Deny, don\'t ask again‎‏‎‎‏‎"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>‎‏‎‎‏‏‏‎ / ‎‏‎‎‏‏‎<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‏‎Show system apps‎‏‎‎‏‎"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‎‎Can\'t be changed‎‏‎‎‏‎"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‎Yes‎‏‎‎‏‎"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎Cancel‎‏‎‎‏‎"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-en-rXC/strings.xml b/packages/PackageInstaller/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..ca392cc
--- /dev/null
+++ b/packages/PackageInstaller/res/values-en-rXC/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎Package installer‎‏‎‎‏‎"</string>
+    <string name="next" msgid="3057143178373252333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‏‎Next‎‏‎‎‏‎"</string>
+    <string name="install" msgid="5896438203900042068">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎‎Install‎‏‎‎‏‎"</string>
+    <string name="done" msgid="3889387558374211719">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‎‎‎‏‏‏‎Done‎‏‎‎‏‎"</string>
+    <string name="cancel" msgid="8360346460165114585">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‎‏‏‎‎‏‎Cancel‎‏‎‎‏‎"</string>
+    <string name="installing" msgid="8613631001631998372">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‎Installing…‎‏‎‎‏‎"</string>
+    <string name="installing_app" msgid="4097935682329028894">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎Installing ‎‏‎‎‏‏‎<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎…‎‏‎‎‏‎"</string>
+    <string name="install_done" msgid="3682715442154357097">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎App installed.‎‏‎‎‏‎"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‎‏‏‎‎‏‎‎Do you want to install this application? It will get access to:‎‏‎‎‏‎"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‎‎Do you want to install this application? It does not require any special access.‎‏‎‎‏‎"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‏‎‎‎Do you want to install an update to this existing application? Your existing data will not be lost. The updated application will get access to:‎‏‎‎‏‎"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‎‎Do you want to install an update to this built-in application? Your existing data will not be lost. The updated application will get access to:‎‏‎‎‏‎"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎Do you want to install an update to this existing application? Your existing data will not be lost. It does not require any special access.‎‏‎‎‏‎"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎‏‎‏‏‎‎Do you want to install an update to this built-in application? Your existing data will not be lost. It does not require any special access.‎‏‎‎‏‎"</string>
+    <string name="install_failed" msgid="6579998651498970899">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎App not installed.‎‏‎‎‏‎"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎The package was blocked from being installed.‎‏‎‎‏‎"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎App not installed as package conflicts with an existing package.‎‏‎‎‏‎"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎App not installed as app isn\'t compatible with your tablet.‎‏‎‎‏‎"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎This app isn\'t compatible with your TV.‎‏‎‎‏‎"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎App not installed as app isn\'t compatible with your phone.‎‏‎‎‏‎"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎App not installed as package appears to be invalid.‎‏‎‎‏‎"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ couldn\'t be installed on your tablet.‎‏‎‎‏‎"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ couldn\'t be installed on your TV.‎‏‎‎‏‎"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ couldn\'t be installed on your phone.‎‏‎‎‏‎"</string>
+    <string name="launch" msgid="4826921505917605463">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‏‎Open‎‏‎‎‏‎"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎Your admin doesn\'t allow installation of apps obtained from unknown sources‎‏‎‎‏‎"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎Unknown apps can\'t be installed by this user‎‏‎‎‏‎"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎This user is not allowed to install apps‎‏‎‎‏‎"</string>
+    <string name="ok" msgid="3468756155452870475">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‎OK‎‏‎‎‏‎"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎Manage apps‎‏‎‎‏‎"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎Out of space‎‏‎‎‏‎"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ couldn\'t be installed. Free up some space and try again.‎‏‎‎‏‎"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‎‎App not found‎‏‎‎‏‎"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‎‏‎‎The app wasn\'t found in the list of installed apps.‎‏‎‎‏‎"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‎‏‎‎‎‎‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎Not allowed‎‏‎‎‏‎"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎The current user is not allowed to perform this uninstallation.‎‏‎‎‏‎"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎Error‎‏‎‎‏‎"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‎‎‎‏‎‎App could not be uninstalled.‎‏‎‎‏‎"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎Uninstall app‎‏‎‎‏‎"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‎‎Uninstall update‎‏‎‎‏‎"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is part of the following app:‎‏‎‎‏‎"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‏‏‎‎Do you want to uninstall this app?‎‏‎‎‏‎"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎Do you want to uninstall this app for ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎all‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ users? The application and its data will be removed from ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎all‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ users on the device.‎‏‎‎‏‎"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‎Do you want to uninstall this app for the user ‎‏‎‎‏‏‎<xliff:g id="USERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‎Replace this app with the factory version? All data will be removed.‎‏‎‎‏‎"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‏‏‎Replace this app with the factory version? All data will be removed. This affects all users of this device, including those with work profiles.‎‏‎‎‏‎"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎‎‏‏‏‏‎Running uninstalls‎‏‎‎‏‎"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎Failed uninstalls‎‏‎‎‏‎"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎Uninstalling…‎‏‎‎‏‎"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎Uninstalling ‎‏‎‎‏‏‎<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎…‎‏‎‎‏‎"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‎‎‎Uninstall finished.‎‏‎‎‏‎"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎Uninstalled ‎‏‎‎‏‏‎<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‎Uninstall unsuccessful.‎‏‎‎‏‎"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎Uninstalling ‎‏‎‎‏‏‎<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ unsuccessful.‎‏‎‎‏‎"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎Can\'t uninstall active device admin app‎‏‎‎‏‎"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎‎Can\'t uninstall active device admin app for ‎‏‎‎‏‏‎<xliff:g id="USERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‎‎This app is required for some users or profiles and was uninstalled for others‎‏‎‎‏‎"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎This app is needed for your profile and can\'t be uninstalled.‎‏‎‎‏‎"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎This app is required by your device administrator and can\'t be uninstalled.‎‏‎‎‏‎"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎Manage device admin apps‎‏‎‎‏‎"</string>
+    <string name="manage_users" msgid="3125018886835668847">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‎Manage users‎‏‎‎‏‎"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ couldn\'t be uninstalled.‎‏‎‎‏‎"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎There was a problem parsing the package.‎‏‎‎‏‎"</string>
+    <string name="newPerms" msgid="6039428254474104210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎‎New‎‏‎‎‏‎"</string>
+    <string name="allPerms" msgid="1024385515840703981">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‏‎All‎‏‎‎‏‎"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎Privacy‎‏‎‎‏‎"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‎‎Device Access‎‏‎‎‏‎"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‏‏‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‏‏‎This update requires no new permissions.‎‏‎‎‏‎"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎Deny‎‏‎‎‏‎"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎More info‎‏‎‎‏‎"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‎Deny anyway‎‏‎‎‏‎"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>‎‏‎‎‏‏‏‎ of ‎‏‎‎‏‏‎<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to ‎‏‎‎‏‏‎<xliff:g id="ACTION">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎Always allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to ‎‏‎‎‏‏‎<xliff:g id="ACTION">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‎Only while using app‎‏‎‎‏‎"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‎Always‎‏‎‎‏‎"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎Deny and don’t ask again‎‏‎‎‏‎"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="COUNT">%1$d</xliff:g>‎‏‎‎‏‏‏‎ disabled‎‏‎‎‏‎"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‏‎‎all disabled‎‏‎‎‏‎"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‎‏‏‏‎‎none disabled‎‏‎‎‏‎"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎Allow‎‏‎‎‏‎"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎Apps‎‏‎‎‏‎"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎App permissions‎‏‎‎‏‎"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎Don\'t ask again‎‏‎‎‏‎"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‎‎‎‏‎‏‏‎‎No permissions‎‏‎‎‏‎"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‎Additional permissions‎‏‎‎‏‎"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎Open app info‎‏‎‎‏‎"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="COUNT_1">%1$d</xliff:g>‎‏‎‎‏‏‏‎ more‎‏‎‎‏‎</item>
+      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="COUNT_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ more‎‏‎‎‏‎</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‏‏‏‎This app was designed for an older version of Android. Denying permission may cause it to no longer function as intended.‎‏‎‎‏‎"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‎‎perform an unknown action‎‏‎‎‏‎"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="COUNT_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ of ‎‏‎‎‏‏‎<xliff:g id="COUNT_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ apps allowed‎‏‎‎‏‎"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‎Show system‎‏‎‎‏‎"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎Hide system‎‏‎‎‏‎"</string>
+    <string name="no_apps" msgid="1965493419005012569">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎No apps‎‏‎‎‏‎"</string>
+    <string name="location_settings" msgid="1774875730854491297">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎Location Settings‎‏‎‎‏‎"</string>
+    <string name="location_warning" msgid="8778701356292735971">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is a provider of location services for this device. Location access can be modified from location settings.‎‏‎‎‏‎"</string>
+    <string name="system_warning" msgid="7103819124542305179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‎‏‏‎If you deny this permission, basic features of your device may no longer function as intended.‎‏‎‎‏‎"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎Enforced by policy‎‏‎‎‏‎"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‏‎Background access disabled by policy‎‏‎‎‏‎"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‎‎Background access enabled by policy‎‏‎‎‏‎"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‏‎‏‎‎‎Foreground access enabled by policy‎‏‎‎‏‎"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎Controlled by admin‎‏‎‎‏‎"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎Always‎‏‎‎‏‎"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎Only while using app‎‏‎‎‏‎"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎Never‎‏‎‎‏‎"</string>
+    <string name="loading" msgid="7811651799620593731">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‏‎Loading…‎‏‎‎‏‎"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎All permissions‎‏‎‎‏‎"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‏‏‏‎‎‏‏‏‎‏‎Other app capabilities‎‏‎‎‏‎"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‎Permission request‎‏‎‎‏‎"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎‏‎Screen overlay detected‎‏‎‎‏‎"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎To change this permission setting, you first have to turn off the screen overlay from Settings &gt; Apps‎‏‎‎‏‎"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‎Open settings‎‏‎‎‏‎"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎Android Wear‎‏‎‎‏‎"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‎‎Install/Uninstall actions not supported on Wear.‎‏‎‎‏‎"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎Choose what to allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access‎‏‎‎‏‎"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‎‎&lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; has been updated. Choose what to allow this app to access.‎‏‎‎‏‎"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎Cancel‎‏‎‎‏‎"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎Continue‎‏‎‎‏‎"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‎New permissions‎‏‎‎‏‎"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎Current permissions‎‏‎‎‏‎"</string>
+    <string name="message_staging" msgid="6151794817691100003">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎Staging app…‎‏‎‎‏‎"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‏‎Unknown‎‏‎‎‏‎"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‎For your security, your tablet is not allowed to install unknown apps from this source.‎‏‎‎‏‎"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎For your security, your TV is not allowed to install unknown apps from this source.‎‏‎‎‏‎"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‎For your security, your phone is not allowed to install unknown apps from this source.‎‏‎‎‏‎"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎Your phone and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your phone or loss of data that may result from its use.‎‏‎‎‏‎"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‎Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use.‎‏‎‎‏‎"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use.‎‏‎‎‏‎"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎Continue‎‏‎‎‏‎"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎Settings‎‏‎‎‏‎"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‎‎‎Installing/uninstalling wear apps‎‏‎‎‏‎"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-es-rUS-television/strings.xml b/packages/PackageInstaller/res/values-es-rUS-television/strings.xml
new file mode 100644
index 0000000..e664dc2
--- /dev/null
+++ b/packages/PackageInstaller/res/values-es-rUS-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Denegar el permiso y no volver a preguntar"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Puedes cambiar esta opción más tarde en Configuración &gt; Aplicaciones"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Mostrar apps del sistema"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Permisos de apps"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Permisos de apps"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Permisos de <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Permisos adicionales"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Permisos de <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-es-rUS-watch/strings.xml b/packages/PackageInstaller/res/values-es-rUS-watch/strings.xml
new file mode 100644
index 0000000..3880892
--- /dev/null
+++ b/packages/PackageInstaller/res/values-es-rUS-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Denegar y no preguntar más"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar apps del sistema"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Inalterable"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Sí"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancelar"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-es-rUS/strings.xml b/packages/PackageInstaller/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..178f551
--- /dev/null
+++ b/packages/PackageInstaller/res/values-es-rUS/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Programa de instalación del paquete"</string>
+    <string name="next" msgid="3057143178373252333">"Siguiente"</string>
+    <string name="install" msgid="5896438203900042068">"Instalar"</string>
+    <string name="done" msgid="3889387558374211719">"Finalizado"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancelar"</string>
+    <string name="installing" msgid="8613631001631998372">"Instalando…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Se instaló la aplicación."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"¿Deseas instalar la aplicación? Esta tendrá acceso a lo siguiente:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"¿Deseas instalar esta aplicación? No requiere accesos especiales."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"¿Deseas instalar una actualización para esta aplicación? Tus datos no se perderán. La aplicación actualizada tendrá acceso a lo siguiente:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"¿Deseas instalar una actualización para esta aplicación integrada? Tus datos no se perderán. La aplicación actualizada tendrá acceso a lo siguiente:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"¿Quieres instalar una actualización de esta aplicación existente? Los datos existentes no se perderán. No se requiere ningún acceso especial."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"¿Quieres instalar una actualización de esta aplicación integrada? Los datos existentes no se perderán. No se requiere ningún acceso especial."</string>
+    <string name="install_failed" msgid="6579998651498970899">"No se instaló la aplicación."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Se bloqueó el paquete para impedir la instalación."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"No se instaló la app ya que está en conflicto con un paquete existente."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"No se instaló la app porque no es compatible con tu tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Esta app no es compatible con la TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"No se instaló la app porque no es compatible con tu teléfono."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"No se instaló la app porque parece que el paquete no es válido."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"No se pudo instalar <xliff:g id="APP_NAME">%1$s</xliff:g> en tu tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"No se pudo instalar <xliff:g id="APP_NAME">%1$s</xliff:g> en la TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"No se pudo instalar <xliff:g id="APP_NAME">%1$s</xliff:g> en tu dispositivo."</string>
+    <string name="launch" msgid="4826921505917605463">"Abrir"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Tu administrador no permite la instalación de apps que se obtuvieron de fuentes desconocidas"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Este usuario no puede instalar apps desconocidas"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Este usuario no puede instalar apps"</string>
+    <string name="ok" msgid="3468756155452870475">"Aceptar"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Administrar aplicaciones"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Sin espacio"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"No se pudo instalar <xliff:g id="APP_NAME">%1$s</xliff:g>. Libera espacio y vuelve a intentarlo."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"No se encontró la aplicación."</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"La aplicación no se encontró en la lista de aplicaciones instaladas."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"No tiene permiso"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"El usuario actual no tiene permiso para llevar a cabo esta desinstalación."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Error"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"No se pudo desinstalar la app."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Desinstalar la aplicación"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Desinstalar la actualización"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> es parte de la siguiente aplicación:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"¿Deseas desinstalar esta aplicación?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"¿Quieres desinstalar esta aplicación para "<b>"todos"</b>" los usuarios? La aplicación y sus datos se eliminarán de "<b>"todos"</b>" los usuarios del dispositivo."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"¿Deseas desinstalar esta aplicación para el usuario <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"¿Deseas reemplazar esta app con la versión de fábrica? Se quitarán todos los datos."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"¿Deseas reemplazar esta app con la versión de fábrica? Se quitarán todos los datos. Esta acción afectará a todos los usuarios de este dispositivo, incluidos los que poseen perfiles de trabajo."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Desinstalaciones activas"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Desinstalaciones con errores"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Desinstalando…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"La desinstalación finalizó."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Se desinstaló <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Desinstalación incorrecta"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"No se pudo desinstalar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"No se puede desinstalar la app de administración activa del dispositivo"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"No se puede desinstalar la app de administración activa del dispositivo para <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"App necesaria en algunos usuarios o perfiles, y desinstalada en otros"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Esta app es necesaria en tu perfil y no la puedes desinstalar."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"El admin. del dispositivo necesita esta aplicación y no se puede desinstalar."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Administrar apps del dispositivo del administrador"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Administrar usuarios"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"No se pudo desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Se produjo un error durante el análisis del paquete."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nuevo"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Todo"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacidad"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Acceso al dispositivo"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Esta actualización no requiere permisos nuevos."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Rechazar"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Más información"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Denegar de todos modos"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"¿Quieres que la app de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; realice la siguiente acción: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pueda <xliff:g id="ACTION">%2$s</xliff:g> siempre?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Solo cuando se usa la app"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Siempre"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Denegar el permiso y no volver a preguntar"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> inhabilitados"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"todos inhabilitados"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ninguno inhabilitado"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Permitir"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplicaciones"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Permisos de apps"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"No volver a preguntar"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Sin permisos"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Permisos adicionales"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Abrir información de la app"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> más</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> más</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Esta aplicación se diseñó para una versión de Android anterior. Si deniegas el permiso, es posible que deje de funcionar de la forma prevista."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"realizar una acción desconocida"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Se otorgó el permiso a <xliff:g id="COUNT_0">%1$d</xliff:g> de <xliff:g id="COUNT_1">%2$d</xliff:g> aplicaciones."</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Mostrar sistema"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ocultar sistema"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Ninguna aplicación"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Configuración de la ubicación"</string>
+    <string name="location_warning" msgid="8778701356292735971">"La aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> provee servicios de ubicación a este dispositivo. El acceso a la ubicación puede modificarse desde la configuración de la ubicación."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Si no concedes este permiso, es posible que algunas funciones básicas del dispositivo dejen de funcionar correctamente."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Se aplica en función de la política"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Acceso en segundo plano inhabilitado por la política"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Acceso en segundo plano habilitado por la política"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Acceso en primer plano habilitado por la política"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlado por el administrador"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Siempre"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Solo cuando se usa la app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nunca"</string>
+    <string name="loading" msgid="7811651799620593731">"Cargando…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Todos los permisos"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Otras funciones de la aplicación"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Solicitud de permiso"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Se detectó una superposición de pantalla"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Para cambiar esta configuración de permisos, primero debes desactivar la superposición de pantalla en Configuración &gt; Aplicaciones"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir configuración"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear no admite las acciones de instalación y desinstalación"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Selecciona los permisos de acceso para &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Se actualizó &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;. Selecciona los permisos de acceso para esta app."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancelar"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continuar"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Permisos nuevos"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Permisos actuales"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Preparando app…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Desconocido"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Por tu seguridad, tu tablet no tiene permitido instalar apps desconocidas de esta fuente."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Por tu seguridad, tu TV no tiene permitido instalar apps desconocidas de esta fuente."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Por tu seguridad, tu teléfono no tiene permitido instalar apps desconocidas de esta fuente."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Tu teléfono y tus datos personales son más vulnerables a los ataques de apps desconocidas. Si instalas esta app, serás responsable de los daños que sufra tu teléfono y la pérdida de datos que pueda ocasionar su uso."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tu tablet y tus datos personales son más vulnerables a los ataques de apps desconocidas. Si instalas esta app, serás responsable de los daños que sufra tu tablet y la pérdida de datos que pueda ocasionar su uso."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Tu TV y tus datos personales son más vulnerables a los ataques de apps desconocidas. Si instalas esta app, serás responsable de los daños que sufra tu TV y la pérdida de datos que pueda ocasionar su uso."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continuar"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Configuración"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instalando/desinstalando apps para Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-es-television/strings.xml b/packages/PackageInstaller/res/values-es-television/strings.xml
new file mode 100644
index 0000000..6a12063
--- /dev/null
+++ b/packages/PackageInstaller/res/values-es-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Denegar y no volver a preguntar"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Puedes cambiar esta opción más tarde en Ajustes &gt; Aplicaciones."</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Mostrar aplicaciones del sistema"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Permisos de aplicaciones"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Permisos de aplicaciones"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Permisos: <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Permisos adicionales"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Permisos: <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-es-watch/strings.xml b/packages/PackageInstaller/res/values-es-watch/strings.xml
new file mode 100644
index 0000000..b3c4ff1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-es-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Denegar y no preguntar más"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar aplicaciones del sistema"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"No se puede cambiar"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Sí"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancelar"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-es/strings.xml b/packages/PackageInstaller/res/values-es/strings.xml
new file mode 100644
index 0000000..bffaa0f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-es/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Instalador de paquetes"</string>
+    <string name="next" msgid="3057143178373252333">"Siguiente"</string>
+    <string name="install" msgid="5896438203900042068">"Instalar"</string>
+    <string name="done" msgid="3889387558374211719">"Listo"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancelar"</string>
+    <string name="installing" msgid="8613631001631998372">"Instalando…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplicación instalada"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"¿Quieres instalar esta aplicación? Tendrá los siguientes permisos:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"¿Quieres instalar esta aplicación? No requiere accesos especiales."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"¿Quieres instalar una actualización de la aplicación? Tus datos no se perderán. La aplicación actualizada podrá acceder a:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"¿Quieres instalar una actualización de esta aplicación integrada? Tus datos no se perderán. La aplicación actualizada podrá acceder a:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"¿Quieres instalar una actualización de esta aplicación? Tus datos no se perderán. No requiere ningún acceso especial."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"¿Quieres instalar una actualización de esta aplicación integrada? Tus datos no se perderán. No requiere ningún acceso especial."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplicación no instalada"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Se ha bloqueado la instalación del paquete."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"La aplicación no se ha instalado debido a un conflicto con un paquete actual."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"La aplicación no se ha instalado porque no es compatible con tu tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Esta aplicación no es compatible con tu TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"La aplicación no se ha instalado porque no es compatible con tu teléfono."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"La aplicación no se ha instalado porque parece que el paquete no es válido."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"No se ha podido instalar <xliff:g id="APP_NAME">%1$s</xliff:g> en el tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> no se ha podido instalar en tu TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"No se ha podido instalar <xliff:g id="APP_NAME">%1$s</xliff:g> en el teléfono."</string>
+    <string name="launch" msgid="4826921505917605463">"Abrir"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"El administrador no permite instalar aplicaciones de fuentes desconocidas"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Este usuario no puede instalar aplicaciones desconocidas"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Este usuario no tiene permiso para instalar aplicaciones"</string>
+    <string name="ok" msgid="3468756155452870475">"Aceptar"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Administrar aplicaciones"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Sin espacio"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"No se ha podido instalar la aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>. Libera espacio y vuelve a intentarlo."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplicación no encontrada"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"No se ha encontrado la aplicación en la lista de aplicaciones instaladas."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"No permitido"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"El usuario actual no puede iniciar el proceso de desinstalación."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Error"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"No se ha podido desinstalar la aplicación."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Desinstalar aplicación"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Desinstalar actualización"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> forma parte de esta aplicación:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"¿Quieres desinstalar esta aplicación?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"¿Quieres desinstalar esta aplicación para "<b>"todos"</b>" los usuarios? La aplicación y sus datos se eliminarán de "<b>"todos"</b>" los usuarios del dispositivo."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"¿Quieres desinstalar esta aplicación para el usuario <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"¿Quieres sustituir esta aplicación con la versión de fábrica? Ten en cuenta que se eliminarán todos los datos."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"¿Quieres sustituir esta aplicación con la versión de fábrica? Ten en cuenta que se eliminarán todos los datos. Esto afecta a todos los usuarios del dispositivo, incluidos los que tienen perfiles de trabajo."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Desinstalaciones en curso"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Desinstalaciones fallidas"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Desinstalando..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Desinstalación completada"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Se ha desinstalado <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Desinstalación correcta"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"No se ha podido desinstalar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"No se puede desinstalar la aplicación de administración de dispositivos activa"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"No se ha podido desinstalar la aplicación de administración de dispositivos activa de <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Aplicación necesaria para algunos usuarios o perfiles y desinstalada en otros casos"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Esta aplicación es necesaria para tu perfil y no se puede desinstalar."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Esta aplicación es necesaria para el administrador de tu dispositivo y no se puede desinstalar."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Gestionar aplicaciones de admón. de dispositivos"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Administrar usuarios"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"No se ha podido desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Se ha producido un error al analizar el paquete."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nuevo"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Todos"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacidad"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Acceso al dispositivo"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Esta actualización no requiere permisos nuevos."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Denegar"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Más información"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Denegar de todos modos"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"¿Permitir a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"¿Quieres permitir siempre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Solo mientras se usa la aplicación"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Siempre"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Denegar y no volver a preguntar"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"Inhabilitados: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"todos inhabilitados"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ninguno inhabilitado"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Permitir"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplicaciones"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Permisos de aplicaciones"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"No volver a preguntar"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Sin permisos"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Permisos adicionales"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Abrir la información de la aplicación"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> más</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> más</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Esta aplicación está diseñada para una versión anterior de Android. Si se le deniega el permiso, puede dejar de funcionar de la forma prevista."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"realizar una acción desconocida"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> de <xliff:g id="COUNT_1">%2$d</xliff:g> aplicaciones permitidas"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Mostrar aplicaciones del sistema"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ocultar aplicaciones del sistema"</string>
+    <string name="no_apps" msgid="1965493419005012569">"No hay aplicaciones"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Ajustes de ubicación"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> es un proveedor de servicios de ubicación de este dispositivo. El acceso a la ubicación se puede modificar en los ajustes de ubicación."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Si rechazas este permiso, es posible que funciones básicas de tu dispositivo dejen de funcionar correctamente."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Aplicado por política"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Acceso en segundo plano inhabilitado por política"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Acceso en segundo plano habilitado por política"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Acceso en primer plano habilitado por política"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlado por el administrador"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Siempre"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Solo mientras se usa la app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nunca"</string>
+    <string name="loading" msgid="7811651799620593731">"Cargando..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Todos los permisos"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Otras funciones de la aplicación"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Solicitud de permiso"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Superposición de pantalla detectada"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Para cambiar la configuración de este permiso, desactiva la superposición de pantalla en Ajustes &gt; Aplicaciones"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir ajustes"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Las acciones de instalar y desinstalar no pueden realizarse en Wear"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Elige los permisos de acceso que quieres conceder a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; se ha actualizado. Elige los permisos de acceso que quieres conceder a esta aplicación."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancelar"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continuar"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Permisos nuevos"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Permisos actuales"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Preparando aplicación…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Desconocido"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Por motivos de seguridad, tu tablet no puede instalar aplicaciones desconocidas de esta fuente."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Por motivos de seguridad, tu TV no puede instalar aplicaciones desconocidas de esta fuente."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Por motivos de seguridad, tu teléfono no puede instalar aplicaciones desconocidas de esta fuente."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Tu teléfono y tus datos personales son más vulnerables a los ataques de aplicaciones desconocidas. Al instalar esta aplicación, aceptas ser responsable de cualquier daño que sufra tu teléfono o la pérdida de datos que se pueda derivar de su uso."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tu tablet y tus datos personales son más vulnerables a los ataques de aplicaciones desconocidas. Al instalar esta aplicación, aceptas ser responsable de cualquier daño que sufra tu tablet o la pérdida de datos que se pueda derivar de su uso."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Tu TV y tus datos personales son más vulnerables a los ataques de aplicaciones desconocidas. Al instalar esta aplicación, aceptas ser responsable de cualquier daño que sufra tu TV o la pérdida de datos que se pueda derivar de su uso."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continuar"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Ajustes"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instalando/desinstalando apps para Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-et-television/strings.xml b/packages/PackageInstaller/res/values-et-television/strings.xml
new file mode 100644
index 0000000..0abb2de
--- /dev/null
+++ b/packages/PackageInstaller/res/values-et-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Keela ja ära enam küsi"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Saate seda hiljem muuta jaotises Seaded &gt; Rakendused"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Kuva süsteemirakendused"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Rakenduste load"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Rakenduste load"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> – load"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Lisaload"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> – load"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-et-watch/strings.xml b/packages/PackageInstaller/res/values-et-watch/strings.xml
new file mode 100644
index 0000000..328e215
--- /dev/null
+++ b/packages/PackageInstaller/res/values-et-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Keela, ära enam küsi"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Kuva süsteemirakendused"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ei saa muuta"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Jah"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Tühista"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-et/strings.xml b/packages/PackageInstaller/res/values-et/strings.xml
new file mode 100644
index 0000000..1754411
--- /dev/null
+++ b/packages/PackageInstaller/res/values-et/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Paketiinstaller"</string>
+    <string name="next" msgid="3057143178373252333">"Järgmine"</string>
+    <string name="install" msgid="5896438203900042068">"Installi"</string>
+    <string name="done" msgid="3889387558374211719">"Valmis"</string>
+    <string name="cancel" msgid="8360346460165114585">"Tühista"</string>
+    <string name="installing" msgid="8613631001631998372">"Installimine ..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Paketi <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> installimine …"</string>
+    <string name="install_done" msgid="3682715442154357097">"Rakendus on installitud."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Kas soovite rakenduse installida? See pääseb järgmiste üksuste juurde:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Kas soovite rakenduse installida? See ei nõua spetsiaalseid juurdepääsuõigusi."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Kas soovite olemasoleva rakenduse värskenduse installida? Teie olemasolevad andmed jäävad alles. Värskendatud rakendus pääseb järgmiste funktsioonide juurde:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Kas soovite sisseehitatud rakenduse värskenduse installida? Teie olemasolevad andmed jäävad alles. Värskendatud rakendus pääseb järgmiste funktsioonide juurde:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Kas soovite installida olemasoleva rakenduse värskenduse? Olemasolevad andmed ei lähe kaduma. See ei nõua erijuurdepääsu."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Kas soovite installida sisseehitatud rakenduse värskenduse? Olemasolevad andmed ei lähe kaduma. See ei nõua erijuurdepääsu."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Rakendus pole installitud."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Paketi installimine blokeeriti."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Rakendust ei installitud, kuna pakett on olemasoleva paketiga vastuolus."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Rakendust ei installitud, kuna rakendus ei ühildu teie tahvelarvutiga."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Rakendus ei ühildu teie teleriga."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Rakendust ei installitud, kuna rakendus ei ühildu teie telefoniga."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Rakendust ei installitud, kuna pakett näib olevat sobimatu."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Rakendust <xliff:g id="APP_NAME">%1$s</xliff:g> ei saa teie tahvelarvutisse installida."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Rakendust <xliff:g id="APP_NAME">%1$s</xliff:g> ei saa teie telerisse installida."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Rakendust <xliff:g id="APP_NAME">%1$s</xliff:g> ei saa teie telefoni installida."</string>
+    <string name="launch" msgid="4826921505917605463">"Ava"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Administraator ei luba installida tundmatutest allikatest pärinevaid rakendusi"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"See kasutaja ei saa installida tundmatuid rakendusi"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Kasutajal ei ole lubatud rakendusi installida"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Rakenduste haldamine"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Pole ruumi"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Rakendust <xliff:g id="APP_NAME">%1$s</xliff:g> ei saa installida. Vabastage mälu ja proovige uuesti."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Rakendust ei leitud"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Rakendust ei leitud installitud rakenduste loendist."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Ei ole lubatud"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Praegusel kasutajal ei ole lubatud seda desinstallimist teha."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Viga"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Rakendust ei saanud desinstallida."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Rakenduse desinstallimine"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Värskenduse desinstallimine"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> on osa järgmisest rakendusest:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Kas soovite selle rakenduse desinstallida?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Kas soovite desinstallida selle rakenduse "<b>"kõikidelt"</b>" kasutajatelt? Rakendus ja selle andmed eemaldatakse "<b>"kõikidelt"</b>" seadme kasutajatelt."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Kas soovite kasutaja <xliff:g id="USERNAME">%1$s</xliff:g> puhul rakenduse desinstallida?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Kas asendada see rakendus tehaseversiooniga? Kõik andmed eemaldatakse."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Kas asendada see rakendus tehaseversiooniga? Kõik andmed eemaldatakse. See mõjutab kõiki seadme kasutajaid, sh neid, kellel on tööprofiilid."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Käimasolevad desinstallimised"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Ebaõnnestunud desinstallimised"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Desinstallimine ..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstallimine …"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Desinstallimine on lõpetatud."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Üksus <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> on desinstallitud"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Desinstallimine ebaõnnestus."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstallimine ebaõnnestus."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Aktiivset seadme administraatori rakendust ei saa desinstallida"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Kasutaja <xliff:g id="USERNAME">%1$s</xliff:g> puhul ei saa aktiivset seadme administraatori rakendust desinstallida"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Rakendus on mõne kasutaja ja profiili puhul vajalik, teiste puhul see desinstalliti"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"See rakendus on vajalik teie profiili jaoks ja seda ei saa desinstallida."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Seadme administraator vajab seda rakendust ja seda ei saa desinstallida."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Halda seadme administraatori rakendusi"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Halda kasutajaid"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Rakendust <xliff:g id="APP_NAME">%1$s</xliff:g> ei saanud desinstallida."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Probleem paketi sõelumisel."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Uus"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Kõik"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privaatsus"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Seadme juurdepääs"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"See värskendus ei nõua uusi lube."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Keela"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Lisateave"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Keela ikkagi"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>-st"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Kas lubada rakenduse puhul &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; alati toiming <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Ainult rakenduse kasutamise ajal"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Alati"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Keela ja ära enam küsi"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> on keelatud"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"kõik on keelatud"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"mitte ükski pole keelatud"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Luba"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Rakendused"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Rakenduste load"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ära enam küsi"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Lube ei ole"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Täiendavad load"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Ava rakenduse teave"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other">Veel <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Veel <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Rakendus on mõeldud Androidi vanemale versioonile. Kui keeldute loa andmisest, ei pruugi see ootuspäraselt töötada."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"tundmatu toiming"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> rakendust <xliff:g id="COUNT_1">%2$d</xliff:g>-st on lubatud"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Kuva süsteem"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Peida süsteem"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Rakendusi pole"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Asukohaseaded"</string>
+    <string name="location_warning" msgid="8778701356292735971">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> on selle seadme asukohateenuste pakkuja. Asukoha juurdepääsu saab muuta asukohaseadetes."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Kui keelate loa, ei pruugi seadme põhifunktsioonid enam ootuspäraselt töötada."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Eeskirjadega jõustatud"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Reegli alusel on taustale juurdepääs keelatud"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Reegli alusel on taustale juurdepääs lubatud"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Reegli alusel on esiplaanile juurdepääs lubatud"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Juhib administraator"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Alati"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Ainult rakenduse kasutamisel"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Mitte kunagi"</string>
+    <string name="loading" msgid="7811651799620593731">"Laadimine ..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Kõik load"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Rakenduse muud funktsioonid"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Loa taotlus"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Tuvastati ekraani ülekate"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Selle loa seade muutmiseks peate esmalt välja lülitama ekraani ülekatte menüüs Seaded &gt; Rakendused"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Ava seaded"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear ei toeta installimist/desinstallimist."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Valige, millele lubate rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurde pääseda"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Rakendust &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; värskendati. Valige, millele lubate sellel rakendusel juurde pääseda."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Tühista"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Jätka"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Uued load"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Praegused load"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Rakenduse ettevalmistamine …"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Tundmatu"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Teie turvalisuse huvides ei ole tahvelarvutil lubatud installida sellest allikast tundmatuid rakendusi."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Teie turvalisuse huvides ei ole TV-l lubatud installida sellest allikast tundmatuid rakendusi."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Teie turvalisuse huvides ei ole telefonil lubatud installida sellest allikast tundmatuid rakendusi."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Teie telefon ja isiklikud andmed on tundmatute rakenduste rünnakute suhtes haavatavamad. Selle rakenduse installimisel nõustute, et vastutate telefoni kahjude ja andmekao eest, mis võivad tuleneda selliste rakenduste kasutamisest."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Teie tahvelarvuti ja isiklikud andmed on tundmatute rakenduste rünnakute suhtes haavatavamad. Selle rakenduse installimisel nõustute, et vastutate tahvelarvuti kahjude ja andmekao eest, mis võivad tuleneda selliste rakenduste kasutamisest."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Teie teler ja isiklikud andmed on tundmatute rakenduste rünnakute suhtes haavatavamad. Selle rakenduse installimisel nõustute, et vastutate teleri kahjude ja andmekao eest, mis võivad tuleneda selliste rakenduste kasutamisest."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Jätka"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Seaded"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Weari rak. installimine/desinstallimine"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-eu-television/strings.xml b/packages/PackageInstaller/res/values-eu-television/strings.xml
new file mode 100644
index 0000000..78fffae
--- /dev/null
+++ b/packages/PackageInstaller/res/values-eu-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Ukatu eta ez galdetu berriro"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Hori geroago alda dezakezu Ezarpenak &gt; Aplikazioak atalean"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Erakutsi sistemaren aplikazioak"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Aplikazio-baimenak"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Aplikazio-baimenak"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> erabiltzeko baimenak"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Baimen gehigarriak"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> erabiltzeko baimenak"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-eu-watch/strings.xml b/packages/PackageInstaller/res/values-eu-watch/strings.xml
new file mode 100644
index 0000000..0f08cad
--- /dev/null
+++ b/packages/PackageInstaller/res/values-eu-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Ukatu; ez galdetu berriro"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Erakutsi sistemaren aplikazioak"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ezin da aldatu"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Bai"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Utzi"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-eu/strings.xml b/packages/PackageInstaller/res/values-eu/strings.xml
new file mode 100644
index 0000000..0cb7e4c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-eu/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Pakete-instalatzailea"</string>
+    <string name="next" msgid="3057143178373252333">"Hurrengoa"</string>
+    <string name="install" msgid="5896438203900042068">"Instalatu"</string>
+    <string name="done" msgid="3889387558374211719">"Eginda"</string>
+    <string name="cancel" msgid="8360346460165114585">"Utzi"</string>
+    <string name="installing" msgid="8613631001631998372">"Instalatzen…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> instalatzen…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikazioa instalatu da."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Aplikazioa instalatu nahi duzu? Elementu hauetarako sarbidea izango du:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Aplikazioa instalatu nahi duzu? Ez du sarbide berezirik behar."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Aplikazioaren eguneratzea instalatu nahi duzu? Lehendik dauden datuak ez dira galduko. Eguneratutako aplikazioak elementu hauetarako sarbidea izango du:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Aplikazio integratu honen eguneratzea instalatu nahi duzu? Lehendik dauden datuak ez dira galduko. Eguneratutako aplikazioak elementu hauetarako sarbidea izango du:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Aplikazioaren eguneratzea instalatu nahi duzu? Lehendik dauden datuak ez dira galduko. Ez du sarbide berezirik behar."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Aplikazio integratu honen eguneratzea instalatu nahi duzu? Lehendik dauden datuak ez dira galduko. Ez du sarbide berezirik behar."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Ez da aplikazioa instalatu."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Blokeatu egin da paketea instalatzeko aukera."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Ez da instalatu aplikazioa, gatazka bat sortu delako lehendik dagoen pakete batekin."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Ez da instalatu aplikazioa, ez delako tabletarekin bateragarria."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Aplikazioa ez da telebistarekin bateragarria."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Ez da instalatu aplikazioa, ez delako telefonoarekin bateragarria."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Ez da instalatu aplikazioa, paketeak ez duelako balio."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Ezin izan da <xliff:g id="APP_NAME">%1$s</xliff:g> tabletan instalatu."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Ezin izan da instalatu <xliff:g id="APP_NAME">%1$s</xliff:g> telebistan."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Ezin izan da <xliff:g id="APP_NAME">%1$s</xliff:g> telefonoan instalatu."</string>
+    <string name="launch" msgid="4826921505917605463">"Ireki"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Administratzaileak ez du onartzen iturburu ezezagunetako aplikazioak instalatzea"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Erabiltzaile honek ezin ditu instalatu aplikazio ezezagunak"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Erabiltzaile honek ez du baimenik aplikazioak instalatzeko"</string>
+    <string name="ok" msgid="3468756155452870475">"Ados"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Kudeatu aplikazioak"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Ez dago behar adina toki"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Ezin izan da <xliff:g id="APP_NAME">%1$s</xliff:g> instalatu. Egin toki pixka bat eta saiatu berriro."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Ez da aplikazioa aurkitu"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplikazioa ez da aurkitu instalatutako aplikazioen zerrendan."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Ez dauka baimenik"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Erabiltzaile honek ez dauka desinstalatzeko baimenik."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Errorea"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Ezin izan da desinstalatu aplikazioa."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Desinstalatu aplikazioa"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Desinstalatu eguneratzea"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> aplikazio honen zati da:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Aplikazioa desinstalatu nahi duzu?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Aplikazioa erabiltzaile "<b>"guztientzat"</b>" desinstalatu nahi duzu? Aplikazioa eta bere datu guztiak gailuko erabiltzaile "<b>"guztiei"</b>" ezabatuko zaizkie."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"<xliff:g id="USERNAME">%1$s</xliff:g> erabiltzailearen aplikazioa desinstalatu nahi duzu?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Aplikazio hau jatorrizko bertsioarekin ordeztu nahi duzu? Datu guztiak ezabatuko dira."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Aplikazio hau jatorrizko bertsioarekin ordeztu nahi duzu? Datu guztiak ezabatuko dira. Gailuaren erabiltzaile guztiengan izango du eragina, laneko profilak dituztenengan barne."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Abian diren desinstalatze-eragiketak"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Huts egin duten desinstalatze-eragiketak"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Desinstalatzen…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstalatzen…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Desinstalatu da."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Desinstalatu da <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Ezin izan da desinstalatu."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Ezin izan da desinstalatu <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Ezin da desinstalatu gailua administratzeko aplikazio aktiboa"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Ezin da desinstalatu <xliff:g id="USERNAME">%1$s</xliff:g> erabiltzailearen gailua administratzeko aplikazio aktiboa"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Erabiltzaile edo profil batzuek behar dute aplikazio hau, baina desinstalatu egin da beste guztientzat."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Zure profilak behar du aplikazio hau eta ezin da desinstalatu."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Gailuaren administratzaileak aplikazio hori behar du eta ezin da desinstalatu."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Kudeatu gailua administratzeko aplikazioak"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Kudeatu erabiltzaileak"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Ezin izan da <xliff:g id="APP_NAME">%1$s</xliff:g> desinstalatu."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Arazo bat izan da paketea analizatzean."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Berriak"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Guztiak"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Pribatutasuna"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Gailurako sarbidea"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Eguneratze honek ez du baimen berririk behar."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Ukatu"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Informazio gehiago"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Ukatu hala ere"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari \"<xliff:g id="ACTION">%2$s</xliff:g>\" izeneko baimena eman nahi diozu?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Beti eman nahi diozu \"<xliff:g id="ACTION">%2$s</xliff:g>\" baimena &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Aplikazioa erabiltzean soilik"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Beti"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Baztertu eta ez galdetu berriro"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> desgaituta"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"guztiak desgaituta"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"guztiak gaituta"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Baimendu"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikazioak"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Aplikazio-baimenak"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ez galdetu berriro"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Ez dago baimenik"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Baimen gehigarriak"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Ireki aplikazioaren informazioa"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> gehiago</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> gehiago</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Aplikazio hau Android-en bertsio zaharrago baterako diseinatuta dago. Baimena ukatzen baduzu, agian aurrerantzean ez du behar bezain ondo funtzionatuko."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"Gauzatu ekintza ezezagunak"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g> aplikaziok dute baimena"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Erakutsi sistema"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ezkutatu sistema"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Ez dago aplikaziorik"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Kokapen-ezarpenak"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> gailu honen kokapen-zerbitzuen hornitzailea da. Kokapenerako sarbidea kokapen-ezarpenetatik alda daiteke."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Baimena ematen ez baduzu, baliteke gailuaren oinarrizko eginbide batzuek behar bezala ez funtzionatzea."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Gidalerroen bidez aplikatzen da"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Gidalerro batek eskatuta, atzeko planoa atzitzeko aukera desgaitu da"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Gidalerro batek eskatuta, atzeko planoa atzitzeko aukera gaitu da"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Gidalerro batek eskatuta, aurreko planoa atzitzeko aukera gaitu da"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Administratzaileak kontrolatzen du"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Beti"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Aplikazioa erabiltzean soilik"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Inoiz ez"</string>
+    <string name="loading" msgid="7811651799620593731">"Kargatzen…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Baimen guztiak"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Aplikazioaren beste gaitasun batzuk"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Baimen-eskaera"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Pantailaren gainjartzea detektatu da"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Baimen-ezarpen hau aldatzeko, pantailaren gainjartzea desaktibatu behar duzu Ezarpenak &gt; Aplikazioak atalean"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Ireki ezarpenak"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Instalatzeko eta desinstalatzeko ekintzak ezin dira gauzatu Wear gailuetan."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Aukeratu zer atzi dezakeen &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioak"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Eguneratu egin da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;. Aukeratu aplikazioak zer atzi dezakeen."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Utzi"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Jarraitu"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Baimen berriak"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Uneko baimenak"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Aplikazioa prestatzen…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Ezezaguna"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Segurtasuna bermatzeko, tableta honetan ezin dira instalatu iturburu honetako aplikazio ezezagunak."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Segurtasuna bermatzeko, telebista honetan ezin dira instalatu iturburu honetako aplikazio ezezagunak."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Segurtasuna bermatzeko, telefono honetan ezin dira instalatu iturburu honetako aplikazio ezezagunak."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefonoak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartzen duzu hura erabiltzeagatik telefonoak jasan ditzakeen kalteen edo datu-galeren erantzulea zeu zarela."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tabletak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartzen duzu hura erabiltzeagatik tabletak jasan ditzakeen kalteen edo datu-galeren erantzulea zeu zarela."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Telebistak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Iturburu honetako aplikazioak instalatzen badituzu, onartzen duzu haiek erabiltzeagatik telebistak jasan ditzakeen kalteen edo datu-galeren erantzulea zeu zarela."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Egin aurrera"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Ezarpenak"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear aplikazioak instalatzea/desinstalatzea"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fa-television/strings.xml b/packages/PackageInstaller/res/values-fa-television/strings.xml
new file mode 100644
index 0000000..95f2a54
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fa-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"اجازه ندارد و دیگر سؤال نشود"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"‏می‌توانید بعداً آن را در تنظیمات &gt; برنامه‌ها تغییر دهید"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"نمایش‌ برنامه‌های سیستم"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"مجوزهای برنامه"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"مجوزهای برنامه"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"مجوزهای <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"مجوزهای بیشتر"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"مجوزهای <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fa-watch/strings.xml b/packages/PackageInstaller/res/values-fa-watch/strings.xml
new file mode 100644
index 0000000..8d14954
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fa-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"رد شود، دیگر سؤال نشود"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"نمایش‌ برنامه‌های سیستم"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"نمی‌تواند تغییر کند"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"بله"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"لغو"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fa/strings.xml b/packages/PackageInstaller/res/values-fa/strings.xml
new file mode 100644
index 0000000..22f1a25
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fa/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"نصب‌کننده بسته"</string>
+    <string name="next" msgid="3057143178373252333">"بعدی"</string>
+    <string name="install" msgid="5896438203900042068">"نصب"</string>
+    <string name="done" msgid="3889387558374211719">"تمام"</string>
+    <string name="cancel" msgid="8360346460165114585">"لغو"</string>
+    <string name="installing" msgid="8613631001631998372">"در حال نصب…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"درحال نصب <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"برنامه نصب شد."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"آیا می‌خواهید این برنامه را نصب کنید؟ این برنامه به این موارد دسترسی خواهد یافت:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"آیا می‌خواهید این برنامه را نصب کنید؟ این برنامه به دسترسی خاصی نیاز ندارد."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"آیا میٰ‌خواهید بهٰ‌روزرسانی این برنامه کنونی را نصب کنید؟ داده کنونی شما از بین نمی‌رود. برنامه به‌روزرسانی شده دسترسی خواهد داشت به:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"آیا می‌خواهید به‌روزرسانی این برنامه جاسازی شده را نصب کنید؟ داده‌های کنونی شما از بین نمی‌رود. برنامه به‌روزرسانی شده دسترسی خواهد داشت به:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"آیا می‌خواهید یک به‌روزرسانی برای این برنامه کاربردی موجود نصب کنید؟ داده‌های موجود شما از دست نخواهد رفت. به دسترسی ویژه‌ای نیاز ندارد."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"آیا می‌خواهید یک به‌روزرسانی برای این برنامه کاربردی داخلی نصب کنید؟ داده‌های موجود شما از دست نخواهد رفت. به دسترسی ویژه‌ای نیاز ندارد."</string>
+    <string name="install_failed" msgid="6579998651498970899">"برنامه نصب نشد."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"از نصب شدن بسته جلوگیری شد."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"برنامه نصب نشد چون بسته با بسته موجود تداخل دارد."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"برنامه نصب نشد چون با رایانه لوحی‌تان سازگار نیست."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"این برنامه با تلویزیون شما سازگار نیست."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"برنامه نصب نشد چون با تلفنتان سازگار نیست."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"برنامه نصب نشد چون به نظر می‌رسد بسته معتبر نیست."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> در رایانهٔ لوحی شما نصب نشد."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> را نمی‌توان روی تلویزیون شما نصب کرد."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> در تلفن شما نصب نشد."</string>
+    <string name="launch" msgid="4826921505917605463">"باز کردن"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"سرپرست سیستم شما اجازه نمی‌دهد برنامه‌های دریافت‌شده از منابع ناشناس را نصب کنید"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"این کاربر نمی‌تواند برنامه‌های ناشناس نصب کند"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"این کاربر مجاز به نصب برنامه‌ نیست"</string>
+    <string name="ok" msgid="3468756155452870475">"تأیید"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"مدیریت برنامه‌ها"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"فضا کافی نیست"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> نصب نمی‌شود. مقداری از فضا را آزاد کرده و دوباره امتحان کنید."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"برنامه یافت نشد"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"برنامه در فهرست برنامه‌های نصب شده یافت نشد."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"مجاز نیست"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"کاربر کنونی مجاز به انجام این حذف نصب نیست."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"خطا"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"برنامه را نمی‌توان حذف نصب کرد."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"حذف نصب برنامه"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"حذف نصب به‌روزرسانی"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> قسمتی از برنامه زیر است:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"می‌خواهید این برنامه را حذف نصب کنید؟"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"آیا می‌خواهید این برنامه را برای "<b>"همه"</b>" کاربران حذف کنید؟ این برنامه کاربردی و داده‌های آن برای "<b>"همه"</b>" کاربران این دستگاه حذف خواهد شد."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"آیا می‌خواهید این برنامه را برای این کاربر <xliff:g id="USERNAME">%1$s</xliff:g> حذف نصب کنید؟"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"این برنامه با نسخه کارخانه جایگزین شود؟ همه داده‌ها پاک می‌شوند."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"این برنامه با نسخه کارخانه جایگزین شود؟ همه داده‌ها پاک می‌شوند. این کار همه کاربران این دستگاه (از جمله کاربرانی که نمایه کاری دارند) را تحت تأثیر قرار خواهد داد."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"حذف‌نصب‌های درحال انجام"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"حذف‌نصب‌های ناموفق"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"در حال حذف نصب..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"درحال حذف نصب <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"حذف نصب پایان یافت."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> را حذف نصب کرد"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"حذف نصب انجام نشد."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> باموفقیت حذف نصب شد."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"نمی‌توان برنامه فعال سرپرست دستگاه را حذف نصب کرد"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"نمی‌توان برنامه فعال سرپرست دستگاه را برای <xliff:g id="USERNAME">%1$s</xliff:g> حذف نصب کرد"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"این برنامه برای برخی کاربران یا نمایه‌ها ضروری است و برای بقیه حذف نصب شد"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"این برنامه برای نمایه شما لازم است و نمی‌توان آن را حذف نصب کرد."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"سرپرست دستگاه شما این برنامه را لازم کرده است و نمی‌تواند حذف نصب شود."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"مدیریت برنامه‌های سرپرست دستگاه"</string>
+    <string name="manage_users" msgid="3125018886835668847">"مدیریت کاربران"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> حذف نصب نشد."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"مشکلی در تجزیه این بسته وجود داشت."</string>
+    <string name="newPerms" msgid="6039428254474104210">"جدید"</string>
+    <string name="allPerms" msgid="1024385515840703981">"همه موارد"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"حریم خصوصی"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"دسترسی به دستگاه"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"این به‌روزرسانی به مجوز جدیدی نیاز ندارد."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"اجازه ندارد"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"اطلاعات بیشتر"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"در هر صورت نادیده گرفته شود"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> از <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"‏به&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه <xliff:g id="ACTION">%2$s</xliff:g> را می‌دهید؟"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"‏همیشه به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; برای <xliff:g id="ACTION">%2$s</xliff:g> اجازه داده شود؟"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"فقط هنگام استفاده از برنامه"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"همیشه"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"رد شود و دیگر سؤال نشود"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> مجوز غیرفعال هستند"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"همه مجوزها غیرفعال هستند"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"هیچ‌ موردی غیرفعال نیست"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"مجاز است"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"برنامه‌ها"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"مجوزهای برنامه"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"دوباره سؤال نشود"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"مجوزی موجود نیست"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"مجوزهای بیشتر"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"باز کردن اطلاعات برنامه"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"‏این برنامه برای یک نسخه قدیمی‌تر از Android طراحی شده بود. نپذیرفتن اجازه ممکن است باعث شود که برنامه دیگر به صورتی که موردنظر است کار نکند."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"انجام یک اقدام ناشناس"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> برنامه از <xliff:g id="COUNT_1">%2$d</xliff:g> برنامه مجاز است"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"نمایش سیستم"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"پنهان کردن سیستم"</string>
+    <string name="no_apps" msgid="1965493419005012569">"برنامه‌ای موجود نیست"</string>
+    <string name="location_settings" msgid="1774875730854491297">"تنظیمات مکان"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> یکی از ارائه‌دهندگان سرویس‌های مکان برای این دستگاه است. با رفتن به تنظیمات مکان می‌توانید دسترسی به موقعیت مکانی را تغییر دهید."</string>
+    <string name="system_warning" msgid="7103819124542305179">"اگر این اجازه را رد کنید، ممکن است قابلیت‌های اصلی دستگاهتان دیگر عملکرد موردانتظار را نداشته باشند."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"اجرا توسط خط‌مشی"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"دسترسی به پس‌زمینه به‌موجب خط‌مشی غیرفعال شد"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"دسترسی به پس‌زمینه به‌موجب خط‌مشی فعال شد"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"دسترسی به پیش‌زمینه به‌موجب خط‌مشی فعال شد"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"توسط سرپرست سیستم کنترل می‌شود"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"همیشه"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"فقط هنگام استفاده از برنامه"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"هرگز"</string>
+    <string name="loading" msgid="7811651799620593731">"درحال بارگیری…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"همه مجوزها"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"سایر قابلیت‌های برنامه"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"درخواست مجوز"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"هم‌پوشانی صفحه شناسایی شد"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"‏برای تغییر این تنظیم مجوز، ابتدا باید هم‌پوشانی صفحه را از «تنظیمات &gt; برنامه‌ها» خاموش کنید"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"باز کردن تنظیمات"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"‏کنش‌های نصب/حذف نصب در Wear پشتیبانی نمی‌شود."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"‏انتخاب کنید &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه دارد به چه چیزی دسترسی پیدا کند"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; به‌روزرسانی شده است. انتخاب کنید این برنامه اجازه دارد به چه چیزی دسترسی پیدا کند."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"لغو"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"ادامه"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"مجوزهای جدید"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"مجوزهای کنونی"</string>
+    <string name="message_staging" msgid="6151794817691100003">"مرحله‌بندی برنامه…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"نامشخص"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"برای امنیت شما، رایانه لوحی‌تان اجازه نمی‌دهد از این منبع برنامه‌های ناشناس نصب شوند."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"برای امنیت شما، تلویزیونتان اجازه نمی‌دهد از این منبع برنامه‌های ناشناس نصب شوند."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"برای امنیت شما، تلفنتان اجازه نمی‌دهد از این منبع برنامه‌های ناشناس نصب شوند."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"تلفن و داده‌های شخصی‌تان در برابر حمله برنامه‌های ناشناس آسیب‌پذیرتر هستند. با نصب این برنامه، موافقت می‌کنید که مسئول هرگونه آسیب به تلفن یا از دست رفتن داده‌ای هستید که ممکن است در نتیجه استفاده از آن به وجود آید."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"رایانه لوحی و داده‌های شخصی‌تان در برابر حمله برنامه‌های ناشناس آسیب‌پذیرتر هستند. با نصب این برنامه، موافقت می‌کنید که مسئول هرگونه آسیب به رایانه لوحی یا از دست رفتن داده‌ای هستید که ممکن است در نتیجه استفاده از آن به وجود آید."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"تلویزیون و داده‌های شخصی‌تان در برابر حمله برنامه‌های ناشناس آسیب‌پذیرتر هستند. با نصب این برنامه، موافقت می‌کنید که مسئول هرگونه آسیب به تلویزیون یا از دست رفتن داده‌ای هستید که ممکن است در نتیجه استفاده از آن به وجود آید."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"ادامه"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"تنظیمات"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"نصب/حذف نصب برنامه‌های پوشیدنی"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fi-television/strings.xml b/packages/PackageInstaller/res/values-fi-television/strings.xml
new file mode 100644
index 0000000..fbcbe4f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fi-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Hylkää äläkä kysy uudelleen"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Voit muuttaa tätä myöhemmin valitsemalla Asetukset &gt; Sovellukset."</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Näytä järjestelmäsovellukset"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Sovellusten käyttöoikeudet"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Sovellusten käyttöoikeudet"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Käyttöoikeudet – <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Lisäkäyttöoikeudet"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Käyttöoikeudet – <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fi-watch/strings.xml b/packages/PackageInstaller/res/values-fi-watch/strings.xml
new file mode 100644
index 0000000..292c417
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fi-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Hylkää, äläkä kysy uudelleen"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Näytä järjestelmäsovellukset"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ei muutettavissa"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Kyllä"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Peruuta"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fi/strings.xml b/packages/PackageInstaller/res/values-fi/strings.xml
new file mode 100644
index 0000000..7ce75d1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fi/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Paketin asentaja"</string>
+    <string name="next" msgid="3057143178373252333">"Seuraava"</string>
+    <string name="install" msgid="5896438203900042068">"Asenna"</string>
+    <string name="done" msgid="3889387558374211719">"Valmis"</string>
+    <string name="cancel" msgid="8360346460165114585">"Peruuta"</string>
+    <string name="installing" msgid="8613631001631998372">"Asennetaan…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Asennetaan kohdetta <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Sovellus on asennettu."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Haluatko asentaa tämän sovelluksen? Se saa käyttöönsä seuraavat ominaisuudet:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Haluatko asentaa tämän sovelluksen? Se ei vaadi erityisiä käyttöoikeuksia."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Haluatko asentaa päivityksen tähän olemassa olevaan sovellukseen? Olemassa olevat tiedot eivät katoa. Päivitetty sovellus saa käyttöönsä seuraavat ominaisuudet:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Haluatko asentaa päivityksen tähän sisäiseen sovellukseen? Olemassa olevat tiedot eivät katoa. Päivitetty sovellus saa käyttöönsä seuraavat ominaisuudet:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Haluatko asentaa päivityksen tähän sovellukseen? Et menetä nykyisiä tietojasi. Päivitys ei edellytä erityisiä käyttöoikeuksia."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Haluatko asentaa päivityksen tähän laitteen mukana tulleeseen sovellukseen? Et menetä nykyisiä tietojasi. Päivitys ei edellytä erityisiä käyttöoikeuksia."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Sovellusta ei asennettu."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Paketin asennus estettiin."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Sovellusta ei asennettu, koska paketti on ristiriidassa nykyisen paketin kanssa."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Sovellusta ei asennettu, koska se ei ole yhteensopiva tabletin kanssa."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Tämä sovellus ei ole yhteensopiva televisiosi kanssa."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Sovellusta ei asennettu, koska se ei ole yhteensopiva puhelimen kanssa."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Sovellusta ei asennettu, koska paketti vaikuttaa virheelliseltä."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Sovelluksen <xliff:g id="APP_NAME">%1$s</xliff:g> asentaminen tähän tablet-laitteeseen epäonnistui."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei asennu televisioosi."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Sovelluksen <xliff:g id="APP_NAME">%1$s</xliff:g> asentaminen puhelimeesi ei onnistunut."</string>
+    <string name="launch" msgid="4826921505917605463">"Avaa"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Järjestelmänvalvoja ei salli sovellusten asentamista tuntemattomista lähteistä."</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Tämä käyttäjä ei voi asentaa tuntemattomia sovelluksia."</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Tämä käyttäjä ei voi asentaa sovelluksia."</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Hallinnoi sovelluksia"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Tallennustila loppu"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Sovelluksen <xliff:g id="APP_NAME">%1$s</xliff:g> asentaminen epäonnistui. Vapauta tallennustilaa ja yritä uudelleen."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Sovellusta ei löydy"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Sovellusta ei löydy asennettujen sovelluksien luettelosta."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Ei sallittu"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Nykyisellä käyttäjällä ei ole oikeutta suorittaa tätä poistoa."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Virhe"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Sovelluksen poistaminen epäonnistui."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Poista sovellus"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Poista päivitys"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> on osa seuraavaa sovellusta:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Haluatko poistaa tämän sovelluksen?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Haluatko poistaa tämän sovelluksen "<b>"kaikilta"</b>" käyttäjiltä? Sovellus ja sen tiedot poistetaan "<b>"kaikilta"</b>" laitteen käyttäjiltä."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Haluatko poistaa tämän sovelluksen käyttäjältä <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Haluatko korvata tämän sovelluksen tehdasversiolla? Kaikki tiedot poistetaan."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Haluatko korvata tämän sovelluksen tehdasversiolla? Kaikki tiedot poistetaan. Tämä vaikuttaa kaikkiin laitteen käyttäjiin, myös työprofiileihin."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Käynnissä olevat poistot"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Epäonnistuneet poistot"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Poistetaan..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Poistetaan pakettia <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Poisto valmis."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> poistettu"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Poisto epäonnistui."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> on poistettu."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Aktiivista laitteenhallintasovellusta ei voi poistaa käytöstä."</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Käyttäjän <xliff:g id="USERNAME">%1$s</xliff:g> aktiivista laitteenhallintasovellusta ei voi poistaa käytöstä."</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Jotkin käyttäjät/profiilit tarvitsevat tätä sovellusta ja se poistettiin muista."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Profiilisi käyttö edellyttää tätä sovellusta. Sovellusta ei voi poistaa."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Laitteen järjestelmänvalvoja tarvitsee tätä sovellusta eikä sitä voi poistaa."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Hallinnoi laitteenhallintasovelluksia"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Hallinnoi käyttäjiä"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Sovelluksen <xliff:g id="APP_NAME">%1$s</xliff:g> poistaminen epäonnistui"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Paketin jäsentämisessä esiintyi ongelma."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Uusi"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Kaikki"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Tietosuoja"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Laitteen käyttö"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Tämä päivitys ei vaadi uusia käyttöoikeuksia."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Estä"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Lisätietoja"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Kiellä silti"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aina <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Vain sovelluksen käytön aikana"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Aina"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Hylkää äläkä kysy uudelleen"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> pois käytöstä"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"kaikki pois käytöstä"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"kaikki käytössä"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Salli"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Sovellukset"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Sovellusten käyttöoikeudet"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Älä kysy uudestaan"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Ei käyttöoikeuksia"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Lisäkäyttöoikeudet"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Avaa sovelluksen tiedot"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> lisää</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> lisää</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Tämä sovellus on suunniteltu vanhemmalle Android-versiolle. Se ei välttämättä toimi oikein, jos käyttöoikeuksia ei sallita."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"suorita tuntematon toiminto"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Sallitut sovellukset: <xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Näytä järjestelmä"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Piilota järjestelmä"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Ei sovelluksia"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Sijaintiasetukset"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> on tämän laitteen sijaintipalveluiden tarjoaja. Sijainnin käyttöoikeutta voi muokata sijaintiasetuksissa."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Jos peruutat tämän käyttöoikeuden, laitteesi perustoiminnot eivät välttämättä enää toimi oikein."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Käytännön vahvistama"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Käytäntö estää taustakäytön"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Käytäntö sallii taustakäytön"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Käytäntö sallii käytön etualalla"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Järjestelmänvalvoja hallinnoi tätä"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Aina"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Vain sovelluksen käytön aikana"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Ei koskaan"</string>
+    <string name="loading" msgid="7811651799620593731">"Ladataan…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Kaikki käyttöoikeudet"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Muut sovellusluvat"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Lupapyyntö"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Näytön peittokuva havaittiin"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Ennen kuin voit muokata tätä käyttöoikeusasetusta, sinun täytyy poistaa näytön peittokuva käytöstä Asetukset-valikon Sovellukset-kohdasta."</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Avaa Asetukset"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear ei tue asennus- ja poistotoimintoja."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Valitse, mitä käyttöoikeuksia sovellukselle &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; myönnetään."</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on päivitetty. Valitse, mitä käyttöoikeuksia tälle sovellukselle myönnetään."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Peruuta"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Jatka"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Uudet käyttöoikeudet"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Nykyiset käyttöoikeudet"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Valmistellaan sovellusta…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Tuntematon"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Turvallisuussyistä tabletti ei voi asentaa tuntemattomia sovelluksia tästä lähteestä."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Turvallisuussyistä televisiosi ei voi asentaa tuntemattomia sovelluksia tästä lähteestä."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Turvallisuussyistä puhelin ei voi asentaa tuntemattomia sovelluksia tästä lähteestä."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Tuntemattomat sovellukset voivat helpommin kaapata puhelimesi ja henkilötietosi. Lataamalla sovelluksia tästä lähteestä hyväksyt, että olet itse vastuussa puhelimellesi aiheutuvista vahingoista tai tietojen menetyksestä, jotka voivat johtua sovellusten käytöstä."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tuntemattomat sovellukset voivat helpommin kaapata tablettisi ja henkilötietosi. Lataamalla sovelluksia tästä lähteestä hyväksyt, että olet itse vastuussa tabletillesi aiheutuvista vahingoista tai tietojen menetyksestä, jotka voivat johtua sovellusten käytöstä."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Tuntemattomat sovellukset voivat helpommin kaapata televisiosi ja henkilötietosi. Lataamalla sovelluksen hyväksyt, että olet itse vastuussa mahdollisista televisiolle aiheutuvista vahingoista tai tietojen menetyksestä, jotka voivat johtua sovellusten käytöstä."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Jatka"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Asetukset"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear-sovellusten asennus/poistaminen"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fr-rCA-television/strings.xml b/packages/PackageInstaller/res/values-fr-rCA-television/strings.xml
new file mode 100644
index 0000000..f9b360e
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fr-rCA-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Refuser et ne plus demander"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Vous pourrez modifier ce choix plus tard dans le menu Paramètres &gt; Applications"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Afficher les applications système"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Autorisations de l\'application"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Autorisations de l\'application"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Autorisations pour <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Autorisations supplémentaires"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Autorisations pour <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fr-rCA-watch/strings.xml b/packages/PackageInstaller/res/values-fr-rCA-watch/strings.xml
new file mode 100644
index 0000000..ad86d016
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fr-rCA-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Refuser et ne plus demander"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Afficher les applications système"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Inchangeable"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Oui"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Annuler"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fr-rCA/strings.xml b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..e44e465
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Programme installation trousse"</string>
+    <string name="next" msgid="3057143178373252333">"Suivante"</string>
+    <string name="install" msgid="5896438203900042068">"Installer"</string>
+    <string name="done" msgid="3889387558374211719">"Terminé"</string>
+    <string name="cancel" msgid="8360346460165114585">"Annuler"</string>
+    <string name="installing" msgid="8613631001631998372">"Installation..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> en cours…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Application installée."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Voulez-vous installer cette application? Elle pourra :"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Voulez-vous installer cette application? Elle n\'exige aucun accès particulier."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Voulez-vous installer une mise à jour pour cette application? Vos données existantes seront conservées. L\'application mise à jour aura accès à :"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Voulez-vous installer une mise à jour pour cette application intégrée? Vos données existantes seront conservées. L\'application mise à jour aura accès à :"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Voulez-vous installer une mise à jour pour cette application? Vos données ne seront pas perdues. Aucun droit d\'accès spécial n\'est requis."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Voulez-vous installer une mise à jour pour cette application intégrée? Vos données existantes ne seront pas perdues. Aucun droit d\'accès spécial n\'est requis."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Application non installée."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"L\'installation du paquet a été bloquée."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"L\'application n\'a pas été installée, car le paquet entre en conflit avec un paquet existant."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"L\'application n\'a pas été installée, car elle n\'est pas compatible avec votre tablette."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Cette application n\'est pas compatible avec votre téléviseur."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"L\'application n\'a pas été installée, car elle n\'est pas compatible avec votre téléphone."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"L\'application n\'a pas été installée, car elle ne semble pas être valide."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Impossible d\'installer <xliff:g id="APP_NAME">%1$s</xliff:g> sur cette tablette."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'a pas pu être installée sur votre téléviseur."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Impossible d\'installer <xliff:g id="APP_NAME">%1$s</xliff:g> sur ce téléphone."</string>
+    <string name="launch" msgid="4826921505917605463">"Ouvrir"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Votre administrateur n\'autorise pas l\'installation d\'applications obtenues à partir de sources inconnues"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Cet utilisateur ne peut pas installer les applications inconnues"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Cet utilisateur n\'est pas autorisé à installer des applications"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Gérer les applications"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Espace insuffisant"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Impossible d\'installer <xliff:g id="APP_NAME">%1$s</xliff:g>. Veuillez libérer de l\'espace, puis réessayer."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Application non trouvée"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"L\'application ne figure pas dans la liste des applications installées."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Non autorisé"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"L\'utilisateur actuel n\'est pas autorisé à effectuer cette désinstallation."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Erreur"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"L\'application n\'a pas pu être désinstallée."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Désinstaller l\'application"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Désinstaller mise à jour"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> fait partie de l\'application suivante :"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Voulez-vous désinstaller cette application?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Voulez-vous désinstaller cette application pour "<b>"tous"</b>" les utilisateurs? L\'application et ses données seront supprimées pour "<b>"tous"</b>" les utilisateurs de l\'appareil."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Voulez-vous désinstaller cette application pour l\'utilisateur <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Remplacer cette application par la version d\'usine? Toutes les données seront supprimées."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Remplacer cette application par la version d\'usine? Toutes les données seront supprimées. Cela touchera tous les utilisateurs de cet appareil, y compris ceux qui utilisent un profil professionnel."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Désinstallations en cours"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Désinstallations échouées"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Désinstallation..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Désinstallation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> en cours…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Désinstallation terminée."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"L\'application <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a bien été désinstallée"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Échec de la désinstallation."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"La désinstallation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> n\'a pas réussi."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Impossible de désinstaller une application d\'administration de l\'appareil active"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Impossible de désinstaller une application d\'administration de l\'appareil active pour <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Cette application est nécessaire pour certains utilisateurs ou profils, et elle a été désinstallée pour d\'autres."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Cette application est nécessaire pour votre profil et ne peut pas être désinstallée."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Impossible de désinstaller l\'application : requise par administrateur appareil."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Gérer les applications d\'administration d\'appareils"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Gérer les utilisateurs"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Impossible de désinstaller <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Un problème est survenu lors de l\'analyse du paquet."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nouvelles"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Toutes"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Confidentialité"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Accès à l\'appareil"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Cette mise à jour n\'exige pas de nouvelles autorisations."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Refuser"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"En savoir plus"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Refuser quand même"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Toujours autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Seulement durant l\'utilisation de l\'application"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Toujours"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Refuser et ne plus demander"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> autorisation(s) désactivée(s)"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"toutes les autorisations sont désactivées"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"aucune autorisation n\'est désactivée"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Autoriser"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Applications"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Autorisations applis"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ne plus demander"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Aucune autorisation"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Autorisations supplémentaires"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Ouvrir l\'information sur l\'application"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> autre</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> autres</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Cette application a été conçue pour une version antérieure d\'Android. Si vous n\'accordez pas l\'autorisation, il se peut qu\'elle ne fonctionne plus correctement."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"effectuer une action inconnue"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> application(s) autorisée(s) sur <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Afficher le système"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Masquer le système"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Aucune application"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Paramètres de localisation"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> est un fournisseur de services de localisation pour cet appareil. L\'accès à la position peut être modifié dans le menu des paramètres de localisation."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Si vous refusez cette autorisation, il est possible que cela touche certaines fonctionnalités de base de votre appareil."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Activé conformément à la politique"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"L\'accès en arrière-plan est désactivé par la politique"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"L\'accès en arrière-plan est activé par la politique"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"L\'accès en avant-plan est activé par la politique"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Contrôlé par l\'administrateur"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Toujours"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Seulement durant l\'util. de l\'appli"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Jamais"</string>
+    <string name="loading" msgid="7811651799620593731">"Chargement en cours…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Toutes les autorisations"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Autres autorisations de l\'application"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Demande d\'autorisation"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"La superposition d\'écran a été détectée"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Pour modifier ce paramètre d\'autorisation, vous devez tout d\'abord désactiver la superposition d\'écran en accédant à Paramètres &gt; Applications."</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Ouvrir les paramètres"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Les actions d\'installation et de désinstallation ne sont pas prises en charge par Android Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Définissez les autorisations d\'accès de l\'application « <xliff:g id="APP_NAME">%1$s</xliff:g> »"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"L\'application « <xliff:g id="APP_NAME">%1$s</xliff:g> » a été mise à jour. Définissez ses autorisations d\'accès."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Annuler"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continuer"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nouvelles autorisations"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Autorisations actuelles"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Pré-production de l\'application en cours…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Inconnue"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"À des fins de sécurité, l\'installation d\'applications inconnues provenant de cette source n\'est pas autorisée sur cette tablette."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"À des fins de sécurité, l\'installation d\'applications inconnues provenant de cette source n\'est pas autorisée sur ce téléviseur."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"À des fins de sécurité, l\'installation d\'applications inconnues provenant de cette source n\'est pas autorisée sur ce téléphone."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Votre téléphone et vos données personnelles sont plus vulnérables aux attaques provenant d\'applications inconnues. En installant cette application vous acceptez d\'être le seul responsable de tout dommage causé à votre téléphone ou de toute perte de données pouvant découler de l\'utilisation de telles applications."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Votre tablette et vos données personnelles sont plus vulnérables aux attaques provenant d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de l\'utilisation de telles applications."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Votre téléviseur et vos données personnelles sont plus vulnérables face aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre téléviseur ou de toute perte de données pouvant découler de son utilisation."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continuer"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Paramètres"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installer/désinstaller applis Google Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fr-television/strings.xml b/packages/PackageInstaller/res/values-fr-television/strings.xml
new file mode 100644
index 0000000..fa16b94
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fr-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Refuser et ne plus demander"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Vous pourrez modifier ce paramètre plus tard sous Paramètres &gt; Applications."</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Afficher les applications système"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Autorisations de l\'application"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Autorisations de l\'application"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Autorisations pour <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Autorisations supplémentaires"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Autorisations pour <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fr-watch/strings.xml b/packages/PackageInstaller/res/values-fr-watch/strings.xml
new file mode 100644
index 0000000..a172e1c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fr-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Refuser et ne plus demander"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Afficher les applications système"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Non modifiable"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Oui"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Annuler"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fr/strings.xml b/packages/PackageInstaller/res/values-fr/strings.xml
new file mode 100644
index 0000000..58d9123
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fr/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Programme d\'installation du kit"</string>
+    <string name="next" msgid="3057143178373252333">"Suivant"</string>
+    <string name="install" msgid="5896438203900042068">"Installer"</string>
+    <string name="done" msgid="3889387558374211719">"OK"</string>
+    <string name="cancel" msgid="8360346460165114585">"Annuler"</string>
+    <string name="installing" msgid="8613631001631998372">"Installation..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Application installée."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Voulez-vous installer cette application ? Elle permet les actions suivantes :"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Voulez-vous installer cette application ? Elle n\'exige aucun accès particulier."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Voulez-vous installer une mise à jour pour cette application ? Vos données existantes seront conservées. L\'application mise à jour pourra :"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Voulez-vous installer une mise à jour pour cette application intégrée ? Vos données existantes seront conservées. L\'application mise à jour pourra :"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Voulez-vous installer une mise à jour pour cette application ? Vos données ne seront pas perdues. Aucun droit d\'accès spécial n\'est requis."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Voulez-vous installer une mise à jour pour cette application intégrée ? Vos données existantes ne seront pas perdues. Aucun droit d\'accès spécial n\'est requis."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Application non installée."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"L\'installation du package a été bloquée."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"L\'application n\'a pas été installée, car le package entre en conflit avec un package existant."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"L\'application n\'a pas été installée, car elle n\'est pas compatible avec votre tablette."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Cette application n\'est pas compatible avec votre téléviseur."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"L\'application n\'a pas été installée, car elle n\'est pas compatible avec votre téléphone."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"L\'application n\'a pas été installée, car le package semble ne pas être valide."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Impossible d\'installer <xliff:g id="APP_NAME">%1$s</xliff:g> sur cette tablette."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Impossible d\'installer <xliff:g id="APP_NAME">%1$s</xliff:g> sur votre téléviseur."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Impossible d\'installer <xliff:g id="APP_NAME">%1$s</xliff:g> sur ce téléphone."</string>
+    <string name="launch" msgid="4826921505917605463">"Ouvrir"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Votre administrateur n\'autorise pas l\'installation d\'applications obtenues à partir de sources inconnues"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Cet utilisateur ne peut pas installer d\'applications inconnues"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Cet utilisateur n\'est pas autorisé à installer des applications"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Gérer les applications"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Mémoire insuffisante"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Impossible d\'installer <xliff:g id="APP_NAME">%1$s</xliff:g>. Veuillez libérer de l\'espace, puis réessayer."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Application non trouvée"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"L\'application ne figure pas dans la liste des applications installées."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Non autorisé"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"L\'utilisateur actuel n\'est pas autorisé à effectuer cette désinstallation."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Erreur"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Impossible de désinstaller l\'application."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Désinstaller l\'application"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Désinstaller la mise à jour"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> fait partie de l\'application suivante :"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Voulez-vous désinstaller cette application ?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Voulez-vous désinstaller cette application pour "<b>"tous"</b>" les utilisateurs ? L\'application et ses données seront supprimées pour "<b>"tous"</b>" les utilisateurs de l\'appareil."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Voulez-vous désinstaller cette application pour l\'utilisateur <xliff:g id="USERNAME">%1$s</xliff:g> ?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Remplacer cette application par la version d\'usine ? Toutes les données seront supprimées."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Remplacer cette application par la version d\'usine ? Toutes les données seront supprimées. Tous les utilisateurs de cet appareil seront affectés, y compris ceux qui ont un profil professionnel."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Désinstallations en cours"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Désinstallations non abouties"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Désinstallation..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Désinstallation de l\'application <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Désinstallation terminée."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"L\'application <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a été désinstallée"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Échec de la désinstallation."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Échec de la désinstallation de l\'application <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Impossible de désinstaller une application d\'administration de l\'appareil active"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Impossible de désinstaller une application d\'administration de l\'appareil active pour <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Cette application nécessaire pour certains utilisateurs ou profils a été désinstallée pour d\'autres."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Impossible de désinstaller l\'application, car elle est nécessaire pour votre profil."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Impossible désinstaller appli, car elle est requise par administrateur appareil."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Gérer les applis d\'administration de l\'appareil"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Gérer les utilisateurs"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Impossible de désinstaller <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Un problème est survenu lors de l\'analyse du package."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nouveautés"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Toutes"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Confidentialité"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Accès à l\'appareil"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Cette mise à jour n\'exige pas de nouvelles autorisations."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Refuser"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Plus d\'infos"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Refuser quand même"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> sur <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Autoriser l\'application &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à <xliff:g id="ACTION">%2$s</xliff:g> ?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Toujours autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à <xliff:g id="ACTION">%2$s</xliff:g> ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Seulement lors de l\'utilisation de l\'application"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Toujours"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Refuser et ne plus demander"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> désactivées"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"toutes désactivées"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"aucune désactivée"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Autoriser"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Applications"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Autorisations applis"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ne plus demander"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Aucune autorisation"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Autorisations supplémentaires"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Ouvrir les informations sur l\'application"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> autre</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> autres</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Cette application a été conçue pour une ancienne version d\'Android. Si vous désactivez les autorisations, l\'application risque de ne plus fonctionner comme prévu."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"effectuer une action inconnue"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> application(s) autorisée(s) sur <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Afficher les processus système"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Masquer les processus système"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Aucune application"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Paramètres de géolocalisation"</string>
+    <string name="location_warning" msgid="8778701356292735971">"Les services de localisation pour cet appareil sont fournis via <xliff:g id="APP_NAME">%1$s</xliff:g>. Vous pouvez modifier l\'accès aux données de localisation dans les paramètres de localisation."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Si vous refusez cette autorisation, il est possible que cela affecte certaines fonctionnalités de base de votre appareil."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Activé conformément aux règles"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Accès en arrière-plan désactivé conformément au règlement"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Accès en arrière-plan activé conformément au règlement"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Accès au premier plan activé conformément au règlement"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Contrôlé par l\'administrateur"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Toujours"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Seulement lors utilisation appli"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Jamais"</string>
+    <string name="loading" msgid="7811651799620593731">"Chargement en cours…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Toutes les autorisations"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Autres autorisations de l\'application"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Demande d\'autorisation"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Superposition d\'écran détectée"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Pour modifier ce paramètre d\'autorisation, vous devez tout d\'abord désactiver la superposition d\'écran en accédant à Paramètres &gt; Applications."</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Ouvrir les paramètres"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Opérations d\'installation et de désinstallation impossibles sur Android Wear"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Sélectionner les éléments auxquels &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; peut accéder"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"L\'application &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a été mise à jour. Sélectionnez les éléments auxquels elle peut accéder."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Annuler"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continuer"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nouvelles autorisations"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Autorisations actuelles"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Pré-production de l\'application…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Inconnu"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"À des fins de sécurité, l\'installation d\'applications inconnues provenant de cette source n\'est pas autorisée sur cette tablette."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"À des fins de sécurité, l\'installation d\'applications inconnues provenant de cette source n\'est pas autorisée sur ce téléviseur."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"À des fins de sécurité, l\'installation d\'applications inconnues provenant de cette source n\'est pas autorisée sur ce téléphone."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Votre téléphone et vos données personnelles sont plus vulnérables face aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre téléphone ou de toute perte de données pouvant découler de son utilisation."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Votre tablette et vos données personnelles sont plus vulnérables face aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de son utilisation."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Votre téléviseur et vos données personnelles sont plus vulnérables face aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre téléviseur ou de toute perte de données pouvant découler de son utilisation."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continuer"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Paramètres"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installer/Désinstaller les applis Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-gl-television/strings.xml b/packages/PackageInstaller/res/values-gl-television/strings.xml
new file mode 100644
index 0000000..01e8498
--- /dev/null
+++ b/packages/PackageInstaller/res/values-gl-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Denegar e non volver preguntar"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Podes cambiar esta opción máis tarde en Configuración e aplicacións"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Mostrar aplicacións do sistema"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Permisos de aplicacións"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Permisos de aplicacións"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Permisos de <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Permisos adicionais"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Permisos de <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-gl-watch/strings.xml b/packages/PackageInstaller/res/values-gl-watch/strings.xml
new file mode 100644
index 0000000..5cbb970
--- /dev/null
+++ b/packages/PackageInstaller/res/values-gl-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Denegar, non volver preguntar"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar aplicacións do sistema"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Cambio imposible"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Si"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancelar"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-gl/strings.xml b/packages/PackageInstaller/res/values-gl/strings.xml
new file mode 100644
index 0000000..f7bf98d
--- /dev/null
+++ b/packages/PackageInstaller/res/values-gl/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Instalador de paquetes"</string>
+    <string name="next" msgid="3057143178373252333">"Seguinte"</string>
+    <string name="install" msgid="5896438203900042068">"Instalar"</string>
+    <string name="done" msgid="3889387558374211719">"Feito"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancelar"</string>
+    <string name="installing" msgid="8613631001631998372">"Instalando…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplicación instalada"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Queres instalar esta aplicación? Poderá acceder a:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Queres instalar esta aplicación? Non require ningún acceso especial."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Queres instalar unha actualización para esta aplicación? Non se perderán os teus datos existentes. A aplicación actualizada disporá de acceso a:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Queres instalar unha actualización para esta aplicación integrada?  Non se perderán os teus datos existentes. A aplicación actualizada disporá de acceso a:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Queres instalar unha actualización para esta aplicación? Non se perderán os teus datos existentes. Non require ningún acceso especial."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Queres instalar unha actualización para esta aplicación integrada? Non se perderán os teus datos existentes. Non require ningún acceso especial."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplicación non instalada"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Bloqueouse a instalación do paquete."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"A aplicación non se instalou porque o paquete presenta un conflito cun paquete existente."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"A aplicación non se instalou porque a aplicación non é compatible coa tableta."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Esta aplicación non é compatible coa túa televisión."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"A aplicación non se instalou porque a aplicación non é compatible co teléfono."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"A aplicación non se instalou porque parece que o paquete non é válido."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Non se puido instalar <xliff:g id="APP_NAME">%1$s</xliff:g> na túa tableta."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> non se puido instalar na túa televisión."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Non se puido instalar <xliff:g id="APP_NAME">%1$s</xliff:g> no teu teléfono."</string>
+    <string name="launch" msgid="4826921505917605463">"Abrir"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"O teu administrador non permite a instalación de aplicacións obtidas a partir de fontes descoñecidas"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Este usuario non pode instalar aplicacións descoñecidas"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Este usuario non ten permiso para instalar aplicacións"</string>
+    <string name="ok" msgid="3468756155452870475">"Aceptar"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Xestionar aplicacións"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Espazo esgotado"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Non se puido instalar <xliff:g id="APP_NAME">%1$s</xliff:g>. Libera espazo e téntao de novo."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Non se encontrou a aplicación"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Non se atopou a aplicación na lista de aplicacións instaladas."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Non permitido"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"O usuario actual non pode realizar esta desinstalación."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Erro"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Non se puido desinstalar a aplicación."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Desinstalar aplicación"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Desinstalar actualización"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> forma parte da seguinte aplicación:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Queres desinstalar esta aplicación?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Queres desinstalar esta aplicación para "<b>"todos"</b>" os usuarios? A aplicación e os seus datos eliminaranse de "<b>"todos"</b>" os usuarios do dispositivo."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Queres desinstalar esta aplicación para o usuario <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Queres substituír esta aplicación pola versión que viña de fábrica? Eliminaranse todos os datos."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Queres substituír esta aplicación pola versión que viña de fábrica? Eliminaranse todos os datos. Isto afectará a todos os usuarios do dispositivo, incluídos os que teñan perfís de traballo."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Desintalacións en curso"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Erros nas desinstalacións"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Desinstalando…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Desinstalación finalizada"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Desinstalouse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Desinstalación incorrecta"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"A desinstalación de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> non se realizou correctamente."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Non se puido desinstalar a aplicación de administración de dispositivos activa"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Non se puido desinstalar a aplicación de administración de dispositivos activa para <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"A aplicación é necesaria para algúns usuarios ou perfís e estaba desinstalada para outros"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"O teu perfil necesita esta aplicación e non se pode desinstalar."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"O administrador do teu dispositivo necesita esta aplicación e non se pode desinstalar."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Xestionar apps de administración de dispositivos"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Administrar usuarios"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Non se puido desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Produciuse un problema ao analizar o paquete."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Novo"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Todos"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacidade"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Acceso dispositivo"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Esta actualización non require novos permisos."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Denegar"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Máis información"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Denegar igualmente"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Queres permitir á aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Permitir sempre á aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Só ao usar a aplicación"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Sempre"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Denegar e non volver preguntar"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> desactivados"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"todos desactivados"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ningún desactivado"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Permitir"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplicacións"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Permisos de aplicacións"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Non preguntar de novo"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Sen permisos"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Permisos adicionais"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Abrir información da aplicación"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> permisos máis</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> permiso máis</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Esta aplicación deseñouse para unha versión anterior de Android. Denegar o permiso pode provocar que non funcione como está previsto."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"realiza unha acción descoñecida"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> de <xliff:g id="COUNT_1">%2$d</xliff:g> aplicacións con permiso"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Mostrar sistema"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ocultar sistema"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Ningunha aplicación"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Configuración da localización"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> é un fornecedor de servizos de localización para este dispositivo. O acceso de localización pode modificarse desde a configuración de localización."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Se denegas este permiso, é posible que as funcións básicas do teu dispositivo deixen de funcionar segundo o previsto."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Aplicado pola política"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"O acceso en segundo plano está desactivado pola política"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"O acceso en segundo plano está activado pola política"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"O acceso en primeiro plano está activado pola política"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Opción controlada polo administrador"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Sempre"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Só ao usar a aplicación"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nunca"</string>
+    <string name="loading" msgid="7811651799620593731">"Cargando…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Todos os permisos"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Outras funcionalidades da aplicación"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Solicitude de permiso"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Detectouse unha superposición na pantalla"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Para cambiar a configuración deste permiso, primeiro tes que desactivar a superposición na pantalla, en Configuración &gt; Aplicacións"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir configuración"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"As accións de instalar e desinstalar non son compatibles con Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Seleccionar os permisos de acceso que queres dar a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Actualizouse a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;. Selecciona os permisos de acceso que lle queres dar."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancelar"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continuar"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Novos permisos"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Permisos actuais"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Probando aplicación…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Descoñecida"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Por cuestións de seguranza, na tableta non se poden instalar aplicacións descoñecidas procedentes desta fonte."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Por cuestións de seguranza, na televisión non se poden instalar aplicacións descoñecidas procedentes desta fonte."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Por cuestións de seguranza, no teléfono non se poden instalar aplicacións descoñecidas procedentes desta fonte."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"O teléfono e os datos persoais son máis vulnerables aos ataques de aplicacións descoñecidas. Ao instalar esta aplicación, aceptas que es responsable dos danos ocasionados no teléfono ou da perda dos datos que se poidan derivar do seu uso."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"A tableta e os datos persoais son máis vulnerables aos ataques de aplicacións descoñecidas. Ao instalar esta aplicación, aceptas que es responsable dos danos ocasionados na tableta ou da perda dos datos que se poidan derivar do seu uso."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"A televisión e os datos persoais son máis vulnerables aos ataques de aplicacións descoñecidas. Ao instalar esta aplicación, aceptas que es responsable dos danos ocasionados na televisión ou da perda dos datos que se poidan derivar do seu uso."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continuar"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Configuración"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instalando/desinstalando apps Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-gu-television/strings.xml b/packages/PackageInstaller/res/values-gu-television/strings.xml
new file mode 100644
index 0000000..b0a40b6
--- /dev/null
+++ b/packages/PackageInstaller/res/values-gu-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"નકારો અને ફરીથી પૂછશો નહીં"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"તમે પછીથી આને સેટિંગ્સ &gt; એપ્લિકેશન્સમાં બદલી શકો છો"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"સિસ્ટમ ઍપ્લિકેશનો બતાવો"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"ઍપ્લિકેશન પરવાનગીઓ"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"ઍપ્લિકેશન પરવાનગીઓ"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> પરવાનગીઓ"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"વધારાની પરવાનગીઓ"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> પરવાનગીઓ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-gu-watch/strings.xml b/packages/PackageInstaller/res/values-gu-watch/strings.xml
new file mode 100644
index 0000000..6e83cf2
--- /dev/null
+++ b/packages/PackageInstaller/res/values-gu-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"નકારો, ફરીથી પૂછશો નહીં"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"સિસ્ટમ ઍપ્લિકેશનો બતાવો"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"બદલી શકતાં નથી"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"હા"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"રદ કરો"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-gu/strings.xml b/packages/PackageInstaller/res/values-gu/strings.xml
new file mode 100644
index 0000000..5e0a2b3
--- /dev/null
+++ b/packages/PackageInstaller/res/values-gu/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"પૅકેજ ઇન્સ્ટોલર"</string>
+    <string name="next" msgid="3057143178373252333">"આગલું"</string>
+    <string name="install" msgid="5896438203900042068">"ઇન્સ્ટોલ કરો"</string>
+    <string name="done" msgid="3889387558374211719">"થઈ ગયું"</string>
+    <string name="cancel" msgid="8360346460165114585">"રદ કરો"</string>
+    <string name="installing" msgid="8613631001631998372">"ઇન્સ્ટોલ કરી રહ્યું છે…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ને ઇન્સ્ટૉલ કરી રહ્યાં છીએ…"</string>
+    <string name="install_done" msgid="3682715442154357097">"ઍપ્લિકેશન ઇન્સ્ટોલ કરી."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"શું તમે આ ઍપ્લિકેશન ઇન્સ્ટોલ કરવા માંગો છો? તે આની ઍક્સેસ મેળવશે:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"શું તમે આ એપ્લિકેશનને ઇન્સ્ટોલ કરવા માંગો છો? તેને કોઈપણ વિશિષ્ટ ઍક્સેસની જરૂર નથી."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"શું તમે આ અસ્તિત્વમાંની એપ્લિકેશનના અપડેટને ઇન્સ્ટોલ કરવા માગો છો? તમારો અસ્તિત્વમાંનો ડેટા ગુમ થશે નહીં. અપડેટ કરેલ એપ્લિકેશનને આની ઍક્સેસ મળશે:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"શું તમે આ બિલ્ટ-ઇન એપ્લિકેશનના અપડેટને ઇન્સ્ટોલ કરવા માગો છો? તમારો અસ્તિત્વમાંનો ડેટા ગુમ થશે નહીં. અપડેટ કરેલ એપ્લિકેશનને આની ઍક્સેસ મળશે:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"શું તમે આ અસ્તિત્વમાંની એપ્લિકેશનના અપડેટને ઇન્સ્ટોલ કરવા માગો છો? તમારો અસ્તિત્વમાંનો ડેટા ગુમ થશે નહીં. તેને કોઈ વિશિષ્ટ ઍક્સેસની જરૂર હોતી નથી."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"શું તમે આ બિલ્ટ-ઇન એપ્લિકેશનના અપડેટને ઇન્સ્ટોલ કરવા માગો છો? તમારો અસ્તિત્વમાંનો ડેટા ગુમ થશે નહીં. તેને કોઈ વિશિષ્ટ ઍક્સેસની જરૂર હોતી નથી."</string>
+    <string name="install_failed" msgid="6579998651498970899">"ઍપ્લિકેશન ઇન્સ્ટોલ કરેલ નથી."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"પૅકેજને ઇન્સ્ટૉલ થવાથી અવરોધિત કરવામાં આવ્યું હતું."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"પૅકેજનો અસ્તિત્વમાંના પૅકેજ સાથે વિરોધાભાસ હોવાને કારણે ઍપ્લિકેશન ઇન્સ્ટૉલ થઈ નથી."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"તમારા ટેબ્લેટ સાથે ઍપ્લિકેશન સુસંગત ન હોવાને કારણે ઍપ્લિકેશન ઇન્સ્ટૉલ થઈ નથી."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"આ અ‍ૅપ્લિકેશન તમારા ટીવી સાથે સુસંગત નથી."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"તમારા ફોન સાથે ઍપ્લિકેશન સુસંગત ન હોવાને કારણે ઍપ્લિકેશન ઇન્સ્ટૉલ થઈ નથી."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"પૅકેજ અમાન્ય લાગી રહ્યું હોવાને કારણે ઍપ્લિકેશન ઇન્સ્ટૉલ થઈ નથી."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"તમારા ટેબ્લેટ પર <xliff:g id="APP_NAME">%1$s</xliff:g> ઇન્સ્ટોલ કરી શકાયું નથી."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"તમારા ટીવી પર <xliff:g id="APP_NAME">%1$s</xliff:g> ઇન્સ્ટોલ કરી શકાયું નથી."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"તમારા ફોન પર <xliff:g id="APP_NAME">%1$s</xliff:g> ઇન્સ્ટોલ કરી શકાયું નથી."</string>
+    <string name="launch" msgid="4826921505917605463">"ખોલો"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"તમારા વ્યવસ્થાપક અજાણ્યા સ્રોતોથી મેળવેલ ઍપ્લિકેશનોના ઇન્સ્ટૉલેશનની મંજૂરી આપતા નથી"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"આ વપરાશકર્તા અજાણી ઍપ્લિકેશનો ઇન્સ્ટૉલ કરી શકશે નહીં"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"આ વપરાશકર્તાને ઍપ્લિકેશનો ઇન્સ્ટૉલ કરવાની મંજૂરી નથી"</string>
+    <string name="ok" msgid="3468756155452870475">"ઓકે"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"એપ્લિકેશન્સનું સંચાલન કરો"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"જગ્યાની બહાર"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> ઇન્સ્ટોલ કરી શકાઈ નથી. થોડી સ્પેસ ખાલી કરો અને ફરીથી પ્રયાસ કરો."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"ઍપ્લિકેશન મળી નથી"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ઇન્સ્ટોલ કરેલ ઍપ્લિકેશન્સની સૂચિમાં ઍપ્લિકેશન મળી નહોતી."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"મંજૂરી નથી"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"વર્તમાન વપરાશકર્તાને આ અનઇન્સ્ટૉલેશન કરવાની મંજૂરી નથી."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"ભૂલ"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"ઍપ્લિકેશન અનઇન્સ્ટૉલ કરી શકાઈ નહીં."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"ઍપ્લિકેશન અનઇન્સ્ટોલ કરો"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"અપડેટ અનઇન્સ્ટોલ કરો"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> એ નીચેની એપ્લિકેશનનો એક ભાગ છે:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"શું તમે આ એપ્લિકેશનને અનઇન્સ્ટોલ કરવા માંગો છો?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"શું તમે "<b>"તમામ"</b>" વપરાશકર્તાઓ માટે આ ઍપ્લિકેશનને અનઇન્સ્ટોલ કરવા માગો છો? ઉપકરણ પરના "<b>"તમામ"</b>" વપરાશકર્તાઓમાંથી ઍપ્લિકેશન અને તેનો ડેટા દૂર કરવામાં આવશે."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"શું તમે <xliff:g id="USERNAME">%1$s</xliff:g> વપરાશકર્તા માટે આ એપ્લિકેશનને અનઇન્સ્ટોલ કરવા માગો છો?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"આ ઍપ્લિકેશનને ફેક્ટરી સંસ્કરણથી બદલીએ? તમામ ડેટા દૂર કરવામાં આવશે."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"આ ઍપ્લિકેશનને ફેક્ટરી સંસ્કરણથી બદલીએ? તમામ ડેટા દૂર કરવામાં આવશે. આનાથી કાર્ય પ્રોફાઇલ્સ સાથેના વપરાશકર્તાઓ સહિત આ ઉપકરણના તમામ વપરાશકર્તાઓ પ્રભાવિત થશે."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"ચાલી રહેલા અનઇન્સ્ટૉલ"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"નિષ્ફળ થયેલા અનઇન્સ્ટૉલ"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"અનઇન્સ્ટોલ કરી રહ્યું છે..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ને અનઇન્સ્ટૉલ કરી રહ્યાં છે…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"અનઇન્સ્ટોલ કરો સમાપ્ત થયું."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> અનઇન્સ્ટૉલ કર્યું"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"અનઇન્સ્ટોલ કરવું અસફળ રહ્યું."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ને અનઇન્સ્ટૉલ કરવું અસફળ રહ્યું."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"સક્રિય ઉપકરણ વ્યવસ્થાપક ઍપ્લિકેશનોને અનઇન્સ્ટૉલ કરી શકાતી નથી"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> માટે સક્રિય ઉપકરણ વ્યવસ્થાપક ઍપ્લિકેશનોને અનઇન્સ્ટૉલ કરી શકાતી નથી"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"આ અ‍ૅપ્લિકેશન અમુક વપરાશકર્તાઓ અથવા પ્રોફાઇલ્સ માટે જરૂરી છે અને તે અન્ય લોકો માટે અનઇન્સ્ટૉલ કરી હતી"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"તમારી કાર્યાલયની પ્રોફાઇલ માટે ઍપ્લિકેશન જરૂરી છે અને અનઇન્સ્ટૉલ કરી શકાતી નથી."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"આ ઍપ્લિકેશન તમારા ઉપકરણ વ્યવસ્થાપક માટે આવશ્યક છે અને તે અનઇન્સ્ટોલ કરી શકાતી નથી."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"ઉપકરણ વ્યવસ્થાપક ઍપ્લિકેશનોનું સંચાલન કરો"</string>
+    <string name="manage_users" msgid="3125018886835668847">"વપરાશકર્તાઓનું સંચાલન કરો"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> અનઇન્સ્ટોલ કરી શકાઈ નથી."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"પૅકેજનું વિશ્લેષણ કરવામાં એક સમસ્યા આવી હતી."</string>
+    <string name="newPerms" msgid="6039428254474104210">"નવું"</string>
+    <string name="allPerms" msgid="1024385515840703981">"તમામ"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"ગોપનીયતા"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"ઉપકરણ ઍક્સેસ"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"આ અપડેટને કોઈ નવી પરવાનગીઓની જરૂર નથી."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"નકારો"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"વધુ માહિતી"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"કોઇપણ રીતે નકારો"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> માંથી <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ને <xliff:g id="ACTION">%2$s</xliff:g> મંજૂરી આપીએ?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને હંમેશા <xliff:g id="ACTION">%2$s</xliff:g>ની મંજૂરી આપીએ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"માત્ર ઍપનો ઉપયોગ કરતી વખતે જ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"હંમેશા"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"નકારો અને ફરીથી પૂછશો નહીં"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> અક્ષમ કરી"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"તમામ અક્ષમ કરી"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"કોઈપણ અક્ષમ કરેલ નથી"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"મંજૂરી આપો"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"ઍપ્લિકેશનો"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"ઍપ્લિકેશન પરવાનગીઓ"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"ફરીથી પૂછશો નહીં"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"કોઈ પરવાનગીઓ નથી"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"વધારાની પરવાનગીઓ"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"ઍપ માહિતી ખોલો"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"આ ઍપ્લિકેશન Android ના જુના સંસ્કરણ માટે તૈયાર કરવામાં આવી હતી. પરવાનગી નકારવાથી તે ધાર્યા પ્રમાણે બિલકુલ કાર્ય કરશે નહી."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"એક અજાણી ક્રિયા કરો"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g> માંથી <xliff:g id="COUNT_0">%1$d</xliff:g> એપ્લિકેશન્સને મંજૂરી છે"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"સિસ્ટમ બતાવો"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"સિસ્ટમ છુપાવો"</string>
+    <string name="no_apps" msgid="1965493419005012569">"કોઇ ઍપ્લિકેશનો નથી"</string>
+    <string name="location_settings" msgid="1774875730854491297">"સ્થાન સેટિંગ્સ"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> એ આ ઉપકરણ માટે સ્થાન સેવાઓના પ્રદાતા છે. સ્થાન સેટિંગ્સમાંથી સ્થાન ઍક્સેસ સંશોધિત કરી શકાય છે."</string>
+    <string name="system_warning" msgid="7103819124542305179">"જો તમે આ પરવાનગી નકારો છો, તો તમારા ઉપકરણની મૂળભૂત સુવિધાઓ અપેક્ષા પ્રમાણે કાર્ય કરી શકશે નહીં."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"નીતિ દ્વારા લાગુ"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"નીતિ દ્વારા બૅકગ્રાઉન્ડ ઍક્સેસને બંધ કરવામાં આવ્યો છે"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"નીતિ દ્વારા બૅકગ્રાઉન્ડ ઍક્સેસને ચાલુ કરવામાં આવ્યો છે"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"નીતિ દ્વારા ફૉરગ્રાઉન્ડ ઍક્સેસને ચાલુ કરવામાં આવ્યો છે"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"વ્યવસ્થાપક દ્વારા નિયંત્રિત"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"હંમેશા"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"માત્ર ઍપનો ઉપયોગ કરતી વખતે જ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"ક્યારેય નહીં"</string>
+    <string name="loading" msgid="7811651799620593731">"લોડ કરી રહ્યું છે..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"બધી પરવાનગીઓ"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"અન્ય ઍપ્લિકેશન ક્ષમતાઓ"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"પરવાનગીની વિનંતી"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"સ્ક્રીન ઓવરલે મળ્યું"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"આ પરવાનગી સેટિંગ બદલવા માટે, તમારે પહેલા સેટિંગ્સ &gt; Apps માંથી સ્ક્રીન ઓવરલે બંધ કરવું પડશે"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"સેટિંગ્સ ખોલો"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear પર ઇન્સ્ટૉલ/અનઇન્સ્ટૉલ ક્રિયાઓ સમર્થિત નથી."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ને શેના ઍક્સેસ માટેની મંજૂરી આપવી તે પસંદ કરો"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; અપડેટ કરવામાં આવી છે. આ ઍપ્લિકેશનને શેના ઍક્સેસ માટેની મંજૂરી આપવી તે પસંદ કરો."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"રદ કરો"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"ચાલુ રાખો"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"નવી પરવાનગીઓ"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"વર્તમાન પરવાનગીઓ"</string>
+    <string name="message_staging" msgid="6151794817691100003">"ઍપ્લિકેશન અમલમં છે..."</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"અજાણી"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"તમારી સુરક્ષા માટે, તમારા ટૅબ્લેટને આ સ્રોત પરથી અજાણી ઍપ્લિકેશનો ઇન્સ્ટૉલ કરવાની મંજૂરી નથી."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"તમારી સુરક્ષા માટે, તમારા ટીવીને આ સ્રોત પરથી અજાણી ઍપ્લિકેશનો ઇન્સ્ટૉલ કરવાની મંજૂરી નથી."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"તમારી સુરક્ષા માટે, તમારા ફોનને આ સ્રોત પરથી અજાણી ઍપ્લિકેશનો ઇન્સ્ટૉલ કરવાની મંજૂરી નથી."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"તમારો ફોન અને વ્યક્તિગત ડેટા અજાણી ઍપ્લિકેશનો દ્વારા હુમલા માટે વધુ સંવેદનશીલ છે. આ ઍપ્લિકેશન ઇન્સ્ટૉલ કરીને તમે સંમત થાઓ છો કે આનો ઉપયોગ કરવાથી તમારા ફોનને થતી કોઈપણ હાનિ અથવા ડેટાના નુકસાન માટે તમે જવાબદાર છો."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"તમારું ટૅબ્લેટ અને વ્યક્તિગત ડેટા અજાણી ઍપ્લિકેશનો દ્વારા હુમલા માટે વધુ સંવેદનશીલ છે. આ ઍપ્લિકેશન ઇન્સ્ટૉલ કરીને તમે સંમત થાઓ છો કે આનો ઉપયોગ કરવાથી તમારા ટૅબ્લેટને થતી કોઈપણ હાનિ અથવા ડેટાના નુકસાન માટે તમે જવાબદાર છો."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"તમારું ટીવી અને વ્યક્તિગત ડેટા અજાણી ઍપ્લિકેશનો દ્વારા હુમલા માટે વધુ સંવેદનશીલ છે. આ  ઍપ્લિકેશન ઇન્સ્ટૉલ કરીને તમે સંમત થાઓ છો કે આનો ઉપયોગ કરવાથી તમારા ટીવીને થતી કોઈપણ હાનિ અથવા ડેટાના નુકસાન માટે તમે જવાબદાર છો."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"ચાલુ રાખો"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"સેટિંગ્સ"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"એમ્બેડ ઍપ્લિકેશનો ઇન્સ્ટૉલ/અનઇન્સ્ટૉલ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hi-television/strings.xml b/packages/PackageInstaller/res/values-hi-television/strings.xml
new file mode 100644
index 0000000..2acd9c5
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hi-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"मना करें और फिर से ना पूछें"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"आप इसे बाद में सेटिंग &gt; ऐप्‍स में बदल सकते हैं"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"सिस्टम ऐप्स दिखाएं"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"ऐप्लिकेशन अनुमतियां"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"ऐप्लिकेशन अनुमतियां"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> अनुमतियां"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"और अनुमतियां"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> अनुमतियां"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hi-watch/strings.xml b/packages/PackageInstaller/res/values-hi-watch/strings.xml
new file mode 100644
index 0000000..f7adb0c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hi-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"मना करें, फिर से ना पूछें"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"सिस्टम ऐप्स दिखाएं"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"बदला नहीं जा सकता"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"हां"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"रद्द करें"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hi/strings.xml b/packages/PackageInstaller/res/values-hi/strings.xml
new file mode 100644
index 0000000..5ddddbe
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hi/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"पैकेज इंस्‍टॉलर"</string>
+    <string name="next" msgid="3057143178373252333">"आगे"</string>
+    <string name="install" msgid="5896438203900042068">"इंस्‍टॉल करें"</string>
+    <string name="done" msgid="3889387558374211719">"हो गया"</string>
+    <string name="cancel" msgid="8360346460165114585">"रद्द करें"</string>
+    <string name="installing" msgid="8613631001631998372">"इंस्‍टॉल कर रहा है…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> इंस्टॉल हो रहा है…"</string>
+    <string name="install_done" msgid="3682715442154357097">"ऐप्स  इंस्‍टॉल हो गया."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"क्‍या आप इस ऐप्स को इंस्‍टॉल करना चाहते हैं? इससे यहां पर पहुंच प्राप्त होगी:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"क्‍या आप इस ऐप्स को इंस्‍टॉल करना चाहते हैं? इसके लिए किसी विशेष पहुंच की आवश्‍यकता नहीं है."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"क्‍या आप इस मौजूदा ऐप के बारे में नई जानकारी इंस्‍टॉल करना चाहते हैं? आपका मौजूदा डेटा गुम नहीं होगा. अपडेट किये गए ऐप से आपको इन पर पहुंच मिलेगी:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"क्‍या आप इस बिल्ट-इन ऐप के बारे में नई जानकारी इंस्‍टॉल करना चाहते हैं? आपका मौजूदा डेटा गुम नहीं होगा. नई जानकारी वाले ऐप से आपको इन पर मिलेगी:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"क्या आप इस मौजूदा ऐप में नई जानकारी इंस्टॉल करना चाहते हैं? आपका मौजूदा डेटा बना रहेगा. इसे किसी खास पहुंच की ज़रुरत नहीं होती."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"क्या आप इस मौजूदा ऐप में नई जानकारी इंस्टॉल करना चाहते हैं? आपका मौजूदा डेटा बना रहेगा. इसे किसी खास पहुंच की ज़रुरत नहीं होती."</string>
+    <string name="install_failed" msgid="6579998651498970899">"ऐप्स  इंस्‍टॉल नहीं हुआ."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"पैकेज को इंस्टॉल होने से अवरुद्ध किया हुआ है."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"ऐप्लिकेशन इंस्टॉल नहीं हुआ क्योंकि पैकेज का किसी मौजूदा पैकेज से विरोध है."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"ऐप्लिकेशन इंस्टॉल नहीं हुआ क्योंकि ऐप्लिकेशन आपके टैबलेट से संगत नहीं है."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"यह ऐप आपके टीवी के संगत नहीं है."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"ऐप्लिकेशन इंस्टॉल नहीं हुआ क्योंकि ऐप्लिकेशन आपके फ़ोन से संगत नहीं है."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"ऐप्लिकेशन इंस्टॉल नहीं हुआ क्योंकि पैकेज अमान्य लग रहा है."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> को आपके टैबलेट पर इंस्‍टॉल नहीं किया जा सका."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> को आपके टीवी पर इंस्‍टॉल नहीं किया जा सकता."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> को आपके फ़ोन पर इंस्‍टॉल नहीं किया जा सका."</string>
+    <string name="launch" msgid="4826921505917605463">"खोलें"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"आपका व्यवस्थापक अनजान स्रोतों से मिलने वाले ऐप्लिकेशन को इंस्टॉल करने की अनुमति नहीं देता है"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"यह उपयोगकर्ता अनजान ऐप्लिकेशन इंस्टॉल नहीं कर सकता"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"इस उपयोगकर्ता ऐप्लिकेशन इंस्टॉल करने की अनुमति नहीं है"</string>
+    <string name="ok" msgid="3468756155452870475">"ठीक है"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"ऐप्स  प्रबंधित करें"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"जगह नहीं है"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> को इंस्‍टॉल नहीं किया जा सका. थोड़ी जगह खाली करें और फिर से कोशिश करें."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"ऐप्स  नहीं मिला"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ऐप्स , इंस्‍टॉल किए गए ऐप्स  की सूची में नहीं मिला था."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"अनुमति नहीं है"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"मौजूदा उपयोगकर्ता को यह अनइंस्टॉल करने की अनुमति नहीं है"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"गड़बड़ी"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"ऐप्लिकेशन अनइंस्टॉल नहीं किया जा सका."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"ऐप्स अनइंस्‍टॉल करें"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"अपडेट अनइंस्‍टॉल करें"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> निम्‍न ऐप्स  का भाग है:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"क्‍या आप इस ऐप्स  को अनइंस्‍टॉल करना चाहते हैं?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"क्या आप इस ऐप्स  को "<b>"सभी"</b>" उपयोगकर्ताओं के लिए अनइंस्टॉल करना चाहते हैं? ऐप्स  और उसके डेटा को डिवाइस पर "<b>"सभी"</b>" उपयोगकर्ताओं से निकाल दिया जाएगा."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"क्या आप उपयोगकर्ता <xliff:g id="USERNAME">%1$s</xliff:g> के लिए इस ऐप को अनइंस्टॉल करना चाहते हैं?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"इस ऐप्लिकेशन को फ़ैक्टरी वर्शन से बदलें? सभी डेटा निकाल दिया जाएगा."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"इस ऐप्लिकेशन को फ़ैक्ट्री वर्शन से बदलें? पूरा डेटा निकाल दिया जाएगा. इसका इस डिवाइस के सभी उपयोगकर्ताओं पर असर पड़ेगा, जिनमें कार्य प्रोफ़ाइल वाले उपयोगकर्ता शामिल हैं."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"वे अनइंस्टॉल जो चल रहे हैं"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"वे अनइंस्टॉल जो सफल नहीं रहे"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"अनइंस्‍टॉल कर रहा है…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल किया जा रहा है…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"अनइंस्‍टॉल करना पूर्ण हो गया."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल किया गया"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"अनइंस्‍टॉल करना विफल."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> को अनइंस्टॉल करना असफल."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"सक्रिय डिवाइस व्यवस्थापक ऐप्लिकेशन को अनइंस्टॉल नहीं किया जा सकता"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> के लिए सक्रिय डिवाइस व्यवस्थापक ऐप्लिकेशन को अनइंस्टॉल नहीं किया जा सकता"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"यह ऐप्लिकेशन कुछ उपयोगकर्ताओं या प्रोफ़ाइल हेतु आवश्यक है और अन्य हेतु अनइंस्टॉल हो गया है"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"आपकी कार्य प्रोफ़ाइल के लिए यह ऐप्लिकेशन आवश्यक है और उसे अनइंस्टॉल नहीं किया जा सकता."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"आपके डिवाइस व्यवस्थापक के लिए यह ऐप्स जरूरी है व इसे अनइंस्टॉल नहीं किया जा सकता."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"डिवाइस व्यवस्थापक ऐप्लिकेशन प्रबंधित करें"</string>
+    <string name="manage_users" msgid="3125018886835668847">"उपयोगकर्ताओं को प्रबंधित करें"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> को अनइंस्‍टॉल नहीं किया जा सका."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"पैकेज को पार्स करने में कोई समस्‍या थी."</string>
+    <string name="newPerms" msgid="6039428254474104210">"नया"</string>
+    <string name="allPerms" msgid="1024385515840703981">"सभी"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"निजता"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"डिवाइस पहुंच"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"इस अपडेट लिए अनुमति की ज़रुरत नहीं है."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"अस्वीकार करें"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"अधिक जानकारी"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"फिर भी अस्वीकार करें"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> में से <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को <xliff:g id="ACTION">%2$s</xliff:g> की अनुमति दें?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को हमेशा <xliff:g id="ACTION">%2$s</xliff:g> की अनुमति दें?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"सिर्फ़ ऐप्लिकेशन इस्तेमाल करते समय"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"हमेशा"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"अनुमति न दें और दोबारा न पूछें"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> अक्षम"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"सभी अक्षम हैं"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"कोई भी अक्षम नहीं है"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"अनुमति दें"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"ऐप्लिकेशन"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"ऐप्लिकेशन अनुमतियां"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"फिर से न पूछें"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"कोई अनुमति नहीं"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"और अनुमतियां"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"ऐप्लिकेशन से जुड़ी जानकारी देखें"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"इस ऐप को Android के पुराने वर्शन के लिए डिज़ाइन किया गया था. अनुमति अस्वीकार करने पर हो सकता है कि फ़ंक्शन लक्षित रूप से काम नहीं करे."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"कोई अज्ञात कार्रवाई करें"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g> में से <xliff:g id="COUNT_0">%1$d</xliff:g> ऐप्लिकेशन को अनुमति है"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"सिस्टम दिखाएं"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"सिस्टम छिपाएं"</string>
+    <string name="no_apps" msgid="1965493419005012569">"कोई ऐप्स नहीं"</string>
+    <string name="location_settings" msgid="1774875730854491297">"जगह की सेटिंग"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> इस डिवाइस के लिए जगह की जानकारी उपलब्‍ध कराता है. जगह की पहुंच (एक्सेस) को जगह की सेटिंग से बदला जा सकता है."</string>
+    <string name="system_warning" msgid="7103819124542305179">"यदि आप इस अनुमति को अस्वीकार करते हैं, तो हो सकता है कि आपके डिवाइस की मूलभूत सुविधाएं लक्षित कार्य ना कर पाएं."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"नीति द्वारा लागू"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"नीति के मुताबिक बैकग्राउंड एक्सेस बंद किया गया"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"नीति के मुताबिक बैकग्राउंड एक्सेस चालू किया गया"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"नीति के मुताबिक फ़ोरग्राउंड एक्सेस चालू किया गया"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"इसका नियंत्रण एडमिन के पास है"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"हमेशा"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"ऐप्लिकेशन इस्तेमाल करते समय"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"कभी नहीं"</string>
+    <string name="loading" msgid="7811651799620593731">"लोड हो रहा है…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"सभी अनुमतियां"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"अन्‍य ऐप कार्यक्षमताएं"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"अनुमति का अनुरोध"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"स्क्रीन ओवरले मिला"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"इस अनुमति सेटिंग को बदलने के लिए, आपको पहले सेटिंग &gt; ऐप, से स्क्रीन ओवरले को बंद करना होगा"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"सेटिंग खोलें"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"इंस्टॉल/अनइंस्टॉल किए जाने की कार्रवाइयां Wear पर समर्थित नहीं हैं."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"यह चुनें कि &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को किस-किस चीज पर पहुंचने देना चाहते हैं"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपडेट कर दिया गया है. यह चुनें कि इस ऐप्लिकेशन को किस-किस चीज तक पहुंचने देना चाहते हैं."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"रद्द करें"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"जारी रखें"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"नई अनुमतियां"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"वर्तमान अनुमतियां"</string>
+    <string name="message_staging" msgid="6151794817691100003">"ऐप्लिकेशन चरणबद्ध किया जा रहा है…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"अज्ञात"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"आपकी सुरक्षा के लिए, आपके टैबलेट को इस स्रोत से आने वाले अनजान ऐप्लिकेशन इंस्टॉल करने की अनुमति नहीं है."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"आपकी सुरक्षा के लिए, आपके टीवी को इस स्रोत से आने वाले अनजान ऐप्लिकेशन इंस्टॉल करने की अनुमति नहीं है."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"आपकी सुरक्षा के लिए, आपके फ़ोन को इस स्रोत से आने वाले अनजान ऐप्लिकेशन इंस्टॉल करने की अनुमति नहीं है."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"आपका फ़ोन और व्यक्तिगत डेटा अज्ञात ऐप्लिकेशन के हमले के प्रति अधिक संवेदनशील हैं. इस ऐप्लिकेशन को इंस्टॉल करके आप सहमति देते हैं कि इसके उपयोग के चलते आपके फ़ोन को होने वाले किसी भी नुकसान या डेटा की हानि के लिए आप ज़िम्मेदार हैं."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"आपका टैबलेट और व्यक्तिगत डेटा अज्ञात ऐप्लिकेशन के हमले के प्रति अधिक संवेदनशील हैं. इस ऐप्लिकेशन को इंस्टॉल करके आप सहमति देते हैं कि इसके उपयोग के चलते आपके टैबलेट को होने वाले किसी भी नुकसान या डेटा की हानि के लिए आप ज़िम्मेदार हैं."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"आपका टीवी और व्यक्तिगत डेटा अज्ञात ऐप्लिकेशन के हमले के प्रति अधिक संवेदनशील हैं. इस ऐप्लिकेशन को इंस्टॉल करके आप सहमति देते हैं कि इसके उपयोग के चलते आपके टीवी को होने वाले किसी भी नुकसान या डेटा की हानि के लिए आप ज़िम्मेदार हैं."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"जारी रखें"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"सेटिंग"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"वियर ऐप इंस्टॉल/अनइंस्टॉल हो रहे हैं"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hr-television/strings.xml b/packages/PackageInstaller/res/values-hr-television/strings.xml
new file mode 100644
index 0000000..ba363f4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hr-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Odbij i više ne pitaj"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"To možete kasnije promijenili u odjeljku Postavke &gt; Aplikacije"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Prikaži aplikacije sustava"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Dopuštenja aplikacije"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Dopuštenja aplikacije"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Dopuštenja – <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Dodatna dopuštenja"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Dopuštenja – <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hr-watch/strings.xml b/packages/PackageInstaller/res/values-hr-watch/strings.xml
new file mode 100644
index 0000000..cd44eee
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hr-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Ne, više ne pitaj"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Prikaži aplikacije sustava"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Promjena nemoguća"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Da"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Odustani"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hr/strings.xml b/packages/PackageInstaller/res/values-hr/strings.xml
new file mode 100644
index 0000000..3884ae5
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hr/strings.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Alat za instaliranje paketa"</string>
+    <string name="next" msgid="3057143178373252333">"Sljedeća"</string>
+    <string name="install" msgid="5896438203900042068">"Instaliraj"</string>
+    <string name="done" msgid="3889387558374211719">"Gotovo"</string>
+    <string name="cancel" msgid="8360346460165114585">"Odustani"</string>
+    <string name="installing" msgid="8613631001631998372">"Instaliranje..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instaliranje paketa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikacija je instalirana."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Želite li instalirati ovu aplikaciju? Aplikacija će moći sljedeće:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Želite li instalirati ovu aplikaciju? Aplikacija ne zahtijeva nikakav poseban pristup."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Želite li instalirati ažuriranje postojeće aplikacije? Vaši postojeći podaci neće biti izgubljeni. Ažurirana aplikacija dobit će pristup sljedećem:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Želite li instalirati ažuriranje za ovu ugrađenu aplikaciju? Vaši postojeći podaci neće biti izgubljeni. Ažurirana aplikacija dobit će pristup sljedećem:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Želite li instalirati ažuriranje postojeće aplikacije? Vaši postojeći podaci neće se izgubiti. Nije potreban nikakav poseban pristup."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Želite li instalirati ažuriranje te ugrađene aplikacije? Vaši postojeći podaci neće se izgubiti. Nije potreban nikakav poseban pristup."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplikacija nije instalirana."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Instaliranje paketa blokirano je."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplikacija koja nije instalirana kao paket u sukobu je s postojećim paketom."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplikacija koja nije instalirana kao aplikacija nije kompatibilna s vašim tabletom."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Aplikacija nije kompatibilna s vašim televizorom."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplikacija koja nije instalirana kao aplikacija nije kompatibilna s vašim telefonom."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplikacija koja nije instalirana kao paket vjerojatno nije važeća."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> nije moguće instalirati na ovo tabletno računalo."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Nije bilo moguće instalirati aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> na vaš televizor."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> nije moguće instalirati na vaš telefon."</string>
+    <string name="launch" msgid="4826921505917605463">"Otvori"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Vaš administrator ne dopušta instaliranje aplikacija iz nepoznatih izvora"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Ovaj korisnik ne može instalirati nepoznate aplikacije"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Ovaj korisnik nema dopuštenje za instaliranje aplikacija"</string>
+    <string name="ok" msgid="3468756155452870475">"U redu"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Upravljanje aplikacijama"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nema dovoljno mjesta"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> nije moguće instalirati. Oslobodite dio prostora i pokušajte ponovo."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplikacija nije pronađena"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Na popisu instaliranih aplikacija ova aplikacija nije pronađena."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Nije dopušteno"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Trenutačni korisnik nema dopuštenje za to deinstaliranje."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Pogreška"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Deinstaliranje aplikacije nije uspjelo."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Deinstaliraj aplikaciju"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Deinstalacija ažuriranja"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"Aktivnost <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> dio je sljedeće aplikacije:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Želite li deinstalirati ovu aplikaciju?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Želite li deinstalirati tu aplikaciju za "<b>"sve"</b>" korisnike? Aplikacija i njezini podaci bit će uklonjeni sa "<b>"svih"</b>" korisnika na uređaju."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Želite li deinstalirati tu aplikaciju za korisnika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Želite li tu aplikaciju zamijeniti tvorničkom verzijom? Izgubit ćete sve podatke."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Želite li tu aplikaciju zamijeniti tvorničkom verzijom? Izgubit ćete sve podatke. To se odnosi na sve korisnike uređaja, uključujući one s radnim profilima."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Deinstaliranja u tijeku"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Neuspjela deinstaliranja"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Deinstaliranje..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Deinstaliranje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Deinstalacija je završena."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> deinstalirana"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Deinstalacija nije uspjela."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Deinstaliranje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nije uspjelo."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Deinstaliranje aktivne aplikacije administratora uređaja nije uspjelo"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Nije uspjelo deinstaliranje aktivne aplikacije administratora uređaja za <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Ta je aplikacija obavezna za neke korisnike ili profile, deinstalirana je za ostale"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ta je aplikacija potrebna za vaš profil i ne može se deinstalirati."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ta je aplikacija neophodna administratoru uređaja i nije ju moguće deinstalirati."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Upravljaj aplikacijama administratora uređaja"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Upravljaj korisnicima"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> nije moguće instalirati."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Došlo je do problema pri analiziranju paketa."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Novo"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Sve"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privatnost"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Pristup uređaja"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Ovo ažuriranje ne zahtijeva nove dozvole."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Odbij"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Više informacija"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Svejedno odbij"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> od <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da može <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Želite li uvijek dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sljedeće: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Samo dok se aplikacija koristi"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Uvijek"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Odbij i više ne pitaj"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"Onemogućeno: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"sve onemogućeno"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ništa nije onemogućeno"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Dopusti"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikacije"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Dopuštenja aplikacije"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Više me ne pitaj"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Nema dopuštenja"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Dodatna dopuštenja"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Otvori informacije o aplikaciji"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one">Još <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">Još <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Još <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ova je aplikacija napravljena za stariju verziju Androida. Ako ne dobije dopuštenje, možda više neće funkcionirati kako treba."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"izvršiti nepoznatu radnju"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Aplikacije s dopuštenjem: <xliff:g id="COUNT_0">%1$d</xliff:g> od <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Prikaži sustav"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Sakrij sustav"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nema aplikacija"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Postavke lokacije"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> pruža usluge lokacije za ovaj uređaj. Pristup lokaciji može se izmijeniti u postavkama lokacije."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ako ne odobrite ovo dopuštenje, osnovne značajke vašeg uređaja možda više neće funkcionirati pravilno."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Provoditi se na temelju pravila"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Pristup u pozadini onemogućen je pravilima"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Pristup u pozadini omogućen je pravilima"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Pristup u prednjem planu omogućen je pravilima"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Kontrolira administrator"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Uvijek"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Samo dok se aplikacija koristi"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nikad"</string>
+    <string name="loading" msgid="7811651799620593731">"Učitavanje…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Sva dopuštenja"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Ostale mogućnosti aplikacije"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Zahtijevanje dopuštenja"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Otkriveno je preklapanje na zaslonu"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Da biste promijenili tu postavku dopuštenja, prvo morate isključiti preklapanje na zaslonu u Postavkama &gt; Aplikacije"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Otvori postavke"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Radnje instaliranja i deinstaliranja nisu podržane na Wearu."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Odaberite čemu će &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; moći pristupiti"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ažurirana je. Odaberite čemu će moći pristupiti."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Otkaži"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Nastavi"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nova dopuštenja"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Trenutačna dopuštenja"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Postavljanje aplikacije…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Nepoznato"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Iz sigurnosnih razloga tablet nema dopuštenje za instaliranje nepoznatih aplikacija iz ovog izvora."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Iz sigurnosnih razloga televizor nema dopuštenje za instaliranje nepoznatih aplikacija iz ovog izvora."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Iz sigurnosnih razloga telefon nema dopuštenje za instaliranje nepoznatih aplikacija iz ovog izvora."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Vaš telefon i osobni podaci podložniji su napadima nepoznatih aplikacija. Instaliranjem te aplikacije prihvaćate odgovornost za oštećenje telefona ili gubitak podataka do kojih može doći uslijed njezine upotrebe."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Vaš tablet i osobni podaci podložniji su napadima nepoznatih aplikacija. Instaliranjem te aplikacije prihvaćate odgovornost za oštećenje tableta ili gubitak podataka do kojih može doći uslijed njezine upotrebe."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Vaš TV i osobni podaci podložniji su napadima nepoznatih aplikacija. Instaliranjem te aplikacije prihvaćate odgovornost za oštećenje televizora ili gubitak podataka do kojih može doći uslijed njezine upotrebe."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Nastavi"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Postavke"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instaliranje/deinstaliranje Wear apl."</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hu-television/strings.xml b/packages/PackageInstaller/res/values-hu-television/strings.xml
new file mode 100644
index 0000000..0557700
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hu-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Megtagadás, és ne jelenjen meg többé"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Ezt később módosíthatja a Beállítások &gt; Alkalmazások pontnál"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Rendszeralkalmazások megjelenítése"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Alkalmazásengedélyek"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Alkalmazásengedélyek"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> – jogosultságok"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"További engedélyek"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> – jogosultságok"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hu-watch/strings.xml b/packages/PackageInstaller/res/values-hu-watch/strings.xml
new file mode 100644
index 0000000..8ae3504
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hu-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Megtagadás, ne jelenjen meg"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>/<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Rendszeralkalmazások megjelenítése"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nem változtatható"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Igen"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Mégse"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hu/strings.xml b/packages/PackageInstaller/res/values-hu/strings.xml
new file mode 100644
index 0000000..5e96550
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hu/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Csomagtelepítő"</string>
+    <string name="next" msgid="3057143178373252333">"Tovább"</string>
+    <string name="install" msgid="5896438203900042068">"Telepítés"</string>
+    <string name="done" msgid="3889387558374211719">"Kész"</string>
+    <string name="cancel" msgid="8360346460165114585">"Mégse"</string>
+    <string name="installing" msgid="8613631001631998372">"Telepítés..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> telepítése…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Alkalmazás telepítve."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Telepíti ezt az alkalmazást? Az a következőkhöz fog hozzáférést kapni:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Telepíti ezt az alkalmazást? Az alkalmazás nem igényel különleges hozzáférést."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Telepít egy frissítést ehhez a meglévő alkalmazáshoz? A meglévő adatai nem vesznek el. A frissített alkalmazás a következőkhöz kap hozzáférést:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Telepít egy frissítést ehhez a beépített alkalmazáshoz? A meglévő adatai nem vesznek el. A frissített alkalmazás a következőkhöz kap hozzáférést:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Telepít egy frissítést ehhez a meglévő alkalmazáshoz? A meglévő adatai nem vesznek el. A frissítés nem igényel különleges hozzáférést."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Telepít egy frissítést ehhez a beépített alkalmazáshoz? A meglévő adatai nem vesznek el. A frissítés nem igényel különleges hozzáférést."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Az alkalmazás nincs telepítve."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"A csomag telepítését letiltotta a rendszer."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"A nem csomagként telepített alkalmazás ütközik egy már létező csomaggal."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"A nem alkalmazásként telepített alkalmazás nem kompatibilis az Ön táblagépével."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Ez az alkalmazás nem kompatibilis tévéjével."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"A nem alkalmazásként telepített alkalmazás nem kompatibilis az Ön telefonjával."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"A nem csomagként telepített alkalmazás érvénytelen."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás nem telepíthető táblagépére."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás nem telepíthető a tévéjére."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás nem telepíthető telefonjára."</string>
+    <string name="launch" msgid="4826921505917605463">"Megnyitás"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"A rendszergazda nem engedélyezi az ismeretlen forrásokból származó alkalmazások telepítését"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Ez a felhasználó nem telepíthet ismeretlen alkalmazásokat"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Ez a felhasználó nem telepíthet alkalmazásokat"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Alkalmazások kezelése"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nincs elég hely"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazást nem lehet telepíteni. Szabadítson fel egy kis helyet, és próbálja újra."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Az alkalmazás nem található"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Az alkalmazás nem található a telepített alkalmazások listájában."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Nem engedélyezett"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"A jelenlegi felhasználó számára nem engedélyezett az eltávolítás végrehajtása."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Hiba"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Az alkalmazás nem távolítható el."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Alkalmazás eltávolítása"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Frissítés eltávolítása"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"A(z) <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> a következő alkalmazás része:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Eltávolítja ezt az alkalmazást?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Szeretné eltávolítani ezt az alkalmazást "<b>"minden"</b>" felhasználónál? Az alkalmazást és adatait az eszköz "<b>"minden"</b>" felhasználójánál töröljük."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Eltávolítja ezt az alkalmazást <xliff:g id="USERNAME">%1$s</xliff:g> felhasználó esetében?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Lecseréli az alkalmazást a gyári verzióra? Minden adat törlődik."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Lecseréli az alkalmazást a gyári verzióra? Minden adat törlődik. Ez az eszköz összes felhasználóját érinti, így a munkaprofilokkal rendelkezőket is."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Futó telepítések"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Sikertelen telepítések"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Eltávolítás..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"A(z) <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> eltávolítása folyamatban van…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Az eltávolítás befejeződött."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"A(z) <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> eltávolítása befejeződött"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Az eltávolítás sikertelen."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"A(z) <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> eltávolítása nem sikerült."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Nem lehet eltávolítani az aktív eszközrendszergazdai alkalmazást"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Nem lehet eltávolítani az aktív eszközrendszergazdai alkalmazást <xliff:g id="USERNAME">%1$s</xliff:g> felhasználó esetében"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Egyes felhasználóknak/profiloknak szüksége van erre, másoknál pedig eltávolították"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ez az alkalmazás szükséges a profiljához, így nem távolítható el."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Az alkalmazásra szüksége van az eszköz adminisztrátorának, és nem távolítható el."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Eszközrendszergazdai alkalmazások kezelése"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Felhasználók kezelése"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Nem sikerült a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> eltávolítása"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Gond volt a csomag elemzésekor."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Új"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Mind"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Adatvédelem"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Eszközhozzáférés"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"A frissítés nem igényel új engedélyeket."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Elutasítás"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"További információ"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Tiltás mindenképpen"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>/<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára a következőt: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Mindig engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt számára a következőt: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Az alkalmazás használatakor"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Mindig"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Megtagadás, és ne jelenjen meg többé"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> van letiltva"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"az összes le van tiltva"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"egy sincs letiltva"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Engedélyezés"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Alkalmazások"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Alkalmazásengedélyek"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ne jelenjen meg többé"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Nincs engedély"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"További engedélyek"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Alkalmazásinformációk megnyitása"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> további</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> további</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ez az alkalmazás az Android egy korábbi verziójához készült. Az engedély megtagadása esetén előfordulhat, hogy a továbbiakban nem fog megfelelően működni."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"végrehajt egy ismeretlen műveletet"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g>/<xliff:g id="COUNT_0">%1$d</xliff:g> alkalmazás engedélyezve"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Rendszerfolyamatok megjelenítése"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Rendszerfolyamatok elrejtése"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nincsenek alkalmazások"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Helybeállítások"</string>
+    <string name="location_warning" msgid="8778701356292735971">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> helyszolgáltatásokat biztosít ennek az eszköznek. A helyhozzáférést a helybeállításokban lehet módosítani."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ha ezt nem engedélyezi, akkor előfordulhat, hogy az eszköz egyes alapfunkciói nem megfelelően fognak működni."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Irányelv által kényszerítve"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Háttérhozzáférés házirend által letiltva"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Háttérhozzáférés házirend által engedélyezve"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Előtérbeli hozzáférés házirend által engedélyezve"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Rendszergazda által irányítva"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Mindig"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Az alkalmazás használatakor"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Soha"</string>
+    <string name="loading" msgid="7811651799620593731">"Betöltés…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Az összes engedély"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Egyéb alkalmazáslehetőségek"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Engedélykérés"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Képernyőfedvény észlelve"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Ennek az engedélynek a módosításához először ki kell kapcsolnia a képernyőfedvényt a Beállítások &gt; Alkalmazások menüben"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Beállítások megnyitása"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"A Wear nem támogatja a telepítés/eltávolítás műveletet."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Válassza ki, hogy a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mihez férjen hozzá"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; frissítése megtörtént. Válassza ki, hogy mihez férjen hozzá ez az alkalmazás."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Mégse"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Tovább"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Új engedélyek"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Jelenlegi engedélyek"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Alkalmazás fokozatos közzététele…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Ismeretlen"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Az Ön biztonsága érdekében táblagépe nem telepíthet ebből a forrásból származó ismeretlen alkalmazásokat."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Az Ön biztonsága érdekében tévéje nem telepíthet ebből a forrásból származó ismeretlen alkalmazásokat."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Az Ön biztonsága érdekében telefonja nem telepíthet ebből a forrásból származó ismeretlen alkalmazásokat."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefonja és személyes adatai fokozott kockázatnak vannak kitéve az ismeretlen alkalmazások támadásaival szemben. Az alkalmazás telepítésével elismeri, hogy Ön a felelős az alkalmazás használatából eredő esetleges adatvesztésért és a telefont ért károkért."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Táblagépe és személyes adatai fokozott kockázatnak vannak kitéve az ismeretlen alkalmazások támadásaival szemben. Az alkalmazás telepítésével elismeri, hogy Ön a felelős az alkalmazás használatából eredő esetleges adatvesztésért és a táblagépet ért károkért."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Tévéje és személyes adatai fokozott kockázatnak vannak kitéve az ismeretlen alkalmazások támadásaival szemben. Az alkalmazás telepítésével elismeri, hogy Ön a felelős az alkalmazás használatából eredő esetleges adatvesztésért és a tévét ért károkért."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Tovább"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Beállítások"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear-alkalmazások telepítése/törlése"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hy-television/strings.xml b/packages/PackageInstaller/res/values-hy-television/strings.xml
new file mode 100644
index 0000000..f260673
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hy-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Մերժել և այլևս չհարցնել"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Կարող եք փոխել սա ավելի ուշ Կարգավորումներում և Հավելվածներում"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Ցուցադրել համակարգի հավելվածները"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Հավելվածի թույլտվությունները"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Հավելվածի թույլտվությունները"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> թույլտվությունները"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Լրացուցիչ թույլտվություններ"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> թույլտվությունները"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hy-watch/strings.xml b/packages/PackageInstaller/res/values-hy-watch/strings.xml
new file mode 100644
index 0000000..5538858
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hy-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Մերժել, այլևս չհարցնել"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Ցուցադրել համակարգի հավելվածները"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Հնարավոր չէ փոխել"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Այո"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Չեղարկել"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-hy/strings.xml b/packages/PackageInstaller/res/values-hy/strings.xml
new file mode 100644
index 0000000..e89f1ec
--- /dev/null
+++ b/packages/PackageInstaller/res/values-hy/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Փաթեթի տեղադրիչ"</string>
+    <string name="next" msgid="3057143178373252333">"Հաջորդը"</string>
+    <string name="install" msgid="5896438203900042068">"Տեղադրել"</string>
+    <string name="done" msgid="3889387558374211719">"Պատրաստ է"</string>
+    <string name="cancel" msgid="8360346460165114585">"Չեղարկել"</string>
+    <string name="installing" msgid="8613631001631998372">"Տեղադրվում է..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-ի տեղադրում…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Հավելվածը տեղադրված է:"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Ցանկանու՞մ եք տեղադրել այս ծրագիրը: Այն մուտքի հնարավորություն կունենա`"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Ցանկանու՞մ եք տեղադրել այս հավելվածը: Այն հատուկ մուտք չի պահանջում:"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Ցանկանու՞մ եք այս առկա հավելվածում թարմացում տեղադրել: Ձեր ընթացիկ տվյալները չեն կորի: Նորացված հավելվածը կստանա մատչում`"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Ցանկանու՞մ եք այս ներկառուցված հավելվածում թարմացում տեղադրել: Ձեր առկա տվյալները չեն կորի: Նորացված հավելվածը կստանա մատչում `"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Ցանկանու՞մ եք այս առկա հավելվածում թարմացում տեղադրել: Ձեր ընթացիկ տվյալները չեն կորի: Այն չի պահանջում որևէ հատուկ մուտք:"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Ցանկանու՞մ եք այս ներկառուցված հավելվածում թարմացում տեղադրել: Ձեր ընթացիկ տվյալները չեն կորի: Այն չի պահանջում որևէ հատուկ մուտք:"</string>
+    <string name="install_failed" msgid="6579998651498970899">"Հավելվածը տեղադրված չէ:"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Փաթեթի տեղադրումն արգելափակվել է:"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Հավելվածը չի տեղադրվել, քանի որ տեղադրման փաթեթն ունի հակասություն առկա փաթեթի հետ:"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Հավելվածը չի տեղադրվել, քանի որ այն համատեղելի չէ ձեր պլանշետի հետ:"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Այս հավելվածը համատեղելի չէ ձեր հեռուստացույցի հետ:"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Հավելվածը չի տեղադրվել, քանի որ այն համատեղելի չէ ձեր հեռախոսի հետ:"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Հավելվածը չի տեղադրվել, քանի որ տեղադրման փաթեթը, կարծես թե, վնասված է:"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը չհաջողվեց տեղադրել ձեր պլանշետում:"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Չհաջողվեց տեղադրել <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր հեռուստացույցի վրա:"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը չհաջողվեց տեղադրել ձեր հեռախոսում:"</string>
+    <string name="launch" msgid="4826921505917605463">"Բացել"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Ձեր ադմինիստրատորը թույլ չի տալիս տեղադրել հավելվածներ անհայտ աղբյուրներից"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Այս օգտատերը չի կարող անհայտ հավելվածներ տեղադրել"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Այս օգտատիրոջը չի թույլատրվում տեղադրել հավելվածներ"</string>
+    <string name="ok" msgid="3468756155452870475">"Հաստատել"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Կառավարել հավելվածները"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Տարածքից դուրս"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը չհաջողվեց տեղադրել: Ազատեք որոշակի տարածք և կրկին փորձեք:"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Հավելվածը չի գտնվել"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Հավելվածը չի գտնվել տեղադրված հավելվածների ցանկում:"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Արգելված է"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Ընթացիկ օգտատերը հեռացնելու թույլտվություն չունի:"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Սխալ"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Հնարավոր չէ հեռացնել հավելվածը:"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Ապատեղադրել հավելվածը"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Ապատեղադրել թարմացումը"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>-ը հետևյալ հավելվածի մասն է`"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Ուզո՞ւմ եք ապատեղադրել այս հավելվածը։"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Ցանկանու՞մ եք ապատեղադրել այս հավելվածը "<b>"բոլոր"</b>" օգտատերերի համար:  Հավելվածը և դրա տվյալները կհեռացվեն սարքի "<b>"բոլոր"</b>" օգտատերերից:"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Ցանկանում եք ապատեղադրե՞լ այս ծրագիրը <xliff:g id="USERNAME">%1$s</xliff:g> օգտատիրոջ համար:"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Փոխարինե՞լ այս հավելվածը գործարանային տարբերակով: Բոլոր տվյալները կհեռացվեն:"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Փոխարինե՞լ այս հավելվածը գործարանային տարբերակով: Բոլոր տվյալները կհեռացվեն: Դա վերաբերում է այս սարքի բոլոր օգտատերերին, այդ թվում նաև աշխատանքային պրոֆիլներ ունեցողներին:"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Ընթացիկ հեռացումներ"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Ձախողված հեռացումներ"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Ապատեղադրում է..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> հավելվածը հեռացվում է…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Ապատեղադրումը ավարտված է:"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Հեռացված <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Ապատեղադրումն անհաջող է:"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Չհաջողվեց հեռացնել <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> հավելվածը:"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Հնարավոր չէ հեռացնել ակտիվ սարքի ադմինիստրատորի հավելվածը"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Հնարավոր չէ հեռացնել ակտիվ սարքի ադմինիստրատորի հավելվածը <xliff:g id="USERNAME">%1$s</xliff:g> օգտատիրոջ համար"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Այս հավելվածն անհրաժեշտ է որոշ օգտատերերի կամ պրոֆիլների համար և մնացածի մոտ հեռացվել է"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Այս հավելվածն անհրաժեշտ է ձեր պրոֆիլի համար: Այն հնարավոր չէ հեռացնել:"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ծրագիրը ձեր սարքի ադմինիստրատորի կողմից նշվել է որպես պարտադիր և չի կարող հեռացվել:"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Կառավարել սարքի ադմինիստրատորի հավելվածները"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Կառավարել օգտատերերին"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը չհաջողվեց ապատեղադրել:"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Փաթեթը վերլուծելիս խնդիր առաջացավ:"</string>
+    <string name="newPerms" msgid="6039428254474104210">"Նոր"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Բոլորը"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Գաղտնիություն"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Սարքի մատչում"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Այս թարմացումը պահանջում է, որ նոր թույլտվություններ չտրվեն:"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Մերժել"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Այլ տեղեկություններ"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Մերժել ամեն դեպքում"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>-ը <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>-ից"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին <xliff:g id="ACTION">%2$s</xliff:g>:"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Միշտ թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին <xliff:g id="ACTION">%2$s</xliff:g>:"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Միայն հավելվածն օգտագործելիս"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Միշտ"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Մերժել և այլևս չհարցնել"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"կասեցվել է <xliff:g id="COUNT">%1$d</xliff:g> թույլտվություն"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"բոլոր թույլտվությունները կասեցվել են"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ոչ մի թույլտվություն չի կասեցվել"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Թույլատրել"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Հավելվածներ"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Հավելվածների թույլտվություններ"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Այլևս չհարցնել"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Թույլտվություններ չկան"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Լրացուցիչ թույլտվություններ"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Հավելվածի մասին"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Այս հավելվածը նախատեսված է Android-ի ավելի հին տարբերակի համար: Եթե մերժեք թույլտվությունը, այն կարող է չաշխատել ինչպես հարկն է:"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"թույլատրել անհայտ գործողություն"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Թույլատրված է <xliff:g id="COUNT_0">%1$d</xliff:g> հավելվածի՝ <xliff:g id="COUNT_1">%2$d</xliff:g>-ից"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Ցուցադրել համակարգայինները"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Թաքցնել համակարգայինները"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Հավելվածներ չկան"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Տեղորոշման կարգավորումներ"</string>
+    <string name="location_warning" msgid="8778701356292735971">"Այս սարքի տեղորոշման ծառայությունները տրամադրում է <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը: Տեղադրության ցուցադրման կարգավորումները կարող եք փոխել տեղադրության կարգավորումներից:"</string>
+    <string name="system_warning" msgid="7103819124542305179">"Եթե չտրամադրեք այս թույլտվությունը, ձեր սարքի հիմնական գործառույթները հնարավոր է սխալ աշխատեն:"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Սահմանված է կանոններով"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Հասանելիությունը ֆոնային ռեժիմում անջատած է կանոնի համաձայն"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Հասանելիությունը ֆոնային ռեժիմում միացված է կանոնի համաձայն"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Հասանելիությունն ակտիվ ռեժիմում միացված է կանոնի համաձայն"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Վերահսկվում է ադմինիստրատորի կողմից"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Միշտ"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Միայն հավելվածն օգտագործելիս"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Երբեք"</string>
+    <string name="loading" msgid="7811651799620593731">"Բեռնում…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Բոլոր թույլտվությունները"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Այլ հավելվածների հնարավորությունները"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Թույլտվության հարցում"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Ցուցադրում այլ պատուհանների վրա"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Այս թույլտվության կարգավորումները փոխելու համար նախ անհրաժեշտ է անջատել էկրանի վերադրումը՝ անցնելով Կարգավորումներ &gt; Հավելվածներ"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Բացել կարգավորումները"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Տեղադրման/հեռացման գործողությունները Android Wear-ում չեն աջակցվում:"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Ընտրեք, ինչ թույլտվություններ եք ցանկանում տրամադրել &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածը թարմացվել է: Ընտրեք, ինչ թույլտվություններ եք ցանկանում տրամադրել այդ հավելվածին:"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Չեղարկել"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Շարունակել"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Նոր թույլտվությունները"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Առկա թույլտվությունները"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Հավելվածի նախապատրաստում…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Անհայտ"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Անվտանգության նկատառումներից ելնելով՝ ձեր պլանշետին չի թույլատրվում այս աղբյուրից տեղադրել անհայտ հավելվածներ:"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Անվտանգության նկատառումներից ելնելով՝ ձեր հեռուստացույցին չի թույլատրվում այս աղբյուրից տեղադրել անհայտ հավելվածներ:"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Անվտանգության նկատառումներից ելնելով՝ ձեր հեռախոսին չի թույլատրվում այս աղբյուրից տեղադրել անհայտ հավելվածներ:"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Ձեր հեռախոսը և անձնական տվյալներն առավել խոցելի են անհայտ հավելվածների գրոհների նկատմամբ: Տեղադրելով այս հավելվածը՝ դուք ընդունում եք, որ պատասխանատվություն եք կրում հավելվածի օգտագործման հետևանքով ձեր հեռախոսին պատճառած ցանկացած վնասի կամ տվյալների կորստի համար:"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Ձեր պլանշետը և անձնական տվյալներն առավել խոցելի են անհայտ հավելվածների գրոհների նկատմամբ: Տեղադրելով այս հավելվածը՝ դուք ընդունում եք, որ պատասխանատվություն եք կրում հավելվածի օգտագործման հետևանքով ձեր պլանշետին պատճառած ցանկացած վնասի կամ տվյալների կորստի համար:"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Ձեր TV-ն և անձնական տվյալներն առավել խոցելի են անհայտ հավելվածների գրոհների նկատմամբ: Տեղադրելով այս հավելվածը՝ դուք ընդունում եք, որ պատասխանատվություն եք կրում հավելվածի օգտագործման հետևանքով ձեր TV-ին պատճառած ցանկացած վնասի կամ տվյալների կորստի համար:"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Շարունակել"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Կարգավորումներ"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear հավելվածների տեղադրում/հեռացում"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-in-television/strings.xml b/packages/PackageInstaller/res/values-in-television/strings.xml
new file mode 100644
index 0000000..8e6e9ab
--- /dev/null
+++ b/packages/PackageInstaller/res/values-in-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Tolak dan jangan tanya lagi"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Anda dapat mengubah ini nanti di Setelan &gt; Aplikasi"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Tampilkan aplikasi sistem"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Izin aplikasi"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Izin aplikasi"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Izin <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Izin tambahan"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Izin <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-in-watch/strings.xml b/packages/PackageInstaller/res/values-in-watch/strings.xml
new file mode 100644
index 0000000..ca2e087
--- /dev/null
+++ b/packages/PackageInstaller/res/values-in-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Tolak, jangan tanya lagi"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Tampilkan aplikasi sistem"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Tidak dapat diubah"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ya"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Batal"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-in/strings.xml b/packages/PackageInstaller/res/values-in/strings.xml
new file mode 100644
index 0000000..afae29a
--- /dev/null
+++ b/packages/PackageInstaller/res/values-in/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Pemasang paket"</string>
+    <string name="next" msgid="3057143178373252333">"Berikutnya"</string>
+    <string name="install" msgid="5896438203900042068">"Instal"</string>
+    <string name="done" msgid="3889387558374211719">"Selesai"</string>
+    <string name="cancel" msgid="8360346460165114585">"Batal"</string>
+    <string name="installing" msgid="8613631001631998372">"Memasang..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Menginstal <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Apl terpasang."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Apakah Anda ingin memasang aplikasi ini? Aplikasi akan memiliki akses ke:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Apakah Anda ingin memasang aplikasi ini? Aplikasi tidak memerlukan akses khusus apa pun."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Apakah Anda ingin memasang pembaruan ke aplikasi yang ada? Data Anda yang ada tidak akan hilang. Aplikasi yang diperbarui akan mendapatkan akses ke:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Apakah Anda ingin memasang pembaruan ke aplikasi yang tertanam? Data Anda yang ada tidak akan hilang. Aplikasi yang diperbarui akan mendapatkan akses ke:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Anda ingin memasang pembaruan ke aplikasi yang ada ini? Data Anda yang ada akan hilang. Tindakan ini tidak memerlukan akses khusus apa pun."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Anda ingin memasang pembaruan ke aplikasi yang ada di dalamnya? Data Anda yang ada akan hilang. Tindakan ini tidak memerlukan akses khusus apa pun."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Apl tidak terpasang."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Paket diblokir sehingga tidak dapat dipasang."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplikasi yang tidak dipasang sebagai paket akan bentrok dengan paket yang sudah ada."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplikasi yang tidak dipasang sebagai aplikasi tidak kompatibel dengan tablet Anda."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Aplikasi ini tidak kompatibel dengan TV Anda."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplikasi yang tidak dipasang sebagai aplikasi tidak kompatibel dengan ponsel Anda."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplikasi yang tidak dipasang sebagai paket tampaknya tidak valid."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dipasang pada tablet Anda."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dipasang di TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dipasang pada ponsel Anda."</string>
+    <string name="launch" msgid="4826921505917605463">"Buka"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Admin tidak mengizinkan penginstalan aplikasi yang didapatkan dari sumber tidak dikenal"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Aplikasi yang tidak dikenal tidak dapat diinstal oleh pengguna ini"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Pengguna ini tidak diizinkan menginstal aplikasi"</string>
+    <string name="ok" msgid="3468756155452870475">"Oke"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Kelola apl"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Kehabisan ruang penyimpanan"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dipasang. Kosongkan sebagian ruang dan coba lagi."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Apl tidak ditemukan"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Apl tersebut tidak ditemukan di dalam daftar apl yang terpasang."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Tidak diizinkan"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Pengguna saat ini tidak diizinkan meng-uninstal."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Kesalahan"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Aplikasi tidak dapat dipasang."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Uninstal apl"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Uninstal pembaruan"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> adalah bagian dari apl berikut:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Apakah Anda ingin meng-uninstal apl ini?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Anda ingin mencopot aplikasi ini untuk "<b>"semua"</b>" pengguna? Aplikasi dan datanya akan dihapus dari "<b>"semua"</b>" pengguna pada perangkat."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Ingin meng-uninstal aplikasi ini untuk pengguna <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Gantikan aplikasi ini dengan versi pabrik? Semua data akan dihapus."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Gantikan aplikasi ini dengan versi pabrik? Semua data akan dihapus. Tindakan ini memengaruhi semua pengguna perangkat ini, termasuk yang memiliki profil kerja."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Menjalankan uninstal"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Uninstal yang gagal"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Mencopot pemasangan..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Mencopot pemasangan <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Pencopotan pemasangan selesai."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> di-uninstal"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Pencopotan pemasangan tidak berhasil."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Gagal meng-uninstal <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Tidak dapat meng-uninstal aplikasi admin perangkat yang aktif"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Tidak dapat meng-uninstal aplikasi admin perangkat yang aktif untuk <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Aplikasi ini diperlukan untuk beberapa pengguna atau profil, dan telah dicopot pemasangannya untuk yang lainnya"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Aplikasi ini diperlukan untuk profil Anda dan tidak dapat dicopot pemasangannya."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Aplikasi diwajibkan administrator perangkat &amp; pemasangannya tidak bisa dicopot."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Kelola aplikasi admin perangkat"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Kelola pengguna"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dicopot pemasangannya."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Terjadi masalah saat mengurai paket."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Baru"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Semua"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privasi"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Akses Perangkat"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Pembaruan ini tidak memerlukan izin baru."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Tolak"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Info selengkapnya"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Tetap tolak"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> dari <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; untuk <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Selalu izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; untuk <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Hanya saat menggunakan aplikasi"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Selalu"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Tolak dan jangan tanya lagi"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> dinonaktifkan"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"semua dinonaktifkan"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"tidak ada yang dinonaktifkan"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Izinkan"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikasi"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Izin aplikasi"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Jangan tanya lagi"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Tidak ada izin"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Izin tambahan"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Buka info aplikasi"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> lainnya</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> lainnya</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Aplikasi ini dirancang untuk versi lama Android. Menolak izin dapat menyebabkan aplikasi tidak berfungsi lagi sesuai harapan."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"melakukan tindakan yang tidak dikenal"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> dari <xliff:g id="COUNT_1">%2$d</xliff:g> aplikasi diizinkan"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Tampilkan sistem"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Sembunyikan sistem"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Tidak ada aplikasi"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Setelan Lokasi"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> adalah penyedia layanan lokasi untuk perangkat ini. Akses lokasi dapat diubah dari setelan lokasi."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Jika Anda menolak izin ini, fitur dasar perangkat mungkin tidak berfungsi lagi sesuai harapan."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Diterapkan menurut kebijakan"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Akses background dinonaktifkan oleh kebijakan"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Akses background diaktifkan oleh kebijakan"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Akses latar depan diaktifkan oleh kebijakan"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Dikontrol oleh admin"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Selalu"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Hanya saat menggunakan aplikasi"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Tidak pernah"</string>
+    <string name="loading" msgid="7811651799620593731">"Memuat…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Semua izin"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Kemampuan aplikasi lainnya"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Permintaan izin"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Hamparan layar terdeteksi"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Untuk mengubah setelan izin ini, terlebih dahulu Anda harus menonaktifkan hamparan layar dari Setelan &gt; Aplikasi"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Buka setelan"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Instal/Uninstal tidak didukung di Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Pilih item yang boleh diakses oleh &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; telah diperbarui. Pilih item yang boleh diakses oleh aplikasi ini."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Batal"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Lanjutkan"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Izin baru"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Izin saat ini"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Menyiapkan aplikasi..."</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Tidak dikenal"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Demi keamanan, TV tidak diizinkan menginstal aplikasi yang tidak dikenal dari sumber ini."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Demi keamanan, TV tidak diizinkan menginstal aplikasi yang tidak dikenal dari sumber ini."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Demi keamanan, ponsel tidak diizinkan menginstal aplikasi yang tidak dikenal dari sumber ini."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Data pribadi dan ponsel lebih rentan terhadap serangan oleh aplikasi yang tidak dikenal. Dengan menginstal aplikasi ini, Anda setuju bahwa Anda bertanggung jawab atas kerusakan ponsel atau kehilangan data yang mungkin diakibatkan oleh penggunaannya."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Data pribadi dan tablet lebih rentan terhadap serangan oleh aplikasi yang tidak dikenal. Dengan menginstal aplikasi ini, Anda setuju bahwa Anda bertanggung jawab atas kerusakan tablet atau kehilangan data yang mungkin diakibatkan oleh penggunaannya."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Data pribadi dan TV lebih rentan terhadap serangan oleh aplikasi yang tidak dikenal. Dengan menginstal aplikasi ini, Anda setuju bahwa Anda bertanggung jawab atas kerusakan TV atau kehilangan data yang mungkin diakibatkan oleh penggunaannya."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Lanjutkan"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Setelan"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Melakukan instal/uninstal aplikasi Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-is-television/strings.xml b/packages/PackageInstaller/res/values-is-television/strings.xml
new file mode 100644
index 0000000..0c1fad7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-is-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Hafna og ekki spyrja aftur"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Þú getur breytt þessu seinna undir Stillingar og forrit"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Sýna kerfisforrit"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Heimildir forrita"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Heimildir forrita"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Heimildir fyrir <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Viðbótarheimildir"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Heimildir fyrir <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-is-watch/strings.xml b/packages/PackageInstaller/res/values-is-watch/strings.xml
new file mode 100644
index 0000000..b82da5e
--- /dev/null
+++ b/packages/PackageInstaller/res/values-is-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Hafna, ekki spyrja aftur"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Sýna kerfisforrit"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Má ekki breyta"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Já"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Hætta við"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-is/strings.xml b/packages/PackageInstaller/res/values-is/strings.xml
new file mode 100644
index 0000000..ea0bdcb
--- /dev/null
+++ b/packages/PackageInstaller/res/values-is/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Uppsetningarforrit pakka"</string>
+    <string name="next" msgid="3057143178373252333">"Áfram"</string>
+    <string name="install" msgid="5896438203900042068">"Setja upp"</string>
+    <string name="done" msgid="3889387558374211719">"Lokið"</string>
+    <string name="cancel" msgid="8360346460165114585">"Hætta við"</string>
+    <string name="installing" msgid="8613631001631998372">"Setur upp…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Setur upp <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Forritið er uppsett."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Viltu setja þetta forrit upp? Það mun fá aðgang að:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Viltu setja þetta forrit upp? Það krefst ekki neins sérstaks aðgangs."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Viltu setja upp uppfærslu á þessu uppsetta forriti? Eldri gögn glatast ekki. Uppfærða forritið mun fá aðgang að:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Viltu setja upp uppfærslu á þessu innbyggða forriti? Eldri gögn glatast ekki. Uppfærða forritið mun fá aðgang að:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Viltu setja upp uppfærslu á þessu uppsetta forriti? Eldri gögn glatast ekki. Forritið krefst ekki neins sérstaks aðgangs."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Viltu setja upp uppfærslu á þessu innbyggða forriti? Eldri gögn glatast ekki. Forritið krefst ekki neins sérstaks aðgangs."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Forritið er ekki uppsett."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Lokað var á uppsetningu pakkans."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Forritið var ekki sett upp vegna árekstra á milli pakkans og annars pakka."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Forritið var ekki sett upp því að forritið er ekki samhæft við spjaldtölvuna þína."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Þetta forrit er ekki samhæft við sjónvarpið."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Forritið var ekki sett upp því að forritið er ekki samhæft við símann þinn."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Forritið var ekki sett upp því að pakkinn virðist vera ógildur."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Ekki tókst að setja <xliff:g id="APP_NAME">%1$s</xliff:g> upp í spjaldtölvunni."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Ekki var hægt að setja <xliff:g id="APP_NAME">%1$s</xliff:g> upp í sjónvarpinu."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Ekki tókst að setja <xliff:g id="APP_NAME">%1$s</xliff:g> upp í símanum."</string>
+    <string name="launch" msgid="4826921505917605463">"Opna"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Kerfisstjórinn leyfir ekki uppsetningu forrita af óþekktum uppruna"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Þessi notandi getur ekki sett upp óþekkt forrit"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Þessi notandi hefur ekki leyfi til að setja upp forrit"</string>
+    <string name="ok" msgid="3468756155452870475">"Í lagi"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Stjórna forritum"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Ekkert pláss eftir"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Ekki tókst að setja upp <xliff:g id="APP_NAME">%1$s</xliff:g>. Losaðu um pláss og reyndu aftur."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Forritið finnst ekki"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Forritið fannst ekki á listanum yfir uppsett forrit."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Ekki heimilað"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Núverandi notandi hefur ekki heimild til að fjarlægja þetta."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Villa"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Ekki tókst að fjarlægja forritið."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Fjarlægja forrit"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Fjarlægja uppfærslu"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> er hluti af þessu forriti:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Viltu fjarlægja þetta forrit?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Viltu fjarlægja þetta forrit hjá "<b>"öllum"</b>" notendum? Forritið og gögn þess verða fjarlægð hjá "<b>"öllum"</b>" notendum tækisins."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Viltu fjarlægja þetta forrit fyrir notandann <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Viltu skipta þessu forriti út fyrir verksmiðjuútgáfuna? Öll gögn verða fjarlægð."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Viltu skipta þessu forriti út fyrir verksmiðjuútgáfuna? Öll gögn verða fjarlægð. Þetta hefur áhrif á alla notendur tækisins, þar á meðal þá sem eru með vinnusnið."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Fjarlægingar í gangi"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Fjarlægingar sem mistókust"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Fjarlægir…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Fjarlægir <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Forritið hefur verið fjarlægt."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Fjarlægði <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Ekki tókst að fjarlægja forritið."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Ekki tókst að fjarlægja <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Ekki er hægt að fjarlægja virkt forrit tækjastjóra"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Ekki er hægt að fjarlægja virkt forrit tækjastjóra fyrir <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Þessa forrits er krafist hjá sumum notendum eða sniðum en var fjarlægt hjá öðrum"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Sniðið þitt krefst þessa forrits og ekki er hægt að fjarlægja það."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Stjórnandi tækisins krefst þessa forrits og ekki er hægt að fjarlægja það."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Stjórna forritum tækjastjóra"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Stjórna notendum"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Ekki tókst að fjarlægja <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Vandamál kom upp við að vinna úr pakkanum."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nýjar"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Allar"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Persónuvernd"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Tækisaðgangur"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Þessi uppfærsla krefst engra nýrra heimilda."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Hafna"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Frekari upplýsingar"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Hafna samt"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> af <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Leyfa forritinu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Viltu alltaf veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; leyfi til að <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Aðeins þegar forrit er í notkun"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Alltaf"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Hafna og ekki spyrja aftur"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> óvirkar"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"allar óvirkar"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"engin óvirk"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Leyfa"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Forrit"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Heimildir forrits"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ekki spyrja aftur"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Engar heimildir"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Viðbótarheimildir"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Opna upplýsingar um forrit"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> í viðbót</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> í viðbót</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Þetta forrit var hannað fyrir eldri útgáfu af Android. Ef því er ekki veitt heimild er hugsanlegt að það virki ekki rétt."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"framkvæma óþekkta aðgerð"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> forrit af <xliff:g id="COUNT_1">%2$d</xliff:g> leyfð"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Sýna kerfisforrit"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Fela kerfisforrit"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Engin forrit"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Staðsetningarstillingar"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> býður upp á staðsetningarþjónustu fyrir þetta tæki. Hægt er að breyta aðgangi að staðsetningu í stillingum staðsetningar."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ef þú veitir ekki þessa heimild getur verið að grunneiginleikar tækisins virki ekki lengur sem skyldi."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Stjórnað af reglu"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Bakgrunnsaðgangur óvirkur vegna reglu"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Bakgrunnsaðgangur virkur vegna reglu"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Forgrunnsaðgangur virkur vegna reglu"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Stjórnað af kerfisstjóra"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Alltaf"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Aðeins þegar forrit er í notkun"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Aldrei"</string>
+    <string name="loading" msgid="7811651799620593731">"Hleður…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Allar heimildir"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Aðrir forritseiginleikar"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Beiðni um heimild"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Skjáyfirlögn greindist"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Til að breyta þessari heimildarstillingu þarftu fyrst að slökkva á skjáyfirlögn undir Stillingar &gt; Forrit"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Opna stillingar"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Aðgerðir til að setja upp / fjarlægja eru ekki studdar í Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Veldu hverju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fær aðgang að"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; hefur verið uppfært. Veldu hverju forritið fær aðgang að."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Hætta við"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Halda áfram"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nýjar heimildir"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Núgildandi heimildir"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Setur upp forrit…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Óþekkt"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Til að tryggja öryggi þitt er ekki heimild í spjaldtölvunni þinni fyrir uppsetningu óþekktra forrita frá þessari veitu."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Til að tryggja öryggi þitt er ekki heimild í sjónvarpinu þínu fyrir uppsetningu óþekktra forrita frá þessari veitu."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Til að tryggja öryggi þitt er ekki heimild í símanum þínum fyrir uppsetningu óþekktra forrita frá þessari veitu."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Síminn þinn og persónuleg gögn eru berskjaldaðri fyrir árásum forrita af óþekktum uppruna. Með uppsetningu þessa forrits samþykkirðu að bera fulla ábyrgð á hverju því tjóni sem verða kann á símanum eða gagnatapi sem leiða kann af notkun þess."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Spjaldtölvan þín og persónuleg gögn eru berskjaldaðri fyrir árásum forrita af óþekktum uppruna. Með uppsetningu þessa forrits samþykkirðu að bera fulla ábyrgð á hverju því tjóni sem verða kann á spjaldtölvunni eða gagnatapi sem leiða kann af notkun þess."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Sjónvarpið þitt og persónuleg gögn eru berskjaldaðri fyrir árásum forrita af óþekktum uppruna. Með uppsetningu þessa forrits samþykkirðu að bera fulla ábyrgð á hverju því tjóni sem verða kann á sjónvarpinu eða gagnatapi sem leiða kann af notkun þess."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Áfram"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Stillingar"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Uppsetning/fjarlæging Wear forrita"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-it-television/strings.xml b/packages/PackageInstaller/res/values-it-television/strings.xml
new file mode 100644
index 0000000..14c46de
--- /dev/null
+++ b/packages/PackageInstaller/res/values-it-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Nega e non chiedermelo più"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Puoi modificare questa scelta in seguito in Impostazioni &gt; App"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Mostra app di sistema"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Autorizzazioni app"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Autorizzazioni app"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Autorizzazioni <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Altre autorizzazioni"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Autorizzazioni <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-it-watch/strings.xml b/packages/PackageInstaller/res/values-it-watch/strings.xml
new file mode 100644
index 0000000..73b2ab1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-it-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Nega e non chiedermelo più"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostra app di sistema"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Imposs modif"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Sì"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Annulla"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml
new file mode 100644
index 0000000..5870722
--- /dev/null
+++ b/packages/PackageInstaller/res/values-it/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Installazione pacchetti"</string>
+    <string name="next" msgid="3057143178373252333">"Avanti"</string>
+    <string name="install" msgid="5896438203900042068">"Installa"</string>
+    <string name="done" msgid="3889387558374211719">"Fine"</string>
+    <string name="cancel" msgid="8360346460165114585">"Annulla"</string>
+    <string name="installing" msgid="8613631001631998372">"Installazione..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installazione di <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"App installata."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Vuoi installare questa applicazione? Avrà accesso a:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Vuoi installare questa applicazione? Non richiede alcun accesso speciale."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Vuoi installare un aggiornamento per questa applicazione esistente? I tuoi dati esistenti non andranno persi. L\'applicazione aggiornata avrà accesso a:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Vuoi installare un aggiornamento per questa applicazione integrata? I tuoi dati esistenti non andranno persi. L\'applicazione aggiornata avrà accesso a:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Vuoi installare un aggiornamento di questa applicazione esistente? I dati correnti verranno conservati. Non occorrono accessi speciali."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Vuoi installare un aggiornamento di questa applicazione integrata? I dati correnti verranno conservati. Non occorrono accessi speciali."</string>
+    <string name="install_failed" msgid="6579998651498970899">"App non installata."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"È stata bloccata l\'installazione del pacchetto."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"App non installata poiché il pacchetto è in conflitto con un pacchetto esistente."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"App non installata poiché non compatibile con il tuo tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Questa app non è compatibile con la tua TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"App non installata poiché non compatibile con il tuo telefono."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"App non installata poiché il pacchetto risulta non valido."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g> sul tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g> sulla tua TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g> sul telefono."</string>
+    <string name="launch" msgid="4826921505917605463">"Apri"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"L\'amministratore non consente l\'installazione di app ottenute da fonti sconosciute"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Questo utente non può installare app sconosciute"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"L\'utente non è autorizzato a installare app"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Gestisci applicazioni"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Spazio esaurito"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g>. Libera dello spazio e riprova."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Applicazione non trovata"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Impossibile trovare l\'applicazione nell\'elenco di applicazioni installate."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Non autorizzato"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"L\'utente corrente non è autorizzato a eseguire questa disinstallazione."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Errore"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Impossibile disinstallare l\'app."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Disinstalla applicazione"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Disinstalla aggiornamento"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> fa parte della seguente applicazione:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Vuoi disinstallare questa applicazione?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Vuoi disinstallare questa applicazione per "<b>"tutti"</b>" gli utenti? L\'applicazione e i relativi dati verranno rimossi da "<b>"tutti"</b>" gli utenti configurati sul dispositivo."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Disinstallare l\'app per l\'utente <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Sostituire questa app con la versione di fabbrica? Tutti i dati verranno rimossi."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Sostituire questa app con la versione di fabbrica? Tutti i dati verranno rimossi. Saranno interessati tutti gli utenti del dispositivo, inclusi quelli che hanno profili di lavoro."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Disinstallazioni attuali"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Disinstallazioni non riuscite"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Disinstallazione..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Disinstallazione di <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Disinstallazione completata."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"App <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> disinstallata"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Disinstallazione non riuscita."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Impossibile disinstallare <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Impossibile disinstallare l\'app di amministrazione del dispositivo attiva"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Impossibile disinstallare l\'app di amministrazione del dispositivo attiva per <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"L\'app è necessaria per alcuni utenti/profili ed è stata disinstallata per altri"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"L\'app è necessaria per il tuo profilo e non può essere disinstallata."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"App richiesta dall\'amministratore del dispositivo. Non può essere disinstallata."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Gestisci app di amministrazione del dispositivo"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Gestisci utenti"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Impossibile disinstallare <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Errore durante l\'analisi del pacchetto."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nuove"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Tutte"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacy"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Accesso dispositivo"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Questo aggiornamento non richiede nuove autorizzazioni."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Nega"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Altre informazioni"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Nega comunque"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> di <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Vuoi consentire sempre all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Solo durante l\'uso dell\'app"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Sempre"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Nega e non chiedermelo più"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> disattivate"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"tutte disattivate"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"nessuna disattivata"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Consenti"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"App"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Autorizzazioni app"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Non chiedermelo più"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Nessuna autorizzazione"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Altre autorizzazioni"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Visualizza informazioni sull\'app"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other">Altre <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> altra</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Questa app è stata sviluppata per una versione precedente di Android. Se l\'autorizzazione viene negata, l\'app potrebbe non funzionare più come previsto."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"esegue un\'azione sconosciuta"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Sono consentite <xliff:g id="COUNT_0">%1$d</xliff:g> app su <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Mostra app di sistema"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Nascondi app di sistema"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nessuna app"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Geolocalizzazione"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> è un fornitore di servizi di geolocalizzazione per questo dispositivo. È possibile modificare l\'accesso alla posizione dalle impostazioni sulla posizione."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Se neghi questa autorizzazione, le funzionalità di base del dispositivo potrebbero non funzionare più come previsto."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Applicata in base alle norme"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Accesso in background disattivato in base alla norma"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Accesso in background attivato in base alla norma"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Accesso in primo piano attivato in base alla norma"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Gestita dall\'amministratore"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Sempre"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Solo durante l\'uso dell\'app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Mai"</string>
+    <string name="loading" msgid="7811651799620593731">"Caricamento…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Tutte le autorizzazioni"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Altre funzionalità dell\'app"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Richiesta di autorizzazione"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Overlay schermo rilevato"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Per modificare questa impostazione di autorizzazione, devi innanzitutto disattivare l\'overlay schermo da Impostazioni &gt; App"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Apri impostazioni"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Le azioni di installazione/disinstallazione non sono supportate su Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Scegli i dati a cui l\'app <xliff:g id="APP_NAME">%1$s</xliff:g> può accedere"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"L\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; è stata aggiornata. Scegli i dati a cui può accedere."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Annulla"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continua"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nuove autorizzazioni"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Autorizzazioni correnti"</string>
+    <string name="message_staging" msgid="6151794817691100003">"App in preparazione…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Sconosciuto"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Per sicurezza, il tuo tablet non è autorizzato a installare app sconosciute da questa origine."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Per sicurezza, la tua TV non è autorizzata a installare app sconosciute da questa origine."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Per sicurezza, il tuo telefono non è autorizzato a installare app sconosciute da questa origine."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"I dati del telefono e i dati personali sono più vulnerabili agli attacchi di app sconosciute. Se installi questa app, accetti di essere responsabile degli eventuali danni al telefono o dell\'eventuale perdita di dati derivanti dall\'uso dell\'app."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"I dati del tablet e i dati personali sono più vulnerabili agli attacchi di app sconosciute. Se installi questa app, accetti di essere responsabile degli eventuali danni al tablet o dell\'eventuale perdita di dati derivanti dall\'uso dell\'app."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"I dati della TV e i dati personali sono più vulnerabili agli attacchi di app sconosciute. Se installi questa app, accetti di essere responsabile degli eventuali danni alla TV o dell\'eventuale perdita di dati derivanti dall\'uso dell\'app."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continua"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Impostazioni"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installazione/disinstallazione di app Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-iw-television/strings.xml b/packages/PackageInstaller/res/values-iw-television/strings.xml
new file mode 100644
index 0000000..1ec1cd7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-iw-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"דחה ואל תשאל שוב"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"‏ניתן לשנות זאת מאוחר יותר ב\'הגדרות\' &gt; \'אפליקציות\'"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"הצג אפליקציות מערכת"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"הרשאות לאפליקציות"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"הרשאות לאפליקציות"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"הרשאות <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"הרשאות נוספות"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"הרשאות <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-iw-watch/strings.xml b/packages/PackageInstaller/res/values-iw-watch/strings.xml
new file mode 100644
index 0000000..34dd0d3
--- /dev/null
+++ b/packages/PackageInstaller/res/values-iw-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"דחה ואל תשאל שוב"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"הצג אפליקציות מערכת"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"לא ניתן לשנות"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"כן"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"ביטול"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-iw/strings.xml b/packages/PackageInstaller/res/values-iw/strings.xml
new file mode 100644
index 0000000..414fe4c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-iw/strings.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"מתקין החבילה"</string>
+    <string name="next" msgid="3057143178373252333">"הבא"</string>
+    <string name="install" msgid="5896438203900042068">"התקן"</string>
+    <string name="done" msgid="3889387558374211719">"סיום"</string>
+    <string name="cancel" msgid="8360346460165114585">"ביטול"</string>
+    <string name="installing" msgid="8613631001631998372">"מתקין..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"מתקין את <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"האפליקציה הותקנה."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"האם ברצונך להתקין את האפליקציה? היא תקבל גישה אל:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"האם ברצונך להתקין את האפליקציה? היא אינה דורשת גישה מיוחדת."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"האם ברצונך להתקין עדכון לאפליקציה קיימת זו? הנתונים הקיימים שלך לא יאבדו. האפליקציה המעודכנת תקבל גישה אל:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"האם ברצונך להתקין עדכון לאפליקציה מובנית זו? הנתונים הקיימים שלך לא יאבדו. האפליקציה המעודכנת תקבל גישה אל:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"האם ברצונך להתקין עדכון עבור אפליקציה קיימת זו? הנתונים הקיימים שלך לא יאבדו. אין צורך בגישה מיוחדת."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"האם ברצונך להתקין עדכון עבור אפליקציה מובנית זו? הנתונים הקיימים שלך לא יאבדו. אין צורך בגישה מיוחדת."</string>
+    <string name="install_failed" msgid="6579998651498970899">"האפליקציה לא הותקנה."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"החבילה נחסמה להתקנה."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"האפליקציה לא הותקנה כי החבילה מתנגשת עם חבילה קיימת."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"האפליקציה לא הותקנה כי האפליקציה אינה תואמת לטאבלט."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"האפליקציה הזו אינה תואמת לטלוויזיה שלך."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"האפליקציה לא הותקנה כי האפליקציה אינה תואמת לטלפון."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"האפליקציה לא הותקנה כי נראה שהחבילה לא תקפה."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"לא ניתן להתקין את <xliff:g id="APP_NAME">%1$s</xliff:g> בטאבלט שלך."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"לא ניתן להתקין את <xliff:g id="APP_NAME">%1$s</xliff:g> בטלוויזיה שלך."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"לא ניתן להתקין את <xliff:g id="APP_NAME">%1$s</xliff:g> בטלפון שלך."</string>
+    <string name="launch" msgid="4826921505917605463">"פתח"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"מנהל המערכת שלך לא מתיר התקנה של אפליקציות ממקורות לא ידועים"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"למשתמש זה אין הרשאה להתקין אפליקציות שאינן מוכרות"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"למשתמש הזה אין הרשאה להתקין אפליקציות"</string>
+    <string name="ok" msgid="3468756155452870475">"אישור"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"נהל אפליקציות"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"אין מספיק שטח"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"לא ניתן להתקין את <xliff:g id="APP_NAME">%1$s</xliff:g>. פנה שטח ונסה שוב."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"האפליקציה לא נמצא"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"האפליקציה לא נמצאה ברשימת האפליקציות המותקנות."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"לא מורשה"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"המשתמש הנוכחי אינו מורשה להסיר את ההתקנה הזו."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"שגיאה"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"לא ניתן היה להסיר את התקנת האפליקציה."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"הסר את התקנת האפליקציה"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"הסר את התקנת העדכון"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> הוא חלק מהאפליקציה הבאה:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"האם ברצונך להסיר את ההתקנה של אפליקציה זו?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"האם אתה רוצה להסיר את האפליקציה הזו עבור "<b>"כל"</b>" המשתמשים? האפליקציה והנתונים שלה יוסרו מ"<b>"כל"</b>" המשתמשים במכשיר."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"האם ברצונך להסיר את התקנתה של אפליקציה זו עבור המשתמש <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"האם להחליף את האפליקציה הזאת בגירסת היצרן? כל הנתונים יוסרו."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"האם להחליף את האפליקציה הזאת בגירסת היצרן? כל הנתונים יוסרו. הפעולה תשפיע על כל משתמשי המכשיר, כולל משתמשים בעלי פרופיל עבודה."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"התקנות בתהליכי הסרה"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"הסרות התקנה שנכשלו"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"מסיר התקנה..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"מסיר את ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"הסרת ההתקנה הסתיימה."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> הוסרה"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"הסרת התקנה נכשלה."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"נכשלה הסרת ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"לא ניתן להסיר את ההתקנה של אפליקציה פעילה של מנהל המכשיר"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"לא ניתן להסיר את ההתקנה של אפליקציה פעילה של מנהל המכשיר של <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"אפליקציה זו נדרשת לחלק מהמשתמשים או מהפרופילים והתקנתה הוסרה למשתמשים אחרים"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"האפליקציה הזו נחוצה לפרופיל שלך ולא ניתן להסיר את ההתקנה שלה."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"מנהל המכשיר שלך מחייב את קיומה של אפליקציה זו, ולא ניתן להסירה."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"אפליקציות למנהל המערכת של מכשיר מנוהל"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ניהול משתמשים"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"לא ניתן להסיר את ההתקנה של <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"אירעה בעיה בניתוח החבילה."</string>
+    <string name="newPerms" msgid="6039428254474104210">"חדש"</string>
+    <string name="allPerms" msgid="1024385515840703981">"הכל"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"פרטיות"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"גישה למכשיר"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"עדכון זה לא דורש הרשאות חדשות."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"לא, תודה"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"למידע נוסף"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"לדחות בכל מקרה"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> מתוך <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"‏האם לאשר ל&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"‏תמיד להרשות לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"רק בזמן השימוש באפליקציה"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"תמיד"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"יש לדחות ואין לשאול שוב"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> הרשאות מושבתות"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"כל ההרשאות מושבתות"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"אין הרשאות מושבתות"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"כן, זה בסדר"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"אפליקציות"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"הרשאות לאפליקציות"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"ראיתי פעם אחת, זה מספיק"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"אין הרשאות"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"הרשאות נוספות"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"פתיחה של פרטי האפליקציה"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"‏האפליקציה הזו עוצבה בשביל גרסה ישנה יותר של Android. דחיית ההרשאה עשויה לגרום לה לתפקד בצורה לקויה."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ביצוע פעולה לא ידועה"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> מתוך <xliff:g id="COUNT_1">%2$d</xliff:g> אפליקציות קיבלו הרשאה"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"הרשאות המערכת"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"הסתר מערכת"</string>
+    <string name="no_apps" msgid="1965493419005012569">"אין אפליקציות"</string>
+    <string name="location_settings" msgid="1774875730854491297">"הגדרות מיקום"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא ספק של שירותי מיקום בשביל המכשיר הזה. אפשר לשנות את גישת המיקום בהגדרות המיקום."</string>
+    <string name="system_warning" msgid="7103819124542305179">"אם תדחה את ההרשאה הזו, ייתכן שתכונות בסיסיות במכשיר לא יפעלו כצפוי."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"נאכף באמצעות מדיניות"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"הגישה ברקע מושבתת על ידי מדיניות"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"הגישה ברקע מופעלת על ידי מדיניות"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"הגישה בחזית מופעלת על ידי מדיניות"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"נמצא בשליטת מנהל מערכת"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"תמיד"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"רק בזמן השימוש באפליקציה"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"אף פעם"</string>
+    <string name="loading" msgid="7811651799620593731">"טוען..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"כל ההרשאות"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"הרשאות אחרות של האפליקציה"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"בקשת הרשאה"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"זוהתה שכבת על במסך"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"‏כדי לשנות את הגדרת ההרשאה הזו, ראשית עליך לכבות את שכבת העל במסך ב\'הגדרות\' &gt; \'אפליקציות\'"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"פתח הגדרות"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"‏פעולות התקנה/הסרת התקנה אינן נתמכות ב-Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"‏בחר אילו הרשאות גישה ברצונך לתת ל &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; עודכנה. בחר אילו הרשאות גישה יהיו לאפליקציה זו."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"ביטול"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"המשך"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"הרשאות חדשות"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"הרשאות קיימות"</string>
+    <string name="message_staging" msgid="6151794817691100003">"מכין אפליקציה להתקנה…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"לא ידוע"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"לצורכי אבטחה, הטאבלט שלך חסום להתקנת אפליקציות בלתי מוכרות המגיעות ממקור זה."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"לצורכי אבטחה, מכשיר הטלוויזיה שלך חסום להתקנת אפליקציות בלתי מוכרות המגיעות ממקור זה."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"לצורכי אבטחה, הטלפון שלך חסום להתקנת אפליקציות בלתי מוכרות המגיעות ממקור זה."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"נתוני הטלפון והנתונים האישיים שלך חשופים יותר בפני התקפות על ידי אפליקציות ממקורות לא ידועים. אם תתקין אפליקציה זו, אתה מסכים לכך שאתה האחראי הבלעדי במקרה של אובדן נתונים או אם ייגרם נזק לטלפון שלך בעקבות השימוש באפליקציה."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"נתוני הטאבלט והנתונים האישיים שלך חשופים יותר בפני התקפות על ידי אפליקציות ממקורות לא ידועים. אם תתקין אפליקציה זו, אתה מסכים לכך שאתה האחראי הבלעדי במקרה של אובדן נתונים או אם ייגרם נזק לטאבלט שלך בעקבות השימוש באפליקציה."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"נתוני הטלוויזיה והנתונים האישיים שלך חשופים יותר בפני התקפות על ידי אפליקציות ממקורות לא ידועים. אם תתקין אפליקציה זו, אתה מסכים לכך שאתה האחראי הבלעדי במקרה של אובדן נתונים או אם ייגרם נזק לטלוויזיה שלך בעקבות השימוש באפליקציה."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"המשך"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"הגדרות"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"‏מתקין/מסיר התקנה של אפליקציות Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ja-television/strings.xml b/packages/PackageInstaller/res/values-ja-television/strings.xml
new file mode 100644
index 0000000..9f31829
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ja-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"許可しない(次回から表示しない)"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"これは後から[設定]&gt;[アプリ]で変更できます"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"システムアプリの表示"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"アプリの権限"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"アプリの権限"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g>の権限"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"その他の権限"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g>の権限"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ja-watch/strings.xml b/packages/PackageInstaller/res/values-ja-watch/strings.xml
new file mode 100644
index 0000000..735b908
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ja-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"許可しない(今後表示しない)"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"システムアプリの表示"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"変更不可"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"はい"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"キャンセル"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ja/strings.xml b/packages/PackageInstaller/res/values-ja/strings.xml
new file mode 100644
index 0000000..5a7dc7d
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ja/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"パッケージインストーラ"</string>
+    <string name="next" msgid="3057143178373252333">"次へ"</string>
+    <string name="install" msgid="5896438203900042068">"インストール"</string>
+    <string name="done" msgid="3889387558374211719">"完了"</string>
+    <string name="cancel" msgid="8360346460165114585">"キャンセル"</string>
+    <string name="installing" msgid="8613631001631998372">"インストール中..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」をインストールしています…"</string>
+    <string name="install_done" msgid="3682715442154357097">"アプリをインストールしました。"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"このアプリケーションをインストールしてもよろしいですか?このアプリケーションは下記にアクセスする場合があります:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"このアプリケーションをインストールしてもよろしいですか?このアプリケーションは特別なアクセス許可を必要としません。"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"この既存のアプリケーションへのアップデートをインストールしてもよろしいですか?既存のデータは失われません。アップデート後のアプリケーションは下記にアクセスする場合があります:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"この内蔵アプリケーションへのアップデートをインストールしてもよろしいですか?既存のデータは失われません。アップデート後のアプリケーションは下記にアクセスする場合があります:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"この既存のアプリにアップデートをインストールしますか?既存のデータが失われることはありません。特別なアクセス権も必要ありません。"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"この内蔵アプリにアップデートをインストールしますか?既存のデータが失われることはありません。特別なアクセス権も必要ありません。"</string>
+    <string name="install_failed" msgid="6579998651498970899">"アプリはインストールされていません。"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"パッケージのインストールはブロックされています。"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"パッケージが既存のパッケージと競合するため、アプリをインストールできませんでした。"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"お使いのタブレットに対応していないため、アプリをインストールできませんでした。"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"このアプリはお使いのテレビに対応していません。"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"お使いのスマートフォンに対応していないため、アプリをインストールできませんでした。"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"パッケージが無効の可能性があるため、アプリをインストールできませんでした。"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g>をタブレットにインストールできませんでした。"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g>をテレビにインストールできませんでした。"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g>を端末にインストールできませんでした。"</string>
+    <string name="launch" msgid="4826921505917605463">"開く"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"提供元不明のアプリをインストールすることは、管理者により禁止されています"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"このユーザーは不明なアプリをインストールできません"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"このユーザーはアプリをインストールできません"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"アプリを管理"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"容量不足です"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g>をインストールできませんでした。空き容量を増やしてもう一度お試しください。"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"アプリが見つかりません"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"インストール済みアプリのリストに、このアプリはありません。"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"許可されていません"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"このアンインストール操作は現在のユーザーには許可されていません。"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"エラー"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"アプリをアンインストールできませんでした。"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"アプリをアンインストール"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"アップデートをアンインストール"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>は次のアプリの一部です:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"このアプリをアンインストールしますか?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"このアプリを"<b>"すべての"</b>"ユーザーからアンインストールしますか?このアプリとそのデータは端末の"<b>"すべての"</b>"ユーザーから削除されます。"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"<xliff:g id="USERNAME">%1$s</xliff:g>さんのアプリをアンインストールしますか?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"このアプリを出荷時の状態に戻しますか?データがすべて削除されます。"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"このアプリを出荷時の状態に戻しますか?データがすべて削除されます。これは、仕事用プロファイルを設定しているユーザーも含めて、この端末を使用するすべてのユーザーが対象となります。"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"実行中のアンインストール"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"エラーになったアンインストール"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"アンインストール中..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」をアンインストールしています…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"アンインストールが完了しました。"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」をアンインストールしました"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"アンインストールできませんでした。"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」をアンインストールできませんでした。"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"有効な端末管理アプリをアンインストールできません"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> さんの有効な端末管理アプリをアンインストールできません"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"このアプリは一部のユーザーやプロファイルに必要なため、アンインストールできませんでした"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"このアプリはプロファイルに必要なため、アンインストールできません。"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"このアプリは端末管理者が必要としているため、アンインストールできません。"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"端末管理アプリを管理"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ユーザーを管理"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g>をアンインストールできませんでした。"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"パッケージの解析中に問題が発生しました。"</string>
+    <string name="newPerms" msgid="6039428254474104210">"New"</string>
+    <string name="allPerms" msgid="1024385515840703981">"すべて"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"プライバシー"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"端末アクセス"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"このアップデートでは新たな許可は必要ありません。"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"許可しない"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"詳細"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"許可しない"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に<xliff:g id="ACTION">%2$s</xliff:g>を許可しますか?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"「<xliff:g id="ACTION">%2$s</xliff:g>」を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に常に許可しますか?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"アプリの使用中のみ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"常時"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"許可しない(次回から表示しない)"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> 件無効"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"すべて無効"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"無効な権限なし"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"許可"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"アプリ"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"アプリの権限"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"今後表示しない"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"権限がありません"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"その他の権限"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"アプリ情報を開く"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"このアプリはAndroidの以前のバージョンを対象としています。権限を許可しないと、意図されたとおりに動作しなくなる可能性があります。"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"不明な操作の実行"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g>個のアプリを許可"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"システムを表示"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"システムを表示しない"</string>
+    <string name="no_apps" msgid="1965493419005012569">"アプリなし"</string>
+    <string name="location_settings" msgid="1774875730854491297">"位置情報の設定"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g>はこの端末の位置情報サービスのプロバイダです。位置情報アクセスは位置情報の設定から変更できます。"</string>
+    <string name="system_warning" msgid="7103819124542305179">"この権限を許可しないと、お使いの端末の基本的な機能が意図されたとおりに動作しなくなる可能性があります。"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"ポリシーにより適用"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"バックグラウンドでのアクセスはポリシーによって無効です"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"バックグラウンドでのアクセスはポリシーによって有効です"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"フォアグラウンドでのアクセスはポリシーによって有効です"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"管理者により管理されています"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"常時"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"アプリの使用中のみ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"なし"</string>
+    <string name="loading" msgid="7811651799620593731">"読み込んでいます…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"すべての権限"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"その他のアプリ機能"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"権限のリクエスト"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"画面オーバーレイを検出"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"この権限設定を変更するには、まず[設定]&gt;[アプリ]から画面オーバーレイをOFFにします"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"設定を開く"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear ではインストールやアンインストールができません"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可する権限の選択"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」が更新されました。このアプリに許可する権限を選択してください。"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"キャンセル"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"続行"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"新しい権限"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"現在の権限"</string>
+    <string name="message_staging" msgid="6151794817691100003">"アプリを準備しています…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"不明"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"セキュリティ上の理由から、お使いのタブレットではこの提供元からの不明なアプリをインストールすることはできません。"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"セキュリティ上の理由から、お使いのテレビではこの提供元からの不明なアプリをインストールすることはできません。"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"セキュリティ上の理由から、お使いのスマートフォンではこの提供元からの不明なアプリをインストールすることはできません。"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"不明なアプリをインストールするとスマートフォンや個人データが攻撃を受ける可能性が高くなります。このアプリをインストールすることにより、アプリの使用により生じる可能性があるスマートフォンへの損害やデータの損失について、ユーザーご自身が単独で責任を負うことに同意するものとします。"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"不明なアプリをインストールするとタブレットや個人データが攻撃を受ける可能性が高くなります。このアプリをインストールすることにより、アプリの使用により生じる可能性があるタブレットへの損害やデータの損失について、ユーザーご自身が単独で責任を負うことに同意するものとします。"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"不明なアプリをインストールすると TV や個人データが攻撃を受ける可能性が高くなります。このアプリをインストールすることにより、アプリの使用により生じる可能性がある TV への損害やデータの損失について、ユーザーご自身が単独で責任を負うことに同意するものとします。"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"続行"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"設定"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear アプリのインストールとアンインストール"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ka-television/strings.xml b/packages/PackageInstaller/res/values-ka-television/strings.xml
new file mode 100644
index 0000000..b7d03b0
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ka-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"უარყავი და აღარ მკითხო"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"ამის შეცვლა მოგვიანებით შეგიძლიათ სექციაში პარამეტრები &gt; აპები"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"სისტემის აპების ჩვენება"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"აპის ნებართვები"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"აპის ნებართვები"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"ნებართვები (<xliff:g id="PERMISSION">%1$s</xliff:g>)"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"დამატებითი ნებართვები"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"ნებართვები (<xliff:g id="PERMISSION">%1$s</xliff:g>)"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ka-watch/strings.xml b/packages/PackageInstaller/res/values-ka-watch/strings.xml
new file mode 100644
index 0000000..1574912
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ka-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"უარყავი და აღარ მკითხო"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"სისტემის აპების ჩვენება"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ვერ შეიცვლება"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"დიახ"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"გაუქმება"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ka/strings.xml b/packages/PackageInstaller/res/values-ka/strings.xml
new file mode 100644
index 0000000..997f95c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ka/strings.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"პაკეტის ინსტალერი"</string>
+    <string name="next" msgid="3057143178373252333">"შემდეგი"</string>
+    <string name="install" msgid="5896438203900042068">"დაყენება"</string>
+    <string name="done" msgid="3889387558374211719">"დასრულდა"</string>
+    <string name="cancel" msgid="8360346460165114585">"გაუქმება"</string>
+    <string name="installing" msgid="8613631001631998372">"მიმდინარეობს ინსტალაცია…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"მიმდინარეობს <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-ის ინსტალაცია…"</string>
+    <string name="install_done" msgid="3682715442154357097">"აპი დაყენებულია."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"გსურთ, ამ აპლიკაციის დაყენება? მას ექნება წვდომა:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"გსურთ ამ აპლიკაციის დაყენება? ის არ მოითხოვს რაიმე განსაკუთრებულ ნებართვას."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"გსურთ განახლების დაყენება ამ არსებული აპლიკაციისთვის? არსებული მონაცემები არ დაიკარგება. განახლებულ აპლიკაციას წვდომა ექნება:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"გსურთ განახლების დაყენება ამ ჩაშენებული აპლიკაციისთვის? არსებული მონაცემები არ დაიკარგება. განახლენულ აპლიკაციას წვდომა ექნება:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"გსურთ განახლების დაყენება ამ არსებული აპლიკაციისთვის? არსებული მონაცემები არ დაიკარგება. ის არ საჭიროებს რაიმე განსაკუთრებულ წვდომას:"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"გსურთ განახლების დაყენება ამ ჩაშენებული აპლიკაციისთვის? არსებული მონაცემები არ დაიკარგება. ის არ საჭიროებს რაიმე განსაკუთრებულ წვდომას:"</string>
+    <string name="install_failed" msgid="6579998651498970899">"აპი არ არის დაყენებული."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ამ პაკეტის ინსტალაცია დაბლოკილია."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"აპი ვერ დაინსტალირდა, რადგან პაკეტი კონფლიქტშია არსებულ პაკეტთან."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"აპი ვერ დაინსტალირდა, რადგან ის არ არის თავსებადი თქვენს ტაბლეტთან."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"ეს აპი არ არის თავსებადი თქვენს ტელევიზორთან."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"აპი ვერ დაინსტალირდა, რადგან ის არ არის თავსებადი თქვენს ტელეფონთან."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"აპი ვერ დაინსტალირდა, რადგან პაკეტი, სავარაუდოდ, არასწორია."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის დაყენება თქვენს ტაბლეტზე ვერ მოხერხდა."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> ვერ დაინსტალირდება თქვენს ტელევიზორში."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის დაყენება თქვენს ტელეფონზე ვერ მოხერხდა."</string>
+    <string name="launch" msgid="4826921505917605463">"გახსნა"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"უცნობი წყაროებიდან ჩამოტვირთული აპების ინსტალაცია თქვენი ადმინისტრატორის მიერ ნებადართული არ არის"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"ამ მომხმარებელს უცნობი აპების ინსტალაცია არ შეუძლია"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"ამ მომხმარებელს აპების დაინსტალირების უფლება არ აქვს"</string>
+    <string name="ok" msgid="3468756155452870475">"კარგი"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"აპების მართვა"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"სივრცე შეივსო"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის დაყენება შეუძლებელია. გაათავისუფლეთ მეხსიერება და სცადეთ ხელახლა."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"აპი ვერ მოიძებნა."</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"დაყენებული აპების სიაში ეს აპი ვერ მოიძებნა."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"დაუშვებელია"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"მიმდინარე მომხმარებელს არ აქვს დეინსტალაციის განხორციელების უფლება."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"შეცდომა"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"აპის დეინსტალაცია ვერ მოხერხდა."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"აპის დეინსტალაცია"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"განახლების დეინსტალაცია"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> არის შემდეგი აპის ნაწილი:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"გსურთ, ამ აპის დეინსტალაცია?"</string>
+    <!-- syntax error in translation for uninstall_application_text_all_users (5574704453233525222) org.xmlpull.v1.XmlPullParserException: expected: /string read: b (position:END_TAG </b>@1:122 in     <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"გსურთ ამ აპის დეინსტალაცია ყველა"</b>" მომხმარებილის "<b>"-თვის? აპლიკაცია და მისი მონაცემენბი წაიშლება ყველა"</b>" მომხმარებლის "<b>"-თვის მოწყობილობაზე."</string>
+)  -->
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"გსურთ <xliff:g id="USERNAME">%1$s</xliff:g> მომხმარებლისათვის ამ აპის დეინსტალაცია?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"გსურთ ამ აპის ქარხნული ვერსიით ჩანაცვლება? მონაცემები მთლიანად ამოიშლება."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"გსურთ ამ აპის ქარხნული ვერსიით ჩანაცვლება? მონაცემები მთლიანად ამოიშლება. ეს მოქმედება გავლენას იქონიებს ამ მოწყობილობის ყველა მომხმარებელზე, მათ შორის, სამსახურის პროფილებით მოსარგებლეებზეც."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"გაშვებული დეინსტალაციები"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"შეუსრულებელი დეინსტალაციები"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"დეინსტალაცია…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"მიმდინარეობს <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-ის დეინსტალაცია…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"დეინსტალაცია დასრულდა."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> დეინსტალირებულია"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"დეინსტალაცია წარუმატებელია."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-ის დეინსტალაცია ვერ მოხერხდა."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"მოწყობილობის ადმინისტრატორის აქტიური აპის დეინსტალაცია ვერ მოხერხდება"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g>-სთვის მოწყობილობის ადმინისტრატორის აქტიური აპის დეინსტალაცია ვერ მოხერხდება"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"ამ აპს მომხმარებლების/პროფილების ნაწილი იყენებს. სხვებისთვის ის დეინსტალირებულია."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"ეს აპი საჭიროა თქვენი პროფილისთვის. მისი დეინსტალაცია ვერ მოხერხდება."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"ეს აპი საჭიროა თქვენი მოწყ. ადმინისტრატორისათვის და დეინსტალაცია ვერ გამოვა."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"მოწყობილობის ადმინისტრატორების აპების მართვა"</string>
+    <string name="manage_users" msgid="3125018886835668847">"მომხმარებლების მართვა"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> -ის დეინსტალაცია ვერ მოხერხდა."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"პაკეტის ანალიზისას წარმოიშვა პრობლემა."</string>
+    <string name="newPerms" msgid="6039428254474104210">"ახალი"</string>
+    <string name="allPerms" msgid="1024385515840703981">"ყველა"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"კონფიდენციალურობა"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"მოწყობილობის წვდომა"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"ეს განახლება არ საჭიროებს ახალ ნებართვებს."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"უარყოფა"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"დამატებითი ინფორმაცია"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"მაინც უარყოფა"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>-დან"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"გსურთ, დაუშვათ, რომ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-მ შეასრულოს <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"გსურთ, ყოველთვის შესრულდეს <xliff:g id="ACTION">%2$s</xliff:g> &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ის&lt;/b&gt; მიერ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"მხოლოდ აპის გამოყენებისას"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ყოველთვის"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"უარყავი და აღარ მკითხო"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"გათიშულია <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"გათიშულია ყველა"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"არაფერია გათიშული"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"დაშვება"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"აპები"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"აპის უფლებები"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"აღარ მკითხოთ"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"ნებართვები არ არის"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"დამატებითი ნებართვები"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"აპის ინფორმაციის გახსნა"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"ეს აპი Android-ის ძველი ვერსიისთვის შეიქმნა. ნებართვის უარყოფამ შესაძლოა მისი არასათანადო ფუნქციონირება გამოიწვიოს."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"უცნობი ქმედების შესრულება"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"დაშვებულია <xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g> აპიდან"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"სისტემის ჩვენება"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"სისტემური პროცესების დამალვა"</string>
+    <string name="no_apps" msgid="1965493419005012569">"აპები არ არის"</string>
+    <string name="location_settings" msgid="1774875730854491297">"მდებარეობის პარამეტრები"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> არის მდებარეობის სერვისების მომწოდებელი ამ მოწყობილობისთვის. მდებარეობაზე წვდომის შეცვლა შესაძლებელია მდებარეობის პარამეტრებიდან."</string>
+    <string name="system_warning" msgid="7103819124542305179">"ამ ნებართვის უარყოფის შემთხვევაში, თქვენი მოწყობილობის ძირითადმა ფუნქციებმა შესაძლოა სათანადოდ აღარ იმუშაოს."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"შეესაბამება წესს"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"ფონზე წვდომა დებულებით გათიშულია"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"ფონზე წვდომა დებულებით დაშვებულია"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"წინა პლანზე წვდომა დებულებით დაშვებულია"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"იმართება ადმინისტრატორის მიერ"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ყოველთვის"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"მხოლოდ აპის გამოყენებისას"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"არასოდეს"</string>
+    <string name="loading" msgid="7811651799620593731">"იტვირთება..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"ყველა ნებართვა"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"აპის სხვა შესაძლებლობები"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"ნებართვის მოთხოვნა"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"ეკრანის გადაფარვა გამოვლინდა"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ამ ნებართვის პარამეტრის შესაცვლელად, ჯერ უნდა გამორთოთ ეკრანის გადაფარვა პარამეტრებიდან &gt; აპებიდან"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"პარამეტრების გახსნა"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"ინსტალაციის/დეინსტალაციის მოქმედებები არ არის მხარდაჭერილი Wear-ზე."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"აირჩიეთ, რაზე ჰქონდეს წვდომა &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; განახლდა. აირჩიეთ, რაზე ჰქონდეს წვდომა ამ აპს."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"გაუქმება"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"გაგრძელება"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"ახალი ნებართვები"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"ამჟამინდელი ნებართვები"</string>
+    <string name="message_staging" msgid="6151794817691100003">"მიმდინარეობს აპის შუალედური შენახვა…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"უცნობი"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"თქვენივე უსაფრთხოებისთვის, ტაბლეტს ამ წყაროდან უცნობი აპების ინსტალაციის უფლება არ აქვს."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"თქვენივე უსაფრთხოებისთვის, ტელევიზორს ამ წყაროდან უცნობი აპების ინსტალაციის უფლება არ აქვს."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"თქვენივე უსაფრთხოებისთვის, ტელეფონს ამ წყაროდან უცნობი აპების ინსტალაციის უფლება არ აქვს."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"თქვენი ტელეფონი და პირადი მონაცემები უცნობი აპების შემოტევების წინაშე მეტად დაუცველია. ამ აპის ინსტალაციის შემთხვევაში, თქვენ თანახმა ხართ, პასუხისმგებელი იყოთ მისი გამოყენების შედეგად ტელეფონისთვის მიყენებულ ზიანსა და მონაცემების დაკარგვაზე."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"თქვენი ტელეფონი და პირადი მონაცემები უცნობი აპების შემოტევების წინაშე მეტად დაუცველია. ამ აპის ინსტალაციის შემთხვევაში, თქვენ თანახმა ხართ, პასუხისმგებელი იყოთ მისი გამოყენების შედეგად ტაბლეტისთვის მიყენებულ ზიანსა და მონაცემების დაკარგვაზე."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"თქვენი ტელევიზორი და პირადი მონაცემები უცნობი აპების შემოტევების წინაშე მეტად დაუცველია. ამ აპის ინსტალაციის შემთხვევაში, თქვენ თანახმა ხართ, პასუხისმგებელი იყოთ მისი გამოყენების შედეგად ტელევიზორისთვის მიყენებულ ზიანსა და მონაცემების დაკარგვაზე."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"გაგრძელება"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"პარამეტრები"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear აპების ინსტალაცია/დეინსტალაცია"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-kk-television/strings.xml b/packages/PackageInstaller/res/values-kk-television/strings.xml
new file mode 100644
index 0000000..2d0ff43
--- /dev/null
+++ b/packages/PackageInstaller/res/values-kk-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Тыйым салу және қайтадан сұрамау"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Мұны кейінірек \"Параметрлер\" және \"Қолданбалар\" ішінен өзгертуге болады"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Жүйелік қолданбаларды көрсету"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Қолданба рұқсаттары"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Қолданба рұқсаттары"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> рұқсаттары"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Қосымша рұқсаттар"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> рұқсаттары"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-kk-watch/strings.xml b/packages/PackageInstaller/res/values-kk-watch/strings.xml
new file mode 100644
index 0000000..8996bcb
--- /dev/null
+++ b/packages/PackageInstaller/res/values-kk-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Тыйым салу, қайтадан сұрамау"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Жүйелік қолданбаларды көрсету"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Өзгерту мүмкін емес"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Иә"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Бас тарту"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-kk/strings.xml b/packages/PackageInstaller/res/values-kk/strings.xml
new file mode 100644
index 0000000..26892e1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-kk/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Бума орнатқыш"</string>
+    <string name="next" msgid="3057143178373252333">"Келесі"</string>
+    <string name="install" msgid="5896438203900042068">"Орнату"</string>
+    <string name="done" msgid="3889387558374211719">"Дайын"</string>
+    <string name="cancel" msgid="8360346460165114585">"Бас тарту"</string>
+    <string name="installing" msgid="8613631001631998372">"Орнатуда…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> орнатылуда…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Қолданба орнатылды."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Бұл қолданбаны орнатуды қалайсыз ба? Оның келесі нәрселерге қол жетімділігі болады:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Бұл қолданбаны орнатуды қалайсыз ба? Ол ерекше қол жетімділікті қажет етпейді."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Бұл қолданбаның жаңартылған нұсқасын орнатуды қалайсыз ба? Деректеріңіз жоғалмайды. Жаңартылған қолданбаның келесі нәрселерге қол жетімділігі болады:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Бұл орнатылған қолданбаның жаңартылған нұсқасын орнатуды қалайсыз ба? Деректеріңіз жоғалмайды. Жаңартылған қолданбаның келесі нәрселерге қол жетімділігі болады:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Бұл қолданбаның жаңартылған нұсқасын орнатуды қалайсыз ба? Деректеріңіз жоғалмайды. Ол ерекше қол жетімділікті қажет етпейді."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Бұл орнатылған қолданбаның жаңартылған нұсқасын орнатуды қалайсыз ба? Деректеріңіз жоғалмайды. Ол ерекше қол жетімділікті қажет етпейді."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Қолданба орнатылмады."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Буманы орнатуға тыйым салынды."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Пакет түрінде орнатылмаған қолданба мен бұрыннан бар пакеттің арасында қайшылық туындайды."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Қолданба түрінде орнатылмаған қолданба, планшетіңізбен үйлесімді емес."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Бұл қолданба теледидарыңызбен үйлесімді емес."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Қолданба түрінде орнатылмаған қолданба, телефоныңызбен үйлесімді емес."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Пакет түрінде орнатылмаған қолданба жарамсыз болып табылады."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын планшетіңізге орнату мүмкін емес"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> теледидарыңызда орнату мүмкін емес."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын телефоныңызға орнату мүмкін емес."</string>
+    <string name="launch" msgid="4826921505917605463">"Ашу"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Әкімші белгісіз көздерден алынған қолданбаларды орнатуға рұқсат етпейді"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Бұл пайдаланушы белгісіз қолданбаларды орната алмайды"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Бұл пайдаланушының қолданбаларды орнату рұқсаты жоқ"</string>
+    <string name="ok" msgid="3468756155452870475">"Жарайды"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Қолданбаларды басқару"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Орнында емес"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын орнату мүмкін болмады. Орын босатып, қайта әрекеттеніп көріңіз."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Қолданба табылмады"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Қолданба орнатылған қолданбалар тізімінен табылмады."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Рұқсат етілмеген"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Ағымдағы пайдаланушыға бұл жою әрекетіне рұқсат берілмеген."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Қате"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Қолданба жойылмады."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Қолданбаны алып тастау"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Жаңартуды алып тастау"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> келесі қолданбаның бөлігі:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Бұл қолданбаны алып тастауды қалайсыз ба?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Бұл қолданбаны "<b>"барлық"</b>" пайдаланушылар үшін алып тастауды қалайсыз ба? Қолданба және оның деректері құрылғыдағы "<b>"барлық"</b>" пайдаланушылардан алынады."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Пайдаланушы <xliff:g id="USERNAME">%1$s</xliff:g> үшін осы қолданбаны жою керек пе?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Осы қолданбаны зауыттық нұсқамен ауыстыру керек пе? Бүкіл деректер жойылады."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Осы қолданбаны зауыттық нұсқамен ауыстыру керек пе? Бүкіл деректер жойылады. Бұл осы құрылғының барлық пайдаланушыларына, соның ішінде жұмыс профильдері бар пайдаланушыларға әсер етеді."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Жұмыс істеп тұрған жою әрекеттері"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Сәтсіз жою әрекеттері"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Алып тастау орындалуда..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> жойылуда…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Алып тастау аяқталды."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> жойылды"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Алып тастау сәтсіздікке ұшырады."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> жою сәтсіз аяқталды."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Белсенді құрылғының әкімші қолданбасын жою мүмкін емес"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> үшін белсенді құрылғының әкімші қолданбасын жою мүмкін емес"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Бұл қолданба кейбір пайдаланушылар немесе профильдер үшін қажет және басқалар үшін жойылды"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Бұл қолданба профиліңіз үшін қажет және оны жою мүмкін емес."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Әкімші осы қолданбаны талап етеді және оны жою мүмкін емес."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Құрылғы әкімшісі қолданбаларын басқару"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Пайдаланушыларды басқару"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын алып тастау мүмкін емес."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Жинақты сараптау кезінде мәселе орын алды."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Жаңа"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Барлық"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Құпиялылық"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Құралға кіру"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Бұл қолданба жаңа рұқсаттарды қажет етпейді."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Тыйым салу"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Қосымша ақпарат"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Бәрібір рұқсат бермеу"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>/<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына <xliff:g id="ACTION">%2$s</xliff:g> рұқсатын беру керек пе?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасы үшін <xliff:g id="ACTION">%2$s</xliff:g> әрекетіне әрқашан рұқсат етілсін бе?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Қолданба пайдаланылғанда ғана"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Әрқашан"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Тыйым салынсын және қайта сұралмасын"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> рұқсат өшірілді"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"барлық рұқсаттар өшірілді"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"рұқсаттардың ешқайсысы өшірілмеді"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Рұқсат беру"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Қолданбалар"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Қолданба рұқсаттары"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Қайта сұралмасын"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Рұқсат жоқ"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Қосымша рұқсаттар"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Қолданба ақпаратын ашу"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Бұл қолданба Android жүйесінің ескі нұсқасына арналған. Рұқсаттан бас тартсаңыз, бұдан былай тиісінше жұмыс істемеуі мүмкін."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"белгісіз әрекетті орындау"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g> қолданбаға рұқсат етілген"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Жүйені көрсету"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Жүйені жасыру"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Қолданбалар жоқ"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Орынды анықтау параметрлері"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> — осы құрылғыға орынды анықтау қызметтерін көрсететін қолданба. Орынды пайдалану мүмкіндігін орынды анықтау параметрлерінде өзгертуге болады."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Бұл рұқсатты бермесеңіз, құрылғының негізгі функциялары енді көзделгендей жұмыс істемеуі мүмкін."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Саясат арқылы қолданылған"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Саясат бойынша фондық режимде кіруге рұқсат етілмеген"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Саясат бойынша фондық режимде кіруге рұқсат етілген"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Саясат бойынша экрандық режимде кіруге рұқсат етілген"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Әкімші басқарады"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Әрқашан"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Қолданба пайдаланылғанда ғана"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Ешқашан"</string>
+    <string name="loading" msgid="7811651799620593731">"Жүктелуде…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Барлық рұқсаттар"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Басқа қолданба мүмкіндіктері"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Рұқсат сұрау"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Экранды қабаттастыру анықталды"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Бұл рұқсат параметрін өзгерту үшін алдымен «Параметрлер» &gt; «Қолданбалар» тармағында экранды қабаттастыруды өшіру керек"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Параметрлерді ашу"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear құрылғысында \"Орнату\"/\"Жою\" әрекеттері қолданылмайды."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы қайда кіре алатынын таңдаңыз"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы жаңартылды. Бұл қолданбаның қайда кіре алатынын таңдаңыз."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Бас тарту"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Жалғастыру"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Жаңа рұқсаттар"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Ағымдағы рұқсаттар"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Қолданба реттелуде…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Белгісіз"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Қауіпсіздікті сақтау үшін планшетке бұл дереккөзден белгісіз қолданбаларды орнатуға рұқсат берілмейді."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Қауіпсіздікті сақтау үшін теледидарға бұл дереккөзден белгісіз қолданбаларды орнатуға рұқсат берілмейді."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Қауіпсіздікті сақтау үшін телефонға бұл дереккөзден белгісіз қолданбаларды орнатуға рұқсат берілмейді."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Телефон және жеке деректер белгісіз қолданбалардың шабуылына ұшырауы мүмкін. Бұл қолданбаны орнату арқылы оны пайдалану нәтижесіндегі телефонға келетін залалға немесе деректердің жоғалуына өзіңіз ғана жауапты болатыныңызға келісесіз."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Планшет және жеке деректер белгісіз қолданбалардың шабуылына ұшырауы мүмкін. Бұл қолданбаны орнату арқылы оны пайдалану нәтижесіндегі планшетке келетін залалға немесе деректердің жоғалуына өзіңіз ғана жауапты болатыныңызға келісесіз."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Теледидар және жеке деректер белгісіз қолданбалардың шабуылына ұшырауы мүмкін. Бұл қолданбаны орнату арқылы оны пайдалану нәтижесіндегі теледидарға келетін қандай да бір залалға немесе деректердің жоғалуына өзіңіз ғана жауапты болатыныңызға келісесіз."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Жалғастыру"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Параметрлер"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear қолданбасын орнату/жою"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-km-television/strings.xml b/packages/PackageInstaller/res/values-km-television/strings.xml
new file mode 100644
index 0000000..f02744d
--- /dev/null
+++ b/packages/PackageInstaller/res/values-km-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"បដិសេធ ហើយកុំសួរម្តងទៀត"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"អ្នកអាចប្តូរវាពេលក្រោយនៅក្នុងការកំណត់ &gt; កម្មវិធី"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"បង្ហាញកម្មវិធីប្រព័ន្ធ"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"សិទ្ធិអនុញ្ញាតកម្មវិធី"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"សិទ្ធិអនុញ្ញាតកម្មវិធី"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"សិទ្ធិអនុញ្ញាត <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"ការអនុញ្ញាតបន្ថែម"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"សិទ្ធិអនុញ្ញាត <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-km-watch/strings.xml b/packages/PackageInstaller/res/values-km-watch/strings.xml
new file mode 100644
index 0000000..c5f49c5
--- /dev/null
+++ b/packages/PackageInstaller/res/values-km-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"បដិសេធ សូមកុំសួរម្តងទៀត"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"បង្ហាញកម្មវិធីប្រព័ន្ធ"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"មិនអាចប្តូរបានទេ"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"បាទ/ចាស"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"បោះបង់"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-km/strings.xml b/packages/PackageInstaller/res/values-km/strings.xml
new file mode 100644
index 0000000..693ea32
--- /dev/null
+++ b/packages/PackageInstaller/res/values-km/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"កម្មវិធី​ដំឡើង​កញ្ចប់"</string>
+    <string name="next" msgid="3057143178373252333">"បន្ទាប់​"</string>
+    <string name="install" msgid="5896438203900042068">"ដំឡើង"</string>
+    <string name="done" msgid="3889387558374211719">"រួចរាល់"</string>
+    <string name="cancel" msgid="8360346460165114585">"បោះ​បង់​"</string>
+    <string name="installing" msgid="8613631001631998372">"កំពុង​ដំឡើង..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"កំពុង​ដំឡើង <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"បាន​ដំឡើង​កម្មវិធី។"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"តើ​អ្នក​ចង់​ដំឡើង​កម្មវិធី​នេះ? វា​នឹង​មាន​សិទ្ធិ​ចូល៖"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"តើ​អ្នក​ចង់​ដំឡើង​កម្មវិធី​នេះ? វា​មិន​ទាមទារ​សិទ្ធិ​ចូល​ពិសេស​ទេ។"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"តើ​អ្នក​ចង់​ដំឡើង​បច្ចុប្បន្នភាព​កម្មវិធី​ដែល​មាន​ស្រាប់​នេះ? ទិន្នន័យ​ដែល​មាន​ស្រាប់​របស់​អ្នក​នឹង​មិន​បាត់បង់​ទេ។ កម្មវិធី​បាន​ធ្វើ​បច្ចុប្បន្នភាព​នឹង​ចូល​ដំណើរការ​ទៅ៖"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"តើ​អ្នក​ចង់​ដំឡើង​បច្ចុប្បន្នភាព​កម្មវិធី​ដែល​ជាប់​ជា​មួយនេះ? ទិន្នន័យ​ដែល​មាន​ស្រាប់​របស់​អ្នក​នឹង​មិនបាត់បង់ទេ។ កម្មវិធី​បាន​ធ្វើ​បច្ចុប្បន្នភាពហើយ​នឹង​មានសិទ្ធិចូល​៖"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"តើ​អ្នក​ចង់​ដំឡើង​បច្ចុប្បន្នភាព​កម្មវិធី​ដែល​មាន​ស្រាប់​នេះ? ​ទិន្នន័យ​ដែល​មាន​ស្រាប់​របស់​អ្នក​នឹង​មិន​បាត់បង់​ទេ។ វា​មិន​ទាមទារ​ការ​ចូល​ដំណើរការ​ពិសេស​ណាមួយ​ទេ។"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"តើ​អ្នក​ចង់​ដំឡើង​បច្ចុប្បន្នភាព​កម្មវិធី​ដែល​ជាប់​ជា​មួយ? ​ទិន្នន័យ​ដែល​មាន​ស្រាប់​របស់​អ្នក​នឹង​មិន​បាត់បង់​ទេ។ វា​មិន​ទាមទារ​ការ​ចូល​ដំណើរការ​ពិសេស​ណាមួយ​ទេ។"</string>
+    <string name="install_failed" msgid="6579998651498970899">"មិន​បាន​ដំឡើង​កម្មវិធី។"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"កញ្ចប់នេះត្រូវបានរារាំងមិនឲ្យដំឡើង"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"កម្មវិធីមិនបានដំឡើងទេ ដោយសារកញ្ចប់កម្មវិធីមិនត្រូវគ្នាជាមួយកញ្ចប់ដែលមានស្រាប់។"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"កម្មវិធីមិនបានដំឡើងទេ ដោយសារកម្មវិធីមិនត្រូវគ្នាជាមួយថេប្លេតរបស់អ្នក។"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"កម្មវិធីនេះមិនត្រូវគ្នាជាមួយទូរទស្សន៍របស់អ្នកទេ"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"កម្មវិធីមិនបានដំឡើងទេ ដោយសារកម្មវិធីមិនត្រូវគ្នាជាមួយទូរសព្ទរបស់អ្នក។"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"កម្មវិធីមិនបានដំឡើងទេ ដោយសារកញ្ចប់គ្មានសុពលភាព។"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"មិន​អាច​ដំឡើង <xliff:g id="APP_NAME">%1$s</xliff:g> ក្នុង​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក។"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> មិនអាចដំឡើងនៅលើទូរទស្សន៍របស់អ្នកទេ។"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"មិន​អាច​ដំឡើង <xliff:g id="APP_NAME">%1$s</xliff:g> ក្នុង​ទូរស័ព្ទ​របស់​អ្នក។"</string>
+    <string name="launch" msgid="4826921505917605463">"បើក"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"អ្នក​គ្រប់គ្រង​របស់​អ្នក​មិន​អនុញ្ញាត​ឲ្យ​ដំឡើង​កម្មវិធី​ដែល​បាន​មក​ពី​ប្រភព​ដែលមិន​ស្គាល់ទេ"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"កម្មវិធី​ដែល​មិនស្គាល់​មិនអាច​ដំឡើង​ដោយ​អ្នកប្រើប្រាស់​នេះ​បាន​ទេ"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"អ្នក​ប្រើ​ប្រាស់នេះ​មិនត្រូវបាន​អនុញ្ញាត​ឲ្យ​ដំឡើងកម្មវិធីទេ"</string>
+    <string name="ok" msgid="3468756155452870475">"យល់​ព្រម​"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"គ្រប់គ្រង​កម្មវិធី"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"អស់​ទំហំ"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"មិន​អាច​ដំឡើង <xliff:g id="APP_NAME">%1$s</xliff:g> ។ លុប​ឯកសារ​ខ្លះ ហើយ​ព្យាយាម​ម្ដង​ទៀត។"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"រក​មិន​ឃើញ​កម្មវិធី"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"រក​មិន​ឃើញ​កម្មវិធី​ក្នុង​បញ្ជី​កម្មវិធី​បាន​ដំឡើង។"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"មិន​បាន​អនុញ្ញាត"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"អ្នកប្រើបច្ចុប្បន្នមិនមានការអនុញ្ញាតឱ្យ​ធ្វើការលុបនេះទេ។"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"បញ្ហា"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"មិនអាចលុបកម្មវិធីនេះបានទេ។"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"លុប​កម្មវិធី"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"លុប​បច្ចុប្បន្នភាព"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>​ ​ជា​ផ្នែក​មួយ​នៃ​កម្មវិធី​ដូច​ខាង​ក្រោម​នេះ​៖"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"តើ​អ្នក​ចង់​លុប​កម្មវិធី​នេះ​ឬ?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"តើ​អ្នក​ចង់​លុប​កម្មវិធី​នេះ​សម្រាប់​អ្នកប្រើ "<b>"ទាំងអស់"</b>"? កម្មវិធី និង​ទិន្នន័យ​របស់​វា​នឹង​ត្រូវ​បាន​លុប​ចេញ​ពី​អ្នកប្រើ "<b>"ទាំងអស់"</b>" ក្នុង​ឧបករណ៍​នេះ។"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"តើ​អ្នក​ចង់​លុប​កម្មវិធី​នេះ​សម្រាប់​អ្នកប្រើ <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ជំនួសកម្មវិធីនេះដោយកំណែរោងចក្រឬ? ទិន្នន័យទាំងអស់នឹងត្រូវបានលុបចេញ។"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ជំនួយកម្មវិធីនេះដោយកំណែរោងចក្រឬ? ទិន្នន័យទាំងអស់នឹងត្រូវបានលុបចេញ។ វាប៉ះពាល់ដល់អ្នកប្រើឧបករណ៍នេះទាំងអស់ ដោយរាប់បញ្ចូលទាំងអ្នកប្រើដែលមានប្រវត្តិរូបការងារផងដែរ។"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"កំពុង​ដំណើរការ​ការលុប"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"មិន​អាច​ធ្វើការលុប​បានទេ"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"កំពុង​លុប..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"កំពុងលុប <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"បាន​បញ្ចប់​ការ​លុប។"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"បានលុប <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"ការ​លុប​បរាជ័យ។"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"មិនអាចលុប <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> បាន។"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"មិនអាច​លុប​កម្មវិធី​អ្នកគ្រប់គ្រង​ឧបករណ៍​ដែល​បាន​ដំណើរការ​បានទេ"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"មិនអាច​លុប​កម្មវិធី​អ្នកគ្រប់គ្រង​ឧបករណ៍​សម្រាប់ <xliff:g id="USERNAME">%1$s</xliff:g> ដែល​បាន​ដំណើរការ​បាន​ទេ"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"កម្មវិធីនេះតម្រូវឲ្យមានសម្រាប់អ្នកប្រើ ឬប្រវត្តិរូបមួយចំនួន និងត្រូវបានលុបសម្រាប់អ្នកប្រើផ្សេងទៀត"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"កម្មវិធីនេះចាំបាច់សម្រាប់ប្រវតិ្តការងាររបស់អ្នក ហើយវាមិនអាចលុបបានទេ។"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"កម្មវិធីនេះត្រូវបានទាមទារដោយអ្នកគ្រប់គ្រងឧបករណ៍របស់អ្នក ហើយមិនអាចលុប​ចេញបាន​ទេ។"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"គ្រប់គ្រង​កម្មវិធី​អ្នកគ្រប់គ្រង​ឧបករណ៍"</string>
+    <string name="manage_users" msgid="3125018886835668847">"គ្រប់គ្រងអ្នកប្រើ"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"មិន​អាច​លុប <xliff:g id="APP_NAME">%1$s</xliff:g> ។"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"មាន​បញ្ហា​ក្នុង​ការ​ញែក​​កញ្ចប់។"</string>
+    <string name="newPerms" msgid="6039428254474104210">"ថ្មី"</string>
+    <string name="allPerms" msgid="1024385515840703981">"ទាំងអស់"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"ភាព​​ឯកជន"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"ការ​ចូល​ដំណើរការ​ឧបករណ៍"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"បច្ចុប្បន្នភាព​នេះ​មិន​ទាមទារ​សិទ្ធិ​ថ្មី​ទេ។"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"បដិសេធ"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"ព័ត៌មានបន្ថែម"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"បដិសេធទោះយ៉ាងណាក៏ដោយ"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> នៃ <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"អនុញ្ញាតឲ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g> ជានិច្ចមែនទេ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"ខណៈពេលប្រើ​កម្មវិធីតែប៉ុណ្ណោះ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ជានិច្ច"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"បដិសេធ ហើយកុំ​សួរម្តងទៀត"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"បានបិទ <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"បានបិទទាំងអស់"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"មិនបានបិទអ្វីទាំងអស់"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"អនុញ្ញាត"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"កម្មវិធី"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"ការអនុញ្ញាតកម្មវិធី"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"កុំសួរទៀត"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"គ្មានសិទ្ធិអនុញ្ញាត"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"ការអនុញ្ញាតបន្ថែម"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"បើក​ព័ត៌មាន​កម្មវិធី"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"កម្មវិធីនេះត្រូវបានរចនាឡើងសម្រាប់កំណែចាស់របស់ Android។ ការបដិសេធសិទ្ធិអនុញ្ញាតអាចបណ្តាលឲ្យវាបំពេញមុខងារមិនដូចអ្វីដែលគេរំពឹងទុកតទៅទៀតទេ។"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ប្រតិបត្តិការសកម្មភាពមិនស្គាល់"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"បានអនុញ្ញាតកម្មវិធី <xliff:g id="COUNT_0">%1$d</xliff:g> នៃ <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"បង្ហាញប្រព័ន្ធ"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"លាក់ប្រព័ន្ធ"</string>
+    <string name="no_apps" msgid="1965493419005012569">"គ្មានកម្មវិធី"</string>
+    <string name="location_settings" msgid="1774875730854491297">"ការកំណត់ទីតាំង"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាអ្នកផ្តល់សេវាកម្មទីតាំងសម្រាប់ឧបករណ៍នេះ។ ការចូលដំណើរការទីតាំងអាចកែសម្រួលបានចេញពីការកំណត់ទីតាំង។"</string>
+    <string name="system_warning" msgid="7103819124542305179">"ប្រសិនបើអ្នកបដិសេធសិទ្ធិអនុញ្ញាតនេះ លក្ខណៈពិសេសគោលនៃឧបករណ៍របស់អ្នកអាចមិនដំណើរការដូចដែលអ្នកចង់បានតទៅទៀតទេ។"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"អនុវត្តតាមគោលការណ៍"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"ការចូលប្រើផ្ទៃខាងក្រោយ​ត្រូវបានបិទដោយគោលការណ៍"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"ការចូលប្រើផ្ទៃខាងក្រោយ​ត្រូវបានបើកដោយគោលការណ៍"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"ការចូលប្រើផ្ទៃខាងមុខ​ត្រូវបានបើកដោយគោលការណ៍"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"គ្រប់គ្រងដោយអ្នកគ្រប់គ្រង"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ជានិច្ច"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"ខណៈពេលប្រើ​កម្មវិធីតែប៉ុណ្ណោះ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"កុំឱ្យសោះ"</string>
+    <string name="loading" msgid="7811651799620593731">"កំពុងដំណើរការ..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"សិទ្ធិអនុញ្ញាតទាំងអស់"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"សមត្ថភាពកម្មវិធីផ្សេងទៀត"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"សំណើសុំសិទ្ធិអនុញ្ញាត"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"បានរកឃើញអេក្រង់ត្រួតគ្នា"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ដើម្បីប្តូរការកំណត់សិទ្ធិអនុញ្ញាតនេះ ជាដំបូងអ្នកត្រូវបិទអេក្រង់ត្រួតគ្នានៅក្នុង ការកំណត់ &gt; កម្មវិធី"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"បើកការកំណត់"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"សកម្មភាពដំឡើង/លុបការដំឡើងមិនគាំទ្រនៅលើ Wear ទេ"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"ជ្រើសរើសអ្វីដែលត្រូវអនុញ្ញាតឲ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលដំណើរការ"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ត្រូវបានអាប់ដេត។ ជ្រើសរើសអ្វីដែលត្រូវអនុញ្ញាតឲ្យកម្មវិធីនេះចូលដំណើរការ។"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"បោះបង់"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"បន្ត"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"សិទ្ធិអនុញ្ញាតថ្មី"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"សិទ្ធិអនុញ្ញាតបច្ចុប្បន្ន"</string>
+    <string name="message_staging" msgid="6151794817691100003">"កំពុងសាកល្បងកម្មវិធី…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"មិនស្គាល់"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"ដើម្បីការពារសុវតិ្ថភាពរបស់អ្នក ថេប្លេតរបស់អ្នកមិនត្រូវបានអនុញ្ញាតឲ្យដំឡើងកម្មវិធីដែលមិនស្គាល់ពីប្រភពនេះទេ។"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"ដើម្បីការពារសុវតិ្ថភាពរបស់អ្នក ទូរទស្សន៍របស់អ្នកមិនត្រូវបានអនុញ្ញាតឲ្យដំឡើងកម្មវិធីដែលមិនស្គាល់ពីប្រភពនេះទេ។"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"ដើម្បីការពារសុវតិ្ថភាពរបស់អ្នក ទូរសព្ទរបស់អ្នកមិនត្រូវបានអនុញ្ញាតឲ្យដំឡើងកម្មវិធីដែលមិនស្គាល់ពីប្រភពនេះទេ។"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"ទូរសព្ទ និងទិន្នន័យផ្ទាល់ខ្លួនរបស់អ្នកងាយនឹងរងគ្រោះពីការវាយប្រហារពីកម្មវិធីដែលមិនស្គាល់។ ប្រសិនបើដំឡើងកម្មវិធីនេះ មានន័យថាអ្នកទទួលខុសត្រូវលើការខូចខាតណាមួយចំពោះទូរសព្ទ ឬការបាត់បង់ទិន្នន័យរបស់អ្នក ដែលអាចបណ្តាលមកពីការប្រើប្រាស់កម្មវិធីនោះ។"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"ថេប្លេត និងទិន្នន័យផ្ទាល់ខ្លួនរបស់អ្នកងាយនឹងរងគ្រោះពីការវាយប្រហារពីកម្មវិធីដែលមិនស្គាល់។ ប្រសិនបើដំឡើងកម្មវិធីនេះ មានន័យថាអ្នកទទួលខុសត្រូវលើការខូចខាតណាមួយចំពោះថេប្លេត ឬការបាត់បង់ទិន្នន័យរបស់អ្នក ដែលអាចបណ្តាលមកពីការប្រើប្រាស់កម្មវិធីនោះ។"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"ទូរទស្សន៍ និងទិន្នន័យផ្ទាល់ខ្លួនរបស់អ្នកងាយនឹងរងគ្រោះពីការវាយប្រហារពីកម្មវិធីដែលមិនស្គាល់។ ប្រសិនបើដំឡើងកម្មវិធីនេះ មានន័យថាអ្នកទទួលខុសត្រូវលើការខូចខាតណាមួយចំពោះទូរទស្សន៍ ឬការបាត់បង់ទិន្នន័យរបស់អ្នក ដែលអាចបណ្តាលមកពីការប្រើប្រាស់កម្មវិធីនោះ។"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"បន្ត"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ការ​កំណត់"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"ការដំឡើង/ការលុបកម្មវិធីឧបករណ៍​ពាក់​"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-kn-television/strings.xml b/packages/PackageInstaller/res/values-kn-television/strings.xml
new file mode 100644
index 0000000..2af5a4b
--- /dev/null
+++ b/packages/PackageInstaller/res/values-kn-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"ನಿರಾಕರಿಸಿ ಹಾಗೂ ಮತ್ತೊಮ್ಮೆ ಕೇಳಬೇಡ"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"ನೀವು ಇದನ್ನು ನಂತರದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್‍‍ಗಳು &gt; ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"ಸಿಸ್ಟಂ ಅಪ್ಲಿಕೇಶನ್‌‌ಗಳನ್ನು ತೋರಿಸು"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"ಅಪ್ಲಿಕೇಶನ್ ಅನುಮತಿಗಳು"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"ಅಪ್ಲಿಕೇಶನ್ ಅನುಮತಿಗಳು"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> ಅನುಮತಿಗಳು"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"ಹೆಚ್ಚುವರಿ ಅನುಮತಿಗಳು"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> ಅನುಮತಿಗಳು"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-kn-watch/strings.xml b/packages/PackageInstaller/res/values-kn-watch/strings.xml
new file mode 100644
index 0000000..1a9a993
--- /dev/null
+++ b/packages/PackageInstaller/res/values-kn-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ನಿರಾಕರಿಸಿ, ಮತ್ತೆ ಕೇಳಬೇಡಿ"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"ಸಿಸ್ಟಂ ಅಪ್ಲಿಕೇಶನ್‌‌ಗಳನ್ನು ತೋರಿಸು"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"ಹೌದು"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"ರದ್ದುಮಾಡಿ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-kn/strings.xml b/packages/PackageInstaller/res/values-kn/strings.xml
new file mode 100644
index 0000000..f42035c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-kn/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"ಪ್ಯಾಕೇಜ್ ಸ್ಥಾಪಕ"</string>
+    <string name="next" msgid="3057143178373252333">"ಮುಂದೆ"</string>
+    <string name="install" msgid="5896438203900042068">"ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
+    <string name="done" msgid="3889387558374211719">"ಮುಗಿದಿದೆ"</string>
+    <string name="cancel" msgid="8360346460165114585">"ರದ್ದುಮಾಡಿ"</string>
+    <string name="installing" msgid="8613631001631998372">"ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="install_done" msgid="3682715442154357097">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪಿಸಲಾಗಿದೆ."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪಿಸಲು ಬಯಸುವಿರಾ? ಇದು ಇಲ್ಲಿಗೆ ಪ್ರವೇಶ ಪಡೆದುಕೊಳ್ಳುತ್ತದೆ:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪಿಸಲು ಬಯಸುವಿರಾ? ಇದಕ್ಕೆ ಯಾವುದೇ ವಿಶೇಷ ಪ್ರವೇಶದ ಅಗತ್ಯವಿಲ್ಲ."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"ನೀವು ಈ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಅಪ್ಲಿಕೇಶನ್‍ನ ಅಪ್‌ಡೇಟ್‌‌ ಆದ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪಿಸಲು ಬಯಸುವಿರಾ? ಈಗಿರುವ ನಿಮ್ಮ ಡೇಟಾ ಕಳೆದು ಹೋಗುವುದಿಲ್ಲ. ಅಪ್‌ಡೇಟ್‌‌ ಆದ ಅಪ್ಲಿಕೇಶನ್ ಇಲ್ಲಿಗೆ ಪ್ರವೇಶ ಪಡೆದುಕೊಳ್ಳುತ್ತದೆ:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"ನೀವು ಈ ಬಿಲ್ಟ್-ಇನ್-ಅಪ್ಲಿಕೇಶನ್‌ನ ಅಪ್‌ಡೇಟ್‌‌ ಆದ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪಿಸಿಕೊಳ್ಳಲು ಬಯಸುವಿರಾ? ಈಗಿರುವ ನಿಮ್ಮ ಡೇಟಾ ಕಳೆದು ಹೋಗುವುದಿಲ್ಲ. ಅಪ್‌ಡೇಟ್‌‌ ಆದ ಅಪ್ಲಿಕೇಶನ್ ಇಲ್ಲಿಗೆ ಪ್ರವೇಶ ಪಡೆದುಕೊಳ್ಳುತ್ತದೆ:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"ನೀವು ಈ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಅಪ್ಲಿಕೇಶನ್‍ನ ಅಪ್‌ಡೇಟ್‌‌ ಆದ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪಿಸಲು ಬಯಸುವಿರಾ? ಈಗಿರುವ ನಿಮ್ಮ ಡೇಟಾ ಕಳೆದು ಹೋಗುವುದಿಲ್ಲ. ಇದಕ್ಕೆ ಯಾವುದೇ ವಿಶೇಷ ಪ್ರವೇಶದ ಅಗತ್ಯವಿಲ್ಲ."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"ನೀವು ಈ ಬಿಲ್ಟ್-ಇನ್-ಅಪ್ಲಿಕೇಶನ್‌ನ ಅಪ್‌ಡೇಟ್‌‌ ಆದ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪಿಸಿಕೊಳ್ಳಲು ಬಯಸುವಿರಾ? ಈಗಿರುವ ನಿಮ್ಮ ಡೇಟಾ ಕಳೆದು ಹೋಗುವುದಿಲ್ಲ. ಇದಕ್ಕೆ ಯಾವುದೇ ವಿಶೇಷ ಪ್ರವೇಶದ ಅಗತ್ಯವಿಲ್ಲ."</string>
+    <string name="install_failed" msgid="6579998651498970899">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ಸ್ಥಾಪಿಸುವಿಕೆಯಿಂದ ಪ್ಯಾಕೇಜ್‌ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"ಪ್ಯಾಕೇಜ್‌ನಂತೆ ಸ್ಥಾಪಿತವಾಗದಿರುವ ಅಪ್ಲಿಕೇಶನ್ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಪ್ಯಾಕೇಜ್ ಜೊತೆಗೆ ಸಂಘರ್ಷವಾಗುತ್ತದೆ."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"ಅಪ್ಲಿಕೇಶನ್‌ನಂತೆ ಸ್ಥಾಪಿತವಾಗದಿರುವ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಜೊತೆಗೆ ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಟಿವಿ ಜೊತೆ ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"ಅಪ್ಲಿಕೇಶನ್‌ನಂತೆ ಸ್ಥಾಪಿತವಾಗದಿರುವ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಫೋನ್ ಜೊತೆಗೆ ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"ಪ್ಯಾಕೇಜ್‌ನಂತೆ ಸ್ಥಾಪಿತವಾಗದಿರುವ ಅಪ್ಲಿಕೇಶನ್ ಅಮಾನ್ಯವಾಗಿರುವಂತೆ ತೋರುತ್ತದೆ."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು ನಿಮ್ಮ ಟಿವಿಗೆ ಸ್ಥಾಪಿಸಲಾಗುವುದಿಲ್ಲ."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string>
+    <string name="launch" msgid="4826921505917605463">"ತೆರೆ"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಅಪರಿಚಿತ ಮೂಲಗಳ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಸ್ಥಾಪನೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"ಈ ಬಳಕೆದಾರರು ಅಪರಿಚಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಲು ಈ ಬಳಕೆದಾರರನ್ನು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
+    <string name="ok" msgid="3468756155452870475">"ಸರಿ"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"ಖಾಲಿ ಇಲ್ಲ"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು ಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಕೊಂಚ ಸ್ಥಳವನ್ನು ಖಾಲಿ ಮಾಡಿ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"ಅಪ್ಲಿಕೇಶನ್ ಕಂಡುಬಂದಿಲ್ಲ"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ಸ್ಥಾಪಿಸಲಾಗಿರುವ ಅಪ್ಲಿಕೇಶನ್‍ಗಳ ಪಟ್ಟಿಯಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕಂಡುಬಂದಿಲ್ಲ."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"ಈ ಅಸ್ಥಾಪಿಸುವಿಕೆಯನ್ನು ಪ್ರಸ್ತುತ ಬಳಕೆದಾರರಿಗೆ ನಿರ್ವಹಿಸಲು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"ದೋಷ"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"ಅಪ್ಲಿಕೇಶನ್ ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"ಅಪ್ಲಿಕೇಶನ್ ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"ನವೀಕರಣವನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ಎಂಬುದು ಕೆಳಗಿನ ಅಪ್ಲಿಕೇಶನ್‌ನ ಭಾಗವಾಗಿದೆ:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅಸ್ಥಾಪಿಸಲು ಬಯಸುವಿರಾ?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"ನೀವು "<b>"ಎಲ್ಲಾ"</b>" ಬಳಕೆದಾರರಿಗೂ ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅಸ್ಥಾಪಿಸಲು ಬಯಸುವಿರಾ? ಸಾಧನದಲ್ಲಿನ "<b>"ಎಲ್ಲಾ"</b>" ಬಳಕೆದಾರರಿಂದ ಅಪ್ಲಿಕೇಶನ್ ಮತ್ತು ಅದರ ಡೇಟಾವನ್ನು ತೆಗೆದುಹಾಕಲಾಗುವುದು."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"<xliff:g id="USERNAME">%1$s</xliff:g> ಬಳಕೆದಾರರಿಗೆ ಈ ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಅಸ್ಥಾಪಿಸಲು ನೀವು ಬಯಸುವಿರಾ?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಬದಲಿಗೆ ಫ್ಯಾಕ್ಟರಿ ಆವೃತ್ತಿಯನ್ನು ಬದಲಾಯಿಸುವುದೇ? ಎಲ್ಲಾ ಡೇಟಾ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಬದಲಿಗೆ ಫ್ಯಾಕ್ಟರಿ ಆವೃತ್ತಿಯನ್ನು ಬದಲಾಯಿಸುವುದೇ? ಎಲ್ಲಾ ಡೇಟಾ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ. ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌ಗಳನ್ನು ಹೊಂದಿರುವವುಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ಈ ಸಾಧನದ ಎಲ್ಲಾ ಬಳಕೆದಾರರಿಗೆ ಇದು ಪರಿಣಾಮ ಬೀರುತ್ತದೆ."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"ಚಾಲನೆಯಲ್ಲಿರುವ ಅಸ್ಥಾಪನೆಗಳು"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"ವಿಫಲಗೊಂಡ ಅಸ್ಥಾಪನೆಗಳು"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"ಅಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಅಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಪೂರ್ಣಗೊಂಡಿದೆ."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಅಸ್ಥಾಪಿಸಲಾಗಿದೆ"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಅಸ್ಥಾಪಿಸುವಿಕೆ ಯಶಸ್ವಿಯಾಗಲಿಲ್ಲ."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"ಸಕ್ರಿಯ ಸಾಧನ ನಿರ್ವಹಣೆ ಅಪ್ಲಿಕೇಶನ್ ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> ಗಾಗಿ ಸಕ್ರಿಯ ಸಾಧನ ನಿರ್ವಹಣೆ ಅಪ್ಲಿಕೇಶನ್ ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"ಕೆಲವು ಬಳಕೆದಾರರು ಅಥವಾ ಪ್ರೊಫೈಲ್‌ಗಳಿಗೆ ಈ ಅಪ್ಲಿಕೇಶನ್ ಅಗತ್ಯವಿರುತ್ತದೆ ಮತ್ತು ಇತರರಿಗೆ ಅಸ್ಥಾಪಿಸಲಾಗಿದೆ"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"ಈ ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ನಿಮ್ಮ ಪ್ರೊಫೈಲ್‌‌ನ ಅಗತ್ಯವಿದೆ ಮತ್ತು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸಾಧನ ನಿರ್ವಾಹಕರಿಗೆ ಅಗತ್ಯವಿದೆ ಮತ್ತು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"ಸಾಧನದ ನಿರ್ವಹಣೆ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸಿ"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"ಪ್ಯಾಕೇಜ್ ಪಾರ್ಸ್ ಮಾಡುವಲ್ಲಿ ಸಮಸ್ಯೆ ಕಂಡುಬಂದಿದೆ."</string>
+    <string name="newPerms" msgid="6039428254474104210">"ಹೊಸತು"</string>
+    <string name="allPerms" msgid="1024385515840703981">"ಎಲ್ಲಾ"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"ಗೌಪ್ಯತೆ"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"ಸಾಧನ ಪ್ರವೇಶ"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"ಈ ನವೀಕರಣಕ್ಕೆ ಯಾವುದೇ ಹೊಸ ಅನುಮತಿಗಳ ಅಗತ್ಯವಿಲ್ಲ."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"ನಿರಾಕರಿಸಿ"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"ಇನ್ನಷ್ಟು ಮಾಹಿತಿ"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"ಹೇಗಾದರೂ ನಿರಾಕರಿಸಿ"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> ರಲ್ಲಿ <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"<xliff:g id="ACTION">%2$s</xliff:g> <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to <xliff:g id="ACTION">%2$s</xliff:g> ಅನ್ನು ಯಾವಾಗಲೂ ಅನುಮತಿಸುವುದೇ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"ಅಪ್ಲಿಕೇಶನ್ ಬಳಸುವಾಗ ಮಾತ್ರ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ಯಾವಾಗಲೂ"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"ನಿರಾಕರಿಸಿ ಹಾಗೂ ಮತ್ತೊಮ್ಮೆ ಕೇಳಬೇಡ"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"ಎಲ್ಲಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ಯಾವುದನ್ನೂ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"ಅನುಮತಿಸಿ"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"ಅಪ್ಲಿಕೇಶನ್ ಅನುಮತಿಗಳು"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"ಮತ್ತೆ ಕೇಳಬೇಡಿ"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"ಯಾವುದೇ ಅನುಮತಿಗಳಿಲ್ಲ"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"ಹೆಚ್ಚುವರಿ ಅನುಮತಿಗಳು"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿಯನ್ನು ತೆರೆಯಿರಿ"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"ಈ ಅಪ್ಲಿಕೇಶನ್ Android ನ ಹಳೆಯ ಆವೃತ್ತಿಗೆ ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿತ್ತು. ಅನುಮತಿ ನಿರಾಕರಿಸುವಿಕೆ ಇನ್ನು ಮುಂದೆ ಉದ್ದೇಶಿಸಲ್ಪಟ್ಟಂತೆ ಕಾರ್ಯನಿರ್ವಹಿಸದೆ ಇರುವುದಕ್ಕೆ ಇದು ಕಾರಣವಾಗಬಹುದು."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ಅಪರಿಚಿತ ಕ್ರಿಯೆಯನ್ನು ಮಾಡಿ"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="COUNT_0">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಅನುಮತಿಸಲಾಗಿದೆ"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"ಸಿಸ್ಟಂ ತೋರಿಸು"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"ಸಿಸ್ಟಂ ಮರೆಮಾಡು"</string>
+    <string name="no_apps" msgid="1965493419005012569">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಇಲ್ಲ"</string>
+    <string name="location_settings" msgid="1774875730854491297">"ಸ್ಥಳ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ ಈ ಸಾಧನಕ್ಕೆ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಒದಗಿಸುತ್ತದೆ. ಸ್ಥಳ ಪ್ರವೇಶವನ್ನು ಸ್ಥಳ ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಂದ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
+    <string name="system_warning" msgid="7103819124542305179">"ನೀವು ಈ ಅನುಮತಿಯನ್ನು ನಿರಾಕರಿಸಿದರೆ, ಇನ್ನು ಮುಂದೆ ನಿಮ್ಮ ಸಾಧನದ ಮೂಲ ವೈಶಿಷ್ಟ್ಯಗಳು ಉದ್ದೇಶಿದಂತೆ ಕಾರ್ಯನಿರ್ವಹಿಸದಿರಬಹುದು."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"ನೀತಿಯ ಮೂಲಕ ಜಾರಿಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"ನೀತಿಯ ಮೂಲಕ ಹಿನ್ನೆಲೆ ಪ್ರವೇಶವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"ನೀತಿ ಮೂಲಕ ಹಿನ್ನೆಲೆ ಪ್ರವೇಶವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾದ"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"ನೀತಿ ಮೂಲಕ ಮುನ್ನೆಲೆ ಪ್ರವೇಶವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾದ"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"ನಿರ್ವಾಹಕರ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗಿದೆ"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ಯಾವಾಗಲೂ"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"ಅಪ್ಲಿಕೇಶನ್ ಬಳಸುವಾಗ ಮಾತ್ರ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"ಎಂದೂ ಇಲ್ಲ"</string>
+    <string name="loading" msgid="7811651799620593731">"ಲೋಡ್ ಆಗುತ್ತಿದೆ..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"ಎಲ್ಲ ಅನುಮತಿಗಳು"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"ಇತರ ಅಪ್ಲಿಕೇಶನ್ ಸಾಮರ್ಥ್ಯಗಳು"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"ಅನುಮತಿ ವಿನಂತಿ"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"ಪರದೆ ಆವರಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಪತ್ತೆಹಚ್ಚಲಾಗಿದೆ"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ಈ ಅನುಮತಿ ಸೆಟ್ಟಿಂಗ್ ಬದಲಾಯಿಸಲು, ನೀವು ಮೊದಲು ಸೆಟ್ಟಿಂಗ್‌ಗಳು &gt; ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಂದ ಪರದೆ ಆವರಿಸಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಆಫ್ ಮಾಡಬೇಕು"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"ಸೆಟ್ಟಿಂಗ್‍ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear ನಲ್ಲಿ ಸ್ಥಾಪಿಸುವಿಕೆ/ಅಸ್ಥಾಪಿಸುವಿಕೆ ಕ್ರಿಯೆಗಳು ಬೆಂಬಲಿತವಾಗಿಲ್ಲ."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಪ್ರವೇಶಿಸಲು ಯಾವುದನ್ನು ಅನುಮತಿಸಬೇಕು ಎಂಬುದನ್ನು ಆರಿಸಿಕೊಳ್ಳಿ"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಅನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಲಾಗಿದೆ. ಈ ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಪ್ರವೇಶಿಸಲು ಯಾವುದನ್ನು ಅನುಮತಿಸಬೇಕು ಎಂಬುದನ್ನು ಆರಿಸಿಕೊಳ್ಳಿ."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"ರದ್ದುಮಾಡಿ"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"ಮುಂದುವರಿಸು"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"ಹೊಸ ಅನುಮತಿಗಳು"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"ಪ್ರಸ್ತುತ ಅನುಮತಿಗಳು"</string>
+    <string name="message_staging" msgid="6151794817691100003">"ಸ್ಥಾಪಿಸಲು ಸಿದ್ಧವಿರುವ ಅಪ್ಲಿಕೇಶನ್…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"ಅಪರಿಚಿತ"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"ನಿಮ್ಮ ಸುರಕ್ಷತೆಯ ದೃಷ್ಟಿಯಿಂದ, ಈ ಮೂಲದಿಂದ ಬಂದಿರುವ ಅಪರಿಚಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಲು ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ಗೆ ಅನುಮತಿಯಿಲ್ಲ."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"ನಿಮ್ಮ ಸುರಕ್ಷತೆಯ ದೃಷ್ಟಿಯಿಂದ, ಅಪರಿಚಿತ ಮೂಲಗಳಿಂದ ಪಡೆದುಕೊಳ್ಳುವ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳನ್ನು ನಿಮ್ಮ ಟಿವಿಯು ಸ್ಥಾಪಿಸದಂತೆ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"ನಿಮ್ಮ ಸುರಕ್ಷತೆಯ ದೃಷ್ಟಿಯಿಂದ, ಈ ಮೂಲದಿಂದ ಬಂದಿರುವ ಅಪರಿಚಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಲು ನಿಮ್ಮ ಫೋನ್‌ಗೆ ಅನುಮತಿಯಿಲ್ಲ."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"ನಿಮ್ಮ ಫೋನ್ ಹಾಗೂ ವೈಯಕ್ತಿಕ ಡೇಟಾ, ಅಪರಿಚಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ದಾಳಿಗೆ ತುತ್ತಾಗುವ ಸಾಧ್ಯತೆ ಹೆಚ್ಚಾಗಿದೆ. ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸ್ಥಾಪಿಸುವ ಮೂಲಕ, ನಿಮ್ಮ ಫೋನ್‌ಗೆ ಯಾವುದೇ ಹಾನಿ ಉಂಟಾದರೆ ಅಥವಾ ಅದರ ಬಳಕೆಯಿಂದ ಡೇಟಾ ನಷ್ಟವಾದರೆ, ಅದಕ್ಕೆ ನೀವೇ ಜವಾಬ್ದಾರರು ಎನ್ನುವುದನ್ನು ಒಪ್ಪಿಕೊಳ್ಳುತ್ತೀರಿ."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಹಾಗೂ ವೈಯಕ್ತಿಕ ಡೇಟಾ, ಅಪರಿಚಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ದಾಳಿಗೆ ತುತ್ತಾಗುವ ಸಾಧ್ಯತೆ ಹೆಚ್ಚಾಗಿದೆ. ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸ್ಥಾಪಿಸುವ ಮೂಲಕ, ನಿಮ್ಮ ಫೋನ್‌ಗೆ ಯಾವುದೇ ಹಾನಿ ಉಂಟಾದರೆ ಅಥವಾ ಅದರ ಬಳಕೆಯಿಂದ ಡೇಟಾ ನಷ್ಟವಾದರೆ, ಅದಕ್ಕೆ ನೀವೇ ಜವಾಬ್ದಾರರು ಎನ್ನುವುದನ್ನು ಒಪ್ಪಿಕೊಳ್ಳುತ್ತೀರಿ."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"ನಿಮ್ಮ ಟಿವಿ ಹಾಗೂ ವೈಯಕ್ತಿಕ ಡೇಟಾ, ಅಪರಿಚಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ದಾಳಿಗೆ ತುತ್ತಾಗುವ ಸಾಧ್ಯತೆ ಹೆಚ್ಚಾಗಿದೆ. ಈ ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಸ್ಥಾಪಿಸುವ ಮೂಲಕ, ನಿಮ್ಮ ಟಿವಿಗೆ ಯಾವುದೇ ಹಾನಿ ಉಂಟಾದರೆ ಅಥವಾ ಅದರ ಬಳಕೆಯಿಂದ ಡೇಟಾ ನಷ್ಟವಾದರೆ, ಅದಕ್ಕೆ ನೀವೇ ಜವಾಬ್ದಾರರು ಎನ್ನುವುದನ್ನು ಒಪ್ಪಿಕೊಳ್ಳುತ್ತೀರಿ."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"ಮುಂದುವರಿಸಿ"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"wear ಅಪ್ಲಿಕೇಶನ್‌ ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ/ಅಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ko-television/strings.xml b/packages/PackageInstaller/res/values-ko-television/strings.xml
new file mode 100644
index 0000000..6ad2ed6
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ko-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"거부 및 다시 묻지 않음"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"설정 &gt; 앱에서 나중에 변경할 수 있습니다."</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>개 중 <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"시스템 앱 보기"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"앱 권한"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"앱 권한"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> 권한"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"추가 권한"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> 권한"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ko-watch/strings.xml b/packages/PackageInstaller/res/values-ko-watch/strings.xml
new file mode 100644
index 0000000..6cce6f9
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ko-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"거부 및 다시 묻지 않음"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"시스템 앱 보기"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"변경할 수 없음"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"예"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"취소"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ko/strings.xml b/packages/PackageInstaller/res/values-ko/strings.xml
new file mode 100644
index 0000000..235a1d4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ko/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"패키지 설치 프로그램"</string>
+    <string name="next" msgid="3057143178373252333">"다음"</string>
+    <string name="install" msgid="5896438203900042068">"설치"</string>
+    <string name="done" msgid="3889387558374211719">"완료"</string>
+    <string name="cancel" msgid="8360346460165114585">"취소"</string>
+    <string name="installing" msgid="8613631001631998372">"설치 중..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 설치 중…"</string>
+    <string name="install_done" msgid="3682715442154357097">"앱이 설치되었습니다."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"이 애플리케이션을 설치하시겠습니까? 애플리케이션이 다음에 액세스할 수 있습니다."</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"이 애플리케이션을 설치하시겠습니까? 특별한 액세스 권한이 필요하지 않습니다."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"기존 애플리케이션에 업데이트를 설치하시겠습니까? 기존 데이터는 손실되지 않습니다. 업데이트된 애플리케이션이 다음에 액세스할 수 있습니다."</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"내장 애플리케이션에 업데이트를 설치하시겠습니까? 기존 데이터는 손실되지 않습니다. 업데이트된 애플리케이션이 다음에 액세스할 수 있습니다."</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"기존의 애플리케이션 업데이트를 설치하시겠습니까? 기존의 데이터는 손실되지 않으며 특별한 액세스 권한이 필요하지 않습니다."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"내장 애플리케이션 업데이트를 설치하시겠습니까? 기존의 데이터는 손실되지 않으며 특별한 액세스 권한이 필요하지 않습니다."</string>
+    <string name="install_failed" msgid="6579998651498970899">"앱이 설치되지 않았습니다."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"패키지 설치가 차단되었습니다."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"패키지가 기존 패키지와 충돌하여 앱이 설치되지 않았습니다."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"앱이 태블릿과 호환되지 않아서 설치되지 않았습니다."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"앱이 사용 중인 TV와 호환되지 않습니다."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"앱이 휴대전화와 호환되지 않아서 설치되지 않았습니다."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"패키지가 잘못되어 앱이 설치되지 않았습니다."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"태블릿에 <xliff:g id="APP_NAME">%1$s</xliff:g> 앱을 설치할 수 없습니다."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g>을(를) TV에 설치할 수 없습니다."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"휴대전화에 <xliff:g id="APP_NAME">%1$s</xliff:g> 앱을 설치할 수 없습니다."</string>
+    <string name="launch" msgid="4826921505917605463">"열기"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"관리자가 알 수 없는 출처의 앱 설치를 허용하지 않습니다."</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"이 사용자는 알 수 없는 앱을 설치할 수 없습니다."</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"이 사용자는 앱을 설치할 권한이 없습니다."</string>
+    <string name="ok" msgid="3468756155452870475">"확인"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"앱 관리"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"여유 공간이 없음"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱을 설치할 수 없습니다. 여유 공간을 늘린 후에 다시 시도하세요."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"앱을 찾을 수 없음"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"설치된 앱 목록에 앱이 없습니다."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"허용되지 않음"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"현재 사용자는 이 제거를 수행할 수 없습니다."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"오류"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"앱을 제거할 수 없습니다."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"앱 제거"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"업데이트 제거"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>은(는) 다음 앱의 일부입니다."</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"이 앱을 제거하시겠습니까?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222"><b>"모든"</b>" 사용자에 대해 이 앱을 제거하시겠습니까? 기기를 사용하는 "<b>"모든"</b>" 사용자에 대해 애플리케이션 및 데이터가 삭제됩니다."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"<xliff:g id="USERNAME">%1$s</xliff:g>님의 기기에 설치된 앱을 제거하시겠습니까?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"이 앱을 초기 버전으로 바꾸시겠습니까? 모든 데이터가 삭제됩니다."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"이 앱을 초기 버전으로 바꾸시겠습니까? 모든 데이터가 삭제되며 직장 프로필 사용자를 포함해 이 기기의 모든 사용자에게 영향을 미칩니다."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"실행 중인 제거 작업"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"실패한 제거 작업"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"제거 중..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 제거 중…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"제거를 완료했습니다."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>을(를) 제거했습니다."</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"제거하지 못했습니다."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>을(를) 제거하지 못했습니다."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"활성 상태의 기기 관리자 앱을 제거할 수 없습니다."</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g>의 활성 상태의 기기 관리자 앱을 제거할 수 없습니다."</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"이 앱은 일부 사용자 또는 프로필에 필요하며 다른 사용자에 대해서는 제거되었습니다."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"이 앱은 프로필에 필요하므로 삭제할 수 없습니다."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"이 앱은 기기 관리자에게 필요하므로 제거할 수 없습니다."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"기기 관리자 앱 관리"</string>
+    <string name="manage_users" msgid="3125018886835668847">"사용자 관리"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱을 제거할 수 없습니다."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"패키지를 파싱하는 중 문제가 발생했습니다."</string>
+    <string name="newPerms" msgid="6039428254474104210">"새 권한"</string>
+    <string name="allPerms" msgid="1024385515840703981">"전체"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"개인정보 보호"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"기기 액세스"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"이 업데이트에는 새로운 권한이 필요하지 않습니다."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"거부"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"추가 정보"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"거부"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;의 다음 작업을 허용하시겠습니까? <xliff:g id="ACTION">%2$s</xliff:g>"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 <xliff:g id="ACTION">%2$s</xliff:g>하도록 허용하시겠습니까??"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"앱 사용 중에만"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"항상"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"거부 및 다시 묻지 않음"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g>개 중지됨"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"모두 중지됨"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"아무것도 중지되지 않음"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"허용"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"앱"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"앱 권한"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"다시 묻지 않음"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"권한이 없음"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"추가 권한"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"앱 정보 열기"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"이 앱은 Android 이전 버전에 맞게 설계되었습니다. 권한을 거부하면 정상적으로 작동하지 않을 수 있습니다."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"알 수 없는 작업 수행"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g>개 앱 허용됨"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"시스템 표시"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"시스템 숨기기"</string>
+    <string name="no_apps" msgid="1965493419005012569">"앱 없음"</string>
+    <string name="location_settings" msgid="1774875730854491297">"위치 설정"</string>
+    <string name="location_warning" msgid="8778701356292735971">"이 기기의 위치 서비스 제공업체는 <xliff:g id="APP_NAME">%1$s</xliff:g>입니다. 위치 정보 액세스는 위치 설정에서 수정할 수 있습니다."</string>
+    <string name="system_warning" msgid="7103819124542305179">"이 권한을 거부하는 경우 기기의 기본 기능이 제대로 작동하지 않을 수 있습니다."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"정책에 의해 시행됨"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"정책에 따라 백그라운드 액세스 사용 중지됨"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"정책에 따라 백그라운드 액세스 사용 설정함"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"정책에 따라 포그라운드 액세스 사용 설정함"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"관리자가 제어"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"항상"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"앱 사용 중에만"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"사용 안함"</string>
+    <string name="loading" msgid="7811651799620593731">"로드 중..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"모든 권한"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"다른 앱 기능"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"권한 요청"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"화면 오버레이 감지됨"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"이 권한 설정을 변경하려면 먼저 설정 &gt; 앱에서 화면 오버레이를 사용하지 않도록 설정해야 합니다."</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"설정 열기"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear에서 지원하지 않는 설치/제거 작업입니다."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 액세스하도록 허용할 항목을 선택하세요."</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;이(가) 업데이트되었습니다. 이 앱에서 액세스하도록 허용할 항목을 선택하세요."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"취소"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"계속"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"새로운 권한"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"기존 권한"</string>
+    <string name="message_staging" msgid="6151794817691100003">"앱 준비 중…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"알 수 없음"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"보안상의 이유로 이 경로를 통한 알 수 없는 앱을 태블릿에 설치할 수 없습니다."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"보안상의 이유로 이 경로를 통한 알 수 없는 앱을 TV에 설치할 수 없습니다."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"보안상의 이유로 이 경로를 통한 알 수 없는 앱을 휴대전화에 설치할 수 없습니다."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"휴대전화와 개인 데이터는 알 수 없는 앱의 공격에 더욱 취약합니다. 이 앱을 설치하면 앱 사용으로 인해 발생할 수 있는 모든 휴대전화 손상이나 데이터 손실에 사용자가 책임을 진다는 것에 동의하게 됩니다."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"태블릿과 개인 데이터는 알 수 없는 앱의 공격에 더욱 취약합니다. 이 앱을 설치하면 앱 사용으로 인해 발생할 수 있는 모든 태블릿 손상이나 데이터 손실에 사용자가 책임을 진다는 것에 동의하게 됩니다."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"TV와 개인 데이터는 알 수 없는 앱의 공격에 더욱 취약합니다. 이 앱을 설치하면 앱 사용으로 인해 발생할 수 있는 모든 TV 손상이나 데이터 손실에 사용자가 책임을 진다는 것에 동의하게 됩니다."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"계속"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"설정"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear 앱 설치/제거"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ky-television/strings.xml b/packages/PackageInstaller/res/values-ky-television/strings.xml
new file mode 100644
index 0000000..20994ff
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ky-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Баш тартам жана экинчи суралбасын"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Муну кийин Жөндөөлөр &gt; Колдонмолордон өзгөртө аласыз"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Тутум колдонмолорун көрсөтүү"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Колдонмонун уруксаттары"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Колдонмонун уруксаттары"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> уруксаттары"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Кошумча уруксаттар"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> уруксаттары"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ky-watch/strings.xml b/packages/PackageInstaller/res/values-ky-watch/strings.xml
new file mode 100644
index 0000000..aadb7c4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ky-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Баш тарам, экинчи суралбасын"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Тутум колдонмолорун көрсөтүү"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Өзгөртүүгө болбойт"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ооба"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Жокко чыгаруу"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ky/strings.xml b/packages/PackageInstaller/res/values-ky/strings.xml
new file mode 100644
index 0000000..9a95c54
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ky/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Топтом орноткуч"</string>
+    <string name="next" msgid="3057143178373252333">"Кийинки"</string>
+    <string name="install" msgid="5896438203900042068">"Орнотуу"</string>
+    <string name="done" msgid="3889387558374211719">"Даяр"</string>
+    <string name="cancel" msgid="8360346460165114585">"Жокко чыгаруу"</string>
+    <string name="installing" msgid="8613631001631998372">"Орнотулууда…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> орнотулууда…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Колдонмо орнотулду."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Бул колдонмону орнотоюн дегениңиз аныкпы? Ал кийинкилерге жетки алат:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Бул колдонмону орнотоюн дегениңиз аныкпы? Ал эч бир атайын жетки уруксаттарын талап кылбайт."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Учурда иштеп турган бул колдонмого жаңыртуу орнотоюн дегениңиз аныкпы? Сиздин сакталган берилиштериңиз өчүрүлбөйт. Жаңыртылган колдонмо кийинкилерге жетки алат:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Бул камтылган колдонмого жаңыртуу орнотоюн дегениңиз аныкпы? Сиздин сакталган берилиштериңиз өчүрүлбөйт. Жаңыртылган колдонмо кийинкилерге жетки алат:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Учурда иштпе турган бул колдонмого жаңыртуу орнотоюн дегениңиз аныкпы? Сиздин сакталган берилиштериңиз өчүрүлбөйт. Ал эч бир атайын жетки уруксаттарын талап кылбайт."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Бул камтылган колдонмого жаңыртуу орнотоюн дегениңиз аныкпы? Сиздин сакталган берилиштериңиз өчүрүлбөйт. Ал эч бир атайын жетки уруксаттарын  талап кылбайт."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Колдонмо орнотулган жок."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Топтом орнотуудан бөгөттөлгөн."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Башка топтом менен дал келбегендиктен колдонмо орнотулган жок."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Бул колдонмо планшетиңизге шайкеш эмес болгондуктан колдонмо орнотулган жок."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Бул колдонмо сыналгыңызга шайкеш келбейт."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Бул колдонмо телефонуңузга шайкеш эмес болгондуктан колдонмо орнотулган жок."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Топтом катары орнотулбай калган колдонмо жараксыз окшойт."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосун планшетиңизге орнотуу мүмкүн эмес."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> сыналгыңызга орнотулбай койду."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосун телефонуңузга орнотуу мүмкүн эмес."</string>
+    <string name="launch" msgid="4826921505917605463">"Ачуу"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Администраторуңуз белгисиз булактардан алынган колдонмолордун орнотулушуна жол бербейт"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Бул колдонуучу белгисиз колдонмолорду орното албайт"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Бул колдонуучу колдонмолорду орното албайт"</string>
+    <string name="ok" msgid="3468756155452870475">"Жарайт"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Колдонмолорду башкаруу"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Бош орун жок"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосун телефонуңузга орнотуу мүмкүн эмес. Орун бошотуп, кайталап орнотуп көрүңүз."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Колдонмо табылган жок"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Колдонмо орнотулган колдонмолор тизмегинен табылган жок."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Тыюу салынган"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Учурдагы колдонуучу колдонмону чыгарып сала албайт."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Ката"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Колдонмону чыгарып салуу мүмкүн болбой жатат."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Колдонмону чечип салуу"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Жаңыртууну чечип салуу"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> кийинки колдонмонун бөлүгү:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Бул колдонмону чечип салгыңыз келеби?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Бул колдонмо "<b>"бардык"</b>" колдонуучулардан алынып салынсынбы? Бул колдонмо жана анын берилиштери бул түзмөктүн "<b>"бардык"</b>" колдонуучуларынан алынат."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Бул колдонмону <xliff:g id="USERNAME">%1$s</xliff:g> колдонуучусу үчүн орнотуудан чыгаргыңыз келеби?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Бул колдонмонун баштапкы версиясы орнотулсунбу? Бардык дайындар өчүп калат."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Бул колдонмонун баштапкы версиясы орнотулсунбу? Түзмөктөгү бардык профилдердин, ошондой эле жумушчу профилдин дайындары өчүп калат."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Чыгарылып салынууда"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Чыгарылып салынбай калгандар"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Чыгарылып салынууда…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> колдонмосу чыгарылууда…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Чечилип бүттү."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> колдонмосу чыгарылды"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Чечүү ийгиликсиз болду."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> колдонмосун чыгарып салуу ишке ашкан жок."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Түзмөктү башкарган колдонмо иштеп жатканда аны чыгарып салууга болбойт"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> колдонуучусунун түзмөктү башкарган колдонмосу иштеп жатканда, аны чыгарып салууга болбойт"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Колдонмо айрым колдонуучулар же профилдерге керек."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Бул колдонмо профилиңизге керек жана аны чыгарып салуу мүмкүн эмес."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Бул колдонмо түзмөк администраторуңузга керектелет жана орнотуудан чыгаруу мүмкүн эмес."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Түзмөктү башкарган колдонмолорду көзөмөлдөө"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Колдонуучуларды башкаруу"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосун чечип салуу мүмкүн эмес."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Таңгакты окууда маселе пайда болду."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Жаңы"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Бардыгы"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Купуялуулук"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Жетүү уруксаттары"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Бул жаңыртуу жаңы уруксаттарды талап кылбайт."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Жок"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Көбүрөөк маалымат"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Баш тартуу"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> ичинен <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна <xliff:g id="ACTION">%2$s</xliff:g> уруксат берилсинби?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна <xliff:g id="ACTION">%2$s</xliff:g> аракетине ар дайым уруксат берилсинби?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Ушул колдонмодо иштегенде гана"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Ар дайым"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Баш тартам жана экинчи суралбасын"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> өчүрүлгөн"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"баары өчүрүлгөн"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"эч бири өчүрүлгөн жок"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Уруксат берүү"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Колдонмолор"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Колдонмо уруксаттары"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Экинчи суралбасын"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Уруксаттар жок"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Кошумча уруксаттар"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Колдонмо тууралуу маалыматты ачуу"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Бул колдонмо эски Android версиясы үчүн түзүлгөн. Уруксат берилбесе, ал туура эмес иштеп калышы мүмкүн."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"белгисиз аракеттерди жасайт"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g> колдонмонун ичинен <xliff:g id="COUNT_0">%1$d</xliff:g> уруксат берилген"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Тутумду көрсөтүү"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Тутумдагы процесстерди жашыруу"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Бир дагы колдонмо жок"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Геолокация параметрлери"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> - бул түзмөктөгү жайгашкан жерди аныктоо кызматынын камсыздоочусу. Жайгашкан жерди көрүү мүмкүнчүлүгүн жайгашкан жерди аныктоо жөндөөлөрүнөн өзгөртсө болот."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Эгер бул уруксатты четке каксаңыз, түзмөгүңүздүн негизги функциялары талаптагыдай иштебей калышы мүмкүн."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Саясат тарабынан күчүнө киргизилген"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Фондук режимде колдонуу саясат тарабынан өчүрүлгөн"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Фондук режимде колдонуу саясат тарабынан иштетилген"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Активдүү режим саясат боюнча иштетилген"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Администратор тарабынан көзөмөлдөнөт"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Ар дайым"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Ушул колдонмодо иштегенде гана"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Эч качан"</string>
+    <string name="loading" msgid="7811651799620593731">"Жүктөлүүдө…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Бардык уруксаттар"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Колдонмонун башка жөндөмдөрү"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Уруксат суроо"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Экран кабатталышы аныкталды"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Бул уруксаттын жөндөөсүн өзгөртүү үчүн, адегенде Жөндөөлөр &gt; Колдонмолордон экрандын кабатталышын өчүрүңүз"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Жөндөөлөрдү ачуу"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Тагынма"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Орнотуу/чыгарып салуу аракеттери Android Wear\'де колдоого алынбайт."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосу үчүн уруксаттарды тандаңыз"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; жаңыртылды. Ал үчүн уруксаттарды тандаңыз."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Жок"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Улантуу"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Жаңы уруксаттар"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Учурдагы уруксаттар"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Күтө туруңуз…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Белгисиз"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Коопсуздукту сактоо максатында, планшетиңизге бул булактан колдонмолорду орнотууга уруксат жок."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Коопсуздукту сактоо максатында, сыналгыңызга бул булактан колдонмолорду орнотууга уруксат жок."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Коопсуздукту сактоо максатында, телефонуңузга бул булактан колдонмолорду орнотууга уруксат жок."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Телефонуңуз жана жеке дайындарыңыз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам телефонуңузга кандайдыр бир зыян келтирилсе же дайындарыңызды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Планшетиңиз жана жеке дайындарыңыз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам планшетиңизге кандайдыр бир зыян келтирилсе же дайындарыңызды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"TV жана жеке дайындарыңыз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам TV\'ңизге кандайдыр бир зыян келтирилсе же дайындарыңызды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Улантуу"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Жөндөөлөр"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Тагынма колдонмолорду орнотуу/чыгаруу"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-lo-television/strings.xml b/packages/PackageInstaller/res/values-lo-television/strings.xml
new file mode 100644
index 0000000..a6f4e49
--- /dev/null
+++ b/packages/PackageInstaller/res/values-lo-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"ປະຕິເສດ ແລະຢ່າຖາມອີກ"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"ທ່ານສາມາດປ່ຽນແປງສິ່ງນີ້ໃນພາຍຫຼັງໄດ້ໃນການຕັ້ງຄ່າ &gt; ແອັບ"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"ສະ​ແດງ​ແອັບ​ລະ​ບົບ"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"ການອະນຸຍາດແອັບ"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"ການອະນຸຍາດແອັບ"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> ການອະນຸຍາດ"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"ການອະນຸຍາດເພີ່ມເຕີມ"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> ການອະນຸຍາດ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-lo-watch/strings.xml b/packages/PackageInstaller/res/values-lo-watch/strings.xml
new file mode 100644
index 0000000..4fae329
--- /dev/null
+++ b/packages/PackageInstaller/res/values-lo-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ປະ​ຕິ​ເສດ, ຢ່າ​ຖາມ​ອີກ"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"ສະ​ແດງ​ແອັບ​ລະ​ບົບ"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ບໍ່​ສາ​ມາດ​ປ່ຽນ​ແປງ​ໄດ້"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"ແມ່ນແລ້ວ"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"ຍົກເລີກ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-lo/strings.xml b/packages/PackageInstaller/res/values-lo/strings.xml
new file mode 100644
index 0000000..f39f140
--- /dev/null
+++ b/packages/PackageInstaller/res/values-lo/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"ໂຕຕິດຕັ້ງແພັກເກດ"</string>
+    <string name="next" msgid="3057143178373252333">"ຕໍ່ໄປ"</string>
+    <string name="install" msgid="5896438203900042068">"ຕິດຕັ້ງ"</string>
+    <string name="done" msgid="3889387558374211719">"ແລ້ວໆ"</string>
+    <string name="cancel" msgid="8360346460165114585">"ຍົກເລີກ"</string>
+    <string name="installing" msgid="8613631001631998372">"ກຳລັງຕິດຕັ້ງ…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"ກຳລັງຕິດຕັ້ງ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"ຕິດຕັ້ງແອັບຯແລ້ວ."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"ທ່ານຕ້ອງການຕິດຕັ້ງແອັບພລິເຄຊັນນີ້ບໍ່? ມັນຈະໄດ້ສິດການເຂົ້າເຖິງ:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"ທ່ານ​ຕ້ອງ​ການ​ຕິດ​ຕັ້ງ​ແອັບພລິເຄຊັນນີ້ບໍ່​? ມັນ​ບໍ່​ຕ້ອງໃຊ້ສິດທິການ​ເຂົ້າ​ເຖິງ​​ພິ​ເສດໃດໆ."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"ທ່ານຕ້ອງການຕິດຕັ້ງອັບເດດໃສ່ແອັບພລິເຄຊັນນີ້ບໍ່? ຂໍ້ມູນຂອງທ່ານທີ່ມີຢູ່ກ່ອນແລ້ວຈະຍັງຄົງຢູ່ຄືເກົ່າ. ແອັບພລິເຄຊັນທີ່ຜ່ານການອັບເດດຈະສາມາດເຂົ້າເຖິງ:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"ທ່ານຕ້ອງການທີ່ຈະຕິດຕັ້ງຊຸດອັບເດດສຳລັບແອັບຯນີ້ບໍ່? ຂໍ້ມູນທີ່ທ່ານມີຢູ່ຈະບໍ່ສູນຫາຍ. ການອັບເດດແອັບພລິເຄຊັນນີ້ຈະສາມາດເຂົ້າເຖິງ:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"ທ່ານຕ້ອງການຕິດຕັ້ງອັບເດດໃສ່ແອັບພລິເຄຊັນນີ້ບໍ່? ຂໍ້ມູນຂອງທ່ານທີ່ມີຢູ່ກ່ອນແລ້ວຈະຍັງຄົງຢູ່ຄືເກົ່າ. ມັນບໍ່ຕ້ອງການສິດເຂົ້າເຖິງພິເສດໃດໆ."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"ທ່ານຕ້ອງການຕິດຕັ້ງອັບເດດໃສ່ແອັບພລິເຄຊັນທີ່ມີມານຳນີ້ບໍ່? ຂໍ້ມູນຂອງທ່ານທີ່ມີຢູ່ກ່ອນແລ້ວຈະຍັງຄົງຢູ່ຄືເກົ່າ. ມັນບໍ່ຕ້ອງການສິດເຂົ້າເຖິງພິເສດໃດໆເລີຍ."</string>
+    <string name="install_failed" msgid="6579998651498970899">"ບໍ່ໄດ້ຕິດຕັ້ງແອັບຯເທື່ອ."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ແພັກ​ເກດ​ຖືກບ​ລັອກ​ບໍ່​ໃຫ້​ໄດ້​ຮັບ​ການ​ຕິດ​ຕັ້ງ"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"App not installed as package conflicts with an existing package."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"App not installed as app isn\'t compatible with your tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"ແອັບ​ນີ້​ບໍ່​ເຂົ້າ​ກັນ​ໄດ້​ກັບໂທລະພາບຂອງ​ທ່ານ."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"App not installed as app isn\'t compatible with your phone."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"App not installed as package appears to be invalid."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"ບໍ່ສາມາດຕິດຕັ້ງ <xliff:g id="APP_NAME">%1$s</xliff:g> ໃສ່ແທັບເລັດຂອງທ່ານໄດ້."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່​ສາ​ມາດ​ຕິດ​ຕັ້ງ​ໃສ່ໂທລະພາບຂອງ​ທ່ານ​ໄດ້."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"ບໍ່​ສາ​ມາດ​ຕິດ​ຕັ້ງ​ <xliff:g id="APP_NAME">%1$s</xliff:g> ໃນໂທລະສັບຂອງທ່ານໄດ້."</string>
+    <string name="launch" msgid="4826921505917605463">"ເປີດ"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"ຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຕິດຕັ້ງແອັບທີ່ໄດ້ມາຈາກແຫຼ່ງທີ່ບໍ່ຮູ້ຈັກ"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"ຜູ້ໃຊ້ນີ້ບໍ່ສາມາດຕິດຕັ້ງແອັບທີ່ບໍ່ຮູ້ຈັກໄດ້"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"ຜູ້ໃຊ້ນີ້ບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ຕິດຕັ້ງແອັບໄດ້"</string>
+    <string name="ok" msgid="3468756155452870475">"ຕົກລົງ"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"ຈັດການແອັບຯ"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"ພື້ນທີ່ຫວ່າງບໍ່ພຽງພໍ"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"ບໍ່ສາມາດຕິດຕັ້ງ <xliff:g id="APP_NAME">%1$s</xliff:g> ໄດ້. ກະລຸນາລຶບຂໍ້ມູນທີ່ບໍ່ຈຳເປັນອອກ ເພື່ອໃຫ້ມີບ່ອນຈັດເກັບຂໍ້ມູນຫວ່າງເພີ່ມຂຶ້ນ ແລ້ວລອງໃໝ່ອີກຄັ້ງ."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"ບໍ່ພົບເຫັນແອັບຯ"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ບໍ່ພົບແອັບຯໃນລາຍການຂອງແອັບຯທີ່ຕິດຕັ້ງແລ້ວ."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"ບໍ່ອະນຸຍາດແລ້ວ"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"ຜູ້ໃຊ້ປັດຈຸບັນບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ຖອນການຕິດຕັ້ງນີ້ໄດ້."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"ຜິດພາດ"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"ບໍ່ສາມາດຖອນການຕິດຕັ້ງແອັບໄດ້."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"ຖອນ​ການ​ຕິດ​ຕັ້ງແອັບຯ"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"ຖອນ​ການ​ຕິດ​ຕັ້ງ​ອັບເດດ"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ແມ່ນ​ສ່ວນ​ນຶ່ງ​ຂອງແອັບຯຂ້າງລຸ່ມ:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"ທ່ານຕ້ອງການຖອນການຕິດຕັ້ງແອັບຯນີ້ບໍ່?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"ທ່ານຕ້ອງການທີ່ຈະຖອນການຕິດຕັ້ງແອັບຯນີ້ ສຳລັງຜູ່ໃຊ້"<b>"ທຸກຄົນ"</b>"ບໍ່? ແອັບພລິເຄຊັນ ແລະຂໍ້ມູນຂອງມັນຈະຖືກລຶບອອກ ຈາກຜູ່ໃຊ້"<b>"ທັງໝົດ"</b>"ໃນອຸປະກອນນີ້."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"ທ່ານ​ຕ້ອງ​ການ​ຖອນ​ການ​ຕິດ​ຕັ້ງ​ແອັບຯ​ນີ້​ສຳ​ລັບ​ຜູ່​ໃຊ້ <xliff:g id="USERNAME">%1$s</xliff:g> ບໍ່?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ແທນທີ່ແອັບນີ້ດ້ວຍເວີຊັນທີ່ມາຈາກໂຮງງານບໍ? ຂໍ້ມູນທັງໝົດຈະຖືກລຶບອອກ."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ແທນທີ່ແອັບນີ້ດ້ວຍເວີຊັນທີ່ມາຈາກໂຮງງານບໍ? ຂໍ້ມູນທັງໝົດຈະຖືກລຶບອອກ ເຊິ່ງມີຜົນກັບຜູ້ໃຊ້ອຸປະກອນນີ້ທຸກຄົນ ຮວມທັງຄົນທີ່ມີໂປຣໄຟລ໌ບ່ອນເຮັດວຽກນຳ."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"ກຳລັງຖອນການຕິດຕັ້ງ"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"ຖອນການຕິດຕັ້ງບໍ່ສຳເລັດ"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"ກຳລັງຖອນການຕິດຕັ້ງ..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"ກຳລັງຖອນການຕິດຕັ້ງ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"ຖອນການຕິດຕັ້ງສຳເລັດແລ້ວ."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"ຖອນການຕິດຕັ້ງ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ແລ້ວ"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"ການຖອນການຕິດຕັ້ງບໍ່ສຳເລັດ."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"ຖອນການຕິດຕັ້ງ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ບໍ່ສຳເລັດ."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"ບໍ່ສາມາດຖອນການຕິດຕັ້ງແອັບອຸປະກອນທີ່ເຮັດວຽກຢູ່ໄດ້"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"ບໍ່ສາມາດຖອນການຕິດຕັ້ງແອັບຜູ້ເບິ່ງແຍງລະບົບທີ່ເຮັດວຽກຢູ່ສຳລັບ <xliff:g id="USERNAME">%1$s</xliff:g> ໄດ້"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"ແອັບນີ້ຈຳເປັນສຳລັບບາງຜູ້ໃຊ້ ຫຼື ບາງໂປຣໄຟລ໌ ແລະ ຖືກຖອນການຕິດຕັ້ງສຳລັບຄົນອື່ນແລ້ວ"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"ແອັບນີ້ຈຳເປັນຕ້ອງໃຊ້ກັບໂປຣໄຟລ໌ຂອງທ່ານ ແລະ ບໍ່ສາມາດຖອນການຕິດຕັ້ງໄດ້."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"​ແອັບຯ​ນີ້​ຕ້ອງ​ໃຊ້​ໂດຍ​ຜູ່​ເບິ່ງ​ແຍງ​ລະ​ບົບ​ຂອງ​ທ່ານ ແລະ​ບໍ່​ສາ​ມາດ​ຖອນ​ການ​ຕິດ​ຕັ້ງ​ໄດ້."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"ຈັດການແອັບຜູ້ເບິ່ງແຍງອຸປະກອນ"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ຈັດການຜູ້ໃຊ້"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ສາມາດຖອນອອກໄດ້."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"ເກີດບັນຫາໃນການວິເຄາະແພັກເກດ."</string>
+    <string name="newPerms" msgid="6039428254474104210">"ໃໝ່"</string>
+    <string name="allPerms" msgid="1024385515840703981">"ທັງໝົດ"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"ຄວາມ​ເປັນ​ສ່ວນ​ຕົວ"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"ການເຂົ້າເຖິງອຸປະກອນ"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"ອັບເດດນີ້ບໍ່ຕ້ອງການການອະນຸຍາດໃໝ່."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"ປະຕິເສດ"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"ຂໍ້ມູນເພີ່ມເຕີມ"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"ຢືນຢັນປະຕິເສດ"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> ໃນ <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ສາມາດ <xliff:g id="ACTION">%2$s</xliff:g> ບໍ?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ໃຊ້ <xliff:g id="ACTION">%2$s</xliff:g> ໄດ້ທຸກເທື່ອບໍ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"ໃນເວລາໃຊ້ແອັບເທົ່ານັ້ນ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ທຸກເທື່ອ"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"ປະຕິເສດ ແລະ ຢ່າຖາມອີກ"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"ປິດໄວ້ <xliff:g id="COUNT">%1$d</xliff:g> ສິດອະນຸຍາດແລ້ວ"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"ປິດໄວ້ທັງໝົດແລ້ວ"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ບໍ່ມີອັນໃດປິດການນຳໃຊ້ໄວ້"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"ອະນຸຍາດ"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"ແອັບ"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"ການ​ອະ​ນຸ​ຍາດ​ແອັບ"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"ບໍ່ຕ້ອງຖາມອີກ"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"​ບໍ່​ມີການ​ອະ​ນຸ​ຍາດ​"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"ການ​ອະ​ນຸ​ຍາດ​​ເພີ່ມ​ເຕີມ"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"ເປີດຂໍ້ມູນແອັບ"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"ແອັບ​ນີ້​ຖືກ​ອອກ​ແບບ​ມາ​ສຳ​ລັບ Android ເວີ​ຊັນ​ເກົ່າ. ການ​ປະ​ຕິ​ເສດ​ການ​ອະ​ນຸ​ຍາດ​ອາດ​ຈະ​ເຮັດ​ໃຫ້​ມັນ​ບໍ່​ເຮັດ​ວຽກ​ຕາມ​ຕ້ອງ​ການ​ໄດ້​ອີກ."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ເຮັດ​ການ​ດຳ​ເນີນ​ການ​ທີ່​ບໍ່​ຮູ້​ຈັກ"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> ໃນ <xliff:g id="COUNT_1">%2$d</xliff:g> ແອັບ​ໄດ້​ຮັບ​ອະ​ນຸ​ຍາດ​ແລ້ວ"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"ສະແດງລະບົບ"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"ເຊື່ອງ​ລະ​ບົບ"</string>
+    <string name="no_apps" msgid="1965493419005012569">"ບໍ່ມີແອັບ"</string>
+    <string name="location_settings" msgid="1774875730854491297">"ການຕັ້ງຄ່າ​ທີ່​ຕັ້ງ"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> ແມ່ນ​ຜູ້​ໃຫ້​ບໍ​ລິ​ການ​ເລື່ອງ​ການ​ບໍ​ລິ​ການ​ທີ່​ຕັ້ງ​ສຳ​ລັບ​ອຸ​ປະ​ກອນ​ນີ້. ການ​ເຂົ້າ​ເຖິງ​ທີ່​ຕັ້ງ​ແມ່ນ​ສາ​ມາດ​ດັດ​ແປງ​ໄດ້​ຈາກ​ການ​ຕັ້ງ​ຄ່າ​ທີ່​ຕັ້ງ."</string>
+    <string name="system_warning" msgid="7103819124542305179">"ຖ້າ​ທ່ານ​ປະ​ຕິ​ເສດ​ການ​ອະ​ນຸ​ຍາດ​ນີ້, ຄຸນສົມບັດໃຊ້ງານ​ພື້ນ​ຖານ​ຂອງ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ອາດ​ຈະ​ບໍ່​ເຮັດ​ໜ້າ​ທີ່​ຕາມທີ່ກຳນົດໄວ້."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"ບັງ​ຄັບ​ໃຊ້​ຕາມ​ນະ​ໂຍ​ບາຍ​ແລ້ວ"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"ປິດນຳໃຊ້ການເຂົ້າເຖິງໃນພື້ນຫຼັງຕາມນະໂຍບາຍແລ້ວ"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"ເປີດນຳໃຊ້ການເຂົ້າເຖິງໃນພື້ນຫຼັງຕາມນະໂຍບາຍແລ້ວ"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"ເປີດນຳໃຊ້ການເຂົ້າເຖິງໃນພື້ນໜ້າຕາມນະໂຍບາຍແລ້ວ"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"ຄວບຄຸມໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ທຸກເທື່ອ"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"ໃນເວລາໃຊ້ແອັບເທົ່ານັ້ນ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"ບໍ່ເລີຍ"</string>
+    <string name="loading" msgid="7811651799620593731">"ກຳລັງ​ໂຫລດ..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"ທຸກ​ການ​ອະ​ນຸ​ຍາດ"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"ຄວາມ​​ສາ​ມາດ​​ອື່ນຂອງແອັບ"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"ການຮ້ອງຂໍການອະນຸຍາດ"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"ກວດ​ພົບ​ການ​ວາງ​ຊ້ອນ​ໜ້າ​ຈໍ​ແລ້ວ"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ເພື່ອ​ປ່ຽນ​ແປງ​ການ​ຕັ້ງ​ຄ່າ​ການ​ອະ​ນຸ​ຍາດ​ນີ້, ກ່ອນ​ອື່ນ​ໝົດ​ທ່ານ​ຕ້ອງ​ປິດ​ການ​ວາງ​ຊ້ອນ​ໜ້າ​ຈໍ​ຈາກ​ແອັບ​ການ​ຕັ້ງ​ຄ່າ"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"ເປີດການຕັ້ງຄ່າ"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"ຕິດຕັ້ງ/ຖອນຕິດຕັ້ງ ຄຳສັ່ງທີ່ບໍ່ຮອງຮັບຢູ່ໃນ Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"ເລືອກວ່າຈະອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງຫຍັງໄດ້ແດ່"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"ອັບເດດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ແລ້ວ. ກະລຸນາເລືອກວ່າຈະໃຫ້ແອັບນີ້ເຂົ້າເຖິງຫຍັງໄດ້ແດ່."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"​ຍົກ​ເລີກ"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"​ສືບ​ຕໍ່"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"ການ​ອະ​ນຸ​ຍາດ​ໃໝ່"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"ການ​ອະນຸຍາດ​ປັດຈຸ​ບັນ"</string>
+    <string name="message_staging" msgid="6151794817691100003">"ກຳລັງຮຽງແອັບ…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"ບໍ່ຮູ້ຈັກ"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"ເພື່ອຄວາມປອດໄພຂອງທ່ານ, ແທັບເລັດຂອງທ່ານບໍ່ສາມາດຕິດຕັ້ງແອັບຈາກແຫລ່ງຂໍ້ມູນນີ້ໄດ້."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"ເພື່ອຄວາມປອດໄພຂອງທ່ານ, ໂທລະທັດຂອງທ່ານບໍ່ສາມາດຕິດຕັ້ງແອັບຈາກແຫລ່ງຂໍ້ມູນນີ້ໄດ້."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"ເພື່ອຄວາມປອດໄພຂອງທ່ານ, ໂທລະສັບຂອງທ່ານບໍ່ສາມາດຕິດຕັ້ງແອັບຈາກແຫລ່ງຂໍ້ມູນນີ້ໄດ້."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"ໂທລະສັບ ແລະ ຂໍ້ມູນສ່ວນຕົວຂອງທ່ານອາດຖືກໂຈມຕີໄດ້ໂດຍແອັບທີ່ບໍ່ຮູ້ຈັກ. ໂດຍການຕິດຕັ້ງແອັບນີ້, ແມ່ນທ່ານຍອມຮັບວ່າທ່ານຈະຮັບຜິດຊອບຕໍ່ຄວາມເສຍຫາຍໃດໆກໍຕາມທີ່ເກີດຂຶ້ນຕໍ່ໂທລະທັດຂອງທ່ານ ຫຼື ການສູນເສຍຂໍ້ມູນທີ່ອາດເກີດຈາກການນຳໃຊ້ມັນ."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"ແທັບເລັດ ແລະ ຂໍ້ມູນສ່ວນຕົວຂອງທ່ານອາດຖືກໂຈມຕີໄດ້ໂດຍແອັບທີ່ບໍ່ຮູ້ຈັກ. ໂດຍການຕິດຕັ້ງແອັບນີ້, ແມ່ນທ່ານຍອມຮັບວ່າທ່ານຈະຮັບຜິດຊອບຕໍ່ຄວາມເສຍຫາຍໃດໆກໍຕາມທີ່ເກີດຂຶ້ນຕໍ່ໂທລະທັດຂອງທ່ານ ຫຼື ການສູນເສຍຂໍ້ມູນທີ່ອາດເກີດຈາກການນຳໃຊ້ມັນ."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"ໂທລະທັດ ແລະ ຂໍ້ມູນສ່ວນຕົວຂອງທ່ານອາດຖືກໂຈມຕີໄດ້ໂດຍແອັບທີ່ບໍ່ຮູ້ຈັກ. ໂດຍການຕິດຕັ້ງແອັບນີ້, ແມ່ນທ່ານຍອມຮັບວ່າທ່ານຈະຮັບຜິດຊອບຕໍ່ຄວາມເສຍຫາຍໃດໆກໍຕາມທີ່ເກີດຂຶ້ນຕໍ່ໂທລະທັດຂອງທ່ານ ຫຼື ການສູນເສຍຂໍ້ມູນທີ່ອາດເກີດຈາກການນຳໃຊ້ມັນ."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"ດຳເນີນການຕໍ່"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ການຕັ້ງຄ່າ"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"ກຳລັງຕິດຕັ້ງ/ຖອດຖອນແອັບ Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-lt-television/strings.xml b/packages/PackageInstaller/res/values-lt-television/strings.xml
new file mode 100644
index 0000000..dee6de7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-lt-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Atmesti ir daugiau neklausti"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Tai vėliau galėsite pakeisti skiltyje „Nustatymai &gt; Programos“"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Rodyti sistemos programas"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Programos leidimai"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Programos leidimai"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> leidimai"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Papildomi leidimai"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> leidimai"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-lt-watch/strings.xml b/packages/PackageInstaller/res/values-lt-watch/strings.xml
new file mode 100644
index 0000000..85eebcf
--- /dev/null
+++ b/packages/PackageInstaller/res/values-lt-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Atmesti, daugiau neklausti"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Rodyti sistemos programas"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Negalima pakeisti"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Taip"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Atšaukti"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-lt/strings.xml b/packages/PackageInstaller/res/values-lt/strings.xml
new file mode 100644
index 0000000..79546a9
--- /dev/null
+++ b/packages/PackageInstaller/res/values-lt/strings.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Paketo įdiegimo programa"</string>
+    <string name="next" msgid="3057143178373252333">"Kitas"</string>
+    <string name="install" msgid="5896438203900042068">"Įdiegti"</string>
+    <string name="done" msgid="3889387558374211719">"Atlikta"</string>
+    <string name="cancel" msgid="8360346460165114585">"Atšaukti"</string>
+    <string name="installing" msgid="8613631001631998372">"Diegiama..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Įdiegiama „<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>“…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Programa įdiegta."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Ar norite įdiegti šią programą? Jai bus suteikta prieiga prie:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Ar norite įdiegti šią programą? Jai nereikalinga jokia speciali prieiga."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Ar norite įdiegti šios esamos programos naujinį? Neprarasite esamų duomenų. Atnaujinus programą bus suteikta prieiga prie:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Ar norite įdiegti šios integruotos programos naujinį? Neprarasite esamų duomenų. Atnaujinus programą bus suteikta prieiga prie:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Ar norite įdiegti šios esamos programos naujinį? Neprarasite esamų duomenų. Nereikia jokios specialios prieigos."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Ar norite įdiegti šios integruotos programos naujinį? Neprarasite esamų duomenų. Nereikia jokios specialios prieigos."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Programa neįdiegta."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Paketas užblokuotas ir negali būti įdiegtas."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Programa neįdiegta, nes paketas nesuderinamas su esamu paketu."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Programa neįdiegta, nes ji nesuderinama su planšetiniu kompiuteriu."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Ši programa nesuderinama su jūsų TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Programa neįdiegta, nes ji nesuderinama su telefonu."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Programa neįdiegta, nes panašu, kad paketas netinkamas."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Jūsų planšetiniame kompiuteryje nepavyko įdiegti „<xliff:g id="APP_NAME">%1$s</xliff:g>“."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Nepavyko programos „<xliff:g id="APP_NAME">%1$s</xliff:g>“ įdiegti jūsų TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Jūsų telefone nepavyko įdiegti „<xliff:g id="APP_NAME">%1$s</xliff:g>“."</string>
+    <string name="launch" msgid="4826921505917605463">"Atidaryti"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Jūsų administratorius neleidžia diegti programų, gautų iš nežinomų šaltinių"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Šis naudotojas negali diegti nežinomų programų"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Šiam naudotojui neleidžiama diegti programų"</string>
+    <string name="ok" msgid="3468756155452870475">"Gerai"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Tvarkyti programas"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nėra vietos"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Nepavyko įdiegti „<xliff:g id="APP_NAME">%1$s</xliff:g>“. Atlaisvinkite vietos ir bandykite dar kartą."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Programa nerasta"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Programa nerasta įdiegtų programų sąraše."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Neleidžiama"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Dabartiniam naudotojui neleidžiama atlikti šio pašalinimo veiksmo."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Klaida"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Nepavyko įdiegti programos."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Pašalinti programą"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Pašalinti naujinį"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"„<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>“ yra šios programos dalis:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Ar norite pašalinti šią programą?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Ar norite pašalinti šią programą "<b>"visiems"</b>" naudotojams? Programa ir jos duomenys bus pašalinti iš "<b>"visų"</b>" naudotojų įrenginyje."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Ar norite pašalinti šią naudotojo <xliff:g id="USERNAME">%1$s</xliff:g> programą?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Pakeisti šios programos versiją į gamyklinę? Visi duomenys bus pašalinti."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Pakeisti šios programos versiją į gamyklinę? Visi duomenys bus pašalinti. Tai paveiks visus šio įrenginio naudotojus, įskaitant turinčius darbo profilius."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Vykdomi įdiegimai"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Nepavykę įdiegimai"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Pašalinama..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Pašalinama „<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>“…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Pašalinimas baigtas."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Paketas „<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>“ pašalintas"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Nepavyko pašalinti."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"„<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>“ pašalinimo veiksmas nesėkmingas."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Negalima pašalinti aktyvios įrenginio administravimo programos"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Negalima pašalinti aktyvios naudotojo <xliff:g id="USERNAME">%1$s</xliff:g> įrenginio administravimo programos"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Ši programa reikalinga kai kuriems naudotojams ar kai kuriuose profiliuose ir buvo pašalinta kitur"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ši programa reikalinga jūsų profilyje ir jos negalima pašalinti."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ši programa reikalinga jūsų įrenginio administratoriui ir jos negalima pašalinti."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Tvarkyti įrenginio administravimo programas"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Valdyti naudotojus"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Nepavyko pašalinti „<xliff:g id="APP_NAME">%1$s</xliff:g>“."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Analizuojant paketą iškilo problema."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Naujiena"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Visi"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privatumas"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Prieiga prie įreng."</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Šiam naujiniui nereikalingi nauji leidimai."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Atmesti"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Daugiau informacijos"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Vis tiek atmesti"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> iš <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Leisti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Visada leisti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Tik naudojant programą"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Visada"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Atmesti ir daugiau neklausti"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"Išjungta leidimų: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"visi leidimai išjungti"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"nė vienas leidimas neišjungtas"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Leisti"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Programos"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Programos leidimai"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Daugiau neklausti"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Nėra jokių leidimų"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Papildomi leidimai"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Atidaryti programos informaciją"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one">Dar <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">Dar <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Dar <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Dar <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ši programa skirta senesnės versijos „Android“. Uždraudus leidimą ji gali nebeveikti kaip numatyta."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"atlieka nežinomą veiksmą"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Leidžiama programų: <xliff:g id="COUNT_0">%1$d</xliff:g> iš <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Rodyti sistemą"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Slėpti sistemą"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nėra jokių programų"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Vietovės nustatymai"</string>
+    <string name="location_warning" msgid="8778701356292735971">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ yra šio įrenginio vietovės paslaugų teikėjas. Vietovės pasiekiamumą galima keisti vietovės nustatymuose."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Jei uždrausite šį leidimą, pagrindinės įrenginio funkcijos gali nebeveikti, kaip numatyta."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Reikalaujama pagal politikos nuostatas"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Prieiga fone išjungta pagal politiką"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Prieiga fone įgalinta pagal politiką"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Prieiga priekiniame plane įgalinta pagal politiką"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Valdo administratorius"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Visada"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Tik naudojant programą"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Niekada"</string>
+    <string name="loading" msgid="7811651799620593731">"Įkeliama..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Visi leidimai"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Kitos programos galimybės"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Leidimo užklausa"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Aptikta ekrano perdanga"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Jei norite pakeisti šį leidimo nustatymą, pirmiausia turite išjungti ekrano perdangą skiltyje „Nustatymai &gt; Programos“"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Atidaryti nustatymus"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Diegimo / pašalinimo veiksmai nepalaikomi sistemoje „Wear“."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Pasirinkite, ką norite leisti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Programa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; buvo atnaujinta. Pasirinkite, ką norite leisti šiai programai pasiekti."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Atšaukti"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Tęsti"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nauji leidimai"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Dabartiniai leidimai"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Programa pateikiama etapais…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Nežinoma"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Saugos sumetimais planšetiniame kompiuteryje neleidžiama diegti nežinomų programų iš šio šaltinio."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Saugos sumetimais TV neleidžiama diegti nežinomų programų iš šio šaltinio."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Saugos sumetimais telefone neleidžiama diegti nežinomų programų iš šio šaltinio."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefonas ir asmeniniai duomenys labiau pažeidžiami įdiegus nežinomų programų. Įdiegdami šią programą sutinkate, kad patys esate atsakingi už žalą telefonui arba prarastus duomenis dėl šios programos naudojimo."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Planšetinis kompiuteris ir asmeniniai duomenys labiau pažeidžiami įdiegus nežinomų programų. Įdiegdami šią programą sutinkate, kad patys esate atsakingi už žalą planšetiniam kompiuteriui arba prarastus duomenis dėl šios programos naudojimo."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"TV ir asmeniniai duomenys labiau pažeidžiami įdiegus nežinomų programų. Įdiegdami šią programą sutinkate, kad patys esate atsakingi už žalą TV arba prarastus duomenis dėl šios programos naudojimo."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Tęsti"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Nustatymai"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Įdiegiamos / pašalinamos „Wear“ program."</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-lv-television/strings.xml b/packages/PackageInstaller/res/values-lv-television/strings.xml
new file mode 100644
index 0000000..f01dfd2
--- /dev/null
+++ b/packages/PackageInstaller/res/values-lv-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Noraidīt un vairs nejautāt"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Vēlāk varat veikt izmaiņas sadaļā Iestatījumi &gt; Lietotnes."</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>. no <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Rādīt sistēmas lietotnes"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Lietotņu atļaujas"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Lietotņu atļaujas"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Lietotnes <xliff:g id="PERMISSION">%1$s</xliff:g> atļaujas"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Papildu atļaujas"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Lietotnes <xliff:g id="PERMISSION">%1$s</xliff:g> atļaujas"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-lv-watch/strings.xml b/packages/PackageInstaller/res/values-lv-watch/strings.xml
new file mode 100644
index 0000000..29aef48
--- /dev/null
+++ b/packages/PackageInstaller/res/values-lv-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Neatļaut un vairs nejautāt"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>. no <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Rādīt sistēmas lietotnes"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nevar mainīt"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Jā"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Atcelt"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-lv/strings.xml b/packages/PackageInstaller/res/values-lv/strings.xml
new file mode 100644
index 0000000..40ddf74
--- /dev/null
+++ b/packages/PackageInstaller/res/values-lv/strings.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Pakotnes instalēšanas programma"</string>
+    <string name="next" msgid="3057143178373252333">"Tālāk"</string>
+    <string name="install" msgid="5896438203900042068">"Instalēt"</string>
+    <string name="done" msgid="3889387558374211719">"Gatavs"</string>
+    <string name="cancel" msgid="8360346460165114585">"Atcelt"</string>
+    <string name="installing" msgid="8613631001631998372">"Notiek instalēšana..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Notiek pakotnes <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> instalēšana…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Lietotne ir instalēta."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Vai vēlaties instalēt šo lietojumprogrammu? Tā iegūs piekļuvi:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Vai vēlaties instalēt šo lietojumprogrammu? Tai nav nepieciešamas īpašas piekļuves atļaujas."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Vai vēlaties instalēt šīs lietojumprogrammas atjauninājumu? Esošie dati netiks zaudēti. Atjauninātajai lietojumprogrammai būs piekļuve:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Vai vēlaties instalēt šīs iebūvētās lietojumprogrammas atjauninājumu? Esošie dati netiks zaudēti. Atjauninātajai lietojumprogrammai būs piekļuve:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Vai vēlaties instalēt šīs lietojumprogrammas atjauninājumu? Esošie dati netiks zaudēti. Tam nav nepieciešama īpaša piekļuves atļauja."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Vai vēlaties instalēt šīs iebūvētās lietojumprogrammas atjauninājumu? Esošie dati netiks zaudēti. Tam nav nepieciešama īpaša piekļuves atļauja."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Lietotne nav instalēta."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Pakotnes instalēšana tika bloķēta."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Lietotne netika instalēta, jo rodas pakotnes konflikts ar esošo pakotni."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Lietotne netika instalēta, jo tā nav saderīga ar jūsu planšetdatoru."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Šī lietotne nav saderīga ar jūsu televizoru."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Lietotne netika instalēta, jo tā nav saderīga ar jūsu tālruni."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Lietotne netika instalēta, jo šķiet, ka pakotne nav derīga."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Lietotni <xliff:g id="APP_NAME">%1$s</xliff:g> nevarēja instalēt planšetdatorā."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Lietotni <xliff:g id="APP_NAME">%1$s</xliff:g> nevarēja instalēt jūsu televizorā."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Lietotni <xliff:g id="APP_NAME">%1$s</xliff:g> nevarēja instalēt tālrunī."</string>
+    <string name="launch" msgid="4826921505917605463">"Atvērt"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Jūsu administrators neļauj instalēt lietotnes, kas iegūtas no nezināmiem avotiem."</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Šis lietotājs nevar instalēt lietotnes, kas iegūtas no nezināmiem avotiem."</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Šim lietotājam nav atļauts instalēt lietotnes"</string>
+    <string name="ok" msgid="3468756155452870475">"Labi"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Pārvaldīt lietotnes"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nav brīvas vietas"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Lietotni <xliff:g id="APP_NAME">%1$s</xliff:g> nevarēja instalēt. Atbrīvojiet vietu un mēģiniet vēlreiz."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Lietotne nav atrasta"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Šī lietotne netika atrasta instalēto lietotņu sarakstā."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Nav atļauts"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Pašreizējam lietotājam nav atļauts veikt atinstalēšanu."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Kļūda"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Nevarēja atinstalēt lietotni."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Atinstalēt lietotni"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Atinstalēt atjauninājumu"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ir daļa no šādas lietotnes:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Vai vēlaties atinstalēt šo lietotni?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Vai vēlaties atinstalēt šo lietotni "<b>"visiem"</b>" lietotājiem? Šī lietojumprogramma un tās dati tiks noņemti no "<b>"visiem"</b>" ierīces lietotāju kontiem."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Vai vēlaties atinstalēt šo lietotni lietotājam <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Vai aizstāt šo lietotni ar rūpnīcas versiju? Visi dati tiks noņemti."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Vai aizstāt šo lietotni ar rūpnīcas versiju? Visi dati tiks noņemti. Tas ietekmēs visu šīs ierīces lietotāju (arī to lietotāju, kuriem ir darba profili) datus."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Pašlaik veiktie atinstalēšanas gadījumi"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Neizdevušies atinstalēšanas gadījumi"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Notiek atinstalēšana..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Notiek lietotnes <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> atinstalēšana…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Atinstalēšana ir pabeigta."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Lietotne <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ir atinstalēta"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Atinstalēšana neizdevās."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Lietotnes <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> atinstalēšana nebija sekmīga."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Neizdevās atinstalēt aktīvas ierīces administratora lietotnes."</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Neizdevās atinstalēt aktīvas ierīces administratora lietotni <xliff:g id="USERNAME">%1$s</xliff:g>."</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Šī lietotne ir nepieciešama dažiem lietotājiem vai profiliem un tika atinstalēta citiem"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Šī lietotne ir nepieciešama jūsu profilam, tāpēc to nevar atinstalēt."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ierīces administrators ir noteicis, ka lietotne ir obligāta un to nevar atinstalēt."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Pārvaldīt ierīces administratora lietotnes"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Pārvaldīt lietotājus"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Lietotni <xliff:g id="APP_NAME">%1$s</xliff:g> nevarēja atinstalēt."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Parsējot pakotni, radās problēma."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Jauna!"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Visas"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Konfidencialitāte"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Piekļuve ierīcei"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Šim atjauninājumam nav nepieciešamas jaunas atļaujas."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Neatļaut"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Plašāka informācija"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Tomēr noraidīt"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>. no <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Vai vienmēr atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Tikai izmantojot lietotni"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Vienmēr"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Noraidīt un vairs nejautāt"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> atspējotas"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"visas atspējotas"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"neviena nav atspējota"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Atļaut"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Lietotnes"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Lietotnes atļaujas"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Turpmāk vairs nejautāt"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Nav atļauju"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Papildu atļaujas"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Atvērt lietotnes informāciju"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="zero">Vēl <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Vēl <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Vēl <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Šī lietotne ir paredzēta vecākai Android versijai. Ja noraidīsiet atļauju, iespējams, netiks nodrošināta paredzētā lietotnes darbība."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"veikt nezināmu darbību"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Atļautas <xliff:g id="COUNT_0">%1$d</xliff:g> lietotnes no <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Rādīt sistēmas lietotnes"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Slēpt sistēmas lietotnes"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nav lietotņu"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Atrašanās vietas iestatījumi"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> nodrošina šai ierīcei atrašanās vietu pakalpojumus. Piekļuves iestatījumus atrašanās vietas datiem var mainīt atrašanās vietas iestatījumos."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ja nepiešķirsiet šo atļauju, ierīces pamatfunkcijas, iespējams, vairs nedarbosies, kā paredzēts."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Īstenota saskaņā ar politiku"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Piekļuve fonā atspējota saskaņā ar politiku"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Piekļuve fonā iespējota saskaņā ar politiku"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Piekļuve priekšplānā iespējota saskaņā ar politiku"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Kontrolē administrators"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Vienmēr"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Tikai izmantojot lietotni"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nekad"</string>
+    <string name="loading" msgid="7811651799620593731">"Notiek ielāde..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Visas atļaujas"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Citas lietotnes atļaujas"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Atļaujas pieprasījums"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Konstatēts ekrāna pārklājums"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Lai mainītu šo atļaujas iestatījumu, vispirms sadaļā “Iestatījumi un lietotnes” izslēdziet ekrāna pārklājumu."</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Atvērt iestatījumus"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear ierīcē netiek atbalstīta instalēšana/atinstalēšana"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Izvēlieties, kādas piekļuves atļaujas piešķirt lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Lietotne &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ir atjaunināta. Izvēlieties, kādas piekļuves atļaujas tai piešķirt."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Atcelt"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Turpināt"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Jaunas atļaujas"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Pašreizējās atļaujas"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Lietotne tiek izstādīta…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Nezināms"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Drošības nolūkos jūsu planšetdatorā nedrīkst instalēt no šī avota iegūtas nezināmas lietotnes."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Drošības nolūkos jūsu televizorā nedrīkst instalēt no šī avota iegūtas nezināmas lietotnes."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Drošības nolūkos jūsu tālrunī nedrīkst instalēt no šī avota iegūtas nezināmas lietotnes."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Jūsu tālruņa un personas dati ir neaizsargātāki pret uzbrukumiem no nezināmām lietotnēm. Instalējot šo lietotni, jūs piekrītat, ka esat atbildīgs par tālruņa bojājumiem vai datu zudumu, kas var rasties lietotnes dēļ."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Jūsu planšetdatora un personas dati ir neaizsargātāki pret uzbrukumiem no nezināmām lietotnēm. Instalējot šo lietotni, jūs piekrītat, ka esat atbildīgs par planšetdatora bojājumiem vai datu zudumu, kas var rasties lietotnes dēļ."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Jūsu televizora un personas dati ir neaizsargātāki pret uzbrukumiem no nezināmām lietotnēm. Instalējot šo lietotni, jūs piekrītat, ka esat atbildīgs par televizora bojājumiem vai datu zudumu, kas var rasties lietotnes dēļ."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Turpināt"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Iestatījumi"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear lietotņu instalēšana/atinstalēšana"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-mk-television/strings.xml b/packages/PackageInstaller/res/values-mk-television/strings.xml
new file mode 100644
index 0000000..bb3ea92
--- /dev/null
+++ b/packages/PackageInstaller/res/values-mk-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Одбиј и не прашувај повторно"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Може да го промените ова подоцна во Поставки &gt; Апликации"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Прикажи ги системските апликации"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Дозволи за апликацијата"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Дозволи за апликацијата"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Дозволи за <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Дополнителни дозволи"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Дозволи за <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-mk-watch/strings.xml b/packages/PackageInstaller/res/values-mk-watch/strings.xml
new file mode 100644
index 0000000..5906f56
--- /dev/null
+++ b/packages/PackageInstaller/res/values-mk-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Одбиј, не прашувај повторно"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Прикажи ги системските апликации"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Не може да се смени"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Да"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Откажи"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-mk/strings.xml b/packages/PackageInstaller/res/values-mk/strings.xml
new file mode 100644
index 0000000..8cf208e
--- /dev/null
+++ b/packages/PackageInstaller/res/values-mk/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Инсталатор на пакет"</string>
+    <string name="next" msgid="3057143178373252333">"Следно"</string>
+    <string name="install" msgid="5896438203900042068">"Инсталирај"</string>
+    <string name="done" msgid="3889387558374211719">"Готово"</string>
+    <string name="cancel" msgid="8360346460165114585">"Откажи"</string>
+    <string name="installing" msgid="8613631001631998372">"Се инсталира..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Се инсталира <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Апликацијата е инсталирана."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Дали сакате да ја инсталирате оваа апликација? Ќе добие пристап до:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Дали сакате да ја инсталирате оваа апликација? Не бара никаков посебен пристап."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Дали сакате да инсталирате надградба на оваа постоечка апликација? Вашите постоечки податоци нема да се изгубат. Ажурираната апликација ќе добие пристап до:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Дали сакате да инсталирате надградба на оваа вградена апликација? Вашите постоечки податоци нема да се изгубат. Ажурираната апликација ќе добие пристап до:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Дали сакате да инсталирате надградба на оваа постоечка апликација? Вашите постоечки податоци нема да се изгубат. Таа не бара никаков посебен пристап."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Дали сакате да инсталирате надградба на оваа вградена апликација? Вашите постоечки податоци нема да се изгубат. Таа не бара никаков посебен пристап."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Апликацијата не е инсталирана."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Инсталирањето на пакетот е блокирано."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Апликација што не е инсталирана како пакет е во конфликт со постоен пакет."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Апликација што не е инсталирана како апликација не е компатибилна со вашиот таблет."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Оваа апликација не е компатибилна со вашиот телевизор."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Апликација што не е инсталирана како апликација не е компатибилна со вашиот телефон."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Апликација што не е инсталирана како пакет се чини дека е неважечка."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> не можеше да се инсталира на вашиот таблет."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> не може да се инсталира на вашиот телевизор."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> не можеше да се инсталира на вашиот телефон."</string>
+    <string name="launch" msgid="4826921505917605463">"Отвори"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Вашиот администратор не дозволува инсталација на апликации добиени од непознати извори"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Корисников не може да инсталира непознати апликации"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"На корисников не му е дозволено да инсталира апликации"</string>
+    <string name="ok" msgid="3468756155452870475">"Во ред"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Управувај со апликации"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Нема простор"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> не можеше да се инсталира. Ослободете простор и обидете се повторно."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Апликацијата не е пронајдена"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Апликацијата не е пронајдена во списокот инсталирани апликации."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Не е дозволено"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Тековниот корисник нема дозвола да ја изведе деинсталацијава."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Грешка"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Не можеше да се деинсталира апликацијата."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Деинсталирај апликација"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Деинсталирај ажурирање"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> е дел од следната апликација:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Дали сакате да ја деинсталирате оваа апликација?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Дали сакате да ја деинсталирате оваа апликација за "<b>"сите"</b>" корисници? Апликацијата и нејзините податоци ќе се отстранат од "<b>"сите"</b>" корисници на уредот."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Дали сакате да ја деинсталирате апликацијава за корисникот <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Сакате да ја замените оваа апликација со фабричката верзија? Сите податоци ќе се отстранат."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Сакате да ја замените оваа апликација со фабричката верзија? Сите податоци ќе се отстранат. Тоа важи за сите корисници на овој уред, вклучувајќи ги и тие со работни профили."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Деинсталации во тек"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Неуспешни деинсталации"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Се деинсталира..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Се деинсталира <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Деинсталирањето заврши."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> е деинсталиран"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Деинсталирањето е неуспешно."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Деинсталирањето на <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> е неуспешно."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Не може да се деинсталира активна апликација на администраторот на уредот"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Не може да се деинсталира активна апликација на администраторот на уредот за <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Апликацијата е неопходна за некои корисници или профили, а за другите е деинсталирана"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Апликацијата е потребна за вашиот профил и не може да се деинсталира."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Апликацијата ја бара администраторот на вашиот уред и не може да се деинсталира."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Управувај со аплик. за администраторот на уредот"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Управувај со корисници"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> не може да се деинсталира."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Настана проблем при разложување на пакетот."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Ново"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Сè"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Приватност"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Пристап кон уредот"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Ова ажурирање не бара нови дозволи."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Одбиј"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Повеќе информации"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Сепак одбиј"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> од <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Дозволете &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Дали секогаш да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Само додека се користи апликацијата"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Секогаш"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Одбиј и не прашувај повторно"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"Оневозможени се <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"сите се оневозможени"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ниедна не е оневозможена"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Овозможи"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Апликации"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Дозволи за апликацијата"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Не прашувај повторно"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Нема дозволи"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Дополнителни дозволи"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Отвора информации за апликација"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Оваа апликација е дизајнирана за постара верзија на Android. Одбивањето на дозволата може да предизвика веќе да не функционира како што треба."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"изврши непознато дејство"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Дозволени се <xliff:g id="COUNT_0">%1$d</xliff:g> од <xliff:g id="COUNT_1">%2$d</xliff:g> апликации"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Прикажи систем"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Сокриј систем"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Нема апликации"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Поставки за локација"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> е давател на услуги според локација за овој уред. Пристапот до локацијата може да се смени од Поставките за локација."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ако ја одбиете оваа дозвола, основните функции на вашиот уред можеби веќе нема да функционираат како што треба."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Наложено од политиката"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Пристапот од заднина е оневозможен со правилото"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Пристапот од заднина е овозможен со правилото"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Пристапот од преден план е овозможен со правилото"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Контролирано од администраторот"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Секогаш"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Само додека се користи аплик."</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Никогаш"</string>
+    <string name="loading" msgid="7811651799620593731">"Се вчитува..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Сите дозволи"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Други можности на апликацијата"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Барање дозвола"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Откривме преклопување на екранот"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"За да ја измените оваа поставка за дозвола, прво мора да го исклучите преклопувањето на екранот од Поставки &gt; Апликации"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Отвори поставки"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Дејствата инсталирај/деинсталирај не се поддржани на Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Изберете што да ѝ се овозможи на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; за пристап"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; е ажурирана. Изберете што да ѝ се овозможи на оваа апликација за пристап."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Откажи"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Продолжи"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Нови дозволи"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Тековни дозволи"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Апликацијата се поставува…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Непознато"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"За ваша безбедност, таблетот нема дозвола за инсталирање непознати апликации од изворов."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"За ваша безбедност, телевизорот нема дозвола за инсталирање непознати апликации од изворов."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"За ваша безбедност, телефонот нема дозвола за инсталирање непознати апликации од изворов."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Телефонот и личните податоци се поподложни на напади од непознати апликации. Ако ја инсталирате апликацијава, се согласувате дека сте одговорни за каква било штета на телефонот или губењето податоци што може да произлезат од нејзиното користење."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Таблетот и личните податоци се поподложни на напади од непознати апликации. Ако ја инсталирате апликацијава, се согласувате дека сте одговорни за каква било штета на таблетот или губењето податоци што може да произлезат од нејзиното користење."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Телевизорот и личните податоци се поподложни на напади од непознати апликации. Ако ја инсталирате апликацијава, се согласувате дека сте одговорни за каква било штета на телевизорот или губењето податоци што може да произлезат од нејзиното користење."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Продолжи"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Поставки"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Се инсталираат/деинсталираат аплик. Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ml-television/strings.xml b/packages/PackageInstaller/res/values-ml-television/strings.xml
new file mode 100644
index 0000000..5ede01f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ml-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"നിരസിക്കുക, വീണ്ടും ആവശ്യപ്പെടരുത്"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"പിന്നീട് നിങ്ങൾക്കിത് ക്രമീകരണവും ആപ്സും എന്നതിൽ മാറ്റാനാകും"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"സിസ്റ്റം ആപ്‌സ് കാണിക്കുക"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"ആപ്പ് അനുമതികൾ"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"ആപ്പ് അനുമതികൾ"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> അനുമതികൾ"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"അധിക അനുമതികൾ"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> അനുമതികൾ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ml-watch/strings.xml b/packages/PackageInstaller/res/values-ml-watch/strings.xml
new file mode 100644
index 0000000..13e3876
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ml-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"നിരസിക്കുക, വീണ്ടും ആവശ്യപ്പെടരുത്"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"സിസ്റ്റം ആപ്‌സ് കാണിക്കുക"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"മാറ്റാനാവില്ല"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"അതെ"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"റദ്ദാക്കുക"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ml/strings.xml b/packages/PackageInstaller/res/values-ml/strings.xml
new file mode 100644
index 0000000..9fadd24
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ml/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"പാക്കേജ് ഇൻസ്‌റ്റാളർ"</string>
+    <string name="next" msgid="3057143178373252333">"അടുത്തത്"</string>
+    <string name="install" msgid="5896438203900042068">"ഇൻസ്റ്റാളുചെയ്യുക"</string>
+    <string name="done" msgid="3889387558374211719">"പൂർത്തിയായി"</string>
+    <string name="cancel" msgid="8360346460165114585">"റദ്ദാക്കുക"</string>
+    <string name="installing" msgid="8613631001631998372">"ഇൻസ്റ്റാൾ ചെയ്യുന്നു..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ഇൻസ്‌റ്റാൾ ചെയ്യുന്നു…"</string>
+    <string name="install_done" msgid="3682715442154357097">"അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്‌തു."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"ഈ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്യണോ? ഇതിന് ഇവയിലേക്ക് ആക്‌സസ്സ് ലഭിക്കും:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"നിങ്ങൾക്ക് ഈ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്യണോ? ഇത് പ്രത്യേക ആക്‌സസ്സൊന്നും ആവശ്യമില്ല."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"നിലവിലുള്ള ഈ അപ്ലിക്കേഷന് ഒരു അപ്‌ഡേറ്റ് ഇൻസ്റ്റാളുചെയ്യണോ? നിങ്ങളുടെ നിലവിലെ ഡാറ്റ നഷ്‌ടപ്പെടില്ല. അപ്‌ഡേറ്റുചെയ്‌ത അപ്ലിക്കേഷന് ഇവയിലേക്ക് ആക്‌സസ്സ് ലഭിക്കും:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"ഈ അന്തർ നിർമ്മിത അപ്ലിക്കേഷന് ഒരു അപ്‌ഡേറ്റ് ഇൻസ്റ്റാളുചെയ്യണോ? നിങ്ങളുടെ നിലവിലെ ഡാറ്റ നഷ്‌ടപ്പെടില്ല. അപ്‌ഡേറ്റുചെയ്‌ത അപ്ലിക്കേഷന് ഇവയിലേക്ക് ആക്‌സസ്സ് ലഭിക്കും:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"നിലവിലുള്ള ഈ അപ്ലിക്കേഷന് ഒരു അപ്‌ഡേറ്റ് ഇൻസ്റ്റാളുചെയ്യണോ? നിങ്ങളുടെ നിലവിലെ ഡാറ്റ നഷ്‌ടപ്പെടില്ല. ഇതിന് പ്രത്യേക ആക്‌സസ്സൊന്നും ആവശ്യമില്ല."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"ഈ അന്തർ നിർമ്മിത അപ്ലിക്കേഷന് ഒരു അപ്‌ഡേറ്റ് ഇൻസ്റ്റാളുചെയ്യണോ? നിങ്ങളുടെ നിലവിലെ ഡാറ്റ നഷ്‌ടപ്പെടില്ല. ഇതിന് പ്രത്യേക ആക്‌സസ്സൊന്നും ആവശ്യമില്ല."</string>
+    <string name="install_failed" msgid="6579998651498970899">"അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്‌തില്ല."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ഇൻസ്റ്റാൾ ചെയ്യുന്നതിൽ നിന്നും പാക്കേജിനെ തടഞ്ഞു."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"നിലവിലുള്ള ഒരു പാക്കേജുമായി പാക്കേജിന് പൊരുത്തക്കേടുള്ളതിനാൽ ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്തില്ല."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"നിങ്ങളുടെ ടാബ്‌ലെറ്റുമായി അനുയോജ്യത ഇല്ലാത്തതിനാൽ ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്തില്ല."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"നിങ്ങളുടെ ടിവിയ്‌ക്ക് ഈ ആപ്പ് അനുയോജ്യമല്ല."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"നിങ്ങളുടെ ഫോണുമായി അനുയോജ്യത ഇല്ലാത്തതിനാൽ ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്തില്ല."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"പാക്കേജ് അസാധുവായി കാണപ്പെടുന്നതിനാൽ ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്തില്ല."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ <xliff:g id="APP_NAME">%1$s</xliff:g> ഇൻസ്റ്റാളുചെയ്യാനായില്ല."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g>, നിങ്ങളുടെ ടിവിയിൽ ഇൻസ്റ്റാളുചെയ്യാനായില്ല."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"നിങ്ങളുടെ ഫോണിൽ <xliff:g id="APP_NAME">%1$s</xliff:g> ഇൻസ്റ്റാളുചെയ്യാനായില്ല."</string>
+    <string name="launch" msgid="4826921505917605463">"തുറക്കുക"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"അജ്ഞാത ഉറവിടങ്ങളിൽ നിന്ന് സ്വന്തമാക്കിയ ആപ്പുകൾ ഇൻസ്റ്റാൾ ചെയ്യാൻ നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്റർ അനുവദിക്കുന്നില്ല"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"ഈ ഉപയോക്താവിന്, തിരിച്ചറിയാനാകാത്ത ആപ്പുകൾ ഇൻസ്റ്റാൾ ചെയ്യാൻ കഴിയില്ല"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"ആപ്പുകൾ ഇൻസ്റ്റാൾ ചെയ്യുന്നതിന് ഈ ഉപയോക്താവിന് അനുവാദമില്ല"</string>
+    <string name="ok" msgid="3468756155452870475">"ശരി"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"അപ്ലിക്കേഷനുകൾ നിയന്ത്രിക്കുക"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"പരിധി കഴിഞ്ഞു"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> ഇൻസ്റ്റാളുചെയ്യാനായില്ല. കുറച്ച് ഇടം ശൂന്യമാക്കിയതിനുശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"അപ്ലിക്കേഷൻ കണ്ടെത്തിയില്ല"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ഇൻസ്റ്റാളുചെയ്‌ത അപ്ലിക്കേഷനുകളുടെ ലിസ്റ്റിൽ അപ്ലിക്കേഷൻ കണ്ടെത്തിയില്ല."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"അനുവദിച്ചിട്ടില്ല"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"ഈ അൺഇൻസ്റ്റലേഷൻ നിർവഹിക്കാൻ നിലവിലെ ഉപയോക്താവിനെ അനുവദിച്ചിട്ടില്ല."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"പിശക്"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"ആപ്പ് അൺഇൻസ്റ്റാൾ ചെയ്യാൻ കഴിഞ്ഞില്ല."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"അപ്ലിക്കേഷൻ അൺഇൻസ്റ്റാളുചെയ്യുക"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"അപ്‌ഡേറ്റ് അൺഇൻസ്റ്റാളുചെയ്യുക"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> എന്നത് ഇനിപ്പറയുന്ന അപ്ലിക്കേഷന്റെ ഭാഗമാണ്:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"ഈ അപ്ലിക്കേഷൻ അൺഇൻസ്റ്റാളുചെയ്യണോ?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"ഈ അപ്ലിക്കേഷൻ "<b>"എല്ലാ"</b>" ഉപയോക്താക്കൾക്കുമായി അൺഇൻസ്റ്റാളുചെയ്യണോ? ഉപകരണത്തിലെ "<b>"എല്ലാ"</b>" ഉപയോക്താക്കളിൽ നിന്നും അപ്ലിക്കേഷനും അതിന്റെ ഡാറ്റയും നീക്കംചെയ്യപ്പെടും."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"<xliff:g id="USERNAME">%1$s</xliff:g> എന്ന ഉപയോക്താവിനായി ഈ അപ്ലിക്കേഷൻ അൺഇൻസ്റ്റാളുചെയ്യണോ?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ഫാക്ടറി പതിപ്പ് ഉപയോഗിച്ച് ഈ ആപ്പ് മാറ്റിസ്ഥാപിക്കണോ? എല്ലാ ഡാറ്റയും നീക്കംചെയ്യപ്പെടും."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ഫാക്ടറി പതിപ്പ് ഉപയോഗിച്ച് ഈ ആപ്പ് മാറ്റിസ്ഥാപിക്കണോ? എല്ലാ ഡാറ്റയും നീക്കംചെയ്യപ്പെടും. ഔദ്യോഗിക പ്രൊഫൈലുകൾ ഉള്ളവർ ഉൾപ്പെടെ, ഈ ഉപകരണത്തിന്റെ എല്ലാ ഉപയോക്താക്കളെയും ഇത് ബാധിക്കുന്നു."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"അൺ ഇൻസ്‌റ്റാൾ ചെയ്‌തുകൊണ്ടിരിക്കുന്നവ"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"അൺ ഇൻസ്‌റ്റാൾ ചെയ്യാൻ കഴിയാഞ്ഞവ"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"അൺഇൻസ്‌‌റ്റാൾ ചെയ്യുന്നു..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> അൺഇൻസ്റ്റാൾ ചെയ്യുന്നു…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"അൺഇൻസ്റ്റാളുചെയ്യൽ പൂർത്തിയായി."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> അൺഇൻസ്‌റ്റാൾ ചെയ്‌തു"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"അൺഇൻസ്റ്റാളുചെയ്തു."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> അൺഇൻസ്റ്റാൾ ചെയ്യൽ പരാജയം."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"സജീവ ഉപകരണ അഡ്‌മിൻ ആപ്പ് അൺഇൻസ്റ്റാൾ ചെയ്യാൻ കഴിയില്ല"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> എന്ന ഉപയോക്താവിന്റെ സജീവ ഉപകരണ അഡ്‌മിൻ ആപ്പ് അൺഇൻസ്റ്റാൾ ചെയ്യാൻ കഴിയില്ല"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"ചില ഉപയോക്താക്കൾക്കോ പ്രൊഫൈലുകൾക്കോ ഈ ആപ്പ് ആവശ്യമാണ്, മറ്റുള്ളവർക്ക് ഈ ആപ്പ് അൺഇൻസ്റ്റാൾ ചെയ്തിരിക്കുന്നു"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലിന് ഈ ആപ്പ് ആവശ്യമുള്ളതിനാൽ അത് അൺ‌ഇൻസ്റ്റാൾ ചെയ്യാനാവില്ല."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"നിങ്ങളുടെ ഉപകരണ അഡ്മിനിസ്ട്രേറ്ററിന് ഈ അപ്ലിക്കേഷൻ ആവശ്യമുള്ളതിനാൽ ഇത് അൺഇൻസ്റ്റാൾ ചെയ്യാനാവില്ല."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"ഉപകരണ അഡ്‌മിൻ ആപ്പുകളെ മാനേജുചെയ്യുക"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ഉപയോക്താക്കളെ മാനേജുചെയ്യുക"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> അൺഇൻസ്റ്റാളുചെയ്യാനായില്ല."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"പാക്കേജ് പാഴ്‌സുചെയ്യുന്നതിൽ ഒരു പ്രശ്‌നമുണ്ടായിരുന്നു."</string>
+    <string name="newPerms" msgid="6039428254474104210">"പുതിയത്"</string>
+    <string name="allPerms" msgid="1024385515840703981">"എല്ലാം"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"സ്വകാര്യത"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"ഉപകരണ ആക്‌സസ്സ്"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"ഈ അപ്‌ഡേറ്റിന് പുതിയ അനുമതികളൊന്നും ആവശ്യമില്ല."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"നിരസിക്കുക"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"കൂടുതൽ‍ വിവരങ്ങള്‍"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"എന്തായാലും നിരസിക്കുക"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"<xliff:g id="ACTION">%2$s</xliff:g> &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ എല്ലായ്‌പ്പോഴും <xliff:g id="ACTION">%2$s</xliff:g> എന്നതിന് അനുവദിക്കണമോ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"ആപ്പ് ഉപയോഗിക്കുമ്പോൾ മാത്രം"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"എല്ലായ്‌പ്പോഴും"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"നിരസിക്കുക, വീണ്ടും ആവശ്യപ്പെടരുത്"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> പ്രവർത്തനരഹിതമാക്കി"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"എല്ലാം പ്രവർത്തനരഹിതമാക്കി"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ഒന്നും പ്രവർത്തനരഹിതമാക്കിയിട്ടില്ല"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"അനുവദിക്കുക"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"ആപ്സ്"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"ആപ്പ് അനുമതികൾ"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"വീണ്ടും ആവശ്യപ്പെടരുത്"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"അനുമതികൾ ഇല്ല"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"അധിക അനുമതികൾ"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"ആപ്പ് വിവരം തുറക്കുക"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"ഈ ആപ്പ് Android-ന്റെ പഴയ പതിപ്പിനായാണ് രൂപകൽപ്പന ചെയ്‌തിരിക്കുന്നത്. അനുമതി നിരസിക്കുന്നത് തുടർന്ന് ഉദ്ദേശിച്ചവിധം പ്രവർത്തിക്കാതിരിക്കാനിടയാക്കുന്നു."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ഒരു അജ്ഞാതപ്രവർത്തനം നടത്തുക"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> / <xliff:g id="COUNT_1">%2$d</xliff:g> ആപ്പുകൾ അനുവദനീയം"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"സിസ്റ്റം കാണിക്കുക"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"സിസ്റ്റം മറയ്‌ക്കുക"</string>
+    <string name="no_apps" msgid="1965493419005012569">"ആപ്സ് ഒന്നുമില്ല"</string>
+    <string name="location_settings" msgid="1774875730854491297">"ലൊക്കേഷൻ ക്രമീകരണം"</string>
+    <string name="location_warning" msgid="8778701356292735971">"ഈ ഉപകരണത്തിനായുള്ള ലൊക്കേഷൻ സേവനങ്ങളുടെ ദാതാവ് <xliff:g id="APP_NAME">%1$s</xliff:g> ആണ്. ലൊക്കേഷൻ ക്രമീകരണത്തിൽ നിന്ന് ലൊക്കേഷൻ ആക്സസ് പരിഷ്കരിക്കാവുന്നതാണ്."</string>
+    <string name="system_warning" msgid="7103819124542305179">"നിങ്ങൾ ഈ അനുമതി നിഷേധിക്കുന്നുവെങ്കിൽ, നിങ്ങളുടെ ഉപകരണത്തിന്റെ അടിസ്ഥാന ഫീച്ചറുകൾ ഉദ്ദേശിച്ചത് പോലെ തുടർന്ന് പ്രവർത്തിച്ചേക്കില്ല."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"നയം മുഖേനെ നടപ്പിലാക്കിയത്"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"നയം അനുസരിച്ച് ബാക്ക്‌ഗ്രൗണ്ട് ആക്‌സസ് പ്രവർത്തനരഹിതമാക്കി"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"നയം അനുസരിച്ച് ബാക്ക്‌ഗ്രൗണ്ട് ആക്‌സസ് പ്രവർത്തനക്ഷമമാക്കി"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"നയം അനുസരിച്ച് ഫോർഗ്രൗണ്ട് ആക്‌സസ് പ്രവർത്തനക്ഷമമാക്കി"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"അഡ്‌മിൻ നിയന്ത്രിക്കുന്നത്"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"എല്ലായ്‌പ്പോഴും"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"ആപ്പ് ഉപയോഗിക്കുമ്പോൾ മാത്രം"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"ഒരിക്കലും"</string>
+    <string name="loading" msgid="7811651799620593731">"ലോഡുചെയ്യുന്നു..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"എല്ലാ അനുമതികളും"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"മറ്റ് ആപ്പ് ശേഷികൾ"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"അനുമതി അഭ്യർത്ഥന"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"സ്ക്രീൻ ഓവർലേ കണ്ടെത്തി"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ഈ അനുമതി ക്രമീകരണം മാറ്റുന്നതിന്, ക്രമീകരണം &gt; ആപ്സ് എന്നതിൽ നിന്ന് നിങ്ങളാദ്യം സ്ക്രീൻ ഓവർലേ ഓഫാക്കേണ്ടതാണ്"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"ക്രമീകരണം തുറക്കുക"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"ഇൻസ്റ്റാളോ അൺഇൻസ്റ്റാളോ ചെയ്യുന്നതിന് Wear-ൽ പിന്തുണയില്ല"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"എന്തൊക്കെ ആക്സസ്സ് ചെയ്യാനാണ് &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കേണ്ടതെന്ന് തിരഞ്ഞെടുക്കുക"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; അപ്‌ഡേറ്റ് ചെയ്തിരിക്കുന്നു. എന്തൊക്കെ ആക്സസ്സ് ചെയ്യാനാണ് ഈ ആപ്പിനെ അനുവദിക്കേണ്ടതെന്ന് തിരഞ്ഞെടുക്കുക."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"റദ്ദാക്കുക"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"തുടരുക"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"പുതിയ അനുമതികൾ"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"നിലവിലെ അനുമതികൾ"</string>
+    <string name="message_staging" msgid="6151794817691100003">"ആപ്പ് തയ്യാറാക്കുന്നു…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"അജ്ഞാതം"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"നിങ്ങളുടെ സുരക്ഷയ്ക്ക്, ഈ ഉറവിടത്തിൽ നിന്നുള്ള, തിരിച്ചറിയാനാകാത്ത ആപ്‌സ് ഇൻസ്റ്റാൾ ചെയ്യാൻ നിങ്ങളുടെ ടാബ്‌ലെറ്റ് അനുവദിക്കപ്പെടില്ല."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"നിങ്ങളുടെ സുരക്ഷയ്ക്ക്, ഈ ഉറവിടത്തിൽ നിന്നുള്ള, തിരിച്ചറിയാനാകാത്ത ആപ്‌സ് ഇൻസ്റ്റാൾ ചെയ്യാൻ നിങ്ങളുടെ ടിവി അനുവദിക്കപ്പെടില്ല."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"നിങ്ങളുടെ സുരക്ഷയ്ക്ക്, ഈ ഉറവിടത്തിൽ നിന്നുള്ള, തിരിച്ചറിയാനാകാത്ത ആപ്‌സ് ഇൻസ്റ്റാൾ ചെയ്യാൻ നിങ്ങളുടെ ഫോൺ അനുവദിക്കപ്പെടില്ല."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"തിരിച്ചറിയാനാകാത്ത ആപ്പുകളാൽ നിങ്ങളുടെ ഫോണും വ്യക്തിഗത ഡാറ്റയും ആക്രമിക്കപ്പെടാനുള്ള സാധ്യത വളരെ കൂടുതലാണ്. ഈ ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യുന്നതിലൂടെ, ഇത് ഉപയോഗിക്കുന്നതിനാൽ നിങ്ങളുടെ ഫോണിന് സംഭവിച്ചേക്കാവുന്ന എല്ലാ നാശനഷ്‌ടങ്ങൾക്കും അല്ലെങ്കിൽ ഡാറ്റാ നഷ്‌ടങ്ങൾക്കും നിങ്ങൾക്കാണ് ഉത്തരവാദിത്തമെന്ന് നിങ്ങൾ അംഗീകരിക്കുന്നു."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"തിരിച്ചറിയാനാകാത്ത ആപ്പുകളാൽ നിങ്ങളുടെ ടാബ്‌ലെറ്റും വ്യക്തിഗത ഡാറ്റയും ആക്രമിക്കപ്പെടാനുള്ള സാധ്യത വളരെ കൂടുതലാണ്. ഈ ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യുന്നതിലൂടെ, ഇത് ഉപയോഗിക്കുന്നതിനാൽ നിങ്ങളുടെ ടാബ്‌ലെറ്റിന് സംഭവിച്ചേക്കാവുന്ന എല്ലാ നാശനഷ്‌ടങ്ങൾക്കും അല്ലെങ്കിൽ ഡാറ്റാ നഷ്‌ടങ്ങൾക്കും നിങ്ങൾക്കാണ് ഉത്തരവാദിത്തമെന്ന് നിങ്ങൾ അംഗീകരിക്കുന്നു."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"തിരിച്ചറിയാനാകാത്ത ആപ്പുകളാൽ നിങ്ങളുടെ ടിവിയും വ്യക്തിഗത ഡാറ്റയും ആക്രമിക്കപ്പെടാനുള്ള സാധ്യത വളരെ കൂടുതലാണ്. ഈ ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യുന്നതിലൂടെ, ഇത് ഉപയോഗിക്കുന്നതിനാൽ നിങ്ങളുടെ ടിവിക്ക് സംഭവിച്ചേക്കാവുന്ന എല്ലാ നാശനഷ്‌ടങ്ങൾക്കും അല്ലെങ്കിൽ ഡാറ്റാ നഷ്‌ടങ്ങൾക്കും നിങ്ങൾക്കാണ് ഉത്തരവാദിത്തമെന്ന് നിങ്ങൾ അംഗീകരിക്കുന്നു."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"തുടരുക"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ക്രമീകരണം"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear ആപ്പുകൾ ഇൻസ്‌റ്റാൾ/അൺ ഇൻസ്‌റ്റാൾ ചെയ്യൽ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-mn-television/strings.xml b/packages/PackageInstaller/res/values-mn-television/strings.xml
new file mode 100644
index 0000000..39c899f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-mn-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Taтгалзаад дахин бүү асуугаарай"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Та дараа үүнийг Toхиргоо &amp; Апп дотроос солих боломжтой"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Системийн аппыг харуулах"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Апп-н зөвшөөрөл"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Апп-н зөвшөөрөл"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> зөвшөөрөл"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Нэмэлт зөвшөөрөл"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> зөвшөөрөл"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-mn-watch/strings.xml b/packages/PackageInstaller/res/values-mn-watch/strings.xml
new file mode 100644
index 0000000..120c336
--- /dev/null
+++ b/packages/PackageInstaller/res/values-mn-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Татгалзах, дахин бүү асуугаарай"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Системийн аппыг харуулах"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Өөрчлөх боломжгүй"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Тийм"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Цуцлах"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-mn/strings.xml b/packages/PackageInstaller/res/values-mn/strings.xml
new file mode 100644
index 0000000..1fd12a2
--- /dev/null
+++ b/packages/PackageInstaller/res/values-mn/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Багц суулгагч"</string>
+    <string name="next" msgid="3057143178373252333">"Дараах"</string>
+    <string name="install" msgid="5896438203900042068">"Суулгах"</string>
+    <string name="done" msgid="3889387558374211719">"Дуусгах"</string>
+    <string name="cancel" msgid="8360346460165114585">"Цуцлах"</string>
+    <string name="installing" msgid="8613631001631998372">"Суулгаж байна…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-г суулгаж байна…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Апп суулгагдсан."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Та энэ аппликешныг суулгамаар байна уу? Энэ дараахад хандах болно:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Та энэ аппликешныг суулгах уу? Энэ тусгай хандалт шаардахгүй."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Та энэ аппликейшны шинэчлэлтийг суулгах уу? Таны хуучин дата устах болно. Шинэчлэгдсэн аппликейшн нь дараахад хандаж чадна:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Та энэ үндсэн аппликейшны шинэчлэлтийг суулгах уу? Таны хуучин дата устах болно. Шинэчлэгдсэн аппликейшн нь дараахад хандаж чадна:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Та энэ аппликешны шинэчлэлтийг суулгах уу? Таны хуучин дата устах болно. Энэ ямар нэгэн тусгай эрх шаардахгүй."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Та энэ үндсэн аппликешны шинэчлэлтийг суулгах уу? Таны хуучин дата устах болно. Энэ ямар нэгэн тусгай эрх шаардахгүй."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Апп суулгагдаагүй."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Багц суулгахыг блоклосон байна."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Багц одоогийн багцтай тохирохгүй байгаа тул апп-г суулгаж чадсангүй."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Апп таны таблеттай тохирохгүй байгаа тул үүнийг суулгасангүй."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Энэ апп нь таны ТВ-д нийцэхгүй."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Апп таны утсанд тохирохгүй байгаа тул үүнийг суулгасангүй."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Багц хүчингүй тул апп-г суулгасангүй."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны таблет дээр суусангүй."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь таны телевизэд суурилуулах боломжгүй байна."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г таны утсан дээр суулгах боломжгүй."</string>
+    <string name="launch" msgid="4826921505917605463">"Нээх"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Таны админ тодорхойгүй сурвалжаас татсан апп суулгахыг зөвшөөрдөггүй"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Энэ хэрэглэгч тодорхойгүй апп суулгах боломжгүй байна"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Энэ хэрэглэгч апп суулгах зөвшөөрөлгүй байна"</string>
+    <string name="ok" msgid="3468756155452870475">"ОК"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Апп удирдах"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Зай дутагдаж байна"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г суулгаж чадсангүй. Зайг чөлөөлөөд дахин оролдоно уу."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Апп олдсонгүй"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Суулгасан апп-н жагсаалт дотроос апп олдсонгүй."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Зөвшөөрөөгүй"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Одоогийн хэрэглэгч үүнийг устгах боломжгүй."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Алдаа"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Апп-г устгаж чадсангүй."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Апп устгах"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Шинэчлэлийг устгах"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> нь дараах апп-н хэсэг болно:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Та энэ апп-г устгамаар байна уу?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Та энэ апп-г "<b>"бүх"</b>" хэрэглэгчээс устгах уу? Аппикешн болон доторх дата нь төхөөрөмж дээрх "<b>"бүх"</b>" хэрэглэгчээс устгагдах болно."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Та энэ апп-г <xliff:g id="USERNAME">%1$s</xliff:g> хэрэглэгчийн хувьд устгах уу?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Энэ апп-г үйлдвэрээс ирсэн хувилбараар нь солих уу? Бүх өгөгдөл устах болно."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Энэ апп-г үйлдвэрээс ирсэн хувилбараар нь солих уу? Бүх өгөгдөл устах болно. Энэ нь ажлын профайлтай хэрэглэгч зэрэг энэ төхөөрөмжийн бүх хэрэглэгчдэд үйлчлэх болно."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Устгаж байна"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Устгаж чадсангүй"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Устгаж байна…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-г устгаж байна…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Устгаж дуусав."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-г устгасан"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Устгалт амжилтгүй болов."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-г устгаж чадсангүй."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Идэвхтэй төхөөрөмжийн админ аппыг устгах боломжгүй"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g>-д идэвхтэй төхөөрөмжийн админ аппыг устгах боломжгүй байна"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Энэ апп нь зарим хэрэглэгч эсвэл профайлд шаардлагатай учир үүнийг тэдгээрээс бусад хэрэглэгчдээс устгасан"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Энэ апп таны профайлд шаардлагатай бөгөөд устгах боломжгүй."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Энэ апп нь таны төхөөрөмжийн админд шаардлагатай бөгөөд устгах боломжгүй."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Төхөөрөмжийн админ аппыг удирдах"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Хэрэгчлэгчдийг удирдах"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г устгаж чадсангүй."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Багцийг задлахад алдаа гарав."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Шинэ"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Бүгд"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Нууцлал"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Төхөөрөмжид хандах"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Энэ шинэчлэл шинэ зөвшөөрөл шаардахгүй."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Татгалзах"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Дэлгэрэнгүй мэдээлэл"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Хэдийд ч татгалзах"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>-ийн <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-г <xliff:g id="ACTION">%2$s</xliff:g>-г зөвшөөрөх үү?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-г <xliff:g id="ACTION">%2$s</xliff:g>-д байнга зөвшөөрөх үү?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Зөвхөн апп ашиглах үед"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Байнга"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Taтгалзаад дахин бүү асуугаарай"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g>-г цуцалсан"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"бүгдийг цуцалсан"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"алийг ч цуцлаагүй"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Зөвшөөрөх"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Апп"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Апп зөвшөөрөл"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Дахиж бүү асуу"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Зөвшөөрөлгүй байна"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Нэмэлт зөвшөөрөл"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Аппын мэдээллийг нээх"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Энэхүү аппыг нь Android-ын хуучин хувилбарт зориулсан. Зөвшөөрлийг үгүйсгэх нь цаашид ажиллахгүй болгож болно."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"Танигдаагүй үйлдлийг гүйцэтгэх"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g>-с <xliff:g id="COUNT_0">%1$d</xliff:g> аппыг зөвшөөрдөг"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Системийг харуулах"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Системийг нуух"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Апп байхгүй"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Байршлын тохиргоо"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь энэ төхөөрөмжийн байршлын үйлчилгээ үзүүлэгч юм. Байршилд хандалтыг байршлын тохиргоо хэсгээс өөрчилж болно."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Хэрэв та энэ зөвшөөрөлд татгалзсан тохиолдолд таны төхөөрөмжийн үндсэн функц нь алдаатай ажиллаж магадгүй."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Бодлогын дагуу хэрэгжсэн"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Арын дэвсгэрийн хандалтыг удирдамжаас идэвхгүй болгосон"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Арын дэвсгэрийн хандалтыг удирдамжаас идэвхтэй болгосон"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Нүүрний дэвсгэрийн хандалтыг удирдамжаас идэвхтэй болгосон"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Админ удирддаг"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Байнга"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Зөвхөн апп ашиглах үед"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Хэзээ ч үгүй"</string>
+    <string name="loading" msgid="7811651799620593731">"Ачаалж байна..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Бүх зөвшөөрөл"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Бусад апп-ын боломж"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Зөвшөөрлийн хүсэлт"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Дэлгэцийн давхарга илрүүллээ"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Зөвшөөрлийн тохиргоог өөрчлөхийн тулд, эхлээд Тохиргоо ба Апп хэсгээс дэлгэцийн давхаргыг унтраана уу."</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Тохиргоог нээх"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Суулгах/Устгах үйлдлийг Wear дэмжээгүй."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-н хандаж болох зүйлсийг сонгоно уу"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-г шинэчиллээ. Энэ апп-н хандаж болох зүйлсийг сонгоно уу."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Цуцлах"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Үргэлжлүүлэх"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Шинэ зөвшөөрөл"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Одоогийн зөвшөөрөл"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Апп-г байршуулж байна…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Тодорхойгүй"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Таны аюулгүй байдлыг хангахын тулд таны таблет энэ эх сурвалжаас тодорхойгүй апп суулгахыг зөвшөөрдөггүй."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Таны аюулгүй байдлыг хангахын тулд таны ТВ энэ эх сурвалжаас тодорхойгүй апп суулгахыг зөвшөөрдөггүй."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Таны аюулгүй байдлыг хангахын тулд таны утас энэ эх сурвалжаас тодорхойгүй апп суулгахыг зөвшөөрдөггүй."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Таны утас болон хувийн өгөгдөл тодорхойгүй апп суулгасан тохиолдолд гэмтэж болзошгүй. Энэ аппыг суулгаснаар үүнийг ашигласнаас үүдэн таны утсанд гэмтэл гарах, эсвэл өгөгдөл устах зэрэг эрсдэлийг хариуцна гэдгээ зөвшөөрч байна."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Таны таблет болон хувийн өгөгдөл тодорхойгүй апп суулгасан тохиолдолд гэмтэж болзошгүй. Энэ аппыг суулгаснаар үүнийг ашигласнаас үүдэн таны таблетад гэмтэл гарах, эсвэл өгөгдөл устах зэрэг эрсдэлийг хариуцна гэдгээ зөвшөөрч байна."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Таны ТВ болон хувийн өгөгдөл тодорхойгүй апп суулгасан тохиолдолд гэмтэж болзошгүй. Энэ аппыг суулгаснаар үүнийг ашигласнаас үүдэн таны ТВ-д гэмтэл гарах, эсвэл өгөгдөл устах зэрэг эрсдэлийг хариуцна гэдгээ зөвшөөрч байна."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Үргэлжлүүлэх"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Тохиргоо"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Зүүсгэл аппыг суулгаж/устгаж байна"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-mr-television/strings.xml b/packages/PackageInstaller/res/values-mr-television/strings.xml
new file mode 100644
index 0000000..e648404
--- /dev/null
+++ b/packages/PackageInstaller/res/values-mr-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"नकार द्या आणि पुन्हा विचारू नका"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"तुम्ही हे नंतर सेटिंग्ज आणि अॅप्स मध्ये बदलू शकता"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"सिस्टम अॅप्स दर्शवा"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"अॅप परवानग्या"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"अॅप परवानग्या"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> परवानग्या"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"अतिरिक्त परवानग्या"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> परवानग्या"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-mr-watch/strings.xml b/packages/PackageInstaller/res/values-mr-watch/strings.xml
new file mode 100644
index 0000000..74d32df
--- /dev/null
+++ b/packages/PackageInstaller/res/values-mr-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"नकार द्या, पुन्हा विचारू नका"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"सिस्टम अॅप्स दर्शवा"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"बदलू शकत नाही"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"होय"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"रद्द करा"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-mr/strings.xml b/packages/PackageInstaller/res/values-mr/strings.xml
new file mode 100644
index 0000000..b9acaa5
--- /dev/null
+++ b/packages/PackageInstaller/res/values-mr/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"पॅकेज स्‍थापनकर्ता"</string>
+    <string name="next" msgid="3057143178373252333">"पुढील"</string>
+    <string name="install" msgid="5896438203900042068">"स्‍थापित करा"</string>
+    <string name="done" msgid="3889387558374211719">"पूर्ण झाले"</string>
+    <string name="cancel" msgid="8360346460165114585">"रद्द करा"</string>
+    <string name="installing" msgid="8613631001631998372">"इंस्टॉल करत आहे..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> इन्‍स्टॉल करत आहे…"</string>
+    <string name="install_done" msgid="3682715442154357097">"अॅप इंस्टॉल झाला."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"तुम्ही हा अॅप्लिकेशन इंस्टॉल करू इच्छिता? यास यावर प्रवेश मिळेल:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"तुम्ही हा अॅप्लिकेशन इंस्टॉल करू इच्छिता? यास कोणत्याही विशेष प्रवेशाची आवश्यकता नसते."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"तुम्हाला सद्य अॅप्लिकेशनवर अपडेट इंस्टॉल करायची आहे? तुम्ही तुमचा सद्य डेटा गमावणार नाही. अपडेट केलेल्या अॅप्लिकेशनला यावर अॅक्सेस मिळेल:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"तुम्ही या बिल्ट-इन अॅप्लिकेशनवर अपडेट इंस्टॉल करायची आहे? तुम्ही तुमचा सद्य डेटा गमावणार नाही. अपडेट केलेल्या अॅप्लिकेशनला यावर अॅक्सेस मिळेल:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"तुम्हाला सद्य अॅप्लिकेशनवर अपडेट इंस्टॉल करायची आहे? तुम्ही तुमचा सद्य डेटा गमावणार नाही. यासाठी कोणताही विशेष अॅक्सेस आवश्यक नसतो."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"तुम्ही या बिल्ट-इन अॅप्लिकेशनवर अपडेट इंस्टॉल करायची आहे? तुम्ही तुमचा सद्य डेटा गमावणार नाही. यासाठी कोणताही विशेष अॅक्सेस आवश्यक नसतो."</string>
+    <string name="install_failed" msgid="6579998651498970899">"अॅप इंस्टॉल झाला नाही."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"पॅकेेच इंस्टॉल होण्यास अवरोधित केलेले होते."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"पॅकेजचा विद्यमान पॅकेजशी विरोध असल्याने अॅप इंस्टॉल केला नाही."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"अॅप आपल्या टॅब्लेटशी सुसंगत नसल्याने अॅप इंस्टॉल केला नाही."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"हा अॅप आपल्या टीव्हीशी सुसंगत नाही."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"अॅप आपल्या फोनशी सुसंगत नसल्याने अॅप इंस्टॉल केला नाही."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"पॅकेज अवैध असल्याचे दिसत असल्याने अॅप इंस्टॉल केले नाही."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपल्या टॅब्लेटवर इंस्टॉल केला जाऊ शकला नाही."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपल्या टीव्हीवर इंस्टॉल केले जाऊ शकले नाही."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपल्या फोनवर इंस्टॉल केला जाऊ शकला नाही."</string>
+    <string name="launch" msgid="4826921505917605463">"उघडा"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"अज्ञात स्रोतांकडून मिळवलेल्या अॅप्सच्या स्थापनेला आपला प्रशासक अनुमती देत नाही"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"या वापरकर्त्याद्वारे अज्ञात अ‍ॅप्स इंस्टॉल केली जाऊ शकत नाहीत"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"या वापरकर्त्याला अ‍ॅप्स इंस्टॉल करण्याची परवानगी नाही"</string>
+    <string name="ok" msgid="3468756155452870475">"ठीक"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"अ‍ॅप्स व्यवस्थापित करा"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"स्‍थानाबाहेर"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> इंस्टॉल केला जाऊ शकला नाही. काही स्थान मोकळे करा आणि पुन्हा प्रयत्न करा."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"अॅप आढळला नाही"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"इंस्टॉल केलेल्या अॅप्सच्या सूचीमध्ये अॅप आढळला नाही."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"अनुमती नाही"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"हे अनइंस्टॉल करण्याची वर्तमान वापरकर्त्यास अनुमती नाही."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"एरर"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"अॅप अनइंस्टॉल करणे शक्य झाले नाही."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"अॅप अनइंस्टॉल करा"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"अपडेट अनइंस्टॉल करा"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> खालील अॅप चा भाग आहे:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"तुम्ही हा अॅप अनइंस्टॉल करू इच्छिता?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"तुम्ही हा अॅप "<b>"सर्व"</b>" वापरकर्त्यांसाठी अनइंस्टॉल करू इच्छिता? अॅप्लिकेशन आणि त्याचा डेटा डिव्हाइसवरील "<b>"सर्व"</b>" वापरकर्त्यांवरून काढला जाईल."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"तुम्ही <xliff:g id="USERNAME">%1$s</xliff:g> वापरकर्त्यासाठी हा अ‍ॅप विस्‍थापित करु इच्‍छिता?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"फॅक्टरी आवृत्तीसह हा अॅप पुनर्स्थित करायचा? सर्व डेटा काढला जाईल."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"फॅक्टरी आवृत्तीसह हा अॅप पुनर्स्थित करायचा? सर्व डेटा काढला जाईल. हे कार्य प्रोफाईल असलेल्यांसह या डिव्हाइसच्या सर्व वापरकर्त्यांना प्रभावित करते."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"अनइंस्टॉल करणे चालू आहे"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"अनइंस्टॉल करणे अयशस्वी झाले"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"अनइंस्टॉल करत आहे…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल करत आहे…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"अनइंस्टॉल करणे समाप्त."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल केले"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"अनइंस्टॉल करणे अयशस्वी."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल करणे अयशस्वी झाले."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"अॅक्टिव्हेट डिव्हाइस प्रशासक अ‍ॅप अनइंस्टॉल करू शकत नाही"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> साठी अॅक्टिव्हेट डिव्हाइस प्रशासक अ‍ॅप अनइंस्टॉल करू शकत नाही"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"हा अॅप काही वापरकर्ते किंवा प्रोफाईलसाठी आवश्यक आहे आणि इतरांसाठी अनइंस्टॉल केला होता"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"आपल्या प्रोफाईलसाठी हा अ‍ॅप आवश्यक आहे आणि अनइंस्टॉल केला जाऊ शकत नाही."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"तुमच्या डिव्हाइस प्रशासकास हे अ‍ॅप आवश्यक आहे आणि ते अनइंस्टॉल केले जाऊ शकत नाही."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"डिव्हाइस प्रशासक अ‍ॅप्स व्यवस्थापित करा"</string>
+    <string name="manage_users" msgid="3125018886835668847">"वापरकर्त्यांना व्यवस्‍थापित करा"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> अनइंस्टॉल केला जाऊ शकला नाही."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"पॅकेज चे विश्लेषण करताना समस्या आली."</string>
+    <string name="newPerms" msgid="6039428254474104210">"नवीन"</string>
+    <string name="allPerms" msgid="1024385515840703981">"सर्व"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"गोपनीयता"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"डिव्हाइस अॅक्सेस"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"या अद्यतनास कोणत्याही नवीन परवानग्यांची आवश्यकता नाही."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"नकार द्या"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"अधिक माहिती"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"तरीही नकार द्या"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> पैकी <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला <xliff:g id="ACTION">%2$s</xliff:g> ची अनुमती द्यायची?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला नेहमी <xliff:g id="ACTION">%2$s</xliff:g> ची अनुमती द्यायची का?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"फक्त अॅप वापरत असताना"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"नेहमी"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"नकार द्या आणि पुन्हा विचारू नका"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> अक्षम केल्या"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"सर्व अक्षम केल्या"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"कोणत्याही अक्षम केल्या नाहीत"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"अनुमती द्या"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"अॅप्स"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"अॅप परवानग्या"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"पुन्हा विचारू नका"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"परवानग्या नाहीत"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"अतिरिक्त परवानग्या"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"अॅप माहिती उघडा"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"हा अॅप Android च्या जुन्या आवृत्तीसाठी डीझाइन करण्यात आला होता. परवानगी नाकारल्यामुळे तो यापुढे उद्देशाप्रमाणे कार्य करणार नाही."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"अज्ञात क्रिया करा"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g> पैकी <xliff:g id="COUNT_0">%1$d</xliff:g> अ‍ॅप्सना अनुमती दिली"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"सिस्टम दर्शवा"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"सिस्‍टीम लपवा"</string>
+    <string name="no_apps" msgid="1965493419005012569">"कोणतेही अॅप्स नाहीत"</string>
+    <string name="location_settings" msgid="1774875730854491297">"स्थान सेटिंग्ज"</string>
+    <string name="location_warning" msgid="8778701356292735971">"या डिव्‍हाइससाठी <xliff:g id="APP_NAME">%1$s</xliff:g> स्थान सेवांचा प्रदाता आहे. स्थान प्रवेश स्थान सेटिंग्ज वरून सुधारित केला जाऊ शकतो."</string>
+    <string name="system_warning" msgid="7103819124542305179">"तुम्ही ही परवानगी नाकारल्यास, आपल्‍या डिव्‍हाइसची मुलभूत वैशिष्ट्ये अपेक्षित असल्याप्रमाणे कदाचित कार्य करू शकणार नाहीत."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"धोरणाद्वारे सक्ती केली"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"धोरणाद्वारे बॅकग्राउंड अॅक्सेस बंद केला आहे"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"धोरणाद्वारे बॅकग्राउंड अॅक्सेस सुरू केला आहे"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"धोरणाद्वारे फोरग्राउंड अॅक्सेस सुरू केला आहे"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"प्रशासनाद्वारे नियंत्रित केलेले"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"नेहमी"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"फक्त अॅप वापरत असताना"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"कधीही नाही"</string>
+    <string name="loading" msgid="7811651799620593731">"लोड करत आहे..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"सर्व परवानग्या"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"अन्य अॅप क्षमता"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"परवानगीची विनंती"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"स्क्रीन ओव्हरले आढळले"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"हे परवानगी सेटिंग बदलण्‍यासाठी, तुम्हाला सेटिंग्ज &gt; अॅप्स मधून स्क्रीन ओव्हरले बंद करावे लागेल"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"सेटिंग्ज उघडा"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"इंस्टॉल करा/अनइंस्टॉल करा क्रिया Wear वर समर्थित नाहीत."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला कशामध्‍ये प्रवेश करण्‍याची अनुमती द्यावी ते निवडा"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; अपडेट केला गेला आहे. या अॅपला कशामध्‍ये प्रवेश करण्‍याची अनुमती द्यावी ते निवडा."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"रद्द करा"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"सुरू ठेवा"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"नवीन परवानग्या"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"वर्तमान परवानग्या"</string>
+    <string name="message_staging" msgid="6151794817691100003">"अॅप प्रारंभाच्या स्थितीत आहे..."</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"अज्ञात"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"आपल्या सुरक्षिततेसाठी, आपल्या टॅबलेटला या स्रोताकडील अज्ञात अ‍ॅप्स इंस्टॉल करण्याची अनुमती नाही."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"आपल्या सुरक्षिततेसाठी, आपल्या टीव्हीला या स्रोताकडील अज्ञात अ‍ॅप्स इंस्टॉल करण्याची अनुमती नाही."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"आपल्या सुरक्षिततेसाठी, आपल्या फोनला या स्रोताकडील अज्ञात अ‍ॅप्स इंस्टॉल करण्याची अनुमती नाही."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"तुमचा फोन आणि वैयक्तिक डेटा अज्ञात अॅप्‍समुळे होणार्‍या अटॅकमुळे अधिक असुरक्षित आहे. हा अॅप इन्‍स्‍टॉल करून, तुम्‍ही सहमती देता की तो वापरल्‍याने होणार्‍या तुमच्‍या फोनच्‍या कोणत्‍याही प्रकारच्‍या नुकसान किंवा डेटा हानीसाठी तुम्ही जबाबदार आहात."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"तुमचा टॅबलेट आणि वैयक्तिक डेटा अज्ञात अॅप्‍समुळे होणार्‍या अटॅकमुळे अधिक असुरक्षित आहे. हा अॅप इन्‍स्‍टॉल करून, तुम्‍ही सहमती देता की तो वापरल्‍याने होणार्‍या तुमच्‍या टॅबलेटच्‍या कोणत्‍याही प्रकारच्‍या नुकसान किंवा डेटा हानीसाठी तुम्ही जबाबदार आहात."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"तुमचा टीव्‍ही आणि वैयक्तिक डेटा अज्ञात अॅप्‍समुळे होणार्‍या अटॅकमुळे अधिक असुरक्षित आहे. हा अॅप इन्‍स्‍टॉल करून, तुम्ही सहमती देता की तो वापरल्‍याने होणार्‍या तुमच्‍या टीव्‍हीच्‍या कोणत्‍याही प्रकारच्‍या नुकसान किंवा डेटा हानीसाठी तुम्‍ही जबाबदार आहात."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"सुरू ठेवा"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"सेटिंग्ज"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"वेअर अ‍ॅप्स इन्‍स्टॉल/अनइन्‍स्टॉल करणे"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ms-television/strings.xml b/packages/PackageInstaller/res/values-ms-television/strings.xml
new file mode 100644
index 0000000..989aba7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ms-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Tolak dan jangan tanya lagi"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Anda boleh menukar ini nanti dalam Tetapan &gt; Apl"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Tunjukkan apl sistem"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Kebenaran apl"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Kebenaran apl"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Kebenaran <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Kebenaran tambahan"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Kebenaran <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ms-watch/strings.xml b/packages/PackageInstaller/res/values-ms-watch/strings.xml
new file mode 100644
index 0000000..dad185fa
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ms-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Tolak, jangan tanya lagi"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Tunjukkan apl sistem"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Tidak dpt diubah"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ya"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Batal"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ms/strings.xml b/packages/PackageInstaller/res/values-ms/strings.xml
new file mode 100644
index 0000000..6ab23ac
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ms/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Pemasang pakej"</string>
+    <string name="next" msgid="3057143178373252333">"Seterusnya"</string>
+    <string name="install" msgid="5896438203900042068">"Pasang"</string>
+    <string name="done" msgid="3889387558374211719">"Selesai"</string>
+    <string name="cancel" msgid="8360346460165114585">"Batal"</string>
+    <string name="installing" msgid="8613631001631998372">"Memasang..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Memasang <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikasi dipasang."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Adakah anda mahu memasang aplikasi ini? Aplikasi ini akan mendapat akses kepada:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Adakah anda mahu memasang aplikasi ini? Aplikasi ini tidak memerlukan sebarang akses khas."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Adakah anda mahu memasang kemas kini kepada aplikasi sedia ada ini? Data sedia ada anda tidak akan hilang. Aplikasi yang dikemaskinikan akan mendapat akses kepada:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Adakah anda ingin memasang kemas kini kepada aplikasi terbina dalam ini? Data sedia ada anda tidak akan hilang. Aplikasi yang dikemaskinikan akan mendapat akses kepada:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Adakah anda mahu memasang kemas kini untuk aplikasi sedia ada ini? Data sedia ada anda tidak akan hilang. Hal ini tidak memerlukan sebarang akses khas."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Adakah anda mahu memasang kemas kini untuk aplikasi terbina dalam ini? Data sedia ada anda tidak akan hilang. Hal ini tidak memerlukan sebarang akses khas."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplikasi tidak dipasang."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Pakej ini telah disekat daripada dipasang."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Apl tidak dipasang kerana pakej bercanggah dengan pakej yang sedia ada."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Apl tidak dipasang kerana apl tidak serasi dengan tablet anda."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Apl ini tidak serasi dengan TV anda."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Apl tidak dipasang kerana apl tidak serasi dengan telefon anda."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Apl tidak dipasang kerana pakej tidak sah."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dipasangkan pada tablet anda."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak boleh dipasang pada TV anda."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dipasangkan pada telefon anda."</string>
+    <string name="launch" msgid="4826921505917605463">"Buka"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Pentadbir anda tidak membenarkan pemasangan apl yang diperoleh daripada sumber yang tidak diketahui"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Apl yang tidak diketahui tidak boleh dipasang oleh pengguna ini"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Pengguna ini tidak dibenarkan memasang apl"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Urus aplikasi"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Kehabisan ruang"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dipasang. Kosongkan sebahagian ruang dan cuba lagi."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplikasi tidak ditemui"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplikasi tidak ditemui dalam senarai aplikasi yang dipasang."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Tidak dibenarkan"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Pengguna semasa tidak dibenarkan untuk melaksanakan penyahpasangan ini."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Ralat"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Apl tidak dapat dinyapasang."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Nyahpasang aplikasi"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Nyahpasang kemas kini"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> merupakan sebahagian daripada aplikasi berikut:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Adakah anda mahu menyahpasang aplikasi ini?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Adakah anda mahu menyahpasang apl ini untuk "<b>"semua"</b>" pengguna? Aplikasi dan datanya akan dialih keluar daripada "<b>"semua"</b>" pengguna pada peranti."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Adakah anda ingin menyahpasang apl ini untuk pengguna <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Gantikan apl ini dengan versi kilang? Semua data akan dialih keluar."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Gantikan apl ini dengan versi kilang? Semua data akan dialih keluar. Tindakan ini melibatkan semua pengguna peranti ini, termasuk mereka yang mempunyai profil kerja."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Penyahpasangan yang sedang berjalan"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Penyahpasangan yang gagal"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Menyahpasang..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Menyahpasang <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Nyahpasang selesai."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> dinyahpasang"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Nyahpasang tidak berjaya."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Tidak berjaya menyahpasang <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Tidak dapat menyahpasang apl pentadbir peranti yang aktif"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Tidak dapat menyahpasang apl pentadbir peranti yang aktif untuk <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Apl ini diperlukan untuk sesetengah pengguna atau profil dan telah dinyahpasang untuk yang lain"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Apl ini diperlukan untuk profil anda dan tidak boleh dinyahpasang."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Apl ini diperlukan oleh pentadbir peranti anda dan tidak boleh dinyahpasang."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Urus apl pentadbir peranti"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Urus pengguna"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dinyahpasang."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Terdapat masalah menghuraikan pakej."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Baharu"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Semua"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privasi"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Akses Peranti"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Kemas kini ini tidak memerlukan kebenaran baharu."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Tolak"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Maklumat lanjut"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Tolak juga"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> daripada <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Sentiasa benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Hanya semasa menggunakan apl"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Sentiasa"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Tolak dan jangan tanya lagi"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> dilumpuhkan"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"semua dilumpuhkan"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"tiada apa-apa yang dilumpuhkan"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Benarkan"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apl"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Kebenaran apl"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Jangan tanya lagi"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Tiada kebenaran"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Kebenaran tambahan"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Buka maklumat apl"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> lagi</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> lagi</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Apl ini direka bentuk untuk versi Android yang lebih lama. Tindakan menafikan kebenaran boleh menyebabkannya tidak berfungsi seperti yang dimaksudkan lagi."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"laksanakan tindakan yang tidak diketahui"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> daripada <xliff:g id="COUNT_1">%2$d</xliff:g> apl dibenarkan"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Tunjukkan sistem"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Sembunyikan sistem"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Tiada apl"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Tetapan Lokasi"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> ialah pembekal perkhidmatan lokasi untuk peranti ini. Akses lokasi boleh diubah suai daripada tetapan lokasi."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Jika anda tolak kebenaran ini, ciri asas peranti anda mungkin tidak berfungsi seperti yang dimaksudkan lagi."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Dikuatkuasakan oleh dasar"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Akses latar belakang dilumpuhkan oleh dasar"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Akses latar belakang didayakan oleh dasar"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Akses latar depan didayakan oleh dasar"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Dikawal oleh pentadbir"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Sentiasa"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Hanya semasa menggunakan apl"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Jangan sekali-kali"</string>
+    <string name="loading" msgid="7811651799620593731">"Memuatkan…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Semua kebenaran"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Keupayaan apl yang lain"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Permintaan kebenaran"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Tindanan skrin dikesan"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Untuk menukar tetapan kebenaran ini, anda perlu mematikan tindanan skrin daripada Tetapan &gt; Apl terlebih dahulu"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Buka tetapan"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Tindakan pasang/nyahpasang tidak disokong pada Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Pilih perkara yang boleh diakses oleh &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; telah dikemas kini. Pilih perkara yang boleh diakses oleh apl ini."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Batal"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Teruskan"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Kebenaran baharu"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Kebenaran semasa"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Pemeringkatan apl…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Tidak diketahui"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Untuk keselamatan, tablet anda tidak dibenarkan memasang apl yang tidak diketahui daripada sumber ini."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Untuk keselamatan, TV anda tidak dibenarkan memasang apl yang tidak diketahui daripada sumber ini."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Untuk keselamatan, telefon anda tidak dibenarkan memasang apl yang tidak diketahui daripada sumber ini."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefon dan data peribadi anda lebih mudah diserang oleh apl yang tidak diketahui. Dengan memasang apl ini, anda bersetuju bahawa anda bertanggungjawab atas sebarang kerosakan pada telefon anda atau kehilangan data yang mungkin disebabkan oleh penggunaan apl tersebut."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tablet dan data peribadi anda lebih mudah diserang oleh apl yang tidak diketahui. Dengan memasang apl ini, anda bersetuju bahawa anda bertanggungjawab atas sebarang kerosakan pada tablet anda atau kehilangan data yang mungkin disebabkan oleh penggunaan apl tersebut."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"TV dan data peribadi anda lebih mudah diserang oleh apl yang tidak diketahui. Dengan memasang apl ini, anda bersetuju bahawa anda bertanggungjawab atas sebarang kerosakan pada TV anda atau kehilangan data yang mungkin disebabkan oleh penggunaan apl tersebut."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Teruskan"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Tetapan"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Memasang/menyahpasang apl wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-my-television/strings.xml b/packages/PackageInstaller/res/values-my-television/strings.xml
new file mode 100644
index 0000000..b802f59
--- /dev/null
+++ b/packages/PackageInstaller/res/values-my-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"ငြင်းဆိုပြီး ထပ်မံ မမေးပါနှင့်"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"နောင်တွင် ဤသည်အား ဆက်တင်များ &gt; အက်ပ်များတွင် ပြင်နိုင်၏"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"စနစ်အပ်ဖ်များ ပြသရန်"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"အက်ပ်ခွင့်ပြုချက်များ"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"အက်ပ်ခွင့်ပြုချက်များ"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> ခွင့်ပြုချက်များ"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"အပိုဆောင်း ခွင့်ပြုချက်များ"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> ခွင့်ပြုချက်များ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-my-watch/strings.xml b/packages/PackageInstaller/res/values-my-watch/strings.xml
new file mode 100644
index 0000000..21283c0
--- /dev/null
+++ b/packages/PackageInstaller/res/values-my-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ငြင်းပယ်သည်၊ ထပ်မမေးပါနှင့်"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"စနစ်အပ်ဖ်များ ပြသရန်"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ပြောင်းလဲ မရနိုင်ပါ"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Yes"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"မလုပ်တော့"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-my/strings.xml b/packages/PackageInstaller/res/values-my/strings.xml
new file mode 100644
index 0000000..02199c3
--- /dev/null
+++ b/packages/PackageInstaller/res/values-my/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Package ထည့်သွင်းခြင်း"</string>
+    <string name="next" msgid="3057143178373252333">"ရှေ့သို့"</string>
+    <string name="install" msgid="5896438203900042068">"ထည့်သွင်းပါ"</string>
+    <string name="done" msgid="3889387558374211719">"ပြီးပါပြီ"</string>
+    <string name="cancel" msgid="8360346460165114585">"မလုပ်တော့"</string>
+    <string name="installing" msgid="8613631001631998372">"ထည့်သွင်းနေပါသည်"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ကို ထည့်သွင်းနေသည်…"</string>
+    <string name="install_done" msgid="3682715442154357097">"အက်ပ်ထည့်သွင်းပြီး"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"ဤအပလီကေးရှင်းကို ထည့်သွင်းပါမလား။ ဤအပလီကေးရှင်း သုံးစွဲခွင့်ရှိမှာ ကတော့:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"ဤအပလီကေးရှင်းကို ထည့်သွင်းပါမလား။ အထူးတလည် သုံးခွင့် မလိုအပ်ပါ"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"လက်ရှိ ရှိပြီးသား အပလီကေးရှင်းကို အပ်ဒိတ်လုပ်လိုပါသလား။ ရှိပြီးသား အချက်အလက်များကို ဆုံးရှုံးမည် မဟုတ်ပါ။ အပ်ဒိတ်လုပ်လိုက်သော အပလီကေးရှင်းသုံးစွဲခွင့်ရှိမှာ များကတော့-"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"အဆင့်သင့် ပါလာသော အပလီကေးရှင်းကို အပ်ဒိတ်လုပ်လိုပါသလား။  ရှိပြီးသား အချက်အလက်များကို ဆုံးရှုံးမည် မဟုတ်ပါ။ အပ်ဒိတ်လုပ်လိုက်သော အပလီကေးရှင်း သုံးစွဲခွင့်ရှိမှာ များကတော့ -"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"လက်ရှိ ရှိပြီးသား အပလီကေးရှင်းကို အပ်ဒိတ်လုပ်လိုပါသလား။  ရှိပြီးသား အချက်အလက်များကို ဆုံးရှုံးမည် မဟုတ်ပါ။ အထူးတလည် သုံးခွင့် မလိုအပ်ပါ"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"အဆင့်သင့် ပါလာသော အပလီကေးရှင်းကို အပ်ဒိတ်လုပ်လိုပါသလား။  ရှိပြီးသား အချက်အလက်များကို ဆုံးရှုံးမည် မဟုတ်ပါ။ အထူးတလည် သုံးခွင့် မလိုအပ်ပါ"</string>
+    <string name="install_failed" msgid="6579998651498970899">"အက်ပ်မထည့်သွင်းရသေးပါ"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ပက်ကေ့ထည့်သွင်းခြင်းကို ပိတ်ဆို့ထားသည်။"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"ပက်ကေ့ဂျ်အဖြစ် ထည့်သွင်းမထားသော အက်ပ်သည် လက်ရှိပက်ကေ့ဂျ်နှင့် တိုက်နေသည်။"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"အက်ပ်အဖြစ် ထည့်သွင်းမထားသော အက်ပ်သည် သင့်တက်ဘလက်နှင့် ကိုက်ညီမှုမရှိပါ။"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"ဤ အက်ပ်သည် သင့်တီဗွီနှင့် တွဲဖက်သုံးမရပါ။"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"အက်ပ်အဖြစ် ထည့်သွင်းမထားသော အက်ပ်သည် သင့်ဖုန်းနှင့် ကိုက်ညီမှုမရှိပါ။"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"ပက်ကေ့ဂျ်အဖြစ် ထည့်သွင်းမထားသော အက်ပ်သည် မှန်ကန်မှုမရှိပုံပေါ်သည်။"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို သင့်တက်ဘလက်တွင် ထည့်သွင်းလို့ မရနိုင်ပါ"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"သင့်တီဗွီတွင် <xliff:g id="APP_NAME">%1$s</xliff:g> အား မတပ်ဆင်နိုင်ပါ။"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို သင့်ဖုန်းတွင် ထည့်သွင်းလို့ မရနိုင်ပါ"</string>
+    <string name="launch" msgid="4826921505917605463">"ဖွင့်သည်"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"သင်၏ စီမံခန့်ခွဲသူက ရင်းမြစ်မသိသော အက်ပ်များကို ထည့်သွင်းခွင့်မပြုပါ"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"အရင်းအမြစ်မသိသော အက်ပ်များကို ဤအသုံးပြုသူက ထည့်သွင်းခွင့်မရှိပါ"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"ဤအသုံးပြုသူသည် အက်ပ်များကို ထည့်သွင်းခွင့်မရှိပါ"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"အပလီကေးရှင်းများအား ထိန်းသိမ်းခြင်း"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"နေရာလွတ်မရှိပါ"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို ထည့်သွင်းလို့ မရနိုင်ပါ။ နေရာအပိုရအောင် ရှင်းလင်းပြီး ပြန်ကြိုးစားပါ"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"အက်ပ်အားမတွေ့ပါ"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ထည့်သွင်းထားသော အပလီကေးရှင်းထဲတွင် ဤအပလီကေးရှင်း မတွေ့ရှိပါ"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"ခွင့်ပြုမထားပါ"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"ဤဖယ်ရှားမှုပြုလုပ်ရန် လက်ရှိအသုံးပြုသူအား ခွင့်ပြုမထားပါ။"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"အမှားအယွင်း"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"အက်ပ်ကို ဖယ်ရှား၍မရနိုင်ပါ။"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"အပလီကေးရှင်းကို ဖယ်ရှားပါ"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"အပ်ဒိတ်လုပ်ထားခြင်းကို ပြန်ထုတ်ပါ"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ကတော့ အောက်ပါ အက်ပ်၏အစိတ်အပိုင်း တစ်ခု ဖြစ်ပါသည်:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"ဤအပလီကေးရှင်းကို သင်ဖယ်ရှားချင်ပါသလား"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"ဤအပလီကေးရှင်းကို အသုံးပြုသူ"<b>" အားလုံး"</b>" အတွက် ဖယ်ရှားချင်ပါသလား? ဤအပလီကေးရှင်း နှင့် သက်ဆိုင်ရာ အချက်အလက်များ အားလုံးကို "<b>" မှ  အားလုံးသော "</b>" စက်အသုံးပြုသူတွေအတွက် ဖယ်ရှားပစ်ပါလိမ့်မည်"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"သင်သည် အသုံးပြုသူ <xliff:g id="USERNAME">%1$s</xliff:g> အတွက် ဒီအကောင့်ကို ဖြုတ်ပစ်လိုပါသလား?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ဤအက်ပ်ကို စက်ရုံထုတ်ဗားရှင်းဖြင့် အစားထိုးမလား။ ဒေတာများအားလုံးကို ဖယ်ရှားလိုက်ပါမည်။"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ဤအက်ပ်ကို စက်ရုံထုတ်ဗားရှင်းဖြင့် အစားထိုးမလား။ ဒေတာများအားလုံးကို ဖယ်ရှားလိုက်ပါမည်။ ၎င်းသည် အလုပ်ပရိုဖိုင်ဖြင့်သုံးသူများအပါအဝင် အသုံးပြုသူများအားလုံးကို အကျိုးသက်ရောက်စေပါလိမ့်မည်။"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"ပရိုဂရမ်ကို ဖယ်ရှားနေပါသည်"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"ပရိုဂရမ်ကို ဖယ်ရှားခြင်းမအောင်မြင်ပါ"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"ဖယ်ထုတ်သည်"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ကို ဖယ်ရှားနေပါသည်…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"ဖယ်ရှားခြင်း ပြီးပါပြီ"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ကို ဖယ်ရှားလိုက်ပါပြီ"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"ဖယ်ရှားမှု မအောင်မြင်ပါ"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ကို ဖယ်ရှားခြင်း မအောင်မြင်ပါ။"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"ဖွင့်ထားသော စက်ပစ္စည်းကို စီမံခန့်ခွဲရန်အက်ပ်အား ဖယ်ရှား၍မရပါ"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> အတွက် ဖွင့်ထားသော စက်ပစ္စည်းကို စီမံခန့်ခွဲရန် အက်ပ်အား ဖယ်ရှား၍မရပါ။"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"အချို့အသုံးပြုသူများ သို့မဟုတ် ပရိုဖိုင်များအတွက် ဤအက်ပ်ကို လိုအပ်သော်လည်း အချို့သူများအတွက် ဖြုတ်ထားပါသည်"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"သင့်ပရိုဖိုင်အတွက် ဤအက်ပ်ကိုလိုအပ်ပြီး ဖြုတ်၍မရပါ။"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"ဒီအက်ပ်မှာ သင်၏ ကိရိယာ စီမံအုပ်ချုပ်သူက လိုအပ်သောကြောင့် ဖြုတ်၍ မရနိုင်ပါ။"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"စက်ပစ္စည်းကို စီမံခန့်ခွဲရန် အက်ပ်များအား စီမံရန်"</string>
+    <string name="manage_users" msgid="3125018886835668847">"အသုံးပြုသူများအား စီမံခန့်ခွဲပါ"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို ဖယ်ရှားလို့ မရပါ"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"ဒေတာအချက်အလက်အစုအားဖတ်ရှုစဉ် ပြသနာ တစ်ခု ဖြစ်ပေါ်ပါသည်"</string>
+    <string name="newPerms" msgid="6039428254474104210">"အသစ်"</string>
+    <string name="allPerms" msgid="1024385515840703981">"အားလုံး"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"လုံခြုံမှု"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"စက်ပစ္စည်း အသုံးပြုခွင့်"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"ဤအပ်ဒိတ်အတွက် ခွင့်ပြုချက်အသစ် မလိုအပ်ပါ"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"ငြင်းပယ်သည်"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"အခြားအချက်အလက်များ"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"မည်သို့ပင်ဖြစ်စေ ငြင်းပယ်ပါ"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို <xliff:g id="ACTION">%2$s</xliff:g> ရန်ခွင့်ပြုမလား။"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို <xliff:g id="ACTION">%2$s</xliff:g> ရန် အမြဲခွင့်ပြုသလား။"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"အက်ပ်အသုံးပြုစဉ်သာ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"အမြဲတမ်း"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"ငြင်းဆိုသည်၊ ထပ်မမေးပါနှင့်"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> ခု ပိတ်ထားသည်"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"အားလုံးပိတ်ထားသည်"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"တစ်ခုမျှ ပိတ်မထားပါ"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"ခွင့်ပြုသည်"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"အက်ပ်များ"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"အက်ပ်ခွင့်ပြုချက်များ"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"နောက်ထပ်မမေးပါနှင့်"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"ခွင့်ပြုချက်မရှိ"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"ထပ်တိုး ခွင့်ပြုချက်များ"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"အက်ပ်အချက်အလက် ဖွင့်ရန်"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"ဤအက်ပ် အား Android ၏ ဗားရှင်းဟောင်းအတွက် ပုံဆွဲရေးဆွဲထား၏။ ခွင့်ပြုချက်ပေးရန် ငြင်းဆိုပါက ရည်ရွယ်ထားသကဲ့သို့ ဆောင်ရွက်လိမ့်မည် မဟုတ်ပါ။"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"အမျိုးအမည်မသိ ဆောင်ရွက်ချက်တစ်ခု လုပ်ရန်"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"အက်ပ် <xliff:g id="COUNT_1">%2$d</xliff:g> မှ <xliff:g id="COUNT_0">%1$d</xliff:g> ခု ခွင့်ပြုသည်"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"စနစ်ကိုပြသရန်"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"စနစ်ကို ဖျောက်မည်"</string>
+    <string name="no_apps" msgid="1965493419005012569">"အက်ပ် မရှိပါ"</string>
+    <string name="location_settings" msgid="1774875730854491297">"တည်နေရာ ဆက်တင်များ"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် ဤစက်ပစ္စည်းအတွက် တည်နေရာ ဝန်ဆောင်မှုများ ထုတ်ပေးသူဖြစ်သည်။ တည်နေရာ အသုံးပြုမှုကို တည်နေရာချိန်ညှိမှုများတွင် ပြုပြင်နိုင်သည်။"</string>
+    <string name="system_warning" msgid="7103819124542305179">"ဤခွင့်ပြုချက်အား သင် ငြင်းဆိုပါက၊ သင့်စက်ကိရိယာ၏ အခြေခံလုပ်ဆောင်ချက်များသည် ရည်ရွယ်ထားသကဲ့သို့ အလုပ်လုပ်မည် မဟုတ်ပါ။"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"မူဝါဒအားဖြင့်ပြဌာန်းရန်"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"နောက်ခံတွင်ဝင်သုံးခွင့်ကို မူဝါဒက ပိတ်ထားသည်"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"နောက်ခံတွင်ဝင်သုံးခွင့်ကို မူဝါဒက ဖွင့်ထားသည်"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"မျက်နှာစာတွင်ဝင်သုံးခွင့်ကို မူဝါဒက ဖွင့်ထားသည်"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"စီမံခန့်ခွဲသူက ထိန်းချုပ်ထားသည်"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"အမြဲတမ်း"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"အက်ပ်အသုံးပြုစဉ်သာ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"ဘယ်တော့မှ"</string>
+    <string name="loading" msgid="7811651799620593731">"တင်နေ…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"ခွင့်ပြုချက်များ အားလုံး"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"အခြားအပ်ဖ်၏ စွမ်းရည်များ"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"ခွင့်ပြုချက် တောင်းခံမှု"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"မျက်နှာပြင် ထပ်ပေးမှုကို ရှာတွေ့ခဲ့"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ဒီခွင့်ပြုချက် ဆက်တင်ကို ပြောင်းရန်၊ သင်ဟာ ဦးစွာ ဆက်တင်များ &gt; အက်ပ်များ ထဲတွင် မျက်နှာပြင် ထပ်ပေးမှုကို ပိတ်လိုက်ရန် လိုမယ်"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"ဆက်တင်းများ ဖွင့်ရန်"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear ပေါ်တွင် ထည့်သွင်းခြင်း/ဖြုတ်ခြင်းများကို ပံ့ပိုးမထားပါ။"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&amp;It;b7gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&amp;It;/b&gt; က အသုံးပြုခွင့်ရမည့် အရာတို့ကို ရွေးပါ"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&amp;It;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&amp;It;/b&gt; ကို အပ်ဒိတ်လုပ်ပြီးပါပြီ။ ဤအက်ပ်က အသုံးပြုခွင့်ရမည့်အရာတို့ကို ရွေးပါ။"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"မလုပ်တော့"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"ဆက်လုပ်ရန်"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"ခွင့်ပြုချက် အသစ်များ"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"လက်ရှိ ခွင့်ပြုချက်များ"</string>
+    <string name="message_staging" msgid="6151794817691100003">"အက်ပ်ကို ပြင်ဆင်နေသည်…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"အမျိုးအမည်မသိ"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"လုံခြုံရေးအရ ဤနေရာမှရယူထားသည့် အမျိုးအမည်မသိသောအက်ပ်များကို သင်၏တက်ဘလက်တွင် ထည့်သွင်းခွင့်မရှိပါ။"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"လုံခြုံရေးအရ ဤနေရာမှရယူထားသည့် အမျိုးအမည်မသိသောအက်ပ်များကို သင်၏တီဗီတွင် ထည့်သွင်းခွင့်မရှိပါ။"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"လုံခြုံရေးအရ ဤနေရာမှရယူထားသည့် အမျိုးအမည်မသိသောအက်ပ်များကို သင်၏ဖုန်းတွင် ထည့်သွင်းခွင့်မရှိပါ။"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"သင်၏ဖုန်းနှင့် ကိုယ်ရေးကိုယ်တာ အချက်အလက်များသည် အမျိုးအမည် မသိသောအက်ပ်များ၏ တိုက်ခိုက်ခြင်းကို ပိုမိုခံရနိုင်ပါသည်။ ဤအက်ပ်ကို ထည့်သွင်းအသုံးပြုခြင်းအားဖြင့် ဖြစ်ပေါ်လာနိုင်သော ဖုန်းပျက်စီးမှု သို့မဟုတ် ဒေတာဆုံးရှုံးမှုများအတွက် သင့်ထံ၌သာ တာဝန်ရှိကြောင်း သဘောတူရာရောက်ပါသည်။"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"သင်၏ တက်ဘလက်နှင့် ကိုယ်ရေးကိုယ်တာ အချက်အလက်များသည် အမျိုးအမည် မသိသောအက်ပ်များ၏ တိုက်ခိုက်ခြင်းကို ပိုမိုခံရနိုင်ပါသည်။ ဤအက်ပ်ကို ထည့်သွင်းအသုံးပြုခြင်းအားဖြင့် ဖြစ်ပေါ်လာနိုင်သော တက်ဘလက်ပျက်စီးမှု သို့မဟုတ် ဒေတာဆုံးရှုံးမှုများအတွက် သင့်ထံ၌သာ တာဝန်ရှိကြောင်း သဘောတူရာရောက်ပါသည်။"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"သင်၏ TV နှင့် ကိုယ်ရေးကိုယ်တာ အချက်အလက်များသည် အမျိုးအမည် မသိသောအက်ပ်များ၏ တိုက်ခိုက်ခြင်းကို ပိုမိုခံရနိုင်ပါသည်။ ဤအက်ပ်ကို ထည့်သွင်းအသုံးပြုခြင်းအားဖြင့် ဖြစ်ပေါ်လာနိုင်သော TV ပျက်စီးမှု သို့မဟုတ် ဒေတာဆုံးရှုံးမှုများအတွက် သင့်ထံ၌သာ တာဝန်ရှိကြောင်း သဘောတူရာရောက်ပါသည်။"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"ဆက်လုပ်ရန်"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ဆက်တင်များ"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"wear အက်ပ်ကိုထည့်သွင်းခြင်း/ဖယ်ရှားခြင်း"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-nb-television/strings.xml b/packages/PackageInstaller/res/values-nb-television/strings.xml
new file mode 100644
index 0000000..57f6a21
--- /dev/null
+++ b/packages/PackageInstaller/res/values-nb-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Avvis, og ikke spør igjen"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Du kan endre dette senere i Innstillinger &gt; Apper"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Vis systemapper"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Apptillatelser"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Apptillatelser"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Tillatelser for <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Flere tillatelser"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Tillatelser for <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-nb-watch/strings.xml b/packages/PackageInstaller/res/values-nb-watch/strings.xml
new file mode 100644
index 0000000..332a8fe
--- /dev/null
+++ b/packages/PackageInstaller/res/values-nb-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Avvis, ikke spør igjen"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Vis systemapper"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Kan ikke endres"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ja"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Avbryt"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-nb/strings.xml b/packages/PackageInstaller/res/values-nb/strings.xml
new file mode 100644
index 0000000..3ff3de4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-nb/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Pakkeinstallasjon"</string>
+    <string name="next" msgid="3057143178373252333">"Neste"</string>
+    <string name="install" msgid="5896438203900042068">"Installer"</string>
+    <string name="done" msgid="3889387558374211719">"Ferdig"</string>
+    <string name="cancel" msgid="8360346460165114585">"Avbryt"</string>
+    <string name="installing" msgid="8613631001631998372">"Installerer…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Installerer <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
+    <string name="install_done" msgid="3682715442154357097">"Appen er installert."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Ønsker du å installere denne appen? Den får tilgang til følgende:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Ønsker du å installere denne appen? Den krever ingen spesiell tilgang."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Ønsker du å installere en oppdatering for denne eksisterende appen? Du mister ingen eksisterende data. Den oppdaterte appen får tilgangen spesifisert nedenfor."</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Ønsker du å installere en oppdatering for denne innebygde appen? Du mister ingen eksisterende data. Den oppdaterte appen får tilgangen spesifisert nedenfor."</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Vil du installere en oppdatering av denne eksisterende appen? De eksisterende dataene dine går ikke tapt. Dette krever ingen spesiell tilgang."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Vil du installere en oppdatering av denne innebygde appen? De eksisterende dataene dine går ikke tapt. Dette krever ingen spesiell tilgang."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Appen ble ikke installert."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Pakken er blokkert fra å bli installert."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Appen ble ikke installert fordi pakken er i konflikt med en eksisterende pakke."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Appen ble ikke installert fordi appen ikke er kompatibel med nettbrettet ditt."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Denne appen er ikke kompatibel med TV-en din."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Appen ble ikke installert fordi appen ikke er kompatibel med telefonen din."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Appen ble ikke installert fordi pakken ser ut til å være ugyldig."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres på nettbrettet ditt."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres på TV-en."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres på telefonen din."</string>
+    <string name="launch" msgid="4826921505917605463">"Åpne"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Administratoren din tillater ikke installering av apper som er hentet fra ukjente kilder"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Ukjente apper kan ikke installeres av denne brukeren"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Brukeren har ikke tillatelse til å installere apper"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Administrer apper"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Tom for plass"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres. Frigjør plass og prøv på nytt."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Appen ble ikke funnet"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Finner ikke appen i listen over installerte apper."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Ikke tillatt"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Denne brukeren har ikke tillatelse til å utføre denne avinstalleringen."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Feil"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Kunne ikke avinstallere appen."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Avinstaller appen"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Avinstaller oppdateringen"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> er del av følgende app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Vil du avinstallere denne appen?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Vil du avinstallere denne appen for "<b>"alle"</b>" brukere? Appen og tilhørende data blir fjernet fra "<b>"alle"</b>" brukere på enheten."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Ønsker du å avinstallere denne appen for brukeren <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Vil du erstatte denne appen med den opprinnelige versjonen? Alle dataene fjernes."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Vil du erstatte denne appen med den opprinnelige versjonen? Alle dataene fjernes. Dette påvirker alle som bruker denne enheten – også personer med jobbprofiler."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Avinstalleringer som er i gang"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Mislykkede avinstalleringer"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Avinstallerer…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Avinstallerer <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Avinstalleringen er  fullført."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Avinstallerte <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Avinstalleringen mislyktes."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Kunne ikke avinstallere <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Kan ikke avinstallere den aktive appen for enhetsadministrator"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Kan ikke avinstallere den aktive appen for enhetsadministrator for <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Appen er nødvendig for noen brukere eller profiler, og den er avinstallert for andre"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Denne appen er nødvendig for profilen din og kan ikke avinstalleres."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Denne appen kreves av enhetsadministratoren din og kan ikke avinstalleres."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Administrer apper for enhetsadministrator"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Administrer brukere"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Det oppsto et problem med analysen av pakken."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nye"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Alle"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Personvern"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Enhetstilgang"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Denne oppdateringen krever ingen nye tillatelser."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Ikke tillat"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Finn ut mer"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Avvis likevel"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> av <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tillatelse til å <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Vil du alltid tillate at &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; kan <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Bare når appen brukes"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Alltid"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Avvis, og ikke spør igjen"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> er slått av"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"alt er slått av"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ingen er slått av"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Tillat"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apper"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Apptillatelser"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ikke spør igjen"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Ingen tillatelser"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Flere tillatelser"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Åpne info om appen"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> til</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> til</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Denne appen er designet for en eldre versjon av Android. Hvis du nekter å gi tillatelse, kan det føre til at den ikke lenger fungerer etter hensikten."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"utfør en ukjent handling"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> av <xliff:g id="COUNT_1">%2$d</xliff:g> apper er tillatt"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Vis systemapper"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Skjul systemet"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Ingen apper"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Posisjonsinnstillinger"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> er en leverandør av posisjonstjenester for denne enheten. Tilgang til posisjon kan endres fra posisjonsinnstillingene."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Hvis du ikke gir denne tillatelsen, kan grunnleggende funksjoner på enheten slutte å fungere som de skal."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Påkrevd ifølge retningslinjene"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Bakgrunnstilgang er slått av pga. retningslinjene"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Bakgrunnstilgang er slått på pga. retningslinjene"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Forgrunnstilgang er slått på pga. retningslinjene"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Kontrollert av administratoren"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Alltid"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Bare når appen brukes"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Aldri"</string>
+    <string name="loading" msgid="7811651799620593731">"Laster inn …"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Alle tillatelser"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Andre appfunksjoner"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Forespørsel om tillatelse"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Skjermoverlegg oppdaget"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"For å endre denne tillatelsesinnstilingen må du først slå av skjermoverlegget fra Innstillinger &gt; Apper"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Åpne innstillingene"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Handlinger for å installere og avinstallere er ikke støttet på Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Velg hva du vil gi <xliff:g id="APP_NAME">%1$s</xliff:g> tilgang til"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"<xliff:g id="APP_NAME">%1$s</xliff:g> er oppdatert. Velg hva du vil gi denne appen tilgang til."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Avbryt"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Fortsett"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nye tillatelser"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Gjeldende tillatelser"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Setter opp appen …"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Ukjent"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Nettbrettet ditt har ikke tillatelse til å installere ukjente apper fra denne kilden, for å ivareta sikkerheten din."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"TV-en din har ikke tillatelse til å installere ukjente apper fra denne kilden, for å ivareta sikkerheten din."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Telefonen din har ikke tillatelse til å installere ukjente apper fra denne kilden, for å ivareta sikkerheten din."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefonen din og de personlige dataene dine er mer sårbare for angrep fra ukjente apper. Når du installerer denne appen, samtykker du i at du er ansvarlig for eventuelle skader på telefonen eller tap av data bruk av appen forårsaker."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Nettbrettet ditt og de personlige dataene dine er mer sårbare for angrep fra ukjente apper. Når du installerer denne appen, samtykker du i at du er ansvarlig for eventuelle skader på nettbrettet eller tap av data bruk av appen forårsaker."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"TV-en din og de personlige dataene dine er mer sårbare for angrep fra ukjente apper. Når du installerer denne appen, samtykker du i at du er ansvarlig for eventuelle skader på TV-en eller tap av data bruk av appen forårsaker."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Fortsett"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Innstillinger"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Installerer/avinstallerer wear-apper"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ne-television/strings.xml b/packages/PackageInstaller/res/values-ne-television/strings.xml
new file mode 100644
index 0000000..d6e908c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ne-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"अस्वीकृत गर्नुहोस् र फेरि नसोध्नुहोस्"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"तपाईं यसलाई पछि सेटिङ &gt; अनुप्रयोगमा बदल्न सक्नु हुन्छ"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"प्रणाली अनुप्रयोगहरू देखाउनुहोस्"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"अनुप्रयोग सम्बन्धी अनुमतिहरू"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"अनुप्रयोग सम्बन्धी अनुमतिहरू"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> सम्बन्धी अनुमतिहरू"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"अतिरिक्त अनुमतिहरू"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> सम्बन्धी अनुमतिहरू"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ne-watch/strings.xml b/packages/PackageInstaller/res/values-ne-watch/strings.xml
new file mode 100644
index 0000000..ffcc2f7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ne-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"अस्वीकार गर्नुहोस्, फेरि नसोध्नुहोस्"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"प्रणाली अनुप्रयोगहरू देखाउनुहोस्"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"परिवर्तन गर्न सकिँदैन"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"हो"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"रद्द गर्नुहोस्"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ne/strings.xml b/packages/PackageInstaller/res/values-ne/strings.xml
new file mode 100644
index 0000000..b2dea8f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ne/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"प्याकेज स्थापनकर्ता"</string>
+    <string name="next" msgid="3057143178373252333">"अर्को"</string>
+    <string name="install" msgid="5896438203900042068">"स्थापना गर्नुहोस्"</string>
+    <string name="done" msgid="3889387558374211719">"भयो"</string>
+    <string name="cancel" msgid="8360346460165114585">"रद्द गर्नुहोस्"</string>
+    <string name="installing" msgid="8613631001631998372">"स्थापित हुँदै…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> स्थापना गर्दै…"</string>
+    <string name="install_done" msgid="3682715442154357097">"अनुप्रयोग स्थापना भयो।"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"के तपाईं यो अनुप्रयोग स्थापन गर्न चाहनु हुन्छ? यसले पहुँच प्राप्त गर्ने छ:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"के तपाईं यस अनुप्रयोगलाई जडान गर्न चाहनु हुन्छ? यसको लागि कुनै विशेष पहुँचको आवश्यकता पर्दैन।"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"के तपाईँसँग अहिले भईरहेको अनुप्रयोगको एक अपडेट लाई स्थापित गर्न चाहानुहुन्छ? तपाईँको अहिलेको डेटा हराउने छैन। अपडेट भएको अनुप्रयोग पहुँच पाउनेछ मा:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"के तपाईं यस पूर्व-निर्मित अनुप्रयोगमा अपडेट स्थापित गर्न चाहनु हुन्छ? तपाईंको रहेको डेटा हराउने छैन। अपडेट गरिएको अनुप्रयोगले पहुँच पाउने छ:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"के तपाईँसँग अहिले भइरहेको अनुप्रयोगको एउटा अपडेटलाई स्थापित गर्न चाहनु हुन्छ? तपाईँको अहिलेको डेटा हराउने छैन। यसलाई कुनै विशेष पहुँचको आवश्यकता छैन।"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"के तपाईं यस जोडिएको अनुप्रयोगको एउटा अपडेटलाई स्थापित गर्न चाहनुहुन्छ? तपाईंको अहिलेको डेटा हराउने छैन। यसलाई कुनै विशेष पहुँचको आवश्यकता छैन।"</string>
+    <string name="install_failed" msgid="6579998651498970899">"अनुप्रयोग स्थापना भएन।"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"यो प्याकेज स्थापना हुनबाट अवरुद्ध भएको थियो।"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"प्याकेजका रूपमा स्थापना नगरिएको अनुप्रयोग विद्यमान प्याकेजसँग मेल खाँदैन।"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"अनुप्रयोगका रूपमा स्थापना नगरिएको अनुप्रयोग तपाईंको ट्याब्लेटसँग मिल्दो छैन।"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"यो अनुप्रयोग तपाईँको TV को लागि उपयुक्त छैन।"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"अनुप्रयोगका रूपमा स्थापना नगरिएको अनुप्रयोग तपाईंको फोनसँग मिल्दो छैन।"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"प्याकेजका रूपमा स्थापना नगरिएको अनुप्रयोग अमान्य जस्तो देखिन्छ।"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईँको ट्याब्लेटमा स्थापित हुन सकेन।"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"तपाईँको TVमा<xliff:g id="APP_NAME">%1$s</xliff:g>स्थापना गर्न सकिएन।"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"तपाईँको फोनमा <xliff:g id="APP_NAME">%1$s</xliff:g> जडान हुन सकेन।"</string>
+    <string name="launch" msgid="4826921505917605463">"खोल्नुहोस्"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"तपाईंका प्रशासकले अज्ञात स्रोतहरूबाट प्राप्त अनुप्रयोगहरूलाई स्थापना गर्ने अनुमति दिनुहुन्न"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"यस प्रयोगकर्ताले अज्ञात अनुप्रयोगहरू स्थापना गर्न सक्नुहुन्न"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"यो प्रयोगकर्तालाई अनुप्रयोगहरूको स्थापना गर्ने अनुमति छैन"</string>
+    <string name="ok" msgid="3468756155452870475">"ठिक छ"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"अनुप्रयोगहरूको व्यवस्थापन गर्नुहोस्"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"ठाउँभन्दा बाहिर"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> स्थापन गर्न सकिएन। केही ठाउँ खाली गर्नुहोस् र फेरि कोसिस गर्नुहोस्"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"अनुप्रयोग फेला परेन"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"स्थापना भएको अनुप्रयोगहरू सूचीमा अनुप्रयोग फेला परेको थिएन।"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"अनुमति छैन"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"हालको प्रयोगकर्तालाई यो स्थापना रद्द गर्ने कार्य गर्ने अनुमति छैन।"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"त्रुटि"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"अनुप्रयोगको स्थापना रद्द गर्न सकिएन।"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"अनुप्रयोग अस्थापना गर्नुहोस्"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"परिस्कारहरू अस्थापना गर्नुहोस्"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> निम्न अनुप्रयोगको अंश हो:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"के तपाईं यो अनुप्रयोग अस्थापना गर्न चाहनु हुन्छ?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"के तपाईं यो अनुप्रयोग "<b>"सबै"</b>" प्रयोगकर्ताहरूको लागि स्थापना रद्द गर्न चाहनु हुन्छ? अनुप्रयोग र यसको डेटा "<b>"सबै"</b>" प्रयोगकर्ताहरूबाट उपकरणमा हटाइने छ।"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"के तपाईं प्रयोगकर्ता <xliff:g id="USERNAME">%1$s</xliff:g> को लागि यो अनुप्रयोग स्थापना रद्द गर्न चाहनुहुन्छ?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"यस अनुप्रयोगलाई फ्याक्ट्रीको संस्करणले बदल्ने हो? सबै डेटा हटाइनेछ।"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"यस अनुप्रयोगलाई फ्याक्ट्रीको संस्करणले बदल्ने हो? सबै डेटा हटाइनेछ। यसले यस यन्त्रका कार्य प्रोफाइल भएका लगायत सबै प्रयोगकर्ताहरूमा असर पार्छ।"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"चलिरहेका स्थापना रद्द गर्ने कार्यहरू"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"असफल भएका स्थापना रद्द गर्ने कार्यहरू"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"अस्थापना गर्दै..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> को स्थापना रद्द गर्दै…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"स्थापना रद्द गर्न सकियो।"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> को स्थापना रद्द गरियो"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"अस्थापना गर्न असफल"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> को स्थापना रद्द गर्ने कार्य असफल भयो।"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"यन्त्रको सक्रिय प्रशासकीय अनुप्रयोगको स्थापना रद्द गर्न मिल्दैन"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> को यन्त्रको सक्रिय प्रशासकीय अनुप्रयोगको स्थापना रद्द गर्न मिल्दैन"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"अन्य प्रयोगकर्ताहरूका लागि यस अनु्प्रयोगको स्थापना रद्द गरे पनि केही प्रयोगकर्ता वा प्रोफाइलहरूलाई यसको आवश्यकता पर्दछ"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"यो अनुप्रयोग तपाईँको प्रोफाइलका लागि आवश्यक छ र यसको स्थापनालाई रद्द गर्न सकिँदैन।"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"यो अनुप्रयोग तपाईँको उपकरण प्रशासकलाई आवश्यक छ र स्थापना रद्द गर्न सकिँदैन।"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"यन्त्रका प्रशासकीय अनुप्रयोगहरूको व्यवस्थापन गर्नुहोस्"</string>
+    <string name="manage_users" msgid="3125018886835668847">"प्रयोगकर्ताहरूलाई व्यवस्थापन गर्नुहोस्"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> स्थापना रद्द गर्न सकिँदैन।"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"प्याकेजलाई पार्सिङ गर्दा एउटा समस्या आयो।"</string>
+    <string name="newPerms" msgid="6039428254474104210">"नयाँ"</string>
+    <string name="allPerms" msgid="1024385515840703981">"सबै"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"गोपनीयता"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"उपकरण पहुँच"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"यस अपडेटलाई नयाँ अनुमति आवश्यक पर्दैन।"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"अस्वीकार गर्नुहोस्"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"थप जानकारी"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"जे भए पनि अस्वीकार गर्नुहोस्"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> को <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई <xliff:g id="ACTION">%2$s</xliff:g> गर्न अनुमति दिने हो?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई सधैँ <xliff:g id="ACTION">%2$s</xliff:g> गर्ने अनुमति दिने हो?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"अनुप्रयोग प्रयोग गर्दा मात्र"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"सधैँ"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"अस्वीकार गरी फेरि नसोध्नुहोस्"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> अनुमतिहरूलाई असक्षम पारिएको छ"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"सबै अनुमतिहरूलाई असक्षम पारिएको छ"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"कुनै पनि अनुमतिलाई असक्षम पारिएको छैन"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"अनुमति दिनुहोस्"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"अनुप्रयोगहरू"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"अनुप्रयोग अनुमतिहरू"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"फेरि नसोध्नुहोस्"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"कुनै अनुमतिहरू छैनन्"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"अतिरिक्त अनुमतिहरू"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"अनुप्रयोगसम्बन्धी जानकारी खोल्नुहोस्"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"यो अनुप्रयोग Android को पुरानो संस्करणका लागि डिजाइन गरिएको थियो। अनुमति अस्वीकृत गर्नाले यसले चाहिएको जस्तो कार्य नगर्न सक्छ।"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"एउटा अज्ञात कार्य गर्नुहोस्"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g> को <xliff:g id="COUNT_0">%1$d</xliff:g> अनुप्रयोगहरूलाई अनुमति छ"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"प्रणाली देखाउनुहोस्"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"प्रणाली लुकाउनुहोस्"</string>
+    <string name="no_apps" msgid="1965493419005012569">"कुनै अनुप्रयोगहरू छैनन्।"</string>
+    <string name="location_settings" msgid="1774875730854491297">"स्थान सेटिङहरू"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> यो यन्त्रका लागि स्थान सेवाहरूको एउटा प्रदायक हो। स्थान पहुँच स्थान सेटिङहरूबाट परिमार्जन गर्न सकिन्छ।"</string>
+    <string name="system_warning" msgid="7103819124542305179">"तपाईँले यो अनुमति अस्वीकार गर्नुभयो भने तपाईँको यन्त्रका मूल विशेषताहरू अब चाहेअनुसार कार्य नगर्न सक्छ।"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"नीतिद्वारा लागू गरियो"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"नीतिले पृष्ठभूमिको प‍हुँचलाई असक्षम पारेको छ"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"नीतिले पृष्ठभूमिको प‍हुँचलाई सक्षम पारेको छ"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"नीतिले अग्रभूमिको पहुँचलाई सक्षम पारेको छ"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"प्रशासकले नियन्त्रण गर्नुभएको"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"सधैँ"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"अनुप्रयोग प्रयोग गर्दा"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"कहिल्यै होइन"</string>
+    <string name="loading" msgid="7811651799620593731">"लोड हुँदैछ..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"सबै अनुमतिहरू"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"अन्य अनुप्रयोग क्षमताहरू"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"अनुमति अनुरोध"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"स्क्रिन ओभरले पत्ता लाग्यो"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"यो अनुमति सेटिङ परिवर्तन गर्न, तपाईँले पहिला सेटिङ अनुप्रयोगबाट स्क्रिन ओभरले बन्द गर्नु पर्दछ।"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"सेटिङहरू खोल्नुहोस्"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear मा स्थापना/स्थापना रद्द गर्ने कारबाहीहरू समर्थित छैनन्।"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई के माथि पहुँच राख्न दिने भन्ने कुरा छनौट गर्नुहोस्"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई अद्यावधिक गरिएको छ। यस अनुप्रयोगलाई के माथि पहुँच राख्न दिने भन्ने कुरा छनौट गर्नुहोस्।"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"रद्द गर्नुहोस्"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"जारी राख्नुहोस्"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"नयाँ अनुमतिहरू"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"वर्तमान अनुमतिहरू"</string>
+    <string name="message_staging" msgid="6151794817691100003">"अनुप्रयोगलाई तयार पार्दै…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"अज्ञात"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"तपाईंको सुरक्षाको लागि, तपाईंको ट्याब्लेटलाई यो स्रोतबाट प्राप्त हुने अज्ञात अनुप्रयोगहरू स्थापना गर्ने अनुमति छैन।"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"तपाईंको सुरक्षाको लागि, तपाईंको TV लाई यो स्रोतबाट प्राप्त हुने अज्ञात अनुप्रयोगहरू स्थापना गर्ने अनुमति छैन।"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"तपाईंको सुरक्षाको लागि, तपाईंको फोनलाई यो स्रोतबाट प्राप्त हुने अज्ञात अनुप्रयोगहरू स्थापना गर्ने अनुमति छैन।"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"तपाईंको फोन र व्यक्तिगत डेटा अज्ञात अनुप्रयोगहरूबाट हुने आक्रमणको चपेटामा पर्ने बढी जोखिममा हुन्छन्। यो अनुप्रयोग स्थापना गरेर तपाईं यसको प्रयोगबाट तपाईंको फोनलाई हुनसक्ने क्षति वा डेटाको नोक्सानीका लागि स्वयं जिम्मेवार हुनुहुन्छ भन्ने कुरामा सहमत हुनुहुन्छ।"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"तपाईंको ट्याब्लेट र व्यक्तिगत डेटा अज्ञात अनुप्रयोगहरूबाट हुने आक्रमणको चपेटामा पर्ने बढी जोखिममा हुन्छन्। यो अनुप्रयोग स्थापना गरेर तपाईं यसको प्रयोगबाट तपाईंको ट्याब्लेटलाई हुनसक्ने क्षति वा डेटाको नोक्सानीका लागि स्वयं जिम्मेवार हुनुहुन्छ भन्ने कुरामा सहमत हुनुहुन्छ।"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"तपाईंको TV र व्यक्तिगत डेटा अज्ञात अनुप्रयोगहरूबाट हुने आक्रमणको चपेटामा पर्ने बढी जोखिममा हुन्छन्। यो अनुप्रयोग स्थापना गरेर तपाईं यसको प्रयोगबाट तपाईंको TV लाई हुनसक्ने क्षति वा डेटाको नोक्सानीका लागि स्वयं जिम्मेवार हुनुहुन्छ भन्ने कुरामा सहमत हुनुहुन्छ।"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"जारी राख्नुहोस्"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"सेटिङहरू"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"वेयर एपहरूको स्थापना/स्थापना रद्द गर्दै"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-night/themes.xml b/packages/PackageInstaller/res/values-night/themes.xml
new file mode 100644
index 0000000..483b0cf
--- /dev/null
+++ b/packages/PackageInstaller/res/values-night/themes.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+
+    <style name="Theme.AlertDialogActivity"
+            parent="@android:style/Theme.DeviceDefault.Dialog.Alert" />
+
+</resources>
diff --git a/packages/PackageInstaller/res/values-nl-television/strings.xml b/packages/PackageInstaller/res/values-nl-television/strings.xml
new file mode 100644
index 0000000..c7256e8
--- /dev/null
+++ b/packages/PackageInstaller/res/values-nl-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Weigeren en niet meer vragen"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"U kunt dit later wijzigen in Instellingen &gt; Apps"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Systeem weergeven"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"App-machtigingen"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"App-machtigingen"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Machtigingen voor <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Aanvullende machtigingen"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Machtigingen voor <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-nl-watch/strings.xml b/packages/PackageInstaller/res/values-nl-watch/strings.xml
new file mode 100644
index 0000000..338b79b
--- /dev/null
+++ b/packages/PackageInstaller/res/values-nl-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Weigeren, niet meer vragen"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Systeem weergeven"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Niet aanpasbaar"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ja"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Annuleren"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml
new file mode 100644
index 0000000..a9e8940
--- /dev/null
+++ b/packages/PackageInstaller/res/values-nl/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Pakket-installatie"</string>
+    <string name="next" msgid="3057143178373252333">"Volgende"</string>
+    <string name="install" msgid="5896438203900042068">"Installeren"</string>
+    <string name="done" msgid="3889387558374211719">"Gereed"</string>
+    <string name="cancel" msgid="8360346460165114585">"Annuleren"</string>
+    <string name="installing" msgid="8613631001631998372">"Installeren..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> installeren…"</string>
+    <string name="install_done" msgid="3682715442154357097">"App geïnstalleerd."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Wil je deze app installeren? Deze krijgt toegang tot:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Wil je deze app installeren? Hiervoor is geen speciale toegang vereist."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Wil je een update voor deze bestaande app installeren? Je huidige gegevens gaan niet verloren. De bijgewerkte app krijgt toegang tot:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Wil je een update van deze ingebouwde app installeren? Je huidige gegevens gaan niet verloren. De bijgewerkte app krijgt toegang tot:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Wil je een update voor deze bestaande app installeren? Je huidige gegevens gaan niet verloren. Hiervoor is geen speciale toegang vereist."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Wil je een update voor deze ingebouwde app installeren? Je huidige gegevens gaan niet verloren. Hiervoor is geen speciale toegang vereist."</string>
+    <string name="install_failed" msgid="6579998651498970899">"App niet geïnstalleerd."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"De installatie van het pakket is geblokkeerd."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"App die niet is geïnstalleerd als pakket conflicteert met een bestaand pakket."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"App die niet is geïnstalleerd als app is niet geschikt voor je tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Deze app is niet compatibel met je tv."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"App die niet is geïnstalleerd als app is niet geschikt voor je telefoon."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"App die niet is geïnstalleerd als pakket lijkt ongeldig te zijn."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan niet worden geïnstalleerd op je tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan niet worden geïnstalleerd op je tv."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan niet worden geïnstalleerd op je telefoon."</string>
+    <string name="launch" msgid="4826921505917605463">"Openen"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Je beheerder staat de installatie van apps afkomstig van onbekende bronnen niet toe"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Onbekende apps kunnen niet worden geïnstalleerd door deze gebruiker"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Deze gebruiker mag geen apps installeren"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Apps beheren"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Geen ruimte beschikbaar"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan niet worden geïnstalleerd. Maak ruimte vrij en probeer het opnieuw."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"App niet gevonden"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"De app is niet gevonden in de lijst met geïnstalleerde apps."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Niet toegestaan"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"De huidige gebruiker mag deze verwijdering niet uitvoeren."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Fout"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"App kan niet worden verwijderd."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"App verwijderen"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Update verwijderen"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> maakt deel uit van de volgende app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Wil je deze app verwijderen?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Wil je deze app verwijderen voor "<b>"alle"</b>" gebruikers? Deze app en de gegevens ervan worden verwijderd voor "<b>"alle"</b>" gebruikers van het apparaat."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Wil je deze app verwijderen voor de gebruiker <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Deze app vervangen door de fabrieksversie? Alle gegevens worden verwijderd."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Deze app vervangen door de fabrieksversie? Alle gegevens worden verwijderd. Dit geldt voor alle gebruikers van het apparaat, dus ook voor gebruikers met een werkprofiel."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Actieve verwijderingen"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Mislukte verwijderingen"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Verwijderen..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> verwijderen…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Verwijdering voltooid."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> verwijderd"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Verwijdering mislukt."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kan niet worden verwijderd."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Kan actieve apparaatbeheer-app niet verwijderen"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Kan actieve apparaatbeheer-app niet verwijderen voor <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Deze app is vereist voor sommige gebruikers of profielen en is verwijderd voor andere"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Deze app is vereist voor je profiel en kan niet worden verwijderd."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Deze app is vereist door je apparaatbeheerder en kan niet worden verwijderd."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Apparaatbeheer-apps beheren"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Gebruikers beheren"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan niet worden verwijderd."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Er is een probleem opgetreden bij het parseren van het pakket."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nieuw"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Alle"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacy"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Apparaattoegang"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Voor deze update zijn geen nieuwe machtigingen vereist."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Weigeren"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Meer informatie"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Toch weigeren"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> van <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; het volgende toestaan: <xliff:g id="ACTION">%2$s</xliff:g>."</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; altijd toestaan om <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Alleen als app in gebruik is"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Altijd"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Weigeren en niet meer vragen"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> uitgeschakeld"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"alle rechten uitgeschakeld"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"geen rechten uitgeschakeld"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Toestaan"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apps"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"App-machtigingen"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Niet meer vragen"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Geen machtigingen"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Aanvullende machtigingen"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"App-info openen"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other">Nog <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Nog <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Deze app is ontworpen voor een oudere versie van Android. Als u geen toestemming geeft, kan de app mogelijk niet functioneren zoals is bedoeld."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"een onbekende actie uitvoeren"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Verleend aan <xliff:g id="COUNT_0">%1$d</xliff:g> van <xliff:g id="COUNT_1">%2$d</xliff:g> apps"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Systeem weergeven"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Systeem-apps verbergen"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Geen apps"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Locatie-instellingen"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> is een leverancier van locatieservices voor dit apparaat. Locatietoegang kan worden aangepast via de locatie-instellingen."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Als je deze machtiging weigert, kan het zijn dat basisfuncties van je apparaat niet meer werken zoals bedoeld."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Afgedwongen door beleid"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Toegang op de achtergrond uitgeschakeld op basis van beleid"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Toegang op de achtergrond ingeschakeld op basis van beleid"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Toegang op de voorgrond ingeschakeld op basis van beleid"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Ingesteld door beheerder"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Altijd"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Alleen als app in gebruik is"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nooit"</string>
+    <string name="loading" msgid="7811651799620593731">"Laden…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Alle machtigingen"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Andere app-mogelijkheden"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Toestemmingsverzoek"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Schermoverlay gedetecteerd"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Als u deze instelling voor rechten wilt wijzigen, moet u eerst de schermoverlay uitschakelen via \'Instellingen\' &gt; \'Apps\'"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Instellingen openen"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Acties voor installeren/verwijderen niet ondersteund op Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Kiezen waartoe &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang krijgt"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; is geüpdatet. Kies waartoe je deze app toegang wilt geven."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Annuleren"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Doorgaan"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nieuwe machtigingen"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Huidige machtigingen"</string>
+    <string name="message_staging" msgid="6151794817691100003">"App uitvoeren…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Onbekend"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Uit veiligheidsoverwegingen heeft je tablet geen toestemming om onbekende apps van deze bron te installeren."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Uit veiligheidsoverwegingen heeft je tv geen toestemming om onbekende apps van deze bron te installeren."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Uit veiligheidsoverwegingen heeft je telefoon geen toestemming om onbekende apps van deze bron te installeren."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Je telefoon en persoonlijke gegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je telefoon of gegevensverlies als gevolg van het gebruik van de app."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Je tablet en persoonlijke gegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je tablet of gegevensverlies als gevolg van het gebruik van de app."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Je tv en persoonlijke gegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je tv of gegevensverlies als gevolg van het gebruik van de app."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Doorgaan"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Instellingen"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear-apps installeren/verwijderen"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-notround-watch/dimens.xml b/packages/PackageInstaller/res/values-notround-watch/dimens.xml
new file mode 100644
index 0000000..55d6248
--- /dev/null
+++ b/packages/PackageInstaller/res/values-notround-watch/dimens.xml
@@ -0,0 +1,23 @@
+<?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>
+    <!-- Dimens for dialog layouts -->
+    <dimen name="diag_button_size">44dp</dimen>
+    <dimen name="diag_preferred_padding">8dp</dimen>
+    <dimen name="diag_button_padding_horizontal">16dp</dimen>
+    <dimen name="diag_button_padding_bottom">8dp</dimen>
+    <dimen name="diag_icon_margin_top">8dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-or-television/strings.xml b/packages/PackageInstaller/res/values-or-television/strings.xml
new file mode 100644
index 0000000..157b922
--- /dev/null
+++ b/packages/PackageInstaller/res/values-or-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"ମନାକରନ୍ତୁ ଏବଂ ପୁଣି ପଚାରନ୍ତୁ ନାହିଁ"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"ସେଟିଙ୍ଗ ଓ ଆପ୍‌ରେ ଏହାକୁ ଆପଣ ପରେ ବଦଳାଇପାରିବେ"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"ସିଷ୍ଟମ୍‍ ଆପ୍‍ ଦେଖାନ୍ତୁ"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"ଆପ୍‌ର ଅନୁମତି"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"ଆପ୍‌ର ଅନୁମତି"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> ଅନୁମତି"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"ଅତିରିକ୍ତ ଅନୁମତି"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> ଅନୁମତି"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-or-watch/strings.xml b/packages/PackageInstaller/res/values-or-watch/strings.xml
new file mode 100644
index 0000000..b7719a1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-or-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ମନାକରନ୍ତୁ, ପୁଣି ପଚାରନ୍ତୁ ନାହିଁ"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"ସିଷ୍ଟମ୍‍ ଆପ୍‍ ଦେଖାନ୍ତୁ"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ବଦଳାଯାଇପାରିବ ନାହିଁ"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"ହଁ"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
new file mode 100644
index 0000000..8d93c6f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"ପ୍ୟାକେଜ୍‌ ଇନଷ୍ଟଲର୍‍"</string>
+    <string name="next" msgid="3057143178373252333">"ପରବର୍ତ୍ତୀ"</string>
+    <string name="install" msgid="5896438203900042068">"ଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ"</string>
+    <string name="done" msgid="3889387558374211719">"ହୋଇଗଲା"</string>
+    <string name="cancel" msgid="8360346460165114585">"କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ"</string>
+    <string name="installing" msgid="8613631001631998372">"ଇନଷ୍ଟଲ୍ କରାଯାଉଛି…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ଇନଷ୍ଟଲ୍‌ କରାଯାଉଛି…"</string>
+    <string name="install_done" msgid="3682715442154357097">"ଆପ୍‍ ଇନଷ୍ଟଲ୍‌ ହୋଇଗଲା।"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"ଏହି ଆପ୍ଲିକେଶନ୍‍ ଆପଣ ଇନଷ୍ଟଲ୍‍ କରିବେ କି? ଏହିଗୁଡ଼ିକୁ ଏହା ଆକ୍ସେସ୍‌ କରିପାରିବ:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"ଏହି ଆପ୍ଲିକେଶନ୍‍ ଆପଣ ଇନଷ୍ଟଲ୍‍ କରିବେ କି? ଏହା କୌଣସି ବିଶେଷ ପ୍ରକାରର ଆକ୍ସେସ୍‌ ଆବଶ୍ୟକ କରେନାହିଁ।"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"ପୂର୍ବରୁ ଥିବା ଏହି ଆପ୍ଲିକେଶନ୍‍ରେ ଆପଣ ଏକ ଅପଡେଟ୍‍ ଇନଷ୍ଟଲ୍‍ କରିବେ କି? ଏଥିରେ ଥିବା ଆପଣଙ୍କ ଡାଟା ନଷ୍ଟ ହେବନାହିଁ। ଅପଡେଟ୍‍ ହେବାପରେ ଆପ୍ଲିକେଶନ୍‍‍ଟି ଏହିଗୁଡ଼ିକୁ ଆକ୍ସେସ୍‌ କରିପାରିବ:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"ଏହି ବିଲ୍ଟ-ଇନ୍‌ ଆପ୍ଲିକେଶନ୍‍ରେ ଆପଣ ଏକ ଅପଡେଟ୍‍ ଇନଷ୍ଟଲ୍‍ କରିବେ କି? ଏଥିରେ ଥିବା ଆପଣଙ୍କ ଡାଟା ନଷ୍ଟ ହେବନାହିଁ। ଅପଡେଟ୍‍ ହେବାପରେ ଆପ୍ଲିକେଶନ୍‍‍ଟି ଏହିଗୁଡ଼ିକୁ ଆକ୍ସେସ୍‌ କରିପାରିବ:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"ଆପଣ ବର୍ତ୍ତମାନର ଏହି ଆପ୍ଲିକେଶନ୍‍ର ଏକ ଅପଡେଟ୍‌ ଇନଷ୍ଟଲ୍‍ କରିବାକୁ ଚାହୁଁଛନ୍ତି କି? ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ଡାଟା ନଷ୍ଟ ହେବନାହିଁ। ଏଥିରେ କୌଣସି ବିଶେଷ ଆକ୍ସେସ୍‍ର ଆବଶ୍ୟକତା ନାହିଁ।"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"ଆପଣ ବର୍ତ୍ତମାନର ଏହି ବିଲ୍ଟ-ଇନ୍‍ ଆପ୍ଲିକେଶନ୍‍ର ଏକ ଅପଡେଟ୍‌ ଇନଷ୍ଟଲ୍‍ କରିବାକୁ ଚାହୁଁଛନ୍ତି କି? ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ଡାଟା ନଷ୍ଟ ହେବନାହିଁ। ଏଥିରେ କୌଣସି ବିଶେଷ ଆକ୍ସେସ୍‍ର ଆବଶ୍ୟକତା ନାହିଁ।"</string>
+    <string name="install_failed" msgid="6579998651498970899">"ଆପ୍‍ ଇନଷ୍ଟଲ୍‌ ହୋଇନାହିଁ।"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ଏହି ପ୍ୟାକେଜ୍‌କୁ ଇନଷ୍ଟଲ୍‍ କରାଯିବାରେ ଅବରୋଧ କରାଯାଇଥିଲା।"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"ପୂର୍ବରୁ ଥିବା ପ୍ୟାକେଜ୍‍ ସହ ଏହି ପ୍ୟାକେଜ୍‌ର ସମସ୍ୟା ଉପୁଯିବାରୁ ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ ହୋଇପାରିଲା ନାହିଁ।"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"ଆପ୍‍ ଆପଣଙ୍କ ଟାବଲେଟ୍‌ ସହ କମ୍ପାଟିବଲ୍‍ ନଥିବା ହେତୁ ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ ହୋଇପାରିଲା ନାହିଁ।"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"ଏହି ଆପ୍‍, ଆପଣଙ୍କ ଟିଭି ସହ କମ୍ପାଟିବଲ୍‍ ନୁହେଁ।"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"ଆପ୍‍ ଆପଣଙ୍କ ଫୋନ୍‌ ସହ କମ୍ପାଟିବଲ୍‍ ନଥିବା ହେତୁ ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ ହୋଇପାରିଲା ନାହିଁ।"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"ପ୍ୟାକେଜ୍‍ ଅମାନ୍ୟ ଥିବା ପରି ଜଣାପଡ଼ିବାରୁ ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ ହୋଇପାରିଲା ନାହିଁ।"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g>ଟି ଆପଣଙ୍କ ଟାବଲେଟ୍‍ରେ ଇନଷ୍ଟଲ୍‌ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କ ଟିଭିରେ ଇନଷ୍ଟଲ୍‍ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g>ଟି ଆପଣଙ୍କ ଫୋନ୍‍ରେ ଇନଷ୍ଟଲ୍‌ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
+    <string name="launch" msgid="4826921505917605463">"ଖୋଲନ୍ତୁ"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"ଅଜଣା ସୋର୍ସରୁ ଆସିଥିବା ଆପଗୁଡ଼ିକ ଇନଷ୍ଟଲ୍‌ କରିବାକୁ ଆପଣଙ୍କ ଆଡମିନ୍‍ ଅନୁମତି ଦିଅନ୍ତି ନାହିଁ"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"ଏହି ୟୁଜରଙ୍କ ଦ୍ୱାରା ଅଜଣା ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ କରାଯାଇ ପାରିବ ନାହିଁ"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"ଏହି ୟୁଜର୍‌ ଜଣକ ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ କରିପାରିବେ ନାହିଁ"</string>
+    <string name="ok" msgid="3468756155452870475">"ଠିକ୍‍ ଅଛି"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"ଆପ୍‌ଗୁଡ଼ିକର ପରିଚାଳନା କରନ୍ତୁ"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"ଆଉ ସ୍ଥାନ ନାହିଁ"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଇନଷ୍ଟଲ୍‌ କରାଯାଇପାରିଲା ନାହିଁ। କିଛି ସ୍ଥାନ ଖାଲିକରି ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"ଆପ୍‍ ମିଳିଲା ନାହିଁ"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ଇନଷ୍ଟଲ୍‌ କରାଯାଇଥିବା ଆପ୍‍ ତାଲିକାରେ ଆପ୍‍ଟି ମିଳିଲା ନାହିଁ।"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"ଅନୁମତି ଦିଆଯାଇନାହିଁ"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"ଏହି ଅନଇନଷ୍ଟଲେଶନ୍‍ କରିବାକୁ ବର୍ତ୍ତମାନର ୟୁଜରଙ୍କୁ ଅନୁମତି ଦିଆଯାଇନାହିଁ।"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"ତ୍ରୁଟି"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"ଆପ୍‍ ଅନଇନଷ୍ଟଲ୍‍ କରାହେଲା ନାହିଁ"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"ଆପ୍‍ ଅନଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"ଅପଡେଟ୍‍ ଅନଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ହେଉଛି ନିମ୍ନ ଆପ୍‍ର ଏକ ଅଂଶ।"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"ଆପଣ ଏହି ଆପ୍‍ ଅନଇନଷ୍ଟଲ୍‌ କରିବାକୁ ଚାହାଁନ୍ତି କି?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"ଆପଣ "<b>"ସମସ୍ତ"</b>" ୟୁଜର୍‌ଙ୍କ ପାଇଁ ଏହି ଆପ୍‌କୁ ଅନଷ୍ଟଲ୍‍ କରିବାକୁ ଚାହୁଁଛନ୍ତି କି? ଡିଭାଇସ୍‌ରେ ଥିବା "<b>"ସମସ୍ତ"</b>" ୟୁଜର୍‌ ଆପ୍ଲିକେଶନ୍‍ ଏବଂ ତାହାର ଡାଟା ବାହାର କରିଦିଆଯିବ।"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"ୟୁଜର୍‌ <xliff:g id="USERNAME">%1$s</xliff:g>ଙ୍କ ପାଇଁ ଆପଣ ଏହି ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ କରିବେ କି?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ଏହି ଆପ୍‍ ଫ୍ୟାକ୍ଟୋରୀ ଭର୍ସନ୍‍‍ ସହ ବଦଳାଇବେ? ସମସ୍ତ ଡାଟା କାଢ଼ିଦିଆଯିବ।"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ଏହି ଆପ୍‍ ଫ୍ୟାକ୍ଟୋରୀ ଭର୍ସନ୍‍‍ ସହ ବଦଳାଇବେ? ସମସ୍ତ ଡାଟା ବାହାର କରିଦିଆଯିବ। ୱର୍କ ପ୍ରୋଫାଇଲ୍‍ ଥିବା ସମେତ, ଏହାଦ୍ୱାରା ଡିଭାଇସରେ ଥିବା ସମସ୍ତ ୟୁଜର୍‌ ପ୍ରଭାବିତ ହେବେ।"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"ଅନଇନଷ୍ଟଲ୍‌ ଚାଲୁଛି"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"ଅନଇନଷ୍ଟଲ୍‌ କରାଯାଇ ପାରିଲା ନାହିଁ"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"ଅନଇନଷ୍ଟଲ୍‌ କରାଯାଉଛି…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ଅନଇନଷ୍ଟଲ୍‍ କରାଯାଉଛି…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"ଅନଇନଷ୍ଟଲ୍‌ ହୋଇଗଲା।"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ଅନଇନଷ୍ଟଲ୍‌ କରାଗଲା"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"ଅନଇନଷ୍ଟଲ୍‌ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ଅନଇନଷ୍ଟଲ୍‍ କରିବା ସଫଳ ହେଲାନାହିଁ।"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"ସକ୍ରିୟ ଡିଭାଇସ୍‍ ଆପ୍‍ ଅନଇନଷ୍ଟଲ୍‌ କରିପାରିବ ନାହିଁ"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g>ଙ୍କ ପାଇଁ ସକ୍ରିୟ ଡିଭାଇସ୍‍ ଆଡମିନ୍‍ ଆପ୍‍ ଅନଇନଷ୍ଟଲ୍‍ କରାଯାଇ ପାରିବ ନାହିଁ"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"କିଛି ୟୁଜର୍‌ କିମ୍ବା ପ୍ରୋଫାଇଲ୍‍ ପାଇଁ ଏହି ଆପ୍‍ ଆବଶ୍ୟକ ଏବଂ ଅନ୍ୟ ସମସ୍ତଙ୍କ ପାଇଁ ଅନଇନଷ୍ଟଲ୍‍ କରାଯାଇଥିଲା"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"ଏହି ଆପ୍‍ ଆପଣଙ୍କ ପ୍ରୋଫାଇଲ୍‍ ପାଇଁ ଆବଶ୍ୟକ ଅଟେ ଏବଂ ଅନଇନଷ୍ଟଲ୍‍ କରାଯାଇପାରିବ ନାହିଁ।"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"ଆପଣଙ୍କ ଡିଭାଇସ୍‍ ଆଡମିନିଷ୍ଟ୍ରେଟର୍‍ ଏହି ଆପ୍‍ ଆବଶ୍ୟକ କରନ୍ତୁ ଏବଂ ଏହାକୁ ଅନ୍‍ଇନଷ୍ଟଲ୍‍ କରାଯାଇପାରିବ ନାହିଁ।"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"ଡିଭାଇସ୍‌ ଆଡମିନ୍‌ ଆପ୍‌ ପରିଚାଳନା କରନ୍ତୁ"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ୟୁଜର୍‌ଙ୍କୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଅନଇନଷ୍ଟଲ୍‍ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"ଏହି ପ୍ୟାକେଜ୍‍ ପାର୍ସ କରିବାରେ ସମସ୍ୟା ଥିଲା।"</string>
+    <string name="newPerms" msgid="6039428254474104210">"ନୂଆ"</string>
+    <string name="allPerms" msgid="1024385515840703981">"ସମସ୍ତ"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"ଗୋପନୀୟତା"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"ଡିଭାଇସ୍ ଆକ୍ସେସ୍‌"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"ଏହି ଅପଡେଟ୍‍ କୌଣସି ନୂଆ ଅନୁମତି ଆବଶ୍ୟକ କରେନାହିଁ"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"ପ୍ରତ୍ୟାଖ୍ୟାନ"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"ଅଧିକ ସୂଚନା"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"ତଥାପି ଖାରଜ କରନ୍ତୁ"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>ଟିରୁ <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>ଟି"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ <xliff:g id="ACTION">%2$s</xliff:g> ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ସବୁବେଳେ <xliff:g id="ACTION">%2$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"କେବଳ ଆପ୍‍ ବ୍ୟବହାର କରୁଥିବା ସମୟରେ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ସର୍ବଦା"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"ମନାକରନ୍ତୁ ଏବଂ ପୁଣି ପଚାରନ୍ତୁ ନାହିଁ"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g>ଟି ଅକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"ସମସ୍ତ ଅକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"କିଛିବି ଅକ୍ଷମ କରାଯାଇନାହିଁ"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"ଆପ୍‌‍"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"ଆପ୍‌ ଅନୁମତି"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"ପୁଣି ପଚାରନ୍ତୁ ନାହିଁ"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"କୌଣସି ଅନୁମତି ନାହିଁ"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"ଅତିରିକ୍ତ ଅନୁମତି"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"ଆପ୍‌ର ତଥ୍ୟ ଖୋଲନ୍ତୁ"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"ଏହି ଆପ୍‍ Androidର ଏକ ପୁରୁଣା ସଂସ୍କରଣ ପାଇଁ ଡିଜାଇନ୍‍ କରାଯାଇଥିଲା। ଅନୁମତି ପ୍ରତ୍ୟାଖ୍ୟାନ କରିବା ଦ୍ୱାରା ଏହା ଠିକ୍‍ ଭାବେ ଆଉ କାମ ନକରିପାରେ।"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ଏକ ଅଜଣା କାମ କରେ"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g>ଟି ଆପରୁ <xliff:g id="COUNT_0">%1$d</xliff:g>ଟିକୁ ଅନୁମତି ଦିଆଯାଇଛି"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"ସିଷ୍ଟମ୍‌କୁ ଦେଖାନ୍ତୁ"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"ସିଷ୍ଟମ୍‌କୁ ଲୁଚାନ୍ତୁ"</string>
+    <string name="no_apps" msgid="1965493419005012569">"କୌଣସି ଆପ୍‌ ନାହିଁ"</string>
+    <string name="location_settings" msgid="1774875730854491297">"ଲୋକେଶନ୍‌ ସେଟିଙ୍ଗ"</string>
+    <string name="location_warning" msgid="8778701356292735971">"ଏହି ଡିଭାଇସ୍‍ ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଲୋକେଶନ୍‍ ସେବା ପ୍ରଦାନ କରେ। ଲୋକେଶନ୍‍ ସେଟିଙ୍ଗରୁ ଲୋକେଶନ୍‍ ଆକ୍ସେସ୍‍ ସଂଶୋଧନ କରାଯାଇପାରିବ।"</string>
+    <string name="system_warning" msgid="7103819124542305179">"ଏହି ଅନୁମତିକୁ ଯଦି ଆପଣ ପ୍ରତ୍ୟାଖ୍ୟାନ କରନ୍ତି, ଆପଣଙ୍କ ଡିଭାଇସ୍‌ର ସାଧାରଣ ସୁବିଧାଗୁଡ଼ିକ ଆଉ କାମ ନକରିପାରେ।"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"ପଲିସୀ ଦ୍ୱାରା ଲାଗୁ"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"ନିତୀ ଅନୁସାରେ ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡ ଆକ୍ସେସ୍‌ ଅକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"ନିତୀ ଅନୁସାରେ ପୃଷ୍ଠପଟ ଆକ୍ସେସ୍‌ ସକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"ନିତୀ ଅନୁସାରେ ସମ୍ମୁଖଭାଗ ଆକ୍ସେସ୍‌ ସକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"ଆଡ୍‌ମିନ୍‌ ଦ୍ୱାରା ନିୟନ୍ତ୍ରିତ"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ସର୍ବଦା"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"କେବଳ ଆପ୍‍ ବ୍ୟବହାର କରୁଥିବା ସମୟରେ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"କେବେ ନୁହେଁ"</string>
+    <string name="loading" msgid="7811651799620593731">"ଲୋଡ୍ କରାଯାଉଛି…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"ସମସ୍ତ ଅନୁମତି"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"ଅନ୍ୟାନ୍ୟ ଆପ୍‍ ଦକ୍ଷତା"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"ଅନୁମତି ଅନୁରୋଧ"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"ସ୍କ୍ରୀନ୍‍ ଓଭର୍‌ଲେ ଚିହ୍ନଟ ହୋଇଛି"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ଏହି ଅନୁମତି ସେଟିଙ୍ଗ ବଦଳାଇବାକୁ, ପ୍ରଥମେ ଆପଣ ସେଟିଙ୍ଗ ଓ ଆପ୍‌ରୁ ସ୍କ୍ରୀନ୍‍ ଅଫ୍‍ କରନ୍ତୁ"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"ସେଟିଙ୍ଗ ଖୋଲନ୍ତୁ"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android ୱିୟର୍‍"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wearରେ ଇନଷ୍ଟଲ୍‍/ଅନଇନଷ୍ଟଲ୍‍ କାର୍ଯ୍ୟ ସପୋର୍ଟ କରେ ନାହିଁ।"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ଆକ୍ସେସ୍‍ କରିବା ପାଇଁ କ\'ଣ କ\'ଣ ଅନୁମତି ଦିଆଯିବ, ତାହା ବାଛନ୍ତୁ"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ଅପଡେଟ୍‍ କରାଯାଇଛି। ଏହି ଆପ୍‍ କ\'ଣ କ\'ଣ ଆକ୍ସେସ୍‍ କରିପାରିବ, ତାହା ବାଛନ୍ତୁ।"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"ଜାରି ରଖନ୍ତୁ"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"ନୂଆ ଅନୁମତି"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"ବର୍ତ୍ତମାନର ଅନୁମତି"</string>
+    <string name="message_staging" msgid="6151794817691100003">"ଆପ୍‍ ପର୍ଯ୍ୟାୟଭୁକ୍ତ କରାଯାଉଛି…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"ଅଜଣା"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"ଆପଣଙ୍କ ସୁରକ୍ଷା ପାଇଁ, ଆପଣଙ୍କ ଟାବଲେଟକୁ ଏହି ସୋର୍ସରୁ ଆସିଥିବା ଅଜଣା ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ।"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"ଆପଣଙ୍କ ସୁରକ୍ଷା ପାଇଁ, ଆପଣଙ୍କ ଟିଭିକୁ ଏହି ସୋର୍ସରୁ ଆସିଥିବା ଅଜଣା ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ।"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"ଆପଣଙ୍କ ସୁରକ୍ଷା ପାଇଁ, ଆପଣଙ୍କ ଫୋନକୁ ଏହି ସୋର୍ସରୁ ଆସିଥିବା ଅଜଣା ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ।"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"ଅଜଣା ଆପ୍‌ ଦ୍ୱାରା ଆପଣଙ୍କ ଫୋନ୍‍ ଏବଂ ବ୍ୟକ୍ତିଗତ ଡାଟାକୁ ନଷ୍ଟ କରାଯାଇ ପାରିବାର ସମ୍ଭାବନା ବହୁତ ଅଧିକ। ଏହି ଆପଜୁ ଇନଷ୍ଟଲ୍‌ କରିବାର ଅର୍ଥ, ଆପଣଙ୍କ ଫୋନରେ ଘଟିବା କୌଣସି ପ୍ରକାର କ୍ଷତି କିମ୍ବା ସେଗୁଡ଼ିକର ବ୍ୟବହାରରୁ ହେବା କୌଣସି ପ୍ରକାର ଡାଟାର ହାନୀ ପାଇଁ ଆପଣ ଦାୟୀ ରହିବାକୁ ରାଜି ହୁଅନ୍ତି।"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"ଅଜଣା ଆପ୍‌ ଦ୍ୱାରା ଆପଣଙ୍କ ଟାବଲେଟ୍‍ ଏବଂ ବ୍ୟକ୍ତିଗତ ଡାଟାକୁ ନଷ୍ଟ କରାଯାଇ ପାରିବାର ସମ୍ଭାବନା ବହୁତ ଅଧିକ। ଏହି ଆପଜୁ ଇନଷ୍ଟଲ୍‌ କରିବାର ଅର୍ଥ, ଆପଣଙ୍କ ଟାବଲେଟରେ ଘଟିବା କୌଣସି ପ୍ରକାର କ୍ଷତି କିମ୍ବା ସେଗୁଡ଼ିକର ବ୍ୟବହାରରୁ ହେବା କୌଣସି ପ୍ରକାର ଡାଟାର ହାନୀ ପାଇଁ ଆପଣ ଦାୟୀ ରହିବାକୁ ରାଜି ହୁଅନ୍ତି।"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"ଅଜଣା ଆପ୍‌ ଦ୍ୱାରା ଆପଣଙ୍କ ଟିଭି ଏବଂ ବ୍ୟକ୍ତିଗତ ଡାଟାକୁ ନଷ୍ଟ କରାଯାଇ ପାରିବାର ସମ୍ଭାବନା ବହୁତ ଅଧିକ। ଏହି ଆପଜୁ ଇନଷ୍ଟଲ୍‌ କରିବାର ଅର୍ଥ, ଆପଣଙ୍କ ଟିଭିରେ ଘଟିବା କୌଣସି ପ୍ରକାର କ୍ଷତି କିମ୍ବା ସେଗୁଡ଼ିକର ବ୍ୟବହାରରୁ ହେବା କୌଣସି ପ୍ରକାର ଡାଟାର ହାନୀ ପାଇଁ ଆପଣ ଦାୟୀ ରହିବାକୁ ରାଜି ହୁଅନ୍ତି।"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"ଜାରି ରଖନ୍ତୁ"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ସେଟିଙ୍ଗ"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"ୱେର୍‍ ଆପ୍‍ ଇନଷ୍ଟଲ୍‌/ଅନଇନଷ୍ଟଲ୍‍ କରାଯାଉଛି"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pa-television/strings.xml b/packages/PackageInstaller/res/values-pa-television/strings.xml
new file mode 100644
index 0000000..76d249c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pa-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"ਅਸਵੀਕਾਰ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਨਾ ਪੁੱਛੋ"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"ਤੁਸੀਂ ਇਸਨੂੰ ਬਾਅਦ ਵਿੱਚ ਸੈਟਿੰਗਾਂ &gt; ਐਪਾਂ ਵਿੱਚ ਬਦਲ ਸਕਦੇ ਹੋ"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"ਸਿਸਟਮ ਐਪਸ ਦਿਖਾਓ"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"ਐਪ ਇਜਾਜ਼ਤਾਂ"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"ਐਪ ਇਜਾਜ਼ਤਾਂ"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> ਇਜਾਜ਼ਤਾਂ"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"ਵਧੀਕ ਇਜਾਜ਼ਤਾਂ"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> ਇਜਾਜ਼ਤਾਂ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pa-watch/strings.xml b/packages/PackageInstaller/res/values-pa-watch/strings.xml
new file mode 100644
index 0000000..e093021
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pa-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ਅਸਵੀਕਾਰ ਕਰੋ, ਦੁਬਾਰਾ ਨਾ ਪੁੱਛੋ"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"ਸਿਸਟਮ ਐਪਸ ਦਿਖਾਓ"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"ਹਾਂ"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"ਰੱਦ ਕਰੋ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pa/strings.xml b/packages/PackageInstaller/res/values-pa/strings.xml
new file mode 100644
index 0000000..b364c78
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pa/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"ਪੈਕੇਜ ਸਥਾਪਨਾਕਾਰ"</string>
+    <string name="next" msgid="3057143178373252333">"ਅੱਗੇ"</string>
+    <string name="install" msgid="5896438203900042068">"ਸਥਾਪਤ ਕਰੋ"</string>
+    <string name="done" msgid="3889387558374211719">"ਹੋ ਗਿਆ"</string>
+    <string name="cancel" msgid="8360346460165114585">"ਰੱਦ ਕਰੋ"</string>
+    <string name="installing" msgid="8613631001631998372">"ਇੰਸਟੌਲ ਕਰ ਰਿਹਾ ਹੈ…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਨੂੰ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+    <string name="install_done" msgid="3682715442154357097">"ਐਪ ਇੰਸਟੌਲ ਕੀਤਾ।"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"ਕੀ ਤੁਸੀਂ ਇਹ ਐਪਲੀਕੇਸ਼ਨ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਹ ਇਸ ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਕਰੇਗਾ:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਸ ਲਈ ਕਿਸੇ ਖਾਸ ਪਹੁੰਚ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"ਕੀ ਤੁਸੀਂ ਇਸ ਮੌਜੂਦਾ ਐਪਲੀਕੇਸ਼ਨ ਤੇ ਇੱਕ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਤੁਹਾਡਾ ਮੌਜੂਦਾ ਡਾਟਾ ਨਸ਼ਟ ਕੀਤਾ ਜਾਏਗਾ। ਅੱਪਡੇਟ ਕੀਤੀ ਐਪਲੀਕੇਸ਼ਨ ਇਸ ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਕਰੇਗੀ:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"ਕੀ ਤੁਸੀਂ ਇਸ ਬਿਲਟ-ਇਨ ਐਪਲੀਕੇਸ਼ਨ ਤੇ ਇੱਕ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਤੁਹਾਡਾ ਮੌਜੂਦਾ ਡਾਟਾ ਨਸ਼ਟ ਕੀਤਾ ਜਾਏਗਾ। ਅੱਪਡੇਟ ਕੀਤੀ ਐਪਲੀਕੇਸ਼ਨ ਇਸ ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਕਰੇਗੀ:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"ਕੀ ਤੁਸੀਂ ਇਸ ਮੌਜੂਦਾ ਐਪਲੀਕੇਸ਼ਨ ਵਿੱਚ ਇੱਕ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਤੁਹਾਡਾ ਮੌਜੂਦਾ ਡਾਟਾ ਨਸ਼ਟ ਨਹੀਂ ਹੋਵੇਗਾ। ਇਸ ਲਈ ਕਿਸੇ ਖਾਸ ਪਹੁੰਚ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"ਕੀ ਤੁਸੀਂ ਇਸ ਬਿਲਟ-ਇਨ ਐਪਲੀਕੇਸ਼ਨ ਵਿੱਚ ਇੱਕ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਤੁਹਾਡਾ ਮੌਜੂਦਾ ਡਾਟਾ ਨਸ਼ਟ ਨਹੀਂ ਹੋਵੇਗਾ। ਇਸ ਲਈ ਕਿਸੇ ਖਾਸ ਪਹੁੰਚ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।"</string>
+    <string name="install_failed" msgid="6579998651498970899">"ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ।"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ਪੈਕੇਜ ਨੂੰ ਸਥਾਪਿਤ ਹੋਣ ਤੋਂ ਬਲੌਕ ਕੀਤਾ ਗਿਆ ਸੀ।"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"ਪੈਕੇਜ ਦੇ ਇੱਕ ਮੌਜੂਦਾ ਪੈਕੇਜ ਨਾਲ ਵਿਵਾਦ ਹੋਣ ਕਰਕੇ ਐਪ ਦੀ ਸਥਾਪਨਾ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"ਐਪ ਦੇ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ ਦੇ ਅਨੁਰੂਪ ਨਾ ਹੋਣ ਕਰਕੇ ਐਪ ਦੀ ਸਥਾਪਨਾ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੀਵੀ ਦੇ ਅਨੁਕੂਲ ਨਹੀਂ ਹੈ।"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"ਐਪ ਦੇ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੇ ਅਨੁਰੂਪ ਨਾ ਹੋਣ ਕਰਕੇ ਐਪ ਦੀ ਸਥਾਪਨਾ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"ਪੈਕੇਜ ਦੇ ਅਵੈਧ ਪ੍ਰਤੀਤ ਹੋਣ ਕਰਕੇ ਐਪ ਦੀ ਸਥਾਪਨਾ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀ ਟੈਬਲੈੱਟ ਤੇ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ।"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੇ TV ਤੇ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ।"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੇ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ।"</string>
+    <string name="launch" msgid="4826921505917605463">"ਖੋਲ੍ਹੋ"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"ਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਅਗਿਆਤ ਸਰੋਤਾਂ ਤੋਂ ਪ੍ਰਾਪਤ ਐਪਾਂ ਸਥਾਪਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੰਦਾ"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"ਇਸ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਅਗਿਆਤ ਐਪਾਂ ਨੂੰ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਐਪਾਂ ਸਥਾਪਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
+    <string name="ok" msgid="3468756155452870475">"ਠੀਕ"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"ਐਪਸ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"ਖਾਲੀ ਸਪੇਸ"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਕੁਝ ਸਪੇਸ ਖਾਲੀ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"ਐਪ ਨਹੀਂ ਮਿਲਿਆ"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ਐਪ ਇੰਸਟੌਲ ਕੀਤੇ ਐਪਸ ਦੀ ਸੂਚੀ ਵਿੱਚ ਨਹੀਂ ਮਿਲਿਆ ਸੀ।"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"ਇਜਾਜ਼ਤ ਨਹੀਂ"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"ਮੌਜੂਦਾ ਵਰਤੋਂਕਾਰ ਨੂੰ ਇਹ ਅਣਸਥਾਪਨਾ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"ਗੜਬੜ"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"ਐਪ ਅਣਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ।"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"ਐਪ ਅਣਸਥਾਪਤ ਕਰੋ"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"ਅੱਪਡੇਟ ਅਣਸਥਾਪਤ ਕਰੋ"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ਇਸ ਐਪ ਦਾ ਭਾਗ ਹੈ:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ "<b>"ਸਾਰੇ"</b>" ਵਰਤੋਂਕਾਰਾਂ ਲਈ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਐਪਲੀਕੇਸ਼ਨ ਅਤੇ ਇਸਦਾ ਡਾਟਾ ਡੀਵਾਈਸ ਤੇ "<b>"ਸਾਰੇ"</b>" ਵਰਤੋਂਕਾਰਾਂ ਵੱਲੋਂ ਹਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"ਕੀ ਤੁਸੀਂ ਵਰਤੋਂਕਾਰ <xliff:g id="USERNAME">%1$s</xliff:g> ਲਈ ਇਸ ਐਪ ਨੂੰ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ਕੀ ਇਸ ਐਪ ਨੂੰ ਫੈਕਟਰੀ ਸੰਸਕਰਣ ਨਾਲ ਬਦਲਣਾ ਹੈ? ਸਾਰਾ  ਡਾਟਾ  ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ਕੀ ਇਸ ਐਪ ਨੂੰ ਫੈਕਟਰੀ ਵਰਜਨ ਨਾਲ ਬਦਲਣਾ ਹੈ? ਸਾਰਾ ਡਾਟਾ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ। ਇਹ ਇਸ ਡੀਵਾਈਸ ਦੇ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਪ੍ਰਭਾਵਿਤ ਕਰੇਗਾ, ਜਿਸ ਵਿੱਚ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਾਲੇ ਵਰਤੋਂਕਾਰ ਵੀ ਸ਼ਾਮਲ ਹਨ।"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"ਚੱਲ ਰਹੀਆਂ ਅਣਸਥਾਪਨਾਵਾਂ"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"ਅਸਫਲ ਅਣਸਥਾਪਨਾਵਾਂ"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"ਅਣਇੰਸਟੌਲ ਕਰ  ਰਿਹਾ ਹੈ…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਨੂੰ ਅਣਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"ਅਣਸਥਾਪਨਾ ਪੂਰੀ ਹੋਈ।"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਨੂੰ ਅਣਸਥਾਪਤ ਕੀਤਾ"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"ਅਣਸਥਾਪਨਾ ਅਸਫਲ।"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਨੂੰ ਅਣਸਥਾਪਤ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ।"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"ਕਿਰਿਆਸ਼ੀਲ ਡੀਵਾਈਸ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਨੂੰ ਅਣਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> ਲਈ ਕਿਰਿਆਸ਼ੀਲ ਡੀਵਾਈਸ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਨੂੰ ਅਣਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"ਇਹ ਐਪ ਕੁਝ ਵਰਤੋਂਕਾਰਾਂ ਜਾਂ ਪ੍ਰੋਫਾਈਲਾਂ ਲਈ ਲੋੜੀਂਦੀ ਹੈ ਅਤੇ ਹੋਰਾਂ ਲਈ ਅਣਸਥਾਪਤ ਕੀਤੀ ਗਈ ਸੀ"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"ਇਹ ਐਪ ਤੁਹਾਡੀ ਪ੍ਰੋਫਾਈਲ ਲਈ ਲੋੜੀਂਦੀ ਹੈ ਅਤੇ ਇਸ ਨੂੰ ਅਣਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਕ ਵੱਲੋਂ ਲੋੜੀਂਦੀ ਹੈ ਅਤੇ ਇਸਨੂੰ ਅਣਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"ਡੀਵਾਈਸ ਪ੍ਰਸ਼ਾਸਕ ਐਪਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
+    <string name="manage_users" msgid="3125018886835668847">"ਵਰਤੋਂਕਾਰਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਅਣਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ।"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"ਪੈਕੇਜ ਨੂੰ ਪਾਰਸ ਕਰਨ ਵਿੱਚ ਇੱਕ ਸਮੱਸਿਆ ਸੀ।"</string>
+    <string name="newPerms" msgid="6039428254474104210">"ਨਵਾਂ"</string>
+    <string name="allPerms" msgid="1024385515840703981">"ਸਭ"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"ਪ੍ਰਾਈਵੇਸੀ"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"ਡੀਵਾਈਸ ਪਹੁੰਚ"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"ਇਸ ਅੱਪਡੇਟ ਲਈ ਕਿਸੇ ਨਵੀਆਂ ਅਨੁਮਤੀਆਂ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"ਹੋਰ ਜਾਣਕਾਰੀ"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"ਫੇਰ ਵੀ ਅਸਵੀਕਾਰ ਕਰੋ"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> ਦਾ <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ <xliff:g id="ACTION">%2$s</xliff:g> ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"ਹਮੇਸ਼ਾਂ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ <xliff:g id="ACTION">%2$s</xliff:g> ਕਰਨ ਦਿਓ?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"ਸਿਰਫ਼ ਐਪ ਵਰਤਣ ਵੇਲੇ"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ਹਮੇਸ਼ਾਂ"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"ਅਸਵੀਕਾਰ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਨਾ ਪੁੱਛੋ"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"ਸਭ ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ਕਿਸੇ ਨੂੰ ਵੀ ਅਯੋਗ ਨਹੀਂ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"ਆਗਿਆ ਦਿਓ"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"ਐਪਾਂ"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"ਐਪ ਇਜਾਜ਼ਤਾਂ"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"ਦੁਬਾਰਾ ਨਾ ਪੁੱਛੋ"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"ਕੋਈ ਇਜਾਜ਼ਤਾਂ ਨਹੀਂ ਹਨ"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"ਵਧੀਕ ਇਜਾਜ਼ਤਾਂ"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"ਐਪ ਜਾਣਕਾਰੀ ਖੋਲ੍ਹੋ"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"ਇਹ ਐਪ Android ਦੇ ਕਿਸੇ ਪੁਰਾਣੇ ਸੰਸਕਰਣ ਲਈ ਬਣਾਈ ਗਈ ਸੀ। ਅਨੁਮਤੀ ਨੂੰ ਇਨਕਾਰ ਕਰਨਾ ਇਸਦੇ ਉਦੇਸ਼ਿਤ ਫੰਕਸ਼ਨ ਨੂੰ ਪ੍ਰਭਾਵਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ਕੋਈ ਅਗਿਆਤ ਕਾਰਵਾਈ ਕਰੋ"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g> ਵਿੱਚੋਂ <xliff:g id="COUNT_0">%1$d</xliff:g> ਐਪਾਂ ਨੂੰ ਆਗਿਆ ਦਿੱਤੀ"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"ਸਿਸਟਮ ਦਿਖਾਓ"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"ਸਿਸਟਮ ਲੁਕਾਓ"</string>
+    <string name="no_apps" msgid="1965493419005012569">"ਕੋਈ ਐਪਾਂ ਨਹੀਂ"</string>
+    <string name="location_settings" msgid="1774875730854491297">"ਟਿਕਾਣਾ ਸੈਟਿੰਗਾਂ"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਇਸ ਡੀਵਾਈਸ ਲਈ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦਾ ਇੱਕ ਪ੍ਰਦਾਤਾ ਹੈ। ਟਿਕਾਣਾ ਪਹੁੰਚ ਨੂੰ ਟਿਕਾਣਾ ਸੈਟਿੰਗਾਂ ਤੋਂ ਸੰਸ਼ੋਧਿਤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।"</string>
+    <string name="system_warning" msgid="7103819124542305179">"ਜੇਕਰ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਨੂੰ ਅਸਵੀਕਾਰ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀਆਂ ਮੂੂਲ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਆਪਣੇ ਫੰਕਸ਼ਨ ਮੁਤਾਬਕ ਕੰਮ ਨਹੀਂ ਵੀ ਕਰ ਸਕਦੀਆਂ।"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"ਨੀਤੀ ਮੁਤਾਬਕ ਲਾਗੂ ਕੀਤਾ"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"ਨੀਤੀ ਵੱਲੋਂ ਬੈਕਗ੍ਰਾਊਂਡ ਪਹੁੰਚ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"ਨੀਤੀ ਵੱਲੋਂ ਬੈਕਗ੍ਰਾਊਂਡ ਪਹੁੰਚ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"ਨੀਤੀ ਵੱਲੋਂ ਫੋਰਗ੍ਰਾਊਂਡ ਪਹੁੰਚ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕੀਤੀ ਗਈ"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ਹਮੇਸ਼ਾਂ"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"ਸਿਰਫ਼ ਐਪ ਵਰਤਣ ਦੌਰਾਨ"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"ਕਦੇ ਵੀ ਨਹੀਂ"</string>
+    <string name="loading" msgid="7811651799620593731">"ਲੋਡ ਕਰ ਰਿਹਾ ਹੈ…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"ਸਾਰੀਆਂ ਅਨੁਮਤੀਆਂ"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"ਹੋਰ ਐਪ ਸਮਰੱਥਤਾਵਾਂ"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"ਇਜਾਜ਼ਤ ਬੇਨਤੀ"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"ਸਕਰੀਨ ਓਵਰਲੇਅ ਲੱਭ ਗਿਆ"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ਇਸ ਇਜ਼ਾਜਤ ਸੈਟਿੰਗ ਨੂੰ ਬਦਲਣ ਲਈ; ਤੁਹਾਨੂੰ ਪਹਿਲਾਂ ਸੈਟਿੰਗਾਂ ਅਤੇ ਐਪਾਂ ਤੋਂ ਸਕ੍ਰੀਨ ਓਵਰਲੇਅ ਬੰਦ ਕਰਨਾ ਪਵੇਗਾ"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"ਵੀਅਰ \'ਤੇ ਸਥਾਪਤ/ਅਣਸਥਾਪਤ ਕਾਰਵਾਈਆਂ ਸਮਰਥਿਤ ਨਹੀਂ ਹਨ।"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"ਇਹ ਚੁਣੋ ਕਿ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਕਿਸ \'ਤੇ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾ ਚੁੱਕਿਆ ਹੈ। ਇਹ ਚੁਣੋ ਕਿ ਇਸ ਐਪ ਨੂੰ ਕਿਸ \'ਤੇ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ।"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"ਰੱਦ ਕਰੋ"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"ਜਾਰੀ ਰੱਖੋ"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"ਨਵੀਆਂ ਇਜਾਜ਼ਤਾਂ"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"ਵਰਤਮਾਨ ਇਜਾਜ਼ਤਾਂ"</string>
+    <string name="message_staging" msgid="6151794817691100003">"ਐਪ ਨੂੰ ਪੜਾਅਬੱਧ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"ਅਗਿਆਤ"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"ਤੁਹਾਡੀ ਸੁਰੱਖਿਆ ਲਈ, ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ ਨੂੰ ਇਸ ਸਰੋਤ ਤੋਂ ਅਗਿਆਤ ਐਪਾਂ ਸਥਾਪਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ।"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"ਤੁਹਾਡੀ ਸੁਰੱਖਿਆ ਲਈ, ਤੁਹਾਡੇ ਟੀਵੀ ਨੂੰ ਇਸ ਸਰੋਤ ਤੋਂ ਅਗਿਆਤ ਐਪਾਂ ਸਥਾਪਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ।"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"ਤੁਹਾਡੀ ਸੁਰੱਖਿਆ ਲਈ, ਤੁਹਾਡੇ ਫ਼ੋਨ ਨੂੰ ਇਸ ਸਰੋਤ ਤੋਂ ਅਗਿਆਤ ਐਪਾਂ ਸਥਾਪਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ।"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਅਤੇ ਨਿੱਜੀ ਡਾਟਾ ਅਗਿਆਤ ਐਪਾਂ ਤੋਂ ਹਮਲੇ ਪ੍ਰਤੀ ਵਧੇਰੇ ਵਿੰਨਣਸ਼ੀਲ ਹਨ। ਇਹ ਐਪ ਸਥਾਪਤ ਕਰਕੇ, ਤੁਸੀਂ ਸਹਿਮਤੀ ਦਿੰਦੇ ਹੋ ਕਿ ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਹੋਣ ਵਾਲੇ ਕਿਸੇ ਵੀ ਨੁਕਸਾਨ ਜਾਂ ਡਾਟੇ ਦੀ ਹਾਨੀ ਲਈ ਤੁਸੀਂ ਜ਼ਿੰਮੇਵਾਰ ਹੋ ਜੋ ਸ਼ਾਇਦ ਇਸ ਐਪ ਨੂੰ ਵਰਤਣ ਦੇ ਨਤੀਜੇ ਵਜੋਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"ਤੁਹਾਡਾ ਟੈਬਲੈੱਟ ਅਤੇ ਨਿੱਜੀ ਡਾਟਾ ਅਗਿਆਤ ਐਪਾਂ ਤੋਂ ਹਮਲੇ ਪ੍ਰਤੀ ਵਧੇਰੇ ਕਮਜ਼ੋਰ ਹੈ। ਇਹ ਐਪ ਸਥਾਪਤ ਕਰਕੇ, ਤੁਸੀਂ ਸਹਿਮਤੀ ਦਿੰਦੇ ਹੋ ਕਿ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਹੋਣ ਵਾਲੇ ਕਿਸੇ ਵੀ ਨੁਕਸਾਨ ਜਾਂ ਡਾਟੇ ਦੀ ਹਾਨੀ ਲਈ ਤੁਸੀਂ ਜ਼ਿੰਮੇਵਾਰ ਹੋ ਜੋ ਸ਼ਾਇਦ ਇਸ ਐਪ ਨੂੰ ਵਰਤਣ ਦੇ ਨਤੀਜੇ ਵਜੋਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"ਤੁਹਾਡਾ ਟੀਵੀ ਅਤੇ ਨਿੱਜੀ  ਡਾਟਾ  ਅਗਿਆਤ ਐਪਾਂ ਤੋਂ ਹਮਲੇ ਪ੍ਰਤੀ ਵਧੇਰੇ ਵਿੰਨਣਸ਼ੀਲ ਹਨ। ਇਹ ਐਪ ਸਥਾਪਤ ਕਰਕੇ, ਤੁਸੀਂ ਸਹਿਮਤੀ ਦਿੰਦੇ ਹੋ ਕਿ ਆਪਣੇ ਟੀਵੀ ਨੂੰ ਹੋਣ ਵਾਲੇ ਕਿਸੇ ਵੀ ਨੁਕਸਾਨ ਜਾਂ  ਡਾਟੇ  ਦੀ ਹਾਨੀ ਲਈ ਤੁਸੀਂ ਜ਼ਿੰਮੇਵਾਰ ਹੋ ਜੋ ਸ਼ਾਇਦ ਇਸ ਐਪ ਨੂੰ ਵਰਤਣ ਦੇ ਨਤੀਜੇ ਵਜੋਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"ਜਾਰੀ ਰੱਖੋ"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"ਵੀਅਰ ਐਪਾਂ ਨੂੰ ਸਥਾਪਤ/ਅਣਸਥਾਪਤ ਕਰਨਾ"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pl-television/strings.xml b/packages/PackageInstaller/res/values-pl-television/strings.xml
new file mode 100644
index 0000000..6fede9a
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pl-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Odmów i nie pytaj ponownie"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Możesz to później zmienić, wybierając Ustawienia &gt; Aplikacje"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Pokaż aplikacje systemowe"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Uprawnienia aplikacji"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Uprawnienia aplikacji"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> – uprawnienia"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Dodatkowe uprawnienia"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> – uprawnienia"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pl-watch/strings.xml b/packages/PackageInstaller/res/values-pl-watch/strings.xml
new file mode 100644
index 0000000..95c3687
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pl-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Odmów i nie pytaj ponownie"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Pokaż aplikacje systemowe"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nie można zmienić"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Tak"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Anuluj"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pl/strings.xml b/packages/PackageInstaller/res/values-pl/strings.xml
new file mode 100644
index 0000000..dbedfad
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pl/strings.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Instalator pakietu"</string>
+    <string name="next" msgid="3057143178373252333">"Dalej"</string>
+    <string name="install" msgid="5896438203900042068">"Instaluj"</string>
+    <string name="done" msgid="3889387558374211719">"Gotowe"</string>
+    <string name="cancel" msgid="8360346460165114585">"Anuluj"</string>
+    <string name="installing" msgid="8613631001631998372">"Instalowanie..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instaluję pakiet <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikacja została zainstalowana."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Zainstalować tę aplikację? Będzie miała następujące uprawnienia:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Zainstalować tę aplikację? Nie ma specjalnych wymagań dotyczących dostępu."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Zainstalować aktualizację tej aplikacji? Nie utracisz wcześniejszych danych. Zaktualizowana aplikacja będzie miała następujące uprawnienia:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Zainstalować aktualizację fabrycznej aplikacji? Nie utracisz wcześniejszych danych. Zaktualizowana aplikacja będzie miała następujące uprawnienia:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Chcesz zaktualizować tę istniejącą aplikację? Nie utracisz danych. Nie są wymagane specjalne uprawnienia dostępu."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Chcesz zaktualizować tę wbudowaną aplikację? Nie utracisz danych. Nie są wymagane specjalne uprawnienia dostępu."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplikacja nie została zainstalowana."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Instalacja pakietu została zablokowana."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplikacja nie została zainstalowana, bo powoduje konflikt z istniejącym pakietem."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplikacja nie została zainstalowana, bo jest niezgodna z Twoim tabletem."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Aplikacja jest niezgodna z Twoim telewizorem."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplikacja nie została zainstalowana, bo jest niezgodna z Twoim telefonem."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplikacja nie została zainstalowana, bo pakiet wygląda na nieprawidłowy."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Nie można zainstalować aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> na Twoim tablecie."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Nie udało się zainstalować <xliff:g id="APP_NAME">%1$s</xliff:g> na Twoim telewizorze."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Nie można zainstalować aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> na Twoim telefonie."</string>
+    <string name="launch" msgid="4826921505917605463">"Otwórz"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Twój administrator nie zezwala na instalowanie aplikacji pochodzących z nieznanych źródeł."</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Ten użytkownik nie może instalować nieznanych aplikacji"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Ten użytkownik nie może instalować aplikacji"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Zarządzaj aplikacjami"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Brak miejsca"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Nie można zainstalować aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>. Zwolnij trochę miejsca i spróbuj ponownie."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Nie znaleziono aplikacji"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplikacji nie znaleziono na liście zainstalowanych programów."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Niedozwolone"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Bieżący użytkownik nie może tego odinstalować."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Błąd"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Nie można odinstalować aplikacji."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Odinstaluj aplikację"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Odinstaluj aktualizację"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> jest częścią następującej aplikacji:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Odinstalować tę aplikację?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Chcesz odinstalować tę aplikację dla "<b>"wszystkich"</b>" użytkowników? Ta aplikacja i jej dane zostaną usunięte dla "<b>"wszystkich"</b>" użytkowników na urządzeniu."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Chcesz odinstalować tę aplikację dla użytkownika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Przywrócić fabryczną wersję tej aplikacji? Wszystkie dane zostaną usunięte."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Przywrócić fabryczną wersję tej aplikacji? Wszystkie dane zostaną usunięte. Dotyczy to wszystkich użytkowników tego urządzenia, również tych korzystających z profilu do pracy."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Aktywne odinstalowania"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Nieudane odinstalowania"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Odinstalowywanie..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Odinstalowuję pakiet <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Odinstalowywanie zakończone"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Odinstalowano pakiet <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Nie udało się odinstalować."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Nie udało się odinstalować pakietu <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Nie można odinstalować aktywnej aplikacji do administrowania urządzeniem"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Nie można odinstalować aplikacji do administrowania urządzeniem aktywnej dla użytkownika <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Niektórzy użytkownicy i niektóre profile wymagają tej aplikacji, a w innych przypadkach została odinstalowana"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ta aplikacja jest potrzebna w Twoim profilu i nie można jej odinstalować."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Administrator urządzenia wymaga tej aplikacji i nie można jej odinstalować."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Zarządzaj aplikacjami do administrowania urządzeniem"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Zarządzaj użytkownikami"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Nie można odinstalować aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Podczas analizowania pakietu wystąpił problem."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nowe"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Wszystkie"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Prywatność"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Dostęp do urządzenia"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Ta aktualizacja nie wymaga nowych uprawnień."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Odmów"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Więcej informacji"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Odmów mimo to"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> z <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Zawsze zezwalać aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Tylko przy używaniu aplikacji"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Zawsze"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Odmów i nie pytaj ponownie"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"wyłączone: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"wszystkie wyłączone"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"brak wyłączonych"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Zezwól"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikacje"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Uprawnienia aplikacji"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Nie pytaj ponownie"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Brak uprawnień"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Dodatkowe uprawnienia"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Otwórz informacje o aplikacji"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="few">Jeszcze <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Jeszcze <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Jeszcze <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Jeszcze <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ta aplikacja jest na straszą wersję Androida. Jeśli odmówisz uprawnień, aplikacja może nie działać prawidłowo."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"wykonywanie nieznanych działań"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Dostęp ma: <xliff:g id="COUNT_0">%1$d</xliff:g> z <xliff:g id="COUNT_1">%2$d</xliff:g> aplikacji"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Pokaż systemowe"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ukryj systemowe"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Brak aplikacji"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Ustawienia lokalizacji"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> jest dostawcą usług lokalizacyjnych dla tego urządzenia. Dostęp do danych lokalizacji można zmienić w ustawieniach lokalizacji."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Jeśli nie przyznasz tych uprawnień, podstawowe funkcje urządzenia mogą nie działać prawidłowo."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Narzucone przez zasady"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Dostęp w tle wyłączony przez zasady"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Dostęp w tle włączony przez zasady"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Dostęp na pierwszym planie włączony przez zasady"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Kontrolowane przez administratora"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Zawsze"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Tylko przy używaniu aplikacji"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nigdy"</string>
+    <string name="loading" msgid="7811651799620593731">"Ładuję…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Wszystkie uprawnienia"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Inne funkcje aplikacji"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Prośba o pozwolenie"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Wykryto nakładkę ekranową"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Aby zmodyfikować te uprawnienia, musisz najpierw wyłączyć nakładkę ekranową, klikając Ustawienia &gt; Aplikacje"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Otwórz ustawienia"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear nie obsługuje instalowania ani odinstalowywania."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Wybierz, jakie uprawnienia dostępu ma mieć &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Aplikacja &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; została zaktualizowana. Wybierz dla niej uprawnienia dostępu."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Anuluj"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Dalej"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nowe uprawnienia"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Aktualne uprawnienia"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Przygotowuję aplikację…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Nieznana"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Ze względów bezpieczeństwa na Twoim tablecie nie można instalować nieznanych aplikacji z tego źródła."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Ze względów bezpieczeństwa na Twoim telewizorze nie można instalować nieznanych aplikacji z tego źródła."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Ze względów bezpieczeństwa na Twoim telefonie nie można instalować nieznanych aplikacji z tego źródła."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Dane na telefonie i prywatne są bardziej narażone na atak nieznanych aplikacji. Instalując tę aplikację, bierzesz na siebie odpowiedzialność za ewentualne uszkodzenie telefonu lub utratę danych w wyniku jej używania."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Dane na tablecie i prywatne są bardziej narażone na atak nieznanych aplikacji. Instalując tę aplikację, bierzesz na siebie odpowiedzialność za ewentualne uszkodzenie tabletu lub utratę danych w wyniku jej używania."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Dane na telewizorze i prywatne są bardziej narażone na atak nieznanych aplikacji. Instalując tę aplikację, bierzesz na siebie odpowiedzialność za ewentualne uszkodzenie telewizora lub utratę danych w wyniku jej używania."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Dalej"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Ustawienia"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instalowanie/odinstalowywanie aplikacji na Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pt-rBR-television/strings.xml b/packages/PackageInstaller/res/values-pt-rBR-television/strings.xml
new file mode 100644
index 0000000..ba6e68f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pt-rBR-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Negar e não perguntar novamente"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"É possível alterar isso mais tarde em \"Config.\" &gt; \"Apps\""</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Mostrar apps do sistema"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Permissões do app"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Permissões do app"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Permissões para <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Outras permissões"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Permissões para <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pt-rBR-watch/strings.xml b/packages/PackageInstaller/res/values-pt-rBR-watch/strings.xml
new file mode 100644
index 0000000..8742c2d
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pt-rBR-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Negar e não perguntar de novo"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar apps do sistema"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Impossível alterar"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Sim"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancelar"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pt-rBR/strings.xml b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..feb2337
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Instalador do pacote"</string>
+    <string name="next" msgid="3057143178373252333">"Próximo"</string>
+    <string name="install" msgid="5896438203900042068">"Instalar"</string>
+    <string name="done" msgid="3889387558374211719">"Concluído"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancelar"</string>
+    <string name="installing" msgid="8613631001631998372">"Instalando..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"App instalado."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Quer instalar este app? Ele terá acesso a:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Quer instalar este app? Não requer acesso especial."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Quer instalar uma atualização para este app? Os dados existentes não serão perdidos. O app atualizado terá acesso a:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Quer instalar uma atualização para este app integrado? Os dados existentes não serão perdidos. O app atualizado terá acesso a:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Quer instalar uma atualização para este app existente? Seus dados existentes não serão perdidos. A atualização não requer qualquer acesso especial."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Quer instalar uma atualização para este app integrado? Seus dados existentes não serão perdidos. A atualização não requer qualquer acesso especial."</string>
+    <string name="install_failed" msgid="6579998651498970899">"O app não foi instalado."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"A instalação do pacote foi bloqueada."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Como o pacote tem um conflito com um pacote já existente, o app não foi instalado."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Como o app não é compatível com seu tablet, ele não foi instalado."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Este app não é compatível com sua TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Como o app não é compatível com seu smartphone, ele não foi instalado."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Como o pacote parece ser inválido, o app não foi instalado."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g> em seu tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g> na sua TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g> em seu telefone."</string>
+    <string name="launch" msgid="4826921505917605463">"Abrir"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Seu administrador não permite a instalação de apps transferidos por download de fontes desconhecidas"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Apps desconhecidos não podem ser instalados por este usuário"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Este usuário não tem permissão para instalar apps"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Gerenciar apps"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Sem espaço"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g>. Libere um pouco de espaço e tente novamente."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"App não encontrado"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"O app não foi encontrado na lista de apps instalados."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Não permitido"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"O usuário atual não tem permissão para executar essa desinstalação."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Erro"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Não foi possível desinstalar o app."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Desinstalar app"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Desinstalar atualização"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> é parte do seguinte app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Quer desinstalar este app?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Quer desinstalar este app para "<b>"todos"</b>" os usuários? O app e seus dados serão removidos para "<b>"todos"</b>" os usuários do dispositivo."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Quer desinstalar este app para o usuário <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Substituir este app pela versão de fábrica? Todos os dados serão removidos."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Substituir este app pela versão de fábrica? Todos os dados serão removidos. Isso afeta todos os usuários deste dispositivo, incluindo aqueles com perfis de trabalho."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Executando desinstalações"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Falha nas desinstalações"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Desinstalando..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Desinstalação concluída."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstalado"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Desinstalação malsucedida."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Falha na desinstalação de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Não é possível desinstalar o app para administrador ativo do dispositivo"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Não é possível desinstalar o app para administrador ativo do dispositivo de <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"O app é necessário para alguns usuários ou perfis e foi desinstalado para outros"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Este app é necessário para seu perfil e não pode ser desinstalado."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"O app é exigido pelo administrador do dispositivo e não pode ser desinstalado."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Gerenciar apps do administrador do dispositivo"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Gerenciar usuários"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Não foi possível desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Ocorreu um problema ao analisar o pacote."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Novas"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Todas"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacidade"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Acesso ao dispositivo"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Esta atualização não requer novas permissões."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Negar"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Mais informações"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Negar mesmo assim"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Sempre permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Apenas ao usar o app"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Sempre"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Negar e não perguntar novamente"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> desativada(s)"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"todas desativadas"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"nenhuma desativada"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Permitir"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apps"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Permissões do app"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Não perguntar novamente"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Sem permissões"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Outras permissões"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Abrir informações do app"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one">Mais <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Mais <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Este app foi projetado para uma versão anterior do Android. Negar a permissão pode fazer com que ele deixe de funcionar conforme esperado."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"executar uma ação desconhecida"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> de <xliff:g id="COUNT_1">%2$d</xliff:g> apps permitidos"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Mostrar sistema"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ocultar sistema"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nenhum app"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Configurações de localização"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> é um provedor de serviços de localização para este dispositivo. O acesso local pode ser modificado nas configurações de localização."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Se você negar essa permissão, recursos básicos do seu dispositivo poderão não funcionar mais como deveriam."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Aplicável por política"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Acesso em segundo plano desativado pela política"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Acesso em segundo plano ativado pela política"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Acesso em primeiro plano ativado pela política"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlada pelo administrador"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Sempre"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Apenas ao usar o app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nunca"</string>
+    <string name="loading" msgid="7811651799620593731">"Carregando…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Todas as permissões"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Outros recursos do app"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Solicitação de permissão"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Sobreposição de tela detectada"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Para alterar a configuração dessa permissão, você deve primeiro desativar a sobreposição de tela em \"Config.\" &gt; \"Apps\""</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir configurações"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"As ações de instalar/desinstalar não são compatíveis com o Android Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Escolha o que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; terá permissão de acessar"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"O app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; foi atualizado. Escolha o que esse app terá permissão de acessar."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancelar"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continuar"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Novas permissões"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Permissões atuais"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Promovendo app…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Desconhecido"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Para sua segurança, seu tablet não tem permissão para instalar apps desconhecidos dessa fonte."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Para sua segurança, sua TV não tem permissão para instalar apps desconhecidos dessa fonte."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Para sua segurança, seu smartphone não tem permissão para instalar apps desconhecidos dessa fonte."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Seu smartphone e seus dados pessoais estão mais vulneráveis a ataques de apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer dano causado ao seu smartphone ou pela perda de dados que possa resultar do uso desse app."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Seu tablet e seus dados pessoais estão mais vulneráveis a ataques de apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer dano causado ao seu tablet ou pela perda de dados que possa resultar do uso desse app."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Sua TV e seus dados pessoais estão mais vulneráveis a ataques por apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer dano à sua TV ou pela perda de dados que possa resultar do uso dese app."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continuar"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Configurações"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instalando/desinstalando apps do Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pt-rPT-television/strings.xml b/packages/PackageInstaller/res/values-pt-rPT-television/strings.xml
new file mode 100644
index 0000000..206676b
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pt-rPT-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Recusar e não perguntar novamente"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Pode alterar esta definição mais tarde em Definições &gt; Aplicações"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Mostrar aplicações do sistema"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Autorizações da aplicação"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Autorizações da aplicação"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Autorizações de <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Autorizações adicionais"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Autorizações de <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pt-rPT-watch/strings.xml b/packages/PackageInstaller/res/values-pt-rPT-watch/strings.xml
new file mode 100644
index 0000000..e3c9e9f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pt-rPT-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Recusar e não perguntar nov."</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar aplicações do sistema"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Não pode ser alterado"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Sim"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancelar"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pt-rPT/strings.xml b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..c380839
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Programa de instalação do pacote"</string>
+    <string name="next" msgid="3057143178373252333">"Seguinte"</string>
+    <string name="install" msgid="5896438203900042068">"Instalar"</string>
+    <string name="done" msgid="3889387558374211719">"Concluído"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancelar"</string>
+    <string name="installing" msgid="8613631001631998372">"A instalar..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"A instalar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplicação instalada."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Pretende instalar esta aplicação? Terá acesso a:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Pretende instalar esta aplicação? Não requer qualquer acesso especial."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Pretende instalar uma atualização para a aplicação existente? Os dados existentes não serão perdidos. A aplicação atualizada terá acesso a:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Pretende instalar uma atualização para a aplicação existente? Os dados existentes não serão perdidos. A aplicação atualizada terá acesso a:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Pretende instalar uma atualização para a aplicação existente? Os dados existentes não serão perdidos. Não é necessário um acesso específico."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Pretende instalar uma atualização para a aplicação integrada? Os dados existentes não serão perdidos. Não é necessário um acesso específico."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplicação não instalada."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Foi bloqueada a instalação do pacote."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"A aplicação não foi instalada porque o pacote entra em conflito com um pacote existente."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"A aplicação não foi instalada porque não é compatível com o seu tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Esta aplicação não é compatível com a sua TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"A aplicação não foi instalada porque não é compatível com o seu telemóvel."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"A aplicação não foi instalada porque o pacote parece ser inválido."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g> no tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Não foi possível instalar o <xliff:g id="APP_NAME">%1$s</xliff:g> na sua TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g> no telemóvel."</string>
+    <string name="launch" msgid="4826921505917605463">"Abrir"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"O gestor não permite a instalação de aplicações obtidas de fontes desconhecidas"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Este utilizador não pode instalar aplicações desconhecidas"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Este utilizador não tem permissão para instalar aplicações"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Gerir aplicações"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Sem espaço"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g>. Liberte algum espaço e tente novamente."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplicação não encontrada"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"A aplicação não foi encontrada na lista de aplicações instaladas."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Não autorizado"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"O utilizador atual não tem autorização para efetuar esta desinstalação."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Erro"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Não foi possível desinstalar a aplicação."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Desinstalar a aplicação"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Desinstalar atualização"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> faz parte da seguinte aplicação:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Pretende desinstalar esta aplicação?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Pretende desinstalar esta aplicação para "<b>"todos"</b>" os utilizadores? A aplicação e os respetivos dados serão removidos de "<b>"todos"</b>" os utilizadores do dispositivo."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Pretende desinstalar esta aplicação para o utilizador <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Pretende substituir esta aplicação pela versão de fábrica? Todos os dados são removidos."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Pretende substituir esta aplicação pela versão de fábrica? Todos os dados são removidos. Esta ação afeta todos os utilizadores deste dispositivo, incluindo os que têm perfis de trabalho."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Desinstalações em execução"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Desinstalações com falha"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"A desinstalar..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"A desinstalar a aplicação <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Desinstalação concluída."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"A aplicação <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> foi desinstalada"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Desinstalação sem êxito."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Falha ao desinstalar a aplicação <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Não é possível desinstalar a aplicação de administração de dispositivos ativa"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Não é possível desinstalar a aplicação de administração de dispositivos ativa para <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Esta aplicação é necessária para alguns utilizadores ou perfis e foi desinstalada para outros"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"O perfil necessita desta aplicação e não é possível desinstalá-la."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Esta aplic. é exigida pelo gestor do disp. e não pode ser desinstalada."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Gerir aplicações de administração de dispositivos"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Gerir utilizadores"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Não foi possível desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Ocorreu um problema ao analisar o pacote."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Novas"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Todas"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacidade"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Acesso ao Dispositivo"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Esta atualização não requer novas permissões."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Recusar"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Mais informações"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Recusar mesmo assim"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Pretende permitir à(ao) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Pretende permitir que a aplicação &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g> sempre?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Apenas ao utilizar a aplicação"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Sempre"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Recusar e não perguntar novamente"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> desativadas"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"todas desativadas"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"nenhuma desativada"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Permitir"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplicações"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Permissões da aplicação"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Não perguntar novamente"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Sem autorizações"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Autorizações adicionais"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Abrir informações da aplicação"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other">Mais <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Mais <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Esta aplicação foi concebida para uma versão mais antiga do Android. Negar autorização pode fazer com que deixe de funcionar como pretendido."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"executar uma ação desconhecida"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> de <xliff:g id="COUNT_1">%2$d</xliff:g> aplicações autorizadas"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Mostrar sistema"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ocultar sistema"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Sem aplicações"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Definições de localização"</string>
+    <string name="location_warning" msgid="8778701356292735971">"O <xliff:g id="APP_NAME">%1$s</xliff:g> é um fornecedor de serviços de localização para este dispositivo. É possível modificar o acesso à localização a partir das definições de localização."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Se negar esta autorização, as funcionalidades básicas do seu dispositivo podem deixar de funcionar corretamente."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Imposta pela política"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Acesso em segundo plano desativado pela política"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Acesso em segundo plano ativado pela política"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Acesso em primeiro plano ativado pela política"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlado pelo administrador"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Sempre"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Apenas ao utilizar a aplicação"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nunca"</string>
+    <string name="loading" msgid="7811651799620593731">"A carregar…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Todas as autorizações"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Outras capacidades de aplicações"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Pedido de autorização"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Sobreposição de ecrã detetada"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Para alterar esta definição de autorização, primeiro tem de desativar a sobreposição do ecrã em Definições &gt; Aplicações"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir definições"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"As ações de instalar/desinstalar não são compatíveis com o Android Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Escolher a que conteúdos permite que o &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"O &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; foi atualizado. Escolha a que conteúdos permite que esta aplicação aceda."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancelar"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continuar"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Novas autorizações"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Autorizações atuais"</string>
+    <string name="message_staging" msgid="6151794817691100003">"A preparar a aplicação…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Desconhecido"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Para sua segurança, o tablet não está autorizado a instalar aplicações desconhecidas a partir desta fonte."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Para sua segurança, a TV não está autorizada a instalar aplicações desconhecidas a partir desta fonte."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Para sua segurança, o telemóvel não está autorizado a instalar aplicações desconhecidas a partir desta fonte."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"O seu telemóvel e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta aplicação, concorda que é responsável por quaisquer danos causados ao telemóvel ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"O seu tablet e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta aplicação, concorda que é responsável por quaisquer danos causados ao tablet ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"A sua TV e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta aplicação, concorda que é responsável por quaisquer danos causados à TV ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continuar"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Definições"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instalar/desinstalar aplicações Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pt-television/strings.xml b/packages/PackageInstaller/res/values-pt-television/strings.xml
new file mode 100644
index 0000000..ba6e68f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pt-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Negar e não perguntar novamente"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"É possível alterar isso mais tarde em \"Config.\" &gt; \"Apps\""</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Mostrar apps do sistema"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Permissões do app"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Permissões do app"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Permissões para <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Outras permissões"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Permissões para <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pt-watch/strings.xml b/packages/PackageInstaller/res/values-pt-watch/strings.xml
new file mode 100644
index 0000000..8742c2d
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pt-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Negar e não perguntar de novo"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Mostrar apps do sistema"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Impossível alterar"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Sim"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Cancelar"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-pt/strings.xml b/packages/PackageInstaller/res/values-pt/strings.xml
new file mode 100644
index 0000000..feb2337
--- /dev/null
+++ b/packages/PackageInstaller/res/values-pt/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Instalador do pacote"</string>
+    <string name="next" msgid="3057143178373252333">"Próximo"</string>
+    <string name="install" msgid="5896438203900042068">"Instalar"</string>
+    <string name="done" msgid="3889387558374211719">"Concluído"</string>
+    <string name="cancel" msgid="8360346460165114585">"Cancelar"</string>
+    <string name="installing" msgid="8613631001631998372">"Instalando..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Instalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"App instalado."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Quer instalar este app? Ele terá acesso a:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Quer instalar este app? Não requer acesso especial."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Quer instalar uma atualização para este app? Os dados existentes não serão perdidos. O app atualizado terá acesso a:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Quer instalar uma atualização para este app integrado? Os dados existentes não serão perdidos. O app atualizado terá acesso a:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Quer instalar uma atualização para este app existente? Seus dados existentes não serão perdidos. A atualização não requer qualquer acesso especial."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Quer instalar uma atualização para este app integrado? Seus dados existentes não serão perdidos. A atualização não requer qualquer acesso especial."</string>
+    <string name="install_failed" msgid="6579998651498970899">"O app não foi instalado."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"A instalação do pacote foi bloqueada."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Como o pacote tem um conflito com um pacote já existente, o app não foi instalado."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Como o app não é compatível com seu tablet, ele não foi instalado."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Este app não é compatível com sua TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Como o app não é compatível com seu smartphone, ele não foi instalado."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Como o pacote parece ser inválido, o app não foi instalado."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g> em seu tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g> na sua TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g> em seu telefone."</string>
+    <string name="launch" msgid="4826921505917605463">"Abrir"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Seu administrador não permite a instalação de apps transferidos por download de fontes desconhecidas"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Apps desconhecidos não podem ser instalados por este usuário"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Este usuário não tem permissão para instalar apps"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Gerenciar apps"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Sem espaço"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Não foi possível instalar <xliff:g id="APP_NAME">%1$s</xliff:g>. Libere um pouco de espaço e tente novamente."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"App não encontrado"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"O app não foi encontrado na lista de apps instalados."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Não permitido"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"O usuário atual não tem permissão para executar essa desinstalação."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Erro"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Não foi possível desinstalar o app."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Desinstalar app"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Desinstalar atualização"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> é parte do seguinte app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Quer desinstalar este app?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Quer desinstalar este app para "<b>"todos"</b>" os usuários? O app e seus dados serão removidos para "<b>"todos"</b>" os usuários do dispositivo."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Quer desinstalar este app para o usuário <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Substituir este app pela versão de fábrica? Todos os dados serão removidos."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Substituir este app pela versão de fábrica? Todos os dados serão removidos. Isso afeta todos os usuários deste dispositivo, incluindo aqueles com perfis de trabalho."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Executando desinstalações"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Falha nas desinstalações"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Desinstalando..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Desinstalação concluída."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstalado"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Desinstalação malsucedida."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Falha na desinstalação de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Não é possível desinstalar o app para administrador ativo do dispositivo"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Não é possível desinstalar o app para administrador ativo do dispositivo de <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"O app é necessário para alguns usuários ou perfis e foi desinstalado para outros"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Este app é necessário para seu perfil e não pode ser desinstalado."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"O app é exigido pelo administrador do dispositivo e não pode ser desinstalado."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Gerenciar apps do administrador do dispositivo"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Gerenciar usuários"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Não foi possível desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Ocorreu um problema ao analisar o pacote."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Novas"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Todas"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacidade"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Acesso ao dispositivo"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Esta atualização não requer novas permissões."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Negar"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Mais informações"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Negar mesmo assim"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Sempre permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Apenas ao usar o app"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Sempre"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Negar e não perguntar novamente"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> desativada(s)"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"todas desativadas"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"nenhuma desativada"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Permitir"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Apps"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Permissões do app"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Não perguntar novamente"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Sem permissões"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Outras permissões"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Abrir informações do app"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one">Mais <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Mais <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Este app foi projetado para uma versão anterior do Android. Negar a permissão pode fazer com que ele deixe de funcionar conforme esperado."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"executar uma ação desconhecida"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> de <xliff:g id="COUNT_1">%2$d</xliff:g> apps permitidos"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Mostrar sistema"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ocultar sistema"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nenhum app"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Configurações de localização"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> é um provedor de serviços de localização para este dispositivo. O acesso local pode ser modificado nas configurações de localização."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Se você negar essa permissão, recursos básicos do seu dispositivo poderão não funcionar mais como deveriam."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Aplicável por política"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Acesso em segundo plano desativado pela política"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Acesso em segundo plano ativado pela política"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Acesso em primeiro plano ativado pela política"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlada pelo administrador"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Sempre"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Apenas ao usar o app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nunca"</string>
+    <string name="loading" msgid="7811651799620593731">"Carregando…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Todas as permissões"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Outros recursos do app"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Solicitação de permissão"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Sobreposição de tela detectada"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Para alterar a configuração dessa permissão, você deve primeiro desativar a sobreposição de tela em \"Config.\" &gt; \"Apps\""</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Abrir configurações"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"As ações de instalar/desinstalar não são compatíveis com o Android Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Escolha o que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; terá permissão de acessar"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"O app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; foi atualizado. Escolha o que esse app terá permissão de acessar."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Cancelar"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continuar"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Novas permissões"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Permissões atuais"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Promovendo app…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Desconhecido"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Para sua segurança, seu tablet não tem permissão para instalar apps desconhecidos dessa fonte."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Para sua segurança, sua TV não tem permissão para instalar apps desconhecidos dessa fonte."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Para sua segurança, seu smartphone não tem permissão para instalar apps desconhecidos dessa fonte."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Seu smartphone e seus dados pessoais estão mais vulneráveis a ataques de apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer dano causado ao seu smartphone ou pela perda de dados que possa resultar do uso desse app."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Seu tablet e seus dados pessoais estão mais vulneráveis a ataques de apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer dano causado ao seu tablet ou pela perda de dados que possa resultar do uso desse app."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Sua TV e seus dados pessoais estão mais vulneráveis a ataques por apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer dano à sua TV ou pela perda de dados que possa resultar do uso dese app."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continuar"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Configurações"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instalando/desinstalando apps do Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ro-television/strings.xml b/packages/PackageInstaller/res/values-ro-television/strings.xml
new file mode 100644
index 0000000..4f8992f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ro-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Respingeți și nu se mai întreabă"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Puteți modifica permisiunile ulterior din Setări &gt; Aplicații"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Afișează aplicațiile de sistem"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Permisiuni aplicații"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Permisiuni aplicații"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Permisiuni pentru <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Permisiuni suplimentare"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Permisiuni pentru <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ro-watch/strings.xml b/packages/PackageInstaller/res/values-ro-watch/strings.xml
new file mode 100644
index 0000000..ea699f3
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ro-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Respingeți; nu se mai întreabă"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Afișează aplicațiile de sistem"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nu se poate modifica"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Da"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Anulați"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ro/strings.xml b/packages/PackageInstaller/res/values-ro/strings.xml
new file mode 100644
index 0000000..3b13dab3
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ro/strings.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Program de instalare a pachetelor"</string>
+    <string name="next" msgid="3057143178373252333">"Înainte"</string>
+    <string name="install" msgid="5896438203900042068">"Instalați"</string>
+    <string name="done" msgid="3889387558374211719">"Terminat"</string>
+    <string name="cancel" msgid="8360346460165114585">"Anulați"</string>
+    <string name="installing" msgid="8613631001631998372">"În curs de instalare..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Se instalează <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplicație instalată."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Doriți să instalați această aplicație? Aceasta va avea acces la:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Doriți să instalați această aplicație? Aplicația nu solicită un acces special."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Doriți să instalați o actualizare pentru această aplicație existentă? Datele existente nu vor fi pierdute. Aplicația actualizată va avea acces la:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Doriți să instalați o actualizare pentru această aplicație încorporată? Datele existente nu vor fi pierdute. Aplicația actualizată va avea acces la:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Doriți să instalați o actualizare pentru această aplicație existentă? Datele existente nu vor fi pierdute. Actualizarea nu are nevoie de acces special."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Doriți să instalați o actualizare pentru această aplicație încorporată? Datele existente nu vor fi pierdute. Actualizarea nu are nevoie de acces special."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplicația nu este instalată."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Instalarea pachetului a fost blocată."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplicația nu a fost instalată deoarece pachetul intră în conflict cu un pachet existent."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplicația nu a fost instalată deoarece nu este compatibilă cu tableta dvs."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Această aplicație nu este compatibilă cu televizorul dvs."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplicația nu a fost instalată deoarece nu este compatibilă cu telefonul dvs."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplicația nu a fost instalată deoarece se pare că pachetul este nevalid."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu a putut fi instalată pe tableta dvs."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Aplicația <xliff:g id="APP_NAME">%1$s</xliff:g> nu a putut fi instalată pe televizor."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu a putut fi instalată pe telefonul dvs."</string>
+    <string name="launch" msgid="4826921505917605463">"Deschideți"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Administratorul nu permite instalarea aplicațiilor obținute din surse necunoscute"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Aplicațiile necunoscute nu pot fi instalate de acest utilizator"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Acest utilizator nu are permisiunea să instaleze aplicații"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Gestionați aplicații"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Spațiu de stocare insuficient"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu a putut fi instalată. Eliberați spațiu și încercați din nou."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplicația nu a fost găsită"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplicația nu a fost găsită în lista de aplicații instalate."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Nu are permisiune"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Utilizatorul actual nu are permisiune pentru a face această dezinstalare."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Eroare"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Aplicația nu a putut fi dezinstalată."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Dezinstalați aplicația"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Dezinstalați actualizarea"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">" <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> face parte din următoarea aplicație:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Doriți să dezinstalați această aplicație?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Doriți să dezinstalați această aplicație pentru "<b>"toți"</b>" utilizatorii? Aplicația și datele acesteia vor fi eliminate de la "<b>"toți"</b>" utilizatorii de pe acest dispozitiv."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Dezinstalați această aplicație pentru utilizatorul <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Înlocuiți această aplicație cu versiunea din fabrică? Toate datele vor fi eliminate."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Înlocuiți această aplicație cu versiunea din fabrică? Toate datele vor fi eliminate. Această acțiune va afecta toți utilizatorii dispozitivului, inclusiv pe cei cu profiluri de serviciu."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Dezinstalări în curs"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Dezinstalări nereușite"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"În curs de dezinstalare..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Se dezinstalează <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Dezinstalare finalizată."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a fost dezinstalat"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Dezinstalare nefinalizată."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nu a putut fi dezinstalată."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Nu se poate dezinstala aplicația activă de administrare a dispozitivului"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Nu se poate dezinstala aplicația activă de administrare a dispozitivului pentru <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Aplicația este necesară unor utilizatori sau profiluri și a fost dezinstalată pentru alții"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Aplicația este necesară pentru profilul dvs. și nu poate fi dezinstalată."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Aplicație necesară administratorului dispozitivului. Nu poate fi dezinstalată."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Gestionați aplicațiile de administrare dispozitiv"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Gestionați utilizatorii"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu a putut fi dezinstalată."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"A apărut o problemă la analizarea pachetului."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Noi"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Toate"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Confidențialitate"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Acces la dispozitiv"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Această actualizare nu necesită permisiuni noi."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Refuzați"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Mai multe informații"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Nu permiteți oricum"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> din <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Permiteți întotdeauna &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Doar în timp ce folosiți aplicația"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Întotdeauna"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Respingeți și nu se mai întreabă"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> dezactivate"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"toate dezactivate"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"niciuna dezactivată"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Permiteți"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplicații"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Permisiuni pentru aplicație"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Nu mai întreba"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Fără permisiuni"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Permisiuni suplimentare"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Deschideți informațiile despre aplicații"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="few">Încă <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Încă <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Încă <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Această aplicație a fost creată pentru o versiune Android mai veche. Dacă nu acordați permisiunea, este posibil ca aceasta să nu mai funcționeze corespunzător."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"efectuează o acțiune necunoscută"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> din <xliff:g id="COUNT_1">%2$d</xliff:g> aplicații au această permisiune"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Afișați aplicațiile de sistem"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ascundeți aplicațiile de sistem"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Nicio aplicație"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Setări privind locația"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> este un furnizor de servicii de localizare pentru acest dispozitiv. Accesul la locație poate fi modificat din setările privind locația."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Dacă refuzați această permisiune, este posibil ca funcțiile de bază ale dispozitivului să nu mai funcționeze corespunzător."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Aplicată conform politicii"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Acces la fundal dezactivat de politică"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Acces la fundal activat de politică"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Acces la prim-plan activat de politică"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Controlat de administrator"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Întotdeauna"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Doar în timp ce folosiți aplicația"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Niciodată"</string>
+    <string name="loading" msgid="7811651799620593731">"Se încarcă..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Toate permisiunile"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Alte funcții ale aplicației"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Solicitare de permisiune"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"S-a detectat suprapunerea pe ecran"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Ca să schimbați această setare pentru permisiuni, mai întâi trebuie să dezactivați suprapunerea pe ecran din Setări &gt; Aplicații"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Deschideți setările"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Acțiunile Instalați/Dezinstalați nu sunt acceptate pe Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Alegeți ce va putea accesa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Aplicația &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a fost actualizată. Alegeți ce va putea accesa această aplicație."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Anulați"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Continuați"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Permisiuni noi"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Permisiuni actuale"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Se pregătește aplicația…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Necunoscut"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Din motive de securitate, tableta dvs. nu are permisiunea să instaleze aplicații necunoscute din această sursă."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Din motive de securitate, televizorul dvs. nu are permisiunea să instaleze aplicații necunoscute din această sursă."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Din motive de securitate, telefonul dvs. nu are permisiunea să instaleze aplicații necunoscute din această sursă."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefonul și datele dvs. personale sunt mai vulnerabile la un atac din partea aplicațiilor necunoscute. Dacă instalați aplicația, acceptați că sunteți singura persoană responsabilă pentru deteriorarea telefonului sau pentru pierderea datelor, care pot avea loc în urma utilizării acesteia."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tableta și datele dvs. personale sunt mai vulnerabile la un atac din partea aplicațiilor necunoscute. Dacă instalați aplicația, acceptați că sunteți singura persoană responsabilă pentru deteriorarea tabletei sau pentru pierderea datelor, care pot avea loc în urma utilizării acesteia."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Televizorul și datele dvs. personale sunt mai vulnerabile la un atac din partea aplicațiilor necunoscute. Dacă instalați această aplicație, acceptați că sunteți singura persoană responsabilă pentru deteriorarea televizorului sau pentru pierderea datelor, care pot avea loc în urma utilizării acesteia."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Continuați"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Setări"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Se (dez)instalează aplicațiile Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-round-watch/dimens.xml b/packages/PackageInstaller/res/values-round-watch/dimens.xml
new file mode 100644
index 0000000..fa36464
--- /dev/null
+++ b/packages/PackageInstaller/res/values-round-watch/dimens.xml
@@ -0,0 +1,23 @@
+<?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>
+    <!-- Dimens for dialog layouts -->
+    <dimen name="diag_button_size">48dp</dimen>
+    <dimen name="diag_preferred_padding">@dimen/screen_percentage_15</dimen>
+    <dimen name="diag_button_padding_horizontal">@dimen/screen_percentage_15</dimen>
+    <dimen name="diag_button_padding_bottom">@dimen/screen_percentage_12</dimen>
+    <dimen name="diag_icon_margin_top">@dimen/screen_percentage_10</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ru-television/strings.xml b/packages/PackageInstaller/res/values-ru-television/strings.xml
new file mode 100644
index 0000000..e105f92
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ru-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Запретить и больше не спрашивать"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Чтобы изменить разрешения, откройте \"Настройки\" и выберите \"Приложения\"."</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Показать системные приложения"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Разрешения приложений"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Разрешения приложений"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Разрешения (<xliff:g id="PERMISSION">%1$s</xliff:g>)"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Ещё разрешения"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Разрешения (<xliff:g id="PERMISSION">%1$s</xliff:g>)"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ru-watch/strings.xml b/packages/PackageInstaller/res/values-ru-watch/strings.xml
new file mode 100644
index 0000000..f58db32
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ru-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Запретить и не спрашивать"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Показать системные приложения"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Нельзя изменить"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Да"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Отмена"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ru/strings.xml b/packages/PackageInstaller/res/values-ru/strings.xml
new file mode 100644
index 0000000..9ffdf4a
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ru/strings.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Установщик пакетов"</string>
+    <string name="next" msgid="3057143178373252333">"Далее"</string>
+    <string name="install" msgid="5896438203900042068">"Установить"</string>
+    <string name="done" msgid="3889387558374211719">"Готово"</string>
+    <string name="cancel" msgid="8360346460165114585">"Отмена"</string>
+    <string name="installing" msgid="8613631001631998372">"Установка..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Устанавливаем <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Приложение установлено."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Хотите ли вы установить это приложение? Оно получит следующие разрешения:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Это приложение не требует специальных разрешений. Установить его?"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Хотите установить обновление для этого приложения? После обновления оно сможет выполнять следующие действия:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Хотите установить обновление для этого приложения? После обновления оно сможет выполнять следующие действия:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Установить обновление этого приложения? На текущих данных это никак не отразится. Специальных прав доступа не требуется."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Установить обновление этого встроенного приложения? На текущих данных это никак не отразится. Специальных прав доступа не требуется."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Приложение не установлено."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Установка пакета заблокирована."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Приложение не установлено, так как оно конфликтует с другим пакетом."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Приложение не установлено, так как оно несовместимо с вашим планшетом."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Приложение несовместимо с вашим телевизором."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Приложение не установлено, так как оно несовместимо с вашим телефоном."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Приложение не установлено, так как его пакет недействителен (например, поврежден)."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Не удалось установить приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" нельзя установить на ваш телевизор."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Не удалось установить приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
+    <string name="launch" msgid="4826921505917605463">"Открыть"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Ваш администратор запретил устанавливать приложения из неизвестных источников"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Этот пользователь не может устанавливать неизвестные приложения"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Этому пользователю не разрешено устанавливать приложения"</string>
+    <string name="ok" msgid="3468756155452870475">"ОК"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Управление приложениями"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Недостаточно места"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Не удалось установить приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\". Освободите место и повторите попытку."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Приложение не найдено"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Приложения нет в списке установленных."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Действие запрещено"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Этот пользователь не может удалить приложение."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Ошибка"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Не удалось удалить приложение."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Удаление приложения"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Удаление обновления"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> – часть следующего приложения:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Удалить приложение?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Удалить это приложение для "<b>"всех"</b>" пользователей? После этого "<b>"ни один"</b>" пользователь устройства не будет иметь доступа к приложению и связанным с ним данным."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Удалить это приложение из профиля <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Установить исходную версию приложения? Все его данные будут удалены."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Установить исходную версию приложения? Его данные будут удалены из всех профилей устройства, в том числе рабочих."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Активные процессы удаления"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Ошибки удаления"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Удаление..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Удаление приложения \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Удаление завершено."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Приложение \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\" удалено"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Ошибка при удалении."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Не удалось удалить приложение \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Невозможно удалить активное приложение для администрирования устройства"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Невозможно удалить активное приложение для администрирования устройства в профиле <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Это приложение обязательно для некоторых пользователей или профилей."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Это приложение обязательно для вашего профиля. Его нельзя удалить."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Это приложение указано администратором как обязательное. Его нельзя удалить."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Настроить приложения для администрир. устройства"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Управление пользователями"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Не удалось удалить приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Ошибка при синтаксическом анализе пакета."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Новые"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Все"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Личные данные"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Доступ к устройству"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Установка этого обновления не требует новых разрешений."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Отклонить"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Подробнее"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Все равно запретить"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> из <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Всегда разрешать приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Когда открыто приложение"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Всегда"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Запретить и больше не спрашивать"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"отключено: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"все отключены"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"все включены"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Разрешить"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Приложения"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Разрешения приложений"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Больше не спрашивать"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Нет разрешений"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Ещё разрешения"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"О приложении"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+      <item quantity="many">Ещё <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Ещё <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Это приложение было разработано для более ранней версии Android. Отзыв разрешения может вызвать неполадки в работе."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"выполняет неизвестные действия"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Приложений с разрешением: <xliff:g id="COUNT_0">%1$d</xliff:g> из <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Показать системные процессы"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Скрыть системные процессы"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Нет приложений"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Настройки геоданных"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> является поставщиком услуг геолокации для этого устройства. Вы можете изменить параметры доступа в настройках геоданных."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Если вы отключите это разрешение, основные функции устройства могут работать неправильно."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"В соответствии с политикой"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Доступ в фоновом режиме отключен в соответствии с правилами."</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Доступ в фоновом режиме включен в соответствии с правилами."</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Активный режим включен в соответствии с правилами."</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Контролируется администратором"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Всегда"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Когда открыто приложение"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Никогда"</string>
+    <string name="loading" msgid="7811651799620593731">"Загрузка…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Все разрешения"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Что ещё может приложение"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Запрос разрешений"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Показ поверх других окон"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Чтобы предоставить или отменить разрешение, сначала отключите показ поверх других окон. Для этого нажмите \"Настройки &gt; Приложения\"."</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Открыть настройки"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Установка и удаление не поддерживаются на Android Wear"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Выберите разрешения для приложения &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Приложение &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; обновлено. Выберите разрешения для него."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Отмена"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Далее"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Новые разрешения"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Имеющиеся разрешения"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Подождите…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Неизвестное приложение"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"В целях безопасности ваш планшет блокирует установку приложений из неизвестных источников."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"В целях безопасности ваш телевизор блокирует установку приложений из неизвестных источников."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"В целях безопасности ваш телефон блокирует установку приложений из неизвестных источников."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Ваши личные данные и данные телефона более уязвимы для атак приложений из неизвестных источников. Устанавливая это приложение, вы соглашаетесь с тем, что несете полную ответственность за любой ущерб, нанесенный телефону, и потерю данных, связанные с использованием этого приложения."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Ваши личные данные и данные планшета более уязвимы для атак приложений из неизвестных источников. Устанавливая это приложение, вы соглашаетесь с тем, что несете полную ответственность за любой ущерб, нанесенный планшету, и потерю данных, связанные с использованием этого приложения."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Ваши личные данные и данные телевизора более уязвимы для атак приложений из неизвестных источников. Устанавливая это приложение, вы соглашаетесь с тем, что несете полную ответственность за любой ущерб, нанесенный телевизору, и потерю данных, связанные с использованием этого приложения."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Продолжить"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Настройки"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Установка/удаление приложений для Android Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-si-television/strings.xml b/packages/PackageInstaller/res/values-si-television/strings.xml
new file mode 100644
index 0000000..2ac8d8b
--- /dev/null
+++ b/packages/PackageInstaller/res/values-si-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"ප්‍රතික්ෂේප කරන්න, නැවත අසන්න එපා"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"ඔබට මෙය පසුව සැකසීම් &gt; යෙදුම් තුළ වෙනස් කළ හැකිය"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"පද්ධති යෙදුම් පෙන්වන්න"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"යෙදුම් අවසර"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"යෙදුම් අවසර"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> අවසර"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"අතිරේක අවසර"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> අවසර"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-si-watch/strings.xml b/packages/PackageInstaller/res/values-si-watch/strings.xml
new file mode 100644
index 0000000..c5d9ae4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-si-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ප්‍රතික්ෂේප කරන්න, නැවත අසන්න එපා"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"පද්ධති යෙදුම් පෙන්වන්න"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"වෙනස් කළ නොහැකිය"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"ඔව්"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"අවලංගු කර."</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-si/strings.xml b/packages/PackageInstaller/res/values-si/strings.xml
new file mode 100644
index 0000000..18fc840
--- /dev/null
+++ b/packages/PackageInstaller/res/values-si/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"පැකේජ ස්ථාපනකරු"</string>
+    <string name="next" msgid="3057143178373252333">"මීලඟ"</string>
+    <string name="install" msgid="5896438203900042068">"ස්ථාපනය"</string>
+    <string name="done" msgid="3889387558374211719">"හරි"</string>
+    <string name="cancel" msgid="8360346460165114585">"අවලංගු කරන්න"</string>
+    <string name="installing" msgid="8613631001631998372">"ස්ථාපනය කරමින්…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ස්ථාපනය කරමින්…"</string>
+    <string name="install_done" msgid="3682715442154357097">"යෙදුම ස්ථාපනය කරන ලදි."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"ඔබට මෙම යෙදුම ස්ථාපනය කිරීමට අවශ්‍යද? පහත ඒවා වෙත එයට ප්‍රවේශය ලැබෙනු ඇත:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"මෙම යෙදුම ස්ථාපනය කිරීමට ඔබට අවශ්‍යද? වෙනත් විශේෂ ප්‍රවේශයක් එයට අවශ්‍ය නොවෙයි."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"දැනට පවතින මෙම යෙදුමට යාවත්කාලීනයක් ස්ථාපනය කිරීමට ඔබට අවශ්‍යද? ඔබගේ පවතින දත්ත නැති නොවේ. යාවත්කාලීන කළ යෙදුම පිවිසීම ලබා ගනී:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"ඔබට මෙම තිළැලි යෙදුමට යාවත්කාලීනය ස්ථාපනය කිරීමට අවශ්‍යද? ඔබගේ දැනට පවතින දත්ත නැති නොවේ. යාවත්කාලීන කරන ලද යෙදුම පහත සඳහා ප්‍රවේශය ලබාගනු ඇත:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"මෙම පවතින යෙදුමට යාවත්කාලීනයක් ස්ථාපනය කිරීමට ඔබට අවශ්‍යද? ඔබගේ පවතින දත්ත නැති නොවේ. එයට විශේෂ ප්‍රවේශයක් අවශ්‍ය නොවේ."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"පවතින මෙම යෙදුමට යාවත්කාලීනයක් ස්ථාපනය කිරීමට ඔබට අවශ්‍යද? ඔබගේ පවතින දත්ත නැති නොවේ. එයට විශේෂ ප්‍රවේශයක් අවශ්‍ය නොවේ."</string>
+    <string name="install_failed" msgid="6579998651498970899">"යෙදුම ස්ථාපනය කරේ නැත."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"මෙම පැකේජය ස්ථාපනය කිරීම අවහිර කරන ලදි."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"පැකේජය දැනට පවතින පැකේජයක් සමග ගැටෙන නිසා යෙදුම ස්ථාපනය නොකරන ලදී."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"යෙදුම ඔබේ ටැබ්ලට් පරිගණකය සමග නොගැළපෙන නිසා යෙදුම ස්ථාපනය නොකරන ලදී."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"මෙම යෙදුම ඔබගේ රූපවාහිනිය හා නොගැළපේ."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"යෙදුම ඔබේ දුරකථනය සමග නොගැළපෙන නිසා යෙදුම ස්ථාපනය නොකරන ලදී."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"පැකේජය වලංගු නොවන බවක් පෙනෙන නිසා යෙදුම ස්ථාපනය නොකරන ලදී."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"ඔබගේ ටැබ්ලටයේ <xliff:g id="APP_NAME">%1$s</xliff:g> ස්ථාපනය කළ නොහැක."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> මෙම රූපවාහිනියෙහි ස්ථාපනය කළ නොහැක."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> දුරකථනයට ස්ථාපිත කිරීමට නොහැකි විය."</string>
+    <string name="launch" msgid="4826921505917605463">"විවෘත කරන්න"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"නාඳුනන මූලයන් වෙතින් ලබාගත් යෙදුම් ස්ථාපනය කිරීමට ඔබගේ පරිපාලකයා ඉඩ නොදේ"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"මෙම පරිශීලකයා මඟින් නොදන්නා යෙදුම් ස්ථාපනය කළ නොහැක"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"මෙම පරිශීලකයාට යෙදුම් ස්ථාපනය කිරීමට අවසර නැත"</string>
+    <string name="ok" msgid="3468756155452870475">"හරි"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"යෙදුම් කළමනාකරණය කරන්න"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"ඉඩ නොමැත"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> ස්ථාපිත කිරීමට නොහැකි විය. ඉඩ පොඩ්ඩක් නිදහස් කොට නැවත උත්සාහ කරන්න."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"යෙදුම හමුවී නැත"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ස්ථාපිත යෙදුම් ලැයිස්තුවේ යෙදුම සොයා ගත නොහැකි විය."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"ඉඩ නොදෙයි"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"වත්මන් පරිශීලකයාට මෙම අස්ථාපනය සිදු කිරීමට ඉඩ නොදේ."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"දෝෂය"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"යෙදුම අස්ථාපනය කළ නොහැකි විය."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"යෙදුම අස්ථාපනය කරන්න"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"යාවත්කාලිනය අස්ථාපනය කරන්න"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> පහත යෙදුමේ කොටසකි:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"ඔබට මෙම යෙදුම අස්ථාපනය කිරීමට අවශ්‍යද?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222"><b>"සියලු"</b>" පරිශීලකයන්  සඳහා මෙම යෙදුම අස්ථාපනය කිරීමට ඔබට අවශ්‍යද? උපාංගයෙහි "<b>"සියලු"</b>" පරිශීලකයන් සඳහා යෙදුම සහ එහි දත්ත ඉවත්වනු ඇත."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"<xliff:g id="USERNAME">%1$s</xliff:g> පරිශීලකයා සඳහා මෙම යෙදුම අස්ථාපනය කිරීමට ඔබට අවශ්‍යයද?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"මෙම යෙදුම කර්මාන්ත ශාලා අනුවාදයක් සමගින් ප්‍රතිස්ථාපනය කරන්නද? සියලු දත්ත ඉවත් කරනු ඇත."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"මෙම යෙදුම කර්මාන්ත ශාලා අනුවාදයක් සමගින් ප්‍රතිස්ථාපනය කරන්නද? සියලු දත්ත ඉවත් කරනු ඇත. මෙය කාර්යාල පැතිකඩවල් සහිත අය ඇතුළුව, මෙම උපාංගයෙහි සියලු පරිශීලකයන් වෙත බලපානු ඇත."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"අස්ථාපන ධාවනය කරමින්"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"අසාර්ථක වූ අස්ථාපන"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"අස්ථාපනය කරමින්…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> අස්ථාපනය කරමින්…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"අස්ථාපනය අවසන්."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> අස්ථාපනය කරන ලදී"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"අස්ථාපිත විම අසාර්ථකයි."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> අස්ථාපනය කිරීම සාර්ථකයි."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"ක්‍රියාකාරී උපාංගය පරිපාලක යෙදුම අස්ථාපනය කිරීමට නොහැක"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> සඳහා ක්‍රියාකාරී උපාංගය පරිපාලක යෙදුම අස්ථාපනය කිරීමට නොහැක"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"මෙම යෙදුම සමහර පරිශීලකයන්ට සහ පැතිකඩවල්වලට අවශ්‍ය අතර අනෙක් අයට අස්ථාපනය කරන ලදී"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"ඔබේ කාර්ය පැතිකඩ සඳහා මෙම යෙදුම අවශ්‍ය වන අතර අස්ථාපනය කළ නොහැකිය."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"ඔබගේ උපාංගයේ පාලකයාට මෙම යෙදුම අවශ්‍ය වේ එම නිසා අස්ථාපනය කළ නොහැක."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"උපාංග පරිපාලක යෙදුම් කළමනාකරණය කිරීම"</string>
+    <string name="manage_users" msgid="3125018886835668847">"පරිශීලකයන් කළමනාකරණය කරන්න"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> අස්ථාපනය කල නොහැක."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"පැකේජය විග්‍රහ කිරීමේදී ගැටළුවක් ඇති විය."</string>
+    <string name="newPerms" msgid="6039428254474104210">"අලුත්"</string>
+    <string name="allPerms" msgid="1024385515840703981">"සියල්ල"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"පෞද්ගලිකත්වය"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"උපාංගය ප්‍රවේශය"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"මෙම යාවත්කාලිනයට අලුත් අවසරයන් අවශ්‍ය නොවේ."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"ප්‍රතික්ෂේප කරන්න"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"වැඩිදුර තොරතුරු"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"කෙසේ වෙතත් ප්‍රතික්ෂේප කරන්න"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> න් <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ට <xliff:g id="ACTION">%2$s</xliff:g> වෙත ඉඩ දෙන්නද?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"සැම විට &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; හට <xliff:g id="ACTION">%2$s</xliff:g> වෙත ඉඩ දෙන්නද?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"යෙදුම භාවිතා කරන විට පමණි"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"සැම විට"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"ප්‍රතික්ෂේප කරන්න, නැවත අසන්න එපා"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> අබලයි"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"සියල්ල අබලයි"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"කිසිවක් අබල නැත"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"ඉඩ දෙන්න"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"යෙදුම්"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"යෙදුම් අවසර"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"නැවත අසන්න එපා"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"අවසර නොමැත"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"අතිරේක අවසර"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"යෙදුම් තොරතුරු විවෘත කරන්න"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"මෙම යෙදුම නිර්මාණය කර ඇත්තේ Android වල පැරණි අනුවාදයකට වේ. අවසර නොදීම මඟින් එය බලාපොරොත්තු වන ආකාරයට වැඩ නොකිරීමට හැක."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"නොදන්නා ක්‍රියාවක් සිදු කරන්න"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"යෙදුම් <xliff:g id="COUNT_1">%2$d</xliff:g> න් <xliff:g id="COUNT_0">%1$d</xliff:g> කට ඉඩ දෙන ලදි"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"පද්ධතිය පෙන්වන්න"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"පද්ධතිය සඟවන්න"</string>
+    <string name="no_apps" msgid="1965493419005012569">"යෙදුම් නොමැත"</string>
+    <string name="location_settings" msgid="1774875730854491297">"ස්ථාන සැකසීම්"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> මෙම උපාංගය සඳහා ස්ථාන සේවාවන් සපයන්නෙකු වේ. ස්ථාන ප්‍රවේශය ස්ථාන සැකසීම් වෙතින් වෙනස් කළ හැක."</string>
+    <string name="system_warning" msgid="7103819124542305179">"ඔබ මෙම අවසරය ප්‍රතික්ෂේප කරන්නේ නම්, සමහර යෙදුම් බලාපොරොත්තු පරිදි ක්‍රියා නොකරනු ඇත."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"ප්‍රතිපත්තිය මඟින් බලාත්මක කරයි"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"පසුබිම් ප්‍රවේශය ප්‍රතිපත්තිය මගින් අබල කර ඇත"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"පසුබිම් ප්‍රවේශය ප්‍රතිපත්තිය මගින් සබල කර ඇත"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"පෙරබිම් ප්‍රවේශය ප්‍රතිපත්තිය මගින් සබල කර ඇත"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"පරිපාලක විසින් පාලනය කෙරේ"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"සැම විට"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"යෙදුම භාවිතා කරන විට පමණි"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"කිසි විටක නැත"</string>
+    <string name="loading" msgid="7811651799620593731">"පූරණය කරමින්…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"සියලු අවසර"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"වෙනත් යෙදුම් හැකියාවන්"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"අවසර ඉල්ලීම"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"තිර උඩැතිරියක් අනාවරණය කරන ලදි"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"මෙම අවසර සැකසීම වෙනස් කිරීම සඳහා, ඔබට මුලින්ම සැකසීම් &gt; යෙදුම් වෙතින් තිර උඩැතිරිය අක්‍රිය කර යුතුයි"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"සැකසීම් විවෘත කරන්න"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear මත ස්ථාපන/අස්ථාපනය ක්‍රියා සහාය දක්වන්නේ නැත."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; හට පිවිසීමට ඉඩ දෙන දේ තෝරන්න"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; යාවත්කාලීන කර ඇත. මෙම යෙදුමට පිවිසීමට ඉඩ දෙන දේ තෝරන්න."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"අවලංගු කරන්න"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"දිගටම කර ගෙන යන්න"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"නව අවසර"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"වත්මන් අවසර"</string>
+    <string name="message_staging" msgid="6151794817691100003">"යෙදුම වේදිකාගත කරමින්..."</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"නොදනී"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"ආරක්ෂාව සඳහා, ඔබගේ ටැබ්ලටය මෙම මුලාශ්‍රයෙන් ලබාගත් නොදන්නා යෙදුම් ස්ථාපනය කිරීමට අවසර නැත."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"ආරක්ෂාව සඳහා, ඔබගේ රූපවාහිනිය මෙම මුලාශ්‍රයෙන් ලබාගත් නොදන්නා යෙදුම් ස්ථාපනය කිරීමට අවසර නැත."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"ආරක්ෂාව සඳහා, ඔබගේ දුරකථනය මෙම මුලාශ්‍රයෙන් ලබාගත් නොදන්නා යෙදුම් ස්ථාපනය කිරීමට අවසර නැත."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"ඔබගේ දුරකථනය සහ පුද්ගලික දත්තවලට නොදන්නා යෙදුම් මඟින් තර්ජන එල්ල කිරීමේ හැකියාව වැඩිය. මෙම යෙදුම් ස්ථාපනය කිරීමෙන් සහ භාවිත කිරීමෙන් ඔබ ඔබේ දුරකථනය සඳහා සිදු වන යම් හානි හෝ එය භාවිත කිරීමේ ප්‍රතිඵලයක් ලෙස සිදු වන දත්ත හානි සඳහා ඔබ වගකිව යුතු බවට එකඟ වේ."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"ඔබගේ ටැබ්ලට් පරිගණකය සහ පුද්ගලික දත්තවලට නොදන්නා යෙදුම් මඟින් තර්ජන එල්ල කිරීමේ හැකියාව වැඩිය. මෙම යෙදුම් ස්ථාපනය කිරීමෙන් සහ භාවිත කිරීමෙන් ඔබ ඔබේ ටැබ්ලට් පරිගණකය සඳහා සිදු වන යම් හානි හෝ එය භාවිත කිරීමේ ප්‍රතිඵලයක් ලෙස සිදු වන දත්ත හානි සඳහා ඔබ වගකිව යුතු බවට එකඟ වේ."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"ඔබගේ TV සහ පුද්ගලික දත්තවලට නොදන්නා යෙදුම් මඟින් තර්ජන එල්ල කිරීමේ හැකියාව වැඩිය. මෙම යෙදුම් ස්ථාපනය කිරීමෙන් සහ භාවිත කිරීමෙන් ඔබ ඔබේ TV සඳහා සිදු වන යම් හානි හෝ එය භාවිත කිරීමේ ප්‍රතිඵලයක් ලෙස සිදු වන දත්ත හානි සඳහා ඔබ වගකිව යුතු බවට එකඟ වේ."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"දිගටම කරගෙන යන්න"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"සැකසීම්"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear යෙදුම් ස්ථාපනය/අස්ථාපනය කරමින්"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sk-television/strings.xml b/packages/PackageInstaller/res/values-sk-television/strings.xml
new file mode 100644
index 0000000..15ecdb8
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sk-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Zamietnuť a nabudúce sa nepýtať"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Neskôr to môžete zmeniť v časti Nastavenia &gt; Aplikácie"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Zobraziť systémové aplikácie"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Povolenia aplikácie"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Povolenia aplikácie"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Povolenia – <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Ďalšie povolenia"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Povolenia – <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sk-watch/strings.xml b/packages/PackageInstaller/res/values-sk-watch/strings.xml
new file mode 100644
index 0000000..dc3ce4f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sk-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Zamietnuť a už sa nepýtať"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Zobraziť systémové aplikácie"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nedá sa zmeniť"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Áno"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Zrušiť"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sk/strings.xml b/packages/PackageInstaller/res/values-sk/strings.xml
new file mode 100644
index 0000000..a27f650
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sk/strings.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Nástroj na inštaláciu balíčkov"</string>
+    <string name="next" msgid="3057143178373252333">"Ďalej"</string>
+    <string name="install" msgid="5896438203900042068">"Inštalovať"</string>
+    <string name="done" msgid="3889387558374211719">"Hotovo"</string>
+    <string name="cancel" msgid="8360346460165114585">"Zrušiť"</string>
+    <string name="installing" msgid="8613631001631998372">"Inštaluje sa..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Inštaluje sa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikácia bola nainštalovaná."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Chcete nainštalovať túto aplikáciu? Získa nasledujúce povolenia:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Chcete nainštalovať túto aplikáciu? Nevyžaduje žiadny zvláštny prístup."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Chcete nainštalovať aktualizáciu existujúcej aplikácie? Existujúce údaje sa nestratia. Aktualizovaná aplikácia získa nasledujúce povolenia:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Chcete nainštalovať aktualizáciu tejto integrovanej aplikácie? Existujúce údaje sa nestratia. Aktualizovaná aplikácia získa nasledujúce povolenia:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Chcete nainštalovať aktualizáciu tejto existujúcej aplikácie? Vaše údaje nebudú stratené. Táto akcia nevyžaduje žiadny zvláštny prístup."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Chcete nainštalovať aktualizáciu tejto vstavanej aplikácie? Vaše údaje sa nestratia. Táto akcia nevyžaduje žiadny zvláštny prístup."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplikácia nebola nainštalovaná."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Inštalácia balíka bola zablokovaná."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplikácia sa nenainštalovala, pretože balík koliduje s existujúcim balíkom."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplikácia sa nenainštalovala, pretože nie je kompatibilná s vaším tabletom."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Táto aplikácia nie je kompatibilná s vaším televízorom."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplikácia sa nenainštalovala, pretože nie je kompatibilná s vaším telefónom."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplikácia sa nenainštalovala, pretože je balík zrejme neplatný."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> sa do vášho tabletu nepodarilo nainštalovať."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> sa nepodarilo nainštalovať na vašom televízore."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> sa do vášho telefónu nepodarilo nainštalovať."</string>
+    <string name="launch" msgid="4826921505917605463">"Otvoriť"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Váš správca zakázal inštaláciu aplikácií z neznámych zdrojov"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Tento používateľ nemôže inštalovať neznáme aplikácie"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Tento používateľ nemá povolené inštalovať aplikácie"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Spravovať aplikácie"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nedostatok miesta"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> sa nepodarilo nainštalovať. Uvoľnite miesto v pamäti a skúste to znova."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplikácia sa nenašla"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplikáciu sa nepodarilo nájsť v zozname nainštalovaných aplikácií."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Nie je povolené"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Aktuálny používateľ nemá na odinštalovanie povolenie."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Chyba"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Aplikáciu nie je možné odinštalovať."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Odinštalovať aplikáciu"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Odinštalovať aktualizáciu"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"Aktivita <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je súčasťou nasledujúcej aplikácie:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Chcete túto aplikáciu odinštalovať?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Chcete odinštalovať túto aplikáciu pre "<b>"všetkých"</b>" používateľov? Aplikácia a jej údaje sa odstránia z tohto zariadenia pre "<b>"všetkých"</b>" používateľov."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Chcete túto aplikáciu odinštalovať pre používateľa <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Nahradiť túto aplikáciu továrenskou verziou? Všetky údaje sa odstránia."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Nahradiť túto aplikáciu továrenskou verziou? Všetky údaje sa odstránia. Ovplyvní to všetkých používateľov tohto zariadenia vrátane tých s pracovnými profilmi."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Prebiehajúce odinštalácie"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Neúspešné odinštalácie"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Prebieha odinštalovanie..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Prebieha odinštalovanie balíčka <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Odinštalovanie bolo dokončené."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Balíček <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> bol odinštalovaný"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Odinštalovanie bolo neúspešné."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Odinštalovanie balíčka <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sa nepodarilo."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Aktívna aplikácia na správu zariadenia sa nedá odinštalovať"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Aktívna aplikácia na správu zariadenia sa v prípade používateľa <xliff:g id="USERNAME">%1$s</xliff:g> nedá odinštalovať"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Táto aplikácia sa vyžaduje v prípade niektorých používateľov či profilov a v prípade iných zase bola odinštalovaná"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Táto aplikácia sa vyžaduje pre váš profil a nemôžete ju odinštalovať."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Túto aplikáciu vyžaduje správca vášho zariadenia a nie je ju možné odinštalovať."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Spravovať aplikácie na ovládanie zariadenia"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Spravovať používateľov"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> sa nepodarilo odinštalovať."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Pri analýze balíka sa vyskytol problém."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nové"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Všetko"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Ochrana súkromia"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Prístup k zariadeniu"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Táto aktualizácia nevyžaduje žiadne nové povolenia."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Odmietnuť"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Ďalšie informácie"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Zamietnuť"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> z <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Vždy povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Iba počas používania aplikácie"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Vždy"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Zamietnuť a nabudúce sa nepýtať"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"deaktivované (<xliff:g id="COUNT">%1$d</xliff:g>)"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"všetky sú zakázané"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"žiadne nie sú zakázané"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Povoliť"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikácie"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Povolenia aplikácií"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Nabudúce sa nepýtať"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Žiadne povolenia"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Ďalšie povolenia"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Otvoriť informácie o aplikácii"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> ďalšie</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> ďalšieho</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ďalších</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ďalšie</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Táto aplikácia bola navrhnutá pre staršiu verziu systému Android. Odmietnutie povolenia môže spôsobiť, že nebude optimálne fungovať."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"umožňuje vykonať neznámu akciu"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Povolené <xliff:g id="COUNT_0">%1$d</xliff:g> z <xliff:g id="COUNT_1">%2$d</xliff:g> aplikácií"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Zobraziť systémové aplikácie"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Skryť systémové aplikácie"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Žiadne aplikácie"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Nastavenia polohy"</string>
+    <string name="location_warning" msgid="8778701356292735971">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> je poskytovateľ služieb určovania polohy tohto zariadenia. Prístup k polohe môžete upraviť v nastaveniach polohy."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ak toto povolenie zamietnete, základné funkcie vášho zariadenia nemusia pracovať podľa očakávaní."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Vynútené pravidlom"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Prístup na pozadí je zakázaný pravidlom"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Prístup na pozadí je povolený pravidlom"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Prístup na popredí je povolený pravidlom"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Ovládané správcom"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Vždy"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Iba počas používania aplikácie"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nikdy"</string>
+    <string name="loading" msgid="7811651799620593731">"Načítava sa…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Všetky povolenia"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Ďalšie možnosti aplikácie"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Žiadosť o povolenie"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Bolo zistené prekrytie obrazovky"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Ak chcete zmeniť nastavenie tohto povolenia, musíte najprv v časti Nastavenia &gt; Aplikácie vypnúť prekrytie obrazovky"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Otvoriť nastavenia"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Systém Wear nepodporuje akciu inštalácie/odinštalovania."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Vyberte, k čomu môže pristupovať aplikácia &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Aplikácia &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; bola aktualizovaná. Vyberte, k čomu môže pristupovať."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Zrušiť"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Pokračovať"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nové povolenia"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Aktuálne povolenia"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Aplikácia je zavádzaná po etapách…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Neznáma"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Váš tablet nemôže z bezpečnostných dôvodov inštalovať neznáme aplikácie z tohto zdroja."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Váš televízor nemôže z bezpečnostných dôvodov inštalovať neznáme aplikácie z tohto zdroja."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Váš telefón nemôže z bezpečnostných dôvodov inštalovať neznáme aplikácie z tohto zdroja."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Váš telefón a osobné údaje sú náchylnejšie na útok z neznámych aplikácií. Inštalovaním tejto aplikácie súhlasíte, že zodpovedáte za akékoľvek poškodenie vášho telefónu či stratu údajov, ku ktorým môže dôjsť v dôsledku jej použitia."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Váš tablet a osobné údaje sú náchylnejšie na útok z neznámych aplikácií. Inštalovaním tejto aplikácie súhlasíte, že zodpovedáte za akékoľvek poškodenie vášho tabletu či stratu údajov, ku ktorým môže dôjsť v dôsledku jej použitia."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Váš televízor a osobné údaje sú náchylnejšie na útok z neznámych aplikácií. Inštalovaním tejto aplikácie súhlasíte, že zodpovedáte za akékoľvek poškodenie vášho televízora či stratu údajov, ku ktorým môže dôjsť v dôsledku jej použitia."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Pokračovať"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Nastavenia"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Inštalácia/odinštalácia aplikácií Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sl-television/strings.xml b/packages/PackageInstaller/res/values-sl-television/strings.xml
new file mode 100644
index 0000000..3e8e4ea
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sl-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Zavrni in ne sprašuj več"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"To lahko pozneje spremenite v »Nastavitve &gt; Aplikacije«"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Prikaz sistemskih aplikacij"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Dovoljenja za aplikacije"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Dovoljenja za aplikacije"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Dovoljenja za: <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Dodatna dovoljenja"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Dovoljenja za: <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sl-watch/strings.xml b/packages/PackageInstaller/res/values-sl-watch/strings.xml
new file mode 100644
index 0000000..906a551
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sl-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Zavrni, ne sprašuj več"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Prikaz sistemskih aplikacij"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ni mogoče sprem."</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Da"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Prekliči"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sl/strings.xml b/packages/PackageInstaller/res/values-sl/strings.xml
new file mode 100644
index 0000000..4075006
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sl/strings.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Namestitveno orodje za paket"</string>
+    <string name="next" msgid="3057143178373252333">"Naprej"</string>
+    <string name="install" msgid="5896438203900042068">"Namesti"</string>
+    <string name="done" msgid="3889387558374211719">"Dokončano"</string>
+    <string name="cancel" msgid="8360346460165114585">"Prekliči"</string>
+    <string name="installing" msgid="8613631001631998372">"Nameščanje …"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Nameščanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikacija je nameščena."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Ali želite namestiti to aplikacijo? Imela bo dostop do:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Ali želite namestiti to aplikacijo? Poseben dostop ni potreben."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Ali želite namestiti posodobitev te obstoječe aplikacije? Obstoječi podatki ne bodo izgubljeni. Posodobljena aplikacija bo imela dostop do:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Ali želite namestiti posodobitev za to vgrajeno aplikacijo? Obstoječi podatki ne bodo izgubljeni. Posodobljena aplikacija bo imela dostop do:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Ali želite namestiti posodobitev te obstoječe aplikacije? Obstoječi podatki ne bodo izgubljeni. Za namestitev ne potrebujete posebnega dostopa."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Ali želite namestiti posodobitev te vgrajene aplikacije? Obstoječi podatki ne bodo izgubljeni. Za namestitev ne potrebujete posebnega dostopa."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplikacija ni nameščena."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Namestitev paketa je bila blokirana."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplikacija ni bila nameščena, ker je paket v navzkrižju z obstoječim paketom."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplikacija ni bila nameščena, ker ni združljiva s tabličnim računalnikom."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Ta aplikacija ni združljiva z vašim televizorjem."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplikacija ni bila nameščena, ker ni združljiva s telefonom."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplikacija ni bila nameščena, ker paket verjetno ni veljaven."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> ni bilo mogoče namestiti v tablični računalnik."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> ni bilo mogoče namestiti v vašem televizorju."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> ni bilo mogoče namestiti v telefon."</string>
+    <string name="launch" msgid="4826921505917605463">"Odpri"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Skrbnik ne dovoli nameščanja aplikacij iz neznanih virov."</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Ta uporabnik nima dovoljenja za nameščanje neznanih aplikacij"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Ta uporabnik nima dovoljenja za nameščanje aplikacij"</string>
+    <string name="ok" msgid="3468756155452870475">"V redu"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Upravljaj aplikacije"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Zmanjkalo je prostora"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> ni bilo mogoče namestiti. Sprostite prostor in poskusite znova."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplikacije ni bilo mogoče najti"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplikacije ni bilo mogoče najti na seznamu nameščenih aplikacij."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Ni dovoljeno"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Trenutni uporabnik nima dovoljenja za izvedbo te odstranitve."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Napaka"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Aplikacije ni bilo mogoče odstraniti."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Odstrani aplikacijo"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Odstrani posodobitev"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je del te aplikacije:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Ali želite odstraniti to aplikacijo?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Ali želite odstraniti aplikacijo za "<b>"vse"</b>" uporabnike? Aplikacija in njeni podatki bodo odstranjeni iz "<b>"vseh"</b>" uporabnikov v napravi."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Ali želite to aplikacijo odstraniti za uporabnika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Želite to aplikacijo nadomestiti s tovarniško različico? Odstranjeni bodo vsi podatki."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Želite to aplikacijo nadomestiti s tovarniško različico? Odstranjeni bodo vsi podatki. To vpliva na vse uporabnike te naprave, vključno s tistimi z delovnimi profili."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Odstranitve v teku"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Neuspele odstranitve"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Odstranjevanje ..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Odstranjevanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Odstranitev je končana."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je bila odstranjena"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Odstranitev ni uspela."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Odstranjevanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ni uspelo."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Aktivne skrbniške aplikacije naprave ni mogoče odstraniti"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Aktivne skrbniške aplikacije za uporabnika <xliff:g id="USERNAME">%1$s</xliff:g> ni mogoče odstraniti"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Aplikacija je obvezna za nekatere uporabnike/profile in je odstranjena za druge."</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ta aplikacija je potrebna za profil in je ni mogoče odstraniti."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"To aplikacijo zahteva skrbnik naprave in je ni mogoče odstraniti."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Upravljanje skrbniških aplikacij naprave"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Upravljanje uporabnikov"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> ni bilo mogoče odstraniti."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Težava pri razčlenjevanju paketa."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Novo"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Vse"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Zasebnost"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Dostop do naprave"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Za to posodobitev niso potrebna nova dovoljenja."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Zavrni"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Več informacij"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Vseeno zavrni"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> od <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Ali dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; izvesti to dejanje: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vedno dovoliti to dejanje: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Samo med uporabo aplikacije"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Vedno"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Zavrni in ne sprašuj več"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"št. onemogočenih: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"vse onemogočeno"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"nič ni onemogočeno"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Dovoli"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikacije"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Dovoljenja za aplikacije"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ne sprašuj več"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Ni dovoljenj"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Dodatna dovoljenja"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Odpri podatke o aplikaciji"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one">Še <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="two">Še <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">Še <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Še <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ta aplikacija je bila zasnovana za starejšo različico sistema Android. Če dovoljenje zavrnete, lahko preneha delovati, kot bi morala."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"izvedba neznanega dejanja"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Dovoljene aplikacije: <xliff:g id="COUNT_0">%1$d</xliff:g> od <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Prikaz sistemskih aplikacij"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Skrivanje sistemskih aplikacij"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Ni aplikacij"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Nastavitve lokacije"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> je ponudnik lokacijskih storitev za to napravo. Dostop do lokacije je mogoče spremeniti v nastavitvah lokacije."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Če zavrnete to dovoljenje, osnovne funkcije naprave morda ne bodo več delovale, kot bi morale."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Uveljavlja pravilnik"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Dostop iz ozadja je onemogočen s pravilnikom"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Dostop iz ozadja je omogočen s pravilnikom"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Dostop v ospredju je omogočen s pravilnikom"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Nadzira skrbnik"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Vedno"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Samo med uporabo aplikacije"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Nikoli"</string>
+    <string name="loading" msgid="7811651799620593731">"Nalaganje …"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Vsa dovoljenja"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Druge zmožnosti aplikacije"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Zahteva za dovoljenje"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Zaznano prekrivanje zaslona"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Če želite spremeniti nastavitev tega dovoljenja, morate najprej izklopiti prekrivanje zaslona v »Nastavitve &gt; Aplikacije«"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Odpri nastavitve"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Dejanja namestitve in odstranitve v sistemu Android Wear niso podprta."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Izberite, do česa aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovolite dostop"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; je posodobljena. Izberite, do česa tej aplikaciji dovolite dostop."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Prekliči"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Naprej"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nova dovoljenja"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Trenutna dovoljenja"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Priprava aplikacije …"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Neznano"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Vaš tablični računalnik zaradi varnosti nima dovoljenja za nameščanje neznanih aplikacij iz tega vira."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Vaš televizor zaradi varnosti nima dovoljenja za nameščanje neznanih aplikacij iz tega vira."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Vaš telefon zaradi varnosti nima dovoljenja za nameščanje neznanih aplikacij iz tega vira."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Neznane aplikacije lahko resno ogrozijo varnost telefona in osebnih podatkov. Z namestitvijo te aplikacije se strinjate, da ste sami odgovorni za morebitno škodo, nastalo v telefonu, ali izgubo podatkov, do katerih lahko pride zaradi uporabe te aplikacije."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Neznane aplikacije lahko resno ogrozijo varnost tabličnega računalnika in osebnih podatkov. Z namestitvijo te aplikacije se strinjate, da ste sami odgovorni za morebitno škodo, nastalo v tabličnem računalniku, ali izgubo podatkov, do katerih lahko pride zaradi uporabe te aplikacije."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Neznane aplikacije lahko resno ogrozijo varnost televizorja in osebnih podatkov. Z namestitvijo te aplikacije se strinjate, da ste sami odgovorni za morebitno škodo, nastalo v televizorju, ali izgubo podatkov, do katerih lahko pride zaradi uporabe te aplikacije."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Nadaljuj"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Nastavitve"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Nameščanje/odstranjev. aplikacij za Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sq-television/strings.xml b/packages/PackageInstaller/res/values-sq-television/strings.xml
new file mode 100644
index 0000000..d66231c
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sq-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Refuzo dhe mos pyet përsëri"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Këtë mund ta ndryshosh më vonë te Cilësimet &gt; Aplikacionet"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Shfaq aplikacionet e sistemit"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Lejet e aplikacionit"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Lejet e aplikacionit"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Lejet për <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Lejet shtesë"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Lejet për <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sq-watch/strings.xml b/packages/PackageInstaller/res/values-sq-watch/strings.xml
new file mode 100644
index 0000000..772bb7a
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sq-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Refuzoje, mos pyet sërish"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Shfaq aplikacionet e sistemit"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Nuk mund të ndryshohet"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Po"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Anulo"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sq/strings.xml b/packages/PackageInstaller/res/values-sq/strings.xml
new file mode 100644
index 0000000..8f7e0fc
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sq/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Instaluesi i paketës"</string>
+    <string name="next" msgid="3057143178373252333">"Përpara"</string>
+    <string name="install" msgid="5896438203900042068">"Instalo"</string>
+    <string name="done" msgid="3889387558374211719">"U krye!"</string>
+    <string name="cancel" msgid="8360346460165114585">"Anulo"</string>
+    <string name="installing" msgid="8613631001631998372">"Po instalon…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Po instalon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Aplikacioni u instalua."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Dëshiron ta instalosh këtë aplikacion? Ai do të ketë qasje në:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Dëshiron ta instalosh këtë aplikacion? Nuk kërkon ndonjë qasje të veçantë."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Dëshiron të instalosh një përditësim në këtë aplikacion ekzistues? Të dhënat e tua ekzistuese nuk do të humbin. Aplikacioni i përditësuar do të ketë qasje në:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Dëshiron të instalosh një përditësim në këtë aplikacion të integruar? Të dhënat e tua ekzistuese nuk do të humbin. Aplikacioni i përditësuar do të ketë qasje në:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Dëshiron të instalosh një përditësim të këtij aplikacioni ekzistues? Të dhënat e tua ekzistuese nuk do të humbasin. Aplikacioni nuk kërkon ndonjë qasje të veçantë."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Dëshiron të instalosh një përditësim të këtij aplikacioni ekzistues? Të dhënat e tua ekzistuese nuk do të humbasin. Aplikacioni nuk kërkon ndonjë qasje të veçantë."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Aplikacioni nuk u instalua."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Instalimi paketës u bllokua."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Aplikacioni nuk u instalua pasi paketa është në konflikt me një paketë ekzistuese."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Aplikacioni nuk u instalua pasi nuk është i përputhet me tabletin tënd."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Ky aplikacion është i papërshtatshëm me televizorin tënd."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Aplikacioni nuk u instalua pasi nuk përputhet me telefonin tënd."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Aplikacioni nuk u instalua pasi paketa duket se nuk është e vlefshme."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mund të instalohej në tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mund të instalohej në televizor."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mundi të instalohej në telefon."</string>
+    <string name="launch" msgid="4826921505917605463">"Hap"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Administratori nuk lejon instalimin e aplikacioneve nga burime të panjohura."</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Aplikacionet e panjohura nuk mund të instalohen nga ky përdorues"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Ky përdorues nuk lejohet të instalojë aplikacione"</string>
+    <string name="ok" msgid="3468756155452870475">"Në rregull"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Menaxho aplikacionet"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nuk ka hapësirë"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mund të instalohej. Liro pak hapësirë dhe provo përsëri."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Aplikacioni nuk u gjet"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Aplikacioni nuk u gjet në listën e aplikacioneve të instaluara."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Nuk lejohet"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Përdoruesi aktual nuk lejohet të kryejë këtë çinstalim."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Gabim"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Aplikacioni nuk mund të instalohej."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Çinstalo aplikacionin"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Çinstalo përditësimin"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> është pjesë e aplikacionit të mëposhtëm:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Dëshiron ta çinstalosh këtë aplikacion?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Dëshiron ta çinstalosh këtë aplikacion për "<b>"të gjithë"</b>" përdoruesit? Aplikacioni dhe të dhënat e tij do të hiqen nga "<b>"të gjithë"</b>" përdoruesit e pajisjes."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Dëshiron ta çinstalosh këtë aplikacion për përdoruesin <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Të zëvendësohet ky aplikacion me versionin e fabrikës? Të gjitha të dhënat do të hiqen."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Të zëvendësohet ky aplikacion me versionin e fabrikës? Të gjitha të dhënat do të hiqen. Kjo ndikon te të gjithë përdoruesit e kësaj pajisjeje, duke përfshirë ata me profile të punës."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Çinstalimet në ekzekutim"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Çinstalimet e dështuara"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Po e çinstalon…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> po çinstalohet…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Çinstalimi përfundoi."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> u çinstalua"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Çinstalimi nuk pati sukses."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Çinstalimi i <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nuk u krye me sukses."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Nuk mund të çinstalohet aplikacioni aktiv i administratorit të pajisjes"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Nuk mund të çinstalohet aplikacioni aktiv i administratorit të pajisjes për <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Ky aplikacion kërkohet për disa përdorues ose profile dhe është çinstaluar për të tjerët"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ky aplikacion nevojitet për profilin tënd dhe nuk mund të çinstalohet."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ky aplikacion kërkohet nga administratori i pajisjes dhe nuk mund të çinstalohet."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Menaxho aplikacionet e administratorit të pajisjes"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Menaxho përdoruesit"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mundi të çinstalohej."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Kishte një problem me analizimin e paketës."</string>
+    <string name="newPerms" msgid="6039428254474104210">"E re"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Të gjitha"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privatësia"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Qasja në pajisje"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Ky përditësim nuk kërkon leje të reja."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Refuzo"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Informacione të tjera"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Refuzo sidoqoftë"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> nga <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Të lejohet &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; që të <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Të lejohet gjithmonë &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; që <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Vetëm gjatë përdorimit të aplikacionit"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Gjithmonë"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Refuzo dhe mos pyet përsëri"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> të çaktivizuara"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"të gjitha të çaktivizuara"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"asnjë e çaktivizuar"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Lejo"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Aplikacionet"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Lejet e aplikacionit"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Mos pyet përsëri"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Nuk ka leje"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Lejet shtesë"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Hap informacionet e aplikacionit"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> të tjera</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> të tjera</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ky aplikacion është projektuar për një version më të vjetër të Android. Refuzimi i lejeve mund të shkaktojë që ai të mos funksionojë më siç duhet."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"kryej një veprim të panjohur"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> aplikacione nga <xliff:g id="COUNT_1">%2$d</xliff:g> të tilla u lejuan"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Shfaq sistemin"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Fshih sistemin"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Asnjë aplikacion"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Cilësimet e vendndodhjeve"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> është një ofrues i shërbimeve të vendndodhjes për këtë pajisje. Qasja e vendndodhjes mund të modifikohet nga cilësimet e vendndodhjes."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Nëse e refuzon këtë leje, funksionet bazë të pajisjes tënde mund të mos funksionojnë më siç pritet."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Zbatuar nga politika"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Qasja në sfond është e çaktivizuar sipas politikës"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Qasja në sfond është e aktivizuar sipas politikës"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Qasja në planin e parë është e aktivizuar sipas politikës"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Kontrolluar nga administratori"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Gjithmonë"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Vetëm gjatë përdorimit të aplikacionit"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Asnjëherë"</string>
+    <string name="loading" msgid="7811651799620593731">"Po ngarkon..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Të gjitha lejet"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Kapacitete të tjera të aplikacionit"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Kërkesa e lejes"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Mbivendosja e ekranit u zbulua"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Për të ndryshuar këtë cilësim të lejes, në fillim duhet të çaktivizosh mbivendosjen e ekranit nga Cilësimet &gt; Aplikacionet"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Hap cilësimet"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Teknologjia \"Android\" që vishet"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Instalo/çinstalo veprimet që nuk mbështeten në teknologjinë që vishet."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Zgjidh se ku do të lejohet të ketë qasje &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; është përditësuar. Zgjidh se ku do të lejohet të ketë qasje ky aplikacion."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Anulo"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Vazhdo"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Lejet e reja"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Lejet aktuale"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Po vihet në përdorim aplikacioni..."</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"E panjohur"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Për sigurinë tënde, tableti yt nuk lejohet të instalojë aplikacione të panjohura nga ky burim."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Për sigurinë tënde, televizori yt nuk lejohet të instalojë aplikacione të panjohura nga ky burim."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Për sigurinë tënde, telefoni yt nuk lejohet të instalojë aplikacione të panjohura nga ky burim."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefoni dhe të dhënat e tua personale janë më të cenueshme për t\'u sulmuar nga aplikacione të panjohura. Duke instaluar këtë aplikacion, ti pranon se je përgjegjës për çdo dëm ndaj telefonit tënd ose çdo humbje të dhënash që mund të rezultojë nga përdorimi i tij."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tableti dhe të dhënat e tua personale janë më të cenueshme për t\'u sulmuar nga aplikacione të panjohura. Duke instaluar këtë aplikacion, ti pranon se je përgjegjës për çdo dëm ndaj tabletit tënd ose çdo humbje të dhënash që mund të rezultojë nga përdorimi i tij."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Televizori dhe të dhënat e tua personale janë më të cenueshme për t\'u sulmuar nga aplikacione të panjohura. Duke instaluar këtë aplikacion, ti pranon se je përgjegjës për çdo dëm ndaj televizorit tënd ose çdo humbje të dhënash që mund të rezultojë nga përdorimi i tij."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Vazhdo"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Cilësimet"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Instalimi/çinstalimi i aplikacioneve të \"Wear\""</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sr-television/strings.xml b/packages/PackageInstaller/res/values-sr-television/strings.xml
new file mode 100644
index 0000000..fcfe156
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sr-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Одбиј и не питај поново"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Ово можете да промените касније у Подешавањима &gt; Апликације"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Прикажи системске апликације"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Дозволе за апликације"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Дозволе за апликације"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Дозволе за апликацију <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Додатне дозволе"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Дозволе за апликацију <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sr-watch/strings.xml b/packages/PackageInstaller/res/values-sr-watch/strings.xml
new file mode 100644
index 0000000..7e15b01
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sr-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Одбиј и не питај поново"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Прикажи системске апликације"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Не може да се промени"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Да"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Откажи"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sr/strings.xml b/packages/PackageInstaller/res/values-sr/strings.xml
new file mode 100644
index 0000000..494b0d4
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sr/strings.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Упаковани програм за инсталацију"</string>
+    <string name="next" msgid="3057143178373252333">"Даље"</string>
+    <string name="install" msgid="5896438203900042068">"Инсталирај"</string>
+    <string name="done" msgid="3889387558374211719">"Готово"</string>
+    <string name="cancel" msgid="8360346460165114585">"Откажи"</string>
+    <string name="installing" msgid="8613631001631998372">"Инсталирање..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Инсталира се <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Апликација је инсталирана."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Желите ли да инсталирате ову апликацију? Имаће приступ следећем:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Желите ли да инсталирате ову апликацију? Не захтева посебан приступ."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Желите ли да инсталирате ажурирање за ову постојећу апликацију? Постојећи подаци неће бити изгубљени. Ажурирана апликација имаће приступ следећем:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Желите ли да инсталирате ажурирање за ову уграђену апликацију? Постојећи подаци неће бити изгубљени. Ажурирана апликација ће имати приступ следећем:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Да ли желите да инсталирате ажурирање ове постојеће апликације? Постојећи подаци неће бити изгубљени. Није потребан посебан приступ."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Да ли желите да инсталирате ажурирање ове уграђене апликације? Постојећи подаци неће бити изгубљени. Није потребан посебан приступ."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Апликација није инсталирана."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Инсталирање пакета је блокирано."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Апликација није инсталирана јер је пакет неусаглашен са постојећим пакетом."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Апликација није инсталирана јер није компатибилна са таблетом."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Ова апликација није компатибилна са ТВ-ом."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Апликација није инсталирана јер није компатибилна са телефоном."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Апликација није инсталирана јер је пакет неважећи."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Није могуће инсталирати апликацију <xliff:g id="APP_NAME">%1$s</xliff:g> на таблет."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Нисмо успели да инсталирамо <xliff:g id="APP_NAME">%1$s</xliff:g> на ТВ."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Није могуће инсталирати апликацију <xliff:g id="APP_NAME">%1$s</xliff:g> на телефон."</string>
+    <string name="launch" msgid="4826921505917605463">"Отвори"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Администратор не дозвољава инсталирање апликација добијених из непознатих извора"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Овај корисник не може да инсталира непознате апликације"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Овом кориснику није дозвољено да инсталира апликације"</string>
+    <string name="ok" msgid="3468756155452870475">"Потврди"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Управљање апликацијама"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Нема више места"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Није могуће инсталирати апликацију <xliff:g id="APP_NAME">%1$s</xliff:g>. Ослободите додатни простор и покушајте поново."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Апликација није пронађена"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Апликација није пронађена на листи инсталираних апликација."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Није дозвољено"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Актуелном кориснику није дозвољено да обави ово деинсталирање."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Грешка"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Деинсталирање апликације није успело."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Деинсталирање апликације"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Деинсталирање ажурирања"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> је део следеће апликације:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Да ли желите да деинсталирате ову апликацију?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Да ли желите да деинсталирате ову апликацију за "<b>"све"</b>" кориснике? Апликација и подаци који се на њу односе биће уклоњени за "<b>"све"</b>" кориснике овог уређаја."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Желите ли да деинсталирате ову апликацију за корисника <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Желите ли да замените ову апликацију фабричком верзијом? Сви подаци ће бити уклоњени."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Желите ли да замените ову апликацију фабричком верзијом? Сви подаци ће бити уклоњени. Ово утиче на све кориснике овог уређаја, укључујући и оне са профилима за Work."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Активна деинсталирања"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Неуспела деинсталирања"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Деинсталирање..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> се деинсталира…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Деинсталирање је завршено."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Апликација <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> је деинсталирана"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Деинсталирање није успело."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Деинсталирање апликације <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> није успело."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Не можете да деинсталирате апликацију за активног администратора уређаја"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Не можете да деинсталирате апликацију за активног администратора уређаја за <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Ова апликација је потребна за неке кориснике или профиле, а деинсталирана је за друге"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ова апликација је потребна за ваш профил и не може да се деинсталира."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ова апликација је потребна администратору уређаја и не може да се деинсталира."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Управљај апликацијама за администраторе уређаја"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Управљаj корисницима"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Није могуће деинсталирати апликацију <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Дошло је до проблема при рашчлањивању пакета."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Ново"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Све"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Приватност"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Приступ уређају"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Ово ажурирање не захтева нове дозволе."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Одбаци"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Више информација"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Ипак одбиј"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>. од <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Желите ли да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Желите ли увек да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Само док се апликација користи"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Увек"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Одбиј и не питај поново"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"Онемогућених: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"све су онемогућене"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ниједна није онемогућена"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Дозволи"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Апликације"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Дозволе за апликације"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Не питај поново"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Нема дозвола"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Додатне дозволе"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Отвори информације о апликацији"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+      <item quantity="other">још <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ова апликација је дизајнирана за старију верзију Android-а. Ако одбијете дозволу, она можда више неће правилно да функционише."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"обавља непознату радњу"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> од <xliff:g id="COUNT_1">%2$d</xliff:g> апликација има дозволу"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Прикажи системске"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Сакриј системске"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Нема апликација"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Подешавања локације"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> пружа услуге локације за овај уређај. Приступ локацији можете да измените у подешавањима локације."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Ако одбијете ову дозволу, основне функције уређаја можда неће више функционисати исправно."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Примењује се у складу са смерницама"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Приступ у позадини је онемогућен смерницама"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Приступ у позадини је омогућен смерницама"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Приступ у првом плану је омогућен смерницама"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Контролише администратор"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Увек"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Само док се апликација користи"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Никада"</string>
+    <string name="loading" msgid="7811651799620593731">"Учитава се…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Све дозволе"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Остале могућности апликације"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Захтев за дозволу"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Откривен је елемент који прекрива садржај екрана"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Да бисте променили подешавање ове дозволе, прво треба да искључите елемент који прекрива садржај екрана у одељку Подешавања &gt; Апликације"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Отвори подешавања"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Радње Инсталирај/Деинсталирај нису подржане у Wear-у."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Изаберите чему &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; може да приступа"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Апликација &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; је ажурирана. Изаберите чему ова апликација може да приступа."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Откажи"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Настави"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Нове дозволе"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Актуелне дозволе"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Апликација се припрема…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Непознато"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Таблету из безбедносних разлога није дозвољено да инсталира непознате апликације из овог извора."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Телевизору из безбедносних разлога није дозвољено да инсталира непознате апликације из овог извора."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Телефону из безбедносних разлога није дозвољено да инсталира непознате апликације из овог извора."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Телефон и лични подаци су подложнији нападу непознатих апликација. Ако инсталирате ову апликацију, прихватате да сте одговорни за евентуална оштећења телефона или губитак података до којих може да дође због њеног коришћења."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Таблет и лични подаци су подложнији нападу непознатих апликација. Ако инсталирате ову апликацију, прихватате да сте одговорни за евентуална оштећења таблета или губитак података до којих може да дође због њеног коришћења."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"ТВ и лични подаци су подложнији нападу непознатих апликација. Ако инсталирате ову апликацију, прихватате да сте одговорни за евентуална оштећења ТВ-а или губитак података до којих може да дође због њеног коришћења."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Настави"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Подешавања"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Инсталирање/деинсталирање Wear апликација"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sv-television/strings.xml b/packages/PackageInstaller/res/values-sv-television/strings.xml
new file mode 100644
index 0000000..5f23767
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sv-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Neka och fråga inte igen"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Du kan ändra detta senare i Inställningar &gt; Appar"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Visa systemappar"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Appens behörigheter"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Appens behörigheter"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Behörigheter för <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Ytterligare behörigheter"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Behörigheter för <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sv-watch/strings.xml b/packages/PackageInstaller/res/values-sv-watch/strings.xml
new file mode 100644
index 0000000..f20ec21
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sv-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Avvisa och fråga inte igen"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Visa systemappar"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Kan inte ändras"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ja"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Avbryt"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sv/strings.xml b/packages/PackageInstaller/res/values-sv/strings.xml
new file mode 100644
index 0000000..ff4f4c1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sv/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Installationsprogram för paket"</string>
+    <string name="next" msgid="3057143178373252333">"Nästa"</string>
+    <string name="install" msgid="5896438203900042068">"Installera"</string>
+    <string name="done" msgid="3889387558374211719">"Färdig"</string>
+    <string name="cancel" msgid="8360346460165114585">"Avbryt"</string>
+    <string name="installing" msgid="8613631001631998372">"Installerar…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> installeras …"</string>
+    <string name="install_done" msgid="3682715442154357097">"Appen har installerats."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Vill du installera den här appen? Den får åtkomst till:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Vill du installera den här appen? Den kräver ingen särskild åtkomst."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Vill du installera en uppdatering till den här befintliga appen? Dina befintliga data försvinner inte. Den uppdaterade appen får åtkomst till:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Vill du installera en uppdatering till den här befintliga förinstallerade appen? Dina befintliga data försvinner inte. Den uppdaterade appen får åtkomst till:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Vill du installera en uppdatering av den befintliga appen? Dina befintliga data försvinner inte. Ingen särskild åtkomst krävs."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Vill du installera en uppdatering av den inbyggda appen? Dina befintliga data försvinner inte. Ingen särskild åtkomst krävs."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Appen har inte installerats."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Paketet har blockerats för installation."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Appen har inte installerats på grund av en konflikt mellan detta paket och ett befintligt paket."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Appen har inte installerats eftersom den inte är kompatibel med surfplattan."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Appen är inte kompatibel med din TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Appen har inte installerats eftersom den inte är kompatibel med mobilen."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Appen har inte installerats eftersom paketet verkar vara ogiltigt."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Det gick inte att installera <xliff:g id="APP_NAME">%1$s</xliff:g> på surfplattan."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunde inte installeras på TV:n."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Det gick inte att installera <xliff:g id="APP_NAME">%1$s</xliff:g> på mobilen."</string>
+    <string name="launch" msgid="4826921505917605463">"Öppna"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Administratören tillåter inte installation av appar från okända källor"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Denna användare får inte installera okända appar"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Användaren har inte behörighet att installera appar"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Hantera appar"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Slut på utrymme"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Det gick inte att installera <xliff:g id="APP_NAME">%1$s</xliff:g>. Frigör minne och försök igen."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Appen hittades inte"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Appen fanns inte i listan över installerade appar."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Ingen behörighet"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Den aktuella användaren har inte behörighet att utföra avinstallationen."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Fel"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Det gick inte att installera appen."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Avinstallera appen"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Avinstallera uppdateringen"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> är en del av följande app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Vill du avinstallera appen?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Vill du avinstallera den här appen för "<b>"alla"</b>" användare? Appen och alla data i den tas bort från "<b>"alla"</b>" användare på enheten."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Vill du avinstallera appen för användaren <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Vill du ersätta den här appen med den version som var installerad när enheten var ny? All information tas bort."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Vill du ersätta den här appen med den version som var installerad när enheten var ny? All information tas bort. Detta påverkar alla som använder enheten, även dem med jobbprofiler."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Avinstallationer som pågår"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Avinstallationer som misslyckats"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Avinstallerar…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> avinstalleras …"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Avinstallationen har slutförts."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> har avinstallerats"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Det gick inte att avinstallera."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Det gick inte att avinstallera <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Det går inte att avinstallera den aktiva appen för enhetsadministratör"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Det går inte att avinstallera den aktiva appen för enhetsadministratör för <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Den här appen är obligatorisk för vissa användare och profiler och har avinstallerats för andra"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Appen behövs i profilen och det går inte att avinstallera den"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Appen krävs av enhetsadministratören och kan därför inte avinstalleras."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Hantera appar för enhetsadministratör"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Hantera användare"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Det gick inte att avinstallera <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Ett problem uppstod när paketet analyserades."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Nytt"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Alla"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Sekretess"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Enhetsåtkomst"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Det krävs inga nya behörigheter för den här uppdateringen."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Neka"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Mer information"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Neka ändå"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> av <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Tillåter du &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; att <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Vill du alltid tillåta att &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Bara när appen används"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Alltid"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Neka och fråga inte igen"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> har inaktiverats"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"alla har inaktiverats"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"inga har inaktiverats"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Tillåt"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Appar"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Appens behörigheter"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Fråga inte igen"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Inga behörigheter"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Ytterligare behörigheter"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Öppna appinformation"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> till</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> till</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Den här appen utformades för en äldre version av Android. Om du nekar appen behörighet kan det hända att den inte längre fungerar som den ska."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"utför en okänd åtgärd"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> av <xliff:g id="COUNT_1">%2$d</xliff:g> appar tillåts"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Visa systemet"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Dölj systemet"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Inga appar"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Platsinställningar"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> är en platstjänstleverantör för enheten. Platsåtkomsten kan redigeras i platsinställningarna."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Om du nekar appen behörighet kan det hända att grundläggande funktioner på enheten inte fungerar som de ska."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Enligt policyn"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Åtkomst i bakgrunden har inaktiverats av en princip"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Åtkomst i bakgrunden har aktiverats av en princip"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Åtkomst i förgrunden har aktiverats av en princip"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Styrs av administratören"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Alltid"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Bara när appen används"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Aldrig"</string>
+    <string name="loading" msgid="7811651799620593731">"Läser in …"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Alla behörigheter"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Andra appbehörigheter"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Begäran om behörighet"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Skärmöverlagring har upptäckts"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Innan du kan ändra den här behörighetsinställningen måste du inaktivera skärmöverlagring under Inställningar &gt; Appar"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Öppna inställningarna"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Åtgärder för att installera/avinstallera stöds inte på Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Välj vad du vill ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; har uppdaterats. Välj vad du vill ge appen åtkomst till."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Avbryt"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Fortsätt"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Nya behörigheter"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Nuvarande behörighet"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Provkör appen …"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Okänd"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Av säkerhetsskäl får okända appar från den här källan inte installeras av surfplattan."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Av säkerhetsskäl får okända appar från den här källan inte installeras av TV:n."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Av säkerhetsskäl får okända appar från den här källan inte installeras av mobilen."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Din mobil och personliga data är mer sårbara för attacker från okända appar. Genom att installera denna app bekräftar du att du är ansvarig för eventuella skador på mobilen och för dataförlust som kan uppstå vid användning av denna app."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Din surfplatta och personliga data är mer sårbara för attacker från okända appar. Genom att installera denna app bekräftar du att du är ansvarig för eventuella skador på surfplattan och för dataförlust som kan uppstå vid användning av denna app."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Din TV och personliga data är mer sårbara för attacker från okända appar. Genom att installera denna app bekräftar du att du är ansvarig för eventuella skador på TV:n och för dataförlust som kan uppstå vid användning av denna app."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Fortsätt"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Inställningar"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear-appar installeras/avinstalleras"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sw-television/strings.xml b/packages/PackageInstaller/res/values-sw-television/strings.xml
new file mode 100644
index 0000000..25fd696
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sw-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Hapana na usiulize tena"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Unaweza kubadilisha hatua hii baadaye kwenye Mipangilio na Programu"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Onyesha programu za mfumo"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Ruhusa za programu"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Ruhusa za programu"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Ruhusa za <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Ruhusa za ziada"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Ruhusa za <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sw-watch/strings.xml b/packages/PackageInstaller/res/values-sw-watch/strings.xml
new file mode 100644
index 0000000..30d68e5
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sw-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Hapana, usiulize tena"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Onyesha programu za mfumo"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Haiwezi kubadilishwa"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ndiyo"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Ghairi"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sw/strings.xml b/packages/PackageInstaller/res/values-sw/strings.xml
new file mode 100644
index 0000000..c431983
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sw/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Kisakinishaji cha furushi"</string>
+    <string name="next" msgid="3057143178373252333">"Inayofuata"</string>
+    <string name="install" msgid="5896438203900042068">"Sakinisha"</string>
+    <string name="done" msgid="3889387558374211719">"Nimemaliza"</string>
+    <string name="cancel" msgid="8360346460165114585">"Ghairi"</string>
+    <string name="installing" msgid="8613631001631998372">"inawekwa..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Inasakinisha <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Programu imewekwa."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Je, ungependa kuiweka programu hii? Itaweza:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Je, ungependa kuiweka programu hii? Haihitaji idhini ya kufikia kitu chochote."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Je, unataka kuweka sasisho katika programu hii? Data yako iliyopo haitapotea. Programu iliyosasishwa itaweza:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Je, unataka kuweka sasisho la programu hii iliyojengewa ndani? Data yako iliyopo haitapotea. Programu iliyosasishwa itaweza:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Je, unataka kuweka sasisho la programu hii? Data yako iliyopo haitapotea. Haihitaji idhini yoyote maalum ya kufikia."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Je, unataka kuweka sasisho la programu hii? Data yako iliyopo haitapotea. Haihitaji idhini yoyote maalum ya kufikia."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Programu haikusakinishwa."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Kifurushi kimezuiwa kisisakinishwe."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Programu haikusakinishwa kwa sababu haiafikiani na kifurushi kingine kilichopo."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Programu haikusakinishwa kwa sababu haioani na kompyuta kibao yako."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Programu hii haioani na runinga yako."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Programu haikusakinishwa kwa sababu haioani na simu yako."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Programu haikusakinishwa kwa sababu inaonekana kuwa kifurushi si sahihi."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> haikuweza kusakinishwa kwenye kompyuta yako kibao."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> haikuweza kusakinishwa kwenye runinga yako."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> haikuweza kusakinishwa kwenye simu yako."</string>
+    <string name="launch" msgid="4826921505917605463">"Fungua"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Msimamizi wako haruhusu usakinishaji wa programu zinazopatikana kutoka vyanzo visivyojulikana"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Mtumiaji huyu hana idhini ya kusakinisha programu ambazo hazijulikani"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Mtumiaji huyu haruhusiwi kusakinisha programu"</string>
+    <string name="ok" msgid="3468756155452870475">"Sawa"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Dhibiti programu"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Nafasi imeisha"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> haingeweza kusakinishwa. Wezesha nafasi kiasi na ujaribu tena."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Programu haikupatikana"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Programu haikupatikana katika orodha ya programu zilizosakinishwa."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Hairuhusiwi"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Mtumiaji wa sasa hana ruhusa ya kuondoa kipengee hiki."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Hitilafu"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Imeshindwa kuondoa programu."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Sanidua programu"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Sanidua kisasisho"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ni sehemu ya programu ifuatayo:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Unataka kusanidua programu hii?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Je, unataka kusanidua programu hii kwa "<b>"watumiaji"</b>" wote? Programu na data yake zitaondolewa kutoka kwa "<b>"watumiaji"</b>" kwenye kifaa."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Je, unataka kuondoa programu hii kwa mtumiaji <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Ungependa kubadilisha programu hii na toleo la kiwanda? Data yote itaondolewa."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Ungependa kubadilisha programu hii na toleo la kiwanda? Data yote itaondolewa. Hatua hii itaathiri watumiaji wote wa kifaa hiki, ikiwa ni pamoja na wale walio na wasifu za kazini."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Mara ambazo programu inaondolewa sasa"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Mara ambazo programu haikuondolewa"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Inasanidua..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Inaondoa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Imesaniduliwa."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Imeondoa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Kusanidua hakukufaulu."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Imeshindwa kuondoa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Imeshindwa kuondoa programu inayotumika ya msimamizi wa kifaa"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Imeshindwa kuondoa programu inayotumika ya msimamizi wa kifaa cha <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Baadhi ya wasifu au watumiaji wanahitaji programu, kwa hivyo haijaondolewa kwa wengine"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Programu hii inahitajika kwa wasifu wako kwa hivyo haiwezi kuondolewa."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Programu hii inahitajika na msimamizi wako wa kifaa na haiwezi kuondolewa."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Dhibiti programu za msimamizi wa kifaa"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Dhibiti watumiaji"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> haingeweza kusaniduliwa."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Kulikuwa na tatizo la kuchanganua furushi."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Mpya"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Zote"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Faragha"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Kufikia Kifaa"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Sasisho hili halihitaji vibali vipya."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Hapana"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Maelezo zaidi"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Kataa"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> kati ya <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; itekeleze <xliff:g id="ACTION">%2$s</xliff:g> kila wakati?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Wakati unatumia programu tu"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Kila wakati"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Kataa na usiulize tena"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> zimezimwa"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"zimezimwa zote"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"hakuna zilizozimwa"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Ndiyo"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Programu"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Ruhusa za programu"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Usiulize tena"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Hakuna ruhusa"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Ruhusa za ziada"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Fungua maelezo ya programu"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> zaidi</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> zaidi</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Programu hii iliundwa kwa ajili ya toleo la zamani la Android. Kuinyima ruhusa kunaweza kusababisha iache kutenda kazi kama ilivyokusudiwa."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"kutekeleza kitendo kisichojulikana"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Inaruhusu programu <xliff:g id="COUNT_0">%1$d</xliff:g> kati ya <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Onyesha mfumo"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ficha mfumo"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Hakuna programu"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Mipangilio ya Mahali"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> hutoa huduma za mahali kwenye kifaa hiki. Idhini ya kufikia mahali inaweza kurekebishwa katika mipangilio ya mahali."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Usipokubali ruhusa hii, huenda vipengele vya msingi vya kifaa chako havitafanya kazi kama ilivyokusudiwa."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Hutekelezwa na sera"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Ufikiaji wa chinichini umezimwa na sera"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Ufikiaji wa chinichini umewashwa na sera"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Ufikiaji wa hadharani umewashwa na sera"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Imedhibitiwa na msimamizi"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Kila wakati"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Wakati unatumia programu tu"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Kamwe"</string>
+    <string name="loading" msgid="7811651799620593731">"Inapakia…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Ruhusa zote"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Uwezo mwingine wa programu"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Ombi la idhini"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Imetambua tangazo lililowekelewa juu ya skrini"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Ili kubadilisha mpangilio huu wa ruhusa, ni lazima kwanza uzime tangazo lililowekelewa juu ya skrini kwenye Mipangilio na Programu"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Fungua mipangilio"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Huduma ya Android Wear haiwezi kutekeleza vitendo vya Kusakinisha au Kuondoa vipengee."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Chagua vipengee ambavyo unaruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; imesasishwa. Chagua vipengee unavyoruhusu programu hii ifikie."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Ghairi"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Endelea"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Ruhusa mpya"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Ruhusa zilizopo"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Inatayarisha programu..."</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Isiyojulikana"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Kwa sababu ya usalama wako, kompyuta yako kibao haina ruhusa ya kusakinisha programu ambazo hazijulikani, kutoka kwenye chanzo hiki."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Kwa sababu ya usalama wako, TV yako haina ruhusa ya kusakinisha programu ambazo hazijulikani, kutoka kwenye chanzo hiki."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Kwa sababu ya usalama wako, simu yako haina ruhusa ya kusakinisha programu ambazo hazijulikani, kutoka kwenye chanzo hiki."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Data yako ya binafsi na ya simu yako inaweza kuathiriwa na programu ambazo hazijulikani. Kwa kusakinisha programu hii, unakubali kuwajibika kutokana na uharibifu wowote kwenye simu yako au kupotea kwa data kutokana na matumizi yake."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Data yako ya binafsi na ya kompyuta yako kibao inaweza kuathiriwa na programu ambazo hazijulikani. Kwa kusakinisha programu hii, unakubali kuwajibika kutokana na uharibifu wowote kwenye kompyuta yako kibao au kupotea kwa data kutokana na matumizi yake."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Data yako ya binafsi na ya televisheni yako inaweza kuathiriwa na programu ambazo hazijulikani. Kwa kusakinisha programu hii, unakubali kuwajibika kutokana na uharibifu wowote kwenye televisheni yako au kupotea kwa data kutokana na matumizi yake."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Endelea"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Mipangilio"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Inasakinisha/inaondoa programu za Android Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sw180dp-notround-watch/dimens.xml b/packages/PackageInstaller/res/values-sw180dp-notround-watch/dimens.xml
new file mode 100644
index 0000000..84072a2
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sw180dp-notround-watch/dimens.xml
@@ -0,0 +1,19 @@
+<?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>
+    <!-- Dimens for dialog layouts -->
+    <dimen name="diag_button_size">48dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-sw210dp-round-watch/dimens.xml b/packages/PackageInstaller/res/values-sw210dp-round-watch/dimens.xml
new file mode 100644
index 0000000..d896138
--- /dev/null
+++ b/packages/PackageInstaller/res/values-sw210dp-round-watch/dimens.xml
@@ -0,0 +1,19 @@
+<?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>
+    <!-- Dimens for dialog layouts -->
+    <dimen name="diag_button_size">54dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ta-television/strings.xml b/packages/PackageInstaller/res/values-ta-television/strings.xml
new file mode 100644
index 0000000..786bbe2
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ta-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"நிராகரி, மீண்டும் கேட்காதே"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"அமைப்புகள் &gt; பயன்பாடுகள் என்பதில் பிறகு மாற்றலாம்"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"முறைமைப் பயன்பாடுகளைக் காட்டு"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"பயன்பாட்டு அனுமதிகள்"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"பயன்பாட்டு அனுமதிகள்"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> அனுமதிகள்"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"கூடுதல் அனுமதிகள்"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> அனுமதிகள்"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ta-watch/strings.xml b/packages/PackageInstaller/res/values-ta-watch/strings.xml
new file mode 100644
index 0000000..23dab29
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ta-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"நிராகரி, மீண்டும் கேட்காதே"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"முறைமைப் பயன்பாடுகளைக் காட்டு"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"மாற்ற முடியாது"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"ஆம்"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"ரத்துசெய்"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ta/strings.xml b/packages/PackageInstaller/res/values-ta/strings.xml
new file mode 100644
index 0000000..366f6d9
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ta/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"பேக்கேஜ் இன்ஸ்டாலர்"</string>
+    <string name="next" msgid="3057143178373252333">"அடுத்து"</string>
+    <string name="install" msgid="5896438203900042068">"நிறுவு"</string>
+    <string name="done" msgid="3889387558374211719">"முடிந்தது"</string>
+    <string name="cancel" msgid="8360346460165114585">"ரத்துசெய்"</string>
+    <string name="installing" msgid="8613631001631998372">"நிறுவுகிறது…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ஐ நிறுவுகிறது…"</string>
+    <string name="install_done" msgid="3682715442154357097">"பயன்பாடு நிறுவப்பட்டது."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"இந்தப் பயன்பாட்டை நிறுவ விரும்புகிறீர்களா? அது இதற்கான அணுகலைப் பெறும்:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"இந்தப் பயன்பாட்டை நிறுவ விரும்புகிறீர்களா? இதற்கு எந்தத் தனிப்பட்ட அணுகலும் தேவையில்லை."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"முன்பே உள்ள இந்தப் பயன்பாட்டில் புதுப்பிப்பை நிறுவ விரும்புகிறீர்களா? ஏற்கனவே உள்ள உங்கள் தரவை இழக்க மாட்டீர்கள். புதுப்பிக்கப்பட்ட பயன்பாடு இதற்கான அணுகலைப் பெறும்:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"உள்ளமைக்கப்பட்ட பயன்பாட்டில் புதுப்பிப்பை நிறுவ விரும்புகிறீர்களா? ஏற்கனவே உள்ள உங்கள் தரவை இழக்க மாட்டீர்கள். புதுப்பிக்கப்பட்ட பயன்பாடு இதற்கான அணுகலைப் பெறும்:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"முன்பே உள்ள இந்தப் பயன்பாட்டில் புதுப்பிப்பை நிறுவ விரும்புகிறீர்களா? ஏற்கனவே உள்ள உங்கள் தரவை இழக்கமாட்டீர்கள். இதற்குத் தனிப்பட்ட அணுகல் எதுவும் தேவையில்லை."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"உள்ளமைக்கப்பட்ட பயன்பாட்டில் புதுப்பிப்பை நிறுவ விரும்புகிறீர்களா? ஏற்கனவே உள்ள உங்கள் தரவை இழக்க மாட்டீர்கள். இதற்குத் தனிப்பட்ட அணுகல் எதுவும் தேவையில்லை."</string>
+    <string name="install_failed" msgid="6579998651498970899">"பயன்பாடு நிறுவப்படவில்லை."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"இந்தத் தொகுப்பு நிறுவுவதிலிருந்து தடுக்கப்பட்டது."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"தொகுப்பானது தற்போதுள்ள தொகுப்புடன் இணக்கமற்றதாக உள்ளதால், பயன்பாடு நிறுவப்படவில்லை."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"உங்கள் டேப்லெட்டுடன் இணக்கமற்றதாக உள்ளதால், பயன்பாடு நிறுவப்படவில்லை."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"உங்கள் டிவியுடன் இந்தப் பயன்பாடு இணங்கவில்லை."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"உங்கள் மொபைலுடன் இணக்கமற்றதாக உள்ளதால், பயன்பாடு நிறுவப்படவில்லை."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"தொகுப்பு தவறானது போல் உள்ளதால், பயன்பாடு நிறுவப்படவில்லை."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> பயன்பாட்டை உங்கள் டேப்லெட்டில் நிறுவ முடியாது."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"உங்கள் டிவியில் <xliff:g id="APP_NAME">%1$s</xliff:g>ஐ நிறுவ முடியவில்லை."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> பயன்பாட்டை உங்கள் மொபைலில் நிறுவ முடியாது."</string>
+    <string name="launch" msgid="4826921505917605463">"திற"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"அறியப்படாத மூலங்களிலிருந்து பெற்ற பயன்பாடுகளை நிறுவ, உங்கள் நிர்வாகி அனுமதிக்கவில்லை"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"அறியப்படாத பயன்பாடுகளை, இந்தப் பயனர் நிறுவ முடியாது"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"பயன்பாடுகளை நிறுவ, இந்தப் பயனருக்கு அனுமதியில்லை"</string>
+    <string name="ok" msgid="3468756155452870475">"சரி"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"பயன்பாடுகளை நிர்வகிக்கவும்"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"இடம் இல்லை"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> பயன்பாட்டை நிறுவ முடியாது. சில இடத்தைக் காலி செய்து மீண்டும் முயற்சிக்கவும்."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"பயன்பாடு கண்டறியப்படவில்லை"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"நிறுவிய பயன்பாடுகளின் பட்டியலில் பயன்பாடு இல்லை."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"அனுமதிக்கப்படவில்லை"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"இதை நிறுவல் நீக்குவதற்கு, தற்போதைய பயனர் அனுமதிக்கப்படவில்லை."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"பிழை"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"பயன்பாட்டை நிறுவல் நீக்க முடியவில்லை."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"பயன்பாட்டை நிறுவல் நீக்கு"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"புதுப்பிப்பை நிறுவல் நீக்கு"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ஆனது பின்வரும் பயன்பாட்டின் பகுதியாகும்:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"இந்தப் பயன்பாட்டை நிறுவல் நீக்க விரும்புகிறீர்களா?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"இந்தப் பயன்பாட்டை "<b>"எல்லா"</b>" பயனர்களுக்கும் நிறுவல் நீக்க விரும்புகிறீர்களா? பயன்பாடும், அதன் தரவும் சாதனத்தில் உள்ள "<b>"எல்லா"</b>" பயனர்களிடமிருந்தும் அகற்றப்படும்."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"<xliff:g id="USERNAME">%1$s</xliff:g> பயனருக்கான இந்தப் பயன்பாட்டை நிறுவல்நீக்க விரும்புகிறீர்களா?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ஆரம்பநிலைப் பதிப்பாக இந்தப் பயன்பாட்டை மாற்றியமைக்கவா? எல்லா தரவும் அகற்றப்படும்."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ஆரம்பநிலைப் பதிப்பாக இந்தப் பயன்பாட்டை மாற்றியமைக்கவா? எல்லா தரவும் அகற்றப்படும். பணிச் சுயவிவரங்களுடன் உள்ளவர்கள் உட்பட இந்தச் சாதனத்தின் எல்லா பயனர்களையும் இது பாதிக்கும்."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"இயக்கத்திலுள்ள நிறுவல் நீக்கங்கள்"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"தோல்வியடைந்த நிறுவல் நீக்கங்கள்"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"நிறுவலை நீக்குகிறது…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ஐ நிறுவல் நீக்குகிறது…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"நிறுவல் நீக்குவது முடிந்தது."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> நிறுவல் நீக்கப்பட்டது"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"நிறுவல் நீக்குவதில் தோல்வி."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ஐ நிறுவல் நீக்க முடியவில்லை."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"செயலில் உள்ள சாதன நிர்வாகிப் பயன்பாட்டை நிறுவல் நீக்க முடியாது"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g>க்கான செயலில் உள்ள சாதன நிர்வாகிப் பயன்பாட்டை நிறுவல் நீக்க முடியாது"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"இது சில பயனர்கள்/சுயவிவரங்களுக்குத் தேவைப்படுவதால், நிறுவல்நீக்க முடியாது, பிறருக்கு நிறுவல் நீக்கப்பட்டது"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"உங்கள் சுயவிவரத்திற்கு இந்தப் பயன்பாடு தேவைப்படுவதால், அதை நிறுவல்நீக்க முடியாது, பிறருக்கு நிறுவல் நீக்கப்பட்டது."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"சாதன நிர்வாகிக்கு இந்தப் பயன்பாடு தேவைப்படுவதால், நிறுவல்நீக்க முடியாது."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"சாதன நிர்வாகிப் பயன்பாடுகளை நிர்வகி"</string>
+    <string name="manage_users" msgid="3125018886835668847">"பயனர்களை நிர்வகி"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> பயன்பாட்டை நிறுவல் நீக்க முடியாது."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"தொகுப்பைக் குறியீட்டு ஆய்வு செய்வதில் சிக்கல் ஏற்பட்டது."</string>
+    <string name="newPerms" msgid="6039428254474104210">"புதிது"</string>
+    <string name="allPerms" msgid="1024385515840703981">"எல்லாம்"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"தனியுரிமை"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"சாதன அணுகல்"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"இந்தப் புதுப்பிப்பிற்குப் புதிய அனுமதிகள் எதுவும் தேவையில்லை."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"நிராகரி"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"மேலும் தகவல்"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"பரவாயில்லை, நிராகரி"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"செயலைச் செய்ய <xliff:g id="ACTION">%2$s</xliff:g>, &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ஐ அனுமதிக்கவா?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"<xliff:g id="ACTION">%2$s</xliff:g>ஐச் செய்ய &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை எப்போதும் அனுமதிக்கவா?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"ஆப்ஸைப் பயன்படுத்தும்போது மட்டும் அனுமதி"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"எப்போதும் அனுமதி"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"நிராகரி, மீண்டும் கேட்காதே"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> முடக்கப்பட்டன"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"எல்லாம் முடக்கப்பட்டன"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"எதுவும் முடக்கப்படவில்லை"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"அனுமதி"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"ஆப்ஸ்"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"பயன்பாட்டு அனுமதிகள்"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"மீண்டும் கேட்காதே"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"அனுமதிகள் இல்லை"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"கூடுதல் அனுமதிகள்"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"பயன்பாட்டுத் தகவலைத் திற"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"இந்தப் பயன்பாடு Android இன் பழைய பதிப்புக்காக வடிவமைக்கப்பட்டது. அனுமதியை மறுத்தால் அது சரியாக செயல்படாமல் போகலாம்."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"அறியாத செயலைச் செயல்படுத்தும்"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"அனுமதிக்கப்பட்ட ஆப்ஸ்: <xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"எல்லாம் காட்டு"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"முறைமையை மறை"</string>
+    <string name="no_apps" msgid="1965493419005012569">"பயன்பாடுகள் இல்லை"</string>
+    <string name="location_settings" msgid="1774875730854491297">"இருப்பிட அமைப்புகள்"</string>
+    <string name="location_warning" msgid="8778701356292735971">"இந்தச் சாதனத்திற்கான இருப்பிடச் சேவைகளின் வழங்குநர் <xliff:g id="APP_NAME">%1$s</xliff:g> ஆகும். இருப்பிட அமைப்புகளிலிருந்து இருப்பிட அணுகலை மாற்றலாம்."</string>
+    <string name="system_warning" msgid="7103819124542305179">"இந்த அனுமதியை நிராகரித்தால், உங்கள் சாதனத்தின் அடிப்படை அம்சங்கள் சரியாகச் செயல்படாமல் போகலாம்."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"கொள்கையின் படி செயல்படுத்தப்பட்டது"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"கொள்கையின்படி பின்புல அணுகல் முடக்கப்பட்டது"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"கொள்கையின்படி பின்புல அணுகல் இயக்கப்பட்டது"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"கொள்கையின்படி முன்புல அணுகல் இயக்கப்பட்டது"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"நிர்வாகி கட்டுப்படுத்துகிறார்"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"எப்போதும்"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"ஆப்ஸை உபயோகிக்கும்போது மட்டும்"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"ஒருபோதும் வேண்டாம்"</string>
+    <string name="loading" msgid="7811651799620593731">"ஏற்றுகிறது..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"எல்லா அனுமதிகளும்"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"பயன்பாட்டின் பிற திறன்கள்"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"அனுமதி கோரிக்கை"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"திரையின் மேலே செயல்படும் பயன்பாடுகள் கண்டறியப்பட்டன"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"இந்த அனுமதியை மாற்ற, அமைப்புகள் &gt; பயன்பாடுகள் என்பதற்குச் சென்று, திரையின் மேலே செயல்படும் பயன்பாடுகளை முதலில் முடக்கவும்"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"அமைப்புகளைத் திற"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear இல் நிறுவுதல்/நிறுவல் நீக்குதலுக்கு ஆதரவில்லை."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; எவற்றை அணுகலாம் என்பதைத் தேர்வுசெய்யவும்"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; புதுப்பிக்கப்பட்டது. இந்தப் பயன்பாடு எவற்றை அணுகலாம் என்பதைத் தேர்வுசெய்யவும்."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"ரத்துசெய்"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"தொடர்க"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"புதிய அனுமதிகள்"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"தற்போதைய அனுமதிகள்"</string>
+    <string name="message_staging" msgid="6151794817691100003">"பயன்பாடு தயாராகிறது…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"தெரியாதது"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"உங்கள் பாதுகாப்பிற்காக, இந்த மூலத்திலிருந்து அறியப்படாத பயன்பாடுகளை உங்கள் டேப்லெட்டில் நிறுவ முடியாது."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"உங்கள் பாதுகாப்பிற்காக, இந்த மூலத்திலிருந்து அறியப்படாத பயன்பாடுகளை உங்கள் டிவியில் நிறுவ முடியாது."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"உங்கள் பாதுகாப்பிற்காக, இந்த மூலத்திலிருந்து அறியப்படாத பயன்பாடுகளை உங்கள் மொபைலில் நிறுவ முடியாது."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"அறியப்படாத பயன்பாடுகள், உங்கள் மொபைலையும் தனிப்பட்ட தரவையும் அதிகம் பாதிக்கக்கூடும். இந்தப் பயன்பாட்டை நிறுவுவதால், அவற்றைப் பயன்படுத்தும் போது உங்கள் மொபைலுக்கு ஏதேனும் சேதம் ஏற்பட்டாலோ அல்லது தரவை இழந்தாலோ, அதற்கு நீங்கள்தான் பொறுப்பாவீர்கள் என்பதை ஏற்கிறீர்கள்."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"அறியப்படாத பயன்பாடுகள், உங்கள் டேப்லெட்டையும் தனிப்பட்ட தரவையும் அதிகம் பாதிக்கக்கூடும். இந்தப் பயன்பாட்டை நிறுவுவதால், அவற்றைப் பயன்படுத்தும் போது உங்கள் டேப்லெட்டுக்கு ஏதேனும் சேதம் ஏற்பட்டாலோ அல்லது தரவை இழந்தாலோ, அதற்கு நீங்கள்தான் பொறுப்பாவீர்கள் என்பதை ஏற்கிறீர்கள்."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"அறியப்படாத பயன்பாடுகள், உங்கள் டிவியையும் தனிப்பட்ட தரவையும் அதிகம் பாதிக்கக்கூடும். இந்தப் பயன்பாட்டை நிறுவுவதால், அவற்றைப் பயன்படுத்தும் போது உங்கள் டிவிக்கு ஏதேனும் சேதம் ஏற்பட்டாலோ அல்லது தரவை இழந்தாலோ, அதற்கு நீங்கள்தான் பொறுப்பாவீர்கள் என்பதை ஏற்கிறீர்கள்."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"தொடர்க"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"அமைப்புகள்"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"வியர் ஆப்ஸை நிறுவுதல்/நிறுவல் நீக்குதல்"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-te-television/strings.xml b/packages/PackageInstaller/res/values-te-television/strings.xml
new file mode 100644
index 0000000..51526b7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-te-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"నిరాకరిస్తున్నాను, మళ్లీ అడగవద్దు"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"మీరు దీన్ని తర్వాత సెట్టింగ్‌లు &gt; అనువర్తనాల్లో మార్చవచ్చు"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"సిస్టమ్ అనువర్తనాలను చూపు"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"యాప్ అనుమతులు"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"యాప్ అనుమతులు"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> అనుమతులు"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"అదనపు అనుమతులు"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> అనుమతులు"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-te-watch/strings.xml b/packages/PackageInstaller/res/values-te-watch/strings.xml
new file mode 100644
index 0000000..d97e970
--- /dev/null
+++ b/packages/PackageInstaller/res/values-te-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"నిరాకరిస్తున్నాను,ఇక అడగవద్దు"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"సిస్టమ్ అనువర్తనాలను చూపు"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"మార్చడం సాధ్యపడదు"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"అవును"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"రద్దు చేయి"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml
new file mode 100644
index 0000000..b612385
--- /dev/null
+++ b/packages/PackageInstaller/res/values-te/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"ప్యాకేజీ ఇన్‌స్టాలర్"</string>
+    <string name="next" msgid="3057143178373252333">"తర్వాత"</string>
+    <string name="install" msgid="5896438203900042068">"ఇన్‌స్టాల్ చేయండి"</string>
+    <string name="done" msgid="3889387558374211719">"పూర్తయింది"</string>
+    <string name="cancel" msgid="8360346460165114585">"రద్దు చేయి"</string>
+    <string name="installing" msgid="8613631001631998372">"ఇన్‌స్టాల్ చేస్తోంది…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ని ఇన్‌స్టాల్ చేస్తోంది…"</string>
+    <string name="install_done" msgid="3682715442154357097">"యాప్ ఇన్‌స్టాల్ చేయబడింది."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"మీరు ఈ అనువర్తనాన్ని ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా? ఇది వీటికి ప్రాప్యతను పొందుతుంది:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"మీరు ఈ యాప్‌ను ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా? దీనికి ఎటువంటి ప్రత్యేక యాక్సెస్ అవసరం లేదు."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"మీరు ఈ ప్రస్తుత యాప్‌నకు అప్‌డేట్‌ను ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా? మీ ప్రస్తుత డేటాను కోల్పోవడం సంభవించదు. అప్‌డేట్ చేసిన యాప్ వీటికి యాక్సెస్‌ను పొందుతుంది:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"మీరు ఈ అంతర్నిర్మిత యాప్‌నకు అప్‌డేట్‌ను ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా? మీ ప్రస్తుత డేటాను కోల్పోవడం సంభవించదు. అప్‌డేట్ చేసిన యాప్ వీటికి యాక్సెస్  పొందుతుంది:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"మీరు ఈ ప్రస్తుత యాప్‌కు అప్‌డేట్‌ను ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా? మీ ప్రస్తుత డేటాను కోల్పోవడం సంభవించదు. దీనికి ఎటువంటి ప్రత్యేక యాక్సెస్ అవసరం లేదు."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"మీరు ఈ అంతర్నిర్మిత యాప్‌కు అప్‌డేట్‌ను ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా? మీ ప్రస్తుత డేటాను కోల్పోవడం సంభవించదు. దీనికి ఎటువంటి ప్రత్యేక యాక్సెస్ అవసరం లేదు."</string>
+    <string name="install_failed" msgid="6579998651498970899">"యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"ప్యాకేజీ ఇన్‌స్టాల్ కాకుండా బ్లాక్ చేయబడింది."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"ప్యాకేజీ ఇప్పటికే ఉన్న ప్యాకేజీకి వైరుధ్యంగా ఉన్నందున యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"యాప్ మీ టాబ్లెట్‌కు అనుకూలంగా లేని కారణంగా ఇన్‌స్టాల్ చేయబడలేదు."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"ఈ యాప్ మీ టీవీకి అనుకూలంగా లేదు."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"యాప్ మీ ఫోన్‌కు అనుకూలంగా లేని కారణంగా ఇన్‌స్టాల్ చేయబడలేదు."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"ప్యాకేజీ చెల్లుబాటు కాని విధంగా ఉన్నందున యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g>ను మీ టాబ్లెట్‌లో ఇన్‌స్టాల్ చేయడం సాధ్యపడలేదు."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g>ని మీ టీవీలో ఇన్‌స్టాల్ చేయడం సాధ్యపడలేదు."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g>ను మీ ఫోన్‌లో ఇన్‌స్టాల్ చేయడం సాధ్యపడలేదు."</string>
+    <string name="launch" msgid="4826921505917605463">"తెరవండి"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"మీ నిర్వాహకులు తెలియని మూలాల నుండి పొందిన అనువర్తనాల ఇన్‌స్టాలేషన్‌ను అనుమతించరు"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"తెలియని అనువర్తనాలను ఈ వినియోగదారు ఇన్‌స్టాల్ చేయలేరు"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"యాప్‌లను ఇన్‌స్టాల్ చేయడానికి ఈ వినియోగదారుకు అనుమతి లేదు"</string>
+    <string name="ok" msgid="3468756155452870475">"సరే"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"అనువర్తనాలను నిర్వహించండి"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"ఖాళీ లేదు"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g>ని ఇన్‌స్టాల్ చేయడం సాధ్యపడలేదు. కొంత స్థలాన్ని ఖాళీ చేసి మళ్లీ ప్రయత్నించండి."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"యాప్ కనుగొనబడలేదు"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ఇన్‌స్టాల్ చేసిన యాప్‌ల జాబితాలో యాప్‌ కనుగొనబడలేదు."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"అనుమతించబడలేదు"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"ప్రస్తుత వినియోగదారు ఈ అన్ఇన్‌స్టాలేషన్ చేసేందుకు అనుమతి లేదు."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"ఎర్రర్"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"అనువర్తనాన్ని అన్ఇన్‌స్టాల్ చేయడం సాధ్యపడదు."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"యాప్‌ను అన్‌ఇన్‌స్టాల్ చేయండి"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"నవీకరణను అన్‌ఇన్‌స్టాల్ చేయండి"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> అనేది క్రింది యాప్‌లో ఒక భాగం:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"మీరు ఈ యాప్‌ను అన్‌ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"మీరు ఈ యాప్‌ను "<b>"మొత్తం"</b>" వినియోగదారులకు అన్‌ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా? యాప్ మరియు దీని డేటా డివైజ్‌లోని "<b>"మొత్తం"</b>" వినియోగదారుల నుండి తీసివేయబడుతుంది."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"మీరు వినియోగదారు <xliff:g id="USERNAME">%1$s</xliff:g> కోసం ఈ అనువర్తనాన్ని అన్‌ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"ఈ అనువర్తనాన్ని ఫ్యాక్టరీ సంస్కరణతో భర్తీ చేయాలా? మొత్తం డేటా తీసివేయబడుతుంది."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"ఈ అనువర్తనాన్ని ఫ్యాక్టరీ సంస్కరణతో భర్తీ చేయాలా? మొత్తం డేటా తీసివేయబడుతుంది. దీని ప్రభావం కార్యాలయ ప్రొఫైల్‌లు కలిగి ఉన్నవారితో సహా ఈ పరికర వినియోగదారులందరిపై ఉంటుంది."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"అమల్లో ఉన్న అన్‌ఇన్‌స్టాల్‌లు"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"విఫలమైన అన్‌ఇన్‌స్టాల్‌లు"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"అన్‌ఇన్‌స్టాల్ చేస్తోంది…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ని అన్ఇన్‌స్టాల్ చేస్తోంది…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"అన్‌ఇన్‌స్టాల్ చేయడం ముగిసింది."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"అన్ఇన్‌స్టాల్ చేసిన <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"అన్‌ఇన్‌స్టాల్ చేయడం విజయవంతం కాలేదు."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> అన్ఇన్‌స్టాల్ చేయడంలో విఫలమైంది."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"సక్రియ పరికర నిర్వాహక అనువర్తనాన్ని అన్ఇన్‌స్టాల్ చేయడం సాధ్యపడదు"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> కోసం సక్రియ పరికర నిర్వాహక అనువర్తనాన్ని అన్ఇన్‌స్టాల్ చేయడం సాధ్యపడదు"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"ఈ యాప్ కొందరు వినియోగదారులకు లేదా కొన్ని ప్రొఫైల్‌లకు అవసరం, ఇతరులకు అన్‌ఇన్‌స్టాల్ చేయబడింది"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"మీ ప్రొఫైల్ కోసం ఈ యాప్ అవసరం మరియు దీన్ని అన్ఇన్‌స్టాల్ చేయలేరు."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"మీ డివైజ్ నిర్వాహకుడికి ఈ యాప్ అవసరం, అందువల్ల దీన్ని అన్‌ఇన్‌స్టాల్ చేయడం కుదరదు."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"పరికర నిర్వాహక అనువర్తనాలను నిర్వహించు"</string>
+    <string name="manage_users" msgid="3125018886835668847">"వినియోగదారులను నిర్వహించు"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g>ని అన్‌ఇన్‌స్టాల్ చేయడం సాధ్యపడలేదు."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"ప్యాకేజీని అన్వయించడంలో సమస్య ఏర్పడింది."</string>
+    <string name="newPerms" msgid="6039428254474104210">"కొత్తవి"</string>
+    <string name="allPerms" msgid="1024385515840703981">"అన్నీ"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"గోప్యత"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"పరికరం యాక్సెస్"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"ఈ నవీకరణకు కొత్త అనుమతులు అవసరం లేదు."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"తిరస్కరించు"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"మరింత సమాచారం"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"ఏదేమైనా నిరాకరించు"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>లో <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని <xliff:g id="ACTION">%2$s</xliff:g> అనుమతించాలా?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"<xliff:g id="ACTION">%2$s</xliff:g> చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను ఎల్లప్పుడూ అనుమతించాలా?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"యాప్‌ను ఉపయోగిస్తున్నప్పుడు మాత్రమే"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ఎల్లప్పుడూ"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"నిరాకరించు, మళ్లీ అడగవద్దు"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> నిలిపివేయబడ్డాయి"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"అన్నీ నిలిపివేయబడ్డాయి"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ఏవీ నిలిపివేయబడలేదు"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"అనుమతించు"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"యాప్‌లు"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"యాప్ అనుమతులు"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"మళ్లీ అడగవద్దు"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"అనుమతులు లేవు"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"అదనపు అనుమతులు"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"యాప్ సమాచారాన్ని తెరుస్తుంది"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"ఈ యాప్ పాత Android వెర్షన్ కోసం రూపొందించబడింది. అనుమతిని నిరాకరించినట్లయితే ఇది ఇకపై ఉద్దేశించిన రీతిలో పని చేయకపోవచ్చు."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"తెలియని చర్యను చేస్తుంది"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g>లో <xliff:g id="COUNT_0">%1$d</xliff:g> యాప్‌లు అనుమతించబడ్డాయి"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"సిస్టమ్‌ను చూపు"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"సిస్టమ్‌ను దాచు"</string>
+    <string name="no_apps" msgid="1965493419005012569">"అనువర్తనాలు లేవు"</string>
+    <string name="location_settings" msgid="1774875730854491297">"స్థాన సెట్టింగ్‌లు"</string>
+    <string name="location_warning" msgid="8778701356292735971">"ఈ పరికరం కోసం స్థాన సేవల ప్రదాత <xliff:g id="APP_NAME">%1$s</xliff:g>. స్థాన సెట్టింగ్‌ల నుండి స్థాన ప్రాప్యతను సవరించవచ్చు."</string>
+    <string name="system_warning" msgid="7103819124542305179">"మీరు ఈ అనుమతిని నిరాకరిస్తే, మీ పరికర ప్రాథమిక లక్షణాలు ఇకపై ఉద్దేశించిన రీతిలో పని చేయకపోవచ్చు."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"విధానం ద్వారా అమలు చేయబడింది"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"విధానం ద్వారా నేపథ్య యాక్సెస్ నిలిపివేయబడింది"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"విధానం ద్వారా నేపథ్య యాక్సెస్ ప్రారంభించబడింది"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"విధానం ద్వారా ముందుభాగం యాక్సెస్ ప్రారంభించబడింది"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"నిర్వాహకుల నియంత్రణలో ఉంటాయి"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ఎల్లప్పుడూ"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"యాప్‌ను ఉపయోగిస్తున్నప్పుడు మాత్రమే"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"ఎన్నడూ వద్దు"</string>
+    <string name="loading" msgid="7811651799620593731">"లోడ్ అవుతోంది..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"అన్ని అనుమతులు"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"ఇతర అనువర్తన సామర్థ్యాలు"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"అనుమతి అభ్యర్థన"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"స్క్రీన్ అతివ్యాప్తి గుర్తించబడింది"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ఈ అనుమతి సెట్టింగ్‌ను మార్చడానికి, మీరు ముందుగా సెట్టింగ్‌లు &gt; అనువర్తనాల నుండి స్క్రీన్ అతివ్యాప్తిని ఆఫ్ చేయాలి"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"సెట్టింగ్‌లను తెరువు"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android వేర్"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wearలో ఇన్‌స్టాల్/అన్ఇన్‌స్టాల్ చర్యలకు మద్దతు లేదు."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; యాక్సెస్ చేయడానికి అనుమతించాల్సిన వాటిని ఎంచుకోండి"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; అప్‌డేట్ చేయబడింది. ఈ యాప్ యాక్సెస్ చేయడానికి అనుమతించాల్సిన వాటిని ఎంచుకోండి."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"రద్దు చేయి"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"కొనసాగించు"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"కొత్త అనుమతులు"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"ప్రస్తుత అనుమతులు"</string>
+    <string name="message_staging" msgid="6151794817691100003">"అనువర్తనాన్ని అందిస్తోంది…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"తెలియదు"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"మీకు భద్రతను అందించడం కోసం, ఈ మూలం నుండి తెలియని యాప్‌లను ఇన్‌స్టాల్ చేయడానికి మీ టాబ్లెట్ అనుమతించబడదు."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"మీకు భద్రతను అందించడం కోసం, ఈ మూలం నుండి తెలియని యాప్‌లను ఇన్‌స్టాల్ చేయడానికి మీ TV అనుమతించబడదు."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"మీకు భద్రతను అందించడం కోసం, ఈ మూలం నుండి తెలియని యాప్‌లను ఇన్‌స్టాల్ చేయడానికి మీ ఫోన్ అనుమతించబడదు."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"మీ ఫోన్ మరియు వ్యక్తిగత డేటా తెలియని మూలాల్లోని అనువర్తనాల ద్వారా దాడికి గురి కావడానికి ఎక్కువ అవకాశం ఉంటుంది. ఈ అనువర్తనాన్ని ఇన్‌స్టాల్ చేయడం ద్వారా, ఈ అనువర్తనాన్ని ఉపయోగించడం వలన మీ ఫోన్‌కు సంభవించే ఏదైనా నష్టానికి లేదా కోల్పోయే డేటాకి బాధ్యత వహించడానికి మీరు అంగీకరిస్తున్నారు."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"మీ టాబ్లెట్ మరియు వ్యక్తిగత డేటా తెలియని మూలాల్లోని అనువర్తనాల ద్వారా దాడికి గురి కావడానికి ఎక్కువ అవకాశం ఉంటుంది. ఈ అనువర్తనాన్ని ఇన్‌స్టాల్ చేయడం ద్వారా, ఈ అనువర్తనాన్ని ఉపయోగించడం ద్వారా మీ టాబ్లెట్‌కు సంభవించే ఏదైనా నష్టానికి లేదా కోల్పోయే డేటాకి బాధ్యత వహించడానికి మీరు అంగీకరిస్తున్నారు."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"మీ TV మరియు వ్యక్తిగత డేటా తెలియని మూలాల్లోని అనువర్తనాల ద్వారా దాడికి గురి కావడానికి ఎక్కువ అవకాశం ఉంటుంది. ఈ అనువర్తనాన్ని ఇన్‌స్టాల్ చేయడం ద్వారా, ఈ అనువర్తనాన్ని ఉపయోగించడం ద్వారా మీ TVకి సంభవించే ఏదైనా నష్టానికి లేదా కోల్పోయే డేటాకి బాధ్యత వహించడానికి మీరు అంగీకరిస్తున్నారు."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"కొనసాగించు"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"సెట్టింగ్‌లు"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"వేర్ ఆప్‌లను ఇన్‌స్టాల్/అన్‌ఇన్‌స్టాల్ చేస్తోంది"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-television/colors.xml b/packages/PackageInstaller/res/values-television/colors.xml
new file mode 100644
index 0000000..1cacc00
--- /dev/null
+++ b/packages/PackageInstaller/res/values-television/colors.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+
+    <color name="lb_content_title_text_color">#FFF1F1F1</color>
+    <color name="lb_content_breadcrumb_text_color">#88F1F1F1</color>
+    <color name="lb_content_description_text_color">#88F1F1F1</color>
+    <color name="lb_action_fragment_background">#FF111111</color>
+    <color name="lb_dialog_activity_background">#77000000</color>
+
+    <color name="lb_header_banner_color">#1f292d</color>
+
+    <color name="off_white">#ffeeeeee</color>
+</resources>
diff --git a/packages/PackageInstaller/res/values-television/dimens.xml b/packages/PackageInstaller/res/values-television/dimens.xml
new file mode 100644
index 0000000..d1c232e
--- /dev/null
+++ b/packages/PackageInstaller/res/values-television/dimens.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <dimen name="action_dialog_z">16dp</dimen>
+    <dimen name="action_dialog_padding_left">52dp</dimen>
+    <dimen name="action_dialog_padding_right">40dp</dimen>
+    <dimen name="action_dialog_padding_top">41dp</dimen>
+    <dimen name="action_dialog_padding_bottom">27dp</dimen>
+
+    <dimen name="action_dialog_content_margin_left">24dp</dimen>
+    <dimen name="action_dialog_content_margin_right">32dp</dimen>
+
+    <dimen name="action_dialog_actions_width">304dp</dimen>
+    <dimen name="action_dialog_actions_margin_left">24dp</dimen>
+    <dimen name="action_dialog_actions_margin_top">18dp</dimen>
+
+    <dimen name="action_dialog_button_padding_left">16dp</dimen>
+    <dimen name="action_dialog_button_padding_right">16dp</dimen>
+    <dimen name="action_dialog_button_padding_top">14dp</dimen>
+    <dimen name="action_dialog_button_padding_bottom">15dp</dimen>
+    <dimen name="action_dialog_button_min_height">48dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-th-television/strings.xml b/packages/PackageInstaller/res/values-th-television/strings.xml
new file mode 100644
index 0000000..042a6f1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-th-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"ปฏิเสธและไม่ต้องถามอีก"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"คุณสามารถเปลี่ยนได้ภายหลังในการตั้งค่า &gt; แอป"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"แสดงแอประบบ"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"สิทธิ์ของแอป"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"สิทธิ์ของแอป"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"สิทธิ์เข้าถึง \"<xliff:g id="PERMISSION">%1$s</xliff:g>\""</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"สิทธิ์เพิ่มเติม"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"สิทธิ์เข้าถึง \"<xliff:g id="PERMISSION">%1$s</xliff:g>\""</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-th-watch/strings.xml b/packages/PackageInstaller/res/values-th-watch/strings.xml
new file mode 100644
index 0000000..05af1e8
--- /dev/null
+++ b/packages/PackageInstaller/res/values-th-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"ปฏิเสธ ไม่ต้องถามอีก"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"แสดงแอประบบ"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ไม่สามารถเปลี่ยน"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"ใช่"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"ยกเลิก"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-th/strings.xml b/packages/PackageInstaller/res/values-th/strings.xml
new file mode 100644
index 0000000..b7735a7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-th/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"โปรแกรมติดตั้งแพ็กเกจ"</string>
+    <string name="next" msgid="3057143178373252333">"ถัดไป"</string>
+    <string name="install" msgid="5896438203900042068">"ติดตั้ง"</string>
+    <string name="done" msgid="3889387558374211719">"เสร็จสิ้น"</string>
+    <string name="cancel" msgid="8360346460165114585">"ยกเลิก"</string>
+    <string name="installing" msgid="8613631001631998372">"กำลังติดตั้ง..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"กำลังติดตั้ง <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"ติดตั้งแอปพลิเคชันแล้ว"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"คุณต้องการติดตั้งแอปพลิเคชันนี้หรือไม่ แอปพลิเคชันจะเข้าถึง:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"คุณต้องการจะติดตั้งแอปพลิเคชันนี้หรือไม่ แอปพลิเคชันไม่ต้องมีการเข้าถึงพิเศษใดๆ"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"คุณต้องการติดตั้งการอัปเดตของแอปพลิเคชันที่มีอยู่นี้หรือไม่ ข้อมูลที่มีอยู่ของคุณจะไม่สูญหายไป แอปพลิเคชันที่อัปเดตแล้วจะเข้าถึง:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"คุณต้องการจะติดตั้งการอัปเดตของแอปพลิเคชันในระบบนี้หรือไม่ ข้อมูลที่มีอยู่ของคุณจะไม่สูญหาย แอปพลิเคชันที่อัปเดตแล้วจะเข้าถึง:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"คุณต้องการติดตั้งการอัปเดตไปยังแอปพลิเคชันที่มีอยู่นี้หรือไม่ ข้อมูลที่มีอยู่ของคุณจะไม่สูญหาย การอัปเดตนี้ไม่จำเป็นต้องใช้การเข้าถึงใดๆ เป็นพิเศษ"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"คุณต้องการติดตั้งการอัปเดตไปยังแอปพลิเคชันในตัวนี้หรือไม่ ข้อมูลที่มีอยู่ของคุณจะไม่สูญหาย การอัปเดตนี้ไม่จำเป็นต้องใช้การเข้าถึงใดๆ เป็นพิเศษ"</string>
+    <string name="install_failed" msgid="6579998651498970899">"ไม่ได้ติดตั้งแอปพลิเคชัน"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"มีการบล็อกแพ็กเกจไม่ให้ติดตั้ง"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"ไม่ได้ติดตั้งแอปเพราะแพ็กเกจขัดแย้งกับแพ็กเกจที่มีอยู่"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"ไม่ได้ติดตั้งแอปเพราะแอปใช้งานไม่ได้กับแท็บเล็ตของคุณ"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"แอปนี้ไม่สามารถใช้งานกับทีวีของคุณ"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"ไม่ได้ติดตั้งแอปเพราะแอปใช้งานไม่ได้กับโทรศัพท์ของคุณ"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"ไม่ได้ติดตั้งแอปเพราะดูเหมือนว่าแพ็กเกจจะไม่ถูกต้อง"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"ไม่สามารถติดตั้ง <xliff:g id="APP_NAME">%1$s</xliff:g> บนแท็บเล็ตของคุณ"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่สามารถติดตั้งบนทีวีได้"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"ไม่สามารถติดตั้ง <xliff:g id="APP_NAME">%1$s</xliff:g> บนโทรศัพท์ของคุณ"</string>
+    <string name="launch" msgid="4826921505917605463">"เปิด"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"ผู้ดูแลระบบของคุณไม่อนุญาตให้ติดตั้งแอปที่ได้มาจากแหล่งที่มาที่ไม่รู้จัก"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"ผู้ใช้รายนี้ไม่สามารถติดตั้งแอปที่ไม่รู้จัก"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"ผู้ใช้รายนี้ไม่ได้รับอนุญาตให้ติดตั้งแอป"</string>
+    <string name="ok" msgid="3468756155452870475">"ตกลง"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"จัดการแอปพลิเคชัน"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"ไม่มีพื้นที่"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"ติดตั้ง <xliff:g id="APP_NAME">%1$s</xliff:g> ไม่ได้ เพิ่มพื้นที่ว่างแล้วลองอีกครั้ง"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"ไม่พบแอปพลิเคชัน"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ไม่พบแอปพลิเคชันนี้ในรายการแอปพลิเคชันที่ติดตั้งไว้"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"ไม่ได้รับอนุญาต"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"ผู้ใช้ปัจจุบันไม่ได้รับอนุญาตให้ทำการถอนการติดตั้งนี้"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"พบข้อผิดพลาด"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"ไม่สามารถถอนการติดตั้งแอป"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"ถอนการติดตั้งแอปพลิเคชัน"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"ถอนการติดตั้งการอัปเดต"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> เป็นส่วนหนึ่งของแอปพลิเคชันต่อไปนี้:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"คุณต้องการถอนการติดตั้งแอปพลิเคชันนี้หรือไม่"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"คุณต้องการถอนการติดตั้งแอปพลิเคชันนี้สำหรับผู้ใช้"<b>"ทั้งหมด"</b>"หรือไม่ แอปพลิเคชันนี้และข้อมูลในแอปพลิเคชันจะถูกลบจากผู้ใช้"<b>"ทั้งหมด"</b>"ในอุปกรณ์"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"คุณต้องการถอนการติดตั้งแอปนี้สำหรับผู้ใช้ <xliff:g id="USERNAME">%1$s</xliff:g> ไหม"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"แทนที่แอปนี้ด้วยเวอร์ชันเริ่มต้นไหม ระบบจะนำข้อมูลทั้งหมดออก"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"แทนที่แอปนี้ด้วยเวอร์ชันเริ่มต้นไหม ระบบจะนำข้อมูลทั้งหมดออก วิธีนี้ส่งผลต่อผู้ใช้ทุกคนที่ใช้อุปกรณ์เครื่องนี้ รวมทั้งผู้ที่มีโปรไฟล์งาน"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"กำลังเรียกใช้การถอนการติดตั้ง"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"การถอนการติดตั้งที่ล้มเหลว"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"กำลังถอนการติดตั้ง..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"กำลังถอนการติดตั้ง <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"ถอนการติดตั้งเสร็จแล้ว"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"ถอนการติดตั้ง <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> แล้ว"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"ถอนการติดตั้งไม่สำเร็จ"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"การถอนการติดตั้ง <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ไม่สำเร็จ"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"ไม่สามารถถอนการติดตั้งแอปผู้ดูแลระบบอุปกรณ์ที่มีการใช้งาน"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"ไม่สามารถถอนการติดตั้งแอปผู้ดูแลระบบอุปกรณ์ที่มีการใช้งานสำหรับ <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"แอปนี้จำเป็นสำหรับผู้ใช้หรือโปรไฟล์บางส่วน และถอนการติดตั้งไปแล้วสำหรับส่วนอื่น"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"แอปนี้จำเป็นสำหรับโปรไฟล์ของคุณและไม่สามารถถอนการติดตั้งได้"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"ผู้ดูแลระบบอุปกรณ์กำหนดให้ใช้แอปนี้ และไม่สามารถถอนการติดตั้งได้"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"จัดการแอปผู้ดูแลระบบอุปกรณ์"</string>
+    <string name="manage_users" msgid="3125018886835668847">"จัดการผู้ใช้"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"ไม่สามารถถอดการติดตั้ง <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"พบปัญหาในการแยกวิเคราะห์แพ็กเกจ"</string>
+    <string name="newPerms" msgid="6039428254474104210">"ใหม่"</string>
+    <string name="allPerms" msgid="1024385515840703981">"ทั้งหมด"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"ข้อมูลส่วนบุคคล"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"การเข้าถึงอุปกรณ์"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"การอัปเดตนี้ไม่จำเป็นต้องมีการอนุญาตใหม่"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"ปฏิเสธ"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"ข้อมูลเพิ่มเติม"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"ยืนยันการปฏิเสธ"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> จาก <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> รายการ"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>ไหม"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>ทุกครั้งใช่ไหม"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"ขณะใช้แอปเท่านั้น"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ตลอดเวลา"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"ปฏิเสธและไม่ต้องถามอีก"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"ปิดใช้ <xliff:g id="COUNT">%1$d</xliff:g> สิทธิ์"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"ปิดใช้สิทธิ์ทั้งหมด"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"ไม่มีการปิดใช้สิทธิ์"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"อนุญาต"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"แอป"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"สิทธิ์ของแอป"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"ไม่ต้องถามอีก"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"ไม่มีสิทธิ์"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"สิทธิ์เพิ่มเติม"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"เปิดข้อมูลแอป"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"แอปนี้ออกแบบมาเพื่อ Android เวอร์ชันเก่า การปฏิเสธสิทธิ์อาจทำให้แอปไม่ทำงานตามที่ต้องการอีกต่อไป"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ดำเนินการทำงานที่ไม่รู้จัก"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"อนุญาตแล้ว <xliff:g id="COUNT_0">%1$d</xliff:g> จาก <xliff:g id="COUNT_1">%2$d</xliff:g> แอป"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"แสดงระบบ"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"ซ่อนระบบ"</string>
+    <string name="no_apps" msgid="1965493419005012569">"ไม่มีแอป"</string>
+    <string name="location_settings" msgid="1774875730854491297">"การตั้งค่าตำแหน่ง"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นผู้ให้บริการตำแหน่งสำหรับอุปกรณ์นี้ คุณสามารถแก้ไขสิทธิ์เข้าถึงตำแหน่งได้จากการตั้งค่าตำแหน่ง"</string>
+    <string name="system_warning" msgid="7103819124542305179">"หากคุณปฏิเสธสิทธิ์นี้ ฟีเจอร์พื้นฐานของอุปกรณ์อาจไม่ทำงานตามที่ควรจะเป็นอีกต่อไป"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"บังคับใช้โดยนโยบาย"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"ปิดใช้การเข้าถึงในเบื้องหลังโดยนโยบาย"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"เปิดใช้การเข้าถึงในเบื้องหลังโดยนโยบาย"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"เปิดใช้การเข้าถึงในเบื้องหน้าโดยนโยบาย"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"ผู้ดูแลระบบเป็นผู้ควบคุม"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ตลอดเวลา"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"ขณะใช้แอปเท่านั้น"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"ไม่เลย"</string>
+    <string name="loading" msgid="7811651799620593731">"กำลังโหลด…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"สิทธิ์ทั้งหมด"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"ความสามารถอื่นๆ ของแอป"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"คำขอสิทธิ์"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"ตรวจพบการวางซ้อนหน้าจอ"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"ในการเปลี่ยนแปลงการตั้งค่าสิทธิ์นี้ ก่อนอื่น คุณต้องปิดการวางซ้อนหน้าจอที่การตั้งค่า &gt; แอป"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"เปิดการตั้งค่า"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"ไม่สามารถติดตั้ง/ถอนการติดตั้งบน Wear"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"โปรดเลือกข้อมูลที่อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึง"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"อัปเดต &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; แล้ว โปรดเลือกข้อมูลที่อนุญาตให้แอปนี้เข้าถึง"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"ยกเลิก"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"ต่อไป"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"สิทธิ์ใหม่"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"สิทธิ์ปัจจุบัน"</string>
+    <string name="message_staging" msgid="6151794817691100003">"กำลังปรับสภาพแวดล้อมของแอป…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"ไม่ทราบ"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"เพื่อความปลอดภัย ไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในแท็บเล็ต"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"เพื่อความปลอดภัย ไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในทีวี"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"เพื่อความปลอดภัย ไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในโทรศัพท์"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"โทรศัพท์และข้อมูลส่วนบุคคลของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้เป็นการยอมรับว่าคุณจะรับผิดชอบความเสียหายต่อเครื่องโทรศัพท์หรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"แท็บเล็ตและข้อมูลส่วนบุคคลของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้เป็นการยอมรับว่าคุณจะรับผิดชอบความเสียหายต่อเครื่องแท็บเล็ตหรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"ทีวีและข้อมูลส่วนบุคคลของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้เป็นการยอมรับว่าคุณจะรับผิดชอบความเสียหายต่อเครื่องทีวีหรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"ต่อไป"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"การตั้งค่า"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"กำลังติดตั้ง/ถอนการติดตั้งแอป Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-tl-television/strings.xml b/packages/PackageInstaller/res/values-tl-television/strings.xml
new file mode 100644
index 0000000..df5b98f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-tl-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Tanggihan at huwag nang tatanunging muli"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Mababago mo ito sa ibang pagkakataon sa Mga Setting &gt; Mga App"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Ipakita ang mga app ng system"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Mga pahintulot sa app"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Mga pahintulot sa app"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Mga pahintulot sa <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Mga karagdagang pahintulot"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Mga pahintulot sa <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-tl-watch/strings.xml b/packages/PackageInstaller/res/values-tl-watch/strings.xml
new file mode 100644
index 0000000..8597451
--- /dev/null
+++ b/packages/PackageInstaller/res/values-tl-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Tanggihan, huwag nang tatanunging muli"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Ipakita ang mga app ng system"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Hindi mababago"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Oo"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Kanselahin"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-tl/strings.xml b/packages/PackageInstaller/res/values-tl/strings.xml
new file mode 100644
index 0000000..05eba98
--- /dev/null
+++ b/packages/PackageInstaller/res/values-tl/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Installer ng package"</string>
+    <string name="next" msgid="3057143178373252333">"Susunod"</string>
+    <string name="install" msgid="5896438203900042068">"Mag-install"</string>
+    <string name="done" msgid="3889387558374211719">"Tapos na"</string>
+    <string name="cancel" msgid="8360346460165114585">"Kanselahin"</string>
+    <string name="installing" msgid="8613631001631998372">"Nag-i-install…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Ini-install ang <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Na-install ang app."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Nais mo bang i-install ang application na ito? Magkakaroon ito ng access sa:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Nais mo bang i-install ang application na ito? Hindi ito nangangailangan ng anumang espesyal na access."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Nais mo bang mag-install ng update sa umiiral nang application na ito? Hindi mawawala ang iyong umiiral nang data. Magkakaroon ng access ang na-update na application sa:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Nais mo bang mag-install ng update sa built-in na application na ito? Hindi mawawala ang iyong umiiral na data. Magkakaroon ng access ang na-update na application sa:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Nais mo bang mag-install ng update sa umiiral na application na ito? Hindi mawawala ang iyong umiiral na data. Hindi ito nangangailangan ng anumang espesyal na access."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Nais mo bang mag-install ng update sa built-in na application na ito? Hindi mawawala ang iyong umiiral na data. Hindi ito nangangailangan ng anumang espesyal na access."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Hindi na-install ang app."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Na-block ang pag-install sa package."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Hindi na-install ang app dahil nagkakaproblema ang package sa isang dati nang package."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Hindi na-install ang app dahil hindi tugma ang app sa iyong tablet."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Hindi compatible ang app na ito sa iyong TV."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Hindi na-install ang app dahil hindi tugma ang app sa iyong telepono."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Hindi na-install ang app dahil lumalabas na di-wasto ang package."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Hindi ma-install ang <xliff:g id="APP_NAME">%1$s</xliff:g> sa iyong tablet."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay hindi ma-install sa iyong TV."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Hindi ma-install ang <xliff:g id="APP_NAME">%1$s</xliff:g> sa iyong telepono."</string>
+    <string name="launch" msgid="4826921505917605463">"Buksan"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Hindi pinapayagan ng iyong admin ang pag-install ng mga app na nakuha mula sa mga hindi kilalang pinagmulan"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Hindi maaaring mag-install ang user na ito ng mga hindi kilalang app"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Hindi pinapayagan ang user na mag-install ng mga app"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Pamahalaan ang apps"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Wala ng espasyo"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Hindi ma-install ang <xliff:g id="APP_NAME">%1$s</xliff:g>. Magbakante ng ilang espasyo at subukang muli."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Hindi makita ang app"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Hindi makita ang app sa listahan ng naka-install na apps."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Hindi pinapayagan"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Hindi pinapayagan ang kasalukuyang user na gawin ang pag-uninstall na ito."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Error"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Hindi ma-uninstall ang app."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"I-uninstall ang app"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"I-uninstall ang update"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"Bahagi ang <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ng sumusunod na app:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Gusto mo bang i-uninstall ang app na ito?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Nais mo bang i-uninstall ang app na ito para sa "<b>"lahat"</b>" ng user? Aalisin ang application at ang data nito mula sa "<b>"lahat"</b>" ng user sa device."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Gusto mo bang i-uninstall ang app na ito para sa user na si <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Gusto mo bang palitan ang app na ito ng factory na bersyon? Maaalis ang lahat ng data."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Gusto mo bang palitan ang app na ito ng factory na bersyon? Maaalis ang lahat ng data. Nakakaapekto ito sa lahat ng user ng device na ito, kasama ang mga may profile sa trabaho."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Mga nasa proseso ng pag-uninstall"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Mga hindi na-uninstall"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Ina-uninstall…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Ina-uninstall ang <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Natapos ang pag-uninstall."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Na-uninstall ang <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Di-matagumpay ang pag-uninstall."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Hindi na-uninstall ang <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Hindi ma-uninstall ang aktibong app ng admin ng device"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Hindi ma-uninstall ang aktibong app ng admin ng device para kay  <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Ang app na ito ay kailangan ng ilang user o profile at na-uninstall na ito sa iba pa"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ang app na ito ay kailangan para sa iyong profile at hindi maaaring i-uninstall."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Kinakailangan app na ito ng administrator ng device mo at di maaari i-uninstall."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Pamahalaan ang mga app ng admin ng device"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Pamahalaan ang mga user"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Hindi ma-install ang <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Nagkaroon ng problema sa pag-parse sa package."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Bago"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Lahat"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Privacy"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Access sa Device"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Walang kinakailangang mga bagong pagpapahintulot ang update na ito."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Tanggihan"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Higit pang impormasyon"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Tanggihan pa rin"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> ng <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Palaging payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Habang ginagamit lang ang app"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Palagi"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Tanggihan at huwag nang itanong muli"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> ang naka-disable"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"naka-disable lahat"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"walang naka-disable"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Payagan"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Mga App"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Mga pahintulot sa app"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Huwag nang tatanunging muli"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Walang pahintulot"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Mga karagdagang pahintulot"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Buksan ang impormasyon ng app"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> pa</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> pa</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ang app na ito ay idinisenyo para sa mas lumang bersyon ng Android. Kapag tinanggihan ang pahintulot, maaaring hindi na ito gumana ayon sa inaasahan."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"gumawa ng hindi kilalang pagkilos"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Pinapayagan ang <xliff:g id="COUNT_0">%1$d</xliff:g> sa <xliff:g id="COUNT_1">%2$d</xliff:g> (na) app"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Ipakita ang system"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Itago ang system"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Walang mga app"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Mga Setting ng Lokasyon"</string>
+    <string name="location_warning" msgid="8778701356292735971">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay isang provider ng mga serbisyo sa lokasyon para sa device na ito. Mababago ang access sa lokasyon mula sa mga setting ng lokasyon."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Kung tatanggihan mo ang pahintulot na ito, maaaring hindi na gumana ang mga pangunahing feature ng iyong device gaya ng inaasahan."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Ipinapatupad sa pamamagitan ng patakaran"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Na-disable ayon sa patakaran ang pag-access sa background"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Na-enable ayon sa patakaran ang pag-access sa background"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Na-enable ayon sa patakaran ang pag-access sa foreground"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Kinokontrol ng admin"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Palagi"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Habang ginagamit lang ang app"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Huwag Kailanman"</string>
+    <string name="loading" msgid="7811651799620593731">"Naglo-load..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Lahat ng pahintulot"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Iba pang mga kakayahan ng app"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Kahilingan sa pagpapahintulot"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Natukoy ang overlay ng screen"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Upang baguhin ang setting ng pahintulot na ito, kailangan mo munang i-off ang overlay ng screen mula sa Mga Setting &gt; Mga App"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Buksan ang mga setting"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Ang mga pagkilos na I-install/I-uninstall ay hindi sinusuportahan sa Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Piliin kung ano ang papayagang i-access ng &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Na-update na ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;. Piliin kung ano ang papayagang i-access ng app na ito."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Kanselahin"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Magpatuloy"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Mga bagong pahintulot"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Mga kasalukuyang pahintulot"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Inihahanda ang app…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Hindi Alam"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Para sa iyong seguridad, hindi pinapayagan ang tablet mo na mag-install ng mga hindi alam na app mula sa pinagmulang ito."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Para sa iyong seguridad, hindi pinapayagan ang TV mo na mag-install ng mga hindi alam na app mula sa pinagmulang ito."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Para sa iyong seguridad, hindi pinapayagan ang telepono mo na mag-install ng mga hindi alam na app mula sa pinagmulang ito."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Mas nanganganib ang iyong telepono at personal na data sa mga pag-atake mula sa mga hindi kilalang app. Sa pamamagitan ng pag-install ng app na ito, sumasang-ayon ka na ikaw ang responsable sa anumang pinsala sa telepono mo o pagkawala ng data na maaaring magresulta mula sa paggamit nito."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Mas nanganganib ang iyong tablet at personal na data sa mga pag-atake mula sa mga hindi kilalang app. Sa pamamagitan ng pag-install ng app na ito, sumasang-ayon ka na ikaw ang responsable sa anumang pinsala sa tablet mo o pagkawala ng data na maaaring magresulta mula sa paggamit nito."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Mas nanganganib ang iyong TV at personal na data sa mga pag-atake mula sa mga hindi kilalang app. Sa pamamagitan ng pag-install ng app na ito, sumasang-ayon ka na ikaw ang responsable sa anumang pinsala sa TV mo o pagkawala ng data na maaaring magresulta mula sa paggamit nito."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Magpatuloy"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Mga Setting"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Ini-install/ina-uninstall ang wear apps"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-tr-television/strings.xml b/packages/PackageInstaller/res/values-tr-television/strings.xml
new file mode 100644
index 0000000..7ed0a68
--- /dev/null
+++ b/packages/PackageInstaller/res/values-tr-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Reddet ve bir daha sorma"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Bu ayarı daha sonra Ayarlar &gt; Uygulamalar\'dan değiştirebilirsiniz"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Sistem uygulamalarını göster"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Uygulama izinleri"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Uygulama izinleri"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> izinleri"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Ek izinler"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> izinleri"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-tr-watch/strings.xml b/packages/PackageInstaller/res/values-tr-watch/strings.xml
new file mode 100644
index 0000000..fbc5b93
--- /dev/null
+++ b/packages/PackageInstaller/res/values-tr-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Reddet, bir daha sorma"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Sistem uygulamalarını göster"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Değiştirilemez"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Evet"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"İptal"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-tr/strings.xml b/packages/PackageInstaller/res/values-tr/strings.xml
new file mode 100644
index 0000000..ef7882d
--- /dev/null
+++ b/packages/PackageInstaller/res/values-tr/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Paket yükleyici"</string>
+    <string name="next" msgid="3057143178373252333">"Sonraki"</string>
+    <string name="install" msgid="5896438203900042068">"Yükle"</string>
+    <string name="done" msgid="3889387558374211719">"Bitti"</string>
+    <string name="cancel" msgid="8360346460165114585">"İptal"</string>
+    <string name="installing" msgid="8613631001631998372">"Yükleniyor…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> yükleniyor…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Uygulama yüklendi."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Bu uygulamayı yüklemek istiyor musunuz? Uygulama şunlara erişebilecektir:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Bu uygulamayı yüklemek istiyor musunuz? Herhangi bir özel erişim gerektirmez."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Bu mevcut uygulamaya ait bir güncellemeyi yüklemek istiyor musunuz? Mevcut verileriniz silinmeyecektir. Güncellenen uygulama şunlara erişebilecektir:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Bu yerleşik uygulamaya ait bir güncellemeyi yüklemek istiyor musunuz? Mevcut verileriniz silinmeyecektir. Güncellenen uygulama şunlara erişebilecektir:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Bu mevcut uygulamaya ait bir güncellemeyi yüklemek istiyor musunuz? Mevcut verileriniz kaybolacaktır. Herhangi bir özel erişim gerektirmez."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Bu yerleşik uygulamaya ait bir güncellemeyi yüklemek istiyor musunuz? Mevcut verileriniz kaybolacaktır. Herhangi bir özel erişim gerektirmez."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Uygulama yüklenmedi."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Paketin yüklemesi engellendi."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Paket, mevcut bir paketle çakıştığından uygulama yüklenemedi."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Tabletinizle uyumlu olmadığından uygulama yüklenemedi."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Bu uygulama TV\'niz ile uyumlu değil."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Telefonunuzla uyumlu olmadığından uygulama yüklenemedi."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Paket geçersiz göründüğünden uygulama yüklenemedi."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu tabletinize yüklenemedi."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> TV\'nize yüklenemedi."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu telefonunuza yüklenemedi."</string>
+    <string name="launch" msgid="4826921505917605463">"Aç"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Yöneticiniz, bilinmeyen kaynaklardan edinilen uygulamaların yüklenmesine izin vermiyor"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Bilinmeyen uygulamalar bu kullanıcı tarafından yüklenemez"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Bu kullanıcının uygulama yüklemesine izin verilmiyor"</string>
+    <string name="ok" msgid="3468756155452870475">"Tamam"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Uygulamaları yönet"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Yer kalmadı"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> yüklenemedi. Boş alan açın ve yeniden deneyin."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Uygulama bulunamadı"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Uygulama, yüklü uygulamalar listesinde bulunamadı."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"İzin verilmiyor"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Geçerli kullanıcının bu yüklemeyi kaldırma izni yok."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Hata"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Uygulamanın yüklemesi kaldırılamadı."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Uygulamayı kaldır"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Güncelleme kaldırılsın mı?"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>, şu uygulamanın bir parçasıdır:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Bu uygulamanın yüklemesini kaldırmak istiyor musunuz?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Bu uygulamanın yüklemesini "<b>"tüm"</b>" kullanıcılar için kaldırmak istiyor musunuz? Uygulama ve verileri cihazdan "<b>"tüm"</b>" kullanıcılar için kaldırılacaktır."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"<xliff:g id="USERNAME">%1$s</xliff:g> adlı kullanıcı için bu uygulamanın yüklemesini kaldırmak istiyor musunuz?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Bu uygulamayı fabrika sürümüyle değiştirmek istiyor musunuz? Tüm veriler silinecektir."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Bu uygulamayı fabrika sürümüyle değiştirmek istiyor musunuz? Tüm veriler silinecektir. Bu, çalışma profilleri olan kullanıcılar da dahil olmak üzere cihazı kullanan tüm kullanıcıları etkiler."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Devam eden yükleme kaldırma işlemleri"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Başarısız yükleme kaldırma işlemleri"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Kaldırılıyor…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> uygulamasının yüklemesi kaldırılıyor…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Kaldırma işlemi tamamlandı."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> uygulamasının yüklemesi kaldırıldı"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Yükleme kaldırılamadı."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> uygulamasının yüklemesi kaldırılamadı."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Etkin cihaz yönetimi uygulamasının yüklemesi kaldırılamıyor"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> adlı kullanıcı için etkin cihaz yönetimi uygulamasının yüklemesi kaldırılamıyor"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Bu uygulama bazı kullanıcılar veya profiller için gerekli ve diğerleri için uygulamanın yüklemesi kaldırıldı"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Profiliniz için bu uygulama gerekli ve yüklemesi kaldırılamaz."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Bu uygulama, cihazınızın yöneticisi için gereklidir ve yüklemesi kaldırılamaz."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Cihaz yönetimi uygulamalarını yönet"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Kullanıcıları yönetme"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> kaldırılamadı."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Paketin ayrıştırılmasında bir sorun oluştu."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Yeni"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Tümü"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Gizlilik"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Cihaz Erişimi"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Bu güncelleme yeni izin gerektirmiyor."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Reddet"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Daha fazla bilgi"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Yine de reddet"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasına <xliff:g id="ACTION">%2$s</xliff:g> izni verilsin mi?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasına <xliff:g id="ACTION">%2$s</xliff:g> için izin verilsin m?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Sadece uygulama kullanılırken"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Her zaman"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Reddet ve bir daha sorma"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> izin devre dışı"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"tümü devre dışı"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"hiçbiri devre dışı değil"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"İzin ver"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Uygulamalar"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Uygulama izinleri"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Tekrar sorma"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"İzin yok"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Ek izinler"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Uygulama bilgilerini aç"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> tane daha</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> tane daha</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Bu uygulama, Android\'in daha eski bir sürümü için tasarlandı. İznin reddedilmesi, uygulamanın bundan sonra amaçlandığı gibi çalışmamasına neden olabilir."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"bilinmeyen bir işlem gerçekleştirme"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> / <xliff:g id="COUNT_1">%2$d</xliff:g> uygulamaya izin veriliyor"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Sistemi göster"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Sistemi gizle"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Uygulama yok"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Konum Ayarları"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g>, bu cihaz için konum hizmetlerinin bir sağlayıcısıdır. Konum erişimi, konum ayarlarından değiştirilebilir."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Bu izni reddederseniz cihazınızın temel özellikleri artık beklendiği gibi çalışmayabilir."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Politika tarafından zorunlu tutuldu"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Arka plan erişimi politika tarafından devre dışı bırakıldı"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Arka plan erişimi politika tarafından etkinleştirildi"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Ön plan erişimi politika tarafından etkinleştirildi"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Yönetici tarafından kontrol ediliyor"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Her zaman"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Sadece uygulama kullanılırken"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Hiçbir zaman"</string>
+    <string name="loading" msgid="7811651799620593731">"Yükleniyor..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Tüm izinler"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Diğer uygulama özellikleri"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"İzin isteği"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Ekran yer paylaşımı tespit edildi"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Bu izin ayarını değiştirmek için ilk olarak Ayarlar &gt; Uygulamalar\'dan ekran yer paylaşımını kapatmanız gerekir"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Ayarları aç"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Yükleme/Yüklemeyi Kaldırma işlemleri Wear\'da desteklenmiyor."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının nelere erişmesine izin vereceğinizi seçin"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; güncellendi. Bu uygulamanın nelere erişmesine izin verileceğini seçin."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"İptal"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Devam"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Yeni izinler"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Geçerli izinler"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Uygulama hazırlanıyor…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Bilinmiyor"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Güvenlik nedeniyle tabletinizin bu kaynaktan bilinmeyen uygulamalar yüklemesine izin verilmez."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Güvenlik nedeniyle TV\'nizin bu kaynaktan bilinmeyen uygulamalar yüklemesine izin verilmez."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Güvenlik nedeniyle telefonunuzun bu kaynaktan bilinmeyen uygulamalar yüklemesine izin verilmez."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefonunuz ve kişisel verileriniz, bilinmeyen uygulamaların saldırılarına karşı daha savunmasızdır. Bu uygulamayı yükleyerek, uygulama kullanımından dolayı telefonunuzda oluşabilecek hasarın veya uğrayabileceğiniz veri kaybının sorumluluğunu kabul etmiş olursunuz."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Tabletiniz ve kişisel verileriniz, bilinmeyen uygulamaların saldırılarına karşı daha savunmasızdır. Bu uygulamayı yükleyerek, uygulama kullanımından dolayı tabletinizde oluşabilecek hasarın veya uğrayabileceğiniz veri kaybının sorumluluğunu kabul etmiş olursunuz."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"TV\'niz ve kişisel verileriniz, bilinmeyen uygulamaların saldırılarına karşı daha savunmasızdır. Bu uygulamayı yükleyerek, uygulama kullanımından dolayı TV\'nizde oluşabilecek hasarın veya uğrayabileceğiniz veri kaybının sorumluluğunu kabul etmiş olursunuz."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Devam"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Ayarlar"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear uyg. yükleme/yüklemesini kaldırma"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-uk-television/strings.xml b/packages/PackageInstaller/res/values-uk-television/strings.xml
new file mode 100644
index 0000000..f4b002f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-uk-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Відмовити й більше не запитувати"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Можна змінити згодом у меню \"Налаштування\" &gt; \"Додатки\""</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> з <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Показати системні додатки"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Дозволи додатка"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Дозволи додатка"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g>: дозволи"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Додаткові дозволи"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g>: дозволи"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-uk-watch/strings.xml b/packages/PackageInstaller/res/values-uk-watch/strings.xml
new file mode 100644
index 0000000..e539d83
--- /dev/null
+++ b/packages/PackageInstaller/res/values-uk-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Відхилити й більше не запитувати"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> з <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Показати системні додатки"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Не можна змінити"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Так"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Скасувати"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-uk/strings.xml b/packages/PackageInstaller/res/values-uk/strings.xml
new file mode 100644
index 0000000..bdc09df
--- /dev/null
+++ b/packages/PackageInstaller/res/values-uk/strings.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Програма встановлення пакета"</string>
+    <string name="next" msgid="3057143178373252333">"Далі"</string>
+    <string name="install" msgid="5896438203900042068">"Установити"</string>
+    <string name="done" msgid="3889387558374211719">"Готово"</string>
+    <string name="cancel" msgid="8360346460165114585">"Скасувати"</string>
+    <string name="installing" msgid="8613631001631998372">"Встановлення…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Установлюється <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Додаток установлено."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Установити цей додаток? Він отримає такі дозволи:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Установити цей додаток? Йому не потрібні спеціальні дозволи."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Дійсно встановити оновлення для цієї наявної програми? Існуючі дані втрачено не буде. Оновлена програма отримає доступ до:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Дійсно встановити оновлення для цієї вбудованої програми? Існуючі дані втрачено не буде. Оновлена програма отримає доступ до:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Хочете встановити оновлення для наявної програми? Ваші наявні дані не зникнуть. Спеціальний доступ не потрібен."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Хочете встановити оновлення для цієї вбудованої програми? Ваші наявні дані не зникнуть. Спеціальний доступ не потрібен."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Додаток не встановлено."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Встановлення пакета заблоковано."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Додаток не встановлено, оскільки пакет конфліктує з наявним пакетом."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Додаток не встановлено, оскільки він несумісний із вашим планшетом."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Цей додаток несумісний із вашим телевізором."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Додаток не встановлено, оскільки він несумісний із вашим телефоном."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Додаток не встановлено, оскільки пакет недійсний."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Програму <xliff:g id="APP_NAME">%1$s</xliff:g> неможливо встановити у вашому планшетному ПК."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Не вдалося встановити додаток <xliff:g id="APP_NAME">%1$s</xliff:g> на ваш телевізор."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Програму <xliff:g id="APP_NAME">%1$s</xliff:g> неможливо встановити у вашому телефоні."</string>
+    <string name="launch" msgid="4826921505917605463">"Відкрити"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Ваш адміністратор заборонив установлювати додатки з невідомих джерел"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Цей користувач не може встановлювати невідомі додатки"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Цей користувач не може встановлювати додатки"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Керувати програмами"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Недостат. місця"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Програму <xliff:g id="APP_NAME">%1$s</xliff:g> неможливо встановити. Звільніть місце та повторіть спробу."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Програму не знайдено"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Програму не знайдено в списку встановлених програм."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Заборонено"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Поточний користувач не може видалити цей додаток."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Помилка"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Не вдалося видалити додаток."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Видалити програму"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Видалити оновлення"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"Дія <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> є частиною такої програми:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Видалити додаток?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Хочете видалити цю програму для "<b>"всіх"</b>" користувачів? Програму та її дані буде видалено для "<b>"всіх"</b>" користувачів цього пристрою."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Видалити цей додаток для користувача <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Відновити заводську версію цього додатка? Усі дані буде видалено."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Відновити заводську версію цього додатка? Усі дані буде видалено. Це вплине на всіх користувачів цього пристрою, зокрема на користувачів із робочими профілями."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Активні видалення"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Невиконані видалення"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Видалення..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Видалення додатка <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Видалення завершено."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Додаток <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> видалено"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Видалення не здійснено."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Не вдалося видалити додаток <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Не вдається видалити активний додаток адміністратора пристрою"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Не вдається видалити активний додаток адміністратора пристрою для користувача <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Цей додаток потрібен для деяких користувачів чи профілів, але його було видалено для інших"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Цей додаток потрібен для вашого профілю, тому його не можна видалити."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Цей додаток не можна видалити – не дозволяє адміністратор пристрою."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Керувати додатками адміністратора пристрою"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Керувати користувачами"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Програму <xliff:g id="APP_NAME">%1$s</xliff:g> неможливо видалити."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Під час аналізу пакету виникла помилка."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Нові"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Усі"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Конфіденційність"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Доступ до пристрою"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Для цього оновлення не потрібні нові дозволи."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Відхилити"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Докладніше"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Усе одно заборонити"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> з <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Завжди дозволяти додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Лише коли додаток активний"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Завжди"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Відхилити й більше не запитувати"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> скасовано"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"усі скасовано"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"нічого не скасовано"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Дозволити"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Додатки"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Дозволи додатків"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Не запитувати знову"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Немає дозволів"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Додаткові дозволи"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Відкрити інформацію про додаток"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+      <item quantity="many">Ще <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Ще <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Цей додаток створено для старішої версії ОС Android. Якщо скасувати дозвіл, він може працювати неналежним чином."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"виконувати невідому дію"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Додатки з дозволом: <xliff:g id="COUNT_0">%1$d</xliff:g> з <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Показати системні додатки"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Сховати системні додатки"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Немає додатків"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Налаштування геоданих"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> є постачальником служб локації для цього пристрою. Доступом до місцезнаходження можна керувати в налаштуваннях геоданих."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Якщо скасувати цей дозвіл, основні функції вашого пристрою можуть працювати неналежним чином."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Застосовується правилом"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Доступ у фоновому режимі вимкнено правилом"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Доступ у фоновому режимі ввімкнено правилом"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Доступ в активному режимі ввімкнено правилом"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Керує адміністратор"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Завжди"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Лише коли додаток активний"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Ніколи"</string>
+    <string name="loading" msgid="7811651799620593731">"Завантаження…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Усі дозволи"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Інші дозволи додатка"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Запит на дозвіл"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Виявлено накладання на екрані"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Щоб змінити налаштування цього дозволу, спершу вимкніть накладання на екрані в меню \"Налаштування\" &gt; \"Додатки\""</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Відкрити налаштування"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Дії \"установити\" або \"видалити\" не підтримуються на пристроях Android Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Виберіть, до чого &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; матиме доступ"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; оновлено. Виберіть, до чого цей додаток матиме доступ."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Скасувати"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Продовжити"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Нові дозволи"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Поточні дозволи"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Підготовка додатка…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Невідомо"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"З міркувань безпеки на вашому планшеті заборонено встановлювати невідомі додатки з цього джерела."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"З міркувань безпеки на вашому телевізорі заборонено встановлювати невідомі додатки з цього джерела."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"З міркувань безпеки на вашому телефоні заборонено встановлювати невідомі додатки з цього джерела."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Ваш телефон і особисті дані більш уразливі до атак невідомих додатків. Установлюючи цей додаток, ви берете на себе відповідальність за пошкодження телефона чи втрату даних унаслідок використання додатка."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Ваш планшет і особисті дані більш уразливі до атак невідомих додатків. Установлюючи цей додаток, ви берете на себе відповідальність за пошкодження планшета чи втрату даних унаслідок використання додатка."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Ваш телевізор і особисті дані більш уразливі до атак невідомих додатків. Установлюючи цей додаток, ви берете на себе відповідальність за пошкодження телевізора чи втрату даних унаслідок використання додатка."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Продовжити"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Налаштування"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Встановлення або видалення додатків Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ur-television/strings.xml b/packages/PackageInstaller/res/values-ur-television/strings.xml
new file mode 100644
index 0000000..27089dd
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ur-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"انکار کریں اور دوبارہ مت پوچھیں"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"آپ بعد میں ترتیبات &gt; ایپس میں جا کر اسے تبدیل کرسکتے ہیں"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"سسٹم ایپس دکھائیں"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"ایپ کی اجازتیں"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"ایپ کی اجازتیں"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> اجازتیں"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"اضافی اجازتیں"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> اجازتیں"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ur-watch/strings.xml b/packages/PackageInstaller/res/values-ur-watch/strings.xml
new file mode 100644
index 0000000..197ac84
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ur-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"انکار کریں، دوبارہ مت پوچھیں"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"سسٹم ایپس دکھائیں"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"ناقابل تبدیل"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"ہاں"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"منسوخ کریں"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-ur/strings.xml b/packages/PackageInstaller/res/values-ur/strings.xml
new file mode 100644
index 0000000..78135a6
--- /dev/null
+++ b/packages/PackageInstaller/res/values-ur/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"پیکیج انسٹال کنندہ"</string>
+    <string name="next" msgid="3057143178373252333">"اگلا"</string>
+    <string name="install" msgid="5896438203900042068">"انسٹال کریں"</string>
+    <string name="done" msgid="3889387558374211719">"ہو گیا"</string>
+    <string name="cancel" msgid="8360346460165114585">"منسوخ کریں"</string>
+    <string name="installing" msgid="8613631001631998372">"انسٹال کیا جا رہا ہے…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> کو انسٹال کیا جا رہا ہے…"</string>
+    <string name="install_done" msgid="3682715442154357097">"ایپ انسٹال ہوگئی۔"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"کیا آپ یہ ایپلیکیشن انسٹال کرنا چاہتے ہیں؟ اس کو مندرجہ ذیل تک رسائی حاصل ہوگی:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"کیا آپ یہ ایپلیکیشن انسٹال کرنا چاہتے ہیں؟ اس کو کوئی خاص رسائی درکار نہیں۔"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"کیا آپ اس موجودہ ایپلیکیشن میں ایک اپ ڈیٹ انسٹال کرنا چاہتے ہیں؟ آپ کا موجودہ ڈیٹا ضائع نہیں ہوگا۔ اپ ڈیٹ کردہ ایپلیکیشن کو مندرجہ ذیل تک رسائی حاصل ہوگی:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"کیا آپ پہلے سے شامل اس ایپلیکیشن میں ایک اپ ڈیٹ انسٹال کرنا چاہتے ہیں؟ آپ کا موجودہ ڈیٹا ضائع نہیں ہوگا۔ اپ ڈیٹ کردہ ایپلیکیشن کو مندرجہ ذیل تک رسائی حاصل ہوگی:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"کیا آپ اس موجودہ ایپلیکیشن میں ایک اپ ڈیٹ انسٹال کرنا چاہتے ہیں؟ آپ کا موجودہ ڈیٹا ضائع نہیں ہوگا۔ اس کو کوئی خاص رسائی درکار نہیں۔"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"کیا آپ پہلے سے شامل اس ایپلیکیشن میں ایک اپ ڈیٹ انسٹال کرنا چاہتے ہیں؟ آپ کا موجودہ ڈیٹا ضائع نہیں ہوگا۔ اس کو کوئی خاص رسائی درکار نہیں۔"</string>
+    <string name="install_failed" msgid="6579998651498970899">"ایپ انسٹال نہیں ہوئی۔"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"پیکج کو انسٹال ہونے سے روک دیا گیا۔"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"ایپ کو پیکج کے بطور انسٹال نہیں کیا گیا کیونکہ پیکج ایک موجودہ پیکیج سے متصادم ہے۔"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"ایپ انسٹال نہیں ہوئی کیونکہ ایپ آپ کے ٹیبلیٹ کے ساتھ مطابقت پذیر نہیں ہے۔"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"‏یہ ایپ آپ کے TV کے ساتھ مطابقت پذیر نہیں ہے۔"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"ایپ انسٹال نہیں ہوئی کیونکہ ایپ آپ کے فون کے ساتھ مطابقت پذیر نہیں ہے۔"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"ایپ انسٹال نہیں ہوئی کیونکہ پیکیج غلط معلوم ہوتا ہے۔"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کے ٹیبلیٹ پر انسٹال نہیں کیا جا سکا۔"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"‏<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کے TV پر انسٹال نہیں کیا جا سکا۔"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کے فون پر انسٹال نہیں کیا جا سکا۔"</string>
+    <string name="launch" msgid="4826921505917605463">"کھولیں"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"آپ کا منتظم نامعلوم ذرائع سے اخذ کردہ ایپس کو انسٹال کرنے کی اجازت نہیں دیتا ہے"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"اس صارف کے ذریعے نامعلوم ایپس کو انسٹال نہیں کیا جا سکتا"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"اس صارف کو ایپس انسٹال کرنے کی اجازت نہیں ہے"</string>
+    <string name="ok" msgid="3468756155452870475">"ٹھیک ہے"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"ایپس کا نظم کریں"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"جگہ ختم ہو گئی ہے"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو انسٹال نہیں کیا جا سکا۔ کچھ جگہ خالی کریں اور دوبارہ کوشش کریں۔"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"ایپ نہیں ملی"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"ایپ انسٹال کردہ ایپس کی فہرست میں نہیں ملی۔"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"اجازت نہیں ہے"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"موجودہ صارف کو اس ان انسٹالیشن کو سرانجام دینے کی اجازت نہیں ہے۔"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"خرابی"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"ایپ ان انسٹال نہیں ہو سکی۔"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"ایپ کو اَن انسٹال کریں"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"اپ ڈیٹ اَن انسٹال کریں"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> درج ذیل ایپ کا حصہ ہے:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"کیا آپ یہ ایپ اَن انسٹال کرنا چاہتے ہیں؟"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"کیا آپ "<b>"سبھی"</b>" صارفین کیلئے یہ ایپ اَن انسٹال کرنا چاہتے ہیں؟ ایپلیکیشن اور اس کا ڈیٹا آلے پر موجود "<b>"سبھی"</b>" صارفین سے ہٹا دیا جائے گا۔"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"کیا آپ اس ایپ کو صارف <xliff:g id="USERNAME">%1$s</xliff:g> کیلئے اَن انسٹال کرنا چاہتے ہیں؟"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"اس ایپ کو فیکٹری ورژن سے تبدیل کریں؟ تمام ڈیٹا ہٹا دیا جائے گا۔"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"اس ایپ کو فیکٹری ورژن سے تبدیل کریں؟ تمام ڈیٹا ہٹا دیا جائے گا۔ اس سے اس آلہ کے تمام صارف متاثر ہوں گے بشمول ان کے جن کے پاس دفتری پروفائلز ہیں۔"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"چل رہے اَن انسٹالس"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"ناکام اَن انسٹالس"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"اَن انسٹال ہو رہا ہے…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ان انسٹال ہو رہی ہے…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"اَن انسٹال پورا ہوگیا۔"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ان انسٹال ہو گیا"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"اَن انسٹال ناکام۔"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> کو ان انسٹال کرنا کامیاب نہیں ہوا۔"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"فعال آلہ کے منتظم کی ایپ اَن انسٹال نہیں کر سکتے"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"فعال آلہ کے منتظم کی ایپ <xliff:g id="USERNAME">%1$s</xliff:g> کیلئے اَن انسٹال نہیں کر سکتے"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"یہ ایپ کچھ صارفین اور پروفائلوں کیلئے درکار ہے اور دیگر کیلئے ان انسٹال ہو گئی"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"یہ ایپ آپ کے پروفائل کیلئے درکار ہے اور یہ ان انسٹال نہیں ہو سکتی۔"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"یہ ایپ آپ کے آلہ کے منتظم کو درکار ہے اور اسے اَن انسٹال نہیں کیا جا سکتا ہے۔"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"آلہ کے منتظم کی ایپس کا نظم کریں"</string>
+    <string name="manage_users" msgid="3125018886835668847">"صارفین کا نظم کریں"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو اَن انسٹال نہیں کیا جا سکا۔"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"پیکیج کو پارس کرنے میں ایک دشواری پیش آگئی۔"</string>
+    <string name="newPerms" msgid="6039428254474104210">"نئی"</string>
+    <string name="allPerms" msgid="1024385515840703981">"سبھی"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"رازداری"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"آلہ کی رسائی"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"اس اپ ڈیٹ کو کوئی نئی اجازتیں درکار نہیں۔"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"مسترد کریں"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"مزید معلومات"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"بہرصورت انکار کریں"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> از <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو <xliff:g id="ACTION">%2$s</xliff:g> کی اجازت دیں؟"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"‏ہمیشہ ‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎ کو <xliff:g id="ACTION">%2$s</xliff:g> کی اجازت دیں؟"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"صرف ایپ استعمال کرنے کے دوران"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"ہمیشہ"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"انکار کریں اور دوبارہ مت پوچھیں"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> غیر فعال ہو گئیں"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"تمام غیر فعال ہو گئیں"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"کچھ بھی غیر فعال نہیں ہوا"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"اجازت دیں"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"ایپس"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"ایپ کی اجازتیں"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"دوبارہ مت پوچھیں"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"کوئی اجازتیں نہیں ہیں"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"اضافی اجازتیں"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"ایپ کی معلومات کھولیں"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"‏یہ ایپ Android کے ایک پرانے ورژن کیلئے ڈیزائن کی گئی تھی۔ اجازت دینے سے انکار کرنے پر ممکن ہے کہ وہ مزید ٹھیک سے کام نہ کرے۔"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"ایک نامعلوم کارروائی کو انجام دیں"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_1">%2$d</xliff:g> میں سے <xliff:g id="COUNT_0">%1$d</xliff:g> ایپس کو اجازت دے دی گئی"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"سسٹم دکھائیں"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"سسٹم چھپائیں"</string>
+    <string name="no_apps" msgid="1965493419005012569">"کوئی ایپس نہیں ہیں"</string>
+    <string name="location_settings" msgid="1774875730854491297">"مقام کی ترتیبات"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> اس آلہ کیلئے مقام کی سروسز کا فراہم کنندہ ہے۔ مقام کی رسائی میں مقام کی ترتیبات سے ترمیم کی جا سکتی ہے۔"</string>
+    <string name="system_warning" msgid="7103819124542305179">"اگرآپ اس اجازت کو مسترد کرتے ہیں تو شاید آپ کے آلہ کی بنیادی خصوصیات ٹھیک سے کام نہ کریں۔"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"پالیسی کی طرف سے نافذ کردہ"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"پالیسی نے پس منظر کی رسائی غیر فعال کر دی ہے"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"پالیسی نے پس منظر کی رسائی فعال کر دی ہے"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"پالیسی نے پیش منظر کی رسائی فعال کر دی ہے"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"کنٹرول کردہ بذریعہ منتظم"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"ہمیشہ"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"صرف ایپ استعمال کرنے کے دوران"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"کبھی نہیں"</string>
+    <string name="loading" msgid="7811651799620593731">"لوڈ ہورہا ہے…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"تمام اجازاتیں"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"دوسری ایپ اہلیتیں"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"اجازت کی درخواست"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"اسکرین اورلے کا پتہ چلا ہے"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"‏اس اجازت کی ترتیب کو تبدیل کرنے کیلئے آپ کو پہلے ترتیبات &gt; Apps سے سکرین اورلے آف کرنا ہوگا"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"ترتیبات کھولیں"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"‏\'کاروائیاں انسٹال/ان انسٹال کریں\' Wear پر تعاون یافتہ نہیں ہے۔"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"‏انتخاب کریں کہ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو کس تک رسائی کی اجازت دینی ہے"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اپ ڈیٹ ہو گئی ہے۔ انتخاب کریں کہ اس ایپ کو کس تک رسائی کی اجازت دینی ہے۔"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"منسوخ کریں"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"جاری رکھیں"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"نئی اجازتیں"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"موجودہ اجازتیں"</string>
+    <string name="message_staging" msgid="6151794817691100003">"ایپ کی مرحلہ بندی ہو رہی ہے…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"نامعلوم"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"آپ کی سیکیوریٹی کیلئے، آپ کے ٹیبلیٹ کو اس ذریعے سے نامعلوم ایپس انسٹال کرنے کی اجازت نہیں ہے۔"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"‏آپ کی سیکیوریٹی کیلئے، آپ کے TV کو اس ذریعے سے نامعلوم ایپس انسٹال کرنے کی اجازت نہیں ہے۔"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"آپ کی سیکیوریٹی کیلئے، آپ کے فون کو اس ذریعے سے نامعلوم ایپس انسٹال کرنے کی اجازت نہیں ہے۔"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"آپ کے فون اور ذاتی ڈیٹا کو نامعلوم ایپس کی جانب سے حملے کا زیادہ خطرہ ہے۔ اس ایپ کو انسٹال کر کے، آپ اس بات سے اتفاق کرتے ہیں کہ آپ اس سے اپنے فون کو ہونے والے کسی بھی نقصان یا ڈیٹا کے نقصان کیلئے خود ذمہ دار ہیں۔"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"آپ کے ٹیبلیٹ اور ذاتی ڈیٹا کو نامعلوم ایپس کی جانب سے حملے کا زیادہ خطرہ ہے۔ اس ایپ کو انسٹال کر کے، آپ اس بات سے اتفاق کرتے ہیں کہ آپ اس سے اپنے ٹیبلیٹ کو ہونے والے کسی بھی نقصان یا ڈیٹا کے نقصان کیلئے خود ذمہ دار ہیں۔"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"‏آپ کے TV اور ذاتی ڈیٹا کو نامعلوم ایپس کی جانب سے حملے کا زیادہ خطرہ ہے۔ اس ایپ کو انسٹال کر کے، آپ اس بات سے اتفاق کرتے ہیں کہ آپ اس سے اپنے TV کو ہونے والے کسی بھی نقصان یا ڈیٹا کے نقصان کیلئے خود ذمہ دار ہیں۔"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"جاری رکھیں"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"ترتیبات"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"‏wear ایپس کا انسٹال/ان انسٹال کرنا"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-uz-television/strings.xml b/packages/PackageInstaller/res/values-uz-television/strings.xml
new file mode 100644
index 0000000..bcc12ac
--- /dev/null
+++ b/packages/PackageInstaller/res/values-uz-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Rad etilsin va boshqa so‘ralmasin"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Siz buni keyinroq Sozlamalar &gt; Ilovalar bo‘limi orqali ham o‘zgartirishingiz mumkin"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Tizim ilovalarini ko‘rsatish"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Ilova uchun ruxsatlar"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Ilova uchun ruxsatlar"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> uchun ruxsat"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Qo‘shimcha ruxsatlar"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> uchun ruxsat"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-uz-watch/strings.xml b/packages/PackageInstaller/res/values-uz-watch/strings.xml
new file mode 100644
index 0000000..83f8da7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-uz-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Rad etilsin va boshqa so‘ralmasin"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Tizim ilovalarini ko‘rsatish"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"O‘zgartirilmaydi"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Ha"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Bekor qilish"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-uz/strings.xml b/packages/PackageInstaller/res/values-uz/strings.xml
new file mode 100644
index 0000000..15a2e92
--- /dev/null
+++ b/packages/PackageInstaller/res/values-uz/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Paket o‘rnatish vositasi"</string>
+    <string name="next" msgid="3057143178373252333">"Keyingisi"</string>
+    <string name="install" msgid="5896438203900042068">"O‘rnatish"</string>
+    <string name="done" msgid="3889387558374211719">"Tayyor"</string>
+    <string name="cancel" msgid="8360346460165114585">"Bekor qilish"</string>
+    <string name="installing" msgid="8613631001631998372">"O‘rnatilmoqda…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> o‘rnatilmoqda…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Ilova o‘rnatildi."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Bu ilovani o‘rnatmoqchimisiz? U quyidagi ruxsatlarga ega:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Bu ilovani o‘rnatmoqchimisiz? U hech qanday maxsus ruxsat talab qilmaydi."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Bu ilova uchun yangilanishni o‘rnatmoqchimisiz? Yangilanganidan keyin u quyidagi ruxsatlarga ega bo‘ladi:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Bu ilova uchun yangilanishni o‘rnatmoqchimisiz? Yangilanganidan keyin u quyidagi ruxsatlarga ega bo‘ladi:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Ushbu mavjud ilovaga yangilanish o‘rnatilsinmi? Mavjud ma’lumotlaringiz o‘chib ketmaydi. U hech qanday maxsus ruxsat talab qilmaydi."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Ushbu tizim ilovasiga yangilanish o‘rnatilsinmi? Mavjud ma’lumotlaringiz o‘chib ketmaydi. U hech qanday maxsus ruxsat talab qilmaydi."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Ilova o‘rnatilmadi."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Paket o‘rnatilishga qarshi bloklangan."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Paket mavjud paket bilan zid kelganligi uchun ilovani o‘rnatib bo‘lmadi."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Ilova planshetingizga mos kelmaganligi uchun uni o‘rnatib bo‘lmadi."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Bu ilova televizoringiz bilan mos emas."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Ilova telefoningizga mos kelmaganligi uchun uni o‘rnatib bo‘lmadi."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Paket yaroqsiz bo‘lganligi uchun ilovani o‘rnatib bo‘lmadi."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"<xliff:g id="APP_NAME">%1$s</xliff:g> planshetingizga o‘rnatilmadi."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasini televizoringizga o‘rnatib bo‘lmadi."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"<xliff:g id="APP_NAME">%1$s</xliff:g> telefoningizga o‘rnatilmadi."</string>
+    <string name="launch" msgid="4826921505917605463">"Ochish"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Administratoringiz begona manbalardan olingan ilovalarni o‘rnatishga ruxsat bermagan"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Notanish ilovalarni bu foydalanuvchi tomonidan o‘rnatib bo‘lmaydi"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Bu foydalanuvchiga ilovalarni o‘rnatish uchun ruxsat berilmagan"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Ilovalarni boshqarish"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Joy qolmadi"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"<xliff:g id="APP_NAME">%1$s</xliff:g> o‘rnatilmadi. Xotiradan biroz joy bo‘shating va qaytadan urinib ko‘ring."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Ilova topilmadi"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Ilova o‘rnatilgan ilovalar ro‘yxatidan topilmadi."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Ruxsat berilmagan"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Joriy foydalanuvchiga bu o‘chirishni amalga oshirishi uchun ruxsat berilmagan."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Xato"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Ilovani o‘chirib bo‘lmadi"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Ilovani o‘chirish"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Yangilanishni o‘chirish"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> quyidagi ilovaning bir qismidir:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Bu ilova o‘chirib tashlansinmi?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Ushbu ilova "<b>"barcha"</b>" foydalanuvchilar uchun o‘chirilsinmi? Ilova va uning ma’lumotlari qurilmadagi "<b>"barcha"</b>" foydalanuvchilardan o‘chib ketadi."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Haqiqatdan ham <xliff:g id="USERNAME">%1$s</xliff:g> foydalanuvchi uchun ushbu ilovani olib tashlamoqchimisiz?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Bu ilova boshlang‘ich versiyasi bilan almashtirilsinmi? Barcha ma’lumotlar o‘chirib tashlanadi."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Bu ilova boshlang‘ich versiyasi bilan almashtirilsinmi? Barcha ma’lumotlar o‘chirib tashlanadi. Bu qurilmaning barcha foydalanuvchilariga, jumladan, ularning ishchi profillariga ham ta’sir qiladi."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Davom etayotganlar"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Amalga oshmaganlar"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"O‘chirilmoqda…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> o‘chirilmoqda…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"O‘chirib tashlandi."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> o‘chirib tashlandi"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"O‘chirish muvaffaqiyatsizlikka uchradi."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ilovasini o‘chirib bo‘lmadi."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Faol qurilma administratori ilovasini o‘chirib bo‘lmaydi"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"<xliff:g id="USERNAME">%1$s</xliff:g> profilida faol qurilma administratori ilovasini o‘chirib bo‘lmaydi"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Bu ilova ba’zi foydalanuvchi yoki profillar uchun zarur, boshqalar uchun esa o‘chirib tashlangan"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Bu ilova profilingiz uchun kerak va uni o‘chirib bo‘lmaydi."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ushbu ilova qurilmangiz ma\'muri tomonidan ishlatiladi, shuning uchun uni olib tashlab bo\'lmaydi."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Qurilma administratori ilovalarini boshqarish"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Foydalanuvchilarni boshqarish"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"<xliff:g id="APP_NAME">%1$s</xliff:g> o‘chirilmadi."</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Paketni tahlil qilishda muammo yuz berdi."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Yangi"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Barchasi"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Maxfiylik"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Qurilmalardan foydalanish"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Ushbu yangilanish hech qanday yangi ruxsatlarni talab qilmaydi."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Rad etish"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Batafsil"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Baribir rad etilsin"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ilovasiga <xliff:g id="ACTION">%2$s</xliff:g> uchun ruxsat berilsinmi?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ilovasiga bu amalga bajarishga doim ruxsat berilsinmi: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Faqat ilova ishlatilayotganda"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Har doim"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Rad etilsin va boshqa so‘ralmasin"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> tasi o‘chiq"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"hammasi o‘chiq"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"hech qaysi o‘chirilmagan"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Ruxsat berish"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Ilovalar"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Ilovalar uchun ruxsatlar"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Boshqa so‘ralmasin"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Hech narsa topilmadi"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Qo‘shimcha ruxsatlar"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Ilovaga oid ma’lumotni ochish"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other">Yana <xliff:g id="COUNT_1">%1$d</xliff:g> ta</item>
+      <item quantity="one">Yana <xliff:g id="COUNT_0">%1$d</xliff:g> ta</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Bu ilova Androidning eskiroq versiyasiga mo‘ljallab ishlab chiqilgan. Agar ruxsat bermasangiz, u kutilganidek ishlamasligi mumkin."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"noma’lum amalni bajarish"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Ruxsat berilgan: <xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Tizimga oid jarayonlar"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Tizimga oid jarayonlarni berkitish"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Hech qanday ilova yo‘q"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Joylashuv sozlamalari"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu qurilma uchun joylashuvni aniqlash xizmatini taqdim etuvchi ilova hisoblanadi. Joylashuv ma’lumotlariga kirish vakolatini joylashuv sozlamalaridan o‘zgartirish mumkin."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Agar bu ruxsatni rad qilsangiz, qurilmangizning asosiy funksiyalari bundan buyon kutilganidek ishlamasligi mumkin."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Qoidaga muvofiq"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Fon rejimida kirish qoidaga muvofiq taqiqlangan"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Fon rejimida kirish qoidaga muvofiq yoqilgan"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Faol rejimda kirish qoidaga muvofiq yoqilgan"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Administrator tomonidan boshqariladi"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Har doim"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Faqat ilova ishlatilayotganda"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Hech qachon"</string>
+    <string name="loading" msgid="7811651799620593731">"Yuklanmoqda…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Barcha ruxsatnomalar"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Ilovaning boshqa imkoniyatlari"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Ruxsatnoma so‘rovi"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Boshqa oynalar ustidan ochiladigan ilova aniqlandi"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Bu ruxsatnoma parametrini o‘zgartirish uchun avval Sozlamalar &gt; Ilovalar bo‘limidan ekran ustidan ochilish funksiyasini o‘chirib qo‘ying"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Sozlamalarni ochish"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear qurilmasi o‘rnatish/o‘chirish amallarini qo‘llab-quvvatlamaydi."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun beriladigan ruxsatlarni tanlang"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; yangilandi. Unga beriladigan ruxsatlarni tanlang."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Bekor qilish"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Davom etish"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Yangi ruxsatnomalar"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Joriy ruxsatnomalar"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Kutib turing…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Noma’lum"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Xavfsizlik yuzasidan, planshetingizga bu manbadan notanish ilovalarni o‘rnatishga ruxsat berilmagan."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Xavfsizlik yuzasidan, televizoringizga bu manbadan notanish ilovalarni o‘rnatishga ruxsat berilmagan."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Xavfsizlik yuzasidan, telefoningizga bu manbadan notanish ilovalarni o‘rnatishga ruxsat berilmagan."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Telefoningiz va shaxsiy ma‘lumotlaringiz notanish ilovalar xujumiga zaif bo‘ladi. Bu ilovani o‘rnatish bilan telefoningizga yetkaziladigan shikast va ma‘lumotlaringizni o‘chirib yuborilishiga javobgarlikni o‘z zimmangizga olasiz."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Planshetingiz va shaxsiy ma‘lumotlaringiz notanish ilovalar xujumiga zaif bo‘ladi. Bu ilovani o‘rnatish bilan planshetingizga yetkaziladigan shikast va ma‘lumotlaringizni o‘chirib yuborilishiga javobgarlikni o‘z zimmangizga olasiz."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"TV va shaxsiy ma‘lumotlaringiz notanish ilovalar xujumiga zaif bo‘ladi. Bu ilovani o‘rnatish bilan televizoringizga yetkaziladigan shikast va ma‘lumotlaringizni o‘chirib yuborilishiga javobgarlikni o‘z zimmangizga olasiz."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Davom etish"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Sozlamalar"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Wear ilovalarini o‘rnatish/o‘chirish"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-vi-television/strings.xml b/packages/PackageInstaller/res/values-vi-television/strings.xml
new file mode 100644
index 0000000..574bde7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-vi-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Từ chối và không hỏi lại"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Bạn có thể thay đổi cài đặt này sau trong Cài đặt &gt; Ứng dụng"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Hiển thị ứng dụng hệ thống"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Quyền của ứng dụng"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Quyền của ứng dụng"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"Quyền <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Quyền bổ sung"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"Quyền <xliff:g id="PERMISSION">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-vi-watch/strings.xml b/packages/PackageInstaller/res/values-vi-watch/strings.xml
new file mode 100644
index 0000000..d63ef28
--- /dev/null
+++ b/packages/PackageInstaller/res/values-vi-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Từ chối, không hỏi lại"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Hiển thị ứng dụng hệ thống"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Ko thể thay đổi"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Có"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Hủy"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-vi/strings.xml b/packages/PackageInstaller/res/values-vi/strings.xml
new file mode 100644
index 0000000..09998d8
--- /dev/null
+++ b/packages/PackageInstaller/res/values-vi/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Trình cài đặt gói"</string>
+    <string name="next" msgid="3057143178373252333">"Tiếp theo"</string>
+    <string name="install" msgid="5896438203900042068">"Cài đặt"</string>
+    <string name="done" msgid="3889387558374211719">"Xong"</string>
+    <string name="cancel" msgid="8360346460165114585">"Hủy"</string>
+    <string name="installing" msgid="8613631001631998372">"Đang cài đặt…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"Đang cài đặt <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"Ứng dụng đã được cài đặt."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Bạn có muốn cài đặt ứng dụng này không? Ứng dụng sẽ có quyền truy cập vào:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Bạn có muốn cài đặt ứng dụng này không? Ứng dụng này không yêu cầu bất kỳ quyền truy cập đặc biệt nào."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Bạn có muốn cài đặt bản cập nhật cho ứng dụng hiện tại này không? Dữ liệu hiện tại của bạn sẽ không bị mất. Ứng dụng đã cập nhật sẽ có quyền truy cập vào:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Bạn có muốn cài đặt bản cập nhật cho ứng dụng được cài sẵn này không? Dữ liệu hiện tại của bạn sẽ không bị mất. Ứng dụng được cập nhật sẽ có quyền truy cập vào:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Bạn có muốn cài đặt bản cập nhật cho ứng dụng hiện có này không? Dữ liệu hiện có của bạn sẽ không bị mất. Việc cài đặt không yêu cầu bất kỳ quyền truy cập đặc biệt nào."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Bạn có muốn cài đặt bản cập nhật cho ứng dụng cài sẵn này không? Dữ liệu hiện có của bạn sẽ không bị mất. Việc cài đặt không yêu cầu quyền truy cập đặc biệt nào."</string>
+    <string name="install_failed" msgid="6579998651498970899">"Ứng dụng chưa được cài đặt."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Đã chặn cài đặt gói."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Ứng dụng chưa được cài đặt dưới dạng gói xung đột với gói hiện có."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Ứng dụng chưa được cài đặt dưới dạng ứng dụng không tương thích với máy tính bảng của bạn."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Ứng dụng này không tương thích với TV của bạn."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Ứng dụng chưa được cài đặt dưới dạng ứng dụng không tương thích với điện thoại của bạn."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Ứng dụng chưa được cài đặt dưới dạng gói dường như không hợp lệ."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"Không thể cài đặt <xliff:g id="APP_NAME">%1$s</xliff:g> trên máy tính bảng của bạn."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"Không cài đặt được <xliff:g id="APP_NAME">%1$s</xliff:g> trên TV của bạn."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"Không thể cài đặt <xliff:g id="APP_NAME">%1$s</xliff:g> trên điện thoại này."</string>
+    <string name="launch" msgid="4826921505917605463">"Mở"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Quản trị viên của bạn không cho phép cài đặt ứng dụng từ nguồn không xác định"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Người dùng này không thể cài đặt ứng dụng không xác định"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Người dùng này không được phép cài đặt ứng dụng"</string>
+    <string name="ok" msgid="3468756155452870475">"OK"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Quản lý ứng dụng"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Hết dung lượng"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"Không thể cài đặt <xliff:g id="APP_NAME">%1$s</xliff:g>. Hãy giải phóng dung lượng và thử lại."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"Không tìm thấy ứng dụng"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Không tìm thấy ứng dụng trong danh sách các ứng dụng đã cài đặt."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Không được phép"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Người dùng hiện tại không được phép thực hiện quá trình gỡ cài đặt này."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Lỗi"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Không thể gỡ cài đặt ứng dụng."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Gỡ cài đặt ứng dụng"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Gỡ cài đặt cập nhật"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> là một phần của ứng dụng sau:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Bạn có muốn gỡ cài đặt ứng dụng này không?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Bạn có muốn gỡ cài đặt ứng dụng này cho "<b>"tất cả"</b>" người dùng không? Ứng dụng và dữ liệu của ứng dụng sẽ bị xóa khỏi "<b>"tất cả"</b>" người dùng trên thiết bị."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Bạn có muốn gỡ cài đặt ứng dụng này cho người dùng <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Thay thế ứng dụng này bằng phiên bản gốc? Tất cả dữ liệu sẽ bị xóa."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Thay thế ứng dụng này bằng phiên bản gốc? Tất cả dữ liệu sẽ bị xóa. Điều này ảnh hưởng đến tất cả người dùng thiết bị này, bao gồm cả những người có hồ sơ công việc."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Gỡ cài đặt đang chạy"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Gỡ cài đặt không thành công"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Đang gỡ cài đặt..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Đang gỡ cài đặt <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Gỡ cài đặt đã hoàn tất."</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Đã gỡ cài đặt <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Gỡ cài đặt không thành công."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Gỡ cài đặt <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> không thành công."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Không thể gỡ cài đặt ứng dụng dành cho quản trị viên thiết bị đang hoạt động"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Không thể gỡ cài đặt ứng dụng dành cho quản trị viên thiết bị đang hoạt động cho <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Ứng dụng này bắt buộc với một số người dùng hoặc hồ sơ và được gỡ cài đặt cho người khác"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Ứng dụng này là cần thiết cho hồ sơ của bạn và không thể gỡ cài đặt."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Ứng dụng này được quản trị viên thiết bị của bạn yêu cầu và không thể gỡ cài đặt."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Quản lý ứng dụng quản trị thiết bị"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Quản lý người dùng"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"Không thể gỡ cài đặt <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Đã xảy ra sự cố khi phân tích cú pháp gói."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Mới"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Tất cả"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Bảo mật"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Truy cập thiết bị"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Bản cập nhật này không yêu cầu quyền mới."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Từ chối"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Thông tin khác"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Vẫn từ chối"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Luôn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Chỉ khi sử dụng ứng dụng"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Luôn luôn"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Từ chối và không hỏi lại"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"Đã vô hiệu hóa <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"tất cả quyền đều bị vô hiệu hóa"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"không có quyền nào bị vô hiệu hóa"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Cho phép"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Ứng dụng"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Quyền của ứng dụng"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Không hỏi lại"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Không có quyền"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Quyền khác"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Mở thông tin về ứng dụng"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> quyền khác</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> quyền khác</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Ứng dụng này được thiết kế cho các phiên bản Android cũ hơn. Từ chối quyền có thể làm cho ứng dụng không còn hoạt động như mong muốn."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"thực hiện hành động không xác định"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"Đã cho phép <xliff:g id="COUNT_0">%1$d</xliff:g> trong số <xliff:g id="COUNT_1">%2$d</xliff:g> ứng dụng"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Hiển thị hệ thống"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Ẩn hệ thống"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Không có ứng dụng"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Cài đặt vị trí"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> là nhà cung cấp dịch vụ vị trí cho thiết bị này. Bạn có thể sửa đổi quyền truy cập vị trí từ cài đặt vị trí."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Nếu bạn từ chối quyền này, các tính năng cơ bản trên thiết bị của bạn có thể không còn hoạt động như dự kiến."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Được thực thi bằng chính sách"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Quyền truy cập nền bị tắt theo chính sách"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Quyền truy cập nền được bật theo chính sách"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Quyền truy cập nền trước được bật theo chính sách"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Do quản trị viên kiểm soát"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Luôn luôn"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Chỉ khi sử dụng ứng dụng"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Không bao giờ"</string>
+    <string name="loading" msgid="7811651799620593731">"Đang tải…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Tất cả các quyền"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Các khả năng khác của ứng dụng"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Yêu cầu quyền"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Đã phát hiện lớp phủ màn hình"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Để thay đổi cài đặt quyền này, trước tiên bạn phải tắt lớp phủ màn hình từ Cài đặt &gt; Ứng dụng"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Mở cài đặt"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Không hỗ trợ tác vụ Cài đặt/Gỡ cài đặt trên Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Chọn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập những gì"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"Đã cập nhật &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;. Chọn cho phép ứng dụng này truy cập những gì."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Hủy"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Tiếp tục"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Các quyền mới"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Các quyền hiện tại"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Đang sắp xếp ứng dụng…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Không xác định"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Để bảo mật, máy tính bảng của bạn không được phép cài đặt các ứng dụng không xác định từ nguồn này."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Để bảo mật, TV của bạn không được phép cài đặt các ứng dụng không xác định từ nguồn này."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Để bảo mật, điện thoại của bạn không được phép cài đặt các ứng dụng không xác định từ nguồn này."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Điện thoại và dữ liệu cá nhân của bạn dễ bị các ứng dụng không xác định tấn công hơn. Bằng cách cài đặt ứng dụng này, bạn đồng ý tự chịu trách nhiệm cho mọi hỏng hóc đối với điện thoại của mình hoặc mất mát dữ liệu có thể phát sinh do sử dụng ứng dụng này."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Máy tính bảng và dữ liệu cá nhân của bạn dễ bị các ứng dụng không xác định tấn công hơn. Bằng cách cài đặt ứng dụng này, bạn đồng ý tự chịu trách nhiệm cho mọi hỏng hóc đối với máy tính bảng của mình hoặc mất mát dữ liệu có thể phát sinh do sử dụng ứng dụng này."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"TV và dữ liệu cá nhân của bạn dễ bị các ứng dụng không xác định tấn công hơn. Bằng cách cài đặt ứng dụng này, bạn đồng ý tự chịu trách nhiệm cho mọi hỏng hóc đối với TV của mình hoặc mất mát dữ liệu có thể phát sinh do sử dụng ứng dụng này."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Tiếp tục"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Cài đặt"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Cài đặt/gỡ cài đặt ứng dụng Wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-w192dp-watch/dimens_percent.xml b/packages/PackageInstaller/res/values-w192dp-watch/dimens_percent.xml
new file mode 100644
index 0000000..b5beca3
--- /dev/null
+++ b/packages/PackageInstaller/res/values-w192dp-watch/dimens_percent.xml
@@ -0,0 +1,21 @@
+<?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>
+    <dimen name="screen_percentage_05">9.6dp</dimen>
+    <dimen name="screen_percentage_10">19.2dp</dimen>
+    <dimen name="screen_percentage_12">23.04dp</dimen>
+    <dimen name="screen_percentage_15">28.8dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-w205dp-watch/dimens_percent.xml b/packages/PackageInstaller/res/values-w205dp-watch/dimens_percent.xml
new file mode 100644
index 0000000..302d23e
--- /dev/null
+++ b/packages/PackageInstaller/res/values-w205dp-watch/dimens_percent.xml
@@ -0,0 +1,21 @@
+<?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>
+    <dimen name="screen_percentage_05">10.25dp</dimen>
+    <dimen name="screen_percentage_10">20.5dp</dimen>
+    <dimen name="screen_percentage_12">24.6dp</dimen>
+    <dimen name="screen_percentage_15">30.75dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-w225dp-watch/dimens_percent.xml b/packages/PackageInstaller/res/values-w225dp-watch/dimens_percent.xml
new file mode 100644
index 0000000..937c5d0
--- /dev/null
+++ b/packages/PackageInstaller/res/values-w225dp-watch/dimens_percent.xml
@@ -0,0 +1,21 @@
+<?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>
+    <dimen name="screen_percentage_05">11.25dp</dimen>
+    <dimen name="screen_percentage_10">22.5dp</dimen>
+    <dimen name="screen_percentage_12">27dp</dimen>
+    <dimen name="screen_percentage_15">33.75dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-w228dp-watch/dimens_percent.xml b/packages/PackageInstaller/res/values-w228dp-watch/dimens_percent.xml
new file mode 100644
index 0000000..b2ad334
--- /dev/null
+++ b/packages/PackageInstaller/res/values-w228dp-watch/dimens_percent.xml
@@ -0,0 +1,21 @@
+<?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>
+    <dimen name="screen_percentage_05">11.4dp</dimen>
+    <dimen name="screen_percentage_10">22.8dp</dimen>
+    <dimen name="screen_percentage_12">27.36dp</dimen>
+    <dimen name="screen_percentage_15">34.2dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-w240dp-watch/dimens_percent.xml b/packages/PackageInstaller/res/values-w240dp-watch/dimens_percent.xml
new file mode 100644
index 0000000..ebc8c75
--- /dev/null
+++ b/packages/PackageInstaller/res/values-w240dp-watch/dimens_percent.xml
@@ -0,0 +1,21 @@
+<?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>
+    <dimen name="screen_percentage_05">12dp</dimen>
+    <dimen name="screen_percentage_10">24dp</dimen>
+    <dimen name="screen_percentage_12">28.8dp</dimen>
+    <dimen name="screen_percentage_15">36dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values-watch/colors.xml b/packages/PackageInstaller/res/values-watch/colors.xml
new file mode 100644
index 0000000..81d0459
--- /dev/null
+++ b/packages/PackageInstaller/res/values-watch/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <!-- Copied from wearable support -->
+    <color name="circular_button_disabled">#757575</color>
+</resources>
diff --git a/packages/PackageInstaller/res/values-watch/integers.xml b/packages/PackageInstaller/res/values-watch/integers.xml
new file mode 100644
index 0000000..365ac3a
--- /dev/null
+++ b/packages/PackageInstaller/res/values-watch/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- START: Ported values -->
+    <integer name="short_title_length">13</integer>
+    <integer name="char_limit_per_line">18</integer>
+    <!-- END: Ported values -->
+</resources>
diff --git a/packages/PackageInstaller/res/values-watch/strings.xml b/packages/PackageInstaller/res/values-watch/strings.xml
new file mode 100644
index 0000000..25e8389
--- /dev/null
+++ b/packages/PackageInstaller/res/values-watch/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Generic text to indicate a yes. [CHAR LIMIT=10] -->
+    <string name="generic_yes">Yes</string>
+
+    <!-- Generic text to indicate Cancel. [CHAR LIMIT=10] -->
+    <string name="generic_cancel">Cancel</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-watch/styles.xml b/packages/PackageInstaller/res/values-watch/styles.xml
new file mode 100644
index 0000000..805d43d
--- /dev/null
+++ b/packages/PackageInstaller/res/values-watch/styles.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <style name="BreadcrumbText" parent="@android:style/TextAppearance.Material.Body2"/>
+    <style name="TitleText" parent="@android:style/TextAppearance.Material.Subhead"/>
+</resources>
diff --git a/packages/PackageInstaller/res/values-watch/themes.xml b/packages/PackageInstaller/res/values-watch/themes.xml
new file mode 100644
index 0000000..5e52008
--- /dev/null
+++ b/packages/PackageInstaller/res/values-watch/themes.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+    <style name="DialogWhenLarge" parent="@android:style/Theme.DeviceDefault.NoActionBar"/>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zh-rCN-television/strings.xml b/packages/PackageInstaller/res/values-zh-rCN-television/strings.xml
new file mode 100644
index 0000000..9b43370
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zh-rCN-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"拒绝,不要再询问"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"您以后可以在“设置”&gt;“应用”中更改此设置"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"显示系统应用"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"应用权限"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"应用权限"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g>权限"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"其他权限"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g>权限"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zh-rCN-watch/strings.xml b/packages/PackageInstaller/res/values-zh-rCN-watch/strings.xml
new file mode 100644
index 0000000..2525619
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zh-rCN-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"拒绝,不要再询问"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"显示系统应用"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"无法更改"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"是"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"取消"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zh-rCN/strings.xml b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..d559774
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"软件包安装程序"</string>
+    <string name="next" msgid="3057143178373252333">"下一步"</string>
+    <string name="install" msgid="5896438203900042068">"安装"</string>
+    <string name="done" msgid="3889387558374211719">"完成"</string>
+    <string name="cancel" msgid="8360346460165114585">"取消"</string>
+    <string name="installing" msgid="8613631001631998372">"正在安装..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"正在安装<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"应用安装完成。"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"要安装此应用吗?它将获得以下权限:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"您要安装此应用吗?此应用不需要任何特殊权限。"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"您要安装此应用的新版本吗?您现有的数据不会丢失。更新后的应用将具备以下权限:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"您要安装此内置应用的新版本吗?您现有的数据不会丢失。更新后的应用将具备以下权限:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"是否要为这一现有应用安装更新?您现有的数据不会丢失,且安装过程无需任何特殊权限。"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"是否要为这一内置应用安装更新?您现有的数据不会丢失,且安装过程无需任何特殊权限。"</string>
+    <string name="install_failed" msgid="6579998651498970899">"应用未安装。"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"系统禁止安装该软件包。"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"应用未安装:软件包与现有软件包存在冲突。"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"应用未安装:应用与您的平板电脑不兼容。"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"此应用与您的电视不兼容。"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"应用未安装:应用与您的手机不兼容。"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"应用未安装:软件包似乎无效。"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"无法在您的平板电脑上安装“<xliff:g id="APP_NAME">%1$s</xliff:g>”。"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"无法将<xliff:g id="APP_NAME">%1$s</xliff:g>安装到您的电视上。"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"无法在您的手机上安装“<xliff:g id="APP_NAME">%1$s</xliff:g>”。"</string>
+    <string name="launch" msgid="4826921505917605463">"打开"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"您的管理员不允许安装来源不明的应用"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"该用户无法安装未知应用"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"此用户不能安装应用"</string>
+    <string name="ok" msgid="3468756155452870475">"确定"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"管理应用"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"没有存储空间"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"无法安装“<xliff:g id="APP_NAME">%1$s</xliff:g>”,请释放一些存储空间并重试。"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"未找到应用"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"未在已安装应用的列表中找到该应用。"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"不允许"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"当前用户无法执行这项卸载操作。"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"错误"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"无法卸载应用。"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"卸载应用"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"卸载更新"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>属于以下应用:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"要卸载此应用吗?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"是否要为"<b>"所有"</b>"用户卸载此应用?系统将为设备上的"<b>"所有"</b>"用户删除此应用及其数据。"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"您要为用户<xliff:g id="USERNAME">%1$s</xliff:g>卸载此应用吗?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"要将此应用替换为出厂版本吗?这样会移除所有数据。"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"要将此应用替换为出厂版本吗?这样会移除所有数据,并会影响此设备的所有用户(包括已设置工作资料的用户)。"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"进行中的卸载操作"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"失败的卸载操作"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"正在卸载..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"正在卸载<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"卸载完成。"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"已卸载<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"卸载失败。"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"卸载<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>失败。"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"无法卸载正在使用中的设备管理应用"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"无法为<xliff:g id="USERNAME">%1$s</xliff:g>卸载正在使用中的设备管理应用"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"这是部分用户或个人资料所需的应用;已为其他用户或个人资料卸载此应用"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"这是您的个人资料所需的应用,因此无法卸载。"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"这是您的设备管理员要求必须安装的应用,因此无法卸载。"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"管理设备管理应用"</string>
+    <string name="manage_users" msgid="3125018886835668847">"管理用户"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"无法卸载“<xliff:g id="APP_NAME">%1$s</xliff:g>”。"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"解析软件包时出现问题。"</string>
+    <string name="newPerms" msgid="6039428254474104210">"新权限"</string>
+    <string name="allPerms" msgid="1024385515840703981">"全部"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"隐私相关权限"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"设备相关权限"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"新版本不需要任何新的权限。"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"拒绝"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"详情"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"仍然拒绝"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"第 <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> 项权限(共 <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> 项)"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"要允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;<xliff:g id="ACTION">%2$s</xliff:g>吗?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"要一律允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;<xliff:g id="ACTION">%2$s</xliff:g>吗?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"仅限使用应用时"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"一律允许"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"拒绝,不要再询问"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> 项已停用"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"全部已停用"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"均未停用"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"允许"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"应用"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"应用权限"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"不再询问"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"没有权限"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"其他权限"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"打开应用信息"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"此应用专为旧版 Android 打造。拒绝权限可能会导致其无法正常运行。"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"执行未知操作"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"已授权 <xliff:g id="COUNT_0">%1$d</xliff:g> 个应用(共 <xliff:g id="COUNT_1">%2$d</xliff:g> 个)"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"显示系统应用"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"隐藏系统应用"</string>
+    <string name="no_apps" msgid="1965493419005012569">"没有应用"</string>
+    <string name="location_settings" msgid="1774875730854491297">"位置信息设置"</string>
+    <string name="location_warning" msgid="8778701356292735971">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”是此设备的一个位置信息服务提供程序。您可以在位置信息设置中修改位置信息使用权。"</string>
+    <string name="system_warning" msgid="7103819124542305179">"如果您拒绝此权限,您设备的基本功能可能会无法正常使用。"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"依据政策强制执行"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"已根据政策停用后台访问权限"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"已根据政策启用后台访问权限"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"已根据政策启用前台访问权限"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"由管理员控制"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"一律允许"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"仅限使用应用时"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"永不"</string>
+    <string name="loading" msgid="7811651799620593731">"正在加载…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"所有权限"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"其他应用功能"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"权限请求"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"检测到屏幕叠加层"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"要更改此权限设置,您必须首先在“设置”&gt;“应用”中关闭屏幕叠加层"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"打开设置"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear 不支持安装/卸载操作。"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"请选择要向&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;授予哪些权限"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;已更新。请选择要向此应用授予哪些权限。"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"取消"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"继续"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"新权限"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"当前权限"</string>
+    <string name="message_staging" msgid="6151794817691100003">"正在准备安装应用…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"未知"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"出于安全考虑,已禁止您的平板电脑安装来自此来源的未知应用。"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"出于安全考虑,已禁止您的电视安装来自此来源的未知应用。"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"出于安全考虑,已禁止您的手机安装来自此来源的未知应用。"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"来历不明的应用很可能会损害您的手机和个人数据。安装该应用即表示,您同意对于因使用该应用可能导致的任何手机损坏或数据丢失情况,您负有全部责任。"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"来历不明的应用很可能会损害您的平板电脑和个人数据。安装该应用即表示,您同意对于因使用该应用可能导致的任何平板电脑损坏或数据丢失情况,您负有全部责任。"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"来历不明的应用很可能会损害您的电视和个人数据。安装该应用即表示,您同意对于因使用该应用可能导致的任何电视损坏或数据丢失情况,您负有全部责任。"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"继续"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"设置"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"正在安装/卸载 Android Wear 应用"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zh-rHK-television/strings.xml b/packages/PackageInstaller/res/values-zh-rHK-television/strings.xml
new file mode 100644
index 0000000..52c3d30
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zh-rHK-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"拒絕,不要再問我"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"您日後可以在 [設定] &gt; [應用程式] 中變更這項設定"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"顯示系統應用程式"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"應用程式權限"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"應用程式權限"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g>權限"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"其他權限"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g>權限"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zh-rHK-watch/strings.xml b/packages/PackageInstaller/res/values-zh-rHK-watch/strings.xml
new file mode 100644
index 0000000..6d0226f
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zh-rHK-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"拒絕,不要再問我"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"顯示系統應用程式"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"不可變更"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"是"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"取消"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zh-rHK/strings.xml b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..0401eb1
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"程式安裝器"</string>
+    <string name="next" msgid="3057143178373252333">"下一步"</string>
+    <string name="install" msgid="5896438203900042068">"安裝"</string>
+    <string name="done" msgid="3889387558374211719">"完成"</string>
+    <string name="cancel" msgid="8360346460165114585">"取消"</string>
+    <string name="installing" msgid="8613631001631998372">"正在安裝..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"正在安裝 <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"已安裝應用程式。"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"您要安裝這個應用程式嗎?應用程式將取得以下存取權:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"您要安裝這個應用程式嗎?應用程式不需任何特殊存取權。"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"您要為這個現有的應用程式安裝更新嗎?您的現有資料將會喪失,更新後的應用程式將取得以下存取權:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"您要為這個內置的應用程式安裝更新嗎?您的現有資料將會喪失,更新後的應用程式將取得以下存取權:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"您要為這個現有的應用程式安裝更新嗎?您不會遺失現有的資料,而應用程式無需任何特殊的存取權限。"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"您要為這個內置應用程式安裝更新嗎?您不會遺失現有的資料,而應用程式無需任何特殊的存取權限。"</string>
+    <string name="install_failed" msgid="6579998651498970899">"未安裝應用程式。"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"套件已遭封鎖,無法安裝。"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"套件與現有的套件發生衝突,無法安裝應用程式。"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"應用程式與平板電腦不兼容,無法安裝應用程式。"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"此應用程式與您的電視不相容。"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"應用程式與手機不兼容,無法安裝應用程式。"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"套件好像無效,無法安裝應用程式。"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"無法在您的平板電腦上安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"無法在您的電視上安裝 <xliff:g id="APP_NAME">%1$s</xliff:g>。"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"無法在您的手機上安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
+    <string name="launch" msgid="4826921505917605463">"開啟"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"您的管理員不允許安裝來自不明來源的應用程式"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"此使用者無法安裝不明的應用程式"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"此使用者無法安裝應用程式"</string>
+    <string name="ok" msgid="3468756155452870475">"確定"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"管理應用程式"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"空間不足"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"無法解除安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。請先騰出一些空間,然後再試一次。"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"找不到應用程式"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"在已安裝的應用程式清單中找不到這個應用程式。"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"不允許"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"目前的使用者不允許執行這項解除安裝操作。"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"錯誤"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"應用程式無法解除安裝。"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"解除安裝應用程式"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"解除安裝更新"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"「<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>」隸屬於以下應用程式:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"您要解除安裝這個應用程式嗎?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"您要為"<b>"所有"</b>"使用者解除安裝這個應用程式嗎?應用程式及其資料會從裝置上的"<b>"所有"</b>"使用者設定檔中移除。"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"您要為使用者 <xliff:g id="USERNAME">%1$s</xliff:g> 解除安裝這個應用程式嗎?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"要將此應用程式回復至原廠版本嗎?所有資料將會刪除。"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"要將此應用程式回復至原廠版本嗎?所有資料將會刪除,此裝置的所有使用者 (包括使用工作設定檔的使用者) 亦會受影響。"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"正在執行的解除安裝操作"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"失敗的解除安裝操作"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"正在解除安裝..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"正在解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"完成解除安裝。"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"已解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"解除安裝失敗。"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」失敗。"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"無法解除安裝可用的裝置管理員應用程式"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"無法為<xliff:g id="USERNAME">%1$s</xliff:g>解除安裝可用的裝置管理員應用程式"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"這是部分使用者或設定檔所需的應用程式,其他使用者或設定檔已解除安裝此應用程式"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"這是您設定檔所需的應用程式,因此無法解除安裝。"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"這是您的裝置管理員要求安裝的應用程式,因此無法解除安裝。"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"管理裝置管理員應用程式"</string>
+    <string name="manage_users" msgid="3125018886835668847">"管理使用者"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"無法解除安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"剖析套件時發生問題。"</string>
+    <string name="newPerms" msgid="6039428254474104210">"新增"</string>
+    <string name="allPerms" msgid="1024385515840703981">"全部"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"私隱權"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"裝置存取權"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"這項更新不需新權限。"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"拒絕"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"更多資訊"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"一律拒絕"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"第 <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> 個 (共 <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> 個)"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<xliff:g id="ACTION">%2$s</xliff:g>嗎?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"要一律允許「<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt;&lt;/b&gt;」<xliff:g id="ACTION">%2$s</xliff:g>嗎?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"只在使用應用程式時"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"一律"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"拒絕,不要再詢問"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> 個權限已停用"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"所有權限已停用"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"沒有權限已停用"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"允許"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"應用程式"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"應用程式權限"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"不要再問我"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"沒有權限"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"其他權限"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"打開應用程式資料"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"這個應用程式專為舊版本的 Android 設計。拒絕權限可能會導致它無法如預期 運作。"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"執行不明的操作"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"已允許 <xliff:g id="COUNT_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="COUNT_1">%2$d</xliff:g> 個)"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"顯示系統"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"隱藏系統"</string>
+    <string name="no_apps" msgid="1965493419005012569">"沒有應用程式"</string>
+    <string name="location_settings" msgid="1774875730854491297">"位置設定"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g>為此裝置提供位置資訊服務。您可以在位置設定中更改位置存取權。"</string>
+    <string name="system_warning" msgid="7103819124542305179">"如果您拒絕這個權限,您的裝置的基本功能可能無法正常運作。"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"由政策強制執行"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"已根據政策停用背景存取權"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"已根據政策啟用背景存取權"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"已根據政策啟用前景存取權"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"由管理員控制"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"一律"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"只在使用應用程式時"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"永不"</string>
+    <string name="loading" msgid="7811651799620593731">"正在載入…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"所有權限"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"其他應用程式功能"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"權限要求"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"已偵測到螢幕重疊功能"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"如要變更此權限設定,請先前往 [設定] &gt; [應用程式],以關閉螢幕重疊功能"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"開啟設定"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear 不支援安裝/解除安裝操作。"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"選擇允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取的內容"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"已更新「<xliff:g id="APP_NAME">%1$s</xliff:g>」。選擇允許此應用程式存取的內容。"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"取消"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"繼續"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"新權限"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"目前權限"</string>
+    <string name="message_staging" msgid="6151794817691100003">"正在準備安裝應用程式…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"不明"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"為安全起見,您的平板電腦不得安裝此來源的不明應用程式。"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"為安全起見,您的電視不得安裝此來源的不明應用程式。"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"為安全起見,您的手機不得安裝此來源的不明應用程式。"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"來源不明的應用程式可能會侵害您的手機和個人資料。安裝此應用程式,即表示您同意承擔因使用這個應用程式而導致手機損壞或資料遺失的責任。"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"來源不明的應用程式可能會侵害您的平板電腦和個人資料。安裝此應用程式,即表示您同意承擔因使用這個應用程式而導致平板電腦損壞或資料遺失的責任。"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"來源不明的應用程式可能會侵害您的電視和個人資料。安裝此應用程式,即表示您同意承擔因使用這個應用程式而導致電視損壞或資料遺失的責任。"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"繼續"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"設定"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"正在安裝/解除安裝 Wear 應用程式"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zh-rTW-television/strings.xml b/packages/PackageInstaller/res/values-zh-rTW-television/strings.xml
new file mode 100644
index 0000000..59266f9
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zh-rTW-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"拒絕且不要再詢問"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"你日後可在 [設定] &gt; [應用程式] 中進行變更"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"顯示系統應用程式"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"應用程式權限"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"應用程式權限"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g>權限"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"其他權限"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g>權限"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zh-rTW-watch/strings.xml b/packages/PackageInstaller/res/values-zh-rTW-watch/strings.xml
new file mode 100644
index 0000000..edaf7ea
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zh-rTW-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"拒絕且不要再詢問"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"顯示系統應用程式"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"無法變更"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"是"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"取消"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zh-rTW/strings.xml b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..db96924
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"程式安裝器"</string>
+    <string name="next" msgid="3057143178373252333">"下一步"</string>
+    <string name="install" msgid="5896438203900042068">"安裝"</string>
+    <string name="done" msgid="3889387558374211719">"完成"</string>
+    <string name="cancel" msgid="8360346460165114585">"取消"</string>
+    <string name="installing" msgid="8613631001631998372">"安裝中…"</string>
+    <string name="installing_app" msgid="4097935682329028894">"正在安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」…"</string>
+    <string name="install_done" msgid="3682715442154357097">"已安裝應用程式。"</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"你要安裝這個應用程式嗎?應用程式將取得以下權限:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"你要安裝這個應用程式嗎?應用程式不需任何特殊權限。"</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"你要為這個現有的應用程式安裝更新嗎?你的現有資料不會遺失,而更新後的應用程式將取得以下權限:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"你要為這個內建的應用程式安裝更新嗎?你的現有資料不會遺失,而更新後的應用程式將取得以下權限:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"你要為這個現有的應用程式安裝更新嗎?你不會遺失現有的資料,且應用程式不需任何特殊權限。"</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"你要為這個現有的內建應用程式安裝更新嗎?你不會遺失現有的資料,且應用程式不需任何特殊權限。"</string>
+    <string name="install_failed" msgid="6579998651498970899">"未安裝應用程式。"</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"這個套件已遭到封鎖,因此無法安裝。"</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"應用程式套件與現有套件衝突,因此未能完成安裝。"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"應用程式與你的平板電腦不相容,因此未能完成安裝。"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"這個應用程式與你的電視不相容。"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"應用程式與你的手機不相容,因此未能完成安裝。"</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"應用程式套件無效,因此未能完成安裝。"</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"無法在你的平板電腦上安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"無法在你的電視上安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"無法在你的手機上安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
+    <string name="launch" msgid="4826921505917605463">"開啟"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"你的管理員不允許安裝來源不明的應用程式"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"這位使用者無法安裝不明的應用程式"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"這位使用者無法安裝應用程式"</string>
+    <string name="ok" msgid="3468756155452870475">"確定"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"管理應用程式"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"空間不足"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"無法安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。請先釋出部分空間,然後再試一次。"</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"找不到應用程式"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"在已安裝的應用程式清單中找不到這個應用程式。"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"不允許此操作"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"目前的使用者無法執行這項解除安裝作業。"</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"發生錯誤"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"無法解除安裝應用程式。"</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"解除安裝應用程式"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"解除安裝更新"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"「<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>」屬於下列應用程式:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"你要解除安裝這個應用程式嗎?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"你要為"<b>"所有"</b>"使用者解除安裝這個應用程式嗎?該應用程式及其資料會從裝置上的"<b>"所有"</b>"使用者設定檔移除。"</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"你要為使用者 <xliff:g id="USERNAME">%1$s</xliff:g> 解除安裝這個應用程式嗎?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"要將應用程式換成原廠版本嗎?這麼做會移除所有資料。"</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"要將應用程式換成原廠版本嗎?這麼做會移除所有資料。凡是這個裝置的使用者 (包括設置工作資料夾的使用者),皆會受到影響。"</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"執行中的解除安裝作業"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"失敗的解除安裝作業"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"解除安裝中…"</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"正在解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"解除安裝完成。"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"已解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"解除安裝失敗。"</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"無法解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」。"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"無法解除安裝使用中的裝置管理員應用程式"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"無法為<xliff:g id="USERNAME">%1$s</xliff:g>解除安裝使用中的裝置管理員應用程式"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"部分使用者或設定檔需要使用這個應用程式;已為其他使用者解除安裝"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"你的設定檔需要使用這個應用程式,因此無法解除安裝。"</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"這是你的裝置管理員要求安裝的應用程式,因此無法解除安裝。"</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"管理裝置管理員應用程式"</string>
+    <string name="manage_users" msgid="3125018886835668847">"管理使用者"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"無法解除安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"剖析套件時發生問題。"</string>
+    <string name="newPerms" msgid="6039428254474104210">"新增"</string>
+    <string name="allPerms" msgid="1024385515840703981">"全部"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"隱私權"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"裝置存取權"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"這項更新不需新權限。"</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"拒絕"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"瞭解詳情"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"直接拒絕"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<xliff:g id="ACTION">%2$s</xliff:g>嗎?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"要一律允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<xliff:g id="ACTION">%2$s</xliff:g>嗎?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"僅限使用應用程式時"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"一律允許"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"拒絕且不要再詢問"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"已停用 <xliff:g id="COUNT">%1$d</xliff:g> 項權限"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"已停用所有權限"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"未停用任何權限"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"允許"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"應用程式"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"應用程式權限"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"不要再詢問"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"沒有權限"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"其他權限"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"開啟應用程式資訊"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <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>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"這個應用程式是為舊版 Android 所開發。拒絕授予權限可能導致應用程式無法正常運作。"</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"執行不明的動作"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"已授權 <xliff:g id="COUNT_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="COUNT_1">%2$d</xliff:g> 個)"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"顯示系統"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"隱藏系統"</string>
+    <string name="no_apps" msgid="1965493419005012569">"沒有應用程式"</string>
+    <string name="location_settings" msgid="1774875730854491297">"位置資訊設定"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> 是這台裝置的定位服務供應商。你可以在位置資訊設定中修改位置資訊存取權。"</string>
+    <string name="system_warning" msgid="7103819124542305179">"如果你拒絕這項權限,裝置的基本功能可能無法正常運作。"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"依據政策規定執行"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"已根據政策停用背景存取權"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"已根據政策啟用背景存取權"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"已根據政策啟用前景存取權"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"由管理員控管"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"一律允許"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"僅限使用應用程式時"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"永不"</string>
+    <string name="loading" msgid="7811651799620593731">"載入中…"</string>
+    <string name="all_permissions" msgid="5156669007784613042">"所有權限"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"其他應用程式功能"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"權限要求"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"偵測到畫面重疊圖層"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"如要變更這項權限設定,你必須先依序前往 [設定] &gt; [應用程式],關閉裝置畫面重疊圖層"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"開啟設定"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Wear 不支援安裝及解除安裝操作。"</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"選擇要將哪些存取權限授予「<xliff:g id="APP_NAME">%1$s</xliff:g>」"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」已更新。請選擇要將哪些存取權限授予這個應用程式。"</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"取消"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"繼續"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"新權限"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"目前權限"</string>
+    <string name="message_staging" msgid="6151794817691100003">"正在啟動應用程式安裝程序…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"不明"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"為了安全起見,你的平板電腦禁止安裝這個來源提供的不明應用程式。"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"為了安全起見,你的電視禁止安裝這個來源提供的不明應用程式。"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"為了安全起見,你的手機禁止安裝這個來源提供的不明應用程式。"</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"來歷不明的應用程式可能會損害你的手機和個人資料。如因安裝及使用這個應用程式,導致你的手機受損或資料遺失,請自行負責。"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"來歷不明的應用程式可能會損害你的平板電腦和個人資料。如因安裝及使用這個應用程式,導致你的平板電腦受損或資料遺失,請自行負責。"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"來歷不明的應用程式可能會損害你的電視和個人資料。如因安裝及使用這個應用程式,導致你的電視受損或資料遺失,請自行負責。"</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"繼續"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"設定"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"安裝/解除安裝 Wear 應用程式"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zu-television/strings.xml b/packages/PackageInstaller/res/values-zu-television/strings.xml
new file mode 100644
index 0000000..a07ad2e
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zu-television/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5694574989758145558">"Yenqaba futhi ungasabuzi"</string>
+    <string name="grant_dialog_how_to_change" msgid="615414835189256888">"Ungashintsha lokhu kamuva kuzilungiselelo &gt; izinhlelo zokusebenza"</string>
+    <string name="current_permission_template" msgid="4793247012451594523">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7330308025768596149">"Bonisa izinhlelo zokusebenza zesistimu"</string>
+    <string name="app_permissions_decor_title" msgid="1461057434211920209">"Izimvume zohlelo lokusebenza"</string>
+    <string name="manage_permissions_decor_title" msgid="4823785025722958092">"Izimvume zohlelo lokusebenza"</string>
+    <string name="permission_apps_decor_title" msgid="3644363529649579576">"<xliff:g id="PERMISSION">%1$s</xliff:g> izimvume"</string>
+    <string name="additional_permissions_decor_title" msgid="7000432624396037882">"Izimvume ezingeziwe"</string>
+    <string name="system_apps_decor_title" msgid="5292119639812561805">"<xliff:g id="PERMISSION">%1$s</xliff:g> izimvume"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zu-watch/strings.xml b/packages/PackageInstaller/res/values-zu-watch/strings.xml
new file mode 100644
index 0000000..38fe1c8
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zu-watch/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="grant_dialog_button_deny_dont_ask_again" msgid="5828565432145544298">"Yenqaba, ungangibuzi futhi"</string>
+    <string name="current_permission_template" msgid="6691830243038105737">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="preference_show_system_apps" msgid="7042886929865431207">"Bonisa izinhlelo zokusebenza zesistimu"</string>
+    <string name="permission_summary_enforced_by_policy" msgid="9002523259681588936">"Akukwazi ukushintshwa"</string>
+    <string name="generic_yes" msgid="3394094077553763689">"Yebo"</string>
+    <string name="generic_cancel" msgid="6384078447202012984">"Khansela"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-zu/strings.xml b/packages/PackageInstaller/res/values-zu/strings.xml
new file mode 100644
index 0000000..6ece479
--- /dev/null
+++ b/packages/PackageInstaller/res/values-zu/strings.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="2738748390251381682">"Isifaki sephakheji"</string>
+    <string name="next" msgid="3057143178373252333">"Okulandelayo"</string>
+    <string name="install" msgid="5896438203900042068">"Faka"</string>
+    <string name="done" msgid="3889387558374211719">"Kwenziwe"</string>
+    <string name="cancel" msgid="8360346460165114585">"Khansela"</string>
+    <string name="installing" msgid="8613631001631998372">"Iyafaka..."</string>
+    <string name="installing_app" msgid="4097935682329028894">"Ifaka i-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="install_done" msgid="3682715442154357097">"I-App ifakiwe."</string>
+    <string name="install_confirm_question" msgid="7295206719219043890">"Ngabe ufuna ukufaka lolu hlelo lokusebenza? Lizothola ukufinyelela ku:"</string>
+    <string name="install_confirm_question_no_perms" msgid="5918305641302873520">"Ngabe ufuna ukufaka lolu hlelo lokusebenza? Alidingi ukufinyelela okukhethekile."</string>
+    <string name="install_confirm_question_update" msgid="4624159567361487964">"Ngabe ufuna ukufaka isibuyekezo ohlelweni lokusebenza olukhona? Idatha yakho ekhona izolahleka. Uhlelo lokusebenza olubuyekeziwe lizothola ukufinyelela ku:"</string>
+    <string name="install_confirm_question_update_system" msgid="1302330093676416336">"Ngabe ufuna ukufaka isibuyekezo kulolu hlelo lokusebenza olakhelwe phakathi? Idatha yakho ekhona izolahleka. Uhlelo lokusebenza olubuyekeziwe luzothola ukufinyelela ku:"</string>
+    <string name="install_confirm_question_update_no_perms" msgid="4885928136844618944">"Ingabe ufuna ukufaka isibuyekezo kulolu hlelo lokusebenza olukhona? Idatha yakho ekhona ngeke ilahleke. Akudingi ukufinyelela okukhethekile."</string>
+    <string name="install_confirm_question_update_system_no_perms" msgid="7676593512694724374">"Ungabe ufuna ukukhipha isibuyekezo kulolu hlelo lokusebenza olakhelwe ngaphakathi? Idatha yakho ekhona ngeke ilahleke. Akudingi ukufinyelela okukhethekile."</string>
+    <string name="install_failed" msgid="6579998651498970899">"I-app ayifakiwe."</string>
+    <string name="install_failed_blocked" msgid="1606870930588770025">"Iphakheji livinjiwe kusukela ekufakweni."</string>
+    <string name="install_failed_conflict" msgid="5336045235168070954">"Uhlelo lokusebenza alufakiwe njengoba ukuphakheja kushayisana nephakheji elikhona."</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6682387386242708974">"Uhlelo lokusebenza alufakiwe njengoba uhlelo lokusebenza lungahambisani nethebulethi yakho."</string>
+    <string name="install_failed_incompatible" product="tv" msgid="3553367270510072729">"Lolu hlelo lokusebenza aluhambisani ne-TV yakho."</string>
+    <string name="install_failed_incompatible" product="default" msgid="7917996365659426872">"Uhlelo lokusebenza alufakiwe njengoba uhlelo lokusebenza lungahambisani nefoni yakho."</string>
+    <string name="install_failed_invalid_apk" msgid="269885385245534742">"Uhlelo lokusebenza alufakiwe njengoba iphakheji ibonakala ingavumelekile."</string>
+    <string name="install_failed_msg" product="tablet" msgid="8368835262605608787">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayikwazanga ukufakwa kuthebhulethi."</string>
+    <string name="install_failed_msg" product="tv" msgid="3990457938384021566">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayikwazanga ukufakwa ku-TV yakho."</string>
+    <string name="install_failed_msg" product="default" msgid="8554909560982962052">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayikwazanga ukufakwa efonini."</string>
+    <string name="launch" msgid="4826921505917605463">"Vula"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="7488386758312008790">"Umlawuli wakho akavumeli ukufakwa kwezinhlelo zokusebenza ezitholwe kusukela kumithombo engaziwa"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="5785226253054083336">"Izinhlelo zokusebenza ezingaziwa azikwazi ukufakwa ilo msebenzisi"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="5041150186260066212">"Lo msebenzisi akavunyelwe ukufaka izinhlelo zokusebenza"</string>
+    <string name="ok" msgid="3468756155452870475">"KULUNGILE"</string>
+    <string name="manage_applications" msgid="4033876279091996596">"Phatha izinhlelo zokusebenza"</string>
+    <string name="out_of_space_dlg_title" msgid="7843674437613797326">"Iphelelwe yisikhala"</string>
+    <string name="out_of_space_dlg_text" msgid="4774775404294282216">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayikwazanga ukufakwa. Khulula isikhala bese uzama futhi."</string>
+    <string name="app_not_found_dlg_title" msgid="2692335460569505484">"I-App ayitholakalanga"</string>
+    <string name="app_not_found_dlg_text" msgid="6107465056055095930">"Uhlelo lokusebenza alutholakalanga ohlwini lwezinhlelo zokusebenza ezifakiwe."</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="118128026847201582">"Akuvumelekile"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="739716827677987545">"Umsebenzisi wamanje akavunyelwe ukwenza lokhu kukhipha."</string>
+    <string name="generic_error_dlg_title" msgid="2684806600635296961">"Iphutha"</string>
+    <string name="generic_error_dlg_text" msgid="4288738047825333954">"Amafu ohlelo lokusebenza angakhishwa."</string>
+    <string name="uninstall_application_title" msgid="1860074100811653963">"Khipha i-app"</string>
+    <string name="uninstall_update_title" msgid="4146940097553335390">"Khipha isibuyekezo"</string>
+    <string name="uninstall_activity_text" msgid="6680688689803932550">"I-<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ingxenye yohlelo lokusebenza olulandelayo:"</string>
+    <string name="uninstall_application_text" msgid="6691975835951187030">"Ufuna ukukhipha le-app?"</string>
+    <string name="uninstall_application_text_all_users" msgid="5574704453233525222">"Ingabe ufuna ukukhipha lolu hlelo lokusebenza kubo "<b>"bonke"</b>" abasebenzisi? Uhlelo lokusebenza nedatha yalo kuzosuswa kubo "<b>"bonke"</b>" abasebenzisi kudivayisi."</string>
+    <string name="uninstall_application_text_user" msgid="8766882355635485733">"Ingabe ufuna ukukhiphela lolu hlelo lokusebenza kumsebenzisi ongu-<xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
+    <string name="uninstall_update_text" msgid="1394549691152728409">"Shintshanisa lolu hlelo lokusebenza ngenguqulo yasekuqaleni? Yonke idatha izosuswa."</string>
+    <string name="uninstall_update_text_multiuser" msgid="2083665452990861991">"Shintshanisa lolu hlelo lokusebenza ngenguqulo yasekuqaleni? Yonke idatha izosuswa. Lokhu kuthinta bonke abasebenzisi bale divayisi, abafaka labo abanamaphrofayela wokusebenza."</string>
+    <string name="uninstalling_notification_channel" msgid="5698369661583525583">"Ukukhishwa okuqhubekayo"</string>
+    <string name="uninstall_failure_notification_channel" msgid="8224276726364132314">"Ukukhishwa okuhlulekile"</string>
+    <string name="uninstalling" msgid="5556217435895938250">"Iyakhipha..."</string>
+    <string name="uninstalling_app" msgid="2773617614877719294">"Ikhipha i-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
+    <string name="uninstall_done" msgid="3792487853420281888">"Ukukhipha kuqedile"</string>
+    <string name="uninstall_done_app" msgid="775837862728680479">"Kukhishwe i-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="uninstall_failed" msgid="631122574306299512">"Ukukhipha akuphumelelanga."</string>
+    <string name="uninstall_failed_app" msgid="945277834056527022">"Ukukhipha i-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> akuphumelele."</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="2727361164694743362">"Ayikwazi ukukhipha uhlelo lokusebenza lomlawuli ledivayisi esebenzayo"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="2161462242935805756">"Ayikwazi ukukhipha uhlelo lokusebenza lomlawuli ledivayisi esebenzayo lika-<xliff:g id="USERNAME">%1$s</xliff:g>"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="3544933038594382346">"Lolu hlelo lokusebenza luyadingeka kwabanye abasebenzisi noma amaphrofayela futhi lukhishelwe abanye"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6912141045528994954">"Lolu hlelo lokusebenza ludingelwa iphrofayela yakho futhi alikwazi ukukhishwa."</string>
+    <string name="uninstall_blocked_device_owner" msgid="7074175526413453063">"Lolu hlelo lokusebenza ludingwa umlawuli wedivayisi yakho futhi alukwazi ukukhishwa."</string>
+    <string name="manage_device_administrators" msgid="118178632652346535">"Phatha izinhlelo zokusebenza zedivayisi yomlawuli"</string>
+    <string name="manage_users" msgid="3125018886835668847">"Phatha abasebenzisi"</string>
+    <string name="uninstall_failed_msg" msgid="8969754702803951175">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayikwazanga ukukhishwa"</string>
+    <string name="Parse_error_dlg_text" msgid="7623286983621067011">"Kube nenkinga yokwehlukanisa iphakheji."</string>
+    <string name="newPerms" msgid="6039428254474104210">"Okusha"</string>
+    <string name="allPerms" msgid="1024385515840703981">"Konke"</string>
+    <string name="privacyPerms" msgid="1850527049572617">"Ubumfihlo"</string>
+    <string name="devicePerms" msgid="6733560207731294504">"Ukufinyelela kwedivayisi"</string>
+    <string name="no_new_perms" msgid="6657813692169565975">"Lesi sibuyekezo asidingi zimvume."</string>
+    <string name="grant_dialog_button_deny" msgid="2176510645406614340">"Phika"</string>
+    <string name="grant_dialog_button_more_info" msgid="2218220771432058426">"Olunye ulwazi"</string>
+    <string name="grant_dialog_button_deny_anyway" msgid="847960499284125250">"Yenqaba noma kunjalo"</string>
+    <string name="current_permission_template" msgid="6378304249516652817">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> kokungu-<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
+    <string name="permission_warning_template" msgid="7332275268559121742">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="permission_add_background_warning_template" msgid="5391175001698541141">"Njalo vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukwenza <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+    <string name="allow_permission_foreground_only" msgid="1016389465002335286">"Kuphela ngenkathi usebenzisa uhlelo lokusebenza"</string>
+    <string name="allow_permission_always" msgid="7047379650123289823">"Njalo"</string>
+    <string name="deny_permission_deny_and_dont_ask_again" msgid="8003202275002645629">"Yenqaba futhi ungasabuzi"</string>
+    <string name="permission_revoked_count" msgid="7386129423432613024">"<xliff:g id="COUNT">%1$d</xliff:g> kukhutshaziwe"</string>
+    <string name="permission_revoked_all" msgid="8595742638132863678">"konke kukhutshaziwe"</string>
+    <string name="permission_revoked_none" msgid="2059511550181271342">"Lutho olukhutshaziwe"</string>
+    <string name="grant_dialog_button_allow" msgid="4616529495342337095">"Vumela"</string>
+    <string name="app_permissions_breadcrumb" msgid="3390836200791539264">"Izinhlelo zokusebenza"</string>
+    <string name="app_permissions" msgid="3146758905824597178">"Izimvume zohlelo lokusebenza"</string>
+    <string name="never_ask_again" msgid="1089938738199748687">"Ungaphindi ubuze"</string>
+    <string name="no_permissions" msgid="3210542466245591574">"Akukho zimvume"</string>
+    <string name="additional_permissions" msgid="6667573114240111763">"Izimvume ezingeziwe"</string>
+    <string name="app_permissions_info_button_label" msgid="7789812060395257748">"Vula ulwazi lohlelo lokusebenza"</string>
+    <plurals name="additional_permissions_more" formatted="false" msgid="945127158155064388">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> okuningi</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> okuningi</item>
+    </plurals>
+    <string name="old_sdk_deny_warning" msgid="3872277112584842615">"Lolu hlelo lokusebenza ludizayinelwe inguqulo endala ye-Android. Ukwala imvume kungalibangela ukuthi lingasasebenzi njengoba kuhlosiwe."</string>
+    <string name="default_permission_description" msgid="4992892207044156668">"Yenza isenzo esingaziwa"</string>
+    <string name="app_permissions_group_summary" msgid="4787239772223699263">"<xliff:g id="COUNT_0">%1$d</xliff:g> kuzinhlelo zokusebenza ezingu-<xliff:g id="COUNT_1">%2$d</xliff:g> ezivunyelwe"</string>
+    <string name="menu_show_system" msgid="6773743421743728921">"Bonisa isistimu"</string>
+    <string name="menu_hide_system" msgid="7595471742649432977">"Fihla isistimu"</string>
+    <string name="no_apps" msgid="1965493419005012569">"Azikho izinhlelo zokusebenza"</string>
+    <string name="location_settings" msgid="1774875730854491297">"Izilungiselelo Zendawo"</string>
+    <string name="location_warning" msgid="8778701356292735971">"<xliff:g id="APP_NAME">%1$s</xliff:g> ingumhlinzeki wamasevisi wendawo kule divayisi. Ukufinyelela kwendawo kungashintshwa kusuka kuzilungiselelo zendawo."</string>
+    <string name="system_warning" msgid="7103819124542305179">"Uma unqabela le mvume, izici eziyisisekelo zedivayisi yakho zingahle zingasasebenzi njengoba zihlosiwe."</string>
+    <string name="permission_summary_enforced_by_policy" msgid="3418617316188986205">"Isetshenziswe yinqubomgomo"</string>
+    <string name="permission_summary_disabled_by_policy_background_only" msgid="160007162349980265">"Ukufinyelela kwangemuva kukhutshazwe inqubomgomo"</string>
+    <string name="permission_summary_enabled_by_policy_background_only" msgid="4834971700297385342">"Ukufinyelela kwangemuva kunikwe amandla ngenqubomgomo"</string>
+    <string name="permission_summary_enabled_by_policy_foreground_only" msgid="5150061275247925588">"Ukufinyelela kwangaphambili kunikwe amandla ngenqubomgomo"</string>
+    <string name="permission_summary_enforced_by_admin" msgid="1702707982488952544">"Kulawulwa umqondisi"</string>
+    <!-- no translation found for background_access_chooser_dialog_choices:0 (7142769853837915143) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:1 (7804653189249679164) -->
+    <!-- no translation found for background_access_chooser_dialog_choices:2 (1131794379787779680) -->
+    <string name="permission_access_always" msgid="5642491469836594184">"Njalo"</string>
+    <string name="permission_access_only_foreground" msgid="6906814759741316041">"Kuphela ngenkathi usebenzisa uhlelo lokusebenza"</string>
+    <string name="permission_access_never" msgid="1258330706341318622">"Soze"</string>
+    <string name="loading" msgid="7811651799620593731">"Iyalayisha..."</string>
+    <string name="all_permissions" msgid="5156669007784613042">"Zonke izimvume"</string>
+    <string name="other_permissions" msgid="2016192512386091933">"Amanye amakhono wohlelo lokusebenza"</string>
+    <string name="permission_request_title" msgid="1204446718549121199">"Isicelo semvume"</string>
+    <string name="screen_overlay_title" msgid="3021729846864038529">"Kutholwe imbondela yesikrini"</string>
+    <string name="screen_overlay_message" msgid="2141944461571677331">"Ukuze uguqule lesi silungiselelo semvume, kuzomele uqale uvale imbondela yesikrini kusukela ku-Izilungiselelo &gt; Izinhlelo zokusebenza"</string>
+    <string name="screen_overlay_button" msgid="4344544843349937743">"Vula izilungiselelo"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8104666773577525713">"I-Android Wear"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="1322352525843583064">"Izenzo zokufaka/ukukhipha azisekelwe ku-Wear."</string>
+    <string name="permission_review_title_template_install" msgid="6819338441305295479">"Khetha ukuthi uzovumela ini ukuthi i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifinyelele kuyo"</string>
+    <string name="permission_review_title_template_update" msgid="8632233603161669426">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ibuyekeziwe. Khetha ukuthi uzovumela ini ukuthi ifinyelelwe ilolu hlelo lokusebenza."</string>
+    <string name="review_button_cancel" msgid="957906817733578877">"Khansela"</string>
+    <string name="review_button_continue" msgid="4809162078179371370">"Qhubeka"</string>
+    <string name="new_permissions_category" msgid="3213523410139204183">"Izimvume ezintsha"</string>
+    <string name="current_permissions_category" msgid="998210994450606094">"Izimvume zamanje"</string>
+    <string name="message_staging" msgid="6151794817691100003">"Ifaka kusiteji uhlelo lokusebenza…"</string>
+    <string name="app_name_unknown" msgid="8931522764510159105">"Akwaziwa"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="1483151219938173935">"Ukuze uvikelwe, ithebulethi yakho ayivunyelwe ukuthi ifake izinhlelo zokusebenza ezingaziwa kusukela kulo mthombo."</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="5373768281884328560">"Ukuze uvikelwe, i-TV yakho ayivunyelwe ukuthi ifake izinhlelo zokusebenza ezingaziwa kusukela kulo mthombo."</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="2223486836232706553">"Ukuze uvikelwe, ifoni yakho ayivunyelwe ukuthi ifake izinhlelo zokusebenza kusukela kulo mthombo."</string>
+    <string name="anonymous_source_warning" product="default" msgid="7700263729981815614">"Idatha yakho yefoni neyohlelo lwakho lokusebenza isengcupheni kakhulu ekuhlaselweni izinhlelo zokusebenza ezingaziwa. Ngokufaka lolu hlelo lokusebenza, uyavuma ukuthi unesibopho sanoma ikuphi ukonakala kufoni yakho noma ukulahlekelwa kwedatha okungabangelwa ukusetshenziswa kwayo."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="8854462805499848630">"Ithebulethi yakho nedatha yomuntu siqu zisengcupheni kakhulu ekuhlaselweni izinhlelo zokusebenza ezingaziwa. Ngokufaka lolu hlelo lokusebenza, uyavuma ukuthi unesibopho sanoma ikuphi ukonakala kuthebulethi yakho noma ukulahleka kwedatha okungabangelwa ukusetshenziswa kwayo."</string>
+    <string name="anonymous_source_warning" product="tv" msgid="1291472686734385872">"Idatha yakho ye-TV neyomuntu siqu isengcupheni kakhulu ekuhlaselweni izinhlelo zokusebenza ezingaziwa. Ngokufaka lolu hlelo lokusebenza, uyavuma ukuthi unesibopho sanoma ikuphi ukonakala ku-TV yakho noma ukulahlekelwa kwedatha okungabangelwa ukusetshenziswa kwayo."</string>
+    <string name="anonymous_source_continue" msgid="2094381167954332292">"Qhubeka"</string>
+    <string name="external_sources_settings" msgid="8601453744517291632">"Izilungiselelo"</string>
+    <string name="wear_app_channel" msgid="6200840123672949356">"Ifaka/ikhipha izinhlelo zokusebenza ze-wear"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values/attrs.xml b/packages/PackageInstaller/res/values/attrs.xml
new file mode 100644
index 0000000..e220f4c
--- /dev/null
+++ b/packages/PackageInstaller/res/values/attrs.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <!-- START: Ported from WearableSupport -->
+    <declare-styleable name="CircledImageView">
+        <attr name="android:src" />
+        <attr name="circle_color" format="color" />
+        <attr name="circle_radius" format="dimension" />
+        <attr name="circle_radius_pressed" format="dimension" />
+        <attr name="circle_border_width" format="dimension" />
+        <attr name="circle_border_color" format="color" />
+        <attr name="circle_padding" format="dimension" />
+        <attr name="shadow_width" format="dimension" />
+        <attr name="image_circle_percentage" format="dimension" />
+        <attr name="image_horizontal_offcenter_percentage" format="dimension" />
+        <attr name="image_tint" format="color" />
+        <attr name="circle_radius_percent" format="fraction" />
+        <attr name="circle_radius_pressed_percent" format="fraction" />
+    </declare-styleable>
+    <!-- END: Ported from WearableSupport -->
+</resources>
diff --git a/packages/PackageInstaller/res/values/colors.xml b/packages/PackageInstaller/res/values/colors.xml
new file mode 100644
index 0000000..01a0c9a
--- /dev/null
+++ b/packages/PackageInstaller/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?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>
+    <color name="bigIconColor">#C8CCCE</color>
+</resources>
diff --git a/packages/PackageInstaller/res/values/dimens.xml b/packages/PackageInstaller/res/values/dimens.xml
new file mode 100644
index 0000000..112723f
--- /dev/null
+++ b/packages/PackageInstaller/res/values/dimens.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <!-- Header sub settings margin start / end -->
+    <dimen name="header_subsettings_margin_start">72dp</dimen>
+    <dimen name="header_subsettings_margin_end">16dp</dimen>
+
+    <!-- Header margin start / end -->
+    <dimen name="header_margin_start">16dp</dimen>
+    <dimen name="header_margin_end">16dp</dimen>
+
+    <dimen name="lb_action_section_width">384dp</dimen>
+
+    <dimen name="lb_content_section_width">576dp</dimen>
+    <dimen name="lb_content_fragment_start_padding">48dp</dimen>
+    <dimen name="lb_content_fragment_delimiter_padding">16dp</dimen>
+    <dimen name="lb_content_fragment_max_icon_height">280dp</dimen>
+    <dimen name="lb_content_fragment_title_text_top_padding">2dp</dimen>
+    <dimen name="lb_content_fragment_title_text_size">36sp</dimen>
+    <dimen name="lb_content_fragment_icon_width">140dp</dimen>
+
+    <dimen name="lb_content_fragment_breadcrumb_text_size">18sp</dimen>
+    <dimen name="lb_content_fragment_description_text_size">14sp</dimen>
+    <dimen name="lb_content_fragment_title_text_bottom_padding">4dp</dimen>
+
+    <dimen name="headerElevation">8dp</dimen>
+
+    <dimen name="wear_permission_review_pref_padding">8dp</dimen>
+    <dimen name="wear_permission_review_icon_size">24dp</dimen>
+</resources>
diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml
new file mode 100644
index 0000000..ba81278
--- /dev/null
+++ b/packages/PackageInstaller/res/values/strings.xml
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- [CHAR LIMIT=25] -->
+    <string name="app_name">Package installer</string>
+
+    <!-- [CHAR LIMIT=15] -->
+    <string name="install">Install</string>
+    <!-- [CHAR LIMIT=15] -->
+    <string name="done">Done</string>
+    <!-- [CHAR LIMIT=15] -->
+    <string name="cancel">Cancel</string>
+    <!-- [CHAR LIMIT=50] -->
+    <string name="installing">Installing\u2026</string>
+    <!-- [CHAR LIMIT=50] -->
+    <string name="installing_app">Installing <xliff:g id="package_label">%1$s</xliff:g>\u2026</string>
+    <!-- [CHAR LIMIT=100] -->
+    <string name="install_done">App installed.</string>
+    <!-- Message for installing a new app that requires some permissions [CHAR LIMIT=NONE] -->
+    <!-- Message for installing a new app that does not require permissions [CHAR LIMIT=NONE] -->
+    <string name="install_confirm_question">Do you want to install this application?</string>
+    <!-- Message for updating an existing app [CHAR LIMIT=NONE] -->
+    <string name="install_confirm_question_update">Do you want to install an update
+            to this existing application?  Your existing data will not
+            be lost.</string>
+    <!-- Message for updating an existing system app [CHAR LIMIT=NONE] -->
+    <string name="install_confirm_question_update_system">Do you want to install an update
+            to this built-in application?  Your existing data will not
+            be lost.</string>
+    <!-- [CHAR LIMIT=100] -->
+    <string name="install_failed">App not installed.</string>
+    <!-- Reason displayed when installation fails because the package was blocked
+        from being installed (e.g., device policy, verification, ...) [CHAR LIMIT=100] -->
+    <string name="install_failed_blocked">The package was blocked from being installed.</string>
+    <!-- Reason displayed when installation fails because the package conflicts with
+        an existing application (e.g., incompatible certificates) [CHAR LIMIT=100] -->
+    <string name="install_failed_conflict">App not installed as package conflicts with an existing package.</string>
+    <!-- Reason displayed when installation fails because the package is incompatible with
+       the current tablet (e.g., missing native code for the current ABI, newer SDK, ...) [CHAR LIMIT=100] -->
+    <string name="install_failed_incompatible" product="tablet">App not installed as app isn\'t
+        compatible with your tablet.</string>
+    <!-- Reason displayed when installation fails because the package is incompatible with
+       the current TV (e.g., missing native code for the current ABI, newer SDK, ...) [CHAR LIMIT=100] -->
+    <string name="install_failed_incompatible" product="tv">This app isn\'t
+        compatible with your TV.</string>
+    <!-- Reason displayed when installation fails because the package is incompatible with
+       the current phone (e.g., missing native code for the current ABI, newer SDK, ...) [CHAR LIMIT=100] -->
+    <string name="install_failed_incompatible" product="default">App not installed as app isn\'t
+        compatible with your phone.</string>
+    <!-- Reason displayed when installation fails because the installation package itself is invalid
+        in some way (e.g., corrupt) [CHAR LIMIT=100] -->
+    <string name="install_failed_invalid_apk">App not installed as package appears to be invalid.</string>
+    <!-- Message presented when an application could not be installed on the tablet for some reason. [CHAR LIMIT=100] -->
+    <string name="install_failed_msg" product="tablet"><xliff:g id="app_name">%1$s</xliff:g> couldn\'t be installed on your tablet.</string>
+    <!-- Message presented when an application could not be installed on the TV for some reason. [CHAR LIMIT=100] -->
+    <string name="install_failed_msg" product="tv"><xliff:g id="app_name">%1$s</xliff:g> couldn\'t be installed on your TV.</string>
+    <!-- Message presented when an application could not be installed on the phone for some reason. [CHAR LIMIT=100] -->
+    <string name="install_failed_msg" product="default"><xliff:g id="app_name">%1$s</xliff:g> couldn\'t be installed on your phone.</string>
+    <string name="launch">Open</string>
+
+    <!-- Message presented in a dialog box when the device administrator restricts the installation of apps from unknown sources. [CHAR LIMIT=none] -->
+    <string name="unknown_apps_admin_dlg_text">Your admin doesn\'t allow installation of apps
+        obtained from unknown sources</string>
+    <!-- Message presented in a dialog box when the user restriction set by the system restricts the installation of apps from unknown sources. [CHAR LIMIT=none] -->
+    <string name="unknown_apps_user_restriction_dlg_text">Unknown apps can\'t be installed by this
+        user</string>
+    <!-- Message presented in a dialog box when the user restriction set by the system restricts the installation of apps. [CHAR LIMIT=none] -->
+    <string name="install_apps_user_restriction_dlg_text">This user is not allowed to install apps</string>
+
+    <!-- [CHAR LIMIT=15] -->
+    <string name="ok">OK</string>
+    <!-- [CHAR LIMIT=15] -->
+    <string name="manage_applications">Manage apps</string>
+    <!-- [CHAR LIMIT=30] -->
+    <string name="out_of_space_dlg_title">Out of space</string>
+    <!-- [CHAR LIMIT=none] -->
+    <string name="out_of_space_dlg_text"><xliff:g id="app_name">%1$s</xliff:g> couldn\'t be installed. Free up some space and try again.</string>
+    <!-- strings related to uninstall activity -->
+    <!--  [CHAR LIMIT=30] -->
+    <string name="app_not_found_dlg_title">App not found</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="app_not_found_dlg_text"> The app wasn\'t found in the list of installed apps.</string>
+    <!--  [CHAR LIMIT=30] -->
+    <string name="user_is_not_allowed_dlg_title">Not allowed</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="user_is_not_allowed_dlg_text">The current user is not allowed to perform this uninstallation.</string>
+    <!--  [CHAR LIMIT=30] -->
+    <string name="generic_error_dlg_title">Error</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="generic_error_dlg_text">App could not be uninstalled.</string>
+    <!--  [CHAR LIMIT=30] -->
+    <string name="uninstall_application_title">Uninstall app</string>
+    <!--  [CHAR LIMIT=30] -->
+    <string name="uninstall_update_title">Uninstall update</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="uninstall_activity_text"><xliff:g id="activity_name">%1$s</xliff:g> is part of the following app:</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="uninstall_application_text">Do you want to uninstall this app?</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="uninstall_application_text_all_users">Do you want to uninstall this app for <b>all</b>
+        users?  The application and its data will be removed from <b>all</b> users on the device.</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="uninstall_application_text_user">Do you want to uninstall this app for the user <xliff:g id="username">%1$s</xliff:g>?</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="uninstall_update_text">Replace this app with the factory version? All data will be removed.</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="uninstall_update_text_multiuser">Replace this app with the factory version? All data will be removed. This affects all users of this device, including those with work profiles.</string>
+
+    <!-- Label for the notification channel containing notifications for current uninstall operations [CHAR LIMIT=40] -->
+    <string name="uninstalling_notification_channel">Running uninstalls</string>
+    <!-- Label for the notification channel containing notifications for failed uninstall operations [CHAR LIMIT=40] -->
+    <string name="uninstall_failure_notification_channel">Failed uninstalls</string>
+
+    <!-- [CHAR LIMIT=50] -->
+    <string name="uninstalling">Uninstalling\u2026</string>
+    <!-- [CHAR LIMIT=50] -->
+    <string name="uninstalling_app">Uninstalling <xliff:g id="package_label">%1$s</xliff:g>\u2026</string>
+    <!-- [CHAR LIMIT=100] -->
+    <string name="uninstall_done">Uninstall finished.</string>
+    <!-- [CHAR LIMIT=100] -->
+    <string name="uninstall_done_app">Uninstalled <xliff:g id="package_label">%1$s</xliff:g></string>
+    <!-- [CHAR LIMIT=100] -->
+    <string name="uninstall_failed">Uninstall unsuccessful.</string>
+    <!-- [CHAR LIMIT=100] -->
+    <string name="uninstall_failed_app">Uninstalling <xliff:g id="package_label">%1$s</xliff:g> unsuccessful.</string>
+    <!-- String presented to the user when uninstalling a package failed because the target package
+        is a current device administrator [CHAR LIMIT=80] -->
+    <string name="uninstall_failed_device_policy_manager">Can\'t uninstall active device admin
+        app</string>
+    <!-- String presented to the user when uninstalling a package failed because the target package
+        is a current device administrator for some user [CHAR LIMIT=100] -->
+    <string name="uninstall_failed_device_policy_manager_of_user">Can\'t uninstall active device
+        admin app for <xliff:g id="username">%1$s</xliff:g></string>
+    <!-- String presented to the admin user when uninstalling a package for all users failed
+    because a profile owner has marked the target package as not able to be uninstalled
+    [CHAR LIMIT=120] -->
+    <string name="uninstall_all_blocked_profile_owner">This app is required for some users or
+        profiles and was uninstalled for others</string>
+    <!-- String presented to the user when uninstalling a package failed because a profile owner
+         has marked the target package as not able to be uninstalled [CHAR LIMIT=120] -->
+    <string name="uninstall_blocked_profile_owner">This app is needed for
+        your profile and can\'t be uninstalled.</string>
+    <!-- String presented to the user when uninstalling a package failed because a device owner
+         has marked the the target package as not able to be uninstalled [CHAR LIMIT=80] -->
+    <string name="uninstall_blocked_device_owner">This app is required
+        by your device administrator and can\'t be uninstalled.</string>
+    <!-- String on a button that leads to the "device admin apps" configuration setting where a
+        user will be able to disable the device admin app in order to uninstall
+        it. [CHAR LIMIT=50] -->
+    <string name="manage_device_administrators">Manage device admin apps</string>
+    <!-- String on a button that leads to the "Users" page in Settings where a
+        user will be able to remove the secondary user(s) in order to uninstall
+        the app. [CHAR LIMIT=50] -->
+    <string name="manage_users">Manage users</string>
+    <!-- [CHAR LIMIT=none] -->
+    <string name="uninstall_failed_msg"><xliff:g id="app_name">%1$s</xliff:g> couldn\'t be uninstalled.</string>
+
+    <!-- Dialog attributes to indicate parse errors -->
+    <string name="Parse_error_dlg_text">There was a problem parsing the package.</string>
+
+    <!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. [CHAR LIMIT=30] -->
+    <string name="wear_not_allowed_dlg_title">Android Wear</string>
+    <!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. [CHAR LIMIT=none] -->
+    <string name="wear_not_allowed_dlg_text">Install/Uninstall actions not supported on Wear.</string>
+
+    <!-- Message that the app to be installed is being staged [CHAR LIMIT=50] -->
+    <string name="message_staging">Staging app&#8230;</string>
+
+    <!-- Placeholder for an app name when it is unknown [CHAR LIMIT=50] -->
+    <string name="app_name_unknown">Unknown</string>
+
+    <!-- Help URL, application permissions [DO NOT TRANSLATE] -->
+    <string name="help_app_permissions" translatable="false"></string>
+
+    <!-- Text to show in warning dialog on the tablet when the app source is not trusted [CHAR LIMIT=NONE] -->
+    <string name="untrusted_external_source_warning" product="tablet">For your security, your tablet is not allowed to install unknown apps from this source.</string>
+
+    <!-- Text to show in warning dialog on the tv when the app source is not trusted [CHAR LIMIT=NONE] -->
+    <string name="untrusted_external_source_warning" product="tv">For your security, your TV is not allowed to install unknown apps from this source.</string>
+
+    <!-- Text to show in warning dialog on the phone when the app source is not trusted [CHAR LIMIT=NONE] -->
+    <string name="untrusted_external_source_warning" product="default">For your security, your phone is not allowed to install unknown apps from this source.</string>
+
+    <!-- Text to show in warning dialog on the phone when the app source cannot be identified [CHAR LIMIT=NONE] -->
+    <string name="anonymous_source_warning" product="default">
+        Your phone and personal data are more vulnerable
+        to attack by unknown apps. By installing this app, you
+        agree that you are responsible for any damage to your
+        phone or loss of data that may result from its use.
+    </string>
+
+    <!-- Text to show in warning dialog on the tablet when the app source cannot be identified [CHAR LIMIT=NONE] -->
+    <string name="anonymous_source_warning" product="tablet">
+        Your tablet and personal data are more vulnerable
+        to attack by unknown apps. By installing this app, you
+        agree that you are responsible for any damage to your
+        tablet or loss of data that may result from its use.
+    </string>
+
+    <!-- Text to show in warning dialog on the tv when the app source cannot be identified [CHAR LIMIT=NONE] -->
+    <string name="anonymous_source_warning" product="tv">
+        Your TV and personal data are more vulnerable
+        to attack by unknown apps. By installing this app, you
+        agree that you are responsible for any damage to your
+        TV or loss of data that may result from its use.
+    </string>
+
+    <!-- Label for button to continue install of an app whose source cannot be identified [CHAR LIMIT=40] -->
+    <string name="anonymous_source_continue">Continue</string>
+
+    <!-- Label for button to open manage external sources settings [CHAR LIMIT=45] -->
+    <string name="external_sources_settings">Settings</string>
+
+    <!-- Label for the notification channel containing notifications for embedded app operations [CHAR LIMIT=40] -->
+    <string name="wear_app_channel">Installing/uninstalling wear apps</string>
+
+</resources>
diff --git a/packages/PackageInstaller/res/values/themes.xml b/packages/PackageInstaller/res/values/themes.xml
new file mode 100644
index 0000000..6c8e4c5
--- /dev/null
+++ b/packages/PackageInstaller/res/values/themes.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+
+    <style name="Theme.AlertDialogActivity.NoAnimation">
+        <item name="android:windowAnimationStyle">@null</item>
+    </style>
+
+    <style name="Theme.AlertDialogActivity"
+            parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
+
+</resources>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java b/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java
new file mode 100644
index 0000000..399cf1f
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import java.io.File;
+
+/**
+ * Trampoline activity. Calls PackageInstallerActivity and deletes staged install file onResult.
+ */
+public class DeleteStagedFileOnResult extends Activity {
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (savedInstanceState == null) {
+            Intent installIntent = new Intent(getIntent());
+            installIntent.setClass(this, PackageInstallerActivity.class);
+
+            installIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
+            startActivityForResult(installIntent, 0);
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        File sourceFile = new File(getIntent().getData().getPath());
+        sourceFile.delete();
+
+        setResult(resultCode, data);
+        finish();
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/DeviceUtils.java b/packages/PackageInstaller/src/com/android/packageinstaller/DeviceUtils.java
new file mode 100644
index 0000000..b54cad6
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/DeviceUtils.java
@@ -0,0 +1,36 @@
+/*
+ * 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.packageinstaller;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+
+public class DeviceUtils {
+    public static boolean isTelevision(Context context) {
+        int uiMode = context.getResources().getConfiguration().uiMode;
+        return (uiMode & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION;
+    }
+
+    public static boolean isWear(final Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+    }
+
+    public static boolean isAuto(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/EventResultPersister.java b/packages/PackageInstaller/src/com/android/packageinstaller/EventResultPersister.java
new file mode 100644
index 0000000..3a94fdc
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/EventResultPersister.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInstaller;
+import android.os.AsyncTask;
+import android.util.AtomicFile;
+import android.util.Log;
+import android.util.SparseArray;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Persists results of events and calls back observers when a matching result arrives.
+ */
+class EventResultPersister {
+    private static final String LOG_TAG = EventResultPersister.class.getSimpleName();
+
+    /** Id passed to {@link #addObserver(int, EventResultObserver)} to generate new id */
+    static final int GENERATE_NEW_ID = Integer.MIN_VALUE;
+
+    /**
+     * The extra with the id to set in the intent delivered to
+     * {@link #onEventReceived(Context, Intent)}
+     */
+    static final String EXTRA_ID = "EventResultPersister.EXTRA_ID";
+
+    /** Persisted state of this object */
+    private final AtomicFile mResultsFile;
+
+    private final Object mLock = new Object();
+
+    /** Currently stored but not yet called back results (install id -> status, status message) */
+    private final SparseArray<EventResult> mResults = new SparseArray<>();
+
+    /** Currently registered, not called back observers (install id -> observer) */
+    private final SparseArray<EventResultObserver> mObservers = new SparseArray<>();
+
+    /** Always increasing counter for install event ids */
+    private int mCounter;
+
+    /** If a write that will persist the state is scheduled */
+    private boolean mIsPersistScheduled;
+
+    /** If the state was changed while the data was being persisted */
+    private boolean mIsPersistingStateValid;
+
+    /**
+     * @return a new event id.
+     */
+    public int getNewId() throws OutOfIdsException {
+        synchronized (mLock) {
+            if (mCounter == Integer.MAX_VALUE) {
+                throw new OutOfIdsException();
+            }
+
+            mCounter++;
+            writeState();
+
+            return mCounter - 1;
+        }
+    }
+
+    /** Call back when a result is received. Observer is removed when onResult it called. */
+    interface EventResultObserver {
+        void onResult(int status, int legacyStatus, @Nullable String message);
+    }
+
+    /**
+     * Progress parser to the next element.
+     *
+     * @param parser The parser to progress
+     */
+    private static void nextElement(@NonNull XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        int type;
+        do {
+            type = parser.next();
+        } while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT);
+    }
+
+    /**
+     * Read an int attribute from the current element
+     *
+     * @param parser The parser to read from
+     * @param name The attribute name to read
+     *
+     * @return The value of the attribute
+     */
+    private static int readIntAttribute(@NonNull XmlPullParser parser, @NonNull String name) {
+        return Integer.parseInt(parser.getAttributeValue(null, name));
+    }
+
+    /**
+     * Read an String attribute from the current element
+     *
+     * @param parser The parser to read from
+     * @param name The attribute name to read
+     *
+     * @return The value of the attribute or null if the attribute is not set
+     */
+    private static String readStringAttribute(@NonNull XmlPullParser parser, @NonNull String name) {
+        return parser.getAttributeValue(null, name);
+    }
+
+    /**
+     * Read persisted state.
+     *
+     * @param resultFile The file the results are persisted in
+     */
+    EventResultPersister(@NonNull File resultFile) {
+        mResultsFile = new AtomicFile(resultFile);
+        mCounter = GENERATE_NEW_ID + 1;
+
+        try (FileInputStream stream = mResultsFile.openRead()) {
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(stream, StandardCharsets.UTF_8.name());
+
+            nextElement(parser);
+            while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+                String tagName = parser.getName();
+                if ("results".equals(tagName)) {
+                    mCounter = readIntAttribute(parser, "counter");
+                } else if ("result".equals(tagName)) {
+                    int id = readIntAttribute(parser, "id");
+                    int status = readIntAttribute(parser, "status");
+                    int legacyStatus = readIntAttribute(parser, "legacyStatus");
+                    String statusMessage = readStringAttribute(parser, "statusMessage");
+
+                    if (mResults.get(id) != null) {
+                        throw new Exception("id " + id + " has two results");
+                    }
+
+                    mResults.put(id, new EventResult(status, legacyStatus, statusMessage));
+                } else {
+                    throw new Exception("unexpected tag");
+                }
+
+                nextElement(parser);
+            }
+        } catch (Exception e) {
+            mResults.clear();
+            writeState();
+        }
+    }
+
+    /**
+     * Add a result. If the result is an pending user action, execute the pending user action
+     * directly and do not queue a result.
+     *
+     * @param context The context the event was received in
+     * @param intent The intent the activity received
+     */
+    void onEventReceived(@NonNull Context context, @NonNull Intent intent) {
+        int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, 0);
+
+        if (status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
+            context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT));
+
+            return;
+        }
+
+        int id = intent.getIntExtra(EXTRA_ID, 0);
+        String statusMessage = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
+        int legacyStatus = intent.getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS, 0);
+
+        EventResultObserver observerToCall = null;
+        synchronized (mLock) {
+            int numObservers = mObservers.size();
+            for (int i = 0; i < numObservers; i++) {
+                if (mObservers.keyAt(i) == id) {
+                    observerToCall = mObservers.valueAt(i);
+                    mObservers.removeAt(i);
+
+                    break;
+                }
+            }
+
+            if (observerToCall != null) {
+                observerToCall.onResult(status, legacyStatus, statusMessage);
+            } else {
+                mResults.put(id, new EventResult(status, legacyStatus, statusMessage));
+                writeState();
+            }
+        }
+    }
+
+    /**
+     * Persist current state. The persistence might be delayed.
+     */
+    private void writeState() {
+        synchronized (mLock) {
+            mIsPersistingStateValid = false;
+
+            if (!mIsPersistScheduled) {
+                mIsPersistScheduled = true;
+
+                AsyncTask.execute(() -> {
+                    int counter;
+                    SparseArray<EventResult> results;
+
+                    while (true) {
+                        // Take snapshot of state
+                        synchronized (mLock) {
+                            counter = mCounter;
+                            results = mResults.clone();
+                            mIsPersistingStateValid = true;
+                        }
+
+                        FileOutputStream stream = null;
+                        try {
+                            stream = mResultsFile.startWrite();
+                            XmlSerializer serializer = Xml.newSerializer();
+                            serializer.setOutput(stream, StandardCharsets.UTF_8.name());
+                            serializer.startDocument(null, true);
+                            serializer.setFeature(
+                                    "http://xmlpull.org/v1/doc/features.html#indent-output", true);
+                            serializer.startTag(null, "results");
+                            serializer.attribute(null, "counter", Integer.toString(counter));
+
+                            int numResults = results.size();
+                            for (int i = 0; i < numResults; i++) {
+                                serializer.startTag(null, "result");
+                                serializer.attribute(null, "id",
+                                        Integer.toString(results.keyAt(i)));
+                                serializer.attribute(null, "status",
+                                        Integer.toString(results.valueAt(i).status));
+                                serializer.attribute(null, "legacyStatus",
+                                        Integer.toString(results.valueAt(i).legacyStatus));
+                                if (results.valueAt(i).message != null) {
+                                    serializer.attribute(null, "statusMessage",
+                                            results.valueAt(i).message);
+                                }
+                                serializer.endTag(null, "result");
+                            }
+
+                            serializer.endTag(null, "results");
+                            serializer.endDocument();
+
+                            mResultsFile.finishWrite(stream);
+                        } catch (IOException e) {
+                            if (stream != null) {
+                                mResultsFile.failWrite(stream);
+                            }
+
+                            Log.e(LOG_TAG, "error writing results", e);
+                            mResultsFile.delete();
+                        }
+
+                        // Check if there was changed state since we persisted. If so, we need to
+                        // persist again.
+                        synchronized (mLock) {
+                            if (mIsPersistingStateValid) {
+                                mIsPersistScheduled = false;
+                                break;
+                            }
+                        }
+                    }
+                });
+            }
+        }
+    }
+
+    /**
+     * Add an observer. If there is already an event for this id, call back inside of this call.
+     *
+     * @param id       The id the observer is for or {@code GENERATE_NEW_ID} to generate a new one.
+     * @param observer The observer to call back.
+     *
+     * @return The id for this event
+     */
+    int addObserver(int id, @NonNull EventResultObserver observer)
+            throws OutOfIdsException {
+        synchronized (mLock) {
+            int resultIndex = -1;
+
+            if (id == GENERATE_NEW_ID) {
+                id = getNewId();
+            } else {
+                resultIndex = mResults.indexOfKey(id);
+            }
+
+            // Check if we can instantly call back
+            if (resultIndex >= 0) {
+                EventResult result = mResults.valueAt(resultIndex);
+
+                observer.onResult(result.status, result.legacyStatus, result.message);
+                mResults.removeAt(resultIndex);
+                writeState();
+            } else {
+                mObservers.put(id, observer);
+            }
+        }
+
+
+        return id;
+    }
+
+    /**
+     * Remove a observer.
+     *
+     * @param id The id the observer was added for
+     */
+    void removeObserver(int id) {
+        synchronized (mLock) {
+            mObservers.delete(id);
+        }
+    }
+
+    /**
+     * The status from an event.
+     */
+    private class EventResult {
+        public final int status;
+        public final int legacyStatus;
+        @Nullable public final String message;
+
+        private EventResult(int status, int legacyStatus, @Nullable String message) {
+            this.status = status;
+            this.legacyStatus = legacyStatus;
+            this.message = message;
+        }
+    }
+
+    class OutOfIdsException extends Exception {}
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallEventReceiver.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallEventReceiver.java
new file mode 100644
index 0000000..c70d7db
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallEventReceiver.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Receives install events and perists them using a {@link EventResultPersister}.
+ */
+public class InstallEventReceiver extends BroadcastReceiver {
+    private static final Object sLock = new Object();
+    private static EventResultPersister sReceiver;
+
+    /**
+     * Get the event receiver persisting the results
+     *
+     * @return The event receiver.
+     */
+    @NonNull private static EventResultPersister getReceiver(@NonNull Context context) {
+        synchronized (sLock) {
+            if (sReceiver == null) {
+                sReceiver = new EventResultPersister(
+                        TemporaryFileManager.getInstallStateFile(context));
+            }
+        }
+
+        return sReceiver;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        getReceiver(context).onEventReceived(context, intent);
+    }
+
+    /**
+     * Add an observer. If there is already an event for this id, call back inside of this call.
+     *
+     * @param context  A context of the current app
+     * @param id       The id the observer is for or {@code GENERATE_NEW_ID} to generate a new one.
+     * @param observer The observer to call back.
+     *
+     * @return The id for this event
+     */
+    static int addObserver(@NonNull Context context, int id,
+            @NonNull EventResultPersister.EventResultObserver observer)
+            throws EventResultPersister.OutOfIdsException {
+        return getReceiver(context).addObserver(id, observer);
+    }
+
+    /**
+     * Remove a observer.
+     *
+     * @param context  A context of the current app
+     * @param id The id the observer was added for
+     */
+    static void removeObserver(@NonNull Context context, int id) {
+        getReceiver(context).removeObserver(id);
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
new file mode 100644
index 0000000..54105bb
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+
+import com.android.internal.app.AlertActivity;
+
+import java.io.File;
+
+/**
+ * Installation failed: Return status code to the caller or display failure UI to user
+ */
+public class InstallFailed extends AlertActivity {
+    private static final String LOG_TAG = InstallFailed.class.getSimpleName();
+
+    /** Label of the app that failed to install */
+    private CharSequence mLabel;
+
+    /**
+     * Unhide the appropriate label for the statusCode.
+     *
+     * @param statusCode The status code from the package installer.
+     */
+    private void setExplanationFromErrorCode(int statusCode) {
+        Log.d(LOG_TAG, "Installation status code: " + statusCode);
+
+        View viewToEnable;
+        switch (statusCode) {
+            case PackageInstaller.STATUS_FAILURE_BLOCKED:
+                viewToEnable = requireViewById(R.id.install_failed_blocked);
+                break;
+            case PackageInstaller.STATUS_FAILURE_CONFLICT:
+                viewToEnable = requireViewById(R.id.install_failed_conflict);
+                break;
+            case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE:
+                viewToEnable = requireViewById(R.id.install_failed_incompatible);
+                break;
+            case PackageInstaller.STATUS_FAILURE_INVALID:
+                viewToEnable = requireViewById(R.id.install_failed_invalid_apk);
+                break;
+            default:
+                viewToEnable = requireViewById(R.id.install_failed);
+                break;
+        }
+
+        viewToEnable.setVisibility(View.VISIBLE);
+    }
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        int statusCode = getIntent().getIntExtra(PackageInstaller.EXTRA_STATUS,
+                PackageInstaller.STATUS_FAILURE);
+
+        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
+            int legacyStatus = getIntent().getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS,
+                    PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
+
+            // Return result if requested
+            Intent result = new Intent();
+            result.putExtra(Intent.EXTRA_INSTALL_RESULT, legacyStatus);
+            setResult(Activity.RESULT_FIRST_USER, result);
+            finish();
+        } else {
+            Intent intent = getIntent();
+            ApplicationInfo appInfo = intent
+                    .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+            Uri packageURI = intent.getData();
+
+            // Set header icon and title
+            PackageUtil.AppSnippet as;
+            PackageManager pm = getPackageManager();
+
+            if ("package".equals(packageURI.getScheme())) {
+                as = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
+                        pm.getApplicationIcon(appInfo));
+            } else {
+                final File sourceFile = new File(packageURI.getPath());
+                as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
+            }
+
+            // Store label for dialog
+            mLabel = as.label;
+
+            mAlert.setIcon(as.icon);
+            mAlert.setTitle(as.label);
+            mAlert.setView(R.layout.install_content_view);
+            mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.done),
+                    (ignored, ignored2) -> finish(), null);
+            setupAlert();
+
+            // Show out of space dialog if needed
+            if (statusCode == PackageInstaller.STATUS_FAILURE_STORAGE) {
+                (new OutOfSpaceDialog()).show(getFragmentManager(), "outofspace");
+            }
+
+            // Get status messages
+            setExplanationFromErrorCode(statusCode);
+        }
+    }
+
+    /**
+     * Dialog shown when we ran out of space during installation. This contains a link to the
+     * "manage applications" settings page.
+     */
+    public static class OutOfSpaceDialog extends DialogFragment {
+        private InstallFailed mActivity;
+
+        @Override
+        public void onAttach(Context context) {
+            super.onAttach(context);
+
+            mActivity = (InstallFailed) context;
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            return new AlertDialog.Builder(mActivity)
+                    .setTitle(R.string.out_of_space_dlg_title)
+                    .setMessage(getString(R.string.out_of_space_dlg_text, mActivity.mLabel))
+                    .setPositiveButton(R.string.manage_applications, (dialog, which) -> {
+                        // launch manage applications
+                        Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
+                        startActivity(intent);
+                        mActivity.finish();
+                    })
+                    .setNegativeButton(R.string.cancel, (dialog, which) -> mActivity.finish())
+                    .create();
+        }
+
+        @Override
+        public void onCancel(DialogInterface dialog) {
+            super.onCancel(dialog);
+
+            mActivity.finish();
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
new file mode 100755
index 0000000..deb6163
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import static android.content.pm.PackageInstaller.SessionParams.UID_UNKNOWN;
+
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.content.PackageHelper;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Send package to the package manager and handle results from package manager. Once the
+ * installation succeeds, start {@link InstallSuccess} or {@link InstallFailed}.
+ * <p>This has two phases: First send the data to the package manager, then wait until the package
+ * manager processed the result.</p>
+ */
+public class InstallInstalling extends AlertActivity {
+    private static final String LOG_TAG = InstallInstalling.class.getSimpleName();
+
+    private static final String SESSION_ID = "com.android.packageinstaller.SESSION_ID";
+    private static final String INSTALL_ID = "com.android.packageinstaller.INSTALL_ID";
+
+    private static final String BROADCAST_ACTION =
+            "com.android.packageinstaller.ACTION_INSTALL_COMMIT";
+
+    /** Listens to changed to the session and updates progress bar */
+    private PackageInstaller.SessionCallback mSessionCallback;
+
+    /** Task that sends the package to the package installer */
+    private InstallingAsyncTask mInstallingTask;
+
+    /** Id of the session to install the package */
+    private int mSessionId;
+
+    /** Id of the install event we wait for */
+    private int mInstallId;
+
+    /** URI of package to install */
+    private Uri mPackageURI;
+
+    /** The button that can cancel this dialog */
+    private Button mCancelButton;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        ApplicationInfo appInfo = getIntent()
+                .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+        mPackageURI = getIntent().getData();
+        final File sourceFile = new File(mPackageURI.getPath());
+        PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
+
+        mAlert.setIcon(as.icon);
+        mAlert.setTitle(as.label);
+        mAlert.setView(R.layout.install_content_view);
+        mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
+                (ignored, ignored2) -> {
+                    if (mInstallingTask != null) {
+                        mInstallingTask.cancel(true);
+                    }
+
+                    if (mSessionId > 0) {
+                        getPackageManager().getPackageInstaller().abandonSession(mSessionId);
+                        mSessionId = 0;
+                    }
+
+                    setResult(RESULT_CANCELED);
+                    finish();
+                }, null);
+        setupAlert();
+        requireViewById(R.id.installing).setVisibility(View.VISIBLE);
+
+        if ("package".equals(mPackageURI.getScheme())) {
+            try {
+                getPackageManager().installExistingPackage(appInfo.packageName);
+                launchSuccess();
+            } catch (PackageManager.NameNotFoundException e) {
+                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
+            }
+        } else {
+            if (savedInstanceState != null) {
+                mSessionId = savedInstanceState.getInt(SESSION_ID);
+                mInstallId = savedInstanceState.getInt(INSTALL_ID);
+
+                // Reregister for result; might instantly call back if result was delivered while
+                // activity was destroyed
+                try {
+                    InstallEventReceiver.addObserver(this, mInstallId,
+                            this::launchFinishBasedOnResult);
+                } catch (EventResultPersister.OutOfIdsException e) {
+                    // Does not happen
+                }
+            } else {
+                PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+                        PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+                params.installFlags = PackageManager.INSTALL_FULL_APP;
+                params.referrerUri = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
+                params.originatingUri = getIntent()
+                        .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
+                params.originatingUid = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
+                        UID_UNKNOWN);
+                params.installerPackageName =
+                        getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
+
+                File file = new File(mPackageURI.getPath());
+                try {
+                    PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
+                    params.setAppPackageName(pkg.packageName);
+                    params.setInstallLocation(pkg.installLocation);
+                    params.setSize(
+                            PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
+                } catch (PackageParser.PackageParserException e) {
+                    Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");
+                    Log.e(LOG_TAG,
+                            "Cannot calculate installed size " + file + ". Try only apk size.");
+                    params.setSize(file.length());
+                } catch (IOException e) {
+                    Log.e(LOG_TAG,
+                            "Cannot calculate installed size " + file + ". Try only apk size.");
+                    params.setSize(file.length());
+                }
+
+                try {
+                    mInstallId = InstallEventReceiver
+                            .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
+                                    this::launchFinishBasedOnResult);
+                } catch (EventResultPersister.OutOfIdsException e) {
+                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
+                }
+
+                try {
+                    mSessionId = getPackageManager().getPackageInstaller().createSession(params);
+                } catch (IOException e) {
+                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
+                }
+            }
+
+            mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);
+
+            mSessionCallback = new InstallSessionCallback();
+        }
+    }
+
+    /**
+     * Launch the "success" version of the final package installer dialog
+     */
+    private void launchSuccess() {
+        Intent successIntent = new Intent(getIntent());
+        successIntent.setClass(this, InstallSuccess.class);
+        successIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+
+        startActivity(successIntent);
+        finish();
+    }
+
+    /**
+     * Launch the "failure" version of the final package installer dialog
+     *
+     * @param legacyStatus  The status as used internally in the package manager.
+     * @param statusMessage The status description.
+     */
+    private void launchFailure(int legacyStatus, String statusMessage) {
+        Intent failureIntent = new Intent(getIntent());
+        failureIntent.setClass(this, InstallFailed.class);
+        failureIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+        failureIntent.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, legacyStatus);
+        failureIntent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, statusMessage);
+
+        startActivity(failureIntent);
+        finish();
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        getPackageManager().getPackageInstaller().registerSessionCallback(mSessionCallback);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        // This is the first onResume in a single life of the activity
+        if (mInstallingTask == null) {
+            PackageInstaller installer = getPackageManager().getPackageInstaller();
+            PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
+
+            if (sessionInfo != null && !sessionInfo.isActive()) {
+                mInstallingTask = new InstallingAsyncTask();
+                mInstallingTask.execute();
+            } else {
+                // we will receive a broadcast when the install is finished
+                mCancelButton.setEnabled(false);
+                setFinishOnTouchOutside(false);
+            }
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putInt(SESSION_ID, mSessionId);
+        outState.putInt(INSTALL_ID, mInstallId);
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (mCancelButton.isEnabled()) {
+            super.onBackPressed();
+        }
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+
+        getPackageManager().getPackageInstaller().unregisterSessionCallback(mSessionCallback);
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mInstallingTask != null) {
+            mInstallingTask.cancel(true);
+            synchronized (mInstallingTask) {
+                while (!mInstallingTask.isDone) {
+                    try {
+                        mInstallingTask.wait();
+                    } catch (InterruptedException e) {
+                        Log.i(LOG_TAG, "Interrupted while waiting for installing task to cancel",
+                                e);
+                    }
+                }
+            }
+        }
+
+        InstallEventReceiver.removeObserver(this, mInstallId);
+
+        super.onDestroy();
+    }
+
+    /**
+     * Launch the appropriate finish activity (success or failed) for the installation result.
+     *
+     * @param statusCode    The installation result.
+     * @param legacyStatus  The installation as used internally in the package manager.
+     * @param statusMessage The detailed installation result.
+     */
+    private void launchFinishBasedOnResult(int statusCode, int legacyStatus, String statusMessage) {
+        if (statusCode == PackageInstaller.STATUS_SUCCESS) {
+            launchSuccess();
+        } else {
+            launchFailure(legacyStatus, statusMessage);
+        }
+    }
+
+
+    private class InstallSessionCallback extends PackageInstaller.SessionCallback {
+        @Override
+        public void onCreated(int sessionId) {
+            // empty
+        }
+
+        @Override
+        public void onBadgingChanged(int sessionId) {
+            // empty
+        }
+
+        @Override
+        public void onActiveChanged(int sessionId, boolean active) {
+            // empty
+        }
+
+        @Override
+        public void onProgressChanged(int sessionId, float progress) {
+            if (sessionId == mSessionId) {
+                ProgressBar progressBar = requireViewById(R.id.progress);
+                progressBar.setMax(Integer.MAX_VALUE);
+                progressBar.setProgress((int) (Integer.MAX_VALUE * progress));
+            }
+        }
+
+        @Override
+        public void onFinished(int sessionId, boolean success) {
+            // empty, finish is handled by InstallResultReceiver
+        }
+    }
+
+    /**
+     * Send the package to the package installer and then register a event result observer that
+     * will call {@link #launchFinishBasedOnResult(int, int, String)}
+     */
+    private final class InstallingAsyncTask extends AsyncTask<Void, Void,
+            PackageInstaller.Session> {
+        volatile boolean isDone;
+
+        @Override
+        protected PackageInstaller.Session doInBackground(Void... params) {
+            PackageInstaller.Session session;
+            try {
+                session = getPackageManager().getPackageInstaller().openSession(mSessionId);
+            } catch (IOException e) {
+                return null;
+            }
+
+            session.setStagingProgress(0);
+
+            try {
+                File file = new File(mPackageURI.getPath());
+
+                try (InputStream in = new FileInputStream(file)) {
+                    long sizeBytes = file.length();
+                    try (OutputStream out = session
+                            .openWrite("PackageInstaller", 0, sizeBytes)) {
+                        byte[] buffer = new byte[1024 * 1024];
+                        while (true) {
+                            int numRead = in.read(buffer);
+
+                            if (numRead == -1) {
+                                session.fsync(out);
+                                break;
+                            }
+
+                            if (isCancelled()) {
+                                session.close();
+                                break;
+                            }
+
+                            out.write(buffer, 0, numRead);
+                            if (sizeBytes > 0) {
+                                float fraction = ((float) numRead / (float) sizeBytes);
+                                session.addProgress(fraction);
+                            }
+                        }
+                    }
+                }
+
+                return session;
+            } catch (IOException | SecurityException e) {
+                Log.e(LOG_TAG, "Could not write package", e);
+
+                session.close();
+
+                return null;
+            } finally {
+                synchronized (this) {
+                    isDone = true;
+                    notifyAll();
+                }
+            }
+        }
+
+        @Override
+        protected void onPostExecute(PackageInstaller.Session session) {
+            if (session != null) {
+                Intent broadcastIntent = new Intent(BROADCAST_ACTION);
+                broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                broadcastIntent.setPackage(getPackageName());
+                broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);
+
+                PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                        InstallInstalling.this,
+                        mInstallId,
+                        broadcastIntent,
+                        PendingIntent.FLAG_UPDATE_CURRENT);
+
+                session.commit(pendingIntent.getIntentSender());
+                mCancelButton.setEnabled(false);
+                setFinishOnTouchOutside(false);
+            } else {
+                getPackageManager().getPackageInstaller().abandonSession(mSessionId);
+
+                if (!isCancelled()) {
+                    launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
+                }
+            }
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java
new file mode 100644
index 0000000..98438cd
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+
+import com.android.internal.app.AlertActivity;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * If a package gets installed from an content URI this step loads the package and turns it into
+ * and installation from a file. Then it re-starts the installation as usual.
+ */
+public class InstallStaging extends AlertActivity {
+    private static final String LOG_TAG = InstallStaging.class.getSimpleName();
+
+    private static final String STAGED_FILE = "STAGED_FILE";
+
+    /** Currently running task that loads the file from the content URI into a file */
+    private @Nullable StagingAsyncTask mStagingTask;
+
+    /** The file the package is in */
+    private @Nullable File mStagedFile;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mAlert.setIcon(R.drawable.ic_file_download);
+        mAlert.setTitle(getString(R.string.app_name_unknown));
+        mAlert.setView(R.layout.install_content_view);
+        mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
+                (ignored, ignored2) -> {
+                    if (mStagingTask != null) {
+                        mStagingTask.cancel(true);
+                    }
+                    setResult(RESULT_CANCELED);
+                    finish();
+                }, null);
+        setupAlert();
+        requireViewById(R.id.staging).setVisibility(View.VISIBLE);
+
+        if (savedInstanceState != null) {
+            mStagedFile = new File(savedInstanceState.getString(STAGED_FILE));
+
+            if (!mStagedFile.exists()) {
+                mStagedFile = null;
+            }
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        // This is the first onResume in a single life of the activity
+        if (mStagingTask == null) {
+            // File does not exist, or became invalid
+            if (mStagedFile == null) {
+                // Create file delayed to be able to show error
+                try {
+                    mStagedFile = TemporaryFileManager.getStagedFile(this);
+                } catch (IOException e) {
+                    showError();
+                    return;
+                }
+            }
+
+            mStagingTask = new StagingAsyncTask();
+            mStagingTask.execute(getIntent().getData());
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putString(STAGED_FILE, mStagedFile.getPath());
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mStagingTask != null) {
+            mStagingTask.cancel(true);
+        }
+
+        super.onDestroy();
+    }
+
+    /**
+     * Show an error message and set result as error.
+     */
+    private void showError() {
+        (new ErrorDialog()).showAllowingStateLoss(getFragmentManager(), "error");
+
+        Intent result = new Intent();
+        result.putExtra(Intent.EXTRA_INSTALL_RESULT,
+                PackageManager.INSTALL_FAILED_INVALID_APK);
+        setResult(RESULT_FIRST_USER, result);
+    }
+
+    /**
+     * Dialog for errors while staging.
+     */
+    public static class ErrorDialog extends DialogFragment {
+        private Activity mActivity;
+
+        @Override
+        public void onAttach(Context context) {
+            super.onAttach(context);
+
+            mActivity = (Activity) context;
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            AlertDialog alertDialog = new AlertDialog.Builder(mActivity)
+                    .setMessage(R.string.Parse_error_dlg_text)
+                    .setPositiveButton(R.string.ok,
+                            (dialog, which) -> mActivity.finish())
+                    .create();
+            alertDialog.setCanceledOnTouchOutside(false);
+
+            return alertDialog;
+        }
+
+        @Override
+        public void onCancel(DialogInterface dialog) {
+            super.onCancel(dialog);
+
+            mActivity.finish();
+        }
+    }
+
+    private final class StagingAsyncTask extends AsyncTask<Uri, Void, Boolean> {
+        @Override
+        protected Boolean doInBackground(Uri... params) {
+            if (params == null || params.length <= 0) {
+                return false;
+            }
+            Uri packageUri = params[0];
+            try (InputStream in = getContentResolver().openInputStream(packageUri)) {
+                // Despite the comments in ContentResolver#openInputStream the returned stream can
+                // be null.
+                if (in == null) {
+                    return false;
+                }
+
+                try (OutputStream out = new FileOutputStream(mStagedFile)) {
+                    byte[] buffer = new byte[1024 * 1024];
+                    int bytesRead;
+                    while ((bytesRead = in.read(buffer)) >= 0) {
+                        // Be nice and respond to a cancellation
+                        if (isCancelled()) {
+                            return false;
+                        }
+                        out.write(buffer, 0, bytesRead);
+                    }
+                }
+            } catch (IOException | SecurityException | IllegalStateException e) {
+                Log.w(LOG_TAG, "Error staging apk from content URI", e);
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        protected void onPostExecute(Boolean success) {
+            if (success) {
+                // Now start the installation again from a file
+                Intent installIntent = new Intent(getIntent());
+                installIntent.setClass(InstallStaging.this, DeleteStagedFileOnResult.class);
+                installIntent.setData(Uri.fromFile(mStagedFile));
+
+                if (installIntent.getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
+                    installIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+                }
+
+                installIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
+                startActivity(installIntent);
+
+                InstallStaging.this.finish();
+            } else {
+                showError();
+            }
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
new file mode 100644
index 0000000..b3f1105
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import static com.android.packageinstaller.PackageUtil.getMaxTargetSdkVersionForUid;
+
+import android.Manifest;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.AppGlobals;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Select which activity is the first visible activity of the installation and forward the intent to
+ * it.
+ */
+public class InstallStart extends Activity {
+    private static final String LOG_TAG = InstallStart.class.getSimpleName();
+
+    private static final String DOWNLOADS_AUTHORITY = "downloads";
+    private IPackageManager mIPackageManager;
+    private boolean mAbortInstall = false;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mIPackageManager = AppGlobals.getPackageManager();
+        Intent intent = getIntent();
+        String callingPackage = getCallingPackage();
+
+        // If the activity was started via a PackageInstaller session, we retrieve the calling
+        // package from that session
+        int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
+        if (callingPackage == null && sessionId != -1) {
+            PackageInstaller packageInstaller = getPackageManager().getPackageInstaller();
+            PackageInstaller.SessionInfo sessionInfo = packageInstaller.getSessionInfo(sessionId);
+            callingPackage = (sessionInfo != null) ? sessionInfo.getInstallerPackageName() : null;
+        }
+
+        final ApplicationInfo sourceInfo = getSourceInfo(callingPackage);
+        final int originatingUid = getOriginatingUid(sourceInfo);
+        boolean isTrustedSource = false;
+        if (sourceInfo != null
+                && (sourceInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
+            isTrustedSource = intent.getBooleanExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, false);
+        }
+
+        if (!isTrustedSource && originatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
+            final int targetSdkVersion = getMaxTargetSdkVersionForUid(this, originatingUid);
+            if (targetSdkVersion < 0) {
+                Log.w(LOG_TAG, "Cannot get target sdk version for uid " + originatingUid);
+                // Invalid originating uid supplied. Abort install.
+                mAbortInstall = true;
+            } else if (targetSdkVersion >= Build.VERSION_CODES.O && !declaresAppOpPermission(
+                    originatingUid, Manifest.permission.REQUEST_INSTALL_PACKAGES)) {
+                Log.e(LOG_TAG, "Requesting uid " + originatingUid + " needs to declare permission "
+                        + Manifest.permission.REQUEST_INSTALL_PACKAGES);
+                mAbortInstall = true;
+            }
+        }
+        if (mAbortInstall) {
+            setResult(RESULT_CANCELED);
+            finish();
+            return;
+        }
+
+        Intent nextActivity = new Intent(intent);
+        nextActivity.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+
+        // The the installation source as the nextActivity thinks this activity is the source, hence
+        // set the originating UID and sourceInfo explicitly
+        nextActivity.putExtra(PackageInstallerActivity.EXTRA_CALLING_PACKAGE, callingPackage);
+        nextActivity.putExtra(PackageInstallerActivity.EXTRA_ORIGINAL_SOURCE_INFO, sourceInfo);
+        nextActivity.putExtra(Intent.EXTRA_ORIGINATING_UID, originatingUid);
+
+        if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) {
+            nextActivity.setClass(this, PackageInstallerActivity.class);
+        } else {
+            Uri packageUri = intent.getData();
+
+            if (packageUri != null && (packageUri.getScheme().equals(ContentResolver.SCHEME_FILE)
+                    || packageUri.getScheme().equals(ContentResolver.SCHEME_CONTENT))) {
+                // Copy file to prevent it from being changed underneath this process
+                nextActivity.setClass(this, InstallStaging.class);
+            } else if (packageUri != null && packageUri.getScheme().equals(
+                    PackageInstallerActivity.SCHEME_PACKAGE)) {
+                nextActivity.setClass(this, PackageInstallerActivity.class);
+            } else {
+                Intent result = new Intent();
+                result.putExtra(Intent.EXTRA_INSTALL_RESULT,
+                        PackageManager.INSTALL_FAILED_INVALID_URI);
+                setResult(RESULT_FIRST_USER, result);
+
+                nextActivity = null;
+            }
+        }
+
+        if (nextActivity != null) {
+            startActivity(nextActivity);
+        }
+        finish();
+    }
+
+    private boolean declaresAppOpPermission(int uid, String permission) {
+        try {
+            final String[] packages = mIPackageManager.getAppOpPermissionPackages(permission);
+            if (packages == null) {
+                return false;
+            }
+            for (String packageName : packages) {
+                try {
+                    if (uid == getPackageManager().getPackageUid(packageName, 0)) {
+                        return true;
+                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                    // Ignore and try the next package
+                }
+            }
+        } catch (RemoteException rexc) {
+            // If remote package manager cannot be reached, install will likely fail anyway.
+        }
+        return false;
+    }
+
+    /**
+     * @return the ApplicationInfo for the installation source (the calling package), if available
+     */
+    private ApplicationInfo getSourceInfo(@Nullable String callingPackage) {
+        if (callingPackage != null) {
+            try {
+                return getPackageManager().getApplicationInfo(callingPackage, 0);
+            } catch (PackageManager.NameNotFoundException ex) {
+                // ignore
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get the originating uid if possible, or
+     * {@link android.content.pm.PackageInstaller.SessionParams#UID_UNKNOWN} if not available
+     *
+     * @param sourceInfo The source of this installation
+     * @return The UID of the installation source or UID_UNKNOWN
+     */
+    private int getOriginatingUid(@Nullable ApplicationInfo sourceInfo) {
+        // The originating uid from the intent. We only trust/use this if it comes from either
+        // the document manager app or the downloads provider
+        final int uidFromIntent = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
+                PackageInstaller.SessionParams.UID_UNKNOWN);
+
+        final int callingUid;
+        if (sourceInfo != null) {
+            callingUid = sourceInfo.uid;
+        } else {
+            try {
+                callingUid = ActivityManager.getService()
+                        .getLaunchedFromUid(getActivityToken());
+            } catch (RemoteException ex) {
+                // Cannot reach ActivityManager. Aborting install.
+                Log.e(LOG_TAG, "Could not determine the launching uid.");
+                mAbortInstall = true;
+                return PackageInstaller.SessionParams.UID_UNKNOWN;
+            }
+        }
+        try {
+            if (mIPackageManager.checkUidPermission(Manifest.permission.MANAGE_DOCUMENTS,
+                    callingUid) == PackageManager.PERMISSION_GRANTED) {
+                return uidFromIntent;
+            }
+        } catch (RemoteException rexc) {
+            // Ignore. Should not happen.
+        }
+        if (isSystemDownloadsProvider(callingUid)) {
+            return uidFromIntent;
+        }
+        // We don't trust uid from the intent. Use the calling uid instead.
+        return callingUid;
+    }
+
+    private boolean isSystemDownloadsProvider(int uid) {
+        final ProviderInfo downloadProviderPackage = getPackageManager().resolveContentProvider(
+                DOWNLOADS_AUTHORITY, 0);
+        if (downloadProviderPackage == null) {
+            // There seems to be no currently enabled downloads provider on the system.
+            return false;
+        }
+        final ApplicationInfo appInfo = downloadProviderPackage.applicationInfo;
+        return (appInfo.isSystemApp() && uid == appInfo.uid);
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
new file mode 100644
index 0000000..705d3f4
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.internal.app.AlertActivity;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Finish installation: Return status code to the caller or display "success" UI to user
+ */
+public class InstallSuccess extends AlertActivity {
+    private static final String LOG_TAG = InstallSuccess.class.getSimpleName();
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
+            // Return result if requested
+            Intent result = new Intent();
+            result.putExtra(Intent.EXTRA_INSTALL_RESULT, PackageManager.INSTALL_SUCCEEDED);
+            setResult(Activity.RESULT_OK, result);
+            finish();
+        } else {
+            Intent intent = getIntent();
+            ApplicationInfo appInfo =
+                    intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+            Uri packageURI = intent.getData();
+
+            // Set header icon and title
+            PackageUtil.AppSnippet as;
+            PackageManager pm = getPackageManager();
+
+            if ("package".equals(packageURI.getScheme())) {
+                as = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
+                        pm.getApplicationIcon(appInfo));
+            } else {
+                File sourceFile = new File(packageURI.getPath());
+                as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
+            }
+
+            mAlert.setIcon(as.icon);
+            mAlert.setTitle(as.label);
+            mAlert.setView(R.layout.install_content_view);
+            mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.launch), null,
+                    null);
+            mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.done),
+                    (ignored, ignored2) -> {
+                        if (appInfo.packageName != null) {
+                            Log.i(LOG_TAG, "Finished installing " + appInfo.packageName);
+                        }
+                        finish();
+                    }, null);
+            setupAlert();
+            requireViewById(R.id.install_success).setVisibility(View.VISIBLE);
+            // Enable or disable "launch" button
+            Intent launchIntent = getPackageManager().getLaunchIntentForPackage(
+                    appInfo.packageName);
+            boolean enabled = false;
+            if (launchIntent != null) {
+                List<ResolveInfo> list = getPackageManager().queryIntentActivities(launchIntent,
+                        0);
+                if (list != null && list.size() > 0) {
+                    enabled = true;
+                }
+            }
+
+            Button launchButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
+            if (enabled) {
+                launchButton.setOnClickListener(view -> {
+                    try {
+                        startActivity(launchIntent);
+                    } catch (ActivityNotFoundException | SecurityException e) {
+                        Log.e(LOG_TAG, "Could not start activity", e);
+                    }
+                    finish();
+                });
+            } else {
+                launchButton.setEnabled(false);
+            }
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
new file mode 100644
index 0000000..580308a
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -0,0 +1,767 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.StringRes;
+import android.app.AlertDialog;
+import android.app.AppGlobals;
+import android.app.AppOpsManager;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.ActivityNotFoundException;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageUserState;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.internal.app.AlertActivity;
+
+import java.io.File;
+
+/**
+ * This activity is launched when a new application is installed via side loading
+ * The package is first parsed and the user is notified of parse errors via a dialog.
+ * If the package is successfully parsed, the user is notified to turn on the install unknown
+ * applications setting. A memory check is made at this point and the user is notified of out
+ * of memory conditions if any. If the package is already existing on the device,
+ * a confirmation dialog (to replace the existing package) is presented to the user.
+ * Based on the user response the package is then installed by launching InstallAppConfirm
+ * sub activity. All state transitions are handled in this activity
+ */
+public class PackageInstallerActivity extends AlertActivity {
+    private static final String TAG = "PackageInstaller";
+
+    private static final int REQUEST_TRUST_EXTERNAL_SOURCE = 1;
+
+    static final String SCHEME_PACKAGE = "package";
+
+    static final String EXTRA_CALLING_PACKAGE = "EXTRA_CALLING_PACKAGE";
+    static final String EXTRA_ORIGINAL_SOURCE_INFO = "EXTRA_ORIGINAL_SOURCE_INFO";
+    private static final String ALLOW_UNKNOWN_SOURCES_KEY =
+            PackageInstallerActivity.class.getName() + "ALLOW_UNKNOWN_SOURCES_KEY";
+
+    private int mSessionId = -1;
+    private Uri mPackageURI;
+    private Uri mOriginatingURI;
+    private Uri mReferrerURI;
+    private int mOriginatingUid = PackageInstaller.SessionParams.UID_UNKNOWN;
+    private String mOriginatingPackage; // The package name corresponding to #mOriginatingUid
+
+    private boolean localLOGV = false;
+    PackageManager mPm;
+    IPackageManager mIpm;
+    AppOpsManager mAppOpsManager;
+    UserManager mUserManager;
+    PackageInstaller mInstaller;
+    PackageInfo mPkgInfo;
+    String mCallingPackage;
+    ApplicationInfo mSourceInfo;
+
+    // ApplicationInfo object primarily used for already existing applications
+    private ApplicationInfo mAppInfo = null;
+
+    // Buttons to indicate user acceptance
+    private Button mOk;
+
+    private PackageUtil.AppSnippet mAppSnippet;
+
+    static final String PREFS_ALLOWED_SOURCES = "allowed_sources";
+
+    // Dialog identifiers used in showDialog
+    private static final int DLG_BASE = 0;
+    private static final int DLG_PACKAGE_ERROR = DLG_BASE + 2;
+    private static final int DLG_OUT_OF_SPACE = DLG_BASE + 3;
+    private static final int DLG_INSTALL_ERROR = DLG_BASE + 4;
+    private static final int DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER = DLG_BASE + 5;
+    private static final int DLG_ANONYMOUS_SOURCE = DLG_BASE + 6;
+    private static final int DLG_NOT_SUPPORTED_ON_WEAR = DLG_BASE + 7;
+    private static final int DLG_EXTERNAL_SOURCE_BLOCKED = DLG_BASE + 8;
+    private static final int DLG_INSTALL_APPS_RESTRICTED_FOR_USER = DLG_BASE + 9;
+
+    // If unknown sources are temporary allowed
+    private boolean mAllowUnknownSources;
+
+    // Would the mOk button be enabled if this activity would be resumed
+    private boolean mEnableOk = false;
+
+    private void startInstallConfirm() {
+        View viewToEnable;
+
+        if (mAppInfo != null) {
+            viewToEnable = (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
+                    ? requireViewById(R.id.install_confirm_question_update_system)
+                    : requireViewById(R.id.install_confirm_question_update);
+        } else {
+            // This is a new application with no permissions.
+            viewToEnable = requireViewById(R.id.install_confirm_question);
+        }
+
+        viewToEnable.setVisibility(View.VISIBLE);
+
+        mEnableOk = true;
+        mOk.setEnabled(true);
+    }
+
+    /**
+     * Replace any dialog shown by the dialog with the one for the given {@link #createDialog id}.
+     *
+     * @param id The dialog type to add
+     */
+    private void showDialogInner(int id) {
+        DialogFragment currentDialog =
+                (DialogFragment) getFragmentManager().findFragmentByTag("dialog");
+        if (currentDialog != null) {
+            currentDialog.dismissAllowingStateLoss();
+        }
+
+        DialogFragment newDialog = createDialog(id);
+        if (newDialog != null) {
+            newDialog.showAllowingStateLoss(getFragmentManager(), "dialog");
+        }
+    }
+
+    /**
+     * Create a new dialog.
+     *
+     * @param id The id of the dialog (determines dialog type)
+     *
+     * @return The dialog
+     */
+    private DialogFragment createDialog(int id) {
+        switch (id) {
+            case DLG_PACKAGE_ERROR:
+                return SimpleErrorDialog.newInstance(R.string.Parse_error_dlg_text);
+            case DLG_OUT_OF_SPACE:
+                return OutOfSpaceDialog.newInstance(
+                        mPm.getApplicationLabel(mPkgInfo.applicationInfo));
+            case DLG_INSTALL_ERROR:
+                return InstallErrorDialog.newInstance(
+                        mPm.getApplicationLabel(mPkgInfo.applicationInfo));
+            case DLG_NOT_SUPPORTED_ON_WEAR:
+                return NotSupportedOnWearDialog.newInstance();
+            case DLG_INSTALL_APPS_RESTRICTED_FOR_USER:
+                return SimpleErrorDialog.newInstance(
+                        R.string.install_apps_user_restriction_dlg_text);
+            case DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER:
+                return SimpleErrorDialog.newInstance(
+                        R.string.unknown_apps_user_restriction_dlg_text);
+            case DLG_EXTERNAL_SOURCE_BLOCKED:
+                return ExternalSourcesBlockedDialog.newInstance(mOriginatingPackage);
+            case DLG_ANONYMOUS_SOURCE:
+                return AnonymousSourceDialog.newInstance();
+        }
+        return null;
+    }
+
+    @Override
+    public void onActivityResult(int request, int result, Intent data) {
+        if (request == REQUEST_TRUST_EXTERNAL_SOURCE && result == RESULT_OK) {
+            // The user has just allowed this package to install other packages (via Settings).
+            mAllowUnknownSources = true;
+
+            // Log the fact that the app is requesting an install, and is now allowed to do it
+            // (before this point we could only log that it's requesting an install, but isn't
+            // allowed to do it yet).
+            int appOpCode =
+                    AppOpsManager.permissionToOpCode(Manifest.permission.REQUEST_INSTALL_PACKAGES);
+            mAppOpsManager.noteOpNoThrow(appOpCode, mOriginatingUid, mOriginatingPackage);
+
+            DialogFragment currentDialog =
+                    (DialogFragment) getFragmentManager().findFragmentByTag("dialog");
+            if (currentDialog != null) {
+                currentDialog.dismissAllowingStateLoss();
+            }
+
+            initiateInstall();
+        } else {
+            finish();
+        }
+    }
+
+    private String getPackageNameForUid(int sourceUid) {
+        String[] packagesForUid = mPm.getPackagesForUid(sourceUid);
+        if (packagesForUid == null) {
+            return null;
+        }
+        if (packagesForUid.length > 1) {
+            if (mCallingPackage != null) {
+                for (String packageName : packagesForUid) {
+                    if (packageName.equals(mCallingPackage)) {
+                        return packageName;
+                    }
+                }
+            }
+            Log.i(TAG, "Multiple packages found for source uid " + sourceUid);
+        }
+        return packagesForUid[0];
+    }
+
+    private boolean isInstallRequestFromUnknownSource(Intent intent) {
+        if (mCallingPackage != null && intent.getBooleanExtra(
+                Intent.EXTRA_NOT_UNKNOWN_SOURCE, false)) {
+            if (mSourceInfo != null) {
+                if ((mSourceInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
+                        != 0) {
+                    // Privileged apps can bypass unknown sources check if they want.
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private void initiateInstall() {
+        String pkgName = mPkgInfo.packageName;
+        // Check if there is already a package on the device with this name
+        // but it has been renamed to something else.
+        String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName });
+        if (oldName != null && oldName.length > 0 && oldName[0] != null) {
+            pkgName = oldName[0];
+            mPkgInfo.packageName = pkgName;
+            mPkgInfo.applicationInfo.packageName = pkgName;
+        }
+        // Check if package is already installed. display confirmation dialog if replacing pkg
+        try {
+            // This is a little convoluted because we want to get all uninstalled
+            // apps, but this may include apps with just data, and if it is just
+            // data we still want to count it as "installed".
+            mAppInfo = mPm.getApplicationInfo(pkgName,
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES);
+            if ((mAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
+                mAppInfo = null;
+            }
+        } catch (NameNotFoundException e) {
+            mAppInfo = null;
+        }
+
+        startInstallConfirm();
+    }
+
+    void setPmResult(int pmResult) {
+        Intent result = new Intent();
+        result.putExtra(Intent.EXTRA_INSTALL_RESULT, pmResult);
+        setResult(pmResult == PackageManager.INSTALL_SUCCEEDED
+                ? RESULT_OK : RESULT_FIRST_USER, result);
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
+        super.onCreate(null);
+
+        if (icicle != null) {
+            mAllowUnknownSources = icicle.getBoolean(ALLOW_UNKNOWN_SOURCES_KEY);
+        }
+
+        mPm = getPackageManager();
+        mIpm = AppGlobals.getPackageManager();
+        mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
+        mInstaller = mPm.getPackageInstaller();
+        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
+
+        final Intent intent = getIntent();
+
+        mCallingPackage = intent.getStringExtra(EXTRA_CALLING_PACKAGE);
+        mSourceInfo = intent.getParcelableExtra(EXTRA_ORIGINAL_SOURCE_INFO);
+        mOriginatingUid = intent.getIntExtra(Intent.EXTRA_ORIGINATING_UID,
+                PackageInstaller.SessionParams.UID_UNKNOWN);
+        mOriginatingPackage = (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN)
+                ? getPackageNameForUid(mOriginatingUid) : null;
+
+
+        final Uri packageUri;
+
+        if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) {
+            final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
+            final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
+            if (info == null || !info.sealed || info.resolvedBaseCodePath == null) {
+                Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
+                finish();
+                return;
+            }
+
+            mSessionId = sessionId;
+            packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
+            mOriginatingURI = null;
+            mReferrerURI = null;
+        } else {
+            mSessionId = -1;
+            packageUri = intent.getData();
+            mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
+            mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
+        }
+
+        // if there's nothing to do, quietly slip into the ether
+        if (packageUri == null) {
+            Log.w(TAG, "Unspecified source");
+            setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
+            finish();
+            return;
+        }
+
+        if (DeviceUtils.isWear(this)) {
+            showDialogInner(DLG_NOT_SUPPORTED_ON_WEAR);
+            return;
+        }
+
+        boolean wasSetUp = processPackageUri(packageUri);
+        if (!wasSetUp) {
+            return;
+        }
+
+        // load dummy layout with OK button disabled until we override this layout in
+        // startInstallConfirm
+        bindUi();
+        checkIfAllowedAndInitiateInstall();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        if (mOk != null) {
+            mOk.setEnabled(mEnableOk);
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+
+        if (mOk != null) {
+            // Don't allow the install button to be clicked as there might be overlays
+            mOk.setEnabled(false);
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putBoolean(ALLOW_UNKNOWN_SOURCES_KEY, mAllowUnknownSources);
+    }
+
+    private void bindUi() {
+        mAlert.setIcon(mAppSnippet.icon);
+        mAlert.setTitle(mAppSnippet.label);
+        mAlert.setView(R.layout.install_content_view);
+        mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
+                (ignored, ignored2) -> {
+                    if (mOk.isEnabled()) {
+                        if (mSessionId != -1) {
+                            mInstaller.setPermissionsResult(mSessionId, true);
+                            finish();
+                        } else {
+                            startInstall();
+                        }
+                    }
+                }, null);
+        mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
+                (ignored, ignored2) -> {
+                    // Cancel and finish
+                    setResult(RESULT_CANCELED);
+                    if (mSessionId != -1) {
+                        mInstaller.setPermissionsResult(mSessionId, false);
+                    }
+                    finish();
+                }, null);
+        setupAlert();
+
+        mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
+        mOk.setEnabled(false);
+    }
+
+    /**
+     * Check if it is allowed to install the package and initiate install if allowed. If not allowed
+     * show the appropriate dialog.
+     */
+    private void checkIfAllowedAndInitiateInstall() {
+        // Check for install apps user restriction first.
+        final int installAppsRestrictionSource = mUserManager.getUserRestrictionSource(
+                UserManager.DISALLOW_INSTALL_APPS, Process.myUserHandle());
+        if ((installAppsRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
+            showDialogInner(DLG_INSTALL_APPS_RESTRICTED_FOR_USER);
+            return;
+        } else if (installAppsRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
+            startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
+            finish();
+            return;
+        }
+
+        if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
+            initiateInstall();
+        } else {
+            // Check for unknown sources restriction
+            final int unknownSourcesRestrictionSource = mUserManager.getUserRestrictionSource(
+                    UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, Process.myUserHandle());
+            if ((unknownSourcesRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
+                showDialogInner(DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER);
+            } else if (unknownSourcesRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
+                startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
+                finish();
+            } else {
+                handleUnknownSources();
+            }
+        }
+    }
+
+    private void handleUnknownSources() {
+        if (mOriginatingPackage == null) {
+            Log.i(TAG, "No source found for package " + mPkgInfo.packageName);
+            showDialogInner(DLG_ANONYMOUS_SOURCE);
+            return;
+        }
+        // Shouldn't use static constant directly, see b/65534401.
+        final int appOpCode =
+                AppOpsManager.permissionToOpCode(Manifest.permission.REQUEST_INSTALL_PACKAGES);
+        final int appOpMode = mAppOpsManager.noteOpNoThrow(appOpCode,
+                mOriginatingUid, mOriginatingPackage);
+        switch (appOpMode) {
+            case AppOpsManager.MODE_DEFAULT:
+                try {
+                    int result = mIpm.checkUidPermission(
+                            Manifest.permission.REQUEST_INSTALL_PACKAGES, mOriginatingUid);
+                    if (result == PackageManager.PERMISSION_GRANTED) {
+                        initiateInstall();
+                        break;
+                    }
+                } catch (RemoteException exc) {
+                    Log.e(TAG, "Unable to talk to package manager");
+                }
+                mAppOpsManager.setMode(appOpCode, mOriginatingUid,
+                        mOriginatingPackage, AppOpsManager.MODE_ERRORED);
+                // fall through
+            case AppOpsManager.MODE_ERRORED:
+                showDialogInner(DLG_EXTERNAL_SOURCE_BLOCKED);
+                break;
+            case AppOpsManager.MODE_ALLOWED:
+                initiateInstall();
+                break;
+            default:
+                Log.e(TAG, "Invalid app op mode " + appOpMode
+                        + " for OP_REQUEST_INSTALL_PACKAGES found for uid " + mOriginatingUid);
+                finish();
+                break;
+        }
+    }
+
+    /**
+     * Parse the Uri and set up the installer for this package.
+     *
+     * @param packageUri The URI to parse
+     *
+     * @return {@code true} iff the installer could be set up
+     */
+    private boolean processPackageUri(final Uri packageUri) {
+        mPackageURI = packageUri;
+
+        final String scheme = packageUri.getScheme();
+
+        switch (scheme) {
+            case SCHEME_PACKAGE: {
+                try {
+                    mPkgInfo = mPm.getPackageInfo(packageUri.getSchemeSpecificPart(),
+                            PackageManager.GET_PERMISSIONS
+                                    | PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                } catch (NameNotFoundException e) {
+                }
+                if (mPkgInfo == null) {
+                    Log.w(TAG, "Requested package " + packageUri.getScheme()
+                            + " not available. Discontinuing installation");
+                    showDialogInner(DLG_PACKAGE_ERROR);
+                    setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
+                    return false;
+                }
+                mAppSnippet = new PackageUtil.AppSnippet(mPm.getApplicationLabel(mPkgInfo.applicationInfo),
+                        mPm.getApplicationIcon(mPkgInfo.applicationInfo));
+            } break;
+
+            case ContentResolver.SCHEME_FILE: {
+                File sourceFile = new File(packageUri.getPath());
+                PackageParser.Package parsed = PackageUtil.getPackageInfo(this, sourceFile);
+
+                // Check for parse errors
+                if (parsed == null) {
+                    Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
+                    showDialogInner(DLG_PACKAGE_ERROR);
+                    setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
+                    return false;
+                }
+                mPkgInfo = PackageParser.generatePackageInfo(parsed, null,
+                        PackageManager.GET_PERMISSIONS, 0, 0, null,
+                        new PackageUserState());
+                mAppSnippet = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
+            } break;
+
+            default: {
+                throw new IllegalArgumentException("Unexpected URI scheme " + packageUri);
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (mSessionId != -1) {
+            mInstaller.setPermissionsResult(mSessionId, false);
+        }
+        super.onBackPressed();
+    }
+
+    private void startInstall() {
+        // Start subactivity to actually install the application
+        Intent newIntent = new Intent();
+        newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
+                mPkgInfo.applicationInfo);
+        newIntent.setData(mPackageURI);
+        newIntent.setClass(this, InstallInstalling.class);
+        String installerPackageName = getIntent().getStringExtra(
+                Intent.EXTRA_INSTALLER_PACKAGE_NAME);
+        if (mOriginatingURI != null) {
+            newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
+        }
+        if (mReferrerURI != null) {
+            newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
+        }
+        if (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
+            newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
+        }
+        if (installerPackageName != null) {
+            newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
+                    installerPackageName);
+        }
+        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
+            newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
+        }
+        newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+        if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
+        startActivity(newIntent);
+        finish();
+    }
+
+    /**
+     * A simple error dialog showing a message
+     */
+    public static class SimpleErrorDialog extends DialogFragment {
+        private static final String MESSAGE_KEY =
+                SimpleErrorDialog.class.getName() + "MESSAGE_KEY";
+
+        static SimpleErrorDialog newInstance(@StringRes int message) {
+            SimpleErrorDialog dialog = new SimpleErrorDialog();
+
+            Bundle args = new Bundle();
+            args.putInt(MESSAGE_KEY, message);
+            dialog.setArguments(args);
+
+            return dialog;
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            return new AlertDialog.Builder(getActivity())
+                    .setMessage(getArguments().getInt(MESSAGE_KEY))
+                    .setPositiveButton(R.string.ok, (dialog, which) -> getActivity().finish())
+                    .create();
+        }
+    }
+
+    /**
+     * Dialog to show when the source of apk can not be identified
+     */
+    public static class AnonymousSourceDialog extends DialogFragment {
+        static AnonymousSourceDialog newInstance() {
+            return new AnonymousSourceDialog();
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            return new AlertDialog.Builder(getActivity())
+                    .setMessage(R.string.anonymous_source_warning)
+                    .setPositiveButton(R.string.anonymous_source_continue,
+                            ((dialog, which) -> {
+                                PackageInstallerActivity activity = ((PackageInstallerActivity)
+                                        getActivity());
+
+                                activity.mAllowUnknownSources = true;
+                                activity.initiateInstall();
+                            }))
+                    .setNegativeButton(R.string.cancel, ((dialog, which) -> getActivity().finish()))
+                    .create();
+        }
+
+        @Override
+        public void onCancel(DialogInterface dialog) {
+            getActivity().finish();
+        }
+    }
+
+    /**
+     * An error dialog shown when the app is not supported on wear
+     */
+    public static class NotSupportedOnWearDialog extends SimpleErrorDialog {
+        static SimpleErrorDialog newInstance() {
+            return SimpleErrorDialog.newInstance(R.string.wear_not_allowed_dlg_text);
+        }
+
+        @Override
+        public void onCancel(DialogInterface dialog) {
+            getActivity().setResult(RESULT_OK);
+            getActivity().finish();
+        }
+    }
+
+    /**
+     * An error dialog shown when the device is out of space
+     */
+    public static class OutOfSpaceDialog extends AppErrorDialog {
+        static AppErrorDialog newInstance(@NonNull CharSequence applicationLabel) {
+            OutOfSpaceDialog dialog = new OutOfSpaceDialog();
+            dialog.setArgument(applicationLabel);
+            return dialog;
+        }
+
+        @Override
+        protected Dialog createDialog(@NonNull CharSequence argument) {
+            String dlgText = getString(R.string.out_of_space_dlg_text, argument);
+            return new AlertDialog.Builder(getActivity())
+                    .setMessage(dlgText)
+                    .setPositiveButton(R.string.manage_applications, (dialog, which) -> {
+                        // launch manage applications
+                        Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        startActivity(intent);
+                        getActivity().finish();
+                    })
+                    .setNegativeButton(R.string.cancel, (dialog, which) -> getActivity().finish())
+                    .create();
+        }
+    }
+
+    /**
+     * A generic install-error dialog
+     */
+    public static class InstallErrorDialog extends AppErrorDialog {
+        static AppErrorDialog newInstance(@NonNull CharSequence applicationLabel) {
+            InstallErrorDialog dialog = new InstallErrorDialog();
+            dialog.setArgument(applicationLabel);
+            return dialog;
+        }
+
+        @Override
+        protected Dialog createDialog(@NonNull CharSequence argument) {
+            return new AlertDialog.Builder(getActivity())
+                    .setNeutralButton(R.string.ok, (dialog, which) -> getActivity().finish())
+                    .setMessage(getString(R.string.install_failed_msg, argument))
+                    .create();
+        }
+    }
+
+    /**
+     * An error dialog shown when external sources are not allowed
+     */
+    public static class ExternalSourcesBlockedDialog extends AppErrorDialog {
+        static AppErrorDialog newInstance(@NonNull String originationPkg) {
+            ExternalSourcesBlockedDialog dialog = new ExternalSourcesBlockedDialog();
+            dialog.setArgument(originationPkg);
+            return dialog;
+        }
+
+        @Override
+        protected Dialog createDialog(@NonNull CharSequence argument) {
+            try {
+                PackageManager pm = getActivity().getPackageManager();
+
+                ApplicationInfo sourceInfo = pm.getApplicationInfo(argument.toString(), 0);
+
+                return new AlertDialog.Builder(getActivity())
+                        .setTitle(pm.getApplicationLabel(sourceInfo))
+                        .setIcon(pm.getApplicationIcon(sourceInfo))
+                        .setMessage(R.string.untrusted_external_source_warning)
+                        .setPositiveButton(R.string.external_sources_settings,
+                                (dialog, which) -> {
+                                    Intent settingsIntent = new Intent();
+                                    settingsIntent.setAction(
+                                            Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
+                                    final Uri packageUri = Uri.parse("package:" + argument);
+                                    settingsIntent.setData(packageUri);
+                                    try {
+                                        getActivity().startActivityForResult(settingsIntent,
+                                                REQUEST_TRUST_EXTERNAL_SOURCE);
+                                    } catch (ActivityNotFoundException exc) {
+                                        Log.e(TAG, "Settings activity not found for action: "
+                                                + Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
+                                    }
+                                })
+                        .setNegativeButton(R.string.cancel,
+                                (dialog, which) -> getActivity().finish())
+                        .create();
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "Did not find app info for " + argument);
+                getActivity().finish();
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Superclass for all error dialogs. Stores a single CharSequence argument
+     */
+    public abstract static class AppErrorDialog extends DialogFragment {
+        private static final String ARGUMENT_KEY = AppErrorDialog.class.getName() + "ARGUMENT_KEY";
+
+        protected void setArgument(@NonNull CharSequence argument) {
+            Bundle args = new Bundle();
+            args.putCharSequence(ARGUMENT_KEY, argument);
+            setArguments(args);
+        }
+
+        protected abstract Dialog createDialog(@NonNull CharSequence argument);
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            return createDialog(getArguments().getString(ARGUMENT_KEY));
+        }
+
+        @Override
+        public void onCancel(DialogInterface dialog) {
+            getActivity().finish();
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerApplication.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerApplication.java
new file mode 100644
index 0000000..9b7e64e
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerApplication.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.app.Application;
+import android.content.pm.PackageItemInfo;
+
+public class PackageInstallerApplication extends Application {
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        PackageItemInfo.setForceSafeLabels(true);
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
new file mode 100644
index 0000000..0e89f56
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
@@ -0,0 +1,190 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package com.android.packageinstaller;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageParserException;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.io.File;
+
+/**
+ * This is a utility class for defining some utility methods and constants
+ * used in the package installer application.
+ */
+public class PackageUtil {
+    private static final String LOG_TAG = PackageUtil.class.getSimpleName();
+
+    public static final String PREFIX="com.android.packageinstaller.";
+    public static final String INTENT_ATTR_INSTALL_STATUS = PREFIX+"installStatus";
+    public static final String INTENT_ATTR_APPLICATION_INFO=PREFIX+"applicationInfo";
+    public static final String INTENT_ATTR_PERMISSIONS_LIST=PREFIX+"PermissionsList";
+    //intent attribute strings related to uninstall
+    public static final String INTENT_ATTR_PACKAGE_NAME=PREFIX+"PackageName";
+
+    /**
+     * Utility method to get package information for a given {@link File}
+     */
+    public static PackageParser.Package getPackageInfo(Context context, File sourceFile) {
+        final PackageParser parser = new PackageParser();
+        parser.setCallback(new PackageParser.CallbackImpl(context.getPackageManager()));
+        try {
+            return parser.parsePackage(sourceFile, 0);
+        } catch (PackageParserException e) {
+            return null;
+        }
+    }
+
+    public static View initSnippet(View snippetView, CharSequence label, Drawable icon) {
+        ((ImageView)snippetView.findViewById(R.id.app_icon)).setImageDrawable(icon);
+        ((TextView)snippetView.findViewById(R.id.app_name)).setText(label);
+        return snippetView;
+    }
+
+    /**
+     * Utility method to display a snippet of an installed application.
+     * The content view should have been set on context before invoking this method.
+     * appSnippet view should include R.id.app_icon and R.id.app_name
+     * defined on it.
+     *
+     * @param pContext context of package that can load the resources
+     * @param componentInfo ComponentInfo object whose resources are to be loaded
+     * @param snippetView the snippet view
+     */
+    public static View initSnippetForInstalledApp(Context pContext,
+            ApplicationInfo appInfo, View snippetView) {
+        return initSnippetForInstalledApp(pContext, appInfo, snippetView, null);
+    }
+
+    /**
+     * Utility method to display a snippet of an installed application.
+     * The content view should have been set on context before invoking this method.
+     * appSnippet view should include R.id.app_icon and R.id.app_name
+     * defined on it.
+     *
+     * @param pContext context of package that can load the resources
+     * @param componentInfo ComponentInfo object whose resources are to be loaded
+     * @param snippetView the snippet view
+     * @param UserHandle user that the app si installed for.
+     */
+    public static View initSnippetForInstalledApp(Context pContext,
+            ApplicationInfo appInfo, View snippetView, UserHandle user) {
+        final PackageManager pm = pContext.getPackageManager();
+        Drawable icon = appInfo.loadIcon(pm);
+        if (user != null) {
+            icon = pContext.getPackageManager().getUserBadgedIcon(icon, user);
+        }
+        return initSnippet(
+                snippetView,
+                appInfo.loadLabel(pm),
+                icon);
+    }
+
+    static public class AppSnippet {
+        @NonNull public CharSequence label;
+        @Nullable public Drawable icon;
+        public AppSnippet(@NonNull CharSequence label, @Nullable Drawable icon) {
+            this.label = label;
+            this.icon = icon;
+        }
+    }
+
+    /**
+     * Utility method to load application label
+     *
+     * @param pContext context of package that can load the resources
+     * @param appInfo ApplicationInfo object of package whose resources are to be loaded
+     * @param sourceFile File the package is in
+     */
+    public static AppSnippet getAppSnippet(
+            Activity pContext, ApplicationInfo appInfo, File sourceFile) {
+        final String archiveFilePath = sourceFile.getAbsolutePath();
+        Resources pRes = pContext.getResources();
+        AssetManager assmgr = new AssetManager();
+        assmgr.addAssetPath(archiveFilePath);
+        Resources res = new Resources(assmgr, pRes.getDisplayMetrics(), pRes.getConfiguration());
+        CharSequence label = null;
+        // Try to load the label from the package's resources. If an app has not explicitly
+        // specified any label, just use the package name.
+        if (appInfo.labelRes != 0) {
+            try {
+                label = res.getText(appInfo.labelRes);
+            } catch (Resources.NotFoundException e) {
+            }
+        }
+        if (label == null) {
+            label = (appInfo.nonLocalizedLabel != null) ?
+                    appInfo.nonLocalizedLabel : appInfo.packageName;
+        }
+        Drawable icon = null;
+        // Try to load the icon from the package's resources. If an app has not explicitly
+        // specified any resource, just use the default icon for now.
+        try {
+            if (appInfo.icon != 0) {
+                try {
+                    icon = res.getDrawable(appInfo.icon);
+                } catch (Resources.NotFoundException e) {
+                }
+            }
+            if (icon == null) {
+                icon = pContext.getPackageManager().getDefaultActivityIcon();
+            }
+        } catch (OutOfMemoryError e) {
+            Log.i(LOG_TAG, "Could not load app icon", e);
+        }
+        return new PackageUtil.AppSnippet(label, icon);
+    }
+
+    /**
+     * Get the maximum target sdk for a UID.
+     *
+     * @param context The context to use
+     * @param uid The UID requesting the install/uninstall
+     *
+     * @return The maximum target SDK or -1 if the uid does not match any packages.
+     */
+    static int getMaxTargetSdkVersionForUid(@NonNull Context context, int uid) {
+        PackageManager pm = context.getPackageManager();
+        final String[] packages = pm.getPackagesForUid(uid);
+        int targetSdkVersion = -1;
+        if (packages != null) {
+            for (String packageName : packages) {
+                try {
+                    ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+                    targetSdkVersion = Math.max(targetSdkVersion, info.targetSdkVersion);
+                } catch (PackageManager.NameNotFoundException e) {
+                    // Ignore and try the next package
+                }
+            }
+        }
+        return targetSdkVersion;
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/RemoveReceiver.java b/packages/PackageInstaller/src/com/android/packageinstaller/RemoveReceiver.java
new file mode 100644
index 0000000..7d8064d
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/RemoveReceiver.java
@@ -0,0 +1,42 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+
+public class RemoveReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(intent.getAction())) {
+            Uri uri = intent.getData();
+            String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
+            if (pkg != null) {
+                SharedPreferences prefs = context.getSharedPreferences(
+                        PackageInstallerActivity.PREFS_ALLOWED_SOURCES,
+                        Context.MODE_PRIVATE);
+                if (prefs.getBoolean(pkg, false)) {
+                    prefs.edit().remove(pkg).apply();
+                }
+            }
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/TemporaryFileManager.java b/packages/PackageInstaller/src/com/android/packageinstaller/TemporaryFileManager.java
new file mode 100644
index 0000000..f77318c
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/TemporaryFileManager.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Manages files of the package installer and resets state during boot.
+ */
+public class TemporaryFileManager extends BroadcastReceiver {
+    private static final String LOG_TAG = TemporaryFileManager.class.getSimpleName();
+
+    /**
+     * Create a new file to hold a staged file.
+     *
+     * @param context The context of the caller
+     *
+     * @return A new file
+     */
+    @NonNull
+    public static File getStagedFile(@NonNull Context context) throws IOException {
+        return File.createTempFile("package", ".apk", context.getNoBackupFilesDir());
+    }
+
+    /**
+     * Get the file used to store the results of installs.
+     *
+     * @param context The context of the caller
+     *
+     * @return the file used to store the results of installs
+     */
+    @NonNull
+    public static File getInstallStateFile(@NonNull Context context) {
+        return new File(context.getNoBackupFilesDir(), "install_results.xml");
+    }
+
+    /**
+     * Get the file used to store the results of uninstalls.
+     *
+     * @param context The context of the caller
+     *
+     * @return the file used to store the results of uninstalls
+     */
+    @NonNull
+    public static File getUninstallStateFile(@NonNull Context context) {
+        return new File(context.getNoBackupFilesDir(), "uninstall_results.xml");
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        long systemBootTime = System.currentTimeMillis() - SystemClock.elapsedRealtime();
+
+        File[] filesOnBoot = context.getNoBackupFilesDir().listFiles();
+
+        if (filesOnBoot == null) {
+            return;
+        }
+
+        for (int i = 0; i < filesOnBoot.length; i++) {
+            File fileOnBoot = filesOnBoot[i];
+
+            if (systemBootTime > fileOnBoot.lastModified()) {
+                boolean wasDeleted = fileOnBoot.delete();
+                if (!wasDeleted) {
+                    Log.w(LOG_TAG, "Could not delete " + fileOnBoot.getName() + " onBoot");
+                }
+            } else {
+                Log.w(LOG_TAG, fileOnBoot.getName() + " was created before onBoot broadcast was "
+                        + "received");
+            }
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallEventReceiver.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallEventReceiver.java
new file mode 100644
index 0000000..c3e9c23
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallEventReceiver.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Receives uninstall events and persists them using a {@link EventResultPersister}.
+ */
+public class UninstallEventReceiver extends BroadcastReceiver {
+    private static final Object sLock = new Object();
+    private static EventResultPersister sReceiver;
+
+    /**
+     * Get the event receiver persisting the results
+     *
+     * @return The event receiver.
+     */
+    @NonNull private static EventResultPersister getReceiver(@NonNull Context context) {
+        synchronized (sLock) {
+            if (sReceiver == null) {
+                sReceiver = new EventResultPersister(
+                        TemporaryFileManager.getUninstallStateFile(context));
+            }
+        }
+
+        return sReceiver;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        getReceiver(context).onEventReceived(context, intent);
+    }
+
+    /**
+     * Add an observer. If there is already an event for this id, call back inside of this call.
+     *
+     * @param context  A context of the current app
+     * @param id       The id the observer is for or {@code GENERATE_NEW_ID} to generate a new one.
+     * @param observer The observer to call back.
+     *
+     * @return The id for this event
+     */
+    static int addObserver(@NonNull Context context, int id,
+            @NonNull EventResultPersister.EventResultObserver observer)
+            throws EventResultPersister.OutOfIdsException {
+        return getReceiver(context).addObserver(id, observer);
+    }
+
+    /**
+     * Remove a observer.
+     *
+     * @param context  A context of the current app
+     * @param id The id the observer was added for
+     */
+    static void removeObserver(@NonNull Context context, int id) {
+        getReceiver(context).removeObserver(id);
+    }
+
+    /**
+     * @param context A context of the current app
+     *
+     * @return A new uninstall id
+     */
+    static int getNewId(@NonNull Context context) throws EventResultPersister.OutOfIdsException {
+        return getReceiver(context).getNewId();
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallFinish.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallFinish.java
new file mode 100644
index 0000000..5a51ac2
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallFinish.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.NonNull;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.admin.IDevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.graphics.drawable.Icon;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.util.List;
+
+/**
+ * Finish an uninstallation and show Toast on success or failure notification.
+ */
+public class UninstallFinish extends BroadcastReceiver {
+    private static final String LOG_TAG = UninstallFinish.class.getSimpleName();
+
+    private static final String UNINSTALL_FAILURE_CHANNEL = "uninstall failure";
+
+    static final String EXTRA_UNINSTALL_ID = "com.android.packageinstaller.extra.UNINSTALL_ID";
+    static final String EXTRA_APP_LABEL = "com.android.packageinstaller.extra.APP_LABEL";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        int returnCode = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, 0);
+
+        Log.i(LOG_TAG, "Uninstall finished extras=" + intent.getExtras());
+
+        if (returnCode == PackageInstaller.STATUS_PENDING_USER_ACTION) {
+            context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT));
+            return;
+        }
+
+        int uninstallId = intent.getIntExtra(EXTRA_UNINSTALL_ID, 0);
+        ApplicationInfo appInfo = intent.getParcelableExtra(
+                PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+        String appLabel = intent.getStringExtra(EXTRA_APP_LABEL);
+        boolean allUsers = intent.getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false);
+
+        NotificationManager notificationManager =
+                context.getSystemService(NotificationManager.class);
+        UserManager userManager = context.getSystemService(UserManager.class);
+
+        NotificationChannel uninstallFailureChannel = new NotificationChannel(
+                UNINSTALL_FAILURE_CHANNEL,
+                context.getString(R.string.uninstall_failure_notification_channel),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        notificationManager.createNotificationChannel(uninstallFailureChannel);
+
+        Notification.Builder uninstallFailedNotification = new Notification.Builder(context,
+                UNINSTALL_FAILURE_CHANNEL);
+
+        switch (returnCode) {
+            case PackageInstaller.STATUS_SUCCESS:
+                notificationManager.cancel(uninstallId);
+
+                Toast.makeText(context, context.getString(R.string.uninstall_done_app, appLabel),
+                        Toast.LENGTH_LONG).show();
+                return;
+            case PackageInstaller.STATUS_FAILURE_BLOCKED: {
+                int legacyStatus = intent.getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS, 0);
+
+                switch (legacyStatus) {
+                    case PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER: {
+                        IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
+                                ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
+                        // Find out if the package is an active admin for some non-current user.
+                        int myUserId = UserHandle.myUserId();
+                        UserInfo otherBlockingUser = null;
+                        for (UserInfo user : userManager.getUsers()) {
+                            // We only catch the case when the user in question is neither the
+                            // current user nor its profile.
+                            if (isProfileOfOrSame(userManager, myUserId, user.id)) {
+                                continue;
+                            }
+
+                            try {
+                                if (dpm.packageHasActiveAdmins(appInfo.packageName, user.id)) {
+                                    otherBlockingUser = user;
+                                    break;
+                                }
+                            } catch (RemoteException e) {
+                                Log.e(LOG_TAG, "Failed to talk to package manager", e);
+                            }
+                        }
+                        if (otherBlockingUser == null) {
+                            Log.d(LOG_TAG, "Uninstall failed because " + appInfo.packageName
+                                    + " is a device admin");
+
+                            addDeviceManagerButton(context, uninstallFailedNotification);
+                            setBigText(uninstallFailedNotification, context.getString(
+                                    R.string.uninstall_failed_device_policy_manager));
+                        } else {
+                            Log.d(LOG_TAG, "Uninstall failed because " + appInfo.packageName
+                                    + " is a device admin of user " + otherBlockingUser);
+
+                            setBigText(uninstallFailedNotification, String.format(context.getString(
+                                    R.string.uninstall_failed_device_policy_manager_of_user),
+                                    otherBlockingUser.name));
+                        }
+                        break;
+                    }
+                    case PackageManager.DELETE_FAILED_OWNER_BLOCKED: {
+                        IPackageManager packageManager = IPackageManager.Stub.asInterface(
+                                ServiceManager.getService("package"));
+
+                        List<UserInfo> users = userManager.getUsers();
+                        int blockingUserId = UserHandle.USER_NULL;
+                        for (int i = 0; i < users.size(); ++i) {
+                            final UserInfo user = users.get(i);
+                            try {
+                                if (packageManager.getBlockUninstallForUser(appInfo.packageName,
+                                        user.id)) {
+                                    blockingUserId = user.id;
+                                    break;
+                                }
+                            } catch (RemoteException e) {
+                                // Shouldn't happen.
+                                Log.e(LOG_TAG, "Failed to talk to package manager", e);
+                            }
+                        }
+
+                        int myUserId = UserHandle.myUserId();
+                        if (isProfileOfOrSame(userManager, myUserId, blockingUserId)) {
+                            addDeviceManagerButton(context, uninstallFailedNotification);
+                        } else {
+                            addManageUsersButton(context, uninstallFailedNotification);
+                        }
+
+                        if (blockingUserId == UserHandle.USER_NULL) {
+                            Log.d(LOG_TAG,
+                                    "Uninstall failed for " + appInfo.packageName + " with code "
+                                            + returnCode + " no blocking user");
+                        } else if (blockingUserId == UserHandle.USER_SYSTEM) {
+                            setBigText(uninstallFailedNotification,
+                                    context.getString(R.string.uninstall_blocked_device_owner));
+                        } else {
+                            if (allUsers) {
+                                setBigText(uninstallFailedNotification,
+                                        context.getString(
+                                                R.string.uninstall_all_blocked_profile_owner));
+                            } else {
+                                setBigText(uninstallFailedNotification, context.getString(
+                                        R.string.uninstall_blocked_profile_owner));
+                            }
+                        }
+                        break;
+                    }
+                    default:
+                        Log.d(LOG_TAG, "Uninstall blocked for " + appInfo.packageName
+                                + " with legacy code " + legacyStatus);
+                } break;
+            }
+            default:
+                Log.d(LOG_TAG, "Uninstall failed for " + appInfo.packageName + " with code "
+                        + returnCode);
+                break;
+        }
+
+        uninstallFailedNotification.setContentTitle(
+                context.getString(R.string.uninstall_failed_app, appLabel));
+        uninstallFailedNotification.setOngoing(false);
+        uninstallFailedNotification.setSmallIcon(R.drawable.ic_error);
+        notificationManager.notify(uninstallId, uninstallFailedNotification.build());
+    }
+
+    /**
+     * Is a profile part of a user?
+     *
+     * @param userManager The user manager
+     * @param userId The id of the user
+     * @param profileId The id of the profile
+     *
+     * @return If the profile is part of the user or the profile parent of the user
+     */
+    private boolean isProfileOfOrSame(@NonNull UserManager userManager, int userId, int profileId) {
+        if (userId == profileId) {
+            return true;
+        }
+
+        UserInfo parentUser = userManager.getProfileParent(profileId);
+        return parentUser != null && parentUser.id == userId;
+    }
+
+    /**
+     * Set big text for the notification.
+     *
+     * @param builder The builder of the notification
+     * @param text The text to set.
+     */
+    private void setBigText(@NonNull Notification.Builder builder,
+            @NonNull CharSequence text) {
+        builder.setStyle(new Notification.BigTextStyle().bigText(text));
+    }
+
+    /**
+     * Add a button to the notification that links to the user management.
+     *
+     * @param context The context the notification is created in
+     * @param builder The builder of the notification
+     */
+    private void addManageUsersButton(@NonNull Context context,
+            @NonNull Notification.Builder builder) {
+        Intent intent = new Intent(Settings.ACTION_USER_SETTINGS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        builder.addAction((new Notification.Action.Builder(
+                Icon.createWithResource(context, R.drawable.ic_settings_multiuser),
+                context.getString(R.string.manage_users),
+                PendingIntent.getActivity(context, 0, intent,
+                        PendingIntent.FLAG_UPDATE_CURRENT))).build());
+    }
+
+    /**
+     * Add a button to the notification that links to the device policy management.
+     *
+     * @param context The context the notification is created in
+     * @param builder The builder of the notification
+     */
+    private void addDeviceManagerButton(@NonNull Context context,
+            @NonNull Notification.Builder builder) {
+        Intent intent = new Intent();
+        intent.setClassName("com.android.settings",
+                "com.android.settings.Settings$DeviceAdminSettingsActivity");
+        intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        builder.addAction((new Notification.Action.Builder(
+                Icon.createWithResource(context, R.drawable.ic_lock),
+                context.getString(R.string.manage_device_administrators),
+                PendingIntent.getActivity(context, 0, intent,
+                        PendingIntent.FLAG_UPDATE_CURRENT))).build());
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
new file mode 100644
index 0000000..1c0aec1
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallUninstalling.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.packageinstaller;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityThread;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageDeleteObserver2;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.content.pm.VersionedPackage;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.widget.Toast;
+
+/**
+ * Start an uninstallation, show a dialog while uninstalling and return result to the caller.
+ */
+public class UninstallUninstalling extends Activity implements
+        EventResultPersister.EventResultObserver {
+    private static final String LOG_TAG = UninstallUninstalling.class.getSimpleName();
+
+    private static final String UNINSTALL_ID = "com.android.packageinstaller.UNINSTALL_ID";
+    private static final String BROADCAST_ACTION =
+            "com.android.packageinstaller.ACTION_UNINSTALL_COMMIT";
+
+    static final String EXTRA_APP_LABEL = "com.android.packageinstaller.extra.APP_LABEL";
+
+    private int mUninstallId;
+    private ApplicationInfo mAppInfo;
+    private IBinder mCallback;
+    private boolean mReturnResult;
+    private String mLabel;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setFinishOnTouchOutside(false);
+
+        mAppInfo = getIntent().getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+        mCallback = getIntent().getIBinderExtra(PackageInstaller.EXTRA_CALLBACK);
+        mReturnResult = getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false);
+        mLabel = getIntent().getStringExtra(EXTRA_APP_LABEL);
+
+        try {
+            if (savedInstanceState == null) {
+                boolean allUsers = getIntent().getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS,
+                        false);
+                UserHandle user = getIntent().getParcelableExtra(Intent.EXTRA_USER);
+
+                // Show dialog, which is the whole UI
+                FragmentTransaction transaction = getFragmentManager().beginTransaction();
+                Fragment prev = getFragmentManager().findFragmentByTag("dialog");
+                if (prev != null) {
+                    transaction.remove(prev);
+                }
+                DialogFragment dialog = new UninstallUninstallingFragment();
+                dialog.setCancelable(false);
+                dialog.show(transaction, "dialog");
+
+                mUninstallId = UninstallEventReceiver.addObserver(this,
+                        EventResultPersister.GENERATE_NEW_ID, this);
+
+                Intent broadcastIntent = new Intent(BROADCAST_ACTION);
+                broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mUninstallId);
+                broadcastIntent.setPackage(getPackageName());
+
+                PendingIntent pendingIntent = PendingIntent.getBroadcast(this, mUninstallId,
+                        broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+                try {
+                    ActivityThread.getPackageManager().getPackageInstaller().uninstall(
+                            new VersionedPackage(mAppInfo.packageName,
+                                    PackageManager.VERSION_CODE_HIGHEST),
+                            getPackageName(), allUsers ? PackageManager.DELETE_ALL_USERS : 0,
+                            pendingIntent.getIntentSender(), user.getIdentifier());
+                } catch (RemoteException e) {
+                    e.rethrowFromSystemServer();
+                }
+            } else {
+                mUninstallId = savedInstanceState.getInt(UNINSTALL_ID);
+                UninstallEventReceiver.addObserver(this, mUninstallId, this);
+            }
+        } catch (EventResultPersister.OutOfIdsException | IllegalArgumentException e) {
+            Log.e(LOG_TAG, "Fails to start uninstall", e);
+            onResult(PackageInstaller.STATUS_FAILURE, PackageManager.DELETE_FAILED_INTERNAL_ERROR,
+                    null);
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putInt(UNINSTALL_ID, mUninstallId);
+    }
+
+    @Override
+    public void onBackPressed() {
+        // do nothing
+    }
+
+    @Override
+    public void onResult(int status, int legacyStatus, @Nullable String message) {
+        if (mCallback != null) {
+            // The caller will be informed about the result via a callback
+            final IPackageDeleteObserver2 observer = IPackageDeleteObserver2.Stub
+                    .asInterface(mCallback);
+            try {
+                observer.onPackageDeleted(mAppInfo.packageName, legacyStatus, message);
+            } catch (RemoteException ignored) {
+            }
+        } else if (mReturnResult) {
+            // The caller will be informed about the result and might decide to display it
+            Intent result = new Intent();
+
+            result.putExtra(Intent.EXTRA_INSTALL_RESULT, legacyStatus);
+            setResult(status == PackageInstaller.STATUS_SUCCESS ? Activity.RESULT_OK
+                    : Activity.RESULT_FIRST_USER, result);
+        } else {
+            // This is the rare case that the caller did not ask for the result, but wanted to be
+            // notified via onActivityResult when the installation finishes
+            if (status != PackageInstaller.STATUS_SUCCESS) {
+                Toast.makeText(this, getString(R.string.uninstall_failed_app, mLabel),
+                        Toast.LENGTH_LONG).show();
+            }
+        }
+        finish();
+    }
+
+    @Override
+    protected void onDestroy() {
+        UninstallEventReceiver.removeObserver(this, mUninstallId);
+
+        super.onDestroy();
+    }
+
+    /**
+     * Dialog that shows that the app is uninstalling.
+     */
+    public static class UninstallUninstallingFragment extends DialogFragment {
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity());
+
+            dialogBuilder.setCancelable(false);
+            dialogBuilder.setMessage(getActivity().getString(R.string.uninstalling_app,
+                    ((UninstallUninstalling) getActivity()).mLabel));
+
+            Dialog dialog = dialogBuilder.create();
+            dialog.setCanceledOnTouchOutside(false);
+
+            return dialog;
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
new file mode 100755
index 0000000..1a01dc0
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
@@ -0,0 +1,395 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+
+import static com.android.packageinstaller.PackageUtil.getMaxTargetSdkVersionForUid;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.StringRes;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityThread;
+import android.app.AppGlobals;
+import android.app.AppOpsManager;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageDeleteObserver2;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.content.pm.VersionedPackage;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import com.android.packageinstaller.handheld.ErrorDialogFragment;
+import com.android.packageinstaller.handheld.UninstallAlertDialogFragment;
+import com.android.packageinstaller.television.ErrorFragment;
+import com.android.packageinstaller.television.UninstallAlertFragment;
+import com.android.packageinstaller.television.UninstallAppProgress;
+
+import java.util.List;
+
+/*
+ * This activity presents UI to uninstall an application. Usually launched with intent
+ * Intent.ACTION_UNINSTALL_PKG_COMMAND and attribute
+ * com.android.packageinstaller.PackageName set to the application package name
+ */
+public class UninstallerActivity extends Activity {
+    private static final String TAG = "UninstallerActivity";
+
+    private static final String UNINSTALLING_CHANNEL = "uninstalling";
+
+    public static class DialogInfo {
+        public ApplicationInfo appInfo;
+        public ActivityInfo activityInfo;
+        public boolean allUsers;
+        public UserHandle user;
+        public IBinder callback;
+    }
+
+    private String mPackageName;
+    private DialogInfo mDialogInfo;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        // Never restore any state, esp. never create any fragments. The data in the fragment might
+        // be stale, if e.g. the app was uninstalled while the activity was destroyed.
+        super.onCreate(null);
+
+        try {
+            int callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken());
+
+            String callingPackage = getPackageNameForUid(callingUid);
+            if (callingPackage == null) {
+                Log.e(TAG, "Package not found for originating uid " + callingUid);
+                setResult(Activity.RESULT_FIRST_USER);
+                finish();
+                return;
+            } else {
+                AppOpsManager appOpsManager = (AppOpsManager) getSystemService(
+                        Context.APP_OPS_SERVICE);
+                if (appOpsManager.noteOpNoThrow(
+                        AppOpsManager.OPSTR_REQUEST_DELETE_PACKAGES, callingUid, callingPackage)
+                        != MODE_ALLOWED) {
+                    Log.e(TAG, "Install from uid " + callingUid + " disallowed by AppOps");
+                    setResult(Activity.RESULT_FIRST_USER);
+                    finish();
+                    return;
+                }
+            }
+
+            if (getMaxTargetSdkVersionForUid(this, callingUid)
+                    >= Build.VERSION_CODES.P && AppGlobals.getPackageManager().checkUidPermission(
+                    Manifest.permission.REQUEST_DELETE_PACKAGES, callingUid)
+                    != PackageManager.PERMISSION_GRANTED
+                    && AppGlobals.getPackageManager().checkUidPermission(
+                            Manifest.permission.DELETE_PACKAGES, callingUid)
+                            != PackageManager.PERMISSION_GRANTED) {
+                Log.e(TAG, "Uid " + callingUid + " does not have "
+                        + Manifest.permission.REQUEST_DELETE_PACKAGES + " or "
+                        + Manifest.permission.DELETE_PACKAGES);
+
+                setResult(Activity.RESULT_FIRST_USER);
+                finish();
+                return;
+            }
+        } catch (RemoteException ex) {
+            // Cannot reach Package/ActivityManager. Aborting uninstall.
+            Log.e(TAG, "Could not determine the launching uid.");
+
+            setResult(Activity.RESULT_FIRST_USER);
+            finish();
+            return;
+        }
+
+        // Get intent information.
+        // We expect an intent with URI of the form package://<packageName>#<className>
+        // className is optional; if specified, it is the activity the user chose to uninstall
+        final Intent intent = getIntent();
+        final Uri packageUri = intent.getData();
+        if (packageUri == null) {
+            Log.e(TAG, "No package URI in intent");
+            showAppNotFound();
+            return;
+        }
+        mPackageName = packageUri.getEncodedSchemeSpecificPart();
+        if (mPackageName == null) {
+            Log.e(TAG, "Invalid package name in URI: " + packageUri);
+            showAppNotFound();
+            return;
+        }
+
+        final IPackageManager pm = IPackageManager.Stub.asInterface(
+                ServiceManager.getService("package"));
+
+        mDialogInfo = new DialogInfo();
+
+        mDialogInfo.allUsers = intent.getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false);
+        if (mDialogInfo.allUsers && !UserManager.get(this).isAdminUser()) {
+            Log.e(TAG, "Only admin user can request uninstall for all users");
+            showUserIsNotAllowed();
+            return;
+        }
+        mDialogInfo.user = intent.getParcelableExtra(Intent.EXTRA_USER);
+        if (mDialogInfo.user == null) {
+            mDialogInfo.user = android.os.Process.myUserHandle();
+        } else {
+            UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+            List<UserHandle> profiles = userManager.getUserProfiles();
+            if (!profiles.contains(mDialogInfo.user)) {
+                Log.e(TAG, "User " + android.os.Process.myUserHandle() + " can't request uninstall "
+                        + "for user " + mDialogInfo.user);
+                showUserIsNotAllowed();
+                return;
+            }
+        }
+
+        mDialogInfo.callback = intent.getIBinderExtra(PackageInstaller.EXTRA_CALLBACK);
+
+        try {
+            mDialogInfo.appInfo = pm.getApplicationInfo(mPackageName,
+                    PackageManager.MATCH_ANY_USER, mDialogInfo.user.getIdentifier());
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to get packageName. Package manager is dead?");
+        }
+
+        if (mDialogInfo.appInfo == null) {
+            Log.e(TAG, "Invalid packageName: " + mPackageName);
+            showAppNotFound();
+            return;
+        }
+
+        // The class name may have been specified (e.g. when deleting an app from all apps)
+        final String className = packageUri.getFragment();
+        if (className != null) {
+            try {
+                mDialogInfo.activityInfo = pm.getActivityInfo(
+                        new ComponentName(mPackageName, className), 0,
+                        mDialogInfo.user.getIdentifier());
+            } catch (RemoteException e) {
+                Log.e(TAG, "Unable to get className. Package manager is dead?");
+                // Continue as the ActivityInfo isn't critical.
+            }
+        }
+
+        showConfirmationDialog();
+    }
+
+    public DialogInfo getDialogInfo() {
+        return mDialogInfo;
+    }
+
+    private void showConfirmationDialog() {
+        if (isTv()) {
+            showContentFragment(new UninstallAlertFragment(), 0, 0);
+        } else {
+            showDialogFragment(new UninstallAlertDialogFragment(), 0, 0);
+        }
+    }
+
+    private void showAppNotFound() {
+        if (isTv()) {
+            showContentFragment(new ErrorFragment(), R.string.app_not_found_dlg_title,
+                    R.string.app_not_found_dlg_text);
+        } else {
+            showDialogFragment(new ErrorDialogFragment(), R.string.app_not_found_dlg_title,
+                    R.string.app_not_found_dlg_text);
+        }
+    }
+
+    private void showUserIsNotAllowed() {
+        if (isTv()) {
+            showContentFragment(new ErrorFragment(),
+                    R.string.user_is_not_allowed_dlg_title, R.string.user_is_not_allowed_dlg_text);
+        } else {
+            showDialogFragment(new ErrorDialogFragment(), 0, R.string.user_is_not_allowed_dlg_text);
+        }
+    }
+
+    private void showGenericError() {
+        if (isTv()) {
+            showContentFragment(new ErrorFragment(),
+                    R.string.generic_error_dlg_title, R.string.generic_error_dlg_text);
+        } else {
+            showDialogFragment(new ErrorDialogFragment(), 0, R.string.generic_error_dlg_text);
+        }
+    }
+
+    private boolean isTv() {
+        return (getResources().getConfiguration().uiMode & Configuration.UI_MODE_TYPE_MASK)
+                == Configuration.UI_MODE_TYPE_TELEVISION;
+    }
+
+    private void showContentFragment(@NonNull Fragment fragment, @StringRes int title,
+            @StringRes int text) {
+        Bundle args = new Bundle();
+        args.putInt(ErrorFragment.TITLE, title);
+        args.putInt(ErrorFragment.TEXT, text);
+        fragment.setArguments(args);
+
+        getFragmentManager().beginTransaction()
+                .replace(android.R.id.content, fragment)
+                .commit();
+    }
+
+    private void showDialogFragment(@NonNull DialogFragment fragment,
+            @StringRes int title, @StringRes int text) {
+        FragmentTransaction ft = getFragmentManager().beginTransaction();
+        Fragment prev = getFragmentManager().findFragmentByTag("dialog");
+        if (prev != null) {
+            ft.remove(prev);
+        }
+
+        Bundle args = new Bundle();
+        if (title != 0) {
+            args.putInt(ErrorDialogFragment.TITLE, title);
+        }
+        args.putInt(ErrorDialogFragment.TEXT, text);
+
+        fragment.setArguments(args);
+        fragment.show(ft, "dialog");
+    }
+
+    public void startUninstallProgress() {
+        boolean returnResult = getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false);
+        CharSequence label = mDialogInfo.appInfo.loadSafeLabel(getPackageManager());
+
+        if (isTv()) {
+            Intent newIntent = new Intent(Intent.ACTION_VIEW);
+            newIntent.putExtra(Intent.EXTRA_USER, mDialogInfo.user);
+            newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers);
+            newIntent.putExtra(PackageInstaller.EXTRA_CALLBACK, mDialogInfo.callback);
+            newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mDialogInfo.appInfo);
+
+            if (returnResult) {
+                newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
+                newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+            }
+
+            newIntent.setClass(this, UninstallAppProgress.class);
+            startActivity(newIntent);
+        } else if (returnResult || mDialogInfo.callback != null || getCallingActivity() != null) {
+            Intent newIntent = new Intent(this, UninstallUninstalling.class);
+
+            newIntent.putExtra(Intent.EXTRA_USER, mDialogInfo.user);
+            newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers);
+            newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mDialogInfo.appInfo);
+            newIntent.putExtra(UninstallUninstalling.EXTRA_APP_LABEL, label);
+            newIntent.putExtra(PackageInstaller.EXTRA_CALLBACK, mDialogInfo.callback);
+
+            if (returnResult) {
+                newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
+            }
+
+            if (returnResult || getCallingActivity() != null) {
+                newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+            }
+
+            startActivity(newIntent);
+        } else {
+            int uninstallId;
+            try {
+                uninstallId = UninstallEventReceiver.getNewId(this);
+            } catch (EventResultPersister.OutOfIdsException e) {
+                showGenericError();
+                return;
+            }
+
+            Intent broadcastIntent = new Intent(this, UninstallFinish.class);
+
+            broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+            broadcastIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers);
+            broadcastIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mDialogInfo.appInfo);
+            broadcastIntent.putExtra(UninstallFinish.EXTRA_APP_LABEL, label);
+            broadcastIntent.putExtra(UninstallFinish.EXTRA_UNINSTALL_ID, uninstallId);
+
+            PendingIntent pendingIntent = PendingIntent.getBroadcast(this, uninstallId,
+                    broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+            NotificationManager notificationManager = getSystemService(NotificationManager.class);
+            NotificationChannel uninstallingChannel = new NotificationChannel(UNINSTALLING_CHANNEL,
+                    getString(R.string.uninstalling_notification_channel),
+                    NotificationManager.IMPORTANCE_MIN);
+            notificationManager.createNotificationChannel(uninstallingChannel);
+
+            Notification uninstallingNotification =
+                    (new Notification.Builder(this, UNINSTALLING_CHANNEL))
+                    .setSmallIcon(R.drawable.ic_remove).setProgress(0, 1, true)
+                    .setContentTitle(getString(R.string.uninstalling_app, label)).setOngoing(true)
+                    .build();
+
+            notificationManager.notify(uninstallId, uninstallingNotification);
+
+            try {
+                Log.i(TAG, "Uninstalling extras=" + broadcastIntent.getExtras());
+
+                ActivityThread.getPackageManager().getPackageInstaller().uninstall(
+                        new VersionedPackage(mDialogInfo.appInfo.packageName,
+                                PackageManager.VERSION_CODE_HIGHEST),
+                        getPackageName(), mDialogInfo.allUsers
+                                ? PackageManager.DELETE_ALL_USERS : 0,
+                        pendingIntent.getIntentSender(), mDialogInfo.user.getIdentifier());
+            } catch (Exception e) {
+                notificationManager.cancel(uninstallId);
+
+                Log.e(TAG, "Cannot start uninstall", e);
+                showGenericError();
+            }
+        }
+    }
+
+    public void dispatchAborted() {
+        if (mDialogInfo != null && mDialogInfo.callback != null) {
+            final IPackageDeleteObserver2 observer = IPackageDeleteObserver2.Stub.asInterface(
+                    mDialogInfo.callback);
+            try {
+                observer.onPackageDeleted(mPackageName,
+                        PackageManager.DELETE_FAILED_ABORTED, "Cancelled by user");
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    private String getPackageNameForUid(int sourceUid) {
+        String[] packagesForUid = getPackageManager().getPackagesForUid(sourceUid);
+        if (packagesForUid == null) {
+            return null;
+        }
+        return packagesForUid[0];
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/ErrorDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/ErrorDialogFragment.java
new file mode 100644
index 0000000..4ec6a2d
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/ErrorDialogFragment.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.packageinstaller.handheld;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import com.android.packageinstaller.UninstallerActivity;
+
+public class ErrorDialogFragment extends DialogFragment {
+    public static final String TITLE = "com.android.packageinstaller.arg.title";
+    public static final String TEXT = "com.android.packageinstaller.arg.text";
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        AlertDialog.Builder b = new AlertDialog.Builder(getActivity())
+                .setMessage(getArguments().getInt(TEXT))
+                .setPositiveButton(android.R.string.ok, null);
+
+        if (getArguments().containsKey(TITLE)) {
+            b.setTitle(getArguments().getInt(TITLE));
+        }
+
+        return b.create();
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        if (isAdded()) {
+            if (getActivity() instanceof UninstallerActivity) {
+                ((UninstallerActivity) getActivity()).dispatchAborted();
+            }
+
+            getActivity().setResult(Activity.RESULT_FIRST_USER);
+            getActivity().finish();
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
new file mode 100644
index 0000000..e0ca74e
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.packageinstaller.handheld;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.UserManager;
+
+import com.android.packageinstaller.R;
+import com.android.packageinstaller.UninstallerActivity;
+
+public class UninstallAlertDialogFragment extends DialogFragment implements
+        DialogInterface.OnClickListener {
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        final PackageManager pm = getActivity().getPackageManager();
+        final UninstallerActivity.DialogInfo dialogInfo =
+                ((UninstallerActivity) getActivity()).getDialogInfo();
+        final CharSequence appLabel = dialogInfo.appInfo.loadSafeLabel(pm);
+        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity());
+        StringBuilder messageBuilder = new StringBuilder();
+
+        // If the Activity label differs from the App label, then make sure the user
+        // knows the Activity belongs to the App being uninstalled.
+        if (dialogInfo.activityInfo != null) {
+            final CharSequence activityLabel = dialogInfo.activityInfo.loadSafeLabel(pm);
+            if (!activityLabel.equals(appLabel)) {
+                messageBuilder.append(
+                        getString(R.string.uninstall_activity_text, activityLabel));
+                messageBuilder.append(" ").append(appLabel).append(".\n\n");
+            }
+        }
+
+        final boolean isUpdate =
+                ((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
+        UserManager userManager = UserManager.get(getActivity());
+        if (isUpdate) {
+            if (isSingleUser(userManager)) {
+                messageBuilder.append(getString(R.string.uninstall_update_text));
+            } else {
+                messageBuilder.append(getString(R.string.uninstall_update_text_multiuser));
+            }
+        } else {
+            if (dialogInfo.allUsers && !isSingleUser(userManager)) {
+                messageBuilder.append(getString(R.string.uninstall_application_text_all_users));
+            } else if (!dialogInfo.user.equals(android.os.Process.myUserHandle())) {
+                UserInfo userInfo = userManager.getUserInfo(dialogInfo.user.getIdentifier());
+                messageBuilder.append(
+                        getString(R.string.uninstall_application_text_user, userInfo.name));
+            } else {
+                messageBuilder.append(getString(R.string.uninstall_application_text));
+            }
+        }
+
+        dialogBuilder.setTitle(appLabel);
+        dialogBuilder.setPositiveButton(android.R.string.ok, this);
+        dialogBuilder.setNegativeButton(android.R.string.cancel, this);
+        dialogBuilder.setMessage(messageBuilder.toString());
+        return dialogBuilder.create();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        if (which == Dialog.BUTTON_POSITIVE) {
+            ((UninstallerActivity) getActivity()).startUninstallProgress();
+        } else {
+            ((UninstallerActivity) getActivity()).dispatchAborted();
+        }
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        if (isAdded()) {
+            getActivity().finish();
+        }
+    }
+
+    /**
+     * Returns whether there is only one user on this device, not including
+     * the system-only user.
+     */
+    private boolean isSingleUser(UserManager userManager) {
+        final int userCount = userManager.getUserCount();
+        return userCount == 1
+                || (UserManager.isSplitSystemUser() && userCount == 2);
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/television/ErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/television/ErrorFragment.java
new file mode 100644
index 0000000..f00f684
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/television/ErrorFragment.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.packageinstaller.television;
+
+import android.app.Activity;
+import android.os.Bundle;
+import androidx.leanback.app.GuidedStepFragment;
+import androidx.leanback.widget.GuidanceStylist;
+import androidx.leanback.widget.GuidedAction;
+
+import com.android.packageinstaller.R;
+import com.android.packageinstaller.UninstallerActivity;
+
+import java.util.List;
+
+public class ErrorFragment extends GuidedStepFragment {
+    public static final String TITLE = "com.android.packageinstaller.arg.title";
+    public static final String TEXT = "com.android.packageinstaller.arg.text";
+
+    @Override
+    public int onProvideTheme() {
+        return R.style.Theme_Leanback_GuidedStep;
+    }
+
+    @Override
+    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
+        return new GuidanceStylist.Guidance(
+                getString(getArguments().getInt(TITLE)),
+                getString(getArguments().getInt(TEXT)),
+                null,
+                null);
+    }
+
+    @Override
+    public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
+        actions.add(new GuidedAction.Builder(getContext())
+                .clickAction(GuidedAction.ACTION_ID_OK)
+                .build());
+    }
+
+    @Override
+    public void onGuidedActionClicked(GuidedAction action) {
+        if (isAdded()) {
+            if (getActivity() instanceof UninstallerActivity) {
+                ((UninstallerActivity) getActivity()).dispatchAborted();
+            }
+
+            getActivity().setResult(Activity.RESULT_FIRST_USER);
+            getActivity().finish();
+        }
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java
new file mode 100644
index 0000000..828e5db
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.packageinstaller.television;
+
+import android.app.Activity;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.UserManager;
+import androidx.leanback.app.GuidedStepFragment;
+import androidx.leanback.widget.GuidanceStylist;
+import androidx.leanback.widget.GuidedAction;
+
+import com.android.packageinstaller.R;
+import com.android.packageinstaller.UninstallerActivity;
+
+import java.util.List;
+
+public class UninstallAlertFragment extends GuidedStepFragment {
+    @Override
+    public int onProvideTheme() {
+        return R.style.Theme_Leanback_GuidedStep;
+    }
+
+    @Override
+    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
+        final PackageManager pm = getActivity().getPackageManager();
+        final UninstallerActivity.DialogInfo dialogInfo =
+                ((UninstallerActivity) getActivity()).getDialogInfo();
+        final CharSequence appLabel = dialogInfo.appInfo.loadSafeLabel(pm);
+
+        StringBuilder messageBuilder = new StringBuilder();
+
+        // If the Activity label differs from the App label, then make sure the user
+        // knows the Activity belongs to the App being uninstalled.
+        if (dialogInfo.activityInfo != null) {
+            final CharSequence activityLabel = dialogInfo.activityInfo.loadSafeLabel(pm);
+            if (!activityLabel.equals(appLabel)) {
+                messageBuilder.append(
+                        getString(R.string.uninstall_activity_text, activityLabel));
+                messageBuilder.append(" ").append(appLabel).append(".\n\n");
+            }
+        }
+
+        final boolean isUpdate =
+                ((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
+        UserManager userManager = UserManager.get(getActivity());
+        if (isUpdate) {
+            if (isSingleUser(userManager)) {
+                messageBuilder.append(getString(R.string.uninstall_update_text));
+            } else {
+                messageBuilder.append(getString(R.string.uninstall_update_text_multiuser));
+            }
+        } else {
+            if (dialogInfo.allUsers && !isSingleUser(userManager)) {
+                messageBuilder.append(getString(R.string.uninstall_application_text_all_users));
+            } else if (!dialogInfo.user.equals(android.os.Process.myUserHandle())) {
+                UserInfo userInfo = userManager.getUserInfo(dialogInfo.user.getIdentifier());
+                messageBuilder.append(
+                        getString(R.string.uninstall_application_text_user, userInfo.name));
+            } else {
+                messageBuilder.append(getString(R.string.uninstall_application_text));
+            }
+        }
+
+        return new GuidanceStylist.Guidance(
+                appLabel.toString(),
+                messageBuilder.toString(),
+                null,
+                dialogInfo.appInfo.loadIcon(pm));
+    }
+
+    @Override
+    public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
+        actions.add(new GuidedAction.Builder(getContext())
+                .clickAction(GuidedAction.ACTION_ID_OK)
+                .build());
+        actions.add(new GuidedAction.Builder(getContext())
+                .clickAction(GuidedAction.ACTION_ID_CANCEL)
+                .build());
+    }
+
+    @Override
+    public void onGuidedActionClicked(GuidedAction action) {
+        if (isAdded()) {
+            if (action.getId() == GuidedAction.ACTION_ID_OK) {
+                ((UninstallerActivity) getActivity()).startUninstallProgress();
+                getActivity().finish();
+            } else {
+                ((UninstallerActivity) getActivity()).dispatchAborted();
+                getActivity().setResult(Activity.RESULT_FIRST_USER);
+                getActivity().finish();
+            }
+        }
+    }
+
+    /**
+     * Returns whether there is only one user on this device, not including
+     * the system-only user.
+     */
+    private boolean isSingleUser(UserManager userManager) {
+        final int userCount = userManager.getUserCount();
+        return userCount == 1
+                || (UserManager.isSplitSystemUser() && userCount == 2);
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAppProgress.java b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAppProgress.java
new file mode 100755
index 0000000..a4f217c
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAppProgress.java
@@ -0,0 +1,377 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller.television;
+
+import android.app.Activity;
+import android.app.admin.IDevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.IPackageDeleteObserver2;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.KeyEvent;
+import android.widget.Toast;
+
+import com.android.packageinstaller.PackageUtil;
+import com.android.packageinstaller.R;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+/**
+ * This activity corresponds to a download progress screen that is displayed
+ * when an application is uninstalled. The result of the application uninstall
+ * is indicated in the result code that gets set to 0 or 1. The application gets launched
+ * by an intent with the intent's class name explicitly set to UninstallAppProgress and expects
+ * the application object of the application to uninstall.
+ */
+public class UninstallAppProgress extends Activity {
+    private static final String TAG = "UninstallAppProgress";
+
+    private static final String FRAGMENT_TAG = "progress_fragment";
+
+    private ApplicationInfo mAppInfo;
+    private boolean mAllUsers;
+    private IBinder mCallback;
+
+    private volatile int mResultCode = -1;
+
+    /**
+     * If initView was called. We delay this call to not have to call it at all if the uninstall is
+     * quick
+     */
+    private boolean mIsViewInitialized;
+
+    /** Amount of time to wait until we show the UI */
+    private static final int QUICK_INSTALL_DELAY_MILLIS = 500;
+
+    private static final int UNINSTALL_COMPLETE = 1;
+    private static final int UNINSTALL_IS_SLOW = 2;
+
+    private Handler mHandler = new MessageHandler(this);
+
+    private static class MessageHandler extends Handler {
+        private final WeakReference<UninstallAppProgress> mActivity;
+
+        public MessageHandler(UninstallAppProgress activity) {
+            mActivity = new WeakReference<>(activity);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            UninstallAppProgress activity = mActivity.get();
+            if (activity != null) {
+                activity.handleMessage(msg);
+            }
+        }
+    }
+
+    private void handleMessage(Message msg) {
+        if (isFinishing() || isDestroyed()) {
+            return;
+        }
+
+        switch (msg.what) {
+            case UNINSTALL_IS_SLOW:
+                initView();
+                break;
+            case UNINSTALL_COMPLETE:
+                mHandler.removeMessages(UNINSTALL_IS_SLOW);
+
+                if (msg.arg1 != PackageManager.DELETE_SUCCEEDED) {
+                    initView();
+                }
+
+                mResultCode = msg.arg1;
+                final String packageName = (String) msg.obj;
+
+                if (mCallback != null) {
+                    final IPackageDeleteObserver2 observer = IPackageDeleteObserver2.Stub
+                            .asInterface(mCallback);
+                    try {
+                        observer.onPackageDeleted(mAppInfo.packageName, mResultCode,
+                                packageName);
+                    } catch (RemoteException ignored) {
+                    }
+                    finish();
+                    return;
+                }
+
+                if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
+                    Intent result = new Intent();
+                    result.putExtra(Intent.EXTRA_INSTALL_RESULT, mResultCode);
+                    setResult(mResultCode == PackageManager.DELETE_SUCCEEDED
+                            ? Activity.RESULT_OK : Activity.RESULT_FIRST_USER,
+                            result);
+                    finish();
+                    return;
+                }
+
+                // Update the status text
+                final String statusText;
+                switch (msg.arg1) {
+                    case PackageManager.DELETE_SUCCEEDED:
+                        statusText = getString(R.string.uninstall_done);
+                        // Show a Toast and finish the activity
+                        Context ctx = getBaseContext();
+                        Toast.makeText(ctx, statusText, Toast.LENGTH_LONG).show();
+                        setResultAndFinish();
+                        return;
+                    case PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER: {
+                        UserManager userManager =
+                                (UserManager) getSystemService(Context.USER_SERVICE);
+                        IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
+                                ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
+                        // Find out if the package is an active admin for some non-current user.
+                        int myUserId = UserHandle.myUserId();
+                        UserInfo otherBlockingUser = null;
+                        for (UserInfo user : userManager.getUsers()) {
+                            // We only catch the case when the user in question is neither the
+                            // current user nor its profile.
+                            if (isProfileOfOrSame(userManager, myUserId, user.id)) continue;
+
+                            try {
+                                if (dpm.packageHasActiveAdmins(packageName, user.id)) {
+                                    otherBlockingUser = user;
+                                    break;
+                                }
+                            } catch (RemoteException e) {
+                                Log.e(TAG, "Failed to talk to package manager", e);
+                            }
+                        }
+                        if (otherBlockingUser == null) {
+                            Log.d(TAG, "Uninstall failed because " + packageName
+                                    + " is a device admin");
+                            getProgressFragment().setDeviceManagerButtonVisible(true);
+                            statusText = getString(
+                                    R.string.uninstall_failed_device_policy_manager);
+                        } else {
+                            Log.d(TAG, "Uninstall failed because " + packageName
+                                    + " is a device admin of user " + otherBlockingUser);
+                            getProgressFragment().setDeviceManagerButtonVisible(false);
+                            statusText = String.format(
+                                    getString(R.string.uninstall_failed_device_policy_manager_of_user),
+                                    otherBlockingUser.name);
+                        }
+                        break;
+                    }
+                    case PackageManager.DELETE_FAILED_OWNER_BLOCKED: {
+                        UserManager userManager =
+                                (UserManager) getSystemService(Context.USER_SERVICE);
+                        IPackageManager packageManager = IPackageManager.Stub.asInterface(
+                                ServiceManager.getService("package"));
+                        List<UserInfo> users = userManager.getUsers();
+                        int blockingUserId = UserHandle.USER_NULL;
+                        for (int i = 0; i < users.size(); ++i) {
+                            final UserInfo user = users.get(i);
+                            try {
+                                if (packageManager.getBlockUninstallForUser(packageName,
+                                        user.id)) {
+                                    blockingUserId = user.id;
+                                    break;
+                                }
+                            } catch (RemoteException e) {
+                                // Shouldn't happen.
+                                Log.e(TAG, "Failed to talk to package manager", e);
+                            }
+                        }
+                        int myUserId = UserHandle.myUserId();
+                        if (isProfileOfOrSame(userManager, myUserId, blockingUserId)) {
+                            getProgressFragment().setDeviceManagerButtonVisible(true);
+                        } else {
+                            getProgressFragment().setDeviceManagerButtonVisible(false);
+                            getProgressFragment().setUsersButtonVisible(true);
+                        }
+                        // TODO: b/25442806
+                        if (blockingUserId == UserHandle.USER_SYSTEM) {
+                            statusText = getString(R.string.uninstall_blocked_device_owner);
+                        } else if (blockingUserId == UserHandle.USER_NULL) {
+                            Log.d(TAG, "Uninstall failed for " + packageName + " with code "
+                                    + msg.arg1 + " no blocking user");
+                            statusText = getString(R.string.uninstall_failed);
+                        } else {
+                            statusText = mAllUsers
+                                    ? getString(R.string.uninstall_all_blocked_profile_owner) :
+                                    getString(R.string.uninstall_blocked_profile_owner);
+                        }
+                        break;
+                    }
+                    default:
+                        Log.d(TAG, "Uninstall failed for " + packageName + " with code "
+                                + msg.arg1);
+                        statusText = getString(R.string.uninstall_failed);
+                        break;
+                }
+                getProgressFragment().showCompletion(statusText);
+                break;
+            default:
+                break;
+        }
+    }
+
+    private boolean isProfileOfOrSame(UserManager userManager, int userId, int profileId) {
+        if (userId == profileId) {
+            return true;
+        }
+        UserInfo parentUser = userManager.getProfileParent(profileId);
+        return parentUser != null && parentUser.id == userId;
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        Intent intent = getIntent();
+        mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+        mCallback = intent.getIBinderExtra(PackageInstaller.EXTRA_CALLBACK);
+
+        // This currently does not support going through a onDestroy->onCreate cycle. Hence if that
+        // happened, just fail the operation for mysterious reasons.
+        if (icicle != null) {
+            mResultCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
+
+            if (mCallback != null) {
+                final IPackageDeleteObserver2 observer = IPackageDeleteObserver2.Stub
+                        .asInterface(mCallback);
+                try {
+                    observer.onPackageDeleted(mAppInfo.packageName, mResultCode, null);
+                } catch (RemoteException ignored) {
+                }
+                finish();
+            } else {
+                setResultAndFinish();
+            }
+
+            return;
+        }
+
+        mAllUsers = intent.getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false);
+        UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
+        if (user == null) {
+            user = android.os.Process.myUserHandle();
+        }
+
+        PackageDeleteObserver observer = new PackageDeleteObserver();
+
+        // Make window transparent until initView is called. In many cases we can avoid showing the
+        // UI at all as the app is uninstalled very quickly. If we show the UI and instantly remove
+        // it, it just looks like a flicker.
+        getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+        getWindow().setStatusBarColor(Color.TRANSPARENT);
+        getWindow().setNavigationBarColor(Color.TRANSPARENT);
+
+        try {
+            getPackageManager().deletePackageAsUser(mAppInfo.packageName, observer,
+                    mAllUsers ? PackageManager.DELETE_ALL_USERS : 0, user.getIdentifier());
+        } catch (IllegalArgumentException e) {
+            // Couldn't find the package, no need to call uninstall.
+            Log.w(TAG, "Could not find package, not deleting " + mAppInfo.packageName, e);
+        }
+
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(UNINSTALL_IS_SLOW),
+                QUICK_INSTALL_DELAY_MILLIS);
+    }
+
+    public ApplicationInfo getAppInfo() {
+        return mAppInfo;
+    }
+
+    private class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
+        public void packageDeleted(String packageName, int returnCode) {
+            Message msg = mHandler.obtainMessage(UNINSTALL_COMPLETE);
+            msg.arg1 = returnCode;
+            msg.obj = packageName;
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    public void setResultAndFinish() {
+        setResult(mResultCode);
+        finish();
+    }
+
+    private void initView() {
+        if (mIsViewInitialized) {
+            return;
+        }
+        mIsViewInitialized = true;
+
+        // We set the window background to translucent in constructor, revert this
+        TypedValue attribute = new TypedValue();
+        getTheme().resolveAttribute(android.R.attr.windowBackground, attribute, true);
+        if (attribute.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
+                attribute.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+            getWindow().setBackgroundDrawable(new ColorDrawable(attribute.data));
+        } else {
+            getWindow().setBackgroundDrawable(getResources().getDrawable(attribute.resourceId,
+                    getTheme()));
+        }
+
+        getTheme().resolveAttribute(android.R.attr.navigationBarColor, attribute, true);
+        getWindow().setNavigationBarColor(attribute.data);
+
+        getTheme().resolveAttribute(android.R.attr.statusBarColor, attribute, true);
+        getWindow().setStatusBarColor(attribute.data);
+
+        boolean isUpdate = ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
+        setTitle(isUpdate ? R.string.uninstall_update_title : R.string.uninstall_application_title);
+
+        getFragmentManager().beginTransaction()
+                .add(android.R.id.content, new UninstallAppProgressFragment(), FRAGMENT_TAG)
+                .commitNowAllowingStateLoss();
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent ev) {
+        if (ev.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+            if (mResultCode == -1) {
+                // Ignore back key when installation is in progress
+                return true;
+            } else {
+                // If installation is done, just set the result code
+                setResult(mResultCode);
+            }
+        }
+        return super.dispatchKeyEvent(ev);
+    }
+
+    private ProgressFragment getProgressFragment() {
+        return (ProgressFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
+    }
+
+    public interface ProgressFragment {
+        void setUsersButtonVisible(boolean visible);
+        void setDeviceManagerButtonVisible(boolean visible);
+        void showCompletion(CharSequence statusText);
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAppProgressFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAppProgressFragment.java
new file mode 100644
index 0000000..af6d9c5
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAppProgressFragment.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.packageinstaller.television;
+
+import android.annotation.Nullable;
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.packageinstaller.PackageUtil;
+import com.android.packageinstaller.R;
+
+public class UninstallAppProgressFragment extends Fragment implements View.OnClickListener,
+        UninstallAppProgress.ProgressFragment {
+    private static final String TAG = "UninstallAppProgressF"; // full class name is too long
+
+    private Button mOkButton;
+    private Button mDeviceManagerButton;
+    private Button mUsersButton;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+            Bundle savedInstanceState) {
+        final View root = inflater.inflate(R.layout.uninstall_progress, container, false);
+        // Initialize views
+        View snippetView = root.findViewById(R.id.app_snippet);
+        PackageUtil.initSnippetForInstalledApp(getContext(),
+                ((UninstallAppProgress)getActivity()).getAppInfo(), snippetView);
+        mDeviceManagerButton = (Button) root.findViewById(R.id.device_manager_button);
+        mUsersButton = (Button) root.findViewById(R.id.users_button);
+        mDeviceManagerButton.setVisibility(View.GONE);
+        mDeviceManagerButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Intent intent = new Intent();
+                intent.setClassName("com.android.settings",
+                        "com.android.settings.Settings$DeviceAdminSettingsActivity");
+                intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK);
+                startActivity(intent);
+                getActivity().finish();
+            }
+        });
+        mUsersButton.setVisibility(View.GONE);
+        mUsersButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Intent intent = new Intent(Settings.ACTION_USER_SETTINGS);
+                intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK);
+                startActivity(intent);
+                getActivity().finish();
+            }
+        });
+        // Hide button till progress is being displayed
+        mOkButton = (Button) root.findViewById(R.id.ok_button);
+        mOkButton.setOnClickListener(this);
+
+        return root;
+    }
+
+    public void onClick(View v) {
+        final UninstallAppProgress activity = (UninstallAppProgress) getActivity();
+        if(v == mOkButton && activity != null) {
+            Log.i(TAG, "Finished uninstalling pkg: " +
+                    activity.getAppInfo().packageName);
+            activity.setResultAndFinish();
+        }
+    }
+
+    @Override
+    public void setUsersButtonVisible(boolean visible) {
+        mUsersButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public void setDeviceManagerButtonVisible(boolean visible) {
+        mDeviceManagerButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public void showCompletion(CharSequence statusText) {
+        final View root = getView();
+        root.findViewById(R.id.progress_view).setVisibility(View.GONE);
+        root.findViewById(R.id.status_view).setVisibility(View.VISIBLE);
+        ((TextView) root.findViewById(R.id.status_text)).setText(statusText);
+        root.findViewById(R.id.ok_panel).setVisibility(View.VISIBLE);
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/wear/InstallTask.java b/packages/PackageInstaller/src/com/android/packageinstaller/wear/InstallTask.java
new file mode 100644
index 0000000..53a460d
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/wear/InstallTask.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.packageinstaller.wear;
+
+import android.content.Context;
+import android.content.IntentSender;
+import android.content.pm.PackageInstaller;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Task that installs an APK. This must not be called on the main thread.
+ * This code is based off the Finsky/Wearsky implementation
+ */
+public class InstallTask {
+    private static final String TAG = "InstallTask";
+
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+    private final Context mContext;
+    private String mPackageName;
+    private ParcelFileDescriptor mParcelFileDescriptor;
+    private PackageInstallerImpl.InstallListener mCallback;
+    private PackageInstaller.Session mSession;
+    private IntentSender mCommitCallback;
+
+    private Exception mException = null;
+    private int mErrorCode = 0;
+    private String mErrorDesc = null;
+
+    public InstallTask(Context context, String packageName,
+            ParcelFileDescriptor parcelFileDescriptor,
+            PackageInstallerImpl.InstallListener callback, PackageInstaller.Session session,
+            IntentSender commitCallback) {
+        mContext = context;
+        mPackageName = packageName;
+        mParcelFileDescriptor = parcelFileDescriptor;
+        mCallback = callback;
+        mSession = session;
+        mCommitCallback = commitCallback;
+    }
+
+    public boolean isError() {
+        return mErrorCode != InstallerConstants.STATUS_SUCCESS || !TextUtils.isEmpty(mErrorDesc);
+    }
+
+    public void execute() {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
+            throw new IllegalStateException("This method cannot be called from the UI thread.");
+        }
+
+        OutputStream sessionStream = null;
+        try {
+            sessionStream = mSession.openWrite(mPackageName, 0, -1);
+
+            // 2b: Stream the asset to the installer. Note:
+            // Note: writeToOutputStreamFromAsset() always safely closes the input stream
+            writeToOutputStreamFromAsset(sessionStream);
+            mSession.fsync(sessionStream);
+        } catch (Exception e) {
+            mException = e;
+            mErrorCode = InstallerConstants.ERROR_INSTALL_COPY_STREAM;
+            mErrorDesc = "Could not write to stream";
+        } finally {
+            if (sessionStream != null) {
+                // 2c: close output stream
+                try {
+                    sessionStream.close();
+                } catch (Exception e) {
+                    // Ignore otherwise
+                    if (mException == null) {
+                        mException = e;
+                        mErrorCode = InstallerConstants.ERROR_INSTALL_CLOSE_STREAM;
+                        mErrorDesc = "Could not close session stream";
+                    }
+                }
+            }
+        }
+
+        if (mErrorCode != InstallerConstants.STATUS_SUCCESS) {
+            // An error occurred, we're done
+            Log.e(TAG, "Exception while installing " + mPackageName + ": " + mErrorCode + ", "
+                    + mErrorDesc + ", " + mException);
+            mSession.close();
+            mCallback.installFailed(mErrorCode, "[" + mPackageName + "]" + mErrorDesc);
+        } else {
+            // 3. Commit the session (this actually installs it.)  Session map
+            // will be cleaned up in the callback.
+            mCallback.installBeginning();
+            mSession.commit(mCommitCallback);
+            mSession.close();
+        }
+    }
+
+    /**
+     * {@code PackageInstaller} works with streams. Get the {@code FileDescriptor}
+     * corresponding to the {@code Asset} and then write the contents into an
+     * {@code OutputStream} that is passed in.
+     * <br>
+     * The {@code FileDescriptor} is closed but the {@code OutputStream} is not closed.
+     */
+    private boolean writeToOutputStreamFromAsset(OutputStream outputStream) {
+        if (outputStream == null) {
+            mErrorCode = InstallerConstants.ERROR_INSTALL_COPY_STREAM_EXCEPTION;
+            mErrorDesc = "Got a null OutputStream.";
+            return false;
+        }
+
+        if (mParcelFileDescriptor == null || mParcelFileDescriptor.getFileDescriptor() == null)  {
+            mErrorCode = InstallerConstants.ERROR_COULD_NOT_GET_FD;
+            mErrorDesc = "Could not get FD";
+            return false;
+        }
+
+        InputStream inputStream = null;
+        try {
+            byte[] inputBuf = new byte[DEFAULT_BUFFER_SIZE];
+            int bytesRead;
+            inputStream = new ParcelFileDescriptor.AutoCloseInputStream(mParcelFileDescriptor);
+
+            while ((bytesRead = inputStream.read(inputBuf)) > -1) {
+                if (bytesRead > 0) {
+                    outputStream.write(inputBuf, 0, bytesRead);
+                }
+            }
+
+            outputStream.flush();
+        } catch (IOException e) {
+            mErrorCode = InstallerConstants.ERROR_INSTALL_APK_COPY_FAILURE;
+            mErrorDesc = "Reading from Asset FD or writing to temp file failed: " + e;
+            return false;
+        } finally {
+            safeClose(inputStream);
+        }
+
+        return true;
+    }
+
+    /**
+     * Quietly close a closeable resource (e.g. a stream or file). The input may already
+     * be closed and it may even be null.
+     */
+    public static void safeClose(Closeable resource) {
+        if (resource != null) {
+            try {
+                resource.close();
+            } catch (IOException ioe) {
+                // Catch and discard the error
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/wear/InstallerConstants.java b/packages/PackageInstaller/src/com/android/packageinstaller/wear/InstallerConstants.java
new file mode 100644
index 0000000..3daf3d8
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/wear/InstallerConstants.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.packageinstaller.wear;
+
+/**
+ * Constants for Installation / Uninstallation requests.
+ * Using the same values as Finsky/Wearsky code for consistency in user analytics of failures
+ */
+public class InstallerConstants {
+    /** Request succeeded */
+    public static final int STATUS_SUCCESS = 0;
+
+    /**
+     * The new PackageInstaller also returns a small set of less granular error codes, which
+     * we'll remap to the range -500 and below to keep away from existing installer codes
+     * (which run from -1 to -110).
+     */
+    public final static int ERROR_PACKAGEINSTALLER_BASE = -500;
+
+    public static final int ERROR_COULD_NOT_GET_FD = -603;
+    /** This node is not targeted by this request. */
+
+    /** The install did not complete because could not create PackageInstaller session */
+    public final static int ERROR_INSTALL_CREATE_SESSION = -612;
+    /** The install did not complete because could not open PackageInstaller session  */
+    public final static int ERROR_INSTALL_OPEN_SESSION = -613;
+    /** The install did not complete because could not open PackageInstaller output stream */
+    public final static int ERROR_INSTALL_OPEN_STREAM = -614;
+    /** The install did not complete because of an exception while streaming bytes */
+    public final static int ERROR_INSTALL_COPY_STREAM_EXCEPTION = -615;
+    /** The install did not complete because of an unexpected exception from PackageInstaller */
+    public final static int ERROR_INSTALL_SESSION_EXCEPTION = -616;
+    /** The install did not complete because of an unexpected userActionRequired callback */
+    public final static int ERROR_INSTALL_USER_ACTION_REQUIRED = -617;
+    /** The install did not complete because of an unexpected broadcast (missing fields) */
+    public final static int ERROR_INSTALL_MALFORMED_BROADCAST = -618;
+    /** The install did not complete because of an error while copying from downloaded file */
+    public final static int ERROR_INSTALL_APK_COPY_FAILURE = -619;
+    /** The install did not complete because of an error while copying to the PackageInstaller
+     * output stream */
+    public final static int ERROR_INSTALL_COPY_STREAM = -620;
+    /** The install did not complete because of an error while closing the PackageInstaller
+     * output stream */
+    public final static int ERROR_INSTALL_CLOSE_STREAM = -621;
+}
\ No newline at end of file
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerFactory.java b/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerFactory.java
new file mode 100644
index 0000000..bdc22cf
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.packageinstaller.wear;
+
+import android.content.Context;
+
+/**
+ * Factory that creates a Package Installer.
+ */
+public class PackageInstallerFactory {
+    private static PackageInstallerImpl sPackageInstaller;
+
+    /**
+     * Return the PackageInstaller shared object. {@code init} should have already been called.
+     */
+    public synchronized static PackageInstallerImpl getPackageInstaller(Context context) {
+        if (sPackageInstaller == null) {
+            sPackageInstaller = new PackageInstallerImpl(context);
+        }
+        return sPackageInstaller;
+    }
+}
\ No newline at end of file
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerImpl.java b/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerImpl.java
new file mode 100644
index 0000000..bf4b03c
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerImpl.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.packageinstaller.wear;
+
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.PackageInstaller;
+import android.os.Build;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of package manager installation using modern PackageInstaller api.
+ *
+ * Heavily copied from Wearsky/Finsky implementation
+ */
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+public class PackageInstallerImpl {
+    private static final String TAG = "PackageInstallerImpl";
+
+    /** Intent actions used for broadcasts from PackageInstaller back to the local receiver */
+    private static final String ACTION_INSTALL_COMMIT =
+            "com.android.vending.INTENT_PACKAGE_INSTALL_COMMIT";
+
+    private final Context mContext;
+    private final PackageInstaller mPackageInstaller;
+    private final Map<String, PackageInstaller.SessionInfo> mSessionInfoMap;
+    private final Map<String, PackageInstaller.Session> mOpenSessionMap;
+
+    public PackageInstallerImpl(Context context) {
+        mContext = context.getApplicationContext();
+        mPackageInstaller = mContext.getPackageManager().getPackageInstaller();
+
+        // Capture a map of known sessions
+        // This list will be pruned a bit later (stale sessions will be canceled)
+        mSessionInfoMap = new HashMap<String, PackageInstaller.SessionInfo>();
+        List<PackageInstaller.SessionInfo> mySessions = mPackageInstaller.getMySessions();
+        for (int i = 0; i < mySessions.size(); i++) {
+            PackageInstaller.SessionInfo sessionInfo = mySessions.get(i);
+            String packageName = sessionInfo.getAppPackageName();
+            PackageInstaller.SessionInfo oldInfo = mSessionInfoMap.put(packageName, sessionInfo);
+
+            // Checking for old info is strictly for logging purposes
+            if (oldInfo != null) {
+                Log.w(TAG, "Multiple sessions for " + packageName + " found. Removing " + oldInfo
+                        .getSessionId() + " & keeping " + mySessions.get(i).getSessionId());
+            }
+        }
+        mOpenSessionMap = new HashMap<String, PackageInstaller.Session>();
+    }
+
+    /**
+     * This callback will be made after an installation attempt succeeds or fails.
+     */
+    public interface InstallListener {
+        /**
+         * This callback signals that preflight checks have succeeded and installation
+         * is beginning.
+         */
+        void installBeginning();
+
+        /**
+         * This callback signals that installation has completed.
+         */
+        void installSucceeded();
+
+        /**
+         * This callback signals that installation has failed.
+         */
+        void installFailed(int errorCode, String errorDesc);
+    }
+
+    /**
+     * This is a placeholder implementation that bundles an entire "session" into a single
+     * call. This will be replaced by more granular versions that allow longer session lifetimes,
+     * download progress tracking, etc.
+     *
+     * This must not be called on main thread.
+     */
+    public void install(final String packageName, ParcelFileDescriptor parcelFileDescriptor,
+            final InstallListener callback) {
+        // 0. Generic try/catch block because I am not really sure what exceptions (other than
+        // IOException) might be thrown by PackageInstaller and I want to handle them
+        // at least slightly gracefully.
+        try {
+            // 1. Create or recover a session, and open it
+            // Try recovery first
+            PackageInstaller.Session session = null;
+            PackageInstaller.SessionInfo sessionInfo = mSessionInfoMap.get(packageName);
+            if (sessionInfo != null) {
+                // See if it's openable, or already held open
+                session = getSession(packageName);
+            }
+            // If open failed, or there was no session, create a new one and open it.
+            // If we cannot create or open here, the failure is terminal.
+            if (session == null) {
+                try {
+                    innerCreateSession(packageName);
+                } catch (IOException ioe) {
+                    Log.e(TAG, "Can't create session for " + packageName + ": " + ioe.getMessage());
+                    callback.installFailed(InstallerConstants.ERROR_INSTALL_CREATE_SESSION,
+                            "Could not create session");
+                    mSessionInfoMap.remove(packageName);
+                    return;
+                }
+                sessionInfo = mSessionInfoMap.get(packageName);
+                try {
+                    session = mPackageInstaller.openSession(sessionInfo.getSessionId());
+                    mOpenSessionMap.put(packageName, session);
+                } catch (SecurityException se) {
+                    Log.e(TAG, "Can't open session for " + packageName + ": " + se.getMessage());
+                    callback.installFailed(InstallerConstants.ERROR_INSTALL_OPEN_SESSION,
+                            "Can't open session");
+                    mSessionInfoMap.remove(packageName);
+                    return;
+                }
+            }
+
+            // 2. Launch task to handle file operations.
+            InstallTask task = new InstallTask( mContext, packageName, parcelFileDescriptor,
+                    callback, session,
+                    getCommitCallback(packageName, sessionInfo.getSessionId(), callback));
+            task.execute();
+            if (task.isError()) {
+                cancelSession(sessionInfo.getSessionId(), packageName);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Unexpected exception while installing: " + packageName + ": "
+                    + e.getMessage());
+            callback.installFailed(InstallerConstants.ERROR_INSTALL_SESSION_EXCEPTION,
+                    "Unexpected exception while installing " + packageName);
+        }
+    }
+
+    /**
+     * Retrieve an existing session. Will open if needed, but does not attempt to create.
+     */
+    private PackageInstaller.Session getSession(String packageName) {
+        // Check for already-open session
+        PackageInstaller.Session session = mOpenSessionMap.get(packageName);
+        if (session != null) {
+            try {
+                // Probe the session to ensure that it's still open. This may or may not
+                // throw (if non-open), but it may serve as a canary for stale sessions.
+                session.getNames();
+                return session;
+            } catch (IOException ioe) {
+                Log.e(TAG, "Stale open session for " + packageName + ": " + ioe.getMessage());
+                mOpenSessionMap.remove(packageName);
+            } catch (SecurityException se) {
+                Log.e(TAG, "Stale open session for " + packageName + ": " + se.getMessage());
+                mOpenSessionMap.remove(packageName);
+            }
+        }
+        // Check to see if this is a known session
+        PackageInstaller.SessionInfo sessionInfo = mSessionInfoMap.get(packageName);
+        if (sessionInfo == null) {
+            return null;
+        }
+        // Try to open it. If we fail here, assume that the SessionInfo was stale.
+        try {
+            session = mPackageInstaller.openSession(sessionInfo.getSessionId());
+        } catch (SecurityException se) {
+            Log.w(TAG, "SessionInfo was stale for " + packageName + " - deleting info");
+            mSessionInfoMap.remove(packageName);
+            return null;
+        } catch (IOException ioe) {
+            Log.w(TAG, "IOException opening old session for " + ioe.getMessage()
+                    + " - deleting info");
+            mSessionInfoMap.remove(packageName);
+            return null;
+        }
+        mOpenSessionMap.put(packageName, session);
+        return session;
+    }
+
+    /** This version throws an IOException when the session cannot be created */
+    private void innerCreateSession(String packageName) throws IOException {
+        if (mSessionInfoMap.containsKey(packageName)) {
+            Log.w(TAG, "Creating session for " + packageName + " when one already exists");
+            return;
+        }
+        PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+        params.setAppPackageName(packageName);
+
+        // IOException may be thrown at this point
+        int sessionId = mPackageInstaller.createSession(params);
+        PackageInstaller.SessionInfo sessionInfo = mPackageInstaller.getSessionInfo(sessionId);
+        mSessionInfoMap.put(packageName, sessionInfo);
+    }
+
+    /**
+     * Cancel a session based on its sessionId. Package name is for logging only.
+     */
+    private void cancelSession(int sessionId, String packageName) {
+        // Close if currently held open
+        closeSession(packageName);
+        // Remove local record
+        mSessionInfoMap.remove(packageName);
+        try {
+            mPackageInstaller.abandonSession(sessionId);
+        } catch (SecurityException se) {
+            // The session no longer exists, so we can exit quietly.
+            return;
+        }
+    }
+
+    /**
+     * Close a session if it happens to be held open.
+     */
+    private void closeSession(String packageName) {
+        PackageInstaller.Session session = mOpenSessionMap.remove(packageName);
+        if (session != null) {
+            // Unfortunately close() is not idempotent. Try our best to make this safe.
+            try {
+                session.close();
+            } catch (Exception e) {
+                Log.w(TAG, "Unexpected error closing session for " + packageName + ": "
+                        + e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Creates a commit callback for the package install that's underway. This will be called
+     * some time after calling session.commit() (above).
+     */
+    private IntentSender getCommitCallback(final String packageName, final int sessionId,
+            final InstallListener callback) {
+        // Create a single-use broadcast receiver
+        BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                mContext.unregisterReceiver(this);
+                handleCommitCallback(intent, packageName, sessionId, callback);
+            }
+        };
+        // Create a matching intent-filter and register the receiver
+        String action = ACTION_INSTALL_COMMIT + "." + packageName;
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(action);
+        mContext.registerReceiver(broadcastReceiver, intentFilter);
+
+        // Create a matching PendingIntent and use it to generate the IntentSender
+        Intent broadcastIntent = new Intent(action);
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, packageName.hashCode(),
+                broadcastIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
+        return pendingIntent.getIntentSender();
+    }
+
+    /**
+     * Examine the extras to determine information about the package update/install, decode
+     * the result, and call the appropriate callback.
+     *
+     * @param intent The intent, which the PackageInstaller will have added Extras to
+     * @param packageName The package name we created the receiver for
+     * @param sessionId The session Id we created the receiver for
+     * @param callback The callback to report success/failure to
+     */
+    private void handleCommitCallback(Intent intent, String packageName, int sessionId,
+            InstallListener callback) {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "Installation of " + packageName + " finished with extras "
+                    + intent.getExtras());
+        }
+        String statusMessage = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
+        int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, Integer.MIN_VALUE);
+        if (status == PackageInstaller.STATUS_SUCCESS) {
+            cancelSession(sessionId, packageName);
+            callback.installSucceeded();
+        } else if (status == -1 /*PackageInstaller.STATUS_USER_ACTION_REQUIRED*/) {
+            // TODO - use the constant when the correct/final name is in the SDK
+            // TODO This is unexpected, so we are treating as failure for now
+            cancelSession(sessionId, packageName);
+            callback.installFailed(InstallerConstants.ERROR_INSTALL_USER_ACTION_REQUIRED,
+                    "Unexpected: user action required");
+        } else {
+            cancelSession(sessionId, packageName);
+            int errorCode = getPackageManagerErrorCode(status);
+            Log.e(TAG, "Error " + errorCode + " while installing " + packageName + ": "
+                    + statusMessage);
+            callback.installFailed(errorCode, null);
+        }
+    }
+
+    private int getPackageManagerErrorCode(int status) {
+        // This is a hack: because PackageInstaller now reports error codes
+        // with small positive values, we need to remap them into a space
+        // that is more compatible with the existing package manager error codes.
+        // See https://sites.google.com/a/google.com/universal-store/documentation
+        //       /android-client/download-error-codes
+        int errorCode;
+        if (status == Integer.MIN_VALUE) {
+            errorCode = InstallerConstants.ERROR_INSTALL_MALFORMED_BROADCAST;
+        } else {
+            errorCode = InstallerConstants.ERROR_PACKAGEINSTALLER_BASE - status;
+        }
+        return errorCode;
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageArgs.java b/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageArgs.java
new file mode 100644
index 0000000..2c289b2
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageArgs.java
@@ -0,0 +1,100 @@
+/*
+ * 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.packageinstaller.wear;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+/**
+ * Installation Util that contains a list of parameters that are needed for
+ * installing/uninstalling.
+ */
+public class WearPackageArgs {
+    private static final String KEY_PACKAGE_NAME =
+            "com.google.android.clockwork.EXTRA_PACKAGE_NAME";
+    private static final String KEY_ASSET_URI =
+            "com.google.android.clockwork.EXTRA_ASSET_URI";
+    private static final String KEY_START_ID =
+            "com.google.android.clockwork.EXTRA_START_ID";
+    private static final String KEY_PERM_URI =
+            "com.google.android.clockwork.EXTRA_PERM_URI";
+    private static final String KEY_CHECK_PERMS =
+            "com.google.android.clockwork.EXTRA_CHECK_PERMS";
+    private static final String KEY_SKIP_IF_SAME_VERSION =
+            "com.google.android.clockwork.EXTRA_SKIP_IF_SAME_VERSION";
+    private static final String KEY_COMPRESSION_ALG =
+            "com.google.android.clockwork.EXTRA_KEY_COMPRESSION_ALG";
+    private static final String KEY_COMPANION_SDK_VERSION =
+            "com.google.android.clockwork.EXTRA_KEY_COMPANION_SDK_VERSION";
+    private static final String KEY_COMPANION_DEVICE_VERSION =
+            "com.google.android.clockwork.EXTRA_KEY_COMPANION_DEVICE_VERSION";
+    private static final String KEY_SHOULD_CHECK_GMS_DEPENDENCY =
+            "com.google.android.clockwork.EXTRA_KEY_SHOULD_CHECK_GMS_DEPENDENCY";
+    private static final String KEY_SKIP_IF_LOWER_VERSION =
+            "com.google.android.clockwork.EXTRA_SKIP_IF_LOWER_VERSION";
+
+    public static String getPackageName(Bundle b) {
+        return b.getString(KEY_PACKAGE_NAME);
+    }
+
+    public static Bundle setPackageName(Bundle b, String packageName) {
+        b.putString(KEY_PACKAGE_NAME, packageName);
+        return b;
+    }
+
+    public static Uri getAssetUri(Bundle b) {
+        return b.getParcelable(KEY_ASSET_URI);
+    }
+
+    public static Uri getPermUri(Bundle b) {
+        return b.getParcelable(KEY_PERM_URI);
+    }
+
+    public static boolean checkPerms(Bundle b) {
+        return b.getBoolean(KEY_CHECK_PERMS);
+    }
+
+    public static boolean skipIfSameVersion(Bundle b) {
+        return b.getBoolean(KEY_SKIP_IF_SAME_VERSION);
+    }
+
+    public static int getCompanionSdkVersion(Bundle b) {
+        return b.getInt(KEY_COMPANION_SDK_VERSION);
+    }
+
+    public static int getCompanionDeviceVersion(Bundle b) {
+        return b.getInt(KEY_COMPANION_DEVICE_VERSION);
+    }
+
+    public static String getCompressionAlg(Bundle b) {
+        return b.getString(KEY_COMPRESSION_ALG);
+    }
+
+    public static int getStartId(Bundle b) {
+        return b.getInt(KEY_START_ID);
+    }
+
+    public static boolean skipIfLowerVersion(Bundle b) {
+        return b.getBoolean(KEY_SKIP_IF_LOWER_VERSION, false);
+    }
+
+    public static Bundle setStartId(Bundle b, int startId) {
+        b.putInt(KEY_START_ID, startId);
+        return b;
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageIconProvider.java b/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageIconProvider.java
new file mode 100644
index 0000000..02b9d29
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageIconProvider.java
@@ -0,0 +1,202 @@
+/*
+ * 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.packageinstaller.wear;
+
+import android.annotation.TargetApi;
+import android.app.ActivityManager;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Build;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.List;
+
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+public class WearPackageIconProvider extends ContentProvider {
+    private static final String TAG = "WearPackageIconProvider";
+    public static final String AUTHORITY = "com.google.android.packageinstaller.wear.provider";
+
+    private static final String REQUIRED_PERMISSION =
+            "com.google.android.permission.INSTALL_WEARABLE_PACKAGES";
+
+    /** MIME types. */
+    public static final String ICON_TYPE = "vnd.android.cursor.item/cw_package_icon";
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        throw new UnsupportedOperationException("Query is not supported.");
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        if (uri == null) {
+            throw new IllegalArgumentException("URI passed in is null.");
+        }
+
+        if (AUTHORITY.equals(uri.getEncodedAuthority())) {
+            return ICON_TYPE;
+        }
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        throw new UnsupportedOperationException("Insert is not supported.");
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        if (uri == null) {
+            throw new IllegalArgumentException("URI passed in is null.");
+        }
+
+        enforcePermissions(uri);
+
+        if (ICON_TYPE.equals(getType(uri))) {
+            final File file = WearPackageUtil.getIconFile(
+                    this.getContext().getApplicationContext(), getPackageNameFromUri(uri));
+            if (file != null) {
+                file.delete();
+            }
+        }
+
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException("Update is not supported.");
+    }
+
+    @Override
+    public ParcelFileDescriptor openFile(
+            Uri uri, @SuppressWarnings("unused") String mode) throws FileNotFoundException {
+        if (uri == null) {
+            throw new IllegalArgumentException("URI passed in is null.");
+        }
+
+        enforcePermissions(uri);
+
+        if (ICON_TYPE.equals(getType(uri))) {
+            final File file = WearPackageUtil.getIconFile(
+                    this.getContext().getApplicationContext(), getPackageNameFromUri(uri));
+            if (file != null) {
+                return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
+            }
+        }
+        return null;
+    }
+
+    public static Uri getUriForPackage(final String packageName) {
+        return Uri.parse("content://" + AUTHORITY + "/icons/" + packageName + ".icon");
+    }
+
+    private String getPackageNameFromUri(Uri uri) {
+        if (uri == null) {
+            return null;
+        }
+        List<String> pathSegments = uri.getPathSegments();
+        String packageName = pathSegments.get(pathSegments.size() - 1);
+
+        if (packageName.endsWith(".icon")) {
+            packageName = packageName.substring(0, packageName.lastIndexOf("."));
+        }
+        return packageName;
+    }
+
+    /**
+     * Make sure the calling app is either a system app or the same app or has the right permission.
+     * @throws SecurityException if the caller has insufficient permissions.
+     */
+    @TargetApi(Build.VERSION_CODES.BASE_1_1)
+    private void enforcePermissions(Uri uri) {
+        // Redo some of the permission check in {@link ContentProvider}. Just add an extra check to
+        // allow System process to access this provider.
+        Context context = getContext();
+        final int pid = Binder.getCallingPid();
+        final int uid = Binder.getCallingUid();
+        final int myUid = android.os.Process.myUid();
+
+        if (uid == myUid || isSystemApp(context, pid)) {
+            return;
+        }
+
+        if (context.checkPermission(REQUIRED_PERMISSION, pid, uid) == PERMISSION_GRANTED) {
+            return;
+        }
+
+        // last chance, check against any uri grants
+        if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
+                == PERMISSION_GRANTED) {
+            return;
+        }
+
+        throw new SecurityException("Permission Denial: reading "
+                + getClass().getName() + " uri " + uri + " from pid=" + pid
+                + ", uid=" + uid);
+    }
+
+    /**
+     * From the pid of the calling process, figure out whether this is a system app or not. We do
+     * this by checking the application information corresponding to the pid and then checking if
+     * FLAG_SYSTEM is set.
+     */
+    @TargetApi(Build.VERSION_CODES.CUPCAKE)
+    private boolean isSystemApp(Context context, int pid) {
+        // Get the Activity Manager Object
+        ActivityManager aManager =
+                (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        // Get the list of running Applications
+        List<ActivityManager.RunningAppProcessInfo> rapInfoList =
+                aManager.getRunningAppProcesses();
+        for (ActivityManager.RunningAppProcessInfo rapInfo : rapInfoList) {
+            if (rapInfo.pid == pid) {
+                try {
+                    PackageInfo pkgInfo = context.getPackageManager().getPackageInfo(
+                            rapInfo.pkgList[0], 0);
+                    if (pkgInfo != null && pkgInfo.applicationInfo != null &&
+                            (pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                        Log.d(TAG, pid + " is a system app.");
+                        return true;
+                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.e(TAG, "Could not find package information.", e);
+                    return false;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageInstallerService.java b/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageInstallerService.java
new file mode 100644
index 0000000..e5f7613
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageInstallerService.java
@@ -0,0 +1,589 @@
+/*
+ * 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.packageinstaller.wear;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.FeatureInfo;
+import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.os.Process;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.packageinstaller.DeviceUtils;
+import com.android.packageinstaller.PackageUtil;
+import com.android.packageinstaller.R;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Service that will install/uninstall packages. It will check for permissions and features as well.
+ *
+ * -----------
+ *
+ * Debugging information:
+ *
+ *  Install Action example:
+ *  adb shell am startservice -a com.android.packageinstaller.wear.INSTALL_PACKAGE \
+ *     -d package://com.google.android.gms \
+ *     --eu com.google.android.clockwork.EXTRA_ASSET_URI content://com.google.android.clockwork.home.provider/host/com.google.android.wearable.app/wearable/com.google.android.gms/apk \
+ *     --es android.intent.extra.INSTALLER_PACKAGE_NAME com.google.android.gms \
+ *     --ez com.google.android.clockwork.EXTRA_CHECK_PERMS false \
+ *     --eu com.google.android.clockwork.EXTRA_PERM_URI content://com.google.android.clockwork.home.provider/host/com.google.android.wearable.app/permissions \
+ *     com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService
+ *
+ *  Uninstall Action example:
+ *  adb shell am startservice -a com.android.packageinstaller.wear.UNINSTALL_PACKAGE \
+ *     -d package://com.google.android.gms \
+ *     com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService
+ *
+ *  Retry GMS:
+ *  adb shell am startservice -a com.android.packageinstaller.wear.RETRY_GMS \
+ *     com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService
+ */
+public class WearPackageInstallerService extends Service {
+    private static final String TAG = "WearPkgInstallerService";
+
+    private static final String WEAR_APPS_CHANNEL = "wear_app_install_uninstall";
+
+    private final int START_INSTALL = 1;
+    private final int START_UNINSTALL = 2;
+
+    private int mInstallNotificationId = 1;
+    private final Map<String, Integer> mNotifIdMap = new ArrayMap<>();
+
+    private final class ServiceHandler extends Handler {
+        public ServiceHandler(Looper looper) {
+            super(looper);
+        }
+
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case START_INSTALL:
+                    installPackage(msg.getData());
+                    break;
+                case START_UNINSTALL:
+                    uninstallPackage(msg.getData());
+                    break;
+            }
+        }
+    }
+    private ServiceHandler mServiceHandler;
+    private NotificationChannel mNotificationChannel;
+    private static volatile PowerManager.WakeLock lockStatic = null;
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        HandlerThread thread = new HandlerThread("PackageInstallerThread",
+                Process.THREAD_PRIORITY_BACKGROUND);
+        thread.start();
+
+        mServiceHandler = new ServiceHandler(thread.getLooper());
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (!DeviceUtils.isWear(this)) {
+            Log.w(TAG, "Not running on wearable.");
+            finishServiceEarly(startId);
+            return START_NOT_STICKY;
+        }
+
+        if (intent == null) {
+            Log.w(TAG, "Got null intent.");
+            finishServiceEarly(startId);
+            return START_NOT_STICKY;
+        }
+
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "Got install/uninstall request " + intent);
+        }
+
+        Uri packageUri = intent.getData();
+        if (packageUri == null) {
+            Log.e(TAG, "No package URI in intent");
+            finishServiceEarly(startId);
+            return START_NOT_STICKY;
+        }
+
+        final String packageName = WearPackageUtil.getSanitizedPackageName(packageUri);
+        if (packageName == null) {
+            Log.e(TAG, "Invalid package name in URI (expected package:<pkgName>): " + packageUri);
+            finishServiceEarly(startId);
+            return START_NOT_STICKY;
+        }
+
+        PowerManager.WakeLock lock = getLock(this.getApplicationContext());
+        if (!lock.isHeld()) {
+            lock.acquire();
+        }
+
+        Bundle intentBundle = intent.getExtras();
+        if (intentBundle == null) {
+            intentBundle = new Bundle();
+        }
+        WearPackageArgs.setStartId(intentBundle, startId);
+        WearPackageArgs.setPackageName(intentBundle, packageName);
+        Message msg;
+        String notifTitle;
+        if (Intent.ACTION_INSTALL_PACKAGE.equals(intent.getAction())) {
+            msg = mServiceHandler.obtainMessage(START_INSTALL);
+            notifTitle = getString(R.string.installing);
+        } else if (Intent.ACTION_UNINSTALL_PACKAGE.equals(intent.getAction())) {
+            msg = mServiceHandler.obtainMessage(START_UNINSTALL);
+            notifTitle = getString(R.string.uninstalling);
+        } else {
+            Log.e(TAG, "Unknown action : " + intent.getAction());
+            finishServiceEarly(startId);
+            return START_NOT_STICKY;
+        }
+        Pair<Integer, Notification> notifPair = buildNotification(packageName, notifTitle);
+        startForeground(notifPair.first, notifPair.second);
+        msg.setData(intentBundle);
+        mServiceHandler.sendMessage(msg);
+        return START_NOT_STICKY;
+    }
+
+    private void installPackage(Bundle argsBundle) {
+        int startId = WearPackageArgs.getStartId(argsBundle);
+        final String packageName = WearPackageArgs.getPackageName(argsBundle);
+        final Uri assetUri = WearPackageArgs.getAssetUri(argsBundle);
+        final Uri permUri = WearPackageArgs.getPermUri(argsBundle);
+        boolean checkPerms = WearPackageArgs.checkPerms(argsBundle);
+        boolean skipIfSameVersion = WearPackageArgs.skipIfSameVersion(argsBundle);
+        int companionSdkVersion = WearPackageArgs.getCompanionSdkVersion(argsBundle);
+        int companionDeviceVersion = WearPackageArgs.getCompanionDeviceVersion(argsBundle);
+        String compressionAlg = WearPackageArgs.getCompressionAlg(argsBundle);
+        boolean skipIfLowerVersion = WearPackageArgs.skipIfLowerVersion(argsBundle);
+
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "Installing package: " + packageName + ", assetUri: " + assetUri +
+                    ",permUri: " + permUri + ", startId: " + startId + ", checkPerms: " +
+                    checkPerms + ", skipIfSameVersion: " + skipIfSameVersion +
+                    ", compressionAlg: " + compressionAlg + ", companionSdkVersion: " +
+                    companionSdkVersion + ", companionDeviceVersion: " + companionDeviceVersion +
+                    ", skipIfLowerVersion: " + skipIfLowerVersion);
+        }
+        final PackageManager pm = getPackageManager();
+        File tempFile = null;
+        int installFlags = 0;
+        PowerManager.WakeLock lock = getLock(this.getApplicationContext());
+        boolean messageSent = false;
+        try {
+            PackageInfo existingPkgInfo = null;
+            try {
+                existingPkgInfo = pm.getPackageInfo(packageName,
+                        PackageManager.MATCH_ANY_USER | PackageManager.GET_PERMISSIONS);
+                if (existingPkgInfo != null) {
+                    installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                // Ignore this exception. We could not find the package, will treat as a new
+                // installation.
+            }
+            if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Replacing package:" + packageName);
+                }
+            }
+            // TODO(28021618): This was left as a temp file due to the fact that this code is being
+            //       deprecated and that we need the bare minimum to continue working moving forward
+            //       If this code is used as reference, this permission logic might want to be
+            //       reworked to use a stream instead of a file so that we don't need to write a
+            //       file at all.  Note that there might be some trickiness with opening a stream
+            //       for multiple users.
+            ParcelFileDescriptor parcelFd = getContentResolver()
+                    .openFileDescriptor(assetUri, "r");
+            tempFile = WearPackageUtil.getFileFromFd(WearPackageInstallerService.this,
+                    parcelFd, packageName, compressionAlg);
+            if (tempFile == null) {
+                Log.e(TAG, "Could not create a temp file from FD for " + packageName);
+                return;
+            }
+            PackageParser.Package pkg = PackageUtil.getPackageInfo(this, tempFile);
+            if (pkg == null) {
+                Log.e(TAG, "Could not parse apk information for " + packageName);
+                return;
+            }
+
+            if (!pkg.packageName.equals(packageName)) {
+                Log.e(TAG, "Wearable Package Name has to match what is provided for " +
+                        packageName);
+                return;
+            }
+
+            pkg.applicationInfo.sourceDir = tempFile.getPath();
+            pkg.applicationInfo.publicSourceDir = tempFile.getPath();
+            getLabelAndUpdateNotification(packageName,
+                    getString(R.string.installing_app, pkg.applicationInfo.loadLabel(pm)));
+
+            List<String> wearablePerms = pkg.requestedPermissions;
+
+            // Log if the installed pkg has a higher version number.
+            if (existingPkgInfo != null) {
+                if (existingPkgInfo.getLongVersionCode() == pkg.getLongVersionCode()) {
+                    if (skipIfSameVersion) {
+                        Log.w(TAG, "Version number (" + pkg.getLongVersionCode() +
+                                ") of new app is equal to existing app for " + packageName +
+                                "; not installing due to versionCheck");
+                        return;
+                    } else {
+                        Log.w(TAG, "Version number of new app (" + pkg.getLongVersionCode() +
+                                ") is equal to existing app for " + packageName);
+                    }
+                } else if (existingPkgInfo.getLongVersionCode() > pkg.getLongVersionCode()) {
+                    if (skipIfLowerVersion) {
+                        // Starting in Feldspar, we are not going to allow downgrades of any app.
+                        Log.w(TAG, "Version number of new app (" + pkg.getLongVersionCode() +
+                                ") is lower than existing app ( "
+                                + existingPkgInfo.getLongVersionCode() +
+                                ") for " + packageName + "; not installing due to versionCheck");
+                        return;
+                    } else {
+                        Log.w(TAG, "Version number of new app (" + pkg.getLongVersionCode() +
+                                ") is lower than existing app ( "
+                                + existingPkgInfo.getLongVersionCode() + ") for " + packageName);
+                    }
+                }
+
+                // Following the Android Phone model, we should only check for permissions for any
+                // newly defined perms.
+                if (existingPkgInfo.requestedPermissions != null) {
+                    for (int i = 0; i < existingPkgInfo.requestedPermissions.length; ++i) {
+                        // If the permission is granted, then we will not ask to request it again.
+                        if ((existingPkgInfo.requestedPermissionsFlags[i] &
+                                PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
+                            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                                Log.d(TAG, existingPkgInfo.requestedPermissions[i] +
+                                        " is already granted for " + packageName);
+                            }
+                            wearablePerms.remove(existingPkgInfo.requestedPermissions[i]);
+                        }
+                    }
+                }
+            }
+
+            // Check that the wearable has all the features.
+            boolean hasAllFeatures = true;
+            if (pkg.reqFeatures != null) {
+                for (FeatureInfo feature : pkg.reqFeatures) {
+                    if (feature.name != null && !pm.hasSystemFeature(feature.name) &&
+                            (feature.flags & FeatureInfo.FLAG_REQUIRED) != 0) {
+                        Log.e(TAG, "Wearable does not have required feature: " + feature +
+                                " for " + packageName);
+                        hasAllFeatures = false;
+                    }
+                }
+            }
+
+            if (!hasAllFeatures) {
+                return;
+            }
+
+            // Check permissions on both the new wearable package and also on the already installed
+            // wearable package.
+            // If the app is targeting API level 23, we will also start a service in ClockworkHome
+            // which will ultimately prompt the user to accept/reject permissions.
+            if (checkPerms && !checkPermissions(pkg, companionSdkVersion, companionDeviceVersion,
+                    permUri, wearablePerms, tempFile)) {
+                Log.w(TAG, "Wearable does not have enough permissions.");
+                return;
+            }
+
+            // Finally install the package.
+            ParcelFileDescriptor fd = getContentResolver().openFileDescriptor(assetUri, "r");
+            PackageInstallerFactory.getPackageInstaller(this).install(packageName, fd,
+                    new PackageInstallListener(this, lock, startId, packageName));
+
+            messageSent = true;
+            Log.i(TAG, "Sent installation request for " + packageName);
+        } catch (FileNotFoundException e) {
+            Log.e(TAG, "Could not find the file with URI " + assetUri, e);
+        } finally {
+            if (!messageSent) {
+                // Some error happened. If the message has been sent, we can wait for the observer
+                // which will finish the service.
+                if (tempFile != null) {
+                    tempFile.delete();
+                }
+                finishService(lock, startId);
+            }
+        }
+    }
+
+    // TODO: This was left using the old PackageManager API due to the fact that this code is being
+    //       deprecated and that we need the bare minimum to continue working moving forward
+    //       If this code is used as reference, this logic should be reworked to use the new
+    //       PackageInstaller APIs similar to how installPackage was reworked
+    private void uninstallPackage(Bundle argsBundle) {
+        int startId = WearPackageArgs.getStartId(argsBundle);
+        final String packageName = WearPackageArgs.getPackageName(argsBundle);
+
+        PowerManager.WakeLock lock = getLock(this.getApplicationContext());
+        final PackageManager pm = getPackageManager();
+        try {
+            PackageInfo pkgInfo = pm.getPackageInfo(packageName, 0);
+            getLabelAndUpdateNotification(packageName,
+                    getString(R.string.uninstalling_app, pkgInfo.applicationInfo.loadLabel(pm)));
+
+            // Found package, send uninstall request.
+            pm.deletePackage(packageName, new PackageDeleteObserver(lock, startId),
+                    PackageManager.DELETE_ALL_USERS);
+
+            Log.i(TAG, "Sent delete request for " + packageName);
+        } catch (IllegalArgumentException | PackageManager.NameNotFoundException e) {
+            // Couldn't find the package, no need to call uninstall.
+            Log.w(TAG, "Could not find package, not deleting " + packageName, e);
+            finishService(lock, startId);
+        }
+    }
+
+    private boolean checkPermissions(PackageParser.Package pkg, int companionSdkVersion,
+            int companionDeviceVersion, Uri permUri, List<String> wearablePermissions,
+            File apkFile) {
+        // Assumption: We are running on Android O.
+        // If the Phone App is targeting M, all permissions may not have been granted to the phone
+        // app. If the Wear App is then not targeting M, there may be permissions that are not
+        // granted on the Phone app (by the user) right now and we cannot just grant it for the Wear
+        // app.
+        if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) {
+            // Install the app if Wear App is ready for the new perms model.
+            return true;
+        }
+
+        if (!doesWearHaveUngrantedPerms(pkg.packageName, permUri, wearablePermissions)) {
+            // All permissions requested by the watch are already granted on the phone, no need
+            // to do anything.
+            return true;
+        }
+
+        // Log an error if Wear is targeting < 23 and phone is targeting >= 23.
+        if (companionSdkVersion == 0 || companionSdkVersion >= Build.VERSION_CODES.M) {
+            Log.e(TAG, "MNC: Wear app's targetSdkVersion should be at least 23, if "
+                    + "phone app is targeting at least 23, will continue.");
+        }
+
+        return false;
+    }
+
+    /**
+     * Given a {@string packageName} corresponding to a phone app, query the provider for all the
+     * perms that are granted.
+     *
+     * @return true if the Wear App has any perms that have not been granted yet on the phone side.
+     * @return true if there is any error cases.
+     */
+    private boolean doesWearHaveUngrantedPerms(String packageName, Uri permUri,
+            List<String> wearablePermissions) {
+        if (permUri == null) {
+            Log.e(TAG, "Permission URI is null");
+            // Pretend there is an ungranted permission to avoid installing for error cases.
+            return true;
+        }
+        Cursor permCursor = getContentResolver().query(permUri, null, null, null, null);
+        if (permCursor == null) {
+            Log.e(TAG, "Could not get the cursor for the permissions");
+            // Pretend there is an ungranted permission to avoid installing for error cases.
+            return true;
+        }
+
+        Set<String> grantedPerms = new HashSet<>();
+        Set<String> ungrantedPerms = new HashSet<>();
+        while(permCursor.moveToNext()) {
+            // Make sure that the MatrixCursor returned by the ContentProvider has 2 columns and
+            // verify their types.
+            if (permCursor.getColumnCount() == 2
+                    && Cursor.FIELD_TYPE_STRING == permCursor.getType(0)
+                    && Cursor.FIELD_TYPE_INTEGER == permCursor.getType(1)) {
+                String perm = permCursor.getString(0);
+                Integer granted = permCursor.getInt(1);
+                if (granted == 1) {
+                    grantedPerms.add(perm);
+                } else {
+                    ungrantedPerms.add(perm);
+                }
+            }
+        }
+        permCursor.close();
+
+        boolean hasUngrantedPerm = false;
+        for (String wearablePerm : wearablePermissions) {
+            if (!grantedPerms.contains(wearablePerm)) {
+                hasUngrantedPerm = true;
+                if (!ungrantedPerms.contains(wearablePerm)) {
+                    // This is an error condition. This means that the wearable has permissions that
+                    // are not even declared in its host app. This is a developer error.
+                    Log.e(TAG, "Wearable " + packageName + " has a permission \"" + wearablePerm
+                            + "\" that is not defined in the host application's manifest.");
+                } else {
+                    Log.w(TAG, "Wearable " + packageName + " has a permission \"" + wearablePerm +
+                            "\" that is not granted in the host application.");
+                }
+            }
+        }
+        return hasUngrantedPerm;
+    }
+
+    /** Finishes the service after fulfilling obligation to call startForeground. */
+    private void finishServiceEarly(int startId) {
+        Pair<Integer, Notification> notifPair = buildNotification(
+                getApplicationContext().getPackageName(), "");
+        startForeground(notifPair.first, notifPair.second);
+        finishService(null, startId);
+    }
+
+    private void finishService(PowerManager.WakeLock lock, int startId) {
+        if (lock != null && lock.isHeld()) {
+            lock.release();
+        }
+        stopSelf(startId);
+    }
+
+    private synchronized PowerManager.WakeLock getLock(Context context) {
+        if (lockStatic == null) {
+            PowerManager mgr =
+                    (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+            lockStatic = mgr.newWakeLock(
+                    PowerManager.PARTIAL_WAKE_LOCK, context.getClass().getSimpleName());
+            lockStatic.setReferenceCounted(true);
+        }
+        return lockStatic;
+    }
+
+    private class PackageInstallListener implements PackageInstallerImpl.InstallListener {
+        private Context mContext;
+        private PowerManager.WakeLock mWakeLock;
+        private int mStartId;
+        private String mApplicationPackageName;
+        private PackageInstallListener(Context context, PowerManager.WakeLock wakeLock,
+                int startId, String applicationPackageName) {
+            mContext = context;
+            mWakeLock = wakeLock;
+            mStartId = startId;
+            mApplicationPackageName = applicationPackageName;
+        }
+
+        @Override
+        public void installBeginning() {
+            Log.i(TAG, "Package " + mApplicationPackageName + " is being installed.");
+        }
+
+        @Override
+        public void installSucceeded() {
+            try {
+                Log.i(TAG, "Package " + mApplicationPackageName + " was installed.");
+
+                // Delete tempFile from the file system.
+                File tempFile = WearPackageUtil.getTemporaryFile(mContext, mApplicationPackageName);
+                if (tempFile != null) {
+                    tempFile.delete();
+                }
+            } finally {
+                finishService(mWakeLock, mStartId);
+            }
+        }
+
+        @Override
+        public void installFailed(int errorCode, String errorDesc) {
+            Log.e(TAG, "Package install failed " + mApplicationPackageName
+                    + ", errorCode " + errorCode);
+            finishService(mWakeLock, mStartId);
+        }
+    }
+
+    private class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
+        private PowerManager.WakeLock mWakeLock;
+        private int mStartId;
+
+        private PackageDeleteObserver(PowerManager.WakeLock wakeLock, int startId) {
+            mWakeLock = wakeLock;
+            mStartId = startId;
+        }
+
+        public void packageDeleted(String packageName, int returnCode) {
+            try {
+                if (returnCode >= 0) {
+                    Log.i(TAG, "Package " + packageName + " was uninstalled.");
+                } else {
+                    Log.e(TAG, "Package uninstall failed " + packageName + ", returnCode " +
+                            returnCode);
+                }
+            } finally {
+                finishService(mWakeLock, mStartId);
+            }
+        }
+    }
+
+    private synchronized Pair<Integer, Notification> buildNotification(final String packageName,
+            final String title) {
+        int notifId;
+        if (mNotifIdMap.containsKey(packageName)) {
+            notifId = mNotifIdMap.get(packageName);
+        } else {
+            notifId = mInstallNotificationId++;
+            mNotifIdMap.put(packageName, notifId);
+        }
+
+        if (mNotificationChannel == null) {
+            mNotificationChannel = new NotificationChannel(WEAR_APPS_CHANNEL,
+                    getString(R.string.wear_app_channel), NotificationManager.IMPORTANCE_MIN);
+            NotificationManager notificationManager = getSystemService(NotificationManager.class);
+            notificationManager.createNotificationChannel(mNotificationChannel);
+        }
+        return new Pair<>(notifId, new Notification.Builder(this, WEAR_APPS_CHANNEL)
+            .setSmallIcon(R.drawable.ic_file_download)
+            .setContentTitle(title)
+            .build());
+    }
+
+    private void getLabelAndUpdateNotification(String packageName, String title) {
+        // Update notification since we have a label now.
+        NotificationManager notificationManager = getSystemService(NotificationManager.class);
+        Pair<Integer, Notification> notifPair = buildNotification(packageName, title);
+        notificationManager.notify(notifPair.first, notifPair.second);
+    }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageUtil.java b/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageUtil.java
new file mode 100644
index 0000000..bc740ab
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageUtil.java
@@ -0,0 +1,133 @@
+/*
+ * 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.packageinstaller.wear;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.tukaani.xz.LZMAInputStream;
+import org.tukaani.xz.XZInputStream;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class WearPackageUtil {
+    private static final String TAG = "WearablePkgInstaller";
+
+    private static final String COMPRESSION_LZMA = "lzma";
+    private static final String COMPRESSION_XZ = "xz";
+
+    public static File getTemporaryFile(Context context, String packageName) {
+        try {
+            File newFileDir = new File(context.getFilesDir(), "tmp");
+            newFileDir.mkdirs();
+            Os.chmod(newFileDir.getAbsolutePath(), 0771);
+            File newFile = new File(newFileDir, packageName + ".apk");
+            return newFile;
+        }   catch (ErrnoException e) {
+            Log.e(TAG, "Failed to open.", e);
+            return null;
+        }
+    }
+
+    public static File getIconFile(final Context context, final String packageName) {
+        try {
+            File newFileDir = new File(context.getFilesDir(), "images/icons");
+            newFileDir.mkdirs();
+            Os.chmod(newFileDir.getAbsolutePath(), 0771);
+            return new File(newFileDir, packageName + ".icon");
+        }   catch (ErrnoException e) {
+            Log.e(TAG, "Failed to open.", e);
+            return null;
+        }
+    }
+
+    /**
+     * In order to make sure that the Wearable Asset Manager has a reasonable apk that can be used
+     * by the PackageManager, we will parse it before sending it to the PackageManager.
+     * Unfortunately, PackageParser needs a file to parse. So, we have to temporarily convert the fd
+     * to a File.
+     *
+     * @param context
+     * @param fd FileDescriptor to convert to File
+     * @param packageName Name of package, will define the name of the file
+     * @param compressionAlg Can be null. For ALT mode the APK will be compressed. We will
+     *                       decompress it here
+     */
+    public static File getFileFromFd(Context context, ParcelFileDescriptor fd,
+            String packageName, String compressionAlg) {
+        File newFile = getTemporaryFile(context, packageName);
+        if (fd == null || fd.getFileDescriptor() == null)  {
+            return null;
+        }
+        InputStream fr = new ParcelFileDescriptor.AutoCloseInputStream(fd);
+        try {
+            if (TextUtils.equals(compressionAlg, COMPRESSION_XZ)) {
+                fr = new XZInputStream(fr);
+            } else if (TextUtils.equals(compressionAlg, COMPRESSION_LZMA)) {
+                fr = new LZMAInputStream(fr);
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "Compression was set to " + compressionAlg + ", but could not decode ", e);
+            return null;
+        }
+
+        int nRead;
+        byte[] data = new byte[1024];
+        try {
+            final FileOutputStream fo = new FileOutputStream(newFile);
+            while ((nRead = fr.read(data, 0, data.length)) != -1) {
+                fo.write(data, 0, nRead);
+            }
+            fo.flush();
+            fo.close();
+            Os.chmod(newFile.getAbsolutePath(), 0644);
+            return newFile;
+        } catch (IOException e) {
+            Log.e(TAG, "Reading from Asset FD or writing to temp file failed ", e);
+            return null;
+        }   catch (ErrnoException e) {
+            Log.e(TAG, "Could not set permissions on file ", e);
+            return null;
+        } finally {
+            try {
+                fr.close();
+            } catch (IOException e) {
+                Log.e(TAG, "Failed to close the file from FD ", e);
+            }
+        }
+    }
+
+    /**
+     * @return com.google.com from expected formats like
+     * Uri: package:com.google.com, package:/com.google.com, package://com.google.com
+     */
+    public static String getSanitizedPackageName(Uri packageUri) {
+        String packageName = packageUri.getEncodedSchemeSpecificPart();
+        if (packageName != null) {
+            return packageName.replaceAll("^/+", "");
+        }
+        return packageName;
+    }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java
index ef93d4a..3cfb865 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java
@@ -19,7 +19,8 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
-import androidx.core.util.Preconditions;
+
+import com.android.printservice.recommendation.util.Preconditions;
 
 import java.net.InetAddress;
 import java.util.Collections;
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/VendorConfig.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/VendorConfig.java
index 5d735a8..dece2d4 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/VendorConfig.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/VendorConfig.java
@@ -22,9 +22,9 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.core.util.Preconditions;
 
 import com.android.printservice.recommendation.R;
+import com.android.printservice.recommendation.util.Preconditions;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
index 65cef94..a6d59cb 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
@@ -24,7 +24,6 @@
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.core.util.Preconditions;
 
 import com.android.printservice.recommendation.PrintServicePlugin;
 
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/Preconditions.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/Preconditions.java
new file mode 100644
index 0000000..9bba66c
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/Preconditions.java
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printservice.recommendation.util;
+
+import android.text.TextUtils;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+
+import java.util.Collection;
+
+/**
+ * Simple static methods to be called at the start of your own methods to verify
+ * correct arguments and state.
+ */
+public class Preconditions {
+
+    public static void checkArgument(boolean expression) {
+        if (!expression) {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    /**
+     * Ensures that an expression checking an argument is true.
+     *
+     * @param expression the expression to check
+     * @param errorMessage the exception message to use if the check fails; will
+     *     be converted to a string using {@link String#valueOf(Object)}
+     * @throws IllegalArgumentException if {@code expression} is false
+     */
+    public static void checkArgument(boolean expression, final Object errorMessage) {
+        if (!expression) {
+            throw new IllegalArgumentException(String.valueOf(errorMessage));
+        }
+    }
+
+    /**
+     * Ensures that an expression checking an argument is true.
+     *
+     * @param expression the expression to check
+     * @param messageTemplate a printf-style message template to use if the check fails; will
+     *     be converted to a string using {@link String#format(String, Object...)}
+     * @param messageArgs arguments for {@code messageTemplate}
+     * @throws IllegalArgumentException if {@code expression} is false
+     */
+    public static void checkArgument(boolean expression,
+            final String messageTemplate,
+            final Object... messageArgs) {
+        if (!expression) {
+            throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
+        }
+    }
+
+    /**
+     * Ensures that an string reference passed as a parameter to the calling
+     * method is not empty.
+     *
+     * @param string an string reference
+     * @return the string reference that was validated
+     * @throws IllegalArgumentException if {@code string} is empty
+     */
+    public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string) {
+        if (TextUtils.isEmpty(string)) {
+            throw new IllegalArgumentException();
+        }
+        return string;
+    }
+
+    /**
+     * Ensures that an string reference passed as a parameter to the calling
+     * method is not empty.
+     *
+     * @param string an string reference
+     * @param errorMessage the exception message to use if the check fails; will
+     *     be converted to a string using {@link String#valueOf(Object)}
+     * @return the string reference that was validated
+     * @throws IllegalArgumentException if {@code string} is empty
+     */
+    public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string,
+            final Object errorMessage) {
+        if (TextUtils.isEmpty(string)) {
+            throw new IllegalArgumentException(String.valueOf(errorMessage));
+        }
+        return string;
+    }
+
+    /**
+     * Ensures that an object reference passed as a parameter to the calling
+     * method is not null.
+     *
+     * @param reference an object reference
+     * @return the non-null reference that was validated
+     * @throws NullPointerException if {@code reference} is null
+     */
+    public static @NonNull <T> T checkNotNull(final T reference) {
+        if (reference == null) {
+            throw new NullPointerException();
+        }
+        return reference;
+    }
+
+    /**
+     * Ensures that an object reference passed as a parameter to the calling
+     * method is not null.
+     *
+     * @param reference an object reference
+     * @param errorMessage the exception message to use if the check fails; will
+     *     be converted to a string using {@link String#valueOf(Object)}
+     * @return the non-null reference that was validated
+     * @throws NullPointerException if {@code reference} is null
+     */
+    public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
+        if (reference == null) {
+            throw new NullPointerException(String.valueOf(errorMessage));
+        }
+        return reference;
+    }
+
+    /**
+     * Ensures that an object reference passed as a parameter to the calling
+     * method is not null.
+     *
+     * @param reference an object reference
+     * @param messageTemplate a printf-style message template to use if the check fails; will
+     *     be converted to a string using {@link String#format(String, Object...)}
+     * @param messageArgs arguments for {@code messageTemplate}
+     * @return the non-null reference that was validated
+     * @throws NullPointerException if {@code reference} is null
+     */
+    public static @NonNull <T> T checkNotNull(final T reference,
+            final String messageTemplate,
+            final Object... messageArgs) {
+        if (reference == null) {
+            throw new NullPointerException(String.format(messageTemplate, messageArgs));
+        }
+        return reference;
+    }
+
+    /**
+     * Ensures the truth of an expression involving the state of the calling
+     * instance, but not involving any parameters to the calling method.
+     *
+     * @param expression a boolean expression
+     * @param message exception message
+     * @throws IllegalStateException if {@code expression} is false
+     */
+    public static void checkState(final boolean expression, String message) {
+        if (!expression) {
+            throw new IllegalStateException(message);
+        }
+    }
+
+    /**
+     * Ensures the truth of an expression involving the state of the calling
+     * instance, but not involving any parameters to the calling method.
+     *
+     * @param expression a boolean expression
+     * @throws IllegalStateException if {@code expression} is false
+     */
+    public static void checkState(final boolean expression) {
+        checkState(expression, null);
+    }
+
+    /**
+     * Check the requested flags, throwing if any requested flags are outside
+     * the allowed set.
+     *
+     * @return the validated requested flags.
+     */
+    public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
+        if ((requestedFlags & allowedFlags) != requestedFlags) {
+            throw new IllegalArgumentException("Requested flags 0x"
+                    + Integer.toHexString(requestedFlags) + ", but only 0x"
+                    + Integer.toHexString(allowedFlags) + " are allowed");
+        }
+
+        return requestedFlags;
+    }
+
+    /**
+     * Ensures that that the argument numeric value is non-negative.
+     *
+     * @param value a numeric int value
+     * @param errorMessage the exception message to use if the check fails
+     * @return the validated numeric value
+     * @throws IllegalArgumentException if {@code value} was negative
+     */
+    public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
+            final String errorMessage) {
+        if (value < 0) {
+            throw new IllegalArgumentException(errorMessage);
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that that the argument numeric value is non-negative.
+     *
+     * @param value a numeric int value
+     *
+     * @return the validated numeric value
+     * @throws IllegalArgumentException if {@code value} was negative
+     */
+    public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) {
+        if (value < 0) {
+            throw new IllegalArgumentException();
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that that the argument numeric value is non-negative.
+     *
+     * @param value a numeric long value
+     * @return the validated numeric value
+     * @throws IllegalArgumentException if {@code value} was negative
+     */
+    public static long checkArgumentNonnegative(final long value) {
+        if (value < 0) {
+            throw new IllegalArgumentException();
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that that the argument numeric value is non-negative.
+     *
+     * @param value a numeric long value
+     * @param errorMessage the exception message to use if the check fails
+     * @return the validated numeric value
+     * @throws IllegalArgumentException if {@code value} was negative
+     */
+    public static long checkArgumentNonnegative(final long value, final String errorMessage) {
+        if (value < 0) {
+            throw new IllegalArgumentException(errorMessage);
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that that the argument numeric value is positive.
+     *
+     * @param value a numeric int value
+     * @param errorMessage the exception message to use if the check fails
+     * @return the validated numeric value
+     * @throws IllegalArgumentException if {@code value} was not positive
+     */
+    public static int checkArgumentPositive(final int value, final String errorMessage) {
+        if (value <= 0) {
+            throw new IllegalArgumentException(errorMessage);
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the argument floating point value is a finite number.
+     *
+     * <p>A finite number is defined to be both representable (that is, not NaN) and
+     * not infinite (that is neither positive or negative infinity).</p>
+     *
+     * @param value a floating point value
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated floating point value
+     *
+     * @throws IllegalArgumentException if {@code value} was not finite
+     */
+    public static float checkArgumentFinite(final float value, final String valueName) {
+        if (Float.isNaN(value)) {
+            throw new IllegalArgumentException(valueName + " must not be NaN");
+        } else if (Float.isInfinite(value)) {
+            throw new IllegalArgumentException(valueName + " must not be infinite");
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the argument floating point value is within the inclusive range.
+     *
+     * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
+     * will always be out of range.</p>
+     *
+     * @param value a floating point value
+     * @param lower the lower endpoint of the inclusive range
+     * @param upper the upper endpoint of the inclusive range
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated floating point value
+     *
+     * @throws IllegalArgumentException if {@code value} was not within the range
+     */
+    public static float checkArgumentInRange(float value, float lower, float upper,
+            String valueName) {
+        if (Float.isNaN(value)) {
+            throw new IllegalArgumentException(valueName + " must not be NaN");
+        } else if (value < lower) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
+        } else if (value > upper) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the argument int value is within the inclusive range.
+     *
+     * @param value a int value
+     * @param lower the lower endpoint of the inclusive range
+     * @param upper the upper endpoint of the inclusive range
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated int value
+     *
+     * @throws IllegalArgumentException if {@code value} was not within the range
+     */
+    public static int checkArgumentInRange(int value, int lower, int upper,
+            String valueName) {
+        if (value < lower) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
+        } else if (value > upper) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the argument long value is within the inclusive range.
+     *
+     * @param value a long value
+     * @param lower the lower endpoint of the inclusive range
+     * @param upper the upper endpoint of the inclusive range
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated long value
+     *
+     * @throws IllegalArgumentException if {@code value} was not within the range
+     */
+    public static long checkArgumentInRange(long value, long lower, long upper,
+            String valueName) {
+        if (value < lower) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
+        } else if (value > upper) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
+     *
+     * @param value an array of boxed objects
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated array
+     *
+     * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
+     */
+    public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
+        if (value == null) {
+            throw new NullPointerException(valueName + " must not be null");
+        }
+
+        for (int i = 0; i < value.length; ++i) {
+            if (value[i] == null) {
+                throw new NullPointerException(
+                        String.format("%s[%d] must not be null", valueName, i));
+            }
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
+     * {@code null}.
+     *
+     * @param value a {@link Collection} of boxed objects
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated {@link Collection}
+     *
+     * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
+     */
+    public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
+            final C value, final String valueName) {
+        if (value == null) {
+            throw new NullPointerException(valueName + " must not be null");
+        }
+
+        long ctr = 0;
+        for (T elem : value) {
+            if (elem == null) {
+                throw new NullPointerException(
+                        String.format("%s[%d] must not be null", valueName, ctr));
+            }
+            ++ctr;
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
+     *
+     * @param value a {@link Collection} of boxed elements.
+     * @param valueName the name of the argument to use if the check fails.
+
+     * @return the validated {@link Collection}
+     *
+     * @throws NullPointerException if the {@code value} was {@code null}
+     * @throws IllegalArgumentException if the {@code value} was empty
+     */
+    public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
+            final String valueName) {
+        if (value == null) {
+            throw new NullPointerException(valueName + " must not be null");
+        }
+        if (value.isEmpty()) {
+            throw new IllegalArgumentException(valueName + " is empty");
+        }
+        return value;
+    }
+
+    /**
+     * Ensures that all elements in the argument floating point array are within the inclusive range
+     *
+     * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
+     * will always be out of range.</p>
+     *
+     * @param value a floating point array of values
+     * @param lower the lower endpoint of the inclusive range
+     * @param upper the upper endpoint of the inclusive range
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated floating point value
+     *
+     * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
+     * @throws NullPointerException if the {@code value} was {@code null}
+     */
+    public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
+            String valueName) {
+        checkNotNull(value, valueName + " must not be null");
+
+        for (int i = 0; i < value.length; ++i) {
+            float v = value[i];
+
+            if (Float.isNaN(v)) {
+                throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
+            } else if (v < lower) {
+                throw new IllegalArgumentException(
+                        String.format("%s[%d] is out of range of [%f, %f] (too low)",
+                                valueName, i, lower, upper));
+            } else if (v > upper) {
+                throw new IllegalArgumentException(
+                        String.format("%s[%d] is out of range of [%f, %f] (too high)",
+                                valueName, i, lower, upper));
+            }
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that all elements in the argument integer array are within the inclusive range
+     *
+     * @param value an integer array of values
+     * @param lower the lower endpoint of the inclusive range
+     * @param upper the upper endpoint of the inclusive range
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated integer array
+     *
+     * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
+     * @throws NullPointerException if the {@code value} was {@code null}
+     */
+    public static int[] checkArrayElementsInRange(int[] value, int lower, int upper,
+            String valueName) {
+        checkNotNull(value, valueName + " must not be null");
+
+        for (int i = 0; i < value.length; ++i) {
+            int v = value[i];
+
+            if (v < lower) {
+                throw new IllegalArgumentException(
+                        String.format("%s[%d] is out of range of [%d, %d] (too low)",
+                                valueName, i, lower, upper));
+            } else if (v > upper) {
+                throw new IllegalArgumentException(
+                        String.format("%s[%d] is out of range of [%d, %d] (too high)",
+                                valueName, i, lower, upper));
+            }
+        }
+
+        return value;
+    }
+}
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less.png
deleted file mode 100644
index b6a5eb5..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more.png
deleted file mode 100644
index 4e36bd2..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_grayedout_printer.png b/packages/PrintSpooler/res/drawable-hdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_restart.png b/packages/PrintSpooler/res/drawable-hdpi/ic_restart.png
deleted file mode 100644
index bb9d855..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_restart.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/stat_notify_cancelling.png b/packages/PrintSpooler/res/drawable-hdpi/stat_notify_cancelling.png
deleted file mode 100644
index 2757db0..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/stat_notify_cancelling.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less.png
deleted file mode 100644
index 428a946..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less_24dp.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less_24dp.png
deleted file mode 100644
index 3220eea..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more.png
deleted file mode 100644
index fbbd094..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more_24dp.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more_24dp.png
deleted file mode 100644
index 5530f52..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_grayedout_printer.png b/packages/PrintSpooler/res/drawable-mdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_restart.png b/packages/PrintSpooler/res/drawable-mdpi/ic_restart.png
deleted file mode 100644
index bd611e8..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_restart.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/stat_notify_cancelling.png b/packages/PrintSpooler/res/drawable-mdpi/stat_notify_cancelling.png
deleted file mode 100644
index c1b380a..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/stat_notify_cancelling.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less.png
deleted file mode 100644
index 6161c20..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more.png
deleted file mode 100644
index 3a89805..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_grayedout_printer.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_restart.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_restart.png
deleted file mode 100644
index a7fdc0d..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_restart.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/stat_notify_cancelling.png b/packages/PrintSpooler/res/drawable-xhdpi/stat_notify_cancelling.png
deleted file mode 100644
index fedc00e..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/stat_notify_cancelling.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less.png
deleted file mode 100644
index 52a52d9..0000000
--- a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more.png
deleted file mode 100644
index 15e6abd..0000000
--- a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less.png
deleted file mode 100644
index 46811a1..0000000
--- a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more.png
deleted file mode 100644
index 141f28b..0000000
--- a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable/ic_clear.xml b/packages/PrintSpooler/res/drawable/ic_clear.xml
new file mode 100644
index 0000000..076e8ef
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable/ic_clear.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<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:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"
+        android:fillColor="?android:colorForeground"/>
+</vector>
diff --git a/packages/PrintSpooler/res/drawable/ic_expand_less.xml b/packages/PrintSpooler/res/drawable/ic_expand_less.xml
index 6f1ece1..c3e87dc 100644
--- a/packages/PrintSpooler/res/drawable/ic_expand_less.xml
+++ b/packages/PrintSpooler/res/drawable/ic_expand_less.xml
@@ -1,43 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+  Copyright (C) 2018 The Android Open Source Project
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
 
-          http://www.apache.org/licenses/LICENSE-2.0
+       http://www.apache.org/licenses/LICENSE-2.0
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:autoMirrored="true">
-
-    <item
-        android:state_checked="true">
-        <bitmap
-            android:src="@drawable/ic_expand_less"
-            android:tint="?android:attr/colorControlActivated">
-        </bitmap>
-    </item>
-
-    <item
-        android:state_pressed="true">
-        <bitmap
-            android:src="@drawable/ic_expand_less"
-            android:tint="?android:attr/colorControlActivated">
-        </bitmap>
-    </item>
-
-    <item>
-        <bitmap
-            android:src="@drawable/ic_expand_less"
-            android:tint="?android:attr/colorControlNormal">
-        </bitmap>
-    </item>
-
-</selector>
+<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:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"
+        android:fillColor="?android:colorForeground" />
+</vector>
\ No newline at end of file
diff --git a/packages/PrintSpooler/res/drawable/ic_expand_more.xml b/packages/PrintSpooler/res/drawable/ic_expand_more.xml
index 8d71452..3895144 100644
--- a/packages/PrintSpooler/res/drawable/ic_expand_more.xml
+++ b/packages/PrintSpooler/res/drawable/ic_expand_more.xml
@@ -1,43 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+  Copyright (C) 2018 The Android Open Source Project
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
 
-          http://www.apache.org/licenses/LICENSE-2.0
+       http://www.apache.org/licenses/LICENSE-2.0
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:autoMirrored="true">
-
-    <item
-        android:state_checked="true">
-        <bitmap
-            android:src="@drawable/ic_expand_more"
-            android:tint="?android:attr/colorControlActivated">
-        </bitmap>
-    </item>
-
-    <item
-        android:state_pressed="true">
-        <bitmap
-            android:src="@drawable/ic_expand_more"
-            android:tint="?android:attr/colorControlActivated">
-        </bitmap>
-    </item>
-
-    <item>
-        <bitmap
-            android:src="@drawable/ic_expand_more"
-            android:tint="?android:attr/colorControlNormal">
-        </bitmap>
-    </item>
-
-</selector>
+<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:pathData="M7.41,8.59L12,13.17l4.59,-4.58L18,10l-6,6l-6,-6L7.41,8.59z"
+        android:fillColor="?android:colorForeground" />
+</vector>
\ No newline at end of file
diff --git a/packages/PrintSpooler/res/drawable/print_warning.xml b/packages/PrintSpooler/res/drawable/print_warning.xml
deleted file mode 100644
index 35f0fed..0000000
--- a/packages/PrintSpooler/res/drawable/print_warning.xml
+++ /dev/null
@@ -1,25 +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.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="96dp"
-        android:height="96dp"
-        android:viewportWidth="96.0"
-        android:viewportHeight="96.0">
-    <path
-        android:fillColor="#C8CCCE"
-        android:pathData="M4,84H92L48,8 4,84zM52,72h-8v-8h8v8zM52,56H44V40h8v16z"/>
-</vector>
diff --git a/packages/PrintSpooler/res/layout/preview_page.xml b/packages/PrintSpooler/res/layout/preview_page.xml
index aafdd8f..8db347e 100644
--- a/packages/PrintSpooler/res/layout/preview_page.xml
+++ b/packages/PrintSpooler/res/layout/preview_page.xml
@@ -44,7 +44,7 @@
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorPrimary">
+            android:textColor="@android:color/white">
         </TextView>
 
         <ImageView
diff --git a/packages/PrintSpooler/res/layout/preview_page_error.xml b/packages/PrintSpooler/res/layout/preview_page_error.xml
index 4e9fb77..99ab99d 100644
--- a/packages/PrintSpooler/res/layout/preview_page_error.xml
+++ b/packages/PrintSpooler/res/layout/preview_page_error.xml
@@ -21,11 +21,14 @@
         android:gravity="center">
 
     <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="12dip"
-            android:src="@drawable/print_warning"
-            android:contentDescription="@null" />
+        android:layout_width="120dp"
+        android:layout_height="110dp"
+        android:layout_marginBottom="12dip"
+        android:src="@*android:drawable/ic_print_error"
+        android:scaleType="fitEnd"
+        android:alpha="0.1"
+        android:tint="@android:color/black"
+        android:importantForAccessibility="no" />
 
     <TextView
             android:layout_width="wrap_content"
diff --git a/packages/PrintSpooler/res/layout/preview_page_loading.xml b/packages/PrintSpooler/res/layout/preview_page_loading.xml
index 1af3a17..918edd9 100644
--- a/packages/PrintSpooler/res/layout/preview_page_loading.xml
+++ b/packages/PrintSpooler/res/layout/preview_page_loading.xml
@@ -19,14 +19,13 @@
     android:layout_height="fill_parent">
 
     <ImageView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_margin="36dip"
+        android:layout_width="120dp"
+        android:layout_height="110dp"
         android:layout_gravity="center"
-        android:src="@drawable/ic_grayedout_printer"
-        android:contentDescription="@null"
-        android:scaleType="centerInside"
-        android:adjustViewBounds="true">
-    </ImageView>
+        android:src="@*android:drawable/ic_print"
+        android:scaleType="fitCenter"
+        android:alpha="0.1"
+        android:tint="@android:color/black"
+        android:importantForAccessibility="no" />
 
 </FrameLayout>
diff --git a/packages/PrintSpooler/res/layout/preview_page_selected.xml b/packages/PrintSpooler/res/layout/preview_page_selected.xml
index 77f4727..6727142 100644
--- a/packages/PrintSpooler/res/layout/preview_page_selected.xml
+++ b/packages/PrintSpooler/res/layout/preview_page_selected.xml
@@ -42,7 +42,7 @@
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorPrimary">
+            android:textColor="@android:color/white">
         </TextView>
 
         <ImageView
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index 774f320..212f398 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -29,7 +29,7 @@
         android:paddingStart="8dip"
         android:layout_marginEnd="16dp"
         android:elevation="@dimen/preview_controls_elevation"
-        android:background="?android:attr/colorPrimary">
+        style="?android:actionBarStyle">
 
         <com.android.printspooler.widget.ClickInterceptSpinner
             android:id="@+id/destination_spinner"
@@ -55,7 +55,7 @@
         android:paddingBottom="8dip"
         android:orientation="horizontal"
         android:elevation="@dimen/preview_controls_elevation"
-        android:background="?android:attr/colorPrimary">
+        style="?android:actionBarStyle">
 
         <TextView
             android:layout_width="wrap_content"
@@ -121,7 +121,6 @@
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
         android:animateLayoutChanges="true"
-        android:background="@color/print_preview_background_color"
         android:gravity="center">
 
         <!-- Error message added here -->
diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml
index 69d4f91..3aafc99 100644
--- a/packages/PrintSpooler/res/layout/print_activity_controls.xml
+++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml
@@ -22,7 +22,7 @@
     android:layout_height="wrap_content"
     android:orientation="vertical"
     android:elevation="@dimen/preview_controls_elevation"
-    android:background="?android:attr/colorPrimary">
+    style="?android:actionBarStyle">
 
     <LinearLayout
         android:id="@+id/draggable_content"
diff --git a/packages/PrintSpooler/res/layout/print_error_fragment.xml b/packages/PrintSpooler/res/layout/print_error_fragment.xml
index 3ea2abd..9d9dd01 100644
--- a/packages/PrintSpooler/res/layout/print_error_fragment.xml
+++ b/packages/PrintSpooler/res/layout/print_error_fragment.xml
@@ -16,35 +16,39 @@
  -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_marginStart="16dip"
+    android:layout_marginEnd="16dip"
     android:gravity="center"
     android:orientation="vertical">
 
     <ImageView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="12dip"
-        android:src="@drawable/ic_grayedout_printer"
-        android:contentDescription="@null">
-    </ImageView>
+        android:layout_width="120dp"
+        android:layout_height="110dp"
+        android:layout_marginBottom="12dp"
+        android:src="@*android:drawable/ic_print_error"
+        android:scaleType="fitEnd"
+        android:alpha="0.1"
+        android:tint="?android:colorForeground"
+        android:importantForAccessibility="no" />
 
     <TextView
         android:id="@+id/message"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginStart="16dip"
-        android:layout_marginEnd="16dip"
-        android:gravity="center_horizontal"
-        android:text="@string/print_error_default_message"
-        android:textAppearance="?android:attr/textAppearanceLargeInverse">
-    </TextView>
+        android:layout_marginBottom="16dp"
+        android:gravity="center"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:textColor="?android:attr/textColorSecondary"
+        android:text="@string/print_error_default_message" />
 
     <Button
         android:id="@+id/action_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="@string/print_error_retry">
-    </Button>
+        style="?android:attr/borderlessButtonStyle"
+        android:textColor="?android:attr/textColorSecondary"
+        android:text="@string/print_add_printer" />
 
 </LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/print_progress_fragment.xml b/packages/PrintSpooler/res/layout/print_progress_fragment.xml
index 3b010f8..89071605 100644
--- a/packages/PrintSpooler/res/layout/print_progress_fragment.xml
+++ b/packages/PrintSpooler/res/layout/print_progress_fragment.xml
@@ -15,34 +15,39 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_marginStart="16dp"
+    android:layout_marginEnd="16dp"
     android:gravity="center"
     android:orientation="vertical">
 
     <ImageView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="12dip"
-        android:src="@drawable/ic_grayedout_printer"
-        android:contentDescription="@null">
-    </ImageView>
-
-    <ProgressBar
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:indeterminate="true"
-        style="?android:attr/progressBarStyleHorizontal">
-    </ProgressBar>
+        android:layout_width="120dp"
+        android:layout_height="110dp"
+        android:layout_marginBottom="12dp"
+        android:src="@*android:drawable/ic_print"
+        android:scaleType="fitEnd"
+        android:alpha="0.1"
+        android:tint="?android:colorForeground"
+        android:importantForAccessibility="no" />
 
     <TextView
         android:id="@+id/message"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceLargeInverse"
-        android:text="@string/print_preparing_preview">
-    </TextView>
+        android:layout_marginBottom="16dp"
+        android:gravity="center"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:textColor="?android:attr/textColorSecondary"
+        android:text="@string/print_preparing_preview" />
+
+    <ProgressBar
+        android:layout_width="300dp"
+        android:layout_height="wrap_content"
+        android:indeterminate="true"
+        android:importantForAccessibility="no"
+        style="?android:attr/progressBarStyleHorizontal" />
 
 </LinearLayout>
 
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
index 91beff6..681924b 100644
--- a/packages/PrintSpooler/res/layout/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -31,45 +31,48 @@
         android:visibility="gone">
 
         <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginStart="16dp"
+            android:layout_marginEnd="16dp"
             android:gravity="center"
             android:orientation="vertical">
 
             <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginBottom="12dip"
-                android:src="@*android:drawable/ic_grayedout_printer"
-                android:importantForAccessibility="no">
-            </ImageView>
+                android:layout_width="120dp"
+                android:layout_height="110dp"
+                android:layout_marginBottom="12dp"
+                android:src="@*android:drawable/ic_print"
+                android:scaleType="fitEnd"
+                android:alpha="0.1"
+                android:tint="?android:colorForeground"
+                android:importantForAccessibility="no" />
 
             <TextView
                 android:id="@+id/title"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:layout_marginBottom="16dp"
+                android:gravity="center"
                 android:textAppearance="?android:attr/textAppearanceLarge"
                 android:textColor="?android:attr/textColorSecondary"
-                android:text="@string/print_searching_for_printers">
-            </TextView>
+                android:text="@string/print_searching_for_printers" />
 
             <ProgressBar
                 android:id="@+id/progress_bar"
-                android:layout_width="fill_parent"
+                android:layout_width="300dp"
                 android:layout_height="wrap_content"
                 android:indeterminate="true"
-                style="?android:attr/progressBarStyleHorizontal">
-            </ProgressBar>
+                android:importantForAccessibility="no"
+                style="?android:attr/progressBarStyleHorizontal" />
 
             <Button
-                    android:id="@+id/button"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    style="?android:attr/buttonBarButtonStyle"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:text="@string/print_add_printer"
-                    android:textAllCaps="true" />
+                android:id="@+id/button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="?android:attr/borderlessButtonStyle"
+                android:textColor="?android:attr/textColorSecondary"
+                android:text="@string/print_add_printer" />
 
         </LinearLayout>
 
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index 779d19b..807426b 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -111,7 +111,7 @@
     <item msgid="3199660090246166812">"أفقي"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"تعذرت الكتابة إلى الملف"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"عذرًا، هذا لا يعمل. أعد المحاولة."</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"تعذّرت عملية الطباعة. يُرجى إعادة المحاولة."</string>
     <string name="print_error_retry" msgid="1426421728784259538">"إعادة المحاولة"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"الطابعة ليست متوفرة في الوقت الحالي."</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"يتعذر عرض المعاينة."</string>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index d44b4ce..d05d96f 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -103,7 +103,7 @@
     <item msgid="3199660090246166812">"Хоризонтално"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"Не можа да се запише във файла"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"За съжаление това не проработи. Опитайте отново."</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"За съжаление, това не проработи. Опитайте отново."</string>
     <string name="print_error_retry" msgid="1426421728784259538">"Нов опит"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"В момента този принтер не е налице."</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"Визуализацията не може да се покаже"</string>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index f88a453..fa59d99 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -32,7 +32,7 @@
     <string name="template_page_range" msgid="428638530038286328">"Interval på <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"f.eks. 1-5,8,11-13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Vis udskrift"</string>
-    <string name="install_for_print_preview" msgid="6366303997385509332">"Installer et PDF-visningsprog. for at se eksempel"</string>
+    <string name="install_for_print_preview" msgid="6366303997385509332">"Installer et PDF-visningsprog. for at se en forhåndsvisning"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"Udskrivningsapp gik ned"</string>
     <string name="generating_print_job" msgid="3119608742651698916">"Udskriften generes"</string>
     <string name="save_as_pdf" msgid="5718454119847596853">"Gem som PDF"</string>
@@ -106,6 +106,6 @@
     <string name="print_error_default_message" msgid="8602678405502922346">"Det virkede desværre ikke. Prøv igen."</string>
     <string name="print_error_retry" msgid="1426421728784259538">"Prøv igen"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Denne printer er i øjeblikket ikke tilgængelig."</string>
-    <string name="print_cannot_load_page" msgid="6179560924492912009">"Eksempelvisning kan ikke vises"</string>
-    <string name="print_preparing_preview" msgid="3939930735671364712">"Eksempelvisning forberedes..."</string>
+    <string name="print_cannot_load_page" msgid="6179560924492912009">"Forhåndsvisning kan ikke vises"</string>
+    <string name="print_preparing_preview" msgid="3939930735671364712">"Forhåndsvisning klargøres..."</string>
 </resources>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index b9a0d9d..c1caf91 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -103,7 +103,7 @@
     <item msgid="3199660090246166812">"Fekvő"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"Nem sikerült írni a fájlba"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"Sajnáljuk, de nem sikerült. Próbálja újra."</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"Sajnáljuk, de nem sikerült. Próbáld újra."</string>
     <string name="print_error_retry" msgid="1426421728784259538">"Újra"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Ez a nyomtató jelenleg nem érhető el."</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"Nem lehet megjeleníteni az előnézetet"</string>
diff --git a/packages/PrintSpooler/res/values-ml/strings.xml b/packages/PrintSpooler/res/values-ml/strings.xml
index 05be7a7..dbcd34b 100644
--- a/packages/PrintSpooler/res/values-ml/strings.xml
+++ b/packages/PrintSpooler/res/values-ml/strings.xml
@@ -35,7 +35,7 @@
     <string name="install_for_print_preview" msgid="6366303997385509332">"പ്രിവ്യൂ കാണിക്കുന്നതിന് PDF വ്യൂവർ ഇൻസ്റ്റാൾ ചെയ്യുക"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"പ്രിന്റുചെയ്യൽ അപ്ലിക്കേഷൻ ക്രാഷായി"</string>
     <string name="generating_print_job" msgid="3119608742651698916">"പ്രിന്റ് ജോലി സൃഷ്‌ടിക്കുന്നു"</string>
-    <string name="save_as_pdf" msgid="5718454119847596853">"PDF ആയി സംരക്ഷിക്കുക"</string>
+    <string name="save_as_pdf" msgid="5718454119847596853">"PDF-ആയി സംരക്ഷിക്കൂ"</string>
     <string name="all_printers" msgid="5018829726861876202">"എല്ലാ പ്രിന്ററുകളും..."</string>
     <string name="print_dialog" msgid="32628687461331979">"പ്രിന്റ് സംഭാഷണം"</string>
     <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-my/strings.xml b/packages/PrintSpooler/res/values-my/strings.xml
index 8ce23e0..96ed754 100644
--- a/packages/PrintSpooler/res/values-my/strings.xml
+++ b/packages/PrintSpooler/res/values-my/strings.xml
@@ -20,7 +20,7 @@
     <string name="more_options_button" msgid="2243228396432556771">"နောက်ထပ် ရွေးစရာများ"</string>
     <string name="label_destination" msgid="9132510997381599275">"ဦးတည်ရာ"</string>
     <string name="label_copies" msgid="3634531042822968308">"မိတ္တူများ"</string>
-    <string name="label_copies_summary" msgid="3861966063536529540">"မိတ္တူများ:"</string>
+    <string name="label_copies_summary" msgid="3861966063536529540">"မိတ္တူများ-"</string>
     <string name="label_paper_size" msgid="908654383827777759">"စက္ကူ  ဆိုက်"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"စက္ကူ  ဆိုက်:"</string>
     <string name="label_color" msgid="1108690305218188969">"ရောင်စုံ"</string>
@@ -35,7 +35,7 @@
     <string name="install_for_print_preview" msgid="6366303997385509332">"အစမ်းကြည့်ရန် ပီဒီအက်ဖ် ဖတ်ရှုစရာ ထည့်သွင်းပါ"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"စာထုတ်လုပ်သော အက်ပ်ခဏ ပျက်သွားပါသည်"</string>
     <string name="generating_print_job" msgid="3119608742651698916">"စာထုတ်အလုပ်ကို လုပ်နေပါသည်"</string>
-    <string name="save_as_pdf" msgid="5718454119847596853">"ပီဒီအက်ဖ် အဖြစ်သိမ်းဆည်းရန်"</string>
+    <string name="save_as_pdf" msgid="5718454119847596853">"PDF အဖြစ်သိမ်းရန်"</string>
     <string name="all_printers" msgid="5018829726861876202">"စာထုတ်စက် အားလုံး"</string>
     <string name="print_dialog" msgid="32628687461331979">"စာထုတ်ရန် အချက်ပြခြင်း"</string>
     <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
@@ -103,8 +103,8 @@
     <item msgid="3199660090246166812">"အလျားလိုက်"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"ဖိုင်သို့ မရေးနိုင်ခဲ့"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"ဆော်ရီး၊ အဲဒါ အလုပ်မဖြစ်ခဲ့ပါ။ ထပ် စမ်းပါ။"</string>
-    <string name="print_error_retry" msgid="1426421728784259538">"ထပ်စမ်း"</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"လုပ်၍မရခဲ့ပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
+    <string name="print_error_retry" msgid="1426421728784259538">"ထပ်စမ်းကြည့်ရန်"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"ဒီပရင်တာမှာ ယခုအချိန်မှာ မရနိုင်ပါ။"</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"အစမ်းကြည့်ခြင်းကို ပြသ၍မရပါ"</string>
     <string name="print_preparing_preview" msgid="3939930735671364712">"အစမ်းကြည့်ရန် ပြင်ဆင်နေ…"</string>
diff --git a/packages/PrintSpooler/res/values-night/themes.xml b/packages/PrintSpooler/res/values-night/themes.xml
new file mode 100644
index 0000000..4428dbb
--- /dev/null
+++ b/packages/PrintSpooler/res/values-night/themes.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <style name="Theme.AddPrinterActivity" parent="@android:style/Theme.DeviceDefault.Dialog">
+        <item name="android:listSeparatorTextViewStyle">@style/ListSeparator</item>
+        <item name="android:textAppearanceListItemSecondary">@style/ListItemSecondary</item>
+    </style>
+
+    <style name="Theme.SelectPrinterActivity"
+           parent="android:style/Theme.DeviceDefault">
+        <item name="android:textAppearanceListItemSecondary">@style/ListItemSecondary</item>
+    </style>
+
+    <style name="Theme.PrintActivity" parent="@android:style/Theme.DeviceDefault">
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowActionBar">false</item>
+        <item name="android:windowNoTitle">true</item>
+    </style>
+
+</resources>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 5da31bd..1c128b4 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -103,7 +103,7 @@
     <item msgid="3199660090246166812">"Horizontal"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"Não foi possível gravar no ficheiro"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"Lamentamos, mas isso não funcionou. Tente novam."</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"Lamentamos, mas isso não funcionou. Tente novamente."</string>
     <string name="print_error_retry" msgid="1426421728784259538">"Tentar novamente"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Esta impressora não está atualmente disponível."</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"Não é possível apresentar a pré-visualização"</string>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 17a029a..184f4d8 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -107,7 +107,7 @@
     <item msgid="3199660090246166812">"Na šírku"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"Do súboru nie je možné zapisovať"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"Je nám to ľúto, nefungovalo to. Skúste to znova."</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"Ľutujeme, nepodarilo sa. Skúste to znova."</string>
     <string name="print_error_retry" msgid="1426421728784259538">"Opakovať"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Táto tlačiareň nie je momentálne k dispozícii."</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"Ukážka sa nedá zobraziť"</string>
diff --git a/packages/PrintSpooler/res/values-uz/strings.xml b/packages/PrintSpooler/res/values-uz/strings.xml
index 8921f8e..7552938 100644
--- a/packages/PrintSpooler/res/values-uz/strings.xml
+++ b/packages/PrintSpooler/res/values-uz/strings.xml
@@ -103,7 +103,7 @@
     <item msgid="3199660090246166812">"Eniga"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"Faylga yozib bo‘lmadi"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"Kechirasiz, ishlamadi. Qayta urinib ko‘ring."</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"Xatolik yuz berdi. Qaytadan urining."</string>
     <string name="print_error_retry" msgid="1426421728784259538">"Qayta urinish"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Ushbu printer hozirda mavjud emas."</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"Oldindan ko‘rsatib bo‘lmaydi"</string>
diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml
index 68bc6f2..cb9e886 100644
--- a/packages/PrintSpooler/res/values/colors.xml
+++ b/packages/PrintSpooler/res/values/colors.xml
@@ -18,8 +18,6 @@
 
     <color name="print_preview_scrim_color">#99000000</color>
 
-    <color name="print_preview_background_color">#F2F1F2</color>
-
     <color name="unselected_page_background_color">#C0C0C0</color>
 
     <color name="material_grey_500">#ffa3a3a3</color>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index a968ffa..844e9c9 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -21,17 +21,14 @@
     </style>
 
     <style name="Theme.SelectPrinterActivity"
-           parent="android:style/Theme.DeviceDefault.Light.DarkActionBar">
+           parent="android:style/Theme.DeviceDefault.Light">
         <item name="android:textAppearanceListItemSecondary">@style/ListItemSecondary</item>
     </style>
 
-    <style name="Theme.PrintActivity" parent="@android:style/Theme.DeviceDefault">
+    <style name="Theme.PrintActivity" parent="@android:style/Theme.DeviceDefault.Light">
         <item name="android:windowIsTranslucent">true</item>
-        <item name="android:windowBackground">@android:color/transparent</item>
-        <item name="android:windowContentOverlay">@null</item>
         <item name="android:windowActionBar">false</item>
         <item name="android:windowNoTitle">true</item>
-        <item name="android:backgroundDimEnabled">false</item>
     </style>
 
 </resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
index 9d737e0..abdfad5 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
@@ -166,7 +166,7 @@
      */
     private Action createCancelAction(PrintJobInfo printJob) {
         return new Action.Builder(
-                Icon.createWithResource(mContext, R.drawable.stat_notify_cancelling),
+                Icon.createWithResource(mContext, R.drawable.ic_clear),
                 mContext.getString(R.string.cancel), createCancelIntent(printJob)).build();
     }
 
@@ -225,7 +225,7 @@
 
     private void createFailedNotification(PrintJobInfo printJob) {
         Action.Builder restartActionBuilder = new Action.Builder(
-                Icon.createWithResource(mContext, R.drawable.ic_restart),
+                Icon.createWithResource(mContext, com.android.internal.R.drawable.ic_restart),
                 mContext.getString(R.string.restart), createRestartIntent(printJob.getId()));
 
         createNotification(printJob, createCancelAction(printJob), restartActionBuilder.build());
@@ -317,7 +317,7 @@
                 if (!printJob.isCancelling()) {
                     return com.android.internal.R.drawable.ic_print;
                 } else {
-                    return R.drawable.stat_notify_cancelling;
+                    return R.drawable.ic_clear;
                 }
             }
         }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 06fbf9f..59f272f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -297,7 +297,7 @@
                     + " cannot be null");
         }
 
-        mCallingPackageName = extras.getString(DocumentsContract.EXTRA_PACKAGE_NAME);
+        mCallingPackageName = extras.getString(Intent.EXTRA_PACKAGE_NAME);
 
         if (savedInstanceState == null) {
             MetricsLogger.action(this, MetricsEvent.PRINT_PREVIEW, mCallingPackageName);
@@ -715,7 +715,7 @@
         Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
         intent.setType("application/pdf");
         intent.putExtra(Intent.EXTRA_TITLE, info.getName());
-        intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, mCallingPackageName);
+        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mCallingPackageName);
 
         try {
             startActivityForResult(intent, ACTIVITY_REQUEST_CREATE_FILE);
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
new file mode 100644
index 0000000..4791517
--- /dev/null
+++ b/packages/SettingsLib/Android.bp
@@ -0,0 +1,25 @@
+android_library {
+
+    name: "SettingsLib",
+
+    libs: [
+        "androidx.annotation_annotation",
+        "androidx.legacy_legacy-support-v4",
+        "androidx.recyclerview_recyclerview",
+        "androidx.preference_preference",
+        "androidx.appcompat_appcompat",
+        "androidx.lifecycle_lifecycle-runtime",
+    ],
+
+    // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES
+    // LOCAL_SHARED_JAVA_LIBRARIES := androidx.lifecycle_lifecycle-common
+
+    resource_dirs: ["res"],
+
+    srcs: ["src/**/*.java"],
+
+    min_sdk_version: "21",
+
+}
+
+// For the test package.
diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk
deleted file mode 100644
index 96012c1..0000000
--- a/packages/SettingsLib/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_AAPT2_ONLY := true
-
-LOCAL_MODULE := SettingsLib
-
-LOCAL_JAVA_LIBRARIES := \
-    androidx.annotation_annotation
-
-LOCAL_SHARED_ANDROID_LIBRARIES := \
-    androidx.legacy_legacy-support-v4 \
-    androidx.recyclerview_recyclerview \
-    androidx.preference_preference \
-    androidx.appcompat_appcompat \
-    androidx.lifecycle_lifecycle-runtime
-
-LOCAL_SHARED_JAVA_LIBRARIES := \
-    androidx.lifecycle_lifecycle-common
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_JAR_EXCLUDE_FILES := none
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MIN_SDK_VERSION := 21
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# For the test package.
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS
index 4211c27..d188c65 100644
--- a/packages/SettingsLib/OWNERS
+++ b/packages/SettingsLib/OWNERS
@@ -8,8 +8,8 @@
 evanlaird@google.com
 jackqdyulei@google.com
 jmonk@google.com
+leifhendrik@google.com
 mfritze@google.com
-nicoya@google.com
 rogerxue@google.com
 virgild@google.com
 zhfan@google.com
@@ -18,4 +18,4 @@
 miket@google.com
 
 # Exempt resource files (because they are in a flat directory and too hard to manage via OWNERS)
-per-file *.xml=*
\ No newline at end of file
+per-file *.xml=*
diff --git a/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml
index c8a80ac..6b45a47 100644
--- a/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml
+++ b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="0.24" android:color="?android:attr/colorBackground" />
+    <item android:alpha="0.24" android:color="@android:color/black" />
 </selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml
index 8dcfdbb..5ef085b 100644
--- a/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml
+++ b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="0.47" android:color="?android:attr/colorBackground" />
+    <item android:alpha="0.47" android:color="@android:color/black" />
 </selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml
index 34de548..81f63a4 100644
--- a/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml
+++ b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="0.3" android:color="?android:attr/colorForeground" />
+    <item android:alpha="0.3" android:color="@android:color/white" />
 </selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml
index 15944c3..61f4e26 100644
--- a/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml
+++ b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="?android:attr/colorForeground" />
+    <item android:color="@android:color/white" />
 </selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout-television/settings_with_drawer.xml b/packages/SettingsLib/res/layout-television/settings_with_drawer.xml
deleted file mode 100644
index e8ca691..0000000
--- a/packages/SettingsLib/res/layout-television/settings_with_drawer.xml
+++ /dev/null
@@ -1,20 +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.
--->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/content_frame"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent" />
diff --git a/packages/SettingsLib/res/layout-watch/settings_with_drawer.xml b/packages/SettingsLib/res/layout-watch/settings_with_drawer.xml
deleted file mode 100644
index e8ca691..0000000
--- a/packages/SettingsLib/res/layout-watch/settings_with_drawer.xml
+++ /dev/null
@@ -1,20 +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.
--->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/content_frame"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent" />
diff --git a/packages/SettingsLib/res/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml
deleted file mode 100644
index e1d5c0f..0000000
--- a/packages/SettingsLib/res/layout/settings_with_drawer.xml
+++ /dev/null
@@ -1,40 +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.
--->
-<!-- The main content view -->
-<LinearLayout
-    android:id="@+id/content_parent"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-    <Toolbar
-        android:id="@+id/action_bar"
-        style="?android:attr/actionBarStyle"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:theme="?android:attr/actionBarTheme"
-        android:navigationContentDescription="@*android:string/action_bar_up_description" />
-    <FrameLayout
-        android:id="@+id/content_header_container"
-        style="?android:attr/actionBarStyle"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-    <FrameLayout
-        android:id="@+id/content_frame"
-        android:layout_width="match_parent"
-        android:layout_height="fill_parent"
-        android:background="?android:attr/windowBackground" />
-</LinearLayout>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 9bacaf33..296a135 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"op <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Tydsduur"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Vra elke keer"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Totdat jy dit afskakel"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Sopas"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 329e9fe..ab52bcb 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"በ<xliff:g id="WHEN">%1$s</xliff:g> ላይ"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"የቆይታ ጊዜ"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ሁልጊዜ ጠይቅ"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"እስኪያጠፉት ድረስ"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ልክ አሁን"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 846f5d8..e8811eb 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -453,5 +453,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"يوم <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"المدة"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"الطلب في كل مرة"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"إلى أن توقف الوضع يدويًا"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"للتو"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index e3b4bc9..0adac28 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> বজাত"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"সময়সীমা"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"প্ৰতিবাৰতে সোধক"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"আপুনি অফ নকৰা পর্যন্ত"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"এই মাত্ৰ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 5a49c62..8f974fe 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> olduqda"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Müddət"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Hər dəfə soruşun"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Deaktiv edənə qədər"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"İndicə"</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 75999a4..1e3eba6 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -450,5 +450,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trajanje"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Uvek pitaj"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Upravo sada"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 6541383..42fda63 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -451,5 +451,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Працягласць"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Заўсёды пытацца"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Пакуль не выключыце"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Зараз"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 6761140..a309449 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"в/ъв <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Времетраене"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Да се пита винаги"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"До изключване"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Току-що"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 66f5c07..ad4ef2f 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"তারিখ ও সময় <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"সময়কাল"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"প্রতিবার জিজ্ঞেস করা হবে"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"যতক্ষণ না আপনি বন্ধ করছেন"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"এখনই"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 8577779..9b3c38c 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -27,7 +27,7 @@
     <item msgid="515055375277271756">"Autentifikacija…"</item>
     <item msgid="1943354004029184381">"Dobivanje IP adrese…"</item>
     <item msgid="4221763391123233270">"Povezano"</item>
-    <item msgid="624838831631122137">"Suspendiran"</item>
+    <item msgid="624838831631122137">"Suspendirano"</item>
     <item msgid="7979680559596111948">"Prekidanje veze…"</item>
     <item msgid="1634960474403853625">"Isključen"</item>
     <item msgid="746097431216080650">"Neuspješno"</item>
@@ -38,11 +38,11 @@
     <item msgid="7714855332363650812"></item>
     <item msgid="8878186979715711006">"Skeniranje…"</item>
     <item msgid="355508996603873860">"Povezivanje na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
-    <item msgid="554971459996405634">"Autentifikacija sa mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+    <item msgid="554971459996405634">"Autentifikacija s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="7928343808033020343">"Dobivanje IP adrese iz mreže <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
-    <item msgid="8937994881315223448">"Povezan na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
-    <item msgid="1330262655415760617">"Suspendiran"</item>
-    <item msgid="7698638434317271902">"Prekidanje veze sa mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+    <item msgid="8937994881315223448">"Povezano na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
+    <item msgid="1330262655415760617">"Suspendirano"</item>
+    <item msgid="7698638434317271902">"Prekidanje veze s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="197508606402264311">"Isključen"</item>
     <item msgid="8578370891960825148">"Neuspješno"</item>
     <item msgid="5660739516542454527">"Blokirano"</item>
@@ -59,7 +59,7 @@
     <item msgid="45075631231212732">"Uvijek koristi HDCP provjeru"</item>
   </string-array>
   <string-array name="bluetooth_avrcp_versions">
-    <item msgid="5347678900838034763">"AVRCP 1.4 (Zadano)"</item>
+    <item msgid="5347678900838034763">"AVRCP 1.4 (zadano)"</item>
     <item msgid="2809759619990248160">"AVRCP 1.3"</item>
     <item msgid="6199178154704729352">"AVRCP 1.5"</item>
     <item msgid="5172170854953034852">"AVRCP 1.6"</item>
@@ -71,58 +71,58 @@
     <item msgid="3422726142222090896">"avrcp16"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="7065842274271279580">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="7065842274271279580">"Koristi odabir sistema (zadano)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
     <item msgid="686685526567131661">"AAC"</item>
     <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
     <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
     <item msgid="6751080638867012696">"LDAC"</item>
-    <item msgid="723675059572222462">"Omogućite opcionalne kodeke"</item>
-    <item msgid="3304843301758635896">"Onemogućite opcionalne kodeke"</item>
+    <item msgid="723675059572222462">"Omogući opcionalne kodeke"</item>
+    <item msgid="3304843301758635896">"Onemogući opcionalne kodeke"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="5062108632402595000">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="5062108632402595000">"Koristi odabir sistema (zadano)"</item>
     <item msgid="6898329690939802290">"SBC"</item>
     <item msgid="6839647709301342559">"AAC"</item>
     <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
     <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
     <item msgid="7950781694447359344">"LDAC"</item>
-    <item msgid="2209680154067241740">"Omogućite opcionalne kodeke"</item>
-    <item msgid="741805482892725657">"Onemogućite opcionalne kodeke"</item>
+    <item msgid="2209680154067241740">"Omogući opcionalne kodeke"</item>
+    <item msgid="741805482892725657">"Onemogući opcionalne kodeke"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
-    <item msgid="3093023430402746802">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="3093023430402746802">"Koristi odabir sistema (zadano)"</item>
     <item msgid="8895532488906185219">"44,1 kHz"</item>
     <item msgid="2909915718994807056">"48,0 kHz"</item>
     <item msgid="3347287377354164611">"88,2 kHz"</item>
     <item msgid="1234212100239985373">"96,0 kHz"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
-    <item msgid="3214516120190965356">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="3214516120190965356">"Koristi odabir sistema (zadano)"</item>
     <item msgid="4482862757811638365">"44,1 kHz"</item>
     <item msgid="354495328188724404">"48,0 kHz"</item>
     <item msgid="7329816882213695083">"88,2 kHz"</item>
     <item msgid="6967397666254430476">"96,0 kHz"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
-    <item msgid="2684127272582591429">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="2684127272582591429">"Koristi odabir sistema (zadano)"</item>
     <item msgid="5618929009984956469">"16 bitova/uzorak"</item>
     <item msgid="3412640499234627248">"24 bitova/uzorak"</item>
     <item msgid="121583001492929387">"32 bitova/uzorak"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
-    <item msgid="1081159789834584363">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="1081159789834584363">"Koristi odabir sistema (zadano)"</item>
     <item msgid="4726688794884191540">"16 bitova/uzorak"</item>
     <item msgid="305344756485516870">"24 bitova/uzorak"</item>
     <item msgid="244568657919675099">"32 bitova/uzorak"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
-    <item msgid="5226878858503393706">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="5226878858503393706">"Koristi odabir sistema (zadano)"</item>
     <item msgid="4106832974775067314">"Mono"</item>
     <item msgid="5571632958424639155">"Stereo"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
-    <item msgid="4118561796005528173">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="4118561796005528173">"Koristi odabir sistema (zadano)"</item>
     <item msgid="8900559293912978337">"Mono"</item>
     <item msgid="8883739882299884241">"Stereo"</item>
   </string-array>
@@ -130,13 +130,13 @@
     <item msgid="7158319962230727476">"Optimizirano za kvalitet zvuka (990 kbps/909 kbps)"</item>
     <item msgid="2921767058740704969">"Uravnotežen kvalitet zvuka i veze (660kbps/606kbps)"</item>
     <item msgid="8860982705384396512">"Optimizirano za kvalitet veze (330 kbps/303 kbps)"</item>
-    <item msgid="4414060457677684127">"Maksimalan napor (Prilagodljiva brzina prijenosa)"</item>
+    <item msgid="4414060457677684127">"Maksimalan napor (prilagodljiva brzina prijenosa)"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
     <item msgid="6398189564246596868">"Optimizirano za kvalitet zvuka"</item>
     <item msgid="4327143584633311908">"Uravnotežen kvalitet zvuka i veze"</item>
     <item msgid="4681409244565426925">"Optimizirano za kvalitet veze"</item>
-    <item msgid="364670732877872677">"Maksimalan napor (Prilagodljiva brzina prijenosa)"</item>
+    <item msgid="364670732877872677">"Maksimalan napor (prilagodljiva brzina prijenosa)"</item>
   </string-array>
   <string-array name="bluetooth_audio_active_device_summaries">
     <item msgid="4862957058729193940"></item>
@@ -169,7 +169,7 @@
   <string-array name="select_logpersist_titles">
     <item msgid="1744840221860799971">"Isključeno"</item>
     <item msgid="3054662377365844197">"Sve"</item>
-    <item msgid="688870735111627832">"Svi osim radija"</item>
+    <item msgid="688870735111627832">"Sve osim radija"</item>
     <item msgid="2850427388488887328">"samo kernel"</item>
   </string-array>
   <string-array name="select_logpersist_summaries">
@@ -208,13 +208,13 @@
   <string-array name="overlay_display_devices_entries">
     <item msgid="1606809880904982133">"Nema"</item>
     <item msgid="9033194758688161545">"480p"</item>
-    <item msgid="1025306206556583600">"480p (osiguran)"</item>
+    <item msgid="1025306206556583600">"480p (sigurno)"</item>
     <item msgid="1853913333042744661">"720p"</item>
-    <item msgid="3414540279805870511">"720p (osiguran)"</item>
+    <item msgid="3414540279805870511">"720p (sigurno)"</item>
     <item msgid="9039818062847141551">"1080p"</item>
-    <item msgid="4939496949750174834">"1080p (osiguran)"</item>
+    <item msgid="4939496949750174834">"1080p (sigurno)"</item>
     <item msgid="1833612718524903568">"4K"</item>
-    <item msgid="238303513127879234">"4K (osiguran)"</item>
+    <item msgid="238303513127879234">"4K (sigurno)"</item>
     <item msgid="3547211260846843098">"4K (povećava rezoluciju)"</item>
     <item msgid="5411365648951414254">"4K (povećava rezoluciju, osiguran)"</item>
     <item msgid="1311305077526792901">"720p, 1080p (dupli ekran)"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index b8195b1..4332682 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -43,7 +43,7 @@
     <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nema internetske veze"</string>
     <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Potrebna je prijava"</string>
     <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pristupna tačka je privremeno puna"</string>
-    <string name="connected_via_carrier" msgid="7583780074526041912">"Povezana koristeći %1$s"</string>
+    <string name="connected_via_carrier" msgid="7583780074526041912">"Povezano koristeći %1$s"</string>
     <string name="available_via_carrier" msgid="1469036129740799053">"Dostupna koristeći %1$s"</string>
     <string name="speed_label_very_slow" msgid="1867055264243608530">"Veoma sporo"</string>
     <string name="speed_label_slow" msgid="813109590815810235">"Sporo"</string>
@@ -84,11 +84,11 @@
     <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezano na slušni aparat"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano na zvuk telefona"</string>
-    <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezan na server za prijenos podataka"</string>
+    <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano sa serverom za prijenos podataka"</string>
     <string name="bluetooth_map_profile_summary_connected" msgid="8191407438851351713">"Povezano na mapu"</string>
     <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"Povezan na SAP"</string>
-    <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"Nije povezan na server za prijenos podataka"</string>
-    <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"Spojen na ulazni uređaj"</string>
+    <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"Nije povezano sa serverom za prijenos podataka"</string>
+    <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"Povezano s ulaznim uređajem"</string>
     <string name="bluetooth_pan_user_profile_summary_connected" msgid="6436258151814414028">"Povezano na uređaj za pristup internetu"</string>
     <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1322694224800769308">"Dijeljenje lokalne internetske veze s uređajem"</string>
     <string name="bluetooth_pan_profile_summary_use_for" msgid="5736111170225304239">"Koristi za pristup internetu"</string>
@@ -102,10 +102,10 @@
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string>
-    <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Uparivanje odobrava pristup kontaktima i istoriji poziva kada je uspostavljeno."</string>
-    <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Nije se moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Nije se moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> zbog pogrešnog PIN-a ili pristupnog koda."</string>
-    <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Ne može komunicirati sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+    <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Uparivanje odobrava pristup kontaktima i historiji poziva kada je uspostavljeno."</string>
+    <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Nije moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Nije moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> zbog pogrešnog PIN-a ili pristupnog koda."</string>
+    <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Nije moguće komunicirati s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> je odbio uparivanje."</string>
     <string name="bluetooth_talkback_computer" msgid="4875089335641234463">"Računar"</string>
     <string name="bluetooth_talkback_headset" msgid="5140152177885220949">"Slušalice s mikrofonom"</string>
@@ -118,12 +118,12 @@
     <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Uparivanje desnog slušnog aparata…"</string>
     <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Lijevi - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
     <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Desni - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
-    <string name="accessibility_wifi_off" msgid="1166761729660614716">"WiFi isključen."</string>
+    <string name="accessibility_wifi_off" msgid="1166761729660614716">"WiFi je isključen."</string>
     <string name="accessibility_no_wifi" msgid="8834610636137374508">"WiFi nije povezan."</string>
-    <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"WiFi jedna crtica."</string>
-    <string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"WiFi dvije crtice."</string>
-    <string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"WiFi tri crtice."</string>
-    <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"WiFi puni signal."</string>
+    <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"WiFi signal ima jednu crtu."</string>
+    <string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"WiFi signal ima dvije crte."</string>
+    <string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"WiFi signal ima tri crte."</string>
+    <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"WiFi signal je pun."</string>
     <string name="accessibility_wifi_security_type_none" msgid="1223747559986205423">"Otvorena mreža"</string>
     <string name="accessibility_wifi_security_type_secured" msgid="862921720418885331">"Sigurna mreža"</string>
     <string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
@@ -132,7 +132,7 @@
     <string name="tether_settings_title_usb" msgid="6688416425801386511">"Povezivanje mobitela USB-om"</string>
     <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prijenosna pristupna tačka"</string>
     <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Dijeljenje Bluetooth veze"</string>
-    <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Dijeljenje veze"</string>
+    <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Povezivanje putem mobitela"</string>
     <string name="tether_settings_title_all" msgid="8356136101061143841">"Povezivanje putem mobitela i prijenosna pristupna tačka"</string>
     <string name="managed_user_title" msgid="8109605045406748842">"Sve radne aplikacije"</string>
     <string name="user_guest" msgid="8475274842845401871">"Gost"</string>
@@ -145,7 +145,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina"</string>
-    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utječe na ton sintetiziranog govora"</string>
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utiče na ton sintetiziranog govora"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Korištenje sistemskog jezika"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije izabran"</string>
@@ -187,7 +187,7 @@
     <string name="development_settings_summary" msgid="1815795401632854041">"Postavi opcije za razvoj aplikacija"</string>
     <string name="development_settings_not_available" msgid="4308569041701535607">"Opcije za programere nisu dostupne za ovog korisnika"</string>
     <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN postavke nisu dostupne za ovog korisnika"</string>
-    <string name="tethering_settings_not_available" msgid="6765770438438291012">"Postavke za privezivanje nisu dostupne za ovog korisnika"</string>
+    <string name="tethering_settings_not_available" msgid="6765770438438291012">"Postavke za povezivanje putem mobitela nisu dostupne za ovog korisnika"</string>
     <string name="apn_settings_not_available" msgid="7873729032165324000">"Postavke za ime pristupne tačke nisu dostupne za ovog korisnika"</string>
     <string name="enable_adb" msgid="7982306934419797485">"Otklanjanje grešaka putem uređaja spojenog na USB"</string>
     <string name="enable_adb_summary" msgid="4881186971746056635">"Način rada za uklanjanje grešaka kada je povezan USB"</string>
@@ -201,7 +201,7 @@
     <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM otključavanje"</string>
     <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Dozvoli otključavanje bootloadera"</string>
     <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"Želite li dozvoliti OEM otključavanje?"</string>
-    <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"UPOZORENJE: Funkcije zaštite ovog uređaja neće funkcionisati dok je ova postavka uključena."</string>
+    <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"UPOZORENJE: Funkcije zaštite ovog uređaja neće funkcionirati dok je ova postavka uključena."</string>
     <string name="mock_location_app" msgid="7966220972812881854">"Odaberite aplikaciju za lažne lokacije"</string>
     <string name="mock_location_app_not_set" msgid="809543285495344223">"Aplikacija za lažnu lokaciju nije postavljena"</string>
     <string name="mock_location_app_set" msgid="8966420655295102685">"Aplikacija za lažne lokacije: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -210,7 +210,7 @@
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući detaljniju evidenciju za WiFi"</string>
     <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Nasumični odabir MAC adrese pri povezivanju"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string>
-    <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje dijeljenja veze"</string>
+    <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje za povezivanje putem mobitela"</string>
     <string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Prikaži Bluetooth uređaje bez naziva"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući apsolutnu jačinu zvuka"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP verzija"</string>
@@ -220,7 +220,7 @@
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Brzina uzorkovanja za Bluetooth audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Aktivirajte Bluetooth Audio Codec\nOdabir: Brzina uzorkovanja"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth audio bitovi po uzorku"</string>
-    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Aktivirajte Bluetooth Audio Codec\nOdabir: Bitovi po semplu"</string>
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Aktivirajte Bluetooth Audio Codec\nOdabir: Bitovi po uzorku"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Način Bluetooth audio kanala"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="7234956835280563341">"Aktivirajte Bluetooth Audio Codec\nOdabir: Način rada po kanalima"</string>
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth Audio LDAC kodek: Kvalitet reprodukcije"</string>
@@ -249,7 +249,7 @@
     <string name="allow_mock_location" msgid="2787962564578664888">"Dozvoli lažne lokacije"</string>
     <string name="allow_mock_location_summary" msgid="317615105156345626">"Dozvoli lažne lokacije"</string>
     <string name="debug_view_attributes" msgid="6485448367803310384">"Omogući pregled atributa prikaza"</string>
-    <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Uvijek drži prijenos podataka na mobilnoj mreži aktivnim, čak i kada je WiFi je aktivan (za brzo prebacivanje između mreža)."</string>
+    <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Uvijek drži prijenos podataka na mobilnoj mreži aktivnim, čak i kada je WiFi aktivan (za brzo prebacivanje između mreža)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Koristi hardversko ubrzavanje dijeljenja veze, ako je dostupno"</string>
     <string name="adb_warning_title" msgid="6234463310896563253">"Omogućiti otklanjanje grešaka putem uređaja spojenog na USB?"</string>
     <string name="adb_warning_message" msgid="7316799925425402244">"Otklanjanje grešaka putem uređaja spojenog na USB je namijenjeno samo u svrhe razvoja aplikacija. Koristite ga za kopiranje podataka između računara i uređaja, instaliranje aplikacija na uređaj bez obavještenja te čitanje podataka iz zapisnika."</string>
@@ -277,7 +277,7 @@
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Prikaz s hardverskom akceleracijom"</string>
     <string name="media_category" msgid="4388305075496848353">"Mediji"</string>
     <string name="debug_monitoring_category" msgid="7640508148375798343">"Praćenje"</string>
-    <string name="strict_mode" msgid="1938795874357830695">"Omogućen strogi režim"</string>
+    <string name="strict_mode" msgid="1938795874357830695">"Omogućen strogi način rada"</string>
     <string name="strict_mode_summary" msgid="142834318897332338">"Prikaži ekran uz treptanje kada aplikacije vrše duge operacije u glavnoj niti"</string>
     <string name="pointer_location" msgid="6084434787496938001">"Lokacija pokazivača"</string>
     <string name="pointer_location_summary" msgid="840819275172753713">"Trenutni podaci o dodirivanju prikazuju se u nadsloju preko ekrana"</string>
@@ -298,8 +298,8 @@
     <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Onemogući autom. usmjerav. na USB audio periferije"</string>
     <string name="debug_layout" msgid="5981361776594526155">"Prikaži granice rasporeda"</string>
     <string name="debug_layout_summary" msgid="2001775315258637682">"Prikaži granice isječka, margine itd."</string>
-    <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Prisilno postavi raspored s desna u lijevo"</string>
-    <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Prisilno postavi raspored ekrana s desna u lijevo za sve regije"</string>
+    <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Prisilno postavi raspored s desna ulijevo"</string>
+    <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Prisilno postavi raspored ekrana s desna ulijevo za sve regije"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Prinudno primijeni 4x MSAA"</string>
     <string name="force_msaa_summary" msgid="9123553203895817537">"Omogući 4x MSAA u OpenGL ES 2.0 aplikacijama"</string>
     <string name="show_non_rect_clip" msgid="505954950474595172">"Ispravi greške na nepravougaonim operacijama isjecanja"</string>
@@ -321,19 +321,19 @@
     <string name="force_allow_on_external" msgid="3215759785081916381">"Nametni aplikacije na vanjskoj pohrani"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava upisivanje svih aplikacija u vanjsku pohranu, bez obzira na prikazane vrijednosti"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni aktivnostima mijenjanje veličina"</string>
-    <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući mijenjanje veličine svih aktivnosti za prikaz sa više prozora, bez obzira na prikazane vrijednosti."</string>
+    <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući mijenjanje veličine svih aktivnosti za prikaz s više prozora, bez obzira na prikazane vrijednosti."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore nepravilnih oblika"</string>
     <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogući podršku za eksperimentalne prozore nepravilnih oblika."</string>
     <string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka za sigurnosnu kopiju radne površine"</string>
     <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Potpune sigurnosne kopije za računare trenutno nisu zaštićene"</string>
-    <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije sa radne površine"</string>
-    <string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova lozinka za sigurnosnu kopiju postavljena"</string>
+    <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije s radne površine"</string>
+    <string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova lozinka za sigurnosnu kopiju je postavljena"</string>
     <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"Nova lozinka i potvrda se ne podudaraju"</string>
     <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Nije uspjelo postavljanje lozinke za sigurnosnu kopiju"</string>
   <string-array name="color_mode_names">
-    <item msgid="2425514299220523812">"Živopisan (zadano)"</item>
+    <item msgid="2425514299220523812">"Živopisno (zadano)"</item>
     <item msgid="8446070607501413455">"Prirodan"</item>
-    <item msgid="6553408765810699025">"Standardni"</item>
+    <item msgid="6553408765810699025">"Standardno"</item>
   </string-array>
   <string-array name="color_mode_descriptions">
     <item msgid="4979629397075120893">"Unaprijeđene boje"</item>
@@ -353,9 +353,9 @@
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvaranje…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fajl je već šifriran"</string>
     <string name="title_convert_fbe" msgid="1263622876196444453">"Pretvaranje u šifrirane fajlove"</string>
-    <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Pretvorite particiju sa podacima u particiju šifriranu sistemom fajlova.\n !! Upozorenje!! Ovo će izbrisati sve vaše podatke.\n Ova funkcija je u alfa fazi razvoja i možda neće ispravno raditi.\n Pritisnite \"Obriši i pretvori…\" da nastavite."</string>
+    <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Pretvorite particiju s podacima u particiju šifriranu sistemom fajlova.\n !! Upozorenje!! Ovo će izbrisati sve vaše podatke.\n Ova funkcija je u alfa fazi razvoja i možda neće ispravno raditi.\n Pritisnite \"Obriši i pretvori…\" da nastavite."</string>
     <string name="button_convert_fbe" msgid="5152671181309826405">"Obriši i pretvori…"</string>
-    <string name="picture_color_mode" msgid="4560755008730283695">"Režim boja Slika"</string>
+    <string name="picture_color_mode" msgid="4560755008730283695">"Način rada boja slika"</string>
     <string name="picture_color_mode_desc" msgid="1141891467675548590">"Koristi sRGB"</string>
     <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Onemogućeno"</string>
     <string name="daltonizer_mode_monochromacy" msgid="8485709880666106721">"Crno-bijelo"</string>
@@ -422,8 +422,8 @@
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je lozinka"</string>
     <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivne metode unosa"</string>
     <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Koristi jezik sistema"</string>
-    <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nije uspjelo otvaranje postavki za <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
-    <string name="ime_security_warning" msgid="4135828934735934248">"Ovaj način unosa može prikupiti sav tekst koji otkucate, uključujući lične podatke kao što su lozinke i brojevi kreditnih kartica. Način omogućava aplikacija <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Da li želite koristiti ovaj način unosa?"</string>
+    <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Otvaranje postavki za <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> nije uspjelo"</string>
+    <string name="ime_security_warning" msgid="4135828934735934248">"Ovaj način unosa može prikupiti sav tekst koji upišete, uključujući lične podatke kao što su lozinke i brojevi kreditnih kartica. Način omogućava aplikacija <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Da li želite koristiti ovaj način unosa?"</string>
     <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Napomena: Nakon ponovnog pokretanja, ova aplikacija se neće moći pokrenuti dok ne otključate telefon"</string>
     <string name="ims_reg_title" msgid="7609782759207241443">"Stanje IMS registracije"</string>
     <string name="ims_reg_status_registered" msgid="933003316932739188">"Registrirano"</string>
@@ -450,5 +450,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trajanje"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pitaj svaki put"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Upravo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 2488f55..7750ef2 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -189,9 +189,9 @@
     <string name="vpn_settings_not_available" msgid="956841430176985598">"La configuració de la VPN no està disponible per a aquest usuari."</string>
     <string name="tethering_settings_not_available" msgid="6765770438438291012">"La configuració de compartició de xarxa no està disponible per a aquest usuari."</string>
     <string name="apn_settings_not_available" msgid="7873729032165324000">"La configuració del nom del punt d\'accés no està disponible per a aquest usuari."</string>
-    <string name="enable_adb" msgid="7982306934419797485">"Depuració USB"</string>
+    <string name="enable_adb" msgid="7982306934419797485">"Depuració per USB"</string>
     <string name="enable_adb_summary" msgid="4881186971746056635">"Activa el mode de depuració quan el dispositiu estigui connectat per USB"</string>
-    <string name="clear_adb_keys" msgid="4038889221503122743">"Revoca autoritzacions de depuració USB"</string>
+    <string name="clear_adb_keys" msgid="4038889221503122743">"Revoca autoritzacions de depuració per USB"</string>
     <string name="bugreport_in_power" msgid="7923901846375587241">"Drecera per a informe d\'errors"</string>
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostra un botó al menú d\'engegada per crear un informe d\'errors"</string>
     <string name="keep_screen_on" msgid="1146389631208760344">"Pantalla sempre activa"</string>
@@ -251,9 +251,9 @@
     <string name="debug_view_attributes" msgid="6485448367803310384">"Inspecció d\'atributs de visualització"</string>
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Mantén les dades mòbils sempre actives, fins i tot quan la Wi‑Fi està activada (per canviar de xarxa ràpidament)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Fes servir l\'acceleració per maquinari per compartir la xarxa, si està disponible"</string>
-    <string name="adb_warning_title" msgid="6234463310896563253">"Voleu permetre la depuració USB?"</string>
-    <string name="adb_warning_message" msgid="7316799925425402244">"La depuració USB només està indicada per a activitats de desenvolupament. Fes-la servir intercanviar dades entre l\'ordinador i el dispositiu, per instal·lar aplicacions al dispositiu sense rebre notificacions i per llegir dades de registre."</string>
-    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Vols revocar l\'accés a la depuració d\'USB dels ordinadors que has autoritzat anteriorment?"</string>
+    <string name="adb_warning_title" msgid="6234463310896563253">"Voleu permetre la depuració per USB?"</string>
+    <string name="adb_warning_message" msgid="7316799925425402244">"La depuració per USB només està indicada per a activitats de desenvolupament. Fes-la servir intercanviar dades entre l\'ordinador i el dispositiu, per instal·lar aplicacions al dispositiu sense rebre notificacions i per llegir dades de registre."</string>
+    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Vols revocar l\'accés a la depuració per USB dels ordinadors que has autoritzat anteriorment?"</string>
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"Vols permetre la conf. de desenvolupament?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"Aquesta configuració només està prevista per a usos de desenvolupament. Pot fer que el dispositiu i que les aplicacions s\'interrompin o tinguin un comportament inadequat."</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifica aplicacions per USB"</string>
@@ -398,8 +398,8 @@
     <string name="enabled_by_admin" msgid="5302986023578399263">"Activada per l\'administrador"</string>
     <string name="disabled_by_admin" msgid="8505398946020816620">"Desactivada per l\'administrador"</string>
     <string name="disabled" msgid="9206776641295849915">"Desactivat"</string>
-    <string name="external_source_trusted" msgid="2707996266575928037">"Permeses"</string>
-    <string name="external_source_untrusted" msgid="2677442511837596726">"No permeses"</string>
+    <string name="external_source_trusted" msgid="2707996266575928037">"Amb permís"</string>
+    <string name="external_source_untrusted" msgid="2677442511837596726">"Sense permís"</string>
     <string name="install_other_apps" msgid="6986686991775883017">"Instal·lar aplicacions desconegudes"</string>
     <string name="home" msgid="3256884684164448244">"Pàgina d\'inici de configuració"</string>
   <string-array name="battery_labels">
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"Data: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Durada"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pregunta sempre"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Fins que no ho desactivi"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Ara mateix"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 1579d8f..72b3389 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -189,9 +189,9 @@
     <string name="vpn_settings_not_available" msgid="956841430176985598">"Nastavení sítě VPN pro tohoto uživatele není dostupné."</string>
     <string name="tethering_settings_not_available" msgid="6765770438438291012">"Nastavení sdíleného připojení pro tohoto uživatele není dostupné."</string>
     <string name="apn_settings_not_available" msgid="7873729032165324000">"Nastavení přístupového bodu pro tohoto uživatele není dostupné."</string>
-    <string name="enable_adb" msgid="7982306934419797485">"Ladění USB"</string>
+    <string name="enable_adb" msgid="7982306934419797485">"Ladění přes USB"</string>
     <string name="enable_adb_summary" msgid="4881186971746056635">"Povolit režim ladění s připojeným zařízením USB"</string>
-    <string name="clear_adb_keys" msgid="4038889221503122743">"Zrušit autorizace k ladění USB"</string>
+    <string name="clear_adb_keys" msgid="4038889221503122743">"Zrušit autorizace k ladění přes USB"</string>
     <string name="bugreport_in_power" msgid="7923901846375587241">"Zástupce hlášení chyb"</string>
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Zobrazit v hlavní nabídce tlačítko k vygenerování chybového hlášení"</string>
     <string name="keep_screen_on" msgid="1146389631208760344">"Nevypínat obrazovku"</string>
@@ -251,9 +251,9 @@
     <string name="debug_view_attributes" msgid="6485448367803310384">"Kontrola atributu zobrazení"</string>
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Mobilní data budou vždy ponechána aktivní, i když bude aktivní Wi-Fi (za účelem rychlého přepínání sítí)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Pokud je k dispozici hardwarová akceleraci tetheringu, použít ji"</string>
-    <string name="adb_warning_title" msgid="6234463310896563253">"Povolit ladění USB?"</string>
+    <string name="adb_warning_title" msgid="6234463310896563253">"Povolit ladění přes USB?"</string>
     <string name="adb_warning_message" msgid="7316799925425402244">"Ladění prostřednictvím rozhraní USB je určeno pouze pro účely vývoje. Použijte je ke kopírování dat mezi počítačem a zařízením, instalaci aplikací do zařízení bez upozornění a čtení dat protokolů."</string>
-    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Zrušit přístup k ladění USB ze všech počítačů, které jste v minulosti autorizovali?"</string>
+    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Zrušit přístup k ladění přes USB ze všech počítačů, které jste v minulosti autorizovali?"</string>
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"Povolit nastavení pro vývojáře?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"Tato nastavení jsou určena pouze pro vývojáře. Mohou způsobit rozbití nebo nesprávné fungování zařízení a nainstalovaných aplikací."</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Ověřit aplikace z USB"</string>
@@ -451,5 +451,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"v <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trvání"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pokaždé se zeptat"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Dokud tuto funkci nevypnete"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Právě teď"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index fbedd90..ca96070 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -386,8 +386,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7466484148515796216">"Denne tablet lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="603933521600231649">"Enheden lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> til det er fuldt opladet"</string>
-    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til det er fuldt opladet"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"fuldt opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – fuldt opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukendt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Oplader"</string>
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"oplader"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"på <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Varighed"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Spørg hver gang"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Indtil du deaktiverer"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Lige nu"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 6fb0fc9..9db490b 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"am <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Dauer"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Jedes Mal fragen"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Bis zur Deaktivierung"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Gerade eben"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 336075f..2ba543e 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"το/τη(ν) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Διάρκεια"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Να ερωτώμαι κάθε φορά"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Μέχρι την απενεργοποίηση"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Μόλις τώρα"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index e028e73..747fdc7 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duration"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ask every time"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index e028e73..747fdc7 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duration"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ask every time"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index e028e73..747fdc7 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duration"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ask every time"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index e028e73..747fdc7 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"on <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duration"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ask every time"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 5e046e0..33b9f1d 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‎on ‎‏‎‎‏‏‎<xliff:g id="WHEN">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‏‎‏‎Duration‎‏‎‎‏‎"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‎Ask every time‎‏‎‎‏‎"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎Until you turn off‎‏‎‎‏‎"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎Just now‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 6c4f3b0..f665b77 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"el <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duración"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Preguntar siempre"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Hasta que lo desactives"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Recién"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index e9b07a4..9cdde92 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -217,8 +217,8 @@
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versión AVRCP del Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio de Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"Activar el códec de audio por Bluetooth\nSelección"</string>
-    <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Porcentaje de muestreo de audio por Bluetooth"</string>
-    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Activar el códec de audio por Bluetooth\nSelección: porcentaje de muestreo"</string>
+    <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Frecuencia de muestreo de audio por Bluetooth"</string>
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Activar el códec de audio por Bluetooth\nSelección: frecuencia de muestreo"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits por muestra del audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Activar el códec de audio por Bluetooth\nSelección: bits por muestra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canal de audio por Bluetooth"</string>
@@ -238,7 +238,7 @@
     <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Ordenar las direcciones MAC de forma aleatoria al conectarse a redes Wi‑Fi"</string>
     <string name="wifi_metered_label" msgid="4514924227256839725">"Medida"</string>
     <string name="wifi_unmetered_label" msgid="6124098729457992931">"No medida"</string>
-    <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de registrador"</string>
+    <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños del búfer para registrar"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Elige el tamaño del Logger por búfer"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"¿Borrar almacenamiento continuo del registrador?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Cuando ya no supervisamos la actividad con el registrador de forma continua, estamos obligados a borrar los datos del registrador almacenados en el dispositivo."</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"Fecha: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duración"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Preguntar siempre"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Hasta que se desactive"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Justo ahora"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 1f50226..2b44321 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"– <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Kestus"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Küsi iga kord"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Kuni välja lülitate"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Äsja"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index ec7bf98..4ad60b3 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -165,7 +165,7 @@
     <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> motorraren ezarpenak"</string>
     <string name="tts_engine_settings_button" msgid="1030512042040722285">"Abiarazi motorraren ezarpenak"</string>
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor hobetsia"</string>
-    <string name="tts_general_section_title" msgid="4402572014604490502">"Orokorra"</string>
+    <string name="tts_general_section_title" msgid="4402572014604490502">"Orokorrak"</string>
     <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Berrezarri ahots-tonua"</string>
     <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Berrezarri testua esateko ahots-tonu lehenetsia."</string>
   <string-array name="tts_rate_entries">
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"data: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Iraupena"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Galdetu beti"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Desaktibatu arte"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Oraintxe"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 7dfd429..1d08821 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -159,7 +159,7 @@
     <string name="tts_default_sample_string" msgid="4040835213373086322">"این نمونه‌ای از ترکیب گفتار است"</string>
     <string name="tts_status_title" msgid="7268566550242584413">"وضعیت زبان پیش‌فرض"</string>
     <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> کاملاً پشتیبانی می‌شود"</string>
-    <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> به اتصال شبکه نیاز دارد"</string>
+    <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> باید اتصال شبکه داشته باشد"</string>
     <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> پشتیبانی نمی‌شود"</string>
     <string name="tts_status_checking" msgid="5339150797940483592">"در حال بررسی…"</string>
     <string name="tts_engine_settings_title" msgid="3499112142425680334">"تنظیمات برای <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"روز <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"مدت"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"هربار پرسیده شود"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"تا زمانی‌که آن را خاموش کنید"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"هم‌اکنون"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 377f8ce..7c253fc 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Kesto"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Kysy aina"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Kunnes poistat sen käytöstä"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Äsken"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 67e7779..99906ca 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"le <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Durée"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Toujours demander"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Jusqu\'à la désactivation"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"À l\'instant"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 5eac8fa..7a51faa 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -371,10 +371,10 @@
     <string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
     <string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Temps restant en fonction de votre utilisation (<xliff:g id="LEVEL">%2$s</xliff:g>) : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Temps restant : <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de l\'utilisation (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de l\'utilisation"</string>
-    <string name="power_discharge_by" msgid="6453537733650125582">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only" msgid="107616694963545745">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Temps restant estimé en fonction de votre utilisation : <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
+    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Temps restant estimé en fonction de votre utilisation : <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by" msgid="6453537733650125582">"Temps restant estimé : <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
+    <string name="power_discharge_by_only" msgid="107616694963545745">"Temps restant estimé : <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"le <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Durée"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Toujours demander"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Jusqu\'à la désactivation"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"À l\'instant"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index c6c4a2e..f8a69c2 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -207,12 +207,12 @@
   </string-array>
   <string-array name="overlay_display_devices_entries">
     <item msgid="1606809880904982133">"Ningunha"</item>
-    <item msgid="9033194758688161545">"480 p"</item>
-    <item msgid="1025306206556583600">"480 p (seguro)"</item>
+    <item msgid="9033194758688161545">"480p"</item>
+    <item msgid="1025306206556583600">"480p (seguro)"</item>
     <item msgid="1853913333042744661">"720p"</item>
     <item msgid="3414540279805870511">"720p (seguro)"</item>
-    <item msgid="9039818062847141551">"1080 p"</item>
-    <item msgid="4939496949750174834">"1080 p (seguro)"</item>
+    <item msgid="9039818062847141551">"1080p"</item>
+    <item msgid="4939496949750174834">"1080p (seguro)"</item>
     <item msgid="1833612718524903568">"4K"</item>
     <item msgid="238303513127879234">"4K (seguro)"</item>
     <item msgid="3547211260846843098">"4K (mellorado)"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 4f26f6a..5bc6163 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -110,7 +110,7 @@
     <string name="bluetooth_talkback_computer" msgid="4875089335641234463">"Ordenador"</string>
     <string name="bluetooth_talkback_headset" msgid="5140152177885220949">"Auriculares con micrófono"</string>
     <string name="bluetooth_talkback_phone" msgid="4260255181240622896">"Teléfono"</string>
-    <string name="bluetooth_talkback_imaging" msgid="551146170554589119">"Imaxes"</string>
+    <string name="bluetooth_talkback_imaging" msgid="551146170554589119">"Dispositivo de imaxe"</string>
     <string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Auriculares"</string>
     <string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Periférico de entrada"</string>
     <string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
@@ -213,8 +213,8 @@
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware para conexión compartida"</string>
     <string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sen nomes"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactivar volume absoluto"</string>
-    <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP de Bluetooth"</string>
-    <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona a versión AVRCP de Bluetooth"</string>
+    <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión de Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona a versión de Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio por Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"Activar códec de audio por Bluetooth\nSelección"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Taxa de mostraxe de audio por Bluetooth"</string>
@@ -353,8 +353,8 @@
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Xa se encriptou o ficheiro"</string>
     <string name="title_convert_fbe" msgid="1263622876196444453">"Convertendo no encriptado baseado en ficheiros"</string>
-    <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Converte a partición de datos nunha encriptación baseada en ficheiros.\n Advertencia: Esta acción borrará todos os datos.\n Esta función é alfa e quizais non funcione correctamente.\n Para continuar, toca Limpar e converter..."</string>
-    <string name="button_convert_fbe" msgid="5152671181309826405">"Limpar e converter..."</string>
+    <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Converte a partición de datos nunha encriptación baseada en ficheiros.\n Advertencia: Esta acción borrará todos os datos.\n Esta función é alfa e quizais non funcione correctamente.\n Para continuar, toca Borrar e converter..."</string>
+    <string name="button_convert_fbe" msgid="5152671181309826405">"Borrar e converter..."</string>
     <string name="picture_color_mode" msgid="4560755008730283695">"Modo de cor da imaxe"</string>
     <string name="picture_color_mode_desc" msgid="1141891467675548590">"Utiliza sRGB"</string>
     <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Desactivado"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"na seguinte data: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duración"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Preguntar sempre"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Ata a desactivación"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Agora mesmo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index bccf0e6..b523ae2 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> વાગ્યે"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"અવધિ"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"દર વખતે પૂછો"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"તમે બંધ ન કરો ત્યાં સુધી"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"હમણાં જ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index c5d662c..cd12f21 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -22,7 +22,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"नेटवर्क के लिए स्‍कैन नहीं कर सकता"</string>
     <string name="wifi_security_none" msgid="7985461072596594400">"कोई नहीं"</string>
-    <string name="wifi_remembered" msgid="4955746899347821096">"सहेजा गया"</string>
+    <string name="wifi_remembered" msgid="4955746899347821096">"सेव किया गया"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्‍फ़िगरेशन की विफलता"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"खराब नेटवर्क होने के कारण कनेक्ट नहीं हुआ"</string>
@@ -449,5 +449,7 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"अलार्म <xliff:g id="WHEN">%1$s</xliff:g> को बजेगा"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"अवधि"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"हर बार पूछें"</string>
+    <!-- no translation found for zen_mode_forever (2704305038191592967) -->
+    <skip />
     <string name="time_unit_just_now" msgid="6363336622778342422">"अभी-अभी"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index f269c38..9c83640 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -450,5 +450,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trajanje"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pitaj svaki put"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Upravo sad"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index a09a4ff..25d11aa 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"ezen a napon: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Időtartam"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Mindig kérdezzen rá"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Kikapcsolásig"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Az imént"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index c808fe7..f811312c 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>-ին"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Տևողություն"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Հարցնել ամեն անգամ"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Մինչև չանջատեք"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Հենց նոր"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index e4b12e4..39a88e5 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"pada <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Durasi"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Selalu tanya"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Sampai Anda menonaktifkannya"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Baru saja"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 61510c2..afb10a9 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"á/í <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Lengd"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Spyrja í hvert skipti"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Þar til þú slekkur"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Rétt í þessu"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 546495b..24eef7a 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"il giorno <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Durata"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Chiedi ogni volta"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Fino alla disattivazione"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Adesso"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 015487a..e9c44c9 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -451,5 +451,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"ב-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"משך"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"שאל בכל פעם"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"עד הכיבוי"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"הרגע"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 2c43d33..0cc2d17 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -141,7 +141,7 @@
     <string name="launch_defaults_some" msgid="313159469856372621">"一部デフォルトで設定"</string>
     <string name="launch_defaults_none" msgid="4241129108140034876">"デフォルトの設定なし"</string>
     <string name="tts_settings" msgid="8186971894801348327">"テキスト読み上げの設定"</string>
-    <string name="tts_settings_title" msgid="1237820681016639683">"テキスト読み上げの出力"</string>
+    <string name="tts_settings_title" msgid="1237820681016639683">"テキスト読み上げの設定"</string>
     <string name="tts_default_rate_title" msgid="6030550998379310088">"音声の速度"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"テキストの読み上げ速度"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"音の高さ"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"期間"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"毎回確認"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"OFF にするまで"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"たった今"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index bd09bf1..daca5b9 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"ხანგრძლივობა"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ყოველთვის მკითხეთ"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"გამორთვამდე"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ახლახან"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 005ee6d..b95d6e9e 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"Уақыты: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Ұзақтығы"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Әрдайым сұрау"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Өшірілгенге дейін"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Дәл қазір"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index d90a89f..5bf38c0 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"នៅ​ថ្ងៃ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"រយៈពេល"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"សួរគ្រប់ពេល"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"រហូតទាល់តែ​អ្នកបិទ"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"អម្បាញ់មិញ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index af7890e..923547f 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> ಕ್ಕೆ"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"ಅವಧಿ"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ಪ್ರತಿ ಬಾರಿ ಕೇಳಿ"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೆ"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ಇದೀಗ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 14ce137..9bac29d 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"일시: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"지속 시간"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"항상 확인"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"사용 중지할 때까지"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"조금 전"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 109c47e..523fabe 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Узактыгы"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ар дайым суралсын"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Бул функция өчүрүлгөнгө чейин"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Азыр эле"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 4034a7e..f85a691 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"ເວລາ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"ໄລຍະເວລາ"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ຖາມທຸກເທື່ອ"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"ຈົນກວ່າທ່ານຈະປິດ"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ຕອນນີ້"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index c974812..fc2924f 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -451,5 +451,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trukmė"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Klausti kaskart"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Kol išjungsite"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Ką tik"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 80aa917..6ce5e8e 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -450,5 +450,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Ilgums"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Vaicāt katru reizi"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Līdz brīdim, kad izslēgsiet"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Tikko"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 534dc2a..c6c508e 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"во <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Времетраење"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Секогаш прашувај"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Додека не го исклучите"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Неодамнешни"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 01d7107..6b6462c 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>-ന്"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"ദൈർഘ്യം"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"എപ്പോഴും ചോദിക്കുക"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"നിങ്ങൾ ഓഫാക്കുന്നത് വരെ"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ഇപ്പോൾ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 960f3e1..56f1cc0 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>-д"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Хугацаа"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Тухай бүрт асуух"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Таныг унтраах хүртэл"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Дөнгөж сая"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 6e89a84..7485886 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> रोजी"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"कालावधी"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"प्रत्येक वेळी विचारा"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"तुम्ही बंद करेपर्यंत"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"आत्ताच"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index f3f9eb6..fdb8702 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"pada <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Tempoh"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Tanya setiap kali"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Sehingga anda matikan"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Sebentar tadi"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index adae0d2..dc5d924 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> တွင်"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"ကြာချိန်"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"အမြဲမေးပါ"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"သင်ပိတ်လိုက်သည် အထိ"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ယခုလေးတင်"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 7f9f4a6..460eb57 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -307,7 +307,7 @@
     <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Slå på GPU-feilsøkingslag"</string>
     <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Tillat GPU-feilsøkingslag for feilsøkingsapper"</string>
     <string name="window_animation_scale_title" msgid="6162587588166114700">"Animasjonsskala for vindu"</string>
-    <string name="transition_animation_scale_title" msgid="387527540523595875">"Overgangsanimasjonsskala"</string>
+    <string name="transition_animation_scale_title" msgid="387527540523595875">"Animasjonsskala for overgang"</string>
     <string name="animator_duration_scale_title" msgid="3406722410819934083">"Varighetsskala for animasjon"</string>
     <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simulering av sekundærskjermer"</string>
     <string name="debug_applications_category" msgid="4206913653849771549">"Apper"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Varighet"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Spør hver gang"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Til du slår av"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Nå nettopp"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 3e2afed..763b60c 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -320,7 +320,7 @@
     <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"अनुप्रयोगले कुनै मान्य च्यानल बिना सूचना पोस्ट गर्दा स्क्रिनमा चेतावनी देखाउँछ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यमा बल प्रयोगको अनुमति प्राप्त अनुप्रयोगहरू"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"म्यानिफेेस्टका मानहरूको ख्याल नगरी कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न सकिने खाले बनाउँछ"</string>
-    <string name="force_resizable_activities" msgid="8615764378147824985">"गतिविधिहरू रिसाइज गर्नको लागि बाध्य गर्नुहोस्"</string>
+    <string name="force_resizable_activities" msgid="8615764378147824985">"आकार बदल्न योग्य हुने बनाउन गतिविधिहरूलाई बाध्यात्मक बनाउनुहोस्।"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"म्यानिफेेस्ट मानहरूको ख्याल नगरी, बहु-विन्डोको लागि सबै रिसाइज गर्न सकिने गतिविधिहरू बनाउनुहोस्।"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"फ्रिफर्म विन्डोहरू सक्रिय गर्नुहोस्"</string>
     <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रयोगात्मक फ्रिफर्म विन्डोहरूका लागि समर्थन सक्रिय गर्नुहोस्।"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> मा"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"अवधि"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"प्रत्येक पटक सोध्नुहोस्"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"तपाईंले निष्क्रिय नपार्दासम्म"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"अहिले भर्खरै"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 41ba2b0..264427e 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -102,7 +102,7 @@
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Koppelen"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOPPELEN"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuleren"</string>
-    <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Koppelen verleent toegang tot je contacten en oproepgeschiedenis wanneer de apparaten zijn verbonden."</string>
+    <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Koppelen verleent toegang tot je contacten en gespreksgeschiedenis wanneer de apparaten zijn verbonden."</string>
     <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Kan niet koppelen aan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Kan niet koppelen aan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> vanwege een onjuiste pincode of toegangscode."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Kan niet communiceren met <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
@@ -306,8 +306,8 @@
     <string name="track_frame_time" msgid="6094365083096851167">"HWUI-weergave van profiel"</string>
     <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"GPU-foutopsporingslagen inschakelen"</string>
     <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Laden van GPU-foutopsporingslagen toestaan voor foutopsporingsapps"</string>
-    <string name="window_animation_scale_title" msgid="6162587588166114700">"Vensteranimatieschaal"</string>
-    <string name="transition_animation_scale_title" msgid="387527540523595875">"Overgangsanimatieschaal"</string>
+    <string name="window_animation_scale_title" msgid="6162587588166114700">"Venster­animatieschaal"</string>
+    <string name="transition_animation_scale_title" msgid="387527540523595875">"Overgangs­animatieschaal"</string>
     <string name="animator_duration_scale_title" msgid="3406722410819934083">"Duur van animatieschaal"</string>
     <string name="overlay_display_devices_title" msgid="5364176287998398539">"Secundaire displays simuleren"</string>
     <string name="debug_applications_category" msgid="4206913653849771549">"Apps"</string>
@@ -371,10 +371,10 @@
     <string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend op basis van je gebruik"</string>
     <string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend op basis van je gebruik (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend"</string>
-    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Is nog genoeg voor ongeveer <xliff:g id="TIME">%1$s</xliff:g> op basis van je gebruik (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Is nog genoeg voor ongeveer <xliff:g id="TIME">%1$s</xliff:g> op basis van je gebruik"</string>
-    <string name="power_discharge_by" msgid="6453537733650125582">"Is nog genoeg voor ongeveer <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only" msgid="107616694963545745">"Is nog genoeg voor ongeveer <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g> op basis van je gebruik (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
+    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g> op basis van je gebruik"</string>
+    <string name="power_discharge_by" msgid="6453537733650125582">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
+    <string name="power_discharge_by_only" msgid="107616694963545745">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minder dan <xliff:g id="THRESHOLD">%1$s</xliff:g> resterend"</string>
     <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Minder dan <xliff:g id="THRESHOLD">%1$s</xliff:g> resterend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Meer dan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"op <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duur"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Altijd vragen"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Totdat je uitschakelt"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Zojuist"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 987d075..ecdc49e 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> ବେଳେ"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"ଅବଧି"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ପ୍ରତ୍ୟେକ ଥର ପଚାରନ୍ତୁ"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"ଆପଣ ବନ୍ଦ ନକରିବା ପର୍ଯ୍ୟନ୍ତ DND ଅନ୍‌ ରହିବ"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ଏହିକ୍ଷଣି"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 995ebfe..63c88cd 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"ਮਿਆਦ"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ਹਰ ਵਾਰ ਪੁੱਛੋ"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਬੰਦ ਨਹੀਂ ਕਰਦੇ"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ਹੁਣੇ ਹੀ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 7ec97b5..7c3da21 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -194,7 +194,7 @@
     <string name="clear_adb_keys" msgid="4038889221503122743">"Odwołaj dostęp do debugowania USB"</string>
     <string name="bugreport_in_power" msgid="7923901846375587241">"Skrót do zgłoszenia błędu"</string>
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Pokaż w menu zasilania przycisk zgłaszania błędu"</string>
-    <string name="keep_screen_on" msgid="1146389631208760344">"Pozostaw ekran włączony"</string>
+    <string name="keep_screen_on" msgid="1146389631208760344">"Pozostaw włączony ekran"</string>
     <string name="keep_screen_on_summary" msgid="2173114350754293009">"Ekran nie będzie gaszony podczas ładowania telefonu"</string>
     <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Włącz dziennik snoop Bluetooth HCI"</string>
     <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"Przechwyć wszystkie pakiety Bluetooth HCI do pliku (przełącz Bluetooth po zmianie tego ustawienia)"</string>
@@ -451,5 +451,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"w: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Czas"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Zawsze pytaj"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Dopóki nie wyłączysz"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Przed chwilą"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index dfdc09c..563698a 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -160,11 +160,11 @@
   </string-array>
   <string-array name="select_logd_size_summaries">
     <item msgid="6921048829791179331">"Desativado"</item>
-    <item msgid="2969458029344750262">"64 K/buffer de log"</item>
-    <item msgid="1342285115665698168">"256 K/buffer de log"</item>
-    <item msgid="1314234299552254621">"1 M/buffer de log"</item>
-    <item msgid="3606047780792894151">"4 M/buffer de log"</item>
-    <item msgid="5431354956856655120">"16 M/buffer de log"</item>
+    <item msgid="2969458029344750262">"64 K/buffer de registro"</item>
+    <item msgid="1342285115665698168">"256 K/buffer de registro"</item>
+    <item msgid="1314234299552254621">"1 M/buffer de registro"</item>
+    <item msgid="3606047780792894151">"4 M/buffer de registro"</item>
+    <item msgid="5431354956856655120">"16 M/buffer de registro"</item>
   </string-array>
   <string-array name="select_logpersist_titles">
     <item msgid="1744840221860799971">"Desativado"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index dd623d0..192e532 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -196,7 +196,7 @@
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
     <string name="keep_screen_on" msgid="1146389631208760344">"Permanecer ativo"</string>
     <string name="keep_screen_on_summary" msgid="2173114350754293009">"A tela nunca entrará em suspensão enquanto estiver carregando."</string>
-    <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Ativar log de rastreamento Bluetooth HCI"</string>
+    <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Ativar registro de rastreamento Bluetooth HCI"</string>
     <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"Capturar todos os pacotes Bluetooth HCI em um arquivo (ative o Bluetooth depois de alterar esta configuração)"</string>
     <string name="oem_unlock_enable" msgid="6040763321967327691">"Desbloqueio de OEM"</string>
     <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Permitir que o bootloader seja desbloqueado"</string>
@@ -239,7 +239,7 @@
     <string name="wifi_metered_label" msgid="4514924227256839725">"Limitada"</string>
     <string name="wifi_unmetered_label" msgid="6124098729457992931">"Ilimitada"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
-    <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
+    <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de registro"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Limpar armazenamento de logger constante?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Quando não estivermos mais monitorando com o logger constante, devemos limpar o residente de dados de logger do seu dispositivo."</string>
     <string name="select_logpersist_title" msgid="7530031344550073166">"Armazenar dados de logger constantemente no dispositivo"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duração"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Perguntar sempre"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Até você desativar"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Agora"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index ce40198..01bc0fc 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"no(a) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duração"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Perguntar sempre"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Até ser desativado"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Agora mesmo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index dfdc09c..563698a 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -160,11 +160,11 @@
   </string-array>
   <string-array name="select_logd_size_summaries">
     <item msgid="6921048829791179331">"Desativado"</item>
-    <item msgid="2969458029344750262">"64 K/buffer de log"</item>
-    <item msgid="1342285115665698168">"256 K/buffer de log"</item>
-    <item msgid="1314234299552254621">"1 M/buffer de log"</item>
-    <item msgid="3606047780792894151">"4 M/buffer de log"</item>
-    <item msgid="5431354956856655120">"16 M/buffer de log"</item>
+    <item msgid="2969458029344750262">"64 K/buffer de registro"</item>
+    <item msgid="1342285115665698168">"256 K/buffer de registro"</item>
+    <item msgid="1314234299552254621">"1 M/buffer de registro"</item>
+    <item msgid="3606047780792894151">"4 M/buffer de registro"</item>
+    <item msgid="5431354956856655120">"16 M/buffer de registro"</item>
   </string-array>
   <string-array name="select_logpersist_titles">
     <item msgid="1744840221860799971">"Desativado"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index dd623d0..192e532 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -196,7 +196,7 @@
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
     <string name="keep_screen_on" msgid="1146389631208760344">"Permanecer ativo"</string>
     <string name="keep_screen_on_summary" msgid="2173114350754293009">"A tela nunca entrará em suspensão enquanto estiver carregando."</string>
-    <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Ativar log de rastreamento Bluetooth HCI"</string>
+    <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Ativar registro de rastreamento Bluetooth HCI"</string>
     <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"Capturar todos os pacotes Bluetooth HCI em um arquivo (ative o Bluetooth depois de alterar esta configuração)"</string>
     <string name="oem_unlock_enable" msgid="6040763321967327691">"Desbloqueio de OEM"</string>
     <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Permitir que o bootloader seja desbloqueado"</string>
@@ -239,7 +239,7 @@
     <string name="wifi_metered_label" msgid="4514924227256839725">"Limitada"</string>
     <string name="wifi_unmetered_label" msgid="6124098729457992931">"Ilimitada"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
-    <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
+    <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de registro"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Limpar armazenamento de logger constante?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Quando não estivermos mais monitorando com o logger constante, devemos limpar o residente de dados de logger do seu dispositivo."</string>
     <string name="select_logpersist_title" msgid="7530031344550073166">"Armazenar dados de logger constantemente no dispositivo"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Duração"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Perguntar sempre"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Até você desativar"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Agora"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index e4a341a..7935a2a 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -22,7 +22,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <string-array name="wifi_status">
     <item msgid="1922181315419294640"></item>
-    <item msgid="8934131797783724664">"În curs de scanare..."</item>
+    <item msgid="8934131797783724664">"Se caută..."</item>
     <item msgid="8513729475867537913">"Se conectează..."</item>
     <item msgid="515055375277271756">"În curs de autentificare…"</item>
     <item msgid="1943354004029184381">"Se obține adresa IP..."</item>
@@ -36,7 +36,7 @@
   </string-array>
   <string-array name="wifi_status_with_ssid">
     <item msgid="7714855332363650812"></item>
-    <item msgid="8878186979715711006">"În curs de scanare..."</item>
+    <item msgid="8878186979715711006">"Se caută..."</item>
     <item msgid="355508996603873860">"Se conectează la <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
     <item msgid="554971459996405634">"Se autentifică cu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="7928343808033020343">"Se obține adresa IP de la <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index b53a3e3..cc74bd3 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -450,5 +450,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Durată"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Întreabă de fiecare dată"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Până când dezactivați"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Chiar acum"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index a421c72..5e1869f 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -451,5 +451,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Длительность"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Всегда спрашивать"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Пока вы не отключите"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Только что"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 6916787..1be890b 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>හිදී"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"කාල සීමාව"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"සෑම විටම ඉල්ලන්න"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"ඔබ ක්‍රියාවිරහිත කරන තුරු"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"මේ දැන්"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index fc30b70..d1ec450 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -451,5 +451,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"o <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trvanie"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Vždy sa opýtať"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Dokiaľ túto funkciu nevypnete"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Teraz"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 458f7f1..4632550 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -451,5 +451,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"v <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trajanje"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Vedno vprašaj"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Dokler ne izklopite"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Pravkar"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index cab1201..24cdcb1 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"ditën <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Kohëzgjatja"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pyet çdo herë"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Deri sa ta çaktivizosh"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Pikërisht tani"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index d2ebb18..ebefc65 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -450,5 +450,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Трајање"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Увек питај"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Док не искључите"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Управо сада"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 0f33159..040aea6 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -306,8 +306,8 @@
     <string name="track_frame_time" msgid="6094365083096851167">"Profilens HWUI-rendering"</string>
     <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Aktivera GPU-felsökningslager"</string>
     <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Tillåt att felsökningsappar läser in GPU-felsökningslager"</string>
-    <string name="window_animation_scale_title" msgid="6162587588166114700">"Skala, fönsteranimering"</string>
-    <string name="transition_animation_scale_title" msgid="387527540523595875">"Skala, övergångsanimering"</string>
+    <string name="window_animation_scale_title" msgid="6162587588166114700">"Skala – fönsteranimering"</string>
+    <string name="transition_animation_scale_title" msgid="387527540523595875">"Skala – övergångsanimering"</string>
     <string name="animator_duration_scale_title" msgid="3406722410819934083">"Längdskala för Animator"</string>
     <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simulera sekundär skärm"</string>
     <string name="debug_applications_category" msgid="4206913653849771549">"Appar"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"på <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Varaktighet"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Fråga varje gång"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Tills du inaktiverar funktionen"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Nyss"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 2d752ea..8be74eacf 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"siku ya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Muda"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Uliza kila wakati"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Hadi utakapoizima"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Sasa hivi"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 7b69c78..54adf82 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -22,7 +22,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <string-array name="wifi_status">
     <item msgid="1922181315419294640"></item>
-    <item msgid="8934131797783724664">"ஸ்கேன் செய்கிறது…"</item>
+    <item msgid="8934131797783724664">"தேடுகிறது..."</item>
     <item msgid="8513729475867537913">"இணைக்கிறது..."</item>
     <item msgid="515055375277271756">"அங்கீகரிக்கிறது..."</item>
     <item msgid="1943354004029184381">"IP முகவரியைப் பெறுகிறது…"</item>
@@ -36,7 +36,7 @@
   </string-array>
   <string-array name="wifi_status_with_ssid">
     <item msgid="7714855332363650812"></item>
-    <item msgid="8878186979715711006">"ஸ்கேன் செய்கிறது…"</item>
+    <item msgid="8878186979715711006">"தேடுகிறது..."</item>
     <item msgid="355508996603873860">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> இல் இணைக்கிறது…"</item>
     <item msgid="554971459996405634">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> உடன் அங்கீகரிக்கிறது…"</item>
     <item msgid="7928343808033020343">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> இலிருந்து IP முகவரியைப் பெறுகிறது…"</item>
@@ -180,30 +180,30 @@
   </string-array>
   <string-array name="window_animation_scale_entries">
     <item msgid="8134156599370824081">"அனிமேஷனை முடக்கு"</item>
-    <item msgid="6624864048416710414">"அனிமேஷன் அளவு .5x"</item>
-    <item msgid="2219332261255416635">"அனிமேஷன் அளவு 1x"</item>
-    <item msgid="3544428804137048509">"அனிமேஷன் அளவு 1.5x"</item>
-    <item msgid="3110710404225974514">"அனிமேஷன் அளவு 2x"</item>
-    <item msgid="4402738611528318731">"அனிமேஷன் அளவு 5x"</item>
-    <item msgid="6189539267968330656">"அனிமேஷன் அளவு 10x"</item>
+    <item msgid="6624864048416710414">"அனிமேஷன் வேகம் .5x"</item>
+    <item msgid="2219332261255416635">"அனிமேஷன் வேகம் 1x"</item>
+    <item msgid="3544428804137048509">"அனிமேஷன் வேகம் 1.5x"</item>
+    <item msgid="3110710404225974514">"அனிமேஷன் வேகம் 2x"</item>
+    <item msgid="4402738611528318731">"அனிமேஷன் வேகம் 5x"</item>
+    <item msgid="6189539267968330656">"அனிமேஷன் வேகம் 10x"</item>
   </string-array>
   <string-array name="transition_animation_scale_entries">
     <item msgid="8464255836173039442">"அனிமேஷனை முடக்கு"</item>
-    <item msgid="3375781541913316411">"அனிமேஷன் அளவு .5x"</item>
-    <item msgid="1991041427801869945">"அனிமேஷன் அளவு 1x"</item>
-    <item msgid="4012689927622382874">"அனிமேஷன் அளவு 1.5x"</item>
-    <item msgid="3289156759925947169">"அனிமேஷன் அளவு 2x"</item>
-    <item msgid="7705857441213621835">"அனிமேஷன் அளவு 5x"</item>
-    <item msgid="6660750935954853365">"அனிமேஷன் அளவு 10x"</item>
+    <item msgid="3375781541913316411">"அனிமேஷன் வேகம் .5x"</item>
+    <item msgid="1991041427801869945">"அனிமேஷன் வேகம் 1x"</item>
+    <item msgid="4012689927622382874">"அனிமேஷன் வேகம் 1.5x"</item>
+    <item msgid="3289156759925947169">"அனிமேஷன் வேகம் 2x"</item>
+    <item msgid="7705857441213621835">"அனிமேஷன் வேகம் 5x"</item>
+    <item msgid="6660750935954853365">"அனிமேஷன் வேகம் 10x"</item>
   </string-array>
   <string-array name="animator_duration_scale_entries">
     <item msgid="6039901060648228241">"அனிமேஷனை முடக்கு"</item>
-    <item msgid="1138649021950863198">"அனிமேஷன் அளவு .5x"</item>
-    <item msgid="4394388961370833040">"அனிமேஷன் அளவு 1x"</item>
-    <item msgid="8125427921655194973">"அனிமேஷன் அளவு 1.5x"</item>
-    <item msgid="3334024790739189573">"அனிமேஷன் அளவு 2x"</item>
-    <item msgid="3170120558236848008">"அனிமேஷன் அளவு 5x"</item>
-    <item msgid="1069584980746680398">"அனிமேஷன் அளவு 10x"</item>
+    <item msgid="1138649021950863198">"அனிமேஷன் வேகம் .5x"</item>
+    <item msgid="4394388961370833040">"அனிமேஷன் வேகம் 1x"</item>
+    <item msgid="8125427921655194973">"அனிமேஷன் வேகம் 1.5x"</item>
+    <item msgid="3334024790739189573">"அனிமேஷன் வேகம் 2x"</item>
+    <item msgid="3170120558236848008">"அனிமேஷன் வேகம் 5x"</item>
+    <item msgid="1069584980746680398">"அனிமேஷன் வேகம் 10x"</item>
   </string-array>
   <string-array name="overlay_display_devices_entries">
     <item msgid="1606809880904982133">"ஏதுமில்லை"</item>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 828e542..225005d 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -306,8 +306,8 @@
     <string name="track_frame_time" msgid="6094365083096851167">"சுயவிவர HWUI ரெண்டரிங்"</string>
     <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"GPU பிழைத்திருத்த லேயர்களை இயக்கு"</string>
     <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"பிழைத்திருத்த ஆப்ஸிற்கு, GPU பிழைத்திருத்த லேயர்களை ஏற்றுவதற்கு அனுமதி"</string>
-    <string name="window_animation_scale_title" msgid="6162587588166114700">"சாளர அனிமேஷன் அளவு"</string>
-    <string name="transition_animation_scale_title" msgid="387527540523595875">"அனிமேஷன் மாற்றத்தின் அளவு"</string>
+    <string name="window_animation_scale_title" msgid="6162587588166114700">"சாளர அனிமேஷன் வேகம்"</string>
+    <string name="transition_animation_scale_title" msgid="387527540523595875">"அனிமேஷன் மாற்றத்தின் வேகம்"</string>
     <string name="animator_duration_scale_title" msgid="3406722410819934083">"அனிமேட்டர் கால அளவு"</string>
     <string name="overlay_display_devices_title" msgid="5364176287998398539">"இரண்டாம்நிலைக் காட்சிகளை உருவகப்படுத்து"</string>
     <string name="debug_applications_category" msgid="4206913653849771549">"ஆப்ஸ்"</string>
@@ -358,7 +358,7 @@
     <string name="picture_color_mode" msgid="4560755008730283695">"படத்தின் வண்ணப் பயன்முறை"</string>
     <string name="picture_color_mode_desc" msgid="1141891467675548590">"sRGBஐப் பயன்படுத்தும்"</string>
     <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"முடக்கப்பட்டது"</string>
-    <string name="daltonizer_mode_monochromacy" msgid="8485709880666106721">"மோனோகுரோமசி"</string>
+    <string name="daltonizer_mode_monochromacy" msgid="8485709880666106721">"ஒற்றை நிறத் தன்மை"</string>
     <string name="daltonizer_mode_deuteranomaly" msgid="5475532989673586329">"நிறம் அடையாளங்காண முடியாமை (சிவப்பு-பச்சை)"</string>
     <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"நிறம் அடையாளங்காண முடியாமை (சிவப்பு-பச்சை)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"நிறம் அடையாளங்காண முடியாமை (நீலம்-மஞ்சள்)"</string>
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"அலாரம்: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"கால அளவு"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ஒவ்வொரு முறையும் கேள்"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"ஆஃப் செய்யும் வரை"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"சற்றுமுன்"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index c30b9cd..531001c 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>కి"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"వ్యవధి"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ప్రతిసారి అడుగు"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"మీరు ఆఫ్‌ చేసే వరకు"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ఇప్పుడే"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index b937a7d..cf214e1 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"วัน<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"ระยะเวลา"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ถามทุกครั้ง"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"จนกว่าคุณจะปิด"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"เมื่อสักครู่"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 2e62dc0..aee95ea 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"sa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Tagal"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Magtanong palagi"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Hanggang sa i-off mo"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Ngayon lang"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 0995a80..e4b23f96 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"zaman: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Süre"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Her zaman sor"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Siz kapatana kadar"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Az önce"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 06fe036..958a3d2 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -451,5 +451,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Тривалість"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Запитувати щоразу"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Доки ви не вимкнете"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Щойно"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 6b33df7..31f0a33 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g> بجے"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"مدت"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ہر بار پوچھیں"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"یہاں تک کہ آپ آف کر دیں"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"ابھی ابھی"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index fdb6bb6..7ff4588 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Davomiyligi"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Har safar so‘ralsin"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Bekor qilinmaguncha"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Hozir"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 8872108..daa9335 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"vào <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Thời lượng"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Luôn hỏi"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Cho đến khi bạn tắt"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Vừa xong"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index addad73..6cb27e9 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"时间:<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"持续时间"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"每次都询问"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"直到您将其关闭"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"刚刚"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 8054548..16039c1 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"時間:<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"持續時間"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"每次都詢問"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"直至您關閉為止"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"剛剛"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 95d8b5d..ed68638 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"時間:<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"時間長度"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"每次都詢問"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"直到你關閉為止"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"剛剛"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 541c588..957584a 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -449,5 +449,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"nge-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Ubude besikhathi"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Buza njalo"</string>
+    <string name="zen_mode_forever" msgid="2704305038191592967">"Uze uvale isikrini"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"Khona manje"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 7788f7e..6bc07c2 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1117,7 +1117,10 @@
     <string name="zen_mode_duration_settings_title">Duration</string>
     <!-- Do not disturb: Duration option to always prompt for the duration of dnd -->
     <string name="zen_mode_duration_always_prompt_title">Ask every time</string>
+    <!-- Do not disturb: Duration option to always have DND on until it is manually turned off [CHAR LIMIT=60] -->
+    <string name="zen_mode_forever">Until you turn off</string>
 
     <!-- time label for event have that happened very recently [CHAR LIMIT=60] -->
     <string name="time_unit_just_now">Just now</string>
-</resources>
+
+  </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreferenceCompat.java b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreferenceCompat.java
new file mode 100644
index 0000000..6ac9d4e
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreferenceCompat.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.DialogPreference;
+import androidx.preference.PreferenceDialogFragmentCompat;
+
+public class CustomDialogPreferenceCompat extends DialogPreference {
+
+    private CustomPreferenceDialogFragment mFragment;
+    private DialogInterface.OnShowListener mOnShowListener;
+
+    public CustomDialogPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public CustomDialogPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public CustomDialogPreferenceCompat(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public CustomDialogPreferenceCompat(Context context) {
+        super(context);
+    }
+
+    public boolean isDialogOpen() {
+        return getDialog() != null && getDialog().isShowing();
+    }
+
+    public Dialog getDialog() {
+        return mFragment != null ? mFragment.getDialog() : null;
+    }
+
+    public void setOnShowListener(DialogInterface.OnShowListener listner) {
+        mOnShowListener = listner;
+    }
+
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
+            DialogInterface.OnClickListener listener) {
+    }
+
+    protected void onDialogClosed(boolean positiveResult) {
+    }
+
+    protected void onClick(DialogInterface dialog, int which) {
+    }
+
+    protected void onBindDialogView(View view) {
+    }
+
+    private void setFragment(CustomPreferenceDialogFragment fragment) {
+        mFragment = fragment;
+    }
+
+    private DialogInterface.OnShowListener getOnShowListener() {
+        return mOnShowListener;
+    }
+
+    public static class CustomPreferenceDialogFragment extends PreferenceDialogFragmentCompat {
+
+        public static CustomPreferenceDialogFragment newInstance(String key) {
+            final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment();
+            final Bundle b = new Bundle(1);
+            b.putString(ARG_KEY, key);
+            fragment.setArguments(b);
+            return fragment;
+        }
+
+        private CustomDialogPreferenceCompat getCustomizablePreference() {
+            return (CustomDialogPreferenceCompat) getPreference();
+        }
+
+        @Override
+        protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+            super.onPrepareDialogBuilder(builder);
+            getCustomizablePreference().setFragment(this);
+            getCustomizablePreference().onPrepareDialogBuilder(builder, this);
+        }
+
+        @Override
+        public void onDialogClosed(boolean positiveResult) {
+            getCustomizablePreference().onDialogClosed(positiveResult);
+        }
+
+        @Override
+        protected void onBindDialogView(View view) {
+            super.onBindDialogView(view);
+            getCustomizablePreference().onBindDialogView(view);
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            final Dialog dialog = super.onCreateDialog(savedInstanceState);
+            dialog.setOnShowListener(getCustomizablePreference().getOnShowListener());
+            return dialog;
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            super.onClick(dialog, which);
+            getCustomizablePreference().onClick(dialog, which);
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreferenceCompat.java b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreferenceCompat.java
new file mode 100644
index 0000000..6ddc89a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreferenceCompat.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import static android.text.InputType.TYPE_CLASS_TEXT;
+import static android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.EditText;
+
+import androidx.annotation.CallSuper;
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.EditTextPreference;
+import androidx.preference.EditTextPreferenceDialogFragmentCompat;
+
+public class CustomEditTextPreferenceCompat extends EditTextPreference {
+
+    private CustomPreferenceDialogFragment mFragment;
+
+    public CustomEditTextPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public CustomEditTextPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public CustomEditTextPreferenceCompat(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public CustomEditTextPreferenceCompat(Context context) {
+        super(context);
+    }
+
+    public EditText getEditText() {
+        if (mFragment != null) {
+            final Dialog dialog = mFragment.getDialog();
+            if (dialog != null) {
+                return (EditText) dialog.findViewById(android.R.id.edit);
+            }
+        }
+        return null;
+    }
+
+    public boolean isDialogOpen() {
+        return getDialog() != null && getDialog().isShowing();
+    }
+
+    public Dialog getDialog() {
+        return mFragment != null ? mFragment.getDialog() : null;
+    }
+
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
+            DialogInterface.OnClickListener listener) {
+    }
+
+    protected void onDialogClosed(boolean positiveResult) {
+    }
+
+    protected void onClick(DialogInterface dialog, int which) {
+    }
+
+    @CallSuper
+    protected void onBindDialogView(View view) {
+        final EditText editText = view.findViewById(android.R.id.edit);
+        if (editText != null) {
+            editText.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_SENTENCES);
+            editText.requestFocus();
+        }
+    }
+
+    private void setFragment(CustomPreferenceDialogFragment fragment) {
+        mFragment = fragment;
+    }
+
+    public static class CustomPreferenceDialogFragment extends
+            EditTextPreferenceDialogFragmentCompat {
+
+        public static CustomPreferenceDialogFragment newInstance(String key) {
+            final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment();
+            final Bundle b = new Bundle(1);
+            b.putString(ARG_KEY, key);
+            fragment.setArguments(b);
+            return fragment;
+        }
+
+        private CustomEditTextPreferenceCompat getCustomizablePreference() {
+            return (CustomEditTextPreferenceCompat) getPreference();
+        }
+
+        @Override
+        protected void onBindDialogView(View view) {
+            super.onBindDialogView(view);
+            getCustomizablePreference().onBindDialogView(view);
+        }
+
+        @Override
+        protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+            super.onPrepareDialogBuilder(builder);
+            getCustomizablePreference().setFragment(this);
+            getCustomizablePreference().onPrepareDialogBuilder(builder, this);
+        }
+
+        @Override
+        public void onDialogClosed(boolean positiveResult) {
+            super.onDialogClosed(positiveResult);
+            getCustomizablePreference().onDialogClosed(positiveResult);
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            super.onClick(dialog, which);
+            getCustomizablePreference().onClick(dialog, which);
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 01efda5..a710410 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -42,7 +42,6 @@
     private BluetoothA2dp mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
 
     static final ParcelUuid[] SINK_UUIDS = {
@@ -71,7 +70,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "A2dpProfile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(A2dpProfile.this, BluetoothProfile.STATE_CONNECTED);
                 device.refresh();
@@ -94,14 +93,12 @@
         return BluetoothProfile.A2DP;
     }
 
-    A2dpProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    A2dpProfile(Context context, CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
         mContext = context;
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        mLocalAdapter.getProfileProxy(context, new A2dpServiceListener(),
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new A2dpServiceListener(),
                 BluetoothProfile.A2DP);
     }
 
@@ -123,20 +120,6 @@
 
     public boolean connect(BluetoothDevice device) {
         if (mService == null) return false;
-        int max_connected_devices = mLocalAdapter.getMaxConnectedAudioDevices();
-        if (max_connected_devices == 1) {
-            // Original behavior: disconnect currently connected device
-            List<BluetoothDevice> sinks = getConnectedDevices();
-            if (sinks != null) {
-                for (BluetoothDevice sink : sinks) {
-                    if (sink.equals(device)) {
-                        Log.w(TAG, "Connecting to device " + device + " : disconnect skipped");
-                        continue;
-                    }
-                    mService.disconnect(sink);
-                }
-            }
-        }
         return mService.connect(device);
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
index 2cf1d58..0c4e02b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
@@ -38,7 +38,6 @@
     private BluetoothA2dpSink mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
 
     static final ParcelUuid[] SRC_UUIDS = {
@@ -67,7 +66,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "A2dpSinkProfile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(A2dpSinkProfile.this, BluetoothProfile.STATE_CONNECTED);
                 device.refresh();
@@ -90,13 +89,11 @@
         return BluetoothProfile.A2DP_SINK;
     }
 
-    A2dpSinkProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    A2dpSinkProfile(Context context, CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        mLocalAdapter.getProfileProxy(context, new A2dpSinkServiceListener(),
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new A2dpSinkServiceListener(),
                 BluetoothProfile.A2DP_SINK);
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java
index c7f8c20..a842229 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java
@@ -22,14 +22,108 @@
  * UI to receive events from {@link BluetoothEventManager}.
  */
 public interface BluetoothCallback {
-    void onBluetoothStateChanged(int bluetoothState);
-    void onScanningStateChanged(boolean started);
-    void onDeviceAdded(CachedBluetoothDevice cachedDevice);
-    void onDeviceDeleted(CachedBluetoothDevice cachedDevice);
-    void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState);
-    void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state);
-    void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile);
-    void onAudioModeChanged();
+    /**
+     * It will be called when the state of the local Bluetooth adapter has been changed.
+     * It is listening {@link android.bluetooth.BluetoothAdapter#ACTION_STATE_CHANGED}.
+     * For example, Bluetooth has been turned on or off.
+     *
+     * @param bluetoothState the current Bluetooth state, the possible values are:
+     * {@link android.bluetooth.BluetoothAdapter#STATE_OFF},
+     * {@link android.bluetooth.BluetoothAdapter#STATE_TURNING_ON},
+     * {@link android.bluetooth.BluetoothAdapter#STATE_ON},
+     * {@link android.bluetooth.BluetoothAdapter#STATE_TURNING_OFF}.
+     */
+    default void onBluetoothStateChanged(int bluetoothState) {}
+
+    /**
+     * It will be called when the local Bluetooth adapter has started
+     * or finished the remote device discovery process.
+     * It is listening {@link android.bluetooth.BluetoothAdapter#ACTION_DISCOVERY_STARTED} and
+     * {@link android.bluetooth.BluetoothAdapter#ACTION_DISCOVERY_FINISHED}.
+     *
+     * @param started indicate the current process is started or finished.
+     */
+    default void onScanningStateChanged(boolean started) {}
+
+    /**
+     * It will be called in following situations:
+     * 1. In scanning mode, when a new device has been found.
+     * 2. When a profile service is connected and existing connected devices has been found.
+     * This API only invoked once for each device and all devices will be cached in
+     * {@link CachedBluetoothDeviceManager}.
+     *
+     * @param cachedDevice the Bluetooth device.
+     */
+    default void onDeviceAdded(CachedBluetoothDevice cachedDevice) {}
+
+    /**
+     * It will be called when requiring to remove a remote device from CachedBluetoothDevice list
+     *
+     * @param cachedDevice the Bluetooth device.
+     */
+    default void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {}
+
+    /**
+     * It will be called when bond state of a remote device is changed.
+     * It is listening {@link android.bluetooth.BluetoothDevice#ACTION_BOND_STATE_CHANGED}
+     *
+     * @param cachedDevice the Bluetooth device.
+     * @param bondState the Bluetooth device bond state, the possible values are:
+     * {@link android.bluetooth.BluetoothDevice#BOND_NONE},
+     * {@link android.bluetooth.BluetoothDevice#BOND_BONDING},
+     * {@link android.bluetooth.BluetoothDevice#BOND_BONDED}.
+     */
+    default void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {}
+
+    /**
+     * It will be called in following situations:
+     * 1. When the adapter is not connected to any profiles of any remote devices
+     * and it attempts a connection to a profile.
+     * 2. When the adapter disconnects from the last profile of the last device.
+     * It is listening {@link android.bluetooth.BluetoothAdapter#ACTION_CONNECTION_STATE_CHANGED}
+     *
+     * @param cachedDevice the Bluetooth device.
+     * @param state the Bluetooth device connection state, the possible values are:
+     * {@link android.bluetooth.BluetoothAdapter#STATE_DISCONNECTED},
+     * {@link android.bluetooth.BluetoothAdapter#STATE_CONNECTING},
+     * {@link android.bluetooth.BluetoothAdapter#STATE_CONNECTED},
+     * {@link android.bluetooth.BluetoothAdapter#STATE_DISCONNECTING}.
+     */
+    default void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {}
+
+    /**
+     * It will be called when device been set as active for {@code bluetoothProfile}
+     * It is listening in following intent:
+     * {@link android.bluetooth.BluetoothA2dp#ACTION_ACTIVE_DEVICE_CHANGED}
+     * {@link android.bluetooth.BluetoothHeadset#ACTION_ACTIVE_DEVICE_CHANGED}
+     * {@link android.bluetooth.BluetoothHearingAid#ACTION_ACTIVE_DEVICE_CHANGED}
+     *
+     * @param activeDevice the active Bluetooth device.
+     * @param bluetoothProfile the profile of active Bluetooth device.
+     */
+    default void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {}
+
+    /**
+     * It will be called in following situations:
+     * 1. When the call state on the device is changed.
+     * 2. When the audio connection state of the A2DP profile is changed.
+     * It is listening in following intent:
+     * {@link android.bluetooth.BluetoothHeadset#ACTION_AUDIO_STATE_CHANGED}
+     * {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
+     */
+    default void onAudioModeChanged() {}
+
+    /**
+     * It will be called when one of the bluetooth device profile connection state is changed.
+     *
+     * @param cachedDevice the active Bluetooth device.
+     * @param state the BluetoothProfile connection state, the possible values are:
+     * {@link android.bluetooth.BluetoothProfile#STATE_CONNECTED},
+     * {@link android.bluetooth.BluetoothProfile#STATE_CONNECTING},
+     * {@link android.bluetooth.BluetoothProfile#STATE_DISCONNECTED},
+     * {@link android.bluetooth.BluetoothProfile#STATE_DISCONNECTING}.
+     * @param bluetoothProfile the BluetoothProfile id.
+     */
     default void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice,
             int state, int bluetoothProfile) {
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 7611e52..25e6831 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -49,42 +49,26 @@
 
     private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
-    private LocalBluetoothProfileManager mProfileManager;
     private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter;
     private final Map<String, Handler> mHandlerMap;
-    private Context mContext;
-
-    private final Collection<BluetoothCallback> mCallbacks =
-            new ArrayList<BluetoothCallback>();
+    private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver();
+    private final BroadcastReceiver mProfileBroadcastReceiver = new BluetoothBroadcastReceiver();
+    private final Collection<BluetoothCallback> mCallbacks = new ArrayList<>();
 
     private android.os.Handler mReceiverHandler;
+    private Context mContext;
 
     interface Handler {
         void onReceive(Context context, Intent intent, BluetoothDevice device);
     }
 
-    private void addHandler(String action, Handler handler) {
-        mHandlerMap.put(action, handler);
-        mAdapterIntentFilter.addAction(action);
-    }
-
-    void addProfileHandler(String action, Handler handler) {
-        mHandlerMap.put(action, handler);
-        mProfileIntentFilter.addAction(action);
-    }
-
-    // Set profile manager after construction due to circular dependency
-    void setProfileManager(LocalBluetoothProfileManager manager) {
-        mProfileManager = manager;
-    }
-
     BluetoothEventManager(LocalBluetoothAdapter adapter,
             CachedBluetoothDeviceManager deviceManager, Context context) {
         mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mAdapterIntentFilter = new IntentFilter();
         mProfileIntentFilter = new IntentFilter();
-        mHandlerMap = new HashMap<String, Handler>();
+        mHandlerMap = new HashMap<>();
         mContext = context;
 
         // Bluetooth on/off broadcasts
@@ -97,7 +81,6 @@
         addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
         addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));
         addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
-        addHandler(BluetoothDevice.ACTION_DISAPPEARED, new DeviceDisappearedHandler());
         addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());
         addHandler(BluetoothDevice.ACTION_ALIAS_CHANGED, new NameChangedHandler());
 
@@ -109,16 +92,11 @@
         addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler());
         addHandler(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED, new BatteryLevelChangedHandler());
 
-        // Dock event broadcasts
-        addHandler(Intent.ACTION_DOCK_EVENT, new DockEventHandler());
-
         // Active device broadcasts
-        addHandler(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED,
-                   new ActiveDeviceChangedHandler());
-        addHandler(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED,
-                   new ActiveDeviceChangedHandler());
+        addHandler(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler());
+        addHandler(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler());
         addHandler(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED,
-                   new ActiveDeviceChangedHandler());
+                new ActiveDeviceChangedHandler());
 
         // Headset state changed broadcasts
         addHandler(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
@@ -130,10 +108,6 @@
         mContext.registerReceiver(mProfileBroadcastReceiver, mProfileIntentFilter, null, mReceiverHandler);
     }
 
-    void registerProfileIntentReceiver() {
-        mContext.registerReceiver(mProfileBroadcastReceiver, mProfileIntentFilter, null, mReceiverHandler);
-    }
-
     public void setReceiverHandler(android.os.Handler handler) {
         mContext.unregisterReceiver(mBroadcastReceiver);
         mContext.unregisterReceiver(mProfileBroadcastReceiver);
@@ -156,7 +130,92 @@
         }
     }
 
-    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+    void registerProfileIntentReceiver() {
+        mContext.registerReceiver(mProfileBroadcastReceiver, mProfileIntentFilter, null, mReceiverHandler);
+    }
+
+    void addProfileHandler(String action, Handler handler) {
+        mHandlerMap.put(action, handler);
+        mProfileIntentFilter.addAction(action);
+    }
+
+    boolean readPairedDevices() {
+        Set<BluetoothDevice> bondedDevices = mLocalAdapter.getBondedDevices();
+        if (bondedDevices == null) {
+            return false;
+        }
+
+        boolean deviceAdded = false;
+        for (BluetoothDevice device : bondedDevices) {
+            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+            if (cachedDevice == null) {
+                mDeviceManager.addDevice(device);
+                deviceAdded = true;
+            }
+        }
+
+        return deviceAdded;
+    }
+
+    void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
+        synchronized (mCallbacks) {
+            for (BluetoothCallback callback : mCallbacks) {
+                callback.onDeviceAdded(cachedDevice);
+            }
+        }
+    }
+
+    void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) {
+        synchronized (mCallbacks) {
+            for (BluetoothCallback callback : mCallbacks) {
+                callback.onDeviceDeleted(cachedDevice);
+            }
+        }
+    }
+
+    void dispatchProfileConnectionStateChanged(CachedBluetoothDevice device, int state,
+            int bluetoothProfile) {
+        synchronized (mCallbacks) {
+            for (BluetoothCallback callback : mCallbacks) {
+                callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
+            }
+        }
+        mDeviceManager.onProfileConnectionStateChanged(device, state, bluetoothProfile);
+    }
+
+    private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+        synchronized (mCallbacks) {
+            for (BluetoothCallback callback : mCallbacks) {
+                callback.onConnectionStateChanged(cachedDevice, state);
+            }
+        }
+    }
+
+    private void dispatchAudioModeChanged() {
+        mDeviceManager.dispatchAudioModeChanged();
+        synchronized (mCallbacks) {
+            for (BluetoothCallback callback : mCallbacks) {
+                callback.onAudioModeChanged();
+            }
+        }
+    }
+
+    private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice,
+            int bluetoothProfile) {
+        mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile);
+        synchronized (mCallbacks) {
+            for (BluetoothCallback callback : mCallbacks) {
+                callback.onActiveDeviceChanged(activeDevice, bluetoothProfile);
+            }
+        }
+    }
+
+    private void addHandler(String action, Handler handler) {
+        mHandlerMap.put(action, handler);
+        mAdapterIntentFilter.addAction(action);
+    }
+
+    private class BluetoothBroadcastReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
@@ -168,27 +227,13 @@
                 handler.onReceive(context, intent, device);
             }
         }
-    };
-
-    private final BroadcastReceiver mProfileBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            BluetoothDevice device = intent
-                    .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
-            Handler handler = mHandlerMap.get(action);
-            if (handler != null) {
-                handler.onReceive(context, intent, device);
-            }
-        }
-    };
+    }
 
     private class AdapterStateChangedHandler implements Handler {
         public void onReceive(Context context, Intent intent,
                 BluetoothDevice device) {
             int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
-                                    BluetoothAdapter.ERROR);
+                    BluetoothAdapter.ERROR);
             // Reregister Profile Broadcast Receiver as part of TURN OFF
             if (state == BluetoothAdapter.STATE_OFF)
             {
@@ -229,19 +274,16 @@
         public void onReceive(Context context, Intent intent,
                 BluetoothDevice device) {
             short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
-            BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
             String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
             // TODO Pick up UUID. They should be available for 2.1 devices.
             // Skip for now, there's a bluez problem and we are not getting uuids even for 2.1.
             CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
             if (cachedDevice == null) {
-                cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
+                cachedDevice = mDeviceManager.addDevice(device);
                 Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
                         + cachedDevice);
             }
             cachedDevice.setRssi(rssi);
-            cachedDevice.setBtClass(btClass);
-            cachedDevice.setNewName(name);
             cachedDevice.setJustDiscovered(true);
         }
     }
@@ -256,48 +298,6 @@
         }
     }
 
-    private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
-        synchronized (mCallbacks) {
-            for (BluetoothCallback callback : mCallbacks) {
-                callback.onConnectionStateChanged(cachedDevice, state);
-            }
-        }
-    }
-
-    void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
-        synchronized (mCallbacks) {
-            for (BluetoothCallback callback : mCallbacks) {
-                callback.onDeviceAdded(cachedDevice);
-            }
-        }
-    }
-
-    void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) {
-        synchronized (mCallbacks) {
-            for (BluetoothCallback callback : mCallbacks) {
-                callback.onDeviceDeleted(cachedDevice);
-            }
-        }
-    }
-
-    private class DeviceDisappearedHandler implements Handler {
-        public void onReceive(Context context, Intent intent,
-                BluetoothDevice device) {
-            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
-            if (cachedDevice == null) {
-                Log.w(TAG, "received ACTION_DISAPPEARED for an unknown device: " + device);
-                return;
-            }
-            if (CachedBluetoothDeviceManager.onDeviceDisappeared(cachedDevice)) {
-                synchronized (mCallbacks) {
-                    for (BluetoothCallback callback : mCallbacks) {
-                        callback.onDeviceDeleted(cachedDevice);
-                    }
-                }
-            }
-        }
-    }
-
     private class NameChangedHandler implements Handler {
         public void onReceive(Context context, Intent intent,
                 BluetoothDevice device) {
@@ -313,22 +313,12 @@
                 return;
             }
             int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
-                                               BluetoothDevice.ERROR);
+                    BluetoothDevice.ERROR);
             CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
             if (cachedDevice == null) {
-                Log.w(TAG, "CachedBluetoothDevice for device " + device +
-                        " not found, calling readPairedDevices().");
-                if (readPairedDevices()) {
-                    cachedDevice = mDeviceManager.findDevice(device);
-                }
-
-                if (cachedDevice == null) {
-                    Log.w(TAG, "Got bonding state changed for " + device +
-                            ", but we have no record of that device.");
-
-                    cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
-                    dispatchDeviceAdded(cachedDevice);
-                }
+                Log.w(TAG, "Got bonding state changed for " + device +
+                        ", but we have no record of that device.");
+                cachedDevice = mDeviceManager.addDevice(device);
             }
 
             synchronized (mCallbacks) {
@@ -360,24 +350,24 @@
             int errorMsg;
 
             switch(reason) {
-            case BluetoothDevice.UNBOND_REASON_AUTH_FAILED:
-                errorMsg = R.string.bluetooth_pairing_pin_error_message;
-                break;
-            case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED:
-                errorMsg = R.string.bluetooth_pairing_rejected_error_message;
-                break;
-            case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN:
-                errorMsg = R.string.bluetooth_pairing_device_down_error_message;
-                break;
-            case BluetoothDevice.UNBOND_REASON_DISCOVERY_IN_PROGRESS:
-            case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT:
-            case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS:
-            case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED:
-                errorMsg = R.string.bluetooth_pairing_error_message;
-                break;
-            default:
-                Log.w(TAG, "showUnbondMessage: Not displaying any message for reason: " + reason);
-                return;
+                case BluetoothDevice.UNBOND_REASON_AUTH_FAILED:
+                    errorMsg = R.string.bluetooth_pairing_pin_error_message;
+                    break;
+                case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED:
+                    errorMsg = R.string.bluetooth_pairing_rejected_error_message;
+                    break;
+                case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN:
+                    errorMsg = R.string.bluetooth_pairing_device_down_error_message;
+                    break;
+                case BluetoothDevice.UNBOND_REASON_DISCOVERY_IN_PROGRESS:
+                case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT:
+                case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS:
+                case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED:
+                    errorMsg = R.string.bluetooth_pairing_error_message;
+                    break;
+                default:
+                    Log.w(TAG, "showUnbondMessage: Not displaying any message for reason: " + reason);
+                    return;
             }
             BluetoothUtils.showError(context, name, errorMsg);
         }
@@ -397,22 +387,6 @@
         }
     }
 
-    private class DockEventHandler implements Handler {
-        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
-            // Remove if unpair device upon undocking
-            int anythingButUnDocked = Intent.EXTRA_DOCK_STATE_UNDOCKED + 1;
-            int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, anythingButUnDocked);
-            if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                if (device != null && device.getBondState() == BluetoothDevice.BOND_NONE) {
-                    CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
-                    if (cachedDevice != null) {
-                        cachedDevice.setJustDiscovered(false);
-                    }
-                }
-            }
-        }
-    }
-
     private class BatteryLevelChangedHandler implements Handler {
         public void onReceive(Context context, Intent intent,
                 BluetoothDevice device) {
@@ -423,25 +397,6 @@
         }
     }
 
-    boolean readPairedDevices() {
-        Set<BluetoothDevice> bondedDevices = mLocalAdapter.getBondedDevices();
-        if (bondedDevices == null) {
-            return false;
-        }
-
-        boolean deviceAdded = false;
-        for (BluetoothDevice device : bondedDevices) {
-            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
-            if (cachedDevice == null) {
-                cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
-                dispatchDeviceAdded(cachedDevice);
-                deviceAdded = true;
-            }
-        }
-
-        return deviceAdded;
-    }
-
     private class ActiveDeviceChangedHandler implements Handler {
         @Override
         public void onReceive(Context context, Intent intent, BluetoothDevice device) {
@@ -466,16 +421,6 @@
         }
     }
 
-    private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice,
-                                             int bluetoothProfile) {
-        mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile);
-        synchronized (mCallbacks) {
-            for (BluetoothCallback callback : mCallbacks) {
-                callback.onActiveDeviceChanged(activeDevice, bluetoothProfile);
-            }
-        }
-    }
-
     private class AudioModeChangedHandler implements Handler {
 
         @Override
@@ -488,23 +433,4 @@
             dispatchAudioModeChanged();
         }
     }
-
-    private void dispatchAudioModeChanged() {
-        mDeviceManager.dispatchAudioModeChanged();
-        synchronized (mCallbacks) {
-            for (BluetoothCallback callback : mCallbacks) {
-                callback.onAudioModeChanged();
-            }
-        }
-    }
-
-    void dispatchProfileConnectionStateChanged(CachedBluetoothDevice device, int state,
-            int bluetoothProfile) {
-        synchronized (mCallbacks) {
-            for (BluetoothCallback callback : mCallbacks) {
-                callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
-            }
-        }
-        mDeviceManager.onProfileConnectionStateChanged(device, state, bluetoothProfile);
-    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index b90d307..68e1dfc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -23,7 +23,6 @@
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.media.AudioManager;
 import android.os.ParcelUuid;
 import android.os.SystemClock;
 import android.text.TextUtils;
@@ -49,17 +48,12 @@
     private static final String TAG = "CachedBluetoothDevice";
 
     private final Context mContext;
-    private final LocalBluetoothAdapter mLocalAdapter;
+    private final BluetoothAdapter mLocalAdapter;
     private final LocalBluetoothProfileManager mProfileManager;
-    private final AudioManager mAudioManager;
     private final BluetoothDevice mDevice;
-    //TODO: consider remove, BluetoothDevice.getName() is already cached
-    private String mName;
     private long mHiSyncId;
     // Need this since there is no method for getting RSSI
     private short mRssi;
-    //TODO: consider remove, BluetoothDevice.getBluetoothClass() is already cached
-    private BluetoothClass mBtClass;
     private HashMap<LocalBluetoothProfile, Integer> mProfileConnectionState;
 
     private final List<LocalBluetoothProfile> mProfiles =
@@ -78,14 +72,6 @@
 
     private final Collection<Callback> mCallbacks = new ArrayList<Callback>();
 
-    // Following constants indicate the user's choices of Phone book/message access settings
-    // User hasn't made any choice or settings app has wiped out the memory
-    public final static int ACCESS_UNKNOWN = 0;
-    // User has accepted the connection and let Settings app remember the decision
-    public final static int ACCESS_ALLOWED = 1;
-    // User has rejected the connection and let Settings app remember the decision
-    public final static int ACCESS_REJECTED = 2;
-
     // How many times user should reject the connection to make the choice persist.
     private final static int MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST = 2;
 
@@ -145,7 +131,7 @@
             Log.d(TAG, "onProfileStateChanged: profile " + profile +
                     " newProfileState " + newProfileState);
         }
-        if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF)
+        if (mLocalAdapter.getState() == BluetoothAdapter.STATE_TURNING_OFF)
         {
             if (BluetoothUtils.D) {
                 Log.d(TAG, " BT Turninig Off...Profile conn state change ignored...");
@@ -181,13 +167,11 @@
     }
 
     CachedBluetoothDevice(Context context,
-                          LocalBluetoothAdapter adapter,
                           LocalBluetoothProfileManager profileManager,
                           BluetoothDevice device) {
         mContext = context;
-        mLocalAdapter = adapter;
+        mLocalAdapter = BluetoothAdapter.getDefaultAdapter();
         mProfileManager = profileManager;
-        mAudioManager = context.getSystemService(AudioManager.class);
         mDevice = device;
         mProfileConnectionState = new HashMap<LocalBluetoothProfile, Integer>();
         fillData();
@@ -303,7 +287,7 @@
             }
             return;
         }
-        Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName);
+        Log.i(TAG, "Failed to connect " + profile.toString() + " to " + getName());
     }
 
     private boolean ensurePaired() {
@@ -380,8 +364,6 @@
 
     // TODO: do any of these need to run async on a background thread?
     private void fillData() {
-        fetchName();
-        fetchBtClass();
         updateProfiles();
         fetchActiveDevices();
         migratePhonebookPermissionChoice();
@@ -404,21 +386,15 @@
         return mDevice.getAddress();
     }
 
-    public String getName() {
-        return mName;
-    }
-
     /**
-     * Populate name from BluetoothDevice.ACTION_FOUND intent
+     * Get name from remote device
+     * @return {@link BluetoothDevice#getAliasName()} if
+     * {@link BluetoothDevice#getAliasName()} is not null otherwise return
+     * {@link BluetoothDevice#getAddress()}
      */
-    void setNewName(String name) {
-        if (mName == null) {
-            mName = name;
-            if (mName == null || TextUtils.isEmpty(mName)) {
-                mName = mDevice.getAddress();
-            }
-            dispatchAttributesChanged();
-        }
+    public String getName() {
+        final String aliasName = mDevice.getAliasName();
+        return TextUtils.isEmpty(aliasName) ? getAddress() : aliasName;
     }
 
     /**
@@ -426,9 +402,8 @@
      * @param name new alias name to be set, should never be null
      */
     public void setName(String name) {
-        // Prevent mName to be set to null if setName(null) is called
-        if (name != null && !TextUtils.equals(name, mName)) {
-            mName = name;
+        // Prevent getName() to be set to null if setName(null) is called
+        if (name != null && !TextUtils.equals(name, getName())) {
             mDevice.setAlias(name);
             dispatchAttributesChanged();
         }
@@ -465,19 +440,10 @@
     }
 
     void refreshName() {
-        fetchName();
-        dispatchAttributesChanged();
-    }
-
-    private void fetchName() {
-        mName = mDevice.getAliasName();
-
-        if (TextUtils.isEmpty(mName)) {
-            mName = mDevice.getAddress();
-            if (BluetoothUtils.D) {
-                Log.d(TAG, "Device has no name (yet), use address: " + mName);
-            }
+        if (BluetoothUtils.D) {
+            Log.d(TAG, "Device name: " + getName());
         }
+        dispatchAttributesChanged();
     }
 
     /**
@@ -610,13 +576,6 @@
         return getBondState() == BluetoothDevice.BOND_BONDING;
     }
 
-    /**
-     * Fetches a new value for the cached BT class.
-     */
-    private void fetchBtClass() {
-        mBtClass = mDevice.getBluetoothClass();
-    }
-
     private boolean updateProfiles() {
         ParcelUuid[] uuids = mDevice.getUuids();
         if (uuids == null) return false;
@@ -661,15 +620,6 @@
     }
 
     /**
-     * Refreshes the UI for the BT class, including fetching the latest value
-     * for the class.
-     */
-    void refreshBtClass() {
-        fetchBtClass();
-        dispatchAttributesChanged();
-    }
-
-    /**
      * Refreshes the UI when framework alerts us of a UUID change.
      */
     void onUuidChanged() {
@@ -701,9 +651,9 @@
     void onBondingStateChanged(int bondState) {
         if (bondState == BluetoothDevice.BOND_NONE) {
             mProfiles.clear();
-            setPhonebookPermissionChoice(ACCESS_UNKNOWN);
-            setMessagePermissionChoice(ACCESS_UNKNOWN);
-            setSimPermissionChoice(ACCESS_UNKNOWN);
+            mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_UNKNOWN);
+            mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_UNKNOWN);
+            mDevice.setSimAccessPermission(BluetoothDevice.ACCESS_UNKNOWN);
             mMessageRejectionCount = 0;
             saveMessageRejectionCount();
         }
@@ -719,15 +669,8 @@
         }
     }
 
-    void setBtClass(BluetoothClass btClass) {
-        if (btClass != null && mBtClass != btClass) {
-            mBtClass = btClass;
-            dispatchAttributesChanged();
-        }
-    }
-
     public BluetoothClass getBtClass() {
-        return mBtClass;
+        return mDevice.getBluetoothClass();
     }
 
     public List<LocalBluetoothProfile> getProfiles() {
@@ -761,7 +704,7 @@
         }
     }
 
-    private void dispatchAttributesChanged() {
+    void dispatchAttributesChanged() {
         synchronized (mCallbacks) {
             for (Callback callback : mCallbacks) {
                 callback.onDeviceAttributesChanged();
@@ -809,33 +752,13 @@
         if (comparison != 0) return comparison;
 
         // Fallback on name
-        return mName.compareTo(another.mName);
+        return getName().compareTo(another.getName());
     }
 
     public interface Callback {
         void onDeviceAttributesChanged();
     }
 
-    public int getPhonebookPermissionChoice() {
-        int permission = mDevice.getPhonebookAccessPermission();
-        if (permission == BluetoothDevice.ACCESS_ALLOWED) {
-            return ACCESS_ALLOWED;
-        } else if (permission == BluetoothDevice.ACCESS_REJECTED) {
-            return ACCESS_REJECTED;
-        }
-        return ACCESS_UNKNOWN;
-    }
-
-    public void setPhonebookPermissionChoice(int permissionChoice) {
-        int permission = BluetoothDevice.ACCESS_UNKNOWN;
-        if (permissionChoice == ACCESS_ALLOWED) {
-            permission = BluetoothDevice.ACCESS_ALLOWED;
-        } else if (permissionChoice == ACCESS_REJECTED) {
-            permission = BluetoothDevice.ACCESS_REJECTED;
-        }
-        mDevice.setPhonebookAccessPermission(permission);
-    }
-
     // Migrates data from old data store (in Settings app's shared preferences) to new (in Bluetooth
     // app's shared preferences).
     private void migratePhonebookPermissionChoice() {
@@ -846,10 +769,11 @@
         }
 
         if (mDevice.getPhonebookAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) {
-            int oldPermission = preferences.getInt(mDevice.getAddress(), ACCESS_UNKNOWN);
-            if (oldPermission == ACCESS_ALLOWED) {
+            int oldPermission =
+                    preferences.getInt(mDevice.getAddress(), BluetoothDevice.ACCESS_UNKNOWN);
+            if (oldPermission == BluetoothDevice.ACCESS_ALLOWED) {
                 mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
-            } else if (oldPermission == ACCESS_REJECTED) {
+            } else if (oldPermission == BluetoothDevice.ACCESS_REJECTED) {
                 mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED);
             }
         }
@@ -859,46 +783,6 @@
         editor.commit();
     }
 
-    public int getMessagePermissionChoice() {
-        int permission = mDevice.getMessageAccessPermission();
-        if (permission == BluetoothDevice.ACCESS_ALLOWED) {
-            return ACCESS_ALLOWED;
-        } else if (permission == BluetoothDevice.ACCESS_REJECTED) {
-            return ACCESS_REJECTED;
-        }
-        return ACCESS_UNKNOWN;
-    }
-
-    public void setMessagePermissionChoice(int permissionChoice) {
-        int permission = BluetoothDevice.ACCESS_UNKNOWN;
-        if (permissionChoice == ACCESS_ALLOWED) {
-            permission = BluetoothDevice.ACCESS_ALLOWED;
-        } else if (permissionChoice == ACCESS_REJECTED) {
-            permission = BluetoothDevice.ACCESS_REJECTED;
-        }
-        mDevice.setMessageAccessPermission(permission);
-    }
-
-    public int getSimPermissionChoice() {
-        int permission = mDevice.getSimAccessPermission();
-        if (permission == BluetoothDevice.ACCESS_ALLOWED) {
-            return ACCESS_ALLOWED;
-        } else if (permission == BluetoothDevice.ACCESS_REJECTED) {
-            return ACCESS_REJECTED;
-        }
-        return ACCESS_UNKNOWN;
-    }
-
-    void setSimPermissionChoice(int permissionChoice) {
-        int permission = BluetoothDevice.ACCESS_UNKNOWN;
-        if (permissionChoice == ACCESS_ALLOWED) {
-            permission = BluetoothDevice.ACCESS_ALLOWED;
-        } else if (permissionChoice == ACCESS_REJECTED) {
-            permission = BluetoothDevice.ACCESS_REJECTED;
-        }
-        mDevice.setSimAccessPermission(permission);
-    }
-
     // Migrates data from old data store (in Settings app's shared preferences) to new (in Bluetooth
     // app's shared preferences).
     private void migrateMessagePermissionChoice() {
@@ -909,10 +793,11 @@
         }
 
         if (mDevice.getMessageAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) {
-            int oldPermission = preferences.getInt(mDevice.getAddress(), ACCESS_UNKNOWN);
-            if (oldPermission == ACCESS_ALLOWED) {
+            int oldPermission =
+                    preferences.getInt(mDevice.getAddress(), BluetoothDevice.ACCESS_UNKNOWN);
+            if (oldPermission == BluetoothDevice.ACCESS_ALLOWED) {
                 mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
-            } else if (oldPermission == ACCESS_REJECTED) {
+            } else if (oldPermission == BluetoothDevice.ACCESS_REJECTED) {
                 mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_REJECTED);
             }
         }
@@ -957,14 +842,14 @@
         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.
-            if (getPhonebookPermissionChoice() == CachedBluetoothDevice.ACCESS_UNKNOWN) {
+            if (mDevice.getPhonebookAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) {
                 if (mDevice.getBluetoothClass().getDeviceClass()
                         == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE ||
                     mDevice.getBluetoothClass().getDeviceClass()
                         == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET) {
-                    setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_ALLOWED);
+                    mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
                 } else {
-                    setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_REJECTED);
+                    mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED);
                 }
             }
         }
@@ -1193,7 +1078,7 @@
     /**
      * @return {@code true} if {@code cachedBluetoothDevice} is a2dp device
      */
-    public boolean isA2dpDevice() {
+    public boolean isConnectedA2dpDevice() {
         A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
         return a2dpProfile != null && a2dpProfile.getConnectionStatus(mDevice) ==
                 BluetoothProfile.STATE_CONNECTED;
@@ -1202,7 +1087,7 @@
     /**
      * @return {@code true} if {@code cachedBluetoothDevice} is HFP device
      */
-    public boolean isHfpDevice() {
+    public boolean isConnectedHfpDevice() {
         HeadsetProfile headsetProfile = mProfileManager.getHeadsetProfile();
         return headsetProfile != null && headsetProfile.getConnectionStatus(mDevice) ==
                 BluetoothProfile.STATE_CONNECTED;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 4104e2f..47bd853 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -107,11 +107,10 @@
      * @param device the address of the new Bluetooth device
      * @return the newly created CachedBluetoothDevice object
      */
-    public CachedBluetoothDevice addDevice(LocalBluetoothAdapter adapter,
-            LocalBluetoothProfileManager profileManager,
-            BluetoothDevice device) {
-        CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter,
-            profileManager, device);
+    public CachedBluetoothDevice addDevice(BluetoothDevice device) {
+        LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+        CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, profileManager,
+                device);
         if (profileManager.getHearingAidProfile() != null
             && profileManager.getHearingAidProfile().getHiSyncId(newDevice.getDevice())
                 != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
@@ -261,7 +260,7 @@
     public synchronized void onBtClassChanged(BluetoothDevice device) {
         CachedBluetoothDevice cachedDevice = findDevice(device);
         if (cachedDevice != null) {
-            cachedDevice.refreshBtClass();
+            cachedDevice.dispatchAttributesChanged();
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 6a4d978..99f550b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -41,7 +41,6 @@
     private BluetoothHeadset mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
     private final LocalBluetoothProfileManager mProfileManager;
 
@@ -70,7 +69,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "HeadsetProfile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(HeadsetProfile.this,
                         BluetoothProfile.STATE_CONNECTED);
@@ -97,13 +96,11 @@
         return BluetoothProfile.HEADSET;
     }
 
-    HeadsetProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    HeadsetProfile(Context context, CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        mLocalAdapter.getProfileProxy(context, new HeadsetServiceListener(),
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new HeadsetServiceListener(),
                 BluetoothProfile.HEADSET);
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 1747d28..6eaa620 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -38,7 +38,6 @@
     private BluetoothHearingAid mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
 
     static final String NAME = "HearingAid";
@@ -64,7 +63,7 @@
                     if (V) {
                         Log.d(TAG, "HearingAidProfile found new device: " + nextDevice);
                     }
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(HearingAidProfile.this,
                         BluetoothProfile.STATE_CONNECTED);
@@ -92,15 +91,13 @@
         return BluetoothProfile.HEARING_AID;
     }
 
-    HearingAidProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    HearingAidProfile(Context context, CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
         mContext = context;
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        mLocalAdapter.getProfileProxy(context, new HearingAidServiceListener(),
-                BluetoothProfile.HEARING_AID);
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context,
+                new HearingAidServiceListener(), BluetoothProfile.HEARING_AID);
     }
 
     public boolean isConnectable() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
index 94c84b9..4b4db75 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -41,7 +41,6 @@
     private BluetoothHeadsetClient mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
 
     static final ParcelUuid[] SRC_UUIDS = {
@@ -71,7 +70,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "HfpClient profile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(
                     HfpClientProfile.this, BluetoothProfile.STATE_CONNECTED);
@@ -97,14 +96,12 @@
         return BluetoothProfile.HEADSET_CLIENT;
     }
 
-    HfpClientProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    HfpClientProfile(Context context, CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        mLocalAdapter.getProfileProxy(context, new HfpClientServiceListener(),
-                BluetoothProfile.HEADSET_CLIENT);
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context,
+                new HfpClientServiceListener(), BluetoothProfile.HEADSET_CLIENT);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
index 179a60d..8c4bff5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
@@ -39,7 +39,6 @@
     private static final int PREFERRED_VALUE = -1;
     private static final boolean DEBUG = true;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
     private final LocalBluetoothProfileManager mProfileManager;
     static final String NAME = "HID DEVICE";
@@ -47,14 +46,12 @@
     private BluetoothHidDevice mService;
     private boolean mIsProfileReady;
 
-    HidDeviceProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    HidDeviceProfile(Context context,CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        adapter.getProfileProxy(context, new HidDeviceServiceListener(),
-                BluetoothProfile.HID_DEVICE);
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context,
+                new HidDeviceServiceListener(), BluetoothProfile.HID_DEVICE);
     }
 
     // These callbacks run on the main thread.
@@ -73,7 +70,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "HidProfile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 Log.d(TAG, "Connection status changed: " + device);
                 device.onProfileStateChanged(HidDeviceProfile.this,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index da348f9..701ef00 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -38,7 +38,6 @@
     private BluetoothHidHost mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
     private final LocalBluetoothProfileManager mProfileManager;
 
@@ -62,7 +61,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "HidProfile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(HidProfile.this, BluetoothProfile.STATE_CONNECTED);
                 device.refresh();
@@ -85,13 +84,12 @@
         return BluetoothProfile.HID_HOST;
     }
 
-    HidProfile(Context context, LocalBluetoothAdapter adapter,
+    HidProfile(Context context,
         CachedBluetoothDeviceManager deviceManager,
         LocalBluetoothProfileManager profileManager) {
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        adapter.getProfileProxy(context, new HidHostServiceListener(),
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new HidHostServiceListener(),
                 BluetoothProfile.HID_HOST);
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
index f8674a6..8f40ab4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
@@ -35,7 +35,10 @@
  * <p>Connection and bonding state changes affecting specific devices
  * are handled by {@link CachedBluetoothDeviceManager},
  * {@link BluetoothEventManager}, and {@link LocalBluetoothProfileManager}.
+ *
+ * @deprecated use {@link BluetoothAdapter} instead.
  */
+@Deprecated
 public class LocalBluetoothAdapter {
     private static final String TAG = "LocalBluetoothAdapter";
 
@@ -246,10 +249,6 @@
         return mAdapter.getRemoteDevice(address);
     }
 
-    public int getMaxConnectedAudioDevices() {
-        return mAdapter.getMaxConnectedAudioDevices();
-    }
-
     public List<Integer> getSupportedProfiles() {
         return mAdapter.getSupportedProfiles();
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 6256922..8bb8210 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -18,6 +18,7 @@
 
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothA2dpSink;
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHeadsetClient;
@@ -37,6 +38,8 @@
 import androidx.annotation.VisibleForTesting;
 import android.util.Log;
 import com.android.internal.R;
+import com.android.internal.util.CollectionUtils;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -51,8 +54,6 @@
 public class LocalBluetoothProfileManager {
     private static final String TAG = "LocalBluetoothProfileManager";
     private static final boolean DEBUG = BluetoothUtils.D;
-    /** Singleton instance. */
-    private static LocalBluetoothProfileManager sInstance;
 
     /**
      * An interface for notifying BluetoothHeadset IPC clients when they have
@@ -79,7 +80,6 @@
     }
 
     private final Context mContext;
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
     private final BluetoothEventManager mEventManager;
 
@@ -89,12 +89,12 @@
     private HfpClientProfile mHfpClientProfile;
     private MapProfile mMapProfile;
     private MapClientProfile mMapClientProfile;
-    private final HidProfile mHidProfile;
+    private HidProfile mHidProfile;
     private HidDeviceProfile mHidDeviceProfile;
     private OppProfile mOppProfile;
-    private final PanProfile mPanProfile;
+    private PanProfile mPanProfile;
     private PbapClientProfile mPbapClientProfile;
-    private final PbapServerProfile mPbapProfile;
+    private PbapServerProfile mPbapProfile;
     private final boolean mUsePbapPce;
     private final boolean mUseMapClient;
     private HearingAidProfile mHearingAidProfile;
@@ -111,187 +111,113 @@
             BluetoothEventManager eventManager) {
         mContext = context;
 
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mEventManager = eventManager;
         mUsePbapPce = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
         // MAP Client is typically used in the same situations as PBAP Client
         mUseMapClient = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
         // pass this reference to adapter and event manager (circular dependency)
-        mLocalAdapter.setProfileManager(this);
-        mEventManager.setProfileManager(this);
+        adapter.setProfileManager(this);
 
-        ParcelUuid[] uuids = adapter.getUuids();
-
-        // uuids may be null if Bluetooth is turned off
-        if (uuids != null) {
-            updateLocalProfiles(uuids);
-        }
-
-        // Always add HID host, HID device, and PAN profiles
-        mHidProfile = new HidProfile(context, mLocalAdapter, mDeviceManager, this);
-        addProfile(mHidProfile, HidProfile.NAME,
-                BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
-
-        mPanProfile = new PanProfile(context, mLocalAdapter);
-        addPanProfile(mPanProfile, PanProfile.NAME,
-                BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
-
-        mHidDeviceProfile = new HidDeviceProfile(context, mLocalAdapter, mDeviceManager, this);
-        addProfile(mHidDeviceProfile, HidDeviceProfile.NAME,
-                BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED);
-
-        if(DEBUG) Log.d(TAG, "Adding local MAP profile");
-        if (mUseMapClient) {
-            mMapClientProfile = new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
-            addProfile(mMapClientProfile, MapClientProfile.NAME,
-                BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
-        } else {
-            mMapProfile = new MapProfile(mContext, mLocalAdapter, mDeviceManager, this);
-            addProfile(mMapProfile, MapProfile.NAME,
-                    BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
-        }
-
-        //Create PBAP server profile
-        if(DEBUG) Log.d(TAG, "Adding local PBAP profile");
-
-        mPbapProfile = new PbapServerProfile(context);
-        addProfile(mPbapProfile, PbapServerProfile.NAME,
-             BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED);
-
-        List<Integer> supportedList = mLocalAdapter.getSupportedProfiles();
-        if (supportedList.contains(BluetoothProfile.HEARING_AID)) {
-            mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager,
-                                                       this);
-            addProfile(mHearingAidProfile, HearingAidProfile.NAME,
-                       BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
-        }
+        updateLocalProfiles();
         if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete");
     }
 
     /**
-     * Initialize or update the local profile objects. If a UUID was previously
-     * present but has been removed, we print a warning but don't remove the
-     * profile object as it might be referenced elsewhere, or the UUID might
-     * come back and we don't want multiple copies of the profile objects.
-     * @param uuids
+     * create profile instance according to bluetooth supported profile list
      */
-    void updateLocalProfiles(ParcelUuid[] uuids) {
-        // A2DP SRC
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource)) {
-            if (mA2dpProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local A2DP SRC profile");
-                mA2dpProfile = new A2dpProfile(mContext, mLocalAdapter, mDeviceManager, this);
-                addProfile(mA2dpProfile, A2dpProfile.NAME,
-                        BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-            }
-        } else if (mA2dpProfile != null) {
-            Log.w(TAG, "Warning: A2DP profile was previously added but the UUID is now missing.");
+    void updateLocalProfiles() {
+        List<Integer> supportedList = BluetoothAdapter.getDefaultAdapter().getSupportedProfiles();
+        if (CollectionUtils.isEmpty(supportedList)) {
+            if(DEBUG) Log.d(TAG, "supportedList is null");
+            return;
         }
-
-        // A2DP SINK
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
-            if (mA2dpSinkProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local A2DP Sink profile");
-                mA2dpSinkProfile = new A2dpSinkProfile(mContext, mLocalAdapter, mDeviceManager, this);
-                addProfile(mA2dpSinkProfile, A2dpSinkProfile.NAME,
-                        BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
-            }
-        } else if (mA2dpSinkProfile != null) {
-            Log.w(TAG, "Warning: A2DP Sink profile was previously added but the UUID is now missing.");
+        if (mA2dpProfile == null && supportedList.contains(BluetoothProfile.A2DP)) {
+            if(DEBUG) Log.d(TAG, "Adding local A2DP profile");
+            mA2dpProfile = new A2dpProfile(mContext, mDeviceManager, this);
+            addProfile(mA2dpProfile, A2dpProfile.NAME,
+                    BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
         }
-
-        // Headset / Handsfree
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) ||
-            BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) {
-            if (mHeadsetProfile == null) {
-                if (DEBUG) Log.d(TAG, "Adding local HEADSET profile");
-                mHeadsetProfile = new HeadsetProfile(mContext, mLocalAdapter,
-                        mDeviceManager, this);
-                addHeadsetProfile(mHeadsetProfile, HeadsetProfile.NAME,
-                        BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
-                        BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
-                        BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
-            }
-        } else if (mHeadsetProfile != null) {
-            Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing.");
+        if (mA2dpSinkProfile == null && supportedList.contains(BluetoothProfile.A2DP_SINK)) {
+            if(DEBUG) Log.d(TAG, "Adding local A2DP SINK profile");
+            mA2dpSinkProfile = new A2dpSinkProfile(mContext, mDeviceManager, this);
+            addProfile(mA2dpSinkProfile, A2dpSinkProfile.NAME,
+                    BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
         }
-
-        // Headset HF
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) {
-            if (mHfpClientProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
-                mHfpClientProfile =
-                    new HfpClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
-                addHeadsetProfile(mHfpClientProfile, HfpClientProfile.NAME,
-                        BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED,
-                        BluetoothHeadsetClient.ACTION_AUDIO_STATE_CHANGED,
-                        BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED);
-            }
-        } else if (mHfpClientProfile != null) {
-            Log.w(TAG,
-                "Warning: Hfp Client profile was previously added but the UUID is now missing.");
-        } else {
-            Log.d(TAG, "Handsfree Uuid not found.");
+        if (mHeadsetProfile == null && supportedList.contains(BluetoothProfile.HEADSET)) {
+            if (DEBUG) Log.d(TAG, "Adding local HEADSET profile");
+            mHeadsetProfile = new HeadsetProfile(mContext, mDeviceManager, this);
+            addHeadsetProfile(mHeadsetProfile, HeadsetProfile.NAME,
+                    BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
+                    BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
+                    BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
         }
-
-        // Message Access Profile Client
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.MNS)) {
-            if (mMapClientProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local Map Client profile");
+        if (mHfpClientProfile == null && supportedList.contains(BluetoothProfile.HEADSET_CLIENT)) {
+            if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
+            mHfpClientProfile = new HfpClientProfile(mContext, mDeviceManager, this);
+            addHeadsetProfile(mHfpClientProfile, HfpClientProfile.NAME,
+                    BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED,
+                    BluetoothHeadsetClient.ACTION_AUDIO_STATE_CHANGED,
+                    BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED);
+        }
+        if (mUseMapClient) {
+            if (mMapClientProfile == null && supportedList.contains(BluetoothProfile.MAP_CLIENT)) {
+                if(DEBUG) Log.d(TAG, "Adding local MAP CLIENT profile");
                 mMapClientProfile =
-                        new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
+                        new MapClientProfile(mContext, mDeviceManager,this);
                 addProfile(mMapClientProfile, MapClientProfile.NAME,
                         BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
             }
-        } else if (mMapClientProfile != null) {
-            Log.w(TAG,
-                    "Warning: MAP Client profile was previously added but the UUID is now missing.");
-        } else {
-            Log.d(TAG, "MAP Client Uuid not found.");
+        } else if (mMapProfile == null && supportedList.contains(BluetoothProfile.MAP)) {
+            if(DEBUG) Log.d(TAG, "Adding local MAP profile");
+            mMapProfile = new MapProfile(mContext, mDeviceManager, this);
+            addProfile(mMapProfile, MapProfile.NAME, BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
         }
-
-        // OPP
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
-            if (mOppProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local OPP profile");
-                mOppProfile = new OppProfile();
-                // Note: no event handler for OPP, only name map.
-                mProfileNameMap.put(OppProfile.NAME, mOppProfile);
-            }
-        } else if (mOppProfile != null) {
-            Log.w(TAG, "Warning: OPP profile was previously added but the UUID is now missing.");
+        if (mOppProfile == null && supportedList.contains(BluetoothProfile.OPP)) {
+            if(DEBUG) Log.d(TAG, "Adding local OPP profile");
+            mOppProfile = new OppProfile();
+            // Note: no event handler for OPP, only name map.
+            mProfileNameMap.put(OppProfile.NAME, mOppProfile);
         }
-
-        //PBAP Client
-        if (mUsePbapPce) {
-            if (mPbapClientProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local PBAP Client profile");
-                mPbapClientProfile = new PbapClientProfile(mContext, mLocalAdapter, mDeviceManager,
-                        this);
-                addProfile(mPbapClientProfile, PbapClientProfile.NAME,
-                        BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
-            }
-        } else if (mPbapClientProfile != null) {
-            Log.w(TAG,
-                "Warning: PBAP Client profile was previously added but the UUID is now missing.");
+        if (mHearingAidProfile == null && supportedList.contains(BluetoothProfile.HEARING_AID)) {
+            if(DEBUG) Log.d(TAG, "Adding local Hearing Aid profile");
+            mHearingAidProfile = new HearingAidProfile(mContext, mDeviceManager,
+                    this);
+            addProfile(mHearingAidProfile, HearingAidProfile.NAME,
+                    BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
         }
-
-        //Hearing Aid Client
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HearingAid)) {
-            if (mHearingAidProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local Hearing Aid profile");
-                mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, this);
-                addProfile(mHearingAidProfile, HearingAidProfile.NAME,
-                        BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
-            }
-        } else if (mHearingAidProfile != null) {
-            Log.w(TAG, "Warning: Hearing Aid profile was previously added but the UUID is now missing.");
+        if (mHidProfile == null && supportedList.contains(BluetoothProfile.HID_HOST)) {
+            if(DEBUG) Log.d(TAG, "Adding local HID_HOST profile");
+            mHidProfile = new HidProfile(mContext, mDeviceManager, this);
+            addProfile(mHidProfile, HidProfile.NAME,
+                    BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
         }
-
+        if (mHidDeviceProfile == null && supportedList.contains(BluetoothProfile.HID_DEVICE)) {
+            if(DEBUG) Log.d(TAG, "Adding local HID_DEVICE profile");
+            mHidDeviceProfile = new HidDeviceProfile(mContext, mDeviceManager, this);
+            addProfile(mHidDeviceProfile, HidDeviceProfile.NAME,
+                    BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED);
+        }
+        if (mPanProfile == null && supportedList.contains(BluetoothProfile.PAN)) {
+            if(DEBUG) Log.d(TAG, "Adding local PAN profile");
+            mPanProfile = new PanProfile(mContext);
+            addPanProfile(mPanProfile, PanProfile.NAME,
+                    BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
+        }
+        if (mPbapProfile == null && supportedList.contains(BluetoothProfile.PBAP)) {
+            if(DEBUG) Log.d(TAG, "Adding local PBAP profile");
+            mPbapProfile = new PbapServerProfile(mContext);
+            addProfile(mPbapProfile, PbapServerProfile.NAME,
+                    BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED);
+        }
+        if (mUsePbapPce && mPbapClientProfile == null && supportedList.contains(
+                BluetoothProfile.PBAP_CLIENT)) {
+            if(DEBUG) Log.d(TAG, "Adding local PBAP Client profile");
+            mPbapClientProfile = new PbapClientProfile(mContext, mDeviceManager,this);
+            addProfile(mPbapClientProfile, PbapClientProfile.NAME,
+                    BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
+        }
         mEventManager.registerProfileIntentReceiver();
-
-        // There is no local SDP record for HID and Settings app doesn't control PBAP Server.
     }
 
     private void addHeadsetProfile(LocalBluetoothProfile profile, String profileName,
@@ -325,10 +251,7 @@
 
     // Called from LocalBluetoothAdapter when state changes to ON
     void setBluetoothStateOn() {
-        ParcelUuid[] uuids = mLocalAdapter.getUuids();
-        if (uuids != null) {
-            updateLocalProfiles(uuids);
-        }
+        updateLocalProfiles();
         mEventManager.readPairedDevices();
     }
 
@@ -346,8 +269,7 @@
             CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
             if (cachedDevice == null) {
                 Log.w(TAG, "StateChangedHandler found new device: " + device);
-                cachedDevice = mDeviceManager.addDevice(mLocalAdapter,
-                        LocalBluetoothProfileManager.this, device);
+                cachedDevice = mDeviceManager.addDevice(device);
             }
             onReceiveInternal(intent, cachedDevice);
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
index 6aa32fc..7d334eb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
@@ -41,7 +41,6 @@
     private BluetoothMapClient mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
     private final LocalBluetoothProfileManager mProfileManager;
 
@@ -71,7 +70,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "MapProfile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(MapClientProfile.this,
                         BluetoothProfile.STATE_CONNECTED);
@@ -99,14 +98,12 @@
         return BluetoothProfile.MAP_CLIENT;
     }
 
-    MapClientProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    MapClientProfile(Context context, CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        mLocalAdapter.getProfileProxy(context, new MapClientServiceListener(),
-                BluetoothProfile.MAP_CLIENT);
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context,
+                new MapClientServiceListener(), BluetoothProfile.MAP_CLIENT);
     }
 
     public boolean isConnectable() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
index c53cacc..689669f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
@@ -41,7 +41,6 @@
     private BluetoothMap mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
     private final LocalBluetoothProfileManager mProfileManager;
 
@@ -70,7 +69,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "MapProfile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(MapProfile.this,
                         BluetoothProfile.STATE_CONNECTED);
@@ -98,13 +97,11 @@
         return BluetoothProfile.MAP;
     }
 
-    MapProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    MapProfile(Context context, CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        mLocalAdapter.getProfileProxy(context, new MapServiceListener(),
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new MapServiceListener(),
                 BluetoothProfile.MAP);
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
index e204d03..02afe8d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
@@ -38,7 +38,6 @@
 
     private BluetoothPan mService;
     private boolean mIsProfileReady;
-    private final LocalBluetoothAdapter mLocalAdapter;
 
     // Tethering direction for each device
     private final HashMap<BluetoothDevice, Integer> mDeviceRoleMap =
@@ -74,9 +73,8 @@
         return BluetoothProfile.PAN;
     }
 
-    PanProfile(Context context, LocalBluetoothAdapter adapter) {
-        mLocalAdapter = adapter;
-        mLocalAdapter.getProfileProxy(context, new PanServiceListener(),
+    PanProfile(Context context) {
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new PanServiceListener(),
             BluetoothProfile.PAN);
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index b735c23..ad3506f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -39,7 +39,6 @@
     private BluetoothPbapClient mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
 
     static final ParcelUuid[] SRC_UUIDS = {
@@ -69,7 +68,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "PbapClientProfile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(PbapClientProfile.this, BluetoothProfile.STATE_CONNECTED);
                 device.refresh();
@@ -105,14 +104,12 @@
         return BluetoothProfile.PBAP_CLIENT;
     }
 
-    PbapClientProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    PbapClientProfile(Context context, CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        mLocalAdapter.getProfileProxy(context, new PbapClientServiceListener(),
-                BluetoothProfile.PBAP_CLIENT);
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context,
+                new PbapClientServiceListener(), BluetoothProfile.PBAP_CLIENT);
     }
 
     public boolean isConnectable() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
index 60985f3c..f0e259e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
@@ -69,7 +69,7 @@
                 // we may add a new device here, but generally this should not happen
                 if (device == null) {
                     Log.w(TAG, "SapProfile found new device: " + nextDevice);
-                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                    device = mDeviceManager.addDevice(nextDevice);
                 }
                 device.onProfileStateChanged(SapProfile.this,
                         BluetoothProfile.STATE_CONNECTED);
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableActivity.java b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableActivity.java
index f9aa062..2bd0b27 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableActivity.java
@@ -24,20 +24,22 @@
 
 import android.annotation.Nullable;
 import android.app.Activity;
-import androidx.lifecycle.LifecycleOwner;
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.view.Menu;
 import android.view.MenuItem;
 
+import androidx.fragment.app.FragmentActivity;
+import androidx.lifecycle.LifecycleOwner;
+
 /**
  * {@link Activity} that has hooks to observe activity lifecycle events.
  */
-public class ObservableActivity extends Activity implements LifecycleOwner {
+public class ObservableActivity extends FragmentActivity implements LifecycleOwner {
 
     private final Lifecycle mLifecycle = new Lifecycle(this);
 
-    public Lifecycle getLifecycle() {
+    public Lifecycle getSettingsLifecycle() {
         return mLifecycle;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableDialogFragment.java b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableDialogFragment.java
index 972e062..869f54f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableDialogFragment.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableDialogFragment.java
@@ -22,14 +22,15 @@
 import static androidx.lifecycle.Lifecycle.Event.ON_START;
 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
 
-import android.app.DialogFragment;
-import androidx.lifecycle.LifecycleOwner;
 import android.content.Context;
 import android.os.Bundle;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import androidx.fragment.app.DialogFragment;
+import androidx.lifecycle.LifecycleOwner;
+
 /**
  * {@link DialogFragment} that has hooks to observe fragment lifecycle events.
  */
@@ -37,6 +38,10 @@
 
     protected final Lifecycle mLifecycle = new Lifecycle(this);
 
+    public Lifecycle getSettingsLifecycle() {
+        return mLifecycle;
+    }
+
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
@@ -100,9 +105,4 @@
         }
         return lifecycleHandled;
     }
-
-    @Override
-    public Lifecycle getLifecycle() {
-        return mLifecycle;
-    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableFragment.java b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableFragment.java
index 55597cc..6ba930d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableFragment.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservableFragment.java
@@ -24,19 +24,20 @@
 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
 
 import android.annotation.CallSuper;
-import android.app.Fragment;
-import androidx.lifecycle.LifecycleOwner;
 import android.content.Context;
 import android.os.Bundle;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.LifecycleOwner;
+
 public class ObservableFragment extends Fragment implements LifecycleOwner {
 
     private final Lifecycle mLifecycle = new Lifecycle(this);
 
-    public Lifecycle getLifecycle() {
+    public Lifecycle getSettingsLifecycle() {
         return mLifecycle;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservablePreferenceFragment.java b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservablePreferenceFragment.java
index 904681c..bd1e5a5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservablePreferenceFragment.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/ObservablePreferenceFragment.java
@@ -24,24 +24,25 @@
 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
 
 import android.annotation.CallSuper;
-import androidx.lifecycle.LifecycleOwner;
 import android.content.Context;
 import android.os.Bundle;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceScreen;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
 /**
- * {@link PreferenceFragment} that has hooks to observe fragment lifecycle events.
+ * {@link PreferenceFragmentCompat} that has hooks to observe fragment lifecycle events.
  */
-public abstract class ObservablePreferenceFragment extends PreferenceFragment
+public abstract class ObservablePreferenceFragment extends PreferenceFragmentCompat
         implements LifecycleOwner {
 
     private final Lifecycle mLifecycle = new Lifecycle(this);
 
-    public Lifecycle getLifecycle() {
+    public Lifecycle getSettingsLifecycle() {
         return mLifecycle;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java
index 332a2a4..ba93970 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java
@@ -88,7 +88,7 @@
     }
 
     private void updateTimes() {
-        mUptime.setSummary(DateUtils.formatDuration(SystemClock.elapsedRealtime()));
+        mUptime.setSummary(DateUtils.formatElapsedTime(SystemClock.elapsedRealtime() / 1000));
     }
 
     private static class MyHandler extends Handler {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
deleted file mode 100644
index d960536..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/**
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settingslib.drawer;
-
-import android.content.ComponentName;
-import android.content.Context;
-import androidx.annotation.VisibleForTesting;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.settingslib.applications.InterestingConfigChanges;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import static java.lang.String.CASE_INSENSITIVE_ORDER;
-
-public class CategoryManager {
-
-    private static final String TAG = "CategoryManager";
-
-    private static CategoryManager sInstance;
-    private final InterestingConfigChanges mInterestingConfigChanges;
-
-    // Tile cache (key: <packageName, activityName>, value: tile)
-    private final Map<Pair<String, String>, Tile> mTileByComponentCache;
-
-    // Tile cache (key: category key, value: category)
-    private final Map<String, DashboardCategory> mCategoryByKeyMap;
-
-    private List<DashboardCategory> mCategories;
-    private String mExtraAction;
-
-    public static CategoryManager get(Context context) {
-        return get(context, null);
-    }
-
-    public static CategoryManager get(Context context, String action) {
-        if (sInstance == null) {
-            sInstance = new CategoryManager(context, action);
-        }
-        return sInstance;
-    }
-
-    CategoryManager(Context context, String action) {
-        mTileByComponentCache = new ArrayMap<>();
-        mCategoryByKeyMap = new ArrayMap<>();
-        mInterestingConfigChanges = new InterestingConfigChanges();
-        mInterestingConfigChanges.applyNewConfig(context.getResources());
-        mExtraAction = action;
-    }
-
-    public synchronized DashboardCategory getTilesByCategory(Context context, String categoryKey) {
-        return getTilesByCategory(context, categoryKey, TileUtils.SETTING_PKG);
-    }
-
-    public synchronized DashboardCategory getTilesByCategory(Context context, String categoryKey,
-            String settingPkg) {
-        tryInitCategories(context, settingPkg);
-
-        return mCategoryByKeyMap.get(categoryKey);
-    }
-
-    public synchronized List<DashboardCategory> getCategories(Context context) {
-        return getCategories(context, TileUtils.SETTING_PKG);
-    }
-
-    public synchronized List<DashboardCategory> getCategories(Context context, String settingPkg) {
-        tryInitCategories(context, settingPkg);
-        return mCategories;
-    }
-
-    public synchronized void reloadAllCategories(Context context, String settingPkg) {
-        final boolean forceClearCache = mInterestingConfigChanges.applyNewConfig(
-                context.getResources());
-        mCategories = null;
-        tryInitCategories(context, forceClearCache, settingPkg);
-    }
-
-    public synchronized void updateCategoryFromBlacklist(Set<ComponentName> tileBlacklist) {
-        if (mCategories == null) {
-            Log.w(TAG, "Category is null, skipping blacklist update");
-        }
-        for (int i = 0; i < mCategories.size(); i++) {
-            DashboardCategory category = mCategories.get(i);
-            for (int j = 0; j < category.getTilesCount(); j++) {
-                Tile tile = category.getTile(j);
-                if (tileBlacklist.contains(tile.intent.getComponent())) {
-                    category.removeTile(j--);
-                }
-            }
-        }
-    }
-
-    private synchronized void tryInitCategories(Context context, String settingPkg) {
-        // Keep cached tiles by default. The cache is only invalidated when InterestingConfigChange
-        // happens.
-        tryInitCategories(context, false /* forceClearCache */, settingPkg);
-    }
-
-    private synchronized void tryInitCategories(Context context, boolean forceClearCache,
-            String settingPkg) {
-        if (mCategories == null) {
-            if (forceClearCache) {
-                mTileByComponentCache.clear();
-            }
-            mCategoryByKeyMap.clear();
-            mCategories = TileUtils.getCategories(context, mTileByComponentCache,
-                    false /* categoryDefinedInManifest */, mExtraAction, settingPkg);
-            for (DashboardCategory category : mCategories) {
-                mCategoryByKeyMap.put(category.key, category);
-            }
-            backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap);
-            sortCategories(context, mCategoryByKeyMap);
-            filterDuplicateTiles(mCategoryByKeyMap);
-        }
-    }
-
-    @VisibleForTesting
-    synchronized void backwardCompatCleanupForCategory(
-            Map<Pair<String, String>, Tile> tileByComponentCache,
-            Map<String, DashboardCategory> categoryByKeyMap) {
-        // A package can use a) CategoryKey, b) old category keys, c) both.
-        // Check if a package uses old category key only.
-        // If yes, map them to new category key.
-
-        // Build a package name -> tile map first.
-        final Map<String, List<Tile>> packageToTileMap = new HashMap<>();
-        for (Entry<Pair<String, String>, Tile> tileEntry : tileByComponentCache.entrySet()) {
-            final String packageName = tileEntry.getKey().first;
-            List<Tile> tiles = packageToTileMap.get(packageName);
-            if (tiles == null) {
-                tiles = new ArrayList<>();
-                packageToTileMap.put(packageName, tiles);
-            }
-            tiles.add(tileEntry.getValue());
-        }
-
-        for (Entry<String, List<Tile>> entry : packageToTileMap.entrySet()) {
-            final List<Tile> tiles = entry.getValue();
-            // Loop map, find if all tiles from same package uses old key only.
-            boolean useNewKey = false;
-            boolean useOldKey = false;
-            for (Tile tile : tiles) {
-                if (CategoryKey.KEY_COMPAT_MAP.containsKey(tile.category)) {
-                    useOldKey = true;
-                } else {
-                    useNewKey = true;
-                    break;
-                }
-            }
-            // Uses only old key, map them to new keys one by one.
-            if (useOldKey && !useNewKey) {
-                for (Tile tile : tiles) {
-                    final String newCategoryKey = CategoryKey.KEY_COMPAT_MAP.get(tile.category);
-                    tile.category = newCategoryKey;
-                    // move tile to new category.
-                    DashboardCategory newCategory = categoryByKeyMap.get(newCategoryKey);
-                    if (newCategory == null) {
-                        newCategory = new DashboardCategory();
-                        categoryByKeyMap.put(newCategoryKey, newCategory);
-                    }
-                    newCategory.addTile(tile);
-                }
-            }
-        }
-    }
-
-    /**
-     * Sort the tiles injected from all apps such that if they have the same priority value,
-     * they wil lbe sorted by package name.
-     * <p/>
-     * A list of tiles are considered sorted when their priority value decreases in a linear
-     * scan.
-     */
-    @VisibleForTesting
-    synchronized void sortCategories(Context context,
-            Map<String, DashboardCategory> categoryByKeyMap) {
-        for (Entry<String, DashboardCategory> categoryEntry : categoryByKeyMap.entrySet()) {
-            categoryEntry.getValue().sortTiles(context.getPackageName());
-        }
-    }
-
-    /**
-     * Filter out duplicate tiles from category. Duplicate tiles are the ones pointing to the
-     * same intent.
-     */
-    @VisibleForTesting
-    synchronized void filterDuplicateTiles(Map<String, DashboardCategory> categoryByKeyMap) {
-        for (Entry<String, DashboardCategory> categoryEntry : categoryByKeyMap.entrySet()) {
-            final DashboardCategory category = categoryEntry.getValue();
-            final int count = category.getTilesCount();
-            final Set<ComponentName> components = new ArraySet<>();
-            for (int i = count - 1; i >= 0; i--) {
-                final Tile tile = category.getTile(i);
-                if (tile.intent == null) {
-                    continue;
-                }
-                final ComponentName tileComponent = tile.intent.getComponent();
-                if (components.contains(tileComponent)) {
-                    category.removeTile(i);
-                } else {
-                    components.add(tileComponent);
-                }
-            }
-        }
-    }
-
-    /**
-     * Sort priority value for tiles within a single {@code DashboardCategory}.
-     *
-     * @see #sortCategories(Context, Map)
-     */
-    private synchronized void sortCategoriesForExternalTiles(Context context,
-            DashboardCategory dashboardCategory) {
-        dashboardCategory.sortTiles(context.getPackageName());
-
-    }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
index 3a03644..a3dda65 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
@@ -5,7 +5,7 @@
  * you may not use this 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,
@@ -18,55 +18,39 @@
 
 import static java.lang.String.CASE_INSENSITIVE_ORDER;
 
-import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
-import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 
 public class DashboardCategory implements Parcelable {
 
-    private static final String TAG = "DashboardCategory";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    /**
-     * Title of the category that is shown to the user.
-     */
-    public CharSequence title;
-
     /**
      * Key used for placing external tiles.
      */
-    public String key;
-
-    /**
-     * Used to control display order.
-     */
-    public int priority;
+    public final String key;
 
     /**
      * List of the category's children
      */
     private List<Tile> mTiles = new ArrayList<>();
 
-    DashboardCategory(DashboardCategory in) {
-        if (in != null) {
-            title = in.title;
-            key = in.key;
-            priority = in.priority;
-            for (Tile tile : in.mTiles) {
-                mTiles.add(tile);
-            }
-        }
+    public DashboardCategory(String key) {
+        this.key = key;
     }
 
-    public DashboardCategory() {
-        // Empty
+    DashboardCategory(Parcel in) {
+        key = in.readString();
+
+        final int count = in.readInt();
+
+        for (int n = 0; n < count; n++) {
+            Tile tile = Tile.CREATOR.createFromParcel(in);
+            mTiles.add(tile);
+        }
     }
 
     /**
@@ -87,14 +71,6 @@
         mTiles.add(tile);
     }
 
-    public synchronized void addTile(int n, Tile tile) {
-        mTiles.add(n, tile);
-    }
-
-    public synchronized void removeTile(Tile tile) {
-        mTiles.remove(tile);
-    }
-
     public synchronized void removeTile(int n) {
         mTiles.remove(n);
     }
@@ -107,44 +83,29 @@
         return mTiles.get(n);
     }
 
-    public synchronized boolean containsComponent(ComponentName component) {
-        for (Tile tile : mTiles) {
-            if (TextUtils.equals(tile.intent.getComponent().getClassName(),
-                    component.getClassName())) {
-                if (DEBUG) {
-                    Log.d(TAG,  "category " + key + "contains component" + component);
-                }
-                return true;
-            }
-        }
-        if (DEBUG) {
-            Log.d(TAG,  "category " + key + " does not contain component" + component);
-        }
-        return false;
-    }
-
     /**
      * Sort priority value for tiles in this category.
      */
     public void sortTiles() {
-        Collections.sort(mTiles, TILE_COMPARATOR);
+        Collections.sort(mTiles, Tile.TILE_COMPARATOR);
     }
 
     /**
      * Sort priority value and package name for tiles in this category.
      */
     public synchronized void sortTiles(String skipPackageName) {
-        // Sort mTiles based on [priority, package within priority]
+        // Sort mTiles based on [order, package within order]
         Collections.sort(mTiles, (tile1, tile2) -> {
-            final String package1 = tile1.intent.getComponent().getPackageName();
-            final String package2 = tile2.intent.getComponent().getPackageName();
-            final int packageCompare = CASE_INSENSITIVE_ORDER.compare(package1, package2);
-            // First sort by priority
-            final int priorityCompare = tile2.priority - tile1.priority;
-            if (priorityCompare != 0) {
-                return priorityCompare;
+            // First sort by order
+            final int orderCompare = tile2.getOrder() - tile1.getOrder();
+            if (orderCompare != 0) {
+                return orderCompare;
             }
+
             // Then sort by package name, skip package take precedence
+            final String package1 = tile1.getPackageName();
+            final String package2 = tile2.getPackageName();
+            final int packageCompare = CASE_INSENSITIVE_ORDER.compare(package1, package2);
             if (packageCompare != 0) {
                 if (TextUtils.equals(package1, skipPackageName)) {
                     return -1;
@@ -164,9 +125,7 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        TextUtils.writeToParcel(title, dest, flags);
         dest.writeString(key);
-        dest.writeInt(priority);
 
         final int count = mTiles.size();
         dest.writeInt(count);
@@ -177,23 +136,6 @@
         }
     }
 
-    public void readFromParcel(Parcel in) {
-        title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-        key = in.readString();
-        priority = in.readInt();
-
-        final int count = in.readInt();
-
-        for (int n = 0; n < count; n++) {
-            Tile tile = Tile.CREATOR.createFromParcel(in);
-            mTiles.add(tile);
-        }
-    }
-
-    DashboardCategory(Parcel in) {
-        readFromParcel(in);
-    }
-
     public static final Creator<DashboardCategory> CREATOR = new Creator<DashboardCategory>() {
         public DashboardCategory createFromParcel(Parcel source) {
             return new DashboardCategory(source);
@@ -204,12 +146,4 @@
         }
     };
 
-    public static final Comparator<Tile> TILE_COMPARATOR =
-            new Comparator<Tile>() {
-                @Override
-                public int compare(Tile lhs, Tile rhs) {
-                    return rhs.priority - lhs.priority;
-                }
-            };
-
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/ProfileSelectDialog.java b/packages/SettingsLib/src/com/android/settingslib/drawer/ProfileSelectDialog.java
deleted file mode 100644
index c79b1466d..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/ProfileSelectDialog.java
+++ /dev/null
@@ -1,90 +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.settingslib.drawer;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.FragmentManager;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
-
-import java.util.List;
-
-public class ProfileSelectDialog extends DialogFragment implements OnClickListener {
-
-    private static final String TAG = "ProfileSelectDialog";
-    private static final String ARG_SELECTED_TILE = "selectedTile";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private Tile mSelectedTile;
-
-    public static void show(FragmentManager manager, Tile tile) {
-        ProfileSelectDialog dialog = new ProfileSelectDialog();
-        Bundle args = new Bundle();
-        args.putParcelable(ARG_SELECTED_TILE, tile);
-        dialog.setArguments(args);
-        dialog.show(manager, "select_profile");
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mSelectedTile = getArguments().getParcelable(ARG_SELECTED_TILE);
-    }
-
-    @Override
-    public Dialog onCreateDialog(Bundle savedInstanceState) {
-        Context context = getActivity();
-        AlertDialog.Builder builder = new AlertDialog.Builder(context);
-        UserAdapter adapter = UserAdapter.createUserAdapter(UserManager.get(context), context,
-                mSelectedTile.userHandle);
-        builder.setTitle(com.android.settingslib.R.string.choose_profile)
-                .setAdapter(adapter, this);
-
-        return builder.create();
-    }
-
-    @Override
-    public void onClick(DialogInterface dialog, int which) {
-        UserHandle user = mSelectedTile.userHandle.get(which);
-        // Show menu on top level items.
-        mSelectedTile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        getActivity().startActivityAsUser(mSelectedTile.intent, user);
-    }
-
-    public static void updateUserHandlesIfNeeded(Context context, Tile tile) {
-        List<UserHandle> userHandles = tile.userHandle;
-        if (tile.userHandle == null || tile.userHandle.size() <= 1) {
-            return;
-        }
-        final UserManager userManager = UserManager.get(context);
-        for (int i = userHandles.size() - 1; i >= 0; i--) {
-            if (userManager.getUserInfo(userHandles.get(i).getIdentifier()) == null) {
-                if (DEBUG) {
-                    Log.d(TAG, "Delete the user: " + userHandles.get(i).getIdentifier());
-                }
-                userHandles.remove(i);
-            }
-        }
-    }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
deleted file mode 100644
index 68ead09..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ /dev/null
@@ -1,214 +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.settingslib.drawer;
-
-import android.annotation.LayoutRes;
-import android.annotation.Nullable;
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.res.TypedArray;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.util.ArraySet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager.LayoutParams;
-import android.widget.FrameLayout;
-import android.widget.Toolbar;
-
-import com.android.settingslib.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class SettingsDrawerActivity extends Activity {
-
-    protected static final boolean DEBUG_TIMING = false;
-    private static final String TAG = "SettingsDrawerActivity";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    public static final String EXTRA_SHOW_MENU = "show_drawer_menu";
-
-    // Serves as a temporary list of tiles to ignore until we heard back from the PM that they
-    // are disabled.
-    private static ArraySet<ComponentName> sTileBlacklist = new ArraySet<>();
-
-    private final PackageReceiver mPackageReceiver = new PackageReceiver();
-    private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
-
-    private FrameLayout mContentHeaderContainer;
-
-    @Override
-    protected void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        long startTime = System.currentTimeMillis();
-
-        TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
-        if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
-            getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
-            requestWindowFeature(Window.FEATURE_NO_TITLE);
-        }
-        super.setContentView(R.layout.settings_with_drawer);
-        mContentHeaderContainer = findViewById(R.id.content_header_container);
-
-        Toolbar toolbar = findViewById(R.id.action_bar);
-        if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
-            toolbar.setVisibility(View.GONE);
-            return;
-        }
-        setActionBar(toolbar);
-
-        if (DEBUG_TIMING) {
-            Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
-                    + " ms");
-        }
-    }
-
-    @Override
-    public boolean onNavigateUp() {
-        if (!super.onNavigateUp()) {
-            finish();
-        }
-        return true;
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
-        filter.addDataScheme("package");
-        registerReceiver(mPackageReceiver, filter);
-
-        new CategoriesUpdateTask().execute();
-    }
-
-    @Override
-    protected void onPause() {
-        unregisterReceiver(mPackageReceiver);
-        super.onPause();
-    }
-
-    public void addCategoryListener(CategoryListener listener) {
-        mCategoryListeners.add(listener);
-    }
-
-    public void remCategoryListener(CategoryListener listener) {
-        mCategoryListeners.remove(listener);
-    }
-
-    @Override
-    public void setContentView(@LayoutRes 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);
-    }
-
-    private void onCategoriesChanged() {
-        final int N = mCategoryListeners.size();
-        for (int i = 0; i < N; i++) {
-            mCategoryListeners.get(i).onCategoriesChanged();
-        }
-    }
-
-    /**
-     * @return whether or not the enabled state actually changed.
-     */
-    public boolean setTileEnabled(ComponentName component, boolean enabled) {
-        PackageManager pm = getPackageManager();
-        int state = pm.getComponentEnabledSetting(component);
-        boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-        if (isEnabled != enabled || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
-            if (enabled) {
-                sTileBlacklist.remove(component);
-            } else {
-                sTileBlacklist.add(component);
-            }
-            pm.setComponentEnabledSetting(component, enabled
-                            ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
-                            : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                    PackageManager.DONT_KILL_APP);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Updates dashboard categories. Only necessary to call this after setTileEnabled
-     */
-    public void updateCategories() {
-        new CategoriesUpdateTask().execute();
-    }
-
-    public String getSettingPkg() {
-        return TileUtils.SETTING_PKG;
-    }
-
-    public interface CategoryListener {
-        void onCategoriesChanged();
-    }
-
-    private class CategoriesUpdateTask extends AsyncTask<Void, Void, Void> {
-
-        private final CategoryManager mCategoryManager;
-
-        public CategoriesUpdateTask() {
-            mCategoryManager = CategoryManager.get(SettingsDrawerActivity.this);
-        }
-
-        @Override
-        protected Void doInBackground(Void... params) {
-            mCategoryManager.reloadAllCategories(SettingsDrawerActivity.this, getSettingPkg());
-            return null;
-        }
-
-        @Override
-        protected void onPostExecute(Void result) {
-            mCategoryManager.updateCategoryFromBlacklist(sTileBlacklist);
-            onCategoriesChanged();
-        }
-    }
-
-    private class PackageReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            new CategoriesUpdateTask().execute();
-        }
-    }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
index b55d2ef..a6b2410 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
@@ -5,7 +5,7 @@
  * you may not use this 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,
@@ -16,92 +16,76 @@
 
 package com.android.settingslib.drawer;
 
+import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
 
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
 import android.text.TextUtils;
-import android.widget.RemoteViews;
+import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
 
 /**
  * Description of a single dashboard tile that the user can select.
  */
 public class Tile implements Parcelable {
 
-    /**
-     * Title of the tile that is shown to the user.
-     * @attr ref android.R.styleable#PreferenceHeader_title
-     */
-    public CharSequence title;
-
-    /**
-     * Optional summary describing what this tile controls.
-     * @attr ref android.R.styleable#PreferenceHeader_summary
-     */
-    public CharSequence summary;
-
-    /**
-     * Optional icon to show for this tile.
-     * @attr ref android.R.styleable#PreferenceHeader_icon
-     */
-    public Icon icon;
-
-    /**
-     * Whether the icon can be tinted. This should be set to true for monochrome (single-color)
-     * icons that can be tinted to match the design.
-     */
-    public boolean isIconTintable;
-
-    /**
-     * Intent to launch when the preference is selected.
-     */
-    public Intent intent;
+    private static final String TAG = "Tile";
 
     /**
      * Optional list of user handles which the intent should be launched on.
      */
     public ArrayList<UserHandle> userHandle = new ArrayList<>();
 
-    /**
-     * Optional additional data for use by subclasses of the activity
-     */
-    public Bundle extras;
+    private final String mActivityPackage;
+    private final String mActivityName;
+    private final Intent mIntent;
 
-    /**
-     * Category in which the tile should be placed.
-     */
-    public String category;
+    private ActivityInfo mActivityInfo;
+    private CharSequence mSummaryOverride;
+    private Bundle mMetaData;
+    private String mCategory;
 
-    /**
-     * Priority of the intent filter that created this tile, used for display ordering.
-     */
-    public int priority;
+    public Tile(ActivityInfo activityInfo, String category) {
+        mActivityInfo = activityInfo;
+        mActivityPackage = mActivityInfo.packageName;
+        mActivityName = mActivityInfo.name;
+        mMetaData = activityInfo.metaData;
+        mCategory = category;
+        mIntent = new Intent().setClassName(mActivityPackage, mActivityName);
+    }
 
-    /**
-     * The metaData from the activity that defines this tile.
-     */
-    public Bundle metaData;
-
-    /**
-     * Optional key to use for this tile.
-     */
-    public String key;
-
-    /**
-     * Optional remote view which will be displayed instead of the regular title-summary item.
-     */
-    public RemoteViews remoteViews;
-
-    public Tile() {
-        // Empty
+    Tile(Parcel in) {
+        mActivityPackage = in.readString();
+        mActivityName = in.readString();
+        mIntent = new Intent().setClassName(mActivityPackage, mActivityName);
+        final int N = in.readInt();
+        for (int i = 0; i < N; i++) {
+            userHandle.add(UserHandle.CREATOR.createFromParcel(in));
+        }
+        mCategory = in.readString();
+        mMetaData = in.readBundle();
     }
 
     @Override
@@ -111,73 +95,242 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        TextUtils.writeToParcel(title, dest, flags);
-        TextUtils.writeToParcel(summary, dest, flags);
-        if (icon != null) {
-            dest.writeByte((byte) 1);
-            icon.writeToParcel(dest, flags);
-        } else {
-            dest.writeByte((byte) 0);
-        }
-        if (intent != null) {
-            dest.writeByte((byte) 1);
-            intent.writeToParcel(dest, flags);
-        } else {
-            dest.writeByte((byte) 0);
-        }
+        dest.writeString(mActivityPackage);
+        dest.writeString(mActivityName);
         final int N = userHandle.size();
         dest.writeInt(N);
         for (int i = 0; i < N; i++) {
             userHandle.get(i).writeToParcel(dest, flags);
         }
-        dest.writeBundle(extras);
-        dest.writeString(category);
-        dest.writeInt(priority);
-        dest.writeBundle(metaData);
-        dest.writeString(key);
-        dest.writeParcelable(remoteViews, flags);
-        dest.writeBoolean(isIconTintable);
+        dest.writeString(mCategory);
+        dest.writeBundle(mMetaData);
     }
 
-    public void readFromParcel(Parcel in) {
-        title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-        summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-        if (in.readByte() != 0) {
-            icon = Icon.CREATOR.createFromParcel(in);
-        }
-        if (in.readByte() != 0) {
-            intent = Intent.CREATOR.createFromParcel(in);
-        }
-        final int N = in.readInt();
-        for (int i = 0; i < N; i++) {
-            userHandle.add(UserHandle.CREATOR.createFromParcel(in));
-        }
-        extras = in.readBundle();
-        category = in.readString();
-        priority = in.readInt();
-        metaData = in.readBundle();
-        key = in.readString();
-        remoteViews = in.readParcelable(RemoteViews.class.getClassLoader());
-        isIconTintable = in.readBoolean();
+    public int getId() {
+        return Objects.hash(mActivityPackage, mActivityName);
     }
 
-    Tile(Parcel in) {
-        readFromParcel(in);
+    public String getDescription() {
+        return mActivityPackage + "/" + mActivityName;
+    }
+
+    public String getPackageName() {
+        return mActivityPackage;
+    }
+
+    /**
+     * Intent to launch when the preference is selected.
+     */
+    public Intent getIntent() {
+        return mIntent;
+    }
+
+    /**
+     * Category in which the tile should be placed.
+     */
+    public String getCategory() {
+        return mCategory;
+    }
+
+    public void setCategory(String newCategoryKey) {
+        mCategory = newCategoryKey;
+    }
+
+    /**
+     * Priority of this tile, used for display ordering.
+     */
+    public int getOrder() {
+        if (hasOrder()) {
+            return mMetaData.getInt(META_DATA_KEY_ORDER);
+        } else {
+            return 0;
+        }
+    }
+
+    public boolean hasOrder() {
+        return mMetaData.containsKey(META_DATA_KEY_ORDER)
+                && mMetaData.get(META_DATA_KEY_ORDER) instanceof Integer;
+    }
+
+    /**
+     * Title of the tile that is shown to the user.
+     */
+    public CharSequence getTitle(Context context) {
+        CharSequence title = null;
+        final PackageManager packageManager = context.getPackageManager();
+        if (mMetaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
+            if (mMetaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
+                try {
+                    final Resources res =
+                            packageManager.getResourcesForApplication(mActivityPackage);
+                    title = res.getString(mMetaData.getInt(META_DATA_PREFERENCE_TITLE));
+                } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
+                    Log.d(TAG, "Couldn't find info", e);
+                }
+            } else {
+                title = mMetaData.getString(META_DATA_PREFERENCE_TITLE);
+            }
+        }
+        // Set the preference title to the activity's label if no
+        // meta-data is found
+        if (title == null) {
+            title = getActivityInfo(context).loadLabel(packageManager);
+        }
+        return title;
+    }
+
+    /**
+     * Returns the raw metadata for summary, this is used for comparing 2 summary text without
+     * loading the real string.
+     */
+    public String getSummaryReference() {
+        if (mSummaryOverride != null) {
+            return mSummaryOverride.toString();
+        }
+        if (mMetaData != null && mMetaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
+            return mMetaData.get(META_DATA_PREFERENCE_SUMMARY).toString();
+        }
+        return null;
+    }
+
+    /**
+     * Overrides the summary. This can happen when injected tile wants to provide dynamic summary.
+     */
+    public void overrideSummary(CharSequence summaryOverride) {
+        mSummaryOverride = summaryOverride;
+    }
+
+    /**
+     * Optional summary describing what this tile controls.
+     */
+    public CharSequence getSummary(Context context) {
+        if (mSummaryOverride != null) {
+            return mSummaryOverride;
+        }
+        CharSequence summary = null;
+        final PackageManager packageManager = context.getPackageManager();
+        if (mMetaData != null) {
+            if (mMetaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
+                return null;
+            }
+            if (mMetaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
+                if (mMetaData.get(META_DATA_PREFERENCE_SUMMARY) instanceof Integer) {
+                    try {
+                        final Resources res =
+                                packageManager.getResourcesForApplication(mActivityPackage);
+                        summary = res.getString(mMetaData.getInt(META_DATA_PREFERENCE_SUMMARY));
+                    } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
+                        Log.d(TAG, "Couldn't find info", e);
+                    }
+                } else {
+                    summary = mMetaData.getString(META_DATA_PREFERENCE_SUMMARY);
+                }
+            }
+        }
+        return summary;
+    }
+
+    public void setMetaData(Bundle metaData) {
+        mMetaData = metaData;
+    }
+
+    /**
+     * The metaData from the activity that defines this tile.
+     */
+    public Bundle getMetaData() {
+        return mMetaData;
+    }
+
+    /**
+     * Optional key to use for this tile.
+     */
+    public String getKey(Context context) {
+        if (!hasKey()) {
+            return null;
+        }
+        if (mMetaData.get(META_DATA_PREFERENCE_KEYHINT) instanceof Integer) {
+            return context.getResources().getString(mMetaData.getInt(META_DATA_PREFERENCE_KEYHINT));
+        } else {
+            return mMetaData.getString(META_DATA_PREFERENCE_KEYHINT);
+        }
+    }
+
+    public boolean hasKey() {
+        return mMetaData != null && mMetaData.containsKey(META_DATA_PREFERENCE_KEYHINT);
+    }
+
+    /**
+     * Optional icon to show for this tile.
+     *
+     * @attr ref android.R.styleable#PreferenceHeader_icon
+     */
+    public Icon getIcon(Context context) {
+        if (context == null || mMetaData == null) {
+            return null;
+        }
+
+        int iconResId = mMetaData.getInt(META_DATA_PREFERENCE_ICON);
+        // Set the icon
+        if (iconResId == 0) {
+            // Only fallback to activityinfo.icon if metadata does not contain ICON_URI.
+            // ICON_URI should be loaded in app UI when need the icon object. Handling IPC at this
+            // level is too complex because we don't have a strong threading contract for this class
+            if (!mMetaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
+                iconResId = getActivityInfo(context).icon;
+            }
+        }
+        if (iconResId != 0) {
+            return Icon.createWithResource(getActivityInfo(context).packageName, iconResId);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Whether the icon can be tinted. This is true when icon needs to be monochrome (single-color)
+     */
+    public boolean isIconTintable(Context context) {
+        if (mMetaData != null
+                && mMetaData.containsKey(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE)) {
+            return mMetaData.getBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE);
+        }
+        final String pkgName = context.getPackageName();
+        // If this drawable is coming from outside Settings, tint it to match the color.
+        final ActivityInfo activityInfo = getActivityInfo(context);
+        return activityInfo != null
+                && !TextUtils.equals(pkgName, activityInfo.packageName);
+    }
+
+    private ActivityInfo getActivityInfo(Context context) {
+        if (mActivityInfo == null) {
+            final PackageManager pm = context.getApplicationContext().getPackageManager();
+            final Intent intent = new Intent().setClassName(mActivityPackage, mActivityName);
+            final List<ResolveInfo> infoList =
+                    pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+            if (infoList != null && !infoList.isEmpty()) {
+                mActivityInfo = infoList.get(0).activityInfo;
+            }
+        }
+        return mActivityInfo;
     }
 
     public static final Creator<Tile> CREATOR = new Creator<Tile>() {
         public Tile createFromParcel(Parcel source) {
             return new Tile(source);
         }
+
         public Tile[] newArray(int size) {
             return new Tile[size];
         }
     };
 
     public boolean isPrimaryProfileOnly() {
-        String profile = metaData != null ?
-            metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
+        String profile = mMetaData != null ?
+                mMetaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
         profile = (profile != null ? profile : PROFILE_ALL);
         return TextUtils.equals(profile, PROFILE_PRIMARY);
     }
+
+    public static final Comparator<Tile> TILE_COMPARATOR =
+            (lhs, rhs) -> rhs.getOrder() - lhs.getOrder();
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 96ed0cd..67cfe6b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -20,11 +20,8 @@
 import android.content.IContentProvider;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -36,19 +33,19 @@
 import android.util.Pair;
 
 import androidx.annotation.VisibleForTesting;
+
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 public class TileUtils {
 
-    private static final boolean DEBUG = false;
     private static final boolean DEBUG_TIMING = false;
 
     private static final String LOG_TAG = "TileUtils";
+    @VisibleForTesting
+    static final String SETTING_PKG = "com.android.settings";
 
     /**
      * Settings will search for system activities of this action and add them as a top level
@@ -65,21 +62,17 @@
      *
      * <p>A summary my be defined by meta-data named {@link #META_DATA_PREFERENCE_SUMMARY}
      */
-    public static final String EXTRA_SETTINGS_ACTION =
-            "com.android.settings.action.EXTRA_SETTINGS";
+    public static final String EXTRA_SETTINGS_ACTION = "com.android.settings.action.EXTRA_SETTINGS";
 
     /**
      * @See {@link #EXTRA_SETTINGS_ACTION}.
      */
-    private static final String IA_SETTINGS_ACTION =
-            "com.android.settings.action.IA_SETTINGS";
-
+    public static final String IA_SETTINGS_ACTION = "com.android.settings.action.IA_SETTINGS";
 
     /**
      * Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities.
      */
-    private static final String SETTINGS_ACTION =
-            "com.android.settings.action.SETTINGS";
+    private static final String SETTINGS_ACTION = "com.android.settings.action.SETTINGS";
 
     private static final String OPERATOR_SETTINGS =
             "com.android.settings.OPERATOR_APPLICATION_SETTING";
@@ -104,7 +97,7 @@
      * The key used to get the package name of the icon resource for the preference.
      */
     private static final String EXTRA_PREFERENCE_ICON_PACKAGE =
-        "com.android.settings.icon_package";
+            "com.android.settings.icon_package";
 
     /**
      * Name of the meta-data item that should be set in the AndroidManifest.xml
@@ -113,6 +106,12 @@
     public static final String META_DATA_PREFERENCE_KEYHINT = "com.android.settings.keyhint";
 
     /**
+     * Order of the item that should be displayed on screen. Bigger value items displays closer on
+     * top.
+     */
+    public static final String META_DATA_KEY_ORDER = "com.android.settings.order";
+
+    /**
      * Name of the meta-data item that should be set in the AndroidManifest.xml
      * to specify the icon that should be displayed for the preference.
      */
@@ -124,6 +123,12 @@
      */
     public static final String META_DATA_PREFERENCE_ICON_BACKGROUND_HINT =
             "com.android.settings.bg.hint";
+    /**
+     * Name of the meta-data item that should be set in the AndroidManifest.xml
+     * to specify the icon background color as raw ARGB.
+     */
+    public static final String META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB =
+            "com.android.settings.bg.argb";
 
     /**
      * Name of the meta-data item that should be set in the AndroidManifest.xml
@@ -167,8 +172,6 @@
     public static final String META_DATA_PREFERENCE_SUMMARY_URI =
             "com.android.settings.summary_uri";
 
-    public static final String SETTING_PKG = "com.android.settings";
-
     /**
      * Value for {@link #META_DATA_KEY_PROFILE}. When the device has a managed profile,
      * the app will always be run in the primary profile.
@@ -198,36 +201,10 @@
     public static final String META_DATA_KEY_PROFILE = "com.android.settings.profile";
 
     /**
-     * Build a list of DashboardCategory. Each category must be defined in manifest.
-     * eg: .Settings$DeviceSettings
-     * @deprecated
+     * Build a list of DashboardCategory.
      */
-    @Deprecated
     public static List<DashboardCategory> getCategories(Context context,
             Map<Pair<String, String>, Tile> cache) {
-        return getCategories(context, cache, true /*categoryDefinedInManifest*/);
-    }
-
-    /**
-     * Build a list of DashboardCategory.
-     * @param categoryDefinedInManifest If true, an dummy activity must exists in manifest to
-     * represent this category (eg: .Settings$DeviceSettings)
-     */
-    public static List<DashboardCategory> getCategories(Context context,
-            Map<Pair<String, String>, Tile> cache, boolean categoryDefinedInManifest) {
-        return getCategories(context, cache, categoryDefinedInManifest, null, SETTING_PKG);
-    }
-
-    /**
-     * Build a list of DashboardCategory.
-     * @param categoryDefinedInManifest If true, an dummy activity must exists in manifest to
-     * represent this category (eg: .Settings$DeviceSettings)
-     * @param extraAction additional intent filter action to be usetileutild to build the dashboard
-     * categories
-     */
-    public static List<DashboardCategory> getCategories(Context context,
-            Map<Pair<String, String>, Tile> cache, boolean categoryDefinedInManifest,
-            String extraAction, String settingPkg) {
         final long startTime = System.currentTimeMillis();
         boolean setup = Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0)
                 != 0;
@@ -237,37 +214,30 @@
             // TODO: Needs much optimization, too many PM queries going on here.
             if (user.getIdentifier() == ActivityManager.getCurrentUser()) {
                 // Only add Settings for this user.
-                getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true,
-                        settingPkg);
+                getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true);
                 getTilesForAction(context, user, OPERATOR_SETTINGS, cache,
-                        OPERATOR_DEFAULT_CATEGORY, tiles, false, true, settingPkg);
+                        OPERATOR_DEFAULT_CATEGORY, tiles, false);
                 getTilesForAction(context, user, MANUFACTURER_SETTINGS, cache,
-                        MANUFACTURER_DEFAULT_CATEGORY, tiles, false, true, settingPkg);
+                        MANUFACTURER_DEFAULT_CATEGORY, tiles, false);
             }
             if (setup) {
-                getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false,
-                        settingPkg);
-                if (!categoryDefinedInManifest) {
-                    getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false,
-                            settingPkg);
-                    if (extraAction != null) {
-                        getTilesForAction(context, user, extraAction, cache, null, tiles, false,
-                                settingPkg);
-                    }
-                }
+                getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
+                getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false);
             }
         }
 
         HashMap<String, DashboardCategory> categoryMap = new HashMap<>();
         for (Tile tile : tiles) {
-            DashboardCategory category = categoryMap.get(tile.category);
+            final String categoryKey = tile.getCategory();
+            DashboardCategory category = categoryMap.get(categoryKey);
             if (category == null) {
-                category = createCategory(context, tile.category, categoryDefinedInManifest);
+                category = new DashboardCategory(categoryKey);
+
                 if (category == null) {
-                    Log.w(LOG_TAG, "Couldn't find category " + tile.category);
+                    Log.w(LOG_TAG, "Couldn't find category " + categoryKey);
                     continue;
                 }
-                categoryMap.put(category.key, category);
+                categoryMap.put(categoryKey, category);
             }
             category.addTile(tile);
         }
@@ -275,83 +245,25 @@
         for (DashboardCategory category : categories) {
             category.sortTiles();
         }
-        Collections.sort(categories, CATEGORY_COMPARATOR);
-        if (DEBUG_TIMING) Log.d(LOG_TAG, "getCategories took "
-                + (System.currentTimeMillis() - startTime) + " ms");
+
+        if (DEBUG_TIMING) {
+            Log.d(LOG_TAG, "getCategories took "
+                    + (System.currentTimeMillis() - startTime) + " ms");
+        }
         return categories;
     }
 
-    /**
-     * Create a new DashboardCategory from key.
-     *
-     * @param context Context to query intent
-     * @param categoryKey The category key
-     * @param categoryDefinedInManifest If true, an dummy activity must exists in manifest to
-     * represent this category (eg: .Settings$DeviceSettings)
-     */
-    private static DashboardCategory createCategory(Context context, String categoryKey,
-            boolean categoryDefinedInManifest) {
-        DashboardCategory category = new DashboardCategory();
-        category.key = categoryKey;
-        if (!categoryDefinedInManifest) {
-            return category;
-        }
-        PackageManager pm = context.getPackageManager();
-        List<ResolveInfo> results = pm.queryIntentActivities(new Intent(categoryKey), 0);
-        if (results.size() == 0) {
-            return null;
-        }
-        for (ResolveInfo resolved : results) {
-            if (!resolved.system) {
-                // Do not allow any app to add to settings, only system ones.
-                continue;
-            }
-            category.title = resolved.activityInfo.loadLabel(pm);
-            category.priority = SETTING_PKG.equals(
-                    resolved.activityInfo.applicationInfo.packageName) ? resolved.priority : 0;
-            if (DEBUG) Log.d(LOG_TAG, "Adding category " + category.title);
-        }
-
-        return category;
-    }
-
-    private static void getTilesForAction(Context context,
+    @VisibleForTesting
+    static void getTilesForAction(Context context,
             UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache,
-            String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings,
-            String settingPkg) {
-        getTilesForAction(context, user, action, addedCache, defaultCategory, outTiles,
-                requireSettings, requireSettings, settingPkg);
-    }
-
-    private static void getTilesForAction(Context context,
-            UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache,
-            String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings,
-            boolean usePriority, String settingPkg) {
-        Intent intent = new Intent(action);
+            String defaultCategory, List<Tile> outTiles, boolean requireSettings) {
+        final Intent intent = new Intent(action);
         if (requireSettings) {
-            intent.setPackage(settingPkg);
+            intent.setPackage(SETTING_PKG);
         }
-        getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles,
-                usePriority, true, true);
-    }
-
-    public static void getTilesForIntent(
-            Context context, UserHandle user, Intent intent,
-            Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles,
-            boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon) {
-        getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles,
-                usePriority, checkCategory, forceTintExternalIcon, false /* shouldUpdateTiles */);
-    }
-
-    public static void getTilesForIntent(
-            Context context, UserHandle user, Intent intent,
-            Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles,
-            boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon,
-            boolean shouldUpdateTiles) {
-        PackageManager pm = context.getPackageManager();
+        final PackageManager pm = context.getPackageManager();
         List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
                 PackageManager.GET_META_DATA, user.getIdentifier());
-        Map<String, IContentProvider> providerMap = new HashMap<>();
         for (ResolveInfo resolved : results) {
             if (!resolved.system) {
                 // Do not allow any app to add to settings, only system ones.
@@ -362,7 +274,7 @@
             String categoryKey = defaultCategory;
 
             // Load category
-            if (checkCategory && ((metaData == null) || !metaData.containsKey(EXTRA_CATEGORY_KEY))
+            if ((metaData == null || !metaData.containsKey(EXTRA_CATEGORY_KEY))
                     && categoryKey == null) {
                 Log.w(LOG_TAG, "Found " + resolved.activityInfo.name + " for intent "
                         + intent + " missing metadata "
@@ -372,22 +284,13 @@
                 categoryKey = metaData.getString(EXTRA_CATEGORY_KEY);
             }
 
-            Pair<String, String> key = new Pair<String, String>(activityInfo.packageName,
-                    activityInfo.name);
+            Pair<String, String> key = new Pair<>(activityInfo.packageName, activityInfo.name);
             Tile tile = addedCache.get(key);
             if (tile == null) {
-                tile = new Tile();
-                tile.intent = new Intent().setClassName(
-                        activityInfo.packageName, activityInfo.name);
-                tile.category = categoryKey;
-                tile.priority = usePriority ? resolved.priority : 0;
-                tile.metaData = activityInfo.metaData;
-                updateTileData(context, tile, activityInfo, activityInfo.applicationInfo,
-                        pm, providerMap, forceTintExternalIcon);
-                if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title);
+                tile = new Tile(activityInfo, categoryKey);
                 addedCache.put(key, tile);
-            } else if (shouldUpdateTiles) {
-                updateSummaryAndTitle(context, providerMap, tile);
+            } else {
+                tile.setMetaData(metaData);
             }
 
             if (!tile.userHandle.contains(user)) {
@@ -399,126 +302,12 @@
         }
     }
 
-    private static boolean updateTileData(Context context, Tile tile,
-            ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm,
-            Map<String, IContentProvider> providerMap, boolean forceTintExternalIcon) {
-        if (applicationInfo.isSystemApp()) {
-            boolean forceTintIcon = false;
-            int icon = 0;
-            Pair<String, Integer> iconFromUri = null;
-            CharSequence title = null;
-            String summary = null;
-            String keyHint = null;
-            boolean isIconTintable = false;
-
-            // Get the activity's meta-data
-            try {
-                Resources res = pm.getResourcesForApplication(applicationInfo.packageName);
-                Bundle metaData = activityInfo.metaData;
-
-                if (forceTintExternalIcon
-                        && !context.getPackageName().equals(applicationInfo.packageName)) {
-                    isIconTintable = true;
-                    forceTintIcon = true;
-                }
-
-                if (res != null && metaData != null) {
-                    if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
-                        icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
-                    }
-                    if (metaData.containsKey(META_DATA_PREFERENCE_ICON_TINTABLE)) {
-                        if (forceTintIcon) {
-                            Log.w(LOG_TAG, "Ignoring icon tintable for " + activityInfo);
-                        } else {
-                            isIconTintable =
-                                    metaData.getBoolean(META_DATA_PREFERENCE_ICON_TINTABLE);
-                        }
-                    }
-                    if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
-                        if (metaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
-                            title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
-                        } else {
-                            title = metaData.getString(META_DATA_PREFERENCE_TITLE);
-                        }
-                    }
-                    if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
-                        if (metaData.get(META_DATA_PREFERENCE_SUMMARY) instanceof Integer) {
-                            summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
-                        } else {
-                            summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY);
-                        }
-                    }
-                    if (metaData.containsKey(META_DATA_PREFERENCE_KEYHINT)) {
-                        if (metaData.get(META_DATA_PREFERENCE_KEYHINT) instanceof Integer) {
-                            keyHint = res.getString(metaData.getInt(META_DATA_PREFERENCE_KEYHINT));
-                        } else {
-                            keyHint = metaData.getString(META_DATA_PREFERENCE_KEYHINT);
-                        }
-                    }
-                }
-            } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
-                if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e);
-            }
-
-            // Set the preference title to the activity's label if no
-            // meta-data is found
-            if (TextUtils.isEmpty(title)) {
-                title = activityInfo.loadLabel(pm).toString();
-            }
-
-            // Set the icon
-            if (icon == 0) {
-                // Only fallback to activityinfo.icon if metadata does not contain ICON_URI.
-                // ICON_URI should be loaded in app UI when need the icon object.
-                if (!tile.metaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
-                    icon = activityInfo.icon;
-                }
-            }
-            if (icon != 0) {
-                tile.icon = Icon.createWithResource(activityInfo.packageName, icon);
-            }
-
-            // Set title and summary for the preference
-            tile.title = title;
-            tile.summary = summary;
-            // Replace the intent with this specific activity
-            tile.intent = new Intent().setClassName(activityInfo.packageName,
-                    activityInfo.name);
-            // Suggest a key for this tile
-            tile.key = keyHint;
-            tile.isIconTintable = isIconTintable;
-
-            return true;
-        }
-
-        return false;
-    }
-
-    private static void updateSummaryAndTitle(
-            Context context, Map<String, IContentProvider> providerMap, Tile tile) {
-        if (tile == null || tile.metaData == null
-                || !tile.metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
-            return;
-        }
-
-        String uriString = tile.metaData.getString(META_DATA_PREFERENCE_SUMMARY_URI);
-        Bundle bundle = getBundleFromUri(context, uriString, providerMap);
-        String overrideSummary = getString(bundle, META_DATA_PREFERENCE_SUMMARY);
-        String overrideTitle = getString(bundle, META_DATA_PREFERENCE_TITLE);
-        if (overrideSummary != null) {
-            tile.remoteViews.setTextViewText(android.R.id.summary, overrideSummary);
-        }
-
-        if (overrideTitle != null) {
-            tile.remoteViews.setTextViewText(android.R.id.title, overrideTitle);
-        }
-    }
-
     /**
      * Gets the icon package name and resource id from content provider.
-     * @param context context
+     *
+     * @param context     context
      * @param packageName package name of the target activity
-     * @param uriString URI for the content provider
+     * @param uriString   URI for the content provider
      * @param providerMap Maps URI authorities to providers
      * @return package name and resource id of the icon specified
      */
@@ -546,10 +335,11 @@
 
     /**
      * Gets text associated with the input key from the content provider.
-     * @param context context
-     * @param uriString URI for the content provider
+     *
+     * @param context     context
+     * @param uriString   URI for the content provider
      * @param providerMap Maps URI authorities to providers
-     * @param key Key mapping to the text in bundle returned by the content provider
+     * @param key         Key mapping to the text in bundle returned by the content provider
      * @return Text associated with the key, if returned by the content provider
      */
     public static String getTextFromUri(Context context, String uriString,
@@ -579,10 +369,6 @@
         }
     }
 
-    private static String getString(Bundle bundle, String key) {
-        return bundle == null ? null : bundle.getString(key);
-    }
-
     private static IContentProvider getProviderFromUri(Context context, Uri uri,
             Map<String, IContentProvider> providerMap) {
         if (uri == null) {
@@ -609,12 +395,4 @@
         }
         return pathSegments.get(0);
     }
-
-    private static final Comparator<DashboardCategory> CATEGORY_COMPARATOR =
-            new Comparator<DashboardCategory>() {
-        @Override
-        public int compare(DashboardCategory lhs, DashboardCategory rhs) {
-            return rhs.priority - lhs.priority;
-        }
-    };
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/UserAdapter.java b/packages/SettingsLib/src/com/android/settingslib/drawer/UserAdapter.java
deleted file mode 100644
index 8a09df2..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/UserAdapter.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.drawer;
-
-import android.app.ActivityManager;
-
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.database.DataSetObserver;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.SpinnerAdapter;
-import android.widget.TextView;
-import com.android.internal.util.UserIcons;
-import com.android.settingslib.drawable.UserIconDrawable;
-
-import com.android.settingslib.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Adapter for a spinner that shows a list of users.
- */
-public class UserAdapter implements SpinnerAdapter, ListAdapter {
-    /** Holder for user details */
-    public static class UserDetails {
-        private final UserHandle mUserHandle;
-        private final String mName;
-        private final Drawable mIcon;
-
-        public UserDetails(UserHandle userHandle, UserManager um, Context context) {
-            mUserHandle = userHandle;
-            UserInfo userInfo = um.getUserInfo(mUserHandle.getIdentifier());
-            Drawable icon;
-            if (userInfo.isManagedProfile()) {
-                mName = context.getString(R.string.managed_user_title);
-                icon = context.getDrawable(
-                    com.android.internal.R.drawable.ic_corp_badge);
-            } else {
-                mName = userInfo.name;
-                final int userId = userInfo.id;
-                if (um.getUserIcon(userId) != null) {
-                    icon = new BitmapDrawable(context.getResources(), um.getUserIcon(userId));
-                } else {
-                    icon = UserIcons.getDefaultUserIcon(
-                            context.getResources(), userId, /* light= */ false);
-                }
-            }
-            this.mIcon = encircle(context, icon);
-        }
-
-        private static Drawable encircle(Context context, Drawable icon) {
-            return new UserIconDrawable(UserIconDrawable.getSizeForList(context))
-                    .setIconDrawable(icon).bake();
-        }
-    }
-    private ArrayList<UserDetails> data;
-    private final LayoutInflater mInflater;
-
-    public UserAdapter(Context context, ArrayList<UserDetails> users) {
-        if (users == null) {
-            throw new IllegalArgumentException("A list of user details must be provided");
-        }
-        this.data = users;
-        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-    }
-
-    public UserHandle getUserHandle(int position) {
-        if (position < 0 || position >= data.size()) {
-            return null;
-        }
-        return data.get(position).mUserHandle;
-    }
-
-    @Override
-    public View getDropDownView(int position, View convertView, ViewGroup parent) {
-        final View row = convertView != null ? convertView : createUser(parent);
-
-        UserDetails user = data.get(position);
-        ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(user.mIcon);
-        ((TextView) row.findViewById(android.R.id.title)).setText(getTitle(user));
-        return row;
-    }
-
-    private int getTitle(UserDetails user) {
-        int userHandle = user.mUserHandle.getIdentifier();
-        if (userHandle == UserHandle.USER_CURRENT
-                || userHandle == ActivityManager.getCurrentUser()) {
-            return R.string.category_personal;
-        } else {
-            return R.string.category_work;
-        }
-    }
-
-    private View createUser(ViewGroup parent) {
-        return mInflater.inflate(R.layout.user_preference, parent, false);
-    }
-
-    @Override
-    public void registerDataSetObserver(DataSetObserver observer) {
-        // We don't support observers
-    }
-
-    @Override
-    public void unregisterDataSetObserver(DataSetObserver observer) {
-        // We don't support observers
-    }
-
-    @Override
-    public int getCount() {
-        return data.size();
-    }
-
-    @Override
-    public UserDetails getItem(int position) {
-        return data.get(position);
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return data.get(position).mUserHandle.getIdentifier();
-    }
-
-    @Override
-    public boolean hasStableIds() {
-        return false;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        return getDropDownView(position, convertView, parent);
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        return 0;
-    }
-
-    @Override
-    public int getViewTypeCount() {
-        return 1;
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return data.isEmpty();
-    }
-
-    @Override
-    public boolean areAllItemsEnabled() {
-        return true;
-    }
-
-    @Override
-    public boolean isEnabled(int position) {
-        return true;
-    }
-
-    /**
-     * Creates a {@link UserAdapter} if there is more than one profile on the device.
-     *
-     * <p> The adapter can be used to populate a spinner that switches between the Settings
-     * app on the different profiles.
-     *
-     * @return a {@link UserAdapter} or null if there is only one profile.
-     */
-    public static UserAdapter createUserSpinnerAdapter(UserManager userManager,
-            Context context) {
-        List<UserHandle> userProfiles = userManager.getUserProfiles();
-        if (userProfiles.size() < 2) {
-            return null;
-        }
-
-        UserHandle myUserHandle = new UserHandle(UserHandle.myUserId());
-        // The first option should be the current profile
-        userProfiles.remove(myUserHandle);
-        userProfiles.add(0, myUserHandle);
-
-        return createUserAdapter(userManager, context, userProfiles);
-    }
-
-    public static UserAdapter createUserAdapter(UserManager userManager,
-            Context context, List<UserHandle> userProfiles) {
-        ArrayList<UserDetails> userDetails = new ArrayList<UserDetails>(userProfiles.size());
-        final int count = userProfiles.size();
-        for (int i = 0; i < count; i++) {
-            userDetails.add(new UserDetails(userProfiles.get(i), userManager, context));
-        }
-        return new UserAdapter(context, userDetails);
-    }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index e5d97c9..3c0f6fe 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -256,11 +256,12 @@
         }
     }
 
-    public void launchSettings(DreamInfo dreamInfo) {
+    public void launchSettings(Context uiContext, DreamInfo dreamInfo) {
         logd("launchSettings(%s)", dreamInfo);
-        if (dreamInfo == null || dreamInfo.settingsComponentName == null)
+        if (dreamInfo == null || dreamInfo.settingsComponentName == null) {
             return;
-        mContext.startActivity(new Intent().setComponent(dreamInfo.settingsComponentName));
+        }
+        uiContext.startActivity(new Intent().setComponent(dreamInfo.settingsComponentName));
     }
 
     public void preview(DreamInfo dreamInfo) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
index 8a1c4ef..94efc71 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.fuelgauge;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -90,6 +91,13 @@
         if (TextUtils.equals(pkg, defaultDialer)) {
             return true;
         }
+
+        final DevicePolicyManager devicePolicyManager = mAppContext.getSystemService(
+                DevicePolicyManager.class);
+        if (devicePolicyManager.packageHasActiveAdmins(pkg)) {
+            return true;
+        }
+
         return false;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java
new file mode 100644
index 0000000..ad1368c
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settingslib.inputmethod;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.text.TextUtils;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.settingslib.R;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
+public class InputMethodAndSubtypeEnablerManagerCompat implements
+        Preference.OnPreferenceChangeListener {
+
+    private final PreferenceFragmentCompat mFragment;
+
+    private boolean mHaveHardKeyboard;
+    private final HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap =
+            new HashMap<>();
+    private final HashMap<String, TwoStatePreference> mAutoSelectionPrefsMap = new HashMap<>();
+    private InputMethodManager mImm;
+    // TODO: Change mInputMethodInfoList to Map
+    private List<InputMethodInfo> mInputMethodInfoList;
+    private final Collator mCollator = Collator.getInstance();
+
+    public InputMethodAndSubtypeEnablerManagerCompat(PreferenceFragmentCompat fragment) {
+        mFragment = fragment;
+        mImm = fragment.getContext().getSystemService(InputMethodManager.class);
+
+        mInputMethodInfoList = mImm.getInputMethodList();
+    }
+
+    public void init(PreferenceFragmentCompat fragment, String targetImi, PreferenceScreen root) {
+        final Configuration config = fragment.getResources().getConfiguration();
+        mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
+
+        for (final InputMethodInfo imi : mInputMethodInfoList) {
+            // Add subtype preferences of this IME when it is specified or no IME is specified.
+            if (imi.getId().equals(targetImi) || TextUtils.isEmpty(targetImi)) {
+                addInputMethodSubtypePreferences(fragment, imi, root);
+            }
+        }
+    }
+
+    public void refresh(Context context, PreferenceFragmentCompat fragment) {
+        // Refresh internal states in mInputMethodSettingValues to keep the latest
+        // "InputMethodInfo"s and "InputMethodSubtype"s
+        InputMethodSettingValuesWrapper
+                .getInstance(context).refreshAllInputMethodAndSubtypes();
+        InputMethodAndSubtypeUtilCompat.loadInputMethodSubtypeList(fragment,
+                context.getContentResolver(), mInputMethodInfoList, mInputMethodAndSubtypePrefsMap);
+        updateAutoSelectionPreferences();
+    }
+
+    public void save(Context context, PreferenceFragmentCompat fragment) {
+        InputMethodAndSubtypeUtilCompat.saveInputMethodSubtypeList(fragment,
+                context.getContentResolver(), mInputMethodInfoList, mHaveHardKeyboard);
+    }
+
+    @Override
+    public boolean onPreferenceChange(final Preference pref, final Object newValue) {
+        if (!(newValue instanceof Boolean)) {
+            return true; // Invoke default behavior.
+        }
+        final boolean isChecking = (Boolean) newValue;
+        for (final String imiId : mAutoSelectionPrefsMap.keySet()) {
+            // An auto select subtype preference is changing.
+            if (mAutoSelectionPrefsMap.get(imiId) == pref) {
+                final TwoStatePreference autoSelectionPref = (TwoStatePreference) pref;
+                autoSelectionPref.setChecked(isChecking);
+                // Enable or disable subtypes depending on the auto selection preference.
+                setAutoSelectionSubtypesEnabled(imiId, autoSelectionPref.isChecked());
+                return false;
+            }
+        }
+        // A subtype preference is changing.
+        if (pref instanceof InputMethodSubtypePreference) {
+            final InputMethodSubtypePreference subtypePref = (InputMethodSubtypePreference) pref;
+            subtypePref.setChecked(isChecking);
+            if (!subtypePref.isChecked()) {
+                // It takes care of the case where no subtypes are explicitly enabled then the auto
+                // selection preference is going to be checked.
+                updateAutoSelectionPreferences();
+            }
+            return false;
+        }
+        return true; // Invoke default behavior.
+    }
+
+    private void addInputMethodSubtypePreferences(PreferenceFragmentCompat fragment,
+            InputMethodInfo imi, final PreferenceScreen root) {
+        Context prefContext = fragment.getPreferenceManager().getContext();
+
+        final int subtypeCount = imi.getSubtypeCount();
+        if (subtypeCount <= 1) {
+            return;
+        }
+        final String imiId = imi.getId();
+        final PreferenceCategory keyboardSettingsCategory =
+                new PreferenceCategory(prefContext);
+        root.addPreference(keyboardSettingsCategory);
+        final PackageManager pm = prefContext.getPackageManager();
+        final CharSequence label = imi.loadLabel(pm);
+
+        keyboardSettingsCategory.setTitle(label);
+        keyboardSettingsCategory.setKey(imiId);
+        // TODO: Use toggle Preference if images are ready.
+        final TwoStatePreference autoSelectionPref =
+                new SwitchWithNoTextPreference(prefContext);
+        mAutoSelectionPrefsMap.put(imiId, autoSelectionPref);
+        keyboardSettingsCategory.addPreference(autoSelectionPref);
+        autoSelectionPref.setOnPreferenceChangeListener(this);
+
+        final PreferenceCategory activeInputMethodsCategory =
+                new PreferenceCategory(prefContext);
+        activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes);
+        root.addPreference(activeInputMethodsCategory);
+
+        CharSequence autoSubtypeLabel = null;
+        final ArrayList<Preference> subtypePreferences = new ArrayList<>();
+        for (int index = 0; index < subtypeCount; ++index) {
+            final InputMethodSubtype subtype = imi.getSubtypeAt(index);
+            if (subtype.overridesImplicitlyEnabledSubtype()) {
+                if (autoSubtypeLabel == null) {
+                    autoSubtypeLabel = InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(
+                            subtype, prefContext, imi);
+                }
+            } else {
+                final Preference subtypePref = new InputMethodSubtypePreference(
+                        prefContext, subtype, imi);
+                subtypePreferences.add(subtypePref);
+            }
+        }
+        subtypePreferences.sort((lhs, rhs) -> {
+            if (lhs instanceof InputMethodSubtypePreference) {
+                return ((InputMethodSubtypePreference) lhs).compareTo(rhs, mCollator);
+            }
+            return lhs.compareTo(rhs);
+        });
+        for (final Preference pref : subtypePreferences) {
+            activeInputMethodsCategory.addPreference(pref);
+            pref.setOnPreferenceChangeListener(this);
+            InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
+        }
+        mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences);
+        if (TextUtils.isEmpty(autoSubtypeLabel)) {
+            autoSelectionPref.setTitle(
+                    R.string.use_system_language_to_select_input_method_subtypes);
+        } else {
+            autoSelectionPref.setTitle(autoSubtypeLabel);
+        }
+    }
+
+    private boolean isNoSubtypesExplicitlySelected(final String imiId) {
+        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
+        for (final Preference pref : subtypePrefs) {
+            if (pref instanceof TwoStatePreference && ((TwoStatePreference) pref).isChecked()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private void setAutoSelectionSubtypesEnabled(final String imiId,
+            final boolean autoSelectionEnabled) {
+        final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
+        if (autoSelectionPref == null) {
+            return;
+        }
+        autoSelectionPref.setChecked(autoSelectionEnabled);
+        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
+        for (final Preference pref : subtypePrefs) {
+            if (pref instanceof TwoStatePreference) {
+                // When autoSelectionEnabled is true, all subtype prefs need to be disabled with
+                // implicitly checked subtypes. In case of false, all subtype prefs need to be
+                // enabled.
+                pref.setEnabled(!autoSelectionEnabled);
+                if (autoSelectionEnabled) {
+                    ((TwoStatePreference) pref).setChecked(false);
+                }
+            }
+        }
+        if (autoSelectionEnabled) {
+            InputMethodAndSubtypeUtilCompat.saveInputMethodSubtypeList(
+                    mFragment, mFragment.getContext().getContentResolver(),
+                    mInputMethodInfoList, mHaveHardKeyboard);
+            updateImplicitlyEnabledSubtypes(imiId);
+        }
+    }
+
+    private void updateImplicitlyEnabledSubtypes(final String targetImiId) {
+        // When targetImiId is null, apply to all subtypes of all IMEs
+        for (final InputMethodInfo imi : mInputMethodInfoList) {
+            final String imiId = imi.getId();
+            final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
+            // No need to update implicitly enabled subtypes when the user has unchecked the
+            // "subtype auto selection".
+            if (autoSelectionPref == null || !autoSelectionPref.isChecked()) {
+                continue;
+            }
+            if (imiId.equals(targetImiId) || targetImiId == null) {
+                updateImplicitlyEnabledSubtypesOf(imi);
+            }
+        }
+    }
+
+    private void updateImplicitlyEnabledSubtypesOf(final InputMethodInfo imi) {
+        final String imiId = imi.getId();
+        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
+        final List<InputMethodSubtype> implicitlyEnabledSubtypes =
+                mImm.getEnabledInputMethodSubtypeList(imi, true);
+        if (subtypePrefs == null || implicitlyEnabledSubtypes == null) {
+            return;
+        }
+        for (final Preference pref : subtypePrefs) {
+            if (!(pref instanceof TwoStatePreference)) {
+                continue;
+            }
+            final TwoStatePreference subtypePref = (TwoStatePreference) pref;
+            subtypePref.setChecked(false);
+            for (final InputMethodSubtype subtype : implicitlyEnabledSubtypes) {
+                final String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode();
+                if (subtypePref.getKey().equals(implicitlyEnabledSubtypePrefKey)) {
+                    subtypePref.setChecked(true);
+                    break;
+                }
+            }
+        }
+    }
+
+    private void updateAutoSelectionPreferences() {
+        for (final String imiId : mInputMethodAndSubtypePrefsMap.keySet()) {
+            setAutoSelectionSubtypesEnabled(imiId, isNoSubtypesExplicitlySelected(imiId));
+        }
+        updateImplicitlyEnabledSubtypes(null /* targetImiId */  /* check */);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
new file mode 100644
index 0000000..9ad2adb
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settingslib.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.icu.text.ListFormatter;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.app.LocaleHelper;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
+// TODO: Consolidate this with {@link InputMethodSettingValuesWrapper}.
+public class InputMethodAndSubtypeUtilCompat {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "InputMethdAndSubtypeUtlCompat";
+
+    private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
+    private static final char INPUT_METHOD_SEPARATER = ':';
+    private static final char INPUT_METHOD_SUBTYPE_SEPARATER = ';';
+    private static final int NOT_A_SUBTYPE_ID = -1;
+
+    private static final TextUtils.SimpleStringSplitter sStringInputMethodSplitter
+            = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATER);
+
+    private static final TextUtils.SimpleStringSplitter sStringInputMethodSubtypeSplitter
+            = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER);
+
+    // InputMethods and subtypes are saved in the settings as follows:
+    // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1
+    public static String buildInputMethodsAndSubtypesString(
+            final HashMap<String, HashSet<String>> imeToSubtypesMap) {
+        final StringBuilder builder = new StringBuilder();
+        for (final String imi : imeToSubtypesMap.keySet()) {
+            if (builder.length() > 0) {
+                builder.append(INPUT_METHOD_SEPARATER);
+            }
+            final HashSet<String> subtypeIdSet = imeToSubtypesMap.get(imi);
+            builder.append(imi);
+            for (final String subtypeId : subtypeIdSet) {
+                builder.append(INPUT_METHOD_SUBTYPE_SEPARATER).append(subtypeId);
+            }
+        }
+        return builder.toString();
+    }
+
+    private static String buildInputMethodsString(final HashSet<String> imiList) {
+        final StringBuilder builder = new StringBuilder();
+        for (final String imi : imiList) {
+            if (builder.length() > 0) {
+                builder.append(INPUT_METHOD_SEPARATER);
+            }
+            builder.append(imi);
+        }
+        return builder.toString();
+    }
+
+    private static int getInputMethodSubtypeSelected(ContentResolver resolver) {
+        try {
+            return Settings.Secure.getInt(resolver,
+                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE);
+        } catch (SettingNotFoundException e) {
+            return NOT_A_SUBTYPE_ID;
+        }
+    }
+
+    private static boolean isInputMethodSubtypeSelected(ContentResolver resolver) {
+        return getInputMethodSubtypeSelected(resolver) != NOT_A_SUBTYPE_ID;
+    }
+
+    private static void putSelectedInputMethodSubtype(ContentResolver resolver, int hashCode) {
+        Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, hashCode);
+    }
+
+    // Needs to modify InputMethodManageService if you want to change the format of saved string.
+    static HashMap<String, HashSet<String>> getEnabledInputMethodsAndSubtypeList(
+            ContentResolver resolver) {
+        final String enabledInputMethodsStr = Settings.Secure.getString(
+                resolver, Settings.Secure.ENABLED_INPUT_METHODS);
+        if (DEBUG) {
+            Log.d(TAG, "--- Load enabled input methods: " + enabledInputMethodsStr);
+        }
+        return parseInputMethodsAndSubtypesString(enabledInputMethodsStr);
+    }
+
+    public static HashMap<String, HashSet<String>> parseInputMethodsAndSubtypesString(
+            final String inputMethodsAndSubtypesString) {
+        final HashMap<String, HashSet<String>> subtypesMap = new HashMap<>();
+        if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) {
+            return subtypesMap;
+        }
+        sStringInputMethodSplitter.setString(inputMethodsAndSubtypesString);
+        while (sStringInputMethodSplitter.hasNext()) {
+            final String nextImsStr = sStringInputMethodSplitter.next();
+            sStringInputMethodSubtypeSplitter.setString(nextImsStr);
+            if (sStringInputMethodSubtypeSplitter.hasNext()) {
+                final HashSet<String> subtypeIdSet = new HashSet<>();
+                // The first element is {@link InputMethodInfoId}.
+                final String imiId = sStringInputMethodSubtypeSplitter.next();
+                while (sStringInputMethodSubtypeSplitter.hasNext()) {
+                    subtypeIdSet.add(sStringInputMethodSubtypeSplitter.next());
+                }
+                subtypesMap.put(imiId, subtypeIdSet);
+            }
+        }
+        return subtypesMap;
+    }
+
+    private static HashSet<String> getDisabledSystemIMEs(ContentResolver resolver) {
+        HashSet<String> set = new HashSet<>();
+        String disabledIMEsStr = Settings.Secure.getString(
+                resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS);
+        if (TextUtils.isEmpty(disabledIMEsStr)) {
+            return set;
+        }
+        sStringInputMethodSplitter.setString(disabledIMEsStr);
+        while(sStringInputMethodSplitter.hasNext()) {
+            set.add(sStringInputMethodSplitter.next());
+        }
+        return set;
+    }
+
+    public static void saveInputMethodSubtypeList(PreferenceFragmentCompat context,
+            ContentResolver resolver, List<InputMethodInfo> inputMethodInfos,
+            boolean hasHardKeyboard) {
+        String currentInputMethodId = Settings.Secure.getString(resolver,
+                Settings.Secure.DEFAULT_INPUT_METHOD);
+        final int selectedInputMethodSubtype = getInputMethodSubtypeSelected(resolver);
+        final HashMap<String, HashSet<String>> enabledIMEsAndSubtypesMap =
+                getEnabledInputMethodsAndSubtypeList(resolver);
+        final HashSet<String> disabledSystemIMEs = getDisabledSystemIMEs(resolver);
+
+        boolean needsToResetSelectedSubtype = false;
+        for (final InputMethodInfo imi : inputMethodInfos) {
+            final String imiId = imi.getId();
+            final Preference pref = context.findPreference(imiId);
+            if (pref == null) {
+                continue;
+            }
+            // In the choose input method screen or in the subtype enabler screen,
+            // <code>pref</code> is an instance of TwoStatePreference.
+            final boolean isImeChecked = (pref instanceof TwoStatePreference) ?
+                    ((TwoStatePreference) pref).isChecked()
+                    : enabledIMEsAndSubtypesMap.containsKey(imiId);
+            final boolean isCurrentInputMethod = imiId.equals(currentInputMethodId);
+            final boolean systemIme = imi.isSystem();
+            if ((!hasHardKeyboard && InputMethodSettingValuesWrapper.getInstance(
+                    context.getActivity()).isAlwaysCheckedIme(imi))
+                    || isImeChecked) {
+                if (!enabledIMEsAndSubtypesMap.containsKey(imiId)) {
+                    // imiId has just been enabled
+                    enabledIMEsAndSubtypesMap.put(imiId, new HashSet<>());
+                }
+                final HashSet<String> subtypesSet = enabledIMEsAndSubtypesMap.get(imiId);
+
+                boolean subtypePrefFound = false;
+                final int subtypeCount = imi.getSubtypeCount();
+                for (int i = 0; i < subtypeCount; ++i) {
+                    final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                    final String subtypeHashCodeStr = String.valueOf(subtype.hashCode());
+                    final TwoStatePreference subtypePref = (TwoStatePreference) context
+                            .findPreference(imiId + subtypeHashCodeStr);
+                    // In the Configure input method screen which does not have subtype preferences.
+                    if (subtypePref == null) {
+                        continue;
+                    }
+                    if (!subtypePrefFound) {
+                        // Once subtype preference is found, subtypeSet needs to be cleared.
+                        // Because of system change, hashCode value could have been changed.
+                        subtypesSet.clear();
+                        // If selected subtype preference is disabled, needs to reset.
+                        needsToResetSelectedSubtype = true;
+                        subtypePrefFound = true;
+                    }
+                    // Checking <code>subtypePref.isEnabled()</code> is insufficient to determine
+                    // whether the user manually enabled this subtype or not.  Implicitly-enabled
+                    // subtypes are also checked just as an indicator to users.  We also need to
+                    // check <code>subtypePref.isEnabled()</code> so that only manually enabled
+                    // subtypes can be saved here.
+                    if (subtypePref.isEnabled() && subtypePref.isChecked()) {
+                        subtypesSet.add(subtypeHashCodeStr);
+                        if (isCurrentInputMethod) {
+                            if (selectedInputMethodSubtype == subtype.hashCode()) {
+                                // Selected subtype is still enabled, there is no need to reset
+                                // selected subtype.
+                                needsToResetSelectedSubtype = false;
+                            }
+                        }
+                    } else {
+                        subtypesSet.remove(subtypeHashCodeStr);
+                    }
+                }
+            } else {
+                enabledIMEsAndSubtypesMap.remove(imiId);
+                if (isCurrentInputMethod) {
+                    // We are processing the current input method, but found that it's not enabled.
+                    // This means that the current input method has been uninstalled.
+                    // If currentInputMethod is already uninstalled, InputMethodManagerService will
+                    // find the applicable IME from the history and the system locale.
+                    if (DEBUG) {
+                        Log.d(TAG, "Current IME was uninstalled or disabled.");
+                    }
+                    currentInputMethodId = null;
+                }
+            }
+            // If it's a disabled system ime, add it to the disabled list so that it
+            // doesn't get enabled automatically on any changes to the package list
+            if (systemIme && hasHardKeyboard) {
+                if (disabledSystemIMEs.contains(imiId)) {
+                    if (isImeChecked) {
+                        disabledSystemIMEs.remove(imiId);
+                    }
+                } else {
+                    if (!isImeChecked) {
+                        disabledSystemIMEs.add(imiId);
+                    }
+                }
+            }
+        }
+
+        final String enabledIMEsAndSubtypesString = buildInputMethodsAndSubtypesString(
+                enabledIMEsAndSubtypesMap);
+        final String disabledSystemIMEsString = buildInputMethodsString(disabledSystemIMEs);
+        if (DEBUG) {
+            Log.d(TAG, "--- Save enabled inputmethod settings. :" + enabledIMEsAndSubtypesString);
+            Log.d(TAG, "--- Save disabled system inputmethod settings. :"
+                    + disabledSystemIMEsString);
+            Log.d(TAG, "--- Save default inputmethod settings. :" + currentInputMethodId);
+            Log.d(TAG, "--- Needs to reset the selected subtype :" + needsToResetSelectedSubtype);
+            Log.d(TAG, "--- Subtype is selected :" + isInputMethodSubtypeSelected(resolver));
+        }
+
+        // Redefines SelectedSubtype when all subtypes are unchecked or there is no subtype
+        // selected. And if the selected subtype of the current input method was disabled,
+        // We should reset the selected input method's subtype.
+        if (needsToResetSelectedSubtype || !isInputMethodSubtypeSelected(resolver)) {
+            if (DEBUG) {
+                Log.d(TAG, "--- Reset inputmethod subtype because it's not defined.");
+            }
+            putSelectedInputMethodSubtype(resolver, NOT_A_SUBTYPE_ID);
+        }
+
+        Settings.Secure.putString(resolver,
+                Settings.Secure.ENABLED_INPUT_METHODS, enabledIMEsAndSubtypesString);
+        if (disabledSystemIMEsString.length() > 0) {
+            Settings.Secure.putString(resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS,
+                    disabledSystemIMEsString);
+        }
+        // If the current input method is unset, InputMethodManagerService will find the applicable
+        // IME from the history and the system locale.
+        Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD,
+                currentInputMethodId != null ? currentInputMethodId : "");
+    }
+
+    public static void loadInputMethodSubtypeList(final PreferenceFragmentCompat context,
+            final ContentResolver resolver, final List<InputMethodInfo> inputMethodInfos,
+            final Map<String, List<Preference>> inputMethodPrefsMap) {
+        final HashMap<String, HashSet<String>> enabledSubtypes =
+                getEnabledInputMethodsAndSubtypeList(resolver);
+
+        for (final InputMethodInfo imi : inputMethodInfos) {
+            final String imiId = imi.getId();
+            final Preference pref = context.findPreference(imiId);
+            if (pref instanceof TwoStatePreference) {
+                final TwoStatePreference subtypePref = (TwoStatePreference) pref;
+                final boolean isEnabled = enabledSubtypes.containsKey(imiId);
+                subtypePref.setChecked(isEnabled);
+                if (inputMethodPrefsMap != null) {
+                    for (final Preference childPref: inputMethodPrefsMap.get(imiId)) {
+                        childPref.setEnabled(isEnabled);
+                    }
+                }
+                setSubtypesPreferenceEnabled(context, inputMethodInfos, imiId, isEnabled);
+            }
+        }
+        updateSubtypesPreferenceChecked(context, inputMethodInfos, enabledSubtypes);
+    }
+
+    private static void setSubtypesPreferenceEnabled(final PreferenceFragmentCompat context,
+            final List<InputMethodInfo> inputMethodProperties, final String id,
+            final boolean enabled) {
+        final PreferenceScreen preferenceScreen = context.getPreferenceScreen();
+        for (final InputMethodInfo imi : inputMethodProperties) {
+            if (id.equals(imi.getId())) {
+                final int subtypeCount = imi.getSubtypeCount();
+                for (int i = 0; i < subtypeCount; ++i) {
+                    final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                    final TwoStatePreference pref = (TwoStatePreference) preferenceScreen
+                            .findPreference(id + subtype.hashCode());
+                    if (pref != null) {
+                        pref.setEnabled(enabled);
+                    }
+                }
+            }
+        }
+    }
+
+    private static void updateSubtypesPreferenceChecked(final PreferenceFragmentCompat context,
+            final List<InputMethodInfo> inputMethodProperties,
+            final HashMap<String, HashSet<String>> enabledSubtypes) {
+        final PreferenceScreen preferenceScreen = context.getPreferenceScreen();
+        for (final InputMethodInfo imi : inputMethodProperties) {
+            final String id = imi.getId();
+            if (!enabledSubtypes.containsKey(id)) {
+                // There is no need to enable/disable subtypes of disabled IMEs.
+                continue;
+            }
+            final HashSet<String> enabledSubtypesSet = enabledSubtypes.get(id);
+            final int subtypeCount = imi.getSubtypeCount();
+            for (int i = 0; i < subtypeCount; ++i) {
+                final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                final String hashCode = String.valueOf(subtype.hashCode());
+                if (DEBUG) {
+                    Log.d(TAG, "--- Set checked state: " + "id" + ", " + hashCode + ", "
+                            + enabledSubtypesSet.contains(hashCode));
+                }
+                final TwoStatePreference pref = (TwoStatePreference) preferenceScreen
+                        .findPreference(id + hashCode);
+                if (pref != null) {
+                    pref.setChecked(enabledSubtypesSet.contains(hashCode));
+                }
+            }
+        }
+    }
+
+    public static void removeUnnecessaryNonPersistentPreference(final Preference pref) {
+        final String key = pref.getKey();
+        if (pref.isPersistent() || key == null) {
+            return;
+        }
+        final SharedPreferences prefs = pref.getSharedPreferences();
+        if (prefs != null && prefs.contains(key)) {
+            prefs.edit().remove(key).apply();
+        }
+    }
+
+    @NonNull
+    public static String getSubtypeLocaleNameAsSentence(@Nullable InputMethodSubtype subtype,
+            @NonNull final Context context, @NonNull final InputMethodInfo inputMethodInfo) {
+        if (subtype == null) {
+            return "";
+        }
+        final Locale locale = getDisplayLocale(context);
+        final CharSequence subtypeName = subtype.getDisplayName(context,
+                inputMethodInfo.getPackageName(), inputMethodInfo.getServiceInfo()
+                        .applicationInfo);
+        return LocaleHelper.toSentenceCase(subtypeName.toString(), locale);
+    }
+
+    @NonNull
+    public static String getSubtypeLocaleNameListAsSentence(
+            @NonNull final List<InputMethodSubtype> subtypes, @NonNull final Context context,
+            @NonNull final InputMethodInfo inputMethodInfo) {
+        if (subtypes.isEmpty()) {
+            return "";
+        }
+        final Locale locale = getDisplayLocale(context);
+        final int subtypeCount = subtypes.size();
+        final CharSequence[] subtypeNames = new CharSequence[subtypeCount];
+        for (int i = 0; i < subtypeCount; i++) {
+            subtypeNames[i] = subtypes.get(i).getDisplayName(context,
+                    inputMethodInfo.getPackageName(), inputMethodInfo.getServiceInfo()
+                            .applicationInfo);
+        }
+        return LocaleHelper.toSentenceCase(
+                ListFormatter.getInstance(locale).format((Object[]) subtypeNames), locale);
+    }
+
+    @NonNull
+    private static Locale getDisplayLocale(@Nullable final Context context) {
+        if (context == null) {
+            return Locale.getDefault();
+        }
+        if (context.getResources() == null) {
+            return Locale.getDefault();
+        }
+        final Configuration configuration = context.getResources().getConfiguration();
+        if (configuration == null) {
+            return Locale.getDefault();
+        }
+        final Locale configurationLocale = configuration.getLocales().get(0);
+        if (configurationLocale == null) {
+            return Locale.getDefault();
+        }
+        return configurationLocale;
+    }
+
+    public static boolean isValidSystemNonAuxAsciiCapableIme(InputMethodInfo imi) {
+        if (imi.isAuxiliaryIme() || !imi.isSystem()) {
+            return false;
+        }
+        final int subtypeCount = imi.getSubtypeCount();
+        for (int i = 0; i < subtypeCount; ++i) {
+            final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+            if (SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())
+                    && subtype.isAsciiCapable()) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java
index 92044c3..3930069 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java
@@ -16,14 +16,17 @@
 
 package com.android.settingslib.license;
 
+import static com.android.settingslib.license.LicenseHtmlLoaderCompat.generateHtmlFile;
+import static com.android.settingslib.license.LicenseHtmlLoaderCompat.getCachedHtmlFile;
+import static com.android.settingslib.license.LicenseHtmlLoaderCompat.getVaildXmlFiles;
+import static com.android.settingslib.license.LicenseHtmlLoaderCompat.isCachedHtmlFileOutdated;
+
 import android.content.Context;
-import androidx.annotation.VisibleForTesting;
 import android.util.Log;
 
 import com.android.settingslib.utils.AsyncLoader;
 
 import java.io.File;
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -32,13 +35,6 @@
 public class LicenseHtmlLoader extends AsyncLoader<File> {
     private static final String TAG = "LicenseHtmlLoader";
 
-    private static final String[] DEFAULT_LICENSE_XML_PATHS = {
-            "/system/etc/NOTICE.xml.gz",
-            "/vendor/etc/NOTICE.xml.gz",
-            "/odm/etc/NOTICE.xml.gz",
-            "/oem/etc/NOTICE.xml.gz"};
-    private static final String NOTICE_HTML_FILE_NAME = "NOTICE.html";
-
     private Context mContext;
 
     public LicenseHtmlLoader(Context context) {
@@ -62,7 +58,7 @@
             return null;
         }
 
-        File cachedHtmlFile = getCachedHtmlFile();
+        File cachedHtmlFile = getCachedHtmlFile(mContext);
         if (!isCachedHtmlFileOutdated(xmlFiles, cachedHtmlFile)
                 || generateHtmlFile(xmlFiles, cachedHtmlFile)) {
             return cachedHtmlFile;
@@ -71,40 +67,4 @@
         return null;
     }
 
-    @VisibleForTesting
-    List<File> getVaildXmlFiles() {
-        final List<File> xmlFiles = new ArrayList();
-        for (final String xmlPath : DEFAULT_LICENSE_XML_PATHS) {
-            File file = new File(xmlPath);
-            if (file.exists() && file.length() != 0) {
-                xmlFiles.add(file);
-            }
-        }
-        return xmlFiles;
-    }
-
-    @VisibleForTesting
-    File getCachedHtmlFile() {
-        return new File(mContext.getCacheDir(), NOTICE_HTML_FILE_NAME);
-    }
-
-    @VisibleForTesting
-    boolean isCachedHtmlFileOutdated(List<File> xmlFiles, File cachedHtmlFile) {
-        boolean outdated = true;
-        if (cachedHtmlFile.exists() && cachedHtmlFile.length() != 0) {
-            outdated = false;
-            for (File file : xmlFiles) {
-                if (cachedHtmlFile.lastModified() < file.lastModified()) {
-                    outdated = true;
-                    break;
-                }
-            }
-        }
-        return outdated;
-    }
-
-    @VisibleForTesting
-    boolean generateHtmlFile(List<File> xmlFiles, File htmlFile) {
-        return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile);
-    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
new file mode 100644
index 0000000..d3b1903
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.license;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.utils.AsyncLoaderCompat;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * LicenseHtmlLoader is a loader which loads a license html file from default license xml files.
+ */
+public class LicenseHtmlLoaderCompat extends AsyncLoaderCompat<File> {
+    private static final String TAG = "LicenseHtmlLoaderCompat";
+
+    static final String[] DEFAULT_LICENSE_XML_PATHS = {
+            "/system/etc/NOTICE.xml.gz",
+            "/vendor/etc/NOTICE.xml.gz",
+            "/odm/etc/NOTICE.xml.gz",
+            "/oem/etc/NOTICE.xml.gz",
+            "/product/etc/NOTICE.xml.gz"};
+    static final String NOTICE_HTML_FILE_NAME = "NOTICE.html";
+
+    private final Context mContext;
+
+    public LicenseHtmlLoaderCompat(Context context) {
+        super(context);
+        mContext = context;
+    }
+
+    @Override
+    public File loadInBackground() {
+        return generateHtmlFromDefaultXmlFiles();
+    }
+
+    @Override
+    protected void onDiscardResult(File f) {
+    }
+
+    private File generateHtmlFromDefaultXmlFiles() {
+        final List<File> xmlFiles = getVaildXmlFiles();
+        if (xmlFiles.isEmpty()) {
+            Log.e(TAG, "No notice file exists.");
+            return null;
+        }
+
+        File cachedHtmlFile = getCachedHtmlFile(mContext);
+        if (!isCachedHtmlFileOutdated(xmlFiles, cachedHtmlFile)
+                || generateHtmlFile(xmlFiles, cachedHtmlFile)) {
+            return cachedHtmlFile;
+        }
+
+        return null;
+    }
+
+    static List<File> getVaildXmlFiles() {
+        final List<File> xmlFiles = new ArrayList();
+        for (final String xmlPath : DEFAULT_LICENSE_XML_PATHS) {
+            File file = new File(xmlPath);
+            if (file.exists() && file.length() != 0) {
+                xmlFiles.add(file);
+            }
+        }
+        return xmlFiles;
+    }
+
+    static File getCachedHtmlFile(Context context) {
+        return new File(context.getCacheDir(), NOTICE_HTML_FILE_NAME);
+    }
+
+    static boolean isCachedHtmlFileOutdated(List<File> xmlFiles, File cachedHtmlFile) {
+        boolean outdated = true;
+        if (cachedHtmlFile.exists() && cachedHtmlFile.length() != 0) {
+            outdated = false;
+            for (File file : xmlFiles) {
+                if (cachedHtmlFile.lastModified() < file.lastModified()) {
+                    outdated = true;
+                    break;
+                }
+            }
+        }
+        return outdated;
+    }
+
+    static boolean generateHtmlFile(List<File> xmlFiles, File htmlFile) {
+        return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/InjectedSetting.java b/packages/SettingsLib/src/com/android/settingslib/location/InjectedSetting.java
new file mode 100644
index 0000000..1805f1a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/location/InjectedSetting.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.location;
+
+import android.content.Intent;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.annotations.Immutable;
+
+import java.util.Objects;
+
+/**
+ * Specifies a setting that is being injected into Settings &gt; Location &gt; Location services.
+ *
+ * @see android.location.SettingInjectorService
+ */
+@Immutable
+public class InjectedSetting {
+
+    /**
+     * Package for the subclass of {@link android.location.SettingInjectorService} and for the
+     * settings activity.
+     */
+    public final String packageName;
+
+    /**
+     * Class name for the subclass of {@link android.location.SettingInjectorService} that
+     * specifies dynamic values for the location setting.
+     */
+    public final String className;
+
+    /**
+     * The {@link android.support.v7.preference.Preference#getTitle()} value.
+     */
+    public final String title;
+
+    /**
+     * The {@link android.support.v7.preference.Preference#getIcon()} value.
+     */
+    public final int iconId;
+
+    /**
+     * The user/profile associated with this setting (e.g. managed profile)
+     */
+    public final UserHandle mUserHandle;
+
+    /**
+     * The activity to launch to allow the user to modify the settings value. Assumed to be in the
+     * {@link #packageName} package.
+     */
+    public final String settingsActivity;
+
+    /**
+     * The user restriction associated with this setting.
+     */
+    public final String userRestriction;
+
+    private InjectedSetting(Builder builder) {
+        this.packageName = builder.mPackageName;
+        this.className = builder.mClassName;
+        this.title = builder.mTitle;
+        this.iconId = builder.mIconId;
+        this.mUserHandle = builder.mUserHandle;
+        this.settingsActivity = builder.mSettingsActivity;
+        this.userRestriction = builder.mUserRestriction;
+    }
+
+    @Override
+    public String toString() {
+        return "InjectedSetting{" +
+                "mPackageName='" + packageName + '\'' +
+                ", mClassName='" + className + '\'' +
+                ", label=" + title +
+                ", iconId=" + iconId +
+                ", userId=" + mUserHandle.getIdentifier() +
+                ", settingsActivity='" + settingsActivity + '\'' +
+                ", userRestriction='" + userRestriction +
+                '}';
+    }
+
+    /**
+     * Returns the intent to start the {@link #className} service.
+     */
+    public Intent getServiceIntent() {
+        Intent intent = new Intent();
+        intent.setClassName(packageName, className);
+        return intent;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof InjectedSetting)) return false;
+
+        InjectedSetting that = (InjectedSetting) o;
+
+        return Objects.equals(packageName, that.packageName)
+                && Objects.equals(className, that.className)
+                && Objects.equals(title, that.title)
+                && Objects.equals(iconId, that.iconId)
+                && Objects.equals(mUserHandle, that.mUserHandle)
+                && Objects.equals(settingsActivity, that.settingsActivity)
+                && Objects.equals(userRestriction, that.userRestriction);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = packageName.hashCode();
+        result = 31 * result + className.hashCode();
+        result = 31 * result + title.hashCode();
+        result = 31 * result + iconId;
+        result = 31 * result + (mUserHandle == null ? 0 : mUserHandle.hashCode());
+        result = 31 * result + settingsActivity.hashCode();
+        result = 31 * result + (userRestriction == null ? 0 : userRestriction.hashCode());
+        return result;
+    }
+
+    public static class Builder {
+        private String mPackageName;
+        private String mClassName;
+        private String mTitle;
+        private int mIconId;
+        private UserHandle mUserHandle;
+        private String mSettingsActivity;
+        private String mUserRestriction;
+
+        public Builder setPackageName(String packageName) {
+            mPackageName = packageName;
+            return this;
+        }
+
+        public Builder setClassName(String className) {
+            mClassName = className;
+            return this;
+        }
+
+        public Builder setTitle(String title) {
+            mTitle = title;
+            return this;
+        }
+
+        public Builder setIconId(int iconId) {
+            mIconId = iconId;
+            return this;
+        }
+
+        public Builder setUserHandle(UserHandle userHandle) {
+            mUserHandle = userHandle;
+            return this;
+        }
+
+        public Builder setSettingsActivity(String settingsActivity) {
+            mSettingsActivity = settingsActivity;
+            return this;
+        }
+
+        public Builder setUserRestriction(String userRestriction) {
+            mUserRestriction = userRestriction;
+            return this;
+        }
+
+        public InjectedSetting build() {
+            if (mPackageName == null || mClassName == null || TextUtils.isEmpty(mTitle)
+                    || TextUtils.isEmpty(mSettingsActivity)) {
+                if (Log.isLoggable(SettingsInjector.TAG, Log.WARN)) {
+                    Log.w(SettingsInjector.TAG, "Illegal setting specification: package="
+                            + mPackageName + ", class=" + mClassName
+                            + ", title=" + mTitle + ", settingsActivity=" + mSettingsActivity);
+                }
+                return null;
+            }
+            return new InjectedSetting(this);
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java
new file mode 100644
index 0000000..780fcba
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.location;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.location.SettingInjectorService;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import android.util.IconDrawableFactory;
+import android.util.Log;
+import android.util.Xml;
+
+import androidx.preference.Preference;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Adds the preferences specified by the {@link InjectedSetting} objects to a preference group.
+ *
+ * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}. We do not use that
+ * class directly because it is not a good match for our use case: we do not need the caching, and
+ * so do not want the additional resource hit at app install/upgrade time; and we would have to
+ * suppress the tie-breaking between multiple services reporting settings with the same name.
+ * Code-sharing would require extracting {@link
+ * android.content.pm.RegisteredServicesCache#parseServiceAttributes(android.content.res.Resources,
+ * String, android.util.AttributeSet)} into an interface, which didn't seem worth it.
+ */
+public class SettingsInjector {
+    static final String TAG = "SettingsInjector";
+
+    /**
+     * If reading the status of a setting takes longer than this, we go ahead and start reading
+     * the next setting.
+     */
+    private static final long INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS = 1000;
+
+    /**
+     * {@link Message#what} value for starting to load status values
+     * in case we aren't already in the process of loading them.
+     */
+    private static final int WHAT_RELOAD = 1;
+
+    /**
+     * {@link Message#what} value sent after receiving a status message.
+     */
+    private static final int WHAT_RECEIVED_STATUS = 2;
+
+    /**
+     * {@link Message#what} value sent after the timeout waiting for a status message.
+     */
+    private static final int WHAT_TIMEOUT = 3;
+
+    private final Context mContext;
+
+    /**
+     * The settings that were injected
+     */
+    protected final Set<Setting> mSettings;
+
+    private final Handler mHandler;
+
+    public SettingsInjector(Context context) {
+        mContext = context;
+        mSettings = new HashSet<Setting>();
+        mHandler = new StatusLoadingHandler();
+    }
+
+    /**
+     * Returns a list for a profile with one {@link InjectedSetting} object for each
+     * {@link android.app.Service} that responds to
+     * {@link SettingInjectorService#ACTION_SERVICE_INTENT} and provides the expected setting
+     * metadata.
+     *
+     * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
+     *
+     * TODO: unit test
+     */
+    protected List<InjectedSetting> getSettings(final UserHandle userHandle) {
+        PackageManager pm = mContext.getPackageManager();
+        Intent intent = new Intent(SettingInjectorService.ACTION_SERVICE_INTENT);
+
+        final int profileId = userHandle.getIdentifier();
+        List<ResolveInfo> resolveInfos =
+                pm.queryIntentServicesAsUser(intent, PackageManager.GET_META_DATA, profileId);
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "Found services for profile id " + profileId + ": " + resolveInfos);
+        }
+        List<InjectedSetting> settings = new ArrayList<InjectedSetting>(resolveInfos.size());
+        for (ResolveInfo resolveInfo : resolveInfos) {
+            try {
+                InjectedSetting setting = parseServiceInfo(resolveInfo, userHandle, pm);
+                if (setting == null) {
+                    Log.w(TAG, "Unable to load service info " + resolveInfo);
+                } else {
+                    settings.add(setting);
+                }
+            } catch (XmlPullParserException e) {
+                Log.w(TAG, "Unable to load service info " + resolveInfo, e);
+            } catch (IOException e) {
+                Log.w(TAG, "Unable to load service info " + resolveInfo, e);
+            }
+        }
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "Loaded settings for profile id " + profileId + ": " + settings);
+        }
+
+        return settings;
+    }
+
+    /**
+     * Adds the InjectedSetting information to a Preference object
+     */
+    private void populatePreference(Preference preference, InjectedSetting setting) {
+        final PackageManager pm = mContext.getPackageManager();
+        Drawable appIcon = null;
+        try {
+            final PackageItemInfo itemInfo = new PackageItemInfo();
+            itemInfo.icon = setting.iconId;
+            itemInfo.packageName = setting.packageName;
+            final ApplicationInfo appInfo = pm.getApplicationInfo(setting.packageName,
+                    PackageManager.GET_META_DATA);
+            appIcon = IconDrawableFactory.newInstance(mContext)
+                    .getBadgedIcon(itemInfo, appInfo, setting.mUserHandle.getIdentifier());
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "Can't get ApplicationInfo for " + setting.packageName, e);
+        }
+        preference.setTitle(setting.title);
+        preference.setSummary(null);
+        preference.setIcon(appIcon);
+        preference.setOnPreferenceClickListener(new ServiceSettingClickedListener(setting));
+    }
+
+    /**
+     * Gets a list of preferences that other apps have injected.
+     *
+     * @param profileId Identifier of the user/profile to obtain the injected settings for or
+     *                  UserHandle.USER_CURRENT for all profiles associated with current user.
+     */
+    public List<Preference> getInjectedSettings(Context prefContext, final int profileId) {
+        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        final List<UserHandle> profiles = um.getUserProfiles();
+        ArrayList<Preference> prefs = new ArrayList<>();
+        for (UserHandle userHandle : profiles) {
+            if (profileId == UserHandle.USER_CURRENT || profileId == userHandle.getIdentifier()) {
+                Iterable<InjectedSetting> settings = getSettings(userHandle);
+                for (InjectedSetting setting : settings) {
+                    Preference preference = createPreference(prefContext, setting);
+                    populatePreference(preference, setting);
+                    prefs.add(preference);
+                    mSettings.add(new Setting(setting, preference));
+                }
+            }
+        }
+
+        reloadStatusMessages();
+
+        return prefs;
+    }
+
+    /**
+     * Creates an injected Preference
+     *
+     * @return the created Preference
+     */
+    protected Preference createPreference(Context prefContext, InjectedSetting setting) {
+        return new Preference(prefContext);
+    }
+
+    /**
+     * Returns the settings parsed from the attributes of the
+     * {@link SettingInjectorService#META_DATA_NAME} tag, or null.
+     *
+     * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
+     */
+    private static InjectedSetting parseServiceInfo(ResolveInfo service, UserHandle userHandle,
+            PackageManager pm) throws XmlPullParserException, IOException {
+
+        ServiceInfo si = service.serviceInfo;
+        ApplicationInfo ai = si.applicationInfo;
+
+        if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+            if (Log.isLoggable(TAG, Log.WARN)) {
+                Log.w(TAG, "Ignoring attempt to inject setting from app not in system image: "
+                        + service);
+                return null;
+            }
+        }
+
+        XmlResourceParser parser = null;
+        try {
+            parser = si.loadXmlMetaData(pm, SettingInjectorService.META_DATA_NAME);
+            if (parser == null) {
+                throw new XmlPullParserException("No " + SettingInjectorService.META_DATA_NAME
+                        + " meta-data for " + service + ": " + si);
+            }
+
+            AttributeSet attrs = Xml.asAttributeSet(parser);
+
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && type != XmlPullParser.START_TAG) {
+            }
+
+            String nodeName = parser.getName();
+            if (!SettingInjectorService.ATTRIBUTES_NAME.equals(nodeName)) {
+                throw new XmlPullParserException("Meta-data does not start with "
+                        + SettingInjectorService.ATTRIBUTES_NAME + " tag");
+            }
+
+            Resources res = pm.getResourcesForApplicationAsUser(si.packageName,
+                    userHandle.getIdentifier());
+            return parseAttributes(si.packageName, si.name, userHandle, res, attrs);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new XmlPullParserException(
+                    "Unable to load resources for package " + si.packageName);
+        } finally {
+            if (parser != null) {
+                parser.close();
+            }
+        }
+    }
+
+    /**
+     * Returns an immutable representation of the static attributes for the setting, or null.
+     */
+    private static InjectedSetting parseAttributes(String packageName, String className,
+            UserHandle userHandle, Resources res, AttributeSet attrs) {
+
+        TypedArray sa = res.obtainAttributes(attrs, android.R.styleable.SettingInjectorService);
+        try {
+            // Note that to help guard against malicious string injection, we do not allow dynamic
+            // specification of the label (setting title)
+            final String title = sa.getString(android.R.styleable.SettingInjectorService_title);
+            final int iconId =
+                    sa.getResourceId(android.R.styleable.SettingInjectorService_icon, 0);
+            final String settingsActivity =
+                    sa.getString(android.R.styleable.SettingInjectorService_settingsActivity);
+            final String userRestriction = sa.getString(
+                    android.R.styleable.SettingInjectorService_userRestriction);
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "parsed title: " + title + ", iconId: " + iconId
+                        + ", settingsActivity: " + settingsActivity);
+            }
+            return new InjectedSetting.Builder()
+                    .setPackageName(packageName)
+                    .setClassName(className)
+                    .setTitle(title)
+                    .setIconId(iconId)
+                    .setUserHandle(userHandle)
+                    .setSettingsActivity(settingsActivity)
+                    .setUserRestriction(userRestriction)
+                    .build();
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    /**
+     * Checks wheteher there is any preference that other apps have injected.
+     *
+     * @param profileId Identifier of the user/profile to obtain the injected settings for or
+     *                  UserHandle.USER_CURRENT for all profiles associated with current user.
+     */
+    public boolean hasInjectedSettings(final int profileId) {
+        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        final List<UserHandle> profiles = um.getUserProfiles();
+        final int profileCount = profiles.size();
+        for (int i = 0; i < profileCount; ++i) {
+            final UserHandle userHandle = profiles.get(i);
+            if (profileId == UserHandle.USER_CURRENT || profileId == userHandle.getIdentifier()) {
+                Iterable<InjectedSetting> settings = getSettings(userHandle);
+                for (InjectedSetting setting : settings) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Reloads the status messages for all the preference items.
+     */
+    public void reloadStatusMessages() {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "reloadingStatusMessages: " + mSettings);
+        }
+        mHandler.sendMessage(mHandler.obtainMessage(WHAT_RELOAD));
+    }
+
+    protected class ServiceSettingClickedListener
+            implements Preference.OnPreferenceClickListener {
+        private InjectedSetting mInfo;
+
+        public ServiceSettingClickedListener(InjectedSetting info) {
+            mInfo = info;
+        }
+
+        @Override
+        public boolean onPreferenceClick(Preference preference) {
+            // Activity to start if they click on the preference. Must start in new task to ensure
+            // that "android.settings.LOCATION_SOURCE_SETTINGS" brings user back to
+            // Settings > Location.
+            Intent settingIntent = new Intent();
+            settingIntent.setClassName(mInfo.packageName, mInfo.settingsActivity);
+            // Sometimes the user may navigate back to "Settings" and launch another different
+            // injected setting after one injected setting has been launched.
+            //
+            // FLAG_ACTIVITY_CLEAR_TOP allows multiple Activities to stack on each other. When
+            // "back" button is clicked, the user will navigate through all the injected settings
+            // launched before. Such behavior could be quite confusing sometimes.
+            //
+            // In order to avoid such confusion, we use FLAG_ACTIVITY_CLEAR_TASK, which always clear
+            // up all existing injected settings and make sure that "back" button always brings the
+            // user back to "Settings" directly.
+            settingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+            mContext.startActivityAsUser(settingIntent, mInfo.mUserHandle);
+            return true;
+        }
+    }
+
+    /**
+     * Loads the setting status values one at a time. Each load starts a subclass of {@link
+     * SettingInjectorService}, so to reduce memory pressure we don't want to load too many at
+     * once.
+     */
+    private final class StatusLoadingHandler extends Handler {
+
+        /**
+         * Settings whose status values need to be loaded. A set is used to prevent redundant loads.
+         */
+        private Set<Setting> mSettingsToLoad = new HashSet<Setting>();
+
+        /**
+         * Settings that are being loaded now and haven't timed out. In practice this should have
+         * zero or one elements.
+         */
+        private Set<Setting> mSettingsBeingLoaded = new HashSet<Setting>();
+
+        /**
+         * Settings that are being loaded but have timed out. If only one setting has timed out, we
+         * will go ahead and start loading the next setting so that one slow load won't delay the
+         * load of the other settings.
+         */
+        private Set<Setting> mTimedOutSettings = new HashSet<Setting>();
+
+        private boolean mReloadRequested;
+
+        private StatusLoadingHandler() {
+            super(Looper.getMainLooper());
+        }
+        @Override
+        public void handleMessage(Message msg) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "handleMessage start: " + msg + ", " + this);
+            }
+
+            // Update state in response to message
+            switch (msg.what) {
+                case WHAT_RELOAD:
+                    mReloadRequested = true;
+                    break;
+                case WHAT_RECEIVED_STATUS:
+                    final Setting receivedSetting = (Setting) msg.obj;
+                    receivedSetting.maybeLogElapsedTime();
+                    mSettingsBeingLoaded.remove(receivedSetting);
+                    mTimedOutSettings.remove(receivedSetting);
+                    removeMessages(WHAT_TIMEOUT, receivedSetting);
+                    break;
+                case WHAT_TIMEOUT:
+                    final Setting timedOutSetting = (Setting) msg.obj;
+                    mSettingsBeingLoaded.remove(timedOutSetting);
+                    mTimedOutSettings.add(timedOutSetting);
+                    if (Log.isLoggable(TAG, Log.WARN)) {
+                        Log.w(TAG, "Timed out after " + timedOutSetting.getElapsedTime()
+                                + " millis trying to get status for: " + timedOutSetting);
+                    }
+                    break;
+                default:
+                    Log.wtf(TAG, "Unexpected what: " + msg);
+            }
+
+            // Decide whether to load additional settings based on the new state. Start by seeing
+            // if we have headroom to load another setting.
+            if (mSettingsBeingLoaded.size() > 0 || mTimedOutSettings.size() > 1) {
+                // Don't load any more settings until one of the pending settings has completed.
+                // To reduce memory pressure, we want to be loading at most one setting (plus at
+                // most one timed-out setting) at a time. This means we'll be responsible for
+                // bringing in at most two services.
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "too many services already live for " + msg + ", " + this);
+                }
+                return;
+            }
+
+            if (mReloadRequested && mSettingsToLoad.isEmpty() && mSettingsBeingLoaded.isEmpty()
+                    && mTimedOutSettings.isEmpty()) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "reloading because idle and reload requesteed " + msg + ", " + this);
+                }
+                // Reload requested, so must reload all settings
+                mSettingsToLoad.addAll(mSettings);
+                mReloadRequested = false;
+            }
+
+            // Remove the next setting to load from the queue, if any
+            Iterator<Setting> iter = mSettingsToLoad.iterator();
+            if (!iter.hasNext()) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "nothing left to do for " + msg + ", " + this);
+                }
+                return;
+            }
+            Setting setting = iter.next();
+            iter.remove();
+
+            // Request the status value
+            setting.startService();
+            mSettingsBeingLoaded.add(setting);
+
+            // Ensure that if receiving the status value takes too long, we start loading the
+            // next value anyway
+            Message timeoutMsg = obtainMessage(WHAT_TIMEOUT, setting);
+            sendMessageDelayed(timeoutMsg, INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS);
+
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "handleMessage end " + msg + ", " + this
+                        + ", started loading " + setting);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "StatusLoadingHandler{" +
+                    "mSettingsToLoad=" + mSettingsToLoad +
+                    ", mSettingsBeingLoaded=" + mSettingsBeingLoaded +
+                    ", mTimedOutSettings=" + mTimedOutSettings +
+                    ", mReloadRequested=" + mReloadRequested +
+                    '}';
+        }
+    }
+
+    /**
+     * Represents an injected setting and the corresponding preference.
+     */
+    protected final class Setting {
+
+        public final InjectedSetting setting;
+        public final Preference preference;
+        public long startMillis;
+
+        public Setting(InjectedSetting setting, Preference preference) {
+            this.setting = setting;
+            this.preference = preference;
+        }
+
+        @Override
+        public String toString() {
+            return "Setting{" +
+                    "setting=" + setting +
+                    ", preference=" + preference +
+                    '}';
+        }
+
+        /**
+         * Returns true if they both have the same {@link #setting} value. Ignores mutable
+         * {@link #preference} and {@link #startMillis} so that it's safe to use in sets.
+         */
+        @Override
+        public boolean equals(Object o) {
+            return this == o || o instanceof Setting && setting.equals(((Setting) o).setting);
+        }
+
+        @Override
+        public int hashCode() {
+            return setting.hashCode();
+        }
+
+        /**
+         * Starts the service to fetch for the current status for the setting, and updates the
+         * preference when the service replies.
+         */
+        public void startService() {
+            final ActivityManager am = (ActivityManager)
+                    mContext.getSystemService(Context.ACTIVITY_SERVICE);
+            if (!am.isUserRunning(setting.mUserHandle.getIdentifier())) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "Cannot start service as user "
+                            + setting.mUserHandle.getIdentifier() + " is not running");
+                }
+                return;
+            }
+            Handler handler = new Handler() {
+                @Override
+                public void handleMessage(Message msg) {
+                    Bundle bundle = msg.getData();
+                    boolean enabled = bundle.getBoolean(SettingInjectorService.ENABLED_KEY, true);
+                    if (Log.isLoggable(TAG, Log.DEBUG)) {
+                        Log.d(TAG, setting + ": received " + msg + ", bundle: " + bundle);
+                    }
+                    preference.setSummary(null);
+                    preference.setEnabled(enabled);
+                    mHandler.sendMessage(
+                            mHandler.obtainMessage(WHAT_RECEIVED_STATUS, Setting.this));
+                }
+            };
+            Messenger messenger = new Messenger(handler);
+
+            Intent intent = setting.getServiceIntent();
+            intent.putExtra(SettingInjectorService.MESSENGER_KEY, messenger);
+
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, setting + ": sending update intent: " + intent
+                        + ", handler: " + handler);
+                startMillis = SystemClock.elapsedRealtime();
+            } else {
+                startMillis = 0;
+            }
+
+            // Start the service, making sure that this is attributed to the user associated with
+            // the setting rather than the system user.
+            mContext.startServiceAsUser(intent, setting.mUserHandle);
+        }
+
+        public long getElapsedTime() {
+            long end = SystemClock.elapsedRealtime();
+            return end - startMillis;
+        }
+
+        public void maybeLogElapsedTime() {
+            if (Log.isLoggable(TAG, Log.DEBUG) && startMillis != 0) {
+                long elapsed = getElapsedTime();
+                Log.d(TAG, this + " update took " + elapsed + " millis");
+            }
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
new file mode 100644
index 0000000..3adbd4d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.net;
+
+import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.SET_FOREGROUND;
+import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
+import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+
+import android.content.Context;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import com.android.settingslib.AppItem;
+
+import androidx.loader.content.AsyncTaskLoader;
+
+/**
+ * Loader for historical chart data for both network and UID details.
+ */
+public class ChartDataLoaderCompat extends AsyncTaskLoader<ChartData> {
+    private static final String KEY_TEMPLATE = "template";
+    private static final String KEY_APP = "app";
+    private static final String KEY_FIELDS = "fields";
+
+    private final INetworkStatsSession mSession;
+    private final Bundle mArgs;
+
+    public static Bundle buildArgs(NetworkTemplate template, AppItem app) {
+        return buildArgs(template, app, FIELD_RX_BYTES | FIELD_TX_BYTES);
+    }
+
+    public static Bundle buildArgs(NetworkTemplate template, AppItem app, int fields) {
+        final Bundle args = new Bundle();
+        args.putParcelable(KEY_TEMPLATE, template);
+        args.putParcelable(KEY_APP, app);
+        args.putInt(KEY_FIELDS, fields);
+        return args;
+    }
+
+    public ChartDataLoaderCompat(Context context, INetworkStatsSession session, Bundle args) {
+        super(context);
+        mSession = session;
+        mArgs = args;
+    }
+
+    @Override
+    protected void onStartLoading() {
+        super.onStartLoading();
+        forceLoad();
+    }
+
+    @Override
+    public ChartData loadInBackground() {
+        final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
+        final AppItem app = mArgs.getParcelable(KEY_APP);
+        final int fields = mArgs.getInt(KEY_FIELDS);
+
+        try {
+            return loadInBackground(template, app, fields);
+        } catch (RemoteException e) {
+            // since we can't do much without history, and we don't want to
+            // leave with half-baked UI, we bail hard.
+            throw new RuntimeException("problem reading network stats", e);
+        }
+    }
+
+    private ChartData loadInBackground(NetworkTemplate template, AppItem app, int fields)
+            throws RemoteException {
+        final ChartData data = new ChartData();
+        data.network = mSession.getHistoryForNetwork(template, fields);
+
+        if (app != null) {
+            // load stats for current uid and template
+            final int size = app.uids.size();
+            for (int i = 0; i < size; i++) {
+                final int uid = app.uids.keyAt(i);
+                data.detailDefault = collectHistoryForUid(
+                        template, uid, SET_DEFAULT, data.detailDefault);
+                data.detailForeground = collectHistoryForUid(
+                        template, uid, SET_FOREGROUND, data.detailForeground);
+            }
+
+            if (size > 0) {
+                data.detail = new NetworkStatsHistory(data.detailForeground.getBucketDuration());
+                data.detail.recordEntireHistory(data.detailDefault);
+                data.detail.recordEntireHistory(data.detailForeground);
+            } else {
+                data.detailDefault = new NetworkStatsHistory(HOUR_IN_MILLIS);
+                data.detailForeground = new NetworkStatsHistory(HOUR_IN_MILLIS);
+                data.detail = new NetworkStatsHistory(HOUR_IN_MILLIS);
+            }
+        }
+
+        return data;
+    }
+
+    @Override
+    protected void onStopLoading() {
+        super.onStopLoading();
+        cancelLoad();
+    }
+
+    @Override
+    protected void onReset() {
+        super.onReset();
+        cancelLoad();
+    }
+
+    /**
+     * Collect {@link NetworkStatsHistory} for the requested UID, combining with
+     * an existing {@link NetworkStatsHistory} if provided.
+     */
+    private NetworkStatsHistory collectHistoryForUid(
+            NetworkTemplate template, int uid, int set, NetworkStatsHistory existing)
+            throws RemoteException {
+        final NetworkStatsHistory history = mSession.getHistoryForUid(
+                template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
+
+        if (existing != null) {
+            existing.recordEntireHistory(history);
+            return existing;
+        } else {
+            return history;
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index 87f5b4f..eeaa987 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -38,13 +38,14 @@
 import android.telephony.TelephonyManager;
 import android.text.format.DateUtils;
 import android.util.Log;
-import android.util.Pair;
+import android.util.Range;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.time.ZonedDateTime;
 import java.util.Date;
+import java.util.Iterator;
 import java.util.Locale;
 
 public class DataUsageController {
@@ -136,11 +137,12 @@
             final NetworkStatsHistory history = session.getHistoryForNetwork(template, FIELDS);
             final long now = System.currentTimeMillis();
             final long start, end;
-            if (policy != null) {
-                final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager
-                        .cycleIterator(policy).next();
-                start = cycle.first.toInstant().toEpochMilli();
-                end = cycle.second.toInstant().toEpochMilli();
+            final Iterator<Range<ZonedDateTime>> it =
+                    (policy != null) ? policy.cycleIterator() : null;
+            if (it != null && it.hasNext()) {
+                final Range<ZonedDateTime> cycle = it.next();
+                start = cycle.getLower().toInstant().toEpochMilli();
+                end = cycle.getUpper().toInstant().toEpochMilli();
             } else {
                 // period = last 4 wks
                 end = now;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java
new file mode 100644
index 0000000..c311337
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.net;
+
+import android.content.Context;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import androidx.loader.content.AsyncTaskLoader;
+
+public class SummaryForAllUidLoaderCompat extends AsyncTaskLoader<NetworkStats> {
+    private static final String KEY_TEMPLATE = "template";
+    private static final String KEY_START = "start";
+    private static final String KEY_END = "end";
+
+    private final INetworkStatsSession mSession;
+    private final Bundle mArgs;
+
+    public static Bundle buildArgs(NetworkTemplate template, long start, long end) {
+        final Bundle args = new Bundle();
+        args.putParcelable(KEY_TEMPLATE, template);
+        args.putLong(KEY_START, start);
+        args.putLong(KEY_END, end);
+        return args;
+    }
+
+    public SummaryForAllUidLoaderCompat(Context context, INetworkStatsSession session,
+            Bundle args) {
+        super(context);
+        mSession = session;
+        mArgs = args;
+    }
+
+    @Override
+    protected void onStartLoading() {
+        super.onStartLoading();
+        forceLoad();
+    }
+
+    @Override
+    public NetworkStats loadInBackground() {
+        final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
+        final long start = mArgs.getLong(KEY_START);
+        final long end = mArgs.getLong(KEY_END);
+
+        try {
+            return mSession.getSummaryForAllUid(template, start, end, false);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    @Override
+    protected void onStopLoading() {
+        super.onStopLoading();
+        cancelLoad();
+    }
+
+    @Override
+    protected void onReset() {
+        super.onReset();
+        cancelLoad();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
index 6da486a..0ef46a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -17,14 +17,12 @@
 package com.android.settingslib.notification;
 
 import android.app.ActivityManager;
-import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.provider.Settings;
 import android.service.notification.Condition;
 import android.service.notification.ZenModeConfig;
-import androidx.annotation.VisibleForTesting;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.CompoundButton;
@@ -42,6 +40,9 @@
 
 import java.util.Arrays;
 
+import androidx.annotation.VisibleForTesting;
+import androidx.appcompat.app.AlertDialog;
+
 public class ZenDurationDialog {
     private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
     @VisibleForTesting protected static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
@@ -66,12 +67,17 @@
     }
 
     public Dialog createDialog() {
-        int zenDuration = Settings.Global.getInt(
-                mContext.getContentResolver(), Settings.Global.ZEN_DURATION,
-                Settings.Global.ZEN_DURATION_FOREVER);
+        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+        setupDialog(builder);
+        return builder.create();
+    }
 
-        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
-                .setTitle(R.string.zen_mode_duration_settings_title)
+    public void setupDialog(AlertDialog.Builder builder) {
+        int zenDuration = Settings.Secure.getInt(
+                mContext.getContentResolver(), Settings.Secure.ZEN_DURATION,
+                Settings.Secure.ZEN_DURATION_FOREVER);
+
+        builder.setTitle(R.string.zen_mode_duration_settings_title)
                 .setNegativeButton(R.string.cancel, null)
                 .setPositiveButton(R.string.okay,
                         new DialogInterface.OnClickListener() {
@@ -84,19 +90,18 @@
         View contentView = getContentView();
         setupRadioButtons(zenDuration);
         builder.setView(contentView);
-        return builder.create();
     }
 
     @VisibleForTesting
     protected void updateZenDuration(int currZenDuration) {
         final int checkedRadioButtonId = mZenRadioGroup.getCheckedRadioButtonId();
 
-        int newZenDuration = Settings.Global.getInt(
-                mContext.getContentResolver(), Settings.Global.ZEN_DURATION,
-                Settings.Global.ZEN_DURATION_FOREVER);
+        int newZenDuration = Settings.Secure.getInt(
+                mContext.getContentResolver(), Settings.Secure.ZEN_DURATION,
+                Settings.Secure.ZEN_DURATION_FOREVER);
         switch (checkedRadioButtonId) {
             case FOREVER_CONDITION_INDEX:
-                newZenDuration = Settings.Global.ZEN_DURATION_FOREVER;
+                newZenDuration = Settings.Secure.ZEN_DURATION_FOREVER;
                 MetricsLogger.action(mContext,
                         MetricsProto.MetricsEvent.
                                 NOTIFICATION_ZEN_MODE_DURATION_FOREVER);
@@ -110,7 +115,7 @@
                         newZenDuration);
                 break;
             case ALWAYS_ASK_CONDITION_INDEX:
-                newZenDuration = Settings.Global.ZEN_DURATION_PROMPT;
+                newZenDuration = Settings.Secure.ZEN_DURATION_PROMPT;
                 MetricsLogger.action(mContext,
                         MetricsProto.MetricsEvent.
                                 NOTIFICATION_ZEN_MODE_DURATION_PROMPT);
@@ -118,8 +123,8 @@
         }
 
         if (currZenDuration != newZenDuration) {
-            Settings.Global.putInt(mContext.getContentResolver(),
-                    Settings.Global.ZEN_DURATION, newZenDuration);
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.Secure.ZEN_DURATION, newZenDuration);
         }
     }
 
@@ -269,8 +274,7 @@
         String radioContentText = "";
         switch (rowIndex) {
             case FOREVER_CONDITION_INDEX:
-                radioContentText = mContext.getString(
-                        com.android.internal.R.string.zen_mode_forever);
+                radioContentText = mContext.getString(R.string.zen_mode_forever);
                 break;
             case COUNTDOWN_CONDITION_INDEX:
                 Condition condition = ZenModeConfig.toTimeCondition(mContext,
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java
new file mode 100644
index 0000000..1791217
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.service.settings.suggestions.Suggestion;
+import android.util.Log;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.List;
+
+import androidx.annotation.Nullable;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.Loader;
+
+/**
+ * Manages IPC communication to SettingsIntelligence for suggestion related services.
+ */
+public class SuggestionControllerMixinCompat implements
+        SuggestionController.ServiceConnectionListener, androidx.lifecycle.LifecycleObserver,
+        LoaderManager.LoaderCallbacks<List<Suggestion>> {
+
+    public interface SuggestionControllerHost {
+        /**
+         * Called when suggestion data fetching is ready.
+         */
+        void onSuggestionReady(List<Suggestion> data);
+
+        /**
+         * Returns {@link LoaderManager} associated with the host. If host is not attached to
+         * activity then return null.
+         */
+        @Nullable
+        LoaderManager getLoaderManager();
+    }
+
+    private static final String TAG = "SuggestionCtrlMixin";
+    private static final boolean DEBUG = false;
+
+    private final Context mContext;
+    private final SuggestionController mSuggestionController;
+    private final SuggestionControllerHost mHost;
+
+    private boolean mSuggestionLoaded;
+
+    public SuggestionControllerMixinCompat(Context context, SuggestionControllerHost host,
+            Lifecycle lifecycle, ComponentName componentName) {
+        mContext = context.getApplicationContext();
+        mHost = host;
+        mSuggestionController = new SuggestionController(mContext, componentName,
+                    this /* serviceConnectionListener */);
+        if (lifecycle != null) {
+            lifecycle.addObserver(this);
+        }
+    }
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_START)
+    public void onStart() {
+        if (DEBUG) {
+            Log.d(TAG, "SuggestionController started");
+        }
+        mSuggestionController.start();
+    }
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+    public void onStop() {
+        if (DEBUG) {
+            Log.d(TAG, "SuggestionController stopped.");
+        }
+        mSuggestionController.stop();
+    }
+
+    @Override
+    public void onServiceConnected() {
+        final LoaderManager loaderManager = mHost.getLoaderManager();
+        if (loaderManager != null) {
+            loaderManager.restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
+                    null /* args */, this /* callback */);
+        }
+    }
+
+    @Override
+    public void onServiceDisconnected() {
+        if (DEBUG) {
+            Log.d(TAG, "SuggestionService disconnected");
+        }
+        final LoaderManager loaderManager = mHost.getLoaderManager();
+        if (loaderManager != null) {
+            loaderManager.destroyLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS);
+        }
+    }
+
+    @Override
+    public Loader<List<Suggestion>> onCreateLoader(int id, Bundle args) {
+        if (id == SuggestionLoader.LOADER_ID_SUGGESTIONS) {
+            mSuggestionLoaded = false;
+            return new SuggestionLoaderCompat(mContext, mSuggestionController);
+        }
+        throw new IllegalArgumentException("This loader id is not supported " + id);
+    }
+
+    @Override
+    public void onLoadFinished(Loader<List<Suggestion>> loader, List<Suggestion> data) {
+        mSuggestionLoaded = true;
+        mHost.onSuggestionReady(data);
+    }
+
+    @Override
+    public void onLoaderReset(Loader<List<Suggestion>> loader) {
+        mSuggestionLoaded = false;
+    }
+
+    public boolean isSuggestionLoaded() {
+        return mSuggestionLoaded;
+    }
+
+    public void dismissSuggestion(Suggestion suggestion) {
+        mSuggestionController.dismissSuggestions(suggestion);
+    }
+
+    public void launchSuggestion(Suggestion suggestion) {
+        mSuggestionController.launchSuggestion(suggestion);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoaderCompat.java
new file mode 100644
index 0000000..066de19
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoaderCompat.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import android.content.Context;
+import android.service.settings.suggestions.Suggestion;
+import android.util.Log;
+
+import com.android.settingslib.utils.AsyncLoaderCompat;
+
+import java.util.List;
+
+public class SuggestionLoaderCompat extends AsyncLoaderCompat<List<Suggestion>> {
+
+    public static final int LOADER_ID_SUGGESTIONS = 42;
+    private static final String TAG = "SuggestionLoader";
+
+    private final SuggestionController mSuggestionController;
+
+    public SuggestionLoaderCompat(Context context, SuggestionController controller) {
+        super(context);
+        mSuggestionController = controller;
+    }
+
+    @Override
+    protected void onDiscardResult(List<Suggestion> result) {
+
+    }
+
+    @Override
+    public List<Suggestion> loadInBackground() {
+        final List<Suggestion> data = mSuggestionController.getSuggestions();
+        if (data == null) {
+            Log.d(TAG, "data is null");
+        } else {
+            Log.d(TAG, "data size " + data.size());
+        }
+        return data;
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoaderCompat.java
new file mode 100644
index 0000000..916d7e3
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoaderCompat.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.utils;
+
+import android.content.Context;
+
+import androidx.loader.content.AsyncTaskLoader;
+
+/**
+ * This class fills in some boilerplate for AsyncTaskLoader to actually load things.
+ *
+ * Subclasses need to implement {@link AsyncLoaderCompat#loadInBackground()} to perform the actual
+ * background task, and {@link AsyncLoaderCompat#onDiscardResult(T)} to clean up previously loaded
+ * results.
+ *
+ * This loader is based on the MailAsyncTaskLoader from the AOSP EmailUnified repo.
+ *
+ * @param <T> the data type to be loaded.
+ */
+public abstract class AsyncLoaderCompat<T> extends AsyncTaskLoader<T> {
+    private T mResult;
+
+    public AsyncLoaderCompat(final Context context) {
+        super(context);
+    }
+
+    @Override
+    protected void onStartLoading() {
+        if (mResult != null) {
+            deliverResult(mResult);
+        }
+
+        if (takeContentChanged() || mResult == null) {
+            forceLoad();
+        }
+    }
+
+    @Override
+    protected void onStopLoading() {
+        cancelLoad();
+    }
+
+    @Override
+    public void deliverResult(final T data) {
+        if (isReset()) {
+            if (data != null) {
+                onDiscardResult(data);
+            }
+            return;
+        }
+
+        final T oldResult = mResult;
+        mResult = data;
+
+        if (isStarted()) {
+            super.deliverResult(data);
+        }
+
+        if (oldResult != null && oldResult != mResult) {
+            onDiscardResult(oldResult);
+        }
+    }
+
+    @Override
+    protected void onReset() {
+        super.onReset();
+
+        onStopLoading();
+
+        if (mResult != null) {
+            onDiscardResult(mResult);
+        }
+        mResult = null;
+    }
+
+    @Override
+    public void onCanceled(final T data) {
+        super.onCanceled(data);
+
+        if (data != null) {
+            onDiscardResult(data);
+        }
+    }
+
+    /**
+     * Called when discarding the load results so subclasses can take care of clean-up or
+     * recycling tasks. This is not called if the same result (by way of pointer equality) is
+     * returned again by a subsequent call to loadInBackground, or if result is null.
+     *
+     * Note that this may be called concurrently with loadInBackground(), and in some circumstances
+     * may be called more than once for a given object.
+     *
+     * @param result The value returned from {@link AsyncLoaderCompat#loadInBackground()} which
+     *               is to be discarded.
+     */
+    protected abstract void onDiscardResult(T result);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
new file mode 100644
index 0000000..260ac83
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget;
+
+import android.content.Context;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.SetPreferenceScreen;
+
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+public class FooterPreferenceMixinCompat implements LifecycleObserver, SetPreferenceScreen {
+
+    private final PreferenceFragmentCompat mFragment;
+    private FooterPreference mFooterPreference;
+
+    public FooterPreferenceMixinCompat(PreferenceFragmentCompat fragment, Lifecycle lifecycle) {
+        mFragment = fragment;
+        lifecycle.addObserver(this);
+    }
+
+    @Override
+    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+        if (mFooterPreference != null) {
+            preferenceScreen.addPreference(mFooterPreference);
+        }
+    }
+
+    /**
+     * Creates a new {@link FooterPreference}.
+     */
+    public FooterPreference createFooterPreference() {
+        final PreferenceScreen screen = mFragment.getPreferenceScreen();
+        if (mFooterPreference != null && screen != null) {
+            screen.removePreference(mFooterPreference);
+        }
+        mFooterPreference = new FooterPreference(getPrefContext());
+
+        if (screen != null) {
+            screen.addPreference(mFooterPreference);
+        }
+        return mFooterPreference;
+    }
+
+    /**
+     * Returns an UI context with theme properly set for new Preference objects.
+     */
+    private Context getPrefContext() {
+        return mFragment.getPreferenceManager().getContext();
+    }
+
+    public boolean hasFooter() {
+        return mFooterPreference != null;
+    }
+}
+
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
index 159b2a1..19e3808 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
@@ -55,8 +55,10 @@
         try {
             List<PasspointConfiguration> savedPasspointConfigs =
                     wifiManager.getPasspointConfigurations();
-            for (PasspointConfiguration config : savedPasspointConfigs) {
-                savedConfigs.add(new AccessPoint(context, config));
+            if (savedPasspointConfigs != null) {
+                for (PasspointConfiguration config : savedPasspointConfigs) {
+                    savedConfigs.add(new AccessPoint(context, config));
+                }
             }
         } catch (UnsupportedOperationException e) {
             // Passpoint not supported.
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
deleted file mode 100644
index ac2d759..0000000
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.drawer;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.UserInfo;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import static junit.framework.Assert.assertEquals;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class ProfileSelectDialogTest {
-
-    @Mock
-    private Context mContext;
-    @Mock
-    private UserManager mUserManager;
-    private static final UserHandle NORMAL_USER = UserHandle.of(1111);
-    private static final UserHandle REMOVED_USER = UserHandle.of(2222);
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
-        final UserInfo userInfo = new UserInfo(
-                NORMAL_USER.getIdentifier(), "test_user", UserInfo.FLAG_RESTRICTED);
-        when(mUserManager.getUserInfo(NORMAL_USER.getIdentifier())).thenReturn(userInfo);
-    }
-
-    @Test
-    public void testUpdateUserHandlesIfNeeded_Normal() {
-        final Tile tile = new Tile();
-        tile.intent = new Intent();
-        tile.userHandle.add(NORMAL_USER);
-
-        ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile);
-
-        assertEquals(tile.userHandle.size(), 1);
-        assertEquals(tile.userHandle.get(0).getIdentifier(), NORMAL_USER.getIdentifier());
-        verify(mUserManager, never()).getUserInfo(NORMAL_USER.getIdentifier());
-    }
-
-    @Test
-    public void testUpdateUserHandlesIfNeeded_Remove() {
-        final Tile tile = new Tile();
-        tile.intent = new Intent();
-        tile.userHandle.add(REMOVED_USER);
-        tile.userHandle.add(NORMAL_USER);
-        tile.userHandle.add(REMOVED_USER);
-
-        ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile);
-
-        assertEquals(tile.userHandle.size(), 1);
-        assertEquals(tile.userHandle.get(0).getIdentifier(), NORMAL_USER.getIdentifier());
-        verify(mUserManager, times(1)).getUserInfo(NORMAL_USER.getIdentifier());
-        verify(mUserManager, times(2)).getUserInfo(REMOVED_USER.getIdentifier());
-    }
-}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
deleted file mode 100644
index 2f417ad..0000000
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.settingslib.drawer;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
-
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class SettingsDrawerActivityTest {
-
-    @Rule
-    public ActivityTestRule<TestActivity> mActivityRule =
-            new ActivityTestRule<>(TestActivity.class, true, true);
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @Test
-    public void startActivity_doNotShowNavUp() {
-        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        final Intent intent = new Intent(instrumentation.getTargetContext(), TestActivity.class)
-                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        instrumentation.startActivitySync(intent);
-
-        onView(withContentDescription(com.android.internal.R.string.action_bar_up_description))
-                .check(doesNotExist());
-    }
-
-    /**
-     * Test Activity in this test.
-     *
-     * Use this activity because SettingsDrawerActivity hasn't been registered in its
-     * AndroidManifest.xml
-     */
-    public static class TestActivity extends SettingsDrawerActivity {
-    }
-}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index 01df0ec..dddfa7a 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -102,17 +102,4 @@
     private boolean isRectZero(Rect r) {
         return r.left == 0 && r.top == 0 && r.right == 0 && r.bottom == 0;
     }
-
-    @Test
-    public void testPlusPaint_isEqualToBoltPaint() {
-        // Before setting color
-        assertTrue(mBatteryDrawable.mPlusPaint.hasEqualAttributes(mBatteryDrawable.mBoltPaint));
-
-        final int fakeFillColor = 123;
-        final int fakeBackgrundColor = 456;
-
-        // After
-        mBatteryDrawable.setColors(fakeFillColor, fakeBackgrundColor);
-        assertTrue(mBatteryDrawable.mPlusPaint.hasEqualAttributes(mBatteryDrawable.mBoltPaint));
-    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java
new file mode 100644
index 0000000..9ba9967
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.EditText;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class CustomEditTextPreferenceComaptTest {
+
+    @Mock
+    private View mView;
+
+    private TestPreference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mPreference = new TestPreference(RuntimeEnvironment.application);
+    }
+
+    @Test
+    public void bindDialogView_shouldRequestFocus() {
+        final String testText = "";
+        final EditText editText = spy(new EditText(RuntimeEnvironment.application));
+        editText.setText(testText);
+        when(mView.findViewById(android.R.id.edit)).thenReturn(editText);
+
+        mPreference.onBindDialogView(mView);
+
+        verify(editText).requestFocus();
+    }
+
+    @Test
+    public void getEditText_noDialog_shouldNotCrash() {
+        ReflectionHelpers.setField(mPreference, "mFragment",
+                mock(CustomEditTextPreferenceCompat.CustomPreferenceDialogFragment.class));
+
+        mPreference.getEditText();
+
+        // no crash
+    }
+
+    private static class TestPreference extends CustomEditTextPreferenceCompat {
+        public TestPreference(Context context) {
+            super(context);
+        }
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
index e153c3e..7553313 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.mock;
@@ -43,13 +44,12 @@
 import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
 /**
  * Tests for {@link HelpUtils}.
  */
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class HelpUtilsTest {
     private static final String TEST_HELP_URL = "intent:#Intent;action=com.android.test;end";
     private static final String PACKAGE_NAME_KEY = "package-name-key";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
index 914d182..dde1746 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
@@ -54,7 +54,7 @@
                     final List<ResourcePath> paths = super.getIncludedResourcePaths();
                     paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/res"));
                     paths.add(resourcePath("file:frameworks/base/core/res/res"));
-                    paths.add(resourcePath("file:frameworks/support/appcompat/res"));
+                    paths.add(resourcePath("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.appcompat_appcompat-nodeps/android_common/aar/res/"));
                     return paths;
                 }
             };
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
index ef13a5f..29831a8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -16,13 +16,14 @@
 package com.android.settingslib.bluetooth;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothCodecConfig;
 import android.bluetooth.BluetoothCodecStatus;
 import android.bluetooth.BluetoothDevice;
@@ -31,40 +32,42 @@
 import android.content.res.Resources;
 
 import com.android.settingslib.R;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
 public class A2dpProfileTest {
 
-    @Mock Context mContext;
-    @Mock LocalBluetoothAdapter mAdapter;
-    @Mock CachedBluetoothDeviceManager mDeviceManager;
-    @Mock LocalBluetoothProfileManager mProfileManager;
-    @Mock BluetoothDevice mDevice;
-    @Mock BluetoothA2dp mBluetoothA2dp;
+    @Mock
+    Context mContext;
+    @Mock
+    CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    BluetoothDevice mDevice;
+    @Mock
+    BluetoothA2dp mBluetoothA2dp;
     BluetoothProfile.ServiceListener mServiceListener;
 
     A2dpProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-
-        // Capture the A2dpServiceListener our A2dpProfile will pass during its constructor, so that
-        // we can call its onServiceConnected method and get it to use our mock BluetoothA2dp
-        // object.
-        doAnswer((invocation) -> {
-            mServiceListener = (BluetoothProfile.ServiceListener) invocation.getArguments()[1];
-            return null;
-        }).when(mAdapter).getProfileProxy(any(Context.class), any(), eq(BluetoothProfile.A2DP));
-
-        mProfile = new A2dpProfile(mContext, mAdapter, mDeviceManager, mProfileManager);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new A2dpProfile(mContext, mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
         mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp);
     }
 
@@ -126,7 +129,7 @@
     private static String KNOWN_CODEC_LABEL = "Use high quality audio: %1$s";
     private static String UNKNOWN_CODEC_LABEL = "Use high quality audio";
     private static String[] CODEC_NAMES =
-            new String[] { "Default", "SBC", "AAC", "aptX", "aptX HD", "LDAC" };
+            new String[]{"Default", "SBC", "AAC", "aptX", "aptX HD", "LDAC"};
 
     /**
      * Helper for setting up several tests of getHighQualityAudioOptionLabel
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
index 1080690..5f42b66 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
@@ -15,26 +15,24 @@
  */
 package com.android.settingslib.bluetooth;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.verify;
 
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.content.Intent;
-
 import android.telephony.TelephonyManager;
 
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class BluetoothEventManagerTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index 16ed85c..7baded8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -17,34 +17,27 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doAnswer;
-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.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 
-import com.android.settingslib.R;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 import java.util.Collection;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class CachedBluetoothDeviceManagerTest {
     private final static String DEVICE_NAME_1 = "TestName_1";
     private final static String DEVICE_NAME_2 = "TestName_2";
@@ -57,7 +50,6 @@
     private final static String DEVICE_ADDRESS_3 = "AA:BB:CC:DD:EE:33";
     private final static String DEVICE_SUMMARY_1 = "summary 1";
     private final static String DEVICE_SUMMARY_2 = "summary 2";
-    private final static String DEVICE_SUMMARY_3 = "summary 3";
     private final static long HISYNCID1 = 10;
     private final static long HISYNCID2 = 11;
     private final BluetoothClass DEVICE_CLASS_1 =
@@ -65,8 +57,6 @@
     private final BluetoothClass DEVICE_CLASS_2 =
         new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
     @Mock
-    private LocalBluetoothAdapter mLocalAdapter;
-    @Mock
     private LocalBluetoothProfileManager mLocalProfileManager;
     @Mock
     private LocalBluetoothManager mLocalBluetoothManager;
@@ -91,11 +81,6 @@
     private CachedBluetoothDevice mCachedDevice3;
     private CachedBluetoothDeviceManager mCachedDeviceManager;
     private Context mContext;
-    private String[] mActiveDeviceStringsArray;
-    private String mActiveDeviceStringNone;
-    private String mActiveDeviceStringAll;
-    private String mActiveDeviceStringMedia;
-    private String mActiveDeviceStringPhone;
 
     @Before
     public void setUp() {
@@ -115,18 +100,18 @@
         when(mDevice3.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
 
         when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
-        when(mLocalAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
+        when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalProfileManager);
         when(mHfpProfile.isProfileReady()).thenReturn(true);
         when(mA2dpProfile.isProfileReady()).thenReturn(true);
         when(mPanProfile.isProfileReady()).thenReturn(true);
         when(mHearingAidProfile.isProfileReady()).thenReturn(true);
         mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
         mCachedDevice1 = spy(
-            new CachedBluetoothDevice(mContext, mLocalAdapter, mLocalProfileManager, mDevice1));
+            new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1));
         mCachedDevice2 = spy(
-            new CachedBluetoothDevice(mContext, mLocalAdapter, mLocalProfileManager, mDevice2));
+            new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2));
         mCachedDevice3 = spy(
-            new CachedBluetoothDevice(mContext, mLocalAdapter, mLocalProfileManager, mDevice3));
+            new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice3));
     }
 
     /**
@@ -134,11 +119,9 @@
      */
     @Test
     public void testAddDevice_validCachedDevices_devicesAdded() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
 
         Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
@@ -154,8 +137,7 @@
      */
     @Test
     public void testGetName_validCachedDevice_nameFound() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         assertThat(mCachedDeviceManager.getName(mDevice1)).isEqualTo(DEVICE_ALIAS_1);
     }
@@ -165,8 +147,7 @@
      */
     @Test
     public void testOnDeviceNameUpdated_validName_nameUpdated() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1);
 
@@ -181,11 +162,9 @@
      */
     @Test
     public void testClearNonBondedDevices_bondedAndNonBondedDevices_nonBondedDevicesCleared() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
 
         when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
@@ -236,11 +215,9 @@
      */
     @Test
     public void testOnHiSyncIdChanged_sameHiSyncId_populateInDifferentLists() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
 
         // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
@@ -271,11 +248,9 @@
      */
     @Test
     public void testOnHiSyncIdChanged_sameHiSyncIdAndOneConnected_chooseConnectedDevice() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
         cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
         cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
@@ -308,11 +283,9 @@
      */
     @Test
     public void testOnHiSyncIdChanged_differentHiSyncId_populateInSameList() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
 
         // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
@@ -344,8 +317,7 @@
      */
     @Test
     public void testOnProfileConnectionStateChanged_singleDeviceConnected_visible() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
 
@@ -382,11 +354,9 @@
      */
     @Test
     public void testOnProfileConnectionStateChanged_twoDevicesConnected_oneDeviceVisible() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
         cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
         cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
@@ -436,11 +406,9 @@
      */
     @Test
     public void testOnProfileConnectionStateChanged_twoDevicesDisconnected_oneDeviceVisible() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
         cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
         cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
@@ -491,11 +459,9 @@
      */
     @Test
     public void testOnDeviceUnpaired_bothHearingAidsPaired_removesItsPairFromList() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
 
         cachedDevice1.setHiSyncId(HISYNCID1);
@@ -523,14 +489,11 @@
      */
     @Test
     public void testOnDeviceUnpaired_bothHearingAidsNotPaired_doesNotRemoveAnyDeviceFromList() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
-        CachedBluetoothDevice cachedDevice3 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice3);
+        CachedBluetoothDevice cachedDevice3 = mCachedDeviceManager.addDevice(mDevice3);
         assertThat(cachedDevice2).isNotNull();
 
         cachedDevice1.setHiSyncId(HISYNCID1);
@@ -575,8 +538,7 @@
         doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
         doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
 
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         // The first hearing aid device should be populated in mCachedDevice and
         // mCachedDevicesMapForHearingAids.
@@ -586,8 +548,7 @@
         assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
             .contains(cachedDevice1);
 
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
         // The second hearing aid device should be populated in mHearingAidDevicesNotAddedInCache.
         assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
@@ -604,8 +565,7 @@
             .getHearingAidProfile();
         doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
         doAnswer((invocation) -> HISYNCID2).when(mHearingAidProfile).getHiSyncId(mDevice2);
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         // The first hearing aid device should be populated in mCachedDevice and
         // mCachedDevicesMapForHearingAids.
@@ -615,8 +575,7 @@
         assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
             .contains(cachedDevice1);
 
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-            mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
         // The second hearing aid device should also be populated in mCachedDevice
         // and mCachedDevicesMapForHearingAids as its not a pair of the first one.
@@ -685,8 +644,7 @@
      */
     @Test
     public void testOnBtClassChanged_validBtClass_classChanged() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         assertThat(cachedDevice1.getBtClass()).isEqualTo(DEVICE_CLASS_1);
 
@@ -701,8 +659,7 @@
      */
     @Test
     public void testOnDeviceDisappeared_deviceBondedUnbonded_unbondedDeviceDisappeared() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
 
         when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
@@ -717,11 +674,9 @@
      */
     @Test
     public void testOnActiveDeviceChanged_connectedDevices_activeDeviceChanged() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
 
         when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
@@ -782,11 +737,9 @@
      */
     @Test
     public void testOnActiveDeviceChanged_withA2dpAndHearingAid() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice1);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
-                mLocalProfileManager, mDevice2);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
         assertThat(cachedDevice2).isNotNull();
 
         when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
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 c39fb85..c18db11 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
@@ -26,7 +26,6 @@
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
 
-import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
@@ -49,8 +48,6 @@
     private final static String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF";
     private final static String DEVICE_ALIAS_NEW = "TestAliasNew";
     @Mock
-    private LocalBluetoothAdapter mAdapter;
-    @Mock
     private LocalBluetoothProfileManager mProfileManager;
     @Mock
     private HeadsetProfile mHfpProfile;
@@ -73,13 +70,11 @@
         mContext = RuntimeEnvironment.application;
         mShadowAudioManager = shadowOf(mContext.getSystemService(AudioManager.class));
         when(mDevice.getAddress()).thenReturn(DEVICE_ADDRESS);
-        when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
         when(mHfpProfile.isProfileReady()).thenReturn(true);
         when(mA2dpProfile.isProfileReady()).thenReturn(true);
         when(mPanProfile.isProfileReady()).thenReturn(true);
         when(mHearingAidProfile.isProfileReady()).thenReturn(true);
-        mCachedDevice = spy(
-                new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice));
+        mCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mDevice));
         doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel();
     }
 
@@ -477,7 +472,7 @@
         when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS);
         when(mDevice.getName()).thenReturn(DEVICE_NAME);
         CachedBluetoothDevice cachedBluetoothDevice =
-                new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice);
+                new CachedBluetoothDevice(mContext, mProfileManager, mDevice);
         // Verify alias is returned on getName
         assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS);
         // Verify device is visible
@@ -487,7 +482,7 @@
     @Test
     public void testDeviceName_testNameNotAvailable() {
         CachedBluetoothDevice cachedBluetoothDevice =
-                new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice);
+                new CachedBluetoothDevice(mContext, mProfileManager, mDevice);
         // Verify device address is returned on getName
         assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ADDRESS);
         // Verify device is not visible
@@ -504,7 +499,7 @@
         }).when(mDevice).setAlias(anyString());
         when(mDevice.getName()).thenReturn(DEVICE_NAME);
         CachedBluetoothDevice cachedBluetoothDevice =
-                new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice);
+                new CachedBluetoothDevice(mContext, mProfileManager, mDevice);
         // Verify alias is returned on getName
         assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS);
         // Verify null name does not get set
@@ -543,7 +538,7 @@
         when(mA2dpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_CONNECTED);
 
-        assertThat(mCachedDevice.isA2dpDevice()).isTrue();
+        assertThat(mCachedDevice.isConnectedA2dpDevice()).isTrue();
     }
 
     @Test
@@ -552,7 +547,7 @@
         when(mA2dpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_DISCONNECTING);
 
-        assertThat(mCachedDevice.isA2dpDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedA2dpDevice()).isFalse();
     }
 
     @Test
@@ -561,7 +556,7 @@
         when(mHfpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_CONNECTED);
 
-        assertThat(mCachedDevice.isHfpDevice()).isTrue();
+        assertThat(mCachedDevice.isConnectedHfpDevice()).isTrue();
     }
 
     @Test
@@ -570,7 +565,7 @@
         when(mHfpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_DISCONNECTING);
 
-        assertThat(mCachedDevice.isHfpDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedHfpDevice()).isFalse();
     }
 
     @Test
@@ -595,14 +590,14 @@
     public void isConnectedHfpDevice_profileIsNull_returnFalse() {
         when(mProfileManager.getHeadsetProfile()).thenReturn(null);
 
-        assertThat(mCachedDevice.isHfpDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedHfpDevice()).isFalse();
     }
 
     @Test
     public void isConnectedA2dpDevice_profileIsNull_returnFalse() {
         when(mProfileManager.getA2dpProfile()).thenReturn(null);
 
-        assertThat(mCachedDevice.isA2dpDevice()).isFalse();
+        assertThat(mCachedDevice.isConnectedA2dpDevice()).isFalse();
     }
 
     @Test
@@ -611,4 +606,35 @@
 
         assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse();
     }
+
+    @Test
+    public void getName_aliasNameNotNull_returnAliasName() {
+        when(mDevice.getAliasName()).thenReturn(DEVICE_NAME);
+
+        assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_NAME);
+    }
+
+    @Test
+    public void getName_aliasNameIsNull_returnAddress() {
+        when(mDevice.getAliasName()).thenReturn(null);
+
+        assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_ADDRESS);
+    }
+
+    @Test
+    public void setName_setDeviceNameIsNotNull() {
+        final String name = "test name";
+        when(mDevice.getAliasName()).thenReturn(DEVICE_NAME);
+
+        mCachedDevice.setName(name);
+
+        verify(mDevice).setAlias(name);
+    }
+
+    @Test
+    public void setName_setDeviceNameIsNull() {
+        mCachedDevice.setName(null);
+
+        verify(mDevice, never()).setAlias(any());
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
index 03b023b..c0a1f0c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
@@ -2,31 +2,32 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
 public class HeadsetProfileTest {
 
     @Mock
-    private LocalBluetoothAdapter mAdapter;
-    @Mock
     private CachedBluetoothDeviceManager mDeviceManager;
     @Mock
     private LocalBluetoothProfileManager mProfileManager;
@@ -38,19 +39,18 @@
     private BluetoothDevice mBluetoothDevice;
     private BluetoothProfile.ServiceListener mServiceListener;
     private HeadsetProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         Context context = spy(RuntimeEnvironment.application);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
 
-        doAnswer((invocation) -> {
-            mServiceListener = (BluetoothProfile.ServiceListener) invocation.getArguments()[1];
-            return null;
-        }).when(mAdapter).getProfileProxy(any(Context.class), any(), eq(BluetoothProfile.HEADSET));
         when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
 
-        mProfile = new HeadsetProfile(context, mAdapter, mDeviceManager, mProfileManager);
+        mProfile = new HeadsetProfile(context, mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
         mServiceListener.onServiceConnected(BluetoothProfile.HEADSET, mService);
     }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index d342bc8..f223176 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -37,43 +37,47 @@
 import android.content.Intent;
 import android.os.ParcelUuid;
 
-import java.util.ArrayList;
-import java.util.List;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
 
-@RunWith(RobolectricTestRunner.class)
-@Config(resourceDir = "../../res")
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
 public class LocalBluetoothProfileManagerTest {
     @Mock
     private CachedBluetoothDeviceManager mDeviceManager;
     @Mock
     private BluetoothEventManager mEventManager;
     @Mock
-    private LocalBluetoothAdapter mAdapter;
-    @Mock
     private BluetoothDevice mDevice;
     @Mock
     private CachedBluetoothDevice mCachedBluetoothDevice;
 
     private Context mContext;
-    private LocalBluetoothProfileManager mProfileManager;
     private Intent mIntent;
+    private LocalBluetoothAdapter mLocalBluetoothAdapter;
+    private LocalBluetoothProfileManager mProfileManager;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
-        mEventManager = spy(new BluetoothEventManager(mAdapter,
-                mDeviceManager, mContext));
-        when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
+        mLocalBluetoothAdapter = LocalBluetoothAdapter.getInstance();
+        mEventManager = spy(new BluetoothEventManager(mLocalBluetoothAdapter, mDeviceManager,
+                mContext));
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
         when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice);
     }
 
@@ -82,8 +86,10 @@
      */
     @Test
     public void constructor_initiateHidAndHidDeviceProfile() {
-        mProfileManager =
-                new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
+        mShadowBluetoothAdapter.setSupportedProfiles(generateList(
+                new int[] {BluetoothProfile.HID_HOST, BluetoothProfile.HID_DEVICE}));
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
 
         assertThat(mProfileManager.getHidProfile()).isNotNull();
         assertThat(mProfileManager.getHidDeviceProfile()).isNotNull();
@@ -94,14 +100,14 @@
      */
     @Test
     public void updateLocalProfiles_addA2dpToLocalProfiles() {
-        mProfileManager =
-                new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
         assertThat(mProfileManager.getA2dpProfile()).isNull();
         assertThat(mProfileManager.getHeadsetProfile()).isNull();
 
-        ParcelUuid[] uuids = mAdapter.getUuids();
-        mProfileManager.updateLocalProfiles(uuids);
+        mShadowBluetoothAdapter.setSupportedProfiles(generateList(
+                new int[] {BluetoothProfile.A2DP}));
+        mProfileManager.updateLocalProfiles();
 
         assertThat(mProfileManager.getA2dpProfile()).isNotNull();
         assertThat(mProfileManager.getHeadsetProfile()).isNull();
@@ -112,8 +118,10 @@
      */
     @Test
     public void updateProfiles_addHidProfileForRemoteDevice() {
-        mProfileManager =
-                new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
+        mShadowBluetoothAdapter.setSupportedProfiles(generateList(
+                new int[] {BluetoothProfile.HID_HOST}));
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
         ParcelUuid[] uuids = new ParcelUuid[]{BluetoothUuid.Hid};
         ParcelUuid[] localUuids = new ParcelUuid[]{};
         List<LocalBluetoothProfile> profiles = new ArrayList<>();
@@ -133,9 +141,10 @@
      */
     @Test
     public void stateChangedHandler_receiveA2dpConnectionStateChanged_shouldDispatchCallback() {
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
-                mEventManager);
+        mShadowBluetoothAdapter.setSupportedProfiles(generateList(
+                new int[] {BluetoothProfile.A2DP}));
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -156,9 +165,10 @@
      */
     @Test
     public void stateChangedHandler_receiveHeadsetConnectionStateChanged_shouldDispatchCallback() {
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.Handsfree_AG});
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
-                mEventManager);
+        mShadowBluetoothAdapter.setSupportedProfiles(generateList(
+                new int[] {BluetoothProfile.HEADSET}));
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -179,12 +189,10 @@
      */
     @Test
     public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldDispatchCallback() {
-        ArrayList<Integer> supportProfiles = new ArrayList<>();
-        supportProfiles.add(BluetoothProfile.HEARING_AID);
-        when(mAdapter.getSupportedProfiles()).thenReturn(supportProfiles);
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.HearingAid});
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
-                mEventManager);
+        mShadowBluetoothAdapter.setSupportedProfiles(generateList(
+                new int[] {BluetoothProfile.HEARING_AID}));
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -205,9 +213,10 @@
      */
     @Test
     public void stateChangedHandler_receivePanConnectionStateChanged_shouldNotDispatchCallback() {
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
-                mEventManager);
+        mShadowBluetoothAdapter.setSupportedProfiles(generateList(
+                new int[] {BluetoothProfile.PAN}));
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -227,10 +236,34 @@
      * handler and refresh CachedBluetoothDevice
      */
     @Test
-    public void stateChangedHandler_receivePanConnectionStateChangedWithoutUuid_shouldNotRefresh() {
-        when(mAdapter.getUuids()).thenReturn(null);
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
-                mEventManager);
+    public void stateChangedHandler_receivePanConnectionStateChangedWithoutProfile_shouldNotRefresh
+    () {
+        mShadowBluetoothAdapter.setSupportedProfiles(null);
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
+        // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
+        // LocalBluetoothProfileManager created.
+        mEventManager.setReceiverHandler(null);
+        mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
+        mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
+        mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
+        mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
+
+        mContext.sendBroadcast(mIntent);
+
+        verify(mCachedBluetoothDevice, never()).refresh();
+    }
+
+    /**
+     * Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuids will dispatch to
+     * handler and refresh CachedBluetoothDevice
+     */
+    @Test
+    public void stateChangedHandler_receivePanConnectionStateChangedWithProfile_shouldRefresh() {
+        mShadowBluetoothAdapter.setSupportedProfiles(generateList(
+                new int[] {BluetoothProfile.PAN}));
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -244,25 +277,14 @@
         verify(mCachedBluetoothDevice).refresh();
     }
 
-    /**
-     * Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuids will dispatch to
-     * handler and refresh CachedBluetoothDevice
-     */
-    @Test
-    public void stateChangedHandler_receivePanConnectionStateChangedWithUuids_shouldRefresh() {
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
-                mEventManager);
-        // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
-        // LocalBluetoothProfileManager created.
-        mEventManager.setReceiverHandler(null);
-        mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
-        mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
-        mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
-        mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
-
-        mContext.sendBroadcast(mIntent);
-
-        verify(mCachedBluetoothDevice).refresh();
+    private List<Integer> generateList(int[] profile) {
+        if (profile == null) {
+            return null;
+        }
+        final List<Integer> profileList = new ArrayList<>(profile.length);
+        for(int i = 0; i < profile.length; i++) {
+            profileList.add(profile[i]);
+        }
+        return profileList;
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java
index 5261ea0..4d7553c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java
@@ -16,21 +16,24 @@
 package com.android.settingslib.core;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class AbstractPreferenceControllerTest {
 
     @Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
index 52068e9..28828a0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
@@ -18,11 +18,12 @@
 import static androidx.lifecycle.Lifecycle.Event.ON_START;
 import static com.google.common.truth.Truth.assertThat;
 
-import androidx.lifecycle.LifecycleOwner;
 import android.content.Context;
+import android.os.Bundle;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
+import android.widget.LinearLayout;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.events.OnAttach;
@@ -34,13 +35,15 @@
 import com.android.settingslib.core.lifecycle.events.OnResume;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.testutils.FragmentTestUtils;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.android.controller.ActivityController;
-import org.robolectric.android.controller.FragmentController;
+
+import androidx.lifecycle.LifecycleOwner;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
 public class LifecycleTest {
@@ -64,7 +67,7 @@
 
         public TestFragment() {
             mFragObserver = new TestObserver();
-            getLifecycle().addObserver(mFragObserver);
+            getSettingsLifecycle().addObserver(mFragObserver);
         }
     }
 
@@ -74,9 +77,17 @@
 
         public TestActivity() {
             mActObserver = new TestObserver();
-            getLifecycle().addObserver(mActObserver);
+            getSettingsLifecycle().addObserver(mActObserver);
         }
 
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            LinearLayout view = new LinearLayout(this);
+            view.setId(1);
+
+            setContentView(view);
+        }
     }
 
     public static class TestObserver implements LifecycleObserver, OnAttach, OnStart, OnResume,
@@ -151,11 +162,9 @@
     @Test
     public void runThroughActivityLifecycles_shouldObserveEverything() {
         ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class);
-        TestActivity activity = ac.get();
+        TestActivity activity = ac.setup().get();
 
-        ac.start();
         assertThat(activity.mActObserver.mOnStartObserved).isTrue();
-        ac.resume();
         assertThat(activity.mActObserver.mOnResumeObserved).isTrue();
         activity.onCreateOptionsMenu(null);
         assertThat(activity.mActObserver.mOnCreateOptionsMenuObserved).isTrue();
@@ -173,50 +182,50 @@
 
     @Test
     public void runThroughDialogFragmentLifecycles_shouldObserveEverything() {
-        FragmentController<TestDialogFragment> fragmentController =
-                Robolectric.buildFragment(TestDialogFragment.class);
-        TestDialogFragment fragment = fragmentController.get();
+        final TestDialogFragment fragment = new TestDialogFragment();
+        FragmentTestUtils.startFragment(fragment);
 
-        fragmentController.create().start().resume();
         fragment.onCreateOptionsMenu(null, null);
         fragment.onPrepareOptionsMenu(null);
         fragment.onOptionsItemSelected(null);
-        fragmentController.pause().stop().destroy();
+        assertThat(fragment.mFragObserver.mOnCreateOptionsMenuObserved).isTrue();
+        assertThat(fragment.mFragObserver.mOnPrepareOptionsMenuObserved).isTrue();
+        assertThat(fragment.mFragObserver.mOnOptionsItemSelectedObserved).isTrue();
 
         assertThat(fragment.mFragObserver.mOnAttachObserved).isTrue();
         assertThat(fragment.mFragObserver.mOnAttachHasContext).isTrue();
         assertThat(fragment.mFragObserver.mOnStartObserved).isTrue();
         assertThat(fragment.mFragObserver.mOnResumeObserved).isTrue();
+        fragment.onPause();
         assertThat(fragment.mFragObserver.mOnPauseObserved).isTrue();
+        fragment.onStop();
         assertThat(fragment.mFragObserver.mOnStopObserved).isTrue();
+        fragment.onDestroy();
         assertThat(fragment.mFragObserver.mOnDestroyObserved).isTrue();
-        assertThat(fragment.mFragObserver.mOnCreateOptionsMenuObserved).isTrue();
-        assertThat(fragment.mFragObserver.mOnPrepareOptionsMenuObserved).isTrue();
-        assertThat(fragment.mFragObserver.mOnOptionsItemSelectedObserved).isTrue();
     }
 
     @Test
     public void runThroughFragmentLifecycles_shouldObserveEverything() {
-        FragmentController<TestFragment> fragmentController =
-                Robolectric.buildFragment(TestFragment.class);
-        TestFragment fragment = fragmentController.get();
+        final TestFragment fragment = new TestFragment();
+        FragmentTestUtils.startFragment(fragment);
 
-        fragmentController.create().start().resume();
         fragment.onCreateOptionsMenu(null, null);
         fragment.onPrepareOptionsMenu(null);
         fragment.onOptionsItemSelected(null);
-        fragmentController.pause().stop().destroy();
+        assertThat(fragment.mFragObserver.mOnCreateOptionsMenuObserved).isTrue();
+        assertThat(fragment.mFragObserver.mOnPrepareOptionsMenuObserved).isTrue();
+        assertThat(fragment.mFragObserver.mOnOptionsItemSelectedObserved).isTrue();
 
         assertThat(fragment.mFragObserver.mOnAttachObserved).isTrue();
         assertThat(fragment.mFragObserver.mOnAttachHasContext).isTrue();
         assertThat(fragment.mFragObserver.mOnStartObserved).isTrue();
         assertThat(fragment.mFragObserver.mOnResumeObserved).isTrue();
+        fragment.onPause();
         assertThat(fragment.mFragObserver.mOnPauseObserved).isTrue();
+        fragment.onStop();
         assertThat(fragment.mFragObserver.mOnStopObserved).isTrue();
+        fragment.onDestroy();
         assertThat(fragment.mFragObserver.mOnDestroyObserved).isTrue();
-        assertThat(fragment.mFragObserver.mOnCreateOptionsMenuObserved).isTrue();
-        assertThat(fragment.mFragObserver.mOnPrepareOptionsMenuObserved).isTrue();
-        assertThat(fragment.mFragObserver.mOnOptionsItemSelectedObserved).isTrue();
     }
 
     @Test
@@ -237,17 +246,16 @@
 
     @Test
     public void onOptionItemSelectedShortCircuitsIfAnObserverHandlesTheMenuItem() {
-        FragmentController<TestFragment> fragmentController =
-                Robolectric.buildFragment(TestFragment.class);
-        TestFragment fragment = fragmentController.get();
-        OptionItemAccepter accepter = new OptionItemAccepter();
+        final TestFragment fragment = new TestFragment();
+        FragmentTestUtils.startFragment(fragment);
+
+        final OptionItemAccepter accepter = new OptionItemAccepter();
         fragment.getLifecycle().addObserver(accepter);
 
-        fragmentController.create().start().resume();
+
         fragment.onCreateOptionsMenu(null, null);
         fragment.onPrepareOptionsMenu(null);
         fragment.onOptionsItemSelected(null);
-        fragmentController.pause().stop().destroy();
 
         assertThat(accepter.wasCalled).isFalse();
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
index ba955f9..20ce465 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
@@ -63,7 +63,8 @@
         uptimePreferenceController.displayPreference(mScreen);
 
         // SystemClock is shadowed so it shouldn't advance unexpectedly while the test is running
-        verify(mPreference).setSummary(DateUtils.formatDuration(SystemClock.elapsedRealtime()));
+        verify(mPreference).setSummary(
+                DateUtils.formatElapsedTime(SystemClock.elapsedRealtime() / 1000));
     }
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
index 605c861..c495511 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
@@ -20,13 +20,15 @@
 
 import android.util.ArraySet;
 
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 
 import java.util.Set;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class CategoryKeyTest {
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
deleted file mode 100644
index 4efcb7e..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.drawer;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Pair;
-
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.shadows.ShadowApplication;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@RunWith(SettingsLibRobolectricTestRunner.class)
-public class CategoryManagerTest {
-
-    private Context mContext;
-    private CategoryManager mCategoryManager;
-    private Map<Pair<String, String>, Tile> mTileByComponentCache;
-    private Map<String, DashboardCategory> mCategoryByKeyMap;
-
-    @Before
-    public void setUp() {
-        mContext = ShadowApplication.getInstance().getApplicationContext();
-        mTileByComponentCache = new HashMap<>();
-        mCategoryByKeyMap = new HashMap<>();
-        mCategoryManager = CategoryManager.get(mContext);
-    }
-
-    @Test
-    public void getInstance_shouldBeSingleton() {
-        assertThat(mCategoryManager).isSameAs(CategoryManager.get(mContext));
-    }
-
-    @Test
-    public void backwardCompatCleanupForCategory_shouldNotChangeCategoryForNewKeys() {
-        final Tile tile1 = new Tile();
-        final Tile tile2 = new Tile();
-        tile1.category = CategoryKey.CATEGORY_ACCOUNT;
-        tile2.category = CategoryKey.CATEGORY_ACCOUNT;
-        final DashboardCategory category = new DashboardCategory();
-        category.addTile(tile1);
-        category.addTile(tile2);
-        mCategoryByKeyMap.put(CategoryKey.CATEGORY_ACCOUNT, category);
-        mTileByComponentCache.put(new Pair<>("PACKAGE", "1"), tile1);
-        mTileByComponentCache.put(new Pair<>("PACKAGE", "2"), tile2);
-
-        mCategoryManager.backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap);
-
-        assertThat(mCategoryByKeyMap.size()).isEqualTo(1);
-        assertThat(mCategoryByKeyMap.get(CategoryKey.CATEGORY_ACCOUNT)).isNotNull();
-    }
-
-    @Test
-    public void backwardCompatCleanupForCategory_shouldNotChangeCategoryForMixedKeys() {
-        final Tile tile1 = new Tile();
-        final Tile tile2 = new Tile();
-        final String oldCategory = "com.android.settings.category.wireless";
-        tile1.category = CategoryKey.CATEGORY_ACCOUNT;
-        tile2.category = oldCategory;
-        final DashboardCategory category1 = new DashboardCategory();
-        category1.addTile(tile1);
-        final DashboardCategory category2 = new DashboardCategory();
-        category2.addTile(tile2);
-        mCategoryByKeyMap.put(CategoryKey.CATEGORY_ACCOUNT, category1);
-        mCategoryByKeyMap.put(oldCategory, category2);
-        mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS1"), tile1);
-        mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS2"), tile2);
-
-        mCategoryManager.backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap);
-
-        assertThat(mCategoryByKeyMap.size()).isEqualTo(2);
-        assertThat(
-                mCategoryByKeyMap.get(CategoryKey.CATEGORY_ACCOUNT).getTilesCount()).isEqualTo(1);
-        assertThat(mCategoryByKeyMap.get(oldCategory).getTilesCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void backwardCompatCleanupForCategory_shouldChangeCategoryForOldKeys() {
-        final Tile tile1 = new Tile();
-        final String oldCategory = "com.android.settings.category.wireless";
-        tile1.category = oldCategory;
-        final DashboardCategory category1 = new DashboardCategory();
-        category1.addTile(tile1);
-        mCategoryByKeyMap.put(oldCategory, category1);
-        mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS1"), tile1);
-
-        mCategoryManager.backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap);
-
-        // Added 1 more category to category map.
-        assertThat(mCategoryByKeyMap.size()).isEqualTo(2);
-        // The new category map has CATEGORY_NETWORK type now, which contains 1 tile.
-        assertThat(
-                mCategoryByKeyMap.get(CategoryKey.CATEGORY_NETWORK).getTilesCount()).isEqualTo(1);
-        // Old category still exists.
-        assertThat(mCategoryByKeyMap.get(oldCategory).getTilesCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void sortCategories_singlePackage_shouldReorderBasedOnPriority() {
-        // Create some fake tiles that are not sorted.
-        final String testPackage = "com.android.test";
-        final DashboardCategory category = new DashboardCategory();
-        final Tile tile1 = new Tile();
-        tile1.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class1"));
-        tile1.priority = 100;
-        final Tile tile2 = new Tile();
-        tile2.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class2"));
-        tile2.priority = 50;
-        final Tile tile3 = new Tile();
-        tile3.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class3"));
-        tile3.priority = 200;
-        category.addTile(tile1);
-        category.addTile(tile2);
-        category.addTile(tile3);
-        mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category);
-
-        // Sort their priorities
-        mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(),
-                mCategoryByKeyMap);
-
-        // Verify they are now sorted.
-        assertThat(category.getTile(0)).isSameAs(tile3);
-        assertThat(category.getTile(1)).isSameAs(tile1);
-        assertThat(category.getTile(2)).isSameAs(tile2);
-    }
-
-    @Test
-    public void sortCategories_multiPackage_shouldReorderBasedOnPackageAndPriority() {
-        // Create some fake tiles that are not sorted.
-        final String testPackage1 = "com.android.test1";
-        final String testPackage2 = "com.android.test2";
-        final DashboardCategory category = new DashboardCategory();
-        final Tile tile1 = new Tile();
-        tile1.intent =
-                new Intent().setComponent(new ComponentName(testPackage2, "class1"));
-        tile1.priority = 100;
-        final Tile tile2 = new Tile();
-        tile2.intent =
-                new Intent().setComponent(new ComponentName(testPackage1, "class2"));
-        tile2.priority = 100;
-        final Tile tile3 = new Tile();
-        tile3.intent =
-                new Intent().setComponent(new ComponentName(testPackage1, "class3"));
-        tile3.priority = 50;
-        category.addTile(tile1);
-        category.addTile(tile2);
-        category.addTile(tile3);
-        mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category);
-
-        // Sort their priorities
-        mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(),
-                mCategoryByKeyMap);
-
-        // Verify they are now sorted.
-        assertThat(category.getTile(0)).isSameAs(tile2);
-        assertThat(category.getTile(1)).isSameAs(tile1);
-        assertThat(category.getTile(2)).isSameAs(tile3);
-    }
-
-    @Test
-    public void sortCategories_internalPackageTiles_shouldSkipTileForInternalPackage() {
-        // Create some fake tiles that are not sorted.
-        final String testPackage =
-                ShadowApplication.getInstance().getApplicationContext().getPackageName();
-        final DashboardCategory category = new DashboardCategory();
-        final Tile tile1 = new Tile();
-        tile1.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class1"));
-        tile1.priority = 100;
-        final Tile tile2 = new Tile();
-        tile2.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class2"));
-        tile2.priority = 100;
-        final Tile tile3 = new Tile();
-        tile3.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class3"));
-        tile3.priority = 50;
-        category.addTile(tile1);
-        category.addTile(tile2);
-        category.addTile(tile3);
-        mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category);
-
-        // Sort their priorities
-        mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(),
-                mCategoryByKeyMap);
-
-        // Verify the sorting order is not changed
-        assertThat(category.getTile(0)).isSameAs(tile1);
-        assertThat(category.getTile(1)).isSameAs(tile2);
-        assertThat(category.getTile(2)).isSameAs(tile3);
-    }
-
-    @Test
-    public void sortCategories_internalAndExternalPackageTiles_shouldRetainPriorityOrdering() {
-        // Inject one external tile among internal tiles.
-        final String testPackage =
-            ShadowApplication.getInstance().getApplicationContext().getPackageName();
-        final String testPackage2 = "com.google.test2";
-        final DashboardCategory category = new DashboardCategory();
-        final Tile tile1 = new Tile();
-        tile1.intent = new Intent().setComponent(new ComponentName(testPackage, "class1"));
-        tile1.priority = 2;
-        final Tile tile2 = new Tile();
-        tile2.intent = new Intent().setComponent(new ComponentName(testPackage, "class2"));
-        tile2.priority = 1;
-        final Tile tile3 = new Tile();
-        tile3.intent = new Intent().setComponent(new ComponentName(testPackage2, "class0"));
-        tile3.priority = 0;
-        final Tile tile4 = new Tile();
-        tile4.intent = new Intent().setComponent(new ComponentName(testPackage, "class3"));
-        tile4.priority = -1;
-        category.addTile(tile1);
-        category.addTile(tile2);
-        category.addTile(tile3);
-        category.addTile(tile4);
-        mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category);
-
-        // Sort their priorities
-        mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(),
-            mCategoryByKeyMap);
-
-        // Verify the sorting order is not changed
-        assertThat(category.getTile(0)).isSameAs(tile1);
-        assertThat(category.getTile(1)).isSameAs(tile2);
-        assertThat(category.getTile(2)).isSameAs(tile3);
-        assertThat(category.getTile(3)).isSameAs(tile4);
-    }
-
-    @Test
-    public void sortCategories_samePriority_internalPackageTileShouldTakePrecedence() {
-        // Inject one external tile among internal tiles with same priority.
-        final String testPackage =
-            ShadowApplication.getInstance().getApplicationContext().getPackageName();
-        final String testPackage2 = "com.google.test2";
-        final String testPackage3 = "com.abcde.test3";
-        final DashboardCategory category = new DashboardCategory();
-        final Tile tile1 = new Tile();
-        tile1.intent = new Intent().setComponent(new ComponentName(testPackage2, "class1"));
-        tile1.priority = 1;
-        final Tile tile2 = new Tile();
-        tile2.intent = new Intent().setComponent(new ComponentName(testPackage, "class2"));
-        tile2.priority = 1;
-        final Tile tile3 = new Tile();
-        tile3.intent = new Intent().setComponent(new ComponentName(testPackage3, "class3"));
-        tile3.priority = 1;
-        category.addTile(tile1);
-        category.addTile(tile2);
-        category.addTile(tile3);
-        mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category);
-
-        // Sort their priorities
-        mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(),
-            mCategoryByKeyMap);
-
-        // Verify the sorting order is internal first, follow by package name ordering
-        assertThat(category.getTile(0)).isSameAs(tile2);
-        assertThat(category.getTile(1)).isSameAs(tile3);
-        assertThat(category.getTile(2)).isSameAs(tile1);
-    }
-
-    @Test
-    public void filterTiles_noDuplicate_noChange() {
-        // Create some unique tiles
-        final String testPackage =
-                ShadowApplication.getInstance().getApplicationContext().getPackageName();
-        final DashboardCategory category = new DashboardCategory();
-        final Tile tile1 = new Tile();
-        tile1.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class1"));
-        tile1.priority = 100;
-        final Tile tile2 = new Tile();
-        tile2.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class2"));
-        tile2.priority = 100;
-        final Tile tile3 = new Tile();
-        tile3.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class3"));
-        tile3.priority = 50;
-        category.addTile(tile1);
-        category.addTile(tile2);
-        category.addTile(tile3);
-        mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category);
-
-        mCategoryManager.filterDuplicateTiles(mCategoryByKeyMap);
-
-        assertThat(category.getTilesCount()).isEqualTo(3);
-    }
-
-    @Test
-    public void filterTiles_hasDuplicate_shouldOnlyKeepUniqueTiles() {
-        // Create tiles pointing to same intent.
-        final String testPackage =
-                ShadowApplication.getInstance().getApplicationContext().getPackageName();
-        final DashboardCategory category = new DashboardCategory();
-        final Tile tile1 = new Tile();
-        tile1.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class1"));
-        tile1.priority = 100;
-        final Tile tile2 = new Tile();
-        tile2.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class1"));
-        tile2.priority = 100;
-        final Tile tile3 = new Tile();
-        tile3.intent =
-                new Intent().setComponent(new ComponentName(testPackage, "class1"));
-        tile3.priority = 50;
-        category.addTile(tile1);
-        category.addTile(tile2);
-        category.addTile(tile3);
-        mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category);
-
-        mCategoryManager.filterDuplicateTiles(mCategoryByKeyMap);
-
-        assertThat(category.getTilesCount()).isEqualTo(1);
-    }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
index 996a122..a501ffa 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
@@ -1,37 +1,51 @@
 package com.android.settingslib.drawer;
 
-import static com.google.common.truth.Truth.assertThat;
-
+import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
 import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
 
-import android.os.Bundle;
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.junit.Test;
+import static com.google.common.truth.Truth.assertThat;
 
-@RunWith(RobolectricTestRunner.class)
+import android.content.pm.ActivityInfo;
+import android.os.Bundle;
+
+import com.android.settingslib.R;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class TileTest {
 
+    private ActivityInfo mActivityInfo;
     private Tile mTile;
 
     @Before
     public void setUp() {
-        mTile = new Tile();
-        mTile.metaData = new Bundle();
+        mActivityInfo = new ActivityInfo();
+        mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName();
+        mActivityInfo.name = "abc";
+        mActivityInfo.icon = R.drawable.ic_plus;
+        mActivityInfo.metaData = new Bundle();
+        mTile = new Tile(mActivityInfo, "category");
     }
 
     @Test
     public void isPrimaryProfileOnly_profilePrimary_shouldReturnTrue() {
-        mTile.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_PRIMARY);
+        mActivityInfo.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_PRIMARY);
         assertThat(mTile.isPrimaryProfileOnly()).isTrue();
     }
 
     @Test
     public void isPrimaryProfileOnly_profileAll_shouldReturnFalse() {
-        mTile.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_ALL);
+        mActivityInfo.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_ALL);
         assertThat(mTile.isPrimaryProfileOnly()).isFalse();
     }
 
@@ -42,7 +56,94 @@
 
     @Test
     public void isPrimaryProfileOnly_nullMetadata_shouldReturnFalse() {
-        mTile.metaData = null;
+        mActivityInfo.metaData = null;
         assertThat(mTile.isPrimaryProfileOnly()).isFalse();
     }
+
+    @Test
+    public void getIcon_noContextOrMetadata_returnNull() {
+        mActivityInfo.metaData = null;
+        final Tile tile = new Tile(mActivityInfo, "category");
+        assertThat(tile.getIcon(null)).isNull();
+        assertThat(tile.getIcon(RuntimeEnvironment.application)).isNull();
+    }
+
+    @Test
+    public void getIcon_providedByUri_returnNull() {
+        mActivityInfo.metaData.putString(META_DATA_PREFERENCE_ICON_URI, "content://foobar/icon");
+
+        assertThat(mTile.getIcon(RuntimeEnvironment.application)).isNull();
+    }
+
+    @Test
+    public void getIcon_hasIconMetadata_returnIcon() {
+        mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_info);
+
+        assertThat(mTile.getIcon(RuntimeEnvironment.application).getResId())
+                .isEqualTo(R.drawable.ic_info);
+    }
+
+    @Test
+    public void getIcon_noIconMetadata_returnActivityIcon() {
+        mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, 0);
+
+        assertThat(mTile.getIcon(RuntimeEnvironment.application).getResId())
+                .isEqualTo(mActivityInfo.icon);
+    }
+
+    @Test
+    public void isIconTintable_hasMetadata_shouldReturnIconTintableMetadata() {
+        final Tile tile = new Tile(mActivityInfo, "category");
+
+        mActivityInfo.metaData.putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, false);
+        assertThat(tile.isIconTintable(RuntimeEnvironment.application)).isFalse();
+
+        mActivityInfo.metaData.putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, true);
+        assertThat(tile.isIconTintable(RuntimeEnvironment.application)).isTrue();
+    }
+
+    @Test
+    public void isIconTintable_noIcon_shouldReturnFalse() {
+        final Tile tile = new Tile(mActivityInfo, "category");
+
+        assertThat(tile.isIconTintable(RuntimeEnvironment.application)).isFalse();
+    }
+
+    @Test
+    public void isIconTintable_noMetadata_shouldReturnPackageNameCheck() {
+        final Tile tile1 = new Tile(mActivityInfo, "category");
+        assertThat(tile1.isIconTintable(RuntimeEnvironment.application)).isFalse();
+
+        final ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.packageName = "blah";
+        activityInfo.name = "abc";
+
+        final Tile tile2 = new Tile(activityInfo, "category");
+        assertThat(tile2.isIconTintable(RuntimeEnvironment.application)).isTrue();
+    }
+
+    @Test
+    public void getPriority_noMetadata_return0() {
+        final Tile tile = new Tile(mActivityInfo, "category");
+
+        assertThat(tile.getOrder()).isEqualTo(0);
+    }
+
+    @Test
+    public void getPriority_badMetadata_return0() {
+        mActivityInfo.metaData.putString(META_DATA_KEY_ORDER, "1");
+
+        final Tile tile = new Tile(mActivityInfo, "category");
+
+        assertThat(tile.getOrder()).isEqualTo(0);
+    }
+
+    @Test
+    public void getPriority_validMetadata_returnMetadataValue() {
+        mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 1);
+
+        final Tile tile = new Tile(mActivityInfo, "category");
+
+        assertThat(tile.getOrder()).isEqualTo(1);
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 6e66805..362ae4c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -16,11 +16,18 @@
 
 package com.android.settingslib.drawer;
 
+import static com.android.settingslib.drawer.TileUtils.IA_SETTINGS_ACTION;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
+
 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.anyString;
-import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.atLeastOnce;
@@ -32,7 +39,6 @@
 import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.IContentProvider;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -40,16 +46,15 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
-import android.net.Uri;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings.Global;
-import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Pair;
-import android.widget.RemoteViews;
+
+import com.android.settingslib.R;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -57,17 +62,12 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = TileUtilsTest.TileUtilsShadowRemoteViews.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class TileUtilsTest {
 
     private Context mContext;
@@ -78,8 +78,6 @@
     @Mock
     private UserManager mUserManager;
     @Mock
-    private IContentProvider mIContentProvider;
-    @Mock
     private ContentResolver mContentResolver;
 
     private static final String URI_GET_SUMMARY = "content://authority/text/summary";
@@ -102,87 +100,58 @@
     @Test
     public void getTilesForIntent_shouldParseCategory() {
         final String testCategory = "category1";
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
         info.add(newInfo(true, testCategory));
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).category).isEqualTo(testCategory);
+        assertThat(outTiles.get(0).getCategory()).isEqualTo(testCategory);
     }
 
     @Test
     public void getTilesForIntent_shouldParseKeyHintForSystemApp() {
         String keyHint = "key";
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
         ResolveInfo resolveInfo = newInfo(true, null /* category */, keyHint);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* requiresSettings */);
 
-        assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).key).isEqualTo(keyHint);
+        assertThat(outTiles).hasSize(1);
+        assertThat(outTiles.get(0).getKey(mContext)).isEqualTo(keyHint);
     }
 
     @Test
     public void getTilesForIntent_shouldSkipNonSystemApp() {
         final String testCategory = "category1";
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
         info.add(newInfo(false, testCategory));
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION,
+                addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
 
-        assertThat(outTiles.isEmpty()).isTrue();
+        assertThat(outTiles).isEmpty();
     }
 
     @Test
-    public void getCategories_shouldHandleExtraIntentAction() {
-        final String testCategory = "category1";
-        final String testAction = "action1";
-        Map<Pair<String, String>, Tile> cache = new ArrayMap<>();
-        List<ResolveInfo> info = new ArrayList<>();
-        info.add(newInfo(true, testCategory));
-        Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
-        List<UserHandle> userHandleList = new ArrayList<>();
-        userHandleList.add(UserHandle.CURRENT);
-        when(mUserManager.getUserProfiles()).thenReturn(userHandleList);
-
-        when(mPackageManager.queryIntentActivitiesAsUser(argThat(
-                event -> testAction.equals(event.getAction())), anyInt(), anyInt()))
-                .thenReturn(info);
-
-        List<DashboardCategory> categoryList = TileUtils.getCategories(
-                mContext, cache, false /* categoryDefinedInManifest */, testAction,
-                TileUtils.SETTING_PKG);
-        assertThat(categoryList.get(0).getTile(0).category).isEqualTo(testCategory);
-    }
-
-    @Test
-    public void getCategories_withPackageName() throws Exception {
+    public void getCategories_withPackageName() {
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         Map<Pair<String, String>, Tile> cache = new ArrayMap<>();
         Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
@@ -192,9 +161,7 @@
         userHandleList.add(new UserHandle(ActivityManager.getCurrentUser()));
         when(mUserManager.getUserProfiles()).thenReturn(userHandleList);
 
-        TileUtils.getCategories(
-                mContext, cache, false /* categoryDefinedInManifest */, null /* action */,
-                TileUtils.SETTING_PKG);
+        TileUtils.getCategories(mContext, cache);
         verify(mPackageManager, atLeastOnce()).queryIntentActivitiesAsUser(
                 intentCaptor.capture(), anyInt(), anyInt());
 
@@ -203,8 +170,7 @@
     }
 
     @Test
-    public void getTilesForIntent_shouldReadMetadataTitleAsString() throws RemoteException {
-        Intent intent = new Intent();
+    public void getTilesForIntent_shouldReadMetadataTitleAsString() {
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -212,20 +178,18 @@
                 URI_GET_SUMMARY, "my title", 0);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).title).isEqualTo("my title");
+        assertThat(outTiles.get(0).getTitle(mContext)).isEqualTo("my title");
     }
 
     @Test
-    public void getTilesForIntent_shouldReadMetadataTitleFromResource() throws RemoteException {
-        Intent intent = new Intent();
+    public void getTilesForIntent_shouldReadMetadataTitleFromResource() {
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -233,27 +197,24 @@
                 URI_GET_SUMMARY, null, 123);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
         when(mResources.getString(eq(123)))
                 .thenReturn("my localized title");
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
-
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
         assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).title).isEqualTo("my localized title");
+        assertThat(outTiles.get(0).getTitle(mContext)).isEqualTo("my localized title");
 
         // Icon should be tintable because the tile is not from settings package, and
         // "forceTintExternalIcon" is set
-        assertThat(outTiles.get(0).isIconTintable).isTrue();
+        assertThat(outTiles.get(0).isIconTintable(mContext)).isTrue();
     }
 
     @Test
     public void getTilesForIntent_shouldNotTintIconIfInSettingsPackage() {
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -263,20 +224,50 @@
         resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
-        assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).isIconTintable).isFalse();
+        assertThat(outTiles.get(0).isIconTintable(mContext)).isFalse();
     }
 
     @Test
+    public void getTilesForIntent_tileAlreadyInCache_shouldUpdateMetaData() {
+        final Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+        final List<Tile> outTiles = new ArrayList<>();
+        final List<ResolveInfo> info = new ArrayList<>();
+        final ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+                URI_GET_SUMMARY, null, 123);
+        resolveInfo.activityInfo.packageName = "com.android.settings";
+        resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
+        info.add(resolveInfo);
+
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+                .thenReturn(info);
+
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
+
+        assertThat(outTiles).hasSize(1);
+        final Bundle oldMetadata = outTiles.get(0).getMetaData();
+
+        resolveInfo.activityInfo.metaData = new Bundle(oldMetadata);
+        resolveInfo.activityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON,
+                R.drawable.ic_bt_cellphone);
+        outTiles.clear();
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
+
+        assertThat(outTiles).hasSize(1);
+        final Bundle newMetaData = outTiles.get(0).getMetaData();
+        assertThat(newMetaData).isNotSameAs(oldMetadata);
+    }
+
+
+    @Test
     public void getTilesForIntent_shouldMarkIconTintableIfMetadataSet() {
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -286,61 +277,17 @@
                 .putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, true);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, false /* forceTintExternalIcon */);
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
-        assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).isIconTintable).isTrue();
+        assertThat(outTiles.get(0).isIconTintable(mContext)).isTrue();
     }
 
     @Test
-    public void getTilesForIntent_shouldNotProcessInvalidUriContentSystemApp()
-            throws RemoteException {
-        Intent intent = new Intent();
-        Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
-        List<Tile> outTiles = new ArrayList<>();
-        List<ResolveInfo> info = new ArrayList<>();
-        ResolveInfo resolveInfo = newInfo(true, null /* category */, null, null, URI_GET_SUMMARY);
-        info.add(resolveInfo);
-
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
-                .thenReturn(info);
-
-        // Case 1: No provider associated with the uri specified.
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
-
-        assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).icon.getResId()).isEqualTo(314159);
-        assertThat(outTiles.get(0).summary).isEqualTo("static-summary");
-
-        // Case 2: Empty bundle.
-        Bundle bundle = new Bundle();
-        when(mIContentProvider.call(anyString(),
-                eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY),
-                any())).thenReturn(bundle);
-        when(mContentResolver.acquireUnstableProvider(anyString()))
-                .thenReturn(mIContentProvider);
-        when(mContentResolver.acquireUnstableProvider(any(Uri.class)))
-                .thenReturn(mIContentProvider);
-
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
-
-        assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).icon.getResId()).isEqualTo(314159);
-        assertThat(outTiles.get(0).summary).isEqualTo("static-summary");
-    }
-
-    @Test
-    public void getTilesForIntent_shouldProcessUriContentForSystemApp() throws RemoteException {
-        Intent intent = new Intent();
+    public void getTilesForIntent_shouldProcessUriContentForSystemApp() {
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -348,12 +295,11 @@
                 URI_GET_SUMMARY);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
     }
@@ -381,16 +327,16 @@
         info.activityInfo.name = "123";
         info.activityInfo.metaData = new Bundle();
         info.activityInfo.metaData.putString("com.android.settings.category", category);
-        info.activityInfo.metaData.putInt("com.android.settings.icon", 314159);
-        info.activityInfo.metaData.putString("com.android.settings.summary", "static-summary");
+        info.activityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, 314159);
+        info.activityInfo.metaData.putString(META_DATA_PREFERENCE_SUMMARY, "static-summary");
         if (keyHint != null) {
-            info.activityInfo.metaData.putString("com.android.settings.keyhint", keyHint);
+            info.activityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, keyHint);
         }
         if (iconUri != null) {
-            info.activityInfo.metaData.putString("com.android.settings.icon_uri", iconUri);
+            info.activityInfo.metaData.putString(META_DATA_PREFERENCE_ICON_URI, iconUri);
         }
         if (summaryUri != null) {
-            info.activityInfo.metaData.putString("com.android.settings.summary_uri", summaryUri);
+            info.activityInfo.metaData.putString(META_DATA_PREFERENCE_SUMMARY_URI, summaryUri);
         }
         if (titleResId != 0) {
             info.activityInfo.metaData.putInt(TileUtils.META_DATA_PREFERENCE_TITLE, titleResId);
@@ -403,29 +349,4 @@
         }
         return info;
     }
-
-    private void addMetadataToInfo(ResolveInfo info, String key, String value) {
-        if (!TextUtils.isEmpty(key)) {
-            if (info.activityInfo == null) {
-                info.activityInfo = new ActivityInfo();
-            }
-            if (info.activityInfo.metaData == null) {
-                info.activityInfo.metaData = new Bundle();
-            }
-            info.activityInfo.metaData.putString(key, value);
-        }
-    }
-
-    @Implements(RemoteViews.class)
-    public static class TileUtilsShadowRemoteViews {
-
-        private Integer overrideViewId;
-        private CharSequence overrideText;
-
-        @Implementation
-        public void setTextViewText(int viewId, CharSequence text) {
-            overrideViewId = viewId;
-            overrideText = text;
-        }
-    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index a23eebc..23087a9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -21,8 +21,10 @@
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -51,7 +53,8 @@
 
     @Mock
     private IDeviceIdleController mDeviceIdleService;
-
+    @Mock
+    private DevicePolicyManager mDevicePolicyManager;
     private PowerWhitelistBackend mPowerWhitelistBackend;
     private ShadowPackageManager mPackageManager;
     private Context mContext;
@@ -59,7 +62,8 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
+        mContext = spy(RuntimeEnvironment.application);
+        doReturn(mContext).when(mContext).getApplicationContext();
         doReturn(new String[] {}).when(mDeviceIdleService).getFullPowerWhitelist();
         doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelist();
         doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
@@ -67,6 +71,7 @@
         doNothing().when(mDeviceIdleService).removePowerSaveWhitelistApp(anyString());
         mPackageManager = Shadow.extract(mContext.getPackageManager());
         mPackageManager.setSystemFeature(PackageManager.FEATURE_TELEPHONY, true);
+        doReturn(mDevicePolicyManager).when(mContext).getSystemService(DevicePolicyManager.class);
 
         mPowerWhitelistBackend = new PowerWhitelistBackend(mContext, mDeviceIdleService);
     }
@@ -123,6 +128,13 @@
     }
 
     @Test
+    public void isWhitelisted_shouldWhitelistActiveDeviceAdminApp() {
+        doReturn(true).when(mDevicePolicyManager).packageHasActiveAdmins(PACKAGE_ONE);
+
+        assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
+    }
+
+    @Test
     public void testIsSystemWhitelisted() throws Exception {
         doReturn(new String[] {PACKAGE_ONE}).when(mDeviceIdleService).getSystemPowerWhitelist();
         mPowerWhitelistBackend.refreshList();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
new file mode 100644
index 0000000..fa64afe
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.inputmethod;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class InputMethodAndSubtypeUtilCompatTest {
+
+    private static final HashSet<String> EMPTY_STRING_SET = new HashSet<>();
+
+    private static HashSet<String> asHashSet(String... strings) {
+        HashSet<String> hashSet = new HashSet<>();
+        for (String s : strings) {
+            hashSet.add(s);
+        }
+        return hashSet;
+    }
+
+    @Test
+    public void parseInputMethodsAndSubtypesString_EmptyString() {
+        assertThat(InputMethodAndSubtypeUtilCompat.
+                parseInputMethodsAndSubtypesString("")).isEmpty();
+        assertThat(InputMethodAndSubtypeUtilCompat.
+                parseInputMethodsAndSubtypesString(null)).isEmpty();
+    }
+
+    @Test
+    public void parseInputMethodsAndSubtypesString_SingleImeNoSubtype() {
+        HashMap<String, HashSet<String>> r =
+                InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString("ime0");
+        assertThat(r).containsExactly("ime0", EMPTY_STRING_SET);
+    }
+
+    @Test
+    public void parseInputMethodsAndSubtypesString_MultipleImesNoSubtype() {
+        HashMap<String, HashSet<String>> r =
+                InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString("ime0:ime1");
+        assertThat(r).containsExactly("ime0", EMPTY_STRING_SET, "ime1", EMPTY_STRING_SET);
+    }
+
+    @Test
+    public void parseInputMethodsAndSubtypesString_SingleImeSingleSubtype() {
+        HashMap<String, HashSet<String>> r =
+                InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString("ime0;subtype0");
+        assertThat(r).containsExactly("ime0", asHashSet("subtype0"));
+    }
+
+    @Test
+    public void parseInputMethodsAndSubtypesString_SingleImeDuplicateSameSubtypes() {
+        HashMap<String, HashSet<String>> r =
+                InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+                        "ime0;subtype0;subtype0");
+        assertThat(r).containsExactly("ime0", asHashSet("subtype0"));
+    }
+
+    @Test
+    public void parseInputMethodsAndSubtypesString_SingleImeMultipleSubtypes() {
+        HashMap<String, HashSet<String>> r =
+                InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+                        "ime0;subtype0;subtype1");
+        assertThat(r).containsExactly("ime0", asHashSet("subtype0", "subtype1"));
+    }
+
+    @Test
+    public void parseInputMethodsAndSubtypesString_MultiplePairsOfImeSubtype() {
+        assertThat(InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+                "ime0;subtype0:ime1;subtype1"))
+                .containsExactly("ime0", asHashSet("subtype0"), "ime1", asHashSet("subtype1"));
+        assertThat(InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+                "ime0;subtype0;subtype1:ime1;subtype2"))
+                .containsExactly("ime0", asHashSet("subtype0", "subtype1"),
+                        "ime1", asHashSet("subtype2"));
+        assertThat(InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+                "ime0;subtype0;subtype1:ime1;subtype1;subtype2"))
+                .containsExactly("ime0", asHashSet("subtype0", "subtype1"),
+                        "ime1", asHashSet("subtype1", "subtype2"));
+
+    }
+
+    @Test
+    public void parseInputMethodsAndSubtypesString_MixedImeSubtypePairsAndImeNoSubtype() {
+        HashMap<String, HashSet<String>> r =
+                InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+                        "ime0;subtype0;subtype1:ime1;subtype1;subtype2:ime2");
+        assertThat(r).containsExactly("ime0", asHashSet("subtype0", "subtype1"),
+                "ime1", asHashSet("subtype1", "subtype2"),
+                "ime2", EMPTY_STRING_SET);
+    }
+
+    @Test
+    public void buildInputMethodsAndSubtypesString_EmptyInput() {
+        HashMap<String, HashSet<String>> map = new HashMap<>();
+        assertThat(map).isEmpty();
+    }
+
+    @Test
+    public void buildInputMethodsAndSubtypesString_SingleIme() {
+        HashMap<String, HashSet<String>> map = new HashMap<>();
+        map.put("ime0", new HashSet<>());
+        String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+        assertThat(result).isEqualTo("ime0");
+    }
+
+    @Test
+    public void buildInputMethodsAndSubtypesString_SingleImeSingleSubtype() {
+        HashMap<String, HashSet<String>> map = new HashMap<>();
+        map.put("ime0", asHashSet("subtype0"));
+        String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+        assertThat(result).isEqualTo("ime0;subtype0");
+    }
+
+    @Test
+    public void buildInputMethodsAndSubtypesString_SingleImeMultipleSubtypes() {
+        HashMap<String, HashSet<String>> map = new HashMap<>();
+        map.put("ime0", asHashSet("subtype0", "subtype1"));
+        String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+
+        // We do not expect what order will be used to concatenate items in
+        // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible
+        // permutations here.
+        assertThat(result).matches("ime0;subtype0;subtype1|ime0;subtype1;subtype0");
+    }
+
+    @Test
+    public void buildInputMethodsAndSubtypesString_MultipleImesNoSubtypes() {
+        HashMap<String, HashSet<String>> map = new HashMap<>();
+        map.put("ime0", EMPTY_STRING_SET);
+        map.put("ime1", EMPTY_STRING_SET);
+        String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+
+        // We do not expect what order will be used to concatenate items in
+        // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible
+        // permutations here.
+        assertThat(result).matches("ime0:ime1|ime1:ime0");
+    }
+
+    @Test
+    public void buildInputMethodsAndSubtypesString_MultipleImesWithAndWithoutSubtypes() {
+        HashMap<String, HashSet<String>> map = new HashMap<>();
+        map.put("ime0", asHashSet("subtype0", "subtype1"));
+        map.put("ime1", EMPTY_STRING_SET);
+        String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+
+        // We do not expect what order will be used to concatenate items in
+        // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible
+        // permutations here.
+        assertThat(result).matches("ime0;subtype0;subtype1:ime1|ime0;subtype1;subtype0:ime1"
+                + "|ime1:ime0;subtype0;subtype1|ime1:ime0;subtype1;subtype0");
+    }
+
+    @Test
+    public void buildInputMethodsAndSubtypesString_MultipleImesWithSubtypes() {
+        HashMap<String, HashSet<String>> map = new HashMap<>();
+        map.put("ime0", asHashSet("subtype0", "subtype1"));
+        map.put("ime1", asHashSet("subtype2", "subtype3"));
+        String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+
+        // We do not expect what order will be used to concatenate items in
+        // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible
+        // permutations here.
+        assertThat(result).matches("ime0;subtype0;subtype1:ime1;subtype2;subtype3"
+                + "|ime0;subtype1;subtype0:ime1;subtype2;subtype3"
+                + "|ime0;subtype0;subtype1:ime1;subtype3;subtype2"
+                + "|ime0;subtype1;subtype0:ime1;subtype3;subtype2"
+                + "|ime1;subtype2;subtype3:ime0;subtype0;subtype1"
+                + "|ime2;subtype3;subtype2:ime0;subtype0;subtype1"
+                + "|ime3;subtype2;subtype3:ime0;subtype1;subtype0"
+                + "|ime4;subtype3;subtype2:ime0;subtype1;subtype0");
+    }
+
+    @Test
+    public void isValidSystemNonAuxAsciiCapableIme() {
+        // System IME w/ no subtype
+        assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+                createDummyIme(true, false)))
+                .isFalse();
+
+        // System IME w/ non-Aux and non-ASCII-capable "keyboard" subtype
+        assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+                createDummyIme(true, false, createDummySubtype("keyboard", false, false))))
+                .isFalse();
+
+        // System IME w/ non-Aux and ASCII-capable "keyboard" subtype
+        assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+                createDummyIme(true, false, createDummySubtype("keyboard", false, true))))
+                .isTrue();
+
+        // System IME w/ Aux and ASCII-capable "keyboard" subtype
+        assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+                createDummyIme(true, true, createDummySubtype("keyboard", true, true))))
+                .isFalse();
+
+        // System IME w/ non-Aux and ASCII-capable "voice" subtype
+        assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+                createDummyIme(true, false, createDummySubtype("voice", false, true))))
+                .isFalse();
+
+        // System IME w/ non-Aux and non-ASCII-capable subtype + Non-Aux and ASCII-capable subtype
+        assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+                createDummyIme(true, false,
+                        createDummySubtype("keyboard", false, true),
+                        createDummySubtype("keyboard", false, false))))
+                .isTrue();
+
+        // Non-system IME w/ non-Aux and ASCII-capable "keyboard" subtype
+        assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+                createDummyIme(false, false, createDummySubtype("keyboard", false, true))))
+                .isFalse();
+    }
+
+    private static InputMethodInfo createDummyIme(boolean isSystem, boolean isAuxIme,
+            InputMethodSubtype... subtypes) {
+        final ResolveInfo ri = new ResolveInfo();
+        final ServiceInfo si = new ServiceInfo();
+        final ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = "com.example.android.dummyime";
+        ai.enabled = true;
+        ai.flags |= (isSystem ? ApplicationInfo.FLAG_SYSTEM : 0);
+        si.applicationInfo = ai;
+        si.enabled = true;
+        si.packageName = "com.example.android.dummyime";
+        si.name = "Dummy IME";
+        si.exported = true;
+        si.nonLocalizedLabel = "Dummy IME";
+        ri.serviceInfo = si;
+        return new InputMethodInfo(ri, isAuxIme, "", Arrays.asList(subtypes), 1, false);
+    }
+
+    private static InputMethodSubtype createDummySubtype(
+            String mode, boolean isAuxiliary, boolean isAsciiCapable) {
+        return new InputMethodSubtypeBuilder()
+                .setSubtypeNameResId(0)
+                .setSubtypeIconResId(0)
+                .setSubtypeLocale("en_US")
+                .setLanguageTag("en-US")
+                .setSubtypeMode(mode)
+                .setIsAuxiliary(isAuxiliary)
+                .setIsAsciiCapable(isAsciiCapable)
+                .build();
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java
index d0a0686..03ab261 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java
@@ -18,10 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
@@ -29,11 +25,16 @@
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class InputMethodAndSubtypeUtilTest {
 
     private static final HashSet<String> EMPTY_STRING_SET = new HashSet<>();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
new file mode 100644
index 0000000..12a4e69
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.license;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = LicenseHtmlLoaderCompatTest.ShadowLicenseHtmlLoaderCompat.class)
+public class LicenseHtmlLoaderCompatTest {
+
+    @Mock
+    private Context mContext;
+    private LicenseHtmlLoaderCompat mLoader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLoader = new LicenseHtmlLoaderCompat(mContext);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowLicenseHtmlLoaderCompat.reset();
+    }
+
+    @Test
+    public void testLoadInBackground() {
+        ArrayList<File> xmlFiles = new ArrayList();
+        xmlFiles.add(new File("test.xml"));
+        File cachedHtmlFile = new File("test.html");
+
+        setupFakeData(xmlFiles, cachedHtmlFile, true, true);
+
+        assertThat(mLoader.loadInBackground()).isEqualTo(cachedHtmlFile);
+    }
+
+    @Test
+    public void testLoadInBackgroundWithNoVaildXmlFiles() {
+        ArrayList<File> xmlFiles = new ArrayList();
+        File cachedHtmlFile = new File("test.html");
+
+        setupFakeData(xmlFiles, cachedHtmlFile, true, true);
+
+        assertThat(mLoader.loadInBackground()).isNull();
+    }
+
+    @Test
+    public void testLoadInBackgroundWithNonOutdatedCachedHtmlFile() {
+        ArrayList<File> xmlFiles = new ArrayList();
+        xmlFiles.add(new File("test.xml"));
+        File cachedHtmlFile = new File("test.html");
+
+        setupFakeData(xmlFiles, cachedHtmlFile, false, true);
+
+        assertThat(mLoader.loadInBackground()).isEqualTo(cachedHtmlFile);
+    }
+
+    @Test
+    public void testLoadInBackgroundWithGenerateHtmlFileFailed() {
+        ArrayList<File> xmlFiles = new ArrayList();
+        xmlFiles.add(new File("test.xml"));
+        File cachedHtmlFile = new File("test.html");
+
+        setupFakeData(xmlFiles, cachedHtmlFile, true, false);
+
+        assertThat(mLoader.loadInBackground()).isNull();
+    }
+
+    void setupFakeData(ArrayList<File> xmlFiles,
+            File cachedHtmlFile, boolean isCachedHtmlFileOutdated,
+            boolean generateHtmlFileSucceeded) {
+
+        ShadowLicenseHtmlLoaderCompat.sValidXmlFiles = xmlFiles;
+        ShadowLicenseHtmlLoaderCompat.sCachedHtmlFile = cachedHtmlFile;
+        ShadowLicenseHtmlLoaderCompat.sIsCachedHtmlFileOutdated = isCachedHtmlFileOutdated;
+        ShadowLicenseHtmlLoaderCompat.sGenerateHtmlFileSucceeded = generateHtmlFileSucceeded;
+    }
+
+    @Implements(LicenseHtmlLoaderCompat.class)
+    public static class ShadowLicenseHtmlLoaderCompat {
+
+
+        public static List<File> sValidXmlFiles;
+        public static File sCachedHtmlFile;
+        public static boolean sIsCachedHtmlFileOutdated;
+        public static boolean sGenerateHtmlFileSucceeded;
+
+        @Resetter
+        public static void reset() {
+            sValidXmlFiles = null;
+            sCachedHtmlFile = null;
+            sIsCachedHtmlFileOutdated = false;
+            sGenerateHtmlFileSucceeded = false;
+        }
+
+        @Implementation
+        static List<File> getVaildXmlFiles() {
+            return sValidXmlFiles;
+        }
+
+        @Implementation
+        static File getCachedHtmlFile(Context context) {
+            return sCachedHtmlFile;
+        }
+
+        @Implementation
+        static boolean isCachedHtmlFileOutdated(List<File> xmlFiles, File cachedHtmlFile) {
+            return sIsCachedHtmlFileOutdated;
+        }
+
+        @Implementation
+        static boolean generateHtmlFile(List<File> xmlFiles, File htmlFile) {
+            return sGenerateHtmlFileSucceeded;
+        }
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderTest.java
deleted file mode 100644
index 5095f50..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.license;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.io.File;
-import java.util.ArrayList;
-
-@RunWith(SettingsLibRobolectricTestRunner.class)
-public class LicenseHtmlLoaderTest {
-    @Mock
-    private Context mContext;
-
-    LicenseHtmlLoader newLicenseHtmlLoader(ArrayList<File> xmlFiles,
-            File cachedHtmlFile, boolean isCachedHtmlFileOutdated,
-            boolean generateHtmlFileSucceeded) {
-        LicenseHtmlLoader loader = spy(new LicenseHtmlLoader(mContext));
-        doReturn(xmlFiles).when(loader).getVaildXmlFiles();
-        doReturn(cachedHtmlFile).when(loader).getCachedHtmlFile();
-        doReturn(isCachedHtmlFileOutdated).when(loader).isCachedHtmlFileOutdated(any(), any());
-        doReturn(generateHtmlFileSucceeded).when(loader).generateHtmlFile(any(), any());
-        return loader;
-    }
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @Test
-    public void testLoadInBackground() {
-        ArrayList<File> xmlFiles = new ArrayList();
-        xmlFiles.add(new File("test.xml"));
-        File cachedHtmlFile = new File("test.html");
-
-        LicenseHtmlLoader loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, true, true);
-
-        assertThat(loader.loadInBackground()).isEqualTo(cachedHtmlFile);
-        verify(loader).generateHtmlFile(any(), any());
-    }
-
-    @Test
-    public void testLoadInBackgroundWithNoVaildXmlFiles() {
-        ArrayList<File> xmlFiles = new ArrayList();
-        File cachedHtmlFile = new File("test.html");
-
-        LicenseHtmlLoader loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, true, true);
-
-        assertThat(loader.loadInBackground()).isNull();
-        verify(loader, never()).generateHtmlFile(any(), any());
-    }
-
-    @Test
-    public void testLoadInBackgroundWithNonOutdatedCachedHtmlFile() {
-        ArrayList<File> xmlFiles = new ArrayList();
-        xmlFiles.add(new File("test.xml"));
-        File cachedHtmlFile = new File("test.html");
-
-        LicenseHtmlLoader loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, false, true);
-
-        assertThat(loader.loadInBackground()).isEqualTo(cachedHtmlFile);
-        verify(loader, never()).generateHtmlFile(any(), any());
-    }
-
-    @Test
-    public void testLoadInBackgroundWithGenerateHtmlFileFailed() {
-        ArrayList<File> xmlFiles = new ArrayList();
-        xmlFiles.add(new File("test.xml"));
-        File cachedHtmlFile = new File("test.html");
-
-        LicenseHtmlLoader loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, true, false);
-
-        assertThat(loader.loadInBackground()).isNull();
-        verify(loader).generateHtmlFile(any(), any());
-    }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/InjectedSettingTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/InjectedSettingTest.java
new file mode 100644
index 0000000..c29481f
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/InjectedSettingTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.location;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public final class InjectedSettingTest {
+
+    private static final String TEST_STRING = "test";
+
+    @Test
+    public void buildWithoutPackageName_ShouldReturnNull() {
+        assertThat(((new InjectedSetting.Builder())
+                .setClassName(TEST_STRING)
+                .setTitle(TEST_STRING)
+                .setSettingsActivity(TEST_STRING).build())).isNull();
+    }
+
+    private InjectedSetting getTestSetting() {
+        return new InjectedSetting.Builder()
+                .setPackageName(TEST_STRING)
+                .setClassName(TEST_STRING)
+                .setTitle(TEST_STRING)
+                .setSettingsActivity(TEST_STRING).build();
+    }
+
+    @Test
+    public void testEquals() {
+        InjectedSetting setting1 = getTestSetting();
+        InjectedSetting setting2 = getTestSetting();
+        assertThat(setting1).isEqualTo(setting2);
+    }
+
+    @Test
+    public void testHashCode() {
+        InjectedSetting setting = getTestSetting();
+        assertThat(setting.hashCode()).isEqualTo(1225314048);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
index 9b491c2..f47f41c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
@@ -26,7 +26,7 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
-import android.app.AlertDialog;
+import android.app.Activity;
 import android.app.Fragment;
 import android.app.NotificationManager;
 import android.content.Context;
@@ -40,6 +40,8 @@
 import android.view.View;
 import android.widget.Button;
 
+import androidx.appcompat.app.AlertDialog;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
 import org.junit.Before;
@@ -47,6 +49,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
@@ -58,6 +61,7 @@
     private Condition mCountdownCondition;
     private Condition mAlarmCondition;
     private ContentResolver mContentResolver;
+    private AlertDialog.Builder mBuilder;
 
     @Before
     public void setup() {
@@ -68,13 +72,14 @@
         mController = spy(new ZenDurationDialog(mContext));
         mController.mLayoutInflater = mLayoutInflater;
         mController.getContentView();
+        mBuilder = new AlertDialog.Builder(mContext);
     }
 
     @Test
     public void testAlwaysPrompt() {
-        Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
                 Settings.Global.ZEN_DURATION_PROMPT);
-        mController.createDialog();
+        mController.setupDialog(mBuilder);
 
         assertFalse(mController.getConditionTagAt(ZenDurationDialog.FOREVER_CONDITION_INDEX).rb
                 .isChecked());
@@ -86,9 +91,9 @@
 
     @Test
     public void testForever() {
-        Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
-                Settings.Global.ZEN_DURATION_FOREVER);
-        mController.createDialog();
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+                Settings.Secure.ZEN_DURATION_FOREVER);
+        mController.setupDialog(mBuilder);
 
         assertTrue(mController.getConditionTagAt(ZenDurationDialog.FOREVER_CONDITION_INDEX).rb
                 .isChecked());
@@ -100,8 +105,8 @@
 
     @Test
     public void testSpecificDuration() {
-        Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION, 45);
-        mController.createDialog();
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION, 45);
+        mController.setupDialog(mBuilder);
 
         assertFalse(mController.getConditionTagAt(ZenDurationDialog.FOREVER_CONDITION_INDEX).rb
                 .isChecked());
@@ -114,53 +119,53 @@
 
     @Test
     public void testChooseAlwaysPromptSetting() {
-        Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
-                Settings.Global.ZEN_DURATION_FOREVER);
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+                Settings.Secure.ZEN_DURATION_FOREVER);
 
-        AlertDialog dialog = (AlertDialog) mController.createDialog();
+        mController.setupDialog(mBuilder);
         mController.getConditionTagAt(ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX).rb.setChecked(
                 true);
-        mController.updateZenDuration(Settings.Global.ZEN_DURATION_FOREVER);
+        mController.updateZenDuration(Settings.Secure.ZEN_DURATION_FOREVER);
 
-        assertEquals(Settings.Global.ZEN_DURATION_PROMPT, Settings.Global.getInt(mContentResolver,
-                Settings.Global.ZEN_DURATION, Settings.Global.ZEN_DURATION_FOREVER));
+        assertEquals(Settings.Secure.ZEN_DURATION_PROMPT, Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.ZEN_DURATION, Settings.Secure.ZEN_DURATION_FOREVER));
     }
 
     @Test
     public void testChooseForeverSetting() {
-        Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
-                Settings.Global.ZEN_DURATION_PROMPT);
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+                Settings.Secure.ZEN_DURATION_PROMPT);
 
-        AlertDialog dialog = (AlertDialog) mController.createDialog();
+        mController.setupDialog(mBuilder);
         mController.getConditionTagAt(ZenDurationDialog.FOREVER_CONDITION_INDEX).rb.setChecked(
                 true);
-        mController.updateZenDuration(Settings.Global.ZEN_DURATION_PROMPT);
+        mController.updateZenDuration(Settings.Secure.ZEN_DURATION_PROMPT);
 
-        assertEquals(Settings.Global.ZEN_DURATION_FOREVER, Settings.Global.getInt(mContentResolver,
-                Settings.Global.ZEN_DURATION, Settings.Global.ZEN_DURATION_PROMPT));
+        assertEquals(Settings.Secure.ZEN_DURATION_FOREVER, Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.ZEN_DURATION, Settings.Secure.ZEN_DURATION_PROMPT));
     }
 
     @Test
     public void testChooseTimeSetting() {
-        Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
-                Settings.Global.ZEN_DURATION_PROMPT);
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+                Settings.Secure.ZEN_DURATION_PROMPT);
 
-        AlertDialog dialog = (AlertDialog) mController.createDialog();
+        mController.setupDialog(mBuilder);
         mController.getConditionTagAt(ZenDurationDialog.COUNTDOWN_CONDITION_INDEX).rb.setChecked(
                 true);
-        mController.updateZenDuration(Settings.Global.ZEN_DURATION_PROMPT);
+        mController.updateZenDuration(Settings.Secure.ZEN_DURATION_PROMPT);
 
         // countdown defaults to 60 minutes:
-        assertEquals(60, Settings.Global.getInt(mContentResolver,
-                Settings.Global.ZEN_DURATION, Settings.Global.ZEN_DURATION_PROMPT));
+        assertEquals(60, Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.ZEN_DURATION, Settings.Secure.ZEN_DURATION_PROMPT));
     }
 
     @Test
     public void testGetTimeFromBucket() {
-        Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
-                Settings.Global.ZEN_DURATION_PROMPT);
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+                Settings.Secure.ZEN_DURATION_PROMPT);
 
-        AlertDialog dialog = (AlertDialog) mController.createDialog();
+        mController.setupDialog(mBuilder);
         // click time button starts at 60 minutes
         // - 1 hour to MAX_BUCKET_MINUTES (12 hours), increments by 1 hour
         // - 0-60 minutes increments by 15 minutes
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
new file mode 100644
index 0000000..1ee3afa
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.loader.app.LoaderManager;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = ShadowSuggestionController.class)
+public class SuggestionControllerMixinCompatTest {
+
+    @Mock
+    private SuggestionControllerMixinCompat.SuggestionControllerHost mHost;
+
+    private Context mContext;
+    private LifecycleOwner mLifecycleOwner;
+    private Lifecycle mLifecycle;
+    private SuggestionControllerMixinCompat mMixin;
+    private ComponentName mComponentName;
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
+        mComponentName = new ComponentName(
+                "com.android.settings.intelligence",
+                "com.android.settings.intelligence.suggestions.SuggestionService");
+    }
+
+    @After
+    public void tearDown() {
+        ShadowSuggestionController.reset();
+    }
+
+    @Test
+    public void goThroughLifecycle_onStartStop_shouldStartStopController() {
+        mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+
+        mLifecycle.handleLifecycleEvent(ON_START);
+        assertThat(ShadowSuggestionController.sStartCalled).isTrue();
+
+        mLifecycle.handleLifecycleEvent(ON_STOP);
+        assertThat(ShadowSuggestionController.sStopCalled).isTrue();
+    }
+
+    @Test
+    public void onServiceConnected_shouldGetSuggestion() {
+        final LoaderManager loaderManager = mock(LoaderManager.class);
+        when(mHost.getLoaderManager()).thenReturn(loaderManager);
+
+        mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+        mMixin.onServiceConnected();
+
+        verify(loaderManager).restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
+                null /* args */, mMixin /* callback */);
+    }
+
+    @Test
+    public void onServiceConnected_hostNotAttached_shouldDoNothing() {
+        when(mHost.getLoaderManager()).thenReturn(null);
+
+        mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+        mMixin.onServiceConnected();
+
+        verify(mHost).getLoaderManager();
+    }
+
+    @Test
+    public void onServiceDisconnected_hostNotAttached_shouldDoNothing() {
+        when(mHost.getLoaderManager()).thenReturn(null);
+
+        mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+        mMixin.onServiceDisconnected();
+
+        verify(mHost).getLoaderManager();
+    }
+
+    @Test
+    public void doneLoadingg_shouldSetSuggestionLoaded() {
+        mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+
+        mMixin.onLoadFinished(mock(SuggestionLoaderCompat.class), null);
+
+        assertThat(mMixin.isSuggestionLoaded()).isTrue();
+
+        mMixin.onLoaderReset(mock(SuggestionLoaderCompat.class));
+
+        assertThat(mMixin.isSuggestionLoaded()).isFalse();
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java
new file mode 100644
index 0000000..8ba8606
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.testutils;
+
+import android.os.Bundle;
+import android.widget.LinearLayout;
+
+import org.robolectric.Robolectric;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+
+/**
+ * Utilities for creating Fragments for testing.
+ * <p>
+ * TODO(b/111195449) - Duplicated from org.robolectric.shadows.support.v4.SupportFragmentTestUtil
+ */
+@Deprecated
+public class FragmentTestUtils {
+
+    public static void startFragment(Fragment fragment) {
+        buildFragmentManager(FragmentUtilActivity.class)
+                .beginTransaction().add(fragment, null).commit();
+    }
+
+    public static void startFragment(Fragment fragment,
+            Class<? extends FragmentActivity> activityClass) {
+        buildFragmentManager(activityClass)
+                .beginTransaction().add(fragment, null).commit();
+    }
+
+    public static void startVisibleFragment(Fragment fragment) {
+        buildFragmentManager(FragmentUtilActivity.class)
+                .beginTransaction().add(1, fragment, null).commit();
+    }
+
+    public static void startVisibleFragment(Fragment fragment,
+            Class<? extends FragmentActivity> activityClass, int containerViewId) {
+        buildFragmentManager(activityClass)
+                .beginTransaction().add(containerViewId, fragment, null).commit();
+    }
+
+    private static FragmentManager buildFragmentManager(
+            Class<? extends FragmentActivity> activityClass) {
+        FragmentActivity activity = Robolectric.setupActivity(activityClass);
+        return activity.getSupportFragmentManager();
+    }
+
+    private static class FragmentUtilActivity extends FragmentActivity {
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            LinearLayout view = new LinearLayout(this);
+            view.setId(1);
+
+            setContentView(view);
+        }
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
new file mode 100644
index 0000000..9b8c230
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.testutils.shadow;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.List;
+
+@Implements(value = BluetoothAdapter.class, inheritImplementationMethods = true)
+public class ShadowBluetoothAdapter extends org.robolectric.shadows.ShadowBluetoothAdapter {
+
+    private List<Integer> mSupportedProfiles;
+    private BluetoothProfile.ServiceListener mServiceListener;
+
+    @Implementation
+    public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
+            int profile) {
+        mServiceListener = listener;
+        return true;
+    }
+
+    public BluetoothProfile.ServiceListener getServiceListener() {
+        return mServiceListener;
+    }
+
+    @Implementation
+    public List<Integer> getSupportedProfiles() {
+        return mSupportedProfiles;
+    }
+
+    public void setSupportedProfiles(List<Integer> supportedProfiles) {
+        mSupportedProfiles = supportedProfiles;
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/IconCacheTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/IconCacheTest.java
index 026ad47..645dfa1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/IconCacheTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/IconCacheTest.java
@@ -30,13 +30,14 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class IconCacheTest {
     private Icon mIcon;
     private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
index 83a9d5b..1e066b1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
@@ -17,14 +17,16 @@
 
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.fail;
 
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.shadows.ShadowLooper;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class ThreadUtilsTest {
 
     @Test
@@ -56,7 +58,7 @@
     }
 
     @Test
-    public void testPostOnMainThread_shouldRunOnMainTread() throws Exception {
+    public void testPostOnMainThread_shouldRunOnMainTread() {
         TestRunnable cr = new TestRunnable();
         ShadowLooper.pauseMainLooper();
         ThreadUtils.postOnMainThread(cr);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
index 36abd20..a00f12d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
@@ -22,13 +22,14 @@
 import android.graphics.drawable.AnimatedRotateDrawable;
 import android.view.View;
 
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingsLibRobolectricTestRunner.class)
 public class AnimatedImageViewTest {
     private AnimatedImageView mAnimatedImageView;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
new file mode 100644
index 0000000..1abbaba
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.shadows.ShadowApplication;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class FooterPreferenceMixinCompatTest {
+
+    @Mock
+    private PreferenceFragmentCompat mFragment;
+    @Mock
+    private PreferenceScreen mScreen;
+
+    private LifecycleOwner mLifecycleOwner;
+    private Lifecycle mLifecycle;
+    private FooterPreferenceMixinCompat mMixin;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
+        when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
+        when(mFragment.getPreferenceManager().getContext())
+                .thenReturn(ShadowApplication.getInstance().getApplicationContext());
+        mMixin = new FooterPreferenceMixinCompat(mFragment, mLifecycle);
+    }
+
+    @Test
+    public void createFooter_screenNotAvailable_noCrash() {
+        assertThat(mMixin.createFooterPreference()).isNotNull();
+    }
+
+    @Test
+    public void createFooter_screenAvailable_canAttachToScreen() {
+        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+
+        final FooterPreference preference = mMixin.createFooterPreference();
+
+        assertThat(preference).isNotNull();
+        verify(mScreen).addPreference(preference);
+    }
+
+    @Test
+    public void createFooter_screenAvailableDelayed_canAttachToScreen() {
+        final FooterPreference preference = mMixin.createFooterPreference();
+
+        mLifecycle.setPreferenceScreen(mScreen);
+
+        assertThat(preference).isNotNull();
+        verify(mScreen).addPreference(preference);
+    }
+
+    @Test
+    public void createFooterTwice_screenAvailable_replaceOldFooter() {
+        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+
+        mMixin.createFooterPreference();
+        mMixin.createFooterPreference();
+
+        verify(mScreen).removePreference(any(FooterPreference.class));
+        verify(mScreen, times(2)).addPreference(any(FooterPreference.class));
+    }
+
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
index 78b7616..8604d18 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
@@ -23,11 +23,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -38,6 +33,11 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.shadows.ShadowApplication;
 
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
 @RunWith(SettingsLibRobolectricTestRunner.class)
 public class FooterPreferenceMixinTest {
 
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index e1a602b..c53417b 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -217,4 +217,10 @@
 
     <!-- Default for Settings.System.VIBRATE_WHEN_RINGING -->
     <bool name="def_vibrate_when_ringing">false</bool>
+
+    <!-- Default for Settings.Secure.CHARGING_VIBRATION_ENABLED -->
+    <bool name="def_charging_vibration_enabled">true</bool>
+
+    <!-- Default for Settings.Secure.CHARGING_SOUNDS_ENABLED -->
+    <bool name="def_charging_sounds_enabled">true</bool>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 77eb6c4..c6ea480 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -186,9 +186,21 @@
                 GlobalSettingsProto.Auto.TIME_ZONE);
         p.end(autoToken);
 
+        final long autofillToken = p.start(GlobalSettingsProto.AUTOFILL);
         dumpSetting(s, p,
                 Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES,
-                GlobalSettingsProto.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES);
+                GlobalSettingsProto.Autofill.COMPAT_MODE_ALLOWED_PACKAGES);
+        dumpSetting(s, p,
+                Settings.Global.AUTOFILL_LOGGING_LEVEL,
+                GlobalSettingsProto.Autofill.LOGGING_LEVEL);
+        dumpSetting(s, p,
+                Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
+                GlobalSettingsProto.Autofill.MAX_PARTITIONS_SIZE);
+        dumpSetting(s, p,
+                Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
+                GlobalSettingsProto.Autofill.MAX_VISIBLE_DATASETS);
+        p.end(autofillToken);
+
         dumpSetting(s, p,
                 Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS,
                 GlobalSettingsProto.BACKUP_AGENT_TIMEOUT_PARAMETERS);
@@ -1170,9 +1182,6 @@
         dumpSetting(s, p,
                 Settings.Global.CHARGING_STARTED_SOUND,
                 GlobalSettingsProto.Sounds.CHARGING_STARTED);
-        dumpSetting(s, p,
-                Settings.Global.CHARGING_SOUNDS_ENABLED,
-                GlobalSettingsProto.Sounds.CHARGING_SOUNDS_ENABLED);
         p.end(soundsToken);
 
         final long soundTriggerToken = p.start(GlobalSettingsProto.SOUND_TRIGGER);
@@ -1466,12 +1475,6 @@
         dumpSetting(s, p,
                 Settings.Global.ZEN_MODE_CONFIG_ETAG,
                 GlobalSettingsProto.Zen.MODE_CONFIG_ETAG);
-        dumpSetting(s, p,
-                Settings.Global.ZEN_DURATION,
-                GlobalSettingsProto.Zen.DURATION);
-        dumpSetting(s, p,
-                Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION,
-                GlobalSettingsProto.Zen.SHOW_ZEN_UPGRADE_NOTIFICATION);
         p.end(zenToken);
 
         dumpSetting(s, p,
@@ -1788,13 +1791,13 @@
                 Settings.Secure.DOZE_ALWAYS_ON,
                 SecureSettingsProto.Doze.ALWAYS_ON);
         dumpSetting(s, p,
-                Settings.Secure.DOZE_PULSE_ON_PICK_UP,
+                Settings.Secure.DOZE_PICK_UP_GESTURE,
                 SecureSettingsProto.Doze.PULSE_ON_PICK_UP);
         dumpSetting(s, p,
                 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
                 SecureSettingsProto.Doze.PULSE_ON_LONG_PRESS);
         dumpSetting(s, p,
-                Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
+                Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
                 SecureSettingsProto.Doze.PULSE_ON_DOUBLE_TAP);
         p.end(dozeToken);
 
@@ -1972,6 +1975,9 @@
         dumpSetting(s, p,
                 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING,
                 SecureSettingsProto.Notification.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING);
+        dumpSetting(s, p,
+                Settings.Secure.IN_CALL_NOTIFICATION_ENABLED,
+                SecureSettingsProto.Notification.IN_CALL_NOTIFICATION_ENABLED);
         p.end(notificationToken);
 
         final long packageVerifierToken = p.start(SecureSettingsProto.PACKAGE_VERIFIER);
@@ -2134,6 +2140,16 @@
         dumpSetting(s, p,
                 Settings.Secure.SMS_DEFAULT_APPLICATION,
                 SecureSettingsProto.SMS_DEFAULT_APPLICATION);
+
+        final long soundsToken = p.start(SecureSettingsProto.SOUNDS);
+        dumpSetting(s, p,
+                Settings.Secure.CHARGING_SOUNDS_ENABLED,
+                SecureSettingsProto.Sounds.CHARGING_SOUNDS_ENABLED);
+        dumpSetting(s, p,
+                Settings.Secure.CHARGING_VIBRATION_ENABLED,
+                SecureSettingsProto.Sounds.CHARGING_VIBRATION_ENABLED);
+        p.end(soundsToken);
+
         dumpSetting(s, p,
                 Settings.Secure.SYNC_PARENT_SOUNDS,
                 SecureSettingsProto.SYNC_PARENT_SOUNDS);
@@ -2240,6 +2256,24 @@
                 SecureSettingsProto.Launcher.SWIPE_UP_TO_SWITCH_APPS_ENABLED);
         p.end(launcherToken);
 
+        final long zenToken = p.start(SecureSettingsProto.ZEN);
+        dumpSetting(s, p,
+                Settings.Secure.ZEN_DURATION,
+                SecureSettingsProto.Zen.DURATION);
+        dumpSetting(s, p,
+                Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION,
+                SecureSettingsProto.Zen.SHOW_ZEN_UPGRADE_NOTIFICATION);
+        dumpSetting(s, p,
+                Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION,
+                SecureSettingsProto.Zen.SHOW_ZEN_SETTINGS_SUGGESTION);
+        dumpSetting(s, p,
+                Settings.Secure.ZEN_SETTINGS_UPDATED,
+                SecureSettingsProto.Zen.SETTINGS_UPDATED);
+        dumpSetting(s, p,
+                Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED,
+                SecureSettingsProto.Zen.SETTINGS_SUGGESTION_VIEWED);
+        p.end(zenToken);
+
         // Please insert new settings using the same order as in SecureSettingsProto.
         p.end(token);
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 375fef8a..500199f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -816,7 +816,7 @@
             @Override
             public void onPackageRemoved(String packageName, int uid) {
                 synchronized (mLock) {
-                    mSettingsRegistry.onPackageRemovedLocked(packageName,
+                    mSettingsRegistry.removeSettingsForPackageLocked(packageName,
                             UserHandle.getUserId(uid));
                 }
             }
@@ -827,6 +827,14 @@
                     mSettingsRegistry.onUidRemovedLocked(uid);
                 }
             }
+
+            @Override
+            public void onPackageDataCleared(String packageName, int uid) {
+                synchronized (mLock) {
+                    mSettingsRegistry.removeSettingsForPackageLocked(packageName,
+                            UserHandle.getUserId(uid));
+                }
+            }
         };
 
         // package changes
@@ -2547,7 +2555,7 @@
             }
         }
 
-        public void onPackageRemovedLocked(String packageName, int userId) {
+        public void removeSettingsForPackageLocked(String packageName, int userId) {
             // Global and secure settings are signature protected. Apps signed
             // by the platform certificate are generally not uninstalled  and
             // the main exception is tests. We trust components signed
@@ -2556,7 +2564,7 @@
             final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
             SettingsState systemSettings = mSettingsStates.get(systemKey);
             if (systemSettings != null) {
-                systemSettings.onPackageRemovedLocked(packageName);
+                systemSettings.removeSettingsForPackageLocked(packageName);
             }
         }
 
@@ -2935,7 +2943,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 169;
+            private static final int SETTINGS_VERSION = 171;
 
             private final int mUserId;
 
@@ -3234,9 +3242,9 @@
                             getSettingLocked(Settings.Secure.DOZE_ENABLED).getValue());
 
                     if (dozeExplicitlyDisabled) {
-                        secureSettings.insertSettingLocked(Settings.Secure.DOZE_PULSE_ON_PICK_UP,
+                        secureSettings.insertSettingLocked(Settings.Secure.DOZE_PICK_UP_GESTURE,
                                 "0", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                        secureSettings.insertSettingLocked(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
+                        secureSettings.insertSettingLocked(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
                                 "0", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
                     }
                     currentVersion = 131;
@@ -3595,7 +3603,8 @@
                 }
 
                 if (currentVersion == 156) {
-                    // Version 157: Set a default value for zen duration
+                    // Version 157: Set a default value for zen duration,
+                    // in version 169, zen duration is moved to secure settings
                     final SettingsState globalSettings = getGlobalSettingsLocked();
                     final Setting currentSetting = globalSettings.getSettingLocked(
                             Global.ZEN_DURATION);
@@ -3731,32 +3740,8 @@
                 }
 
                 if (currentVersion == 165) {
-                    // Version 165: Show zen settings suggestion and zen updated
-                    final SettingsState settings = getGlobalSettingsLocked();
-                    final Setting currentSetting = settings.getSettingLocked(
-                            Global.SHOW_ZEN_SETTINGS_SUGGESTION);
-                    if (currentSetting.isNull()) {
-                        settings.insertSettingLocked(
-                                Global.SHOW_ZEN_SETTINGS_SUGGESTION, "1",
-                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
-
-                    final Setting currentUpdatedSetting = settings.getSettingLocked(
-                            Global.ZEN_SETTINGS_UPDATED);
-                    if (currentUpdatedSetting.isNull()) {
-                        settings.insertSettingLocked(
-                                Global.ZEN_SETTINGS_UPDATED, "0",
-                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
-
-                    final Setting currentSettingSuggestionViewed = settings.getSettingLocked(
-                            Global.ZEN_SETTINGS_SUGGESTION_VIEWED);
-                    if (currentSettingSuggestionViewed.isNull()) {
-                        settings.insertSettingLocked(
-                                Global.ZEN_SETTINGS_SUGGESTION_VIEWED, "0",
-                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
-
+                    // Version 165: MOVED: Show zen settings suggestion and zen updated settings
+                    // moved to secure settings and are set in version 169
                     currentVersion = 166;
                 }
 
@@ -3783,15 +3768,8 @@
                 }
 
                 if (currentVersion == 167) {
-                    // Version 167: by default, vibrate for wireless charging
-                    final SettingsState globalSettings = getGlobalSettingsLocked();
-                    final Setting currentSetting = globalSettings.getSettingLocked(
-                            Global.CHARGING_VIBRATION_ENABLED);
-                    if (currentSetting.isNull()) {
-                        globalSettings.insertSettingLocked(
-                                Global.CHARGING_VIBRATION_ENABLED, "1",
-                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
+                    // Version 167: MOVED - Settings.Global.CHARGING_VIBRATION_ENABLED moved to
+                    // Settings.Secure.CHARGING_VIBRATION_ENABLED, set in version 170
                     currentVersion = 168;
                 }
 
@@ -3810,6 +3788,113 @@
                     currentVersion = 169;
                 }
 
+                if (currentVersion == 169) {
+                    // Version 169: Set the default value for Secure Settings ZEN_DURATION,
+                    // SHOW_ZEN_SETTINGS_SUGGESTION, ZEN_SETTINGS_UPDATE and
+                    // ZEN_SETTINGS_SUGGESTION_VIEWED
+
+                    final SettingsState globalSettings = getGlobalSettingsLocked();
+                    final Setting globalZenDuration = globalSettings.getSettingLocked(
+                            Global.ZEN_DURATION);
+
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+                    final Setting secureZenDuration = secureSettings.getSettingLocked(
+                            Secure.ZEN_DURATION);
+
+                    // ZEN_DURATION
+                    if (!globalZenDuration.isNull()) {
+                        secureSettings.insertSettingLocked(
+                                Secure.ZEN_DURATION, globalZenDuration.getValue(), null, false,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+
+                        // set global zen duration setting to null since it's deprecated
+                        globalSettings.insertSettingLocked(
+                                Global.ZEN_DURATION, null, null, true,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+                    } else if (secureZenDuration.isNull()) {
+                        String defaultZenDuration = Integer.toString(getContext()
+                                .getResources().getInteger(R.integer.def_zen_duration));
+                        secureSettings.insertSettingLocked(
+                                Secure.ZEN_DURATION, defaultZenDuration, null, true,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    // SHOW_ZEN_SETTINGS_SUGGESTION
+                    final Setting currentShowZenSettingSuggestion = secureSettings.getSettingLocked(
+                            Secure.SHOW_ZEN_SETTINGS_SUGGESTION);
+                    if (currentShowZenSettingSuggestion.isNull()) {
+                        secureSettings.insertSettingLocked(
+                                Secure.SHOW_ZEN_SETTINGS_SUGGESTION, "1",
+                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    // ZEN_SETTINGS_UPDATED
+                    final Setting currentUpdatedSetting = secureSettings.getSettingLocked(
+                            Secure.ZEN_SETTINGS_UPDATED);
+                    if (currentUpdatedSetting.isNull()) {
+                        secureSettings.insertSettingLocked(
+                                Secure.ZEN_SETTINGS_UPDATED, "0",
+                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    // ZEN_SETTINGS_SUGGESTION_VIEWED
+                    final Setting currentSettingSuggestionViewed = secureSettings.getSettingLocked(
+                            Secure.ZEN_SETTINGS_SUGGESTION_VIEWED);
+                    if (currentSettingSuggestionViewed.isNull()) {
+                        secureSettings.insertSettingLocked(
+                                Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, "0",
+                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    currentVersion = 170;
+                }
+
+                if (currentVersion == 170) {
+                    // Version 170: Set the default value for Secure Settings:
+                    // CHARGING_SOUNDS_ENABLED and CHARGING_VIBRATION_ENABLED
+
+                    final SettingsState globalSettings = getGlobalSettingsLocked();
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+
+                    // CHARGING_SOUNDS_ENABLED
+                    final Setting globalChargingSoundEnabled = globalSettings.getSettingLocked(
+                            Global.CHARGING_SOUNDS_ENABLED);
+                    final Setting secureChargingSoundsEnabled = secureSettings.getSettingLocked(
+                            Secure.CHARGING_SOUNDS_ENABLED);
+
+                    if (!globalChargingSoundEnabled.isNull()) {
+                        secureSettings.insertSettingLocked(
+                                Secure.CHARGING_SOUNDS_ENABLED,
+                                globalChargingSoundEnabled.getValue(), null, false,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+
+                        // set global charging_sounds_enabled setting to null since it's deprecated
+                        globalSettings.insertSettingLocked(
+                                Global.CHARGING_SOUNDS_ENABLED, null, null, true,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+                    } else if (secureChargingSoundsEnabled.isNull()) {
+                        String defChargingSoundsEnabled = getContext().getResources()
+                                .getBoolean(R.bool.def_charging_sounds_enabled) ? "1" : "0";
+                        secureSettings.insertSettingLocked(
+                                Secure.CHARGING_SOUNDS_ENABLED, defChargingSoundsEnabled, null,
+                                true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    // CHARGING_VIBRATION_ENABLED
+                    final Setting secureChargingVibrationEnabled = secureSettings.getSettingLocked(
+                            Secure.CHARGING_VIBRATION_ENABLED);
+
+                    if (secureChargingVibrationEnabled.isNull()) {
+                        String defChargingVibrationEnabled = getContext().getResources()
+                                .getBoolean(R.bool.def_charging_vibration_enabled) ? "1" : "0";
+                        secureSettings.insertSettingLocked(
+                                Secure.CHARGING_VIBRATION_ENABLED, defChargingVibrationEnabled,
+                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    currentVersion = 171;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 449946d..e57483a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -293,7 +293,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
-    public void onPackageRemovedLocked(String packageName) {
+    public void removeSettingsForPackageLocked(String packageName) {
         boolean removedSomething = false;
 
         final int settingCount = mSettings.size();
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 8a5cb4a..da870bd 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -144,14 +144,13 @@
     <uses-permission android:name="android.permission.MANAGE_SENSORS" />
     <uses-permission android:name="android.permission.MANAGE_AUDIO_POLICY" />
     <uses-permission android:name="android.permission.MANAGE_CAMERA" />
-    <!-- Permission needed to enable/disable Bluetooth/Wifi when on permission review mode -->
-    <uses-permission
-        android:name="android.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED" />
-    <uses-permission
-        android:name="android.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED" />
+    <!-- Permission needed to enable/disable Bluetooth/Wifi -->
+    <uses-permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED" />
+    <uses-permission android:name="android.permission.MANAGE_WIFI_WHEN_WIRELESS_CONSENT_REQUIRED" />
     <uses-permission android:name="android.permission.WATCH_APPOPS" />
 
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+    <uses-permission android:name="android.permission.SUSPEND_APPS" />
 
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/res/values-hy/strings.xml b/packages/Shell/res/values-hy/strings.xml
index 3bc54b2..33f76f0 100644
--- a/packages/Shell/res/values-hy/strings.xml
+++ b/packages/Shell/res/values-hy/strings.xml
@@ -25,9 +25,9 @@
     <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="watch" msgid="1474435374470177193">"Հպեք՝ վրիպակի զեկույցն առանց սքրինշոթի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Հպեք՝ վրիպակի զեկույցն առանց սքրինշոթի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը"</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>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Այլևս ցույց չտալ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Վրիպակների հաշվետվություններ"</string>
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
new file mode 100644
index 0000000..0913503
--- /dev/null
+++ b/packages/SystemUI/Android.bp
@@ -0,0 +1,155 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+java_library {
+    name: "SystemUI-proto",
+
+    srcs: ["src/**/*.proto"],
+
+    proto: {
+        type: "nano",
+    },
+}
+
+java_library {
+    name: "SystemUI-tags",
+    srcs: ["src/com/android/systemui/EventLogTags.logtags"],
+}
+
+android_library {
+    name: "SystemUI-core",
+    srcs: [
+        "src/**/*.kt",
+        "src/**/*.java",
+        "src/**/I*.aidl",
+    ],
+    resource_dirs: [
+        "res-keyguard",
+        "res",
+    ],
+    static_libs: [
+        "SystemUIPluginLib",
+        "SystemUISharedLib",
+        "SettingsLib",
+        "androidx.car_car",
+        "androidx.legacy_legacy-support-v4",
+        "androidx.recyclerview_recyclerview",
+        "androidx.preference_preference",
+        "androidx.appcompat_appcompat",
+        "androidx.mediarouter_mediarouter",
+        "androidx.palette_palette",
+        "androidx.legacy_legacy-preference-v14",
+        "androidx.leanback_leanback",
+        "androidx.slice_slice-core",
+        "androidx.slice_slice-view",
+        "androidx.slice_slice-builders",
+        "androidx.arch.core_core-runtime",
+        "androidx.lifecycle_lifecycle-extensions",
+        "SystemUI-tags",
+        "SystemUI-proto",
+    ],
+    manifest: "AndroidManifest.xml",
+
+    libs: [
+        "telephony-common",
+        "android.car",
+    ],
+
+    aaptflags: [
+        "--extra-packages",
+        "com.android.keyguard",
+    ],
+}
+
+android_library {
+    name: "SystemUI-tests",
+    manifest: "tests/AndroidManifest.xml",
+    resource_dirs: [
+        "tests/res",
+        "res-keyguard",
+        "res",
+    ],
+    srcs: [
+        "tests/src/**/*.kt",
+        "tests/src/**/*.java",
+        "src/**/*.kt",
+        "src/**/*.java",
+        "src/**/I*.aidl",
+    ],
+    static_libs: [
+        "SystemUIPluginLib",
+        "SystemUISharedLib",
+        "SettingsLib",
+        "androidx.car_car",
+        "androidx.legacy_legacy-support-v4",
+        "androidx.recyclerview_recyclerview",
+        "androidx.preference_preference",
+        "androidx.appcompat_appcompat",
+        "androidx.mediarouter_mediarouter",
+        "androidx.palette_palette",
+        "androidx.legacy_legacy-preference-v14",
+        "androidx.leanback_leanback",
+        "androidx.slice_slice-core",
+        "androidx.slice_slice-view",
+        "androidx.slice_slice-builders",
+        "androidx.arch.core_core-runtime",
+        "androidx.lifecycle_lifecycle-extensions",
+        "SystemUI-tags",
+        "SystemUI-proto",
+        "metrics-helper-lib",
+        "android-support-test",
+        "mockito-target-inline-minus-junit4",
+        "testables",
+        "truth-prebuilt",
+    ],
+    libs: [
+        "android.test.runner",
+        "telephony-common",
+        "android.car",
+        "android.test.base",
+    ],
+    aaptflags: [
+        "--extra-packages",
+        "com.android.keyguard:com.android.systemui",
+    ],
+}
+
+android_app {
+    name: "SystemUI",
+    static_libs: [
+        "SystemUI-core",
+    ],
+
+    platform_apis: true,
+    certificate: "platform",
+    privileged: true,
+
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
+
+    libs: [
+        "telephony-common",
+        "android.car",
+    ],
+
+    dxflags: ["--multi-dex"],
+    aaptflags: [
+        "--extra-packages",
+        "com.android.keyguard",
+    ],
+
+}
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
deleted file mode 100644
index d9ec0fd0..0000000
--- a/packages/SystemUI/Android.mk
+++ /dev/null
@@ -1,83 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := SystemUI-proto
-
-LOCAL_SRC_FILES := $(call all-proto-files-under,src)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := SystemUI-tags
-
-LOCAL_SRC_FILES := src/com/android/systemui/EventLogTags.logtags
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# ------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_MODULE_TAGS := optional
-
-RELATIVE_FINGERPRINT_PATH := ../../core/java/android/hardware/fingerprint
-
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src) \
-    $(call all-Iaidl-files-under, src) \
-    $(call all-Iaidl-files-under, $(RELATIVE_FINGERPRINT_PATH))
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    SystemUIPluginLib \
-    SystemUISharedLib \
-    androidx.car_car \
-    androidx.legacy_legacy-support-v4 \
-    androidx.recyclerview_recyclerview \
-    androidx.preference_preference \
-    androidx.appcompat_appcompat \
-    androidx.mediarouter_mediarouter \
-    androidx.palette_palette \
-    androidx.legacy_legacy-preference-v14 \
-    androidx.leanback_leanback \
-    androidx.slice_slice-core \
-    androidx.slice_slice-view \
-    androidx.slice_slice-builders \
-    androidx.arch.core_core-runtime \
-    androidx.lifecycle_lifecycle-extensions \
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    SystemUI-tags \
-    SystemUI-proto
-
-LOCAL_JAVA_LIBRARIES := telephony-common \
-    android.car
-
-LOCAL_PACKAGE_NAME := SystemUI
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res-keyguard $(LOCAL_PATH)/res
-
-ifneq ($(INCREMENTAL_BUILDS),)
-    LOCAL_PROGUARD_ENABLED := disabled
-    LOCAL_JACK_ENABLED := incremental
-    LOCAL_DX_FLAGS := --multi-dex
-    LOCAL_JACK_FLAGS := --multi-dex native
-endif
-
-include frameworks/base/packages/SettingsLib/common.mk
-
-LOCAL_AAPT_FLAGS := --extra-packages com.android.keyguard
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index eab4b97..a5616d5 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -339,19 +339,17 @@
             android:exported="false">
         </activity>
 
-        <!-- Springboard for launching the share activity -->
-        <receiver android:name=".screenshot.GlobalScreenshot$ScreenshotActionReceiver"
-            android:process=":screenshot"
+        <!-- Springboard for launching the share and edit activity. This needs to be in the main
+             system ui process since we need to notify the status bar to dismiss the keyguard -->
+        <receiver android:name=".screenshot.GlobalScreenshot$ActionProxyReceiver"
             android:exported="false" />
 
         <!-- Callback for dismissing screenshot notification after a share target is picked -->
         <receiver android:name=".screenshot.GlobalScreenshot$TargetChosenReceiver"
-            android:process=":screenshot"
             android:exported="false" />
 
         <!-- Callback for deleting screenshot notification -->
         <receiver android:name=".screenshot.GlobalScreenshot$DeleteScreenshotReceiver"
-            android:process=":screenshot"
             android:exported="false" />
 
         <!-- started from UsbDeviceSettingsManager -->
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index d80e4ff..33c5551 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -162,7 +162,7 @@
 
 Draws decorations about the screen in software (e.g. rounded corners, cutouts).
 
-### [com.android.systemui.fingerprint.FingerprintDialogImpl](/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java)
+### [com.android.systemui.biometrics.BiometricDialogImpl](/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java)
 
 Fingerprint UI.
 
diff --git a/packages/SystemUI/docs/kotlin-in-sysui.md b/packages/SystemUI/docs/kotlin-in-sysui.md
new file mode 100644
index 0000000..1bf24f6
--- /dev/null
+++ b/packages/SystemUI/docs/kotlin-in-sysui.md
@@ -0,0 +1,22 @@
+# Kotlin in SystemUI
+
+Queue "it's happening" gif.
+
+Kotlin is probably going to be a bit of a wild west for a while, but please
+try to follow these guidelines as much as possible.
+
+ - No semi-colons: they are optional, we probably don't want them in the
+   future, so let's just not add them.
+ - No DSLs: sysui is complicated enough as is, let's not add more layers at
+   the moment.
+ - Only use extension functions for keeping complex code locality: Don't use
+   extension functions to add methods to android classes that you always wished
+   were there, instead add them directly to the class and save us the extension.
+ - inline, reified, and de-compisition can all be great things: just make sure
+   you know what they do and why you are using them.
+
+# Recommended reading
+
+ - [Kotlin](https://kotlinlang.org/)
+ - [AndroidX-KTX](https://www.youtube.com/watch?v=st1XVfkDWqk)
+ - [Performance and Kotlin tricks](https://www.youtube.com/watch?v=6P20npkvcb8)
diff --git a/packages/SystemUI/docs/plugin_hooks.md b/packages/SystemUI/docs/plugin_hooks.md
index 5b08bfc..9fe2e18 100644
--- a/packages/SystemUI/docs/plugin_hooks.md
+++ b/packages/SystemUI/docs/plugin_hooks.md
@@ -51,6 +51,10 @@
 
 Use: Control over swipes/input for notification views, can be used to control what happens when you swipe/long-press
 
+### Action: com.android.systemui.action.PLUGIN_CLOCK
+Expected interface: [ClockPlugin](/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java)
+
+Use: Allows replacement of the keyguard main clock.
 
 # Global plugin dependencies
 These classes can be accessed by any plugin using PluginDependency as long as they @Requires them.
diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp
new file mode 100644
index 0000000..b38059d
--- /dev/null
+++ b/packages/SystemUI/plugin/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+
+java_library {
+
+    name: "SystemUIPluginLib",
+
+    srcs: ["src/**/*.java"],
+
+
+}
+
+android_app {
+
+    // Dummy to generate .toc files.
+    name: "PluginDummyLib",
+    platform_apis: true,
+    srcs: ["src/**/*.java"],
+
+    libs: ["SystemUIPluginLib"],
+
+    optimize: {
+        enabled: false,
+    },
+
+}
diff --git a/packages/SystemUI/plugin/Android.mk b/packages/SystemUI/plugin/Android.mk
deleted file mode 100644
index 8634684..0000000
--- a/packages/SystemUI/plugin/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE := SystemUIPluginLib
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_JAR_EXCLUDE_FILES := none
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-# Dummy to generate .toc files.
-LOCAL_PACKAGE_NAME := PluginDummyLib
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := SystemUIPluginLib
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/packages/SystemUI/plugin/ExamplePlugin/Android.bp b/packages/SystemUI/plugin/ExamplePlugin/Android.bp
new file mode 100644
index 0000000..a0eaf14
--- /dev/null
+++ b/packages/SystemUI/plugin/ExamplePlugin/Android.bp
@@ -0,0 +1,14 @@
+android_app {
+
+    name: "ExamplePlugin",
+
+    libs: ["SystemUIPluginLib"],
+
+    certificate: "platform",
+    optimize: {
+        enabled: false,
+    },
+
+    srcs: ["src/**/*.java"],
+
+}
diff --git a/packages/SystemUI/plugin/ExamplePlugin/Android.mk b/packages/SystemUI/plugin/ExamplePlugin/Android.mk
deleted file mode 100644
index 4c82c75..0000000
--- a/packages/SystemUI/plugin/ExamplePlugin/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PACKAGE_NAME := ExamplePlugin
-
-LOCAL_JAVA_LIBRARIES := SystemUIPluginLib
-
-LOCAL_CERTIFICATE := platform
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-include $(BUILD_PACKAGE)
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
new file mode 100644
index 0000000..b4fc820
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package com.android.systemui.plugins;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+import android.graphics.Paint.Style;
+import android.view.View;
+
+/**
+ * This plugin is used to replace main clock in keyguard.
+ */
+@ProvidesInterface(action = ClockPlugin.ACTION, version = ClockPlugin.VERSION)
+public interface ClockPlugin extends Plugin {
+
+    String ACTION = "com.android.systemui.action.PLUGIN_CLOCK";
+    int VERSION = 1;
+
+    /**
+     * Get clock view.
+     * @return clock view from plugin.
+     */
+    View getView();
+
+    /**
+     * Set clock paint style.
+     * @param style The new style to set in the paint.
+     */
+    void setStyle(Style style);
+
+    /**
+     * Set clock text color.
+     * @param color A color value.
+     */
+    void setTextColor(int color);
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index 61f7fe8..bf4374a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -43,7 +43,7 @@
     boolean isAvailable();
     void setTileSpec(String tileSpec);
 
-    void clearState();
+    @Deprecated default void clearState() {}
     void refreshState();
 
     void addCallback(Callback callback);
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index e6452e7..fa4c8b5 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -39,6 +39,6 @@
 -keep class ** extends androidx.preference.PreferenceFragment
 -keep class com.android.systemui.tuner.*
 -keep class com.android.systemui.plugins.** {
-    public protected *;
+    *;
 }
 -keep class androidx.core.app.CoreComponentFactory
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
new file mode 100644
index 0000000..89b873e
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is a view that shows clock information in Keyguard. -->
+<com.android.keyguard.KeyguardClockSwitch
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_horizontal"
+    android:layout_alignParentTop="true">
+    <TextClock
+        android:id="@+id/default_clock_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:letterSpacing="0.03"
+        android:textColor="?attr/wallpaperTextColor"
+        android:singleLine="true"
+        style="@style/widget_big_thin"
+        android:format12Hour="@string/keyguard_widget_12_hours_format"
+        android:format24Hour="@string/keyguard_widget_24_hours_format" />
+</com.android.keyguard.KeyguardClockSwitch>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
index 87983b9..a795442 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
@@ -38,19 +38,10 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal|top">
-                <TextClock
-                    android:id="@+id/clock_view"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center_horizontal"
-                    android:layout_centerHorizontal="true"
-                    android:layout_alignParentTop="true"
-                    android:letterSpacing="0.03"
-                    android:textColor="?attr/wallpaperTextColor"
-                    android:singleLine="true"
-                    style="@style/widget_big_thin"
-                    android:format12Hour="@string/keyguard_widget_12_hours_format"
-                    android:format24Hour="@string/keyguard_widget_24_hours_format" />
+                <include layout="@layout/keyguard_clock_switch"
+                         android:id="@+id/clock_view"
+                         android:layout_width="match_parent"
+                         android:layout_height="wrap_content" />
                 <View
                     android:id="@+id/clock_separator"
                     android:layout_width="@dimen/widget_separator_width"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index ba05ccf..4ae2d41 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -55,19 +55,10 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal|top">
-            <TextClock
-                android:id="@+id/clock_view"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:layout_centerHorizontal="true"
-                android:layout_alignParentTop="true"
-                android:letterSpacing="0.03"
-                android:textColor="?attr/wallpaperTextColor"
-                android:singleLine="true"
-                style="@style/widget_big_thin"
-                android:format12Hour="@string/keyguard_widget_12_hours_format"
-                android:format24Hour="@string/keyguard_widget_24_hours_format" />
+            <include layout="@layout/keyguard_clock_switch"
+                 android:id="@+id/clock_view"
+                 android:layout_width="match_parent"
+                 android:layout_height="wrap_content" />
             <View
                 android:id="@+id/clock_separator"
                 android:layout_width="@dimen/widget_separator_width"
diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index f43d57a..4e2937a 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Voer wagwoord in om te ontsluit"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Tik PIN in om te ontsluit"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Voer jou PIN in"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Voer jou patroon in"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Voer jou wagwoord in"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Voer jou patroon in"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Voer jou wagwoord in"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Verkeerde PIN-kode."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ongeldige kaart."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Gelaai"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Volgelaai"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Die e-SIM kan weens \'n fout nie gedeaktiveer word nie."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Het jy die patroon vergeet?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Verkeerde patroon"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Verkeerde wagwoord"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Verkeerde patroon"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Verkeerde wagwoord"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Verkeerde PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Probeer oor <xliff:g id="NUMBER">%d</xliff:g> sekondes weer.</item>
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index 11e099a..c892ac3 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"ለመክፈት የይለፍ ቃል ይተይቡ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"ለመክፈት ፒን ይተይቡ"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"የእርስዎን ፒን ያስገቡ"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"ስርዓተ-ጥለትዎን ያስገቡ"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"ይለፍ ቃልዎን ያስገቡ"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"ሥርዓተ-ጥለትዎን ያስገቡ"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ይለፍ ቃልዎን ያስገቡ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ትክክል ያልሆነ ፒን  ኮድ።"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ልክ ያልሆነ ካርድ።"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"ባትሪ ሞልቷል"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"ሙሉ በሙሉ ኃይል ተሞልቷል"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"በአንድ ስህተት ምክንያት eSIM ሊሰናከል አልቻለም።"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"አስገባ"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ስርዓተ ጥለቱን እርሳ"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"የተሳሳተ ስርዓተ ጥለት"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"የተሳሳተ ይለፍ ቃል"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"የተሳሳተ ሥርዓተ ጥለት"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"የተሳሳተ የይለፍ ቃል"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"የተሳሳተ ፒን"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">በ<xliff:g id="NUMBER">%d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።</item>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 1117730..af958e5 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"اكتب كلمة المرور لإلغاء التأمين"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"اكتب رمز رقم التعريف الشخصي لإلغاء التأمين"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"‏أدخل رقم التعريف الشخصي (PIN)"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"أدخل النقش"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"أدخل كلمة المرور"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"أدخل النقش"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"أدخل كلمة المرور"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"رمز رقم التعريف الشخصي غير صحيح."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"بطاقة غير صالحة."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"تم الشحن"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"تم شحن البطارية بالكامل"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"‏يتعذّر إيقاف eSIM بسبب خطأ."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"نسيت النقش"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"نقش خاطئ"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"كلمة مرور خاطئة"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"نقش غير صحيح"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"كلمة مرور غير صحيحة"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"رقم تعريف شخصي خاطئ"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="zero">حاول مرة أخرى خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية.</item>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index 50dd855..89c468d 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"আনলক কৰিবলৈ পাছৱৰ্ড লিখক"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"আনলক কৰিবলৈ পিন লিখক"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"আপোনাৰ পিন দিয়ক"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"আপোনাৰ আৰ্হি দিয়ক"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"আপোনাৰ পাছৱৰ্ড দিয়ক"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"আপোনাৰ আৰ্হি দিয়ক"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"আপোনাৰ পাছৱর্ড দিয়ক"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ভুল পিন ক\'ড।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ব্যৱহাৰৰ অযোগ্য ছিম কাৰ্ড"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"চ্চার্জ কৰা হ\'ল"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"পূৰ্ণৰূপে চ্চাৰ্জ হৈছে"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চ্চার্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"এটা আসোঁৱাহৰ কাৰণে ই-ছিম অক্ষম কৰিব পৰা নাযায়।"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"এণ্টাৰ বুটাম"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"আৰ্হি পাহৰিলে নেকি"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ভুল আৰ্হি"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"ভুল পাছৱৰ্ড"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"ভুল আৰ্হি"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"ভুল পাছৱৰ্ড"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"ভুল পিন"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> ছেকেণ্ডত আকৌ চেষ্টা কৰক।</item>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index 19a0963..1867186 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Kilidi açmaq üçün parol daxil edin"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Kilidi açmaq üçün PIN daxil edin"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"PIN kodu daxil edin"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Modeli daxil edin"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Parol daxil edin"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Modeli daxil edin"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Şifrənizi daxil edin"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Yanlış PIN kod."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Yanlış Kart."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Enerji yığdı"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Tam dolub"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerji yığır"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM xəta səbəbi ilə deaktiv edilmədi."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Daxil edin"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Modeli unutmuşam"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Yanlış Model"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Yanlış Parol"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Yanlış model"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Yanlış parol"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Yanlış PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> saniyə ərzində yenidən cəhd edin.</item>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index 1e8e443..ef0e1ce 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Unesite lozinku da biste otključali"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Unesite PIN za otključavanje"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Unesite PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Unesite šablon"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Unesite lozinku"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Unesite šablon"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Unesite lozinku"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kôd je netačan."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nevažeća kartica."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Napunjena je"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Napunjena je u potpunosti"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Puni se"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM ne može da se onemogući zbog greške."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Zaboravio/la sam šablon"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Pogrešan šablon"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Pogrešna lozinka"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Pogrešan šablon"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Pogrešna lozinka"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Pogrešan PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekundu.</item>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index 8251071..873a87b 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Увядзіце пароль для разблакіравання"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Каб разблакіраваць, увядзіце PIN-код"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Увядзіце PIN-код"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Увядзіце ўзор разблакіроўкі"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Увядзіце пароль"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Увядзіце ўзор разблакіроўкі"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Увядзіце пароль"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Няправільны PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Несапраўдная картка."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Зараджаны"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Акумулятар поўнасцю зараджаны"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Немагчыма адключыць eSIM-карту з-за памылкі."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Увесці"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Забыў(-ла) узор"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Няправільны ўзор"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Няправільны пароль"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Няправільны ўзор разблакіроўкі"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Няправільны пароль"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Няправільны PIN-код"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Паўтарыце спробу праз <xliff:g id="NUMBER">%d</xliff:g> секунду.</item>
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index 7438d7f..3725a5e 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Въведете парола, за да отключите"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Въведете ПИН кода, за да отключите"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Въведете ПИН кода си"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Въведете фигурата си"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Въведете паролата си"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Въведете фигурата си"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Въведете паролата си"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Неправилен ПИН код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Картата е невалидна."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Заредена"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Напълно заредено"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Електронната SIM карта не може да бъде деактивирана поради грешка."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"„Enter“"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Забравена фигура"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Грешна фигура"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Грешна парола"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Грешна фигура"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Грешна парола"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Грешен ПИН код"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Опитайте отново след <xliff:g id="NUMBER">%d</xliff:g> секунди.</item>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index 814aafe..ff925f8 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"আনলক করতে পাসওয়ার্ড লিখুন"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"আনলক করতে পিন লিখুন"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"পিন লিখুন"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"প্যাটার্ন আঁকুন"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"পাসওয়ার্ড লিখুন"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"প্যাটার্ন আঁকুন"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"পাসওয়ার্ড লিখুন"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ভুল পিন কোড দেওয়া হয়েছে।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ভুল কার্ড।"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"চার্জ হয়েছে"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"সম্পূর্ণ চার্জ আছে"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"একটি সমস্যার কারণে ই-সিমটি বন্ধ করা যাচ্ছে না।"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"এন্টার"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"প্যাটার্ন ভুলে গেছি"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ভুল প্যাটার্ন"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"ভুল পাসওয়ার্ড"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"ভুল প্যাটার্ন"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"ভুল পাসওয়ার্ড"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"ভুল পিন"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।</item>
@@ -140,10 +140,8 @@
       <item quantity="one">ডিভাইসটি <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধরে আনলক করা হয় নি। পাসওয়ার্ড নিশ্চিত করুন।</item>
       <item quantity="other">ডিভাইসটি <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধরে আনলক করা হয় নি। পাসওয়ার্ড নিশ্চিত করুন।</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"শনাক্ত করা যায়নি"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"শনাক্ত করা যায়নি"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="one">সিমের পিন লিখুন। আপনি আর <xliff:g id="NUMBER_1">%d</xliff:g> বার চেষ্টা করতে পারবেন।</item>
       <item quantity="other">সিমের পিন লিখুন। আপনি আর <xliff:g id="NUMBER_1">%d</xliff:g> বার চেষ্টা করতে পারবেন।</item>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index a87b72a..9984061 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Upišite lozinku za otključavanje"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Upišite PIN za otključavanje"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Unesite svoj PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Unesite svoj uzorak"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Unesite svoju lozinku"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Unesite uzorak"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Unesite lozinku"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Pogrešan PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nevažeća kartica."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Napunjeno"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Potpuno napunjen"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM nije moguće onemogućiti zbog greške."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Zaboravili ste uzorak?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Pogrešan uzorak"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Pogrešna lozinka"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Pogrešan uzorak"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Pogrešna lozinka"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Pogrešan PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekundu.</item>
@@ -146,8 +146,8 @@
       <item quantity="few">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite lozinku.</item>
       <item quantity="other">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite lozinku.</item>
     </plurals>
-    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"Nije prepoznat"</string>
-    <string name="kg_face_not_recognized" msgid="6382535088345875294">"Nije prepoznat"</string>
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"Nije prepoznato"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"Nije prepoznato"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="one">Unesite PIN za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj.</item>
       <item quantity="few">Unesite PIN za SIM. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 093bd1c..3a734b1 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Escriu la contrasenya per desbloquejar"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Escriu el PIN per desbloquejar"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Introdueix el PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Introdueix el patró"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Introdueix la contrasenya"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Introdueix el patró"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introdueix la contrasenya"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"El codi PIN no és correcte."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"La targeta no és vàlida."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Bateria carregada"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Completament carregada"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"S\'ha produït un error i no es pot desactivar l\'eSIM."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Retorn"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"He oblidat el patró"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"El patró no és correcte"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"La contrasenya no és correcta"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Patró incorrecte"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Contrasenya incorrecta"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"El PIN no és correcte"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Torna-ho a provar d\'aquí a <xliff:g id="NUMBER">%d</xliff:g> segons.</item>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index 2142c9c..1bfc294 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Zadejte heslo pro odemknutí"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Zadejte kód PIN pro odemknutí"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Zadejte PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Zadejte gesto"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Zadejte heslo"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Zadejte gesto"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Zadejte heslo"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Nesprávný kód PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Neplatná karta."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Nabito"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Plně nabito"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM kartu kvůli chybě nelze deaktivovat."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Zapomenuté gesto"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Nesprávné gesto"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Nesprávné heslo"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Nesprávné gesto"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Špatné heslo"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Nesprávný kód PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="few">Zkuste to znovu za <xliff:g id="NUMBER">%d</xliff:g> sekundy.</item>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index df4ab21..b3b9732 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Angiv adgangskoden for at låse op"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Angiv pinkoden for at låse op"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Angiv din pinkode"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Angiv dit mønster"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Angiv din adgangskode"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Angiv dit mønster"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Angiv din adgangskode"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Forkert pinkode."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ugyldigt kort."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Opladet"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Fuldt opladet"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM kan ikke deaktiveres på grund af en fejl."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Har du glemt mønsteret?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Forkert mønster"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Forkert adgangskode"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Forkert mønster"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Forkert adgangskode"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Forkert pinkode"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Prøv igen om <xliff:g id="NUMBER">%d</xliff:g> sekund.</item>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index c86a9ad..83d7da5c 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Bitte gib das Passwort zum Entsperren ein"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Bitte gib die PIN zum Entsperren ein"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Gib deine PIN ein"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Gib dein Muster ein"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Gib dein Passwort ein"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Muster eingeben"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Passwort eingeben"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Falscher PIN-Code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ungültige Karte."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Aufgeladen"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Vollständig aufgeladen"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Die eSim kann aufgrund eines Fehlers nicht deaktiviert werden."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Eingabe"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Muster vergessen"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Falsches Muster"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Falsches Passwort"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Falsches Muster"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Falsches Passwort"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Falsche PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">In <xliff:g id="NUMBER">%d</xliff:g> Sekunden noch einmal versuchen.</item>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index 59e7669..89b05ec 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Πληκτρολογήστε τον κωδικό πρόσβασης για ξεκλείδωμα"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Πληκτρολογήστε τον αριθμό PIN για ξεκλείδωμα"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Εισαγάγετε τον αριθμό PIN σας"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Εισαγάγετε το μοτίβο σας"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Εισαγάγετε τον κωδικό πρόσβ."</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Εισαγάγετε το μοτίβο σας"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Εισαγάγετε κωδικό πρόσβασης"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Λανθασμένος κωδικός PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Μη έγκυρη κάρτα."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Φορτίστηκε"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Πλήρως φορτισμένη"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Φόρτιση"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Δεν είναι δυνατή η απενεργοποίηση της eSIM, εξαιτίας κάποιου σφάλματος."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Ξεχάσατε το μοτίβο"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Λάθος μοτίβο"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Λανθασμένος κωδικός πρόσβασης"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Λανθασμένο μοτίβο"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Λανθασμένος κωδικός πρόσβασης"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Λανθασμένο PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Δοκιμάστε ξανά σε <xliff:g id="NUMBER">%d</xliff:g> δευτερόλεπτα.</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 77ff1b7..415e3de 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Type password to unlock"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Type PIN to unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Enter your PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Enter your pattern"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Enter your password"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Enter your pattern"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Enter your password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Invalid card."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Charged"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Fully charged"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"The eSIM can’t be disabled due to an error."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Forgotten Pattern"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Wrong Pattern"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Wrong Password"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Wrong pattern"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Wrong password"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Wrong PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index dafdd32..56a4bcc 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Type password to unlock"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Type PIN to unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Enter your PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Enter your pattern"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Enter your password"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Enter your pattern"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Enter your password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Invalid card."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Charged"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Fully charged"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"The eSIM can’t be disabled due to an error."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Forgotten Pattern"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Wrong Pattern"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Wrong Password"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Wrong pattern"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Wrong password"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Wrong PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 77ff1b7..415e3de 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Type password to unlock"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Type PIN to unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Enter your PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Enter your pattern"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Enter your password"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Enter your pattern"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Enter your password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Invalid card."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Charged"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Fully charged"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"The eSIM can’t be disabled due to an error."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Forgotten Pattern"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Wrong Pattern"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Wrong Password"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Wrong pattern"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Wrong password"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Wrong PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 77ff1b7..415e3de 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Type password to unlock"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Type PIN to unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Enter your PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Enter your pattern"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Enter your password"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Enter your pattern"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Enter your password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Invalid card."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Charged"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Fully charged"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"The eSIM can’t be disabled due to an error."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Forgotten Pattern"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Wrong Pattern"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Wrong Password"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Wrong pattern"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Wrong password"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Wrong PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index 5eac25c..f3b398d 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‎‎‎Type password to unlock‎‏‎‎‏‎"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‏‎‎Type PIN to unlock‎‏‎‎‏‎"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎Enter your PIN‎‏‎‎‏‎"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‏‎Enter your Pattern‎‏‎‎‏‎"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‏‎Enter your Password‎‏‎‎‏‎"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‎‎‎‏‎Enter your pattern‎‏‎‎‏‎"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎Enter your password‎‏‎‎‏‎"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎Incorrect PIN code.‎‏‎‎‏‎"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎‎Invalid Card.‎‏‎‎‏‎"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎Charged‎‏‎‎‏‎"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎Fully charged‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly‎‏‎‎‏‎"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎The eSIM can’t be disabled due to an error.‎‏‎‎‏‎"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‎Enter‎‏‎‎‏‎"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎Forgot Pattern‎‏‎‎‏‎"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎Wrong Pattern‎‏‎‎‏‎"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎Wrong Password‎‏‎‎‏‎"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎Wrong pattern‎‏‎‎‏‎"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎Wrong password‎‏‎‎‏‎"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎Wrong PIN‎‏‎‎‏‎"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‏‏‎Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎</item>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index 8af47fd..e56fa6b 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Ingresa la contraseña para desbloquearlo"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Ingresa el PIN para desbloquearlo"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Ingresa tu PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Ingresa tu patrón"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Ingresa tu contraseña"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Ingresa tu patrón"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Ingresa tu contraseña"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorrecto"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Tarjeta no válida"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Cargada"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Carga completa"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"No se puede inhabilitar la eSIM debido a un error."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Intro"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"¿Olvidaste el patrón?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Patrón incorrecto"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Contraseña incorrecta"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Patrón incorrecto"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Contraseña incorrecta"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN incorrecto"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index 92dc58f..8a755b4 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Escribe la contraseña para desbloquear"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Escribe el código PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Introduce tu PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Introduce tu patrón"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Introduce tu contraseña"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Introduce tu patrón"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introduce tu contraseña"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"El código PIN es incorrecto."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Tarjeta no válida."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Cargada"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Carga completa"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"No se puede mostrar la tarjeta eSIM debido a un error."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Intro"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"¿Has olvidado el patrón?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Patrón incorrecto"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Contraseña incorrecta"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Patrón incorrecto"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Contraseña incorrecta"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN incorrecto"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
@@ -140,8 +140,8 @@
       <item quantity="other">El dispositivo no se ha desbloqueado durante <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirma la contraseña.</item>
       <item quantity="one">El dispositivo no se ha desbloqueado durante <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirma la contraseña.</item>
     </plurals>
-    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"No reconocida"</string>
-    <string name="kg_face_not_recognized" msgid="6382535088345875294">"No reconocida"</string>
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"No se reconoce"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"No se reconoce"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="other">Introduce el PIN de la tarjeta SIM. Te quedan <xliff:g id="NUMBER_1">%d</xliff:g> intentos.</item>
       <item quantity="one">Introduce el PIN de la tarjeta SIM. Te queda <xliff:g id="NUMBER_0">%d</xliff:g> intento para tener que ponerte en contacto con tu operador para desbloquear el dispositivo.</item>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index ad6becd..a19cc23 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Avamiseks sisestage parool"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Avamiseks sisestage PIN-kood"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Sisestage PIN-kood"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Sisestage muster"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Sisestage parool"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Sisestage muster"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Sisestage parool"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Vale PIN-kood."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Kehtetu kaart."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Laetud"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Täielikult laetud"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Vea tõttu ei saa eSIM-kaarte keelata."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Sisesta"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Unustasin mustri"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Vale muster"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Vale parool"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Vale muster"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Vale parool"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Vale PIN-kood"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Proovige uuesti <xliff:g id="NUMBER">%d</xliff:g> sekundi pärast.</item>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 4036851..b063107 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Idatzi desblokeatzeko pasahitza"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Idatzi desblokeatzeko PIN kodea"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Idatzi PIN kodea"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Marraztu eredua"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Idatzi pasahitza"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Marraztu eredua"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Idatzi pasahitza"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kode hori ez da zuzena."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Txartelak ez du balio."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Kargatuta"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Erabat kargatuta"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Errore bat gertatu da eta ezin da desgaitu eSIM txartela."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Sartu"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Eredua ahaztu zaizu"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Eredu hori ez da zuzena"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Pasahitz hori ez da zuzena"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Eredua ez da zuzena"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Pasahitza ez da zuzena"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN kode hori ez da zuzena"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Saiatu berriro <xliff:g id="NUMBER">%d</xliff:g> segundo igarotakoan.</item>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index 3b1d8d7..db7923d 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"برای بازکردن قفل، گذرواژه را وارد کنید"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"برای بازکردن قفل، پین را تایپ کنید"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"پین را وارد کنید"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"الگویتان را وارد کنید"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"گذرواژه‌تان را وارد کنید"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"الگویتان را وارد کنید"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"گذرواژه‌تان را وارد کنید"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"کد پین اشتباه است."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"کارت نامعتبر"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"شارژ کامل شد"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"شارژ کامل است"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ آهسته"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"به دلیل بروز خطا، سیم‌کارت داخلی غیرفعال نشد."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"الگو را فراموش کرده‌اید"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"الگوی اشتباه"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"گذرواژه اشتباه"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"الگو اشتباه است"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"گذرواژه اشتباه است"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"پین اشتباه"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> ثانیه دیگر دوباره امتحان کنید.</item>
@@ -99,8 +99,8 @@
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"<xliff:g id="NUMBER_0">%1$d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل رایانه لوحی داشته‌اید. نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"‏شما الگوی باز کردن قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب رایانامه قفل رایانه لوحی خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"‏شما الگوی باز کردن قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب رایانامه قفل تلفن را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"‏شما الگوی باز کردن قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‎اید. بعد از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل رایانه لوحی خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"‏شما الگوی باز کردن قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل تلفن را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"کد پین سیم‌کارت اشتباه است، اکنون برای باز کردن قفل دستگاهتان باید با شرکت مخابراتی تماس بگیرید."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
       <item quantity="one">کد پین سیم‌کارت اشتباه است، <xliff:g id="NUMBER_1">%d</xliff:g> بار دیگر می‌توانید تلاش کنید.</item>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index 34d830f..2bd8314 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Poista lukitus antamalla salasana."</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Poista lukitus antamalla PIN-koodi."</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Syötä PIN-koodi"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Piirrä kuvio"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Kirjoita salasana"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Piirrä kuvio"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Kirjoita salasana"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Väärä PIN-koodi"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Virheellinen kortti"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Ladattu"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Täyteen ladattu"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Tapahtui virhe, eikä eSIMiä voitu poistaa käytöstä."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Unohtunut kuvio"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Väärä kuvio"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Väärä salasana"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Väärä kuvio"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Väärä salasana"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Väärä PIN-koodi"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Yritä uudelleen <xliff:g id="NUMBER">%d</xliff:g> sekunnin kuluttua.</item>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index c344807..9b0e269 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Entrez le mot de passe pour déverrouiller le clavier."</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Entrez le NIP pour déverrouiller le clavier."</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Entrez votre NIP"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Entrez votre schéma"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Entrez votre mot de passe"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Entrez votre schéma"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Entrez votre mot de passe"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"NIP erroné."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Cette carte n\'est pas valide."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Chargé"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Complètement chargé"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"En recharge : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"La carte eSIM ne peut pas être réinitialisée à cause d\'une erreur."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Entrée"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"J\'ai oublié le schéma"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Schéma incorrect"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Mot de passe incorrect"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Schéma incorrect"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Mot de passe incorrect"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"NIP incorrect"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index bf8c7e8..d5e36ce 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Saisissez le mot de passe pour déverrouiller le clavier"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Saisissez le code pour déverrouiller le clavier"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Saisissez le code d\'accès"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Tracez le schéma"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Saisissez le mot de passe"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Tracez le schéma"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Saisissez votre mot de passe"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Le code est incorrect."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Carte non valide."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Chargé"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Complètement chargée"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rechargement…"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rechargement rapide…"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rechargement lent…"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Impossible de désactiver la carte eSIM en raison d\'une erreur."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Entrée"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"J\'ai oublié le schéma"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Schéma incorrect"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Mot de passe incorrect"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Schéma incorrect"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Mot de passe incorrect"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Code incorrect"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index b4ff9ea..756fc27 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Escribe o contrasinal para desbloquear"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Escribe o PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Introduce o teu PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Introduce o teu padrón"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Introduce o teu contrasinal"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Introduce o padrón"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introduce o contrasinal"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorrecto"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"A tarxeta non é válida."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Cargada"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Batería totalmente cargada"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"A eSIM non se puido desactivar debido a un erro."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Intro"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Esqueciches o padrón"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Padrón incorrecto"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Contrasinal incorrecto"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"O padrón é incorrecto"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"O contrasinal é incorrecto"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN incorrecto"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Téntao de novo dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index e2cd09b..fb3a14b 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"અનલૉક કરવા માટે પાસવર્ડ લખો"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"અનલૉક કરવા માટે પિન લખો"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"તમારો પિન દાખલ કરો"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"તમારી પૅટર્ન દાખલ કરો"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"તમારો પાસવર્ડ દાખલ કરો"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"તમારી પૅટર્ન દાખલ કરો"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"તમારો પાસવર્ડ દાખલ કરો"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ખોટો પિન કોડ."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"અમાન્ય કાર્ડ."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"ચાર્જ થઈ ગયું"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"સંપૂર્ણપણે ચાર્જ થયેલ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"એક ભૂલને લીધે ઇ-સિમ બંધ કરી શકાતું નથી."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"દાખલ કરો"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"પૅટર્ન ભૂલી ગયાં"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ખોટી પૅટર્ન"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"ખોટો પાસવર્ડ"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"ખોટી પૅટર્ન"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"ખોટો પાસવર્ડ"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"ખોટો પિન"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> સેકન્ડમાં ફરી પ્રયાસ કરો.</item>
@@ -140,10 +140,8 @@
       <item quantity="one">ઉપકરણને <xliff:g id="NUMBER_1">%d</xliff:g> કલાક માટે અનલૉક કરવામાં આવ્યું નથી. પાસવર્ડની પુષ્ટિ કરો.</item>
       <item quantity="other">ઉપકરણને <xliff:g id="NUMBER_1">%d</xliff:g> કલાક માટે અનલૉક કરવામાં આવ્યું નથી. પાસવર્ડની પુષ્ટિ કરો.</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"ઓળખાયેલ નથી"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"ઓળખાયેલ નથી"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="one">સિમનો પિન દાખલ કરો, તમારી પાસે <xliff:g id="NUMBER_1">%d</xliff:g> પ્રયાસ બાકી છે.</item>
       <item quantity="other">સિમનો પિન દાખલ કરો, તમારી પાસે <xliff:g id="NUMBER_1">%d</xliff:g> પ્રયાસો બાકી છે.</item>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 539efd9..7bfc635 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"अनलॉक करने के लिए पासवर्ड लिखें"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"अनलॉक करने के लिए पिन लिखें"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"अपना पिन डालें"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"अपना पैटर्न डालें"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"अपना पासवर्ड डालें"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"अपना पैटर्न डालें"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"अपना पासवर्ड डालें"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"गलत पिन कोड."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"गलत कार्ड."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"चार्ज हो गई है"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"पूरी तरह चार्ज हो गया"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"किसी गड़बड़ी की वजह से ई-सिम बंद नहीं किया जा सकता."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"पैटर्न भूल गए हैं"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"गलत पैटर्न"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"गलत पासवर्ड"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"डाला गया पैटर्न गलत है"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"डाला गया पासवर्ड गलत है"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"गलत पिन"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> सेकंड में फिर से कोशिश करें.</item>
@@ -140,10 +140,8 @@
       <item quantity="one">डिवाइस को <xliff:g id="NUMBER_1">%d</xliff:g> घंटों से अनलॉक नहीं किया गया है. पासवर्ड की पुष्टि करें.</item>
       <item quantity="other">डिवाइस को <xliff:g id="NUMBER_1">%d</xliff:g> घंटों से अनलॉक नहीं किया गया है. पासवर्ड की पुष्टि करें.</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"पहचान नहीं हो पाई"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"पहचान नहीं हो पाई"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="one">सिम का पिन डालें. आपके पास <xliff:g id="NUMBER_1">%d</xliff:g> मौके बचे हैं.</item>
       <item quantity="other">सिम का पिन डालें. आपके पास <xliff:g id="NUMBER_1">%d</xliff:g> मौके बचे हैं.</item>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index 6ae39b2..089c6c4 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Unesite zaporku da biste otključali"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Unesite PIN da biste otključali"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Unesite PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Unesite uzorak"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Unesite zaporku"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Unesite uzorak"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Unesite zaporku"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kôd nije točan."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nevažeća kartica."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Napunjeno"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Potpuno napunjena baterija"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Onemogućivanje eSIM-a nije uspjelo zbog pogreške."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Unos"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Zaboravili ste uzorak"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Pogrešan uzorak"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Pogrešna zaporka"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Pogrešan uzorak"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Pogrešna zaporka"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Pogrešan PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekundu</item>
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index a03a8b2..49d8401 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"A feloldáshoz írja be a jelszót"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"A feloldáshoz írja be a PIN-kódot"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Adja meg PIN-kódját"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Adja meg mintáját"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Adja meg jelszavát"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Adja meg a mintáját"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Adja meg jelszavát"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Helytelen PIN-kód."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Érvénytelen kártya."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Feltöltve"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Teljesen feltöltve"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Hiba történt, így az eSIM-et nem lehet letiltani."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Elfelejtettem a mintát"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Helytelen minta"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Helytelen jelszó"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Helytelen minta"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Helytelen jelszó"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Helytelen PIN-kód"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Próbálja újra <xliff:g id="NUMBER">%d</xliff:g> másodperc múlva.</item>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index 8009371..5198da6 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Ապակողպելու համար մուտքագրեք գաղտնաբառը"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Ապակողպելու համար մուտքագրեք PIN կոդը"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Մուտքագրեք PIN կոդը"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Մուտքագրեք նախշը"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Մուտքագրեք գաղտնաբառը"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Մուտքագրեք նախշը"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Մուտքագրեք գաղտնաբառը"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN կոդը սխալ է։"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Սխալ քարտ"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Լիցքավորված է"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Ամբողջությամբ լիցքավորված է"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Սխալի պատճառով չհաջողվեց անջատել eSIM-ը։"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Մուտքի ստեղն"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Մոռացել եմ նախշը"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Նախշը սխալ է"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Գաղտնաբառը սխալ է"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Նախշը սխալ է"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Գաղտնաբառը սխալ է"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN կոդը սխալ է"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Փորձեք <xliff:g id="NUMBER">%d</xliff:g> վայրկյանից:</item>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index c1a20c6..161287c 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Ketik sandi untuk membuka kunci"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Ketik PIN untuk membuka kunci"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Masukkan PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Masukkan Pola"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Masukkan Sandi"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Masukkan pola"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Masukkan sandi"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Kode PIN salah."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Kartu Tidak Valid"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Terisi"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Terisi penuh"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM tidak dapat dinonaktifkan karena terjadi error."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Masukkan"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Lupa Pola?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Pola Salah"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Sandi Salah"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Pola salah"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Sandi salah"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN Salah"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Coba <xliff:g id="NUMBER">%d</xliff:g> detik lagi.</item>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index 0800b3e..9ed1188 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Sláðu inn aðgangsorðið til að opna"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Sláðu inn PIN-númer til að opna"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Sláðu inn PIN-númer"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Færðu inn mynstur"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Sláðu inn aðgangsorð"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Færðu inn mynstrið þitt"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Sláðu inn aðgangsorðið þitt"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Rangt PIN-númer."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ógilt kort."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Fullhlaðin"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Fullhlaðin"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í hleðslu"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Villa kom í veg fyrir að hægt væri að gera eSIM-kortið óvirkt."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Færa inn"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Man ekki mynstrið"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Rangt mynstur"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Rangt aðgangsorð"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Rangt mynstur"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Rangt aðgangsorð"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Rangt PIN-númer"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Reyndu aftur eftir <xliff:g id="NUMBER">%d</xliff:g> sekúndu.</item>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index 07830c2..b5f85f6 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Inserisci password per sbloccare"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Inserisci PIN per sbloccare"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Inserisci il PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Inserisci la sequenza"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Inserisci la password"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Inserisci la sequenza"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Inserisci la password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Codice PIN errato."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Scheda non valida."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Carico"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Completamente carica"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Impossibile disattivare la eSIM a causa di un errore."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Invio"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Sequenza dimenticata"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Sequenza sbagliata"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Password sbagliata"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Sequenza errata"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Password errata"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN errato"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Riprova fra <xliff:g id="NUMBER">%d</xliff:g> secondi.</item>
@@ -140,8 +140,8 @@
       <item quantity="other">Il dispositivo non viene sbloccato da <xliff:g id="NUMBER_1">%d</xliff:g> ore. Conferma la password.</item>
       <item quantity="one">Il dispositivo non viene sbloccato da <xliff:g id="NUMBER_0">%d</xliff:g> ora. Conferma la password.</item>
     </plurals>
-    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"Non riconosciuta"</string>
-    <string name="kg_face_not_recognized" msgid="6382535088345875294">"Non riconosciuta"</string>
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"Non riconosciuto"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"Non riconosciuto"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="other">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item>
       <item quantity="one">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index 6ed4e5f..09b3cfa 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"הזן סיסמה לביטול הנעילה"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"הזן את קוד הגישה לביטול הנעילה"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"הזנת קוד גישה"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"הזנת קו ביטול נעילה"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"הזנת סיסמה"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"יש להזין קו ביטול נעילה"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"יש להזין סיסמה"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"קוד הגישה שגוי"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"כרטיס לא חוקי."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"הסוללה טעונה"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"טעונה במלואה"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"‏לא ניתן להשבית את כרטיס ה-eSIM עקב שגיאה."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"שכחתי את קו ביטול הנעילה"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"קו ביטול הנעילה שגוי"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"הסיסמה שגויה"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"קו ביטול נעילה שגוי"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"סיסמה שגויה"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"קוד הגישה שגוי"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="two">אפשר יהיה לנסות שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index c9acb55..08d4b9b 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"ロックを解除するにはパスワードを入力してください"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"ロックを解除するには PIN を入力してください"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"PIN を入力してください"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"パターンを入力してください"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"パスワードを入力してください"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"パターンを入力してください"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"パスワードを入力してください"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN コードが無効です。"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"無効なカードです。"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"充電が完了しました"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"充電完了"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"エラーのため、eSIM を無効にできません。"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"入力"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"パターンを忘れた場合"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"パターンが正しくありません"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"パスワードが正しくありません"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"パターンが正しくありません"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"パスワードが正しくありません"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN が正しくありません"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> 秒後にもう一度お試しください。</item>
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index c5f415b..f966c33 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"განსაბლოკად აკრიფეთ პაროლი"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"განსაბლოკად აკრიფეთ PIN-კოდი"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"შეიყვანეთ PIN-კოდი"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"შეიყვანეთ განმბლოკავი ნიმუში"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"შეიყვანეთ პაროლი"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"შეიყვანეთ განმბლოკავი ნიმუში"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"შეიყვანეთ პაროლი"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN-კოდი არასწორია."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ბარათი არასწორია."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"დატენილია"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"ბოლომდე დატენილი"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM-ის გათიშვა ვერ ხერხდება წარმოქმნილი შეცდომის გამო."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"შეყვანა"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"დაგავიწყდათ ნიმუში"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ნიმუში არასწორია"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"პაროლი არასწორია"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"ნიმუში არასწორია"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"პაროლი არასწორია"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN-კოდი არასწორია"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">ცადეთ ხელახლა <xliff:g id="NUMBER">%d</xliff:g> წამში.</item>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index d206bcb..530418f 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Құлпын ашу үшін құпия сөзді теріңіз"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Құлпын ашу үшін PIN кодын енгізіңіз"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"PIN кодын енгізіңіз"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Өрнекті енгізіңіз"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Құпия сөзді енгізіңіз"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Өрнекті енгізіңіз"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Құпия сөзді енгізіңіз"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN коды қате"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Жарамсыз карта."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Зарядталды"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Толық зарядталды"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Қатеге байланысты eSIM картасы өшірілмеді."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Енгізу"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Өрнекті ұмытып қалдыңыз ба?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Өрнек қате"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Құпия сөз қате"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Өрнек дұрыс емес"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Құпия сөз дұрыс емес"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN коды қате"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"> <xliff:g id="NUMBER">%d</xliff:g> секундтан кейін қайталап көріңіз.</item>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index d38aa3f..7ab347d 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"វាយ​បញ្ចូល​ពាក្យ​សម្ងាត់​ ដើម្បី​ដោះ​សោ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"វាយ​បញ្ចូល​កូដ PIN ដើម្បី​ដោះ​សោ"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"បញ្ចូល​កូដ PIN របស់​អ្នក"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"បញ្ចូល​លំនាំ​របស់អ្នក"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"បញ្ចូល​ពាក្យ​សម្ងាត់​របស់​អ្នក"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"បញ្ចូល​លំនាំ​របស់​អ្នក"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"បញ្ចូល​ពាក្យ​សម្ងាត់​របស់អ្នក"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"កូដ PIN មិន​ត្រឹមត្រូវ​ទេ។"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"បណ្ណមិនត្រឹមត្រូវទេ។"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"បាន​សាក​ថ្ម"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"បានសាក​ថ្មពេញ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្ម"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយឺត"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"មិនអាច​បិទ eSIM បានទេ ដោយសារ​មាន​បញ្ហា។"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ភ្លេច​​លំនាំ"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"លំនាំ​មិន​ត្រឹមត្រូវ​ទេ"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ​ទេ"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"លំនាំមិនត្រឹមត្រូវ"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"ពាក្យសម្ងាត់មិនត្រឹមត្រូវ"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"កូដ PIN មិន​ត្រឹមត្រូវ​ទេ"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">ព្យាយាមម្តងទៀតក្នុងរយៈពេល <xliff:g id="NUMBER">%d</xliff:g> វិនាទី។</item>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index a435608..ef92951 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"ಅನ್‌ಲಾಕ್‌ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್‌ ಟೈಪ್‌ ಮಾಡಿ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"ಅನ್‌ಲಾಕ್‌ ಮಾಡಲು ಪಿನ್‌ ಟೈಪ್‌ ಮಾಡಿ"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"ನಿಮ್ಮ ಪಿನ್ ನಮೂದಿಸಿ"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"ನಿಮ್ಮ ಪ್ಯಾಟರ್ನ್ ನಮೂದಿಸಿ"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"ನಿಮ್ಮ ಪ್ಯಾಟರ್ನ್ ನಮೂದಿಸಿ"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ತಪ್ಪಾದ ಪಿನ್‌ ಕೋಡ್."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ಅಮಾನ್ಯ ಕಾರ್ಡ್."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"ಪೂರ್ಣವಾಗಿ ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್‌ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"ದೋಷದ ಕಾರಣದಿಂದಾಗಿ eSIM ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"ನಮೂದಿಸಿ"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ಪ್ಯಾಟರ್ನ್ ಮರೆತಿದ್ದೀರಿ"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ಪ್ಯಾಟರ್ನ್ ತಪ್ಪಾಗಿದೆ"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"ಪಾಸ್‌ವರ್ಡ್ ತಪ್ಪಾಗಿದೆ"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"ಪ್ಯಾಟರ್ನ್ ತಪ್ಪಾಗಿದೆ"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"ತಪ್ಪು ಪಾಸ್‌ವರ್ಡ್"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"ಪಿನ್‌ ತಪ್ಪಾಗಿದೆ"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</item>
@@ -140,10 +140,8 @@
       <item quantity="one">ಸಾಧನವನ್ನು <xliff:g id="NUMBER_1">%d</xliff:g> ಗಂಟೆಗಳವರೆಗೆ ಅನ್‌ಲಾಕ್‌ ಮಾಡಿರಲಿಲ್ಲ. ಪಾಸ್‌ವರ್ಡ್‌ ಖಚಿತಪಡಿಸಿ.</item>
       <item quantity="other">ಸಾಧನವನ್ನು <xliff:g id="NUMBER_1">%d</xliff:g> ಗಂಟೆಗಳವರೆಗೆ ಅನ್‌ಲಾಕ್‌ ಮಾಡಿರಲಿಲ್ಲ. ಪಾಸ್‌ವರ್ಡ್‌ ಖಚಿತಪಡಿಸಿ.</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="one">ಸಿಮ್ ಪಿನ್ ನಮೂದಿಸಿ. ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER_1">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ.</item>
       <item quantity="other">ಸಿಮ್ ಪಿನ್ ನಮೂದಿಸಿ. ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER_1">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 87359ca..8a65c95 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"잠금 해제하려면 비밀번호 입력"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"잠금 해제하려면 PIN 입력"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"PIN을 입력해 주세요."</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"패턴을 입력해 주세요."</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"비밀번호를 입력해 주세요."</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"패턴 입력"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"비밀번호 입력"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"잘못된 PIN 코드입니다."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"유효하지 않은 카드"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"충전됨"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"충전 완료"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 중"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"오류로 인해 eSIM을 사용 중지할 수 없습니다."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter 키"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"패턴을 잊음"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"잘못된 패턴"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"잘못된 비밀번호"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"잘못된 패턴"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"잘못된 비밀번호"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"잘못된 PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g>초 후에 다시 시도하세요.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index 832e5af..a7d5d45 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Кулпуну ачуу үчүн сырсөздү териңиз"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Кулпуну ачуу үчүн PIN-кодду териңиз"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"PIN кодуңузду киргизиңиз"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Графикалык ачкычты киргизиңиз"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Сырсөзүңүздү киргизиңиз"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Графикалык ачкычты киргизиңиз"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Сырсөзүңүздү киргизиңиз"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN-код туура эмес."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"SIM-карта жараксыз."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Кубатталды"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Толук кубатталды"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубатталууда"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Катадан улам eSIM-картаны өчүрүүгө болбойт."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Киргизүү"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Графикалык ачкычты унутуп калдым"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Графикалык ачкыч туура эмес"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Сырсөз туура эмес"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Графикалык ачкыч туура эмес"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Сырсөз туура эмес"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN-код туура эмес"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> секунддан кийин кайталаңыз.</item>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index 4d66dfe..9f3de8b0 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"ພິມລະຫັດເພື່ອປົດລັອກ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"ພິມລະຫັດ PIN ເພື່ອປົດລັອກ"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"ໃສ່ລະຫັດ PIN ຂອງທ່ານ"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"ໃສ່ຮູບແບບປົດລັອກຂອງທ່ານ"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"ໃສ່ລະຫັດຜ່ານຂອງທ່ານ"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"ໃສ່ຮູບແບບປົດລັອກຂອງທ່ານ"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ປ້ອນລະຫັດຜ່ານຂອງທ່ານ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ລະຫັດ PIN ບໍ່ຖືກຕ້ອງ."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ບັດບໍ່ຖືກຕ້ອງ."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"ສາກເຕັມແລ້ວ."</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"ສາກເຕັມແລ້ວ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"ບໍ່ສາມາດປິດການນຳໃຊ້ eSIM ໄດ້ເນື່ອງຈາກມີຂໍ້ຜິດພາດ."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"ປ້ອນເຂົ້າ"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ລືມຮູບແບບປົດລັອກ?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ຮູບແບບຜິດ"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"ລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"ຮູບແບບບໍ່ຖືກຕ້ອງ"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"ລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"ລະຫັດ PIN ບໍ່ຖືກຕ້ອງ"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">ລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER">%d</xliff:g> ວິນາທີ.</item>
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index 18404e0..bdebf67 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Įveskite slaptažodį, kad atrakintumėte"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Įveskite PIN kodą, kad atrakintumėte"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Įveskite PIN kodą"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Įveskite atrakinimo piešinį"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Įveskite slaptažodį"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Nubrėžkite atrakinimo piešinį"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Įveskite slaptažodį"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Netinkamas PIN kodas."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Netinkama kortelė."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Įkrauta"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Visiškai įkrautas"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Dėl klaidos nepavyko išjungti „eSIM“ kortelės."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Pamiršau atrakinimo piešinį"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Netinkamas atrakinimo piešinys"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Netinkamas slaptažodis"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Netinkamas atrakinimo piešinys"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Netinkamas slaptažodis"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Netinkamas PIN kodas"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Bandykite dar kartą po <xliff:g id="NUMBER">%d</xliff:g> sekundės.</item>
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index 9ec52cf..c68761d 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Ievadiet paroli, lai atbloķētu."</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Ievadiet PIN kodu, lai atbloķētu."</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Ievadiet savu PIN kodu"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Ievadiet savu kombināciju"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Ievadiet savu paroli"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Ievadiet savu kombināciju"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Ievadiet paroli"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kods nav pareizs."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nederīga karte."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Akumulators uzlādēts"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Pilnībā uzlādēts"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Kļūdas dēļ nevar atspējot eSIM karti."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Ievadīšanas taustiņš"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Aizmirsu kombināciju"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Nepareiza kombinācija."</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Nepareiza parole."</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Nepareiza kombinācija"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Nepareiza parole"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Nepareizs PIN kods."</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="zero">Mēģiniet vēlreiz pēc <xliff:g id="NUMBER">%d</xliff:g> sekundēm.</item>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index 0685a10..0ace83f 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Напишете ја лозинката за да отклучите"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Напишете PIN-код за да отклучите"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Внесете го PIN-кодот"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Внесете ја шемата"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Внесете ја лозинката"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Внесете ја шемата"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Внесете ја лозинката"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Погрешен PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Неважечка картичка."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Полна"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Целосно полна"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM-картичката не може да се оневозможи поради грешка."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Внеси"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Ја заборавивте шемата?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Погрешна шема"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Погрешна лозинка"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Погрешна шема"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Погрешна лозинка"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Погрешен PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Обидете се повторно за <xliff:g id="NUMBER">%d</xliff:g> секунда.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index c6aadb0..779a532 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"അൺലോക്കുചെയ്യുന്നതിന് പാസ്‌വേഡ് ടൈപ്പുചെയ്യുക"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"അൺലോക്കുചെയ്യുന്നതിന് പിൻ ടൈപ്പുചെയ്യുക"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"പിൻ നൽകുക"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"നിങ്ങളുടെ പാറ്റേൺ നൽകുക"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"നിങ്ങളുടെ പാസ്‌വേഡ് നല്‍‌കുക"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"നിങ്ങളുടെ പാറ്റേൺ നൽകുക"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"നിങ്ങളുടെ പാസ്‌വേഡ് നല്‍‌കുക"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"പിൻ കോഡ് തെറ്റാണ്."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"അസാധുവായ കാർഡ്."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"ചാർജായി"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"പൂർണ്ണമായി ചാർജ് ചെയ്‌തു"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"പിശക് കാരണം ഇ-സിം പ്രവർത്തനരഹിതമാക്കാനാകുന്നില്ല"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"എന്റർ"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"പാറ്റേൺ മറന്നു"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"പാറ്റേൺ തെറ്റാണ്"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"പാസ്‌വേഡ് തെറ്റാണ്"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"പാറ്റേൺ തെറ്റാണ്"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"പാസ്‌വേഡ് തെറ്റാണ്"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"പിൻ തെറ്റാണ്"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> സെക്കൻഡുകൾക്കുള്ളിൽ വീണ്ടും ശ്രമിക്കുക.</item>
@@ -140,10 +140,8 @@
       <item quantity="other">ഉപകരണം <xliff:g id="NUMBER_1">%d</xliff:g> മണിക്കൂറായി അൺലോക്ക് ചെയ്തിട്ടില്ല. പാസ്‌വേഡ് സ്ഥിരീകരിക്കുക.</item>
       <item quantity="one">ഉപകരണം <xliff:g id="NUMBER_0">%d</xliff:g> മണിക്കൂറായി അൺലോക്ക് ചെയ്തിട്ടില്ല. പാസ്‌വേഡ് സ്ഥിരീകരിക്കുക.</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"തിരിച്ചറിയുന്നില്ല"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"തിരിച്ചറിയുന്നില്ല"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="other">സിം പിൻ നൽകുക. നിങ്ങൾക്ക് <xliff:g id="NUMBER_1">%d</xliff:g> ശ്രമങ്ങൾ കൂടി ശേഷിക്കുന്നു.</item>
       <item quantity="one">സിം പിൻ നൽകുക. ഉപകരണം അൺലോക്ക് ചെയ്യാൻ കാരിയറുമായി ബന്ധപ്പെടേണ്ടിവരുന്നതിന് മുമ്പ് <xliff:g id="NUMBER_0">%d</xliff:g> ശ്രമം കൂടി ശേഷിക്കുന്നു.</item>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index 3c1870d..189d407 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Түгжээг тайлахын тулд нууц үгийг оруулна уу"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Түгжээг тайлахын тулд ПИН кодыг оруулна уу"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"ПИН-ээ оруулна уу"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Загвараа оруулна уу"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Нууц үгээ оруулна уу"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Хээгээ оруулна уу"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Нууц үгээ оруулна уу"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ПИН код буруу байна."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Карт хүчингүй байна."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Цэнэглэсэн"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Бүрэн цэнэглэсэн"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Алдаа гарсан тул eSIM-г идэвхгүй болгох боломжгүй байна."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Оруулах"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Загварыг мартсан"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Загвар буруу байна"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Нууц үг буруу байна"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Хээ буруу байна"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Нууц үг буруу байна"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"ПИН код буруу байна"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> секундын дараа дахин оролдоно уу.</item>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 88724ce9..c2759da 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"अनलॉक करण्यासाठी पासवर्ड टाइप करा"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"अनलॉक करण्यासाठी पिन टाइप करा"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"तुमचा पिन एंटर करा"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"तुमचा पॅटर्न एंटर करा"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"तुमचा पासवर्ड एंटर करा"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"तुमचा पॅटर्न एंटर करा"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"तुमचा पासवर्ड एंटर करा"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"चुकीचा पिन कोड."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"अवैध कार्ड."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"चार्ज झाली"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"पूर्णपणे चार्ज"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज होत आहे"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"एका एररमुळे eSIM बंद होऊ शकत नाही."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"एंटर करा"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"पॅटर्न विसरलात"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"चुकीचा पॅटर्न"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"चुकीचा पासवर्ड"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"चुकीचा पॅटर्न"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"चुकीचा पासवर्ड"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"चुकीचा पिन"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> सेकंदात पुन्हा प्रयत्न करा.</item>
@@ -140,10 +140,8 @@
       <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
       <item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"ओळखले नाही"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"ओळखले नाही"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="one">सिम पिन एंटर करा, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहे.</item>
       <item quantity="other">सिम पिन एंटर करा, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index bec3295..9e10298 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Taip kata laluan untuk membuka kunci"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Taip PIN untuk membuka kunci"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Masukkan PIN anda"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Masukkan Corak anda"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Masukkan Kata Laluan anda"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Masukkan corak anda"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Masukkan kata laluan anda"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Kod PIN salah."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Kad Tidak Sah."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Sudah dicas"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Dicas penuh"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM tidak dapat dilumpuhkan kerana ralat."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Kekunci Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Terlupa Corak"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Corak salah"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Kata Laluan salah"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Corak salah"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Kata laluan salah"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN salah"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Cuba lagi dalam masa <xliff:g id="NUMBER">%d</xliff:g> saat.</item>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index 017bf0a..87fca07 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"လော့ခ်ဖွင့်ရန် စကားဝှက်ကို ထည့်ပါ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"လော့ခ်ဖွင့်ရန် ပင်နံပါတ်ထည့်ပါ"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"သင့်ပင်နံပါတ် ထည့်ပါ"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"သင့်လော့ခ်ဖွင့်ပုံစံ ထည့်ပါ"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"သင့်စကားဝှက် ထည့်ပါ"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"သင့်လော့ခ်ဖွင့်ပုံစံ ထည့်ပါ"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"သင့်စကားဝှက် ထည့်ပါ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ပင်နံပါတ် မှားနေသည်။"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ကတ် မမှန်ကန်ပါ။"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"အားသွင်းပြီးပါပြီ"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"အားအပြည့်သွင်းထားသည်"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"အမှားအယွင်းရှိနေသောကြောင့် eSIM ကို ပိတ်၍မရပါ။"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter ခလုတ်"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ပုံစံအား မေ့သွားပါသည်"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ပုံစံ မမှန်ကန်ပါ"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"စကားဝှက် မမှန်ကန်ပါ"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"လော့ခ်ဖွင့်ပုံစံ မှားနေသည်"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"စကားဝှက် မှားနေသည်"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"ပင်နံပါတ် မမှန်ကန်ပါ"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> စက္ကန့် အကြာတွင် ထပ်လုပ်ကြည့်ပါ</item>
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index 125ffb0..977784c 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Skriv inn passordet for å låse opp"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Skriv inn PIN-koden for å låse opp"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Skriv inn PIN-koden din"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Skriv inn mønsteret ditt"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Skriv inn passordet ditt"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Legg inn mønsteret ditt"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Skriv inn passordet ditt"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Feil PIN-kode."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ugyldig kort."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Oppladet"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Fulladet"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"E-SIM-kortet kan ikke deaktiveres på grunn av en feil."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Har du glemt mønsteret?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Feil mønster"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Feil passord"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Feil mønster"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Feil passord"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Feil PIN-kode"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Prøv på nytt om <xliff:g id="NUMBER">%d</xliff:g> sekunder.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index ccb78d1..913c3bb 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"अनलक गर्न पासवर्ड टाइप गर्नुहोस्"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"अनलक गर्न PIN कोड टाइप गर्नुहोस्"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"आफ्नो PIN प्रविष्ट गर्नुहोस्"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"आफ्नो ढाँचा प्रविष्ट गर्नुहोस्"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"आफ्नो पासवर्ड प्रविष्ट गर्ने"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"आफ्नो ढाँचा प्रविष्ट गर्नुहोस्"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"आफ्नो पासवर्ड प्रविष्ट गर्नु…"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN कोड गलत छ।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"अमान्य कार्ड।"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"चार्ज भयो"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"पूर्ण चार्ज भएको"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज गरिँदै"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"कुनै त्रुटिका कारण यो eSIM लाई असक्षम पार्न सकिएन।"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"प्रविष्टि गर्नुहोस्"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ढाँचा बिर्सनुभयो"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"गलत ढाँचा"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"गलत पासवर्ड"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"गलत ढाँचा"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"गलत पासवर्ड"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"गलत PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।</item>
@@ -140,10 +140,8 @@
       <item quantity="other">यन्त्र <xliff:g id="NUMBER_1">%d</xliff:g> घन्टा देखि अनलक भएको छैन। पासवर्ड पुष्टि गर्नुहोस्।</item>
       <item quantity="one">यन्त्र <xliff:g id="NUMBER_0">%d</xliff:g> घन्टा देखि अनलक भएको छैन। पासवर्ड पुष्टि गर्नुहोस्।</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"पहिचान भएन"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"पहिचान भएन"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="other">SIM को PIN प्रविष्ट गर्नुहोस्। तपाईंसँग <xliff:g id="NUMBER_1">%d</xliff:g>  प्रयासहरू बाँकी छन्।</item>
       <item quantity="one">SIM को PIN प्रविष्ट गर्नुहोस्। तपाईंसँग <xliff:g id="NUMBER_0">%d</xliff:g> प्रयास बाँकी छ, त्यसपछि भने आफ्नो यन्त्र अनलक गर्नका लागि तपाईंले अनिवार्य रूपमा आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नु पर्ने हुन्छ।</item>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index cf0cff2..f80749f 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Typ het wachtwoord om te ontgrendelen"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Typ pincode om te ontgrendelen"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Geef je pincode op"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Geef je patroon op"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Geef je wachtwoord op"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Geef je patroon op"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Geef je wachtwoord op"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Onjuiste pincode."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ongeldige kaart."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Opgeladen"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Volledig opgeladen"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"De e-simkaart kan niet worden uitgeschakeld vanwege een fout."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Patroon vergeten"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Onjuist patroon"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Onjuist wachtwoord"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Onjuist patroon"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Onjuist wachtwoord"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Onjuiste pincode"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Probeer het over <xliff:g id="NUMBER">%d</xliff:g> seconden opnieuw.</item>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index 6d94626..eff493b 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"ଅନଲକ୍‍ କରିବାକୁ ପାସ୍‌ୱର୍ଡ ଟାଇପ୍‍ କରନ୍ତୁ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"ଅନଲକ୍‍ କରିବାକୁ PIN ଟାଇପ୍‍ କରନ୍ତୁ"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"ନିଜର PIN ଲେଖନ୍ତୁ"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"ନିଜର ପାଟର୍ନ ଆଙ୍କନ୍ତୁ"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"ନିଜର ପାସ୍‌ୱର୍ଡ ଲେଖନ୍ତୁ"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"ନିଜର ପାଟର୍ନ ଆଙ୍କନ୍ତୁ"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ନିଜ ପାସ୍‌ୱର୍ଡ ଲେଖନ୍ତୁ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ଭୁଲ PIN କୋଡ୍।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ଅମାନ୍ୟ କାର୍ଡ।"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"ଚାର୍ଜ ହୋଇଗଲା"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"ସମ୍ପୂର୍ଣ୍ଣ ଭାବରେ ଚାର୍ଜ ହୋ‍ଇଗଲା"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହେଉଛି"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"ଗୋଟିଏ ତ୍ରୁଟି କାରଣରୁ eSIMକୁ ଅକ୍ଷମ କରାଯାଇପାରିବ ନାହିଁ।"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"ଏଣ୍ଟର୍"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ପାଟର୍ନ ଭୁଲି ଯାଇଛନ୍ତି"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ଭୁଲ ପାଟର୍ନ"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"ଭୁଲ ପାସୱର୍ଡ"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"ଭୁଲ ପାଟର୍ନ"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"ଭୁଲ ପାସ୍‌ୱର୍ଡ"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"ଭୁଲ PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</item>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index 498151c..08245dc 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪਿੰਨ ਟਾਈਪ ਕਰੋ"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"ਆਪਣਾ ਪਿੰਨ ਦਾਖਲ ਕਰੋ"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"ਆਪਣਾ ਪੈਟਰਨ ਦਾਖਲ ਕਰੋ"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"ਆਪਣਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"ਆਪਣਾ ਪੈਟਰਨ ਦਾਖਲ ਕਰੋ"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ਆਪਣਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ਗਲਤ ਪਿੰਨ ਕੋਡ।"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"ਅਵੈਧ ਕਾਰਡ।"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"ਚਾਰਜ ਹੋ ਗਿਆ"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"ਪੂਰਾ ਚਾਰਜ"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"ਕੋਈ ਗੜਬੜ ਹੋਣ ਕਰਕੇ ਈ-ਸਿਮ ਬੰਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"ਦਾਖਲ ਕਰੋ"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ਪੈਟਰਨ ਭੁੱਲ ਗਏ"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ਗਲਤ ਪੈਟਰਨ"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"ਗਲਤ ਪਾਸਵਰਡ"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"ਗਲਤ ਪੈਟਰਨ"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"ਗਲਤ ਪਾਸਵਰਡ"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"ਗਲਤ ਪਿੰਨ"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> ਸਕਿੰਟ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</item>
@@ -140,10 +140,8 @@
       <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</item>
       <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="one">ਸਿਮ ਪਿੰਨ ਦਾਖਲ ਕਰੋ। ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
       <item quantity="other">ਸਿਮ ਪਿੰਨ ਦਾਖਲ ਕਰੋ। ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ਾਂ ਬਾਕੀ ਹਨ।</item>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 538135f..49792e2 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Wpisz hasło, aby odblokować"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Wpisz kod PIN, aby odblokować"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Wpisz kod PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Narysuj wzór"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Wpisz hasło"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Narysuj wzór"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Wpisz hasło"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Nieprawidłowy kod PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Nieprawidłowa karta."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Naładowana"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Bateria w pełni naładowana"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Nie można wyłączyć karty eSIM z powodu błędu."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Nie pamiętam wzoru"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Nieprawidłowy wzór"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Nieprawidłowe hasło"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Nieprawidłowy wzór"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Nieprawidłowe hasło"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Nieprawidłowy kod PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="few">Spróbuj ponownie za <xliff:g id="NUMBER">%d</xliff:g> sekundy.</item>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index 13508b7..862b964a 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Digite a senha para desbloquear"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Insira o PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Digite seu PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Digite seu padrão"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Digite sua senha"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Digite seu padrão"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Digite sua senha"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorreto."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Cartão inválido."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Carregada"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Carga completa"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Não é possível desativar o eSIM devido a um erro."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Inserir"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Esqueci o padrão"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Padrão incorreto"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Senha incorreta"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Padrão incorreto"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Senha incorreta"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN incorreto"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundo.</item>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index c87799a..321b898 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Introduza a palavra-passe para desbloquear"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Introduza o PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Introduza o PIN."</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Introduza o padrão."</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Introduza a palavra-passe."</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Introduza o padrão."</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introduza a palavra-passe."</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorreto."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Cartão inválido."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Carregada"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Totalmente carregada"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar…"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Não é possível desativar o eSIM devido a um erro."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Tecla Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Esqueceu-se do padrão"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Padrão incorreto"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Palavra-passe incorreta"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Padrão incorreto."</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Palavra-passe incorreta."</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN incorreto"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index 13508b7..862b964a 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Digite a senha para desbloquear"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Insira o PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Digite seu PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Digite seu padrão"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Digite sua senha"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Digite seu padrão"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Digite sua senha"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Código PIN incorreto."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Cartão inválido."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Carregada"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Carga completa"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Não é possível desativar o eSIM devido a um erro."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Inserir"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Esqueci o padrão"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Padrão incorreto"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Senha incorreta"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Padrão incorreto"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Senha incorreta"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN incorreto"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundo.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index 3741157..083adbd 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Introduceți parola pentru a debloca"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Introduceți codul PIN pentru a debloca"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Introduceți codul PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Introduceți modelul"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Introduceți parola"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Introduceți modelul"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Introduceți parola"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Cod PIN incorect."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Card nevalid"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Încărcată"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Complet încărcată"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Cardul eSIM nu poate fi dezactivat din cauza unei erori."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Introduceți"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Ați uitat modelul"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Model greșit"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Parolă greșită"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Model greșit"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Parolă greșită"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Cod PIN greșit"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="few">Încercați din nou în <xliff:g id="NUMBER">%d</xliff:g> secunde.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index 5fc9af7..e5b1d0e 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Введите пароль"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Введите PIN-код для разблокировки"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Введите PIN-код"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Введите графический ключ"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Введите пароль"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Введите графический ключ"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Введите пароль"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Неверный PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ошибка SIM-карты."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Батарея заряжена"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Аккумулятор полностью заряжен"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"Идет зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Не удалось отключить eSIM."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Клавиша ввода"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Забыли графический ключ?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Неверный графический ключ"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Неверный пароль"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Неверный графический ключ"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Неверный пароль"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Неверный PIN-код"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Повторите попытку через <xliff:g id="NUMBER">%d</xliff:g> секунду.</item>
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index dd99e8b..1955edd 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"අගුළු ඇරීමට මුරපදය ටයිප් කරන්න"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"අගුළු හැරීමට PIN එක ටයිප් කරන්න"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"ඔබේ PIN ඇතුළු කරන්න"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"ඔබගේ රටාව ඇතුළු කරන්න"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"ඔබගේ මුරපදය ඇතුළු කරන්න"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"ඔබගේ රටාව ඇතුළු කරන්න"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ඔබේ මුරපදය ඇතුළු කරන්න"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"වැරදි PIN කේතයකි."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"වලංගු නොවන කාඩ්පත."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"අරෝපිතයි"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"සම්පූර්ණයෙන් ආරෝපණය වී ඇත"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වෙමින්"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"දෝෂයක් හේතුවෙන් eSIM අබල කළ නොහැකිය."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"ඇතුල් කරන්න"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"රටාව අමතකයි"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"වැරදි රටාවකි"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"වැරදි මුරපදය"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"වැරදි රටාවකි"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"වැරදි මුරපදයකි"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN එක වැරදියි"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">තත්පර <xliff:g id="NUMBER">%d</xliff:g>කින් නැවත උත්සාහ කරන්න.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index 868e0f6..f9f39e5 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Zadajte heslo na odomknutie"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Zadajte kód PIN na odomknutie"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Zadajte PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Zadajte vzor"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Zadajte heslo"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Zadajte vzor"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Zadajte heslo"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Nesprávny kód PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Neplatná karta."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Nabité"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Úplne nabité"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM karta sa nedá deaktivovať, pretože sa vyskytla chyba."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Nepamätám si vzor"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Nesprávny vzor"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Nesprávne heslo"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Nesprávny vzor"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Nesprávne heslo"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Nesprávny kód PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="few">Skúste to znova o <xliff:g id="NUMBER">%d</xliff:g> sekundy.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index 9be4dbd..2a4417c 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Vnesite geslo za odklepanje"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Vnesite kodo PIN za odklepanje"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Vnesite kodo PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Vnesite vzorec"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Vnesite geslo"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Vnesite vzorec"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Vnesite geslo"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Napačna koda PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Neveljavna kartica"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Akumulator napolnjen"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Popolnoma napolnjen"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Digitalne kartice e-SIM zaradi napake ni mogoče onemogočiti."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Tipka Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Pozabljen vzorec"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Napačen vzorec"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Napačno geslo"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Napačen vzorec"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Napačno geslo"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Napačna koda PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Poskusite znova čez <xliff:g id="NUMBER">%d</xliff:g> sekundo.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index e92b9b6..4057e03 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Shkruaj fjalëkalimin për të shkyçur"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Shkruaj kodin PIN për ta shkyçur"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Fut kodin PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Fut motivin"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Fut fjalëkalimin"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Fut motivin"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Fut fjalëkalimin"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Kodi PIN është i pasaktë."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Karta e pavlefshme."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"I ngarkuar"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"I ngarkuar plotësisht"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po ngarkohet"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po ngarkohet me shpejtësi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po ngarkohet ngadalë"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Karta eSIM nuk mund të çaktivizohet për shkak të një gabimi."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Dërgo"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Harrova motivin"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Motivi është i gabuar"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Fjalëkalim i gabuar"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Motiv i gabuar"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Fjalëkalim i gabuar"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Kod PIN i gabuar"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Provo sërish për <xliff:g id="NUMBER">%d</xliff:g> sekonda.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index b146603..16c1bde 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Унесите лозинку да бисте откључали"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Унесите PIN за откључавање"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Унесите PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Унесите шаблон"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Унесите лозинку"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Унесите шаблон"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Унесите лозинку"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN кôд је нетачан."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Неважећа картица."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Напуњена је"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Напуњена је у потпуности"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуни се"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"eSIM не може да се онемогући због грешке."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Заборавио/ла сам шаблон"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Погрешан шаблон"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Погрешна лозинка"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Погрешан шаблон"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Погрешна лозинка"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Погрешан PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунду.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index ba5c346..8e75aa2 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Lås upp med lösenordet"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Lås upp med pinkoden"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Ange pinkoden"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Ange det grafiska lösenordet"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Ange lösenordet"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Ange det grafiska lösenordet"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Ange ditt lösenord"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Fel pinkod."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ogiltigt kort."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Laddat"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Fulladdad"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Det gick inte att inaktivera eSIM-kortet på grund av ett fel."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Retur"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Har du glömt ditt grafiska lösenord?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Fel grafiskt lösenord"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Fel lösenord"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Fel grafiskt lösenord"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Fel lösenord"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Fel pinkod"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Försök igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder.</item>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index 6376b61..e5277b2 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Andika nenosiri ili ufungue"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Andika PIN ili ufungue"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Weka PIN yako"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Weka Mchoro wako"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Weka Nenosiri lako"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Weka mchoro wako"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Weka nenosiri lako"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Nambari ya PIN si sahihi."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Kadi si Sahihi."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Betri imejaa"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Imejaa chaji"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Hitilafu imetokea wakati wa kuzima eSIM."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Weka"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Umesahau Mchoro"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Mchoro si Sahihi"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Nenosiri si Sahihi"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Mchoro si sahihi"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Nenosiri si sahihi"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Nambari ya PIN si sahihi"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Jaribu tena baada ya sekunde <xliff:g id="NUMBER">%d</xliff:g>.</item>
@@ -140,7 +140,7 @@
       <item quantity="other">Hujafungua kifaa kwa saa <xliff:g id="NUMBER_1">%d</xliff:g>. Thibitisha nenosiri.</item>
       <item quantity="one">Hujafungua kifaa kwa saa <xliff:g id="NUMBER_0">%d</xliff:g>. Thibitisha nenosiri.</item>
     </plurals>
-    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"Haikutambua alama ya kidole"</string>
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"Haitambuliwi"</string>
     <string name="kg_face_not_recognized" msgid="6382535088345875294">"Haitambuliwi"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="other">Weka PIN ya SIM. Zimesalia mara <xliff:g id="NUMBER_1">%d</xliff:g> za kujaribu.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index 44968c3..f5fb357 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"திறக்க, கடவுச்சொல்லை உள்ளிடவும்"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"திறக்க, பின்னை உள்ளிடவும்"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"பின்னை உள்ளிடுக"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"பேட்டர்னை உள்ளிடுக"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"கடவுச்சொல்லை உள்ளிடுக"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"பேட்டர்னை உள்ளிடுக"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"கடவுச்சொல்லை உள்ளிடுக"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"தவறான பின் குறியீடு."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"செல்லாத சிம் கார்டு."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"சார்ஜ் செய்யப்பட்டது"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"முழுவதுமாகச் சார்ஜ் ஆகிவிட்டது"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"பிழை ஏற்பட்டதால் eSIMஐ முடக்க முடியவில்லை."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"என்டர் பொத்தான்"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"பேட்டர்ன் நினைவில்லையா"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"தவறான பேட்டர்ன்"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"தவறான கடவுச்சொல்"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"தவறான பேட்டர்ன்"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"தவறான கடவுச்சொல்"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"தவறான பின்"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> வினாடிகளுக்குப் பிறகு முயலவும்.</item>
@@ -140,10 +140,8 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> மணிநேரமாகச் சாதனம் திறக்கப்படவில்லை. கடவுச்சொல்லை உறுதிப்படுத்தவும்.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> மணிநேரமாகச் சாதனம் திறக்கப்படவில்லை. கடவுச்சொல்லை உறுதிப்படுத்தவும்.</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"அடையாளங்காணபடவில்லை"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"அடையாளங்காணபடவில்லை"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="other">சிம் பின்னை உள்ளிடவும். மேலும், <xliff:g id="NUMBER_1">%d</xliff:g> வாய்ப்புகள் மீதமுள்ளன.</item>
       <item quantity="one">சிம் பின்னை உள்ளிடவும். மீதமுள்ள <xliff:g id="NUMBER_0">%d</xliff:g> வாய்ப்பில் தவறுதலான பின் உள்ளிடப்பட்டால், உங்கள் தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்பு கொண்டு மட்டுமே சாதனத்தைத் திறக்க முடியும்.</item>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index 2597a55..1e08177 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"అన్‌లాక్ చేయడానికి పాస్‌వర్డ్‌ను టైప్ చేయండి"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"అన్‌లాక్ చేయడానికి పిన్ టైప్ చేయండి"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"మీ పిన్‌ని నమోదు చేయండి"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"మీ ఆకృతిని నమోదు చేయండి"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"మీ పాస్‌వర్డ్‌ను నమోదు చేయండి"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"మీ నమూనాను నమోదు చేయండి"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"మీ పాస్‌వర్డ్‌ను నమోదు చేయండి"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"పిన్ కోడ్ తప్పు."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"చెల్లని కార్డ్."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"ఛార్జ్ చేయబడింది"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"పూర్తిగా ఛార్జ్ చేయబడింది"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"ఎర్రర్ కారణంగా eSIMని నిలపడం సాధ్యపడదు."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"నమూనాను మర్చిపోయాను"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"ఆకృతి తప్పు"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"పాస్‌వర్డ్ తప్పు"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"నమూనా తప్పు"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"పాస్‌వర్డ్ తప్పు"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"పిన్ తప్పు"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి.</item>
@@ -140,10 +140,8 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> గంటల పాటు పరికరాన్ని అన్‌లాక్ చేయలేదు. పాస్‌వర్డ్‌ని నమోదు చేయండి.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> గంట పాటు పరికరాన్ని అన్‌లాక్ చేయలేదు. పాస్‌వర్డ్‌ని నమోదు చేయండి.</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"గుర్తించలేదు"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"గుర్తించలేదు"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="other">SIM పిన్‌ని నమోదు చేయండి. మీకు <xliff:g id="NUMBER_1">%d</xliff:g> ప్రయత్నలు మిగిలి ఉన్నాయి.</item>
       <item quantity="one">SIM పిన్‌ని నమోదు చేయండి, మీరు మీ పరికరాన్ని అన్‌లాక్ చేయడానికి తప్పనిసరిగా మీ క్యారియర్‌ను సంప్రదించడానికి ముందు మీకు <xliff:g id="NUMBER_0">%d</xliff:g> ప్రయత్నం మిగిలి ఉంది.</item>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index 52d7f1f..bde50f3 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"พิมพ์รหัสผ่านเพื่อปลดล็อก"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"พิมพ์ PIN เพื่อปลดล็อก"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"ป้อน PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"ป้อนรูปแบบ"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"ป้อนรหัสผ่าน"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"ป้อนรูปแบบ"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"ป้อนรหัสผ่าน"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"รหัส PIN ไม่ถูกต้อง"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"การ์ดไม่ถูกต้อง"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"ชาร์จแล้ว"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"ชาร์จเต็มแล้ว"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"ปิดใช้ eSIM ไม่ได้เนื่องจากมีข้อผิดพลาด"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ลืมรูปแบบ"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"รูปแบบไม่ถูกต้อง"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"รหัสผ่านไม่ถูกต้อง"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"รูปแบบไม่ถูกต้อง"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"รหัสผ่านไม่ถูกต้อง"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN ไม่ถูกต้อง"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">ลองอีกครั้งใน <xliff:g id="NUMBER">%d</xliff:g> วินาที</item>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index eb4f2ca0..71a7537 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"I-type ang password upang i-unlock"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"I-type ang PIN upang i-unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Ilagay ang iyong PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Ilagay ang iyong Pattern"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Ilagay ang iyong Password"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Ilagay ang iyong pattern"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Ilagay ang iyong password"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Mali ang PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Di-wasto ang Card."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Tapos nang mag-charge"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Puno na ang baterya"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nagcha-charge"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Hindi ma-disable ang eSIM dahil sa isang error."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Nakalimutan ang Pattern"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Mali ang Pattern"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Mali ang Password"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Mali ang pattern"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Mali ang password"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Mali ang PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Subukang muli sa loob ng <xliff:g id="NUMBER">%d</xliff:g> segundo.</item>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index a7d870a..fbbf63e 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Kilidi açmak için şifreyi yazın"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Kilidi açmak için PIN kodunu yazın"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"PIN kodunuzu girin"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Deseninizi girin"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Şifrenizi girin"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Deseninizi girin"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Şifrenizi girin"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Yanlış PIN kodu."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Geçersiz Kart."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Ödeme alındı"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Tamamen şarj edildi"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj oluyor"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Bir hata nedeniyle eSIM devre dışı bırakılamıyor."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Deseni unuttunuz mu?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Yanlış Desen"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Yanlış Şifre"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Yanlış desen"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Yanlış şifre"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Yanlış PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> saniye içinde tekrar deneyin.</item>
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index 5f5bfc3..feab22f 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Введіть пароль, щоб розблокувати"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Введіть PIN-код, щоб розблокувати"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Введіть PIN-код"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Введіть ключ"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Введіть пароль"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Введіть ключ"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Введіть пароль"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Неправильний PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Недійсна картка."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Заряджено"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Повністю заряджений"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Не вдається вимкнути eSIM-карту через помилку."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Ввести"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Не пам’ятаю ключ"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Неправильний ключ"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Неправильний пароль"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Неправильний ключ"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Неправильний пароль"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Неправильний PIN-код"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Повторіть спробу через <xliff:g id="NUMBER">%d</xliff:g> секунду.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 3e7aaee..928fcbdb 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"غیر مقفل کرنے کیلئے پاس ورڈ ٹائپ کریں"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"‏غیر مقفل کرنے کیلئے PIN ٹائپ کریں"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"‏اپنا PIN درج کریں"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"اپنا پیٹرن درج کریں"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"اپنا پاس ورڈ درج کریں"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"اپنا پیٹرن درج کریں"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"اپنا پاس ورڈ درج کریں"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"‏غلط PIN کوڈ۔"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"غلط کارڈ۔"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"چارج ہوگئی"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"مکمل طور پر چارج ہو گيا"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"‏ایک خرابی کی وجہ سے eSIM کو غیر فعال نہیں کیا جا سکتا۔"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"درج کریں"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"پیٹرن بھول گئے"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"غلط پیٹرن"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"غلط پاسورڈ"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"غلط پیٹرن"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"غلط پاس ورڈ"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"‏غلط PIN"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> سیکنڈز میں دوبارہ کوشش کریں۔</item>
@@ -140,10 +140,8 @@
       <item quantity="other">آلہ <xliff:g id="NUMBER_1">%d</xliff:g> گھنٹوں سے غیر مقفل نہیں کیا گيا۔ پاسورڈ کی توثیق کریں۔</item>
       <item quantity="one">آلہ <xliff:g id="NUMBER_0">%d</xliff:g> گھنٹہ سے غیر مقفل نہیں کیا گیا۔ پاسورڈ کی توثیق کریں۔</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"تسلیم شدہ نہیں ہے"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"تسلیم شدہ نہیں ہے"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="other">‏SIM کا PIN درج کریں، آپ کے پاس <xliff:g id="NUMBER_1">%d</xliff:g> کوششیں بچی ہیں۔</item>
       <item quantity="one">‏SIM کا PIN درج کریں، آپ کے پاس <xliff:g id="NUMBER_0">%d</xliff:g> کوشش بچی ہے، اس کے بعد آپ کو اپنا آلہ غیر مقفل کرنے کے لیے اپنے کیریئر سے رابطہ کرنا ہوگا۔</item>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 277fa8b..faa7d50 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -29,11 +29,13 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Qulfni ochish uchun parolni kiriting"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Qulfni ochish uchun PIN kodni kiriting"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"PIN kodni kiriting"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Grafik kalitni chizing"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Parolni kiriting"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Grafik kalitni chizing"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Parolni kiriting"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kodi xato."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"SIM karta yaroqsiz."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Batareya quvvati to‘ldi"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for keyguard_charged (3316115607283493413) -->
+    <skip />
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string>
@@ -61,8 +63,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Xatolik tufayli eSIM faolsizlantirilmadi."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter tugmasi"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Grafik kalit esimdan chiqdi"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Grafik kalit xato"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Parol xato"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Grafik kalit xato"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Parol xato"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN kod xato"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> soniyadan keyin qaytadan urining.</item>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index d851ceb..6b06513 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Nhập mật khẩu để mở khóa"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Nhập mã PIN để mở khóa"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Nhập mã PIN của bạn"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Nhập hình mở khóa của bạn"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Nhập mật khẩu của bạn"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Nhập hình mở khóa của bạn"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Nhập mật khẩu của bạn"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Mã PIN không chính xác."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Thẻ không hợp lệ."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Đã sạc đầy"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Đã sạc đầy"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"Không thể tắt eSIM do lỗi."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Nhập"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Đã quên hình mở khóa"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Hình mở khóa sai"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Mật khẩu sai"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Hình mở khóa sai"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Mật khẩu sai"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Mã PIN sai"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">Hãy thử lại sau <xliff:g id="NUMBER">%d</xliff:g> giây.</item>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index 693a31b..44f06a6 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"输入密码即可解锁"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"输入 PIN 码即可解锁"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"输入您的 PIN 码"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"绘制您的图案"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"输入您的密码"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"绘制您的图案"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"输入您的密码"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN 码有误。"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"SIM 卡无效。"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"已充满电"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"充电完成"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"出现错误,无法停用 eSIM 卡。"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"输入"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"忘记了图案"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"图案错误"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"密码错误"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"图案错误"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"密码错误"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN 码错误"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">请在 <xliff:g id="NUMBER">%d</xliff:g> 秒后重试。</item>
@@ -140,10 +140,8 @@
       <item quantity="other">设备已保持锁定状态达 <xliff:g id="NUMBER_1">%d</xliff:g> 小时。请确认密码。</item>
       <item quantity="one">设备已保持锁定状态达 <xliff:g id="NUMBER_0">%d</xliff:g> 小时。请确认密码。</item>
     </plurals>
-    <!-- no translation found for kg_fingerprint_not_recognized (7854413849848459418) -->
-    <skip />
-    <!-- no translation found for kg_face_not_recognized (6382535088345875294) -->
-    <skip />
+    <string name="kg_fingerprint_not_recognized" msgid="7854413849848459418">"无法识别"</string>
+    <string name="kg_face_not_recognized" msgid="6382535088345875294">"无法识别"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="3739658416797652781">
       <item quantity="other">请输入 SIM 卡 PIN 码,您还可以尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item>
       <item quantity="one">请输入 SIM 卡 PIN 码,您还可以尝试 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍不正确,则需要联系运营商帮您解锁设备。</item>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index 539bb92..364f126 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"輸入密碼即可解鎖"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"輸入 PIN 碼即可解鎖"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"請輸入 PIN"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"請輸入圖案"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"請輸入密碼"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"請畫出圖案"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"請輸入密碼"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN 碼不正確。"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"SIM 卡無效。"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"已完成充電"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"充電完成"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充電"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> •正在慢速充電"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"發生錯誤,因此無法停用此 eSIM 卡。"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter 鍵 (輸入)"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"忘記上鎖圖案"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"上鎖圖案錯誤"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"密碼錯誤"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"圖案錯誤"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"密碼錯誤"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN 碼錯誤"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">請在 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試一次。</item>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index 6e5e984..f687397 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"輸入密碼即可解鎖"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"輸入 PIN 碼即可解鎖"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"輸入 PIN 碼"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"輸入解鎖圖案"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"輸入密碼"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"畫出解鎖圖案"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"輸入密碼"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN 碼不正確。"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"卡片無效。"</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"充電完成"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"充電完成"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"發生錯誤,因此無法停用 eSIM 卡。"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter 鍵"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"忘記解鎖圖案"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"解鎖圖案錯誤"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"密碼錯誤"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"圖案錯誤"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"密碼錯誤"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN 碼錯誤"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="other">請於 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試一次。</item>
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index 78bb66c..66904eb 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -29,11 +29,11 @@
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Bhala iphasiwedi ukuze kuvuleke"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Faka i-PIN ukuvula"</string>
     <string name="keyguard_enter_your_pin" msgid="7152989016739952871">"Faka iPHINIKHODI yakho"</string>
-    <string name="keyguard_enter_your_pattern" msgid="3915717164691787047">"Faka iphethini yakho"</string>
-    <string name="keyguard_enter_your_password" msgid="5761514484663983731">"Faka iphasiwedi yakho"</string>
+    <string name="keyguard_enter_your_pattern" msgid="4297890206109830353">"Faka iphethini yakho"</string>
+    <string name="keyguard_enter_your_password" msgid="5397328359341314506">"Faka iphasiwedi yakho"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Ikhodi ye-PIN engalungile!"</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Ikhadi elingavumelekile."</string>
-    <string name="keyguard_charged" msgid="2222329688813033109">"Kushajiwe"</string>
+    <string name="keyguard_charged" msgid="3316115607283493413">"Ishaje ngokuphelele"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string>
@@ -61,8 +61,8 @@
     <string name="error_disable_esim_msg" msgid="676694908770135639">"I-eSIM ayikwakhi ukukhutshazwa ngenxa yephutha."</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Faka"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Ukhohlwe iphethini?"</string>
-    <string name="kg_wrong_pattern" msgid="7620081431514773802">"Iphatheni engalungile"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"Iphasiwedi engalungile"</string>
+    <string name="kg_wrong_pattern" msgid="2873443744087746812">"Iphethini engalungile"</string>
+    <string name="kg_wrong_password" msgid="8060364776224836597">"Iphasiwedi engalungile"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Iphinikhodi engalungile"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
       <item quantity="one">Zama futhi kumasekhondi angu-<xliff:g id="NUMBER">%d</xliff:g>.</item>
diff --git a/packages/SystemUI/res-keyguard/values/alias.xml b/packages/SystemUI/res-keyguard/values/alias.xml
index f06b450..1c63c79 100644
--- a/packages/SystemUI/res-keyguard/values/alias.xml
+++ b/packages/SystemUI/res-keyguard/values/alias.xml
@@ -25,9 +25,6 @@
     <!-- Alias used to reference framework "OK" string in keyguard.  -->
     <item type="string" name="ok">@*android:string/ok</item>
 
-    <!-- Alias used to reference framework "OK" string in keyguard.  -->
-    <item type="string" name="system_ui_date_pattern">@*android:string/system_ui_date_pattern</item>
-
     <!-- Alias used to reference framework configuration for screen rotation.  -->
     <item type="bool" name="config_enableLockScreenRotation">@*android:bool/config_enableLockScreenRotation</item>
 
diff --git a/packages/SystemUI/res-keyguard/values/attrs.xml b/packages/SystemUI/res-keyguard/values/attrs.xml
index e2ce210..293b683 100644
--- a/packages/SystemUI/res-keyguard/values/attrs.xml
+++ b/packages/SystemUI/res-keyguard/values/attrs.xml
@@ -38,9 +38,5 @@
         <attr name="android:textColor" format="color" />
     </declare-styleable>
 
-    <declare-styleable name="CarrierText">
-        <attr name="allCaps" format="boolean" />
-    </declare-styleable>
-
     <attr name="passwordStyle" format="reference" />
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 6bc0965..1d5aa6d 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -48,10 +48,10 @@
     <string name="keyguard_enter_your_pin">Enter your PIN</string>
 
     <!-- Instructions telling the user to enter their pattern to unlock the keyguard [CHAR LIMIT=30] -->
-    <string name="keyguard_enter_your_pattern">Enter your Pattern</string>
+    <string name="keyguard_enter_your_pattern">Enter your pattern</string>
 
     <!-- Instructions telling the user to enter their text password to unlock the keyguard [CHAR LIMIT=30] -->
-    <string name="keyguard_enter_your_password">Enter your Password</string>
+    <string name="keyguard_enter_your_password">Enter your password</string>
 
     <!-- Instructions telling the user that they entered the wrong pin while trying
          to unlock the keyguard.  Displayed in one line in a large font.  -->
@@ -62,7 +62,7 @@
 
     <!-- When the lock screen is showing, the phone is plugged in and the battery is fully
          charged, say that it is charged. -->
-    <string name="keyguard_charged">Charged</string>
+    <string name="keyguard_charged">Fully charged</string>
 
     <!-- When the lock screen is showing and the phone plugged in, and the battery
          is not fully charged, say that it's charging.  -->
@@ -146,9 +146,9 @@
     <!-- Message shown in pattern unlock after some number of unsuccessful attempts -->
     <string name="kg_forgot_pattern_button_text">Forgot Pattern</string>
     <!-- Message shown when user enters wrong pattern -->
-    <string name="kg_wrong_pattern">Wrong Pattern</string>
+    <string name="kg_wrong_pattern">Wrong pattern</string>
     <!-- Message shown when user enters wrong password -->
-    <string name="kg_wrong_password">Wrong Password</string>
+    <string name="kg_wrong_password">Wrong password</string>
     <!-- Message shown when user enters wrong PIN -->
     <string name="kg_wrong_pin">Wrong PIN</string>
     <!-- Countdown message shown after too many failed unlock attempts -->
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_01_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_01_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_01_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_02_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_02_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_02_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_03_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_03_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_03_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_04_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_04_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_04_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_05_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_05_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_05_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_06_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_06_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_06_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_07_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_07_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_07_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_08_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_08_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_08_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_09_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_09_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_09_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_10_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_10_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_10_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_11_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_11_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_11_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_12_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_12_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_12_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_13_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_13_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_13_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_14_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_14_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_14_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_15_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_15_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_15_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_16_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_16_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_16_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_17_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_17_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_17_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging__dot_18_pivot_animation.xml b/packages/SystemUI/res/anim/wireless_charging__dot_18_pivot_animation.xml
new file mode 100644
index 0000000..fd5561b
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging__dot_18_pivot_animation.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:pathData="M 0.0,-25.0 c 0.0,-11.16667 0.0,-55.83333 0.0,-67.0"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_1" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_10_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_10_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_10_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_11_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_11_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_11_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_12_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_12_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_12_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_13_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_13_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_13_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_14_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_14_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_14_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_15_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_15_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_15_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_16_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_16_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_16_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_17_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_17_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_17_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_18_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_18_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_18_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_1_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_1_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_1_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_2_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_2_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_2_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_3_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_3_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_3_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_4_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_4_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_4_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_5_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_5_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_5_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_6_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_6_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_6_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_7_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_7_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_7_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_8_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_8_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_8_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_ellipse_path_9_animation.xml b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_9_animation.xml
new file mode 100644
index 0000000..d20e741
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_ellipse_path_9_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="pathData"
+        android:valueFrom="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-3.5 c 1.9329966243,0.0 3.5,1.5670033757 3.5,3.5 c 0.0,1.9329966243 -1.5670033757,3.5 -3.5,3.5 c -1.9329966243,0.0 -3.5,-1.5670033757 -3.5,-3.5 c 0.0,-1.9329966243 1.5670033757,-3.5 3.5,-3.5 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/wireless_charging_animation_interpolator_0" />
+</set>
diff --git a/packages/SystemUI/res/anim/wireless_charging_null_1_animation.xml b/packages/SystemUI/res/anim/wireless_charging_null_1_animation.xml
new file mode 100644
index 0000000..fffae80
--- /dev/null
+++ b/packages/SystemUI/res/anim/wireless_charging_null_1_animation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="1166"
+        android:propertyName="rotation"
+        android:valueFrom="0.0"
+        android:valueTo="20.0"
+        android:valueType="floatType"
+        android:interpolator="@android:interpolator/linear" />
+</set>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml b/packages/SystemUI/res/color-night/qs_detail_progress_track.xml
similarity index 100%
rename from packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml
rename to packages/SystemUI/res/color-night/qs_detail_progress_track.xml
diff --git a/packages/SystemUI/res/color/notification_guts_buttons.xml b/packages/SystemUI/res/color/notification_guts_buttons.xml
index 3b8d59b..412e0be 100644
--- a/packages/SystemUI/res/color/notification_guts_buttons.xml
+++ b/packages/SystemUI/res/color/notification_guts_buttons.xml
@@ -2,6 +2,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_checked="true"
           android:color="?android:attr/colorAccent" />
-    <item android:color="@android:color/black"
+    <item android:color="@color/notification_primary_text_color"
           android:alpha=".54" />
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_carmode.png
deleted file mode 100644
index 95e5778..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_carmode.png
deleted file mode 100644
index 6421146..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_carmode.png
deleted file mode 100644
index 151d5fe..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_carmode.png
deleted file mode 100644
index b954aa7..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_carmode.png
deleted file mode 100644
index 61d5db6..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_carmode.png
deleted file mode 100644
index 7b98c1f..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_carmode.png
deleted file mode 100644
index aad1320..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_carmode.png
deleted file mode 100644
index 754b2d9..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_carmode.png
deleted file mode 100644
index 873ed7f..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_carmode.png
deleted file mode 100644
index 7696d87..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_carmode.png
deleted file mode 100644
index c98f55e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_carmode.png
deleted file mode 100644
index 187a566..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_carmode.png
deleted file mode 100644
index c66f8be..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_carmode.png
deleted file mode 100644
index 3a3a119..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_carmode.png
deleted file mode 100644
index 7198c82..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_carmode.png
deleted file mode 100644
index b1fc02e..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_carmode.png
deleted file mode 100644
index c06bfda..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_carmode.png
deleted file mode 100644
index a8c76bf..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_carmode.png
deleted file mode 100644
index b798e3d..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_carmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/faster_emergency_icon.xml b/packages/SystemUI/res/drawable/faster_emergency_icon.xml
deleted file mode 100644
index 208ff41..0000000
--- a/packages/SystemUI/res/drawable/faster_emergency_icon.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-Copyright (C) 2018 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<!-- TODO: For demo only, will change content after UI team provide new faster emergency icon. -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?attr/colorControlNormal">
-    <path
-        android:fillColor="#D93025"
-        android:pathData="M0,0h24v24H0z" />
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19,3H5c-1.1,0-1.99,0.9,-1.99,2L3,19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2zm-1,11h-4v4h-4v-4H6v-4h4V6h4v4h4v4z" />
-
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back_carmode.xml b/packages/SystemUI/res/drawable/ic_sysbar_back_carmode.xml
new file mode 100644
index 0000000..5844b2e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_back_carmode.xml
@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="44dp"
+        android:height="44dp"
+        android:viewportWidth="44.0"
+        android:viewportHeight="44.0">
+    <path
+        android:pathData="M9,22.06C9,21.22 9.51,20.42 10.36,19.95L31.56,7.87C32.57,7.3 33.42,7.49 33.89,7.75C34.92,8.33 35,9.44 35,9.91L35,34.09C35,34.65 34.92,35.69 33.91,36.25C33.46,36.51 32.66,36.69 31.67,36.14L10.26,24.05C9.49,23.61 9,22.87 9,22.06L9,22.06ZM31.5,12L13.5,22.04L31.5,32L31.5,12Z"
+        android:strokeColor="#00000000"
+        android:fillType="evenOdd"
+        android:fillColor="#F8F9FA"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_home.xml b/packages/SystemUI/res/drawable/ic_sysbar_home.xml
index a960af7..da23937 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_home.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_home.xml
@@ -14,13 +14,13 @@
      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="oval"
-    android:useLevel="false">
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="28dp"
+    android:height="28dp"
+    android:viewportWidth="28"
+    android:viewportHeight="28">
 
-    <solid android:color="?attr/singleToneColor" />
-
-    <size
-        android:height="14dp"
-        android:width="14dp" />
-</shape>
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M 14 7 C 17.8659932488 7 21 10.1340067512 21 14 C 21 17.8659932488 17.8659932488 21 14 21 C 10.1340067512 21 7 17.8659932488 7 14 C 7 10.1340067512 10.1340067512 7 14 7 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_home_carmode.xml b/packages/SystemUI/res/drawable/ic_sysbar_home_carmode.xml
new file mode 100644
index 0000000..e07bf6f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_home_carmode.xml
@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="44dp"
+        android:height="44dp"
+        android:viewportWidth="44.0"
+        android:viewportHeight="44.0">
+    <path
+        android:pathData="M22.39,22.39m-14.54,0a14.54,14.54 0,1 1,29.07 0a14.54,14.54 0,1 1,-29.07 0"
+        android:fillType="evenOdd"
+        android:strokeColor="#F8F9FA"
+        android:fillColor="#00000000"
+        android:strokeWidth="4"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/wireless_charging.xml b/packages/SystemUI/res/drawable/wireless_charging.xml
new file mode 100644
index 0000000..0bf633a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/wireless_charging.xml
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:name="wireless_charging"
+    android:width="200dp"
+    android:viewportWidth="200"
+    android:height="200dp"
+    android:viewportHeight="200" >
+    <group
+        android:name="null_1"
+        android:translateX="100"
+        android:translateY="100" >
+        <group
+            android:name="dot_01" >
+            <group
+                android:name="dot_01_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_1" >
+                    <path
+                        android:name="ellipse_path_1"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_02"
+            android:rotation="20" >
+            <group
+                android:name="dot_02_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_2" >
+                    <path
+                        android:name="ellipse_path_2"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_03"
+            android:rotation="40" >
+            <group
+                android:name="dot_03_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_3" >
+                    <path
+                        android:name="ellipse_path_3"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_04"
+            android:rotation="60" >
+            <group
+                android:name="dot_04_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_4" >
+                    <path
+                        android:name="ellipse_path_4"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_05"
+            android:rotation="80" >
+            <group
+                android:name="dot_05_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_5" >
+                    <path
+                        android:name="ellipse_path_5"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_06"
+            android:rotation="100" >
+            <group
+                android:name="dot_06_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_6" >
+                    <path
+                        android:name="ellipse_path_6"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_07"
+            android:rotation="120" >
+            <group
+                android:name="dot_07_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_7" >
+                    <path
+                        android:name="ellipse_path_7"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_08"
+            android:rotation="140" >
+            <group
+                android:name="dot_08_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_8" >
+                    <path
+                        android:name="ellipse_path_8"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_09"
+            android:rotation="160" >
+            <group
+                android:name="dot_09_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_9" >
+                    <path
+                        android:name="ellipse_path_9"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_10"
+            android:rotation="180" >
+            <group
+                android:name="dot_10_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_10" >
+                    <path
+                        android:name="ellipse_path_10"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_11"
+            android:rotation="200" >
+            <group
+                android:name="dot_11_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_11" >
+                    <path
+                        android:name="ellipse_path_11"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_12"
+            android:rotation="220" >
+            <group
+                android:name="dot_12_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_12" >
+                    <path
+                        android:name="ellipse_path_12"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_13"
+            android:rotation="240" >
+            <group
+                android:name="dot_13_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_13" >
+                    <path
+                        android:name="ellipse_path_13"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_14"
+            android:rotation="260" >
+            <group
+                android:name="dot_14_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_14" >
+                    <path
+                        android:name="ellipse_path_14"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_15"
+            android:rotation="280" >
+            <group
+                android:name="dot_15_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_15" >
+                    <path
+                        android:name="ellipse_path_15"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_16"
+            android:rotation="300" >
+            <group
+                android:name="dot_16_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_16" >
+                    <path
+                        android:name="ellipse_path_16"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_17"
+            android:rotation="320" >
+            <group
+                android:name="dot_17_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_17" >
+                    <path
+                        android:name="ellipse_path_17"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="dot_18"
+            android:rotation="340" >
+            <group
+                android:name="dot_18_pivot"
+                android:translateY="-25" >
+                <group
+                    android:name="ellipse_18" >
+                    <path
+                        android:name="ellipse_path_18"
+                        android:fillColor="?attr/chargingAnimColor"
+                        android:pathData="M 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/wireless_charging_animation.xml b/packages/SystemUI/res/drawable/wireless_charging_animation.xml
new file mode 100644
index 0000000..4cf13b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/wireless_charging_animation.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<animated-vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/wireless_charging" >
+    <target
+        android:name="null_1"
+        android:animation="@anim/wireless_charging_null_1_animation" />
+    <target
+        android:name="dot_01_pivot"
+        android:animation="@anim/wireless_charging__dot_01_pivot_animation" />
+    <target
+        android:name="ellipse_path_1"
+        android:animation="@anim/wireless_charging_ellipse_path_1_animation" />
+    <target
+        android:name="dot_02_pivot"
+        android:animation="@anim/wireless_charging__dot_02_pivot_animation" />
+    <target
+        android:name="ellipse_path_2"
+        android:animation="@anim/wireless_charging_ellipse_path_2_animation" />
+    <target
+        android:name="dot_03_pivot"
+        android:animation="@anim/wireless_charging__dot_03_pivot_animation" />
+    <target
+        android:name="ellipse_path_3"
+        android:animation="@anim/wireless_charging_ellipse_path_3_animation" />
+    <target
+        android:name="dot_04_pivot"
+        android:animation="@anim/wireless_charging__dot_04_pivot_animation" />
+    <target
+        android:name="ellipse_path_4"
+        android:animation="@anim/wireless_charging_ellipse_path_4_animation" />
+    <target
+        android:name="dot_05_pivot"
+        android:animation="@anim/wireless_charging__dot_05_pivot_animation" />
+    <target
+        android:name="ellipse_path_5"
+        android:animation="@anim/wireless_charging_ellipse_path_5_animation" />
+    <target
+        android:name="dot_06_pivot"
+        android:animation="@anim/wireless_charging__dot_06_pivot_animation" />
+    <target
+        android:name="ellipse_path_6"
+        android:animation="@anim/wireless_charging_ellipse_path_6_animation" />
+    <target
+        android:name="dot_07_pivot"
+        android:animation="@anim/wireless_charging__dot_07_pivot_animation" />
+    <target
+        android:name="ellipse_path_7"
+        android:animation="@anim/wireless_charging_ellipse_path_7_animation" />
+    <target
+        android:name="dot_08_pivot"
+        android:animation="@anim/wireless_charging__dot_08_pivot_animation" />
+    <target
+        android:name="ellipse_path_8"
+        android:animation="@anim/wireless_charging_ellipse_path_8_animation" />
+    <target
+        android:name="dot_09_pivot"
+        android:animation="@anim/wireless_charging__dot_09_pivot_animation" />
+    <target
+        android:name="ellipse_path_9"
+        android:animation="@anim/wireless_charging_ellipse_path_9_animation" />
+    <target
+        android:name="dot_10_pivot"
+        android:animation="@anim/wireless_charging__dot_10_pivot_animation" />
+    <target
+        android:name="ellipse_path_10"
+        android:animation="@anim/wireless_charging_ellipse_path_10_animation" />
+    <target
+        android:name="dot_11_pivot"
+        android:animation="@anim/wireless_charging__dot_11_pivot_animation" />
+    <target
+        android:name="ellipse_path_11"
+        android:animation="@anim/wireless_charging_ellipse_path_11_animation" />
+    <target
+        android:name="dot_12_pivot"
+        android:animation="@anim/wireless_charging__dot_12_pivot_animation" />
+    <target
+        android:name="ellipse_path_12"
+        android:animation="@anim/wireless_charging_ellipse_path_12_animation" />
+    <target
+        android:name="dot_13_pivot"
+        android:animation="@anim/wireless_charging__dot_13_pivot_animation" />
+    <target
+        android:name="ellipse_path_13"
+        android:animation="@anim/wireless_charging_ellipse_path_13_animation" />
+    <target
+        android:name="dot_14_pivot"
+        android:animation="@anim/wireless_charging__dot_14_pivot_animation" />
+    <target
+        android:name="ellipse_path_14"
+        android:animation="@anim/wireless_charging_ellipse_path_14_animation" />
+    <target
+        android:name="dot_15_pivot"
+        android:animation="@anim/wireless_charging__dot_15_pivot_animation" />
+    <target
+        android:name="ellipse_path_15"
+        android:animation="@anim/wireless_charging_ellipse_path_15_animation" />
+    <target
+        android:name="dot_16_pivot"
+        android:animation="@anim/wireless_charging__dot_16_pivot_animation" />
+    <target
+        android:name="ellipse_path_16"
+        android:animation="@anim/wireless_charging_ellipse_path_16_animation" />
+    <target
+        android:name="dot_17_pivot"
+        android:animation="@anim/wireless_charging__dot_17_pivot_animation" />
+    <target
+        android:name="ellipse_path_17"
+        android:animation="@anim/wireless_charging_ellipse_path_17_animation" />
+    <target
+        android:name="dot_18_pivot"
+        android:animation="@anim/wireless_charging__dot_18_pivot_animation" />
+    <target
+        android:name="ellipse_path_18"
+        android:animation="@anim/wireless_charging_ellipse_path_18_animation" />
+</animated-vector>
diff --git a/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_0.xml
new file mode 100644
index 0000000..3fe59ae
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_0.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.001,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_1.xml
new file mode 100644
index 0000000..3fe59ae
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/wireless_charging_animation_interpolator_1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.001,0.0 0.2,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/layout/app_ops_info.xml b/packages/SystemUI/res/layout/app_ops_info.xml
index 676301e..82a0115 100644
--- a/packages/SystemUI/res/layout/app_ops_info.xml
+++ b/packages/SystemUI/res/layout/app_ops_info.xml
@@ -15,7 +15,7 @@
     limitations under the License.
 -->
 
-<com.android.systemui.statusbar.AppOpsInfo
+<com.android.systemui.statusbar.notification.row.AppOpsInfo
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -88,4 +88,4 @@
             android:layout_marginEnd="-8dp"
             style="@style/TextAppearance.NotificationInfo.Button"/>
     </LinearLayout>
-</com.android.systemui.statusbar.AppOpsInfo>
+</com.android.systemui.statusbar.notification.row.AppOpsInfo>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index 8379dbb..ee8d357 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -28,7 +28,7 @@
     <ImageView android:id="@+id/user_avatar"
         android:layout_width="@dimen/car_user_switcher_image_avatar_size"
         android:layout_height="@dimen/car_user_switcher_image_avatar_size"
-        android:background="@drawable/car_button_ripple_background_inverse"
+        android:background="@drawable/car_button_ripple_background_light"
         android:gravity="center"/>
 
     <TextView android:id="@+id/user_name"
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index 37e2b53..c9f5148 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -38,8 +38,8 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_marginTop="@dimen/car_user_switcher_margin_top"
+            android:theme="@style/Theme.Car.Light.List"
             app:verticallyCenterListContent="true"
-            app:dayNightStyle="always_light"
             app:showPagedListViewDivider="false"
             app:gutter="both"
             app:itemSpacing="@dimen/car_user_switcher_vertical_spacing_between_users"/>
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index c43afc9..e7413de 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -39,7 +39,7 @@
             android:id="@+id/user_grid"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            app:dayNightStyle="always_light"
+            android:theme="@style/Theme.Car.Light.List"
             app:showPagedListViewDivider="false"
             app:gutter="both"
             app:itemSpacing="@dimen/car_user_switcher_vertical_spacing_between_users"/>
diff --git a/packages/SystemUI/res/layout/contextual.xml b/packages/SystemUI/res/layout/contextual.xml
index 94591e9..c8f0a24 100644
--- a/packages/SystemUI/res/layout/contextual.xml
+++ b/packages/SystemUI/res/layout/contextual.xml
@@ -20,6 +20,7 @@
              android:layout_width="@dimen/navigation_key_width"
              android:layout_height="match_parent"
              android:importantForAccessibility="no"
+             android:focusable="false"
              android:clipChildren="false"
              android:clipToPadding="false"
              >
diff --git a/packages/SystemUI/res/layout/hybrid_notification.xml b/packages/SystemUI/res/layout/hybrid_notification.xml
index 23e8a15..e8d7751 100644
--- a/packages/SystemUI/res/layout/hybrid_notification.xml
+++ b/packages/SystemUI/res/layout/hybrid_notification.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.statusbar.notification.HybridNotificationView
+<com.android.systemui.statusbar.notification.row.HybridNotificationView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -35,4 +35,4 @@
         android:singleLine="true"
         style="?attr/hybridNotificationTextStyle"
     />
-</com.android.systemui.statusbar.notification.HybridNotificationView>
\ No newline at end of file
+</com.android.systemui.statusbar.notification.row.HybridNotificationView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index 8e491dc..5b9816d 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -18,7 +18,7 @@
 <!-- Extends RelativeLayout -->
 <com.android.systemui.statusbar.phone.KeyguardStatusBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_header"
     android:layout_width="match_parent"
     android:layout_height="@dimen/status_bar_header_height_keyguard"
@@ -73,6 +73,8 @@
         android:textDirection="locale"
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:textColor="?attr/wallpaperTextColorSecondary"
-        android:singleLine="true" />
+        android:singleLine="true"
+        systemui:showMissingSim="true"
+        systemui:showAirplaneMode="true" />
 
 </com.android.systemui.statusbar.phone.KeyguardStatusBarView>
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 9130fb4..b047efb 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -17,13 +17,14 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/menu_container"
-    android:layout_width="match_parent"
+    android:layout_width="@dimen/navigation_key_width"
     android:layout_height="match_parent"
+    android:focusable="false"
     android:importantForAccessibility="no"
     >
-    <!-- Use width & height=match_parent for parent FrameLayout and buttons because they are placed
-    inside a view that has a size controlled by weight. Ensure weight is large enough to support
-    icon size. -->
+    <!-- Use nav button width & height=match_parent for parent FrameLayout and buttons because they
+    are placed inside a view that has a size controlled by weight. Ensure weight is large enough to
+    support icon size. -->
 
     <com.android.systemui.statusbar.policy.KeyButtonView
         android:id="@+id/menu"
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index baaf699..d72021e 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -18,14 +18,16 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:layout_marginStart="@dimen/rounded_corner_content_padding"
+    android:layout_marginEnd="@dimen/rounded_corner_content_padding"
+    android:paddingStart="@dimen/nav_content_padding"
+    android:paddingEnd="@dimen/nav_content_padding">
 
     <com.android.systemui.statusbar.phone.NearestTouchFrame
         android:id="@+id/nav_buttons"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:paddingStart="@dimen/rounded_corner_content_padding"
-        android:paddingEnd="@dimen/rounded_corner_content_padding"
         android:clipChildren="false"
         android:clipToPadding="false">
 
@@ -34,8 +36,6 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:orientation="horizontal"
-            android:paddingStart="@dimen/nav_content_padding"
-            android:paddingEnd="@dimen/nav_content_padding"
             android:clipToPadding="false"
             android:clipChildren="false" />
 
@@ -46,8 +46,6 @@
             android:layout_gravity="center"
             android:gravity="center"
             android:orientation="horizontal"
-            android:paddingStart="@dimen/nav_content_padding"
-            android:paddingEnd="@dimen/nav_content_padding"
             android:clipToPadding="false"
             android:clipChildren="false" />
 
diff --git a/packages/SystemUI/res/layout/navigation_layout_rot90.xml b/packages/SystemUI/res/layout/navigation_layout_rot90.xml
index 6d5b7788..24a0c71 100644
--- a/packages/SystemUI/res/layout/navigation_layout_rot90.xml
+++ b/packages/SystemUI/res/layout/navigation_layout_rot90.xml
@@ -18,14 +18,16 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:layout_marginTop="@dimen/rounded_corner_content_padding"
+    android:layout_marginBottom="@dimen/rounded_corner_content_padding"
+    android:paddingTop="@dimen/nav_content_padding"
+    android:paddingBottom="@dimen/nav_content_padding">
 
     <com.android.systemui.statusbar.phone.NearestTouchFrame
         android:id="@+id/nav_buttons"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:paddingTop="@dimen/rounded_corner_content_padding"
-        android:paddingBottom="@dimen/rounded_corner_content_padding"
         android:clipChildren="false"
         android:clipToPadding="false">
 
@@ -34,10 +36,8 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:orientation="vertical"
-            android:paddingTop="@dimen/nav_content_padding"
-            android:paddingBottom="@dimen/nav_content_padding"
-            android:clipChildren="false"
-            android:clipToPadding="false" />
+            android:clipToPadding="false"
+            android:clipChildren="false" />
 
         <com.android.systemui.statusbar.phone.ReverseLinearLayout
             android:id="@+id/center_group"
@@ -45,10 +45,8 @@
             android:layout_height="match_parent"
             android:gravity="center"
             android:orientation="vertical"
-            android:paddingTop="@dimen/nav_content_padding"
-            android:paddingBottom="@dimen/nav_content_padding"
-            android:clipChildren="false"
-            android:clipToPadding="false" />
+            android:clipToPadding="false"
+            android:clipChildren="false" />
 
     </com.android.systemui.statusbar.phone.NearestTouchFrame>
 
diff --git a/packages/SystemUI/res/layout/notification_children_container.xml b/packages/SystemUI/res/layout/notification_children_container.xml
index ac6a000..d3bb5d5 100644
--- a/packages/SystemUI/res/layout/notification_children_container.xml
+++ b/packages/SystemUI/res/layout/notification_children_container.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.statusbar.stack.NotificationChildrenContainer
+<com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" />
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index 9d8ef83..dc94697 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -15,7 +15,7 @@
     limitations under the License.
 -->
 
-<com.android.systemui.statusbar.NotificationGuts
+<com.android.systemui.statusbar.notification.row.NotificationGuts
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 28466fd..e1e812b 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -15,7 +15,7 @@
     limitations under the License.
 -->
 
-<com.android.systemui.statusbar.NotificationInfo
+<com.android.systemui.statusbar.notification.row.NotificationInfo
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/notification_guts"
     android:layout_width="match_parent"
@@ -161,7 +161,7 @@
                 style="@style/TextAppearance.NotificationInfo.Button"/>
         </LinearLayout>
     </LinearLayout>
-    <com.android.systemui.statusbar.NotificationUndoLayout
+    <com.android.systemui.statusbar.notification.row.NotificationUndoLayout
         android:id="@+id/confirmation"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -187,5 +187,5 @@
             android:layout_gravity="end|center_vertical"
             android:text="@string/inline_undo"
             style="@style/TextAppearance.NotificationInfo.Button"/>
-    </com.android.systemui.statusbar.NotificationUndoLayout>
-</com.android.systemui.statusbar.NotificationInfo>
+    </com.android.systemui.statusbar.notification.row.NotificationUndoLayout>
+</com.android.systemui.statusbar.notification.row.NotificationInfo>
diff --git a/packages/SystemUI/res/layout/notification_snooze.xml b/packages/SystemUI/res/layout/notification_snooze.xml
index ea6ef4c..ffe2eee 100644
--- a/packages/SystemUI/res/layout/notification_snooze.xml
+++ b/packages/SystemUI/res/layout/notification_snooze.xml
@@ -15,14 +15,14 @@
     limitations under the License.
 -->
 
-<com.android.systemui.statusbar.NotificationSnooze
+<com.android.systemui.statusbar.notification.row.NotificationSnooze
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
     android:clickable="true"
     android:background="@color/notification_guts_bg_color"
-    android:theme="@*android:style/Theme.DeviceDefault.Light">
+    android:theme="@style/Theme.SystemUI">
 
     <RelativeLayout
         android:id="@+id/notification_snooze"
@@ -36,7 +36,7 @@
             android:layout_alignParentStart="true"
             android:layout_centerVertical="true"
             android:paddingStart="@*android:dimen/notification_content_margin_start"
-            android:textColor="#DD000000"
+            android:textColor="?android:attr/textColorPrimary"
             android:paddingEnd="4dp"/>
 
         <ImageView
@@ -72,4 +72,4 @@
         android:paddingBottom="8dp"
         android:orientation="vertical" />
 
-</com.android.systemui.statusbar.NotificationSnooze>
+</com.android.systemui.statusbar.notification.row.NotificationSnooze>
diff --git a/packages/SystemUI/res/layout/notification_snooze_option.xml b/packages/SystemUI/res/layout/notification_snooze_option.xml
index aaf45f3..f203839 100644
--- a/packages/SystemUI/res/layout/notification_snooze_option.xml
+++ b/packages/SystemUI/res/layout/notification_snooze_option.xml
@@ -22,4 +22,4 @@
         android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
         android:gravity="center_vertical"
         android:textSize="14sp"
-        android:textColor="#DD000000"/>
\ No newline at end of file
+        android:textColor="?android:attr/textColorSecondary"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_customize_divider.xml b/packages/SystemUI/res/layout/qs_customize_divider.xml
index 51febc7..6fcfa8d 100644
--- a/packages/SystemUI/res/layout/qs_customize_divider.xml
+++ b/packages/SystemUI/res/layout/qs_customize_divider.xml
@@ -23,6 +23,6 @@
     android:gravity="center"
     android:paddingTop="20dp"
     android:paddingBottom="13dp"
-    android:textAppearance="@android:style/TextAppearance.Material.Body2"
+    android:textAppearance="@style/TextAppearance.QSEdit.Headers"
     android:textColor="?android:attr/colorAccent"
     android:text="@string/drag_to_add_tiles" />
diff --git a/packages/SystemUI/res/layout/qs_customize_header.xml b/packages/SystemUI/res/layout/qs_customize_header.xml
new file mode 100644
index 0000000..093f971
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_customize_header.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/title"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:minHeight="28dp"
+    android:textAppearance="@style/TextAppearance.QSEdit.Headers"
+    android:textColor="?android:attr/colorAccent"
+    android:text="@string/drag_to_rearrange_tiles" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
index 4ce6ef6..bb67c54 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
@@ -43,7 +43,6 @@
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:layout_weight="1"
-            android:paddingTop="28dp"
             android:paddingLeft="@dimen/qs_tile_layout_margin_side"
             android:paddingRight="@dimen/qs_tile_layout_margin_side"
             android:paddingBottom="28dp"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index bef0830..2674f07c 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -47,7 +47,7 @@
             android:clipChildren="false"
             systemui:viewType="com.android.systemui.plugins.qs.QS" />
 
-        <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+        <com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
             android:id="@+id/notification_stack_scroller"
             android:layout_marginTop="@dimen/notification_panel_margin_top"
             android:layout_width="@dimen/notification_panel_width"
diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
index 6c5cebc..056f16a 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
@@ -15,7 +15,7 @@
   -->
 
 <!-- Extends Framelayout -->
-<com.android.systemui.statusbar.FooterView
+<com.android.systemui.statusbar.notification.row.FooterView
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -26,7 +26,7 @@
         android:id="@+id/content"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" >
-        <com.android.systemui.statusbar.FooterViewButton
+        <com.android.systemui.statusbar.notification.row.FooterViewButton
             style="@android:style/Widget.Material.Button.Borderless"
             android:id="@+id/manage_text"
             android:layout_width="wrap_content"
@@ -36,7 +36,7 @@
             android:text="@string/manage_notifications_text"
             android:textColor="?attr/wallpaperTextColor"
             android:textAllCaps="false"/>
-        <com.android.systemui.statusbar.FooterViewButton
+        <com.android.systemui.statusbar.notification.row.FooterViewButton
             style="@android:style/Widget.Material.Button.Borderless"
             android:id="@+id/dismiss_text"
             android:layout_width="wrap_content"
@@ -47,4 +47,4 @@
             android:text="@string/clear_all_notifications_text"
             android:textColor="?attr/wallpaperTextColor"/>
     </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-</com.android.systemui.statusbar.FooterView>
+</com.android.systemui.statusbar.notification.row.FooterView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index f15ca9e..84b9e3d 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -16,7 +16,7 @@
 -->
 
 <!-- extends FrameLayout -->
-<com.android.systemui.statusbar.ExpandableNotificationRow
+<com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -26,21 +26,23 @@
 
     <!-- Menu displayed behind notification added here programmatically -->
 
-    <com.android.systemui.statusbar.NotificationBackgroundView
+    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
         android:id="@+id/backgroundNormal"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
-    <com.android.systemui.statusbar.NotificationBackgroundView
+    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
         android:id="@+id/backgroundDimmed"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
-    <com.android.systemui.statusbar.NotificationContentView android:id="@+id/expanded"
+    <com.android.systemui.statusbar.notification.row.NotificationContentView
+        android:id="@+id/expanded"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
 
-    <com.android.systemui.statusbar.NotificationContentView android:id="@+id/expandedPublic"
+    <com.android.systemui.statusbar.notification.row.NotificationContentView
+        android:id="@+id/expandedPublic"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
@@ -76,4 +78,4 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
-</com.android.systemui.statusbar.ExpandableNotificationRow>
+</com.android.systemui.statusbar.notification.row.ExpandableNotificationRow>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_shelf.xml b/packages/SystemUI/res/layout/status_bar_notification_shelf.xml
index 7bfbd3c..781c015 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_shelf.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_shelf.xml
@@ -23,14 +23,14 @@
     android:clickable="true"
     >
 
-    <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundNormal"
+    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
+        android:id="@+id/backgroundNormal"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        />
-    <com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundDimmed"
+        android:layout_height="match_parent" />
+    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
+        android:id="@+id/backgroundDimmed"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        />
+        android:layout_height="match_parent" />
     <com.android.systemui.statusbar.phone.NotificationIconContainer
         android:id="@+id/content"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/tuner_activity.xml b/packages/SystemUI/res/layout/tuner_activity.xml
new file mode 100644
index 0000000..0b792ae
--- /dev/null
+++ b/packages/SystemUI/res/layout/tuner_activity.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<!-- The tuner content view -->
+<LinearLayout
+    android:id="@+id/content_parent"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <Toolbar
+        android:id="@+id/action_bar"
+        style="?android:attr/actionBarStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:theme="?android:attr/actionBarTheme"
+        android:navigationContentDescription="@*android:string/action_bar_up_description" />
+    <FrameLayout
+        android:id="@+id/content_frame"
+        android:layout_width="match_parent"
+        android:layout_height="fill_parent"
+        android:background="?android:attr/windowBackground" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/wireless_charging_layout.xml b/packages/SystemUI/res/layout/wireless_charging_layout.xml
index e848901..4610409 100644
--- a/packages/SystemUI/res/layout/wireless_charging_layout.xml
+++ b/packages/SystemUI/res/layout/wireless_charging_layout.xml
@@ -23,11 +23,12 @@
     android:layout_height="match_parent">
 
     <!-- Circle animation -->
-    <com.android.systemui.charging.WirelessChargingView
+    <ImageView
         android:id="@+id/wireless_charging_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:elevation="4dp"/>
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:src="@drawable/wireless_charging_animation"/>
 
     <!-- Text inside circle -->
     <LinearLayout
@@ -42,8 +43,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center"
-            android:textSize="24sp"
-            android:textColor="?attr/wallpaperTextColor"/>
+            android:textSize="24sp"/>
     </LinearLayout>
 
 </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 fb9b5df..6bfd9b2 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Kennisgewings"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Battery kan binnekort afloop"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor; ongeveer <xliff:g id="TIME">%s</xliff:g> oor op grond van jou gebruik"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor; ongeveer <xliff:g id="TIME">%s</xliff:g> oor"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> oor; ongeveer <xliff:g id="TIME">%2$s</xliff:g> oor op grond van jou gebruik"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> oor; ongeveer <xliff:g id="TIME">%2$s</xliff:g> oor"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor. Batterybespaarder is aan."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Kan nie deur USB laai nie. Gebruik die laaier wat jy saam met jou toestel gekry het."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Kan nie deur USB laai nie"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Liggingversoeke aktief"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Verwyder alle kennisgewings."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">nog <xliff:g id="NUMBER_1">%s</xliff:g> kennisgewings binne.</item>
       <item quantity="one">nog <xliff:g id="NUMBER_0">%s</xliff:g> kennisgewing binne.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Volkome\nstilte"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Net\nprioriteit"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Net\nwekkers"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans vinnig (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans stadig (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> tot vol)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans vinnig (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> tot vol)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans stadig (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> tot vol)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Wissel gebruiker"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Wissel gebruiker, huidige gebruiker <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Huidige gebruiker <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"MELD GEBRUIKER AF"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Voeg nuwe gebruiker by?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Wanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel.\n\nEnige gebruiker kan programme vir al die ander gebruikers opdateer."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Verwyder gebruiker?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Alle programme en data van hierdie gebruiker sal uitgevee word."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Verwyder"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Links-ikoon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Regs-ikoon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Hou en sleep om teëls by te voeg"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Sleep hierheen om te verwyder"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Jy moet minstens 6 teëls hê"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Wysig"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Volskerm onder"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posisie <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dubbeltik om te wysig."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dubbeltik om by te voeg."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posisie <xliff:g id="POSITION">%1$d</xliff:g>. Dubbeltik om te kies."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Skuif <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Verwyder <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is by posisie <xliff:g id="POSITION">%2$d</xliff:g> gevoeg"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is verwyder"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is na posisie <xliff:g id="POSITION">%2$d</xliff:g> geskuif"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Voeg <xliff:g id="TILE_NAME">%1$s</xliff:g> by posisie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Skuif <xliff:g id="TILE_NAME">%1$s</xliff:g> na posisie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Kitsinstellingswysiger."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g>-kennisgewing: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Program sal dalk nie met verdeelde skerm werk nie."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Programinligting"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Gaan na blaaier"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiele data"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is af"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is af"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Moenie Steur Nie is af"</string>
diff --git a/packages/SystemUI/res/values-af/strings_car.xml b/packages/SystemUI/res/values-af/strings_car.xml
index 407ddcb..0127af8 100644
--- a/packages/SystemUI/res/values-af/strings_car.xml
+++ b/packages/SystemUI/res/values-af/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gas"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gas"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Voeg gebruiker by"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nuwe gebruiker"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Wanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 305082f..43a27f0 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ማሳወቂያዎች"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ባትሪ በቅርቡ ሊያልቅ ይችላል"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል፣ በእርስዎ አጠቃቀም ላይ በመመረት <xliff:g id="TIME">%s</xliff:g> ገደማ ይቀራል"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል፣ <xliff:g id="TIME">%s</xliff:g> ገደማ ይቀራል"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ይቀራል፣ በእርስዎ አጠቃቀም ላይ በመመረት <xliff:g id="TIME">%2$s</xliff:g> ገደማ ይቀራል"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ይቀራል፣ <xliff:g id="TIME">%2$s</xliff:g> ገደማ ይቀራል"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል። ባትሪ ቆጣቢ በርቷል።"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"በዩኤስቢ በኩል ኃይል መሙላት አይቻልም። ከመሣሪያዎ ጋር የመጣውን ኃይል መሙያ ይጠቀሙ።"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"በዩኤስቢ በኩል ኃይል መሙላት አይቻልም"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"የአካባቢ ጥያቄዎች ነቅተዋል"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>፣ +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>፣ +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">ከውስጥ ተጨማሪ <xliff:g id="NUMBER_1">%s</xliff:g> ማሳወቂያዎች።</item>
       <item quantity="other">ከውስጥ ተጨማሪ <xliff:g id="NUMBER_1">%s</xliff:g> ማሳወቂያዎች።</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"ሙሉ ለሙሉ\nጸጥታ"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ቅድሚያ ተሰጪ\nብቻ"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ማንቂያዎች\nብቻ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ (እስኪሞላ ድረስ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ (እስኪሞላ ድረስ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ (እስኪሞላ ድረስ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ (እስኪሞላ ድረስ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ (እስኪሞላ ድረስ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ (እስኪሞላ ድረስ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ተጠቃሚ ቀይር"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ተጠቃሚ ይለውጡ፣ የአሁን ተጠቃሚ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"የአሁን ተጠቃሚ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ተጠቃሚን አስወጣ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"አዲስ ተጠቃሚ ይታከል?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"እርስዎ አንድ አዲስ ተጠቃሚ ሲያክሉ ያ ሰው የራሱ ቦታ ማዘጋጀት አለበት።\n\nማንኛውም ተጠቃሚ መተግበሪያዎችን ለሌሎች ተጠቃሚዎች ሁሉ ሊያዘምን ይችላል።"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"ተጠቃሚ ይወገድ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"ሁሉም የዚህ ተጠቃሚ መተግበሪያዎች እና ውሂብ ይሰረዛሉ።"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"አስወግድ"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"የግራ አዶ"</string>
     <string name="right_icon" msgid="3952104823293824311">"የቀኝ አዶ"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ፋይሎችን ለማከል ይዘት ይጎትቱ"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ለማስወገድ ወደዚህ ይጎትቱ"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"ቢያንስ 6 ሰቆች ያስፈልገዎታል"</string>
     <string name="qs_edit" msgid="2232596095725105230">"አርትዕ"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"የታች ሙሉ ማያ ገጽ"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ቦታ <xliff:g id="POSITION">%1$d</xliff:g>፣ <xliff:g id="TILE_NAME">%2$s</xliff:g>። ለማርትዕ ሁለቴ መታ ያድርጉ።"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>። ለማከል ሁለቴ መታ ያድርጉ።"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ቦታ <xliff:g id="POSITION">%1$d</xliff:g>። ለመምረጥ ሁለቴ መታ ያድርጉ።"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ይውሰዱ"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ያስወግዱ"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ወደ ቦታ <xliff:g id="POSITION">%2$d</xliff:g> ታክሏል"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ተወግዷል"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ወደ ቦታ <xliff:g id="POSITION">%2$d</xliff:g> ተወስዷል"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ወደ አቀማመጥ <xliff:g id="POSITION">%2$d</xliff:g> አክል"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ወደ አቀማመጥ <xliff:g id="POSITION">%2$d</xliff:g> አንቀሳቅስ"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"የፈጣን ቅንብሮች አርታዒ።"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"የ<xliff:g id="ID_1">%1$s</xliff:g> ማሳወቂያ፦ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"መተግበሪያ ከተከፈለ ማያ ገጽ ጋር ላይሠራ ይችላል"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ወደ አሳሽ ሂድ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g>— <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g>— <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ጠፍቷል"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ብሉቱዝ ጠፍቷል"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"አትረብሽ ጠፍቷል"</string>
diff --git a/packages/SystemUI/res/values-am/strings_car.xml b/packages/SystemUI/res/values-am/strings_car.xml
index 635c9de..cc709de 100644
--- a/packages/SystemUI/res/values-am/strings_car.xml
+++ b/packages/SystemUI/res/values-am/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"እንግዳ"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"እንግዳ"</string>
     <string name="car_add_user" msgid="5245196248349230898">"ተጠቃሚ አክል"</string>
     <string name="car_new_user" msgid="8142927244990323906">"አዲስ ተጠቃሚ"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"አዲስ ተጠቃሚ ሲያክሉ ያ ሰው የራሳቸውን ቦታ ማቀናበር አለባቸው።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 8f197e8..598d822 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -38,8 +38,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"الإشعارات"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"قد ينفد شحن البطارية قريبًا"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"متبقي <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"طاقة البطارية المتبقية <xliff:g id="PERCENTAGE">%s</xliff:g> ويتبقى على نفادها <xliff:g id="TIME">%s</xliff:g> تقريبًا بناءً على استخدامك."</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"طاقة البطارية المتبقية <xliff:g id="PERCENTAGE">%s</xliff:g> ويتبقى على نفادها <xliff:g id="TIME">%s</xliff:g> تقريبًا."</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"طاقة البطارية المتبقية <xliff:g id="PERCENTAGE">%1$s</xliff:g> ويتبقى على نفادها <xliff:g id="TIME">%2$s</xliff:g> تقريبًا بناءً على استخدامك."</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"طاقة البطارية المتبقية <xliff:g id="PERCENTAGE">%1$s</xliff:g> ويتبقى على نفادها <xliff:g id="TIME">%2$s</xliff:g> تقريبًا."</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"يتبقى <xliff:g id="PERCENTAGE">%s</xliff:g>. تم تفعيل ميزة توفير شحن البطارية."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"‏يتعذّر الشحن باستخدام USB. استخدم الشاحن المرفق بجهازك."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"‏يتعذّر الشحن باستخدام USB."</string>
@@ -261,7 +261,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"طلبات الموقع نشطة"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"محو جميع الإشعارات."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>، + <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>، + <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="zero"><xliff:g id="NUMBER_1">%s</xliff:g> إشعار آخر بداخل المجموعة.</item>
       <item quantity="two">إشعاران (<xliff:g id="NUMBER_1">%s</xliff:g>) آخران بداخل المجموعة.</item>
@@ -411,9 +411,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"كتم الصوت\nتمامًا"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"الأولوية \nفقط"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"التنبيهات\nفقط"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن (يتبقى <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> حتى الامتلاء)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن سريعًا (يتبقى <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> حتى الامتلاء)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن ببطء (يتبقى <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> حتى الامتلاء)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن (يتبقى <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> حتى الامتلاء)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن سريعًا (يتبقى <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> حتى الامتلاء)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن ببطء (يتبقى <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> حتى الامتلاء)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"تبديل المستخدم"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"تبديل المستخدم، المستخدم الحالي <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"المستخدم الحالي <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -438,6 +438,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"خروج المستخدم"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"هل تريد إضافة مستخدم جديد؟"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"عند إضافة مستخدم جديد، عليه إعداد مساحته.\n\nويُمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"هل تريد إزالة المستخدم؟"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"سيتم حذف جميع تطبيقات وبيانات هذا المستخدم."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"إزالة"</string>
@@ -749,6 +752,8 @@
     <string name="left_icon" msgid="3096287125959387541">"رمز اليسار"</string>
     <string name="right_icon" msgid="3952104823293824311">"رمز اليمين"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"انقر باستمرار مع السحب لإضافة المربعات."</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"اسحب هنا للإزالة"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"تحتاج إلى 6 مربعات على الأقل."</string>
     <string name="qs_edit" msgid="2232596095725105230">"تعديل"</string>
@@ -777,12 +782,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"عرض النافذة السفلية بملء الشاشة"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"الموضع <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>. انقر مرّتين للتعديل."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. انقر مرّتين للإضافة."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"الموضع <xliff:g id="POSITION">%1$d</xliff:g>. انقر مرّتين للتحديد."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"نقل <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"إزالة <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"تمت إضافة <xliff:g id="TILE_NAME">%1$s</xliff:g> إلى الموضع <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"تمت إزالة <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"تم نقل <xliff:g id="TILE_NAME">%1$s</xliff:g> إلى الموضع <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"إضافة <xliff:g id="TILE_NAME">%1$s</xliff:g> إلى الموضع <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"نقل <xliff:g id="TILE_NAME">%1$s</xliff:g> إلى الموضع <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"برنامج تعديل الإعدادات السريعة."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"إشعار <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"يمكن ألا يعمل التطبيق مع وضع تقسيم الشاشة."</string>
@@ -799,7 +802,7 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"فتح إعدادات <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"تعديل ترتيب الإعدادات."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"الصفحة <xliff:g id="ID_1">%1$d</xliff:g> من <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <string name="tuner_lock_screen" msgid="5755818559638850294">"شاشة التأمين"</string>
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"شاشة القفل"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"توسيع"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"تصغير"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"إغلاق"</string>
@@ -843,7 +846,7 @@
     <string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string>
     <string name="go_to_web" msgid="2650669128861626071">"الانتقال إلى المتصفح"</string>
     <string name="mobile_data" msgid="7094582042819250762">"بيانات الجوّال"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‏تم إيقاف شبكة Wi-Fi"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"تم إيقاف البلوتوث."</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"تم إيقاف وضع \"عدم الإزعاج\""</string>
diff --git a/packages/SystemUI/res/values-ar/strings_car.xml b/packages/SystemUI/res/values-ar/strings_car.xml
index d6dfa12f..54b7e1d 100644
--- a/packages/SystemUI/res/values-ar/strings_car.xml
+++ b/packages/SystemUI/res/values-ar/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"ضيف"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"ضيف"</string>
     <string name="car_add_user" msgid="5245196248349230898">"إضافة المستخدم"</string>
     <string name="car_new_user" msgid="8142927244990323906">"مستخدم جديد"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"عند إضافة مستخدم جديد، عليه إعداد مساحته."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index c20b5bc..84d178b 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"জাননীসমূহ"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"বেটাৰি অতি সোনকালে শেষ হ\'ব পাৰে"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকী আছে"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> অৱশিষ্ট আছে, আপোনাৰ ব্যৱহাৰক ভিত্তি কৰি প্ৰায় <xliff:g id="TIME">%s</xliff:g> বাকী আছে"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> অৱশিষ্ট আছে, প্ৰায় <xliff:g id="TIME">%s</xliff:g> বাকী"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> অৱশিষ্ট আছে, আপোনাৰ ব্যৱহাৰক ভিত্তি কৰি প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> অৱশিষ্ট আছে, প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকী আছে। বেটাৰি সঞ্চয়কাৰী অন হৈ আছে।"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"ইউএছবি জৰিয়তে চ্চাৰ্জ কৰিব নোৱাৰি। আপোনাৰ ডিভাইচৰ লগত পোৱা চ্চাৰ্জাৰটো ব্যৱহাৰ কৰক।"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"ইউএছবি জৰিয়তে চ্চাৰ্জ কৰিব নোৱাৰি"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"অৱস্থানৰ অনুৰোধ সক্ৰিয় হৈ আছে"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"সকলো জাননী মচক৷"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one"> ভিতৰত আৰু <xliff:g id="NUMBER_1">%s</xliff:g>টা জাননী আছে।</item>
       <item quantity="other"> ভিতৰত আৰু <xliff:g id="NUMBER_1">%s</xliff:g>টা জাননী আছে।</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"সম্পূর্ণ \n নিৰৱতা"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"কেৱল\nগুৰুত্বপূৰ্ণ"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"কেৱল\nএলাৰ্মসমূহ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চ্চাৰ্জ কৰি থকা হৈছে (সম্পূৰ্ণ হ\'বলৈ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> বাকী)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্ৰুতগতিৰে চ্চাৰ্জ কৰি থকা হৈছে (সম্পূৰ্ণ হ\'বলৈ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> বাকী)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে (সম্পূৰ্ণ হ\'বলৈ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> বাকী)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চ্চাৰ্জ কৰি থকা হৈছে (সম্পূৰ্ণ হ\'বলৈ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> বাকী)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্ৰুতগতিৰে চ্চাৰ্জ কৰি থকা হৈছে (সম্পূৰ্ণ হ\'বলৈ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> বাকী)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে (সম্পূৰ্ণ হ\'বলৈ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> বাকী)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ব্যৱহাৰকাৰী সলনি কৰক"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ব্যৱহাৰকাৰী সলনি কৰক, বৰ্তমানৰ ব্যৱহাৰকাৰী <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"বর্তমানৰ ব্যৱহাৰকাৰী <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ব্যৱহাৰকাৰীক লগ আউট কৰক"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"নতুন ব্যৱহাৰকাৰী যোগ কৰিবনে?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"আপুনি যেতিয়া এজন নতুন ব্যৱহাৰকাৰী যোগ কৰে, তেওঁ নিজৰ স্থান ছেট আপ কৰা প্ৰয়োজন।\n\nযিকোনো ব্যৱহাৰকাৰীয়ে নিজৰ লগতে আন ব্যৱহাৰকাৰীৰো এপ্ আপডেট কৰিব পাৰে।"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"ব্যৱহাৰকাৰীক আঁতৰাবনে?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"এই ব্যৱহাৰকাৰীৰ সকলো এপ্ আৰু ডেটা মচা হ\'ব।"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"আঁতৰাওক"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"বাওঁ আইকন"</string>
     <string name="right_icon" msgid="3952104823293824311">"সোঁ আইকন"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"টাইল যোগ কৰিবলৈ হেঁচি ধৰি টানি আনক"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"আঁতৰাবৰ বাবে টানি আনি ইয়াত এৰি দিয়ক"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"আপোনাক অতি কমেও ৬খন টাইল লাগিব"</string>
     <string name="qs_edit" msgid="2232596095725105230">"সম্পাদনা কৰক"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"তলৰ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"অৱস্থান <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। সম্পাদনা কৰিবৰ বাবে দুবাৰ টিপক।"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। যোগ কৰিবলৈ দুবাৰ টিপক।"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"অৱস্থান <xliff:g id="POSITION">%1$d</xliff:g>। বাছনি কৰিবলৈ দুবাৰ টিপক।"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> স্থানান্তৰ কৰক"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ক আঁতৰাওক"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ক <xliff:g id="POSITION">%2$d</xliff:g> অৱস্থানত যোগ কৰা হৈছে"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ক আঁতৰোৱা হৈছে"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ক <xliff:g id="POSITION">%2$d</xliff:g> অৱস্থানলৈ স্থানান্তৰ কৰা হৈছে"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"এই স্থান <xliff:g id="POSITION">%2$d</xliff:g>ত <xliff:g id="TILE_NAME">%1$s</xliff:g> যোগ কৰক"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ক এই স্থান <xliff:g id="POSITION">%2$d</xliff:g>লৈ যাওক"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ক্ষিপ্ৰ ছেটিংসমূহৰ সম্পাদক।"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> জাননী: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"বিভাজিত স্ক্ৰীণৰ সৈতে এপে হয়তো কাম নকৰিব।"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"এপ্ সম্পৰ্কীয় তথ্য"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ব্ৰাউজাৰলৈ যাওক"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ম\'বাইল ডেটা"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ৱাই-ফাই অফ অৱস্থাত আছে"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ব্লুটুথ অফ অৱস্থাত আছে"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"অসুবিধা নিদিব অফ অৱস্থাত আছে"</string>
diff --git a/packages/SystemUI/res/values-as/strings_car.xml b/packages/SystemUI/res/values-as/strings_car.xml
index 1c4d7944..b8031a5d 100644
--- a/packages/SystemUI/res/values-as/strings_car.xml
+++ b/packages/SystemUI/res/values-as/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"অতিথি"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"অতিথি"</string>
     <string name="car_add_user" msgid="5245196248349230898">"ব্যৱহাৰকাৰী যোগ কৰক"</string>
     <string name="car_new_user" msgid="8142927244990323906">"নতুন ব্যৱহাৰকাৰী"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"আপুনি কোনো নতুন ব্য়ৱহাৰকাৰীক যোগ কৰিলে তেখেতে নিজৰ বাবে খালী ঠাই ছেট আপ কৰিব লাগে।"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 239dc20..bbc67a5 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirişlər"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Batareya tezliklə bitə bilər"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> qalır"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Qalan <xliff:g id="PERCENTAGE">%s</xliff:g>, istifadəyə əsasən təxminən <xliff:g id="TIME">%s</xliff:g> qalıb"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Qalan <xliff:g id="PERCENTAGE">%s</xliff:g>, təxminən <xliff:g id="TIME">%s</xliff:g> qalır"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Qalan <xliff:g id="PERCENTAGE">%1$s</xliff:g>, istifadəyə əsasən təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Qalan <xliff:g id="PERCENTAGE">%1$s</xliff:g>, təxminən <xliff:g id="TIME">%2$s</xliff:g> qalır"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> qalır. Batareya Qənaəti aktivdir."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB vasitəsilə enerji yığa bilməz. Cihazla verilən adapterdən istifadə edin."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB vasitəsilə enerji yığa bilməz"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Məkan sorğuları arxivi"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Bütün bildirişləri sil."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Daxilində daha <xliff:g id="NUMBER_1">%s</xliff:g> bildiriş.</item>
       <item quantity="one">Daxilində daha <xliff:g id="NUMBER_0">%s</xliff:g> bildiriş.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Tam\nsakitlik"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Yalnız\nprioritet"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Yalnız\nalarmlar"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Enerji yığır (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> dolana qədər)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sürətlə enerji yığır (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> dolana qədər)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş enerji yığır (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> dolana qədər)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Enerji yığır (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> dolana qədər)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sürətlə enerji yığır (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> dolana qədər)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş enerji yığır (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> dolana qədər)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"İstifadəçiləri dəyişin, indiki istifadəçi: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Cari istifadəçi <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"İSTİFADƏÇİ ÇIXIŞI"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Yeni istifadəçi əlavə edilsin?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Yeni istifadəçi əlavə etdiyiniz zaman həmin şəxs öz yerini quraşdırmalıdır. \n\n İstənilən istifadəçi bütün digər istifadəçilərdən olan tətbiqləri güncəlləşdirə bilər."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"İstifadəçi silinsin?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Bu istifadəçinin bütün tətbiqləri və datası silinəcək."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Silin"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Sol ikona"</string>
     <string name="right_icon" msgid="3952104823293824311">"Sağ ikona"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Mozaika əlavə etmək üçün basıb saxlayaraq çəkin"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Silmək üçün bura sürüşdürün"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Minimum 6 mozaikaya ehtiyacınız var"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Redaktə edin"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Aşağı tam ekran"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyi, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Redaktə etmək üçün iki dəfə tıklayın."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Əlavə etmək üçün iki dəfə tıklayın."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyi. Seçmək üçün iki dəfə tıklayın."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> köçürün"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> silin"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> mövqeyinə əlavə edildi"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> silindi"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> mövqeyinə köçürüldü"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="POSITION">%2$d</xliff:g> pozisiyasına <xliff:g id="TILE_NAME">%1$s</xliff:g> əlavə edin"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="POSITION">%2$d</xliff:g> pozisiyasına <xliff:g id="TILE_NAME">%1$s</xliff:g> köçürün"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Sürətli ayarlar redaktoru."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> bildiriş: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Tətbiq bölünmüş ekran ilə işləməyə bilər."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Brauzerə daxil edin"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobil data"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi deaktivdir"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth deaktivdir"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Narahat Etməyin\" deaktivdir"</string>
diff --git a/packages/SystemUI/res/values-az/strings_car.xml b/packages/SystemUI/res/values-az/strings_car.xml
index 79a946c..d64f4c2 100644
--- a/packages/SystemUI/res/values-az/strings_car.xml
+++ b/packages/SystemUI/res/values-az/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Qonaq"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Qonaq"</string>
     <string name="car_add_user" msgid="5245196248349230898">"İstifadəçi əlavə edin"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Yeni İstifadəçi"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Yeni istifadəçi əlavə etdiyinizdə həmin şəxs öz yerini təyin etməlidir."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 47eb266..679fdde 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -35,8 +35,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obaveštenja"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Baterija će se možda uskoro isprazniti"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>, na osnovu korišćenja ostalo je oko <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>, ostalo je oko <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Još <xliff:g id="PERCENTAGE">%1$s</xliff:g>, na osnovu korišćenja ostalo je oko <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Još <xliff:g id="PERCENTAGE">%1$s</xliff:g>, ostalo je oko <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>. Ušteda baterije je uključena."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Punjenje preko USB-a nije uspelo. Koristite punjač koji ste dobili uz uređaj."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Punjenje preko USB-a nije uspelo"</string>
@@ -258,7 +258,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Ima aktivnih zahteva za lokaciju"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Obriši sva obaveštenja."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"i još <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, još <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, još <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Još <xliff:g id="NUMBER_1">%s</xliff:g> obaveštenje u grupi.</item>
       <item quantity="few">Još <xliff:g id="NUMBER_1">%s</xliff:g> obaveštenja u grupi.</item>
@@ -375,7 +375,7 @@
     <string name="quick_step_accessibility_toggle_overview" msgid="7171470775439860480">"Uključi/isključi pregled"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjena je"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Punjenje"</string>
-    <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> dok se ne napuni"</string>
+    <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do kraja punjenja"</string>
     <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Ne puni se"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mreža se možda\nnadgleda"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Pretraga"</string>
@@ -402,9 +402,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Potpuna\ntišina"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Samo\npriorit. prekidi"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Samo\nalarmi"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se (napuniće se za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo se puni (napuniće se za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo se puni (napuniće se za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se (napuniće se za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo se puni (napuniće se za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo se puni (napuniće se za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Zameni korisnika"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Promenite korisnika, aktuelni korisnik je <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Aktuelni korisnik <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -429,6 +429,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ODJAVI KORISNIKA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Dodajete novog korisnika?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Kada dodate novog korisnika, ta osoba treba da podesi svoj prostor.\n\nSvaki korisnik može da ažurira aplikacije za sve ostale korisnike."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Želite li da uklonite korisnika?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Sve aplikacije i podaci ovog korisnika će biti izbrisani."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Ukloni"</string>
@@ -734,6 +737,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Leva ikona"</string>
     <string name="right_icon" msgid="3952104823293824311">"Desna ikona"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Zadržite i prevucite da biste dodali pločice"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Prevucite ovde da biste uklonili"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Treba da izaberete najmanje 6 pločica"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Izmeni"</string>
@@ -762,12 +767,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Režim celog ekrana za donji ekran"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. pozicija, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvaput dodirnite da biste izmenili."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dvaput dodirnite da biste dodali."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. pozicija. Dvaput dodirnite da biste izabrali."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Premesti pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Ukloni pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> je dodata na <xliff:g id="POSITION">%2$d</xliff:g>. poziciju"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> je uklonjena"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> je premeštena na <xliff:g id="POSITION">%2$d</xliff:g>. poziciju"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Dodajte „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Premestite „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Uređivač za Brza podešavanja."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Obaveštenja za <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija možda neće funkcionisati sa podeljenim ekranom."</string>
@@ -828,7 +831,7 @@
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Idi na pregledač"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Režim Ne uznemiravaj je isključen"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml
index 381d804..3cf7e2e 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gost"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gost"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Dodaj korisnika"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Novi korisnik"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kada dodate novog korisnika, ta osoba treba da podesi svoj prostor."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 2db91e8..d26b322 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -36,8 +36,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Апавяшчэнні"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Акумулятар хутка разрадзіцца"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g>, у вас ёсць каля <xliff:g id="TIME">%s</xliff:g> на аснове даных аб выкарыстанні вашай прылады"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g>, у вас ёсць каля <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Засталося <xliff:g id="PERCENTAGE">%1$s</xliff:g>, у вас ёсць каля <xliff:g id="TIME">%2$s</xliff:g> на аснове даных аб выкарыстанні вашай прылады"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Засталося <xliff:g id="PERCENTAGE">%1$s</xliff:g>, у вас ёсць каля <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g>. Уключана эканомія зараду."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Не ўдалося выканаць зарадку праз USB. Выкарыстоўвайце зараднае прыстасаванне з камплекта прылады."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Не ўдалося выканаць зарадку праз USB"</string>
@@ -261,7 +261,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Ёсць актыўныя запыты пра месцазнаходжанне"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Выдалiць усе апавяшчэннi."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Яшчэ <xliff:g id="NUMBER_1">%s</xliff:g> апавяшчэнне ўнутры.</item>
       <item quantity="few">Яшчэ <xliff:g id="NUMBER_1">%s</xliff:g> апавяшчэнні ўнутры.</item>
@@ -407,9 +407,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Поўная\nцішыня"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Толькі\nпрыярытэтныя"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Толькі\nбудзільнікі"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"Ідзе зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"Ідзе хуткая зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Ідзе павольная зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"Ідзе зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"Ідзе хуткая зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Ідзе павольная зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Перайсці да іншага карыстальніка"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Перайсці да іншага карыстальніка, бягучы карыстальнік <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Бягучы карыстальнік <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -434,6 +434,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ВЫКАНАЦЬ ВЫХАД КАРЫСТАЛЬНІКА"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Дадаць новага карыстальніка?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Пасля стварэння профіля яго трэба наладзіць.\n\nЛюбы карыстальнік прылады можа абнаўляць праграмы ўсіх іншых карыстальнікаў."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Выдаліць карыстальніка?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Усе праграмы і даныя гэтага карыстальніка будуць выдалены."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Выдаліць"</string>
@@ -741,6 +744,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Значок \"улева\""</string>
     <string name="right_icon" msgid="3952104823293824311">"Значок \"управа\""</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Перацягніце патрэбныя пліткі"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Перацягніце сюды, каб выдаліць"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Трэба па меншай меры 6 плітак"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Рэдагаваць"</string>
@@ -769,12 +774,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Ніжні экран – поўнаэкранны рэжым"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Краніце двойчы, каб рэдагаваць."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Краніце двойчы, каб дадаць."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>. Краніце двойчы, каб выбраць."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Перамясціць <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Выдаліць <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Плітка <xliff:g id="TILE_NAME">%1$s</xliff:g> дададзена ў наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Плітка <xliff:g id="TILE_NAME">%1$s</xliff:g> выдалена"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> перамешчана ў наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Дадаць \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" у наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Перамясціць \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" у наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Рэдактар хуткіх налад."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Апавяшчэнне <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Праграма можа не працаваць у рэжыме дзялення экрана."</string>
@@ -835,7 +838,7 @@
     <string name="app_info" msgid="6856026610594615344">"Інфармацыя пра праграму"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Перайсці ў браўзер"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Маб. перадача даных"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi выключаны"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth выключаны"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Рэжым \"Не турбаваць\" выключаны"</string>
diff --git a/packages/SystemUI/res/values-be/strings_car.xml b/packages/SystemUI/res/values-be/strings_car.xml
index a56dd84..d665bf1 100644
--- a/packages/SystemUI/res/values-be/strings_car.xml
+++ b/packages/SystemUI/res/values-be/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Госць"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Госць"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Дадаць карыстальніка"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Новы карыстальнік"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Калі вы дадаяце новага карыстальніка, яму трэба наладзіць свой профіль."</string>
diff --git a/packages/SystemUI/res/values-bg/donottranslate.xml b/packages/SystemUI/res/values-bg/donottranslate.xml
deleted file mode 100644
index dcf434d..0000000
--- a/packages/SystemUI/res/values-bg/donottranslate.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%2$s\n%1$s</string>
-
-</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 850977d..2bd6cc4 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известия"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Батерията може скоро да се изтощи"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g> – още около <xliff:g id="TIME">%s</xliff:g> въз основа на използването"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g> – още около <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Остава/т <xliff:g id="PERCENTAGE">%1$s</xliff:g> – още около <xliff:g id="TIME">%2$s</xliff:g> въз основа на използването"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Остава/т <xliff:g id="PERCENTAGE">%1$s</xliff:g> – още около <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g>. Режимът за запазване на батерията е включен."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Зареждането през USB не е възможно. Използвайте оригиналното зарядно устройство."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Зареждането през USB не е възможно"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Активни заявки за местоположение"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, + <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, + <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Съдържа още <xliff:g id="NUMBER_1">%s</xliff:g> известия.</item>
       <item quantity="one">Съдържа още <xliff:g id="NUMBER_0">%s</xliff:g> известие.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Пълна\nтишина"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Само\nс приоритет"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Само\nбудилници"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до пълно зареждане)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бързо (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до пълно зареждане)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бавно (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до пълно зареждане)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бързо (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бавно (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Превключване между потребителите"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Превключване на потребителя – текущият е <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Текущ потребител – <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ИЗЛИЗАНЕ НА ПОТРЕБИТЕЛЯ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Да се добави ли нов потреб.?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Когато добавите нов потребител, той трябва да настрои работното си пространство.\n\nВсеки потребител може да актуализира приложенията за всички останали потребители."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Да се премахне ли потребителят?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Всички приложения и данни на този потребител ще бъдат изтрити."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Премахване"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Лява икона"</string>
     <string name="right_icon" msgid="3952104823293824311">"Дясна икона"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Задръжте и плъзнете, за да добавите плочки"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Преместете тук с плъзгане за премахване"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Трябва да останат поне 6 плочки"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Редактиране"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Долен екран: Показване на цял екран"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>, „<xliff:g id="TILE_NAME">%2$s</xliff:g>“. Докоснете двукратно, за да редактирате."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"„<xliff:g id="TILE_NAME">%1$s</xliff:g>“. Докоснете двукратно, за да добавите."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>. Докоснете двукратно, за да изберете."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Преместване на „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Премахване на „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Добавихте „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ към позиция <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Премахнахте „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Преместихте „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позиция <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Добавете „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позиция <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Преместете „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позиция <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Редактор за бързи настройки."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Известие от <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Приложението може да не работи в режим на разделен екран."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Към браузъра"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобилни данни"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Функцията за Wi‑Fi е изключена"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Функцията за Bluetooth е изключена"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Режимът „Не безпокойте“ е изключен"</string>
diff --git a/packages/SystemUI/res/values-bg/strings_car.xml b/packages/SystemUI/res/values-bg/strings_car.xml
index fe159ea..39e19b5 100644
--- a/packages/SystemUI/res/values-bg/strings_car.xml
+++ b/packages/SystemUI/res/values-bg/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Гост"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Гост"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Добавяне на потребител"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Нов потребител"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Когато добавите нов потребител, той трябва да настрои работното си пространство."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index eacf30c..866deae 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"বিজ্ঞপ্তিগুলি"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"চার্জ শীঘ্রই শেষ হয়ে যেতে পারে"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকি আছে, বর্তমান ব্যবহারের ভিত্তিতে আর <xliff:g id="TIME">%s</xliff:g> চলবে"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকি আছে, আর <xliff:g id="TIME">%s</xliff:g> চলবে"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> বাকি আছে, বর্তমান ব্যবহারের ভিত্তিতে আর <xliff:g id="TIME">%2$s</xliff:g> চলবে"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> বাকি আছে, আর <xliff:g id="TIME">%2$s</xliff:g> চলবে"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে। ব্যাটারি সেভার চালু আছে।"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"ইউএসবি দিয়ে চার্জ করা যাবে না। ডিভাইসের সাথে যে চার্জারটি পেয়েছেন, সেটি ব্যবহার করুন।"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"ইউএসবি দিয়ে চার্জ করা যাবে না"</string>
@@ -47,7 +47,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"সেটিংস"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"ওয়াই-ফাই"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"অটো-রোটেট স্ক্রিন"</string>
-    <string name="status_bar_settings_mute_label" msgid="554682549917429396">"নিঃশব্দ করুন"</string>
+    <string name="status_bar_settings_mute_label" msgid="554682549917429396">"মিউট করুন"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"স্বতঃ"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"বিজ্ঞপ্তিগুলি"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"ব্লুটুথ টিথার করা হয়েছে"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"লোকেশন অনুরোধ সক্রিয় রয়েছে"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"সমস্ত বিজ্ঞপ্তি সাফ করুন৷"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>টি"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">ভিতরে আরও <xliff:g id="NUMBER_1">%s</xliff:g>টি বিজ্ঞপ্তি আছে।</item>
       <item quantity="other">ভিতরে আরও <xliff:g id="NUMBER_1">%s</xliff:g>টি বিজ্ঞপ্তি আছে।</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"একদম\nনিরব"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"শুধুমাত্র\nঅগ্রাধিকার"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"শুধুমাত্র\nঅ্যালার্মগুলি"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জ হচ্ছে (পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> লাগবে)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্রুত চার্জ হচ্ছে (পুরোটা হতে <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> লাগবে)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ধীরে চার্জ হচ্ছে (পুরোটা হতে <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> লাগবে)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জ হচ্ছে (পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • দ্রুত চার্জ হচ্ছে (পুরোটা হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ধীরে চার্জ হচ্ছে (পুরোটা হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ব্যবহারকারী পাল্টে দিন"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ব্যবহারকারী পাল্টান, বর্তমান ব্যবহারকারী <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"<xliff:g id="CURRENT_USER_NAME">%s</xliff:g> হল বর্তমান ব্যবহারকারী"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ব্যবহারকারীকে লগ-আউট করুন"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"নতুন ব্যবহারকারীকে যোগ করবেন?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"আপনি একজন নতুন ব্যবহারকারী যোগ করলে তাকে তার জায়গা সেট আপ করে নিতে হবে৷\n\nযেকোনো ব্যবহারকারী অন্য সব ব্যবহারকারীর জন্য অ্যাপ্লিকেশান আপডেট করতে পারবেন৷"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"ব্যবহারকারী সরাবেন?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"এই ব্যবহারকারীর সমস্ত অ্যাপ্লিকেশান ও ডেটা মুছে ফেলা হবে।"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"সরান"</string>
@@ -538,10 +541,10 @@
     <string name="qs_status_phone_vibrate" msgid="204362991135761679">"ফোন ভাইব্রেশন মোডে আছে"</string>
     <string name="qs_status_phone_muted" msgid="5437668875879171548">"ফোন মিউট করা আছে"</string>
     <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। সশব্দ করতে আলতো চাপুন।"</string>
-    <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। কম্পন এ সেট করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string>
-    <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। নিঃশব্দ করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string>
+    <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। কম্পন এ সেট করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে মিউট করা হতে পারে।"</string>
+    <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। মিউট করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে মিউট করা হতে পারে।"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s। ভাইব্রেট করতে ট্যাপ করুন।"</string>
-    <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s। নিঃশব্দ করতে ট্যাপ করুন।"</string>
+    <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s। মিউট করতে ট্যাপ করুন।"</string>
     <string name="volume_ringer_hint_mute" msgid="9199811307292269601">"মিউট করুন"</string>
     <string name="volume_ringer_hint_unmute" msgid="6602880133293060368">"আনমিউট করুন"</string>
     <string name="volume_ringer_hint_vibrate" msgid="4036802135666515202">"ভাইব্রেট করান"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"বাঁ দিকের আইকন"</string>
     <string name="right_icon" msgid="3952104823293824311">"ডানদিকের আইকন"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"টাইল যোগ করতে ট্যাপ করে টেনে আনুন"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"সরানোর জন্য এখানে টেনে আনুন"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"অন্তত ৬টি টাইল রাখতে হবে"</string>
     <string name="qs_edit" msgid="2232596095725105230">"সম্পাদনা করুন"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"নীচের অংশ নিয়ে পূর্ণ স্ক্রিন"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g> লোকেশন, <xliff:g id="TILE_NAME">%2$s</xliff:g>৷ সম্পাদনা করতে দুবার আলতো চাপুন৷"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>৷ যোগ করতে দুবার আলতো চাপুন৷"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> অবস্থান৷ নির্বাচন করতে দুবার আলতো চাপুন৷"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> সরান"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> সরান"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="POSITION">%2$d</xliff:g> অবস্থানে <xliff:g id="TILE_NAME">%1$s</xliff:g> যোগ করা হয়েছে"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> মোছা হয়েছে"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> এ সরানো হয়েছে"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>-এ যোগ করুন"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>-এ সরান"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"দ্রুত সেটিংস সম্পাদক৷"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> বিজ্ঞপ্তি: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"অ্যাপ্লিকেশানটি বিভক্ত স্ক্রীনে কাজ নাও করতে পারে৷"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"অ্যাপের তথ্য"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ব্রাউজারে যান"</string>
     <string name="mobile_data" msgid="7094582042819250762">"মোবাইল ডেটা"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ওয়াই ফাই বন্ধ আছে"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ব্লুটুথ বন্ধ আছে"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"বিরক্ত করবেন না বিকল্পটি বন্ধ আছে"</string>
diff --git a/packages/SystemUI/res/values-bn/strings_car.xml b/packages/SystemUI/res/values-bn/strings_car.xml
index 121e517..b40ccdd 100644
--- a/packages/SystemUI/res/values-bn/strings_car.xml
+++ b/packages/SystemUI/res/values-bn/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"অতিথি"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"অতিথি"</string>
     <string name="car_add_user" msgid="5245196248349230898">"ব্যবহারকারীকে যুক্ত করুন"</string>
     <string name="car_new_user" msgid="8142927244990323906">"নতুন ব্যবহারকারী"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"আপনি কোনও নতুন ব্যবহারকারীকে যোগ করলে তাকে তার স্পেস সেট-আপ করে নিতে হবে।"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 0303ffd..57089b8 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -35,8 +35,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obavještenja"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Baterija će se uskoro isprazniti"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>. Preostalo je oko <xliff:g id="TIME">%s</xliff:g>, na osnovu vašeg korištenja"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>. Preostalo je oko <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Još <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Preostalo je oko <xliff:g id="TIME">%2$s</xliff:g>, na osnovu vašeg korištenja"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Još <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Preostalo je oko <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>. Uključena je Ušteda baterije."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Punjenje putem USB-a nije moguće. Koristite punjač koji ste dobili uz uređaj."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Punjenje putem USB-a nije moguće"</string>
@@ -258,7 +258,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aktiviran je zahtjev za lokaciju"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Uklanjanje svih obavještenja."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> i još <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> i još <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Još <xliff:g id="NUMBER_1">%s</xliff:g> obavještenje unutra.</item>
       <item quantity="few">Još <xliff:g id="NUMBER_1">%s</xliff:g> obavještenja unutra.</item>
@@ -310,7 +310,7 @@
     <string name="quick_settings_wifi_label" msgid="9135344704899546041">"WiFi"</string>
     <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nije povezano"</string>
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nema mreže"</string>
-    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WiFi isključen"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WiFi je isključen"</string>
     <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"WiFi uključen"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Nema dostupnih WiFi mreža"</string>
     <string name="quick_settings_wifi_secondary_label_transient" msgid="7748206246119760554">"Uključivanje…"</string>
@@ -328,7 +328,7 @@
     <string name="quick_settings_connected" msgid="1722253542984847487">"Povezano"</string>
     <string name="quick_settings_connected_battery_level" msgid="4136051440381328892">"Povezano, baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="quick_settings_connecting" msgid="47623027419264404">"Povezivanje..."</string>
-    <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Dijeljenje veze"</string>
+    <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Povezivanje putem mobitela"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Pristupna tačka"</string>
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="8010579363691405477">"Uključivanje…"</string>
     <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="5672131949987422420">"Ušteda podataka uklj."</string>
@@ -402,9 +402,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Potpuna\ntišina"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Samo\nprioritetni prekidi"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Samo\nalarmi"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje (još <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do kraja)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo punjenje (još <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do kraja)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo punjenje (još <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do kraja)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje (još <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo punjenje (još <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Brzo punjenje (još <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Zamijeni korisnika"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Zamijeni korisnika. Trenutni korisnik je <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Trenutni korisnik <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -429,6 +429,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ODJAVI KORISNIKA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Želite dodati novog korisnika?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Kada dodate novog korisnika, ta osoba treba uspostaviti svoj prostor.\n\nSvaki korisnik može ažurirati aplikacije za sve ostale korisnike."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Zaista želite ukloniti korisnika?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Sve aplikacije i podaci ovog korisnika bit će izbrisani."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Ukloni"</string>
@@ -736,6 +739,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ikona lijevo"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ikona desno"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Držite i prevucite da dodate polja"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Prevucite ovdje za uklanjanje"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Trebate najmanje šest polja"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
@@ -764,12 +769,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Donji ekran kao cijeli ekran"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dodirnite dvaput za uređivanje."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> Dodirnite dvaput za dodavanje."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>. Dodirnite dvaput za odabir."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Pomjeri <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Ukloni <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> je dodan na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> je uklonjen"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> je premješten na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Dodaj <xliff:g id="TILE_NAME">%1$s</xliff:g> na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Premjesti <xliff:g id="TILE_NAME">%1$s</xliff:g> na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Uređivanje brzih postavki"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> obavještenje: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija možda neće raditi na podijeljenom ekranu"</string>
@@ -830,7 +833,7 @@
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Idi na preglednik"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Prijenos podataka"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"WiFi veza je isključena"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Način rada Ne ometaj je isključen"</string>
diff --git a/packages/SystemUI/res/values-bs/strings_car.xml b/packages/SystemUI/res/values-bs/strings_car.xml
index 6591880..cb2f427 100644
--- a/packages/SystemUI/res/values-bs/strings_car.xml
+++ b/packages/SystemUI/res/values-bs/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gost"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gost"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Dodaj korisnika"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Novi korisnik"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kada dodate novog korisnika, ta osoba treba postaviti svoj prostor."</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 171fd1a..920db25 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacions"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"És possible que la bateria s\'esgoti aviat"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>."</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>; temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>; temps restant aproximat: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Queda un <xliff:g id="PERCENTAGE">%1$s</xliff:g>; temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Queda un <xliff:g id="PERCENTAGE">%1$s</xliff:g>; temps restant aproximat: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>. El mode d\'estalvi de bateria està activat."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"No es pot carregar el dispositiu per USB. Fes servir el carregador original del dispositiu."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"No es pot carregar per USB"</string>
@@ -62,10 +62,10 @@
     <string name="label_view" msgid="6304565553218192990">"Mostra"</string>
     <string name="always_use_device" msgid="4015357883336738417">"Obre sempre <xliff:g id="APPLICATION">%1$s</xliff:g> quan es connecti <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Obre sempre <xliff:g id="APPLICATION">%1$s</xliff:g> quan es connecti <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string>
-    <string name="usb_debugging_title" msgid="4513918393387141949">"Vols permetre la depuració USB?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"L\'empremta digital de la clau de l\'RSA de l\'equip és:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Vols permetre la depuració per USB?"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"L\'empremta digital de la clau de RSA de l\'equip és:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Dona sempre permís des d\'aquest equip"</string>
-    <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"No es permet la depuració USB"</string>
+    <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"No es permet la depuració per USB"</string>
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"L\'usuari que té iniciada la sessió al dispositiu en aquest moment no pot activar la depuració per USB. Per utilitzar aquesta funció, cal canviar a l\'usuari principal."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estira per omplir pant."</string>
@@ -83,7 +83,7 @@
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Munta com a càmera (PTP)"</string>
     <string name="installer_cd_button_title" msgid="2312667578562201583">"Instal·la aplic. transf. fitxers Android per a Mac"</string>
     <string name="accessibility_back" msgid="567011538994429120">"Enrere"</string>
-    <string name="accessibility_home" msgid="8217216074895377641">"Pàgina d\'inici"</string>
+    <string name="accessibility_home" msgid="8217216074895377641">"Inici"</string>
     <string name="accessibility_menu" msgid="316839303324695949">"Menú"</string>
     <string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accessibilitat"</string>
     <string name="accessibility_rotate_button" msgid="7402949513740253006">"Gira la pantalla"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Sol·licituds d\'ubicació actives"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> i <xliff:g id="OVERFLOW">%s</xliff:g> més"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> i <xliff:g id="OVERFLOW">%2$s</xliff:g> més"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> notificacions més a l\'interior.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> notificació més a l\'interior.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silenci\ntotal"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Només\ninterr. prior."</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Només\nalarmes"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant (temps restant: <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant ràpidament (temps restant: <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant lentament (temps restant: <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant (temps restant: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant ràpidament (temps restant: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant lentament (temps restant: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Canvia d\'usuari"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Canvia d\'usuari. Usuari actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Usuari actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"TANCA LA SESSIÓ DE L\'USUARI"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Vols afegir un usuari nou?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Quan s\'afegeix un usuari nou, aquest usuari ha de configurar-se l\'espai.\n\nQualsevol usuari pot actualitzar les aplicacions de la resta d\'usuaris."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Vols suprimir l\'usuari?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Totes les aplicacions i les dades d\'aquest usuari se suprimiran."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Suprimeix"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Icona de l\'esquerra"</string>
     <string name="right_icon" msgid="3952104823293824311">"Icona de la dreta"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Mantén premut i arrossega per afegir funcions"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrossega aquí per suprimir una funció"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Necessites com a mínim 6 mosaics"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edita"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Pantalla inferior completa"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posició <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Fes doble toc per editar-la."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Fes doble toc per afegir-ho."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posició <xliff:g id="POSITION">%1$d</xliff:g>. Fes doble toc per seleccionar-la."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mou <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Suprimeix <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha afegit a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha suprimit"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha mogut a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Afegeix <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Mou <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de configuració ràpida."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notificació de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"És possible que l\'aplicació no funcioni amb la pantalla dividida."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Ves al navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dades mòbils"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"La Wi-Fi està desactivada"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"El Bluetooth està desactivat"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"El mode No molestis està desactivat"</string>
diff --git a/packages/SystemUI/res/values-ca/strings_car.xml b/packages/SystemUI/res/values-ca/strings_car.xml
index 47d59dd..80df882 100644
--- a/packages/SystemUI/res/values-ca/strings_car.xml
+++ b/packages/SystemUI/res/values-ca/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Convidat"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Convidat"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Afegeix un usuari"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Usuari nou"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Quan s\'afegeix un usuari nou, aquest usuari ha de configurar el seu espai."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index d72b1d1..4077908 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -36,8 +36,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Oznámení"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Baterie se brzy vybije"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>, při obvyklém využití asi <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>, asi <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Zbývá <xliff:g id="PERCENTAGE">%1$s</xliff:g>, při obvyklém využití asi <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Zbývá <xliff:g id="PERCENTAGE">%1$s</xliff:g>, asi <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>. Spořič baterie je zapnutý."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Nabíjení přes USB nefunguje. Používejte originální nabíječku, která byla dodána spolu se zařízením."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Nabíjení přes USB nefunguje"</string>
@@ -64,11 +64,11 @@
     <string name="label_view" msgid="6304565553218192990">"Zobrazit"</string>
     <string name="always_use_device" msgid="4015357883336738417">"Když bude připojeno zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>, vždy otevřít <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Když bude připojeno zařízení <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>, vždy otevřít <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
-    <string name="usb_debugging_title" msgid="4513918393387141949">"Povolit ladění USB?"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Povolit ladění přes USB?"</string>
     <string name="usb_debugging_message" msgid="2220143855912376496">"Digitální otisk RSA počítače je:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Vždy povolit z tohoto počítače"</string>
-    <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Ladění USB není povoleno"</string>
-    <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Uživatel aktuálně přihlášený k tomuto zařízení nemůže zapnout ladění USB. Chcete-li tuto funkci použít, přepněte na primárního uživatele."</string>
+    <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Ladění přes USB není povoleno"</string>
+    <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Uživatel aktuálně přihlášený k tomuto zařízení nemůže zapnout ladění přes USB. Chcete-li tuto funkci použít, přepněte na primárního uživatele."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Přiblížit na celou obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Snímek obrazovky"</string>
@@ -261,7 +261,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aktivní žádosti o polohu"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazat všechna oznámení."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"a ještě <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="few">Skupina obsahuje ještě <xliff:g id="NUMBER_1">%s</xliff:g> oznámení.</item>
       <item quantity="many">Skupina obsahuje ještě <xliff:g id="NUMBER_1">%s</xliff:g> oznámení.</item>
@@ -407,9 +407,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Úplné\nticho"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Pouze\nprioritní"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Pouze\nbudíky"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rychlé nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Pomalé nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rychlé nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Pomalé nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Přepnout uživatele"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Přepnout uživatele, aktuální uživatel: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Aktuální uživatel <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -434,6 +434,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ODHLÁSIT UŽIVATELE"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Přidat nového uživatele?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Když přidáte nového uživatele, musí si nastavit vlastní prostor.\n\nJakýkoli uživatel může aktualizovat aplikace všech ostatních uživatelů."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Odstranit uživatele?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Veškeré aplikace a data tohoto uživatele budou smazána."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Odstranit"</string>
@@ -741,6 +744,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ikona vlevo"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ikona vpravo"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Dlaždice přidáte podržením a přetažením"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Přetažením sem dlaždice odstraníte"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Potřebujete minimálně šest dlaždic"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Upravit"</string>
@@ -769,12 +774,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Dolní část na celou obrazovku"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozice <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvojitým klepnutím ji upravíte."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dlaždici přidáte dvojitým klepnutím."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozice <xliff:g id="POSITION">%1$d</xliff:g>. Dvojitým klepnutím ji vyberete."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Přesunout dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Odstranit dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Dlaždice <xliff:g id="TILE_NAME">%1$s</xliff:g> byla přidána na pozici <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Dlaždice <xliff:g id="TILE_NAME">%1$s</xliff:g> byla odstraněna"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Dlaždice <xliff:g id="TILE_NAME">%1$s</xliff:g> byla přesunuta na pozici <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Přidat dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozici <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Přesunout dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozici <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor rychlého nastavení"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Oznámení aplikace <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikace v režimu rozdělené obrazovky nemusí fungovat."</string>
@@ -835,7 +838,7 @@
     <string name="app_info" msgid="6856026610594615344">"O aplikaci"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Přejít do prohlížeče"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilní data"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je vypnuta"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je vypnuto"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Režim Nerušit je vypnut"</string>
diff --git a/packages/SystemUI/res/values-cs/strings_car.xml b/packages/SystemUI/res/values-cs/strings_car.xml
index 7f29118..0f09aca 100644
--- a/packages/SystemUI/res/values-cs/strings_car.xml
+++ b/packages/SystemUI/res/values-cs/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Host"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Host"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Přidat uživatele"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nový uživatel"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Každý nově přidaný uživatel si musí nastavit vlastní prostor."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index fff619b..2ebc0e8 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Underretninger"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Enheden løber muligvis snart tør for batteri"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> tilbage"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Der er <xliff:g id="PERCENTAGE">%s</xliff:g> tilbage eller ca. <xliff:g id="TIME">%s</xliff:g>, alt efter hvordan du bruger enheden"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> tilbage eller ca. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Der er <xliff:g id="PERCENTAGE">%1$s</xliff:g> tilbage eller ca. <xliff:g id="TIME">%2$s</xliff:g>, alt efter hvordan du bruger enheden"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> tilbage eller ca. <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> tilbage. Batterisparefunktion er aktiveret."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Enheden kan ikke oplades via USB. Brug den oplader, der fulgte med din enhed."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Enheden kan ikke oplades via USB"</string>
@@ -43,7 +43,7 @@
     <string name="battery_low_why" msgid="4553600287639198111">"Indstillinger"</string>
     <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"Vil du aktivere Batterisparefunktion?"</string>
     <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"Aktivér"</string>
-    <string name="battery_saver_start_action" msgid="8187820911065797519">"Aktivér Batterisparefunktion"</string>
+    <string name="battery_saver_start_action" msgid="8187820911065797519">"Aktivér batterisparefunktion"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Indstillinger"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Automatisk skærmrotation"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aktive placeringsanmodninger"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle underretninger."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"<xliff:g id="NUMBER">%s</xliff:g> mere"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> underretning mere i gruppen.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> underretninger mere i gruppen.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nstilhed"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Kun\nprioritet"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Kun\nalarmer"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader hurtigt (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader langsomt (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader hurtigt (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader langsomt (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Skift bruger"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Skift bruger. Nuværende bruger er <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Nuværende bruger: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,12 +426,15 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"LOG BRUGEREN UD"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Vil du tilføje den nye bruger?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Når du tilføjer en ny bruger, skal personen konfigurere sit område.\n\nEnhver bruger kan opdatere apps for alle andre brugere."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Vil du fjerne brugeren?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Alle apps og data for denne bruger slettes."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Fjern"</string>
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"Batterisparefunktion er aktiveret"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"Reducerer ydeevne og baggrundsdata"</string>
-    <string name="battery_saver_notification_action_text" msgid="132118784269455533">"Deaktiver Batterisparefunktion"</string>
+    <string name="battery_saver_notification_action_text" msgid="132118784269455533">"Deaktiver batterisparefunktion"</string>
     <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vil begynde at optage alt, hvad der vises på din skærm."</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Vis ikke igen"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Ryd alt"</string>
@@ -680,7 +683,7 @@
     <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applikationer"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistance"</string>
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
-    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktpersoner"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakter"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="638701213803242744">"Sms"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Venstre ikon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Højre ikon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Tilføj felter ved at holde dem nede og trække"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Træk herhen for at fjerne"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Du skal bruge mindst seks felter"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Rediger"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Vis nederste del i fuld skærm"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tryk to gange for at redigere."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tryk to gange for at tilføje."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Tryk to gange for at vælge."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Flyt <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Fjern <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> føjes til position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> fjernes"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> blev flyttet til position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Føj <xliff:g id="TILE_NAME">%1$s</xliff:g> til position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Flyt <xliff:g id="TILE_NAME">%1$s</xliff:g> til position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigeringsværktøj for Hurtige indstillinger."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g>-underretning: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Appen fungerer muligvis ikke i delt skærm."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Appinfo"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Gå til en browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er slået fra"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth er slået fra"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Forstyr ikke er slået fra"</string>
diff --git a/packages/SystemUI/res/values-da/strings_car.xml b/packages/SystemUI/res/values-da/strings_car.xml
index 1e7bbbf..f0d14a0 100644
--- a/packages/SystemUI/res/values-da/strings_car.xml
+++ b/packages/SystemUI/res/values-da/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gæst"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gæst"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Tilføj bruger"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Ny bruger"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Når du tilføjer en ny bruger, skal vedkommende konfigurere sit område."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index d3d9458..6636c9d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Benachrichtigungen"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Der Akku ist fast leer"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> verbleibend"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ausstehend; noch ca. <xliff:g id="TIME">%s</xliff:g>, basierend auf deiner Nutzung"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ausstehend; noch ca. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ausstehend; noch ca. <xliff:g id="TIME">%2$s</xliff:g>, basierend auf deiner Nutzung"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ausstehend; noch ca. <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Noch <xliff:g id="PERCENTAGE">%s</xliff:g>. Der Energiesparmodus ist aktiviert."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Aufladen über USB nicht möglich. Verwende das mit dem Gerät gelieferte Ladegerät."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Aufladen über USB nicht möglich"</string>
@@ -261,7 +261,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Standortanfragen aktiv"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> weitere Benachrichtigungen vorhanden.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> weitere Benachrichtigung vorhanden.</item>
@@ -403,9 +403,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Laut-\nlos"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Nur\nwichtige"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Nur\nWecker"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird schnell geladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird langsam geladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird schnell geladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird langsam geladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Nutzer wechseln"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Nutzer wechseln. Aktueller Nutzer: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Aktueller Nutzer <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -430,6 +430,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"Nutzer abmelden"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Neuen Nutzer hinzufügen?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Wenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten.\n\nJeder Nutzer kann Apps für alle anderen Nutzer aktualisieren."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Nutzer entfernen?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Alle Apps und Daten dieses Nutzers werden gelöscht."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Entfernen"</string>
@@ -733,6 +736,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Linkes Symbol"</string>
     <string name="right_icon" msgid="3952104823293824311">"Rechtes Symbol"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Halten und ziehen, um Kacheln hinzuzufügen"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Zum Entfernen hierher ziehen"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Du brauchst mindestens sechs Kacheln"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Bearbeiten"</string>
@@ -761,12 +766,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Vollbild unten"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Zum Bearbeiten doppeltippen."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Zum Hinzufügen doppeltippen."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Zum Auswählen doppeltippen."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verschieben"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> entfernen"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ist auf Position <xliff:g id="POSITION">%2$d</xliff:g> hinzugefügt worden"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> wurde entfernt"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> an Position <xliff:g id="POSITION">%2$d</xliff:g> verschoben"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> auf Position <xliff:g id="POSITION">%2$d</xliff:g> hinzufügen"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> auf Position <xliff:g id="POSITION">%2$d</xliff:g> verschieben"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor für Schnelleinstellungen."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Benachrichtigung von <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Die App funktioniert unter Umständen bei geteiltem Bildschirm nicht."</string>
@@ -827,7 +830,7 @@
     <string name="app_info" msgid="6856026610594615344">"App-Informationen"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Browser öffnen"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile Daten"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"WLAN ist deaktiviert"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ist deaktiviert"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Nicht stören\" ist deaktiviert"</string>
diff --git a/packages/SystemUI/res/values-de/strings_car.xml b/packages/SystemUI/res/values-de/strings_car.xml
index bf03f5d..b55a2e5 100644
--- a/packages/SystemUI/res/values-de/strings_car.xml
+++ b/packages/SystemUI/res/values-de/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gast"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gast"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Nutzer hinzufügen"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Neuer Nutzer"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Wenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 45e1b1b..60c412a 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ειδοποιήσεις"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Η μπαταρία μπορεί να εξαντληθεί σύντομα"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Απομένουν <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Απομένει <xliff:g id="PERCENTAGE">%s</xliff:g>, περίπου <xliff:g id="TIME">%s</xliff:g> με βάση τη χρήση σας"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Απομένει <xliff:g id="PERCENTAGE">%s</xliff:g>, περίπου <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Απομένει <xliff:g id="PERCENTAGE">%1$s</xliff:g>, περίπου <xliff:g id="TIME">%2$s</xliff:g> με βάση τη χρήση σας"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Απομένει <xliff:g id="PERCENTAGE">%1$s</xliff:g>, περίπου <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Απομένουν <xliff:g id="PERCENTAGE">%s</xliff:g>. Η Εξοικονόμηση μπαταρίας είναι ενεργή."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Δεν είναι δυνατή η φόρτιση μέσω USB. Χρησιμοποιήστε τον φορτιστή που συνοδεύει τη συσκευή σας."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Δεν είναι δυνατή η φόρτιση μέσω USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Τα αιτήματα τοποθεσίας έχουν ενεργοποιηθεί"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Διαγραφή όλων των ειδοποιήσεων."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> επιπλέον ειδοποιήσεις εντός της ομάδας.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> επιπλέον ειδοποίηση εντός της ομάδας.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Πλήρης\nσίγαση"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Μόνο\nπροτεραιότητας"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Μόνο\nειδοποιήσεις"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Γρήγορη φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Αργή φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> για πλήρη φόρτιση)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Γρήγορη φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> για πλήρη φόρτιση)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Αργή φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> για πλήρη φόρτιση)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Εναλλαγή χρήστη"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Εναλλαγή χρήστη, τρέχων χρήστης <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Τρέχων χρήστης <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ΑΠΟΣΥΝΔΕΣΗ ΧΡΗΣΤΗ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Προσθήκη νέου χρήστη;"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Κατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει το χώρο του.\n\nΟποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Κατάργηση χρήστη;"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Όλες οι εφαρμογές και τα δεδομένα αυτού του χρήστη θα διαγραφούν."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Κατάργηση"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Αριστερό εικονίδιο"</string>
     <string name="right_icon" msgid="3952104823293824311">"Δεξιό εικονίδιο"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Κρατήστε και σύρετε για την προσθήκη πλακιδίων"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Σύρετε εδώ για κατάργηση"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Απαιτούνται τουλάχιστον 6 πλακίδια"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Επεξεργασία"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Κάτω πλήρης οθόνη"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Θέση <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Πατήστε δύο φορές για επεξεργασία."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Πατήστε δύο φορές για προσθήκη."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Θέση <xliff:g id="POSITION">%1$d</xliff:g>. Πατήστε δύο φορές για επιλογή."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Μετακίνηση <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Κατάργηση <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Το <xliff:g id="TILE_NAME">%1$s</xliff:g> προστέθηκε στη θέση <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Το <xliff:g id="TILE_NAME">%1$s</xliff:g> καταργείται"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Το <xliff:g id="TILE_NAME">%1$s</xliff:g> μετακινήθηκε στη θέση <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Προσθήκη <xliff:g id="TILE_NAME">%1$s</xliff:g> στη θέση <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Μετακίνηση <xliff:g id="TILE_NAME">%1$s</xliff:g> στη θέση <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Επεξεργασία γρήγορων ρυθμίσεων."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Ειδοποίηση <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Δεν είναι δυνατή η λειτουργία της εφαρμογής με διαχωρισμό οθόνης."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Μετάβ. σε πρόγ. περ."</string>
     <string name="mobile_data" msgid="7094582042819250762">"Δεδομένα κινητής τηλεφωνίας"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Το Wi-Fi είναι ανενεργό"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Το Bluetooth είναι ανενεργό"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Η λειτουργία \"Μην ενοχλείτε\" είναι ανενεργή"</string>
diff --git a/packages/SystemUI/res/values-el/strings_car.xml b/packages/SystemUI/res/values-el/strings_car.xml
index 37e4e92b..7b67ed5 100644
--- a/packages/SystemUI/res/values-el/strings_car.xml
+++ b/packages/SystemUI/res/values-el/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Επισκέπτης"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Επισκέπτης"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Προσθήκη χρήστη"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Νέος χρήστης"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Όταν προσθέτετε έναν νέο χρήστη, αυτός ο χρήστης θα πρέπει να ρυθμίσει τον χώρο του."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 561601d..c0afae6 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Battery may run out soon"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left based on your usage"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> remaining, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> remaining, about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery Saver is on."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Can\'t charge via USB. Use the charger that came with your device."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Can\'t charge via USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> more notification inside.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nsilence"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Switch user, current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,11 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"LOGOUT USER"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+    <string name="user_limit_reached_title" msgid="7374910700117359177">"User limit reached"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
+      <item quantity="one">Only one user can be created.</item>
+    </plurals>
     <string name="user_remove_user_title" msgid="4681256956076895559">"Remove user?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"All apps and data of this user will be deleted."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Remove"</string>
@@ -729,6 +734,7 @@
     <string name="left_icon" msgid="3096287125959387541">"Left icon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Right icon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Hold and drag to add tiles"</string>
+    <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Hold and drag to rearrange tiles"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Drag here to remove"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"You need at least 6 tiles"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
@@ -757,12 +763,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Bottom full screen"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Double tap to select."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is added to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is removed"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> moved to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Add <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Quick settings editor."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
@@ -823,7 +827,7 @@
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_car.xml b/packages/SystemUI/res/values-en-rAU/strings_car.xml
index e058c5b..5ff5a52 100644
--- a/packages/SystemUI/res/values-en-rAU/strings_car.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Guest"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Guest"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Add User"</string>
     <string name="car_new_user" msgid="8142927244990323906">"New User"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"When you add a new user, that person needs to set up their space."</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index efa8ad2..488c748 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Battery may run out soon"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left based on your usage"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> remaining, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> remaining, about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery Saver is on."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Can\'t charge via USB. Use the charger that came with your device."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Can\'t charge via USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> more notification inside.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nsilence"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Switch user, current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,11 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"LOGOUT USER"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+    <string name="user_limit_reached_title" msgid="7374910700117359177">"User limit reached"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
+      <item quantity="one">Only one user can be created.</item>
+    </plurals>
     <string name="user_remove_user_title" msgid="4681256956076895559">"Remove user?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"All apps and data of this user will be deleted."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Remove"</string>
@@ -729,6 +734,7 @@
     <string name="left_icon" msgid="3096287125959387541">"Left icon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Right icon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Hold and drag to add tiles"</string>
+    <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Hold and drag to rearrange tiles"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Drag here to remove"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"You need at least 6 tiles"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
@@ -757,12 +763,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Bottom full screen"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Double tap to select."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is added to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is removed"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> moved to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Add <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Quick settings editor."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
@@ -823,7 +827,7 @@
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings_car.xml b/packages/SystemUI/res/values-en-rCA/strings_car.xml
index e058c5b..5ff5a52 100644
--- a/packages/SystemUI/res/values-en-rCA/strings_car.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Guest"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Guest"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Add User"</string>
     <string name="car_new_user" msgid="8142927244990323906">"New User"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"When you add a new user, that person needs to set up their space."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 561601d..c0afae6 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Battery may run out soon"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left based on your usage"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> remaining, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> remaining, about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery Saver is on."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Can\'t charge via USB. Use the charger that came with your device."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Can\'t charge via USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> more notification inside.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nsilence"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Switch user, current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,11 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"LOGOUT USER"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+    <string name="user_limit_reached_title" msgid="7374910700117359177">"User limit reached"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
+      <item quantity="one">Only one user can be created.</item>
+    </plurals>
     <string name="user_remove_user_title" msgid="4681256956076895559">"Remove user?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"All apps and data of this user will be deleted."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Remove"</string>
@@ -729,6 +734,7 @@
     <string name="left_icon" msgid="3096287125959387541">"Left icon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Right icon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Hold and drag to add tiles"</string>
+    <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Hold and drag to rearrange tiles"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Drag here to remove"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"You need at least 6 tiles"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
@@ -757,12 +763,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Bottom full screen"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Double tap to select."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is added to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is removed"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> moved to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Add <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Quick settings editor."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
@@ -823,7 +827,7 @@
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_car.xml b/packages/SystemUI/res/values-en-rGB/strings_car.xml
index e058c5b..5ff5a52 100644
--- a/packages/SystemUI/res/values-en-rGB/strings_car.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Guest"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Guest"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Add User"</string>
     <string name="car_new_user" msgid="8142927244990323906">"New User"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"When you add a new user, that person needs to set up their space."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 561601d..c0afae6 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Battery may run out soon"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left based on your usage"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> remaining, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> remaining, about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery Saver is on."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Can\'t charge via USB. Use the charger that came with your device."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Can\'t charge via USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> more notification inside.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nsilence"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> until full)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Switch user, current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,11 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"LOGOUT USER"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+    <string name="user_limit_reached_title" msgid="7374910700117359177">"User limit reached"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
+      <item quantity="one">Only one user can be created.</item>
+    </plurals>
     <string name="user_remove_user_title" msgid="4681256956076895559">"Remove user?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"All apps and data of this user will be deleted."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Remove"</string>
@@ -729,6 +734,7 @@
     <string name="left_icon" msgid="3096287125959387541">"Left icon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Right icon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Hold and drag to add tiles"</string>
+    <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"Hold and drag to rearrange tiles"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Drag here to remove"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"You need at least 6 tiles"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
@@ -757,12 +763,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Bottom full screen"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Double tap to select."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is added to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is removed"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> moved to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Add <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Quick settings editor."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
@@ -823,7 +827,7 @@
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_car.xml b/packages/SystemUI/res/values-en-rIN/strings_car.xml
index e058c5b..5ff5a52 100644
--- a/packages/SystemUI/res/values-en-rIN/strings_car.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Guest"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Guest"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Add User"</string>
     <string name="car_new_user" msgid="8142927244990323906">"New User"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"When you add a new user, that person needs to set up their space."</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 881ee90..f775bb1 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‎Notifications‎‏‎‎‏‎"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‎Battery may run out soon‎‏‎‎‏‎"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ remaining, about ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ remaining, about ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ remaining, about ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ remaining, about ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ remaining. Battery Saver is on.‎‏‎‎‏‎"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎Can\'t charge via USB. Use the charger that came with your device.‎‏‎‎‏‎"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎Can\'t charge via USB‎‏‎‎‏‎"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎Location requests active‎‏‎‎‏‎"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎Clear all notifications.‎‏‎‎‏‎"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎+ ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>‎‏‎‎‏‏‏‎, +‎‏‎‎‏‏‎<xliff:g id="OVERFLOW">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>‎‏‎‎‏‏‏‎, +‎‏‎‎‏‏‎<xliff:g id="OVERFLOW">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%s</xliff:g>‎‏‎‎‏‏‏‎ more notifications inside.‎‏‎‎‏‎</item>
       <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%s</xliff:g>‎‏‎‎‏‏‏‎ more notification inside.‎‏‎‎‏‎</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎Total‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎silence‎‏‎‎‏‎"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‎‎‎Priority‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎only‎‏‎‎‏‎"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‏‏‎‎‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎Alarms‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎only‎‏‎‎‏‎"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging (‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>‎‏‎‎‏‏‏‎ until full)‎‏‎‎‏‎"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly (‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>‎‏‎‎‏‏‏‎ until full)‎‏‎‎‏‎"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly (‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>‎‏‎‎‏‏‏‎ until full)‎‏‎‎‏‎"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging (‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎ until full)‎‏‎‎‏‎"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly (‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎ until full)‎‏‎‎‏‎"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly (‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎ until full)‎‏‎‎‏‎"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎Switch user‎‏‎‎‏‎"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎Switch user, current user ‎‏‎‎‏‏‎<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎Current user ‎‏‎‎‏‏‎<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
@@ -426,6 +426,11 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎LOGOUT USER‎‏‎‎‏‎"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎Add new user?‎‏‎‎‏‎"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‏‎When you add a new user, that person needs to set up their space.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Any user can update apps for all other users.‎‏‎‎‏‎"</string>
+    <string name="user_limit_reached_title" msgid="7374910700117359177">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‎User limit reached‎‏‎‎‏‎"</string>
+    <plurals name="user_limit_reached_message" formatted="false" msgid="1855040563671964242">
+      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎You can add up to ‎‏‎‎‏‏‎<xliff:g id="COUNT">%d</xliff:g>‎‏‎‎‏‏‏‎ users.‎‏‎‎‏‎</item>
+      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎Only one user can be created.‎‏‎‎‏‎</item>
+    </plurals>
     <string name="user_remove_user_title" msgid="4681256956076895559">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‏‏‏‎Remove user?‎‏‎‎‏‎"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎All apps and data of this user will be deleted.‎‏‎‎‏‎"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎Remove‎‏‎‎‏‎"</string>
@@ -729,6 +734,7 @@
     <string name="left_icon" msgid="3096287125959387541">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎Left icon‎‏‎‎‏‎"</string>
     <string name="right_icon" msgid="3952104823293824311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎Right icon‎‏‎‎‏‎"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎Hold and drag to add tiles‎‏‎‎‏‎"</string>
+    <string name="drag_to_rearrange_tiles" msgid="4566074720193667473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‏‎‎‏‎‎‎‏‎Hold and drag to rearrange tiles‎‏‎‎‏‎"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‎Drag here to remove‎‏‎‎‏‎"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎You need at least 6 tiles‎‏‎‎‏‎"</string>
     <string name="qs_edit" msgid="2232596095725105230">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎Edit‎‏‎‎‏‎"</string>
@@ -757,12 +763,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‎Bottom full screen‎‏‎‎‏‎"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎Position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%1$d</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎. Double tap to edit.‎‏‎‎‏‎"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. Double tap to add.‎‏‎‎‏‎"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‏‏‎Position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%1$d</xliff:g>‎‏‎‎‏‏‏‎. Double tap to select.‎‏‎‎‏‎"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‏‏‎‎Move ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎Remove ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is added to position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%2$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is removed‎‏‎‎‏‎"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ moved to position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%2$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎Add ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%2$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‎‎Move ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%2$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‎Quick settings editor.‎‏‎‎‏‎"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="ID_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ notification: ‎‏‎‎‏‏‎<xliff:g id="ID_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎App may not work with split-screen.‎‏‎‎‏‎"</string>
@@ -823,7 +827,7 @@
     <string name="app_info" msgid="6856026610594615344">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‎‎‎App info‎‏‎‎‏‎"</string>
     <string name="go_to_web" msgid="2650669128861626071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎Go to browser‎‏‎‎‏‎"</string>
     <string name="mobile_data" msgid="7094582042819250762">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎Mobile data‎‏‎‎‏‎"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="ID_1">%s</xliff:g>‎‏‎‎‏‏‏‎ — ‎‏‎‎‏‏‎<xliff:g id="ID_2">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="ID_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ — ‎‏‎‎‏‏‎<xliff:g id="ID_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎Wi-Fi is off‎‏‎‎‏‎"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‎‎‎‎Bluetooth is off‎‏‎‎‏‎"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎Do Not Disturb is off‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings_car.xml b/packages/SystemUI/res/values-en-rXC/strings_car.xml
index fe91bea..deb7021 100644
--- a/packages/SystemUI/res/values-en-rXC/strings_car.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‎Guest‎‏‎‎‏‎"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎Guest‎‏‎‎‏‎"</string>
     <string name="car_add_user" msgid="5245196248349230898">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎‎Add User‎‏‎‎‏‎"</string>
     <string name="car_new_user" msgid="8142927244990323906">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎New User‎‏‎‎‏‎"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‎‏‎When you add a new user, that person needs to set up their space.‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 6681dbb..f5587fe 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Es posible que pronto se agote la batería"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería."</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Batería: <xliff:g id="PERCENTAGE">%s</xliff:g> (tiempo restante aproximado según tu uso: <xliff:g id="TIME">%s</xliff:g>)"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Batería: <xliff:g id="PERCENTAGE">%s</xliff:g> (tiempo restante aproximado: <xliff:g id="TIME">%s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Batería: <xliff:g id="PERCENTAGE">%1$s</xliff:g> (tiempo restante aproximado según tu uso: <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Batería: <xliff:g id="PERCENTAGE">%1$s</xliff:g> (tiempo restante aproximado: <xliff:g id="TIME">%2$s</xliff:g>)"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Queda <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. El Ahorro de batería está activado."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"No se puede cargar mediante USB. Usa el cargador que se incluyó con el dispositivo."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"No se puede cargar mediante USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de ubicación activas"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas las notificaciones"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"<xliff:g id="NUMBER">%s</xliff:g> más"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> (+<xliff:g id="OVERFLOW">%s</xliff:g>)"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (+<xliff:g id="OVERFLOW">%2$s</xliff:g>)"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> notificaciones más en el grupo.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> notificación más en el grupo.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silencio\ntotal"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Solo\nprioridad"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Solo\nalarmas"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando rápido (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lento (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> para completar)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando rápido (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> para completar)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lento (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> para completar)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambiar usuario"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambiar de usuario (usuario actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"El usuario actual es <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"SALIR DE SESIÓN DEL USUARIO"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"¿Agregar usuario nuevo?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Cuando agregas un nuevo usuario, esa persona debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de los usuarios."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"¿Confirmas que quieres quitar el usuario?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Se borrarán todas las aplicaciones y los datos de este usuario."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Quitar"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ícono izquierdo"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ícono derecho"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Mantén presionado para agregar mosaicos"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra aquí para quitar"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Necesitas al menos 6 mosaicos"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Pantalla inferior completa"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Presiona dos veces para editarla."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Presiona dos veces para agregarlo."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posición <xliff:g id="POSITION">%1$d</xliff:g>. Presiona dos veces para seleccionarla."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Quitar <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Se agregó <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Se quitó <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Se movió <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Agregar <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de Configuración rápida"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Es posible que la app no funcione en el modo de pantalla dividida."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Información de apps"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Ir al navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Datos móviles"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desactivado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"No interrumpir desactivado"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_car.xml b/packages/SystemUI/res/values-es-rUS/strings_car.xml
index c81573eb8..7187bef 100644
--- a/packages/SystemUI/res/values-es-rUS/strings_car.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Invitado"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Invitado"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Agregar usuario"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nuevo usuario"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Cuando agregues un usuario nuevo, esa persona deberá configurar su espacio."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 27daa5c..e78e130 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Es posible que te quedes sin batería pronto"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> (tiempo restante aproximado según tu uso: <xliff:g id="TIME">%s</xliff:g>)"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> (tiempo restante aproximado: <xliff:g id="TIME">%s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Queda un <xliff:g id="PERCENTAGE">%1$s</xliff:g> (tiempo restante aproximado según tu uso: <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Queda un <xliff:g id="PERCENTAGE">%1$s</xliff:g> (tiempo restante aproximado: <xliff:g id="TIME">%2$s</xliff:g>)"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. Se ha activado la función Ahorro de energía."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"No se puede cargar por USB. Utiliza el cargador original incluido con el dispositivo."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"No se puede cargar por USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de ubicación activas"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar todas las notificaciones"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"<xliff:g id="NUMBER">%s</xliff:g> más"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> (+ <xliff:g id="OVERFLOW">%s</xliff:g>)"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (+ <xliff:g id="OVERFLOW">%2$s</xliff:g>)"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> notificaciones más dentro.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> notificación más dentro.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silencio\ntotal"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Solo\ncon prioridad"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Solo\nalarmas"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para carga completa)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para carga completa)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para carga completa)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> para carga completa)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> para carga completa)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> para carga completa)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambiar de usuario"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambiar de usuario (usuario actual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Usuario actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"SALIR DE USUARIO"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"¿Añadir nuevo usuario?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Al añadir un nuevo usuario, este debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de usuarios."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"¿Quitar usuario?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Se eliminarán todas las aplicaciones y todos los datos de este usuario."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Quitar"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Icono a la izquierda"</string>
     <string name="right_icon" msgid="3952104823293824311">"Icono a la derecha"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Pulsa y arrastra para añadir funciones"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra aquí para quitar una función"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Necesitas 6 mosaicos como mínimo"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Pantalla inferior completa"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toca dos veces para cambiarla."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toca dos veces para añadirlo."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posición <xliff:g id="POSITION">%1$d</xliff:g>. Toca dos veces para seleccionarla."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Quitar <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> se ha añadido a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> se ha quitado"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> se ha movido a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Añadir <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de ajustes rápidos."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Es posible que la aplicación no funcione con la pantalla dividida."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Ir al navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Datos móviles"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> ‑ <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> ‑ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desactivado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"No molestar está desactivado"</string>
diff --git a/packages/SystemUI/res/values-es/strings_car.xml b/packages/SystemUI/res/values-es/strings_car.xml
index 7da21a8..7758113 100644
--- a/packages/SystemUI/res/values-es/strings_car.xml
+++ b/packages/SystemUI/res/values-es/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Invitado"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Invitado"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Añadir usuario"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nuevo usuario"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Al añadir un nuevo usuario, este debe configurar su espacio."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index c309294..68cb738 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Märguanded"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Aku võib peagi tühjaks saada"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Jäänud on <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> on alles, teie kasutuse põhjal on jäänud umbes <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> on alles, umbes <xliff:g id="TIME">%s</xliff:g> on jäänud"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> on alles, teie kasutuse põhjal on jäänud umbes <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> on alles, umbes <xliff:g id="TIME">%2$s</xliff:g> on jäänud"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Jäänud on <xliff:g id="PERCENTAGE">%s</xliff:g>. Akusäästja on sisse lülitatud."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Ei saa USB kaudu laadida. Kasutage seadmega kaasas olnud laadijat."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Ei saa USB kaudu laadida"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Asukoha taotlused on aktiivsed"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Kustuta kõik teatised."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, üle <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, üle <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Sees on veel <xliff:g id="NUMBER_1">%s</xliff:g> märguannet.</item>
       <item quantity="one">Sees on veel <xliff:g id="NUMBER_0">%s</xliff:g> märguanne.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Täielik\nvaikus"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Ainult\nprioriteetsed"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Ainult\nalarmid"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine (täislaadimiseks kulub <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kiirlaadim. (täislaadimiseks kulub <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Aegl. laad. (täislaadimiseks kulub <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine (täislaadimiseks kulub <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kiirlaadim. (täislaadimiseks kulub <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Aegl. laad. (täislaadimiseks kulub <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Kasutaja vahetamine"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Kasutaja vahetamine, praegune kasutaja: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Praegune kasutaja <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"LOGI KASUTAJA VÄLJA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Kas lisada uus kasutaja?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Kui lisate uue kasutaja, siis peab ta seadistama oma ruumi.\n\nIga kasutaja saab värskendada rakendusi kõigi kasutajate jaoks."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Kas eemaldada kasutaja?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Kasutaja kõik rakendused ja andmed kustutatakse."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Eemalda"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Vasak ikoon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Parem ikoon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Paanide lisamiseks hoidke all ja lohistage"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Lohistage eemaldamiseks siia"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Teil on vaja vähemalt kuut paani"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Muutmine"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Alumine täisekraan"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Asend <xliff:g id="POSITION">%1$d</xliff:g>, paan <xliff:g id="TILE_NAME">%2$s</xliff:g>. Topeltpuudutage muutmiseks."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Topeltpuudutage lisamiseks."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Asend <xliff:g id="POSITION">%1$d</xliff:g>. Topeltpuudutage valimiseks."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Paani <xliff:g id="TILE_NAME">%1$s</xliff:g> teisaldamine"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Paani <xliff:g id="TILE_NAME">%1$s</xliff:g> eemaldamine"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Paan <xliff:g id="TILE_NAME">%1$s</xliff:g> lisati asendisse <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Paan <xliff:g id="TILE_NAME">%1$s</xliff:g> eemaldati"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Paan <xliff:g id="TILE_NAME">%1$s</xliff:g> teisaldati asendisse <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Lisage <xliff:g id="TILE_NAME">%1$s</xliff:g> asendisse <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Teisaldage <xliff:g id="TILE_NAME">%1$s</xliff:g> asendisse <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Kiirseadete redigeerija."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Teenuse <xliff:g id="ID_1">%1$s</xliff:g> märguanne: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Rakendus ei pruugi poolitatud ekraaniga töötada."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Ava brauser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiilne andmeside"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"WiFi on välja lülitatud"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth on välja lülitatud"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Funktsioon Mitte segada on välja lülitatud"</string>
diff --git a/packages/SystemUI/res/values-et/strings_car.xml b/packages/SystemUI/res/values-et/strings_car.xml
index 9ed97aa..fd93f94 100644
--- a/packages/SystemUI/res/values-et/strings_car.xml
+++ b/packages/SystemUI/res/values-et/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Külaline"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Külaline"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Kasutaja lisamine"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Uus kasutaja"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kui lisate uue kasutaja, siis peab ta seadistama oma ruumi."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index d2dbc79..e203b76 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Jakinarazpenak"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Laster agortuko da bateria"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da; <xliff:g id="TIME">%s</xliff:g> inguru gelditzen dira, erabileraren arabera"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da; <xliff:g id="TIME">%s</xliff:g> inguru gelditzen dira"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> gelditzen da; <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen dira, erabileraren arabera"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> gelditzen da; <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen dira"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da. Bateria-aurrezlea aktibatuta dago."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Ezin da USB bidez kargatu. Erabili gailuaren kargagailua."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Ezin da USB bidez kargatu"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aplikazioen kokapen-eskaerak aktibo daude"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Garbitu jakinarazpen guztiak."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Beste <xliff:g id="NUMBER_1">%s</xliff:g> jakinarazpen daude barnean.</item>
       <item quantity="one">Beste <xliff:g id="NUMBER_0">%s</xliff:g> jakinarazpen daude barnean.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Isiltasun\nosoa"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Lehentasunezkoak\nsoilik"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmak\nsoilik"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> guztiz kargatzeko)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Bizkor kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> guztiz kargatzeko)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mantso kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> guztiz kargatzeko)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatzeko)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Bizkor kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatzeko)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mantso kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatzeko)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Aldatu erabiltzailea"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Aldatu erabiltzailez. <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> da saioa hasita duena."</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Uneko erabiltzailea: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"AMAITU ERABILTZAILEAREN SAIOA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Beste erabiltzaile bat gehitu?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Erabiltzaile bat gehitzen duzunean, horrek bere eremua konfiguratu beharko du.\n\nEdozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Erabiltzailea kendu nahi duzu?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Erabiltzailearen aplikazio eta datu guztiak ezabatuko dira."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Kendu"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ezkerreko ikonoa"</string>
     <string name="right_icon" msgid="3952104823293824311">"Eskuineko ikonoa"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Eduki sakatuta eta arrastatu lauzak gehitzeko"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Kentzeko, arrastatu hona"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Gutxienez sei lauza behar dituzu"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editatu"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Ezarri behealdea pantaila osoan"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. posizioa, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Editatzeko, sakatu birritan."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Gehitzeko, sakatu birritan."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. posizioa. Hautatzeko, sakatu birritan."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mugitu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Kendu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> gehitu da <xliff:g id="POSITION">%2$d</xliff:g>. posizioan"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Kendu da <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>. posiziora eraman da"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Gehitu <xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>garren postuan"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Eraman <xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>garren postura"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Ezarpen bizkorren editorea."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> zerbitzuaren jakinarazpena: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Baliteke aplikazioak ez funtzionatzea pantaila zatituan."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Joan arakatzailera"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Datu-konexioa"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi konexioa desaktibatuta dago"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth konexioa desaktibatuta dago"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Ez molestatu\" modua desaktibatuta dago"</string>
diff --git a/packages/SystemUI/res/values-eu/strings_car.xml b/packages/SystemUI/res/values-eu/strings_car.xml
index 99c66d2..3e645ce 100644
--- a/packages/SystemUI/res/values-eu/strings_car.xml
+++ b/packages/SystemUI/res/values-eu/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gonbidatua"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gonbidatua"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Gehitu erabiltzaile bat"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Erabiltzaile berria"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Erabiltzaile bat gehitzen duzunean, bere eremua konfiguratu beharko du."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 34ab46f..62bb59f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلان‌ها"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ممکن است باتری به‌زودی تمام شود"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده، براساس میزان مصرف شما حدود <xliff:g id="TIME">%s</xliff:g> باقی مانده است"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده، حدود <xliff:g id="TIME">%s</xliff:g> باقی مانده است"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> باقی مانده، براساس میزان مصرف شما حدود <xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> باقی مانده، حدود <xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است. بهینه‌سازی باتری روشن است."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"‏ازطریق USB شارژ نمی‌شود. از شارژر ارائه‌شده با دستگاه استفاده کنید."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"‏ازطریق USB شارژ نمی‌شود"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"درخواست‌های موقعیت مکانی فعال است"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"پاک کردن تمام اعلان‌ها"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>، +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>، +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> اعلان دیگر در گروه.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> اعلان دیگر در گروه.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"سکوت\nکامل"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"فقط\nاولویت‌دار"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"فقط\nهشدارها"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ شدن (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> تا شارژ کامل)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ سریع (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> تا شارژ کامل)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ آهسته (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> تا شارژ کامل)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ شدن (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ سریع (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ آهسته (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"تغییر کاربر"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"تعویض کاربر، کاربر کنونی <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"کاربر کنونی <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"خروج کاربر از سیستم"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"کاربر جدیدی اضافه می‌کنید؟"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"وقتی کاربر جدیدی اضافه می‌کنید آن فرد باید فضای خودش را تنظیم کند.\n\nهر کاربری می‌تواند برنامه‌ها را برای همه کاربران دیگر به‌روزرسانی کند."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"کاربر حذف شود؟"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"همه برنامه‌ها و داده‌های این کاربر حذف می‌شود."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"حذف"</string>
@@ -472,28 +475,28 @@
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"سازمان شما مرجع گواهینامه‌ای در نمایه کاری شما نصب کرده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
     <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"مرجع گواهینامه‌ای در این دستگاه نصب شده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
     <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"سرپرست سیستم شما گزارش‌گیری از شبکه را (که ترافیک دستگاه شما را پایش می‌کند) روشن کرده است."</string>
-    <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل شده‌اید، که می‌تواند فعالیت شبکه شما را (ازجمله رایانامه‌‌ها، برنامه‌‌ها و وب‌سایت‌ها) پایش کند."</string>
-    <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"به <xliff:g id="VPN_APP_0">%1$s</xliff:g> و <xliff:g id="VPN_APP_1">%2$s</xliff:g> متصل شده‌اید، که می‌توانند فعالیت شما را در شبکه (ازجمله رایانامه‌‌ها، برنامه‌‌ها و وب‌سایت‌ها) پایش کنند."</string>
-    <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"نمایه کاری شما به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل است، که می‌تواند فعالیت شما در شبکه (ازجمله رایانامه‌ها، برنامه‌ها و وب‌سایت‌ها) را پایش کند."</string>
-    <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"نمایه شخصی شما به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل شده‌ است، که می‌تواند فعالیت شما در شبکه (ازجمله رایانامه‌‌ها، برنامه‌‌ها و وب‌سایت‌ها) را پایش کند."</string>
+    <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل شده‌اید، که می‌تواند فعالیت شبکه شما را (ازجمله ایمیل‌ها، برنامه‌‌ها و وب‌سایت‌ها) پایش کند."</string>
+    <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"به <xliff:g id="VPN_APP_0">%1$s</xliff:g> و <xliff:g id="VPN_APP_1">%2$s</xliff:g> متصل شده‌اید، که می‌توانند فعالیت شما را در شبکه (ازجمله ایمیل‌ها، برنامه‌‌ها و وب‌سایت‌ها) پایش کنند."</string>
+    <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"نمایه کاری شما به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل است، که می‌تواند فعالیت شما در شبکه (ازجمله ایمیل‌ها، برنامه‌ها و وب‌سایت‌ها) را پایش کند."</string>
+    <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"نمایه شخصی شما به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل شده‌ است، که می‌تواند فعالیت شما در شبکه (ازجمله ایمیل‌ها، برنامه‌‌ها و وب‌سایت‌ها) را پایش کند."</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"<xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> دستگاه شما را مدیریت می‌کند."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> با استفاده از <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> دستگاهتان را مدیریت می‌کند."</string>
     <string name="monitoring_description_do_body" msgid="3639594537660975895">"سرپرست سیستم شما می‌تواند تنظیمات، دسترسی شرکتی، برنامه‌ها، داده‌های مرتبط با دستگاه و اطلاعات مکان دستگاه شما را مدیریت کند و بر آن‌ها نظارت داشته باشد."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"بیشتر بدانید"</string>
-    <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"به <xliff:g id="VPN_APP">%1$s</xliff:g> وصل شده‌اید، که می‌تواند فعالیت شبکه شما را (ازجمله رایانامه‌‌ها، برنامه‌‌ها و وب‌سایت‌ها) کنترل کند."</string>
+    <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"به <xliff:g id="VPN_APP">%1$s</xliff:g> وصل شده‌اید، که می‌تواند فعالیت شبکه شما را (ازجمله ایمیل‌ها، برنامه‌‌ها و وب‌سایت‌ها) کنترل کند."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"‏باز کردن تنظیمات VPN"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"باز کردن اعتبارنامه مورداعتماد"</string>
     <string name="monitoring_description_network_logging" msgid="7223505523384076027">"سرپرست سیستم شما گزارش‌گیری شبکه را (که بر ترافیک دستگاهتان نظارت می‌کند) روشن کرده است.\n\nبرای اطلاعات بیشتر، با سرپرست خود تماس بگیرید."</string>
-    <string name="monitoring_description_vpn" msgid="4445150119515393526">"‏شما به برنامه‌ای برای تنظیم اتصال VPN اجازه دادید.\n\n این برنامه می‌تواند دستگاه و فعالیت شبکه‌تان را کنترل کند، از جمله رایانامه‌، برنامه‌ و وب‌سایت‌ها."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"‏نمایه کاری شما توسط <xliff:g id="ORGANIZATION">%1$s</xliff:g> مدیریت می‌شود.\n\nسرپرست سیستم شما می‌تواند بر فعالیت شبکه شما (ازجمله رایانامه‌ها، برنامه‌ها و وب‌سایت‌ها) نظارت داشته باشد.\n\nبرای اطلاعات بیشتر، با سرپرست خود تماس بگیرید.\n\nهمچنین به VPN متصل هستید که می‌تواند بر فعالیت شبکه شما نظارت داشته باشد."</string>
+    <string name="monitoring_description_vpn" msgid="4445150119515393526">"‏شما به برنامه‌ای برای تنظیم اتصال VPN اجازه دادید.\n\n این برنامه می‌تواند دستگاه و فعالیت شبکه‌تان را کنترل کند، از جمله ایمیل‌، برنامه‌ و وب‌سایت‌ها."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"‏نمایه کاری شما توسط <xliff:g id="ORGANIZATION">%1$s</xliff:g> مدیریت می‌شود.\n\nسرپرست سیستم شما می‌تواند بر فعالیت شبکه شما (ازجمله ایمیل‌ها، برنامه‌ها و وب‌سایت‌ها) نظارت داشته باشد.\n\nبرای اطلاعات بیشتر، با سرپرست خود تماس بگیرید.\n\nهمچنین به VPN متصل هستید که می‌تواند بر فعالیت شبکه شما نظارت داشته باشد."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
-    <string name="monitoring_description_app" msgid="1828472472674709532">"شما به <xliff:g id="APPLICATION">%1$s</xliff:g> متصل هستید، که می‌تواند فعالیت شما در شبکه (ازجمله رایانامه‌، برنامه‌ و وب‌سایت‌ها) را پایش کند."</string>
-    <string name="monitoring_description_app_personal" msgid="484599052118316268">"شما به <xliff:g id="APPLICATION">%1$s</xliff:g> وصل شده‌اید، که می‌تواند فعالیت شبکه شخصی شما از جمله رایانامه‌، برنامه‌ و وب‌سایت‌ها را کنترل کند."</string>
-    <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"به <xliff:g id="APPLICATION">%1$s</xliff:g> وصل شده‌اید، که می‌تواند فعالیت شبکه شخصی شما را (ازجمله رایانامه‌‌ها، برنامه‌‌ها و وب‌سایت‌ها) کنترل کند."</string>
-    <string name="monitoring_description_app_work" msgid="4612997849787922906">"نمایه کاری شما توسط <xliff:g id="ORGANIZATION">%1$s</xliff:g> مدیریت می‌شود. این نمایه به <xliff:g id="APPLICATION">%2$s</xliff:g> متصل است که می‌تواند فعالیت شما در شبکه (ازجمله رایانامه‌ها، برنامه‌ها و وب‌سایت‌ها) را پایش کند.\n\nبرای اطلاعات بیشتر، با سرپرست سیستم تماس بگیرید."</string>
+    <string name="monitoring_description_app" msgid="1828472472674709532">"شما به <xliff:g id="APPLICATION">%1$s</xliff:g> متصل هستید، که می‌تواند فعالیت شما در شبکه (ازجمله ایمیل‌، برنامه‌ و وب‌سایت‌ها) را پایش کند."</string>
+    <string name="monitoring_description_app_personal" msgid="484599052118316268">"شما به <xliff:g id="APPLICATION">%1$s</xliff:g> وصل شده‌اید، که می‌تواند فعالیت شبکه شخصی شما از جمله ایمیل‌، برنامه‌ و وب‌سایت‌ها را کنترل کند."</string>
+    <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"به <xliff:g id="APPLICATION">%1$s</xliff:g> وصل شده‌اید که می‌تواند فعالیت شبکه شخصی شما را (ازجمله ایمیل‌ها، برنامه‌‌ها و وب‌سایت‌ها) کنترل کند."</string>
+    <string name="monitoring_description_app_work" msgid="4612997849787922906">"نمایه کاری شما توسط <xliff:g id="ORGANIZATION">%1$s</xliff:g> مدیریت می‌شود. این نمایه به <xliff:g id="APPLICATION">%2$s</xliff:g> متصل است که می‌تواند فعالیت شما در شبکه (ازجمله ایمیل‌ها، برنامه‌ها و وب‌سایت‌ها) را پایش کند.\n\nبرای اطلاعات بیشتر، با سرپرست سیستم تماس بگیرید."</string>
     <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"نمایه کاری‌تان توسط <xliff:g id="ORGANIZATION">%1$s</xliff:g> مدیریت می‌شود. این نمایه به <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> متصل است که می‌تواند تنظیمات، دسترسی شرکتی، برنامه‌ها، داده‌های مرتبط با دستگاه و اطلاعات مکان دستگاه شما را پایش کند.\n\nشما همچنین به <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> متصل هستید که می‌تواند فعالیت خصوصی شما را در شبکه پایش کند."</string>
     <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"قفل برای <xliff:g id="USER_NAME">%1$s</xliff:g> باز شد"</string>
     <string name="keyguard_indication_trust_managed" msgid="8319646760022357585">"<xliff:g id="TRUST_AGENT">%1$s</xliff:g> درحال اجرا است"</string>
@@ -681,7 +684,7 @@
     <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"دستیار"</string>
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"مرورگر"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"مخاطبین"</string>
-    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"رایانامه"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ایمیل"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="638701213803242744">"پیامک"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"موسیقی"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"نماد چپ"</string>
     <string name="right_icon" msgid="3952104823293824311">"نماد راست"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"نگه‌داشتن و کشیدن برای افزودن کاشی"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"برای حذف، به اینجا بکشید"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"حداقل به ۶ کاشی نیاز دارید"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ویرایش"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"تمام‌صفحه پایین"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"موقعیت <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>. برای ویرایش دو ضربه سریع بزنید."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. برای افزودن دو ضربه سریع بزنید."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"موقعیت <xliff:g id="POSITION">%1$d</xliff:g>. برای انتخاب دو ضربه سریع بزنید."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"انتقال <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"حذف <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> به موقعیت <xliff:g id="POSITION">%2$d</xliff:g> اضافه می‌شود"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> حذف می‌شود"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> به موقعیت <xliff:g id="POSITION">%2$d</xliff:g> منتقل شد"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"افزودن <xliff:g id="TILE_NAME">%1$s</xliff:g> به موقعیت <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"انتقال <xliff:g id="TILE_NAME">%1$s</xliff:g> به موقعیت <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ویرایشگر تنظیمات سریع."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"اعلان <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"ممکن است برنامه با تقسیم صفحه کار نکند."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
     <string name="go_to_web" msgid="2650669128861626071">"رفتن به مرورگر"</string>
     <string name="mobile_data" msgid="7094582042819250762">"داده تلفن همراه"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi خاموش است"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"بلوتوث خاموش است"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"«مزاحم نشوید» خاموش است"</string>
diff --git a/packages/SystemUI/res/values-fa/strings_car.xml b/packages/SystemUI/res/values-fa/strings_car.xml
index 3328af1..97657b95 100644
--- a/packages/SystemUI/res/values-fa/strings_car.xml
+++ b/packages/SystemUI/res/values-fa/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"مهمان"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"مهمان"</string>
     <string name="car_add_user" msgid="5245196248349230898">"افزودن کاربر"</string>
     <string name="car_new_user" msgid="8142927244990323906">"کاربر جدید"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"وقتی کاربر جدیدی اضافه می‌کنید، آن فرد باید فضای خود را تنظیم کند."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index baa7822..330f7d6 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ilmoitukset"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Akku voi loppua pian"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> jäljellä"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> käytettävissä, noin <xliff:g id="TIME">%s</xliff:g> jäljellä käytön perusteella"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> käytettävissä, noin <xliff:g id="TIME">%s</xliff:g> jäljellä"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> käytettävissä, noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä käytön perusteella"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> käytettävissä, noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> jäljellä. Virransäästö on käytössä."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Lataaminen USB:llä ei onnistu. Käytä laitteesi mukana tullutta laturia."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Lataaminen USB:llä ei onnistu"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Sijaintipyynnöt aktiiviset"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tyhjennä kaikki ilmoitukset."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">+<xliff:g id="NUMBER_1">%s</xliff:g> ilmoitusta ryhmässä</item>
       <item quantity="one">+<xliff:g id="NUMBER_0">%s</xliff:g> ilmoitus ryhmässä</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Täydellinen\nhiljaisuus"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Vain\ntärkeät"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Vain\nherätykset"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladataan (täynnä <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> päästä)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladataan nopeasti (täynnä <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> päästä)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladataan hitaasti (täynnä <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> päästä)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladataan (täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladataan nopeasti (täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladataan hitaasti (täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Vaihda käyttäjää"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Vaihda käyttäjä (nyt <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Nykyinen käyttäjä: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"KIRJAA KÄYTTÄJÄ ULOS"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Lisätäänkö uusi käyttäjä?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Kun lisäät uuden käyttäjän, hänen tulee määrittää oman tilansa asetukset.\n\nKaikki käyttäjät voivat päivittää sovelluksia muille käyttäjille."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Poistetaanko käyttäjä?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Kaikki käyttäjän tiedot ja sovellukset poistetaan."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Poista"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Vasen kuvake"</string>
     <string name="right_icon" msgid="3952104823293824311">"Oikea kuvake"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Lisää osioita koskettamalla pitkään ja vetämällä"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Poista vetämällä tähän."</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Kuusi osiota on vähimmäismäärä."</string>
     <string name="qs_edit" msgid="2232596095725105230">"Muokkaa"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Alaosa koko näytölle"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Paikka <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Muokkaa kaksoisnapauttamalla."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lisää kaksoisnapauttamalla."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Paikka <xliff:g id="POSITION">%1$d</xliff:g>. Valitse kaksoisnapauttamalla."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Siirrä <xliff:g id="TILE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Poista <xliff:g id="TILE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> lisättiin paikkaan <xliff:g id="POSITION">%2$d</xliff:g>."</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> poistettiin."</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> siirrettiin paikkaan <xliff:g id="POSITION">%2$d</xliff:g>."</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Siirrä <xliff:g id="TILE_NAME">%1$s</xliff:g> kohtaan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Siirrä <xliff:g id="TILE_NAME">%1$s</xliff:g> kohtaan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Pika-asetusten muokkausnäkymä"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Ilmoitus kohteesta <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Sovellus ei ehkä toimi jaetulla näytöllä."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Siirry selaimeen"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiilitiedonsiirto"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi on pois käytöstä"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ei ole käytössä"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Älä häiritse ‑tila on pois käytöstä"</string>
diff --git a/packages/SystemUI/res/values-fi/strings_car.xml b/packages/SystemUI/res/values-fi/strings_car.xml
index 408eea1..d062d67 100644
--- a/packages/SystemUI/res/values-fi/strings_car.xml
+++ b/packages/SystemUI/res/values-fi/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Vieras"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Vieras"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Lisää käyttäjä"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Uusi käyttäjä"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kun lisäät uuden käyttäjän, hänen on määritettävä oman tilansa asetukset."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index bb4cdfb..47430ba 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"La pile sera bientôt épuisée"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Il reste <xliff:g id="PERCENTAGE">%s</xliff:g>, environ <xliff:g id="TIME">%s</xliff:g> en fonction de votre usage"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Il reste <xliff:g id="PERCENTAGE">%s</xliff:g>, environ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Il reste <xliff:g id="PERCENTAGE">%1$s</xliff:g>, environ <xliff:g id="TIME">%2$s</xliff:g> en fonction de votre usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Il reste <xliff:g id="PERCENTAGE">%1$s</xliff:g>, environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants. La fonction Économie d\'énergie est activée."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Impossible de charger l\'appareil par USB. Servez-vous du chargeur fourni avec celui-ci."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Impossible de charger l\'appareil par USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Demandes de localisation actives"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, + <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, + <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> autre notification à l\'intérieur.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> autres notifications à l\'intérieur.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Aucune\ninterruption"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorités\nuniquement"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"En recharge : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> jusqu\'à charge complète)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"En recharge rapide : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> jusqu\'à ch. comp.)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> jusqu\'à ch. comp.)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"En recharge : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à charge complète)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"En recharge rapide : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à ch. comp.)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à ch. comp.)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"DÉCONNECTER L\'UTILISATEUR"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Ajouter un utilisateur?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.\n\nTout utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Supprimer l\'utilisateur?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Toutes les applications et les données de cet utilisateur seront supprimées."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Supprimer"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Icône à gauche"</string>
     <string name="right_icon" msgid="3952104823293824311">"Icône droite"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Maint. doigt sur écran, puis glissez-le pour aj. des tuiles"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Faites glisser les tuiles ici pour les supprimer"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Vous avez besoin d\'au moins six tuiles"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Modifier"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Plein écran dans le bas"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Touchez deux fois pour modifier."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Touchez deux fois pour ajouter."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position : <xliff:g id="POSITION">%1$d</xliff:g>. Touchez deux fois pour sélectionner."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Déplacer <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Supprimer <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> a été ajouté à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> a été supprimé"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> a été déplacé à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Ajouter <xliff:g id="TILE_NAME">%1$s</xliff:g> à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Déplacer <xliff:g id="TILE_NAME">%1$s</xliff:g> à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Éditeur de paramètres rapides."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notification <xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Ouvrir le navigateur"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Données cellulaires"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> : <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Le Wi-Fi est désactivé"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Le Bluetooth est désactivé"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Le mode Ne pas déranger est désactivé"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_car.xml b/packages/SystemUI/res/values-fr-rCA/strings_car.xml
index e1cd5a2..c100828 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_car.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Invité"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Invité"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Ajouter un utilisateur"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nouvel utilisateur"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index e38e83c..c10c1d2 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Il est possible que vous soyez bientôt à court de batterie"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> – Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> – Temps restant : environ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – Temps restant : environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants. L\'économiseur de batterie est activé."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Chargement par USB impossible. Utiliser le chargeur d\'origine fourni avec votre appareil."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Impossible de recharger via USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Demandes de localisation actives"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"<xliff:g id="NUMBER">%s</xliff:g> autres"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> + <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> + <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> autre notification à l\'intérieur.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> autres notifications à l\'intérieur.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Aucune\ninterruption"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorité\nuniquement"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement… (rechargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement rapide… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement lent… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement… (rechargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement rapide… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement lent… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"DÉCONNECTER L\'UTILISATEUR"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Ajouter un utilisateur ?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.\n\nN\'importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Supprimer l\'utilisateur ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Toutes les applications et les données de cet utilisateur seront supprimées."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Supprimer"</string>
@@ -536,7 +539,7 @@
     <string name="ring_toggle_title" msgid="3281244519428819576">"Appels"</string>
     <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Sonnerie"</string>
     <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibreur"</string>
-    <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silencieux"</string>
+    <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Couper le son"</string>
     <string name="qs_status_phone_vibrate" msgid="204362991135761679">"Mode Vibreur activé"</string>
     <string name="qs_status_phone_muted" msgid="5437668875879171548">"Sons du téléphone désactivés"</string>
     <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Appuyez pour ne plus ignorer."</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Icône gauche"</string>
     <string name="right_icon" msgid="3952104823293824311">"Icône droite"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Sélectionnez et faites glisser les tuiles pour les ajouter"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Faites glisser les tuiles ici pour les supprimer."</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Au minimum six tuiles sont nécessaires"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Modifier"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Écran du bas en plein écran"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, \"<xliff:g id="TILE_NAME">%2$s</xliff:g>\". Appuyer deux fois pour modifier."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Appuyer deux fois pour ajouter."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Appuyer deux fois pour sélectionner."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Déplacer \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Supprimer \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Le bloc \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" a bien été ajouté à la position <xliff:g id="POSITION">%2$d</xliff:g>."</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Le bloc \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" a bien été supprimé."</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Le bloc \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" a bien été déplacé à la position <xliff:g id="POSITION">%2$d</xliff:g>."</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Ajouter l\'élément \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Déplacer l\'élément \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Éditeur de configuration rapide."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notification <xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Accéder au navigateur"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Données mobiles"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi désactivé"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth désactivé"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Mode \"Ne pas déranger\" désactivé"</string>
diff --git a/packages/SystemUI/res/values-fr/strings_car.xml b/packages/SystemUI/res/values-fr/strings_car.xml
index f35d2f6..0b65fa6 100644
--- a/packages/SystemUI/res/values-fr/strings_car.xml
+++ b/packages/SystemUI/res/values-fr/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Invité"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Invité"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Ajouter un utilisateur"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nouvel utilisateur"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace."</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 0e8b093..5c6737f 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacións"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"A batería pode esgotarse en breve"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>, é dicir, aproximadamente <xliff:g id="TIME">%s</xliff:g> en función do uso que fas"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>, é dicir, aproximadamente <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Queda un <xliff:g id="PERCENTAGE">%1$s</xliff:g>, é dicir, aproximadamente <xliff:g id="TIME">%2$s</xliff:g> en función do uso que fas"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Queda un <xliff:g id="PERCENTAGE">%1$s</xliff:g>, é dicir, aproximadamente <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Está activada a función Aforro de batería."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Non se puido realizar a carga por USB. Utiliza o cargador que incluía o dispositivo."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Non se puido realizar a carga por USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de localización activas"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas as notificacións."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"<xliff:g id="NUMBER">%s</xliff:g> máis"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> (+<xliff:g id="OVERFLOW">%s</xliff:g>)"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (+<xliff:g id="OVERFLOW">%2$s</xliff:g>)"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> notificacións máis no grupo.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> notificación máis no grupo.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silencio\ntotal"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Só\nprioridade"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Só\nalarmas"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para rematar a carga)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando rapidamente (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para rematar a carga)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lentamente (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para rematar a carga)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> para rematar a carga)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando rapidamente (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> para rematar a carga)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lentamente (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> para rematar a carga)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambiar usuario"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambiar usuario, usuario actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Usuario actual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"PECHAR SESIÓN DO USUARIO"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Engadir un usuario novo?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Cando engadas un usuario novo, este deberá configurar o seu espazo\n\nCalquera usuario pode actualizar as aplicacións para todos os demais usuarios."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Queres eliminar o usuario?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Eliminaranse todas as aplicacións e os datos deste usuario."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Eliminar"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Icona á esquerda"</string>
     <string name="right_icon" msgid="3952104823293824311">"Icona á dereita"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Mantén premidas as funcións e arrástraas para engadilas"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra o elemento ata aquí para eliminalo"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Necesitas polo menos 6 mosaicos"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Pantalla completa abaixo"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toca dúas veces o elemento para editalo."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toca dúas veces o elemento para engadilo"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posición <xliff:g id="POSITION">%1$d</xliff:g>. Toca dúas veces o elemento para seleccionalo."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Elimina <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> engadiuse á posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Eliminouse <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> moveuse á posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Engadir \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" á posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Mover \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" á posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de configuración rápida."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Pode que a aplicación non funcione coa pantalla dividida."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Info. da aplicación"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Ir ao navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Datos móbiles"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g>-<xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g>-<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"A wifi está desactivada"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"O Bluetooth está desactivado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"O modo Non molestar está desactivado"</string>
diff --git a/packages/SystemUI/res/values-gl/strings_car.xml b/packages/SystemUI/res/values-gl/strings_car.xml
index e69c302..24304dc 100644
--- a/packages/SystemUI/res/values-gl/strings_car.xml
+++ b/packages/SystemUI/res/values-gl/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Convidado"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Convidado"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Engadir usuario"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Novo usuario"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Cando engadas un usuario novo, este deberá configurar o seu espazo."</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index a730f01..76e00d4 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"નોટિફિકેશનો"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"બૅટરી ટૂંક સમયમાં સમાપ્ત થશે"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી, તમારા વપરાશના આધારે લગભગ <xliff:g id="TIME">%s</xliff:g> બાકી છે"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી, લગભગ <xliff:g id="TIME">%s</xliff:g> બાકી"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> બાકી, તમારા વપરાશના આધારે લગભગ <xliff:g id="TIME">%2$s</xliff:g> બાકી છે"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> બાકી, લગભગ <xliff:g id="TIME">%2$s</xliff:g> બાકી"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી. બૅટરી સેવર ચાલુ છે."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB મારફતે ચાર્જ કરી શકતા નથી. તમારા ઉપકરણ સાથે આવેલ ચાર્જરનો ઉપયોગ કરો."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB મારફતે ચાર્જ કરી શકતા નથી"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"સ્થાન વિનંતીઓ સક્રિય"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"બધા સૂચનો સાફ કરો."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> વધુ સૂચના અંદર છે.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> વધુ સૂચના અંદર છે.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"સાવ\nશાંતિ"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ફક્ત\nપ્રાધાન્યતા"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ફક્ત\nએલાર્મ્સ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જિંગ (પૂર્ણ થવામાં <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> બાકી)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ઝડપથી ચાર્જિંગ (પૂર્ણ થવામાં <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> બાકી)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ધીમેથી ચાર્જિંગ (પૂર્ણ થવામાં <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> બાકી)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જિંગ (પૂર્ણ થવામાં <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> બાકી)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ઝડપથી ચાર્જિંગ (પૂર્ણ થવામાં <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> બાકી)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ધીમેથી ચાર્જિંગ (પૂર્ણ થવામાં <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> બાકી)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"વપરાશકર્તા સ્વિચ કરો"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"વપરાશકર્તાને સ્વિચ કરો, વર્તમાન વપરાશકર્તા <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"વર્તમાન વપરાશકર્તા <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"વપરાશકર્તાને લૉગઆઉટ કરો"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"નવા વપરાશકર્તાને ઉમેરીએ?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિને તેમનું સ્થાન સેટ કરવાની જરૂર પડે છે.\n\nકોઈપણ વપરાશકર્તા બધા અન્ય વપરાશકર્તાઓ માટે એપ્લિકેશન્સને અપડેટ કરી શકે છે."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"વપરાશકર્તાને દૂર કરીએ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"આ વપરાશકર્તાની તમામ ઍપ્લિકેશનો અને ડેટા કાઢી નાખવામાં આવશે."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"દૂર કરો"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"ડાબું આઇકન"</string>
     <string name="right_icon" msgid="3952104823293824311">"જમણું આઇકન"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ટાઇલ ઉમેરવા માટે તેના પર આંગળી દબાવીને ખેંચો"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"દૂર કરવા માટે અહીં ખેંચો"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"તમને ઓછામાં ઓછી 6 ટાઇલની જરૂર છે"</string>
     <string name="qs_edit" msgid="2232596095725105230">"સંપાદિત કરો"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"તળિયાની પૂર્ણ સ્ક્રીન"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"સ્થિતિ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. સંપાદિત કરવા માટે બે વાર ટૅપ કરો."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ઉમેરવા માટે બે વાર ટૅપ કરો."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"સ્થિતિ <xliff:g id="POSITION">%1$d</xliff:g>. પસંદ કરવા માટે બે વાર ટૅપ કરો."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ખસેડો"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> દૂર કરો"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="POSITION">%2$d</xliff:g> સ્થિતિ પર <xliff:g id="TILE_NAME">%1$s</xliff:g> ઉમેર્યું છે"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> દૂર કરવામાં આવ્યું છે"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ને <xliff:g id="POSITION">%2$d</xliff:g> સ્થિતિ પર ખસેડ્યું"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="POSITION">%2$d</xliff:g> જગ્યા પર <xliff:g id="TILE_NAME">%1$s</xliff:g>ને ઉમેરો"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="POSITION">%2$d</xliff:g> જગ્યા પર <xliff:g id="TILE_NAME">%1$s</xliff:g>ને ખસેડો"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ઝડપી સેટિંગ્સ સંપાદક."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> નોટિફિકેશન: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"વિભાજિત-સ્ક્રીન સાથે ઍપ્લિકેશન કદાચ કામ ન કરે."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
     <string name="go_to_web" msgid="2650669128861626071">"બ્રાઉઝર પર જાઓ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"મોબાઇલ ડેટા"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"વાઇ-ફાઇ બંધ છે"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"બ્લૂટૂથ બંધ છે"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"ખલેલ પાડશો નહીં બંધ છે"</string>
diff --git a/packages/SystemUI/res/values-gu/strings_car.xml b/packages/SystemUI/res/values-gu/strings_car.xml
index 83ae932..3f95205 100644
--- a/packages/SystemUI/res/values-gu/strings_car.xml
+++ b/packages/SystemUI/res/values-gu/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"અતિથિ"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"અતિથિ"</string>
     <string name="car_add_user" msgid="5245196248349230898">"વપરાશકર્તા ઉમેરો"</string>
     <string name="car_new_user" msgid="8142927244990323906">"નવા વપરાશકર્તા"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિએ તેમની સ્પેસ સેટ કરવાની જરૂર રહે છે."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 7049044..ad8d505 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाएं"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"बैटरी जल्दी ही खत्म हो जाएगी"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> शेष"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> बची है, आपके इस्तेमाल करने के तरीके के हिसाब से बैटरी लगभग <xliff:g id="TIME">%s</xliff:g> चलेगी"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> बची है, बैटरी लगभग <xliff:g id="TIME">%s</xliff:g> चलेगी"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> बची है, आपके इस्तेमाल करने के तरीके के हिसाब से बैटरी लगभग <xliff:g id="TIME">%2$s</xliff:g> चलेगी"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> बची है, बैटरी लगभग <xliff:g id="TIME">%2$s</xliff:g> चलेगी"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> बैटरी बची है. बैटरी सेवर चालू है."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"यूएसबी के ज़रिए चार्ज नहीं किया जा सकता. अपने डिवाइस के साथ मिलने वाले चार्जर का इस्तेमाल करें."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"यूएसबी के ज़रिए चार्ज नहीं किया जा सकता"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"जगह का अनुरोध किया जा रहा है"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और सूचनाएं हैं.</item>
       <item quantity="other">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और सूचनाएं हैं.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"पूरी तरह\nशांत"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"केवल\nप्राथमिकता"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"केवल\nअलार्म"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> में पूरा होगा)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • तेज़ चार्ज हो रहा है (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> में पूरा होगा)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • धीरे चार्ज हो रहा है (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> में पूरा होगा)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा होगा)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • तेज़ चार्ज हो रहा है (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा होगा)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • धीरे चार्ज हो रहा है (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा होगा)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"उपयोगकर्ता बदलें"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"उपयोगकर्ता बदलें, मौजूदा उपयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"मौजूदा उपयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"उपयोगकर्ता को प्रस्थान करवाएं"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"नया उपयोगकर्ता जोड़ें?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं तो उस व्यक्ति को अपनी जगह सेट करनी होती है.\n\nकोई भी उपयोगकर्ता बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"उपयोगकर्ता निकालें?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"इस उपयोगकर्ता के सभी ऐप और डेटा को हटा दिया जाएगा."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"निकालें"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"बायां आइकॉन"</string>
     <string name="right_icon" msgid="3952104823293824311">"दायां आइकॉन"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"टाइल जोड़ने के लिए दबाएं और खींचें"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"हटाने के लिए यहां खींचें और छोड़ें"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"आपके पास कम से कम 6 टाइल होनी चाहिए"</string>
     <string name="qs_edit" msgid="2232596095725105230">"बदलाव करें"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"नीचे की स्क्रीन को पूर्ण स्क्रीन बनाएं"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. में बदलाव करने के लिए दो बार छूएं."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. जोड़ने के लिए दो बार छूएं."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>. चुनने के लिए दो बार छूएं."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> को ले जाएं"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> निकालें"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> को <xliff:g id="POSITION">%2$d</xliff:g> स्थिति में जोड़ा गया"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> निकाल दिया गया है"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> को <xliff:g id="POSITION">%2$d</xliff:g> स्थिति में ले जाया गया"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> काे क्रम संख्या <xliff:g id="POSITION">%2$d</xliff:g> पर जाेड़ें"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> काे क्रम संख्या <xliff:g id="POSITION">%2$d</xliff:g> पर ले जाएं"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"त्वरित सेटिंग संपादक."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"हो सकता है कि ऐप्लिकेशन विभाजित स्क्रीन के साथ काम ना करे."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ब्राउज़र पर जाएं"</string>
     <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"वाई-फ़ाई बंद है"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ब्लूटूथ बंद है"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"परेशान न करें बंद है"</string>
diff --git a/packages/SystemUI/res/values-hi/strings_car.xml b/packages/SystemUI/res/values-hi/strings_car.xml
index 468fba0..8820046 100644
--- a/packages/SystemUI/res/values-hi/strings_car.xml
+++ b/packages/SystemUI/res/values-hi/strings_car.xml
@@ -20,6 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"मेहमान"</string>
+    <!-- no translation found for start_guest_session (7055742120180595689) -->
+    <skip />
     <string name="car_add_user" msgid="5245196248349230898">"उपयोगकर्ता जोड़ें"</string>
     <string name="car_new_user" msgid="8142927244990323906">"नया उपयोगकर्ता"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं तो, उस व्यक्ति को अपनी जगह सेट करनी होती है."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index a77b7ff..435fc56 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -35,8 +35,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obavijesti"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Baterija bi se uskoro mogla isprazniti"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Preostalo je <xliff:g id="PERCENTAGE">%s</xliff:g>, još otprilike <xliff:g id="TIME">%s</xliff:g> na temelju vaše upotrebe"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Preostalo je <xliff:g id="PERCENTAGE">%s</xliff:g>, još otprilike <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Preostalo je <xliff:g id="PERCENTAGE">%1$s</xliff:g>, još otprilike <xliff:g id="TIME">%2$s</xliff:g> na temelju vaše upotrebe"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Preostalo je <xliff:g id="PERCENTAGE">%1$s</xliff:g>, još otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>. Uključena je Štednja baterije."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Punjenje putem USB-a nije moguće. Koristite punjač koji ste dobili s uređajem."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Punjenje putem USB-a nije moguće"</string>
@@ -258,7 +258,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Zahtjevi za lokaciju aktivni su"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Brisanje svih obavijesti."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"još <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">U skupini je još <xliff:g id="NUMBER_1">%s</xliff:g> obavijest.</item>
       <item quantity="few">U skupini su još <xliff:g id="NUMBER_1">%s</xliff:g> obavijesti.</item>
@@ -402,9 +402,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Potpuna\ntišina"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Samo\nprioritetno"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Samo\nalarmi"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • brzo punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • sporo punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • brzo punjenje (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • sporo punjenje (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Promjena korisnika"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Promjena korisnika, trenutačni korisnik <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Trenutačan korisnik <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -429,6 +429,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ODJAVI KORISNIKA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Dodati novog korisnika?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor.\n\nBilo koji korisnik može ažurirati aplikacije za sve ostale korisnike."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Ukloniti korisnika?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Izbrisat će se sve aplikacije i podaci ovog korisnika."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Ukloni"</string>
@@ -734,6 +737,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Lijeva ikona"</string>
     <string name="right_icon" msgid="3952104823293824311">"Desna ikona"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Zadržite i povucite za dodavanje pločica"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Povucite ovdje za uklanjanje"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Potrebno je barem 6 pločica"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
@@ -762,12 +767,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Donji zaslon u cijeli zaslon"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dodirnite dvaput da biste uredili."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dodirnite dvaput da biste dodali."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>. Dodirnite dvaput da biste odabrali."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Premjesti <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Ukloni <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> dodana je na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> uklonjena"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> premještena je na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Dodajte pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Premjestite pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Uređivač brzih postavki."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> obavijest: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija možda neće funkcionirati s podijeljenim zaslonom."</string>
@@ -828,7 +831,7 @@
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Otvori preglednik"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Način Ne ometaj isključen"</string>
diff --git a/packages/SystemUI/res/values-hr/strings_car.xml b/packages/SystemUI/res/values-hr/strings_car.xml
index aff0090..44f4a09 100644
--- a/packages/SystemUI/res/values-hr/strings_car.xml
+++ b/packages/SystemUI/res/values-hr/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gost"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gost"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Dodajte korisnika"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Novi korisnik"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor."</string>
diff --git a/packages/SystemUI/res/values-hu/donottranslate.xml b/packages/SystemUI/res/values-hu/donottranslate.xml
deleted file mode 100644
index dcf434d..0000000
--- a/packages/SystemUI/res/values-hu/donottranslate.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%2$s\n%1$s</string>
-
-</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d6e2cb6..6574c97 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Értesítések"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Az akkumulátor hamarosan lemerül"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt, körülbelül <xliff:g id="TIME">%s</xliff:g> van hátra a használat alapján"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt, körülbelül <xliff:g id="TIME">%s</xliff:g> van hátra"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> maradt, körülbelül <xliff:g id="TIME">%2$s</xliff:g> van hátra a használat alapján"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> maradt, körülbelül <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt. Az Akkumulátorkímélő mód be van kapcsolva."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Nem tölthető USB-n keresztül. Használja az eszközhöz kapott eredeti töltőt."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Nem tölthető USB-n keresztül"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aktív helylekérések"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> további értesítés.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> további értesítés.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Teljes\nnémítás"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Csak\nprioritás"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Csak\nriasztások"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Gyors töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lassú töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> a teljes töltöttségig)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Gyors töltés (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> a teljes töltöttségig)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lassú töltés (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> a teljes töltöttségig)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Felhasználóváltás"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Felhasználóváltás (a jelenlegi felhasználó: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Jelenlegi felhasználó (<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"FELHASZNÁLÓ KIJELENTKEZÉSE"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Új felhasználó hozzáadása?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Ha új felhasználót ad hozzá, az illetőnek be kell állítania saját tárterületét.\n\nBármely felhasználó frissítheti az alkalmazásokat valamennyi felhasználó számára."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Törli a felhasználót?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"A felhasználóhoz tartozó minden adat és alkalmazás törölve lesz."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Eltávolítás"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Bal oldali ikon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Jobb oldali ikon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Tartsa lenyomva, és húzza a mozaikok hozzáadásához"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Húzza ide az eltávolításhoz"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Legalább hat mozaik szükséges"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Szerkesztés"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Alsó teljes képernyőre"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. pozíció: <xliff:g id="TILE_NAME">%2$s</xliff:g>. Koppintson duplán a szerkesztéshez."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Koppintson duplán a hozzáadáshoz."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. pozíció. Koppintson duplán a kiválasztáshoz."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> áthelyezése"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> eltávolítása"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> hozzáadva <xliff:g id="POSITION">%2$d</xliff:g>. pozícióban"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> eltávolítva"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> áthelyezve a(z) <xliff:g id="POSITION">%2$d</xliff:g>. pozícióba"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> hozzáadása a következő pozícióhoz: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> áthelyezése a következő pozícióba: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Gyorsbeállítások szerkesztője"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g>-értesítések: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Lehet, hogy az alkalmazás nem működik osztott képernyős nézetben."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Ugrás a böngészőbe"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiladatok"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"A Wi-Fi ki van kapcsolva"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"A Bluetooth ki van kapcsolva"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"A „Ne zavarjanak” mód ki van kapcsolva"</string>
diff --git a/packages/SystemUI/res/values-hu/strings_car.xml b/packages/SystemUI/res/values-hu/strings_car.xml
index 1eb17ce..d0f00ba 100644
--- a/packages/SystemUI/res/values-hu/strings_car.xml
+++ b/packages/SystemUI/res/values-hu/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Vendég"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Vendég"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Felhasználó hozzáadása"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Új felhasználó"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Ha új felhasználót ad hozzá, az illetőnek be kell állítania saját felületét."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 2e8c9be..20209a2 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ծանուցումներ"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Մարտկոցի լիցքը շուտով կարող է սպառվել"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Մնաց <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%s</xliff:g>, մնացել է մոտ <xliff:g id="TIME">%s</xliff:g>՝ օգտագործման եղանակից կախված"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%s</xliff:g>, մնացել է մոտ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%1$s</xliff:g>, մնացել է մոտ <xliff:g id="TIME">%2$s</xliff:g>՝ օգտագործման եղանակից կախված"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%1$s</xliff:g>, մնացել է մոտ <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Մնացել է <xliff:g id="PERCENTAGE">%s</xliff:g>: Մարտկոցի տնտեսումը միացված է:"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Հնարավոր չէ լիցքավորել USB-ի միջոցով: Օգտագործեք սարքի լիցքավորիչը:"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Սարքը հնարավոր չէ լիցքավորել USB-ի միջոցով"</string>
@@ -77,7 +77,7 @@
     <string name="screenshot_failed_title" msgid="7612509838919089748">"Չհաջողվեց պահել սքրինշոթը"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Փորձեք նորից"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Չհաջողվեց պահել սքրինշոթը անբավարար հիշողության պատճառով"</string>
-    <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում էկրանի պատկերի ստացումը"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում սքրինշոթի ստացումը"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ֆայլերի փոխանցման ընտրանքներ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Միացնել որպես մեդիա նվագարկիչ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Միացնել որպես ֆոտոխցիկ (PTP)"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Տեղադրության հարցումներն ակտիվ են"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Մաքրել բոլոր ծանուցումները:"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Ներսում ևս <xliff:g id="NUMBER_1">%s</xliff:g> ծանուցում կա:</item>
       <item quantity="other">Ներսում ևս <xliff:g id="NUMBER_1">%s</xliff:g> ծանուցում կա:</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Ընդհանուր\nլուռ վիճակը"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Միայն\nկարևորները"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Միայն\nզարթուցիչ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում (մնացել է <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Արագ լիցքավորում (մնացել է <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Դանդաղ լիցքավորում (մնացել է <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում (մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Արագ լիցքավորում (մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Դանդաղ լիցքավորում (մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Անջատել օգտվողին"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Փոխել օգտատիրոջը. ներկայիս օգտատերն է՝ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Ընթացիկ օգտատերը՝ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ԸՆԹԱՑԻԿ ՕԳՏՎՈՂԻ ԴՈՒՐՍ ԳՐՈՒՄ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Ավելացնե՞լ նոր պրոֆիլ:"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Երբ նոր օգտատեր եք ավելացնում, նա պետք է կարգավորի իր պրոֆիլը:\n\nՑանկացած օգտատեր կարող է թարմացնել հավելվածները մյուս բոլոր հաշիվների համար:"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Հեռացնե՞լ օգտատիրոջը:"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Այս օգտատիրոջ բոլոր հավելվածներն ու տվյալները կջնջվեն:"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Հեռացնել"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ձախ պատկերակ"</string>
     <string name="right_icon" msgid="3952104823293824311">"Աջ պատկերակ"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Պահեք և քաշեք՝ սալիկներ ավելացնելու համար"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Քաշեք այստեղ՝ հեռացնելու համար"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Հարկավոր է առնվազն 6 սալիկ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Փոփոխել"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Ներքևի էկրանը՝ լիաէկրան"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Դիրք <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>: Կրկնակի հպեք՝ փոխելու համար:"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>: Կրկնակի հպեք՝ ավելացնելու համար:"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Դիրք <xliff:g id="POSITION">%1$d</xliff:g>: Կրկնակի հպեք՝ ընտրելու համար:"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Տեղափոխել <xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Հեռացնել <xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկն ավելացվել է <xliff:g id="POSITION">%2$d</xliff:g> դիրքին"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը հեռացվել է"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը տեղափոխվել է դեպի <xliff:g id="POSITION">%2$d</xliff:g> դիրք"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Ավելացնել <xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը դիրք <xliff:g id="POSITION">%2$d</xliff:g>-ում"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը տեղափոխել դիրք <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Արագ կարգավորումների խմբագրիչ:"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> ծանուցում՝ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Հավելվածը չի կարող աշխատել տրոհված էկրանի ռեժիմում:"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Անցնել դիտարկիչ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Բջջային ինտերնետ"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi-ն անջատված է"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth-ն անջատված է"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Չանհանգստացնելու ռեժիմն անջատված է"</string>
diff --git a/packages/SystemUI/res/values-hy/strings_car.xml b/packages/SystemUI/res/values-hy/strings_car.xml
index 555deeb..85af3c8 100644
--- a/packages/SystemUI/res/values-hy/strings_car.xml
+++ b/packages/SystemUI/res/values-hy/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Հյուր"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Հյուր"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Ավելացնել օգտատեր"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Նոր օգտատեր"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Երբ դուք նոր օգտատեր եք ավելացնում, նա պետք է կարգավորի իր պրոֆիլը:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index d75d121..5111ed6 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifikasi"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Baterai mungkin akan segera habis"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Sisa <xliff:g id="PERCENTAGE">%s</xliff:g>, kira-kira <xliff:g id="TIME">%s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Sisa <xliff:g id="PERCENTAGE">%s</xliff:g>, kira-kira <xliff:g id="TIME">%s</xliff:g> lagi"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Sisa <xliff:g id="PERCENTAGE">%1$s</xliff:g>, kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Sisa <xliff:g id="PERCENTAGE">%1$s</xliff:g>, kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>. Penghemat Baterai aktif."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Tidak dapat mengisi daya melalui USB. Gunakan pengisi daya yang disertakan dengan perangkat."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Tidak dapat mengisi daya melalui USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Permintaan lokasi aktif"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> notifikasi lainnya di dalam.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> notifikasi lainnya di dalam.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Senyap\ntotal"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Hanya\nprioritas"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Hanya\nalarm"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan cepat (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> hingga penuh)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan cepat (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> hingga penuh)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> hingga penuh)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Beralih pengguna"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Ganti pengguna, pengguna saat ini <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Pengguna saat ini <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"KELUARKAN PENGGUNA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Tambahkan pengguna baru?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Saat Anda menambahkan pengguna baru, orang tersebut perlu menyiapkan ruangnya sendiri.\n\nPengguna mana pun dapat mengupdate aplikasi untuk semua pengguna lain."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Hapus pengguna?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Semua aplikasi dan data pengguna ini akan dihapus."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Hapus"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ikon kiri"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ikon kanan"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Tahan dan tarik untuk menambahkan tile"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Tarik ke sini untuk menghapus"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Anda membutuhkan setidaknya 6 tile"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Layar penuh di bawah"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posisi <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tap dua kali untuk mengedit."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tap dua kali untuk menambahkan."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posisi <xliff:g id="POSITION">%1$d</xliff:g>. Tap dua kali untuk memilih."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Pindahkan <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Hapus <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ditambahkan ke posisi <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> dihapus"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> dpindahkan ke posisi <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Tambahkan <xliff:g id="TILE_NAME">%1$s</xliff:g> ke posisi <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Pindahkan <xliff:g id="TILE_NAME">%1$s</xliff:g> ke posisi <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor setelan cepat."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notifikasi <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikasi mungkin tidak berfungsi dengan layar terpisah."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Buka browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Data seluler"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi nonaktif"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth nonaktif"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Fitur Jangan Ganggu nonaktif"</string>
diff --git a/packages/SystemUI/res/values-in/strings_car.xml b/packages/SystemUI/res/values-in/strings_car.xml
index f0620d0..7423a1c 100644
--- a/packages/SystemUI/res/values-in/strings_car.xml
+++ b/packages/SystemUI/res/values-in/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Tamu"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Tamu"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Tambahkan Pengguna"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Pengguna Baru"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Saat Anda menambahkan pengguna baru, orang tersebut perlu menyiapkan ruangnya sendiri."</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index eaad622..508b2bd 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Tilkynningar"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Rafhlaðan gæti tæmst bráðlega"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir, um það bil <xliff:g id="TIME">%s</xliff:g> eftir miðað við notkun"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir, um það bil <xliff:g id="TIME">%s</xliff:g> eftir"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> eftir, um það bil <xliff:g id="TIME">%2$s</xliff:g> eftir miðað við notkun"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> eftir, um það bil <xliff:g id="TIME">%2$s</xliff:g> eftir"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir. Kveikt er á rafhlöðusparnaði."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Ekki er hægt að hlaða í gegnum USB. Notaðu hleðslutækið sem fylgdi tækinu þínu."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Ekki er hægt að hlaða í gegnum USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Staðsetningarbeiðnir virkar"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Hreinsa allar tilkynningar."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> tilkynning í viðbót.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> tilkynningar í viðbót.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Algjör\nþögn"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Aðeins\nforgangur"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Aðeins\nvekjarar"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> fram að fullri hleðslu)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hröð hleðsla (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> að fullri hleðslu)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hæg hleðsla (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> fram að fullri hleðslu)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> fram að fullri hleðslu)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hröð hleðsla (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> að fullri hleðslu)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hæg hleðsla (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> fram að fullri hleðslu)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Skipta um notanda"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Skipta um notanda; núverandi notandi er <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Núverandi notandi er <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"SKRÁ NOTANDA ÚT"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Bæta nýjum notanda við?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Þegar þú bætir nýjum notanda við þarf sá notandi að setja upp svæðið sitt.\n\nHvaða notandi sem er getur uppfært forrit fyrir alla aðra notendur."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Fjarlægja notandann?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Öllum forritum og gögnum þessa notanda verður eytt."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Fjarlægja"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Tákn til vinstri"</string>
     <string name="right_icon" msgid="3952104823293824311">"Tákn til hægri"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Haltu inni og dragðu til að bæta við reitum"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Dragðu hingað til að fjarlægja"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Reitirnir mega ekki vera færri en sex"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Breyta"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Neðri á öllum skjánum"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Staða <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Ýttu tvisvar til að breyta."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Ýttu tvisvar til að bæta við."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Staða <xliff:g id="POSITION">%1$d</xliff:g>. Ýttu tvisvar til að velja."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Færa <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Fjarlægja <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> er bætt við í stöðu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> var fjarlægð"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> færð í stöðu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Bæta <xliff:g id="TILE_NAME">%1$s</xliff:g> við í stöðu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Færa <xliff:g id="TILE_NAME">%1$s</xliff:g> í stöðu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Flýtistillingaritill."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> tilkynning: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Hugsanlega virkar forritið ekki ef skjánum er skipt upp."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Opna vafra"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Farsímagögn"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Slökkt á Wi-Fi"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Slökkt á Bluetooth"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Slökkt á „Ónáðið ekki“"</string>
diff --git a/packages/SystemUI/res/values-is/strings_car.xml b/packages/SystemUI/res/values-is/strings_car.xml
index 2a633f4..9300e36 100644
--- a/packages/SystemUI/res/values-is/strings_car.xml
+++ b/packages/SystemUI/res/values-is/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gestur"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gestur"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Bæta notanda við"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nýr notandi"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Þegar þú bætir nýjum notanda við þarf viðkomandi að setja upp sitt eigið svæði."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 7bd52d4..467ca8d 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifiche"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"La batteria potrebbe esaurirsi a breve"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> rimanente"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%s</xliff:g> circa"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Tempo rimanente: <xliff:g id="TIME">%s</xliff:g> circa"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> restante. Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%2$s</xliff:g> circa"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> restante. Tempo rimanente: <xliff:g id="TIME">%2$s</xliff:g> circa"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> rimanente. Risparmio energetico attivo."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Impossibile ricaricare tramite USB. Utilizza il caricabatterie fornito in dotazione con il dispositivo."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Impossibile ricaricare tramite USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Richieste di accesso alla posizione attive"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Cancella tutte le notifiche."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Altre <xliff:g id="NUMBER_1">%s</xliff:g> notifiche nel gruppo.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> altra notifica nel gruppo.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silenzio\ntotale"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Solo con\npriorità"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Solo\nsveglie"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica veloce (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica lenta (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> al termine)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica veloce (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> al termine)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica lenta (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> al termine)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambio utente"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambia utente, utente corrente <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utente corrente <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"DISCONNETTI UTENTE"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Aggiungere un nuovo utente?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Il nuovo utente, una volta aggiunto, deve impostare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Rimuovere l\'utente?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Tutte le app e i dati di questo utente verranno eliminati."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Rimuovi"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Icona sinistra"</string>
     <string name="right_icon" msgid="3952104823293824311">"Icona destra"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Tieni premuto e trascina per aggiungere riquadri"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Trascina qui per rimuovere"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Occorrono almeno sei riquadri"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Modifica"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Schermata inferiore a schermo intero"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tocca due volte per modificare."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tocca due volte per aggiungere."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>. Tocca due volte per selezionare."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Sposta <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Rimuovi <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> è stato aggiunto alla posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> è stato rimosso"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> è stato spostato nella posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Aggiungi il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> alla posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Sposta il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> nella posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor di impostazioni rapide."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notifica di <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"L\'app potrebbe non funzionare con lo schermo diviso."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Informazioni app"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Vai al browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dati mobili"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi disattivato"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth non attivo"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Funzione Non disturbare disattivata"</string>
diff --git a/packages/SystemUI/res/values-it/strings_car.xml b/packages/SystemUI/res/values-it/strings_car.xml
index 095e5dc..e79adda 100644
--- a/packages/SystemUI/res/values-it/strings_car.xml
+++ b/packages/SystemUI/res/values-it/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Ospite"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Ospite"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Aggiungi utente"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nuovo utente"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Il nuovo utente, una volta aggiunto, dovrà configurare il proprio spazio."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index cac6d31..46d930e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -36,8 +36,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"הודעות"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ייתכן שהסוללה תתרוקן בקרוב"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>, נשארו בערך <xliff:g id="TIME">%s</xliff:g> על סמך השימוש במכשיר"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>, נשארו בערך <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"נותרו <xliff:g id="PERCENTAGE">%1$s</xliff:g>, נשארו בערך <xliff:g id="TIME">%2$s</xliff:g> על סמך השימוש במכשיר"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"נותרו <xliff:g id="PERCENTAGE">%1$s</xliff:g>, נשארו בערך <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>. הופעלה תכונת החיסכון בסוללה."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"‏לא ניתן לטעון באמצעות USB. ניתן להשתמש במטען שצורף למכשיר שלך."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"‏לא ניתן לטעון באמצעות USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"בקשות מיקום פעילות"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההודעות."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="two">יש בפנים עוד <xliff:g id="NUMBER_1">%s</xliff:g> הודעות.</item>
       <item quantity="many">יש בפנים עוד <xliff:g id="NUMBER_1">%s</xliff:g> הודעות.</item>
@@ -405,9 +405,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"שקט\nמוחלט"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"הודעות בעדיפות\nבלבד"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"התראות\nבלבד"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד לסיום)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה מהירה (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד לסיום)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה איטית (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד לסיום)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה מהירה (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה איטית (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"החלפת משתמש"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"החלף משתמש. המשתמש הנוכחי הוא <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"משתמש נוכחי <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -432,6 +432,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"נתק משתמש"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"האם להוסיף משתמש חדש?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"בעת הוספת משתמש חדש, על משתמש זה להגדיר את השטח שלו.\n\nכל משתמש יכול לעדכן אפליקציות עבור כל המשתמשים האחרים."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"האם להסיר את המשתמש?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"כל האפליקציות והנתונים של המשתמש הזה יימחקו."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"הסר"</string>
@@ -739,6 +742,8 @@
     <string name="left_icon" msgid="3096287125959387541">"סמל שמאלי"</string>
     <string name="right_icon" msgid="3952104823293824311">"סמל ימני"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"יש ללחוץ ולגרור כדי להוסיף אריחים"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"גרור לכאן כדי להסיר"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"יש צורך בשישה אריחים לכל הפחות"</string>
     <string name="qs_edit" msgid="2232596095725105230">"עריכה"</string>
@@ -767,12 +772,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"מסך תחתון מלא"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"מיקום <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. הקש פעמיים כדי לערוך."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. הקש פעמיים כדי להוסיף."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"מיקום <xliff:g id="POSITION">%1$d</xliff:g>. הקש פעמיים כדי לבחור."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"הזזת <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"הסרת <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> התווסף למיקום <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> הוסר"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> הועבר למיקום <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"הוספת <xliff:g id="TILE_NAME">%1$s</xliff:g> למיקום <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"העברת <xliff:g id="TILE_NAME">%1$s</xliff:g> למיקום <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"עורך הגדרות מהירות."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"הודעת <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"ייתכן שהיישום לא יפעל עם מסך מפוצל."</string>
@@ -833,7 +836,7 @@
     <string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
     <string name="go_to_web" msgid="2650669128861626071">"מעבר אל הדפדפן"</string>
     <string name="mobile_data" msgid="7094582042819250762">"נתונים סלולריים"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> ‏— <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> ‏— <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi כבוי"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"‏Bluetooth כבוי"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"מצב \'נא לא להפריע\' כבוי"</string>
diff --git a/packages/SystemUI/res/values-iw/strings_car.xml b/packages/SystemUI/res/values-iw/strings_car.xml
index 04a8b9e..19bd19d 100644
--- a/packages/SystemUI/res/values-iw/strings_car.xml
+++ b/packages/SystemUI/res/values-iw/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"אורח"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"אורח"</string>
     <string name="car_add_user" msgid="5245196248349230898">"הוספת משתמש"</string>
     <string name="car_new_user" msgid="8142927244990323906">"משתמש חדש"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"בעת הוספת משתמש חדש, על משתמש זה להגדיר את המרחב שלו."</string>
diff --git a/packages/SystemUI/res/values-ja/donottranslate.xml b/packages/SystemUI/res/values-ja/donottranslate.xml
deleted file mode 100644
index dcf434d..0000000
--- a/packages/SystemUI/res/values-ja/donottranslate.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%2$s\n%1$s</string>
-
-</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 10e9568..b34a5b4 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"もうすぐ電池がなくなります"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"残量が<xliff:g id="PERCENTAGE">%s</xliff:g>です"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"残量 <xliff:g id="PERCENTAGE">%s</xliff:g>、約 <xliff:g id="TIME">%s</xliff:g>(使用状況に基づく)"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"残量 <xliff:g id="PERCENTAGE">%s</xliff:g>、約 <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"残量 <xliff:g id="PERCENTAGE">%1$s</xliff:g>、約 <xliff:g id="TIME">%2$s</xliff:g>(使用状況に基づく)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"残量 <xliff:g id="PERCENTAGE">%1$s</xliff:g>、約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"残量が <xliff:g id="PERCENTAGE">%s</xliff:g> です。バッテリー セーバーは ON です。"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB 経由では充電できません。端末に付属の充電器を使用してください。"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB 経由では充電できません"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"現在地リクエストがアクティブ"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"他 <xliff:g id="NUMBER">%s</xliff:g> 件"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>、他 <xliff:g id="OVERFLOW">%s</xliff:g> 件"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>、他 <xliff:g id="OVERFLOW">%2$s</xliff:g> 件"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">他 <xliff:g id="NUMBER_1">%s</xliff:g> 件の通知</item>
       <item quantity="one">他 <xliff:g id="NUMBER_0">%s</xliff:g> 件の通知</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"サイレント\n"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"重要な\n通知のみ"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"アラーム\nのみ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中(完了まで <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 急速充電中(完了まで <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 低速充電中(完了まで <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中(完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 急速充電中(完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 低速充電中(完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ユーザーを切り替える"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ユーザーを切り替える、現在のユーザーは<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"現在のユーザー: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ユーザーをログアウト"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"新しいユーザーを追加しますか?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。\n\nすべてのユーザーは他のユーザーに代わってアプリを更新できます。"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"ユーザーを削除しますか?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"このユーザーのアプリとデータがすべて削除されます。"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"削除"</string>
@@ -537,7 +540,7 @@
     <string name="volume_ringer_status_normal" msgid="4273142424125855384">"着信音"</string>
     <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"バイブレーション"</string>
     <string name="volume_ringer_status_silent" msgid="6896394161022916369">"ミュート"</string>
-    <string name="qs_status_phone_vibrate" msgid="204362991135761679">"スマートフォンをバイブレーションに設定"</string>
+    <string name="qs_status_phone_vibrate" msgid="204362991135761679">"スマートフォンのバイブレーションは ON です"</string>
     <string name="qs_status_phone_muted" msgid="5437668875879171548">"スマートフォンをミュートに設定"</string>
     <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。タップしてミュートを解除します。"</string>
     <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。タップしてバイブレーションに設定します。ユーザー補助機能サービスがミュートされる場合があります。"</string>
@@ -605,7 +608,7 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"今後、この通知は表示されません"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"通知を最小化します"</string>
-    <string name="inline_blocking_helper" msgid="3055064577771478591">"通常、この通知は非表示にしています。\n引き続き、表示しますか?"</string>
+    <string name="inline_blocking_helper" msgid="3055064577771478591">"通常、この通知はスワイプして非表示にしています。\n今後も表示しますか?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"この通知を今後も表示しますか?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"通知を表示しない"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"今後も表示する"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"左アイコン"</string>
     <string name="right_icon" msgid="3952104823293824311">"右アイコン"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"タイルを追加するには押し続けながらドラッグ"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"削除するにはここにドラッグ"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"タイルは 6 個以上必要"</string>
     <string name="qs_edit" msgid="2232596095725105230">"編集"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"下部全画面"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ポジション <xliff:g id="POSITION">%1$d</xliff:g> の <xliff:g id="TILE_NAME">%2$s</xliff:g> を編集するにはダブルタップします。"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を追加するにはダブルタップします。"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ポジション <xliff:g id="POSITION">%1$d</xliff:g> に配置します。選択するにはダブルタップします。"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を移動します"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を削除します"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> をポジション <xliff:g id="POSITION">%2$d</xliff:g> に追加しました"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を削除しました"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> をポジション <xliff:g id="POSITION">%2$d</xliff:g> に移動しました"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> をポジション <xliff:g id="POSITION">%2$d</xliff:g> に追加"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> をポジション <xliff:g id="POSITION">%2$d</xliff:g> に移動"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"クイック設定エディタ"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> の通知: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"アプリは分割画面では動作しないことがあります。"</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"アプリ情報"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ブラウザに移動"</string>
     <string name="mobile_data" msgid="7094582042819250762">"モバイルデータ"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi は OFF です"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth は OFF です"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"マナーモードは OFF です"</string>
diff --git a/packages/SystemUI/res/values-ja/strings_car.xml b/packages/SystemUI/res/values-ja/strings_car.xml
index 5a2872d..7aa4389 100644
--- a/packages/SystemUI/res/values-ja/strings_car.xml
+++ b/packages/SystemUI/res/values-ja/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"ゲスト"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"ゲスト"</string>
     <string name="car_add_user" msgid="5245196248349230898">"ユーザーを追加"</string>
     <string name="car_new_user" msgid="8142927244990323906">"新しいユーザー"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index c28fab70..e490dac 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"შეტყობინებები"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ბატარეა შესაძლოა მალე ამოიწუროს"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>, რაც დაახლოებით <xliff:g id="TIME">%s</xliff:g> არის, მოხმარების გათვალისწინებით"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>, რაც დაახლოებით <xliff:g id="TIME">%s</xliff:g> არის"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"დარჩენილია <xliff:g id="PERCENTAGE">%1$s</xliff:g>, რაც დაახლოებით <xliff:g id="TIME">%2$s</xliff:g> არის, მოხმარების გათვალისწინებით"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"დარჩენილია <xliff:g id="PERCENTAGE">%1$s</xliff:g>, რაც დაახლოებით <xliff:g id="TIME">%2$s</xliff:g> არის"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>. ბატარეის დამზოგი ჩართულია."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB-თ დატენვა ვერ ხერხდება. გამოიყენეთ დამტენი, რომელიც თქვენს მოწყობილობას მოჰყვა."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB-თ დატენვა ვერ ხერხდება"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"მდებარეობის მოთხოვნები აქტიურია"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ყველა შეტყობინების წაშლა"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">კიდევ <xliff:g id="NUMBER_1">%s</xliff:g> შეტყობინება ჯგუფში.</item>
       <item quantity="one">კიდევ <xliff:g id="NUMBER_0">%s</xliff:g> შეტყობინება ჯგუფში.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"სრული\nსიჩუმე"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"მხოლოდ\nპრიორიტეტულები"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"მხოლოდ\nგაფრთხილებები"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> სრულ დატენვამდე)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება სწრაფად (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> სრულ დატენვამდე)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება ნელა (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> სრულ დატენვამდე)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> სრულ დატენვამდე)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება სწრაფად (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> სრულ დატენვამდე)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება ნელა (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> სრულ დატენვამდე)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"მომხმარებლის გადართვა"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"მომხმარებლის გდართვა. ამჟამინდელი მომხმარებელი <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"ამჟამინდელი მომხმარებელი <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"მომხმარებლის გასვლა"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"დაემატოს ახალი მომხმარებელი?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"ახალი მომხმარებლის დამატებისას, ამ მომხმარებელს საკუთარი სივრცის შექმნა მოუწევს.\n\nნებისმიერ მომხმარებელს შეუძლია აპები ყველა სხვა მომხმარებლისათვის განაახლოს."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"გსურთ მომხმარებლის წაშლა?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"ამ მომხმარებლის ყველა აპი და მონაცემი წაიშლება."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"წაშლა"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"მარცხენა ხატულა"</string>
     <string name="right_icon" msgid="3952104823293824311">"მარჯვენა ხატულა"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ჩავლებით გადაიტანეთ ბლოკების დასამატებლად"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ამოსაშლელად, ჩავლებით გადმოიტანეთ აქ"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"გჭირდებათ მინიმუმ 6 ბლოკი"</string>
     <string name="qs_edit" msgid="2232596095725105230">"რედაქტირება"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"ქვედა ნაწილის სრულ ეკრანზე გაშლა"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"პოზიცია <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. რედაქტირებისთვის, შეეხეთ ორმაგად."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. დასამატებლად, შეეხეთ ორმაგად."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"პოზიცია <xliff:g id="POSITION">%1$d</xliff:g>. ასარჩევად, შეეხეთ ორმაგად."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის გადატანა"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის წაშლა"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> დამატებულია პოზიციაზე <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ამოიშალა"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> გადატანილია პოზიციაზე <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის დამატება პოზიციაზე <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის გადატანა პოზიციაზე <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"სწრაფი პარამეტრების რედაქტორი."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> შეტყობინება: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"აპმა შეიძლება არ იმუშაოს გაყოფილი ეკრანის რეჟიმში."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ბრაუზერზე გადასვლა"</string>
     <string name="mobile_data" msgid="7094582042819250762">"მობილური ინტერნეტი"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi გამორთულია"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth გამორთულია"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"„არ შემაწუხოთ“ რეჟიმი გამორთულია"</string>
diff --git a/packages/SystemUI/res/values-ka/strings_car.xml b/packages/SystemUI/res/values-ka/strings_car.xml
index bb12f6d..4a6dfbd 100644
--- a/packages/SystemUI/res/values-ka/strings_car.xml
+++ b/packages/SystemUI/res/values-ka/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"სტუმარი"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"სტუმარი"</string>
     <string name="car_add_user" msgid="5245196248349230898">"მომხმარებლის დამატება"</string>
     <string name="car_new_user" msgid="8142927244990323906">"ახალი მომხმარებელი"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"ახალი მომხმარებლის დამატებისას, ამ მომხმარებელს საკუთარი სივრცის შექმნა მოუწევს."</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index f256d33..eb50c28 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Хабарлар"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Батерея заряды жақын арада бітуі мүмкін"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Пайдалану барысына байланысты <xliff:g id="PERCENTAGE">%s</xliff:g> заряд, шамамен <xliff:g id="TIME">%s</xliff:g> қалды"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> заряд, шамамен <xliff:g id="TIME">%s</xliff:g> қалды"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Пайдалану барысына байланысты <xliff:g id="PERCENTAGE">%1$s</xliff:g> заряд, шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> заряд, шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды. Battery Saver қосулы."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB арқылы зарядтау мүмкін емес. Құрылғымен бірге берілген зарядтау құралын пайдаланыңыз."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB арқылы зарядтау мүмкін емес"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Орын өтініштері қосылған"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Барлық хабарларды жойыңыз."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Ішінде тағы <xliff:g id="NUMBER_1">%s</xliff:g> хабарландыру.</item>
       <item quantity="one">Ішінде тағы <xliff:g id="NUMBER_0">%s</xliff:g> хабарландыру.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Толық\nтыныштық"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Тек\nбасымдық"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Тек\nдабылдар"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталуда (толуына <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> қалды)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жылдам зарядталуда (толуына <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> қалды)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Баяу зарядталуда (толуына <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> қалды)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталуда (толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жылдам зарядталуда (толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Баяу зарядталуда (толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Пайдаланушыны ауыстыру"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Пайдаланушыны ауыстыру, ағымдағы пайдаланушы <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Ағымдағы пайдаланушы: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ПАЙДАЛАНУШЫНЫ ШЫҒАРУ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Жаңа пайдаланушы қосылсын ба?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Жаңа пайдаланушыны қосқанда, сол адам өз кеңістігін реттеуі керек.\n\nКез келген пайдаланушы барлық басқа пайдаланушылар үшін қолданбаларды жаңарта алады."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Пайдаланушы жойылсын ба?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Осы пайдаланушының барлық қолданбалары мен деректері жойылады."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Жою"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Сол жақ белгіше"</string>
     <string name="right_icon" msgid="3952104823293824311">"Оң жақ белгіше"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Қажетті элементтерді сүйреп әкеліп қойыңыз"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Керексіздерін осы жерге сүйреңіз"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Кемінде 6 бөлшек қажет"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Өңдеу"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Төменгісін толық экранға шығару"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g> орны, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Өңдеу үшін екі рет түртіңіз."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Қосу үшін екі рет түртіңіз."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> орны. Таңдау үшін екі рет түртіңіз."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> жылжыту"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> жою"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> орнына қосылды"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> жойылды"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> орнына жылжытылды"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> бөлшегін <xliff:g id="POSITION">%2$d</xliff:g>-позицияға енгізу"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> бөлшегін <xliff:g id="POSITION">%2$d</xliff:g>-позицияға жылжыту"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Жылдам параметрлер өңдегіші."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> хабарландыруы: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Қолданба бөлінген экранда жұмыс істемеуі мүмкін."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Браузерге өту"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобильдік деректер"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өшірулі"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth өшірулі"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Мазаламау\" режимі өшірулі"</string>
diff --git a/packages/SystemUI/res/values-kk/strings_car.xml b/packages/SystemUI/res/values-kk/strings_car.xml
index 50aedf3..9915d98 100644
--- a/packages/SystemUI/res/values-kk/strings_car.xml
+++ b/packages/SystemUI/res/values-kk/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Қонақ"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Қонақ"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Пайдаланушыны енгізу"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Жаңа пайдаланушы"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Енгізілген жаңа пайдаланушы өз профилін реттеуі керек."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 2c9a554..4f1d71d 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ការ​ជូន​ដំណឹង"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"អាចនឹងអស់ថ្មក្នុងពេលបន្តិចទៀត"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"នៅ​សល់ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"នៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g> អាច​ប្រើ​បាន​ប្រហែល <xliff:g id="TIME">%s</xliff:g> ទៀត​ផ្អែកលើ​ការប្រើប្រាស់​របស់អ្នក"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"នៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g> អាច​ប្រើ​បាន​ប្រហែល <xliff:g id="TIME">%s</xliff:g> ទៀត"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"នៅសល់ <xliff:g id="PERCENTAGE">%1$s</xliff:g> អាច​ប្រើ​បាន​ប្រហែល <xliff:g id="TIME">%2$s</xliff:g> ទៀត​ផ្អែកលើ​ការប្រើប្រាស់​របស់អ្នក"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"នៅសល់ <xliff:g id="PERCENTAGE">%1$s</xliff:g> អាច​ប្រើ​បាន​ប្រហែល <xliff:g id="TIME">%2$s</xliff:g> ទៀត"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"នៅ​សល់ <xliff:g id="PERCENTAGE">%s</xliff:g> ។ កម្មវិធី​សន្សំ​ថ្ម​បានបើក។"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"មិន​អាច​សាក​តាម USB បានទេ។ សូម​ប្រើ​ឆ្នាំង​សាក​ដែល​ភ្ជាប់​មក​ជាមួយ​ឧបករណ៍​របស់អ្នក។"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"មិន​អាច​សាក​តាម USB បានទេ"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"សំណើ​ទីតាំង​សកម្ម"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"សម្អាត​ការ​ជូន​ដំណឹង​ទាំងអស់។"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">មានការជូនដំណឹង <xliff:g id="NUMBER_1">%s</xliff:g> ទៀតនៅខាងក្នុង</item>
       <item quantity="one">មានការជូនដំណឹង <xliff:g id="NUMBER_0">%s</xliff:g> ទៀតនៅខាងក្នុង</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"ស្ងៀមស្ងាត់\nទាំងស្រុង"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"អាទិភាព\nប៉ុណ្ណោះ"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"សំឡេងរោទ៍\nប៉ុណ្ណោះ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្ម (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ទៀតទើប​ពេញ)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ទៀតទើបពេញ)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្ម​​យឺត (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ទៀតទើប​ពេញ)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្ម (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ទៀតទើប​ពេញ)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ទៀតទើបពេញ)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុង​សាកថ្ម​​យឺត (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ទៀតទើប​ពេញ)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ប្ដូរ​អ្នក​ប្រើ"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ប្ដូរ​អ្នកប្រើ ​អ្នកប្រើ​បច្ចុប្បន្ន <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"អ្នកប្រើបច្ចុប្បន្ន <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ចុះឈ្មោះអ្នកប្រើចេញ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"បន្ថែម​អ្នកប្រើ​ថ្មី?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"ពេល​អ្នក​បន្ថែម​អ្នកប្រើ​ថ្មី អ្នកប្រើ​នោះ​ត្រូវ​កំណត់​ទំហំ​ផ្ទាល់​របស់​គេ។\n\nអ្នក​ប្រើ​ណាមួយ​ក៏​អាច​ធ្វើ​បច្ចុប្បន្នភាព​កម្មវិធី​សម្រាប់​អ្នកប្រើ​ផ្សេង​បាន​ដែរ។"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"យកអ្នកប្រើចេញ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"កម្មវិធី និងទិន្នន័យទាំងអស់របស់អ្នកប្រើនេះនឹងត្រូវបានលុប។"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"យកចេញ"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"រូបតំណាង​ខាង​ឆ្វេង"</string>
     <string name="right_icon" msgid="3952104823293824311">"រូបតំណាង​ខាង​ស្ដាំ"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ចុច​ឱ្យ​ជាប់ រួចអូសដើម្បី​បញ្ចូល​ប្រអប់"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"អូសទីនេះដើម្បីយកចេញ"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"អ្នកត្រូវការប្រអប់​យ៉ាងតិច 6"</string>
     <string name="qs_edit" msgid="2232596095725105230">"កែសម្រួល"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"អេក្រង់ពេញខាងក្រោម"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ទីតាំង <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>, ប៉ះពីរដងដើម្បីកែ"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>, ប៉ះពីរដងដើម្បីបន្ថែម"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ទីតាំង <xliff:g id="POSITION">%1$d</xliff:g>, ប៉ះពីរដងដើម្បីជ្រើស"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"ផ្លាស់ទី <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"យក <xliff:g id="TILE_NAME">%1$s</xliff:g> ចេញ"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ត្រូវបានបន្ថែមទៅទីតាំង <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ត្រូវបានយកចេញ"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> បានផ្លាស់ទីទៅទីតាំង <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"បញ្ចូល <xliff:g id="TILE_NAME">%1$s</xliff:g> ទៅទីតាំង <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"ផ្លាស់ទី <xliff:g id="TILE_NAME">%1$s</xliff:g> ទៅទីតាំង <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"កម្មវិធីកែការកំណត់រហ័ស"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> ការជូនដំណឹង៖ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"កម្មវិធីអាចនឹងមិនដំណើរការនៅលើអេក្រង់បំបែកទេ"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ព័ត៌មាន​កម្មវិធី"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ចូល​ទៅ​កម្មវិធី​រុករក​តាម​អ៊ីនធឺណិត"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ទិន្នន័យ​ទូរសព្ទចល័ត"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi បាន​បិទ"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ប៊្លូធូស​បាន​បិទ"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"មុខងារ​កុំរំខាន​បាន​បិទ"</string>
diff --git a/packages/SystemUI/res/values-km/strings_car.xml b/packages/SystemUI/res/values-km/strings_car.xml
index 15b462c..cae300d 100644
--- a/packages/SystemUI/res/values-km/strings_car.xml
+++ b/packages/SystemUI/res/values-km/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"ភ្ញៀវ"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"ភ្ញៀវ"</string>
     <string name="car_add_user" msgid="5245196248349230898">"បញ្ចូល​អ្នក​ប្រើប្រាស់"</string>
     <string name="car_new_user" msgid="8142927244990323906">"អ្នក​ប្រើប្រាស់​ថ្មី"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"នៅពេលដែល​អ្នក​បញ្ចូល​អ្នក​ប្រើប្រាស់​ថ្មី បុគ្គល​នោះ​ត្រូវតែ​រៀបចំ​ទំហំ​ផ្ទុក​របស់គេ។"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 8760d00..49a9419b 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ಬ್ಯಾಟರಿ ಸದ್ಯದಲ್ಲೇ ಖಾಲಿಯಾಗಬಹುದು"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಉಳಿದಿದೆ"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಬಾಕಿ ಉಳಿದಿದೆ, ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ <xliff:g id="TIME">%s</xliff:g> ಉಳಿದಿದೆ"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಬಾಕಿ ಉಳಿದಿದೆ, <xliff:g id="TIME">%s</xliff:g> ಉಳಿದಿದೆ"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ಬಾಕಿ ಉಳಿದಿದೆ, ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ <xliff:g id="TIME">%2$s</xliff:g> ಉಳಿದಿದೆ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ಬಾಕಿ ಉಳಿದಿದೆ, <xliff:g id="TIME">%2$s</xliff:g> ಉಳಿದಿದೆ"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಉಳಿದಿದೆ. ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಆನ್‌ ಆಗಿದೆ."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB ಮೂಲಕ ಚಾರ್ಜ್‌ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ನಿಮ್ಮ ಸಾಧನದೊಂದಿಗೆ ನೀಡಲಾಗಿರುವ ಚಾರ್ಜರ್‌ ಬಳಸಿ."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB ಮೂಲಕ ಚಾರ್ಜ್‌ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"ಸ್ಥಳ ವಿನಂತಿಗಳು ಸಕ್ರಿಯವಾಗಿವೆ"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೆರವುಗೊಳಿಸು."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು ಅಧಿಸೂಚನೆಗಳು ಒಳಗಿವೆ.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು ಅಧಿಸೂಚನೆಗಳು ಒಳಗಿವೆ.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"ಸಂಪೂರ್ಣ\nನಿಶ್ಯಬ್ಧ"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ಆದ್ಯತೆ\nಮಾತ್ರ"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ಅಲಾರಮ್‌ಗಳು\nಮಾತ್ರ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್‌ಆಗುತ್ತಿದೆ (ಪೂರ್ಣಗೊಳ್ಳಲು <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ಸಮಯ ಬಾಕಿ)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ (ಪೂರ್ಣಗೊಳ್ಳಲು <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ಸಮಯ ಬಾಕಿ)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್‌ಆಗುತ್ತಿದೆ (ಪೂರ್ಣವಾಗಲು <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ಸಮಯ ಬಾಕಿ)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್‌ಆಗುತ್ತಿದೆ (ಪೂರ್ಣಗೊಳ್ಳಲು <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ (ಪೂರ್ಣಗೊಳ್ಳಲು <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್‌ಆಗುತ್ತಿದೆ (ಪೂರ್ಣವಾಗಲು <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ, ಪ್ರಸ್ತುತ ಬಳಕೆದಾರ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"<xliff:g id="CURRENT_USER_NAME">%s</xliff:g> ಪ್ರಸ್ತುತ ಬಳಕೆದಾರ"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ಬಳಕೆದಾರರನ್ನು ಲಾಗ್ಔಟ್ ಮಾಡಿ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸುವುದೇ?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"ನೀವು ಒಬ್ಬ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಸ್ಥಾಪಿಸಬೇಕಾಗುತ್ತದೆ.\n\nಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಬಹುದು."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕುವುದೇ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"ಈ ಬಳಕೆದಾರರ ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುವುದು."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"ತೆಗೆದುಹಾಕಿ"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"ಎಡ ಐಕಾನ್"</string>
     <string name="right_icon" msgid="3952104823293824311">"ಬಲ ಐಕಾನ್"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ಟೈಲ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಹೋಲ್ಡ್‌ ಮಾಡಿ ಮತ್ತು ಡ್ರ್ಯಾಗ್‌ ಮಾಡಿ"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ತೆಗೆದುಹಾಕಲು ಇಲ್ಲಿ ಡ್ರ್ಯಾಗ್‌ ಮಾಡಿ"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"ನಿಮಗೆ ಕನಿಷ್ಠ 6 ಟೈಲ್‌ಗಳ ಅಗತ್ಯವಿದೆ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ಎಡಿಟ್"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"ಕೆಳಗಿನ ಪೂರ್ಣ ಪರದೆ"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ಸ್ಥಳ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. ಎಡಿಟ್ ಮಾಡಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ಸೇರಿಸಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ಸ್ಥಳ <xliff:g id="POSITION">%1$d</xliff:g>. ಆಯ್ಕೆಮಾಡಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ಸರಿಸಿ"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ತೆಗೆದುಹಾಕಿ"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="POSITION">%2$d</xliff:g> ಸ್ಥಾನಕ್ಕೆ <xliff:g id="TILE_NAME">%1$s</xliff:g> ಸೇರಿಸಲಾಗಿದೆ"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="POSITION">%2$d</xliff:g> ಸ್ಥಾನಕ್ಕೆ <xliff:g id="TILE_NAME">%1$s</xliff:g> ಸೇರಿಸಲಾಗಿದೆ"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ಅನ್ನು <xliff:g id="POSITION">%2$d</xliff:g> ಗೆ ಸೇರಿಸಿ"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ಅನ್ನು <xliff:g id="POSITION">%2$d</xliff:g> ಗೆ ಸರಿಸಿ"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳ ಎಡಿಟರ್."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> ಅಧಿಸೂಚನೆ: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"ವಿಭಜಿಸಿದ ಪರದೆಯಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕೆಲಸ ಮಾಡದೇ ಇರಬಹುದು."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ಬ್ರೌಸರ್‌ಗೆ ಹೋಗಿ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ವೈ-ಫೈ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ಬ್ಲೂಟೂತ್‌ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆಫ್ ಆಗಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings_car.xml b/packages/SystemUI/res/values-kn/strings_car.xml
index d06d411..2b07ac2 100644
--- a/packages/SystemUI/res/values-kn/strings_car.xml
+++ b/packages/SystemUI/res/values-kn/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"ಅತಿಥಿ"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"ಅತಿಥಿ"</string>
     <string name="car_add_user" msgid="5245196248349230898">"ಬಳಕೆದಾರ ಸೇರಿಸು"</string>
     <string name="car_new_user" msgid="8142927244990323906">"ಹೊಸ ಬಳಕೆದಾರ"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"ನೀವು ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಸೆಟಪ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string>
diff --git a/packages/SystemUI/res/values-ko/donottranslate.xml b/packages/SystemUI/res/values-ko/donottranslate.xml
deleted file mode 100644
index dcf434d..0000000
--- a/packages/SystemUI/res/values-ko/donottranslate.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%2$s\n%1$s</string>
-
-</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 7983966..ad98bce 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"알림"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"배터리가 얼마 남지 않음"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남았습니다."</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남음, 내 사용량을 기준으로 약 <xliff:g id="TIME">%s</xliff:g> 남음"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남음, 약 <xliff:g id="TIME">%s</xliff:g> 남음"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> 남음, 내 사용량을 기준으로 약 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> 남음, 약 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남았습니다. 배터리 세이버를 사용 중입니다."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB로 충전할 수 없습니다. 기기와 함께 제공된 충전기를 사용하세요."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB로 충전할 수 없습니다."</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"위치 요청 있음"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"<xliff:g id="NUMBER">%s</xliff:g>개 더보기"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g>개 알림 더보기</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g>개 알림 더보기</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"모두\n차단"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"중요 알림만\n허용"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"알람만\n"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> 후 충전 완료)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 고속 충전 중(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> 후 충전 완료)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 저속 충전 중(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> 후 충전 완료)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중(<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 고속 충전 중(<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 저속 충전 중(<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"사용자 전환"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"사용자 전환, 현재 사용자 <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"현재 사용자: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"사용자 로그아웃"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"새 사용자를 추가할까요?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"추가된 새로운 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자는 다른 사용자들을 위하여 앱을 업데이트할 수 있습니다."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"사용자를 삭제할까요?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"이 사용자의 모든 앱과 데이터가 삭제됩니다."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"삭제"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"왼쪽 아이콘"</string>
     <string name="right_icon" msgid="3952104823293824311">"오른쪽 아이콘"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"길게 터치하고 드래그하여 타일 추가"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"여기로 드래그하여 삭제"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"6개 이상의 타일이 필요합니다."</string>
     <string name="qs_edit" msgid="2232596095725105230">"수정"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"아래쪽 화면 전체화면"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"위치 <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. 수정하려면 두 번 탭하세요."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. 추가하려면 두 번 탭하세요."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"위치 <xliff:g id="POSITION">%1$d</xliff:g>. 선택하려면 두 번 탭하세요."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 이동"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 삭제"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일이 위치 <xliff:g id="POSITION">%2$d</xliff:g>에 추가됩니다."</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일이 삭제되었습니다."</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일을 위치 <xliff:g id="POSITION">%2$d</xliff:g>(으)로 이동함"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일을 위치 <xliff:g id="POSITION">%2$d</xliff:g>에 추가"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일을 위치 <xliff:g id="POSITION">%2$d</xliff:g>(으)로 이동"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"빠른 설정 편집기"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> 알림: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"앱이 분할 화면에서 작동하지 않을 수 있습니다."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
     <string name="go_to_web" msgid="2650669128861626071">"브라우저로 이동"</string>
     <string name="mobile_data" msgid="7094582042819250762">"모바일 데이터"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g>, <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g>, <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi가 사용 중지됨"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"블루투스가 사용 중지됨"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"알림 일시중지가 사용 중지됨"</string>
diff --git a/packages/SystemUI/res/values-ko/strings_car.xml b/packages/SystemUI/res/values-ko/strings_car.xml
index 1af18aa..31cb38f 100644
--- a/packages/SystemUI/res/values-ko/strings_car.xml
+++ b/packages/SystemUI/res/values-ko/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"게스트"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"게스트"</string>
     <string name="car_add_user" msgid="5245196248349230898">"사용자 추가"</string>
     <string name="car_new_user" msgid="8142927244990323906">"신규 사용자"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"추가된 새로운 사용자는 자신의 공간을 설정해야 합니다."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 5ee60c9..0bbdc91 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Билдирмелер"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Батарея жакында отуруп калышы мүмкүн"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды, колдонушуңузга караганда болжол менен дагы <xliff:g id="TIME">%s</xliff:g> бар"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды, болжол менен дагы <xliff:g id="TIME">%s</xliff:g> бар"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> калды, колдонушуңузга караганда болжол менен дагы <xliff:g id="TIME">%2$s</xliff:g> бар"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> калды, болжол менен дагы <xliff:g id="TIME">%2$s</xliff:g> бар"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды. Батареяны үнөмдөгүч режими күйүк."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB аркылуу кубатталбай жатат. Түзмөгүңүз менен келген кубаттагычты колдонуңуз."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB аркылуу кубатталбай жатат"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Жайгаштыруу талаптары иштелүүдө"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Бардык эскертмелерди тазалоо."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Дагы <xliff:g id="NUMBER_1">%s</xliff:g> эскертме бар.</item>
       <item quantity="one">Дагы <xliff:g id="NUMBER_0">%s</xliff:g> эскертме бар.</item>
@@ -299,7 +299,7 @@
     <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Жайгашытрууну өчүрүү"</string>
     <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Медиа түзмөгү"</string>
     <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
-    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Куткаруучуларга чалуу гана"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Өзгөчө кырдаалда гана чалууга болот"</string>
     <string name="quick_settings_settings_label" msgid="5326556592578065401">"Жөндөөлөр"</string>
     <string name="quick_settings_time_label" msgid="4635969182239736408">"Убакыт"</string>
     <string name="quick_settings_user_label" msgid="5238995632130897840">"Мен"</string>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Тым-\nтырс"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Артыкчылыктуу\nгана"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Ойготкучтар\nгана"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда (толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> калды)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Тез кубатталууда (толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> калды)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жай кубатталууда (толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> калды)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда (толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Тез кубатталууда (толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жай кубатталууда (толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Колдонуучуну которуу"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Колдонуучуну күйгүзүү, учурдагы колдонуучу <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Учурдагы колдонуучу <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"КОЛДОНУУЧУНУ ТУТУМДАН ЧЫГАРУУ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Жаңы колдонуучу кошосузбу?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Жаңы колдонуучу кошулганда, ал өз мейкиндигин түзүп алышы керек.\n\nКолдонмолорду бир колдонуучу жаңыртканда, ал калган бардык колдонуучулар үчүн да жаңырат."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Колдонуучу алынып салынсынбы?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Бул колдонуучунун бардык колдонмолору жана дайындары жок кылынат."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Алып салуу"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Сол жактагы сүрөтчө"</string>
     <string name="right_icon" msgid="3952104823293824311">"Оң жактагы сүрөтчө"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Керектүү элементтерди сүйрөп келиңиз"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Алып салуу үчүн бул жерге сүйрөңүз"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Сизге жок дегенде 6 мозаика керек"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Түзөтүү"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Ылдыйкы экранды толук экран режимине өткөрүү"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Түзөтүү үчүн эки жолу таптаңыз."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Кошуу үчүн эки жолу таптаңыз."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>. Тандоо үчүн эки жолу таптаңыз."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> дегенди жылдыруу"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> дегенди алып салуу"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> деген <xliff:g id="POSITION">%2$d</xliff:g>-орунга кошулду"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> алынып салынды"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> деген <xliff:g id="POSITION">%2$d</xliff:g>-орунга жылдырылды"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> плиткасы <xliff:g id="POSITION">%2$d</xliff:g>-позицияга кошулсун"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> плиткасы <xliff:g id="POSITION">%2$d</xliff:g>-позицияга кошулсун"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Ыкчам жөндөөлөр түзөткүчү."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> эскертмеси: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Колдонмодо экран бөлүнбөшү мүмкүн."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Серепчиге өтүү"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобилдик Интернет"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өчүк"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth өчүк"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Тынчымды алба\" режими өчүк"</string>
diff --git a/packages/SystemUI/res/values-ky/strings_car.xml b/packages/SystemUI/res/values-ky/strings_car.xml
index f84e073..237e638 100644
--- a/packages/SystemUI/res/values-ky/strings_car.xml
+++ b/packages/SystemUI/res/values-ky/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Конок"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Конок"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Колдонуучу кошуу"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Жаңы колдонуучу"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Жаңы колдонуучу кошулганда, ал өзүнүн профилин жөндөп алышы керек."</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 7e2375e..12c67db 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ການແຈ້ງເຕືອນ"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ແບັດເຕີຣີໃກ້ຈະໝົດແລ້ວ"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"ຍັງ​ເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>, ປະມານ <xliff:g id="TIME">%s</xliff:g> ໂດຍອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>, ປະມານ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%1$s</xliff:g>, ປະມານ <xliff:g id="TIME">%2$s</xliff:g> ໂດຍອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%1$s</xliff:g>, ປະມານ <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>. ເປີດໃຊ້ຕົວປະຢັດແບັດເຕີຣີແລ້ວ."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"ບໍ່ສາມາດສາກຜ່ານ USB ໄດ້. ໃຫ້ໃຊ້ຕົວສາກທີ່ມາພ້ອມກັບອຸປະກອນຂອງທ່ານ."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"ບໍ່ສາມາດສາກຜ່ານ USB ໄດ້"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"ການຮ້ອງຂໍສະຖານທີ່ທີ່ເຮັດວຽກຢູ່"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ລຶບການແຈ້ງເຕືອນທັງໝົດ."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">ມີ <xliff:g id="NUMBER_1">%s</xliff:g> ການແຈ້ງເຕືອນເພີ່ມເຕີມຢູ່ທາງໃນ.</item>
       <item quantity="one">ມີ <xliff:g id="NUMBER_0">%s</xliff:g> ການແຈ້ງເຕືອນເພີ່ມເຕີມຢູ່ທາງໃນ.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"ຄວາມ​ງຽບ\nທັງ​ໝົດ"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ບຸ​ລິ​ມະ​ສິດ\nເທົ່າ​ນັ້ນ"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ໂມງ​ປຸກ\nເທົ່າ​ນັ້ນ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກ (ອີກ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ຈຶ່ງຈະເຕັມ)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກແບບດ່ວນ (ອີກ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ຈຶ່ງຈະເຕັມ)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກແບບຊ້າ (ອີກ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ຈຶ່ງຈະເຕັມ)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກ (ອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ຈຶ່ງຈະເຕັມ)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກແບບດ່ວນ (ອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ຈຶ່ງຈະເຕັມ)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກແບບຊ້າ (ອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ຈຶ່ງຈະເຕັມ)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ສະຫຼັບຜູ້ໃຊ້"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ປ່ຽນຜູ່ໃຊ້, ຜູ່ໃຊ້ປະຈຸບັນ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"ຜູ້ໃຊ້ປະຈຸບັນ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ເອົາຜູ້ໃຊ້ອອກຈາກລະບົບ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"ເພີ່ມຜູ້ໃຊ້ໃໝ່ບໍ?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"ເມື່ອ​ທ່ານ​ເພີ່ມ​ຜູ້ໃຊ້​ໃໝ່, ຜູ້ໃຊ້​ນັ້ນ​ຈະ​ຕ້ອງ​ຕັ້ງ​ຄ່າ​ພື້ນ​ທີ່​ບ່ອນ​ຈັດ​ເກັບ​ຂໍ້​ມູນ​ຂອງ​ລາວ.\n\nຜູ້ໃຊ້​ທຸກ​ຄົນ​ສາ​ມາດ​ອັບ​ເດດ​ແອັບຯຂອງ​ຜູ້​ໃຊ້​ຄົນ​ອື່ນ​ທັງ​ໝົດ​ໄດ້."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"ລຶບຜູ້ໃຊ້ອອກບໍ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"ທຸກ​ແອັບ ແລະ ຂໍ້​ມູນ​ຂອງ​ຜູ້​ໃຊ້​ນີ້​ຈະ​ຖືກ​ລຶບ."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"ເອົາ​ອອກ"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"ໄອຄອນຊ້າຍ"</string>
     <string name="right_icon" msgid="3952104823293824311">"ໄອຄອນຂວາ"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ກົດຄ້າງໄວ້ແລ້ວລາກເພື່ອເພີ່ມຊ່ອງ"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ລາກມາບ່ອນນີ້ເພື່ອລຶບອອກ"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"ທ່ານຍຕ້ອງໃຊ້ຢ່າງໜ້ອຍ 6 ຊ່ອງ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ແກ້ໄຂ"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"ເຕັມໜ້າຈໍລຸ່ມສຸດ"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. ແຕະສອງເທື່ອເພື່ອແກ້ໄຂ."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ແຕະສອງເທື່ອເພື່ອເພີ່ມ."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>. ແຕະສອງເທື່ອເພື່ອເລືອກ."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"ຍ້າຍ <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"ລຶບ <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ຖືກເພີ່ມໃສ່ຕຳແໜ່ງ <xliff:g id="POSITION">%2$d</xliff:g> ແລ້ວ"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"ລຶບ <xliff:g id="TILE_NAME">%1$s</xliff:g> ອອກແລ້ວ"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ຍ້າຍໄປຕຳແໜ່ງ <xliff:g id="POSITION">%2$d</xliff:g> ແລ້ວ"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"ເພີ່ມ <xliff:g id="TILE_NAME">%1$s</xliff:g> ໄປຕຳແໜ່ງ <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"ຍ້າຍ <xliff:g id="TILE_NAME">%1$s</xliff:g> ໄປຕຳແໜ່ງ <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ຕົວແກ້ໄຂການຕັ້ງຄ່າດ່ວນ"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"ການແຈ້ງເຕືອນ <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"ແອັບອາດໃຊ້ບໍ່ໄດ້ກັບການແບ່ງໜ້າຈໍ."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ໄປທີ່ໂປຣແກຣມທ່ອງເວັບ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ອິນເຕີເນັດມືຖື"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ປິດຢູ່"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ປິດຢູ່"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"ຫ້າມລົບກວນ ປິດຢູ່"</string>
diff --git a/packages/SystemUI/res/values-lo/strings_car.xml b/packages/SystemUI/res/values-lo/strings_car.xml
index 124d6a8..43067f5 100644
--- a/packages/SystemUI/res/values-lo/strings_car.xml
+++ b/packages/SystemUI/res/values-lo/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"ແຂກ"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"ແຂກ"</string>
     <string name="car_add_user" msgid="5245196248349230898">"ເພີ່ມຜູ້ໃຊ້"</string>
     <string name="car_new_user" msgid="8142927244990323906">"ຜູ້ໃຊ້ໃໝ່"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"ເມື່ອທ່ານເພີ່ມຜູ້ໃຊ້ໃໝ່, ບຸກຄົນນັ້ນຈຳເປັນຕ້ອງຕັ້ງຄ່າພື້ນທີ່ຂອງເຂົາເຈົ້າ."</string>
diff --git a/packages/SystemUI/res/values-lt/donottranslate.xml b/packages/SystemUI/res/values-lt/donottranslate.xml
deleted file mode 100644
index dcf434d..0000000
--- a/packages/SystemUI/res/values-lt/donottranslate.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%2$s\n%1$s</string>
-
-</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d784ba6..f59b1ad 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -36,8 +36,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pranešimai"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Akumuliatoriaus energija gali netrukus išsekti"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Liko <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Liko: <xliff:g id="PERCENTAGE">%s</xliff:g> (atsižvelgiant į naudojimą liko maždaug <xliff:g id="TIME">%s</xliff:g>)"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Liko: <xliff:g id="PERCENTAGE">%s</xliff:g> (liko maždaug <xliff:g id="TIME">%s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Liko: <xliff:g id="PERCENTAGE">%1$s</xliff:g> (atsižvelgiant į naudojimą liko maždaug <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Liko: <xliff:g id="PERCENTAGE">%1$s</xliff:g> (liko maždaug <xliff:g id="TIME">%2$s</xliff:g>)"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Liko <xliff:g id="PERCENTAGE">%s</xliff:g>. Akumuliatoriaus tausojimo priemonė įjungta."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Negalima įkrauti naudojant USB. Naudokite originalų su įrenginiu pateiktą įkroviklį."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Negalima įkrauti naudojant USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Vietovės užklausos aktyvios"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"Dar <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Grupėje yra dar <xliff:g id="NUMBER_1">%s</xliff:g> pranešimas.</item>
       <item quantity="few">Grupėje yra dar <xliff:g id="NUMBER_1">%s</xliff:g> pranešimai.</item>
@@ -405,9 +405,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Visiška\ntyla"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Tik\nprioritetiniai"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Tik\nsignalai"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkrovimo)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Greitai įkraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkr.)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lėtai įkraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkr.)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Greitai įkraunama (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkr.)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lėtai įkraunama (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkr.)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Perjungti naudotoją"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Perjungti naudotoją, dabartinis naudotojas <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Dabartinis naudotojas <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -432,6 +432,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ATJUNGTI NAUDOTOJĄ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Pridėti naują naudotoją?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Kai pridedate naują naudotoją, šis asmuo turi nustatyti savo erdvę.\n\nBet kuris naudotojas gali atnaujinti visų kitų naudotojų programas."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Pašalinti naudotoją?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Bus ištrinti visi šio naudotojo duomenys ir programos."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Pašalinti"</string>
@@ -739,6 +742,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Piktograma kairėje"</string>
     <string name="right_icon" msgid="3952104823293824311">"Piktograma dešinėje"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Jei norite pridėti išklotinių, laikykite nuspaudę ir vilkite"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Vilkite čia, jei norite pašalinti"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Turi būti bent 6 išklotinės"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Redaguoti"</string>
@@ -767,12 +772,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Apatinis ekranas viso ekrano režimu"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g> padėtis, išklotinės elementas „<xliff:g id="TILE_NAME">%2$s</xliff:g>“. Dukart palieskite, kad redaguotumėte."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“. Dukart palieskite, kad pridėtumėte."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> padėtis. Dukart palieskite, kad pasirinktumėte."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Perkelti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Pašalinti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ pridėtas prie <xliff:g id="POSITION">%2$d</xliff:g> padėties"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ pašalintas"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ perkeltas į <xliff:g id="POSITION">%2$d</xliff:g> padėtį"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Pridėti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ į <xliff:g id="POSITION">%2$d</xliff:g> padėtį"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Perkelti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ į <xliff:g id="POSITION">%2$d</xliff:g> padėtį"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Sparčiųjų nustatymų redagavimo priemonė."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"„<xliff:g id="ID_1">%1$s</xliff:g>“ pranešimas: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Programa gali neveikti naudojant skaidytą ekraną."</string>
@@ -828,12 +831,12 @@
     <string name="notification_channel_general" msgid="4525309436693914482">"Bendrieji pranešimai"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Saugykla"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Užuominos"</string>
-    <string name="instant_apps" msgid="6647570248119804907">"Akimirksniu įkeliamos programėlės"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Akimirksniu įkeliamų programėlių nereikia įdiegti."</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Akimirksniu įkeliamos programos"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Akimirksniu įkeliamų programų nereikia įdiegti."</string>
     <string name="app_info" msgid="6856026610594615344">"Programos informacija"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Eiti į naršyklę"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilieji duomenys"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g>–<xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g>–<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"„Wi-Fi“ išjungtas"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"„Bluetooth“ išjungtas"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Netrukdymo režimas išjungtas"</string>
diff --git a/packages/SystemUI/res/values-lt/strings_car.xml b/packages/SystemUI/res/values-lt/strings_car.xml
index 7b7856f..ae9f24a 100644
--- a/packages/SystemUI/res/values-lt/strings_car.xml
+++ b/packages/SystemUI/res/values-lt/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Svečias"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Svečias"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Pridėti naudotoją"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Naujas naudotojas"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kai pridedate naują naudotoją, šis asmuo turi nustatyti savo vietą."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 86e2e4c..0075094 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -35,8 +35,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Paziņojumi"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Akumulators, iespējams, drīz izlādēsies"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Atlikušais laiks: <xliff:g id="PERCENTAGE">%s</xliff:g> — aptuveni <xliff:g id="TIME">%s</xliff:g> (ņemot vērā lietojumu)"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Atlikušais laiks: <xliff:g id="PERCENTAGE">%s</xliff:g> — aptuveni <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Atlikušais laiks: <xliff:g id="PERCENTAGE">%1$s</xliff:g> — aptuveni <xliff:g id="TIME">%2$s</xliff:g> (ņemot vērā lietojumu)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Atlikušais laiks: <xliff:g id="PERCENTAGE">%1$s</xliff:g> — aptuveni <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>. Ir ieslēgts akumulatora jaudas taupīšanas režīms."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Nevar veikt uzlādi, izmantojot USB. Izmantojiet ierīces komplektācijā iekļauto uzlādes ierīci."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Nevar veikt uzlādi, izmantojot USB"</string>
@@ -258,7 +258,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aktīvi atrašanās vietu pieprasījumi"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"vēl <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> + <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> + <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="zero">Vēl <xliff:g id="NUMBER_1">%s</xliff:g> paziņojumi grupā.</item>
       <item quantity="one">Vēl <xliff:g id="NUMBER_1">%s</xliff:g> paziņojums grupā.</item>
@@ -402,9 +402,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Pilnīgs\nklusums"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Tikai\nprioritārie"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Tikai\nsignāli"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnai uzlādei)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ātrā uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnai uzlādei)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lēnā uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnai uzlādei)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> līdz pilnai uzlādei)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ātrā uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> līdz pilnai uzlādei)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lēnā uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> līdz pilnai uzlādei)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Mainīt lietotāju"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Pārslēgt lietotāju; pašreizējais lietotājs: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Pašreizējais lietotājs: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -429,6 +429,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ATTEIKT LIETOTĀJU"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Vai pievienot jaunu lietotāju?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Kad pievienosiet jaunu lietotāju, viņam būs jāizveido savs profils.\n\nIkviens lietotājs var atjaunināt lietotnes citu lietotāju vietā."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Vai noņemt lietotāju?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Tiks dzēstas visas šī lietotāja lietotnes un dati."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Noņemt"</string>
@@ -734,6 +737,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ikona kreisajā pusē"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ikona labajā pusē"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Lai pievienotu elementus, pieturiet tos un velciet"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Lai noņemtu vienumus, velciet tos šeit."</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Nepieciešami vismaz 6 elementi"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Rediģēt"</string>
@@ -762,12 +767,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Apakšdaļu pa visu ekrānu"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. pozīcija, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Lai rediģētu, veiciet dubultskārienu."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lai pievienotu, veiciet dubultskārienu."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. pozīcija. Lai atlasītu, veiciet dubultskārienu."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Pārvietot elementu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Noņemt elementu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Elements <xliff:g id="TILE_NAME">%1$s</xliff:g> ir pievienots <xliff:g id="POSITION">%2$d</xliff:g>. pozīcijā"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Elements <xliff:g id="TILE_NAME">%1$s</xliff:g> ir noņemts"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Elements <xliff:g id="TILE_NAME">%1$s</xliff:g> ir pārvietots uz <xliff:g id="POSITION">%2$d</xliff:g>. pozīciju"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Pievienot elementu “<xliff:g id="TILE_NAME">%1$s</xliff:g>” <xliff:g id="POSITION">%2$d</xliff:g>. pozīcijā"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Pārvietot elementu “<xliff:g id="TILE_NAME">%1$s</xliff:g>” uz <xliff:g id="POSITION">%2$d</xliff:g>. pozīciju"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Ātro iestatījumu redaktors."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> paziņojums: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Iespējams, lietotnē nedarbosies ekrāna sadalīšana."</string>
@@ -828,7 +831,7 @@
     <string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Atvērt pārlūku"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilie dati"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ir izslēgts"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ir izslēgts"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Režīms “Netraucēt” ir izslēgts"</string>
diff --git a/packages/SystemUI/res/values-lv/strings_car.xml b/packages/SystemUI/res/values-lv/strings_car.xml
index d19834b..b884614 100644
--- a/packages/SystemUI/res/values-lv/strings_car.xml
+++ b/packages/SystemUI/res/values-lv/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Viesis"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Viesis"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Lietotāja pievienošana"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Jauns lietotājs"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kad pievienosiet jaunu lietotāju, viņam būs jāizveido savs profils."</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 88ea162..68dc653 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известувања"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Наскоро може да снема батерија"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>, уште околу <xliff:g id="TIME">%s</xliff:g> според користењето"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>, уште околу <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Преостануваат <xliff:g id="PERCENTAGE">%1$s</xliff:g>, уште околу <xliff:g id="TIME">%2$s</xliff:g> според користењето"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Преостануваат <xliff:g id="PERCENTAGE">%1$s</xliff:g>, уште околу <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>. Штедачот на батерија е вклучен."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Не може да се полни преку USB. Користете го полначот што дојде со вашиот уред."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Не може да се полни преку USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Активни барања за локација"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Исчисти ги сите известувања."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, + <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, + <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Уште <xliff:g id="NUMBER_1">%s</xliff:g> известување внатре.</item>
       <item quantity="other">Уште <xliff:g id="NUMBER_1">%s</xliff:g> известувања внатре.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Целосна\nтишина"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Само\nприоритетни"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Само\nаларми"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до полна батерија)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Брзо полнење (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до полна батерија)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Бавно полнење (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до полна батерија)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до полна батерија)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Брзо полнење (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до полна батерија)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Бавно полнење (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до полна батерија)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Промени го корисникот"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Промени го корисникот, тековен корисник <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Тековен корисник <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ОДЈАВИ ГО КОРИСНИКОТ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Да се додаде нов корисник?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Кога додавате нов корисник, тоа лице треба да го постави својот простор.\n\nСекој корисник може да ажурира апликации за сите други корисници."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Да се отстрани корисникот?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Сите апликации и податоци од овој корисник ќе се избришат."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Отстрани"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Лева икона"</string>
     <string name="right_icon" msgid="3952104823293824311">"Десна икона"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Задржете и влечете за да додадете плочки"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Повлечете тука за да се отстрани"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Потребни ви се најмалку 6 плочки"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Измени"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Долниот на цел екран"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Место <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Допрете двапати за уредување."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Допрете двапати за додавање."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Место <xliff:g id="POSITION">%1$d</xliff:g>. Допрете двапати за избирање."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Преместете <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Отстранете <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> е додадена на место <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> е отстранета"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> е преместена на место <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Додајте <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицијата <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Преместете <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицијата <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Уредник за брзи поставки."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Известување од <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Апликацијата можеби нема да работи во поделен екран."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Одете на прелистувач"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобилен интернет"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi е исклучено"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth е исклучен"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"„Не вознемирувај“ е исклучено"</string>
diff --git a/packages/SystemUI/res/values-mk/strings_car.xml b/packages/SystemUI/res/values-mk/strings_car.xml
index 0ac6cd3..8372fb5 100644
--- a/packages/SystemUI/res/values-mk/strings_car.xml
+++ b/packages/SystemUI/res/values-mk/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Гостин"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Гостин"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Додај корисник"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Нов корисник"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Кога додавате нов корисник, тоа лице треба да го постави својот простор."</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 9c18a22..507cbbf 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"അറിയിപ്പുകൾ"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ബാറ്ററി ഉടൻ തീർന്നേക്കാം"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ശേഷിക്കുന്നു"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> അവശേഷിക്കുന്നു, ഉപയോഗം അടിസ്ഥാനമാക്കി ഏകദേശം <xliff:g id="TIME">%s</xliff:g> ശേഷിക്കുന്നു"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> അവശേഷിക്കുന്നു, ഏകദേശം <xliff:g id="TIME">%s</xliff:g> ശേഷിക്കുന്നു"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> അവശേഷിക്കുന്നു, ഉപയോഗം അടിസ്ഥാനമാക്കി ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> അവശേഷിക്കുന്നു, ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ശേഷിക്കുന്നു. ബാറ്ററി ലാഭിക്കൽ ഓണാണ്."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB വഴി ചാർജ് ചെയ്യാനാകില്ല. നിങ്ങളുടെ ഉകരണത്തിനൊപ്പം ലഭിച്ച ചാർജർ ഉപയോഗിക്കുക."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB വഴി ചാർജ് ചെയ്യാനാകില്ല"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"ലൊക്കേഷൻ അഭ്യർത്ഥനകൾ സജീവമാണ്"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"എല്ലാ വിവരങ്ങളും മായ്‌ക്കുക."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">ഉള്ളിൽ <xliff:g id="NUMBER_1">%s</xliff:g> അറിയിപ്പുകൾ കൂടിയുണ്ട്.</item>
       <item quantity="one">ഉള്ളിൽ <xliff:g id="NUMBER_0">%s</xliff:g> അറിയിപ്പ് കൂടിയുണ്ട്.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"പൂർണ്ണ\nനിശബ്‌ദത"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"മുൻഗണന\nമാത്രം"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"അലാറങ്ങൾ\nമാത്രം"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു (പൂർണ്ണമാകാൻ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു (പൂർണ്ണമാകാൻ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു (പൂർണ്ണമാകാൻ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു (പൂർണ്ണമാകാൻ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു (പൂർണ്ണമാകാൻ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു (പൂർണ്ണമാകാൻ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ഉപയോക്താവ് മാറുക"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ഉപയോക്താവിനെ മാറ്റുക, <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> എന്നയാളാണ് നിലവിലുള്ള ഉപയോക്താവ്"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"നിലവിലെ ഉപയോക്താവ് <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ഉപയോക്താവിനെ ലോഗൗട്ട് ചെയ്യുക"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"പുതിയ ഉപയോക്താവിനെ ചേർക്കണോ?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"നിങ്ങൾ ഒരു പുതിയ ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തിക്ക് അവരുടെ ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്.\n\nമറ്റ് എല്ലാ ഉപയോക്താക്കൾക്കുമായി ഏതൊരു ഉപയോക്താവിനും അപ്ലിക്കേഷനുകൾ അപ്‌ഡേറ്റ് ചെയ്യാനാവും."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"ഉപയോക്താവിനെ ഇല്ലാതാക്കണോ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"ഈ ഉപയോക്താവിന്റെ എല്ലാ ആപ്സും ഡാറ്റയും ഇല്ലാതാക്കും."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"നീക്കംചെയ്യുക"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"ഇടതുവശത്തെ ചിഹ്നം"</string>
     <string name="right_icon" msgid="3952104823293824311">"വലതുവശത്തെ ചിഹ്നം"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ടൈലുകൾ ചേർക്കാൻ ക്ലിക്ക് ചെയ്ത് ഇഴയ്‌ക്കുക"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"നീക്കംചെയ്യുന്നതിന് ഇവിടെ വലിച്ചിടുക"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"നിങ്ങൾക്ക് ചുരുങ്ങിയത് 6 ടൈലുകൾ വേണം"</string>
     <string name="qs_edit" msgid="2232596095725105230">"എഡിറ്റുചെയ്യുക"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"താഴെ പൂർണ്ണ സ്ക്രീൻ"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"സ്ഥാനം <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. എഡിറ്റുചെയ്യുന്നതിന് രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ചേർക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"സ്ഥാനം <xliff:g id="POSITION">%1$d</xliff:g>. തിരഞ്ഞെടുക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കുക"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കംചെയ്യുക"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"സ്ഥാനം <xliff:g id="POSITION">%2$d</xliff:g>-ലേക്ക് <xliff:g id="TILE_NAME">%1$s</xliff:g> ചേർക്കുന്നു"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കംചെയ്യുന്നു"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"സ്ഥാനം <xliff:g id="POSITION">%2$d</xliff:g>-ലേക്ക് <xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കി"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="POSITION">%2$d</xliff:g> സ്ഥാനത്തേയ്ക്ക് <xliff:g id="TILE_NAME">%1$s</xliff:g> ചേർക്കുക"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="POSITION">%2$d</xliff:g> സ്ഥാനത്തേയ്ക്ക് <xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കുക"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ദ്രുത ക്രമീകരണ എഡിറ്റർ."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> അറിയിപ്പ്: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"സ്പ്ലിറ്റ്-സ്ക്രീനിനൊപ്പം ആപ്പ് പ്രവർത്തിച്ചേക്കില്ല."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ബ്രൗസറിലേക്ക് പോവുക"</string>
     <string name="mobile_data" msgid="7094582042819250762">"മൊബൈൽ ഡാറ്റ"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"വൈഫൈ ഓഫാണ്"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ഓഫാണ്"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\'ശല്യപ്പെടുത്തരുത്\' ഓഫാണ്"</string>
diff --git a/packages/SystemUI/res/values-ml/strings_car.xml b/packages/SystemUI/res/values-ml/strings_car.xml
index e83baf1..26afb0d 100644
--- a/packages/SystemUI/res/values-ml/strings_car.xml
+++ b/packages/SystemUI/res/values-ml/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"അതിഥി"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"അതിഥി"</string>
     <string name="car_add_user" msgid="5245196248349230898">"ഉപയോക്താവിനെ ചേര്‍ക്കുക"</string>
     <string name="car_new_user" msgid="8142927244990323906">"പുതിയ ഉപയോക്താവ്"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"നിങ്ങളൊരു പുതിയ ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തി സ്വന്തം ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്."</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index fb26e81..8e27efe 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -32,8 +32,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Мэдэгдэл"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Батaрей удахгүй дуусaж болзошгүй"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн байна. Таны хэрэглээнд тулгуурлан ойролцоогоор <xliff:g id="TIME">%s</xliff:g>-н хугацаа үлдсэн"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн байна. Ойролцоогоор <xliff:g id="TIME">%s</xliff:g>-н хугацаа үлдсэн"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> үлдсэн байна. Таны хэрэглээнд тулгуурлан ойролцоогоор <xliff:g id="TIME">%2$s</xliff:g>-н хугацаа үлдсэн"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> үлдсэн байна. Ойролцоогоор <xliff:g id="TIME">%2$s</xliff:g>-н хугацаа үлдсэн"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн. Тэжээл хэмнэгч асаалттай байна."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB-р цэнэглэх боломжгүй байна. Төхөөрөмждөө дагалдаж ирсэн цэнэглэгчийг ашиглана уу."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB-р цэнэглэх боломжгүй байна"</string>
@@ -255,7 +255,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Байршлын хүсэлтүүд идэвхтэй"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Бүх мэдэгдлийг цэвэрлэх."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">дотор бусад <xliff:g id="NUMBER_1">%s</xliff:g> мэдэгдэл байна.</item>
       <item quantity="one">дотор бусад <xliff:g id="NUMBER_0">%s</xliff:g> мэдэгдэл байна.</item>
@@ -397,9 +397,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Дуугүй\nболгох"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Зөвхөн\nхамгийн чухлыг"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Зөвхөн\nсэрүүлэг"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> шаардлагатай)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Хурдан цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> шаардлагатай)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Удаан цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> шаардлагатай)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> шаардлагатай)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Хурдан цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> шаардлагатай)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Удаан цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> шаардлагатай)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Хэрэглэгчийг сэлгэх"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Хэрэглэгчийг сэлгэх, одоогийн хэрэглэгч <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Одоогийн хэрэглэгч <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -424,6 +424,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ХЭРЭГЛЭГЧЭЭС ГАРАХ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Шинэ хэрэглэгч нэмэх үү?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Та шинэ хэрэглэгч нэмбэл тухайн хүн өөрийн профайлыг тохируулах шаардлагатай.\n\nАль ч хэрэглэгч бүх хэрэглэгчийн апп-уудыг шинэчлэх боломжтой."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Хэрэглэгчийг устгах уу?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Энэ хэрэглэгчийн бүх апп болон мэдээлэл устах болно."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Арилгах"</string>
@@ -727,6 +730,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Зүүн дүрс тэмдэг"</string>
     <string name="right_icon" msgid="3952104823293824311">"Баруун дүрс тэмдэг"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Хавтанд нэмэхийн тулд дараад чирэх"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Устгахын тулд энд зөөнө үү"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Танд хамгийн багадаа 6 хавтан шаардлагатай"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Засах"</string>
@@ -755,12 +760,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Доод бүтэн дэлгэц"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Байршил <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Засахын тулд 2 удаа дарна уу."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Нэмэхийн тулд 2 удаа дарна уу."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Албан тушаал <xliff:g id="POSITION">%1$d</xliff:g>. Сонгохын тулд 2 удаа дарна уу."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г зөөх"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г устгах"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г <xliff:g id="POSITION">%2$d</xliff:g> байршилд нэмсэн"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г устгасан"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г <xliff:g id="POSITION">%2$d</xliff:g> байршилд зөөсөн"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г <xliff:g id="POSITION">%2$d</xliff:g> байрлалд нэмэх"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г байрлал <xliff:g id="POSITION">%2$d</xliff:g> руу зөөх"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Түргэн тохиргоо засварлагч."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> мэдэгдэл: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Апп хуваагдсан дэлгэцэд ажиллахгүй."</string>
@@ -821,7 +824,7 @@
     <string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Хөтчид очих"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобайл дата"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi унтраалттай байна"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth унтраалттай байна"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Бүү саад бол горим унтраалттай байна"</string>
diff --git a/packages/SystemUI/res/values-mn/strings_car.xml b/packages/SystemUI/res/values-mn/strings_car.xml
index 01a92e7..5bc1f57 100644
--- a/packages/SystemUI/res/values-mn/strings_car.xml
+++ b/packages/SystemUI/res/values-mn/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Зочин"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Зочин"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Хэрэглэгч нэмэх"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Шинэ хэрэглэгч"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Таныг шинэ хэрэглэгч нэмэх үед тухайн хэрэглэгч хувийн орон зайгаа тохируулах шаардлагатай."</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 958a877..1c16dc2 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचना"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"बॅटरी लवकर संपू शकते"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाकी, तुमच्या वापरावर आधारित सुमारे <xliff:g id="TIME">%s</xliff:g> शिल्लक"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाकी, सुमारे <xliff:g id="TIME">%s</xliff:g> शिल्लक"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> बाकी, तुमच्या वापरावर आधारित सुमारे <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> बाकी, सुमारे <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक. बॅटरी सेव्‍हर चालू आहे."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB द्वारे चार्ज करू शकत नाही. तुमच्या डिव्हाइससह आलेल्‍या चार्जरचा वापर करा."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB द्वारे चार्ज होऊ शकत नाही"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"स्थान विनंत्या सक्रिय"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"सर्व सूचना साफ करा."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">आत आणखी <xliff:g id="NUMBER_1">%s</xliff:g> सूचना.</item>
       <item quantity="other">आत आणखी <xliff:g id="NUMBER_1">%s</xliff:g> सूचना.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"संपूर्ण\nशांतता"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"केवळ\nप्राधान्य"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"केवळ\nअलार्म"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> मध्ये पूर्ण होईल)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • वेगाने चार्ज होत आहे (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> मध्ये पूर्ण होईल)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • सावकाश चार्ज होत आहे (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> मध्ये पूर्ण होईल)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • वेगाने चार्ज होत आहे (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • सावकाश चार्ज होत आहे (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"वापरकर्ता स्विच करा"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"वापरकर्ता स्विच करा, वर्तमान वापरकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"वर्तमान वापरकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"वापरकर्त्यास लॉगआउट करा"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"नवीन वापरकर्ता जोडायचा?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"तुम्ही एक नवीन वापरकर्ता जोडता तेव्हा, त्या व्यक्तीने त्यांचे स्थान सेट करणे आवश्यक असते.\n\nकोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप्स अपडेट करू शकतो."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"वापरकर्त्यास काढायचे?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"या वापरकर्त्याचे सर्व अॅप्स आणि डेटा काढून टाकला जाईल."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"काढा"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"डावे आयकन"</string>
     <string name="right_icon" msgid="3952104823293824311">"उजवे आयकन"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"टाइल जोडण्यासाठी धरून ठेवा आणि ड्रॅग करा"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"काढण्यासाठी येथे ड्रॅग करा"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"तुम्हाला किमान ६ टाइलची गरज आहे"</string>
     <string name="qs_edit" msgid="2232596095725105230">"संपादित करा"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"तळाशी पूर्ण स्क्रीन"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिती <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. संपादित करण्यासाठी दोनदा टॅप करा."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> . जोडण्यासाठी दोनदा टॅप करा."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिती <xliff:g id="POSITION">%1$d</xliff:g>. निवडण्यासाठी दोनदा टॅप करा."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> हलवा"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> काढा"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ला <xliff:g id="POSITION">%2$d</xliff:g> स्थितीवर जोडले आहे"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ला काढले आहे"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ला <xliff:g id="POSITION">%2$d</xliff:g> स्थितीवर हलविले"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> स्थानावर जोडा"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> स्थानावर हलवा"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"द्रुत सेटिंग्ज संपादक."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"अॅप कदाचित विभाजित-स्क्रीनसह कार्य करू शकत नाही."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ब्राउझरवर जा"</string>
     <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"वाय-फाय बंद आहे"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ब्लूटूथ बंद आहे"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"व्यत्यय आणू नका बंद आहे"</string>
diff --git a/packages/SystemUI/res/values-mr/strings_car.xml b/packages/SystemUI/res/values-mr/strings_car.xml
index 52d6260..f8b9627f 100644
--- a/packages/SystemUI/res/values-mr/strings_car.xml
+++ b/packages/SystemUI/res/values-mr/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"अतिथी"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"अतिथी"</string>
     <string name="car_add_user" msgid="5245196248349230898">"वापरकर्ता जोडा"</string>
     <string name="car_new_user" msgid="8142927244990323906">"नवीन वापरकर्ता"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"तुम्ही नवीन वापरकर्त्याला जोडल्यावर, त्या व्यक्तीने त्यांचे स्थान सेट करणे आवश्यक असते."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 18007c2..947c0ff 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Bateri mungkin kehabisan tidak lama lagi"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> yang tinggal"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Tinggal <xliff:g id="PERCENTAGE">%s</xliff:g>, kira-kira <xliff:g id="TIME">%s</xliff:g> lagi berdasarkan penggunaan anda"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Tinggal <xliff:g id="PERCENTAGE">%s</xliff:g>, kira-kira <xliff:g id="TIME">%s</xliff:g> lagi"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Tinggal <xliff:g id="PERCENTAGE">%1$s</xliff:g>, kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan anda"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Tinggal <xliff:g id="PERCENTAGE">%1$s</xliff:g>, kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Tinggal <xliff:g id="PERCENTAGE">%s</xliff:g>. Penjimat Bateri dihidupkan."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Tidak dapat mengecas melalui USB. Gunakan pengecas yang disertakan dengan peranti anda."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Tidak dapat mengecas melalui USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Permintaan lokasi aktif"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Padamkan semua pemberitahuan."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> lagi pemberitahuan di dalam.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> lagi pemberitahuan di dalam.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Senyap\nsepenuhnya"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Keutamaan\nsahaja"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Penggera\nsahaja"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan cepat (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan perlahan (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> hingga penuh)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan cepat (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> hingga penuh)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan perlahan (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> hingga penuh)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Tukar pengguna"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Tukar pengguna, pengguna semasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Pengguna semasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"LOG KELUAR PENGGUNA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Tambah pengguna baharu?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Apabila anda menambah pengguna baharu, orang itu perlu menyediakan ruang mereka.\n\nMana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Alih keluar pengguna?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Semua apl dan data pengguna ini akan dipadamkan."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Alih keluar"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ikon kiri"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ikon kanan"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Tahan dan seret untuk menambah jubin"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Seret ke sini untuk mengalih keluar"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Anda memerlukan sekurang-kurangnya 6 jubin"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Skrin penuh bawah"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Kedudukan <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dwiketik untuk mengedit."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dwiketik untuk menambah."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Kedudukan <xliff:g id="POSITION">%1$d</xliff:g>. Dwiketik untuk memilih."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Alihkan <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Alih keluar <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ditambahkan pada kedudukan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> dialih keluar"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> dialihkan ke kedudukan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Tambahkan <xliff:g id="TILE_NAME">%1$s</xliff:g> pada kedudukan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Alihkan <xliff:g id="TILE_NAME">%1$s</xliff:g> ke kedudukan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor tetapan pantas."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Pemberitahuan <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Apl mungkin tidak berfungsi dengan skrin pisah."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Pergi ke penyemak imbas"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Data mudah alih"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi dimatikan"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth dimatikan"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Jangan Ganggu dimatikan"</string>
diff --git a/packages/SystemUI/res/values-ms/strings_car.xml b/packages/SystemUI/res/values-ms/strings_car.xml
index 6aaf348..a41eacf 100644
--- a/packages/SystemUI/res/values-ms/strings_car.xml
+++ b/packages/SystemUI/res/values-ms/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Tetamu"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Tetamu"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Tambah Pengguna"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Pengguna Baharu"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Apabila anda menambahkan pengguna baharu, orang itu perlu menyediakan ruang mereka."</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index f1d48b9..8264240 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"အကြောင်းကြားချက်များ။"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"မကြာမီ ဘက်ထရီကုန်သွားနိုင်ပါသည်"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်ရှိနေ"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်သည်၊ သင့်အသုံးပြုမှုအရ <xliff:g id="TIME">%s</xliff:g> ခန့် ကျန်ပါသည်"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်သည်၊ <xliff:g id="TIME">%s</xliff:g> ခန့် ကျန်ပါသည်"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ကျန်သည်၊ သင့်အသုံးပြုမှုအရ <xliff:g id="TIME">%2$s</xliff:g> ခန့် ကျန်ပါသည်"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ကျန်သည်၊ <xliff:g id="TIME">%2$s</xliff:g> ခန့် ကျန်ပါသည်"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်ပါတယ်။ ဘက်ထရီ အားထိန်းကို ဖွင့်ထားသည်။"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB ဖြင့် အားသွင်း၍မရပါ။ သင့်စက်ပစ္စည်းနှင့် အတူပါလာသည့် အားသွင်းကိရိယာကို အသုံးပြုပါ။"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB ဖြင့် အားသွင်း၍မရပါ"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"တည်နေရာပြ တောင်းဆိုချက်များ အသက်ဝင်ရန်"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"သတိပေးချက်အားလုံးအား ဖယ်ရှားခြင်း။"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>၊ +<xliff:g id="OVERFLOW">%s</xliff:g> ခု"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>၊ +<xliff:g id="OVERFLOW">%2$s</xliff:g> ခု"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">အတွင်းတွင် အကြောင်းကြားချက် နောက်ထပ် <xliff:g id="NUMBER_1">%s</xliff:g> ခုရှိပါသည်။</item>
       <item quantity="one">အတွင်းတွင် အကြောင်းကြားချက် နောက်ထပ် <xliff:g id="NUMBER_0">%s</xliff:g> ခုရှိပါသည်။</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"လုံးဝ\nတိတ်ဆိတ်ခြင်း"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ဦးစားပေးမှု\nသာ"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"နှိုးစက်များ\nသာ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် (အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> လို)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အမြန်အားသွင်းနေသည် (အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> လို)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • နှေးကွေးစွာ သွင်းနေသည် (အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> လို)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် (အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လို)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အမြန်အားသွင်းနေသည် (အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လို)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • နှေးကွေးစွာ သွင်းနေသည် (အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လို)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"အသုံးပြုသူကို ပြောင်းရန်၊ လက်ရှိ အသုံးပြုသူ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"လတ်တလော သုံးစွဲသူ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"အသုံးပြုသူ ထွက်လိုက်ပါ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"အသုံးပြုသူအသစ်ကို ထည့်မလား။"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"သင်ထည့်လိုက်သော အသုံးပြုသူအသစ်သည် ၎င်း၏နေရာကို သတ်မှတ်စီစဉ်ရန် လိုအပ်သည်။\n\nမည်သည့်အသုံးပြုသူမဆို ကျန်သူများအားလုံးအတွက် အက်ပ်များကို အပ်ဒိတ်လုပ်ပေးနိုင်သည်။"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"သုံးစွဲသူကိုဖယ်ရှားမည်လား?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"ဤအသုံးပြုသူ၏ ဒေတာနှင့် အပ်ဖ်များအားလုံး ဖျက်လိုက်ပါမည်"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"ဖယ်ရှားရန်"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"လက်ဝဲသင်္ကေတ"</string>
     <string name="right_icon" msgid="3952104823293824311">"လက်ယာသင်္ကေတ"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"အကွက်များထည့်ရန် ဖိဆွဲပါ"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ဖယ်ရှားရန် ဤနေရာသို့ဖိဆွဲပါ"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"အနည်းဆုံး ၆ ကွက် ရှိရမည်"</string>
     <string name="qs_edit" msgid="2232596095725105230">"တည်းဖြတ်ပါ"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"အောက်ခြေ မျက်နှာပြင်အပြည့်"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>၊ <xliff:g id="TILE_NAME">%2$s</xliff:g> နေရာ။ တည်းဖြတ်ရန် နှစ်ချက်တို့ပါ။"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>။ ပေါင်းထည့်ရန် နှစ်ချက်တို့ပါ။"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> နေရာ။ ရွေးချယ်ရန် နှစ်ချက်တို့ပါ။"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကိုရွှေ့ပါ"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကိုဖယ်ရှားပါ"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကို <xliff:g id="POSITION">%2$d</xliff:g> နေရာသို့ ပေါင်းထည့်ထားပါသည်"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကိုဖယ်ရှားလိုက်ပါပြီ"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကို <xliff:g id="POSITION">%2$d</xliff:g> နေရာသို့ ရွှေ့လိုက်ပါပြီ"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကို အနေအထား <xliff:g id="POSITION">%2$d</xliff:g> သို့ ပေါင်းထည့်ရန်"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကို အနေအထား <xliff:g id="POSITION">%2$d</xliff:g> သို့ ရွှေ့ရန်"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"မြန်ဆန်သည့် ဆက်တင်တည်းဖြတ်စနစ်"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> အကြောင်းကြားချက် − <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"မျက်နှာပြင် ခွဲခြမ်းပြသမှုဖြင့် အက်ပ်သည် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ဘရောင်ဇာသို့ သွားပါ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"မိုဘိုင်းဒေတာ"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> —<xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> —<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ကို ပိတ်ထားသည်"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ဘလူးတုသ်ကို ပိတ်ထားသည်"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"မနှောင့်ယှက်ရ\" ကို ပိတ်ထားသည်"</string>
diff --git a/packages/SystemUI/res/values-my/strings_car.xml b/packages/SystemUI/res/values-my/strings_car.xml
index 66ab4af..fdb4998 100644
--- a/packages/SystemUI/res/values-my/strings_car.xml
+++ b/packages/SystemUI/res/values-my/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"ဧည့်သည်"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"ဧည့်သည်"</string>
     <string name="car_add_user" msgid="5245196248349230898">"အသုံးပြုသူ ထည့်ရန်"</string>
     <string name="car_new_user" msgid="8142927244990323906">"အသုံးပြုသူ အသစ်"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"အသုံးပြုသူအသစ် ထည့်သည့်အခါ ထိုသူသည် မိမိ၏ နေရာကို စီစဉ်သတ်မှတ်ရပါမည်။"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index d8d6e47..8c8e905 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varsler"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Batteriet går kanskje snart tomt"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår, omtrent <xliff:g id="TIME">%s</xliff:g> igjen basert på bruken din"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår, omtrent <xliff:g id="TIME">%s</xliff:g> igjen"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> gjenstår, omtrent <xliff:g id="TIME">%2$s</xliff:g> igjen basert på bruken din"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> gjenstår, omtrent <xliff:g id="TIME">%2$s</xliff:g> igjen"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår. Batterisparing er på."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Kan ikke lade via USB. Bruk laderen som fulgte med enheten."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Kan ikke lade via USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aktive stedsforespørsler"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> andre varsler i gruppen.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> annet varsel i gruppen.</item>
@@ -292,7 +292,7 @@
     <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Rotér skjermen automatisk"</string>
     <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"<xliff:g id="ID_1">%s</xliff:g>-modus"</string>
     <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotasjonen er låst"</string>
-    <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"Portrett"</string>
+    <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"Stående"</string>
     <string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"Landskap"</string>
     <string name="quick_settings_ime_label" msgid="7073463064369468429">"Inndatametode"</string>
     <string name="quick_settings_location_label" msgid="5011327048748762257">"Sted"</string>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nstillhet"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Bare\nPrioritet"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Bare\nalarmer"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader raskt (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader sakte (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader raskt (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader sakte (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Bytt bruker"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Bytt bruker, gjeldende bruker er <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Gjeldende bruker: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"LOGG UT BRUKER"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Vil du legge til en ny bruker?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område.\n\nAlle brukere kan oppdatere apper for alle andre brukere."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Vil du fjerne brukeren?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Alle apper og data som tilhører denne brukeren, blir slettet."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Fjern"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Venstre-ikon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Høyre-ikon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Hold og dra for å legge til ruter"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Dra hit for å fjerne"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Du trenger minst seks ruter"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Endre"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Utvid den nederste delen av skjermen til hele skjermen"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Plassering <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dobbelttrykk for å endre."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dobbelttrykk for å legge til."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Plassering <xliff:g id="POSITION">%1$d</xliff:g>. Dobbelttrykk for å velge."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Flytt <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Fjern <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> er lagt til i plassering <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> er fjernet"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> er flyttet til plassering <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Legg til <xliff:g id="TILE_NAME">%1$s</xliff:g> i posisjon <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Flytt <xliff:g id="TILE_NAME">%1$s</xliff:g> til posisjon <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigeringsvindu for hurtiginnstillinger."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g>-varsel: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Det kan hende at appen ikke fungerer med delt skjerm."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Gå til nettleser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er av"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth er av"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Ikke forstyrr er av"</string>
diff --git a/packages/SystemUI/res/values-nb/strings_car.xml b/packages/SystemUI/res/values-nb/strings_car.xml
index f63db63..09593f1 100644
--- a/packages/SystemUI/res/values-nb/strings_car.xml
+++ b/packages/SystemUI/res/values-nb/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gjest"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gjest"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Legg til bruker"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Ny bruker"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område."</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 5cd4325..1b8149e 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाहरू"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ब्याट्री चाँडै सकिन सक्छ"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी, तपाईंको प्रयोगका आधारमा करिब <xliff:g id="TIME">%s</xliff:g> बाँकी छ"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी, करिब <xliff:g id="TIME">%s</xliff:g> बाँकी छ"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> बाँकी, तपाईंको प्रयोगका आधारमा करिब <xliff:g id="TIME">%2$s</xliff:g> बाँकी छ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> बाँकी, करिब <xliff:g id="TIME">%2$s</xliff:g> बाँकी छ"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी। ब्याट्री सेभर सक्रिय छ।"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB मार्फत चार्ज गर्न सकिँदैन। तपाईंको यन्त्रसँगै आएको चार्जर प्रयोग गर्नुहोस्‌।"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB मार्फत चार्ज गर्न सकिँदैन"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"स्थान अनुरोधहरू सक्रिय"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"सबै सूचनाहरू हटाउनुहोस्।"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">भित्र थप <xliff:g id="NUMBER_1">%s</xliff:g> सूचनाहरू छन्।</item>
       <item quantity="one">भित्र थप <xliff:g id="NUMBER_0">%s</xliff:g> सूचना छ।</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"पूरै\nशान्त"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"प्राथमिकता \nमात्र"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"अलार्महरू \nमात्र"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज गरिँदै (चार्ज पूरा हुन <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> बाँकी)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> समय बाँकी)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • मन्द गतिमा चार्ज गरिँदै (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> समय बाँकी)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज गरिँदै (चार्ज पूरा हुन <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> बाँकी)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> समय बाँकी)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • मन्द गतिमा चार्ज गरिँदै (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> समय बाँकी)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"प्रयोगकर्ता फेर्नुहोस्"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"प्रयोगकर्ता, हालको प्रयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> मा स्विच गर्नुहोस्"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"हालको प्रयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"प्रयोगकर्ता लगआउट गर्नुहोस्"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"नयाँ प्रयोगकर्ता थप्ने हो?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"जब तपाईँले नयाँ प्रयोगकर्ता थप्नुहुन्छ, त्यस प्रयोगकर्ताले आफ्नो स्थान स्थापना गर्न पर्ने छ।\n\nकुनै पनि प्रयोगकर्ताले सबै अन्य प्रयोगकर्ताहरूका लागि अनुप्रयोगहरू अद्यावधिक गर्न सक्छन्।"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"प्रयोगकर्ता हटाउन चाहनुहुन्छ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"यस प्रयोगकर्ताको सबै अनुप्रयोगहरू तथा डेटा हटाइनेछ।"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"हटाउनुहोस्"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"बायाँतिर देखाउने आइकन"</string>
     <string name="right_icon" msgid="3952104823293824311">"दायाँतिरको आइकन"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"टाइलहरू थप्न होल्ड गरी ड्र्याग गर्नुहोस्"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"हटाउनका लागि यहाँ तान्नुहोस्"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"तपाईंलाई कम्तीमा ६ वटा टाइलहरू चाहिन्छ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"सम्पादन गर्नुहोस्"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"तल्लो भाग पूर्ण स्क्रिन"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। सम्पादन गर्नाका लागि डबल ट्याप गर्नुहोस्।"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। थप्नका लागि डबल ट्याप गर्नुहोस्।"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>। चयन गर्नाका लागि डबल ट्याप गर्नुहोस्।"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई सार्नुहोस्"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई हटाउनुहोस्"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई स्थिति <xliff:g id="POSITION">%2$d</xliff:g> मा थपियो"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई हटाइयो"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई स्थिति <xliff:g id="POSITION">%2$d</xliff:g> मा सारियो"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई <xliff:g id="POSITION">%2$d</xliff:g> स्थितिमा थप्नुहोस्"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई <xliff:g id="POSITION">%2$d</xliff:g> स्थितिमा सार्नुहोस्"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"द्रुत सेटिङ सम्पादक।"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> को सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"अनुप्रयोगले विभाजित-स्क्रिनमा काम नगर्न सक्छ।"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ब्राउजरमा जानुहोस्"</string>
     <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi‑Fi निष्क्रिय छ"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ब्लुटुथ निष्क्रिय छ"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"बाधा नपुर्‍याउनुहोस् नामक विकल्प निष्क्रिय छ"</string>
diff --git a/packages/SystemUI/res/values-ne/strings_car.xml b/packages/SystemUI/res/values-ne/strings_car.xml
index 1b92f6e..40d6f7d 100644
--- a/packages/SystemUI/res/values-ne/strings_car.xml
+++ b/packages/SystemUI/res/values-ne/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"अतिथि"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"अतिथि"</string>
     <string name="car_add_user" msgid="5245196248349230898">"प्रयोगकर्ता थप्नुहोस्"</string>
     <string name="car_new_user" msgid="8142927244990323906">"नयाँ प्रयोगकर्ता"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"तपाईंले नयाँ प्रयोगकर्ता थप्दा ती व्यक्तिले आफ्नो स्थान सेटअप गर्नु पर्छ।"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
new file mode 100644
index 0000000..45d2185
--- /dev/null
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+
+  NOTE: You might also want to edit: core/res/res/values-night/*.xml
+  -->
+<resources>
+    <!-- The color of the material notification background -->
+    <color name="notification_material_background_color">@*android:color/notification_material_background_color</color>
+
+    <!-- The color of the legacy notifications with customs backgrounds (gingerbread and lollipop.)
+    It's fine to override this color since at that point the shade was dark. -->
+    <color name="notification_legacy_background_color">@*android:color/notification_material_background_color</color>
+
+    <!-- The color of the material notification background when dimmed -->
+    <color name="notification_material_background_dimmed_color">#aa212121</color>
+
+    <!-- The color of the dividing line between grouped notifications while . -->
+    <color name="notification_divider_color">#000</color>
+
+    <!-- The background color of the notification shade -->
+    <color name="notification_shade_background_color">#181818</color>
+
+    <!-- The color of the ripples on the untinted notifications -->
+    <color name="notification_ripple_untinted_color">#30ffffff</color>
+
+    <!-- The "inside" of a notification, reached via longpress -->
+    <color name="notification_guts_bg_color">@*android:color/notification_material_background_color</color>
+
+    <!-- The color of the text inside a notification -->
+    <color name="notification_primary_text_color">@*android:color/notification_primary_text_color_dark</color>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-night/dimens.xml b/packages/SystemUI/res/values-night/dimens.xml
new file mode 100644
index 0000000..4814839
--- /dev/null
+++ b/packages/SystemUI/res/values-night/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+    <!-- The height of the divider between the individual notifications. -->
+    <dimen name="notification_divider_height">1dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index ac5b3e1..61dba4a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meldingen"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Batterij is bijna leeg"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend, nog ongeveer <xliff:g id="TIME">%s</xliff:g> over op basis van je gebruik"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend, nog ongeveer <xliff:g id="TIME">%s</xliff:g> over"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> resterend, nog ongeveer <xliff:g id="TIME">%2$s</xliff:g> over op basis van je gebruik"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> resterend, nog ongeveer <xliff:g id="TIME">%2$s</xliff:g> over"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend. Batterijbesparing is ingeschakeld."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Kan niet opladen via USB. Gebruik de oplader die bij je apparaat is geleverd."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Kan niet opladen via USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Locatieverzoeken actief"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Nog <xliff:g id="NUMBER_1">%s</xliff:g> meldingen in deze groep.</item>
       <item quantity="one">Nog <xliff:g id="NUMBER_0">%s</xliff:g> melding in deze groep.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Totale\nstilte"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Alleen\nprioriteit"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alleen\nalarmen"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Snel opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Langzaam opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Snel opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Langzaam opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Gebruiker wijzigen"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Schakelen tussen gebruikers, huidige gebruiker <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Huidige gebruiker <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"GEBRUIKER UITLOGGEN"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Nieuwe gebruiker toevoegen?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Wanneer u een nieuwe gebruiker toevoegt, moet die persoon zijn eigen profiel instellen.\n\nElke gebruiker kan apps updaten voor alle andere gebruikers."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Gebruiker verwijderen?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Alle apps en gegevens van deze gebruiker worden verwijderd."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Verwijderen"</string>
@@ -531,7 +534,7 @@
     <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string>
     <string name="stream_dtmf" msgid="2447177903892477915">"Frequentie voor tweevoudige multitoon"</string>
     <string name="stream_accessibility" msgid="301136219144385106">"Toegankelijkheid"</string>
-    <string name="ring_toggle_title" msgid="3281244519428819576">"Oproepen"</string>
+    <string name="ring_toggle_title" msgid="3281244519428819576">"Gesprekken"</string>
     <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Bellen"</string>
     <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Trillen"</string>
     <string name="volume_ringer_status_silent" msgid="6896394161022916369">"Dempen"</string>
@@ -546,7 +549,7 @@
     <string name="volume_ringer_hint_unmute" msgid="6602880133293060368">"dempen opheffen"</string>
     <string name="volume_ringer_hint_vibrate" msgid="4036802135666515202">"trillen"</string>
     <string name="volume_dialog_title" msgid="7272969888820035876">"%s-volumeknoppen"</string>
-    <string name="volume_dialog_ringer_guidance_ring" msgid="3360373718388509040">"Oproepen en meldingen gaan over (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
+    <string name="volume_dialog_ringer_guidance_ring" msgid="3360373718388509040">"Gesprekken en meldingen gaan over (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
     <string name="output_title" msgid="5355078100792942802">"Media-uitvoer"</string>
     <string name="output_calls_title" msgid="8717692905017206161">"Uitvoer van telefoongesprek"</string>
     <string name="output_none_found" msgid="5544982839808921091">"Geen apparaten gevonden"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Pictogram links"</string>
     <string name="right_icon" msgid="3952104823293824311">"Pictogram rechts"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Houd vast en sleep om tegels toe te voegen"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Sleep hier naartoe om te verwijderen"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Je hebt minimaal zes tegels nodig"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Bewerken"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Onderste scherm op volledig scherm"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Positie <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dubbeltik om te bewerken."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dubbeltik om toe te voegen."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Positie <xliff:g id="POSITION">%1$d</xliff:g>. Dubbeltik om te selecteren."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verplaatsen"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verwijderen"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is toegevoegd op positie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is verwijderd"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is verplaatst naar positie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> toevoegen aan positie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verplaatsen naar positie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor voor \'Snelle instellingen\'."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g>-melding: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"App werkt mogelijk niet met gesplitst scherm."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"App-info"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Ga naar browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiele data"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wifi is uitgeschakeld"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is uitgeschakeld"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\'Niet storen\' is uitgeschakeld"</string>
diff --git a/packages/SystemUI/res/values-nl/strings_car.xml b/packages/SystemUI/res/values-nl/strings_car.xml
index 6346037..86da413 100644
--- a/packages/SystemUI/res/values-nl/strings_car.xml
+++ b/packages/SystemUI/res/values-nl/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gast"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gast"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Gebruiker toevoegen"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nieuwe gebruiker"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Wanneer je een nieuwe gebruiker toevoegt, moet die persoon zijn eigen profiel instellen."</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 8ac9f5f..7f79090 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ବିଜ୍ଞପ୍ତି"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ଖୁବ୍ ଶୀଘ୍ର ବ୍ୟାଟେରୀ ସରିଯାଇପାରେ"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ବାକି ଅଛି"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ବଳକା ଅଛି, ଆପଣଙ୍କ ବ୍ୟବହାର ଅନୁସାରେ ବ୍ୟାଟେରୀ ପାଖାପାଖି <xliff:g id="TIME">%s</xliff:g> ସମୟ ଚାଲିବ"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ବଳକା ଅଛି, <xliff:g id="TIME">%s</xliff:g> ସମୟ ଚାଲିପାରେ"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ବଳକା ଅଛି, ଆପଣଙ୍କ ବ୍ୟବହାର ଅନୁସାରେ ବ୍ୟାଟେରୀ ପାଖାପାଖି <xliff:g id="TIME">%2$s</xliff:g> ସମୟ ଚାଲିବ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ବଳକା ଅଛି, <xliff:g id="TIME">%2$s</xliff:g> ସମୟ ଚାଲିପାରେ"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ବାକି ଅଛି। ବ୍ୟାଟେରୀ ସେଭର୍‌ ଅନ୍‍ ଅଛି।"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB ଦ୍ଵାରା ଚାର୍ଜ କରିହେବନାହିଁ। ଆପଣଙ୍କ ଡିଭାଇସ୍ ପାଇଁ ଥିବା ଚାର୍ଜର୍‌କୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB ଦ୍ଵାରା ଚାର୍ଜ କରିହେବନାହିଁ"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"ଲୋକେଶନ୍‍ ଅନୁରୋଧ ସକ୍ରିୟ ଅଛି"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ସମସ୍ତ ବିଜ୍ଞପ୍ତି ଖାଲି କରନ୍ତୁ।"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">ଭିତରେ ଆଉ <xliff:g id="NUMBER_1">%s</xliff:g>ଟି ଅଧିକ ବିଜ୍ଞପ୍ତି ରହିଛି।</item>
       <item quantity="one">ଭିତରେ ଆଉ <xliff:g id="NUMBER_0">%s</xliff:g>ଟି ଅଧିକ ବିଜ୍ଞପ୍ତି ରହିଛି।</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"ସମ୍ପୂର୍ଣ୍ଣ\nନୀରବ"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"କେବଳ\nପ୍ରାଥମିକତା"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"କେବଳ\nଆଲାର୍ମ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି (ପୂର୍ଣ୍ଣ ହେବା ପାଇଁ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ବଳକା ଅଛି)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି (ପୂର୍ଣ୍ଣ ହେବା ପାଇଁ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ବଳକା ଅଛି)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି (ପୂର୍ଣ୍ଣ ହେବା ପାଇଁ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ବଳକା ଅଛି)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି (ପୂର୍ଣ୍ଣ ହେବା ପାଇଁ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ବଳକା ଅଛି)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି (ପୂର୍ଣ୍ଣ ହେବା ପାଇଁ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ବଳକା ଅଛି)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି (ପୂର୍ଣ୍ଣ ହେବା ପାଇଁ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ବଳକା ଅଛି)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ୟୁଜର୍‍ ବଦଳାନ୍ତୁ"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ୟୁଜର୍‍ ବଦଳାନ୍ତୁ, ବର୍ତ୍ତମାନର ୟୁଜର୍‍ ହେଉଛନ୍ତି <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"ବର୍ତ୍ତମାନର ୟୁଜର୍‍ ହେଉଛନ୍ତି <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ୟୁଜରଙ୍କୁ ଲଗଆଉଟ୍‍ କରନ୍ତୁ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"ନୂତନ ୟୁଜର୍‍ ଯୋଡ଼ିବେ?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"ଜଣେ ନୂଆ ୟୁଜର୍‍ଙ୍କୁ ଯୋଡ଼ିବାବେଳେ, ସେହି ବ୍ୟକ୍ତିଙ୍କୁ ସ୍ଥାନ ସେଟ୍‍ କରିବାକୁ ପଡ଼ିବ। \n \n ଅନ୍ୟ ସମସ୍ତ ୟୁଜର୍‍ଙ୍କ ପାଇଁ ଯେକୌଣସି ୟୁଜର୍‍ ଆପ୍‌ଗୁଡ଼ିକୁ ଅପଡେଟ୍‌ କରିପାରିବେ।"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"ୟୁଜରଙ୍କୁ ବାହାର କରିବେ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"ଏହି ୟୁଜରଙ୍କ ସମସ୍ତ ଆପ୍‍ ଓ ଡାଟା ଡିଲିଟ୍‍ ହେବ।"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"ବାହାର କରନ୍ତୁ"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"ବାମ ଆଇକନ୍‍"</string>
     <string name="right_icon" msgid="3952104823293824311">"ଡାହାଣ ଆଇକନ୍"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ଟାଇଲ୍ ଯୋଡ଼ିବା ପାଇଁ ଦାବିଧରି ଟାଣନ୍ତୁ"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ବାହାର କରିବାକୁ ଏଠାକୁ ଡ୍ରାଗ୍‍ କରନ୍ତୁ"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"ଆପଣଙ୍କର ଅତିକମରେ 6ଟି ଟାଇଲ୍ ଆବଶ୍ୟକ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ଏଡିଟ୍‌ କରନ୍ତୁ"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"ତଳ ଅଂଶର ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍‍"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ଅବସ୍ଥାନ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। ଏଡିଟ୍ କରିବାକୁ ଡବଲ୍‍-ଟାପ୍‍ କରନ୍ତୁ।"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। ଯୋଡ଼ିବା ପାଇଁ ଡବଲ୍‍-ଟାପ୍‍ କରନ୍ତୁ।"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ଅବସ୍ଥିତି <xliff:g id="POSITION">%1$d</xliff:g>। ଚୟନ କରିବାକୁ ଡବଲ୍‍-ଟାପ୍‍ କରନ୍ତୁ।"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ନିଅନ୍ତୁ"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ବାହାର କରିଦିଅନ୍ତୁ"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g>କୁ ଅବସ୍ଥାନ <xliff:g id="POSITION">%2$d</xliff:g>ରେ ଯୋଡ଼ାଗଲା"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ବାହାର କରିଦିଆଗଲା"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> କୁ ଅବସ୍ଥାନ <xliff:g id="POSITION">%2$d</xliff:g> କୁ ନିଆଗଲା"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="POSITION">%2$d</xliff:g> ଅବସ୍ଥାନକୁ <xliff:g id="TILE_NAME">%1$s</xliff:g> ଯୋଡନ୍ତୁ"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="POSITION">%2$d</xliff:g> ଅବସ୍ଥାନକୁ <xliff:g id="TILE_NAME">%1$s</xliff:g> ଘୁଞ୍ଚାନ୍ତୁ"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ଦ୍ରୁତ ସେଟିଙ୍ଗ ଏଡିଟର୍।"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> ବିଜ୍ଞପ୍ତି: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"ସ୍ପ୍ଲିଟ୍‍-ସ୍କ୍ରୀନରେ ଆପ୍‍ କାମ କରିନପାରେ।"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ଆପ୍‍ ସୂଚନା"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ବ୍ରାଉଜର୍‌କୁ ଯାଆନ୍ତୁ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ମୋବାଇଲ୍‌ ଡାଟା"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ୱାଇ-ଫାଇ ଅଫ୍‍ ଅଛି"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ବ୍ଲୁ-ଟୂଥ୍‍‌ ଅଫ୍ ଅଛି"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ଅଫ୍‍ ଅଛି"</string>
diff --git a/packages/SystemUI/res/values-or/strings_car.xml b/packages/SystemUI/res/values-or/strings_car.xml
index 2dfa37d..a9be075 100644
--- a/packages/SystemUI/res/values-or/strings_car.xml
+++ b/packages/SystemUI/res/values-or/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"ଅତିଥି"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"ଅତିଥି"</string>
     <string name="car_add_user" msgid="5245196248349230898">"ୟୁଜର୍‍ଙ୍କୁ ଯୋଡ଼ନ୍ତୁ"</string>
     <string name="car_new_user" msgid="8142927244990323906">"ନୂଆ ୟୁଜର୍‍"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"ଯେତେବେଳେ ଆପଣ ଜଣେ ନୂଆ ୟୁଜର୍‍ଙ୍କୁ ଯୋଡ଼ିବେ, ସେହି ବ୍ୟକ୍ତିଙ୍କୁ ନିଜ ପାଇଁ ସ୍ପେସ୍‍ ସେଟ‍ଅପ୍ କରିବାକୁ ପଡ଼ିବ।"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index f4be71c..c6ec96e 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"ਬੈਟਰੀ ਛੇਤੀ ਹੀ ਖਤਮ ਹੋ ਸਕਦੀ ਹੈ"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ, ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%s</xliff:g> ਬਾਕੀ"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ, ਲਗਭਗ <xliff:g id="TIME">%s</xliff:g> ਬਾਕੀ"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ਬਾਕੀ, ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ਬਾਕੀ, ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ। ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ।"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB ਰਾਹੀਂ ਚਾਰਜ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। ਆਪਣੇ ਡੀਵਾਈਸ ਦੇ ਨਾਲ ਮਿਲੇ ਚਾਰਜਰ ਦੀ ਵਰਤੋਂ ਕਰੋ।"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB ਰਾਹੀਂ ਚਾਰਜ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸੇਵਾ ਬੇਨਤੀਆਂ ਸਕਿਰਿਆ"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਹਟਾਓ।"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> ਅਤੇ <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ਅਤੇ <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">ਅੰਦਰ <xliff:g id="NUMBER_1">%s</xliff:g> ਹੋਰ ਸੂਚਨਾਵਾਂ।</item>
       <item quantity="other">ਅੰਦਰ <xliff:g id="NUMBER_1">%s</xliff:g> ਹੋਰ ਸੂਚਨਾਵਾਂ।</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"ਕੁਲ \n ਚੁੱਪੀ"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ਕੇਵਲ\nਤਰਜੀਹੀ"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ਕੇਵਲ\nਅਲਾਰਮ"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ਵਿੱਚ ਮੁਕੰਮਲ)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ਵਿੱਚ ਮੁਕੰਮਲ)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ਵਿੱਚ ਮੁਕੰਮਲ)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਮੁਕੰਮਲ)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਮੁਕੰਮਲ)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਮੁਕੰਮਲ)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ਵਰਤੋਂਕਾਰ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ਵਰਤੋਂਕਾਰ, ਵਰਤਮਾਨ ਵਰਤੋਂਕਾਰ ਸਵਿੱਚ ਕਰੋ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"ਮੌਜੂਦਾ ਉਪਭੋਗਤਾ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ਉਪਭੋਗਤਾ ਨੂੰ ਲੌਗ ਆਉਟ ਕਰੋ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"ਕੀ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਨਾ ਹੈ?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣੀ ਜਗ੍ਹਾ ਸਥਾਪਤ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।\n\nਕੋਈ ਵੀ ਵਰਤੋਂਕਾਰ ਹੋਰ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"ਕੀ ਵਰਤੋਂਕਾਰ ਹਟਾਉਣਾ ਹੈ?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"ਇਸ ਉਪਭੋਗਤਾ ਦੇ ਸਾਰੇ ਐਪਸ ਅਤੇ  ਡਾਟਾ  ਮਿਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"ਹਟਾਓ"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"ਖੱਬਾ ਪ੍ਰਤੀਕ"</string>
     <string name="right_icon" msgid="3952104823293824311">"ਸੱਜਾ ਪ੍ਰਤੀਕ"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ਟਾਇਲਾਂ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਫੜ੍ਹ ਕੇ ਰੱਖੋ ਅਤੇ ਘਸੀਟੋ"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ਹਟਾਉਣ ਲਈ ਇੱਥੇ ਘਸੀਟੋ"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"ਤੁਹਾਨੂੰ ਘੱਟੋ-ਘੱਟ 6 ਟਾਇਲਾਂ ਦੀ ਲੋੜ ਪਵੇਗੀ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ਸੰਪਾਦਨ ਕਰੋ"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"ਹੇਠਾਂ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ਸਥਿਤੀ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। ਸੰਪਾਦਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ਸਥਿਤੀ <xliff:g id="POSITION">%1$d</xliff:g>। ਚੁਣਨ ਲਈ ਡਬਲ ਟੈਪ ਕਰੋ।"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ ਤਬਦੀਲ ਕਰੋ"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਹਟਾਓ"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ <xliff:g id="POSITION">%2$d</xliff:g> ਸਥਿਤੀ \'ਤੇ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ ਹਟਾਇਆ ਗਿਆ"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ <xliff:g id="POSITION">%2$d</xliff:g> ਸਥਿਤੀ \'ਤੇ ਤਬਦੀਲ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ <xliff:g id="POSITION">%2$d</xliff:g> ਸਥਾਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ <xliff:g id="POSITION">%2$d</xliff:g> ਸਥਾਨ \'ਤੇ ਲਿਜਾਓ"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਸੰਪਾਦਕ।"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> ਸੂਚਨਾ: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ।"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ਬ੍ਰਾਊਜ਼ਰ \'ਤੇ ਜਾਓ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ਵਾਈ-ਫਾਈ ਬੰਦ ਹੈ"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ਬਲੂਟੁੱਥ ਬੰਦ ਹੈ"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਬੰਦ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings_car.xml b/packages/SystemUI/res/values-pa/strings_car.xml
index 5da8376..dd45851 100644
--- a/packages/SystemUI/res/values-pa/strings_car.xml
+++ b/packages/SystemUI/res/values-pa/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"ਮਹਿਮਾਨ"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"ਮਹਿਮਾਨ"</string>
     <string name="car_add_user" msgid="5245196248349230898">"ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="car_new_user" msgid="8142927244990323906">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣੀ ਜਗ੍ਹਾ ਸੈੱਟਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 6e2f664..33a8117 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -36,8 +36,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Powiadomienia"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Bateria może się wkrótce wyczerpać"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>, jeszcze około <xliff:g id="TIME">%s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>, jeszcze około <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Pozostało <xliff:g id="PERCENTAGE">%1$s</xliff:g>, jeszcze około <xliff:g id="TIME">%2$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Pozostało <xliff:g id="PERCENTAGE">%1$s</xliff:g>, jeszcze około <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>. Oszczędzanie baterii jest włączone."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Nie można naładować przez USB. Użyj ładowarki dostarczonej z urządzeniem."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Nie można naładować przez USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Prośby o lokalizację są aktywne"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="few">Jeszcze <xliff:g id="NUMBER_1">%s</xliff:g> powiadomienia w grupie.</item>
       <item quantity="many">Jeszcze <xliff:g id="NUMBER_1">%s</xliff:g> powiadomień w grupie.</item>
@@ -405,9 +405,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Całkowita\ncisza"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Tylko\npriorytetowe"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Tylko\nalarmy"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do końca)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Szybkie ładowanie (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do końca)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wolne ładowanie (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do końca)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do końca)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Szybkie ładowanie (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do końca)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wolne ładowanie (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do końca)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Przełącz użytkownika"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Przełącz użytkownika. Bieżący użytkownik: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Bieżący użytkownik: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -432,6 +432,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"WYLOGUJ UŻYTKOWNIKA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Dodać nowego użytkownika?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Gdy dodasz nowego użytkownika, musi on skonfigurować swój profil.\n\nKażdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Usunąć użytkownika?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Wszystkie aplikacje i dane tego użytkownika zostaną usunięte."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Usuń"</string>
@@ -611,7 +614,7 @@
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Te powiadomienia zostaną zminimalizowane"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Zwykle odrzucasz te powiadomienia. \nNadal je pokazywać?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Nadal pokazywać te powiadomienia?"</string>
-    <string name="inline_stop_button" msgid="4172980096860941033">"Zatrzymaj powiadomienia"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Zablokuj powiadomienia"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Pokazuj nadal"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimalizuj"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Nadal pokazywać powiadomienia z tej aplikacji?"</string>
@@ -739,6 +742,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Lewa ikona"</string>
     <string name="right_icon" msgid="3952104823293824311">"Prawa ikona"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Przytrzymaj i przeciągnij, by dodać kafelki"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Przeciągnij tutaj, by usunąć"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Potrzebnych jest co najmniej sześć kafelków"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edytuj"</string>
@@ -767,12 +772,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Dolna część ekranu na pełnym ekranie"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Położenie <xliff:g id="POSITION">%1$d</xliff:g>, kafelek <xliff:g id="TILE_NAME">%2$s</xliff:g>. Kliknij dwukrotnie, by edytować."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"Kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g>. Kliknij dwukrotnie, by dodać."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Położenie <xliff:g id="POSITION">%1$d</xliff:g>. Kliknij dwukrotnie, by wybrać."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Przenieś kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Usuń kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> został dodany w położeniu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> został usunięty"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> przeniesiony w położenie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Dodaj kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> w położeniu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Przenieś kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> w położenie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Edytor szybkich ustawień."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Powiadomienie z aplikacji <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacja może nie działać przy podzielonym ekranie."</string>
@@ -833,7 +836,7 @@
     <string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Otwórz przeglądarkę"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Komórkowa transmisja danych"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi jest wyłączone"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth jest wyłączony"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Tryb Nie przeszkadzać jest wyłączony"</string>
diff --git a/packages/SystemUI/res/values-pl/strings_car.xml b/packages/SystemUI/res/values-pl/strings_car.xml
index 807eeab..92c5f05 100644
--- a/packages/SystemUI/res/values-pl/strings_car.xml
+++ b/packages/SystemUI/res/values-pl/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gość"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gość"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Dodaj użytkownika"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nowy użytkownik"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Gdy dodasz nowego użytkownika, musi on skonfigurować swój profil."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index a4f46a0..60825b7 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"A bateria pode acabar em breve"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restantes"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%s</xliff:g> com base no seu uso"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%2$s</xliff:g> com base no seu uso"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s). A Economia de bateria está ativada."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Não é possível carregar via USB. Use o carregador que acompanha o dispositivo."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Não é possível carregar via USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitações de localização ativas"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"Mais <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
       <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silêncio\ntotal"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Somente\nprioridade"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Somente\nalarmes"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até a conclusão)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até a conclusão)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até a conclusão)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> até a conclusão)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> até a conclusão)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> até a conclusão)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Trocar usuário"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Alternar usuário. Usuário atual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Usuário atual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"DESCONECTAR USUÁRIO"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Adicionar novo usuário?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Remover usuário?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Todos os apps e dados deste usuário serão excluídos."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Remover"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ícone à esquerda"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ícone à direita"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Mantenha pressionado e arraste para adicionar blocos"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arraste aqui para remover"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"É preciso haver pelo menos seis blocos"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Parte inferior em tela cheia"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posição <xliff:g id="POSITION">%1$d</xliff:g>. Toque duas vezes para selecionar."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> é adicionado à posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> é removido"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> movido para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Adicionar <xliff:g id="TILE_NAME">%1$s</xliff:g> à posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de configurações rápidas."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"É possível que o app não funcione com o recurso de divisão de tela."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Abrir o navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"O recurso Não perturbe está desativado"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_car.xml b/packages/SystemUI/res/values-pt-rBR/strings_car.xml
index fa23b58..e252e8d 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_car.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Visitante"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Visitante"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Adicionar usuário"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Novo usuário"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Quando você adiciona um usuário novo, essa pessoa precisa configurar o espaço dela."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 58b0315..4be7281 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Pode ficar sem bateria em breve"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Cerca de <xliff:g id="TIME">%s</xliff:g> restante(s) com base na sua utilização."</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Cerca de <xliff:g id="TIME">%s</xliff:g> restante(s)."</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> restante. Cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s) com base na sua utilização."</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> restante. Cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s)."</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. A Poupança de bateria está ativada."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Não é possível carregar através de USB. Utilize o carregador fornecido com o dispositivo."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Não é possível carregar através de USB."</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Pedidos de localização ativos"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
       <item quantity="one">Mais <xliff:g id="NUMBER_0">%s</xliff:g> notificação no grupo.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silêncio\ntotal"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Apenas\nprioridade"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Apenas\nalarmes"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até à carga máxima)…"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar rapid. (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até carga máx.)…"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar lentam. (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até carga máx.)…"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> até à carga máxima)…"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar rapid. (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> até carga máx.)…"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar lentam. (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> até carga máx.)…"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Mudar utilizador"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Mudar de utilizador; o utilizador atual é <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilizador atual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"TERMINAR SESSÃO DO UTILIZADOR"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Adicionar um novo utilizador?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar aplicações para todos os outros utilizadores."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Pretende remover o utilizador?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Serão eliminados todos os dados e todas as aplicações deste utilizador."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Remover"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ícone esquerdo"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ícone direito"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Toque sem soltar e arraste para adicionar mosaicos."</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastar para aqui para remover"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Necessita de, pelo menos, 6 mosaicos."</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Ecrã inferior inteiro"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posição <xliff:g id="POSITION">%1$d</xliff:g>. Toque duas vezes para selecionar."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Remover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> adicionado à posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> removido"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> movido para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Adicionar <xliff:g id="TILE_NAME">%1$s</xliff:g> à posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de definições rápidas."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"A aplicação pode não funcionar com o ecrã dividido."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Info. da aplicação"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Ir para o navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desativado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Não incomodar desativado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_car.xml b/packages/SystemUI/res/values-pt-rPT/strings_car.xml
index 9ea0e7a..386496d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_car.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Convidado"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Convidado"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Adicionar utilizador"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Novo utilizador"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index a4f46a0..60825b7 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"A bateria pode acabar em breve"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restantes"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%s</xliff:g> com base no seu uso"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%2$s</xliff:g> com base no seu uso"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s). A Economia de bateria está ativada."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Não é possível carregar via USB. Use o carregador que acompanha o dispositivo."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Não é possível carregar via USB"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitações de localização ativas"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"Mais <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
       <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silêncio\ntotal"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Somente\nprioridade"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Somente\nalarmes"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até a conclusão)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até a conclusão)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até a conclusão)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> até a conclusão)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga rápida (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> até a conclusão)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> até a conclusão)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Trocar usuário"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Alternar usuário. Usuário atual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Usuário atual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"DESCONECTAR USUÁRIO"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Adicionar novo usuário?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Remover usuário?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Todos os apps e dados deste usuário serão excluídos."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Remover"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ícone à esquerda"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ícone à direita"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Mantenha pressionado e arraste para adicionar blocos"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arraste aqui para remover"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"É preciso haver pelo menos seis blocos"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Parte inferior em tela cheia"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posição <xliff:g id="POSITION">%1$d</xliff:g>. Toque duas vezes para selecionar."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> é adicionado à posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> é removido"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> movido para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Adicionar <xliff:g id="TILE_NAME">%1$s</xliff:g> à posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de configurações rápidas."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"É possível que o app não funcione com o recurso de divisão de tela."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Abrir o navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"O recurso Não perturbe está desativado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings_car.xml b/packages/SystemUI/res/values-pt/strings_car.xml
index fa23b58..e252e8d 100644
--- a/packages/SystemUI/res/values-pt/strings_car.xml
+++ b/packages/SystemUI/res/values-pt/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Visitante"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Visitante"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Adicionar usuário"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Novo usuário"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Quando você adiciona um usuário novo, essa pessoa precisa configurar o espaço dela."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 34baa8a..618c890 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -35,8 +35,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificări"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Este posibil ca bateria să se descarce în curând"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Procent rămas din baterie: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Procent rămas din baterie <xliff:g id="PERCENTAGE">%s</xliff:g>, în baza utilizării, timp aproximativ rămas <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Procent rămas din baterie <xliff:g id="PERCENTAGE">%s</xliff:g>, timp aproximativ rămas <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Procent rămas din baterie <xliff:g id="PERCENTAGE">%1$s</xliff:g>, în baza utilizării, timp aproximativ rămas <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Procent rămas din baterie <xliff:g id="PERCENTAGE">%1$s</xliff:g>, timp aproximativ rămas <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Procent rămas din baterie: <xliff:g id="PERCENTAGE">%s</xliff:g>. Economisirea bateriei este activată."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Nu se poate realiza încărcarea prin USB. Utilizați încărcătorul livrat împreună cu dispozitivul."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Nu se poate realiza încărcarea prin USB"</string>
@@ -260,7 +260,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitări locație active"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ștergeți toate notificările."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="few">Încă <xliff:g id="NUMBER_1">%s</xliff:g> notificări în grup.</item>
       <item quantity="other">Încă <xliff:g id="NUMBER_1">%s</xliff:g> de notificări în grup.</item>
@@ -404,9 +404,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Niciun\nsunet"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Numai\ncu prioritate"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Numai\nalarme"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă rapid (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă lent (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la finalizare)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă rapid (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la finalizare)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă lent (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la finalizare)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Comutați între utilizatori"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Schimbați utilizatorul (utilizator actual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilizator actual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -431,6 +431,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"DECONECTAȚI UTILIZATORUL"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Adăugați un utilizator nou?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul.\n\nOrice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Eliminați utilizatorul?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Toate aplicațiile și datele acestui utilizator vor fi șterse."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Eliminați"</string>
@@ -736,6 +739,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Pictograma din stânga"</string>
     <string name="right_icon" msgid="3952104823293824311">"Pictograma din dreapta"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Țineți apăsat și trageți pentru a adăuga piese"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Trageți aici pentru a elimina"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Aveți nevoie de cel puțin 6 piese"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editați"</string>
@@ -764,12 +769,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Partea de jos pe ecran complet"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Poziția <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Atingeți de două ori pentru a edita."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Atingeți de două ori pentru a adăuga."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Poziția <xliff:g id="POSITION">%1$d</xliff:g>. Atingeți de două ori pentru a selecta."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mutați <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Eliminați <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Caseta <xliff:g id="TILE_NAME">%1$s</xliff:g> este adăugată pe poziția <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Caseta <xliff:g id="TILE_NAME">%1$s</xliff:g> este eliminată"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Caseta <xliff:g id="TILE_NAME">%1$s</xliff:g> a fost mutată pe poziția <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Adăugați <xliff:g id="TILE_NAME">%1$s</xliff:g> pe poziția <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Mutați <xliff:g id="TILE_NAME">%1$s</xliff:g> pe poziția <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editorul pentru setări rapide."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notificare <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Este posibil ca aplicația să nu funcționeze cu ecranul împărțit."</string>
@@ -830,7 +833,7 @@
     <string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Accesați browserul"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Date mobile"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Conexiunea Wi-Fi este dezactivată"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Funcția Bluetooth este dezactivată"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Funcția Nu deranja este dezactivată"</string>
diff --git a/packages/SystemUI/res/values-ro/strings_car.xml b/packages/SystemUI/res/values-ro/strings_car.xml
index c9f0132..ba23df6 100644
--- a/packages/SystemUI/res/values-ro/strings_car.xml
+++ b/packages/SystemUI/res/values-ro/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Invitat"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Invitat"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Adăugați un utilizator"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Utilizator nou"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 186baca..c754c36 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -36,8 +36,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Уведомления"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Батарея скоро разрядится"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Осталось: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Заряд батареи – <xliff:g id="PERCENTAGE">%s</xliff:g>, осталось примерно <xliff:g id="TIME">%s</xliff:g> при текущем уровне использования."</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Заряд батареи – <xliff:g id="PERCENTAGE">%s</xliff:g>, осталось примерно <xliff:g id="TIME">%s</xliff:g>."</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Заряд батареи – <xliff:g id="PERCENTAGE">%1$s</xliff:g>, осталось примерно <xliff:g id="TIME">%2$s</xliff:g> при текущем уровне использования."</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Заряд батареи – <xliff:g id="PERCENTAGE">%1$s</xliff:g>, осталось примерно <xliff:g id="TIME">%2$s</xliff:g>."</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Уровень заряда батареи: <xliff:g id="PERCENTAGE">%s</xliff:g>. Включен режим энергосбережения."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Невозможно выполнить зарядку через USB. Используйте зарядное устройство из комплекта."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Невозможно выполнить зарядку через USB"</string>
@@ -261,7 +261,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Есть активные запросы на определение местоположения"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Ещё <xliff:g id="NUMBER_1">%s</xliff:g> уведомление.</item>
       <item quantity="few">Ещё <xliff:g id="NUMBER_1">%s</xliff:g> уведомления.</item>
@@ -407,9 +407,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Полная\nтишина"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Только\nважные"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Только\nбудильник"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"Идет зарядка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, ещё <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, ещё <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, ещё <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"Идет зарядка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, ещё <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, ещё <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, ещё <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Сменить пользователя."</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Сменить аккаунт. Вход выполнен под именем <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>."</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Выбран аккаунт пользователя <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -434,6 +434,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ВЫЙТИ ОТ ИМЕНИ ПОЛЬЗОВАТЕЛЯ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Добавить пользователя?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Когда вы добавите пользователя, ему потребуется настроить профиль.\n\nЛюбой пользователь устройства может обновлять приложения для всех аккаунтов."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Удалить аккаунт?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Все приложения и данные этого пользователя будут удалены."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Удалить"</string>
@@ -741,6 +744,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Значок \"Влево\""</string>
     <string name="right_icon" msgid="3952104823293824311">"Значок \"Вправо\""</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Перетащите нужные элементы"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Чтобы удалить, перетащите сюда"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Должно остаться не менее 6 элементов"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Изменить"</string>
@@ -769,12 +774,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Нижний во весь экран"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>, кнопка \"<xliff:g id="TILE_NAME">%2$s</xliff:g>\". Чтобы изменить, нажмите дважды."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"Кнопка \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\". Чтобы добавить, нажмите дважды."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>. Чтобы выбрать, нажмите дважды."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Переместить кнопку \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Удалить кнопку \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Кнопка \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" теперь занимает позицию <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Кнопка \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" удалена"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Кнопка \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" теперь занимает позицию <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Добавить значок <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицию <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Переместить значок <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицию <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Редактор быстрых настроек."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Уведомление <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Приложение не поддерживает разделение экрана."</string>
@@ -835,7 +838,7 @@
     <string name="app_info" msgid="6856026610594615344">"О приложении"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Перейти в браузер"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Моб. Интернет"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Модуль Wi-Fi отключен"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Модуль Bluetooth отключен"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Режим \"Не беспокоить\" отключен"</string>
diff --git a/packages/SystemUI/res/values-ru/strings_car.xml b/packages/SystemUI/res/values-ru/strings_car.xml
index 63aefb0..0ccf16e 100644
--- a/packages/SystemUI/res/values-ru/strings_car.xml
+++ b/packages/SystemUI/res/values-ru/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Гость"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Гость"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Добавить пользователя"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Новый пользователь"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Когда вы добавите пользователя, ему потребуется настроить профиль."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index a34cd9d..8ec763d 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"දැනුම්දීම්"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"බැටරිය ඉක්මනින් අවසන් විය හැකිය"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව තිබේ"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව ඇත, ඔබගේ භාවිතය මත පදනම්ව <xliff:g id="TIME">%s</xliff:g> පමණ"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව ඇත, <xliff:g id="TIME">%s</xliff:g> පමණ ඇත"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ඉතිරිව ඇත, ඔබගේ භාවිතය මත පදනම්ව <xliff:g id="TIME">%2$s</xliff:g> පමණ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> ඉතිරිව ඇත, <xliff:g id="TIME">%2$s</xliff:g> පමණ ඇත"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව ඇත. බැටරි සුරැකුම ක්‍රියාත්මකයි."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB හරහා ආරෝපණය කළ නොහැකිය. ඔබේ උපාංගය සමඟ පැමිණි ආරෝපකය භාවිත කරන්න."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB හරහා ආරෝපණය කළ නොහැකිය"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"පිහිටීම් ඉල්ලීම් සක්‍රියයි"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"සියලු දැනුම්දීම් හිස් කරන්න."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">ඇතුළත තව දැනුම්දීම් <xliff:g id="NUMBER_1">%s</xliff:g>ක් ඇත.</item>
       <item quantity="other">ඇතුළත තව දැනුම්දීම් <xliff:g id="NUMBER_1">%s</xliff:g>ක් ඇත.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"සම්පූර්ණ\nනිහඬතාව"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ප්‍රමුඛතා\nපමණි"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ඇඟවීම්\nපමණි"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> සම්පූර්ණ වන තෙක්)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින් (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> සම්පූර්ණ වන තෙක්)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • සෙමින් ආරෝපණය වෙමින් (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> සම්පූර්ණ වන තෙක්)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> සම්පූර්ණ වන තෙක්)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින් (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> සම්පූර්ණ වන තෙක්)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • සෙමින් ආරෝපණය වෙමින් (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> සම්පූර්ණ වන තෙක්)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"පරිශීලක මාරුව"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"පරිශීලකයා මාරු කරන්න,දැන් සිටින පරිශීලකයා <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"වත්මන් පරිශීලක <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"පරිශීලකයා වරන්න"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"අලුත් පරිශීලකයෙක් එක් කරන්නද?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"ඔබ අලුත් පරිශීලකයෙක් එකතු කරන විට, එම පුද්ගලයා ඔහුගේ වැඩ කරන ඉඩ සකසා ගත යුතුය.\n\nසියළුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යාවත්කාලීන කළ හැක."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"පරිශීලකයා ඉවත් කරන්නද?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"මෙම පරිශීලකයාගේ සියලු යෙදුම් සහ දත්ත මකනු ඇත."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"ඉවත් කරන්න"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"වම් නිරූපකය"</string>
     <string name="right_icon" msgid="3952104823293824311">"දකුණු නිරූපකය"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ටයිල් එක් කිරීමට අල්ලාගෙන සිට අදින්න"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ඉවත් කිරීමට මෙතැනට අදින්න"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"ඔබ අවම වශයෙන් ටයිල් 6ක් අවශ්‍ය වේ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"සංස්කරණය"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"පහළ පූර්ණ තිරය"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ස්ථානය <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. වෙනස් කිරීමට දෙවරක් තට්ටු කරන්න."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. එක් කිරීමට දෙවරක් තට්ටු කරන්න."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ස්ථානය <xliff:g id="POSITION">%1$d</xliff:g>. තෝරා ගැනීමට දෙවරක් තට්ටු කරන්න."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ගෙන යන්න"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ඉවත් කරන්න"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> වන ස්ථානයට එක් කරන ලදි"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ඉවත් කරන ලදි"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> වන ස්ථානයට ගෙන යන ලදි"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> තත්ත්වයට <xliff:g id="POSITION">%2$d</xliff:g> එක් කරන්න"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> තත්ත්වයට <xliff:g id="POSITION">%2$d</xliff:g> ගෙන යන්න"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ඉක්මන් සැකසුම් සංස්කාරකය."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> දැනුම්දීම: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"යෙදුම බෙදුම්-තිරය සමග ක්‍රියා නොකළ හැකිය."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
     <string name="go_to_web" msgid="2650669128861626071">"බ්‍රවුසරය වෙත යන්න"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ජංගම දත්ත"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ක්‍රියා විරහිතයි"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"බ්ලූටූත් ක්‍රියා විරහිතයි"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"බාධා නොකරන්න ක්‍රියා විරහිතයි"</string>
diff --git a/packages/SystemUI/res/values-si/strings_car.xml b/packages/SystemUI/res/values-si/strings_car.xml
index 24b8e49..0796d27 100644
--- a/packages/SystemUI/res/values-si/strings_car.xml
+++ b/packages/SystemUI/res/values-si/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"අමුත්තා"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"අමුත්තා"</string>
     <string name="car_add_user" msgid="5245196248349230898">"පරිශීලක එක් කරන්න"</string>
     <string name="car_new_user" msgid="8142927244990323906">"නව පරිශීලක"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"ඔබ අලුත් පරිශීලකයෙක් එක් කරන විට, එම පුද්ගලයාට තමන්ගේ ඉඩ සකසා ගැනීමට අවශ්‍ය වේ."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index e2fa577..de32ae5 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -36,8 +36,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Upozornenia"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Batéria sa môže čoskoro minúť"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g>, približne <xliff:g id="TIME">%s</xliff:g> v závislosti od intenzity využitia"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g>, približne <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Zostáva <xliff:g id="PERCENTAGE">%1$s</xliff:g>, približne <xliff:g id="TIME">%2$s</xliff:g> v závislosti od intenzity využitia"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Zostáva <xliff:g id="PERCENTAGE">%1$s</xliff:g>, približne <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Zostáva: <xliff:g id="PERCENTAGE">%s</xliff:g>. Šetrič batérie je zapnutý."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Nedá sa nabíjať cez USB. Použite nabíjačku dodanú so zariadením."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Nedá sa nabíjať cez USB"</string>
@@ -261,7 +261,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Žiadosti o polohu sú aktívne"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="few">Skupina obsahuje ešte <xliff:g id="NUMBER_1">%s</xliff:g> upozornenia.</item>
       <item quantity="many">Skupina obsahuje ešte <xliff:g id="NUMBER_1">%s</xliff:g> upozornenia.</item>
@@ -407,9 +407,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Úplné\nticho"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Iba\nprioritné"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Iba\nbudíky"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa rýchlo (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa pomaly (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa rýchlo (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa pomaly (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Prepnutie používateľa"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Prepnúť používateľa (súčasný používateľ: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Aktuálny používateľ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -434,6 +434,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ODHLÁSIŤ POUŽÍVATEĽA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Pridať nového používateľa?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor.\n\nKtorýkoľvek používateľ môže aktualizovať aplikácie všetkých ostatných používateľov."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Odstrániť používateľa?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Všetky aplikácie a údaje tohto používateľa budú odstránené."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Odstrániť"</string>
@@ -741,6 +744,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ľavá ikona"</string>
     <string name="right_icon" msgid="3952104823293824311">"Pravá ikona"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Pridržaním a presunutím pridáte dlaždice"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Presunutím sem odstránite"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Potrebujete aspoň šesť dlaždíc"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Upraviť"</string>
@@ -769,12 +774,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Dolná – na celú obrazovku"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozícia <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Upravíte ju dvojitým klepnutím."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Pridáte ju dvojitým klepnutím."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozícia <xliff:g id="POSITION">%1$d</xliff:g>. Vyberiete ju dvojitým klepnutím."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Presunúť dlaždicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Odstrániť dlaždicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Dlaždica <xliff:g id="TILE_NAME">%1$s</xliff:g> bola pridaná na pozíciu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Dlaždica <xliff:g id="TILE_NAME">%1$s</xliff:g> bola odstránená"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Dlaždica <xliff:g id="TILE_NAME">%1$s</xliff:g> bola presunutá na pozíciu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Pridať <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozíciu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Presunúť <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozíciu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor rýchlych nastavení"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Upozornenie <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikácia nemusí fungovať so zapnutou rozdelenou obrazovkou."</string>
@@ -835,7 +838,7 @@
     <string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Otvoriť prehliadač"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilné dáta"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Pripojenie Wi‑Fi je vypnuté"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Rozhranie Bluetooth je vypnuté"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Nastavenie Nerušiť je vypnuté"</string>
diff --git a/packages/SystemUI/res/values-sk/strings_car.xml b/packages/SystemUI/res/values-sk/strings_car.xml
index 550fecd..408c55c 100644
--- a/packages/SystemUI/res/values-sk/strings_car.xml
+++ b/packages/SystemUI/res/values-sk/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Hosť"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Hosť"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Pridať používateľa"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nový používateľ"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 3114f10..11de2d5 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -36,8 +36,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obvestila"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Akumulator bo morda kmalu izpraznjen"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>, glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>, na voljo imate še približno <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Še <xliff:g id="PERCENTAGE">%1$s</xliff:g>, glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Še <xliff:g id="PERCENTAGE">%1$s</xliff:g>, na voljo imate še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>. Vklopljeno je varčevanje z energijo akumulatorja."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Ni mogoče polniti prek USB-ja. Uporabite polnilnik, ki je bil priložen napravi."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Ni mogoče polniti prek USB-ja"</string>
@@ -261,7 +261,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aktivne zahteve za lokacijo"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"in <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Notri je še <xliff:g id="NUMBER_1">%s</xliff:g> obvestilo.</item>
       <item quantity="two">Notri sta še <xliff:g id="NUMBER_1">%s</xliff:g> obvestili.</item>
@@ -407,9 +407,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Popolna\ntišina"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Samo\nprednostno"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Samo\nalarmi"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • hitro polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • počasno polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napolnjenosti)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • hitro polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napolnjenosti)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • počasno polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napolnjenosti)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Preklop med uporabniki"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Preklop med uporabniki, trenutni uporabnik <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Trenutni uporabnik: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -434,6 +434,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ODJAVA UPORABNIKA"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Dodajanje novega uporabnika?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Ko dodate novega uporabnika, mora ta nastaviti svoj prostor.\n\nVsak uporabnik lahko posodobi aplikacije za vse druge uporabnike."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Želite odstraniti uporabnika?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Vse aplikacije in podatki tega uporabnika bodo izbrisani."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Odstrani"</string>
@@ -741,6 +744,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Leva ikona"</string>
     <string name="right_icon" msgid="3952104823293824311">"Desna ikona"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Držite in povlecite, da dodate ploščice"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Če želite odstraniti, povlecite sem"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Imeti morate vsaj 6 ploščic"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
@@ -769,12 +774,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Spodnji v celozaslonski način"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Če želite urediti, se dvakrat dotaknite."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Če želite dodati, se dvakrat dotaknite."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Položaj: <xliff:g id="POSITION">%1$d</xliff:g>. Če želite izbrati, se dvakrat dotaknite."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Premik tega: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Odstranitev tega: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> je dodano na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> je odstranjeno"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> premaknjeno na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Dodaj ploščico <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Premakni ploščico <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Urejevalnik hitrih nastavitev."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Obvestilo za <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija morda ne deluje v načinu razdeljenega zaslona."</string>
@@ -835,7 +838,7 @@
     <string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Odpri brskalnik"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilni podatki"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je izklopljen"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je izklopljen"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Način »ne moti« je izklopljen"</string>
diff --git a/packages/SystemUI/res/values-sl/strings_car.xml b/packages/SystemUI/res/values-sl/strings_car.xml
index c67d11e..1efe69f 100644
--- a/packages/SystemUI/res/values-sl/strings_car.xml
+++ b/packages/SystemUI/res/values-sl/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gost"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gost"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Dodaj uporabnika"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Nov uporabnik"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Ko dodate novega uporabnika, mora ta nastaviti svoj prostor."</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 7ad3fa3..ab7076c 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Njoftimet"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Bateria mund të mbarojë së shpejti"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Ka mbetur edhe <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> të mbetura, rreth <xliff:g id="TIME">%s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> të mbetura, rreth <xliff:g id="TIME">%s</xliff:g> të mbetura"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> të mbetura, rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> të mbetura, rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Ka mbetur edhe <xliff:g id="PERCENTAGE">%s</xliff:g>. \"Kursyesi i baterisë\" është i aktivizuar."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Nuk mund të ngarkohet përmes USB-së. Përdor ngarkuesin që ke marrë me pajisjen."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Nuk mund të ngarkohet përmes USB-së"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Kërkesat për vendodhje janë aktive"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Pastro të gjitha njoftimet."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> njoftime të tjera në brendësi.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> njoftim tjetër në brendësi.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Heshtje\ne plotë"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Vetëm\nme prioritet"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Vetëm\nalarmet"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po ngarkohet (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> derisa të mbushet)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po ngarkohet me shpejtësi (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> derisa të mbushet)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po ngarkohet ngadalë (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> derisa të mbushet)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po ngarkohet (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> derisa të mbushet)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po ngarkohet me shpejtësi (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> derisa të mbushet)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po ngarkohet ngadalë (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> derisa të mbushet)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Ndërro përdorues"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Ndërro përdoruesin. Përdoruesi aktual është <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Përdoruesi aktual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"NXJERRJA E PËRDORUESIT NGA IDENTIFIKIMI"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Të shtohet përdorues i ri?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Kur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet.\n\nÇdo përdorues mund t\'i përditësojë aplikacionet për të gjithë përdoruesit e tjerë."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Të hiqet ky përdorues?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Të gjitha aplikacionet dhe të dhënat e këtij përdoruesi do të fshihen."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Hiqe"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Ikona majtas"</string>
     <string name="right_icon" msgid="3952104823293824311">"Ikona djathtas"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Mbaje të shtypur dhe zvarrit për të shtuar pllakëza"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Zvarrit këtu për ta hequr"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Të duhen të paktën 6 pllakëza"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Redakto"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Ekrani i plotë poshtë"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozicioni <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Trokit dy herë për ta redaktuar."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Trokit dy herë për ta shtuar."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozicioni <xliff:g id="POSITION">%1$d</xliff:g>. Trokit dy herë për ta zgjedhur."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Zhvendose <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Hiqe <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> është shtuar te pozicioni <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> u hoq"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> u zhvendos te pozicioni <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Shto <xliff:g id="TILE_NAME">%1$s</xliff:g> te pozicioni <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Zhvendos <xliff:g id="TILE_NAME">%1$s</xliff:g> te pozicioni <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redaktori i cilësimeve të shpejta."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Njoftim nga <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacioni mund të mos funksionojë me ekranin e ndarë."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Shko te shfletuesi"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Të dhënat celulare"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi është joaktiv"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth-i është joaktiv"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Modaliteti \"Mos shqetëso\" është joaktiv"</string>
diff --git a/packages/SystemUI/res/values-sq/strings_car.xml b/packages/SystemUI/res/values-sq/strings_car.xml
index e622e60..e2bfc00 100644
--- a/packages/SystemUI/res/values-sq/strings_car.xml
+++ b/packages/SystemUI/res/values-sq/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"I ftuar"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"I ftuar"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Shto përdorues"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Përdorues i ri"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index da30392..2dbdc3d 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -35,8 +35,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Обавештења"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Батерија ће се можда ускоро испразнити"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>, на основу коришћења остало је око <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>, остало је око <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Још <xliff:g id="PERCENTAGE">%1$s</xliff:g>, на основу коришћења остало је око <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Још <xliff:g id="PERCENTAGE">%1$s</xliff:g>, остало је око <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>. Уштеда батерије је укључена."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Пуњење преко USB-а није успело. Користите пуњач који сте добили уз уређај."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Пуњење преко USB-а није успело"</string>
@@ -258,7 +258,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Има активних захтева за локацију"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Обриши сва обавештења."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"и још <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, још <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, још <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Још <xliff:g id="NUMBER_1">%s</xliff:g> обавештење у групи.</item>
       <item quantity="few">Још <xliff:g id="NUMBER_1">%s</xliff:g> обавештења у групи.</item>
@@ -375,7 +375,7 @@
     <string name="quick_step_accessibility_toggle_overview" msgid="7171470775439860480">"Укључи/искључи преглед"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Напуњена је"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Пуњење"</string>
-    <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> док се не напуни"</string>
+    <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> до краја пуњења"</string>
     <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Не пуни се"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежа се можда\nнадгледа"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Претрага"</string>
@@ -402,9 +402,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Потпуна\nтишина"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Само\nприорит. прекиди"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Само\nаларми"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се (напуниће се за <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Брзо се пуни (напуниће се за <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Споро се пуни (напуниће се за <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се (напуниће се за <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Брзо се пуни (напуниће се за <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Споро се пуни (напуниће се за <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Замени корисника"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Промените корисника, актуелни корисник је <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Актуелни корисник <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -429,6 +429,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ОДЈАВИ КОРИСНИКА"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Додајете новог корисника?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Када додате новог корисника, та особа треба да подеси свој простор.\n\nСваки корисник може да ажурира апликације за све остале кориснике."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Желите ли да уклоните корисника?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Све апликације и подаци овог корисника ће бити избрисани."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Уклони"</string>
@@ -734,6 +737,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Лева икона"</string>
     <string name="right_icon" msgid="3952104823293824311">"Десна икона"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Задржите и превуците да бисте додали плочице"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Превуците овде да бисте уклонили"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Треба да изаберете најмање 6 плочица"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Измени"</string>
@@ -762,12 +767,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Режим целог екрана за доњи екран"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. позиција, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Двапут додирните да бисте изменили."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Двапут додирните да бисте додали."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. позиција. Двапут додирните да бисте изабрали."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Премести плочицу <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Уклони плочицу <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Плочица <xliff:g id="TILE_NAME">%1$s</xliff:g> је додата на <xliff:g id="POSITION">%2$d</xliff:g>. позицију"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Плочица <xliff:g id="TILE_NAME">%1$s</xliff:g> је уклоњена"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Плочица <xliff:g id="TILE_NAME">%1$s</xliff:g> је премештена на <xliff:g id="POSITION">%2$d</xliff:g>. позицију"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Додајте „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позицију <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Преместите „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позицију <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Уређивач за Брза подешавања."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Обавештења за <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Апликација можда неће функционисати са подељеним екраном."</string>
@@ -828,7 +831,7 @@
     <string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Иди на прегледач"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобилни подаци"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi је искључен"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth је искључен"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Режим Не узнемиравај је искључен"</string>
diff --git a/packages/SystemUI/res/values-sr/strings_car.xml b/packages/SystemUI/res/values-sr/strings_car.xml
index d25f0e7..2ee8b01 100644
--- a/packages/SystemUI/res/values-sr/strings_car.xml
+++ b/packages/SystemUI/res/values-sr/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Гост"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Гост"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Додај корисника"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Нови корисник"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Када додате новог корисника, та особа треба да подеси свој простор."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 0deb4b4..4b05e27 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Aviseringar"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Batteriet kan ta slut snart"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> kvar"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> återstår, cirka <xliff:g id="TIME">%s</xliff:g> kvar utifrån din användning"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> återstår, cirka <xliff:g id="TIME">%s</xliff:g> kvar"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> återstår, cirka <xliff:g id="TIME">%2$s</xliff:g> kvar utifrån din användning"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> återstår, cirka <xliff:g id="TIME">%2$s</xliff:g> kvar"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> kvar. Batterisparläget är aktiverat."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Det går inte att ladda via USB. Använd laddaren som följde med enheten."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Det går inte att ladda via USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Det finns aktiva platsbegäranden"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"<xliff:g id="NUMBER">%s</xliff:g> till"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> fler aviseringar i gruppen.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> till avisering i gruppen.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Helt\ntyst"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Endast\nprioriterade"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Endast\nalarm"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas (fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas snabbt (fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas långsamt (fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas (fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas snabbt (fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas långsamt (fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Byt användare"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Byt användare. Aktuell användare: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Aktuell användare <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"LOGGA UT ANVÄNDAREN"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Lägga till ny användare?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme.\n\nAlla användare kan uppdatera appar för samtliga användares räkning."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Vill du ta bort användaren?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Alla appar och all data som tillhör den här användaren raderas."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Ta bort"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Vänster ikon"</string>
     <string name="right_icon" msgid="3952104823293824311">"Höger ikon"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Lägg till rutor genom att trycka och dra"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Ta bort genom att dra här"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Minst sex rutor måste finnas kvar"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Redigera"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Helskärm på nedre skärm"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tryck snabbt två gånger för att redigera positionen."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lägg till genom att trycka snabbt två gånger."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Välj den genom att trycka snabbt två gånger."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Flytta <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Ta bort <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> har lagts till på position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> har tagits bort"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> har flyttats till position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Lägg till <xliff:g id="TILE_NAME">%1$s</xliff:g> på position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Flytta <xliff:g id="TILE_NAME">%1$s</xliff:g> till position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigerare för snabbinställningar."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g>-avisering: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Appen kanske inte fungerar med delad skärm."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Öppna webbläsaren"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi är inaktiverat"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth är inaktiverat"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Stör ej är inaktiverat"</string>
diff --git a/packages/SystemUI/res/values-sv/strings_car.xml b/packages/SystemUI/res/values-sv/strings_car.xml
index c758641..754d628 100644
--- a/packages/SystemUI/res/values-sv/strings_car.xml
+++ b/packages/SystemUI/res/values-sv/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Gäst"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Gäst"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Lägg till användare"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Ny användare"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index ef90f3e..7cb38b2 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Arifa"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Huenda chaji itaisha hivi karibuni"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Imebakisha <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>, itadumu takribani <xliff:g id="TIME">%s</xliff:g> kulingana na jinsi unavyotumia"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>, itadumu takribani <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Imesalia <xliff:g id="PERCENTAGE">%1$s</xliff:g>, itadumu takribani <xliff:g id="TIME">%2$s</xliff:g> kulingana na jinsi unavyotumia"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Imesalia <xliff:g id="PERCENTAGE">%1$s</xliff:g>, itadumu takribani <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>. Umewasha Kiokoa Betri."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Haiwezi kuchaji kupitia USB. Tumia chaja ambayo ilikuja na kifaa chako."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Haiwezi kuchaji kupitia USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Maombi ya eneo yanatumika"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Futa arifa zote."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Kuna arifa <xliff:g id="NUMBER_1">%s</xliff:g> zaidi katika kikundi.</item>
       <item quantity="one">Kuna arifa <xliff:g id="NUMBER_0">%s</xliff:g> zaidi katika kikundi.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Kimya\nkabisa"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Kipaumbele\npekee"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Kengele\npekee"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ili ijae)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji kwa kasi (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ili ijae)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji pole pole (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ili ijae)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ili ijae)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji kwa kasi (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ili ijae)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji pole pole (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ili ijae)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Badili mtumiaji"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Badili mtumiaji, mtumiaji wa sasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Mtumiaji wa sasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ONDOA MTUMIAJI"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Ungependa kuongeza mtumiaji?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Mtumiaji mpya utakayemwongeza atahitaji kuongeza akaunti yake.\n\nMtumiaji yoyote anaweza kusasisha programu kwa niaba ya wengine wote."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Je, ungependa kuondoa mtumiaji?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Programu na data yote ya mtumiaji huyu itafutwa."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Ondoa"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Aikoni ya kushoto"</string>
     <string name="right_icon" msgid="3952104823293824311">"Aikoni ya kulia"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Shikilia na uburute ili uongeze vigae"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Buruta hapa ili uondoe"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Unahitaji angalau vigae 6"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Badilisha"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Skrini nzima ya chini"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Gusa mara mbili ili ubadilishe."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Gusa mara mbili ili uongeze."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>. Gusa mara mbili ili uchague."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Hamisha <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Ondoa <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> imeongezwa kwenye nafasi ya <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> imeondolewa"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> imehamishiwa kwenye nafasi ya <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Ongeza <xliff:g id="TILE_NAME">%1$s</xliff:g> kwenye nafasi ya <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Sogeza <xliff:g id="TILE_NAME">%1$s</xliff:g> kwenye nafasi ya <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Kihariri cha Mipangilio ya haraka."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Arifa kutoka <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Huenda programu isifanye kazi kwenye skrini inayogawanywa."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Tumia kivinjari"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Data ya simu"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g><xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g><xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi imezimwa"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth imezimwa"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Kipengele cha Usinisumbue kimezimwa"</string>
diff --git a/packages/SystemUI/res/values-sw/strings_car.xml b/packages/SystemUI/res/values-sw/strings_car.xml
index c4b3dcc..0c664ac 100644
--- a/packages/SystemUI/res/values-sw/strings_car.xml
+++ b/packages/SystemUI/res/values-sw/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Mgeni"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Mgeni"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Ongeza Mtumiaji"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Mtumiaji Mpya"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Ukiongeza mtumiaji mpya, ni lazima aweke kikundi chake."</string>
diff --git a/packages/SystemUI/res/values-sw720dp/donottranslate.xml b/packages/SystemUI/res/values-sw720dp/donottranslate.xml
deleted file mode 100644
index 0996067..0000000
--- a/packages/SystemUI/res/values-sw720dp/donottranslate.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2011, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  %1$s is DOW, %2$s is date.
-         We show both (DOW on one line, then the date) but this can be overridden for locales as
-         necessary.
-         -->
-    <string name="status_bar_date_formatter">%1$s\n%2$s</string>
-
-</resources>
-
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index b1eeb41..84041a9 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"அறிவிப்புகள்"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"பேட்டரி விரைவில் தீர்ந்துவிடக்கூடும்"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> உள்ளது"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> பேட்டரி மீதமுள்ளது. உங்கள் உபயோகத்தைப் பொறுத்து, இதைச் சுமார் <xliff:g id="TIME">%s</xliff:g> மணி நேரத்திற்குப் பயன்படுத்தலாம்"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> மீதமுள்ளது, இதைச் சுமார் <xliff:g id="TIME">%s</xliff:g> மணி நேரத்திற்குப் பயன்படுத்தலாம்"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> பேட்டரி மீதமுள்ளது. உங்கள் உபயோகத்தைப் பொறுத்து, இதைச் சுமார் <xliff:g id="TIME">%2$s</xliff:g> மணி நேரத்திற்குப் பயன்படுத்தலாம்"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> மீதமுள்ளது, இதைச் சுமார் <xliff:g id="TIME">%2$s</xliff:g> மணி நேரத்திற்குப் பயன்படுத்தலாம்"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> மீதமுள்ளது. பேட்டரி சேமிப்பான் ஆன் செய்யப்பட்டுள்ளது."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB மூலம், சார்ஜ் செய்ய முடியாது. உங்கள் சாதனத்துடன் வழங்கப்பட்ட சார்ஜரைப் பயன்படுத்தவும்."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB மூலம், சார்ஜ் செய்ய முடியாது"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"இருப்பிடக் கோரிக்கைகள் இயக்கப்பட்டன"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"எல்லா அறிவிப்புகளையும் அழி."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">உள்ளே மேலும் <xliff:g id="NUMBER_1">%s</xliff:g> அறிவிப்புகள் உள்ளன.</item>
       <item quantity="one">உள்ளே மேலும் <xliff:g id="NUMBER_0">%s</xliff:g> அறிவிப்பு உள்ளது.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"அறிவிப்புகள்\nவேண்டாம்"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"முன்னுரிமைகள்\nமட்டும்"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"அலாரங்கள்\nமட்டும்"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது (முழு சார்ஜ்: <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • வேகமாகச் சார்ஜாகிறது (முழு சார்ஜ்: <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • மெதுவாகச் சார்ஜாகிறது (முழு சார்ஜ்: <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது (முழு சார்ஜ்: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • வேகமாகச் சார்ஜாகிறது (முழு சார்ஜ்: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • மெதுவாகச் சார்ஜாகிறது (முழு சார்ஜ்: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"பயனரை மாற்று"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"பயனரை மாற்று, தற்போதைய பயனர் <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"தற்போதைய பயனர்: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"பயனரை வெளியேற்று"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"புதியவரைச் சேர்க்கவா?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"புதிய பயனரைச் சேர்க்கும்போது, அவர் தனக்கான இடத்தை அமைக்க வேண்டும்.\n\nஎந்தவொரு பயனரும், மற்ற எல்லா பயனர்களுக்காகவும் பயன்பாடுகளைப் புதுப்பிக்கலாம்."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"பயனரை அகற்றவா?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"இந்தப் பயனரின் எல்லா பயன்பாடுகளும் தரவும் நீக்கப்படும்."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"அகற்று"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"இடப்புற ஐகான்"</string>
     <string name="right_icon" msgid="3952104823293824311">"வலப்புற ஐகான்"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"கட்டங்களைச் சேர்க்க, அவற்றைப் பிடித்து இழுக்கவும்"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"அகற்ற, இங்கே இழுக்கவும்"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"குறைந்தது 6 கட்டங்கள் தேவை"</string>
     <string name="qs_edit" msgid="2232596095725105230">"மாற்று"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"கீழ்ப்புறம் முழுத் திரை"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"நிலை <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. திருத்த, இருமுறை தட்டவும்."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. சேர்க்க, இருமுறை தட்டவும்."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"நிலை <xliff:g id="POSITION">%1$d</xliff:g>. தேர்ந்தெடுக்க, இருமுறை தட்டவும்."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ஐ நகர்த்தவும்"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ஐ அகற்றவும்"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> நிலை <xliff:g id="POSITION">%2$d</xliff:g> இல் சேர்க்கப்பட்டது"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> அகற்றப்பட்டது"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> நிலை <xliff:g id="POSITION">%2$d</xliff:g>க்கு நகர்த்தப்பட்டது"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"நிலைப்பாடு <xliff:g id="POSITION">%2$d</xliff:g> இல் <xliff:g id="TILE_NAME">%1$s</xliff:g>ஐச் சேர்க்கும்"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"நிலைப்பாடு <xliff:g id="POSITION">%2$d</xliff:g>க்கு <xliff:g id="TILE_NAME">%1$s</xliff:g>ஐ நகர்த்தும்"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"விரைவு அமைப்புகள் திருத்தி."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> அறிவிப்பு: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"திரைப் பிரிப்பில் பயன்பாடு வேலைசெய்யாமல் போகக்கூடும்."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
     <string name="go_to_web" msgid="2650669128861626071">"உலாவிக்குச் செல்"</string>
     <string name="mobile_data" msgid="7094582042819250762">"மொபைல் டேட்டா"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"வைஃபை முடக்கத்தில் உள்ளது"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"புளூடூத் முடக்கத்தில் உள்ளது"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"தொந்தரவு செய்ய வேண்டாம்\" முடக்கத்தில் உள்ளது"</string>
diff --git a/packages/SystemUI/res/values-ta/strings_car.xml b/packages/SystemUI/res/values-ta/strings_car.xml
index 0187c94..226e3d9 100644
--- a/packages/SystemUI/res/values-ta/strings_car.xml
+++ b/packages/SystemUI/res/values-ta/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"விருந்தினர்"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"விருந்தினர்"</string>
     <string name="car_add_user" msgid="5245196248349230898">"பயனரைச் சேர்க்கவும்"</string>
     <string name="car_new_user" msgid="8142927244990323906">"புதிய பயனர்"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"புதிய பயனரைச் சேர்க்கும்போது, அவர் தனக்கான இடத்தை அமைக்க வேண்டும்."</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 20a146e..fc48ac1 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"నోటిఫికేషన్‌లు"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"బ్యాటరీ త్వరలో ఖాళీ అవ్వచ్చు"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది, మీ ఉపయోగం ఆధారంగా దాదాపు <xliff:g id="TIME">%s</xliff:g> ఉండవచ్చు"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది, దాదాపు <xliff:g id="TIME">%s</xliff:g> ఉండవచ్చు"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> మిగిలి ఉంది, మీ ఉపయోగం ఆధారంగా దాదాపు <xliff:g id="TIME">%2$s</xliff:g> ఉండవచ్చు"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> మిగిలి ఉంది, దాదాపు <xliff:g id="TIME">%2$s</xliff:g> ఉండవచ్చు"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది. బ్యాటరీ సేవర్ ఆన్‌లో ఉంది."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB ద్వారా ఛార్జ్ చేయలేరు. మీ పరికరంతో వచ్చిన ఛార్జర్‌ను ఉపయోగించండి."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB ద్వారా ఛార్జ్ చేయలేరు"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"స్థాన అభ్యర్థనలు సక్రియంగా ఉన్నాయి"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"అన్ని నోటిఫికేషన్‌లను క్లియర్ చేయండి."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">లోపల మరో <xliff:g id="NUMBER_1">%s</xliff:g> నోటిఫికేషన్‌లు ఉన్నాయి.</item>
       <item quantity="one">లోపల మరో <xliff:g id="NUMBER_0">%s</xliff:g> నోటిఫికేషన్ ఉంది.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"మొత్తం\nనిశ్శబ్దం"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ప్రాధాన్యమైనవి\nమాత్రమే"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"అలారాలు\nమాత్రమే"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది (పూర్తి కావడానికి <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది (పూర్తి కావడానికి <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది (పూర్తి కావడానికి <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది (పూర్తి కావడానికి <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది (పూర్తి కావడానికి <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది (పూర్తి కావడానికి <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"వినియోగదారుని మార్చు"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"వినియోగదారుని మార్చు, ప్రస్తుత వినియోగదారు <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"ప్రస్తుత వినియోగదారు <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"వినియోగదారుని లాగ్ అవుట్ చేయి"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"కొత్త వినియోగదారుని జోడించాలా?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"మీరు కొత్త వినియోగదారుని జోడించినప్పుడు, ఆ వ్యక్తి తన స్థలాన్ని సెటప్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగతా అందరు వినియోగదారుల కోసం అనువర్తనాలను నవీకరించగలరు."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"వినియోగదారుని తీసివేయాలా?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"ఈ వినియోగదారుకు సంబంధించిన అన్ని అనువర్తనాలు మరియు డేటా తొలగించబడతాయి."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"తీసివేయి"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"ఎడమ వైపు చిహ్నం"</string>
     <string name="right_icon" msgid="3952104823293824311">"కుడివైపు ఉన్న చిహ్నం"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"టైల్‌లను జోడించడం కోసం పట్టుకుని, లాగండి"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"తీసివేయడానికి ఇక్కడికి లాగండి"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"మీ వద్ద కనీసం 6 టైల్‌లు ఉండాలి"</string>
     <string name="qs_edit" msgid="2232596095725105230">"సవరించు"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"దిగువ పూర్తి స్క్రీన్"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. సవరించడానికి రెండుసార్లు నొక్కండి."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. జోడించడానికి రెండుసార్లు నొక్కండి."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>. ఎంచుకోవడానికి రెండుసార్లు నొక్కండి."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ని తరలిస్తుంది"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ని తీసివేస్తుంది"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>వ స్థానానికి జోడించబడింది"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> తీసివేయబడింది"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>వ స్థానానికి తరలించబడింది"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"స్థానం <xliff:g id="POSITION">%2$d</xliff:g>కి <xliff:g id="TILE_NAME">%1$s</xliff:g>ని జోడించండి"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"స్థానం <xliff:g id="POSITION">%2$d</xliff:g>కి <xliff:g id="TILE_NAME">%1$s</xliff:g>ని తరలించండి"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"శీఘ్ర సెట్టింగ్‌ల ఎడిటర్."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> నోటిఫికేషన్: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"స్క్రీన్ విభజనతో యాప్‌ పని చేయకపోవచ్చు."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"యాప్ సమాచారం"</string>
     <string name="go_to_web" msgid="2650669128861626071">"బ్రౌజర్‌కు వెళ్లండి"</string>
     <string name="mobile_data" msgid="7094582042819250762">"మొబైల్ డేటా"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ఆఫ్‌లో ఉంది"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"బ్లూటూత్ ఆఫ్‌లో ఉంది"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"అంతరాయం కలిగించవద్దు ఆఫ్‌లో ఉంది"</string>
diff --git a/packages/SystemUI/res/values-te/strings_car.xml b/packages/SystemUI/res/values-te/strings_car.xml
index 36afe5d..0fc29bc 100644
--- a/packages/SystemUI/res/values-te/strings_car.xml
+++ b/packages/SystemUI/res/values-te/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"అతిథి"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"అతిథి"</string>
     <string name="car_add_user" msgid="5245196248349230898">"వినియోగదారును జోడించండి"</string>
     <string name="car_new_user" msgid="8142927244990323906">"కొత్త వినియోగదారు"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"మీరు కొత్త వినియోగదారును జోడించినప్పుడు, ఆ వ్యక్తి తన స్థలాన్ని సెటప్ చేసుకోవాలి."</string>
diff --git a/packages/SystemUI/res/values-television/styles.xml b/packages/SystemUI/res/values-television/styles.xml
index 53dc4aa..b59f007 100644
--- a/packages/SystemUI/res/values-television/styles.xml
+++ b/packages/SystemUI/res/values-television/styles.xml
@@ -15,5 +15,6 @@
 -->
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Dialog" />
     <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert" />
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 76fae4e..bf61986 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"การแจ้งเตือน"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"แบตเตอรี่อาจหมดเร็วๆ นี้"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"เหลืออีก <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"เหลือ <xliff:g id="PERCENTAGE">%s</xliff:g> หรืออีกราว <xliff:g id="TIME">%s</xliff:g> ขึ้นอยู่กับการใช้งานของคุณ"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"เหลือ <xliff:g id="PERCENTAGE">%s</xliff:g> หรืออีกราว <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"เหลือ <xliff:g id="PERCENTAGE">%1$s</xliff:g> หรืออีกราว <xliff:g id="TIME">%2$s</xliff:g> ขึ้นอยู่กับการใช้งานของคุณ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"เหลือ <xliff:g id="PERCENTAGE">%1$s</xliff:g> หรืออีกราว <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"แบตเตอรี่เหลือ <xliff:g id="PERCENTAGE">%s</xliff:g> เปิดโหมดประหยัดแบตเตอรี่อยู่"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"ชาร์จผ่าน USB ไม่ได้ โปรดใช้ที่ชาร์จที่ให้มาพร้อมกับอุปกรณ์"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"ชาร์จผ่าน USB ไม่ได้"</string>
@@ -57,7 +57,7 @@
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ไหม"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ไหม"</string>
-    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"แอปพลิเคชันที่ติดตั้งใช้กับอุปกรณ์ USB นี้ไม่ได้ เรียนรู้เพิ่มเติมเกี่ยวกับอุปกรณ์เสริมนี้ที่ <xliff:g id="URL">%1$s</xliff:g>"</string>
+    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"แอปพลิเคชันที่ติดตั้งใช้กับอุปกรณ์ USB นี้ไม่ได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับอุปกรณ์เสริมนี้ที่ <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"อุปกรณ์เสริม USB"</string>
     <string name="label_view" msgid="6304565553218192990">"ดู"</string>
     <string name="always_use_device" msgid="4015357883336738417">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> ทุกครั้งเมื่อเชื่อมต่อกับ <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string>
@@ -85,7 +85,7 @@
     <string name="accessibility_back" msgid="567011538994429120">"กลับ"</string>
     <string name="accessibility_home" msgid="8217216074895377641">"หน้าแรก"</string>
     <string name="accessibility_menu" msgid="316839303324695949">"เมนู"</string>
-    <string name="accessibility_accessibility_button" msgid="7601252764577607915">"ความสามารถเข้าถึงได้ง่าย"</string>
+    <string name="accessibility_accessibility_button" msgid="7601252764577607915">"การเข้าถึงพิเศษ"</string>
     <string name="accessibility_rotate_button" msgid="7402949513740253006">"หมุนหน้าจอ"</string>
     <string name="accessibility_recent" msgid="5208608566793607626">"ภาพรวม"</string>
     <string name="accessibility_search_light" msgid="1103867596330271848">"ค้นหา"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"คำขอตำแหน่งที่มีการใช้งาน"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ล้างการแจ้งเตือนทั้งหมด"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">มีการแจ้งเตือนอีก <xliff:g id="NUMBER_1">%s</xliff:g> รายการด้านใน</item>
       <item quantity="one">มีการแจ้งเตือนอีก <xliff:g id="NUMBER_0">%s</xliff:g> รายการด้านใน</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"ปิดเสียง\nทั้งหมด"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"เฉพาะเรื่อง\nสำคัญ"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"เฉพาะปลุก\nเท่านั้น"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ (อีก <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> จะเต็ม)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างเร็ว (อีก <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> จะเต็ม)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างช้าๆ (อีก <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> จะเต็ม)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ (อีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> จะเต็ม)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างเร็ว (อีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> จะเต็ม)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างช้าๆ (อีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> จะเต็ม)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"สลับผู้ใช้"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"เปลี่ยนผู้ใช้จากผู้ใช้ปัจจุบัน <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"ผู้ใช้ปัจจุบัน <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ออกจากระบบผู้ใช้"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"ต้องการเพิ่มผู้ใช้ใหม่ใช่ไหม"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"เมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตนเอง\n\nผู้ใช้ทุกคนสามารถอัปเดตแอปสำหรับผู้ใช้รายอื่นทุกคนได้"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"นำผู้ใช้ออกใช่ไหม"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"แอปและข้อมูลทั้งหมดของผู้ใช้นี้จะถูกลบ"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"นำออก"</string>
@@ -480,7 +483,7 @@
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ใช้ <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> เพื่อจัดการอุปกรณ์"</string>
     <string name="monitoring_description_do_body" msgid="3639594537660975895">"ผู้ดูแลระบบสามารถตรวจสอบและจัดการการตั้งค่า การเข้าถึงของบริษัท แอป ข้อมูลที่เชื่อมโยงกับอุปกรณ์ของคุณ และข้อมูลตำแหน่งของอุปกรณ์"</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
-    <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"เรียนรู้เพิ่มเติม"</string>
+    <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"ดูข้อมูลเพิ่มเติม"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"คุณเชื่อมต่อกับ <xliff:g id="VPN_APP">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ รวมถึงอีเมล แอป และเว็บไซต์ได้"</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"เปิดการตั้งค่า VPN"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"ไอคอนทางซ้าย"</string>
     <string name="right_icon" msgid="3952104823293824311">"ไอคอนทางขวา"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"กดชิ้นส่วนค้างไว้แล้วลากไปเพื่อเพิ่ม"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ลากมาที่นี่เพื่อนำออก"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"คุณต้องมีชิ้นส่วนอย่างน้อย 6 ชิ้น"</string>
     <string name="qs_edit" msgid="2232596095725105230">"แก้ไข"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"เต็มหน้าจอด้านล่าง"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g> <xliff:g id="TILE_NAME">%2$s</xliff:g> แตะ 2 ครั้งเพื่อแก้ไข"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> แตะ 2 ครั้งเพื่อเพิ่ม"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g> แตะ 2 ครั้งเพื่อเลือก"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"ย้าย <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"นำ <xliff:g id="TILE_NAME">%1$s</xliff:g> ออก"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"เพิ่ม <xliff:g id="TILE_NAME">%1$s</xliff:g> ลงในตำแหน่ง <xliff:g id="POSITION">%2$d</xliff:g> แล้ว"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"นำ <xliff:g id="TILE_NAME">%1$s</xliff:g> ออกแล้ว"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"ย้าย <xliff:g id="TILE_NAME">%1$s</xliff:g> ไปยังตำแหน่ง <xliff:g id="POSITION">%2$d</xliff:g> แล้ว"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"เพิ่ม <xliff:g id="TILE_NAME">%1$s</xliff:g> ไปยังตำแหน่ง <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"ย้าย <xliff:g id="TILE_NAME">%1$s</xliff:g> ไปยังตำแหน่ง <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ตัวแก้ไขการตั้งค่าด่วน"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> การแจ้งเตือน: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"แอปอาจใช้ไม่ได้กับโหมดแยกหน้าจอ"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string>
     <string name="go_to_web" msgid="2650669128861626071">"ไปที่เบราว์เซอร์"</string>
     <string name="mobile_data" msgid="7094582042819250762">"เน็ตมือถือ"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ปิดอยู่"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"บลูทูธปิดอยู่"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"ห้ามรบกวน\" ปิดอยู่"</string>
diff --git a/packages/SystemUI/res/values-th/strings_car.xml b/packages/SystemUI/res/values-th/strings_car.xml
index 92cc60b..44b2e62 100644
--- a/packages/SystemUI/res/values-th/strings_car.xml
+++ b/packages/SystemUI/res/values-th/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"ผู้มาเยือน"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"ผู้มาเยือน"</string>
     <string name="car_add_user" msgid="5245196248349230898">"เพิ่มผู้ใช้"</string>
     <string name="car_new_user" msgid="8142927244990323906">"ผู้ใช้ใหม่"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"เมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตนเอง"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 0c1b8a5..fef7632 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Mga Notification"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Malapit nang maubos ang baterya"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira, humigit-kumulang <xliff:g id="TIME">%s</xliff:g> ang natitira batay sa iyong paggamit"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira, humigit-kumulang <xliff:g id="TIME">%s</xliff:g> ang natitira"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> na lang ang natitira, humigit-kumulang <xliff:g id="TIME">%2$s</xliff:g> ang natitira batay sa iyong paggamit"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> na lang ang natitira, humigit-kumulang <xliff:g id="TIME">%2$s</xliff:g> ang natitira"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira. Naka-on ang Pangtipid sa Baterya."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Hindi makapag-charge sa pamamagitan ng USB. Gamitin ang charger na kasama ng iyong device."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Hindi makapag-charge sa pamamagitan ng USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aktibo ang mga kahilingan ng lokasyon"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"I-clear ang lahat ng notification."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">May <xliff:g id="NUMBER_1">%s</xliff:g> pang notification sa loob.</item>
       <item quantity="other">May <xliff:g id="NUMBER_1">%s</xliff:g> pang notification sa loob.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Ganap na\nkatahimikan"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priyoridad\nlang"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Mga alarm\nlang"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hanggang mapuno)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabilis na nagcha-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> na lang)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabagal na nagcha-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> na lang)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> hanggang mapuno)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabilis na nagcha-charge (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabagal na nagcha-charge (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Magpalit ng user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Magpalit ng user, kasalukuyang user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Kasalukuyang user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"I-LOGOUT ANG USER"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Magdagdag ng bagong user?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Kapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo.\n\nAng sinumang user ay maaaring mag-update ng mga app para sa lahat ng iba pang user."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Gusto mo bang alisin ang user?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Made-delete ang lahat ng app at data ng user na ito."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Alisin"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Icon ng kaliwa"</string>
     <string name="right_icon" msgid="3952104823293824311">"Icon ng kanan"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Pindutin nang matagal at i-drag para magdagdag ng mga tile"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"I-drag dito upang alisin"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Kailangan mo ng hindi bababa sa 6 na tile"</string>
     <string name="qs_edit" msgid="2232596095725105230">"I-edit"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"I-full screen ang nasa ibaba"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posisyon <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. I-double tap upang i-edit."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. I-double tap upang idagdag."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posisyon <xliff:g id="POSITION">%1$d</xliff:g>. I-double tap upang piliin."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Ilipat ang <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Alisin ang <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Idinagdag ang <xliff:g id="TILE_NAME">%1$s</xliff:g> sa posisyon <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Inalis ang <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Inilipat ang <xliff:g id="TILE_NAME">%1$s</xliff:g> sa posisyon <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Idagdag ang <xliff:g id="TILE_NAME">%1$s</xliff:g> sa posisyong <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Ilipat ang <xliff:g id="TILE_NAME">%1$s</xliff:g> sa posisyong <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor ng Mga mabilisang setting."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Notification sa <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Maaaring hindi gumana ang app sa split-screen."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Pumunta sa browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Naka-off ang Wi-Fi"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Naka-off ang Bluetooth"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Naka-off ang Huwag Istorbohin"</string>
diff --git a/packages/SystemUI/res/values-tl/strings_car.xml b/packages/SystemUI/res/values-tl/strings_car.xml
index 19e60a5..7458f28 100644
--- a/packages/SystemUI/res/values-tl/strings_car.xml
+++ b/packages/SystemUI/res/values-tl/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Bisita"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Bisita"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Magdagdag ng User"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Bagong User"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo."</string>
diff --git a/packages/SystemUI/res/values-tr/donottranslate.xml b/packages/SystemUI/res/values-tr/donottranslate.xml
deleted file mode 100644
index dcf434d..0000000
--- a/packages/SystemUI/res/values-tr/donottranslate.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%2$s\n%1$s</string>
-
-</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 7abf64f..fd8ab73 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirimler"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Pil kısa süre sonra bitebilir"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> kaldı"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> kaldı (kullanımınıza göre yaklaşık <xliff:g id="TIME">%s</xliff:g>)"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> (yaklaşık <xliff:g id="TIME">%s</xliff:g>) kaldı"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> kaldı (kullanımınıza göre yaklaşık <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> (yaklaşık <xliff:g id="TIME">%2$s</xliff:g>) kaldı"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> kaldı. Pil Tasarrufu açık."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB üzerinden şarj edilemiyor. Cihazınızla birlikte gelen şarj cihazını kullanın."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB ile şarj edilemiyor"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Konum bilgisi istekleri etkin"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Grup içinde <xliff:g id="NUMBER_1">%s</xliff:g> bildirim daha var.</item>
       <item quantity="one">Grup içinde <xliff:g id="NUMBER_0">%s</xliff:g> bildirim daha var.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Tamamen\nsessiz"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Yalnızca\nöncelik"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Yalnızca\nalarmlar"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor (dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hızlı şarj oluyor (dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş şarj oluyor (dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor (dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hızlı şarj oluyor (dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş şarj oluyor (dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Kullanıcı değiştirme"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Kullanıcı değiştir. Geçerli kullanıcı: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Geçerli kullanıcı: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"KULLANICI OTURUMUNU KAPAT"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Yeni kullanıcı eklensin mi?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Yeni bir kullanıcı eklediğinizde, bu kişinin kendi alanını ayarlaması gerekir.\n\nHerhangi bir kullanıcı, diğer tüm kullanıcılar için uygulamaları güncelleyebilir."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Kullanıcı kaldırılsın mı?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Bu kullanıcının tüm uygulamaları ve verileri silinecek."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Kaldır"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Sol simge"</string>
     <string name="right_icon" msgid="3952104823293824311">"Sağ simge"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Blok eklemek için basılı tutup sürükleyin"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Kaldırmak için buraya sürükleyin"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"En az 6 blok gerekiyor"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Düzenle"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Altta tam ekran"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. konum, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Düzenlemek için iki kez dokunun."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Eklemek için iki kez dokunun."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. konum. Seçmek için iki kez dokunun."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> kutusunu taşı"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> kutusunu kaldır"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> kutusu <xliff:g id="POSITION">%2$d</xliff:g>. konuma eklendi"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> kaldırıldı"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>. konumuna taşındı"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="TILE_NAME">%1$s</xliff:g> öğesini <xliff:g id="POSITION">%2$d</xliff:g> konumuna ekle"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> öğesini <xliff:g id="POSITION">%2$d</xliff:g> konumuna taşı"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Hızlı ayar düzenleyicisi."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> bildirimi: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Uygulama bölünmüş ekranda çalışmayabilir."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Tarayıcıya git"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobil veriler"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Kablosuz bağlantı kapalı"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth kapalı"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Rahatsız Etmeyin kapalı"</string>
diff --git a/packages/SystemUI/res/values-tr/strings_car.xml b/packages/SystemUI/res/values-tr/strings_car.xml
index f54498b..1ccb206 100644
--- a/packages/SystemUI/res/values-tr/strings_car.xml
+++ b/packages/SystemUI/res/values-tr/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Misafir"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Misafir"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Kullanıcı Ekle"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Yeni Kullanıcı"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Yeni kullanıcı eklediğinizde, bu kişinin kendi alanını ayarlaması gerekir."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index f9f5ce8..7d61d37 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -36,8 +36,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Сповіщення"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Акумулятор може невдовзі розрядитися"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"На основі використання залишилося <xliff:g id="PERCENTAGE">%s</xliff:g> – близько <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g> – близько <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"На основі використання залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> – близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> – близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>. Увімкнено режим економії заряду акумулятора."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Не вдається зарядити через USB. Використовуйте зарядний пристрій, який входить у комплект пристрою."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Не вдається зарядити через USB"</string>
@@ -261,7 +261,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Запити про місцезнаходження активні"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, + <xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, + <xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one">Ще <xliff:g id="NUMBER_1">%s</xliff:g> сповіщення в групі.</item>
       <item quantity="few">Ще <xliff:g id="NUMBER_1">%s</xliff:g> сповіщення в групі.</item>
@@ -407,9 +407,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Без\nсигналів"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Лише\nприорітетні"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Лише\nсигнали"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до повного)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Швидке заряджання (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до повного)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Повільне заряджання (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до повного)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Швидке заряджання (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Повільне заряджання (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Змінити користувача"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Змінити користувача, поточний користувач – <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Поточний користувач: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -434,6 +434,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ВИЙТИ З ОБЛІКОВОГО ЗАПИСУ"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Додати нового користувача?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Користувач має налаштувати свій профіль після створення.\n\nБудь-який користувач пристрою може оновлювати додатки для решти користувачів."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Видалити користувача?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Усі додатки й дані цього користувача буде видалено."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Видалити"</string>
@@ -741,6 +744,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Значок ліворуч"</string>
     <string name="right_icon" msgid="3952104823293824311">"Значок праворуч"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Натисніть і перетягніть, щоб додати фрагменти"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Перетягніть сюди, щоб видалити"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Потрібно принаймні 6 фрагментів"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Редагувати"</string>
@@ -769,12 +774,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Нижнє вікно на весь екран"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Позиція <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Двічі торкніться, щоб змінити."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Двічі торкніться, щоб додати."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Позиція <xliff:g id="POSITION">%1$d</xliff:g>. Двічі торкніться, щоб вибрати."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Перемістити <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Видалити <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> додано на позицію <xliff:g id="POSITION">%2$d</xliff:g>."</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> видалено"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> переміщено на позицію <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Додати <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицію <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Перемістити <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицію <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Редактор швидких налаштувань."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"Сповіщення <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Додаток може не працювати в режимі розділеного екрана."</string>
@@ -835,7 +838,7 @@
     <string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Веб-переглядач"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобільний трафік"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi вимкнено"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth вимкнено"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Режим \"Не турбувати\" вимкнено"</string>
diff --git a/packages/SystemUI/res/values-uk/strings_car.xml b/packages/SystemUI/res/values-uk/strings_car.xml
index c5e8608..d0f9954 100644
--- a/packages/SystemUI/res/values-uk/strings_car.xml
+++ b/packages/SystemUI/res/values-uk/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Гість"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Гість"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Додати користувача"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Новий користувач"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Коли ви додаєте нового користувача, він має налаштувати свій профіль."</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 0566022..dbdc034 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اطلاعات"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"بیٹری جلد ہی ختم ہو سکتی ہے"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی، آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%s</xliff:g> باقی ہے"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی، تقریباً <xliff:g id="TIME">%s</xliff:g> باقی ہے"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> باقی، آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> باقی، تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے۔ بیٹری سیور آن ہے۔"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"‏USB کے ذریعے چارج نہیں کر سکتے۔ اپنے آلہ کے ساتھ ملنے والے چارجر کا استعمال کریں۔"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"‏USB کے ذریعے چارج نہیں کر سکتے"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"مقام کی درخواستیں فعال ہیں"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"سبھی اطلاعات صاف کریں۔"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"<xliff:g id="NUMBER">%s</xliff:g> +"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>، +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>، +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">اندر <xliff:g id="NUMBER_1">%s</xliff:g> مزید اطلاعات ہیں۔ </item>
       <item quantity="one">اندر <xliff:g id="NUMBER_0">%s</xliff:g> مزید اطلاع ہے۔</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"مکمل\nخاموشی"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"صرف\nترجیحی"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"صرف\nالارمز"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے (مکمل ہونے میں <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> باقی)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • تیزی سے چارج ہو رہا ہے (مکمل ہونے میں <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> باقی)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • آہستہ چارج ہو رہا ہے (مکمل ہونے میں <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> باقی)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے (مکمل ہونے میں <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> باقی)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • تیزی سے چارج ہو رہا ہے (مکمل ہونے میں <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> باقی)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • آہستہ چارج ہو رہا ہے (مکمل ہونے میں <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> باقی)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"صارف سوئچ کریں"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"صارف سوئچ کریں، موجودہ صارف <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"موجودہ صارف <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"صارف لاگ آؤٹ کریں"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"نیا صارف شامل کریں؟"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"جب آپ ایک نیا صارف شامل کرتے ہیں تو اس شخص کو اپنی جگہ کو ترتیب دینے کی ضرورت ہوتی ہے۔\n\nکوئی بھی صارف دیگر سبھی صارفین کیلئے ایپس کو اپ ڈیٹ کر سکتا ہے۔"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"صارف کو ہٹائیں؟"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"اس صارف کی سبھی ایپس اور ڈیٹا حذف کر دیا جائے گا۔"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"ہٹائیں"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"بائیں جانب کا آئیکن"</string>
     <string name="right_icon" msgid="3952104823293824311">"دائيں جانب کا آئيکن"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"ٹائلز شامل کرنے کے لئے پکڑ کر گھسیٹیں"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ہٹانے کیلئے یہاں گھسیٹیں؟"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"آپ کو کم از کم 6 ٹائلز کی ضرورت ہے"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ترمیم کریں"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"نچلی فل اسکرین"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>۔ ترمیم کرنے کیلئے دو بار تھپتھپائیں۔"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>۔ شامل کرنے کیلئے دو بار تھپتھپائیں۔"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g>۔ منتخب کرنے کیلئے دو بار تھپتھپائیں۔"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> کو منتقل کریں"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ہٹائیں"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="POSITION">%2$d</xliff:g> پوزیشن پر <xliff:g id="TILE_NAME">%1$s</xliff:g> شامل ہو گیا ہے"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ہٹا دیا گیا"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="POSITION">%2$d</xliff:g> پوزیشن پر <xliff:g id="TILE_NAME">%1$s</xliff:g> منتقل ہو گیا ہے"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"پوزیشن <xliff:g id="TILE_NAME">%1$s</xliff:g> میں <xliff:g id="POSITION">%2$d</xliff:g> شامل کریں"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="TILE_NAME">%1$s</xliff:g> کو پوزیشن <xliff:g id="POSITION">%2$d</xliff:g> میں منتقل کریں"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"فوری ترتیبات کا ایڈیٹر۔"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> اطلاع: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"ممکن ہے کہ ایپ سپلٹ اسکرین کے ساتھ کام نہ کرے۔"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
     <string name="go_to_web" msgid="2650669128861626071">"براؤزر پر جائیں"</string>
     <string name="mobile_data" msgid="7094582042819250762">"موبائل ڈیٹا"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi آف ہے"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"بلوٹوتھ آف ہے"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\'ڈسٹرب نہ کریں\' آف ہے"</string>
diff --git a/packages/SystemUI/res/values-ur/strings_car.xml b/packages/SystemUI/res/values-ur/strings_car.xml
index eabff5b..557c232 100644
--- a/packages/SystemUI/res/values-ur/strings_car.xml
+++ b/packages/SystemUI/res/values-ur/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"مہمان"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"مہمان"</string>
     <string name="car_add_user" msgid="5245196248349230898">"صارف شامل کریں"</string>
     <string name="car_new_user" msgid="8142927244990323906">"نیا صارف"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"جب آپ ایک نیا صارف شامل کرتے ہیں تو اس شخص کو اپنی جگہ کو ترتیب دینے کی ضرورت ہوتی ہے۔"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 5ce50a3..f4403e7 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Eslatmalar"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Batareya tez orada tugaydi"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> qoldi"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> (joriy holatda taxminan <xliff:g id="TIME">%s</xliff:g> qoldi)"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> (taxminan <xliff:g id="TIME">%s</xliff:g> qoldi)"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> (joriy holatda taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> (taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi)"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> qoldi. Quvvat tejash rejimi yoniq."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"USB orqali quvvatlash imkonsiz. Qurilmangiz bilan kelgan quvvatlash moslamasidan foydalaning."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"USB orqali quvvatlash imkonsiz"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Joylashuv so‘rovlari yoniq"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Barcha eslatmalarni tozalash."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Guruhda yana <xliff:g id="NUMBER_1">%s</xliff:g> ta bildirishnoma.</item>
       <item quantity="one">Guruhda yana <xliff:g id="NUMBER_0">%s</xliff:g> ta bildirishnoma.</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Tinchlik\nsaqlansin"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Faqat\nmuhimlar"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Faqat\nsignallar"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> qoldi)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Tez quvvat olmoqda (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> qoldi)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sekin quvvat olmoqda (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> qoldi)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Tez quvvat olmoqda (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sekin quvvat olmoqda (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Foydalanuvchini almashtirish"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Foydalanuvchini o‘zgartirish. Joriy foydalanuvchi – <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Joriy foydalanuvchi <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"FOYDALANUVCHI NOMIDAN CHIQISH"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Foydalanuvchi qo‘shilsinmi?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Yangi profil qo‘shilgach, uni sozlash lozim.\n\nQurilmaning istalgan foydalanuvchisi ilovalarni barcha hisoblar uchun yangilashi mumkin."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Foydalanuvchi olib tashlansinmi?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Ushbu foydalanuvchining barcha ilovalari va ma’lumotlari o‘chirib tashlanadi."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Olib tashlash"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Chapga belgisi"</string>
     <string name="right_icon" msgid="3952104823293824311">"O‘ngga belgisi"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Keraklisini ushlab torting"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"O‘chirish uchun bu yerga torting"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Kamida 6 ta katakcha lozim"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Tahrirlash"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Pastda to‘liq ekran"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>-joy, “<xliff:g id="TILE_NAME">%2$s</xliff:g>” tugmasi. Tahrirlash uchun ustiga ikki marta bosing."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasi. Qo‘shish uchun ustiga ikki marta bosing."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Joylashuv: <xliff:g id="POSITION">%1$d</xliff:g>. Belgilash uchun ustiga ikki marta bosing."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasini ko‘chirish"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasini o‘chirish"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasi endi <xliff:g id="POSITION">%2$d</xliff:g>-joyni egallamoqda"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasi o‘chirildi"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasi endi <xliff:g id="POSITION">%2$d</xliff:g>-joyni egallanmoqda"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"<xliff:g id="POSITION">%2$d</xliff:g>-joyga buni qo‘shish: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"<xliff:g id="POSITION">%2$d</xliff:g>-joyga buni ko‘chirish: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Tezkor sozlamalar muharriri"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> bildirishnomasi: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Ilova ekranni ikkiga bo‘lish rejimini qo‘llab-quvvatlamaydi."</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Brauzerni ochish"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobil internet"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi o‘chiq"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth o‘chiq"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Bezovta qilinmasin rejimi o‘chiq"</string>
diff --git a/packages/SystemUI/res/values-uz/strings_car.xml b/packages/SystemUI/res/values-uz/strings_car.xml
index 656e7b3..2916a00 100644
--- a/packages/SystemUI/res/values-uz/strings_car.xml
+++ b/packages/SystemUI/res/values-uz/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Mehmon"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Mehmon"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Foydalanuvchi qo‘shish"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Yangi foydalanuvchi"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Yangi profil qo‘shilgach, uni sozlash lozim."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 3f0091f..d8fd0eb 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Thông báo"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Có thể sắp hết pin"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>, còn khoảng <xliff:g id="TIME">%s</xliff:g> dựa trên mức sử dụng của bạn"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>, còn khoảng <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Còn lại <xliff:g id="PERCENTAGE">%1$s</xliff:g>, còn khoảng <xliff:g id="TIME">%2$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Còn lại <xliff:g id="PERCENTAGE">%1$s</xliff:g>, còn khoảng <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>. Trình tiết kiệm pin đang bật."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Không thể sạc qua USB. Hãy sử dụng bộ sạc đi kèm với thiết bị."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Không thể sạc qua USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Yêu cầu về thông tin vị trí đang hoạt động"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">Còn <xliff:g id="NUMBER_1">%s</xliff:g> thông báo nữa bên trong.</item>
       <item quantity="one">Còn <xliff:g id="NUMBER_0">%s</xliff:g> thông báo nữa bên trong.</item>
@@ -329,7 +329,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string>
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="8010579363691405477">"Đang bật…"</string>
-    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="5672131949987422420">"Trình tiết kiệm dữ liệu bật"</string>
+    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="5672131949987422420">"Trình tiết kiệm dữ liệu đang bật"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="2324635800672199428">
       <item quantity="other">%d thiết bị</item>
       <item quantity="one">%d thiết bị</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Hoàn toàn\ntắt tiếng"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Chỉ\nưu tiên"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Chỉ\nbáo thức"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho tới khi đầy)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc nhanh (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho tới khi đầy)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc chậm (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho tới khi đầy)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> cho tới khi đầy)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc nhanh (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> cho tới khi đầy)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc chậm (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> cho tới khi đầy)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Chuyển đổi người dùng"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Chuyển người dùng, người dùng hiện tại <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Người dùng hiện tại <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"ĐĂNG XUẤT NGƯỜI DÙNG"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Thêm người dùng mới?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Khi bạn thêm người dùng mới, người dùng đó cần thiết lập dung lượng lưu trữ của mình.\n\nMọi người dùng đều có thể cập nhật ứng dụng cho tất cả người dùng khác."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Xóa người dùng?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Tất cả các ứng dụng và dữ liệu của người dùng này sẽ bị xóa."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Xóa"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Biểu tượng bên trái"</string>
     <string name="right_icon" msgid="3952104823293824311">"Biểu tượng bên phải"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Giữ và kéo để thêm ô"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Kéo vào đây để xóa"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Bạn cần ít nhất 6 ô"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Chỉnh sửa"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Toàn màn hình phía dưới"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Vị trí <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Nhấn đúp để chỉnh sửa."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Nhấn đúp để thêm."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Vị trí <xliff:g id="POSITION">%1$d</xliff:g>. Nhấn đúp để chọn."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Di chuyển <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Xóa <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> được thêm vào vị trí <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> được di chuyển"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> được di chuyển sang vị trí <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Thêm <xliff:g id="TILE_NAME">%1$s</xliff:g> vào vị trí <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Di chuyển <xliff:g id="TILE_NAME">%1$s</xliff:g> đến vị trí <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Trình chỉnh sửa cài đặt nhanh."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"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="dock_forced_resizable" msgid="5914261505436217520">"Ứng dụng có thể không hoạt động với tính năng chia đôi màn hình."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Đi tới trình duyệt"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dữ liệu di động"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi tắt"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth tắt"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Không làm phiền tắt"</string>
diff --git a/packages/SystemUI/res/values-vi/strings_car.xml b/packages/SystemUI/res/values-vi/strings_car.xml
index 08aece1..f3f8d5f 100644
--- a/packages/SystemUI/res/values-vi/strings_car.xml
+++ b/packages/SystemUI/res/values-vi/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Khách"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Khách"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Thêm người dùng"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Người dùng mới"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Khi bạn thêm một người dùng mới, người đó cần thiết lập không gian của họ."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/donottranslate.xml b/packages/SystemUI/res/values-zh-rCN/donottranslate.xml
deleted file mode 100644
index dcf434d..0000000
--- a/packages/SystemUI/res/values-zh-rCN/donottranslate.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%2$s\n%1$s</string>
-
-</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 12675b0..c7443fe 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"电池电量可能很快就要耗尽"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"剩余电量:<xliff:g id="PERCENTAGE">%s</xliff:g>;根据您的使用情况,大约还可使用 <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"剩余电量:<xliff:g id="PERCENTAGE">%s</xliff:g>;大约还可使用 <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"剩余电量:<xliff:g id="PERCENTAGE">%1$s</xliff:g>;根据您的使用情况,大约还可使用 <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"剩余电量:<xliff:g id="PERCENTAGE">%1$s</xliff:g>;大约还可使用 <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"剩余 <xliff:g id="PERCENTAGE">%s</xliff:g>。省电模式已开启。"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"无法通过 USB 充电。请使用设备随附的充电器。"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"无法通过 USB 充电"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"应用发出了有效位置信息请求"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> (+<xliff:g id="OVERFLOW">%s</xliff:g>)"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (+<xliff:g id="OVERFLOW">%2$s</xliff:g>)"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">此群组内还有 <xliff:g id="NUMBER_1">%s</xliff:g> 条通知。</item>
       <item quantity="one">此群组内还有 <xliff:g id="NUMBER_0">%s</xliff:g> 条通知。</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"完全\n静音"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"仅限\n优先打扰"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"仅限\n闹钟"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电(还需 <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>充满)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在快速充电(还需 <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>充满)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充电(还需 <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>充满)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电(还需 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>充满)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在快速充电(还需 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>充满)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充电(还需 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>充满)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"切换用户"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"切换用户,当前用户为<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"当前用户为<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"退出当前用户"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"要添加新用户吗?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"当您添加新用户时,该用户必须设置自己的空间。\n\n任何用户均可为其他所有用户更新应用。"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"是否移除用户?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"此用户的所有应用和数据均将被删除。"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"移除"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"向左图标"</string>
     <string name="right_icon" msgid="3952104823293824311">"向右图标"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"按住并拖动即可添加图块"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"拖动到此处即可移除"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"您至少需要 6 个图块"</string>
     <string name="qs_edit" msgid="2232596095725105230">"编辑"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"底部全屏"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。点按两次即可修改。"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。点按两次即可添加。"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"位置 <xliff:g id="POSITION">%1$d</xliff:g>。点按两次即可选择。"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"移动<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"移除<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"已将<xliff:g id="TILE_NAME">%1$s</xliff:g>添加到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"已移除<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"已将<xliff:g id="TILE_NAME">%1$s</xliff:g>移至位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"将“<xliff:g id="TILE_NAME">%1$s</xliff:g>”添加到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"将“<xliff:g id="TILE_NAME">%1$s</xliff:g>”移动到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快捷设置编辑器。"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g>通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"应用可能无法在分屏模式下正常运行。"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"应用信息"</string>
     <string name="go_to_web" msgid="2650669128861626071">"转到浏览器"</string>
     <string name="mobile_data" msgid="7094582042819250762">"移动数据"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"WLAN 已关闭"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"蓝牙已关闭"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"“勿扰”模式已关闭"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_car.xml b/packages/SystemUI/res/values-zh-rCN/strings_car.xml
index e29397a..a600429 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings_car.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"访客"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"访客"</string>
     <string name="car_add_user" msgid="5245196248349230898">"添加用户"</string>
     <string name="car_new_user" msgid="8142927244990323906">"新用户"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"当您添加新用户时,该用户必须设置自己的空间。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 8f9b33f..dace26a 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"電池電量可能即將耗盡"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"電量剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,根據您的使用情況,剩餘時間大約 <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"電量剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,剩餘時間大約 <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"電量剩餘 <xliff:g id="PERCENTAGE">%1$s</xliff:g>,根據您的使用情況,剩餘時間大約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"電量剩餘 <xliff:g id="PERCENTAGE">%1$s</xliff:g>,剩餘時間大約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>。省電模式已開啟。"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"無法透過 USB 充電,請使用裝置隨附的充電器。"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"無法透過 USB 充電"</string>
@@ -259,7 +259,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"位置要求啟動中"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> (+<xliff:g id="OVERFLOW">%s</xliff:g> 個)"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (+<xliff:g id="OVERFLOW">%2$s</xliff:g> 個)"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">裡面還有 <xliff:g id="NUMBER_1">%s</xliff:g> 個通知。</item>
       <item quantity="one">裡面還有 <xliff:g id="NUMBER_0">%s</xliff:g> 個通知。</item>
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"完全\n靜音"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"僅限\n優先"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"僅限\n鬧鐘"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充電 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後完成充電)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在快速充電 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後完成充電)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充電 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後完成)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充電 (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後完成充電)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在快速充電 (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後完成充電)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充電 (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後完成)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"切換使用者"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"切換使用者,目前使用者是<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"目前的使用者是 <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -428,6 +428,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"登出使用者"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"新增使用者?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"新增的使用者需要自行設定個人空間。\n\n任何使用者均可為所有其他使用者更新應用程式。"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"移除使用者?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"系統將會刪除這個使用者的所有應用程式和資料。"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"移除"</string>
@@ -731,6 +734,8 @@
     <string name="left_icon" msgid="3096287125959387541">"向左圖示"</string>
     <string name="right_icon" msgid="3952104823293824311">"向右圖示"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"按住並拖曳即可新增圖塊"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"拖曳這裡即可移除"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"您必須至少有 6 個圖塊"</string>
     <string name="qs_edit" msgid="2232596095725105230">"編輯"</string>
@@ -759,12 +764,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"底部全螢幕"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。輕按兩下即可編輯。"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。輕按兩下即可新增。"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"位置 <xliff:g id="POSITION">%1$d</xliff:g>。輕按兩下即可選取。"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"移動 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"移除 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 已新增至位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 已移除"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 已移至位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"將「<xliff:g id="TILE_NAME">%1$s</xliff:g>」加去位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"將「<xliff:g id="TILE_NAME">%1$s</xliff:g>」移去位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快速設定編輯工具。"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> 通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"應用程式可能無法在分割畫面中運作。"</string>
@@ -825,7 +828,7 @@
     <string name="app_info" msgid="6856026610594615344">"應用程式資料"</string>
     <string name="go_to_web" msgid="2650669128861626071">"前往瀏覽器"</string>
     <string name="mobile_data" msgid="7094582042819250762">"流動數據"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"藍牙已關閉"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"「請勿騷擾」已關閉"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_car.xml b/packages/SystemUI/res/values-zh-rHK/strings_car.xml
index b247dd6..7c4bf30 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_car.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"訪客"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"訪客"</string>
     <string name="car_add_user" msgid="5245196248349230898">"新增使用者"</string>
     <string name="car_new_user" msgid="8142927244990323906">"新使用者"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"新增的使用者需要自行設定個人空間。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/donottranslate.xml b/packages/SystemUI/res/values-zh-rTW/donottranslate.xml
deleted file mode 100644
index dcf434d..0000000
--- a/packages/SystemUI/res/values-zh-rTW/donottranslate.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%2$s\n%1$s</string>
-
-</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2672138..c1be1fb 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"電池電力可能很快就會耗盡"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"僅剩 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"電力剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,根據你的使用情形,剩餘時間大約還有 <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"電力剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,剩餘時間大約還有 <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"電力剩餘 <xliff:g id="PERCENTAGE">%1$s</xliff:g>,根據你的使用情形,剩餘時間大約還有 <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"電力剩餘 <xliff:g id="PERCENTAGE">%1$s</xliff:g>,剩餘時間大約還有 <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"僅剩 <xliff:g id="PERCENTAGE">%s</xliff:g>。節約耗電量模式已開啟。"</string>
     <string name="invalid_charger" msgid="2741987096648693172">"無法透過 USB 充電,請使用裝置隨附的充電器。"</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"無法透過 USB 充電"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"有位置資訊要求"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g> (+<xliff:g id="OVERFLOW">%s</xliff:g>)"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (+<xliff:g id="OVERFLOW">%2$s</xliff:g>)"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other">群組中還有 <xliff:g id="NUMBER_1">%s</xliff:g> 則通知。</item>
       <item quantity="one">群組中還有 <xliff:g id="NUMBER_0">%s</xliff:g> 則通知。</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"完全\n靜音"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"僅允許\n優先通知"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"僅允許\n鬧鐘"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後充飽)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後充飽)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後充飽)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 快速充電中 (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"切換使用者"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"切換使用者,目前使用者是<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"目前使用者是「<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>」"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"登出使用者"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"新增使用者?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"新增的使用者需要自行設定個人空間。\n\n任何使用者皆可為其他所有使用者更新應用程式。"</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"要移除使用者嗎?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"系統將刪除這個使用者的所有應用程式和資料。"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"移除"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"向左圖示"</string>
     <string name="right_icon" msgid="3952104823293824311">"向右圖示"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"按住並拖曳即可新增圖塊"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"拖曳到這裡即可移除"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"你至少必須要有 6 個圖塊"</string>
     <string name="qs_edit" msgid="2232596095725105230">"編輯"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"以全螢幕顯示底部畫面"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。輕觸兩下即可編輯。"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。輕觸兩下即可新增。"</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"位置 <xliff:g id="POSITION">%1$d</xliff:g>。輕觸兩下即可選取。"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"移動 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"移除 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"已將 <xliff:g id="TILE_NAME">%1$s</xliff:g> 新增到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"已移除 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"已將 <xliff:g id="TILE_NAME">%1$s</xliff:g> 移到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"將 <xliff:g id="TILE_NAME">%1$s</xliff:g> 新增到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"將 <xliff:g id="TILE_NAME">%1$s</xliff:g> 移到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快速設定編輯器。"</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> 通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"應用程式可能無法在分割畫面中運作。"</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string>
     <string name="go_to_web" msgid="2650669128861626071">"前往瀏覽器"</string>
     <string name="mobile_data" msgid="7094582042819250762">"行動數據"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"藍牙已關閉"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"零打擾模式已關閉"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_car.xml b/packages/SystemUI/res/values-zh-rTW/strings_car.xml
index 6772d37..41b7222 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings_car.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"訪客"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"訪客"</string>
     <string name="car_add_user" msgid="5245196248349230898">"新增使用者"</string>
     <string name="car_new_user" msgid="8142927244990323906">"新使用者"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"新增的使用者需要自行設定個人空間。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 099cbfe..5be16e3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -34,8 +34,8 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Izaziso"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"Ibhethri lingaphela maduze"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> okusele"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> okusele, cishe u-<xliff:g id="TIME">%s</xliff:g> osele ngokusukela ekusebenziseni kwakho"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> okusele, cishe u-<xliff:g id="TIME">%s</xliff:g> osele"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> okusele, cishe u-<xliff:g id="TIME">%2$s</xliff:g> osele ngokusukela ekusebenziseni kwakho"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> okusele, cishe u-<xliff:g id="TIME">%2$s</xliff:g> osele"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> esele. Isilondolozi sebhethri sivuliwe."</string>
     <string name="invalid_charger" msgid="2741987096648693172">"Ayikwazi ukushaja nge-USB. Sebenzisa ishaja eze nedivayisi yakho."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Ayikwazi ukushaja nge-USB"</string>
@@ -257,7 +257,7 @@
     <string name="accessibility_location_active" msgid="2427290146138169014">"Izicelo zendawo ziyasebenza"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Susa zonke izaziso."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%s</xliff:g>, +<xliff:g id="OVERFLOW">%s</xliff:g>"</string>
+    <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> izaziso eziningi ngaphakathi.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> izaziso eziningi ngaphakathi.</item>
@@ -399,9 +399,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Ukuthula\niokuphelele"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Okubalulekile\nkuphela"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Ama-alamu\nkuphela"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ishaja kaningi (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja kancane (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ize igcwale)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ishaja kaningi (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ize igcwale)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja kancane (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ize igcwale)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Shintsha umsebenzisi"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Shintsha umsebenzisi, umsebenzisi wamanje ngu-<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Umsebenzisi wamanje <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -426,6 +426,9 @@
     <string name="user_logout_notification_action" msgid="1195428991423425062">"KHIPHA UMSEBENZISI"</string>
     <string name="user_add_user_title" msgid="4553596395824132638">"Engeza umsebenzisi omusha?"</string>
     <string name="user_add_user_message_short" msgid="2161624834066214559">"Uma ungeza umsebenzisi omusha, loyo muntu udinga ukusetha isikhala sakhe.\n\nNoma yimuphi umsebenzisi angabuyekeza izinhlelo zokusebenza kubo bonke abasebenzisi."</string>
+    <!-- no translation found for user_limit_reached_title (7374910700117359177) -->
+    <skip />
+    <!-- no translation found for user_limit_reached_message (1855040563671964242) -->
     <string name="user_remove_user_title" msgid="4681256956076895559">"Susa umsebenzisi?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Zonke izinhlelo zokusebenza nedatha yalo msebenzisi kuzosuswa."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Susa"</string>
@@ -729,6 +732,8 @@
     <string name="left_icon" msgid="3096287125959387541">"Isithonjana esingakwesokunxele"</string>
     <string name="right_icon" msgid="3952104823293824311">"Isithonjana sangakwesokudla"</string>
     <string name="drag_to_add_tiles" msgid="230586591689084925">"Bamba uphinde uhudule ukuze ungeze amathayela"</string>
+    <!-- no translation found for drag_to_rearrange_tiles (4566074720193667473) -->
+    <skip />
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Hudulela lapha ukuze ususe"</string>
     <string name="drag_to_remove_disabled" msgid="2390968976638993382">"Udinga okungenani amathayela angu-6"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Hlela"</string>
@@ -757,12 +762,10 @@
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"Ngaphansi kwesikrini esigcwele"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Isimo esingu-<xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Thepha kabili ukuze uhlele."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Thepha kabili ukuze ungeze."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Isimo esingu-<xliff:g id="POSITION">%1$d</xliff:g>. Thepha kabili ukuze ukhethe."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Hambisa i-<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Susa i-<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"I-<xliff:g id="TILE_NAME">%1$s</xliff:g> ingezwe kusimo esingu-<xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"I-<xliff:g id="TILE_NAME">%1$s</xliff:g> isusiwe"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"I-<xliff:g id="TILE_NAME">%1$s</xliff:g> ihanjiswe kusimo esingu-<xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Engeza i-<xliff:g id="TILE_NAME">%1$s</xliff:g> ukuze ubeke i-<xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Hambisa i-<xliff:g id="TILE_NAME">%1$s</xliff:g> ukuze ubeke i-<xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Isihleli sezilungiselelo ezisheshayo."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> isaziso: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Izinhlelo zokusebenza kungenzeka zingasebenzi ngesikrini esihlukanisiwe."</string>
@@ -823,7 +826,7 @@
     <string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string>
     <string name="go_to_web" msgid="2650669128861626071">"Iya kusiphequluli"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Idatha yeselula"</string>
-    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
+    <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"I-Wi-Fi ivaliwe"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"I-Bluetooth ivaliwe"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Ungaphazamisi kuvaliwe"</string>
diff --git a/packages/SystemUI/res/values-zu/strings_car.xml b/packages/SystemUI/res/values-zu/strings_car.xml
index f922f46..c82c3b8 100644
--- a/packages/SystemUI/res/values-zu/strings_car.xml
+++ b/packages/SystemUI/res/values-zu/strings_car.xml
@@ -20,6 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"Isivakashi"</string>
+    <string name="start_guest_session" msgid="7055742120180595689">"Isivakashi"</string>
     <string name="car_add_user" msgid="5245196248349230898">"Engeza umsebenzisi"</string>
     <string name="car_new_user" msgid="8142927244990323906">"Umsebenzisi omusha"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"Uma ungeza umsebenzisi omusha, loyo muntu udinga ukusetha izikhala zakhe."</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 3f63f22..f50ef82 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -143,5 +143,15 @@
     <attr name="rotateButtonEndAngle" format="float" />
     <attr name="rotateButtonScaleX" format="float" />
 
+    <!-- Used to style charging animation AVD animation -->
+    <attr name="chargingAnimColor" format="color" />
+
+    <!-- Used display CarrierText in Keyguard or QS Footer -->
+    <declare-styleable name="CarrierText">
+        <attr name="allCaps" format="boolean" />
+        <attr name="showMissingSim" format="boolean" />
+        <attr name="showAirplaneMode" format="boolean" />
+    </declare-styleable>
+
 </resources>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 07f1ee0..4920fb2 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -94,6 +94,9 @@
     <!-- The color of the gear shown behind a notification -->
     <color name="notification_gear_color">#ff757575</color>
 
+    <!-- The color of the text inside a notification -->
+    <color name="notification_primary_text_color">@*android:color/notification_primary_text_color_light</color>
+
     <!-- The "inside" of a notification, reached via longpress -->
     <color name="notification_guts_bg_color">#f8f9fa</color>
 
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index aecf494..19492a0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -354,7 +354,7 @@
         <item>com.android.systemui.LatencyTester</item>
         <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
         <item>com.android.systemui.ScreenDecorations</item>
-        <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
+        <item>com.android.systemui.biometrics.BiometricDialogImpl</item>
         <item>com.android.systemui.SliceBroadcastRelayHandler</item>
     </string-array>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 786edf2..7e35f5f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -236,6 +236,9 @@
     <!-- Height of search panel including navigation bar height -->
     <dimen name="navbar_search_panel_height">230dip</dimen>
 
+    <!-- Move the back button drawable for 3 button layout upwards in ime mode and in portrait -->
+    <dimen name="navbar_back_button_ime_offset">2dp</dimen>
+
     <!-- Height of the draggable handle at the bottom of the phone notification panel -->
     <dimen name="close_handle_height">36dp</dimen>
 
@@ -252,6 +255,9 @@
          -->
     <dimen name="qs_header_system_icons_area_height">48dp</dimen>
 
+    <!-- How far the quick-quick settings panel extends below the status bar -->
+    <dimen name="qs_quick_header_panel_height">128dp</dimen>
+
     <!-- The height of the container that holds the system icons in the quick settings header in the
          car setting. -->
     <dimen name="car_qs_header_system_icons_area_height">54dp</dimen>
@@ -922,26 +928,31 @@
 
     <dimen name="global_actions_translate">9dp</dimen>
 
-    <!-- the maximum offset in either direction that elements are moved horizontally to prevent
-            burn-in on AOD -->
+    <!-- The maximum offset in either direction that elements are moved horizontally to prevent
+         burn-in on AOD. -->
     <dimen name="burn_in_prevention_offset_x">8dp</dimen>
 
-    <!-- the maximum offset in either direction that elements are moved vertically to prevent
-            burn-in on AOD -->
+    <!-- The maximum offset in either direction that elements are moved vertically to prevent
+         burn-in on AOD. -->
     <dimen name="burn_in_prevention_offset_y">50dp</dimen>
 
+    <!-- The maximum offset in either direction that the charging indication moves vertically
+         to prevent burn-in on AOD. -->
+    <dimen name="charging_indication_burn_in_prevention_offset_y">5dp</dimen>
+
     <dimen name="corner_size">8dp</dimen>
     <dimen name="top_padding">0dp</dimen>
     <dimen name="bottom_padding">48dp</dimen>
     <dimen name="edge_margin">8dp</dimen>
 
-    <dimen name="rounded_corner_radius">0dp</dimen>
-    <dimen name="rounded_corner_radius_top">0dp</dimen>
-    <dimen name="rounded_corner_radius_bottom">0dp</dimen>
+    <dimen name="rounded_corner_radius">@*android:dimen/rounded_corner_radius</dimen>
+    <dimen name="rounded_corner_radius_top">@*android:dimen/rounded_corner_radius_top</dimen>
+    <dimen name="rounded_corner_radius_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen>
     <dimen name="rounded_corner_content_padding">0dp</dimen>
     <dimen name="nav_content_padding">0dp</dimen>
     <dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
     <dimen name="nav_quick_scrub_track_thickness">10dp</dimen>
+    <dimen name="nav_home_back_gesture_drag_limit">60dp</dimen>
 
     <!-- Navigation bar shadow params. -->
     <dimen name="nav_key_button_shadow_offset_x">0dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 915fc6e..36f97cd 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -69,13 +69,13 @@
     <!-- A message that appears when the battery remaining estimate is low in a dialog.  This is
     appended to the subtitle of the low battery alert.  "percentage" is the percentage of battery
     remaining. "time" is the amount of time remaining before the phone runs out of battery [CHAR LIMIT=none]-->
-    <string name="battery_low_percent_format_hybrid"><xliff:g id="percentage">%s</xliff:g> remaining, about <xliff:g id="time">%s</xliff:g> left based on your usage</string>
+    <string name="battery_low_percent_format_hybrid"><xliff:g id="percentage">%1$s</xliff:g> remaining, about <xliff:g id="time">%2$s</xliff:g> left based on your usage</string>
 
     <!-- A message that appears when the battery remaining estimate is low in a dialog and insufficient
     data was present to say it is customized to the user. This is appended to the subtitle of the
     low battery alert.  "percentage" is the percentage of battery remaining. "time" is the amount
      of time remaining before the phone runs out of battery [CHAR LIMIT=none]-->
-    <string name="battery_low_percent_format_hybrid_short"><xliff:g id="percentage">%s</xliff:g> remaining, about <xliff:g id="time">%s</xliff:g> left</string>
+    <string name="battery_low_percent_format_hybrid_short"><xliff:g id="percentage">%1$s</xliff:g> remaining, about <xliff:g id="time">%2$s</xliff:g> left</string>
 
     <!-- Same as battery_low_percent_format, with a notice about battery saver if on. [CHAR LIMIT=none]-->
     <string name="battery_low_percent_format_saver_started"><xliff:g id="percentage">%s</xliff:g> remaining. Battery Saver is on.</string>
@@ -624,7 +624,7 @@
     <!-- The overflow indicator shown when a group has more notification inside the group than the visible ones. An example is "+ 3" [CHAR LIMIT=5] -->
     <string name="notification_group_overflow_indicator">+ <xliff:g id="number" example="3">%s</xliff:g></string>
     <!-- The overflow indicator shown when a group has more notification inside the group than the visible ones. An example is "New message, +3" [CHAR LIMIT=7] -->
-    <string name="notification_group_overflow_indicator_ambient"><xliff:g id="notification_title" example="New message">%s</xliff:g>, +<xliff:g id="overflow" example="+3">%s</xliff:g></string>
+    <string name="notification_group_overflow_indicator_ambient"><xliff:g id="notification_title" example="New message">%1$s</xliff:g>, +<xliff:g id="overflow" example="+3">%2$s</xliff:g></string>
 
     <!-- Content description describing how many more notifications are in a group [CHAR LIMIT=NONE] -->
     <plurals name="notification_group_overflow_description">
@@ -956,13 +956,13 @@
     <string name="interruption_level_alarms_twoline">Alarms\nonly</string>
 
     <!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=50]-->
-    <string name="keyguard_indication_charging_time"><xliff:g id="percentage">%2$s</xliff:g> • Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> until full)</string>
+    <string name="keyguard_indication_charging_time"><xliff:g id="percentage">%2$s</xliff:g> • Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
 
     <!-- Indication on the keyguard that is shown when the device is charging rapidly. Should match keyguard_plugged_in_charging_fast [CHAR LIMIT=50]-->
-    <string name="keyguard_indication_charging_time_fast"><xliff:g id="percentage">%2$s</xliff:g> • Charging rapidly (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> until full)</string>
+    <string name="keyguard_indication_charging_time_fast"><xliff:g id="percentage">%2$s</xliff:g> • Charging rapidly (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
 
     <!-- Indication on the keyguard that is shown when the device is charging slowly. Should match keyguard_plugged_in_charging_slowly [CHAR LIMIT=50]-->
-    <string name="keyguard_indication_charging_time_slowly"><xliff:g id="percentage">%2$s</xliff:g> • Charging slowly (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> until full)</string>
+    <string name="keyguard_indication_charging_time_slowly"><xliff:g id="percentage">%2$s</xliff:g> • Charging slowly (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
 
     <!-- Related to user switcher --><skip/>
 
@@ -1038,6 +1038,15 @@
     <!-- Message for add user confirmation dialog - short version. [CHAR LIMIT=none] -->
     <string name="user_add_user_message_short" msgid="1511354412249044381">When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. </string>
 
+    <!-- Title for the dialog that lets users know that the maximum allowed number of users on the device has been reached. [CHAR LIMIT=35]-->
+    <string name="user_limit_reached_title">User limit reached</string>
+
+    <!-- Message that tells people what's the maximum number of uses allowed on the device. [CHAR_LIMIT=NONE]-->
+    <plurals name="user_limit_reached_message">
+        <item quantity="one">Only one user can be created.</item>
+        <item quantity="other">You can add up to <xliff:g id="count" example="3">%d</xliff:g> users.</item>
+    </plurals>
+
     <!-- Title of the confirmation dialog for deleting a user [CHAR LIMIT=NONE] -->
     <string name="user_remove_user_title">Remove user?</string>
 
@@ -1869,6 +1878,9 @@
     <!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
     <string name="drag_to_add_tiles">Hold and drag to add tiles</string>
 
+    <!-- Label for header of customize QS [CHAR LIMIT=60] -->
+    <string name="drag_to_rearrange_tiles">Hold and drag to rearrange tiles</string>
+
     <!-- Label for area where tiles can be dragged in to [CHAR LIMIT=60] -->
     <string name="drag_to_remove_tiles">Drag here to remove</string>
 
@@ -1929,23 +1941,17 @@
     <!-- Accessibility description of a QS tile while editing positions [CHAR LIMIT=NONE] -->
     <string name="accessibility_qs_edit_add_tile_label"><xliff:g id="tile_name" example="Wi-Fi">%1$s</xliff:g>. Double tap to add.</string>
 
-    <!-- Accessibility description of a place to drop a tile while editing positions [CHAR LIMIT=NONE] -->
-    <string name="accessibility_qs_edit_position_label">Position <xliff:g id="position" example="2">%1$d</xliff:g>. Double tap to select.</string>
-
     <!-- Accessibility description of option to move QS tile [CHAR LIMIT=NONE] -->
     <string name="accessibility_qs_edit_move_tile">Move <xliff:g id="tile_name" example="Wi-Fi">%1$s</xliff:g></string>
 
     <!-- Accessibility description of option to remove QS tile [CHAR LIMIT=NONE] -->
     <string name="accessibility_qs_edit_remove_tile">Remove <xliff:g id="tile_name" example="Wi-Fi">%1$s</xliff:g></string>
 
-    <!-- Accessibility action when QS tile is added [CHAR LIMIT=NONE] -->
-    <string name="accessibility_qs_edit_tile_added"><xliff:g id="tile_name" example="Wi-Fi">%1$s</xliff:g> is added to position <xliff:g id="position" example="5">%2$d</xliff:g></string>
+    <!-- Accessibility action when QS tile is to be added [CHAR LIMIT=NONE] -->
+    <string name="accessibility_qs_edit_tile_add">Add <xliff:g id="tile_name" example="Wi-Fi">%1$s</xliff:g> to position <xliff:g id="position" example="5">%2$d</xliff:g></string>
 
-    <!-- Accessibility action when QS tile is removed [CHAR LIMIT=NONE] -->
-    <string name="accessibility_qs_edit_tile_removed"><xliff:g id="tile_name" example="Wi-Fi">%1$s</xliff:g> is removed</string>
-
-    <!-- Accessibility action when QS tile is moved [CHAR LIMIT=NONE] -->
-    <string name="accessibility_qs_edit_tile_moved"><xliff:g id="tile_name" example="Wi-Fi">%1$s</xliff:g> moved to position <xliff:g id="position" example="5">%2$d</xliff:g></string>
+    <!-- Accessibility action when QS tile is to be moved [CHAR LIMIT=NONE] -->
+    <string name="accessibility_qs_edit_tile_move">Move <xliff:g id="tile_name" example="Wi-Fi">%1$s</xliff:g> to position <xliff:g id="position" example="5">%2$d</xliff:g></string>
 
     <!-- Accessibility label for window when QS editing is happening [CHAR LIMIT=NONE] -->
     <string name="accessibility_desc_quick_settings_edit">Quick settings editor.</string>
@@ -2139,7 +2145,7 @@
     <string name="mobile_data">Mobile data</string>
 
     <!-- Quick settings tile secondary label format combining roaming with the mobile data type. [CHAR LIMIT=NONE] -->
-    <string name="mobile_data_text_format"><xliff:g name="roaming_status" example="Roaming">%s</xliff:g> \u2014 <xliff:g name="mobile_data_type" example="LTE">%s</xliff:g></string>
+    <string name="mobile_data_text_format"><xliff:g name="roaming_status" example="Roaming">%1$s</xliff:g> \u2014 <xliff:g name="mobile_data_type" example="LTE">%2$s</xliff:g></string>
 
     <!-- Label for when wifi is off in QS detail panel [CHAR LIMIT=NONE] -->
     <string name="wifi_is_off">Wi-Fi is off</string>
diff --git a/packages/SystemUI/res/values/strings_car.xml b/packages/SystemUI/res/values/strings_car.xml
index 61d734f..2890cf2 100644
--- a/packages/SystemUI/res/values/strings_car.xml
+++ b/packages/SystemUI/res/values/strings_car.xml
@@ -19,7 +19,9 @@
 <resources>
     <!-- Name of Guest Profile. [CHAR LIMIT=30] -->
     <string name="car_guest">Guest</string>
-    <!-- Name of Add User Profile. [CHAR LIMIT=30] -->
+    <!-- Title for button that starts a guest session. [CHAR LIMIT=30] -->
+    <string name="start_guest_session">Guest</string>
+    <!-- Title for button that  adds a new user. [CHAR LIMIT=30] -->
     <string name="car_add_user">Add User</string>
     <!-- Default name of the new user created. [CHAR LIMIT=30] -->
     <string name="car_new_user">New User</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 988a516..8442dd1 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -321,12 +321,15 @@
         <item name="*android:isLightTheme">false</item>
     </style>
 
-    <style name="Theme.SystemUI.Light" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+    <style name="Theme.SystemUI.Light">
         <item name="wallpaperTextColor">@*android:color/primary_text_material_light</item>
         <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_light</item>
         <item name="android:colorError">@*android:color/error_color_material_light</item>
         <item name="android:colorControlHighlight">#40000000</item>
         <item name="passwordStyle">@style/PasswordTheme.Light</item>
+
+        <!-- Needed for MediaRoute chooser dialog -->
+        <item name="*android:isLightTheme">true</item>
     </style>
 
     <style name="LockPatternStyle">
@@ -335,10 +338,7 @@
         <item name="*android:errorColor">?android:attr/colorError</item>
     </style>
 
-    <!-- Overlay manager may replace this theme -->
-    <style name="qs_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
-
-    <style name="qs_theme" parent="qs_base">
+    <style name="qs_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
         <item name="lightIconTheme">@style/QSIconTheme</item>
         <item name="darkIconTheme">@style/QSIconTheme</item>
         <item name="android:windowIsFloating">true</item>
@@ -455,23 +455,20 @@
 
     <style name="TextAppearance.NotificationInfo">
         <item name="android:fontFamily">sans-serif</item>
-        <item name="android:textColor">@android:color/black</item>
+        <item name="android:textColor">@color/notification_primary_text_color</item>
     </style>
 
     <style name="TextAppearance.NotificationInfo.Primary">
-        <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textSize">16sp</item>
         <item name="android:alpha">0.87</item>
     </style>
 
     <style name="TextAppearance.NotificationInfo.Confirmation">
-        <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textSize">14sp</item>
         <item name="android:alpha">0.87</item>
     </style>
 
     <style name="TextAppearance.NotificationInfo.Secondary">
-        <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textSize">14sp</item>
         <item name="android:alpha">0.54</item>
     </style>
@@ -501,7 +498,12 @@
            parent="@*android:style/TextAppearance.Material.Notification.Info">
     </style>
 
-    <style name="edit_theme" parent="qs_base">
+    <style name="TextAppearance.QSEdit.Headers"
+        parent="@*android:style/TextAppearance.Material.Body2">
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+    </style>
+
+    <style name="edit_theme" parent="qs_theme">
         <item name="android:colorBackground">?android:attr/colorSecondary</item>
     </style>
 
@@ -530,4 +532,16 @@
         <item name="rotateButtonScaleX">-1</item>
     </style>
 
+    <!-- Used to style charging animation AVD animation -->
+    <style name="ChargingAnim" />
+
+    <style name="ChargingAnim.WallpaperBackground">
+        <item name="chargingAnimColor">?attr/wallpaperTextColor</item>
+        <item name="android:textColor">?attr/wallpaperTextColor</item>
+    </style>
+
+    <style name="ChargingAnim.DarkBackground">
+        <item name="chargingAnimColor">@android:color/white</item>
+        <item name="android:textColor">@android:color/white</item>
+    </style>
 </resources>
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
new file mode 100644
index 0000000..eb71698
--- /dev/null
+++ b/packages/SystemUI/shared/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_library {
+
+    name: "SystemUISharedLib",
+    srcs: [
+        "src/**/*.java",
+        "src/**/I*.aidl",
+    ],
+
+    // Enforce that the library is build agains java 7 so that there are
+    // no compatibility issues with launcher
+    java_version: "1.7",
+}
+
+android_app {
+
+    name: "SysUISharedLib",
+    platform_apis: true,
+    srcs: [
+        "src/**/*.java",
+        "src/**/I*.aidl",
+    ],
+
+    static_libs: ["SystemUISharedLib"],
+
+    optimize: {
+        enabled: false,
+    },
+
+}
diff --git a/packages/SystemUI/shared/Android.mk b/packages/SystemUI/shared/Android.mk
deleted file mode 100644
index f20df0c..0000000
--- a/packages/SystemUI/shared/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE := SystemUISharedLib
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_JAR_EXCLUDE_FILES := none
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := SysUISharedLib
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := SystemUISharedLib
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index ebfadd8..ece2bb9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -17,7 +17,7 @@
 package com.android.systemui.shared.recents;
 
 import android.graphics.Rect;
-import com.android.systemui.shared.system.GraphicBufferCompat;
+import android.view.MotionEvent;
 
 /**
  * Temporary callbacks into SystemUI.
@@ -26,9 +26,10 @@
 
     /**
      * Proxies SurfaceControl.screenshotToBuffer().
+     * @Removed
+     * GraphicBufferCompat screenshot(in Rect sourceCrop, int width, int height, int minLayer,
+     *             int maxLayer, boolean useIdentityTransform, int rotation) = 0;
      */
-    GraphicBufferCompat screenshot(in Rect sourceCrop, int width, int height, int minLayer,
-            int maxLayer, boolean useIdentityTransform, int rotation) = 0;
 
     /**
      * Begins screen pinning on the provided {@param taskId}.
@@ -60,4 +61,14 @@
      * needed from current value
      */
     void setBackButtonAlpha(float alpha, boolean animate) = 8;
+
+    /**
+     * Proxies motion events from the homescreen UI to the status bar. Only called when
+     * swipe down is detected on WORKSPACE. The sender guarantees the following order of events on
+     * the tracking pointer.
+     *
+     * Normal gesture: DOWN, MOVE/POINTER_DOWN/POINTER_UP)*, UP or CANCLE
+     */
+    void onStatusBarMotionEvent(in MotionEvent event) = 9;
+
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java
index a0e7752..19e8673 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java
@@ -110,11 +110,19 @@
                     synchronized(mLoadQueue) {
                         try {
                             mWaitingOnLoadQueue = true;
-                            mMainThreadHandler.post(
-                                    () -> mOnIdleChangedListener.onIdleChanged(true));
+                            mMainThreadHandler.post(new Runnable() {
+                                @Override
+                                public void run() {
+                                    mOnIdleChangedListener.onIdleChanged(true);
+                                }
+                            });
                             mLoadQueue.wait();
-                            mMainThreadHandler.post(
-                                    () -> mOnIdleChangedListener.onIdleChanged(false));
+                            mMainThreadHandler.post(new Runnable() {
+                                @Override
+                                public void run() {
+                                    mOnIdleChangedListener.onIdleChanged(false);
+                                }
+                            });
                             mWaitingOnLoadQueue = false;
                         } catch (InterruptedException ie) {
                             ie.printStackTrace();
@@ -142,8 +150,12 @@
 
             if (!mCancelled) {
                 // Notify that the task data has changed
-                mMainThreadHandler.post(
-                        () -> t.notifyTaskDataLoaded(thumbnailData, icon));
+                mMainThreadHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        t.notifyTaskDataLoaded(thumbnailData, icon);
+                    }
+                });
             }
         }
     }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java
index 24ba998..852463f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java
@@ -34,7 +34,8 @@
 /**
  * Loader class that loads full-resolution thumbnails when appropriate.
  */
-public class HighResThumbnailLoader implements TaskCallbacks {
+public class HighResThumbnailLoader implements
+        TaskCallbacks, BackgroundTaskLoader.OnIdleChangedListener {
 
     private final ActivityManagerWrapper mActivityManager;
 
@@ -80,6 +81,11 @@
         updateLoading();
     }
 
+    @Override
+    public void onIdleChanged(boolean idle) {
+        setTaskLoadQueueIdle(idle);
+    }
+
     /**
      * Sets whether the other task load queue is idling. Avoid double-loading bitmaps by not
      * starting this queue until the other queue is idling.
@@ -220,15 +226,18 @@
             }
         }
 
-        private void loadTask(Task t) {
-            ThumbnailData thumbnail = mActivityManager.getTaskThumbnail(t.key.id,
+        private void loadTask(final Task t) {
+            final ThumbnailData thumbnail = mActivityManager.getTaskThumbnail(t.key.id,
                     false /* reducedResolution */);
-            mMainThreadHandler.post(() -> {
-                synchronized (mLoadQueue) {
-                    mLoadingTasks.remove(t);
-                }
-                if (mVisibleTasks.contains(t)) {
-                    t.notifyTaskDataLoaded(thumbnail, t.icon);
+            mMainThreadHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    synchronized (mLoadQueue) {
+                        mLoadingTasks.remove(t);
+                    }
+                    if (mVisibleTasks.contains(t)) {
+                        t.notifyTaskDataLoaded(thumbnail, t.icon);
+                    }
                 }
             });
         }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
index ab2e277..996c837 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
@@ -110,8 +110,7 @@
         mActivityInfoCache = new LruCache<>(numRecentTasks);
 
         mIconLoader = createNewIconLoader(context, mIconCache, mActivityInfoCache);
-        mLoader = new BackgroundTaskLoader(mLoadQueue, mIconLoader,
-                mHighResThumbnailLoader::setTaskLoadQueueIdle);
+        mLoader = new BackgroundTaskLoader(mLoadQueue, mIconLoader, mHighResThumbnailLoader);
     }
 
     protected IconLoader createNewIconLoader(Context context,TaskKeyLruCache<Drawable> iconCache,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java
index 4bf3500..23582d4 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java
@@ -34,7 +34,7 @@
      * Gets a specific entry in the cache with the specified key, regardless of whether the cached
      * value is valid or not.
      */
-    final V get(TaskKey key) {
+    final synchronized V get(TaskKey key) {
         return getCacheEntry(key.id);
     }
 
@@ -42,7 +42,7 @@
      * Returns the value only if the key is valid (has not been updated since the last time it was
      * in the cache)
      */
-    final V getAndInvalidateIfModified(TaskKey key) {
+    final synchronized V getAndInvalidateIfModified(TaskKey key) {
         TaskKey lastKey = mKeys.get(key.id);
         if (lastKey != null) {
             if ((lastKey.windowingMode != key.windowingMode) ||
@@ -59,7 +59,7 @@
     }
 
     /** Puts an entry in the cache for a specific key. */
-    final void put(TaskKey key, V value) {
+    final synchronized void put(TaskKey key, V value) {
         if (key == null || value == null) {
             Log.e(TAG, "Unexpected null key or value: " + key + ", " + value);
             return;
@@ -70,14 +70,14 @@
 
 
     /** Removes a cache entry for a specific key. */
-    final void remove(TaskKey key) {
+    final synchronized void remove(TaskKey key) {
         // Remove the key after the cache value because we need it to make the callback
         removeCacheEntry(key.id);
         mKeys.remove(key.id);
     }
 
     /** Removes all the entries in the cache. */
-    final void evictAll() {
+    final synchronized void evictAll() {
         evictAllCache();
         mKeys.clear();
     }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
index a369397..c731ac9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
@@ -19,6 +19,7 @@
 import android.content.ComponentName;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.SparseArray;
 
 import com.android.systemui.shared.recents.model.Task.TaskKey;
 import com.android.systemui.shared.recents.utilities.AnimationProps;
@@ -67,7 +68,12 @@
 
     public TaskStack() {
         // Ensure that we only show stack tasks
-        mStackTaskList.setFilter((taskIdMap, t, index) -> t.isStackTask);
+        mStackTaskList.setFilter(new TaskFilter() {
+            @Override
+            public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) {
+                return  t.isStackTask;
+            }
+        });
     }
 
     /** Sets the callbacks for this task stack. */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index dce72b4..b04d047 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -201,8 +201,8 @@
     /**
      * Starts the recents activity. The caller should manage the thread on which this is called.
      */
-    public void startRecentsActivity(Intent intent, AssistDataReceiver assistDataReceiver,
-            RecentsAnimationListener animationHandler, Consumer<Boolean> resultCallback,
+    public void startRecentsActivity(Intent intent, final AssistDataReceiver assistDataReceiver,
+            final RecentsAnimationListener animationHandler, final Consumer<Boolean> resultCallback,
             Handler resultCallbackHandler) {
         try {
             IAssistDataReceiver receiver = null;
@@ -284,9 +284,9 @@
      * @param resultCallback The result success callback
      * @param resultCallbackHandler The handler to receive the result callback
      */
-    public void startActivityFromRecentsAsync(Task.TaskKey taskKey, ActivityOptions options,
-            int windowingMode, int activityType, Consumer<Boolean> resultCallback,
-            Handler resultCallbackHandler) {
+    public void startActivityFromRecentsAsync(final Task.TaskKey taskKey, ActivityOptions options,
+            int windowingMode, int activityType, final Consumer<Boolean> resultCallback,
+            final Handler resultCallbackHandler) {
         if (taskKey.windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
             // We show non-visible docked tasks in Recents, but we always want to launch
             // them in the fullscreen stack.
@@ -364,7 +364,7 @@
     /**
      * Requests that the system close any open system windows (including other SystemUI).
      */
-    public void closeSystemWindows(String reason) {
+    public void closeSystemWindows(final String reason) {
         mBackgroundExecutor.submit(new Runnable() {
             @Override
             public void run() {
@@ -380,7 +380,7 @@
     /**
      * Removes a task by id.
      */
-    public void removeTask(int taskId) {
+    public void removeTask(final int taskId) {
         mBackgroundExecutor.submit(new Runnable() {
             @Override
             public void run() {
@@ -394,6 +394,22 @@
     }
 
     /**
+     * Removes all the recent tasks.
+     */
+    public void removeAllRecentTasks() {
+        mBackgroundExecutor.submit(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    ActivityTaskManager.getService().removeAllVisibleRecentTasks();
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Failed to remove all tasks", e);
+                }
+            }
+        });
+    }
+
+    /**
      * Cancels the current window transtion to/from Recents for the given task id.
      */
     public void cancelWindowTransition(int taskId) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/DockedStackListenerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/DockedStackListenerCompat.java
new file mode 100644
index 0000000..bb319e6
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/DockedStackListenerCompat.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.system;
+
+import android.view.IDockedStackListener;
+
+/**
+ * An interface to track docked stack changes.
+ */
+public class DockedStackListenerCompat {
+
+    IDockedStackListener.Stub mListener = new IDockedStackListener.Stub() {
+        @Override
+        public void onDividerVisibilityChanged(boolean visible) {}
+
+        @Override
+        public void onDockedStackExistsChanged(boolean exists) {
+            DockedStackListenerCompat.this.onDockedStackExistsChanged(exists);
+        }
+
+        @Override
+        public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
+                boolean isHomeStackResizable) {
+            DockedStackListenerCompat.this.onDockedStackMinimizedChanged(minimized, animDuration,
+                    isHomeStackResizable);
+        }
+
+        @Override
+        public void onAdjustedForImeChanged(boolean adjustedForIme, long animDuration) {}
+
+        @Override
+        public void onDockSideChanged(final int newDockSide) {
+            DockedStackListenerCompat.this.onDockSideChanged(newDockSide);
+        }
+    };
+
+    public void onDockedStackExistsChanged(boolean exists) {
+        // To be overridden
+    }
+
+    public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
+            boolean isHomeStackResizable) {
+        // To be overridden
+    }
+
+    public void onDockSideChanged(final int newDockSide) {
+        // To be overridden
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.aidl
deleted file mode 100644
index f9450ad..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shared.system;
-
-parcelable GraphicBufferCompat;
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.java
deleted file mode 100644
index 66b8fed..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/GraphicBufferCompat.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.shared.system;
-
-import android.graphics.Bitmap;
-import android.graphics.GraphicBuffer;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Wraps the internal graphic buffer.
- */
-public class GraphicBufferCompat implements Parcelable {
-
-    private GraphicBuffer mBuffer;
-
-    public GraphicBufferCompat(GraphicBuffer buffer) {
-        mBuffer = buffer;
-    }
-
-    public GraphicBufferCompat(Parcel in) {
-        mBuffer = GraphicBuffer.CREATOR.createFromParcel(in);
-    }
-
-    public Bitmap toBitmap() {
-        return mBuffer != null
-                ? Bitmap.createHardwareBitmap(mBuffer)
-                : null;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        mBuffer.writeToParcel(dest, flags);
-    }
-
-    public static final Parcelable.Creator<GraphicBufferCompat> CREATOR
-            = new Parcelable.Creator<GraphicBufferCompat>() {
-        public GraphicBufferCompat createFromParcel(Parcel in) {
-            return new GraphicBufferCompat(in);
-        }
-
-        public GraphicBufferCompat[] newArray(int size) {
-            return new GraphicBufferCompat[size];
-        }
-    };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
index 625b1de..61be076 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
@@ -41,11 +41,11 @@
     }
 
     private static IRemoteAnimationRunner.Stub wrapRemoteAnimationRunner(
-            RemoteAnimationRunnerCompat remoteAnimationAdapter) {
+            final RemoteAnimationRunnerCompat remoteAnimationAdapter) {
         return new IRemoteAnimationRunner.Stub() {
             @Override
             public void onAnimationStart(RemoteAnimationTarget[] apps,
-                    IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
+                    final IRemoteAnimationFinishedCallback finishedCallback) {
                 final RemoteAnimationTargetCompat[] appsCompat =
                         RemoteAnimationTargetCompat.wrap(apps);
                 final Runnable animationFinishedCallback = new Runnable() {
@@ -63,7 +63,7 @@
             }
 
             @Override
-            public void onAnimationCancelled() throws RemoteException {
+            public void onAnimationCancelled() {
                 remoteAnimationAdapter.onAnimationCancelled();
             }
         };
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java
index 217e0aa..dc4eb3b 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java
@@ -21,6 +21,7 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
+import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewRootImpl;
 
@@ -47,11 +48,13 @@
      * @param params The surface parameters to apply. DO NOT MODIFY the list after passing into
      *               this method to avoid synchronization issues.
      */
-    public void scheduleApply(SurfaceParams... params) {
+    public void scheduleApply(final SurfaceParams... params) {
         if (mTargetViewRootImpl == null) {
             return;
         }
-        mTargetViewRootImpl.registerRtFrameCallback(frame -> {
+        mTargetViewRootImpl.registerRtFrameCallback(new ThreadedRenderer.FrameDrawingCallback() {
+            @Override
+            public void onFrameDraw(long frame) {
                 if (mTargetSurface == null || !mTargetSurface.isValid()) {
                     return;
                 }
@@ -64,6 +67,7 @@
                 }
                 t.setEarlyWakeup();
                 t.apply();
+            }
         });
 
         // Make sure a frame gets scheduled.
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index ed2f831..d83b36d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -166,4 +166,16 @@
         }
         return NAV_BAR_POS_INVALID;
     }
+
+    /**
+     * Registers a docked stack listener with the system.
+     */
+    public void registerDockedStackListener(DockedStackListenerCompat listener) {
+        try {
+            WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(
+                    listener.mListener);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to register docked stack listener");
+        }
+    }
 }
diff --git a/packages/SystemUI/shared/tests/Android.mk b/packages/SystemUI/shared/tests/Android.mk
index 4e7cbbf..02774c9 100644
--- a/packages/SystemUI/shared/tests/Android.mk
+++ b/packages/SystemUI/shared/tests/Android.mk
@@ -30,10 +30,10 @@
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 # Add local path sources as well as shared lib sources
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-    $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
+	SystemUISharedLib \
     metrics-helper-lib \
     android-support-test \
     mockito-target-inline-minus-junit4 \
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index 66475e2..a0a3687 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -43,11 +43,6 @@
 import android.telephony.TelephonyManager;
 
 public class CarrierText extends TextView {
-    /** Do not show missing sim message. */
-    public static final int FLAG_HIDE_MISSING_SIM = 1 << 0;
-    /** Do not show airplane mode message. */
-    public static final int FLAG_HIDE_AIRPLANE_MODE = 1 << 1;
-
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "CarrierText";
 
@@ -55,17 +50,23 @@
 
     private final boolean mIsEmergencyCallCapable;
 
+    private boolean mTelephonyCapable;
+
+    private boolean mShowMissingSim;
+
+    private boolean mShowAirplaneMode;
+
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
     private WifiManager mWifiManager;
 
     private boolean[] mSimErrorState = new boolean[TelephonyManager.getDefault().getPhoneCount()];
 
-    private int mFlags;
-
-    private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+    private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
         @Override
         public void onRefreshCarrierInfo() {
+            if (DEBUG) Log.d(TAG, "onRefreshCarrierInfo(), mTelephonyCapable: "
+                    + Boolean.toString(mTelephonyCapable));
             updateCarrierText();
         }
 
@@ -77,9 +78,18 @@
             setSelected(true);
         };
 
+        @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, IccCardConstants.State simState) {
             if (slotId < 0) {
-                Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId);
+                Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId
+                        + " mTelephonyCapable: " + Boolean.toString(mTelephonyCapable));
                 return;
             }
 
@@ -91,13 +101,9 @@
                 mSimErrorState[slotId] = false;
                 updateCarrierText();
             }
-        };
+        }
     };
 
-    public void setDisplayFlags(int flags) {
-        mFlags = flags;
-    }
-
     /**
      * The status of this lock screen. Primarily used for widgets on LockScreen.
      */
@@ -110,7 +116,8 @@
         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
+        SimIoError, // SIM card is faulty
+        SimUnknown // SIM card is unknown
     }
 
     public CarrierText(Context context) {
@@ -126,6 +133,8 @@
                 attrs, R.styleable.CarrierText, 0, 0);
         try {
             useAllCaps = a.getBoolean(R.styleable.CarrierText_allCaps, false);
+            mShowAirplaneMode = a.getBoolean(R.styleable.CarrierText_showAirplaneMode, false);
+            mShowMissingSim = a.getBoolean(R.styleable.CarrierText_showMissingSim, false);
         } finally {
             a.recycle();
         }
@@ -249,12 +258,12 @@
     }
 
     private String getMissingSimMessage() {
-        return (mFlags & FLAG_HIDE_MISSING_SIM) == 0
+        return mShowMissingSim && mTelephonyCapable
                 ? getContext().getString(R.string.keyguard_missing_sim_message_short) : "";
     }
 
     private String getAirplaneModeMessage() {
-        return (mFlags & FLAG_HIDE_AIRPLANE_MODE) == 0
+        return mShowAirplaneMode
                 ? getContext().getString(R.string.airplane_mode) : "";
     }
 
@@ -360,6 +369,9 @@
                         getContext().getText(R.string.keyguard_sim_error_message_short),
                         text);
                 break;
+            case SimUnknown:
+                carrierText = null;
+                break;
         }
 
         return carrierText;
@@ -408,11 +420,11 @@
             case PERM_DISABLED:
                 return StatusMode.SimPermDisabled;
             case UNKNOWN:
-                return StatusMode.SimMissing;
+                return StatusMode.SimUnknown;
             case CARD_IO_ERROR:
                 return StatusMode.SimIoError;
         }
-        return StatusMode.SimMissing;
+        return StatusMode.SimUnknown;
     }
 
     private static CharSequence concatenate(CharSequence plmn, CharSequence spn) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
new file mode 100644
index 0000000..5bbbc52
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -0,0 +1,155 @@
+package com.android.keyguard;
+
+import android.content.Context;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.TextClock;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+
+/**
+ * Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
+ */
+public class KeyguardClockSwitch extends FrameLayout {
+    /**
+     * Optional/alternative clock injected via plugin.
+     */
+    private ClockPlugin mClockPlugin;
+    /**
+     * Default clock.
+     */
+    private TextClock mClockView;
+
+    private final PluginListener<ClockPlugin> mClockPluginListener =
+            new PluginListener<ClockPlugin>() {
+                @Override
+                public void onPluginConnected(ClockPlugin plugin, Context pluginContext) {
+                    View view = plugin.getView();
+                    if (view != null) {
+                        mClockPlugin = plugin;
+                        addView(view, -1,
+                                new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                                        ViewGroup.LayoutParams.WRAP_CONTENT));
+                        initPluginParams();
+                        mClockView.setVisibility(View.GONE);
+                    }
+                }
+
+                @Override
+                public void onPluginDisconnected(ClockPlugin plugin) {
+                    View view = plugin.getView();
+                    if (view != null) {
+                        mClockPlugin = null;
+                        removeView(view);
+                        mClockView.setVisibility(View.VISIBLE);
+                    }
+                }
+            };
+
+    public KeyguardClockSwitch(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardClockSwitch(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mClockView = findViewById(R.id.default_clock_view);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        Dependency.get(PluginManager.class).addPluginListener(mClockPluginListener,
+                ClockPlugin.class);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        Dependency.get(PluginManager.class).removePluginListener(mClockPluginListener);
+    }
+
+    /**
+     * It will also update plugin setStyle if plugin is connected.
+     */
+    public void setStyle(Style style) {
+        mClockView.getPaint().setStyle(style);
+        if (mClockPlugin != null) {
+            mClockPlugin.setStyle(style);
+        }
+    }
+
+    /**
+     * It will also update plugin setTextColor if plugin is connected.
+     */
+    public void setTextColor(int color) {
+        mClockView.setTextColor(color);
+        if (mClockPlugin != null) {
+            mClockPlugin.setTextColor(color);
+        }
+    }
+
+    public void setShowCurrentUserTime(boolean showCurrentUserTime) {
+        mClockView.setShowCurrentUserTime(showCurrentUserTime);
+    }
+
+    public void setElegantTextHeight(boolean elegant) {
+        mClockView.setElegantTextHeight(elegant);
+    }
+
+    public void setTextSize(int unit, float size) {
+        mClockView.setTextSize(unit, size);
+    }
+
+    public void setFormat12Hour(CharSequence format) {
+        mClockView.setFormat12Hour(format);
+    }
+
+    public void setFormat24Hour(CharSequence format) {
+        mClockView.setFormat24Hour(format);
+    }
+
+    public Paint getPaint() {
+        return mClockView.getPaint();
+    }
+
+    public int getCurrentTextColor() {
+        return mClockView.getCurrentTextColor();
+    }
+
+    public float getTextSize() {
+        return mClockView.getTextSize();
+    }
+
+    public void refresh() {
+        mClockView.refresh();
+    }
+
+    /**
+     * When plugin changes, set all kept parameters into newer plugin.
+     */
+    private void initPluginParams() {
+        if (mClockPlugin != null) {
+            mClockPlugin.setStyle(getPaint().getStyle());
+            mClockPlugin.setTextColor(getCurrentTextColor());
+        }
+    }
+
+    @VisibleForTesting (otherwise = VisibleForTesting.NONE)
+    PluginListener getClockPluginListener() {
+        return mClockPluginListener;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index df64160..265a961 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -242,6 +242,11 @@
         mViewMediatorCallback.resetKeyguard();
     }
 
+    @Override
+    public void onCancelClicked() {
+        mViewMediatorCallback.onCancelClicked();
+    }
+
     public void resetSecurityContainer() {
         mSecurityContainer.reset();
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index adb2460..a3862eb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -112,6 +112,7 @@
         if (cancelBtn != null) {
             cancelBtn.setOnClickListener(view -> {
                 mCallback.reset();
+                mCallback.onCancelClicked();
             });
         }
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 81cf3ae..6b24ad5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -201,6 +201,7 @@
         if (cancelBtn != null) {
             cancelBtn.setOnClickListener(view -> {
                 mCallback.reset();
+                mCallback.onCancelClicked();
             });
         }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 50cf5b9..5ffdc7b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -145,6 +145,8 @@
         mLockPatternView = findViewById(R.id.lockPatternView);
         mLockPatternView.setSaveEnabled(false);
         mLockPatternView.setOnPatternListener(new UnlockPatternListener());
+        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
+                KeyguardUpdateMonitor.getCurrentUser()));
 
         // vibrate mode will be the same for the life of this screen
         mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
@@ -163,6 +165,7 @@
         if (cancelBtn != null) {
             cancelBtn.setOnClickListener(view -> {
                 mCallback.reset();
+                mCallback.onCancelClicked();
             });
         }
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index 5b743c1..cbfbffb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -48,4 +48,11 @@
      * Resets the keyguard view.
      */
     void reset();
+
+    /**
+     * Call when cancel button is pressed in bouncer.
+     */
+    default void onCancelClicked() {
+        // No-op
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 745f81d..b159b39 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -15,7 +15,6 @@
  */
 package com.android.keyguard;
 
-import android.R.style;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.admin.DevicePolicyManager;
@@ -27,7 +26,6 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.StatsLog;
-import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
@@ -68,6 +66,7 @@
          */
         public void finish(boolean strongAuth, int targetUserId);
         public void reset();
+        public void onCancelClicked();
     }
 
     public KeyguardSecurityContainer(Context context, AttributeSet attrs) {
@@ -211,7 +210,7 @@
 
         if (messageId != 0) {
             final String message = mContext.getString(messageId,
-                    KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(userId),
+                    mLockPatternUtils.getCurrentFailedPasswordAttempts(userId),
                     timeoutInSeconds);
             showDialog(null, message);
         }
@@ -256,8 +255,8 @@
     }
 
     private void reportFailedUnlockAttempt(int userId, int timeoutMs) {
-        final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
-        final int failedAttempts = monitor.getFailedUnlockAttempts(userId) + 1; // +1 for this time
+        // +1 for this time
+        final int failedAttempts = mLockPatternUtils.getCurrentFailedPasswordAttempts(userId) + 1;
 
         if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
 
@@ -291,7 +290,6 @@
                 showWipeDialog(failedAttempts, userType);
             }
         }
-        monitor.reportFailedStrongAuthUnlockAttempt(userId);
         mLockPatternUtils.reportFailedPasswordAttempt(userId);
         if (timeoutMs > 0) {
             mLockPatternUtils.reportPasswordLockout(timeoutMs, userId);
@@ -435,7 +433,6 @@
             if (success) {
                 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED,
                     StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__SUCCESS);
-                monitor.clearFailedUnlockAttempts();
                 mLockPatternUtils.reportSuccessfulPasswordAttempt(userId);
             } else {
                 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED,
@@ -447,6 +444,10 @@
         public void reset() {
             mSecurityCallback.reset();
         }
+
+        public void onCancelClicked() {
+            mSecurityCallback.onCancelClicked();
+        }
     };
 
     // The following is used to ignore callbacks from SecurityViews that are no longer current
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 6517a9d..7479152 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -16,6 +16,8 @@
 
 package com.android.keyguard;
 
+import static android.app.slice.Slice.HINT_LIST_ITEM;
+
 import android.animation.LayoutTransition;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
@@ -27,6 +29,7 @@
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Trace;
 import android.provider.Settings;
 import android.text.Layout;
 import android.text.TextUtils;
@@ -63,6 +66,7 @@
 import androidx.slice.core.SliceQuery;
 import androidx.slice.widget.ListContent;
 import androidx.slice.widget.RowContent;
+import androidx.slice.widget.SliceContent;
 import androidx.slice.widget.SliceLiveData;
 
 /**
@@ -148,6 +152,7 @@
     }
 
     private void showSlice() {
+        Trace.beginSection("KeyguardSliceView#showSlice");
         if (mPulsing || mSlice == null) {
             mTitle.setVisibility(GONE);
             mRow.setVisibility(GONE);
@@ -157,12 +162,13 @@
             return;
         }
 
-        ListContent lc = new ListContent(getContext(), mSlice, null, 0, 0);
-        mHasHeader = lc.hasHeader();
-        List<SliceItem> subItems = new ArrayList<SliceItem>();
+        ListContent lc = new ListContent(getContext(), mSlice);
+        SliceContent headerContent = lc.getHeader();
+        mHasHeader = headerContent != null && !headerContent.getSliceItem().hasHint(HINT_LIST_ITEM);
+        List<SliceContent> subItems = new ArrayList<SliceContent>();
         for (int i = 0; i < lc.getRowItems().size(); i++) {
-            SliceItem subItem = lc.getRowItems().get(i);
-            String itemUri = subItem.getSlice().getUri().toString();
+            SliceContent subItem = lc.getRowItems().get(i);
+            String itemUri = subItem.getSliceItem().getSlice().getUri().toString();
             // Filter out the action row
             if (!KeyguardSliceProvider.KEYGUARD_ACTION_URI.equals(itemUri)) {
                 subItems.add(subItem);
@@ -173,9 +179,7 @@
         } else {
             mTitle.setVisibility(VISIBLE);
 
-            // If there's a header it'll be the first subitem
-            RowContent header = new RowContent(getContext(), subItems.get(0),
-                    true /* showStartItem */);
+            RowContent header = lc.getHeader();
             SliceItem mainTitle = header.getTitleItem();
             CharSequence title = mainTitle != null ? mainTitle.getText() : null;
             mTitle.setText(title);
@@ -187,8 +191,8 @@
         final int startIndex = mHasHeader ? 1 : 0; // First item is header; skip it
         mRow.setVisibility(subItemsCount > 0 ? VISIBLE : GONE);
         for (int i = startIndex; i < subItemsCount; i++) {
-            SliceItem item = subItems.get(i);
-            RowContent rc = new RowContent(getContext(), item, true /* showStartItem */);
+            RowContent rc = (RowContent) subItems.get(i);
+            SliceItem item = rc.getSliceItem();
             final Uri itemTag = item.getSlice().getUri();
             // Try to reuse the view if already exists in the layout
             KeyguardSliceButton button = mRow.findViewWithTag(itemTag);
@@ -236,6 +240,7 @@
         if (mContentChangeListener != null) {
             mContentChangeListener.run();
         }
+        Trace.endSection();
     }
 
     public void setPulsing(boolean pulsing, boolean animate) {
@@ -383,8 +388,23 @@
     }
 
     public void refresh() {
-        Slice slice = SliceViewManager.getInstance(getContext()).bindSlice(mKeyguardSliceUri);
+        Slice slice;
+        Trace.beginSection("KeyguardSliceView#refresh");
+        // We can optimize performance and avoid binder calls when we know that we're bound
+        // to a Slice on the same process.
+        if (KeyguardSliceProvider.KEYGUARD_SLICE_URI.equals(mKeyguardSliceUri.toString())) {
+            KeyguardSliceProvider instance = KeyguardSliceProvider.getAttachedInstance();
+            if (instance != null) {
+                slice = instance.onBindSlice(mKeyguardSliceUri);
+            } else {
+                Log.w(TAG, "Keyguard slice not bound yet?");
+                slice = null;
+            }
+        } else {
+            slice = SliceViewManager.getInstance(getContext()).bindSlice(mKeyguardSliceUri);
+        }
         onChanged(slice);
+        Trace.endSection();
     }
 
     public static class Row extends LinearLayout {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 6da143c..6d1313c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -39,7 +39,6 @@
 import android.view.View;
 import android.widget.GridLayout;
 import android.widget.RelativeLayout;
-import android.widget.TextClock;
 import android.widget.TextView;
 
 import com.android.internal.widget.LockPatternUtils;
@@ -64,7 +63,7 @@
     private final float mSmallClockScale;
 
     private TextView mLogoutView;
-    private TextClock mClockView;
+    private KeyguardClockSwitch mClockView;
     private View mClockSeparator;
     private TextView mOwnerInfo;
     private KeyguardSliceView mKeyguardSlice;
@@ -248,7 +247,7 @@
                         .scaleX(clockScale)
                         .scaleY(clockScale)
                         .withEndAction(() -> {
-                            mClockView.getPaint().setStyle(style);
+                            mClockView.setStyle(style);
                             mClockView.invalidate();
                         })
                         .start();
@@ -256,7 +255,7 @@
                 mClockView.setY(top);
                 mClockView.setScaleX(clockScale);
                 mClockView.setScaleY(clockScale);
-                mClockView.getPaint().setStyle(style);
+                mClockView.setStyle(style);
                 mClockView.invalidate();
             }
         } else if (view == mClockSeparator) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fa7e814..3e534d1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -84,6 +84,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.Preconditions;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.settingslib.WirelessUtils;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
@@ -148,6 +149,7 @@
     private static final int MSG_ASSISTANT_STACK_CHANGED = 335;
     private static final int MSG_BIOMETRIC_AUTHENTICATION_CONTINUE = 336;
     private static final int MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED = 337;
+    private static final int MSG_TELEPHONY_CAPABLE = 338;
 
     /** Biometric authentication state: Not listening. */
     private static final int BIOMETRIC_STATE_STOPPED = 0;
@@ -204,6 +206,8 @@
     private boolean mHasLockscreenWallpaper;
     private boolean mAssistantVisible;
     private boolean mKeyguardOccluded;
+    @VisibleForTesting
+    protected boolean mTelephonyCapable;
 
     // Device provisioning state
     private boolean mDeviceProvisioned;
@@ -211,9 +215,6 @@
     // Battery status
     private BatteryStatus mBatteryStatus;
 
-    // Password attempts
-    private SparseIntArray mFailedAttempts = new SparseIntArray();
-
     private final StrongAuthTracker mStrongAuthTracker;
 
     private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
@@ -344,6 +345,9 @@
                 case MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED:
                     updateLogoutEnabled();
                     break;
+                case MSG_TELEPHONY_CAPABLE:
+                    updateTelephonyCapable((boolean)msg.obj);
+                    break;
                 default:
                     super.handleMessage(msg);
                     break;
@@ -962,14 +966,18 @@
                                 maxChargingMicroWatt));
                 mHandler.sendMessage(msg);
             } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
+                SimData args = SimData.fromIntent(intent);
                 // ACTION_SIM_STATE_CHANGED is rebroadcast after unlocking the device to
                 // keep compatibility with apps that aren't direct boot aware.
                 // SysUI should just ignore this broadcast because it was already received
                 // and processed previously.
                 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
+                    // Guarantee mTelephonyCapable state after SysUI crash and restart
+                    if (args.simState == State.ABSENT) {
+                        mHandler.obtainMessage(MSG_TELEPHONY_CAPABLE, true).sendToTarget();
+                    }
                     return;
                 }
-                SimData args = SimData.fromIntent(intent);
                 if (DEBUG_SIM_STATES) {
                     Log.v(TAG, "action " + action
                         + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
@@ -1467,6 +1475,16 @@
         mUserManager = context.getSystemService(UserManager.class);
         mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
         mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
+        updateAirplaneModeState();
+    }
+
+    private void updateAirplaneModeState() {
+        // ACTION_AIRPLANE_MODE_CHANGED do not broadcast if device set AirplaneMode ON and boot
+        if (!WirelessUtils.isAirplaneModeOn(mContext)
+                || mHandler.hasMessages(MSG_AIRPLANE_MODE_CHANGED)) {
+            return;
+        }
+        mHandler.sendEmptyMessage(MSG_AIRPLANE_MODE_CHANGED);
     }
 
     private void updateBiometricListeningState() {
@@ -1823,6 +1841,23 @@
     }
 
     /**
+     * Handle Telephony status during Boot for CarrierText display policy
+     */
+    @VisibleForTesting
+    void updateTelephonyCapable(boolean capable){
+        if (capable == mTelephonyCapable) {
+            return;
+        }
+        mTelephonyCapable = capable;
+        for (WeakReference<KeyguardUpdateMonitorCallback> ref : mCallbacks) {
+            KeyguardUpdateMonitorCallback cb = ref.get();
+            if (cb != null) {
+                cb.onTelephonyCapable(mTelephonyCapable);
+            }
+        }
+    }
+
+    /**
      * Handle {@link #MSG_SIM_STATE_CHANGE}
      */
     @VisibleForTesting
@@ -1835,6 +1870,10 @@
 
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             Log.w(TAG, "invalid subId in handleSimStateChange()");
+            /* Only handle No SIM(ABSENT) due to handleServiceStateChange() handle other case */
+            if (state == State.ABSENT) {
+                updateTelephonyCapable(true);
+            }
             return;
         }
 
@@ -1863,7 +1902,8 @@
     /**
      * Handle {@link #MSG_SERVICE_STATE_CHANGE}
      */
-    private void handleServiceStateChange(int subId, ServiceState serviceState) {
+    @VisibleForTesting
+    void handleServiceStateChange(int subId, ServiceState serviceState) {
         if (DEBUG) {
             Log.d(TAG,
                     "handleServiceStateChange(subId=" + subId + ", serviceState=" + serviceState);
@@ -1872,6 +1912,8 @@
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             Log.w(TAG, "invalid subId in handleServiceStateChange()");
             return;
+        } else {
+            updateTelephonyCapable(true);
         }
 
         mServiceStates.put(subId, serviceState);
@@ -2035,6 +2077,7 @@
         callback.onRefreshCarrierInfo();
         callback.onClockVisibilityChanged();
         callback.onKeyguardVisibilityChangedRaw(mKeyguardIsVisible);
+        callback.onTelephonyCapable(mTelephonyCapable);
         for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
             final SimData state = data.getValue();
             callback.onSimStateChanged(state.subId, state.slotId, state.simState);
@@ -2095,22 +2138,10 @@
         return mDeviceProvisioned;
     }
 
-    public void clearFailedUnlockAttempts() {
-        mFailedAttempts.delete(sCurrentUser);
-    }
-
     public ServiceState getServiceState(int subId) {
         return mServiceStates.get(subId);
     }
 
-    public int getFailedUnlockAttempts(int userId) {
-        return mFailedAttempts.get(userId, 0);
-    }
-
-    public void reportFailedStrongAuthUnlockAttempt(int userId) {
-        mFailedAttempts.put(userId, getFailedUnlockAttempts(userId) + 1);
-    }
-
     public void clearBiometricRecognized() {
         mUserFingerprintAuthenticated.clear();
         mUserFaceAuthenticated.clear();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 8135ac5..f818d05 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -117,6 +117,12 @@
     public void onUserSwitchComplete(int userId) { }
 
     /**
+     * Called when the Telephony capable
+     * @param capable
+     */
+    public void onTelephonyCapable(boolean capable) { }
+
+    /**
      * Called when the SIM state changes.
      * @param slotId
      * @param simState
diff --git a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
index 5c68123..41b86a7 100644
--- a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
@@ -105,4 +105,9 @@
      * @return Message that should be displayed above the challenge.
      */
     CharSequence consumeCustomMessage();
+
+    /**
+     * Call when cancel button is pressed in bouncer.
+     */
+    void onCancelClicked();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
index 01b4254..bbc8ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
@@ -92,6 +92,11 @@
     }
 
     @Override
+    public void onUiModeChanged() {
+        inflateLayout();
+    }
+
+    @Override
     public void onLocaleListChanged() {
         inflateLayout();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 3ac6705..f6fec54 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -82,7 +82,6 @@
 
     private int mLightModeBackgroundColor;
     private int mLightModeFillColor;
-    private float mDarkIntensity;
     private int mUser;
 
     /**
@@ -146,6 +145,7 @@
                 getContext().getContentResolver().registerContentObserver(
                         Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver,
                         newUserId);
+                updateShowPercent();
             }
         };
 
@@ -320,8 +320,6 @@
 
     @Override
     public void onDarkChanged(Rect area, float darkIntensity, int tint) {
-        mDarkIntensity = darkIntensity;
-
         float intensity = DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0;
         mNonAdaptedForegroundColor = getColorForDarkIntensity(
                 intensity, mLightModeFillColor, mDarkModeFillColor);
@@ -341,14 +339,6 @@
         }
     }
 
-    public void setFillColor(int color) {
-        if (mLightModeFillColor == color) {
-            return;
-        }
-        mLightModeFillColor = color;
-        onDarkChanged(new Rect(), mDarkIntensity, DarkIconDispatcher.DEFAULT_ICON_TINT);
-    }
-
     private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
         return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 9c9f021..2dd54aa 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -23,6 +23,7 @@
 import android.os.Process;
 import android.os.ServiceManager;
 import android.util.ArrayMap;
+import android.util.DisplayMetrics;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
 
@@ -46,16 +47,17 @@
 import com.android.systemui.power.EnhancedEstimatesImpl;
 import com.android.systemui.power.PowerNotificationWarnings;
 import com.android.systemui.power.PowerUI;
-import com.android.systemui.statusbar.AppOpsListener;
+import com.android.systemui.statusbar.notification.AppOpsListener;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
 import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
-import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -258,8 +260,8 @@
         mProviders.put(TunerService.class, () ->
                 new TunerServiceImpl(mContext));
 
-        mProviders.put(StatusBarWindowManager.class, () ->
-                new StatusBarWindowManager(mContext));
+        mProviders.put(StatusBarWindowController.class, () ->
+                new StatusBarWindowController(mContext));
 
         mProviders.put(DarkIconDispatcher.class, () ->
                 new DarkIconDispatcherImpl(mContext));
@@ -328,6 +330,12 @@
         mProviders.put(IStatusBarService.class, () -> IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE)));
 
+        // Single instance of DisplayMetrics, gets updated by StatusBar, but can be used
+        // anywhere it is needed.
+        mProviders.put(DisplayMetrics.class, () -> new DisplayMetrics());
+
+        mProviders.put(LockscreenGestureLogger.class, () -> new LockscreenGestureLogger());
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
 
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 377fab5..f5ad747 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -32,8 +32,8 @@
 import android.view.ViewConfiguration;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 7742c55..198a4e6 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -28,6 +28,7 @@
 import android.view.ViewOutlineProvider;
 import android.view.ViewTreeObserver;
 import android.widget.LinearLayout;
+
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.leak.RotationUtils;
@@ -41,14 +42,15 @@
     private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
     private static final String ROUNDED_DIVIDER = "sysui_hwui_rounded_divider";
     private final int[] mTmp2 = new int[2];
-    private View mChild;
+    private View mList;
     private View mSeparatedView;
     private int mOldHeight;
     private boolean mAnimating;
     private AnimatorSet mAnimation;
     private View mDivision;
     private boolean mHasOutsideTouch;
-    private HardwareBgDrawable mBackground;
+    private HardwareBgDrawable mListBackground;
+    private HardwareBgDrawable mSeparatedViewBackground;
     private Animator mAnimator;
     private boolean mCollapse;
     private boolean mHasSeparatedButton;
@@ -90,17 +92,19 @@
         mRoundedDivider = Settings.Secure.getInt(getContext().getContentResolver(),
                 ROUNDED_DIVIDER, 0) != 0;
         updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
-        mBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext());
-        if (mChild != null) {
-            mChild.setBackground(mBackground);
-            mSeparatedView.setBackground(mBackground);
+        mListBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext());
+        mSeparatedViewBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed,
+                getContext());
+        if (mList != null) {
+            mList.setBackground(mListBackground);
+            mSeparatedView.setBackground(mSeparatedViewBackground);
             requestLayout();
         }
     }
 
     private void updateEdgeMargin(int edge) {
-        if (mChild != null) {
-            MarginLayoutParams params = (MarginLayoutParams) mChild.getLayoutParams();
+        if (mList != null) {
+            MarginLayoutParams params = (MarginLayoutParams) mList.getLayoutParams();
             if (mRotation == ROTATION_LANDSCAPE) {
                 params.topMargin = edge;
             } else if (mRotation == ROTATION_SEASCAPE) {
@@ -108,7 +112,7 @@
             } else {
                 params.rightMargin = edge;
             }
-            mChild.setLayoutParams(params);
+            mList.setLayoutParams(params);
         }
 
         if (mSeparatedView != null) {
@@ -131,15 +135,15 @@
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        if (mChild == null) {
+        if (mList == null) {
             if (getChildCount() != 0) {
-                mChild = getChildAt(0);
-                mChild.setBackground(mBackground);
+                mList = getChildAt(0);
+                mList.setBackground(mListBackground);
                 mSeparatedView = getChildAt(1);
-                mSeparatedView.setBackground(mBackground);
+                mSeparatedView.setBackground(mSeparatedViewBackground);
                 updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
-                mOldHeight = mChild.getMeasuredHeight();
-                mChild.addOnLayoutChangeListener(
+                mOldHeight = mList.getMeasuredHeight();
+                mList.addOnLayoutChangeListener(
                         (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
                                 updatePosition());
                 updateRotation();
@@ -147,7 +151,7 @@
                 return;
             }
         }
-        int newHeight = mChild.getMeasuredHeight();
+        int newHeight = mList.getMeasuredHeight();
         if (newHeight != mOldHeight) {
             animateChild(mOldHeight, newHeight);
         }
@@ -196,27 +200,29 @@
             }
         }
         if (to != ROTATION_NONE) {
-            if (mChild instanceof LinearLayout) {
+            if (mList instanceof LinearLayout) {
                 mRotatedBackground = true;
-                mBackground.setRotatedBackground(true);
-                LinearLayout linearLayout = (LinearLayout) mChild;
+                mListBackground.setRotatedBackground(true);
+                mSeparatedViewBackground.setRotatedBackground(true);
+                LinearLayout linearLayout = (LinearLayout) mList;
                 if (mSwapOrientation) {
                     linearLayout.setOrientation(LinearLayout.HORIZONTAL);
                     setOrientation(LinearLayout.HORIZONTAL);
                 }
-                swapDimens(mChild);
+                swapDimens(mList);
                 swapDimens(mSeparatedView);
             }
         } else {
-            if (mChild instanceof LinearLayout) {
+            if (mList instanceof LinearLayout) {
                 mRotatedBackground = false;
-                mBackground.setRotatedBackground(false);
-                LinearLayout linearLayout = (LinearLayout) mChild;
+                mListBackground.setRotatedBackground(false);
+                mSeparatedViewBackground.setRotatedBackground(false);
+                LinearLayout linearLayout = (LinearLayout) mList;
                 if (mSwapOrientation) {
                     linearLayout.setOrientation(LinearLayout.VERTICAL);
                     setOrientation(LinearLayout.VERTICAL);
                 }
-                swapDimens(mChild);
+                swapDimens(mList);
                 swapDimens(mSeparatedView);
             }
         }
@@ -224,12 +230,12 @@
 
     private void rotateRight() {
         rotateRight(this);
-        rotateRight(mChild);
+        rotateRight(mList);
         swapDimens(this);
 
-        LayoutParams p = (LayoutParams) mChild.getLayoutParams();
+        LayoutParams p = (LayoutParams) mList.getLayoutParams();
         p.gravity = rotateGravityRight(p.gravity);
-        mChild.setLayoutParams(p);
+        mList.setLayoutParams(p);
 
         LayoutParams separatedViewLayoutParams = (LayoutParams) mSeparatedView.getLayoutParams();
         separatedViewLayoutParams.gravity = rotateGravityRight(separatedViewLayoutParams.gravity);
@@ -282,12 +288,12 @@
 
     private void rotateLeft() {
         rotateLeft(this);
-        rotateLeft(mChild);
+        rotateLeft(mList);
         swapDimens(this);
 
-        LayoutParams p = (LayoutParams) mChild.getLayoutParams();
+        LayoutParams p = (LayoutParams) mList.getLayoutParams();
         p.gravity = rotateGravityLeft(p.gravity);
-        mChild.setLayoutParams(p);
+        mList.setLayoutParams(p);
 
         LayoutParams separatedViewLayoutParams = (LayoutParams) mSeparatedView.getLayoutParams();
         separatedViewLayoutParams.gravity = rotateGravityLeft(separatedViewLayoutParams.gravity);
@@ -379,14 +385,14 @@
                 mAnimating = false;
             }
         });
-        int fromTop = mChild.getTop();
-        int fromBottom = mChild.getBottom();
+        int fromTop = mList.getTop();
+        int fromBottom = mList.getBottom();
         int toTop = fromTop - ((newHeight - oldHeight) / 2);
         int toBottom = fromBottom + ((newHeight - oldHeight) / 2);
-        ObjectAnimator top = ObjectAnimator.ofInt(mChild, "top", fromTop, toTop);
-        top.addUpdateListener(animation -> mBackground.invalidateSelf());
+        ObjectAnimator top = ObjectAnimator.ofInt(mList, "top", fromTop, toTop);
+        top.addUpdateListener(animation -> mListBackground.invalidateSelf());
         mAnimation.playTogether(top,
-                ObjectAnimator.ofInt(mChild, "bottom", fromBottom, toBottom));
+                ObjectAnimator.ofInt(mList, "bottom", fromBottom, toBottom));
     }
 
     public void setDivisionView(View v) {
@@ -400,29 +406,30 @@
     }
 
     private void updatePosition() {
-        if (mChild == null) return;
+        if (mList == null) return;
         // If got separated button, setRotatedBackground to false,
         // all items won't get white background.
-        mBackground.setRotatedBackground(mHasSeparatedButton);
+        mListBackground.setRotatedBackground(mHasSeparatedButton);
+        mSeparatedViewBackground.setRotatedBackground(mHasSeparatedButton);
         if (mDivision != null && mDivision.getVisibility() == VISIBLE) {
             int index = mRotatedBackground ? 0 : 1;
             mDivision.getLocationOnScreen(mTmp2);
             float trans = mRotatedBackground ? mDivision.getTranslationX()
                     : mDivision.getTranslationY();
             int viewTop = (int) (mTmp2[index] + trans);
-            mChild.getLocationOnScreen(mTmp2);
+            mList.getLocationOnScreen(mTmp2);
             viewTop -= mTmp2[index];
             setCutPoint(viewTop);
         } else {
-            setCutPoint(mChild.getMeasuredHeight());
+            setCutPoint(mList.getMeasuredHeight());
         }
     }
 
     private void setCutPoint(int point) {
-        int curPoint = mBackground.getCutPoint();
+        int curPoint = mListBackground.getCutPoint();
         if (curPoint == point) return;
         if (getAlpha() == 0 || curPoint == 0) {
-            mBackground.setCutPoint(point);
+            mListBackground.setCutPoint(point);
             return;
         }
         if (mAnimator != null) {
@@ -432,7 +439,7 @@
             mAnimator.cancel();
         }
         mEndPoint = point;
-        mAnimator = ObjectAnimator.ofInt(mBackground, "cutPoint", curPoint, point);
+        mAnimator = ObjectAnimator.ofInt(mListBackground, "cutPoint", curPoint, point);
         if (mCollapse) {
             mAnimator.setStartDelay(300);
             mCollapse = false;
@@ -470,14 +477,14 @@
     }
 
     private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
-        if (mHasOutsideTouch || (mChild == null)) {
+        if (mHasOutsideTouch || (mList == null)) {
             inoutInfo.setTouchableInsets(
                     ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
             return;
         }
         inoutInfo.setTouchableInsets(
                 ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT);
-        inoutInfo.contentInsets.set(mChild.getLeft(), mChild.getTop(),
-                0, getBottom() - mChild.getBottom());
+        inoutInfo.contentInsets.set(mList.getLeft(), mList.getTop(),
+                0, getBottom() - mList.getBottom());
     };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 50d862d..acc7b49 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -30,6 +30,7 @@
 import android.util.Log;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.DisplayListCanvas;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.WindowManager;
@@ -273,7 +274,9 @@
                 // Sometimes a wallpaper is not large enough to cover the screen in one dimension.
                 // Call updateSurfaceSize -- it will only actually do the update if the dimensions
                 // should change
-                if (newRotation != mLastRotation) {
+                if (newRotation != mLastRotation
+                        || mDisplayWidthAtLastSurfaceSizeUpdate != displayInfo.logicalWidth
+                        || mDisplayHeightAtLastSurfaceSizeUpdate != displayInfo.logicalHeight) {
                     // Update surface size (if necessary)
                     if (!updateSurfaceSize(getSurfaceHolder(), displayInfo, true /* forDraw */)) {
                         return; // had to reload wallpaper, will retry later
@@ -366,7 +369,12 @@
                 protected Bitmap doInBackground(Void... params) {
                     Throwable exception;
                     try {
-                        return mWallpaperManager.getBitmap(true /* hardware */);
+                        Bitmap wallpaper = mWallpaperManager.getBitmap(true /* hardware */);
+                        if (wallpaper != null
+                                && wallpaper.getByteCount() > DisplayListCanvas.MAX_BITMAP_SIZE) {
+                            throw new RuntimeException("Wallpaper is too large to draw!");
+                        }
+                        return wallpaper;
                     } catch (RuntimeException | OutOfMemoryError e) {
                         exception = e;
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/Interpolators.java b/packages/SystemUI/src/com/android/systemui/Interpolators.java
index aeef496..2b3ea3a 100644
--- a/packages/SystemUI/src/com/android/systemui/Interpolators.java
+++ b/packages/SystemUI/src/com/android/systemui/Interpolators.java
@@ -24,13 +24,20 @@
 import android.view.animation.LinearInterpolator;
 import android.view.animation.PathInterpolator;
 
-import com.android.systemui.statusbar.stack.HeadsUpAppearInterpolator;
+import com.android.systemui.statusbar.notification.stack.HeadsUpAppearInterpolator;
 
 /**
  * Utility class to receive interpolators from
  */
 public class Interpolators {
     public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
+
+    /**
+     * Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t
+     * goes from 1 to 0 instead of 0 to 1).
+     */
+    public static final Interpolator FAST_OUT_SLOW_IN_REVERSE =
+            new PathInterpolator(0.8f, 0f, 0.6f, 1f);
     public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
     public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
     public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
@@ -51,4 +58,11 @@
      */
     public static final Interpolator TOUCH_RESPONSE =
             new PathInterpolator(0.3f, 0f, 0.1f, 1f);
+
+    /**
+     * Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t
+     * goes from 1 to 0 instead of 0 to 1).
+     */
+    public static final Interpolator TOUCH_RESPONSE_REVERSE =
+            new PathInterpolator(0.9f, 0f, 0.7f, 1f);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 1e5b77e..bd2b7a5 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -30,8 +30,9 @@
 import android.os.PatternMatcher;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Log;
-import android.view.SurfaceControl;
+import android.view.MotionEvent;
 
 import com.android.systemui.OverviewProxyService.OverviewProxyListener;
 import com.android.systemui.recents.events.EventBus;
@@ -40,7 +41,6 @@
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.GraphicBufferCompat;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.CallbackController;
@@ -54,6 +54,7 @@
 
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
 import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
 
 /**
@@ -68,6 +69,13 @@
     private static final long BACKOFF_MILLIS = 1000;
     private static final long DEFERRED_CALLBACK_MILLIS = 5000;
 
+    // Max backoff caps at 5 mins
+    private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;
+
+    // Default interaction flags if swipe up is disabled before connecting to launcher
+    private static final int DEFAULT_DISABLE_SWIPE_UP_STATE = FLAG_DISABLE_SWIPE_UP
+            | FLAG_SHOW_OVERVIEW_BUTTON;
+
     private final Context mContext;
     private final Handler mHandler;
     private final Runnable mConnectionRunnable = this::internalConnectToCurrentUser;
@@ -81,25 +89,19 @@
     private int mConnectionBackoffAttempts;
     private @InteractionType int mInteractionFlags;
     private boolean mIsEnabled;
+    private int mCurrentBoundedUserId = -1;
+    private float mBackButtonAlpha;
 
     private ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
 
-        public GraphicBufferCompat screenshot(Rect sourceCrop, int width, int height, int minLayer,
-                int maxLayer, boolean useIdentityTransform, int rotation) {
-            long token = Binder.clearCallingIdentity();
-            try {
-                return new GraphicBufferCompat(SurfaceControl.screenshotToBuffer(sourceCrop, width,
-                        height, minLayer, maxLayer, useIdentityTransform, rotation));
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
         public void startScreenPinning(int taskId) {
+            if (!verifyCaller("startScreenPinning")) {
+                return;
+            }
             long token = Binder.clearCallingIdentity();
             try {
                 mHandler.post(() -> {
-                    StatusBar statusBar = ((SystemUIApplication) mContext).getComponent(
+                    StatusBar statusBar = SysUiServiceProvider.getComponent(mContext,
                             StatusBar.class);
                     if (statusBar != null) {
                         statusBar.showScreenPinningRequest(taskId, false /* allowCancel */);
@@ -110,7 +112,25 @@
             }
         }
 
+        public void onStatusBarMotionEvent(MotionEvent event) {
+            long token = Binder.clearCallingIdentity();
+            try {
+                // TODO move this logic to message queue
+                mHandler.post(()->{
+                    StatusBar bar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
+                    if (bar != null) {
+                        bar.dispatchNotificationsPanelTouchEvent(event);
+                    }
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
         public void onSplitScreenInvoked() {
+            if (!verifyCaller("onSplitScreenInvoked")) {
+                return;
+            }
             long token = Binder.clearCallingIdentity();
             try {
                 EventBus.getDefault().post(new DockedFirstAnimationFrameEvent());
@@ -120,6 +140,9 @@
         }
 
         public void onOverviewShown(boolean fromHome) {
+            if (!verifyCaller("onOverviewShown")) {
+                return;
+            }
             long token = Binder.clearCallingIdentity();
             try {
                 mHandler.post(() -> {
@@ -133,6 +156,9 @@
         }
 
         public void setInteractionState(@InteractionType int flags) {
+            if (!verifyCaller("setInteractionState")) {
+                return;
+            }
             long token = Binder.clearCallingIdentity();
             try {
                 if (mInteractionFlags != flags) {
@@ -150,9 +176,12 @@
         }
 
         public Rect getNonMinimizedSplitScreenSecondaryBounds() {
+            if (!verifyCaller("getNonMinimizedSplitScreenSecondaryBounds")) {
+                return null;
+            }
             long token = Binder.clearCallingIdentity();
             try {
-                Divider divider = ((SystemUIApplication) mContext).getComponent(Divider.class);
+                Divider divider = SysUiServiceProvider.getComponent(mContext, Divider.class);
                 if (divider != null) {
                     return divider.getView().getNonMinimizedSplitScreenSecondaryBounds();
                 }
@@ -163,8 +192,12 @@
         }
 
         public void setBackButtonAlpha(float alpha, boolean animate) {
+            if (!verifyCaller("setBackButtonAlpha")) {
+                return;
+            }
             long token = Binder.clearCallingIdentity();
             try {
+                mBackButtonAlpha = alpha;
                 mHandler.post(() -> {
                     notifyBackButtonAlphaChanged(alpha, animate);
                 });
@@ -172,12 +205,22 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        private boolean verifyCaller(String reason) {
+            final int callerId = Binder.getCallingUserHandle().getIdentifier();
+            if (callerId != mCurrentBoundedUserId) {
+                Log.w(TAG_OPS, "Launcher called sysui with invalid user: " + callerId + ", reason: "
+                        + reason);
+                return false;
+            }
+            return true;
+        }
     };
 
     private final Runnable mDeferredConnectionCallback = () -> {
         Log.w(TAG_OPS, "Binder supposed established connection but actual connection to service "
             + "timed out, trying again");
-        internalConnectToCurrentUser();
+        retryConnectionWithBackoff();
     };
 
     private final BroadcastReceiver mLauncherStateChangedReceiver = new BroadcastReceiver() {
@@ -187,7 +230,7 @@
 
             // When launcher service is disabled, reset interaction flags because it is inactive
             if (!isEnabled()) {
-                mInteractionFlags = 0;
+                mInteractionFlags = getDefaultInteractionFlags();
                 Prefs.remove(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS);
             }
 
@@ -210,7 +253,9 @@
             }
             try {
                 mOverviewProxy.onBind(mSysUiProxy);
+                mCurrentBoundedUserId = mDeviceProvisionedController.getCurrentUser();
             } catch (RemoteException e) {
+                mCurrentBoundedUserId = -1;
                 Log.e(TAG_OPS, "Failed to call onBind()", e);
             }
             notifyConnectionChanged();
@@ -219,18 +264,21 @@
         @Override
         public void onNullBinding(ComponentName name) {
             Log.w(TAG_OPS, "Null binding of '" + name + "', try reconnecting");
-            internalConnectToCurrentUser();
+            mCurrentBoundedUserId = -1;
+            retryConnectionWithBackoff();
         }
 
         @Override
         public void onBindingDied(ComponentName name) {
             Log.w(TAG_OPS, "Binding died of '" + name + "', try reconnecting");
-            internalConnectToCurrentUser();
+            mCurrentBoundedUserId = -1;
+            retryConnectionWithBackoff();
         }
 
         @Override
         public void onServiceDisconnected(ComponentName name) {
             // Do nothing
+            mCurrentBoundedUserId = -1;
         }
     };
 
@@ -262,7 +310,8 @@
                 com.android.internal.R.string.config_recentsComponentName));
         mQuickStepIntent = new Intent(ACTION_QUICKSTEP)
                 .setPackage(mRecentsComponentName.getPackageName());
-        mInteractionFlags = Prefs.getInt(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS, 0);
+        mInteractionFlags = Prefs.getInt(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS,
+                getDefaultInteractionFlags());
 
         // Listen for the package update changes.
         if (SystemServicesProxy.getInstance(context)
@@ -278,6 +327,10 @@
         }
     }
 
+    public float getBackButtonAlpha() {
+        return mBackButtonAlpha;
+    }
+
     public void startConnectionToCurrentUser() {
         if (mHandler.getLooper() != Looper.myLooper()) {
             mHandler.post(mConnectionRunnable);
@@ -302,7 +355,8 @@
         boolean bound = false;
         try {
             bound = mContext.bindServiceAsUser(launcherServiceIntent,
-                    mOverviewServiceConnection, Context.BIND_AUTO_CREATE,
+                    mOverviewServiceConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                     UserHandle.of(mDeviceProvisionedController.getCurrentUser()));
         } catch (SecurityException e) {
             Log.e(TAG_OPS, "Unable to bind because of security error", e);
@@ -312,14 +366,22 @@
             mHandler.postDelayed(mDeferredConnectionCallback, DEFERRED_CALLBACK_MILLIS);
         } else {
             // Retry after exponential backoff timeout
-            final long timeoutMs = (long) Math.scalb(BACKOFF_MILLIS, mConnectionBackoffAttempts);
-            mHandler.postDelayed(mConnectionRunnable, timeoutMs);
-            mConnectionBackoffAttempts++;
-            Log.w(TAG_OPS, "Failed to connect on attempt " + mConnectionBackoffAttempts
-                    + " will try again in " + timeoutMs + "ms");
+            retryConnectionWithBackoff();
         }
     }
 
+    private void retryConnectionWithBackoff() {
+        if (mHandler.hasCallbacks(mConnectionRunnable)) {
+            return;
+        }
+        final long timeoutMs = (long) Math.min(
+                Math.scalb(BACKOFF_MILLIS, mConnectionBackoffAttempts), MAX_BACKOFF_MILLIS);
+        mHandler.postDelayed(mConnectionRunnable, timeoutMs);
+        mConnectionBackoffAttempts++;
+        Log.w(TAG_OPS, "Failed to connect on attempt " + mConnectionBackoffAttempts
+                + " will try again in " + timeoutMs + "ms");
+    }
+
     @Override
     public void addCallback(OverviewProxyListener listener) {
         mConnectionCallbacks.add(listener);
@@ -358,6 +420,15 @@
         }
     }
 
+    private int getDefaultInteractionFlags() {
+        // If there is no settings available use device default or get it from settings
+        final boolean defaultState = getSwipeUpDefaultValue();
+        final boolean swipeUpEnabled = getSwipeUpSettingAvailable()
+                ? getSwipeUpEnabledFromSettings(defaultState)
+                : defaultState;
+        return swipeUpEnabled ? 0 : DEFAULT_DISABLE_SWIPE_UP_STATE;
+    }
+
     private void notifyBackButtonAlphaChanged(float alpha, boolean animate) {
         for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
             mConnectionCallbacks.get(i).onBackButtonAlphaChanged(alpha, animate);
@@ -388,17 +459,38 @@
                 ActivityManagerWrapper.getInstance().getCurrentUserId()) != null;
     }
 
+    private boolean getSwipeUpDefaultValue() {
+        return mContext.getResources()
+                .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_default);
+    }
+
+    private boolean getSwipeUpSettingAvailable() {
+        return mContext.getResources()
+                .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_setting_available);
+    }
+
+    private boolean getSwipeUpEnabledFromSettings(boolean defaultValue) {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, defaultValue ? 1 : 0) == 1;
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println(TAG_OPS + " state:");
-        pw.print("  mConnectionBackoffAttempts="); pw.println(mConnectionBackoffAttempts);
+        pw.print("  recentsComponentName="); pw.println(mRecentsComponentName);
+        pw.print("  isConnected="); pw.println(mOverviewProxy != null);
         pw.print("  isCurrentUserSetup="); pw.println(mDeviceProvisionedController
                 .isCurrentUserSetup());
-        pw.print("  isConnected="); pw.println(mOverviewProxy != null);
-        pw.print("  mRecentsComponentName="); pw.println(mRecentsComponentName);
-        pw.print("  mIsEnabled="); pw.println(isEnabled());
-        pw.print("  mInteractionFlags="); pw.println(mInteractionFlags);
-        pw.print("  mQuickStepIntent="); pw.println(mQuickStepIntent);
+        pw.print("  connectionBackoffAttempts="); pw.println(mConnectionBackoffAttempts);
+        pw.print("  interactionFlags="); pw.println(mInteractionFlags);
+
+        pw.print("  quickStepIntent="); pw.println(mQuickStepIntent);
+        pw.print("  quickStepIntentResolved="); pw.println(isEnabled());
+
+        final boolean swipeUpDefaultValue = getSwipeUpDefaultValue();
+        final boolean swipeUpEnabled = getSwipeUpEnabledFromSettings(swipeUpDefaultValue);
+        pw.print("  swipeUpSetting="); pw.println(swipeUpEnabled);
+        pw.print("  swipeUpSettingDefault="); pw.println(swipeUpDefaultValue);
     }
 
     public interface OverviewProxyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index bbbc71f..044cc5c 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -43,9 +43,12 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.SystemProperties;
 import android.provider.Settings.Secure;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 import android.view.Gravity;
@@ -55,10 +58,12 @@
 import android.view.View.OnLayoutChangeListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import com.android.internal.util.Preconditions;
 import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
@@ -78,6 +83,9 @@
  * for antialiasing and emulation purposes.
  */
 public class ScreenDecorations extends SystemUI implements Tunable {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "ScreenDecorations";
+
     public static final String SIZE = "sysui_rounded_size";
     public static final String PADDING = "sysui_rounded_content_padding";
     private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
@@ -86,9 +94,9 @@
     private DisplayManager mDisplayManager;
     private DisplayManager.DisplayListener mDisplayListener;
 
-    private int mRoundedDefault;
-    private int mRoundedDefaultTop;
-    private int mRoundedDefaultBottom;
+    @VisibleForTesting protected int mRoundedDefault;
+    @VisibleForTesting protected int mRoundedDefaultTop;
+    @VisibleForTesting protected int mRoundedDefaultBottom;
     private View mOverlay;
     private View mBottomOverlay;
     private float mDensity;
@@ -97,26 +105,31 @@
     private DisplayCutoutView mCutoutTop;
     private DisplayCutoutView mCutoutBottom;
     private SecureSetting mColorInversionSetting;
+    private boolean mPendingRotationChange;
+    private Handler mHandler;
 
     @Override
     public void start() {
+        mHandler = startHandlerThread();
+        mHandler.post(this::startOnScreenDecorationsThread);
+        setupStatusBarPaddingIfNeeded();
+    }
+
+    @VisibleForTesting
+    Handler startHandlerThread() {
+        HandlerThread thread = new HandlerThread("ScreenDecorations");
+        thread.start();
+        return thread.getThreadHandler();
+    }
+
+    private void startOnScreenDecorationsThread() {
+        mRotation = RotationUtils.getExactRotation(mContext);
         mWindowManager = mContext.getSystemService(WindowManager.class);
-        mRoundedDefault = mContext.getResources().getDimensionPixelSize(
-                R.dimen.rounded_corner_radius);
-        mRoundedDefaultTop = mContext.getResources().getDimensionPixelSize(
-                R.dimen.rounded_corner_radius_top);
-        mRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize(
-                R.dimen.rounded_corner_radius_bottom);
+        updateRoundedCornerRadii();
         if (hasRoundedCorners() || shouldDrawCutout()) {
             setupDecorations();
         }
 
-        int padding = mContext.getResources().getDimensionPixelSize(
-                R.dimen.rounded_corner_content_padding);
-        if (padding != 0) {
-            setupPadding(padding);
-        }
-
         mDisplayListener = new DisplayManager.DisplayListener() {
             @Override
             public void onDisplayAdded(int displayId) {
@@ -130,26 +143,46 @@
 
             @Override
             public void onDisplayChanged(int displayId) {
+                final int newRotation = RotationUtils.getExactRotation(mContext);
+                if (mOverlay != null && mBottomOverlay != null && mRotation != newRotation) {
+                    // We cannot immediately update the orientation. Otherwise
+                    // WindowManager is still deferring layout until it has finished dispatching
+                    // the config changes, which may cause divergence between what we draw
+                    // (new orientation), and where we are placed on the screen (old orientation).
+                    // Instead we wait until either:
+                    // - we are trying to redraw. This because WM resized our window and told us to.
+                    // - the config change has been dispatched, so WM is no longer deferring layout.
+                    mPendingRotationChange = true;
+                    if (DEBUG) {
+                        Log.i(TAG, "Rotation changed, deferring " + newRotation + ", staying at "
+                                + mRotation);
+                    }
+
+                    mOverlay.getViewTreeObserver().addOnPreDrawListener(
+                            new RestartingPreDrawListener(mOverlay, newRotation));
+                    mBottomOverlay.getViewTreeObserver().addOnPreDrawListener(
+                            new RestartingPreDrawListener(mBottomOverlay, newRotation));
+                }
                 updateOrientation();
             }
         };
 
-        mRotation = -1;
         mDisplayManager = (DisplayManager) mContext.getSystemService(
                 Context.DISPLAY_SERVICE);
-        mDisplayManager.registerDisplayListener(mDisplayListener, null);
+        mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
+        updateOrientation();
     }
 
     private void setupDecorations() {
         mOverlay = LayoutInflater.from(mContext)
                 .inflate(R.layout.rounded_corners, null);
         mCutoutTop = new DisplayCutoutView(mContext, true,
-                this::updateWindowVisibilities);
+                this::updateWindowVisibilities, this);
         ((ViewGroup)mOverlay).addView(mCutoutTop);
         mBottomOverlay = LayoutInflater.from(mContext)
                 .inflate(R.layout.rounded_corners, null);
         mCutoutBottom = new DisplayCutoutView(mContext, false,
-                this::updateWindowVisibilities);
+                this::updateWindowVisibilities, this);
         ((ViewGroup)mBottomOverlay).addView(mCutoutBottom);
 
         mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
@@ -167,10 +200,11 @@
         mWindowManager.getDefaultDisplay().getMetrics(metrics);
         mDensity = metrics.density;
 
-        Dependency.get(TunerService.class).addTunable(this, SIZE);
+        Dependency.get(Dependency.MAIN_HANDLER).post(
+                () -> Dependency.get(TunerService.class).addTunable(this, SIZE));
 
         // Watch color inversion and invert the overlay as needed.
-        mColorInversionSetting = new SecureSetting(mContext, Dependency.get(Dependency.MAIN_HANDLER),
+        mColorInversionSetting = new SecureSetting(mContext, mHandler,
                 Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
             @Override
             protected void handleValueChanged(int value, boolean observedChange) {
@@ -182,7 +216,7 @@
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_USER_SWITCHED);
-        mContext.registerReceiver(mIntentReceiver, filter);
+        mContext.registerReceiver(mIntentReceiver, filter, null /* permission */, mHandler);
 
         mOverlay.addOnLayoutChangeListener(new OnLayoutChangeListener() {
             @Override
@@ -200,6 +234,11 @@
                         .start();
             }
         });
+
+        mOverlay.getViewTreeObserver().addOnPreDrawListener(
+                new ValidatingPreDrawListener(mOverlay));
+        mBottomOverlay.getViewTreeObserver().addOnPreDrawListener(
+                new ValidatingPreDrawListener(mBottomOverlay));
     }
 
     private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -229,13 +268,32 @@
 
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
-        updateOrientation();
-        if (shouldDrawCutout() && mOverlay == null) {
-            setupDecorations();
-        }
+        mHandler.post(() -> {
+            int oldRotation = mRotation;
+            mPendingRotationChange = false;
+            updateOrientation();
+            updateRoundedCornerRadii();
+            if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
+            if (shouldDrawCutout() && mOverlay == null) {
+                setupDecorations();
+            }
+            if (mOverlay != null) {
+                // Updating the layout params ensures that ViewRootImpl will call relayoutWindow(),
+                // which ensures that the forced seamless rotation will end, even if we updated
+                // the rotation before window manager was ready (and was still waiting for sending
+                // the updated rotation).
+                updateLayoutParams();
+            }
+        });
     }
 
-    protected void updateOrientation() {
+    private void updateOrientation() {
+        Preconditions.checkState(mHandler.getLooper().getThread() == Thread.currentThread(),
+                "must call on " + mHandler.getLooper().getThread()
+                        + ", but was " + Thread.currentThread());
+        if (mPendingRotationChange) {
+            return;
+        }
         int newRotation = RotationUtils.getExactRotation(mContext);
         if (newRotation != mRotation) {
             mRotation = newRotation;
@@ -247,6 +305,26 @@
         }
     }
 
+    private void updateRoundedCornerRadii() {
+        final int newRoundedDefault = mContext.getResources().getDimensionPixelSize(
+                R.dimen.rounded_corner_radius);
+        final int newRoundedDefaultTop = mContext.getResources().getDimensionPixelSize(
+                R.dimen.rounded_corner_radius_top);
+        final int newRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize(
+                R.dimen.rounded_corner_radius_bottom);
+
+        final boolean roundedCornersChanged = mRoundedDefault != newRoundedDefault
+                || mRoundedDefaultBottom != newRoundedDefaultBottom
+                || mRoundedDefaultTop != newRoundedDefaultTop;
+
+        if (roundedCornersChanged) {
+            mRoundedDefault = newRoundedDefault;
+            mRoundedDefaultTop = newRoundedDefaultTop;
+            mRoundedDefaultBottom = newRoundedDefaultBottom;
+            onTuningChanged(SIZE, null);
+        }
+    }
+
     private void updateViews() {
         View topLeft = mOverlay.findViewById(R.id.left);
         View topRight = mOverlay.findViewById(R.id.right);
@@ -312,7 +390,19 @@
                 com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout);
     }
 
-    private void setupPadding(int padding) {
+
+    private void setupStatusBarPaddingIfNeeded() {
+        // TODO: This should be moved to a more appropriate place, as it is not related to the
+        // screen decorations overlay.
+        int padding = mContext.getResources().getDimensionPixelSize(
+                R.dimen.rounded_corner_content_padding);
+        if (padding != 0) {
+            setupStatusBarPadding(padding);
+        }
+
+    }
+
+    private void setupStatusBarPadding(int padding) {
         // Add some padding to all the content near the edge of the screen.
         StatusBar sb = getComponent(StatusBar.class);
         View statusBar = (sb != null ? sb.getStatusBarWindow() : null);
@@ -381,30 +471,32 @@
 
     @Override
     public void onTuningChanged(String key, String newValue) {
-        if (mOverlay == null) return;
-        if (SIZE.equals(key)) {
-            int size = mRoundedDefault;
-            int sizeTop = mRoundedDefaultTop;
-            int sizeBottom = mRoundedDefaultBottom;
-            if (newValue != null) {
-                try {
-                    size = (int) (Integer.parseInt(newValue) * mDensity);
-                } catch (Exception e) {
+        mHandler.post(() -> {
+            if (mOverlay == null) return;
+            if (SIZE.equals(key)) {
+                int size = mRoundedDefault;
+                int sizeTop = mRoundedDefaultTop;
+                int sizeBottom = mRoundedDefaultBottom;
+                if (newValue != null) {
+                    try {
+                        size = (int) (Integer.parseInt(newValue) * mDensity);
+                    } catch (Exception e) {
+                    }
                 }
-            }
 
-            if (sizeTop == 0) {
-                sizeTop = size;
-            }
-            if (sizeBottom == 0) {
-                sizeBottom = size;
-            }
+                if (sizeTop == 0) {
+                    sizeTop = size;
+                }
+                if (sizeBottom == 0) {
+                    sizeBottom = size;
+                }
 
-            setSize(mOverlay.findViewById(R.id.left), sizeTop);
-            setSize(mOverlay.findViewById(R.id.right), sizeTop);
-            setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom);
-            setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom);
-        }
+                setSize(mOverlay.findViewById(R.id.left), sizeTop);
+                setSize(mOverlay.findViewById(R.id.right), sizeTop);
+                setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom);
+                setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom);
+            }
+        });
     }
 
     private void setSize(View view, int pixelSize) {
@@ -451,16 +543,23 @@
         private final int[] mLocation = new int[2];
         private final boolean mInitialStart;
         private final Runnable mVisibilityChangedListener;
+        private final ScreenDecorations mDecorations;
         private int mColor = Color.BLACK;
         private boolean mStart;
         private int mRotation;
 
         public DisplayCutoutView(Context context, boolean start,
-                Runnable visibilityChangedListener) {
+                Runnable visibilityChangedListener, ScreenDecorations decorations) {
             super(context);
             mInitialStart = start;
             mVisibilityChangedListener = visibilityChangedListener;
+            mDecorations = decorations;
             setId(R.id.display_cutout);
+            if (DEBUG) {
+                getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
+                        (mInitialStart ? "OverlayTop" : "OverlayBottom")
+                                + " drawn in rot " + mRotation));
+            }
         }
 
         public void setColor(int color) {
@@ -522,10 +621,10 @@
         }
 
         private void update() {
-            mStart = isStart();
-            if (!isAttachedToWindow()) {
+            if (!isAttachedToWindow() || mDecorations.mPendingRotationChange) {
                 return;
             }
+            mStart = isStart();
             requestLayout();
             getDisplay().getDisplayInfo(mInfo);
             mBounds.setEmpty();
@@ -688,4 +787,74 @@
         return rotation == RotationUtils.ROTATION_LANDSCAPE || rotation ==
                 RotationUtils.ROTATION_SEASCAPE;
     }
+
+    /**
+     * A pre-draw listener, that cancels the draw and restarts the traversal with the updated
+     * window attributes.
+     */
+    private class RestartingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
+
+        private final View mView;
+        private final int mTargetRotation;
+
+        private RestartingPreDrawListener(View view, int targetRotation) {
+            mView = view;
+            mTargetRotation = targetRotation;
+        }
+
+        @Override
+        public boolean onPreDraw() {
+            mView.getViewTreeObserver().removeOnPreDrawListener(this);
+
+            if (mTargetRotation == mRotation) {
+                if (DEBUG) {
+                    Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom")
+                            + " already in target rot "
+                            + mTargetRotation + ", allow draw without restarting it");
+                }
+                return true;
+            }
+
+            mPendingRotationChange = false;
+            // This changes the window attributes - we need to restart the traversal for them to
+            // take effect.
+            updateOrientation();
+            if (DEBUG) {
+                Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom")
+                        + " restarting listener fired, restarting draw for rot " + mRotation);
+            }
+            mView.invalidate();
+            return false;
+        }
+    }
+
+    /**
+     * A pre-draw listener, that validates that the rotation we draw in matches the displays
+     * rotation before continuing the draw.
+     *
+     * This is to prevent a race condition, where we have not received the display changed event
+     * yet, and would thus draw in an old orientation.
+     */
+    private class ValidatingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
+
+        private final View mView;
+
+        public ValidatingPreDrawListener(View view) {
+            mView = view;
+        }
+
+        @Override
+        public boolean onPreDraw() {
+            final int displayRotation = RotationUtils.getExactRotation(mContext);
+            if (displayRotation != mRotation && !mPendingRotationChange) {
+                if (DEBUG) {
+                    Log.i(TAG, "Drawing rot " + mRotation + ", but display is at rot "
+                            + displayRotation + ". Restarting draw");
+                }
+                mView.invalidate();
+                return false;
+            }
+            return true;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index a64ce29..a3b5395 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -35,8 +35,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
 public class SwipeHelper implements Gefingerpoken {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 4e7c3ab..b96a604 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -36,7 +36,7 @@
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.util.NotificationChannels;
 
 import java.util.HashMap;
@@ -210,9 +210,9 @@
                         if (mOverlays == null) mOverlays = new ArraySet<>();
                         if (plugin.holdStatusBarOpen()) {
                             mOverlays.add(plugin);
-                            Dependency.get(StatusBarWindowManager.class).setStateListener(b ->
+                            Dependency.get(StatusBarWindowController.class).setStateListener(b ->
                                     mOverlays.forEach(o -> o.setCollapseDesired(b)));
-                            Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
+                            Dependency.get(StatusBarWindowController.class).setForcePluginOpen(
                                     mOverlays.size() != 0);
 
                         }
@@ -221,7 +221,7 @@
                     @Override
                     public void onPluginDisconnected(OverlayPlugin plugin) {
                         mOverlays.remove(plugin);
-                        Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
+                        Dependency.get(StatusBarWindowController.class).setForcePluginOpen(
                                 mOverlays.size() != 0);
                     }
                 }, OverlayPlugin.class, true /* Allow multiple plugins */);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 03a6398..04d72ce 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -22,7 +22,6 @@
 import android.util.Log;
 import android.view.ViewGroup;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
@@ -32,12 +31,13 @@
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationBlockingHelperManager;
-import com.android.systemui.statusbar.NotificationEntryManager;
-import com.android.systemui.statusbar.NotificationGutsManager;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationLogger;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
@@ -130,6 +130,7 @@
 
     public void injectDependencies(ArrayMap<Object, DependencyProvider> providers,
             Context context) {
+        providers.put(StatusBarStateController.class, StatusBarStateController::new);
         providers.put(NotificationLockscreenUserManager.class,
                 () -> new NotificationLockscreenUserManager(context));
         providers.put(VisualStabilityManager.class, VisualStabilityManager::new);
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
index f8b73a1..d6472b7 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
@@ -101,31 +101,31 @@
 
     public Session toProto() {
         Session proto = new Session();
-        proto.setStartTimestampMillis(mStartTimestampMillis);
-        proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis);
-        proto.setBuild(Build.FINGERPRINT);
-        proto.setResult(mResult);
-        proto.setType(mType);
+        proto.startTimestampMillis = mStartTimestampMillis;
+        proto.durationMillis = mEndTimestampMillis - mStartTimestampMillis;
+        proto.build = Build.FINGERPRINT;
+        proto.result = mResult;
+        proto.type = mType;
         proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
         proto.touchEvents = mMotionEvents.toArray(proto.touchEvents);
         proto.phoneEvents = mPhoneEvents.toArray(proto.phoneEvents);
-        proto.setTouchAreaWidth(mTouchAreaWidth);
-        proto.setTouchAreaHeight(mTouchAreaHeight);
+        proto.touchAreaWidth = mTouchAreaWidth;
+        proto.touchAreaHeight = mTouchAreaHeight;
         return proto;
     }
 
     private PhoneEvent phoneEventToProto(int eventType, long sysTimeNanos) {
         PhoneEvent proto = new PhoneEvent();
-        proto.setType(eventType);
-        proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos);
+        proto.type = eventType;
+        proto.timeOffsetNanos = sysTimeNanos - mStartSystemTimeNanos;
         return proto;
     }
 
     private SensorEvent sensorEventToProto(android.hardware.SensorEvent ev, long sysTimeNanos) {
         SensorEvent proto = new SensorEvent();
-        proto.setType(ev.sensor.getType());
-        proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos);
-        proto.setTimestamp(ev.timestamp);
+        proto.type = ev.sensor.getType();
+        proto.timeOffsetNanos = sysTimeNanos - mStartSystemTimeNanos;
+        proto.timestamp = ev.timestamp;
         proto.values = ev.values.clone();
         return proto;
     }
@@ -133,17 +133,17 @@
     private TouchEvent motionEventToProto(MotionEvent ev) {
         int count = ev.getPointerCount();
         TouchEvent proto = new TouchEvent();
-        proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos);
-        proto.setAction(ev.getActionMasked());
-        proto.setActionIndex(ev.getActionIndex());
+        proto.timeOffsetNanos = ev.getEventTimeNano() - mStartSystemTimeNanos;
+        proto.action = ev.getActionMasked();
+        proto.actionIndex = ev.getActionIndex();
         proto.pointers = new TouchEvent.Pointer[count];
         for (int i = 0; i < count; i++) {
             TouchEvent.Pointer p = new TouchEvent.Pointer();
-            p.setX(ev.getX(i));
-            p.setY(ev.getY(i));
-            p.setSize(ev.getSize(i));
-            p.setPressure(ev.getPressure(i));
-            p.setId(ev.getPointerId(i));
+            p.x = ev.getX(i);
+            p.y = ev.getY(i);
+            p.size = ev.getSize(i);
+            p.pressure = ev.getPressure(i);
+            p.id = ev.getPointerId(i);
             proto.pointers[i] = p;
         }
         return proto;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
new file mode 100644
index 0000000..6e62b0d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.biometrics;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.IBiometricPromptReceiver;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.android.internal.os.SomeArgs;
+import com.android.systemui.SystemUI;
+import com.android.systemui.statusbar.CommandQueue;
+
+/**
+ * Receives messages sent from AuthenticationClient and shows the appropriate biometric UI (e.g.
+ * FingerprintDialogView).
+ */
+public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callbacks {
+    private static final String TAG = "FingerprintDialogImpl";
+    private static final boolean DEBUG = true;
+
+    private static final int MSG_SHOW_DIALOG = 1;
+    private static final int MSG_BIOMETRIC_AUTHENTICATED = 2;
+    private static final int MSG_BIOMETRIC_HELP = 3;
+    private static final int MSG_BIOMETRIC_ERROR = 4;
+    private static final int MSG_HIDE_DIALOG = 5;
+    private static final int MSG_BUTTON_NEGATIVE = 6;
+    private static final int MSG_USER_CANCELED = 7;
+    private static final int MSG_BUTTON_POSITIVE = 8;
+
+    private FingerprintDialogView mDialogView;
+    private WindowManager mWindowManager;
+    private IBiometricPromptReceiver mReceiver;
+    private boolean mDialogShowing;
+    private Callback mCallback = new Callback();
+
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case MSG_SHOW_DIALOG:
+                    handleShowDialog((SomeArgs) msg.obj);
+                    break;
+                case MSG_BIOMETRIC_AUTHENTICATED:
+                    handleBiometricAuthenticated();
+                    break;
+                case MSG_BIOMETRIC_HELP:
+                    handleBiometricHelp((String) msg.obj);
+                    break;
+                case MSG_BIOMETRIC_ERROR:
+                    handleBiometricError((String) msg.obj);
+                    break;
+                case MSG_HIDE_DIALOG:
+                    handleHideDialog((Boolean) msg.obj);
+                    break;
+                case MSG_BUTTON_NEGATIVE:
+                    handleButtonNegative();
+                    break;
+                case MSG_USER_CANCELED:
+                    handleUserCanceled();
+                    break;
+                case MSG_BUTTON_POSITIVE:
+                    handleButtonPositive();
+                    break;
+            }
+        }
+    };
+
+    private class Callback implements DialogViewCallback {
+        @Override
+        public void onUserCanceled() {
+            mHandler.obtainMessage(BiometricDialogImpl.MSG_USER_CANCELED).sendToTarget();
+        }
+
+        @Override
+        public void onErrorShown() {
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_HIDE_DIALOG,
+                    false /* userCanceled */), BiometricPrompt.HIDE_DIALOG_DELAY);
+        }
+
+        @Override
+        public void onNegativePressed() {
+            mHandler.obtainMessage(BiometricDialogImpl.MSG_BUTTON_NEGATIVE).sendToTarget();
+        }
+
+        @Override
+        public void onPositivePressed() {
+            mHandler.obtainMessage(BiometricDialogImpl.MSG_BUTTON_POSITIVE).sendToTarget();
+        }
+    }
+
+    @Override
+    public void start() {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+            return;
+        }
+        getComponent(CommandQueue.class).addCallbacks(this);
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mDialogView = new FingerprintDialogView(mContext, mCallback);
+    }
+
+    @Override
+    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
+        if (DEBUG) Log.d(TAG, "showBiometricDialog");
+        // Remove these messages as they are part of the previous client
+        mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
+        mHandler.removeMessages(MSG_BIOMETRIC_HELP);
+        mHandler.removeMessages(MSG_BIOMETRIC_AUTHENTICATED);
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = bundle;
+        args.arg2 = receiver;
+        mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
+    }
+
+    @Override
+    public void onBiometricAuthenticated() {
+        if (DEBUG) Log.d(TAG, "onBiometricAuthenticated");
+        mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED).sendToTarget();
+    }
+
+    @Override
+    public void onBiometricHelp(String message) {
+        if (DEBUG) Log.d(TAG, "onBiometricHelp: " + message);
+        mHandler.obtainMessage(MSG_BIOMETRIC_HELP, message).sendToTarget();
+    }
+
+    @Override
+    public void onBiometricError(String error) {
+        if (DEBUG) Log.d(TAG, "onBiometricError: " + error);
+        mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, error).sendToTarget();
+    }
+
+    @Override
+    public void hideBiometricDialog() {
+        if (DEBUG) Log.d(TAG, "hideBiometricDialog");
+        mHandler.obtainMessage(MSG_HIDE_DIALOG, false /* userCanceled */).sendToTarget();
+    }
+
+    private void handleShowDialog(SomeArgs args) {
+        if (DEBUG) Log.d(TAG, "handleShowDialog, isAnimatingAway: "
+                + mDialogView.isAnimatingAway());
+        if (mDialogView.isAnimatingAway()) {
+            mDialogView.forceRemove();
+        } else if (mDialogShowing) {
+            Log.w(TAG, "Dialog already showing");
+            return;
+        }
+        mReceiver = (IBiometricPromptReceiver) args.arg2;
+        mDialogView.setBundle((Bundle)args.arg1);
+        mWindowManager.addView(mDialogView, mDialogView.getLayoutParams());
+        mDialogShowing = true;
+    }
+
+    private void handleBiometricAuthenticated() {
+        if (DEBUG) Log.d(TAG, "handleBiometricAuthenticated");
+
+        // TODO: announce correct string depending on modality
+        mDialogView.announceForAccessibility(
+                mContext.getResources().getText(
+                        com.android.internal.R.string.fingerprint_authenticated));
+        handleHideDialog(false /* userCanceled */);
+    }
+
+    private void handleBiometricHelp(String message) {
+        if (DEBUG) Log.d(TAG, "handleBiometricHelp: " + message);
+        mDialogView.showHelpMessage(message);
+    }
+
+    private void handleBiometricError(String error) {
+        if (DEBUG) Log.d(TAG, "handleBiometricError: " + error);
+        if (!mDialogShowing) {
+            if (DEBUG) Log.d(TAG, "Dialog already dismissed");
+            return;
+        }
+        mDialogView.showErrorMessage(error);
+    }
+
+    private void handleHideDialog(boolean userCanceled) {
+        if (DEBUG) Log.d(TAG, "handleHideDialog, userCanceled: " + userCanceled);
+        if (!mDialogShowing) {
+            // This can happen if there's a race and we get called from both
+            // onAuthenticated and onError, etc.
+            Log.w(TAG, "Dialog already dismissed, userCanceled: " + userCanceled);
+            return;
+        }
+        if (userCanceled) {
+            try {
+                mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException when hiding dialog", e);
+            }
+        }
+        mReceiver = null;
+        mDialogShowing = false;
+        mDialogView.startDismiss();
+    }
+
+    private void handleButtonNegative() {
+        if (mReceiver == null) {
+            Log.e(TAG, "Receiver is null");
+            return;
+        }
+        try {
+            mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_NEGATIVE);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception when handling negative button", e);
+        }
+        handleHideDialog(false /* userCanceled */);
+    }
+
+    private void handleButtonPositive() {
+        if (mReceiver == null) {
+            Log.e(TAG, "Receiver is null");
+            return;
+        }
+        try {
+            mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_POSITIVE);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Remote exception when handling positive button", e);
+        }
+        handleHideDialog(false /* userCanceled */);
+    }
+
+    private void handleUserCanceled() {
+        handleHideDialog(true /* userCanceled */);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java b/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java
new file mode 100644
index 0000000..f388d9c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.biometrics;
+
+/**
+ * Callback interface for dialog views. These should be implemented by the controller (e.g.
+ * FingerprintDialogImpl) and passed into their views (e.g. FingerprintDialogView).
+ */
+public interface DialogViewCallback {
+    /**
+     * Invoked when the user cancels authentication by tapping outside the prompt, etc. The dialog
+     * should be dismissed.
+     */
+    void onUserCanceled();
+
+    /**
+     * Invoked when an error is shown. The dialog should be dismissed after a set amount of time.
+     */
+    void onErrorShown();
+
+    /**
+     * Invoked when the negative button is pressed. The client should be notified and the dialog
+     * should be dismissed.
+     */
+    void onNegativePressed();
+
+    /**
+     * Invoked when the positive button is pressed. The client should be notified and the dialog
+     * should be dismissed.
+     */
+    void onPositivePressed();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
new file mode 100644
index 0000000..68c2c42
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.biometrics;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
+import android.hardware.biometrics.BiometricPrompt;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.animation.Interpolator;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+
+/**
+ * This class loads the view for the system-provided dialog. The view consists of:
+ * Application Icon, Title, Subtitle, Description, Fingerprint Icon, Error/Help message area,
+ * and positive/negative buttons.
+ */
+public class FingerprintDialogView extends LinearLayout {
+
+    private static final String TAG = "FingerprintDialogView";
+
+    private static final int ANIMATION_DURATION_SHOW = 250; // ms
+    private static final int ANIMATION_DURATION_AWAY = 350; // ms
+
+    private static final int MSG_CLEAR_MESSAGE = 1;
+
+    private static final int STATE_NONE = 0;
+    private static final int STATE_FINGERPRINT = 1;
+    private static final int STATE_FINGERPRINT_ERROR = 2;
+    private static final int STATE_FINGERPRINT_AUTHENTICATED = 3;
+
+    private final IBinder mWindowToken = new Binder();
+    private final Interpolator mLinearOutSlowIn;
+    private final WindowManager mWindowManager;
+    private final float mAnimationTranslationOffset;
+    private final int mErrorColor;
+    private final int mTextColor;
+    private final int mFingerprintColor;
+    private final float mDisplayWidth;
+    private final DialogViewCallback mCallback;
+
+    private ViewGroup mLayout;
+    private final TextView mErrorText;
+    private Bundle mBundle;
+    private final LinearLayout mDialog;
+    private int mLastState;
+    private boolean mAnimatingAway;
+    private boolean mWasForceRemoved;
+
+    private final Runnable mShowAnimationRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mLayout.animate()
+                    .alpha(1f)
+                    .setDuration(ANIMATION_DURATION_SHOW)
+                    .setInterpolator(mLinearOutSlowIn)
+                    .withLayer()
+                    .start();
+            mDialog.animate()
+                    .translationY(0)
+                    .setDuration(ANIMATION_DURATION_SHOW)
+                    .setInterpolator(mLinearOutSlowIn)
+                    .withLayer()
+                    .start();
+        }
+    };
+
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case MSG_CLEAR_MESSAGE:
+                    handleClearMessage();
+                    break;
+                default:
+                    Log.e(TAG, "Unhandled message: " + msg.what);
+                    break;
+            }
+        }
+    };
+
+    public FingerprintDialogView(Context context, DialogViewCallback callback) {
+        super(context);
+        mCallback = callback;
+        mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mAnimationTranslationOffset = getResources()
+                .getDimension(R.dimen.fingerprint_dialog_animation_translation_offset);
+        mErrorColor = Color.parseColor(
+                getResources().getString(R.color.fingerprint_dialog_error_color));
+        mTextColor = Color.parseColor(
+                getResources().getString(R.color.fingerprint_dialog_text_light_color));
+        mFingerprintColor = Color.parseColor(
+                getResources().getString(R.color.fingerprint_dialog_fingerprint_color));
+
+        DisplayMetrics metrics = new DisplayMetrics();
+        mWindowManager.getDefaultDisplay().getMetrics(metrics);
+        mDisplayWidth = metrics.widthPixels;
+
+        // Create the dialog
+        LayoutInflater factory = LayoutInflater.from(getContext());
+        mLayout = (ViewGroup) factory.inflate(R.layout.fingerprint_dialog, this, false);
+        addView(mLayout);
+
+        mDialog = mLayout.findViewById(R.id.dialog);
+
+        mErrorText = mLayout.findViewById(R.id.error);
+
+        mLayout.setOnKeyListener(new View.OnKeyListener() {
+            boolean downPressed = false;
+            @Override
+            public boolean onKey(View v, int keyCode, KeyEvent event) {
+                if (keyCode != KeyEvent.KEYCODE_BACK) {
+                    return false;
+                }
+                if (event.getAction() == KeyEvent.ACTION_DOWN && downPressed == false) {
+                    downPressed = true;
+                } else if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                    downPressed = false;
+                } else if (event.getAction() == KeyEvent.ACTION_UP && downPressed == true) {
+                    downPressed = false;
+                    mCallback.onUserCanceled();
+                }
+                return true;
+            }
+        });
+
+        final View space = mLayout.findViewById(R.id.space);
+        final View leftSpace = mLayout.findViewById(R.id.left_space);
+        final View rightSpace = mLayout.findViewById(R.id.right_space);
+        final Button negative = mLayout.findViewById(R.id.button2);
+        final Button positive = mLayout.findViewById(R.id.button1);
+
+        setDismissesDialog(space);
+        setDismissesDialog(leftSpace);
+        setDismissesDialog(rightSpace);
+
+        negative.setOnClickListener((View v) -> {
+            mCallback.onNegativePressed();
+        });
+
+        positive.setOnClickListener((View v) -> {
+            mCallback.onPositivePressed();
+        });
+
+        mLayout.setFocusableInTouchMode(true);
+        mLayout.requestFocus();
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        final TextView title = mLayout.findViewById(R.id.title);
+        final TextView subtitle = mLayout.findViewById(R.id.subtitle);
+        final TextView description = mLayout.findViewById(R.id.description);
+        final Button negative = mLayout.findViewById(R.id.button2);
+        final Button positive = mLayout.findViewById(R.id.button1);
+
+        mDialog.getLayoutParams().width = (int) mDisplayWidth;
+
+        mLastState = STATE_NONE;
+        updateFingerprintIcon(STATE_FINGERPRINT);
+
+        title.setText(mBundle.getCharSequence(BiometricPrompt.KEY_TITLE));
+        title.setSelected(true);
+
+        final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE);
+        if (TextUtils.isEmpty(subtitleText)) {
+            subtitle.setVisibility(View.GONE);
+        } else {
+            subtitle.setVisibility(View.VISIBLE);
+            subtitle.setText(subtitleText);
+        }
+
+        final CharSequence descriptionText = mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION);
+        if (TextUtils.isEmpty(descriptionText)) {
+            description.setVisibility(View.GONE);
+        } else {
+            description.setVisibility(View.VISIBLE);
+            description.setText(descriptionText);
+        }
+
+        negative.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
+
+        final CharSequence positiveText =
+                mBundle.getCharSequence(BiometricPrompt.KEY_POSITIVE_TEXT);
+        positive.setText(positiveText); // needs to be set for marquee to work
+        if (positiveText != null) {
+            positive.setVisibility(View.VISIBLE);
+        } else {
+            positive.setVisibility(View.GONE);
+        }
+
+        if (!mWasForceRemoved) {
+            // Dim the background and slide the dialog up
+            mDialog.setTranslationY(mAnimationTranslationOffset);
+            mLayout.setAlpha(0f);
+            postOnAnimation(mShowAnimationRunnable);
+        } else {
+            // Show the dialog immediately
+            mLayout.animate().cancel();
+            mDialog.animate().cancel();
+            mDialog.setAlpha(1.0f);
+            mDialog.setTranslationY(0);
+            mLayout.setAlpha(1.0f);
+        }
+        mWasForceRemoved = false;
+    }
+
+    private void setDismissesDialog(View v) {
+        v.setClickable(true);
+        v.setOnTouchListener((View view, MotionEvent event) -> {
+            mCallback.onUserCanceled();
+            return true;
+        });
+    }
+
+    public void startDismiss() {
+        mAnimatingAway = true;
+
+        final Runnable endActionRunnable = new Runnable() {
+            @Override
+            public void run() {
+                mWindowManager.removeView(FingerprintDialogView.this);
+                mAnimatingAway = false;
+            }
+        };
+
+        postOnAnimation(new Runnable() {
+            @Override
+            public void run() {
+                mLayout.animate()
+                        .alpha(0f)
+                        .setDuration(ANIMATION_DURATION_AWAY)
+                        .setInterpolator(mLinearOutSlowIn)
+                        .withLayer()
+                        .start();
+                mDialog.animate()
+                        .translationY(mAnimationTranslationOffset)
+                        .setDuration(ANIMATION_DURATION_AWAY)
+                        .setInterpolator(mLinearOutSlowIn)
+                        .withLayer()
+                        .withEndAction(endActionRunnable)
+                        .start();
+            }
+        });
+    }
+
+    /**
+     * Force remove the window, cancelling any animation that's happening. This should only be
+     * called if we want to quickly show the dialog again (e.g. on rotation). Calling this method
+     * will cause the dialog to show without an animation the next time it's attached.
+     */
+    public void forceRemove() {
+        mLayout.animate().cancel();
+        mDialog.animate().cancel();
+        mWindowManager.removeView(FingerprintDialogView.this);
+        mAnimatingAway = false;
+        mWasForceRemoved = true;
+    }
+
+    public boolean isAnimatingAway() {
+        return mAnimatingAway;
+    }
+
+    public void setBundle(Bundle bundle) {
+        mBundle = bundle;
+    }
+
+    // Clears the temporary message and shows the help message.
+    private void handleClearMessage() {
+        updateFingerprintIcon(STATE_FINGERPRINT);
+        mErrorText.setText(R.string.fingerprint_dialog_touch_sensor);
+        mErrorText.setTextColor(mTextColor);
+    }
+
+    // Shows an error/help message
+    private void showTemporaryMessage(String message) {
+        mHandler.removeMessages(MSG_CLEAR_MESSAGE);
+        updateFingerprintIcon(STATE_FINGERPRINT_ERROR);
+        mErrorText.setText(message);
+        mErrorText.setTextColor(mErrorColor);
+        mErrorText.setContentDescription(message);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_MESSAGE),
+                BiometricPrompt.HIDE_DIALOG_DELAY);
+    }
+
+    public void showHelpMessage(String message) {
+        showTemporaryMessage(message);
+    }
+
+    public void showErrorMessage(String error) {
+        showTemporaryMessage(error);
+        mCallback.onErrorShown();
+    }
+
+    private void updateFingerprintIcon(int newState) {
+        Drawable icon  = getAnimationForTransition(mLastState, newState);
+
+        if (icon == null) {
+            Log.e(TAG, "Animation not found");
+            return;
+        }
+
+        final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
+                ? (AnimatedVectorDrawable) icon
+                : null;
+
+        final ImageView fingerprint_icon = mLayout.findViewById(R.id.fingerprint_icon);
+        fingerprint_icon.setImageDrawable(icon);
+
+        if (animation != null && shouldAnimateForTransition(mLastState, newState)) {
+            animation.forceAnimationOnUI();
+            animation.start();
+        }
+
+        mLastState = newState;
+    }
+
+    private boolean shouldAnimateForTransition(int oldState, int newState) {
+        if (oldState == STATE_NONE && newState == STATE_FINGERPRINT) {
+            return false;
+        } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) {
+            return true;
+        } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) {
+            return true;
+        } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_AUTHENTICATED) {
+            // TODO(b/77328470): add animation when fingerprint is authenticated
+            return false;
+        }
+        return false;
+    }
+
+    private Drawable getAnimationForTransition(int oldState, int newState) {
+        int iconRes;
+        if (oldState == STATE_NONE && newState == STATE_FINGERPRINT) {
+            iconRes = R.drawable.fingerprint_dialog_fp_to_error;
+        } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) {
+            iconRes = R.drawable.fingerprint_dialog_fp_to_error;
+        } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) {
+            iconRes = R.drawable.fingerprint_dialog_error_to_fp;
+        } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_AUTHENTICATED) {
+            // TODO(b/77328470): add animation when fingerprint is authenticated
+            iconRes = R.drawable.fingerprint_dialog_error_to_fp;
+        }
+        else {
+            return null;
+        }
+        return mContext.getDrawable(iconRes);
+    }
+
+    public WindowManager.LayoutParams getLayoutParams() {
+        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+                PixelFormat.TRANSLUCENT);
+        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        lp.setTitle("FingerprintDialogView");
+        lp.token = mWindowToken;
+        return lp;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index a89a8ef..d6a1cf0 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -18,9 +18,9 @@
 import android.content.Context;
 import android.service.notification.StatusBarNotification;
 
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 
 public class CarNotificationEntryManager extends NotificationEntryManager {
     public CarNotificationEntryManager(Context context) {
@@ -29,7 +29,7 @@
 
     /**
      * Returns the
-     * {@link com.android.systemui.statusbar.ExpandableNotificationRow.LongPressListener} that will
+     * {@link ExpandableNotificationRow.LongPressListener} that will
      * be triggered when a notification card is long-pressed.
      */
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
index cc9fec0..a015a18 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
@@ -17,15 +17,13 @@
 
 import android.content.Context;
 import android.util.ArrayMap;
-import android.view.View;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.Dependency.DependencyProvider;
 import com.android.systemui.SystemUIFactory;
-import com.android.systemui.statusbar.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.car.CarFacetButtonController;
-import com.android.systemui.statusbar.car.CarStatusBar;
 import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.car.hvac.HvacController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
index e11fe4e..d5b54f9 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
@@ -37,7 +37,7 @@
 
     public static final long DURATION = 1133;
     private static final String TAG = "WirelessChargingView";
-    private static final boolean LOCAL_LOGV = false;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final WirelessChargingView mCurrentWirelessChargingView;
     private static WirelessChargingView mPreviousWirelessChargingView;
@@ -95,7 +95,6 @@
         private final Handler mHandler;
 
         private int mGravity;
-
         private View mView;
         private View mNextView;
         private WindowManager mWM;
@@ -112,7 +111,7 @@
             params.width = WindowManager.LayoutParams.MATCH_PARENT;
             params.format = PixelFormat.TRANSLUCENT;
 
-            params.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
+            params.type = WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
             params.setTitle("Charging Animation");
             params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
@@ -151,20 +150,20 @@
         }
 
         public void show() {
-            if (LOCAL_LOGV) Log.v(TAG, "SHOW: " + this);
+            if (DEBUG) Slog.d(TAG, "SHOW: " + this);
             mHandler.obtainMessage(SHOW).sendToTarget();
         }
 
         public void hide(long duration) {
             mHandler.removeMessages(HIDE);
 
-            if (LOCAL_LOGV) Log.v(TAG, "HIDE: " + this);
+            if (DEBUG) Slog.d(TAG, "HIDE: " + this);
             mHandler.sendMessageDelayed(Message.obtain(mHandler, HIDE), duration);
         }
 
         private void handleShow() {
-            if (LOCAL_LOGV) {
-                Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView + " mNextView="
+            if (DEBUG) {
+                Slog.d(TAG, "HANDLE SHOW: " + this + " mView=" + mView + " mNextView="
                         + mNextView);
             }
 
@@ -182,10 +181,10 @@
                 mParams.hideTimeoutMilliseconds = DURATION;
 
                 if (mView.getParent() != null) {
-                    if (LOCAL_LOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
+                    if (DEBUG) Slog.d(TAG, "REMOVE! " + mView + " in " + this);
                     mWM.removeView(mView);
                 }
-                if (LOCAL_LOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
+                if (DEBUG) Slog.d(TAG, "ADD! " + mView + " in " + this);
 
                 try {
                     if (mCallback != null) {
@@ -199,10 +198,10 @@
         }
 
         private void handleHide() {
-            if (LOCAL_LOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView);
+            if (DEBUG) Slog.d(TAG, "HANDLE HIDE: " + this + " mView=" + mView);
             if (mView != null) {
                 if (mView.getParent() != null) {
-                    if (LOCAL_LOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
+                    if (DEBUG) Slog.d(TAG, "REMOVE! " + mView + " in " + this);
                     if (mCallback != null) {
                         mCallback.onAnimationEnded();
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index c8e83de..ec150873 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -20,10 +20,12 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
-import android.graphics.Color;
+import android.graphics.drawable.Animatable;
 import android.util.AttributeSet;
+import android.view.ContextThemeWrapper;
 import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 import android.widget.TextView;
 
 import com.android.systemui.Interpolators;
@@ -58,19 +60,22 @@
 
     private void init(Context context, AttributeSet attrs, int batteryLevel, boolean isDozing) {
         final int mBatteryLevel = batteryLevel;
-        inflate(context, R.layout.wireless_charging_layout, this);
+
+        // set style based on background
+        int style = R.style.ChargingAnim_WallpaperBackground;
+        if (isDozing) {
+            style = R.style.ChargingAnim_DarkBackground;
+        }
+
+        inflate(new ContextThemeWrapper(context, style), R.layout.wireless_charging_layout, this);
 
         // where the circle animation occurs:
-        final WirelessChargingView mChargingView = findViewById(R.id.wireless_charging_view);
+        final ImageView chargingView = findViewById(R.id.wireless_charging_view);
+        final Animatable chargingAnimation = (Animatable) chargingView.getDrawable();
 
         // amount of battery:
         final TextView mPercentage = findViewById(R.id.wireless_charging_percentage);
 
-        if (isDozing) {
-            mChargingView.setPaintColor(Color.WHITE);
-            mPercentage.setTextColor(Color.WHITE);
-        }
-
         if (batteryLevel != UNKNOWN_BATTERY_LEVEL) {
             mPercentage.setText(NumberFormat.getPercentInstance().format(mBatteryLevel / 100f));
             mPercentage.setAlpha(0);
@@ -106,17 +111,10 @@
         textFadeAnimator.setInterpolator(Interpolators.LINEAR);
         textFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset);
 
-        // Animation Opacity: wireless charging circle animation fades from 1 to 0 opacity
-        ValueAnimator circleFadeAnimator = ObjectAnimator.ofFloat(mChargingView, "alpha",
-                1, 0);
-        circleFadeAnimator.setDuration(chargingAnimationFadeDuration);
-        circleFadeAnimator.setInterpolator(Interpolators.LINEAR);
-        circleFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset);
-
         // play all animations together
         AnimatorSet animatorSet = new AnimatorSet();
-        animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator,
-                circleFadeAnimator);
+        animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator);
+        chargingAnimation.start();
         animatorSet.start();
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java
deleted file mode 100644
index ad6dfa4..0000000
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.charging;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.animation.Interpolator;
-
-import com.android.settingslib.Utils;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-
-final class WirelessChargingView extends View {
-
-    private Interpolator mInterpolator;
-    private float mPathGone;
-    private float mInterpolatedPathGone;
-    private long mAnimationStartTime;
-    private long mScaleDotsDuration;
-
-    private boolean mFinishedAnimatingDots = false;
-    private int mNumDots;
-
-    private double mAngleOffset;
-    private double mCurrAngleOffset;
-
-    private int mDotsRadiusStart;
-    private int mDotsRadiusEnd;
-    private int mCurrDotRadius;
-
-    private int mMainCircleStartRadius;
-    private int mMainCircleEndRadius;
-    private int mMainCircleCurrentRadius;
-
-    private int mCenterX;
-    private int mCenterY;
-
-    private Paint mPaint;
-    private Context mContext;
-
-    public WirelessChargingView(Context context) {
-        super(context);
-        init(context, null);
-    }
-
-    public WirelessChargingView(Context context, AttributeSet attr) {
-        super(context, attr);
-        init(context, attr);
-    }
-
-    public WirelessChargingView(Context context, AttributeSet attr, int styleAttr) {
-        super(context, attr, styleAttr);
-        init(context, attr);
-    }
-
-    public void init(Context context, AttributeSet attr) {
-        mContext = context;
-
-        mDotsRadiusStart = context.getResources().getDimensionPixelSize(
-                R.dimen.wireless_charging_dots_radius_start);
-        mDotsRadiusEnd = context.getResources().getDimensionPixelSize(
-                R.dimen.wireless_charging_dots_radius_end);
-
-        mMainCircleStartRadius = context.getResources().getDimensionPixelSize(
-                R.dimen.wireless_charging_circle_radius_start);
-        mMainCircleEndRadius = context.getResources().getDimensionPixelSize(
-                R.dimen.wireless_charging_circle_radius_end);
-        mMainCircleCurrentRadius = mMainCircleStartRadius;
-
-        mAngleOffset = context.getResources().getInteger(R.integer.wireless_charging_angle_offset);
-        mScaleDotsDuration = (long) context.getResources().getInteger(
-                R.integer.wireless_charging_scale_dots_duration);
-        mNumDots = context.getResources().getInteger(R.integer.wireless_charging_num_dots);
-
-        setupPaint();
-        mInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
-    }
-
-    private void setupPaint() {
-        mPaint = new Paint();
-        mPaint.setColor(Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor));
-    }
-
-    public void setPaintColor(int color) {
-        mPaint.setColor(color);
-    }
-
-    @Override
-    protected void onDraw(final Canvas canvas) {
-        super.onDraw(canvas);
-
-        if (mAnimationStartTime == 0) {
-            mAnimationStartTime = System.currentTimeMillis();
-        }
-
-        updateDrawingParameters();
-        drawCircles(canvas);
-
-        if (!mFinishedAnimatingDots) {
-            invalidate();
-        }
-    }
-
-    /**
-     * Draws a larger circle of radius {@link WirelessChargingView#mMainCircleEndRadius} composed of
-     * {@link WirelessChargingView#mNumDots} smaller circles
-     * @param canvas
-     */
-    private void drawCircles(Canvas canvas) {
-        mCenterX = canvas.getWidth() / 2;
-        mCenterY = canvas.getHeight() / 2;
-
-        // draws mNumDots to compose a larger, main circle
-        for (int circle = 0; circle < mNumDots; circle++) {
-            double angle = ((mCurrAngleOffset) * Math.PI / 180) + (circle * ((2 * Math.PI)
-                    / mNumDots));
-
-            int x = (int) (mCenterX + Math.cos(angle) * (mMainCircleCurrentRadius +
-                    mCurrDotRadius));
-            int y = (int) (mCenterY + Math.sin(angle) * (mMainCircleCurrentRadius +
-                    mCurrDotRadius));
-
-            canvas.drawCircle(x, y, mCurrDotRadius, mPaint);
-        }
-
-        if (mMainCircleCurrentRadius >= mMainCircleEndRadius) {
-            mFinishedAnimatingDots = true;
-        }
-    }
-
-    private void updateDrawingParameters() {
-        long now = System.currentTimeMillis();
-        long timeSinceStart = now - mAnimationStartTime;
-        mPathGone = getPathGone(now);
-        mInterpolatedPathGone = mInterpolator.getInterpolation(mPathGone);
-
-        // Position Dots: update main circle radius (that the dots compose)
-        if (mPathGone < 1.0f) {
-            mMainCircleCurrentRadius = mMainCircleStartRadius + (int) (mInterpolatedPathGone *
-                    (mMainCircleEndRadius - mMainCircleStartRadius));
-        } else {
-            mMainCircleCurrentRadius = mMainCircleEndRadius;
-        }
-
-        // Scale Dots: update dot radius
-        if (timeSinceStart < mScaleDotsDuration) {
-            mCurrDotRadius = mDotsRadiusStart + (int) (mInterpolator.getInterpolation((float)
-                    timeSinceStart / mScaleDotsDuration) * (mDotsRadiusEnd - mDotsRadiusStart));
-        } else {
-            mCurrDotRadius = mDotsRadiusEnd;
-        }
-
-        // Rotation Dot Group: dots rotate from 0 to 20 degrees
-        mCurrAngleOffset = mAngleOffset * mPathGone;
-    }
-
-    /**
-     * @return decimal depicting how far along the creation of the larger circle (of circles) is
-     * For values < 1.0, the larger circle is being drawn
-     * For values > 1.0 the larger circle has been drawn and further animation can occur
-     */
-    private float getPathGone(long now) {
-        return (float) (now - mAnimationStartTime) / (WirelessChargingAnimation.DURATION);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 0ca0a11..3d578c3 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -36,6 +36,8 @@
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.analytics.DataCollector;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.util.AsyncSensorManager;
 
 import java.io.PrintWriter;
@@ -82,6 +84,8 @@
     private boolean mShowingAod;
     private Runnable mPendingWtf;
 
+    private final StateListener mStateListener = this::setStatusBarState;
+
     protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
         @Override
         public void onChange(boolean selfChange) {
@@ -104,6 +108,7 @@
                 UserHandle.USER_ALL);
 
         updateConfiguration();
+        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
     }
 
     public static FalsingManager getInstance(Context context) {
@@ -274,7 +279,7 @@
         updateSessionActive();
     }
 
-    public void setStatusBarState(int state) {
+    private void setStatusBarState(int state) {
         if (FalsingLog.ENABLED) {
             FalsingLog.i("setStatusBarState", new StringBuilder()
                     .append("from=").append(StatusBarState.toShortString(mState))
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 79de48a..51cc4a1 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -35,7 +35,7 @@
     private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50;
     static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
-    private static final int PULSE_REASONS = 6;
+    private static final int PULSE_REASONS = 7;
 
     public static final int PULSE_REASON_NONE = -1;
     public static final int PULSE_REASON_INTENT = 0;
@@ -44,6 +44,7 @@
     public static final int PULSE_REASON_SENSOR_PICKUP = 3;
     public static final int PULSE_REASON_SENSOR_DOUBLE_TAP = 4;
     public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5;
+    public static final int PULSE_REASON_SENSOR_REACH = 6;
 
     private static boolean sRegisterKeyguardCallback = true;
 
@@ -62,10 +63,10 @@
     private static SummaryStats sEmergencyCallStats;
     private static SummaryStats[][] sProxStats; // [reason][near/far]
 
-    public static void tracePickupPulse(Context context, boolean withinVibrationThreshold) {
+    public static void tracePickupWakeUp(Context context, boolean withinVibrationThreshold) {
         if (!ENABLED) return;
         init(context);
-        log("pickupPulse withinVibrationThreshold=" + withinVibrationThreshold);
+        log("pickupWakeUp withinVibrationThreshold=" + withinVibrationThreshold);
         (withinVibrationThreshold ? sPickupPulseNearVibrationStats
                 : sPickupPulseNotNearVibrationStats).append();
     }
@@ -169,6 +170,11 @@
         log("state " + state);
     }
 
+    public static void traceReachWakeUp() {
+        if (!ENABLED) return;
+        log("reachWakeUp");
+    }
+
     public static void traceProximityResult(Context context, boolean near, long millis,
             int pulseReason) {
         if (!ENABLED) return;
@@ -186,6 +192,7 @@
             case PULSE_REASON_SENSOR_PICKUP: return "pickup";
             case PULSE_REASON_SENSOR_DOUBLE_TAP: return "doubletap";
             case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress";
+            case PULSE_REASON_SENSOR_REACH: return "reach";
             default: throw new IllegalArgumentException("bad reason: " + pulseReason);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 4bb4e79..36b2347 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -23,6 +23,8 @@
 import android.hardware.SensorManager;
 import android.os.Handler;
 import android.os.Trace;
+import android.os.UserHandle;
+import android.provider.Settings;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -111,7 +113,7 @@
             int brightness = computeBrightness(mLastSensorValue);
             boolean brightnessReady = brightness > 0;
             if (brightnessReady) {
-                mDozeService.setDozeScreenBrightness(brightness);
+                mDozeService.setDozeScreenBrightness(clampToUserSetting(brightness));
             }
 
             int scrimOpacity = -1;
@@ -150,10 +152,17 @@
     }
 
     private void resetBrightnessToDefault() {
-        mDozeService.setDozeScreenBrightness(mDefaultDozeBrightness);
+        mDozeService.setDozeScreenBrightness(clampToUserSetting(mDefaultDozeBrightness));
         mDozeHost.setAodDimmingScrim(0f);
     }
 
+    private int clampToUserSetting(int brightness) {
+        int userSetting = Settings.System.getIntForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS, Integer.MAX_VALUE,
+                UserHandle.USER_CURRENT);
+        return Math.min(brightness, userSetting);
+    }
+
     private void setLightSensorEnabled(boolean enabled) {
         if (enabled && !mRegistered && mLightSensor != null) {
             // Wait until we get an event from the sensor until indicating ready.
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index e87bd09..045a98c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -91,13 +91,13 @@
                         false /* touchscreen */),
                 mPickupSensor = new TriggerSensor(
                         mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
-                        Settings.Secure.DOZE_PULSE_ON_PICK_UP,
-                        config.pulseOnPickupAvailable(),
+                        Settings.Secure.DOZE_PICK_UP_GESTURE,
+                        config.dozePickupSensorAvailable(),
                         DozeLog.PULSE_REASON_SENSOR_PICKUP, false /* touchCoords */,
                         false /* touchscreen */),
                 new TriggerSensor(
                         findSensorWithType(config.doubleTapSensorType()),
-                        Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
+                        Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
                         true /* configured */,
                         DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP,
                         dozeParameters.doubleTapReportsTouchCoordinates(),
@@ -110,6 +110,13 @@
                         DozeLog.PULSE_REASON_SENSOR_LONG_PRESS,
                         true /* reports touch coordinates */,
                         true /* touchscreen */),
+                new TriggerSensor(
+                        findSensorWithType(config.reachSensorType()),
+                        Settings.Secure.DOZE_REACH_GESTURE,
+                        true /* configured */,
+                        DozeLog.PULSE_REASON_SENSOR_REACH,
+                        false /* reports touch coordinates */,
+                        false /* touchscreen */),
         };
 
         mProxSensor = new ProxSensor(policy);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index be3e322..73cbd7d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -128,8 +128,11 @@
         boolean isDoubleTap = pulseReason == DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP;
         boolean isPickup = pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
         boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS;
+        boolean isReach = pulseReason == DozeLog.PULSE_REASON_SENSOR_REACH;
 
-        if (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) && !isLongPress) {
+        if (isLongPress) {
+            requestPulse(pulseReason, sensorPerformedProxCheck);
+        } else {
             proximityCheckThenCall((result) -> {
                 if (result == ProximityCheck.RESULT_NEAR) {
                     // In pocket, drop event.
@@ -138,13 +141,13 @@
                 if (isDoubleTap) {
                     mDozeHost.onDoubleTap(screenX, screenY);
                     mMachine.wakeUp();
+                } else if (isPickup || isReach) {
+                    mMachine.wakeUp();
                 } else {
                     mDozeHost.extendPulse();
                 }
             }, sensorPerformedProxCheck, pulseReason);
             return;
-        } else {
-            requestPulse(pulseReason, sensorPerformedProxCheck);
         }
 
         if (isPickup) {
@@ -152,7 +155,9 @@
                     SystemClock.elapsedRealtime() - mNotificationPulseTime;
             final boolean withinVibrationThreshold =
                     timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
-            DozeLog.tracePickupPulse(mContext, withinVibrationThreshold);
+            DozeLog.tracePickupWakeUp(mContext, withinVibrationThreshold);
+        } else if (isReach) {
+            DozeLog.traceReachWakeUp();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index b7ff984..7863245 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -33,7 +33,6 @@
 import com.android.systemui.util.wakelock.WakeLock;
 
 import java.util.Calendar;
-import java.util.GregorianCalendar;
 
 /**
  * The policy controlling doze.
@@ -113,9 +112,7 @@
                     // The display buffers will be empty and need to be filled.
                     mHost.dozeTimeTick();
                     // The first frame may arrive when the display isn't ready yet.
-                    mHandler.postDelayed(mWakeLock.wrap(mHost::dozeTimeTick), 100);
-                    // The the delayed frame may arrive when the display isn't ready yet either.
-                    mHandler.postDelayed(mWakeLock.wrap(mHost::dozeTimeTick), 1000);
+                    mHandler.postDelayed(mWakeLock.wrap(mHost::dozeTimeTick), 500);
                 }
                 scheduleTimeTick();
                 break;
@@ -184,7 +181,7 @@
     }
 
     private long roundToNextMinute(long timeInMillis) {
-        Calendar calendar = GregorianCalendar.getInstance();
+        Calendar calendar = Calendar.getInstance();
         calendar.setTimeInMillis(timeInMillis);
         calendar.set(Calendar.MILLISECOND, 0);
         calendar.set(Calendar.SECOND, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
deleted file mode 100644
index a81043e..0000000
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.fingerprint;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.hardware.biometrics.BiometricPrompt;
-import android.hardware.biometrics.IBiometricPromptReceiver;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.WindowManager;
-
-import com.android.internal.os.SomeArgs;
-import com.android.systemui.SystemUI;
-import com.android.systemui.statusbar.CommandQueue;
-
-public class FingerprintDialogImpl extends SystemUI implements CommandQueue.Callbacks {
-    private static final String TAG = "FingerprintDialogImpl";
-    private static final boolean DEBUG = true;
-
-    protected static final int MSG_SHOW_DIALOG = 1;
-    protected static final int MSG_FINGERPRINT_AUTHENTICATED = 2;
-    protected static final int MSG_FINGERPRINT_HELP = 3;
-    protected static final int MSG_FINGERPRINT_ERROR = 4;
-    protected static final int MSG_HIDE_DIALOG = 5;
-    protected static final int MSG_BUTTON_NEGATIVE = 6;
-    protected static final int MSG_USER_CANCELED = 7;
-    protected static final int MSG_BUTTON_POSITIVE = 8;
-    protected static final int MSG_CLEAR_MESSAGE = 9;
-
-
-    private FingerprintDialogView mDialogView;
-    private WindowManager mWindowManager;
-    private IBiometricPromptReceiver mReceiver;
-    private boolean mDialogShowing;
-
-    private Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch(msg.what) {
-                case MSG_SHOW_DIALOG:
-                    handleShowDialog((SomeArgs) msg.obj);
-                    break;
-                case MSG_FINGERPRINT_AUTHENTICATED:
-                    handleFingerprintAuthenticated();
-                    break;
-                case MSG_FINGERPRINT_HELP:
-                    handleFingerprintHelp((String) msg.obj);
-                    break;
-                case MSG_FINGERPRINT_ERROR:
-                    handleFingerprintError((String) msg.obj);
-                    break;
-                case MSG_HIDE_DIALOG:
-                    handleHideDialog((Boolean) msg.obj);
-                    break;
-                case MSG_BUTTON_NEGATIVE:
-                    handleButtonNegative();
-                    break;
-                case MSG_USER_CANCELED:
-                    handleUserCanceled();
-                    break;
-                case MSG_BUTTON_POSITIVE:
-                    handleButtonPositive();
-                    break;
-                case MSG_CLEAR_MESSAGE:
-                    handleClearMessage();
-                    break;
-            }
-        }
-    };
-
-    @Override
-    public void start() {
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
-            return;
-        }
-        getComponent(CommandQueue.class).addCallbacks(this);
-        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        mDialogView = new FingerprintDialogView(mContext, mHandler);
-    }
-
-    @Override
-    public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
-        if (DEBUG) Log.d(TAG, "showFingerprintDialog");
-        // Remove these messages as they are part of the previous client
-        mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
-        mHandler.removeMessages(MSG_FINGERPRINT_HELP);
-        mHandler.removeMessages(MSG_FINGERPRINT_AUTHENTICATED);
-        SomeArgs args = SomeArgs.obtain();
-        args.arg1 = bundle;
-        args.arg2 = receiver;
-        mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
-    }
-
-    @Override
-    public void onFingerprintAuthenticated() {
-        if (DEBUG) Log.d(TAG, "onFingerprintAuthenticated");
-        mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
-    }
-
-    @Override
-    public void onFingerprintHelp(String message) {
-        if (DEBUG) Log.d(TAG, "onFingerprintHelp: " + message);
-        mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
-    }
-
-    @Override
-    public void onFingerprintError(String error) {
-        if (DEBUG) Log.d(TAG, "onFingerprintError: " + error);
-        mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
-    }
-
-    @Override
-    public void hideFingerprintDialog() {
-        if (DEBUG) Log.d(TAG, "hideFingerprintDialog");
-        mHandler.obtainMessage(MSG_HIDE_DIALOG, false /* userCanceled */).sendToTarget();
-    }
-
-    private void handleShowDialog(SomeArgs args) {
-        if (DEBUG) Log.d(TAG, "handleShowDialog, isAnimatingAway: "
-                + mDialogView.isAnimatingAway());
-        if (mDialogView.isAnimatingAway()) {
-            mDialogView.forceRemove();
-        } else if (mDialogShowing) {
-            Log.w(TAG, "Dialog already showing");
-            return;
-        }
-        mReceiver = (IBiometricPromptReceiver) args.arg2;
-        mDialogView.setBundle((Bundle)args.arg1);
-        mWindowManager.addView(mDialogView, mDialogView.getLayoutParams());
-        mDialogShowing = true;
-    }
-
-    private void handleFingerprintAuthenticated() {
-        if (DEBUG) Log.d(TAG, "handleFingerprintAuthenticated");
-        mDialogView.announceForAccessibility(
-                mContext.getResources().getText(
-                        com.android.internal.R.string.fingerprint_authenticated));
-        handleHideDialog(false /* userCanceled */);
-    }
-
-    private void handleFingerprintHelp(String message) {
-        if (DEBUG) Log.d(TAG, "handleFingerprintHelp: " + message);
-        mDialogView.showHelpMessage(message);
-    }
-
-    private void handleFingerprintError(String error) {
-        if (DEBUG) Log.d(TAG, "handleFingerprintError: " + error);
-        if (!mDialogShowing) {
-            if (DEBUG) Log.d(TAG, "Dialog already dismissed");
-            return;
-        }
-        mDialogView.showErrorMessage(error);
-    }
-
-    private void handleHideDialog(boolean userCanceled) {
-        if (DEBUG) Log.d(TAG, "handleHideDialog, userCanceled: " + userCanceled);
-        if (!mDialogShowing) {
-            // This can happen if there's a race and we get called from both
-            // onAuthenticated and onError, etc.
-            Log.w(TAG, "Dialog already dismissed, userCanceled: " + userCanceled);
-            return;
-        }
-        if (userCanceled) {
-            try {
-                mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException when hiding dialog", e);
-            }
-        }
-        mReceiver = null;
-        mDialogShowing = false;
-        mDialogView.startDismiss();
-    }
-
-    private void handleButtonNegative() {
-        if (mReceiver == null) {
-            Log.e(TAG, "Receiver is null");
-            return;
-        }
-        try {
-            mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_NEGATIVE);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception when handling negative button", e);
-        }
-        handleHideDialog(false /* userCanceled */);
-    }
-
-    private void handleButtonPositive() {
-        if (mReceiver == null) {
-            Log.e(TAG, "Receiver is null");
-            return;
-        }
-        try {
-            mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_POSITIVE);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception when handling positive button", e);
-        }
-        handleHideDialog(false /* userCanceled */);
-    }
-
-    private void handleClearMessage() {
-        mDialogView.resetMessage();
-    }
-
-    private void handleUserCanceled() {
-        handleHideDialog(true /* userCanceled */);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
deleted file mode 100644
index 8013a9e..0000000
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.fingerprint;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.AnimatedVectorDrawable;
-import android.graphics.drawable.Drawable;
-import android.hardware.biometrics.BiometricPrompt;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.text.TextUtils;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.animation.Interpolator;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-
-/**
- * This class loads the view for the system-provided dialog. The view consists of:
- * Application Icon, Title, Subtitle, Description, Fingerprint Icon, Error/Help message area,
- * and positive/negative buttons.
- */
-public class FingerprintDialogView extends LinearLayout {
-
-    private static final String TAG = "FingerprintDialogView";
-
-    private static final int ANIMATION_DURATION_SHOW = 250; // ms
-    private static final int ANIMATION_DURATION_AWAY = 350; // ms
-
-    private static final int STATE_NONE = 0;
-    private static final int STATE_FINGERPRINT = 1;
-    private static final int STATE_FINGERPRINT_ERROR = 2;
-    private static final int STATE_FINGERPRINT_AUTHENTICATED = 3;
-
-    private final IBinder mWindowToken = new Binder();
-    private final Interpolator mLinearOutSlowIn;
-    private final WindowManager mWindowManager;
-    private final float mAnimationTranslationOffset;
-    private final int mErrorColor;
-    private final int mTextColor;
-    private final int mFingerprintColor;
-
-    private ViewGroup mLayout;
-    private final TextView mErrorText;
-    private Handler mHandler;
-    private Bundle mBundle;
-    private final LinearLayout mDialog;
-    private int mLastState;
-    private boolean mAnimatingAway;
-    private boolean mWasForceRemoved;
-
-    private final float mDisplayWidth;
-
-    private final Runnable mShowAnimationRunnable = new Runnable() {
-        @Override
-        public void run() {
-            mLayout.animate()
-                    .alpha(1f)
-                    .setDuration(ANIMATION_DURATION_SHOW)
-                    .setInterpolator(mLinearOutSlowIn)
-                    .withLayer()
-                    .start();
-            mDialog.animate()
-                    .translationY(0)
-                    .setDuration(ANIMATION_DURATION_SHOW)
-                    .setInterpolator(mLinearOutSlowIn)
-                    .withLayer()
-                    .start();
-        }
-    };
-
-    public FingerprintDialogView(Context context, Handler handler) {
-        super(context);
-        mHandler = handler;
-        mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
-        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        mAnimationTranslationOffset = getResources()
-                .getDimension(R.dimen.fingerprint_dialog_animation_translation_offset);
-        mErrorColor = Color.parseColor(
-                getResources().getString(R.color.fingerprint_dialog_error_color));
-        mTextColor = Color.parseColor(
-                getResources().getString(R.color.fingerprint_dialog_text_light_color));
-        mFingerprintColor = Color.parseColor(
-                getResources().getString(R.color.fingerprint_dialog_fingerprint_color));
-
-        DisplayMetrics metrics = new DisplayMetrics();
-        mWindowManager.getDefaultDisplay().getMetrics(metrics);
-        mDisplayWidth = metrics.widthPixels;
-
-        // Create the dialog
-        LayoutInflater factory = LayoutInflater.from(getContext());
-        mLayout = (ViewGroup) factory.inflate(R.layout.fingerprint_dialog, this, false);
-        addView(mLayout);
-
-        mDialog = mLayout.findViewById(R.id.dialog);
-
-        mErrorText = mLayout.findViewById(R.id.error);
-
-        mLayout.setOnKeyListener(new View.OnKeyListener() {
-            boolean downPressed = false;
-            @Override
-            public boolean onKey(View v, int keyCode, KeyEvent event) {
-                if (keyCode != KeyEvent.KEYCODE_BACK) {
-                    return false;
-                }
-                if (event.getAction() == KeyEvent.ACTION_DOWN && downPressed == false) {
-                    downPressed = true;
-                } else if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                    downPressed = false;
-                } else if (event.getAction() == KeyEvent.ACTION_UP && downPressed == true) {
-                    downPressed = false;
-                    mHandler.obtainMessage(FingerprintDialogImpl.MSG_USER_CANCELED).sendToTarget();
-                }
-                return true;
-            }
-        });
-
-        final View space = mLayout.findViewById(R.id.space);
-        final View leftSpace = mLayout.findViewById(R.id.left_space);
-        final View rightSpace = mLayout.findViewById(R.id.right_space);
-        final Button negative = mLayout.findViewById(R.id.button2);
-        final Button positive = mLayout.findViewById(R.id.button1);
-
-        setDismissesDialog(space);
-        setDismissesDialog(leftSpace);
-        setDismissesDialog(rightSpace);
-
-        negative.setOnClickListener((View v) -> {
-            mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_NEGATIVE).sendToTarget();
-        });
-
-        positive.setOnClickListener((View v) -> {
-            mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_POSITIVE).sendToTarget();
-        });
-
-        mLayout.setFocusableInTouchMode(true);
-        mLayout.requestFocus();
-    }
-
-    @Override
-    public void onAttachedToWindow() {
-        super.onAttachedToWindow();
-
-        final TextView title = mLayout.findViewById(R.id.title);
-        final TextView subtitle = mLayout.findViewById(R.id.subtitle);
-        final TextView description = mLayout.findViewById(R.id.description);
-        final Button negative = mLayout.findViewById(R.id.button2);
-        final Button positive = mLayout.findViewById(R.id.button1);
-
-        mDialog.getLayoutParams().width = (int) mDisplayWidth;
-
-        mLastState = STATE_NONE;
-        updateFingerprintIcon(STATE_FINGERPRINT);
-
-        title.setText(mBundle.getCharSequence(BiometricPrompt.KEY_TITLE));
-        title.setSelected(true);
-
-        final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE);
-        if (TextUtils.isEmpty(subtitleText)) {
-            subtitle.setVisibility(View.GONE);
-        } else {
-            subtitle.setVisibility(View.VISIBLE);
-            subtitle.setText(subtitleText);
-        }
-
-        final CharSequence descriptionText = mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION);
-        if (TextUtils.isEmpty(descriptionText)) {
-            description.setVisibility(View.GONE);
-        } else {
-            description.setVisibility(View.VISIBLE);
-            description.setText(descriptionText);
-        }
-
-        negative.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
-
-        final CharSequence positiveText =
-                mBundle.getCharSequence(BiometricPrompt.KEY_POSITIVE_TEXT);
-        positive.setText(positiveText); // needs to be set for marquee to work
-        if (positiveText != null) {
-            positive.setVisibility(View.VISIBLE);
-        } else {
-            positive.setVisibility(View.GONE);
-        }
-
-        if (!mWasForceRemoved) {
-            // Dim the background and slide the dialog up
-            mDialog.setTranslationY(mAnimationTranslationOffset);
-            mLayout.setAlpha(0f);
-            postOnAnimation(mShowAnimationRunnable);
-        } else {
-            // Show the dialog immediately
-            mLayout.animate().cancel();
-            mDialog.animate().cancel();
-            mDialog.setAlpha(1.0f);
-            mDialog.setTranslationY(0);
-            mLayout.setAlpha(1.0f);
-        }
-        mWasForceRemoved = false;
-    }
-
-    private void setDismissesDialog(View v) {
-        v.setClickable(true);
-        v.setOnTouchListener((View view, MotionEvent event) -> {
-            mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG, true /* userCanceled */)
-                    .sendToTarget();
-            return true;
-        });
-    }
-
-    public void startDismiss() {
-        mAnimatingAway = true;
-
-        final Runnable endActionRunnable = new Runnable() {
-            @Override
-            public void run() {
-                mWindowManager.removeView(FingerprintDialogView.this);
-                mAnimatingAway = false;
-            }
-        };
-
-        postOnAnimation(new Runnable() {
-            @Override
-            public void run() {
-                mLayout.animate()
-                        .alpha(0f)
-                        .setDuration(ANIMATION_DURATION_AWAY)
-                        .setInterpolator(mLinearOutSlowIn)
-                        .withLayer()
-                        .start();
-                mDialog.animate()
-                        .translationY(mAnimationTranslationOffset)
-                        .setDuration(ANIMATION_DURATION_AWAY)
-                        .setInterpolator(mLinearOutSlowIn)
-                        .withLayer()
-                        .withEndAction(endActionRunnable)
-                        .start();
-            }
-        });
-    }
-
-    /**
-     * Force remove the window, cancelling any animation that's happening. This should only be
-     * called if we want to quickly show the dialog again (e.g. on rotation). Calling this method
-     * will cause the dialog to show without an animation the next time it's attached.
-     */
-    public void forceRemove() {
-        mLayout.animate().cancel();
-        mDialog.animate().cancel();
-        mWindowManager.removeView(FingerprintDialogView.this);
-        mAnimatingAway = false;
-        mWasForceRemoved = true;
-    }
-
-    public boolean isAnimatingAway() {
-        return mAnimatingAway;
-    }
-
-    public void setBundle(Bundle bundle) {
-        mBundle = bundle;
-    }
-
-    // Clears the temporary message and shows the help message.
-    protected void resetMessage() {
-        updateFingerprintIcon(STATE_FINGERPRINT);
-        mErrorText.setText(R.string.fingerprint_dialog_touch_sensor);
-        mErrorText.setTextColor(mTextColor);
-    }
-
-    // Shows an error/help message
-    private void showTemporaryMessage(String message) {
-        mHandler.removeMessages(FingerprintDialogImpl.MSG_CLEAR_MESSAGE);
-        updateFingerprintIcon(STATE_FINGERPRINT_ERROR);
-        mErrorText.setText(message);
-        mErrorText.setTextColor(mErrorColor);
-        mErrorText.setContentDescription(message);
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_CLEAR_MESSAGE),
-                BiometricPrompt.HIDE_DIALOG_DELAY);
-    }
-
-    public void showHelpMessage(String message) {
-        showTemporaryMessage(message);
-    }
-
-    public void showErrorMessage(String error) {
-        showTemporaryMessage(error);
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG,
-                false /* userCanceled */), BiometricPrompt.HIDE_DIALOG_DELAY);
-    }
-
-    private void updateFingerprintIcon(int newState) {
-        Drawable icon  = getAnimationForTransition(mLastState, newState);
-
-        if (icon == null) {
-            Log.e(TAG, "Animation not found");
-            return;
-        }
-
-        final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
-                ? (AnimatedVectorDrawable) icon
-                : null;
-
-        final ImageView fingerprint_icon = mLayout.findViewById(R.id.fingerprint_icon);
-        fingerprint_icon.setImageDrawable(icon);
-
-        if (animation != null && shouldAnimateForTransition(mLastState, newState)) {
-            animation.forceAnimationOnUI();
-            animation.start();
-        }
-
-        mLastState = newState;
-    }
-
-    private boolean shouldAnimateForTransition(int oldState, int newState) {
-        if (oldState == STATE_NONE && newState == STATE_FINGERPRINT) {
-            return false;
-        } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) {
-            return true;
-        } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) {
-            return true;
-        } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_AUTHENTICATED) {
-            // TODO(b/77328470): add animation when fingerprint is authenticated
-            return false;
-        }
-        return false;
-    }
-
-    private Drawable getAnimationForTransition(int oldState, int newState) {
-        int iconRes;
-        if (oldState == STATE_NONE && newState == STATE_FINGERPRINT) {
-            iconRes = R.drawable.fingerprint_dialog_fp_to_error;
-        } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) {
-            iconRes = R.drawable.fingerprint_dialog_fp_to_error;
-        } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) {
-            iconRes = R.drawable.fingerprint_dialog_error_to_fp;
-        } else if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_AUTHENTICATED) {
-            // TODO(b/77328470): add animation when fingerprint is authenticated
-            iconRes = R.drawable.fingerprint_dialog_error_to_fp;
-        }
-        else {
-            return null;
-        }
-        return mContext.getDrawable(iconRes);
-    }
-
-    public WindowManager.LayoutParams getLayoutParams() {
-        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
-                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
-                PixelFormat.TRANSLUCENT);
-        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-        lp.setTitle("FingerprintDialogView");
-        lp.token = mWindowToken;
-        return lp;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index f422737..0ed1cd1 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -51,7 +51,8 @@
     private final View mRootView;
     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_ASSETS_PATHS
+                | ActivityInfo.CONFIG_UI_MODE);
     private final FragmentService mManager;
     private final ExtensionFragmentManager mPlugins = new ExtensionFragmentManager();
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 532fa034a..a195fc9 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -146,11 +146,11 @@
     private boolean mDeviceProvisioned = false;
     private ToggleAction.State mAirplaneState = ToggleAction.State.Off;
     private boolean mIsWaitingForEcmExit = false;
-    private boolean mHasFasterEmergencyButton;
     private boolean mHasTelephony;
     private boolean mHasVibrator;
     private boolean mHasLogoutButton;
     private boolean mHasLockdownButton;
+    private boolean mSeparatedEmergencyButtonEnabled;
     private final boolean mShowSilentToggle;
     private final EmergencyAffordanceManager mEmergencyAffordanceManager;
     private final ScreenshotHelper mScreenshotHelper;
@@ -265,7 +265,7 @@
         if (!mHasVibrator) {
             mSilentModeAction = new SilentModeToggleAction();
         } else {
-            mSilentModeAction = new SilentModeTriStateAction(mContext, mAudioManager, mHandler);
+            mSilentModeAction = new SilentModeTriStateAction(mAudioManager, mHandler);
         }
         mAirplaneModeOn = new ToggleAction(
                 R.drawable.ic_lock_airplane_mode,
@@ -317,7 +317,8 @@
         ArraySet<String> addedKeys = new ArraySet<String>();
         mHasLogoutButton = false;
         mHasLockdownButton = false;
-        mHasFasterEmergencyButton = false;
+        mSeparatedEmergencyButtonEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.FASTER_EMERGENCY_PHONE_CALL_ENABLED, 0) != 0;
         for (int i = 0; i < defaultActions.length; i++) {
             String actionKey = defaultActions[i];
             if (addedKeys.contains(actionKey)) {
@@ -356,13 +357,6 @@
                 mItems.add(getAssistAction());
             } else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
                 mItems.add(new RestartAction());
-            } else if (GLOBAL_ACTION_KEY_EMERGENCY.equals(actionKey)) {
-                if (Settings.Global.getInt(mContext.getContentResolver(),
-                        Settings.Global.FASTER_EMERGENCY_PHONE_CALL_ENABLED, 0) != 0
-                        && !mEmergencyAffordanceManager.needsEmergencyAffordance()) {
-                    mItems.add(new EmergencyAction());
-                    mHasFasterEmergencyButton = true;
-                }
             } else if (GLOBAL_ACTION_KEY_SCREENSHOT.equals(actionKey)) {
                 mItems.add(new ScreenshotAction());
             } else if (GLOBAL_ACTION_KEY_LOGOUT.equals(actionKey)) {
@@ -371,6 +365,11 @@
                     mItems.add(new LogoutAction());
                     mHasLogoutButton = true;
                 }
+            } else if (GLOBAL_ACTION_KEY_EMERGENCY.equals(actionKey)) {
+                if (mSeparatedEmergencyButtonEnabled
+                        && !mEmergencyAffordanceManager.needsEmergencyAffordance()) {
+                    mItems.add(new EmergencyDialerAction());
+                }
             } else {
                 Log.e(TAG, "Invalid global action key " + actionKey);
             }
@@ -393,7 +392,7 @@
             return false;
         };
         ActionsDialog dialog = new ActionsDialog(mContext, this, mAdapter, onItemLongClickListener,
-                mHasFasterEmergencyButton);
+                mSeparatedEmergencyButtonEnabled);
         dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
         dialog.setKeyguardShowing(mKeyguardShowing);
 
@@ -448,12 +447,12 @@
         }
     }
 
-    private class EmergencyAction extends SinglePressAction {
+    private class EmergencyDialerAction extends SinglePressAction {
         private static final String ACTION_EMERGENCY_DIALER_DIAL =
                 "com.android.phone.EmergencyDialer.DIAL";
 
-        private EmergencyAction() {
-            super(com.android.systemui.R.drawable.faster_emergency_icon,
+        private EmergencyDialerAction() {
+            super(R.drawable.ic_faster_emergency,
                     R.string.global_action_emergency);
         }
 
@@ -660,6 +659,12 @@
     }
 
     private Action getEmergencyAction() {
+        Drawable emergencyIcon = mContext.getDrawable(R.drawable.emergency_icon);
+        if(!mSeparatedEmergencyButtonEnabled) {
+            // use un-colored legacy treatment
+            emergencyIcon.setTintList(null);
+        }
+
         return new SinglePressAction(R.drawable.emergency_icon,
                 R.string.global_action_emergency) {
             @Override
@@ -1211,12 +1216,10 @@
 
         private final AudioManager mAudioManager;
         private final Handler mHandler;
-        private final Context mContext;
 
-        SilentModeTriStateAction(Context context, AudioManager audioManager, Handler handler) {
+        SilentModeTriStateAction(AudioManager audioManager, Handler handler) {
             mAudioManager = audioManager;
             mHandler = handler;
-            mContext = context;
         }
 
         private int ringerModeToIndex(int ringerMode) {
@@ -1396,6 +1399,7 @@
         private final ColorExtractor mColorExtractor;
         private boolean mKeyguardShowing;
         private boolean mShouldDisplaySeparatedButton;
+        private boolean mShowing;
 
         public ActionsDialog(Context context, OnClickListener clickListener, MyAdapter adapter,
                 OnItemLongClickListener longClickListener, boolean shouldDisplaySeparatedButton) {
@@ -1504,6 +1508,7 @@
         @Override
         public void show() {
             super.show();
+            mShowing = true;
             mGradientDrawable.setAlpha(0);
             mHardwareLayout.setTranslationX(getAnimTranslation());
             mHardwareLayout.setAlpha(0);
@@ -1523,6 +1528,10 @@
 
         @Override
         public void dismiss() {
+            if (!mShowing) {
+                return;
+            }
+            mShowing = false;
             mHardwareLayout.setTranslationX(0);
             mHardwareLayout.setAlpha(1);
             mHardwareLayout.animate()
@@ -1541,6 +1550,7 @@
 
         void dismissImmediately() {
             super.dismiss();
+            mShowing = false;
         }
 
         private float getAnimTranslation() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 81d700c..76a1acc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -318,8 +318,7 @@
     private CachedBluetoothDevice getCachedBluetoothDevice(BluetoothDevice d) {
         CachedBluetoothDevice cachedDevice = mCachedDeviceManager.findDevice(d);
         if (cachedDevice == null) {
-            cachedDevice = mCachedDeviceManager.addDevice(
-                    mLocalBluetoothAdapter, mProfileManager, d);
+            cachedDevice = mCachedDeviceManager.addDevice(d);
         }
         return cachedDevice;
     }
@@ -599,21 +598,6 @@
             mHandler.obtainMessage(MSG_ON_DEVICE_BOND_STATE_CHANGED,
                     bondState, 0, cachedDevice).sendToTarget();
         }
-
-        @Override
-        public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { }
-        @Override
-        public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { }
-        @Override
-        public void onScanningStateChanged(boolean started) { }
-        @Override
-        public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { }
-        @Override
-        public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice,
-                                          int bluetoothProfile) { }
-
-        @Override
-        public void onAudioModeChanged() { }
     }
 
     private final class BluetoothErrorListener implements BluetoothUtils.ErrorListener {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index fe8ea34..82b79ac 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -30,6 +30,7 @@
 import android.icu.text.DisplayContext;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.Trace;
 import android.provider.Settings;
 import android.service.notification.ZenModeConfig;
 import android.text.TextUtils;
@@ -45,6 +46,7 @@
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
+import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
 import androidx.slice.SliceProvider;
 import androidx.slice.builders.ListBuilder;
@@ -71,6 +73,8 @@
     @VisibleForTesting
     static final int ALARM_VISIBILITY_HOURS = 12;
 
+    private static KeyguardSliceProvider sInstance;
+
     protected final Uri mSliceUri;
     protected final Uri mDateUri;
     protected final Uri mAlarmUri;
@@ -88,6 +92,7 @@
     protected AlarmManager mAlarmManager;
     protected ContentResolver mContentResolver;
     private AlarmManager.AlarmClockInfo mNextAlarmInfo;
+    private PendingIntent mPendingIntent;
 
     /**
      * Receiver responsible for time ticking and updating the date format.
@@ -116,6 +121,10 @@
         this(new Handler());
     }
 
+    public static KeyguardSliceProvider getAttachedInstance() {
+        return KeyguardSliceProvider.sInstance;
+    }
+
     @VisibleForTesting
     KeyguardSliceProvider(Handler handler) {
         mHandler = handler;
@@ -127,23 +136,26 @@
 
     @Override
     public Slice onBindSlice(Uri sliceUri) {
-        ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
-        builder.addRow(new RowBuilder(builder, mDateUri).setTitle(mLastText));
+        Trace.beginSection("KeyguardSliceProvider#onBindSlice");
+        ListBuilder builder = new ListBuilder(getContext(), mSliceUri, ListBuilder.INFINITY);
+        builder.addRow(new RowBuilder(mDateUri).setTitle(mLastText));
         addNextAlarm(builder);
         addZenMode(builder);
         addPrimaryAction(builder);
-        return builder.build();
+        Slice slice = builder.build();
+        Trace.endSection();
+        return slice;
     }
 
     protected void addPrimaryAction(ListBuilder builder) {
         // Add simple action because API requires it; Keyguard handles presenting
         // its own slices so this action + icon are actually never used.
-        PendingIntent pi = PendingIntent.getActivity(getContext(), 0, new Intent(), 0);
-        Icon icon = Icon.createWithResource(getContext(), R.drawable.ic_access_alarms_big);
-        SliceAction action = new SliceAction(pi, icon, mLastText);
-
-        RowBuilder primaryActionRow = new RowBuilder(builder, Uri.parse(KEYGUARD_ACTION_URI))
-            .setPrimaryAction(action);
+        IconCompat icon = IconCompat.createWithResource(getContext(),
+                R.drawable.ic_access_alarms_big);
+        SliceAction action = SliceAction.createDeeplink(mPendingIntent, icon,
+                ListBuilder.ICON_IMAGE, mLastText);
+        RowBuilder primaryActionRow = new RowBuilder(Uri.parse(KEYGUARD_ACTION_URI))
+                .setPrimaryAction(action);
         builder.addRow(primaryActionRow);
     }
 
@@ -151,11 +163,11 @@
         if (TextUtils.isEmpty(mNextAlarm)) {
             return;
         }
-
-        Icon alarmIcon = Icon.createWithResource(getContext(), R.drawable.ic_access_alarms_big);
-        RowBuilder alarmRowBuilder = new RowBuilder(builder, mAlarmUri)
+        IconCompat alarmIcon = IconCompat.createWithResource(getContext(),
+                R.drawable.ic_access_alarms_big);
+        RowBuilder alarmRowBuilder = new RowBuilder(mAlarmUri)
                 .setTitle(mNextAlarm)
-                .addEndItem(alarmIcon);
+                .addEndItem(alarmIcon, ListBuilder.ICON_IMAGE);
         builder.addRow(alarmRowBuilder);
     }
 
@@ -167,10 +179,11 @@
         if (!isDndSuppressingNotifications()) {
             return;
         }
-        RowBuilder dndBuilder = new RowBuilder(builder, mDndUri)
+        RowBuilder dndBuilder = new RowBuilder(mDndUri)
                 .setContentDescription(getContext().getResources()
                         .getString(R.string.accessibility_quick_settings_dnd))
-                .addEndItem(Icon.createWithResource(getContext(), R.drawable.stat_sys_dnd));
+                .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.stat_sys_dnd),
+                        ListBuilder.ICON_IMAGE);
         builder.addRow(dndBuilder);
     }
 
@@ -193,6 +206,8 @@
         mZenModeController = new ZenModeControllerImpl(getContext(), mHandler);
         mZenModeController.addCallback(this);
         mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern);
+        mPendingIntent = PendingIntent.getActivity(getContext(), 0, new Intent(), 0);
+        KeyguardSliceProvider.sInstance = this;
         registerClockUpdate();
         updateClock();
         return true;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index b9d1021..4977ff7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -346,6 +346,11 @@
      */
     private WorkLockActivityController mWorkLockController;
 
+    /**
+     * @see #setPulsing(boolean)
+     */
+    private boolean mPulsing;
+
     private boolean mLockLater;
 
     private boolean mWakeAndUnlocking;
@@ -624,6 +629,11 @@
         }
 
         @Override
+        public void onCancelClicked() {
+            mStatusBarKeyguardViewManager.onCancelClicked();
+        }
+
+        @Override
         public void onBouncerVisiblityChanged(boolean shown) {
             synchronized (KeyguardViewMediator.this) {
                 adjustStatusBarLocked(shown);
@@ -1645,7 +1655,6 @@
             resetKeyguardDonePendingLocked();
         }
 
-        mUpdateMonitor.clearFailedUnlockAttempts();
         mUpdateMonitor.clearBiometricRecognized();
 
         if (mGoingToSleep) {
@@ -1801,10 +1810,12 @@
 
                 int flags = 0;
                 if (mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
-                        || mWakeAndUnlocking) {
-                    flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
+                        || (mWakeAndUnlocking && !mPulsing)) {
+                    flags |= WindowManagerPolicyConstants
+                            .KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
                 }
-                if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()) {
+                if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()
+                        || (mWakeAndUnlocking && mPulsing)) {
                     flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
                 }
                 if (mStatusBarKeyguardViewManager.isUnlockWithWallpaper()) {
@@ -2103,10 +2114,20 @@
         pw.print("  mDrawnCallback: "); pw.println(mDrawnCallback);
     }
 
+    /**
+     * @param aodShowing true when AOD - or ambient mode - is showing.
+     */
     public void setAodShowing(boolean aodShowing) {
         setShowingLocked(mShowing, aodShowing);
     }
 
+    /**
+     * @param pulsing true when device temporarily wakes up to display an incoming notification.
+     */
+    public void setPulsing(boolean pulsing) {
+        mPulsing = pulsing;
+    }
+
     private static class StartKeyguardExitAnimParams {
 
         long startTime;
diff --git a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
index f5f06db..89786ee 100644
--- a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
@@ -86,11 +86,12 @@
             // synchronized on mCompletionHandlingLock due to the Object.wait() in startSound(cmd)
             mLooper = Looper.myLooper();
             if (DEBUG) Log.d(mTag, "in run: new looper " + mLooper);
+            MediaPlayer player = null;
             synchronized(this) {
                 AudioManager audioManager =
                     (AudioManager) mCmd.context.getSystemService(Context.AUDIO_SERVICE);
                 try {
-                    MediaPlayer player = new MediaPlayer();
+                    player = new MediaPlayer();
                     if (mCmd.attributes == null) {
                         mCmd.attributes = new AudioAttributes.Builder()
                                 .setUsage(AudioAttributes.USAGE_NOTIFICATION)
@@ -137,26 +138,26 @@
                         Log.e(mTag, "Exception while sleeping to sync notification playback"
                                 + " with ducking", e);
                     }
-                    try {
-                        player.start();
-                        if (DEBUG) { Log.d(mTag, "player.start"); }
-                    } catch (Exception e) {
+                    player.start();
+                    if (DEBUG) { Log.d(mTag, "player.start"); }
+                } catch (Exception e) {
+                    if (player != null) {
                         player.release();
                         player = null;
-                        // playing the notification didn't work, revert the focus request
-                        abandonAudioFocusAfterError();
                     }
-                    if (mPlayer != null) {
-                        if (DEBUG) { Log.d(mTag, "mPlayer.release"); }
-                        mPlayer.release();
-                    }
-                    mPlayer = player;
-                }
-                catch (Exception e) {
                     Log.w(mTag, "error loading sound for " + mCmd.uri, e);
                     // playing the notification didn't work, revert the focus request
                     abandonAudioFocusAfterError();
                 }
+                final MediaPlayer mp;
+                synchronized (mPlayerLock) {
+                    mp = mPlayer;
+                    mPlayer = player;
+                }
+                if (mp != null) {
+                    if (DEBUG) { Log.d(mTag, "mPlayer.release"); }
+                    mp.release();
+                }
                 this.notify();
             }
             Looper.loop();
@@ -230,14 +231,20 @@
                     break;
                 case STOP:
                     if (DEBUG) Log.d(mTag, "STOP");
-                    if (mPlayer != null) {
+                    final MediaPlayer mp;
+                    synchronized (mPlayerLock) {
+                        mp = mPlayer;
+                        mPlayer = null;
+                    }
+                    if (mp != null) {
                         long delay = SystemClock.uptimeMillis() - cmd.requestTime;
                         if (delay > 1000) {
                             Log.w(mTag, "Notification stop delayed by " + delay + "msecs");
                         }
-                        mPlayer.stop();
-                        mPlayer.release();
-                        mPlayer = null;
+                        try {
+                            mp.stop();
+                        } catch (Exception e) { }
+                        mp.release();
                         synchronized(mQueueAudioFocusLock) {
                             if (mAudioManagerWithAudioFocus != null) {
                                 if (DEBUG) { Log.d(mTag, "in STOP: abandonning AudioFocus"); }
@@ -297,6 +304,14 @@
                 }
             }
         }
+        synchronized (mPlayerLock) {
+            if (mp == mPlayer) {
+                mPlayer = null;
+            }
+        }
+        if (mp != null) {
+            mp.release();
+        }
     }
 
     public boolean onError(MediaPlayer mp, int what, int extra) {
@@ -311,6 +326,8 @@
     @GuardedBy("mCmdQueue")
     private CmdThread mThread;
 
+    private final Object mPlayerLock = new Object();
+    @GuardedBy("mPlayerLock")
     private MediaPlayer mPlayer;
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 3742194..03a573e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -65,6 +65,7 @@
     private static final boolean ENABLE_FLING_DISMISS = false;
 
     private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 225;
+    private static final int BOTTOM_OFFSET_BUFFER_DP = 1;
 
     // Allow dragging the PIP to a location to close it
     private final boolean mEnableDimissDragToEdge;
@@ -314,8 +315,10 @@
                 // above the position as if shelf/IME shows, don't move the PIP window.
                 int movementBoundsAdjustment = toMovementBounds.bottom - mMovementBounds.bottom;
                 int offsetAdjustment = fromImeAdjustment ? mImeOffset : mShelfHeight;
+                final float bottomOffsetBufferInPx = BOTTOM_OFFSET_BUFFER_DP
+                        * mContext.getResources().getDisplayMetrics().density;
                 if (toAdjustedBounds.bottom >= mMovementBounds.bottom
-                        && animatingBounds.top
+                        && animatingBounds.top + Math.round(bottomOffsetBufferInPx)
                         < toAdjustedBounds.bottom - movementBoundsAdjustment - offsetAdjustment) {
                     return;
                 }
@@ -514,7 +517,7 @@
      * Sets the menu visibility.
      */
     private void setMenuState(int menuState, boolean resize) {
-        if (menuState == MENU_STATE_FULL) {
+        if (menuState == MENU_STATE_FULL && mMenuState != MENU_STATE_FULL) {
             // Save the current snap fraction and if we do not drag or move the PiP, then
             // we store back to this snap fraction.  Otherwise, we'll reset the snap
             // fraction and snap to the closest edge
@@ -523,7 +526,7 @@
                 mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
                         mMovementBounds, mExpandedMovementBounds);
             }
-        } else if (menuState == MENU_STATE_NONE) {
+        } else if (menuState == MENU_STATE_NONE && mMenuState == MENU_STATE_FULL) {
             // Try and restore the PiP to the closest edge, using the saved snap fraction
             // if possible
             if (resize) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
old mode 100644
new mode 100755
index d9f923f..020c550
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -262,12 +262,13 @@
                             entry = Pair.<String, String>create(packageAndClassName[0], null);
                             break;
                         case 2:
-                            if (packageAndClassName[1] != null
-                                    && packageAndClassName[1].startsWith(".")) {
-                                entry = Pair.<String, String>create(
-                                        packageAndClassName[0],
-                                        packageAndClassName[0] + packageAndClassName[1]);
+                            if (packageAndClassName[1] != null) {
+                                entry = Pair.<String, String>create(packageAndClassName[0],
+                                        packageAndClassName[1].startsWith(".")
+                                                ? packageAndClassName[0] + packageAndClassName[1]
+                                                : packageAndClassName[1]);
                             }
+                            break;
                     }
                     if (entry != null) {
                         sSettingsPackageAndClassNamePairList.add(entry);
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 9070170..21eab59 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -266,9 +266,12 @@
                 || mEstimate.estimateMillis < mSevereWarningThreshold) {
             nb.setColor(Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorError));
         }
-        nb.addAction(0,
-                mContext.getString(R.string.battery_saver_start_action),
-                pendingBroadcast(ACTION_START_SAVER));
+
+        if (!mPowerMan.isPowerSaveMode()) {
+            nb.addAction(0,
+                    mContext.getString(R.string.battery_saver_start_action),
+                    pendingBroadcast(ACTION_START_SAVER));
+        }
         nb.setOnlyAlertOnce(!mPlaySound);
         mPlaySound = false;
         SystemUI.overrideNotificationAppName(mContext, nb, false);
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 6801e69..0b9067e 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -77,6 +77,7 @@
     private int mPlugType = 0;
     private int mInvalidCharger = 0;
     private EnhancedEstimates mEnhancedEstimates;
+    private Estimate mLastEstimate;
     private boolean mLowWarningShownThisChargeCycle;
     private boolean mSevereWarningShownThisChargeCycle;
 
@@ -247,7 +248,8 @@
 
                 // Show the correct version of low battery warning if needed
                 ThreadUtils.postOnBackgroundThread(() -> {
-                    maybeShowBatteryWarning(plugged, oldPlugged, oldBucket, bucket);
+                    maybeShowBatteryWarning(
+                            oldBatteryLevel, plugged, oldPlugged, oldBucket, bucket);
                 });
 
             } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
@@ -262,14 +264,18 @@
         }
     }
 
-    protected void maybeShowBatteryWarning(boolean plugged, boolean oldPlugged, int oldBucket,
-        int bucket) {
+    protected void maybeShowBatteryWarning(int oldBatteryLevel, boolean plugged, boolean oldPlugged,
+            int oldBucket, int bucket) {
         boolean isPowerSaver = mPowerManager.isPowerSaveMode();
         // only play SFX when the dialog comes up or the bucket changes
         final boolean playSound = bucket != oldBucket || oldPlugged;
         final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled();
         if (hybridEnabled) {
-            final Estimate estimate = mEnhancedEstimates.getEstimate();
+            Estimate estimate = mLastEstimate;
+            if (estimate == null || mBatteryLevel != oldBatteryLevel) {
+                estimate = mEnhancedEstimates.getEstimate();
+                mLastEstimate = estimate;
+            }
             // Turbo is not always booted once SysUI is running so we have ot make sure we actually
             // get data back
             if (estimate != null) {
@@ -327,10 +333,11 @@
     @VisibleForTesting
     boolean shouldDismissLowBatteryWarning(boolean plugged, int oldBucket, int bucket,
             long timeRemaining, boolean isPowerSaver) {
-        final boolean hybridWouldDismiss = mEnhancedEstimates.isHybridNotificationEnabled()
+        final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled();
+        final boolean hybridWouldDismiss = hybridEnabled
                 && timeRemaining > mEnhancedEstimates.getLowWarningThreshold();
         final boolean standardWouldDismiss = (bucket > oldBucket && bucket > 0);
-        return isPowerSaver
+        return (isPowerSaver && !hybridEnabled)
                 || plugged
                 || (standardWouldDismiss && (!mEnhancedEstimates.isHybridNotificationEnabled()
                         || hybridWouldDismiss));
@@ -338,14 +345,14 @@
 
     private boolean isEnhancedTrigger(boolean plugged, long timeRemaining, boolean isPowerSaver,
             int batteryStatus) {
-        if (plugged || isPowerSaver || batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
+        if (plugged || batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
             return false;
         }
         int warnLevel = mLowBatteryReminderLevels[0];
         int critLevel = mLowBatteryReminderLevels[1];
 
-        // Only show the low warning once per charge cycle
-        final boolean canShowWarning = !mLowWarningShownThisChargeCycle
+        // Only show the low warning once per charge cycle & no battery saver
+        final boolean canShowWarning = !mLowWarningShownThisChargeCycle && !isPowerSaver
                 && (timeRemaining < mEnhancedEstimates.getLowWarningThreshold()
                         || mBatteryLevel <= warnLevel);
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
index 2a2bc09..dfd3f73 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
@@ -72,6 +72,12 @@
         }
     }
 
+    public void setTileRemoved(String tile) {
+        if (mAutoAdded.remove(tile)) {
+            saveTiles();
+        }
+    }
+
     public void destroy() {
         mContext.getContentResolver().unregisterContentObserver(mObserver);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index f13f489..f1b7eec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -55,7 +55,6 @@
     private Scroller mScroller;
 
     private AnimatorSet mBounceAnimatorSet;
-    private int mAnimatingToPage = -1;
     private float mLastExpansion;
 
     public PagedTileLayout(Context context, AttributeSet attrs) {
@@ -95,40 +94,16 @@
     }
 
     @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        // Suppress all touch event during reveal animation.
-        if (mAnimatingToPage != -1) {
-            return true;
-        }
-        return super.onInterceptTouchEvent(ev);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        // Suppress all touch event during reveal animation.
-        if (mAnimatingToPage != -1) {
-            return true;
-        }
-        return super.onTouchEvent(ev);
-    }
-
-    @Override
     public void computeScroll() {
         if (!mScroller.isFinished() && mScroller.computeScrollOffset()) {
-            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
-            float pageFraction = (float) getScrollX() / getWidth();
-            int position = (int) pageFraction;
-            float positionOffset = pageFraction - position;
-            mOnPageChangeListener.onPageScrolled(position, positionOffset, getScrollX());
+            fakeDragBy(getScrollX() - mScroller.getCurrX());
             // Keep on drawing until the animation has finished.
             postInvalidateOnAnimation();
             return;
-        }
-        if (mAnimatingToPage != -1) {
-            setCurrentItem(mAnimatingToPage, true);
+        } else if (isFakeDragging()) {
+            endFakeDrag();
             mBounceAnimatorSet.start();
             setOffscreenPageLimit(1);
-            mAnimatingToPage = -1;
         }
         super.computeScroll();
     }
@@ -287,7 +262,7 @@
     }
 
     public void startTileReveal(Set<String> tileSpecs, final Runnable postAnimation) {
-        if (tileSpecs.isEmpty() || mPages.size() < 2 || getScrollX() != 0) {
+        if (tileSpecs.isEmpty() || mPages.size() < 2 || getScrollX() != 0 || !beginFakeDrag()) {
             // Do not start the reveal animation unless there are tiles to animate, multiple
             // TilePages available and the user has not already started dragging.
             return;
@@ -305,6 +280,7 @@
         if (bounceAnims.isEmpty()) {
             // All tileSpecs are on the first page. Nothing to do.
             // TODO: potentially show a bounce animation for first page QS tiles
+            endFakeDrag();
             return;
         }
 
@@ -317,10 +293,10 @@
                 postAnimation.run();
             }
         });
-        mAnimatingToPage = lastPageNumber;
-        setOffscreenPageLimit(mAnimatingToPage); // Ensure the page to reveal has been inflated.
-        mScroller.startScroll(getScrollX(), getScrollY(), getWidth() * mAnimatingToPage, 0,
-                REVEAL_SCROLL_DURATION_MILLIS);
+        setOffscreenPageLimit(lastPageNumber); // Ensure the page to reveal has been inflated.
+        int dx = getWidth() * lastPageNumber;
+        mScroller.startScroll(getScrollX(), getScrollY(), isLayoutRtl() ? -dx  : dx, 0,
+            REVEAL_SCROLL_DURATION_MILLIS);
         postInvalidateOnAnimation();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
index a1c2577..87c64c7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
@@ -47,16 +47,12 @@
         final int N = a.getIndexCount();
         for (int i = 0; i < N; i++) {
             int attr = a.getIndex(i);
-            switch (attr) {
-                case R.styleable.PseudoGridView_numColumns:
-                    mNumColumns = a.getInt(attr, 3);
-                    break;
-                case R.styleable.PseudoGridView_verticalSpacing:
-                    mVerticalSpacing = a.getDimensionPixelSize(attr, 0);
-                    break;
-                case R.styleable.PseudoGridView_horizontalSpacing:
-                    mHorizontalSpacing = a.getDimensionPixelSize(attr, 0);
-                    break;
+            if (attr == R.styleable.PseudoGridView_numColumns) {
+                mNumColumns = a.getInt(attr, 3);
+            } else if (attr == R.styleable.PseudoGridView_verticalSpacing) {
+                mVerticalSpacing = a.getDimensionPixelSize(attr, 0);
+            } else if (attr == R.styleable.PseudoGridView_horizontalSpacing) {
+                mHorizontalSpacing = a.getDimensionPixelSize(attr, 0);
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 80b6c73..feff5d4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -70,7 +70,6 @@
         mBackgroundGradient = findViewById(R.id.quick_settings_gradient_view);
         mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
 
-        setClickable(true);
         setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
         setMargins();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index a6b065f..f147fb3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -123,8 +123,6 @@
         mMobileSignal = findViewById(R.id.mobile_signal);
         mMobileRoaming = findViewById(R.id.mobile_roaming);
         mCarrierText = findViewById(R.id.qs_carrier_text);
-        mCarrierText.setDisplayFlags(
-                CarrierText.FLAG_HIDE_AIRPLANE_MODE | CarrierText.FLAG_HIDE_MISSING_SIM);
 
         mMultiUserSwitch = findViewById(R.id.multi_user_switch);
         mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index bd89ad1..7cb22a3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -19,7 +19,6 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.app.Fragment;
-import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -45,7 +44,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 public class QSFragment extends Fragment implements QS, CommandQueue.Callbacks {
     private static final String TAG = "QS";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index 84524a6..84fa700 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -32,6 +32,7 @@
     void removeCallback(Callback callback);
     TileServices getTileServices();
     void removeTile(String tileSpec);
+    void unmarkTileAsAutoAdded(String tileSpec);
 
     int indexOf(String tileSpec);
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 0876a5d..3fc258b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -285,9 +285,6 @@
 
         updatePageIndicator();
 
-        for (TileRecord r : mRecords) {
-            r.tile.clearState();
-        }
         if (mListening) {
             refreshAllTiles();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 02937d8..86e69e3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -50,6 +50,7 @@
 import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.function.Predicate;
 
 /** Platform implementation of the quick settings tile host **/
 public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory> {
@@ -226,23 +227,27 @@
     }
 
     @Override
-    public void removeTile(String tileSpec) {
-        ArrayList<String> specs = new ArrayList<>(mTileSpecs);
-        specs.remove(tileSpec);
-        Settings.Secure.putStringForUser(mContext.getContentResolver(), TILES_SETTING,
-                TextUtils.join(",", specs), ActivityManager.getCurrentUser());
+    public void removeTile(String spec) {
+        changeTileSpecs(tileSpecs-> tileSpecs.remove(spec));
+    }
+
+    @Override
+    public void unmarkTileAsAutoAdded(String spec) {
+        mAutoTiles.unmarkTileAsAutoAdded(spec);
     }
 
     public void addTile(String spec) {
+        changeTileSpecs(tileSpecs-> tileSpecs.add(spec));
+    }
+
+    private void changeTileSpecs(Predicate<List<String>> changeFunction) {
         final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
-                TILES_SETTING, ActivityManager.getCurrentUser());
+            TILES_SETTING, ActivityManager.getCurrentUser());
         final List<String> tileSpecs = loadTileSpecs(mContext, setting);
-        if (tileSpecs.contains(spec)) {
-            return;
-        }
-        tileSpecs.add(spec);
-        Settings.Secure.putStringForUser(mContext.getContentResolver(), TILES_SETTING,
+        if (changeFunction.test(tileSpecs)) {
+            Settings.Secure.putStringForUser(mContext.getContentResolver(), TILES_SETTING,
                 TextUtils.join(",", tileSpecs), ActivityManager.getCurrentUser());
+        }
     }
 
     public void addTile(ComponentName tile) {
@@ -300,7 +305,7 @@
         throw new RuntimeException("Default factory didn't create view for " + tile.getTileSpec());
     }
 
-    protected List<String> loadTileSpecs(Context context, String tileList) {
+    protected static List<String> loadTileSpecs(Context context, String tileList) {
         final Resources res = context.getResources();
         final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
         if (tileList == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index a218868..ff5ac76 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -33,6 +33,7 @@
 import android.os.Handler;
 import android.provider.AlarmClock;
 import android.service.notification.ZenModeConfig;
+import android.widget.FrameLayout;
 import androidx.annotation.VisibleForTesting;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
@@ -270,8 +271,22 @@
         updateResources();
     }
 
+    /**
+     * The height of QQS should always be the status bar height + 128dp. This is normally easy, but
+     * when there is a notch involved the status bar can remain a fixed pixel size.
+     */
+    private void updateMinimumHeight() {
+        int sbHeight = mContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_height);
+        int qqsHeight = mContext.getResources().getDimensionPixelSize(
+                R.dimen.qs_quick_header_panel_height);
+
+        setMinimumHeight(sbHeight + qqsHeight);
+    }
+
     private void updateResources() {
         Resources resources = mContext.getResources();
+        updateMinimumHeight();
 
         // Update height for a few views, especially due to landscape mode restricting space.
         mHeaderTextContainerView.getLayoutParams().height =
@@ -282,10 +297,17 @@
                 com.android.internal.R.dimen.quick_qs_offset_height);
         mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
 
-        getLayoutParams().height = resources.getDimensionPixelSize(mQsDisabled
-                ? com.android.internal.R.dimen.quick_qs_offset_height
-                : com.android.internal.R.dimen.quick_qs_total_height);
-        setLayoutParams(getLayoutParams());
+        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+        if (mQsDisabled) {
+            lp.height = resources.getDimensionPixelSize(
+                    com.android.internal.R.dimen.quick_qs_offset_height);
+        } else {
+            lp.height = Math.max(getMinimumHeight(),
+                    resources.getDimensionPixelSize(
+                            com.android.internal.R.dimen.quick_qs_total_height));
+        }
+
+        setLayoutParams(lp);
 
         updateStatusIconAlphaAnimator();
         updateHeaderTextContainerAlphaAnimator();
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 78e9f36..92f5cae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -62,6 +62,7 @@
     private static final int TYPE_TILE = 0;
     private static final int TYPE_EDIT = 1;
     private static final int TYPE_ACCESSIBLE_DROP = 2;
+    private static final int TYPE_HEADER = 3;
     private static final int TYPE_DIVIDER = 4;
 
     private static final long EDIT_ID = 10000;
@@ -88,6 +89,7 @@
     private Holder mCurrentDrag;
     private int mAccessibilityAction = ACTION_NONE;
     private int mAccessibilityFromIndex;
+    private CharSequence mAccessibilityFromLabel;
     private QSTileHost mHost;
 
     public TileAdapter(Context context) {
@@ -111,7 +113,7 @@
 
     public void saveSpecs(QSTileHost host) {
         List<String> newSpecs = new ArrayList<>();
-        for (int i = 0; i < mTiles.size() && mTiles.get(i) != null; i++) {
+        for (int i = 1; i < mTiles.size() && mTiles.get(i) != null; i++) {
             newSpecs.add(mTiles.get(i).spec);
         }
         host.changeTiles(mCurrentSpecs, newSpecs);
@@ -144,6 +146,7 @@
         }
         mOtherTiles = new ArrayList<TileInfo>(mAllTiles);
         mTiles.clear();
+        mTiles.add(null);
         for (int i = 0; i < mCurrentSpecs.size(); i++) {
             final TileInfo tile = getAndRemoveOther(mCurrentSpecs.get(i));
             if (tile != null) {
@@ -176,6 +179,9 @@
 
     @Override
     public int getItemViewType(int position) {
+        if (position == 0) {
+            return TYPE_HEADER;
+        }
         if (mAccessibilityAction == ACTION_ADD && position == mEditIndex - 1) {
             return TYPE_ACCESSIBLE_DROP;
         }
@@ -192,6 +198,9 @@
     public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
         final Context context = parent.getContext();
         LayoutInflater inflater = LayoutInflater.from(context);
+        if (viewType == TYPE_HEADER) {
+            return new Holder(inflater.inflate(R.layout.qs_customize_header, parent, false));
+        }
         if (viewType == TYPE_DIVIDER) {
             return new Holder(inflater.inflate(R.layout.qs_customize_tile_divider, parent, false));
         }
@@ -217,6 +226,9 @@
 
     @Override
     public void onBindViewHolder(final Holder holder, int position) {
+        if (holder.getItemViewType() == TYPE_HEADER) {
+            return;
+        }
         if (holder.getItemViewType() == TYPE_DIVIDER) {
             holder.itemView.setVisibility(mTileDividerIndex < mTiles.size() - 1 ? View.VISIBLE
                     : View.INVISIBLE);
@@ -241,7 +253,8 @@
             holder.mTileView.setVisibility(View.VISIBLE);
             holder.mTileView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
             holder.mTileView.setContentDescription(mContext.getString(
-                    R.string.accessibility_qs_edit_position_label, position + 1));
+                    R.string.accessibility_qs_edit_tile_add, mAccessibilityFromLabel,
+                    position));
             holder.mTileView.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
@@ -270,12 +283,15 @@
         if (position > mEditIndex) {
             info.state.contentDescription = mContext.getString(
                     R.string.accessibility_qs_edit_add_tile_label, info.state.label);
-        } else if (mAccessibilityAction != ACTION_NONE) {
+        } else if (mAccessibilityAction == ACTION_ADD) {
             info.state.contentDescription = mContext.getString(
-                    R.string.accessibility_qs_edit_position_label, position + 1);
+                    R.string.accessibility_qs_edit_tile_add, mAccessibilityFromLabel, position);
+        } else if (mAccessibilityAction == ACTION_MOVE) {
+            info.state.contentDescription = mContext.getString(
+                    R.string.accessibility_qs_edit_tile_move, mAccessibilityFromLabel, position);
         } else {
             info.state.contentDescription = mContext.getString(
-                    R.string.accessibility_qs_edit_tile_label, position + 1, info.state.label);
+                    R.string.accessibility_qs_edit_tile_label, position, info.state.label);
         }
         holder.mTileView.handleStateChanged(info.state);
         holder.mTileView.setShowAppLabel(position > mEditIndex && !info.isSystem);
@@ -351,6 +367,7 @@
 
     private void startAccessibleAdd(int position) {
         mAccessibilityFromIndex = position;
+        mAccessibilityFromLabel = mTiles.get(position).state.label;
         mAccessibilityAction = ACTION_ADD;
         // Add placeholder for last slot.
         mTiles.add(mEditIndex++, null);
@@ -360,6 +377,7 @@
 
     private void startAccessibleMove(int position) {
         mAccessibilityFromIndex = position;
+        mAccessibilityFromLabel = mTiles.get(position).state.label;
         mAccessibilityAction = ACTION_MOVE;
         notifyDataSetChanged();
     }
@@ -385,26 +403,23 @@
                     strip(mTiles.get(to)));
             MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_ADD,
                     to);
-            v.announceForAccessibility(mContext.getString(R.string.accessibility_qs_edit_tile_added,
-                    fromLabel, (to + 1)));
         } else {
             MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_MOVE_SPEC,
                     strip(mTiles.get(to)));
             MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_MOVE,
                     to);
-            v.announceForAccessibility(mContext.getString(R.string.accessibility_qs_edit_tile_moved,
-                    fromLabel, (to + 1)));
         }
         saveSpecs(mHost);
         return true;
     }
 
     private void updateDividerLocations() {
-        // The first null is the edit tiles label, the second null is the tile divider.
-        // If there is no second null, then there are no non-system tiles.
+        // The first null is the header label (index 0) so we can skip it,
+        // the second null is the edit tiles label, the third null is the tile divider.
+        // If there is no third null, then there are no non-system tiles.
         mEditIndex = -1;
         mTileDividerIndex = mTiles.size();
-        for (int i = 0; i < mTiles.size(); i++) {
+        for (int i = 1; i < mTiles.size(); i++) {
             if (mTiles.get(i) == null) {
                 if (mEditIndex == -1) {
                     mEditIndex = i;
@@ -483,7 +498,7 @@
         @Override
         public int getSpanSize(int position) {
             final int type = getItemViewType(position);
-            return type == TYPE_EDIT || type == TYPE_DIVIDER ? 3 : 1;
+            return type == TYPE_EDIT || type == TYPE_DIVIDER || type == TYPE_HEADER ? 3 : 1;
         }
     };
 
@@ -508,7 +523,8 @@
             for (int i = 0; i < childCount; i++) {
                 final View child = parent.getChildAt(i);
                 final ViewHolder holder = parent.getChildViewHolder(child);
-                if (holder.getAdapterPosition() < mEditIndex && !(child instanceof TextView)) {
+                if (holder.getAdapterPosition() == 0 ||
+                        holder.getAdapterPosition() < mEditIndex && !(child instanceof TextView)) {
                     continue;
                 }
 
@@ -566,6 +582,9 @@
         @Override
         public boolean canDropOver(RecyclerView recyclerView, ViewHolder current,
                 ViewHolder target) {
+            if (target.getAdapterPosition() == 0){
+                return false;
+            }
             if (!canRemoveTiles() && current.getAdapterPosition() < mEditIndex) {
                 return target.getAdapterPosition() < mEditIndex;
             }
@@ -574,12 +593,17 @@
 
         @Override
         public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {
-            if (viewHolder.getItemViewType() == TYPE_EDIT || viewHolder.getItemViewType() == TYPE_DIVIDER) {
-                return makeMovementFlags(0, 0);
+            switch (viewHolder.getItemViewType()) {
+                case TYPE_EDIT:
+                case TYPE_DIVIDER:
+                case TYPE_HEADER:
+                    // Fall through
+                    return makeMovementFlags(0, 0);
+                default:
+                    int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN
+                            | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT;
+                    return makeMovementFlags(dragFlags, 0);
             }
-            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT
-                    | ItemTouchHelper.LEFT;
-            return makeMovementFlags(dragFlags, 0);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 53a576d..591e9e0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -95,7 +95,6 @@
                 continue;
             }
             tile.setListening(this, true);
-            tile.clearState();
             tile.refreshState();
             tile.setListening(this, false);
             tile.setTileSpec(spec);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 6bc3bee..b6a776f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -211,10 +211,6 @@
         mHandler.obtainMessage(H.REFRESH_STATE, arg).sendToTarget();
     }
 
-    public void clearState() {
-        mHandler.sendEmptyMessage(H.CLEAR_STATE);
-    }
-
     public void userSwitch(int newUserId) {
         mHandler.obtainMessage(H.USER_SWITCH, newUserId, 0).sendToTarget();
     }
@@ -266,11 +262,6 @@
 
     public abstract Intent getLongClickIntent();
 
-    protected void handleClearState() {
-        mTmpState = newTileState();
-        mState = newTileState();
-    }
-
     protected void handleRefreshState(Object arg) {
         handleUpdateState(mTmpState, arg);
         final boolean changed = mTmpState.copyTo(mState);
@@ -409,11 +400,10 @@
         private static final int TOGGLE_STATE_CHANGED = 8;
         private static final int SCAN_STATE_CHANGED = 9;
         private static final int DESTROY = 10;
-        private static final int CLEAR_STATE = 11;
-        private static final int REMOVE_CALLBACKS = 12;
-        private static final int REMOVE_CALLBACK = 13;
-        private static final int SET_LISTENING = 14;
-        private static final int STALE = 15;
+        private static final int REMOVE_CALLBACKS = 11;
+        private static final int REMOVE_CALLBACK = 12;
+        private static final int SET_LISTENING = 13;
+        private static final int STALE = 14;
 
         @VisibleForTesting
         protected H(Looper looper) {
@@ -467,9 +457,6 @@
                 } else if (msg.what == DESTROY) {
                     name = "handleDestroy";
                     handleDestroy();
-                } else if (msg.what == CLEAR_STATE) {
-                    name = "handleClearState";
-                    handleClearState();
                 } else if (msg.what == SET_LISTENING) {
                     name = "handleSetListeningInternal";
                     handleSetListeningInternal(msg.obj, msg.arg1 != 0);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index d1e33d3..50c8698 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -142,14 +142,16 @@
 
     @Override
     public void showDetail(boolean show) {
-        int zenDuration = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.ZEN_DURATION, 0);
-        boolean showOnboarding = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0;
+        int zenDuration = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.ZEN_DURATION, 0);
+        boolean showOnboarding = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
+                && Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
         if (showOnboarding) {
             // don't show on-boarding again or notification ever
-            Settings.Global.putInt(mContext.getContentResolver(),
-                    Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
             // turn on DND
             mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG);
             // show on-boarding screen
@@ -158,7 +160,7 @@
             Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(intent, 0);
         } else {
             switch (zenDuration) {
-                case Settings.Global.ZEN_DURATION_PROMPT:
+                case Settings.Secure.ZEN_DURATION_PROMPT:
                     mUiHandler.post(() -> {
                         Dialog mDialog = new EnableZenModeDialog(mContext).createDialog();
                         mDialog.getWindow().setType(
@@ -170,7 +172,7 @@
                         mHost.collapsePanels();
                     });
                     break;
-                case Settings.Global.ZEN_DURATION_FOREVER:
+                case Settings.Secure.ZEN_DURATION_FOREVER:
                     mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG);
                     break;
                 default:
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index e0a9148..c41f087 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -26,7 +26,6 @@
 import android.service.quicksettings.Tile;
 import androidx.annotation.StringRes;
 import android.text.TextUtils;
-import android.text.format.DateFormat;
 import android.util.Log;
 import android.widget.Switch;
 
@@ -37,8 +36,11 @@
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
+import java.text.DateFormat;
 import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.TimeZone;
 
 public class NightDisplayTile extends QSTileImpl<BooleanState>
         implements ColorDisplayController.Callback {
@@ -144,13 +146,17 @@
                     toggleTimeStringRes = R.string.quick_settings_night_secondary_label_on_at;
                 }
 
-                // Choose between just showing the hour or also showing the minutes (based on the
-                // user-selected toggle time). This helps reduce how much space the label takes.
-                toggleTimeFormat = DateTimeFormatter.ofPattern(
-                        DateFormat.is24HourFormat(mContext) ? PATTERN_HOUR_NINUTE_24 :
-                        toggleTime.getMinute() == 0 ? PATTERN_HOUR : PATTERN_HOUR_MINUTE);
-
-                return mContext.getString(toggleTimeStringRes, toggleTime.format(toggleTimeFormat));
+                // TODO(b/111085930): Move this calendar snippet to a common code location that
+                // settings lib can also access.
+                final Calendar c = Calendar.getInstance();
+                DateFormat nightTileFormat = android.text.format.DateFormat.getTimeFormat(mContext);
+                nightTileFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+                c.setTimeZone(nightTileFormat.getTimeZone());
+                c.set(Calendar.HOUR_OF_DAY, toggleTime.getHour());
+                c.set(Calendar.MINUTE, toggleTime.getMinute());
+                c.set(Calendar.SECOND, 0);
+                c.set(Calendar.MILLISECOND, 0);
+                return mContext.getString(toggleTimeStringRes, nightTileFormat.format(c.getTime()));
 
             default:
                 // No secondary label when auto mode is disabled.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index 1e9a618..ad7d1b6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -69,13 +69,10 @@
         final int N = a.getIndexCount();
         for (int i = 0; i < N; i++) {
             int attr = a.getIndex(i);
-            switch (attr) {
-                case R.styleable.UserDetailItemView_regularFontFamily:
-                    mRegularTypeface = Typeface.create(a.getString(attr), 0 /* style */);
-                    break;
-                case R.styleable.UserDetailItemView_activatedFontFamily:
-                    mActivatedTypeface = Typeface.create(a.getString(attr), 0 /* style */);
-                    break;
+            if (attr == R.styleable.UserDetailItemView_regularFontFamily) {
+                mRegularTypeface = Typeface.create(a.getString(attr), 0 /* style */);
+            } else if (attr == R.styleable.UserDetailItemView_activatedFontFamily) {
+                mActivatedTypeface = Typeface.create(a.getString(attr), 0 /* style */);
             }
         }
         a.recycle();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 5bab3e8..3109dea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -78,6 +78,7 @@
     @Override
     public void onManagedProfileRemoved() {
         mHost.removeTile(getTileSpec());
+        mHost.unmarkTileAsAutoAdded(getTileSpec());
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 7e4acc2..63a65d0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -48,6 +48,7 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.OverviewProxyService;
+import com.android.systemui.SysUiServiceProvider;
 import com.google.android.collect.Lists;
 
 import com.android.internal.logging.MetricsLogger;
@@ -1095,7 +1096,7 @@
     }
 
     private StatusBar getStatusBar() {
-        return ((SystemUIApplication) mContext).getComponent(StatusBar.class);
+        return SysUiServiceProvider.getComponent(mContext, StatusBar.class);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index ce9d7e1..db2b69f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -88,16 +88,16 @@
     // Show quick scrub tips after opening overview this number of times.
     private static final int QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT = 10;
     // Maximum number of dismissals while still showing swipe-up tips.
-    private static final int MAX_DISMISSAL_ON_SWIPE_UP_SHOW = 4;
+    private static final int MAX_DISMISSAL_ON_SWIPE_UP_SHOW = 2;
     // Number of dismissals for swipe-up tips when exponential backoff starts.
-    private static final int BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW = 2;
+    private static final int BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW = 1;
     // After explicitly dismissing for <= BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW times, show again
     // after launching this number of apps for swipe-up tips.
     private static final int SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS = 5;
     // After explicitly dismissing for > BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW but
     // <= MAX_DISMISSAL_ON_SWIPE_UP_SHOW times, show again after launching this number of apps for
     // swipe-up tips.
-    private static final int SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS_BACK_OFF = 10;
+    private static final int SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS_BACK_OFF = 40;
 
     private final Context mContext;
     private final WindowManager mWindowManager;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java
index 2c1158d..b4212d3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java
@@ -21,6 +21,7 @@
 import android.os.IBinder;
 import android.util.Log;
 
+import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.SystemUIApplication;
 
 /**
@@ -40,8 +41,7 @@
 
     @Override
     public IBinder onBind(Intent intent) {
-        SystemUIApplication app = (SystemUIApplication) getApplication();
-        Recents recents = app.getComponent(Recents.class);
+        Recents recents = SysUiServiceProvider.getComponent(this, Recents.class);
         if (DEBUG) {
             Log.d(TAG, "onBind: " + recents);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 64ccba8..5eaee54 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -16,9 +16,11 @@
 
 package com.android.systemui.screenshot;
 
+import static android.content.Context.NOTIFICATION_SERVICE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-
-import static com.android.systemui.screenshot.GlobalScreenshot.SHARING_INTENT;
+import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_INTENT;
+import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION;
+import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP;
 import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
 
 import android.animation.Animator;
@@ -26,7 +28,6 @@
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.Notification;
 import android.app.Notification.BigPictureStyle;
@@ -56,9 +57,9 @@
 import android.os.Environment;
 import android.os.PowerManager;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.MediaStore;
+import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Slog;
@@ -73,12 +74,13 @@
 import android.view.animation.Interpolator;
 import android.widget.ImageView;
 import android.widget.Toast;
-
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.SystemUI;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.NotificationChannels;
-
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.OutputStream;
@@ -277,7 +279,12 @@
             values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length());
             Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
 
-            // Create a share intent
+            // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
+            // order to do some common work like dismissing the keyguard and sending
+            // closeSystemWindows
+
+            // Create a share intent, this will always go through the chooser activity first which
+            // should not trigger auto-enter PiP
             String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
             String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
             Intent sharingIntent = new Intent(Intent.ACTION_SEND);
@@ -286,37 +293,47 @@
             sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
             sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
-            // Create a share action for the notification. Note, we proxy the call to
-            // ScreenshotActionReceiver because RemoteViews currently forces an activity options
-            // on the PendingIntent being launched, and since we don't want to trigger the share
-            // sheet in this case, we start the chooser activity directly in
-            // ScreenshotActionReceiver.
-            PendingIntent shareAction = PendingIntent.getBroadcast(context, 0,
-                    new Intent(context, GlobalScreenshot.ScreenshotActionReceiver.class)
-                            .putExtra(SHARING_INTENT, sharingIntent),
-                    PendingIntent.FLAG_CANCEL_CURRENT);
+            PendingIntent chooserAction = PendingIntent.getBroadcast(context, 0,
+                    new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
+                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+            Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
+                    chooserAction.getIntentSender())
+                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            // Create a share action for the notification
+            PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, 0,
+                    new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+                            .putExtra(EXTRA_ACTION_INTENT, sharingChooserIntent)
+                            .putExtra(EXTRA_DISALLOW_ENTER_PIP, true),
+                    PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
             Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
                     R.drawable.ic_screenshot_share,
                     r.getString(com.android.internal.R.string.share), shareAction);
             mNotificationBuilder.addAction(shareActionBuilder.build());
 
+            // Create an edit intent, if a specific package is provided as the editor, then launch
+            // that directly
+            String editorPackage = context.getString(R.string.config_screenshotEditor);
             Intent editIntent = new Intent(Intent.ACTION_EDIT);
+            if (!TextUtils.isEmpty(editorPackage)) {
+                editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
+            }
             editIntent.setType("image/png");
             editIntent.setData(uri);
             editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
             editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 
-            // Create a edit action for the notification the same way.
-            PendingIntent editAction = PendingIntent.getBroadcast(context, 1,
-                    new Intent(context, GlobalScreenshot.ScreenshotActionReceiver.class)
-                            .putExtra(SHARING_INTENT, editIntent),
-                    PendingIntent.FLAG_CANCEL_CURRENT);
+            // Create a edit action
+            PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, 1,
+                    new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+                            .putExtra(EXTRA_ACTION_INTENT, editIntent)
+                            .putExtra(EXTRA_CANCEL_NOTIFICATION, editIntent.getComponent() != null),
+                    PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
             Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
                     R.drawable.ic_screenshot_edit,
                     r.getString(com.android.internal.R.string.screenshot_edit), editAction);
             mNotificationBuilder.addAction(editActionBuilder.build());
 
-
             // Create a delete action for the notification
             PendingIntent deleteAction = PendingIntent.getBroadcast(context, 0,
                     new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
@@ -429,7 +446,9 @@
 
 class GlobalScreenshot {
     static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
-    static final String SHARING_INTENT = "android:screenshot_sharing_intent";
+    static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
+    static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
+    static final String EXTRA_DISALLOW_ENTER_PIP = "android:screenshot_disallow_enter_pip";
 
     private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
     private static final int SCREENSHOT_DROP_IN_DURATION = 430;
@@ -452,7 +471,6 @@
     private NotificationManager mNotificationManager;
     private Display mDisplay;
     private DisplayMetrics mDisplayMetrics;
-    private Matrix mDisplayMatrix;
 
     private Bitmap mScreenBitmap;
     private View mScreenshotLayout;
@@ -482,7 +500,6 @@
                 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
         // Inflate the screenshot layout
-        mDisplayMatrix = new Matrix();
         mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
         mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
         mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
@@ -512,7 +529,7 @@
         mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         mNotificationManager =
-            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+            (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
         mDisplay = mWindowManager.getDefaultDisplay();
         mDisplayMetrics = new DisplayMetrics();
         mDisplay.getRealMetrics(mDisplayMetrics);
@@ -562,21 +579,6 @@
     }
 
     /**
-     * @return the current display rotation in degrees
-     */
-    private float getDegreesForRotation(int value) {
-        switch (value) {
-        case Surface.ROTATION_90:
-            return 360f - 90f;
-        case Surface.ROTATION_180:
-            return 360f - 180f;
-        case Surface.ROTATION_270:
-            return 360f - 270f;
-        }
-        return 0f;
-    }
-
-    /**
      * Takes a screenshot of the current display and shows an animation.
      */
     private void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible,
@@ -891,52 +893,39 @@
     }
 
     /**
-     * Receiver to proxy the share or edit intent.
+     * Receiver to proxy the share or edit intent, used to clean up the notification and send
+     * appropriate signals to the system (ie. to dismiss the keyguard if necessary).
      */
-    public static class ScreenshotActionReceiver extends BroadcastReceiver {
+    public static class ActionProxyReceiver extends BroadcastReceiver {
         @Override
-        public void onReceive(Context context, Intent intent) {
-            try {
-                ActivityManager.getService().closeSystemDialogs(SYSTEM_DIALOG_REASON_SCREENSHOT);
-            } catch (RemoteException e) {
-            }
+        public void onReceive(Context context, final Intent intent) {
+            Runnable startActivityRunnable = () -> {
+                ActivityManagerWrapper.getInstance().closeSystemWindows(
+                        SYSTEM_DIALOG_REASON_SCREENSHOT);
 
-            Intent actionIntent = intent.getParcelableExtra(SHARING_INTENT);
-
-            // If this is an edit & default editor exists, route straight there.
-            String editorPackage = context.getResources().getString(R.string.config_screenshotEditor);
-            if (actionIntent.getAction() == Intent.ACTION_EDIT &&
-                    editorPackage != null && editorPackage.length() > 0) {
-                actionIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
-                final NotificationManager nm =
-                        (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-                nm.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
-            } else {
-                PendingIntent chooseAction = PendingIntent.getBroadcast(context, 0,
-                        new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
-                        PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
-                actionIntent = Intent.createChooser(actionIntent, null,
-                        chooseAction.getIntentSender())
-                        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
-            }
-
-            ActivityOptions opts = ActivityOptions.makeBasic();
-            opts.setDisallowEnterPictureInPictureWhileLaunching(true);
-
-            context.startActivityAsUser(actionIntent, opts.toBundle(), UserHandle.CURRENT);
+                Intent actionIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
+                if (intent.getBooleanExtra(EXTRA_CANCEL_NOTIFICATION, false)) {
+                    cancelScreenshotNotification(context);
+                }
+                ActivityOptions opts = ActivityOptions.makeBasic();
+                opts.setDisallowEnterPictureInPictureWhileLaunching(
+                        intent.getBooleanExtra(EXTRA_DISALLOW_ENTER_PIP, false));
+                context.startActivityAsUser(actionIntent, opts.toBundle(), UserHandle.CURRENT);
+            };
+            StatusBar statusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
+            statusBar.executeRunnableDismissingKeyguard(startActivityRunnable, null,
+                    true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
         }
     }
 
     /**
-     * Removes the notification for a screenshot after a share or edit target is chosen.
+     * Removes the notification for a screenshot after a share target is chosen.
      */
     public static class TargetChosenReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
-            // Clear the notification
-            final NotificationManager nm =
-                    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-            nm.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+            // Clear the notification only after the user has chosen a share action
+            cancelScreenshotNotification(context);
         }
     }
 
@@ -950,14 +939,18 @@
                 return;
             }
 
-            // Clear the notification
-            final NotificationManager nm =
-                    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-            final Uri uri = Uri.parse(intent.getStringExtra(SCREENSHOT_URI_ID));
-            nm.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+            // Clear the notification when the image is deleted
+            cancelScreenshotNotification(context);
 
             // And delete the image from the media store
+            final Uri uri = Uri.parse(intent.getStringExtra(SCREENSHOT_URI_ID));
             new DeleteImageInBackgroundTask(context).execute(uri);
         }
     }
+
+    private static void cancelScreenshotNotification(Context context) {
+        final NotificationManager nm =
+                (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
+        nm.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 3eb3160..98925b9 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -226,22 +226,16 @@
         public boolean performAccessibilityAction(View host, int action, Bundle args) {
             int currentPosition = getCurrentPosition();
             SnapTarget nextTarget = null;
-            switch (action) {
-                case R.id.action_move_tl_full:
-                    nextTarget = mSnapAlgorithm.getDismissEndTarget();
-                    break;
-                case R.id.action_move_tl_70:
-                    nextTarget = mSnapAlgorithm.getLastSplitTarget();
-                    break;
-                case R.id.action_move_tl_50:
-                    nextTarget = mSnapAlgorithm.getMiddleTarget();
-                    break;
-                case R.id.action_move_tl_30:
-                    nextTarget = mSnapAlgorithm.getFirstSplitTarget();
-                    break;
-                case R.id.action_move_rb_full:
-                    nextTarget = mSnapAlgorithm.getDismissStartTarget();
-                    break;
+            if (action == R.id.action_move_tl_full) {
+                nextTarget = mSnapAlgorithm.getDismissEndTarget();
+            } else if (action == R.id.action_move_tl_70) {
+                nextTarget = mSnapAlgorithm.getLastSplitTarget();
+            } else if (action == R.id.action_move_tl_50) {
+                nextTarget = mSnapAlgorithm.getMiddleTarget();
+            } else if (action == R.id.action_move_tl_30) {
+                nextTarget = mSnapAlgorithm.getFirstSplitTarget();
+            } else if (action == R.id.action_move_rb_full) {
+                nextTarget = mSnapAlgorithm.getDismissStartTarget();
             }
             if (nextTarget != null) {
                 startDragging(true /* animate */, false /* touching */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
deleted file mode 100644
index 6a387971..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ /dev/null
@@ -1,1098 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.TimeAnimator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.util.MathUtils;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewAnimationUtils;
-import android.view.accessibility.AccessibilityManager;
-import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.statusbar.notification.FakeShadowView;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.phone.DoubleTapHelper;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
-
-/**
- * Base class for both {@link ExpandableNotificationRow} and {@link NotificationShelf}
- * to implement dimming/activating on Keyguard for the double-tap gesture
- */
-public abstract class ActivatableNotificationView extends ExpandableOutlineView {
-
-    private static final int BACKGROUND_ANIMATION_LENGTH_MS = 220;
-    private static final int ACTIVATE_ANIMATION_LENGTH = 220;
-    private static final long DARK_ANIMATION_LENGTH = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
-
-    /**
-     * The amount of width, which is kept in the end when performing a disappear animation (also
-     * the amount from which the horizontal appearing begins)
-     */
-    private static final float HORIZONTAL_COLLAPSED_REST_PARTIAL = 0.05f;
-
-    /**
-     * At which point from [0,1] does the horizontal collapse animation end (or start when
-     * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
-     */
-    private static final float HORIZONTAL_ANIMATION_END = 0.2f;
-
-    /**
-     * At which point from [0,1] does the alpha animation end (or start when
-     * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
-     */
-    private static final float ALPHA_ANIMATION_END = 0.0f;
-
-    /**
-     * At which point from [0,1] does the horizontal collapse animation start (or start when
-     * expanding)? 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
-     */
-    private static final float HORIZONTAL_ANIMATION_START = 1.0f;
-
-    /**
-     * At which point from [0,1] does the vertical collapse animation start (or end when
-     * expanding) 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
-     */
-    private static final float VERTICAL_ANIMATION_START = 1.0f;
-
-    /**
-     * Scale for the background to animate from when exiting dark mode.
-     */
-    private static final float DARK_EXIT_SCALE_START = 0.93f;
-
-    /**
-     * A sentinel value when no color should be used. Can be used with {@link #setTintColor(int)}
-     * or {@link #setOverrideTintColor(int, float)}.
-     */
-    protected static final int NO_COLOR = 0;
-
-    private static final Interpolator ACTIVATE_INVERSE_INTERPOLATOR
-            = new PathInterpolator(0.6f, 0, 0.5f, 1);
-    private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR
-            = new PathInterpolator(0, 0, 0.5f, 1);
-    private final int mTintedRippleColor;
-    protected final int mNormalRippleColor;
-    private final AccessibilityManager mAccessibilityManager;
-    private final DoubleTapHelper mDoubleTapHelper;
-
-    private boolean mDimmed;
-    private boolean mDark;
-
-    protected int mBgTint = NO_COLOR;
-    private float mBgAlpha = 1f;
-
-    /**
-     * Flag to indicate that the notification has been touched once and the second touch will
-     * click it.
-     */
-    private boolean mActivated;
-
-    private OnActivatedListener mOnActivatedListener;
-
-    private final Interpolator mSlowOutFastInInterpolator;
-    private final Interpolator mSlowOutLinearInInterpolator;
-    private Interpolator mCurrentAppearInterpolator;
-    private Interpolator mCurrentAlphaInterpolator;
-
-    protected NotificationBackgroundView mBackgroundNormal;
-    private NotificationBackgroundView mBackgroundDimmed;
-    private ObjectAnimator mBackgroundAnimator;
-    private RectF mAppearAnimationRect = new RectF();
-    private float mAnimationTranslationY;
-    private boolean mDrawingAppearAnimation;
-    private ValueAnimator mAppearAnimator;
-    private ValueAnimator mBackgroundColorAnimator;
-    private float mAppearAnimationFraction = -1.0f;
-    private float mAppearAnimationTranslation;
-    private final int mNormalColor;
-    private boolean mIsBelowSpeedBump;
-    private FalsingManager mFalsingManager;
-
-    private float mNormalBackgroundVisibilityAmount;
-    private ValueAnimator mFadeInFromDarkAnimator;
-    private float mDimmedBackgroundFadeInAmount = -1;
-    private ValueAnimator.AnimatorUpdateListener mBackgroundVisibilityUpdater
-            = new ValueAnimator.AnimatorUpdateListener() {
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            setNormalBackgroundVisibilityAmount(mBackgroundNormal.getAlpha());
-            mDimmedBackgroundFadeInAmount = mBackgroundDimmed.getAlpha();
-        }
-    };
-    private AnimatorListenerAdapter mFadeInEndListener = new AnimatorListenerAdapter() {
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            super.onAnimationEnd(animation);
-            mFadeInFromDarkAnimator = null;
-            mDimmedBackgroundFadeInAmount = -1;
-            updateBackground();
-        }
-    };
-    private ValueAnimator.AnimatorUpdateListener mUpdateOutlineListener
-            = new ValueAnimator.AnimatorUpdateListener() {
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            updateOutlineAlpha();
-        }
-    };
-    private float mShadowAlpha = 1.0f;
-    private FakeShadowView mFakeShadow;
-    private int mCurrentBackgroundTint;
-    private int mTargetTint;
-    private int mStartTint;
-    private int mOverrideTint;
-    private float mOverrideAmount;
-    private boolean mShadowHidden;
-    /**
-     * Similar to mDimmed but is also true if it's not dimmable but should be
-     */
-    private boolean mNeedsDimming;
-    private int mDimmedAlpha;
-    private boolean mBlockNextTouch;
-    private boolean mIsHeadsUpAnimation;
-    private int mHeadsUpAddStartLocation;
-    private float mHeadsUpLocation;
-    private boolean mIsAppearing;
-
-    public ActivatableNotificationView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
-        mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
-        setClipChildren(false);
-        setClipToPadding(false);
-        mNormalColor = context.getColor(R.color.notification_material_background_color);
-        mTintedRippleColor = context.getColor(
-                R.color.notification_ripple_tinted_color);
-        mNormalRippleColor = context.getColor(
-                R.color.notification_ripple_untinted_color);
-        mFalsingManager = FalsingManager.getInstance(context);
-        mAccessibilityManager = AccessibilityManager.getInstance(mContext);
-
-        mDoubleTapHelper = new DoubleTapHelper(this, (active) -> {
-            if (active) {
-                makeActive();
-            } else {
-                makeInactive(true /* animate */);
-            }
-        }, super::performClick, this::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
-        initDimens();
-    }
-
-    private void initDimens() {
-        mHeadsUpAddStartLocation = getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.notification_content_margin_start);
-    }
-
-    @Override
-    public void onDensityOrFontScaleChanged() {
-        super.onDensityOrFontScaleChanged();
-        initDimens();
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mBackgroundNormal = findViewById(R.id.backgroundNormal);
-        mFakeShadow = findViewById(R.id.fake_shadow);
-        mShadowHidden = mFakeShadow.getVisibility() != VISIBLE;
-        mBackgroundDimmed = findViewById(R.id.backgroundDimmed);
-        mDimmedAlpha = Color.alpha(mContext.getColor(
-                R.color.notification_material_background_dimmed_color));
-        initBackground();
-        updateBackground();
-        updateBackgroundTint();
-        updateOutlineAlpha();
-    }
-
-    /**
-     * Sets the custom backgrounds on {@link #mBackgroundNormal} and {@link #mBackgroundDimmed}.
-     * This method can also be used to reload the backgrounds on both of those views, which can
-     * be useful in a configuration change.
-     */
-    protected void initBackground() {
-        mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
-        mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
-    }
-
-    private final Runnable mTapTimeoutRunnable = new Runnable() {
-        @Override
-        public void run() {
-            makeInactive(true /* animate */);
-        }
-    };
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (mNeedsDimming && ev.getActionMasked() == MotionEvent.ACTION_DOWN
-                && disallowSingleClick(ev) && !isTouchExplorationEnabled()) {
-            if (!mActivated) {
-                return true;
-            } else if (!mDoubleTapHelper.isWithinDoubleTapSlop(ev)) {
-                mBlockNextTouch = true;
-                makeInactive(true /* animate */);
-                return true;
-            }
-        }
-        return super.onInterceptTouchEvent(ev);
-    }
-
-    private boolean isTouchExplorationEnabled() {
-        return mAccessibilityManager.isTouchExplorationEnabled();
-    }
-
-    protected boolean disallowSingleClick(MotionEvent ev) {
-        return false;
-    }
-
-    protected boolean handleSlideBack() {
-        return false;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        boolean result;
-        if (mBlockNextTouch) {
-            mBlockNextTouch = false;
-            return false;
-        }
-        if (mNeedsDimming && !isTouchExplorationEnabled() && isInteractive()) {
-            boolean wasActivated = mActivated;
-            result = handleTouchEventDimmed(event);
-            if (wasActivated && result && event.getAction() == MotionEvent.ACTION_UP) {
-                removeCallbacks(mTapTimeoutRunnable);
-            }
-        } else {
-            result = super.onTouchEvent(event);
-        }
-        return result;
-    }
-
-    /**
-     * @return whether this view is interactive and can be double tapped
-     */
-    protected boolean isInteractive() {
-        return true;
-    }
-
-    @Override
-    public void drawableHotspotChanged(float x, float y) {
-        if (!mDimmed){
-            mBackgroundNormal.drawableHotspotChanged(x, y);
-        }
-    }
-
-    @Override
-    protected void drawableStateChanged() {
-        super.drawableStateChanged();
-        if (mDimmed) {
-            mBackgroundDimmed.setState(getDrawableState());
-        } else {
-            mBackgroundNormal.setState(getDrawableState());
-        }
-    }
-
-    public void setRippleAllowed(boolean allowed) {
-        mBackgroundNormal.setPressedAllowed(allowed);
-    }
-
-    private boolean handleTouchEventDimmed(MotionEvent event) {
-        if (mNeedsDimming && !mDimmed) {
-            // We're actually dimmed, but our content isn't dimmable, let's ensure we have a ripple
-            super.onTouchEvent(event);
-        }
-        return mDoubleTapHelper.onTouchEvent(event, getActualHeight());
-    }
-
-    @Override
-    public boolean performClick() {
-        if (!mNeedsDimming || isTouchExplorationEnabled()) {
-            return super.performClick();
-        }
-        return false;
-    }
-
-    private void makeActive() {
-        mFalsingManager.onNotificationActive();
-        startActivateAnimation(false /* reverse */);
-        mActivated = true;
-        if (mOnActivatedListener != null) {
-            mOnActivatedListener.onActivated(this);
-        }
-    }
-
-    private void startActivateAnimation(final boolean reverse) {
-        if (!isAttachedToWindow()) {
-            return;
-        }
-        if (!isDimmable()) {
-            return;
-        }
-        int widthHalf = mBackgroundNormal.getWidth()/2;
-        int heightHalf = mBackgroundNormal.getActualHeight()/2;
-        float radius = (float) Math.sqrt(widthHalf*widthHalf + heightHalf*heightHalf);
-        Animator animator;
-        if (reverse) {
-            animator = ViewAnimationUtils.createCircularReveal(mBackgroundNormal,
-                    widthHalf, heightHalf, radius, 0);
-        } else {
-            animator = ViewAnimationUtils.createCircularReveal(mBackgroundNormal,
-                    widthHalf, heightHalf, 0, radius);
-        }
-        mBackgroundNormal.setVisibility(View.VISIBLE);
-        Interpolator interpolator;
-        Interpolator alphaInterpolator;
-        if (!reverse) {
-            interpolator = Interpolators.LINEAR_OUT_SLOW_IN;
-            alphaInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
-        } else {
-            interpolator = ACTIVATE_INVERSE_INTERPOLATOR;
-            alphaInterpolator = ACTIVATE_INVERSE_ALPHA_INTERPOLATOR;
-        }
-        animator.setInterpolator(interpolator);
-        animator.setDuration(ACTIVATE_ANIMATION_LENGTH);
-        if (reverse) {
-            mBackgroundNormal.setAlpha(1f);
-            animator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    updateBackground();
-                }
-            });
-            animator.start();
-        } else {
-            mBackgroundNormal.setAlpha(0.4f);
-            animator.start();
-        }
-        mBackgroundNormal.animate()
-                .alpha(reverse ? 0f : 1f)
-                .setInterpolator(alphaInterpolator)
-                .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-                    @Override
-                    public void onAnimationUpdate(ValueAnimator animation) {
-                        float animatedFraction = animation.getAnimatedFraction();
-                        if (reverse) {
-                            animatedFraction = 1.0f - animatedFraction;
-                        }
-                        setNormalBackgroundVisibilityAmount(animatedFraction);
-                    }
-                })
-                .setDuration(ACTIVATE_ANIMATION_LENGTH);
-    }
-
-    /**
-     * Cancels the hotspot and makes the notification inactive.
-     */
-    public void makeInactive(boolean animate) {
-        if (mActivated) {
-            mActivated = false;
-            if (mDimmed) {
-                if (animate) {
-                    startActivateAnimation(true /* reverse */);
-                } else {
-                    updateBackground();
-                }
-            }
-        }
-        if (mOnActivatedListener != null) {
-            mOnActivatedListener.onActivationReset(this);
-        }
-        removeCallbacks(mTapTimeoutRunnable);
-    }
-
-    public void setDimmed(boolean dimmed, boolean fade) {
-        mNeedsDimming = dimmed;
-        dimmed &= isDimmable();
-        if (mDimmed != dimmed) {
-            mDimmed = dimmed;
-            resetBackgroundAlpha();
-            if (fade) {
-                fadeDimmedBackground();
-            } else {
-                updateBackground();
-            }
-        }
-    }
-
-    public boolean isDimmable() {
-        return true;
-    }
-
-    public void setDark(boolean dark, boolean fade, long delay) {
-        super.setDark(dark, fade, delay);
-        if (mDark == dark) {
-            return;
-        }
-        mDark = dark;
-        updateBackground();
-        updateBackgroundTint(false);
-        if (!dark && fade && !shouldHideBackground()) {
-            fadeInFromDark(delay);
-        }
-        updateOutlineAlpha();
-    }
-
-    private void updateOutlineAlpha() {
-        if (mDark) {
-            setOutlineAlpha(0f);
-            return;
-        }
-        float alpha = NotificationStackScrollLayout.BACKGROUND_ALPHA_DIMMED;
-        alpha = (alpha + (1.0f - alpha) * mNormalBackgroundVisibilityAmount);
-        alpha *= mShadowAlpha;
-        if (mFadeInFromDarkAnimator != null) {
-            alpha *= mFadeInFromDarkAnimator.getAnimatedFraction();
-        }
-        setOutlineAlpha(alpha);
-    }
-
-    public void setNormalBackgroundVisibilityAmount(float normalBackgroundVisibilityAmount) {
-        mNormalBackgroundVisibilityAmount = normalBackgroundVisibilityAmount;
-        updateOutlineAlpha();
-    }
-
-    @Override
-    public void setBelowSpeedBump(boolean below) {
-        super.setBelowSpeedBump(below);
-        if (below != mIsBelowSpeedBump) {
-            mIsBelowSpeedBump = below;
-            updateBackgroundTint();
-            onBelowSpeedBumpChanged();
-        }
-    }
-
-    protected void onBelowSpeedBumpChanged() {
-    }
-
-    /**
-     * @return whether we are below the speed bump
-     */
-    public boolean isBelowSpeedBump() {
-        return mIsBelowSpeedBump;
-    }
-
-    /**
-     * Sets the tint color of the background
-     */
-    public void setTintColor(int color) {
-        setTintColor(color, false);
-    }
-
-    /**
-     * Sets the tint color of the background
-     */
-    public void setTintColor(int color, boolean animated) {
-        if (color != mBgTint) {
-            mBgTint = color;
-            updateBackgroundTint(animated);
-        }
-    }
-
-    @Override
-    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
-        super.setDistanceToTopRoundness(distanceToTopRoundness);
-        mBackgroundNormal.setDistanceToTopRoundness(distanceToTopRoundness);
-        mBackgroundDimmed.setDistanceToTopRoundness(distanceToTopRoundness);
-    }
-
-    /**
-     * Set an override tint color that is used for the background.
-     *
-     * @param color the color that should be used to tint the background.
-     *              This can be {@link #NO_COLOR} if the tint should be normally computed.
-     * @param overrideAmount a value from 0 to 1 how much the override tint should be used. The
-     *                       background color will then be the interpolation between this and the
-     *                       regular background color, where 1 means the overrideTintColor is fully
-     *                       used and the background color not at all.
-     */
-    public void setOverrideTintColor(int color, float overrideAmount) {
-        if (mDark) {
-            color = NO_COLOR;
-            overrideAmount = 0;
-        }
-        mOverrideTint = color;
-        mOverrideAmount = overrideAmount;
-        int newColor = calculateBgColor();
-        setBackgroundTintColor(newColor);
-        if (!isDimmable() && mNeedsDimming) {
-           mBackgroundNormal.setDrawableAlpha((int) NotificationUtils.interpolate(255,
-                   mDimmedAlpha,
-                   overrideAmount));
-        } else {
-            mBackgroundNormal.setDrawableAlpha(255);
-        }
-    }
-
-    protected void updateBackgroundTint() {
-        updateBackgroundTint(false /* animated */);
-    }
-
-    private void updateBackgroundTint(boolean animated) {
-        if (mBackgroundColorAnimator != null) {
-            mBackgroundColorAnimator.cancel();
-        }
-        int rippleColor = getRippleColor();
-        mBackgroundDimmed.setRippleColor(rippleColor);
-        mBackgroundNormal.setRippleColor(rippleColor);
-        int color = calculateBgColor();
-        if (!animated) {
-            setBackgroundTintColor(color);
-        } else if (color != mCurrentBackgroundTint) {
-            mStartTint = mCurrentBackgroundTint;
-            mTargetTint = color;
-            mBackgroundColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
-            mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    int newColor = NotificationUtils.interpolateColors(mStartTint, mTargetTint,
-                            animation.getAnimatedFraction());
-                    setBackgroundTintColor(newColor);
-                }
-            });
-            mBackgroundColorAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-            mBackgroundColorAnimator.setInterpolator(Interpolators.LINEAR);
-            mBackgroundColorAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mBackgroundColorAnimator = null;
-                }
-            });
-            mBackgroundColorAnimator.start();
-        }
-    }
-
-    protected void setBackgroundTintColor(int color) {
-        if (color != mCurrentBackgroundTint) {
-            mCurrentBackgroundTint = color;
-            if (color == mNormalColor) {
-                // We don't need to tint a normal notification
-                color = 0;
-            }
-            mBackgroundDimmed.setTint(color);
-            mBackgroundNormal.setTint(color);
-        }
-    }
-
-    /**
-     * Fades in the background when exiting dark mode.
-     */
-    private void fadeInFromDark(long delay) {
-        final View background = mDimmed ? mBackgroundDimmed : mBackgroundNormal;
-        background.setAlpha(0f);
-        mBackgroundVisibilityUpdater.onAnimationUpdate(null);
-        background.animate()
-                .alpha(1f)
-                .setDuration(DARK_ANIMATION_LENGTH)
-                .setStartDelay(delay)
-                .setInterpolator(Interpolators.ALPHA_IN)
-                .setListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationCancel(Animator animation) {
-                        // Jump state if we are cancelled
-                        background.setAlpha(1f);
-                    }
-                })
-                .setUpdateListener(mBackgroundVisibilityUpdater)
-                .start();
-        mFadeInFromDarkAnimator = TimeAnimator.ofFloat(0.0f, 1.0f);
-        mFadeInFromDarkAnimator.setDuration(DARK_ANIMATION_LENGTH);
-        mFadeInFromDarkAnimator.setStartDelay(delay);
-        mFadeInFromDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-        mFadeInFromDarkAnimator.addListener(mFadeInEndListener);
-        mFadeInFromDarkAnimator.addUpdateListener(mUpdateOutlineListener);
-        mFadeInFromDarkAnimator.start();
-    }
-
-    /**
-     * Fades the background when the dimmed state changes.
-     */
-    private void fadeDimmedBackground() {
-        mBackgroundDimmed.animate().cancel();
-        mBackgroundNormal.animate().cancel();
-        if (mActivated) {
-            updateBackground();
-            return;
-        }
-        if (!shouldHideBackground()) {
-            if (mDimmed) {
-                mBackgroundDimmed.setVisibility(View.VISIBLE);
-            } else {
-                mBackgroundNormal.setVisibility(View.VISIBLE);
-            }
-        }
-        float startAlpha = mDimmed ? 1f : 0;
-        float endAlpha = mDimmed ? 0 : 1f;
-        int duration = BACKGROUND_ANIMATION_LENGTH_MS;
-        // Check whether there is already a background animation running.
-        if (mBackgroundAnimator != null) {
-            startAlpha = (Float) mBackgroundAnimator.getAnimatedValue();
-            duration = (int) mBackgroundAnimator.getCurrentPlayTime();
-            mBackgroundAnimator.removeAllListeners();
-            mBackgroundAnimator.cancel();
-            if (duration <= 0) {
-                updateBackground();
-                return;
-            }
-        }
-        mBackgroundNormal.setAlpha(startAlpha);
-        mBackgroundAnimator =
-                ObjectAnimator.ofFloat(mBackgroundNormal, View.ALPHA, startAlpha, endAlpha);
-        mBackgroundAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        mBackgroundAnimator.setDuration(duration);
-        mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                updateBackground();
-                mBackgroundAnimator = null;
-                if (mFadeInFromDarkAnimator == null) {
-                    mDimmedBackgroundFadeInAmount = -1;
-                }
-            }
-        });
-        mBackgroundAnimator.addUpdateListener(mBackgroundVisibilityUpdater);
-        mBackgroundAnimator.start();
-    }
-
-    protected void updateBackgroundAlpha(float transformationAmount) {
-        mBgAlpha =  isChildInGroup() && mDimmed ? transformationAmount : 1f;
-        if (mDimmedBackgroundFadeInAmount != -1) {
-            mBgAlpha *= mDimmedBackgroundFadeInAmount;
-        }
-        mBackgroundDimmed.setAlpha(mBgAlpha);
-    }
-
-    protected void resetBackgroundAlpha() {
-        updateBackgroundAlpha(0f /* transformationAmount */);
-    }
-
-    protected void updateBackground() {
-        cancelFadeAnimations();
-        if (shouldHideBackground()) {
-            mBackgroundDimmed.setVisibility(INVISIBLE);
-            mBackgroundNormal.setVisibility(mActivated ? VISIBLE : INVISIBLE);
-        } else if (mDimmed) {
-            // When groups are animating to the expanded state from the lockscreen, show the
-            // normal background instead of the dimmed background
-            final boolean dontShowDimmed = isGroupExpansionChanging() && isChildInGroup();
-            mBackgroundDimmed.setVisibility(dontShowDimmed ? View.INVISIBLE : View.VISIBLE);
-            mBackgroundNormal.setVisibility((mActivated || dontShowDimmed)
-                    ? View.VISIBLE
-                    : View.INVISIBLE);
-        } else {
-            mBackgroundDimmed.setVisibility(View.INVISIBLE);
-            mBackgroundNormal.setVisibility(View.VISIBLE);
-            mBackgroundNormal.setAlpha(1f);
-            removeCallbacks(mTapTimeoutRunnable);
-            // make in inactive to avoid it sticking around active
-            makeInactive(false /* animate */);
-        }
-        setNormalBackgroundVisibilityAmount(
-                mBackgroundNormal.getVisibility() == View.VISIBLE ? 1.0f : 0.0f);
-    }
-
-    protected void updateBackgroundClipping() {
-        mBackgroundNormal.setBottomAmountClips(!isChildInGroup());
-        mBackgroundDimmed.setBottomAmountClips(!isChildInGroup());
-    }
-
-    protected boolean shouldHideBackground() {
-        return mDark;
-    }
-
-    private void cancelFadeAnimations() {
-        if (mBackgroundAnimator != null) {
-            mBackgroundAnimator.cancel();
-        }
-        mBackgroundDimmed.animate().cancel();
-        mBackgroundNormal.animate().cancel();
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        setPivotX(getWidth() / 2);
-    }
-
-    @Override
-    public void setActualHeight(int actualHeight, boolean notifyListeners) {
-        super.setActualHeight(actualHeight, notifyListeners);
-        setPivotY(actualHeight / 2);
-        mBackgroundNormal.setActualHeight(actualHeight);
-        mBackgroundDimmed.setActualHeight(actualHeight);
-    }
-
-    @Override
-    public void setClipTopAmount(int clipTopAmount) {
-        super.setClipTopAmount(clipTopAmount);
-        mBackgroundNormal.setClipTopAmount(clipTopAmount);
-        mBackgroundDimmed.setClipTopAmount(clipTopAmount);
-    }
-
-    @Override
-    public void setClipBottomAmount(int clipBottomAmount) {
-        super.setClipBottomAmount(clipBottomAmount);
-        mBackgroundNormal.setClipBottomAmount(clipBottomAmount);
-        mBackgroundDimmed.setClipBottomAmount(clipBottomAmount);
-    }
-
-    @Override
-    public void performRemoveAnimation(long duration, long delay,
-            float translationDirection, boolean isHeadsUpAnimation, float endLocation,
-            Runnable onFinishedRunnable, AnimatorListenerAdapter animationListener) {
-        enableAppearDrawing(true);
-        mIsHeadsUpAnimation = isHeadsUpAnimation;
-        mHeadsUpLocation = endLocation;
-        if (mDrawingAppearAnimation) {
-            startAppearAnimation(false /* isAppearing */, translationDirection,
-                    delay, duration, onFinishedRunnable, animationListener);
-        } else if (onFinishedRunnable != null) {
-            onFinishedRunnable.run();
-        }
-    }
-
-    @Override
-    public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) {
-        enableAppearDrawing(true);
-        mIsHeadsUpAnimation = isHeadsUpAppear;
-        mHeadsUpLocation = mHeadsUpAddStartLocation;
-        if (mDrawingAppearAnimation) {
-            startAppearAnimation(true /* isAppearing */, isHeadsUpAppear ? 0.0f : -1.0f, delay,
-                    duration, null, null);
-        }
-    }
-
-    private void startAppearAnimation(boolean isAppearing, float translationDirection, long delay,
-            long duration, final Runnable onFinishedRunnable,
-            AnimatorListenerAdapter animationListener) {
-        cancelAppearAnimation();
-        mAnimationTranslationY = translationDirection * getActualHeight();
-        if (mAppearAnimationFraction == -1.0f) {
-            // not initialized yet, we start anew
-            if (isAppearing) {
-                mAppearAnimationFraction = 0.0f;
-                mAppearAnimationTranslation = mAnimationTranslationY;
-            } else {
-                mAppearAnimationFraction = 1.0f;
-                mAppearAnimationTranslation = 0;
-            }
-        }
-        mIsAppearing = isAppearing;
-
-        float targetValue;
-        if (isAppearing) {
-            mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
-            mCurrentAlphaInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
-            targetValue = 1.0f;
-        } else {
-            mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN;
-            mCurrentAlphaInterpolator = mSlowOutLinearInInterpolator;
-            targetValue = 0.0f;
-        }
-        mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction,
-                targetValue);
-        mAppearAnimator.setInterpolator(Interpolators.LINEAR);
-        mAppearAnimator.setDuration(
-                (long) (duration * Math.abs(mAppearAnimationFraction - targetValue)));
-        mAppearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                mAppearAnimationFraction = (float) animation.getAnimatedValue();
-                updateAppearAnimationAlpha();
-                updateAppearRect();
-                invalidate();
-            }
-        });
-        if (animationListener != null) {
-            mAppearAnimator.addListener(animationListener);
-        }
-        if (delay > 0) {
-            // we need to apply the initial state already to avoid drawn frames in the wrong state
-            updateAppearAnimationAlpha();
-            updateAppearRect();
-            mAppearAnimator.setStartDelay(delay);
-        }
-        mAppearAnimator.addListener(new AnimatorListenerAdapter() {
-            private boolean mWasCancelled;
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (onFinishedRunnable != null) {
-                    onFinishedRunnable.run();
-                }
-                if (!mWasCancelled) {
-                    enableAppearDrawing(false);
-                    onAppearAnimationFinished(isAppearing);
-                }
-            }
-
-            @Override
-            public void onAnimationStart(Animator animation) {
-                mWasCancelled = false;
-            }
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                mWasCancelled = true;
-            }
-        });
-        mAppearAnimator.start();
-    }
-
-    protected void onAppearAnimationFinished(boolean wasAppearing) {
-    }
-
-    private void cancelAppearAnimation() {
-        if (mAppearAnimator != null) {
-            mAppearAnimator.cancel();
-            mAppearAnimator = null;
-        }
-    }
-
-    public void cancelAppearDrawing() {
-        cancelAppearAnimation();
-        enableAppearDrawing(false);
-    }
-
-    private void updateAppearRect() {
-        float inverseFraction = (1.0f - mAppearAnimationFraction);
-        float translationFraction = mCurrentAppearInterpolator.getInterpolation(inverseFraction);
-        float translateYTotalAmount = translationFraction * mAnimationTranslationY;
-        mAppearAnimationTranslation = translateYTotalAmount;
-
-        // handle width animation
-        float widthFraction = (inverseFraction - (1.0f - HORIZONTAL_ANIMATION_START))
-                / (HORIZONTAL_ANIMATION_START - HORIZONTAL_ANIMATION_END);
-        widthFraction = Math.min(1.0f, Math.max(0.0f, widthFraction));
-        widthFraction = mCurrentAppearInterpolator.getInterpolation(widthFraction);
-        float startWidthFraction = HORIZONTAL_COLLAPSED_REST_PARTIAL;
-        if (mIsHeadsUpAnimation && !mIsAppearing) {
-            startWidthFraction = 0;
-        }
-        float width = MathUtils.lerp(startWidthFraction, 1.0f, 1.0f - widthFraction)
-                        * getWidth();
-        float left;
-        float right;
-        if (mIsHeadsUpAnimation) {
-            left = MathUtils.lerp(mHeadsUpLocation, 0, 1.0f - widthFraction);
-            right = left + width;
-        } else {
-            left = getWidth() * 0.5f - width / 2.0f;
-            right = getWidth() - left;
-        }
-
-        // handle top animation
-        float heightFraction = (inverseFraction - (1.0f - VERTICAL_ANIMATION_START)) /
-                VERTICAL_ANIMATION_START;
-        heightFraction = Math.max(0.0f, heightFraction);
-        heightFraction = mCurrentAppearInterpolator.getInterpolation(heightFraction);
-
-        float top;
-        float bottom;
-        final int actualHeight = getActualHeight();
-        if (mAnimationTranslationY > 0.0f) {
-            bottom = actualHeight - heightFraction * mAnimationTranslationY * 0.1f
-                    - translateYTotalAmount;
-            top = bottom * heightFraction;
-        } else {
-            top = heightFraction * (actualHeight + mAnimationTranslationY) * 0.1f -
-                    translateYTotalAmount;
-            bottom = actualHeight * (1 - heightFraction) + top * heightFraction;
-        }
-        mAppearAnimationRect.set(left, top, right, bottom);
-        setOutlineRect(left, top + mAppearAnimationTranslation, right,
-                bottom + mAppearAnimationTranslation);
-    }
-
-    private void updateAppearAnimationAlpha() {
-        float contentAlphaProgress = mAppearAnimationFraction;
-        contentAlphaProgress = contentAlphaProgress / (1.0f - ALPHA_ANIMATION_END);
-        contentAlphaProgress = Math.min(1.0f, contentAlphaProgress);
-        contentAlphaProgress = mCurrentAlphaInterpolator.getInterpolation(contentAlphaProgress);
-        setContentAlpha(contentAlphaProgress);
-    }
-
-    private void setContentAlpha(float contentAlpha) {
-        View contentView = getContentView();
-        if (contentView.hasOverlappingRendering()) {
-            int layerType = contentAlpha == 0.0f || contentAlpha == 1.0f ? LAYER_TYPE_NONE
-                    : LAYER_TYPE_HARDWARE;
-            int currentLayerType = contentView.getLayerType();
-            if (currentLayerType != layerType) {
-                contentView.setLayerType(layerType, null);
-            }
-        }
-        contentView.setAlpha(contentAlpha);
-    }
-
-    @Override
-    protected void applyRoundness() {
-        super.applyRoundness();
-        applyBackgroundRoundness(getCurrentBackgroundRadiusTop(),
-                getCurrentBackgroundRadiusBottom());
-    }
-
-    protected void applyBackgroundRoundness(float topRadius, float bottomRadius) {
-        mBackgroundDimmed.setRoundness(topRadius, bottomRadius);
-        mBackgroundNormal.setRoundness(topRadius, bottomRadius);
-    }
-
-    @Override
-    protected void setBackgroundTop(int backgroundTop) {
-        mBackgroundDimmed.setBackgroundTop(backgroundTop);
-        mBackgroundNormal.setBackgroundTop(backgroundTop);
-    }
-
-    protected abstract View getContentView();
-
-    public int calculateBgColor() {
-        return calculateBgColor(true /* withTint */, true /* withOverRide */);
-    }
-
-    @Override
-    protected boolean childNeedsClipping(View child) {
-        if (child instanceof NotificationBackgroundView && isClippingNeeded()) {
-            return true;
-        }
-        return super.childNeedsClipping(child);
-    }
-
-    /**
-     * @param withTint should a possible tint be factored in?
-     * @param withOverRide should the value be interpolated with {@link #mOverrideTint}
-     * @return the calculated background color
-     */
-    private int calculateBgColor(boolean withTint, boolean withOverRide) {
-        if (withTint && mDark) {
-            return getContext().getColor(R.color.notification_material_background_dark_color);
-        }
-        if (withOverRide && mOverrideTint != NO_COLOR) {
-            int defaultTint = calculateBgColor(withTint, false);
-            return NotificationUtils.interpolateColors(defaultTint, mOverrideTint, mOverrideAmount);
-        }
-        if (withTint && mBgTint != NO_COLOR) {
-            return mBgTint;
-        } else {
-            return mNormalColor;
-        }
-    }
-
-    protected int getRippleColor() {
-        if (mBgTint != 0) {
-            return mTintedRippleColor;
-        } else {
-            return mNormalRippleColor;
-        }
-    }
-
-    /**
-     * When we draw the appear animation, we render the view in a bitmap and render this bitmap
-     * as a shader of a rect. This call creates the Bitmap and switches the drawing mode,
-     * such that the normal drawing of the views does not happen anymore.
-     *
-     * @param enable Should it be enabled.
-     */
-    private void enableAppearDrawing(boolean enable) {
-        if (enable != mDrawingAppearAnimation) {
-            mDrawingAppearAnimation = enable;
-            if (!enable) {
-                setContentAlpha(1.0f);
-                mAppearAnimationFraction = -1;
-                setOutlineRect(null);
-            }
-            invalidate();
-        }
-    }
-
-    public boolean isDrawingAppearAnimation() {
-        return mDrawingAppearAnimation;
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        if (mDrawingAppearAnimation) {
-            canvas.save();
-            canvas.translate(0, mAppearAnimationTranslation);
-        }
-        super.dispatchDraw(canvas);
-        if (mDrawingAppearAnimation) {
-            canvas.restore();
-        }
-    }
-
-    public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
-        mOnActivatedListener = onActivatedListener;
-    }
-
-    public boolean hasSameBgColor(ActivatableNotificationView otherView) {
-        return calculateBgColor() == otherView.calculateBgColor();
-    }
-
-    @Override
-    public float getShadowAlpha() {
-        return mShadowAlpha;
-    }
-
-    @Override
-    public void setShadowAlpha(float shadowAlpha) {
-        if (shadowAlpha != mShadowAlpha) {
-            mShadowAlpha = shadowAlpha;
-            updateOutlineAlpha();
-        }
-    }
-
-    @Override
-    public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
-            int outlineTranslation) {
-        boolean hiddenBefore = mShadowHidden;
-        mShadowHidden = shadowIntensity == 0.0f;
-        if (!mShadowHidden || !hiddenBefore) {
-            mFakeShadow.setFakeShadowTranslationZ(shadowIntensity * (getTranslationZ()
-                            + FakeShadowView.SHADOW_SIBLING_TRESHOLD), outlineAlpha, shadowYEnd,
-                    outlineTranslation);
-        }
-    }
-
-    public int getBackgroundColorWithoutTint() {
-        return calculateBgColor(false /* withTint */, false /* withOverride */);
-    }
-
-    public boolean isPinned() {
-        return false;
-    }
-
-    public boolean isHeadsUpAnimatingAway() {
-        return false;
-    }
-
-    public interface OnActivatedListener {
-        void onActivated(ActivatableNotificationView view);
-        void onActivationReset(ActivatableNotificationView view);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
new file mode 100644
index 0000000..c017104
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.notification.NotificationData;
+
+import java.util.stream.Stream;
+
+/**
+ * A manager which contains notification alerting functionality, providing methods to add and
+ * remove notifications that appear on screen for a period of time and dismiss themselves at the
+ * appropriate time.  These include heads up notifications and ambient pulses.
+ */
+public abstract class AlertingNotificationManager {
+    private static final String TAG = "AlertNotifManager";
+    protected final Clock mClock = new Clock();
+    protected final ArrayMap<String, AlertEntry> mAlertEntries = new ArrayMap<>();
+    protected int mMinimumDisplayTime;
+    protected int mAutoDismissNotificationDecay;
+    @VisibleForTesting
+    public Handler mHandler = new Handler(Looper.getMainLooper());
+
+    /**
+     * Called when posting a new notification that should alert the user and appear on screen.
+     * Adds the notification to be managed.
+     * @param entry entry to show
+     */
+    public void showNotification(@NonNull NotificationData.Entry entry) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "showNotification");
+        }
+        addAlertEntry(entry);
+        updateNotification(entry.key, true /* alert */);
+        entry.setInterruption();
+    }
+
+    /**
+     * Try to remove the notification.  May not succeed if the notification has not been shown long
+     * enough and needs to be kept around.
+     * @param key the key of the notification to remove
+     * @param releaseImmediately force a remove regardless of earliest removal time
+     * @return true if notification is removed, false otherwise
+     */
+    public boolean removeNotification(@NonNull String key, boolean releaseImmediately) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "removeNotification");
+        }
+        AlertEntry alertEntry = mAlertEntries.get(key);
+        if (alertEntry == null) {
+            return true;
+        }
+        if (releaseImmediately || alertEntry.wasShownLongEnough()) {
+            removeAlertEntry(key);
+        } else {
+            alertEntry.removeAsSoonAsPossible();
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Called when the notification state has been updated.
+     * @param key the key of the entry that was updated
+     * @param alert whether the notification should alert again and force reevaluation of
+     *              removal time
+     */
+    public void updateNotification(@NonNull String key, boolean alert) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "updateNotification");
+        }
+
+        AlertEntry alertEntry = mAlertEntries.get(key);
+        if (alertEntry == null) {
+            // the entry was released before this update (i.e by a listener) This can happen
+            // with the groupmanager
+            return;
+        }
+
+        alertEntry.mEntry.row.sendAccessibilityEvent(
+                AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+        if (alert) {
+            alertEntry.updateEntry(true /* updatePostTime */);
+        }
+    }
+
+    /**
+     * Clears all managed notifications.
+     */
+    public void releaseAllImmediately() {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "releaseAllImmediately");
+        }
+        // A copy is necessary here as we are changing the underlying map.  This would cause
+        // undefined behavior if we iterated over the key set directly.
+        ArraySet<String> keysToRemove = new ArraySet<>(mAlertEntries.keySet());
+        for (String key : keysToRemove) {
+            removeAlertEntry(key);
+        }
+    }
+
+    /**
+     * Returns the entry if it is managed by this manager.
+     * @param key key of notification
+     * @return the entry
+     */
+    @Nullable
+    public NotificationData.Entry getEntry(@NonNull String key) {
+        AlertEntry entry = mAlertEntries.get(key);
+        return entry != null ? entry.mEntry : null;
+    }
+
+    /**
+     * Returns the stream of all current notifications managed by this manager.
+     * @return all entries
+     */
+    @NonNull
+    public Stream<NotificationData.Entry> getAllEntries() {
+        return mAlertEntries.values().stream().map(headsUpEntry -> headsUpEntry.mEntry);
+    }
+
+    /**
+     * Whether or not there are any active alerting notifications.
+     * @return true if there is an alert, false otherwise
+     */
+    public boolean hasNotifications() {
+        return !mAlertEntries.isEmpty();
+    }
+
+    /**
+     * Whether or not the given notification is alerting and managed by this manager.
+     * @return true if the notification is alerting
+     */
+    public boolean contains(@NonNull String key) {
+        return mAlertEntries.containsKey(key);
+    }
+
+    /**
+     * Add a new entry and begin managing it.
+     * @param entry the entry to add
+     */
+    protected final void addAlertEntry(@NonNull NotificationData.Entry entry) {
+        AlertEntry alertEntry = createAlertEntry();
+        alertEntry.setEntry(entry);
+        mAlertEntries.put(entry.key, alertEntry);
+        onAlertEntryAdded(alertEntry);
+        entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+    }
+
+    /**
+     * Manager-specific logic that should occur when an entry is added.
+     * @param alertEntry alert entry added
+     */
+    protected abstract void onAlertEntryAdded(@NonNull AlertEntry alertEntry);
+
+    /**
+     * Remove a notification and reset the alert entry.
+     * @param key key of notification to remove
+     */
+    protected final void removeAlertEntry(@NonNull String key) {
+        AlertEntry alertEntry = mAlertEntries.get(key);
+        if (alertEntry == null) {
+            return;
+        }
+        NotificationData.Entry entry = alertEntry.mEntry;
+        mAlertEntries.remove(key);
+        onAlertEntryRemoved(alertEntry);
+        entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+        alertEntry.reset();
+    }
+
+    /**
+     * Manager-specific logic that should occur when an alert entry is removed.
+     * @param alertEntry alert entry removed
+     */
+    protected abstract void onAlertEntryRemoved(@NonNull AlertEntry alertEntry);
+
+    /**
+     * Returns a new alert entry instance.
+     * @return a new AlertEntry
+     */
+    protected AlertEntry createAlertEntry() {
+        return new AlertEntry();
+    }
+
+    protected class AlertEntry implements Comparable<AlertEntry> {
+        @Nullable public NotificationData.Entry mEntry;
+        public long mPostTime;
+        public long mEarliestRemovaltime;
+
+        @Nullable protected Runnable mRemoveAlertRunnable;
+
+        public void setEntry(@Nullable final NotificationData.Entry entry) {
+            setEntry(entry, () -> removeAlertEntry(entry.key));
+        }
+
+        public void setEntry(@Nullable final NotificationData.Entry entry,
+                @Nullable Runnable removeAlertRunnable) {
+            mEntry = entry;
+            mRemoveAlertRunnable = removeAlertRunnable;
+
+            mPostTime = calculatePostTime();
+            updateEntry(true /* updatePostTime */);
+        }
+
+        /**
+         * Updates an entry's removal time.
+         * @param updatePostTime whether or not to refresh the post time
+         */
+        public void updateEntry(boolean updatePostTime) {
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, "updateEntry");
+            }
+
+            long currentTime = mClock.currentTimeMillis();
+            mEarliestRemovaltime = currentTime + mMinimumDisplayTime;
+            if (updatePostTime) {
+                mPostTime = Math.max(mPostTime, currentTime);
+            }
+            removeAutoRemovalCallbacks();
+
+            if (!isSticky()) {
+                long finishTime = mPostTime + mAutoDismissNotificationDecay;
+                long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime);
+                mHandler.postDelayed(mRemoveAlertRunnable, removeDelay);
+            }
+        }
+
+        /**
+         * Whether or not the notification is "sticky" i.e. should stay on screen regardless
+         * of the timer and should be removed externally.
+         * @return true if the notification is sticky
+         */
+        protected boolean isSticky() {
+            return false;
+        }
+
+        /**
+         * Whether the notification has been on screen long enough and can be removed.
+         * @return true if the notification has been on screen long enough
+         */
+        public boolean wasShownLongEnough() {
+            return mEarliestRemovaltime < mClock.currentTimeMillis();
+        }
+
+        @Override
+        public int compareTo(@NonNull AlertEntry alertEntry) {
+            return (mPostTime < alertEntry.mPostTime)
+                    ? 1 : ((mPostTime == alertEntry.mPostTime)
+                            ? mEntry.key.compareTo(alertEntry.mEntry.key) : -1);
+        }
+
+        public void reset() {
+            mEntry = null;
+            removeAutoRemovalCallbacks();
+            mRemoveAlertRunnable = null;
+        }
+
+        /**
+         * Clear any pending removal runnables.
+         */
+        public void removeAutoRemovalCallbacks() {
+            if (mRemoveAlertRunnable != null) {
+                mHandler.removeCallbacks(mRemoveAlertRunnable);
+            }
+        }
+
+        /**
+         * Remove the alert at the earliest allowed removal time.
+         */
+        public void removeAsSoonAsPossible() {
+            if (mRemoveAlertRunnable != null) {
+                removeAutoRemovalCallbacks();
+                mHandler.postDelayed(mRemoveAlertRunnable,
+                        mEarliestRemovaltime - mClock.currentTimeMillis());
+            }
+        }
+
+        /**
+         * Calculate what the post time of a notification is at some current time.
+         * @return the post time
+         */
+        protected long calculatePostTime() {
+            return mClock.currentTimeMillis();
+        }
+    }
+
+    protected final static class Clock {
+        public long currentTimeMillis() {
+            return SystemClock.elapsedRealtime();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaImageView.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaImageView.java
deleted file mode 100644
index 06dc4e6..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaImageView.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-/**
- * An ImageView which does not have overlapping renderings commands and therefore does not need a
- * layer when alpha is changed.
- */
-public class AlphaImageView extends ImageView {
-    public AlphaImageView(Context context) {
-        super(context);
-    }
-
-    public AlphaImageView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public AlphaImageView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    public AlphaImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsInfo.java
deleted file mode 100644
index 7999a6c..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsInfo.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.os.RemoteException;
-import android.service.notification.StatusBarNotification;
-import android.util.ArraySet;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-
-/**
- * The guts of a notification revealed when performing a long press.
- */
-public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsContent {
-    private static final String TAG = "AppOpsGuts";
-
-    private PackageManager mPm;
-
-    private String mPkg;
-    private String mAppName;
-    private int mAppUid;
-    private StatusBarNotification mSbn;
-    private ArraySet<Integer> mAppOps;
-    private MetricsLogger mMetricsLogger;
-    private OnSettingsClickListener mOnSettingsClickListener;
-    private NotificationGuts mGutsContainer;
-
-    private OnClickListener mOnOk = v -> {
-        closeControls(v);
-    };
-
-    public AppOpsInfo(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public interface OnSettingsClickListener {
-        void onClick(View v, String pkg, int uid, ArraySet<Integer> ops);
-    }
-
-    public void bindGuts(final PackageManager pm,
-            final OnSettingsClickListener onSettingsClick,
-            final StatusBarNotification sbn,
-            ArraySet<Integer> activeOps) {
-        mPkg = sbn.getPackageName();
-        mSbn = sbn;
-        mPm = pm;
-        mAppName = mPkg;
-        mOnSettingsClickListener = onSettingsClick;
-        mAppOps = activeOps;
-
-        bindHeader();
-        bindPrompt();
-        bindButtons();
-
-        mMetricsLogger = new MetricsLogger();
-        mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, true);
-    }
-
-    private void bindHeader() {
-        // Package name
-        Drawable pkgicon = null;
-        ApplicationInfo info;
-        try {
-            info = mPm.getApplicationInfo(mPkg,
-                    PackageManager.MATCH_UNINSTALLED_PACKAGES
-                            | PackageManager.MATCH_DISABLED_COMPONENTS
-                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-                            | PackageManager.MATCH_DIRECT_BOOT_AWARE);
-            if (info != null) {
-                mAppUid = mSbn.getUid();
-                mAppName = String.valueOf(mPm.getApplicationLabel(info));
-                pkgicon = mPm.getApplicationIcon(info);
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            // app is gone, just show package name and generic icon
-            pkgicon = mPm.getDefaultActivityIcon();
-        }
-        ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
-        ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
-    }
-
-    private void bindPrompt() {
-        final TextView prompt = findViewById(R.id.prompt);
-        prompt.setText(getPrompt());
-    }
-
-    private void bindButtons() {
-        View settings =  findViewById(R.id.settings);
-        settings.setOnClickListener((View view) -> {
-            mOnSettingsClickListener.onClick(view, mPkg, mAppUid, mAppOps);
-        });
-        TextView ok = findViewById(R.id.ok);
-        ok.setOnClickListener(mOnOk);
-    }
-
-    private String getPrompt() {
-        if (mAppOps == null || mAppOps.size() == 0) {
-            return "";
-        } else if (mAppOps.size() == 1) {
-            if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
-                return mContext.getString(R.string.appops_camera);
-            } else if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
-                return mContext.getString(R.string.appops_microphone);
-            } else {
-                return mContext.getString(R.string.appops_overlay);
-            }
-        } else if (mAppOps.size() == 2) {
-            if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
-                if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
-                    return mContext.getString(R.string.appops_camera_mic);
-                } else {
-                    return mContext.getString(R.string.appops_camera_overlay);
-                }
-            } else {
-                return mContext.getString(R.string.appops_mic_overlay);
-            }
-        } else {
-            return mContext.getString(R.string.appops_camera_mic_overlay);
-        }
-    }
-
-    @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEvent(event);
-        if (mGutsContainer != null &&
-                event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-            if (mGutsContainer.isExposed()) {
-                event.getText().add(mContext.getString(
-                        R.string.notification_channel_controls_opened_accessibility, mAppName));
-            } else {
-                event.getText().add(mContext.getString(
-                        R.string.notification_channel_controls_closed_accessibility, mAppName));
-            }
-        }
-    }
-
-    private void closeControls(View v) {
-        mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
-        int[] parentLoc = new int[2];
-        int[] targetLoc = new int[2];
-        mGutsContainer.getLocationOnScreen(parentLoc);
-        v.getLocationOnScreen(targetLoc);
-        final int centerX = v.getWidth() / 2;
-        final int centerY = v.getHeight() / 2;
-        final int x = targetLoc[0] - parentLoc[0] + centerX;
-        final int y = targetLoc[1] - parentLoc[1] + centerY;
-        mGutsContainer.closeControls(x, y, false, false);
-    }
-
-    @Override
-    public void setGutsParent(NotificationGuts guts) {
-        mGutsContainer = guts;
-    }
-
-    @Override
-    public boolean willBeRemoved() {
-        return false;
-    }
-
-    @Override
-    public boolean shouldBeSaved() {
-        return false;
-    }
-
-    @Override
-    public View getContentView() {
-        return this;
-    }
-
-    @Override
-    public boolean handleCloseControls(boolean save, boolean force) {
-        return false;
-    }
-
-    @Override
-    public int getActualHeight() {
-        return getHeight();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java
deleted file mode 100644
index 019c680..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.app.AppOpsManager;
-import android.content.Context;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.ForegroundServiceController;
-
-/**
- * This class handles listening to notification updates and passing them along to
- * NotificationPresenter to be displayed to the user.
- */
-public class AppOpsListener implements AppOpsManager.OnOpActiveChangedListener {
-    private static final String TAG = "NotificationListener";
-
-    // Dependencies:
-    private final ForegroundServiceController mFsc =
-            Dependency.get(ForegroundServiceController.class);
-
-    private final Context mContext;
-    protected NotificationPresenter mPresenter;
-    protected NotificationEntryManager mEntryManager;
-    protected final AppOpsManager mAppOps;
-
-    protected static final int[] OPS = new int[] {AppOpsManager.OP_CAMERA,
-            AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
-            AppOpsManager.OP_RECORD_AUDIO};
-
-    public AppOpsListener(Context context) {
-        mContext = context;
-        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
-    }
-
-    public void setUpWithPresenter(NotificationPresenter presenter,
-            NotificationEntryManager entryManager) {
-        mPresenter = presenter;
-        mEntryManager = entryManager;
-        mAppOps.startWatchingActive(OPS, this);
-    }
-
-    public void destroy() {
-        mAppOps.stopWatchingActive(this);
-    }
-
-    @Override
-    public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
-        mFsc.onAppOpChanged(code, uid, packageName, active);
-        mPresenter.getHandler().post(() -> {
-          mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active);
-        });
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 145a246..909cd79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -85,11 +85,11 @@
     private static final int MSG_SHOW_SHUTDOWN_UI              = 36 << MSG_SHIFT;
     private static final int MSG_SET_TOP_APP_HIDES_STATUS_BAR  = 37 << MSG_SHIFT;
     private static final int MSG_ROTATION_PROPOSAL             = 38 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_SHOW              = 39 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_AUTHENTICATED     = 40 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_HELP              = 41 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_ERROR             = 42 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_HIDE              = 43 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_SHOW                = 39 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_AUTHENTICATED       = 40 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_HELP                = 41 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_ERROR               = 42 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_HIDE                = 43 << MSG_SHIFT;
     private static final int MSG_SHOW_CHARGING_ANIMATION       = 44 << MSG_SHIFT;
     private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
     private static final int MSG_SHOW_PINNING_TOAST_ESCAPE     = 46 << MSG_SHIFT;
@@ -160,11 +160,11 @@
 
         default void onRotationProposal(int rotation, boolean isValid) { }
 
-        default void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) { }
-        default void onFingerprintAuthenticated() { }
-        default void onFingerprintHelp(String message) { }
-        default void onFingerprintError(String error) { }
-        default void hideFingerprintDialog() { }
+        default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) { }
+        default void onBiometricAuthenticated() { }
+        default void onBiometricHelp(String message) { }
+        default void onBiometricError(String error) { }
+        default void hideBiometricDialog() { }
     }
 
     @VisibleForTesting
@@ -513,41 +513,41 @@
     }
 
     @Override
-    public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
+    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
         synchronized (mLock) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = bundle;
             args.arg2 = receiver;
-            mHandler.obtainMessage(MSG_FINGERPRINT_SHOW, args)
+            mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args)
                     .sendToTarget();
         }
     }
 
     @Override
-    public void onFingerprintAuthenticated() {
+    public void onBiometricAuthenticated() {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED).sendToTarget();
         }
     }
 
     @Override
-    public void onFingerprintHelp(String message) {
+    public void onBiometricHelp(String message) {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_HELP, message).sendToTarget();
         }
     }
 
     @Override
-    public void onFingerprintError(String error) {
+    public void onBiometricError(String error) {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, error).sendToTarget();
         }
     }
 
     @Override
-    public void hideFingerprintDialog() {
+    public void hideBiometricDialog() {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_HIDE).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_HIDE).sendToTarget();
         }
     }
 
@@ -752,34 +752,34 @@
                         mCallbacks.get(i).onRotationProposal(msg.arg1, msg.arg2 != 0);
                     }
                     break;
-                case MSG_FINGERPRINT_SHOW:
-                    mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
-                    mHandler.removeMessages(MSG_FINGERPRINT_HELP);
-                    mHandler.removeMessages(MSG_FINGERPRINT_AUTHENTICATED);
+                case MSG_BIOMETRIC_SHOW:
+                    mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
+                    mHandler.removeMessages(MSG_BIOMETRIC_HELP);
+                    mHandler.removeMessages(MSG_BIOMETRIC_AUTHENTICATED);
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).showFingerprintDialog(
+                        mCallbacks.get(i).showBiometricDialog(
                                 (Bundle)((SomeArgs)msg.obj).arg1,
                                 (IBiometricPromptReceiver)((SomeArgs)msg.obj).arg2);
                     }
                     break;
-                case MSG_FINGERPRINT_AUTHENTICATED:
+                case MSG_BIOMETRIC_AUTHENTICATED:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).onFingerprintAuthenticated();
+                        mCallbacks.get(i).onBiometricAuthenticated();
                     }
                     break;
-                case MSG_FINGERPRINT_HELP:
+                case MSG_BIOMETRIC_HELP:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).onFingerprintHelp((String) msg.obj);
+                        mCallbacks.get(i).onBiometricHelp((String) msg.obj);
                     }
                     break;
-                case MSG_FINGERPRINT_ERROR:
+                case MSG_BIOMETRIC_ERROR:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).onFingerprintError((String) msg.obj);
+                        mCallbacks.get(i).onBiometricError((String) msg.obj);
                     }
                     break;
-                case MSG_FINGERPRINT_HIDE:
+                case MSG_BIOMETRIC_HIDE:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).hideFingerprintDialog();
+                        mCallbacks.get(i).hideBiometricDialog();
                     }
                     break;
                 case MSG_SHOW_CHARGING_ANIMATION:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
index 4728a1d..6c3e504 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
@@ -19,7 +19,7 @@
 import android.view.View;
 
 import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 /**
  * A helper to fade views in and out.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 1bbf848..30d9ef7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -30,7 +30,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
 
 /**
  * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
index 4da1558..745b2f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
@@ -25,8 +25,9 @@
 import android.widget.TextView;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.stack.ExpandableViewState;
-import com.android.systemui.statusbar.stack.StackScrollState;
+import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
+import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
+import com.android.systemui.statusbar.notification.stack.StackScrollState;
 
 public class EmptyShadeView extends StackScrollerDecorView {
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
deleted file mode 100644
index 9393d5b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ /dev/null
@@ -1,2987 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
-import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.Nullable;
-import android.app.NotificationChannel;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Path;
-import android.graphics.drawable.AnimatedVectorDrawable;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.SystemClock;
-import android.os.Bundle;
-import android.service.notification.StatusBarNotification;
-import android.util.ArraySet;
-import android.util.AttributeSet;
-import android.util.FloatProperty;
-import android.util.Log;
-import android.util.MathUtils;
-import android.util.Property;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.NotificationHeaderView;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import android.widget.Chronometer;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.RemoteViews;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.ContrastColorUtil;
-import com.android.internal.widget.CachingIconView;
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.statusbar.NotificationGuts.GutsContent;
-import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
-import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.notification.HybridNotificationView;
-import com.android.systemui.statusbar.notification.NotificationCounters;
-import com.android.systemui.statusbar.notification.NotificationInflater;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.notification.NotificationViewWrapper;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.stack.AmbientState;
-import com.android.systemui.statusbar.stack.AnimationProperties;
-import com.android.systemui.statusbar.stack.ExpandableViewState;
-import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
-import com.android.systemui.statusbar.stack.StackScrollState;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.BooleanSupplier;
-import java.util.function.Consumer;
-
-/**
- * View representing a notification item - this can be either the individual child notification or
- * the group summary (which contains 1 or more child notifications).
- */
-public class ExpandableNotificationRow extends ActivatableNotificationView
-        implements PluginListener<NotificationMenuRowPlugin> {
-
-    private static final boolean DEBUG = false;
-    private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
-    private static final int COLORED_DIVIDER_ALPHA = 0x7B;
-    private static final int MENU_VIEW_INDEX = 0;
-    private static final String TAG = "ExpandableNotifRow";
-    public static final float DEFAULT_HEADER_VISIBLE_AMOUNT = 1.0f;
-
-    /**
-     * Listener for when {@link ExpandableNotificationRow} is laid out.
-     */
-    public interface LayoutListener {
-        void onLayout();
-    }
-
-    private LayoutListener mLayoutListener;
-    private boolean mDark;
-    private boolean mLowPriorityStateUpdated;
-    private final NotificationInflater mNotificationInflater;
-    private int mIconTransformContentShift;
-    private int mIconTransformContentShiftNoIcon;
-    private int mMaxHeadsUpHeightBeforeN;
-    private int mMaxHeadsUpHeightBeforeP;
-    private int mMaxHeadsUpHeight;
-    private int mMaxHeadsUpHeightIncreased;
-    private int mNotificationMinHeightBeforeN;
-    private int mNotificationMinHeightBeforeP;
-    private int mNotificationMinHeight;
-    private int mNotificationMinHeightLarge;
-    private int mNotificationMaxHeight;
-    private int mNotificationAmbientHeight;
-    private int mIncreasedPaddingBetweenElements;
-    private int mNotificationLaunchHeight;
-    private boolean mMustStayOnScreen;
-
-    /** Does this row contain layouts that can adapt to row expansion */
-    private boolean mExpandable;
-    /** Has the user actively changed the expansion state of this row */
-    private boolean mHasUserChangedExpansion;
-    /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
-    private boolean mUserExpanded;
-    /** Whether the blocking helper is showing on this notification (even if dismissed) */
-    private boolean mIsBlockingHelperShowing;
-
-    /**
-     * Has this notification been expanded while it was pinned
-     */
-    private boolean mExpandedWhenPinned;
-    /** Is the user touching this row */
-    private boolean mUserLocked;
-    /** Are we showing the "public" version */
-    private boolean mShowingPublic;
-    private boolean mSensitive;
-    private boolean mSensitiveHiddenInGeneral;
-    private boolean mShowingPublicInitialized;
-    private boolean mHideSensitiveForIntrinsicHeight;
-    private float mHeaderVisibleAmount = DEFAULT_HEADER_VISIBLE_AMOUNT;
-
-    /**
-     * Is this notification expanded by the system. The expansion state can be overridden by the
-     * user expansion.
-     */
-    private boolean mIsSystemExpanded;
-
-    /**
-     * Whether the notification is on the keyguard and the expansion is disabled.
-     */
-    private boolean mOnKeyguard;
-
-    private Animator mTranslateAnim;
-    private ArrayList<View> mTranslateableViews;
-    private NotificationContentView mPublicLayout;
-    private NotificationContentView mPrivateLayout;
-    private NotificationContentView[] mLayouts;
-    private int mNotificationColor;
-    private ExpansionLogger mLogger;
-    private String mLoggingKey;
-    private NotificationGuts mGuts;
-    private NotificationData.Entry mEntry;
-    private StatusBarNotification mStatusBarNotification;
-    private String mAppName;
-    private boolean mIsHeadsUp;
-    private boolean mLastChronometerRunning = true;
-    private ViewStub mChildrenContainerStub;
-    private NotificationGroupManager mGroupManager;
-    private boolean mChildrenExpanded;
-    private boolean mIsSummaryWithChildren;
-    private NotificationChildrenContainer mChildrenContainer;
-    private NotificationMenuRowPlugin mMenuRow;
-    private ViewStub mGutsStub;
-    private boolean mIsSystemChildExpanded;
-    private boolean mIsPinned;
-    private FalsingManager mFalsingManager;
-    private boolean mExpandAnimationRunning;
-    private AboveShelfChangedListener mAboveShelfChangedListener;
-    private HeadsUpManager mHeadsUpManager;
-    private Consumer<Boolean> mHeadsUpAnimatingAwayListener;
-    private boolean mChildIsExpanding;
-
-    private boolean mJustClicked;
-    private boolean mIconAnimationRunning;
-    private boolean mShowNoBackground;
-    private ExpandableNotificationRow mNotificationParent;
-    private OnExpandClickListener mOnExpandClickListener;
-    private View.OnClickListener mOnAppOpsClickListener;
-
-    // Listener will be called when receiving a long click event.
-    // Use #setLongPressPosition to optionally assign positional data with the long press.
-    private LongPressListener mLongPressListener;
-
-    private boolean mGroupExpansionChanging;
-
-    /**
-     * A supplier that returns true if keyguard is secure.
-     */
-    private BooleanSupplier mSecureStateProvider;
-
-    /**
-     * Whether or not a notification that is not part of a group of notifications can be manually
-     * expanded by the user.
-     */
-    private boolean mEnableNonGroupedNotificationExpand;
-
-    /**
-     * Whether or not to update the background of the header of the notification when its expanded.
-     * If {@code true}, the header background will disappear when expanded.
-     */
-    private boolean mShowGroupBackgroundWhenExpanded;
-
-    private OnClickListener mExpandClickListener = new OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            if (!shouldShowPublic() && (!mIsLowPriority || isExpanded())
-                    && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
-                mGroupExpansionChanging = true;
-                final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
-                boolean nowExpanded = mGroupManager.toggleGroupExpansion(mStatusBarNotification);
-                mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
-                MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
-                        nowExpanded);
-                onExpansionChanged(true /* userAction */, wasExpanded);
-            } else if (mEnableNonGroupedNotificationExpand) {
-                if (v.isAccessibilityFocused()) {
-                    mPrivateLayout.setFocusOnVisibilityChange();
-                }
-                boolean nowExpanded;
-                if (isPinned()) {
-                    nowExpanded = !mExpandedWhenPinned;
-                    mExpandedWhenPinned = nowExpanded;
-                } else {
-                    nowExpanded = !isExpanded();
-                    setUserExpanded(nowExpanded);
-                }
-                notifyHeightChanged(true);
-                mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
-                MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_EXPANDER,
-                        nowExpanded);
-            }
-        }
-    };
-    private boolean mForceUnlocked;
-    private boolean mDismissed;
-    private boolean mKeepInParent;
-    private boolean mRemoved;
-    private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT =
-            new FloatProperty<ExpandableNotificationRow>("translate") {
-                @Override
-                public void setValue(ExpandableNotificationRow object, float value) {
-                    object.setTranslation(value);
-                }
-
-                @Override
-                public Float get(ExpandableNotificationRow object) {
-                    return object.getTranslation();
-                }
-            };
-    private OnClickListener mOnClickListener;
-    private boolean mHeadsupDisappearRunning;
-    private View mChildAfterViewWhenDismissed;
-    private View mGroupParentWhenDismissed;
-    private boolean mRefocusOnDismiss;
-    private float mContentTransformationAmount;
-    private boolean mIconsVisible = true;
-    private boolean mAboveShelf;
-    private boolean mShowAmbient;
-    private boolean mIsLastChild;
-    private Runnable mOnDismissRunnable;
-    private boolean mIsLowPriority;
-    private boolean mIsColorized;
-    private boolean mUseIncreasedCollapsedHeight;
-    private boolean mUseIncreasedHeadsUpHeight;
-    private float mTranslationWhenRemoved;
-    private boolean mWasChildInGroupWhenRemoved;
-    private int mNotificationColorAmbient;
-    private NotificationViewState mNotificationViewState;
-
-    private SystemNotificationAsyncTask mSystemNotificationAsyncTask =
-            new SystemNotificationAsyncTask();
-
-    /**
-     * Returns whether the given {@code statusBarNotification} is a system notification.
-     * <b>Note</b>, this should be run in the background thread if possible as it makes multiple IPC
-     * calls.
-     */
-    private static Boolean isSystemNotification(
-            Context context, StatusBarNotification statusBarNotification) {
-        PackageManager packageManager = StatusBar.getPackageManagerForUser(
-                context, statusBarNotification.getUser().getIdentifier());
-        Boolean isSystemNotification = null;
-
-        try {
-            PackageInfo packageInfo = packageManager.getPackageInfo(
-                    statusBarNotification.getPackageName(), PackageManager.GET_SIGNATURES);
-
-            isSystemNotification =
-                    com.android.settingslib.Utils.isSystemPackage(
-                            context.getResources(), packageManager, packageInfo);
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, "cacheIsSystemNotification: Could not find package info");
-        }
-        return isSystemNotification;
-    }
-
-    @Override
-    public boolean isGroupExpansionChanging() {
-        if (isChildInGroup()) {
-            return mNotificationParent.isGroupExpansionChanging();
-        }
-        return mGroupExpansionChanging;
-    }
-
-    public void setGroupExpansionChanging(boolean changing) {
-        mGroupExpansionChanging = changing;
-    }
-
-    @Override
-    public void setActualHeightAnimating(boolean animating) {
-        if (mPrivateLayout != null) {
-            mPrivateLayout.setContentHeightAnimating(animating);
-        }
-    }
-
-    public NotificationContentView getPrivateLayout() {
-        return mPrivateLayout;
-    }
-
-    public NotificationContentView getPublicLayout() {
-        return mPublicLayout;
-    }
-
-    public void setIconAnimationRunning(boolean running) {
-        for (NotificationContentView l : mLayouts) {
-            setIconAnimationRunning(running, l);
-        }
-        if (mIsSummaryWithChildren) {
-            setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView());
-            setIconAnimationRunningForChild(running, mChildrenContainer.getLowPriorityHeaderView());
-            List<ExpandableNotificationRow> notificationChildren =
-                    mChildrenContainer.getNotificationChildren();
-            for (int i = 0; i < notificationChildren.size(); i++) {
-                ExpandableNotificationRow child = notificationChildren.get(i);
-                child.setIconAnimationRunning(running);
-            }
-        }
-        mIconAnimationRunning = running;
-    }
-
-    private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
-        if (layout != null) {
-            View contractedChild = layout.getContractedChild();
-            View expandedChild = layout.getExpandedChild();
-            View headsUpChild = layout.getHeadsUpChild();
-            setIconAnimationRunningForChild(running, contractedChild);
-            setIconAnimationRunningForChild(running, expandedChild);
-            setIconAnimationRunningForChild(running, headsUpChild);
-        }
-    }
-
-    private void setIconAnimationRunningForChild(boolean running, View child) {
-        if (child != null) {
-            ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
-            setIconRunning(icon, running);
-            ImageView rightIcon = (ImageView) child.findViewById(
-                    com.android.internal.R.id.right_icon);
-            setIconRunning(rightIcon, running);
-        }
-    }
-
-    private void setIconRunning(ImageView imageView, boolean running) {
-        if (imageView != null) {
-            Drawable drawable = imageView.getDrawable();
-            if (drawable instanceof AnimationDrawable) {
-                AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
-                if (running) {
-                    animationDrawable.start();
-                } else {
-                    animationDrawable.stop();
-                }
-            } else if (drawable instanceof AnimatedVectorDrawable) {
-                AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
-                if (running) {
-                    animationDrawable.start();
-                } else {
-                    animationDrawable.stop();
-                }
-            }
-        }
-    }
-
-    public void updateNotification(NotificationData.Entry entry) {
-        mEntry = entry;
-        mStatusBarNotification = entry.notification;
-        mNotificationInflater.inflateNotificationViews();
-
-        cacheIsSystemNotification();
-    }
-
-    /**
-     * Caches whether or not this row contains a system notification. Note, this is only cached
-     * once per notification as the packageInfo can't technically change for a notification row.
-     */
-    private void cacheIsSystemNotification() {
-        if (mEntry != null && mEntry.mIsSystemNotification == null) {
-            if (mSystemNotificationAsyncTask.getStatus() == AsyncTask.Status.PENDING) {
-                // Run async task once, only if it hasn't already been executed. Note this is
-                // executed in serial - no need to parallelize this small task.
-                mSystemNotificationAsyncTask.execute();
-            }
-        }
-    }
-
-    /**
-     * Returns whether this row is considered non-blockable (i.e. it's a non-blockable system notif
-     * or is in a whitelist).
-     */
-    public boolean getIsNonblockable() {
-        boolean isNonblockable = Dependency.get(NotificationBlockingHelperManager.class)
-                .isNonblockable(mStatusBarNotification.getPackageName(),
-                        mEntry.channel.getId());
-
-        // If the SystemNotifAsyncTask hasn't finished running or retrieved a value, we'll try once
-        // again, but in-place on the main thread this time. This should rarely ever get called.
-        if (mEntry != null && mEntry.mIsSystemNotification == null) {
-            if (DEBUG) {
-                Log.d(TAG, "Retrieving isSystemNotification on main thread");
-            }
-            mSystemNotificationAsyncTask.cancel(true /* mayInterruptIfRunning */);
-            mEntry.mIsSystemNotification = isSystemNotification(mContext, mStatusBarNotification);
-        }
-
-        if (!isNonblockable && mEntry != null && mEntry.mIsSystemNotification != null) {
-            if (mEntry.mIsSystemNotification) {
-                if (mEntry.channel != null
-                        && !mEntry.channel.isBlockableSystem()) {
-                    isNonblockable = true;
-                }
-            }
-        }
-        return isNonblockable;
-    }
-
-    public void onNotificationUpdated() {
-        for (NotificationContentView l : mLayouts) {
-            l.onNotificationUpdated(mEntry);
-        }
-        mIsColorized = mStatusBarNotification.getNotification().isColorized();
-        mShowingPublicInitialized = false;
-        updateNotificationColor();
-        if (mMenuRow != null) {
-            mMenuRow.onNotificationUpdated(mStatusBarNotification);
-            mMenuRow.setAppName(mAppName);
-        }
-        if (mIsSummaryWithChildren) {
-            mChildrenContainer.recreateNotificationHeader(mExpandClickListener);
-            mChildrenContainer.onNotificationUpdated();
-        }
-        if (mIconAnimationRunning) {
-            setIconAnimationRunning(true);
-        }
-        if (mNotificationParent != null) {
-            mNotificationParent.updateChildrenHeaderAppearance();
-        }
-        onChildrenCountChanged();
-        // The public layouts expand button is always visible
-        mPublicLayout.updateExpandButtons(true);
-        updateLimits();
-        updateIconVisibilities();
-        updateShelfIconColor();
-        updateRippleAllowed();
-    }
-
-    @VisibleForTesting
-    void updateShelfIconColor() {
-        StatusBarIconView expandedIcon = mEntry.expandedIcon;
-        boolean isPreL = Boolean.TRUE.equals(expandedIcon.getTag(R.id.icon_is_pre_L));
-        boolean colorize = !isPreL || NotificationUtils.isGrayscale(expandedIcon,
-                ContrastColorUtil.getInstance(mContext));
-        int color = StatusBarIconView.NO_COLOR;
-        if (colorize) {
-            NotificationHeaderView header = getVisibleNotificationHeader();
-            if (header != null) {
-                color = header.getOriginalIconColor();
-            } else {
-                color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded(),
-                        getBackgroundColorWithoutTint());
-            }
-        }
-        expandedIcon.setStaticDrawableColor(color);
-    }
-
-    public void setAboveShelfChangedListener(AboveShelfChangedListener aboveShelfChangedListener) {
-        mAboveShelfChangedListener = aboveShelfChangedListener;
-    }
-
-    /**
-     * Sets a supplier that can determine whether the keyguard is secure or not.
-     * @param secureStateProvider A function that returns true if keyguard is secure.
-     */
-    public void setSecureStateProvider(BooleanSupplier secureStateProvider) {
-        mSecureStateProvider = secureStateProvider;
-    }
-
-    @Override
-    public boolean isDimmable() {
-        if (!getShowingLayout().isDimmable()) {
-            return false;
-        }
-        return super.isDimmable();
-    }
-
-    private void updateLimits() {
-        for (NotificationContentView l : mLayouts) {
-            updateLimitsForView(l);
-        }
-    }
-
-    private void updateLimitsForView(NotificationContentView layout) {
-        boolean customView = layout.getContractedChild().getId()
-                != com.android.internal.R.id.status_bar_latest_event_content;
-        boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
-        boolean beforeP = mEntry.targetSdk < Build.VERSION_CODES.P;
-        int minHeight;
-        if (customView && beforeP && !mIsSummaryWithChildren) {
-            minHeight = beforeN ? mNotificationMinHeightBeforeN : mNotificationMinHeightBeforeP;
-        } else if (mUseIncreasedCollapsedHeight && layout == mPrivateLayout) {
-            minHeight = mNotificationMinHeightLarge;
-        } else {
-            minHeight = mNotificationMinHeight;
-        }
-        boolean headsUpCustom = layout.getHeadsUpChild() != null &&
-                layout.getHeadsUpChild().getId()
-                        != com.android.internal.R.id.status_bar_latest_event_content;
-        int headsUpHeight;
-        if (headsUpCustom && beforeP) {
-            headsUpHeight = beforeN ? mMaxHeadsUpHeightBeforeN : mMaxHeadsUpHeightBeforeP;
-        } else if (mUseIncreasedHeadsUpHeight && layout == mPrivateLayout) {
-            headsUpHeight = mMaxHeadsUpHeightIncreased;
-        } else {
-            headsUpHeight = mMaxHeadsUpHeight;
-        }
-        NotificationViewWrapper headsUpWrapper = layout.getVisibleWrapper(
-                NotificationContentView.VISIBLE_TYPE_HEADSUP);
-        if (headsUpWrapper != null) {
-            headsUpHeight = Math.max(headsUpHeight, headsUpWrapper.getMinLayoutHeight());
-        }
-        layout.setHeights(minHeight, headsUpHeight, mNotificationMaxHeight,
-                mNotificationAmbientHeight);
-    }
-
-    public StatusBarNotification getStatusBarNotification() {
-        return mStatusBarNotification;
-    }
-
-    public NotificationData.Entry getEntry() {
-        return mEntry;
-    }
-
-    public boolean isHeadsUp() {
-        return mIsHeadsUp;
-    }
-
-    public void setHeadsUp(boolean isHeadsUp) {
-        boolean wasAboveShelf = isAboveShelf();
-        int intrinsicBefore = getIntrinsicHeight();
-        mIsHeadsUp = isHeadsUp;
-        mPrivateLayout.setHeadsUp(isHeadsUp);
-        if (mIsSummaryWithChildren) {
-            // The overflow might change since we allow more lines as HUN.
-            mChildrenContainer.updateGroupOverflow();
-        }
-        if (intrinsicBefore != getIntrinsicHeight()) {
-            notifyHeightChanged(false  /* needsAnimation */);
-        }
-        if (isHeadsUp) {
-            mMustStayOnScreen = true;
-            setAboveShelf(true);
-        } else if (isAboveShelf() != wasAboveShelf) {
-            mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
-        }
-    }
-
-    public void setGroupManager(NotificationGroupManager groupManager) {
-        mGroupManager = groupManager;
-        mPrivateLayout.setGroupManager(groupManager);
-    }
-
-    public void setRemoteInputController(RemoteInputController r) {
-        mPrivateLayout.setRemoteInputController(r);
-    }
-
-    public void setAppName(String appName) {
-        mAppName = appName;
-        if (mMenuRow != null && mMenuRow.getMenuView() != null) {
-            mMenuRow.setAppName(mAppName);
-        }
-    }
-
-    public void addChildNotification(ExpandableNotificationRow row) {
-        addChildNotification(row, -1);
-    }
-
-    /**
-     * Set the how much the header should be visible. A value of 0 will make the header fully gone
-     * and a value of 1 will make the notification look just like normal.
-     * This is being used for heads up notifications, when they are pinned to the top of the screen
-     * and the header content is extracted to the statusbar.
-     *
-     * @param headerVisibleAmount the amount the header should be visible.
-     */
-    public void setHeaderVisibleAmount(float headerVisibleAmount) {
-        if (mHeaderVisibleAmount != headerVisibleAmount) {
-            mHeaderVisibleAmount = headerVisibleAmount;
-            mPrivateLayout.setHeaderVisibleAmount(headerVisibleAmount);
-            if (mChildrenContainer != null) {
-                mChildrenContainer.setHeaderVisibleAmount(headerVisibleAmount);
-            }
-            notifyHeightChanged(false /* needsAnimation */);
-        }
-    }
-
-    @Override
-    public float getHeaderVisibleAmount() {
-        return mHeaderVisibleAmount;
-    }
-
-    @Override
-    public void setHeadsUpIsVisible() {
-        super.setHeadsUpIsVisible();
-        mMustStayOnScreen = false;
-    }
-
-    /**
-     * Add a child notification to this view.
-     *
-     * @param row the row to add
-     * @param childIndex the index to add it at, if -1 it will be added at the end
-     */
-    public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
-        if (mChildrenContainer == null) {
-            mChildrenContainerStub.inflate();
-        }
-        mChildrenContainer.addNotification(row, childIndex);
-        onChildrenCountChanged();
-        row.setIsChildInGroup(true, this);
-    }
-
-    public void removeChildNotification(ExpandableNotificationRow row) {
-        if (mChildrenContainer != null) {
-            mChildrenContainer.removeNotification(row);
-        }
-        onChildrenCountChanged();
-        row.setIsChildInGroup(false, null);
-        row.setBottomRoundness(0.0f, false /* animate */);
-    }
-
-    @Override
-    public boolean isChildInGroup() {
-        return mNotificationParent != null;
-    }
-
-    /**
-     * @return whether this notification is the only child in the group summary
-     */
-    public boolean isOnlyChildInGroup() {
-        return mGroupManager.isOnlyChildInGroup(getStatusBarNotification());
-    }
-
-    public ExpandableNotificationRow getNotificationParent() {
-        return mNotificationParent;
-    }
-
-    /**
-     * @param isChildInGroup Is this notification now in a group
-     * @param parent the new parent notification
-     */
-    public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {
-        boolean childInGroup = StatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
-        if (mExpandAnimationRunning && !isChildInGroup && mNotificationParent != null) {
-            mNotificationParent.setChildIsExpanding(false);
-            mNotificationParent.setExtraWidthForClipping(0.0f);
-            mNotificationParent.setMinimumHeightForClipping(0);
-        }
-        mNotificationParent = childInGroup ? parent : null;
-        mPrivateLayout.setIsChildInGroup(childInGroup);
-        mNotificationInflater.setIsChildInGroup(childInGroup);
-        resetBackgroundAlpha();
-        updateBackgroundForGroupState();
-        updateClickAndFocus();
-        if (mNotificationParent != null) {
-            setOverrideTintColor(NO_COLOR, 0.0f);
-            // Let's reset the distance to top roundness, as this isn't applied to group children
-            setDistanceToTopRoundness(NO_ROUNDNESS);
-            mNotificationParent.updateBackgroundForGroupState();
-        }
-        updateIconVisibilities();
-        updateBackgroundClipping();
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (event.getActionMasked() != MotionEvent.ACTION_DOWN
-                || !isChildInGroup() || isGroupExpanded()) {
-            return super.onTouchEvent(event);
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    protected boolean handleSlideBack() {
-        if (mMenuRow != null && mMenuRow.isMenuVisible()) {
-            animateTranslateNotification(0 /* targetLeft */);
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    protected boolean shouldHideBackground() {
-        return super.shouldHideBackground() || mShowNoBackground;
-    }
-
-    @Override
-    public boolean isSummaryWithChildren() {
-        return mIsSummaryWithChildren;
-    }
-
-    @Override
-    public boolean areChildrenExpanded() {
-        return mChildrenExpanded;
-    }
-
-    public List<ExpandableNotificationRow> getNotificationChildren() {
-        return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
-    }
-
-    public int getNumberOfNotificationChildren() {
-        if (mChildrenContainer == null) {
-            return 0;
-        }
-        return mChildrenContainer.getNotificationChildren().size();
-    }
-
-    /**
-     * Apply the order given in the list to the children.
-     *
-     * @param childOrder the new list order
-     * @param visualStabilityManager
-     * @param callback the callback to invoked in case it is not allowed
-     * @return whether the list order has changed
-     */
-    public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
-            VisualStabilityManager visualStabilityManager,
-            VisualStabilityManager.Callback callback) {
-        return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder,
-                visualStabilityManager, callback);
-    }
-
-    public void getChildrenStates(StackScrollState resultState,
-            AmbientState ambientState) {
-        if (mIsSummaryWithChildren) {
-            ExpandableViewState parentState = resultState.getViewStateForView(this);
-            mChildrenContainer.getState(resultState, parentState, ambientState);
-        }
-    }
-
-    public void applyChildrenState(StackScrollState state) {
-        if (mIsSummaryWithChildren) {
-            mChildrenContainer.applyState(state);
-        }
-    }
-
-    public void prepareExpansionChanged(StackScrollState state) {
-        if (mIsSummaryWithChildren) {
-            mChildrenContainer.prepareExpansionChanged(state);
-        }
-    }
-
-    public void startChildAnimation(StackScrollState finalState, AnimationProperties properties) {
-        if (mIsSummaryWithChildren) {
-            mChildrenContainer.startAnimationToState(finalState, properties);
-        }
-    }
-
-    public ExpandableNotificationRow getViewAtPosition(float y) {
-        if (!mIsSummaryWithChildren || !mChildrenExpanded) {
-            return this;
-        } else {
-            ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
-            return view == null ? this : view;
-        }
-    }
-
-    public NotificationGuts getGuts() {
-        return mGuts;
-    }
-
-    /**
-     * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
-     * the notification will be rendered on top of the screen.
-     *
-     * @param pinned whether it is pinned
-     */
-    public void setPinned(boolean pinned) {
-        int intrinsicHeight = getIntrinsicHeight();
-        boolean wasAboveShelf = isAboveShelf();
-        mIsPinned = pinned;
-        if (intrinsicHeight != getIntrinsicHeight()) {
-            notifyHeightChanged(false /* needsAnimation */);
-        }
-        if (pinned) {
-            setIconAnimationRunning(true);
-            mExpandedWhenPinned = false;
-        } else if (mExpandedWhenPinned) {
-            setUserExpanded(true);
-        }
-        setChronometerRunning(mLastChronometerRunning);
-        if (isAboveShelf() != wasAboveShelf) {
-            mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
-        }
-    }
-
-    @Override
-    public boolean isPinned() {
-        return mIsPinned;
-    }
-
-    @Override
-    public int getPinnedHeadsUpHeight() {
-        return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
-    }
-
-    /**
-     * @param atLeastMinHeight should the value returned be at least the minimum height.
-     *                         Used to avoid cyclic calls
-     * @return the height of the heads up notification when pinned
-     */
-    private int getPinnedHeadsUpHeight(boolean atLeastMinHeight) {
-        if (mIsSummaryWithChildren) {
-            return mChildrenContainer.getIntrinsicHeight();
-        }
-        if(mExpandedWhenPinned) {
-            return Math.max(getMaxExpandHeight(), getHeadsUpHeight());
-        } else if (atLeastMinHeight) {
-            return Math.max(getCollapsedHeight(), getHeadsUpHeight());
-        } else {
-            return getHeadsUpHeight();
-        }
-    }
-
-    /**
-     * Mark whether this notification was just clicked, i.e. the user has just clicked this
-     * notification in this frame.
-     */
-    public void setJustClicked(boolean justClicked) {
-        mJustClicked = justClicked;
-    }
-
-    /**
-     * @return true if this notification has been clicked in this frame, false otherwise
-     */
-    public boolean wasJustClicked() {
-        return mJustClicked;
-    }
-
-    public void setChronometerRunning(boolean running) {
-        mLastChronometerRunning = running;
-        setChronometerRunning(running, mPrivateLayout);
-        setChronometerRunning(running, mPublicLayout);
-        if (mChildrenContainer != null) {
-            List<ExpandableNotificationRow> notificationChildren =
-                    mChildrenContainer.getNotificationChildren();
-            for (int i = 0; i < notificationChildren.size(); i++) {
-                ExpandableNotificationRow child = notificationChildren.get(i);
-                child.setChronometerRunning(running);
-            }
-        }
-    }
-
-    private void setChronometerRunning(boolean running, NotificationContentView layout) {
-        if (layout != null) {
-            running = running || isPinned();
-            View contractedChild = layout.getContractedChild();
-            View expandedChild = layout.getExpandedChild();
-            View headsUpChild = layout.getHeadsUpChild();
-            setChronometerRunningForChild(running, contractedChild);
-            setChronometerRunningForChild(running, expandedChild);
-            setChronometerRunningForChild(running, headsUpChild);
-        }
-    }
-
-    private void setChronometerRunningForChild(boolean running, View child) {
-        if (child != null) {
-            View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
-            if (chronometer instanceof Chronometer) {
-                ((Chronometer) chronometer).setStarted(running);
-            }
-        }
-    }
-
-    public NotificationHeaderView getNotificationHeader() {
-        if (mIsSummaryWithChildren) {
-            return mChildrenContainer.getHeaderView();
-        }
-        return mPrivateLayout.getNotificationHeader();
-    }
-
-    /**
-     * @return the currently visible notification header. This can be different from
-     * {@link #getNotificationHeader()} in case it is a low-priority group.
-     */
-    public NotificationHeaderView getVisibleNotificationHeader() {
-        if (mIsSummaryWithChildren && !shouldShowPublic()) {
-            return mChildrenContainer.getVisibleHeader();
-        }
-        return getShowingLayout().getVisibleNotificationHeader();
-    }
-
-
-    /**
-     * @return the contracted notification header. This can be different from
-     * {@link #getNotificationHeader()} and also {@link #getVisibleNotificationHeader()} and only
-     * returns the contracted version.
-     */
-    public NotificationHeaderView getContractedNotificationHeader() {
-        if (mIsSummaryWithChildren) {
-            return mChildrenContainer.getHeaderView();
-        }
-        return mPrivateLayout.getContractedNotificationHeader();
-    }
-
-    public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
-        mOnExpandClickListener = onExpandClickListener;
-    }
-
-    public void setLongPressListener(LongPressListener longPressListener) {
-        mLongPressListener = longPressListener;
-    }
-
-    @Override
-    public void setOnClickListener(@Nullable OnClickListener l) {
-        super.setOnClickListener(l);
-        mOnClickListener = l;
-        updateClickAndFocus();
-    }
-
-    private void updateClickAndFocus() {
-        boolean normalChild = !isChildInGroup() || isGroupExpanded();
-        boolean clickable = mOnClickListener != null && normalChild;
-        if (isFocusable() != normalChild) {
-            setFocusable(normalChild);
-        }
-        if (isClickable() != clickable) {
-            setClickable(clickable);
-        }
-    }
-
-    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
-        mHeadsUpManager = headsUpManager;
-    }
-
-    public void setGutsView(MenuItem item) {
-        if (mGuts != null && item.getGutsView() instanceof GutsContent) {
-            ((GutsContent) item.getGutsView()).setGutsParent(mGuts);
-            mGuts.setGutsContent((GutsContent) item.getGutsView());
-        }
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mEntry.setInitializationTime(SystemClock.elapsedRealtime());
-        Dependency.get(PluginManager.class).addPluginListener(this,
-                NotificationMenuRowPlugin.class, false /* Allow multiple */);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        Dependency.get(PluginManager.class).removePluginListener(this);
-    }
-
-    @Override
-    public void onPluginConnected(NotificationMenuRowPlugin plugin, Context pluginContext) {
-        boolean existed = mMenuRow.getMenuView() != null;
-        if (existed) {
-            removeView(mMenuRow.getMenuView());
-        }
-        mMenuRow = plugin;
-        if (mMenuRow.useDefaultMenuItems()) {
-            ArrayList<MenuItem> items = new ArrayList<>();
-            items.add(NotificationMenuRow.createInfoItem(mContext));
-            items.add(NotificationMenuRow.createSnoozeItem(mContext));
-            items.add(NotificationMenuRow.createAppOpsItem(mContext));
-            mMenuRow.setMenuItems(items);
-        }
-        if (existed) {
-            createMenu();
-        }
-    }
-
-    @Override
-    public void onPluginDisconnected(NotificationMenuRowPlugin plugin) {
-        boolean existed = mMenuRow.getMenuView() != null;
-        mMenuRow = new NotificationMenuRow(mContext); // Back to default
-        if (existed) {
-            createMenu();
-        }
-    }
-
-    public NotificationMenuRowPlugin createMenu() {
-        if (mMenuRow.getMenuView() == null) {
-            mMenuRow.createMenu(this, mStatusBarNotification);
-            mMenuRow.setAppName(mAppName);
-            FrameLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
-                    LayoutParams.MATCH_PARENT);
-            addView(mMenuRow.getMenuView(), MENU_VIEW_INDEX, lp);
-        }
-        return mMenuRow;
-    }
-
-    public NotificationMenuRowPlugin getProvider() {
-        return mMenuRow;
-    }
-
-    @Override
-    public void onDensityOrFontScaleChanged() {
-        super.onDensityOrFontScaleChanged();
-        initDimens();
-        initBackground();
-        // Let's update our childrencontainer. This is intentionally not guarded with
-        // mIsSummaryWithChildren since we might have had children but not anymore.
-        if (mChildrenContainer != null) {
-            mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
-        }
-        if (mGuts != null) {
-            View oldGuts = mGuts;
-            int index = indexOfChild(oldGuts);
-            removeView(oldGuts);
-            mGuts = (NotificationGuts) LayoutInflater.from(mContext).inflate(
-                    R.layout.notification_guts, this, false);
-            mGuts.setVisibility(oldGuts.getVisibility());
-            addView(mGuts, index);
-        }
-        View oldMenu = mMenuRow.getMenuView();
-        if (oldMenu != null) {
-            int menuIndex = indexOfChild(oldMenu);
-            removeView(oldMenu);
-            mMenuRow.createMenu(ExpandableNotificationRow.this, mStatusBarNotification);
-            mMenuRow.setAppName(mAppName);
-            addView(mMenuRow.getMenuView(), menuIndex);
-        }
-        for (NotificationContentView l : mLayouts) {
-            l.initView();
-            l.reInflateViews();
-        }
-        mNotificationInflater.onDensityOrFontScaleChanged();
-        onNotificationUpdated();
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        if (mMenuRow.getMenuView() != null) {
-            mMenuRow.onConfigurationChanged();
-        }
-    }
-
-    public void setContentBackground(int customBackgroundColor, boolean animate,
-            NotificationContentView notificationContentView) {
-        if (getShowingLayout() == notificationContentView) {
-            setTintColor(customBackgroundColor, animate);
-        }
-    }
-
-    @Override
-    protected void setBackgroundTintColor(int color) {
-        super.setBackgroundTintColor(color);
-        NotificationContentView view = getShowingLayout();
-        if (view != null) {
-            view.setBackgroundTintColor(color);
-        }
-    }
-
-    public void closeRemoteInput() {
-        for (NotificationContentView l : mLayouts) {
-            l.closeRemoteInput();
-        }
-    }
-
-    /**
-     * Set by how much the single line view should be indented.
-     */
-    public void setSingleLineWidthIndention(int indention) {
-        mPrivateLayout.setSingleLineWidthIndention(indention);
-    }
-
-    public int getNotificationColor() {
-        return mNotificationColor;
-    }
-
-    private void updateNotificationColor() {
-        mNotificationColor = ContrastColorUtil.resolveContrastColor(mContext,
-                getStatusBarNotification().getNotification().color,
-                getBackgroundColorWithoutTint());
-        mNotificationColorAmbient = ContrastColorUtil.resolveAmbientColor(mContext,
-                getStatusBarNotification().getNotification().color);
-    }
-
-    public HybridNotificationView getSingleLineView() {
-        return mPrivateLayout.getSingleLineView();
-    }
-
-    public HybridNotificationView getAmbientSingleLineView() {
-        return getShowingLayout().getAmbientSingleLineChild();
-    }
-
-    public boolean isOnKeyguard() {
-        return mOnKeyguard;
-    }
-
-    public void removeAllChildren() {
-        List<ExpandableNotificationRow> notificationChildren
-                = mChildrenContainer.getNotificationChildren();
-        ArrayList<ExpandableNotificationRow> clonedList = new ArrayList<>(notificationChildren);
-        for (int i = 0; i < clonedList.size(); i++) {
-            ExpandableNotificationRow row = clonedList.get(i);
-            if (row.keepInParent()) {
-                continue;
-            }
-            mChildrenContainer.removeNotification(row);
-            row.setIsChildInGroup(false, null);
-        }
-        onChildrenCountChanged();
-    }
-
-    public void setForceUnlocked(boolean forceUnlocked) {
-        mForceUnlocked = forceUnlocked;
-        if (mIsSummaryWithChildren) {
-            List<ExpandableNotificationRow> notificationChildren = getNotificationChildren();
-            for (ExpandableNotificationRow child : notificationChildren) {
-                child.setForceUnlocked(forceUnlocked);
-            }
-        }
-    }
-
-    public void setDismissed(boolean fromAccessibility) {
-        setLongPressListener(null);
-        mDismissed = true;
-        mGroupParentWhenDismissed = mNotificationParent;
-        mRefocusOnDismiss = fromAccessibility;
-        mChildAfterViewWhenDismissed = null;
-        mEntry.icon.setDismissed();
-        if (isChildInGroup()) {
-            List<ExpandableNotificationRow> notificationChildren =
-                    mNotificationParent.getNotificationChildren();
-            int i = notificationChildren.indexOf(this);
-            if (i != -1 && i < notificationChildren.size() - 1) {
-                mChildAfterViewWhenDismissed = notificationChildren.get(i + 1);
-            }
-        }
-    }
-
-    public boolean isDismissed() {
-        return mDismissed;
-    }
-
-    public boolean keepInParent() {
-        return mKeepInParent;
-    }
-
-    public void setKeepInParent(boolean keepInParent) {
-        mKeepInParent = keepInParent;
-    }
-
-    @Override
-    public boolean isRemoved() {
-        return mRemoved;
-    }
-
-    public void setRemoved() {
-        mRemoved = true;
-        mTranslationWhenRemoved = getTranslationY();
-        mWasChildInGroupWhenRemoved = isChildInGroup();
-        if (isChildInGroup()) {
-            mTranslationWhenRemoved += getNotificationParent().getTranslationY();
-        }
-        mPrivateLayout.setRemoved();
-    }
-
-    public boolean wasChildInGroupWhenRemoved() {
-        return mWasChildInGroupWhenRemoved;
-    }
-
-    public float getTranslationWhenRemoved() {
-        return mTranslationWhenRemoved;
-    }
-
-    public NotificationChildrenContainer getChildrenContainer() {
-        return mChildrenContainer;
-    }
-
-    public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
-        boolean wasAboveShelf = isAboveShelf();
-        boolean changed = headsUpAnimatingAway != mHeadsupDisappearRunning;
-        mHeadsupDisappearRunning = headsUpAnimatingAway;
-        mPrivateLayout.setHeadsUpAnimatingAway(headsUpAnimatingAway);
-        if (changed && mHeadsUpAnimatingAwayListener != null) {
-            mHeadsUpAnimatingAwayListener.accept(headsUpAnimatingAway);
-        }
-        if (isAboveShelf() != wasAboveShelf) {
-            mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
-        }
-    }
-
-    public void setHeadsUpAnimatingAwayListener(Consumer<Boolean> listener) {
-        mHeadsUpAnimatingAwayListener = listener;
-    }
-
-    /**
-     * @return if the view was just heads upped and is now animating away. During such a time the
-     * layout needs to be kept consistent
-     */
-    @Override
-    public boolean isHeadsUpAnimatingAway() {
-        return mHeadsupDisappearRunning;
-    }
-
-    public View getChildAfterViewWhenDismissed() {
-        return mChildAfterViewWhenDismissed;
-    }
-
-    public View getGroupParentWhenDismissed() {
-        return mGroupParentWhenDismissed;
-    }
-
-    /**
-     * Dismisses the notification with the option of showing the blocking helper in-place if we have
-     * a negative user sentiment.
-     *
-     * @param fromAccessibility whether this dismiss is coming from an accessibility action
-     * @return whether a blocking helper is shown in this row
-     */
-    public boolean performDismissWithBlockingHelper(boolean fromAccessibility) {
-        NotificationBlockingHelperManager manager =
-                Dependency.get(NotificationBlockingHelperManager.class);
-        boolean isBlockingHelperShown = manager.perhapsShowBlockingHelper(this, mMenuRow);
-
-        Dependency.get(MetricsLogger.class).count(NotificationCounters.NOTIFICATION_DISMISSED, 1);
-
-        // Continue with dismiss since we don't want the blocking helper to be directly associated
-        // with a certain notification.
-        performDismiss(fromAccessibility);
-        return isBlockingHelperShown;
-    }
-
-    public void performDismiss(boolean fromAccessibility) {
-        if (isOnlyChildInGroup()) {
-            ExpandableNotificationRow groupSummary =
-                    mGroupManager.getLogicalGroupSummary(getStatusBarNotification());
-            if (groupSummary.isClearable()) {
-                // If this is the only child in the group, dismiss the group, but don't try to show
-                // the blocking helper affordance!
-                groupSummary.performDismiss(fromAccessibility);
-            }
-        }
-        setDismissed(fromAccessibility);
-        if (isClearable()) {
-            if (mOnDismissRunnable != null) {
-                mOnDismissRunnable.run();
-            }
-        }
-    }
-
-    public void setBlockingHelperShowing(boolean isBlockingHelperShowing) {
-        mIsBlockingHelperShowing = isBlockingHelperShowing;
-    }
-
-    public boolean isBlockingHelperShowing() {
-        return mIsBlockingHelperShowing;
-    }
-
-    public void setOnDismissRunnable(Runnable onDismissRunnable) {
-        mOnDismissRunnable = onDismissRunnable;
-    }
-
-    public View getNotificationIcon() {
-        NotificationHeaderView notificationHeader = getVisibleNotificationHeader();
-        if (notificationHeader != null) {
-            return notificationHeader.getIcon();
-        }
-        return null;
-    }
-
-    /**
-     * @return whether the notification is currently showing a view with an icon.
-     */
-    public boolean isShowingIcon() {
-        if (areGutsExposed()) {
-            return false;
-        }
-        return getVisibleNotificationHeader() != null;
-    }
-
-    /**
-     * Set how much this notification is transformed into an icon.
-     *
-     * @param contentTransformationAmount A value from 0 to 1 indicating how much we are transformed
-     *                                 to the content away
-     * @param isLastChild is this the last child in the list. If true, then the transformation is
-     *                    different since it's content fades out.
-     */
-    public void setContentTransformationAmount(float contentTransformationAmount,
-            boolean isLastChild) {
-        boolean changeTransformation = isLastChild != mIsLastChild;
-        changeTransformation |= mContentTransformationAmount != contentTransformationAmount;
-        mIsLastChild = isLastChild;
-        mContentTransformationAmount = contentTransformationAmount;
-        if (changeTransformation) {
-            updateContentTransformation();
-        }
-    }
-
-    /**
-     * Set the icons to be visible of this notification.
-     */
-    public void setIconsVisible(boolean iconsVisible) {
-        if (iconsVisible != mIconsVisible) {
-            mIconsVisible = iconsVisible;
-            updateIconVisibilities();
-        }
-    }
-
-    @Override
-    protected void onBelowSpeedBumpChanged() {
-        updateIconVisibilities();
-    }
-
-    private void updateContentTransformation() {
-        if (mExpandAnimationRunning) {
-            return;
-        }
-        float contentAlpha;
-        float translationY = -mContentTransformationAmount * mIconTransformContentShift;
-        if (mIsLastChild) {
-            contentAlpha = 1.0f - mContentTransformationAmount;
-            contentAlpha = Math.min(contentAlpha / 0.5f, 1.0f);
-            contentAlpha = Interpolators.ALPHA_OUT.getInterpolation(contentAlpha);
-            translationY *= 0.4f;
-        } else {
-            contentAlpha = 1.0f;
-        }
-        for (NotificationContentView l : mLayouts) {
-            l.setAlpha(contentAlpha);
-            l.setTranslationY(translationY);
-        }
-        if (mChildrenContainer != null) {
-            mChildrenContainer.setAlpha(contentAlpha);
-            mChildrenContainer.setTranslationY(translationY);
-            // TODO: handle children fade out better
-        }
-    }
-
-    private void updateIconVisibilities() {
-        boolean visible = isChildInGroup()
-                || (isBelowSpeedBump() && !NotificationShelf.SHOW_AMBIENT_ICONS)
-                || mIconsVisible;
-        for (NotificationContentView l : mLayouts) {
-            l.setIconsVisible(visible);
-        }
-        if (mChildrenContainer != null) {
-            mChildrenContainer.setIconsVisible(visible);
-        }
-    }
-
-    /**
-     * Get the relative top padding of a view relative to this view. This recursively walks up the
-     * hierarchy and does the corresponding measuring.
-     *
-     * @param view the view to the the padding for. The requested view has to be a child of this
-     *             notification.
-     * @return the toppadding
-     */
-    public int getRelativeTopPadding(View view) {
-        int topPadding = 0;
-        while (view.getParent() instanceof ViewGroup) {
-            topPadding += view.getTop();
-            view = (View) view.getParent();
-            if (view instanceof ExpandableNotificationRow) {
-                return topPadding;
-            }
-        }
-        return topPadding;
-    }
-
-    public float getContentTranslation() {
-        return mPrivateLayout.getTranslationY();
-    }
-
-    public void setIsLowPriority(boolean isLowPriority) {
-        mIsLowPriority = isLowPriority;
-        mPrivateLayout.setIsLowPriority(isLowPriority);
-        mNotificationInflater.setIsLowPriority(mIsLowPriority);
-        if (mChildrenContainer != null) {
-            mChildrenContainer.setIsLowPriority(isLowPriority);
-        }
-    }
-
-
-    public void setLowPriorityStateUpdated(boolean lowPriorityStateUpdated) {
-        mLowPriorityStateUpdated = lowPriorityStateUpdated;
-    }
-
-    public boolean hasLowPriorityStateUpdated() {
-        return mLowPriorityStateUpdated;
-    }
-
-    public boolean isLowPriority() {
-        return mIsLowPriority;
-    }
-
-    public void setUseIncreasedCollapsedHeight(boolean use) {
-        mUseIncreasedCollapsedHeight = use;
-        mNotificationInflater.setUsesIncreasedHeight(use);
-    }
-
-    public void setUseIncreasedHeadsUpHeight(boolean use) {
-        mUseIncreasedHeadsUpHeight = use;
-        mNotificationInflater.setUsesIncreasedHeadsUpHeight(use);
-    }
-
-    public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
-        mNotificationInflater.setRemoteViewClickHandler(remoteViewClickHandler);
-    }
-
-    public void setInflationCallback(InflationCallback callback) {
-        mNotificationInflater.setInflationCallback(callback);
-    }
-
-    public void setNeedsRedaction(boolean needsRedaction) {
-        mNotificationInflater.setRedactAmbient(needsRedaction);
-    }
-
-    @VisibleForTesting
-    public NotificationInflater getNotificationInflater() {
-        return mNotificationInflater;
-    }
-
-    public int getNotificationColorAmbient() {
-        return mNotificationColorAmbient;
-    }
-
-    public interface ExpansionLogger {
-        void logNotificationExpansion(String key, boolean userAction, boolean expanded);
-    }
-
-    public ExpandableNotificationRow(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mFalsingManager = FalsingManager.getInstance(context);
-        mNotificationInflater = new NotificationInflater(this);
-        mMenuRow = new NotificationMenuRow(mContext);
-        initDimens();
-    }
-
-    private void initDimens() {
-        mNotificationMinHeightBeforeN = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_min_height_legacy);
-        mNotificationMinHeightBeforeP = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_min_height_before_p);
-        mNotificationMinHeight = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_min_height);
-        mNotificationMinHeightLarge = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_min_height_increased);
-        mNotificationMaxHeight = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_max_height);
-        mNotificationAmbientHeight = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_ambient_height);
-        mMaxHeadsUpHeightBeforeN = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_max_heads_up_height_legacy);
-        mMaxHeadsUpHeightBeforeP = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_max_heads_up_height_before_p);
-        mMaxHeadsUpHeight = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_max_heads_up_height);
-        mMaxHeadsUpHeightIncreased = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_max_heads_up_height_increased);
-
-        Resources res = getResources();
-        mIncreasedPaddingBetweenElements = res.getDimensionPixelSize(
-                R.dimen.notification_divider_height_increased);
-        mIconTransformContentShiftNoIcon = res.getDimensionPixelSize(
-                R.dimen.notification_icon_transform_content_shift);
-        mEnableNonGroupedNotificationExpand =
-                res.getBoolean(R.bool.config_enableNonGroupedNotificationExpand);
-        mShowGroupBackgroundWhenExpanded =
-                res.getBoolean(R.bool.config_showGroupNotificationBgWhenExpanded);
-    }
-
-    /**
-     * Resets this view so it can be re-used for an updated notification.
-     */
-    public void reset() {
-        mShowingPublicInitialized = false;
-        onHeightReset();
-        requestLayout();
-    }
-
-    public void showAppOpsIcons(ArraySet<Integer> activeOps) {
-        if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() != null) {
-            mChildrenContainer.getHeaderView().showAppOpsIcons(activeOps);
-        }
-        mPrivateLayout.showAppOpsIcons(activeOps);
-        mPublicLayout.showAppOpsIcons(activeOps);
-    }
-
-    public View.OnClickListener getAppOpsOnClickListener() {
-        return mOnAppOpsClickListener;
-    }
-
-    protected void setAppOpsOnClickListener(ExpandableNotificationRow.OnAppOpsClickListener l) {
-        mOnAppOpsClickListener = v -> {
-            createMenu();
-            MenuItem menuItem = getProvider().getAppOpsMenuItem(mContext);
-            if (menuItem != null) {
-                l.onClick(this, v.getWidth() / 2, v.getHeight() / 2, menuItem);
-            }
-        };
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
-        mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
-        mLayouts = new NotificationContentView[] {mPrivateLayout, mPublicLayout};
-
-        for (NotificationContentView l : mLayouts) {
-            l.setExpandClickListener(mExpandClickListener);
-            l.setContainingNotification(this);
-        }
-        mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
-        mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
-            @Override
-            public void onInflate(ViewStub stub, View inflated) {
-                mGuts = (NotificationGuts) inflated;
-                mGuts.setClipTopAmount(getClipTopAmount());
-                mGuts.setActualHeight(getActualHeight());
-                mGutsStub = null;
-            }
-        });
-        mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
-        mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
-
-            @Override
-            public void onInflate(ViewStub stub, View inflated) {
-                mChildrenContainer = (NotificationChildrenContainer) inflated;
-                mChildrenContainer.setIsLowPriority(mIsLowPriority);
-                mChildrenContainer.setContainingNotification(ExpandableNotificationRow.this);
-                mChildrenContainer.onNotificationUpdated();
-
-                if (mShouldTranslateContents) {
-                    mTranslateableViews.add(mChildrenContainer);
-                }
-            }
-        });
-
-        if (mShouldTranslateContents) {
-            // Add the views that we translate to reveal the menu
-            mTranslateableViews = new ArrayList<>();
-            for (int i = 0; i < getChildCount(); i++) {
-                mTranslateableViews.add(getChildAt(i));
-            }
-            // Remove views that don't translate
-            mTranslateableViews.remove(mChildrenContainerStub);
-            mTranslateableViews.remove(mGutsStub);
-        }
-    }
-
-    private void doLongClickCallback() {
-        doLongClickCallback(getWidth() / 2, getHeight() / 2);
-    }
-
-    public void doLongClickCallback(int x, int y) {
-        createMenu();
-        MenuItem menuItem = getProvider().getLongpressMenuItem(mContext);
-        doLongClickCallback(x, y, menuItem);
-    }
-
-    private void doLongClickCallback(int x, int y, MenuItem menuItem) {
-        if (mLongPressListener != null && menuItem != null) {
-            mLongPressListener.onLongPress(this, x, y, menuItem);
-        }
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (KeyEvent.isConfirmKey(keyCode)) {
-            event.startTracking();
-            return true;
-        }
-        return super.onKeyDown(keyCode, event);
-    }
-
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (KeyEvent.isConfirmKey(keyCode)) {
-            if (!event.isCanceled()) {
-                performClick();
-            }
-            return true;
-        }
-        return super.onKeyUp(keyCode, event);
-    }
-
-    @Override
-    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
-        if (KeyEvent.isConfirmKey(keyCode)) {
-            doLongClickCallback();
-            return true;
-        }
-        return false;
-    }
-
-    public void resetTranslation() {
-        if (mTranslateAnim != null) {
-            mTranslateAnim.cancel();
-        }
-
-        if (!mShouldTranslateContents) {
-            setTranslationX(0);
-        } else if (mTranslateableViews != null) {
-            for (int i = 0; i < mTranslateableViews.size(); i++) {
-                mTranslateableViews.get(i).setTranslationX(0);
-            }
-            invalidateOutline();
-            getEntry().expandedIcon.setScrollX(0);
-        }
-
-        mMenuRow.resetMenu();
-    }
-
-    void onGutsOpened() {
-        resetTranslation();
-        updateContentAccessibilityImportanceForGuts(false /* isEnabled */);
-    }
-
-    void onGutsClosed() {
-        updateContentAccessibilityImportanceForGuts(true /* isEnabled */);
-    }
-
-    /**
-     * Updates whether all the non-guts content inside this row is important for accessibility.
-     *
-     * @param isEnabled whether the content views should be enabled for accessibility
-     */
-    private void updateContentAccessibilityImportanceForGuts(boolean isEnabled) {
-        if (mChildrenContainer != null) {
-            updateChildAccessibilityImportance(mChildrenContainer, isEnabled);
-        }
-        if (mLayouts != null) {
-            for (View view : mLayouts) {
-                updateChildAccessibilityImportance(view, isEnabled);
-            }
-        }
-
-        if (isEnabled) {
-            this.requestAccessibilityFocus();
-        }
-    }
-
-    /**
-     * Updates whether the given childView is important for accessibility based on
-     * {@code isEnabled}.
-     */
-    private void updateChildAccessibilityImportance(View childView, boolean isEnabled) {
-        childView.setImportantForAccessibility(isEnabled
-                ? View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
-                : View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
-    }
-
-    public CharSequence getActiveRemoteInputText() {
-        return mPrivateLayout.getActiveRemoteInputText();
-    }
-
-    public void animateTranslateNotification(final float leftTarget) {
-        if (mTranslateAnim != null) {
-            mTranslateAnim.cancel();
-        }
-        mTranslateAnim = getTranslateViewAnimator(leftTarget, null /* updateListener */);
-        if (mTranslateAnim != null) {
-            mTranslateAnim.start();
-        }
-    }
-
-    @Override
-    public void setTranslation(float translationX) {
-        if (areGutsExposed()) {
-            // Don't translate if guts are showing.
-            return;
-        }
-        if (!mShouldTranslateContents) {
-            setTranslationX(translationX);
-        } else if (mTranslateableViews != null) {
-            // Translate the group of views
-            for (int i = 0; i < mTranslateableViews.size(); i++) {
-                if (mTranslateableViews.get(i) != null) {
-                    mTranslateableViews.get(i).setTranslationX(translationX);
-                }
-            }
-            invalidateOutline();
-
-            // In order to keep the shelf in sync with this swiping, we're simply translating
-            // it's icon by the same amount. The translation is already being used for the normal
-            // positioning, so we can use the scrollX instead.
-            getEntry().expandedIcon.setScrollX((int) -translationX);
-        }
-        if (mMenuRow.getMenuView() != null) {
-            mMenuRow.onTranslationUpdate(translationX);
-        }
-    }
-
-    @Override
-    public float getTranslation() {
-        if (!mShouldTranslateContents) {
-            return getTranslationX();
-        }
-
-        if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
-            // All of the views in the list should have same translation, just use first one.
-            return mTranslateableViews.get(0).getTranslationX();
-        }
-
-        return 0;
-    }
-
-    public Animator getTranslateViewAnimator(final float leftTarget,
-            AnimatorUpdateListener listener) {
-        if (mTranslateAnim != null) {
-            mTranslateAnim.cancel();
-        }
-        if (areGutsExposed()) {
-            // No translation if guts are exposed.
-            return null;
-        }
-        final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(this, TRANSLATE_CONTENT,
-                leftTarget);
-        if (listener != null) {
-            translateAnim.addUpdateListener(listener);
-        }
-        translateAnim.addListener(new AnimatorListenerAdapter() {
-            boolean cancelled = false;
-
-            @Override
-            public void onAnimationCancel(Animator anim) {
-                cancelled = true;
-            }
-
-            @Override
-            public void onAnimationEnd(Animator anim) {
-                if (!cancelled && leftTarget == 0) {
-                    mMenuRow.resetMenu();
-                    mTranslateAnim = null;
-                }
-            }
-        });
-        mTranslateAnim = translateAnim;
-        return translateAnim;
-    }
-
-    public void inflateGuts() {
-        if (mGuts == null) {
-            mGutsStub.inflate();
-        }
-    }
-
-    private void updateChildrenVisibility() {
-        boolean hideContentWhileLaunching = mExpandAnimationRunning && mGuts != null
-                && mGuts.isExposed();
-        mPrivateLayout.setVisibility(!shouldShowPublic() && !mIsSummaryWithChildren
-                && !hideContentWhileLaunching ? VISIBLE : INVISIBLE);
-        if (mChildrenContainer != null) {
-            mChildrenContainer.setVisibility(!shouldShowPublic() && mIsSummaryWithChildren
-                    && !hideContentWhileLaunching ? VISIBLE
-                    : INVISIBLE);
-        }
-        // The limits might have changed if the view suddenly became a group or vice versa
-        updateLimits();
-    }
-
-    @Override
-    public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
-        if (super.onRequestSendAccessibilityEventInternal(child, event)) {
-            // Add a record for the entire layout since its content is somehow small.
-            // The event comes from a leaf view that is interacted with.
-            AccessibilityEvent record = AccessibilityEvent.obtain();
-            onInitializeAccessibilityEvent(record);
-            dispatchPopulateAccessibilityEvent(record);
-            event.appendRecord(record);
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void setDark(boolean dark, boolean fade, long delay) {
-        super.setDark(dark, fade, delay);
-        mDark = dark;
-        if (!mIsHeadsUp) {
-            // Only fade the showing view of the pulsing notification.
-            fade = false;
-        }
-        final NotificationContentView showing = getShowingLayout();
-        if (showing != null) {
-            showing.setDark(dark, fade, delay);
-        }
-        if (mIsSummaryWithChildren) {
-            mChildrenContainer.setDark(dark, fade, delay);
-        }
-        updateShelfIconColor();
-    }
-
-    public void applyExpandAnimationParams(ExpandAnimationParameters params) {
-        if (params == null) {
-            return;
-        }
-        float zProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
-                params.getProgress(0, 50));
-        float translationZ = MathUtils.lerp(params.getStartTranslationZ(),
-                mNotificationLaunchHeight,
-                zProgress);
-        setTranslationZ(translationZ);
-        float extraWidthForClipping = params.getWidth() - getWidth()
-                + MathUtils.lerp(0, mOutlineRadius * 2, params.getProgress());
-        setExtraWidthForClipping(extraWidthForClipping);
-        int top = params.getTop();
-        float interpolation = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(params.getProgress());
-        int startClipTopAmount = params.getStartClipTopAmount();
-        if (mNotificationParent != null) {
-            top -= mNotificationParent.getTranslationY();
-            mNotificationParent.setTranslationZ(translationZ);
-            int parentStartClipTopAmount = params.getParentStartClipTopAmount();
-            if (startClipTopAmount != 0) {
-                int clipTopAmount = (int) MathUtils.lerp(parentStartClipTopAmount,
-                        parentStartClipTopAmount - startClipTopAmount,
-                        interpolation);
-                mNotificationParent.setClipTopAmount(clipTopAmount);
-            }
-            mNotificationParent.setExtraWidthForClipping(extraWidthForClipping);
-            mNotificationParent.setMinimumHeightForClipping(params.getHeight()
-                    + mNotificationParent.getActualHeight());
-        } else if (startClipTopAmount != 0) {
-            int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, interpolation);
-            setClipTopAmount(clipTopAmount);
-        }
-        setTranslationY(top);
-        setActualHeight(params.getHeight());
-
-        mBackgroundNormal.setExpandAnimationParams(params);
-    }
-
-    public void setExpandAnimationRunning(boolean expandAnimationRunning) {
-        View contentView;
-        if (mIsSummaryWithChildren) {
-            contentView =  mChildrenContainer;
-        } else {
-            contentView = getShowingLayout();
-        }
-        if (mGuts != null && mGuts.isExposed()) {
-            contentView = mGuts;
-        }
-        if (expandAnimationRunning) {
-            contentView.animate()
-                    .alpha(0f)
-                    .setDuration(ActivityLaunchAnimator.ANIMATION_DURATION_FADE_CONTENT)
-                    .setInterpolator(Interpolators.ALPHA_OUT);
-            setAboveShelf(true);
-            mExpandAnimationRunning = true;
-            mNotificationViewState.cancelAnimations(this);
-            mNotificationLaunchHeight = AmbientState.getNotificationLaunchHeight(getContext());
-        } else {
-            mExpandAnimationRunning = false;
-            setAboveShelf(isAboveShelf());
-            if (mGuts != null) {
-                mGuts.setAlpha(1.0f);
-            }
-            if (contentView != null) {
-                contentView.setAlpha(1.0f);
-            }
-            setExtraWidthForClipping(0.0f);
-            if (mNotificationParent != null) {
-                mNotificationParent.setExtraWidthForClipping(0.0f);
-                mNotificationParent.setMinimumHeightForClipping(0);
-            }
-        }
-        if (mNotificationParent != null) {
-            mNotificationParent.setChildIsExpanding(mExpandAnimationRunning);
-        }
-        updateChildrenVisibility();
-        updateClipping();
-        mBackgroundNormal.setExpandAnimationRunning(expandAnimationRunning);
-    }
-
-    private void setChildIsExpanding(boolean isExpanding) {
-        mChildIsExpanding = isExpanding;
-    }
-
-    @Override
-    public boolean hasExpandingChild() {
-        return mChildIsExpanding;
-    }
-
-    @Override
-    protected boolean shouldClipToActualHeight() {
-        return super.shouldClipToActualHeight() && !mExpandAnimationRunning && !mChildIsExpanding;
-    }
-
-    @Override
-    public boolean isExpandAnimationRunning() {
-        return mExpandAnimationRunning;
-    }
-
-    /**
-     * Tap sounds should not be played when we're unlocking.
-     * Doing so would cause audio collision and the system would feel unpolished.
-     */
-    @Override
-    public boolean isSoundEffectsEnabled() {
-        final boolean mute = mDark && mSecureStateProvider != null &&
-                !mSecureStateProvider.getAsBoolean();
-        return !mute && super.isSoundEffectsEnabled();
-    }
-
-    public boolean isExpandable() {
-        if (mIsSummaryWithChildren && !shouldShowPublic()) {
-            return !mChildrenExpanded;
-        }
-        return mEnableNonGroupedNotificationExpand && mExpandable;
-    }
-
-    public void setExpandable(boolean expandable) {
-        mExpandable = expandable;
-        mPrivateLayout.updateExpandButtons(isExpandable());
-    }
-
-    @Override
-    public void setClipToActualHeight(boolean clipToActualHeight) {
-        super.setClipToActualHeight(clipToActualHeight || isUserLocked());
-        getShowingLayout().setClipToActualHeight(clipToActualHeight || isUserLocked());
-    }
-
-    /**
-     * @return whether the user has changed the expansion state
-     */
-    public boolean hasUserChangedExpansion() {
-        return mHasUserChangedExpansion;
-    }
-
-    public boolean isUserExpanded() {
-        return mUserExpanded;
-    }
-
-    /**
-     * Set this notification to be expanded by the user
-     *
-     * @param userExpanded whether the user wants this notification to be expanded
-     */
-    public void setUserExpanded(boolean userExpanded) {
-        setUserExpanded(userExpanded, false /* allowChildExpansion */);
-    }
-
-    /**
-     * Set this notification to be expanded by the user
-     *
-     * @param userExpanded whether the user wants this notification to be expanded
-     * @param allowChildExpansion whether a call to this method allows expanding children
-     */
-    public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
-        mFalsingManager.setNotificationExpanded();
-        if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
-                && !mChildrenContainer.showingAsLowPriority()) {
-            final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
-            mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
-            onExpansionChanged(true /* userAction */, wasExpanded);
-            return;
-        }
-        if (userExpanded && !mExpandable) return;
-        final boolean wasExpanded = isExpanded();
-        mHasUserChangedExpansion = true;
-        mUserExpanded = userExpanded;
-        onExpansionChanged(true /* userAction */, wasExpanded);
-        if (!wasExpanded && isExpanded()
-                && getActualHeight() != getIntrinsicHeight()) {
-            notifyHeightChanged(true /* needsAnimation */);
-        }
-    }
-
-    public void resetUserExpansion() {
-        boolean changed = mUserExpanded;
-        mHasUserChangedExpansion = false;
-        mUserExpanded = false;
-        if (changed && mIsSummaryWithChildren) {
-            mChildrenContainer.onExpansionChanged();
-        }
-        updateShelfIconColor();
-    }
-
-    public boolean isUserLocked() {
-        return mUserLocked && !mForceUnlocked;
-    }
-
-    public void setUserLocked(boolean userLocked) {
-        mUserLocked = userLocked;
-        mPrivateLayout.setUserExpanding(userLocked);
-        // This is intentionally not guarded with mIsSummaryWithChildren since we might have had
-        // children but not anymore.
-        if (mChildrenContainer != null) {
-            mChildrenContainer.setUserLocked(userLocked);
-            if (mIsSummaryWithChildren && (userLocked || !isGroupExpanded())) {
-                updateBackgroundForGroupState();
-            }
-        }
-    }
-
-    /**
-     * @return has the system set this notification to be expanded
-     */
-    public boolean isSystemExpanded() {
-        return mIsSystemExpanded;
-    }
-
-    /**
-     * Set this notification to be expanded by the system.
-     *
-     * @param expand whether the system wants this notification to be expanded.
-     */
-    public void setSystemExpanded(boolean expand) {
-        if (expand != mIsSystemExpanded) {
-            final boolean wasExpanded = isExpanded();
-            mIsSystemExpanded = expand;
-            notifyHeightChanged(false /* needsAnimation */);
-            onExpansionChanged(false /* userAction */, wasExpanded);
-            if (mIsSummaryWithChildren) {
-                mChildrenContainer.updateGroupOverflow();
-            }
-        }
-    }
-
-    /**
-     * @param onKeyguard whether to prevent notification expansion
-     */
-    public void setOnKeyguard(boolean onKeyguard) {
-        if (onKeyguard != mOnKeyguard) {
-            boolean wasAboveShelf = isAboveShelf();
-            final boolean wasExpanded = isExpanded();
-            mOnKeyguard = onKeyguard;
-            onExpansionChanged(false /* userAction */, wasExpanded);
-            if (wasExpanded != isExpanded()) {
-                if (mIsSummaryWithChildren) {
-                    mChildrenContainer.updateGroupOverflow();
-                }
-                notifyHeightChanged(false /* needsAnimation */);
-            }
-            if (isAboveShelf() != wasAboveShelf) {
-                mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
-            }
-        }
-        updateRippleAllowed();
-    }
-
-    private void updateRippleAllowed() {
-        boolean allowed = isOnKeyguard()
-                || mEntry.notification.getNotification().contentIntent == null;
-        setRippleAllowed(allowed);
-    }
-
-    /**
-     * @return Can the underlying notification be cleared? This can be different from whether the
-     *         notification can be dismissed in case notifications are sensitive on the lockscreen.
-     * @see #canViewBeDismissed()
-     */
-    public boolean isClearable() {
-        if (mStatusBarNotification == null || !mStatusBarNotification.isClearable()) {
-            return false;
-        }
-        if (mIsSummaryWithChildren) {
-            List<ExpandableNotificationRow> notificationChildren =
-                    mChildrenContainer.getNotificationChildren();
-            for (int i = 0; i < notificationChildren.size(); i++) {
-                ExpandableNotificationRow child = notificationChildren.get(i);
-                if (!child.isClearable()) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public int getIntrinsicHeight() {
-        if (isUserLocked()) {
-            return getActualHeight();
-        }
-        if (mGuts != null && mGuts.isExposed()) {
-            return mGuts.getIntrinsicHeight();
-        } else if ((isChildInGroup() && !isGroupExpanded())) {
-            return mPrivateLayout.getMinHeight();
-        } else if (mSensitive && mHideSensitiveForIntrinsicHeight) {
-            return getMinHeight();
-        } else if (mIsSummaryWithChildren && (!mOnKeyguard || mShowAmbient)) {
-            return mChildrenContainer.getIntrinsicHeight();
-        } else if (isHeadsUpAllowed() && (mIsHeadsUp || mHeadsupDisappearRunning)) {
-            if (isPinned() || mHeadsupDisappearRunning) {
-                return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
-            } else if (isExpanded()) {
-                return Math.max(getMaxExpandHeight(), getHeadsUpHeight());
-            } else {
-                return Math.max(getCollapsedHeight(), getHeadsUpHeight());
-            }
-        } else if (isExpanded()) {
-            return getMaxExpandHeight();
-        } else {
-            return getCollapsedHeight();
-        }
-    }
-
-    private boolean isHeadsUpAllowed() {
-        return !mOnKeyguard && !mShowAmbient;
-    }
-
-    @Override
-    public boolean isGroupExpanded() {
-        return mGroupManager.isGroupExpanded(mStatusBarNotification);
-    }
-
-    private void onChildrenCountChanged() {
-        mIsSummaryWithChildren = StatusBar.ENABLE_CHILD_NOTIFICATIONS
-                && mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0;
-        if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) {
-            mChildrenContainer.recreateNotificationHeader(mExpandClickListener
-            );
-        }
-        getShowingLayout().updateBackgroundColor(false /* animate */);
-        mPrivateLayout.updateExpandButtons(isExpandable());
-        updateChildrenHeaderAppearance();
-        updateChildrenVisibility();
-        applyChildrenRoundness();
-    }
-    /**
-     * Returns the number of channels covered by the notification row (including its children if
-     * it's a summary notification).
-     */
-    public int getNumUniqueChannels() {
-        ArraySet<NotificationChannel> channels = new ArraySet<>();
-
-        channels.add(mEntry.channel);
-
-        // If this is a summary, then add in the children notification channels for the
-        // same user and pkg.
-        if (mIsSummaryWithChildren) {
-            final List<ExpandableNotificationRow> childrenRows = getNotificationChildren();
-            final int numChildren = childrenRows.size();
-            for (int i = 0; i < numChildren; i++) {
-                final ExpandableNotificationRow childRow = childrenRows.get(i);
-                final NotificationChannel childChannel = childRow.getEntry().channel;
-                final StatusBarNotification childSbn = childRow.getStatusBarNotification();
-                if (childSbn.getUser().equals(mStatusBarNotification.getUser()) &&
-                        childSbn.getPackageName().equals(mStatusBarNotification.getPackageName())) {
-                    channels.add(childChannel);
-                }
-            }
-        }
-        return channels.size();
-    }
-
-    public void updateChildrenHeaderAppearance() {
-        if (mIsSummaryWithChildren) {
-            mChildrenContainer.updateChildrenHeaderAppearance();
-        }
-    }
-
-    /**
-     * Check whether the view state is currently expanded. This is given by the system in {@link
-     * #setSystemExpanded(boolean)} and can be overridden by user expansion or
-     * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
-     * view can differ from this state, if layout params are modified from outside.
-     *
-     * @return whether the view state is currently expanded.
-     */
-    public boolean isExpanded() {
-        return isExpanded(false /* allowOnKeyguard */);
-    }
-
-    public boolean isExpanded(boolean allowOnKeyguard) {
-        return (!mOnKeyguard || allowOnKeyguard)
-                && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
-                || isUserExpanded());
-    }
-
-    private boolean isSystemChildExpanded() {
-        return mIsSystemChildExpanded;
-    }
-
-    public void setSystemChildExpanded(boolean expanded) {
-        mIsSystemChildExpanded = expanded;
-    }
-
-    public void setLayoutListener(LayoutListener listener) {
-        mLayoutListener = listener;
-    }
-
-    public void removeListener() {
-        mLayoutListener = null;
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        int intrinsicBefore = getIntrinsicHeight();
-        super.onLayout(changed, left, top, right, bottom);
-        if (intrinsicBefore != getIntrinsicHeight()) {
-            notifyHeightChanged(true  /* needsAnimation */);
-        }
-        if (mMenuRow.getMenuView() != null) {
-            mMenuRow.onHeightUpdate();
-        }
-        updateContentShiftHeight();
-        if (mLayoutListener != null) {
-            mLayoutListener.onLayout();
-        }
-    }
-
-    /**
-     * Updates the content shift height such that the header is completely hidden when coming from
-     * the top.
-     */
-    private void updateContentShiftHeight() {
-        NotificationHeaderView notificationHeader = getVisibleNotificationHeader();
-        if (notificationHeader != null) {
-            CachingIconView icon = notificationHeader.getIcon();
-            mIconTransformContentShift = getRelativeTopPadding(icon) + icon.getHeight();
-        } else {
-            mIconTransformContentShift = mIconTransformContentShiftNoIcon;
-        }
-    }
-
-    @Override
-    public void notifyHeightChanged(boolean needsAnimation) {
-        super.notifyHeightChanged(needsAnimation);
-        getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
-    }
-
-    public void setSensitive(boolean sensitive, boolean hideSensitive) {
-        mSensitive = sensitive;
-        mSensitiveHiddenInGeneral = hideSensitive;
-    }
-
-    @Override
-    public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
-        mHideSensitiveForIntrinsicHeight = hideSensitive;
-        if (mIsSummaryWithChildren) {
-            List<ExpandableNotificationRow> notificationChildren =
-                    mChildrenContainer.getNotificationChildren();
-            for (int i = 0; i < notificationChildren.size(); i++) {
-                ExpandableNotificationRow child = notificationChildren.get(i);
-                child.setHideSensitiveForIntrinsicHeight(hideSensitive);
-            }
-        }
-    }
-
-    @Override
-    public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
-            long duration) {
-        if (getVisibility() == GONE) {
-            // If we are GONE, the hideSensitive parameter will not be calculated and always be
-            // false, which is incorrect, let's wait until a real call comes in later.
-            return;
-        }
-        boolean oldShowingPublic = mShowingPublic;
-        mShowingPublic = mSensitive && hideSensitive;
-        if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
-            return;
-        }
-
-        // bail out if no public version
-        if (mPublicLayout.getChildCount() == 0) return;
-
-        if (!animated) {
-            mPublicLayout.animate().cancel();
-            mPrivateLayout.animate().cancel();
-            if (mChildrenContainer != null) {
-                mChildrenContainer.animate().cancel();
-                mChildrenContainer.setAlpha(1f);
-            }
-            mPublicLayout.setAlpha(1f);
-            mPrivateLayout.setAlpha(1f);
-            mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
-            updateChildrenVisibility();
-        } else {
-            animateShowingPublic(delay, duration, mShowingPublic);
-        }
-        NotificationContentView showingLayout = getShowingLayout();
-        showingLayout.updateBackgroundColor(animated);
-        mPrivateLayout.updateExpandButtons(isExpandable());
-        updateShelfIconColor();
-        showingLayout.setDark(isDark(), false /* animate */, 0 /* delay */);
-        mShowingPublicInitialized = true;
-    }
-
-    private void animateShowingPublic(long delay, long duration, boolean showingPublic) {
-        View[] privateViews = mIsSummaryWithChildren
-                ? new View[] {mChildrenContainer}
-                : new View[] {mPrivateLayout};
-        View[] publicViews = new View[] {mPublicLayout};
-        View[] hiddenChildren = showingPublic ? privateViews : publicViews;
-        View[] shownChildren = showingPublic ? publicViews : privateViews;
-        for (final View hiddenView : hiddenChildren) {
-            hiddenView.setVisibility(View.VISIBLE);
-            hiddenView.animate().cancel();
-            hiddenView.animate()
-                    .alpha(0f)
-                    .setStartDelay(delay)
-                    .setDuration(duration)
-                    .withEndAction(new Runnable() {
-                        @Override
-                        public void run() {
-                            hiddenView.setVisibility(View.INVISIBLE);
-                        }
-                    });
-        }
-        for (View showView : shownChildren) {
-            showView.setVisibility(View.VISIBLE);
-            showView.setAlpha(0f);
-            showView.animate().cancel();
-            showView.animate()
-                    .alpha(1f)
-                    .setStartDelay(delay)
-                    .setDuration(duration);
-        }
-    }
-
-    @Override
-    public boolean mustStayOnScreen() {
-        return mIsHeadsUp && mMustStayOnScreen;
-    }
-
-    /**
-     * @return Whether this view is allowed to be dismissed. Only valid for visible notifications as
-     *         otherwise some state might not be updated. To request about the general clearability
-     *         see {@link #isClearable()}.
-     */
-    public boolean canViewBeDismissed() {
-        return isClearable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral);
-    }
-
-    private boolean shouldShowPublic() {
-        return mSensitive && mHideSensitiveForIntrinsicHeight;
-    }
-
-    public void makeActionsVisibile() {
-        setUserExpanded(true, true);
-        if (isChildInGroup()) {
-            mGroupManager.setGroupExpanded(mStatusBarNotification, true);
-        }
-        notifyHeightChanged(false /* needsAnimation */);
-    }
-
-    public void setChildrenExpanded(boolean expanded, boolean animate) {
-        mChildrenExpanded = expanded;
-        if (mChildrenContainer != null) {
-            mChildrenContainer.setChildrenExpanded(expanded);
-        }
-        updateBackgroundForGroupState();
-        updateClickAndFocus();
-    }
-
-    public static void applyTint(View v, int color) {
-        int alpha;
-        if (color != 0) {
-            alpha = COLORED_DIVIDER_ALPHA;
-        } else {
-            color = 0xff000000;
-            alpha = DEFAULT_DIVIDER_ALPHA;
-        }
-        if (v.getBackground() instanceof ColorDrawable) {
-            ColorDrawable background = (ColorDrawable) v.getBackground();
-            background.mutate();
-            background.setColor(color);
-            background.setAlpha(alpha);
-        }
-    }
-
-    public int getMaxExpandHeight() {
-        return mPrivateLayout.getExpandHeight();
-    }
-
-
-    private int getHeadsUpHeight() {
-        return mPrivateLayout.getHeadsUpHeight();
-    }
-
-    public boolean areGutsExposed() {
-        return (mGuts != null && mGuts.isExposed());
-    }
-
-    @Override
-    public boolean isContentExpandable() {
-        if (mIsSummaryWithChildren && !shouldShowPublic()) {
-            return true;
-        }
-        NotificationContentView showingLayout = getShowingLayout();
-        return showingLayout.isContentExpandable();
-    }
-
-    @Override
-    protected View getContentView() {
-        if (mIsSummaryWithChildren && !shouldShowPublic()) {
-            return mChildrenContainer;
-        }
-        return getShowingLayout();
-    }
-
-    @Override
-    protected void onAppearAnimationFinished(boolean wasAppearing) {
-        super.onAppearAnimationFinished(wasAppearing);
-        if (wasAppearing) {
-            // During the animation the visible view might have changed, so let's make sure all
-            // alphas are reset
-            if (mChildrenContainer != null) {
-                mChildrenContainer.setAlpha(1.0f);
-                mChildrenContainer.setLayerType(LAYER_TYPE_NONE, null);
-            }
-            for (NotificationContentView l : mLayouts) {
-                l.setAlpha(1.0f);
-                l.setLayerType(LAYER_TYPE_NONE, null);
-            }
-        }
-    }
-
-    @Override
-    public int getExtraBottomPadding() {
-        if (mIsSummaryWithChildren && isGroupExpanded()) {
-            return mIncreasedPaddingBetweenElements;
-        }
-        return 0;
-    }
-
-    @Override
-    public void setActualHeight(int height, boolean notifyListeners) {
-        boolean changed = height != getActualHeight();
-        super.setActualHeight(height, notifyListeners);
-        if (changed && isRemoved()) {
-            // TODO: remove this once we found the gfx bug for this.
-            // This is a hack since a removed view sometimes would just stay blank. it occured
-            // when sending yourself a message and then clicking on it.
-            ViewGroup parent = (ViewGroup) getParent();
-            if (parent != null) {
-                parent.invalidate();
-            }
-        }
-        if (mGuts != null && mGuts.isExposed()) {
-            mGuts.setActualHeight(height);
-            return;
-        }
-        int contentHeight = Math.max(getMinHeight(), height);
-        for (NotificationContentView l : mLayouts) {
-            l.setContentHeight(contentHeight);
-        }
-        if (mIsSummaryWithChildren) {
-            mChildrenContainer.setActualHeight(height);
-        }
-        if (mGuts != null) {
-            mGuts.setActualHeight(height);
-        }
-        if (mMenuRow.getMenuView() != null) {
-            mMenuRow.onHeightUpdate();
-        }
-    }
-
-    @Override
-    public int getMaxContentHeight() {
-        if (mIsSummaryWithChildren && !shouldShowPublic()) {
-            return mChildrenContainer.getMaxContentHeight();
-        }
-        NotificationContentView showingLayout = getShowingLayout();
-        return showingLayout.getMaxHeight();
-    }
-
-    @Override
-    public int getMinHeight(boolean ignoreTemporaryStates) {
-        if (!ignoreTemporaryStates && mGuts != null && mGuts.isExposed()) {
-            return mGuts.getIntrinsicHeight();
-        } else if (!ignoreTemporaryStates && isHeadsUpAllowed() && mIsHeadsUp
-                && mHeadsUpManager.isTrackingHeadsUp()) {
-                return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
-        } else if (mIsSummaryWithChildren && !isGroupExpanded() && !shouldShowPublic()) {
-            return mChildrenContainer.getMinHeight();
-        } else if (!ignoreTemporaryStates && isHeadsUpAllowed() && mIsHeadsUp) {
-            return getHeadsUpHeight();
-        }
-        NotificationContentView showingLayout = getShowingLayout();
-        return showingLayout.getMinHeight();
-    }
-
-    @Override
-    public int getCollapsedHeight() {
-        if (mIsSummaryWithChildren && !shouldShowPublic()) {
-            return mChildrenContainer.getCollapsedHeight();
-        }
-        return getMinHeight();
-    }
-
-    @Override
-    public void setClipTopAmount(int clipTopAmount) {
-        super.setClipTopAmount(clipTopAmount);
-        for (NotificationContentView l : mLayouts) {
-            l.setClipTopAmount(clipTopAmount);
-        }
-        if (mGuts != null) {
-            mGuts.setClipTopAmount(clipTopAmount);
-        }
-    }
-
-    @Override
-    public void setClipBottomAmount(int clipBottomAmount) {
-        if (mExpandAnimationRunning) {
-            return;
-        }
-        if (clipBottomAmount != mClipBottomAmount) {
-            super.setClipBottomAmount(clipBottomAmount);
-            for (NotificationContentView l : mLayouts) {
-                l.setClipBottomAmount(clipBottomAmount);
-            }
-            if (mGuts != null) {
-                mGuts.setClipBottomAmount(clipBottomAmount);
-            }
-        }
-        if (mChildrenContainer != null && !mChildIsExpanding) {
-            // We have to update this even if it hasn't changed, since the children locations can
-            // have changed
-            mChildrenContainer.setClipBottomAmount(clipBottomAmount);
-        }
-    }
-
-    public NotificationContentView getShowingLayout() {
-        return shouldShowPublic() ? mPublicLayout : mPrivateLayout;
-    }
-
-    public void setLegacy(boolean legacy) {
-        for (NotificationContentView l : mLayouts) {
-            l.setLegacy(legacy);
-        }
-    }
-
-    @Override
-    protected void updateBackgroundTint() {
-        super.updateBackgroundTint();
-        updateBackgroundForGroupState();
-        if (mIsSummaryWithChildren) {
-            List<ExpandableNotificationRow> notificationChildren =
-                    mChildrenContainer.getNotificationChildren();
-            for (int i = 0; i < notificationChildren.size(); i++) {
-                ExpandableNotificationRow child = notificationChildren.get(i);
-                child.updateBackgroundForGroupState();
-            }
-        }
-    }
-
-    /**
-     * Called when a group has finished animating from collapsed or expanded state.
-     */
-    public void onFinishedExpansionChange() {
-        mGroupExpansionChanging = false;
-        updateBackgroundForGroupState();
-    }
-
-    /**
-     * Updates the parent and children backgrounds in a group based on the expansion state.
-     */
-    public void updateBackgroundForGroupState() {
-        if (mIsSummaryWithChildren) {
-            // Only when the group has finished expanding do we hide its background.
-            mShowNoBackground = !mShowGroupBackgroundWhenExpanded && isGroupExpanded()
-                    && !isGroupExpansionChanging() && !isUserLocked();
-            mChildrenContainer.updateHeaderForExpansion(mShowNoBackground);
-            List<ExpandableNotificationRow> children = mChildrenContainer.getNotificationChildren();
-            for (int i = 0; i < children.size(); i++) {
-                children.get(i).updateBackgroundForGroupState();
-            }
-        } else if (isChildInGroup()) {
-            final int childColor = getShowingLayout().getBackgroundColorForExpansionState();
-            // Only show a background if the group is expanded OR if it is expanding / collapsing
-            // and has a custom background color.
-            final boolean showBackground = isGroupExpanded()
-                    || ((mNotificationParent.isGroupExpansionChanging()
-                    || mNotificationParent.isUserLocked()) && childColor != 0);
-            mShowNoBackground = !showBackground;
-        } else {
-            // Only children or parents ever need no background.
-            mShowNoBackground = false;
-        }
-        updateOutline();
-        updateBackground();
-    }
-
-    public int getPositionOfChild(ExpandableNotificationRow childRow) {
-        if (mIsSummaryWithChildren) {
-            return mChildrenContainer.getPositionInLinearLayout(childRow);
-        }
-        return 0;
-    }
-
-    public void setExpansionLogger(ExpansionLogger logger, String key) {
-        mLogger = logger;
-        mLoggingKey = key;
-    }
-
-    public void onExpandedByGesture(boolean userExpanded) {
-        int event = MetricsEvent.ACTION_NOTIFICATION_GESTURE_EXPANDER;
-        if (mGroupManager.isSummaryOfGroup(getStatusBarNotification())) {
-            event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER;
-        }
-        MetricsLogger.action(mContext, event, userExpanded);
-    }
-
-    @Override
-    public float getIncreasedPaddingAmount() {
-        if (mIsSummaryWithChildren) {
-            if (isGroupExpanded()) {
-                return 1.0f;
-            } else if (isUserLocked()) {
-                return mChildrenContainer.getIncreasedPaddingAmount();
-            }
-        } else if (isColorized() && (!mIsLowPriority || isExpanded())) {
-            return -1.0f;
-        }
-        return 0.0f;
-    }
-
-    private boolean isColorized() {
-        return mIsColorized && mBgTint != NO_COLOR;
-    }
-
-    @Override
-    protected boolean disallowSingleClick(MotionEvent event) {
-        if (areGutsExposed()) {
-            return false;
-        }
-        float x = event.getX();
-        float y = event.getY();
-        NotificationHeaderView header = getVisibleNotificationHeader();
-        if (header != null && header.isInTouchRect(x - getTranslation(), y)) {
-            return true;
-        }
-        if ((!mIsSummaryWithChildren || shouldShowPublic())
-                && getShowingLayout().disallowSingleClick(x, y)) {
-            return true;
-        }
-        return super.disallowSingleClick(event);
-    }
-
-    private void onExpansionChanged(boolean userAction, boolean wasExpanded) {
-        boolean nowExpanded = isExpanded();
-        if (mIsSummaryWithChildren && (!mIsLowPriority || wasExpanded)) {
-            nowExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
-        }
-        if (nowExpanded != wasExpanded) {
-            updateShelfIconColor();
-            if (mLogger != null) {
-                mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded);
-            }
-            if (mIsSummaryWithChildren) {
-                mChildrenContainer.onExpansionChanged();
-            }
-        }
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
-        if (canViewBeDismissed()) {
-            info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
-        }
-        boolean expandable = shouldShowPublic();
-        boolean isExpanded = false;
-        if (!expandable) {
-            if (mIsSummaryWithChildren) {
-                expandable = true;
-                if (!mIsLowPriority || isExpanded()) {
-                    isExpanded = isGroupExpanded();
-                }
-            } else {
-                expandable = mPrivateLayout.isContentExpandable();
-                isExpanded = isExpanded();
-            }
-        }
-        if (expandable) {
-            if (isExpanded) {
-                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
-            } else {
-                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
-            }
-        }
-        NotificationMenuRowPlugin provider = getProvider();
-        if (provider != null) {
-            MenuItem snoozeMenu = provider.getSnoozeMenuItem(getContext());
-            if (snoozeMenu != null) {
-                AccessibilityAction action = new AccessibilityAction(R.id.action_snooze,
-                    getContext().getResources()
-                        .getString(R.string.notification_menu_snooze_action));
-                info.addAction(action);
-            }
-        }
-    }
-
-    @Override
-    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
-        if (super.performAccessibilityActionInternal(action, arguments)) {
-            return true;
-        }
-        switch (action) {
-            case AccessibilityNodeInfo.ACTION_DISMISS:
-                performDismissWithBlockingHelper(true /* fromAccessibility */);
-                return true;
-            case AccessibilityNodeInfo.ACTION_COLLAPSE:
-            case AccessibilityNodeInfo.ACTION_EXPAND:
-                mExpandClickListener.onClick(this);
-                return true;
-            case AccessibilityNodeInfo.ACTION_LONG_CLICK:
-                doLongClickCallback();
-                return true;
-            case R.id.action_snooze:
-                NotificationMenuRowPlugin provider = getProvider();
-                if (provider == null) {
-                    provider = createMenu();
-                }
-                MenuItem snoozeMenu = provider.getSnoozeMenuItem(getContext());
-                if (snoozeMenu != null) {
-                    doLongClickCallback(getWidth() / 2, getHeight() / 2, snoozeMenu);
-                }
-                return true;
-        }
-        return false;
-    }
-
-    public boolean shouldRefocusOnDismiss() {
-        return mRefocusOnDismiss || isAccessibilityFocused();
-    }
-
-    public interface OnExpandClickListener {
-        void onExpandClicked(NotificationData.Entry clickedEntry, boolean nowExpanded);
-    }
-
-    @Override
-    public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
-        mNotificationViewState = new NotificationViewState(stackScrollState);
-        return mNotificationViewState;
-    }
-
-    public NotificationViewState getViewState() {
-        return mNotificationViewState;
-    }
-
-    @Override
-    public boolean isAboveShelf() {
-        return !isOnKeyguard()
-                && (mIsPinned || mHeadsupDisappearRunning || (mIsHeadsUp && mAboveShelf)
-                || mExpandAnimationRunning || mChildIsExpanding);
-    }
-
-    public void setShowAmbient(boolean showAmbient) {
-        if (showAmbient != mShowAmbient) {
-            mShowAmbient = showAmbient;
-            if (mChildrenContainer != null) {
-                mChildrenContainer.notifyShowAmbientChanged();
-            }
-            notifyHeightChanged(false /* needsAnimation */);
-        }
-    }
-
-    @Override
-    public boolean topAmountNeedsClipping() {
-        if (isGroupExpanded()) {
-            return true;
-        }
-        if (isGroupExpansionChanging()) {
-            return true;
-        }
-        if (getShowingLayout().shouldClipToRounding(true /* topRounded */,
-                false /* bottomRounded */)) {
-            return true;
-        }
-        if (mGuts != null && mGuts.getAlpha() != 0.0f) {
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    protected boolean childNeedsClipping(View child) {
-        if (child instanceof NotificationContentView) {
-            NotificationContentView contentView = (NotificationContentView) child;
-            if (isClippingNeeded()) {
-                return true;
-            } else if (!hasNoRounding()
-                    && contentView.shouldClipToRounding(getCurrentTopRoundness() != 0.0f,
-                    getCurrentBottomRoundness() != 0.0f)) {
-                return true;
-            }
-        } else if (child == mChildrenContainer) {
-            if (!mChildIsExpanding && (isClippingNeeded() || !hasNoRounding())) {
-                return true;
-            }
-        } else if (child instanceof NotificationGuts) {
-            return !hasNoRounding();
-        }
-        return super.childNeedsClipping(child);
-    }
-
-    @Override
-    protected void applyRoundness() {
-        super.applyRoundness();
-        applyChildrenRoundness();
-    }
-
-    private void applyChildrenRoundness() {
-        if (mIsSummaryWithChildren) {
-            mChildrenContainer.setCurrentBottomRoundness(getCurrentBottomRoundness());
-        }
-    }
-
-    @Override
-    public Path getCustomClipPath(View child) {
-        if (child instanceof NotificationGuts) {
-            return getClipPath(true /* ignoreTranslation */);
-        }
-        return super.getCustomClipPath(child);
-    }
-
-    private boolean hasNoRounding() {
-        return getCurrentBottomRoundness() == 0.0f && getCurrentTopRoundness() == 0.0f;
-    }
-
-    public boolean isShowingAmbient() {
-        return mShowAmbient;
-    }
-
-    public void setAboveShelf(boolean aboveShelf) {
-        boolean wasAboveShelf = isAboveShelf();
-        mAboveShelf = aboveShelf;
-        if (isAboveShelf() != wasAboveShelf) {
-            mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
-        }
-    }
-
-    public static class NotificationViewState extends ExpandableViewState {
-
-        private final StackScrollState mOverallState;
-
-
-        private NotificationViewState(StackScrollState stackScrollState) {
-            mOverallState = stackScrollState;
-        }
-
-        @Override
-        public void applyToView(View view) {
-            if (view instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-                if (row.isExpandAnimationRunning()) {
-                    return;
-                }
-                handleFixedTranslationZ(row);
-                super.applyToView(view);
-                row.applyChildrenState(mOverallState);
-            }
-        }
-
-        private void handleFixedTranslationZ(ExpandableNotificationRow row) {
-            if (row.hasExpandingChild()) {
-                zTranslation = row.getTranslationZ();
-                clipTopAmount = row.getClipTopAmount();
-            }
-        }
-
-        @Override
-        protected void onYTranslationAnimationFinished(View view) {
-            super.onYTranslationAnimationFinished(view);
-            if (view instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-                if (row.isHeadsUpAnimatingAway()) {
-                    row.setHeadsUpAnimatingAway(false);
-                }
-            }
-        }
-
-        @Override
-        public void animateTo(View child, AnimationProperties properties) {
-            if (child instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                if (row.isExpandAnimationRunning()) {
-                    return;
-                }
-                handleFixedTranslationZ(row);
-                super.animateTo(child, properties);
-                row.startChildAnimation(mOverallState, properties);
-            }
-        }
-    }
-
-    @VisibleForTesting
-    protected void setChildrenContainer(NotificationChildrenContainer childrenContainer) {
-        mChildrenContainer = childrenContainer;
-    }
-
-    @VisibleForTesting
-    protected void setPrivateLayout(NotificationContentView privateLayout) {
-        mPrivateLayout = privateLayout;
-    }
-
-    @VisibleForTesting
-    protected void setPublicLayout(NotificationContentView publicLayout) {
-        mPublicLayout = publicLayout;
-    }
-
-    /**
-     * Equivalent to View.OnLongClickListener with coordinates
-     */
-    public interface LongPressListener {
-        /**
-         * Equivalent to {@link View.OnLongClickListener#onLongClick(View)} with coordinates
-         * @return whether the longpress was handled
-         */
-        boolean onLongPress(View v, int x, int y, MenuItem item);
-    }
-
-    /**
-     * Equivalent to View.OnClickListener with coordinates
-     */
-    public interface OnAppOpsClickListener {
-        /**
-         * Equivalent to {@link View.OnClickListener#onClick(View)} with coordinates
-         * @return whether the click was handled
-         */
-        boolean onClick(View v, int x, int y, MenuItem item);
-    }
-
-    /**
-     * Background task for executing IPCs to check if the notification is a system notification. The
-     * output is used for both the blocking helper and the notification info.
-     */
-    private class SystemNotificationAsyncTask extends AsyncTask<Void, Void, Boolean> {
-
-        @Override
-        protected Boolean doInBackground(Void... voids) {
-            return isSystemNotification(mContext, mStatusBarNotification);
-        }
-
-        @Override
-        protected void onPostExecute(Boolean result) {
-            if (mEntry != null) {
-                mEntry.mIsSystemNotification = result;
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
deleted file mode 100644
index 584b637..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Outline;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewOutlineProvider;
-
-import com.android.settingslib.Utils;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
-import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.stack.AnimationProperties;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
-
-/**
- * Like {@link ExpandableView}, but setting an outline for the height and clipping.
- */
-public abstract class ExpandableOutlineView extends ExpandableView {
-
-    private static final AnimatableProperty TOP_ROUNDNESS = AnimatableProperty.from(
-            "topRoundness",
-            ExpandableOutlineView::setTopRoundnessInternal,
-            ExpandableOutlineView::getCurrentTopRoundness,
-            R.id.top_roundess_animator_tag,
-            R.id.top_roundess_animator_end_tag,
-            R.id.top_roundess_animator_start_tag);
-    private static final AnimatableProperty BOTTOM_ROUNDNESS = AnimatableProperty.from(
-            "bottomRoundness",
-            ExpandableOutlineView::setBottomRoundnessInternal,
-            ExpandableOutlineView::getCurrentBottomRoundness,
-            R.id.bottom_roundess_animator_tag,
-            R.id.bottom_roundess_animator_end_tag,
-            R.id.bottom_roundess_animator_start_tag);
-    private static final AnimationProperties ROUNDNESS_PROPERTIES =
-            new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-    private static final Path EMPTY_PATH = new Path();
-
-    private final Rect mOutlineRect = new Rect();
-    private final Path mClipPath = new Path();
-    private boolean mCustomOutline;
-    private float mOutlineAlpha = -1f;
-    protected float mOutlineRadius;
-    private boolean mAlwaysRoundBothCorners;
-    private Path mTmpPath = new Path();
-    private float mCurrentBottomRoundness;
-    private float mCurrentTopRoundness;
-    private float mBottomRoundness;
-    private float mTopRoundness;
-    private int mBackgroundTop;
-
-    /**
-     * {@code true} if the children views of the {@link ExpandableOutlineView} are translated when
-     * it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
-     */
-    protected boolean mShouldTranslateContents;
-    private boolean mTopAmountRounded;
-    private float mDistanceToTopRoundness = -1;
-    private float mExtraWidthForClipping;
-    private int mMinimumHeightForClipping = 0;
-
-    private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
-        @Override
-        public void getOutline(View view, Outline outline) {
-            if (!mCustomOutline && mCurrentTopRoundness == 0.0f
-                    && mCurrentBottomRoundness == 0.0f && !mAlwaysRoundBothCorners
-                    && !mTopAmountRounded) {
-                int translation = mShouldTranslateContents ? (int) getTranslation() : 0;
-                int left = Math.max(translation, 0);
-                int top = mClipTopAmount + mBackgroundTop;
-                int right = getWidth() + Math.min(translation, 0);
-                int bottom = Math.max(getActualHeight() - mClipBottomAmount, top);
-                outline.setRect(left, top, right, bottom);
-            } else {
-                Path clipPath = getClipPath(false /* ignoreTranslation */);
-                if (clipPath != null && clipPath.isConvex()) {
-                    // The path might not be convex in border cases where the view is small and
-                    // clipped
-                    outline.setConvexPath(clipPath);
-                }
-            }
-            outline.setAlpha(mOutlineAlpha);
-        }
-    };
-
-    protected Path getClipPath(boolean ignoreTranslation) {
-        int left;
-        int top;
-        int right;
-        int bottom;
-        int height;
-        float topRoundness = mAlwaysRoundBothCorners
-                ? mOutlineRadius : getCurrentBackgroundRadiusTop();
-        if (!mCustomOutline) {
-            int translation = mShouldTranslateContents && !ignoreTranslation
-                    ? (int) getTranslation() : 0;
-            left = Math.max(translation, 0);
-            top = mClipTopAmount + mBackgroundTop;
-            right = getWidth() + Math.min(translation, 0);
-            // If the top is rounded we want the bottom to be at most at the top roundness, in order
-            // to avoid the shadow changing when scrolling up.
-            bottom = Math.max(getActualHeight() - mClipBottomAmount, (int) (top + topRoundness));
-        } else {
-            left = mOutlineRect.left;
-            top = mOutlineRect.top;
-            right = mOutlineRect.right;
-            bottom = mOutlineRect.bottom;
-        }
-        height = bottom - top;
-        if (height == 0) {
-            return EMPTY_PATH;
-        }
-        float bottomRoundness = mAlwaysRoundBothCorners
-                ? mOutlineRadius : getCurrentBackgroundRadiusBottom();
-        if (topRoundness + bottomRoundness > height) {
-            float overShoot = topRoundness + bottomRoundness - height;
-            topRoundness -= overShoot * mCurrentTopRoundness
-                    / (mCurrentTopRoundness + mCurrentBottomRoundness);
-            bottomRoundness -= overShoot * mCurrentBottomRoundness
-                    / (mCurrentTopRoundness + mCurrentBottomRoundness);
-        }
-        getRoundedRectPath(left, top, right, bottom, topRoundness,
-                bottomRoundness, mTmpPath);
-        return mTmpPath;
-    }
-
-    public static void getRoundedRectPath(int left, int top, int right, int bottom,
-            float topRoundness, float bottomRoundness, Path outPath) {
-        outPath.reset();
-        int width = right - left;
-        float topRoundnessX = topRoundness;
-        float bottomRoundnessX = bottomRoundness;
-        topRoundnessX = Math.min(width / 2, topRoundnessX);
-        bottomRoundnessX = Math.min(width / 2, bottomRoundnessX);
-        if (topRoundness > 0.0f) {
-            outPath.moveTo(left, top + topRoundness);
-            outPath.quadTo(left, top, left + topRoundnessX, top);
-            outPath.lineTo(right - topRoundnessX, top);
-            outPath.quadTo(right, top, right, top + topRoundness);
-        } else {
-            outPath.moveTo(left, top);
-            outPath.lineTo(right, top);
-        }
-        if (bottomRoundness > 0.0f) {
-            outPath.lineTo(right, bottom - bottomRoundness);
-            outPath.quadTo(right, bottom, right - bottomRoundnessX, bottom);
-            outPath.lineTo(left + bottomRoundnessX, bottom);
-            outPath.quadTo(left, bottom, left, bottom - bottomRoundness);
-        } else {
-            outPath.lineTo(right, bottom);
-            outPath.lineTo(left, bottom);
-        }
-        outPath.close();
-    }
-
-    public ExpandableOutlineView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setOutlineProvider(mProvider);
-        initDimens();
-    }
-
-    @Override
-    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
-        canvas.save();
-        Path intersectPath = null;
-        if (mTopAmountRounded && topAmountNeedsClipping()) {
-            int left = (int) (- mExtraWidthForClipping / 2.0f);
-            int top = (int) (mClipTopAmount - mDistanceToTopRoundness);
-            int right = getWidth() + (int) (mExtraWidthForClipping + left);
-            int bottom = (int) Math.max(mMinimumHeightForClipping,
-                    Math.max(getActualHeight() - mClipBottomAmount, top + mOutlineRadius));
-            ExpandableOutlineView.getRoundedRectPath(left, top, right, bottom, mOutlineRadius,
-                    0.0f,
-                    mClipPath);
-            intersectPath = mClipPath;
-        }
-        boolean clipped = false;
-        if (childNeedsClipping(child)) {
-            Path clipPath = getCustomClipPath(child);
-            if (clipPath == null) {
-                clipPath = getClipPath(false /* ignoreTranslation */);
-            }
-            if (clipPath != null) {
-                if (intersectPath != null) {
-                    clipPath.op(intersectPath, Path.Op.INTERSECT);
-                }
-                canvas.clipPath(clipPath);
-                clipped = true;
-            }
-        }
-        if (!clipped && intersectPath != null) {
-            canvas.clipPath(intersectPath);
-        }
-        boolean result = super.drawChild(canvas, child, drawingTime);
-        canvas.restore();
-        return result;
-    }
-
-    public void setExtraWidthForClipping(float extraWidthForClipping) {
-        mExtraWidthForClipping = extraWidthForClipping;
-    }
-
-    public void setMinimumHeightForClipping(int minimumHeightForClipping) {
-        mMinimumHeightForClipping = minimumHeightForClipping;
-    }
-
-    @Override
-    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
-        super.setDistanceToTopRoundness(distanceToTopRoundness);
-        if (distanceToTopRoundness != mDistanceToTopRoundness) {
-            mTopAmountRounded = distanceToTopRoundness >= 0;
-            mDistanceToTopRoundness = distanceToTopRoundness;
-            applyRoundness();
-        }
-    }
-
-    protected boolean childNeedsClipping(View child) {
-        return false;
-    }
-
-    public boolean topAmountNeedsClipping() {
-        return true;
-    }
-
-    protected boolean isClippingNeeded() {
-        return mAlwaysRoundBothCorners || mCustomOutline || getTranslation() != 0 ;
-    }
-
-    private void initDimens() {
-        Resources res = getResources();
-        mShouldTranslateContents =
-                res.getBoolean(R.bool.config_translateNotificationContentsOnSwipe);
-        mOutlineRadius = res.getDimension(R.dimen.notification_shadow_radius);
-        mAlwaysRoundBothCorners = res.getBoolean(R.bool.config_clipNotificationsToOutline);
-        if (!mAlwaysRoundBothCorners) {
-            mOutlineRadius = res.getDimensionPixelSize(
-                    Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius));
-        }
-        setClipToOutline(mAlwaysRoundBothCorners);
-    }
-
-    /**
-     * Set the topRoundness of this view.
-     * @return Whether the roundness was changed.
-     */
-    public boolean setTopRoundness(float topRoundness, boolean animate) {
-        if (mTopRoundness != topRoundness) {
-            mTopRoundness = topRoundness;
-            PropertyAnimator.setProperty(this, TOP_ROUNDNESS, topRoundness,
-                    ROUNDNESS_PROPERTIES, animate);
-            return true;
-        }
-        return false;
-    }
-
-    protected void applyRoundness() {
-        invalidateOutline();
-        invalidate();
-    }
-
-    public float getCurrentBackgroundRadiusTop() {
-        // If this view is top amount notification view, it should always has round corners on top.
-        // It will be applied with applyRoundness()
-        if (mTopAmountRounded) {
-            return mOutlineRadius;
-        }
-        return mCurrentTopRoundness * mOutlineRadius;
-    }
-
-    public float getCurrentTopRoundness() {
-        return mCurrentTopRoundness;
-    }
-
-    public float getCurrentBottomRoundness() {
-        return mCurrentBottomRoundness;
-    }
-
-    protected float getCurrentBackgroundRadiusBottom() {
-        return mCurrentBottomRoundness * mOutlineRadius;
-    }
-
-    /**
-     * Set the bottom roundness of this view.
-     * @return Whether the roundness was changed.
-     */
-    public boolean setBottomRoundness(float bottomRoundness, boolean animate) {
-        if (mBottomRoundness != bottomRoundness) {
-            mBottomRoundness = bottomRoundness;
-            PropertyAnimator.setProperty(this, BOTTOM_ROUNDNESS, bottomRoundness,
-                    ROUNDNESS_PROPERTIES, animate);
-            return true;
-        }
-        return false;
-    }
-
-    protected void setBackgroundTop(int backgroundTop) {
-        if (mBackgroundTop != backgroundTop) {
-            mBackgroundTop = backgroundTop;
-            invalidateOutline();
-        }
-    }
-
-    private void setTopRoundnessInternal(float topRoundness) {
-        mCurrentTopRoundness = topRoundness;
-        applyRoundness();
-    }
-
-    private void setBottomRoundnessInternal(float bottomRoundness) {
-        mCurrentBottomRoundness = bottomRoundness;
-        applyRoundness();
-    }
-
-    public void onDensityOrFontScaleChanged() {
-        initDimens();
-        applyRoundness();
-    }
-
-    @Override
-    public void setActualHeight(int actualHeight, boolean notifyListeners) {
-        int previousHeight = getActualHeight();
-        super.setActualHeight(actualHeight, notifyListeners);
-        if (previousHeight != actualHeight) {
-            applyRoundness();
-        }
-    }
-
-    @Override
-    public void setClipTopAmount(int clipTopAmount) {
-        int previousAmount = getClipTopAmount();
-        super.setClipTopAmount(clipTopAmount);
-        if (previousAmount != clipTopAmount) {
-            applyRoundness();
-        }
-    }
-
-    @Override
-    public void setClipBottomAmount(int clipBottomAmount) {
-        int previousAmount = getClipBottomAmount();
-        super.setClipBottomAmount(clipBottomAmount);
-        if (previousAmount != clipBottomAmount) {
-            applyRoundness();
-        }
-    }
-
-    protected void setOutlineAlpha(float alpha) {
-        if (alpha != mOutlineAlpha) {
-            mOutlineAlpha = alpha;
-            applyRoundness();
-        }
-    }
-
-    @Override
-    public float getOutlineAlpha() {
-        return mOutlineAlpha;
-    }
-
-    protected void setOutlineRect(RectF rect) {
-        if (rect != null) {
-            setOutlineRect(rect.left, rect.top, rect.right, rect.bottom);
-        } else {
-            mCustomOutline = false;
-            applyRoundness();
-        }
-    }
-
-    @Override
-    public int getOutlineTranslation() {
-        return mCustomOutline ? mOutlineRect.left : (int) getTranslation();
-    }
-
-    public void updateOutline() {
-        if (mCustomOutline) {
-            return;
-        }
-        boolean hasOutline = needsOutline();
-        setOutlineProvider(hasOutline ? mProvider : null);
-    }
-
-    /**
-     * @return Whether the view currently needs an outline. This is usually {@code false} in case
-     * it doesn't have a background.
-     */
-    protected boolean needsOutline() {
-        if (isChildInGroup()) {
-            return isGroupExpanded() && !isGroupExpansionChanging();
-        } else if (isSummaryWithChildren()) {
-            return !isGroupExpanded() || isGroupExpansionChanging();
-        }
-        return true;
-    }
-
-    public boolean isOutlineShowing() {
-        ViewOutlineProvider op = getOutlineProvider();
-        return op != null;
-    }
-
-    protected void setOutlineRect(float left, float top, float right, float bottom) {
-        mCustomOutline = true;
-
-        mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom);
-
-        // Outlines need to be at least 1 dp
-        mOutlineRect.bottom = (int) Math.max(top, mOutlineRect.bottom);
-        mOutlineRect.right = (int) Math.max(left, mOutlineRect.right);
-        applyRoundness();
-    }
-
-    public Path getCustomClipPath(View child) {
-        return null;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
deleted file mode 100644
index ae8d844..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.animation.AnimatorListenerAdapter;
-import android.content.Context;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import com.android.systemui.statusbar.stack.ExpandableViewState;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.StackScrollState;
-
-import java.util.ArrayList;
-
-/**
- * An abstract view for expandable views.
- */
-public abstract class ExpandableView extends FrameLayout {
-
-    public static final float NO_ROUNDNESS = -1;
-    protected OnHeightChangedListener mOnHeightChangedListener;
-    private int mActualHeight;
-    protected int mClipTopAmount;
-    protected int mClipBottomAmount;
-    private boolean mDark;
-    private ArrayList<View> mMatchParentViews = new ArrayList<View>();
-    private static Rect mClipRect = new Rect();
-    private boolean mWillBeGone;
-    private int mMinClipTopAmount = 0;
-    private boolean mClipToActualHeight = true;
-    private boolean mChangingPosition = false;
-    private ViewGroup mTransientContainer;
-    private boolean mInShelf;
-    private boolean mTransformingInShelf;
-
-    public ExpandableView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int givenSize = MeasureSpec.getSize(heightMeasureSpec);
-        final int viewHorizontalPadding = getPaddingStart() + getPaddingEnd();
-        int ownMaxHeight = Integer.MAX_VALUE;
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        if (heightMode != MeasureSpec.UNSPECIFIED && givenSize != 0) {
-            ownMaxHeight = Math.min(givenSize, ownMaxHeight);
-        }
-        int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
-        int maxChildHeight = 0;
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child.getVisibility() == GONE) {
-                continue;
-            }
-            int childHeightSpec = newHeightSpec;
-            ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
-            if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) {
-                if (layoutParams.height >= 0) {
-                    // An actual height is set
-                    childHeightSpec = layoutParams.height > ownMaxHeight
-                        ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY)
-                        : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
-                }
-                child.measure(getChildMeasureSpec(
-                        widthMeasureSpec, viewHorizontalPadding, layoutParams.width),
-                        childHeightSpec);
-                int childHeight = child.getMeasuredHeight();
-                maxChildHeight = Math.max(maxChildHeight, childHeight);
-            } else {
-                mMatchParentViews.add(child);
-            }
-        }
-        int ownHeight = heightMode == MeasureSpec.EXACTLY
-                ? givenSize : Math.min(ownMaxHeight, maxChildHeight);
-        newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
-        for (View child : mMatchParentViews) {
-            child.measure(getChildMeasureSpec(
-                    widthMeasureSpec, viewHorizontalPadding, child.getLayoutParams().width),
-                    newHeightSpec);
-        }
-        mMatchParentViews.clear();
-        int width = MeasureSpec.getSize(widthMeasureSpec);
-        setMeasuredDimension(width, ownHeight);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        updateClipping();
-    }
-
-    @Override
-    public boolean pointInView(float localX, float localY, float slop) {
-        float top = mClipTopAmount;
-        float bottom = mActualHeight;
-        return localX >= -slop && localY >= top - slop && localX < ((mRight - mLeft) + slop) &&
-                localY < (bottom + slop);
-    }
-
-    /**
-     * Sets the actual height of this notification. This is different than the laid out
-     * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
-     *
-     * @param actualHeight The height of this notification.
-     * @param notifyListeners Whether the listener should be informed about the change.
-     */
-    public void setActualHeight(int actualHeight, boolean notifyListeners) {
-        mActualHeight = actualHeight;
-        updateClipping();
-        if (notifyListeners) {
-            notifyHeightChanged(false  /* needsAnimation */);
-        }
-    }
-
-    /**
-     * Set the distance to the top roundness, from where we should start clipping a value above
-     * or equal to 0 is the effective distance, and if a value below 0 is received, there should
-     * be no clipping.
-     */
-    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
-    }
-
-    public void setActualHeight(int actualHeight) {
-        setActualHeight(actualHeight, true /* notifyListeners */);
-    }
-
-    /**
-     * See {@link #setActualHeight}.
-     *
-     * @return The current actual height of this notification.
-     */
-    public int getActualHeight() {
-        return mActualHeight;
-    }
-
-    public boolean isExpandAnimationRunning() {
-        return false;
-    }
-
-    /**
-     * @return The maximum height of this notification.
-     */
-    public int getMaxContentHeight() {
-        return getHeight();
-    }
-
-    /**
-     * @return The minimum content height of this notification. This also respects the temporary
-     * states of the view.
-     */
-    public int getMinHeight() {
-        return getMinHeight(false /* ignoreTemporaryStates */);
-    }
-
-    /**
-     * Get the minimum height of this view.
-     *
-     * @param ignoreTemporaryStates should temporary states be ignored like the guts or heads-up.
-     *
-     * @return The minimum height that this view needs.
-     */
-    public int getMinHeight(boolean ignoreTemporaryStates) {
-        return getHeight();
-    }
-
-    /**
-     * @return The collapsed height of this view. Note that this might be different
-     * than {@link #getMinHeight()} because some elements like groups may have different sizes when
-     * they are system expanded.
-     */
-    public int getCollapsedHeight() {
-        return getHeight();
-    }
-
-    /**
-     * Sets the notification as dimmed. The default implementation does nothing.
-     *
-     * @param dimmed Whether the notification should be dimmed.
-     * @param fade Whether an animation should be played to change the state.
-     */
-    public void setDimmed(boolean dimmed, boolean fade) {
-    }
-
-    /**
-     * Sets the notification as dark. The default implementation does nothing.
-     *
-     * @param dark Whether the notification should be dark.
-     * @param fade Whether an animation should be played to change the state.
-     * @param delay If fading, the delay of the animation.
-     */
-    public void setDark(boolean dark, boolean fade, long delay) {
-        mDark = dark;
-    }
-
-    public boolean isDark() {
-        return mDark;
-    }
-
-    public boolean isRemoved() {
-        return false;
-    }
-
-    /**
-     * See {@link #setHideSensitive}. This is a variant which notifies this view in advance about
-     * the upcoming state of hiding sensitive notifications. It gets called at the very beginning
-     * of a stack scroller update such that the updated intrinsic height (which is dependent on
-     * whether private or public layout is showing) gets taken into account into all layout
-     * calculations.
-     */
-    public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
-    }
-
-    /**
-     * Sets whether the notification should hide its private contents if it is sensitive.
-     */
-    public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
-            long duration) {
-    }
-
-    /**
-     * @return The desired notification height.
-     */
-    public int getIntrinsicHeight() {
-        return getHeight();
-    }
-
-    /**
-     * Sets the amount this view should be clipped from the top. This is used when an expanded
-     * notification is scrolling in the top or bottom stack.
-     *
-     * @param clipTopAmount The amount of pixels this view should be clipped from top.
-     */
-    public void setClipTopAmount(int clipTopAmount) {
-        mClipTopAmount = clipTopAmount;
-        updateClipping();
-    }
-
-    /**
-     * Set the amount the the notification is clipped on the bottom in addition to the regular
-     * clipping. This is mainly used to clip something in a non-animated way without changing the
-     * actual height of the notification and is purely visual.
-     *
-     * @param clipBottomAmount the amount to clip.
-     */
-    public void setClipBottomAmount(int clipBottomAmount) {
-        mClipBottomAmount = clipBottomAmount;
-        updateClipping();
-    }
-
-    public int getClipTopAmount() {
-        return mClipTopAmount;
-    }
-
-    public int getClipBottomAmount() {
-        return mClipBottomAmount;
-    }
-
-    public void setOnHeightChangedListener(OnHeightChangedListener listener) {
-        mOnHeightChangedListener = listener;
-    }
-
-    /**
-     * @return Whether we can expand this views content.
-     */
-    public boolean isContentExpandable() {
-        return false;
-    }
-
-    public void notifyHeightChanged(boolean needsAnimation) {
-        if (mOnHeightChangedListener != null) {
-            mOnHeightChangedListener.onHeightChanged(this, needsAnimation);
-        }
-    }
-
-    public boolean isTransparent() {
-        return false;
-    }
-
-    /**
-     * Perform a remove animation on this view.
-     * @param duration The duration of the remove animation.
-     * @param delay The delay of the animation
-     * @param translationDirection The direction value from [-1 ... 1] indicating in which the
- *                             animation should be performed. A value of -1 means that The
- *                             remove animation should be performed upwards,
- *                             such that the  child appears to be going away to the top. 1
- *                             Should mean the opposite.
-     * @param isHeadsUpAnimation Is this a headsUp animation.
-     * @param endLocation The location where the horizonal heads up disappear animation should end.
-     * @param onFinishedRunnable A runnable which should be run when the animation is finished.
-     * @param animationListener An animation listener to add to the animation.
-     */
-    public abstract void performRemoveAnimation(long duration,
-            long delay, float translationDirection, boolean isHeadsUpAnimation, float endLocation,
-            Runnable onFinishedRunnable,
-            AnimatorListenerAdapter animationListener);
-
-    public abstract void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear);
-
-    /**
-     * Set the notification appearance to be below the speed bump.
-     * @param below true if it is below.
-     */
-    public void setBelowSpeedBump(boolean below) {
-    }
-
-    public int getPinnedHeadsUpHeight() {
-        return getIntrinsicHeight();
-    }
-
-
-    /**
-     * Sets the translation of the view.
-     */
-    public void setTranslation(float translation) {
-        setTranslationX(translation);
-    }
-
-    /**
-     * Gets the translation of the view.
-     */
-    public float getTranslation() {
-        return getTranslationX();
-    }
-
-    public void onHeightReset() {
-        if (mOnHeightChangedListener != null) {
-            mOnHeightChangedListener.onReset(this);
-        }
-    }
-
-    /**
-     * This method returns the drawing rect for the view which is different from the regular
-     * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at
-     * position 0 and usually the translation is neglected. Since we are manually clipping this
-     * view,we also need to subtract the clipTopAmount from the top. This is needed in order to
-     * ensure that accessibility and focusing work correctly.
-     *
-     * @param outRect The (scrolled) drawing bounds of the view.
-     */
-    @Override
-    public void getDrawingRect(Rect outRect) {
-        super.getDrawingRect(outRect);
-        outRect.left += getTranslationX();
-        outRect.right += getTranslationX();
-        outRect.bottom = (int) (outRect.top + getTranslationY() + getActualHeight());
-        outRect.top += getTranslationY() + getClipTopAmount();
-    }
-
-    @Override
-    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
-        super.getBoundsOnScreen(outRect, clipToParent);
-        if (getTop() + getTranslationY() < 0) {
-            // We got clipped to the parent here - make sure we undo that.
-            outRect.top += getTop() + getTranslationY();
-        }
-        outRect.bottom = outRect.top + getActualHeight();
-        outRect.top += getClipTopAmount();
-    }
-
-    public boolean isSummaryWithChildren() {
-        return false;
-    }
-
-    public boolean areChildrenExpanded() {
-        return false;
-    }
-
-    protected void updateClipping() {
-        if (mClipToActualHeight && shouldClipToActualHeight()) {
-            int top = getClipTopAmount();
-            mClipRect.set(0, top, getWidth(), Math.max(getActualHeight() + getExtraBottomPadding()
-                    - mClipBottomAmount, top));
-            setClipBounds(mClipRect);
-        } else {
-            setClipBounds(null);
-        }
-    }
-
-    public float getHeaderVisibleAmount() {
-        return 1.0f;
-    }
-
-    protected boolean shouldClipToActualHeight() {
-        return true;
-    }
-
-    public void setClipToActualHeight(boolean clipToActualHeight) {
-        mClipToActualHeight = clipToActualHeight;
-        updateClipping();
-    }
-
-    public boolean willBeGone() {
-        return mWillBeGone;
-    }
-
-    public void setWillBeGone(boolean willBeGone) {
-        mWillBeGone = willBeGone;
-    }
-
-    public int getMinClipTopAmount() {
-        return mMinClipTopAmount;
-    }
-
-    public void setMinClipTopAmount(int minClipTopAmount) {
-        mMinClipTopAmount = minClipTopAmount;
-    }
-
-    @Override
-    public void setLayerType(int layerType, Paint paint) {
-        if (hasOverlappingRendering()) {
-            super.setLayerType(layerType, paint);
-        }
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        // Otherwise it will be clipped
-        return super.hasOverlappingRendering() && getActualHeight() <= getHeight();
-    }
-
-    public float getShadowAlpha() {
-        return 0.0f;
-    }
-
-    public void setShadowAlpha(float shadowAlpha) {
-    }
-
-    /**
-     * @return an amount between -1 and 1 of increased padding that this child needs. 1 means it
-     * needs a full increased padding while -1 means it needs no padding at all. For 0.0f the normal
-     * padding is applied.
-     */
-    public float getIncreasedPaddingAmount() {
-        return 0.0f;
-    }
-
-    public boolean mustStayOnScreen() {
-        return false;
-    }
-
-    public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
-            int outlineTranslation) {
-    }
-
-    public float getOutlineAlpha() {
-        return 0.0f;
-    }
-
-    public int getOutlineTranslation() {
-        return 0;
-    }
-
-    public void setChangingPosition(boolean changingPosition) {
-        mChangingPosition = changingPosition;
-    }
-
-    public boolean isChangingPosition() {
-        return mChangingPosition;
-    }
-
-    public void setTransientContainer(ViewGroup transientContainer) {
-        mTransientContainer = transientContainer;
-    }
-
-    public ViewGroup getTransientContainer() {
-        return mTransientContainer;
-    }
-
-    /**
-     * @return padding used to alter how much of the view is clipped.
-     */
-    public int getExtraBottomPadding() {
-        return 0;
-    }
-
-    /**
-     * @return true if the group's expansion state is changing, false otherwise.
-     */
-    public boolean isGroupExpansionChanging() {
-        return false;
-    }
-
-    public boolean isGroupExpanded() {
-        return false;
-    }
-
-    public void setHeadsUpIsVisible() {
-    }
-
-    public boolean isChildInGroup() {
-        return false;
-    }
-
-    public void setActualHeightAnimating(boolean animating) {}
-
-    public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
-        return new ExpandableViewState();
-    }
-
-    /**
-     * @return whether the current view doesn't add height to the overall content. This means that
-     * if it is added to a list of items, it's content will still have the same height.
-     * An example is the notification shelf, that is always placed on top of another view.
-     */
-    public boolean hasNoContentHeight() {
-        return false;
-    }
-
-    /**
-     * @param inShelf whether the view is currently fully in the notification shelf.
-     */
-    public void setInShelf(boolean inShelf) {
-        mInShelf = inShelf;
-    }
-
-    public boolean isInShelf() {
-        return mInShelf;
-    }
-
-    /**
-     * @param transformingInShelf whether the view is currently transforming into the shelf in an
-     *                            animated way
-     */
-    public void setTransformingInShelf(boolean transformingInShelf) {
-        mTransformingInShelf = transformingInShelf;
-    }
-
-    public boolean isTransformingIntoShelf() {
-        return mTransformingInShelf;
-    }
-
-    public boolean isAboveShelf() {
-        return false;
-    }
-
-    public boolean hasExpandingChild() {
-        return false;
-    }
-
-    /**
-     * A listener notifying when {@link #getActualHeight} changes.
-     */
-    public interface OnHeightChangedListener {
-
-        /**
-         * @param view the view for which the height changed, or {@code null} if just the top
-         *             padding or the padding between the elements changed
-         * @param needsAnimation whether the view height needs to be animated
-         */
-        void onHeightChanged(ExpandableView view, boolean needsAnimation);
-
-        /**
-         * Called when the view is reset and therefore the height will change abruptly
-         *
-         * @param view The view which was reset.
-         */
-        void onReset(ExpandableView view);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/FooterView.java
deleted file mode 100644
index dc5bb9a..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FooterView.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.annotation.ColorInt;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.util.AttributeSet;
-import android.view.View;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.stack.ExpandableViewState;
-import com.android.systemui.statusbar.stack.StackScrollState;
-
-public class FooterView extends StackScrollerDecorView {
-    private final int mClearAllTopPadding;
-    private FooterViewButton mDismissButton;
-    private FooterViewButton mManageButton;
-
-    public FooterView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mClearAllTopPadding = context.getResources().getDimensionPixelSize(
-                R.dimen.clear_all_padding_top);
-    }
-
-    @Override
-    protected View findContentView() {
-        return findViewById(R.id.content);
-    }
-
-    protected View findSecondaryView() {
-        return findViewById(R.id.dismiss_text);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mDismissButton = (FooterViewButton) findSecondaryView();
-        mManageButton = findViewById(R.id.manage_text);
-    }
-
-    public void setTextColor(@ColorInt int color) {
-        mManageButton.setTextColor(color);
-        mDismissButton.setTextColor(color);
-    }
-
-    public void setManageButtonClickListener(OnClickListener listener) {
-        mManageButton.setOnClickListener(listener);
-    }
-
-    public void setDismissButtonClickListener(OnClickListener listener) {
-        mDismissButton.setOnClickListener(listener);
-    }
-
-    public boolean isOnEmptySpace(float touchX, float touchY) {
-        return touchX < mContent.getX()
-                || touchX > mContent.getX() + mContent.getWidth()
-                || touchY < mContent.getY()
-                || touchY > mContent.getY() + mContent.getHeight();
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        mDismissButton.setText(R.string.clear_all_notifications_text);
-        mDismissButton.setContentDescription(
-                mContext.getString(R.string.accessibility_clear_all));
-        mManageButton.setText(R.string.manage_notifications_text);
-    }
-
-    public boolean isButtonVisible() {
-        return mManageButton.getAlpha() != 0.0f;
-    }
-
-    @Override
-    public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
-        return new FooterViewState();
-    }
-
-    public class FooterViewState extends ExpandableViewState {
-        @Override
-        public void applyToView(View view) {
-            super.applyToView(view);
-            if (view instanceof FooterView) {
-                FooterView footerView = (FooterView) view;
-                boolean visible = this.clipTopAmount < mClearAllTopPadding;
-                footerView.setContentVisible(visible && footerView.isVisible());
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FooterViewButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/FooterViewButton.java
deleted file mode 100644
index 16ca0f2..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FooterViewButton.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.ViewGroup;
-
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-
-public class FooterViewButton extends AlphaOptimizedButton {
-
-    public FooterViewButton(Context context) {
-        this(context, null);
-    }
-
-    public FooterViewButton(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public FooterViewButton(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public FooterViewButton(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    /**
-     * This method returns the drawing rect for the view which is different from the regular
-     * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at
-     * position 0 and usually the translation is neglected. The standard implementation doesn't
-     * account for translation.
-     *
-     * @param outRect The (scrolled) drawing bounds of the view.
-     */
-    @Override
-    public void getDrawingRect(Rect outRect) {
-        super.getDrawingRect(outRect);
-        float translationX = ((ViewGroup) mParent).getTranslationX();
-        float translationY = ((ViewGroup) mParent).getTranslationY();
-        outRect.left += translationX;
-        outRect.right += translationX;
-        outRect.top += translationY;
-        outRect.bottom += translationY;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
index ac289d7..b39a96d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
@@ -24,7 +24,6 @@
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.util.AttributeSet;
-import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.View;
 import android.widget.TextView;
@@ -32,6 +31,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.keyguard.AlphaOptimizedLinearLayout;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 
 import java.util.List;
@@ -214,7 +214,7 @@
     }
 
     /** In order to do UI alignment, this view will be notified by
-     * {@link com.android.systemui.statusbar.stack.NotificationStackScrollLayout}.
+     * {@link com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout}.
      * After scroller laid out, the scroller will tell this view about scroller's getX()
      * @param translationX how to translate the horizontal position
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 294e2f4..551e8a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -364,22 +364,41 @@
                 R.integer.wired_charging_keyguard_text_animation_duration_up);
         int animateDownDuration = mContext.getResources().getInteger(
                 R.integer.wired_charging_keyguard_text_animation_duration_down);
+        textView.animate().cancel();
+        float translation = textView.getTranslationY();
         textView.animate()
                 .translationYBy(yTranslation)
                 .setInterpolator(Interpolators.LINEAR)
                 .setDuration(animateUpDuration)
                 .setListener(new AnimatorListenerAdapter() {
+                    private boolean mCancelled;
+
                     @Override
                     public void onAnimationStart(Animator animation) {
                         textView.switchIndication(indication);
                     }
+
+                    @Override
+                    public void onAnimationCancel(Animator animation) {
+                        textView.setTranslationY(translation);
+                        mCancelled = true;
+                    }
+
                     @Override
                     public void onAnimationEnd(Animator animation) {
+                        if (mCancelled) {
+                            return;
+                        }
                         textView.animate()
                                 .setDuration(animateDownDuration)
                                 .setInterpolator(Interpolators.BOUNCE)
-                                .translationYBy(-1 * yTranslation)
-                                .setListener(null);
+                                .translationY(translation)
+                                .setListener(new AnimatorListenerAdapter() {
+                                    @Override
+                                    public void onAnimationCancel(Animator animation) {
+                                        textView.setTranslationY(translation);
+                                    }
+                                });
                     }
                 });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
deleted file mode 100644
index 969e9d9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Canvas;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.RippleDrawable;
-import android.util.AttributeSet;
-import android.view.View;
-
-import com.android.internal.util.ArrayUtils;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-
-/**
- * A view that can be used for both the dimmed and normal background of an notification.
- */
-public class NotificationBackgroundView extends View {
-
-    private final boolean mDontModifyCorners;
-    private Drawable mBackground;
-    private int mClipTopAmount;
-    private int mActualHeight;
-    private int mClipBottomAmount;
-    private int mTintColor;
-    private float[] mCornerRadii = new float[8];
-    private boolean mBottomIsRounded;
-    private int mBackgroundTop;
-    private boolean mBottomAmountClips = true;
-    private boolean mExpandAnimationRunning;
-    private float mActualWidth;
-    private int mDrawableAlpha = 255;
-    private boolean mIsPressedAllowed;
-
-    private boolean mTopAmountRounded;
-    private float mDistanceToTopRoundness;
-
-    public NotificationBackgroundView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mDontModifyCorners = getResources().getBoolean(
-                R.bool.config_clipNotificationsToOutline);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        if (mClipTopAmount + mClipBottomAmount < mActualHeight - mBackgroundTop
-                || mExpandAnimationRunning) {
-            canvas.save();
-            if (!mExpandAnimationRunning) {
-                canvas.clipRect(0, mClipTopAmount, getWidth(), mActualHeight - mClipBottomAmount);
-            }
-            draw(canvas, mBackground);
-            canvas.restore();
-        }
-    }
-
-    private void draw(Canvas canvas, Drawable drawable) {
-        if (drawable != null) {
-            int top = mBackgroundTop;
-            int bottom = mActualHeight;
-            if (mBottomIsRounded && mBottomAmountClips && !mExpandAnimationRunning) {
-                bottom -= mClipBottomAmount;
-            }
-            int left = 0;
-            int right = getWidth();
-            if (mExpandAnimationRunning) {
-                left = (int) ((getWidth() - mActualWidth) / 2.0f);
-                right = (int) (left + mActualWidth);
-            }
-            if (mTopAmountRounded) {
-                int clipTop = (int) (mClipTopAmount - mDistanceToTopRoundness);
-                top += clipTop;
-                if (clipTop >= 0) {
-                    bottom += clipTop;
-                }
-            }
-            drawable.setBounds(left, top, right, bottom);
-            drawable.draw(canvas);
-        }
-    }
-
-    @Override
-    protected boolean verifyDrawable(Drawable who) {
-        return super.verifyDrawable(who) || who == mBackground;
-    }
-
-    @Override
-    protected void drawableStateChanged() {
-        setState(getDrawableState());
-    }
-
-    @Override
-    public void drawableHotspotChanged(float x, float y) {
-        if (mBackground != null) {
-            mBackground.setHotspot(x, y);
-        }
-    }
-
-    /**
-     * Sets a background drawable. As we need to change our bounds independently of layout, we need
-     * the notion of a background independently of the regular View background..
-     */
-    public void setCustomBackground(Drawable background) {
-        if (mBackground != null) {
-            mBackground.setCallback(null);
-            unscheduleDrawable(mBackground);
-        }
-        mBackground = background;
-        mBackground.mutate();
-        if (mBackground != null) {
-            mBackground.setCallback(this);
-            setTint(mTintColor);
-        }
-        if (mBackground instanceof RippleDrawable) {
-            ((RippleDrawable) mBackground).setForceSoftware(true);
-        }
-        updateBackgroundRadii();
-        invalidate();
-    }
-
-    public void setCustomBackground(int drawableResId) {
-        final Drawable d = mContext.getDrawable(drawableResId);
-        setCustomBackground(d);
-    }
-
-    public void setTint(int tintColor) {
-        if (tintColor != 0) {
-            mBackground.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
-        } else {
-            mBackground.clearColorFilter();
-        }
-        mTintColor = tintColor;
-        invalidate();
-    }
-
-    public void setActualHeight(int actualHeight) {
-        if (mExpandAnimationRunning) {
-            return;
-        }
-        mActualHeight = actualHeight;
-        invalidate();
-    }
-
-    public int getActualHeight() {
-        return mActualHeight;
-    }
-
-    public void setClipTopAmount(int clipTopAmount) {
-        mClipTopAmount = clipTopAmount;
-        invalidate();
-    }
-
-    public void setClipBottomAmount(int clipBottomAmount) {
-        mClipBottomAmount = clipBottomAmount;
-        invalidate();
-    }
-
-    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
-        if (distanceToTopRoundness != mDistanceToTopRoundness) {
-            mTopAmountRounded = distanceToTopRoundness >= 0;
-            mDistanceToTopRoundness = distanceToTopRoundness;
-            invalidate();
-        }
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-
-        // Prevents this view from creating a layer when alpha is animating.
-        return false;
-    }
-
-    public void setState(int[] drawableState) {
-        if (mBackground != null && mBackground.isStateful()) {
-            if (!mIsPressedAllowed) {
-                drawableState = ArrayUtils.removeInt(drawableState,
-                        com.android.internal.R.attr.state_pressed);
-            }
-            mBackground.setState(drawableState);
-        }
-    }
-
-    public void setRippleColor(int color) {
-        if (mBackground instanceof RippleDrawable) {
-            RippleDrawable ripple = (RippleDrawable) mBackground;
-            ripple.setColor(ColorStateList.valueOf(color));
-        }
-    }
-
-    public void setDrawableAlpha(int drawableAlpha) {
-        mDrawableAlpha = drawableAlpha;
-        if (mExpandAnimationRunning) {
-            return;
-        }
-        mBackground.setAlpha(drawableAlpha);
-    }
-
-    public void setRoundness(float topRoundness, float bottomRoundNess) {
-        if (topRoundness == mCornerRadii[0] && bottomRoundNess == mCornerRadii[4]) {
-            return;
-        }
-        mBottomIsRounded = bottomRoundNess != 0.0f;
-        mCornerRadii[0] = topRoundness;
-        mCornerRadii[1] = topRoundness;
-        mCornerRadii[2] = topRoundness;
-        mCornerRadii[3] = topRoundness;
-        mCornerRadii[4] = bottomRoundNess;
-        mCornerRadii[5] = bottomRoundNess;
-        mCornerRadii[6] = bottomRoundNess;
-        mCornerRadii[7] = bottomRoundNess;
-        updateBackgroundRadii();
-    }
-
-    public void setBottomAmountClips(boolean clips) {
-        if (clips != mBottomAmountClips) {
-            mBottomAmountClips = clips;
-            invalidate();
-        }
-    }
-
-    private void updateBackgroundRadii() {
-        if (mDontModifyCorners) {
-            return;
-        }
-        if (mBackground instanceof LayerDrawable) {
-            GradientDrawable gradientDrawable =
-                    (GradientDrawable) ((LayerDrawable) mBackground).getDrawable(0);
-            gradientDrawable.setCornerRadii(mCornerRadii);
-        }
-    }
-
-    public void setBackgroundTop(int backgroundTop) {
-        mBackgroundTop = backgroundTop;
-        invalidate();
-    }
-
-    public void setExpandAnimationParams(ActivityLaunchAnimator.ExpandAnimationParameters params) {
-        mActualHeight = params.getHeight();
-        mActualWidth = params.getWidth();
-        float alphaProgress = Interpolators.ALPHA_IN.getInterpolation(
-                params.getProgress(
-                        ActivityLaunchAnimator.ANIMATION_DURATION_FADE_CONTENT /* delay */,
-                        ActivityLaunchAnimator.ANIMATION_DURATION_FADE_APP /* duration */));
-        mBackground.setAlpha((int) (mDrawableAlpha * (1.0f - alphaProgress)));
-        invalidate();
-    }
-
-    public void setExpandAnimationRunning(boolean running) {
-        mExpandAnimationRunning = running;
-        if (mBackground instanceof LayerDrawable) {
-            GradientDrawable gradientDrawable =
-                    (GradientDrawable) ((LayerDrawable) mBackground).getDrawable(0);
-            gradientDrawable.setXfermode(
-                    running ? new PorterDuffXfermode(PorterDuff.Mode.SRC) : null);
-            // Speed optimization: disable AA if transfer mode is not SRC_OVER. AA is not easy to
-            // spot during animation anyways.
-            gradientDrawable.setAntiAlias(!running);
-        }
-        if (!mExpandAnimationRunning) {
-            setDrawableAlpha(mDrawableAlpha);
-        }
-        invalidate();
-    }
-
-    public void setPressedAllowed(boolean allowed) {
-        mIsPressedAllowed = allowed;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBlockingHelperManager.java
deleted file mode 100644
index c78ab8d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBlockingHelperManager.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
-import androidx.annotation.VisibleForTesting;
-import android.util.Log;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationCounters;
-import com.android.systemui.statusbar.phone.StatusBar;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-
-/**
- * Manager for the notification blocking helper - tracks and helps create the blocking helper
- * affordance.
- */
-public class NotificationBlockingHelperManager {
-    /** Enables debug logging and always makes the blocking helper show up after a dismiss. */
-    private static final boolean DEBUG = false;
-    private static final String TAG = "BlockingHelper";
-
-    private final Context mContext;
-    /** Row that the blocking helper will be shown in (via {@link NotificationGuts}. */
-    private ExpandableNotificationRow mBlockingHelperRow;
-    private Set<String> mNonBlockablePkgs;
-
-    /**
-     * Whether the notification shade/stack is expanded - used to determine blocking helper
-     * eligibility.
-     */
-    private boolean mIsShadeExpanded;
-
-    public NotificationBlockingHelperManager(Context context) {
-        mContext = context;
-        mNonBlockablePkgs = new HashSet<>();
-        Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
-                com.android.internal.R.array.config_nonBlockableNotificationPackages));
-    }
-
-    /**
-     * Potentially shows the blocking helper, represented via the {@link NotificationInfo} menu
-     * item, in the current row if user sentiment is negative.
-     *
-     * @param row row to render the blocking helper in
-     * @param menuRow menu used to generate the {@link NotificationInfo} view that houses the
-     *                blocking helper UI
-     * @return whether we're showing a blocking helper in the given notification row
-     */
-    boolean perhapsShowBlockingHelper(
-            ExpandableNotificationRow row, NotificationMenuRowPlugin menuRow) {
-        // We only show the blocking helper if:
-        // - User sentiment is negative (DEBUG flag can bypass)
-        // - The notification shade is fully expanded (guarantees we're not touching a HUN).
-        // - The row is blockable (i.e. not non-blockable)
-        // - The dismissed row is a valid group (>1 or 0 children) or the only child in the group
-        if ((row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE || DEBUG)
-                && mIsShadeExpanded
-                && !row.getIsNonblockable()
-                && (!row.isChildInGroup() || row.isOnlyChildInGroup())) {
-            // Dismiss any current blocking helper before continuing forward (only one can be shown
-            // at a given time).
-            dismissCurrentBlockingHelper();
-
-            if (DEBUG) {
-                Log.d(TAG, "Manager.perhapsShowBlockingHelper: Showing new blocking helper");
-            }
-            NotificationGutsManager manager = Dependency.get(NotificationGutsManager.class);
-
-            // Enable blocking helper on the row before moving forward so everything in the guts is
-            // correctly prepped.
-            mBlockingHelperRow = row;
-            mBlockingHelperRow.setBlockingHelperShowing(true);
-
-            // We don't care about the touch origin (x, y) since we're opening guts without any
-            // explicit user interaction.
-            manager.openGuts(mBlockingHelperRow, 0, 0, menuRow.getLongpressMenuItem(mContext));
-
-            Dependency.get(MetricsLogger.class)
-                    .count(NotificationCounters.BLOCKING_HELPER_SHOWN, 1);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Dismiss the currently showing blocking helper, if any, through a notification update.
-     *
-     * @return whether the blocking helper was dismissed
-     */
-    boolean dismissCurrentBlockingHelper() {
-        if (!isBlockingHelperRowNull()) {
-            if (DEBUG) {
-                Log.d(TAG, "Manager.dismissCurrentBlockingHelper: Dismissing current helper");
-            }
-            if (!mBlockingHelperRow.isBlockingHelperShowing()) {
-                Log.e(TAG, "Manager.dismissCurrentBlockingHelper: "
-                        + "Non-null row is not showing a blocking helper");
-            }
-
-            mBlockingHelperRow.setBlockingHelperShowing(false);
-            if (mBlockingHelperRow.isAttachedToWindow()) {
-                Dependency.get(NotificationEntryManager.class).updateNotifications();
-            }
-            mBlockingHelperRow = null;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Update the expansion status of the notification shade/stack.
-     *
-     * @param expandedHeight how much the shade is expanded ({code 0} indicating it's collapsed)
-     */
-    public void setNotificationShadeExpanded(float expandedHeight) {
-        mIsShadeExpanded = expandedHeight > 0.0f;
-    }
-
-    /**
-     * Returns whether the given package name is in the list of non-blockable packages.
-     */
-    public boolean isNonblockable(String packageName, String channelName) {
-        return mNonBlockablePkgs.contains(packageName)
-                || mNonBlockablePkgs.contains(makeChannelKey(packageName, channelName));
-    }
-
-    // Format must stay in sync with frameworks/base/core/res/res/values/config.xml
-    // config_nonBlockableNotificationPackages
-    private String makeChannelKey(String pkg, String channel) {
-        return pkg + ":" + channel;
-    }
-
-    @VisibleForTesting
-    boolean isBlockingHelperRowNull() {
-        return mBlockingHelperRow == null;
-    }
-
-    @VisibleForTesting
-    void setBlockingHelperRowForTest(ExpandableNotificationRow blockingHelperRowForTest) {
-        mBlockingHelperRow = blockingHelperRowForTest;
-    }
-
-    @VisibleForTesting
-    void setNonBlockablePkgs(String[] pkgsAndChannels) {
-        mNonBlockablePkgs = new HashSet<>();
-        Collections.addAll(mNonBlockablePkgs, pkgsAndChannels);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
deleted file mode 100644
index a90ddf0..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ /dev/null
@@ -1,1744 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.RemoteInput;
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.Build;
-import android.service.notification.StatusBarNotification;
-import android.util.ArraySet;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.NotificationHeaderView;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ContrastColorUtil;
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.HybridGroupManager;
-import com.android.systemui.statusbar.notification.HybridNotificationView;
-import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.notification.NotificationViewWrapper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.policy.RemoteInputView;
-import com.android.systemui.statusbar.policy.SmartReplyConstants;
-import com.android.systemui.statusbar.policy.SmartReplyView;
-
-/**
- * A frame layout containing the actual payload of the notification, including the contracted,
- * expanded and heads up layout. This class is responsible for clipping the content and and
- * switching between the expanded, contracted and the heads up view depending on its clipped size.
- */
-public class NotificationContentView extends FrameLayout {
-
-    private static final String TAG = "NotificationContentView";
-    public static final int VISIBLE_TYPE_CONTRACTED = 0;
-    public static final int VISIBLE_TYPE_EXPANDED = 1;
-    public static final int VISIBLE_TYPE_HEADSUP = 2;
-    private static final int VISIBLE_TYPE_SINGLELINE = 3;
-    public static final int VISIBLE_TYPE_AMBIENT = 4;
-    private static final int VISIBLE_TYPE_AMBIENT_SINGLELINE = 5;
-    public static final int UNDEFINED = -1;
-
-    private final Rect mClipBounds = new Rect();
-
-    private int mMinContractedHeight;
-    private int mNotificationContentMarginEnd;
-    private View mContractedChild;
-    private View mExpandedChild;
-    private View mHeadsUpChild;
-    private HybridNotificationView mSingleLineView;
-    private View mAmbientChild;
-    private HybridNotificationView mAmbientSingleLineChild;
-
-    private RemoteInputView mExpandedRemoteInput;
-    private RemoteInputView mHeadsUpRemoteInput;
-
-    private SmartReplyConstants mSmartReplyConstants;
-    private SmartReplyView mExpandedSmartReplyView;
-    private SmartReplyController mSmartReplyController;
-
-    private NotificationViewWrapper mContractedWrapper;
-    private NotificationViewWrapper mExpandedWrapper;
-    private NotificationViewWrapper mHeadsUpWrapper;
-    private NotificationViewWrapper mAmbientWrapper;
-    private HybridGroupManager mHybridGroupManager;
-    private int mClipTopAmount;
-    private int mContentHeight;
-    private int mVisibleType = VISIBLE_TYPE_CONTRACTED;
-    private boolean mDark;
-    private boolean mAnimate;
-    private boolean mIsHeadsUp;
-    private boolean mLegacy;
-    private boolean mIsChildInGroup;
-    private int mSmallHeight;
-    private int mHeadsUpHeight;
-    private int mNotificationMaxHeight;
-    private int mNotificationAmbientHeight;
-    private StatusBarNotification mStatusBarNotification;
-    private NotificationGroupManager mGroupManager;
-    private RemoteInputController mRemoteInputController;
-    private Runnable mExpandedVisibleListener;
-
-    private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
-            = new ViewTreeObserver.OnPreDrawListener() {
-        @Override
-        public boolean onPreDraw() {
-            // We need to post since we don't want the notification to animate on the very first
-            // frame
-            post(new Runnable() {
-                @Override
-                public void run() {
-                    mAnimate = true;
-                }
-            });
-            getViewTreeObserver().removeOnPreDrawListener(this);
-            return true;
-        }
-    };
-
-    private OnClickListener mExpandClickListener;
-    private boolean mBeforeN;
-    private boolean mExpandable;
-    private boolean mClipToActualHeight = true;
-    private ExpandableNotificationRow mContainingNotification;
-    /** The visible type at the start of a touch driven transformation */
-    private int mTransformationStartVisibleType;
-    /** The visible type at the start of an animation driven transformation */
-    private int mAnimationStartVisibleType = UNDEFINED;
-    private boolean mUserExpanding;
-    private int mSingleLineWidthIndention;
-    private boolean mForceSelectNextLayout = true;
-    private PendingIntent mPreviousExpandedRemoteInputIntent;
-    private PendingIntent mPreviousHeadsUpRemoteInputIntent;
-    private RemoteInputView mCachedExpandedRemoteInput;
-    private RemoteInputView mCachedHeadsUpRemoteInput;
-
-    private int mContentHeightAtAnimationStart = UNDEFINED;
-    private boolean mFocusOnVisibilityChange;
-    private boolean mHeadsUpAnimatingAway;
-    private boolean mIconsVisible;
-    private int mClipBottomAmount;
-    private boolean mIsLowPriority;
-    private boolean mIsContentExpandable;
-    private boolean mRemoteInputVisible;
-    private int mUnrestrictedContentHeight;
-
-
-    public NotificationContentView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mHybridGroupManager = new HybridGroupManager(getContext(), this);
-        mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
-        mSmartReplyController = Dependency.get(SmartReplyController.class);
-        initView();
-    }
-
-    public void initView() {
-        mMinContractedHeight = getResources().getDimensionPixelSize(
-                R.dimen.min_notification_layout_height);
-        mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.notification_content_margin_end);
-    }
-
-    public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight,
-            int ambientHeight) {
-        mSmallHeight = smallHeight;
-        mHeadsUpHeight = headsUpMaxHeight;
-        mNotificationMaxHeight = maxHeight;
-        mNotificationAmbientHeight = ambientHeight;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
-        boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
-        int maxSize = Integer.MAX_VALUE / 2;
-        int width = MeasureSpec.getSize(widthMeasureSpec);
-        if (hasFixedHeight || isHeightLimited) {
-            maxSize = MeasureSpec.getSize(heightMeasureSpec);
-        }
-        int maxChildHeight = 0;
-        if (mExpandedChild != null) {
-            int notificationMaxHeight = mNotificationMaxHeight;
-            if (mExpandedSmartReplyView != null) {
-                notificationMaxHeight += mExpandedSmartReplyView.getHeightUpperLimit();
-            }
-            notificationMaxHeight += mExpandedWrapper.getExtraMeasureHeight();
-            int size = notificationMaxHeight;
-            ViewGroup.LayoutParams layoutParams = mExpandedChild.getLayoutParams();
-            boolean useExactly = false;
-            if (layoutParams.height >= 0) {
-                // An actual height is set
-                size = Math.min(size, layoutParams.height);
-                useExactly = true;
-            }
-            int spec = MeasureSpec.makeMeasureSpec(size, useExactly
-                            ? MeasureSpec.EXACTLY
-                            : MeasureSpec.AT_MOST);
-            measureChildWithMargins(mExpandedChild, widthMeasureSpec, 0, spec, 0);
-            maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight());
-        }
-        if (mContractedChild != null) {
-            int heightSpec;
-            int size = mSmallHeight;
-            ViewGroup.LayoutParams layoutParams = mContractedChild.getLayoutParams();
-            boolean useExactly = false;
-            if (layoutParams.height >= 0) {
-                // An actual height is set
-                size = Math.min(size, layoutParams.height);
-                useExactly = true;
-            }
-            if (shouldContractedBeFixedSize() || useExactly) {
-                heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
-            } else {
-                heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
-            }
-            measureChildWithMargins(mContractedChild, widthMeasureSpec, 0, heightSpec, 0);
-            int measuredHeight = mContractedChild.getMeasuredHeight();
-            if (measuredHeight < mMinContractedHeight) {
-                heightSpec = MeasureSpec.makeMeasureSpec(mMinContractedHeight, MeasureSpec.EXACTLY);
-                measureChildWithMargins(mContractedChild, widthMeasureSpec, 0, heightSpec, 0);
-            }
-            maxChildHeight = Math.max(maxChildHeight, measuredHeight);
-            if (updateContractedHeaderWidth()) {
-                measureChildWithMargins(mContractedChild, widthMeasureSpec, 0, heightSpec, 0);
-            }
-            if (mExpandedChild != null
-                    && mContractedChild.getMeasuredHeight() > mExpandedChild.getMeasuredHeight()) {
-                // the Expanded child is smaller then the collapsed. Let's remeasure it.
-                heightSpec = MeasureSpec.makeMeasureSpec(mContractedChild.getMeasuredHeight(),
-                        MeasureSpec.EXACTLY);
-                measureChildWithMargins(mExpandedChild, widthMeasureSpec, 0, heightSpec, 0);
-            }
-        }
-        if (mHeadsUpChild != null) {
-            int maxHeight = mHeadsUpHeight;
-            maxHeight += mHeadsUpWrapper.getExtraMeasureHeight();
-            int size = maxHeight;
-            ViewGroup.LayoutParams layoutParams = mHeadsUpChild.getLayoutParams();
-            boolean useExactly = false;
-            if (layoutParams.height >= 0) {
-                // An actual height is set
-                size = Math.min(size, layoutParams.height);
-                useExactly = true;
-            }
-            measureChildWithMargins(mHeadsUpChild, widthMeasureSpec, 0,
-                    MeasureSpec.makeMeasureSpec(size, useExactly ? MeasureSpec.EXACTLY
-                            : MeasureSpec.AT_MOST), 0);
-            maxChildHeight = Math.max(maxChildHeight, mHeadsUpChild.getMeasuredHeight());
-        }
-        if (mSingleLineView != null) {
-            int singleLineWidthSpec = widthMeasureSpec;
-            if (mSingleLineWidthIndention != 0
-                    && MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) {
-                singleLineWidthSpec = MeasureSpec.makeMeasureSpec(
-                        width - mSingleLineWidthIndention + mSingleLineView.getPaddingEnd(),
-                        MeasureSpec.EXACTLY);
-            }
-            mSingleLineView.measure(singleLineWidthSpec,
-                    MeasureSpec.makeMeasureSpec(mNotificationMaxHeight, MeasureSpec.AT_MOST));
-            maxChildHeight = Math.max(maxChildHeight, mSingleLineView.getMeasuredHeight());
-        }
-        if (mAmbientChild != null) {
-            int size = mNotificationAmbientHeight;
-            ViewGroup.LayoutParams layoutParams = mAmbientChild.getLayoutParams();
-            boolean useExactly = false;
-            if (layoutParams.height >= 0) {
-                // An actual height is set
-                size = Math.min(size, layoutParams.height);
-                useExactly = true;
-            }
-            mAmbientChild.measure(widthMeasureSpec,
-                    MeasureSpec.makeMeasureSpec(size, useExactly ? MeasureSpec.EXACTLY
-                            : MeasureSpec.AT_MOST));
-            maxChildHeight = Math.max(maxChildHeight, mAmbientChild.getMeasuredHeight());
-        }
-        if (mAmbientSingleLineChild != null) {
-            int size = mNotificationAmbientHeight;
-            ViewGroup.LayoutParams layoutParams = mAmbientSingleLineChild.getLayoutParams();
-            boolean useExactly = false;
-            if (layoutParams.height >= 0) {
-                // An actual height is set
-                size = Math.min(size, layoutParams.height);
-                useExactly = true;
-            }
-            int ambientSingleLineWidthSpec = widthMeasureSpec;
-            if (mSingleLineWidthIndention != 0
-                    && MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) {
-                ambientSingleLineWidthSpec = MeasureSpec.makeMeasureSpec(
-                        width - mSingleLineWidthIndention + mAmbientSingleLineChild.getPaddingEnd(),
-                        MeasureSpec.EXACTLY);
-            }
-            mAmbientSingleLineChild.measure(ambientSingleLineWidthSpec,
-                    MeasureSpec.makeMeasureSpec(size, useExactly ? MeasureSpec.EXACTLY
-                            : MeasureSpec.AT_MOST));
-            maxChildHeight = Math.max(maxChildHeight, mAmbientSingleLineChild.getMeasuredHeight());
-        }
-        int ownHeight = Math.min(maxChildHeight, maxSize);
-        setMeasuredDimension(width, ownHeight);
-    }
-
-    /**
-     * Get the extra height that needs to be added to the notification height for a given
-     * {@link RemoteInputView}.
-     * This is needed when the user is inline replying in order to ensure that the reply bar has
-     * enough padding.
-     *
-     * @param remoteInput The remote input to check.
-     * @return The extra height needed.
-     */
-    private int getExtraRemoteInputHeight(RemoteInputView remoteInput) {
-        if (remoteInput != null && (remoteInput.isActive() || remoteInput.isSending())) {
-            return getResources().getDimensionPixelSize(
-                    com.android.internal.R.dimen.notification_content_margin);
-        }
-        return 0;
-    }
-
-    private boolean updateContractedHeaderWidth() {
-        // We need to update the expanded and the collapsed header to have exactly the same with to
-        // have the expand buttons laid out at the same location.
-        NotificationHeaderView contractedHeader = mContractedWrapper.getNotificationHeader();
-        if (contractedHeader != null) {
-            if (mExpandedChild != null
-                    && mExpandedWrapper.getNotificationHeader() != null) {
-                NotificationHeaderView expandedHeader = mExpandedWrapper.getNotificationHeader();
-                int expandedSize = expandedHeader.getMeasuredWidth()
-                        - expandedHeader.getPaddingEnd();
-                int collapsedSize = contractedHeader.getMeasuredWidth()
-                        - expandedHeader.getPaddingEnd();
-                if (expandedSize != collapsedSize) {
-                    int paddingEnd = contractedHeader.getMeasuredWidth() - expandedSize;
-                    contractedHeader.setPadding(
-                            contractedHeader.isLayoutRtl()
-                                    ? paddingEnd
-                                    : contractedHeader.getPaddingLeft(),
-                            contractedHeader.getPaddingTop(),
-                            contractedHeader.isLayoutRtl()
-                                    ? contractedHeader.getPaddingLeft()
-                                    : paddingEnd,
-                            contractedHeader.getPaddingBottom());
-                    contractedHeader.setShowWorkBadgeAtEnd(true);
-                    return true;
-                }
-            } else {
-                int paddingEnd = mNotificationContentMarginEnd;
-                if (contractedHeader.getPaddingEnd() != paddingEnd) {
-                    contractedHeader.setPadding(
-                            contractedHeader.isLayoutRtl()
-                                    ? paddingEnd
-                                    : contractedHeader.getPaddingLeft(),
-                            contractedHeader.getPaddingTop(),
-                            contractedHeader.isLayoutRtl()
-                                    ? contractedHeader.getPaddingLeft()
-                                    : paddingEnd,
-                            contractedHeader.getPaddingBottom());
-                    contractedHeader.setShowWorkBadgeAtEnd(false);
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private boolean shouldContractedBeFixedSize() {
-        return mBeforeN && mContractedWrapper instanceof NotificationCustomViewWrapper;
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        int previousHeight = 0;
-        if (mExpandedChild != null) {
-            previousHeight = mExpandedChild.getHeight();
-        }
-        super.onLayout(changed, left, top, right, bottom);
-        if (previousHeight != 0 && mExpandedChild.getHeight() != previousHeight) {
-            mContentHeightAtAnimationStart = previousHeight;
-        }
-        updateClipping();
-        invalidateOutline();
-        selectLayout(false /* animate */, mForceSelectNextLayout /* force */);
-        mForceSelectNextLayout = false;
-        updateExpandButtons(mExpandable);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        updateVisibility();
-    }
-
-    public View getContractedChild() {
-        return mContractedChild;
-    }
-
-    public View getExpandedChild() {
-        return mExpandedChild;
-    }
-
-    public View getHeadsUpChild() {
-        return mHeadsUpChild;
-    }
-
-    public View getAmbientChild() {
-        return mAmbientChild;
-    }
-
-    public HybridNotificationView getAmbientSingleLineChild() {
-        return mAmbientSingleLineChild;
-    }
-
-    public void setContractedChild(View child) {
-        if (mContractedChild != null) {
-            mContractedChild.animate().cancel();
-            removeView(mContractedChild);
-        }
-        addView(child);
-        mContractedChild = child;
-        mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child,
-                mContainingNotification);
-    }
-
-    private NotificationViewWrapper getWrapperForView(View child) {
-        if (child == mContractedChild) {
-            return mContractedWrapper;
-        }
-        if (child == mExpandedChild) {
-            return mExpandedWrapper;
-        }
-        if (child == mHeadsUpChild) {
-            return mHeadsUpWrapper;
-        }
-        if (child == mAmbientChild) {
-            return mAmbientWrapper;
-        }
-        return null;
-    }
-
-    public void setExpandedChild(View child) {
-        if (mExpandedChild != null) {
-            mPreviousExpandedRemoteInputIntent = null;
-            if (mExpandedRemoteInput != null) {
-                mExpandedRemoteInput.onNotificationUpdateOrReset();
-                if (mExpandedRemoteInput.isActive()) {
-                    mPreviousExpandedRemoteInputIntent = mExpandedRemoteInput.getPendingIntent();
-                    mCachedExpandedRemoteInput = mExpandedRemoteInput;
-                    mExpandedRemoteInput.dispatchStartTemporaryDetach();
-                    ((ViewGroup)mExpandedRemoteInput.getParent()).removeView(mExpandedRemoteInput);
-                }
-            }
-            mExpandedChild.animate().cancel();
-            removeView(mExpandedChild);
-            mExpandedRemoteInput = null;
-        }
-        if (child == null) {
-            mExpandedChild = null;
-            mExpandedWrapper = null;
-            if (mVisibleType == VISIBLE_TYPE_EXPANDED) {
-                mVisibleType = VISIBLE_TYPE_CONTRACTED;
-            }
-            if (mTransformationStartVisibleType == VISIBLE_TYPE_EXPANDED) {
-                mTransformationStartVisibleType = UNDEFINED;
-            }
-            return;
-        }
-        addView(child);
-        mExpandedChild = child;
-        mExpandedWrapper = NotificationViewWrapper.wrap(getContext(), child,
-                mContainingNotification);
-    }
-
-    public void setHeadsUpChild(View child) {
-        if (mHeadsUpChild != null) {
-            mPreviousHeadsUpRemoteInputIntent = null;
-            if (mHeadsUpRemoteInput != null) {
-                mHeadsUpRemoteInput.onNotificationUpdateOrReset();
-                if (mHeadsUpRemoteInput.isActive()) {
-                    mPreviousHeadsUpRemoteInputIntent = mHeadsUpRemoteInput.getPendingIntent();
-                    mCachedHeadsUpRemoteInput = mHeadsUpRemoteInput;
-                    mHeadsUpRemoteInput.dispatchStartTemporaryDetach();
-                    ((ViewGroup)mHeadsUpRemoteInput.getParent()).removeView(mHeadsUpRemoteInput);
-                }
-            }
-            mHeadsUpChild.animate().cancel();
-            removeView(mHeadsUpChild);
-            mHeadsUpRemoteInput = null;
-        }
-        if (child == null) {
-            mHeadsUpChild = null;
-            mHeadsUpWrapper = null;
-            if (mVisibleType == VISIBLE_TYPE_HEADSUP) {
-                mVisibleType = VISIBLE_TYPE_CONTRACTED;
-            }
-            if (mTransformationStartVisibleType == VISIBLE_TYPE_HEADSUP) {
-                mTransformationStartVisibleType = UNDEFINED;
-            }
-            return;
-        }
-        addView(child);
-        mHeadsUpChild = child;
-        mHeadsUpWrapper = NotificationViewWrapper.wrap(getContext(), child,
-                mContainingNotification);
-    }
-
-    public void setAmbientChild(View child) {
-        if (mAmbientChild != null) {
-            mAmbientChild.animate().cancel();
-            removeView(mAmbientChild);
-        }
-        if (child == null) {
-            return;
-        }
-        addView(child);
-        mAmbientChild = child;
-        mAmbientWrapper = NotificationViewWrapper.wrap(getContext(), child,
-                mContainingNotification);
-    }
-
-    @Override
-    protected void onVisibilityChanged(View changedView, int visibility) {
-        super.onVisibilityChanged(changedView, visibility);
-        updateVisibility();
-    }
-
-    private void updateVisibility() {
-        setVisible(isShown());
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
-    }
-
-    private void setVisible(final boolean isVisible) {
-        if (isVisible) {
-            // This call can happen multiple times, but removing only removes a single one.
-            // We therefore need to remove the old one.
-            getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
-            // We only animate if we are drawn at least once, otherwise the view might animate when
-            // it's shown the first time
-            getViewTreeObserver().addOnPreDrawListener(mEnableAnimationPredrawListener);
-        } else {
-            getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
-            mAnimate = false;
-        }
-    }
-
-    private void focusExpandButtonIfNecessary() {
-        if (mFocusOnVisibilityChange) {
-            NotificationHeaderView header = getVisibleNotificationHeader();
-            if (header != null) {
-                ImageView expandButton = header.getExpandButton();
-                if (expandButton != null) {
-                    expandButton.requestAccessibilityFocus();
-                }
-            }
-            mFocusOnVisibilityChange = false;
-        }
-    }
-
-    public void setContentHeight(int contentHeight) {
-        mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight());
-        int maxContentHeight = mContainingNotification.getIntrinsicHeight()
-                - getExtraRemoteInputHeight(mExpandedRemoteInput)
-                - getExtraRemoteInputHeight(mHeadsUpRemoteInput);
-        mContentHeight = Math.min(mUnrestrictedContentHeight, maxContentHeight);
-        selectLayout(mAnimate /* animate */, false /* force */);
-
-        int minHeightHint = getMinContentHeightHint();
-
-        NotificationViewWrapper wrapper = getVisibleWrapper(mVisibleType);
-        if (wrapper != null) {
-            wrapper.setContentHeight(mUnrestrictedContentHeight, minHeightHint);
-        }
-
-        wrapper = getVisibleWrapper(mTransformationStartVisibleType);
-        if (wrapper != null) {
-            wrapper.setContentHeight(mUnrestrictedContentHeight, minHeightHint);
-        }
-
-        updateClipping();
-        invalidateOutline();
-    }
-
-    /**
-     * @return the minimum apparent height that the wrapper should allow for the purpose
-     *         of aligning elements at the bottom edge. If this is larger than the content
-     *         height, the notification is clipped instead of being further shrunk.
-     */
-    private int getMinContentHeightHint() {
-        if (mIsChildInGroup && isVisibleOrTransitioning(VISIBLE_TYPE_SINGLELINE)) {
-            return mContext.getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.notification_action_list_height);
-        }
-
-        // Transition between heads-up & expanded, or pinned.
-        if (mHeadsUpChild != null && mExpandedChild != null) {
-            boolean transitioningBetweenHunAndExpanded =
-                    isTransitioningFromTo(VISIBLE_TYPE_HEADSUP, VISIBLE_TYPE_EXPANDED) ||
-                    isTransitioningFromTo(VISIBLE_TYPE_EXPANDED, VISIBLE_TYPE_HEADSUP);
-            boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED)
-                    && (mIsHeadsUp || mHeadsUpAnimatingAway)
-                    && !mContainingNotification.isOnKeyguard();
-            if (transitioningBetweenHunAndExpanded || pinned) {
-                return Math.min(getViewHeight(VISIBLE_TYPE_HEADSUP),
-                        getViewHeight(VISIBLE_TYPE_EXPANDED));
-            }
-        }
-
-        // Size change of the expanded version
-        if ((mVisibleType == VISIBLE_TYPE_EXPANDED) && mContentHeightAtAnimationStart >= 0
-                && mExpandedChild != null) {
-            return Math.min(mContentHeightAtAnimationStart, getViewHeight(VISIBLE_TYPE_EXPANDED));
-        }
-
-        int hint;
-        if (mAmbientChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_AMBIENT)) {
-            hint = mAmbientChild.getHeight();
-        } else if (mAmbientSingleLineChild != null && isVisibleOrTransitioning(
-                VISIBLE_TYPE_AMBIENT_SINGLELINE)) {
-            hint = mAmbientSingleLineChild.getHeight();
-        } else if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
-            hint = getViewHeight(VISIBLE_TYPE_HEADSUP);
-        } else if (mExpandedChild != null) {
-            hint = getViewHeight(VISIBLE_TYPE_EXPANDED);
-        } else {
-            hint = getViewHeight(VISIBLE_TYPE_CONTRACTED)
-                    + mContext.getResources().getDimensionPixelSize(
-                            com.android.internal.R.dimen.notification_action_list_height);
-        }
-
-        if (mExpandedChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_EXPANDED)) {
-            hint = Math.min(hint, getViewHeight(VISIBLE_TYPE_EXPANDED));
-        }
-        return hint;
-    }
-
-    private boolean isTransitioningFromTo(int from, int to) {
-        return (mTransformationStartVisibleType == from || mAnimationStartVisibleType == from)
-                && mVisibleType == to;
-    }
-
-    private boolean isVisibleOrTransitioning(int type) {
-        return mVisibleType == type || mTransformationStartVisibleType == type
-                || mAnimationStartVisibleType == type;
-    }
-
-    private void updateContentTransformation() {
-        int visibleType = calculateVisibleType();
-        if (visibleType != mVisibleType) {
-            // A new transformation starts
-            mTransformationStartVisibleType = mVisibleType;
-            final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
-            final TransformableView hiddenView = getTransformableViewForVisibleType(
-                    mTransformationStartVisibleType);
-            shownView.transformFrom(hiddenView, 0.0f);
-            getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
-            hiddenView.transformTo(shownView, 0.0f);
-            mVisibleType = visibleType;
-            updateBackgroundColor(true /* animate */);
-        }
-        if (mForceSelectNextLayout) {
-            forceUpdateVisibilities();
-        }
-        if (mTransformationStartVisibleType != UNDEFINED
-                && mVisibleType != mTransformationStartVisibleType
-                && getViewForVisibleType(mTransformationStartVisibleType) != null) {
-            final TransformableView shownView = getTransformableViewForVisibleType(mVisibleType);
-            final TransformableView hiddenView = getTransformableViewForVisibleType(
-                    mTransformationStartVisibleType);
-            float transformationAmount = calculateTransformationAmount();
-            shownView.transformFrom(hiddenView, transformationAmount);
-            hiddenView.transformTo(shownView, transformationAmount);
-            updateBackgroundTransformation(transformationAmount);
-        } else {
-            updateViewVisibilities(visibleType);
-            updateBackgroundColor(false);
-        }
-    }
-
-    private void updateBackgroundTransformation(float transformationAmount) {
-        int endColor = getBackgroundColor(mVisibleType);
-        int startColor = getBackgroundColor(mTransformationStartVisibleType);
-        if (endColor != startColor) {
-            if (startColor == 0) {
-                startColor = mContainingNotification.getBackgroundColorWithoutTint();
-            }
-            if (endColor == 0) {
-                endColor = mContainingNotification.getBackgroundColorWithoutTint();
-            }
-            endColor = NotificationUtils.interpolateColors(startColor, endColor,
-                    transformationAmount);
-        }
-        mContainingNotification.updateBackgroundAlpha(transformationAmount);
-        mContainingNotification.setContentBackground(endColor, false, this);
-    }
-
-    private float calculateTransformationAmount() {
-        int startHeight = getViewHeight(mTransformationStartVisibleType);
-        int endHeight = getViewHeight(mVisibleType);
-        int progress = Math.abs(mContentHeight - startHeight);
-        int totalDistance = Math.abs(endHeight - startHeight);
-        if (totalDistance == 0) {
-            Log.wtf(TAG, "the total transformation distance is 0"
-                    + "\n StartType: " + mTransformationStartVisibleType + " height: " + startHeight
-                    + "\n VisibleType: " + mVisibleType + " height: " + endHeight
-                    + "\n mContentHeight: " + mContentHeight);
-            return 1.0f;
-        }
-        float amount = (float) progress / (float) totalDistance;
-        return Math.min(1.0f, amount);
-    }
-
-    public int getContentHeight() {
-        return mContentHeight;
-    }
-
-    public int getMaxHeight() {
-        if (mContainingNotification.isShowingAmbient()) {
-            return getShowingAmbientView().getHeight();
-        } else if (mExpandedChild != null) {
-            return getViewHeight(VISIBLE_TYPE_EXPANDED)
-                    + getExtraRemoteInputHeight(mExpandedRemoteInput);
-        } else if (mIsHeadsUp && mHeadsUpChild != null && !mContainingNotification.isOnKeyguard()) {
-            return getViewHeight(VISIBLE_TYPE_HEADSUP)
-                    + getExtraRemoteInputHeight(mHeadsUpRemoteInput);
-        }
-        return getViewHeight(VISIBLE_TYPE_CONTRACTED);
-    }
-
-    private int getViewHeight(int visibleType) {
-        View view = getViewForVisibleType(visibleType);
-        int height = view.getHeight();
-        NotificationViewWrapper viewWrapper = getWrapperForView(view);
-        if (viewWrapper != null) {
-            height += viewWrapper.getHeaderTranslation();
-        }
-        return height;
-    }
-
-    public int getMinHeight() {
-        return getMinHeight(false /* likeGroupExpanded */);
-    }
-
-    public int getMinHeight(boolean likeGroupExpanded) {
-        if (mContainingNotification.isShowingAmbient()) {
-            return getShowingAmbientView().getHeight();
-        } else if (likeGroupExpanded || !mIsChildInGroup || isGroupExpanded()) {
-            return getViewHeight(VISIBLE_TYPE_CONTRACTED);
-        } else {
-            return mSingleLineView.getHeight();
-        }
-    }
-
-    public View getShowingAmbientView() {
-        View v = mIsChildInGroup ? mAmbientSingleLineChild : mAmbientChild;
-        if (v != null) {
-            return v;
-        } else {
-            return mContractedChild;
-        }
-    }
-
-    private boolean isGroupExpanded() {
-        return mGroupManager.isGroupExpanded(mStatusBarNotification);
-    }
-
-    public void setClipTopAmount(int clipTopAmount) {
-        mClipTopAmount = clipTopAmount;
-        updateClipping();
-    }
-
-
-    public void setClipBottomAmount(int clipBottomAmount) {
-        mClipBottomAmount = clipBottomAmount;
-        updateClipping();
-    }
-
-    @Override
-    public void setTranslationY(float translationY) {
-        super.setTranslationY(translationY);
-        updateClipping();
-    }
-
-    private void updateClipping() {
-        if (mClipToActualHeight) {
-            int top = (int) (mClipTopAmount - getTranslationY());
-            int bottom = (int) (mUnrestrictedContentHeight - mClipBottomAmount - getTranslationY());
-            bottom = Math.max(top, bottom);
-            mClipBounds.set(0, top, getWidth(), bottom);
-            setClipBounds(mClipBounds);
-        } else {
-            setClipBounds(null);
-        }
-    }
-
-    public void setClipToActualHeight(boolean clipToActualHeight) {
-        mClipToActualHeight = clipToActualHeight;
-        updateClipping();
-    }
-
-    private void selectLayout(boolean animate, boolean force) {
-        if (mContractedChild == null) {
-            return;
-        }
-        if (mUserExpanding) {
-            updateContentTransformation();
-        } else {
-            int visibleType = calculateVisibleType();
-            boolean changedType = visibleType != mVisibleType;
-            if (changedType || force) {
-                View visibleView = getViewForVisibleType(visibleType);
-                if (visibleView != null) {
-                    visibleView.setVisibility(VISIBLE);
-                    transferRemoteInputFocus(visibleType);
-                }
-
-                if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
-                        || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
-                        || (visibleType == VISIBLE_TYPE_SINGLELINE && mSingleLineView != null)
-                        || visibleType == VISIBLE_TYPE_CONTRACTED)) {
-                    animateToVisibleType(visibleType);
-                } else {
-                    updateViewVisibilities(visibleType);
-                }
-                mVisibleType = visibleType;
-                if (changedType) {
-                    focusExpandButtonIfNecessary();
-                }
-                NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
-                if (visibleWrapper != null) {
-                    visibleWrapper.setContentHeight(mUnrestrictedContentHeight,
-                            getMinContentHeightHint());
-                }
-                updateBackgroundColor(animate);
-            }
-        }
-    }
-
-    private void forceUpdateVisibilities() {
-        forceUpdateVisibility(VISIBLE_TYPE_CONTRACTED, mContractedChild, mContractedWrapper);
-        forceUpdateVisibility(VISIBLE_TYPE_EXPANDED, mExpandedChild, mExpandedWrapper);
-        forceUpdateVisibility(VISIBLE_TYPE_HEADSUP, mHeadsUpChild, mHeadsUpWrapper);
-        forceUpdateVisibility(VISIBLE_TYPE_SINGLELINE, mSingleLineView, mSingleLineView);
-        forceUpdateVisibility(VISIBLE_TYPE_AMBIENT, mAmbientChild, mAmbientWrapper);
-        forceUpdateVisibility(VISIBLE_TYPE_AMBIENT_SINGLELINE, mAmbientSingleLineChild,
-                mAmbientSingleLineChild);
-        fireExpandedVisibleListenerIfVisible();
-        // forceUpdateVisibilities cancels outstanding animations without updating the
-        // mAnimationStartVisibleType. Do so here instead.
-        mAnimationStartVisibleType = UNDEFINED;
-    }
-
-    private void fireExpandedVisibleListenerIfVisible() {
-        if (mExpandedVisibleListener != null && mExpandedChild != null && isShown()
-                && mExpandedChild.getVisibility() == VISIBLE) {
-            Runnable listener = mExpandedVisibleListener;
-            mExpandedVisibleListener = null;
-            listener.run();
-        }
-    }
-
-    private void forceUpdateVisibility(int type, View view, TransformableView wrapper) {
-        if (view == null) {
-            return;
-        }
-        boolean visible = mVisibleType == type
-                || mTransformationStartVisibleType == type;
-        if (!visible) {
-            view.setVisibility(INVISIBLE);
-        } else {
-            wrapper.setVisible(true);
-        }
-    }
-
-    public void updateBackgroundColor(boolean animate) {
-        int customBackgroundColor = getBackgroundColor(mVisibleType);
-        mContainingNotification.resetBackgroundAlpha();
-        mContainingNotification.setContentBackground(customBackgroundColor, animate, this);
-    }
-
-    public void setBackgroundTintColor(int color) {
-        if (mExpandedSmartReplyView != null) {
-            mExpandedSmartReplyView.setBackgroundTintColor(color);
-        }
-    }
-
-    public int getVisibleType() {
-        return mVisibleType;
-    }
-
-    public int getBackgroundColorForExpansionState() {
-        // When expanding or user locked we want the new type, when collapsing we want
-        // the original type
-        final int visibleType = (mContainingNotification.isGroupExpanded()
-                || mContainingNotification.isUserLocked())
-                        ? calculateVisibleType()
-                        : getVisibleType();
-        return getBackgroundColor(visibleType);
-    }
-
-    public int getBackgroundColor(int visibleType) {
-        NotificationViewWrapper currentVisibleWrapper = getVisibleWrapper(visibleType);
-        int customBackgroundColor = 0;
-        if (currentVisibleWrapper != null) {
-            customBackgroundColor = currentVisibleWrapper.getCustomBackgroundColor();
-        }
-        return customBackgroundColor;
-    }
-
-    private void updateViewVisibilities(int visibleType) {
-        updateViewVisibility(visibleType, VISIBLE_TYPE_CONTRACTED,
-                mContractedChild, mContractedWrapper);
-        updateViewVisibility(visibleType, VISIBLE_TYPE_EXPANDED,
-                mExpandedChild, mExpandedWrapper);
-        updateViewVisibility(visibleType, VISIBLE_TYPE_HEADSUP,
-                mHeadsUpChild, mHeadsUpWrapper);
-        updateViewVisibility(visibleType, VISIBLE_TYPE_SINGLELINE,
-                mSingleLineView, mSingleLineView);
-        updateViewVisibility(visibleType, VISIBLE_TYPE_AMBIENT,
-                mAmbientChild, mAmbientWrapper);
-        updateViewVisibility(visibleType, VISIBLE_TYPE_AMBIENT_SINGLELINE,
-                mAmbientSingleLineChild, mAmbientSingleLineChild);
-        fireExpandedVisibleListenerIfVisible();
-        // updateViewVisibilities cancels outstanding animations without updating the
-        // mAnimationStartVisibleType. Do so here instead.
-        mAnimationStartVisibleType = UNDEFINED;
-    }
-
-    private void updateViewVisibility(int visibleType, int type, View view,
-            TransformableView wrapper) {
-        if (view != null) {
-            wrapper.setVisible(visibleType == type);
-        }
-    }
-
-    private void animateToVisibleType(int visibleType) {
-        final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
-        final TransformableView hiddenView = getTransformableViewForVisibleType(mVisibleType);
-        if (shownView == hiddenView || hiddenView == null) {
-            shownView.setVisible(true);
-            return;
-        }
-        mAnimationStartVisibleType = mVisibleType;
-        shownView.transformFrom(hiddenView);
-        getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
-        hiddenView.transformTo(shownView, new Runnable() {
-            @Override
-            public void run() {
-                if (hiddenView != getTransformableViewForVisibleType(mVisibleType)) {
-                    hiddenView.setVisible(false);
-                }
-                mAnimationStartVisibleType = UNDEFINED;
-            }
-        });
-        fireExpandedVisibleListenerIfVisible();
-    }
-
-    private void transferRemoteInputFocus(int visibleType) {
-        if (visibleType == VISIBLE_TYPE_HEADSUP
-                && mHeadsUpRemoteInput != null
-                && (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive())) {
-            mHeadsUpRemoteInput.stealFocusFrom(mExpandedRemoteInput);
-        }
-        if (visibleType == VISIBLE_TYPE_EXPANDED
-                && mExpandedRemoteInput != null
-                && (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive())) {
-            mExpandedRemoteInput.stealFocusFrom(mHeadsUpRemoteInput);
-        }
-    }
-
-    /**
-     * @param visibleType one of the static enum types in this view
-     * @return the corresponding transformable view according to the given visible type
-     */
-    private TransformableView getTransformableViewForVisibleType(int visibleType) {
-        switch (visibleType) {
-            case VISIBLE_TYPE_EXPANDED:
-                return mExpandedWrapper;
-            case VISIBLE_TYPE_HEADSUP:
-                return mHeadsUpWrapper;
-            case VISIBLE_TYPE_SINGLELINE:
-                return mSingleLineView;
-            case VISIBLE_TYPE_AMBIENT:
-                return mAmbientWrapper;
-            case VISIBLE_TYPE_AMBIENT_SINGLELINE:
-                return mAmbientSingleLineChild;
-            default:
-                return mContractedWrapper;
-        }
-    }
-
-    /**
-     * @param visibleType one of the static enum types in this view
-     * @return the corresponding view according to the given visible type
-     */
-    private View getViewForVisibleType(int visibleType) {
-        switch (visibleType) {
-            case VISIBLE_TYPE_EXPANDED:
-                return mExpandedChild;
-            case VISIBLE_TYPE_HEADSUP:
-                return mHeadsUpChild;
-            case VISIBLE_TYPE_SINGLELINE:
-                return mSingleLineView;
-            case VISIBLE_TYPE_AMBIENT:
-                return mAmbientChild;
-            case VISIBLE_TYPE_AMBIENT_SINGLELINE:
-                return mAmbientSingleLineChild;
-            default:
-                return mContractedChild;
-        }
-    }
-
-    public NotificationViewWrapper getVisibleWrapper(int visibleType) {
-        switch (visibleType) {
-            case VISIBLE_TYPE_EXPANDED:
-                return mExpandedWrapper;
-            case VISIBLE_TYPE_HEADSUP:
-                return mHeadsUpWrapper;
-            case VISIBLE_TYPE_CONTRACTED:
-                return mContractedWrapper;
-            case VISIBLE_TYPE_AMBIENT:
-                return mAmbientWrapper;
-            default:
-                return null;
-        }
-    }
-
-    /**
-     * @return one of the static enum types in this view, calculated form the current state
-     */
-    public int calculateVisibleType() {
-        if (mContainingNotification.isShowingAmbient()) {
-            if (mIsChildInGroup && mAmbientSingleLineChild != null) {
-                return VISIBLE_TYPE_AMBIENT_SINGLELINE;
-            } else if (mAmbientChild != null) {
-                return VISIBLE_TYPE_AMBIENT;
-            } else {
-                return VISIBLE_TYPE_CONTRACTED;
-            }
-        }
-        if (mUserExpanding) {
-            int height = !mIsChildInGroup || isGroupExpanded()
-                    || mContainingNotification.isExpanded(true /* allowOnKeyguard */)
-                    ? mContainingNotification.getMaxContentHeight()
-                    : mContainingNotification.getShowingLayout().getMinHeight();
-            if (height == 0) {
-                height = mContentHeight;
-            }
-            int expandedVisualType = getVisualTypeForHeight(height);
-            int collapsedVisualType = mIsChildInGroup && !isGroupExpanded()
-                    ? VISIBLE_TYPE_SINGLELINE
-                    : getVisualTypeForHeight(mContainingNotification.getCollapsedHeight());
-            return mTransformationStartVisibleType == collapsedVisualType
-                    ? expandedVisualType
-                    : collapsedVisualType;
-        }
-        int intrinsicHeight = mContainingNotification.getIntrinsicHeight();
-        int viewHeight = mContentHeight;
-        if (intrinsicHeight != 0) {
-            // the intrinsicHeight might be 0 because it was just reset.
-            viewHeight = Math.min(mContentHeight, intrinsicHeight);
-        }
-        return getVisualTypeForHeight(viewHeight);
-    }
-
-    private int getVisualTypeForHeight(float viewHeight) {
-        boolean noExpandedChild = mExpandedChild == null;
-        if (!noExpandedChild && viewHeight == getViewHeight(VISIBLE_TYPE_EXPANDED)) {
-            return VISIBLE_TYPE_EXPANDED;
-        }
-        if (!mUserExpanding && mIsChildInGroup && !isGroupExpanded()) {
-            return VISIBLE_TYPE_SINGLELINE;
-        }
-
-        if ((mIsHeadsUp || mHeadsUpAnimatingAway) && mHeadsUpChild != null
-                && !mContainingNotification.isOnKeyguard()) {
-            if (viewHeight <= getViewHeight(VISIBLE_TYPE_HEADSUP) || noExpandedChild) {
-                return VISIBLE_TYPE_HEADSUP;
-            } else {
-                return VISIBLE_TYPE_EXPANDED;
-            }
-        } else {
-            if (noExpandedChild || (viewHeight <= getViewHeight(VISIBLE_TYPE_CONTRACTED)
-                    && (!mIsChildInGroup || isGroupExpanded()
-                            || !mContainingNotification.isExpanded(true /* allowOnKeyguard */)))) {
-                return VISIBLE_TYPE_CONTRACTED;
-            } else {
-                return VISIBLE_TYPE_EXPANDED;
-            }
-        }
-    }
-
-    public boolean isContentExpandable() {
-        return mIsContentExpandable;
-    }
-
-    public void setDark(boolean dark, boolean fade, long delay) {
-        if (mContractedChild == null) {
-            return;
-        }
-        mDark = dark;
-        selectLayout(!dark && fade /* animate */, false /* force */);
-    }
-
-    public void setHeadsUp(boolean headsUp) {
-        mIsHeadsUp = headsUp;
-        selectLayout(false /* animate */, true /* force */);
-        updateExpandButtons(mExpandable);
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-
-        // This is not really true, but good enough when fading from the contracted to the expanded
-        // layout, and saves us some layers.
-        return false;
-    }
-
-    public void setLegacy(boolean legacy) {
-        mLegacy = legacy;
-        updateLegacy();
-    }
-
-    private void updateLegacy() {
-        if (mContractedChild != null) {
-            mContractedWrapper.setLegacy(mLegacy);
-        }
-        if (mExpandedChild != null) {
-            mExpandedWrapper.setLegacy(mLegacy);
-        }
-        if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.setLegacy(mLegacy);
-        }
-    }
-
-    public void setIsChildInGroup(boolean isChildInGroup) {
-        mIsChildInGroup = isChildInGroup;
-        if (mContractedChild != null) {
-            mContractedWrapper.setIsChildInGroup(mIsChildInGroup);
-        }
-        if (mExpandedChild != null) {
-            mExpandedWrapper.setIsChildInGroup(mIsChildInGroup);
-        }
-        if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.setIsChildInGroup(mIsChildInGroup);
-        }
-        if (mAmbientChild != null) {
-            mAmbientWrapper.setIsChildInGroup(mIsChildInGroup);
-        }
-        updateAllSingleLineViews();
-    }
-
-    public void onNotificationUpdated(NotificationData.Entry entry) {
-        mStatusBarNotification = entry.notification;
-        mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
-        updateAllSingleLineViews();
-        if (mContractedChild != null) {
-            mContractedWrapper.onContentUpdated(entry.row);
-        }
-        if (mExpandedChild != null) {
-            mExpandedWrapper.onContentUpdated(entry.row);
-        }
-        if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.onContentUpdated(entry.row);
-        }
-        if (mAmbientChild != null) {
-            mAmbientWrapper.onContentUpdated(entry.row);
-        }
-        applyRemoteInputAndSmartReply(entry);
-        updateLegacy();
-        mForceSelectNextLayout = true;
-        setDark(mDark, false /* animate */, 0 /* delay */);
-        mPreviousExpandedRemoteInputIntent = null;
-        mPreviousHeadsUpRemoteInputIntent = null;
-    }
-
-    private void updateAllSingleLineViews() {
-        updateSingleLineView();
-        updateAmbientSingleLineView();
-    }
-    private void updateSingleLineView() {
-        if (mIsChildInGroup) {
-            boolean isNewView = mSingleLineView == null;
-            mSingleLineView = mHybridGroupManager.bindFromNotification(
-                    mSingleLineView, mStatusBarNotification.getNotification());
-            if (isNewView) {
-                updateViewVisibility(mVisibleType, VISIBLE_TYPE_SINGLELINE,
-                        mSingleLineView, mSingleLineView);
-            }
-        } else if (mSingleLineView != null) {
-            removeView(mSingleLineView);
-            mSingleLineView = null;
-        }
-    }
-
-    private void updateAmbientSingleLineView() {
-        if (mIsChildInGroup) {
-            boolean isNewView = mAmbientSingleLineChild == null;
-            mAmbientSingleLineChild = mHybridGroupManager.bindAmbientFromNotification(
-                    mAmbientSingleLineChild, mStatusBarNotification.getNotification());
-            if (isNewView) {
-                updateViewVisibility(mVisibleType, VISIBLE_TYPE_AMBIENT_SINGLELINE,
-                        mAmbientSingleLineChild, mAmbientSingleLineChild);
-            }
-        } else if (mAmbientSingleLineChild != null) {
-            removeView(mAmbientSingleLineChild);
-            mAmbientSingleLineChild = null;
-        }
-    }
-
-    private void applyRemoteInputAndSmartReply(final NotificationData.Entry entry) {
-        if (mRemoteInputController == null) {
-            return;
-        }
-
-        boolean enableSmartReplies = (mSmartReplyConstants.isEnabled()
-                && (!mSmartReplyConstants.requiresTargetingP()
-                    || entry.targetSdk >= Build.VERSION_CODES.P));
-
-        boolean hasRemoteInput = false;
-        RemoteInput remoteInputWithChoices = null;
-        PendingIntent pendingIntentWithChoices = null;
-
-        Notification.Action[] actions = entry.notification.getNotification().actions;
-        if (actions != null) {
-            for (Notification.Action a : actions) {
-                if (a.getRemoteInputs() != null) {
-                    for (RemoteInput ri : a.getRemoteInputs()) {
-                        boolean showRemoteInputView = ri.getAllowFreeFormInput();
-                        boolean showSmartReplyView = enableSmartReplies && ri.getChoices() != null
-                                && ri.getChoices().length > 0;
-                        if (showRemoteInputView) {
-                            hasRemoteInput = true;
-                        }
-                        if (showSmartReplyView) {
-                            remoteInputWithChoices = ri;
-                            pendingIntentWithChoices = a.actionIntent;
-                        }
-                        if (showRemoteInputView || showSmartReplyView) {
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        applyRemoteInput(entry, hasRemoteInput);
-        applySmartReplyView(remoteInputWithChoices, pendingIntentWithChoices, entry);
-    }
-
-    private void applyRemoteInput(NotificationData.Entry entry, boolean hasRemoteInput) {
-        View bigContentView = mExpandedChild;
-        if (bigContentView != null) {
-            mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput,
-                    mPreviousExpandedRemoteInputIntent, mCachedExpandedRemoteInput,
-                    mExpandedWrapper);
-        } else {
-            mExpandedRemoteInput = null;
-        }
-        if (mCachedExpandedRemoteInput != null
-                && mCachedExpandedRemoteInput != mExpandedRemoteInput) {
-            // We had a cached remote input but didn't reuse it. Clean up required.
-            mCachedExpandedRemoteInput.dispatchFinishTemporaryDetach();
-        }
-        mCachedExpandedRemoteInput = null;
-
-        View headsUpContentView = mHeadsUpChild;
-        if (headsUpContentView != null) {
-            mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput,
-                    mPreviousHeadsUpRemoteInputIntent, mCachedHeadsUpRemoteInput, mHeadsUpWrapper);
-        } else {
-            mHeadsUpRemoteInput = null;
-        }
-        if (mCachedHeadsUpRemoteInput != null
-                && mCachedHeadsUpRemoteInput != mHeadsUpRemoteInput) {
-            // We had a cached remote input but didn't reuse it. Clean up required.
-            mCachedHeadsUpRemoteInput.dispatchFinishTemporaryDetach();
-        }
-        mCachedHeadsUpRemoteInput = null;
-    }
-
-    private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry,
-            boolean hasRemoteInput, PendingIntent existingPendingIntent,
-            RemoteInputView cachedView, NotificationViewWrapper wrapper) {
-        View actionContainerCandidate = view.findViewById(
-                com.android.internal.R.id.actions_container);
-        if (actionContainerCandidate instanceof FrameLayout) {
-            RemoteInputView existing = (RemoteInputView)
-                    view.findViewWithTag(RemoteInputView.VIEW_TAG);
-
-            if (existing != null) {
-                existing.onNotificationUpdateOrReset();
-            }
-
-            if (existing == null && hasRemoteInput) {
-                ViewGroup actionContainer = (FrameLayout) actionContainerCandidate;
-                if (cachedView == null) {
-                    RemoteInputView riv = RemoteInputView.inflate(
-                            mContext, actionContainer, entry, mRemoteInputController);
-
-                    riv.setVisibility(View.INVISIBLE);
-                    actionContainer.addView(riv, new LayoutParams(
-                            ViewGroup.LayoutParams.MATCH_PARENT,
-                            ViewGroup.LayoutParams.MATCH_PARENT)
-                    );
-                    existing = riv;
-                } else {
-                    actionContainer.addView(cachedView);
-                    cachedView.dispatchFinishTemporaryDetach();
-                    cachedView.requestFocus();
-                    existing = cachedView;
-                }
-            }
-            if (hasRemoteInput) {
-                int color = entry.notification.getNotification().color;
-                if (color == Notification.COLOR_DEFAULT) {
-                    color = mContext.getColor(R.color.default_remote_input_background);
-                }
-                existing.setBackgroundColor(ContrastColorUtil.ensureTextBackgroundColor(color,
-                        mContext.getColor(R.color.remote_input_text_enabled),
-                        mContext.getColor(R.color.remote_input_hint)));
-
-                existing.setWrapper(wrapper);
-                existing.setOnVisibilityChangedListener(this::setRemoteInputVisible);
-
-                if (existingPendingIntent != null || existing.isActive()) {
-                    // The current action could be gone, or the pending intent no longer valid.
-                    // If we find a matching action in the new notification, focus, otherwise close.
-                    Notification.Action[] actions = entry.notification.getNotification().actions;
-                    if (existingPendingIntent != null) {
-                        existing.setPendingIntent(existingPendingIntent);
-                    }
-                    if (existing.updatePendingIntentFromActions(actions)) {
-                        if (!existing.isActive()) {
-                            existing.focus();
-                        }
-                    } else {
-                        if (existing.isActive()) {
-                            existing.close();
-                        }
-                    }
-                }
-            }
-            return existing;
-        }
-        return null;
-    }
-
-    private void applySmartReplyView(RemoteInput remoteInput, PendingIntent pendingIntent,
-            NotificationData.Entry entry) {
-        if (mExpandedChild != null) {
-            mExpandedSmartReplyView =
-                    applySmartReplyView(mExpandedChild, remoteInput, pendingIntent, entry);
-            if (mExpandedSmartReplyView != null && remoteInput != null
-                    && remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) {
-                mSmartReplyController.smartRepliesAdded(entry, remoteInput.getChoices().length);
-            }
-        }
-    }
-
-    private SmartReplyView applySmartReplyView(
-            View view, RemoteInput remoteInput, PendingIntent pendingIntent,
-            NotificationData.Entry entry) {
-        View smartReplyContainerCandidate = view.findViewById(
-                com.android.internal.R.id.smart_reply_container);
-        if (!(smartReplyContainerCandidate instanceof LinearLayout)) {
-            return null;
-        }
-        LinearLayout smartReplyContainer = (LinearLayout) smartReplyContainerCandidate;
-        if (remoteInput == null || pendingIntent == null) {
-            smartReplyContainer.setVisibility(View.GONE);
-            return null;
-        }
-        // If we are showing the spinner we don't want to add the buttons.
-        boolean showingSpinner = entry.notification.getNotification()
-                .extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
-        if (showingSpinner) {
-            smartReplyContainer.setVisibility(View.GONE);
-            return null;
-        }
-        // If we are keeping the notification around while sending we don't want to add the buttons.
-        boolean hideSmartReplies = entry.notification.getNotification()
-                .extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false);
-        if (hideSmartReplies) {
-            smartReplyContainer.setVisibility(View.GONE);
-            return null;
-        }
-        SmartReplyView smartReplyView = null;
-        if (smartReplyContainer.getChildCount() == 0) {
-            smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer);
-            smartReplyContainer.addView(smartReplyView);
-        } else if (smartReplyContainer.getChildCount() == 1) {
-            View child = smartReplyContainer.getChildAt(0);
-            if (child instanceof SmartReplyView) {
-                smartReplyView = (SmartReplyView) child;
-            }
-        }
-        if (smartReplyView != null) {
-            smartReplyView.setRepliesFromRemoteInput(remoteInput, pendingIntent,
-                    mSmartReplyController, entry, smartReplyContainer);
-            smartReplyContainer.setVisibility(View.VISIBLE);
-        }
-        return smartReplyView;
-    }
-
-    public void closeRemoteInput() {
-        if (mHeadsUpRemoteInput != null) {
-            mHeadsUpRemoteInput.close();
-        }
-        if (mExpandedRemoteInput != null) {
-            mExpandedRemoteInput.close();
-        }
-    }
-
-    public void setGroupManager(NotificationGroupManager groupManager) {
-        mGroupManager = groupManager;
-    }
-
-    public void setRemoteInputController(RemoteInputController r) {
-        mRemoteInputController = r;
-    }
-
-    public void setExpandClickListener(OnClickListener expandClickListener) {
-        mExpandClickListener = expandClickListener;
-    }
-
-    public void updateExpandButtons(boolean expandable) {
-        mExpandable = expandable;
-        // if the expanded child has the same height as the collapsed one we hide it.
-        if (mExpandedChild != null && mExpandedChild.getHeight() != 0) {
-            if ((!mIsHeadsUp && !mHeadsUpAnimatingAway)
-                    || mHeadsUpChild == null || mContainingNotification.isOnKeyguard()) {
-                if (mExpandedChild.getHeight() <= mContractedChild.getHeight()) {
-                    expandable = false;
-                }
-            } else if (mExpandedChild.getHeight() <= mHeadsUpChild.getHeight()) {
-                expandable = false;
-            }
-        }
-        if (mExpandedChild != null) {
-            mExpandedWrapper.updateExpandability(expandable, mExpandClickListener);
-        }
-        if (mContractedChild != null) {
-            mContractedWrapper.updateExpandability(expandable, mExpandClickListener);
-        }
-        if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.updateExpandability(expandable,  mExpandClickListener);
-        }
-        mIsContentExpandable = expandable;
-    }
-
-    public NotificationHeaderView getNotificationHeader() {
-        NotificationHeaderView header = null;
-        if (mContractedChild != null) {
-            header = mContractedWrapper.getNotificationHeader();
-        }
-        if (header == null && mExpandedChild != null) {
-            header = mExpandedWrapper.getNotificationHeader();
-        }
-        if (header == null && mHeadsUpChild != null) {
-            header = mHeadsUpWrapper.getNotificationHeader();
-        }
-        if (header == null && mAmbientChild != null) {
-            header = mAmbientWrapper.getNotificationHeader();
-        }
-        return header;
-    }
-
-    public void showAppOpsIcons(ArraySet<Integer> activeOps) {
-        if (mContractedChild != null && mContractedWrapper.getNotificationHeader() != null) {
-            mContractedWrapper.getNotificationHeader().showAppOpsIcons(activeOps);
-        }
-        if (mExpandedChild != null && mExpandedWrapper.getNotificationHeader() != null) {
-            mExpandedWrapper.getNotificationHeader().showAppOpsIcons(activeOps);
-        }
-        if (mHeadsUpChild != null && mHeadsUpWrapper.getNotificationHeader() != null) {
-            mHeadsUpWrapper.getNotificationHeader().showAppOpsIcons(activeOps);
-        }
-    }
-
-    public NotificationHeaderView getContractedNotificationHeader() {
-        if (mContractedChild != null) {
-            return mContractedWrapper.getNotificationHeader();
-        }
-        return null;
-    }
-
-    public NotificationHeaderView getVisibleNotificationHeader() {
-        NotificationViewWrapper wrapper = getVisibleWrapper(mVisibleType);
-        return wrapper == null ? null : wrapper.getNotificationHeader();
-    }
-
-    public void setContainingNotification(ExpandableNotificationRow containingNotification) {
-        mContainingNotification = containingNotification;
-    }
-
-    public void requestSelectLayout(boolean needsAnimation) {
-        selectLayout(needsAnimation, false);
-    }
-
-    public void reInflateViews() {
-        if (mIsChildInGroup && mSingleLineView != null) {
-            removeView(mSingleLineView);
-            mSingleLineView = null;
-            updateAllSingleLineViews();
-        }
-    }
-
-    public void setUserExpanding(boolean userExpanding) {
-        mUserExpanding = userExpanding;
-        if (userExpanding) {
-            mTransformationStartVisibleType = mVisibleType;
-        } else {
-            mTransformationStartVisibleType = UNDEFINED;
-            mVisibleType = calculateVisibleType();
-            updateViewVisibilities(mVisibleType);
-            updateBackgroundColor(false);
-        }
-    }
-
-    /**
-     * Set by how much the single line view should be indented. Used when a overflow indicator is
-     * present and only during measuring
-     */
-    public void setSingleLineWidthIndention(int singleLineWidthIndention) {
-        if (singleLineWidthIndention != mSingleLineWidthIndention) {
-            mSingleLineWidthIndention = singleLineWidthIndention;
-            mContainingNotification.forceLayout();
-            forceLayout();
-        }
-    }
-
-    public HybridNotificationView getSingleLineView() {
-        return mSingleLineView;
-    }
-
-    public void setRemoved() {
-        if (mExpandedRemoteInput != null) {
-            mExpandedRemoteInput.setRemoved();
-        }
-        if (mHeadsUpRemoteInput != null) {
-            mHeadsUpRemoteInput.setRemoved();
-        }
-    }
-
-    public void setContentHeightAnimating(boolean animating) {
-        if (!animating) {
-            mContentHeightAtAnimationStart = UNDEFINED;
-        }
-    }
-
-    @VisibleForTesting
-    boolean isAnimatingVisibleType() {
-        return mAnimationStartVisibleType != UNDEFINED;
-    }
-
-    public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
-        mHeadsUpAnimatingAway = headsUpAnimatingAway;
-        selectLayout(false /* animate */, true /* force */);
-    }
-
-    public void setFocusOnVisibilityChange() {
-        mFocusOnVisibilityChange = true;
-    }
-
-    public void setIconsVisible(boolean iconsVisible) {
-        mIconsVisible = iconsVisible;
-        updateIconVisibilities();
-    }
-
-    private void updateIconVisibilities() {
-        if (mContractedWrapper != null) {
-            NotificationHeaderView header = mContractedWrapper.getNotificationHeader();
-            if (header != null) {
-                header.getIcon().setForceHidden(!mIconsVisible);
-            }
-        }
-        if (mHeadsUpWrapper != null) {
-            NotificationHeaderView header = mHeadsUpWrapper.getNotificationHeader();
-            if (header != null) {
-                header.getIcon().setForceHidden(!mIconsVisible);
-            }
-        }
-        if (mExpandedWrapper != null) {
-            NotificationHeaderView header = mExpandedWrapper.getNotificationHeader();
-            if (header != null) {
-                header.getIcon().setForceHidden(!mIconsVisible);
-            }
-        }
-    }
-
-    @Override
-    public void onVisibilityAggregated(boolean isVisible) {
-        super.onVisibilityAggregated(isVisible);
-        if (isVisible) {
-            fireExpandedVisibleListenerIfVisible();
-        }
-    }
-
-    /**
-     * Sets a one-shot listener for when the expanded view becomes visible.
-     *
-     * This will fire the listener immediately if the expanded view is already visible.
-     */
-    public void setOnExpandedVisibleListener(Runnable r) {
-        mExpandedVisibleListener = r;
-        fireExpandedVisibleListenerIfVisible();
-    }
-
-    public void setIsLowPriority(boolean isLowPriority) {
-        mIsLowPriority = isLowPriority;
-    }
-
-    public boolean isDimmable() {
-        if (!mContractedWrapper.isDimmable()) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Should a single click be disallowed on this view when on the keyguard?
-     */
-    public boolean disallowSingleClick(float x, float y) {
-        NotificationViewWrapper visibleWrapper = getVisibleWrapper(getVisibleType());
-        if (visibleWrapper != null) {
-            return visibleWrapper.disallowSingleClick(x, y);
-        }
-        return false;
-    }
-
-    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
-        boolean needsPaddings = shouldClipToRounding(getVisibleType(), topRounded, bottomRounded);
-        if (mUserExpanding) {
-             needsPaddings |= shouldClipToRounding(mTransformationStartVisibleType, topRounded,
-                     bottomRounded);
-        }
-        return needsPaddings;
-    }
-
-    private boolean shouldClipToRounding(int visibleType, boolean topRounded,
-            boolean bottomRounded) {
-        NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
-        if (visibleWrapper == null) {
-            return false;
-        }
-        return visibleWrapper.shouldClipToRounding(topRounded, bottomRounded);
-    }
-
-    public CharSequence getActiveRemoteInputText() {
-        if (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive()) {
-            return mExpandedRemoteInput.getText();
-        }
-        if (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive()) {
-            return mHeadsUpRemoteInput.getText();
-        }
-        return null;
-    }
-
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        float y = ev.getY();
-        // We still want to distribute touch events to the remote input even if it's outside the
-        // view boundary. We're therefore manually dispatching these events to the remote view
-        RemoteInputView riv = getRemoteInputForView(getViewForVisibleType(mVisibleType));
-        if (riv != null && riv.getVisibility() == VISIBLE) {
-            int inputStart = mUnrestrictedContentHeight - riv.getHeight();
-            if (y <= mUnrestrictedContentHeight && y >= inputStart) {
-                ev.offsetLocation(0, -inputStart);
-                return riv.dispatchTouchEvent(ev);
-            }
-        }
-        return super.dispatchTouchEvent(ev);
-    }
-
-    /**
-     * Overridden to make sure touches to the reply action bar actually go through to this view
-     */
-    @Override
-    public boolean pointInView(float localX, float localY, float slop) {
-        float top = mClipTopAmount;
-        float bottom = mUnrestrictedContentHeight;
-        return localX >= -slop && localY >= top - slop && localX < ((mRight - mLeft) + slop) &&
-                localY < (bottom + slop);
-    }
-
-    private RemoteInputView getRemoteInputForView(View child) {
-        if (child == mExpandedChild) {
-            return mExpandedRemoteInput;
-        } else if (child == mHeadsUpChild) {
-            return mHeadsUpRemoteInput;
-        }
-        return null;
-    }
-
-    public int getExpandHeight() {
-        int viewType = VISIBLE_TYPE_EXPANDED;
-        if (mExpandedChild == null) {
-            viewType = VISIBLE_TYPE_CONTRACTED;
-        }
-        return getViewHeight(viewType) + getExtraRemoteInputHeight(mExpandedRemoteInput);
-    }
-
-    public int getHeadsUpHeight() {
-        int viewType = VISIBLE_TYPE_HEADSUP;
-        if (mHeadsUpChild == null) {
-            viewType = VISIBLE_TYPE_CONTRACTED;
-        }
-        // The headsUp remote input quickly switches to the expanded one, so lets also include that
-        // one
-        return getViewHeight(viewType) + getExtraRemoteInputHeight(mHeadsUpRemoteInput)
-                + getExtraRemoteInputHeight(mExpandedRemoteInput);
-    }
-
-    public void setRemoteInputVisible(boolean remoteInputVisible) {
-        mRemoteInputVisible = remoteInputVisible;
-        setClipChildren(!remoteInputVisible);
-    }
-
-    @Override
-    public void setClipChildren(boolean clipChildren) {
-        clipChildren = clipChildren && !mRemoteInputVisible;
-        super.setClipChildren(clipChildren);
-    }
-
-    public void setHeaderVisibleAmount(float headerVisibleAmount) {
-        if (mContractedWrapper != null) {
-            mContractedWrapper.setHeaderVisibleAmount(headerVisibleAmount);
-        }
-        if (mHeadsUpWrapper != null) {
-            mHeadsUpWrapper.setHeaderVisibleAmount(headerVisibleAmount);
-        }
-        if (mExpandedWrapper != null) {
-            mExpandedWrapper.setHeaderVisibleAmount(headerVisibleAmount);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
deleted file mode 100644
index a58752c..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ /dev/null
@@ -1,841 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static android.app.Notification.CATEGORY_ALARM;
-import static android.app.Notification.CATEGORY_CALL;
-import static android.app.Notification.CATEGORY_EVENT;
-import static android.app.Notification.CATEGORY_MESSAGE;
-import static android.app.Notification.CATEGORY_REMINDER;
-import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
-import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
-import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
-import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
-import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
-
-import android.Manifest;
-import android.app.AppGlobals;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.Person;
-import android.content.Context;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Icon;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.service.notification.NotificationListenerService.Ranking;
-import android.service.notification.NotificationListenerService.RankingMap;
-import android.service.notification.SnoozeCriterion;
-import android.service.notification.StatusBarNotification;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.RemoteViews;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.ContrastColorUtil;
-import com.android.systemui.Dependency;
-import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.statusbar.notification.InflationException;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.ZenModeController;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * The list of currently displaying notifications.
- */
-public class NotificationData {
-
-    private final Environment mEnvironment;
-    private HeadsUpManager mHeadsUpManager;
-
-    final ZenModeController mZen = Dependency.get(ZenModeController.class);
-    final ForegroundServiceController mFsc = Dependency.get(ForegroundServiceController.class);
-
-    public static final class Entry {
-        private static final long LAUNCH_COOLDOWN = 2000;
-        private static final long REMOTE_INPUT_COOLDOWN = 500;
-        private static final long INITIALIZATION_DELAY = 400;
-        private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
-        private static final int COLOR_INVALID = 1;
-        public String key;
-        public StatusBarNotification notification;
-        public NotificationChannel channel;
-        public StatusBarIconView icon;
-        public StatusBarIconView expandedIcon;
-        public ExpandableNotificationRow row; // the outer expanded view
-        private boolean interruption;
-        public boolean autoRedacted; // whether the redacted notification was generated by us
-        public int targetSdk;
-        private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET;
-        public RemoteViews cachedContentView;
-        public RemoteViews cachedBigContentView;
-        public RemoteViews cachedHeadsUpContentView;
-        public RemoteViews cachedPublicContentView;
-        public RemoteViews cachedAmbientContentView;
-        public CharSequence remoteInputText;
-        public List<SnoozeCriterion> snoozeCriteria;
-        public int userSentiment = Ranking.USER_SENTIMENT_NEUTRAL;
-
-        private int mCachedContrastColor = COLOR_INVALID;
-        private int mCachedContrastColorIsFor = COLOR_INVALID;
-        private InflationTask mRunningTask = null;
-        private Throwable mDebugThrowable;
-        public CharSequence remoteInputTextWhenReset;
-        public long lastRemoteInputSent = NOT_LAUNCHED_YET;
-        public ArraySet<Integer> mActiveAppOps = new ArraySet<>(3);
-        public CharSequence headsUpStatusBarText;
-        public CharSequence headsUpStatusBarTextPublic;
-
-        private long initializationTime = -1;
-
-        /**
-         * Whether or not this row represents a system notification. Note that if this is
-         * {@code null}, that means we were either unable to retrieve the info or have yet to
-         * retrieve the info.
-         */
-        public Boolean mIsSystemNotification;
-
-        /**
-         * Has the user sent a reply through this Notification.
-         */
-        private boolean hasSentReply;
-
-        public Entry(StatusBarNotification n) {
-            this.key = n.getKey();
-            this.notification = n;
-        }
-
-        public void setInterruption() {
-            interruption = true;
-        }
-
-        public boolean hasInterrupted() {
-            return interruption;
-        }
-
-        /**
-         * Resets the notification entry to be re-used.
-         */
-        public void reset() {
-            if (row != null) {
-                row.reset();
-            }
-        }
-
-        public View getExpandedContentView() {
-            return row.getPrivateLayout().getExpandedChild();
-        }
-
-        public View getPublicContentView() {
-            return row.getPublicLayout().getContractedChild();
-        }
-
-        public void notifyFullScreenIntentLaunched() {
-            setInterruption();
-            lastFullScreenIntentLaunchTime = SystemClock.elapsedRealtime();
-        }
-
-        public boolean hasJustLaunchedFullScreenIntent() {
-            return SystemClock.elapsedRealtime() < lastFullScreenIntentLaunchTime + LAUNCH_COOLDOWN;
-        }
-
-        public boolean hasJustSentRemoteInput() {
-            return SystemClock.elapsedRealtime() < lastRemoteInputSent + REMOTE_INPUT_COOLDOWN;
-        }
-
-        public boolean hasFinishedInitialization() {
-            return initializationTime == -1 ||
-                    SystemClock.elapsedRealtime() > initializationTime + INITIALIZATION_DELAY;
-        }
-
-        /**
-         * Create the icons for a notification
-         * @param context the context to create the icons with
-         * @param sbn the notification
-         * @throws InflationException
-         */
-        public void createIcons(Context context, StatusBarNotification sbn)
-                throws InflationException {
-            Notification n = sbn.getNotification();
-            final Icon smallIcon = n.getSmallIcon();
-            if (smallIcon == null) {
-                throw new InflationException("No small icon in notification from "
-                        + sbn.getPackageName());
-            }
-
-            // Construct the icon.
-            icon = new StatusBarIconView(context,
-                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
-            icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
-
-            // Construct the expanded icon.
-            expandedIcon = new StatusBarIconView(context,
-                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
-            expandedIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
-            final StatusBarIcon ic = new StatusBarIcon(
-                    sbn.getUser(),
-                    sbn.getPackageName(),
-                    smallIcon,
-                    n.iconLevel,
-                    n.number,
-                    StatusBarIconView.contentDescForNotification(context, n));
-            if (!icon.set(ic) || !expandedIcon.set(ic)) {
-                icon = null;
-                expandedIcon = null;
-                throw new InflationException("Couldn't create icon: " + ic);
-            }
-            expandedIcon.setVisibility(View.INVISIBLE);
-            expandedIcon.setOnVisibilityChangedListener(
-                    newVisibility -> {
-                        if (row != null) {
-                            row.setIconsVisible(newVisibility != View.VISIBLE);
-                        }
-                    });
-        }
-
-        public void setIconTag(int key, Object tag) {
-            if (icon != null) {
-                icon.setTag(key, tag);
-                expandedIcon.setTag(key, tag);
-            }
-        }
-
-        /**
-         * Update the notification icons.
-         * @param context the context to create the icons with.
-         * @param sbn the notification to read the icon from.
-         * @throws InflationException
-         */
-        public void updateIcons(Context context, StatusBarNotification sbn)
-                throws InflationException {
-            if (icon != null) {
-                // Update the icon
-                Notification n = sbn.getNotification();
-                final StatusBarIcon ic = new StatusBarIcon(
-                        notification.getUser(),
-                        notification.getPackageName(),
-                        n.getSmallIcon(),
-                        n.iconLevel,
-                        n.number,
-                        StatusBarIconView.contentDescForNotification(context, n));
-                icon.setNotification(sbn);
-                expandedIcon.setNotification(sbn);
-                if (!icon.set(ic) || !expandedIcon.set(ic)) {
-                    throw new InflationException("Couldn't update icon: " + ic);
-                }
-            }
-        }
-
-        public int getContrastedColor(Context context, boolean isLowPriority,
-                int backgroundColor) {
-            int rawColor = isLowPriority ? Notification.COLOR_DEFAULT :
-                    notification.getNotification().color;
-            if (mCachedContrastColorIsFor == rawColor && mCachedContrastColor != COLOR_INVALID) {
-                return mCachedContrastColor;
-            }
-            final int contrasted = ContrastColorUtil.resolveContrastColor(context, rawColor,
-                    backgroundColor);
-            mCachedContrastColorIsFor = rawColor;
-            mCachedContrastColor = contrasted;
-            return mCachedContrastColor;
-        }
-
-        /**
-         * Abort all existing inflation tasks
-         */
-        public void abortTask() {
-            if (mRunningTask != null) {
-                mRunningTask.abort();
-                mRunningTask = null;
-            }
-        }
-
-        public void setInflationTask(InflationTask abortableTask) {
-            // abort any existing inflation
-            InflationTask existing = mRunningTask;
-            abortTask();
-            mRunningTask = abortableTask;
-            if (existing != null && mRunningTask != null) {
-                mRunningTask.supersedeTask(existing);
-            }
-        }
-
-        public void onInflationTaskFinished() {
-           mRunningTask = null;
-        }
-
-        @VisibleForTesting
-        public InflationTask getRunningTask() {
-            return mRunningTask;
-        }
-
-        /**
-         * Set a throwable that is used for debugging
-         *
-         * @param debugThrowable the throwable to save
-         */
-        public void setDebugThrowable(Throwable debugThrowable) {
-            mDebugThrowable = debugThrowable;
-        }
-
-        public Throwable getDebugThrowable() {
-            return mDebugThrowable;
-        }
-
-        public void onRemoteInputInserted() {
-            lastRemoteInputSent = NOT_LAUNCHED_YET;
-            remoteInputTextWhenReset = null;
-        }
-
-        public void setHasSentReply() {
-            hasSentReply = true;
-        }
-
-        public boolean isLastMessageFromReply() {
-            if (!hasSentReply) {
-                return false;
-            }
-            Bundle extras = notification.getNotification().extras;
-            CharSequence[] replyTexts = extras.getCharSequenceArray(
-                    Notification.EXTRA_REMOTE_INPUT_HISTORY);
-            if (!ArrayUtils.isEmpty(replyTexts)) {
-                return true;
-            }
-            Parcelable[] messages = extras.getParcelableArray(Notification.EXTRA_MESSAGES);
-            if (messages != null && messages.length > 0) {
-                Parcelable message = messages[messages.length - 1];
-                if (message instanceof Bundle) {
-                    Notification.MessagingStyle.Message lastMessage =
-                            Notification.MessagingStyle.Message.getMessageFromBundle(
-                                    (Bundle) message);
-                    if (lastMessage != null) {
-                        Person senderPerson = lastMessage.getSenderPerson();
-                        if (senderPerson == null) {
-                            return true;
-                        }
-                        Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON);
-                        return Objects.equals(user, senderPerson);
-                    }
-                }
-            }
-            return false;
-        }
-
-        public void setInitializationTime(long time) {
-            if (initializationTime == -1) {
-                initializationTime = time;
-            }
-        }
-    }
-
-    private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
-    private final ArrayList<Entry> mSortedAndFiltered = new ArrayList<>();
-    private final ArrayList<Entry> mFilteredForUser = new ArrayList<>();
-
-    private NotificationGroupManager mGroupManager;
-
-    private RankingMap mRankingMap;
-    private final Ranking mTmpRanking = new Ranking();
-
-    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
-        mHeadsUpManager = headsUpManager;
-    }
-
-    private final Comparator<Entry> mRankingComparator = new Comparator<Entry>() {
-        private final Ranking mRankingA = new Ranking();
-        private final Ranking mRankingB = new Ranking();
-
-        @Override
-        public int compare(Entry a, Entry b) {
-            final StatusBarNotification na = a.notification;
-            final StatusBarNotification nb = b.notification;
-            int aImportance = NotificationManager.IMPORTANCE_DEFAULT;
-            int bImportance = NotificationManager.IMPORTANCE_DEFAULT;
-            int aRank = 0;
-            int bRank = 0;
-
-            if (mRankingMap != null) {
-                // RankingMap as received from NoMan
-                getRanking(a.key, mRankingA);
-                getRanking(b.key, mRankingB);
-                aImportance = mRankingA.getImportance();
-                bImportance = mRankingB.getImportance();
-                aRank = mRankingA.getRank();
-                bRank = mRankingB.getRank();
-            }
-
-            String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
-
-            // IMPORTANCE_MIN media streams are allowed to drift to the bottom
-            final boolean aMedia = a.key.equals(mediaNotification)
-                    && aImportance > NotificationManager.IMPORTANCE_MIN;
-            final boolean bMedia = b.key.equals(mediaNotification)
-                    && bImportance > NotificationManager.IMPORTANCE_MIN;
-
-            boolean aSystemMax = aImportance >= NotificationManager.IMPORTANCE_HIGH &&
-                    isSystemNotification(na);
-            boolean bSystemMax = bImportance >= NotificationManager.IMPORTANCE_HIGH &&
-                    isSystemNotification(nb);
-
-            boolean isHeadsUp = a.row.isHeadsUp();
-            if (isHeadsUp != b.row.isHeadsUp()) {
-                return isHeadsUp ? -1 : 1;
-            } else if (isHeadsUp) {
-                // Provide consistent ranking with headsUpManager
-                return mHeadsUpManager.compare(a, b);
-            } else if (aMedia != bMedia) {
-                // Upsort current media notification.
-                return aMedia ? -1 : 1;
-            } else if (aSystemMax != bSystemMax) {
-                // Upsort PRIORITY_MAX system notifications
-                return aSystemMax ? -1 : 1;
-            } else if (aRank != bRank) {
-                return aRank - bRank;
-            } else {
-                return Long.compare(nb.getNotification().when, na.getNotification().when);
-            }
-        }
-    };
-
-    public NotificationData(Environment environment) {
-        mEnvironment = environment;
-        mGroupManager = environment.getGroupManager();
-    }
-
-    /**
-     * Returns the sorted list of active notifications (depending on {@link Environment}
-     *
-     * <p>
-     * This call doesn't update the list of active notifications. Call {@link #filterAndSort()}
-     * when the environment changes.
-     * <p>
-     * Don't hold on to or modify the returned list.
-     */
-    public ArrayList<Entry> getActiveNotifications() {
-        return mSortedAndFiltered;
-    }
-
-    public ArrayList<Entry> getNotificationsForCurrentUser() {
-        mFilteredForUser.clear();
-
-        synchronized (mEntries) {
-            final int N = mEntries.size();
-            for (int i = 0; i < N; i++) {
-                Entry entry = mEntries.valueAt(i);
-                final StatusBarNotification sbn = entry.notification;
-                if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) {
-                    continue;
-                }
-                mFilteredForUser.add(entry);
-            }
-        }
-        return mFilteredForUser;
-    }
-
-    public Entry get(String key) {
-        return mEntries.get(key);
-    }
-
-    public void add(Entry entry) {
-        synchronized (mEntries) {
-            mEntries.put(entry.notification.getKey(), entry);
-        }
-        mGroupManager.onEntryAdded(entry);
-
-        updateRankingAndSort(mRankingMap);
-    }
-
-    public Entry remove(String key, RankingMap ranking) {
-        Entry removed = null;
-        synchronized (mEntries) {
-            removed = mEntries.remove(key);
-        }
-        if (removed == null) return null;
-        mGroupManager.onEntryRemoved(removed);
-        updateRankingAndSort(ranking);
-        return removed;
-    }
-
-    public void updateRanking(RankingMap ranking) {
-        updateRankingAndSort(ranking);
-    }
-
-    public void updateAppOp(int appOp, int uid, String pkg, String key, boolean showIcon) {
-        synchronized (mEntries) {
-            final int N = mEntries.size();
-            for (int i = 0; i < N; i++) {
-                Entry entry = mEntries.valueAt(i);
-                if (uid == entry.notification.getUid()
-                        && pkg.equals(entry.notification.getPackageName())
-                        && key.equals(entry.key)) {
-                    if (showIcon) {
-                        entry.mActiveAppOps.add(appOp);
-                    } else {
-                        entry.mActiveAppOps.remove(appOp);
-                    }
-                }
-            }
-        }
-    }
-
-    public boolean isAmbient(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.isAmbient();
-        }
-        return false;
-    }
-
-    public int getVisibilityOverride(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getVisibilityOverride();
-        }
-        return Ranking.VISIBILITY_NO_OVERRIDE;
-    }
-
-    public boolean shouldSuppressFullScreenIntent(Entry entry) {
-        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
-    }
-
-    public boolean shouldSuppressPeek(Entry entry) {
-        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_PEEK);
-    }
-
-    public boolean shouldSuppressStatusBar(Entry entry) {
-        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_STATUS_BAR);
-    }
-
-    public boolean shouldSuppressAmbient(Entry entry) {
-        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_AMBIENT);
-    }
-
-    public boolean shouldSuppressNotificationList(Entry entry) {
-        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_NOTIFICATION_LIST);
-    }
-
-    private boolean shouldSuppressVisualEffect(Entry entry, int effect) {
-        if (isExemptFromDndVisualSuppression(entry)) {
-            return false;
-        }
-        String key = entry.key;
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return (mTmpRanking.getSuppressedVisualEffects() & effect) != 0;
-        }
-        return false;
-    }
-
-    protected boolean isExemptFromDndVisualSuppression(Entry entry) {
-        if (isNotificationBlockedByPolicy(entry.notification.getNotification())) {
-            return false;
-        }
-
-        if ((entry.notification.getNotification().flags
-                & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
-            return true;
-        }
-        if (entry.notification.getNotification().isMediaNotification()) {
-            return true;
-        }
-        if (entry.mIsSystemNotification != null && entry.mIsSystemNotification) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Categories that are explicitly called out on DND settings screens are always blocked, if
-     * DND has flagged them, even if they are foreground or system notifications that might
-     * otherwise visually bypass DND.
-     */
-    protected boolean isNotificationBlockedByPolicy(Notification n) {
-        if (isCategory(CATEGORY_CALL, n)
-                || isCategory(CATEGORY_MESSAGE, n)
-                || isCategory(CATEGORY_ALARM, n)
-                || isCategory(CATEGORY_EVENT, n)
-                || isCategory(CATEGORY_REMINDER, n)) {
-            return true;
-        }
-        return false;
-    }
-
-    private boolean isCategory(String category, Notification n) {
-        return Objects.equals(n.category, category);
-    }
-
-    public int getImportance(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getImportance();
-        }
-        return NotificationManager.IMPORTANCE_UNSPECIFIED;
-    }
-
-    public String getOverrideGroupKey(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getOverrideGroupKey();
-        }
-         return null;
-    }
-
-    public List<SnoozeCriterion> getSnoozeCriteria(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getSnoozeCriteria();
-        }
-        return null;
-    }
-
-    public NotificationChannel getChannel(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getChannel();
-        }
-        return null;
-    }
-
-    public int getRank(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getRank();
-        }
-        return 0;
-    }
-
-    public boolean shouldHide(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.isSuspended();
-        }
-        return false;
-    }
-
-    private void updateRankingAndSort(RankingMap ranking) {
-        if (ranking != null) {
-            mRankingMap = ranking;
-            synchronized (mEntries) {
-                final int N = mEntries.size();
-                for (int i = 0; i < N; i++) {
-                    Entry entry = mEntries.valueAt(i);
-                    if (!getRanking(entry.key, mTmpRanking)) {
-                        continue;
-                    }
-                    final StatusBarNotification oldSbn = entry.notification.cloneLight();
-                    final String overrideGroupKey = getOverrideGroupKey(entry.key);
-                    if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
-                        entry.notification.setOverrideGroupKey(overrideGroupKey);
-                        mGroupManager.onEntryUpdated(entry, oldSbn);
-                    }
-                    entry.channel = getChannel(entry.key);
-                    entry.snoozeCriteria = getSnoozeCriteria(entry.key);
-                    entry.userSentiment = mTmpRanking.getUserSentiment();
-                }
-            }
-        }
-        filterAndSort();
-    }
-
-    /**
-     * Get the ranking from the current ranking map.
-     *
-     * @param key the key to look up
-     * @param outRanking the ranking to populate
-     *
-     * @return {@code true} if the ranking was properly obtained.
-     */
-    @VisibleForTesting
-    protected boolean getRanking(String key, Ranking outRanking) {
-        return mRankingMap.getRanking(key, outRanking);
-    }
-
-    // TODO: This should not be public. Instead the Environment should notify this class when
-    // anything changed, and this class should call back the UI so it updates itself.
-    public void filterAndSort() {
-        mSortedAndFiltered.clear();
-
-        synchronized (mEntries) {
-            final int N = mEntries.size();
-            for (int i = 0; i < N; i++) {
-                Entry entry = mEntries.valueAt(i);
-
-                if (shouldFilterOut(entry)) {
-                    continue;
-                }
-
-                mSortedAndFiltered.add(entry);
-            }
-        }
-
-        Collections.sort(mSortedAndFiltered, mRankingComparator);
-    }
-
-    /**
-     * @return true if this notification should NOT be shown right now
-     */
-    public boolean shouldFilterOut(Entry entry) {
-        final StatusBarNotification sbn = entry.notification;
-        if (!(mEnvironment.isDeviceProvisioned() ||
-                showNotificationEvenIfUnprovisioned(sbn))) {
-            return true;
-        }
-
-        if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) {
-            return true;
-        }
-
-        if (mEnvironment.isSecurelyLocked(sbn.getUserId()) &&
-                (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
-                        || mEnvironment.shouldHideNotifications(sbn.getUserId())
-                        || mEnvironment.shouldHideNotifications(sbn.getKey()))) {
-            return true;
-        }
-
-        if (mEnvironment.isDozing() && shouldSuppressAmbient(entry)) {
-            return true;
-        }
-
-        if (!mEnvironment.isDozing() && shouldSuppressNotificationList(entry)) {
-            return true;
-        }
-
-        if (shouldHide(sbn.getKey())) {
-            return true;
-        }
-
-        if (!StatusBar.ENABLE_CHILD_NOTIFICATIONS
-                && mGroupManager.isChildInGroupWithSummary(sbn)) {
-            return true;
-        }
-
-        if (mFsc.isDungeonNotification(sbn) && !mFsc.isDungeonNeededForUser(sbn.getUserId())) {
-            // this is a foreground-service disclosure for a user that does not need to show one
-            return true;
-        }
-        if (mFsc.isSystemAlertNotification(sbn)) {
-            final String[] apps = sbn.getNotification().extras.getStringArray(
-                    Notification.EXTRA_FOREGROUND_APPS);
-            if (apps != null && apps.length >= 1) {
-                if (!mFsc.isSystemAlertWarningNeeded(sbn.getUserId(), apps[0])) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    // Q: What kinds of notifications should show during setup?
-    // A: Almost none! Only things coming from packages with permission
-    // android.permission.NOTIFICATION_DURING_SETUP that also have special "kind" tags marking them
-    // as relevant for setup (see below).
-    public static boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
-        return showNotificationEvenIfUnprovisioned(AppGlobals.getPackageManager(), sbn);
-    }
-
-    @VisibleForTesting
-    static boolean showNotificationEvenIfUnprovisioned(IPackageManager packageManager,
-            StatusBarNotification sbn) {
-        return checkUidPermission(packageManager, Manifest.permission.NOTIFICATION_DURING_SETUP,
-                sbn.getUid()) == PackageManager.PERMISSION_GRANTED
-                && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
-    }
-
-    private static int checkUidPermission(IPackageManager packageManager, String permission,
-            int uid) {
-        try {
-            return packageManager.checkUidPermission(permission, uid);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    public void dump(PrintWriter pw, String indent) {
-        int N = mSortedAndFiltered.size();
-        pw.print(indent);
-        pw.println("active notifications: " + N);
-        int active;
-        for (active = 0; active < N; active++) {
-            NotificationData.Entry e = mSortedAndFiltered.get(active);
-            dumpEntry(pw, indent, active, e);
-        }
-        synchronized (mEntries) {
-            int M = mEntries.size();
-            pw.print(indent);
-            pw.println("inactive notifications: " + (M - active));
-            int inactiveCount = 0;
-            for (int i = 0; i < M; i++) {
-                Entry entry = mEntries.valueAt(i);
-                if (!mSortedAndFiltered.contains(entry)) {
-                    dumpEntry(pw, indent, inactiveCount, entry);
-                    inactiveCount++;
-                }
-            }
-        }
-    }
-
-    private void dumpEntry(PrintWriter pw, String indent, int i, Entry e) {
-        getRanking(e.key, mTmpRanking);
-        pw.print(indent);
-        pw.println("  [" + i + "] key=" + e.key + " icon=" + e.icon);
-        StatusBarNotification n = e.notification;
-        pw.print(indent);
-        pw.println("      pkg=" + n.getPackageName() + " id=" + n.getId() + " importance=" +
-                mTmpRanking.getImportance());
-        pw.print(indent);
-        pw.println("      notification=" + n.getNotification());
-    }
-
-    private static boolean isSystemNotification(StatusBarNotification sbn) {
-        String sbnPackage = sbn.getPackageName();
-        return "android".equals(sbnPackage) || "com.android.systemui".equals(sbnPackage);
-    }
-
-    /**
-     * Provides access to keyguard state and user settings dependent data.
-     */
-    public interface Environment {
-        public boolean isSecurelyLocked(int userId);
-        public boolean shouldHideNotifications(int userid);
-        public boolean shouldHideNotifications(String key);
-        public boolean isDeviceProvisioned();
-        public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
-        public String getCurrentMediaNotificationKey();
-        public NotificationGroupManager getGroupManager();
-        /**
-         * @return true iff the device is dozing
-         */
-        boolean isDozing();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
deleted file mode 100644
index 06f26c9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
+++ /dev/null
@@ -1,1092 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.systemui.statusbar;
-
-import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
-import static com.android.systemui.statusbar.NotificationRemoteInputManager
-        .FORCE_REMOTE_INPUT_HISTORY;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.database.ContentObserver;
-import android.os.Build;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationStats;
-import android.service.notification.StatusBarNotification;
-import android.text.TextUtils;
-import android.util.ArraySet;
-import android.util.EventLog;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.internal.util.NotificationMessagingUtil;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.Dependency;
-import com.android.systemui.Dumpable;
-import com.android.systemui.EventLogTags;
-import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.R;
-import com.android.systemui.UiOffloadThread;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.statusbar.notification.InflationException;
-import com.android.systemui.statusbar.notification.NotificationInflater;
-import com.android.systemui.statusbar.notification.RowInflaterTask;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.util.leak.LeakDetector;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * NotificationEntryManager is responsible for the adding, removing, and updating of notifications.
- * It also handles tasks such as their inflation and their interaction with other
- * Notification.*Manager objects.
- */
-public class NotificationEntryManager implements Dumpable, NotificationInflater.InflationCallback,
-        ExpandableNotificationRow.ExpansionLogger, NotificationUpdateHandler,
-        VisualStabilityManager.Callback {
-    private static final String TAG = "NotificationEntryMgr";
-    protected static final boolean DEBUG = false;
-    protected static final boolean ENABLE_HEADS_UP = true;
-    protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
-
-    protected final NotificationMessagingUtil mMessagingUtil;
-    protected final Context mContext;
-    protected final HashMap<String, NotificationData.Entry> mPendingNotifications = new HashMap<>();
-    protected final NotificationClicker mNotificationClicker = new NotificationClicker();
-    protected final ArraySet<NotificationData.Entry> mHeadsUpEntriesToRemoveOnSwitch =
-            new ArraySet<>();
-
-    // Dependencies:
-    protected final NotificationLockscreenUserManager mLockscreenUserManager =
-            Dependency.get(NotificationLockscreenUserManager.class);
-    protected final NotificationGroupManager mGroupManager =
-            Dependency.get(NotificationGroupManager.class);
-    protected final NotificationGutsManager mGutsManager =
-            Dependency.get(NotificationGutsManager.class);
-    protected final NotificationRemoteInputManager mRemoteInputManager =
-            Dependency.get(NotificationRemoteInputManager.class);
-    protected final NotificationMediaManager mMediaManager =
-            Dependency.get(NotificationMediaManager.class);
-    protected final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
-    protected final DeviceProvisionedController mDeviceProvisionedController =
-            Dependency.get(DeviceProvisionedController.class);
-    protected final VisualStabilityManager mVisualStabilityManager =
-            Dependency.get(VisualStabilityManager.class);
-    protected final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
-    protected final ForegroundServiceController mForegroundServiceController =
-            Dependency.get(ForegroundServiceController.class);
-    protected final NotificationListener mNotificationListener =
-            Dependency.get(NotificationListener.class);
-    private final SmartReplyController mSmartReplyController =
-            Dependency.get(SmartReplyController.class);
-
-    protected IStatusBarService mBarService;
-    protected NotificationPresenter mPresenter;
-    protected Callback mCallback;
-    protected PowerManager mPowerManager;
-    protected SystemServicesProxy mSystemServicesProxy;
-    protected NotificationListenerService.RankingMap mLatestRankingMap;
-    protected HeadsUpManager mHeadsUpManager;
-    protected NotificationData mNotificationData;
-    protected ContentObserver mHeadsUpObserver;
-    protected boolean mUseHeadsUp = false;
-    protected boolean mDisableNotificationAlerts;
-    protected NotificationListContainer mListContainer;
-    private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
-    /**
-     * Notifications with keys in this set are not actually around anymore. We kept them around
-     * when they were canceled in response to a remote input interaction. This allows us to show
-     * what you replied and allows you to continue typing into it.
-     */
-    private final ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>();
-
-
-    private final class NotificationClicker implements View.OnClickListener {
-
-        @Override
-        public void onClick(final View v) {
-            if (!(v instanceof ExpandableNotificationRow)) {
-                Log.e(TAG, "NotificationClicker called on a view that is not a notification row.");
-                return;
-            }
-
-            mPresenter.wakeUpIfDozing(SystemClock.uptimeMillis(), v);
-
-            final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-            final StatusBarNotification sbn = row.getStatusBarNotification();
-            if (sbn == null) {
-                Log.e(TAG, "NotificationClicker called on an unclickable notification,");
-                return;
-            }
-
-            // Check if the notification is displaying the menu, if so slide notification back
-            if (row.getProvider() != null && row.getProvider().isMenuVisible()) {
-                row.animateTranslateNotification(0);
-                return;
-            }
-
-            // Mark notification for one frame.
-            row.setJustClicked(true);
-            DejankUtils.postAfterTraversal(() -> row.setJustClicked(false));
-
-            mCallback.onNotificationClicked(sbn, row);
-        }
-
-        public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
-            Notification notification = sbn.getNotification();
-            if (notification.contentIntent != null || notification.fullScreenIntent != null) {
-                row.setOnClickListener(this);
-            } else {
-                row.setOnClickListener(null);
-            }
-        }
-    }
-
-    private final DeviceProvisionedController.DeviceProvisionedListener
-            mDeviceProvisionedListener =
-            new DeviceProvisionedController.DeviceProvisionedListener() {
-                @Override
-                public void onDeviceProvisionedChanged() {
-                    updateNotifications();
-                }
-            };
-
-    public NotificationListenerService.RankingMap getLatestRankingMap() {
-        return mLatestRankingMap;
-    }
-
-    public void setLatestRankingMap(NotificationListenerService.RankingMap latestRankingMap) {
-        mLatestRankingMap = latestRankingMap;
-    }
-
-    public void setDisableNotificationAlerts(boolean disableNotificationAlerts) {
-        mDisableNotificationAlerts = disableNotificationAlerts;
-        mHeadsUpObserver.onChange(true);
-    }
-
-    public void destroy() {
-        mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
-    }
-
-    public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
-        if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) {
-            removeNotification(entry.key, getLatestRankingMap());
-            mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
-            if (mHeadsUpEntriesToRemoveOnSwitch.isEmpty()) {
-                setLatestRankingMap(null);
-            }
-        } else {
-            updateNotificationRanking(null);
-        }
-    }
-
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("NotificationEntryManager state:");
-        pw.print("  mPendingNotifications=");
-        if (mPendingNotifications.size() == 0) {
-            pw.println("null");
-        } else {
-            for (NotificationData.Entry entry : mPendingNotifications.values()) {
-                pw.println(entry.notification);
-            }
-        }
-        pw.print("  mUseHeadsUp=");
-        pw.println(mUseHeadsUp);
-        pw.print("  mKeysKeptForRemoteInput: ");
-        pw.println(mKeysKeptForRemoteInput);
-    }
-
-    public NotificationEntryManager(Context context) {
-        mContext = context;
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mBarService = IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-        mMessagingUtil = new NotificationMessagingUtil(context);
-        mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
-        mGroupManager.setPendingEntries(mPendingNotifications);
-    }
-
-    public void setUpWithPresenter(NotificationPresenter presenter,
-            NotificationListContainer listContainer, Callback callback,
-            HeadsUpManager headsUpManager) {
-        mPresenter = presenter;
-        mCallback = callback;
-        mNotificationData = new NotificationData(presenter);
-        mHeadsUpManager = headsUpManager;
-        mNotificationData.setHeadsUpManager(mHeadsUpManager);
-        mListContainer = listContainer;
-
-        mHeadsUpObserver = new ContentObserver(mPresenter.getHandler()) {
-            @Override
-            public void onChange(boolean selfChange) {
-                boolean wasUsing = mUseHeadsUp;
-                mUseHeadsUp = ENABLE_HEADS_UP && !mDisableNotificationAlerts
-                        && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt(
-                        mContext.getContentResolver(),
-                        Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
-                        Settings.Global.HEADS_UP_OFF);
-                Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled"));
-                if (wasUsing != mUseHeadsUp) {
-                    if (!mUseHeadsUp) {
-                        Log.d(TAG,
-                                "dismissing any existing heads up notification on disable event");
-                        mHeadsUpManager.releaseAllImmediately();
-                    }
-                }
-            }
-        };
-
-        if (ENABLE_HEADS_UP) {
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED),
-                    true,
-                    mHeadsUpObserver);
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
-                    mHeadsUpObserver);
-        }
-
-        mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
-
-        mHeadsUpObserver.onChange(true); // set up
-        mOnAppOpsClickListener = mGutsManager::openGuts;
-    }
-
-    public NotificationData getNotificationData() {
-        return mNotificationData;
-    }
-
-    public ExpandableNotificationRow.LongPressListener getNotificationLongClicker() {
-        return mGutsManager::openGuts;
-    }
-
-    @Override
-    public void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
-        mUiOffloadThread.submit(() -> {
-            try {
-                mBarService.onNotificationExpansionChanged(key, userAction, expanded);
-            } catch (RemoteException e) {
-                // Ignore.
-            }
-        });
-    }
-
-    @Override
-    public void onReorderingAllowed() {
-        updateNotifications();
-    }
-
-    private boolean shouldSuppressFullScreenIntent(NotificationData.Entry entry) {
-        if (mPresenter.isDeviceInVrMode()) {
-            return true;
-        }
-
-        return mNotificationData.shouldSuppressFullScreenIntent(entry);
-    }
-
-    private void inflateViews(NotificationData.Entry entry, ViewGroup parent) {
-        PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
-                entry.notification.getUser().getIdentifier());
-
-        final StatusBarNotification sbn = entry.notification;
-        if (entry.row != null) {
-            entry.reset();
-            updateNotification(entry, pmUser, sbn, entry.row);
-        } else {
-            new RowInflaterTask().inflate(mContext, parent, entry,
-                    row -> {
-                        bindRow(entry, pmUser, sbn, row);
-                        updateNotification(entry, pmUser, sbn, row);
-                    });
-        }
-    }
-
-    private void bindRow(NotificationData.Entry entry, PackageManager pmUser,
-            StatusBarNotification sbn, ExpandableNotificationRow row) {
-        row.setExpansionLogger(this, entry.notification.getKey());
-        row.setGroupManager(mGroupManager);
-        row.setHeadsUpManager(mHeadsUpManager);
-        row.setOnExpandClickListener(mPresenter);
-        row.setInflationCallback(this);
-        row.setLongPressListener(getNotificationLongClicker());
-        mListContainer.bindRow(row);
-        mRemoteInputManager.bindRow(row);
-
-        // Get the app name.
-        // Note that Notification.Builder#bindHeaderAppName has similar logic
-        // but since this field is used in the guts, it must be accurate.
-        // Therefore we will only show the application label, or, failing that, the
-        // package name. No substitutions.
-        final String pkg = sbn.getPackageName();
-        String appname = pkg;
-        try {
-            final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
-                    PackageManager.MATCH_UNINSTALLED_PACKAGES
-                            | PackageManager.MATCH_DISABLED_COMPONENTS);
-            if (info != null) {
-                appname = String.valueOf(pmUser.getApplicationLabel(info));
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            // Do nothing
-        }
-        row.setAppName(appname);
-        row.setOnDismissRunnable(() ->
-                performRemoveNotification(row.getStatusBarNotification()));
-        row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
-        if (ENABLE_REMOTE_INPUT) {
-            row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
-        }
-
-        row.setAppOpsOnClickListener(mOnAppOpsClickListener);
-
-        mCallback.onBindRow(entry, pmUser, sbn, row);
-    }
-
-    public void performRemoveNotification(StatusBarNotification n) {
-        final int rank = mNotificationData.getRank(n.getKey());
-        final int count = mNotificationData.getActiveNotifications().size();
-        final NotificationVisibility nv = NotificationVisibility.obtain(n.getKey(), rank, count,
-                true);
-        NotificationData.Entry entry = mNotificationData.get(n.getKey());
-
-        if (FORCE_REMOTE_INPUT_HISTORY
-                && mKeysKeptForRemoteInput.contains(n.getKey())) {
-            mKeysKeptForRemoteInput.remove(n.getKey());
-        }
-
-        mRemoteInputManager.onPerformRemoveNotification(n, entry);
-        final String pkg = n.getPackageName();
-        final String tag = n.getTag();
-        final int id = n.getId();
-        final int userId = n.getUserId();
-        try {
-            int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
-            if (isHeadsUp(n.getKey())) {
-                dismissalSurface = NotificationStats.DISMISSAL_PEEK;
-            } else if (mListContainer.hasPulsingNotifications()) {
-                dismissalSurface = NotificationStats.DISMISSAL_AOD;
-            }
-            mBarService.onNotificationClear(pkg, tag, id, userId, n.getKey(), dismissalSurface, nv);
-            removeNotification(n.getKey(), null);
-
-        } catch (RemoteException ex) {
-            // system process is dead if we're here.
-        }
-
-        mCallback.onPerformRemoveNotification(n);
-    }
-
-    /**
-     * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
-     * about the failure.
-     *
-     * WARNING: this will call back into us.  Don't hold any locks.
-     */
-    void handleNotificationError(StatusBarNotification n, String message) {
-        removeNotification(n.getKey(), null);
-        try {
-            mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
-                    n.getInitialPid(), message, n.getUserId());
-        } catch (RemoteException ex) {
-            // The end is nigh.
-        }
-    }
-
-    private void abortExistingInflation(String key) {
-        if (mPendingNotifications.containsKey(key)) {
-            NotificationData.Entry entry = mPendingNotifications.get(key);
-            entry.abortTask();
-            mPendingNotifications.remove(key);
-        }
-        NotificationData.Entry addedEntry = mNotificationData.get(key);
-        if (addedEntry != null) {
-            addedEntry.abortTask();
-        }
-    }
-
-    @Override
-    public void handleInflationException(StatusBarNotification notification, Exception e) {
-        handleNotificationError(notification, e.getMessage());
-    }
-
-    private void addEntry(NotificationData.Entry shadeEntry) {
-        boolean isHeadsUped = shouldPeek(shadeEntry);
-        if (isHeadsUped) {
-            mHeadsUpManager.showNotification(shadeEntry);
-            // Mark as seen immediately
-            setNotificationShown(shadeEntry.notification);
-        }
-        addNotificationViews(shadeEntry);
-        mCallback.onNotificationAdded(shadeEntry);
-    }
-
-    @Override
-    public void onAsyncInflationFinished(NotificationData.Entry entry) {
-        mPendingNotifications.remove(entry.key);
-        // If there was an async task started after the removal, we don't want to add it back to
-        // the list, otherwise we might get leaks.
-        boolean isNew = mNotificationData.get(entry.key) == null;
-        if (isNew && !entry.row.isRemoved()) {
-            addEntry(entry);
-        } else if (!isNew && entry.row.hasLowPriorityStateUpdated()) {
-            mVisualStabilityManager.onLowPriorityUpdated(entry);
-            mPresenter.updateNotificationViews();
-        }
-        entry.row.setLowPriorityStateUpdated(false);
-    }
-
-    @Override
-    public void removeNotification(String key, NotificationListenerService.RankingMap ranking) {
-        boolean deferRemoval = false;
-        abortExistingInflation(key);
-        if (mHeadsUpManager.isHeadsUp(key)) {
-            // A cancel() in response to a remote input shouldn't be delayed, as it makes the
-            // sending look longer than it takes.
-            // Also we should not defer the removal if reordering isn't allowed since otherwise
-            // some notifications can't disappear before the panel is closed.
-            boolean ignoreEarliestRemovalTime = mRemoteInputManager.getController().isSpinning(key)
-                    && !FORCE_REMOTE_INPUT_HISTORY
-                    || !mVisualStabilityManager.isReorderingAllowed();
-            deferRemoval = !mHeadsUpManager.removeNotification(key,  ignoreEarliestRemovalTime);
-        }
-        mMediaManager.onNotificationRemoved(key);
-
-        NotificationData.Entry entry = mNotificationData.get(key);
-        if (FORCE_REMOTE_INPUT_HISTORY
-                && shouldKeepForRemoteInput(entry)
-                && entry.row != null && !entry.row.isDismissed()) {
-            CharSequence remoteInputText = entry.remoteInputText;
-            if (TextUtils.isEmpty(remoteInputText)) {
-                remoteInputText = entry.remoteInputTextWhenReset;
-            }
-            StatusBarNotification newSbn = rebuildNotificationWithRemoteInput(entry,
-                    remoteInputText, false /* showSpinner */);
-            boolean updated = false;
-            entry.onRemoteInputInserted();
-            try {
-                updateNotificationInternal(newSbn, null);
-                updated = true;
-            } catch (InflationException e) {
-                deferRemoval = false;
-            }
-            if (updated) {
-                Log.w(TAG, "Keeping notification around after sending remote input "+ entry.key);
-                addKeyKeptForRemoteInput(entry.key);
-                return;
-            }
-        }
-
-        if (FORCE_REMOTE_INPUT_HISTORY
-                && shouldKeepForSmartReply(entry)
-                && entry.row != null && !entry.row.isDismissed()) {
-            // Turn off the spinner and hide buttons when an app cancels the notification.
-            StatusBarNotification newSbn = rebuildNotificationForCanceledSmartReplies(entry);
-            boolean updated = false;
-            try {
-                updateNotificationInternal(newSbn, null);
-                updated = true;
-            } catch (InflationException e) {
-                // Ignore just don't keep the notification around.
-            }
-            // Treat the reply as longer sending.
-            mSmartReplyController.stopSending(entry);
-            if (updated) {
-                Log.w(TAG, "Keeping notification around after sending smart reply " + entry.key);
-                addKeyKeptForRemoteInput(entry.key);
-                return;
-            }
-        }
-
-        // Actually removing notification so smart reply controller can forget about it.
-        mSmartReplyController.stopSending(entry);
-
-        if (deferRemoval) {
-            mLatestRankingMap = ranking;
-            mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key));
-            return;
-        }
-
-        if (mRemoteInputManager.onRemoveNotification(entry)) {
-            mLatestRankingMap = ranking;
-            return;
-        }
-
-        if (entry != null && mGutsManager.getExposedGuts() != null
-                && mGutsManager.getExposedGuts() == entry.row.getGuts()
-                && entry.row.getGuts() != null && !entry.row.getGuts().isLeavebehind()) {
-            Log.w(TAG, "Keeping notification because it's showing guts. " + key);
-            mLatestRankingMap = ranking;
-            mGutsManager.setKeyToRemoveOnGutsClosed(key);
-            return;
-        }
-
-        if (entry != null) {
-            mForegroundServiceController.removeNotification(entry.notification);
-        }
-
-        if (entry != null && entry.row != null) {
-            entry.row.setRemoved();
-            mListContainer.cleanUpViewState(entry.row);
-        }
-        // Let's remove the children if this was a summary
-        handleGroupSummaryRemoved(key);
-        StatusBarNotification old = removeNotificationViews(key, ranking);
-
-        mCallback.onNotificationRemoved(key, old);
-    }
-
-    public StatusBarNotification rebuildNotificationWithRemoteInput(NotificationData.Entry entry,
-            CharSequence remoteInputText, boolean showSpinner) {
-        StatusBarNotification sbn = entry.notification;
-
-        Notification.Builder b = Notification.Builder
-                .recoverBuilder(mContext, sbn.getNotification().clone());
-        if (remoteInputText != null) {
-            CharSequence[] oldHistory = sbn.getNotification().extras
-                    .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
-            CharSequence[] newHistory;
-            if (oldHistory == null) {
-                newHistory = new CharSequence[1];
-            } else {
-                newHistory = new CharSequence[oldHistory.length + 1];
-                System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length);
-            }
-            newHistory[0] = String.valueOf(remoteInputText);
-            b.setRemoteInputHistory(newHistory);
-        }
-        b.setShowRemoteInputSpinner(showSpinner);
-        b.setHideSmartReplies(true);
-
-        Notification newNotification = b.build();
-
-        // Undo any compatibility view inflation
-        newNotification.contentView = sbn.getNotification().contentView;
-        newNotification.bigContentView = sbn.getNotification().bigContentView;
-        newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
-
-        StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(),
-                sbn.getOpPkg(),
-                sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
-                newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
-        return newSbn;
-    }
-
-    @VisibleForTesting
-    StatusBarNotification rebuildNotificationForCanceledSmartReplies(
-            NotificationData.Entry entry) {
-        return rebuildNotificationWithRemoteInput(entry, null /* remoteInputTest */,
-                false /* showSpinner */);
-    }
-
-    private boolean shouldKeepForSmartReply(NotificationData.Entry entry) {
-        return entry != null && mSmartReplyController.isSendingSmartReply(entry.key);
-    }
-
-    private boolean shouldKeepForRemoteInput(NotificationData.Entry entry) {
-        if (entry == null) {
-            return false;
-        }
-        if (mRemoteInputManager.getController().isSpinning(entry.key)) {
-            return true;
-        }
-        if (entry.hasJustSentRemoteInput()) {
-            return true;
-        }
-        return false;
-    }
-
-    private StatusBarNotification removeNotificationViews(String key,
-            NotificationListenerService.RankingMap ranking) {
-        NotificationData.Entry entry = mNotificationData.remove(key, ranking);
-        if (entry == null) {
-            Log.w(TAG, "removeNotification for unknown key: " + key);
-            return null;
-        }
-        updateNotifications();
-        Dependency.get(LeakDetector.class).trackGarbage(entry);
-        return entry.notification;
-    }
-
-    /**
-     * Ensures that the group children are cancelled immediately when the group summary is cancelled
-     * instead of waiting for the notification manager to send all cancels. Otherwise this could
-     * lead to flickers.
-     *
-     * This also ensures that the animation looks nice and only consists of a single disappear
-     * animation instead of multiple.
-     *  @param key the key of the notification was removed
-     *
-     */
-    private void handleGroupSummaryRemoved(String key) {
-        NotificationData.Entry entry = mNotificationData.get(key);
-        if (entry != null && entry.row != null
-                && entry.row.isSummaryWithChildren()) {
-            if (entry.notification.getOverrideGroupKey() != null && !entry.row.isDismissed()) {
-                // We don't want to remove children for autobundled notifications as they are not
-                // always cancelled. We only remove them if they were dismissed by the user.
-                return;
-            }
-            List<ExpandableNotificationRow> notificationChildren =
-                    entry.row.getNotificationChildren();
-            for (int i = 0; i < notificationChildren.size(); i++) {
-                ExpandableNotificationRow row = notificationChildren.get(i);
-                if ((row.getStatusBarNotification().getNotification().flags
-                        & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
-                    // the child is a foreground service notification which we can't remove!
-                    continue;
-                }
-                row.setKeepInParent(true);
-                // we need to set this state earlier as otherwise we might generate some weird
-                // animations
-                row.setRemoved();
-            }
-        }
-    }
-
-    public void updateNotificationsOnDensityOrFontScaleChanged() {
-        ArrayList<NotificationData.Entry> userNotifications =
-                mNotificationData.getNotificationsForCurrentUser();
-        for (int i = 0; i < userNotifications.size(); i++) {
-            NotificationData.Entry entry = userNotifications.get(i);
-            boolean exposedGuts = mGutsManager.getExposedGuts() != null
-                    && entry.row.getGuts() == mGutsManager.getExposedGuts();
-            entry.row.onDensityOrFontScaleChanged();
-            if (exposedGuts) {
-                mGutsManager.onDensityOrFontScaleChanged(entry.row);
-            }
-        }
-    }
-
-    protected void updateNotification(NotificationData.Entry entry, PackageManager pmUser,
-            StatusBarNotification sbn, ExpandableNotificationRow row) {
-        row.setNeedsRedaction(mLockscreenUserManager.needsRedaction(entry));
-        boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
-        boolean isUpdate = mNotificationData.get(entry.key) != null;
-        boolean wasLowPriority = row.isLowPriority();
-        row.setIsLowPriority(isLowPriority);
-        row.setLowPriorityStateUpdated(isUpdate && (wasLowPriority != isLowPriority));
-        // bind the click event to the content area
-        mNotificationClicker.register(row, sbn);
-
-        // Extract target SDK version.
-        try {
-            ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
-            entry.targetSdk = info.targetSdkVersion;
-        } catch (PackageManager.NameNotFoundException ex) {
-            Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
-        }
-        row.setLegacy(entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
-                && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
-        entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
-        entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
-
-        entry.row = row;
-        entry.row.setOnActivatedListener(mPresenter);
-
-        boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(sbn,
-                mNotificationData.getImportance(sbn.getKey()));
-        boolean useIncreasedHeadsUp = useIncreasedCollapsedHeight
-                && !mPresenter.isPresenterFullyCollapsed();
-        row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
-        row.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
-        row.updateNotification(entry);
-    }
-
-
-    protected void addNotificationViews(NotificationData.Entry entry) {
-        if (entry == null) {
-            return;
-        }
-        // Add the expanded view and icon.
-        mNotificationData.add(entry);
-        tagForeground(entry.notification);
-        updateNotifications();
-    }
-
-    protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn)
-            throws InflationException {
-        if (DEBUG) {
-            Log.d(TAG, "createNotificationViews(notification=" + sbn);
-        }
-        NotificationData.Entry entry = new NotificationData.Entry(sbn);
-        Dependency.get(LeakDetector.class).trackInstance(entry);
-        entry.createIcons(mContext, sbn);
-        // Construct the expanded view.
-        inflateViews(entry, mListContainer.getViewParentForNotification(entry));
-        return entry;
-    }
-
-    private void addNotificationInternal(StatusBarNotification notification,
-            NotificationListenerService.RankingMap ranking) throws InflationException {
-        String key = notification.getKey();
-        if (DEBUG) Log.d(TAG, "addNotification key=" + key);
-
-        mNotificationData.updateRanking(ranking);
-        NotificationData.Entry shadeEntry = createNotificationViews(notification);
-        boolean isHeadsUped = shouldPeek(shadeEntry);
-        if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
-            if (shouldSuppressFullScreenIntent(shadeEntry)) {
-                if (DEBUG) {
-                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + key);
-                }
-            } else if (mNotificationData.getImportance(key)
-                    < NotificationManager.IMPORTANCE_HIGH) {
-                if (DEBUG) {
-                    Log.d(TAG, "No Fullscreen intent: not important enough: "
-                            + key);
-                }
-            } else {
-                // Stop screensaver if the notification has a fullscreen intent.
-                // (like an incoming phone call)
-                SystemServicesProxy.getInstance(mContext).awakenDreamsAsync();
-
-                // not immersive & a fullscreen alert should be shown
-                if (DEBUG)
-                    Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
-                try {
-                    EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
-                            key);
-                    notification.getNotification().fullScreenIntent.send();
-                    shadeEntry.notifyFullScreenIntentLaunched();
-                    mMetricsLogger.count("note_fullscreen", 1);
-                } catch (PendingIntent.CanceledException e) {
-                }
-            }
-        }
-        abortExistingInflation(key);
-
-        mForegroundServiceController.addNotification(notification,
-                mNotificationData.getImportance(key));
-
-        mPendingNotifications.put(key, shadeEntry);
-        mGroupManager.onPendingEntryAdded(shadeEntry);
-    }
-
-    @VisibleForTesting
-    protected void tagForeground(StatusBarNotification notification) {
-        ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
-                notification.getUserId(), notification.getPackageName());
-        if (activeOps != null) {
-            int N = activeOps.size();
-            for (int i = 0; i < N; i++) {
-                updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
-                        notification.getPackageName(), true);
-            }
-        }
-    }
-
-    @Override
-    public void addNotification(StatusBarNotification notification,
-            NotificationListenerService.RankingMap ranking) {
-        try {
-            addNotificationInternal(notification, ranking);
-        } catch (InflationException e) {
-            handleInflationException(notification, e);
-        }
-    }
-
-    public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
-        String foregroundKey = mForegroundServiceController.getStandardLayoutKey(
-                UserHandle.getUserId(uid), pkg);
-        if (foregroundKey != null) {
-            mNotificationData.updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
-            updateNotifications();
-        }
-    }
-
-    private boolean alertAgain(NotificationData.Entry oldEntry, Notification newNotification) {
-        return oldEntry == null || !oldEntry.hasInterrupted()
-                || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
-    }
-
-    private void updateNotificationInternal(StatusBarNotification notification,
-            NotificationListenerService.RankingMap ranking) throws InflationException {
-        if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
-
-        final String key = notification.getKey();
-        abortExistingInflation(key);
-        NotificationData.Entry entry = mNotificationData.get(key);
-        if (entry == null) {
-            return;
-        }
-        mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
-        mRemoteInputManager.onUpdateNotification(entry);
-        mSmartReplyController.stopSending(entry);
-
-        if (key.equals(mGutsManager.getKeyToRemoveOnGutsClosed())) {
-            mGutsManager.setKeyToRemoveOnGutsClosed(null);
-            Log.w(TAG, "Notification that was kept for guts was updated. " + key);
-        }
-
-        Notification n = notification.getNotification();
-        mNotificationData.updateRanking(ranking);
-
-        final StatusBarNotification oldNotification = entry.notification;
-        entry.notification = notification;
-        mGroupManager.onEntryUpdated(entry, oldNotification);
-
-        entry.updateIcons(mContext, notification);
-        inflateViews(entry, mListContainer.getViewParentForNotification(entry));
-
-        mForegroundServiceController.updateNotification(notification,
-                mNotificationData.getImportance(key));
-
-        boolean shouldPeek = shouldPeek(entry, notification);
-        boolean alertAgain = alertAgain(entry, n);
-
-        updateHeadsUp(key, entry, shouldPeek, alertAgain);
-        updateNotifications();
-
-        if (!notification.isClearable()) {
-            // The user may have performed a dismiss action on the notification, since it's
-            // not clearable we should snap it back.
-            mListContainer.snapViewIfNeeded(entry.row);
-        }
-
-        if (DEBUG) {
-            // Is this for you?
-            boolean isForCurrentUser = mPresenter.isNotificationForCurrentProfiles(notification);
-            Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
-        }
-
-        mCallback.onNotificationUpdated(notification);
-    }
-
-    @Override
-    public void updateNotification(StatusBarNotification notification,
-            NotificationListenerService.RankingMap ranking) {
-        try {
-            updateNotificationInternal(notification, ranking);
-        } catch (InflationException e) {
-            handleInflationException(notification, e);
-        }
-    }
-
-    public void updateNotifications() {
-        mNotificationData.filterAndSort();
-
-        mPresenter.updateNotificationViews();
-    }
-
-    public void updateNotificationRanking(NotificationListenerService.RankingMap ranking) {
-        mNotificationData.updateRanking(ranking);
-        updateNotifications();
-    }
-
-    protected boolean shouldPeek(NotificationData.Entry entry) {
-        return shouldPeek(entry, entry.notification);
-    }
-
-    public boolean shouldPeek(NotificationData.Entry entry, StatusBarNotification sbn) {
-        if (!mUseHeadsUp || mPresenter.isDeviceInVrMode()) {
-            if (DEBUG) Log.d(TAG, "No peeking: no huns or vr mode");
-            return false;
-        }
-
-        if (mNotificationData.shouldFilterOut(entry)) {
-            if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
-            return false;
-        }
-
-        boolean inUse = mPowerManager.isScreenOn() && !mSystemServicesProxy.isDreaming();
-
-        if (!inUse && !mPresenter.isDozing()) {
-            if (DEBUG) {
-                Log.d(TAG, "No peeking: not in use: " + sbn.getKey());
-            }
-            return false;
-        }
-
-        if (!mPresenter.isDozing() && mNotificationData.shouldSuppressPeek(entry)) {
-            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
-            return false;
-        }
-
-        // Peeking triggers an ambient display pulse, so disable peek is ambient is active
-        if (mPresenter.isDozing() && mNotificationData.shouldSuppressAmbient(entry)) {
-            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
-            return false;
-        }
-
-        if (entry.hasJustLaunchedFullScreenIntent()) {
-            if (DEBUG) Log.d(TAG, "No peeking: recent fullscreen: " + sbn.getKey());
-            return false;
-        }
-
-        if (isSnoozedPackage(sbn)) {
-            if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
-            return false;
-        }
-
-        // Allow peeking for DEFAULT notifications only if we're on Ambient Display.
-        int importanceLevel = mPresenter.isDozing() ? NotificationManager.IMPORTANCE_DEFAULT
-                : NotificationManager.IMPORTANCE_HIGH;
-        if (mNotificationData.getImportance(sbn.getKey()) < importanceLevel) {
-            if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
-            return false;
-        }
-
-        // Don't peek notifications that are suppressed due to group alert behavior
-        if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) {
-            if (DEBUG) Log.d(TAG, "No peeking: suppressed due to group alert behavior");
-            return false;
-        }
-
-        if (!mCallback.shouldPeek(entry, sbn)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    protected void setNotificationShown(StatusBarNotification n) {
-        setNotificationsShown(new String[]{n.getKey()});
-    }
-
-    protected void setNotificationsShown(String[] keys) {
-        try {
-            mNotificationListener.setNotificationsShown(keys);
-        } catch (RuntimeException e) {
-            Log.d(TAG, "failed setNotificationsShown: ", e);
-        }
-    }
-
-    protected boolean isSnoozedPackage(StatusBarNotification sbn) {
-        return mHeadsUpManager.isSnoozed(sbn.getPackageName());
-    }
-
-    protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldPeek,
-            boolean alertAgain) {
-        final boolean wasHeadsUp = isHeadsUp(key);
-        if (wasHeadsUp) {
-            if (!shouldPeek) {
-                // We don't want this to be interrupting anymore, lets remove it
-                mHeadsUpManager.removeNotification(key, false /* ignoreEarliestRemovalTime */);
-            } else {
-                mHeadsUpManager.updateNotification(entry, alertAgain);
-            }
-        } else if (shouldPeek && alertAgain) {
-            // This notification was updated to be a heads-up, show it!
-            mHeadsUpManager.showNotification(entry);
-        }
-    }
-
-    protected boolean isHeadsUp(String key) {
-        return mHeadsUpManager.isHeadsUp(key);
-    }
-
-    public boolean isNotificationKeptForRemoteInput(String key) {
-        return mKeysKeptForRemoteInput.contains(key);
-    }
-
-    public void removeKeyKeptForRemoteInput(String key) {
-        mKeysKeptForRemoteInput.remove(key);
-    }
-
-    public void addKeyKeptForRemoteInput(String key) {
-        if (FORCE_REMOTE_INPUT_HISTORY) {
-            mKeysKeptForRemoteInput.add(key);
-        }
-    }
-
-    /**
-     * Callback for NotificationEntryManager.
-     */
-    public interface Callback {
-
-        /**
-         * Called when a new entry is created.
-         *
-         * @param shadeEntry entry that was created
-         */
-        void onNotificationAdded(NotificationData.Entry shadeEntry);
-
-        /**
-         * Called when a notification was updated.
-         *
-         * @param notification notification that was updated
-         */
-        void onNotificationUpdated(StatusBarNotification notification);
-
-        /**
-         * Called when a notification was removed.
-         *
-         * @param key key of notification that was removed
-         * @param old StatusBarNotification of the notification before it was removed
-         */
-        void onNotificationRemoved(String key, StatusBarNotification old);
-
-
-        /**
-         * Called when a notification is clicked.
-         *
-         * @param sbn notification that was clicked
-         * @param row row for that notification
-         */
-        void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row);
-
-        /**
-         * Called when a new notification and row is created.
-         *
-         * @param entry entry for the notification
-         * @param pmUser package manager for user
-         * @param sbn notification
-         * @param row row for the notification
-         */
-        void onBindRow(NotificationData.Entry entry, PackageManager pmUser,
-                StatusBarNotification sbn, ExpandableNotificationRow row);
-
-        /**
-         * Removes a notification immediately.
-         *
-         * @param statusBarNotification notification that is being removed
-         */
-        void onPerformRemoveNotification(StatusBarNotification statusBarNotification);
-
-        /**
-         * Returns true if NotificationEntryManager should peek this notification.
-         *
-         * @param entry entry of the notification that might be peeked
-         * @param sbn notification that might be peeked
-         * @return true if the notification should be peeked
-         */
-        boolean shouldPeek(NotificationData.Entry entry, StatusBarNotification sbn);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
deleted file mode 100644
index 4a8f4bbf..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import androidx.annotation.Nullable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewAnimationUtils;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.FrameLayout;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
-
-/**
- * The guts of a notification revealed when performing a long press.
- */
-public class NotificationGuts extends FrameLayout {
-    private static final String TAG = "NotificationGuts";
-    private static final long CLOSE_GUTS_DELAY = 8000;
-
-    private Drawable mBackground;
-    private int mClipTopAmount;
-    private int mClipBottomAmount;
-    private int mActualHeight;
-    private boolean mExposed;
-
-    private Handler mHandler;
-    private Runnable mFalsingCheck;
-    private boolean mNeedsFalsingProtection;
-    private OnGutsClosedListener mClosedListener;
-    private OnHeightChangedListener mHeightListener;
-
-    private GutsContent mGutsContent;
-
-    public interface GutsContent {
-
-        public void setGutsParent(NotificationGuts listener);
-
-        /**
-         * Return the view to be shown in the notification guts.
-         */
-        public View getContentView();
-
-        /**
-         * Return the actual height of the content.
-         */
-        public int getActualHeight();
-
-        /**
-         * Called when the guts view have been told to close, typically after an outside
-         * interaction.
-         *
-         * @param save whether the state should be saved.
-         * @param force whether the guts view should be forced closed regardless of state.
-         * @return if closing the view has been handled.
-         */
-        public boolean handleCloseControls(boolean save, boolean force);
-
-        /**
-         * Return whether the notification associated with these guts is set to be removed.
-         */
-        public boolean willBeRemoved();
-
-        /**
-         * Return whether these guts are a leavebehind (e.g. {@link NotificationSnooze}).
-         */
-        public default boolean isLeavebehind() {
-            return false;
-        }
-
-        /**
-         * Return whether something changed and needs to be saved, possibly requiring a bouncer.
-         */
-        boolean shouldBeSaved();
-    }
-
-    public interface OnGutsClosedListener {
-        public void onGutsClosed(NotificationGuts guts);
-    }
-
-    public interface OnHeightChangedListener {
-        public void onHeightChanged(NotificationGuts guts);
-    }
-
-    interface OnSettingsClickListener {
-        void onClick(View v, int appUid);
-    }
-
-    public NotificationGuts(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setWillNotDraw(false);
-        mHandler = new Handler();
-        mFalsingCheck = new Runnable() {
-            @Override
-            public void run() {
-                if (mNeedsFalsingProtection && mExposed) {
-                    closeControls(-1 /* x */, -1 /* y */, false /* save */, false /* force */);
-                }
-            }
-        };
-        final TypedArray ta = context.obtainStyledAttributes(attrs,
-                com.android.internal.R.styleable.Theme, 0, 0);
-        ta.recycle();
-    }
-
-    public NotificationGuts(Context context) {
-        this(context, null);
-    }
-
-    public void setGutsContent(GutsContent content) {
-        mGutsContent = content;
-        removeAllViews();
-        addView(mGutsContent.getContentView());
-    }
-
-    public GutsContent getGutsContent() {
-        return mGutsContent;
-    }
-
-    public void resetFalsingCheck() {
-        mHandler.removeCallbacks(mFalsingCheck);
-        if (mNeedsFalsingProtection && mExposed) {
-            mHandler.postDelayed(mFalsingCheck, CLOSE_GUTS_DELAY);
-        }
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        draw(canvas, mBackground);
-    }
-
-    private void draw(Canvas canvas, Drawable drawable) {
-        int top = mClipTopAmount;
-        int bottom = mActualHeight - mClipBottomAmount;
-        if (drawable != null && top < bottom) {
-            drawable.setBounds(0, top, getWidth(), bottom);
-            drawable.draw(canvas);
-        }
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mBackground = mContext.getDrawable(R.drawable.notification_guts_bg);
-        if (mBackground != null) {
-            mBackground.setCallback(this);
-        }
-    }
-
-    @Override
-    protected boolean verifyDrawable(Drawable who) {
-        return super.verifyDrawable(who) || who == mBackground;
-    }
-
-    @Override
-    protected void drawableStateChanged() {
-        drawableStateChanged(mBackground);
-    }
-
-    private void drawableStateChanged(Drawable d) {
-        if (d != null && d.isStateful()) {
-            d.setState(getDrawableState());
-        }
-    }
-
-    @Override
-    public void drawableHotspotChanged(float x, float y) {
-        if (mBackground != null) {
-            mBackground.setHotspot(x, y);
-        }
-    }
-
-    public void openControls(
-            boolean shouldDoCircularReveal,
-            int x,
-            int y,
-            boolean needsFalsingProtection,
-            @Nullable Runnable onAnimationEnd) {
-        animateOpen(shouldDoCircularReveal, x, y, onAnimationEnd);
-        setExposed(true /* exposed */, needsFalsingProtection);
-    }
-
-    /**
-     * Hide controls if they are visible
-     * @param leavebehinds true if leavebehinds should be closed
-     * @param controls true if controls should be closed
-     * @param x x coordinate to animate the close circular reveal with
-     * @param y y coordinate to animate the close circular reveal with
-     * @param force whether the guts should be force-closed regardless of state.
-     */
-    public void closeControls(boolean leavebehinds, boolean controls, int x, int y, boolean force) {
-        if (mGutsContent != null) {
-            if ((mGutsContent.isLeavebehind() && leavebehinds)
-                    || (!mGutsContent.isLeavebehind() && controls)) {
-                closeControls(x, y, mGutsContent.shouldBeSaved(), force);
-            }
-        }
-    }
-
-    /**
-     * Closes any exposed guts/views.
-     *
-     * @param x x coordinate to animate the close circular reveal with
-     * @param y y coordinate to animate the close circular reveal with
-     * @param save whether the state should be saved
-     * @param force whether the guts should be force-closed regardless of state.
-     */
-    public void closeControls(int x, int y, boolean save, boolean force) {
-        // First try to dismiss any blocking helper.
-        boolean wasBlockingHelperDismissed =
-                Dependency.get(NotificationBlockingHelperManager.class)
-                        .dismissCurrentBlockingHelper();
-
-        if (getWindowToken() == null) {
-            if (mClosedListener != null) {
-                mClosedListener.onGutsClosed(this);
-            }
-            return;
-        }
-
-        if (mGutsContent == null
-                || !mGutsContent.handleCloseControls(save, force)
-                || wasBlockingHelperDismissed) {
-            // We only want to do a circular reveal if we're not showing the blocking helper.
-            animateClose(x, y, !wasBlockingHelperDismissed /* shouldDoCircularReveal */);
-
-            setExposed(false, mNeedsFalsingProtection);
-            if (mClosedListener != null) {
-                mClosedListener.onGutsClosed(this);
-            }
-        }
-    }
-
-    /** Animates in the guts view via either a fade or a circular reveal. */
-    private void animateOpen(
-            boolean shouldDoCircularReveal, int x, int y, @Nullable Runnable onAnimationEnd) {
-        if (isAttachedToWindow()) {
-            if (shouldDoCircularReveal) {
-                double horz = Math.max(getWidth() - x, x);
-                double vert = Math.max(getHeight() - y, y);
-                float r = (float) Math.hypot(horz, vert);
-                // Circular reveal originating at (x, y)
-                Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
-                a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-                a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-                a.addListener(new AnimateOpenListener(onAnimationEnd));
-                a.start();
-            } else {
-                // Fade in content
-                this.setAlpha(0f);
-                this.animate()
-                        .alpha(1f)
-                        .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
-                        .setInterpolator(Interpolators.ALPHA_IN)
-                        .setListener(new AnimateOpenListener(onAnimationEnd))
-                        .start();
-            }
-        } else {
-            Log.w(TAG, "Failed to animate guts open");
-        }
-    }
-
-
-    /** Animates out the guts view via either a fade or a circular reveal. */
-    @VisibleForTesting
-    void animateClose(int x, int y, boolean shouldDoCircularReveal) {
-        if (isAttachedToWindow()) {
-            if (shouldDoCircularReveal) {
-                // Circular reveal originating at (x, y)
-                if (x == -1 || y == -1) {
-                    x = (getLeft() + getRight()) / 2;
-                    y = (getTop() + getHeight() / 2);
-                }
-                double horz = Math.max(getWidth() - x, x);
-                double vert = Math.max(getHeight() - y, y);
-                float r = (float) Math.hypot(horz, vert);
-                Animator a = ViewAnimationUtils.createCircularReveal(this,
-                        x, y, r, 0);
-                a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-                a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-                a.addListener(new AnimateCloseListener(this /* view */));
-                a.start();
-            } else {
-                // Fade in the blocking helper.
-                this.animate()
-                        .alpha(0f)
-                        .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
-                        .setInterpolator(Interpolators.ALPHA_OUT)
-                        .setListener(new AnimateCloseListener(this /* view */))
-                        .start();
-            }
-        } else {
-            Log.w(TAG, "Failed to animate guts close");
-        }
-    }
-
-    public void setActualHeight(int actualHeight) {
-        mActualHeight = actualHeight;
-        invalidate();
-    }
-
-    public int getActualHeight() {
-        return mActualHeight;
-    }
-
-    public int getIntrinsicHeight() {
-        return mGutsContent != null && mExposed ? mGutsContent.getActualHeight() : getHeight();
-    }
-
-    public void setClipTopAmount(int clipTopAmount) {
-        mClipTopAmount = clipTopAmount;
-        invalidate();
-    }
-
-    public void setClipBottomAmount(int clipBottomAmount) {
-        mClipBottomAmount = clipBottomAmount;
-        invalidate();
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        // Prevents this view from creating a layer when alpha is animating.
-        return false;
-    }
-
-    public void setClosedListener(OnGutsClosedListener listener) {
-        mClosedListener = listener;
-    }
-
-    public void setHeightChangedListener(OnHeightChangedListener listener) {
-        mHeightListener = listener;
-    }
-
-    protected void onHeightChanged() {
-        if (mHeightListener != null) {
-            mHeightListener.onHeightChanged(this);
-        }
-    }
-
-    @VisibleForTesting
-    void setExposed(boolean exposed, boolean needsFalsingProtection) {
-        final boolean wasExposed = mExposed;
-        mExposed = exposed;
-        mNeedsFalsingProtection = needsFalsingProtection;
-        if (mExposed && mNeedsFalsingProtection) {
-            resetFalsingCheck();
-        } else {
-            mHandler.removeCallbacks(mFalsingCheck);
-        }
-        if (wasExposed != mExposed && mGutsContent != null) {
-            final View contentView = mGutsContent.getContentView();
-            contentView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
-            if (mExposed) {
-                contentView.requestAccessibilityFocus();
-            }
-        }
-    }
-
-    public boolean willBeRemoved() {
-        return mGutsContent != null ? mGutsContent.willBeRemoved() : false;
-    }
-
-    public boolean isExposed() {
-        return mExposed;
-    }
-
-    public boolean isLeavebehind() {
-        return mGutsContent != null && mGutsContent.isLeavebehind();
-    }
-
-    /** Listener for animations executed in {@link #animateOpen(boolean, int, int, Runnable)}. */
-    private static class AnimateOpenListener extends AnimatorListenerAdapter {
-        final Runnable mOnAnimationEnd;
-
-        private AnimateOpenListener(Runnable onAnimationEnd) {
-            mOnAnimationEnd = onAnimationEnd;
-        }
-
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            super.onAnimationEnd(animation);
-            if (mOnAnimationEnd != null) {
-                mOnAnimationEnd.run();
-            }
-        }
-    }
-
-    /** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
-    private static class AnimateCloseListener extends AnimatorListenerAdapter {
-        final View mView;
-
-        private AnimateCloseListener(View view) {
-            mView = view;
-        }
-
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            super.onAnimationEnd(animation);
-            mView.setVisibility(View.GONE);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
deleted file mode 100644
index 91a381f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGutsManager.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.systemui.statusbar;
-
-import static android.app.AppOpsManager.OP_CAMERA;
-import static android.app.AppOpsManager.OP_RECORD_AUDIO;
-import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
-import static android.service.notification.NotificationListenerService.Ranking
-        .USER_SENTIMENT_NEGATIVE;
-
-import android.app.INotificationManager;
-import android.app.NotificationChannel;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.service.notification.StatusBarNotification;
-import androidx.annotation.VisibleForTesting;
-import android.util.ArraySet;
-import android.util.Log;
-import android.view.HapticFeedbackConstants;
-import android.view.View;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.systemui.Dependency;
-import com.android.systemui.Dumpable;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.phone.StatusBar;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Handles various NotificationGuts related tasks, such as binding guts to a row, opening and
- * closing guts, and keeping track of the currently exposed notification guts.
- */
-public class NotificationGutsManager implements Dumpable {
-    private static final String TAG = "NotificationGutsManager";
-
-    // Must match constant in Settings. Used to highlight preferences when linking to Settings.
-    private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
-
-    private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
-    private final Context mContext;
-    private final AccessibilityManager mAccessibilityManager;
-
-    // Dependencies:
-    private final NotificationLockscreenUserManager mLockscreenUserManager =
-            Dependency.get(NotificationLockscreenUserManager.class);
-
-    // which notification is currently being longpress-examined by the user
-    private NotificationGuts mNotificationGutsExposed;
-    private NotificationMenuRowPlugin.MenuItem mGutsMenuItem;
-    protected NotificationPresenter mPresenter;
-    protected NotificationEntryManager mEntryManager;
-    private NotificationListContainer mListContainer;
-    private NotificationInfo.CheckSaveListener mCheckSaveListener;
-    private OnSettingsClickListener mOnSettingsClickListener;
-    private String mKeyToRemoveOnGutsClosed;
-
-    public NotificationGutsManager(Context context) {
-        mContext = context;
-        Resources res = context.getResources();
-
-        mAccessibilityManager = (AccessibilityManager)
-                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
-    }
-
-    public void setUpWithPresenter(NotificationPresenter presenter,
-            NotificationEntryManager entryManager, NotificationListContainer listContainer,
-            NotificationInfo.CheckSaveListener checkSaveListener,
-            OnSettingsClickListener onSettingsClickListener) {
-        mPresenter = presenter;
-        mEntryManager = entryManager;
-        mListContainer = listContainer;
-        mCheckSaveListener = checkSaveListener;
-        mOnSettingsClickListener = onSettingsClickListener;
-    }
-
-    public String getKeyToRemoveOnGutsClosed() {
-        return mKeyToRemoveOnGutsClosed;
-    }
-
-    public void setKeyToRemoveOnGutsClosed(String keyToRemoveOnGutsClosed) {
-        mKeyToRemoveOnGutsClosed = keyToRemoveOnGutsClosed;
-    }
-
-    public void onDensityOrFontScaleChanged(ExpandableNotificationRow row) {
-        setExposedGuts(row.getGuts());
-        bindGuts(row);
-    }
-
-    /**
-     * Sends an intent to open the app settings for a particular package and optional
-     * channel.
-     */
-    private void startAppNotificationSettingsActivity(String packageName, final int appUid,
-            final NotificationChannel channel, ExpandableNotificationRow row) {
-        final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
-        intent.setData(Uri.fromParts("package", packageName, null));
-        intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
-        intent.putExtra(Settings.EXTRA_APP_UID, appUid);
-        if (channel != null) {
-            intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channel.getId());
-        }
-        mPresenter.startNotificationGutsIntent(intent, appUid, row);
-    }
-
-    protected void startAppOpsSettingsActivity(String pkg, int uid, ArraySet<Integer> ops,
-            ExpandableNotificationRow row) {
-        if (ops.contains(OP_SYSTEM_ALERT_WINDOW)) {
-            if (ops.contains(OP_CAMERA) || ops.contains(OP_RECORD_AUDIO)) {
-                startAppNotificationSettingsActivity(pkg, uid, null, row);
-            } else {
-                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
-                intent.setData(Uri.fromParts("package", pkg, null));
-                mPresenter.startNotificationGutsIntent(intent, uid, row);
-            }
-        } else if (ops.contains(OP_CAMERA) || ops.contains(OP_RECORD_AUDIO)) {
-            Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS);
-            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, pkg);
-            mPresenter.startNotificationGutsIntent(intent, uid, row);
-        }
-    }
-
-    public void bindGuts(final ExpandableNotificationRow row) {
-        bindGuts(row, mGutsMenuItem);
-    }
-
-    private void bindGuts(final ExpandableNotificationRow row,
-            NotificationMenuRowPlugin.MenuItem item) {
-        StatusBarNotification sbn = row.getStatusBarNotification();
-
-        row.inflateGuts();
-        row.setGutsView(item);
-        row.setTag(sbn.getPackageName());
-        row.getGuts().setClosedListener((NotificationGuts g) -> {
-            row.onGutsClosed();
-            if (!g.willBeRemoved() && !row.isRemoved()) {
-                mListContainer.onHeightChanged(
-                        row, !mPresenter.isPresenterFullyCollapsed() /* needsAnimation */);
-            }
-            if (mNotificationGutsExposed == g) {
-                mNotificationGutsExposed = null;
-                mGutsMenuItem = null;
-            }
-            String key = sbn.getKey();
-            if (key.equals(mKeyToRemoveOnGutsClosed)) {
-                mKeyToRemoveOnGutsClosed = null;
-                mEntryManager.removeNotification(key, mEntryManager.getLatestRankingMap());
-            }
-        });
-
-        View gutsView = item.getGutsView();
-        if (gutsView instanceof NotificationSnooze) {
-            initializeSnoozeView(row, (NotificationSnooze) gutsView);
-        } else if (gutsView instanceof AppOpsInfo) {
-            initializeAppOpsInfo(row, (AppOpsInfo) gutsView);
-        } else if (gutsView instanceof NotificationInfo) {
-            initializeNotificationInfo(row, (NotificationInfo) gutsView);
-        }
-    }
-
-    /**
-     * Sets up the {@link NotificationSnooze} inside the notification row's guts.
-     *
-     * @param row view to set up the guts for
-     * @param notificationSnoozeView view to set up/bind within {@code row}
-     */
-    private void initializeSnoozeView(
-            final ExpandableNotificationRow row,
-            NotificationSnooze notificationSnoozeView) {
-        NotificationGuts guts = row.getGuts();
-        StatusBarNotification sbn = row.getStatusBarNotification();
-
-        notificationSnoozeView.setSnoozeListener(mListContainer.getSwipeActionHelper());
-        notificationSnoozeView.setStatusBarNotification(sbn);
-        notificationSnoozeView.setSnoozeOptions(row.getEntry().snoozeCriteria);
-        guts.setHeightChangedListener((NotificationGuts g) -> {
-            mListContainer.onHeightChanged(row, row.isShown() /* needsAnimation */);
-        });
-    }
-
-    /**
-     * Sets up the {@link AppOpsInfo} inside the notification row's guts.
-     *
-     * @param row view to set up the guts for
-     * @param appOpsInfoView view to set up/bind within {@code row}
-     */
-    private void initializeAppOpsInfo(
-            final ExpandableNotificationRow row,
-            AppOpsInfo appOpsInfoView) {
-        NotificationGuts guts = row.getGuts();
-        StatusBarNotification sbn = row.getStatusBarNotification();
-        UserHandle userHandle = sbn.getUser();
-        PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
-                userHandle.getIdentifier());
-
-        AppOpsInfo.OnSettingsClickListener onSettingsClick =
-                (View v, String pkg, int uid, ArraySet<Integer> ops) -> {
-            mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS);
-            guts.resetFalsingCheck();
-            startAppOpsSettingsActivity(pkg, uid, ops, row);
-        };
-        if (!row.getEntry().mActiveAppOps.isEmpty()) {
-            appOpsInfoView.bindGuts(pmUser, onSettingsClick, sbn, row.getEntry().mActiveAppOps);
-        }
-    }
-
-    /**
-     * Sets up the {@link NotificationInfo} inside the notification row's guts.
-     *
-     * @param row view to set up the guts for
-     * @param notificationInfoView view to set up/bind within {@code row}
-     */
-    @VisibleForTesting
-    void initializeNotificationInfo(
-            final ExpandableNotificationRow row,
-            NotificationInfo notificationInfoView) {
-        NotificationGuts guts = row.getGuts();
-        StatusBarNotification sbn = row.getStatusBarNotification();
-        String packageName = sbn.getPackageName();
-        // Settings link is only valid for notifications that specify a non-system user
-        NotificationInfo.OnSettingsClickListener onSettingsClick = null;
-        UserHandle userHandle = sbn.getUser();
-        PackageManager pmUser = StatusBar.getPackageManagerForUser(
-                mContext, userHandle.getIdentifier());
-        INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(
-                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-        final NotificationInfo.OnAppSettingsClickListener onAppSettingsClick =
-                (View v, Intent intent) -> {
-                    mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_APP_NOTE_SETTINGS);
-                    guts.resetFalsingCheck();
-                    mPresenter.startNotificationGutsIntent(intent, sbn.getUid(), row);
-                };
-        boolean isForBlockingHelper = row.isBlockingHelperShowing();
-
-        if (!userHandle.equals(UserHandle.ALL)
-                || mLockscreenUserManager.getCurrentUserId() == UserHandle.USER_SYSTEM) {
-            onSettingsClick = (View v, NotificationChannel channel, int appUid) -> {
-                mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_NOTE_INFO);
-                guts.resetFalsingCheck();
-                mOnSettingsClickListener.onClick(sbn.getKey());
-                startAppNotificationSettingsActivity(packageName, appUid, channel, row);
-            };
-        }
-
-        try {
-            notificationInfoView.bindNotification(
-                    pmUser,
-                    iNotificationManager,
-                    packageName,
-                    row.getEntry().channel,
-                    row.getNumUniqueChannels(),
-                    sbn,
-                    mCheckSaveListener,
-                    onSettingsClick,
-                    onAppSettingsClick,
-                    row.getIsNonblockable(),
-                    isForBlockingHelper,
-                    row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
-        } catch (RemoteException e) {
-            Log.e(TAG, e.toString());
-        }
-    }
-
-    /**
-     * Closes guts or notification menus that might be visible and saves any changes.
-     *
-     * @param removeLeavebehinds true if leavebehinds (e.g. snooze) should be closed.
-     * @param force true if guts should be closed regardless of state (used for snooze only).
-     * @param removeControls true if controls (e.g. info) should be closed.
-     * @param x if closed based on touch location, this is the x touch location.
-     * @param y if closed based on touch location, this is the y touch location.
-     * @param resetMenu if any notification menus that might be revealed should be closed.
-     */
-    public void closeAndSaveGuts(boolean removeLeavebehinds, boolean force, boolean removeControls,
-            int x, int y, boolean resetMenu) {
-        if (mNotificationGutsExposed != null) {
-            mNotificationGutsExposed.closeControls(removeLeavebehinds, removeControls, x, y, force);
-        }
-        if (resetMenu) {
-            mListContainer.resetExposedMenuView(false /* animate */, true /* force */);
-        }
-    }
-
-    /**
-     * Returns the exposed NotificationGuts or null if none are exposed.
-     */
-    public NotificationGuts getExposedGuts() {
-        return mNotificationGutsExposed;
-    }
-
-    public void setExposedGuts(NotificationGuts guts) {
-        mNotificationGutsExposed = guts;
-    }
-
-    /**
-     * Opens guts on the given ExpandableNotificationRow {@code view}. This handles opening guts for
-     * the normal half-swipe and long-press use cases via a circular reveal. When the blocking
-     * helper needs to be shown on the row, this will skip the circular reveal.
-     *
-     * @param view ExpandableNotificationRow to open guts on
-     * @param x x coordinate of origin of circular reveal
-     * @param y y coordinate of origin of circular reveal
-     * @param menuItem MenuItem the guts should display
-     * @return true if guts was opened
-     */
-    boolean openGuts(
-            View view,
-            int x,
-            int y,
-            NotificationMenuRowPlugin.MenuItem menuItem) {
-        if (!(view instanceof ExpandableNotificationRow)) {
-            return false;
-        }
-
-        if (view.getWindowToken() == null) {
-            Log.e(TAG, "Trying to show notification guts, but not attached to window");
-            return false;
-        }
-
-        final ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-        if (row.isDark()) {
-            return false;
-        }
-        view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-        if (row.areGutsExposed()) {
-            closeAndSaveGuts(false /* removeLeavebehind */, false /* force */,
-                    true /* removeControls */, -1 /* x */, -1 /* y */,
-                    true /* resetMenu */);
-            return false;
-        }
-        bindGuts(row, menuItem);
-        NotificationGuts guts = row.getGuts();
-
-        // Assume we are a status_bar_notification_row
-        if (guts == null) {
-            // This view has no guts. Examples are the more card or the dismiss all view
-            return false;
-        }
-
-        mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_NOTE_CONTROLS);
-
-        // ensure that it's laid but not visible until actually laid out
-        guts.setVisibility(View.INVISIBLE);
-        // Post to ensure the the guts are properly laid out.
-        guts.post(new Runnable() {
-            @Override
-            public void run() {
-                if (row.getWindowToken() == null) {
-                    Log.e(TAG, "Trying to show notification guts in post(), but not attached to "
-                            + "window");
-                    return;
-                }
-                closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
-                        true /* removeControls */, -1 /* x */, -1 /* y */,
-                        false /* resetMenu */);
-                guts.setVisibility(View.VISIBLE);
-
-                final boolean needsFalsingProtection =
-                        (mPresenter.isPresenterLocked() &&
-                                !mAccessibilityManager.isTouchExplorationEnabled());
-
-                guts.openControls(
-                        !row.isBlockingHelperShowing(),
-                        x,
-                        y,
-                        needsFalsingProtection,
-                        row::onGutsOpened);
-
-                row.closeRemoteInput();
-                mListContainer.onHeightChanged(row, true /* needsAnimation */);
-                mNotificationGutsExposed = guts;
-                mGutsMenuItem = menuItem;
-            }
-        });
-        return true;
-    }
-
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("NotificationGutsManager state:");
-        pw.print("  mKeyToRemoveOnGutsClosed: ");
-        pw.println(mKeyToRemoveOnGutsClosed);
-    }
-
-    public interface OnSettingsClickListener {
-        void onClick(String key);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 886d6f1..ef40d98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar;
 
 import android.app.Notification;
+import android.content.res.Configuration;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Icon;
 import android.text.TextUtils;
@@ -25,6 +26,10 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.internal.util.ContrastColorUtil;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationContentView;
+
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -74,8 +79,11 @@
                 imageView.getDrawable().mutate();
                 if (shouldApply) {
                     // lets gray it out
-                    int grey = view.getContext().getColor(
-                            com.android.internal.R.color.notification_default_color_light);
+                    Configuration config = view.getContext().getResources().getConfiguration();
+                    boolean inNightMode = (config.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+                            == Configuration.UI_MODE_NIGHT_YES;
+                    int grey = ContrastColorUtil.resolveColor(view.getContext(),
+                            Notification.COLOR_DEFAULT, inNightMode);
                     imageView.getDrawable().setColorFilter(grey, PorterDuff.Mode.SRC_ATOP);
                 } else {
                     // lets reset it
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
deleted file mode 100644
index bd40686..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.annotation.Nullable;
-import android.app.INotificationManager;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.service.notification.StatusBarNotification;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.NotificationCounters;
-
-import java.util.List;
-
-/**
- * The guts of a notification revealed when performing a long press. This also houses the blocking
- * helper affordance that allows a user to keep/stop notifications after swiping one away.
- */
-public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
-    private static final String TAG = "InfoGuts";
-
-    private INotificationManager mINotificationManager;
-    private PackageManager mPm;
-    private MetricsLogger mMetricsLogger;
-
-    private String mPackageName;
-    private String mAppName;
-    private int mAppUid;
-    private int mNumUniqueChannelsInRow;
-    private NotificationChannel mSingleNotificationChannel;
-    private int mStartingUserImportance;
-    private int mChosenImportance;
-    private boolean mIsSingleDefaultChannel;
-    private boolean mIsNonblockable;
-    private StatusBarNotification mSbn;
-    private AnimatorSet mExpandAnimation;
-    private boolean mIsForeground;
-
-    private CheckSaveListener mCheckSaveListener;
-    private OnSettingsClickListener mOnSettingsClickListener;
-    private OnAppSettingsClickListener mAppSettingsClickListener;
-    private NotificationGuts mGutsContainer;
-
-    /** Whether this view is being shown as part of the blocking helper. */
-    private boolean mIsForBlockingHelper;
-    private boolean mNegativeUserSentiment;
-
-    /**
-     * String that describes how the user exit or quit out of this view, also used as a counter tag.
-     */
-    private String mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
-
-    private OnClickListener mOnKeepShowing = v -> {
-        mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
-        closeControls(v);
-    };
-
-    private OnClickListener mOnStopOrMinimizeNotifications = v -> {
-        mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
-        swapContent(false);
-    };
-
-    private OnClickListener mOnUndo = v -> {
-        // Reset exit counter that we'll log and record an undo event separately (not an exit event)
-        mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
-        logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
-        swapContent(true);
-    };
-
-    public NotificationInfo(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    // Specify a CheckSaveListener to override when/if the user's changes are committed.
-    public interface CheckSaveListener {
-        // Invoked when importance has changed and the NotificationInfo wants to try to save it.
-        // Listener should run saveImportance unless the change should be canceled.
-        void checkSave(Runnable saveImportance, StatusBarNotification sbn);
-    }
-
-    public interface OnSettingsClickListener {
-        void onClick(View v, NotificationChannel channel, int appUid);
-    }
-
-    public interface OnAppSettingsClickListener {
-        void onClick(View v, Intent intent);
-    }
-
-    @VisibleForTesting
-    void bindNotification(
-            final PackageManager pm,
-            final INotificationManager iNotificationManager,
-            final String pkg,
-            final NotificationChannel notificationChannel,
-            final int numUniqueChannelsInRow,
-            final StatusBarNotification sbn,
-            final CheckSaveListener checkSaveListener,
-            final OnSettingsClickListener onSettingsClick,
-            final OnAppSettingsClickListener onAppSettingsClick,
-            boolean isNonblockable)
-            throws RemoteException {
-        bindNotification(pm, iNotificationManager, pkg, notificationChannel,
-                numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
-                onAppSettingsClick, isNonblockable, false /* isBlockingHelper */,
-                false /* isUserSentimentNegative */);
-    }
-
-    public void bindNotification(
-            PackageManager pm,
-            INotificationManager iNotificationManager,
-            String pkg,
-            NotificationChannel notificationChannel,
-            int numUniqueChannelsInRow,
-            StatusBarNotification sbn,
-            CheckSaveListener checkSaveListener,
-            OnSettingsClickListener onSettingsClick,
-            OnAppSettingsClickListener onAppSettingsClick,
-            boolean isNonblockable,
-            boolean isForBlockingHelper,
-            boolean isUserSentimentNegative)
-            throws RemoteException {
-        mINotificationManager = iNotificationManager;
-        mMetricsLogger = Dependency.get(MetricsLogger.class);
-        mPackageName = pkg;
-        mNumUniqueChannelsInRow = numUniqueChannelsInRow;
-        mSbn = sbn;
-        mPm = pm;
-        mAppSettingsClickListener = onAppSettingsClick;
-        mAppName = mPackageName;
-        mCheckSaveListener = checkSaveListener;
-        mOnSettingsClickListener = onSettingsClick;
-        mSingleNotificationChannel = notificationChannel;
-        mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
-        mNegativeUserSentiment = isUserSentimentNegative;
-        mIsNonblockable = isNonblockable;
-        mIsForeground =
-                (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
-        mIsForBlockingHelper = isForBlockingHelper;
-        mAppUid = mSbn.getUid();
-
-        int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
-                pkg, mAppUid, false /* includeDeleted */);
-        if (mNumUniqueChannelsInRow == 0) {
-            throw new IllegalArgumentException("bindNotification requires at least one channel");
-        } else  {
-            // Special behavior for the Default channel if no other channels have been defined.
-            mIsSingleDefaultChannel = mNumUniqueChannelsInRow == 1
-                    && mSingleNotificationChannel.getId().equals(
-                            NotificationChannel.DEFAULT_CHANNEL_ID)
-                    && numTotalChannels == 1;
-        }
-
-        bindHeader();
-        bindPrompt();
-        bindButtons();
-    }
-
-    private void bindHeader() throws RemoteException {
-        // Package name
-        Drawable pkgicon = null;
-        ApplicationInfo info;
-        try {
-            info = mPm.getApplicationInfo(
-                    mPackageName,
-                    PackageManager.MATCH_UNINSTALLED_PACKAGES
-                            | PackageManager.MATCH_DISABLED_COMPONENTS
-                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-                            | PackageManager.MATCH_DIRECT_BOOT_AWARE);
-            if (info != null) {
-                mAppName = String.valueOf(mPm.getApplicationLabel(info));
-                pkgicon = mPm.getApplicationIcon(info);
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            // app is gone, just show package name and generic icon
-            pkgicon = mPm.getDefaultActivityIcon();
-        }
-        ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
-        ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
-
-        // Set group information if this channel has an associated group.
-        CharSequence groupName = null;
-        if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
-            final NotificationChannelGroup notificationChannelGroup =
-                    mINotificationManager.getNotificationChannelGroupForPackage(
-                            mSingleNotificationChannel.getGroup(), mPackageName, mAppUid);
-            if (notificationChannelGroup != null) {
-                groupName = notificationChannelGroup.getName();
-            }
-        }
-        TextView groupNameView = findViewById(R.id.group_name);
-        TextView groupDividerView = findViewById(R.id.pkg_group_divider);
-        if (groupName != null) {
-            groupNameView.setText(groupName);
-            groupNameView.setVisibility(View.VISIBLE);
-            groupDividerView.setVisibility(View.VISIBLE);
-        } else {
-            groupNameView.setVisibility(View.GONE);
-            groupDividerView.setVisibility(View.GONE);
-        }
-
-        // Settings button.
-        final View settingsButton = findViewById(R.id.info);
-        if (mAppUid >= 0 && mOnSettingsClickListener != null) {
-            settingsButton.setVisibility(View.VISIBLE);
-            final int appUidF = mAppUid;
-            settingsButton.setOnClickListener(
-                    (View view) -> {
-                        logBlockingHelperCounter(
-                                NotificationCounters.BLOCKING_HELPER_NOTIF_SETTINGS);
-                        mOnSettingsClickListener.onClick(view,
-                                mNumUniqueChannelsInRow > 1 ? null : mSingleNotificationChannel,
-                                appUidF);
-                    });
-        } else {
-            settingsButton.setVisibility(View.GONE);
-        }
-    }
-
-    private void bindPrompt() {
-        final TextView blockPrompt = findViewById(R.id.block_prompt);
-        bindName();
-        if (mIsNonblockable) {
-            blockPrompt.setText(R.string.notification_unblockable_desc);
-        } else {
-            if (mNegativeUserSentiment) {
-                blockPrompt.setText(R.string.inline_blocking_helper);
-            }  else if (mIsSingleDefaultChannel || mNumUniqueChannelsInRow > 1) {
-                blockPrompt.setText(R.string.inline_keep_showing_app);
-            } else {
-                blockPrompt.setText(R.string.inline_keep_showing);
-            }
-        }
-    }
-
-    private void bindName() {
-        final TextView channelName = findViewById(R.id.channel_name);
-        if (mIsSingleDefaultChannel || mNumUniqueChannelsInRow > 1) {
-            channelName.setVisibility(View.GONE);
-        } else {
-            channelName.setText(mSingleNotificationChannel.getName());
-        }
-    }
-
-    @VisibleForTesting
-    void logBlockingHelperCounter(String counterTag) {
-        if (mIsForBlockingHelper) {
-            mMetricsLogger.count(counterTag, 1);
-        }
-    }
-
-    private boolean hasImportanceChanged() {
-        return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
-    }
-
-    private void saveImportance() {
-        if (!mIsNonblockable) {
-            // Only go through the lock screen/bouncer if the user hit 'Stop notifications'.
-            // Otherwise, update the importance immediately.
-            if (mCheckSaveListener != null
-                    && NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS.equals(
-                            mExitReason)) {
-                mCheckSaveListener.checkSave(this::updateImportance, mSbn);
-            } else {
-                updateImportance();
-            }
-        }
-    }
-
-    /**
-     * Commits the updated importance values on the background thread.
-     */
-    private void updateImportance() {
-        MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
-                mChosenImportance - mStartingUserImportance);
-
-        Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
-        bgHandler.post(new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
-                mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null,
-                mStartingUserImportance, mChosenImportance));
-    }
-
-    private void bindButtons() {
-        // Set up stay-in-notification actions
-        View block =  findViewById(R.id.block);
-        TextView keep = findViewById(R.id.keep);
-        View minimize = findViewById(R.id.minimize);
-
-        findViewById(R.id.undo).setOnClickListener(mOnUndo);
-        block.setOnClickListener(mOnStopOrMinimizeNotifications);
-        keep.setOnClickListener(mOnKeepShowing);
-        minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
-
-        if (mIsNonblockable) {
-            keep.setText(android.R.string.ok);
-            block.setVisibility(GONE);
-            minimize.setVisibility(GONE);
-        } else if (mIsForeground) {
-            block.setVisibility(GONE);
-            minimize.setVisibility(VISIBLE);
-        } else if (!mIsForeground) {
-            block.setVisibility(VISIBLE);
-            minimize.setVisibility(GONE);
-        }
-
-        // Set up app settings link (i.e. Customize)
-        TextView settingsLinkView = findViewById(R.id.app_settings);
-        Intent settingsIntent = getAppSettingsIntent(mPm, mPackageName, mSingleNotificationChannel,
-                mSbn.getId(), mSbn.getTag());
-        if (!mIsForBlockingHelper
-                && settingsIntent != null
-                && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
-            settingsLinkView.setVisibility(VISIBLE);
-            settingsLinkView.setText(mContext.getString(R.string.notification_app_settings));
-            settingsLinkView.setOnClickListener((View view) -> {
-                mAppSettingsClickListener.onClick(view, settingsIntent);
-            });
-        } else {
-            settingsLinkView.setVisibility(View.GONE);
-        }
-    }
-
-    private void swapContent(boolean showPrompt) {
-        if (mExpandAnimation != null) {
-            mExpandAnimation.cancel();
-        }
-
-        View prompt = findViewById(R.id.prompt);
-        ViewGroup confirmation = findViewById(R.id.confirmation);
-        TextView confirmationText = findViewById(R.id.confirmation_text);
-        View header = findViewById(R.id.header);
-
-        if (showPrompt) {
-            mChosenImportance = mStartingUserImportance;
-        } else if (mIsForeground) {
-            mChosenImportance = IMPORTANCE_MIN;
-            confirmationText.setText(R.string.notification_channel_minimized);
-        } else {
-            mChosenImportance = IMPORTANCE_NONE;
-            confirmationText.setText(R.string.notification_channel_disabled);
-        }
-
-        ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
-                prompt.getAlpha(), showPrompt ? 1f : 0f);
-        promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
-        ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
-                confirmation.getAlpha(), showPrompt ? 0f : 1f);
-        confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
-
-        prompt.setVisibility(showPrompt ? VISIBLE : GONE);
-        confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
-        header.setVisibility(showPrompt ? VISIBLE : GONE);
-
-        mExpandAnimation = new AnimatorSet();
-        mExpandAnimation.playTogether(promptAnim, confirmAnim);
-        mExpandAnimation.setDuration(150);
-        mExpandAnimation.addListener(new AnimatorListenerAdapter() {
-            boolean cancelled = false;
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                cancelled = true;
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (!cancelled) {
-                    prompt.setVisibility(showPrompt ? VISIBLE : GONE);
-                    confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
-                }
-            }
-        });
-        mExpandAnimation.start();
-
-        // Since we're swapping/update the content, reset the timeout so the UI can't close
-        // immediately after the update.
-        if (mGutsContainer != null) {
-            mGutsContainer.resetFalsingCheck();
-        }
-    }
-
-    @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEvent(event);
-        if (mGutsContainer != null &&
-                event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-            if (mGutsContainer.isExposed()) {
-                event.getText().add(mContext.getString(
-                        R.string.notification_channel_controls_opened_accessibility, mAppName));
-            } else {
-                event.getText().add(mContext.getString(
-                        R.string.notification_channel_controls_closed_accessibility, mAppName));
-            }
-        }
-    }
-
-    private Intent getAppSettingsIntent(PackageManager pm, String packageName,
-            NotificationChannel channel, int id, String tag) {
-        Intent intent = new Intent(Intent.ACTION_MAIN)
-                .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
-                .setPackage(packageName);
-        final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
-                intent,
-                PackageManager.MATCH_DEFAULT_ONLY
-        );
-        if (resolveInfos == null || resolveInfos.size() == 0 || resolveInfos.get(0) == null) {
-            return null;
-        }
-        final ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
-        intent.setClassName(activityInfo.packageName, activityInfo.name);
-        if (channel != null) {
-            intent.putExtra(Notification.EXTRA_CHANNEL_ID, channel.getId());
-        }
-        intent.putExtra(Notification.EXTRA_NOTIFICATION_ID, id);
-        intent.putExtra(Notification.EXTRA_NOTIFICATION_TAG, tag);
-        return intent;
-    }
-
-    /**
-     * Closes the controls and commits the updated importance values (indirectly). If this view is
-     * being used to show the blocking helper, this will immediately dismiss the blocking helper and
-     * commit the updated importance.
-     *
-     * <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
-     * user does not have the ability to undo the action anymore. See {@link #swapContent(boolean)}
-     * for where undo is handled.
-     */
-    @VisibleForTesting
-    void closeControls(View v) {
-        int[] parentLoc = new int[2];
-        int[] targetLoc = new int[2];
-        mGutsContainer.getLocationOnScreen(parentLoc);
-        v.getLocationOnScreen(targetLoc);
-        final int centerX = v.getWidth() / 2;
-        final int centerY = v.getHeight() / 2;
-        final int x = targetLoc[0] - parentLoc[0] + centerX;
-        final int y = targetLoc[1] - parentLoc[1] + centerY;
-        mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
-    }
-
-    @Override
-    public void setGutsParent(NotificationGuts guts) {
-        mGutsContainer = guts;
-    }
-
-    @Override
-    public boolean willBeRemoved() {
-        return hasImportanceChanged();
-    }
-
-    @Override
-    public boolean shouldBeSaved() {
-        return hasImportanceChanged();
-    }
-
-    @Override
-    public View getContentView() {
-        return this;
-    }
-
-    @Override
-    public boolean handleCloseControls(boolean save, boolean force) {
-        // Save regardless of the importance so we can lock the importance field if the user wants
-        // to keep getting notifications
-        if (save) {
-            saveImportance();
-        }
-        logBlockingHelperCounter(mExitReason);
-        return false;
-    }
-
-    @Override
-    public int getActualHeight() {
-        return getHeight();
-    }
-
-    /**
-     * Runnable to either update the given channel (with a new importance value) or, if no channel
-     * is provided, update notifications enabled state for the package.
-     */
-    private static class UpdateImportanceRunnable implements Runnable {
-        private final INotificationManager mINotificationManager;
-        private final String mPackageName;
-        private final int mAppUid;
-        private final @Nullable NotificationChannel mChannelToUpdate;
-        private final int mCurrentImportance;
-        private final int mNewImportance;
-
-
-        public UpdateImportanceRunnable(INotificationManager notificationManager,
-                String packageName, int appUid, @Nullable NotificationChannel channelToUpdate,
-                int currentImportance, int newImportance) {
-            mINotificationManager = notificationManager;
-            mPackageName = packageName;
-            mAppUid = appUid;
-            mChannelToUpdate = channelToUpdate;
-            mCurrentImportance = currentImportance;
-            mNewImportance = newImportance;
-        }
-
-        @Override
-        public void run() {
-            try {
-                if (mChannelToUpdate != null) {
-                    mChannelToUpdate.setImportance(mNewImportance);
-                    mChannelToUpdate.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
-                    mINotificationManager.updateNotificationChannelForPackage(
-                            mPackageName, mAppUid, mChannelToUpdate);
-                } else {
-                    // For notifications with more than one channel, update notification enabled
-                    // state. If the importance was lowered, we disable notifications.
-                    mINotificationManager.setNotificationsEnabledWithImportanceLockForPackage(
-                            mPackageName, mAppUid, mNewImportance >= mCurrentImportance);
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "Unable to update notification importance", e);
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListContainer.java
deleted file mode 100644
index af9a3a3..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListContainer.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
-
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-
-/**
- * Interface representing the entity that contains notifications. It can have
- * notification views added and removed from it, and will manage displaying them to the user.
- */
-public interface NotificationListContainer {
-
-    /**
-     * Called when a child is being transferred.
-     *
-     * @param childTransferInProgress whether child transfer is in progress
-     */
-    void setChildTransferInProgress(boolean childTransferInProgress);
-
-    /**
-     * Change the position of child to a new location
-     *
-     * @param child the view to change the position for
-     * @param newIndex the new index
-     */
-    void changeViewPosition(View child, int newIndex);
-
-    /**
-     * Called when a child was added to a group.
-     *
-     * @param row row of the group child that was added
-     */
-    void notifyGroupChildAdded(View row);
-
-    /**
-     * Called when a child was removed from a group.
-     *
-     * @param row row of the child that was removed
-     * @param childrenContainer ViewGroup of the group that the child was removed from
-     */
-    void notifyGroupChildRemoved(View row, ViewGroup childrenContainer);
-
-    /**
-     * Generate an animation for an added child view.
-     *
-     * @param child The view to be added.
-     * @param fromMoreCard Whether this add is coming from the "more" card on lockscreen.
-     */
-    void generateAddAnimation(View child, boolean fromMoreCard);
-
-    /**
-     * Generate a child order changed event.
-     */
-    void generateChildOrderChangedEvent();
-
-    /**
-     * Returns the number of children in the NotificationListContainer.
-     *
-     * @return the number of children in the NotificationListContainer
-     */
-    int getContainerChildCount();
-
-    /**
-     * Gets the ith child in the NotificationListContainer.
-     *
-     * @param i ith child to get
-     * @return the ith child in the list container
-     */
-    View getContainerChildAt(int i);
-
-    /**
-     * Remove a view from the container
-     *
-     * @param v view to remove
-     */
-    void removeContainerView(View v);
-
-    /**
-     * Add a view to the container
-     *
-     * @param v view to add
-     */
-    void addContainerView(View v);
-
-    /**
-     * Sets the maximum number of notifications to display.
-     *
-     * @param maxNotifications max number of notifications to display
-     */
-    void setMaxDisplayedNotifications(int maxNotifications);
-
-    /**
-     * Handle snapping a non-dismissable row back if the user tried to dismiss it.
-     *
-     * @param row row to snap back
-     */
-    void snapViewIfNeeded(ExpandableNotificationRow row);
-
-    /**
-     * Get the view parent for a notification entry. For example, NotificationStackScrollLayout.
-     *
-     * @param entry entry to get the view parent for
-     * @return the view parent for entry
-     */
-    ViewGroup getViewParentForNotification(NotificationData.Entry entry);
-
-    /**
-     * Called when the height of an expandable view changes.
-     *
-     * @param view view whose height changed
-     * @param animate whether this change should be animated
-     */
-    void onHeightChanged(ExpandableView view, boolean animate);
-
-    /**
-     * Resets the currently exposed menu view.
-     *
-     * @param animate whether to animate the closing/change of menu view
-     * @param force reset the menu view even if it looks like it is already reset
-     */
-    void resetExposedMenuView(boolean animate, boolean force);
-
-    /**
-     * Returns the NotificationSwipeActionHelper for the NotificationListContainer.
-     *
-     * @return swipe action helper for the list container
-     */
-    NotificationSwipeActionHelper getSwipeActionHelper();
-
-    /**
-     * Called when a notification is removed from the shade. This cleans up the state for a
-     * given view.
-     *
-     * @param view view to clean up view state for
-     */
-    void cleanUpViewState(View view);
-
-    /**
-     * Returns whether an ExpandableNotificationRow is in a visible location or not.
-     *
-     * @param row
-     * @return true if row is in a visible location
-     */
-    boolean isInVisibleLocation(ExpandableNotificationRow row);
-
-    /**
-     * Sets a listener to listen for changes in notification locations.
-     *
-     * @param listener listener to set
-     */
-    void setChildLocationsChangedListener(
-            NotificationLogger.OnChildLocationsChangedListener listener);
-
-    /**
-     * Called when an update to the notification view hierarchy is completed.
-     */
-    default void onNotificationViewUpdateFinished() {}
-
-    /**
-     * Returns true if there are pulsing notifications.
-     *
-     * @return true if has pulsing notifications
-     */
-    boolean hasPulsingNotifications();
-
-    /**
-     * Apply parameters of the expand animation to the layout
-     */
-    default void applyExpandAnimationParams(ExpandAnimationParameters params) {}
-
-    default void setExpandingNotification(ExpandableNotificationRow row) {}
-
-    /**
-     * Bind a newly created row.
-     *
-     * @param row The notification to bind.
-     */
-    default void bindRow(ExpandableNotificationRow row) {}
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index a2d0c2b..9b375df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -28,6 +28,7 @@
 import android.util.Log;
 
 import com.android.systemui.Dependency;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index 2f62d59..d6886f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -16,7 +16,6 @@
 package com.android.systemui.statusbar;
 
 import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
 import android.app.Notification;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
@@ -35,8 +34,6 @@
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
-import android.widget.TextView;
-import android.widget.Toast;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
@@ -44,7 +41,8 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.OverviewProxyService;
-import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
 import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLogger.java
deleted file mode 100644
index 8e8e718..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLogger.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.service.notification.NotificationListenerService;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.Dependency;
-import com.android.systemui.UiOffloadThread;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * Handles notification logging, in particular, logging which notifications are visible and which
- * are not.
- */
-public class NotificationLogger {
-    private static final String TAG = "NotificationLogger";
-
-    /** The minimum delay in ms between reports of notification visibility. */
-    private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500;
-
-    /** Keys of notifications currently visible to the user. */
-    private final ArraySet<NotificationVisibility> mCurrentlyVisibleNotifications =
-            new ArraySet<>();
-
-    // Dependencies:
-    private final NotificationListenerService mNotificationListener =
-            Dependency.get(NotificationListener.class);
-    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
-
-    protected NotificationEntryManager mEntryManager;
-    protected Handler mHandler = new Handler();
-    protected IStatusBarService mBarService;
-    private long mLastVisibilityReportUptimeMs;
-    private NotificationListContainer mListContainer;
-
-    protected final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
-            new OnChildLocationsChangedListener() {
-                @Override
-                public void onChildLocationsChanged() {
-                    if (mHandler.hasCallbacks(mVisibilityReporter)) {
-                        // Visibilities will be reported when the existing
-                        // callback is executed.
-                        return;
-                    }
-                    // Calculate when we're allowed to run the visibility
-                    // reporter. Note that this timestamp might already have
-                    // passed. That's OK, the callback will just be executed
-                    // ASAP.
-                    long nextReportUptimeMs =
-                            mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS;
-                    mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs);
-                }
-            };
-
-    // Tracks notifications currently visible in mNotificationStackScroller and
-    // emits visibility events via NoMan on changes.
-    protected final Runnable mVisibilityReporter = new Runnable() {
-        private final ArraySet<NotificationVisibility> mTmpNewlyVisibleNotifications =
-                new ArraySet<>();
-        private final ArraySet<NotificationVisibility> mTmpCurrentlyVisibleNotifications =
-                new ArraySet<>();
-        private final ArraySet<NotificationVisibility> mTmpNoLongerVisibleNotifications =
-                new ArraySet<>();
-
-        @Override
-        public void run() {
-            mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis();
-
-            // 1. Loop over mNotificationData entries:
-            //   A. Keep list of visible notifications.
-            //   B. Keep list of previously hidden, now visible notifications.
-            // 2. Compute no-longer visible notifications by removing currently
-            //    visible notifications from the set of previously visible
-            //    notifications.
-            // 3. Report newly visible and no-longer visible notifications.
-            // 4. Keep currently visible notifications for next report.
-            ArrayList<NotificationData.Entry> activeNotifications = mEntryManager
-                    .getNotificationData().getActiveNotifications();
-            int N = activeNotifications.size();
-            for (int i = 0; i < N; i++) {
-                NotificationData.Entry entry = activeNotifications.get(i);
-                String key = entry.notification.getKey();
-                boolean isVisible = mListContainer.isInVisibleLocation(entry.row);
-                NotificationVisibility visObj = NotificationVisibility.obtain(key, i, N, isVisible);
-                boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(visObj);
-                if (isVisible) {
-                    // Build new set of visible notifications.
-                    mTmpCurrentlyVisibleNotifications.add(visObj);
-                    if (!previouslyVisible) {
-                        mTmpNewlyVisibleNotifications.add(visObj);
-                    }
-                } else {
-                    // release object
-                    visObj.recycle();
-                }
-            }
-            mTmpNoLongerVisibleNotifications.addAll(mCurrentlyVisibleNotifications);
-            mTmpNoLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
-
-            logNotificationVisibilityChanges(
-                    mTmpNewlyVisibleNotifications, mTmpNoLongerVisibleNotifications);
-
-            recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
-            mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications);
-
-            recycleAllVisibilityObjects(mTmpNoLongerVisibleNotifications);
-            mTmpCurrentlyVisibleNotifications.clear();
-            mTmpNewlyVisibleNotifications.clear();
-            mTmpNoLongerVisibleNotifications.clear();
-        }
-    };
-
-    public NotificationLogger() {
-        mBarService = IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-    }
-
-    public void setUpWithEntryManager(NotificationEntryManager entryManager,
-            NotificationListContainer listContainer) {
-        mEntryManager = entryManager;
-        mListContainer = listContainer;
-    }
-
-    public void stopNotificationLogging() {
-        // Report all notifications as invisible and turn down the
-        // reporter.
-        if (!mCurrentlyVisibleNotifications.isEmpty()) {
-            logNotificationVisibilityChanges(
-                    Collections.emptyList(), mCurrentlyVisibleNotifications);
-            recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
-        }
-        mHandler.removeCallbacks(mVisibilityReporter);
-        mListContainer.setChildLocationsChangedListener(null);
-    }
-
-    public void startNotificationLogging() {
-        mListContainer.setChildLocationsChangedListener(mNotificationLocationsChangedListener);
-        // Some transitions like mVisibleToUser=false -> mVisibleToUser=true don't
-        // cause the scroller to emit child location events. Hence generate
-        // one ourselves to guarantee that we're reporting visible
-        // notifications.
-        // (Note that in cases where the scroller does emit events, this
-        // additional event doesn't break anything.)
-        mNotificationLocationsChangedListener.onChildLocationsChanged();
-    }
-
-    private void logNotificationVisibilityChanges(
-            Collection<NotificationVisibility> newlyVisible,
-            Collection<NotificationVisibility> noLongerVisible) {
-        if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
-            return;
-        }
-        final NotificationVisibility[] newlyVisibleAr = cloneVisibilitiesAsArr(newlyVisible);
-        final NotificationVisibility[] noLongerVisibleAr = cloneVisibilitiesAsArr(noLongerVisible);
-
-        mUiOffloadThread.submit(() -> {
-            try {
-                mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
-            } catch (RemoteException e) {
-                // Ignore.
-            }
-
-            final int N = newlyVisible.size();
-            if (N > 0) {
-                String[] newlyVisibleKeyAr = new String[N];
-                for (int i = 0; i < N; i++) {
-                    newlyVisibleKeyAr[i] = newlyVisibleAr[i].key;
-                }
-
-                // TODO: Call NotificationEntryManager to do this, once it exists.
-                // TODO: Consider not catching all runtime exceptions here.
-                try {
-                    mNotificationListener.setNotificationsShown(newlyVisibleKeyAr);
-                } catch (RuntimeException e) {
-                    Log.d(TAG, "failed setNotificationsShown: ", e);
-                }
-            }
-            recycleAllVisibilityObjects(newlyVisibleAr);
-            recycleAllVisibilityObjects(noLongerVisibleAr);
-        });
-    }
-
-    private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
-        final int N = array.size();
-        for (int i = 0 ; i < N; i++) {
-            array.valueAt(i).recycle();
-        }
-        array.clear();
-    }
-
-    private void recycleAllVisibilityObjects(NotificationVisibility[] array) {
-        final int N = array.length;
-        for (int i = 0 ; i < N; i++) {
-            if (array[i] != null) {
-                array[i].recycle();
-            }
-        }
-    }
-
-    private NotificationVisibility[] cloneVisibilitiesAsArr(Collection<NotificationVisibility> c) {
-
-        final NotificationVisibility[] array = new NotificationVisibility[c.size()];
-        int i = 0;
-        for(NotificationVisibility nv: c) {
-            if (nv != null) {
-                array[i] = nv.clone();
-            }
-            i++;
-        }
-        return array;
-    }
-
-    @VisibleForTesting
-    public Runnable getVisibilityReporter() {
-        return mVisibilityReporter;
-    }
-
-    /**
-     * A listener that is notified when some child locations might have changed.
-     */
-    public interface OnChildLocationsChangedListener {
-        void onChildLocationsChanged();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index f737a8c..e89e6e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -26,6 +26,8 @@
 import android.util.Log;
 
 import com.android.systemui.Dumpable;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
deleted file mode 100644
index ada1a17..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
-
-import java.util.ArrayList;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-import com.android.systemui.statusbar.NotificationGuts.GutsContent;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.annotation.Nullable;
-import android.app.Notification;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-import android.service.notification.StatusBarNotification;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.FrameLayout.LayoutParams;
-
-public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnClickListener,
-        ExpandableNotificationRow.LayoutListener {
-
-    private static final boolean DEBUG = false;
-    private static final String TAG = "swipe";
-
-    private static final int ICON_ALPHA_ANIM_DURATION = 200;
-    private static final long SHOW_MENU_DELAY = 60;
-    private static final long SWIPE_MENU_TIMING = 200;
-
-    // Notification must be swiped at least this fraction of a single menu item to show menu
-    private static final float SWIPED_FAR_ENOUGH_MENU_FRACTION = 0.25f;
-    private static final float SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION = 0.15f;
-
-    // When the menu is displayed, the notification must be swiped within this fraction of a single
-    // menu item to snap back to menu (else it will cover the menu or it'll be dismissed)
-    private static final float SWIPED_BACK_ENOUGH_TO_COVER_FRACTION = 0.2f;
-
-    private ExpandableNotificationRow mParent;
-
-    private Context mContext;
-    private FrameLayout mMenuContainer;
-    private MenuItem mInfoItem;
-    private MenuItem mAppOpsItem;
-    private MenuItem mSnoozeItem;
-    private ArrayList<MenuItem> mMenuItems;
-    private OnMenuEventListener mMenuListener;
-
-    private ValueAnimator mFadeAnimator;
-    private boolean mAnimating;
-    private boolean mMenuFadedIn;
-
-    private boolean mOnLeft;
-    private boolean mIconsPlaced;
-
-    private boolean mDismissing;
-    private boolean mSnapping;
-    private float mTranslation;
-
-    private int[] mIconLocation = new int[2];
-    private int[] mParentLocation = new int[2];
-
-    private float mHorizSpaceForIcon = -1;
-    private int mVertSpaceForIcons = -1;
-    private int mIconPadding = -1;
-    private int mSidePadding;
-
-    private float mAlpha = 0f;
-    private float mPrevX;
-
-    private CheckForDrag mCheckForDrag;
-    private Handler mHandler;
-
-    private boolean mMenuSnappedTo;
-    private boolean mMenuSnappedOnLeft;
-    private boolean mShouldShowMenu;
-
-    private NotificationSwipeActionHelper mSwipeHelper;
-    private boolean mIsUserTouching;
-
-    public NotificationMenuRow(Context context) {
-        mContext = context;
-        mShouldShowMenu = context.getResources().getBoolean(R.bool.config_showNotificationGear);
-        mHandler = new Handler(Looper.getMainLooper());
-        mMenuItems = new ArrayList<>();
-    }
-
-    @Override
-    public ArrayList<MenuItem> getMenuItems(Context context) {
-        return mMenuItems;
-    }
-
-    @Override
-    public MenuItem getLongpressMenuItem(Context context) {
-        return mInfoItem;
-    }
-
-    @Override
-    public MenuItem getAppOpsMenuItem(Context context) {
-        return mAppOpsItem;
-    }
-
-    @Override
-    public MenuItem getSnoozeMenuItem(Context context) {
-        return mSnoozeItem;
-    }
-
-    @Override
-    public void setSwipeActionHelper(NotificationSwipeActionHelper helper) {
-        mSwipeHelper = helper;
-    }
-
-    @Override
-    public void setMenuClickListener(OnMenuEventListener listener) {
-        mMenuListener = listener;
-    }
-
-    @Override
-    public void createMenu(ViewGroup parent, StatusBarNotification sbn) {
-        mParent = (ExpandableNotificationRow) parent;
-        createMenuViews(true /* resetState */);
-    }
-
-    @Override
-    public boolean isMenuVisible() {
-        return mAlpha > 0;
-    }
-
-    @Override
-    public View getMenuView() {
-        return mMenuContainer;
-    }
-
-    @Override
-    public void resetMenu() {
-        resetState(true);
-    }
-
-    @Override
-    public void onNotificationUpdated(StatusBarNotification sbn) {
-        if (mMenuContainer == null) {
-            // Menu hasn't been created yet, no need to do anything.
-            return;
-        }
-        createMenuViews(!isMenuVisible() /* resetState */);
-    }
-
-    @Override
-    public void onConfigurationChanged() {
-        mParent.setLayoutListener(this);
-    }
-
-    @Override
-    public void onLayout() {
-        mIconsPlaced = false; // Force icons to be re-placed
-        setMenuLocation();
-        mParent.removeListener();
-    }
-
-    private void createMenuViews(boolean resetState) {
-        final Resources res = mContext.getResources();
-        mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
-        mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
-        mMenuItems.clear();
-        // Construct the menu items based on the notification
-        if (mParent != null && mParent.getStatusBarNotification() != null) {
-            int flags = mParent.getStatusBarNotification().getNotification().flags;
-            boolean isForeground = (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
-            if (!isForeground) {
-                // Only show snooze for non-foreground notifications
-                mSnoozeItem = createSnoozeItem(mContext);
-                mMenuItems.add(mSnoozeItem);
-            }
-        }
-        mInfoItem = createInfoItem(mContext);
-        mMenuItems.add(mInfoItem);
-
-        mAppOpsItem = createAppOpsItem(mContext);
-        mMenuItems.add(mAppOpsItem);
-
-        // Construct the menu views
-        if (mMenuContainer != null) {
-            mMenuContainer.removeAllViews();
-        } else {
-            mMenuContainer = new FrameLayout(mContext);
-        }
-        for (int i = 0; i < mMenuItems.size(); i++) {
-            addMenuView(mMenuItems.get(i), mMenuContainer);
-        }
-        if (resetState) {
-            resetState(false /* notify */);
-        } else {
-            mIconsPlaced = false;
-            setMenuLocation();
-            if (!mIsUserTouching) {
-                // If the # of items showing changed we need to update the snap position
-                showMenu(mParent, mOnLeft ? getSpaceForMenu() : -getSpaceForMenu(),
-                        0 /* velocity */);
-            }
-        }
-    }
-
-    private void resetState(boolean notify) {
-        setMenuAlpha(0f);
-        mIconsPlaced = false;
-        mMenuFadedIn = false;
-        mAnimating = false;
-        mSnapping = false;
-        mDismissing = false;
-        mMenuSnappedTo = false;
-        setMenuLocation();
-        if (mMenuListener != null && notify) {
-            mMenuListener.onMenuReset(mParent);
-        }
-    }
-
-    @Override
-    public boolean onTouchEvent(View view, MotionEvent ev, float velocity) {
-        final int action = ev.getActionMasked();
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mSnapping = false;
-                if (mFadeAnimator != null) {
-                    mFadeAnimator.cancel();
-                }
-                mHandler.removeCallbacks(mCheckForDrag);
-                mCheckForDrag = null;
-                mPrevX = ev.getRawX();
-                mIsUserTouching = true;
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                mSnapping = false;
-                float diffX = ev.getRawX() - mPrevX;
-                mPrevX = ev.getRawX();
-                if (!isTowardsMenu(diffX) && isMenuLocationChange()) {
-                    // Don't consider it "snapped" if location has changed.
-                    mMenuSnappedTo = false;
-
-                    // Changed directions, make sure we check to fade in icon again.
-                    if (!mHandler.hasCallbacks(mCheckForDrag)) {
-                        // No check scheduled, set null to schedule a new one.
-                        mCheckForDrag = null;
-                    } else {
-                        // Check scheduled, reset alpha and update location; check will fade it in
-                        setMenuAlpha(0f);
-                        setMenuLocation();
-                    }
-                }
-                if (mShouldShowMenu
-                        && !NotificationStackScrollLayout.isPinnedHeadsUp(view)
-                        && !mParent.areGutsExposed()
-                        && !mParent.isDark()
-                        && (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag))) {
-                    // Only show the menu if we're not a heads up view and guts aren't exposed.
-                    mCheckForDrag = new CheckForDrag();
-                    mHandler.postDelayed(mCheckForDrag, SHOW_MENU_DELAY);
-                }
-                break;
-
-            case MotionEvent.ACTION_UP:
-                mIsUserTouching = false;
-                return handleUpEvent(ev, view, velocity);
-            case MotionEvent.ACTION_CANCEL:
-                mIsUserTouching = false;
-                cancelDrag();
-                return false;
-        }
-        return false;
-    }
-
-    private boolean handleUpEvent(MotionEvent ev, View animView, float velocity) {
-        // If the menu should not be shown, then there is no need to check if the a swipe
-        // should result in a snapping to the menu. As a result, just check if the swipe
-        // was enough to dismiss the notification.
-        if (!mShouldShowMenu) {
-            if (mSwipeHelper.isDismissGesture(ev)) {
-                dismiss(animView, velocity);
-            } else {
-                snapBack(animView, velocity);
-            }
-            return true;
-        }
-
-        final boolean gestureTowardsMenu = isTowardsMenu(velocity);
-        final boolean gestureFastEnough =
-                mSwipeHelper.getMinDismissVelocity() <= Math.abs(velocity);
-        final boolean gestureFarEnough =
-                mSwipeHelper.swipedFarEnough(mTranslation, mParent.getWidth());
-        final double timeForGesture = ev.getEventTime() - ev.getDownTime();
-        final boolean showMenuForSlowOnGoing = !mParent.canViewBeDismissed()
-                && timeForGesture >= SWIPE_MENU_TIMING;
-        final float menuSnapTarget = mOnLeft ? getSpaceForMenu() : -getSpaceForMenu();
-
-        if (DEBUG) {
-            Log.d(TAG, "mTranslation= " + mTranslation
-                    + " mAlpha= " + mAlpha
-                    + " velocity= " + velocity
-                    + " mMenuSnappedTo= " + mMenuSnappedTo
-                    + " mMenuSnappedOnLeft= " + mMenuSnappedOnLeft
-                    + " mOnLeft= " + mOnLeft
-                    + " minDismissVel= " + mSwipeHelper.getMinDismissVelocity()
-                    + " isDismissGesture= " + mSwipeHelper.isDismissGesture(ev)
-                    + " gestureTowardsMenu= " + gestureTowardsMenu
-                    + " gestureFastEnough= " + gestureFastEnough
-                    + " gestureFarEnough= " + gestureFarEnough);
-        }
-
-        if (mMenuSnappedTo && isMenuVisible() && mMenuSnappedOnLeft == mOnLeft) {
-            // Menu was snapped to previously and we're on the same side, figure out if
-            // we should stick to the menu, snap back into place, or dismiss
-            final float maximumSwipeDistance = mHorizSpaceForIcon
-                    * SWIPED_BACK_ENOUGH_TO_COVER_FRACTION;
-            final float targetLeft = getSpaceForMenu() - maximumSwipeDistance;
-            final float targetRight = mParent.getWidth() * SWIPED_FAR_ENOUGH_SIZE_FRACTION;
-            boolean withinSnapMenuThreshold = mOnLeft
-                    ? mTranslation > targetLeft && mTranslation < targetRight
-                    : mTranslation < -targetLeft && mTranslation > -targetRight;
-            boolean shouldSnapTo = mOnLeft ? mTranslation < targetLeft : mTranslation > -targetLeft;
-            if (DEBUG) {
-                Log.d(TAG, "   withinSnapMenuThreshold= " + withinSnapMenuThreshold
-                        + "   shouldSnapTo= " + shouldSnapTo
-                        + "   targetLeft= " + targetLeft
-                        + "   targetRight= " + targetRight);
-            }
-            if (withinSnapMenuThreshold && !mSwipeHelper.isDismissGesture(ev)) {
-                // Haven't moved enough to unsnap from the menu
-                showMenu(animView, menuSnapTarget, velocity);
-            } else if (mSwipeHelper.isDismissGesture(ev) && !shouldSnapTo) {
-                // Only dismiss if we're not moving towards the menu
-                dismiss(animView, velocity);
-            } else {
-                snapBack(animView, velocity);
-            }
-        } else if (!mSwipeHelper.isFalseGesture(ev)
-                && (swipedEnoughToShowMenu() && (!gestureFastEnough || showMenuForSlowOnGoing))
-                || (gestureTowardsMenu && !mSwipeHelper.isDismissGesture(ev))) {
-            // Menu has not been snapped to previously and this is menu revealing gesture
-            showMenu(animView, menuSnapTarget, velocity);
-        } else if (mSwipeHelper.isDismissGesture(ev) && !gestureTowardsMenu) {
-            dismiss(animView, velocity);
-        } else {
-            snapBack(animView, velocity);
-        }
-        return true;
-    }
-
-    private void showMenu(View animView, float targetLeft, float velocity) {
-        mMenuSnappedTo = true;
-        mMenuSnappedOnLeft = mOnLeft;
-        mMenuListener.onMenuShown(animView);
-        mSwipeHelper.snap(animView, targetLeft, velocity);
-    }
-
-    private void snapBack(View animView, float velocity) {
-        cancelDrag();
-        mMenuSnappedTo = false;
-        mSnapping = true;
-        mSwipeHelper.snap(animView, 0 /* leftTarget */, velocity);
-    }
-
-    private void dismiss(View animView, float velocity) {
-        cancelDrag();
-        mMenuSnappedTo = false;
-        mDismissing = true;
-        mSwipeHelper.dismiss(animView, velocity);
-    }
-
-    private void cancelDrag() {
-        if (mFadeAnimator != null) {
-            mFadeAnimator.cancel();
-        }
-        mHandler.removeCallbacks(mCheckForDrag);
-    }
-
-    /**
-     * @return whether the notification has been translated enough to show the menu and not enough
-     *         to be dismissed.
-     */
-    private boolean swipedEnoughToShowMenu() {
-        final float multiplier = mParent.canViewBeDismissed()
-                ? SWIPED_FAR_ENOUGH_MENU_FRACTION
-                : SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION;
-        final float minimumSwipeDistance = mHorizSpaceForIcon * multiplier;
-        return !mSwipeHelper.swipedFarEnough(0, 0) && isMenuVisible()
-                && (mOnLeft ? mTranslation > minimumSwipeDistance
-                        : mTranslation < -minimumSwipeDistance);
-    }
-
-    /**
-     * Returns whether the gesture is towards the menu location or not.
-     */
-    private boolean isTowardsMenu(float movement) {
-        return isMenuVisible()
-                && ((mOnLeft && movement <= 0)
-                        || (!mOnLeft && movement >= 0));
-    }
-
-    @Override
-    public void setAppName(String appName) {
-        if (appName == null) {
-            return;
-        }
-        Resources res = mContext.getResources();
-        final int count = mMenuItems.size();
-        for (int i = 0; i < count; i++) {
-            MenuItem item = mMenuItems.get(i);
-            String description = String.format(
-                    res.getString(R.string.notification_menu_accessibility),
-                    appName, item.getContentDescription());
-            View menuView = item.getMenuView();
-            if (menuView != null) {
-                menuView.setContentDescription(description);
-            }
-        }
-    }
-
-    @Override
-    public void onHeightUpdate() {
-        if (mParent == null || mMenuItems.size() == 0 || mMenuContainer == null) {
-            return;
-        }
-        int parentHeight = mParent.getActualHeight();
-        float translationY;
-        if (parentHeight < mVertSpaceForIcons) {
-            translationY = (parentHeight / 2) - (mHorizSpaceForIcon / 2);
-        } else {
-            translationY = (mVertSpaceForIcons - mHorizSpaceForIcon) / 2;
-        }
-        mMenuContainer.setTranslationY(translationY);
-    }
-
-    @Override
-    public void onTranslationUpdate(float translation) {
-        mTranslation = translation;
-        if (mAnimating || !mMenuFadedIn) {
-            // Don't adjust when animating, or if the menu hasn't been shown yet.
-            return;
-        }
-        final float fadeThreshold = mParent.getWidth() * 0.3f;
-        final float absTrans = Math.abs(translation);
-        float desiredAlpha = 0;
-        if (absTrans == 0) {
-            desiredAlpha = 0;
-        } else if (absTrans <= fadeThreshold) {
-            desiredAlpha = 1;
-        } else {
-            desiredAlpha = 1 - ((absTrans - fadeThreshold) / (mParent.getWidth() - fadeThreshold));
-        }
-        setMenuAlpha(desiredAlpha);
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (mMenuListener == null) {
-            // Nothing to do
-            return;
-        }
-        v.getLocationOnScreen(mIconLocation);
-        mParent.getLocationOnScreen(mParentLocation);
-        final int centerX = (int) (mHorizSpaceForIcon / 2);
-        final int centerY = v.getHeight() / 2;
-        final int x = mIconLocation[0] - mParentLocation[0] + centerX;
-        final int y = mIconLocation[1] - mParentLocation[1] + centerY;
-        final int index = mMenuContainer.indexOfChild(v);
-        mMenuListener.onMenuClicked(mParent, x, y, mMenuItems.get(index));
-    }
-
-    private boolean isMenuLocationChange() {
-        boolean onLeft = mTranslation > mIconPadding;
-        boolean onRight = mTranslation < -mIconPadding;
-        if ((mOnLeft && onRight) || (!mOnLeft && onLeft)) {
-            return true;
-        }
-        return false;
-    }
-
-    private void setMenuLocation() {
-        boolean showOnLeft = mTranslation > 0;
-        if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping || mMenuContainer == null
-                || !mMenuContainer.isAttachedToWindow()) {
-            // Do nothing
-            return;
-        }
-        final int count = mMenuContainer.getChildCount();
-        for (int i = 0; i < count; i++) {
-            final View v = mMenuContainer.getChildAt(i);
-            final float left = i * mHorizSpaceForIcon;
-            final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1));
-            v.setX(showOnLeft ? left : right);
-        }
-        mOnLeft = showOnLeft;
-        mIconsPlaced = true;
-    }
-
-    private void setMenuAlpha(float alpha) {
-        mAlpha = alpha;
-        if (mMenuContainer == null) {
-            return;
-        }
-        if (alpha == 0) {
-            mMenuFadedIn = false; // Can fade in again once it's gone.
-            mMenuContainer.setVisibility(View.INVISIBLE);
-        } else {
-            mMenuContainer.setVisibility(View.VISIBLE);
-        }
-        final int count = mMenuContainer.getChildCount();
-        for (int i = 0; i < count; i++) {
-            mMenuContainer.getChildAt(i).setAlpha(mAlpha);
-        }
-    }
-
-    /**
-     * Returns the horizontal space in pixels required to display the menu.
-     */
-    private float getSpaceForMenu() {
-        return mHorizSpaceForIcon * mMenuContainer.getChildCount();
-    }
-
-    private final class CheckForDrag implements Runnable {
-        @Override
-        public void run() {
-            final float absTransX = Math.abs(mTranslation);
-            final float bounceBackToMenuWidth = getSpaceForMenu();
-            final float notiThreshold = mParent.getWidth() * 0.4f;
-            if ((!isMenuVisible() || isMenuLocationChange())
-                    && absTransX >= bounceBackToMenuWidth * 0.4
-                    && absTransX < notiThreshold) {
-                fadeInMenu(notiThreshold);
-            }
-        }
-    }
-
-    private void fadeInMenu(final float notiThreshold) {
-        if (mDismissing || mAnimating) {
-            return;
-        }
-        if (isMenuLocationChange()) {
-            setMenuAlpha(0f);
-        }
-        final float transX = mTranslation;
-        final boolean fromLeft = mTranslation > 0;
-        setMenuLocation();
-        mFadeAnimator = ValueAnimator.ofFloat(mAlpha, 1);
-        mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                final float absTrans = Math.abs(transX);
-
-                boolean pastMenu = (fromLeft && transX <= notiThreshold)
-                        || (!fromLeft && absTrans <= notiThreshold);
-                if (pastMenu && !mMenuFadedIn) {
-                    setMenuAlpha((float) animation.getAnimatedValue());
-                }
-            }
-        });
-        mFadeAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                mAnimating = true;
-            }
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                // TODO should animate back to 0f from current alpha
-                setMenuAlpha(0f);
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mAnimating = false;
-                mMenuFadedIn = mAlpha == 1;
-            }
-        });
-        mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
-        mFadeAnimator.setDuration(ICON_ALPHA_ANIM_DURATION);
-        mFadeAnimator.start();
-    }
-
-    @Override
-    public void setMenuItems(ArrayList<MenuItem> items) {
-        // Do nothing we use our own for now.
-        // TODO -- handle / allow custom menu items!
-    }
-
-    public static MenuItem createSnoozeItem(Context context) {
-        Resources res = context.getResources();
-        NotificationSnooze content = (NotificationSnooze) LayoutInflater.from(context)
-                .inflate(R.layout.notification_snooze, null, false);
-        String snoozeDescription = res.getString(R.string.notification_menu_snooze_description);
-        MenuItem snooze = new NotificationMenuItem(context, snoozeDescription, content,
-                R.drawable.ic_snooze);
-        return snooze;
-    }
-
-    public static MenuItem createInfoItem(Context context) {
-        Resources res = context.getResources();
-        String infoDescription = res.getString(R.string.notification_menu_gear_description);
-        NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
-                R.layout.notification_info, null, false);
-        MenuItem info = new NotificationMenuItem(context, infoDescription, infoContent,
-                R.drawable.ic_settings);
-        return info;
-    }
-
-    public static MenuItem createAppOpsItem(Context context) {
-        AppOpsInfo appOpsContent = (AppOpsInfo) LayoutInflater.from(context).inflate(
-                R.layout.app_ops_info, null, false);
-        MenuItem info = new NotificationMenuItem(context, null, appOpsContent,
-                -1 /*don't show in slow swipe menu */);
-        return info;
-    }
-
-    private void addMenuView(MenuItem item, ViewGroup parent) {
-        View menuView = item.getMenuView();
-        if (menuView != null) {
-            parent.addView(menuView);
-            menuView.setOnClickListener(this);
-            FrameLayout.LayoutParams lp = (LayoutParams) menuView.getLayoutParams();
-            lp.width = (int) mHorizSpaceForIcon;
-            lp.height = (int) mHorizSpaceForIcon;
-            menuView.setLayoutParams(lp);
-        }
-    }
-
-    public static class NotificationMenuItem implements MenuItem {
-        View mMenuView;
-        GutsContent mGutsContent;
-        String mContentDescription;
-
-        /**
-         * Add a new 'guts' panel. If iconResId < 0 it will not appear in the slow swipe menu
-         * but can still be exposed via other affordances.
-         */
-        public NotificationMenuItem(Context context, String s, GutsContent content, int iconResId) {
-            Resources res = context.getResources();
-            int padding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
-            int tint = res.getColor(R.color.notification_gear_color);
-            if (iconResId >= 0) {
-                AlphaOptimizedImageView iv = new AlphaOptimizedImageView(context);
-                iv.setPadding(padding, padding, padding, padding);
-                Drawable icon = context.getResources().getDrawable(iconResId);
-                iv.setImageDrawable(icon);
-                iv.setColorFilter(tint);
-                iv.setAlpha(1f);
-                mMenuView = iv;
-            }
-            mContentDescription = s;
-            mGutsContent = content;
-        }
-
-        @Override
-        @Nullable
-        public View getMenuView() {
-            return mMenuView;
-        }
-
-        @Override
-        public View getGutsView() {
-            return mGutsContent.getContentView();
-        }
-
-        @Override
-        public String getContentDescription() {
-            return mContentDescription;
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index 21d3d81..c58eb80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -19,6 +19,11 @@
 import android.os.Handler;
 import android.view.View;
 
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
 /**
  * An abstraction of something that presents notifications, e.g. StatusBar. Contains methods
  * for both querying the state of the system (some modularised piece of functionality may
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 9e87a0b..929713c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -18,6 +18,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
 
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
 import android.content.Context;
@@ -42,6 +43,9 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.RemoteInputView;
 
 import java.io.FileDescriptor;
@@ -110,7 +114,7 @@
             } catch (RemoteException e) {
             }
             return mCallback.handleRemoteViewClick(view, pendingIntent, fillInIntent,
-                    () -> superOnClickHandler(view, pendingIntent, fillInIntent));
+                    () -> super.onClickHandler(view, pendingIntent, fillInIntent));
         }
 
         private void logActionClick(View view) {
@@ -148,10 +152,11 @@
             return null;
         }
 
-        private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
-                Intent fillInIntent) {
-            return super.onClickHandler(view, pendingIntent, fillInIntent,
-                    WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+        @Override
+        protected ActivityOptions getActivityOptions(Context context) {
+            ActivityOptions options = super.getActivityOptions(context);
+            options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+            return options;
         }
 
         private boolean handleRemoteInput(View view, PendingIntent pendingIntent) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 3063199..f7615e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN_REVERSE;
 import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState.NO_VALUE;
 
 import android.content.Context;
@@ -26,21 +27,28 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.MathUtils;
+import android.view.DisplayCutout;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.phone.NotificationIconContainer;
-import com.android.systemui.statusbar.stack.AmbientState;
-import com.android.systemui.statusbar.stack.AnimationProperties;
-import com.android.systemui.statusbar.stack.ExpandableViewState;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.StackScrollState;
-import com.android.systemui.statusbar.stack.ViewState;
+import com.android.systemui.statusbar.notification.stack.AmbientState;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.StackScrollState;
+import com.android.systemui.statusbar.notification.stack.ViewState;
 
 /**
  * A notification shelf view that is placed inside the notification scroller. It manages the
@@ -86,6 +94,9 @@
     private boolean mShowNotificationShelf;
     private float mFirstElementRoundness;
     private Rect mClipRect = new Rect();
+    private int mCutoutHeight;
+
+    private final StateListener mStateListener = this::setStatusBarState;
 
     public NotificationShelf(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -107,6 +118,18 @@
         initDimens();
     }
 
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        Dependency.get(StatusBarStateController.class).removeListener(mStateListener);
+    }
+
     public void bind(AmbientState ambientState, NotificationStackScrollLayout hostLayout) {
         mAmbientState = ambientState;
         mHostLayout = hostLayout;
@@ -151,12 +174,11 @@
     }
 
     public void fadeInTranslating() {
-        float translation = mShelfIcons.getTranslationY();
-        mShelfIcons.setTranslationY(translation - mShelfAppearTranslation);
+        mShelfIcons.setTranslationY(-mShelfAppearTranslation);
         mShelfIcons.setAlpha(0);
         mShelfIcons.animate()
                 .setInterpolator(Interpolators.DECELERATE_QUINT)
-                .translationY(translation)
+                .translationY(0)
                 .setDuration(SHELF_IN_TRANSLATION_DURATION)
                 .start();
         mShelfIcons.animate()
@@ -198,8 +220,12 @@
                     0 : mAmbientState.getDarkAmount();
             mShelfState.yTranslation = MathUtils.lerp(awakenTranslation, darkTranslation, yRatio);
             mShelfState.zTranslation = ambientState.getBaseZHeight();
+            // For the small display size, it's not enough to make the icon not covered by
+            // the top cutout so the denominator add the height of cutout.
+            // Totally, (getIntrinsicHeight() * 2 + mCutoutHeight) should be smaller then
+            // mAmbientState.getTopPadding().
             float openedAmount = (mShelfState.yTranslation - getFullyClosedTranslation())
-                    / (getIntrinsicHeight() * 2);
+                    / (getIntrinsicHeight() * 2 + mCutoutHeight);
             openedAmount = Math.min(1.0f, openedAmount);
             mShelfState.openedAmount = openedAmount;
             mShelfState.clipTopAmount = 0;
@@ -743,6 +769,22 @@
         mRelativeOffset -= mTmp[0];
     }
 
+    @Override
+    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        WindowInsets ret = super.onApplyWindowInsets(insets);
+
+        // NotificationShelf drag from the status bar and the status bar dock on the top
+        // of the display for current design so just focus on the top of ScreenDecorations.
+        // In landscape or multiple window split mode, the NotificationShelf still drag from
+        // the top and the physical notch/cutout goes to the right, left, or both side of the
+        // display so it doesn't matter for the NotificationSelf in landscape.
+        DisplayCutout displayCutout = insets.getDisplayCutout();
+        mCutoutHeight = displayCutout == null || displayCutout.getSafeInsetTop() < 0
+                ? 0 : displayCutout.getSafeInsetTop();
+
+        return ret;
+    }
+
     private void setOpenedAmount(float openedAmount) {
         mNoAnimationsInThisFrame = openedAmount == 1.0f && mOpenedAmount == 0.0f;
         mOpenedAmount = openedAmount;
@@ -757,7 +799,7 @@
         int width = (int) NotificationUtils.interpolate(
                 start + mCollapsedIcons.getFinalTranslationX(),
                 mShelfIcons.getWidth(),
-                openedAmount);
+                FAST_OUT_SLOW_IN_REVERSE.getInterpolation(openedAmount));
         mShelfIcons.setActualLayoutWidth(width);
         boolean hasOverflow = mCollapsedIcons.hasOverflow();
         int collapsedPadding = mCollapsedIcons.getPaddingEnd();
@@ -810,11 +852,9 @@
         mCollapsedIcons.addOnLayoutChangeListener(this);
     }
 
-    public void setStatusBarState(int statusBarState) {
-        if (mStatusBarState != statusBarState) {
-            mStatusBarState = statusBarState;
-            updateInteractiveness();
-        }
+    private void setStatusBarState(int statusBarState) {
+        mStatusBarState = statusBarState;
+        updateInteractiveness();
     }
 
     private void updateInteractiveness() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
deleted file mode 100644
index b3ab109..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
+++ /dev/null
@@ -1,486 +0,0 @@
-package com.android.systemui.statusbar;
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Typeface;
-import android.metrics.LogMaker;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.service.notification.SnoozeCriterion;
-import android.service.notification.StatusBarNotification;
-import android.text.SpannableString;
-import android.text.style.StyleSpan;
-import android.util.AttributeSet;
-import android.util.KeyValueListParser;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-
-public class NotificationSnooze extends LinearLayout
-        implements NotificationGuts.GutsContent, View.OnClickListener {
-
-    private static final String TAG = "NotificationSnooze";
-    /**
-     * If this changes more number increases, more assistant action resId's should be defined for
-     * accessibility purposes, see {@link #setSnoozeOptions(List)}
-     */
-    private static final int MAX_ASSISTANT_SUGGESTIONS = 1;
-    private static final String KEY_DEFAULT_SNOOZE = "default";
-    private static final String KEY_OPTIONS = "options_array";
-    private static final LogMaker OPTIONS_OPEN_LOG =
-            new LogMaker(MetricsEvent.NOTIFICATION_SNOOZE_OPTIONS)
-                    .setType(MetricsEvent.TYPE_OPEN);
-    private static final LogMaker OPTIONS_CLOSE_LOG =
-            new LogMaker(MetricsEvent.NOTIFICATION_SNOOZE_OPTIONS)
-                    .setType(MetricsEvent.TYPE_CLOSE);
-    private static final LogMaker UNDO_LOG =
-            new LogMaker(MetricsEvent.NOTIFICATION_UNDO_SNOOZE)
-                    .setType(MetricsEvent.TYPE_ACTION);
-    private NotificationGuts mGutsContainer;
-    private NotificationSwipeActionHelper mSnoozeListener;
-    private StatusBarNotification mSbn;
-
-    private TextView mSelectedOptionText;
-    private TextView mUndoButton;
-    private ImageView mExpandButton;
-    private View mDivider;
-    private ViewGroup mSnoozeOptionContainer;
-    private List<SnoozeOption> mSnoozeOptions;
-    private int mCollapsedHeight;
-    private SnoozeOption mDefaultOption;
-    private SnoozeOption mSelectedOption;
-    private boolean mSnoozing;
-    private boolean mExpanded;
-    private AnimatorSet mExpandAnimation;
-    private KeyValueListParser mParser;
-
-    private final static int[] sAccessibilityActions = {
-            R.id.action_snooze_shorter,
-            R.id.action_snooze_short,
-            R.id.action_snooze_long,
-            R.id.action_snooze_longer,
-    };
-
-    private MetricsLogger mMetricsLogger = new MetricsLogger();
-
-    public NotificationSnooze(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mParser = new KeyValueListParser(',');
-    }
-
-    @VisibleForTesting
-    SnoozeOption getDefaultOption()
-    {
-        return mDefaultOption;
-    }
-
-    @VisibleForTesting
-    void setKeyValueListParser(KeyValueListParser parser) {
-        mParser = parser;
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.snooze_snackbar_min_height);
-        findViewById(R.id.notification_snooze).setOnClickListener(this);
-        mSelectedOptionText = (TextView) findViewById(R.id.snooze_option_default);
-        mUndoButton = (TextView) findViewById(R.id.undo);
-        mUndoButton.setOnClickListener(this);
-        mExpandButton = (ImageView) findViewById(R.id.expand_button);
-        mDivider = findViewById(R.id.divider);
-        mDivider.setAlpha(0f);
-        mSnoozeOptionContainer = (ViewGroup) findViewById(R.id.snooze_options);
-        mSnoozeOptionContainer.setVisibility(View.INVISIBLE);
-        mSnoozeOptionContainer.setAlpha(0f);
-
-        // Create the different options based on list
-        mSnoozeOptions = getDefaultSnoozeOptions();
-        createOptionViews();
-
-        setSelected(mDefaultOption, false);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        logOptionSelection(MetricsEvent.NOTIFICATION_SNOOZE_CLICKED, mDefaultOption);
-    }
-
-    @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEvent(event);
-        if (mGutsContainer != null && mGutsContainer.isExposed()) {
-            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-                event.getText().add(mSelectedOptionText.getText());
-            }
-        }
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(info);
-        info.addAction(new AccessibilityAction(R.id.action_snooze_undo,
-                getResources().getString(R.string.snooze_undo)));
-        int count = mSnoozeOptions.size();
-        for (int i = 0; i < count; i++) {
-            AccessibilityAction action = mSnoozeOptions.get(i).getAccessibilityAction();
-            if (action != null) {
-                info.addAction(action);
-            }
-        }
-    }
-
-    @Override
-    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
-        if (super.performAccessibilityActionInternal(action, arguments)) {
-            return true;
-        }
-        if (action == R.id.action_snooze_undo) {
-            undoSnooze(mUndoButton);
-            return true;
-        }
-        for (int i = 0; i < mSnoozeOptions.size(); i++) {
-            SnoozeOption so = mSnoozeOptions.get(i);
-            if (so.getAccessibilityAction() != null
-                    && so.getAccessibilityAction().getId() == action) {
-                setSelected(so, true);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void setSnoozeOptions(final List<SnoozeCriterion> snoozeList) {
-        if (snoozeList == null) {
-            return;
-        }
-        mSnoozeOptions.clear();
-        mSnoozeOptions = getDefaultSnoozeOptions();
-        final int count = Math.min(MAX_ASSISTANT_SUGGESTIONS, snoozeList.size());
-        for (int i = 0; i < count; i++) {
-            SnoozeCriterion sc = snoozeList.get(i);
-            AccessibilityAction action = new AccessibilityAction(
-                    R.id.action_snooze_assistant_suggestion_1, sc.getExplanation());
-            mSnoozeOptions.add(new NotificationSnoozeOption(sc, 0, sc.getExplanation(),
-                    sc.getConfirmation(), action));
-        }
-        createOptionViews();
-    }
-
-    public boolean isExpanded() {
-        return mExpanded;
-    }
-
-    public void setSnoozeListener(NotificationSwipeActionHelper listener) {
-        mSnoozeListener = listener;
-    }
-
-    public void setStatusBarNotification(StatusBarNotification sbn) {
-        mSbn = sbn;
-    }
-
-    @VisibleForTesting
-    ArrayList<SnoozeOption> getDefaultSnoozeOptions() {
-        final Resources resources = getContext().getResources();
-        ArrayList<SnoozeOption> options = new ArrayList<>();
-        try {
-            final String config = Settings.Global.getString(getContext().getContentResolver(),
-                    Settings.Global.NOTIFICATION_SNOOZE_OPTIONS);
-            mParser.setString(config);
-        } catch (IllegalArgumentException e) {
-            Log.e(TAG, "Bad snooze constants");
-        }
-
-        final int defaultSnooze = mParser.getInt(KEY_DEFAULT_SNOOZE,
-                resources.getInteger(R.integer.config_notification_snooze_time_default));
-        final int[] snoozeTimes = mParser.getIntArray(KEY_OPTIONS,
-                resources.getIntArray(R.array.config_notification_snooze_times));
-
-        for (int i = 0; i < snoozeTimes.length && i < sAccessibilityActions.length; i++) {
-            int snoozeTime = snoozeTimes[i];
-            SnoozeOption option = createOption(snoozeTime, sAccessibilityActions[i]);
-            if (i == 0 || snoozeTime == defaultSnooze) {
-                mDefaultOption = option;
-            }
-            options.add(option);
-        }
-        return options;
-    }
-
-    private SnoozeOption createOption(int minutes, int accessibilityActionId) {
-        Resources res = getResources();
-        boolean showInHours = minutes >= 60;
-        int pluralResId = showInHours
-                ? R.plurals.snoozeHourOptions
-                : R.plurals.snoozeMinuteOptions;
-        int count = showInHours ? (minutes / 60) : minutes;
-        String description = res.getQuantityString(pluralResId, count, count);
-        String resultText = String.format(res.getString(R.string.snoozed_for_time), description);
-        AccessibilityAction action = new AccessibilityAction(accessibilityActionId, description);
-        final int index = resultText.indexOf(description);
-        if (index == -1) {
-            return new NotificationSnoozeOption(null, minutes, description, resultText, action);
-        }
-        SpannableString string = new SpannableString(resultText);
-        string.setSpan(new StyleSpan(Typeface.BOLD),
-                index, index + description.length(), 0 /* flags */);
-        return new NotificationSnoozeOption(null, minutes, description, string,
-                action);
-    }
-
-    private void createOptionViews() {
-        mSnoozeOptionContainer.removeAllViews();
-        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
-                Context.LAYOUT_INFLATER_SERVICE);
-        for (int i = 0; i < mSnoozeOptions.size(); i++) {
-            SnoozeOption option = mSnoozeOptions.get(i);
-            TextView tv = (TextView) inflater.inflate(R.layout.notification_snooze_option,
-                    mSnoozeOptionContainer, false);
-            mSnoozeOptionContainer.addView(tv);
-            tv.setText(option.getDescription());
-            tv.setTag(option);
-            tv.setOnClickListener(this);
-        }
-    }
-
-    private void hideSelectedOption() {
-        final int childCount = mSnoozeOptionContainer.getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = mSnoozeOptionContainer.getChildAt(i);
-            child.setVisibility(child.getTag() == mSelectedOption ? View.GONE : View.VISIBLE);
-        }
-    }
-
-    private void showSnoozeOptions(boolean show) {
-        int drawableId = show ? com.android.internal.R.drawable.ic_collapse_notification
-                : com.android.internal.R.drawable.ic_expand_notification;
-        mExpandButton.setImageResource(drawableId);
-        if (mExpanded != show) {
-            mExpanded = show;
-            animateSnoozeOptions(show);
-            if (mGutsContainer != null) {
-                mGutsContainer.onHeightChanged();
-            }
-        }
-    }
-
-    private void animateSnoozeOptions(boolean show) {
-        if (mExpandAnimation != null) {
-            mExpandAnimation.cancel();
-        }
-        ObjectAnimator dividerAnim = ObjectAnimator.ofFloat(mDivider, View.ALPHA,
-                mDivider.getAlpha(), show ? 1f : 0f);
-        ObjectAnimator optionAnim = ObjectAnimator.ofFloat(mSnoozeOptionContainer, View.ALPHA,
-                mSnoozeOptionContainer.getAlpha(), show ? 1f : 0f);
-        mSnoozeOptionContainer.setVisibility(View.VISIBLE);
-        mExpandAnimation = new AnimatorSet();
-        mExpandAnimation.playTogether(dividerAnim, optionAnim);
-        mExpandAnimation.setDuration(150);
-        mExpandAnimation.setInterpolator(show ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
-        mExpandAnimation.addListener(new AnimatorListenerAdapter() {
-            boolean cancelled = false;
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                cancelled = true;
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (!show && !cancelled) {
-                    mSnoozeOptionContainer.setVisibility(View.INVISIBLE);
-                    mSnoozeOptionContainer.setAlpha(0f);
-                }
-            }
-        });
-        mExpandAnimation.start();
-    }
-
-    private void setSelected(SnoozeOption option, boolean userAction) {
-        mSelectedOption = option;
-        mSelectedOptionText.setText(option.getConfirmation());
-        showSnoozeOptions(false);
-        hideSelectedOption();
-        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
-        if (userAction) {
-            logOptionSelection(MetricsEvent.NOTIFICATION_SELECT_SNOOZE, option);
-        }
-    }
-
-    private void logOptionSelection(int category, SnoozeOption option) {
-        int index = mSnoozeOptions.indexOf(option);
-        long duration = TimeUnit.MINUTES.toMillis(option.getMinutesToSnoozeFor());
-        mMetricsLogger.write(new LogMaker(category)
-                .setType(MetricsEvent.TYPE_ACTION)
-                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_SNOOZE_INDEX, index)
-                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_SNOOZE_DURATION_MS, duration));
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (mGutsContainer != null) {
-            mGutsContainer.resetFalsingCheck();
-        }
-        final int id = v.getId();
-        final SnoozeOption tag = (SnoozeOption) v.getTag();
-        if (tag != null) {
-            setSelected(tag, true);
-        } else if (id == R.id.notification_snooze) {
-            // Toggle snooze options
-            showSnoozeOptions(!mExpanded);
-            mMetricsLogger.write(!mExpanded ? OPTIONS_OPEN_LOG : OPTIONS_CLOSE_LOG);
-        } else {
-            // Undo snooze was selected
-            undoSnooze(v);
-            mMetricsLogger.write(UNDO_LOG);
-        }
-    }
-
-    private void undoSnooze(View v) {
-        mSelectedOption = null;
-        int[] parentLoc = new int[2];
-        int[] targetLoc = new int[2];
-        mGutsContainer.getLocationOnScreen(parentLoc);
-        v.getLocationOnScreen(targetLoc);
-        final int centerX = v.getWidth() / 2;
-        final int centerY = v.getHeight() / 2;
-        final int x = targetLoc[0] - parentLoc[0] + centerX;
-        final int y = targetLoc[1] - parentLoc[1] + centerY;
-        showSnoozeOptions(false);
-        mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
-    }
-
-    @Override
-    public int getActualHeight() {
-        return mExpanded ? getHeight() : mCollapsedHeight;
-    }
-
-    @Override
-    public boolean willBeRemoved() {
-        return mSnoozing;
-    }
-
-    @Override
-    public View getContentView() {
-        // Reset the view before use
-        setSelected(mDefaultOption, false);
-        return this;
-    }
-
-    @Override
-    public void setGutsParent(NotificationGuts guts) {
-        mGutsContainer = guts;
-    }
-
-    @Override
-    public boolean handleCloseControls(boolean save, boolean force) {
-        if (mExpanded && !force) {
-            // Collapse expanded state on outside touch
-            showSnoozeOptions(false);
-            return true;
-        } else if (mSnoozeListener != null && mSelectedOption != null) {
-            // Snooze option selected so commit it
-            mSnoozing = true;
-            mSnoozeListener.snooze(mSbn, mSelectedOption);
-            return true;
-        } else {
-            // The view should actually be closed
-            setSelected(mSnoozeOptions.get(0), false);
-            return false; // Return false here so that guts handles closing the view
-        }
-    }
-
-    @Override
-    public boolean isLeavebehind() {
-        return true;
-    }
-
-    @Override
-    public boolean shouldBeSaved() {
-        return true;
-    }
-
-    public class NotificationSnoozeOption implements SnoozeOption {
-        private SnoozeCriterion mCriterion;
-        private int mMinutesToSnoozeFor;
-        private CharSequence mDescription;
-        private CharSequence mConfirmation;
-        private AccessibilityAction mAction;
-
-        public NotificationSnoozeOption(SnoozeCriterion sc, int minToSnoozeFor,
-                CharSequence description,
-                CharSequence confirmation, AccessibilityAction action) {
-            mCriterion = sc;
-            mMinutesToSnoozeFor = minToSnoozeFor;
-            mDescription = description;
-            mConfirmation = confirmation;
-            mAction = action;
-        }
-
-        @Override
-        public SnoozeCriterion getSnoozeCriterion() {
-            return mCriterion;
-        }
-
-        @Override
-        public CharSequence getDescription() {
-            return mDescription;
-        }
-
-        @Override
-        public CharSequence getConfirmation() {
-            return mConfirmation;
-        }
-
-        @Override
-        public int getMinutesToSnoozeFor() {
-            return mMinutesToSnoozeFor;
-        }
-
-        @Override
-        public AccessibilityAction getAccessibilityAction() {
-            return mAction;
-        }
-
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
new file mode 100644
index 0000000..47b7fe9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.RemoteInput;
+import android.graphics.drawable.Icon;
+import android.text.TextUtils;
+
+import com.android.systemui.statusbar.notification.NotificationData;
+
+import androidx.annotation.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * By diffing two entries, determines is view reinflation needed.
+ */
+public class NotificationUiAdjustment {
+
+    public final String key;
+    public final List<Notification.Action> smartActions;
+    public final CharSequence[] smartReplies;
+
+    @VisibleForTesting
+    NotificationUiAdjustment(
+            String key, List<Notification.Action> smartActions, CharSequence[] smartReplies) {
+        this.key = key;
+        this.smartActions = smartActions == null
+                ? Collections.emptyList()
+                : new ArrayList<>(smartActions);
+        this.smartReplies = smartReplies == null ? new CharSequence[0] : smartReplies.clone();
+    }
+
+    public static NotificationUiAdjustment extractFromNotificationEntry(
+            NotificationData.Entry entry) {
+        return new NotificationUiAdjustment(entry.key, entry.smartActions, entry.smartReplies);
+    }
+
+    public static boolean needReinflate(
+            @NonNull NotificationUiAdjustment oldAdjustment,
+            @NonNull NotificationUiAdjustment newAdjustment) {
+        if (oldAdjustment == newAdjustment) {
+            return false;
+        }
+        if (areDifferent(oldAdjustment.smartActions, newAdjustment.smartActions)) {
+            return true;
+        }
+        if (!Arrays.equals(oldAdjustment.smartReplies, newAdjustment.smartReplies)) {
+            return true;
+        }
+        return false;
+    }
+
+    public static boolean areDifferent(
+            @NonNull List<Notification.Action> first, @NonNull List<Notification.Action> second) {
+        if (first == second) {
+            return false;
+        }
+        if (first == null || second == null) {
+            return true;
+        }
+        if (first.size() != second.size()) {
+            return true;
+        }
+        for (int i = 0; i < first.size(); i++) {
+            Notification.Action firstAction = first.get(i);
+            Notification.Action secondAction = second.get(i);
+
+            if (!TextUtils.equals(firstAction.title, secondAction.title)) {
+                return true;
+            }
+
+            if (areDifferent(firstAction.getIcon(), secondAction.getIcon())) {
+                return true;
+            }
+
+            if (!Objects.equals(firstAction.actionIntent, secondAction.actionIntent)) {
+                return true;
+            }
+
+            if (areDifferent(firstAction.getRemoteInputs(), secondAction.getRemoteInputs())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean areDifferent(@Nullable Icon first, @Nullable Icon second) {
+        if (first == second) {
+            return false;
+        }
+        if (first == null || second == null) {
+            return true;
+        }
+        return !first.sameAs(second);
+    }
+
+    private static boolean areDifferent(
+            @Nullable RemoteInput[] first, @Nullable RemoteInput[] second) {
+        if (first == second) {
+            return false;
+        }
+        if (first == null || second == null) {
+            return true;
+        }
+        if (first.length != second.length) {
+            return true;
+        }
+        for (int i = 0; i < first.length; i++) {
+            RemoteInput firstRemoteInput = first[i];
+            RemoteInput secondRemoteInput = second[i];
+
+            if (!TextUtils.equals(firstRemoteInput.getLabel(), secondRemoteInput.getLabel())) {
+                return true;
+            }
+            if (areDifferent(firstRemoteInput.getChoices(), secondRemoteInput.getChoices())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean areDifferent(
+            @Nullable CharSequence[] first, @Nullable CharSequence[] second) {
+        if (first == second) {
+            return false;
+        }
+        if (first == null || second == null) {
+            return true;
+        }
+        if (first.length != second.length) {
+            return true;
+        }
+        for (int i = 0; i < first.length; i++) {
+            CharSequence firstCharSequence = first[i];
+            CharSequence secondCharSequence = second[i];
+            if (!TextUtils.equals(firstCharSequence, secondCharSequence)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUndoLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUndoLayout.java
deleted file mode 100644
index 11a1c9b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUndoLayout.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.systemui.R;
-
-/**
- * Custom view for the NotificationInfo confirmation views so that the confirmation text can
- * occupy the full width of the notification and push the undo button down to the next line if
- * necessary.
- *
- * @see NotificationInfo
- */
-public class NotificationUndoLayout extends FrameLayout {
-    /**
-     * View for the prompt/confirmation text to tell the user the previous action was successful.
-     */
-    private View mConfirmationTextView;
-    /** Undo button (actionable text) view. */
-    private View mUndoView;
-
-    /**
-     * Whether {@link #mConfirmationTextView} is multiline and will require the full width of the
-     * parent (which causes the {@link #mUndoView} to push down).
-     */
-    private boolean mIsMultiline = false;
-    private int mMultilineTopMargin;
-
-    public NotificationUndoLayout(Context context) {
-        this(context, null);
-    }
-
-    public NotificationUndoLayout(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public NotificationUndoLayout(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-
-        mConfirmationTextView = findViewById(R.id.confirmation_text);
-        mUndoView = findViewById(R.id.undo);
-
-        mMultilineTopMargin = getResources().getDimensionPixelOffset(
-                com.android.internal.R.dimen.notification_content_margin_start);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
-        LayoutParams confirmationLayoutParams =
-                (LayoutParams) mConfirmationTextView.getLayoutParams();
-        LayoutParams undoLayoutParams =(LayoutParams) mUndoView.getLayoutParams();
-
-        int measuredWidth = getMeasuredWidth();
-        // Ignore the left margin on the undo button - no need for additional extra space between
-        // the text and the button.
-        int requiredWidth = mConfirmationTextView.getMeasuredWidth()
-                + confirmationLayoutParams.rightMargin
-                + confirmationLayoutParams.leftMargin
-                + mUndoView.getMeasuredWidth()
-                + undoLayoutParams.rightMargin;
-        // If the measured width isn't enough to accommodate both the undo button and the text in
-        // the same line, we'll need to adjust the view to be multi-line. Otherwise, we're done.
-        if (requiredWidth > measuredWidth) {
-            mIsMultiline = true;
-
-            // Update height requirement to the text height and the button's height (along with
-            // additional spacing for the top of the text).
-            int updatedHeight = mMultilineTopMargin
-                    + mConfirmationTextView.getMeasuredHeight()
-                    + mUndoView.getMeasuredHeight()
-                    + undoLayoutParams.topMargin
-                    + undoLayoutParams.bottomMargin;
-
-            setMeasuredDimension(measuredWidth, updatedHeight);
-        } else {
-            mIsMultiline = false;
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        // If the text view and undo view don't fit on the same line, we'll need to manually lay
-        // out the content.
-        if (mIsMultiline) {
-            // Re-align parent right/bottom values. Left and top are considered to be 0.
-            int parentBottom = getMeasuredHeight();
-            int parentRight = getMeasuredWidth();
-
-            LayoutParams confirmationLayoutParams =
-                    (LayoutParams) mConfirmationTextView.getLayoutParams();
-            LayoutParams undoLayoutParams = (LayoutParams) mUndoView.getLayoutParams();
-
-            // The confirmation text occupies the full width as computed earlier. Both side margins
-            // are equivalent, so we only need to grab the left one here.
-            mConfirmationTextView.layout(
-                    confirmationLayoutParams.leftMargin,
-                    mMultilineTopMargin,
-                    confirmationLayoutParams.leftMargin + mConfirmationTextView.getMeasuredWidth(),
-                    mMultilineTopMargin + mConfirmationTextView.getMeasuredHeight());
-
-            // The undo button is aligned bottom|end with the parent in the case of multiline text.
-            int undoViewLeft = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
-                    ? undoLayoutParams.rightMargin
-                    : parentRight - mUndoView.getMeasuredWidth() - undoLayoutParams.rightMargin;
-            mUndoView.layout(
-                    undoViewLeft,
-                    parentBottom - mUndoView.getMeasuredHeight() - undoLayoutParams.bottomMargin,
-                    undoViewLeft + mUndoView.getMeasuredWidth(),
-                    parentBottom - undoLayoutParams.bottomMargin);
-        } else {
-            super.onLayout(changed, left, top, right, bottom);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 341c692..d479838 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -19,14 +19,17 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Trace;
-import android.service.notification.NotificationListenerService;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index b0d5536..7f63191 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -17,8 +17,7 @@
 package com.android.systemui.statusbar;
 
 import com.android.internal.util.Preconditions;
-import com.android.systemui.Dependency;
-import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.policy.RemoteInputView;
 
 import android.app.Notification;
@@ -26,7 +25,6 @@
 import android.content.Context;
 import android.os.SystemProperties;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.Pair;
 
 import java.lang.ref.WeakReference;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index 5ba75de..e43c9e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -21,6 +21,8 @@
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dependency;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 
 import java.util.Set;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
deleted file mode 100644
index c5b3560..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.animation.AnimatorListenerAdapter;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.animation.Interpolator;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Interpolators;
-
-/**
- * A common base class for all views in the notification stack scroller which don't have a
- * background.
- */
-public abstract class StackScrollerDecorView extends ExpandableView {
-
-    protected View mContent;
-    protected View mSecondaryView;
-    private boolean mIsVisible = true;
-    private boolean mContentVisible = true;
-    private boolean mIsSecondaryVisible = true;
-    private int mDuration = 260;
-    private boolean mContentAnimating;
-    private final Runnable mContentVisibilityEndRunnable = () -> {
-        mContentAnimating = false;
-        if (getVisibility() != View.GONE && !mIsVisible) {
-            setVisibility(GONE);
-            setWillBeGone(false);
-            notifyHeightChanged(false /* needsAnimation */);
-        }
-    };
-
-    public StackScrollerDecorView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mContent = findContentView();
-        mSecondaryView = findSecondaryView();
-        setVisible(false /* nowVisible */, false /* animate */);
-        setSecondaryVisible(false /* nowVisible */, false /* animate */);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        setOutlineProvider(null);
-    }
-
-    @Override
-    public boolean isTransparent() {
-        return true;
-    }
-
-    /**
-     * Set the content of this view to be visible in an animated way.
-     *
-     * @param contentVisible True if the content should be visible or false if it should be hidden.
-     */
-    public void setContentVisible(boolean contentVisible) {
-        setContentVisible(contentVisible, true /* animate */);
-    }
-    /**
-     * Set the content of this view to be visible.
-     * @param contentVisible True if the content should be visible or false if it should be hidden.
-     * @param animate Should an animation be performed.
-     */
-    private void setContentVisible(boolean contentVisible, boolean animate) {
-        if (mContentVisible != contentVisible) {
-            mContentAnimating = animate;
-            setViewVisible(mContent, contentVisible, animate, mContentVisibilityEndRunnable);
-            mContentVisible = contentVisible;
-        } if (!mContentAnimating) {
-            mContentVisibilityEndRunnable.run();
-        }
-    }
-
-    public boolean isContentVisible() {
-        return mContentVisible;
-    }
-
-    /**
-     * Make this view visible. If {@code false} is passed, the view will fade out it's content
-     * and set the view Visibility to GONE. If only the content should be changed
-     * {@link #setContentVisible(boolean)} can be used.
-     *
-     * @param nowVisible should the view be visible
-     * @param animate should the change be animated.
-     */
-    public void setVisible(boolean nowVisible, boolean animate) {
-        if (mIsVisible != nowVisible) {
-            mIsVisible = nowVisible;
-            if (animate) {
-                if (nowVisible) {
-                    setVisibility(VISIBLE);
-                    setWillBeGone(false);
-                    notifyHeightChanged(false /* needsAnimation */);
-                } else {
-                    setWillBeGone(true);
-                }
-                setContentVisible(nowVisible, true /* animate */);
-            } else {
-                setVisibility(nowVisible ? VISIBLE : GONE);
-                setContentVisible(nowVisible, false /* animate */);
-                setWillBeGone(false);
-                notifyHeightChanged(false /* needsAnimation */);
-            }
-        }
-    }
-
-    /**
-     * Set the secondary view of this layout to visible.
-     *
-     * @param nowVisible should the secondary view be visible
-     * @param animate should the change be animated
-     */
-    public void setSecondaryVisible(boolean nowVisible, boolean animate) {
-        if (mIsSecondaryVisible != nowVisible) {
-            setViewVisible(mSecondaryView, nowVisible, animate, null /* endRunnable */);
-            mIsSecondaryVisible = nowVisible;
-        }
-    }
-
-    @VisibleForTesting
-    boolean isSecondaryVisible() {
-        return mIsSecondaryVisible;
-    }
-
-    /**
-     * Is this view visible. If a view is currently animating to gone, it will
-     * return {@code false}.
-     */
-    public boolean isVisible() {
-        return mIsVisible;
-    }
-
-    void setDuration(int duration) {
-        mDuration = duration;
-    }
-
-    /**
-     * Animate a view to a new visibility.
-     * @param view Target view, maybe content view or dismiss view.
-     * @param nowVisible Should it now be visible.
-     * @param animate Should this be done in an animated way.
-     * @param endRunnable A runnable that is run when the animation is done.
-     */
-    private void setViewVisible(View view, boolean nowVisible,
-            boolean animate, Runnable endRunnable) {
-        if (view == null) {
-            return;
-        }
-        // cancel any previous animations
-        view.animate().cancel();
-        float endValue = nowVisible ? 1.0f : 0.0f;
-        if (!animate) {
-            view.setAlpha(endValue);
-            if (endRunnable != null) {
-                endRunnable.run();
-            }
-            return;
-        }
-
-        // Animate the view alpha
-        Interpolator interpolator = nowVisible ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT;
-        view.animate()
-                .alpha(endValue)
-                .setInterpolator(interpolator)
-                .setDuration(mDuration)
-                .withEndAction(endRunnable);
-    }
-
-    @Override
-    public void performRemoveAnimation(long duration, long delay,
-            float translationDirection, boolean isHeadsUpAnimation, float endLocation,
-            Runnable onFinishedRunnable,
-            AnimatorListenerAdapter animationListener) {
-        // TODO: Use duration
-        setContentVisible(false);
-    }
-
-    @Override
-    public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) {
-        // TODO: use delay and duration
-        setContentVisible(true);
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-
-    protected abstract View findContentView();
-
-    /**
-     * Returns a view that might not always appear while the main content view is still visible.
-     */
-    protected abstract View findSecondaryView();
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index c820e2b..cc5fbe5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -661,8 +661,9 @@
             if (hsl[1] < 0.2f) {
                 contrastedColor = Notification.COLOR_DEFAULT;
             }
+            boolean isDark = !ContrastColorUtil.isColorLight(mCachedContrastBackgroundColor);
             contrastedColor = ContrastColorUtil.resolveContrastColor(mContext,
-                    contrastedColor, mCachedContrastBackgroundColor);
+                    contrastedColor, mCachedContrastBackgroundColor, isDark);
         }
         mContrastedDrawableColor = contrastedColor;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
new file mode 100644
index 0000000..7a69f2e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.util.ArraySet;
+
+/**
+ * Tracks and reports on {@link StatusBarState}.
+ */
+public class StatusBarStateController {
+
+    private static final int MAX_STATE = StatusBarState.FULLSCREEN_USER_SWITCHER;
+    private static final int MIN_STATE = StatusBarState.SHADE;
+
+    private final ArraySet<StateListener> mListeners = new ArraySet<>();
+    private int mState;
+    private int mLastState;
+    private boolean mLeaveOpenOnKeyguardHide;
+
+    public int getState() {
+        return mState;
+    }
+
+    public void setState(int state) {
+        if (state > MAX_STATE || state < MIN_STATE) {
+            throw new IllegalArgumentException("Invalid state " + state);
+        }
+        if (state == mState) {
+            return;
+        }
+        synchronized (mListeners) {
+            for (StateListener listener : new ArraySet<>(mListeners)) {
+                listener.onStatePreChange(mState, state);
+            }
+            mLastState = mState;
+            mState = state;
+            for (StateListener listener : new ArraySet<>(mListeners)) {
+                listener.onStateChanged(mState);
+            }
+        }
+    }
+
+    public boolean goingToFullShade() {
+        return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide;
+    }
+
+    public void setLeaveOpenOnKeyguardHide(boolean leaveOpen) {
+        mLeaveOpenOnKeyguardHide = leaveOpen;
+    }
+
+    public boolean leaveOpenOnKeyguardHide() {
+        return mLeaveOpenOnKeyguardHide;
+    }
+
+    public boolean fromShadeLocked() {
+        return mLastState == StatusBarState.SHADE_LOCKED;
+    }
+
+    public void addListener(StateListener listener) {
+        synchronized (mListeners) {
+            mListeners.add(listener);
+        }
+    }
+
+    public void removeListener(StateListener listener) {
+        synchronized (mListeners) {
+            mListeners.remove(listener);
+        }
+    }
+
+    public interface StateListener {
+        public default void onStatePreChange(int oldState, int newState) {
+        }
+
+        public void onStateChanged(int newState);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index 09b11c2..7b5a70e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -28,7 +28,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.TransformState;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 import java.util.Stack;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 288b473..ed06752 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -16,11 +16,10 @@
 
 package com.android.systemui.statusbar.car;
 
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
+import android.car.user.CarUserManagerHelper;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
-import android.os.SystemProperties;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
@@ -41,6 +40,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.car.hvac.HvacController;
+import com.android.systemui.statusbar.car.hvac.TemperatureView;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -50,14 +50,13 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Map;
+
 /**
  * A status bar (and navigation bar) tailored for the automotive use case.
  */
 public class CarStatusBar extends StatusBar implements
         CarBatteryController.BatteryViewHandler {
     private static final String TAG = "CarStatusBar";
-    public static final boolean ENABLE_HVAC_CONNECTION
-            = !SystemProperties.getBoolean("android.car.hvac.demo", true);
 
     private TaskStackListenerImpl mTaskStackListener;
 
@@ -83,6 +82,7 @@
     private ActivityManagerWrapper mActivityManagerWrapper;
     private DeviceProvisionedController mDeviceProvisionedController;
     private boolean mDeviceIsProvisioned = true;
+    private HvacController mHvacController;
 
     @Override
     public void start() {
@@ -91,15 +91,13 @@
         mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
         mActivityManagerWrapper.registerTaskStackListener(mTaskStackListener);
 
-        mStackScroller.setScrollingEnabled(true);
+        mNotificationPanel.setScrollingEnabled(true);
 
         createBatteryController();
         mCarBatteryController.startListening();
 
-        if (ENABLE_HVAC_CONNECTION) {
-            Log.d(TAG, "Connecting to HVAC service");
-            Dependency.get(HvacController.class).connectToCarService();
-        }
+        mHvacController.connectToCarService();
+
         mCarFacetButtonController = Dependency.get(CarFacetButtonController.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
         mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned();
@@ -121,10 +119,11 @@
      * before and after the device is provisioned
      */
     private void restartNavBars() {
+        // remove and reattach all hvac components such that we don't keep a reference to unused
+        // ui elements
+        mHvacController.removeAllComponents();
+        addTemperatureViewToController(mStatusBarWindow);
         mCarFacetButtonController.removeAll();
-        if (ENABLE_HVAC_CONNECTION) {
-            Dependency.get(HvacController.class).removeAllComponents();
-        }
         if (mNavigationBarWindow != null) {
             mNavigationBarWindow.removeAllViews();
             mNavigationBarView = null;
@@ -139,14 +138,27 @@
             mRightNavigationBarWindow.removeAllViews();
             mRightNavigationBarView = null;
         }
+
         buildNavBarContent();
     }
 
+    private void addTemperatureViewToController(View v) {
+        if (v instanceof TemperatureView) {
+            Log.d(TAG, "addTemperatureViewToController: found ");
+            mHvacController.addHvacTextView((TemperatureView) v);
+        } else if (v instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) v;
+            for (int i = 0; i < viewGroup.getChildCount(); i++) {
+                addTemperatureViewToController(viewGroup.getChildAt(i));
+            }
+        }
+    }
+
     /**
      * Allows for showing or hiding just the navigation bars. This is indented to be used when
      * the full screen user selector is shown.
      */
-     void setNavBarVisibility(@View.Visibility int visibility) {
+    void setNavBarVisibility(@View.Visibility int visibility) {
         if (mNavigationBarWindow != null) {
             mNavigationBarWindow.setVisibility(visibility);
         }
@@ -216,6 +228,7 @@
     @Override
     protected void makeStatusBarView() {
         super.makeStatusBarView();
+        mHvacController = Dependency.get(HvacController.class);
 
         mNotificationPanelBackground = getDefaultWallpaper();
         mScrimController.setScrimBehindDrawable(mNotificationPanelBackground);
@@ -228,6 +241,7 @@
             // when a device has connected by bluetooth.
             mBatteryMeterView.setVisibility(View.GONE);
         });
+        addTemperatureViewToController(mStatusBarWindow);
     }
 
     private BatteryController createBatteryController() {
@@ -266,13 +280,12 @@
 
     private void buildNavBarWindows() {
         if (mShowBottom) {
-
-             mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
+            mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
                     R.layout.navigation_bar_window, null);
         }
         if (mShowLeft) {
             mLeftNavigationBarWindow = (ViewGroup) View.inflate(mContext,
-                R.layout.navigation_bar_window, null);
+                    R.layout.navigation_bar_window, null);
         }
         if (mShowRight) {
             mRightNavigationBarWindow = (ViewGroup) View.inflate(mContext,
@@ -344,6 +357,7 @@
             throw new RuntimeException("Unable to build botom nav bar due to missing layout");
         }
         mNavigationBarView.setStatusBar(this);
+        addTemperatureViewToController(mNavigationBarView);
     }
 
     private void buildLeft(int layout) {
@@ -354,6 +368,7 @@
             throw new RuntimeException("Unable to build left nav bar due to missing layout");
         }
         mLeftNavigationBarView.setStatusBar(this);
+        addTemperatureViewToController(mLeftNavigationBarView);
     }
 
 
@@ -364,6 +379,8 @@
             Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
             throw new RuntimeException("Unable to build right nav bar due to missing layout");
         }
+        mRightNavigationBarView.setStatusBar(this);
+        addTemperatureViewToController(mRightNavigationBarView);
     }
 
     @Override
@@ -377,10 +394,12 @@
                     + "," + mStackScroller.getScrollY());
         }
 
-        pw.print("  mTaskStackListener="); pw.println(mTaskStackListener);
+        pw.print("  mTaskStackListener=");
+        pw.println(mTaskStackListener);
         pw.print("  mCarFacetButtonController=");
         pw.println(mCarFacetButtonController);
-        pw.print("  mFullscreenUserSwitcher="); pw.println(mFullscreenUserSwitcher);
+        pw.print("  mFullscreenUserSwitcher=");
+        pw.println(mFullscreenUserSwitcher);
         pw.print("  mCarBatteryController=");
         pw.println(mCarBatteryController);
         pw.print("  mBatteryMeterView=");
@@ -399,7 +418,10 @@
 
         pw.println("SharedPreferences:");
         for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
-            pw.print("  "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
+            pw.print("  ");
+            pw.print(entry.getKey());
+            pw.print("=");
+            pw.println(entry.getValue());
         }
     }
 
@@ -445,8 +467,8 @@
     }
 
     /**
-     * An implementation of SysUiTaskStackChangeListener, that listens for changes in the system task
-     * stack and notifies the navigation bar.
+     * An implementation of SysUiTaskStackChangeListener, that listens for changes in the system
+     * task stack and notifies the navigation bar.
      */
     private class TaskStackListenerImpl extends SysUiTaskStackChangeListener {
         @Override
@@ -481,8 +503,15 @@
     }
 
     @Override
-    public void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) {
-        super.updateKeyguardState(goingToFullShade, fromShadeLocked);
+    public void onStateChanged(int newState) {
+        super.onStateChanged(newState);
+        CarUserManagerHelper helper = new CarUserManagerHelper(mContext);
+        if (!helper.isHeadlessSystemUser()) {
+            showUserSwitcher();
+        }
+    }
+
+    public void showUserSwitcher() {
         if (mFullscreenUserSwitcher != null) {
             if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
                 mFullscreenUserSwitcher.show();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
index dabe23e..d0f0629 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
@@ -39,4 +39,13 @@
     protected boolean shouldDestroyViewOnReset() {
         return true;
     }
+
+    /**
+     * Called when cancel button in bouncer is pressed.
+     */
+    @Override
+    public void onCancelClicked() {
+        CarStatusBar statusBar = (CarStatusBar) mStatusBar;
+        statusBar.showUserSwitcher();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index d720aef..67a76fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -18,15 +18,13 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.car.user.CarUserManagerHelper;
 import android.content.Context;
-import android.content.pm.UserInfo;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewStub;
 
 import androidx.recyclerview.widget.GridLayoutManager;
 
-import com.android.settingslib.users.UserManagerHelper;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.StatusBar;
 
@@ -39,8 +37,7 @@
     private final UserGridRecyclerView mUserGridView;
     private final int mShortAnimDuration;
     private final StatusBar mStatusBar;
-    private final UserManagerHelper mUserManagerHelper;
-    private int mCurrentForegroundUserId;
+    private final CarUserManagerHelper mCarUserManagerHelper;
     private boolean mShowing;
 
     public FullscreenUserSwitcher(StatusBar statusBar, ViewStub containerStub, Context context) {
@@ -54,18 +51,15 @@
         mUserGridView.buildAdapter();
         mUserGridView.setUserSelectionListener(this::onUserSelected);
 
-        mUserManagerHelper = new UserManagerHelper(context);
-        updateCurrentForegroundUser();
+        mCarUserManagerHelper = new CarUserManagerHelper(context);
 
         mShortAnimDuration = mContainer.getResources()
             .getInteger(android.R.integer.config_shortAnimTime);
     }
 
     public void show() {
-        // On a switch from the system user, don't show the user switcher
-        if (mUserManagerHelper.isHeadlessSystemUser() && mUserManagerHelper
-            .userIsSystemUser(mUserManagerHelper.getForegroundUserInfo())) {
-            return;
+        if (mCarUserManagerHelper.isHeadlessSystemUser()) {
+            showUserGrid();
         }
         if (mShowing) {
             return;
@@ -80,32 +74,31 @@
     }
 
     public void onUserSwitched(int newUserId) {
-        // The logic for foreground user change is needed here to exclude the reboot case. On
-        // reboot, system fires ACTION_USER_SWITCHED change from -1 to 0 user. This is not an actual
-        // user switch. We only want to trigger keyguard dismissal when foreground user changes.
-        if (foregroundUserChanged()) {
-            toggleSwitchInProgress(false);
-            updateCurrentForegroundUser();
-            mParent.post(this::dismissKeyguard);
-        }
-    }
-
-    private boolean foregroundUserChanged() {
-        return mCurrentForegroundUserId != mUserManagerHelper.getForegroundUserId();
-    }
-
-    private void updateCurrentForegroundUser() {
-        mCurrentForegroundUserId = mUserManagerHelper.getForegroundUserId();
+        toggleSwitchInProgress(false);
+        mParent.post(this::dismissKeyguard);
     }
 
     private void onUserSelected(UserGridRecyclerView.UserRecord record) {
-        if (record.mIsForeground) {
+        if (mCarUserManagerHelper.isHeadlessSystemUser()) {
+            hideUserGrid();
+        }
+
+        if (record.mIsForeground || (record.mIsStartGuestSession
+                && mCarUserManagerHelper.isForegroundUserGuest())) {
             dismissKeyguard();
             return;
         }
         toggleSwitchInProgress(true);
     }
 
+    private void showUserGrid() {
+        mUserGridView.setVisibility(View.VISIBLE);
+    }
+
+    private void hideUserGrid() {
+        mUserGridView.setVisibility(View.INVISIBLE);
+    }
+
     // Dismisses the keyguard and shows bouncer if authentication is necessary.
     private void dismissKeyguard() {
         mStatusBar.executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 257fa75..67e512c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -22,6 +22,7 @@
 import android.app.AlertDialog;
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
+import android.car.user.CarUserManagerHelper;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.pm.UserInfo;
@@ -42,7 +43,6 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.internal.util.UserIcons;
-import com.android.settingslib.users.UserManagerHelper;
 import com.android.systemui.R;
 
 import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -54,16 +54,16 @@
  * One of the uses of this is for the lock screen in auto.
  */
 public class UserGridRecyclerView extends PagedListView implements
-        UserManagerHelper.OnUsersUpdateListener {
+        CarUserManagerHelper.OnUsersUpdateListener {
     private UserSelectionListener mUserSelectionListener;
     private UserAdapter mAdapter;
-    private UserManagerHelper mUserManagerHelper;
+    private CarUserManagerHelper mCarUserManagerHelper;
     private Context mContext;
 
     public UserGridRecyclerView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
-        mUserManagerHelper = new UserManagerHelper(mContext);
+        mCarUserManagerHelper = new CarUserManagerHelper(mContext);
     }
 
     /**
@@ -72,7 +72,7 @@
     @Override
     public void onFinishInflate() {
         super.onFinishInflate();
-        mUserManagerHelper.registerOnUsersUpdateListener(this);
+        mCarUserManagerHelper.registerOnUsersUpdateListener(this);
     }
 
     /**
@@ -81,7 +81,7 @@
     @Override
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        mUserManagerHelper.unregisterOnUsersUpdateListener();
+        mCarUserManagerHelper.unregisterOnUsersUpdateListener(this);
     }
 
     /**
@@ -90,7 +90,7 @@
      * @return the adapter
      */
     public void buildAdapter() {
-        List<UserRecord> userRecords = createUserRecords(mUserManagerHelper
+        List<UserRecord> userRecords = createUserRecords(mCarUserManagerHelper
                 .getAllUsers());
         mAdapter = new UserAdapter(mContext, userRecords);
         super.setAdapter(mAdapter);
@@ -98,44 +98,56 @@
 
     private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) {
         List<UserRecord> userRecords = new ArrayList<>();
+
+        // If the foreground user CANNOT switch to other users, only display the foreground user.
+        if (!mCarUserManagerHelper.canForegroundUserSwitchUsers()) {
+            userRecords.add(createForegroundUserRecord());
+            return userRecords;
+        }
+
         for (UserInfo userInfo : userInfoList) {
             if (userInfo.isGuest()) {
                 // Don't display guests in the switcher.
                 continue;
             }
-            boolean isForeground = mUserManagerHelper.getForegroundUserId() == userInfo.id;
+
+            boolean isForeground =
+                    mCarUserManagerHelper.getCurrentForegroundUserId() == userInfo.id;
             UserRecord record = new UserRecord(userInfo, false /* isStartGuestSession */,
                     false /* isAddUser */, isForeground);
             userRecords.add(record);
         }
 
-        // Add guest user record if the foreground user is not a guest
-        if (!mUserManagerHelper.foregroundUserIsGuestUser()) {
-            userRecords.add(addGuestUserRecord());
-        }
+        // Add button for starting guest session.
+        userRecords.add(createStartGuestUserRecord());
 
         // Add add user record if the foreground user can add users
-        if (mUserManagerHelper.foregroundUserCanAddUsers()) {
-            userRecords.add(addUserRecord());
+        if (mCarUserManagerHelper.canForegroundUserAddUsers()) {
+            userRecords.add(createAddUserRecord());
         }
 
         return userRecords;
     }
 
+    private UserRecord createForegroundUserRecord() {
+        return new UserRecord(mCarUserManagerHelper.getCurrentForegroundUserInfo(),
+                false /* isStartGuestSession */, false /* isAddUser */, true /* isForeground */);
+    }
+
     /**
      * Create guest user record
      */
-    private UserRecord addGuestUserRecord() {
+    private UserRecord createStartGuestUserRecord() {
         UserInfo userInfo = new UserInfo();
-        userInfo.name = mContext.getString(R.string.car_guest);
-        return new UserRecord(userInfo, true /* isStartGuestSession */,
-                false /* isAddUser */, false /* isForeground */);
+        userInfo.name = mContext.getString(R.string.start_guest_session);
+        return new UserRecord(userInfo, true /* isStartGuestSession */, false /* isAddUser */,
+                false /* isForeground */);
     }
 
     /**
      * Create add user record
      */
-    private UserRecord addUserRecord() {
+    private UserRecord createAddUserRecord() {
         UserInfo userInfo = new UserInfo();
         userInfo.name = mContext.getString(R.string.car_add_user);
         return new UserRecord(userInfo, false /* isStartGuestSession */,
@@ -149,7 +161,7 @@
     @Override
     public void onUsersUpdate() {
         mAdapter.clearUsers();
-        mAdapter.updateUsers(createUserRecords(mUserManagerHelper.getAllUsers()));
+        mAdapter.updateUsers(createUserRecords(mCarUserManagerHelper.getAllUsers()));
         mAdapter.notifyDataSetChanged();
     }
 
@@ -157,14 +169,13 @@
      * Adapter to populate the grid layout with the available user profiles
      */
     public final class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserAdapterViewHolder>
-            implements Dialog.OnClickListener {
+            implements Dialog.OnClickListener, Dialog.OnCancelListener {
 
         private final Context mContext;
         private List<UserRecord> mUsers;
         private final Resources mRes;
         private final String mGuestName;
         private final String mNewUserName;
-        private AlertDialog mDialog;
         // View that holds the add user button.  Used to enable/disable the view
         private View mAddUserView;
         // User record for the add user.  Need to call notifyUserSelected only if the user
@@ -210,11 +221,9 @@
                     return;
                 }
 
-
-                // If the user selects Guest, start the guest session.
                 if (userRecord.mIsStartGuestSession) {
                     notifyUserSelected(userRecord);
-                    mUserManagerHelper.startNewGuestSession(mGuestName);
+                    mCarUserManagerHelper.startNewGuestSession(mGuestName);
                     return;
                 }
 
@@ -223,31 +232,59 @@
                     // Disable button so it cannot be clicked multiple times
                     mAddUserView = holder.mView;
                     mAddUserView.setEnabled(false);
-
-                    String message = mRes.getString(R.string.user_add_user_message_setup)
-                        .concat(System.getProperty("line.separator"))
-                        .concat(System.getProperty("line.separator"))
-                        .concat(mRes.getString(R.string.user_add_user_message_update));
-
                     mAddUserRecord = userRecord;
-                    mDialog = new Builder(mContext, R.style.Theme_Car_Dark_Dialog_Alert)
-                        .setTitle(R.string.user_add_user_title)
-                        .setMessage(message)
-                        .setNegativeButton(android.R.string.cancel, this)
-                        .setPositiveButton(android.R.string.ok, this)
-                        .create();
-                    // Sets window flags for the SysUI dialog
-                    SystemUIDialog.applyFlags(mDialog);
-                    mDialog.show();
+
+                    handleAddUserClicked();
                     return;
                 }
                 // If the user doesn't want to be a guest or add a user, switch to the user selected
                 notifyUserSelected(userRecord);
-                mUserManagerHelper.switchToUser(userRecord.mInfo);
+                mCarUserManagerHelper.switchToUser(userRecord.mInfo);
             });
 
         }
 
+        private void handleAddUserClicked() {
+            if (mCarUserManagerHelper.isUserLimitReached()) {
+                mAddUserView.setEnabled(true);
+                showMaxUserLimitReachedDialog();
+            } else {
+                showConfirmAddUserDialog();
+            }
+        }
+
+        private void showMaxUserLimitReachedDialog() {
+            AlertDialog maxUsersDialog = new Builder(mContext, R.style.Theme_Car_Dark_Dialog_Alert)
+                .setTitle(R.string.user_limit_reached_title)
+                .setMessage(getResources().getQuantityString(
+                    R.plurals.user_limit_reached_message,
+                    mCarUserManagerHelper.getMaxSupportedRealUsers(),
+                    mCarUserManagerHelper.getMaxSupportedRealUsers()))
+                .setPositiveButton(android.R.string.ok, null)
+                .create();
+            // Sets window flags for the SysUI dialog
+            SystemUIDialog.applyFlags(maxUsersDialog);
+            maxUsersDialog.show();
+        }
+
+        private void showConfirmAddUserDialog() {
+            String message = mRes.getString(R.string.user_add_user_message_setup)
+                .concat(System.getProperty("line.separator"))
+                .concat(System.getProperty("line.separator"))
+                .concat(mRes.getString(R.string.user_add_user_message_update));
+
+            AlertDialog addUserDialog = new Builder(mContext, R.style.Theme_Car_Dark_Dialog_Alert)
+                .setTitle(R.string.user_add_user_title)
+                .setMessage(message)
+                .setNegativeButton(android.R.string.cancel, this)
+                .setPositiveButton(android.R.string.ok, this)
+                .setOnCancelListener(this)
+                .create();
+            // Sets window flags for the SysUI dialog
+            SystemUIDialog.applyFlags(addUserDialog);
+            addUserDialog.show();
+        }
+
         private void notifyUserSelected(UserRecord userRecord) {
             // Notify the listener which user was selected
             if (mUserSelectionListener != null) {
@@ -257,7 +294,7 @@
 
         private Bitmap getUserRecordIcon(UserRecord userRecord) {
             if (userRecord.mIsStartGuestSession) {
-                return mUserManagerHelper.getGuestDefaultIcon();
+                return mCarUserManagerHelper.getGuestDefaultIcon();
             }
 
             if (userRecord.mIsAddUser) {
@@ -265,7 +302,7 @@
                     .getDrawable(R.drawable.car_add_circle_round));
             }
 
-            return mUserManagerHelper.getUserIcon(userRecord.mInfo);
+            return mCarUserManagerHelper.getUserIcon(userRecord.mInfo);
         }
 
         @Override
@@ -281,11 +318,19 @@
             }
         }
 
+        @Override
+        public void onCancel(DialogInterface dialog) {
+            // Enable the add button again if user cancels dialog by clicking outside the dialog
+            if (mAddUserView != null) {
+                mAddUserView.setEnabled(true);
+            }
+        }
+
         private class AddNewUserTask extends AsyncTask<String, Void, UserInfo> {
 
             @Override
             protected UserInfo doInBackground(String... userNames) {
-                return mUserManagerHelper.createNewUser(userNames[0]);
+                return mCarUserManagerHelper.createNewNonAdminUser(userNames[0]);
             }
 
             @Override
@@ -295,7 +340,7 @@
             @Override
             protected void onPostExecute(UserInfo user) {
                 if (user != null) {
-                    mUserManagerHelper.switchToUser(user);
+                    mCarUserManagerHelper.switchToUser(user);
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
index 81d6191..6c924e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.car.hvac;
 
 import android.car.Car;
-import android.car.CarNotConnectedException;
 import android.car.hardware.CarPropertyValue;
 import android.car.hardware.hvac.CarHvacManager;
 import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback;
@@ -147,7 +146,7 @@
                 return;
             }
             view.setTemp(mHvacManager.getFloatProperty(id, zone));
-        } catch (CarNotConnectedException e) {
+        } catch (Exception e) {
             view.setTemp(Float.NaN);
             Log.e(TAG, "Failed to get value from hvac service", e);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureTextView.java
index 8143c13..4d8ce43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureTextView.java
@@ -21,7 +21,6 @@
 import android.util.AttributeSet;
 import android.widget.TextView;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 
 /**
@@ -31,8 +30,6 @@
  * hvacPropertyId - Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (16385)
  * hvacAreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1)
  * hvacTempFormat - Example: "%.1f\u00B0" (1 decimal and the degree symbol)
- *
- * Note: It registers itself with {@link HvacController}
  */
 public class TemperatureTextView extends TextView implements TemperatureView {
 
@@ -47,10 +44,6 @@
         mPropertyId = typedArray.getInt(R.styleable.TemperatureView_hvacPropertyId, -1);
         String format = typedArray.getString(R.styleable.TemperatureView_hvacTempFormat);
         mTempFormat = (format == null) ? "%.1f\u00B0" : format;
-
-        // register with controller
-        HvacController hvacController = Dependency.get(HvacController.class);
-        hvacController.addHvacTextView(this);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AboveShelfObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AboveShelfObserver.java
index f10d2d7..24eb5be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AboveShelfObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AboveShelfObserver.java
@@ -20,7 +20,7 @@
 import android.view.ViewGroup;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * An observer that listens to the above shelf state and can notify listeners
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index a68d75a..53d38c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -29,20 +29,20 @@
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
 
+import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.shared.system.SurfaceControlCompat;
 import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier;
 import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationListContainer;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarWindowView;
 
-import java.util.ArrayList;
-
 /**
  * A class that allows activities to be launched in a seamless way where the notification
  * transforms nicely into the starting window.
@@ -59,6 +59,7 @@
     private final NotificationPanelView mNotificationPanel;
     private final NotificationListContainer mNotificationContainer;
     private final StatusBarWindowView mStatusBarWindow;
+    private final StatusBarStateController mStatusBarStateController;
     private StatusBar mStatusBar;
     private final Runnable mTimeoutRunnable = () -> {
         setAnimationPending(false);
@@ -74,11 +75,12 @@
         mNotificationContainer = container;
         mStatusBarWindow = statusBarWindow;
         mStatusBar = statusBar;
+        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
     }
 
     public RemoteAnimationAdapter getLaunchAnimation(
             ExpandableNotificationRow sourceNotification, boolean occluded) {
-        if (mStatusBar.getBarState() != StatusBarState.SHADE || occluded) {
+        if (mStatusBarStateController.getState() != StatusBarState.SHADE || occluded) {
             return null;
         }
         AnimationRunner animationRunner = new AnimationRunner(sourceNotification);
@@ -93,7 +95,7 @@
     public void setLaunchResult(int launchResult) {
         setAnimationPending((launchResult == ActivityManager.START_TASK_TO_FRONT
                 || launchResult == ActivityManager.START_SUCCESS)
-                        && mStatusBar.getBarState() == StatusBarState.SHADE);
+                        && mStatusBarStateController.getState() == StatusBarState.SHADE);
     }
 
     private void setAnimationPending(boolean pending) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java
new file mode 100644
index 0000000..8cae806
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.statusbar.NotificationPresenter;
+
+/**
+ * This class handles listening to notification updates and passing them along to
+ * NotificationPresenter to be displayed to the user.
+ */
+public class AppOpsListener implements AppOpsManager.OnOpActiveChangedListener {
+    private static final String TAG = "NotificationListener";
+
+    // Dependencies:
+    private final ForegroundServiceController mFsc =
+            Dependency.get(ForegroundServiceController.class);
+
+    private final Context mContext;
+    protected NotificationPresenter mPresenter;
+    protected NotificationEntryManager mEntryManager;
+    protected final AppOpsManager mAppOps;
+
+    protected static final int[] OPS = new int[] {AppOpsManager.OP_CAMERA,
+            AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+            AppOpsManager.OP_RECORD_AUDIO};
+
+    public AppOpsListener(Context context) {
+        mContext = context;
+        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+    }
+
+    public void setUpWithPresenter(NotificationPresenter presenter,
+            NotificationEntryManager entryManager) {
+        mPresenter = presenter;
+        mEntryManager = entryManager;
+        mAppOps.startWatchingActive(OPS, this);
+    }
+
+    public void destroy() {
+        mAppOps.stopWatchingActive(this);
+    }
+
+    @Override
+    public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
+        mFsc.onAppOpChanged(code, uid, packageName, active);
+        mPresenter.getHandler().post(() -> {
+          mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active);
+        });
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java
deleted file mode 100644
index ec94df1..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java
+++ /dev/null
@@ -1,176 +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.systemui.statusbar.notification;
-
-import android.app.Notification;
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.TypedValue;
-import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import com.android.systemui.R;
-
-/**
- * A class managing hybrid groups that include {@link HybridNotificationView} and the notification
- * group overflow.
- */
-public class HybridGroupManager {
-
-    private final Context mContext;
-    private final NotificationDozeHelper mDozer;
-    private final ViewGroup mParent;
-
-    private float mOverflowNumberSizeDark;
-    private int mOverflowNumberPaddingDark;
-    private float mOverflowNumberSize;
-    private int mOverflowNumberPadding;
-
-    private int mOverflowNumberColor;
-    private int mOverflowNumberColorDark;
-    private float mDarkAmount = 0f;
-
-    public HybridGroupManager(Context ctx, ViewGroup parent) {
-        mContext = ctx;
-        mParent = parent;
-        mDozer = new NotificationDozeHelper();
-        initDimens();
-    }
-
-    public void initDimens() {
-        Resources res = mContext.getResources();
-        mOverflowNumberSize = res.getDimensionPixelSize(
-                R.dimen.group_overflow_number_size);
-        mOverflowNumberSizeDark = res.getDimensionPixelSize(
-                R.dimen.group_overflow_number_size_dark);
-        mOverflowNumberPadding = res.getDimensionPixelSize(
-                R.dimen.group_overflow_number_padding);
-        mOverflowNumberPaddingDark = mOverflowNumberPadding + res.getDimensionPixelSize(
-                R.dimen.group_overflow_number_extra_padding_dark);
-    }
-
-    private HybridNotificationView inflateHybridViewWithStyle(int style) {
-        LayoutInflater inflater = new ContextThemeWrapper(mContext, style)
-                .getSystemService(LayoutInflater.class);
-        HybridNotificationView hybrid = (HybridNotificationView) inflater.inflate(
-                R.layout.hybrid_notification, mParent, false);
-        mParent.addView(hybrid);
-        return hybrid;
-    }
-
-    private TextView inflateOverflowNumber() {
-        LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
-        TextView numberView = (TextView) inflater.inflate(
-                R.layout.hybrid_overflow_number, mParent, false);
-        mParent.addView(numberView);
-        updateOverFlowNumberColor(numberView);
-        return numberView;
-    }
-
-    private void updateOverFlowNumberColor(TextView numberView) {
-        numberView.setTextColor(NotificationUtils.interpolateColors(
-                mOverflowNumberColor, mOverflowNumberColorDark, mDarkAmount));
-    }
-
-    public void setOverflowNumberColor(TextView numberView, int colorRegular, int colorDark) {
-        mOverflowNumberColor = colorRegular;
-        mOverflowNumberColorDark = colorDark;
-        if (numberView != null) {
-            updateOverFlowNumberColor(numberView);
-        }
-    }
-
-    public HybridNotificationView bindFromNotification(HybridNotificationView reusableView,
-            Notification notification) {
-        return bindFromNotificationWithStyle(reusableView, notification,
-                R.style.HybridNotification);
-    }
-
-    public HybridNotificationView bindAmbientFromNotification(HybridNotificationView reusableView,
-            Notification notification) {
-        return bindFromNotificationWithStyle(reusableView, notification,
-                R.style.HybridNotification_Ambient);
-    }
-
-    private HybridNotificationView bindFromNotificationWithStyle(
-            HybridNotificationView reusableView, Notification notification, int style) {
-        if (reusableView == null) {
-            reusableView = inflateHybridViewWithStyle(style);
-        }
-        CharSequence titleText = resolveTitle(notification);
-        CharSequence contentText = resolveText(notification);
-        reusableView.bind(titleText, contentText);
-        return reusableView;
-    }
-
-    private CharSequence resolveText(Notification notification) {
-        CharSequence contentText = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
-        if (contentText == null) {
-            contentText = notification.extras.getCharSequence(Notification.EXTRA_BIG_TEXT);
-        }
-        return contentText;
-    }
-
-    private CharSequence resolveTitle(Notification notification) {
-        CharSequence titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
-        if (titleText == null) {
-            titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE_BIG);
-        }
-        return titleText;
-    }
-
-    public TextView bindOverflowNumber(TextView reusableView, int number) {
-        if (reusableView == null) {
-            reusableView = inflateOverflowNumber();
-        }
-        String text = mContext.getResources().getString(
-                R.string.notification_group_overflow_indicator, number);
-        if (!text.equals(reusableView.getText())) {
-            reusableView.setText(text);
-        }
-        String contentDescription = String.format(mContext.getResources().getQuantityString(
-                R.plurals.notification_group_overflow_description, number), number);
-
-        reusableView.setContentDescription(contentDescription);
-        return reusableView;
-    }
-
-    public TextView bindOverflowNumberAmbient(TextView titleView, Notification notification,
-            int number) {
-        String text = mContext.getResources().getString(
-                R.string.notification_group_overflow_indicator_ambient,
-                resolveTitle(notification), number);
-        if (!text.equals(titleView.getText())) {
-            titleView.setText(text);
-        }
-        return titleView;
-    }
-
-    public void setOverflowNumberDark(TextView view, boolean dark, boolean fade, long delay) {
-        mDozer.setIntensityDark((f)->{
-            mDarkAmount = f;
-            updateOverFlowNumberColor(view);
-        }, dark, fade, delay, view);
-        view.setTextSize(TypedValue.COMPLEX_UNIT_PX,
-                dark ? mOverflowNumberSizeDark : mOverflowNumberSize);
-        int paddingEnd = dark ? mOverflowNumberPaddingDark : mOverflowNumberPadding;
-        view.setPaddingRelative(view.getPaddingStart(), view.getPaddingTop(), paddingEnd,
-                view.getPaddingBottom());
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
deleted file mode 100644
index 85f2a63..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
+++ /dev/null
@@ -1,155 +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.systemui.statusbar.notification;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.TextView;
-
-import com.android.keyguard.AlphaOptimizedLinearLayout;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.ViewTransformationHelper;
-
-/**
- * A hybrid view which may contain information about one ore more notifications.
- */
-public class HybridNotificationView extends AlphaOptimizedLinearLayout
-        implements TransformableView {
-
-    private ViewTransformationHelper mTransformationHelper;
-
-    protected TextView mTitleView;
-    protected TextView mTextView;
-
-    public HybridNotificationView(Context context) {
-        this(context, null);
-    }
-
-    public HybridNotificationView(Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    public TextView getTitleView() {
-        return mTitleView;
-    }
-
-    public TextView getTextView() {
-        return mTextView;
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mTitleView = (TextView) findViewById(R.id.notification_title);
-        mTextView = (TextView) findViewById(R.id.notification_text);
-        mTransformationHelper = new ViewTransformationHelper();
-        mTransformationHelper.setCustomTransformation(
-                new ViewTransformationHelper.CustomTransformation() {
-                    @Override
-                    public boolean transformTo(TransformState ownState, TransformableView notification,
-                            float transformationAmount) {
-                        // We want to transform to the same y location as the title
-                        TransformState otherState = notification.getCurrentState(
-                                TRANSFORMING_VIEW_TITLE);
-                        CrossFadeHelper.fadeOut(mTextView, transformationAmount);
-                        if (otherState != null) {
-                            ownState.transformViewVerticalTo(otherState, transformationAmount);
-                            otherState.recycle();
-                        }
-                        return true;
-                    }
-
-                    @Override
-                    public boolean transformFrom(TransformState ownState,
-                            TransformableView notification, float transformationAmount) {
-                        // We want to transform from the same y location as the title
-                        TransformState otherState = notification.getCurrentState(
-                                TRANSFORMING_VIEW_TITLE);
-                        CrossFadeHelper.fadeIn(mTextView, transformationAmount);
-                        if (otherState != null) {
-                            ownState.transformViewVerticalFrom(otherState, transformationAmount);
-                            otherState.recycle();
-                        }
-                        return true;
-                    }
-                }, TRANSFORMING_VIEW_TEXT);
-        mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TITLE, mTitleView);
-        mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TEXT, mTextView);
-    }
-
-    public void bind(CharSequence title) {
-        bind(title, null);
-    }
-
-    public void bind(CharSequence title, CharSequence text) {
-        mTitleView.setText(title);
-        mTitleView.setVisibility(TextUtils.isEmpty(title) ? GONE : VISIBLE);
-        if (TextUtils.isEmpty(text)) {
-            mTextView.setVisibility(GONE);
-            mTextView.setText(null);
-        } else {
-            mTextView.setVisibility(VISIBLE);
-            mTextView.setText(text.toString());
-        }
-        requestLayout();
-    }
-
-    @Override
-    public TransformState getCurrentState(int fadingView) {
-        return mTransformationHelper.getCurrentState(fadingView);
-    }
-
-    @Override
-    public void transformTo(TransformableView notification, Runnable endRunnable) {
-        mTransformationHelper.transformTo(notification, endRunnable);
-    }
-
-    @Override
-    public void transformTo(TransformableView notification, float transformationAmount) {
-        mTransformationHelper.transformTo(notification, transformationAmount);
-    }
-
-    @Override
-    public void transformFrom(TransformableView notification) {
-        mTransformationHelper.transformFrom(notification);
-    }
-
-    @Override
-    public void transformFrom(TransformableView notification, float transformationAmount) {
-        mTransformationHelper.transformFrom(notification, transformationAmount);
-    }
-
-    @Override
-    public void setVisible(boolean visible) {
-        setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
-        mTransformationHelper.setVisible(visible);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
index d3a325d..4882a23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
@@ -21,13 +21,12 @@
 import android.view.View;
 import android.widget.ImageView;
 
-import com.android.internal.widget.MessagingImageMessage;
-import com.android.internal.widget.MessagingMessage;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.statusbar.notification.row.HybridNotificationView;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 /**
  * A transform state of a image view.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
deleted file mode 100644
index cf12e94..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import android.app.Notification;
-import android.content.Context;
-import android.graphics.drawable.Icon;
-import android.os.Bundle;
-import android.service.notification.StatusBarNotification;
-import android.view.View;
-
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-
-/**
- * Wraps a notification containing a big picture template
- */
-public class NotificationBigPictureTemplateViewWrapper extends NotificationTemplateViewWrapper {
-
-    protected NotificationBigPictureTemplateViewWrapper(Context ctx, View view,
-            ExpandableNotificationRow row) {
-        super(ctx, view, row);
-    }
-
-    @Override
-    public void onContentUpdated(ExpandableNotificationRow row) {
-        super.onContentUpdated(row);
-        updateImageTag(row.getStatusBarNotification());
-    }
-
-    private void updateImageTag(StatusBarNotification notification) {
-        final Bundle extras = notification.getNotification().extras;
-        Icon overRiddenIcon = extras.getParcelable(Notification.EXTRA_LARGE_ICON_BIG);
-        if (overRiddenIcon != null) {
-            mPicture.setTag(ImageTransformState.ICON_TAG, overRiddenIcon);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
deleted file mode 100644
index 20a3d8f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import android.content.Context;
-import android.service.notification.StatusBarNotification;
-import android.view.View;
-
-import com.android.internal.widget.ImageFloatingTextView;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-
-/**
- * Wraps a notification containing a big text template
- */
-public class NotificationBigTextTemplateViewWrapper extends NotificationTemplateViewWrapper {
-
-    private ImageFloatingTextView mBigtext;
-
-    protected NotificationBigTextTemplateViewWrapper(Context ctx, View view,
-            ExpandableNotificationRow row) {
-        super(ctx, view, row);
-    }
-
-    private void resolveViews(StatusBarNotification notification) {
-        mBigtext = (ImageFloatingTextView) mView.findViewById(com.android.internal.R.id.big_text);
-    }
-
-    @Override
-    public void onContentUpdated(ExpandableNotificationRow row) {
-        // Reinspect the notification. Before the super call, because the super call also updates
-        // the transformation types and we need to have our values set by then.
-        resolveViews(row.getStatusBarNotification());
-        super.onContentUpdated(row);
-    }
-
-    @Override
-    protected void updateTransformedTypes() {
-        // This also clears the existing types
-        super.updateTransformedTypes();
-        if (mBigtext != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
-                    mBigtext);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCounters.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCounters.java
deleted file mode 100644
index 9a12e8b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCounters.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-/**
- * Constants for counter tags for Notification-related actions/views.
- */
-public class NotificationCounters {
-    /** Counter tag for notification dismissal. */
-    public static final String NOTIFICATION_DISMISSED = "notification_dismissed";
-
-    /** Counter tag for when the blocking helper is shown to the user. */
-    public static final String BLOCKING_HELPER_SHOWN = "blocking_helper_shown";
-    /** Counter tag for when the blocking helper is dismissed via a miscellaneous interaction. */
-    public static final String BLOCKING_HELPER_DISMISSED = "blocking_helper_dismissed";
-    /** Counter tag for when the user hits 'stop notifications' in the blocking helper. */
-    public static final String BLOCKING_HELPER_STOP_NOTIFICATIONS =
-            "blocking_helper_stop_notifications";
-    /** Counter tag for when the user hits 'keep showing' in the blocking helper. */
-    public static final String BLOCKING_HELPER_KEEP_SHOWING =
-            "blocking_helper_keep_showing";
-    /**
-     * Counter tag for when the user hits undo in context of the blocking helper - this can happen
-     * multiple times per view.
-     */
-    public static final String BLOCKING_HELPER_UNDO = "blocking_helper_undo";
-    /** Counter tag for when the user hits the notification settings icon in the blocking helper. */
-    public static final String BLOCKING_HELPER_NOTIF_SETTINGS =
-            "blocking_helper_notif_settings";
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
deleted file mode 100644
index 7a51fe1..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import android.content.Context;
-import android.view.View;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-
-/**
- * Wraps a notification containing a custom view.
- */
-public class NotificationCustomViewWrapper extends NotificationViewWrapper {
-
-    private boolean mIsLegacy;
-    private int mLegacyColor;
-
-    protected NotificationCustomViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
-        super(ctx, view, row);
-        mLegacyColor = row.getContext().getColor(R.color.notification_legacy_background_color);
-    }
-
-    @Override
-    public void setVisible(boolean visible) {
-        super.setVisible(visible);
-        mView.setAlpha(visible ? 1.0f : 0.0f);
-    }
-
-    @Override
-    protected boolean shouldClearBackgroundOnReapply() {
-        return false;
-    }
-
-    @Override
-    public int getCustomBackgroundColor() {
-        int customBackgroundColor = super.getCustomBackgroundColor();
-        if (customBackgroundColor == 0 && mIsLegacy) {
-            return mLegacyColor;
-        }
-        return customBackgroundColor;
-    }
-
-    public void setLegacy(boolean legacy) {
-        super.setLegacy(legacy);
-        mIsLegacy = legacy;
-    }
-
-    @Override
-    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
-        return true;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
new file mode 100644
index 0000000..804e842
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -0,0 +1,867 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import static android.app.Notification.CATEGORY_ALARM;
+import static android.app.Notification.CATEGORY_CALL;
+import static android.app.Notification.CATEGORY_EVENT;
+import static android.app.Notification.CATEGORY_MESSAGE;
+import static android.app.Notification.CATEGORY_REMINDER;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.app.AppGlobals;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Person;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.SnoozeCriterion;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RemoteViews;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.ContrastColorUtil;
+import com.android.systemui.Dependency;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.statusbar.InflationTask;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * The list of currently displaying notifications.
+ */
+public class NotificationData {
+
+    private final Environment mEnvironment;
+    private HeadsUpManager mHeadsUpManager;
+
+    final ZenModeController mZen = Dependency.get(ZenModeController.class);
+    final ForegroundServiceController mFsc = Dependency.get(ForegroundServiceController.class);
+
+    public static final class Entry {
+        private static final long LAUNCH_COOLDOWN = 2000;
+        private static final long REMOTE_INPUT_COOLDOWN = 500;
+        private static final long INITIALIZATION_DELAY = 400;
+        private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
+        private static final int COLOR_INVALID = 1;
+        public String key;
+        public StatusBarNotification notification;
+        public NotificationChannel channel;
+        public StatusBarIconView icon;
+        public StatusBarIconView expandedIcon;
+        public ExpandableNotificationRow row; // the outer expanded view
+        private boolean interruption;
+        public boolean autoRedacted; // whether the redacted notification was generated by us
+        public int targetSdk;
+        private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET;
+        public RemoteViews cachedContentView;
+        public RemoteViews cachedBigContentView;
+        public RemoteViews cachedHeadsUpContentView;
+        public RemoteViews cachedPublicContentView;
+        public RemoteViews cachedAmbientContentView;
+        public CharSequence remoteInputText;
+        public List<SnoozeCriterion> snoozeCriteria;
+        public int userSentiment = Ranking.USER_SENTIMENT_NEUTRAL;
+        @NonNull
+        public List<Notification.Action> smartActions = Collections.emptyList();
+        public CharSequence[] smartReplies = new CharSequence[0];
+
+        private int mCachedContrastColor = COLOR_INVALID;
+        private int mCachedContrastColorIsFor = COLOR_INVALID;
+        private InflationTask mRunningTask = null;
+        private Throwable mDebugThrowable;
+        public CharSequence remoteInputTextWhenReset;
+        public long lastRemoteInputSent = NOT_LAUNCHED_YET;
+        public ArraySet<Integer> mActiveAppOps = new ArraySet<>(3);
+        public CharSequence headsUpStatusBarText;
+        public CharSequence headsUpStatusBarTextPublic;
+
+        private long initializationTime = -1;
+
+        /**
+         * Whether or not this row represents a system notification. Note that if this is
+         * {@code null}, that means we were either unable to retrieve the info or have yet to
+         * retrieve the info.
+         */
+        public Boolean mIsSystemNotification;
+
+        /**
+         * Has the user sent a reply through this Notification.
+         */
+        private boolean hasSentReply;
+
+        public Entry(StatusBarNotification n) {
+            this(n, null);
+        }
+
+        public Entry(StatusBarNotification n, @Nullable Ranking ranking) {
+            this.key = n.getKey();
+            this.notification = n;
+            if (ranking != null) {
+                populateFromRanking(ranking);
+            }
+        }
+
+        public void populateFromRanking(@NonNull Ranking ranking) {
+            channel = ranking.getChannel();
+            snoozeCriteria = ranking.getSnoozeCriteria();
+            userSentiment = ranking.getUserSentiment();
+            smartActions = ranking.getSmartActions() == null
+                    ? Collections.emptyList() : ranking.getSmartActions();
+            smartReplies = ranking.getSmartReplies() == null
+                    ? new CharSequence[0]
+                    : ranking.getSmartReplies().toArray(new CharSequence[0]);
+        }
+
+        public void setInterruption() {
+            interruption = true;
+        }
+
+        public boolean hasInterrupted() {
+            return interruption;
+        }
+
+        /**
+         * Resets the notification entry to be re-used.
+         */
+        public void reset() {
+            if (row != null) {
+                row.reset();
+            }
+        }
+
+        public View getExpandedContentView() {
+            return row.getPrivateLayout().getExpandedChild();
+        }
+
+        public View getPublicContentView() {
+            return row.getPublicLayout().getContractedChild();
+        }
+
+        public void notifyFullScreenIntentLaunched() {
+            setInterruption();
+            lastFullScreenIntentLaunchTime = SystemClock.elapsedRealtime();
+        }
+
+        public boolean hasJustLaunchedFullScreenIntent() {
+            return SystemClock.elapsedRealtime() < lastFullScreenIntentLaunchTime + LAUNCH_COOLDOWN;
+        }
+
+        public boolean hasJustSentRemoteInput() {
+            return SystemClock.elapsedRealtime() < lastRemoteInputSent + REMOTE_INPUT_COOLDOWN;
+        }
+
+        public boolean hasFinishedInitialization() {
+            return initializationTime == -1 ||
+                    SystemClock.elapsedRealtime() > initializationTime + INITIALIZATION_DELAY;
+        }
+
+        /**
+         * Create the icons for a notification
+         * @param context the context to create the icons with
+         * @param sbn the notification
+         * @throws InflationException
+         */
+        public void createIcons(Context context, StatusBarNotification sbn)
+                throws InflationException {
+            Notification n = sbn.getNotification();
+            final Icon smallIcon = n.getSmallIcon();
+            if (smallIcon == null) {
+                throw new InflationException("No small icon in notification from "
+                        + sbn.getPackageName());
+            }
+
+            // Construct the icon.
+            icon = new StatusBarIconView(context,
+                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
+            icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+
+            // Construct the expanded icon.
+            expandedIcon = new StatusBarIconView(context,
+                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
+            expandedIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+            final StatusBarIcon ic = new StatusBarIcon(
+                    sbn.getUser(),
+                    sbn.getPackageName(),
+                    smallIcon,
+                    n.iconLevel,
+                    n.number,
+                    StatusBarIconView.contentDescForNotification(context, n));
+            if (!icon.set(ic) || !expandedIcon.set(ic)) {
+                icon = null;
+                expandedIcon = null;
+                throw new InflationException("Couldn't create icon: " + ic);
+            }
+            expandedIcon.setVisibility(View.INVISIBLE);
+            expandedIcon.setOnVisibilityChangedListener(
+                    newVisibility -> {
+                        if (row != null) {
+                            row.setIconsVisible(newVisibility != View.VISIBLE);
+                        }
+                    });
+        }
+
+        public void setIconTag(int key, Object tag) {
+            if (icon != null) {
+                icon.setTag(key, tag);
+                expandedIcon.setTag(key, tag);
+            }
+        }
+
+        /**
+         * Update the notification icons.
+         *
+         * @param context the context to create the icons with.
+         * @param sbn the notification to read the icon from.
+         * @throws InflationException
+         */
+        public void updateIcons(Context context, StatusBarNotification sbn)
+                throws InflationException {
+            if (icon != null) {
+                // Update the icon
+                Notification n = sbn.getNotification();
+                final StatusBarIcon ic = new StatusBarIcon(
+                        notification.getUser(),
+                        notification.getPackageName(),
+                        n.getSmallIcon(),
+                        n.iconLevel,
+                        n.number,
+                        StatusBarIconView.contentDescForNotification(context, n));
+                icon.setNotification(sbn);
+                expandedIcon.setNotification(sbn);
+                if (!icon.set(ic) || !expandedIcon.set(ic)) {
+                    throw new InflationException("Couldn't update icon: " + ic);
+                }
+            }
+        }
+
+        public int getContrastedColor(Context context, boolean isLowPriority,
+                int backgroundColor) {
+            int rawColor = isLowPriority ? Notification.COLOR_DEFAULT :
+                    notification.getNotification().color;
+            if (mCachedContrastColorIsFor == rawColor && mCachedContrastColor != COLOR_INVALID) {
+                return mCachedContrastColor;
+            }
+            final int contrasted = ContrastColorUtil.resolveContrastColor(context, rawColor,
+                    backgroundColor);
+            mCachedContrastColorIsFor = rawColor;
+            mCachedContrastColor = contrasted;
+            return mCachedContrastColor;
+        }
+
+        /**
+         * Abort all existing inflation tasks
+         */
+        public void abortTask() {
+            if (mRunningTask != null) {
+                mRunningTask.abort();
+                mRunningTask = null;
+            }
+        }
+
+        public void setInflationTask(InflationTask abortableTask) {
+            // abort any existing inflation
+            InflationTask existing = mRunningTask;
+            abortTask();
+            mRunningTask = abortableTask;
+            if (existing != null && mRunningTask != null) {
+                mRunningTask.supersedeTask(existing);
+            }
+        }
+
+        public void onInflationTaskFinished() {
+            mRunningTask = null;
+        }
+
+        @VisibleForTesting
+        public InflationTask getRunningTask() {
+            return mRunningTask;
+        }
+
+        /**
+         * Set a throwable that is used for debugging
+         *
+         * @param debugThrowable the throwable to save
+         */
+        public void setDebugThrowable(Throwable debugThrowable) {
+            mDebugThrowable = debugThrowable;
+        }
+
+        public Throwable getDebugThrowable() {
+            return mDebugThrowable;
+        }
+
+        public void onRemoteInputInserted() {
+            lastRemoteInputSent = NOT_LAUNCHED_YET;
+            remoteInputTextWhenReset = null;
+        }
+
+        public void setHasSentReply() {
+            hasSentReply = true;
+        }
+
+        public boolean isLastMessageFromReply() {
+            if (!hasSentReply) {
+                return false;
+            }
+            Bundle extras = notification.getNotification().extras;
+            CharSequence[] replyTexts = extras.getCharSequenceArray(
+                    Notification.EXTRA_REMOTE_INPUT_HISTORY);
+            if (!ArrayUtils.isEmpty(replyTexts)) {
+                return true;
+            }
+            Parcelable[] messages = extras.getParcelableArray(Notification.EXTRA_MESSAGES);
+            if (messages != null && messages.length > 0) {
+                Parcelable message = messages[messages.length - 1];
+                if (message instanceof Bundle) {
+                    Notification.MessagingStyle.Message lastMessage =
+                            Notification.MessagingStyle.Message.getMessageFromBundle(
+                                    (Bundle) message);
+                    if (lastMessage != null) {
+                        Person senderPerson = lastMessage.getSenderPerson();
+                        if (senderPerson == null) {
+                            return true;
+                        }
+                        Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON);
+                        return Objects.equals(user, senderPerson);
+                    }
+                }
+            }
+            return false;
+        }
+
+        public void setInitializationTime(long time) {
+            if (initializationTime == -1) {
+                initializationTime = time;
+            }
+        }
+    }
+
+    private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
+    private final ArrayList<Entry> mSortedAndFiltered = new ArrayList<>();
+    private final ArrayList<Entry> mFilteredForUser = new ArrayList<>();
+
+    private NotificationGroupManager mGroupManager;
+
+    private RankingMap mRankingMap;
+    private final Ranking mTmpRanking = new Ranking();
+
+    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+        mHeadsUpManager = headsUpManager;
+    }
+
+    private final Comparator<Entry> mRankingComparator = new Comparator<Entry>() {
+        private final Ranking mRankingA = new Ranking();
+        private final Ranking mRankingB = new Ranking();
+
+        @Override
+        public int compare(Entry a, Entry b) {
+            final StatusBarNotification na = a.notification;
+            final StatusBarNotification nb = b.notification;
+            int aImportance = NotificationManager.IMPORTANCE_DEFAULT;
+            int bImportance = NotificationManager.IMPORTANCE_DEFAULT;
+            int aRank = 0;
+            int bRank = 0;
+
+            if (mRankingMap != null) {
+                // RankingMap as received from NoMan
+                getRanking(a.key, mRankingA);
+                getRanking(b.key, mRankingB);
+                aImportance = mRankingA.getImportance();
+                bImportance = mRankingB.getImportance();
+                aRank = mRankingA.getRank();
+                bRank = mRankingB.getRank();
+            }
+
+            String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
+
+            // IMPORTANCE_MIN media streams are allowed to drift to the bottom
+            final boolean aMedia = a.key.equals(mediaNotification)
+                    && aImportance > NotificationManager.IMPORTANCE_MIN;
+            final boolean bMedia = b.key.equals(mediaNotification)
+                    && bImportance > NotificationManager.IMPORTANCE_MIN;
+
+            boolean aSystemMax = aImportance >= NotificationManager.IMPORTANCE_HIGH &&
+                    isSystemNotification(na);
+            boolean bSystemMax = bImportance >= NotificationManager.IMPORTANCE_HIGH &&
+                    isSystemNotification(nb);
+
+            boolean isHeadsUp = a.row.isHeadsUp();
+            if (isHeadsUp != b.row.isHeadsUp()) {
+                return isHeadsUp ? -1 : 1;
+            } else if (isHeadsUp) {
+                // Provide consistent ranking with headsUpManager
+                return mHeadsUpManager.compare(a, b);
+            } else if (aMedia != bMedia) {
+                // Upsort current media notification.
+                return aMedia ? -1 : 1;
+            } else if (aSystemMax != bSystemMax) {
+                // Upsort PRIORITY_MAX system notifications
+                return aSystemMax ? -1 : 1;
+            } else if (aRank != bRank) {
+                return aRank - bRank;
+            } else {
+                return Long.compare(nb.getNotification().when, na.getNotification().when);
+            }
+        }
+    };
+
+    public NotificationData(Environment environment) {
+        mEnvironment = environment;
+        mGroupManager = environment.getGroupManager();
+    }
+
+    /**
+     * Returns the sorted list of active notifications (depending on {@link Environment}
+     *
+     * <p>
+     * This call doesn't update the list of active notifications. Call {@link #filterAndSort()}
+     * when the environment changes.
+     * <p>
+     * Don't hold on to or modify the returned list.
+     */
+    public ArrayList<Entry> getActiveNotifications() {
+        return mSortedAndFiltered;
+    }
+
+    public ArrayList<Entry> getNotificationsForCurrentUser() {
+        mFilteredForUser.clear();
+
+        synchronized (mEntries) {
+            final int N = mEntries.size();
+            for (int i = 0; i < N; i++) {
+                Entry entry = mEntries.valueAt(i);
+                final StatusBarNotification sbn = entry.notification;
+                if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) {
+                    continue;
+                }
+                mFilteredForUser.add(entry);
+            }
+        }
+        return mFilteredForUser;
+    }
+
+    public Entry get(String key) {
+        return mEntries.get(key);
+    }
+
+    public void add(Entry entry) {
+        synchronized (mEntries) {
+            mEntries.put(entry.notification.getKey(), entry);
+        }
+        mGroupManager.onEntryAdded(entry);
+
+        updateRankingAndSort(mRankingMap);
+    }
+
+    public Entry remove(String key, RankingMap ranking) {
+        Entry removed = null;
+        synchronized (mEntries) {
+            removed = mEntries.remove(key);
+        }
+        if (removed == null) return null;
+        mGroupManager.onEntryRemoved(removed);
+        updateRankingAndSort(ranking);
+        return removed;
+    }
+
+    public void updateRanking(RankingMap ranking) {
+        updateRankingAndSort(ranking);
+    }
+
+    public void updateAppOp(int appOp, int uid, String pkg, String key, boolean showIcon) {
+        synchronized (mEntries) {
+            final int N = mEntries.size();
+            for (int i = 0; i < N; i++) {
+                Entry entry = mEntries.valueAt(i);
+                if (uid == entry.notification.getUid()
+                        && pkg.equals(entry.notification.getPackageName())
+                        && key.equals(entry.key)) {
+                    if (showIcon) {
+                        entry.mActiveAppOps.add(appOp);
+                    } else {
+                        entry.mActiveAppOps.remove(appOp);
+                    }
+                }
+            }
+        }
+    }
+
+    public boolean isAmbient(String key) {
+        if (mRankingMap != null) {
+            getRanking(key, mTmpRanking);
+            return mTmpRanking.isAmbient();
+        }
+        return false;
+    }
+
+    public int getVisibilityOverride(String key) {
+        if (mRankingMap != null) {
+            getRanking(key, mTmpRanking);
+            return mTmpRanking.getVisibilityOverride();
+        }
+        return Ranking.VISIBILITY_NO_OVERRIDE;
+    }
+
+    public boolean shouldSuppressFullScreenIntent(Entry entry) {
+        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
+    }
+
+    public boolean shouldSuppressPeek(Entry entry) {
+        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_PEEK);
+    }
+
+    public boolean shouldSuppressStatusBar(Entry entry) {
+        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_STATUS_BAR);
+    }
+
+    public boolean shouldSuppressAmbient(Entry entry) {
+        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_AMBIENT);
+    }
+
+    public boolean shouldSuppressNotificationList(Entry entry) {
+        return shouldSuppressVisualEffect(entry, SUPPRESSED_EFFECT_NOTIFICATION_LIST);
+    }
+
+    private boolean shouldSuppressVisualEffect(Entry entry, int effect) {
+        if (isExemptFromDndVisualSuppression(entry)) {
+            return false;
+        }
+        String key = entry.key;
+        if (mRankingMap != null) {
+            getRanking(key, mTmpRanking);
+            return (mTmpRanking.getSuppressedVisualEffects() & effect) != 0;
+        }
+        return false;
+    }
+
+    protected boolean isExemptFromDndVisualSuppression(Entry entry) {
+        if (isNotificationBlockedByPolicy(entry.notification.getNotification())) {
+            return false;
+        }
+
+        if ((entry.notification.getNotification().flags
+                & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+            return true;
+        }
+        if (entry.notification.getNotification().isMediaNotification()) {
+            return true;
+        }
+        if (entry.mIsSystemNotification != null && entry.mIsSystemNotification) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Categories that are explicitly called out on DND settings screens are always blocked, if
+     * DND has flagged them, even if they are foreground or system notifications that might
+     * otherwise visually bypass DND.
+     */
+    protected boolean isNotificationBlockedByPolicy(Notification n) {
+        if (isCategory(CATEGORY_CALL, n)
+                || isCategory(CATEGORY_MESSAGE, n)
+                || isCategory(CATEGORY_ALARM, n)
+                || isCategory(CATEGORY_EVENT, n)
+                || isCategory(CATEGORY_REMINDER, n)) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isCategory(String category, Notification n) {
+        return Objects.equals(n.category, category);
+    }
+
+    public int getImportance(String key) {
+        if (mRankingMap != null) {
+            getRanking(key, mTmpRanking);
+            return mTmpRanking.getImportance();
+        }
+        return NotificationManager.IMPORTANCE_UNSPECIFIED;
+    }
+
+    public String getOverrideGroupKey(String key) {
+        if (mRankingMap != null) {
+            getRanking(key, mTmpRanking);
+            return mTmpRanking.getOverrideGroupKey();
+        }
+        return null;
+    }
+
+    public List<SnoozeCriterion> getSnoozeCriteria(String key) {
+        if (mRankingMap != null) {
+            getRanking(key, mTmpRanking);
+            return mTmpRanking.getSnoozeCriteria();
+        }
+        return null;
+    }
+
+    public NotificationChannel getChannel(String key) {
+        if (mRankingMap != null) {
+            getRanking(key, mTmpRanking);
+            return mTmpRanking.getChannel();
+        }
+        return null;
+    }
+
+    public int getRank(String key) {
+        if (mRankingMap != null) {
+            getRanking(key, mTmpRanking);
+            return mTmpRanking.getRank();
+        }
+        return 0;
+    }
+
+    public boolean shouldHide(String key) {
+        if (mRankingMap != null) {
+            getRanking(key, mTmpRanking);
+            return mTmpRanking.isSuspended();
+        }
+        return false;
+    }
+
+    private void updateRankingAndSort(RankingMap ranking) {
+        if (ranking != null) {
+            mRankingMap = ranking;
+            synchronized (mEntries) {
+                final int N = mEntries.size();
+                for (int i = 0; i < N; i++) {
+                    Entry entry = mEntries.valueAt(i);
+                    if (!getRanking(entry.key, mTmpRanking)) {
+                        continue;
+                    }
+                    final StatusBarNotification oldSbn = entry.notification.cloneLight();
+                    final String overrideGroupKey = getOverrideGroupKey(entry.key);
+                    if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
+                        entry.notification.setOverrideGroupKey(overrideGroupKey);
+                        mGroupManager.onEntryUpdated(entry, oldSbn);
+                    }
+                    entry.populateFromRanking(mTmpRanking);
+                }
+            }
+        }
+        filterAndSort();
+    }
+
+    /**
+     * Get the ranking from the current ranking map.
+     *
+     * @param key the key to look up
+     * @param outRanking the ranking to populate
+     *
+     * @return {@code true} if the ranking was properly obtained.
+     */
+    @VisibleForTesting
+    protected boolean getRanking(String key, Ranking outRanking) {
+        return mRankingMap.getRanking(key, outRanking);
+    }
+
+    // TODO: This should not be public. Instead the Environment should notify this class when
+    // anything changed, and this class should call back the UI so it updates itself.
+    public void filterAndSort() {
+        mSortedAndFiltered.clear();
+
+        synchronized (mEntries) {
+            final int N = mEntries.size();
+            for (int i = 0; i < N; i++) {
+                Entry entry = mEntries.valueAt(i);
+
+                if (shouldFilterOut(entry)) {
+                    continue;
+                }
+
+                mSortedAndFiltered.add(entry);
+            }
+        }
+
+        Collections.sort(mSortedAndFiltered, mRankingComparator);
+    }
+
+    /**
+     * @return true if this notification should NOT be shown right now
+     */
+    public boolean shouldFilterOut(Entry entry) {
+        final StatusBarNotification sbn = entry.notification;
+        if (!(mEnvironment.isDeviceProvisioned() ||
+                showNotificationEvenIfUnprovisioned(sbn))) {
+            return true;
+        }
+
+        if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) {
+            return true;
+        }
+
+        if (mEnvironment.isSecurelyLocked(sbn.getUserId()) &&
+                (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
+                        || mEnvironment.shouldHideNotifications(sbn.getUserId())
+                        || mEnvironment.shouldHideNotifications(sbn.getKey()))) {
+            return true;
+        }
+
+        if (mEnvironment.isDozing() && shouldSuppressAmbient(entry)) {
+            return true;
+        }
+
+        if (!mEnvironment.isDozing() && shouldSuppressNotificationList(entry)) {
+            return true;
+        }
+
+        if (shouldHide(sbn.getKey())) {
+            return true;
+        }
+
+        if (!StatusBar.ENABLE_CHILD_NOTIFICATIONS
+                && mGroupManager.isChildInGroupWithSummary(sbn)) {
+            return true;
+        }
+
+        if (mFsc.isDungeonNotification(sbn) && !mFsc.isDungeonNeededForUser(sbn.getUserId())) {
+            // this is a foreground-service disclosure for a user that does not need to show one
+            return true;
+        }
+        if (mFsc.isSystemAlertNotification(sbn)) {
+            final String[] apps = sbn.getNotification().extras.getStringArray(
+                    Notification.EXTRA_FOREGROUND_APPS);
+            if (apps != null && apps.length >= 1) {
+                if (!mFsc.isSystemAlertWarningNeeded(sbn.getUserId(), apps[0])) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    // Q: What kinds of notifications should show during setup?
+    // A: Almost none! Only things coming from packages with permission
+    // android.permission.NOTIFICATION_DURING_SETUP that also have special "kind" tags marking them
+    // as relevant for setup (see below).
+    public static boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
+        return showNotificationEvenIfUnprovisioned(AppGlobals.getPackageManager(), sbn);
+    }
+
+    @VisibleForTesting
+    static boolean showNotificationEvenIfUnprovisioned(IPackageManager packageManager,
+            StatusBarNotification sbn) {
+        return checkUidPermission(packageManager, Manifest.permission.NOTIFICATION_DURING_SETUP,
+                sbn.getUid()) == PackageManager.PERMISSION_GRANTED
+                && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
+    }
+
+    private static int checkUidPermission(IPackageManager packageManager, String permission,
+            int uid) {
+        try {
+            return packageManager.checkUidPermission(permission, uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    public void dump(PrintWriter pw, String indent) {
+        int N = mSortedAndFiltered.size();
+        pw.print(indent);
+        pw.println("active notifications: " + N);
+        int active;
+        for (active = 0; active < N; active++) {
+            NotificationData.Entry e = mSortedAndFiltered.get(active);
+            dumpEntry(pw, indent, active, e);
+        }
+        synchronized (mEntries) {
+            int M = mEntries.size();
+            pw.print(indent);
+            pw.println("inactive notifications: " + (M - active));
+            int inactiveCount = 0;
+            for (int i = 0; i < M; i++) {
+                Entry entry = mEntries.valueAt(i);
+                if (!mSortedAndFiltered.contains(entry)) {
+                    dumpEntry(pw, indent, inactiveCount, entry);
+                    inactiveCount++;
+                }
+            }
+        }
+    }
+
+    private void dumpEntry(PrintWriter pw, String indent, int i, Entry e) {
+        getRanking(e.key, mTmpRanking);
+        pw.print(indent);
+        pw.println("  [" + i + "] key=" + e.key + " icon=" + e.icon);
+        StatusBarNotification n = e.notification;
+        pw.print(indent);
+        pw.println("      pkg=" + n.getPackageName() + " id=" + n.getId() + " importance=" +
+                mTmpRanking.getImportance());
+        pw.print(indent);
+        pw.println("      notification=" + n.getNotification());
+    }
+
+    private static boolean isSystemNotification(StatusBarNotification sbn) {
+        String sbnPackage = sbn.getPackageName();
+        return "android".equals(sbnPackage) || "com.android.systemui".equals(sbnPackage);
+    }
+
+    /**
+     * Provides access to keyguard state and user settings dependent data.
+     */
+    public interface Environment {
+        public boolean isSecurelyLocked(int userId);
+        public boolean shouldHideNotifications(int userid);
+        public boolean shouldHideNotifications(String key);
+        public boolean isDeviceProvisioned();
+        public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
+        public String getCurrentMediaNotificationKey();
+        public NotificationGroupManager getGroupManager();
+
+        /**
+         * @return true iff the device is dozing
+         */
+        boolean isDozing();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
new file mode 100644
index 0000000..b655a6b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -0,0 +1,1160 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.statusbar.notification;
+
+import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
+import static com.android.systemui.statusbar.NotificationRemoteInputManager
+        .FORCE_REMOTE_INPUT_HISTORY;
+
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.os.Build;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationStats;
+import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.EventLog;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.util.NotificationMessagingUtil;
+import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
+import com.android.systemui.EventLogTags;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.R;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationUiAdjustment;
+import com.android.systemui.statusbar.NotificationUpdateHandler;
+import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.row.NotificationInflater;
+import com.android.systemui.statusbar.notification.row.RowInflaterTask;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.util.leak.LeakDetector;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * NotificationEntryManager is responsible for the adding, removing, and updating of notifications.
+ * It also handles tasks such as their inflation and their interaction with other
+ * Notification.*Manager objects.
+ */
+public class NotificationEntryManager implements Dumpable, NotificationInflater.InflationCallback,
+        ExpandableNotificationRow.ExpansionLogger, NotificationUpdateHandler,
+        VisualStabilityManager.Callback {
+    private static final String TAG = "NotificationEntryMgr";
+    protected static final boolean DEBUG = false;
+    protected static final boolean ENABLE_HEADS_UP = true;
+    protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
+
+    protected final NotificationMessagingUtil mMessagingUtil;
+    protected final Context mContext;
+    protected final HashMap<String, NotificationData.Entry> mPendingNotifications = new HashMap<>();
+    protected final NotificationClicker mNotificationClicker = new NotificationClicker();
+    protected final ArraySet<NotificationData.Entry> mHeadsUpEntriesToRemoveOnSwitch =
+            new ArraySet<>();
+
+    // Dependencies:
+    protected final NotificationLockscreenUserManager mLockscreenUserManager =
+            Dependency.get(NotificationLockscreenUserManager.class);
+    protected final NotificationGroupManager mGroupManager =
+            Dependency.get(NotificationGroupManager.class);
+    protected final NotificationGutsManager mGutsManager =
+            Dependency.get(NotificationGutsManager.class);
+    protected final NotificationRemoteInputManager mRemoteInputManager =
+            Dependency.get(NotificationRemoteInputManager.class);
+    protected final NotificationMediaManager mMediaManager =
+            Dependency.get(NotificationMediaManager.class);
+    protected final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+    protected final DeviceProvisionedController mDeviceProvisionedController =
+            Dependency.get(DeviceProvisionedController.class);
+    protected final VisualStabilityManager mVisualStabilityManager =
+            Dependency.get(VisualStabilityManager.class);
+    protected final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+    protected final ForegroundServiceController mForegroundServiceController =
+            Dependency.get(ForegroundServiceController.class);
+    protected final NotificationListener mNotificationListener =
+            Dependency.get(NotificationListener.class);
+    private final SmartReplyController mSmartReplyController =
+            Dependency.get(SmartReplyController.class);
+
+    protected IStatusBarService mBarService;
+    protected NotificationPresenter mPresenter;
+    protected Callback mCallback;
+    protected PowerManager mPowerManager;
+    protected SystemServicesProxy mSystemServicesProxy;
+    protected NotificationListenerService.RankingMap mLatestRankingMap;
+    protected HeadsUpManager mHeadsUpManager;
+    protected NotificationData mNotificationData;
+    protected ContentObserver mHeadsUpObserver;
+    protected boolean mUseHeadsUp = false;
+    protected boolean mDisableNotificationAlerts;
+    protected NotificationListContainer mListContainer;
+    private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
+    /**
+     * Notifications with keys in this set are not actually around anymore. We kept them around
+     * when they were canceled in response to a remote input interaction. This allows us to show
+     * what you replied and allows you to continue typing into it.
+     */
+    private final ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>();
+
+
+    private final class NotificationClicker implements View.OnClickListener {
+
+        @Override
+        public void onClick(final View v) {
+            if (!(v instanceof ExpandableNotificationRow)) {
+                Log.e(TAG, "NotificationClicker called on a view that is not a notification row.");
+                return;
+            }
+
+            mPresenter.wakeUpIfDozing(SystemClock.uptimeMillis(), v);
+
+            final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+            final StatusBarNotification sbn = row.getStatusBarNotification();
+            if (sbn == null) {
+                Log.e(TAG, "NotificationClicker called on an unclickable notification,");
+                return;
+            }
+
+            // Check if the notification is displaying the menu, if so slide notification back
+            if (row.getProvider() != null && row.getProvider().isMenuVisible()) {
+                row.animateTranslateNotification(0);
+                return;
+            }
+
+            // Mark notification for one frame.
+            row.setJustClicked(true);
+            DejankUtils.postAfterTraversal(() -> row.setJustClicked(false));
+
+            mCallback.onNotificationClicked(sbn, row);
+        }
+
+        public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
+            Notification notification = sbn.getNotification();
+            if (notification.contentIntent != null || notification.fullScreenIntent != null) {
+                row.setOnClickListener(this);
+            } else {
+                row.setOnClickListener(null);
+            }
+        }
+    }
+
+    private final DeviceProvisionedController.DeviceProvisionedListener
+            mDeviceProvisionedListener =
+            new DeviceProvisionedController.DeviceProvisionedListener() {
+                @Override
+                public void onDeviceProvisionedChanged() {
+                    updateNotifications();
+                }
+            };
+
+    public NotificationListenerService.RankingMap getLatestRankingMap() {
+        return mLatestRankingMap;
+    }
+
+    public void setLatestRankingMap(NotificationListenerService.RankingMap latestRankingMap) {
+        mLatestRankingMap = latestRankingMap;
+    }
+
+    public void setDisableNotificationAlerts(boolean disableNotificationAlerts) {
+        mDisableNotificationAlerts = disableNotificationAlerts;
+        mHeadsUpObserver.onChange(true);
+    }
+
+    public void destroy() {
+        mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
+    }
+
+    public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
+        if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) {
+            removeNotification(entry.key, getLatestRankingMap());
+            mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
+            if (mHeadsUpEntriesToRemoveOnSwitch.isEmpty()) {
+                setLatestRankingMap(null);
+            }
+        } else {
+            updateNotificationRanking(null);
+        }
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("NotificationEntryManager state:");
+        pw.print("  mPendingNotifications=");
+        if (mPendingNotifications.size() == 0) {
+            pw.println("null");
+        } else {
+            for (NotificationData.Entry entry : mPendingNotifications.values()) {
+                pw.println(entry.notification);
+            }
+        }
+        pw.print("  mUseHeadsUp=");
+        pw.println(mUseHeadsUp);
+        pw.print("  mKeysKeptForRemoteInput: ");
+        pw.println(mKeysKeptForRemoteInput);
+    }
+
+    public NotificationEntryManager(Context context) {
+        mContext = context;
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+        mMessagingUtil = new NotificationMessagingUtil(context);
+        mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
+        mGroupManager.setPendingEntries(mPendingNotifications);
+    }
+
+    public void setUpWithPresenter(NotificationPresenter presenter,
+            NotificationListContainer listContainer, Callback callback,
+            HeadsUpManager headsUpManager) {
+        mPresenter = presenter;
+        mCallback = callback;
+        mNotificationData = new NotificationData(presenter);
+        mHeadsUpManager = headsUpManager;
+        mNotificationData.setHeadsUpManager(mHeadsUpManager);
+        mListContainer = listContainer;
+
+        mHeadsUpObserver = new ContentObserver(mPresenter.getHandler()) {
+            @Override
+            public void onChange(boolean selfChange) {
+                boolean wasUsing = mUseHeadsUp;
+                mUseHeadsUp = ENABLE_HEADS_UP && !mDisableNotificationAlerts
+                        && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt(
+                        mContext.getContentResolver(),
+                        Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
+                        Settings.Global.HEADS_UP_OFF);
+                Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled"));
+                if (wasUsing != mUseHeadsUp) {
+                    if (!mUseHeadsUp) {
+                        Log.d(TAG,
+                                "dismissing any existing heads up notification on disable event");
+                        mHeadsUpManager.releaseAllImmediately();
+                    }
+                }
+            }
+        };
+
+        if (ENABLE_HEADS_UP) {
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED),
+                    true,
+                    mHeadsUpObserver);
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
+                    mHeadsUpObserver);
+        }
+
+        mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
+
+        mHeadsUpObserver.onChange(true); // set up
+        mOnAppOpsClickListener = mGutsManager::openGuts;
+    }
+
+    public NotificationData getNotificationData() {
+        return mNotificationData;
+    }
+
+    public ExpandableNotificationRow.LongPressListener getNotificationLongClicker() {
+        return mGutsManager::openGuts;
+    }
+
+    @Override
+    public void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
+        mUiOffloadThread.submit(() -> {
+            try {
+                mBarService.onNotificationExpansionChanged(key, userAction, expanded);
+            } catch (RemoteException e) {
+                // Ignore.
+            }
+        });
+    }
+
+    @Override
+    public void onReorderingAllowed() {
+        updateNotifications();
+    }
+
+    private boolean shouldSuppressFullScreenIntent(NotificationData.Entry entry) {
+        if (mPresenter.isDeviceInVrMode()) {
+            return true;
+        }
+
+        return mNotificationData.shouldSuppressFullScreenIntent(entry);
+    }
+
+    private void inflateViews(NotificationData.Entry entry, ViewGroup parent) {
+        PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
+                entry.notification.getUser().getIdentifier());
+
+        final StatusBarNotification sbn = entry.notification;
+        if (entry.row != null) {
+            entry.reset();
+            updateNotification(entry, pmUser, sbn, entry.row);
+        } else {
+            new RowInflaterTask().inflate(mContext, parent, entry,
+                    row -> {
+                        bindRow(entry, pmUser, sbn, row);
+                        updateNotification(entry, pmUser, sbn, row);
+                    });
+        }
+    }
+
+    private void bindRow(NotificationData.Entry entry, PackageManager pmUser,
+            StatusBarNotification sbn, ExpandableNotificationRow row) {
+        row.setExpansionLogger(this, entry.notification.getKey());
+        row.setGroupManager(mGroupManager);
+        row.setHeadsUpManager(mHeadsUpManager);
+        row.setOnExpandClickListener(mPresenter);
+        row.setInflationCallback(this);
+        row.setLongPressListener(getNotificationLongClicker());
+        mListContainer.bindRow(row);
+        mRemoteInputManager.bindRow(row);
+
+        // Get the app name.
+        // Note that Notification.Builder#bindHeaderAppName has similar logic
+        // but since this field is used in the guts, it must be accurate.
+        // Therefore we will only show the application label, or, failing that, the
+        // package name. No substitutions.
+        final String pkg = sbn.getPackageName();
+        String appname = pkg;
+        try {
+            final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES
+                            | PackageManager.MATCH_DISABLED_COMPONENTS);
+            if (info != null) {
+                appname = String.valueOf(pmUser.getApplicationLabel(info));
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            // Do nothing
+        }
+        row.setAppName(appname);
+        row.setOnDismissRunnable(() ->
+                performRemoveNotification(row.getStatusBarNotification()));
+        row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+        if (ENABLE_REMOTE_INPUT) {
+            row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+        }
+
+        row.setAppOpsOnClickListener(mOnAppOpsClickListener);
+
+        mCallback.onBindRow(entry, pmUser, sbn, row);
+    }
+
+    public void performRemoveNotification(StatusBarNotification n) {
+        final int rank = mNotificationData.getRank(n.getKey());
+        final int count = mNotificationData.getActiveNotifications().size();
+        final NotificationVisibility nv = NotificationVisibility.obtain(n.getKey(), rank, count,
+                true);
+        NotificationData.Entry entry = mNotificationData.get(n.getKey());
+
+        if (FORCE_REMOTE_INPUT_HISTORY
+                && mKeysKeptForRemoteInput.contains(n.getKey())) {
+            mKeysKeptForRemoteInput.remove(n.getKey());
+        }
+
+        mRemoteInputManager.onPerformRemoveNotification(n, entry);
+        final String pkg = n.getPackageName();
+        final String tag = n.getTag();
+        final int id = n.getId();
+        final int userId = n.getUserId();
+        try {
+            int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
+            if (isHeadsUp(n.getKey())) {
+                dismissalSurface = NotificationStats.DISMISSAL_PEEK;
+            } else if (mListContainer.hasPulsingNotifications()) {
+                dismissalSurface = NotificationStats.DISMISSAL_AOD;
+            }
+            int dismissalSentiment = NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
+            mBarService.onNotificationClear(pkg, tag, id, userId, n.getKey(), dismissalSurface,
+                    dismissalSentiment, nv);
+            removeNotification(n.getKey(), null);
+
+        } catch (RemoteException ex) {
+            // system process is dead if we're here.
+        }
+
+        mCallback.onPerformRemoveNotification(n);
+    }
+
+    /**
+     * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
+     * about the failure.
+     *
+     * WARNING: this will call back into us.  Don't hold any locks.
+     */
+    void handleNotificationError(StatusBarNotification n, String message) {
+        removeNotification(n.getKey(), null);
+        try {
+            mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
+                    n.getInitialPid(), message, n.getUserId());
+        } catch (RemoteException ex) {
+            // The end is nigh.
+        }
+    }
+
+    private void abortExistingInflation(String key) {
+        if (mPendingNotifications.containsKey(key)) {
+            NotificationData.Entry entry = mPendingNotifications.get(key);
+            entry.abortTask();
+            mPendingNotifications.remove(key);
+        }
+        NotificationData.Entry addedEntry = mNotificationData.get(key);
+        if (addedEntry != null) {
+            addedEntry.abortTask();
+        }
+    }
+
+    @Override
+    public void handleInflationException(StatusBarNotification notification, Exception e) {
+        handleNotificationError(notification, e.getMessage());
+    }
+
+    private void addEntry(NotificationData.Entry shadeEntry) {
+        boolean isHeadsUped = shouldPeek(shadeEntry);
+        if (isHeadsUped) {
+            mHeadsUpManager.showNotification(shadeEntry);
+            // Mark as seen immediately
+            setNotificationShown(shadeEntry.notification);
+        }
+        addNotificationViews(shadeEntry);
+        mCallback.onNotificationAdded(shadeEntry);
+    }
+
+    @Override
+    public void onAsyncInflationFinished(NotificationData.Entry entry) {
+        mPendingNotifications.remove(entry.key);
+        // If there was an async task started after the removal, we don't want to add it back to
+        // the list, otherwise we might get leaks.
+        boolean isNew = mNotificationData.get(entry.key) == null;
+        if (isNew && !entry.row.isRemoved()) {
+            addEntry(entry);
+        } else if (!isNew && entry.row.hasLowPriorityStateUpdated()) {
+            mVisualStabilityManager.onLowPriorityUpdated(entry);
+            mPresenter.updateNotificationViews();
+        }
+        entry.row.setLowPriorityStateUpdated(false);
+    }
+
+    @Override
+    public void removeNotification(String key, NotificationListenerService.RankingMap ranking) {
+        boolean deferRemoval = false;
+        abortExistingInflation(key);
+        if (mHeadsUpManager.contains(key)) {
+            // A cancel() in response to a remote input shouldn't be delayed, as it makes the
+            // sending look longer than it takes.
+            // Also we should not defer the removal if reordering isn't allowed since otherwise
+            // some notifications can't disappear before the panel is closed.
+            boolean ignoreEarliestRemovalTime = mRemoteInputManager.getController().isSpinning(key)
+                    && !FORCE_REMOTE_INPUT_HISTORY
+                    || !mVisualStabilityManager.isReorderingAllowed();
+            deferRemoval = !mHeadsUpManager.removeNotification(key,  ignoreEarliestRemovalTime);
+        }
+        mMediaManager.onNotificationRemoved(key);
+
+        NotificationData.Entry entry = mNotificationData.get(key);
+        if (FORCE_REMOTE_INPUT_HISTORY
+                && shouldKeepForRemoteInput(entry)
+                && entry.row != null && !entry.row.isDismissed()) {
+            CharSequence remoteInputText = entry.remoteInputText;
+            if (TextUtils.isEmpty(remoteInputText)) {
+                remoteInputText = entry.remoteInputTextWhenReset;
+            }
+            StatusBarNotification newSbn = rebuildNotificationWithRemoteInput(entry,
+                    remoteInputText, false /* showSpinner */);
+            boolean updated = false;
+            entry.onRemoteInputInserted();
+            try {
+                updateNotificationInternal(newSbn, null);
+                updated = true;
+            } catch (InflationException e) {
+                deferRemoval = false;
+            }
+            if (updated) {
+                Log.w(TAG, "Keeping notification around after sending remote input "+ entry.key);
+                addKeyKeptForRemoteInput(entry.key);
+                return;
+            }
+        }
+
+        if (FORCE_REMOTE_INPUT_HISTORY
+                && shouldKeepForSmartReply(entry)
+                && entry.row != null && !entry.row.isDismissed()) {
+            // Turn off the spinner and hide buttons when an app cancels the notification.
+            StatusBarNotification newSbn = rebuildNotificationForCanceledSmartReplies(entry);
+            boolean updated = false;
+            try {
+                updateNotificationInternal(newSbn, null);
+                updated = true;
+            } catch (InflationException e) {
+                // Ignore just don't keep the notification around.
+            }
+            // Treat the reply as longer sending.
+            mSmartReplyController.stopSending(entry);
+            if (updated) {
+                Log.w(TAG, "Keeping notification around after sending smart reply " + entry.key);
+                addKeyKeptForRemoteInput(entry.key);
+                return;
+            }
+        }
+
+        // Actually removing notification so smart reply controller can forget about it.
+        mSmartReplyController.stopSending(entry);
+
+        if (deferRemoval) {
+            mLatestRankingMap = ranking;
+            mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key));
+            return;
+        }
+
+        if (mRemoteInputManager.onRemoveNotification(entry)) {
+            mLatestRankingMap = ranking;
+            return;
+        }
+
+        if (entry != null && mGutsManager.getExposedGuts() != null
+                && mGutsManager.getExposedGuts() == entry.row.getGuts()
+                && entry.row.getGuts() != null && !entry.row.getGuts().isLeavebehind()) {
+            Log.w(TAG, "Keeping notification because it's showing guts. " + key);
+            mLatestRankingMap = ranking;
+            mGutsManager.setKeyToRemoveOnGutsClosed(key);
+            return;
+        }
+
+        if (entry != null) {
+            mForegroundServiceController.removeNotification(entry.notification);
+        }
+
+        if (entry != null && entry.row != null) {
+            entry.row.setRemoved();
+            mListContainer.cleanUpViewState(entry.row);
+        }
+        // Let's remove the children if this was a summary
+        handleGroupSummaryRemoved(key);
+        StatusBarNotification old = removeNotificationViews(key, ranking);
+
+        mCallback.onNotificationRemoved(key, old);
+    }
+
+    public StatusBarNotification rebuildNotificationWithRemoteInput(NotificationData.Entry entry,
+            CharSequence remoteInputText, boolean showSpinner) {
+        StatusBarNotification sbn = entry.notification;
+
+        Notification.Builder b = Notification.Builder
+                .recoverBuilder(mContext, sbn.getNotification().clone());
+        if (remoteInputText != null) {
+            CharSequence[] oldHistory = sbn.getNotification().extras
+                    .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+            CharSequence[] newHistory;
+            if (oldHistory == null) {
+                newHistory = new CharSequence[1];
+            } else {
+                newHistory = new CharSequence[oldHistory.length + 1];
+                System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length);
+            }
+            newHistory[0] = String.valueOf(remoteInputText);
+            b.setRemoteInputHistory(newHistory);
+        }
+        b.setShowRemoteInputSpinner(showSpinner);
+        b.setHideSmartReplies(true);
+
+        Notification newNotification = b.build();
+
+        // Undo any compatibility view inflation
+        newNotification.contentView = sbn.getNotification().contentView;
+        newNotification.bigContentView = sbn.getNotification().bigContentView;
+        newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
+
+        StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(),
+                sbn.getOpPkg(),
+                sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
+                newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
+        return newSbn;
+    }
+
+    @VisibleForTesting
+    StatusBarNotification rebuildNotificationForCanceledSmartReplies(
+            NotificationData.Entry entry) {
+        return rebuildNotificationWithRemoteInput(entry, null /* remoteInputTest */,
+                false /* showSpinner */);
+    }
+
+    private boolean shouldKeepForSmartReply(NotificationData.Entry entry) {
+        return entry != null && mSmartReplyController.isSendingSmartReply(entry.key);
+    }
+
+    private boolean shouldKeepForRemoteInput(NotificationData.Entry entry) {
+        if (entry == null) {
+            return false;
+        }
+        if (mRemoteInputManager.getController().isSpinning(entry.key)) {
+            return true;
+        }
+        if (entry.hasJustSentRemoteInput()) {
+            return true;
+        }
+        return false;
+    }
+
+    private StatusBarNotification removeNotificationViews(String key,
+            NotificationListenerService.RankingMap ranking) {
+        NotificationData.Entry entry = mNotificationData.remove(key, ranking);
+        if (entry == null) {
+            Log.w(TAG, "removeNotification for unknown key: " + key);
+            return null;
+        }
+        updateNotifications();
+        Dependency.get(LeakDetector.class).trackGarbage(entry);
+        return entry.notification;
+    }
+
+    /**
+     * Ensures that the group children are cancelled immediately when the group summary is cancelled
+     * instead of waiting for the notification manager to send all cancels. Otherwise this could
+     * lead to flickers.
+     *
+     * This also ensures that the animation looks nice and only consists of a single disappear
+     * animation instead of multiple.
+     *  @param key the key of the notification was removed
+     *
+     */
+    private void handleGroupSummaryRemoved(String key) {
+        NotificationData.Entry entry = mNotificationData.get(key);
+        if (entry != null && entry.row != null
+                && entry.row.isSummaryWithChildren()) {
+            if (entry.notification.getOverrideGroupKey() != null && !entry.row.isDismissed()) {
+                // We don't want to remove children for autobundled notifications as they are not
+                // always cancelled. We only remove them if they were dismissed by the user.
+                return;
+            }
+            List<ExpandableNotificationRow> notificationChildren =
+                    entry.row.getNotificationChildren();
+            for (int i = 0; i < notificationChildren.size(); i++) {
+                ExpandableNotificationRow row = notificationChildren.get(i);
+                NotificationData.Entry childEntry = row.getEntry();
+                boolean isForeground = (row.getStatusBarNotification().getNotification().flags
+                        & Notification.FLAG_FOREGROUND_SERVICE) != 0;
+                boolean keepForReply = FORCE_REMOTE_INPUT_HISTORY
+                        && (shouldKeepForRemoteInput(childEntry)
+                                || shouldKeepForSmartReply(childEntry));
+                if (isForeground || keepForReply) {
+                    // the child is a foreground service notification which we can't remove or it's
+                    // a child we're keeping around for reply!
+                    continue;
+                }
+                row.setKeepInParent(true);
+                // we need to set this state earlier as otherwise we might generate some weird
+                // animations
+                row.setRemoved();
+            }
+        }
+    }
+
+    public void updateNotificationsOnDensityOrFontScaleChanged() {
+        ArrayList<NotificationData.Entry> userNotifications =
+                mNotificationData.getNotificationsForCurrentUser();
+        for (int i = 0; i < userNotifications.size(); i++) {
+            NotificationData.Entry entry = userNotifications.get(i);
+            boolean exposedGuts = mGutsManager.getExposedGuts() != null
+                    && entry.row.getGuts() == mGutsManager.getExposedGuts();
+            entry.row.onDensityOrFontScaleChanged();
+            if (exposedGuts) {
+                mGutsManager.onDensityOrFontScaleChanged(entry.row);
+            }
+        }
+    }
+
+    protected void updateNotification(NotificationData.Entry entry, PackageManager pmUser,
+            StatusBarNotification sbn, ExpandableNotificationRow row) {
+        row.setNeedsRedaction(mLockscreenUserManager.needsRedaction(entry));
+        boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
+        boolean isUpdate = mNotificationData.get(entry.key) != null;
+        boolean wasLowPriority = row.isLowPriority();
+        row.setIsLowPriority(isLowPriority);
+        row.setLowPriorityStateUpdated(isUpdate && (wasLowPriority != isLowPriority));
+        // bind the click event to the content area
+        mNotificationClicker.register(row, sbn);
+
+        // Extract target SDK version.
+        try {
+            ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
+            entry.targetSdk = info.targetSdkVersion;
+        } catch (PackageManager.NameNotFoundException ex) {
+            Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
+        }
+        row.setLegacy(entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
+                && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
+        entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
+        entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
+
+        entry.row = row;
+        entry.row.setOnActivatedListener(mPresenter);
+
+        boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(sbn,
+                mNotificationData.getImportance(sbn.getKey()));
+        boolean useIncreasedHeadsUp = useIncreasedCollapsedHeight
+                && !mPresenter.isPresenterFullyCollapsed();
+        row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
+        row.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
+        row.setSmartActions(entry.smartActions);
+        row.updateNotification(entry);
+    }
+
+    protected void addNotificationViews(NotificationData.Entry entry) {
+        if (entry == null) {
+            return;
+        }
+        // Add the expanded view and icon.
+        mNotificationData.add(entry);
+        tagForeground(entry.notification);
+        updateNotifications();
+    }
+
+    protected NotificationData.Entry createNotificationViews(
+            StatusBarNotification sbn, NotificationListenerService.Ranking ranking)
+            throws InflationException {
+        if (DEBUG) {
+            Log.d(TAG, "createNotificationViews(notification=" + sbn + " " + ranking);
+        }
+        NotificationData.Entry entry = new NotificationData.Entry(sbn, ranking);
+        Dependency.get(LeakDetector.class).trackInstance(entry);
+        entry.createIcons(mContext, sbn);
+        // Construct the expanded view.
+        inflateViews(entry, mListContainer.getViewParentForNotification(entry));
+        return entry;
+    }
+
+    private void addNotificationInternal(StatusBarNotification notification,
+            NotificationListenerService.RankingMap rankingMap) throws InflationException {
+        String key = notification.getKey();
+        if (DEBUG) Log.d(TAG, "addNotification key=" + key);
+
+        mNotificationData.updateRanking(rankingMap);
+        NotificationListenerService.Ranking ranking = new NotificationListenerService.Ranking();
+        rankingMap.getRanking(key, ranking);
+        NotificationData.Entry shadeEntry = createNotificationViews(notification, ranking);
+        boolean isHeadsUped = shouldPeek(shadeEntry);
+        if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
+            if (shouldSuppressFullScreenIntent(shadeEntry)) {
+                if (DEBUG) {
+                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + key);
+                }
+            } else if (mNotificationData.getImportance(key)
+                    < NotificationManager.IMPORTANCE_HIGH) {
+                if (DEBUG) {
+                    Log.d(TAG, "No Fullscreen intent: not important enough: "
+                            + key);
+                }
+            } else {
+                // Stop screensaver if the notification has a fullscreen intent.
+                // (like an incoming phone call)
+                SystemServicesProxy.getInstance(mContext).awakenDreamsAsync();
+
+                // not immersive & a fullscreen alert should be shown
+                if (DEBUG)
+                    Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
+                try {
+                    EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
+                            key);
+                    notification.getNotification().fullScreenIntent.send();
+                    shadeEntry.notifyFullScreenIntentLaunched();
+                    mMetricsLogger.count("note_fullscreen", 1);
+                } catch (PendingIntent.CanceledException e) {
+                }
+            }
+        }
+        abortExistingInflation(key);
+
+        mForegroundServiceController.addNotification(notification,
+                mNotificationData.getImportance(key));
+
+        mPendingNotifications.put(key, shadeEntry);
+        mGroupManager.onPendingEntryAdded(shadeEntry);
+    }
+
+    @VisibleForTesting
+    protected void tagForeground(StatusBarNotification notification) {
+        ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
+                notification.getUserId(), notification.getPackageName());
+        if (activeOps != null) {
+            int N = activeOps.size();
+            for (int i = 0; i < N; i++) {
+                updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
+                        notification.getPackageName(), true);
+            }
+        }
+    }
+
+    @Override
+    public void addNotification(StatusBarNotification notification,
+            NotificationListenerService.RankingMap ranking) {
+        try {
+            addNotificationInternal(notification, ranking);
+        } catch (InflationException e) {
+            handleInflationException(notification, e);
+        }
+    }
+
+    public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
+        String foregroundKey = mForegroundServiceController.getStandardLayoutKey(
+                UserHandle.getUserId(uid), pkg);
+        if (foregroundKey != null) {
+            mNotificationData.updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
+            updateNotifications();
+        }
+    }
+
+    private boolean alertAgain(NotificationData.Entry oldEntry, Notification newNotification) {
+        return oldEntry == null || !oldEntry.hasInterrupted()
+                || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
+    }
+
+    private void updateNotificationInternal(StatusBarNotification notification,
+            NotificationListenerService.RankingMap ranking) throws InflationException {
+        if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
+
+        final String key = notification.getKey();
+        abortExistingInflation(key);
+        NotificationData.Entry entry = mNotificationData.get(key);
+        if (entry == null) {
+            return;
+        }
+        mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
+        mRemoteInputManager.onUpdateNotification(entry);
+        mSmartReplyController.stopSending(entry);
+
+        if (key.equals(mGutsManager.getKeyToRemoveOnGutsClosed())) {
+            mGutsManager.setKeyToRemoveOnGutsClosed(null);
+            Log.w(TAG, "Notification that was kept for guts was updated. " + key);
+        }
+
+        Notification n = notification.getNotification();
+        mNotificationData.updateRanking(ranking);
+
+        final StatusBarNotification oldNotification = entry.notification;
+        entry.notification = notification;
+        mGroupManager.onEntryUpdated(entry, oldNotification);
+
+        entry.updateIcons(mContext, notification);
+        inflateViews(entry, mListContainer.getViewParentForNotification(entry));
+
+        mForegroundServiceController.updateNotification(notification,
+                mNotificationData.getImportance(key));
+
+        boolean shouldPeek = shouldPeek(entry, notification);
+        boolean alertAgain = alertAgain(entry, n);
+
+        updateHeadsUp(key, entry, shouldPeek, alertAgain);
+        updateNotifications();
+
+        if (!notification.isClearable()) {
+            // The user may have performed a dismiss action on the notification, since it's
+            // not clearable we should snap it back.
+            mListContainer.snapViewIfNeeded(entry.row);
+        }
+
+        if (DEBUG) {
+            // Is this for you?
+            boolean isForCurrentUser = mPresenter.isNotificationForCurrentProfiles(notification);
+            Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
+        }
+
+        mCallback.onNotificationUpdated(notification);
+    }
+
+    @Override
+    public void updateNotification(StatusBarNotification notification,
+            NotificationListenerService.RankingMap ranking) {
+        try {
+            updateNotificationInternal(notification, ranking);
+        } catch (InflationException e) {
+            handleInflationException(notification, e);
+        }
+    }
+
+    public void updateNotifications() {
+        mNotificationData.filterAndSort();
+
+        mPresenter.updateNotificationViews();
+    }
+
+    public void updateNotificationRanking(NotificationListenerService.RankingMap rankingMap) {
+        List<NotificationData.Entry> entries = new ArrayList<>();
+        entries.addAll(mNotificationData.getActiveNotifications());
+        entries.addAll(mPendingNotifications.values());
+
+        // Has a copy of the current UI adjustments.
+        ArrayMap<String, NotificationUiAdjustment> oldAdjustments = new ArrayMap<>();
+        for (NotificationData.Entry entry : entries) {
+            NotificationUiAdjustment adjustment =
+                    NotificationUiAdjustment.extractFromNotificationEntry(entry);
+            oldAdjustments.put(entry.key, adjustment);
+        }
+
+        // Populate notification entries from the new rankings.
+        mNotificationData.updateRanking(rankingMap);
+        updateRankingOfPendingNotifications(rankingMap);
+
+        // By comparing the old and new UI adjustments, reinflate the view accordingly.
+        for (NotificationData.Entry entry : entries) {
+            NotificationUiAdjustment newAdjustment =
+                    NotificationUiAdjustment.extractFromNotificationEntry(entry);
+
+            if (NotificationUiAdjustment.needReinflate(
+                    oldAdjustments.get(entry.key), newAdjustment)) {
+                if (entry.row != null) {
+                    entry.reset();
+                    PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
+                            entry.notification.getUser().getIdentifier());
+                    updateNotification(entry, pmUser, entry.notification, entry.row);
+                } else {
+                    // Once the RowInflaterTask is done, it will pick up the updated entry, so
+                    // no-op here.
+                }
+            }
+        }
+
+        updateNotifications();
+    }
+
+    private void updateRankingOfPendingNotifications(
+            @Nullable NotificationListenerService.RankingMap rankingMap) {
+        if (rankingMap == null) {
+            return;
+        }
+        NotificationListenerService.Ranking tmpRanking = new NotificationListenerService.Ranking();
+        for (NotificationData.Entry pendingNotification : mPendingNotifications.values()) {
+            rankingMap.getRanking(pendingNotification.key, tmpRanking);
+            pendingNotification.populateFromRanking(tmpRanking);
+        }
+    }
+
+    protected boolean shouldPeek(NotificationData.Entry entry) {
+        return shouldPeek(entry, entry.notification);
+    }
+
+    public boolean shouldPeek(NotificationData.Entry entry, StatusBarNotification sbn) {
+        if (!mUseHeadsUp || mPresenter.isDeviceInVrMode()) {
+            if (DEBUG) Log.d(TAG, "No peeking: no huns or vr mode");
+            return false;
+        }
+
+        if (mNotificationData.shouldFilterOut(entry)) {
+            if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
+            return false;
+        }
+
+        boolean inUse = mPowerManager.isScreenOn() && !mSystemServicesProxy.isDreaming();
+
+        if (!inUse && !mPresenter.isDozing()) {
+            if (DEBUG) {
+                Log.d(TAG, "No peeking: not in use: " + sbn.getKey());
+            }
+            return false;
+        }
+
+        if (!mPresenter.isDozing() && mNotificationData.shouldSuppressPeek(entry)) {
+            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
+            return false;
+        }
+
+        // Peeking triggers an ambient display pulse, so disable peek is ambient is active
+        if (mPresenter.isDozing() && mNotificationData.shouldSuppressAmbient(entry)) {
+            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
+            return false;
+        }
+
+        if (entry.hasJustLaunchedFullScreenIntent()) {
+            if (DEBUG) Log.d(TAG, "No peeking: recent fullscreen: " + sbn.getKey());
+            return false;
+        }
+
+        if (isSnoozedPackage(sbn)) {
+            if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
+            return false;
+        }
+
+        // Allow peeking for DEFAULT notifications only if we're on Ambient Display.
+        int importanceLevel = mPresenter.isDozing() ? NotificationManager.IMPORTANCE_DEFAULT
+                : NotificationManager.IMPORTANCE_HIGH;
+        if (mNotificationData.getImportance(sbn.getKey()) < importanceLevel) {
+            if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
+            return false;
+        }
+
+        // Don't peek notifications that are suppressed due to group alert behavior
+        if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) {
+            if (DEBUG) Log.d(TAG, "No peeking: suppressed due to group alert behavior");
+            return false;
+        }
+
+        if (!mCallback.shouldPeek(entry, sbn)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    protected void setNotificationShown(StatusBarNotification n) {
+        setNotificationsShown(new String[]{n.getKey()});
+    }
+
+    protected void setNotificationsShown(String[] keys) {
+        try {
+            mNotificationListener.setNotificationsShown(keys);
+        } catch (RuntimeException e) {
+            Log.d(TAG, "failed setNotificationsShown: ", e);
+        }
+    }
+
+    protected boolean isSnoozedPackage(StatusBarNotification sbn) {
+        return mHeadsUpManager.isSnoozed(sbn.getPackageName());
+    }
+
+    protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldPeek,
+            boolean alertAgain) {
+        final boolean wasHeadsUp = isHeadsUp(key);
+        if (wasHeadsUp) {
+            if (!shouldPeek) {
+                // We don't want this to be interrupting anymore, lets remove it
+                mHeadsUpManager.removeNotification(key, false /* ignoreEarliestRemovalTime */);
+            } else {
+                mHeadsUpManager.updateNotification(entry.key, alertAgain);
+            }
+        } else if (shouldPeek && alertAgain) {
+            // This notification was updated to be a heads-up, show it!
+            mHeadsUpManager.showNotification(entry);
+        }
+    }
+
+    protected boolean isHeadsUp(String key) {
+        return mHeadsUpManager.contains(key);
+    }
+
+    public boolean isNotificationKeptForRemoteInput(String key) {
+        return mKeysKeptForRemoteInput.contains(key);
+    }
+
+    public void removeKeyKeptForRemoteInput(String key) {
+        mKeysKeptForRemoteInput.remove(key);
+    }
+
+    public void addKeyKeptForRemoteInput(String key) {
+        if (FORCE_REMOTE_INPUT_HISTORY) {
+            mKeysKeptForRemoteInput.add(key);
+        }
+    }
+
+    /**
+     * Callback for NotificationEntryManager.
+     */
+    public interface Callback {
+
+        /**
+         * Called when a new entry is created.
+         *
+         * @param shadeEntry entry that was created
+         */
+        void onNotificationAdded(NotificationData.Entry shadeEntry);
+
+        /**
+         * Called when a notification was updated.
+         *
+         * @param notification notification that was updated
+         */
+        void onNotificationUpdated(StatusBarNotification notification);
+
+        /**
+         * Called when a notification was removed.
+         *
+         * @param key key of notification that was removed
+         * @param old StatusBarNotification of the notification before it was removed
+         */
+        void onNotificationRemoved(String key, StatusBarNotification old);
+
+
+        /**
+         * Called when a notification is clicked.
+         *
+         * @param sbn notification that was clicked
+         * @param row row for that notification
+         */
+        void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row);
+
+        /**
+         * Called when a new notification and row is created.
+         *
+         * @param entry entry for the notification
+         * @param pmUser package manager for user
+         * @param sbn notification
+         * @param row row for the notification
+         */
+        void onBindRow(NotificationData.Entry entry, PackageManager pmUser,
+                StatusBarNotification sbn, ExpandableNotificationRow row);
+
+        /**
+         * Removes a notification immediately.
+         *
+         * @param statusBarNotification notification that is being removed
+         */
+        void onPerformRemoveNotification(StatusBarNotification statusBarNotification);
+
+        /**
+         * Returns true if NotificationEntryManager should peek this notification.
+         *
+         * @param entry entry of the notification that might be peeked
+         * @param sbn notification that might be peeked
+         * @return true if the notification should be peeked
+         */
+        boolean shouldPeek(NotificationData.Entry entry, StatusBarNotification sbn);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
deleted file mode 100644
index ade27f9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ /dev/null
@@ -1,250 +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.systemui.statusbar.notification;
-
-import static com.android.systemui.statusbar.ExpandableNotificationRow
-        .DEFAULT_HEADER_VISIBLE_AMOUNT;
-import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
-
-import android.app.Notification;
-import android.content.Context;
-import android.util.ArraySet;
-import android.view.NotificationHeaderView;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.internal.widget.NotificationExpandButton;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.ViewTransformationHelper;
-
-import java.util.Stack;
-
-/**
- * Wraps a notification header view.
- */
-public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
-
-    private static final Interpolator LOW_PRIORITY_HEADER_CLOSE
-            = new PathInterpolator(0.4f, 0f, 0.7f, 1f);
-
-    protected final ViewTransformationHelper mTransformationHelper;
-    private final int mTranslationForHeader;
-
-    protected int mColor;
-    private ImageView mIcon;
-
-    private NotificationExpandButton mExpandButton;
-    private NotificationHeaderView mNotificationHeader;
-    private TextView mHeaderText;
-    private ImageView mWorkProfileImage;
-    private boolean mIsLowPriority;
-    private boolean mTransformLowPriorityTitle;
-    private boolean mShowExpandButtonAtEnd;
-    protected float mHeaderTranslation;
-
-    protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
-        super(ctx, view, row);
-        mShowExpandButtonAtEnd = ctx.getResources().getBoolean(
-                R.bool.config_showNotificationExpandButtonAtEnd);
-        mTransformationHelper = new ViewTransformationHelper();
-
-        // we want to avoid that the header clashes with the other text when transforming
-        // low-priority
-        mTransformationHelper.setCustomTransformation(
-                new CustomInterpolatorTransformation(TRANSFORMING_VIEW_TITLE) {
-
-                    @Override
-                    public Interpolator getCustomInterpolator(int interpolationType,
-                            boolean isFrom) {
-                        boolean isLowPriority = mView instanceof NotificationHeaderView;
-                        if (interpolationType == TRANSFORM_Y) {
-                            if (isLowPriority && !isFrom
-                                    || !isLowPriority && isFrom) {
-                                return Interpolators.LINEAR_OUT_SLOW_IN;
-                            } else {
-                                return LOW_PRIORITY_HEADER_CLOSE;
-                            }
-                        }
-                        return null;
-                    }
-
-                    @Override
-                    protected boolean hasCustomTransformation() {
-                        return mIsLowPriority && mTransformLowPriorityTitle;
-                    }
-                }, TRANSFORMING_VIEW_TITLE);
-        resolveHeaderViews();
-        addAppOpsOnClickListener(row);
-        mTranslationForHeader = ctx.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.notification_content_margin)
-                - ctx.getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.notification_content_margin_top);
-    }
-
-    protected void resolveHeaderViews() {
-        mIcon = mView.findViewById(com.android.internal.R.id.icon);
-        mHeaderText = mView.findViewById(com.android.internal.R.id.header_text);
-        mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
-        mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
-        mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
-        mNotificationHeader.setShowExpandButtonAtEnd(mShowExpandButtonAtEnd);
-        mColor = mNotificationHeader.getOriginalIconColor();
-    }
-
-    private void addAppOpsOnClickListener(ExpandableNotificationRow row) {
-        mNotificationHeader.setAppOpsOnClickListener(row.getAppOpsOnClickListener());
-    }
-
-    @Override
-    public void onContentUpdated(ExpandableNotificationRow row) {
-        super.onContentUpdated(row);
-        mIsLowPriority = row.isLowPriority();
-        mTransformLowPriorityTitle = !row.isChildInGroup() && !row.isSummaryWithChildren();
-        ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews();
-
-        // Reinspect the notification.
-        resolveHeaderViews();
-        if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) {
-            setHeaderVisibleAmount(row.getHeaderVisibleAmount());
-        }
-        updateTransformedTypes();
-        addRemainingTransformTypes();
-        updateCropToPaddingForImageViews();
-        Notification notification = row.getStatusBarNotification().getNotification();
-        mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
-        // The work profile image is always the same lets just set the icon tag for it not to
-        // animate
-        mWorkProfileImage.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
-
-        // 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.
-        ArraySet<View> currentViews = mTransformationHelper.getAllTransformingViews();
-        for (int i = 0; i < previousViews.size(); i++) {
-            View view = previousViews.valueAt(i);
-            if (!currentViews.contains(view)) {
-                mTransformationHelper.resetTransformedView(view);
-            }
-        }
-    }
-
-    /**
-     * Adds the remaining TransformTypes to the TransformHelper. This is done to make sure that each
-     * child is faded automatically and doesn't have to be manually added.
-     * The keys used for the views are the ids.
-     */
-    private void addRemainingTransformTypes() {
-        mTransformationHelper.addRemainingTransformTypes(mView);
-    }
-
-    /**
-     * Since we are deactivating the clipping when transforming the ImageViews don't get clipped
-     * anymore during these transitions. We can avoid that by using
-     * {@link ImageView#setCropToPadding(boolean)} on all ImageViews.
-     */
-    private void updateCropToPaddingForImageViews() {
-        Stack<View> stack = new Stack<>();
-        stack.push(mView);
-        while (!stack.isEmpty()) {
-            View child = stack.pop();
-            if (child instanceof ImageView) {
-                ((ImageView) child).setCropToPadding(true);
-            } else if (child instanceof ViewGroup){
-                ViewGroup group = (ViewGroup) child;
-                for (int i = 0; i < group.getChildCount(); i++) {
-                    stack.push(group.getChildAt(i));
-                }
-            }
-        }
-    }
-
-    protected void updateTransformedTypes() {
-        mTransformationHelper.reset();
-        mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_ICON, mIcon);
-        if (mIsLowPriority) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
-                    mHeaderText);
-        }
-    }
-
-    @Override
-    public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {
-        mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE);
-        mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
-    }
-
-    @Override
-    public void setHeaderVisibleAmount(float headerVisibleAmount) {
-        super.setHeaderVisibleAmount(headerVisibleAmount);
-        mNotificationHeader.setAlpha(headerVisibleAmount);
-        mHeaderTranslation = (1.0f - headerVisibleAmount) * mTranslationForHeader;
-        mView.setTranslationY(mHeaderTranslation);
-    }
-
-    @Override
-    public int getHeaderTranslation() {
-        return (int) mHeaderTranslation;
-    }
-
-    @Override
-    public NotificationHeaderView getNotificationHeader() {
-        return mNotificationHeader;
-    }
-
-    @Override
-    public TransformState getCurrentState(int fadingView) {
-        return mTransformationHelper.getCurrentState(fadingView);
-    }
-
-    @Override
-    public void transformTo(TransformableView notification, Runnable endRunnable) {
-        mTransformationHelper.transformTo(notification, endRunnable);
-    }
-
-    @Override
-    public void transformTo(TransformableView notification, float transformationAmount) {
-        mTransformationHelper.transformTo(notification, transformationAmount);
-    }
-
-    @Override
-    public void transformFrom(TransformableView notification) {
-        mTransformationHelper.transformFrom(notification);
-    }
-
-    @Override
-    public void transformFrom(TransformableView notification, float transformationAmount) {
-        mTransformationHelper.transformFrom(notification, transformationAmount);
-    }
-
-    @Override
-    public void setIsChildInGroup(boolean isChildInGroup) {
-        super.setIsChildInGroup(isChildInGroup);
-        mTransformLowPriorityTitle = !isChildInGroup;
-    }
-
-    @Override
-    public void setVisible(boolean visible) {
-        super.setVisible(visible);
-        mTransformationHelper.setVisible(visible);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
deleted file mode 100644
index 1303057..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import android.annotation.Nullable;
-import android.app.Notification;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.CancellationSignal;
-import android.service.notification.StatusBarNotification;
-import android.util.Log;
-import android.view.View;
-import android.widget.RemoteViews;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.InflationTask;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationContentView;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.util.Assert;
-
-import java.util.HashMap;
-import java.util.concurrent.Executor;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * A utility that inflates the right kind of contentView based on the state
- */
-public class NotificationInflater {
-
-    public static final String TAG = "NotificationInflater";
-    @VisibleForTesting
-    static final int FLAG_REINFLATE_ALL = ~0;
-    private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0;
-    @VisibleForTesting
-    static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1;
-    private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2;
-    private static final int FLAG_REINFLATE_PUBLIC_VIEW = 1<<3;
-    private static final int FLAG_REINFLATE_AMBIENT_VIEW = 1<<4;
-    private static final InflationExecutor EXECUTOR = new InflationExecutor();
-
-    private final ExpandableNotificationRow mRow;
-    private boolean mIsLowPriority;
-    private boolean mUsesIncreasedHeight;
-    private boolean mUsesIncreasedHeadsUpHeight;
-    private RemoteViews.OnClickHandler mRemoteViewClickHandler;
-    private boolean mIsChildInGroup;
-    private InflationCallback mCallback;
-    private boolean mRedactAmbient;
-
-    public NotificationInflater(ExpandableNotificationRow row) {
-        mRow = row;
-    }
-
-    public void setIsLowPriority(boolean isLowPriority) {
-        mIsLowPriority = isLowPriority;
-    }
-
-    /**
-     * Set whether the notification is a child in a group
-     *
-     * @return whether the view was re-inflated
-     */
-    public void setIsChildInGroup(boolean childInGroup) {
-        if (childInGroup != mIsChildInGroup) {
-            mIsChildInGroup = childInGroup;
-            if (mIsLowPriority) {
-                int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW;
-                inflateNotificationViews(flags);
-            }
-        } ;
-    }
-
-    public void setUsesIncreasedHeight(boolean usesIncreasedHeight) {
-        mUsesIncreasedHeight = usesIncreasedHeight;
-    }
-
-    public void setUsesIncreasedHeadsUpHeight(boolean usesIncreasedHeight) {
-        mUsesIncreasedHeadsUpHeight = usesIncreasedHeight;
-    }
-
-    public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
-        mRemoteViewClickHandler = remoteViewClickHandler;
-    }
-
-    public void setRedactAmbient(boolean redactAmbient) {
-        if (mRedactAmbient != redactAmbient) {
-            mRedactAmbient = redactAmbient;
-            if (mRow.getEntry() == null) {
-                return;
-            }
-            inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW);
-        }
-    }
-
-    /**
-     * Inflate all views of this notification on a background thread. This is asynchronous and will
-     * notify the callback once it's finished.
-     */
-    public void inflateNotificationViews() {
-        inflateNotificationViews(FLAG_REINFLATE_ALL);
-    }
-
-    /**
-     * Reinflate all views for the specified flags on a background thread. This is asynchronous and
-     * will notify the callback once it's finished.
-     *
-     * @param reInflateFlags flags which views should be reinflated. Use {@link #FLAG_REINFLATE_ALL}
-     *                       to reinflate all of views.
-     */
-    @VisibleForTesting
-    void inflateNotificationViews(int reInflateFlags) {
-        if (mRow.isRemoved()) {
-            // We don't want to reinflate anything for removed notifications. Otherwise views might
-            // be readded to the stack, leading to leaks. This may happen with low-priority groups
-            // where the removal of already removed children can lead to a reinflation.
-            return;
-        }
-        StatusBarNotification sbn = mRow.getEntry().notification;
-        AsyncInflationTask task = new AsyncInflationTask(sbn, reInflateFlags, mRow,
-                mIsLowPriority,
-                mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
-                mCallback, mRemoteViewClickHandler);
-        if (mCallback != null && mCallback.doInflateSynchronous()) {
-            task.onPostExecute(task.doInBackground());
-        } else {
-            task.execute();
-        }
-    }
-
-    @VisibleForTesting
-    InflationProgress inflateNotificationViews(int reInflateFlags,
-            Notification.Builder builder, Context packageContext) {
-        InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority,
-                mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight,
-                mRedactAmbient, packageContext);
-        apply(result, reInflateFlags, mRow, mRedactAmbient, mRemoteViewClickHandler, null);
-        return result;
-    }
-
-    private static InflationProgress createRemoteViews(int reInflateFlags,
-            Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup,
-            boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
-            Context packageContext) {
-        InflationProgress result = new InflationProgress();
-        isLowPriority = isLowPriority && !isChildInGroup;
-        if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
-            result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight);
-        }
-
-        if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
-            result.newExpandedView = createExpandedView(builder, isLowPriority);
-        }
-
-        if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
-            result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight);
-        }
-
-        if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
-            result.newPublicView = builder.makePublicContentView();
-        }
-
-        if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
-            result.newAmbientView = redactAmbient ? builder.makePublicAmbientNotification()
-                    : builder.makeAmbientNotification();
-        }
-        result.packageContext = packageContext;
-        result.headsUpStatusBarText = builder.getHeadsUpStatusBarText(false /* showingPublic */);
-        result.headsUpStatusBarTextPublic = builder.getHeadsUpStatusBarText(
-                true /* showingPublic */);
-        return result;
-    }
-
-    public static CancellationSignal apply(InflationProgress result, int reInflateFlags,
-            ExpandableNotificationRow row, boolean redactAmbient,
-            RemoteViews.OnClickHandler remoteViewClickHandler,
-            @Nullable InflationCallback callback) {
-        NotificationData.Entry entry = row.getEntry();
-        NotificationContentView privateLayout = row.getPrivateLayout();
-        NotificationContentView publicLayout = row.getPublicLayout();
-        final HashMap<Integer, CancellationSignal> runningInflations = new HashMap<>();
-
-        int flag = FLAG_REINFLATE_CONTENT_VIEW;
-        if ((reInflateFlags & flag) != 0) {
-            boolean isNewView = !canReapplyRemoteView(result.newContentView, entry.cachedContentView);
-            ApplyCallback applyCallback = new ApplyCallback() {
-                @Override
-                public void setResultView(View v) {
-                    result.inflatedContentView = v;
-                }
-
-                @Override
-                public RemoteViews getRemoteView() {
-                    return result.newContentView;
-                }
-            };
-            applyRemoteView(result, reInflateFlags, flag, row, redactAmbient,
-                    isNewView, remoteViewClickHandler, callback, entry, privateLayout,
-                    privateLayout.getContractedChild(), privateLayout.getVisibleWrapper(
-                            NotificationContentView.VISIBLE_TYPE_CONTRACTED),
-                    runningInflations, applyCallback);
-        }
-
-        flag = FLAG_REINFLATE_EXPANDED_VIEW;
-        if ((reInflateFlags & flag) != 0) {
-            if (result.newExpandedView != null) {
-                boolean isNewView = !canReapplyRemoteView(result.newExpandedView,
-                        entry.cachedBigContentView);
-                ApplyCallback applyCallback = new ApplyCallback() {
-                    @Override
-                    public void setResultView(View v) {
-                        result.inflatedExpandedView = v;
-                    }
-
-                    @Override
-                    public RemoteViews getRemoteView() {
-                        return result.newExpandedView;
-                    }
-                };
-                applyRemoteView(result, reInflateFlags, flag, row,
-                        redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
-                        privateLayout, privateLayout.getExpandedChild(),
-                        privateLayout.getVisibleWrapper(
-                                NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations,
-                        applyCallback);
-            }
-        }
-
-        flag = FLAG_REINFLATE_HEADS_UP_VIEW;
-        if ((reInflateFlags & flag) != 0) {
-            if (result.newHeadsUpView != null) {
-                boolean isNewView = !canReapplyRemoteView(result.newHeadsUpView,
-                        entry.cachedHeadsUpContentView);
-                ApplyCallback applyCallback = new ApplyCallback() {
-                    @Override
-                    public void setResultView(View v) {
-                        result.inflatedHeadsUpView = v;
-                    }
-
-                    @Override
-                    public RemoteViews getRemoteView() {
-                        return result.newHeadsUpView;
-                    }
-                };
-                applyRemoteView(result, reInflateFlags, flag, row,
-                        redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
-                        privateLayout, privateLayout.getHeadsUpChild(),
-                        privateLayout.getVisibleWrapper(
-                                NotificationContentView.VISIBLE_TYPE_HEADSUP), runningInflations,
-                        applyCallback);
-            }
-        }
-
-        flag = FLAG_REINFLATE_PUBLIC_VIEW;
-        if ((reInflateFlags & flag) != 0) {
-            boolean isNewView = !canReapplyRemoteView(result.newPublicView,
-                    entry.cachedPublicContentView);
-            ApplyCallback applyCallback = new ApplyCallback() {
-                @Override
-                public void setResultView(View v) {
-                    result.inflatedPublicView = v;
-                }
-
-                @Override
-                public RemoteViews getRemoteView() {
-                    return result.newPublicView;
-                }
-            };
-            applyRemoteView(result, reInflateFlags, flag, row,
-                    redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
-                    publicLayout, publicLayout.getContractedChild(),
-                    publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED),
-                    runningInflations, applyCallback);
-        }
-
-        flag = FLAG_REINFLATE_AMBIENT_VIEW;
-        if ((reInflateFlags & flag) != 0) {
-            NotificationContentView newParent = redactAmbient ? publicLayout : privateLayout;
-            boolean isNewView = !canReapplyAmbient(row, redactAmbient) ||
-                    !canReapplyRemoteView(result.newAmbientView, entry.cachedAmbientContentView);
-            ApplyCallback applyCallback = new ApplyCallback() {
-                @Override
-                public void setResultView(View v) {
-                    result.inflatedAmbientView = v;
-                }
-
-                @Override
-                public RemoteViews getRemoteView() {
-                    return result.newAmbientView;
-                }
-            };
-            applyRemoteView(result, reInflateFlags, flag, row,
-                    redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
-                    newParent, newParent.getAmbientChild(), newParent.getVisibleWrapper(
-                            NotificationContentView.VISIBLE_TYPE_AMBIENT), runningInflations,
-                    applyCallback);
-        }
-
-        // Let's try to finish, maybe nobody is even inflating anything
-        finishIfDone(result, reInflateFlags, runningInflations, callback, row,
-                redactAmbient);
-        CancellationSignal cancellationSignal = new CancellationSignal();
-        cancellationSignal.setOnCancelListener(
-                () -> runningInflations.values().forEach(CancellationSignal::cancel));
-        return cancellationSignal;
-    }
-
-    @VisibleForTesting
-    static void applyRemoteView(final InflationProgress result,
-            final int reInflateFlags, int inflationId,
-            final ExpandableNotificationRow row,
-            final boolean redactAmbient, boolean isNewView,
-            RemoteViews.OnClickHandler remoteViewClickHandler,
-            @Nullable final InflationCallback callback, NotificationData.Entry entry,
-            NotificationContentView parentLayout, View existingView,
-            NotificationViewWrapper existingWrapper,
-            final HashMap<Integer, CancellationSignal> runningInflations,
-            ApplyCallback applyCallback) {
-        RemoteViews newContentView = applyCallback.getRemoteView();
-        if (callback != null && callback.doInflateSynchronous()) {
-            try {
-                if (isNewView) {
-                    View v = newContentView.apply(
-                            result.packageContext,
-                            parentLayout,
-                            remoteViewClickHandler);
-                    v.setIsRootNamespace(true);
-                    applyCallback.setResultView(v);
-                } else {
-                    newContentView.reapply(
-                            result.packageContext,
-                            existingView,
-                            remoteViewClickHandler);
-                    existingWrapper.onReinflated();
-                }
-            } catch (Exception e) {
-                handleInflationError(runningInflations, e, entry.notification, callback);
-                // Add a running inflation to make sure we don't trigger callbacks.
-                // Safe to do because only happens in tests.
-                runningInflations.put(inflationId, new CancellationSignal());
-            }
-            return;
-        }
-        RemoteViews.OnViewAppliedListener listener
-                = new RemoteViews.OnViewAppliedListener() {
-
-            @Override
-            public void onViewApplied(View v) {
-                if (isNewView) {
-                    v.setIsRootNamespace(true);
-                    applyCallback.setResultView(v);
-                } else if (existingWrapper != null) {
-                    existingWrapper.onReinflated();
-                }
-                runningInflations.remove(inflationId);
-                finishIfDone(result, reInflateFlags, runningInflations, callback, row,
-                        redactAmbient);
-            }
-
-            @Override
-            public void onError(Exception e) {
-                // Uh oh the async inflation failed. Due to some bugs (see b/38190555), this could
-                // actually also be a system issue, so let's try on the UI thread again to be safe.
-                try {
-                    View newView = existingView;
-                    if (isNewView) {
-                        newView = newContentView.apply(
-                                result.packageContext,
-                                parentLayout,
-                                remoteViewClickHandler);
-                    } else {
-                        newContentView.reapply(
-                                result.packageContext,
-                                existingView,
-                                remoteViewClickHandler);
-                    }
-                    Log.wtf(TAG, "Async Inflation failed but normal inflation finished normally.",
-                            e);
-                    onViewApplied(newView);
-                } catch (Exception anotherException) {
-                    runningInflations.remove(inflationId);
-                    handleInflationError(runningInflations, e, entry.notification, callback);
-                }
-            }
-        };
-        CancellationSignal cancellationSignal;
-        if (isNewView) {
-            cancellationSignal = newContentView.applyAsync(
-                    result.packageContext,
-                    parentLayout,
-                    EXECUTOR,
-                    listener,
-                    remoteViewClickHandler);
-        } else {
-            cancellationSignal = newContentView.reapplyAsync(
-                    result.packageContext,
-                    existingView,
-                    EXECUTOR,
-                    listener,
-                    remoteViewClickHandler);
-        }
-        runningInflations.put(inflationId, cancellationSignal);
-    }
-
-    private static void handleInflationError(HashMap<Integer, CancellationSignal> runningInflations,
-            Exception e, StatusBarNotification notification, @Nullable InflationCallback callback) {
-        Assert.isMainThread();
-        runningInflations.values().forEach(CancellationSignal::cancel);
-        if (callback != null) {
-            callback.handleInflationException(notification, e);
-        }
-    }
-
-    /**
-     * Finish the inflation of the views
-     *
-     * @return true if the inflation was finished
-     */
-    private static boolean finishIfDone(InflationProgress result, int reInflateFlags,
-            HashMap<Integer, CancellationSignal> runningInflations,
-            @Nullable InflationCallback endListener, ExpandableNotificationRow row,
-            boolean redactAmbient) {
-        Assert.isMainThread();
-        NotificationData.Entry entry = row.getEntry();
-        NotificationContentView privateLayout = row.getPrivateLayout();
-        NotificationContentView publicLayout = row.getPublicLayout();
-        if (runningInflations.isEmpty()) {
-            if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
-                if (result.inflatedContentView != null) {
-                    privateLayout.setContractedChild(result.inflatedContentView);
-                }
-                entry.cachedContentView = result.newContentView;
-            }
-
-            if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
-                if (result.inflatedExpandedView != null) {
-                    privateLayout.setExpandedChild(result.inflatedExpandedView);
-                } else if (result.newExpandedView == null) {
-                    privateLayout.setExpandedChild(null);
-                }
-                entry.cachedBigContentView = result.newExpandedView;
-                row.setExpandable(result.newExpandedView != null);
-            }
-
-            if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
-                if (result.inflatedHeadsUpView != null) {
-                    privateLayout.setHeadsUpChild(result.inflatedHeadsUpView);
-                } else if (result.newHeadsUpView == null) {
-                    privateLayout.setHeadsUpChild(null);
-                }
-                entry.cachedHeadsUpContentView = result.newHeadsUpView;
-            }
-
-            if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
-                if (result.inflatedPublicView != null) {
-                    publicLayout.setContractedChild(result.inflatedPublicView);
-                }
-                entry.cachedPublicContentView = result.newPublicView;
-            }
-
-            if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
-                if (result.inflatedAmbientView != null) {
-                    NotificationContentView newParent = redactAmbient
-                            ? publicLayout : privateLayout;
-                    NotificationContentView otherParent = !redactAmbient
-                            ? publicLayout : privateLayout;
-                    newParent.setAmbientChild(result.inflatedAmbientView);
-                    otherParent.setAmbientChild(null);
-                }
-                entry.cachedAmbientContentView = result.newAmbientView;
-            }
-            entry.headsUpStatusBarText = result.headsUpStatusBarText;
-            entry.headsUpStatusBarTextPublic = result.headsUpStatusBarTextPublic;
-            if (endListener != null) {
-                endListener.onAsyncInflationFinished(row.getEntry());
-            }
-            return true;
-        }
-        return false;
-    }
-
-    private static RemoteViews createExpandedView(Notification.Builder builder,
-            boolean isLowPriority) {
-        RemoteViews bigContentView = builder.createBigContentView();
-        if (bigContentView != null) {
-            return bigContentView;
-        }
-        if (isLowPriority) {
-            RemoteViews contentView = builder.createContentView();
-            Notification.Builder.makeHeaderExpanded(contentView);
-            return contentView;
-        }
-        return null;
-    }
-
-    private static RemoteViews createContentView(Notification.Builder builder,
-            boolean isLowPriority, boolean useLarge) {
-        if (isLowPriority) {
-            return builder.makeLowPriorityContentView(false /* useRegularSubtext */);
-        }
-        return builder.createContentView(useLarge);
-    }
-
-    /**
-     * @param newView The new view that will be applied
-     * @param oldView The old view that was applied to the existing view before
-     * @return {@code true} if the RemoteViews are the same and the view can be reused to reapply.
-     */
-     @VisibleForTesting
-     static boolean canReapplyRemoteView(final RemoteViews newView,
-            final RemoteViews oldView) {
-        return (newView == null && oldView == null) ||
-                (newView != null && oldView != null
-                        && oldView.getPackage() != null
-                        && newView.getPackage() != null
-                        && newView.getPackage().equals(oldView.getPackage())
-                        && newView.getLayoutId() == oldView.getLayoutId()
-                        && !oldView.isReapplyDisallowed());
-    }
-
-    public void setInflationCallback(InflationCallback callback) {
-        mCallback = callback;
-    }
-
-    public interface InflationCallback {
-        void handleInflationException(StatusBarNotification notification, Exception e);
-        void onAsyncInflationFinished(NotificationData.Entry entry);
-
-        /**
-         * Used to disable async-ness for tests. Should only be used for tests.
-         */
-        default boolean doInflateSynchronous() {
-            return false;
-        }
-    }
-
-    public void onDensityOrFontScaleChanged() {
-        NotificationData.Entry entry = mRow.getEntry();
-        entry.cachedAmbientContentView = null;
-        entry.cachedBigContentView = null;
-        entry.cachedContentView = null;
-        entry.cachedHeadsUpContentView = null;
-        entry.cachedPublicContentView = null;
-        inflateNotificationViews();
-    }
-
-    private static boolean canReapplyAmbient(ExpandableNotificationRow row, boolean redactAmbient) {
-        NotificationContentView ambientView = redactAmbient ? row.getPublicLayout()
-                : row.getPrivateLayout();            ;
-        return ambientView.getAmbientChild() != null;
-    }
-
-    public static class AsyncInflationTask extends AsyncTask<Void, Void, InflationProgress>
-            implements InflationCallback, InflationTask {
-
-        private final StatusBarNotification mSbn;
-        private final Context mContext;
-        private final boolean mIsLowPriority;
-        private final boolean mIsChildInGroup;
-        private final boolean mUsesIncreasedHeight;
-        private final InflationCallback mCallback;
-        private final boolean mUsesIncreasedHeadsUpHeight;
-        private final boolean mRedactAmbient;
-        private int mReInflateFlags;
-        private ExpandableNotificationRow mRow;
-        private Exception mError;
-        private RemoteViews.OnClickHandler mRemoteViewClickHandler;
-        private CancellationSignal mCancellationSignal;
-
-        private AsyncInflationTask(StatusBarNotification notification,
-                int reInflateFlags, ExpandableNotificationRow row, boolean isLowPriority,
-                boolean isChildInGroup, boolean usesIncreasedHeight,
-                boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
-                InflationCallback callback,
-                RemoteViews.OnClickHandler remoteViewClickHandler) {
-            mRow = row;
-            mSbn = notification;
-            mReInflateFlags = reInflateFlags;
-            mContext = mRow.getContext();
-            mIsLowPriority = isLowPriority;
-            mIsChildInGroup = isChildInGroup;
-            mUsesIncreasedHeight = usesIncreasedHeight;
-            mUsesIncreasedHeadsUpHeight = usesIncreasedHeadsUpHeight;
-            mRedactAmbient = redactAmbient;
-            mRemoteViewClickHandler = remoteViewClickHandler;
-            mCallback = callback;
-            NotificationData.Entry entry = row.getEntry();
-            entry.setInflationTask(this);
-        }
-
-        @VisibleForTesting
-        public int getReInflateFlags() {
-            return mReInflateFlags;
-        }
-
-        @Override
-        protected InflationProgress doInBackground(Void... params) {
-            try {
-                final Notification.Builder recoveredBuilder
-                        = Notification.Builder.recoverBuilder(mContext,
-                        mSbn.getNotification());
-                Context packageContext = mSbn.getPackageContext(mContext);
-                Notification notification = mSbn.getNotification();
-                if (notification.isMediaNotification()) {
-                    MediaNotificationProcessor processor = new MediaNotificationProcessor(mContext,
-                            packageContext);
-                    processor.processNotification(notification, recoveredBuilder);
-                }
-                return createRemoteViews(mReInflateFlags,
-                        recoveredBuilder, mIsLowPriority, mIsChildInGroup,
-                        mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
-                        packageContext);
-            } catch (Exception e) {
-                mError = e;
-                return null;
-            }
-        }
-
-        @Override
-        protected void onPostExecute(InflationProgress result) {
-            if (mError == null) {
-                mCancellationSignal = apply(result, mReInflateFlags, mRow, mRedactAmbient,
-                        mRemoteViewClickHandler, this);
-            } else {
-                handleError(mError);
-            }
-        }
-
-        private void handleError(Exception e) {
-            mRow.getEntry().onInflationTaskFinished();
-            StatusBarNotification sbn = mRow.getStatusBarNotification();
-            final String ident = sbn.getPackageName() + "/0x"
-                    + Integer.toHexString(sbn.getId());
-            Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
-            mCallback.handleInflationException(sbn,
-                    new InflationException("Couldn't inflate contentViews" + e));
-        }
-
-        @Override
-        public void abort() {
-            cancel(true /* mayInterruptIfRunning */);
-            if (mCancellationSignal != null) {
-                mCancellationSignal.cancel();
-            }
-        }
-
-        @Override
-        public void supersedeTask(InflationTask task) {
-            if (task instanceof AsyncInflationTask) {
-                // We want to inflate all flags of the previous task as well
-                mReInflateFlags |= ((AsyncInflationTask) task).mReInflateFlags;
-            }
-        }
-
-        @Override
-        public void handleInflationException(StatusBarNotification notification, Exception e) {
-            handleError(e);
-        }
-
-        @Override
-        public void onAsyncInflationFinished(NotificationData.Entry entry) {
-            mRow.getEntry().onInflationTaskFinished();
-            mRow.onNotificationUpdated();
-            mCallback.onAsyncInflationFinished(mRow.getEntry());
-        }
-
-        @Override
-        public boolean doInflateSynchronous() {
-            return mCallback != null && mCallback.doInflateSynchronous();
-        }
-    }
-
-    @VisibleForTesting
-    static class InflationProgress {
-        private RemoteViews newContentView;
-        private RemoteViews newHeadsUpView;
-        private RemoteViews newExpandedView;
-        private RemoteViews newAmbientView;
-        private RemoteViews newPublicView;
-
-        @VisibleForTesting
-        Context packageContext;
-
-        private View inflatedContentView;
-        private View inflatedHeadsUpView;
-        private View inflatedExpandedView;
-        private View inflatedAmbientView;
-        private View inflatedPublicView;
-        private CharSequence headsUpStatusBarText;
-        private CharSequence headsUpStatusBarTextPublic;
-    }
-
-    @VisibleForTesting
-    abstract static class ApplyCallback {
-        public abstract void setResultView(View v);
-        public abstract RemoteViews getRemoteView();
-    }
-
-    /**
-     * A custom executor that allows more tasks to be queued. Default values are copied from
-     * AsyncTask
-      */
-    private static class InflationExecutor implements Executor {
-        private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
-        // We want at least 2 threads and at most 4 threads in the core pool,
-        // preferring to have 1 less than the CPU count to avoid saturating
-        // the CPU with background work
-        private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
-        private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
-        private static final int KEEP_ALIVE_SECONDS = 30;
-
-        private static final ThreadFactory sThreadFactory = new ThreadFactory() {
-            private final AtomicInteger mCount = new AtomicInteger(1);
-
-            public Thread newThread(Runnable r) {
-                return new Thread(r, "InflaterThread #" + mCount.getAndIncrement());
-            }
-        };
-
-        private final ThreadPoolExecutor mExecutor;
-
-        private InflationExecutor() {
-            mExecutor = new ThreadPoolExecutor(
-                    CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
-                    new LinkedBlockingQueue<>(), sThreadFactory);
-            mExecutor.allowCoreThreadTimeOut(true);
-        }
-
-        @Override
-        public void execute(Runnable runnable) {
-            mExecutor.execute(runnable);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
deleted file mode 100644
index 548f006..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import android.content.Context;
-import android.view.View;
-
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-
-/**
- * Wraps a notification containing a media template
- */
-public class NotificationMediaTemplateViewWrapper extends NotificationTemplateViewWrapper {
-
-    protected NotificationMediaTemplateViewWrapper(Context ctx, View view,
-            ExpandableNotificationRow row) {
-        super(ctx, view, row);
-    }
-
-    View mActions;
-
-    private void resolveViews() {
-        mActions = mView.findViewById(com.android.internal.R.id.media_actions);
-    }
-
-    @Override
-    public void onContentUpdated(ExpandableNotificationRow row) {
-        // Reinspect the notification. Before the super call, because the super call also updates
-        // the transformation types and we need to have our values set by then.
-        resolveViews();
-        super.onContentUpdated(row);
-    }
-
-    @Override
-    protected void updateTransformedTypes() {
-        // This also clears the existing types
-        super.updateTransformedTypes();
-        if (mActions != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_ACTIONS,
-                    mActions);
-        }
-    }
-
-    @Override
-    public boolean isDimmable() {
-        return getCustomBackgroundColor() == 0;
-    }
-
-    @Override
-    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
-        return true;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
deleted file mode 100644
index fb5644f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import com.android.internal.widget.MessagingLayout;
-import com.android.internal.widget.MessagingLinearLayout;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.view.View;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-
-/**
- * Wraps a notification containing a messaging template
- */
-public class NotificationMessagingTemplateViewWrapper extends NotificationTemplateViewWrapper {
-
-    private final int mMinHeightWithActions;
-    private MessagingLayout mMessagingLayout;
-    private MessagingLinearLayout mMessagingLinearLayout;
-
-    protected NotificationMessagingTemplateViewWrapper(Context ctx, View view,
-            ExpandableNotificationRow row) {
-        super(ctx, view, row);
-        mMessagingLayout = (MessagingLayout) view;
-        mMinHeightWithActions = NotificationUtils.getFontScaledHeight(ctx,
-                R.dimen.notification_messaging_actions_min_height);
-    }
-
-    private void resolveViews() {
-        mMessagingLinearLayout = mMessagingLayout.getMessagingLinearLayout();
-    }
-
-    @Override
-    public void onContentUpdated(ExpandableNotificationRow row) {
-        // Reinspect the notification. Before the super call, because the super call also updates
-        // the transformation types and we need to have our values set by then.
-        resolveViews();
-        super.onContentUpdated(row);
-    }
-
-    @Override
-    protected void updateTransformedTypes() {
-        // This also clears the existing types
-        super.updateTransformedTypes();
-        if (mMessagingLinearLayout != null) {
-            mTransformationHelper.addTransformedView(mMessagingLinearLayout.getId(),
-                    mMessagingLinearLayout);
-        }
-    }
-
-    @Override
-    public void setRemoteInputVisible(boolean visible) {
-        mMessagingLayout.showHistoricMessages(visible);
-    }
-
-    @Override
-    public int getMinLayoutHeight() {
-        if (mActionsContainer != null && mActionsContainer.getVisibility() != View.GONE) {
-            return mMinHeightWithActions;
-        }
-        return super.getMinLayoutHeight();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
deleted file mode 100644
index d4b0be8..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.service.notification.StatusBarNotification;
-import android.util.ArraySet;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.android.internal.util.ContrastColorUtil;
-import com.android.internal.widget.NotificationActionListLayout;
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.UiOffloadThread;
-import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.ViewTransformationHelper;
-
-/**
- * Wraps a notification view inflated from a template.
- */
-public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapper {
-
-    protected ImageView mPicture;
-    private ProgressBar mProgressBar;
-    private TextView mTitle;
-    private TextView mText;
-    protected View mActionsContainer;
-    private ImageView mReplyAction;
-    private Rect mTmpRect = new Rect();
-
-    private int mContentHeight;
-    private int mMinHeightHint;
-    private NotificationActionListLayout mActions;
-    private ArraySet<PendingIntent> mCancelledPendingIntents = new ArraySet<>();
-    private UiOffloadThread mUiOffloadThread;
-    private View mRemoteInputHistory;
-
-    protected NotificationTemplateViewWrapper(Context ctx, View view,
-            ExpandableNotificationRow row) {
-        super(ctx, view, row);
-        mTransformationHelper.setCustomTransformation(
-                new ViewTransformationHelper.CustomTransformation() {
-                    @Override
-                    public boolean transformTo(TransformState ownState,
-                            TransformableView notification, final float transformationAmount) {
-                        if (!(notification instanceof HybridNotificationView)) {
-                            return false;
-                        }
-                        TransformState otherState = notification.getCurrentState(
-                                TRANSFORMING_VIEW_TITLE);
-                        final View text = ownState.getTransformedView();
-                        CrossFadeHelper.fadeOut(text, transformationAmount);
-                        if (otherState != null) {
-                            ownState.transformViewVerticalTo(otherState, this,
-                                    transformationAmount);
-                            otherState.recycle();
-                        }
-                        return true;
-                    }
-
-                    @Override
-                    public boolean customTransformTarget(TransformState ownState,
-                            TransformState otherState) {
-                        float endY = getTransformationY(ownState, otherState);
-                        ownState.setTransformationEndY(endY);
-                        return true;
-                    }
-
-                    @Override
-                    public boolean transformFrom(TransformState ownState,
-                            TransformableView notification, float transformationAmount) {
-                        if (!(notification instanceof HybridNotificationView)) {
-                            return false;
-                        }
-                        TransformState otherState = notification.getCurrentState(
-                                TRANSFORMING_VIEW_TITLE);
-                        final View text = ownState.getTransformedView();
-                        CrossFadeHelper.fadeIn(text, transformationAmount);
-                        if (otherState != null) {
-                            ownState.transformViewVerticalFrom(otherState, this,
-                                    transformationAmount);
-                            otherState.recycle();
-                        }
-                        return true;
-                    }
-
-                    @Override
-                    public boolean initTransformation(TransformState ownState,
-                            TransformState otherState) {
-                        float startY = getTransformationY(ownState, otherState);
-                        ownState.setTransformationStartY(startY);
-                        return true;
-                    }
-
-                    private float getTransformationY(TransformState ownState,
-                            TransformState otherState) {
-                        int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
-                        int[] ownStablePosition = ownState.getLaidOutLocationOnScreen();
-                        return (otherStablePosition[1]
-                                + otherState.getTransformedView().getHeight()
-                                - ownStablePosition[1]) * 0.33f;
-                    }
-
-                }, TRANSFORMING_VIEW_TEXT);
-    }
-
-    private void resolveTemplateViews(StatusBarNotification notification) {
-        mPicture = (ImageView) mView.findViewById(com.android.internal.R.id.right_icon);
-        if (mPicture != null) {
-            mPicture.setTag(ImageTransformState.ICON_TAG,
-                    notification.getNotification().getLargeIcon());
-        }
-        mTitle = (TextView) mView.findViewById(com.android.internal.R.id.title);
-        mText = (TextView) mView.findViewById(com.android.internal.R.id.text);
-        final View progress = mView.findViewById(com.android.internal.R.id.progress);
-        if (progress instanceof ProgressBar) {
-            mProgressBar = (ProgressBar) progress;
-        } else {
-            // It's still a viewstub
-            mProgressBar = null;
-        }
-        mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container);
-        mActions = mView.findViewById(com.android.internal.R.id.actions);
-        mReplyAction = mView.findViewById(com.android.internal.R.id.reply_icon_action);
-        mRemoteInputHistory = mView.findViewById(
-                com.android.internal.R.id.notification_material_reply_container);
-        updatePendingIntentCancellations();
-    }
-
-    private void updatePendingIntentCancellations() {
-        if (mActions != null) {
-            int numActions = mActions.getChildCount();
-            for (int i = 0; i < numActions; i++) {
-                Button action = (Button) mActions.getChildAt(i);
-                performOnPendingIntentCancellation(action, () -> {
-                    if (action.isEnabled()) {
-                        action.setEnabled(false);
-                        // The visual appearance doesn't look disabled enough yet, let's add the
-                        // alpha as well. Since Alpha doesn't play nicely right now with the
-                        // transformation, we rather blend it manually with the background color.
-                        ColorStateList textColors = action.getTextColors();
-                        int[] colors = textColors.getColors();
-                        int[] newColors = new int[colors.length];
-                        float disabledAlpha = mView.getResources().getFloat(
-                                com.android.internal.R.dimen.notification_action_disabled_alpha);
-                        for (int j = 0; j < colors.length; j++) {
-                            int color = colors[j];
-                            color = blendColorWithBackground(color, disabledAlpha);
-                            newColors[j] = color;
-                        }
-                        ColorStateList newColorStateList = new ColorStateList(
-                                textColors.getStates(), newColors);
-                        action.setTextColor(newColorStateList);
-                    }
-                });
-            }
-        }
-        if (mReplyAction != null) {
-            // Let's reset the view on update, assuming the new pending intent isn't cancelled
-            // anymore. The color filter automatically resets when it's updated.
-            mReplyAction.setEnabled(true);
-            performOnPendingIntentCancellation(mReplyAction, () -> {
-                if (mReplyAction != null && mReplyAction.isEnabled()) {
-                    mReplyAction.setEnabled(false);
-                    // The visual appearance doesn't look disabled enough yet, let's add the
-                    // alpha as well. Since Alpha doesn't play nicely right now with the
-                    // transformation, we rather blend it manually with the background color.
-                    Drawable drawable = mReplyAction.getDrawable().mutate();
-                    PorterDuffColorFilter colorFilter =
-                            (PorterDuffColorFilter) drawable.getColorFilter();
-                    float disabledAlpha = mView.getResources().getFloat(
-                            com.android.internal.R.dimen.notification_action_disabled_alpha);
-                    if (colorFilter != null) {
-                        int color = colorFilter.getColor();
-                        color = blendColorWithBackground(color, disabledAlpha);
-                        drawable.mutate().setColorFilter(color, colorFilter.getMode());
-                    } else {
-                        mReplyAction.setAlpha(disabledAlpha);
-                    }
-                }
-            });
-        }
-    }
-
-    private int blendColorWithBackground(int color, float alpha) {
-        // alpha doesn't go well for color filters, so let's blend it manually
-        return ContrastColorUtil.compositeColors(Color.argb((int) (alpha * 255),
-                Color.red(color), Color.green(color), Color.blue(color)), resolveBackgroundColor());
-    }
-
-    private void performOnPendingIntentCancellation(View view, Runnable cancellationRunnable) {
-        PendingIntent pendingIntent = (PendingIntent) view.getTag(
-                com.android.internal.R.id.pending_intent_tag);
-        if (pendingIntent == null) {
-            return;
-        }
-        if (mCancelledPendingIntents.contains(pendingIntent)) {
-            cancellationRunnable.run();
-        } else {
-            PendingIntent.CancelListener listener = (PendingIntent intent) -> {
-                mView.post(() -> {
-                    mCancelledPendingIntents.add(pendingIntent);
-                    cancellationRunnable.run();
-                });
-            };
-            if (mUiOffloadThread == null) {
-                mUiOffloadThread = Dependency.get(UiOffloadThread.class);
-            }
-            if (view.isAttachedToWindow()) {
-                mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
-            }
-            view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
-                @Override
-                public void onViewAttachedToWindow(View v) {
-                    mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
-                }
-
-                @Override
-                public void onViewDetachedFromWindow(View v) {
-                    mUiOffloadThread.submit(() -> pendingIntent.unregisterCancelListener(listener));
-                }
-            });
-        }
-    }
-
-    @Override
-    public boolean disallowSingleClick(float x, float y) {
-        if (mReplyAction != null && mReplyAction.getVisibility() == View.VISIBLE) {
-            if (isOnView(mReplyAction, x, y) || isOnView(mPicture, x, y)) {
-                return true;
-            }
-        }
-        return super.disallowSingleClick(x, y);
-    }
-
-    private boolean isOnView(View view, float x, float y) {
-        View searchView = (View) view.getParent();
-        while (searchView != null && !(searchView instanceof ExpandableNotificationRow)) {
-            searchView.getHitRect(mTmpRect);
-            x -= mTmpRect.left;
-            y -= mTmpRect.top;
-            searchView = (View) searchView.getParent();
-        }
-        view.getHitRect(mTmpRect);
-        return mTmpRect.contains((int) x,(int) y);
-    }
-
-    @Override
-    public void onContentUpdated(ExpandableNotificationRow row) {
-        // Reinspect the notification. Before the super call, because the super call also updates
-        // the transformation types and we need to have our values set by then.
-        resolveTemplateViews(row.getStatusBarNotification());
-        super.onContentUpdated(row);
-    }
-
-    @Override
-    protected void updateTransformedTypes() {
-        // This also clears the existing types
-        super.updateTransformedTypes();
-        if (mTitle != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
-                    mTitle);
-        }
-        if (mText != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
-                    mText);
-        }
-        if (mPicture != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE,
-                    mPicture);
-        }
-        if (mProgressBar != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS,
-                    mProgressBar);
-        }
-    }
-
-    @Override
-    public void setContentHeight(int contentHeight, int minHeightHint) {
-        super.setContentHeight(contentHeight, minHeightHint);
-
-        mContentHeight = contentHeight;
-        mMinHeightHint = minHeightHint;
-        updateActionOffset();
-    }
-
-    @Override
-    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
-        if (super.shouldClipToRounding(topRounded, bottomRounded)) {
-            return true;
-        }
-        return bottomRounded && mActionsContainer != null
-                && mActionsContainer.getVisibility() != View.GONE;
-    }
-
-    private void updateActionOffset() {
-        if (mActionsContainer != null) {
-            // We should never push the actions higher than they are in the headsup view.
-            int constrainedContentHeight = Math.max(mContentHeight, mMinHeightHint);
-
-            // We also need to compensate for any header translation, since we're always at the end.
-            mActionsContainer.setTranslationY(constrainedContentHeight - mView.getHeight()
-                    - getHeaderTranslation());
-        }
-    }
-
-    @Override
-    public int getExtraMeasureHeight() {
-        int extra = 0;
-        if (mActions != null) {
-            extra = mActions.getExtraMeasureHeight();
-        }
-        if (mRemoteInputHistory != null && mRemoteInputHistory.getVisibility() != View.GONE) {
-            extra += mRow.getContext().getResources().getDimensionPixelSize(
-                    R.dimen.remote_input_history_extra_height);
-        }
-        return extra + super.getExtraMeasureHeight();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
deleted file mode 100644
index 93058b8..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import android.content.Context;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.view.NotificationHeaderView;
-import android.view.View;
-
-import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-
-/**
- * Wraps the actual notification content view; used to implement behaviors which are different for
- * the individual templates and custom views.
- */
-public abstract class NotificationViewWrapper implements TransformableView {
-
-    protected final View mView;
-    protected final ExpandableNotificationRow mRow;
-
-    private int mBackgroundColor = 0;
-
-    public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
-        if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
-            if ("bigPicture".equals(v.getTag())) {
-                return new NotificationBigPictureTemplateViewWrapper(ctx, v, row);
-            } else if ("bigText".equals(v.getTag())) {
-                return new NotificationBigTextTemplateViewWrapper(ctx, v, row);
-            } else if ("media".equals(v.getTag()) || "bigMediaNarrow".equals(v.getTag())) {
-                return new NotificationMediaTemplateViewWrapper(ctx, v, row);
-            } else if ("messaging".equals(v.getTag())) {
-                return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
-            }
-            return new NotificationTemplateViewWrapper(ctx, v, row);
-        } else if (v instanceof NotificationHeaderView) {
-            return new NotificationHeaderViewWrapper(ctx, v, row);
-        } else {
-            return new NotificationCustomViewWrapper(ctx, v, row);
-        }
-    }
-
-    protected NotificationViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
-        mView = view;
-        mRow = row;
-        onReinflated();
-    }
-
-    /**
-     * Notifies this wrapper that the content of the view might have changed.
-     * @param row the row this wrapper is attached to
-     */
-    public void onContentUpdated(ExpandableNotificationRow row) {
-    }
-
-    public void onReinflated() {
-        if (shouldClearBackgroundOnReapply()) {
-            mBackgroundColor = 0;
-        }
-        Drawable background = mView.getBackground();
-        if (background instanceof ColorDrawable) {
-            mBackgroundColor = ((ColorDrawable) background).getColor();
-            mView.setBackground(null);
-        }
-    }
-
-    protected boolean shouldClearBackgroundOnReapply() {
-        return true;
-    }
-
-    /**
-     * Update the appearance of the expand button.
-     *
-     * @param expandable should this view be expandable
-     * @param onClickListener the listener to invoke when the expand affordance is clicked on
-     */
-    public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {}
-
-    /**
-     * @return the notification header if it exists
-     */
-    public NotificationHeaderView getNotificationHeader() {
-        return null;
-    }
-
-    public int getHeaderTranslation() {
-        return 0;
-    }
-
-    @Override
-    public TransformState getCurrentState(int fadingView) {
-        return null;
-    }
-
-    @Override
-    public void transformTo(TransformableView notification, Runnable endRunnable) {
-        // By default we are fading out completely
-        CrossFadeHelper.fadeOut(mView, endRunnable);
-    }
-
-    @Override
-    public void transformTo(TransformableView notification, float transformationAmount) {
-        CrossFadeHelper.fadeOut(mView, transformationAmount);
-    }
-
-    @Override
-    public void transformFrom(TransformableView notification) {
-        // By default we are fading in completely
-        CrossFadeHelper.fadeIn(mView);
-    }
-
-    @Override
-    public void transformFrom(TransformableView notification, float transformationAmount) {
-        CrossFadeHelper.fadeIn(mView, transformationAmount);
-    }
-
-    @Override
-    public void setVisible(boolean visible) {
-        mView.animate().cancel();
-        mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
-    }
-
-    public int getCustomBackgroundColor() {
-        // Parent notifications should always use the normal background color
-        return mRow.isSummaryWithChildren() ? 0 : mBackgroundColor;
-    }
-
-    protected int resolveBackgroundColor() {
-        int customBackgroundColor = getCustomBackgroundColor();
-        if (customBackgroundColor != 0) {
-            return customBackgroundColor;
-        }
-        return mView.getContext().getColor(
-                com.android.internal.R.color.notification_material_background_color);
-    }
-
-    public void setLegacy(boolean legacy) {
-    }
-
-    public void setContentHeight(int contentHeight, int minHeightHint) {
-    }
-
-    public void setRemoteInputVisible(boolean visible) {
-    }
-
-    public void setIsChildInGroup(boolean isChildInGroup) {
-    }
-
-    public boolean isDimmable() {
-        return true;
-    }
-
-    public boolean disallowSingleClick(float x, float y) {
-        return false;
-    }
-
-    public int getMinLayoutHeight() {
-        return 0;
-    }
-
-    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
-        return false;
-    }
-
-    public void setHeaderVisibleAmount(float headerVisibleAmount) {
-    }
-
-    /**
-     * Get the extra height that needs to be added to this view, such that it can be measured
-     * normally.
-     */
-    public int getExtraMeasureHeight() {
-        return 0;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
index 2efcd16..aacb22d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
@@ -24,11 +24,10 @@
 import android.view.View;
 import android.view.animation.Interpolator;
 
-import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.stack.AnimationFilter;
-import com.android.systemui.statusbar.stack.AnimationProperties;
-import com.android.systemui.statusbar.stack.ViewState;
+import com.android.systemui.statusbar.notification.stack.AnimationFilter;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.ViewState;
 
 /**
  * An animator to animate properties
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
deleted file mode 100644
index 9b9dfc9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import android.content.Context;
-import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.InflationTask;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
-
-/**
- * An inflater task that asynchronously inflates a ExpandableNotificationRow
- */
-public class RowInflaterTask implements InflationTask, AsyncLayoutInflater.OnInflateFinishedListener {
-
-    private static final String TAG = "RowInflaterTask";
-    private static final boolean TRACE_ORIGIN = true;
-
-    private RowInflationFinishedListener mListener;
-    private NotificationData.Entry mEntry;
-    private boolean mCancelled;
-    private Throwable mInflateOrigin;
-
-    /**
-     * Inflates a new notificationView. This should not be called twice on this object
-     */
-    public void inflate(Context context, ViewGroup parent, NotificationData.Entry entry,
-            RowInflationFinishedListener listener) {
-        if (TRACE_ORIGIN) {
-            mInflateOrigin = new Throwable("inflate requested here");
-        }
-        mListener = listener;
-        AsyncLayoutInflater inflater = new AsyncLayoutInflater(context);
-        mEntry = entry;
-        entry.setInflationTask(this);
-        inflater.inflate(R.layout.status_bar_notification_row, parent, this);
-    }
-
-    @Override
-    public void abort() {
-        mCancelled = true;
-    }
-
-    @Override
-    public void onInflateFinished(View view, int resid, ViewGroup parent) {
-        if (!mCancelled) {
-            try {
-                mEntry.onInflationTaskFinished();
-                mListener.onInflationFinished((ExpandableNotificationRow) view);
-            } catch (Throwable t) {
-                if (mInflateOrigin != null) {
-                    Log.e(TAG, "Error in inflation finished listener: " + t, mInflateOrigin);
-                    t.addSuppressed(mInflateOrigin);
-                }
-                throw t;
-            }
-        }
-    }
-
-    public interface RowInflationFinishedListener {
-        void onInflationFinished(ExpandableNotificationRow row);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 879ac92..07b8c35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -29,7 +29,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.ViewTransformationHelper;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisibilityLocationProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisibilityLocationProvider.java
index 4a52acc..81208c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisibilityLocationProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisibilityLocationProvider.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.notification;
 
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * An object that can determine the visibility of a Notification.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index 7fe01c0..da8954a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -19,8 +19,7 @@
 import androidx.collection.ArraySet;
 import android.view.View;
 
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
new file mode 100644
index 0000000..28c07a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.logging;
+
+/**
+ * Constants for counter tags for Notification-related actions/views.
+ */
+public class NotificationCounters {
+    /** Counter tag for notification dismissal. */
+    public static final String NOTIFICATION_DISMISSED = "notification_dismissed";
+
+    /** Counter tag for when the blocking helper is shown to the user. */
+    public static final String BLOCKING_HELPER_SHOWN = "blocking_helper_shown";
+    /** Counter tag for when the blocking helper is dismissed via a miscellaneous interaction. */
+    public static final String BLOCKING_HELPER_DISMISSED = "blocking_helper_dismissed";
+    /** Counter tag for when the user hits 'stop notifications' in the blocking helper. */
+    public static final String BLOCKING_HELPER_STOP_NOTIFICATIONS =
+            "blocking_helper_stop_notifications";
+    /** Counter tag for when the user hits 'keep showing' in the blocking helper. */
+    public static final String BLOCKING_HELPER_KEEP_SHOWING =
+            "blocking_helper_keep_showing";
+    /**
+     * Counter tag for when the user hits undo in context of the blocking helper - this can happen
+     * multiple times per view.
+     */
+    public static final String BLOCKING_HELPER_UNDO = "blocking_helper_undo";
+    /** Counter tag for when the user hits the notification settings icon in the blocking helper. */
+    public static final String BLOCKING_HELPER_NOTIF_SETTINGS =
+            "blocking_helper_notif_settings";
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
new file mode 100644
index 0000000..e96e176
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.statusbar.notification.logging;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.service.notification.NotificationListenerService;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.Dependency;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Handles notification logging, in particular, logging which notifications are visible and which
+ * are not.
+ */
+public class NotificationLogger {
+    private static final String TAG = "NotificationLogger";
+
+    /** The minimum delay in ms between reports of notification visibility. */
+    private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500;
+
+    /** Keys of notifications currently visible to the user. */
+    private final ArraySet<NotificationVisibility> mCurrentlyVisibleNotifications =
+            new ArraySet<>();
+
+    // Dependencies:
+    private final NotificationListenerService mNotificationListener =
+            Dependency.get(NotificationListener.class);
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+
+    protected NotificationEntryManager mEntryManager;
+    protected Handler mHandler = new Handler();
+    protected IStatusBarService mBarService;
+    private long mLastVisibilityReportUptimeMs;
+    private NotificationListContainer mListContainer;
+    private Object mDozingLock = new Object();
+    private boolean mDozing;
+
+    protected final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
+            new OnChildLocationsChangedListener() {
+                @Override
+                public void onChildLocationsChanged() {
+                    if (mHandler.hasCallbacks(mVisibilityReporter)) {
+                        // Visibilities will be reported when the existing
+                        // callback is executed.
+                        return;
+                    }
+                    // Calculate when we're allowed to run the visibility
+                    // reporter. Note that this timestamp might already have
+                    // passed. That's OK, the callback will just be executed
+                    // ASAP.
+                    long nextReportUptimeMs =
+                            mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS;
+                    mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs);
+                }
+            };
+
+    // Tracks notifications currently visible in mNotificationStackScroller and
+    // emits visibility events via NoMan on changes.
+    protected final Runnable mVisibilityReporter = new Runnable() {
+        private final ArraySet<NotificationVisibility> mTmpNewlyVisibleNotifications =
+                new ArraySet<>();
+        private final ArraySet<NotificationVisibility> mTmpCurrentlyVisibleNotifications =
+                new ArraySet<>();
+        private final ArraySet<NotificationVisibility> mTmpNoLongerVisibleNotifications =
+                new ArraySet<>();
+
+        @Override
+        public void run() {
+            mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis();
+
+            // 1. Loop over mNotificationData entries:
+            //   A. Keep list of visible notifications.
+            //   B. Keep list of previously hidden, now visible notifications.
+            // 2. Compute no-longer visible notifications by removing currently
+            //    visible notifications from the set of previously visible
+            //    notifications.
+            // 3. Report newly visible and no-longer visible notifications.
+            // 4. Keep currently visible notifications for next report.
+            ArrayList<NotificationData.Entry> activeNotifications = mEntryManager
+                    .getNotificationData().getActiveNotifications();
+            int N = activeNotifications.size();
+            for (int i = 0; i < N; i++) {
+                NotificationData.Entry entry = activeNotifications.get(i);
+                String key = entry.notification.getKey();
+                boolean isVisible = mListContainer.isInVisibleLocation(entry.row);
+                NotificationVisibility visObj = NotificationVisibility.obtain(key, i, N, isVisible);
+                boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(visObj);
+                if (isVisible) {
+                    // Build new set of visible notifications.
+                    mTmpCurrentlyVisibleNotifications.add(visObj);
+                    if (!previouslyVisible) {
+                        mTmpNewlyVisibleNotifications.add(visObj);
+                    }
+                } else {
+                    // release object
+                    visObj.recycle();
+                }
+            }
+            mTmpNoLongerVisibleNotifications.addAll(mCurrentlyVisibleNotifications);
+            mTmpNoLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
+
+            logNotificationVisibilityChanges(
+                    mTmpNewlyVisibleNotifications, mTmpNoLongerVisibleNotifications);
+
+            recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
+            mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications);
+
+            recycleAllVisibilityObjects(mTmpNoLongerVisibleNotifications);
+            mTmpCurrentlyVisibleNotifications.clear();
+            mTmpNewlyVisibleNotifications.clear();
+            mTmpNoLongerVisibleNotifications.clear();
+        }
+    };
+
+    public NotificationLogger() {
+        mBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+    }
+
+    public void setUpWithEntryManager(NotificationEntryManager entryManager,
+            NotificationListContainer listContainer) {
+        mEntryManager = entryManager;
+        mListContainer = listContainer;
+    }
+
+    public void stopNotificationLogging() {
+        // Report all notifications as invisible and turn down the
+        // reporter.
+        if (!mCurrentlyVisibleNotifications.isEmpty()) {
+            logNotificationVisibilityChanges(
+                    Collections.emptyList(), mCurrentlyVisibleNotifications);
+            recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
+        }
+        mHandler.removeCallbacks(mVisibilityReporter);
+        mListContainer.setChildLocationsChangedListener(null);
+    }
+
+    public void startNotificationLogging() {
+        mListContainer.setChildLocationsChangedListener(mNotificationLocationsChangedListener);
+        // Some transitions like mVisibleToUser=false -> mVisibleToUser=true don't
+        // cause the scroller to emit child location events. Hence generate
+        // one ourselves to guarantee that we're reporting visible
+        // notifications.
+        // (Note that in cases where the scroller does emit events, this
+        // additional event doesn't break anything.)
+        mNotificationLocationsChangedListener.onChildLocationsChanged();
+    }
+
+    public void setDozing(boolean dozing) {
+        synchronized (mDozingLock) {
+            mDozing = dozing;
+        }
+    }
+
+    private void logNotificationVisibilityChanges(
+            Collection<NotificationVisibility> newlyVisible,
+            Collection<NotificationVisibility> noLongerVisible) {
+        if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
+            return;
+        }
+        final NotificationVisibility[] newlyVisibleAr = cloneVisibilitiesAsArr(newlyVisible);
+        final NotificationVisibility[] noLongerVisibleAr = cloneVisibilitiesAsArr(noLongerVisible);
+
+        mUiOffloadThread.submit(() -> {
+            try {
+                mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
+            } catch (RemoteException e) {
+                // Ignore.
+            }
+
+            final int N = newlyVisibleAr.length;
+            if (N > 0) {
+                String[] newlyVisibleKeyAr = new String[N];
+                for (int i = 0; i < N; i++) {
+                    newlyVisibleKeyAr[i] = newlyVisibleAr[i].key;
+                }
+
+                synchronized (mDozingLock) {
+                    // setNotificationsShown should only be called if we are confident that
+                    // the user has seen the notification, aka not when ambient display is on
+                    if (!mDozing) {
+                        // TODO: Call NotificationEntryManager to do this, once it exists.
+                        // TODO: Consider not catching all runtime exceptions here.
+                        try {
+                            mNotificationListener.setNotificationsShown(newlyVisibleKeyAr);
+                        } catch (RuntimeException e) {
+                            Log.d(TAG, "failed setNotificationsShown: ", e);
+                        }
+                    }
+                }
+            }
+            recycleAllVisibilityObjects(newlyVisibleAr);
+            recycleAllVisibilityObjects(noLongerVisibleAr);
+        });
+    }
+
+    private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
+        final int N = array.size();
+        for (int i = 0 ; i < N; i++) {
+            array.valueAt(i).recycle();
+        }
+        array.clear();
+    }
+
+    private void recycleAllVisibilityObjects(NotificationVisibility[] array) {
+        final int N = array.length;
+        for (int i = 0 ; i < N; i++) {
+            if (array[i] != null) {
+                array[i].recycle();
+            }
+        }
+    }
+
+    private NotificationVisibility[] cloneVisibilitiesAsArr(Collection<NotificationVisibility> c) {
+
+        final NotificationVisibility[] array = new NotificationVisibility[c.size()];
+        int i = 0;
+        for(NotificationVisibility nv: c) {
+            if (nv != null) {
+                array[i] = nv.clone();
+            }
+            i++;
+        }
+        return array;
+    }
+
+    @VisibleForTesting
+    public Runnable getVisibilityReporter() {
+        return mVisibilityReporter;
+    }
+
+    /**
+     * A listener that is notified when some child locations might have changed.
+     */
+    public interface OnChildLocationsChangedListener {
+        void onChildLocationsChanged();
+    }
+}
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
new file mode 100644
index 0000000..58db03c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -0,0 +1,1109 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.TimeAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.MathUtils;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.accessibility.AccessibilityManager;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.notification.FakeShadowView;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.phone.DoubleTapHelper;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+
+/**
+ * Base class for both {@link ExpandableNotificationRow} and {@link NotificationShelf}
+ * to implement dimming/activating on Keyguard for the double-tap gesture
+ */
+public abstract class ActivatableNotificationView extends ExpandableOutlineView {
+
+    private static final int BACKGROUND_ANIMATION_LENGTH_MS = 220;
+    private static final int ACTIVATE_ANIMATION_LENGTH = 220;
+    private static final long DARK_ANIMATION_LENGTH = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
+
+    /**
+     * The amount of width, which is kept in the end when performing a disappear animation (also
+     * the amount from which the horizontal appearing begins)
+     */
+    private static final float HORIZONTAL_COLLAPSED_REST_PARTIAL = 0.05f;
+
+    /**
+     * At which point from [0,1] does the horizontal collapse animation end (or start when
+     * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
+     */
+    private static final float HORIZONTAL_ANIMATION_END = 0.2f;
+
+    /**
+     * At which point from [0,1] does the alpha animation end (or start when
+     * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
+     */
+    private static final float ALPHA_ANIMATION_END = 0.0f;
+
+    /**
+     * At which point from [0,1] does the horizontal collapse animation start (or start when
+     * expanding)? 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
+     */
+    private static final float HORIZONTAL_ANIMATION_START = 1.0f;
+
+    /**
+     * At which point from [0,1] does the vertical collapse animation start (or end when
+     * expanding) 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
+     */
+    private static final float VERTICAL_ANIMATION_START = 1.0f;
+
+    /**
+     * Scale for the background to animate from when exiting dark mode.
+     */
+    private static final float DARK_EXIT_SCALE_START = 0.93f;
+
+    /**
+     * A sentinel value when no color should be used. Can be used with {@link #setTintColor(int)}
+     * or {@link #setOverrideTintColor(int, float)}.
+     */
+    protected static final int NO_COLOR = 0;
+
+    private static final Interpolator ACTIVATE_INVERSE_INTERPOLATOR
+            = new PathInterpolator(0.6f, 0, 0.5f, 1);
+    private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR
+            = new PathInterpolator(0, 0, 0.5f, 1);
+    private int mTintedRippleColor;
+    protected int mNormalRippleColor;
+    private final AccessibilityManager mAccessibilityManager;
+    private final DoubleTapHelper mDoubleTapHelper;
+
+    private boolean mDimmed;
+    private boolean mDark;
+
+    protected int mBgTint = NO_COLOR;
+    private float mBgAlpha = 1f;
+
+    /**
+     * Flag to indicate that the notification has been touched once and the second touch will
+     * click it.
+     */
+    private boolean mActivated;
+
+    private OnActivatedListener mOnActivatedListener;
+
+    private final Interpolator mSlowOutFastInInterpolator;
+    private final Interpolator mSlowOutLinearInInterpolator;
+    private Interpolator mCurrentAppearInterpolator;
+    private Interpolator mCurrentAlphaInterpolator;
+
+    protected NotificationBackgroundView mBackgroundNormal;
+    private NotificationBackgroundView mBackgroundDimmed;
+    private ObjectAnimator mBackgroundAnimator;
+    private RectF mAppearAnimationRect = new RectF();
+    private float mAnimationTranslationY;
+    private boolean mDrawingAppearAnimation;
+    private ValueAnimator mAppearAnimator;
+    private ValueAnimator mBackgroundColorAnimator;
+    private float mAppearAnimationFraction = -1.0f;
+    private float mAppearAnimationTranslation;
+    private int mNormalColor;
+    private boolean mIsBelowSpeedBump;
+    private FalsingManager mFalsingManager;
+
+    private float mNormalBackgroundVisibilityAmount;
+    private ValueAnimator mFadeInFromDarkAnimator;
+    private float mDimmedBackgroundFadeInAmount = -1;
+    private ValueAnimator.AnimatorUpdateListener mBackgroundVisibilityUpdater
+            = new ValueAnimator.AnimatorUpdateListener() {
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            setNormalBackgroundVisibilityAmount(mBackgroundNormal.getAlpha());
+            mDimmedBackgroundFadeInAmount = mBackgroundDimmed.getAlpha();
+        }
+    };
+    private AnimatorListenerAdapter mFadeInEndListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            super.onAnimationEnd(animation);
+            mFadeInFromDarkAnimator = null;
+            mDimmedBackgroundFadeInAmount = -1;
+            updateBackground();
+        }
+    };
+    private ValueAnimator.AnimatorUpdateListener mUpdateOutlineListener
+            = new ValueAnimator.AnimatorUpdateListener() {
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            updateOutlineAlpha();
+        }
+    };
+    private float mShadowAlpha = 1.0f;
+    private FakeShadowView mFakeShadow;
+    private int mCurrentBackgroundTint;
+    private int mTargetTint;
+    private int mStartTint;
+    private int mOverrideTint;
+    private float mOverrideAmount;
+    private boolean mShadowHidden;
+    /**
+     * Similar to mDimmed but is also true if it's not dimmable but should be
+     */
+    private boolean mNeedsDimming;
+    private int mDimmedAlpha;
+    private boolean mBlockNextTouch;
+    private boolean mIsHeadsUpAnimation;
+    private int mHeadsUpAddStartLocation;
+    private float mHeadsUpLocation;
+    private boolean mIsAppearing;
+
+    public ActivatableNotificationView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
+        mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
+        setClipChildren(false);
+        setClipToPadding(false);
+        updateColors();
+        mFalsingManager = FalsingManager.getInstance(context);
+        mAccessibilityManager = AccessibilityManager.getInstance(mContext);
+
+        mDoubleTapHelper = new DoubleTapHelper(this, (active) -> {
+            if (active) {
+                makeActive();
+            } else {
+                makeInactive(true /* animate */);
+            }
+        }, super::performClick, this::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
+        initDimens();
+    }
+
+    private void updateColors() {
+        mNormalColor = mContext.getColor(R.color.notification_material_background_color);
+        mTintedRippleColor = mContext.getColor(
+                R.color.notification_ripple_tinted_color);
+        mNormalRippleColor = mContext.getColor(
+                R.color.notification_ripple_untinted_color);
+        mDimmedAlpha = Color.alpha(mContext.getColor(
+                R.color.notification_material_background_dimmed_color));
+    }
+
+    private void initDimens() {
+        mHeadsUpAddStartLocation = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin_start);
+    }
+
+    @Override
+    public void onDensityOrFontScaleChanged() {
+        super.onDensityOrFontScaleChanged();
+        initDimens();
+    }
+
+    public void onUiModeChanged() {
+        updateColors();
+        initBackground();
+        updateBackgroundTint();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mBackgroundNormal = findViewById(R.id.backgroundNormal);
+        mFakeShadow = findViewById(R.id.fake_shadow);
+        mShadowHidden = mFakeShadow.getVisibility() != VISIBLE;
+        mBackgroundDimmed = findViewById(R.id.backgroundDimmed);
+        initBackground();
+        updateBackground();
+        updateBackgroundTint();
+        updateOutlineAlpha();
+    }
+
+    /**
+     * Sets the custom backgrounds on {@link #mBackgroundNormal} and {@link #mBackgroundDimmed}.
+     * This method can also be used to reload the backgrounds on both of those views, which can
+     * be useful in a configuration change.
+     */
+    protected void initBackground() {
+        mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
+        mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
+    }
+
+    private final Runnable mTapTimeoutRunnable = new Runnable() {
+        @Override
+        public void run() {
+            makeInactive(true /* animate */);
+        }
+    };
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (mNeedsDimming && ev.getActionMasked() == MotionEvent.ACTION_DOWN
+                && disallowSingleClick(ev) && !isTouchExplorationEnabled()) {
+            if (!mActivated) {
+                return true;
+            } else if (!mDoubleTapHelper.isWithinDoubleTapSlop(ev)) {
+                mBlockNextTouch = true;
+                makeInactive(true /* animate */);
+                return true;
+            }
+        }
+        return super.onInterceptTouchEvent(ev);
+    }
+
+    private boolean isTouchExplorationEnabled() {
+        return mAccessibilityManager.isTouchExplorationEnabled();
+    }
+
+    protected boolean disallowSingleClick(MotionEvent ev) {
+        return false;
+    }
+
+    protected boolean handleSlideBack() {
+        return false;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        boolean result;
+        if (mBlockNextTouch) {
+            mBlockNextTouch = false;
+            return false;
+        }
+        if (mNeedsDimming && !isTouchExplorationEnabled() && isInteractive()) {
+            boolean wasActivated = mActivated;
+            result = handleTouchEventDimmed(event);
+            if (wasActivated && result && event.getAction() == MotionEvent.ACTION_UP) {
+                removeCallbacks(mTapTimeoutRunnable);
+            }
+        } else {
+            result = super.onTouchEvent(event);
+        }
+        return result;
+    }
+
+    /**
+     * @return whether this view is interactive and can be double tapped
+     */
+    protected boolean isInteractive() {
+        return true;
+    }
+
+    @Override
+    public void drawableHotspotChanged(float x, float y) {
+        if (!mDimmed){
+            mBackgroundNormal.drawableHotspotChanged(x, y);
+        }
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+        if (mDimmed) {
+            mBackgroundDimmed.setState(getDrawableState());
+        } else {
+            mBackgroundNormal.setState(getDrawableState());
+        }
+    }
+
+    public void setRippleAllowed(boolean allowed) {
+        mBackgroundNormal.setPressedAllowed(allowed);
+    }
+
+    private boolean handleTouchEventDimmed(MotionEvent event) {
+        if (mNeedsDimming && !mDimmed) {
+            // We're actually dimmed, but our content isn't dimmable, let's ensure we have a ripple
+            super.onTouchEvent(event);
+        }
+        return mDoubleTapHelper.onTouchEvent(event, getActualHeight());
+    }
+
+    @Override
+    public boolean performClick() {
+        if (!mNeedsDimming || isTouchExplorationEnabled()) {
+            return super.performClick();
+        }
+        return false;
+    }
+
+    private void makeActive() {
+        mFalsingManager.onNotificationActive();
+        startActivateAnimation(false /* reverse */);
+        mActivated = true;
+        if (mOnActivatedListener != null) {
+            mOnActivatedListener.onActivated(this);
+        }
+    }
+
+    private void startActivateAnimation(final boolean reverse) {
+        if (!isAttachedToWindow()) {
+            return;
+        }
+        if (!isDimmable()) {
+            return;
+        }
+        int widthHalf = mBackgroundNormal.getWidth()/2;
+        int heightHalf = mBackgroundNormal.getActualHeight()/2;
+        float radius = (float) Math.sqrt(widthHalf*widthHalf + heightHalf*heightHalf);
+        Animator animator;
+        if (reverse) {
+            animator = ViewAnimationUtils.createCircularReveal(mBackgroundNormal,
+                    widthHalf, heightHalf, radius, 0);
+        } else {
+            animator = ViewAnimationUtils.createCircularReveal(mBackgroundNormal,
+                    widthHalf, heightHalf, 0, radius);
+        }
+        mBackgroundNormal.setVisibility(View.VISIBLE);
+        Interpolator interpolator;
+        Interpolator alphaInterpolator;
+        if (!reverse) {
+            interpolator = Interpolators.LINEAR_OUT_SLOW_IN;
+            alphaInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
+        } else {
+            interpolator = ACTIVATE_INVERSE_INTERPOLATOR;
+            alphaInterpolator = ACTIVATE_INVERSE_ALPHA_INTERPOLATOR;
+        }
+        animator.setInterpolator(interpolator);
+        animator.setDuration(ACTIVATE_ANIMATION_LENGTH);
+        if (reverse) {
+            mBackgroundNormal.setAlpha(1f);
+            animator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    updateBackground();
+                }
+            });
+            animator.start();
+        } else {
+            mBackgroundNormal.setAlpha(0.4f);
+            animator.start();
+        }
+        mBackgroundNormal.animate()
+                .alpha(reverse ? 0f : 1f)
+                .setInterpolator(alphaInterpolator)
+                .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        float animatedFraction = animation.getAnimatedFraction();
+                        if (reverse) {
+                            animatedFraction = 1.0f - animatedFraction;
+                        }
+                        setNormalBackgroundVisibilityAmount(animatedFraction);
+                    }
+                })
+                .setDuration(ACTIVATE_ANIMATION_LENGTH);
+    }
+
+    /**
+     * Cancels the hotspot and makes the notification inactive.
+     */
+    public void makeInactive(boolean animate) {
+        if (mActivated) {
+            mActivated = false;
+            if (mDimmed) {
+                if (animate) {
+                    startActivateAnimation(true /* reverse */);
+                } else {
+                    updateBackground();
+                }
+            }
+        }
+        if (mOnActivatedListener != null) {
+            mOnActivatedListener.onActivationReset(this);
+        }
+        removeCallbacks(mTapTimeoutRunnable);
+    }
+
+    public void setDimmed(boolean dimmed, boolean fade) {
+        mNeedsDimming = dimmed;
+        dimmed &= isDimmable();
+        if (mDimmed != dimmed) {
+            mDimmed = dimmed;
+            resetBackgroundAlpha();
+            if (fade) {
+                fadeDimmedBackground();
+            } else {
+                updateBackground();
+            }
+        }
+    }
+
+    public boolean isDimmable() {
+        return true;
+    }
+
+    public void setDark(boolean dark, boolean fade, long delay) {
+        super.setDark(dark, fade, delay);
+        if (mDark == dark) {
+            return;
+        }
+        mDark = dark;
+        updateBackground();
+        updateBackgroundTint(false);
+        if (!dark && fade && !shouldHideBackground()) {
+            fadeInFromDark(delay);
+        }
+        updateOutlineAlpha();
+    }
+
+    private void updateOutlineAlpha() {
+        if (mDark) {
+            setOutlineAlpha(0f);
+            return;
+        }
+        float alpha = NotificationStackScrollLayout.BACKGROUND_ALPHA_DIMMED;
+        alpha = (alpha + (1.0f - alpha) * mNormalBackgroundVisibilityAmount);
+        alpha *= mShadowAlpha;
+        if (mFadeInFromDarkAnimator != null) {
+            alpha *= mFadeInFromDarkAnimator.getAnimatedFraction();
+        }
+        setOutlineAlpha(alpha);
+    }
+
+    public void setNormalBackgroundVisibilityAmount(float normalBackgroundVisibilityAmount) {
+        mNormalBackgroundVisibilityAmount = normalBackgroundVisibilityAmount;
+        updateOutlineAlpha();
+    }
+
+    @Override
+    public void setBelowSpeedBump(boolean below) {
+        super.setBelowSpeedBump(below);
+        if (below != mIsBelowSpeedBump) {
+            mIsBelowSpeedBump = below;
+            updateBackgroundTint();
+            onBelowSpeedBumpChanged();
+        }
+    }
+
+    protected void onBelowSpeedBumpChanged() {
+    }
+
+    /**
+     * @return whether we are below the speed bump
+     */
+    public boolean isBelowSpeedBump() {
+        return mIsBelowSpeedBump;
+    }
+
+    /**
+     * Sets the tint color of the background
+     */
+    public void setTintColor(int color) {
+        setTintColor(color, false);
+    }
+
+    /**
+     * Sets the tint color of the background
+     */
+    public void setTintColor(int color, boolean animated) {
+        if (color != mBgTint) {
+            mBgTint = color;
+            updateBackgroundTint(animated);
+        }
+    }
+
+    @Override
+    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+        super.setDistanceToTopRoundness(distanceToTopRoundness);
+        mBackgroundNormal.setDistanceToTopRoundness(distanceToTopRoundness);
+        mBackgroundDimmed.setDistanceToTopRoundness(distanceToTopRoundness);
+    }
+
+    /**
+     * Set an override tint color that is used for the background.
+     *
+     * @param color the color that should be used to tint the background.
+     *              This can be {@link #NO_COLOR} if the tint should be normally computed.
+     * @param overrideAmount a value from 0 to 1 how much the override tint should be used. The
+     *                       background color will then be the interpolation between this and the
+     *                       regular background color, where 1 means the overrideTintColor is fully
+     *                       used and the background color not at all.
+     */
+    public void setOverrideTintColor(int color, float overrideAmount) {
+        if (mDark) {
+            color = NO_COLOR;
+            overrideAmount = 0;
+        }
+        mOverrideTint = color;
+        mOverrideAmount = overrideAmount;
+        int newColor = calculateBgColor();
+        setBackgroundTintColor(newColor);
+        if (!isDimmable() && mNeedsDimming) {
+           mBackgroundNormal.setDrawableAlpha((int) NotificationUtils.interpolate(255,
+                   mDimmedAlpha,
+                   overrideAmount));
+        } else {
+            mBackgroundNormal.setDrawableAlpha(255);
+        }
+    }
+
+    protected void updateBackgroundTint() {
+        updateBackgroundTint(false /* animated */);
+    }
+
+    private void updateBackgroundTint(boolean animated) {
+        if (mBackgroundColorAnimator != null) {
+            mBackgroundColorAnimator.cancel();
+        }
+        int rippleColor = getRippleColor();
+        mBackgroundDimmed.setRippleColor(rippleColor);
+        mBackgroundNormal.setRippleColor(rippleColor);
+        int color = calculateBgColor();
+        if (!animated) {
+            setBackgroundTintColor(color);
+        } else if (color != mCurrentBackgroundTint) {
+            mStartTint = mCurrentBackgroundTint;
+            mTargetTint = color;
+            mBackgroundColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
+            mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    int newColor = NotificationUtils.interpolateColors(mStartTint, mTargetTint,
+                            animation.getAnimatedFraction());
+                    setBackgroundTintColor(newColor);
+                }
+            });
+            mBackgroundColorAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+            mBackgroundColorAnimator.setInterpolator(Interpolators.LINEAR);
+            mBackgroundColorAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mBackgroundColorAnimator = null;
+                }
+            });
+            mBackgroundColorAnimator.start();
+        }
+    }
+
+    protected void setBackgroundTintColor(int color) {
+        if (color != mCurrentBackgroundTint) {
+            mCurrentBackgroundTint = color;
+            if (color == mNormalColor) {
+                // We don't need to tint a normal notification
+                color = 0;
+            }
+            mBackgroundDimmed.setTint(color);
+            mBackgroundNormal.setTint(color);
+        }
+    }
+
+    /**
+     * Fades in the background when exiting dark mode.
+     */
+    private void fadeInFromDark(long delay) {
+        final View background = mDimmed ? mBackgroundDimmed : mBackgroundNormal;
+        background.setAlpha(0f);
+        mBackgroundVisibilityUpdater.onAnimationUpdate(null);
+        background.animate()
+                .alpha(1f)
+                .setDuration(DARK_ANIMATION_LENGTH)
+                .setStartDelay(delay)
+                .setInterpolator(Interpolators.ALPHA_IN)
+                .setListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationCancel(Animator animation) {
+                        // Jump state if we are cancelled
+                        background.setAlpha(1f);
+                    }
+                })
+                .setUpdateListener(mBackgroundVisibilityUpdater)
+                .start();
+        mFadeInFromDarkAnimator = TimeAnimator.ofFloat(0.0f, 1.0f);
+        mFadeInFromDarkAnimator.setDuration(DARK_ANIMATION_LENGTH);
+        mFadeInFromDarkAnimator.setStartDelay(delay);
+        mFadeInFromDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+        mFadeInFromDarkAnimator.addListener(mFadeInEndListener);
+        mFadeInFromDarkAnimator.addUpdateListener(mUpdateOutlineListener);
+        mFadeInFromDarkAnimator.start();
+    }
+
+    /**
+     * Fades the background when the dimmed state changes.
+     */
+    private void fadeDimmedBackground() {
+        mBackgroundDimmed.animate().cancel();
+        mBackgroundNormal.animate().cancel();
+        if (mActivated) {
+            updateBackground();
+            return;
+        }
+        if (!shouldHideBackground()) {
+            if (mDimmed) {
+                mBackgroundDimmed.setVisibility(View.VISIBLE);
+            } else {
+                mBackgroundNormal.setVisibility(View.VISIBLE);
+            }
+        }
+        float startAlpha = mDimmed ? 1f : 0;
+        float endAlpha = mDimmed ? 0 : 1f;
+        int duration = BACKGROUND_ANIMATION_LENGTH_MS;
+        // Check whether there is already a background animation running.
+        if (mBackgroundAnimator != null) {
+            startAlpha = (Float) mBackgroundAnimator.getAnimatedValue();
+            duration = (int) mBackgroundAnimator.getCurrentPlayTime();
+            mBackgroundAnimator.removeAllListeners();
+            mBackgroundAnimator.cancel();
+            if (duration <= 0) {
+                updateBackground();
+                return;
+            }
+        }
+        mBackgroundNormal.setAlpha(startAlpha);
+        mBackgroundAnimator =
+                ObjectAnimator.ofFloat(mBackgroundNormal, View.ALPHA, startAlpha, endAlpha);
+        mBackgroundAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        mBackgroundAnimator.setDuration(duration);
+        mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                updateBackground();
+                mBackgroundAnimator = null;
+                if (mFadeInFromDarkAnimator == null) {
+                    mDimmedBackgroundFadeInAmount = -1;
+                }
+            }
+        });
+        mBackgroundAnimator.addUpdateListener(mBackgroundVisibilityUpdater);
+        mBackgroundAnimator.start();
+    }
+
+    protected void updateBackgroundAlpha(float transformationAmount) {
+        mBgAlpha =  isChildInGroup() && mDimmed ? transformationAmount : 1f;
+        if (mDimmedBackgroundFadeInAmount != -1) {
+            mBgAlpha *= mDimmedBackgroundFadeInAmount;
+        }
+        mBackgroundDimmed.setAlpha(mBgAlpha);
+    }
+
+    protected void resetBackgroundAlpha() {
+        updateBackgroundAlpha(0f /* transformationAmount */);
+    }
+
+    protected void updateBackground() {
+        cancelFadeAnimations();
+        if (shouldHideBackground()) {
+            mBackgroundDimmed.setVisibility(INVISIBLE);
+            mBackgroundNormal.setVisibility(mActivated ? VISIBLE : INVISIBLE);
+        } else if (mDimmed) {
+            // When groups are animating to the expanded state from the lockscreen, show the
+            // normal background instead of the dimmed background
+            final boolean dontShowDimmed = isGroupExpansionChanging() && isChildInGroup();
+            mBackgroundDimmed.setVisibility(dontShowDimmed ? View.INVISIBLE : View.VISIBLE);
+            mBackgroundNormal.setVisibility((mActivated || dontShowDimmed)
+                    ? View.VISIBLE
+                    : View.INVISIBLE);
+        } else {
+            mBackgroundDimmed.setVisibility(View.INVISIBLE);
+            mBackgroundNormal.setVisibility(View.VISIBLE);
+            mBackgroundNormal.setAlpha(1f);
+            removeCallbacks(mTapTimeoutRunnable);
+            // make in inactive to avoid it sticking around active
+            makeInactive(false /* animate */);
+        }
+        setNormalBackgroundVisibilityAmount(
+                mBackgroundNormal.getVisibility() == View.VISIBLE ? 1.0f : 0.0f);
+    }
+
+    protected void updateBackgroundClipping() {
+        mBackgroundNormal.setBottomAmountClips(!isChildInGroup());
+        mBackgroundDimmed.setBottomAmountClips(!isChildInGroup());
+    }
+
+    protected boolean shouldHideBackground() {
+        return mDark;
+    }
+
+    private void cancelFadeAnimations() {
+        if (mBackgroundAnimator != null) {
+            mBackgroundAnimator.cancel();
+        }
+        mBackgroundDimmed.animate().cancel();
+        mBackgroundNormal.animate().cancel();
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        setPivotX(getWidth() / 2);
+    }
+
+    @Override
+    public void setActualHeight(int actualHeight, boolean notifyListeners) {
+        super.setActualHeight(actualHeight, notifyListeners);
+        setPivotY(actualHeight / 2);
+        mBackgroundNormal.setActualHeight(actualHeight);
+        mBackgroundDimmed.setActualHeight(actualHeight);
+    }
+
+    @Override
+    public void setClipTopAmount(int clipTopAmount) {
+        super.setClipTopAmount(clipTopAmount);
+        mBackgroundNormal.setClipTopAmount(clipTopAmount);
+        mBackgroundDimmed.setClipTopAmount(clipTopAmount);
+    }
+
+    @Override
+    public void setClipBottomAmount(int clipBottomAmount) {
+        super.setClipBottomAmount(clipBottomAmount);
+        mBackgroundNormal.setClipBottomAmount(clipBottomAmount);
+        mBackgroundDimmed.setClipBottomAmount(clipBottomAmount);
+    }
+
+    @Override
+    public void performRemoveAnimation(long duration, long delay,
+            float translationDirection, boolean isHeadsUpAnimation, float endLocation,
+            Runnable onFinishedRunnable, AnimatorListenerAdapter animationListener) {
+        enableAppearDrawing(true);
+        mIsHeadsUpAnimation = isHeadsUpAnimation;
+        mHeadsUpLocation = endLocation;
+        if (mDrawingAppearAnimation) {
+            startAppearAnimation(false /* isAppearing */, translationDirection,
+                    delay, duration, onFinishedRunnable, animationListener);
+        } else if (onFinishedRunnable != null) {
+            onFinishedRunnable.run();
+        }
+    }
+
+    @Override
+    public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) {
+        enableAppearDrawing(true);
+        mIsHeadsUpAnimation = isHeadsUpAppear;
+        mHeadsUpLocation = mHeadsUpAddStartLocation;
+        if (mDrawingAppearAnimation) {
+            startAppearAnimation(true /* isAppearing */, isHeadsUpAppear ? 0.0f : -1.0f, delay,
+                    duration, null, null);
+        }
+    }
+
+    private void startAppearAnimation(boolean isAppearing, float translationDirection, long delay,
+            long duration, final Runnable onFinishedRunnable,
+            AnimatorListenerAdapter animationListener) {
+        cancelAppearAnimation();
+        mAnimationTranslationY = translationDirection * getActualHeight();
+        if (mAppearAnimationFraction == -1.0f) {
+            // not initialized yet, we start anew
+            if (isAppearing) {
+                mAppearAnimationFraction = 0.0f;
+                mAppearAnimationTranslation = mAnimationTranslationY;
+            } else {
+                mAppearAnimationFraction = 1.0f;
+                mAppearAnimationTranslation = 0;
+            }
+        }
+        mIsAppearing = isAppearing;
+
+        float targetValue;
+        if (isAppearing) {
+            mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
+            mCurrentAlphaInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
+            targetValue = 1.0f;
+        } else {
+            mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+            mCurrentAlphaInterpolator = mSlowOutLinearInInterpolator;
+            targetValue = 0.0f;
+        }
+        mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction,
+                targetValue);
+        mAppearAnimator.setInterpolator(Interpolators.LINEAR);
+        mAppearAnimator.setDuration(
+                (long) (duration * Math.abs(mAppearAnimationFraction - targetValue)));
+        mAppearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                mAppearAnimationFraction = (float) animation.getAnimatedValue();
+                updateAppearAnimationAlpha();
+                updateAppearRect();
+                invalidate();
+            }
+        });
+        if (animationListener != null) {
+            mAppearAnimator.addListener(animationListener);
+        }
+        if (delay > 0) {
+            // we need to apply the initial state already to avoid drawn frames in the wrong state
+            updateAppearAnimationAlpha();
+            updateAppearRect();
+            mAppearAnimator.setStartDelay(delay);
+        }
+        mAppearAnimator.addListener(new AnimatorListenerAdapter() {
+            private boolean mWasCancelled;
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (onFinishedRunnable != null) {
+                    onFinishedRunnable.run();
+                }
+                if (!mWasCancelled) {
+                    enableAppearDrawing(false);
+                    onAppearAnimationFinished(isAppearing);
+                }
+            }
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mWasCancelled = false;
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mWasCancelled = true;
+            }
+        });
+        mAppearAnimator.start();
+    }
+
+    protected void onAppearAnimationFinished(boolean wasAppearing) {
+    }
+
+    private void cancelAppearAnimation() {
+        if (mAppearAnimator != null) {
+            mAppearAnimator.cancel();
+            mAppearAnimator = null;
+        }
+    }
+
+    public void cancelAppearDrawing() {
+        cancelAppearAnimation();
+        enableAppearDrawing(false);
+    }
+
+    private void updateAppearRect() {
+        float inverseFraction = (1.0f - mAppearAnimationFraction);
+        float translationFraction = mCurrentAppearInterpolator.getInterpolation(inverseFraction);
+        float translateYTotalAmount = translationFraction * mAnimationTranslationY;
+        mAppearAnimationTranslation = translateYTotalAmount;
+
+        // handle width animation
+        float widthFraction = (inverseFraction - (1.0f - HORIZONTAL_ANIMATION_START))
+                / (HORIZONTAL_ANIMATION_START - HORIZONTAL_ANIMATION_END);
+        widthFraction = Math.min(1.0f, Math.max(0.0f, widthFraction));
+        widthFraction = mCurrentAppearInterpolator.getInterpolation(widthFraction);
+        float startWidthFraction = HORIZONTAL_COLLAPSED_REST_PARTIAL;
+        if (mIsHeadsUpAnimation && !mIsAppearing) {
+            startWidthFraction = 0;
+        }
+        float width = MathUtils.lerp(startWidthFraction, 1.0f, 1.0f - widthFraction)
+                        * getWidth();
+        float left;
+        float right;
+        if (mIsHeadsUpAnimation) {
+            left = MathUtils.lerp(mHeadsUpLocation, 0, 1.0f - widthFraction);
+            right = left + width;
+        } else {
+            left = getWidth() * 0.5f - width / 2.0f;
+            right = getWidth() - left;
+        }
+
+        // handle top animation
+        float heightFraction = (inverseFraction - (1.0f - VERTICAL_ANIMATION_START)) /
+                VERTICAL_ANIMATION_START;
+        heightFraction = Math.max(0.0f, heightFraction);
+        heightFraction = mCurrentAppearInterpolator.getInterpolation(heightFraction);
+
+        float top;
+        float bottom;
+        final int actualHeight = getActualHeight();
+        if (mAnimationTranslationY > 0.0f) {
+            bottom = actualHeight - heightFraction * mAnimationTranslationY * 0.1f
+                    - translateYTotalAmount;
+            top = bottom * heightFraction;
+        } else {
+            top = heightFraction * (actualHeight + mAnimationTranslationY) * 0.1f -
+                    translateYTotalAmount;
+            bottom = actualHeight * (1 - heightFraction) + top * heightFraction;
+        }
+        mAppearAnimationRect.set(left, top, right, bottom);
+        setOutlineRect(left, top + mAppearAnimationTranslation, right,
+                bottom + mAppearAnimationTranslation);
+    }
+
+    private void updateAppearAnimationAlpha() {
+        float contentAlphaProgress = mAppearAnimationFraction;
+        contentAlphaProgress = contentAlphaProgress / (1.0f - ALPHA_ANIMATION_END);
+        contentAlphaProgress = Math.min(1.0f, contentAlphaProgress);
+        contentAlphaProgress = mCurrentAlphaInterpolator.getInterpolation(contentAlphaProgress);
+        setContentAlpha(contentAlphaProgress);
+    }
+
+    private void setContentAlpha(float contentAlpha) {
+        View contentView = getContentView();
+        if (contentView.hasOverlappingRendering()) {
+            int layerType = contentAlpha == 0.0f || contentAlpha == 1.0f ? LAYER_TYPE_NONE
+                    : LAYER_TYPE_HARDWARE;
+            int currentLayerType = contentView.getLayerType();
+            if (currentLayerType != layerType) {
+                contentView.setLayerType(layerType, null);
+            }
+        }
+        contentView.setAlpha(contentAlpha);
+    }
+
+    @Override
+    protected void applyRoundness() {
+        super.applyRoundness();
+        applyBackgroundRoundness(getCurrentBackgroundRadiusTop(),
+                getCurrentBackgroundRadiusBottom());
+    }
+
+    protected void applyBackgroundRoundness(float topRadius, float bottomRadius) {
+        mBackgroundDimmed.setRoundness(topRadius, bottomRadius);
+        mBackgroundNormal.setRoundness(topRadius, bottomRadius);
+    }
+
+    @Override
+    protected void setBackgroundTop(int backgroundTop) {
+        mBackgroundDimmed.setBackgroundTop(backgroundTop);
+        mBackgroundNormal.setBackgroundTop(backgroundTop);
+    }
+
+    protected abstract View getContentView();
+
+    public int calculateBgColor() {
+        return calculateBgColor(true /* withTint */, true /* withOverRide */);
+    }
+
+    @Override
+    protected boolean childNeedsClipping(View child) {
+        if (child instanceof NotificationBackgroundView && isClippingNeeded()) {
+            return true;
+        }
+        return super.childNeedsClipping(child);
+    }
+
+    /**
+     * @param withTint should a possible tint be factored in?
+     * @param withOverRide should the value be interpolated with {@link #mOverrideTint}
+     * @return the calculated background color
+     */
+    private int calculateBgColor(boolean withTint, boolean withOverRide) {
+        if (withTint && mDark) {
+            return getContext().getColor(R.color.notification_material_background_dark_color);
+        }
+        if (withOverRide && mOverrideTint != NO_COLOR) {
+            int defaultTint = calculateBgColor(withTint, false);
+            return NotificationUtils.interpolateColors(defaultTint, mOverrideTint, mOverrideAmount);
+        }
+        if (withTint && mBgTint != NO_COLOR) {
+            return mBgTint;
+        } else {
+            return mNormalColor;
+        }
+    }
+
+    protected int getRippleColor() {
+        if (mBgTint != 0) {
+            return mTintedRippleColor;
+        } else {
+            return mNormalRippleColor;
+        }
+    }
+
+    /**
+     * When we draw the appear animation, we render the view in a bitmap and render this bitmap
+     * as a shader of a rect. This call creates the Bitmap and switches the drawing mode,
+     * such that the normal drawing of the views does not happen anymore.
+     *
+     * @param enable Should it be enabled.
+     */
+    private void enableAppearDrawing(boolean enable) {
+        if (enable != mDrawingAppearAnimation) {
+            mDrawingAppearAnimation = enable;
+            if (!enable) {
+                setContentAlpha(1.0f);
+                mAppearAnimationFraction = -1;
+                setOutlineRect(null);
+            }
+            invalidate();
+        }
+    }
+
+    public boolean isDrawingAppearAnimation() {
+        return mDrawingAppearAnimation;
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        if (mDrawingAppearAnimation) {
+            canvas.save();
+            canvas.translate(0, mAppearAnimationTranslation);
+        }
+        super.dispatchDraw(canvas);
+        if (mDrawingAppearAnimation) {
+            canvas.restore();
+        }
+    }
+
+    public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
+        mOnActivatedListener = onActivatedListener;
+    }
+
+    public boolean hasSameBgColor(ActivatableNotificationView otherView) {
+        return calculateBgColor() == otherView.calculateBgColor();
+    }
+
+    @Override
+    public float getShadowAlpha() {
+        return mShadowAlpha;
+    }
+
+    @Override
+    public void setShadowAlpha(float shadowAlpha) {
+        if (shadowAlpha != mShadowAlpha) {
+            mShadowAlpha = shadowAlpha;
+            updateOutlineAlpha();
+        }
+    }
+
+    @Override
+    public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
+            int outlineTranslation) {
+        boolean hiddenBefore = mShadowHidden;
+        mShadowHidden = shadowIntensity == 0.0f;
+        if (!mShadowHidden || !hiddenBefore) {
+            mFakeShadow.setFakeShadowTranslationZ(shadowIntensity * (getTranslationZ()
+                            + FakeShadowView.SHADOW_SIBLING_TRESHOLD), outlineAlpha, shadowYEnd,
+                    outlineTranslation);
+        }
+    }
+
+    public int getBackgroundColorWithoutTint() {
+        return calculateBgColor(false /* withTint */, false /* withOverride */);
+    }
+
+    public boolean isPinned() {
+        return false;
+    }
+
+    public boolean isHeadsUpAnimatingAway() {
+        return false;
+    }
+
+    public interface OnActivatedListener {
+        void onActivated(ActivatableNotificationView view);
+        void onActivationReset(ActivatableNotificationView view);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
new file mode 100644
index 0000000..10fc990
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+
+/**
+ * The guts of a notification revealed when performing a long press.
+ */
+public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsContent {
+    private static final String TAG = "AppOpsGuts";
+
+    private PackageManager mPm;
+
+    private String mPkg;
+    private String mAppName;
+    private int mAppUid;
+    private StatusBarNotification mSbn;
+    private ArraySet<Integer> mAppOps;
+    private MetricsLogger mMetricsLogger;
+    private OnSettingsClickListener mOnSettingsClickListener;
+    private NotificationGuts mGutsContainer;
+
+    private OnClickListener mOnOk = v -> {
+        closeControls(v);
+    };
+
+    public AppOpsInfo(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public interface OnSettingsClickListener {
+        void onClick(View v, String pkg, int uid, ArraySet<Integer> ops);
+    }
+
+    public void bindGuts(final PackageManager pm,
+            final OnSettingsClickListener onSettingsClick,
+            final StatusBarNotification sbn,
+            ArraySet<Integer> activeOps) {
+        mPkg = sbn.getPackageName();
+        mSbn = sbn;
+        mPm = pm;
+        mAppName = mPkg;
+        mOnSettingsClickListener = onSettingsClick;
+        mAppOps = activeOps;
+
+        bindHeader();
+        bindPrompt();
+        bindButtons();
+
+        mMetricsLogger = new MetricsLogger();
+        mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, true);
+    }
+
+    private void bindHeader() {
+        // Package name
+        Drawable pkgicon = null;
+        ApplicationInfo info;
+        try {
+            info = mPm.getApplicationInfo(mPkg,
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES
+                            | PackageManager.MATCH_DISABLED_COMPONENTS
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+            if (info != null) {
+                mAppUid = mSbn.getUid();
+                mAppName = String.valueOf(mPm.getApplicationLabel(info));
+                pkgicon = mPm.getApplicationIcon(info);
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            // app is gone, just show package name and generic icon
+            pkgicon = mPm.getDefaultActivityIcon();
+        }
+        ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
+        ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
+    }
+
+    private void bindPrompt() {
+        final TextView prompt = findViewById(R.id.prompt);
+        prompt.setText(getPrompt());
+    }
+
+    private void bindButtons() {
+        View settings =  findViewById(R.id.settings);
+        settings.setOnClickListener((View view) -> {
+            mOnSettingsClickListener.onClick(view, mPkg, mAppUid, mAppOps);
+        });
+        TextView ok = findViewById(R.id.ok);
+        ok.setOnClickListener(mOnOk);
+    }
+
+    private String getPrompt() {
+        if (mAppOps == null || mAppOps.size() == 0) {
+            return "";
+        } else if (mAppOps.size() == 1) {
+            if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
+                return mContext.getString(R.string.appops_camera);
+            } else if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
+                return mContext.getString(R.string.appops_microphone);
+            } else {
+                return mContext.getString(R.string.appops_overlay);
+            }
+        } else if (mAppOps.size() == 2) {
+            if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
+                if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
+                    return mContext.getString(R.string.appops_camera_mic);
+                } else {
+                    return mContext.getString(R.string.appops_camera_overlay);
+                }
+            } else {
+                return mContext.getString(R.string.appops_mic_overlay);
+            }
+        } else {
+            return mContext.getString(R.string.appops_camera_mic_overlay);
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        if (mGutsContainer != null &&
+                event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+            if (mGutsContainer.isExposed()) {
+                event.getText().add(mContext.getString(
+                        R.string.notification_channel_controls_opened_accessibility, mAppName));
+            } else {
+                event.getText().add(mContext.getString(
+                        R.string.notification_channel_controls_closed_accessibility, mAppName));
+            }
+        }
+    }
+
+    private void closeControls(View v) {
+        mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
+        int[] parentLoc = new int[2];
+        int[] targetLoc = new int[2];
+        mGutsContainer.getLocationOnScreen(parentLoc);
+        v.getLocationOnScreen(targetLoc);
+        final int centerX = v.getWidth() / 2;
+        final int centerY = v.getHeight() / 2;
+        final int x = targetLoc[0] - parentLoc[0] + centerX;
+        final int y = targetLoc[1] - parentLoc[1] + centerY;
+        mGutsContainer.closeControls(x, y, false, false);
+    }
+
+    @Override
+    public void setGutsParent(NotificationGuts guts) {
+        mGutsContainer = guts;
+    }
+
+    @Override
+    public boolean willBeRemoved() {
+        return false;
+    }
+
+    @Override
+    public boolean shouldBeSaved() {
+        return false;
+    }
+
+    @Override
+    public View getContentView() {
+        return this;
+    }
+
+    @Override
+    public boolean handleCloseControls(boolean save, boolean force) {
+        return false;
+    }
+
+    @Override
+    public int getActualHeight() {
+        return getHeight();
+    }
+}
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
new file mode 100644
index 0000000..67db68d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -0,0 +1,3011 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater.InflationCallback;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Path;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.SystemClock;
+import android.os.Bundle;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.Property;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.NotificationHeaderView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewStub;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.widget.Chronometer;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.RemoteViews;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.util.ContrastColorUtil;
+import com.android.internal.widget.CachingIconView;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.logging.NotificationCounters;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.notification.stack.AmbientState;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
+import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
+import com.android.systemui.statusbar.notification.stack.StackScrollState;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
+
+/**
+ * View representing a notification item - this can be either the individual child notification or
+ * the group summary (which contains 1 or more child notifications).
+ */
+public class ExpandableNotificationRow extends ActivatableNotificationView
+        implements PluginListener<NotificationMenuRowPlugin> {
+
+    private static final boolean DEBUG = false;
+    private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
+    private static final int COLORED_DIVIDER_ALPHA = 0x7B;
+    private static final int MENU_VIEW_INDEX = 0;
+    private static final String TAG = "ExpandableNotifRow";
+    public static final float DEFAULT_HEADER_VISIBLE_AMOUNT = 1.0f;
+
+    /**
+     * Listener for when {@link ExpandableNotificationRow} is laid out.
+     */
+    public interface LayoutListener {
+        void onLayout();
+    }
+
+    private LayoutListener mLayoutListener;
+    private boolean mDark;
+    private boolean mLowPriorityStateUpdated;
+    private final NotificationInflater mNotificationInflater;
+    private int mIconTransformContentShift;
+    private int mIconTransformContentShiftNoIcon;
+    private int mMaxHeadsUpHeightBeforeN;
+    private int mMaxHeadsUpHeightBeforeP;
+    private int mMaxHeadsUpHeight;
+    private int mMaxHeadsUpHeightIncreased;
+    private int mNotificationMinHeightBeforeN;
+    private int mNotificationMinHeightBeforeP;
+    private int mNotificationMinHeight;
+    private int mNotificationMinHeightLarge;
+    private int mNotificationMaxHeight;
+    private int mNotificationAmbientHeight;
+    private int mIncreasedPaddingBetweenElements;
+    private int mNotificationLaunchHeight;
+    private boolean mMustStayOnScreen;
+
+    /** Does this row contain layouts that can adapt to row expansion */
+    private boolean mExpandable;
+    /** Has the user actively changed the expansion state of this row */
+    private boolean mHasUserChangedExpansion;
+    /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
+    private boolean mUserExpanded;
+    /** Whether the blocking helper is showing on this notification (even if dismissed) */
+    private boolean mIsBlockingHelperShowing;
+
+    /**
+     * Has this notification been expanded while it was pinned
+     */
+    private boolean mExpandedWhenPinned;
+    /** Is the user touching this row */
+    private boolean mUserLocked;
+    /** Are we showing the "public" version */
+    private boolean mShowingPublic;
+    private boolean mSensitive;
+    private boolean mSensitiveHiddenInGeneral;
+    private boolean mShowingPublicInitialized;
+    private boolean mHideSensitiveForIntrinsicHeight;
+    private float mHeaderVisibleAmount = DEFAULT_HEADER_VISIBLE_AMOUNT;
+
+    /**
+     * Is this notification expanded by the system. The expansion state can be overridden by the
+     * user expansion.
+     */
+    private boolean mIsSystemExpanded;
+
+    /**
+     * Whether the notification is on the keyguard and the expansion is disabled.
+     */
+    private boolean mOnKeyguard;
+
+    private Animator mTranslateAnim;
+    private ArrayList<View> mTranslateableViews;
+    private NotificationContentView mPublicLayout;
+    private NotificationContentView mPrivateLayout;
+    private NotificationContentView[] mLayouts;
+    private int mNotificationColor;
+    private ExpansionLogger mLogger;
+    private String mLoggingKey;
+    private NotificationGuts mGuts;
+    private NotificationData.Entry mEntry;
+    private StatusBarNotification mStatusBarNotification;
+    private String mAppName;
+    private boolean mIsHeadsUp;
+    private boolean mLastChronometerRunning = true;
+    private ViewStub mChildrenContainerStub;
+    private NotificationGroupManager mGroupManager;
+    private boolean mChildrenExpanded;
+    private boolean mIsSummaryWithChildren;
+    private NotificationChildrenContainer mChildrenContainer;
+    private NotificationMenuRowPlugin mMenuRow;
+    private ViewStub mGutsStub;
+    private boolean mIsSystemChildExpanded;
+    private boolean mIsPinned;
+    private FalsingManager mFalsingManager;
+    private boolean mExpandAnimationRunning;
+    private AboveShelfChangedListener mAboveShelfChangedListener;
+    private HeadsUpManager mHeadsUpManager;
+    private Consumer<Boolean> mHeadsUpAnimatingAwayListener;
+    private boolean mChildIsExpanding;
+
+    private boolean mJustClicked;
+    private boolean mIconAnimationRunning;
+    private boolean mShowNoBackground;
+    private ExpandableNotificationRow mNotificationParent;
+    private OnExpandClickListener mOnExpandClickListener;
+    private View.OnClickListener mOnAppOpsClickListener;
+
+    // Listener will be called when receiving a long click event.
+    // Use #setLongPressPosition to optionally assign positional data with the long press.
+    private LongPressListener mLongPressListener;
+
+    private boolean mGroupExpansionChanging;
+
+    /**
+     * A supplier that returns true if keyguard is secure.
+     */
+    private BooleanSupplier mSecureStateProvider;
+
+    /**
+     * Whether or not a notification that is not part of a group of notifications can be manually
+     * expanded by the user.
+     */
+    private boolean mEnableNonGroupedNotificationExpand;
+
+    /**
+     * Whether or not to update the background of the header of the notification when its expanded.
+     * If {@code true}, the header background will disappear when expanded.
+     */
+    private boolean mShowGroupBackgroundWhenExpanded;
+
+    private OnClickListener mExpandClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (!shouldShowPublic() && (!mIsLowPriority || isExpanded())
+                    && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
+                mGroupExpansionChanging = true;
+                final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
+                boolean nowExpanded = mGroupManager.toggleGroupExpansion(mStatusBarNotification);
+                mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
+                        nowExpanded);
+                onExpansionChanged(true /* userAction */, wasExpanded);
+            } else if (mEnableNonGroupedNotificationExpand) {
+                if (v.isAccessibilityFocused()) {
+                    mPrivateLayout.setFocusOnVisibilityChange();
+                }
+                boolean nowExpanded;
+                if (isPinned()) {
+                    nowExpanded = !mExpandedWhenPinned;
+                    mExpandedWhenPinned = nowExpanded;
+                } else {
+                    nowExpanded = !isExpanded();
+                    setUserExpanded(nowExpanded);
+                }
+                notifyHeightChanged(true);
+                mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_EXPANDER,
+                        nowExpanded);
+            }
+        }
+    };
+    private boolean mForceUnlocked;
+    private boolean mDismissed;
+    private boolean mKeepInParent;
+    private boolean mRemoved;
+    private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT =
+            new FloatProperty<ExpandableNotificationRow>("translate") {
+                @Override
+                public void setValue(ExpandableNotificationRow object, float value) {
+                    object.setTranslation(value);
+                }
+
+                @Override
+                public Float get(ExpandableNotificationRow object) {
+                    return object.getTranslation();
+                }
+            };
+    private OnClickListener mOnClickListener;
+    private boolean mHeadsupDisappearRunning;
+    private View mChildAfterViewWhenDismissed;
+    private View mGroupParentWhenDismissed;
+    private boolean mRefocusOnDismiss;
+    private float mContentTransformationAmount;
+    private boolean mIconsVisible = true;
+    private boolean mAboveShelf;
+    private boolean mShowAmbient;
+    private boolean mIsLastChild;
+    private Runnable mOnDismissRunnable;
+    private boolean mIsLowPriority;
+    private boolean mIsColorized;
+    private boolean mUseIncreasedCollapsedHeight;
+    private boolean mUseIncreasedHeadsUpHeight;
+    private float mTranslationWhenRemoved;
+    private boolean mWasChildInGroupWhenRemoved;
+    private int mNotificationColorAmbient;
+    private NotificationViewState mNotificationViewState;
+
+    private SystemNotificationAsyncTask mSystemNotificationAsyncTask =
+            new SystemNotificationAsyncTask();
+
+    /**
+     * Returns whether the given {@code statusBarNotification} is a system notification.
+     * <b>Note</b>, this should be run in the background thread if possible as it makes multiple IPC
+     * calls.
+     */
+    private static Boolean isSystemNotification(
+            Context context, StatusBarNotification statusBarNotification) {
+        PackageManager packageManager = StatusBar.getPackageManagerForUser(
+                context, statusBarNotification.getUser().getIdentifier());
+        Boolean isSystemNotification = null;
+
+        try {
+            PackageInfo packageInfo = packageManager.getPackageInfo(
+                    statusBarNotification.getPackageName(), PackageManager.GET_SIGNATURES);
+
+            isSystemNotification =
+                    com.android.settingslib.Utils.isSystemPackage(
+                            context.getResources(), packageManager, packageInfo);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "cacheIsSystemNotification: Could not find package info");
+        }
+        return isSystemNotification;
+    }
+
+    @Override
+    public boolean isGroupExpansionChanging() {
+        if (isChildInGroup()) {
+            return mNotificationParent.isGroupExpansionChanging();
+        }
+        return mGroupExpansionChanging;
+    }
+
+    public void setGroupExpansionChanging(boolean changing) {
+        mGroupExpansionChanging = changing;
+    }
+
+    @Override
+    public void setActualHeightAnimating(boolean animating) {
+        if (mPrivateLayout != null) {
+            mPrivateLayout.setContentHeightAnimating(animating);
+        }
+    }
+
+    public NotificationContentView getPrivateLayout() {
+        return mPrivateLayout;
+    }
+
+    public NotificationContentView getPublicLayout() {
+        return mPublicLayout;
+    }
+
+    public void setIconAnimationRunning(boolean running) {
+        for (NotificationContentView l : mLayouts) {
+            setIconAnimationRunning(running, l);
+        }
+        if (mIsSummaryWithChildren) {
+            setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView());
+            setIconAnimationRunningForChild(running, mChildrenContainer.getLowPriorityHeaderView());
+            List<ExpandableNotificationRow> notificationChildren =
+                    mChildrenContainer.getNotificationChildren();
+            for (int i = 0; i < notificationChildren.size(); i++) {
+                ExpandableNotificationRow child = notificationChildren.get(i);
+                child.setIconAnimationRunning(running);
+            }
+        }
+        mIconAnimationRunning = running;
+    }
+
+    private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
+        if (layout != null) {
+            View contractedChild = layout.getContractedChild();
+            View expandedChild = layout.getExpandedChild();
+            View headsUpChild = layout.getHeadsUpChild();
+            setIconAnimationRunningForChild(running, contractedChild);
+            setIconAnimationRunningForChild(running, expandedChild);
+            setIconAnimationRunningForChild(running, headsUpChild);
+        }
+    }
+
+    private void setIconAnimationRunningForChild(boolean running, View child) {
+        if (child != null) {
+            ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
+            setIconRunning(icon, running);
+            ImageView rightIcon = (ImageView) child.findViewById(
+                    com.android.internal.R.id.right_icon);
+            setIconRunning(rightIcon, running);
+        }
+    }
+
+    private void setIconRunning(ImageView imageView, boolean running) {
+        if (imageView != null) {
+            Drawable drawable = imageView.getDrawable();
+            if (drawable instanceof AnimationDrawable) {
+                AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
+                if (running) {
+                    animationDrawable.start();
+                } else {
+                    animationDrawable.stop();
+                }
+            } else if (drawable instanceof AnimatedVectorDrawable) {
+                AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
+                if (running) {
+                    animationDrawable.start();
+                } else {
+                    animationDrawable.stop();
+                }
+            }
+        }
+    }
+
+    public void updateNotification(NotificationData.Entry entry) {
+        mEntry = entry;
+        mStatusBarNotification = entry.notification;
+        mNotificationInflater.inflateNotificationViews();
+
+        cacheIsSystemNotification();
+    }
+
+    /**
+     * Caches whether or not this row contains a system notification. Note, this is only cached
+     * once per notification as the packageInfo can't technically change for a notification row.
+     */
+    private void cacheIsSystemNotification() {
+        if (mEntry != null && mEntry.mIsSystemNotification == null) {
+            if (mSystemNotificationAsyncTask.getStatus() == AsyncTask.Status.PENDING) {
+                // Run async task once, only if it hasn't already been executed. Note this is
+                // executed in serial - no need to parallelize this small task.
+                mSystemNotificationAsyncTask.execute();
+            }
+        }
+    }
+
+    /**
+     * Returns whether this row is considered non-blockable (i.e. it's a non-blockable system notif
+     * or is in a whitelist).
+     */
+    public boolean getIsNonblockable() {
+        boolean isNonblockable = Dependency.get(NotificationBlockingHelperManager.class)
+                .isNonblockable(mStatusBarNotification.getPackageName(),
+                        mEntry.channel.getId());
+
+        // If the SystemNotifAsyncTask hasn't finished running or retrieved a value, we'll try once
+        // again, but in-place on the main thread this time. This should rarely ever get called.
+        if (mEntry != null && mEntry.mIsSystemNotification == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Retrieving isSystemNotification on main thread");
+            }
+            mSystemNotificationAsyncTask.cancel(true /* mayInterruptIfRunning */);
+            mEntry.mIsSystemNotification = isSystemNotification(mContext, mStatusBarNotification);
+        }
+
+        if (!isNonblockable && mEntry != null && mEntry.mIsSystemNotification != null) {
+            if (mEntry.mIsSystemNotification) {
+                if (mEntry.channel != null
+                        && !mEntry.channel.isBlockableSystem()) {
+                    isNonblockable = true;
+                }
+            }
+        }
+        return isNonblockable;
+    }
+
+    public void onNotificationUpdated() {
+        for (NotificationContentView l : mLayouts) {
+            l.onNotificationUpdated(mEntry);
+        }
+        mIsColorized = mStatusBarNotification.getNotification().isColorized();
+        mShowingPublicInitialized = false;
+        updateNotificationColor();
+        if (mMenuRow != null) {
+            mMenuRow.onNotificationUpdated(mStatusBarNotification);
+            mMenuRow.setAppName(mAppName);
+        }
+        if (mIsSummaryWithChildren) {
+            mChildrenContainer.recreateNotificationHeader(mExpandClickListener);
+            mChildrenContainer.onNotificationUpdated();
+        }
+        if (mIconAnimationRunning) {
+            setIconAnimationRunning(true);
+        }
+        if (mNotificationParent != null) {
+            mNotificationParent.updateChildrenHeaderAppearance();
+        }
+        onChildrenCountChanged();
+        // The public layouts expand button is always visible
+        mPublicLayout.updateExpandButtons(true);
+        updateLimits();
+        updateIconVisibilities();
+        updateShelfIconColor();
+        updateRippleAllowed();
+    }
+
+    @VisibleForTesting
+    void updateShelfIconColor() {
+        StatusBarIconView expandedIcon = mEntry.expandedIcon;
+        boolean isPreL = Boolean.TRUE.equals(expandedIcon.getTag(R.id.icon_is_pre_L));
+        boolean colorize = !isPreL || NotificationUtils.isGrayscale(expandedIcon,
+                ContrastColorUtil.getInstance(mContext));
+        int color = StatusBarIconView.NO_COLOR;
+        if (colorize) {
+            NotificationHeaderView header = getVisibleNotificationHeader();
+            if (header != null) {
+                color = header.getOriginalIconColor();
+            } else {
+                color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded(),
+                        getBackgroundColorWithoutTint());
+            }
+        }
+        expandedIcon.setStaticDrawableColor(color);
+    }
+
+    public void setAboveShelfChangedListener(AboveShelfChangedListener aboveShelfChangedListener) {
+        mAboveShelfChangedListener = aboveShelfChangedListener;
+    }
+
+    /**
+     * Sets a supplier that can determine whether the keyguard is secure or not.
+     * @param secureStateProvider A function that returns true if keyguard is secure.
+     */
+    public void setSecureStateProvider(BooleanSupplier secureStateProvider) {
+        mSecureStateProvider = secureStateProvider;
+    }
+
+    @Override
+    public boolean isDimmable() {
+        if (!getShowingLayout().isDimmable()) {
+            return false;
+        }
+        return super.isDimmable();
+    }
+
+    private void updateLimits() {
+        for (NotificationContentView l : mLayouts) {
+            updateLimitsForView(l);
+        }
+    }
+
+    private void updateLimitsForView(NotificationContentView layout) {
+        boolean customView = layout.getContractedChild().getId()
+                != com.android.internal.R.id.status_bar_latest_event_content;
+        boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
+        boolean beforeP = mEntry.targetSdk < Build.VERSION_CODES.P;
+        int minHeight;
+        if (customView && beforeP && !mIsSummaryWithChildren) {
+            minHeight = beforeN ? mNotificationMinHeightBeforeN : mNotificationMinHeightBeforeP;
+        } else if (mUseIncreasedCollapsedHeight && layout == mPrivateLayout) {
+            minHeight = mNotificationMinHeightLarge;
+        } else {
+            minHeight = mNotificationMinHeight;
+        }
+        boolean headsUpCustom = layout.getHeadsUpChild() != null &&
+                layout.getHeadsUpChild().getId()
+                        != com.android.internal.R.id.status_bar_latest_event_content;
+        int headsUpHeight;
+        if (headsUpCustom && beforeP) {
+            headsUpHeight = beforeN ? mMaxHeadsUpHeightBeforeN : mMaxHeadsUpHeightBeforeP;
+        } else if (mUseIncreasedHeadsUpHeight && layout == mPrivateLayout) {
+            headsUpHeight = mMaxHeadsUpHeightIncreased;
+        } else {
+            headsUpHeight = mMaxHeadsUpHeight;
+        }
+        NotificationViewWrapper headsUpWrapper = layout.getVisibleWrapper(
+                NotificationContentView.VISIBLE_TYPE_HEADSUP);
+        if (headsUpWrapper != null) {
+            headsUpHeight = Math.max(headsUpHeight, headsUpWrapper.getMinLayoutHeight());
+        }
+        layout.setHeights(minHeight, headsUpHeight, mNotificationMaxHeight,
+                mNotificationAmbientHeight);
+    }
+
+    public StatusBarNotification getStatusBarNotification() {
+        return mStatusBarNotification;
+    }
+
+    public NotificationData.Entry getEntry() {
+        return mEntry;
+    }
+
+    public boolean isHeadsUp() {
+        return mIsHeadsUp;
+    }
+
+    public void setHeadsUp(boolean isHeadsUp) {
+        boolean wasAboveShelf = isAboveShelf();
+        int intrinsicBefore = getIntrinsicHeight();
+        mIsHeadsUp = isHeadsUp;
+        mPrivateLayout.setHeadsUp(isHeadsUp);
+        if (mIsSummaryWithChildren) {
+            // The overflow might change since we allow more lines as HUN.
+            mChildrenContainer.updateGroupOverflow();
+        }
+        if (intrinsicBefore != getIntrinsicHeight()) {
+            notifyHeightChanged(false  /* needsAnimation */);
+        }
+        if (isHeadsUp) {
+            mMustStayOnScreen = true;
+            setAboveShelf(true);
+        } else if (isAboveShelf() != wasAboveShelf) {
+            mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
+        }
+    }
+
+    public void setGroupManager(NotificationGroupManager groupManager) {
+        mGroupManager = groupManager;
+        mPrivateLayout.setGroupManager(groupManager);
+    }
+
+    public void setRemoteInputController(RemoteInputController r) {
+        mPrivateLayout.setRemoteInputController(r);
+    }
+
+    public void setAppName(String appName) {
+        mAppName = appName;
+        if (mMenuRow != null && mMenuRow.getMenuView() != null) {
+            mMenuRow.setAppName(mAppName);
+        }
+    }
+
+    public void addChildNotification(ExpandableNotificationRow row) {
+        addChildNotification(row, -1);
+    }
+
+    /**
+     * Set the how much the header should be visible. A value of 0 will make the header fully gone
+     * and a value of 1 will make the notification look just like normal.
+     * This is being used for heads up notifications, when they are pinned to the top of the screen
+     * and the header content is extracted to the statusbar.
+     *
+     * @param headerVisibleAmount the amount the header should be visible.
+     */
+    public void setHeaderVisibleAmount(float headerVisibleAmount) {
+        if (mHeaderVisibleAmount != headerVisibleAmount) {
+            mHeaderVisibleAmount = headerVisibleAmount;
+            mPrivateLayout.setHeaderVisibleAmount(headerVisibleAmount);
+            if (mChildrenContainer != null) {
+                mChildrenContainer.setHeaderVisibleAmount(headerVisibleAmount);
+            }
+            notifyHeightChanged(false /* needsAnimation */);
+        }
+    }
+
+    @Override
+    public float getHeaderVisibleAmount() {
+        return mHeaderVisibleAmount;
+    }
+
+    @Override
+    public void setHeadsUpIsVisible() {
+        super.setHeadsUpIsVisible();
+        mMustStayOnScreen = false;
+    }
+
+    /**
+     * Add a child notification to this view.
+     *
+     * @param row the row to add
+     * @param childIndex the index to add it at, if -1 it will be added at the end
+     */
+    public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
+        if (mChildrenContainer == null) {
+            mChildrenContainerStub.inflate();
+        }
+        mChildrenContainer.addNotification(row, childIndex);
+        onChildrenCountChanged();
+        row.setIsChildInGroup(true, this);
+    }
+
+    public void removeChildNotification(ExpandableNotificationRow row) {
+        if (mChildrenContainer != null) {
+            mChildrenContainer.removeNotification(row);
+        }
+        onChildrenCountChanged();
+        row.setIsChildInGroup(false, null);
+        row.setBottomRoundness(0.0f, false /* animate */);
+    }
+
+    @Override
+    public boolean isChildInGroup() {
+        return mNotificationParent != null;
+    }
+
+    /**
+     * @return whether this notification is the only child in the group summary
+     */
+    public boolean isOnlyChildInGroup() {
+        return mGroupManager.isOnlyChildInGroup(getStatusBarNotification());
+    }
+
+    public ExpandableNotificationRow getNotificationParent() {
+        return mNotificationParent;
+    }
+
+    /**
+     * @param isChildInGroup Is this notification now in a group
+     * @param parent the new parent notification
+     */
+    public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {
+        boolean childInGroup = StatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
+        if (mExpandAnimationRunning && !isChildInGroup && mNotificationParent != null) {
+            mNotificationParent.setChildIsExpanding(false);
+            mNotificationParent.setExtraWidthForClipping(0.0f);
+            mNotificationParent.setMinimumHeightForClipping(0);
+        }
+        mNotificationParent = childInGroup ? parent : null;
+        mPrivateLayout.setIsChildInGroup(childInGroup);
+        mNotificationInflater.setIsChildInGroup(childInGroup);
+        resetBackgroundAlpha();
+        updateBackgroundForGroupState();
+        updateClickAndFocus();
+        if (mNotificationParent != null) {
+            setOverrideTintColor(NO_COLOR, 0.0f);
+            // Let's reset the distance to top roundness, as this isn't applied to group children
+            setDistanceToTopRoundness(NO_ROUNDNESS);
+            mNotificationParent.updateBackgroundForGroupState();
+        }
+        updateIconVisibilities();
+        updateBackgroundClipping();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (event.getActionMasked() != MotionEvent.ACTION_DOWN
+                || !isChildInGroup() || isGroupExpanded()) {
+            return super.onTouchEvent(event);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    protected boolean handleSlideBack() {
+        if (mMenuRow != null && mMenuRow.isMenuVisible()) {
+            animateTranslateNotification(0 /* targetLeft */);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean shouldHideBackground() {
+        return super.shouldHideBackground() || mShowNoBackground;
+    }
+
+    @Override
+    public boolean isSummaryWithChildren() {
+        return mIsSummaryWithChildren;
+    }
+
+    @Override
+    public boolean areChildrenExpanded() {
+        return mChildrenExpanded;
+    }
+
+    public List<ExpandableNotificationRow> getNotificationChildren() {
+        return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
+    }
+
+    public int getNumberOfNotificationChildren() {
+        if (mChildrenContainer == null) {
+            return 0;
+        }
+        return mChildrenContainer.getNotificationChildren().size();
+    }
+
+    /**
+     * Apply the order given in the list to the children.
+     *
+     * @param childOrder the new list order
+     * @param visualStabilityManager
+     * @param callback the callback to invoked in case it is not allowed
+     * @return whether the list order has changed
+     */
+    public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
+            VisualStabilityManager visualStabilityManager,
+            VisualStabilityManager.Callback callback) {
+        return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder,
+                visualStabilityManager, callback);
+    }
+
+    public void getChildrenStates(StackScrollState resultState,
+            AmbientState ambientState) {
+        if (mIsSummaryWithChildren) {
+            ExpandableViewState parentState = resultState.getViewStateForView(this);
+            mChildrenContainer.getState(resultState, parentState, ambientState);
+        }
+    }
+
+    public void applyChildrenState(StackScrollState state) {
+        if (mIsSummaryWithChildren) {
+            mChildrenContainer.applyState(state);
+        }
+    }
+
+    public void prepareExpansionChanged(StackScrollState state) {
+        if (mIsSummaryWithChildren) {
+            mChildrenContainer.prepareExpansionChanged(state);
+        }
+    }
+
+    public void startChildAnimation(StackScrollState finalState, AnimationProperties properties) {
+        if (mIsSummaryWithChildren) {
+            mChildrenContainer.startAnimationToState(finalState, properties);
+        }
+    }
+
+    public ExpandableNotificationRow getViewAtPosition(float y) {
+        if (!mIsSummaryWithChildren || !mChildrenExpanded) {
+            return this;
+        } else {
+            ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
+            return view == null ? this : view;
+        }
+    }
+
+    public NotificationGuts getGuts() {
+        return mGuts;
+    }
+
+    /**
+     * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
+     * the notification will be rendered on top of the screen.
+     *
+     * @param pinned whether it is pinned
+     */
+    public void setPinned(boolean pinned) {
+        int intrinsicHeight = getIntrinsicHeight();
+        boolean wasAboveShelf = isAboveShelf();
+        mIsPinned = pinned;
+        if (intrinsicHeight != getIntrinsicHeight()) {
+            notifyHeightChanged(false /* needsAnimation */);
+        }
+        if (pinned) {
+            setIconAnimationRunning(true);
+            mExpandedWhenPinned = false;
+        } else if (mExpandedWhenPinned) {
+            setUserExpanded(true);
+        }
+        setChronometerRunning(mLastChronometerRunning);
+        if (isAboveShelf() != wasAboveShelf) {
+            mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
+        }
+    }
+
+    @Override
+    public boolean isPinned() {
+        return mIsPinned;
+    }
+
+    @Override
+    public int getPinnedHeadsUpHeight() {
+        return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
+    }
+
+    /**
+     * @param atLeastMinHeight should the value returned be at least the minimum height.
+     *                         Used to avoid cyclic calls
+     * @return the height of the heads up notification when pinned
+     */
+    private int getPinnedHeadsUpHeight(boolean atLeastMinHeight) {
+        if (mIsSummaryWithChildren) {
+            return mChildrenContainer.getIntrinsicHeight();
+        }
+        if(mExpandedWhenPinned) {
+            return Math.max(getMaxExpandHeight(), getHeadsUpHeight());
+        } else if (atLeastMinHeight) {
+            return Math.max(getCollapsedHeight(), getHeadsUpHeight());
+        } else {
+            return getHeadsUpHeight();
+        }
+    }
+
+    /**
+     * Mark whether this notification was just clicked, i.e. the user has just clicked this
+     * notification in this frame.
+     */
+    public void setJustClicked(boolean justClicked) {
+        mJustClicked = justClicked;
+    }
+
+    /**
+     * @return true if this notification has been clicked in this frame, false otherwise
+     */
+    public boolean wasJustClicked() {
+        return mJustClicked;
+    }
+
+    public void setChronometerRunning(boolean running) {
+        mLastChronometerRunning = running;
+        setChronometerRunning(running, mPrivateLayout);
+        setChronometerRunning(running, mPublicLayout);
+        if (mChildrenContainer != null) {
+            List<ExpandableNotificationRow> notificationChildren =
+                    mChildrenContainer.getNotificationChildren();
+            for (int i = 0; i < notificationChildren.size(); i++) {
+                ExpandableNotificationRow child = notificationChildren.get(i);
+                child.setChronometerRunning(running);
+            }
+        }
+    }
+
+    private void setChronometerRunning(boolean running, NotificationContentView layout) {
+        if (layout != null) {
+            running = running || isPinned();
+            View contractedChild = layout.getContractedChild();
+            View expandedChild = layout.getExpandedChild();
+            View headsUpChild = layout.getHeadsUpChild();
+            setChronometerRunningForChild(running, contractedChild);
+            setChronometerRunningForChild(running, expandedChild);
+            setChronometerRunningForChild(running, headsUpChild);
+        }
+    }
+
+    private void setChronometerRunningForChild(boolean running, View child) {
+        if (child != null) {
+            View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
+            if (chronometer instanceof Chronometer) {
+                ((Chronometer) chronometer).setStarted(running);
+            }
+        }
+    }
+
+    public NotificationHeaderView getNotificationHeader() {
+        if (mIsSummaryWithChildren) {
+            return mChildrenContainer.getHeaderView();
+        }
+        return mPrivateLayout.getNotificationHeader();
+    }
+
+    /**
+     * @return the currently visible notification header. This can be different from
+     * {@link #getNotificationHeader()} in case it is a low-priority group.
+     */
+    public NotificationHeaderView getVisibleNotificationHeader() {
+        if (mIsSummaryWithChildren && !shouldShowPublic()) {
+            return mChildrenContainer.getVisibleHeader();
+        }
+        return getShowingLayout().getVisibleNotificationHeader();
+    }
+
+
+    /**
+     * @return the contracted notification header. This can be different from
+     * {@link #getNotificationHeader()} and also {@link #getVisibleNotificationHeader()} and only
+     * returns the contracted version.
+     */
+    public NotificationHeaderView getContractedNotificationHeader() {
+        if (mIsSummaryWithChildren) {
+            return mChildrenContainer.getHeaderView();
+        }
+        return mPrivateLayout.getContractedNotificationHeader();
+    }
+
+    public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
+        mOnExpandClickListener = onExpandClickListener;
+    }
+
+    public void setLongPressListener(LongPressListener longPressListener) {
+        mLongPressListener = longPressListener;
+    }
+
+    @Override
+    public void setOnClickListener(@Nullable OnClickListener l) {
+        super.setOnClickListener(l);
+        mOnClickListener = l;
+        updateClickAndFocus();
+    }
+
+    private void updateClickAndFocus() {
+        boolean normalChild = !isChildInGroup() || isGroupExpanded();
+        boolean clickable = mOnClickListener != null && normalChild;
+        if (isFocusable() != normalChild) {
+            setFocusable(normalChild);
+        }
+        if (isClickable() != clickable) {
+            setClickable(clickable);
+        }
+    }
+
+    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+        mHeadsUpManager = headsUpManager;
+    }
+
+    public void setGutsView(MenuItem item) {
+        if (mGuts != null && item.getGutsView() instanceof NotificationGuts.GutsContent) {
+            ((NotificationGuts.GutsContent) item.getGutsView()).setGutsParent(mGuts);
+            mGuts.setGutsContent((NotificationGuts.GutsContent) item.getGutsView());
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mEntry.setInitializationTime(SystemClock.elapsedRealtime());
+        Dependency.get(PluginManager.class).addPluginListener(this,
+                NotificationMenuRowPlugin.class, false /* Allow multiple */);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        Dependency.get(PluginManager.class).removePluginListener(this);
+    }
+
+    @Override
+    public void onPluginConnected(NotificationMenuRowPlugin plugin, Context pluginContext) {
+        boolean existed = mMenuRow.getMenuView() != null;
+        if (existed) {
+            removeView(mMenuRow.getMenuView());
+        }
+        mMenuRow = plugin;
+        if (mMenuRow.useDefaultMenuItems()) {
+            ArrayList<MenuItem> items = new ArrayList<>();
+            items.add(NotificationMenuRow.createInfoItem(mContext));
+            items.add(NotificationMenuRow.createSnoozeItem(mContext));
+            items.add(NotificationMenuRow.createAppOpsItem(mContext));
+            mMenuRow.setMenuItems(items);
+        }
+        if (existed) {
+            createMenu();
+        }
+    }
+
+    @Override
+    public void onPluginDisconnected(NotificationMenuRowPlugin plugin) {
+        boolean existed = mMenuRow.getMenuView() != null;
+        mMenuRow = new NotificationMenuRow(mContext); // Back to default
+        if (existed) {
+            createMenu();
+        }
+    }
+
+    public NotificationMenuRowPlugin createMenu() {
+        if (mMenuRow.getMenuView() == null) {
+            mMenuRow.createMenu(this, mStatusBarNotification);
+            mMenuRow.setAppName(mAppName);
+            FrameLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.MATCH_PARENT);
+            addView(mMenuRow.getMenuView(), MENU_VIEW_INDEX, lp);
+        }
+        return mMenuRow;
+    }
+
+    public NotificationMenuRowPlugin getProvider() {
+        return mMenuRow;
+    }
+
+    @Override
+    public void onDensityOrFontScaleChanged() {
+        super.onDensityOrFontScaleChanged();
+        initDimens();
+        initBackground();
+        reInflateViews();
+    }
+
+    private void reInflateViews() {
+        // Let's update our childrencontainer. This is intentionally not guarded with
+        // mIsSummaryWithChildren since we might have had children but not anymore.
+        if (mChildrenContainer != null) {
+            mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
+        }
+        if (mGuts != null) {
+            View oldGuts = mGuts;
+            int index = indexOfChild(oldGuts);
+            removeView(oldGuts);
+            mGuts = (NotificationGuts) LayoutInflater.from(mContext).inflate(
+                    R.layout.notification_guts, this, false);
+            mGuts.setVisibility(oldGuts.getVisibility());
+            addView(mGuts, index);
+        }
+        View oldMenu = mMenuRow.getMenuView();
+        if (oldMenu != null) {
+            int menuIndex = indexOfChild(oldMenu);
+            removeView(oldMenu);
+            mMenuRow.createMenu(ExpandableNotificationRow.this, mStatusBarNotification);
+            mMenuRow.setAppName(mAppName);
+            addView(mMenuRow.getMenuView(), menuIndex);
+        }
+        for (NotificationContentView l : mLayouts) {
+            l.initView();
+            l.reInflateViews();
+        }
+        mNotificationInflater.clearCachesAndReInflate();
+        onNotificationUpdated();
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        if (mMenuRow.getMenuView() != null) {
+            mMenuRow.onConfigurationChanged();
+        }
+    }
+
+    @Override
+    public void onUiModeChanged() {
+        super.onUiModeChanged();
+        reInflateViews();
+        if (mChildrenContainer != null) {
+            for (ExpandableNotificationRow child : mChildrenContainer.getNotificationChildren()) {
+                child.onUiModeChanged();
+            }
+        }
+    }
+
+    public void setContentBackground(int customBackgroundColor, boolean animate,
+            NotificationContentView notificationContentView) {
+        if (getShowingLayout() == notificationContentView) {
+            setTintColor(customBackgroundColor, animate);
+        }
+    }
+
+    @Override
+    protected void setBackgroundTintColor(int color) {
+        super.setBackgroundTintColor(color);
+        NotificationContentView view = getShowingLayout();
+        if (view != null) {
+            view.setBackgroundTintColor(color);
+        }
+    }
+
+    public void closeRemoteInput() {
+        for (NotificationContentView l : mLayouts) {
+            l.closeRemoteInput();
+        }
+    }
+
+    /**
+     * Set by how much the single line view should be indented.
+     */
+    public void setSingleLineWidthIndention(int indention) {
+        mPrivateLayout.setSingleLineWidthIndention(indention);
+    }
+
+    public int getNotificationColor() {
+        return mNotificationColor;
+    }
+
+    private void updateNotificationColor() {
+        mNotificationColor = ContrastColorUtil.resolveContrastColor(mContext,
+                getStatusBarNotification().getNotification().color,
+                getBackgroundColorWithoutTint());
+        mNotificationColorAmbient = ContrastColorUtil.resolveAmbientColor(mContext,
+                getStatusBarNotification().getNotification().color);
+    }
+
+    public HybridNotificationView getSingleLineView() {
+        return mPrivateLayout.getSingleLineView();
+    }
+
+    public HybridNotificationView getAmbientSingleLineView() {
+        return getShowingLayout().getAmbientSingleLineChild();
+    }
+
+    public boolean isOnKeyguard() {
+        return mOnKeyguard;
+    }
+
+    public void removeAllChildren() {
+        List<ExpandableNotificationRow> notificationChildren
+                = mChildrenContainer.getNotificationChildren();
+        ArrayList<ExpandableNotificationRow> clonedList = new ArrayList<>(notificationChildren);
+        for (int i = 0; i < clonedList.size(); i++) {
+            ExpandableNotificationRow row = clonedList.get(i);
+            if (row.keepInParent()) {
+                continue;
+            }
+            mChildrenContainer.removeNotification(row);
+            row.setIsChildInGroup(false, null);
+        }
+        onChildrenCountChanged();
+    }
+
+    public void setForceUnlocked(boolean forceUnlocked) {
+        mForceUnlocked = forceUnlocked;
+        if (mIsSummaryWithChildren) {
+            List<ExpandableNotificationRow> notificationChildren = getNotificationChildren();
+            for (ExpandableNotificationRow child : notificationChildren) {
+                child.setForceUnlocked(forceUnlocked);
+            }
+        }
+    }
+
+    public void setDismissed(boolean fromAccessibility) {
+        setLongPressListener(null);
+        mDismissed = true;
+        mGroupParentWhenDismissed = mNotificationParent;
+        mRefocusOnDismiss = fromAccessibility;
+        mChildAfterViewWhenDismissed = null;
+        mEntry.icon.setDismissed();
+        if (isChildInGroup()) {
+            List<ExpandableNotificationRow> notificationChildren =
+                    mNotificationParent.getNotificationChildren();
+            int i = notificationChildren.indexOf(this);
+            if (i != -1 && i < notificationChildren.size() - 1) {
+                mChildAfterViewWhenDismissed = notificationChildren.get(i + 1);
+            }
+        }
+    }
+
+    public boolean isDismissed() {
+        return mDismissed;
+    }
+
+    public boolean keepInParent() {
+        return mKeepInParent;
+    }
+
+    public void setKeepInParent(boolean keepInParent) {
+        mKeepInParent = keepInParent;
+    }
+
+    @Override
+    public boolean isRemoved() {
+        return mRemoved;
+    }
+
+    public void setRemoved() {
+        mRemoved = true;
+        mTranslationWhenRemoved = getTranslationY();
+        mWasChildInGroupWhenRemoved = isChildInGroup();
+        if (isChildInGroup()) {
+            mTranslationWhenRemoved += getNotificationParent().getTranslationY();
+        }
+        mPrivateLayout.setRemoved();
+    }
+
+    public boolean wasChildInGroupWhenRemoved() {
+        return mWasChildInGroupWhenRemoved;
+    }
+
+    public float getTranslationWhenRemoved() {
+        return mTranslationWhenRemoved;
+    }
+
+    public NotificationChildrenContainer getChildrenContainer() {
+        return mChildrenContainer;
+    }
+
+    public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
+        boolean wasAboveShelf = isAboveShelf();
+        boolean changed = headsUpAnimatingAway != mHeadsupDisappearRunning;
+        mHeadsupDisappearRunning = headsUpAnimatingAway;
+        mPrivateLayout.setHeadsUpAnimatingAway(headsUpAnimatingAway);
+        if (changed && mHeadsUpAnimatingAwayListener != null) {
+            mHeadsUpAnimatingAwayListener.accept(headsUpAnimatingAway);
+        }
+        if (isAboveShelf() != wasAboveShelf) {
+            mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
+        }
+    }
+
+    public void setHeadsUpAnimatingAwayListener(Consumer<Boolean> listener) {
+        mHeadsUpAnimatingAwayListener = listener;
+    }
+
+    /**
+     * @return if the view was just heads upped and is now animating away. During such a time the
+     * layout needs to be kept consistent
+     */
+    @Override
+    public boolean isHeadsUpAnimatingAway() {
+        return mHeadsupDisappearRunning;
+    }
+
+    public View getChildAfterViewWhenDismissed() {
+        return mChildAfterViewWhenDismissed;
+    }
+
+    public View getGroupParentWhenDismissed() {
+        return mGroupParentWhenDismissed;
+    }
+
+    /**
+     * Dismisses the notification with the option of showing the blocking helper in-place if we have
+     * a negative user sentiment.
+     *
+     * @param fromAccessibility whether this dismiss is coming from an accessibility action
+     * @return whether a blocking helper is shown in this row
+     */
+    public boolean performDismissWithBlockingHelper(boolean fromAccessibility) {
+        NotificationBlockingHelperManager manager =
+                Dependency.get(NotificationBlockingHelperManager.class);
+        boolean isBlockingHelperShown = manager.perhapsShowBlockingHelper(this, mMenuRow);
+
+        Dependency.get(MetricsLogger.class).count(NotificationCounters.NOTIFICATION_DISMISSED, 1);
+
+        // Continue with dismiss since we don't want the blocking helper to be directly associated
+        // with a certain notification.
+        performDismiss(fromAccessibility);
+        return isBlockingHelperShown;
+    }
+
+    public void performDismiss(boolean fromAccessibility) {
+        if (isOnlyChildInGroup()) {
+            ExpandableNotificationRow groupSummary =
+                    mGroupManager.getLogicalGroupSummary(getStatusBarNotification());
+            if (groupSummary.isClearable()) {
+                // If this is the only child in the group, dismiss the group, but don't try to show
+                // the blocking helper affordance!
+                groupSummary.performDismiss(fromAccessibility);
+            }
+        }
+        setDismissed(fromAccessibility);
+        if (isClearable()) {
+            // TODO: track dismiss sentiment
+            if (mOnDismissRunnable != null) {
+                mOnDismissRunnable.run();
+            }
+        }
+    }
+
+    public void setBlockingHelperShowing(boolean isBlockingHelperShowing) {
+        mIsBlockingHelperShowing = isBlockingHelperShowing;
+    }
+
+    public boolean isBlockingHelperShowing() {
+        return mIsBlockingHelperShowing;
+    }
+
+    public void setOnDismissRunnable(Runnable onDismissRunnable) {
+        mOnDismissRunnable = onDismissRunnable;
+    }
+
+    public View getNotificationIcon() {
+        NotificationHeaderView notificationHeader = getVisibleNotificationHeader();
+        if (notificationHeader != null) {
+            return notificationHeader.getIcon();
+        }
+        return null;
+    }
+
+    /**
+     * @return whether the notification is currently showing a view with an icon.
+     */
+    public boolean isShowingIcon() {
+        if (areGutsExposed()) {
+            return false;
+        }
+        return getVisibleNotificationHeader() != null;
+    }
+
+    /**
+     * Set how much this notification is transformed into an icon.
+     *
+     * @param contentTransformationAmount A value from 0 to 1 indicating how much we are transformed
+     *                                 to the content away
+     * @param isLastChild is this the last child in the list. If true, then the transformation is
+     *                    different since it's content fades out.
+     */
+    public void setContentTransformationAmount(float contentTransformationAmount,
+            boolean isLastChild) {
+        boolean changeTransformation = isLastChild != mIsLastChild;
+        changeTransformation |= mContentTransformationAmount != contentTransformationAmount;
+        mIsLastChild = isLastChild;
+        mContentTransformationAmount = contentTransformationAmount;
+        if (changeTransformation) {
+            updateContentTransformation();
+        }
+    }
+
+    /**
+     * Set the icons to be visible of this notification.
+     */
+    public void setIconsVisible(boolean iconsVisible) {
+        if (iconsVisible != mIconsVisible) {
+            mIconsVisible = iconsVisible;
+            updateIconVisibilities();
+        }
+    }
+
+    @Override
+    protected void onBelowSpeedBumpChanged() {
+        updateIconVisibilities();
+    }
+
+    private void updateContentTransformation() {
+        if (mExpandAnimationRunning) {
+            return;
+        }
+        float contentAlpha;
+        float translationY = -mContentTransformationAmount * mIconTransformContentShift;
+        if (mIsLastChild) {
+            contentAlpha = 1.0f - mContentTransformationAmount;
+            contentAlpha = Math.min(contentAlpha / 0.5f, 1.0f);
+            contentAlpha = Interpolators.ALPHA_OUT.getInterpolation(contentAlpha);
+            translationY *= 0.4f;
+        } else {
+            contentAlpha = 1.0f;
+        }
+        for (NotificationContentView l : mLayouts) {
+            l.setAlpha(contentAlpha);
+            l.setTranslationY(translationY);
+        }
+        if (mChildrenContainer != null) {
+            mChildrenContainer.setAlpha(contentAlpha);
+            mChildrenContainer.setTranslationY(translationY);
+            // TODO: handle children fade out better
+        }
+    }
+
+    private void updateIconVisibilities() {
+        boolean visible = isChildInGroup()
+                || (isBelowSpeedBump() && !NotificationShelf.SHOW_AMBIENT_ICONS)
+                || mIconsVisible;
+        for (NotificationContentView l : mLayouts) {
+            l.setIconsVisible(visible);
+        }
+        if (mChildrenContainer != null) {
+            mChildrenContainer.setIconsVisible(visible);
+        }
+    }
+
+    /**
+     * Get the relative top padding of a view relative to this view. This recursively walks up the
+     * hierarchy and does the corresponding measuring.
+     *
+     * @param view the view to the the padding for. The requested view has to be a child of this
+     *             notification.
+     * @return the toppadding
+     */
+    public int getRelativeTopPadding(View view) {
+        int topPadding = 0;
+        while (view.getParent() instanceof ViewGroup) {
+            topPadding += view.getTop();
+            view = (View) view.getParent();
+            if (view instanceof ExpandableNotificationRow) {
+                return topPadding;
+            }
+        }
+        return topPadding;
+    }
+
+    public float getContentTranslation() {
+        return mPrivateLayout.getTranslationY();
+    }
+
+    public void setIsLowPriority(boolean isLowPriority) {
+        mIsLowPriority = isLowPriority;
+        mPrivateLayout.setIsLowPriority(isLowPriority);
+        mNotificationInflater.setIsLowPriority(mIsLowPriority);
+        if (mChildrenContainer != null) {
+            mChildrenContainer.setIsLowPriority(isLowPriority);
+        }
+    }
+
+
+    public void setLowPriorityStateUpdated(boolean lowPriorityStateUpdated) {
+        mLowPriorityStateUpdated = lowPriorityStateUpdated;
+    }
+
+    public boolean hasLowPriorityStateUpdated() {
+        return mLowPriorityStateUpdated;
+    }
+
+    public boolean isLowPriority() {
+        return mIsLowPriority;
+    }
+
+    public void setUseIncreasedCollapsedHeight(boolean use) {
+        mUseIncreasedCollapsedHeight = use;
+        mNotificationInflater.setUsesIncreasedHeight(use);
+    }
+
+    public void setSmartActions(List<Notification.Action> smartActions) {
+        mNotificationInflater.setSmartActions(smartActions);
+    }
+
+    public void setUseIncreasedHeadsUpHeight(boolean use) {
+        mUseIncreasedHeadsUpHeight = use;
+        mNotificationInflater.setUsesIncreasedHeadsUpHeight(use);
+    }
+
+    public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
+        mNotificationInflater.setRemoteViewClickHandler(remoteViewClickHandler);
+    }
+
+    public void setInflationCallback(InflationCallback callback) {
+        mNotificationInflater.setInflationCallback(callback);
+    }
+
+    public void setNeedsRedaction(boolean needsRedaction) {
+        mNotificationInflater.setRedactAmbient(needsRedaction);
+    }
+
+    @VisibleForTesting
+    public NotificationInflater getNotificationInflater() {
+        return mNotificationInflater;
+    }
+
+    public int getNotificationColorAmbient() {
+        return mNotificationColorAmbient;
+    }
+
+    public interface ExpansionLogger {
+        void logNotificationExpansion(String key, boolean userAction, boolean expanded);
+    }
+
+    public ExpandableNotificationRow(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mFalsingManager = FalsingManager.getInstance(context);
+        mNotificationInflater = new NotificationInflater(this);
+        mMenuRow = new NotificationMenuRow(mContext);
+        initDimens();
+    }
+
+    private void initDimens() {
+        mNotificationMinHeightBeforeN = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_min_height_legacy);
+        mNotificationMinHeightBeforeP = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_min_height_before_p);
+        mNotificationMinHeight = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_min_height);
+        mNotificationMinHeightLarge = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_min_height_increased);
+        mNotificationMaxHeight = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_max_height);
+        mNotificationAmbientHeight = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_ambient_height);
+        mMaxHeadsUpHeightBeforeN = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_max_heads_up_height_legacy);
+        mMaxHeadsUpHeightBeforeP = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_max_heads_up_height_before_p);
+        mMaxHeadsUpHeight = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_max_heads_up_height);
+        mMaxHeadsUpHeightIncreased = NotificationUtils.getFontScaledHeight(mContext,
+                R.dimen.notification_max_heads_up_height_increased);
+
+        Resources res = getResources();
+        mIncreasedPaddingBetweenElements = res.getDimensionPixelSize(
+                R.dimen.notification_divider_height_increased);
+        mIconTransformContentShiftNoIcon = res.getDimensionPixelSize(
+                R.dimen.notification_icon_transform_content_shift);
+        mEnableNonGroupedNotificationExpand =
+                res.getBoolean(R.bool.config_enableNonGroupedNotificationExpand);
+        mShowGroupBackgroundWhenExpanded =
+                res.getBoolean(R.bool.config_showGroupNotificationBgWhenExpanded);
+    }
+
+    /**
+     * Resets this view so it can be re-used for an updated notification.
+     */
+    public void reset() {
+        mShowingPublicInitialized = false;
+        onHeightReset();
+        requestLayout();
+    }
+
+    public void showAppOpsIcons(ArraySet<Integer> activeOps) {
+        if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() != null) {
+            mChildrenContainer.getHeaderView().showAppOpsIcons(activeOps);
+        }
+        mPrivateLayout.showAppOpsIcons(activeOps);
+        mPublicLayout.showAppOpsIcons(activeOps);
+    }
+
+    public View.OnClickListener getAppOpsOnClickListener() {
+        return mOnAppOpsClickListener;
+    }
+
+    public void setAppOpsOnClickListener(ExpandableNotificationRow.OnAppOpsClickListener l) {
+        mOnAppOpsClickListener = v -> {
+            createMenu();
+            MenuItem menuItem = getProvider().getAppOpsMenuItem(mContext);
+            if (menuItem != null) {
+                l.onClick(this, v.getWidth() / 2, v.getHeight() / 2, menuItem);
+            }
+        };
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
+        mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
+        mLayouts = new NotificationContentView[] {mPrivateLayout, mPublicLayout};
+
+        for (NotificationContentView l : mLayouts) {
+            l.setExpandClickListener(mExpandClickListener);
+            l.setContainingNotification(this);
+        }
+        mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
+        mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
+            @Override
+            public void onInflate(ViewStub stub, View inflated) {
+                mGuts = (NotificationGuts) inflated;
+                mGuts.setClipTopAmount(getClipTopAmount());
+                mGuts.setActualHeight(getActualHeight());
+                mGutsStub = null;
+            }
+        });
+        mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
+        mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
+
+            @Override
+            public void onInflate(ViewStub stub, View inflated) {
+                mChildrenContainer = (NotificationChildrenContainer) inflated;
+                mChildrenContainer.setIsLowPriority(mIsLowPriority);
+                mChildrenContainer.setContainingNotification(ExpandableNotificationRow.this);
+                mChildrenContainer.onNotificationUpdated();
+
+                if (mShouldTranslateContents) {
+                    mTranslateableViews.add(mChildrenContainer);
+                }
+            }
+        });
+
+        if (mShouldTranslateContents) {
+            // Add the views that we translate to reveal the menu
+            mTranslateableViews = new ArrayList<>();
+            for (int i = 0; i < getChildCount(); i++) {
+                mTranslateableViews.add(getChildAt(i));
+            }
+            // Remove views that don't translate
+            mTranslateableViews.remove(mChildrenContainerStub);
+            mTranslateableViews.remove(mGutsStub);
+        }
+    }
+
+    private void doLongClickCallback() {
+        doLongClickCallback(getWidth() / 2, getHeight() / 2);
+    }
+
+    public void doLongClickCallback(int x, int y) {
+        createMenu();
+        MenuItem menuItem = getProvider().getLongpressMenuItem(mContext);
+        doLongClickCallback(x, y, menuItem);
+    }
+
+    private void doLongClickCallback(int x, int y, MenuItem menuItem) {
+        if (mLongPressListener != null && menuItem != null) {
+            mLongPressListener.onLongPress(this, x, y, menuItem);
+        }
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (KeyEvent.isConfirmKey(keyCode)) {
+            event.startTracking();
+            return true;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (KeyEvent.isConfirmKey(keyCode)) {
+            if (!event.isCanceled()) {
+                performClick();
+            }
+            return true;
+        }
+        return super.onKeyUp(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+        if (KeyEvent.isConfirmKey(keyCode)) {
+            doLongClickCallback();
+            return true;
+        }
+        return false;
+    }
+
+    public void resetTranslation() {
+        if (mTranslateAnim != null) {
+            mTranslateAnim.cancel();
+        }
+
+        if (!mShouldTranslateContents) {
+            setTranslationX(0);
+        } else if (mTranslateableViews != null) {
+            for (int i = 0; i < mTranslateableViews.size(); i++) {
+                mTranslateableViews.get(i).setTranslationX(0);
+            }
+            invalidateOutline();
+            getEntry().expandedIcon.setScrollX(0);
+        }
+
+        mMenuRow.resetMenu();
+    }
+
+    void onGutsOpened() {
+        resetTranslation();
+        updateContentAccessibilityImportanceForGuts(false /* isEnabled */);
+    }
+
+    void onGutsClosed() {
+        updateContentAccessibilityImportanceForGuts(true /* isEnabled */);
+    }
+
+    /**
+     * Updates whether all the non-guts content inside this row is important for accessibility.
+     *
+     * @param isEnabled whether the content views should be enabled for accessibility
+     */
+    private void updateContentAccessibilityImportanceForGuts(boolean isEnabled) {
+        if (mChildrenContainer != null) {
+            updateChildAccessibilityImportance(mChildrenContainer, isEnabled);
+        }
+        if (mLayouts != null) {
+            for (View view : mLayouts) {
+                updateChildAccessibilityImportance(view, isEnabled);
+            }
+        }
+
+        if (isEnabled) {
+            this.requestAccessibilityFocus();
+        }
+    }
+
+    /**
+     * Updates whether the given childView is important for accessibility based on
+     * {@code isEnabled}.
+     */
+    private void updateChildAccessibilityImportance(View childView, boolean isEnabled) {
+        childView.setImportantForAccessibility(isEnabled
+                ? View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
+                : View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+    }
+
+    public CharSequence getActiveRemoteInputText() {
+        return mPrivateLayout.getActiveRemoteInputText();
+    }
+
+    public void animateTranslateNotification(final float leftTarget) {
+        if (mTranslateAnim != null) {
+            mTranslateAnim.cancel();
+        }
+        mTranslateAnim = getTranslateViewAnimator(leftTarget, null /* updateListener */);
+        if (mTranslateAnim != null) {
+            mTranslateAnim.start();
+        }
+    }
+
+    @Override
+    public void setTranslation(float translationX) {
+        if (areGutsExposed()) {
+            // Don't translate if guts are showing.
+            return;
+        }
+        if (!mShouldTranslateContents) {
+            setTranslationX(translationX);
+        } else if (mTranslateableViews != null) {
+            // Translate the group of views
+            for (int i = 0; i < mTranslateableViews.size(); i++) {
+                if (mTranslateableViews.get(i) != null) {
+                    mTranslateableViews.get(i).setTranslationX(translationX);
+                }
+            }
+            invalidateOutline();
+
+            // In order to keep the shelf in sync with this swiping, we're simply translating
+            // it's icon by the same amount. The translation is already being used for the normal
+            // positioning, so we can use the scrollX instead.
+            getEntry().expandedIcon.setScrollX((int) -translationX);
+        }
+        if (mMenuRow.getMenuView() != null) {
+            mMenuRow.onTranslationUpdate(translationX);
+        }
+    }
+
+    @Override
+    public float getTranslation() {
+        if (!mShouldTranslateContents) {
+            return getTranslationX();
+        }
+
+        if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
+            // All of the views in the list should have same translation, just use first one.
+            return mTranslateableViews.get(0).getTranslationX();
+        }
+
+        return 0;
+    }
+
+    public Animator getTranslateViewAnimator(final float leftTarget,
+            AnimatorUpdateListener listener) {
+        if (mTranslateAnim != null) {
+            mTranslateAnim.cancel();
+        }
+        if (areGutsExposed()) {
+            // No translation if guts are exposed.
+            return null;
+        }
+        final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(this, TRANSLATE_CONTENT,
+                leftTarget);
+        if (listener != null) {
+            translateAnim.addUpdateListener(listener);
+        }
+        translateAnim.addListener(new AnimatorListenerAdapter() {
+            boolean cancelled = false;
+
+            @Override
+            public void onAnimationCancel(Animator anim) {
+                cancelled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator anim) {
+                if (!cancelled && leftTarget == 0) {
+                    mMenuRow.resetMenu();
+                    mTranslateAnim = null;
+                }
+            }
+        });
+        mTranslateAnim = translateAnim;
+        return translateAnim;
+    }
+
+    public void inflateGuts() {
+        if (mGuts == null) {
+            mGutsStub.inflate();
+        }
+    }
+
+    private void updateChildrenVisibility() {
+        boolean hideContentWhileLaunching = mExpandAnimationRunning && mGuts != null
+                && mGuts.isExposed();
+        mPrivateLayout.setVisibility(!shouldShowPublic() && !mIsSummaryWithChildren
+                && !hideContentWhileLaunching ? VISIBLE : INVISIBLE);
+        if (mChildrenContainer != null) {
+            mChildrenContainer.setVisibility(!shouldShowPublic() && mIsSummaryWithChildren
+                    && !hideContentWhileLaunching ? VISIBLE
+                    : INVISIBLE);
+        }
+        // The limits might have changed if the view suddenly became a group or vice versa
+        updateLimits();
+    }
+
+    @Override
+    public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEventInternal(child, event)) {
+            // Add a record for the entire layout since its content is somehow small.
+            // The event comes from a leaf view that is interacted with.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void setDark(boolean dark, boolean fade, long delay) {
+        super.setDark(dark, fade, delay);
+        mDark = dark;
+        if (!mIsHeadsUp) {
+            // Only fade the showing view of the pulsing notification.
+            fade = false;
+        }
+        final NotificationContentView showing = getShowingLayout();
+        if (showing != null) {
+            showing.setDark(dark, fade, delay);
+        }
+        if (mIsSummaryWithChildren) {
+            mChildrenContainer.setDark(dark, fade, delay);
+        }
+        updateShelfIconColor();
+    }
+
+    public void applyExpandAnimationParams(ExpandAnimationParameters params) {
+        if (params == null) {
+            return;
+        }
+        float zProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
+                params.getProgress(0, 50));
+        float translationZ = MathUtils.lerp(params.getStartTranslationZ(),
+                mNotificationLaunchHeight,
+                zProgress);
+        setTranslationZ(translationZ);
+        float extraWidthForClipping = params.getWidth() - getWidth()
+                + MathUtils.lerp(0, mOutlineRadius * 2, params.getProgress());
+        setExtraWidthForClipping(extraWidthForClipping);
+        int top = params.getTop();
+        float interpolation = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(params.getProgress());
+        int startClipTopAmount = params.getStartClipTopAmount();
+        if (mNotificationParent != null) {
+            top -= mNotificationParent.getTranslationY();
+            mNotificationParent.setTranslationZ(translationZ);
+            int parentStartClipTopAmount = params.getParentStartClipTopAmount();
+            if (startClipTopAmount != 0) {
+                int clipTopAmount = (int) MathUtils.lerp(parentStartClipTopAmount,
+                        parentStartClipTopAmount - startClipTopAmount,
+                        interpolation);
+                mNotificationParent.setClipTopAmount(clipTopAmount);
+            }
+            mNotificationParent.setExtraWidthForClipping(extraWidthForClipping);
+            mNotificationParent.setMinimumHeightForClipping(params.getHeight()
+                    + mNotificationParent.getActualHeight());
+        } else if (startClipTopAmount != 0) {
+            int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, interpolation);
+            setClipTopAmount(clipTopAmount);
+        }
+        setTranslationY(top);
+        setActualHeight(params.getHeight());
+
+        mBackgroundNormal.setExpandAnimationParams(params);
+    }
+
+    public void setExpandAnimationRunning(boolean expandAnimationRunning) {
+        View contentView;
+        if (mIsSummaryWithChildren) {
+            contentView =  mChildrenContainer;
+        } else {
+            contentView = getShowingLayout();
+        }
+        if (mGuts != null && mGuts.isExposed()) {
+            contentView = mGuts;
+        }
+        if (expandAnimationRunning) {
+            contentView.animate()
+                    .alpha(0f)
+                    .setDuration(ActivityLaunchAnimator.ANIMATION_DURATION_FADE_CONTENT)
+                    .setInterpolator(Interpolators.ALPHA_OUT);
+            setAboveShelf(true);
+            mExpandAnimationRunning = true;
+            mNotificationViewState.cancelAnimations(this);
+            mNotificationLaunchHeight = AmbientState.getNotificationLaunchHeight(getContext());
+        } else {
+            mExpandAnimationRunning = false;
+            setAboveShelf(isAboveShelf());
+            if (mGuts != null) {
+                mGuts.setAlpha(1.0f);
+            }
+            if (contentView != null) {
+                contentView.setAlpha(1.0f);
+            }
+            setExtraWidthForClipping(0.0f);
+            if (mNotificationParent != null) {
+                mNotificationParent.setExtraWidthForClipping(0.0f);
+                mNotificationParent.setMinimumHeightForClipping(0);
+            }
+        }
+        if (mNotificationParent != null) {
+            mNotificationParent.setChildIsExpanding(mExpandAnimationRunning);
+        }
+        updateChildrenVisibility();
+        updateClipping();
+        mBackgroundNormal.setExpandAnimationRunning(expandAnimationRunning);
+    }
+
+    private void setChildIsExpanding(boolean isExpanding) {
+        mChildIsExpanding = isExpanding;
+    }
+
+    @Override
+    public boolean hasExpandingChild() {
+        return mChildIsExpanding;
+    }
+
+    @Override
+    protected boolean shouldClipToActualHeight() {
+        return super.shouldClipToActualHeight() && !mExpandAnimationRunning && !mChildIsExpanding;
+    }
+
+    @Override
+    public boolean isExpandAnimationRunning() {
+        return mExpandAnimationRunning;
+    }
+
+    /**
+     * Tap sounds should not be played when we're unlocking.
+     * Doing so would cause audio collision and the system would feel unpolished.
+     */
+    @Override
+    public boolean isSoundEffectsEnabled() {
+        final boolean mute = mDark && mSecureStateProvider != null &&
+                !mSecureStateProvider.getAsBoolean();
+        return !mute && super.isSoundEffectsEnabled();
+    }
+
+    public boolean isExpandable() {
+        if (mIsSummaryWithChildren && !shouldShowPublic()) {
+            return !mChildrenExpanded;
+        }
+        return mEnableNonGroupedNotificationExpand && mExpandable;
+    }
+
+    public void setExpandable(boolean expandable) {
+        mExpandable = expandable;
+        mPrivateLayout.updateExpandButtons(isExpandable());
+    }
+
+    @Override
+    public void setClipToActualHeight(boolean clipToActualHeight) {
+        super.setClipToActualHeight(clipToActualHeight || isUserLocked());
+        getShowingLayout().setClipToActualHeight(clipToActualHeight || isUserLocked());
+    }
+
+    /**
+     * @return whether the user has changed the expansion state
+     */
+    public boolean hasUserChangedExpansion() {
+        return mHasUserChangedExpansion;
+    }
+
+    public boolean isUserExpanded() {
+        return mUserExpanded;
+    }
+
+    /**
+     * Set this notification to be expanded by the user
+     *
+     * @param userExpanded whether the user wants this notification to be expanded
+     */
+    public void setUserExpanded(boolean userExpanded) {
+        setUserExpanded(userExpanded, false /* allowChildExpansion */);
+    }
+
+    /**
+     * Set this notification to be expanded by the user
+     *
+     * @param userExpanded whether the user wants this notification to be expanded
+     * @param allowChildExpansion whether a call to this method allows expanding children
+     */
+    public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
+        mFalsingManager.setNotificationExpanded();
+        if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
+                && !mChildrenContainer.showingAsLowPriority()) {
+            final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
+            mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
+            onExpansionChanged(true /* userAction */, wasExpanded);
+            return;
+        }
+        if (userExpanded && !mExpandable) return;
+        final boolean wasExpanded = isExpanded();
+        mHasUserChangedExpansion = true;
+        mUserExpanded = userExpanded;
+        onExpansionChanged(true /* userAction */, wasExpanded);
+        if (!wasExpanded && isExpanded()
+                && getActualHeight() != getIntrinsicHeight()) {
+            notifyHeightChanged(true /* needsAnimation */);
+        }
+    }
+
+    public void resetUserExpansion() {
+        boolean changed = mUserExpanded;
+        mHasUserChangedExpansion = false;
+        mUserExpanded = false;
+        if (changed && mIsSummaryWithChildren) {
+            mChildrenContainer.onExpansionChanged();
+        }
+        updateShelfIconColor();
+    }
+
+    public boolean isUserLocked() {
+        return mUserLocked && !mForceUnlocked;
+    }
+
+    public void setUserLocked(boolean userLocked) {
+        mUserLocked = userLocked;
+        mPrivateLayout.setUserExpanding(userLocked);
+        // This is intentionally not guarded with mIsSummaryWithChildren since we might have had
+        // children but not anymore.
+        if (mChildrenContainer != null) {
+            mChildrenContainer.setUserLocked(userLocked);
+            if (mIsSummaryWithChildren && (userLocked || !isGroupExpanded())) {
+                updateBackgroundForGroupState();
+            }
+        }
+    }
+
+    /**
+     * @return has the system set this notification to be expanded
+     */
+    public boolean isSystemExpanded() {
+        return mIsSystemExpanded;
+    }
+
+    /**
+     * Set this notification to be expanded by the system.
+     *
+     * @param expand whether the system wants this notification to be expanded.
+     */
+    public void setSystemExpanded(boolean expand) {
+        if (expand != mIsSystemExpanded) {
+            final boolean wasExpanded = isExpanded();
+            mIsSystemExpanded = expand;
+            notifyHeightChanged(false /* needsAnimation */);
+            onExpansionChanged(false /* userAction */, wasExpanded);
+            if (mIsSummaryWithChildren) {
+                mChildrenContainer.updateGroupOverflow();
+            }
+        }
+    }
+
+    /**
+     * @param onKeyguard whether to prevent notification expansion
+     */
+    public void setOnKeyguard(boolean onKeyguard) {
+        if (onKeyguard != mOnKeyguard) {
+            boolean wasAboveShelf = isAboveShelf();
+            final boolean wasExpanded = isExpanded();
+            mOnKeyguard = onKeyguard;
+            onExpansionChanged(false /* userAction */, wasExpanded);
+            if (wasExpanded != isExpanded()) {
+                if (mIsSummaryWithChildren) {
+                    mChildrenContainer.updateGroupOverflow();
+                }
+                notifyHeightChanged(false /* needsAnimation */);
+            }
+            if (isAboveShelf() != wasAboveShelf) {
+                mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
+            }
+        }
+        updateRippleAllowed();
+    }
+
+    private void updateRippleAllowed() {
+        boolean allowed = isOnKeyguard()
+                || mEntry.notification.getNotification().contentIntent == null;
+        setRippleAllowed(allowed);
+    }
+
+    /**
+     * @return Can the underlying notification be cleared? This can be different from whether the
+     *         notification can be dismissed in case notifications are sensitive on the lockscreen.
+     * @see #canViewBeDismissed()
+     */
+    public boolean isClearable() {
+        if (mStatusBarNotification == null || !mStatusBarNotification.isClearable()) {
+            return false;
+        }
+        if (mIsSummaryWithChildren) {
+            List<ExpandableNotificationRow> notificationChildren =
+                    mChildrenContainer.getNotificationChildren();
+            for (int i = 0; i < notificationChildren.size(); i++) {
+                ExpandableNotificationRow child = notificationChildren.get(i);
+                if (!child.isClearable()) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        if (isUserLocked()) {
+            return getActualHeight();
+        }
+        if (mGuts != null && mGuts.isExposed()) {
+            return mGuts.getIntrinsicHeight();
+        } else if ((isChildInGroup() && !isGroupExpanded())) {
+            return mPrivateLayout.getMinHeight();
+        } else if (mSensitive && mHideSensitiveForIntrinsicHeight) {
+            return getMinHeight();
+        } else if (mIsSummaryWithChildren && (!mOnKeyguard || mShowAmbient)) {
+            return mChildrenContainer.getIntrinsicHeight();
+        } else if (isHeadsUpAllowed() && (mIsHeadsUp || mHeadsupDisappearRunning)) {
+            if (isPinned() || mHeadsupDisappearRunning) {
+                return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
+            } else if (isExpanded()) {
+                return Math.max(getMaxExpandHeight(), getHeadsUpHeight());
+            } else {
+                return Math.max(getCollapsedHeight(), getHeadsUpHeight());
+            }
+        } else if (isExpanded()) {
+            return getMaxExpandHeight();
+        } else {
+            return getCollapsedHeight();
+        }
+    }
+
+    private boolean isHeadsUpAllowed() {
+        return !mOnKeyguard && !mShowAmbient;
+    }
+
+    @Override
+    public boolean isGroupExpanded() {
+        return mGroupManager.isGroupExpanded(mStatusBarNotification);
+    }
+
+    private void onChildrenCountChanged() {
+        mIsSummaryWithChildren = StatusBar.ENABLE_CHILD_NOTIFICATIONS
+                && mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0;
+        if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) {
+            mChildrenContainer.recreateNotificationHeader(mExpandClickListener
+            );
+        }
+        getShowingLayout().updateBackgroundColor(false /* animate */);
+        mPrivateLayout.updateExpandButtons(isExpandable());
+        updateChildrenHeaderAppearance();
+        updateChildrenVisibility();
+        applyChildrenRoundness();
+    }
+    /**
+     * Returns the number of channels covered by the notification row (including its children if
+     * it's a summary notification).
+     */
+    public int getNumUniqueChannels() {
+        ArraySet<NotificationChannel> channels = new ArraySet<>();
+
+        channels.add(mEntry.channel);
+
+        // If this is a summary, then add in the children notification channels for the
+        // same user and pkg.
+        if (mIsSummaryWithChildren) {
+            final List<ExpandableNotificationRow> childrenRows = getNotificationChildren();
+            final int numChildren = childrenRows.size();
+            for (int i = 0; i < numChildren; i++) {
+                final ExpandableNotificationRow childRow = childrenRows.get(i);
+                final NotificationChannel childChannel = childRow.getEntry().channel;
+                final StatusBarNotification childSbn = childRow.getStatusBarNotification();
+                if (childSbn.getUser().equals(mStatusBarNotification.getUser()) &&
+                        childSbn.getPackageName().equals(mStatusBarNotification.getPackageName())) {
+                    channels.add(childChannel);
+                }
+            }
+        }
+        return channels.size();
+    }
+
+    public void updateChildrenHeaderAppearance() {
+        if (mIsSummaryWithChildren) {
+            mChildrenContainer.updateChildrenHeaderAppearance();
+        }
+    }
+
+    /**
+     * Check whether the view state is currently expanded. This is given by the system in {@link
+     * #setSystemExpanded(boolean)} and can be overridden by user expansion or
+     * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
+     * view can differ from this state, if layout params are modified from outside.
+     *
+     * @return whether the view state is currently expanded.
+     */
+    public boolean isExpanded() {
+        return isExpanded(false /* allowOnKeyguard */);
+    }
+
+    public boolean isExpanded(boolean allowOnKeyguard) {
+        return (!mOnKeyguard || allowOnKeyguard)
+                && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
+                || isUserExpanded());
+    }
+
+    private boolean isSystemChildExpanded() {
+        return mIsSystemChildExpanded;
+    }
+
+    public void setSystemChildExpanded(boolean expanded) {
+        mIsSystemChildExpanded = expanded;
+    }
+
+    public void setLayoutListener(LayoutListener listener) {
+        mLayoutListener = listener;
+    }
+
+    public void removeListener() {
+        mLayoutListener = null;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        int intrinsicBefore = getIntrinsicHeight();
+        super.onLayout(changed, left, top, right, bottom);
+        if (intrinsicBefore != getIntrinsicHeight()) {
+            notifyHeightChanged(true  /* needsAnimation */);
+        }
+        if (mMenuRow.getMenuView() != null) {
+            mMenuRow.onHeightUpdate();
+        }
+        updateContentShiftHeight();
+        if (mLayoutListener != null) {
+            mLayoutListener.onLayout();
+        }
+    }
+
+    /**
+     * Updates the content shift height such that the header is completely hidden when coming from
+     * the top.
+     */
+    private void updateContentShiftHeight() {
+        NotificationHeaderView notificationHeader = getVisibleNotificationHeader();
+        if (notificationHeader != null) {
+            CachingIconView icon = notificationHeader.getIcon();
+            mIconTransformContentShift = getRelativeTopPadding(icon) + icon.getHeight();
+        } else {
+            mIconTransformContentShift = mIconTransformContentShiftNoIcon;
+        }
+    }
+
+    @Override
+    public void notifyHeightChanged(boolean needsAnimation) {
+        super.notifyHeightChanged(needsAnimation);
+        getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
+    }
+
+    public void setSensitive(boolean sensitive, boolean hideSensitive) {
+        mSensitive = sensitive;
+        mSensitiveHiddenInGeneral = hideSensitive;
+    }
+
+    @Override
+    public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
+        mHideSensitiveForIntrinsicHeight = hideSensitive;
+        if (mIsSummaryWithChildren) {
+            List<ExpandableNotificationRow> notificationChildren =
+                    mChildrenContainer.getNotificationChildren();
+            for (int i = 0; i < notificationChildren.size(); i++) {
+                ExpandableNotificationRow child = notificationChildren.get(i);
+                child.setHideSensitiveForIntrinsicHeight(hideSensitive);
+            }
+        }
+    }
+
+    @Override
+    public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
+            long duration) {
+        if (getVisibility() == GONE) {
+            // If we are GONE, the hideSensitive parameter will not be calculated and always be
+            // false, which is incorrect, let's wait until a real call comes in later.
+            return;
+        }
+        boolean oldShowingPublic = mShowingPublic;
+        mShowingPublic = mSensitive && hideSensitive;
+        if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
+            return;
+        }
+
+        // bail out if no public version
+        if (mPublicLayout.getChildCount() == 0) return;
+
+        if (!animated) {
+            mPublicLayout.animate().cancel();
+            mPrivateLayout.animate().cancel();
+            if (mChildrenContainer != null) {
+                mChildrenContainer.animate().cancel();
+                mChildrenContainer.setAlpha(1f);
+            }
+            mPublicLayout.setAlpha(1f);
+            mPrivateLayout.setAlpha(1f);
+            mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
+            updateChildrenVisibility();
+        } else {
+            animateShowingPublic(delay, duration, mShowingPublic);
+        }
+        NotificationContentView showingLayout = getShowingLayout();
+        showingLayout.updateBackgroundColor(animated);
+        mPrivateLayout.updateExpandButtons(isExpandable());
+        updateShelfIconColor();
+        showingLayout.setDark(isDark(), false /* animate */, 0 /* delay */);
+        mShowingPublicInitialized = true;
+    }
+
+    private void animateShowingPublic(long delay, long duration, boolean showingPublic) {
+        View[] privateViews = mIsSummaryWithChildren
+                ? new View[] {mChildrenContainer}
+                : new View[] {mPrivateLayout};
+        View[] publicViews = new View[] {mPublicLayout};
+        View[] hiddenChildren = showingPublic ? privateViews : publicViews;
+        View[] shownChildren = showingPublic ? publicViews : privateViews;
+        for (final View hiddenView : hiddenChildren) {
+            hiddenView.setVisibility(View.VISIBLE);
+            hiddenView.animate().cancel();
+            hiddenView.animate()
+                    .alpha(0f)
+                    .setStartDelay(delay)
+                    .setDuration(duration)
+                    .withEndAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            hiddenView.setVisibility(View.INVISIBLE);
+                        }
+                    });
+        }
+        for (View showView : shownChildren) {
+            showView.setVisibility(View.VISIBLE);
+            showView.setAlpha(0f);
+            showView.animate().cancel();
+            showView.animate()
+                    .alpha(1f)
+                    .setStartDelay(delay)
+                    .setDuration(duration);
+        }
+    }
+
+    @Override
+    public boolean mustStayOnScreen() {
+        return mIsHeadsUp && mMustStayOnScreen;
+    }
+
+    /**
+     * @return Whether this view is allowed to be dismissed. Only valid for visible notifications as
+     *         otherwise some state might not be updated. To request about the general clearability
+     *         see {@link #isClearable()}.
+     */
+    public boolean canViewBeDismissed() {
+        return isClearable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral);
+    }
+
+    private boolean shouldShowPublic() {
+        return mSensitive && mHideSensitiveForIntrinsicHeight;
+    }
+
+    public void makeActionsVisibile() {
+        setUserExpanded(true, true);
+        if (isChildInGroup()) {
+            mGroupManager.setGroupExpanded(mStatusBarNotification, true);
+        }
+        notifyHeightChanged(false /* needsAnimation */);
+    }
+
+    public void setChildrenExpanded(boolean expanded, boolean animate) {
+        mChildrenExpanded = expanded;
+        if (mChildrenContainer != null) {
+            mChildrenContainer.setChildrenExpanded(expanded);
+        }
+        updateBackgroundForGroupState();
+        updateClickAndFocus();
+    }
+
+    public static void applyTint(View v, int color) {
+        int alpha;
+        if (color != 0) {
+            alpha = COLORED_DIVIDER_ALPHA;
+        } else {
+            color = 0xff000000;
+            alpha = DEFAULT_DIVIDER_ALPHA;
+        }
+        if (v.getBackground() instanceof ColorDrawable) {
+            ColorDrawable background = (ColorDrawable) v.getBackground();
+            background.mutate();
+            background.setColor(color);
+            background.setAlpha(alpha);
+        }
+    }
+
+    public int getMaxExpandHeight() {
+        return mPrivateLayout.getExpandHeight();
+    }
+
+
+    private int getHeadsUpHeight() {
+        return mPrivateLayout.getHeadsUpHeight();
+    }
+
+    public boolean areGutsExposed() {
+        return (mGuts != null && mGuts.isExposed());
+    }
+
+    @Override
+    public boolean isContentExpandable() {
+        if (mIsSummaryWithChildren && !shouldShowPublic()) {
+            return true;
+        }
+        NotificationContentView showingLayout = getShowingLayout();
+        return showingLayout.isContentExpandable();
+    }
+
+    @Override
+    protected View getContentView() {
+        if (mIsSummaryWithChildren && !shouldShowPublic()) {
+            return mChildrenContainer;
+        }
+        return getShowingLayout();
+    }
+
+    @Override
+    protected void onAppearAnimationFinished(boolean wasAppearing) {
+        super.onAppearAnimationFinished(wasAppearing);
+        if (wasAppearing) {
+            // During the animation the visible view might have changed, so let's make sure all
+            // alphas are reset
+            if (mChildrenContainer != null) {
+                mChildrenContainer.setAlpha(1.0f);
+                mChildrenContainer.setLayerType(LAYER_TYPE_NONE, null);
+            }
+            for (NotificationContentView l : mLayouts) {
+                l.setAlpha(1.0f);
+                l.setLayerType(LAYER_TYPE_NONE, null);
+            }
+        }
+    }
+
+    @Override
+    public int getExtraBottomPadding() {
+        if (mIsSummaryWithChildren && isGroupExpanded()) {
+            return mIncreasedPaddingBetweenElements;
+        }
+        return 0;
+    }
+
+    @Override
+    public void setActualHeight(int height, boolean notifyListeners) {
+        boolean changed = height != getActualHeight();
+        super.setActualHeight(height, notifyListeners);
+        if (changed && isRemoved()) {
+            // TODO: remove this once we found the gfx bug for this.
+            // This is a hack since a removed view sometimes would just stay blank. it occured
+            // when sending yourself a message and then clicking on it.
+            ViewGroup parent = (ViewGroup) getParent();
+            if (parent != null) {
+                parent.invalidate();
+            }
+        }
+        if (mGuts != null && mGuts.isExposed()) {
+            mGuts.setActualHeight(height);
+            return;
+        }
+        int contentHeight = Math.max(getMinHeight(), height);
+        for (NotificationContentView l : mLayouts) {
+            l.setContentHeight(contentHeight);
+        }
+        if (mIsSummaryWithChildren) {
+            mChildrenContainer.setActualHeight(height);
+        }
+        if (mGuts != null) {
+            mGuts.setActualHeight(height);
+        }
+        if (mMenuRow.getMenuView() != null) {
+            mMenuRow.onHeightUpdate();
+        }
+    }
+
+    @Override
+    public int getMaxContentHeight() {
+        if (mIsSummaryWithChildren && !shouldShowPublic()) {
+            return mChildrenContainer.getMaxContentHeight();
+        }
+        NotificationContentView showingLayout = getShowingLayout();
+        return showingLayout.getMaxHeight();
+    }
+
+    @Override
+    public int getMinHeight(boolean ignoreTemporaryStates) {
+        if (!ignoreTemporaryStates && mGuts != null && mGuts.isExposed()) {
+            return mGuts.getIntrinsicHeight();
+        } else if (!ignoreTemporaryStates && isHeadsUpAllowed() && mIsHeadsUp
+                && mHeadsUpManager.isTrackingHeadsUp()) {
+                return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
+        } else if (mIsSummaryWithChildren && !isGroupExpanded() && !shouldShowPublic()) {
+            return mChildrenContainer.getMinHeight();
+        } else if (!ignoreTemporaryStates && isHeadsUpAllowed() && mIsHeadsUp) {
+            return getHeadsUpHeight();
+        }
+        NotificationContentView showingLayout = getShowingLayout();
+        return showingLayout.getMinHeight();
+    }
+
+    @Override
+    public int getCollapsedHeight() {
+        if (mIsSummaryWithChildren && !shouldShowPublic()) {
+            return mChildrenContainer.getCollapsedHeight();
+        }
+        return getMinHeight();
+    }
+
+    @Override
+    public void setClipTopAmount(int clipTopAmount) {
+        super.setClipTopAmount(clipTopAmount);
+        for (NotificationContentView l : mLayouts) {
+            l.setClipTopAmount(clipTopAmount);
+        }
+        if (mGuts != null) {
+            mGuts.setClipTopAmount(clipTopAmount);
+        }
+    }
+
+    @Override
+    public void setClipBottomAmount(int clipBottomAmount) {
+        if (mExpandAnimationRunning) {
+            return;
+        }
+        if (clipBottomAmount != mClipBottomAmount) {
+            super.setClipBottomAmount(clipBottomAmount);
+            for (NotificationContentView l : mLayouts) {
+                l.setClipBottomAmount(clipBottomAmount);
+            }
+            if (mGuts != null) {
+                mGuts.setClipBottomAmount(clipBottomAmount);
+            }
+        }
+        if (mChildrenContainer != null && !mChildIsExpanding) {
+            // We have to update this even if it hasn't changed, since the children locations can
+            // have changed
+            mChildrenContainer.setClipBottomAmount(clipBottomAmount);
+        }
+    }
+
+    public NotificationContentView getShowingLayout() {
+        return shouldShowPublic() ? mPublicLayout : mPrivateLayout;
+    }
+
+    public void setLegacy(boolean legacy) {
+        for (NotificationContentView l : mLayouts) {
+            l.setLegacy(legacy);
+        }
+    }
+
+    @Override
+    protected void updateBackgroundTint() {
+        super.updateBackgroundTint();
+        updateBackgroundForGroupState();
+        if (mIsSummaryWithChildren) {
+            List<ExpandableNotificationRow> notificationChildren =
+                    mChildrenContainer.getNotificationChildren();
+            for (int i = 0; i < notificationChildren.size(); i++) {
+                ExpandableNotificationRow child = notificationChildren.get(i);
+                child.updateBackgroundForGroupState();
+            }
+        }
+    }
+
+    /**
+     * Called when a group has finished animating from collapsed or expanded state.
+     */
+    public void onFinishedExpansionChange() {
+        mGroupExpansionChanging = false;
+        updateBackgroundForGroupState();
+    }
+
+    /**
+     * Updates the parent and children backgrounds in a group based on the expansion state.
+     */
+    public void updateBackgroundForGroupState() {
+        if (mIsSummaryWithChildren) {
+            // Only when the group has finished expanding do we hide its background.
+            mShowNoBackground = !mShowGroupBackgroundWhenExpanded && isGroupExpanded()
+                    && !isGroupExpansionChanging() && !isUserLocked();
+            mChildrenContainer.updateHeaderForExpansion(mShowNoBackground);
+            List<ExpandableNotificationRow> children = mChildrenContainer.getNotificationChildren();
+            for (int i = 0; i < children.size(); i++) {
+                children.get(i).updateBackgroundForGroupState();
+            }
+        } else if (isChildInGroup()) {
+            final int childColor = getShowingLayout().getBackgroundColorForExpansionState();
+            // Only show a background if the group is expanded OR if it is expanding / collapsing
+            // and has a custom background color.
+            final boolean showBackground = isGroupExpanded()
+                    || ((mNotificationParent.isGroupExpansionChanging()
+                    || mNotificationParent.isUserLocked()) && childColor != 0);
+            mShowNoBackground = !showBackground;
+        } else {
+            // Only children or parents ever need no background.
+            mShowNoBackground = false;
+        }
+        updateOutline();
+        updateBackground();
+    }
+
+    public int getPositionOfChild(ExpandableNotificationRow childRow) {
+        if (mIsSummaryWithChildren) {
+            return mChildrenContainer.getPositionInLinearLayout(childRow);
+        }
+        return 0;
+    }
+
+    public void setExpansionLogger(ExpansionLogger logger, String key) {
+        mLogger = logger;
+        mLoggingKey = key;
+    }
+
+    public void onExpandedByGesture(boolean userExpanded) {
+        int event = MetricsEvent.ACTION_NOTIFICATION_GESTURE_EXPANDER;
+        if (mGroupManager.isSummaryOfGroup(getStatusBarNotification())) {
+            event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER;
+        }
+        MetricsLogger.action(mContext, event, userExpanded);
+    }
+
+    @Override
+    public float getIncreasedPaddingAmount() {
+        if (mIsSummaryWithChildren) {
+            if (isGroupExpanded()) {
+                return 1.0f;
+            } else if (isUserLocked()) {
+                return mChildrenContainer.getIncreasedPaddingAmount();
+            }
+        } else if (isColorized() && (!mIsLowPriority || isExpanded())) {
+            return -1.0f;
+        }
+        return 0.0f;
+    }
+
+    private boolean isColorized() {
+        return mIsColorized && mBgTint != NO_COLOR;
+    }
+
+    @Override
+    protected boolean disallowSingleClick(MotionEvent event) {
+        if (areGutsExposed()) {
+            return false;
+        }
+        float x = event.getX();
+        float y = event.getY();
+        NotificationHeaderView header = getVisibleNotificationHeader();
+        if (header != null && header.isInTouchRect(x - getTranslation(), y)) {
+            return true;
+        }
+        if ((!mIsSummaryWithChildren || shouldShowPublic())
+                && getShowingLayout().disallowSingleClick(x, y)) {
+            return true;
+        }
+        return super.disallowSingleClick(event);
+    }
+
+    private void onExpansionChanged(boolean userAction, boolean wasExpanded) {
+        boolean nowExpanded = isExpanded();
+        if (mIsSummaryWithChildren && (!mIsLowPriority || wasExpanded)) {
+            nowExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
+        }
+        if (nowExpanded != wasExpanded) {
+            updateShelfIconColor();
+            if (mLogger != null) {
+                mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded);
+            }
+            if (mIsSummaryWithChildren) {
+                mChildrenContainer.onExpansionChanged();
+            }
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfoInternal(info);
+        info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
+        if (canViewBeDismissed()) {
+            info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
+        }
+        boolean expandable = shouldShowPublic();
+        boolean isExpanded = false;
+        if (!expandable) {
+            if (mIsSummaryWithChildren) {
+                expandable = true;
+                if (!mIsLowPriority || isExpanded()) {
+                    isExpanded = isGroupExpanded();
+                }
+            } else {
+                expandable = mPrivateLayout.isContentExpandable();
+                isExpanded = isExpanded();
+            }
+        }
+        if (expandable) {
+            if (isExpanded) {
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
+            } else {
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
+            }
+        }
+        NotificationMenuRowPlugin provider = getProvider();
+        if (provider != null) {
+            MenuItem snoozeMenu = provider.getSnoozeMenuItem(getContext());
+            if (snoozeMenu != null) {
+                AccessibilityAction action = new AccessibilityAction(R.id.action_snooze,
+                    getContext().getResources()
+                        .getString(R.string.notification_menu_snooze_action));
+                info.addAction(action);
+            }
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+        if (super.performAccessibilityActionInternal(action, arguments)) {
+            return true;
+        }
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_DISMISS:
+                performDismissWithBlockingHelper(true /* fromAccessibility */);
+                return true;
+            case AccessibilityNodeInfo.ACTION_COLLAPSE:
+            case AccessibilityNodeInfo.ACTION_EXPAND:
+                mExpandClickListener.onClick(this);
+                return true;
+            case AccessibilityNodeInfo.ACTION_LONG_CLICK:
+                doLongClickCallback();
+                return true;
+            default:
+                if (action == R.id.action_snooze) {
+                    NotificationMenuRowPlugin provider = getProvider();
+                    if (provider == null) {
+                        provider = createMenu();
+                    }
+                    MenuItem snoozeMenu = provider.getSnoozeMenuItem(getContext());
+                    if (snoozeMenu != null) {
+                        doLongClickCallback(getWidth() / 2, getHeight() / 2, snoozeMenu);
+                    }
+                    return true;
+                }
+        }
+        return false;
+    }
+
+    public boolean shouldRefocusOnDismiss() {
+        return mRefocusOnDismiss || isAccessibilityFocused();
+    }
+
+    public interface OnExpandClickListener {
+        void onExpandClicked(NotificationData.Entry clickedEntry, boolean nowExpanded);
+    }
+
+    @Override
+    public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
+        mNotificationViewState = new NotificationViewState(stackScrollState);
+        return mNotificationViewState;
+    }
+
+    public NotificationViewState getViewState() {
+        return mNotificationViewState;
+    }
+
+    @Override
+    public boolean isAboveShelf() {
+        return !isOnKeyguard()
+                && (mIsPinned || mHeadsupDisappearRunning || (mIsHeadsUp && mAboveShelf)
+                || mExpandAnimationRunning || mChildIsExpanding);
+    }
+
+    public void setShowAmbient(boolean showAmbient) {
+        if (showAmbient != mShowAmbient) {
+            mShowAmbient = showAmbient;
+            if (mChildrenContainer != null) {
+                mChildrenContainer.notifyShowAmbientChanged();
+            }
+            notifyHeightChanged(false /* needsAnimation */);
+        }
+    }
+
+    @Override
+    public boolean topAmountNeedsClipping() {
+        if (isGroupExpanded()) {
+            return true;
+        }
+        if (isGroupExpansionChanging()) {
+            return true;
+        }
+        if (getShowingLayout().shouldClipToRounding(true /* topRounded */,
+                false /* bottomRounded */)) {
+            return true;
+        }
+        if (mGuts != null && mGuts.getAlpha() != 0.0f) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean childNeedsClipping(View child) {
+        if (child instanceof NotificationContentView) {
+            NotificationContentView contentView = (NotificationContentView) child;
+            if (isClippingNeeded()) {
+                return true;
+            } else if (!hasNoRounding()
+                    && contentView.shouldClipToRounding(getCurrentTopRoundness() != 0.0f,
+                    getCurrentBottomRoundness() != 0.0f)) {
+                return true;
+            }
+        } else if (child == mChildrenContainer) {
+            if (!mChildIsExpanding && (isClippingNeeded() || !hasNoRounding())) {
+                return true;
+            }
+        } else if (child instanceof NotificationGuts) {
+            return !hasNoRounding();
+        }
+        return super.childNeedsClipping(child);
+    }
+
+    @Override
+    protected void applyRoundness() {
+        super.applyRoundness();
+        applyChildrenRoundness();
+    }
+
+    private void applyChildrenRoundness() {
+        if (mIsSummaryWithChildren) {
+            mChildrenContainer.setCurrentBottomRoundness(getCurrentBottomRoundness());
+        }
+    }
+
+    @Override
+    public Path getCustomClipPath(View child) {
+        if (child instanceof NotificationGuts) {
+            return getClipPath(true /* ignoreTranslation */);
+        }
+        return super.getCustomClipPath(child);
+    }
+
+    private boolean hasNoRounding() {
+        return getCurrentBottomRoundness() == 0.0f && getCurrentTopRoundness() == 0.0f;
+    }
+
+    public boolean isShowingAmbient() {
+        return mShowAmbient;
+    }
+
+    public void setAboveShelf(boolean aboveShelf) {
+        boolean wasAboveShelf = isAboveShelf();
+        mAboveShelf = aboveShelf;
+        if (isAboveShelf() != wasAboveShelf) {
+            mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
+        }
+    }
+
+    public static class NotificationViewState extends ExpandableViewState {
+
+        private final StackScrollState mOverallState;
+
+
+        private NotificationViewState(StackScrollState stackScrollState) {
+            mOverallState = stackScrollState;
+        }
+
+        @Override
+        public void applyToView(View view) {
+            if (view instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+                if (row.isExpandAnimationRunning()) {
+                    return;
+                }
+                handleFixedTranslationZ(row);
+                super.applyToView(view);
+                row.applyChildrenState(mOverallState);
+            }
+        }
+
+        private void handleFixedTranslationZ(ExpandableNotificationRow row) {
+            if (row.hasExpandingChild()) {
+                zTranslation = row.getTranslationZ();
+                clipTopAmount = row.getClipTopAmount();
+            }
+        }
+
+        @Override
+        protected void onYTranslationAnimationFinished(View view) {
+            super.onYTranslationAnimationFinished(view);
+            if (view instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+                if (row.isHeadsUpAnimatingAway()) {
+                    row.setHeadsUpAnimatingAway(false);
+                }
+            }
+        }
+
+        @Override
+        public void animateTo(View child, AnimationProperties properties) {
+            if (child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                if (row.isExpandAnimationRunning()) {
+                    return;
+                }
+                handleFixedTranslationZ(row);
+                super.animateTo(child, properties);
+                row.startChildAnimation(mOverallState, properties);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    protected void setChildrenContainer(NotificationChildrenContainer childrenContainer) {
+        mChildrenContainer = childrenContainer;
+    }
+
+    @VisibleForTesting
+    protected void setPrivateLayout(NotificationContentView privateLayout) {
+        mPrivateLayout = privateLayout;
+    }
+
+    @VisibleForTesting
+    protected void setPublicLayout(NotificationContentView publicLayout) {
+        mPublicLayout = publicLayout;
+    }
+
+    /**
+     * Equivalent to View.OnLongClickListener with coordinates
+     */
+    public interface LongPressListener {
+        /**
+         * Equivalent to {@link View.OnLongClickListener#onLongClick(View)} with coordinates
+         * @return whether the longpress was handled
+         */
+        boolean onLongPress(View v, int x, int y, MenuItem item);
+    }
+
+    /**
+     * Equivalent to View.OnClickListener with coordinates
+     */
+    public interface OnAppOpsClickListener {
+        /**
+         * Equivalent to {@link View.OnClickListener#onClick(View)} with coordinates
+         * @return whether the click was handled
+         */
+        boolean onClick(View v, int x, int y, MenuItem item);
+    }
+
+    /**
+     * Background task for executing IPCs to check if the notification is a system notification. The
+     * output is used for both the blocking helper and the notification info.
+     */
+    private class SystemNotificationAsyncTask extends AsyncTask<Void, Void, Boolean> {
+
+        @Override
+        protected Boolean doInBackground(Void... voids) {
+            return isSystemNotification(mContext, mStatusBarNotification);
+        }
+
+        @Override
+        protected void onPostExecute(Boolean result) {
+            if (mEntry != null) {
+                mEntry.mIsSystemNotification = result;
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
new file mode 100644
index 0000000..a7aed5f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Outline;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.AnimatableProperty;
+import com.android.systemui.statusbar.notification.PropertyAnimator;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+
+/**
+ * Like {@link ExpandableView}, but setting an outline for the height and clipping.
+ */
+public abstract class ExpandableOutlineView extends ExpandableView {
+
+    private static final AnimatableProperty TOP_ROUNDNESS = AnimatableProperty.from(
+            "topRoundness",
+            ExpandableOutlineView::setTopRoundnessInternal,
+            ExpandableOutlineView::getCurrentTopRoundness,
+            R.id.top_roundess_animator_tag,
+            R.id.top_roundess_animator_end_tag,
+            R.id.top_roundess_animator_start_tag);
+    private static final AnimatableProperty BOTTOM_ROUNDNESS = AnimatableProperty.from(
+            "bottomRoundness",
+            ExpandableOutlineView::setBottomRoundnessInternal,
+            ExpandableOutlineView::getCurrentBottomRoundness,
+            R.id.bottom_roundess_animator_tag,
+            R.id.bottom_roundess_animator_end_tag,
+            R.id.bottom_roundess_animator_start_tag);
+    private static final AnimationProperties ROUNDNESS_PROPERTIES =
+            new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+    private static final Path EMPTY_PATH = new Path();
+
+    private final Rect mOutlineRect = new Rect();
+    private final Path mClipPath = new Path();
+    private boolean mCustomOutline;
+    private float mOutlineAlpha = -1f;
+    protected float mOutlineRadius;
+    private boolean mAlwaysRoundBothCorners;
+    private Path mTmpPath = new Path();
+    private float mCurrentBottomRoundness;
+    private float mCurrentTopRoundness;
+    private float mBottomRoundness;
+    private float mTopRoundness;
+    private int mBackgroundTop;
+
+    /**
+     * {@code true} if the children views of the {@link ExpandableOutlineView} are translated when
+     * it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
+     */
+    protected boolean mShouldTranslateContents;
+    private boolean mTopAmountRounded;
+    private float mDistanceToTopRoundness = -1;
+    private float mExtraWidthForClipping;
+    private int mMinimumHeightForClipping = 0;
+
+    private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
+        @Override
+        public void getOutline(View view, Outline outline) {
+            if (!mCustomOutline && mCurrentTopRoundness == 0.0f
+                    && mCurrentBottomRoundness == 0.0f && !mAlwaysRoundBothCorners
+                    && !mTopAmountRounded) {
+                int translation = mShouldTranslateContents ? (int) getTranslation() : 0;
+                int left = Math.max(translation, 0);
+                int top = mClipTopAmount + mBackgroundTop;
+                int right = getWidth() + Math.min(translation, 0);
+                int bottom = Math.max(getActualHeight() - mClipBottomAmount, top);
+                outline.setRect(left, top, right, bottom);
+            } else {
+                Path clipPath = getClipPath(false /* ignoreTranslation */);
+                if (clipPath != null && clipPath.isConvex()) {
+                    // The path might not be convex in border cases where the view is small and
+                    // clipped
+                    outline.setConvexPath(clipPath);
+                }
+            }
+            outline.setAlpha(mOutlineAlpha);
+        }
+    };
+
+    protected Path getClipPath(boolean ignoreTranslation) {
+        int left;
+        int top;
+        int right;
+        int bottom;
+        int height;
+        float topRoundness = mAlwaysRoundBothCorners
+                ? mOutlineRadius : getCurrentBackgroundRadiusTop();
+        if (!mCustomOutline) {
+            int translation = mShouldTranslateContents && !ignoreTranslation
+                    ? (int) getTranslation() : 0;
+            left = Math.max(translation, 0);
+            top = mClipTopAmount + mBackgroundTop;
+            right = getWidth() + Math.min(translation, 0);
+            // If the top is rounded we want the bottom to be at most at the top roundness, in order
+            // to avoid the shadow changing when scrolling up.
+            bottom = Math.max(getActualHeight() - mClipBottomAmount, (int) (top + topRoundness));
+        } else {
+            left = mOutlineRect.left;
+            top = mOutlineRect.top;
+            right = mOutlineRect.right;
+            bottom = mOutlineRect.bottom;
+        }
+        height = bottom - top;
+        if (height == 0) {
+            return EMPTY_PATH;
+        }
+        float bottomRoundness = mAlwaysRoundBothCorners
+                ? mOutlineRadius : getCurrentBackgroundRadiusBottom();
+        if (topRoundness + bottomRoundness > height) {
+            float overShoot = topRoundness + bottomRoundness - height;
+            topRoundness -= overShoot * mCurrentTopRoundness
+                    / (mCurrentTopRoundness + mCurrentBottomRoundness);
+            bottomRoundness -= overShoot * mCurrentBottomRoundness
+                    / (mCurrentTopRoundness + mCurrentBottomRoundness);
+        }
+        getRoundedRectPath(left, top, right, bottom, topRoundness,
+                bottomRoundness, mTmpPath);
+        return mTmpPath;
+    }
+
+    public static void getRoundedRectPath(int left, int top, int right, int bottom,
+            float topRoundness, float bottomRoundness, Path outPath) {
+        outPath.reset();
+        int width = right - left;
+        float topRoundnessX = topRoundness;
+        float bottomRoundnessX = bottomRoundness;
+        topRoundnessX = Math.min(width / 2, topRoundnessX);
+        bottomRoundnessX = Math.min(width / 2, bottomRoundnessX);
+        if (topRoundness > 0.0f) {
+            outPath.moveTo(left, top + topRoundness);
+            outPath.quadTo(left, top, left + topRoundnessX, top);
+            outPath.lineTo(right - topRoundnessX, top);
+            outPath.quadTo(right, top, right, top + topRoundness);
+        } else {
+            outPath.moveTo(left, top);
+            outPath.lineTo(right, top);
+        }
+        if (bottomRoundness > 0.0f) {
+            outPath.lineTo(right, bottom - bottomRoundness);
+            outPath.quadTo(right, bottom, right - bottomRoundnessX, bottom);
+            outPath.lineTo(left + bottomRoundnessX, bottom);
+            outPath.quadTo(left, bottom, left, bottom - bottomRoundness);
+        } else {
+            outPath.lineTo(right, bottom);
+            outPath.lineTo(left, bottom);
+        }
+        outPath.close();
+    }
+
+    public ExpandableOutlineView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setOutlineProvider(mProvider);
+        initDimens();
+    }
+
+    @Override
+    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+        canvas.save();
+        Path intersectPath = null;
+        if (mTopAmountRounded && topAmountNeedsClipping()) {
+            int left = (int) (- mExtraWidthForClipping / 2.0f);
+            int top = (int) (mClipTopAmount - mDistanceToTopRoundness);
+            int right = getWidth() + (int) (mExtraWidthForClipping + left);
+            int bottom = (int) Math.max(mMinimumHeightForClipping,
+                    Math.max(getActualHeight() - mClipBottomAmount, top + mOutlineRadius));
+            ExpandableOutlineView.getRoundedRectPath(left, top, right, bottom, mOutlineRadius,
+                    0.0f,
+                    mClipPath);
+            intersectPath = mClipPath;
+        }
+        boolean clipped = false;
+        if (childNeedsClipping(child)) {
+            Path clipPath = getCustomClipPath(child);
+            if (clipPath == null) {
+                clipPath = getClipPath(false /* ignoreTranslation */);
+            }
+            if (clipPath != null) {
+                if (intersectPath != null) {
+                    clipPath.op(intersectPath, Path.Op.INTERSECT);
+                }
+                canvas.clipPath(clipPath);
+                clipped = true;
+            }
+        }
+        if (!clipped && intersectPath != null) {
+            canvas.clipPath(intersectPath);
+        }
+        boolean result = super.drawChild(canvas, child, drawingTime);
+        canvas.restore();
+        return result;
+    }
+
+    public void setExtraWidthForClipping(float extraWidthForClipping) {
+        mExtraWidthForClipping = extraWidthForClipping;
+    }
+
+    public void setMinimumHeightForClipping(int minimumHeightForClipping) {
+        mMinimumHeightForClipping = minimumHeightForClipping;
+    }
+
+    @Override
+    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+        super.setDistanceToTopRoundness(distanceToTopRoundness);
+        if (distanceToTopRoundness != mDistanceToTopRoundness) {
+            mTopAmountRounded = distanceToTopRoundness >= 0;
+            mDistanceToTopRoundness = distanceToTopRoundness;
+            applyRoundness();
+        }
+    }
+
+    protected boolean childNeedsClipping(View child) {
+        return false;
+    }
+
+    public boolean topAmountNeedsClipping() {
+        return true;
+    }
+
+    protected boolean isClippingNeeded() {
+        return mAlwaysRoundBothCorners || mCustomOutline || getTranslation() != 0 ;
+    }
+
+    private void initDimens() {
+        Resources res = getResources();
+        mShouldTranslateContents =
+                res.getBoolean(R.bool.config_translateNotificationContentsOnSwipe);
+        mOutlineRadius = res.getDimension(R.dimen.notification_shadow_radius);
+        mAlwaysRoundBothCorners = res.getBoolean(R.bool.config_clipNotificationsToOutline);
+        if (!mAlwaysRoundBothCorners) {
+            mOutlineRadius = res.getDimensionPixelSize(
+                    Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius));
+        }
+        setClipToOutline(mAlwaysRoundBothCorners);
+    }
+
+    /**
+     * Set the topRoundness of this view.
+     * @return Whether the roundness was changed.
+     */
+    public boolean setTopRoundness(float topRoundness, boolean animate) {
+        if (mTopRoundness != topRoundness) {
+            mTopRoundness = topRoundness;
+            PropertyAnimator.setProperty(this, TOP_ROUNDNESS, topRoundness,
+                    ROUNDNESS_PROPERTIES, animate);
+            return true;
+        }
+        return false;
+    }
+
+    protected void applyRoundness() {
+        invalidateOutline();
+        invalidate();
+    }
+
+    public float getCurrentBackgroundRadiusTop() {
+        // If this view is top amount notification view, it should always has round corners on top.
+        // It will be applied with applyRoundness()
+        if (mTopAmountRounded) {
+            return mOutlineRadius;
+        }
+        return mCurrentTopRoundness * mOutlineRadius;
+    }
+
+    public float getCurrentTopRoundness() {
+        return mCurrentTopRoundness;
+    }
+
+    public float getCurrentBottomRoundness() {
+        return mCurrentBottomRoundness;
+    }
+
+    protected float getCurrentBackgroundRadiusBottom() {
+        return mCurrentBottomRoundness * mOutlineRadius;
+    }
+
+    /**
+     * Set the bottom roundness of this view.
+     * @return Whether the roundness was changed.
+     */
+    public boolean setBottomRoundness(float bottomRoundness, boolean animate) {
+        if (mBottomRoundness != bottomRoundness) {
+            mBottomRoundness = bottomRoundness;
+            PropertyAnimator.setProperty(this, BOTTOM_ROUNDNESS, bottomRoundness,
+                    ROUNDNESS_PROPERTIES, animate);
+            return true;
+        }
+        return false;
+    }
+
+    protected void setBackgroundTop(int backgroundTop) {
+        if (mBackgroundTop != backgroundTop) {
+            mBackgroundTop = backgroundTop;
+            invalidateOutline();
+        }
+    }
+
+    private void setTopRoundnessInternal(float topRoundness) {
+        mCurrentTopRoundness = topRoundness;
+        applyRoundness();
+    }
+
+    private void setBottomRoundnessInternal(float bottomRoundness) {
+        mCurrentBottomRoundness = bottomRoundness;
+        applyRoundness();
+    }
+
+    public void onDensityOrFontScaleChanged() {
+        initDimens();
+        applyRoundness();
+    }
+
+    @Override
+    public void setActualHeight(int actualHeight, boolean notifyListeners) {
+        int previousHeight = getActualHeight();
+        super.setActualHeight(actualHeight, notifyListeners);
+        if (previousHeight != actualHeight) {
+            applyRoundness();
+        }
+    }
+
+    @Override
+    public void setClipTopAmount(int clipTopAmount) {
+        int previousAmount = getClipTopAmount();
+        super.setClipTopAmount(clipTopAmount);
+        if (previousAmount != clipTopAmount) {
+            applyRoundness();
+        }
+    }
+
+    @Override
+    public void setClipBottomAmount(int clipBottomAmount) {
+        int previousAmount = getClipBottomAmount();
+        super.setClipBottomAmount(clipBottomAmount);
+        if (previousAmount != clipBottomAmount) {
+            applyRoundness();
+        }
+    }
+
+    protected void setOutlineAlpha(float alpha) {
+        if (alpha != mOutlineAlpha) {
+            mOutlineAlpha = alpha;
+            applyRoundness();
+        }
+    }
+
+    @Override
+    public float getOutlineAlpha() {
+        return mOutlineAlpha;
+    }
+
+    protected void setOutlineRect(RectF rect) {
+        if (rect != null) {
+            setOutlineRect(rect.left, rect.top, rect.right, rect.bottom);
+        } else {
+            mCustomOutline = false;
+            applyRoundness();
+        }
+    }
+
+    @Override
+    public int getOutlineTranslation() {
+        return mCustomOutline ? mOutlineRect.left : (int) getTranslation();
+    }
+
+    public void updateOutline() {
+        if (mCustomOutline) {
+            return;
+        }
+        boolean hasOutline = needsOutline();
+        setOutlineProvider(hasOutline ? mProvider : null);
+    }
+
+    /**
+     * @return Whether the view currently needs an outline. This is usually {@code false} in case
+     * it doesn't have a background.
+     */
+    protected boolean needsOutline() {
+        if (isChildInGroup()) {
+            return isGroupExpanded() && !isGroupExpansionChanging();
+        } else if (isSummaryWithChildren()) {
+            return !isGroupExpanded() || isGroupExpansionChanging();
+        }
+        return true;
+    }
+
+    public boolean isOutlineShowing() {
+        ViewOutlineProvider op = getOutlineProvider();
+        return op != null;
+    }
+
+    protected void setOutlineRect(float left, float top, float right, float bottom) {
+        mCustomOutline = true;
+
+        mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom);
+
+        // Outlines need to be at least 1 dp
+        mOutlineRect.bottom = (int) Math.max(top, mOutlineRect.bottom);
+        mOutlineRect.right = (int) Math.max(left, mOutlineRect.right);
+        applyRoundness();
+    }
+
+    public Path getCustomClipPath(View child) {
+        return null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
new file mode 100644
index 0000000..46019e3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -0,0 +1,581 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.StackScrollState;
+
+import java.util.ArrayList;
+
+/**
+ * An abstract view for expandable views.
+ */
+public abstract class ExpandableView extends FrameLayout {
+
+    public static final float NO_ROUNDNESS = -1;
+    protected OnHeightChangedListener mOnHeightChangedListener;
+    private int mActualHeight;
+    protected int mClipTopAmount;
+    protected int mClipBottomAmount;
+    private boolean mDark;
+    private ArrayList<View> mMatchParentViews = new ArrayList<View>();
+    private static Rect mClipRect = new Rect();
+    private boolean mWillBeGone;
+    private int mMinClipTopAmount = 0;
+    private boolean mClipToActualHeight = true;
+    private boolean mChangingPosition = false;
+    private ViewGroup mTransientContainer;
+    private boolean mInShelf;
+    private boolean mTransformingInShelf;
+
+    public ExpandableView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int givenSize = MeasureSpec.getSize(heightMeasureSpec);
+        final int viewHorizontalPadding = getPaddingStart() + getPaddingEnd();
+        int ownMaxHeight = Integer.MAX_VALUE;
+        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        if (heightMode != MeasureSpec.UNSPECIFIED && givenSize != 0) {
+            ownMaxHeight = Math.min(givenSize, ownMaxHeight);
+        }
+        int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
+        int maxChildHeight = 0;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() == GONE) {
+                continue;
+            }
+            int childHeightSpec = newHeightSpec;
+            ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
+            if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) {
+                if (layoutParams.height >= 0) {
+                    // An actual height is set
+                    childHeightSpec = layoutParams.height > ownMaxHeight
+                        ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY)
+                        : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
+                }
+                child.measure(getChildMeasureSpec(
+                        widthMeasureSpec, viewHorizontalPadding, layoutParams.width),
+                        childHeightSpec);
+                int childHeight = child.getMeasuredHeight();
+                maxChildHeight = Math.max(maxChildHeight, childHeight);
+            } else {
+                mMatchParentViews.add(child);
+            }
+        }
+        int ownHeight = heightMode == MeasureSpec.EXACTLY
+                ? givenSize : Math.min(ownMaxHeight, maxChildHeight);
+        newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
+        for (View child : mMatchParentViews) {
+            child.measure(getChildMeasureSpec(
+                    widthMeasureSpec, viewHorizontalPadding, child.getLayoutParams().width),
+                    newHeightSpec);
+        }
+        mMatchParentViews.clear();
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        setMeasuredDimension(width, ownHeight);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        updateClipping();
+    }
+
+    @Override
+    public boolean pointInView(float localX, float localY, float slop) {
+        float top = mClipTopAmount;
+        float bottom = mActualHeight;
+        return localX >= -slop && localY >= top - slop && localX < ((mRight - mLeft) + slop) &&
+                localY < (bottom + slop);
+    }
+
+    /**
+     * Sets the actual height of this notification. This is different than the laid out
+     * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
+     *
+     * @param actualHeight The height of this notification.
+     * @param notifyListeners Whether the listener should be informed about the change.
+     */
+    public void setActualHeight(int actualHeight, boolean notifyListeners) {
+        mActualHeight = actualHeight;
+        updateClipping();
+        if (notifyListeners) {
+            notifyHeightChanged(false  /* needsAnimation */);
+        }
+    }
+
+    /**
+     * Set the distance to the top roundness, from where we should start clipping a value above
+     * or equal to 0 is the effective distance, and if a value below 0 is received, there should
+     * be no clipping.
+     */
+    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+    }
+
+    public void setActualHeight(int actualHeight) {
+        setActualHeight(actualHeight, true /* notifyListeners */);
+    }
+
+    /**
+     * See {@link #setActualHeight}.
+     *
+     * @return The current actual height of this notification.
+     */
+    public int getActualHeight() {
+        return mActualHeight;
+    }
+
+    public boolean isExpandAnimationRunning() {
+        return false;
+    }
+
+    /**
+     * @return The maximum height of this notification.
+     */
+    public int getMaxContentHeight() {
+        return getHeight();
+    }
+
+    /**
+     * @return The minimum content height of this notification. This also respects the temporary
+     * states of the view.
+     */
+    public int getMinHeight() {
+        return getMinHeight(false /* ignoreTemporaryStates */);
+    }
+
+    /**
+     * Get the minimum height of this view.
+     *
+     * @param ignoreTemporaryStates should temporary states be ignored like the guts or heads-up.
+     *
+     * @return The minimum height that this view needs.
+     */
+    public int getMinHeight(boolean ignoreTemporaryStates) {
+        return getHeight();
+    }
+
+    /**
+     * @return The collapsed height of this view. Note that this might be different
+     * than {@link #getMinHeight()} because some elements like groups may have different sizes when
+     * they are system expanded.
+     */
+    public int getCollapsedHeight() {
+        return getHeight();
+    }
+
+    /**
+     * Sets the notification as dimmed. The default implementation does nothing.
+     *
+     * @param dimmed Whether the notification should be dimmed.
+     * @param fade Whether an animation should be played to change the state.
+     */
+    public void setDimmed(boolean dimmed, boolean fade) {
+    }
+
+    /**
+     * Sets the notification as dark. The default implementation does nothing.
+     *
+     * @param dark Whether the notification should be dark.
+     * @param fade Whether an animation should be played to change the state.
+     * @param delay If fading, the delay of the animation.
+     */
+    public void setDark(boolean dark, boolean fade, long delay) {
+        mDark = dark;
+    }
+
+    public boolean isDark() {
+        return mDark;
+    }
+
+    public boolean isRemoved() {
+        return false;
+    }
+
+    /**
+     * See {@link #setHideSensitive}. This is a variant which notifies this view in advance about
+     * the upcoming state of hiding sensitive notifications. It gets called at the very beginning
+     * of a stack scroller update such that the updated intrinsic height (which is dependent on
+     * whether private or public layout is showing) gets taken into account into all layout
+     * calculations.
+     */
+    public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
+    }
+
+    /**
+     * Sets whether the notification should hide its private contents if it is sensitive.
+     */
+    public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
+            long duration) {
+    }
+
+    /**
+     * @return The desired notification height.
+     */
+    public int getIntrinsicHeight() {
+        return getHeight();
+    }
+
+    /**
+     * Sets the amount this view should be clipped from the top. This is used when an expanded
+     * notification is scrolling in the top or bottom stack.
+     *
+     * @param clipTopAmount The amount of pixels this view should be clipped from top.
+     */
+    public void setClipTopAmount(int clipTopAmount) {
+        mClipTopAmount = clipTopAmount;
+        updateClipping();
+    }
+
+    /**
+     * Set the amount the the notification is clipped on the bottom in addition to the regular
+     * clipping. This is mainly used to clip something in a non-animated way without changing the
+     * actual height of the notification and is purely visual.
+     *
+     * @param clipBottomAmount the amount to clip.
+     */
+    public void setClipBottomAmount(int clipBottomAmount) {
+        mClipBottomAmount = clipBottomAmount;
+        updateClipping();
+    }
+
+    public int getClipTopAmount() {
+        return mClipTopAmount;
+    }
+
+    public int getClipBottomAmount() {
+        return mClipBottomAmount;
+    }
+
+    public void setOnHeightChangedListener(OnHeightChangedListener listener) {
+        mOnHeightChangedListener = listener;
+    }
+
+    /**
+     * @return Whether we can expand this views content.
+     */
+    public boolean isContentExpandable() {
+        return false;
+    }
+
+    public void notifyHeightChanged(boolean needsAnimation) {
+        if (mOnHeightChangedListener != null) {
+            mOnHeightChangedListener.onHeightChanged(this, needsAnimation);
+        }
+    }
+
+    public boolean isTransparent() {
+        return false;
+    }
+
+    /**
+     * Perform a remove animation on this view.
+     * @param duration The duration of the remove animation.
+     * @param delay The delay of the animation
+     * @param translationDirection The direction value from [-1 ... 1] indicating in which the
+ *                             animation should be performed. A value of -1 means that The
+ *                             remove animation should be performed upwards,
+ *                             such that the  child appears to be going away to the top. 1
+ *                             Should mean the opposite.
+     * @param isHeadsUpAnimation Is this a headsUp animation.
+     * @param endLocation The location where the horizonal heads up disappear animation should end.
+     * @param onFinishedRunnable A runnable which should be run when the animation is finished.
+     * @param animationListener An animation listener to add to the animation.
+     */
+    public abstract void performRemoveAnimation(long duration,
+            long delay, float translationDirection, boolean isHeadsUpAnimation, float endLocation,
+            Runnable onFinishedRunnable,
+            AnimatorListenerAdapter animationListener);
+
+    public abstract void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear);
+
+    /**
+     * Set the notification appearance to be below the speed bump.
+     * @param below true if it is below.
+     */
+    public void setBelowSpeedBump(boolean below) {
+    }
+
+    public int getPinnedHeadsUpHeight() {
+        return getIntrinsicHeight();
+    }
+
+
+    /**
+     * Sets the translation of the view.
+     */
+    public void setTranslation(float translation) {
+        setTranslationX(translation);
+    }
+
+    /**
+     * Gets the translation of the view.
+     */
+    public float getTranslation() {
+        return getTranslationX();
+    }
+
+    public void onHeightReset() {
+        if (mOnHeightChangedListener != null) {
+            mOnHeightChangedListener.onReset(this);
+        }
+    }
+
+    /**
+     * This method returns the drawing rect for the view which is different from the regular
+     * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at
+     * position 0 and usually the translation is neglected. Since we are manually clipping this
+     * view,we also need to subtract the clipTopAmount from the top. This is needed in order to
+     * ensure that accessibility and focusing work correctly.
+     *
+     * @param outRect The (scrolled) drawing bounds of the view.
+     */
+    @Override
+    public void getDrawingRect(Rect outRect) {
+        super.getDrawingRect(outRect);
+        outRect.left += getTranslationX();
+        outRect.right += getTranslationX();
+        outRect.bottom = (int) (outRect.top + getTranslationY() + getActualHeight());
+        outRect.top += getTranslationY() + getClipTopAmount();
+    }
+
+    @Override
+    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
+        super.getBoundsOnScreen(outRect, clipToParent);
+        if (getTop() + getTranslationY() < 0) {
+            // We got clipped to the parent here - make sure we undo that.
+            outRect.top += getTop() + getTranslationY();
+        }
+        outRect.bottom = outRect.top + getActualHeight();
+        outRect.top += getClipTopAmount();
+    }
+
+    public boolean isSummaryWithChildren() {
+        return false;
+    }
+
+    public boolean areChildrenExpanded() {
+        return false;
+    }
+
+    protected void updateClipping() {
+        if (mClipToActualHeight && shouldClipToActualHeight()) {
+            int top = getClipTopAmount();
+            mClipRect.set(0, top, getWidth(), Math.max(getActualHeight() + getExtraBottomPadding()
+                    - mClipBottomAmount, top));
+            setClipBounds(mClipRect);
+        } else {
+            setClipBounds(null);
+        }
+    }
+
+    public float getHeaderVisibleAmount() {
+        return 1.0f;
+    }
+
+    protected boolean shouldClipToActualHeight() {
+        return true;
+    }
+
+    public void setClipToActualHeight(boolean clipToActualHeight) {
+        mClipToActualHeight = clipToActualHeight;
+        updateClipping();
+    }
+
+    public boolean willBeGone() {
+        return mWillBeGone;
+    }
+
+    public void setWillBeGone(boolean willBeGone) {
+        mWillBeGone = willBeGone;
+    }
+
+    public int getMinClipTopAmount() {
+        return mMinClipTopAmount;
+    }
+
+    public void setMinClipTopAmount(int minClipTopAmount) {
+        mMinClipTopAmount = minClipTopAmount;
+    }
+
+    @Override
+    public void setLayerType(int layerType, Paint paint) {
+        if (hasOverlappingRendering()) {
+            super.setLayerType(layerType, paint);
+        }
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        // Otherwise it will be clipped
+        return super.hasOverlappingRendering() && getActualHeight() <= getHeight();
+    }
+
+    public float getShadowAlpha() {
+        return 0.0f;
+    }
+
+    public void setShadowAlpha(float shadowAlpha) {
+    }
+
+    /**
+     * @return an amount between -1 and 1 of increased padding that this child needs. 1 means it
+     * needs a full increased padding while -1 means it needs no padding at all. For 0.0f the normal
+     * padding is applied.
+     */
+    public float getIncreasedPaddingAmount() {
+        return 0.0f;
+    }
+
+    public boolean mustStayOnScreen() {
+        return false;
+    }
+
+    public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
+            int outlineTranslation) {
+    }
+
+    public float getOutlineAlpha() {
+        return 0.0f;
+    }
+
+    public int getOutlineTranslation() {
+        return 0;
+    }
+
+    public void setChangingPosition(boolean changingPosition) {
+        mChangingPosition = changingPosition;
+    }
+
+    public boolean isChangingPosition() {
+        return mChangingPosition;
+    }
+
+    public void setTransientContainer(ViewGroup transientContainer) {
+        mTransientContainer = transientContainer;
+    }
+
+    public ViewGroup getTransientContainer() {
+        return mTransientContainer;
+    }
+
+    /**
+     * @return padding used to alter how much of the view is clipped.
+     */
+    public int getExtraBottomPadding() {
+        return 0;
+    }
+
+    /**
+     * @return true if the group's expansion state is changing, false otherwise.
+     */
+    public boolean isGroupExpansionChanging() {
+        return false;
+    }
+
+    public boolean isGroupExpanded() {
+        return false;
+    }
+
+    public void setHeadsUpIsVisible() {
+    }
+
+    public boolean isChildInGroup() {
+        return false;
+    }
+
+    public void setActualHeightAnimating(boolean animating) {}
+
+    public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
+        return new ExpandableViewState();
+    }
+
+    /**
+     * @return whether the current view doesn't add height to the overall content. This means that
+     * if it is added to a list of items, it's content will still have the same height.
+     * An example is the notification shelf, that is always placed on top of another view.
+     */
+    public boolean hasNoContentHeight() {
+        return false;
+    }
+
+    /**
+     * @param inShelf whether the view is currently fully in the notification shelf.
+     */
+    public void setInShelf(boolean inShelf) {
+        mInShelf = inShelf;
+    }
+
+    public boolean isInShelf() {
+        return mInShelf;
+    }
+
+    /**
+     * @param transformingInShelf whether the view is currently transforming into the shelf in an
+     *                            animated way
+     */
+    public void setTransformingInShelf(boolean transformingInShelf) {
+        mTransformingInShelf = transformingInShelf;
+    }
+
+    public boolean isTransformingIntoShelf() {
+        return mTransformingInShelf;
+    }
+
+    public boolean isAboveShelf() {
+        return false;
+    }
+
+    public boolean hasExpandingChild() {
+        return false;
+    }
+
+    /**
+     * A listener notifying when {@link #getActualHeight} changes.
+     */
+    public interface OnHeightChangedListener {
+
+        /**
+         * @param view the view for which the height changed, or {@code null} if just the top
+         *             padding or the padding between the elements changed
+         * @param needsAnimation whether the view height needs to be animated
+         */
+        void onHeightChanged(ExpandableView view, boolean needsAnimation);
+
+        /**
+         * Called when the view is reset and therefore the height will change abruptly
+         *
+         * @param view The view which was reset.
+         */
+        void onReset(ExpandableView view);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
new file mode 100644
index 0000000..1f15ed0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
+import com.android.systemui.statusbar.notification.stack.StackScrollState;
+
+public class FooterView extends StackScrollerDecorView {
+    private final int mClearAllTopPadding;
+    private FooterViewButton mDismissButton;
+    private FooterViewButton mManageButton;
+
+    public FooterView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mClearAllTopPadding = context.getResources().getDimensionPixelSize(
+                R.dimen.clear_all_padding_top);
+    }
+
+    @Override
+    protected View findContentView() {
+        return findViewById(R.id.content);
+    }
+
+    protected View findSecondaryView() {
+        return findViewById(R.id.dismiss_text);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mDismissButton = (FooterViewButton) findSecondaryView();
+        mManageButton = findViewById(R.id.manage_text);
+    }
+
+    public void setTextColor(@ColorInt int color) {
+        mManageButton.setTextColor(color);
+        mDismissButton.setTextColor(color);
+    }
+
+    public void setManageButtonClickListener(OnClickListener listener) {
+        mManageButton.setOnClickListener(listener);
+    }
+
+    public void setDismissButtonClickListener(OnClickListener listener) {
+        mDismissButton.setOnClickListener(listener);
+    }
+
+    public boolean isOnEmptySpace(float touchX, float touchY) {
+        return touchX < mContent.getX()
+                || touchX > mContent.getX() + mContent.getWidth()
+                || touchY < mContent.getY()
+                || touchY > mContent.getY() + mContent.getHeight();
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        mDismissButton.setText(R.string.clear_all_notifications_text);
+        mDismissButton.setContentDescription(
+                mContext.getString(R.string.accessibility_clear_all));
+        mManageButton.setText(R.string.manage_notifications_text);
+    }
+
+    public boolean isButtonVisible() {
+        return mManageButton.getAlpha() != 0.0f;
+    }
+
+    @Override
+    public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
+        return new FooterViewState();
+    }
+
+    public class FooterViewState extends ExpandableViewState {
+        @Override
+        public void applyToView(View view) {
+            super.applyToView(view);
+            if (view instanceof FooterView) {
+                FooterView footerView = (FooterView) view;
+                boolean visible = this.clipTopAmount < mClearAllTopPadding;
+                footerView.setContentVisible(visible && footerView.isVisible());
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterViewButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterViewButton.java
new file mode 100644
index 0000000..e1c4a0c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterViewButton.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+
+import com.android.systemui.statusbar.AlphaOptimizedButton;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+
+public class FooterViewButton extends AlphaOptimizedButton {
+
+    public FooterViewButton(Context context) {
+        this(context, null);
+    }
+
+    public FooterViewButton(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public FooterViewButton(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public FooterViewButton(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    /**
+     * This method returns the drawing rect for the view which is different from the regular
+     * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at
+     * position 0 and usually the translation is neglected. The standard implementation doesn't
+     * account for translation.
+     *
+     * @param outRect The (scrolled) drawing bounds of the view.
+     */
+    @Override
+    public void getDrawingRect(Rect outRect) {
+        super.getDrawingRect(outRect);
+        float translationX = ((ViewGroup) mParent).getTranslationX();
+        float translationY = ((ViewGroup) mParent).getTranslationY();
+        outRect.left += translationX;
+        outRect.right += translationX;
+        outRect.top += translationY;
+        outRect.bottom += translationY;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
new file mode 100644
index 0000000..33badaf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
@@ -0,0 +1,178 @@
+/*
+ * 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.systemui.statusbar.notification.row;
+
+import android.app.Notification;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationDozeHelper;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+
+/**
+ * A class managing hybrid groups that include {@link HybridNotificationView} and the notification
+ * group overflow.
+ */
+public class HybridGroupManager {
+
+    private final Context mContext;
+    private final NotificationDozeHelper mDozer;
+    private final ViewGroup mParent;
+
+    private float mOverflowNumberSizeDark;
+    private int mOverflowNumberPaddingDark;
+    private float mOverflowNumberSize;
+    private int mOverflowNumberPadding;
+
+    private int mOverflowNumberColor;
+    private int mOverflowNumberColorDark;
+    private float mDarkAmount = 0f;
+
+    public HybridGroupManager(Context ctx, ViewGroup parent) {
+        mContext = ctx;
+        mParent = parent;
+        mDozer = new NotificationDozeHelper();
+        initDimens();
+    }
+
+    public void initDimens() {
+        Resources res = mContext.getResources();
+        mOverflowNumberSize = res.getDimensionPixelSize(
+                R.dimen.group_overflow_number_size);
+        mOverflowNumberSizeDark = res.getDimensionPixelSize(
+                R.dimen.group_overflow_number_size_dark);
+        mOverflowNumberPadding = res.getDimensionPixelSize(
+                R.dimen.group_overflow_number_padding);
+        mOverflowNumberPaddingDark = mOverflowNumberPadding + res.getDimensionPixelSize(
+                R.dimen.group_overflow_number_extra_padding_dark);
+    }
+
+    private HybridNotificationView inflateHybridViewWithStyle(int style) {
+        LayoutInflater inflater = new ContextThemeWrapper(mContext, style)
+                .getSystemService(LayoutInflater.class);
+        HybridNotificationView hybrid = (HybridNotificationView) inflater.inflate(
+                R.layout.hybrid_notification, mParent, false);
+        mParent.addView(hybrid);
+        return hybrid;
+    }
+
+    private TextView inflateOverflowNumber() {
+        LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
+        TextView numberView = (TextView) inflater.inflate(
+                R.layout.hybrid_overflow_number, mParent, false);
+        mParent.addView(numberView);
+        updateOverFlowNumberColor(numberView);
+        return numberView;
+    }
+
+    private void updateOverFlowNumberColor(TextView numberView) {
+        numberView.setTextColor(NotificationUtils.interpolateColors(
+                mOverflowNumberColor, mOverflowNumberColorDark, mDarkAmount));
+    }
+
+    public void setOverflowNumberColor(TextView numberView, int colorRegular, int colorDark) {
+        mOverflowNumberColor = colorRegular;
+        mOverflowNumberColorDark = colorDark;
+        if (numberView != null) {
+            updateOverFlowNumberColor(numberView);
+        }
+    }
+
+    public HybridNotificationView bindFromNotification(HybridNotificationView reusableView,
+            Notification notification) {
+        return bindFromNotificationWithStyle(reusableView, notification,
+                R.style.HybridNotification);
+    }
+
+    public HybridNotificationView bindAmbientFromNotification(HybridNotificationView reusableView,
+            Notification notification) {
+        return bindFromNotificationWithStyle(reusableView, notification,
+                R.style.HybridNotification_Ambient);
+    }
+
+    private HybridNotificationView bindFromNotificationWithStyle(
+            HybridNotificationView reusableView, Notification notification, int style) {
+        if (reusableView == null) {
+            reusableView = inflateHybridViewWithStyle(style);
+        }
+        CharSequence titleText = resolveTitle(notification);
+        CharSequence contentText = resolveText(notification);
+        reusableView.bind(titleText, contentText);
+        return reusableView;
+    }
+
+    private CharSequence resolveText(Notification notification) {
+        CharSequence contentText = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
+        if (contentText == null) {
+            contentText = notification.extras.getCharSequence(Notification.EXTRA_BIG_TEXT);
+        }
+        return contentText;
+    }
+
+    private CharSequence resolveTitle(Notification notification) {
+        CharSequence titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
+        if (titleText == null) {
+            titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE_BIG);
+        }
+        return titleText;
+    }
+
+    public TextView bindOverflowNumber(TextView reusableView, int number) {
+        if (reusableView == null) {
+            reusableView = inflateOverflowNumber();
+        }
+        String text = mContext.getResources().getString(
+                R.string.notification_group_overflow_indicator, number);
+        if (!text.equals(reusableView.getText())) {
+            reusableView.setText(text);
+        }
+        String contentDescription = String.format(mContext.getResources().getQuantityString(
+                R.plurals.notification_group_overflow_description, number), number);
+
+        reusableView.setContentDescription(contentDescription);
+        return reusableView;
+    }
+
+    public TextView bindOverflowNumberAmbient(TextView titleView, Notification notification,
+            int number) {
+        String text = mContext.getResources().getString(
+                R.string.notification_group_overflow_indicator_ambient,
+                resolveTitle(notification), number);
+        if (!text.equals(titleView.getText())) {
+            titleView.setText(text);
+        }
+        return titleView;
+    }
+
+    public void setOverflowNumberDark(TextView view, boolean dark, boolean fade, long delay) {
+        mDozer.setIntensityDark((f)->{
+            mDarkAmount = f;
+            updateOverFlowNumberColor(view);
+        }, dark, fade, delay, view);
+        view.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                dark ? mOverflowNumberSizeDark : mOverflowNumberSize);
+        int paddingEnd = dark ? mOverflowNumberPaddingDark : mOverflowNumberPadding;
+        view.setPaddingRelative(view.getPaddingStart(), view.getPaddingTop(), paddingEnd,
+                view.getPaddingBottom());
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
new file mode 100644
index 0000000..be25d63
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
@@ -0,0 +1,156 @@
+/*
+ * 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.systemui.statusbar.notification.row;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.keyguard.AlphaOptimizedLinearLayout;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.ViewTransformationHelper;
+import com.android.systemui.statusbar.notification.TransformState;
+
+/**
+ * A hybrid view which may contain information about one ore more notifications.
+ */
+public class HybridNotificationView extends AlphaOptimizedLinearLayout
+        implements TransformableView {
+
+    private ViewTransformationHelper mTransformationHelper;
+
+    protected TextView mTitleView;
+    protected TextView mTextView;
+
+    public HybridNotificationView(Context context) {
+        this(context, null);
+    }
+
+    public HybridNotificationView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public HybridNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public TextView getTitleView() {
+        return mTitleView;
+    }
+
+    public TextView getTextView() {
+        return mTextView;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTitleView = (TextView) findViewById(R.id.notification_title);
+        mTextView = (TextView) findViewById(R.id.notification_text);
+        mTransformationHelper = new ViewTransformationHelper();
+        mTransformationHelper.setCustomTransformation(
+                new ViewTransformationHelper.CustomTransformation() {
+                    @Override
+                    public boolean transformTo(TransformState ownState, TransformableView notification,
+                            float transformationAmount) {
+                        // We want to transform to the same y location as the title
+                        TransformState otherState = notification.getCurrentState(
+                                TRANSFORMING_VIEW_TITLE);
+                        CrossFadeHelper.fadeOut(mTextView, transformationAmount);
+                        if (otherState != null) {
+                            ownState.transformViewVerticalTo(otherState, transformationAmount);
+                            otherState.recycle();
+                        }
+                        return true;
+                    }
+
+                    @Override
+                    public boolean transformFrom(TransformState ownState,
+                            TransformableView notification, float transformationAmount) {
+                        // We want to transform from the same y location as the title
+                        TransformState otherState = notification.getCurrentState(
+                                TRANSFORMING_VIEW_TITLE);
+                        CrossFadeHelper.fadeIn(mTextView, transformationAmount);
+                        if (otherState != null) {
+                            ownState.transformViewVerticalFrom(otherState, transformationAmount);
+                            otherState.recycle();
+                        }
+                        return true;
+                    }
+                }, TRANSFORMING_VIEW_TEXT);
+        mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TITLE, mTitleView);
+        mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TEXT, mTextView);
+    }
+
+    public void bind(CharSequence title) {
+        bind(title, null);
+    }
+
+    public void bind(CharSequence title, CharSequence text) {
+        mTitleView.setText(title);
+        mTitleView.setVisibility(TextUtils.isEmpty(title) ? GONE : VISIBLE);
+        if (TextUtils.isEmpty(text)) {
+            mTextView.setVisibility(GONE);
+            mTextView.setText(null);
+        } else {
+            mTextView.setVisibility(VISIBLE);
+            mTextView.setText(text.toString());
+        }
+        requestLayout();
+    }
+
+    @Override
+    public TransformState getCurrentState(int fadingView) {
+        return mTransformationHelper.getCurrentState(fadingView);
+    }
+
+    @Override
+    public void transformTo(TransformableView notification, Runnable endRunnable) {
+        mTransformationHelper.transformTo(notification, endRunnable);
+    }
+
+    @Override
+    public void transformTo(TransformableView notification, float transformationAmount) {
+        mTransformationHelper.transformTo(notification, transformationAmount);
+    }
+
+    @Override
+    public void transformFrom(TransformableView notification) {
+        mTransformationHelper.transformFrom(notification);
+    }
+
+    @Override
+    public void transformFrom(TransformableView notification, float transformationAmount) {
+        mTransformationHelper.transformFrom(notification, transformationAmount);
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+        mTransformationHelper.setVisible(visible);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
new file mode 100644
index 0000000..1ed726d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.RippleDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+
+/**
+ * A view that can be used for both the dimmed and normal background of an notification.
+ */
+public class NotificationBackgroundView extends View {
+
+    private final boolean mDontModifyCorners;
+    private Drawable mBackground;
+    private int mClipTopAmount;
+    private int mActualHeight;
+    private int mClipBottomAmount;
+    private int mTintColor;
+    private float[] mCornerRadii = new float[8];
+    private boolean mBottomIsRounded;
+    private int mBackgroundTop;
+    private boolean mBottomAmountClips = true;
+    private boolean mExpandAnimationRunning;
+    private float mActualWidth;
+    private int mDrawableAlpha = 255;
+    private boolean mIsPressedAllowed;
+
+    private boolean mTopAmountRounded;
+    private float mDistanceToTopRoundness;
+
+    public NotificationBackgroundView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mDontModifyCorners = getResources().getBoolean(
+                R.bool.config_clipNotificationsToOutline);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mClipTopAmount + mClipBottomAmount < mActualHeight - mBackgroundTop
+                || mExpandAnimationRunning) {
+            canvas.save();
+            if (!mExpandAnimationRunning) {
+                canvas.clipRect(0, mClipTopAmount, getWidth(), mActualHeight - mClipBottomAmount);
+            }
+            draw(canvas, mBackground);
+            canvas.restore();
+        }
+    }
+
+    private void draw(Canvas canvas, Drawable drawable) {
+        if (drawable != null) {
+            int top = mBackgroundTop;
+            int bottom = mActualHeight;
+            if (mBottomIsRounded && mBottomAmountClips && !mExpandAnimationRunning) {
+                bottom -= mClipBottomAmount;
+            }
+            int left = 0;
+            int right = getWidth();
+            if (mExpandAnimationRunning) {
+                left = (int) ((getWidth() - mActualWidth) / 2.0f);
+                right = (int) (left + mActualWidth);
+            }
+            if (mTopAmountRounded) {
+                int clipTop = (int) (mClipTopAmount - mDistanceToTopRoundness);
+                top += clipTop;
+                if (clipTop >= 0) {
+                    bottom += clipTop;
+                }
+            }
+            drawable.setBounds(left, top, right, bottom);
+            drawable.draw(canvas);
+        }
+    }
+
+    @Override
+    protected boolean verifyDrawable(Drawable who) {
+        return super.verifyDrawable(who) || who == mBackground;
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        setState(getDrawableState());
+    }
+
+    @Override
+    public void drawableHotspotChanged(float x, float y) {
+        if (mBackground != null) {
+            mBackground.setHotspot(x, y);
+        }
+    }
+
+    /**
+     * Sets a background drawable. As we need to change our bounds independently of layout, we need
+     * the notion of a background independently of the regular View background..
+     */
+    public void setCustomBackground(Drawable background) {
+        if (mBackground != null) {
+            mBackground.setCallback(null);
+            unscheduleDrawable(mBackground);
+        }
+        mBackground = background;
+        mBackground.mutate();
+        if (mBackground != null) {
+            mBackground.setCallback(this);
+            setTint(mTintColor);
+        }
+        if (mBackground instanceof RippleDrawable) {
+            ((RippleDrawable) mBackground).setForceSoftware(true);
+        }
+        updateBackgroundRadii();
+        invalidate();
+    }
+
+    public void setCustomBackground(int drawableResId) {
+        final Drawable d = mContext.getDrawable(drawableResId);
+        setCustomBackground(d);
+    }
+
+    public void setTint(int tintColor) {
+        if (tintColor != 0) {
+            mBackground.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
+        } else {
+            mBackground.clearColorFilter();
+        }
+        mTintColor = tintColor;
+        invalidate();
+    }
+
+    public void setActualHeight(int actualHeight) {
+        if (mExpandAnimationRunning) {
+            return;
+        }
+        mActualHeight = actualHeight;
+        invalidate();
+    }
+
+    public int getActualHeight() {
+        return mActualHeight;
+    }
+
+    public void setClipTopAmount(int clipTopAmount) {
+        mClipTopAmount = clipTopAmount;
+        invalidate();
+    }
+
+    public void setClipBottomAmount(int clipBottomAmount) {
+        mClipBottomAmount = clipBottomAmount;
+        invalidate();
+    }
+
+    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+        if (distanceToTopRoundness != mDistanceToTopRoundness) {
+            mTopAmountRounded = distanceToTopRoundness >= 0;
+            mDistanceToTopRoundness = distanceToTopRoundness;
+            invalidate();
+        }
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+
+        // Prevents this view from creating a layer when alpha is animating.
+        return false;
+    }
+
+    public void setState(int[] drawableState) {
+        if (mBackground != null && mBackground.isStateful()) {
+            if (!mIsPressedAllowed) {
+                drawableState = ArrayUtils.removeInt(drawableState,
+                        com.android.internal.R.attr.state_pressed);
+            }
+            mBackground.setState(drawableState);
+        }
+    }
+
+    public void setRippleColor(int color) {
+        if (mBackground instanceof RippleDrawable) {
+            RippleDrawable ripple = (RippleDrawable) mBackground;
+            ripple.setColor(ColorStateList.valueOf(color));
+        }
+    }
+
+    public void setDrawableAlpha(int drawableAlpha) {
+        mDrawableAlpha = drawableAlpha;
+        if (mExpandAnimationRunning) {
+            return;
+        }
+        mBackground.setAlpha(drawableAlpha);
+    }
+
+    public void setRoundness(float topRoundness, float bottomRoundNess) {
+        if (topRoundness == mCornerRadii[0] && bottomRoundNess == mCornerRadii[4]) {
+            return;
+        }
+        mBottomIsRounded = bottomRoundNess != 0.0f;
+        mCornerRadii[0] = topRoundness;
+        mCornerRadii[1] = topRoundness;
+        mCornerRadii[2] = topRoundness;
+        mCornerRadii[3] = topRoundness;
+        mCornerRadii[4] = bottomRoundNess;
+        mCornerRadii[5] = bottomRoundNess;
+        mCornerRadii[6] = bottomRoundNess;
+        mCornerRadii[7] = bottomRoundNess;
+        updateBackgroundRadii();
+    }
+
+    public void setBottomAmountClips(boolean clips) {
+        if (clips != mBottomAmountClips) {
+            mBottomAmountClips = clips;
+            invalidate();
+        }
+    }
+
+    private void updateBackgroundRadii() {
+        if (mDontModifyCorners) {
+            return;
+        }
+        if (mBackground instanceof LayerDrawable) {
+            GradientDrawable gradientDrawable =
+                    (GradientDrawable) ((LayerDrawable) mBackground).getDrawable(0);
+            gradientDrawable.setCornerRadii(mCornerRadii);
+        }
+    }
+
+    public void setBackgroundTop(int backgroundTop) {
+        mBackgroundTop = backgroundTop;
+        invalidate();
+    }
+
+    public void setExpandAnimationParams(ActivityLaunchAnimator.ExpandAnimationParameters params) {
+        mActualHeight = params.getHeight();
+        mActualWidth = params.getWidth();
+        float alphaProgress = Interpolators.ALPHA_IN.getInterpolation(
+                params.getProgress(
+                        ActivityLaunchAnimator.ANIMATION_DURATION_FADE_CONTENT /* delay */,
+                        ActivityLaunchAnimator.ANIMATION_DURATION_FADE_APP /* duration */));
+        mBackground.setAlpha((int) (mDrawableAlpha * (1.0f - alphaProgress)));
+        invalidate();
+    }
+
+    public void setExpandAnimationRunning(boolean running) {
+        mExpandAnimationRunning = running;
+        if (mBackground instanceof LayerDrawable) {
+            GradientDrawable gradientDrawable =
+                    (GradientDrawable) ((LayerDrawable) mBackground).getDrawable(0);
+            gradientDrawable.setXfermode(
+                    running ? new PorterDuffXfermode(PorterDuff.Mode.SRC) : null);
+            // Speed optimization: disable AA if transfer mode is not SRC_OVER. AA is not easy to
+            // spot during animation anyways.
+            gradientDrawable.setAntiAlias(!running);
+        }
+        if (!mExpandAnimationRunning) {
+            setDrawableAlpha(mDrawableAlpha);
+        }
+        invalidate();
+    }
+
+    public void setPressedAllowed(boolean allowed) {
+        mIsPressedAllowed = allowed;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
new file mode 100644
index 0000000..1a4ef09
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.content.Context;
+
+import androidx.annotation.VisibleForTesting;
+import android.util.Log;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.logging.NotificationCounters;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
+
+/**
+ * Manager for the notification blocking helper - tracks and helps create the blocking helper
+ * affordance.
+ */
+public class NotificationBlockingHelperManager {
+    /** Enables debug logging and always makes the blocking helper show up after a dismiss. */
+    private static final boolean DEBUG = false;
+    private static final String TAG = "BlockingHelper";
+
+    private final Context mContext;
+    /** Row that the blocking helper will be shown in (via {@link NotificationGuts}. */
+    private ExpandableNotificationRow mBlockingHelperRow;
+    private Set<String> mNonBlockablePkgs;
+
+    /**
+     * Whether the notification shade/stack is expanded - used to determine blocking helper
+     * eligibility.
+     */
+    private boolean mIsShadeExpanded;
+
+    public NotificationBlockingHelperManager(Context context) {
+        mContext = context;
+        mNonBlockablePkgs = new HashSet<>();
+        Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
+                com.android.internal.R.array.config_nonBlockableNotificationPackages));
+    }
+
+    /**
+     * Potentially shows the blocking helper, represented via the {@link NotificationInfo} menu
+     * item, in the current row if user sentiment is negative.
+     *
+     * @param row row to render the blocking helper in
+     * @param menuRow menu used to generate the {@link NotificationInfo} view that houses the
+     *                blocking helper UI
+     * @return whether we're showing a blocking helper in the given notification row
+     */
+    boolean perhapsShowBlockingHelper(
+            ExpandableNotificationRow row, NotificationMenuRowPlugin menuRow) {
+        // We only show the blocking helper if:
+        // - User sentiment is negative (DEBUG flag can bypass)
+        // - The notification shade is fully expanded (guarantees we're not touching a HUN).
+        // - The row is blockable (i.e. not non-blockable)
+        // - The dismissed row is a valid group (>1 or 0 children) or the only child in the group
+        if ((row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE || DEBUG)
+                && mIsShadeExpanded
+                && !row.getIsNonblockable()
+                && (!row.isChildInGroup() || row.isOnlyChildInGroup())) {
+            // Dismiss any current blocking helper before continuing forward (only one can be shown
+            // at a given time).
+            dismissCurrentBlockingHelper();
+
+            if (DEBUG) {
+                Log.d(TAG, "Manager.perhapsShowBlockingHelper: Showing new blocking helper");
+            }
+            NotificationGutsManager manager = Dependency.get(NotificationGutsManager.class);
+
+            // Enable blocking helper on the row before moving forward so everything in the guts is
+            // correctly prepped.
+            mBlockingHelperRow = row;
+            mBlockingHelperRow.setBlockingHelperShowing(true);
+
+            // We don't care about the touch origin (x, y) since we're opening guts without any
+            // explicit user interaction.
+            manager.openGuts(mBlockingHelperRow, 0, 0, menuRow.getLongpressMenuItem(mContext));
+
+            Dependency.get(MetricsLogger.class)
+                    .count(NotificationCounters.BLOCKING_HELPER_SHOWN, 1);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Dismiss the currently showing blocking helper, if any, through a notification update.
+     *
+     * @return whether the blocking helper was dismissed
+     */
+    boolean dismissCurrentBlockingHelper() {
+        if (!isBlockingHelperRowNull()) {
+            if (DEBUG) {
+                Log.d(TAG, "Manager.dismissCurrentBlockingHelper: Dismissing current helper");
+            }
+            if (!mBlockingHelperRow.isBlockingHelperShowing()) {
+                Log.e(TAG, "Manager.dismissCurrentBlockingHelper: "
+                        + "Non-null row is not showing a blocking helper");
+            }
+
+            mBlockingHelperRow.setBlockingHelperShowing(false);
+            if (mBlockingHelperRow.isAttachedToWindow()) {
+                Dependency.get(NotificationEntryManager.class).updateNotifications();
+            }
+            mBlockingHelperRow = null;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Update the expansion status of the notification shade/stack.
+     *
+     * @param expandedHeight how much the shade is expanded ({code 0} indicating it's collapsed)
+     */
+    public void setNotificationShadeExpanded(float expandedHeight) {
+        mIsShadeExpanded = expandedHeight > 0.0f;
+    }
+
+    /**
+     * Returns whether the given package name is in the list of non-blockable packages.
+     */
+    public boolean isNonblockable(String packageName, String channelName) {
+        return mNonBlockablePkgs.contains(packageName)
+                || mNonBlockablePkgs.contains(makeChannelKey(packageName, channelName));
+    }
+
+    // Format must stay in sync with frameworks/base/core/res/res/values/config.xml
+    // config_nonBlockableNotificationPackages
+    private String makeChannelKey(String pkg, String channel) {
+        return pkg + ":" + channel;
+    }
+
+    @VisibleForTesting
+    boolean isBlockingHelperRowNull() {
+        return mBlockingHelperRow == null;
+    }
+
+    @VisibleForTesting
+    void setBlockingHelperRowForTest(ExpandableNotificationRow blockingHelperRowForTest) {
+        mBlockingHelperRow = blockingHelperRowForTest;
+    }
+
+    @VisibleForTesting
+    void setNonBlockablePkgs(String[] pkgsAndChannels) {
+        mNonBlockablePkgs = new HashSet<>();
+        Collections.addAll(mNonBlockablePkgs, pkgsAndChannels);
+    }
+}
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
new file mode 100644
index 0000000..0110610
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -0,0 +1,1756 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Build;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.NotificationHeaderView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.ContrastColorUtil;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationCustomViewWrapper;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.policy.RemoteInputView;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
+import com.android.systemui.statusbar.policy.SmartReplyView;
+
+/**
+ * A frame layout containing the actual payload of the notification, including the contracted,
+ * expanded and heads up layout. This class is responsible for clipping the content and and
+ * switching between the expanded, contracted and the heads up view depending on its clipped size.
+ */
+public class NotificationContentView extends FrameLayout {
+
+    private static final String TAG = "NotificationContentView";
+    public static final int VISIBLE_TYPE_CONTRACTED = 0;
+    public static final int VISIBLE_TYPE_EXPANDED = 1;
+    public static final int VISIBLE_TYPE_HEADSUP = 2;
+    private static final int VISIBLE_TYPE_SINGLELINE = 3;
+    public static final int VISIBLE_TYPE_AMBIENT = 4;
+    private static final int VISIBLE_TYPE_AMBIENT_SINGLELINE = 5;
+    public static final int UNDEFINED = -1;
+
+    private final Rect mClipBounds = new Rect();
+
+    private int mMinContractedHeight;
+    private int mNotificationContentMarginEnd;
+    private View mContractedChild;
+    private View mExpandedChild;
+    private View mHeadsUpChild;
+    private HybridNotificationView mSingleLineView;
+    private View mAmbientChild;
+    private HybridNotificationView mAmbientSingleLineChild;
+
+    private RemoteInputView mExpandedRemoteInput;
+    private RemoteInputView mHeadsUpRemoteInput;
+
+    private SmartReplyConstants mSmartReplyConstants;
+    private SmartReplyView mExpandedSmartReplyView;
+    private SmartReplyController mSmartReplyController;
+
+    private NotificationViewWrapper mContractedWrapper;
+    private NotificationViewWrapper mExpandedWrapper;
+    private NotificationViewWrapper mHeadsUpWrapper;
+    private NotificationViewWrapper mAmbientWrapper;
+    private HybridGroupManager mHybridGroupManager;
+    private int mClipTopAmount;
+    private int mContentHeight;
+    private int mVisibleType = VISIBLE_TYPE_CONTRACTED;
+    private boolean mDark;
+    private boolean mAnimate;
+    private boolean mIsHeadsUp;
+    private boolean mLegacy;
+    private boolean mIsChildInGroup;
+    private int mSmallHeight;
+    private int mHeadsUpHeight;
+    private int mNotificationMaxHeight;
+    private int mNotificationAmbientHeight;
+    private StatusBarNotification mStatusBarNotification;
+    private NotificationGroupManager mGroupManager;
+    private RemoteInputController mRemoteInputController;
+    private Runnable mExpandedVisibleListener;
+
+    private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
+            = new ViewTreeObserver.OnPreDrawListener() {
+        @Override
+        public boolean onPreDraw() {
+            // We need to post since we don't want the notification to animate on the very first
+            // frame
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    mAnimate = true;
+                }
+            });
+            getViewTreeObserver().removeOnPreDrawListener(this);
+            return true;
+        }
+    };
+
+    private OnClickListener mExpandClickListener;
+    private boolean mBeforeN;
+    private boolean mExpandable;
+    private boolean mClipToActualHeight = true;
+    private ExpandableNotificationRow mContainingNotification;
+    /** The visible type at the start of a touch driven transformation */
+    private int mTransformationStartVisibleType;
+    /** The visible type at the start of an animation driven transformation */
+    private int mAnimationStartVisibleType = UNDEFINED;
+    private boolean mUserExpanding;
+    private int mSingleLineWidthIndention;
+    private boolean mForceSelectNextLayout = true;
+    private PendingIntent mPreviousExpandedRemoteInputIntent;
+    private PendingIntent mPreviousHeadsUpRemoteInputIntent;
+    private RemoteInputView mCachedExpandedRemoteInput;
+    private RemoteInputView mCachedHeadsUpRemoteInput;
+
+    private int mContentHeightAtAnimationStart = UNDEFINED;
+    private boolean mFocusOnVisibilityChange;
+    private boolean mHeadsUpAnimatingAway;
+    private boolean mIconsVisible;
+    private int mClipBottomAmount;
+    private boolean mIsLowPriority;
+    private boolean mIsContentExpandable;
+    private boolean mRemoteInputVisible;
+    private int mUnrestrictedContentHeight;
+
+
+    public NotificationContentView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mHybridGroupManager = new HybridGroupManager(getContext(), this);
+        mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
+        mSmartReplyController = Dependency.get(SmartReplyController.class);
+        initView();
+    }
+
+    public void initView() {
+        mMinContractedHeight = getResources().getDimensionPixelSize(
+                R.dimen.min_notification_layout_height);
+        mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin_end);
+    }
+
+    public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight,
+            int ambientHeight) {
+        mSmallHeight = smallHeight;
+        mHeadsUpHeight = headsUpMaxHeight;
+        mNotificationMaxHeight = maxHeight;
+        mNotificationAmbientHeight = ambientHeight;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
+        boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
+        int maxSize = Integer.MAX_VALUE / 2;
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        if (hasFixedHeight || isHeightLimited) {
+            maxSize = MeasureSpec.getSize(heightMeasureSpec);
+        }
+        int maxChildHeight = 0;
+        if (mExpandedChild != null) {
+            int notificationMaxHeight = mNotificationMaxHeight;
+            if (mExpandedSmartReplyView != null) {
+                notificationMaxHeight += mExpandedSmartReplyView.getHeightUpperLimit();
+            }
+            notificationMaxHeight += mExpandedWrapper.getExtraMeasureHeight();
+            int size = notificationMaxHeight;
+            ViewGroup.LayoutParams layoutParams = mExpandedChild.getLayoutParams();
+            boolean useExactly = false;
+            if (layoutParams.height >= 0) {
+                // An actual height is set
+                size = Math.min(size, layoutParams.height);
+                useExactly = true;
+            }
+            int spec = MeasureSpec.makeMeasureSpec(size, useExactly
+                            ? MeasureSpec.EXACTLY
+                            : MeasureSpec.AT_MOST);
+            measureChildWithMargins(mExpandedChild, widthMeasureSpec, 0, spec, 0);
+            maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight());
+        }
+        if (mContractedChild != null) {
+            int heightSpec;
+            int size = mSmallHeight;
+            ViewGroup.LayoutParams layoutParams = mContractedChild.getLayoutParams();
+            boolean useExactly = false;
+            if (layoutParams.height >= 0) {
+                // An actual height is set
+                size = Math.min(size, layoutParams.height);
+                useExactly = true;
+            }
+            if (shouldContractedBeFixedSize() || useExactly) {
+                heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
+            } else {
+                heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
+            }
+            measureChildWithMargins(mContractedChild, widthMeasureSpec, 0, heightSpec, 0);
+            int measuredHeight = mContractedChild.getMeasuredHeight();
+            if (measuredHeight < mMinContractedHeight) {
+                heightSpec = MeasureSpec.makeMeasureSpec(mMinContractedHeight, MeasureSpec.EXACTLY);
+                measureChildWithMargins(mContractedChild, widthMeasureSpec, 0, heightSpec, 0);
+            }
+            maxChildHeight = Math.max(maxChildHeight, measuredHeight);
+            if (updateContractedHeaderWidth()) {
+                measureChildWithMargins(mContractedChild, widthMeasureSpec, 0, heightSpec, 0);
+            }
+            if (mExpandedChild != null
+                    && mContractedChild.getMeasuredHeight() > mExpandedChild.getMeasuredHeight()) {
+                // the Expanded child is smaller then the collapsed. Let's remeasure it.
+                heightSpec = MeasureSpec.makeMeasureSpec(mContractedChild.getMeasuredHeight(),
+                        MeasureSpec.EXACTLY);
+                measureChildWithMargins(mExpandedChild, widthMeasureSpec, 0, heightSpec, 0);
+            }
+        }
+        if (mHeadsUpChild != null) {
+            int maxHeight = mHeadsUpHeight;
+            maxHeight += mHeadsUpWrapper.getExtraMeasureHeight();
+            int size = maxHeight;
+            ViewGroup.LayoutParams layoutParams = mHeadsUpChild.getLayoutParams();
+            boolean useExactly = false;
+            if (layoutParams.height >= 0) {
+                // An actual height is set
+                size = Math.min(size, layoutParams.height);
+                useExactly = true;
+            }
+            measureChildWithMargins(mHeadsUpChild, widthMeasureSpec, 0,
+                    MeasureSpec.makeMeasureSpec(size, useExactly ? MeasureSpec.EXACTLY
+                            : MeasureSpec.AT_MOST), 0);
+            maxChildHeight = Math.max(maxChildHeight, mHeadsUpChild.getMeasuredHeight());
+        }
+        if (mSingleLineView != null) {
+            int singleLineWidthSpec = widthMeasureSpec;
+            if (mSingleLineWidthIndention != 0
+                    && MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) {
+                singleLineWidthSpec = MeasureSpec.makeMeasureSpec(
+                        width - mSingleLineWidthIndention + mSingleLineView.getPaddingEnd(),
+                        MeasureSpec.EXACTLY);
+            }
+            mSingleLineView.measure(singleLineWidthSpec,
+                    MeasureSpec.makeMeasureSpec(mNotificationMaxHeight, MeasureSpec.AT_MOST));
+            maxChildHeight = Math.max(maxChildHeight, mSingleLineView.getMeasuredHeight());
+        }
+        if (mAmbientChild != null) {
+            int size = mNotificationAmbientHeight;
+            ViewGroup.LayoutParams layoutParams = mAmbientChild.getLayoutParams();
+            boolean useExactly = false;
+            if (layoutParams.height >= 0) {
+                // An actual height is set
+                size = Math.min(size, layoutParams.height);
+                useExactly = true;
+            }
+            mAmbientChild.measure(widthMeasureSpec,
+                    MeasureSpec.makeMeasureSpec(size, useExactly ? MeasureSpec.EXACTLY
+                            : MeasureSpec.AT_MOST));
+            maxChildHeight = Math.max(maxChildHeight, mAmbientChild.getMeasuredHeight());
+        }
+        if (mAmbientSingleLineChild != null) {
+            int size = mNotificationAmbientHeight;
+            ViewGroup.LayoutParams layoutParams = mAmbientSingleLineChild.getLayoutParams();
+            boolean useExactly = false;
+            if (layoutParams.height >= 0) {
+                // An actual height is set
+                size = Math.min(size, layoutParams.height);
+                useExactly = true;
+            }
+            int ambientSingleLineWidthSpec = widthMeasureSpec;
+            if (mSingleLineWidthIndention != 0
+                    && MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) {
+                ambientSingleLineWidthSpec = MeasureSpec.makeMeasureSpec(
+                        width - mSingleLineWidthIndention + mAmbientSingleLineChild.getPaddingEnd(),
+                        MeasureSpec.EXACTLY);
+            }
+            mAmbientSingleLineChild.measure(ambientSingleLineWidthSpec,
+                    MeasureSpec.makeMeasureSpec(size, useExactly ? MeasureSpec.EXACTLY
+                            : MeasureSpec.AT_MOST));
+            maxChildHeight = Math.max(maxChildHeight, mAmbientSingleLineChild.getMeasuredHeight());
+        }
+        int ownHeight = Math.min(maxChildHeight, maxSize);
+        setMeasuredDimension(width, ownHeight);
+    }
+
+    /**
+     * Get the extra height that needs to be added to the notification height for a given
+     * {@link RemoteInputView}.
+     * This is needed when the user is inline replying in order to ensure that the reply bar has
+     * enough padding.
+     *
+     * @param remoteInput The remote input to check.
+     * @return The extra height needed.
+     */
+    private int getExtraRemoteInputHeight(RemoteInputView remoteInput) {
+        if (remoteInput != null && (remoteInput.isActive() || remoteInput.isSending())) {
+            return getResources().getDimensionPixelSize(
+                    com.android.internal.R.dimen.notification_content_margin);
+        }
+        return 0;
+    }
+
+    private boolean updateContractedHeaderWidth() {
+        // We need to update the expanded and the collapsed header to have exactly the same with to
+        // have the expand buttons laid out at the same location.
+        NotificationHeaderView contractedHeader = mContractedWrapper.getNotificationHeader();
+        if (contractedHeader != null) {
+            if (mExpandedChild != null
+                    && mExpandedWrapper.getNotificationHeader() != null) {
+                NotificationHeaderView expandedHeader = mExpandedWrapper.getNotificationHeader();
+                int expandedSize = expandedHeader.getMeasuredWidth()
+                        - expandedHeader.getPaddingEnd();
+                int collapsedSize = contractedHeader.getMeasuredWidth()
+                        - expandedHeader.getPaddingEnd();
+                if (expandedSize != collapsedSize) {
+                    int paddingEnd = contractedHeader.getMeasuredWidth() - expandedSize;
+                    contractedHeader.setPadding(
+                            contractedHeader.isLayoutRtl()
+                                    ? paddingEnd
+                                    : contractedHeader.getPaddingLeft(),
+                            contractedHeader.getPaddingTop(),
+                            contractedHeader.isLayoutRtl()
+                                    ? contractedHeader.getPaddingLeft()
+                                    : paddingEnd,
+                            contractedHeader.getPaddingBottom());
+                    contractedHeader.setShowWorkBadgeAtEnd(true);
+                    return true;
+                }
+            } else {
+                int paddingEnd = mNotificationContentMarginEnd;
+                if (contractedHeader.getPaddingEnd() != paddingEnd) {
+                    contractedHeader.setPadding(
+                            contractedHeader.isLayoutRtl()
+                                    ? paddingEnd
+                                    : contractedHeader.getPaddingLeft(),
+                            contractedHeader.getPaddingTop(),
+                            contractedHeader.isLayoutRtl()
+                                    ? contractedHeader.getPaddingLeft()
+                                    : paddingEnd,
+                            contractedHeader.getPaddingBottom());
+                    contractedHeader.setShowWorkBadgeAtEnd(false);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean shouldContractedBeFixedSize() {
+        return mBeforeN && mContractedWrapper instanceof NotificationCustomViewWrapper;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        int previousHeight = 0;
+        if (mExpandedChild != null) {
+            previousHeight = mExpandedChild.getHeight();
+        }
+        super.onLayout(changed, left, top, right, bottom);
+        if (previousHeight != 0 && mExpandedChild.getHeight() != previousHeight) {
+            mContentHeightAtAnimationStart = previousHeight;
+        }
+        updateClipping();
+        invalidateOutline();
+        selectLayout(false /* animate */, mForceSelectNextLayout /* force */);
+        mForceSelectNextLayout = false;
+        updateExpandButtons(mExpandable);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        updateVisibility();
+    }
+
+    public View getContractedChild() {
+        return mContractedChild;
+    }
+
+    public View getExpandedChild() {
+        return mExpandedChild;
+    }
+
+    public View getHeadsUpChild() {
+        return mHeadsUpChild;
+    }
+
+    public View getAmbientChild() {
+        return mAmbientChild;
+    }
+
+    public HybridNotificationView getAmbientSingleLineChild() {
+        return mAmbientSingleLineChild;
+    }
+
+    public void setContractedChild(View child) {
+        if (mContractedChild != null) {
+            mContractedChild.animate().cancel();
+            removeView(mContractedChild);
+        }
+        addView(child);
+        mContractedChild = child;
+        mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child,
+                mContainingNotification);
+    }
+
+    private NotificationViewWrapper getWrapperForView(View child) {
+        if (child == mContractedChild) {
+            return mContractedWrapper;
+        }
+        if (child == mExpandedChild) {
+            return mExpandedWrapper;
+        }
+        if (child == mHeadsUpChild) {
+            return mHeadsUpWrapper;
+        }
+        if (child == mAmbientChild) {
+            return mAmbientWrapper;
+        }
+        return null;
+    }
+
+    public void setExpandedChild(View child) {
+        if (mExpandedChild != null) {
+            mPreviousExpandedRemoteInputIntent = null;
+            if (mExpandedRemoteInput != null) {
+                mExpandedRemoteInput.onNotificationUpdateOrReset();
+                if (mExpandedRemoteInput.isActive()) {
+                    mPreviousExpandedRemoteInputIntent = mExpandedRemoteInput.getPendingIntent();
+                    mCachedExpandedRemoteInput = mExpandedRemoteInput;
+                    mExpandedRemoteInput.dispatchStartTemporaryDetach();
+                    ((ViewGroup)mExpandedRemoteInput.getParent()).removeView(mExpandedRemoteInput);
+                }
+            }
+            mExpandedChild.animate().cancel();
+            removeView(mExpandedChild);
+            mExpandedRemoteInput = null;
+        }
+        if (child == null) {
+            mExpandedChild = null;
+            mExpandedWrapper = null;
+            if (mVisibleType == VISIBLE_TYPE_EXPANDED) {
+                mVisibleType = VISIBLE_TYPE_CONTRACTED;
+            }
+            if (mTransformationStartVisibleType == VISIBLE_TYPE_EXPANDED) {
+                mTransformationStartVisibleType = UNDEFINED;
+            }
+            return;
+        }
+        addView(child);
+        mExpandedChild = child;
+        mExpandedWrapper = NotificationViewWrapper.wrap(getContext(), child,
+                mContainingNotification);
+    }
+
+    public void setHeadsUpChild(View child) {
+        if (mHeadsUpChild != null) {
+            mPreviousHeadsUpRemoteInputIntent = null;
+            if (mHeadsUpRemoteInput != null) {
+                mHeadsUpRemoteInput.onNotificationUpdateOrReset();
+                if (mHeadsUpRemoteInput.isActive()) {
+                    mPreviousHeadsUpRemoteInputIntent = mHeadsUpRemoteInput.getPendingIntent();
+                    mCachedHeadsUpRemoteInput = mHeadsUpRemoteInput;
+                    mHeadsUpRemoteInput.dispatchStartTemporaryDetach();
+                    ((ViewGroup)mHeadsUpRemoteInput.getParent()).removeView(mHeadsUpRemoteInput);
+                }
+            }
+            mHeadsUpChild.animate().cancel();
+            removeView(mHeadsUpChild);
+            mHeadsUpRemoteInput = null;
+        }
+        if (child == null) {
+            mHeadsUpChild = null;
+            mHeadsUpWrapper = null;
+            if (mVisibleType == VISIBLE_TYPE_HEADSUP) {
+                mVisibleType = VISIBLE_TYPE_CONTRACTED;
+            }
+            if (mTransformationStartVisibleType == VISIBLE_TYPE_HEADSUP) {
+                mTransformationStartVisibleType = UNDEFINED;
+            }
+            return;
+        }
+        addView(child);
+        mHeadsUpChild = child;
+        mHeadsUpWrapper = NotificationViewWrapper.wrap(getContext(), child,
+                mContainingNotification);
+    }
+
+    public void setAmbientChild(View child) {
+        if (mAmbientChild != null) {
+            mAmbientChild.animate().cancel();
+            removeView(mAmbientChild);
+        }
+        if (child == null) {
+            return;
+        }
+        addView(child);
+        mAmbientChild = child;
+        mAmbientWrapper = NotificationViewWrapper.wrap(getContext(), child,
+                mContainingNotification);
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        updateVisibility();
+    }
+
+    private void updateVisibility() {
+        setVisible(isShown());
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
+    }
+
+    private void setVisible(final boolean isVisible) {
+        if (isVisible) {
+            // This call can happen multiple times, but removing only removes a single one.
+            // We therefore need to remove the old one.
+            getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
+            // We only animate if we are drawn at least once, otherwise the view might animate when
+            // it's shown the first time
+            getViewTreeObserver().addOnPreDrawListener(mEnableAnimationPredrawListener);
+        } else {
+            getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
+            mAnimate = false;
+        }
+    }
+
+    private void focusExpandButtonIfNecessary() {
+        if (mFocusOnVisibilityChange) {
+            NotificationHeaderView header = getVisibleNotificationHeader();
+            if (header != null) {
+                ImageView expandButton = header.getExpandButton();
+                if (expandButton != null) {
+                    expandButton.requestAccessibilityFocus();
+                }
+            }
+            mFocusOnVisibilityChange = false;
+        }
+    }
+
+    public void setContentHeight(int contentHeight) {
+        mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight());
+        int maxContentHeight = mContainingNotification.getIntrinsicHeight()
+                - getExtraRemoteInputHeight(mExpandedRemoteInput)
+                - getExtraRemoteInputHeight(mHeadsUpRemoteInput);
+        mContentHeight = Math.min(mUnrestrictedContentHeight, maxContentHeight);
+        selectLayout(mAnimate /* animate */, false /* force */);
+
+        int minHeightHint = getMinContentHeightHint();
+
+        NotificationViewWrapper wrapper = getVisibleWrapper(mVisibleType);
+        if (wrapper != null) {
+            wrapper.setContentHeight(mUnrestrictedContentHeight, minHeightHint);
+        }
+
+        wrapper = getVisibleWrapper(mTransformationStartVisibleType);
+        if (wrapper != null) {
+            wrapper.setContentHeight(mUnrestrictedContentHeight, minHeightHint);
+        }
+
+        updateClipping();
+        invalidateOutline();
+    }
+
+    /**
+     * @return the minimum apparent height that the wrapper should allow for the purpose
+     *         of aligning elements at the bottom edge. If this is larger than the content
+     *         height, the notification is clipped instead of being further shrunk.
+     */
+    private int getMinContentHeightHint() {
+        if (mIsChildInGroup && isVisibleOrTransitioning(VISIBLE_TYPE_SINGLELINE)) {
+            return mContext.getResources().getDimensionPixelSize(
+                        com.android.internal.R.dimen.notification_action_list_height);
+        }
+
+        // Transition between heads-up & expanded, or pinned.
+        if (mHeadsUpChild != null && mExpandedChild != null) {
+            boolean transitioningBetweenHunAndExpanded =
+                    isTransitioningFromTo(VISIBLE_TYPE_HEADSUP, VISIBLE_TYPE_EXPANDED) ||
+                    isTransitioningFromTo(VISIBLE_TYPE_EXPANDED, VISIBLE_TYPE_HEADSUP);
+            boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED)
+                    && (mIsHeadsUp || mHeadsUpAnimatingAway)
+                    && !mContainingNotification.isOnKeyguard();
+            if (transitioningBetweenHunAndExpanded || pinned) {
+                return Math.min(getViewHeight(VISIBLE_TYPE_HEADSUP),
+                        getViewHeight(VISIBLE_TYPE_EXPANDED));
+            }
+        }
+
+        // Size change of the expanded version
+        if ((mVisibleType == VISIBLE_TYPE_EXPANDED) && mContentHeightAtAnimationStart >= 0
+                && mExpandedChild != null) {
+            return Math.min(mContentHeightAtAnimationStart, getViewHeight(VISIBLE_TYPE_EXPANDED));
+        }
+
+        int hint;
+        if (mAmbientChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_AMBIENT)) {
+            hint = mAmbientChild.getHeight();
+        } else if (mAmbientSingleLineChild != null && isVisibleOrTransitioning(
+                VISIBLE_TYPE_AMBIENT_SINGLELINE)) {
+            hint = mAmbientSingleLineChild.getHeight();
+        } else if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
+            hint = getViewHeight(VISIBLE_TYPE_HEADSUP);
+        } else if (mExpandedChild != null) {
+            hint = getViewHeight(VISIBLE_TYPE_EXPANDED);
+        } else {
+            hint = getViewHeight(VISIBLE_TYPE_CONTRACTED)
+                    + mContext.getResources().getDimensionPixelSize(
+                            com.android.internal.R.dimen.notification_action_list_height);
+        }
+
+        if (mExpandedChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_EXPANDED)) {
+            hint = Math.min(hint, getViewHeight(VISIBLE_TYPE_EXPANDED));
+        }
+        return hint;
+    }
+
+    private boolean isTransitioningFromTo(int from, int to) {
+        return (mTransformationStartVisibleType == from || mAnimationStartVisibleType == from)
+                && mVisibleType == to;
+    }
+
+    private boolean isVisibleOrTransitioning(int type) {
+        return mVisibleType == type || mTransformationStartVisibleType == type
+                || mAnimationStartVisibleType == type;
+    }
+
+    private void updateContentTransformation() {
+        int visibleType = calculateVisibleType();
+        if (visibleType != mVisibleType) {
+            // A new transformation starts
+            mTransformationStartVisibleType = mVisibleType;
+            final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
+            final TransformableView hiddenView = getTransformableViewForVisibleType(
+                    mTransformationStartVisibleType);
+            shownView.transformFrom(hiddenView, 0.0f);
+            getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
+            hiddenView.transformTo(shownView, 0.0f);
+            mVisibleType = visibleType;
+            updateBackgroundColor(true /* animate */);
+        }
+        if (mForceSelectNextLayout) {
+            forceUpdateVisibilities();
+        }
+        if (mTransformationStartVisibleType != UNDEFINED
+                && mVisibleType != mTransformationStartVisibleType
+                && getViewForVisibleType(mTransformationStartVisibleType) != null) {
+            final TransformableView shownView = getTransformableViewForVisibleType(mVisibleType);
+            final TransformableView hiddenView = getTransformableViewForVisibleType(
+                    mTransformationStartVisibleType);
+            float transformationAmount = calculateTransformationAmount();
+            shownView.transformFrom(hiddenView, transformationAmount);
+            hiddenView.transformTo(shownView, transformationAmount);
+            updateBackgroundTransformation(transformationAmount);
+        } else {
+            updateViewVisibilities(visibleType);
+            updateBackgroundColor(false);
+        }
+    }
+
+    private void updateBackgroundTransformation(float transformationAmount) {
+        int endColor = getBackgroundColor(mVisibleType);
+        int startColor = getBackgroundColor(mTransformationStartVisibleType);
+        if (endColor != startColor) {
+            if (startColor == 0) {
+                startColor = mContainingNotification.getBackgroundColorWithoutTint();
+            }
+            if (endColor == 0) {
+                endColor = mContainingNotification.getBackgroundColorWithoutTint();
+            }
+            endColor = NotificationUtils.interpolateColors(startColor, endColor,
+                    transformationAmount);
+        }
+        mContainingNotification.updateBackgroundAlpha(transformationAmount);
+        mContainingNotification.setContentBackground(endColor, false, this);
+    }
+
+    private float calculateTransformationAmount() {
+        int startHeight = getViewHeight(mTransformationStartVisibleType);
+        int endHeight = getViewHeight(mVisibleType);
+        int progress = Math.abs(mContentHeight - startHeight);
+        int totalDistance = Math.abs(endHeight - startHeight);
+        if (totalDistance == 0) {
+            Log.wtf(TAG, "the total transformation distance is 0"
+                    + "\n StartType: " + mTransformationStartVisibleType + " height: " + startHeight
+                    + "\n VisibleType: " + mVisibleType + " height: " + endHeight
+                    + "\n mContentHeight: " + mContentHeight);
+            return 1.0f;
+        }
+        float amount = (float) progress / (float) totalDistance;
+        return Math.min(1.0f, amount);
+    }
+
+    public int getContentHeight() {
+        return mContentHeight;
+    }
+
+    public int getMaxHeight() {
+        if (mContainingNotification.isShowingAmbient()) {
+            return getShowingAmbientView().getHeight();
+        } else if (mExpandedChild != null) {
+            return getViewHeight(VISIBLE_TYPE_EXPANDED)
+                    + getExtraRemoteInputHeight(mExpandedRemoteInput);
+        } else if (mIsHeadsUp && mHeadsUpChild != null && !mContainingNotification.isOnKeyguard()) {
+            return getViewHeight(VISIBLE_TYPE_HEADSUP)
+                    + getExtraRemoteInputHeight(mHeadsUpRemoteInput);
+        }
+        return getViewHeight(VISIBLE_TYPE_CONTRACTED);
+    }
+
+    private int getViewHeight(int visibleType) {
+        View view = getViewForVisibleType(visibleType);
+        int height = view.getHeight();
+        NotificationViewWrapper viewWrapper = getWrapperForView(view);
+        if (viewWrapper != null) {
+            height += viewWrapper.getHeaderTranslation();
+        }
+        return height;
+    }
+
+    public int getMinHeight() {
+        return getMinHeight(false /* likeGroupExpanded */);
+    }
+
+    public int getMinHeight(boolean likeGroupExpanded) {
+        if (mContainingNotification.isShowingAmbient()) {
+            return getShowingAmbientView().getHeight();
+        } else if (likeGroupExpanded || !mIsChildInGroup || isGroupExpanded()) {
+            return getViewHeight(VISIBLE_TYPE_CONTRACTED);
+        } else {
+            return mSingleLineView.getHeight();
+        }
+    }
+
+    public View getShowingAmbientView() {
+        View v = mIsChildInGroup ? mAmbientSingleLineChild : mAmbientChild;
+        if (v != null) {
+            return v;
+        } else {
+            return mContractedChild;
+        }
+    }
+
+    private boolean isGroupExpanded() {
+        return mGroupManager.isGroupExpanded(mStatusBarNotification);
+    }
+
+    public void setClipTopAmount(int clipTopAmount) {
+        mClipTopAmount = clipTopAmount;
+        updateClipping();
+    }
+
+
+    public void setClipBottomAmount(int clipBottomAmount) {
+        mClipBottomAmount = clipBottomAmount;
+        updateClipping();
+    }
+
+    @Override
+    public void setTranslationY(float translationY) {
+        super.setTranslationY(translationY);
+        updateClipping();
+    }
+
+    private void updateClipping() {
+        if (mClipToActualHeight) {
+            int top = (int) (mClipTopAmount - getTranslationY());
+            int bottom = (int) (mUnrestrictedContentHeight - mClipBottomAmount - getTranslationY());
+            bottom = Math.max(top, bottom);
+            mClipBounds.set(0, top, getWidth(), bottom);
+            setClipBounds(mClipBounds);
+        } else {
+            setClipBounds(null);
+        }
+    }
+
+    public void setClipToActualHeight(boolean clipToActualHeight) {
+        mClipToActualHeight = clipToActualHeight;
+        updateClipping();
+    }
+
+    private void selectLayout(boolean animate, boolean force) {
+        if (mContractedChild == null) {
+            return;
+        }
+        if (mUserExpanding) {
+            updateContentTransformation();
+        } else {
+            int visibleType = calculateVisibleType();
+            boolean changedType = visibleType != mVisibleType;
+            if (changedType || force) {
+                View visibleView = getViewForVisibleType(visibleType);
+                if (visibleView != null) {
+                    visibleView.setVisibility(VISIBLE);
+                    transferRemoteInputFocus(visibleType);
+                }
+
+                if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
+                        || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
+                        || (visibleType == VISIBLE_TYPE_SINGLELINE && mSingleLineView != null)
+                        || visibleType == VISIBLE_TYPE_CONTRACTED)) {
+                    animateToVisibleType(visibleType);
+                } else {
+                    updateViewVisibilities(visibleType);
+                }
+                mVisibleType = visibleType;
+                if (changedType) {
+                    focusExpandButtonIfNecessary();
+                }
+                NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
+                if (visibleWrapper != null) {
+                    visibleWrapper.setContentHeight(mUnrestrictedContentHeight,
+                            getMinContentHeightHint());
+                }
+                updateBackgroundColor(animate);
+            }
+        }
+    }
+
+    private void forceUpdateVisibilities() {
+        forceUpdateVisibility(VISIBLE_TYPE_CONTRACTED, mContractedChild, mContractedWrapper);
+        forceUpdateVisibility(VISIBLE_TYPE_EXPANDED, mExpandedChild, mExpandedWrapper);
+        forceUpdateVisibility(VISIBLE_TYPE_HEADSUP, mHeadsUpChild, mHeadsUpWrapper);
+        forceUpdateVisibility(VISIBLE_TYPE_SINGLELINE, mSingleLineView, mSingleLineView);
+        forceUpdateVisibility(VISIBLE_TYPE_AMBIENT, mAmbientChild, mAmbientWrapper);
+        forceUpdateVisibility(VISIBLE_TYPE_AMBIENT_SINGLELINE, mAmbientSingleLineChild,
+                mAmbientSingleLineChild);
+        fireExpandedVisibleListenerIfVisible();
+        // forceUpdateVisibilities cancels outstanding animations without updating the
+        // mAnimationStartVisibleType. Do so here instead.
+        mAnimationStartVisibleType = UNDEFINED;
+    }
+
+    private void fireExpandedVisibleListenerIfVisible() {
+        if (mExpandedVisibleListener != null && mExpandedChild != null && isShown()
+                && mExpandedChild.getVisibility() == VISIBLE) {
+            Runnable listener = mExpandedVisibleListener;
+            mExpandedVisibleListener = null;
+            listener.run();
+        }
+    }
+
+    private void forceUpdateVisibility(int type, View view, TransformableView wrapper) {
+        if (view == null) {
+            return;
+        }
+        boolean visible = mVisibleType == type
+                || mTransformationStartVisibleType == type;
+        if (!visible) {
+            view.setVisibility(INVISIBLE);
+        } else {
+            wrapper.setVisible(true);
+        }
+    }
+
+    public void updateBackgroundColor(boolean animate) {
+        int customBackgroundColor = getBackgroundColor(mVisibleType);
+        mContainingNotification.resetBackgroundAlpha();
+        mContainingNotification.setContentBackground(customBackgroundColor, animate, this);
+    }
+
+    public void setBackgroundTintColor(int color) {
+        if (mExpandedSmartReplyView != null) {
+            mExpandedSmartReplyView.setBackgroundTintColor(color);
+        }
+    }
+
+    public int getVisibleType() {
+        return mVisibleType;
+    }
+
+    public int getBackgroundColorForExpansionState() {
+        // When expanding or user locked we want the new type, when collapsing we want
+        // the original type
+        final int visibleType = (mContainingNotification.isGroupExpanded()
+                || mContainingNotification.isUserLocked())
+                        ? calculateVisibleType()
+                        : getVisibleType();
+        return getBackgroundColor(visibleType);
+    }
+
+    public int getBackgroundColor(int visibleType) {
+        NotificationViewWrapper currentVisibleWrapper = getVisibleWrapper(visibleType);
+        int customBackgroundColor = 0;
+        if (currentVisibleWrapper != null) {
+            customBackgroundColor = currentVisibleWrapper.getCustomBackgroundColor();
+        }
+        return customBackgroundColor;
+    }
+
+    private void updateViewVisibilities(int visibleType) {
+        updateViewVisibility(visibleType, VISIBLE_TYPE_CONTRACTED,
+                mContractedChild, mContractedWrapper);
+        updateViewVisibility(visibleType, VISIBLE_TYPE_EXPANDED,
+                mExpandedChild, mExpandedWrapper);
+        updateViewVisibility(visibleType, VISIBLE_TYPE_HEADSUP,
+                mHeadsUpChild, mHeadsUpWrapper);
+        updateViewVisibility(visibleType, VISIBLE_TYPE_SINGLELINE,
+                mSingleLineView, mSingleLineView);
+        updateViewVisibility(visibleType, VISIBLE_TYPE_AMBIENT,
+                mAmbientChild, mAmbientWrapper);
+        updateViewVisibility(visibleType, VISIBLE_TYPE_AMBIENT_SINGLELINE,
+                mAmbientSingleLineChild, mAmbientSingleLineChild);
+        fireExpandedVisibleListenerIfVisible();
+        // updateViewVisibilities cancels outstanding animations without updating the
+        // mAnimationStartVisibleType. Do so here instead.
+        mAnimationStartVisibleType = UNDEFINED;
+    }
+
+    private void updateViewVisibility(int visibleType, int type, View view,
+            TransformableView wrapper) {
+        if (view != null) {
+            wrapper.setVisible(visibleType == type);
+        }
+    }
+
+    private void animateToVisibleType(int visibleType) {
+        final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
+        final TransformableView hiddenView = getTransformableViewForVisibleType(mVisibleType);
+        if (shownView == hiddenView || hiddenView == null) {
+            shownView.setVisible(true);
+            return;
+        }
+        mAnimationStartVisibleType = mVisibleType;
+        shownView.transformFrom(hiddenView);
+        getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
+        hiddenView.transformTo(shownView, new Runnable() {
+            @Override
+            public void run() {
+                if (hiddenView != getTransformableViewForVisibleType(mVisibleType)) {
+                    hiddenView.setVisible(false);
+                }
+                mAnimationStartVisibleType = UNDEFINED;
+            }
+        });
+        fireExpandedVisibleListenerIfVisible();
+    }
+
+    private void transferRemoteInputFocus(int visibleType) {
+        if (visibleType == VISIBLE_TYPE_HEADSUP
+                && mHeadsUpRemoteInput != null
+                && (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive())) {
+            mHeadsUpRemoteInput.stealFocusFrom(mExpandedRemoteInput);
+        }
+        if (visibleType == VISIBLE_TYPE_EXPANDED
+                && mExpandedRemoteInput != null
+                && (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive())) {
+            mExpandedRemoteInput.stealFocusFrom(mHeadsUpRemoteInput);
+        }
+    }
+
+    /**
+     * @param visibleType one of the static enum types in this view
+     * @return the corresponding transformable view according to the given visible type
+     */
+    private TransformableView getTransformableViewForVisibleType(int visibleType) {
+        switch (visibleType) {
+            case VISIBLE_TYPE_EXPANDED:
+                return mExpandedWrapper;
+            case VISIBLE_TYPE_HEADSUP:
+                return mHeadsUpWrapper;
+            case VISIBLE_TYPE_SINGLELINE:
+                return mSingleLineView;
+            case VISIBLE_TYPE_AMBIENT:
+                return mAmbientWrapper;
+            case VISIBLE_TYPE_AMBIENT_SINGLELINE:
+                return mAmbientSingleLineChild;
+            default:
+                return mContractedWrapper;
+        }
+    }
+
+    /**
+     * @param visibleType one of the static enum types in this view
+     * @return the corresponding view according to the given visible type
+     */
+    private View getViewForVisibleType(int visibleType) {
+        switch (visibleType) {
+            case VISIBLE_TYPE_EXPANDED:
+                return mExpandedChild;
+            case VISIBLE_TYPE_HEADSUP:
+                return mHeadsUpChild;
+            case VISIBLE_TYPE_SINGLELINE:
+                return mSingleLineView;
+            case VISIBLE_TYPE_AMBIENT:
+                return mAmbientChild;
+            case VISIBLE_TYPE_AMBIENT_SINGLELINE:
+                return mAmbientSingleLineChild;
+            default:
+                return mContractedChild;
+        }
+    }
+
+    public NotificationViewWrapper getVisibleWrapper(int visibleType) {
+        switch (visibleType) {
+            case VISIBLE_TYPE_EXPANDED:
+                return mExpandedWrapper;
+            case VISIBLE_TYPE_HEADSUP:
+                return mHeadsUpWrapper;
+            case VISIBLE_TYPE_CONTRACTED:
+                return mContractedWrapper;
+            case VISIBLE_TYPE_AMBIENT:
+                return mAmbientWrapper;
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * @return one of the static enum types in this view, calculated form the current state
+     */
+    public int calculateVisibleType() {
+        if (mContainingNotification.isShowingAmbient()) {
+            if (mIsChildInGroup && mAmbientSingleLineChild != null) {
+                return VISIBLE_TYPE_AMBIENT_SINGLELINE;
+            } else if (mAmbientChild != null) {
+                return VISIBLE_TYPE_AMBIENT;
+            } else {
+                return VISIBLE_TYPE_CONTRACTED;
+            }
+        }
+        if (mUserExpanding) {
+            int height = !mIsChildInGroup || isGroupExpanded()
+                    || mContainingNotification.isExpanded(true /* allowOnKeyguard */)
+                    ? mContainingNotification.getMaxContentHeight()
+                    : mContainingNotification.getShowingLayout().getMinHeight();
+            if (height == 0) {
+                height = mContentHeight;
+            }
+            int expandedVisualType = getVisualTypeForHeight(height);
+            int collapsedVisualType = mIsChildInGroup && !isGroupExpanded()
+                    ? VISIBLE_TYPE_SINGLELINE
+                    : getVisualTypeForHeight(mContainingNotification.getCollapsedHeight());
+            return mTransformationStartVisibleType == collapsedVisualType
+                    ? expandedVisualType
+                    : collapsedVisualType;
+        }
+        int intrinsicHeight = mContainingNotification.getIntrinsicHeight();
+        int viewHeight = mContentHeight;
+        if (intrinsicHeight != 0) {
+            // the intrinsicHeight might be 0 because it was just reset.
+            viewHeight = Math.min(mContentHeight, intrinsicHeight);
+        }
+        return getVisualTypeForHeight(viewHeight);
+    }
+
+    private int getVisualTypeForHeight(float viewHeight) {
+        boolean noExpandedChild = mExpandedChild == null;
+        if (!noExpandedChild && viewHeight == getViewHeight(VISIBLE_TYPE_EXPANDED)) {
+            return VISIBLE_TYPE_EXPANDED;
+        }
+        if (!mUserExpanding && mIsChildInGroup && !isGroupExpanded()) {
+            return VISIBLE_TYPE_SINGLELINE;
+        }
+
+        if ((mIsHeadsUp || mHeadsUpAnimatingAway) && mHeadsUpChild != null
+                && !mContainingNotification.isOnKeyguard()) {
+            if (viewHeight <= getViewHeight(VISIBLE_TYPE_HEADSUP) || noExpandedChild) {
+                return VISIBLE_TYPE_HEADSUP;
+            } else {
+                return VISIBLE_TYPE_EXPANDED;
+            }
+        } else {
+            if (noExpandedChild || (viewHeight <= getViewHeight(VISIBLE_TYPE_CONTRACTED)
+                    && (!mIsChildInGroup || isGroupExpanded()
+                            || !mContainingNotification.isExpanded(true /* allowOnKeyguard */)))) {
+                return VISIBLE_TYPE_CONTRACTED;
+            } else {
+                return VISIBLE_TYPE_EXPANDED;
+            }
+        }
+    }
+
+    public boolean isContentExpandable() {
+        return mIsContentExpandable;
+    }
+
+    public void setDark(boolean dark, boolean fade, long delay) {
+        if (mContractedChild == null) {
+            return;
+        }
+        mDark = dark;
+        selectLayout(!dark && fade /* animate */, false /* force */);
+    }
+
+    public void setHeadsUp(boolean headsUp) {
+        mIsHeadsUp = headsUp;
+        selectLayout(false /* animate */, true /* force */);
+        updateExpandButtons(mExpandable);
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+
+        // This is not really true, but good enough when fading from the contracted to the expanded
+        // layout, and saves us some layers.
+        return false;
+    }
+
+    public void setLegacy(boolean legacy) {
+        mLegacy = legacy;
+        updateLegacy();
+    }
+
+    private void updateLegacy() {
+        if (mContractedChild != null) {
+            mContractedWrapper.setLegacy(mLegacy);
+        }
+        if (mExpandedChild != null) {
+            mExpandedWrapper.setLegacy(mLegacy);
+        }
+        if (mHeadsUpChild != null) {
+            mHeadsUpWrapper.setLegacy(mLegacy);
+        }
+    }
+
+    public void setIsChildInGroup(boolean isChildInGroup) {
+        mIsChildInGroup = isChildInGroup;
+        if (mContractedChild != null) {
+            mContractedWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        if (mExpandedChild != null) {
+            mExpandedWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        if (mHeadsUpChild != null) {
+            mHeadsUpWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        if (mAmbientChild != null) {
+            mAmbientWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        updateAllSingleLineViews();
+    }
+
+    public void onNotificationUpdated(NotificationData.Entry entry) {
+        mStatusBarNotification = entry.notification;
+        mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
+        updateAllSingleLineViews();
+        if (mContractedChild != null) {
+            mContractedWrapper.onContentUpdated(entry.row);
+        }
+        if (mExpandedChild != null) {
+            mExpandedWrapper.onContentUpdated(entry.row);
+        }
+        if (mHeadsUpChild != null) {
+            mHeadsUpWrapper.onContentUpdated(entry.row);
+        }
+        if (mAmbientChild != null) {
+            mAmbientWrapper.onContentUpdated(entry.row);
+        }
+        applyRemoteInputAndSmartReply(entry);
+        updateLegacy();
+        mForceSelectNextLayout = true;
+        setDark(mDark, false /* animate */, 0 /* delay */);
+        mPreviousExpandedRemoteInputIntent = null;
+        mPreviousHeadsUpRemoteInputIntent = null;
+    }
+
+    private void updateAllSingleLineViews() {
+        updateSingleLineView();
+        updateAmbientSingleLineView();
+    }
+    private void updateSingleLineView() {
+        if (mIsChildInGroup) {
+            boolean isNewView = mSingleLineView == null;
+            mSingleLineView = mHybridGroupManager.bindFromNotification(
+                    mSingleLineView, mStatusBarNotification.getNotification());
+            if (isNewView) {
+                updateViewVisibility(mVisibleType, VISIBLE_TYPE_SINGLELINE,
+                        mSingleLineView, mSingleLineView);
+            }
+        } else if (mSingleLineView != null) {
+            removeView(mSingleLineView);
+            mSingleLineView = null;
+        }
+    }
+
+    private void updateAmbientSingleLineView() {
+        if (mIsChildInGroup) {
+            boolean isNewView = mAmbientSingleLineChild == null;
+            mAmbientSingleLineChild = mHybridGroupManager.bindAmbientFromNotification(
+                    mAmbientSingleLineChild, mStatusBarNotification.getNotification());
+            if (isNewView) {
+                updateViewVisibility(mVisibleType, VISIBLE_TYPE_AMBIENT_SINGLELINE,
+                        mAmbientSingleLineChild, mAmbientSingleLineChild);
+            }
+        } else if (mAmbientSingleLineChild != null) {
+            removeView(mAmbientSingleLineChild);
+            mAmbientSingleLineChild = null;
+        }
+    }
+
+    private void applyRemoteInputAndSmartReply(final NotificationData.Entry entry) {
+        if (mRemoteInputController == null) {
+            return;
+        }
+
+        boolean enableSmartReplies = (mSmartReplyConstants.isEnabled()
+                && (!mSmartReplyConstants.requiresTargetingP()
+                    || entry.targetSdk >= Build.VERSION_CODES.P));
+
+        boolean hasRemoteInput = false;
+        RemoteInput remoteInputWithChoices = null;
+        PendingIntent pendingIntentWithChoices = null;
+        CharSequence[] choices = null;
+
+        Notification.Action[] actions = entry.notification.getNotification().actions;
+        if (actions != null) {
+            for (Notification.Action a : actions) {
+                if (a.getRemoteInputs() == null) {
+                    continue;
+                }
+                for (RemoteInput ri : a.getRemoteInputs()) {
+                    boolean showRemoteInputView = ri.getAllowFreeFormInput();
+                    boolean showSmartReplyView = enableSmartReplies
+                            && (ArrayUtils.isEmpty(ri.getChoices())
+                            || (showRemoteInputView && !ArrayUtils.isEmpty(entry.smartReplies)));
+                    if (showRemoteInputView) {
+                        hasRemoteInput = true;
+                    }
+                    if (showSmartReplyView) {
+                        remoteInputWithChoices = ri;
+                        pendingIntentWithChoices = a.actionIntent;
+                        if (!ArrayUtils.isEmpty(ri.getChoices())) {
+                            choices = ri.getChoices();
+                        } else {
+                            choices = entry.smartReplies;
+                        }
+                    }
+                    if (showRemoteInputView || showSmartReplyView) {
+                        break;
+                    }
+                }
+            }
+        }
+
+        applyRemoteInput(entry, hasRemoteInput);
+        applySmartReplyView(remoteInputWithChoices, pendingIntentWithChoices, entry, choices);
+    }
+
+    private void applyRemoteInput(NotificationData.Entry entry, boolean hasRemoteInput) {
+        View bigContentView = mExpandedChild;
+        if (bigContentView != null) {
+            mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput,
+                    mPreviousExpandedRemoteInputIntent, mCachedExpandedRemoteInput,
+                    mExpandedWrapper);
+        } else {
+            mExpandedRemoteInput = null;
+        }
+        if (mCachedExpandedRemoteInput != null
+                && mCachedExpandedRemoteInput != mExpandedRemoteInput) {
+            // We had a cached remote input but didn't reuse it. Clean up required.
+            mCachedExpandedRemoteInput.dispatchFinishTemporaryDetach();
+        }
+        mCachedExpandedRemoteInput = null;
+
+        View headsUpContentView = mHeadsUpChild;
+        if (headsUpContentView != null) {
+            mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput,
+                    mPreviousHeadsUpRemoteInputIntent, mCachedHeadsUpRemoteInput, mHeadsUpWrapper);
+        } else {
+            mHeadsUpRemoteInput = null;
+        }
+        if (mCachedHeadsUpRemoteInput != null
+                && mCachedHeadsUpRemoteInput != mHeadsUpRemoteInput) {
+            // We had a cached remote input but didn't reuse it. Clean up required.
+            mCachedHeadsUpRemoteInput.dispatchFinishTemporaryDetach();
+        }
+        mCachedHeadsUpRemoteInput = null;
+    }
+
+    private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry,
+            boolean hasRemoteInput, PendingIntent existingPendingIntent,
+            RemoteInputView cachedView, NotificationViewWrapper wrapper) {
+        View actionContainerCandidate = view.findViewById(
+                com.android.internal.R.id.actions_container);
+        if (actionContainerCandidate instanceof FrameLayout) {
+            RemoteInputView existing = (RemoteInputView)
+                    view.findViewWithTag(RemoteInputView.VIEW_TAG);
+
+            if (existing != null) {
+                existing.onNotificationUpdateOrReset();
+            }
+
+            if (existing == null && hasRemoteInput) {
+                ViewGroup actionContainer = (FrameLayout) actionContainerCandidate;
+                if (cachedView == null) {
+                    RemoteInputView riv = RemoteInputView.inflate(
+                            mContext, actionContainer, entry, mRemoteInputController);
+
+                    riv.setVisibility(View.INVISIBLE);
+                    actionContainer.addView(riv, new LayoutParams(
+                            ViewGroup.LayoutParams.MATCH_PARENT,
+                            ViewGroup.LayoutParams.MATCH_PARENT)
+                    );
+                    existing = riv;
+                } else {
+                    actionContainer.addView(cachedView);
+                    cachedView.dispatchFinishTemporaryDetach();
+                    cachedView.requestFocus();
+                    existing = cachedView;
+                }
+            }
+            if (hasRemoteInput) {
+                int color = entry.notification.getNotification().color;
+                if (color == Notification.COLOR_DEFAULT) {
+                    color = mContext.getColor(R.color.default_remote_input_background);
+                }
+                existing.setBackgroundColor(ContrastColorUtil.ensureTextBackgroundColor(color,
+                        mContext.getColor(R.color.remote_input_text_enabled),
+                        mContext.getColor(R.color.remote_input_hint)));
+
+                existing.setWrapper(wrapper);
+                existing.setOnVisibilityChangedListener(this::setRemoteInputVisible);
+
+                if (existingPendingIntent != null || existing.isActive()) {
+                    // The current action could be gone, or the pending intent no longer valid.
+                    // If we find a matching action in the new notification, focus, otherwise close.
+                    Notification.Action[] actions = entry.notification.getNotification().actions;
+                    if (existingPendingIntent != null) {
+                        existing.setPendingIntent(existingPendingIntent);
+                    }
+                    if (existing.updatePendingIntentFromActions(actions)) {
+                        if (!existing.isActive()) {
+                            existing.focus();
+                        }
+                    } else {
+                        if (existing.isActive()) {
+                            existing.close();
+                        }
+                    }
+                }
+            }
+            return existing;
+        }
+        return null;
+    }
+
+    private void applySmartReplyView(RemoteInput remoteInput, PendingIntent pendingIntent,
+            NotificationData.Entry entry, CharSequence[] choices) {
+        if (mExpandedChild != null) {
+            mExpandedSmartReplyView =
+                    applySmartReplyView(mExpandedChild, remoteInput, pendingIntent, entry, choices);
+            if (mExpandedSmartReplyView != null && remoteInput != null
+                    && remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) {
+                mSmartReplyController.smartRepliesAdded(entry, remoteInput.getChoices().length);
+            }
+        }
+    }
+
+    private SmartReplyView applySmartReplyView(
+            View view, RemoteInput remoteInput, PendingIntent pendingIntent,
+            NotificationData.Entry entry, CharSequence[] choices) {
+        View smartReplyContainerCandidate = view.findViewById(
+                com.android.internal.R.id.smart_reply_container);
+        if (!(smartReplyContainerCandidate instanceof LinearLayout)) {
+            return null;
+        }
+        LinearLayout smartReplyContainer = (LinearLayout) smartReplyContainerCandidate;
+        if (remoteInput == null || pendingIntent == null) {
+            smartReplyContainer.setVisibility(View.GONE);
+            return null;
+        }
+        // If we are showing the spinner we don't want to add the buttons.
+        boolean showingSpinner = entry.notification.getNotification()
+                .extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
+        if (showingSpinner) {
+            smartReplyContainer.setVisibility(View.GONE);
+            return null;
+        }
+        // If we are keeping the notification around while sending we don't want to add the buttons.
+        boolean hideSmartReplies = entry.notification.getNotification()
+                .extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false);
+        if (hideSmartReplies) {
+            smartReplyContainer.setVisibility(View.GONE);
+            return null;
+        }
+        SmartReplyView smartReplyView = null;
+        if (smartReplyContainer.getChildCount() == 0) {
+            smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer);
+            smartReplyContainer.addView(smartReplyView);
+        } else if (smartReplyContainer.getChildCount() == 1) {
+            View child = smartReplyContainer.getChildAt(0);
+            if (child instanceof SmartReplyView) {
+                smartReplyView = (SmartReplyView) child;
+            }
+        }
+        if (smartReplyView != null) {
+            smartReplyView.setRepliesFromRemoteInput(remoteInput, pendingIntent,
+                    mSmartReplyController, entry, smartReplyContainer, choices
+            );
+            smartReplyContainer.setVisibility(View.VISIBLE);
+        }
+        return smartReplyView;
+    }
+
+    public void closeRemoteInput() {
+        if (mHeadsUpRemoteInput != null) {
+            mHeadsUpRemoteInput.close();
+        }
+        if (mExpandedRemoteInput != null) {
+            mExpandedRemoteInput.close();
+        }
+    }
+
+    public void setGroupManager(NotificationGroupManager groupManager) {
+        mGroupManager = groupManager;
+    }
+
+    public void setRemoteInputController(RemoteInputController r) {
+        mRemoteInputController = r;
+    }
+
+    public void setExpandClickListener(OnClickListener expandClickListener) {
+        mExpandClickListener = expandClickListener;
+    }
+
+    public void updateExpandButtons(boolean expandable) {
+        mExpandable = expandable;
+        // if the expanded child has the same height as the collapsed one we hide it.
+        if (mExpandedChild != null && mExpandedChild.getHeight() != 0) {
+            if ((!mIsHeadsUp && !mHeadsUpAnimatingAway)
+                    || mHeadsUpChild == null || mContainingNotification.isOnKeyguard()) {
+                if (mExpandedChild.getHeight() <= mContractedChild.getHeight()) {
+                    expandable = false;
+                }
+            } else if (mExpandedChild.getHeight() <= mHeadsUpChild.getHeight()) {
+                expandable = false;
+            }
+        }
+        if (mExpandedChild != null) {
+            mExpandedWrapper.updateExpandability(expandable, mExpandClickListener);
+        }
+        if (mContractedChild != null) {
+            mContractedWrapper.updateExpandability(expandable, mExpandClickListener);
+        }
+        if (mHeadsUpChild != null) {
+            mHeadsUpWrapper.updateExpandability(expandable,  mExpandClickListener);
+        }
+        mIsContentExpandable = expandable;
+    }
+
+    public NotificationHeaderView getNotificationHeader() {
+        NotificationHeaderView header = null;
+        if (mContractedChild != null) {
+            header = mContractedWrapper.getNotificationHeader();
+        }
+        if (header == null && mExpandedChild != null) {
+            header = mExpandedWrapper.getNotificationHeader();
+        }
+        if (header == null && mHeadsUpChild != null) {
+            header = mHeadsUpWrapper.getNotificationHeader();
+        }
+        if (header == null && mAmbientChild != null) {
+            header = mAmbientWrapper.getNotificationHeader();
+        }
+        return header;
+    }
+
+    public void showAppOpsIcons(ArraySet<Integer> activeOps) {
+        if (mContractedChild != null && mContractedWrapper.getNotificationHeader() != null) {
+            mContractedWrapper.getNotificationHeader().showAppOpsIcons(activeOps);
+        }
+        if (mExpandedChild != null && mExpandedWrapper.getNotificationHeader() != null) {
+            mExpandedWrapper.getNotificationHeader().showAppOpsIcons(activeOps);
+        }
+        if (mHeadsUpChild != null && mHeadsUpWrapper.getNotificationHeader() != null) {
+            mHeadsUpWrapper.getNotificationHeader().showAppOpsIcons(activeOps);
+        }
+    }
+
+    public NotificationHeaderView getContractedNotificationHeader() {
+        if (mContractedChild != null) {
+            return mContractedWrapper.getNotificationHeader();
+        }
+        return null;
+    }
+
+    public NotificationHeaderView getVisibleNotificationHeader() {
+        NotificationViewWrapper wrapper = getVisibleWrapper(mVisibleType);
+        return wrapper == null ? null : wrapper.getNotificationHeader();
+    }
+
+    public void setContainingNotification(ExpandableNotificationRow containingNotification) {
+        mContainingNotification = containingNotification;
+    }
+
+    public void requestSelectLayout(boolean needsAnimation) {
+        selectLayout(needsAnimation, false);
+    }
+
+    public void reInflateViews() {
+        if (mIsChildInGroup && mSingleLineView != null) {
+            removeView(mSingleLineView);
+            mSingleLineView = null;
+            updateAllSingleLineViews();
+        }
+    }
+
+    public void setUserExpanding(boolean userExpanding) {
+        mUserExpanding = userExpanding;
+        if (userExpanding) {
+            mTransformationStartVisibleType = mVisibleType;
+        } else {
+            mTransformationStartVisibleType = UNDEFINED;
+            mVisibleType = calculateVisibleType();
+            updateViewVisibilities(mVisibleType);
+            updateBackgroundColor(false);
+        }
+    }
+
+    /**
+     * Set by how much the single line view should be indented. Used when a overflow indicator is
+     * present and only during measuring
+     */
+    public void setSingleLineWidthIndention(int singleLineWidthIndention) {
+        if (singleLineWidthIndention != mSingleLineWidthIndention) {
+            mSingleLineWidthIndention = singleLineWidthIndention;
+            mContainingNotification.forceLayout();
+            forceLayout();
+        }
+    }
+
+    public HybridNotificationView getSingleLineView() {
+        return mSingleLineView;
+    }
+
+    public void setRemoved() {
+        if (mExpandedRemoteInput != null) {
+            mExpandedRemoteInput.setRemoved();
+        }
+        if (mHeadsUpRemoteInput != null) {
+            mHeadsUpRemoteInput.setRemoved();
+        }
+    }
+
+    public void setContentHeightAnimating(boolean animating) {
+        if (!animating) {
+            mContentHeightAtAnimationStart = UNDEFINED;
+        }
+    }
+
+    @VisibleForTesting
+    boolean isAnimatingVisibleType() {
+        return mAnimationStartVisibleType != UNDEFINED;
+    }
+
+    public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
+        mHeadsUpAnimatingAway = headsUpAnimatingAway;
+        selectLayout(false /* animate */, true /* force */);
+    }
+
+    public void setFocusOnVisibilityChange() {
+        mFocusOnVisibilityChange = true;
+    }
+
+    public void setIconsVisible(boolean iconsVisible) {
+        mIconsVisible = iconsVisible;
+        updateIconVisibilities();
+    }
+
+    private void updateIconVisibilities() {
+        if (mContractedWrapper != null) {
+            NotificationHeaderView header = mContractedWrapper.getNotificationHeader();
+            if (header != null) {
+                header.getIcon().setForceHidden(!mIconsVisible);
+            }
+        }
+        if (mHeadsUpWrapper != null) {
+            NotificationHeaderView header = mHeadsUpWrapper.getNotificationHeader();
+            if (header != null) {
+                header.getIcon().setForceHidden(!mIconsVisible);
+            }
+        }
+        if (mExpandedWrapper != null) {
+            NotificationHeaderView header = mExpandedWrapper.getNotificationHeader();
+            if (header != null) {
+                header.getIcon().setForceHidden(!mIconsVisible);
+            }
+        }
+    }
+
+    @Override
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
+        if (isVisible) {
+            fireExpandedVisibleListenerIfVisible();
+        }
+    }
+
+    /**
+     * Sets a one-shot listener for when the expanded view becomes visible.
+     *
+     * This will fire the listener immediately if the expanded view is already visible.
+     */
+    public void setOnExpandedVisibleListener(Runnable r) {
+        mExpandedVisibleListener = r;
+        fireExpandedVisibleListenerIfVisible();
+    }
+
+    public void setIsLowPriority(boolean isLowPriority) {
+        mIsLowPriority = isLowPriority;
+    }
+
+    public boolean isDimmable() {
+        if (!mContractedWrapper.isDimmable()) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Should a single click be disallowed on this view when on the keyguard?
+     */
+    public boolean disallowSingleClick(float x, float y) {
+        NotificationViewWrapper visibleWrapper = getVisibleWrapper(getVisibleType());
+        if (visibleWrapper != null) {
+            return visibleWrapper.disallowSingleClick(x, y);
+        }
+        return false;
+    }
+
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
+        boolean needsPaddings = shouldClipToRounding(getVisibleType(), topRounded, bottomRounded);
+        if (mUserExpanding) {
+             needsPaddings |= shouldClipToRounding(mTransformationStartVisibleType, topRounded,
+                     bottomRounded);
+        }
+        return needsPaddings;
+    }
+
+    private boolean shouldClipToRounding(int visibleType, boolean topRounded,
+            boolean bottomRounded) {
+        NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
+        if (visibleWrapper == null) {
+            return false;
+        }
+        return visibleWrapper.shouldClipToRounding(topRounded, bottomRounded);
+    }
+
+    public CharSequence getActiveRemoteInputText() {
+        if (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive()) {
+            return mExpandedRemoteInput.getText();
+        }
+        if (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive()) {
+            return mHeadsUpRemoteInput.getText();
+        }
+        return null;
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        float y = ev.getY();
+        // We still want to distribute touch events to the remote input even if it's outside the
+        // view boundary. We're therefore manually dispatching these events to the remote view
+        RemoteInputView riv = getRemoteInputForView(getViewForVisibleType(mVisibleType));
+        if (riv != null && riv.getVisibility() == VISIBLE) {
+            int inputStart = mUnrestrictedContentHeight - riv.getHeight();
+            if (y <= mUnrestrictedContentHeight && y >= inputStart) {
+                ev.offsetLocation(0, -inputStart);
+                return riv.dispatchTouchEvent(ev);
+            }
+        }
+        return super.dispatchTouchEvent(ev);
+    }
+
+    /**
+     * Overridden to make sure touches to the reply action bar actually go through to this view
+     */
+    @Override
+    public boolean pointInView(float localX, float localY, float slop) {
+        float top = mClipTopAmount;
+        float bottom = mUnrestrictedContentHeight;
+        return localX >= -slop && localY >= top - slop && localX < ((mRight - mLeft) + slop) &&
+                localY < (bottom + slop);
+    }
+
+    private RemoteInputView getRemoteInputForView(View child) {
+        if (child == mExpandedChild) {
+            return mExpandedRemoteInput;
+        } else if (child == mHeadsUpChild) {
+            return mHeadsUpRemoteInput;
+        }
+        return null;
+    }
+
+    public int getExpandHeight() {
+        int viewType = VISIBLE_TYPE_EXPANDED;
+        if (mExpandedChild == null) {
+            viewType = VISIBLE_TYPE_CONTRACTED;
+        }
+        return getViewHeight(viewType) + getExtraRemoteInputHeight(mExpandedRemoteInput);
+    }
+
+    public int getHeadsUpHeight() {
+        int viewType = VISIBLE_TYPE_HEADSUP;
+        if (mHeadsUpChild == null) {
+            viewType = VISIBLE_TYPE_CONTRACTED;
+        }
+        // The headsUp remote input quickly switches to the expanded one, so lets also include that
+        // one
+        return getViewHeight(viewType) + getExtraRemoteInputHeight(mHeadsUpRemoteInput)
+                + getExtraRemoteInputHeight(mExpandedRemoteInput);
+    }
+
+    public void setRemoteInputVisible(boolean remoteInputVisible) {
+        mRemoteInputVisible = remoteInputVisible;
+        setClipChildren(!remoteInputVisible);
+    }
+
+    @Override
+    public void setClipChildren(boolean clipChildren) {
+        clipChildren = clipChildren && !mRemoteInputVisible;
+        super.setClipChildren(clipChildren);
+    }
+
+    public void setHeaderVisibleAmount(float headerVisibleAmount) {
+        if (mContractedWrapper != null) {
+            mContractedWrapper.setHeaderVisibleAmount(headerVisibleAmount);
+        }
+        if (mHeadsUpWrapper != null) {
+            mHeadsUpWrapper.setHeaderVisibleAmount(headerVisibleAmount);
+        }
+        if (mExpandedWrapper != null) {
+            mExpandedWrapper.setHeaderVisibleAmount(headerVisibleAmount);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
new file mode 100644
index 0000000..0a197da
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import androidx.annotation.Nullable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.FrameLayout;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+
+/**
+ * The guts of a notification revealed when performing a long press.
+ */
+public class NotificationGuts extends FrameLayout {
+    private static final String TAG = "NotificationGuts";
+    private static final long CLOSE_GUTS_DELAY = 8000;
+
+    private Drawable mBackground;
+    private int mClipTopAmount;
+    private int mClipBottomAmount;
+    private int mActualHeight;
+    private boolean mExposed;
+
+    private Handler mHandler;
+    private Runnable mFalsingCheck;
+    private boolean mNeedsFalsingProtection;
+    private OnGutsClosedListener mClosedListener;
+    private OnHeightChangedListener mHeightListener;
+
+    private GutsContent mGutsContent;
+
+    public interface GutsContent {
+
+        public void setGutsParent(NotificationGuts listener);
+
+        /**
+         * Return the view to be shown in the notification guts.
+         */
+        public View getContentView();
+
+        /**
+         * Return the actual height of the content.
+         */
+        public int getActualHeight();
+
+        /**
+         * Called when the guts view have been told to close, typically after an outside
+         * interaction.
+         *
+         * @param save whether the state should be saved.
+         * @param force whether the guts view should be forced closed regardless of state.
+         * @return if closing the view has been handled.
+         */
+        public boolean handleCloseControls(boolean save, boolean force);
+
+        /**
+         * Return whether the notification associated with these guts is set to be removed.
+         */
+        public boolean willBeRemoved();
+
+        /**
+         * Return whether these guts are a leavebehind (e.g. {@link NotificationSnooze}).
+         */
+        public default boolean isLeavebehind() {
+            return false;
+        }
+
+        /**
+         * Return whether something changed and needs to be saved, possibly requiring a bouncer.
+         */
+        boolean shouldBeSaved();
+    }
+
+    public interface OnGutsClosedListener {
+        public void onGutsClosed(NotificationGuts guts);
+    }
+
+    public interface OnHeightChangedListener {
+        public void onHeightChanged(NotificationGuts guts);
+    }
+
+    interface OnSettingsClickListener {
+        void onClick(View v, int appUid);
+    }
+
+    public NotificationGuts(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setWillNotDraw(false);
+        mHandler = new Handler();
+        mFalsingCheck = new Runnable() {
+            @Override
+            public void run() {
+                if (mNeedsFalsingProtection && mExposed) {
+                    closeControls(-1 /* x */, -1 /* y */, false /* save */, false /* force */);
+                }
+            }
+        };
+        final TypedArray ta = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.Theme, 0, 0);
+        ta.recycle();
+    }
+
+    public NotificationGuts(Context context) {
+        this(context, null);
+    }
+
+    public void setGutsContent(GutsContent content) {
+        mGutsContent = content;
+        removeAllViews();
+        addView(mGutsContent.getContentView());
+    }
+
+    public GutsContent getGutsContent() {
+        return mGutsContent;
+    }
+
+    public void resetFalsingCheck() {
+        mHandler.removeCallbacks(mFalsingCheck);
+        if (mNeedsFalsingProtection && mExposed) {
+            mHandler.postDelayed(mFalsingCheck, CLOSE_GUTS_DELAY);
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        draw(canvas, mBackground);
+    }
+
+    private void draw(Canvas canvas, Drawable drawable) {
+        int top = mClipTopAmount;
+        int bottom = mActualHeight - mClipBottomAmount;
+        if (drawable != null && top < bottom) {
+            drawable.setBounds(0, top, getWidth(), bottom);
+            drawable.draw(canvas);
+        }
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mBackground = mContext.getDrawable(R.drawable.notification_guts_bg);
+        if (mBackground != null) {
+            mBackground.setCallback(this);
+        }
+    }
+
+    @Override
+    protected boolean verifyDrawable(Drawable who) {
+        return super.verifyDrawable(who) || who == mBackground;
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        drawableStateChanged(mBackground);
+    }
+
+    private void drawableStateChanged(Drawable d) {
+        if (d != null && d.isStateful()) {
+            d.setState(getDrawableState());
+        }
+    }
+
+    @Override
+    public void drawableHotspotChanged(float x, float y) {
+        if (mBackground != null) {
+            mBackground.setHotspot(x, y);
+        }
+    }
+
+    public void openControls(
+            boolean shouldDoCircularReveal,
+            int x,
+            int y,
+            boolean needsFalsingProtection,
+            @Nullable Runnable onAnimationEnd) {
+        animateOpen(shouldDoCircularReveal, x, y, onAnimationEnd);
+        setExposed(true /* exposed */, needsFalsingProtection);
+    }
+
+    /**
+     * Hide controls if they are visible
+     * @param leavebehinds true if leavebehinds should be closed
+     * @param controls true if controls should be closed
+     * @param x x coordinate to animate the close circular reveal with
+     * @param y y coordinate to animate the close circular reveal with
+     * @param force whether the guts should be force-closed regardless of state.
+     */
+    public void closeControls(boolean leavebehinds, boolean controls, int x, int y, boolean force) {
+        if (mGutsContent != null) {
+            if ((mGutsContent.isLeavebehind() && leavebehinds)
+                    || (!mGutsContent.isLeavebehind() && controls)) {
+                closeControls(x, y, mGutsContent.shouldBeSaved(), force);
+            }
+        }
+    }
+
+    /**
+     * Closes any exposed guts/views.
+     *
+     * @param x x coordinate to animate the close circular reveal with
+     * @param y y coordinate to animate the close circular reveal with
+     * @param save whether the state should be saved
+     * @param force whether the guts should be force-closed regardless of state.
+     */
+    public void closeControls(int x, int y, boolean save, boolean force) {
+        // First try to dismiss any blocking helper.
+        boolean wasBlockingHelperDismissed =
+                Dependency.get(NotificationBlockingHelperManager.class)
+                        .dismissCurrentBlockingHelper();
+
+        if (getWindowToken() == null) {
+            if (mClosedListener != null) {
+                mClosedListener.onGutsClosed(this);
+            }
+            return;
+        }
+
+        if (mGutsContent == null
+                || !mGutsContent.handleCloseControls(save, force)
+                || wasBlockingHelperDismissed) {
+            // We only want to do a circular reveal if we're not showing the blocking helper.
+            animateClose(x, y, !wasBlockingHelperDismissed /* shouldDoCircularReveal */);
+
+            setExposed(false, mNeedsFalsingProtection);
+            if (mClosedListener != null) {
+                mClosedListener.onGutsClosed(this);
+            }
+        }
+    }
+
+    /** Animates in the guts view via either a fade or a circular reveal. */
+    private void animateOpen(
+            boolean shouldDoCircularReveal, int x, int y, @Nullable Runnable onAnimationEnd) {
+        if (isAttachedToWindow()) {
+            if (shouldDoCircularReveal) {
+                double horz = Math.max(getWidth() - x, x);
+                double vert = Math.max(getHeight() - y, y);
+                float r = (float) Math.hypot(horz, vert);
+                // Circular reveal originating at (x, y)
+                Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
+                a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+                a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+                a.addListener(new AnimateOpenListener(onAnimationEnd));
+                a.start();
+            } else {
+                // Fade in content
+                this.setAlpha(0f);
+                this.animate()
+                        .alpha(1f)
+                        .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
+                        .setInterpolator(Interpolators.ALPHA_IN)
+                        .setListener(new AnimateOpenListener(onAnimationEnd))
+                        .start();
+            }
+        } else {
+            Log.w(TAG, "Failed to animate guts open");
+        }
+    }
+
+
+    /** Animates out the guts view via either a fade or a circular reveal. */
+    @VisibleForTesting
+    void animateClose(int x, int y, boolean shouldDoCircularReveal) {
+        if (isAttachedToWindow()) {
+            if (shouldDoCircularReveal) {
+                // Circular reveal originating at (x, y)
+                if (x == -1 || y == -1) {
+                    x = (getLeft() + getRight()) / 2;
+                    y = (getTop() + getHeight() / 2);
+                }
+                double horz = Math.max(getWidth() - x, x);
+                double vert = Math.max(getHeight() - y, y);
+                float r = (float) Math.hypot(horz, vert);
+                Animator a = ViewAnimationUtils.createCircularReveal(this,
+                        x, y, r, 0);
+                a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+                a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+                a.addListener(new AnimateCloseListener(this /* view */));
+                a.start();
+            } else {
+                // Fade in the blocking helper.
+                this.animate()
+                        .alpha(0f)
+                        .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
+                        .setInterpolator(Interpolators.ALPHA_OUT)
+                        .setListener(new AnimateCloseListener(this /* view */))
+                        .start();
+            }
+        } else {
+            Log.w(TAG, "Failed to animate guts close");
+        }
+    }
+
+    public void setActualHeight(int actualHeight) {
+        mActualHeight = actualHeight;
+        invalidate();
+    }
+
+    public int getActualHeight() {
+        return mActualHeight;
+    }
+
+    public int getIntrinsicHeight() {
+        return mGutsContent != null && mExposed ? mGutsContent.getActualHeight() : getHeight();
+    }
+
+    public void setClipTopAmount(int clipTopAmount) {
+        mClipTopAmount = clipTopAmount;
+        invalidate();
+    }
+
+    public void setClipBottomAmount(int clipBottomAmount) {
+        mClipBottomAmount = clipBottomAmount;
+        invalidate();
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        // Prevents this view from creating a layer when alpha is animating.
+        return false;
+    }
+
+    public void setClosedListener(OnGutsClosedListener listener) {
+        mClosedListener = listener;
+    }
+
+    public void setHeightChangedListener(OnHeightChangedListener listener) {
+        mHeightListener = listener;
+    }
+
+    protected void onHeightChanged() {
+        if (mHeightListener != null) {
+            mHeightListener.onHeightChanged(this);
+        }
+    }
+
+    @VisibleForTesting
+    void setExposed(boolean exposed, boolean needsFalsingProtection) {
+        final boolean wasExposed = mExposed;
+        mExposed = exposed;
+        mNeedsFalsingProtection = needsFalsingProtection;
+        if (mExposed && mNeedsFalsingProtection) {
+            resetFalsingCheck();
+        } else {
+            mHandler.removeCallbacks(mFalsingCheck);
+        }
+        if (wasExposed != mExposed && mGutsContent != null) {
+            final View contentView = mGutsContent.getContentView();
+            contentView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+            if (mExposed) {
+                contentView.requestAccessibilityFocus();
+            }
+        }
+    }
+
+    public boolean willBeRemoved() {
+        return mGutsContent != null ? mGutsContent.willBeRemoved() : false;
+    }
+
+    public boolean isExposed() {
+        return mExposed;
+    }
+
+    public boolean isLeavebehind() {
+        return mGutsContent != null && mGutsContent.isLeavebehind();
+    }
+
+    /** Listener for animations executed in {@link #animateOpen(boolean, int, int, Runnable)}. */
+    private static class AnimateOpenListener extends AnimatorListenerAdapter {
+        final Runnable mOnAnimationEnd;
+
+        private AnimateOpenListener(Runnable onAnimationEnd) {
+            mOnAnimationEnd = onAnimationEnd;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            super.onAnimationEnd(animation);
+            if (mOnAnimationEnd != null) {
+                mOnAnimationEnd.run();
+            }
+        }
+    }
+
+    /** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
+    private static class AnimateCloseListener extends AnimatorListenerAdapter {
+        final View mView;
+
+        private AnimateCloseListener(View view) {
+            mView = view;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            super.onAnimationEnd(animation);
+            mView.setVisibility(View.GONE);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
new file mode 100644
index 0000000..e635976
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.statusbar.notification.row;
+
+import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_NEGATIVE;
+
+import android.app.INotificationManager;
+import android.app.NotificationChannel;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+import android.util.Log;
+import android.view.HapticFeedbackConstants;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * Handles various NotificationGuts related tasks, such as binding guts to a row, opening and
+ * closing guts, and keeping track of the currently exposed notification guts.
+ */
+public class NotificationGutsManager implements Dumpable {
+    private static final String TAG = "NotificationGutsManager";
+
+    // Must match constant in Settings. Used to highlight preferences when linking to Settings.
+    private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
+
+    private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+    private final Context mContext;
+    private final AccessibilityManager mAccessibilityManager;
+
+    // Dependencies:
+    private final NotificationLockscreenUserManager mLockscreenUserManager =
+            Dependency.get(NotificationLockscreenUserManager.class);
+
+    // which notification is currently being longpress-examined by the user
+    private NotificationGuts mNotificationGutsExposed;
+    private NotificationMenuRowPlugin.MenuItem mGutsMenuItem;
+    protected NotificationPresenter mPresenter;
+    protected NotificationEntryManager mEntryManager;
+    private NotificationListContainer mListContainer;
+    private NotificationInfo.CheckSaveListener mCheckSaveListener;
+    private OnSettingsClickListener mOnSettingsClickListener;
+    private String mKeyToRemoveOnGutsClosed;
+
+    public NotificationGutsManager(Context context) {
+        mContext = context;
+        Resources res = context.getResources();
+
+        mAccessibilityManager = (AccessibilityManager)
+                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+    }
+
+    public void setUpWithPresenter(NotificationPresenter presenter,
+            NotificationEntryManager entryManager, NotificationListContainer listContainer,
+            NotificationInfo.CheckSaveListener checkSaveListener,
+            OnSettingsClickListener onSettingsClickListener) {
+        mPresenter = presenter;
+        mEntryManager = entryManager;
+        mListContainer = listContainer;
+        mCheckSaveListener = checkSaveListener;
+        mOnSettingsClickListener = onSettingsClickListener;
+    }
+
+    public String getKeyToRemoveOnGutsClosed() {
+        return mKeyToRemoveOnGutsClosed;
+    }
+
+    public void setKeyToRemoveOnGutsClosed(String keyToRemoveOnGutsClosed) {
+        mKeyToRemoveOnGutsClosed = keyToRemoveOnGutsClosed;
+    }
+
+    public void onDensityOrFontScaleChanged(ExpandableNotificationRow row) {
+        setExposedGuts(row.getGuts());
+        bindGuts(row);
+    }
+
+    /**
+     * Sends an intent to open the app settings for a particular package and optional
+     * channel.
+     */
+    private void startAppNotificationSettingsActivity(String packageName, final int appUid,
+            final NotificationChannel channel, ExpandableNotificationRow row) {
+        final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+        intent.setData(Uri.fromParts("package", packageName, null));
+        intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
+        intent.putExtra(Settings.EXTRA_APP_UID, appUid);
+        if (channel != null) {
+            intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channel.getId());
+        }
+        mPresenter.startNotificationGutsIntent(intent, appUid, row);
+    }
+
+    protected void startAppOpsSettingsActivity(String pkg, int uid, ArraySet<Integer> ops,
+            ExpandableNotificationRow row) {
+        if (ops.contains(OP_SYSTEM_ALERT_WINDOW)) {
+            if (ops.contains(OP_CAMERA) || ops.contains(OP_RECORD_AUDIO)) {
+                startAppNotificationSettingsActivity(pkg, uid, null, row);
+            } else {
+                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
+                intent.setData(Uri.fromParts("package", pkg, null));
+                mPresenter.startNotificationGutsIntent(intent, uid, row);
+            }
+        } else if (ops.contains(OP_CAMERA) || ops.contains(OP_RECORD_AUDIO)) {
+            Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS);
+            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, pkg);
+            mPresenter.startNotificationGutsIntent(intent, uid, row);
+        }
+    }
+
+    public boolean bindGuts(final ExpandableNotificationRow row) {
+        row.inflateGuts();
+        return bindGuts(row, mGutsMenuItem);
+    }
+
+    private boolean bindGuts(final ExpandableNotificationRow row,
+            NotificationMenuRowPlugin.MenuItem item) {
+        StatusBarNotification sbn = row.getStatusBarNotification();
+
+        row.setGutsView(item);
+        row.setTag(sbn.getPackageName());
+        row.getGuts().setClosedListener((NotificationGuts g) -> {
+            row.onGutsClosed();
+            if (!g.willBeRemoved() && !row.isRemoved()) {
+                mListContainer.onHeightChanged(
+                        row, !mPresenter.isPresenterFullyCollapsed() /* needsAnimation */);
+            }
+            if (mNotificationGutsExposed == g) {
+                mNotificationGutsExposed = null;
+                mGutsMenuItem = null;
+            }
+            String key = sbn.getKey();
+            if (key.equals(mKeyToRemoveOnGutsClosed)) {
+                mKeyToRemoveOnGutsClosed = null;
+                mEntryManager.removeNotification(key, mEntryManager.getLatestRankingMap());
+            }
+        });
+
+        View gutsView = item.getGutsView();
+        try {
+            if (gutsView instanceof NotificationSnooze) {
+                initializeSnoozeView(row, (NotificationSnooze) gutsView);
+            } else if (gutsView instanceof AppOpsInfo) {
+                initializeAppOpsInfo(row, (AppOpsInfo) gutsView);
+            } else if (gutsView instanceof NotificationInfo) {
+                initializeNotificationInfo(row, (NotificationInfo) gutsView);
+            }
+            return true;
+        } catch (Exception e) {
+            Log.e(TAG, "error binding guts", e);
+            return false;
+        }
+    }
+
+    /**
+     * Sets up the {@link NotificationSnooze} inside the notification row's guts.
+     *
+     * @param row view to set up the guts for
+     * @param notificationSnoozeView view to set up/bind within {@code row}
+     */
+    private void initializeSnoozeView(
+            final ExpandableNotificationRow row,
+            NotificationSnooze notificationSnoozeView) {
+        NotificationGuts guts = row.getGuts();
+        StatusBarNotification sbn = row.getStatusBarNotification();
+
+        notificationSnoozeView.setSnoozeListener(mListContainer.getSwipeActionHelper());
+        notificationSnoozeView.setStatusBarNotification(sbn);
+        notificationSnoozeView.setSnoozeOptions(row.getEntry().snoozeCriteria);
+        guts.setHeightChangedListener((NotificationGuts g) -> {
+            mListContainer.onHeightChanged(row, row.isShown() /* needsAnimation */);
+        });
+    }
+
+    /**
+     * Sets up the {@link AppOpsInfo} inside the notification row's guts.
+     *
+     * @param row view to set up the guts for
+     * @param appOpsInfoView view to set up/bind within {@code row}
+     */
+    private void initializeAppOpsInfo(
+            final ExpandableNotificationRow row,
+            AppOpsInfo appOpsInfoView) {
+        NotificationGuts guts = row.getGuts();
+        StatusBarNotification sbn = row.getStatusBarNotification();
+        UserHandle userHandle = sbn.getUser();
+        PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
+                userHandle.getIdentifier());
+
+        AppOpsInfo.OnSettingsClickListener onSettingsClick =
+                (View v, String pkg, int uid, ArraySet<Integer> ops) -> {
+            mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS);
+            guts.resetFalsingCheck();
+            startAppOpsSettingsActivity(pkg, uid, ops, row);
+        };
+        if (!row.getEntry().mActiveAppOps.isEmpty()) {
+            appOpsInfoView.bindGuts(pmUser, onSettingsClick, sbn, row.getEntry().mActiveAppOps);
+        }
+    }
+
+    /**
+     * Sets up the {@link NotificationInfo} inside the notification row's guts.
+     *
+     * @param row view to set up the guts for
+     * @param notificationInfoView view to set up/bind within {@code row}
+     */
+    @VisibleForTesting
+    void initializeNotificationInfo(
+            final ExpandableNotificationRow row,
+            NotificationInfo notificationInfoView) throws Exception {
+        NotificationGuts guts = row.getGuts();
+        StatusBarNotification sbn = row.getStatusBarNotification();
+        String packageName = sbn.getPackageName();
+        // Settings link is only valid for notifications that specify a non-system user
+        NotificationInfo.OnSettingsClickListener onSettingsClick = null;
+        UserHandle userHandle = sbn.getUser();
+        PackageManager pmUser = StatusBar.getPackageManagerForUser(
+                mContext, userHandle.getIdentifier());
+        INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(
+                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        final NotificationInfo.OnAppSettingsClickListener onAppSettingsClick =
+                (View v, Intent intent) -> {
+                    mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_APP_NOTE_SETTINGS);
+                    guts.resetFalsingCheck();
+                    mPresenter.startNotificationGutsIntent(intent, sbn.getUid(), row);
+                };
+        boolean isForBlockingHelper = row.isBlockingHelperShowing();
+
+        if (!userHandle.equals(UserHandle.ALL)
+                || mLockscreenUserManager.getCurrentUserId() == UserHandle.USER_SYSTEM) {
+            onSettingsClick = (View v, NotificationChannel channel, int appUid) -> {
+                mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_NOTE_INFO);
+                guts.resetFalsingCheck();
+                mOnSettingsClickListener.onClick(sbn.getKey());
+                startAppNotificationSettingsActivity(packageName, appUid, channel, row);
+            };
+        }
+
+        notificationInfoView.bindNotification(
+                pmUser,
+                iNotificationManager,
+                packageName,
+                row.getEntry().channel,
+                row.getNumUniqueChannels(),
+                sbn,
+                mCheckSaveListener,
+                onSettingsClick,
+                onAppSettingsClick,
+                mPresenter.isDeviceProvisioned(),
+                row.getIsNonblockable(),
+                isForBlockingHelper,
+                row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
+
+    }
+
+    /**
+     * Closes guts or notification menus that might be visible and saves any changes.
+     *
+     * @param removeLeavebehinds true if leavebehinds (e.g. snooze) should be closed.
+     * @param force true if guts should be closed regardless of state (used for snooze only).
+     * @param removeControls true if controls (e.g. info) should be closed.
+     * @param x if closed based on touch location, this is the x touch location.
+     * @param y if closed based on touch location, this is the y touch location.
+     * @param resetMenu if any notification menus that might be revealed should be closed.
+     */
+    public void closeAndSaveGuts(boolean removeLeavebehinds, boolean force, boolean removeControls,
+            int x, int y, boolean resetMenu) {
+        if (mNotificationGutsExposed != null) {
+            mNotificationGutsExposed.closeControls(removeLeavebehinds, removeControls, x, y, force);
+        }
+        if (resetMenu) {
+            mListContainer.resetExposedMenuView(false /* animate */, true /* force */);
+        }
+    }
+
+    /**
+     * Returns the exposed NotificationGuts or null if none are exposed.
+     */
+    public NotificationGuts getExposedGuts() {
+        return mNotificationGutsExposed;
+    }
+
+    public void setExposedGuts(NotificationGuts guts) {
+        mNotificationGutsExposed = guts;
+    }
+
+    /**
+     * Opens guts on the given ExpandableNotificationRow {@code view}. This handles opening guts for
+     * the normal half-swipe and long-press use cases via a circular reveal. When the blocking
+     * helper needs to be shown on the row, this will skip the circular reveal.
+     *
+     * @param view ExpandableNotificationRow to open guts on
+     * @param x x coordinate of origin of circular reveal
+     * @param y y coordinate of origin of circular reveal
+     * @param menuItem MenuItem the guts should display
+     * @return true if guts was opened
+     */
+    public boolean openGuts(
+            View view,
+            int x,
+            int y,
+            NotificationMenuRowPlugin.MenuItem menuItem) {
+        if (!(view instanceof ExpandableNotificationRow)) {
+            return false;
+        }
+
+        if (view.getWindowToken() == null) {
+            Log.e(TAG, "Trying to show notification guts, but not attached to window");
+            return false;
+        }
+
+        final ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+        if (row.isDark()) {
+            return false;
+        }
+        view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+        if (row.areGutsExposed()) {
+            closeAndSaveGuts(false /* removeLeavebehind */, false /* force */,
+                    true /* removeControls */, -1 /* x */, -1 /* y */,
+                    true /* resetMenu */);
+            return false;
+        }
+
+        row.inflateGuts();
+        NotificationGuts guts = row.getGuts();
+        mNotificationGutsExposed = guts;
+        if (!bindGuts(row, menuItem)) {
+            // exception occurred trying to fill in all the data, bail.
+            return false;
+        }
+
+
+        // Assume we are a status_bar_notification_row
+        if (guts == null) {
+            // This view has no guts. Examples are the more card or the dismiss all view
+            return false;
+        }
+
+        mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_NOTE_CONTROLS);
+
+        // ensure that it's laid but not visible until actually laid out
+        guts.setVisibility(View.INVISIBLE);
+        // Post to ensure the the guts are properly laid out.
+        guts.post(new Runnable() {
+            @Override
+            public void run() {
+                if (row.getWindowToken() == null) {
+                    Log.e(TAG, "Trying to show notification guts in post(), but not attached to "
+                            + "window");
+                    return;
+                }
+                guts.setVisibility(View.VISIBLE);
+
+                final boolean needsFalsingProtection =
+                        (mPresenter.isPresenterLocked() &&
+                                !mAccessibilityManager.isTouchExplorationEnabled());
+
+                guts.openControls(
+                        !row.isBlockingHelperShowing(),
+                        x,
+                        y,
+                        needsFalsingProtection,
+                        row::onGutsOpened);
+
+                row.closeRemoteInput();
+                mListContainer.onHeightChanged(row, true /* needsAnimation */);
+                mGutsMenuItem = menuItem;
+            }
+        });
+        return true;
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("NotificationGutsManager state:");
+        pw.print("  mKeyToRemoveOnGutsClosed: ");
+        pw.println(mKeyToRemoveOnGutsClosed);
+    }
+
+    public interface OnSettingsClickListener {
+        void onClick(String key);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java
new file mode 100644
index 0000000..aa4765a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.CancellationSignal;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.InflationTask;
+import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.MediaNotificationProcessor;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.util.Assert;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A utility that inflates the right kind of contentView based on the state
+ */
+public class NotificationInflater {
+
+    public static final String TAG = "NotificationInflater";
+    @VisibleForTesting
+    static final int FLAG_REINFLATE_ALL = ~0;
+    private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0;
+    @VisibleForTesting
+    static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1;
+    private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2;
+    private static final int FLAG_REINFLATE_PUBLIC_VIEW = 1<<3;
+    private static final int FLAG_REINFLATE_AMBIENT_VIEW = 1<<4;
+    private static final InflationExecutor EXECUTOR = new InflationExecutor();
+
+    private final ExpandableNotificationRow mRow;
+    private boolean mIsLowPriority;
+    private boolean mUsesIncreasedHeight;
+    private boolean mUsesIncreasedHeadsUpHeight;
+    private RemoteViews.OnClickHandler mRemoteViewClickHandler;
+    private boolean mIsChildInGroup;
+    private InflationCallback mCallback;
+    private boolean mRedactAmbient;
+    private List<Notification.Action> mSmartActions;
+
+    public NotificationInflater(ExpandableNotificationRow row) {
+        mRow = row;
+    }
+
+    public void setIsLowPriority(boolean isLowPriority) {
+        mIsLowPriority = isLowPriority;
+    }
+
+    /**
+     * Set whether the notification is a child in a group
+     *
+     * @return whether the view was re-inflated
+     */
+    public void setIsChildInGroup(boolean childInGroup) {
+        if (childInGroup != mIsChildInGroup) {
+            mIsChildInGroup = childInGroup;
+            if (mIsLowPriority) {
+                int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW;
+                inflateNotificationViews(flags);
+            }
+        } ;
+    }
+
+    public void setUsesIncreasedHeight(boolean usesIncreasedHeight) {
+        mUsesIncreasedHeight = usesIncreasedHeight;
+    }
+
+    public void setSmartActions(List<Notification.Action> smartActions) {
+        mSmartActions = smartActions;
+    }
+
+    public void setUsesIncreasedHeadsUpHeight(boolean usesIncreasedHeight) {
+        mUsesIncreasedHeadsUpHeight = usesIncreasedHeight;
+    }
+
+    public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
+        mRemoteViewClickHandler = remoteViewClickHandler;
+    }
+
+    public void setRedactAmbient(boolean redactAmbient) {
+        if (mRedactAmbient != redactAmbient) {
+            mRedactAmbient = redactAmbient;
+            if (mRow.getEntry() == null) {
+                return;
+            }
+            inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW);
+        }
+    }
+
+    /**
+     * Inflate all views of this notification on a background thread. This is asynchronous and will
+     * notify the callback once it's finished.
+     */
+    public void inflateNotificationViews() {
+        inflateNotificationViews(FLAG_REINFLATE_ALL);
+    }
+
+    /**
+     * Reinflate all views for the specified flags on a background thread. This is asynchronous and
+     * will notify the callback once it's finished.
+     *
+     * @param reInflateFlags flags which views should be reinflated. Use {@link #FLAG_REINFLATE_ALL}
+     *                       to reinflate all of views.
+     */
+    @VisibleForTesting
+    void inflateNotificationViews(int reInflateFlags) {
+        if (mRow.isRemoved()) {
+            // We don't want to reinflate anything for removed notifications. Otherwise views might
+            // be readded to the stack, leading to leaks. This may happen with low-priority groups
+            // where the removal of already removed children can lead to a reinflation.
+            return;
+        }
+        StatusBarNotification sbn = mRow.getEntry().notification;
+        AsyncInflationTask task = new AsyncInflationTask(sbn, reInflateFlags, mRow,
+                mIsLowPriority,
+                mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
+                mCallback, mRemoteViewClickHandler, mSmartActions);
+        if (mCallback != null && mCallback.doInflateSynchronous()) {
+            task.onPostExecute(task.doInBackground());
+        } else {
+            task.execute();
+        }
+    }
+
+    @VisibleForTesting
+    InflationProgress inflateNotificationViews(int reInflateFlags,
+            Notification.Builder builder, Context packageContext) {
+        InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority,
+                mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight,
+                mRedactAmbient, packageContext);
+        apply(result, reInflateFlags, mRow, mRedactAmbient, mRemoteViewClickHandler, null);
+        return result;
+    }
+
+    private static InflationProgress createRemoteViews(int reInflateFlags,
+            Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup,
+            boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
+            Context packageContext) {
+        InflationProgress result = new InflationProgress();
+        isLowPriority = isLowPriority && !isChildInGroup;
+        if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
+            result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight);
+        }
+
+        if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
+            result.newExpandedView = createExpandedView(builder, isLowPriority);
+        }
+
+        if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
+            result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight);
+        }
+
+        if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
+            result.newPublicView = builder.makePublicContentView();
+        }
+
+        if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
+            result.newAmbientView = redactAmbient ? builder.makePublicAmbientNotification()
+                    : builder.makeAmbientNotification();
+        }
+        result.packageContext = packageContext;
+        result.headsUpStatusBarText = builder.getHeadsUpStatusBarText(false /* showingPublic */);
+        result.headsUpStatusBarTextPublic = builder.getHeadsUpStatusBarText(
+                true /* showingPublic */);
+        return result;
+    }
+
+    public static CancellationSignal apply(InflationProgress result, int reInflateFlags,
+            ExpandableNotificationRow row, boolean redactAmbient,
+            RemoteViews.OnClickHandler remoteViewClickHandler,
+            @Nullable InflationCallback callback) {
+        NotificationData.Entry entry = row.getEntry();
+        NotificationContentView privateLayout = row.getPrivateLayout();
+        NotificationContentView publicLayout = row.getPublicLayout();
+        final HashMap<Integer, CancellationSignal> runningInflations = new HashMap<>();
+
+        int flag = FLAG_REINFLATE_CONTENT_VIEW;
+        if ((reInflateFlags & flag) != 0) {
+            boolean isNewView = !canReapplyRemoteView(result.newContentView, entry.cachedContentView);
+            ApplyCallback applyCallback = new ApplyCallback() {
+                @Override
+                public void setResultView(View v) {
+                    result.inflatedContentView = v;
+                }
+
+                @Override
+                public RemoteViews getRemoteView() {
+                    return result.newContentView;
+                }
+            };
+            applyRemoteView(result, reInflateFlags, flag, row, redactAmbient,
+                    isNewView, remoteViewClickHandler, callback, entry, privateLayout,
+                    privateLayout.getContractedChild(), privateLayout.getVisibleWrapper(
+                            NotificationContentView.VISIBLE_TYPE_CONTRACTED),
+                    runningInflations, applyCallback);
+        }
+
+        flag = FLAG_REINFLATE_EXPANDED_VIEW;
+        if ((reInflateFlags & flag) != 0) {
+            if (result.newExpandedView != null) {
+                boolean isNewView = !canReapplyRemoteView(result.newExpandedView,
+                        entry.cachedBigContentView);
+                ApplyCallback applyCallback = new ApplyCallback() {
+                    @Override
+                    public void setResultView(View v) {
+                        result.inflatedExpandedView = v;
+                    }
+
+                    @Override
+                    public RemoteViews getRemoteView() {
+                        return result.newExpandedView;
+                    }
+                };
+                applyRemoteView(result, reInflateFlags, flag, row,
+                        redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
+                        privateLayout, privateLayout.getExpandedChild(),
+                        privateLayout.getVisibleWrapper(
+                                NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations,
+                        applyCallback);
+            }
+        }
+
+        flag = FLAG_REINFLATE_HEADS_UP_VIEW;
+        if ((reInflateFlags & flag) != 0) {
+            if (result.newHeadsUpView != null) {
+                boolean isNewView = !canReapplyRemoteView(result.newHeadsUpView,
+                        entry.cachedHeadsUpContentView);
+                ApplyCallback applyCallback = new ApplyCallback() {
+                    @Override
+                    public void setResultView(View v) {
+                        result.inflatedHeadsUpView = v;
+                    }
+
+                    @Override
+                    public RemoteViews getRemoteView() {
+                        return result.newHeadsUpView;
+                    }
+                };
+                applyRemoteView(result, reInflateFlags, flag, row,
+                        redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
+                        privateLayout, privateLayout.getHeadsUpChild(),
+                        privateLayout.getVisibleWrapper(
+                                NotificationContentView.VISIBLE_TYPE_HEADSUP), runningInflations,
+                        applyCallback);
+            }
+        }
+
+        flag = FLAG_REINFLATE_PUBLIC_VIEW;
+        if ((reInflateFlags & flag) != 0) {
+            boolean isNewView = !canReapplyRemoteView(result.newPublicView,
+                    entry.cachedPublicContentView);
+            ApplyCallback applyCallback = new ApplyCallback() {
+                @Override
+                public void setResultView(View v) {
+                    result.inflatedPublicView = v;
+                }
+
+                @Override
+                public RemoteViews getRemoteView() {
+                    return result.newPublicView;
+                }
+            };
+            applyRemoteView(result, reInflateFlags, flag, row,
+                    redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
+                    publicLayout, publicLayout.getContractedChild(),
+                    publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED),
+                    runningInflations, applyCallback);
+        }
+
+        flag = FLAG_REINFLATE_AMBIENT_VIEW;
+        if ((reInflateFlags & flag) != 0) {
+            NotificationContentView newParent = redactAmbient ? publicLayout : privateLayout;
+            boolean isNewView = !canReapplyAmbient(row, redactAmbient) ||
+                    !canReapplyRemoteView(result.newAmbientView, entry.cachedAmbientContentView);
+            ApplyCallback applyCallback = new ApplyCallback() {
+                @Override
+                public void setResultView(View v) {
+                    result.inflatedAmbientView = v;
+                }
+
+                @Override
+                public RemoteViews getRemoteView() {
+                    return result.newAmbientView;
+                }
+            };
+            applyRemoteView(result, reInflateFlags, flag, row,
+                    redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
+                    newParent, newParent.getAmbientChild(), newParent.getVisibleWrapper(
+                            NotificationContentView.VISIBLE_TYPE_AMBIENT), runningInflations,
+                    applyCallback);
+        }
+
+        // Let's try to finish, maybe nobody is even inflating anything
+        finishIfDone(result, reInflateFlags, runningInflations, callback, row,
+                redactAmbient);
+        CancellationSignal cancellationSignal = new CancellationSignal();
+        cancellationSignal.setOnCancelListener(
+                () -> runningInflations.values().forEach(CancellationSignal::cancel));
+        return cancellationSignal;
+    }
+
+    @VisibleForTesting
+    static void applyRemoteView(final InflationProgress result,
+            final int reInflateFlags, int inflationId,
+            final ExpandableNotificationRow row,
+            final boolean redactAmbient, boolean isNewView,
+            RemoteViews.OnClickHandler remoteViewClickHandler,
+            @Nullable final InflationCallback callback, NotificationData.Entry entry,
+            NotificationContentView parentLayout, View existingView,
+            NotificationViewWrapper existingWrapper,
+            final HashMap<Integer, CancellationSignal> runningInflations,
+            ApplyCallback applyCallback) {
+        RemoteViews newContentView = applyCallback.getRemoteView();
+        if (callback != null && callback.doInflateSynchronous()) {
+            try {
+                if (isNewView) {
+                    View v = newContentView.apply(
+                            result.packageContext,
+                            parentLayout,
+                            remoteViewClickHandler);
+                    v.setIsRootNamespace(true);
+                    applyCallback.setResultView(v);
+                } else {
+                    newContentView.reapply(
+                            result.packageContext,
+                            existingView,
+                            remoteViewClickHandler);
+                    existingWrapper.onReinflated();
+                }
+            } catch (Exception e) {
+                handleInflationError(runningInflations, e, entry.notification, callback);
+                // Add a running inflation to make sure we don't trigger callbacks.
+                // Safe to do because only happens in tests.
+                runningInflations.put(inflationId, new CancellationSignal());
+            }
+            return;
+        }
+        RemoteViews.OnViewAppliedListener listener
+                = new RemoteViews.OnViewAppliedListener() {
+
+            @Override
+            public void onViewApplied(View v) {
+                if (isNewView) {
+                    v.setIsRootNamespace(true);
+                    applyCallback.setResultView(v);
+                } else if (existingWrapper != null) {
+                    existingWrapper.onReinflated();
+                }
+                runningInflations.remove(inflationId);
+                finishIfDone(result, reInflateFlags, runningInflations, callback, row,
+                        redactAmbient);
+            }
+
+            @Override
+            public void onError(Exception e) {
+                // Uh oh the async inflation failed. Due to some bugs (see b/38190555), this could
+                // actually also be a system issue, so let's try on the UI thread again to be safe.
+                try {
+                    View newView = existingView;
+                    if (isNewView) {
+                        newView = newContentView.apply(
+                                result.packageContext,
+                                parentLayout,
+                                remoteViewClickHandler);
+                    } else {
+                        newContentView.reapply(
+                                result.packageContext,
+                                existingView,
+                                remoteViewClickHandler);
+                    }
+                    Log.wtf(TAG, "Async Inflation failed but normal inflation finished normally.",
+                            e);
+                    onViewApplied(newView);
+                } catch (Exception anotherException) {
+                    runningInflations.remove(inflationId);
+                    handleInflationError(runningInflations, e, entry.notification, callback);
+                }
+            }
+        };
+        CancellationSignal cancellationSignal;
+        if (isNewView) {
+            cancellationSignal = newContentView.applyAsync(
+                    result.packageContext,
+                    parentLayout,
+                    EXECUTOR,
+                    listener,
+                    remoteViewClickHandler);
+        } else {
+            cancellationSignal = newContentView.reapplyAsync(
+                    result.packageContext,
+                    existingView,
+                    EXECUTOR,
+                    listener,
+                    remoteViewClickHandler);
+        }
+        runningInflations.put(inflationId, cancellationSignal);
+    }
+
+    private static void handleInflationError(HashMap<Integer, CancellationSignal> runningInflations,
+            Exception e, StatusBarNotification notification, @Nullable InflationCallback callback) {
+        Assert.isMainThread();
+        runningInflations.values().forEach(CancellationSignal::cancel);
+        if (callback != null) {
+            callback.handleInflationException(notification, e);
+        }
+    }
+
+    /**
+     * Finish the inflation of the views
+     *
+     * @return true if the inflation was finished
+     */
+    private static boolean finishIfDone(InflationProgress result, int reInflateFlags,
+            HashMap<Integer, CancellationSignal> runningInflations,
+            @Nullable InflationCallback endListener, ExpandableNotificationRow row,
+            boolean redactAmbient) {
+        Assert.isMainThread();
+        NotificationData.Entry entry = row.getEntry();
+        NotificationContentView privateLayout = row.getPrivateLayout();
+        NotificationContentView publicLayout = row.getPublicLayout();
+        if (runningInflations.isEmpty()) {
+            if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
+                if (result.inflatedContentView != null) {
+                    privateLayout.setContractedChild(result.inflatedContentView);
+                }
+                entry.cachedContentView = result.newContentView;
+            }
+
+            if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
+                if (result.inflatedExpandedView != null) {
+                    privateLayout.setExpandedChild(result.inflatedExpandedView);
+                } else if (result.newExpandedView == null) {
+                    privateLayout.setExpandedChild(null);
+                }
+                entry.cachedBigContentView = result.newExpandedView;
+                row.setExpandable(result.newExpandedView != null);
+            }
+
+            if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
+                if (result.inflatedHeadsUpView != null) {
+                    privateLayout.setHeadsUpChild(result.inflatedHeadsUpView);
+                } else if (result.newHeadsUpView == null) {
+                    privateLayout.setHeadsUpChild(null);
+                }
+                entry.cachedHeadsUpContentView = result.newHeadsUpView;
+            }
+
+            if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
+                if (result.inflatedPublicView != null) {
+                    publicLayout.setContractedChild(result.inflatedPublicView);
+                }
+                entry.cachedPublicContentView = result.newPublicView;
+            }
+
+            if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
+                if (result.inflatedAmbientView != null) {
+                    NotificationContentView newParent = redactAmbient
+                            ? publicLayout : privateLayout;
+                    NotificationContentView otherParent = !redactAmbient
+                            ? publicLayout : privateLayout;
+                    newParent.setAmbientChild(result.inflatedAmbientView);
+                    otherParent.setAmbientChild(null);
+                }
+                entry.cachedAmbientContentView = result.newAmbientView;
+            }
+            entry.headsUpStatusBarText = result.headsUpStatusBarText;
+            entry.headsUpStatusBarTextPublic = result.headsUpStatusBarTextPublic;
+            if (endListener != null) {
+                endListener.onAsyncInflationFinished(row.getEntry());
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private static RemoteViews createExpandedView(Notification.Builder builder,
+            boolean isLowPriority) {
+        RemoteViews bigContentView = builder.createBigContentView();
+        if (bigContentView != null) {
+            return bigContentView;
+        }
+        if (isLowPriority) {
+            RemoteViews contentView = builder.createContentView();
+            Notification.Builder.makeHeaderExpanded(contentView);
+            return contentView;
+        }
+        return null;
+    }
+
+    private static RemoteViews createContentView(Notification.Builder builder,
+            boolean isLowPriority, boolean useLarge) {
+        if (isLowPriority) {
+            return builder.makeLowPriorityContentView(false /* useRegularSubtext */);
+        }
+        return builder.createContentView(useLarge);
+    }
+
+    /**
+     * @param newView The new view that will be applied
+     * @param oldView The old view that was applied to the existing view before
+     * @return {@code true} if the RemoteViews are the same and the view can be reused to reapply.
+     */
+     @VisibleForTesting
+     static boolean canReapplyRemoteView(final RemoteViews newView,
+            final RemoteViews oldView) {
+        return (newView == null && oldView == null) ||
+                (newView != null && oldView != null
+                        && oldView.getPackage() != null
+                        && newView.getPackage() != null
+                        && newView.getPackage().equals(oldView.getPackage())
+                        && newView.getLayoutId() == oldView.getLayoutId()
+                        && !oldView.isReapplyDisallowed());
+    }
+
+    public void setInflationCallback(InflationCallback callback) {
+        mCallback = callback;
+    }
+
+    public interface InflationCallback {
+        void handleInflationException(StatusBarNotification notification, Exception e);
+        void onAsyncInflationFinished(NotificationData.Entry entry);
+
+        /**
+         * Used to disable async-ness for tests. Should only be used for tests.
+         */
+        default boolean doInflateSynchronous() {
+            return false;
+        }
+    }
+
+    public void clearCachesAndReInflate() {
+        NotificationData.Entry entry = mRow.getEntry();
+        entry.cachedAmbientContentView = null;
+        entry.cachedBigContentView = null;
+        entry.cachedContentView = null;
+        entry.cachedHeadsUpContentView = null;
+        entry.cachedPublicContentView = null;
+        inflateNotificationViews();
+    }
+
+    private static boolean canReapplyAmbient(ExpandableNotificationRow row, boolean redactAmbient) {
+        NotificationContentView ambientView = redactAmbient ? row.getPublicLayout()
+                : row.getPrivateLayout();            ;
+        return ambientView.getAmbientChild() != null;
+    }
+
+    public static class AsyncInflationTask extends AsyncTask<Void, Void, InflationProgress>
+            implements InflationCallback, InflationTask {
+
+        private final StatusBarNotification mSbn;
+        private final Context mContext;
+        private final boolean mIsLowPriority;
+        private final boolean mIsChildInGroup;
+        private final boolean mUsesIncreasedHeight;
+        private final InflationCallback mCallback;
+        private final boolean mUsesIncreasedHeadsUpHeight;
+        private final boolean mRedactAmbient;
+        private int mReInflateFlags;
+        private ExpandableNotificationRow mRow;
+        private Exception mError;
+        private RemoteViews.OnClickHandler mRemoteViewClickHandler;
+        private CancellationSignal mCancellationSignal;
+        private List<Notification.Action> mSmartActions;
+
+        private AsyncInflationTask(StatusBarNotification notification,
+                int reInflateFlags, ExpandableNotificationRow row, boolean isLowPriority,
+                boolean isChildInGroup, boolean usesIncreasedHeight,
+                boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
+                InflationCallback callback,
+                RemoteViews.OnClickHandler remoteViewClickHandler,
+                List<Notification.Action> smartActions) {
+            mRow = row;
+            mSbn = notification;
+            mReInflateFlags = reInflateFlags;
+            mContext = mRow.getContext();
+            mIsLowPriority = isLowPriority;
+            mIsChildInGroup = isChildInGroup;
+            mUsesIncreasedHeight = usesIncreasedHeight;
+            mUsesIncreasedHeadsUpHeight = usesIncreasedHeadsUpHeight;
+            mRedactAmbient = redactAmbient;
+            mRemoteViewClickHandler = remoteViewClickHandler;
+            mCallback = callback;
+            mSmartActions = smartActions == null
+                    ? Collections.emptyList()
+                    : new ArrayList<>(smartActions);
+            NotificationData.Entry entry = row.getEntry();
+            entry.setInflationTask(this);
+        }
+
+        @VisibleForTesting
+        public int getReInflateFlags() {
+            return mReInflateFlags;
+        }
+
+        @Override
+        protected InflationProgress doInBackground(Void... params) {
+            try {
+                final Notification.Builder recoveredBuilder
+                        = Notification.Builder.recoverBuilder(mContext,
+                        mSbn.getNotification());
+
+                applyChanges(recoveredBuilder);
+
+                Context packageContext = mSbn.getPackageContext(mContext);
+                Notification notification = mSbn.getNotification();
+                if (notification.isMediaNotification()) {
+                    MediaNotificationProcessor processor = new MediaNotificationProcessor(mContext,
+                            packageContext);
+                    processor.processNotification(notification, recoveredBuilder);
+                }
+                return createRemoteViews(mReInflateFlags,
+                        recoveredBuilder, mIsLowPriority, mIsChildInGroup,
+                        mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
+                        packageContext);
+            } catch (Exception e) {
+                mError = e;
+                return null;
+            }
+        }
+
+        @Override
+        protected void onPostExecute(InflationProgress result) {
+            if (mError == null) {
+                mCancellationSignal = apply(result, mReInflateFlags, mRow, mRedactAmbient,
+                        mRemoteViewClickHandler, this);
+            } else {
+                handleError(mError);
+            }
+        }
+
+        /**
+         * Apply changes to the given notification builder, like adding smart actions suggested by
+         * a {@link android.service.notification.NotificationAssistantService}.
+         */
+        private void applyChanges(Notification.Builder builder) {
+            if (mSmartActions != null) {
+                for (Notification.Action smartAction : mSmartActions) {
+                    builder.addAction(smartAction);
+                }
+            }
+        }
+
+        private void handleError(Exception e) {
+            mRow.getEntry().onInflationTaskFinished();
+            StatusBarNotification sbn = mRow.getStatusBarNotification();
+            final String ident = sbn.getPackageName() + "/0x"
+                    + Integer.toHexString(sbn.getId());
+            Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
+            mCallback.handleInflationException(sbn,
+                    new InflationException("Couldn't inflate contentViews" + e));
+        }
+
+        @Override
+        public void abort() {
+            cancel(true /* mayInterruptIfRunning */);
+            if (mCancellationSignal != null) {
+                mCancellationSignal.cancel();
+            }
+        }
+
+        @Override
+        public void supersedeTask(InflationTask task) {
+            if (task instanceof AsyncInflationTask) {
+                // We want to inflate all flags of the previous task as well
+                mReInflateFlags |= ((AsyncInflationTask) task).mReInflateFlags;
+            }
+        }
+
+        @Override
+        public void handleInflationException(StatusBarNotification notification, Exception e) {
+            handleError(e);
+        }
+
+        @Override
+        public void onAsyncInflationFinished(NotificationData.Entry entry) {
+            mRow.getEntry().onInflationTaskFinished();
+            mRow.onNotificationUpdated();
+            mCallback.onAsyncInflationFinished(mRow.getEntry());
+        }
+
+        @Override
+        public boolean doInflateSynchronous() {
+            return mCallback != null && mCallback.doInflateSynchronous();
+        }
+    }
+
+    @VisibleForTesting
+    static class InflationProgress {
+        private RemoteViews newContentView;
+        private RemoteViews newHeadsUpView;
+        private RemoteViews newExpandedView;
+        private RemoteViews newAmbientView;
+        private RemoteViews newPublicView;
+
+        @VisibleForTesting
+        Context packageContext;
+
+        private View inflatedContentView;
+        private View inflatedHeadsUpView;
+        private View inflatedExpandedView;
+        private View inflatedAmbientView;
+        private View inflatedPublicView;
+        private CharSequence headsUpStatusBarText;
+        private CharSequence headsUpStatusBarTextPublic;
+    }
+
+    @VisibleForTesting
+    abstract static class ApplyCallback {
+        public abstract void setResultView(View v);
+        public abstract RemoteViews getRemoteView();
+    }
+
+    /**
+     * A custom executor that allows more tasks to be queued. Default values are copied from
+     * AsyncTask
+      */
+    private static class InflationExecutor implements Executor {
+        private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
+        // We want at least 2 threads and at most 4 threads in the core pool,
+        // preferring to have 1 less than the CPU count to avoid saturating
+        // the CPU with background work
+        private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
+        private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
+        private static final int KEEP_ALIVE_SECONDS = 30;
+
+        private static final ThreadFactory sThreadFactory = new ThreadFactory() {
+            private final AtomicInteger mCount = new AtomicInteger(1);
+
+            public Thread newThread(Runnable r) {
+                return new Thread(r, "InflaterThread #" + mCount.getAndIncrement());
+            }
+        };
+
+        private final ThreadPoolExecutor mExecutor;
+
+        private InflationExecutor() {
+            mExecutor = new ThreadPoolExecutor(
+                    CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
+                    new LinkedBlockingQueue<>(), sThreadFactory);
+            mExecutor.allowCoreThreadTimeOut(true);
+        }
+
+        @Override
+        public void execute(Runnable runnable) {
+            mExecutor.execute(runnable);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
new file mode 100644
index 0000000..9e2331f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -0,0 +1,569 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.annotation.Nullable;
+import android.app.INotificationManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.logging.NotificationCounters;
+
+import java.util.List;
+
+/**
+ * The guts of a notification revealed when performing a long press. This also houses the blocking
+ * helper affordance that allows a user to keep/stop notifications after swiping one away.
+ */
+public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
+    private static final String TAG = "InfoGuts";
+
+    private INotificationManager mINotificationManager;
+    private PackageManager mPm;
+    private MetricsLogger mMetricsLogger;
+
+    private String mPackageName;
+    private String mAppName;
+    private int mAppUid;
+    private int mNumUniqueChannelsInRow;
+    private NotificationChannel mSingleNotificationChannel;
+    private int mStartingUserImportance;
+    private int mChosenImportance;
+    private boolean mIsSingleDefaultChannel;
+    private boolean mIsNonblockable;
+    private StatusBarNotification mSbn;
+    private AnimatorSet mExpandAnimation;
+    private boolean mIsForeground;
+    private boolean mIsDeviceProvisioned;
+
+    private CheckSaveListener mCheckSaveListener;
+    private OnSettingsClickListener mOnSettingsClickListener;
+    private OnAppSettingsClickListener mAppSettingsClickListener;
+    private NotificationGuts mGutsContainer;
+
+    /** Whether this view is being shown as part of the blocking helper. */
+    private boolean mIsForBlockingHelper;
+    private boolean mNegativeUserSentiment;
+
+    /**
+     * String that describes how the user exit or quit out of this view, also used as a counter tag.
+     */
+    private String mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
+
+    private OnClickListener mOnKeepShowing = v -> {
+        mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
+        closeControls(v);
+    };
+
+    private OnClickListener mOnStopOrMinimizeNotifications = v -> {
+        mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
+        swapContent(false);
+    };
+
+    private OnClickListener mOnUndo = v -> {
+        // Reset exit counter that we'll log and record an undo event separately (not an exit event)
+        mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
+        logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
+        swapContent(true);
+    };
+
+    public NotificationInfo(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    // Specify a CheckSaveListener to override when/if the user's changes are committed.
+    public interface CheckSaveListener {
+        // Invoked when importance has changed and the NotificationInfo wants to try to save it.
+        // Listener should run saveImportance unless the change should be canceled.
+        void checkSave(Runnable saveImportance, StatusBarNotification sbn);
+    }
+
+    public interface OnSettingsClickListener {
+        void onClick(View v, NotificationChannel channel, int appUid);
+    }
+
+    public interface OnAppSettingsClickListener {
+        void onClick(View v, Intent intent);
+    }
+
+    @VisibleForTesting
+    void bindNotification(
+            final PackageManager pm,
+            final INotificationManager iNotificationManager,
+            final String pkg,
+            final NotificationChannel notificationChannel,
+            final int numUniqueChannelsInRow,
+            final StatusBarNotification sbn,
+            final CheckSaveListener checkSaveListener,
+            final OnSettingsClickListener onSettingsClick,
+            final OnAppSettingsClickListener onAppSettingsClick,
+            boolean isDeviceProvisioned,
+            boolean isNonblockable)
+            throws RemoteException {
+        bindNotification(pm, iNotificationManager, pkg, notificationChannel,
+                numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
+                onAppSettingsClick, isDeviceProvisioned, isNonblockable,
+                false /* isBlockingHelper */, false /* isUserSentimentNegative */);
+    }
+
+    public void bindNotification(
+            PackageManager pm,
+            INotificationManager iNotificationManager,
+            String pkg,
+            NotificationChannel notificationChannel,
+            int numUniqueChannelsInRow,
+            StatusBarNotification sbn,
+            CheckSaveListener checkSaveListener,
+            OnSettingsClickListener onSettingsClick,
+            OnAppSettingsClickListener onAppSettingsClick,
+            boolean isDeviceProvisioned,
+            boolean isNonblockable,
+            boolean isForBlockingHelper,
+            boolean isUserSentimentNegative)
+            throws RemoteException {
+        mINotificationManager = iNotificationManager;
+        mMetricsLogger = Dependency.get(MetricsLogger.class);
+        mPackageName = pkg;
+        mNumUniqueChannelsInRow = numUniqueChannelsInRow;
+        mSbn = sbn;
+        mPm = pm;
+        mAppSettingsClickListener = onAppSettingsClick;
+        mAppName = mPackageName;
+        mCheckSaveListener = checkSaveListener;
+        mOnSettingsClickListener = onSettingsClick;
+        mSingleNotificationChannel = notificationChannel;
+        mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
+        mNegativeUserSentiment = isUserSentimentNegative;
+        mIsNonblockable = isNonblockable;
+        mIsForeground =
+                (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
+        mIsForBlockingHelper = isForBlockingHelper;
+        mAppUid = mSbn.getUid();
+        mIsDeviceProvisioned = isDeviceProvisioned;
+
+        int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
+                pkg, mAppUid, false /* includeDeleted */);
+        if (mNumUniqueChannelsInRow == 0) {
+            throw new IllegalArgumentException("bindNotification requires at least one channel");
+        } else  {
+            // Special behavior for the Default channel if no other channels have been defined.
+            mIsSingleDefaultChannel = mNumUniqueChannelsInRow == 1
+                    && mSingleNotificationChannel.getId().equals(
+                            NotificationChannel.DEFAULT_CHANNEL_ID)
+                    && numTotalChannels == 1;
+        }
+
+        bindHeader();
+        bindPrompt();
+        bindButtons();
+    }
+
+    private void bindHeader() throws RemoteException {
+        // Package name
+        Drawable pkgicon = null;
+        ApplicationInfo info;
+        try {
+            info = mPm.getApplicationInfo(
+                    mPackageName,
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES
+                            | PackageManager.MATCH_DISABLED_COMPONENTS
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+            if (info != null) {
+                mAppName = String.valueOf(mPm.getApplicationLabel(info));
+                pkgicon = mPm.getApplicationIcon(info);
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            // app is gone, just show package name and generic icon
+            pkgicon = mPm.getDefaultActivityIcon();
+        }
+        ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
+        ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
+
+        // Set group information if this channel has an associated group.
+        CharSequence groupName = null;
+        if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
+            final NotificationChannelGroup notificationChannelGroup =
+                    mINotificationManager.getNotificationChannelGroupForPackage(
+                            mSingleNotificationChannel.getGroup(), mPackageName, mAppUid);
+            if (notificationChannelGroup != null) {
+                groupName = notificationChannelGroup.getName();
+            }
+        }
+        TextView groupNameView = findViewById(R.id.group_name);
+        TextView groupDividerView = findViewById(R.id.pkg_group_divider);
+        if (groupName != null) {
+            groupNameView.setText(groupName);
+            groupNameView.setVisibility(View.VISIBLE);
+            groupDividerView.setVisibility(View.VISIBLE);
+        } else {
+            groupNameView.setVisibility(View.GONE);
+            groupDividerView.setVisibility(View.GONE);
+        }
+
+        // Settings button.
+        final View settingsButton = findViewById(R.id.info);
+        if (mAppUid >= 0 && mOnSettingsClickListener != null && mIsDeviceProvisioned) {
+            settingsButton.setVisibility(View.VISIBLE);
+            final int appUidF = mAppUid;
+            settingsButton.setOnClickListener(
+                    (View view) -> {
+                        logBlockingHelperCounter(
+                                NotificationCounters.BLOCKING_HELPER_NOTIF_SETTINGS);
+                        mOnSettingsClickListener.onClick(view,
+                                mNumUniqueChannelsInRow > 1 ? null : mSingleNotificationChannel,
+                                appUidF);
+                    });
+        } else {
+            settingsButton.setVisibility(View.GONE);
+        }
+    }
+
+    private void bindPrompt() {
+        final TextView blockPrompt = findViewById(R.id.block_prompt);
+        bindName();
+        if (mIsNonblockable) {
+            blockPrompt.setText(R.string.notification_unblockable_desc);
+        } else {
+            if (mNegativeUserSentiment) {
+                blockPrompt.setText(R.string.inline_blocking_helper);
+            }  else if (mIsSingleDefaultChannel || mNumUniqueChannelsInRow > 1) {
+                blockPrompt.setText(R.string.inline_keep_showing_app);
+            } else {
+                blockPrompt.setText(R.string.inline_keep_showing);
+            }
+        }
+    }
+
+    private void bindName() {
+        final TextView channelName = findViewById(R.id.channel_name);
+        if (mIsSingleDefaultChannel || mNumUniqueChannelsInRow > 1) {
+            channelName.setVisibility(View.GONE);
+        } else {
+            channelName.setText(mSingleNotificationChannel.getName());
+        }
+    }
+
+    @VisibleForTesting
+    void logBlockingHelperCounter(String counterTag) {
+        if (mIsForBlockingHelper) {
+            mMetricsLogger.count(counterTag, 1);
+        }
+    }
+
+    private boolean hasImportanceChanged() {
+        return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
+    }
+
+    private void saveImportance() {
+        if (!mIsNonblockable) {
+            // Only go through the lock screen/bouncer if the user hit 'Stop notifications'.
+            // Otherwise, update the importance immediately.
+            if (mCheckSaveListener != null
+                    && NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS.equals(
+                            mExitReason)) {
+                mCheckSaveListener.checkSave(this::updateImportance, mSbn);
+            } else {
+                updateImportance();
+            }
+        }
+    }
+
+    /**
+     * Commits the updated importance values on the background thread.
+     */
+    private void updateImportance() {
+        MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
+                mChosenImportance - mStartingUserImportance);
+
+        Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
+        bgHandler.post(new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
+                mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null,
+                mStartingUserImportance, mChosenImportance));
+    }
+
+    private void bindButtons() {
+        // Set up stay-in-notification actions
+        View block =  findViewById(R.id.block);
+        TextView keep = findViewById(R.id.keep);
+        View minimize = findViewById(R.id.minimize);
+
+        findViewById(R.id.undo).setOnClickListener(mOnUndo);
+        block.setOnClickListener(mOnStopOrMinimizeNotifications);
+        keep.setOnClickListener(mOnKeepShowing);
+        minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
+
+        if (mIsNonblockable) {
+            keep.setText(android.R.string.ok);
+            block.setVisibility(GONE);
+            minimize.setVisibility(GONE);
+        } else if (mIsForeground) {
+            block.setVisibility(GONE);
+            minimize.setVisibility(VISIBLE);
+        } else if (!mIsForeground) {
+            block.setVisibility(VISIBLE);
+            minimize.setVisibility(GONE);
+        }
+
+        // Set up app settings link (i.e. Customize)
+        TextView settingsLinkView = findViewById(R.id.app_settings);
+        Intent settingsIntent = getAppSettingsIntent(mPm, mPackageName, mSingleNotificationChannel,
+                mSbn.getId(), mSbn.getTag());
+        if (!mIsForBlockingHelper
+                && settingsIntent != null
+                && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
+            settingsLinkView.setVisibility(VISIBLE);
+            settingsLinkView.setText(mContext.getString(R.string.notification_app_settings));
+            settingsLinkView.setOnClickListener((View view) -> {
+                mAppSettingsClickListener.onClick(view, settingsIntent);
+            });
+        } else {
+            settingsLinkView.setVisibility(View.GONE);
+        }
+    }
+
+    private void swapContent(boolean showPrompt) {
+        if (mExpandAnimation != null) {
+            mExpandAnimation.cancel();
+        }
+
+        View prompt = findViewById(R.id.prompt);
+        ViewGroup confirmation = findViewById(R.id.confirmation);
+        TextView confirmationText = findViewById(R.id.confirmation_text);
+        View header = findViewById(R.id.header);
+
+        if (showPrompt) {
+            mChosenImportance = mStartingUserImportance;
+        } else if (mIsForeground) {
+            mChosenImportance = IMPORTANCE_MIN;
+            confirmationText.setText(R.string.notification_channel_minimized);
+        } else {
+            mChosenImportance = IMPORTANCE_NONE;
+            confirmationText.setText(R.string.notification_channel_disabled);
+        }
+
+        ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
+                prompt.getAlpha(), showPrompt ? 1f : 0f);
+        promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+        ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
+                confirmation.getAlpha(), showPrompt ? 0f : 1f);
+        confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
+
+        prompt.setVisibility(showPrompt ? VISIBLE : GONE);
+        confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
+        header.setVisibility(showPrompt ? VISIBLE : GONE);
+
+        mExpandAnimation = new AnimatorSet();
+        mExpandAnimation.playTogether(promptAnim, confirmAnim);
+        mExpandAnimation.setDuration(150);
+        mExpandAnimation.addListener(new AnimatorListenerAdapter() {
+            boolean cancelled = false;
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                cancelled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (!cancelled) {
+                    prompt.setVisibility(showPrompt ? VISIBLE : GONE);
+                    confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
+                }
+            }
+        });
+        mExpandAnimation.start();
+
+        // Since we're swapping/update the content, reset the timeout so the UI can't close
+        // immediately after the update.
+        if (mGutsContainer != null) {
+            mGutsContainer.resetFalsingCheck();
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        if (mGutsContainer != null &&
+                event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+            if (mGutsContainer.isExposed()) {
+                event.getText().add(mContext.getString(
+                        R.string.notification_channel_controls_opened_accessibility, mAppName));
+            } else {
+                event.getText().add(mContext.getString(
+                        R.string.notification_channel_controls_closed_accessibility, mAppName));
+            }
+        }
+    }
+
+    private Intent getAppSettingsIntent(PackageManager pm, String packageName,
+            NotificationChannel channel, int id, String tag) {
+        Intent intent = new Intent(Intent.ACTION_MAIN)
+                .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
+                .setPackage(packageName);
+        final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
+                intent,
+                PackageManager.MATCH_DEFAULT_ONLY
+        );
+        if (resolveInfos == null || resolveInfos.size() == 0 || resolveInfos.get(0) == null) {
+            return null;
+        }
+        final ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
+        intent.setClassName(activityInfo.packageName, activityInfo.name);
+        if (channel != null) {
+            intent.putExtra(Notification.EXTRA_CHANNEL_ID, channel.getId());
+        }
+        intent.putExtra(Notification.EXTRA_NOTIFICATION_ID, id);
+        intent.putExtra(Notification.EXTRA_NOTIFICATION_TAG, tag);
+        return intent;
+    }
+
+    /**
+     * Closes the controls and commits the updated importance values (indirectly). If this view is
+     * being used to show the blocking helper, this will immediately dismiss the blocking helper and
+     * commit the updated importance.
+     *
+     * <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
+     * user does not have the ability to undo the action anymore. See {@link #swapContent(boolean)}
+     * for where undo is handled.
+     */
+    @VisibleForTesting
+    void closeControls(View v) {
+        int[] parentLoc = new int[2];
+        int[] targetLoc = new int[2];
+        mGutsContainer.getLocationOnScreen(parentLoc);
+        v.getLocationOnScreen(targetLoc);
+        final int centerX = v.getWidth() / 2;
+        final int centerY = v.getHeight() / 2;
+        final int x = targetLoc[0] - parentLoc[0] + centerX;
+        final int y = targetLoc[1] - parentLoc[1] + centerY;
+        mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
+    }
+
+    @Override
+    public void setGutsParent(NotificationGuts guts) {
+        mGutsContainer = guts;
+    }
+
+    @Override
+    public boolean willBeRemoved() {
+        return hasImportanceChanged();
+    }
+
+    @Override
+    public boolean shouldBeSaved() {
+        return hasImportanceChanged();
+    }
+
+    @Override
+    public View getContentView() {
+        return this;
+    }
+
+    @Override
+    public boolean handleCloseControls(boolean save, boolean force) {
+        // Save regardless of the importance so we can lock the importance field if the user wants
+        // to keep getting notifications
+        if (save) {
+            saveImportance();
+        }
+        logBlockingHelperCounter(mExitReason);
+        return false;
+    }
+
+    @Override
+    public int getActualHeight() {
+        return getHeight();
+    }
+
+    /**
+     * Runnable to either update the given channel (with a new importance value) or, if no channel
+     * is provided, update notifications enabled state for the package.
+     */
+    private static class UpdateImportanceRunnable implements Runnable {
+        private final INotificationManager mINotificationManager;
+        private final String mPackageName;
+        private final int mAppUid;
+        private final @Nullable NotificationChannel mChannelToUpdate;
+        private final int mCurrentImportance;
+        private final int mNewImportance;
+
+
+        public UpdateImportanceRunnable(INotificationManager notificationManager,
+                String packageName, int appUid, @Nullable NotificationChannel channelToUpdate,
+                int currentImportance, int newImportance) {
+            mINotificationManager = notificationManager;
+            mPackageName = packageName;
+            mAppUid = appUid;
+            mChannelToUpdate = channelToUpdate;
+            mCurrentImportance = currentImportance;
+            mNewImportance = newImportance;
+        }
+
+        @Override
+        public void run() {
+            try {
+                if (mChannelToUpdate != null) {
+                    mChannelToUpdate.setImportance(mNewImportance);
+                    mChannelToUpdate.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+                    mINotificationManager.updateNotificationChannelForPackage(
+                            mPackageName, mAppUid, mChannelToUpdate);
+                } else {
+                    // For notifications with more than one channel, update notification enabled
+                    // state. If the importance was lowered, we disable notifications.
+                    mINotificationManager.setNotificationsEnabledWithImportanceLockForPackage(
+                            mPackageName, mAppUid, mNewImportance >= mCurrentImportance);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Unable to update notification importance", e);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
new file mode 100644
index 0000000..dec88d4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -0,0 +1,697 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
+
+import java.util.ArrayList;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.AlphaOptimizedImageView;
+import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.service.notification.StatusBarNotification;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.FrameLayout.LayoutParams;
+
+public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnClickListener,
+        ExpandableNotificationRow.LayoutListener {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "swipe";
+
+    private static final int ICON_ALPHA_ANIM_DURATION = 200;
+    private static final long SHOW_MENU_DELAY = 60;
+    private static final long SWIPE_MENU_TIMING = 200;
+
+    // Notification must be swiped at least this fraction of a single menu item to show menu
+    private static final float SWIPED_FAR_ENOUGH_MENU_FRACTION = 0.25f;
+    private static final float SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION = 0.15f;
+
+    // When the menu is displayed, the notification must be swiped within this fraction of a single
+    // menu item to snap back to menu (else it will cover the menu or it'll be dismissed)
+    private static final float SWIPED_BACK_ENOUGH_TO_COVER_FRACTION = 0.2f;
+
+    private ExpandableNotificationRow mParent;
+
+    private Context mContext;
+    private FrameLayout mMenuContainer;
+    private MenuItem mInfoItem;
+    private MenuItem mAppOpsItem;
+    private MenuItem mSnoozeItem;
+    private ArrayList<MenuItem> mMenuItems;
+    private OnMenuEventListener mMenuListener;
+
+    private ValueAnimator mFadeAnimator;
+    private boolean mAnimating;
+    private boolean mMenuFadedIn;
+
+    private boolean mOnLeft;
+    private boolean mIconsPlaced;
+
+    private boolean mDismissing;
+    private boolean mSnapping;
+    private float mTranslation;
+
+    private int[] mIconLocation = new int[2];
+    private int[] mParentLocation = new int[2];
+
+    private float mHorizSpaceForIcon = -1;
+    private int mVertSpaceForIcons = -1;
+    private int mIconPadding = -1;
+    private int mSidePadding;
+
+    private float mAlpha = 0f;
+    private float mPrevX;
+
+    private CheckForDrag mCheckForDrag;
+    private Handler mHandler;
+
+    private boolean mMenuSnappedTo;
+    private boolean mMenuSnappedOnLeft;
+    private boolean mShouldShowMenu;
+
+    private NotificationSwipeActionHelper mSwipeHelper;
+    private boolean mIsUserTouching;
+
+    public NotificationMenuRow(Context context) {
+        mContext = context;
+        mShouldShowMenu = context.getResources().getBoolean(R.bool.config_showNotificationGear);
+        mHandler = new Handler(Looper.getMainLooper());
+        mMenuItems = new ArrayList<>();
+    }
+
+    @Override
+    public ArrayList<MenuItem> getMenuItems(Context context) {
+        return mMenuItems;
+    }
+
+    @Override
+    public MenuItem getLongpressMenuItem(Context context) {
+        return mInfoItem;
+    }
+
+    @Override
+    public MenuItem getAppOpsMenuItem(Context context) {
+        return mAppOpsItem;
+    }
+
+    @Override
+    public MenuItem getSnoozeMenuItem(Context context) {
+        return mSnoozeItem;
+    }
+
+    @Override
+    public void setSwipeActionHelper(NotificationSwipeActionHelper helper) {
+        mSwipeHelper = helper;
+    }
+
+    @Override
+    public void setMenuClickListener(OnMenuEventListener listener) {
+        mMenuListener = listener;
+    }
+
+    @Override
+    public void createMenu(ViewGroup parent, StatusBarNotification sbn) {
+        mParent = (ExpandableNotificationRow) parent;
+        createMenuViews(true /* resetState */);
+    }
+
+    @Override
+    public boolean isMenuVisible() {
+        return mAlpha > 0;
+    }
+
+    @Override
+    public View getMenuView() {
+        return mMenuContainer;
+    }
+
+    @Override
+    public void resetMenu() {
+        resetState(true);
+    }
+
+    @Override
+    public void onNotificationUpdated(StatusBarNotification sbn) {
+        if (mMenuContainer == null) {
+            // Menu hasn't been created yet, no need to do anything.
+            return;
+        }
+        createMenuViews(!isMenuVisible() /* resetState */);
+    }
+
+    @Override
+    public void onConfigurationChanged() {
+        mParent.setLayoutListener(this);
+    }
+
+    @Override
+    public void onLayout() {
+        mIconsPlaced = false; // Force icons to be re-placed
+        setMenuLocation();
+        mParent.removeListener();
+    }
+
+    private void createMenuViews(boolean resetState) {
+        final Resources res = mContext.getResources();
+        mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
+        mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
+        mMenuItems.clear();
+        // Construct the menu items based on the notification
+        if (mParent != null && mParent.getStatusBarNotification() != null) {
+            int flags = mParent.getStatusBarNotification().getNotification().flags;
+            boolean isForeground = (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
+            if (!isForeground) {
+                // Only show snooze for non-foreground notifications
+                mSnoozeItem = createSnoozeItem(mContext);
+                mMenuItems.add(mSnoozeItem);
+            }
+        }
+        mInfoItem = createInfoItem(mContext);
+        mMenuItems.add(mInfoItem);
+
+        mAppOpsItem = createAppOpsItem(mContext);
+        mMenuItems.add(mAppOpsItem);
+
+        // Construct the menu views
+        if (mMenuContainer != null) {
+            mMenuContainer.removeAllViews();
+        } else {
+            mMenuContainer = new FrameLayout(mContext);
+        }
+        for (int i = 0; i < mMenuItems.size(); i++) {
+            addMenuView(mMenuItems.get(i), mMenuContainer);
+        }
+        if (resetState) {
+            resetState(false /* notify */);
+        } else {
+            mIconsPlaced = false;
+            setMenuLocation();
+            if (!mIsUserTouching) {
+                // If the # of items showing changed we need to update the snap position
+                showMenu(mParent, mOnLeft ? getSpaceForMenu() : -getSpaceForMenu(),
+                        0 /* velocity */);
+            }
+        }
+    }
+
+    private void resetState(boolean notify) {
+        setMenuAlpha(0f);
+        mIconsPlaced = false;
+        mMenuFadedIn = false;
+        mAnimating = false;
+        mSnapping = false;
+        mDismissing = false;
+        mMenuSnappedTo = false;
+        setMenuLocation();
+        if (mMenuListener != null && notify) {
+            mMenuListener.onMenuReset(mParent);
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(View view, MotionEvent ev, float velocity) {
+        final int action = ev.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                mSnapping = false;
+                if (mFadeAnimator != null) {
+                    mFadeAnimator.cancel();
+                }
+                mHandler.removeCallbacks(mCheckForDrag);
+                mCheckForDrag = null;
+                mPrevX = ev.getRawX();
+                mIsUserTouching = true;
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                mSnapping = false;
+                float diffX = ev.getRawX() - mPrevX;
+                mPrevX = ev.getRawX();
+                if (!isTowardsMenu(diffX) && isMenuLocationChange()) {
+                    // Don't consider it "snapped" if location has changed.
+                    mMenuSnappedTo = false;
+
+                    // Changed directions, make sure we check to fade in icon again.
+                    if (!mHandler.hasCallbacks(mCheckForDrag)) {
+                        // No check scheduled, set null to schedule a new one.
+                        mCheckForDrag = null;
+                    } else {
+                        // Check scheduled, reset alpha and update location; check will fade it in
+                        setMenuAlpha(0f);
+                        setMenuLocation();
+                    }
+                }
+                if (mShouldShowMenu
+                        && !NotificationStackScrollLayout.isPinnedHeadsUp(view)
+                        && !mParent.areGutsExposed()
+                        && !mParent.isDark()
+                        && (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag))) {
+                    // Only show the menu if we're not a heads up view and guts aren't exposed.
+                    mCheckForDrag = new CheckForDrag();
+                    mHandler.postDelayed(mCheckForDrag, SHOW_MENU_DELAY);
+                }
+                break;
+
+            case MotionEvent.ACTION_UP:
+                mIsUserTouching = false;
+                return handleUpEvent(ev, view, velocity);
+            case MotionEvent.ACTION_CANCEL:
+                mIsUserTouching = false;
+                cancelDrag();
+                return false;
+        }
+        return false;
+    }
+
+    private boolean handleUpEvent(MotionEvent ev, View animView, float velocity) {
+        // If the menu should not be shown, then there is no need to check if the a swipe
+        // should result in a snapping to the menu. As a result, just check if the swipe
+        // was enough to dismiss the notification.
+        if (!mShouldShowMenu) {
+            if (mSwipeHelper.isDismissGesture(ev)) {
+                dismiss(animView, velocity);
+            } else {
+                snapBack(animView, velocity);
+            }
+            return true;
+        }
+
+        final boolean gestureTowardsMenu = isTowardsMenu(velocity);
+        final boolean gestureFastEnough =
+                mSwipeHelper.getMinDismissVelocity() <= Math.abs(velocity);
+        final boolean gestureFarEnough =
+                mSwipeHelper.swipedFarEnough(mTranslation, mParent.getWidth());
+        final double timeForGesture = ev.getEventTime() - ev.getDownTime();
+        final boolean showMenuForSlowOnGoing = !mParent.canViewBeDismissed()
+                && timeForGesture >= SWIPE_MENU_TIMING;
+        final float menuSnapTarget = mOnLeft ? getSpaceForMenu() : -getSpaceForMenu();
+
+        if (DEBUG) {
+            Log.d(TAG, "mTranslation= " + mTranslation
+                    + " mAlpha= " + mAlpha
+                    + " velocity= " + velocity
+                    + " mMenuSnappedTo= " + mMenuSnappedTo
+                    + " mMenuSnappedOnLeft= " + mMenuSnappedOnLeft
+                    + " mOnLeft= " + mOnLeft
+                    + " minDismissVel= " + mSwipeHelper.getMinDismissVelocity()
+                    + " isDismissGesture= " + mSwipeHelper.isDismissGesture(ev)
+                    + " gestureTowardsMenu= " + gestureTowardsMenu
+                    + " gestureFastEnough= " + gestureFastEnough
+                    + " gestureFarEnough= " + gestureFarEnough);
+        }
+
+        if (mMenuSnappedTo && isMenuVisible() && mMenuSnappedOnLeft == mOnLeft) {
+            // Menu was snapped to previously and we're on the same side, figure out if
+            // we should stick to the menu, snap back into place, or dismiss
+            final float maximumSwipeDistance = mHorizSpaceForIcon
+                    * SWIPED_BACK_ENOUGH_TO_COVER_FRACTION;
+            final float targetLeft = getSpaceForMenu() - maximumSwipeDistance;
+            final float targetRight = mParent.getWidth() * SWIPED_FAR_ENOUGH_SIZE_FRACTION;
+            boolean withinSnapMenuThreshold = mOnLeft
+                    ? mTranslation > targetLeft && mTranslation < targetRight
+                    : mTranslation < -targetLeft && mTranslation > -targetRight;
+            boolean shouldSnapTo = mOnLeft ? mTranslation < targetLeft : mTranslation > -targetLeft;
+            if (DEBUG) {
+                Log.d(TAG, "   withinSnapMenuThreshold= " + withinSnapMenuThreshold
+                        + "   shouldSnapTo= " + shouldSnapTo
+                        + "   targetLeft= " + targetLeft
+                        + "   targetRight= " + targetRight);
+            }
+            if (withinSnapMenuThreshold && !mSwipeHelper.isDismissGesture(ev)) {
+                // Haven't moved enough to unsnap from the menu
+                showMenu(animView, menuSnapTarget, velocity);
+            } else if (mSwipeHelper.isDismissGesture(ev) && !shouldSnapTo) {
+                // Only dismiss if we're not moving towards the menu
+                dismiss(animView, velocity);
+            } else {
+                snapBack(animView, velocity);
+            }
+        } else if (!mSwipeHelper.isFalseGesture(ev)
+                && (swipedEnoughToShowMenu() && (!gestureFastEnough || showMenuForSlowOnGoing))
+                || (gestureTowardsMenu && !mSwipeHelper.isDismissGesture(ev))) {
+            // Menu has not been snapped to previously and this is menu revealing gesture
+            showMenu(animView, menuSnapTarget, velocity);
+        } else if (mSwipeHelper.isDismissGesture(ev) && !gestureTowardsMenu) {
+            dismiss(animView, velocity);
+        } else {
+            snapBack(animView, velocity);
+        }
+        return true;
+    }
+
+    private void showMenu(View animView, float targetLeft, float velocity) {
+        mMenuSnappedTo = true;
+        mMenuSnappedOnLeft = mOnLeft;
+        mMenuListener.onMenuShown(animView);
+        mSwipeHelper.snap(animView, targetLeft, velocity);
+    }
+
+    private void snapBack(View animView, float velocity) {
+        cancelDrag();
+        mMenuSnappedTo = false;
+        mSnapping = true;
+        mSwipeHelper.snap(animView, 0 /* leftTarget */, velocity);
+    }
+
+    private void dismiss(View animView, float velocity) {
+        cancelDrag();
+        mMenuSnappedTo = false;
+        mDismissing = true;
+        mSwipeHelper.dismiss(animView, velocity);
+    }
+
+    private void cancelDrag() {
+        if (mFadeAnimator != null) {
+            mFadeAnimator.cancel();
+        }
+        mHandler.removeCallbacks(mCheckForDrag);
+    }
+
+    /**
+     * @return whether the notification has been translated enough to show the menu and not enough
+     *         to be dismissed.
+     */
+    private boolean swipedEnoughToShowMenu() {
+        final float multiplier = mParent.canViewBeDismissed()
+                ? SWIPED_FAR_ENOUGH_MENU_FRACTION
+                : SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION;
+        final float minimumSwipeDistance = mHorizSpaceForIcon * multiplier;
+        return !mSwipeHelper.swipedFarEnough(0, 0) && isMenuVisible()
+                && (mOnLeft ? mTranslation > minimumSwipeDistance
+                        : mTranslation < -minimumSwipeDistance);
+    }
+
+    /**
+     * Returns whether the gesture is towards the menu location or not.
+     */
+    private boolean isTowardsMenu(float movement) {
+        return isMenuVisible()
+                && ((mOnLeft && movement <= 0)
+                        || (!mOnLeft && movement >= 0));
+    }
+
+    @Override
+    public void setAppName(String appName) {
+        if (appName == null) {
+            return;
+        }
+        Resources res = mContext.getResources();
+        final int count = mMenuItems.size();
+        for (int i = 0; i < count; i++) {
+            MenuItem item = mMenuItems.get(i);
+            String description = String.format(
+                    res.getString(R.string.notification_menu_accessibility),
+                    appName, item.getContentDescription());
+            View menuView = item.getMenuView();
+            if (menuView != null) {
+                menuView.setContentDescription(description);
+            }
+        }
+    }
+
+    @Override
+    public void onHeightUpdate() {
+        if (mParent == null || mMenuItems.size() == 0 || mMenuContainer == null) {
+            return;
+        }
+        int parentHeight = mParent.getActualHeight();
+        float translationY;
+        if (parentHeight < mVertSpaceForIcons) {
+            translationY = (parentHeight / 2) - (mHorizSpaceForIcon / 2);
+        } else {
+            translationY = (mVertSpaceForIcons - mHorizSpaceForIcon) / 2;
+        }
+        mMenuContainer.setTranslationY(translationY);
+    }
+
+    @Override
+    public void onTranslationUpdate(float translation) {
+        mTranslation = translation;
+        if (mAnimating || !mMenuFadedIn) {
+            // Don't adjust when animating, or if the menu hasn't been shown yet.
+            return;
+        }
+        final float fadeThreshold = mParent.getWidth() * 0.3f;
+        final float absTrans = Math.abs(translation);
+        float desiredAlpha = 0;
+        if (absTrans == 0) {
+            desiredAlpha = 0;
+        } else if (absTrans <= fadeThreshold) {
+            desiredAlpha = 1;
+        } else {
+            desiredAlpha = 1 - ((absTrans - fadeThreshold) / (mParent.getWidth() - fadeThreshold));
+        }
+        setMenuAlpha(desiredAlpha);
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (mMenuListener == null) {
+            // Nothing to do
+            return;
+        }
+        v.getLocationOnScreen(mIconLocation);
+        mParent.getLocationOnScreen(mParentLocation);
+        final int centerX = (int) (mHorizSpaceForIcon / 2);
+        final int centerY = v.getHeight() / 2;
+        final int x = mIconLocation[0] - mParentLocation[0] + centerX;
+        final int y = mIconLocation[1] - mParentLocation[1] + centerY;
+        final int index = mMenuContainer.indexOfChild(v);
+        mMenuListener.onMenuClicked(mParent, x, y, mMenuItems.get(index));
+    }
+
+    private boolean isMenuLocationChange() {
+        boolean onLeft = mTranslation > mIconPadding;
+        boolean onRight = mTranslation < -mIconPadding;
+        if ((mOnLeft && onRight) || (!mOnLeft && onLeft)) {
+            return true;
+        }
+        return false;
+    }
+
+    private void setMenuLocation() {
+        boolean showOnLeft = mTranslation > 0;
+        if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping || mMenuContainer == null
+                || !mMenuContainer.isAttachedToWindow()) {
+            // Do nothing
+            return;
+        }
+        final int count = mMenuContainer.getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View v = mMenuContainer.getChildAt(i);
+            final float left = i * mHorizSpaceForIcon;
+            final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1));
+            v.setX(showOnLeft ? left : right);
+        }
+        mOnLeft = showOnLeft;
+        mIconsPlaced = true;
+    }
+
+    private void setMenuAlpha(float alpha) {
+        mAlpha = alpha;
+        if (mMenuContainer == null) {
+            return;
+        }
+        if (alpha == 0) {
+            mMenuFadedIn = false; // Can fade in again once it's gone.
+            mMenuContainer.setVisibility(View.INVISIBLE);
+        } else {
+            mMenuContainer.setVisibility(View.VISIBLE);
+        }
+        final int count = mMenuContainer.getChildCount();
+        for (int i = 0; i < count; i++) {
+            mMenuContainer.getChildAt(i).setAlpha(mAlpha);
+        }
+    }
+
+    /**
+     * Returns the horizontal space in pixels required to display the menu.
+     */
+    private float getSpaceForMenu() {
+        return mHorizSpaceForIcon * mMenuContainer.getChildCount();
+    }
+
+    private final class CheckForDrag implements Runnable {
+        @Override
+        public void run() {
+            final float absTransX = Math.abs(mTranslation);
+            final float bounceBackToMenuWidth = getSpaceForMenu();
+            final float notiThreshold = mParent.getWidth() * 0.4f;
+            if ((!isMenuVisible() || isMenuLocationChange())
+                    && absTransX >= bounceBackToMenuWidth * 0.4
+                    && absTransX < notiThreshold) {
+                fadeInMenu(notiThreshold);
+            }
+        }
+    }
+
+    private void fadeInMenu(final float notiThreshold) {
+        if (mDismissing || mAnimating) {
+            return;
+        }
+        if (isMenuLocationChange()) {
+            setMenuAlpha(0f);
+        }
+        final float transX = mTranslation;
+        final boolean fromLeft = mTranslation > 0;
+        setMenuLocation();
+        mFadeAnimator = ValueAnimator.ofFloat(mAlpha, 1);
+        mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final float absTrans = Math.abs(transX);
+
+                boolean pastMenu = (fromLeft && transX <= notiThreshold)
+                        || (!fromLeft && absTrans <= notiThreshold);
+                if (pastMenu && !mMenuFadedIn) {
+                    setMenuAlpha((float) animation.getAnimatedValue());
+                }
+            }
+        });
+        mFadeAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mAnimating = true;
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                // TODO should animate back to 0f from current alpha
+                setMenuAlpha(0f);
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mAnimating = false;
+                mMenuFadedIn = mAlpha == 1;
+            }
+        });
+        mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
+        mFadeAnimator.setDuration(ICON_ALPHA_ANIM_DURATION);
+        mFadeAnimator.start();
+    }
+
+    @Override
+    public void setMenuItems(ArrayList<MenuItem> items) {
+        // Do nothing we use our own for now.
+        // TODO -- handle / allow custom menu items!
+    }
+
+    public static MenuItem createSnoozeItem(Context context) {
+        Resources res = context.getResources();
+        NotificationSnooze content = (NotificationSnooze) LayoutInflater.from(context)
+                .inflate(R.layout.notification_snooze, null, false);
+        String snoozeDescription = res.getString(R.string.notification_menu_snooze_description);
+        MenuItem snooze = new NotificationMenuItem(context, snoozeDescription, content,
+                R.drawable.ic_snooze);
+        return snooze;
+    }
+
+    public static MenuItem createInfoItem(Context context) {
+        Resources res = context.getResources();
+        String infoDescription = res.getString(R.string.notification_menu_gear_description);
+        NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
+                R.layout.notification_info, null, false);
+        MenuItem info = new NotificationMenuItem(context, infoDescription, infoContent,
+                R.drawable.ic_settings);
+        return info;
+    }
+
+    public static MenuItem createAppOpsItem(Context context) {
+        AppOpsInfo appOpsContent = (AppOpsInfo) LayoutInflater.from(context).inflate(
+                R.layout.app_ops_info, null, false);
+        MenuItem info = new NotificationMenuItem(context, null, appOpsContent,
+                -1 /*don't show in slow swipe menu */);
+        return info;
+    }
+
+    private void addMenuView(MenuItem item, ViewGroup parent) {
+        View menuView = item.getMenuView();
+        if (menuView != null) {
+            parent.addView(menuView);
+            menuView.setOnClickListener(this);
+            FrameLayout.LayoutParams lp = (LayoutParams) menuView.getLayoutParams();
+            lp.width = (int) mHorizSpaceForIcon;
+            lp.height = (int) mHorizSpaceForIcon;
+            menuView.setLayoutParams(lp);
+        }
+    }
+
+    public static class NotificationMenuItem implements MenuItem {
+        View mMenuView;
+        GutsContent mGutsContent;
+        String mContentDescription;
+
+        /**
+         * Add a new 'guts' panel. If iconResId < 0 it will not appear in the slow swipe menu
+         * but can still be exposed via other affordances.
+         */
+        public NotificationMenuItem(Context context, String s, GutsContent content, int iconResId) {
+            Resources res = context.getResources();
+            int padding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
+            int tint = res.getColor(R.color.notification_gear_color);
+            if (iconResId >= 0) {
+                AlphaOptimizedImageView iv = new AlphaOptimizedImageView(context);
+                iv.setPadding(padding, padding, padding, padding);
+                Drawable icon = context.getResources().getDrawable(iconResId);
+                iv.setImageDrawable(icon);
+                iv.setColorFilter(tint);
+                iv.setAlpha(1f);
+                mMenuView = iv;
+            }
+            mContentDescription = s;
+            mGutsContent = content;
+        }
+
+        @Override
+        @Nullable
+        public View getMenuView() {
+            return mMenuView;
+        }
+
+        @Override
+        public View getGutsView() {
+            return mGutsContent.getContentView();
+        }
+
+        @Override
+        public String getContentDescription() {
+            return mContentDescription;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
new file mode 100644
index 0000000..75b05c2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Typeface;
+import android.metrics.LogMaker;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.service.notification.SnoozeCriterion;
+import android.service.notification.StatusBarNotification;
+import android.text.SpannableString;
+import android.text.style.StyleSpan;
+import android.util.AttributeSet;
+import android.util.KeyValueListParser;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+
+public class NotificationSnooze extends LinearLayout
+        implements NotificationGuts.GutsContent, View.OnClickListener {
+
+    private static final String TAG = "NotificationSnooze";
+    /**
+     * If this changes more number increases, more assistant action resId's should be defined for
+     * accessibility purposes, see {@link #setSnoozeOptions(List)}
+     */
+    private static final int MAX_ASSISTANT_SUGGESTIONS = 1;
+    private static final String KEY_DEFAULT_SNOOZE = "default";
+    private static final String KEY_OPTIONS = "options_array";
+    private static final LogMaker OPTIONS_OPEN_LOG =
+            new LogMaker(MetricsEvent.NOTIFICATION_SNOOZE_OPTIONS)
+                    .setType(MetricsEvent.TYPE_OPEN);
+    private static final LogMaker OPTIONS_CLOSE_LOG =
+            new LogMaker(MetricsEvent.NOTIFICATION_SNOOZE_OPTIONS)
+                    .setType(MetricsEvent.TYPE_CLOSE);
+    private static final LogMaker UNDO_LOG =
+            new LogMaker(MetricsEvent.NOTIFICATION_UNDO_SNOOZE)
+                    .setType(MetricsEvent.TYPE_ACTION);
+    private NotificationGuts mGutsContainer;
+    private NotificationSwipeActionHelper mSnoozeListener;
+    private StatusBarNotification mSbn;
+
+    private TextView mSelectedOptionText;
+    private TextView mUndoButton;
+    private ImageView mExpandButton;
+    private View mDivider;
+    private ViewGroup mSnoozeOptionContainer;
+    private List<SnoozeOption> mSnoozeOptions;
+    private int mCollapsedHeight;
+    private SnoozeOption mDefaultOption;
+    private SnoozeOption mSelectedOption;
+    private boolean mSnoozing;
+    private boolean mExpanded;
+    private AnimatorSet mExpandAnimation;
+    private KeyValueListParser mParser;
+
+    private final static int[] sAccessibilityActions = {
+            R.id.action_snooze_shorter,
+            R.id.action_snooze_short,
+            R.id.action_snooze_long,
+            R.id.action_snooze_longer,
+    };
+
+    private MetricsLogger mMetricsLogger = new MetricsLogger();
+
+    public NotificationSnooze(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mParser = new KeyValueListParser(',');
+    }
+
+    @VisibleForTesting
+    SnoozeOption getDefaultOption()
+    {
+        return mDefaultOption;
+    }
+
+    @VisibleForTesting
+    void setKeyValueListParser(KeyValueListParser parser) {
+        mParser = parser;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.snooze_snackbar_min_height);
+        findViewById(R.id.notification_snooze).setOnClickListener(this);
+        mSelectedOptionText = (TextView) findViewById(R.id.snooze_option_default);
+        mUndoButton = (TextView) findViewById(R.id.undo);
+        mUndoButton.setOnClickListener(this);
+        mExpandButton = (ImageView) findViewById(R.id.expand_button);
+        mDivider = findViewById(R.id.divider);
+        mDivider.setAlpha(0f);
+        mSnoozeOptionContainer = (ViewGroup) findViewById(R.id.snooze_options);
+        mSnoozeOptionContainer.setVisibility(View.INVISIBLE);
+        mSnoozeOptionContainer.setAlpha(0f);
+
+        // Create the different options based on list
+        mSnoozeOptions = getDefaultSnoozeOptions();
+        createOptionViews();
+
+        setSelected(mDefaultOption, false);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        logOptionSelection(MetricsEvent.NOTIFICATION_SNOOZE_CLICKED, mDefaultOption);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        if (mGutsContainer != null && mGutsContainer.isExposed()) {
+            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+                event.getText().add(mSelectedOptionText.getText());
+            }
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.addAction(new AccessibilityAction(R.id.action_snooze_undo,
+                getResources().getString(R.string.snooze_undo)));
+        int count = mSnoozeOptions.size();
+        for (int i = 0; i < count; i++) {
+            AccessibilityAction action = mSnoozeOptions.get(i).getAccessibilityAction();
+            if (action != null) {
+                info.addAction(action);
+            }
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+        if (super.performAccessibilityActionInternal(action, arguments)) {
+            return true;
+        }
+        if (action == R.id.action_snooze_undo) {
+            undoSnooze(mUndoButton);
+            return true;
+        }
+        for (int i = 0; i < mSnoozeOptions.size(); i++) {
+            SnoozeOption so = mSnoozeOptions.get(i);
+            if (so.getAccessibilityAction() != null
+                    && so.getAccessibilityAction().getId() == action) {
+                setSelected(so, true);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setSnoozeOptions(final List<SnoozeCriterion> snoozeList) {
+        if (snoozeList == null) {
+            return;
+        }
+        mSnoozeOptions.clear();
+        mSnoozeOptions = getDefaultSnoozeOptions();
+        final int count = Math.min(MAX_ASSISTANT_SUGGESTIONS, snoozeList.size());
+        for (int i = 0; i < count; i++) {
+            SnoozeCriterion sc = snoozeList.get(i);
+            AccessibilityAction action = new AccessibilityAction(
+                    R.id.action_snooze_assistant_suggestion_1, sc.getExplanation());
+            mSnoozeOptions.add(new NotificationSnoozeOption(sc, 0, sc.getExplanation(),
+                    sc.getConfirmation(), action));
+        }
+        createOptionViews();
+    }
+
+    public boolean isExpanded() {
+        return mExpanded;
+    }
+
+    public void setSnoozeListener(NotificationSwipeActionHelper listener) {
+        mSnoozeListener = listener;
+    }
+
+    public void setStatusBarNotification(StatusBarNotification sbn) {
+        mSbn = sbn;
+    }
+
+    @VisibleForTesting
+    ArrayList<SnoozeOption> getDefaultSnoozeOptions() {
+        final Resources resources = getContext().getResources();
+        ArrayList<SnoozeOption> options = new ArrayList<>();
+        try {
+            final String config = Settings.Global.getString(getContext().getContentResolver(),
+                    Settings.Global.NOTIFICATION_SNOOZE_OPTIONS);
+            mParser.setString(config);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "Bad snooze constants");
+        }
+
+        final int defaultSnooze = mParser.getInt(KEY_DEFAULT_SNOOZE,
+                resources.getInteger(R.integer.config_notification_snooze_time_default));
+        final int[] snoozeTimes = mParser.getIntArray(KEY_OPTIONS,
+                resources.getIntArray(R.array.config_notification_snooze_times));
+
+        for (int i = 0; i < snoozeTimes.length && i < sAccessibilityActions.length; i++) {
+            int snoozeTime = snoozeTimes[i];
+            SnoozeOption option = createOption(snoozeTime, sAccessibilityActions[i]);
+            if (i == 0 || snoozeTime == defaultSnooze) {
+                mDefaultOption = option;
+            }
+            options.add(option);
+        }
+        return options;
+    }
+
+    private SnoozeOption createOption(int minutes, int accessibilityActionId) {
+        Resources res = getResources();
+        boolean showInHours = minutes >= 60;
+        int pluralResId = showInHours
+                ? R.plurals.snoozeHourOptions
+                : R.plurals.snoozeMinuteOptions;
+        int count = showInHours ? (minutes / 60) : minutes;
+        String description = res.getQuantityString(pluralResId, count, count);
+        String resultText = String.format(res.getString(R.string.snoozed_for_time), description);
+        AccessibilityAction action = new AccessibilityAction(accessibilityActionId, description);
+        final int index = resultText.indexOf(description);
+        if (index == -1) {
+            return new NotificationSnoozeOption(null, minutes, description, resultText, action);
+        }
+        SpannableString string = new SpannableString(resultText);
+        string.setSpan(new StyleSpan(Typeface.BOLD),
+                index, index + description.length(), 0 /* flags */);
+        return new NotificationSnoozeOption(null, minutes, description, string,
+                action);
+    }
+
+    private void createOptionViews() {
+        mSnoozeOptionContainer.removeAllViews();
+        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+        for (int i = 0; i < mSnoozeOptions.size(); i++) {
+            SnoozeOption option = mSnoozeOptions.get(i);
+            TextView tv = (TextView) inflater.inflate(R.layout.notification_snooze_option,
+                    mSnoozeOptionContainer, false);
+            mSnoozeOptionContainer.addView(tv);
+            tv.setText(option.getDescription());
+            tv.setTag(option);
+            tv.setOnClickListener(this);
+        }
+    }
+
+    private void hideSelectedOption() {
+        final int childCount = mSnoozeOptionContainer.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = mSnoozeOptionContainer.getChildAt(i);
+            child.setVisibility(child.getTag() == mSelectedOption ? View.GONE : View.VISIBLE);
+        }
+    }
+
+    private void showSnoozeOptions(boolean show) {
+        int drawableId = show ? com.android.internal.R.drawable.ic_collapse_notification
+                : com.android.internal.R.drawable.ic_expand_notification;
+        mExpandButton.setImageResource(drawableId);
+        if (mExpanded != show) {
+            mExpanded = show;
+            animateSnoozeOptions(show);
+            if (mGutsContainer != null) {
+                mGutsContainer.onHeightChanged();
+            }
+        }
+    }
+
+    private void animateSnoozeOptions(boolean show) {
+        if (mExpandAnimation != null) {
+            mExpandAnimation.cancel();
+        }
+        ObjectAnimator dividerAnim = ObjectAnimator.ofFloat(mDivider, View.ALPHA,
+                mDivider.getAlpha(), show ? 1f : 0f);
+        ObjectAnimator optionAnim = ObjectAnimator.ofFloat(mSnoozeOptionContainer, View.ALPHA,
+                mSnoozeOptionContainer.getAlpha(), show ? 1f : 0f);
+        mSnoozeOptionContainer.setVisibility(View.VISIBLE);
+        mExpandAnimation = new AnimatorSet();
+        mExpandAnimation.playTogether(dividerAnim, optionAnim);
+        mExpandAnimation.setDuration(150);
+        mExpandAnimation.setInterpolator(show ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+        mExpandAnimation.addListener(new AnimatorListenerAdapter() {
+            boolean cancelled = false;
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                cancelled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (!show && !cancelled) {
+                    mSnoozeOptionContainer.setVisibility(View.INVISIBLE);
+                    mSnoozeOptionContainer.setAlpha(0f);
+                }
+            }
+        });
+        mExpandAnimation.start();
+    }
+
+    private void setSelected(SnoozeOption option, boolean userAction) {
+        mSelectedOption = option;
+        mSelectedOptionText.setText(option.getConfirmation());
+        showSnoozeOptions(false);
+        hideSelectedOption();
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+        if (userAction) {
+            logOptionSelection(MetricsEvent.NOTIFICATION_SELECT_SNOOZE, option);
+        }
+    }
+
+    private void logOptionSelection(int category, SnoozeOption option) {
+        int index = mSnoozeOptions.indexOf(option);
+        long duration = TimeUnit.MINUTES.toMillis(option.getMinutesToSnoozeFor());
+        mMetricsLogger.write(new LogMaker(category)
+                .setType(MetricsEvent.TYPE_ACTION)
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_SNOOZE_INDEX, index)
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_SNOOZE_DURATION_MS, duration));
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (mGutsContainer != null) {
+            mGutsContainer.resetFalsingCheck();
+        }
+        final int id = v.getId();
+        final SnoozeOption tag = (SnoozeOption) v.getTag();
+        if (tag != null) {
+            setSelected(tag, true);
+        } else if (id == R.id.notification_snooze) {
+            // Toggle snooze options
+            showSnoozeOptions(!mExpanded);
+            mMetricsLogger.write(!mExpanded ? OPTIONS_OPEN_LOG : OPTIONS_CLOSE_LOG);
+        } else {
+            // Undo snooze was selected
+            undoSnooze(v);
+            mMetricsLogger.write(UNDO_LOG);
+        }
+    }
+
+    private void undoSnooze(View v) {
+        mSelectedOption = null;
+        int[] parentLoc = new int[2];
+        int[] targetLoc = new int[2];
+        mGutsContainer.getLocationOnScreen(parentLoc);
+        v.getLocationOnScreen(targetLoc);
+        final int centerX = v.getWidth() / 2;
+        final int centerY = v.getHeight() / 2;
+        final int x = targetLoc[0] - parentLoc[0] + centerX;
+        final int y = targetLoc[1] - parentLoc[1] + centerY;
+        showSnoozeOptions(false);
+        mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
+    }
+
+    @Override
+    public int getActualHeight() {
+        return mExpanded ? getHeight() : mCollapsedHeight;
+    }
+
+    @Override
+    public boolean willBeRemoved() {
+        return mSnoozing;
+    }
+
+    @Override
+    public View getContentView() {
+        // Reset the view before use
+        setSelected(mDefaultOption, false);
+        return this;
+    }
+
+    @Override
+    public void setGutsParent(NotificationGuts guts) {
+        mGutsContainer = guts;
+    }
+
+    @Override
+    public boolean handleCloseControls(boolean save, boolean force) {
+        if (mExpanded && !force) {
+            // Collapse expanded state on outside touch
+            showSnoozeOptions(false);
+            return true;
+        } else if (mSnoozeListener != null && mSelectedOption != null) {
+            // Snooze option selected so commit it
+            mSnoozing = true;
+            mSnoozeListener.snooze(mSbn, mSelectedOption);
+            return true;
+        } else {
+            // The view should actually be closed
+            setSelected(mSnoozeOptions.get(0), false);
+            return false; // Return false here so that guts handles closing the view
+        }
+    }
+
+    @Override
+    public boolean isLeavebehind() {
+        return true;
+    }
+
+    @Override
+    public boolean shouldBeSaved() {
+        return true;
+    }
+
+    public class NotificationSnoozeOption implements SnoozeOption {
+        private SnoozeCriterion mCriterion;
+        private int mMinutesToSnoozeFor;
+        private CharSequence mDescription;
+        private CharSequence mConfirmation;
+        private AccessibilityAction mAction;
+
+        public NotificationSnoozeOption(SnoozeCriterion sc, int minToSnoozeFor,
+                CharSequence description,
+                CharSequence confirmation, AccessibilityAction action) {
+            mCriterion = sc;
+            mMinutesToSnoozeFor = minToSnoozeFor;
+            mDescription = description;
+            mConfirmation = confirmation;
+            mAction = action;
+        }
+
+        @Override
+        public SnoozeCriterion getSnoozeCriterion() {
+            return mCriterion;
+        }
+
+        @Override
+        public CharSequence getDescription() {
+            return mDescription;
+        }
+
+        @Override
+        public CharSequence getConfirmation() {
+            return mConfirmation;
+        }
+
+        @Override
+        public int getMinutesToSnoozeFor() {
+            return mMinutesToSnoozeFor;
+        }
+
+        @Override
+        public AccessibilityAction getAccessibilityAction() {
+            return mAction;
+        }
+
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationUndoLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationUndoLayout.java
new file mode 100644
index 0000000..3ea8195
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationUndoLayout.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+
+/**
+ * Custom view for the NotificationInfo confirmation views so that the confirmation text can
+ * occupy the full width of the notification and push the undo button down to the next line if
+ * necessary.
+ *
+ * @see NotificationInfo
+ */
+public class NotificationUndoLayout extends FrameLayout {
+    /**
+     * View for the prompt/confirmation text to tell the user the previous action was successful.
+     */
+    private View mConfirmationTextView;
+    /** Undo button (actionable text) view. */
+    private View mUndoView;
+
+    /**
+     * Whether {@link #mConfirmationTextView} is multiline and will require the full width of the
+     * parent (which causes the {@link #mUndoView} to push down).
+     */
+    private boolean mIsMultiline = false;
+    private int mMultilineTopMargin;
+
+    public NotificationUndoLayout(Context context) {
+        this(context, null);
+    }
+
+    public NotificationUndoLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public NotificationUndoLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mConfirmationTextView = findViewById(R.id.confirmation_text);
+        mUndoView = findViewById(R.id.undo);
+
+        mMultilineTopMargin = getResources().getDimensionPixelOffset(
+                com.android.internal.R.dimen.notification_content_margin_start);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        LayoutParams confirmationLayoutParams =
+                (LayoutParams) mConfirmationTextView.getLayoutParams();
+        LayoutParams undoLayoutParams =(LayoutParams) mUndoView.getLayoutParams();
+
+        int measuredWidth = getMeasuredWidth();
+        // Ignore the left margin on the undo button - no need for additional extra space between
+        // the text and the button.
+        int requiredWidth = mConfirmationTextView.getMeasuredWidth()
+                + confirmationLayoutParams.rightMargin
+                + confirmationLayoutParams.leftMargin
+                + mUndoView.getMeasuredWidth()
+                + undoLayoutParams.rightMargin;
+        // If the measured width isn't enough to accommodate both the undo button and the text in
+        // the same line, we'll need to adjust the view to be multi-line. Otherwise, we're done.
+        if (requiredWidth > measuredWidth) {
+            mIsMultiline = true;
+
+            // Update height requirement to the text height and the button's height (along with
+            // additional spacing for the top of the text).
+            int updatedHeight = mMultilineTopMargin
+                    + mConfirmationTextView.getMeasuredHeight()
+                    + mUndoView.getMeasuredHeight()
+                    + undoLayoutParams.topMargin
+                    + undoLayoutParams.bottomMargin;
+
+            setMeasuredDimension(measuredWidth, updatedHeight);
+        } else {
+            mIsMultiline = false;
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        // If the text view and undo view don't fit on the same line, we'll need to manually lay
+        // out the content.
+        if (mIsMultiline) {
+            // Re-align parent right/bottom values. Left and top are considered to be 0.
+            int parentBottom = getMeasuredHeight();
+            int parentRight = getMeasuredWidth();
+
+            LayoutParams confirmationLayoutParams =
+                    (LayoutParams) mConfirmationTextView.getLayoutParams();
+            LayoutParams undoLayoutParams = (LayoutParams) mUndoView.getLayoutParams();
+
+            // The confirmation text occupies the full width as computed earlier. Both side margins
+            // are equivalent, so we only need to grab the left one here.
+            mConfirmationTextView.layout(
+                    confirmationLayoutParams.leftMargin,
+                    mMultilineTopMargin,
+                    confirmationLayoutParams.leftMargin + mConfirmationTextView.getMeasuredWidth(),
+                    mMultilineTopMargin + mConfirmationTextView.getMeasuredHeight());
+
+            // The undo button is aligned bottom|end with the parent in the case of multiline text.
+            int undoViewLeft = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
+                    ? undoLayoutParams.rightMargin
+                    : parentRight - mUndoView.getMeasuredWidth() - undoLayoutParams.rightMargin;
+            mUndoView.layout(
+                    undoViewLeft,
+                    parentBottom - mUndoView.getMeasuredHeight() - undoLayoutParams.bottomMargin,
+                    undoViewLeft + mUndoView.getMeasuredWidth(),
+                    parentBottom - undoLayoutParams.bottomMargin);
+        } else {
+            super.onLayout(changed, left, top, right, bottom);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
new file mode 100644
index 0000000..a21794b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.content.Context;
+import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.InflationTask;
+import com.android.systemui.statusbar.notification.NotificationData;
+
+/**
+ * An inflater task that asynchronously inflates a ExpandableNotificationRow
+ */
+public class RowInflaterTask implements InflationTask, AsyncLayoutInflater.OnInflateFinishedListener {
+
+    private static final String TAG = "RowInflaterTask";
+    private static final boolean TRACE_ORIGIN = true;
+
+    private RowInflationFinishedListener mListener;
+    private NotificationData.Entry mEntry;
+    private boolean mCancelled;
+    private Throwable mInflateOrigin;
+
+    /**
+     * Inflates a new notificationView. This should not be called twice on this object
+     */
+    public void inflate(Context context, ViewGroup parent, NotificationData.Entry entry,
+            RowInflationFinishedListener listener) {
+        if (TRACE_ORIGIN) {
+            mInflateOrigin = new Throwable("inflate requested here");
+        }
+        mListener = listener;
+        AsyncLayoutInflater inflater = new AsyncLayoutInflater(context);
+        mEntry = entry;
+        entry.setInflationTask(this);
+        inflater.inflate(R.layout.status_bar_notification_row, parent, this);
+    }
+
+    @Override
+    public void abort() {
+        mCancelled = true;
+    }
+
+    @Override
+    public void onInflateFinished(View view, int resid, ViewGroup parent) {
+        if (!mCancelled) {
+            try {
+                mEntry.onInflationTaskFinished();
+                mListener.onInflationFinished((ExpandableNotificationRow) view);
+            } catch (Throwable t) {
+                if (mInflateOrigin != null) {
+                    Log.e(TAG, "Error in inflation finished listener: " + t, mInflateOrigin);
+                    t.addSuppressed(mInflateOrigin);
+                }
+                throw t;
+            }
+        }
+    }
+
+    public interface RowInflationFinishedListener {
+        void onInflationFinished(ExpandableNotificationRow row);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
new file mode 100644
index 0000000..8a061a6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+
+/**
+ * A common base class for all views in the notification stack scroller which don't have a
+ * background.
+ */
+public abstract class StackScrollerDecorView extends ExpandableView {
+
+    protected View mContent;
+    protected View mSecondaryView;
+    private boolean mIsVisible = true;
+    private boolean mContentVisible = true;
+    private boolean mIsSecondaryVisible = true;
+    private int mDuration = 260;
+    private boolean mContentAnimating;
+    private final Runnable mContentVisibilityEndRunnable = () -> {
+        mContentAnimating = false;
+        if (getVisibility() != View.GONE && !mIsVisible) {
+            setVisibility(GONE);
+            setWillBeGone(false);
+            notifyHeightChanged(false /* needsAnimation */);
+        }
+    };
+
+    public StackScrollerDecorView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mContent = findContentView();
+        mSecondaryView = findSecondaryView();
+        setVisible(false /* nowVisible */, false /* animate */);
+        setSecondaryVisible(false /* nowVisible */, false /* animate */);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        setOutlineProvider(null);
+    }
+
+    @Override
+    public boolean isTransparent() {
+        return true;
+    }
+
+    /**
+     * Set the content of this view to be visible in an animated way.
+     *
+     * @param contentVisible True if the content should be visible or false if it should be hidden.
+     */
+    public void setContentVisible(boolean contentVisible) {
+        setContentVisible(contentVisible, true /* animate */);
+    }
+    /**
+     * Set the content of this view to be visible.
+     * @param contentVisible True if the content should be visible or false if it should be hidden.
+     * @param animate Should an animation be performed.
+     */
+    private void setContentVisible(boolean contentVisible, boolean animate) {
+        if (mContentVisible != contentVisible) {
+            mContentAnimating = animate;
+            setViewVisible(mContent, contentVisible, animate, mContentVisibilityEndRunnable);
+            mContentVisible = contentVisible;
+        } if (!mContentAnimating) {
+            mContentVisibilityEndRunnable.run();
+        }
+    }
+
+    public boolean isContentVisible() {
+        return mContentVisible;
+    }
+
+    /**
+     * Make this view visible. If {@code false} is passed, the view will fade out it's content
+     * and set the view Visibility to GONE. If only the content should be changed
+     * {@link #setContentVisible(boolean)} can be used.
+     *
+     * @param nowVisible should the view be visible
+     * @param animate should the change be animated.
+     */
+    public void setVisible(boolean nowVisible, boolean animate) {
+        if (mIsVisible != nowVisible) {
+            mIsVisible = nowVisible;
+            if (animate) {
+                if (nowVisible) {
+                    setVisibility(VISIBLE);
+                    setWillBeGone(false);
+                    notifyHeightChanged(false /* needsAnimation */);
+                } else {
+                    setWillBeGone(true);
+                }
+                setContentVisible(nowVisible, true /* animate */);
+            } else {
+                setVisibility(nowVisible ? VISIBLE : GONE);
+                setContentVisible(nowVisible, false /* animate */);
+                setWillBeGone(false);
+                notifyHeightChanged(false /* needsAnimation */);
+            }
+        }
+    }
+
+    /**
+     * Set the secondary view of this layout to visible.
+     *
+     * @param nowVisible should the secondary view be visible
+     * @param animate should the change be animated
+     */
+    public void setSecondaryVisible(boolean nowVisible, boolean animate) {
+        if (mIsSecondaryVisible != nowVisible) {
+            setViewVisible(mSecondaryView, nowVisible, animate, null /* endRunnable */);
+            mIsSecondaryVisible = nowVisible;
+        }
+    }
+
+    @VisibleForTesting
+    boolean isSecondaryVisible() {
+        return mIsSecondaryVisible;
+    }
+
+    /**
+     * Is this view visible. If a view is currently animating to gone, it will
+     * return {@code false}.
+     */
+    public boolean isVisible() {
+        return mIsVisible;
+    }
+
+    void setDuration(int duration) {
+        mDuration = duration;
+    }
+
+    /**
+     * Animate a view to a new visibility.
+     * @param view Target view, maybe content view or dismiss view.
+     * @param nowVisible Should it now be visible.
+     * @param animate Should this be done in an animated way.
+     * @param endRunnable A runnable that is run when the animation is done.
+     */
+    private void setViewVisible(View view, boolean nowVisible,
+            boolean animate, Runnable endRunnable) {
+        if (view == null) {
+            return;
+        }
+        // cancel any previous animations
+        view.animate().cancel();
+        float endValue = nowVisible ? 1.0f : 0.0f;
+        if (!animate) {
+            view.setAlpha(endValue);
+            if (endRunnable != null) {
+                endRunnable.run();
+            }
+            return;
+        }
+
+        // Animate the view alpha
+        Interpolator interpolator = nowVisible ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT;
+        view.animate()
+                .alpha(endValue)
+                .setInterpolator(interpolator)
+                .setDuration(mDuration)
+                .withEndAction(endRunnable);
+    }
+
+    @Override
+    public void performRemoveAnimation(long duration, long delay,
+            float translationDirection, boolean isHeadsUpAnimation, float endLocation,
+            Runnable onFinishedRunnable,
+            AnimatorListenerAdapter animationListener) {
+        // TODO: Use duration
+        setContentVisible(false);
+    }
+
+    @Override
+    public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) {
+        // TODO: use delay and duration
+        setContentVisible(true);
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
+    protected abstract View findContentView();
+
+    /**
+     * Returns a view that might not always appear while the main content view is still visible.
+     */
+    protected abstract View findSecondaryView();
+}
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
new file mode 100644
index 0000000..2da4d2c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.service.notification.StatusBarNotification;
+import android.view.View;
+
+import com.android.systemui.statusbar.notification.ImageTransformState;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+/**
+ * Wraps a notification containing a big picture template
+ */
+public class NotificationBigPictureTemplateViewWrapper extends NotificationTemplateViewWrapper {
+
+    protected NotificationBigPictureTemplateViewWrapper(Context ctx, View view,
+            ExpandableNotificationRow row) {
+        super(ctx, view, row);
+    }
+
+    @Override
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        super.onContentUpdated(row);
+        updateImageTag(row.getStatusBarNotification());
+    }
+
+    private void updateImageTag(StatusBarNotification notification) {
+        final Bundle extras = notification.getNotification().extras;
+        Icon overRiddenIcon = extras.getParcelable(Notification.EXTRA_LARGE_ICON_BIG);
+        if (overRiddenIcon != null) {
+            mPicture.setTag(ImageTransformState.ICON_TAG, overRiddenIcon);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
new file mode 100644
index 0000000..133df3c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.view.View;
+
+import com.android.internal.widget.ImageFloatingTextView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.TransformableView;
+
+/**
+ * Wraps a notification containing a big text template
+ */
+public class NotificationBigTextTemplateViewWrapper extends NotificationTemplateViewWrapper {
+
+    private ImageFloatingTextView mBigtext;
+
+    protected NotificationBigTextTemplateViewWrapper(Context ctx, View view,
+            ExpandableNotificationRow row) {
+        super(ctx, view, row);
+    }
+
+    private void resolveViews(StatusBarNotification notification) {
+        mBigtext = (ImageFloatingTextView) mView.findViewById(com.android.internal.R.id.big_text);
+    }
+
+    @Override
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        // Reinspect the notification. Before the super call, because the super call also updates
+        // the transformation types and we need to have our values set by then.
+        resolveViews(row.getStatusBarNotification());
+        super.onContentUpdated(row);
+    }
+
+    @Override
+    protected void updateTransformedTypes() {
+        // This also clears the existing types
+        super.updateTransformedTypes();
+        if (mBigtext != null) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
+                    mBigtext);
+        }
+    }
+}
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
new file mode 100644
index 0000000..db7b4fc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import android.content.Context;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+/**
+ * Wraps a notification containing a custom view.
+ */
+public class NotificationCustomViewWrapper extends NotificationViewWrapper {
+
+    private boolean mIsLegacy;
+    private int mLegacyColor;
+
+    protected NotificationCustomViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
+        super(ctx, view, row);
+        mLegacyColor = row.getContext().getColor(R.color.notification_legacy_background_color);
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        super.setVisible(visible);
+        mView.setAlpha(visible ? 1.0f : 0.0f);
+    }
+
+    @Override
+    protected boolean shouldClearBackgroundOnReapply() {
+        return false;
+    }
+
+    @Override
+    public int getCustomBackgroundColor() {
+        int customBackgroundColor = super.getCustomBackgroundColor();
+        if (customBackgroundColor == 0 && mIsLegacy) {
+            return mLegacyColor;
+        }
+        return customBackgroundColor;
+    }
+
+    public void setLegacy(boolean legacy) {
+        super.setLegacy(legacy);
+        mIsLegacy = legacy;
+    }
+
+    @Override
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
+        return true;
+    }
+}
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
new file mode 100644
index 0000000..6ca07ed
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -0,0 +1,253 @@
+/*
+ * 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.systemui.statusbar.notification.row.wrapper;
+
+import static com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+        .DEFAULT_HEADER_VISIBLE_AMOUNT;
+import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
+
+import android.app.Notification;
+import android.content.Context;
+import android.util.ArraySet;
+import android.view.NotificationHeaderView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.widget.NotificationExpandButton;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.CustomInterpolatorTransformation;
+import com.android.systemui.statusbar.notification.ImageTransformState;
+import com.android.systemui.statusbar.notification.TransformState;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.ViewTransformationHelper;
+
+import java.util.Stack;
+
+/**
+ * Wraps a notification header view.
+ */
+public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
+
+    private static final Interpolator LOW_PRIORITY_HEADER_CLOSE
+            = new PathInterpolator(0.4f, 0f, 0.7f, 1f);
+
+    protected final ViewTransformationHelper mTransformationHelper;
+    private final int mTranslationForHeader;
+
+    protected int mColor;
+    private ImageView mIcon;
+
+    private NotificationExpandButton mExpandButton;
+    private NotificationHeaderView mNotificationHeader;
+    private TextView mHeaderText;
+    private ImageView mWorkProfileImage;
+    private boolean mIsLowPriority;
+    private boolean mTransformLowPriorityTitle;
+    private boolean mShowExpandButtonAtEnd;
+    protected float mHeaderTranslation;
+
+    protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
+        super(ctx, view, row);
+        mShowExpandButtonAtEnd = ctx.getResources().getBoolean(
+                R.bool.config_showNotificationExpandButtonAtEnd);
+        mTransformationHelper = new ViewTransformationHelper();
+
+        // we want to avoid that the header clashes with the other text when transforming
+        // low-priority
+        mTransformationHelper.setCustomTransformation(
+                new CustomInterpolatorTransformation(TRANSFORMING_VIEW_TITLE) {
+
+                    @Override
+                    public Interpolator getCustomInterpolator(int interpolationType,
+                            boolean isFrom) {
+                        boolean isLowPriority = mView instanceof NotificationHeaderView;
+                        if (interpolationType == TRANSFORM_Y) {
+                            if (isLowPriority && !isFrom
+                                    || !isLowPriority && isFrom) {
+                                return Interpolators.LINEAR_OUT_SLOW_IN;
+                            } else {
+                                return LOW_PRIORITY_HEADER_CLOSE;
+                            }
+                        }
+                        return null;
+                    }
+
+                    @Override
+                    protected boolean hasCustomTransformation() {
+                        return mIsLowPriority && mTransformLowPriorityTitle;
+                    }
+                }, TRANSFORMING_VIEW_TITLE);
+        resolveHeaderViews();
+        addAppOpsOnClickListener(row);
+        mTranslationForHeader = ctx.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin)
+                - ctx.getResources().getDimensionPixelSize(
+                        com.android.internal.R.dimen.notification_content_margin_top);
+    }
+
+    protected void resolveHeaderViews() {
+        mIcon = mView.findViewById(com.android.internal.R.id.icon);
+        mHeaderText = mView.findViewById(com.android.internal.R.id.header_text);
+        mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
+        mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
+        mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
+        mNotificationHeader.setShowExpandButtonAtEnd(mShowExpandButtonAtEnd);
+        mColor = mNotificationHeader.getOriginalIconColor();
+    }
+
+    private void addAppOpsOnClickListener(ExpandableNotificationRow row) {
+        mNotificationHeader.setAppOpsOnClickListener(row.getAppOpsOnClickListener());
+    }
+
+    @Override
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        super.onContentUpdated(row);
+        mIsLowPriority = row.isLowPriority();
+        mTransformLowPriorityTitle = !row.isChildInGroup() && !row.isSummaryWithChildren();
+        ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews();
+
+        // Reinspect the notification.
+        resolveHeaderViews();
+        if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) {
+            setHeaderVisibleAmount(row.getHeaderVisibleAmount());
+        }
+        updateTransformedTypes();
+        addRemainingTransformTypes();
+        updateCropToPaddingForImageViews();
+        Notification notification = row.getStatusBarNotification().getNotification();
+        mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
+        // The work profile image is always the same lets just set the icon tag for it not to
+        // animate
+        mWorkProfileImage.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
+
+        // 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.
+        ArraySet<View> currentViews = mTransformationHelper.getAllTransformingViews();
+        for (int i = 0; i < previousViews.size(); i++) {
+            View view = previousViews.valueAt(i);
+            if (!currentViews.contains(view)) {
+                mTransformationHelper.resetTransformedView(view);
+            }
+        }
+    }
+
+    /**
+     * Adds the remaining TransformTypes to the TransformHelper. This is done to make sure that each
+     * child is faded automatically and doesn't have to be manually added.
+     * The keys used for the views are the ids.
+     */
+    private void addRemainingTransformTypes() {
+        mTransformationHelper.addRemainingTransformTypes(mView);
+    }
+
+    /**
+     * Since we are deactivating the clipping when transforming the ImageViews don't get clipped
+     * anymore during these transitions. We can avoid that by using
+     * {@link ImageView#setCropToPadding(boolean)} on all ImageViews.
+     */
+    private void updateCropToPaddingForImageViews() {
+        Stack<View> stack = new Stack<>();
+        stack.push(mView);
+        while (!stack.isEmpty()) {
+            View child = stack.pop();
+            if (child instanceof ImageView) {
+                ((ImageView) child).setCropToPadding(true);
+            } else if (child instanceof ViewGroup){
+                ViewGroup group = (ViewGroup) child;
+                for (int i = 0; i < group.getChildCount(); i++) {
+                    stack.push(group.getChildAt(i));
+                }
+            }
+        }
+    }
+
+    protected void updateTransformedTypes() {
+        mTransformationHelper.reset();
+        mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_ICON, mIcon);
+        if (mIsLowPriority) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
+                    mHeaderText);
+        }
+    }
+
+    @Override
+    public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {
+        mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE);
+        mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
+    }
+
+    @Override
+    public void setHeaderVisibleAmount(float headerVisibleAmount) {
+        super.setHeaderVisibleAmount(headerVisibleAmount);
+        mNotificationHeader.setAlpha(headerVisibleAmount);
+        mHeaderTranslation = (1.0f - headerVisibleAmount) * mTranslationForHeader;
+        mView.setTranslationY(mHeaderTranslation);
+    }
+
+    @Override
+    public int getHeaderTranslation() {
+        return (int) mHeaderTranslation;
+    }
+
+    @Override
+    public NotificationHeaderView getNotificationHeader() {
+        return mNotificationHeader;
+    }
+
+    @Override
+    public TransformState getCurrentState(int fadingView) {
+        return mTransformationHelper.getCurrentState(fadingView);
+    }
+
+    @Override
+    public void transformTo(TransformableView notification, Runnable endRunnable) {
+        mTransformationHelper.transformTo(notification, endRunnable);
+    }
+
+    @Override
+    public void transformTo(TransformableView notification, float transformationAmount) {
+        mTransformationHelper.transformTo(notification, transformationAmount);
+    }
+
+    @Override
+    public void transformFrom(TransformableView notification) {
+        mTransformationHelper.transformFrom(notification);
+    }
+
+    @Override
+    public void transformFrom(TransformableView notification, float transformationAmount) {
+        mTransformationHelper.transformFrom(notification, transformationAmount);
+    }
+
+    @Override
+    public void setIsChildInGroup(boolean isChildInGroup) {
+        super.setIsChildInGroup(isChildInGroup);
+        mTransformLowPriorityTitle = !isChildInGroup;
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        super.setVisible(visible);
+        mTransformationHelper.setVisible(visible);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
new file mode 100644
index 0000000..37d2f6b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import android.content.Context;
+import android.view.View;
+
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.TransformableView;
+
+/**
+ * Wraps a notification containing a media template
+ */
+public class NotificationMediaTemplateViewWrapper extends NotificationTemplateViewWrapper {
+
+    protected NotificationMediaTemplateViewWrapper(Context ctx, View view,
+            ExpandableNotificationRow row) {
+        super(ctx, view, row);
+    }
+
+    View mActions;
+
+    private void resolveViews() {
+        mActions = mView.findViewById(com.android.internal.R.id.media_actions);
+    }
+
+    @Override
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        // Reinspect the notification. Before the super call, because the super call also updates
+        // the transformation types and we need to have our values set by then.
+        resolveViews();
+        super.onContentUpdated(row);
+    }
+
+    @Override
+    protected void updateTransformedTypes() {
+        // This also clears the existing types
+        super.updateTransformedTypes();
+        if (mActions != null) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_ACTIONS,
+                    mActions);
+        }
+    }
+
+    @Override
+    public boolean isDimmable() {
+        return getCustomBackgroundColor() == 0;
+    }
+
+    @Override
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
+        return true;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
new file mode 100644
index 0000000..13c5960
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import com.android.internal.widget.MessagingLayout;
+import com.android.internal.widget.MessagingLinearLayout;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+import android.content.Context;
+import android.view.View;
+
+/**
+ * Wraps a notification containing a messaging template
+ */
+public class NotificationMessagingTemplateViewWrapper extends NotificationTemplateViewWrapper {
+
+    private final int mMinHeightWithActions;
+    private MessagingLayout mMessagingLayout;
+    private MessagingLinearLayout mMessagingLinearLayout;
+
+    protected NotificationMessagingTemplateViewWrapper(Context ctx, View view,
+            ExpandableNotificationRow row) {
+        super(ctx, view, row);
+        mMessagingLayout = (MessagingLayout) view;
+        mMinHeightWithActions = NotificationUtils.getFontScaledHeight(ctx,
+                R.dimen.notification_messaging_actions_min_height);
+    }
+
+    private void resolveViews() {
+        mMessagingLinearLayout = mMessagingLayout.getMessagingLinearLayout();
+    }
+
+    @Override
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        // Reinspect the notification. Before the super call, because the super call also updates
+        // the transformation types and we need to have our values set by then.
+        resolveViews();
+        super.onContentUpdated(row);
+    }
+
+    @Override
+    protected void updateTransformedTypes() {
+        // This also clears the existing types
+        super.updateTransformedTypes();
+        if (mMessagingLinearLayout != null) {
+            mTransformationHelper.addTransformedView(mMessagingLinearLayout.getId(),
+                    mMessagingLinearLayout);
+        }
+    }
+
+    @Override
+    public void setRemoteInputVisible(boolean visible) {
+        mMessagingLayout.showHistoricMessages(visible);
+    }
+
+    @Override
+    public int getMinLayoutHeight() {
+        if (mActionsContainer != null && mActionsContainer.getVisibility() != View.GONE) {
+            return mMinHeightWithActions;
+        }
+        return super.getMinLayoutHeight();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
new file mode 100644
index 0000000..d934902
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.internal.util.ContrastColorUtil;
+import com.android.internal.widget.NotificationActionListLayout;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.notification.ImageTransformState;
+import com.android.systemui.statusbar.notification.TransformState;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.ViewTransformationHelper;
+import com.android.systemui.statusbar.notification.row.HybridNotificationView;
+
+/**
+ * Wraps a notification view inflated from a template.
+ */
+public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapper {
+
+    protected ImageView mPicture;
+    private ProgressBar mProgressBar;
+    private TextView mTitle;
+    private TextView mText;
+    protected View mActionsContainer;
+    private ImageView mReplyAction;
+    private Rect mTmpRect = new Rect();
+
+    private int mContentHeight;
+    private int mMinHeightHint;
+    private NotificationActionListLayout mActions;
+    private ArraySet<PendingIntent> mCancelledPendingIntents = new ArraySet<>();
+    private UiOffloadThread mUiOffloadThread;
+    private View mRemoteInputHistory;
+
+    protected NotificationTemplateViewWrapper(Context ctx, View view,
+            ExpandableNotificationRow row) {
+        super(ctx, view, row);
+        mTransformationHelper.setCustomTransformation(
+                new ViewTransformationHelper.CustomTransformation() {
+                    @Override
+                    public boolean transformTo(TransformState ownState,
+                            TransformableView notification, final float transformationAmount) {
+                        if (!(notification instanceof HybridNotificationView)) {
+                            return false;
+                        }
+                        TransformState otherState = notification.getCurrentState(
+                                TRANSFORMING_VIEW_TITLE);
+                        final View text = ownState.getTransformedView();
+                        CrossFadeHelper.fadeOut(text, transformationAmount);
+                        if (otherState != null) {
+                            ownState.transformViewVerticalTo(otherState, this,
+                                    transformationAmount);
+                            otherState.recycle();
+                        }
+                        return true;
+                    }
+
+                    @Override
+                    public boolean customTransformTarget(TransformState ownState,
+                            TransformState otherState) {
+                        float endY = getTransformationY(ownState, otherState);
+                        ownState.setTransformationEndY(endY);
+                        return true;
+                    }
+
+                    @Override
+                    public boolean transformFrom(TransformState ownState,
+                            TransformableView notification, float transformationAmount) {
+                        if (!(notification instanceof HybridNotificationView)) {
+                            return false;
+                        }
+                        TransformState otherState = notification.getCurrentState(
+                                TRANSFORMING_VIEW_TITLE);
+                        final View text = ownState.getTransformedView();
+                        CrossFadeHelper.fadeIn(text, transformationAmount);
+                        if (otherState != null) {
+                            ownState.transformViewVerticalFrom(otherState, this,
+                                    transformationAmount);
+                            otherState.recycle();
+                        }
+                        return true;
+                    }
+
+                    @Override
+                    public boolean initTransformation(TransformState ownState,
+                            TransformState otherState) {
+                        float startY = getTransformationY(ownState, otherState);
+                        ownState.setTransformationStartY(startY);
+                        return true;
+                    }
+
+                    private float getTransformationY(TransformState ownState,
+                            TransformState otherState) {
+                        int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
+                        int[] ownStablePosition = ownState.getLaidOutLocationOnScreen();
+                        return (otherStablePosition[1]
+                                + otherState.getTransformedView().getHeight()
+                                - ownStablePosition[1]) * 0.33f;
+                    }
+
+                }, TRANSFORMING_VIEW_TEXT);
+    }
+
+    private void resolveTemplateViews(StatusBarNotification notification) {
+        mPicture = (ImageView) mView.findViewById(com.android.internal.R.id.right_icon);
+        if (mPicture != null) {
+            mPicture.setTag(ImageTransformState.ICON_TAG,
+                    notification.getNotification().getLargeIcon());
+        }
+        mTitle = (TextView) mView.findViewById(com.android.internal.R.id.title);
+        mText = (TextView) mView.findViewById(com.android.internal.R.id.text);
+        final View progress = mView.findViewById(com.android.internal.R.id.progress);
+        if (progress instanceof ProgressBar) {
+            mProgressBar = (ProgressBar) progress;
+        } else {
+            // It's still a viewstub
+            mProgressBar = null;
+        }
+        mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container);
+        mActions = mView.findViewById(com.android.internal.R.id.actions);
+        mReplyAction = mView.findViewById(com.android.internal.R.id.reply_icon_action);
+        mRemoteInputHistory = mView.findViewById(
+                com.android.internal.R.id.notification_material_reply_container);
+        updatePendingIntentCancellations();
+    }
+
+    private void updatePendingIntentCancellations() {
+        if (mActions != null) {
+            int numActions = mActions.getChildCount();
+            for (int i = 0; i < numActions; i++) {
+                Button action = (Button) mActions.getChildAt(i);
+                performOnPendingIntentCancellation(action, () -> {
+                    if (action.isEnabled()) {
+                        action.setEnabled(false);
+                        // The visual appearance doesn't look disabled enough yet, let's add the
+                        // alpha as well. Since Alpha doesn't play nicely right now with the
+                        // transformation, we rather blend it manually with the background color.
+                        ColorStateList textColors = action.getTextColors();
+                        int[] colors = textColors.getColors();
+                        int[] newColors = new int[colors.length];
+                        float disabledAlpha = mView.getResources().getFloat(
+                                com.android.internal.R.dimen.notification_action_disabled_alpha);
+                        for (int j = 0; j < colors.length; j++) {
+                            int color = colors[j];
+                            color = blendColorWithBackground(color, disabledAlpha);
+                            newColors[j] = color;
+                        }
+                        ColorStateList newColorStateList = new ColorStateList(
+                                textColors.getStates(), newColors);
+                        action.setTextColor(newColorStateList);
+                    }
+                });
+            }
+        }
+        if (mReplyAction != null) {
+            // Let's reset the view on update, assuming the new pending intent isn't cancelled
+            // anymore. The color filter automatically resets when it's updated.
+            mReplyAction.setEnabled(true);
+            performOnPendingIntentCancellation(mReplyAction, () -> {
+                if (mReplyAction != null && mReplyAction.isEnabled()) {
+                    mReplyAction.setEnabled(false);
+                    // The visual appearance doesn't look disabled enough yet, let's add the
+                    // alpha as well. Since Alpha doesn't play nicely right now with the
+                    // transformation, we rather blend it manually with the background color.
+                    Drawable drawable = mReplyAction.getDrawable().mutate();
+                    PorterDuffColorFilter colorFilter =
+                            (PorterDuffColorFilter) drawable.getColorFilter();
+                    float disabledAlpha = mView.getResources().getFloat(
+                            com.android.internal.R.dimen.notification_action_disabled_alpha);
+                    if (colorFilter != null) {
+                        int color = colorFilter.getColor();
+                        color = blendColorWithBackground(color, disabledAlpha);
+                        drawable.mutate().setColorFilter(color, colorFilter.getMode());
+                    } else {
+                        mReplyAction.setAlpha(disabledAlpha);
+                    }
+                }
+            });
+        }
+    }
+
+    private int blendColorWithBackground(int color, float alpha) {
+        // alpha doesn't go well for color filters, so let's blend it manually
+        return ContrastColorUtil.compositeColors(Color.argb((int) (alpha * 255),
+                Color.red(color), Color.green(color), Color.blue(color)), resolveBackgroundColor());
+    }
+
+    private void performOnPendingIntentCancellation(View view, Runnable cancellationRunnable) {
+        PendingIntent pendingIntent = (PendingIntent) view.getTag(
+                com.android.internal.R.id.pending_intent_tag);
+        if (pendingIntent == null) {
+            return;
+        }
+        if (mCancelledPendingIntents.contains(pendingIntent)) {
+            cancellationRunnable.run();
+        } else {
+            PendingIntent.CancelListener listener = (PendingIntent intent) -> {
+                mView.post(() -> {
+                    mCancelledPendingIntents.add(pendingIntent);
+                    cancellationRunnable.run();
+                });
+            };
+            if (mUiOffloadThread == null) {
+                mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+            }
+            if (view.isAttachedToWindow()) {
+                mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
+            }
+            view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+                @Override
+                public void onViewAttachedToWindow(View v) {
+                    mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
+                }
+
+                @Override
+                public void onViewDetachedFromWindow(View v) {
+                    mUiOffloadThread.submit(() -> pendingIntent.unregisterCancelListener(listener));
+                }
+            });
+        }
+    }
+
+    @Override
+    public boolean disallowSingleClick(float x, float y) {
+        if (mReplyAction != null && mReplyAction.getVisibility() == View.VISIBLE) {
+            if (isOnView(mReplyAction, x, y) || isOnView(mPicture, x, y)) {
+                return true;
+            }
+        }
+        return super.disallowSingleClick(x, y);
+    }
+
+    private boolean isOnView(View view, float x, float y) {
+        View searchView = (View) view.getParent();
+        while (searchView != null && !(searchView instanceof ExpandableNotificationRow)) {
+            searchView.getHitRect(mTmpRect);
+            x -= mTmpRect.left;
+            y -= mTmpRect.top;
+            searchView = (View) searchView.getParent();
+        }
+        view.getHitRect(mTmpRect);
+        return mTmpRect.contains((int) x,(int) y);
+    }
+
+    @Override
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        // Reinspect the notification. Before the super call, because the super call also updates
+        // the transformation types and we need to have our values set by then.
+        resolveTemplateViews(row.getStatusBarNotification());
+        super.onContentUpdated(row);
+    }
+
+    @Override
+    protected void updateTransformedTypes() {
+        // This also clears the existing types
+        super.updateTransformedTypes();
+        if (mTitle != null) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
+                    mTitle);
+        }
+        if (mText != null) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
+                    mText);
+        }
+        if (mPicture != null) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE,
+                    mPicture);
+        }
+        if (mProgressBar != null) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS,
+                    mProgressBar);
+        }
+    }
+
+    @Override
+    public void setContentHeight(int contentHeight, int minHeightHint) {
+        super.setContentHeight(contentHeight, minHeightHint);
+
+        mContentHeight = contentHeight;
+        mMinHeightHint = minHeightHint;
+        updateActionOffset();
+    }
+
+    @Override
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
+        if (super.shouldClipToRounding(topRounded, bottomRounded)) {
+            return true;
+        }
+        return bottomRounded && mActionsContainer != null
+                && mActionsContainer.getVisibility() != View.GONE;
+    }
+
+    private void updateActionOffset() {
+        if (mActionsContainer != null) {
+            // We should never push the actions higher than they are in the headsup view.
+            int constrainedContentHeight = Math.max(mContentHeight, mMinHeightHint);
+
+            // We also need to compensate for any header translation, since we're always at the end.
+            mActionsContainer.setTranslationY(constrainedContentHeight - mView.getHeight()
+                    - getHeaderTranslation());
+        }
+    }
+
+    @Override
+    public int getExtraMeasureHeight() {
+        int extra = 0;
+        if (mActions != null) {
+            extra = mActions.getExtraMeasureHeight();
+        }
+        if (mRemoteInputHistory != null && mRemoteInputHistory.getVisibility() != View.GONE) {
+            extra += mRow.getContext().getResources().getDimensionPixelSize(
+                    R.dimen.remote_input_history_extra_height);
+        }
+        return extra + super.getExtraMeasureHeight();
+    }
+}
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
new file mode 100644
index 0000000..2ca7282
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import android.content.Context;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.view.NotificationHeaderView;
+import android.view.View;
+
+import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.notification.TransformState;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.TransformableView;
+
+/**
+ * Wraps the actual notification content view; used to implement behaviors which are different for
+ * the individual templates and custom views.
+ */
+public abstract class NotificationViewWrapper implements TransformableView {
+
+    protected final View mView;
+    protected final ExpandableNotificationRow mRow;
+
+    private int mBackgroundColor = 0;
+
+    public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
+        if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
+            if ("bigPicture".equals(v.getTag())) {
+                return new NotificationBigPictureTemplateViewWrapper(ctx, v, row);
+            } else if ("bigText".equals(v.getTag())) {
+                return new NotificationBigTextTemplateViewWrapper(ctx, v, row);
+            } else if ("media".equals(v.getTag()) || "bigMediaNarrow".equals(v.getTag())) {
+                return new NotificationMediaTemplateViewWrapper(ctx, v, row);
+            } else if ("messaging".equals(v.getTag())) {
+                return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
+            }
+            return new NotificationTemplateViewWrapper(ctx, v, row);
+        } else if (v instanceof NotificationHeaderView) {
+            return new NotificationHeaderViewWrapper(ctx, v, row);
+        } else {
+            return new NotificationCustomViewWrapper(ctx, v, row);
+        }
+    }
+
+    protected NotificationViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
+        mView = view;
+        mRow = row;
+        onReinflated();
+    }
+
+    /**
+     * Notifies this wrapper that the content of the view might have changed.
+     * @param row the row this wrapper is attached to
+     */
+    public void onContentUpdated(ExpandableNotificationRow row) {
+    }
+
+    public void onReinflated() {
+        if (shouldClearBackgroundOnReapply()) {
+            mBackgroundColor = 0;
+        }
+        Drawable background = mView.getBackground();
+        if (background instanceof ColorDrawable) {
+            mBackgroundColor = ((ColorDrawable) background).getColor();
+            mView.setBackground(null);
+        }
+    }
+
+    protected boolean shouldClearBackgroundOnReapply() {
+        return true;
+    }
+
+    /**
+     * Update the appearance of the expand button.
+     *
+     * @param expandable should this view be expandable
+     * @param onClickListener the listener to invoke when the expand affordance is clicked on
+     */
+    public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {}
+
+    /**
+     * @return the notification header if it exists
+     */
+    public NotificationHeaderView getNotificationHeader() {
+        return null;
+    }
+
+    public int getHeaderTranslation() {
+        return 0;
+    }
+
+    @Override
+    public TransformState getCurrentState(int fadingView) {
+        return null;
+    }
+
+    @Override
+    public void transformTo(TransformableView notification, Runnable endRunnable) {
+        // By default we are fading out completely
+        CrossFadeHelper.fadeOut(mView, endRunnable);
+    }
+
+    @Override
+    public void transformTo(TransformableView notification, float transformationAmount) {
+        CrossFadeHelper.fadeOut(mView, transformationAmount);
+    }
+
+    @Override
+    public void transformFrom(TransformableView notification) {
+        // By default we are fading in completely
+        CrossFadeHelper.fadeIn(mView);
+    }
+
+    @Override
+    public void transformFrom(TransformableView notification, float transformationAmount) {
+        CrossFadeHelper.fadeIn(mView, transformationAmount);
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        mView.animate().cancel();
+        mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+    }
+
+    public int getCustomBackgroundColor() {
+        // Parent notifications should always use the normal background color
+        return mRow.isSummaryWithChildren() ? 0 : mBackgroundColor;
+    }
+
+    protected int resolveBackgroundColor() {
+        int customBackgroundColor = getCustomBackgroundColor();
+        if (customBackgroundColor != 0) {
+            return customBackgroundColor;
+        }
+        return mView.getContext().getColor(
+                com.android.internal.R.color.notification_material_background_color);
+    }
+
+    public void setLegacy(boolean legacy) {
+    }
+
+    public void setContentHeight(int contentHeight, int minHeightHint) {
+    }
+
+    public void setRemoteInputVisible(boolean visible) {
+    }
+
+    public void setIsChildInGroup(boolean isChildInGroup) {
+    }
+
+    public boolean isDimmable() {
+        return true;
+    }
+
+    public boolean disallowSingleClick(float x, float y) {
+        return false;
+    }
+
+    public int getMinLayoutHeight() {
+        return 0;
+    }
+
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
+        return false;
+    }
+
+    public void setHeaderVisibleAmount(float headerVisibleAmount) {
+    }
+
+    /**
+     * Get the extra height that needs to be added to this view, such that it can be measured
+     * normally.
+     */
+    public int getExtraMeasureHeight() {
+        return 0;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
new file mode 100644
index 0000000..15eaaac
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+import java.util.ArrayList;
+
+/**
+ * A global state to track all input states for the algorithm.
+ */
+public class AmbientState {
+    private ArrayList<View> mDraggedViews = new ArrayList<View>();
+    private int mScrollY;
+    private boolean mDimmed;
+    private ActivatableNotificationView mActivatedChild;
+    private float mOverScrollTopAmount;
+    private float mOverScrollBottomAmount;
+    private int mSpeedBumpIndex = -1;
+    private boolean mDark;
+    private boolean mHideSensitive;
+    private HeadsUpManager mHeadsUpManager;
+    private float mStackTranslation;
+    private int mLayoutHeight;
+    private int mTopPadding;
+    private boolean mShadeExpanded;
+    private float mMaxHeadsUpTranslation;
+    private boolean mDismissAllInProgress;
+    private int mLayoutMinHeight;
+    private NotificationShelf mShelf;
+    private int mZDistanceBetweenElements;
+    private int mBaseZHeight;
+    private int mMaxLayoutHeight;
+    private ActivatableNotificationView mLastVisibleBackgroundChild;
+    private float mCurrentScrollVelocity;
+    private int mStatusBarState;
+    private float mExpandingVelocity;
+    private boolean mPanelTracking;
+    private boolean mExpansionChanging;
+    private boolean mPanelFullWidth;
+    private boolean mPulsing;
+    private boolean mUnlockHintRunning;
+    private boolean mQsCustomizerShowing;
+    private int mIntrinsicPadding;
+    private int mExpandAnimationTopChange;
+    private ExpandableNotificationRow mExpandingNotification;
+    private int mDarkTopPadding;
+    private float mDarkAmount;
+    private boolean mAppearing;
+
+    public AmbientState(Context context) {
+        reload(context);
+    }
+
+    /**
+     * Reload the dimens e.g. if the density changed.
+     */
+    public void reload(Context context) {
+        mZDistanceBetweenElements = getZDistanceBetweenElements(context);
+        mBaseZHeight = getBaseHeight(mZDistanceBetweenElements);
+    }
+
+    private static int getZDistanceBetweenElements(Context context) {
+        return Math.max(1, context.getResources()
+                .getDimensionPixelSize(R.dimen.z_distance_between_notifications));
+    }
+
+    private static int getBaseHeight(int zdistanceBetweenElements) {
+        return 4 * zdistanceBetweenElements;
+    }
+
+    /**
+     * @return the launch height for notifications that are launched
+     */
+    public static int getNotificationLaunchHeight(Context context) {
+        int zDistance = getZDistanceBetweenElements(context);
+        return getBaseHeight(zDistance) * 2;
+    }
+
+    /**
+     * @return the basic Z height on which notifications remain.
+     */
+    public int getBaseZHeight() {
+        return mBaseZHeight;
+    }
+
+    /**
+     * @return the distance in Z between two overlaying notifications.
+     */
+    public int getZDistanceBetweenElements() {
+        return mZDistanceBetweenElements;
+    }
+
+    public int getScrollY() {
+        return mScrollY;
+    }
+
+    public void setScrollY(int scrollY) {
+        this.mScrollY = scrollY;
+    }
+
+    public void onBeginDrag(View view) {
+        mDraggedViews.add(view);
+    }
+
+    public void onDragFinished(View view) {
+        mDraggedViews.remove(view);
+    }
+
+    public ArrayList<View> getDraggedViews() {
+        return mDraggedViews;
+    }
+
+    /**
+     * @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are
+     *               translucent and everything is scaled back a bit.
+     */
+    public void setDimmed(boolean dimmed) {
+        mDimmed = dimmed;
+    }
+
+    /** In dark mode, we draw as little as possible, assuming a black background */
+    public void setDark(boolean dark) {
+        mDark = dark;
+    }
+
+    /** Dark ratio of the status bar **/
+    public void setDarkAmount(float darkAmount) {
+        mDarkAmount = darkAmount;
+    }
+
+    /** Returns the dark ratio of the status bar */
+    public float getDarkAmount() {
+        return mDarkAmount;
+    }
+
+    public void setHideSensitive(boolean hideSensitive) {
+        mHideSensitive = hideSensitive;
+    }
+
+    /**
+     * In dimmed mode, a child can be activated, which happens on the first tap of the double-tap
+     * interaction. This child is then scaled normally and its background is fully opaque.
+     */
+    public void setActivatedChild(ActivatableNotificationView activatedChild) {
+        mActivatedChild = activatedChild;
+    }
+
+    public boolean isDimmed() {
+        return mDimmed;
+    }
+
+    public boolean isDark() {
+        return mDark;
+    }
+
+    public boolean isHideSensitive() {
+        return mHideSensitive;
+    }
+
+    public ActivatableNotificationView getActivatedChild() {
+        return mActivatedChild;
+    }
+
+    public void setOverScrollAmount(float amount, boolean onTop) {
+        if (onTop) {
+            mOverScrollTopAmount = amount;
+        } else {
+            mOverScrollBottomAmount = amount;
+        }
+    }
+
+    public float getOverScrollAmount(boolean top) {
+        return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
+    }
+
+    public int getSpeedBumpIndex() {
+        return mSpeedBumpIndex;
+    }
+
+    public void setSpeedBumpIndex(int shelfIndex) {
+        mSpeedBumpIndex = shelfIndex;
+    }
+
+    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+        mHeadsUpManager = headsUpManager;
+    }
+
+    public float getStackTranslation() {
+        return mStackTranslation;
+    }
+
+    public void setStackTranslation(float stackTranslation) {
+        mStackTranslation = stackTranslation;
+    }
+
+    public void setLayoutHeight(int layoutHeight) {
+        mLayoutHeight = layoutHeight;
+    }
+
+    public float getTopPadding() {
+        return mTopPadding;
+    }
+
+    public void setTopPadding(int topPadding) {
+        mTopPadding = topPadding;
+    }
+
+    public int getInnerHeight() {
+        return Math.max(Math.min(mLayoutHeight, mMaxLayoutHeight) - mTopPadding, mLayoutMinHeight);
+    }
+
+    public boolean isShadeExpanded() {
+        return mShadeExpanded;
+    }
+
+    public void setShadeExpanded(boolean shadeExpanded) {
+        mShadeExpanded = shadeExpanded;
+    }
+
+    public void setMaxHeadsUpTranslation(float maxHeadsUpTranslation) {
+        mMaxHeadsUpTranslation = maxHeadsUpTranslation;
+    }
+
+    public float getMaxHeadsUpTranslation() {
+        return mMaxHeadsUpTranslation;
+    }
+
+    public void setDismissAllInProgress(boolean dismissAllInProgress) {
+        mDismissAllInProgress = dismissAllInProgress;
+    }
+
+    public boolean isDismissAllInProgress() {
+        return mDismissAllInProgress;
+    }
+
+    public void setLayoutMinHeight(int layoutMinHeight) {
+        mLayoutMinHeight = layoutMinHeight;
+    }
+
+    public void setShelf(NotificationShelf shelf) {
+        mShelf = shelf;
+    }
+
+    @Nullable
+    public NotificationShelf getShelf() {
+        return mShelf;
+    }
+
+    public void setLayoutMaxHeight(int maxLayoutHeight) {
+        mMaxLayoutHeight = maxLayoutHeight;
+    }
+
+    /**
+     * Sets the last visible view of the host layout, that has a background, i.e the very last
+     * view in the shade, without the clear all button.
+     */
+    public void setLastVisibleBackgroundChild(
+            ActivatableNotificationView lastVisibleBackgroundChild) {
+        mLastVisibleBackgroundChild = lastVisibleBackgroundChild;
+    }
+
+    public ActivatableNotificationView getLastVisibleBackgroundChild() {
+        return mLastVisibleBackgroundChild;
+    }
+
+    public void setCurrentScrollVelocity(float currentScrollVelocity) {
+        mCurrentScrollVelocity = currentScrollVelocity;
+    }
+
+    public float getCurrentScrollVelocity() {
+        return mCurrentScrollVelocity;
+    }
+
+    public boolean isOnKeyguard() {
+        return mStatusBarState == StatusBarState.KEYGUARD;
+    }
+
+    public void setStatusBarState(int statusBarState) {
+        mStatusBarState = statusBarState;
+    }
+
+    public void setExpandingVelocity(float expandingVelocity) {
+        mExpandingVelocity = expandingVelocity;
+    }
+
+    public void setExpansionChanging(boolean expansionChanging) {
+        mExpansionChanging = expansionChanging;
+    }
+
+    public boolean isExpansionChanging() {
+        return mExpansionChanging;
+    }
+
+    public float getExpandingVelocity() {
+        return mExpandingVelocity;
+    }
+
+    public void setPanelTracking(boolean panelTracking) {
+        mPanelTracking = panelTracking;
+    }
+
+    public boolean hasPulsingNotifications() {
+        return mPulsing;
+    }
+
+    public void setPulsing(boolean hasPulsing) {
+        mPulsing = hasPulsing;
+    }
+
+    public boolean isPulsing(NotificationData.Entry entry) {
+        if (!mPulsing || mHeadsUpManager == null) {
+            return false;
+        }
+        return mHeadsUpManager.getAllEntries().anyMatch(e -> (e == entry));
+    }
+
+    public boolean isPanelTracking() {
+        return mPanelTracking;
+    }
+
+    public boolean isPanelFullWidth() {
+        return mPanelFullWidth;
+    }
+
+    public void setPanelFullWidth(boolean panelFullWidth) {
+        mPanelFullWidth = panelFullWidth;
+    }
+
+    public void setUnlockHintRunning(boolean unlockHintRunning) {
+        mUnlockHintRunning = unlockHintRunning;
+    }
+
+    public boolean isUnlockHintRunning() {
+        return mUnlockHintRunning;
+    }
+
+    public boolean isQsCustomizerShowing() {
+        return mQsCustomizerShowing;
+    }
+
+    public void setQsCustomizerShowing(boolean qsCustomizerShowing) {
+        mQsCustomizerShowing = qsCustomizerShowing;
+    }
+
+    public void setIntrinsicPadding(int intrinsicPadding) {
+        mIntrinsicPadding = intrinsicPadding;
+    }
+
+    public int getIntrinsicPadding() {
+        return mIntrinsicPadding;
+    }
+
+    /**
+     * Similar to the normal is above shelf logic but doesn't allow it to be above in AOD1.
+     *
+     * @param expandableView the view to check
+     */
+    public boolean isAboveShelf(ExpandableView expandableView) {
+        if (!(expandableView instanceof ExpandableNotificationRow)) {
+            return expandableView.isAboveShelf();
+        }
+        ExpandableNotificationRow row = (ExpandableNotificationRow) expandableView;
+        return row.isAboveShelf() && !isDozingAndNotPulsing(row);
+    }
+
+    /**
+     * @return whether a view is dozing and not pulsing right now
+     */
+    public boolean isDozingAndNotPulsing(ExpandableView view) {
+        if (view instanceof ExpandableNotificationRow) {
+            return isDozingAndNotPulsing((ExpandableNotificationRow) view);
+        }
+        return false;
+    }
+
+    /**
+     * @return whether a row is dozing and not pulsing right now
+     */
+    public boolean isDozingAndNotPulsing(ExpandableNotificationRow row) {
+        return isDark() && !isPulsing(row.getEntry());
+    }
+
+    public void setExpandAnimationTopChange(int expandAnimationTopChange) {
+        mExpandAnimationTopChange = expandAnimationTopChange;
+    }
+
+    public void setExpandingNotification(ExpandableNotificationRow row) {
+        mExpandingNotification = row;
+    }
+
+    public ExpandableNotificationRow getExpandingNotification() {
+        return mExpandingNotification;
+    }
+
+    public int getExpandAnimationTopChange() {
+        return mExpandAnimationTopChange;
+    }
+
+    /**
+     * @return {@code true } when shade is completely dark: in AOD or ambient display.
+     */
+    public boolean isFullyDark() {
+        return mDarkAmount == 1;
+    }
+
+    public void setDarkTopPadding(int darkTopPadding) {
+        mDarkTopPadding = darkTopPadding;
+    }
+
+    public int getDarkTopPadding() {
+        return mDarkTopPadding;
+    }
+
+    public void setAppearing(boolean appearing) {
+        mAppearing = appearing;
+    }
+
+    public boolean isAppearing() {
+        return mAppearing;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
new file mode 100644
index 0000000..c6f953c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import androidx.collection.ArraySet;
+import android.util.Property;
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * Filters the animations for only a certain type of properties.
+ */
+public class AnimationFilter {
+    public static final int NO_DELAY = -1;
+    boolean animateAlpha;
+    boolean animateX;
+    boolean animateY;
+    ArraySet<View> animateYViews = new ArraySet<>();
+    boolean animateZ;
+    boolean animateHeight;
+    boolean animateTopInset;
+    boolean animateDimmed;
+    boolean animateDark;
+    boolean animateHideSensitive;
+    public boolean animateShadowAlpha;
+    boolean hasDelays;
+    boolean hasGoToFullShadeEvent;
+    long customDelay;
+    private ArraySet<Property> mAnimatedProperties = new ArraySet<>();
+
+    public AnimationFilter animateAlpha() {
+        animateAlpha = true;
+        return this;
+    }
+
+    public AnimationFilter animateScale() {
+        animate(View.SCALE_X);
+        animate(View.SCALE_Y);
+        return this;
+    }
+
+    public AnimationFilter animateX() {
+        animateX = true;
+        return this;
+    }
+
+    public AnimationFilter animateY() {
+        animateY = true;
+        return this;
+    }
+
+    public AnimationFilter hasDelays() {
+        hasDelays = true;
+        return this;
+    }
+
+    public AnimationFilter animateZ() {
+        animateZ = true;
+        return this;
+    }
+
+    public AnimationFilter animateHeight() {
+        animateHeight = true;
+        return this;
+    }
+
+    public AnimationFilter animateTopInset() {
+        animateTopInset = true;
+        return this;
+    }
+
+    public AnimationFilter animateDimmed() {
+        animateDimmed = true;
+        return this;
+    }
+
+    public AnimationFilter animateDark() {
+        animateDark = true;
+        return this;
+    }
+
+    public AnimationFilter animateHideSensitive() {
+        animateHideSensitive = true;
+        return this;
+    }
+
+    public AnimationFilter animateShadowAlpha() {
+        animateShadowAlpha = true;
+        return this;
+    }
+
+    public AnimationFilter animateY(View view) {
+        animateYViews.add(view);
+        return this;
+    }
+
+    public boolean shouldAnimateY(View view) {
+        return animateY || animateYViews.contains(view);
+    }
+
+    /**
+     * Combines multiple filters into {@code this} filter, using or as the operand .
+     *
+     * @param events The animation events from the filters to combine.
+     */
+    public void applyCombination(ArrayList<NotificationStackScrollLayout.AnimationEvent> events) {
+        reset();
+        int size = events.size();
+        for (int i = 0; i < size; i++) {
+            NotificationStackScrollLayout.AnimationEvent ev = events.get(i);
+            combineFilter(events.get(i).filter);
+            if (ev.animationType ==
+                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_GO_TO_FULL_SHADE) {
+                hasGoToFullShadeEvent = true;
+            }
+            if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
+                    .ANIMATION_TYPE_HEADS_UP_DISAPPEAR) {
+                customDelay = StackStateAnimator.ANIMATION_DELAY_HEADS_UP;
+            } else if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
+                    .ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
+                // We need both timeouts when clicking, one to delay it and one for the animation
+                // to look nice
+                customDelay = StackStateAnimator.ANIMATION_DELAY_HEADS_UP_CLICKED
+                        + StackStateAnimator.ANIMATION_DELAY_HEADS_UP;
+            } else if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
+                    .ANIMATION_TYPE_PULSE_APPEAR || ev.animationType ==
+                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) {
+                customDelay = StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR / 2;
+            }
+        }
+    }
+
+    public void combineFilter(AnimationFilter filter) {
+        animateAlpha |= filter.animateAlpha;
+        animateX |= filter.animateX;
+        animateY |= filter.animateY;
+        animateYViews.addAll(filter.animateYViews);
+        animateZ |= filter.animateZ;
+        animateHeight |= filter.animateHeight;
+        animateTopInset |= filter.animateTopInset;
+        animateDimmed |= filter.animateDimmed;
+        animateDark |= filter.animateDark;
+        animateHideSensitive |= filter.animateHideSensitive;
+        animateShadowAlpha |= filter.animateShadowAlpha;
+        hasDelays |= filter.hasDelays;
+        mAnimatedProperties.addAll(filter.mAnimatedProperties);
+    }
+
+    public void reset() {
+        animateAlpha = false;
+        animateX = false;
+        animateY = false;
+        animateYViews.clear();
+        animateZ = false;
+        animateHeight = false;
+        animateShadowAlpha = false;
+        animateTopInset = false;
+        animateDimmed = false;
+        animateDark = false;
+        animateHideSensitive = false;
+        hasDelays = false;
+        hasGoToFullShadeEvent = false;
+        customDelay = NO_DELAY;
+        mAnimatedProperties.clear();
+    }
+
+    public AnimationFilter animate(Property property) {
+        mAnimatedProperties.add(property);
+        return this;
+    }
+
+    public boolean shouldAnimateProperty(Property property) {
+        // TODO: migrate all existing animators to properties
+        return mAnimatedProperties.contains(property);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
new file mode 100644
index 0000000..87a3cc9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.animation.AnimatorListenerAdapter;
+import android.util.ArrayMap;
+import android.util.Property;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+/**
+ * Properties for a View animation
+ */
+public class AnimationProperties {
+    public long duration;
+    public long delay;
+    private ArrayMap<Property, Interpolator> mInterpolatorMap;
+    private AnimatorListenerAdapter mAnimatorListenerAdapter;
+
+    /**
+     * @return an animation filter for this animation.
+     */
+    public AnimationFilter getAnimationFilter() {
+        return new AnimationFilter() {
+            @Override
+            public boolean shouldAnimateProperty(Property property) {
+                return true;
+            }
+        };
+    }
+
+    /**
+     * @return a listener that should be run whenever any property finished its animation
+     */
+    public AnimatorListenerAdapter getAnimationFinishListener() {
+        return mAnimatorListenerAdapter;
+    }
+
+    public AnimationProperties setAnimationFinishListener(AnimatorListenerAdapter listener) {
+        mAnimatorListenerAdapter = listener;
+        return this;
+    }
+
+    public boolean wasAdded(View view) {
+        return false;
+    }
+
+    /**
+     * Get a custom interpolator for a property instead of the normal one.
+     */
+    public Interpolator getCustomInterpolator(View child, Property property) {
+        return mInterpolatorMap != null ? mInterpolatorMap.get(property) : null;
+    }
+
+
+    public void combineCustomInterpolators(AnimationProperties iconAnimationProperties) {
+        ArrayMap<Property, Interpolator> map = iconAnimationProperties.mInterpolatorMap;
+        if (map != null) {
+            if (mInterpolatorMap == null) {
+                mInterpolatorMap = new ArrayMap<>();
+            }
+            mInterpolatorMap.putAll(map);
+        }
+    }
+
+    /**
+     * Set a custom interpolator to use for all views for a property.
+     */
+    public AnimationProperties setCustomInterpolator(Property property, Interpolator interpolator) {
+        if (mInterpolatorMap == null) {
+            mInterpolatorMap = new ArrayMap<>();
+        }
+        mInterpolatorMap.put(property, interpolator);
+        return this;
+    }
+
+    public AnimationProperties setDuration(long duration) {
+        this.duration = duration;
+        return this;
+    }
+
+    public AnimationProperties setDelay(long delay) {
+        this.delay = delay;
+        return this;
+    }
+
+    public AnimationProperties resetCustomInterpolators() {
+        mInterpolatorMap = null;
+        return this;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java
new file mode 100644
index 0000000..8c1a788
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java
@@ -0,0 +1,488 @@
+/*
+ * 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.systemui.statusbar.notification.stack;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.view.View;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+
+/**
+* A state of an expandable view
+*/
+public class ExpandableViewState extends ViewState {
+
+    private static final int TAG_ANIMATOR_HEIGHT = R.id.height_animator_tag;
+    private static final int TAG_ANIMATOR_TOP_INSET = R.id.top_inset_animator_tag;
+    private static final int TAG_ANIMATOR_SHADOW_ALPHA = R.id.shadow_alpha_animator_tag;
+    private static final int TAG_END_HEIGHT = R.id.height_animator_end_value_tag;
+    private static final int TAG_END_TOP_INSET = R.id.top_inset_animator_end_value_tag;
+    private static final int TAG_END_SHADOW_ALPHA = R.id.shadow_alpha_animator_end_value_tag;
+    private static final int TAG_START_HEIGHT = R.id.height_animator_start_value_tag;
+    private static final int TAG_START_TOP_INSET = R.id.top_inset_animator_start_value_tag;
+    private static final int TAG_START_SHADOW_ALPHA = R.id.shadow_alpha_animator_start_value_tag;
+
+    // These are flags such that we can create masks for filtering.
+
+    /**
+     * No known location. This is the default and should not be set after an invocation of the
+     * algorithm.
+     */
+    public static final int LOCATION_UNKNOWN = 0x00;
+
+    /**
+     * The location is the first heads up notification, so on the very top.
+     */
+    public static final int LOCATION_FIRST_HUN = 0x01;
+
+    /**
+     * The location is hidden / scrolled away on the top.
+     */
+    public static final int LOCATION_HIDDEN_TOP = 0x02;
+
+    /**
+     * The location is in the main area of the screen and visible.
+     */
+    public static final int LOCATION_MAIN_AREA = 0x04;
+
+    /**
+     * The location is in the bottom stack and it's peeking
+     */
+    public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x08;
+
+    /**
+     * The location is in the bottom stack and it's hidden.
+     */
+    public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x10;
+
+    /**
+     * The view isn't laid out at all.
+     */
+    public static final int LOCATION_GONE = 0x40;
+
+    /**
+     * The visible locations of a view.
+     */
+    public static final int VISIBLE_LOCATIONS = ExpandableViewState.LOCATION_FIRST_HUN
+            | ExpandableViewState.LOCATION_MAIN_AREA;
+
+    public int height;
+    public boolean dimmed;
+    public boolean dark;
+    public boolean hideSensitive;
+    public boolean belowSpeedBump;
+    public float shadowAlpha;
+    public boolean inShelf;
+
+    /**
+     * A state indicating whether a headsup is currently fully visible, even when not scrolled.
+     * Only valid if the view is heads upped.
+     */
+    public boolean headsUpIsVisible;
+
+    /**
+     * How much the child overlaps with the previous child on top. This is used to
+     * show the background properly when the child on top is translating away.
+     */
+    public int clipTopAmount;
+
+    /**
+     * The index of the view, only accounting for views not equal to GONE
+     */
+    public int notGoneIndex;
+
+    /**
+     * The location this view is currently rendered at.
+     *
+     * <p>See <code>LOCATION_</code> flags.</p>
+     */
+    public int location;
+
+    @Override
+    public void copyFrom(ViewState viewState) {
+        super.copyFrom(viewState);
+        if (viewState instanceof ExpandableViewState) {
+            ExpandableViewState svs = (ExpandableViewState) viewState;
+            height = svs.height;
+            dimmed = svs.dimmed;
+            shadowAlpha = svs.shadowAlpha;
+            dark = svs.dark;
+            hideSensitive = svs.hideSensitive;
+            belowSpeedBump = svs.belowSpeedBump;
+            clipTopAmount = svs.clipTopAmount;
+            notGoneIndex = svs.notGoneIndex;
+            location = svs.location;
+            headsUpIsVisible = svs.headsUpIsVisible;
+        }
+    }
+
+    /**
+     * Applies a {@link ExpandableViewState} to a {@link ExpandableView}.
+     */
+    @Override
+    public void applyToView(View view) {
+        super.applyToView(view);
+        if (view instanceof ExpandableView) {
+            ExpandableView expandableView = (ExpandableView) view;
+
+            int height = expandableView.getActualHeight();
+            int newHeight = this.height;
+
+            // apply height
+            if (height != newHeight) {
+                expandableView.setActualHeight(newHeight, false /* notifyListeners */);
+            }
+
+            float shadowAlpha = expandableView.getShadowAlpha();
+            float newShadowAlpha = this.shadowAlpha;
+
+            // apply shadowAlpha
+            if (shadowAlpha != newShadowAlpha) {
+                expandableView.setShadowAlpha(newShadowAlpha);
+            }
+
+            // apply dimming
+            expandableView.setDimmed(this.dimmed, false /* animate */);
+
+            // apply hiding sensitive
+            expandableView.setHideSensitive(
+                    this.hideSensitive, false /* animated */, 0 /* delay */, 0 /* duration */);
+
+            // apply below shelf speed bump
+            expandableView.setBelowSpeedBump(this.belowSpeedBump);
+
+            // apply dark
+            expandableView.setDark(this.dark, false /* animate */, 0 /* delay */);
+
+            // apply clipping
+            float oldClipTopAmount = expandableView.getClipTopAmount();
+            if (oldClipTopAmount != this.clipTopAmount) {
+                expandableView.setClipTopAmount(this.clipTopAmount);
+            }
+
+            expandableView.setTransformingInShelf(false);
+            expandableView.setInShelf(inShelf);
+
+            if (headsUpIsVisible) {
+                expandableView.setHeadsUpIsVisible();
+            }
+        }
+    }
+
+    @Override
+    public void animateTo(View child, AnimationProperties properties) {
+        super.animateTo(child, properties);
+        if (!(child instanceof ExpandableView)) {
+            return;
+        }
+        ExpandableView expandableView = (ExpandableView) child;
+        AnimationFilter animationFilter = properties.getAnimationFilter();
+
+        // start height animation
+        if (this.height != expandableView.getActualHeight()) {
+            startHeightAnimation(expandableView, properties);
+        }  else {
+            abortAnimation(child, TAG_ANIMATOR_HEIGHT);
+        }
+
+        // start shadow alpha animation
+        if (this.shadowAlpha != expandableView.getShadowAlpha()) {
+            startShadowAlphaAnimation(expandableView, properties);
+        } else {
+            abortAnimation(child, TAG_ANIMATOR_SHADOW_ALPHA);
+        }
+
+        // start top inset animation
+        if (this.clipTopAmount != expandableView.getClipTopAmount()) {
+            startInsetAnimation(expandableView, properties);
+        } else {
+            abortAnimation(child, TAG_ANIMATOR_TOP_INSET);
+        }
+
+        // start dimmed animation
+        expandableView.setDimmed(this.dimmed, animationFilter.animateDimmed);
+
+        // apply below the speed bump
+        expandableView.setBelowSpeedBump(this.belowSpeedBump);
+
+        // start hiding sensitive animation
+        expandableView.setHideSensitive(this.hideSensitive, animationFilter.animateHideSensitive,
+                properties.delay, properties.duration);
+
+        // start dark animation
+        expandableView.setDark(this.dark, animationFilter.animateDark, properties.delay);
+
+        if (properties.wasAdded(child) && !hidden) {
+            expandableView.performAddAnimation(properties.delay, properties.duration,
+                    false /* isHeadsUpAppear */);
+        }
+
+        if (!expandableView.isInShelf() && this.inShelf) {
+            expandableView.setTransformingInShelf(true);
+        }
+        expandableView.setInShelf(this.inShelf);
+
+        if (headsUpIsVisible) {
+            expandableView.setHeadsUpIsVisible();
+        }
+    }
+
+    private void startHeightAnimation(final ExpandableView child, AnimationProperties properties) {
+        Integer previousStartValue = getChildTag(child, TAG_START_HEIGHT);
+        Integer previousEndValue = getChildTag(child, TAG_END_HEIGHT);
+        int newEndValue = this.height;
+        if (previousEndValue != null && previousEndValue == newEndValue) {
+            return;
+        }
+        ValueAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_HEIGHT);
+        AnimationFilter filter = properties.getAnimationFilter();
+        if (!filter.animateHeight) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                int relativeDiff = newEndValue - previousEndValue;
+                int newStartValue = previousStartValue + relativeDiff;
+                values[0].setIntValues(newStartValue, newEndValue);
+                child.setTag(TAG_START_HEIGHT, newStartValue);
+                child.setTag(TAG_END_HEIGHT, newEndValue);
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                child.setActualHeight(newEndValue, false);
+                return;
+            }
+        }
+
+        ValueAnimator animator = ValueAnimator.ofInt(child.getActualHeight(), newEndValue);
+        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                child.setActualHeight((int) animation.getAnimatedValue(),
+                        false /* notifyListeners */);
+            }
+        });
+        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
+        animator.setDuration(newDuration);
+        if (properties.delay > 0 && (previousAnimator == null
+                || previousAnimator.getAnimatedFraction() == 0)) {
+            animator.setStartDelay(properties.delay);
+        }
+        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
+        if (listener != null) {
+            animator.addListener(listener);
+        }
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            boolean mWasCancelled;
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                child.setTag(TAG_ANIMATOR_HEIGHT, null);
+                child.setTag(TAG_START_HEIGHT, null);
+                child.setTag(TAG_END_HEIGHT, null);
+                child.setActualHeightAnimating(false);
+                if (!mWasCancelled && child instanceof ExpandableNotificationRow) {
+                    ((ExpandableNotificationRow) child).setGroupExpansionChanging(
+                            false /* isExpansionChanging */);
+                }
+            }
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mWasCancelled = false;
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mWasCancelled = true;
+            }
+        });
+        startAnimator(animator, listener);
+        child.setTag(TAG_ANIMATOR_HEIGHT, animator);
+        child.setTag(TAG_START_HEIGHT, child.getActualHeight());
+        child.setTag(TAG_END_HEIGHT, newEndValue);
+        child.setActualHeightAnimating(true);
+    }
+
+    private void startShadowAlphaAnimation(final ExpandableView child,
+            AnimationProperties properties) {
+        Float previousStartValue = getChildTag(child, TAG_START_SHADOW_ALPHA);
+        Float previousEndValue = getChildTag(child, TAG_END_SHADOW_ALPHA);
+        float newEndValue = this.shadowAlpha;
+        if (previousEndValue != null && previousEndValue == newEndValue) {
+            return;
+        }
+        ValueAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_SHADOW_ALPHA);
+        AnimationFilter filter = properties.getAnimationFilter();
+        if (!filter.animateShadowAlpha) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                float relativeDiff = newEndValue - previousEndValue;
+                float newStartValue = previousStartValue + relativeDiff;
+                values[0].setFloatValues(newStartValue, newEndValue);
+                child.setTag(TAG_START_SHADOW_ALPHA, newStartValue);
+                child.setTag(TAG_END_SHADOW_ALPHA, newEndValue);
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                child.setShadowAlpha(newEndValue);
+                return;
+            }
+        }
+
+        ValueAnimator animator = ValueAnimator.ofFloat(child.getShadowAlpha(), newEndValue);
+        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                child.setShadowAlpha((float) animation.getAnimatedValue());
+            }
+        });
+        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
+        animator.setDuration(newDuration);
+        if (properties.delay > 0 && (previousAnimator == null
+                || previousAnimator.getAnimatedFraction() == 0)) {
+            animator.setStartDelay(properties.delay);
+        }
+        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
+        if (listener != null) {
+            animator.addListener(listener);
+        }
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                child.setTag(TAG_ANIMATOR_SHADOW_ALPHA, null);
+                child.setTag(TAG_START_SHADOW_ALPHA, null);
+                child.setTag(TAG_END_SHADOW_ALPHA, null);
+            }
+        });
+        startAnimator(animator, listener);
+        child.setTag(TAG_ANIMATOR_SHADOW_ALPHA, animator);
+        child.setTag(TAG_START_SHADOW_ALPHA, child.getShadowAlpha());
+        child.setTag(TAG_END_SHADOW_ALPHA, newEndValue);
+    }
+
+    private void startInsetAnimation(final ExpandableView child, AnimationProperties properties) {
+        Integer previousStartValue = getChildTag(child, TAG_START_TOP_INSET);
+        Integer previousEndValue = getChildTag(child, TAG_END_TOP_INSET);
+        int newEndValue = this.clipTopAmount;
+        if (previousEndValue != null && previousEndValue == newEndValue) {
+            return;
+        }
+        ValueAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TOP_INSET);
+        AnimationFilter filter = properties.getAnimationFilter();
+        if (!filter.animateTopInset) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                int relativeDiff = newEndValue - previousEndValue;
+                int newStartValue = previousStartValue + relativeDiff;
+                values[0].setIntValues(newStartValue, newEndValue);
+                child.setTag(TAG_START_TOP_INSET, newStartValue);
+                child.setTag(TAG_END_TOP_INSET, newEndValue);
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                child.setClipTopAmount(newEndValue);
+                return;
+            }
+        }
+
+        ValueAnimator animator = ValueAnimator.ofInt(child.getClipTopAmount(), newEndValue);
+        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                child.setClipTopAmount((int) animation.getAnimatedValue());
+            }
+        });
+        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
+        animator.setDuration(newDuration);
+        if (properties.delay > 0 && (previousAnimator == null
+                || previousAnimator.getAnimatedFraction() == 0)) {
+            animator.setStartDelay(properties.delay);
+        }
+        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
+        if (listener != null) {
+            animator.addListener(listener);
+        }
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                child.setTag(TAG_ANIMATOR_TOP_INSET, null);
+                child.setTag(TAG_START_TOP_INSET, null);
+                child.setTag(TAG_END_TOP_INSET, null);
+            }
+        });
+        startAnimator(animator, listener);
+        child.setTag(TAG_ANIMATOR_TOP_INSET, animator);
+        child.setTag(TAG_START_TOP_INSET, child.getClipTopAmount());
+        child.setTag(TAG_END_TOP_INSET, newEndValue);
+    }
+
+    /**
+     * Get the end value of the height animation running on a view or the actualHeight
+     * if no animation is running.
+     */
+    public static int getFinalActualHeight(ExpandableView view) {
+        if (view == null) {
+            return 0;
+        }
+        ValueAnimator heightAnimator = getChildTag(view, TAG_ANIMATOR_HEIGHT);
+        if (heightAnimator == null) {
+            return view.getActualHeight();
+        } else {
+            return getChildTag(view, TAG_END_HEIGHT);
+        }
+    }
+
+    @Override
+    public void cancelAnimations(View view) {
+        super.cancelAnimations(view);
+        Animator animator = getChildTag(view, TAG_ANIMATOR_HEIGHT);
+        if (animator != null) {
+            animator.cancel();
+        }
+        animator = getChildTag(view, TAG_ANIMATOR_SHADOW_ALPHA);
+        if (animator != null) {
+            animator.cancel();
+        }
+        animator = getChildTag(view, TAG_ANIMATOR_TOP_INSET);
+        if (animator != null) {
+            animator.cancel();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java
new file mode 100644
index 0000000..24e1f32
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java
@@ -0,0 +1,52 @@
+/*
+ * 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.systemui.statusbar.notification.stack;
+
+import android.graphics.Path;
+import android.view.animation.PathInterpolator;
+
+/**
+ * An interpolator specifically designed for the appear animation of heads up notifications.
+ */
+public class HeadsUpAppearInterpolator extends PathInterpolator {
+
+    private static float X1 = 250f;
+    private static float X2 = 200f;
+    private static float XTOT = (X1 + X2);;
+
+    public HeadsUpAppearInterpolator() {
+        super(getAppearPath());
+    }
+
+    private static Path getAppearPath() {
+        Path path = new Path();
+        path.moveTo(0, 0);
+        float y1 = 90f;
+        float y2 = 80f;
+        path.cubicTo(X1 * 0.8f / XTOT, y1 / y2,
+                X1 * 0.8f / XTOT, y1 / y2,
+                X1 / XTOT, y1 / y2);
+        path.cubicTo((X1 + X2 * 0.4f) / XTOT, y1 / y2,
+                (X1 + X2 * 0.2f) / XTOT, 1.0f,
+                1.0f , 1.0f);
+        return path;
+    }
+
+    public static float getFractionUntilOvershoot() {
+        return X1 / XTOT;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
new file mode 100644
index 0000000..3d44e3c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -0,0 +1,1325 @@
+/*
+ * 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.systemui.statusbar.notification.stack;
+
+import android.app.Notification;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.drawable.ColorDrawable;
+import android.service.notification.StatusBarNotification;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.NotificationHeaderView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RemoteViews;
+import android.widget.TextView;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationHeaderUtil;
+import com.android.systemui.statusbar.notification.row.HybridGroupManager;
+import com.android.systemui.statusbar.notification.row.HybridNotificationView;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A container containing child notifications
+ */
+public class NotificationChildrenContainer extends ViewGroup {
+
+    @VisibleForTesting
+    static final int NUMBER_OF_CHILDREN_WHEN_COLLAPSED = 2;
+    @VisibleForTesting
+    static final int NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED = 5;
+    @VisibleForTesting
+    static final int NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED = 8;
+    @VisibleForTesting
+    static final int NUMBER_OF_CHILDREN_WHEN_AMBIENT = 1;
+    private static final AnimationProperties ALPHA_FADE_IN = new AnimationProperties() {
+        private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
+
+        @Override
+        public AnimationFilter getAnimationFilter() {
+            return mAnimationFilter;
+        }
+    }.setDuration(200);
+
+    private final List<View> mDividers = new ArrayList<>();
+    private final List<ExpandableNotificationRow> mChildren = new ArrayList<>();
+    private final HybridGroupManager mHybridGroupManager;
+    private int mChildPadding;
+    private int mDividerHeight;
+    private float mDividerAlpha;
+    private int mNotificationHeaderMargin;
+
+    private int mNotificatonTopPadding;
+    private float mCollapsedBottompadding;
+    private boolean mChildrenExpanded;
+    private ExpandableNotificationRow mContainingNotification;
+    private TextView mOverflowNumber;
+    private ViewState mGroupOverFlowState;
+    private int mRealHeight;
+    private boolean mUserLocked;
+    private int mActualHeight;
+    private boolean mNeverAppliedGroupState;
+    private int mHeaderHeight;
+
+    /**
+     * Whether or not individual notifications that are part of this container will have shadows.
+     */
+    private boolean mEnableShadowOnChildNotifications;
+
+    private NotificationHeaderView mNotificationHeader;
+    private NotificationViewWrapper mNotificationHeaderWrapper;
+    private NotificationHeaderView mNotificationHeaderLowPriority;
+    private NotificationViewWrapper mNotificationHeaderWrapperLowPriority;
+    private ViewGroup mNotificationHeaderAmbient;
+    private NotificationViewWrapper mNotificationHeaderWrapperAmbient;
+    private NotificationHeaderUtil mHeaderUtil;
+    private ViewState mHeaderViewState;
+    private int mClipBottomAmount;
+    private boolean mIsLowPriority;
+    private OnClickListener mHeaderClickListener;
+    private ViewGroup mCurrentHeader;
+
+    private boolean mShowDividersWhenExpanded;
+    private boolean mHideDividersDuringExpand;
+    private int mTranslationForHeader;
+    private int mCurrentHeaderTranslation = 0;
+    private float mHeaderVisibleAmount = 1.0f;
+
+    public NotificationChildrenContainer(Context context) {
+        this(context, null);
+    }
+
+    public NotificationChildrenContainer(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public NotificationChildrenContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public NotificationChildrenContainer(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mHybridGroupManager = new HybridGroupManager(getContext(), this);
+        initDimens();
+        setClipChildren(false);
+    }
+
+    private void initDimens() {
+        Resources res = getResources();
+        mChildPadding = res.getDimensionPixelSize(R.dimen.notification_children_padding);
+        mDividerHeight = res.getDimensionPixelSize(
+                R.dimen.notification_children_container_divider_height);
+        mDividerAlpha = res.getFloat(R.dimen.notification_divider_alpha);
+        mNotificationHeaderMargin = res.getDimensionPixelSize(
+                R.dimen.notification_children_container_margin_top);
+        mNotificatonTopPadding = res.getDimensionPixelSize(
+                R.dimen.notification_children_container_top_padding);
+        mHeaderHeight = mNotificationHeaderMargin + mNotificatonTopPadding;
+        mCollapsedBottompadding = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin);
+        mEnableShadowOnChildNotifications =
+                res.getBoolean(R.bool.config_enableShadowOnChildNotifications);
+        mShowDividersWhenExpanded =
+                res.getBoolean(R.bool.config_showDividersWhenGroupNotificationExpanded);
+        mHideDividersDuringExpand =
+                res.getBoolean(R.bool.config_hideDividersDuringExpand);
+        mTranslationForHeader = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin)
+                - mNotificationHeaderMargin;
+        mHybridGroupManager.initDimens();
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
+        for (int i = 0; i < childCount; i++) {
+            View child = mChildren.get(i);
+            // We need to layout all children even the GONE ones, such that the heights are
+            // calculated correctly as they are used to calculate how many we can fit on the screen
+            child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
+            mDividers.get(i).layout(0, 0, getWidth(), mDividerHeight);
+        }
+        if (mOverflowNumber != null) {
+            boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+            int left = (isRtl ? 0 : getWidth() - mOverflowNumber.getMeasuredWidth());
+            int right = left + mOverflowNumber.getMeasuredWidth();
+            mOverflowNumber.layout(left, 0, right, mOverflowNumber.getMeasuredHeight());
+        }
+        if (mNotificationHeader != null) {
+            mNotificationHeader.layout(0, 0, mNotificationHeader.getMeasuredWidth(),
+                    mNotificationHeader.getMeasuredHeight());
+        }
+        if (mNotificationHeaderLowPriority != null) {
+            mNotificationHeaderLowPriority.layout(0, 0,
+                    mNotificationHeaderLowPriority.getMeasuredWidth(),
+                    mNotificationHeaderLowPriority.getMeasuredHeight());
+        }
+        if (mNotificationHeaderAmbient != null) {
+            mNotificationHeaderAmbient.layout(0, 0,
+                    mNotificationHeaderAmbient.getMeasuredWidth(),
+                    mNotificationHeaderAmbient.getMeasuredHeight());
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
+        boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
+        int size = MeasureSpec.getSize(heightMeasureSpec);
+        int newHeightSpec = heightMeasureSpec;
+        if (hasFixedHeight || isHeightLimited) {
+            newHeightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
+        }
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        if (mOverflowNumber != null) {
+            mOverflowNumber.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
+                    newHeightSpec);
+        }
+        int dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY);
+        int height = mNotificationHeaderMargin + mNotificatonTopPadding;
+        int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
+        int collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
+        int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1;
+        for (int i = 0; i < childCount; i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            // We need to measure all children even the GONE ones, such that the heights are
+            // calculated correctly as they are used to calculate how many we can fit on the screen.
+            boolean isOverflow = i == overflowIndex;
+            child.setSingleLineWidthIndention(isOverflow && mOverflowNumber != null &&
+                    !mContainingNotification.isShowingAmbient()
+                    ? mOverflowNumber.getMeasuredWidth() : 0);
+            child.measure(widthMeasureSpec, newHeightSpec);
+            // layout the divider
+            View divider = mDividers.get(i);
+            divider.measure(widthMeasureSpec, dividerHeightSpec);
+            if (child.getVisibility() != GONE) {
+                height += child.getMeasuredHeight() + mDividerHeight;
+            }
+        }
+        mRealHeight = height;
+        if (heightMode != MeasureSpec.UNSPECIFIED) {
+            height = Math.min(height, size);
+        }
+
+        int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
+        if (mNotificationHeader != null) {
+            mNotificationHeader.measure(widthMeasureSpec, headerHeightSpec);
+        }
+        if (mNotificationHeaderLowPriority != null) {
+            headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
+            mNotificationHeaderLowPriority.measure(widthMeasureSpec, headerHeightSpec);
+        }
+        if (mNotificationHeaderAmbient != null) {
+            headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
+            mNotificationHeaderAmbient.measure(widthMeasureSpec, headerHeightSpec);
+        }
+
+        setMeasuredDimension(width, height);
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
+    @Override
+    public boolean pointInView(float localX, float localY, float slop) {
+        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
+                localY < (mRealHeight + slop);
+    }
+
+    /**
+     * Add a child notification to this view.
+     *
+     * @param row the row to add
+     * @param childIndex the index to add it at, if -1 it will be added at the end
+     */
+    public void addNotification(ExpandableNotificationRow row, int childIndex) {
+        int newIndex = childIndex < 0 ? mChildren.size() : childIndex;
+        mChildren.add(newIndex, row);
+        addView(row);
+        row.setUserLocked(mUserLocked);
+
+        View divider = inflateDivider();
+        addView(divider);
+        mDividers.add(newIndex, divider);
+
+        updateGroupOverflow();
+        row.setContentTransformationAmount(0, false /* isLastChild */);
+        // It doesn't make sense to keep old animations around, lets cancel them!
+        ExpandableNotificationRow.NotificationViewState viewState = row.getViewState();
+        if (viewState != null) {
+            viewState.cancelAnimations(row);
+            row.cancelAppearDrawing();
+        }
+    }
+
+    public void removeNotification(ExpandableNotificationRow row) {
+        int childIndex = mChildren.indexOf(row);
+        mChildren.remove(row);
+        removeView(row);
+
+        final View divider = mDividers.remove(childIndex);
+        removeView(divider);
+        getOverlay().add(divider);
+        CrossFadeHelper.fadeOut(divider, new Runnable() {
+            @Override
+            public void run() {
+                getOverlay().remove(divider);
+            }
+        });
+
+        row.setSystemChildExpanded(false);
+        row.setUserLocked(false);
+        updateGroupOverflow();
+        if (!row.isRemoved()) {
+            mHeaderUtil.restoreNotificationHeader(row);
+        }
+    }
+
+    /**
+     * @return The number of notification children in the container.
+     */
+    public int getNotificationChildCount() {
+        return mChildren.size();
+    }
+
+    public void recreateNotificationHeader(OnClickListener listener) {
+        mHeaderClickListener = listener;
+        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
+        final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
+                notification.getNotification());
+        RemoteViews header = builder.makeNotificationHeader(false /* ambient */);
+        if (mNotificationHeader == null) {
+            mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
+            final View expandButton = mNotificationHeader.findViewById(
+                    com.android.internal.R.id.expand_button);
+            expandButton.setVisibility(VISIBLE);
+            mNotificationHeader.setOnClickListener(mHeaderClickListener);
+            mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
+                    mNotificationHeader, mContainingNotification);
+            addView(mNotificationHeader, 0);
+            invalidate();
+        } else {
+            header.reapply(getContext(), mNotificationHeader);
+        }
+        mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
+        recreateLowPriorityHeader(builder);
+        recreateAmbientHeader(builder);
+        updateHeaderVisibility(false /* animate */);
+        updateChildrenHeaderAppearance();
+    }
+
+    private void recreateAmbientHeader(Notification.Builder builder) {
+        RemoteViews header;
+        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
+        if (builder == null) {
+            builder = Notification.Builder.recoverBuilder(getContext(),
+                    notification.getNotification());
+        }
+        header = builder.makeNotificationHeader(true /* ambient */);
+        if (mNotificationHeaderAmbient == null) {
+            mNotificationHeaderAmbient = (ViewGroup) header.apply(getContext(), this);
+            mNotificationHeaderWrapperAmbient = NotificationViewWrapper.wrap(getContext(),
+                    mNotificationHeaderAmbient, mContainingNotification);
+            mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
+            addView(mNotificationHeaderAmbient, 0);
+            invalidate();
+        } else {
+            header.reapply(getContext(), mNotificationHeaderAmbient);
+        }
+        resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, calculateDesiredHeader());
+        mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
+    }
+
+    /**
+     * Recreate the low-priority header.
+     *
+     * @param builder a builder to reuse. Otherwise the builder will be recovered.
+     */
+    private void recreateLowPriorityHeader(Notification.Builder builder) {
+        RemoteViews header;
+        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
+        if (mIsLowPriority) {
+            if (builder == null) {
+                builder = Notification.Builder.recoverBuilder(getContext(),
+                        notification.getNotification());
+            }
+            header = builder.makeLowPriorityContentView(true /* useRegularSubtext */);
+            if (mNotificationHeaderLowPriority == null) {
+                mNotificationHeaderLowPriority = (NotificationHeaderView) header.apply(getContext(),
+                        this);
+                final View expandButton = mNotificationHeaderLowPriority.findViewById(
+                        com.android.internal.R.id.expand_button);
+                expandButton.setVisibility(VISIBLE);
+                mNotificationHeaderLowPriority.setOnClickListener(mHeaderClickListener);
+                mNotificationHeaderWrapperLowPriority = NotificationViewWrapper.wrap(getContext(),
+                        mNotificationHeaderLowPriority, mContainingNotification);
+                addView(mNotificationHeaderLowPriority, 0);
+                invalidate();
+            } else {
+                header.reapply(getContext(), mNotificationHeaderLowPriority);
+            }
+            mNotificationHeaderWrapperLowPriority.onContentUpdated(mContainingNotification);
+            resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, calculateDesiredHeader());
+        } else {
+            removeView(mNotificationHeaderLowPriority);
+            mNotificationHeaderLowPriority = null;
+            mNotificationHeaderWrapperLowPriority = null;
+        }
+    }
+
+    public void updateChildrenHeaderAppearance() {
+        mHeaderUtil.updateChildrenHeaderAppearance();
+    }
+
+    public void updateGroupOverflow() {
+        int childCount = mChildren.size();
+        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
+        if (childCount > maxAllowedVisibleChildren) {
+            int number = childCount - maxAllowedVisibleChildren;
+            mOverflowNumber = mHybridGroupManager.bindOverflowNumber(mOverflowNumber, number);
+            if (mContainingNotification.isShowingAmbient()) {
+                ExpandableNotificationRow overflowView = mChildren.get(0);
+                HybridNotificationView ambientSingleLineView = overflowView == null ? null
+                        : overflowView.getAmbientSingleLineView();
+                if (ambientSingleLineView != null) {
+                    mHybridGroupManager.bindOverflowNumberAmbient(
+                            ambientSingleLineView.getTitleView(),
+                            mContainingNotification.getStatusBarNotification().getNotification(),
+                            number);
+                }
+            }
+            if (mGroupOverFlowState == null) {
+                mGroupOverFlowState = new ViewState();
+                mNeverAppliedGroupState = true;
+            }
+        } else if (mOverflowNumber != null) {
+            removeView(mOverflowNumber);
+            if (isShown() && isAttachedToWindow()) {
+                final View removedOverflowNumber = mOverflowNumber;
+                addTransientView(removedOverflowNumber, getTransientViewCount());
+                CrossFadeHelper.fadeOut(removedOverflowNumber, new Runnable() {
+                    @Override
+                    public void run() {
+                        removeTransientView(removedOverflowNumber);
+                    }
+                });
+            }
+            mOverflowNumber = null;
+            mGroupOverFlowState = null;
+        }
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateGroupOverflow();
+    }
+
+    private View inflateDivider() {
+        return LayoutInflater.from(mContext).inflate(
+                R.layout.notification_children_divider, this, false);
+    }
+
+    public List<ExpandableNotificationRow> getNotificationChildren() {
+        return mChildren;
+    }
+
+    /**
+     * Apply the order given in the list to the children.
+     *
+     * @param childOrder the new list order
+     * @param visualStabilityManager
+     * @param callback
+     * @return whether the list order has changed
+     */
+    public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
+            VisualStabilityManager visualStabilityManager,
+            VisualStabilityManager.Callback callback) {
+        if (childOrder == null) {
+            return false;
+        }
+        boolean result = false;
+        for (int i = 0; i < mChildren.size() && i < childOrder.size(); i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            ExpandableNotificationRow desiredChild = childOrder.get(i);
+            if (child != desiredChild) {
+                if (visualStabilityManager.canReorderNotification(desiredChild)) {
+                    mChildren.remove(desiredChild);
+                    mChildren.add(i, desiredChild);
+                    result = true;
+                } else {
+                    visualStabilityManager.addReorderingAllowedCallback(callback);
+                }
+            }
+        }
+        updateExpansionStates();
+        return result;
+    }
+
+    private void updateExpansionStates() {
+        if (mChildrenExpanded || mUserLocked) {
+            // we don't modify it the group is expanded or if we are expanding it
+            return;
+        }
+        int size = mChildren.size();
+        for (int i = 0; i < size; i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            child.setSystemChildExpanded(i == 0 && size == 1);
+        }
+    }
+
+    /**
+     *
+     * @return the intrinsic size of this children container, i.e the natural fully expanded state
+     */
+    public int getIntrinsicHeight() {
+        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
+        return getIntrinsicHeight(maxAllowedVisibleChildren);
+    }
+
+    /**
+     * @return the intrinsic height with a number of children given
+     *         in @param maxAllowedVisibleChildren
+     */
+    private int getIntrinsicHeight(float maxAllowedVisibleChildren) {
+        if (showingAsLowPriority()) {
+            return mNotificationHeaderLowPriority.getHeight();
+        }
+        int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation;
+        int visibleChildren = 0;
+        int childCount = mChildren.size();
+        boolean firstChild = true;
+        float expandFactor = 0;
+        if (mUserLocked) {
+            expandFactor = getGroupExpandFraction();
+        }
+        boolean childrenExpanded = mChildrenExpanded || mContainingNotification.isShowingAmbient();
+        for (int i = 0; i < childCount; i++) {
+            if (visibleChildren >= maxAllowedVisibleChildren) {
+                break;
+            }
+            if (!firstChild) {
+                if (mUserLocked) {
+                    intrinsicHeight += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
+                            expandFactor);
+                } else {
+                    intrinsicHeight += childrenExpanded ? mDividerHeight : mChildPadding;
+                }
+            } else {
+                if (mUserLocked) {
+                    intrinsicHeight += NotificationUtils.interpolate(
+                            0,
+                            mNotificatonTopPadding + mDividerHeight,
+                            expandFactor);
+                } else {
+                    intrinsicHeight += childrenExpanded
+                            ? mNotificatonTopPadding + mDividerHeight
+                            : 0;
+                }
+                firstChild = false;
+            }
+            ExpandableNotificationRow child = mChildren.get(i);
+            intrinsicHeight += child.getIntrinsicHeight();
+            visibleChildren++;
+        }
+        if (mUserLocked) {
+            intrinsicHeight += NotificationUtils.interpolate(mCollapsedBottompadding, 0.0f,
+                    expandFactor);
+        } else if (!childrenExpanded) {
+            intrinsicHeight += mCollapsedBottompadding;
+        }
+        return intrinsicHeight;
+    }
+
+    /**
+     * Update the state of all its children based on a linear layout algorithm.
+     *  @param resultState the state to update
+     * @param parentState the state of the parent
+     * @param ambientState
+     */
+    public void getState(StackScrollState resultState, ExpandableViewState parentState,
+            AmbientState ambientState) {
+        int childCount = mChildren.size();
+        int yPosition = mNotificationHeaderMargin + mCurrentHeaderTranslation;
+        boolean firstChild = true;
+        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
+        int lastVisibleIndex = maxAllowedVisibleChildren - 1;
+        int firstOverflowIndex = lastVisibleIndex + 1;
+        float expandFactor = 0;
+        boolean expandingToExpandedGroup = mUserLocked && !showingAsLowPriority();
+        if (mUserLocked) {
+            expandFactor = getGroupExpandFraction();
+            firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
+        }
+
+        boolean childrenExpandedAndNotAnimating = mChildrenExpanded
+                && !mContainingNotification.isGroupExpansionChanging();
+        int launchTransitionCompensation = 0;
+        for (int i = 0; i < childCount; i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            if (!firstChild) {
+                if (expandingToExpandedGroup) {
+                    yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
+                            expandFactor);
+                } else {
+                    yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding;
+                }
+            } else {
+                if (expandingToExpandedGroup) {
+                    yPosition += NotificationUtils.interpolate(
+                            0,
+                            mNotificatonTopPadding + mDividerHeight,
+                            expandFactor);
+                } else {
+                    yPosition += mChildrenExpanded ? mNotificatonTopPadding + mDividerHeight : 0;
+                }
+                firstChild = false;
+            }
+
+            ExpandableViewState childState = resultState.getViewStateForView(child);
+            int intrinsicHeight = child.getIntrinsicHeight();
+            childState.height = intrinsicHeight;
+            childState.yTranslation = yPosition + launchTransitionCompensation;
+            childState.hidden = false;
+            // When the group is expanded, the children cast the shadows rather than the parent
+            // so use the parent's elevation here.
+            childState.zTranslation =
+                    (childrenExpandedAndNotAnimating && mEnableShadowOnChildNotifications)
+                    ? parentState.zTranslation
+                    : 0;
+            childState.dimmed = parentState.dimmed;
+            childState.dark = parentState.dark;
+            childState.hideSensitive = parentState.hideSensitive;
+            childState.belowSpeedBump = parentState.belowSpeedBump;
+            childState.clipTopAmount = 0;
+            childState.alpha = 0;
+            if (i < firstOverflowIndex) {
+                childState.alpha = showingAsLowPriority() ? expandFactor : 1.0f;
+            } else if (expandFactor == 1.0f && i <= lastVisibleIndex) {
+                childState.alpha = (mActualHeight - childState.yTranslation) / childState.height;
+                childState.alpha = Math.max(0.0f, Math.min(1.0f, childState.alpha));
+            }
+            childState.location = parentState.location;
+            childState.inShelf = parentState.inShelf;
+            yPosition += intrinsicHeight;
+            if (child.isExpandAnimationRunning()) {
+                launchTransitionCompensation = -ambientState.getExpandAnimationTopChange();
+            }
+
+        }
+        if (mOverflowNumber != null) {
+            ExpandableNotificationRow overflowView = mChildren.get(Math.min(
+                    getMaxAllowedVisibleChildren(true /* likeCollapsed */), childCount) - 1);
+            mGroupOverFlowState.copyFrom(resultState.getViewStateForView(overflowView));
+
+            if (mContainingNotification.isShowingAmbient()) {
+                mGroupOverFlowState.alpha = 0.0f;
+            } else if (!mChildrenExpanded) {
+                HybridNotificationView alignView = overflowView.getSingleLineView();
+                if (alignView != null) {
+                    View mirrorView = alignView.getTextView();
+                    if (mirrorView.getVisibility() == GONE) {
+                        mirrorView = alignView.getTitleView();
+                    }
+                    if (mirrorView.getVisibility() == GONE) {
+                        mirrorView = alignView;
+                    }
+                    mGroupOverFlowState.alpha = mirrorView.getAlpha();
+                    mGroupOverFlowState.yTranslation += NotificationUtils.getRelativeYOffset(
+                            mirrorView, overflowView);
+                }
+            } else {
+                mGroupOverFlowState.yTranslation += mNotificationHeaderMargin;
+                mGroupOverFlowState.alpha = 0.0f;
+            }
+        }
+        if (mNotificationHeader != null) {
+            if (mHeaderViewState == null) {
+                mHeaderViewState = new ViewState();
+            }
+            mHeaderViewState.initFrom(mNotificationHeader);
+            mHeaderViewState.zTranslation = childrenExpandedAndNotAnimating
+                    ? parentState.zTranslation
+                    : 0;
+            mHeaderViewState.yTranslation = mCurrentHeaderTranslation;
+            mHeaderViewState.alpha = mHeaderVisibleAmount;
+            // The hiding is done automatically by the alpha, otherwise we'll pick it up again
+            // in the next frame with the initFrom call above and have an invisible header
+            mHeaderViewState.hidden = false;
+        }
+    }
+
+    /**
+     * When moving into the bottom stack, the bottom visible child in an expanded group adjusts its
+     * height, children in the group after this are gone.
+     *
+     * @param child the child who's height to adjust.
+     * @param parentHeight the height of the parent.
+     * @param childState the state to update.
+     * @param yPosition the yPosition of the view.
+     * @return true if children after this one should be hidden.
+     */
+    private boolean updateChildStateForExpandedGroup(ExpandableNotificationRow child,
+            int parentHeight, ExpandableViewState childState, int yPosition) {
+        final int top = yPosition + child.getClipTopAmount();
+        final int intrinsicHeight = child.getIntrinsicHeight();
+        final int bottom = top + intrinsicHeight;
+        int newHeight = intrinsicHeight;
+        if (bottom >= parentHeight) {
+            // Child is either clipped or gone
+            newHeight = Math.max((parentHeight - top), 0);
+        }
+        childState.hidden = newHeight == 0;
+        childState.height = newHeight;
+        return childState.height != intrinsicHeight && !childState.hidden;
+    }
+
+    @VisibleForTesting
+    int getMaxAllowedVisibleChildren() {
+        return getMaxAllowedVisibleChildren(false /* likeCollapsed */);
+    }
+
+    @VisibleForTesting
+    int getMaxAllowedVisibleChildren(boolean likeCollapsed) {
+        if (mContainingNotification.isShowingAmbient()) {
+            return NUMBER_OF_CHILDREN_WHEN_AMBIENT;
+        }
+        if (!likeCollapsed && (mChildrenExpanded || mContainingNotification.isUserLocked())
+                && !showingAsLowPriority()) {
+            return NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
+        }
+        if (mIsLowPriority || !mContainingNotification.isOnKeyguard()
+                && (mContainingNotification.isExpanded() || mContainingNotification.isHeadsUp())) {
+            return NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED;
+        }
+        return NUMBER_OF_CHILDREN_WHEN_COLLAPSED;
+    }
+
+    public void applyState(StackScrollState state) {
+        int childCount = mChildren.size();
+        ViewState tmpState = new ViewState();
+        float expandFraction = 0.0f;
+        if (mUserLocked) {
+            expandFraction = getGroupExpandFraction();
+        }
+        final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
+                || (mChildrenExpanded && mShowDividersWhenExpanded)
+                || (mContainingNotification.isGroupExpansionChanging()
+                && !mHideDividersDuringExpand);
+        for (int i = 0; i < childCount; i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            ExpandableViewState viewState = state.getViewStateForView(child);
+            viewState.applyToView(child);
+
+            // layout the divider
+            View divider = mDividers.get(i);
+            tmpState.initFrom(divider);
+            tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
+            float alpha = mChildrenExpanded && viewState.alpha != 0 ? mDividerAlpha : 0;
+            if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
+                alpha = NotificationUtils.interpolate(0, 0.5f,
+                        Math.min(viewState.alpha, expandFraction));
+            }
+            tmpState.hidden = !dividersVisible;
+            tmpState.alpha = alpha;
+            tmpState.applyToView(divider);
+            // There is no fake shadow to be drawn on the children
+            child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
+        }
+        if (mGroupOverFlowState != null) {
+            mGroupOverFlowState.applyToView(mOverflowNumber);
+            mNeverAppliedGroupState = false;
+        }
+        if (mHeaderViewState != null) {
+            mHeaderViewState.applyToView(mNotificationHeader);
+        }
+        updateChildrenClipping();
+    }
+
+    private void updateChildrenClipping() {
+        if (mContainingNotification.hasExpandingChild()) {
+            return;
+        }
+        int childCount = mChildren.size();
+        int layoutEnd = mContainingNotification.getActualHeight() - mClipBottomAmount;
+        for (int i = 0; i < childCount; i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            if (child.getVisibility() == GONE) {
+                continue;
+            }
+            float childTop = child.getTranslationY();
+            float childBottom = childTop + child.getActualHeight();
+            boolean visible = true;
+            int clipBottomAmount = 0;
+            if (childTop > layoutEnd) {
+                visible = false;
+            } else if (childBottom > layoutEnd) {
+                clipBottomAmount = (int) (childBottom - layoutEnd);
+            }
+
+            boolean isVisible = child.getVisibility() == VISIBLE;
+            if (visible != isVisible) {
+                child.setVisibility(visible ? VISIBLE : INVISIBLE);
+            }
+
+            child.setClipBottomAmount(clipBottomAmount);
+        }
+    }
+
+    /**
+     * This is called when the children expansion has changed and positions the children properly
+     * for an appear animation.
+     *
+     * @param state the new state we animate to
+     */
+    public void prepareExpansionChanged(StackScrollState state) {
+        // TODO: do something that makes sense, like placing the invisible views correctly
+        return;
+    }
+
+    public void startAnimationToState(StackScrollState state, AnimationProperties properties) {
+        int childCount = mChildren.size();
+        ViewState tmpState = new ViewState();
+        float expandFraction = getGroupExpandFraction();
+        final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
+                || (mChildrenExpanded && mShowDividersWhenExpanded)
+                || (mContainingNotification.isGroupExpansionChanging()
+                && !mHideDividersDuringExpand);
+        for (int i = childCount - 1; i >= 0; i--) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            ExpandableViewState viewState = state.getViewStateForView(child);
+            viewState.animateTo(child, properties);
+
+            // layout the divider
+            View divider = mDividers.get(i);
+            tmpState.initFrom(divider);
+            tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
+            float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
+            if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
+                alpha = NotificationUtils.interpolate(0, 0.5f,
+                        Math.min(viewState.alpha, expandFraction));
+            }
+            tmpState.hidden = !dividersVisible;
+            tmpState.alpha = alpha;
+            tmpState.animateTo(divider, properties);
+            // There is no fake shadow to be drawn on the children
+            child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
+        }
+        if (mOverflowNumber != null) {
+            if (mNeverAppliedGroupState) {
+                float alpha = mGroupOverFlowState.alpha;
+                mGroupOverFlowState.alpha = 0;
+                mGroupOverFlowState.applyToView(mOverflowNumber);
+                mGroupOverFlowState.alpha = alpha;
+                mNeverAppliedGroupState = false;
+            }
+            mGroupOverFlowState.animateTo(mOverflowNumber, properties);
+        }
+        if (mNotificationHeader != null) {
+            mHeaderViewState.applyToView(mNotificationHeader);
+        }
+        updateChildrenClipping();
+    }
+
+    public ExpandableNotificationRow getViewAtPosition(float y) {
+        // find the view under the pointer, accounting for GONE views
+        final int count = mChildren.size();
+        for (int childIdx = 0; childIdx < count; childIdx++) {
+            ExpandableNotificationRow slidingChild = mChildren.get(childIdx);
+            float childTop = slidingChild.getTranslationY();
+            float top = childTop + slidingChild.getClipTopAmount();
+            float bottom = childTop + slidingChild.getActualHeight();
+            if (y >= top && y <= bottom) {
+                return slidingChild;
+            }
+        }
+        return null;
+    }
+
+    public void setChildrenExpanded(boolean childrenExpanded) {
+        mChildrenExpanded = childrenExpanded;
+        updateExpansionStates();
+        if (mNotificationHeader != null) {
+            mNotificationHeader.setExpanded(childrenExpanded);
+        }
+        final int count = mChildren.size();
+        for (int childIdx = 0; childIdx < count; childIdx++) {
+            ExpandableNotificationRow child = mChildren.get(childIdx);
+            child.setChildrenExpanded(childrenExpanded, false);
+        }
+    }
+
+    public void setContainingNotification(ExpandableNotificationRow parent) {
+        mContainingNotification = parent;
+        mHeaderUtil = new NotificationHeaderUtil(mContainingNotification);
+    }
+
+    public ExpandableNotificationRow getContainingNotification() {
+        return mContainingNotification;
+    }
+
+    public NotificationHeaderView getHeaderView() {
+        return mNotificationHeader;
+    }
+
+    public NotificationHeaderView getLowPriorityHeaderView() {
+        return mNotificationHeaderLowPriority;
+    }
+
+    @VisibleForTesting
+    public ViewGroup getCurrentHeaderView() {
+        return mCurrentHeader;
+    }
+
+    public void notifyShowAmbientChanged() {
+        updateHeaderVisibility(false);
+        updateGroupOverflow();
+    }
+
+    private void updateHeaderVisibility(boolean animate) {
+        ViewGroup desiredHeader;
+        ViewGroup currentHeader = mCurrentHeader;
+        desiredHeader = calculateDesiredHeader();
+
+        if (currentHeader == desiredHeader) {
+            return;
+        }
+        if (desiredHeader == mNotificationHeaderAmbient
+                || currentHeader == mNotificationHeaderAmbient) {
+            animate = false;
+        }
+
+        if (animate) {
+            if (desiredHeader != null && currentHeader != null) {
+                currentHeader.setVisibility(VISIBLE);
+                desiredHeader.setVisibility(VISIBLE);
+                NotificationViewWrapper visibleWrapper = getWrapperForView(desiredHeader);
+                NotificationViewWrapper hiddenWrapper = getWrapperForView(currentHeader);
+                visibleWrapper.transformFrom(hiddenWrapper);
+                hiddenWrapper.transformTo(visibleWrapper, () -> updateHeaderVisibility(false));
+                startChildAlphaAnimations(desiredHeader == mNotificationHeader);
+            } else {
+                animate = false;
+            }
+        }
+        if (!animate) {
+            if (desiredHeader != null) {
+                getWrapperForView(desiredHeader).setVisible(true);
+                desiredHeader.setVisibility(VISIBLE);
+            }
+            if (currentHeader != null) {
+                // Wrapper can be null if we were a low priority notification
+                // and just destroyed it by calling setIsLowPriority(false)
+                NotificationViewWrapper wrapper = getWrapperForView(currentHeader);
+                if (wrapper != null) {
+                    wrapper.setVisible(false);
+                }
+                currentHeader.setVisibility(INVISIBLE);
+            }
+        }
+
+        resetHeaderVisibilityIfNeeded(mNotificationHeader, desiredHeader);
+        resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, desiredHeader);
+        resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, desiredHeader);
+
+        mCurrentHeader = desiredHeader;
+    }
+
+    private void resetHeaderVisibilityIfNeeded(View header, View desiredHeader) {
+        if (header == null) {
+            return;
+        }
+        if (header != mCurrentHeader && header != desiredHeader) {
+            getWrapperForView(header).setVisible(false);
+            header.setVisibility(INVISIBLE);
+        }
+        if (header == desiredHeader && header.getVisibility() != VISIBLE) {
+            getWrapperForView(header).setVisible(true);
+            header.setVisibility(VISIBLE);
+        }
+    }
+
+    private ViewGroup calculateDesiredHeader() {
+        ViewGroup desiredHeader;
+        if (mContainingNotification.isShowingAmbient()) {
+            desiredHeader = mNotificationHeaderAmbient;
+        } else if (showingAsLowPriority()) {
+            desiredHeader = mNotificationHeaderLowPriority;
+        } else {
+            desiredHeader = mNotificationHeader;
+        }
+        return desiredHeader;
+    }
+
+    private void startChildAlphaAnimations(boolean toVisible) {
+        float target = toVisible ? 1.0f : 0.0f;
+        float start = 1.0f - target;
+        int childCount = mChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            if (i >= NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED) {
+                break;
+            }
+            ExpandableNotificationRow child = mChildren.get(i);
+            child.setAlpha(start);
+            ViewState viewState = new ViewState();
+            viewState.initFrom(child);
+            viewState.alpha = target;
+            ALPHA_FADE_IN.setDelay(i * 50);
+            viewState.animateTo(child, ALPHA_FADE_IN);
+        }
+    }
+
+
+    private void updateHeaderTransformation() {
+        if (mUserLocked && showingAsLowPriority()) {
+            float fraction = getGroupExpandFraction();
+            mNotificationHeaderWrapper.transformFrom(mNotificationHeaderWrapperLowPriority,
+                    fraction);
+            mNotificationHeader.setVisibility(VISIBLE);
+            mNotificationHeaderWrapperLowPriority.transformTo(mNotificationHeaderWrapper,
+                    fraction);
+        }
+
+    }
+
+    private NotificationViewWrapper getWrapperForView(View visibleHeader) {
+        if (visibleHeader == mNotificationHeader) {
+            return mNotificationHeaderWrapper;
+        }
+        if (visibleHeader == mNotificationHeaderAmbient) {
+            return mNotificationHeaderWrapperAmbient;
+        }
+        return mNotificationHeaderWrapperLowPriority;
+    }
+
+    /**
+     * Called when a groups expansion changes to adjust the background of the header view.
+     *
+     * @param expanded whether the group is expanded.
+     */
+    public void updateHeaderForExpansion(boolean expanded) {
+        if (mNotificationHeader != null) {
+            if (expanded) {
+                ColorDrawable cd = new ColorDrawable();
+                cd.setColor(mContainingNotification.calculateBgColor());
+                mNotificationHeader.setHeaderBackgroundDrawable(cd);
+            } else {
+                mNotificationHeader.setHeaderBackgroundDrawable(null);
+            }
+        }
+    }
+
+    public int getMaxContentHeight() {
+        if (showingAsLowPriority()) {
+            return getMinHeight(NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED, true
+                    /* likeHighPriority */);
+        }
+        int maxContentHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation
+                + mNotificatonTopPadding;
+        int visibleChildren = 0;
+        int childCount = mChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            if (visibleChildren >= NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED) {
+                break;
+            }
+            ExpandableNotificationRow child = mChildren.get(i);
+            float childHeight = child.isExpanded(true /* allowOnKeyguard */)
+                    ? child.getMaxExpandHeight()
+                    : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
+            maxContentHeight += childHeight;
+            visibleChildren++;
+        }
+        if (visibleChildren > 0) {
+            maxContentHeight += visibleChildren * mDividerHeight;
+        }
+        return maxContentHeight;
+    }
+
+    public void setActualHeight(int actualHeight) {
+        if (!mUserLocked) {
+            return;
+        }
+        mActualHeight = actualHeight;
+        float fraction = getGroupExpandFraction();
+        boolean showingLowPriority = showingAsLowPriority();
+        updateHeaderTransformation();
+        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
+        int childCount = mChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            float childHeight;
+            if (showingLowPriority) {
+                childHeight = child.getShowingLayout().getMinHeight(false /* likeGroupExpanded */);
+            } else if (child.isExpanded(true /* allowOnKeyguard */)) {
+                childHeight = child.getMaxExpandHeight();
+            } else {
+                childHeight = child.getShowingLayout().getMinHeight(
+                        true /* likeGroupExpanded */);
+            }
+            if (i < maxAllowedVisibleChildren) {
+                float singleLineHeight = child.getShowingLayout().getMinHeight(
+                        false /* likeGroupExpanded */);
+                child.setActualHeight((int) NotificationUtils.interpolate(singleLineHeight,
+                        childHeight, fraction), false);
+            } else {
+                child.setActualHeight((int) childHeight, false);
+            }
+        }
+    }
+
+    public float getGroupExpandFraction() {
+        int visibleChildrenExpandedHeight = showingAsLowPriority() ? getMaxContentHeight()
+                : getVisibleChildrenExpandHeight();
+        int minExpandHeight = getCollapsedHeight();
+        float factor = (mActualHeight - minExpandHeight)
+                / (float) (visibleChildrenExpandedHeight - minExpandHeight);
+        return Math.max(0.0f, Math.min(1.0f, factor));
+    }
+
+    private int getVisibleChildrenExpandHeight() {
+        int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation
+                + mNotificatonTopPadding + mDividerHeight;
+        int visibleChildren = 0;
+        int childCount = mChildren.size();
+        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
+        for (int i = 0; i < childCount; i++) {
+            if (visibleChildren >= maxAllowedVisibleChildren) {
+                break;
+            }
+            ExpandableNotificationRow child = mChildren.get(i);
+            float childHeight = child.isExpanded(true /* allowOnKeyguard */)
+                    ? child.getMaxExpandHeight()
+                    : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
+            intrinsicHeight += childHeight;
+            visibleChildren++;
+        }
+        return intrinsicHeight;
+    }
+
+    public int getMinHeight() {
+        return getMinHeight(mContainingNotification.isShowingAmbient()
+                ? NUMBER_OF_CHILDREN_WHEN_AMBIENT
+                : NUMBER_OF_CHILDREN_WHEN_COLLAPSED, false /* likeHighPriority */);
+    }
+
+    public int getCollapsedHeight() {
+        return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */),
+                false /* likeHighPriority */);
+    }
+
+    /**
+     * Get the minimum Height for this group.
+     *
+     * @param maxAllowedVisibleChildren the number of children that should be visible
+     * @param likeHighPriority if the height should be calculated as if it were not low priority
+     */
+    private int getMinHeight(int maxAllowedVisibleChildren, boolean likeHighPriority) {
+        if (!likeHighPriority && showingAsLowPriority()) {
+            return mNotificationHeaderLowPriority.getHeight();
+        }
+        int minExpandHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation;
+        int visibleChildren = 0;
+        boolean firstChild = true;
+        int childCount = mChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            if (visibleChildren >= maxAllowedVisibleChildren) {
+                break;
+            }
+            if (!firstChild) {
+                minExpandHeight += mChildPadding;
+            } else {
+                firstChild = false;
+            }
+            ExpandableNotificationRow child = mChildren.get(i);
+            minExpandHeight += child.getSingleLineView().getHeight();
+            visibleChildren++;
+        }
+        minExpandHeight += mCollapsedBottompadding;
+        return minExpandHeight;
+    }
+
+    public boolean showingAsLowPriority() {
+        return mIsLowPriority && !mContainingNotification.isExpanded();
+    }
+
+    public void setDark(boolean dark, boolean fade, long delay) {
+        if (mOverflowNumber != null) {
+            mHybridGroupManager.setOverflowNumberDark(mOverflowNumber, dark, fade, delay);
+        }
+    }
+
+    public void reInflateViews(OnClickListener listener, StatusBarNotification notification) {
+        if (mNotificationHeader != null) {
+            removeView(mNotificationHeader);
+            mNotificationHeader = null;
+        }
+        if (mNotificationHeaderLowPriority != null) {
+            removeView(mNotificationHeaderLowPriority);
+            mNotificationHeaderLowPriority = null;
+        }
+        if (mNotificationHeaderAmbient != null) {
+            removeView(mNotificationHeaderAmbient);
+            mNotificationHeaderAmbient = null;
+        }
+        recreateNotificationHeader(listener);
+        initDimens();
+        for (int i = 0; i < mDividers.size(); i++) {
+            View prevDivider = mDividers.get(i);
+            int index = indexOfChild(prevDivider);
+            removeView(prevDivider);
+            View divider = inflateDivider();
+            addView(divider, index);
+            mDividers.set(i, divider);
+        }
+        removeView(mOverflowNumber);
+        mOverflowNumber = null;
+        mGroupOverFlowState = null;
+        updateGroupOverflow();
+    }
+
+    public void setUserLocked(boolean userLocked) {
+        mUserLocked = userLocked;
+        if (!mUserLocked) {
+            updateHeaderVisibility(false /* animate */);
+        }
+        int childCount = mChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            child.setUserLocked(userLocked && !showingAsLowPriority());
+        }
+    }
+
+    public void onNotificationUpdated() {
+        mHybridGroupManager.setOverflowNumberColor(mOverflowNumber,
+                mContainingNotification.getNotificationColor(),
+                mContainingNotification.getNotificationColorAmbient());
+    }
+
+    public int getPositionInLinearLayout(View childInGroup) {
+        int position = mNotificationHeaderMargin + mCurrentHeaderTranslation
+                + mNotificatonTopPadding;
+
+        for (int i = 0; i < mChildren.size(); i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            boolean notGone = child.getVisibility() != View.GONE;
+            if (notGone) {
+                position += mDividerHeight;
+            }
+            if (child == childInGroup) {
+                return position;
+            }
+            if (notGone) {
+                position += child.getIntrinsicHeight();
+            }
+        }
+        return 0;
+    }
+
+    public void setIconsVisible(boolean iconsVisible) {
+        if (mNotificationHeaderWrapper != null) {
+            NotificationHeaderView header = mNotificationHeaderWrapper.getNotificationHeader();
+            if (header != null) {
+                header.getIcon().setForceHidden(!iconsVisible);
+            }
+        }
+        if (mNotificationHeaderWrapperLowPriority != null) {
+            NotificationHeaderView header
+                    = mNotificationHeaderWrapperLowPriority.getNotificationHeader();
+            if (header != null) {
+                header.getIcon().setForceHidden(!iconsVisible);
+            }
+        }
+    }
+
+    public void setClipBottomAmount(int clipBottomAmount) {
+        mClipBottomAmount = clipBottomAmount;
+        updateChildrenClipping();
+    }
+
+    public void setIsLowPriority(boolean isLowPriority) {
+        mIsLowPriority = isLowPriority;
+        if (mContainingNotification != null) { /* we're not yet set up yet otherwise */
+            recreateLowPriorityHeader(null /* existingBuilder */);
+            updateHeaderVisibility(false /* animate */);
+        }
+        if (mUserLocked) {
+            setUserLocked(mUserLocked);
+        }
+    }
+
+    public NotificationHeaderView getVisibleHeader() {
+        NotificationHeaderView header = mNotificationHeader;
+        if (showingAsLowPriority()) {
+            header = mNotificationHeaderLowPriority;
+        }
+        return header;
+    }
+
+    public void onExpansionChanged() {
+        if (mIsLowPriority) {
+            if (mUserLocked) {
+                setUserLocked(mUserLocked);
+            }
+            updateHeaderVisibility(true /* animate */);
+        }
+    }
+
+    public float getIncreasedPaddingAmount() {
+        if (showingAsLowPriority()) {
+            return 0.0f;
+        }
+        return getGroupExpandFraction();
+    }
+
+    @VisibleForTesting
+    public boolean isUserLocked() {
+        return mUserLocked;
+    }
+
+    public void setCurrentBottomRoundness(float currentBottomRoundness) {
+        boolean last = true;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            if (child.getVisibility() == View.GONE) {
+                continue;
+            }
+            float bottomRoundness = last ? currentBottomRoundness : 0.0f;
+            child.setBottomRoundness(bottomRoundness, isShown() /* animate */);
+            last = false;
+        }
+    }
+
+    public void setHeaderVisibleAmount(float headerVisibleAmount) {
+        mHeaderVisibleAmount = headerVisibleAmount;
+        mCurrentHeaderTranslation = (int) ((1.0f - headerVisibleAmount) * mTranslationForHeader);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
new file mode 100644
index 0000000..fa75c71
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+
+/**
+ * Interface representing the entity that contains notifications. It can have
+ * notification views added and removed from it, and will manage displaying them to the user.
+ */
+public interface NotificationListContainer {
+
+    /**
+     * Called when a child is being transferred.
+     *
+     * @param childTransferInProgress whether child transfer is in progress
+     */
+    void setChildTransferInProgress(boolean childTransferInProgress);
+
+    /**
+     * Change the position of child to a new location
+     *
+     * @param child the view to change the position for
+     * @param newIndex the new index
+     */
+    void changeViewPosition(View child, int newIndex);
+
+    /**
+     * Called when a child was added to a group.
+     *
+     * @param row row of the group child that was added
+     */
+    void notifyGroupChildAdded(View row);
+
+    /**
+     * Called when a child was removed from a group.
+     *
+     * @param row row of the child that was removed
+     * @param childrenContainer ViewGroup of the group that the child was removed from
+     */
+    void notifyGroupChildRemoved(View row, ViewGroup childrenContainer);
+
+    /**
+     * Generate an animation for an added child view.
+     *
+     * @param child The view to be added.
+     * @param fromMoreCard Whether this add is coming from the "more" card on lockscreen.
+     */
+    void generateAddAnimation(View child, boolean fromMoreCard);
+
+    /**
+     * Generate a child order changed event.
+     */
+    void generateChildOrderChangedEvent();
+
+    /**
+     * Returns the number of children in the NotificationListContainer.
+     *
+     * @return the number of children in the NotificationListContainer
+     */
+    int getContainerChildCount();
+
+    /**
+     * Gets the ith child in the NotificationListContainer.
+     *
+     * @param i ith child to get
+     * @return the ith child in the list container
+     */
+    View getContainerChildAt(int i);
+
+    /**
+     * Remove a view from the container
+     *
+     * @param v view to remove
+     */
+    void removeContainerView(View v);
+
+    /**
+     * Add a view to the container
+     *
+     * @param v view to add
+     */
+    void addContainerView(View v);
+
+    /**
+     * Sets the maximum number of notifications to display.
+     *
+     * @param maxNotifications max number of notifications to display
+     */
+    void setMaxDisplayedNotifications(int maxNotifications);
+
+    /**
+     * Handle snapping a non-dismissable row back if the user tried to dismiss it.
+     *
+     * @param row row to snap back
+     */
+    void snapViewIfNeeded(ExpandableNotificationRow row);
+
+    /**
+     * Get the view parent for a notification entry. For example, NotificationStackScrollLayout.
+     *
+     * @param entry entry to get the view parent for
+     * @return the view parent for entry
+     */
+    ViewGroup getViewParentForNotification(NotificationData.Entry entry);
+
+    /**
+     * Called when the height of an expandable view changes.
+     *
+     * @param view view whose height changed
+     * @param animate whether this change should be animated
+     */
+    void onHeightChanged(ExpandableView view, boolean animate);
+
+    /**
+     * Resets the currently exposed menu view.
+     *
+     * @param animate whether to animate the closing/change of menu view
+     * @param force reset the menu view even if it looks like it is already reset
+     */
+    void resetExposedMenuView(boolean animate, boolean force);
+
+    /**
+     * Returns the NotificationSwipeActionHelper for the NotificationListContainer.
+     *
+     * @return swipe action helper for the list container
+     */
+    NotificationSwipeActionHelper getSwipeActionHelper();
+
+    /**
+     * Called when a notification is removed from the shade. This cleans up the state for a
+     * given view.
+     *
+     * @param view view to clean up view state for
+     */
+    void cleanUpViewState(View view);
+
+    /**
+     * Returns whether an ExpandableNotificationRow is in a visible location or not.
+     *
+     * @param row
+     * @return true if row is in a visible location
+     */
+    boolean isInVisibleLocation(ExpandableNotificationRow row);
+
+    /**
+     * Sets a listener to listen for changes in notification locations.
+     *
+     * @param listener listener to set
+     */
+    void setChildLocationsChangedListener(
+            NotificationLogger.OnChildLocationsChangedListener listener);
+
+    /**
+     * Called when an update to the notification view hierarchy is completed.
+     */
+    default void onNotificationViewUpdateFinished() {}
+
+    /**
+     * Returns true if there are pulsing notifications.
+     *
+     * @return true if has pulsing notifications
+     */
+    boolean hasPulsingNotifications();
+
+    /**
+     * Apply parameters of the expand animation to the layout
+     */
+    default void applyExpandAnimationParams(ExpandAnimationParameters params) {}
+
+    default void setExpandingNotification(ExpandableNotificationRow row) {}
+
+    /**
+     * Bind a newly created row.
+     *
+     * @param row The notification to bind.
+     */
+    default void bindRow(ExpandableNotificationRow row) {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
new file mode 100644
index 0000000..e32df42
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.view.View;
+
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+
+import java.util.HashSet;
+
+/**
+ * A class that manages the roundness for notification views
+ */
+class NotificationRoundnessManager implements OnHeadsUpChangedListener {
+
+    private boolean mExpanded;
+    private ActivatableNotificationView mFirst;
+    private ActivatableNotificationView mLast;
+    private HashSet<View> mAnimatedChildren;
+    private Runnable mRoundingChangedCallback;
+    private ExpandableNotificationRow mTrackedHeadsUp;
+    private float mAppearFraction;
+
+    @Override
+    public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
+        updateRounding(headsUp, false /* animate */);
+    }
+
+    @Override
+    public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
+        updateRounding(headsUp, true /* animate */);
+    }
+
+    public void onHeadsupAnimatingAwayChanged(ExpandableNotificationRow row,
+            boolean isAnimatingAway) {
+        updateRounding(row, false /* animate */);
+    }
+
+    private void updateRounding(ActivatableNotificationView view, boolean animate) {
+        float topRoundness = getRoundness(view, true /* top */);
+        float bottomRoundness = getRoundness(view, false /* top */);
+        boolean firstChanged = view.setTopRoundness(topRoundness, animate);
+        boolean secondChanged = view.setBottomRoundness(bottomRoundness, animate);
+        if ((view == mFirst || view == mLast) && (firstChanged || secondChanged)) {
+            mRoundingChangedCallback.run();
+        }
+    }
+
+    private float getRoundness(ActivatableNotificationView view, boolean top) {
+        if ((view.isPinned() || view.isHeadsUpAnimatingAway()) && !mExpanded) {
+            return 1.0f;
+        }
+        if (view == mFirst && top) {
+            return 1.0f;
+        }
+        if (view == mLast && !top) {
+            return 1.0f;
+        }
+        if (view == mTrackedHeadsUp && mAppearFraction <= 0.0f) {
+            // If we're pushing up on a headsup the appear fraction is < 0 and it needs to still be
+            // rounded.
+            return 1.0f;
+        }
+        return 0.0f;
+    }
+
+    public void setExpanded(float expandedHeight, float appearFraction) {
+        mExpanded = expandedHeight != 0.0f;
+        mAppearFraction = appearFraction;
+        if (mTrackedHeadsUp != null) {
+            updateRounding(mTrackedHeadsUp, true);
+        }
+    }
+
+    public void setFirstAndLastBackgroundChild(ActivatableNotificationView first,
+            ActivatableNotificationView last) {
+        boolean firstChanged = mFirst != first;
+        boolean lastChanged = mLast != last;
+        if (!firstChanged && !lastChanged) {
+            return;
+        }
+        ActivatableNotificationView oldFirst = mFirst;
+        ActivatableNotificationView oldLast = mLast;
+        mFirst = first;
+        mLast = last;
+        if (firstChanged && oldFirst != null && !oldFirst.isRemoved()) {
+            updateRounding(oldFirst, oldFirst.isShown());
+        }
+        if (lastChanged && oldLast != null && !oldLast.isRemoved()) {
+            updateRounding(oldLast, oldLast.isShown());
+        }
+        if (mFirst != null) {
+            updateRounding(mFirst, mFirst.isShown() && !mAnimatedChildren.contains(mFirst));
+        }
+        if (mLast != null) {
+            updateRounding(mLast, mLast.isShown() && !mAnimatedChildren.contains(mLast));
+        }
+        mRoundingChangedCallback.run();
+    }
+
+    public void setAnimatedChildren(HashSet<View> animatedChildren) {
+        mAnimatedChildren = animatedChildren;
+    }
+
+    public void setOnRoundingChangedCallback(Runnable roundingChangedCallback) {
+        mRoundingChangedCallback = roundingChangedCallback;
+    }
+
+    public void setTrackingHeadsUp(ExpandableNotificationRow row) {
+        mTrackedHeadsUp = row;
+    }
+}
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
new file mode 100644
index 0000000..4f554b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -0,0 +1,5654 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
+        .ExpandAnimationParameters;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.TimeAnimator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.FloatRange;
+import android.annotation.Nullable;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.core.graphics.ColorUtils;
+
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.Pair;
+import android.view.ContextThemeWrapper;
+import android.view.InputDevice;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.OverScroller;
+import android.widget.ScrollView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.keyguard.KeyguardSliceView;
+import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
+import com.android.systemui.ExpandHelper;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.SwipeHelper.Callback;
+import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
+import com.android.systemui.statusbar.notification.row.FooterView;
+import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.NotificationGuts;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.notification.row.NotificationSnooze;
+import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.FakeShadowView;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone.AnimationStateHandler;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.HeadsUpUtil;
+import com.android.systemui.statusbar.policy.ScrollAdapter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.function.BiConsumer;
+
+/**
+ * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
+ */
+public class NotificationStackScrollLayout extends ViewGroup
+        implements Callback, ExpandHelper.Callback, ScrollAdapter,
+        OnHeightChangedListener, OnGroupChangeListener,
+        OnMenuEventListener, VisibilityLocationProvider,
+        NotificationListContainer, ConfigurationListener, DragDownCallback, AnimationStateHandler,
+        Dumpable {
+
+    public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
+    private static final String TAG = "StackScroller";
+    private static final boolean DEBUG = false;
+    private static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
+    private static final float RUBBER_BAND_FACTOR_AFTER_EXPAND = 0.15f;
+    private static final float RUBBER_BAND_FACTOR_ON_PANEL_EXPAND = 0.21f;
+    /**
+     * Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
+     */
+    private static final int INVALID_POINTER = -1;
+
+    private ExpandHelper mExpandHelper;
+    private NotificationSwipeHelper mSwipeHelper;
+    private boolean mSwipingInProgress;
+    private int mCurrentStackHeight = Integer.MAX_VALUE;
+    private final Paint mBackgroundPaint = new Paint();
+    private final boolean mShouldDrawNotificationBackground;
+
+    private float mExpandedHeight;
+    private int mOwnScrollY;
+    private int mMaxLayoutHeight;
+
+    private VelocityTracker mVelocityTracker;
+    private OverScroller mScroller;
+    private Runnable mFinishScrollingCallback;
+    private int mTouchSlop;
+    private int mMinimumVelocity;
+    private int mMaximumVelocity;
+    private int mOverflingDistance;
+    private float mMaxOverScroll;
+    private boolean mIsBeingDragged;
+    private int mLastMotionY;
+    private int mDownX;
+    private int mActivePointerId = INVALID_POINTER;
+    private boolean mTouchIsClick;
+    private float mInitialTouchX;
+    private float mInitialTouchY;
+
+    private Paint mDebugPaint;
+    private int mContentHeight;
+    private int mIntrinsicContentHeight;
+    private int mCollapsedSize;
+    private int mPaddingBetweenElements;
+    private int mIncreasedPaddingBetweenElements;
+    private int mMaxTopPadding;
+    private int mRegularTopPadding;
+    private int mDarkTopPadding;
+    // Current padding, will be either mRegularTopPadding or mDarkTopPadding
+    private int mTopPadding;
+    // Distance between AOD separator and shelf
+    private int mDarkSeparatorPadding;
+    private int mBottomMargin;
+    private int mBottomInset = 0;
+    private float mQsExpansionFraction;
+
+    /**
+     * The algorithm which calculates the properties for our children
+     */
+    protected final StackScrollAlgorithm mStackScrollAlgorithm;
+
+    /**
+     * The current State this Layout is in
+     */
+    private StackScrollState mCurrentStackScrollState = new StackScrollState(this);
+    private final AmbientState mAmbientState;
+    private NotificationGroupManager mGroupManager;
+    private HashSet<View> mChildrenToAddAnimated = new HashSet<>();
+    private ArrayList<View> mAddedHeadsUpChildren = new ArrayList<>();
+    private ArrayList<View> mChildrenToRemoveAnimated = new ArrayList<>();
+    private ArrayList<View> mSnappedBackChildren = new ArrayList<>();
+    private ArrayList<View> mDragAnimPendingChildren = new ArrayList<>();
+    private ArrayList<View> mChildrenChangingPositions = new ArrayList<>();
+    private HashSet<View> mFromMoreCardAdditions = new HashSet<>();
+    private ArrayList<AnimationEvent> mAnimationEvents = new ArrayList<>();
+    private ArrayList<View> mSwipedOutViews = new ArrayList<>();
+    private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
+    private boolean mAnimationsEnabled;
+    private boolean mChangePositionInProgress;
+    private boolean mChildTransferInProgress;
+
+    /**
+     * The raw amount of the overScroll on the top, which is not rubber-banded.
+     */
+    private float mOverScrolledTopPixels;
+
+    /**
+     * The raw amount of the overScroll on the bottom, which is not rubber-banded.
+     */
+    private float mOverScrolledBottomPixels;
+    private NotificationLogger.OnChildLocationsChangedListener mListener;
+    private OnOverscrollTopChangedListener mOverscrollTopChangedListener;
+    private ExpandableView.OnHeightChangedListener mOnHeightChangedListener;
+    private OnEmptySpaceClickListener mOnEmptySpaceClickListener;
+    private boolean mNeedsAnimation;
+    private boolean mTopPaddingNeedsAnimation;
+    private boolean mDimmedNeedsAnimation;
+    private boolean mHideSensitiveNeedsAnimation;
+    private boolean mDarkNeedsAnimation;
+    private int mDarkAnimationOriginIndex;
+    private boolean mActivateNeedsAnimation;
+    private boolean mGoToFullShadeNeedsAnimation;
+    private boolean mIsExpanded = true;
+    private boolean mChildrenUpdateRequested;
+    private boolean mIsExpansionChanging;
+    private boolean mPanelTracking;
+    private boolean mExpandingNotification;
+    private boolean mExpandedInThisMotion;
+    private boolean mShouldShowShelfOnly;
+    protected boolean mScrollingEnabled;
+    protected FooterView mFooterView;
+    protected EmptyShadeView mEmptyShadeView;
+    private boolean mDismissAllInProgress;
+    private boolean mFadeNotificationsOnDismiss;
+
+    /**
+     * Was the scroller scrolled to the top when the down motion was observed?
+     */
+    private boolean mScrolledToTopOnFirstDown;
+    /**
+     * The minimal amount of over scroll which is needed in order to switch to the quick settings
+     * when over scrolling on a expanded card.
+     */
+    private float mMinTopOverScrollToEscape;
+    private int mIntrinsicPadding;
+    private float mStackTranslation;
+    private float mTopPaddingOverflow;
+    private boolean mDontReportNextOverScroll;
+    private boolean mDontClampNextScroll;
+    private boolean mNeedViewResizeAnimation;
+    private View mExpandedGroupView;
+    private boolean mEverythingNeedsAnimation;
+
+    /**
+     * The maximum scrollPosition which we are allowed to reach when a notification was expanded.
+     * This is needed to avoid scrolling too far after the notification was collapsed in the same
+     * motion.
+     */
+    private int mMaxScrollAfterExpand;
+    private ExpandableNotificationRow.LongPressListener mLongPressListener;
+
+    private NotificationMenuRowPlugin mCurrMenuRow;
+    private View mTranslatingParentView;
+    private View mMenuExposedView;
+    boolean mCheckForLeavebehind;
+
+    /**
+     * Should in this touch motion only be scrolling allowed? It's true when the scroller was
+     * animating.
+     */
+    private boolean mOnlyScrollingInThisMotion;
+    private boolean mDisallowDismissInThisMotion;
+    private boolean mDisallowScrollingInThisMotion;
+    private long mGoToFullShadeDelay;
+    private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
+            = new ViewTreeObserver.OnPreDrawListener() {
+        @Override
+        public boolean onPreDraw() {
+            updateForcedScroll();
+            updateChildren();
+            mChildrenUpdateRequested = false;
+            getViewTreeObserver().removeOnPreDrawListener(this);
+            return true;
+        }
+    };
+    private StatusBar mStatusBar;
+    private int[] mTempInt2 = new int[2];
+    private boolean mGenerateChildOrderChangedEvent;
+    private HashSet<Runnable> mAnimationFinishedRunnables = new HashSet<>();
+    private HashSet<ExpandableView> mClearTransientViewsWhenFinished = new HashSet<>();
+    private HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations
+            = new HashSet<>();
+    private HeadsUpManagerPhone mHeadsUpManager;
+    private NotificationRoundnessManager mRoundnessManager = new NotificationRoundnessManager();
+    private boolean mTrackingHeadsUp;
+    private ScrimController mScrimController;
+    private boolean mForceNoOverlappingRendering;
+    private final ArrayList<Pair<ExpandableNotificationRow, Boolean>> mTmpList = new ArrayList<>();
+    private FalsingManager mFalsingManager;
+    private boolean mAnimationRunning;
+    private ViewTreeObserver.OnPreDrawListener mRunningAnimationUpdater
+            = new ViewTreeObserver.OnPreDrawListener() {
+        @Override
+        public boolean onPreDraw() {
+            onPreDrawDuringAnimation();
+            return true;
+        }
+    };
+    private Rect mBackgroundBounds = new Rect();
+    private Rect mStartAnimationRect = new Rect();
+    private Rect mEndAnimationRect = new Rect();
+    private Rect mCurrentBounds = new Rect(-1, -1, -1, -1);
+    private boolean mAnimateNextBackgroundBottom;
+    private boolean mAnimateNextBackgroundTop;
+    private ObjectAnimator mBottomAnimator = null;
+    private ObjectAnimator mTopAnimator = null;
+    private ActivatableNotificationView mFirstVisibleBackgroundChild = null;
+    private ActivatableNotificationView mLastVisibleBackgroundChild = null;
+    private int mBgColor;
+    private float mDimAmount;
+    private ValueAnimator mDimAnimator;
+    private ArrayList<ExpandableView> mTmpSortedChildren = new ArrayList<>();
+    private Animator.AnimatorListener mDimEndListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mDimAnimator = null;
+        }
+    };
+    private ValueAnimator.AnimatorUpdateListener mDimUpdateListener
+            = new ValueAnimator.AnimatorUpdateListener() {
+
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            setDimAmount((Float) animation.getAnimatedValue());
+        }
+    };
+    protected ViewGroup mQsContainer;
+    private boolean mContinuousShadowUpdate;
+    private ViewTreeObserver.OnPreDrawListener mShadowUpdater
+            = new ViewTreeObserver.OnPreDrawListener() {
+
+        @Override
+        public boolean onPreDraw() {
+            updateViewShadows();
+            return true;
+        }
+    };
+    private Comparator<ExpandableView> mViewPositionComparator = new Comparator<ExpandableView>() {
+        @Override
+        public int compare(ExpandableView view, ExpandableView otherView) {
+            float endY = view.getTranslationY() + view.getActualHeight();
+            float otherEndY = otherView.getTranslationY() + otherView.getActualHeight();
+            if (endY < otherEndY) {
+                return -1;
+            } else if (endY > otherEndY) {
+                return 1;
+            } else {
+                // The two notifications end at the same location
+                return 0;
+            }
+        }
+    };
+    private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
+    private boolean mPulsing;
+    private boolean mDrawBackgroundAsSrc;
+    private boolean mFadingOut;
+    private boolean mParentNotFullyVisible;
+    private boolean mGroupExpandedForMeasure;
+    private boolean mScrollable;
+    private View mForcedScroll;
+    private View mNeedingPulseAnimation;
+
+    /**
+     * @see #setDarkAmount(float, float)
+     */
+    private float mInterpolatedDarkAmount = 0f;
+
+    /**
+     * @see #setDarkAmount(float, float)
+     */
+    private float mLinearDarkAmount = 0f;
+
+    /**
+     * How fast the background scales in the X direction as a factor of the Y expansion.
+     */
+    private float mBackgroundXFactor = 1f;
+
+    private boolean mUsingLightTheme;
+    private boolean mQsExpanded;
+    private boolean mForwardScrollable;
+    private boolean mBackwardScrollable;
+    private NotificationShelf mShelf;
+    private int mMaxDisplayedNotifications = -1;
+    private int mStatusBarHeight;
+    private int mMinInteractionHeight;
+    private boolean mNoAmbient;
+    private final Rect mClipRect = new Rect();
+    private boolean mIsClipped;
+    private Rect mRequestedClipBounds;
+    private boolean mInHeadsUpPinnedMode;
+    private boolean mHeadsUpAnimatingAway;
+    private int mStatusBarState;
+    private int mCachedBackgroundColor;
+    private boolean mHeadsUpGoingAwayAnimationsAllowed = true;
+    private Runnable mAnimateScroll = this::animateScroll;
+    private int mCornerRadius;
+    private int mSidePaddings;
+    private final int mSeparatorWidth;
+    private final int mSeparatorThickness;
+    private final Rect mBackgroundAnimationRect = new Rect();
+    private int mAntiBurnInOffsetX;
+    private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>();
+    private int mHeadsUpInset;
+    private HeadsUpAppearanceController mHeadsUpAppearanceController;
+    private NotificationIconAreaController mIconAreaController;
+    private float mVerticalPanelTranslation;
+    private final NotificationLockscreenUserManager mLockscreenUserManager =
+            Dependency.get(NotificationLockscreenUserManager.class);
+    private final Rect mTmpRect = new Rect();
+    private final NotificationEntryManager mEntryManager =
+            Dependency.get(NotificationEntryManager.class);
+    private final IStatusBarService mBarService = IStatusBarService.Stub.asInterface(
+            ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+    private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+    private final NotificationRemoteInputManager mRemoteInputManager =
+            Dependency.get(NotificationRemoteInputManager.class);
+    private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+
+    private final DisplayMetrics mDisplayMetrics = Dependency.get(DisplayMetrics.class);
+    private final LockscreenGestureLogger mLockscreenGestureLogger =
+            Dependency.get(LockscreenGestureLogger.class);
+    private final VisualStabilityManager mVisualStabilityManager =
+            Dependency.get(VisualStabilityManager.class);
+    protected boolean mClearAllEnabled;
+
+    private Interpolator mDarkXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+    private NotificationPanelView mNotificationPanel;
+
+    public NotificationStackScrollLayout(Context context) {
+        this(context, null);
+    }
+
+    public NotificationStackScrollLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        Resources res = getResources();
+
+        mAmbientState = new AmbientState(context);
+        mBgColor = context.getColor(R.color.notification_shade_background_color);
+        int minHeight = res.getDimensionPixelSize(R.dimen.notification_min_height);
+        int maxHeight = res.getDimensionPixelSize(R.dimen.notification_max_height);
+        mExpandHelper = new ExpandHelper(getContext(), this,
+                minHeight, maxHeight);
+        mExpandHelper.setEventSource(this);
+        mExpandHelper.setScrollAdapter(this);
+        mSwipeHelper = new NotificationSwipeHelper(SwipeHelper.X, this, getContext());
+        mStackScrollAlgorithm = createStackScrollAlgorithm(context);
+        initView(context);
+        mFalsingManager = FalsingManager.getInstance(context);
+        mShouldDrawNotificationBackground =
+                res.getBoolean(R.bool.config_drawNotificationBackground);
+        mFadeNotificationsOnDismiss =
+                res.getBoolean(R.bool.config_fadeNotificationsOnDismiss);
+        mSeparatorWidth = res.getDimensionPixelSize(R.dimen.widget_separator_width);
+        mSeparatorThickness = res.getDimensionPixelSize(R.dimen.widget_separator_thickness);
+        mDarkSeparatorPadding = res.getDimensionPixelSize(R.dimen.widget_bottom_separator_padding);
+        mRoundnessManager.setAnimatedChildren(mChildrenToAddAnimated);
+        mRoundnessManager.setOnRoundingChangedCallback(this::invalidate);
+        addOnExpandedHeightListener(mRoundnessManager::setExpanded);
+
+        // Blocking helper manager wants to know the expanded state, update as well.
+        NotificationBlockingHelperManager blockingHelperManager =
+                Dependency.get(NotificationBlockingHelperManager.class);
+        addOnExpandedHeightListener((height, unused) -> {
+            blockingHelperManager.setNotificationShadeExpanded(height);
+        });
+
+        updateWillNotDraw();
+        mBackgroundPaint.setAntiAlias(true);
+        if (DEBUG) {
+            mDebugPaint = new Paint();
+            mDebugPaint.setColor(0xffff0000);
+            mDebugPaint.setStrokeWidth(2);
+            mDebugPaint.setStyle(Paint.Style.STROKE);
+        }
+        mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        inflateEmptyShadeView();
+        inflateFooterView();
+        mVisualStabilityManager.setVisibilityLocationProvider(this);
+        setLongPressListener(mEntryManager.getNotificationLongClicker());
+    }
+
+    @Override
+    public void onDensityOrFontScaleChanged() {
+        inflateFooterView();
+        inflateEmptyShadeView();
+        updateFooter();
+    }
+
+    @Override
+    public void onThemeChanged() {
+        int which;
+        if (mStatusBarState == StatusBarState.KEYGUARD
+                || mStatusBarState == StatusBarState.SHADE_LOCKED) {
+            which = WallpaperManager.FLAG_LOCK;
+        } else {
+            which = WallpaperManager.FLAG_SYSTEM;
+        }
+        final boolean useDarkText = mColorExtractor.getColors(which,
+                true /* ignoreVisibility */).supportsDarkText();
+        updateDecorViews(useDarkText);
+
+        updateFooter();
+    }
+
+    @VisibleForTesting
+    public void updateFooter() {
+        boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications();
+        boolean showFooterView = (showDismissView ||
+                mEntryManager.getNotificationData().getActiveNotifications().size() != 0)
+                && mStatusBarState != StatusBarState.KEYGUARD
+                && !mRemoteInputManager.getController().isRemoteInputActive();
+
+        updateFooterView(showFooterView, showDismissView);
+    }
+
+    /**
+     * Return whether there are any clearable notifications
+     */
+    public boolean hasActiveClearableNotifications() {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (!(child instanceof ExpandableNotificationRow)) {
+                continue;
+            }
+            if (((ExpandableNotificationRow) child).canViewBeDismissed()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public RemoteInputController.Delegate createDelegate() {
+        return new RemoteInputController.Delegate() {
+            public void setRemoteInputActive(NotificationData.Entry entry,
+                    boolean remoteInputActive) {
+                mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive);
+                entry.row.notifyHeightChanged(true /* needsAnimation */);
+                updateFooter();
+            }
+
+            public void lockScrollTo(NotificationData.Entry entry) {
+                NotificationStackScrollLayout.this.lockScrollTo(entry.row);
+            }
+
+            public void requestDisallowLongPressAndDismiss() {
+                requestDisallowLongPress();
+                requestDisallowDismiss();
+            }
+        };
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+        Dependency.get(ConfigurationController.class).addCallback(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        Dependency.get(StatusBarStateController.class).removeListener(mStateListener);
+        Dependency.get(ConfigurationController.class).removeCallback(this);
+    }
+
+    @Override
+    public NotificationSwipeActionHelper getSwipeActionHelper() {
+        return mSwipeHelper;
+    }
+
+    @Override
+    public void onMenuClicked(View view, int x, int y, MenuItem item) {
+        if (mLongPressListener == null) {
+            return;
+        }
+        if (view instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR,
+                    row.getStatusBarNotification().getPackageName());
+        }
+        mLongPressListener.onLongPress(view, x, y, item);
+    }
+
+    @Override
+    public void onMenuReset(View row) {
+        if (mTranslatingParentView != null && row == mTranslatingParentView) {
+            mMenuExposedView = null;
+            mTranslatingParentView = null;
+        }
+    }
+
+    @Override
+    public void onMenuShown(View row) {
+        mMenuExposedView = mTranslatingParentView;
+        if (row instanceof ExpandableNotificationRow) {
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
+                    ((ExpandableNotificationRow) row).getStatusBarNotification()
+                            .getPackageName());
+        }
+        mSwipeHelper.onMenuShown(row);
+    }
+
+    @Override
+    public void onUiModeChanged() {
+        mBgColor = mContext.getColor(R.color.notification_shade_background_color);
+        updateBackgroundDimming();
+
+        // Re-inflate all notification views
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child instanceof ActivatableNotificationView) {
+                ((ActivatableNotificationView) child).onUiModeChanged();
+            }
+        }
+    }
+
+    protected void onDraw(Canvas canvas) {
+        if (mShouldDrawNotificationBackground
+                && (mCurrentBounds.top < mCurrentBounds.bottom || mAmbientState.isDark())) {
+            drawBackground(canvas);
+        }
+
+        if (DEBUG) {
+            int y = mTopPadding;
+            canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+            y = getLayoutHeight();
+            canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+            y = getHeight() - getEmptyBottomMargin();
+            canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+        }
+    }
+
+    private void drawBackground(Canvas canvas) {
+        final int lockScreenLeft = mSidePaddings;
+        final int lockScreenRight = getWidth() - mSidePaddings;
+        final int lockScreenTop = mCurrentBounds.top;
+        final int lockScreenBottom = mCurrentBounds.bottom;
+        int separatorWidth = 0;
+        int separatorThickness = 0;
+        if (mIconAreaController.hasShelfIconsWhenFullyDark()) {
+            separatorThickness = mSeparatorThickness;
+            separatorWidth = mSeparatorWidth;
+        }
+        final int darkLeft = getWidth() / 2 - separatorWidth / 2;
+        final int darkRight = darkLeft + separatorWidth;
+        final int darkTop = (int) (mRegularTopPadding + separatorThickness / 2f);
+        final int darkBottom = darkTop + separatorThickness;
+
+        if (mAmbientState.hasPulsingNotifications()) {
+            // No divider, we have a notification icon instead
+        } else if (mAmbientState.isFullyDark()) {
+            // Only draw divider on AOD if we actually have notifications
+            if (mFirstVisibleBackgroundChild != null) {
+                canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint);
+            }
+        } else {
+            float yProgress = 1 - mInterpolatedDarkAmount;
+            float xProgress = mDarkXInterpolator.getInterpolation(
+                    (1 - mLinearDarkAmount) * mBackgroundXFactor);
+
+            mBackgroundAnimationRect.set(
+                    (int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress),
+                    (int) MathUtils.lerp(darkTop, lockScreenTop, yProgress),
+                    (int) MathUtils.lerp(darkRight, lockScreenRight, xProgress),
+                    (int) MathUtils.lerp(darkBottom, lockScreenBottom, yProgress));
+
+            if (!mAmbientState.isDark() || mFirstVisibleBackgroundChild != null) {
+                canvas.drawRoundRect(mBackgroundAnimationRect.left, mBackgroundAnimationRect.top,
+                        mBackgroundAnimationRect.right, mBackgroundAnimationRect.bottom,
+                        mCornerRadius, mCornerRadius, mBackgroundPaint);
+            }
+        }
+        updateClipping();
+    }
+
+    private void updateBackgroundDimming() {
+        // No need to update the background color if it's not being drawn.
+        if (!mShouldDrawNotificationBackground) {
+            return;
+        }
+
+        float alpha =
+                BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
+        alpha *= 1f - mInterpolatedDarkAmount;
+        // We need to manually blend in the background color.
+        int scrimColor = mScrimController.getBackgroundColor();
+        int awakeColor = ColorUtils.blendARGB(scrimColor, mBgColor, alpha);
+
+        // Interpolate between semi-transparent notification panel background color
+        // and white AOD separator.
+        float colorInterpolation = MathUtils.smoothStep(0.4f /* start */, 1f /* end */,
+                mLinearDarkAmount);
+        int color = ColorUtils.blendARGB(awakeColor, Color.WHITE, colorInterpolation);
+
+        if (mCachedBackgroundColor != color) {
+            mCachedBackgroundColor = color;
+            mBackgroundPaint.setColor(color);
+            invalidate();
+        }
+    }
+
+    private void initView(Context context) {
+        mScroller = new OverScroller(getContext());
+        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
+        setClipChildren(false);
+        final ViewConfiguration configuration = ViewConfiguration.get(context);
+        mTouchSlop = configuration.getScaledTouchSlop();
+        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
+        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+        mOverflingDistance = configuration.getScaledOverflingDistance();
+
+        Resources res = context.getResources();
+        mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
+        mStackScrollAlgorithm.initView(context);
+        mAmbientState.reload(context);
+        mPaddingBetweenElements = Math.max(1,
+                res.getDimensionPixelSize(R.dimen.notification_divider_height));
+        mIncreasedPaddingBetweenElements =
+                res.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
+        mMinTopOverScrollToEscape = res.getDimensionPixelSize(
+                R.dimen.min_top_overscroll_to_qs);
+        mStatusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
+        mBottomMargin = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom);
+        mSidePaddings = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
+        mMinInteractionHeight = res.getDimensionPixelSize(
+                R.dimen.notification_min_interaction_height);
+        mCornerRadius = res.getDimensionPixelSize(
+                Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius));
+        mHeadsUpInset = mStatusBarHeight + res.getDimensionPixelSize(
+                R.dimen.heads_up_status_bar_padding);
+    }
+
+    public void setDrawBackgroundAsSrc(boolean asSrc) {
+        mDrawBackgroundAsSrc = asSrc;
+        updateSrcDrawing();
+    }
+
+    private void updateSrcDrawing() {
+        if (!mShouldDrawNotificationBackground) {
+            return;
+        }
+
+        mBackgroundPaint.setXfermode(mDrawBackgroundAsSrc && !mFadingOut && !mParentNotFullyVisible
+                ? mSrcMode : null);
+        invalidate();
+    }
+
+    private void notifyHeightChangeListener(ExpandableView view) {
+        notifyHeightChangeListener(view, false /* needsAnimation */);
+    }
+
+    private void notifyHeightChangeListener(ExpandableView view, boolean needsAnimation) {
+        if (mOnHeightChangedListener != null) {
+            mOnHeightChangedListener.onHeightChanged(view, needsAnimation);
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        int childWidthSpec = MeasureSpec.makeMeasureSpec(width - mSidePaddings * 2,
+                MeasureSpec.getMode(widthMeasureSpec));
+        // Don't constrain the height of the children so we know how big they'd like to be
+        int childHeightSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
+                MeasureSpec.UNSPECIFIED);
+
+        // We need to measure all children even the GONE ones, such that the heights are calculated
+        // correctly as they are used to calculate how many we can fit on the screen.
+        final int size = getChildCount();
+        for (int i = 0; i < size; i++) {
+            measureChild(getChildAt(i), childWidthSpec, childHeightSpec);
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        // we layout all our children centered on the top
+        float centerX = getWidth() / 2.0f;
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            // We need to layout all children even the GONE ones, such that the heights are
+            // calculated correctly as they are used to calculate how many we can fit on the screen
+            float width = child.getMeasuredWidth();
+            float height = child.getMeasuredHeight();
+            child.layout((int) (centerX - width / 2.0f),
+                    0,
+                    (int) (centerX + width / 2.0f),
+                    (int) height);
+        }
+        setMaxLayoutHeight(getHeight());
+        updateContentHeight();
+        clampScrollPosition();
+        requestChildrenUpdate();
+        updateFirstAndLastBackgroundViews();
+        updateAlgorithmLayoutMinHeight();
+    }
+
+    private void requestAnimationOnViewResize(ExpandableNotificationRow row) {
+        if (mAnimationsEnabled && (mIsExpanded || row != null && row.isPinned())) {
+            mNeedViewResizeAnimation = true;
+            mNeedsAnimation = true;
+        }
+    }
+
+    public void updateSpeedBumpIndex(int newIndex, boolean noAmbient) {
+        mAmbientState.setSpeedBumpIndex(newIndex);
+        mNoAmbient = noAmbient;
+    }
+
+    @Override
+    public void setChildLocationsChangedListener(
+            NotificationLogger.OnChildLocationsChangedListener listener) {
+        mListener = listener;
+    }
+
+    @Override
+    public boolean isInVisibleLocation(ExpandableNotificationRow row) {
+        ExpandableViewState childViewState = mCurrentStackScrollState.getViewStateForView(row);
+        if (childViewState == null) {
+            return false;
+        }
+        if ((childViewState.location & ExpandableViewState.VISIBLE_LOCATIONS) == 0) {
+            return false;
+        }
+        if (row.getVisibility() != View.VISIBLE) {
+            return false;
+        }
+        return true;
+    }
+
+    private void setMaxLayoutHeight(int maxLayoutHeight) {
+        mMaxLayoutHeight = maxLayoutHeight;
+        mShelf.setMaxLayoutHeight(maxLayoutHeight);
+        updateAlgorithmHeightAndPadding();
+    }
+
+    private void updateAlgorithmHeightAndPadding() {
+        mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding,
+                mInterpolatedDarkAmount);
+        mAmbientState.setLayoutHeight(getLayoutHeight());
+        updateAlgorithmLayoutMinHeight();
+        mAmbientState.setTopPadding(mTopPadding);
+    }
+
+    private void updateAlgorithmLayoutMinHeight() {
+        mAmbientState.setLayoutMinHeight(mQsExpanded || isHeadsUpTransition()
+                ? getLayoutMinHeight() : 0);
+    }
+
+    /**
+     * Updates the children views according to the stack scroll algorithm. Call this whenever
+     * modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
+     */
+    private void updateChildren() {
+        updateScrollStateForAddedChildren();
+        mAmbientState.setCurrentScrollVelocity(mScroller.isFinished()
+                ? 0
+                : mScroller.getCurrVelocity());
+        mAmbientState.setScrollY(mOwnScrollY);
+        mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState);
+        if (!isCurrentlyAnimating() && !mNeedsAnimation) {
+            applyCurrentState();
+        } else {
+            startAnimationToState();
+        }
+    }
+
+    private void onPreDrawDuringAnimation() {
+        mShelf.updateAppearance();
+        updateClippingToTopRoundedCorner();
+        if (!mNeedsAnimation && !mChildrenUpdateRequested) {
+            updateBackground();
+        }
+    }
+
+    private void updateClippingToTopRoundedCorner() {
+        Float clipStart = (float) mTopPadding
+                + mStackTranslation
+                + mAmbientState.getExpandAnimationTopChange();
+        Float clipEnd = clipStart + mCornerRadius;
+        boolean first = true;
+        for (int i = 0; i < getChildCount(); i++) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child.getVisibility() == GONE) {
+                continue;
+            }
+            float start = child.getTranslationY();
+            float end = start + child.getActualHeight();
+            boolean clip = clipStart > start && clipStart < end
+                    || clipEnd >= start && clipEnd <= end;
+            clip &= !(first && mOwnScrollY == 0);
+            child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0)
+                    : ExpandableView.NO_ROUNDNESS);
+            first = false;
+        }
+    }
+
+    private void updateScrollStateForAddedChildren() {
+        if (mChildrenToAddAnimated.isEmpty()) {
+            return;
+        }
+        for (int i = 0; i < getChildCount(); i++) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (mChildrenToAddAnimated.contains(child)) {
+                int startingPosition = getPositionInLinearLayout(child);
+                float increasedPaddingAmount = child.getIncreasedPaddingAmount();
+                int padding = increasedPaddingAmount == 1.0f ? mIncreasedPaddingBetweenElements
+                        : increasedPaddingAmount == -1.0f ? 0 : mPaddingBetweenElements;
+                int childHeight = getIntrinsicHeight(child) + padding;
+                if (startingPosition < mOwnScrollY) {
+                    // This child starts off screen, so let's keep it offscreen to keep the
+                    // others visible
+
+                    setOwnScrollY(mOwnScrollY + childHeight);
+                }
+            }
+        }
+        clampScrollPosition();
+    }
+
+    private void updateForcedScroll() {
+        if (mForcedScroll != null && (!mForcedScroll.hasFocus()
+                || !mForcedScroll.isAttachedToWindow())) {
+            mForcedScroll = null;
+        }
+        if (mForcedScroll != null) {
+            ExpandableView expandableView = (ExpandableView) mForcedScroll;
+            int positionInLinearLayout = getPositionInLinearLayout(expandableView);
+            int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
+            int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
+
+            targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange()));
+
+            // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
+            // that it is not visible anymore.
+            if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
+                setOwnScrollY(targetScroll);
+            }
+        }
+    }
+
+    private void requestChildrenUpdate() {
+        if (!mChildrenUpdateRequested) {
+            getViewTreeObserver().addOnPreDrawListener(mChildrenUpdater);
+            mChildrenUpdateRequested = true;
+            invalidate();
+        }
+    }
+
+    private boolean isCurrentlyAnimating() {
+        return mStateAnimator.isRunning();
+    }
+
+    private void clampScrollPosition() {
+        int scrollRange = getScrollRange();
+        if (scrollRange < mOwnScrollY) {
+            setOwnScrollY(scrollRange);
+        }
+    }
+
+    public int getTopPadding() {
+        return mTopPadding;
+    }
+
+    private void setTopPadding(int topPadding, boolean animate) {
+        if (mRegularTopPadding != topPadding) {
+            mRegularTopPadding = topPadding;
+            mDarkTopPadding = topPadding + mDarkSeparatorPadding;
+            mAmbientState.setDarkTopPadding(mDarkTopPadding);
+            updateAlgorithmHeightAndPadding();
+            updateContentHeight();
+            if (animate && mAnimationsEnabled && mIsExpanded) {
+                mTopPaddingNeedsAnimation = true;
+                mNeedsAnimation = true;
+            }
+            requestChildrenUpdate();
+            notifyHeightChangeListener(null, animate);
+        }
+    }
+
+    /**
+     * Update the height of the panel.
+     *
+     * @param height the expanded height of the panel
+     */
+    public void setExpandedHeight(float height) {
+        mExpandedHeight = height;
+        setIsExpanded(height > 0);
+        int minExpansionHeight = getMinExpansionHeight();
+        if (height < minExpansionHeight) {
+            mClipRect.left = 0;
+            mClipRect.right = getWidth();
+            mClipRect.top = 0;
+            mClipRect.bottom = (int) height;
+            height = minExpansionHeight;
+            setRequestedClipBounds(mClipRect);
+        } else {
+            setRequestedClipBounds(null);
+        }
+        int stackHeight;
+        float translationY;
+        float appearEndPosition = getAppearEndPosition();
+        float appearStartPosition = getAppearStartPosition();
+        float appearFraction = 1.0f;
+        boolean appearing = height < appearEndPosition;
+        mAmbientState.setAppearing(appearing);
+        if (!appearing) {
+            translationY = 0;
+            if (mShouldShowShelfOnly) {
+                stackHeight = mTopPadding + mShelf.getIntrinsicHeight();
+            } else if (mQsExpanded) {
+                int stackStartPosition = mContentHeight - mTopPadding + mIntrinsicPadding;
+                int stackEndPosition = mMaxTopPadding + mShelf.getIntrinsicHeight();
+                if (stackStartPosition <= stackEndPosition) {
+                    stackHeight = stackEndPosition;
+                } else {
+                    stackHeight = (int) NotificationUtils.interpolate(stackStartPosition,
+                            stackEndPosition, mQsExpansionFraction);
+                }
+            } else {
+                stackHeight = (int) height;
+            }
+        } else {
+            appearFraction = getAppearFraction(height);
+            if (appearFraction >= 0) {
+                translationY = NotificationUtils.interpolate(getExpandTranslationStart(), 0,
+                        appearFraction);
+            } else {
+                // This may happen when pushing up a heads up. We linearly push it up from the
+                // start
+                translationY = height - appearStartPosition + getExpandTranslationStart();
+            }
+            if (isHeadsUpTransition()) {
+                stackHeight = mFirstVisibleBackgroundChild.getPinnedHeadsUpHeight();
+                translationY = MathUtils.lerp(mHeadsUpInset - mTopPadding, 0, appearFraction);
+            } else {
+                stackHeight = (int) (height - translationY);
+            }
+        }
+        if (stackHeight != mCurrentStackHeight) {
+            mCurrentStackHeight = stackHeight;
+            updateAlgorithmHeightAndPadding();
+            requestChildrenUpdate();
+        }
+        setStackTranslation(translationY);
+        for (int i = 0; i < mExpandedHeightListeners.size(); i++) {
+            BiConsumer<Float, Float> listener = mExpandedHeightListeners.get(i);
+            listener.accept(mExpandedHeight, appearFraction);
+        }
+    }
+
+    private void setRequestedClipBounds(Rect clipRect) {
+        mRequestedClipBounds = clipRect;
+        updateClipping();
+    }
+
+    /**
+     * Return the height of the content ignoring the footer.
+     */
+    public int getIntrinsicContentHeight() {
+        return mIntrinsicContentHeight;
+    }
+
+    public void updateClipping() {
+        boolean animatingClipping = mInterpolatedDarkAmount > 0 && mInterpolatedDarkAmount < 1;
+        boolean clipped = mRequestedClipBounds != null && !mInHeadsUpPinnedMode
+                && !mHeadsUpAnimatingAway;
+        if (mIsClipped != clipped) {
+            mIsClipped = clipped;
+            updateFadingState();
+        }
+
+        if (animatingClipping) {
+            setClipBounds(mBackgroundAnimationRect);
+        } else if (clipped) {
+            setClipBounds(mRequestedClipBounds);
+        } else {
+            setClipBounds(null);
+        }
+    }
+
+    /**
+     * @return The translation at the beginning when expanding.
+     * Measured relative to the resting position.
+     */
+    private float getExpandTranslationStart() {
+        return -mTopPadding + getMinExpansionHeight();
+    }
+
+    /**
+     * @return the position from where the appear transition starts when expanding.
+     * Measured in absolute height.
+     */
+    private float getAppearStartPosition() {
+        if (isHeadsUpTransition()) {
+            return mHeadsUpInset + mFirstVisibleBackgroundChild.getPinnedHeadsUpHeight();
+        }
+        return getMinExpansionHeight();
+    }
+
+    /**
+     * @return the height of the top heads up notification when pinned. This is different from the
+     * intrinsic height, which also includes whether the notification is system expanded and
+     * is mainly used when dragging down from a heads up notification.
+     */
+    private int getTopHeadsUpPinnedHeight() {
+        NotificationData.Entry topEntry = mHeadsUpManager.getTopEntry();
+        if (topEntry == null) {
+            return 0;
+        }
+        ExpandableNotificationRow row = topEntry.row;
+        if (row.isChildInGroup()) {
+            final ExpandableNotificationRow groupSummary
+                    = mGroupManager.getGroupSummary(row.getStatusBarNotification());
+            if (groupSummary != null) {
+                row = groupSummary;
+            }
+        }
+        return row.getPinnedHeadsUpHeight();
+    }
+
+    /**
+     * @return the position from where the appear transition ends when expanding.
+     * Measured in absolute height.
+     */
+    private float getAppearEndPosition() {
+        int appearPosition;
+        int notGoneChildCount = getNotGoneChildCount();
+        if (mEmptyShadeView.getVisibility() == GONE && notGoneChildCount != 0) {
+            if (isHeadsUpTransition()
+                    || (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDark())) {
+                appearPosition = getTopHeadsUpPinnedHeight();
+            } else {
+                appearPosition = 0;
+                if (notGoneChildCount >= 1 && mShelf.getVisibility() != GONE) {
+                    appearPosition += mShelf.getIntrinsicHeight();
+                }
+            }
+        } else {
+            appearPosition = mEmptyShadeView.getHeight();
+        }
+        return appearPosition + (onKeyguard() ? mTopPadding : mIntrinsicPadding);
+    }
+
+    private boolean isHeadsUpTransition() {
+        return mTrackingHeadsUp && mFirstVisibleBackgroundChild != null
+                && mAmbientState.isAboveShelf(mFirstVisibleBackgroundChild);
+    }
+
+    /**
+     * @param height the height of the panel
+     * @return the fraction of the appear animation that has been performed
+     */
+    public float getAppearFraction(float height) {
+        float appearEndPosition = getAppearEndPosition();
+        float appearStartPosition = getAppearStartPosition();
+        return (height - appearStartPosition)
+                / (appearEndPosition - appearStartPosition);
+    }
+
+    public float getStackTranslation() {
+        return mStackTranslation;
+    }
+
+    private void setStackTranslation(float stackTranslation) {
+        if (stackTranslation != mStackTranslation) {
+            mStackTranslation = stackTranslation;
+            mAmbientState.setStackTranslation(stackTranslation);
+            requestChildrenUpdate();
+        }
+    }
+
+    /**
+     * Get the current height of the view. This is at most the msize of the view given by a the
+     * layout but it can also be made smaller by setting {@link #mCurrentStackHeight}
+     *
+     * @return either the layout height or the externally defined height, whichever is smaller
+     */
+    private int getLayoutHeight() {
+        return Math.min(mMaxLayoutHeight, mCurrentStackHeight);
+    }
+
+    public int getFirstItemMinHeight() {
+        final ExpandableView firstChild = getFirstChildNotGone();
+        return firstChild != null ? firstChild.getMinHeight() : mCollapsedSize;
+    }
+
+    public void setLongPressListener(ExpandableNotificationRow.LongPressListener listener) {
+        mLongPressListener = listener;
+    }
+
+    public void setQsContainer(ViewGroup qsContainer) {
+        mQsContainer = qsContainer;
+    }
+
+    /**
+     * Handles cleanup after the given {@code view} has been fully swiped out (including
+     * re-invoking dismiss logic in case the notification has not made its way out yet).
+     */
+    @Override
+    public void onChildDismissed(View view) {
+        ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+        if (!row.isDismissed()) {
+            handleChildViewDismissed(view);
+        }
+        ViewGroup transientContainer = row.getTransientContainer();
+        if (transientContainer != null) {
+            transientContainer.removeTransientView(view);
+        }
+    }
+
+    /**
+     * Starts up notification dismiss and tells the notification, if any, to remove itself from
+     * layout.
+     *
+     * @param view view (e.g. notification) to dismiss from the layout
+     */
+    private void handleChildViewDismissed(View view) {
+        if (mDismissAllInProgress) {
+            return;
+        }
+
+        boolean isBlockingHelperShown = false;
+
+        setSwipingInProgress(false);
+        if (mDragAnimPendingChildren.contains(view)) {
+            // We start the swipe and finish it in the same frame; we don't want a drag animation.
+            mDragAnimPendingChildren.remove(view);
+        }
+        mAmbientState.onDragFinished(view);
+        updateContinuousShadowDrawing();
+
+        if (view instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+            if (row.isHeadsUp()) {
+                mHeadsUpManager.addSwipedOutNotification(row.getStatusBarNotification().getKey());
+            }
+            isBlockingHelperShown =
+                    row.performDismissWithBlockingHelper(false /* fromAccessibility */);
+        }
+
+        if (!isBlockingHelperShown) {
+            mSwipedOutViews.add(view);
+        }
+        mFalsingManager.onNotificationDismissed();
+        if (mFalsingManager.shouldEnforceBouncer()) {
+            mStatusBar.executeRunnableDismissingKeyguard(
+                    null,
+                    null /* cancelAction */,
+                    false /* dismissShade */,
+                    true /* afterKeyguardGone */,
+                    false /* deferred */);
+        }
+    }
+
+    @Override
+    public void onChildSnappedBack(View animView, float targetLeft) {
+        mAmbientState.onDragFinished(animView);
+        updateContinuousShadowDrawing();
+        if (!mDragAnimPendingChildren.contains(animView)) {
+            if (mAnimationsEnabled) {
+                mSnappedBackChildren.add(animView);
+                mNeedsAnimation = true;
+            }
+            requestChildrenUpdate();
+        } else {
+            // We start the swipe and snap back in the same frame, we don't want any animation
+            mDragAnimPendingChildren.remove(animView);
+        }
+        if (mCurrMenuRow != null && targetLeft == 0) {
+            mCurrMenuRow.resetMenu();
+            mCurrMenuRow = null;
+        }
+    }
+
+    @Override
+    public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) {
+        // Returning true prevents alpha fading.
+        return !mFadeNotificationsOnDismiss;
+    }
+
+    @Override
+    public void onBeginDrag(View v) {
+        mFalsingManager.onNotificatonStartDismissing();
+        setSwipingInProgress(true);
+        mAmbientState.onBeginDrag(v);
+        updateContinuousShadowDrawing();
+        if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
+            mDragAnimPendingChildren.add(v);
+            mNeedsAnimation = true;
+        }
+        requestChildrenUpdate();
+    }
+
+    public static boolean isPinnedHeadsUp(View v) {
+        if (v instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+            return row.isHeadsUp() && row.isPinned();
+        }
+        return false;
+    }
+
+    private boolean isHeadsUp(View v) {
+        if (v instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+            return row.isHeadsUp();
+        }
+        return false;
+    }
+
+    @Override
+    public void onDragCancelled(View v) {
+        mFalsingManager.onNotificatonStopDismissing();
+        setSwipingInProgress(false);
+    }
+
+    @Override
+    public float getFalsingThresholdFactor() {
+        return mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
+    }
+
+    @Override
+    public View getChildAtPosition(MotionEvent ev) {
+        View child = getChildAtPosition(ev.getX(), ev.getY());
+        if (child instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            ExpandableNotificationRow parent = row.getNotificationParent();
+            if (parent != null && parent.areChildrenExpanded()
+                    && (parent.areGutsExposed()
+                    || mMenuExposedView == parent
+                    || (parent.getNotificationChildren().size() == 1
+                    && parent.isClearable()))) {
+                // In this case the group is expanded and showing the menu for the
+                // group, further interaction should apply to the group, not any
+                // child notifications so we use the parent of the child. We also do the same
+                // if we only have a single child.
+                child = parent;
+            }
+        }
+        return child;
+    }
+
+    public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) {
+        getLocationOnScreen(mTempInt2);
+        float localTouchY = touchY - mTempInt2[1];
+
+        ExpandableView closestChild = null;
+        float minDist = Float.MAX_VALUE;
+
+        // find the view closest to the location, accounting for GONE views
+        final int count = getChildCount();
+        for (int childIdx = 0; childIdx < count; childIdx++) {
+            ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
+            if (slidingChild.getVisibility() == GONE
+                    || slidingChild instanceof StackScrollerDecorView) {
+                continue;
+            }
+            float childTop = slidingChild.getTranslationY();
+            float top = childTop + slidingChild.getClipTopAmount();
+            float bottom = childTop + slidingChild.getActualHeight()
+                    - slidingChild.getClipBottomAmount();
+
+            float dist = Math.min(Math.abs(top - localTouchY), Math.abs(bottom - localTouchY));
+            if (dist < minDist) {
+                closestChild = slidingChild;
+                minDist = dist;
+            }
+        }
+        return closestChild;
+    }
+
+    @Override
+    public ExpandableView getChildAtRawPosition(float touchX, float touchY) {
+        getLocationOnScreen(mTempInt2);
+        return getChildAtPosition(touchX - mTempInt2[0], touchY - mTempInt2[1]);
+    }
+
+    @Override
+    public ExpandableView getChildAtPosition(float touchX, float touchY) {
+        return getChildAtPosition(touchX, touchY, true /* requireMinHeight */);
+
+    }
+
+    /**
+     * Get the child at a certain screen location.
+     *
+     * @param touchX           the x coordinate
+     * @param touchY           the y coordinate
+     * @param requireMinHeight Whether a minimum height is required for a child to be returned.
+     * @return the child at the given location.
+     */
+    private ExpandableView getChildAtPosition(float touchX, float touchY,
+            boolean requireMinHeight) {
+        // find the view under the pointer, accounting for GONE views
+        final int count = getChildCount();
+        for (int childIdx = 0; childIdx < count; childIdx++) {
+            ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
+            if (slidingChild.getVisibility() != VISIBLE
+                    || slidingChild instanceof StackScrollerDecorView) {
+                continue;
+            }
+            float childTop = slidingChild.getTranslationY();
+            float top = childTop + slidingChild.getClipTopAmount();
+            float bottom = childTop + slidingChild.getActualHeight()
+                    - slidingChild.getClipBottomAmount();
+
+            // Allow the full width of this view to prevent gesture conflict on Keyguard (phone and
+            // camera affordance).
+            int left = 0;
+            int right = getWidth();
+
+            if ((bottom - top >= mMinInteractionHeight || !requireMinHeight)
+                    && touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
+                if (slidingChild instanceof ExpandableNotificationRow) {
+                    ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
+                    if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
+                            && mHeadsUpManager.getTopEntry().row != row
+                            && mGroupManager.getGroupSummary(
+                            mHeadsUpManager.getTopEntry().row.getStatusBarNotification())
+                            != row) {
+                        continue;
+                    }
+                    return row.getViewAtPosition(touchY - childTop);
+                }
+                return slidingChild;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean canChildBeExpanded(View v) {
+        return v instanceof ExpandableNotificationRow
+                && ((ExpandableNotificationRow) v).isExpandable()
+                && !((ExpandableNotificationRow) v).areGutsExposed()
+                && (mIsExpanded || !((ExpandableNotificationRow) v).isPinned());
+    }
+
+    /* Only ever called as a consequence of an expansion gesture in the shade. */
+    @Override
+    public void setUserExpandedChild(View v, boolean userExpanded) {
+        if (v instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+            if (userExpanded && onKeyguard()) {
+                // Due to a race when locking the screen while touching, a notification may be
+                // expanded even after we went back to keyguard. An example of this happens if
+                // you click in the empty space while expanding a group.
+
+                // We also need to un-user lock it here, since otherwise the content height
+                // calculated might be wrong. We also can't invert the two calls since
+                // un-userlocking it will trigger a layout switch in the content view.
+                row.setUserLocked(false);
+                updateContentHeight();
+                notifyHeightChangeListener(row);
+                return;
+            }
+            row.setUserExpanded(userExpanded, true /* allowChildrenExpansion */);
+            row.onExpandedByGesture(userExpanded);
+        }
+    }
+
+    @Override
+    public void setExpansionCancelled(View v) {
+        if (v instanceof ExpandableNotificationRow) {
+            ((ExpandableNotificationRow) v).setGroupExpansionChanging(false);
+        }
+    }
+
+    @Override
+    public void setUserLockedChild(View v, boolean userLocked) {
+        if (v instanceof ExpandableNotificationRow) {
+            ((ExpandableNotificationRow) v).setUserLocked(userLocked);
+        }
+        cancelLongPress();
+        requestDisallowInterceptTouchEvent(true);
+    }
+
+    @Override
+    public void expansionStateChanged(boolean isExpanding) {
+        mExpandingNotification = isExpanding;
+        if (!mExpandedInThisMotion) {
+            mMaxScrollAfterExpand = mOwnScrollY;
+            mExpandedInThisMotion = true;
+        }
+    }
+
+    @Override
+    public int getMaxExpandHeight(ExpandableView view) {
+        return view.getMaxContentHeight();
+    }
+
+    public void setScrollingEnabled(boolean enable) {
+        mScrollingEnabled = enable;
+    }
+
+    public void lockScrollTo(View v) {
+        if (mForcedScroll == v) {
+            return;
+        }
+        mForcedScroll = v;
+        scrollTo(v);
+    }
+
+    public boolean scrollTo(View v) {
+        ExpandableView expandableView = (ExpandableView) v;
+        int positionInLinearLayout = getPositionInLinearLayout(v);
+        int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
+        int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
+
+        // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
+        // that it is not visible anymore.
+        if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
+            mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
+            mDontReportNextOverScroll = true;
+            animateScroll();
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @return the scroll necessary to make the bottom edge of {@param v} align with the top of
+     * the IME.
+     */
+    private int targetScrollForView(ExpandableView v, int positionInLinearLayout) {
+        return positionInLinearLayout + v.getIntrinsicHeight() +
+                getImeInset() - getHeight()
+                + ((!isExpanded() && isPinnedHeadsUp(v)) ? mHeadsUpInset : getTopPadding());
+    }
+
+    @Override
+    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        mBottomInset = insets.getSystemWindowInsetBottom();
+
+        int range = getScrollRange();
+        if (mOwnScrollY > range) {
+            // HACK: We're repeatedly getting staggered insets here while the IME is
+            // animating away. To work around that we'll wait until things have settled.
+            removeCallbacks(mReclamp);
+            postDelayed(mReclamp, 50);
+        } else if (mForcedScroll != null) {
+            // The scroll was requested before we got the actual inset - in case we need
+            // to scroll up some more do so now.
+            scrollTo(mForcedScroll);
+        }
+        return insets;
+    }
+
+    private Runnable mReclamp = new Runnable() {
+        @Override
+        public void run() {
+            int range = getScrollRange();
+            mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY);
+            mDontReportNextOverScroll = true;
+            mDontClampNextScroll = true;
+            animateScroll();
+        }
+    };
+
+    private void setExpandingEnabled(boolean enable) {
+        mExpandHelper.setEnabled(enable);
+    }
+
+    private boolean isScrollingEnabled() {
+        return mScrollingEnabled;
+    }
+
+    @Override
+    public boolean canChildBeDismissed(View v) {
+        return StackScrollAlgorithm.canChildBeDismissed(v);
+    }
+
+    @Override
+    public boolean isAntiFalsingNeeded() {
+        return onKeyguard();
+    }
+
+    private boolean onKeyguard() {
+        return mStatusBarState == StatusBarState.KEYGUARD;
+    }
+
+    private void setSwipingInProgress(boolean isSwiped) {
+        mSwipingInProgress = isSwiped;
+        if (isSwiped) {
+            requestDisallowInterceptTouchEvent(true);
+        }
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        mStatusBarHeight = getResources().getDimensionPixelOffset(R.dimen.status_bar_height);
+        float densityScale = getResources().getDisplayMetrics().density;
+        mSwipeHelper.setDensityScale(densityScale);
+        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
+        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
+        initView(getContext());
+    }
+
+    public void dismissViewAnimated(View child, Runnable endRunnable, int delay, long duration) {
+        mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration,
+                true /* isDismissAll */);
+    }
+
+    @Override
+    public void snapViewIfNeeded(ExpandableNotificationRow child) {
+        boolean animate = mIsExpanded || isPinnedHeadsUp(child);
+        // If the child is showing the notification menu snap to that
+        float targetLeft = child.getProvider().isMenuVisible() ? child.getTranslation() : 0;
+        mSwipeHelper.snapChildIfNeeded(child, animate, targetLeft);
+    }
+
+    @Override
+    public ViewGroup getViewParentForNotification(NotificationData.Entry entry) {
+        return this;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        boolean isCancelOrUp = ev.getActionMasked() == MotionEvent.ACTION_CANCEL
+                || ev.getActionMasked() == MotionEvent.ACTION_UP;
+        handleEmptySpaceClick(ev);
+        boolean expandWantsIt = false;
+        if (mIsExpanded && !mSwipingInProgress && !mOnlyScrollingInThisMotion) {
+            if (isCancelOrUp) {
+                mExpandHelper.onlyObserveMovements(false);
+            }
+            boolean wasExpandingBefore = mExpandingNotification;
+            expandWantsIt = mExpandHelper.onTouchEvent(ev);
+            if (mExpandedInThisMotion && !mExpandingNotification && wasExpandingBefore
+                    && !mDisallowScrollingInThisMotion) {
+                dispatchDownEventToScroller(ev);
+            }
+        }
+        boolean scrollerWantsIt = false;
+        if (mIsExpanded && !mSwipingInProgress && !mExpandingNotification
+                && !mDisallowScrollingInThisMotion) {
+            scrollerWantsIt = onScrollTouch(ev);
+        }
+        boolean horizontalSwipeWantsIt = false;
+        if (!mIsBeingDragged
+                && !mExpandingNotification
+                && !mExpandedInThisMotion
+                && !mOnlyScrollingInThisMotion
+                && !mDisallowDismissInThisMotion) {
+            horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);
+        }
+
+        // Check if we need to clear any snooze leavebehinds
+        NotificationGuts guts = mStatusBar.getGutsManager().getExposedGuts();
+        if (guts != null && !isTouchInView(ev, guts)
+                && guts.getGutsContent() instanceof NotificationSnooze) {
+            NotificationSnooze ns = (NotificationSnooze) guts.getGutsContent();
+            if ((ns.isExpanded() && isCancelOrUp)
+                    || (!horizontalSwipeWantsIt && scrollerWantsIt)) {
+                // If the leavebehind is expanded we clear it on the next up event, otherwise we
+                // clear it on the next non-horizontal swipe or expand event.
+                checkSnoozeLeavebehind();
+            }
+        }
+        if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
+            mCheckForLeavebehind = true;
+        }
+        return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt || super.onTouchEvent(ev);
+    }
+
+    private void dispatchDownEventToScroller(MotionEvent ev) {
+        MotionEvent downEvent = MotionEvent.obtain(ev);
+        downEvent.setAction(MotionEvent.ACTION_DOWN);
+        onScrollTouch(downEvent);
+        downEvent.recycle();
+    }
+
+    @Override
+    public boolean onGenericMotionEvent(MotionEvent event) {
+        if (!isScrollingEnabled() || !mIsExpanded || mSwipingInProgress || mExpandingNotification
+                || mDisallowScrollingInThisMotion) {
+            return false;
+        }
+        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_SCROLL: {
+                    if (!mIsBeingDragged) {
+                        final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                        if (vscroll != 0) {
+                            final int delta = (int) (vscroll * getVerticalScrollFactor());
+                            final int range = getScrollRange();
+                            int oldScrollY = mOwnScrollY;
+                            int newScrollY = oldScrollY - delta;
+                            if (newScrollY < 0) {
+                                newScrollY = 0;
+                            } else if (newScrollY > range) {
+                                newScrollY = range;
+                            }
+                            if (newScrollY != oldScrollY) {
+                                setOwnScrollY(newScrollY);
+                                return true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return super.onGenericMotionEvent(event);
+    }
+
+    private boolean onScrollTouch(MotionEvent ev) {
+        if (!isScrollingEnabled()) {
+            return false;
+        }
+        if (isInsideQsContainer(ev) && !mIsBeingDragged) {
+            return false;
+        }
+        mForcedScroll = null;
+        initVelocityTrackerIfNotExists();
+        mVelocityTracker.addMovement(ev);
+
+        final int action = ev.getAction();
+
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN: {
+                if (getChildCount() == 0 || !isInContentBounds(ev)) {
+                    return false;
+                }
+                boolean isBeingDragged = !mScroller.isFinished();
+                setIsBeingDragged(isBeingDragged);
+                /*
+                 * If being flinged and user touches, stop the fling. isFinished
+                 * will be false if being flinged.
+                 */
+                if (!mScroller.isFinished()) {
+                    mScroller.forceFinished(true);
+                }
+
+                // Remember where the motion event started
+                mLastMotionY = (int) ev.getY();
+                mDownX = (int) ev.getX();
+                mActivePointerId = ev.getPointerId(0);
+                break;
+            }
+            case MotionEvent.ACTION_MOVE:
+                final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
+                if (activePointerIndex == -1) {
+                    Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent");
+                    break;
+                }
+
+                final int y = (int) ev.getY(activePointerIndex);
+                final int x = (int) ev.getX(activePointerIndex);
+                int deltaY = mLastMotionY - y;
+                final int xDiff = Math.abs(x - mDownX);
+                final int yDiff = Math.abs(deltaY);
+                if (!mIsBeingDragged && yDiff > mTouchSlop && yDiff > xDiff) {
+                    setIsBeingDragged(true);
+                    if (deltaY > 0) {
+                        deltaY -= mTouchSlop;
+                    } else {
+                        deltaY += mTouchSlop;
+                    }
+                }
+                if (mIsBeingDragged) {
+                    // Scroll to follow the motion event
+                    mLastMotionY = y;
+                    int range = getScrollRange();
+                    if (mExpandedInThisMotion) {
+                        range = Math.min(range, mMaxScrollAfterExpand);
+                    }
+
+                    float scrollAmount;
+                    if (deltaY < 0) {
+                        scrollAmount = overScrollDown(deltaY);
+                    } else {
+                        scrollAmount = overScrollUp(deltaY, range);
+                    }
+
+                    // Calling customOverScrollBy will call onCustomOverScrolled, which
+                    // sets the scrolling if applicable.
+                    if (scrollAmount != 0.0f) {
+                        // The scrolling motion could not be compensated with the
+                        // existing overScroll, we have to scroll the view
+                        customOverScrollBy((int) scrollAmount, mOwnScrollY,
+                                range, getHeight() / 2);
+                        // If we're scrolling, leavebehinds should be dismissed
+                        checkSnoozeLeavebehind();
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (mIsBeingDragged) {
+                    final VelocityTracker velocityTracker = mVelocityTracker;
+                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+                    int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
+
+                    if (shouldOverScrollFling(initialVelocity)) {
+                        onOverScrollFling(true, initialVelocity);
+                    } else {
+                        if (getChildCount() > 0) {
+                            if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
+                                float currentOverScrollTop = getCurrentOverScrollAmount(true);
+                                if (currentOverScrollTop == 0.0f || initialVelocity > 0) {
+                                    fling(-initialVelocity);
+                                } else {
+                                    onOverScrollFling(false, initialVelocity);
+                                }
+                            } else {
+                                if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
+                                        getScrollRange())) {
+                                    animateScroll();
+                                }
+                            }
+                        }
+                    }
+                    mActivePointerId = INVALID_POINTER;
+                    endDrag();
+                }
+
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                if (mIsBeingDragged && getChildCount() > 0) {
+                    if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
+                        animateScroll();
+                    }
+                    mActivePointerId = INVALID_POINTER;
+                    endDrag();
+                }
+                break;
+            case MotionEvent.ACTION_POINTER_DOWN: {
+                final int index = ev.getActionIndex();
+                mLastMotionY = (int) ev.getY(index);
+                mDownX = (int) ev.getX(index);
+                mActivePointerId = ev.getPointerId(index);
+                break;
+            }
+            case MotionEvent.ACTION_POINTER_UP:
+                onSecondaryPointerUp(ev);
+                mLastMotionY = (int) ev.getY(ev.findPointerIndex(mActivePointerId));
+                mDownX = (int) ev.getX(ev.findPointerIndex(mActivePointerId));
+                break;
+        }
+        return true;
+    }
+
+    protected boolean isInsideQsContainer(MotionEvent ev) {
+        return ev.getY() < mQsContainer.getBottom();
+    }
+
+    private void onOverScrollFling(boolean open, int initialVelocity) {
+        if (mOverscrollTopChangedListener != null) {
+            mOverscrollTopChangedListener.flingTopOverscroll(initialVelocity, open);
+        }
+        mDontReportNextOverScroll = true;
+        setOverScrollAmount(0.0f, true, false);
+    }
+
+    /**
+     * Perform a scroll upwards and adapt the overscroll amounts accordingly
+     *
+     * @param deltaY The amount to scroll upwards, has to be positive.
+     * @return The amount of scrolling to be performed by the scroller,
+     * not handled by the overScroll amount.
+     */
+    private float overScrollUp(int deltaY, int range) {
+        deltaY = Math.max(deltaY, 0);
+        float currentTopAmount = getCurrentOverScrollAmount(true);
+        float newTopAmount = currentTopAmount - deltaY;
+        if (currentTopAmount > 0) {
+            setOverScrollAmount(newTopAmount, true /* onTop */,
+                    false /* animate */);
+        }
+        // Top overScroll might not grab all scrolling motion,
+        // we have to scroll as well.
+        float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f;
+        float newScrollY = mOwnScrollY + scrollAmount;
+        if (newScrollY > range) {
+            if (!mExpandedInThisMotion) {
+                float currentBottomPixels = getCurrentOverScrolledPixels(false);
+                // We overScroll on the top
+                setOverScrolledPixels(currentBottomPixels + newScrollY - range,
+                        false /* onTop */,
+                        false /* animate */);
+            }
+            setOwnScrollY(range);
+            scrollAmount = 0.0f;
+        }
+        return scrollAmount;
+    }
+
+    /**
+     * Perform a scroll downward and adapt the overscroll amounts accordingly
+     *
+     * @param deltaY The amount to scroll downwards, has to be negative.
+     * @return The amount of scrolling to be performed by the scroller,
+     * not handled by the overScroll amount.
+     */
+    private float overScrollDown(int deltaY) {
+        deltaY = Math.min(deltaY, 0);
+        float currentBottomAmount = getCurrentOverScrollAmount(false);
+        float newBottomAmount = currentBottomAmount + deltaY;
+        if (currentBottomAmount > 0) {
+            setOverScrollAmount(newBottomAmount, false /* onTop */,
+                    false /* animate */);
+        }
+        // Bottom overScroll might not grab all scrolling motion,
+        // we have to scroll as well.
+        float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f;
+        float newScrollY = mOwnScrollY + scrollAmount;
+        if (newScrollY < 0) {
+            float currentTopPixels = getCurrentOverScrolledPixels(true);
+            // We overScroll on the top
+            setOverScrolledPixels(currentTopPixels - newScrollY,
+                    true /* onTop */,
+                    false /* animate */);
+            setOwnScrollY(0);
+            scrollAmount = 0.0f;
+        }
+        return scrollAmount;
+    }
+
+    private void onSecondaryPointerUp(MotionEvent ev) {
+        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
+                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+        final int pointerId = ev.getPointerId(pointerIndex);
+        if (pointerId == mActivePointerId) {
+            // This was our active pointer going up. Choose a new
+            // active pointer and adjust accordingly.
+            // TODO: Make this decision more intelligent.
+            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+            mLastMotionY = (int) ev.getY(newPointerIndex);
+            mActivePointerId = ev.getPointerId(newPointerIndex);
+            if (mVelocityTracker != null) {
+                mVelocityTracker.clear();
+            }
+        }
+    }
+
+    private void initVelocityTrackerIfNotExists() {
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        }
+    }
+
+    private void recycleVelocityTracker() {
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
+    }
+
+    private void initOrResetVelocityTracker() {
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        } else {
+            mVelocityTracker.clear();
+        }
+    }
+
+    public void setFinishScrollingCallback(Runnable runnable) {
+        mFinishScrollingCallback = runnable;
+    }
+
+    private void animateScroll() {
+        if (mScroller.computeScrollOffset()) {
+            int oldY = mOwnScrollY;
+            int y = mScroller.getCurrY();
+
+            if (oldY != y) {
+                int range = getScrollRange();
+                if (y < 0 && oldY >= 0 || y > range && oldY <= range) {
+                    float currVelocity = mScroller.getCurrVelocity();
+                    if (currVelocity >= mMinimumVelocity) {
+                        mMaxOverScroll = Math.abs(currVelocity) / 1000 * mOverflingDistance;
+                    }
+                }
+
+                if (mDontClampNextScroll) {
+                    range = Math.max(range, oldY);
+                }
+                customOverScrollBy(y - oldY, oldY, range,
+                        (int) (mMaxOverScroll));
+            }
+
+            postOnAnimation(mAnimateScroll);
+        } else {
+            mDontClampNextScroll = false;
+            if (mFinishScrollingCallback != null) {
+                mFinishScrollingCallback.run();
+            }
+        }
+    }
+
+    private boolean customOverScrollBy(int deltaY, int scrollY, int scrollRangeY,
+            int maxOverScrollY) {
+
+        int newScrollY = scrollY + deltaY;
+        final int top = -maxOverScrollY;
+        final int bottom = maxOverScrollY + scrollRangeY;
+
+        boolean clampedY = false;
+        if (newScrollY > bottom) {
+            newScrollY = bottom;
+            clampedY = true;
+        } else if (newScrollY < top) {
+            newScrollY = top;
+            clampedY = true;
+        }
+
+        onCustomOverScrolled(newScrollY, clampedY);
+
+        return clampedY;
+    }
+
+    /**
+     * Set the amount of overScrolled pixels which will force the view to apply a rubber-banded
+     * overscroll effect based on numPixels. By default this will also cancel animations on the
+     * same overScroll edge.
+     *
+     * @param numPixels The amount of pixels to overScroll by. These will be scaled according to
+     *                  the rubber-banding logic.
+     * @param onTop     Should the effect be applied on top of the scroller.
+     * @param animate   Should an animation be performed.
+     */
+    public void setOverScrolledPixels(float numPixels, boolean onTop, boolean animate) {
+        setOverScrollAmount(numPixels * getRubberBandFactor(onTop), onTop, animate, true);
+    }
+
+    /**
+     * Set the effective overScroll amount which will be directly reflected in the layout.
+     * By default this will also cancel animations on the same overScroll edge.
+     *
+     * @param amount  The amount to overScroll by.
+     * @param onTop   Should the effect be applied on top of the scroller.
+     * @param animate Should an animation be performed.
+     */
+    public void setOverScrollAmount(float amount, boolean onTop, boolean animate) {
+        setOverScrollAmount(amount, onTop, animate, true);
+    }
+
+    /**
+     * Set the effective overScroll amount which will be directly reflected in the layout.
+     *
+     * @param amount          The amount to overScroll by.
+     * @param onTop           Should the effect be applied on top of the scroller.
+     * @param animate         Should an animation be performed.
+     * @param cancelAnimators Should running animations be cancelled.
+     */
+    public void setOverScrollAmount(float amount, boolean onTop, boolean animate,
+            boolean cancelAnimators) {
+        setOverScrollAmount(amount, onTop, animate, cancelAnimators, isRubberbanded(onTop));
+    }
+
+    /**
+     * Set the effective overScroll amount which will be directly reflected in the layout.
+     *
+     * @param amount          The amount to overScroll by.
+     * @param onTop           Should the effect be applied on top of the scroller.
+     * @param animate         Should an animation be performed.
+     * @param cancelAnimators Should running animations be cancelled.
+     * @param isRubberbanded  The value which will be passed to
+     *                        {@link OnOverscrollTopChangedListener#onOverscrollTopChanged}
+     */
+    public void setOverScrollAmount(float amount, boolean onTop, boolean animate,
+            boolean cancelAnimators, boolean isRubberbanded) {
+        if (cancelAnimators) {
+            mStateAnimator.cancelOverScrollAnimators(onTop);
+        }
+        setOverScrollAmountInternal(amount, onTop, animate, isRubberbanded);
+    }
+
+    private void setOverScrollAmountInternal(float amount, boolean onTop, boolean animate,
+            boolean isRubberbanded) {
+        amount = Math.max(0, amount);
+        if (animate) {
+            mStateAnimator.animateOverScrollToAmount(amount, onTop, isRubberbanded);
+        } else {
+            setOverScrolledPixels(amount / getRubberBandFactor(onTop), onTop);
+            mAmbientState.setOverScrollAmount(amount, onTop);
+            if (onTop) {
+                notifyOverscrollTopListener(amount, isRubberbanded);
+            }
+            requestChildrenUpdate();
+        }
+    }
+
+    private void notifyOverscrollTopListener(float amount, boolean isRubberbanded) {
+        mExpandHelper.onlyObserveMovements(amount > 1.0f);
+        if (mDontReportNextOverScroll) {
+            mDontReportNextOverScroll = false;
+            return;
+        }
+        if (mOverscrollTopChangedListener != null) {
+            mOverscrollTopChangedListener.onOverscrollTopChanged(amount, isRubberbanded);
+        }
+    }
+
+    public void setOverscrollTopChangedListener(
+            OnOverscrollTopChangedListener overscrollTopChangedListener) {
+        mOverscrollTopChangedListener = overscrollTopChangedListener;
+    }
+
+    public float getCurrentOverScrollAmount(boolean top) {
+        return mAmbientState.getOverScrollAmount(top);
+    }
+
+    public float getCurrentOverScrolledPixels(boolean top) {
+        return top ? mOverScrolledTopPixels : mOverScrolledBottomPixels;
+    }
+
+    private void setOverScrolledPixels(float amount, boolean onTop) {
+        if (onTop) {
+            mOverScrolledTopPixels = amount;
+        } else {
+            mOverScrolledBottomPixels = amount;
+        }
+    }
+
+    private void onCustomOverScrolled(int scrollY, boolean clampedY) {
+        // Treat animating scrolls differently; see #computeScroll() for why.
+        if (!mScroller.isFinished()) {
+            setOwnScrollY(scrollY);
+            if (clampedY) {
+                springBack();
+            } else {
+                float overScrollTop = getCurrentOverScrollAmount(true);
+                if (mOwnScrollY < 0) {
+                    notifyOverscrollTopListener(-mOwnScrollY, isRubberbanded(true));
+                } else {
+                    notifyOverscrollTopListener(overScrollTop, isRubberbanded(true));
+                }
+            }
+        } else {
+            setOwnScrollY(scrollY);
+        }
+    }
+
+    private void springBack() {
+        int scrollRange = getScrollRange();
+        boolean overScrolledTop = mOwnScrollY <= 0;
+        boolean overScrolledBottom = mOwnScrollY >= scrollRange;
+        if (overScrolledTop || overScrolledBottom) {
+            boolean onTop;
+            float newAmount;
+            if (overScrolledTop) {
+                onTop = true;
+                newAmount = -mOwnScrollY;
+                setOwnScrollY(0);
+                mDontReportNextOverScroll = true;
+            } else {
+                onTop = false;
+                newAmount = mOwnScrollY - scrollRange;
+                setOwnScrollY(scrollRange);
+            }
+            setOverScrollAmount(newAmount, onTop, false);
+            setOverScrollAmount(0.0f, onTop, true);
+            mScroller.forceFinished(true);
+        }
+    }
+
+    private int getScrollRange() {
+        // In current design, it only use the top HUN to treat all of HUNs
+        // although there are more than one HUNs
+        int contentHeight = mContentHeight;
+        if (!isExpanded() && mHeadsUpManager.hasPinnedHeadsUp()) {
+            contentHeight = mHeadsUpInset + getTopHeadsUpPinnedHeight();
+        }
+        int scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight);
+        int imeInset = getImeInset();
+        scrollRange += Math.min(imeInset, Math.max(0, contentHeight - (getHeight() - imeInset)));
+        return scrollRange;
+    }
+
+    private int getImeInset() {
+        return Math.max(0, mBottomInset - (getRootView().getHeight() - getHeight()));
+    }
+
+    /**
+     * @return the first child which has visibility unequal to GONE
+     */
+    public ExpandableView getFirstChildNotGone() {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE && child != mShelf) {
+                return (ExpandableView) child;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @return the child before the given view which has visibility unequal to GONE
+     */
+    public ExpandableView getViewBeforeView(ExpandableView view) {
+        ExpandableView previousView = null;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child == view) {
+                return previousView;
+            }
+            if (child.getVisibility() != View.GONE) {
+                previousView = (ExpandableView) child;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @return The first child which has visibility unequal to GONE which is currently below the
+     * given translationY or equal to it.
+     */
+    private View getFirstChildBelowTranlsationY(float translationY, boolean ignoreChildren) {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() == View.GONE) {
+                continue;
+            }
+            float rowTranslation = child.getTranslationY();
+            if (rowTranslation >= translationY) {
+                return child;
+            } else if (!ignoreChildren && child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                if (row.isSummaryWithChildren() && row.areChildrenExpanded()) {
+                    List<ExpandableNotificationRow> notificationChildren =
+                            row.getNotificationChildren();
+                    for (int childIndex = 0; childIndex < notificationChildren.size();
+                            childIndex++) {
+                        ExpandableNotificationRow rowChild = notificationChildren.get(childIndex);
+                        if (rowChild.getTranslationY() + rowTranslation >= translationY) {
+                            return rowChild;
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @return the last child which has visibility unequal to GONE
+     */
+    public View getLastChildNotGone() {
+        int childCount = getChildCount();
+        for (int i = childCount - 1; i >= 0; i--) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE && child != mShelf) {
+                return child;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @return the number of children which have visibility unequal to GONE
+     */
+    public int getNotGoneChildCount() {
+        int childCount = getChildCount();
+        int count = 0;
+        for (int i = 0; i < childCount; i++) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child.getVisibility() != View.GONE && !child.willBeGone() && child != mShelf) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    private void updateContentHeight() {
+        int height = 0;
+        float previousPaddingRequest = mPaddingBetweenElements;
+        float previousPaddingAmount = 0.0f;
+        int numShownItems = 0;
+        boolean finish = false;
+        int maxDisplayedNotifications = mAmbientState.isFullyDark()
+                ? (hasPulsingNotifications() ? 1 : 0)
+                : mMaxDisplayedNotifications;
+
+        for (int i = 0; i < getChildCount(); i++) {
+            ExpandableView expandableView = (ExpandableView) getChildAt(i);
+            boolean footerViewOnLockScreen = expandableView == mFooterView && onKeyguard();
+            if (expandableView.getVisibility() != View.GONE
+                    && !expandableView.hasNoContentHeight() && !footerViewOnLockScreen) {
+                boolean limitReached = maxDisplayedNotifications != -1
+                        && numShownItems >= maxDisplayedNotifications;
+                boolean notificationOnAmbientThatIsNotPulsing = mAmbientState.isFullyDark()
+                        && hasPulsingNotifications()
+                        && expandableView instanceof ExpandableNotificationRow
+                        && !isPulsing(((ExpandableNotificationRow) expandableView).getEntry());
+                if (limitReached || notificationOnAmbientThatIsNotPulsing) {
+                    expandableView = mShelf;
+                    finish = true;
+                }
+                float increasedPaddingAmount = expandableView.getIncreasedPaddingAmount();
+                float padding;
+                if (increasedPaddingAmount >= 0.0f) {
+                    padding = (int) NotificationUtils.interpolate(
+                            previousPaddingRequest,
+                            mIncreasedPaddingBetweenElements,
+                            increasedPaddingAmount);
+                    previousPaddingRequest = (int) NotificationUtils.interpolate(
+                            mPaddingBetweenElements,
+                            mIncreasedPaddingBetweenElements,
+                            increasedPaddingAmount);
+                } else {
+                    int ownPadding = (int) NotificationUtils.interpolate(
+                            0,
+                            mPaddingBetweenElements,
+                            1.0f + increasedPaddingAmount);
+                    if (previousPaddingAmount > 0.0f) {
+                        padding = (int) NotificationUtils.interpolate(
+                                ownPadding,
+                                mIncreasedPaddingBetweenElements,
+                                previousPaddingAmount);
+                    } else {
+                        padding = ownPadding;
+                    }
+                    previousPaddingRequest = ownPadding;
+                }
+                if (height != 0) {
+                    height += padding;
+                }
+                previousPaddingAmount = increasedPaddingAmount;
+                height += expandableView.getIntrinsicHeight();
+                numShownItems++;
+                if (finish) {
+                    break;
+                }
+            }
+        }
+        mIntrinsicContentHeight = height;
+
+        // We don't want to use the toppadding since that might be interpolated and we want
+        // to take the final value of the animation.
+        int topPadding = mAmbientState.isFullyDark() ? mDarkTopPadding : mRegularTopPadding;
+        mContentHeight = height + topPadding + mBottomMargin;
+        updateScrollability();
+        clampScrollPosition();
+        mAmbientState.setLayoutMaxHeight(mContentHeight);
+    }
+
+    private boolean isPulsing(NotificationData.Entry entry) {
+        return mAmbientState.isPulsing(entry);
+    }
+
+    @Override
+    public boolean hasPulsingNotifications() {
+        return mPulsing;
+    }
+
+    private void updateScrollability() {
+        boolean scrollable = !mQsExpanded && getScrollRange() > 0;
+        if (scrollable != mScrollable) {
+            mScrollable = scrollable;
+            setFocusable(scrollable);
+            updateForwardAndBackwardScrollability();
+        }
+    }
+
+    private void updateForwardAndBackwardScrollability() {
+        boolean forwardScrollable = mScrollable && mOwnScrollY < getScrollRange();
+        boolean backwardsScrollable = mScrollable && mOwnScrollY > 0;
+        boolean changed = forwardScrollable != mForwardScrollable
+                || backwardsScrollable != mBackwardScrollable;
+        mForwardScrollable = forwardScrollable;
+        mBackwardScrollable = backwardsScrollable;
+        if (changed) {
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+        }
+    }
+
+    private void updateBackground() {
+        // No need to update the background color if it's not being drawn.
+        if (!mShouldDrawNotificationBackground || mAmbientState.isFullyDark()) {
+            return;
+        }
+
+        updateBackgroundBounds();
+        if (!mCurrentBounds.equals(mBackgroundBounds)) {
+            boolean animate = mAnimateNextBackgroundTop || mAnimateNextBackgroundBottom
+                    || areBoundsAnimating();
+            if (!isExpanded()) {
+                abortBackgroundAnimators();
+                animate = false;
+            }
+            if (animate) {
+                startBackgroundAnimation();
+            } else {
+                mCurrentBounds.set(mBackgroundBounds);
+                applyCurrentBackgroundBounds();
+            }
+        } else {
+            abortBackgroundAnimators();
+        }
+        mAnimateNextBackgroundBottom = false;
+        mAnimateNextBackgroundTop = false;
+    }
+
+    private void abortBackgroundAnimators() {
+        if (mBottomAnimator != null) {
+            mBottomAnimator.cancel();
+        }
+        if (mTopAnimator != null) {
+            mTopAnimator.cancel();
+        }
+    }
+
+    private boolean areBoundsAnimating() {
+        return mBottomAnimator != null || mTopAnimator != null;
+    }
+
+    private void startBackgroundAnimation() {
+        // left and right are always instantly applied
+        mCurrentBounds.left = mBackgroundBounds.left;
+        mCurrentBounds.right = mBackgroundBounds.right;
+        startBottomAnimation();
+        startTopAnimation();
+    }
+
+    private void startTopAnimation() {
+        int previousEndValue = mEndAnimationRect.top;
+        int newEndValue = mBackgroundBounds.top;
+        ObjectAnimator previousAnimator = mTopAnimator;
+        if (previousAnimator != null && previousEndValue == newEndValue) {
+            return;
+        }
+        if (!mAnimateNextBackgroundTop) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                int previousStartValue = mStartAnimationRect.top;
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                values[0].setIntValues(previousStartValue, newEndValue);
+                mStartAnimationRect.top = previousStartValue;
+                mEndAnimationRect.top = newEndValue;
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                setBackgroundTop(newEndValue);
+                return;
+            }
+        }
+        if (previousAnimator != null) {
+            previousAnimator.cancel();
+        }
+        ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundTop",
+                mCurrentBounds.top, newEndValue);
+        Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN;
+        animator.setInterpolator(interpolator);
+        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mStartAnimationRect.top = -1;
+                mEndAnimationRect.top = -1;
+                mTopAnimator = null;
+            }
+        });
+        animator.start();
+        mStartAnimationRect.top = mCurrentBounds.top;
+        mEndAnimationRect.top = newEndValue;
+        mTopAnimator = animator;
+    }
+
+    private void startBottomAnimation() {
+        int previousStartValue = mStartAnimationRect.bottom;
+        int previousEndValue = mEndAnimationRect.bottom;
+        int newEndValue = mBackgroundBounds.bottom;
+        ObjectAnimator previousAnimator = mBottomAnimator;
+        if (previousAnimator != null && previousEndValue == newEndValue) {
+            return;
+        }
+        if (!mAnimateNextBackgroundBottom) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                values[0].setIntValues(previousStartValue, newEndValue);
+                mStartAnimationRect.bottom = previousStartValue;
+                mEndAnimationRect.bottom = newEndValue;
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                setBackgroundBottom(newEndValue);
+                return;
+            }
+        }
+        if (previousAnimator != null) {
+            previousAnimator.cancel();
+        }
+        ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundBottom",
+                mCurrentBounds.bottom, newEndValue);
+        Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN;
+        animator.setInterpolator(interpolator);
+        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mStartAnimationRect.bottom = -1;
+                mEndAnimationRect.bottom = -1;
+                mBottomAnimator = null;
+            }
+        });
+        animator.start();
+        mStartAnimationRect.bottom = mCurrentBounds.bottom;
+        mEndAnimationRect.bottom = newEndValue;
+        mBottomAnimator = animator;
+    }
+
+    private void setBackgroundTop(int top) {
+        mCurrentBounds.top = top;
+        applyCurrentBackgroundBounds();
+    }
+
+    public void setBackgroundBottom(int bottom) {
+        mCurrentBounds.bottom = bottom;
+        applyCurrentBackgroundBounds();
+    }
+
+    private void applyCurrentBackgroundBounds() {
+        // If the background of the notification is not being drawn, then there is no need to
+        // exclude an area in the scrim. Rather, the scrim's color should serve as the background.
+        if (!mShouldDrawNotificationBackground) {
+            return;
+        }
+
+        final boolean awake = mInterpolatedDarkAmount != 0 || mAmbientState.isDark();
+        mScrimController.setExcludedBackgroundArea(
+                mFadingOut || mParentNotFullyVisible || awake || mIsClipped ? null
+                        : mCurrentBounds);
+        invalidate();
+    }
+
+    /**
+     * Update the background bounds to the new desired bounds
+     */
+    private void updateBackgroundBounds() {
+        getLocationInWindow(mTempInt2);
+        mBackgroundBounds.left = mTempInt2[0] + mSidePaddings;
+        mBackgroundBounds.right = mTempInt2[0] + getWidth() - mSidePaddings;
+
+        if (!mIsExpanded) {
+            mBackgroundBounds.top = 0;
+            mBackgroundBounds.bottom = 0;
+            return;
+        }
+        ActivatableNotificationView firstView = mFirstVisibleBackgroundChild;
+        int top = 0;
+        if (firstView != null) {
+            // Round Y up to avoid seeing the background during animation
+            int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView));
+            if (mAnimateNextBackgroundTop
+                    || mTopAnimator == null && mCurrentBounds.top == finalTranslationY
+                    || mTopAnimator != null && mEndAnimationRect.top == finalTranslationY) {
+                // we're ending up at the same location as we are now, lets just skip the animation
+                top = finalTranslationY;
+            } else {
+                top = (int) Math.ceil(firstView.getTranslationY());
+            }
+        }
+        ActivatableNotificationView lastView =
+                mShelf.hasItemsInStableShelf() && mShelf.getVisibility() != GONE
+                        ? mShelf
+                        : mLastVisibleBackgroundChild;
+        int bottom;
+        if (lastView != null) {
+            int finalTranslationY;
+            if (lastView == mShelf) {
+                finalTranslationY = (int) mShelf.getTranslationY();
+            } else {
+                finalTranslationY = (int) ViewState.getFinalTranslationY(lastView);
+            }
+            int finalHeight = ExpandableViewState.getFinalActualHeight(lastView);
+            int finalBottom = finalTranslationY + finalHeight - lastView.getClipBottomAmount();
+            if (mAnimateNextBackgroundBottom
+                    || mBottomAnimator == null && mCurrentBounds.bottom == finalBottom
+                    || mBottomAnimator != null && mEndAnimationRect.bottom == finalBottom) {
+                // we're ending up at the same location as we are now, lets just skip the animation
+                bottom = finalBottom;
+            } else {
+                bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight()
+                        - lastView.getClipBottomAmount());
+            }
+        } else {
+            top = mTopPadding;
+            bottom = top;
+        }
+        if (mStatusBarState != StatusBarState.KEYGUARD) {
+            top = (int) Math.max(mTopPadding + mStackTranslation, top);
+        } else {
+            // otherwise the animation from the shade to the keyguard will jump as it's maxed
+            top = Math.max(0, top);
+        }
+        mBackgroundBounds.top = top;
+        mBackgroundBounds.bottom = Math.max(bottom, top);
+    }
+
+    private ActivatableNotificationView getFirstPinnedHeadsUp() {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE
+                    && child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                if (row.isPinned()) {
+                    return row;
+                }
+            }
+        }
+        return null;
+    }
+
+    private ActivatableNotificationView getLastChildWithBackground() {
+        int childCount = getChildCount();
+        for (int i = childCount - 1; i >= 0; i--) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
+                    && child != mShelf) {
+                return (ActivatableNotificationView) child;
+            }
+        }
+        return null;
+    }
+
+    private ActivatableNotificationView getFirstChildWithBackground() {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
+                    && child != mShelf) {
+                return (ActivatableNotificationView) child;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Fling the scroll view
+     *
+     * @param velocityY The initial velocity in the Y direction. Positive
+     *                  numbers mean that the finger/cursor is moving down the screen,
+     *                  which means we want to scroll towards the top.
+     */
+    protected void fling(int velocityY) {
+        if (getChildCount() > 0) {
+            int scrollRange = getScrollRange();
+
+            float topAmount = getCurrentOverScrollAmount(true);
+            float bottomAmount = getCurrentOverScrollAmount(false);
+            if (velocityY < 0 && topAmount > 0) {
+                setOwnScrollY(mOwnScrollY - (int) topAmount);
+                mDontReportNextOverScroll = true;
+                setOverScrollAmount(0, true, false);
+                mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor(true /* onTop */)
+                        * mOverflingDistance + topAmount;
+            } else if (velocityY > 0 && bottomAmount > 0) {
+                setOwnScrollY((int) (mOwnScrollY + bottomAmount));
+                setOverScrollAmount(0, false, false);
+                mMaxOverScroll = Math.abs(velocityY) / 1000f
+                        * getRubberBandFactor(false /* onTop */) * mOverflingDistance
+                        + bottomAmount;
+            } else {
+                // it will be set once we reach the boundary
+                mMaxOverScroll = 0.0f;
+            }
+            int minScrollY = Math.max(0, scrollRange);
+            if (mExpandedInThisMotion) {
+                minScrollY = Math.min(minScrollY, mMaxScrollAfterExpand);
+            }
+            mScroller.fling(mScrollX, mOwnScrollY, 1, velocityY, 0, 0, 0, minScrollY, 0,
+                    mExpandedInThisMotion && mOwnScrollY >= 0 ? 0 : Integer.MAX_VALUE / 2);
+
+            animateScroll();
+        }
+    }
+
+    /**
+     * @return Whether a fling performed on the top overscroll edge lead to the expanded
+     * overScroll view (i.e QS).
+     */
+    private boolean shouldOverScrollFling(int initialVelocity) {
+        float topOverScroll = getCurrentOverScrollAmount(true);
+        return mScrolledToTopOnFirstDown
+                && !mExpandedInThisMotion
+                && topOverScroll > mMinTopOverScrollToEscape
+                && initialVelocity > 0;
+    }
+
+    /**
+     * Updates the top padding of the notifications, taking {@link #getIntrinsicPadding()} into
+     * account.
+     *
+     * @param qsHeight               the top padding imposed by the quick settings panel
+     * @param animate                whether to animate the change
+     * @param ignoreIntrinsicPadding if true, {@link #getIntrinsicPadding()} is ignored and
+     *                               {@code qsHeight} is the final top padding
+     */
+    public void updateTopPadding(float qsHeight, boolean animate,
+            boolean ignoreIntrinsicPadding) {
+        int topPadding = (int) qsHeight;
+        int minStackHeight = getLayoutMinHeight();
+        if (topPadding + minStackHeight > getHeight()) {
+            mTopPaddingOverflow = topPadding + minStackHeight - getHeight();
+        } else {
+            mTopPaddingOverflow = 0;
+        }
+        setTopPadding(ignoreIntrinsicPadding ? topPadding : clampPadding(topPadding),
+                animate);
+        setExpandedHeight(mExpandedHeight);
+    }
+
+    public void setMaxTopPadding(int maxTopPadding) {
+        mMaxTopPadding = maxTopPadding;
+    }
+
+    public int getLayoutMinHeight() {
+        if (isHeadsUpTransition()) {
+            return getTopHeadsUpPinnedHeight();
+        }
+        return mShelf.getVisibility() == GONE ? 0 : mShelf.getIntrinsicHeight();
+    }
+
+    public int getFirstChildIntrinsicHeight() {
+        final ExpandableView firstChild = getFirstChildNotGone();
+        int firstChildMinHeight = firstChild != null
+                ? firstChild.getIntrinsicHeight()
+                : mEmptyShadeView != null
+                        ? mEmptyShadeView.getIntrinsicHeight()
+                        : mCollapsedSize;
+        if (mOwnScrollY > 0) {
+            firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
+        }
+        return firstChildMinHeight;
+    }
+
+    public float getTopPaddingOverflow() {
+        return mTopPaddingOverflow;
+    }
+
+    public int getPeekHeight() {
+        final ExpandableView firstChild = getFirstChildNotGone();
+        final int firstChildMinHeight = firstChild != null ? firstChild.getCollapsedHeight()
+                : mCollapsedSize;
+        int shelfHeight = 0;
+        if (mLastVisibleBackgroundChild != null && mShelf.getVisibility() != GONE) {
+            shelfHeight = mShelf.getIntrinsicHeight();
+        }
+        return mIntrinsicPadding + firstChildMinHeight + shelfHeight;
+    }
+
+    private int clampPadding(int desiredPadding) {
+        return Math.max(desiredPadding, mIntrinsicPadding);
+    }
+
+    private float getRubberBandFactor(boolean onTop) {
+        if (!onTop) {
+            return RUBBER_BAND_FACTOR_NORMAL;
+        }
+        if (mExpandedInThisMotion) {
+            return RUBBER_BAND_FACTOR_AFTER_EXPAND;
+        } else if (mIsExpansionChanging || mPanelTracking) {
+            return RUBBER_BAND_FACTOR_ON_PANEL_EXPAND;
+        } else if (mScrolledToTopOnFirstDown) {
+            return 1.0f;
+        }
+        return RUBBER_BAND_FACTOR_NORMAL;
+    }
+
+    /**
+     * Accompanying function for {@link #getRubberBandFactor}: Returns true if the overscroll is
+     * rubberbanded, false if it is technically an overscroll but rather a motion to expand the
+     * overscroll view (e.g. expand QS).
+     */
+    private boolean isRubberbanded(boolean onTop) {
+        return !onTop || mExpandedInThisMotion || mIsExpansionChanging || mPanelTracking
+                || !mScrolledToTopOnFirstDown;
+    }
+
+    private void endDrag() {
+        setIsBeingDragged(false);
+
+        recycleVelocityTracker();
+
+        if (getCurrentOverScrollAmount(true /* onTop */) > 0) {
+            setOverScrollAmount(0, true /* onTop */, true /* animate */);
+        }
+        if (getCurrentOverScrollAmount(false /* onTop */) > 0) {
+            setOverScrollAmount(0, false /* onTop */, true /* animate */);
+        }
+    }
+
+    private void transformTouchEvent(MotionEvent ev, View sourceView, View targetView) {
+        ev.offsetLocation(sourceView.getX(), sourceView.getY());
+        ev.offsetLocation(-targetView.getX(), -targetView.getY());
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        initDownStates(ev);
+        handleEmptySpaceClick(ev);
+        boolean expandWantsIt = false;
+        if (!mSwipingInProgress && !mOnlyScrollingInThisMotion) {
+            expandWantsIt = mExpandHelper.onInterceptTouchEvent(ev);
+        }
+        boolean scrollWantsIt = false;
+        if (!mSwipingInProgress && !mExpandingNotification) {
+            scrollWantsIt = onInterceptTouchEventScroll(ev);
+        }
+        boolean swipeWantsIt = false;
+        if (!mIsBeingDragged
+                && !mExpandingNotification
+                && !mExpandedInThisMotion
+                && !mOnlyScrollingInThisMotion
+                && !mDisallowDismissInThisMotion) {
+            swipeWantsIt = mSwipeHelper.onInterceptTouchEvent(ev);
+        }
+        // Check if we need to clear any snooze leavebehinds
+        boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
+        NotificationGuts guts = mStatusBar.getGutsManager().getExposedGuts();
+        if (!isTouchInView(ev, guts) && isUp && !swipeWantsIt && !expandWantsIt
+                && !scrollWantsIt) {
+            mCheckForLeavebehind = false;
+            mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
+                    false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
+                    false /* resetMenu */);
+        }
+        if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
+            mCheckForLeavebehind = true;
+        }
+        return swipeWantsIt || scrollWantsIt || expandWantsIt || super.onInterceptTouchEvent(ev);
+    }
+
+    private void handleEmptySpaceClick(MotionEvent ev) {
+        switch (ev.getActionMasked()) {
+            case MotionEvent.ACTION_MOVE:
+                if (mTouchIsClick && (Math.abs(ev.getY() - mInitialTouchY) > mTouchSlop
+                        || Math.abs(ev.getX() - mInitialTouchX) > mTouchSlop)) {
+                    mTouchIsClick = false;
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (mStatusBarState != StatusBarState.KEYGUARD && mTouchIsClick &&
+                        isBelowLastNotification(mInitialTouchX, mInitialTouchY)) {
+                    mOnEmptySpaceClickListener.onEmptySpaceClicked(mInitialTouchX, mInitialTouchY);
+                }
+                break;
+        }
+    }
+
+    private void initDownStates(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            mExpandedInThisMotion = false;
+            mOnlyScrollingInThisMotion = !mScroller.isFinished();
+            mDisallowScrollingInThisMotion = false;
+            mDisallowDismissInThisMotion = false;
+            mTouchIsClick = true;
+            mInitialTouchX = ev.getX();
+            mInitialTouchY = ev.getY();
+        }
+    }
+
+    public void setChildTransferInProgress(boolean childTransferInProgress) {
+        mChildTransferInProgress = childTransferInProgress;
+    }
+
+    @Override
+    public void onViewRemoved(View child) {
+        super.onViewRemoved(child);
+        // we only call our internal methods if this is actually a removal and not just a
+        // notification which becomes a child notification
+        if (!mChildTransferInProgress) {
+            onViewRemovedInternal(child, this);
+        }
+    }
+
+    @Override
+    public void cleanUpViewState(View child) {
+        if (child == mTranslatingParentView) {
+            mTranslatingParentView = null;
+        }
+        mCurrentStackScrollState.removeViewStateForView(child);
+    }
+
+    @Override
+    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+        super.requestDisallowInterceptTouchEvent(disallowIntercept);
+        if (disallowIntercept) {
+            cancelLongPress();
+        }
+    }
+
+    private void onViewRemovedInternal(View child, ViewGroup container) {
+        if (mChangePositionInProgress) {
+            // This is only a position change, don't do anything special
+            return;
+        }
+        ExpandableView expandableView = (ExpandableView) child;
+        expandableView.setOnHeightChangedListener(null);
+        mCurrentStackScrollState.removeViewStateForView(child);
+        updateScrollStateForRemovedChild(expandableView);
+        boolean animationGenerated = generateRemoveAnimation(child);
+        if (animationGenerated) {
+            if (!mSwipedOutViews.contains(child)
+                    || Math.abs(expandableView.getTranslation()) != expandableView.getWidth()) {
+                container.addTransientView(child, 0);
+                expandableView.setTransientContainer(container);
+            }
+        } else {
+            mSwipedOutViews.remove(child);
+        }
+        updateAnimationState(false, child);
+
+        focusNextViewIfFocused(child);
+    }
+
+    private void focusNextViewIfFocused(View view) {
+        if (view instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+            if (row.shouldRefocusOnDismiss()) {
+                View nextView = row.getChildAfterViewWhenDismissed();
+                if (nextView == null) {
+                    View groupParentWhenDismissed = row.getGroupParentWhenDismissed();
+                    nextView = getFirstChildBelowTranlsationY(groupParentWhenDismissed != null
+                            ? groupParentWhenDismissed.getTranslationY()
+                            : view.getTranslationY(), true /* ignoreChildren */);
+                }
+                if (nextView != null) {
+                    nextView.requestAccessibilityFocus();
+                }
+            }
+        }
+
+    }
+
+    private boolean isChildInGroup(View child) {
+        return child instanceof ExpandableNotificationRow
+                && mGroupManager.isChildInGroupWithSummary(
+                ((ExpandableNotificationRow) child).getStatusBarNotification());
+    }
+
+    /**
+     * Generate a remove animation for a child view.
+     *
+     * @param child The view to generate the remove animation for.
+     * @return Whether an animation was generated.
+     */
+    private boolean generateRemoveAnimation(View child) {
+        if (removeRemovedChildFromHeadsUpChangeAnimations(child)) {
+            mAddedHeadsUpChildren.remove(child);
+            return false;
+        }
+        if (isClickedHeadsUp(child)) {
+            // An animation is already running, add it transiently
+            mClearTransientViewsWhenFinished.add((ExpandableView) child);
+            return true;
+        }
+        if (mIsExpanded && mAnimationsEnabled && !isChildInInvisibleGroup(child)) {
+            if (!mChildrenToAddAnimated.contains(child)) {
+                // Generate Animations
+                mChildrenToRemoveAnimated.add(child);
+                mNeedsAnimation = true;
+                return true;
+            } else {
+                mChildrenToAddAnimated.remove(child);
+                mFromMoreCardAdditions.remove(child);
+                return false;
+            }
+        }
+        return false;
+    }
+
+    private boolean isClickedHeadsUp(View child) {
+        return HeadsUpUtil.isClickedHeadsUpNotification(child);
+    }
+
+    /**
+     * Remove a removed child view from the heads up animations if it was just added there
+     *
+     * @return whether any child was removed from the list to animate
+     */
+    private boolean removeRemovedChildFromHeadsUpChangeAnimations(View child) {
+        boolean hasAddEvent = false;
+        for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
+            ExpandableNotificationRow row = eventPair.first;
+            boolean isHeadsUp = eventPair.second;
+            if (child == row) {
+                mTmpList.add(eventPair);
+                hasAddEvent |= isHeadsUp;
+            }
+        }
+        if (hasAddEvent) {
+            // This child was just added lets remove all events.
+            mHeadsUpChangeAnimations.removeAll(mTmpList);
+            ((ExpandableNotificationRow) child).setHeadsUpAnimatingAway(false);
+        }
+        mTmpList.clear();
+        return hasAddEvent;
+    }
+
+    /**
+     * @param child the child to query
+     * @return whether a view is not a top level child but a child notification and that group is
+     * not expanded
+     */
+    private boolean isChildInInvisibleGroup(View child) {
+        if (child instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            ExpandableNotificationRow groupSummary =
+                    mGroupManager.getGroupSummary(row.getStatusBarNotification());
+            if (groupSummary != null && groupSummary != row) {
+                return row.getVisibility() == View.INVISIBLE;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Updates the scroll position when a child was removed
+     *
+     * @param removedChild the removed child
+     */
+    private void updateScrollStateForRemovedChild(ExpandableView removedChild) {
+        int startingPosition = getPositionInLinearLayout(removedChild);
+        float increasedPaddingAmount = removedChild.getIncreasedPaddingAmount();
+        int padding;
+        if (increasedPaddingAmount >= 0) {
+            padding = (int) NotificationUtils.interpolate(
+                    mPaddingBetweenElements,
+                    mIncreasedPaddingBetweenElements,
+                    increasedPaddingAmount);
+        } else {
+            padding = (int) NotificationUtils.interpolate(
+                    0,
+                    mPaddingBetweenElements,
+                    1.0f + increasedPaddingAmount);
+        }
+        int childHeight = getIntrinsicHeight(removedChild) + padding;
+        int endPosition = startingPosition + childHeight;
+        if (endPosition <= mOwnScrollY) {
+            // This child is fully scrolled of the top, so we have to deduct its height from the
+            // scrollPosition
+            setOwnScrollY(mOwnScrollY - childHeight);
+        } else if (startingPosition < mOwnScrollY) {
+            // This child is currently being scrolled into, set the scroll position to the start of
+            // this child
+            setOwnScrollY(startingPosition);
+        }
+    }
+
+    private int getIntrinsicHeight(View view) {
+        if (view instanceof ExpandableView) {
+            ExpandableView expandableView = (ExpandableView) view;
+            return expandableView.getIntrinsicHeight();
+        }
+        return view.getHeight();
+    }
+
+    public int getPositionInLinearLayout(View requestedView) {
+        ExpandableNotificationRow childInGroup = null;
+        ExpandableNotificationRow requestedRow = null;
+        if (isChildInGroup(requestedView)) {
+            // We're asking for a child in a group. Calculate the position of the parent first,
+            // then within the parent.
+            childInGroup = (ExpandableNotificationRow) requestedView;
+            requestedView = requestedRow = childInGroup.getNotificationParent();
+        }
+        int position = 0;
+        float previousPaddingRequest = mPaddingBetweenElements;
+        float previousPaddingAmount = 0.0f;
+        for (int i = 0; i < getChildCount(); i++) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            boolean notGone = child.getVisibility() != View.GONE;
+            if (notGone && !child.hasNoContentHeight()) {
+                float increasedPaddingAmount = child.getIncreasedPaddingAmount();
+                float padding;
+                if (increasedPaddingAmount >= 0.0f) {
+                    padding = (int) NotificationUtils.interpolate(
+                            previousPaddingRequest,
+                            mIncreasedPaddingBetweenElements,
+                            increasedPaddingAmount);
+                    previousPaddingRequest = (int) NotificationUtils.interpolate(
+                            mPaddingBetweenElements,
+                            mIncreasedPaddingBetweenElements,
+                            increasedPaddingAmount);
+                } else {
+                    int ownPadding = (int) NotificationUtils.interpolate(
+                            0,
+                            mPaddingBetweenElements,
+                            1.0f + increasedPaddingAmount);
+                    if (previousPaddingAmount > 0.0f) {
+                        padding = (int) NotificationUtils.interpolate(
+                                ownPadding,
+                                mIncreasedPaddingBetweenElements,
+                                previousPaddingAmount);
+                    } else {
+                        padding = ownPadding;
+                    }
+                    previousPaddingRequest = ownPadding;
+                }
+                if (position != 0) {
+                    position += padding;
+                }
+                previousPaddingAmount = increasedPaddingAmount;
+            }
+            if (child == requestedView) {
+                if (requestedRow != null) {
+                    position += requestedRow.getPositionOfChild(childInGroup);
+                }
+                return position;
+            }
+            if (notGone) {
+                position += getIntrinsicHeight(child);
+            }
+        }
+        return 0;
+    }
+
+    @Override
+    public void onViewAdded(View child) {
+        super.onViewAdded(child);
+        onViewAddedInternal(child);
+    }
+
+    private void updateFirstAndLastBackgroundViews() {
+        ActivatableNotificationView firstChild = getFirstChildWithBackground();
+        ActivatableNotificationView lastChild = getLastChildWithBackground();
+        if (mAnimationsEnabled && mIsExpanded) {
+            mAnimateNextBackgroundTop = firstChild != mFirstVisibleBackgroundChild;
+            mAnimateNextBackgroundBottom = lastChild != mLastVisibleBackgroundChild;
+        } else {
+            mAnimateNextBackgroundTop = false;
+            mAnimateNextBackgroundBottom = false;
+        }
+        mFirstVisibleBackgroundChild = firstChild;
+        mLastVisibleBackgroundChild = lastChild;
+        mAmbientState.setLastVisibleBackgroundChild(lastChild);
+        mRoundnessManager.setFirstAndLastBackgroundChild(mFirstVisibleBackgroundChild,
+                mLastVisibleBackgroundChild);
+        invalidate();
+    }
+
+    private void onViewAddedInternal(View child) {
+        updateHideSensitiveForChild(child);
+        ((ExpandableView) child).setOnHeightChangedListener(this);
+        generateAddAnimation(child, false /* fromMoreCard */);
+        updateAnimationState(child);
+        updateChronometerForChild(child);
+    }
+
+    private void updateHideSensitiveForChild(View child) {
+        if (child instanceof ExpandableView) {
+            ExpandableView expandableView = (ExpandableView) child;
+            expandableView.setHideSensitiveForIntrinsicHeight(mAmbientState.isHideSensitive());
+        }
+    }
+
+    @Override
+    public void notifyGroupChildRemoved(View row, ViewGroup childrenContainer) {
+        onViewRemovedInternal(row, childrenContainer);
+    }
+
+    @Override
+    public void notifyGroupChildAdded(View row) {
+        onViewAddedInternal(row);
+    }
+
+    public void setAnimationsEnabled(boolean animationsEnabled) {
+        mAnimationsEnabled = animationsEnabled;
+        updateNotificationAnimationStates();
+        if (!animationsEnabled) {
+            mSwipedOutViews.clear();
+            mChildrenToRemoveAnimated.clear();
+            clearTemporaryViewsInGroup(this);
+        }
+    }
+
+    private void updateNotificationAnimationStates() {
+        boolean running = mAnimationsEnabled || hasPulsingNotifications();
+        mShelf.setAnimationsEnabled(running);
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            running &= mIsExpanded || isPinnedHeadsUp(child);
+            updateAnimationState(running, child);
+        }
+    }
+
+    private void updateAnimationState(View child) {
+        updateAnimationState((mAnimationsEnabled || hasPulsingNotifications())
+                && (mIsExpanded || isPinnedHeadsUp(child)), child);
+    }
+
+    @Override
+    public void setExpandingNotification(ExpandableNotificationRow row) {
+        mAmbientState.setExpandingNotification(row);
+        requestChildrenUpdate();
+    }
+
+    @Override
+    public void bindRow(ExpandableNotificationRow row) {
+        row.setHeadsUpAnimatingAwayListener(animatingAway -> {
+            mRoundnessManager.onHeadsupAnimatingAwayChanged(row, animatingAway);
+            mHeadsUpAppearanceController.updateHeader(row.getEntry());
+        });
+    }
+
+    @Override
+    public void applyExpandAnimationParams(ExpandAnimationParameters params) {
+        mAmbientState.setExpandAnimationTopChange(params == null ? 0 : params.getTopChange());
+        requestChildrenUpdate();
+    }
+
+    private void updateAnimationState(boolean running, View child) {
+        if (child instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            row.setIconAnimationRunning(running);
+        }
+    }
+
+    public boolean isAddOrRemoveAnimationPending() {
+        return mNeedsAnimation
+                && (!mChildrenToAddAnimated.isEmpty() || !mChildrenToRemoveAnimated.isEmpty());
+    }
+
+    @Override
+    public void generateAddAnimation(View child, boolean fromMoreCard) {
+        if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress) {
+            // Generate Animations
+            mChildrenToAddAnimated.add(child);
+            if (fromMoreCard) {
+                mFromMoreCardAdditions.add(child);
+            }
+            mNeedsAnimation = true;
+        }
+        if (isHeadsUp(child) && mAnimationsEnabled && !mChangePositionInProgress) {
+            mAddedHeadsUpChildren.add(child);
+            mChildrenToAddAnimated.remove(child);
+        }
+    }
+
+    @Override
+    public void changeViewPosition(View child, int newIndex) {
+        int currentIndex = indexOfChild(child);
+
+        if (currentIndex == -1) {
+            boolean isTransient = false;
+            if (child instanceof ExpandableNotificationRow
+                    && ((ExpandableNotificationRow) child).getTransientContainer() != null) {
+                isTransient = true;
+            }
+            Log.e(TAG, "Attempting to re-position "
+                    + (isTransient ? "transient" : "")
+                    + " view {"
+                    + child
+                    + "}");
+            return;
+        }
+
+        if (child != null && child.getParent() == this && currentIndex != newIndex) {
+            mChangePositionInProgress = true;
+            ((ExpandableView) child).setChangingPosition(true);
+            removeView(child);
+            addView(child, newIndex);
+            ((ExpandableView) child).setChangingPosition(false);
+            mChangePositionInProgress = false;
+            if (mIsExpanded && mAnimationsEnabled && child.getVisibility() != View.GONE) {
+                mChildrenChangingPositions.add(child);
+                mNeedsAnimation = true;
+            }
+        }
+    }
+
+    private void startAnimationToState() {
+        if (mNeedsAnimation) {
+            generateAllAnimationEvents();
+            mNeedsAnimation = false;
+        }
+        if (!mAnimationEvents.isEmpty() || isCurrentlyAnimating()) {
+            setAnimationRunning(true);
+            mStateAnimator.startAnimationForEvents(mAnimationEvents, mCurrentStackScrollState,
+                    mGoToFullShadeDelay);
+            mAnimationEvents.clear();
+            updateBackground();
+            updateViewShadows();
+            updateClippingToTopRoundedCorner();
+        } else {
+            applyCurrentState();
+        }
+        mGoToFullShadeDelay = 0;
+    }
+
+    private void generateAllAnimationEvents() {
+        generateHeadsUpAnimationEvents();
+        generateChildRemovalEvents();
+        generateChildAdditionEvents();
+        generatePositionChangeEvents();
+        generateSnapBackEvents();
+        generateDragEvents();
+        generateTopPaddingEvent();
+        generateActivateEvent();
+        generateDimmedEvent();
+        generateHideSensitiveEvent();
+        generateDarkEvent();
+        generateGoToFullShadeEvent();
+        generateViewResizeEvent();
+        generateGroupExpansionEvent();
+        generateAnimateEverythingEvent();
+        generatePulsingAnimationEvent();
+    }
+
+    private void generateHeadsUpAnimationEvents() {
+        for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
+            ExpandableNotificationRow row = eventPair.first;
+            boolean isHeadsUp = eventPair.second;
+            int type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_OTHER;
+            boolean onBottom = false;
+            boolean pinnedAndClosed = row.isPinned() && !mIsExpanded;
+            if (!mIsExpanded && !isHeadsUp) {
+                type = row.wasJustClicked()
+                        ? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+                        : AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
+                if (row.isChildInGroup()) {
+                    // We can otherwise get stuck in there if it was just isolated
+                    row.setHeadsUpAnimatingAway(false);
+                    continue;
+                }
+            } else {
+                ExpandableViewState viewState = mCurrentStackScrollState.getViewStateForView(row);
+                if (viewState == null) {
+                    // A view state was never generated for this view, so we don't need to animate
+                    // this. This may happen with notification children.
+                    continue;
+                }
+                if (isHeadsUp && (mAddedHeadsUpChildren.contains(row) || pinnedAndClosed)) {
+                    if (pinnedAndClosed || shouldHunAppearFromBottom(viewState)) {
+                        // Our custom add animation
+                        type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR;
+                    } else {
+                        // Normal add animation
+                        type = AnimationEvent.ANIMATION_TYPE_ADD;
+                    }
+                    onBottom = !pinnedAndClosed;
+                }
+            }
+            AnimationEvent event = new AnimationEvent(row, type);
+            event.headsUpFromBottom = onBottom;
+            mAnimationEvents.add(event);
+        }
+        mHeadsUpChangeAnimations.clear();
+        mAddedHeadsUpChildren.clear();
+    }
+
+    private boolean shouldHunAppearFromBottom(ExpandableViewState viewState) {
+        if (viewState.yTranslation + viewState.height < mAmbientState.getMaxHeadsUpTranslation()) {
+            return false;
+        }
+        return true;
+    }
+
+    private void generateGroupExpansionEvent() {
+        // Generate a group expansion/collapsing event if there is such a group at all
+        if (mExpandedGroupView != null) {
+            mAnimationEvents.add(new AnimationEvent(mExpandedGroupView,
+                    AnimationEvent.ANIMATION_TYPE_GROUP_EXPANSION_CHANGED));
+            mExpandedGroupView = null;
+        }
+    }
+
+    private void generateViewResizeEvent() {
+        if (mNeedViewResizeAnimation) {
+            boolean hasDisappearAnimation = false;
+            for (AnimationEvent animationEvent : mAnimationEvents) {
+                final int type = animationEvent.animationType;
+                if (type == AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+                        || type == AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR) {
+                    hasDisappearAnimation = true;
+                    break;
+                }
+            }
+
+            if (!hasDisappearAnimation) {
+                mAnimationEvents.add(
+                        new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_VIEW_RESIZE));
+            }
+        }
+        mNeedViewResizeAnimation = false;
+    }
+
+    private void generateSnapBackEvents() {
+        for (View child : mSnappedBackChildren) {
+            mAnimationEvents.add(new AnimationEvent(child,
+                    AnimationEvent.ANIMATION_TYPE_SNAP_BACK));
+        }
+        mSnappedBackChildren.clear();
+    }
+
+    private void generateDragEvents() {
+        for (View child : mDragAnimPendingChildren) {
+            mAnimationEvents.add(new AnimationEvent(child,
+                    AnimationEvent.ANIMATION_TYPE_START_DRAG));
+        }
+        mDragAnimPendingChildren.clear();
+    }
+
+    private void generateChildRemovalEvents() {
+        for (View child : mChildrenToRemoveAnimated) {
+            boolean childWasSwipedOut = mSwipedOutViews.contains(child);
+
+            // we need to know the view after this one
+            float removedTranslation = child.getTranslationY();
+            boolean ignoreChildren = true;
+            if (child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                if (row.isRemoved() && row.wasChildInGroupWhenRemoved()) {
+                    removedTranslation = row.getTranslationWhenRemoved();
+                    ignoreChildren = false;
+                }
+                childWasSwipedOut |= Math.abs(row.getTranslation()) == row.getWidth();
+            }
+            if (!childWasSwipedOut) {
+                Rect clipBounds = child.getClipBounds();
+                childWasSwipedOut = clipBounds != null && clipBounds.height() == 0;
+
+                if (childWasSwipedOut && child instanceof ExpandableView) {
+                    // Clean up any potential transient views if the child has already been swiped
+                    // out, as we won't be animating it further (due to its height already being
+                    // clipped to 0.
+                    ViewGroup transientContainer = ((ExpandableView) child).getTransientContainer();
+                    if (transientContainer != null) {
+                        transientContainer.removeTransientView(child);
+                    }
+                }
+            }
+            int animationType = childWasSwipedOut
+                    ? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
+                    : AnimationEvent.ANIMATION_TYPE_REMOVE;
+            AnimationEvent event = new AnimationEvent(child, animationType);
+            event.viewAfterChangingView = getFirstChildBelowTranlsationY(removedTranslation,
+                    ignoreChildren);
+            mAnimationEvents.add(event);
+            mSwipedOutViews.remove(child);
+        }
+        mChildrenToRemoveAnimated.clear();
+    }
+
+    private void generatePositionChangeEvents() {
+        for (View child : mChildrenChangingPositions) {
+            mAnimationEvents.add(new AnimationEvent(child,
+                    AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION));
+        }
+        mChildrenChangingPositions.clear();
+        if (mGenerateChildOrderChangedEvent) {
+            mAnimationEvents.add(new AnimationEvent(null,
+                    AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION));
+            mGenerateChildOrderChangedEvent = false;
+        }
+    }
+
+    private void generateChildAdditionEvents() {
+        for (View child : mChildrenToAddAnimated) {
+            if (mFromMoreCardAdditions.contains(child)) {
+                mAnimationEvents.add(new AnimationEvent(child,
+                        AnimationEvent.ANIMATION_TYPE_ADD,
+                        StackStateAnimator.ANIMATION_DURATION_STANDARD));
+            } else {
+                mAnimationEvents.add(new AnimationEvent(child,
+                        AnimationEvent.ANIMATION_TYPE_ADD));
+            }
+        }
+        mChildrenToAddAnimated.clear();
+        mFromMoreCardAdditions.clear();
+    }
+
+    private void generateTopPaddingEvent() {
+        if (mTopPaddingNeedsAnimation) {
+            AnimationEvent event;
+            if (mAmbientState.isDark()) {
+                event = new AnimationEvent(null /* view */,
+                        AnimationEvent.ANIMATION_TYPE_TOP_PADDING_CHANGED,
+                        KeyguardSliceView.DEFAULT_ANIM_DURATION);
+            } else {
+                event = new AnimationEvent(null /* view */,
+                        AnimationEvent.ANIMATION_TYPE_TOP_PADDING_CHANGED);
+            }
+            mAnimationEvents.add(event);
+        }
+        mTopPaddingNeedsAnimation = false;
+    }
+
+    private void generateActivateEvent() {
+        if (mActivateNeedsAnimation) {
+            mAnimationEvents.add(
+                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_ACTIVATED_CHILD));
+        }
+        mActivateNeedsAnimation = false;
+    }
+
+    private void generateAnimateEverythingEvent() {
+        if (mEverythingNeedsAnimation) {
+            mAnimationEvents.add(
+                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_EVERYTHING));
+        }
+        mEverythingNeedsAnimation = false;
+    }
+
+    private void generateDimmedEvent() {
+        if (mDimmedNeedsAnimation) {
+            mAnimationEvents.add(
+                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_DIMMED));
+        }
+        mDimmedNeedsAnimation = false;
+    }
+
+    private void generateHideSensitiveEvent() {
+        if (mHideSensitiveNeedsAnimation) {
+            mAnimationEvents.add(
+                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_HIDE_SENSITIVE));
+        }
+        mHideSensitiveNeedsAnimation = false;
+    }
+
+    private void generateDarkEvent() {
+        if (mDarkNeedsAnimation) {
+            AnimationEvent ev = new AnimationEvent(null,
+                    AnimationEvent.ANIMATION_TYPE_DARK,
+                    new AnimationFilter()
+                            .animateDark()
+                            .animateY(mShelf));
+            ev.darkAnimationOriginIndex = mDarkAnimationOriginIndex;
+            mAnimationEvents.add(ev);
+        }
+        mDarkNeedsAnimation = false;
+    }
+
+    private void generateGoToFullShadeEvent() {
+        if (mGoToFullShadeNeedsAnimation) {
+            mAnimationEvents.add(
+                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_GO_TO_FULL_SHADE));
+        }
+        mGoToFullShadeNeedsAnimation = false;
+    }
+
+    private boolean onInterceptTouchEventScroll(MotionEvent ev) {
+        if (!isScrollingEnabled()) {
+            return false;
+        }
+        /*
+         * This method JUST determines whether we want to intercept the motion.
+         * If we return true, onMotionEvent will be called and we do the actual
+         * scrolling there.
+         */
+
+        /*
+         * Shortcut the most recurring case: the user is in the dragging
+         * state and is moving their finger.  We want to intercept this
+         * motion.
+         */
+        final int action = ev.getAction();
+        if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
+            return true;
+        }
+
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_MOVE: {
+                /*
+                 * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
+                 * whether the user has moved far enough from the original down touch.
+                 */
+
+                /*
+                 * Locally do absolute value. mLastMotionY is set to the y value
+                 * of the down event.
+                 */
+                final int activePointerId = mActivePointerId;
+                if (activePointerId == INVALID_POINTER) {
+                    // If we don't have a valid id, the touch down wasn't on content.
+                    break;
+                }
+
+                final int pointerIndex = ev.findPointerIndex(activePointerId);
+                if (pointerIndex == -1) {
+                    Log.e(TAG, "Invalid pointerId=" + activePointerId
+                            + " in onInterceptTouchEvent");
+                    break;
+                }
+
+                final int y = (int) ev.getY(pointerIndex);
+                final int x = (int) ev.getX(pointerIndex);
+                final int yDiff = Math.abs(y - mLastMotionY);
+                final int xDiff = Math.abs(x - mDownX);
+                if (yDiff > mTouchSlop && yDiff > xDiff) {
+                    setIsBeingDragged(true);
+                    mLastMotionY = y;
+                    mDownX = x;
+                    initVelocityTrackerIfNotExists();
+                    mVelocityTracker.addMovement(ev);
+                }
+                break;
+            }
+
+            case MotionEvent.ACTION_DOWN: {
+                final int y = (int) ev.getY();
+                mScrolledToTopOnFirstDown = isScrolledToTop();
+                if (getChildAtPosition(ev.getX(), y, false /* requireMinHeight */) == null) {
+                    setIsBeingDragged(false);
+                    recycleVelocityTracker();
+                    break;
+                }
+
+                /*
+                 * Remember location of down touch.
+                 * ACTION_DOWN always refers to pointer index 0.
+                 */
+                mLastMotionY = y;
+                mDownX = (int) ev.getX();
+                mActivePointerId = ev.getPointerId(0);
+
+                initOrResetVelocityTracker();
+                mVelocityTracker.addMovement(ev);
+                /*
+                 * If being flinged and user touches the screen, initiate drag;
+                 * otherwise don't.  mScroller.isFinished should be false when
+                 * being flinged.
+                 */
+                boolean isBeingDragged = !mScroller.isFinished();
+                setIsBeingDragged(isBeingDragged);
+                break;
+            }
+
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                /* Release the drag */
+                setIsBeingDragged(false);
+                mActivePointerId = INVALID_POINTER;
+                recycleVelocityTracker();
+                if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
+                    animateScroll();
+                }
+                break;
+            case MotionEvent.ACTION_POINTER_UP:
+                onSecondaryPointerUp(ev);
+                break;
+        }
+
+        /*
+         * The only time we want to intercept motion events is if we are in the
+         * drag mode.
+         */
+        return mIsBeingDragged;
+    }
+
+    protected StackScrollAlgorithm createStackScrollAlgorithm(Context context) {
+        return new StackScrollAlgorithm(context);
+    }
+
+    /**
+     * @return Whether the specified motion event is actually happening over the content.
+     */
+    private boolean isInContentBounds(MotionEvent event) {
+        return isInContentBounds(event.getY());
+    }
+
+    /**
+     * @return Whether a y coordinate is inside the content.
+     */
+    public boolean isInContentBounds(float y) {
+        return y < getHeight() - getEmptyBottomMargin();
+    }
+
+    private void setIsBeingDragged(boolean isDragged) {
+        mIsBeingDragged = isDragged;
+        if (isDragged) {
+            requestDisallowInterceptTouchEvent(true);
+            cancelLongPress();
+        }
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        super.onWindowFocusChanged(hasWindowFocus);
+        if (!hasWindowFocus) {
+            cancelLongPress();
+        }
+    }
+
+    @Override
+    public void clearChildFocus(View child) {
+        super.clearChildFocus(child);
+        if (mForcedScroll == child) {
+            mForcedScroll = null;
+        }
+    }
+
+    public void requestDisallowLongPress() {
+        cancelLongPress();
+    }
+
+    public void requestDisallowDismiss() {
+        mDisallowDismissInThisMotion = true;
+    }
+
+    public void cancelLongPress() {
+        mSwipeHelper.cancelLongPress();
+    }
+
+    @Override
+    public boolean isScrolledToTop() {
+        return mOwnScrollY == 0;
+    }
+
+    @Override
+    public boolean isScrolledToBottom() {
+        return mOwnScrollY >= getScrollRange();
+    }
+
+    @Override
+    public View getHostView() {
+        return this;
+    }
+
+    public int getEmptyBottomMargin() {
+        return Math.max(mMaxLayoutHeight - mContentHeight, 0);
+    }
+
+    public void checkSnoozeLeavebehind() {
+        if (mCheckForLeavebehind) {
+            mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
+                    false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
+                    false /* resetMenu */);
+            mCheckForLeavebehind = false;
+        }
+    }
+
+    public void resetCheckSnoozeLeavebehind() {
+        mCheckForLeavebehind = true;
+    }
+
+    public void onExpansionStarted() {
+        mIsExpansionChanging = true;
+        mAmbientState.setExpansionChanging(true);
+        checkSnoozeLeavebehind();
+    }
+
+    public void onExpansionStopped() {
+        mIsExpansionChanging = false;
+        resetCheckSnoozeLeavebehind();
+        mAmbientState.setExpansionChanging(false);
+        if (!mIsExpanded) {
+            setOwnScrollY(0);
+            mStatusBar.resetUserExpandedStates();
+            clearTemporaryViews();
+            clearUserLockedViews();
+        }
+    }
+
+    private void clearUserLockedViews() {
+        for (int i = 0; i < getChildCount(); i++) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                row.setUserLocked(false);
+            }
+        }
+    }
+
+    private void clearTemporaryViews() {
+        // lets make sure nothing is transient anymore
+        clearTemporaryViewsInGroup(this);
+        for (int i = 0; i < getChildCount(); i++) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                clearTemporaryViewsInGroup(row.getChildrenContainer());
+            }
+        }
+    }
+
+    private void clearTemporaryViewsInGroup(ViewGroup viewGroup) {
+        while (viewGroup != null && viewGroup.getTransientViewCount() != 0) {
+            viewGroup.removeTransientView(viewGroup.getTransientView(0));
+        }
+    }
+
+    public void onPanelTrackingStarted() {
+        mPanelTracking = true;
+        mAmbientState.setPanelTracking(true);
+    }
+
+    public void onPanelTrackingStopped() {
+        mPanelTracking = false;
+        mAmbientState.setPanelTracking(false);
+    }
+
+    public void resetScrollPosition() {
+        mScroller.abortAnimation();
+        setOwnScrollY(0);
+    }
+
+    private void setIsExpanded(boolean isExpanded) {
+        boolean changed = isExpanded != mIsExpanded;
+        mIsExpanded = isExpanded;
+        mStackScrollAlgorithm.setIsExpanded(isExpanded);
+        if (changed) {
+            if (!mIsExpanded) {
+                mGroupManager.collapseAllGroups();
+                mExpandHelper.cancelImmediately();
+            }
+            updateNotificationAnimationStates();
+            updateChronometers();
+            requestChildrenUpdate();
+        }
+    }
+
+    private void updateChronometers() {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            updateChronometerForChild(getChildAt(i));
+        }
+    }
+
+    private void updateChronometerForChild(View child) {
+        if (child instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            row.setChronometerRunning(mIsExpanded);
+        }
+    }
+
+    @Override
+    public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
+        updateContentHeight();
+        updateScrollPositionOnExpandInBottom(view);
+        clampScrollPosition();
+        notifyHeightChangeListener(view, needsAnimation);
+        ExpandableNotificationRow row = view instanceof ExpandableNotificationRow
+                ? (ExpandableNotificationRow) view
+                : null;
+        if (row != null && (row == mFirstVisibleBackgroundChild
+                || row.getNotificationParent() == mFirstVisibleBackgroundChild)) {
+            updateAlgorithmLayoutMinHeight();
+        }
+        if (needsAnimation) {
+            requestAnimationOnViewResize(row);
+        }
+        requestChildrenUpdate();
+    }
+
+    @Override
+    public void onReset(ExpandableView view) {
+        updateAnimationState(view);
+        updateChronometerForChild(view);
+    }
+
+    private void updateScrollPositionOnExpandInBottom(ExpandableView view) {
+        if (view instanceof ExpandableNotificationRow && !onKeyguard()) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+            if (row.isUserLocked() && row != getFirstChildNotGone()) {
+                if (row.isSummaryWithChildren()) {
+                    return;
+                }
+                // We are actually expanding this view
+                float endPosition = row.getTranslationY() + row.getActualHeight();
+                if (row.isChildInGroup()) {
+                    endPosition += row.getNotificationParent().getTranslationY();
+                }
+                int layoutEnd = mMaxLayoutHeight + (int) mStackTranslation;
+                if (row != mLastVisibleBackgroundChild && mShelf.getVisibility() != GONE) {
+                    layoutEnd -= mShelf.getIntrinsicHeight() + mPaddingBetweenElements;
+                }
+                if (endPosition > layoutEnd) {
+                    setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd));
+                    mDisallowScrollingInThisMotion = true;
+                }
+            }
+        }
+    }
+
+    public void setOnHeightChangedListener(
+            ExpandableView.OnHeightChangedListener mOnHeightChangedListener) {
+        this.mOnHeightChangedListener = mOnHeightChangedListener;
+    }
+
+    public void setOnEmptySpaceClickListener(OnEmptySpaceClickListener listener) {
+        mOnEmptySpaceClickListener = listener;
+    }
+
+    public void onChildAnimationFinished() {
+        setAnimationRunning(false);
+        requestChildrenUpdate();
+        runAnimationFinishedRunnables();
+        clearTransient();
+        clearHeadsUpDisappearRunning();
+    }
+
+    private void clearHeadsUpDisappearRunning() {
+        for (int i = 0; i < getChildCount(); i++) {
+            View view = getChildAt(i);
+            if (view instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+                row.setHeadsUpAnimatingAway(false);
+                if (row.isSummaryWithChildren()) {
+                    for (ExpandableNotificationRow child : row.getNotificationChildren()) {
+                        child.setHeadsUpAnimatingAway(false);
+                    }
+                }
+            }
+        }
+    }
+
+    private void clearTransient() {
+        for (ExpandableView view : mClearTransientViewsWhenFinished) {
+            StackStateAnimator.removeTransientView(view);
+        }
+        mClearTransientViewsWhenFinished.clear();
+    }
+
+    private void runAnimationFinishedRunnables() {
+        for (Runnable runnable : mAnimationFinishedRunnables) {
+            runnable.run();
+        }
+        mAnimationFinishedRunnables.clear();
+    }
+
+    /**
+     * See {@link AmbientState#setDimmed}.
+     */
+    public void setDimmed(boolean dimmed, boolean animate) {
+        dimmed &= onKeyguard();
+        mAmbientState.setDimmed(dimmed);
+        if (animate && mAnimationsEnabled) {
+            mDimmedNeedsAnimation = true;
+            mNeedsAnimation = true;
+            animateDimmed(dimmed);
+        } else {
+            setDimAmount(dimmed ? 1.0f : 0.0f);
+        }
+        requestChildrenUpdate();
+    }
+
+    @VisibleForTesting
+    boolean isDimmed() {
+        return mAmbientState.isDimmed();
+    }
+
+    private void setDimAmount(float dimAmount) {
+        mDimAmount = dimAmount;
+        updateBackgroundDimming();
+    }
+
+    private void animateDimmed(boolean dimmed) {
+        if (mDimAnimator != null) {
+            mDimAnimator.cancel();
+        }
+        float target = dimmed ? 1.0f : 0.0f;
+        if (target == mDimAmount) {
+            return;
+        }
+        mDimAnimator = TimeAnimator.ofFloat(mDimAmount, target);
+        mDimAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_DIMMED_ACTIVATED);
+        mDimAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        mDimAnimator.addListener(mDimEndListener);
+        mDimAnimator.addUpdateListener(mDimUpdateListener);
+        mDimAnimator.start();
+    }
+
+    private void setHideSensitive(boolean hideSensitive, boolean animate) {
+        if (hideSensitive != mAmbientState.isHideSensitive()) {
+            int childCount = getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                ExpandableView v = (ExpandableView) getChildAt(i);
+                v.setHideSensitiveForIntrinsicHeight(hideSensitive);
+            }
+            mAmbientState.setHideSensitive(hideSensitive);
+            if (animate && mAnimationsEnabled) {
+                mHideSensitiveNeedsAnimation = true;
+                mNeedsAnimation = true;
+            }
+            updateContentHeight();
+            requestChildrenUpdate();
+        }
+    }
+
+    /**
+     * See {@link AmbientState#setActivatedChild}.
+     */
+    public void setActivatedChild(ActivatableNotificationView activatedChild) {
+        mAmbientState.setActivatedChild(activatedChild);
+        if (mAnimationsEnabled) {
+            mActivateNeedsAnimation = true;
+            mNeedsAnimation = true;
+        }
+        requestChildrenUpdate();
+    }
+
+    public ActivatableNotificationView getActivatedChild() {
+        return mAmbientState.getActivatedChild();
+    }
+
+    private void applyCurrentState() {
+        mCurrentStackScrollState.apply();
+        if (mListener != null) {
+            mListener.onChildLocationsChanged();
+        }
+        runAnimationFinishedRunnables();
+        setAnimationRunning(false);
+        updateBackground();
+        updateViewShadows();
+        updateClippingToTopRoundedCorner();
+    }
+
+    private void updateViewShadows() {
+        // we need to work around an issue where the shadow would not cast between siblings when
+        // their z difference is between 0 and 0.1
+
+        // Lefts first sort by Z difference
+        for (int i = 0; i < getChildCount(); i++) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child.getVisibility() != GONE) {
+                mTmpSortedChildren.add(child);
+            }
+        }
+        Collections.sort(mTmpSortedChildren, mViewPositionComparator);
+
+        // Now lets update the shadow for the views
+        ExpandableView previous = null;
+        for (int i = 0; i < mTmpSortedChildren.size(); i++) {
+            ExpandableView expandableView = mTmpSortedChildren.get(i);
+            float translationZ = expandableView.getTranslationZ();
+            float otherZ = previous == null ? translationZ : previous.getTranslationZ();
+            float diff = otherZ - translationZ;
+            if (diff <= 0.0f || diff >= FakeShadowView.SHADOW_SIBLING_TRESHOLD) {
+                // There is no fake shadow to be drawn
+                expandableView.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
+            } else {
+                float yLocation = previous.getTranslationY() + previous.getActualHeight() -
+                        expandableView.getTranslationY() - previous.getExtraBottomPadding();
+                expandableView.setFakeShadowIntensity(
+                        diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD,
+                        previous.getOutlineAlpha(), (int) yLocation,
+                        previous.getOutlineTranslation());
+            }
+            previous = expandableView;
+        }
+
+        mTmpSortedChildren.clear();
+    }
+
+    /**
+     * Update colors of "dismiss" and "empty shade" views.
+     *
+     * @param lightTheme True if light theme should be used.
+     */
+    public void updateDecorViews(boolean lightTheme) {
+        if (lightTheme == mUsingLightTheme) {
+            return;
+        }
+        mUsingLightTheme = lightTheme;
+        Context context = new ContextThemeWrapper(mContext,
+                lightTheme ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI);
+        final int textColor = Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColor);
+        mFooterView.setTextColor(textColor);
+        mEmptyShadeView.setTextColor(textColor);
+    }
+
+    public void goToFullShade(long delay) {
+        mGoToFullShadeNeedsAnimation = true;
+        mGoToFullShadeDelay = delay;
+        mNeedsAnimation = true;
+        requestChildrenUpdate();
+    }
+
+    public void cancelExpandHelper() {
+        mExpandHelper.cancel();
+    }
+
+    public void setIntrinsicPadding(int intrinsicPadding) {
+        mIntrinsicPadding = intrinsicPadding;
+        mAmbientState.setIntrinsicPadding(intrinsicPadding);
+    }
+
+    public int getIntrinsicPadding() {
+        return mIntrinsicPadding;
+    }
+
+    /**
+     * @return the y position of the first notification
+     */
+    public float getNotificationsTopY() {
+        return mTopPadding + getStackTranslation();
+    }
+
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return true;
+    }
+
+    /**
+     * See {@link AmbientState#setDark}.
+     */
+    public void setDark(boolean dark, boolean animate, @Nullable PointF touchWakeUpScreenLocation) {
+        if (mAmbientState.isDark() == dark) {
+            return;
+        }
+        mAmbientState.setDark(dark);
+        if (animate && mAnimationsEnabled) {
+            mDarkNeedsAnimation = true;
+            mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation);
+            mNeedsAnimation = true;
+        } else {
+            setDarkAmount(dark ? 1f : 0f);
+            updateBackground();
+        }
+        requestChildrenUpdate();
+        applyCurrentBackgroundBounds();
+        updateWillNotDraw();
+        notifyHeightChangeListener(mShelf);
+    }
+
+    private void updatePanelTranslation() {
+        setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mInterpolatedDarkAmount);
+    }
+
+    public void setVerticalPanelTranslation(float verticalPanelTranslation) {
+        mVerticalPanelTranslation = verticalPanelTranslation;
+        updatePanelTranslation();
+    }
+
+    /**
+     * Updates whether or not this Layout will perform its own custom drawing (i.e. whether or
+     * not {@link #onDraw(Canvas)} is called). This method should be called whenever the
+     * {@link #mAmbientState}'s dark mode is toggled.
+     */
+    private void updateWillNotDraw() {
+        boolean willDraw = mShouldDrawNotificationBackground || DEBUG;
+        setWillNotDraw(!willDraw);
+    }
+
+    private void setDarkAmount(float darkAmount) {
+        setDarkAmount(darkAmount, darkAmount);
+    }
+
+    /**
+     * Sets the current dark amount.
+     *
+     * @param linearDarkAmount       The dark amount that follows linear interpoloation in the
+     *                               animation,
+     *                               i.e. animates from 0 to 1 or vice-versa in a linear manner.
+     * @param interpolatedDarkAmount The dark amount that follows the actual interpolation of the
+     *                               animation curve.
+     */
+    public void setDarkAmount(float linearDarkAmount, float interpolatedDarkAmount) {
+        mLinearDarkAmount = linearDarkAmount;
+        mInterpolatedDarkAmount = interpolatedDarkAmount;
+        boolean wasFullyDark = mAmbientState.isFullyDark();
+        mAmbientState.setDarkAmount(interpolatedDarkAmount);
+        boolean nowFullyDark = mAmbientState.isFullyDark();
+        if (nowFullyDark != wasFullyDark) {
+            updateContentHeight();
+            DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
+            if (nowFullyDark && dozeParameters.shouldControlScreenOff()) {
+                mShelf.fadeInTranslating();
+            }
+            if (mIconAreaController != null) {
+                mIconAreaController.setFullyDark(nowFullyDark);
+            }
+        }
+        updateAlgorithmHeightAndPadding();
+        updateBackgroundDimming();
+        updatePanelTranslation();
+        requestChildrenUpdate();
+    }
+
+    public void notifyDarkAnimationStart(boolean dark) {
+        // We only swap the scaling factor if we're fully dark or fully awake to avoid
+        // interpolation issues when playing with the power button.
+        if (mInterpolatedDarkAmount == 0 || mInterpolatedDarkAmount == 1) {
+            mBackgroundXFactor = dark ? 1.8f : 1.5f;
+            mDarkXInterpolator = dark
+                    ? Interpolators.FAST_OUT_SLOW_IN_REVERSE
+                    : Interpolators.FAST_OUT_SLOW_IN;
+        }
+    }
+
+    public long getDarkAnimationDuration(boolean dark) {
+        long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
+        // Longer animation when sleeping with more than 1 notification
+        if (dark && getNotGoneChildCount() > 2) {
+            duration *= 1.2f;
+        }
+        return duration;
+    }
+
+    private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
+        if (screenLocation == null || screenLocation.y < mTopPadding) {
+            return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
+        }
+        if (screenLocation.y > getBottomMostNotificationBottom()) {
+            return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_BELOW;
+        }
+        View child = getClosestChildAtRawPosition(screenLocation.x, screenLocation.y);
+        if (child != null) {
+            return getNotGoneIndex(child);
+        } else {
+            return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
+        }
+    }
+
+    private int getNotGoneIndex(View child) {
+        int count = getChildCount();
+        int notGoneIndex = 0;
+        for (int i = 0; i < count; i++) {
+            View v = getChildAt(i);
+            if (child == v) {
+                return notGoneIndex;
+            }
+            if (v.getVisibility() != View.GONE) {
+                notGoneIndex++;
+            }
+        }
+        return -1;
+    }
+
+    public void setFooterView(@NonNull FooterView footerView) {
+        int index = -1;
+        if (mFooterView != null) {
+            index = indexOfChild(mFooterView);
+            removeView(mFooterView);
+        }
+        mFooterView = footerView;
+        addView(mFooterView, index);
+    }
+
+    public void setEmptyShadeView(EmptyShadeView emptyShadeView) {
+        int index = -1;
+        if (mEmptyShadeView != null) {
+            index = indexOfChild(mEmptyShadeView);
+            removeView(mEmptyShadeView);
+        }
+        mEmptyShadeView = emptyShadeView;
+        addView(mEmptyShadeView, index);
+    }
+
+    public void updateEmptyShadeView(boolean visible) {
+        mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
+
+        int oldTextRes = mEmptyShadeView.getTextResource();
+        int newTextRes = mStatusBar.areNotificationsHidden()
+                ? R.string.dnd_suppressing_shade_text : R.string.empty_shade_text;
+        if (oldTextRes != newTextRes) {
+            mEmptyShadeView.setText(newTextRes);
+        }
+    }
+
+    public void updateFooterView(boolean visible, boolean showDismissView) {
+        if (mFooterView == null) {
+            return;
+        }
+        boolean animate = mIsExpanded && mAnimationsEnabled;
+        mFooterView.setVisible(visible, animate);
+        mFooterView.setSecondaryVisible(showDismissView, animate);
+    }
+
+    public void setDismissAllInProgress(boolean dismissAllInProgress) {
+        mDismissAllInProgress = dismissAllInProgress;
+        mAmbientState.setDismissAllInProgress(dismissAllInProgress);
+        handleDismissAllClipping();
+    }
+
+    private void handleDismissAllClipping() {
+        final int count = getChildCount();
+        boolean previousChildWillBeDismissed = false;
+        for (int i = 0; i < count; i++) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child.getVisibility() == GONE) {
+                continue;
+            }
+            if (mDismissAllInProgress && previousChildWillBeDismissed) {
+                child.setMinClipTopAmount(child.getClipTopAmount());
+            } else {
+                child.setMinClipTopAmount(0);
+            }
+            previousChildWillBeDismissed = canChildBeDismissed(child);
+        }
+    }
+
+    public boolean isFooterViewNotGone() {
+        return mFooterView != null
+                && mFooterView.getVisibility() != View.GONE
+                && !mFooterView.willBeGone();
+    }
+
+    public boolean isFooterViewContentVisible() {
+        return mFooterView != null && mFooterView.isContentVisible();
+    }
+
+    public int getFooterViewHeight() {
+        return mFooterView == null ? 0 : mFooterView.getHeight() + mPaddingBetweenElements;
+    }
+
+    public int getEmptyShadeViewHeight() {
+        return mEmptyShadeView.getHeight();
+    }
+
+    public float getBottomMostNotificationBottom() {
+        final int count = getChildCount();
+        float max = 0;
+        for (int childIdx = 0; childIdx < count; childIdx++) {
+            ExpandableView child = (ExpandableView) getChildAt(childIdx);
+            if (child.getVisibility() == GONE) {
+                continue;
+            }
+            float bottom = child.getTranslationY() + child.getActualHeight()
+                    - child.getClipBottomAmount();
+            if (bottom > max) {
+                max = bottom;
+            }
+        }
+        return max + getStackTranslation();
+    }
+
+    public void setStatusBar(StatusBar statusBar) {
+        this.mStatusBar = statusBar;
+    }
+
+    public void setGroupManager(NotificationGroupManager groupManager) {
+        this.mGroupManager = groupManager;
+        mGroupManager.setOnGroupChangeListener(this);
+    }
+
+    private void requestAnimateEverything() {
+        if (mIsExpanded && mAnimationsEnabled) {
+            mEverythingNeedsAnimation = true;
+            mNeedsAnimation = true;
+            requestChildrenUpdate();
+        }
+    }
+
+    public boolean isBelowLastNotification(float touchX, float touchY) {
+        int childCount = getChildCount();
+        for (int i = childCount - 1; i >= 0; i--) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child.getVisibility() != View.GONE) {
+                float childTop = child.getY();
+                if (childTop > touchY) {
+                    // we are above a notification entirely let's abort
+                    return false;
+                }
+                boolean belowChild = touchY > childTop + child.getActualHeight()
+                        - child.getClipBottomAmount();
+                if (child == mFooterView) {
+                    if (!belowChild && !mFooterView.isOnEmptySpace(touchX - mFooterView.getX(),
+                            touchY - childTop)) {
+                        // We clicked on the dismiss button
+                        return false;
+                    }
+                } else if (child == mEmptyShadeView) {
+                    // We arrived at the empty shade view, for which we accept all clicks
+                    return true;
+                } else if (!belowChild) {
+                    // We are on a child
+                    return false;
+                }
+            }
+        }
+        return touchY > mTopPadding + mStackTranslation;
+    }
+
+    @Override
+    public void onGroupExpansionChanged(ExpandableNotificationRow changedRow, boolean expanded) {
+        boolean animated = !mGroupExpandedForMeasure && mAnimationsEnabled
+                && (mIsExpanded || changedRow.isPinned());
+        if (animated) {
+            mExpandedGroupView = changedRow;
+            mNeedsAnimation = true;
+        }
+        changedRow.setChildrenExpanded(expanded, animated);
+        if (!mGroupExpandedForMeasure) {
+            onHeightChanged(changedRow, false /* needsAnimation */);
+        }
+        runAfterAnimationFinished(new Runnable() {
+            @Override
+            public void run() {
+                changedRow.onFinishedExpansionChange();
+            }
+        });
+    }
+
+    @Override
+    public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
+        mStatusBar.requestNotificationUpdate();
+    }
+
+    /** @hide */
+    @Override
+    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEventInternal(event);
+        event.setScrollable(mScrollable);
+        event.setScrollX(mScrollX);
+        event.setScrollY(mOwnScrollY);
+        event.setMaxScrollX(mScrollX);
+        event.setMaxScrollY(getScrollRange());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfoInternal(info);
+        if (mScrollable) {
+            info.setScrollable(true);
+            if (mBackwardScrollable) {
+                info.addAction(
+                        AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP);
+            }
+            if (mForwardScrollable) {
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_DOWN);
+            }
+        }
+        // Talkback only listenes to scroll events of certain classes, let's make us a scrollview
+        info.setClassName(ScrollView.class.getName());
+    }
+
+    /** @hide */
+    @Override
+    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+        if (super.performAccessibilityActionInternal(action, arguments)) {
+            return true;
+        }
+        if (!isEnabled()) {
+            return false;
+        }
+        int direction = -1;
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
+                // fall through
+            case android.R.id.accessibilityActionScrollDown:
+                direction = 1;
+                // fall through
+            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
+                // fall through
+            case android.R.id.accessibilityActionScrollUp:
+                final int viewportHeight = getHeight() - mPaddingBottom - mTopPadding - mPaddingTop
+                        - mShelf.getIntrinsicHeight();
+                final int targetScrollY = Math.max(0,
+                        Math.min(mOwnScrollY + direction * viewportHeight, getScrollRange()));
+                if (targetScrollY != mOwnScrollY) {
+                    mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScrollY - mOwnScrollY);
+                    animateScroll();
+                    return true;
+                }
+                break;
+        }
+        return false;
+    }
+
+    @Override
+    public void onGroupsChanged() {
+        mStatusBar.requestNotificationUpdate();
+    }
+
+    public void generateChildOrderChangedEvent() {
+        if (mIsExpanded && mAnimationsEnabled) {
+            mGenerateChildOrderChangedEvent = true;
+            mNeedsAnimation = true;
+            requestChildrenUpdate();
+        }
+    }
+
+    @Override
+    public int getContainerChildCount() {
+        return getChildCount();
+    }
+
+    @Override
+    public View getContainerChildAt(int i) {
+        return getChildAt(i);
+    }
+
+    @Override
+    public void removeContainerView(View v) {
+        removeView(v);
+    }
+
+    @Override
+    public void addContainerView(View v) {
+        addView(v);
+    }
+
+    public void runAfterAnimationFinished(Runnable runnable) {
+        mAnimationFinishedRunnables.add(runnable);
+    }
+
+    public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
+        mHeadsUpManager = headsUpManager;
+        mAmbientState.setHeadsUpManager(headsUpManager);
+        mHeadsUpManager.addListener(mRoundnessManager);
+        mHeadsUpManager.setAnimationStateHandler(this);
+    }
+
+    public void generateHeadsUpAnimation(ExpandableNotificationRow row, boolean isHeadsUp) {
+        if (mAnimationsEnabled && (isHeadsUp || mHeadsUpGoingAwayAnimationsAllowed)) {
+            mHeadsUpChangeAnimations.add(new Pair<>(row, isHeadsUp));
+            mNeedsAnimation = true;
+            if (!mIsExpanded && !isHeadsUp) {
+                row.setHeadsUpAnimatingAway(true);
+            }
+            requestChildrenUpdate();
+        }
+    }
+
+    public void setShadeExpanded(boolean shadeExpanded) {
+        mAmbientState.setShadeExpanded(shadeExpanded);
+        mStateAnimator.setShadeExpanded(shadeExpanded);
+    }
+
+    /**
+     * Set the boundary for the bottom heads up position. The heads up will always be above this
+     * position.
+     *
+     * @param height          the height of the screen
+     * @param bottomBarHeight the height of the bar on the bottom
+     */
+    public void setHeadsUpBoundaries(int height, int bottomBarHeight) {
+        mAmbientState.setMaxHeadsUpTranslation(height - bottomBarHeight);
+        mStateAnimator.setHeadsUpAppearHeightBottom(height);
+        requestChildrenUpdate();
+    }
+
+    public void setTrackingHeadsUp(ExpandableNotificationRow row) {
+        mTrackingHeadsUp = row != null;
+        mRoundnessManager.setTrackingHeadsUp(row);
+    }
+
+    public void setScrimController(ScrimController scrimController) {
+        mScrimController = scrimController;
+        mScrimController.setScrimBehindChangeRunnable(this::updateBackgroundDimming);
+    }
+
+    public void forceNoOverlappingRendering(boolean force) {
+        mForceNoOverlappingRendering = force;
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return !mForceNoOverlappingRendering && super.hasOverlappingRendering();
+    }
+
+    public void setAnimationRunning(boolean animationRunning) {
+        if (animationRunning != mAnimationRunning) {
+            if (animationRunning) {
+                getViewTreeObserver().addOnPreDrawListener(mRunningAnimationUpdater);
+            } else {
+                getViewTreeObserver().removeOnPreDrawListener(mRunningAnimationUpdater);
+            }
+            mAnimationRunning = animationRunning;
+            updateContinuousShadowDrawing();
+        }
+    }
+
+    public boolean isExpanded() {
+        return mIsExpanded;
+    }
+
+    public void setPulsing(boolean pulsing, boolean animated) {
+        if (!mPulsing && !pulsing) {
+            return;
+        }
+        mPulsing = pulsing;
+        mNeedingPulseAnimation = animated ? getFirstChildNotGone() : null;
+        mAmbientState.setPulsing(pulsing);
+        updateNotificationAnimationStates();
+        updateAlgorithmHeightAndPadding();
+        updateContentHeight();
+        requestChildrenUpdate();
+        notifyHeightChangeListener(null, animated);
+        mNeedsAnimation |= animated;
+    }
+
+    private void generatePulsingAnimationEvent() {
+        if (mNeedingPulseAnimation != null) {
+            int type = mPulsing ? AnimationEvent.ANIMATION_TYPE_PULSE_APPEAR
+                    : AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR;
+            mAnimationEvents.add(new AnimationEvent(mNeedingPulseAnimation, type));
+            mNeedingPulseAnimation = null;
+        }
+    }
+
+    public void setFadingOut(boolean fadingOut) {
+        if (fadingOut != mFadingOut) {
+            mFadingOut = fadingOut;
+            updateFadingState();
+        }
+    }
+
+    public void setParentNotFullyVisible(boolean parentNotFullyVisible) {
+        if (mScrimController == null) {
+            // we're not set up yet.
+            return;
+        }
+        if (parentNotFullyVisible != mParentNotFullyVisible) {
+            mParentNotFullyVisible = parentNotFullyVisible;
+            updateFadingState();
+        }
+    }
+
+    private void updateFadingState() {
+        applyCurrentBackgroundBounds();
+        updateSrcDrawing();
+    }
+
+    @Override
+    public void setAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha) {
+        super.setAlpha(alpha);
+        setFadingOut(alpha != 1.0f);
+    }
+
+    public void setQsExpanded(boolean qsExpanded) {
+        mQsExpanded = qsExpanded;
+        updateAlgorithmLayoutMinHeight();
+        updateScrollability();
+    }
+
+    public void setQsExpansionFraction(float qsExpansionFraction) {
+        mQsExpansionFraction = qsExpansionFraction;
+    }
+
+    public void setOwnScrollY(int ownScrollY) {
+        if (ownScrollY != mOwnScrollY) {
+            // We still want to call the normal scrolled changed for accessibility reasons
+            onScrollChanged(mScrollX, ownScrollY, mScrollX, mOwnScrollY);
+            mOwnScrollY = ownScrollY;
+            updateForwardAndBackwardScrollability();
+            requestChildrenUpdate();
+        }
+    }
+
+    public void setShelf(NotificationShelf shelf) {
+        int index = -1;
+        if (mShelf != null) {
+            index = indexOfChild(mShelf);
+            removeView(mShelf);
+        }
+        mShelf = shelf;
+        addView(mShelf, index);
+        mAmbientState.setShelf(shelf);
+        mStateAnimator.setShelf(shelf);
+        shelf.bind(mAmbientState, this);
+    }
+
+    public NotificationShelf getNotificationShelf() {
+        return mShelf;
+    }
+
+    public void setMaxDisplayedNotifications(int maxDisplayedNotifications) {
+        if (mMaxDisplayedNotifications != maxDisplayedNotifications) {
+            mMaxDisplayedNotifications = maxDisplayedNotifications;
+            updateContentHeight();
+            notifyHeightChangeListener(mShelf);
+        }
+    }
+
+    public void setShouldShowShelfOnly(boolean shouldShowShelfOnly) {
+        mShouldShowShelfOnly = shouldShowShelfOnly;
+        updateAlgorithmLayoutMinHeight();
+    }
+
+    public int getMinExpansionHeight() {
+        return mShelf.getIntrinsicHeight() - (mShelf.getIntrinsicHeight() - mStatusBarHeight) / 2;
+    }
+
+    public void setInHeadsUpPinnedMode(boolean inHeadsUpPinnedMode) {
+        mInHeadsUpPinnedMode = inHeadsUpPinnedMode;
+        updateClipping();
+    }
+
+    public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
+        mHeadsUpAnimatingAway = headsUpAnimatingAway;
+        updateClipping();
+    }
+
+    private void setStatusBarState(int statusBarState) {
+        mStatusBarState = statusBarState;
+        mAmbientState.setStatusBarState(statusBarState);
+        boolean onKeyguard = onKeyguard();
+        boolean publicMode = mLockscreenUserManager.isAnyProfilePublicMode();
+        if (mHeadsUpAppearanceController != null) {
+            mHeadsUpAppearanceController.setPublicMode(publicMode);
+        }
+
+        StatusBarStateController state = Dependency.get(StatusBarStateController.class);
+        setHideSensitive(publicMode, state.goingToFullShade() /* animate */);
+        setDimmed(onKeyguard, state.fromShadeLocked() /* animate */);
+        setExpandingEnabled(!onKeyguard);
+        ActivatableNotificationView activatedChild = getActivatedChild();
+        setActivatedChild(null);
+        if (activatedChild != null) {
+            activatedChild.makeInactive(false /* animate */);
+        }
+        updateFooter();
+        updateChildren();
+        onUpdateRowStates();
+    }
+
+    public void setExpandingVelocity(float expandingVelocity) {
+        mAmbientState.setExpandingVelocity(expandingVelocity);
+    }
+
+    public float getOpeningHeight() {
+        if (mEmptyShadeView.getVisibility() == GONE) {
+            return getMinExpansionHeight();
+        } else {
+            return getAppearEndPosition();
+        }
+    }
+
+    public void setIsFullWidth(boolean isFullWidth) {
+        mAmbientState.setPanelFullWidth(isFullWidth);
+    }
+
+    public void setUnlockHintRunning(boolean running) {
+        mAmbientState.setUnlockHintRunning(running);
+    }
+
+    public void setQsCustomizerShowing(boolean isShowing) {
+        mAmbientState.setQsCustomizerShowing(isShowing);
+        requestChildrenUpdate();
+    }
+
+    @Override
+    public void setHeadsUpGoingAwayAnimationsAllowed(boolean headsUpGoingAwayAnimationsAllowed) {
+        mHeadsUpGoingAwayAnimationsAllowed = headsUpGoingAwayAnimationsAllowed;
+    }
+
+    public void setAntiBurnInOffsetX(int antiBurnInOffsetX) {
+        mAntiBurnInOffsetX = antiBurnInOffsetX;
+        updatePanelTranslation();
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println(String.format("[%s: pulsing=%s qsCustomizerShowing=%s visibility=%s"
+                        + " alpha:%f scrollY:%d maxTopPadding:%d showShelfOnly=%s"
+                        + " qsExpandFraction=%f]",
+                this.getClass().getSimpleName(),
+                mPulsing ? "T" : "f",
+                mAmbientState.isQsCustomizerShowing() ? "T" : "f",
+                getVisibility() == View.VISIBLE ? "visible"
+                        : getVisibility() == View.GONE ? "gone"
+                                : "invisible",
+                getAlpha(),
+                mAmbientState.getScrollY(),
+                mMaxTopPadding,
+                mShouldShowShelfOnly ? "T" : "f",
+                mQsExpansionFraction));
+    }
+
+    public boolean isFullyDark() {
+        return mAmbientState.isFullyDark();
+    }
+
+    /**
+     * Add a listener whenever the expanded height changes. The first value passed as an argument
+     * is the expanded height and the second one is the appearFraction.
+     *
+     * @param listener the listener to notify.
+     */
+    public void addOnExpandedHeightListener(BiConsumer<Float, Float> listener) {
+        mExpandedHeightListeners.add(listener);
+    }
+
+    /**
+     * Stop a listener from listening to the expandedHeight.
+     */
+    public void removeOnExpandedHeightListener(BiConsumer<Float, Float> listener) {
+        mExpandedHeightListeners.remove(listener);
+    }
+
+    public void setHeadsUpAppearanceController(
+            HeadsUpAppearanceController headsUpAppearanceController) {
+        mHeadsUpAppearanceController = headsUpAppearanceController;
+    }
+
+    public void setIconAreaController(NotificationIconAreaController controller) {
+        mIconAreaController = controller;
+    }
+
+    public void manageNotifications(View v) {
+        Intent intent = new Intent(Settings.ACTION_ALL_APPS_NOTIFICATION_SETTINGS);
+        mStatusBar.startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP);
+    }
+
+    public void clearAllNotifications() {
+        // animate-swipe all dismissable notifications, then animate the shade closed
+        int numChildren = getChildCount();
+
+        final ArrayList<View> viewsToHide = new ArrayList<>(numChildren);
+        final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren);
+        for (int i = 0; i < numChildren; i++) {
+            final View child = getChildAt(i);
+            if (child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                boolean parentVisible = false;
+                boolean hasClipBounds = child.getClipBounds(mTmpRect);
+                if (canChildBeDismissed(child)) {
+                    viewsToRemove.add(row);
+                    if (child.getVisibility() == View.VISIBLE
+                            && (!hasClipBounds || mTmpRect.height() > 0)) {
+                        viewsToHide.add(child);
+                        parentVisible = true;
+                    }
+                } else if (child.getVisibility() == View.VISIBLE
+                        && (!hasClipBounds || mTmpRect.height() > 0)) {
+                    parentVisible = true;
+                }
+                List<ExpandableNotificationRow> children = row.getNotificationChildren();
+                if (children != null) {
+                    for (ExpandableNotificationRow childRow : children) {
+                        viewsToRemove.add(childRow);
+                        if (parentVisible && row.areChildrenExpanded()
+                                && canChildBeDismissed(childRow)) {
+                            hasClipBounds = childRow.getClipBounds(mTmpRect);
+                            if (childRow.getVisibility() == View.VISIBLE
+                                    && (!hasClipBounds || mTmpRect.height() > 0)) {
+                                viewsToHide.add(childRow);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (viewsToRemove.isEmpty()) {
+            mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+            return;
+        }
+
+        mStatusBar.addPostCollapseAction(() -> {
+            setDismissAllInProgress(false);
+            for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
+                if (canChildBeDismissed(rowToRemove)) {
+                    mEntryManager.removeNotification(rowToRemove.getEntry().key, null);
+                } else {
+                    rowToRemove.resetTranslation();
+                }
+            }
+            try {
+                mBarService.onClearAllNotifications(mLockscreenUserManager.getCurrentUserId());
+            } catch (Exception ex) {
+            }
+        });
+
+        performDismissAllAnimations(viewsToHide);
+    }
+
+    public void performDismissAllAnimations(ArrayList<View> hideAnimatedList) {
+        Runnable animationFinishAction = () -> {
+            mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+        };
+
+        if (hideAnimatedList.isEmpty()) {
+            animationFinishAction.run();
+            return;
+        }
+
+        // let's disable our normal animations
+        setDismissAllInProgress(true);
+
+        // Decrease the delay for every row we animate to give the sense of
+        // accelerating the swipes
+        int rowDelayDecrement = 10;
+        int currentDelay = 140;
+        int totalDelay = 180;
+        int numItems = hideAnimatedList.size();
+        for (int i = numItems - 1; i >= 0; i--) {
+            View view = hideAnimatedList.get(i);
+            Runnable endRunnable = null;
+            if (i == 0) {
+                endRunnable = animationFinishAction;
+            }
+            dismissViewAnimated(view, endRunnable, totalDelay, 260);
+            currentDelay = Math.max(50, currentDelay - rowDelayDecrement);
+            totalDelay += currentDelay;
+        }
+    }
+
+    @VisibleForTesting
+    protected void inflateFooterView() {
+        FooterView footerView = (FooterView) LayoutInflater.from(mContext).inflate(
+                R.layout.status_bar_notification_footer, this, false);
+        footerView.setDismissButtonClickListener(v -> {
+            mMetricsLogger.action(MetricsEvent.ACTION_DISMISS_ALL_NOTES);
+            clearAllNotifications();
+        });
+        footerView.setManageButtonClickListener(this::manageNotifications);
+        setFooterView(footerView);
+    }
+
+    private void inflateEmptyShadeView() {
+        EmptyShadeView view = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
+                R.layout.status_bar_no_notifications, this, false);
+        view.setText(R.string.empty_shade_text);
+        setEmptyShadeView(view);
+    }
+
+    /**
+     * Updates expanded, dimmed and locked states of notification rows.
+     */
+    public void onUpdateRowStates() {
+        changeViewPosition(mFooterView, -1);
+
+        // The following views will be moved to the end of mStackScroller. This counter represents
+        // the offset from the last child. Initialized to 1 for the very last position. It is post-
+        // incremented in the following "changeViewPosition" calls so that its value is correct for
+        // subsequent calls.
+        int offsetFromEnd = 1;
+        changeViewPosition(mEmptyShadeView,
+                getChildCount() - offsetFromEnd++);
+
+        // No post-increment for this call because it is the last one. Make sure to add one if
+        // another "changeViewPosition" call is ever added.
+        changeViewPosition(mShelf,
+                getChildCount() - offsetFromEnd);
+
+        // Scrim opacity varies based on notification count
+        mScrimController.setNotificationCount(getNotGoneChildCount());
+    }
+
+    public void setNotificationPanel(NotificationPanelView notificationPanelView) {
+        mNotificationPanel = notificationPanelView;
+    }
+
+    /**
+     * A listener that is notified when the empty space below the notifications is clicked on
+     */
+    public interface OnEmptySpaceClickListener {
+        void onEmptySpaceClicked(float x, float y);
+    }
+
+    /**
+     * A listener that gets notified when the overscroll at the top has changed.
+     */
+    public interface OnOverscrollTopChangedListener {
+
+        /**
+         * Notifies a listener that the overscroll has changed.
+         *
+         * @param amount         the amount of overscroll, in pixels
+         * @param isRubberbanded if true, this is a rubberbanded overscroll; if false, this is an
+         *                       unrubberbanded motion to directly expand overscroll view (e.g
+         *                       expand
+         *                       QS)
+         */
+        void onOverscrollTopChanged(float amount, boolean isRubberbanded);
+
+        /**
+         * Notify a listener that the scroller wants to escape from the scrolling motion and
+         * start a fling animation to the expanded or collapsed overscroll view (e.g expand the QS)
+         *
+         * @param velocity The velocity that the Scroller had when over flinging
+         * @param open     Should the fling open or close the overscroll view.
+         */
+        void flingTopOverscroll(float velocity, boolean open);
+    }
+
+    private class NotificationSwipeHelper extends SwipeHelper
+            implements NotificationSwipeActionHelper {
+        private static final long COVER_MENU_DELAY = 4000;
+        private Runnable mFalsingCheck;
+        private Handler mHandler;
+
+        public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) {
+            super(swipeDirection, callback, context);
+            mHandler = new Handler();
+            mFalsingCheck = new Runnable() {
+                @Override
+                public void run() {
+                    resetExposedMenuView(true /* animate */, true /* force */);
+                }
+            };
+        }
+
+        @Override
+        public void onDownUpdate(View currView, MotionEvent ev) {
+            mTranslatingParentView = currView;
+            if (mCurrMenuRow != null) {
+                mCurrMenuRow.onTouchEvent(currView, ev, 0 /* velocity */);
+            }
+            mCurrMenuRow = null;
+            mHandler.removeCallbacks(mFalsingCheck);
+
+            // Slide back any notifications that might be showing a menu
+            resetExposedMenuView(true /* animate */, false /* force */);
+
+            if (currView instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) currView;
+
+                if (row.getEntry().hasFinishedInitialization()) {
+                    mCurrMenuRow = row.createMenu();
+                    mCurrMenuRow.setSwipeActionHelper(NotificationSwipeHelper.this);
+                    mCurrMenuRow.setMenuClickListener(NotificationStackScrollLayout.this);
+                    mCurrMenuRow.onTouchEvent(currView, ev, 0 /* velocity */);
+                }
+            }
+        }
+
+        @Override
+        public void onMoveUpdate(View view, MotionEvent ev, float translation, float delta) {
+            mHandler.removeCallbacks(mFalsingCheck);
+            if (mCurrMenuRow != null) {
+                mCurrMenuRow.onTouchEvent(view, ev, 0 /* velocity */);
+            }
+        }
+
+        @Override
+        public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
+                float translation) {
+            if (mCurrMenuRow != null) {
+                return mCurrMenuRow.onTouchEvent(animView, ev, velocity);
+            }
+            return false;
+        }
+
+        @Override
+        public void dismissChild(final View view, float velocity,
+                boolean useAccelerateInterpolator) {
+            super.dismissChild(view, velocity, useAccelerateInterpolator);
+            if (mIsExpanded) {
+                // We don't want to quick-dismiss when it's a heads up as this might lead to closing
+                // of the panel early.
+                handleChildViewDismissed(view);
+            }
+            mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
+                    false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
+                    false /* resetMenu */);
+            handleMenuCoveredOrDismissed();
+        }
+
+        @Override
+        public void snapChild(final View animView, final float targetLeft, float velocity) {
+            super.snapChild(animView, targetLeft, velocity);
+            onDragCancelled(animView);
+            if (targetLeft == 0) {
+                handleMenuCoveredOrDismissed();
+            }
+        }
+
+        @Override
+        public void snooze(StatusBarNotification sbn, SnoozeOption snoozeOption) {
+            mStatusBar.setNotificationSnoozed(sbn, snoozeOption);
+        }
+
+        public boolean isFalseGesture(MotionEvent ev) {
+            return super.isFalseGesture(ev);
+        }
+
+        private void handleMenuCoveredOrDismissed() {
+            if (mMenuExposedView != null && mMenuExposedView == mTranslatingParentView) {
+                mMenuExposedView = null;
+            }
+        }
+
+        @Override
+        public Animator getViewTranslationAnimator(View v, float target,
+                AnimatorUpdateListener listener) {
+            if (v instanceof ExpandableNotificationRow) {
+                return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
+            } else {
+                return super.getViewTranslationAnimator(v, target, listener);
+            }
+        }
+
+        @Override
+        public void setTranslation(View v, float translate) {
+            ((ExpandableView) v).setTranslation(translate);
+        }
+
+        @Override
+        public float getTranslation(View v) {
+            return ((ExpandableView) v).getTranslation();
+        }
+
+        @Override
+        public void dismiss(View animView, float velocity) {
+            dismissChild(animView, velocity,
+                    !swipedFastEnough(0, 0) /* useAccelerateInterpolator */);
+        }
+
+        @Override
+        public void snap(View animView, float targetLeft, float velocity) {
+            snapChild(animView, targetLeft, velocity);
+        }
+
+        @Override
+        public boolean swipedFarEnough(float translation, float viewSize) {
+            return swipedFarEnough();
+        }
+
+        @Override
+        public boolean swipedFastEnough(float translation, float velocity) {
+            return swipedFastEnough();
+        }
+
+        @Override
+        public float getMinDismissVelocity() {
+            return getEscapeVelocity();
+        }
+
+        public void onMenuShown(View animView) {
+            onDragCancelled(animView);
+
+            // If we're on the lockscreen we want to false this.
+            if (isAntiFalsingNeeded()) {
+                mHandler.removeCallbacks(mFalsingCheck);
+                mHandler.postDelayed(mFalsingCheck, COVER_MENU_DELAY);
+            }
+        }
+
+        public void closeControlsIfOutsideTouch(MotionEvent ev) {
+            NotificationGuts guts = mStatusBar.getGutsManager().getExposedGuts();
+            View view = null;
+            if (guts != null && !guts.getGutsContent().isLeavebehind()) {
+                // Only close visible guts if they're not a leavebehind.
+                view = guts;
+            } else if (mCurrMenuRow != null && mCurrMenuRow.isMenuVisible()
+                    && mTranslatingParentView != null) {
+                // Checking menu
+                view = mTranslatingParentView;
+            }
+            if (view != null && !isTouchInView(ev, view)) {
+                // Touch was outside visible guts / menu notification, close what's visible
+                mStatusBar.getGutsManager().closeAndSaveGuts(false /* removeLeavebehind */,
+                        false /* force */, true /* removeControls */, -1 /* x */, -1 /* y */,
+                        false /* resetMenu */);
+                resetExposedMenuView(true /* animate */, true /* force */);
+            }
+        }
+
+        public void resetExposedMenuView(boolean animate, boolean force) {
+            if (mMenuExposedView == null
+                    || (!force && mMenuExposedView == mTranslatingParentView)) {
+                // If no menu is showing or it's showing for this view we do nothing.
+                return;
+            }
+            final View prevMenuExposedView = mMenuExposedView;
+            if (animate) {
+                Animator anim = getViewTranslationAnimator(prevMenuExposedView,
+                        0 /* leftTarget */, null /* updateListener */);
+                if (anim != null) {
+                    anim.start();
+                }
+            } else if (mMenuExposedView instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) mMenuExposedView;
+                if (!row.isRemoved()) {
+                    row.resetTranslation();
+                }
+            }
+            mMenuExposedView = null;
+        }
+    }
+
+    public boolean hasActiveNotifications() {
+        return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
+    }
+
+    // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
+
+
+    /* Only ever called as a consequence of a lockscreen expansion gesture. */
+    @Override
+    public boolean onDraggedDown(View startingChild, int dragLengthY) {
+        if (mStatusBarState == StatusBarState.KEYGUARD
+                && hasActiveNotifications() && (!mStatusBar.isDozing() || mStatusBar.isPulsing())) {
+            mLockscreenGestureLogger.write(
+                    MetricsEvent.ACTION_LS_SHADE,
+                    (int) (dragLengthY / mDisplayMetrics.density),
+                    0 /* velocityDp - N/A */);
+
+            // We have notifications, go to locked shade.
+            mStatusBar.goToLockedShade(startingChild);
+            if (startingChild instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild;
+                row.onExpandedByGesture(true /* drag down is always an open */);
+            }
+            return true;
+        } else {
+            // abort gesture.
+            return false;
+        }
+    }
+
+    @Override
+    public void onDragDownReset() {
+        setDimmed(true /* dimmed */, true /* animated */);
+        resetScrollPosition();
+        resetCheckSnoozeLeavebehind();
+    }
+
+    @Override
+    public void onCrossedThreshold(boolean above) {
+        setDimmed(!above /* dimmed */, true /* animate */);
+    }
+
+    @Override
+    public void onTouchSlopExceeded() {
+        cancelLongPress();
+        checkSnoozeLeavebehind();
+    }
+
+    @Override
+    public void setEmptyDragAmount(float amount) {
+        mNotificationPanel.setEmptyDragAmount(amount);
+    }
+
+    @Override
+    public boolean isFalsingCheckNeeded() {
+        return mStatusBarState == StatusBarState.KEYGUARD;
+    }
+
+    public void updateSpeedBumpIndex() {
+        int speedBumpIndex = 0;
+        int currentIndex = 0;
+        final int N = getChildCount();
+        for (int i = 0; i < N; i++) {
+            View view = getChildAt(i);
+            if (view.getVisibility() == View.GONE || !(view instanceof ExpandableNotificationRow)) {
+                continue;
+            }
+            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+            currentIndex++;
+            if (!mEntryManager.getNotificationData().isAmbient(
+                    row.getStatusBarNotification().getKey())) {
+                speedBumpIndex = currentIndex;
+            }
+        }
+        boolean noAmbient = speedBumpIndex == N;
+        updateSpeedBumpIndex(speedBumpIndex, noAmbient);
+    }
+
+    private boolean isTouchInView(MotionEvent ev, View view) {
+        if (view == null) {
+            return false;
+        }
+        final int height = (view instanceof ExpandableView)
+                ? ((ExpandableView) view).getActualHeight()
+                : view.getHeight();
+        final int rx = (int) ev.getRawX();
+        final int ry = (int) ev.getRawY();
+        view.getLocationOnScreen(mTempInt2);
+        final int x = mTempInt2[0];
+        final int y = mTempInt2[1];
+        Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
+        boolean ret = rect.contains(rx, ry);
+        return ret;
+    }
+
+    private void updateContinuousShadowDrawing() {
+        boolean continuousShadowUpdate = mAnimationRunning
+                || !mAmbientState.getDraggedViews().isEmpty();
+        if (continuousShadowUpdate != mContinuousShadowUpdate) {
+            if (continuousShadowUpdate) {
+                getViewTreeObserver().addOnPreDrawListener(mShadowUpdater);
+            } else {
+                getViewTreeObserver().removeOnPreDrawListener(mShadowUpdater);
+            }
+            mContinuousShadowUpdate = continuousShadowUpdate;
+        }
+    }
+
+    @Override
+    public void resetExposedMenuView(boolean animate, boolean force) {
+        mSwipeHelper.resetExposedMenuView(animate, force);
+    }
+
+    public void closeControlsIfOutsideTouch(MotionEvent ev) {
+        mSwipeHelper.closeControlsIfOutsideTouch(ev);
+    }
+
+    static class AnimationEvent {
+
+        static AnimationFilter[] FILTERS = new AnimationFilter[]{
+
+                // ANIMATION_TYPE_ADD
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ()
+                        .hasDelays(),
+
+                // ANIMATION_TYPE_REMOVE
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ()
+                        .hasDelays(),
+
+                // ANIMATION_TYPE_REMOVE_SWIPED_OUT
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ()
+                        .hasDelays(),
+
+                // ANIMATION_TYPE_TOP_PADDING_CHANGED
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateDimmed()
+                        .animateZ(),
+
+                // ANIMATION_TYPE_START_DRAG
+                new AnimationFilter()
+                        .animateShadowAlpha(),
+
+                // ANIMATION_TYPE_SNAP_BACK
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight(),
+
+                // ANIMATION_TYPE_ACTIVATED_CHILD
+                new AnimationFilter()
+                        .animateZ(),
+
+                // ANIMATION_TYPE_DIMMED
+                new AnimationFilter()
+                        .animateDimmed(),
+
+                // ANIMATION_TYPE_CHANGE_POSITION
+                new AnimationFilter()
+                        .animateAlpha() // maybe the children change positions
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ(),
+
+                // ANIMATION_TYPE_DARK
+                null, // Unused
+
+                // ANIMATION_TYPE_GO_TO_FULL_SHADE
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateDimmed()
+                        .animateZ()
+                        .hasDelays(),
+
+                // ANIMATION_TYPE_HIDE_SENSITIVE
+                new AnimationFilter()
+                        .animateHideSensitive(),
+
+                // ANIMATION_TYPE_VIEW_RESIZE
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ(),
+
+                // ANIMATION_TYPE_GROUP_EXPANSION_CHANGED
+                new AnimationFilter()
+                        .animateAlpha()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ(),
+
+                // ANIMATION_TYPE_HEADS_UP_APPEAR
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ(),
+
+                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ()
+                        .hasDelays(),
+
+                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ()
+                        .hasDelays(),
+
+                // ANIMATION_TYPE_HEADS_UP_OTHER
+                new AnimationFilter()
+                        .animateShadowAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ(),
+
+                // ANIMATION_TYPE_EVERYTHING
+                new AnimationFilter()
+                        .animateAlpha()
+                        .animateShadowAlpha()
+                        .animateDark()
+                        .animateDimmed()
+                        .animateHideSensitive()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ(),
+
+                // ANIMATION_TYPE_PULSE_APPEAR
+                new AnimationFilter()
+                        .animateAlpha()
+                        .hasDelays()
+                        .animateY(),
+
+                // ANIMATION_TYPE_PULSE_DISAPPEAR
+                new AnimationFilter()
+                        .animateAlpha()
+                        .hasDelays()
+                        .animateY(),
+        };
+
+        static int[] LENGTHS = new int[]{
+
+                // ANIMATION_TYPE_ADD
+                StackStateAnimator.ANIMATION_DURATION_APPEAR_DISAPPEAR,
+
+                // ANIMATION_TYPE_REMOVE
+                StackStateAnimator.ANIMATION_DURATION_APPEAR_DISAPPEAR,
+
+                // ANIMATION_TYPE_REMOVE_SWIPED_OUT
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_TOP_PADDING_CHANGED
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_START_DRAG
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_SNAP_BACK
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_ACTIVATED_CHILD
+                StackStateAnimator.ANIMATION_DURATION_DIMMED_ACTIVATED,
+
+                // ANIMATION_TYPE_DIMMED
+                StackStateAnimator.ANIMATION_DURATION_DIMMED_ACTIVATED,
+
+                // ANIMATION_TYPE_CHANGE_POSITION
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_DARK
+                StackStateAnimator.ANIMATION_DURATION_WAKEUP,
+
+                // ANIMATION_TYPE_GO_TO_FULL_SHADE
+                StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE,
+
+                // ANIMATION_TYPE_HIDE_SENSITIVE
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_VIEW_RESIZE
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_GROUP_EXPANSION_CHANGED
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_HEADS_UP_APPEAR
+                StackStateAnimator.ANIMATION_DURATION_HEADS_UP_APPEAR,
+
+                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR
+                StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
+
+                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+                StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
+
+                // ANIMATION_TYPE_HEADS_UP_OTHER
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_EVERYTHING
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_PULSE_APPEAR
+                StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR,
+
+                // ANIMATION_TYPE_PULSE_DISAPPEAR
+                StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR / 2,
+        };
+
+        static final int ANIMATION_TYPE_ADD = 0;
+        static final int ANIMATION_TYPE_REMOVE = 1;
+        static final int ANIMATION_TYPE_REMOVE_SWIPED_OUT = 2;
+        static final int ANIMATION_TYPE_TOP_PADDING_CHANGED = 3;
+        static final int ANIMATION_TYPE_START_DRAG = 4;
+        static final int ANIMATION_TYPE_SNAP_BACK = 5;
+        static final int ANIMATION_TYPE_ACTIVATED_CHILD = 6;
+        static final int ANIMATION_TYPE_DIMMED = 7;
+        static final int ANIMATION_TYPE_CHANGE_POSITION = 8;
+        static final int ANIMATION_TYPE_DARK = 9;
+        static final int ANIMATION_TYPE_GO_TO_FULL_SHADE = 10;
+        static final int ANIMATION_TYPE_HIDE_SENSITIVE = 11;
+        static final int ANIMATION_TYPE_VIEW_RESIZE = 12;
+        static final int ANIMATION_TYPE_GROUP_EXPANSION_CHANGED = 13;
+        static final int ANIMATION_TYPE_HEADS_UP_APPEAR = 14;
+        static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR = 15;
+        static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK = 16;
+        static final int ANIMATION_TYPE_HEADS_UP_OTHER = 17;
+        static final int ANIMATION_TYPE_EVERYTHING = 18;
+        static final int ANIMATION_TYPE_PULSE_APPEAR = 19;
+        static final int ANIMATION_TYPE_PULSE_DISAPPEAR = 20;
+
+        static final int DARK_ANIMATION_ORIGIN_INDEX_ABOVE = -1;
+        static final int DARK_ANIMATION_ORIGIN_INDEX_BELOW = -2;
+
+        final long eventStartTime;
+        final View changingView;
+        final int animationType;
+        final AnimationFilter filter;
+        final long length;
+        View viewAfterChangingView;
+        int darkAnimationOriginIndex;
+        boolean headsUpFromBottom;
+
+        AnimationEvent(View view, int type) {
+            this(view, type, LENGTHS[type]);
+        }
+
+        AnimationEvent(View view, int type, AnimationFilter filter) {
+            this(view, type, LENGTHS[type], filter);
+        }
+
+        AnimationEvent(View view, int type, long length) {
+            this(view, type, length, FILTERS[type]);
+        }
+
+        AnimationEvent(View view, int type, long length, AnimationFilter filter) {
+            eventStartTime = AnimationUtils.currentAnimationTimeMillis();
+            changingView = view;
+            animationType = type;
+            this.length = length;
+            this.filter = filter;
+        }
+
+        /**
+         * Combines the length of several animation events into a single value.
+         *
+         * @param events The events of the lengths to combine.
+         * @return The combined length. Depending on the event types, this might be the maximum of
+         * all events or the length of a specific event.
+         */
+        static long combineLength(ArrayList<AnimationEvent> events) {
+            long length = 0;
+            int size = events.size();
+            for (int i = 0; i < size; i++) {
+                AnimationEvent event = events.get(i);
+                length = Math.max(length, event.length);
+                if (event.animationType == ANIMATION_TYPE_GO_TO_FULL_SHADE) {
+                    return event.length;
+                }
+            }
+            return length;
+        }
+    }
+
+    private final StateListener mStateListener = new StateListener() {
+        @Override
+        public void onStatePreChange(int oldState, int newState) {
+            if (oldState == StatusBarState.SHADE_LOCKED && newState == StatusBarState.KEYGUARD) {
+                requestAnimateEverything();
+            }
+        }
+
+        @Override
+        public void onStateChanged(int newState) {
+            setStatusBarState(newState);
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
new file mode 100644
index 0000000..742d89d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -0,0 +1,655 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.row.FooterView;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * The Algorithm of the {@link com.android.systemui.statusbar.notification.stack
+ * .NotificationStackScrollLayout} which can be queried for {@link com.android.systemui.statusbar
+ * .stack.StackScrollState}
+ */
+public class StackScrollAlgorithm {
+
+    private static final String LOG_TAG = "StackScrollAlgorithm";
+
+    private int mPaddingBetweenElements;
+    private int mIncreasedPaddingBetweenElements;
+    private int mCollapsedSize;
+
+    private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
+    private boolean mIsExpanded;
+    private boolean mClipNotificationScrollToTop;
+    private int mStatusBarHeight;
+    private float mHeadsUpInset;
+    private int mPinnedZTranslationExtra;
+
+    public StackScrollAlgorithm(Context context) {
+        initView(context);
+    }
+
+    public void initView(Context context) {
+        initConstants(context);
+    }
+
+    private void initConstants(Context context) {
+        Resources res = context.getResources();
+        mPaddingBetweenElements = res.getDimensionPixelSize(
+                R.dimen.notification_divider_height);
+        mIncreasedPaddingBetweenElements =
+                res.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
+        mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
+        mStatusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
+        mClipNotificationScrollToTop = res.getBoolean(R.bool.config_clipNotificationScrollToTop);
+        mHeadsUpInset = mStatusBarHeight + res.getDimensionPixelSize(
+                R.dimen.heads_up_status_bar_padding);
+        mPinnedZTranslationExtra = res.getDimensionPixelSize(
+                R.dimen.heads_up_pinned_elevation);
+    }
+
+    public void getStackScrollState(AmbientState ambientState, StackScrollState resultState) {
+        // The state of the local variables are saved in an algorithmState to easily subdivide it
+        // into multiple phases.
+        StackScrollAlgorithmState algorithmState = mTempAlgorithmState;
+
+        // First we reset the view states to their default values.
+        resultState.resetViewStates();
+
+        initAlgorithmState(resultState, algorithmState, ambientState);
+
+        updatePositionsForState(resultState, algorithmState, ambientState);
+
+        updateZValuesForState(resultState, algorithmState, ambientState);
+
+        updateHeadsUpStates(resultState, algorithmState, ambientState);
+
+        handleDraggedViews(ambientState, resultState, algorithmState);
+        updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState);
+        updateClipping(resultState, algorithmState, ambientState);
+        updateSpeedBumpState(resultState, algorithmState, ambientState);
+        updateShelfState(resultState, ambientState);
+        getNotificationChildrenStates(resultState, algorithmState, ambientState);
+    }
+
+    private void getNotificationChildrenStates(StackScrollState resultState,
+            StackScrollAlgorithmState algorithmState,
+            AmbientState ambientState) {
+        int childCount = algorithmState.visibleChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            ExpandableView v = algorithmState.visibleChildren.get(i);
+            if (v instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+                row.getChildrenStates(resultState, ambientState);
+            }
+        }
+    }
+
+    private void updateSpeedBumpState(StackScrollState resultState,
+            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
+        int childCount = algorithmState.visibleChildren.size();
+        int belowSpeedBump = ambientState.getSpeedBumpIndex();
+        for (int i = 0; i < childCount; i++) {
+            View child = algorithmState.visibleChildren.get(i);
+            ExpandableViewState childViewState = resultState.getViewStateForView(child);
+
+            // The speed bump can also be gone, so equality needs to be taken when comparing
+            // indices.
+            childViewState.belowSpeedBump = i >= belowSpeedBump;
+        }
+
+    }
+    private void updateShelfState(StackScrollState resultState, AmbientState ambientState) {
+        NotificationShelf shelf = ambientState.getShelf();
+        if (shelf != null) {
+            shelf.updateState(resultState, ambientState);
+        }
+    }
+
+    private void updateClipping(StackScrollState resultState,
+            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
+        float drawStart = !ambientState.isOnKeyguard() ? ambientState.getTopPadding()
+                + ambientState.getStackTranslation() + ambientState.getExpandAnimationTopChange()
+                : 0;
+        float previousNotificationEnd = 0;
+        float previousNotificationStart = 0;
+        int childCount = algorithmState.visibleChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            ExpandableView child = algorithmState.visibleChildren.get(i);
+            ExpandableViewState state = resultState.getViewStateForView(child);
+            if (!child.mustStayOnScreen() || state.headsUpIsVisible) {
+                previousNotificationEnd = Math.max(drawStart, previousNotificationEnd);
+                previousNotificationStart = Math.max(drawStart, previousNotificationStart);
+            }
+            float newYTranslation = state.yTranslation;
+            float newHeight = state.height;
+            float newNotificationEnd = newYTranslation + newHeight;
+            boolean isHeadsUp = (child instanceof ExpandableNotificationRow)
+                    && ((ExpandableNotificationRow) child).isPinned();
+            if (mClipNotificationScrollToTop
+                    && !state.inShelf && newYTranslation < previousNotificationEnd
+                    && (!isHeadsUp || ambientState.isShadeExpanded())) {
+                // The previous view is overlapping on top, clip!
+                float overlapAmount = previousNotificationEnd - newYTranslation;
+                state.clipTopAmount = (int) overlapAmount;
+            } else {
+                state.clipTopAmount = 0;
+            }
+
+            if (!child.isTransparent()) {
+                // Only update the previous values if we are not transparent,
+                // otherwise we would clip to a transparent view.
+                previousNotificationEnd = newNotificationEnd;
+                previousNotificationStart = newYTranslation;
+            }
+        }
+    }
+
+    public static boolean canChildBeDismissed(View v) {
+        if (!(v instanceof ExpandableNotificationRow)) {
+            return false;
+        }
+        ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+        if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
+            return false;
+        }
+        return row.canViewBeDismissed();
+    }
+
+    /**
+     * Updates the dimmed, activated and hiding sensitive states of the children.
+     */
+    private void updateDimmedActivatedHideSensitive(AmbientState ambientState,
+            StackScrollState resultState, StackScrollAlgorithmState algorithmState) {
+        boolean dimmed = ambientState.isDimmed();
+        boolean dark = ambientState.isFullyDark();
+        boolean hideSensitive = ambientState.isHideSensitive();
+        View activatedChild = ambientState.getActivatedChild();
+        int childCount = algorithmState.visibleChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            View child = algorithmState.visibleChildren.get(i);
+            ExpandableViewState childViewState = resultState.getViewStateForView(child);
+            childViewState.dimmed = dimmed;
+            childViewState.dark = dark;
+            childViewState.hideSensitive = hideSensitive;
+            boolean isActivatedChild = activatedChild == child;
+            if (dimmed && isActivatedChild) {
+                childViewState.zTranslation += 2.0f * ambientState.getZDistanceBetweenElements();
+            }
+        }
+    }
+
+    /**
+     * Handle the special state when views are being dragged
+     */
+    private void handleDraggedViews(AmbientState ambientState, StackScrollState resultState,
+            StackScrollAlgorithmState algorithmState) {
+        ArrayList<View> draggedViews = ambientState.getDraggedViews();
+        for (View draggedView : draggedViews) {
+            int childIndex = algorithmState.visibleChildren.indexOf(draggedView);
+            if (childIndex >= 0 && childIndex < algorithmState.visibleChildren.size() - 1) {
+                View nextChild = algorithmState.visibleChildren.get(childIndex + 1);
+                if (!draggedViews.contains(nextChild)) {
+                    // only if the view is not dragged itself we modify its state to be fully
+                    // visible
+                    ExpandableViewState viewState = resultState.getViewStateForView(
+                            nextChild);
+                    // The child below the dragged one must be fully visible
+                    if (ambientState.isShadeExpanded()) {
+                        viewState.shadowAlpha = 1;
+                        viewState.hidden = false;
+                    }
+                }
+
+                // Lets set the alpha to the one it currently has, as its currently being dragged
+                ExpandableViewState viewState = resultState.getViewStateForView(draggedView);
+                // The dragged child should keep the set alpha
+                viewState.alpha = draggedView.getAlpha();
+            }
+        }
+    }
+
+    /**
+     * Initialize the algorithm state like updating the visible children.
+     */
+    private void initAlgorithmState(StackScrollState resultState, StackScrollAlgorithmState state,
+            AmbientState ambientState) {
+        float bottomOverScroll = ambientState.getOverScrollAmount(false /* onTop */);
+
+        int scrollY = ambientState.getScrollY();
+
+        // Due to the overScroller, the stackscroller can have negative scroll state. This is
+        // already accounted for by the top padding and doesn't need an additional adaption
+        scrollY = Math.max(0, scrollY);
+        state.scrollY = (int) (scrollY + bottomOverScroll);
+
+        //now init the visible children and update paddings
+        ViewGroup hostView = resultState.getHostView();
+        int childCount = hostView.getChildCount();
+        state.visibleChildren.clear();
+        state.visibleChildren.ensureCapacity(childCount);
+        state.paddingMap.clear();
+        int notGoneIndex = 0;
+        ExpandableView lastView = null;
+        int firstHiddenIndex = ambientState.isDark()
+                ? (ambientState.hasPulsingNotifications() ? 1 : 0)
+                : childCount;
+
+        // The goal here is to fill the padding map, by iterating over how much padding each child
+        // needs. The map is thereby reused, by first filling it with the padding amount and when
+        // iterating over it again, it's filled with the actual resolved value.
+
+        for (int i = 0; i < childCount; i++) {
+            ExpandableView v = (ExpandableView) hostView.getChildAt(i);
+            if (v.getVisibility() != View.GONE) {
+                if (v == ambientState.getShelf()) {
+                    continue;
+                }
+                if (i >= firstHiddenIndex) {
+                    // we need normal padding now, to be in sync with what the stack calculates
+                    lastView = null;
+                }
+                notGoneIndex = updateNotGoneIndex(resultState, state, notGoneIndex, v);
+                float increasedPadding = v.getIncreasedPaddingAmount();
+                if (increasedPadding != 0.0f) {
+                    state.paddingMap.put(v, increasedPadding);
+                    if (lastView != null) {
+                        Float prevValue = state.paddingMap.get(lastView);
+                        float newValue = getPaddingForValue(increasedPadding);
+                        if (prevValue != null) {
+                            float prevPadding = getPaddingForValue(prevValue);
+                            if (increasedPadding > 0) {
+                                newValue = NotificationUtils.interpolate(
+                                        prevPadding,
+                                        newValue,
+                                        increasedPadding);
+                            } else if (prevValue > 0) {
+                                newValue = NotificationUtils.interpolate(
+                                        newValue,
+                                        prevPadding,
+                                        prevValue);
+                            }
+                        }
+                        state.paddingMap.put(lastView, newValue);
+                    }
+                } else if (lastView != null) {
+
+                    // Let's now resolve the value to an actual padding
+                    float newValue = getPaddingForValue(state.paddingMap.get(lastView));
+                    state.paddingMap.put(lastView, newValue);
+                }
+                if (v instanceof ExpandableNotificationRow) {
+                    ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+
+                    // handle the notgoneIndex for the children as well
+                    List<ExpandableNotificationRow> children =
+                            row.getNotificationChildren();
+                    if (row.isSummaryWithChildren() && children != null) {
+                        for (ExpandableNotificationRow childRow : children) {
+                            if (childRow.getVisibility() != View.GONE) {
+                                ExpandableViewState childState
+                                        = resultState.getViewStateForView(childRow);
+                                childState.notGoneIndex = notGoneIndex;
+                                notGoneIndex++;
+                            }
+                        }
+                    }
+                }
+                lastView = v;
+            }
+        }
+        ExpandableNotificationRow expandingNotification = ambientState.getExpandingNotification();
+        state.indexOfExpandingNotification = expandingNotification != null
+                ? expandingNotification.isChildInGroup()
+                    ? state.visibleChildren.indexOf(expandingNotification.getNotificationParent())
+                    : state.visibleChildren.indexOf(expandingNotification)
+                : -1;
+    }
+
+    private float getPaddingForValue(Float increasedPadding) {
+        if (increasedPadding == null) {
+            return mPaddingBetweenElements;
+        } else if (increasedPadding >= 0.0f) {
+            return NotificationUtils.interpolate(
+                    mPaddingBetweenElements,
+                    mIncreasedPaddingBetweenElements,
+                    increasedPadding);
+        } else {
+            return NotificationUtils.interpolate(
+                    0,
+                    mPaddingBetweenElements,
+                    1.0f + increasedPadding);
+        }
+    }
+
+    private int updateNotGoneIndex(StackScrollState resultState,
+            StackScrollAlgorithmState state, int notGoneIndex,
+            ExpandableView v) {
+        ExpandableViewState viewState = resultState.getViewStateForView(v);
+        viewState.notGoneIndex = notGoneIndex;
+        state.visibleChildren.add(v);
+        notGoneIndex++;
+        return notGoneIndex;
+    }
+
+    /**
+     * Determine the positions for the views. This is the main part of the algorithm.
+     *
+     * @param resultState The result state to update if a change to the properties of a child occurs
+     * @param algorithmState The state in which the current pass of the algorithm is currently in
+     * @param ambientState The current ambient state
+     */
+    private void updatePositionsForState(StackScrollState resultState,
+            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
+
+        // The y coordinate of the current child.
+        float currentYPosition = -algorithmState.scrollY;
+        int childCount = algorithmState.visibleChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            currentYPosition = updateChild(i, resultState, algorithmState, ambientState,
+                    currentYPosition);
+        }
+    }
+
+    protected float updateChild(int i, StackScrollState resultState,
+            StackScrollAlgorithmState algorithmState, AmbientState ambientState,
+            float currentYPosition) {
+        ExpandableView child = algorithmState.visibleChildren.get(i);
+        ExpandableViewState childViewState = resultState.getViewStateForView(child);
+        childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
+        int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
+        int childHeight = getMaxAllowedChildHeight(child);
+        childViewState.yTranslation = currentYPosition;
+        boolean isFooterView = child instanceof FooterView;
+        boolean isEmptyShadeView = child instanceof EmptyShadeView;
+
+        childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
+        float inset = ambientState.getTopPadding() + ambientState.getStackTranslation();
+        if (i <= algorithmState.getIndexOfExpandingNotification()) {
+            inset += ambientState.getExpandAnimationTopChange();
+        }
+        if (child.mustStayOnScreen() && childViewState.yTranslation >= 0) {
+            // Even if we're not scrolled away we're in view and we're also not in the
+            // shelf. We can relax the constraints and let us scroll off the top!
+            float end = childViewState.yTranslation + childViewState.height + inset;
+            childViewState.headsUpIsVisible = end < ambientState.getMaxHeadsUpTranslation();
+        }
+        if (isFooterView) {
+            childViewState.yTranslation = Math.min(childViewState.yTranslation,
+                    ambientState.getInnerHeight() - childHeight);
+        } else if (isEmptyShadeView) {
+            childViewState.yTranslation = ambientState.getInnerHeight() - childHeight
+                    + ambientState.getStackTranslation() * 0.25f;
+        } else {
+            clampPositionToShelf(child, childViewState, ambientState);
+        }
+
+        currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
+        if (currentYPosition <= 0) {
+            childViewState.location = ExpandableViewState.LOCATION_HIDDEN_TOP;
+        }
+        if (childViewState.location == ExpandableViewState.LOCATION_UNKNOWN) {
+            Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
+        }
+
+        childViewState.yTranslation += inset;
+        return currentYPosition;
+    }
+
+    protected int getPaddingAfterChild(StackScrollAlgorithmState algorithmState,
+            ExpandableView child) {
+        return algorithmState.getPaddingAfterChild(child);
+    }
+
+    private void updateHeadsUpStates(StackScrollState resultState,
+            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
+        int childCount = algorithmState.visibleChildren.size();
+        ExpandableNotificationRow topHeadsUpEntry = null;
+        for (int i = 0; i < childCount; i++) {
+            View child = algorithmState.visibleChildren.get(i);
+            if (!(child instanceof ExpandableNotificationRow)) {
+                break;
+            }
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            if (!row.isHeadsUp()) {
+                break;
+            }
+            ExpandableViewState childState = resultState.getViewStateForView(row);
+            if (topHeadsUpEntry == null && row.mustStayOnScreen() && !childState.headsUpIsVisible) {
+                topHeadsUpEntry = row;
+                childState.location = ExpandableViewState.LOCATION_FIRST_HUN;
+            }
+            boolean isTopEntry = topHeadsUpEntry == row;
+            float unmodifiedEndLocation = childState.yTranslation + childState.height;
+            if (mIsExpanded) {
+                if (row.mustStayOnScreen() && !childState.headsUpIsVisible) {
+                    // Ensure that the heads up is always visible even when scrolled off
+                    clampHunToTop(ambientState, row, childState);
+                    if (i == 0 && ambientState.isAboveShelf(row)) {
+                        // the first hun can't get off screen.
+                        clampHunToMaxTranslation(ambientState, row, childState);
+                        childState.hidden = false;
+                    }
+                }
+            }
+            if (row.isPinned()) {
+                childState.yTranslation = Math.max(childState.yTranslation, mHeadsUpInset);
+                childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
+                childState.hidden = false;
+                ExpandableViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
+                if (topState != null && !isTopEntry && (!mIsExpanded
+                        || unmodifiedEndLocation < topState.yTranslation + topState.height)) {
+                    // Ensure that a headsUp doesn't vertically extend further than the heads-up at
+                    // the top most z-position
+                    childState.height = row.getIntrinsicHeight();
+                    childState.yTranslation = topState.yTranslation + topState.height
+                            - childState.height;
+                }
+
+                // heads up notification show and this row is the top entry of heads up
+                // notifications. i.e. this row should be the only one row that has input field
+                // To check if the row need to do translation according to scroll Y
+                // heads up show full of row's content and any scroll y indicate that the
+                // translationY need to move up the HUN.
+                if (!mIsExpanded && isTopEntry && ambientState.getScrollY() > 0) {
+                    childState.yTranslation -= ambientState.getScrollY();
+                }
+            }
+            if (row.isHeadsUpAnimatingAway()) {
+                childState.hidden = false;
+            }
+        }
+    }
+
+    private void clampHunToTop(AmbientState ambientState, ExpandableNotificationRow row,
+            ExpandableViewState childState) {
+        float newTranslation = Math.max(ambientState.getTopPadding()
+                + ambientState.getStackTranslation(), childState.yTranslation);
+        childState.height = (int) Math.max(childState.height - (newTranslation
+                - childState.yTranslation), row.getCollapsedHeight());
+        childState.yTranslation = newTranslation;
+    }
+
+    private void clampHunToMaxTranslation(AmbientState ambientState, ExpandableNotificationRow row,
+            ExpandableViewState childState) {
+        float newTranslation;
+        float maxHeadsUpTranslation = ambientState.getMaxHeadsUpTranslation();
+        float maxShelfPosition = ambientState.getInnerHeight() + ambientState.getTopPadding()
+                + ambientState.getStackTranslation();
+        maxHeadsUpTranslation = Math.min(maxHeadsUpTranslation, maxShelfPosition);
+        float bottomPosition = maxHeadsUpTranslation - row.getCollapsedHeight();
+        newTranslation = Math.min(childState.yTranslation, bottomPosition);
+        childState.height = (int) Math.min(childState.height, maxHeadsUpTranslation
+                - newTranslation);
+        childState.yTranslation = newTranslation;
+    }
+
+    /**
+     * Clamp the height of the child down such that its end is at most on the beginning of
+     * the shelf.
+     *
+     * @param child
+     * @param childViewState the view state of the child
+     * @param ambientState the ambient state
+     */
+    private void clampPositionToShelf(ExpandableView child,
+            ExpandableViewState childViewState,
+            AmbientState ambientState) {
+        if (ambientState.getShelf() == null) {
+            return;
+        }
+
+        int shelfStart = ambientState.getInnerHeight()
+                - ambientState.getShelf().getIntrinsicHeight();
+        if (ambientState.isAppearing() && !child.isAboveShelf()) {
+            // Don't show none heads-up notifications while in appearing phase.
+            childViewState.yTranslation = Math.max(childViewState.yTranslation, shelfStart);
+        }
+        childViewState.yTranslation = Math.min(childViewState.yTranslation, shelfStart);
+        if (childViewState.yTranslation >= shelfStart) {
+            childViewState.hidden = !child.isExpandAnimationRunning() && !child.hasExpandingChild();
+            childViewState.inShelf = true;
+            childViewState.headsUpIsVisible = false;
+        }
+    }
+
+    protected int getMaxAllowedChildHeight(View child) {
+        if (child instanceof ExpandableView) {
+            ExpandableView expandableView = (ExpandableView) child;
+            return expandableView.getIntrinsicHeight();
+        }
+        return child == null? mCollapsedSize : child.getHeight();
+    }
+
+    /**
+     * Calculate the Z positions for all children based on the number of items in both stacks and
+     * save it in the resultState
+     *  @param resultState The result state to update the zTranslation values
+     * @param algorithmState The state in which the current pass of the algorithm is currently in
+     * @param ambientState The ambient state of the algorithm
+     */
+    private void updateZValuesForState(StackScrollState resultState,
+            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
+        int childCount = algorithmState.visibleChildren.size();
+        float childrenOnTop = 0.0f;
+        for (int i = childCount - 1; i >= 0; i--) {
+            childrenOnTop = updateChildZValue(i, childrenOnTop,
+                    resultState, algorithmState, ambientState);
+        }
+    }
+
+    protected float updateChildZValue(int i, float childrenOnTop,
+            StackScrollState resultState, StackScrollAlgorithmState algorithmState,
+            AmbientState ambientState) {
+        ExpandableView child = algorithmState.visibleChildren.get(i);
+        ExpandableViewState childViewState = resultState.getViewStateForView(child);
+        int zDistanceBetweenElements = ambientState.getZDistanceBetweenElements();
+        float baseZ = ambientState.getBaseZHeight();
+        if (child.mustStayOnScreen() && !childViewState.headsUpIsVisible
+                && !ambientState.isDozingAndNotPulsing(child)
+                && childViewState.yTranslation < ambientState.getTopPadding()
+                + ambientState.getStackTranslation()) {
+            if (childrenOnTop != 0.0f) {
+                childrenOnTop++;
+            } else {
+                float overlap = ambientState.getTopPadding()
+                        + ambientState.getStackTranslation() - childViewState.yTranslation;
+                childrenOnTop += Math.min(1.0f, overlap / childViewState.height);
+            }
+            childViewState.zTranslation = baseZ
+                    + childrenOnTop * zDistanceBetweenElements;
+        } else if (i == 0 && ambientState.isAboveShelf(child)) {
+            // In case this is a new view that has never been measured before, we don't want to
+            // elevate if we are currently expanded more then the notification
+            int shelfHeight = ambientState.getShelf() == null ? 0 :
+                    ambientState.getShelf().getIntrinsicHeight();
+            float shelfStart = ambientState.getInnerHeight()
+                    - shelfHeight + ambientState.getTopPadding()
+                    + ambientState.getStackTranslation();
+            float notificationEnd = childViewState.yTranslation + child.getPinnedHeadsUpHeight()
+                    + mPaddingBetweenElements;
+            if (shelfStart > notificationEnd) {
+                childViewState.zTranslation = baseZ;
+            } else {
+                float factor = (notificationEnd - shelfStart) / shelfHeight;
+                factor = Math.min(factor, 1.0f);
+                childViewState.zTranslation = baseZ + factor * zDistanceBetweenElements;
+            }
+        } else {
+            childViewState.zTranslation = baseZ;
+        }
+
+        // We need to scrim the notification more from its surrounding content when we are pinned,
+        // and we therefore elevate it higher.
+        // We can use the headerVisibleAmount for this, since the value nicely goes from 0 to 1 when
+        // expanding after which we have a normal elevation again.
+        childViewState.zTranslation += (1.0f - child.getHeaderVisibleAmount())
+                * mPinnedZTranslationExtra;
+        return childrenOnTop;
+    }
+
+    public void setIsExpanded(boolean isExpanded) {
+        this.mIsExpanded = isExpanded;
+    }
+
+    public class StackScrollAlgorithmState {
+
+        /**
+         * The scroll position of the algorithm
+         */
+        public int scrollY;
+
+        /**
+         * The children from the host view which are not gone.
+         */
+        public final ArrayList<ExpandableView> visibleChildren = new ArrayList<ExpandableView>();
+
+        /**
+         * The padding after each child measured in pixels.
+         */
+        public final HashMap<ExpandableView, Float> paddingMap = new HashMap<>();
+        private int indexOfExpandingNotification;
+
+        public int getPaddingAfterChild(ExpandableView child) {
+            Float padding = paddingMap.get(child);
+            if (padding == null) {
+                // Should only happen for the last view
+                return mPaddingBetweenElements;
+            }
+            return (int) padding.floatValue();
+        }
+
+        public int getIndexOfExpandingNotification() {
+            return indexOfExpandingNotification;
+        }
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollState.java
new file mode 100644
index 0000000..c03fd22
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollState.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+
+import java.util.List;
+import java.util.WeakHashMap;
+
+/**
+ * A state of a
+ * {@link com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout} which
+ * can be applied to a viewGroup.
+ */
+public class StackScrollState {
+
+    private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
+
+    private final ViewGroup mHostView;
+    private WeakHashMap<ExpandableView, ExpandableViewState> mStateMap;
+
+    public StackScrollState(ViewGroup hostView) {
+        mHostView = hostView;
+        mStateMap = new WeakHashMap<>();
+    }
+
+    public ViewGroup getHostView() {
+        return mHostView;
+    }
+
+    public void resetViewStates() {
+        int numChildren = mHostView.getChildCount();
+        for (int i = 0; i < numChildren; i++) {
+            ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
+            resetViewState(child);
+
+            // handling reset for child notifications
+            if (child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                List<ExpandableNotificationRow> children =
+                        row.getNotificationChildren();
+                if (row.isSummaryWithChildren() && children != null) {
+                    for (ExpandableNotificationRow childRow : children) {
+                        resetViewState(childRow);
+                    }
+                }
+            }
+        }
+    }
+
+    private void resetViewState(ExpandableView view) {
+        ExpandableViewState viewState = mStateMap.get(view);
+        if (viewState == null) {
+            viewState = view.createNewViewState(this);
+            mStateMap.put(view, viewState);
+        }
+        // initialize with the default values of the view
+        viewState.height = view.getIntrinsicHeight();
+        viewState.gone = view.getVisibility() == View.GONE;
+        viewState.alpha = 1f;
+        viewState.shadowAlpha = 1f;
+        viewState.notGoneIndex = -1;
+        viewState.xTranslation = view.getTranslationX();
+        viewState.hidden = false;
+        viewState.scaleX = view.getScaleX();
+        viewState.scaleY = view.getScaleY();
+        viewState.inShelf = false;
+        viewState.headsUpIsVisible = false;
+    }
+
+    public ExpandableViewState getViewStateForView(View requestedView) {
+        return mStateMap.get(requestedView);
+    }
+
+    public void removeViewStateForView(View child) {
+        mStateMap.remove(child);
+    }
+
+    /**
+     * Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
+     * The properties are only applied if they effectively changed.
+     */
+    public void apply() {
+        int numChildren = mHostView.getChildCount();
+        for (int i = 0; i < numChildren; i++) {
+            ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
+            ExpandableViewState state = mStateMap.get(child);
+            if (state == null) {
+                Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
+                        "to the hostView");
+                continue;
+            }
+            if (state.gone) {
+                continue;
+            }
+            state.applyToView(child);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
new file mode 100644
index 0000000..da3fb66
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -0,0 +1,590 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.util.Property;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.keyguard.KeyguardSliceView;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.StatusBarIconView;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Stack;
+
+/**
+ * An stack state animator which handles animations to new StackScrollStates
+ */
+public class StackStateAnimator {
+
+    public static final int ANIMATION_DURATION_STANDARD = 360;
+    public static final int ANIMATION_DURATION_WAKEUP = 500;
+    public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448;
+    public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
+    public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;
+    public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150;
+    public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 550;
+    public static final int ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED
+            = (int) (ANIMATION_DURATION_HEADS_UP_APPEAR
+                    * HeadsUpAppearInterpolator.getFractionUntilOvershoot());
+    public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 300;
+    public static final int ANIMATION_DURATION_PULSE_APPEAR =
+            KeyguardSliceView.DEFAULT_ANIM_DURATION;
+    public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240;
+    public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;
+    public static final int ANIMATION_DELAY_PER_ELEMENT_MANUAL = 32;
+    public static final int ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE = 48;
+    public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
+    public static final int ANIMATION_DELAY_HEADS_UP = 120;
+    public static final int ANIMATION_DELAY_HEADS_UP_CLICKED= 120;
+
+    private final int mGoToFullShadeAppearingTranslation;
+    private final int mPulsingAppearingTranslation;
+    private final ExpandableViewState mTmpState = new ExpandableViewState();
+    private final AnimationProperties mAnimationProperties;
+    public NotificationStackScrollLayout mHostLayout;
+    private ArrayList<NotificationStackScrollLayout.AnimationEvent> mNewEvents =
+            new ArrayList<>();
+    private ArrayList<View> mNewAddChildren = new ArrayList<>();
+    private HashSet<View> mHeadsUpAppearChildren = new HashSet<>();
+    private HashSet<View> mHeadsUpDisappearChildren = new HashSet<>();
+    private HashSet<Animator> mAnimatorSet = new HashSet<>();
+    private Stack<AnimatorListenerAdapter> mAnimationListenerPool = new Stack<>();
+    private AnimationFilter mAnimationFilter = new AnimationFilter();
+    private long mCurrentLength;
+    private long mCurrentAdditionalDelay;
+
+    /** The current index for the last child which was not added in this event set. */
+    private int mCurrentLastNotAddedIndex;
+    private ValueAnimator mTopOverScrollAnimator;
+    private ValueAnimator mBottomOverScrollAnimator;
+    private int mHeadsUpAppearHeightBottom;
+    private boolean mShadeExpanded;
+    private ArrayList<ExpandableView> mTransientViewsToRemove = new ArrayList<>();
+    private NotificationShelf mShelf;
+    private float mStatusBarIconLocation;
+    private int[] mTmpLocation = new int[2];
+
+    public StackStateAnimator(NotificationStackScrollLayout hostLayout) {
+        mHostLayout = hostLayout;
+        mGoToFullShadeAppearingTranslation =
+                hostLayout.getContext().getResources().getDimensionPixelSize(
+                        R.dimen.go_to_full_shade_appearing_translation);
+        mPulsingAppearingTranslation =
+                hostLayout.getContext().getResources().getDimensionPixelSize(
+                        R.dimen.pulsing_notification_appear_translation);
+        mAnimationProperties = new AnimationProperties() {
+            @Override
+            public AnimationFilter getAnimationFilter() {
+                return mAnimationFilter;
+            }
+
+            @Override
+            public AnimatorListenerAdapter getAnimationFinishListener() {
+                return getGlobalAnimationFinishedListener();
+            }
+
+            @Override
+            public boolean wasAdded(View view) {
+                return mNewAddChildren.contains(view);
+            }
+
+            @Override
+            public Interpolator getCustomInterpolator(View child, Property property) {
+                if (mHeadsUpAppearChildren.contains(child) && View.TRANSLATION_Y.equals(property)) {
+                    return Interpolators.HEADS_UP_APPEAR;
+                }
+                return null;
+            }
+        };
+    }
+
+    public boolean isRunning() {
+        return !mAnimatorSet.isEmpty();
+    }
+
+    public void startAnimationForEvents(
+            ArrayList<NotificationStackScrollLayout.AnimationEvent> mAnimationEvents,
+            StackScrollState finalState, long additionalDelay) {
+
+        processAnimationEvents(mAnimationEvents, finalState);
+
+        int childCount = mHostLayout.getChildCount();
+        mAnimationFilter.applyCombination(mNewEvents);
+        mCurrentAdditionalDelay = additionalDelay;
+        mCurrentLength = NotificationStackScrollLayout.AnimationEvent.combineLength(mNewEvents);
+        mCurrentLastNotAddedIndex = findLastNotAddedIndex(finalState);
+        for (int i = 0; i < childCount; i++) {
+            final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
+
+            ExpandableViewState viewState = finalState.getViewStateForView(child);
+            if (viewState == null || child.getVisibility() == View.GONE
+                    || applyWithoutAnimation(child, viewState, finalState)) {
+                continue;
+            }
+
+            initAnimationProperties(finalState, child, viewState);
+            viewState.animateTo(child, mAnimationProperties);
+        }
+        if (!isRunning()) {
+            // no child has preformed any animation, lets finish
+            onAnimationFinished();
+        }
+        mHeadsUpAppearChildren.clear();
+        mHeadsUpDisappearChildren.clear();
+        mNewEvents.clear();
+        mNewAddChildren.clear();
+    }
+
+    private void initAnimationProperties(StackScrollState finalState, ExpandableView child,
+            ExpandableViewState viewState) {
+        boolean wasAdded = mAnimationProperties.wasAdded(child);
+        mAnimationProperties.duration = mCurrentLength;
+        adaptDurationWhenGoingToFullShade(child, viewState, wasAdded);
+        mAnimationProperties.delay = 0;
+        if (wasAdded || mAnimationFilter.hasDelays
+                        && (viewState.yTranslation != child.getTranslationY()
+                        || viewState.zTranslation != child.getTranslationZ()
+                        || viewState.alpha != child.getAlpha()
+                        || viewState.height != child.getActualHeight()
+                        || viewState.clipTopAmount != child.getClipTopAmount()
+                        || viewState.dark != child.isDark()
+                        || viewState.shadowAlpha != child.getShadowAlpha())) {
+            mAnimationProperties.delay = mCurrentAdditionalDelay
+                    + calculateChildAnimationDelay(viewState, finalState);
+        }
+    }
+
+    private void adaptDurationWhenGoingToFullShade(ExpandableView child,
+            ExpandableViewState viewState, boolean wasAdded) {
+        if (wasAdded && mAnimationFilter.hasGoToFullShadeEvent) {
+            child.setTranslationY(child.getTranslationY() + mGoToFullShadeAppearingTranslation);
+            float longerDurationFactor = viewState.notGoneIndex - mCurrentLastNotAddedIndex;
+            longerDurationFactor = (float) Math.pow(longerDurationFactor, 0.7f);
+            mAnimationProperties.duration = ANIMATION_DURATION_APPEAR_DISAPPEAR + 50 +
+                    (long) (100 * longerDurationFactor);
+        }
+    }
+
+    /**
+     * Determines if a view should not perform an animation and applies it directly.
+     *
+     * @return true if no animation should be performed
+     */
+    private boolean applyWithoutAnimation(ExpandableView child, ExpandableViewState viewState,
+            StackScrollState finalState) {
+        if (mShadeExpanded) {
+            return false;
+        }
+        if (ViewState.isAnimatingY(child)) {
+            // A Y translation animation is running
+            return false;
+        }
+        if (mHeadsUpDisappearChildren.contains(child) || mHeadsUpAppearChildren.contains(child)) {
+            // This is a heads up animation
+            return false;
+        }
+        if (NotificationStackScrollLayout.isPinnedHeadsUp(child)) {
+            // This is another headsUp which might move. Let's animate!
+            return false;
+        }
+        viewState.applyToView(child);
+        return true;
+    }
+
+    private int findLastNotAddedIndex(StackScrollState finalState) {
+        int childCount = mHostLayout.getChildCount();
+        for (int i = childCount - 1; i >= 0; i--) {
+            final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
+
+            ExpandableViewState viewState = finalState.getViewStateForView(child);
+            if (viewState == null || child.getVisibility() == View.GONE) {
+                continue;
+            }
+            if (!mNewAddChildren.contains(child)) {
+                return viewState.notGoneIndex;
+            }
+        }
+        return -1;
+    }
+
+    private long calculateChildAnimationDelay(ExpandableViewState viewState,
+            StackScrollState finalState) {
+        if (mAnimationFilter.hasGoToFullShadeEvent) {
+            return calculateDelayGoToFullShade(viewState);
+        }
+        if (mAnimationFilter.customDelay != AnimationFilter.NO_DELAY) {
+            return mAnimationFilter.customDelay;
+        }
+        long minDelay = 0;
+        for (NotificationStackScrollLayout.AnimationEvent event : mNewEvents) {
+            long delayPerElement = ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING;
+            switch (event.animationType) {
+                case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD: {
+                    int ownIndex = viewState.notGoneIndex;
+                    int changingIndex = finalState
+                            .getViewStateForView(event.changingView).notGoneIndex;
+                    int difference = Math.abs(ownIndex - changingIndex);
+                    difference = Math.max(0, Math.min(DELAY_EFFECT_MAX_INDEX_DIFFERENCE,
+                            difference - 1));
+                    long delay = (DELAY_EFFECT_MAX_INDEX_DIFFERENCE - difference) * delayPerElement;
+                    minDelay = Math.max(delay, minDelay);
+                    break;
+                }
+                case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT:
+                    delayPerElement = ANIMATION_DELAY_PER_ELEMENT_MANUAL;
+                case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE: {
+                    int ownIndex = viewState.notGoneIndex;
+                    boolean noNextView = event.viewAfterChangingView == null;
+                    View viewAfterChangingView = noNextView
+                            ? mHostLayout.getLastChildNotGone()
+                            : event.viewAfterChangingView;
+                    if (viewAfterChangingView == null) {
+                        // This can happen when the last view in the list is removed.
+                        // Since the shelf is still around and the only view, the code still goes
+                        // in here and tries to calculate the delay for it when case its properties
+                        // have changed.
+                        continue;
+                    }
+                    int nextIndex = finalState
+                            .getViewStateForView(viewAfterChangingView).notGoneIndex;
+                    if (ownIndex >= nextIndex) {
+                        // we only have the view afterwards
+                        ownIndex++;
+                    }
+                    int difference = Math.abs(ownIndex - nextIndex);
+                    difference = Math.max(0, Math.min(DELAY_EFFECT_MAX_INDEX_DIFFERENCE,
+                            difference - 1));
+                    long delay = difference * delayPerElement;
+                    minDelay = Math.max(delay, minDelay);
+                    break;
+                }
+                default:
+                    break;
+            }
+        }
+        return minDelay;
+    }
+
+    private long calculateDelayGoToFullShade(ExpandableViewState viewState) {
+        int shelfIndex = mShelf.getNotGoneIndex();
+        float index = viewState.notGoneIndex;
+        long result = 0;
+        if (index > shelfIndex) {
+            float diff = index - shelfIndex;
+            diff = (float) Math.pow(diff, 0.7f);
+            result += (long) (diff * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE * 0.25);
+            index = shelfIndex;
+        }
+        index = (float) Math.pow(index, 0.7f);
+        result += (long) (index * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE);
+        return result;
+    }
+
+    /**
+     * @return an adapter which ensures that onAnimationFinished is called once no animation is
+     *         running anymore
+     */
+    private AnimatorListenerAdapter getGlobalAnimationFinishedListener() {
+        if (!mAnimationListenerPool.empty()) {
+            return mAnimationListenerPool.pop();
+        }
+
+        // We need to create a new one, no reusable ones found
+        return new AnimatorListenerAdapter() {
+            private boolean mWasCancelled;
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mAnimatorSet.remove(animation);
+                if (mAnimatorSet.isEmpty() && !mWasCancelled) {
+                    onAnimationFinished();
+                }
+                mAnimationListenerPool.push(this);
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mWasCancelled = true;
+            }
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mWasCancelled = false;
+                mAnimatorSet.add(animation);
+            }
+        };
+    }
+
+    private void onAnimationFinished() {
+        mHostLayout.onChildAnimationFinished();
+
+        for (ExpandableView transientViewsToRemove : mTransientViewsToRemove) {
+            transientViewsToRemove.getTransientContainer()
+                    .removeTransientView(transientViewsToRemove);
+        }
+        mTransientViewsToRemove.clear();
+    }
+
+    /**
+     * Process the animationEvents for a new animation
+     *
+     * @param animationEvents the animation events for the animation to perform
+     * @param finalState the final state to animate to
+     */
+    private void processAnimationEvents(
+            ArrayList<NotificationStackScrollLayout.AnimationEvent> animationEvents,
+            StackScrollState finalState) {
+        for (NotificationStackScrollLayout.AnimationEvent event : animationEvents) {
+            final ExpandableView changingView = (ExpandableView) event.changingView;
+            if (event.animationType ==
+                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD) {
+
+                // This item is added, initialize it's properties.
+                ExpandableViewState viewState = finalState
+                        .getViewStateForView(changingView);
+                if (viewState == null || viewState.gone) {
+                    // The position for this child was never generated, let's continue.
+                    continue;
+                }
+                viewState.applyToView(changingView);
+                mNewAddChildren.add(changingView);
+
+            } else if (event.animationType ==
+                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE) {
+                if (changingView.getVisibility() != View.VISIBLE) {
+                    removeTransientView(changingView);
+                    continue;
+                }
+
+                // Find the amount to translate up. This is needed in order to understand the
+                // direction of the remove animation (either downwards or upwards)
+                ExpandableViewState viewState = finalState
+                        .getViewStateForView(event.viewAfterChangingView);
+                int actualHeight = changingView.getActualHeight();
+                // upwards by default
+                float translationDirection = -1.0f;
+                if (viewState != null) {
+                    float ownPosition = changingView.getTranslationY();
+                    if (changingView instanceof ExpandableNotificationRow
+                            && event.viewAfterChangingView instanceof ExpandableNotificationRow) {
+                        ExpandableNotificationRow changingRow =
+                                (ExpandableNotificationRow) changingView;
+                        ExpandableNotificationRow nextRow =
+                                (ExpandableNotificationRow) event.viewAfterChangingView;
+                        if (changingRow.isRemoved()
+                                && changingRow.wasChildInGroupWhenRemoved()
+                                && !nextRow.isChildInGroup()) {
+                            // the next row isn't actually a child from a group! Let's
+                            // compare absolute positions!
+                            ownPosition = changingRow.getTranslationWhenRemoved();
+                        }
+                    }
+                    // there was a view after this one, Approximate the distance the next child
+                    // travelled
+                    translationDirection = ((viewState.yTranslation
+                            - (ownPosition + actualHeight / 2.0f)) * 2 /
+                            actualHeight);
+                    translationDirection = Math.max(Math.min(translationDirection, 1.0f),-1.0f);
+
+                }
+                changingView.performRemoveAnimation(ANIMATION_DURATION_APPEAR_DISAPPEAR,
+                        0 /* delay */, translationDirection,  false /* isHeadsUpAppear */,
+                        0, new Runnable() {
+                    @Override
+                    public void run() {
+                        removeTransientView(changingView);
+                    }
+                }, null);
+            } else if (event.animationType ==
+                NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT) {
+                if (Math.abs(changingView.getTranslation()) == changingView.getWidth()
+                        && changingView.getTransientContainer() != null) {
+                    changingView.getTransientContainer().removeTransientView(changingView);
+                }
+            } else if (event.animationType == NotificationStackScrollLayout
+                    .AnimationEvent.ANIMATION_TYPE_GROUP_EXPANSION_CHANGED) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) event.changingView;
+                row.prepareExpansionChanged(finalState);
+            } else if (event.animationType == NotificationStackScrollLayout
+                    .AnimationEvent.ANIMATION_TYPE_PULSE_APPEAR) {
+                ExpandableViewState viewState = finalState.getViewStateForView(changingView);
+                if (viewState != null) {
+                    mTmpState.copyFrom(viewState);
+                    mTmpState.yTranslation += mPulsingAppearingTranslation;
+                    mTmpState.alpha = 0;
+                    mTmpState.applyToView(changingView);
+                }
+            } else if (event.animationType == NotificationStackScrollLayout
+                    .AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) {
+                ExpandableViewState viewState = finalState.getViewStateForView(changingView);
+                if (viewState != null) {
+                    viewState.alpha = 0;
+                    // We want to animate the alpha away before the view starts translating,
+                    // otherwise everything will overlap and look xtra ugly.
+                    float originalYTranslation = viewState.yTranslation;
+                    viewState.yTranslation = changingView.getTranslationY();
+                    mAnimationFilter.animateAlpha = true;
+                    mAnimationProperties.duration = ANIMATION_DURATION_PULSE_APPEAR / 2;
+                    viewState.animateTo(changingView, mAnimationProperties);
+                    viewState.yTranslation = originalYTranslation;
+                }
+            } else if (event.animationType == NotificationStackScrollLayout
+                    .AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR) {
+                // This item is added, initialize it's properties.
+                ExpandableViewState viewState = finalState.getViewStateForView(changingView);
+                mTmpState.copyFrom(viewState);
+                if (event.headsUpFromBottom) {
+                    mTmpState.yTranslation = mHeadsUpAppearHeightBottom;
+                } else {
+                    mTmpState.yTranslation = 0;
+                    changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED,
+                            true /* isHeadsUpAppear */);
+                }
+                mHeadsUpAppearChildren.add(changingView);
+                mTmpState.applyToView(changingView);
+            } else if (event.animationType == NotificationStackScrollLayout
+                            .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR ||
+                    event.animationType == NotificationStackScrollLayout
+                            .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
+                mHeadsUpDisappearChildren.add(changingView);
+                Runnable endRunnable = null;
+                // We need some additional delay in case we were removed to make sure we're not
+                // lagging
+                int extraDelay = event.animationType == NotificationStackScrollLayout
+                        .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+                        ? ANIMATION_DELAY_HEADS_UP_CLICKED
+                        : 0;
+                if (changingView.getParent() == null) {
+                    // This notification was actually removed, so we need to add it transiently
+                    mHostLayout.addTransientView(changingView, 0);
+                    changingView.setTransientContainer(mHostLayout);
+                    mTmpState.initFrom(changingView);
+                    mTmpState.yTranslation = 0;
+                    // We temporarily enable Y animations, the real filter will be combined
+                    // afterwards anyway
+                    mAnimationFilter.animateY = true;
+                    mAnimationProperties.delay = extraDelay + ANIMATION_DELAY_HEADS_UP;
+                    mAnimationProperties.duration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR;
+                    mTmpState.animateTo(changingView, mAnimationProperties);
+                    endRunnable = () -> removeTransientView(changingView);
+                }
+                float targetLocation = 0;
+                boolean needsAnimation = true;
+                if (changingView instanceof ExpandableNotificationRow) {
+                    ExpandableNotificationRow row = (ExpandableNotificationRow) changingView;
+                    if (row.isDismissed()) {
+                        needsAnimation = false;
+                    }
+                    StatusBarIconView icon = row.getEntry().icon;
+                    if (icon.getParent() != null) {
+                        icon.getLocationOnScreen(mTmpLocation);
+                        float iconPosition = mTmpLocation[0] - icon.getTranslationX()
+                                + ViewState.getFinalTranslationX(icon) + icon.getWidth() * 0.25f;
+                        mHostLayout.getLocationOnScreen(mTmpLocation);
+                        targetLocation = iconPosition - mTmpLocation[0];
+                    }
+                }
+
+                if (needsAnimation) {
+                    // We need to add the global animation listener, since once no animations are
+                    // running anymore, the panel will instantly hide itself. We need to wait until
+                    // the animation is fully finished for this though.
+                    changingView.performRemoveAnimation(ANIMATION_DURATION_HEADS_UP_DISAPPEAR
+                                    + ANIMATION_DELAY_HEADS_UP, extraDelay, 0.0f,
+                            true /* isHeadsUpAppear */, targetLocation, endRunnable,
+                            getGlobalAnimationFinishedListener());
+                } else if (endRunnable != null) {
+                    endRunnable.run();
+                }
+            }
+            mNewEvents.add(event);
+        }
+    }
+
+    public static void removeTransientView(ExpandableView viewToRemove) {
+        if (viewToRemove.getTransientContainer() != null) {
+            viewToRemove.getTransientContainer().removeTransientView(viewToRemove);
+        }
+    }
+
+    public void animateOverScrollToAmount(float targetAmount, final boolean onTop,
+            final boolean isRubberbanded) {
+        final float startOverScrollAmount = mHostLayout.getCurrentOverScrollAmount(onTop);
+        if (targetAmount == startOverScrollAmount) {
+            return;
+        }
+        cancelOverScrollAnimators(onTop);
+        ValueAnimator overScrollAnimator = ValueAnimator.ofFloat(startOverScrollAmount,
+                targetAmount);
+        overScrollAnimator.setDuration(ANIMATION_DURATION_STANDARD);
+        overScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float currentOverScroll = (float) animation.getAnimatedValue();
+                mHostLayout.setOverScrollAmount(
+                        currentOverScroll, onTop, false /* animate */, false /* cancelAnimators */,
+                        isRubberbanded);
+            }
+        });
+        overScrollAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        overScrollAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (onTop) {
+                    mTopOverScrollAnimator = null;
+                } else {
+                    mBottomOverScrollAnimator = null;
+                }
+            }
+        });
+        overScrollAnimator.start();
+        if (onTop) {
+            mTopOverScrollAnimator = overScrollAnimator;
+        } else {
+            mBottomOverScrollAnimator = overScrollAnimator;
+        }
+    }
+
+    public void cancelOverScrollAnimators(boolean onTop) {
+        ValueAnimator currentAnimator = onTop ? mTopOverScrollAnimator : mBottomOverScrollAnimator;
+        if (currentAnimator != null) {
+            currentAnimator.cancel();
+        }
+    }
+
+    public void setHeadsUpAppearHeightBottom(int headsUpAppearHeightBottom) {
+        mHeadsUpAppearHeightBottom = headsUpAppearHeightBottom;
+    }
+
+    public void setShadeExpanded(boolean shadeExpanded) {
+        mShadeExpanded = shadeExpanded;
+    }
+
+    public void setShelf(NotificationShelf shelf) {
+        mShelf = shelf;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
new file mode 100644
index 0000000..1f3244f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -0,0 +1,713 @@
+/*
+ * 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.systemui.statusbar.notification.stack;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.util.Property;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.AnimatableProperty;
+import com.android.systemui.statusbar.notification.PropertyAnimator;
+import com.android.systemui.statusbar.policy.HeadsUpUtil;
+
+/**
+ * A state of a view. This can be used to apply a set of view properties to a view with
+ * {@link com.android.systemui.statusbar.notification.stack.StackScrollState} or start
+ * animations with {@link com.android.systemui.statusbar.notification.stack.StackStateAnimator}.
+*/
+public class ViewState {
+
+    /**
+     * Some animation properties that can be used to update running animations but not creating
+     * any new ones.
+     */
+    protected static final AnimationProperties NO_NEW_ANIMATIONS = new AnimationProperties() {
+        AnimationFilter mAnimationFilter = new AnimationFilter();
+        @Override
+        public AnimationFilter getAnimationFilter() {
+            return mAnimationFilter;
+        }
+    };
+    private static final int TAG_ANIMATOR_TRANSLATION_X = R.id.translation_x_animator_tag;
+    private static final int TAG_ANIMATOR_TRANSLATION_Y = R.id.translation_y_animator_tag;
+    private static final int TAG_ANIMATOR_TRANSLATION_Z = R.id.translation_z_animator_tag;
+    private static final int TAG_ANIMATOR_ALPHA = R.id.alpha_animator_tag;
+    private static final int TAG_END_TRANSLATION_X = R.id.translation_x_animator_end_value_tag;
+    private static final int TAG_END_TRANSLATION_Y = R.id.translation_y_animator_end_value_tag;
+    private static final int TAG_END_TRANSLATION_Z = R.id.translation_z_animator_end_value_tag;
+    private static final int TAG_END_ALPHA = R.id.alpha_animator_end_value_tag;
+    private static final int TAG_START_TRANSLATION_X = R.id.translation_x_animator_start_value_tag;
+    private static final int TAG_START_TRANSLATION_Y = R.id.translation_y_animator_start_value_tag;
+    private static final int TAG_START_TRANSLATION_Z = R.id.translation_z_animator_start_value_tag;
+    private static final int TAG_START_ALPHA = R.id.alpha_animator_start_value_tag;
+
+    private static final AnimatableProperty SCALE_X_PROPERTY
+            = new AnimatableProperty() {
+
+        @Override
+        public int getAnimationStartTag() {
+            return R.id.scale_x_animator_start_value_tag;
+        }
+
+        @Override
+        public int getAnimationEndTag() {
+            return R.id.scale_x_animator_end_value_tag;
+        }
+
+        @Override
+        public int getAnimatorTag() {
+            return R.id.scale_x_animator_tag;
+        }
+
+        @Override
+        public Property getProperty() {
+            return View.SCALE_X;
+        }
+    };
+
+    private static final AnimatableProperty SCALE_Y_PROPERTY
+            = new AnimatableProperty() {
+
+        @Override
+        public int getAnimationStartTag() {
+            return R.id.scale_y_animator_start_value_tag;
+        }
+
+        @Override
+        public int getAnimationEndTag() {
+            return R.id.scale_y_animator_end_value_tag;
+        }
+
+        @Override
+        public int getAnimatorTag() {
+            return R.id.scale_y_animator_tag;
+        }
+
+        @Override
+        public Property getProperty() {
+            return View.SCALE_Y;
+        }
+    };
+
+    public float alpha;
+    public float xTranslation;
+    public float yTranslation;
+    public float zTranslation;
+    public boolean gone;
+    public boolean hidden;
+    public float scaleX = 1.0f;
+    public float scaleY = 1.0f;
+
+    public void copyFrom(ViewState viewState) {
+        alpha = viewState.alpha;
+        xTranslation = viewState.xTranslation;
+        yTranslation = viewState.yTranslation;
+        zTranslation = viewState.zTranslation;
+        gone = viewState.gone;
+        hidden = viewState.hidden;
+        scaleX = viewState.scaleX;
+        scaleY = viewState.scaleY;
+    }
+
+    public void initFrom(View view) {
+        alpha = view.getAlpha();
+        xTranslation = view.getTranslationX();
+        yTranslation = view.getTranslationY();
+        zTranslation = view.getTranslationZ();
+        gone = view.getVisibility() == View.GONE;
+        hidden = view.getVisibility() == View.INVISIBLE;
+        scaleX = view.getScaleX();
+        scaleY = view.getScaleY();
+    }
+
+    /**
+     * Applies a {@link ViewState} to a normal view.
+     */
+    public void applyToView(View view) {
+        if (this.gone) {
+            // don't do anything with it
+            return;
+        }
+
+        // apply xTranslation
+        boolean animatingX = isAnimating(view, TAG_ANIMATOR_TRANSLATION_X);
+        if (animatingX) {
+            updateAnimationX(view);
+        } else if (view.getTranslationX() != this.xTranslation){
+            view.setTranslationX(this.xTranslation);
+        }
+
+        // apply yTranslation
+        boolean animatingY = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y);
+        if (animatingY) {
+            updateAnimationY(view);
+        } else if (view.getTranslationY() != this.yTranslation) {
+            view.setTranslationY(this.yTranslation);
+        }
+
+        // apply zTranslation
+        boolean animatingZ = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Z);
+        if (animatingZ) {
+            updateAnimationZ(view);
+        } else if (view.getTranslationZ() != this.zTranslation) {
+            view.setTranslationZ(this.zTranslation);
+        }
+
+        // apply scaleX
+        boolean animatingScaleX = isAnimating(view, SCALE_X_PROPERTY);
+        if (animatingScaleX) {
+            updateAnimation(view, SCALE_X_PROPERTY, scaleX);
+        } else if (view.getScaleX() != scaleX) {
+            view.setScaleX(scaleX);
+        }
+
+        // apply scaleY
+        boolean animatingScaleY = isAnimating(view, SCALE_Y_PROPERTY);
+        if (animatingScaleY) {
+            updateAnimation(view, SCALE_Y_PROPERTY, scaleY);
+        } else if (view.getScaleY() != scaleY) {
+            view.setScaleY(scaleY);
+        }
+
+        int oldVisibility = view.getVisibility();
+        boolean becomesInvisible = this.alpha == 0.0f
+                || (this.hidden && (!isAnimating(view) || oldVisibility != View.VISIBLE));
+        boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
+        if (animatingAlpha) {
+            updateAlphaAnimation(view);
+        } else if (view.getAlpha() != this.alpha) {
+            // apply layer type
+            boolean becomesFullyVisible = this.alpha == 1.0f;
+            boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
+                    && view.hasOverlappingRendering();
+            int layerType = view.getLayerType();
+            int newLayerType = newLayerTypeIsHardware
+                    ? View.LAYER_TYPE_HARDWARE
+                    : View.LAYER_TYPE_NONE;
+            if (layerType != newLayerType) {
+                view.setLayerType(newLayerType, null);
+            }
+
+            // apply alpha
+            view.setAlpha(this.alpha);
+        }
+
+        // apply visibility
+        int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
+        if (newVisibility != oldVisibility) {
+            if (!(view instanceof ExpandableView) || !((ExpandableView) view).willBeGone()) {
+                // We don't want views to change visibility when they are animating to GONE
+                view.setVisibility(newVisibility);
+            }
+        }
+    }
+
+    public boolean isAnimating(View view) {
+        if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_X)) {
+            return true;
+        }
+        if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y)) {
+            return true;
+        }
+        if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Z)) {
+            return true;
+        }
+        if (isAnimating(view, TAG_ANIMATOR_ALPHA)) {
+            return true;
+        }
+        if (isAnimating(view, SCALE_X_PROPERTY)) {
+            return true;
+        }
+        if (isAnimating(view, SCALE_Y_PROPERTY)) {
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean isAnimating(View view, int tag) {
+        return getChildTag(view, tag) != null;
+    }
+
+    public static boolean isAnimating(View view, AnimatableProperty property) {
+        return getChildTag(view, property.getAnimatorTag()) != null;
+    }
+
+    /**
+     * Start an animation to this viewstate
+     * @param child the view to animate
+     * @param animationProperties the properties of the animation
+     */
+    public void animateTo(View child, AnimationProperties animationProperties) {
+        boolean wasVisible = child.getVisibility() == View.VISIBLE;
+        final float alpha = this.alpha;
+        if (!wasVisible && (alpha != 0 || child.getAlpha() != 0)
+                && !this.gone && !this.hidden) {
+            child.setVisibility(View.VISIBLE);
+        }
+        float childAlpha = child.getAlpha();
+        boolean alphaChanging = this.alpha != childAlpha;
+        if (child instanceof ExpandableView) {
+            // We don't want views to change visibility when they are animating to GONE
+            alphaChanging &= !((ExpandableView) child).willBeGone();
+        }
+
+        // start translationX animation
+        if (child.getTranslationX() != this.xTranslation) {
+            startXTranslationAnimation(child, animationProperties);
+        } else {
+            abortAnimation(child, TAG_ANIMATOR_TRANSLATION_X);
+        }
+
+        // start translationY animation
+        if (child.getTranslationY() != this.yTranslation) {
+            startYTranslationAnimation(child, animationProperties);
+        } else {
+            abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Y);
+        }
+
+        // start translationZ animation
+        if (child.getTranslationZ() != this.zTranslation) {
+            startZTranslationAnimation(child, animationProperties);
+        } else {
+            abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Z);
+        }
+
+        // start scaleX animation
+        if (child.getScaleX() != scaleX) {
+            PropertyAnimator.startAnimation(child, SCALE_X_PROPERTY, scaleX, animationProperties);
+        } else {
+            abortAnimation(child, SCALE_X_PROPERTY.getAnimatorTag());
+        }
+
+        // start scaleX animation
+        if (child.getScaleY() != scaleY) {
+            PropertyAnimator.startAnimation(child, SCALE_Y_PROPERTY, scaleY, animationProperties);
+        } else {
+            abortAnimation(child, SCALE_Y_PROPERTY.getAnimatorTag());
+        }
+
+        // start alpha animation
+        if (alphaChanging) {
+            startAlphaAnimation(child, animationProperties);
+        }  else {
+            abortAnimation(child, TAG_ANIMATOR_ALPHA);
+        }
+    }
+
+    private void updateAlphaAnimation(View view) {
+        startAlphaAnimation(view, NO_NEW_ANIMATIONS);
+    }
+
+    private void startAlphaAnimation(final View child, AnimationProperties properties) {
+        Float previousStartValue = getChildTag(child,TAG_START_ALPHA);
+        Float previousEndValue = getChildTag(child,TAG_END_ALPHA);
+        final float newEndValue = this.alpha;
+        if (previousEndValue != null && previousEndValue == newEndValue) {
+            return;
+        }
+        ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_ALPHA);
+        AnimationFilter filter = properties.getAnimationFilter();
+        if (!filter.animateAlpha) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                float relativeDiff = newEndValue - previousEndValue;
+                float newStartValue = previousStartValue + relativeDiff;
+                values[0].setFloatValues(newStartValue, newEndValue);
+                child.setTag(TAG_START_ALPHA, newStartValue);
+                child.setTag(TAG_END_ALPHA, newEndValue);
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                child.setAlpha(newEndValue);
+                if (newEndValue == 0) {
+                    child.setVisibility(View.INVISIBLE);
+                }
+            }
+        }
+
+        ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.ALPHA,
+                child.getAlpha(), newEndValue);
+        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        // Handle layer type
+        child.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+        animator.addListener(new AnimatorListenerAdapter() {
+            public boolean mWasCancelled;
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                child.setLayerType(View.LAYER_TYPE_NONE, null);
+                if (newEndValue == 0 && !mWasCancelled) {
+                    child.setVisibility(View.INVISIBLE);
+                }
+                // remove the tag when the animation is finished
+                child.setTag(TAG_ANIMATOR_ALPHA, null);
+                child.setTag(TAG_START_ALPHA, null);
+                child.setTag(TAG_END_ALPHA, null);
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mWasCancelled = true;
+            }
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mWasCancelled = false;
+            }
+        });
+        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
+        animator.setDuration(newDuration);
+        if (properties.delay > 0 && (previousAnimator == null
+                || previousAnimator.getAnimatedFraction() == 0)) {
+            animator.setStartDelay(properties.delay);
+        }
+        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
+        if (listener != null) {
+            animator.addListener(listener);
+        }
+
+        startAnimator(animator, listener);
+        child.setTag(TAG_ANIMATOR_ALPHA, animator);
+        child.setTag(TAG_START_ALPHA, child.getAlpha());
+        child.setTag(TAG_END_ALPHA, newEndValue);
+    }
+
+    private void updateAnimationZ(View view) {
+        startZTranslationAnimation(view, NO_NEW_ANIMATIONS);
+    }
+
+    private void updateAnimation(View view, AnimatableProperty property,
+            float endValue) {
+        PropertyAnimator.startAnimation(view, property, endValue, NO_NEW_ANIMATIONS);
+    }
+
+    private void startZTranslationAnimation(final View child, AnimationProperties properties) {
+        Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Z);
+        Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Z);
+        float newEndValue = this.zTranslation;
+        if (previousEndValue != null && previousEndValue == newEndValue) {
+            return;
+        }
+        ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Z);
+        AnimationFilter filter = properties.getAnimationFilter();
+        if (!filter.animateZ) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                float relativeDiff = newEndValue - previousEndValue;
+                float newStartValue = previousStartValue + relativeDiff;
+                values[0].setFloatValues(newStartValue, newEndValue);
+                child.setTag(TAG_START_TRANSLATION_Z, newStartValue);
+                child.setTag(TAG_END_TRANSLATION_Z, newEndValue);
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                child.setTranslationZ(newEndValue);
+            }
+        }
+
+        ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Z,
+                child.getTranslationZ(), newEndValue);
+        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
+        animator.setDuration(newDuration);
+        if (properties.delay > 0 && (previousAnimator == null
+                || previousAnimator.getAnimatedFraction() == 0)) {
+            animator.setStartDelay(properties.delay);
+        }
+        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
+        if (listener != null) {
+            animator.addListener(listener);
+        }
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                child.setTag(TAG_ANIMATOR_TRANSLATION_Z, null);
+                child.setTag(TAG_START_TRANSLATION_Z, null);
+                child.setTag(TAG_END_TRANSLATION_Z, null);
+            }
+        });
+        startAnimator(animator, listener);
+        child.setTag(TAG_ANIMATOR_TRANSLATION_Z, animator);
+        child.setTag(TAG_START_TRANSLATION_Z, child.getTranslationZ());
+        child.setTag(TAG_END_TRANSLATION_Z, newEndValue);
+    }
+
+    private void updateAnimationX(View view) {
+        startXTranslationAnimation(view, NO_NEW_ANIMATIONS);
+    }
+
+    private void startXTranslationAnimation(final View child, AnimationProperties properties) {
+        Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_X);
+        Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_X);
+        float newEndValue = this.xTranslation;
+        if (previousEndValue != null && previousEndValue == newEndValue) {
+            return;
+        }
+        ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_X);
+        AnimationFilter filter = properties.getAnimationFilter();
+        if (!filter.animateX) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                float relativeDiff = newEndValue - previousEndValue;
+                float newStartValue = previousStartValue + relativeDiff;
+                values[0].setFloatValues(newStartValue, newEndValue);
+                child.setTag(TAG_START_TRANSLATION_X, newStartValue);
+                child.setTag(TAG_END_TRANSLATION_X, newEndValue);
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                child.setTranslationX(newEndValue);
+                return;
+            }
+        }
+
+        ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_X,
+                child.getTranslationX(), newEndValue);
+        Interpolator customInterpolator = properties.getCustomInterpolator(child,
+                View.TRANSLATION_X);
+        Interpolator interpolator =  customInterpolator != null ? customInterpolator
+                : Interpolators.FAST_OUT_SLOW_IN;
+        animator.setInterpolator(interpolator);
+        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
+        animator.setDuration(newDuration);
+        if (properties.delay > 0 && (previousAnimator == null
+                || previousAnimator.getAnimatedFraction() == 0)) {
+            animator.setStartDelay(properties.delay);
+        }
+        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
+        if (listener != null) {
+            animator.addListener(listener);
+        }
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                child.setTag(TAG_ANIMATOR_TRANSLATION_X, null);
+                child.setTag(TAG_START_TRANSLATION_X, null);
+                child.setTag(TAG_END_TRANSLATION_X, null);
+            }
+        });
+        startAnimator(animator, listener);
+        child.setTag(TAG_ANIMATOR_TRANSLATION_X, animator);
+        child.setTag(TAG_START_TRANSLATION_X, child.getTranslationX());
+        child.setTag(TAG_END_TRANSLATION_X, newEndValue);
+    }
+
+    private void updateAnimationY(View view) {
+        startYTranslationAnimation(view, NO_NEW_ANIMATIONS);
+    }
+
+    private void startYTranslationAnimation(final View child, AnimationProperties properties) {
+        Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Y);
+        Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Y);
+        float newEndValue = this.yTranslation;
+        if (previousEndValue != null && previousEndValue == newEndValue) {
+            return;
+        }
+        ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y);
+        AnimationFilter filter = properties.getAnimationFilter();
+        if (!filter.shouldAnimateY(child)) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                float relativeDiff = newEndValue - previousEndValue;
+                float newStartValue = previousStartValue + relativeDiff;
+                values[0].setFloatValues(newStartValue, newEndValue);
+                child.setTag(TAG_START_TRANSLATION_Y, newStartValue);
+                child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                child.setTranslationY(newEndValue);
+                return;
+            }
+        }
+
+        ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Y,
+                child.getTranslationY(), newEndValue);
+        Interpolator customInterpolator = properties.getCustomInterpolator(child,
+                View.TRANSLATION_Y);
+        Interpolator interpolator =  customInterpolator != null ? customInterpolator
+                : Interpolators.FAST_OUT_SLOW_IN;
+        animator.setInterpolator(interpolator);
+        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
+        animator.setDuration(newDuration);
+        if (properties.delay > 0 && (previousAnimator == null
+                || previousAnimator.getAnimatedFraction() == 0)) {
+            animator.setStartDelay(properties.delay);
+        }
+        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
+        if (listener != null) {
+            animator.addListener(listener);
+        }
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                HeadsUpUtil.setIsClickedHeadsUpNotification(child, false);
+                child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
+                child.setTag(TAG_START_TRANSLATION_Y, null);
+                child.setTag(TAG_END_TRANSLATION_Y, null);
+                onYTranslationAnimationFinished(child);
+            }
+        });
+        startAnimator(animator, listener);
+        child.setTag(TAG_ANIMATOR_TRANSLATION_Y, animator);
+        child.setTag(TAG_START_TRANSLATION_Y, child.getTranslationY());
+        child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
+    }
+
+    protected void onYTranslationAnimationFinished(View view) {
+        if (hidden && !gone) {
+            view.setVisibility(View.INVISIBLE);
+        }
+    }
+
+    public static void startAnimator(Animator animator, AnimatorListenerAdapter listener) {
+        if (listener != null) {
+            // Even if there's a delay we'd want to notify it of the start immediately.
+            listener.onAnimationStart(animator);
+        }
+        animator.start();
+    }
+
+    public static <T> T getChildTag(View child, int tag) {
+        return (T) child.getTag(tag);
+    }
+
+    protected void abortAnimation(View child, int animatorTag) {
+        Animator previousAnimator = getChildTag(child, animatorTag);
+        if (previousAnimator != null) {
+            previousAnimator.cancel();
+        }
+    }
+
+    /**
+     * Cancel the previous animator and get the duration of the new animation.
+     *
+     * @param duration the new duration
+     * @param previousAnimator the animator which was running before
+     * @return the new duration
+     */
+    public static long cancelAnimatorAndGetNewDuration(long duration,
+            ValueAnimator previousAnimator) {
+        long newDuration = duration;
+        if (previousAnimator != null) {
+            // We take either the desired length of the new animation or the remaining time of
+            // the previous animator, whichever is longer.
+            newDuration = Math.max(previousAnimator.getDuration()
+                    - previousAnimator.getCurrentPlayTime(), newDuration);
+            previousAnimator.cancel();
+        }
+        return newDuration;
+    }
+
+    /**
+     * Get the end value of the xTranslation animation running on a view or the xTranslation
+     * if no animation is running.
+     */
+    public static float getFinalTranslationX(View view) {
+        if (view == null) {
+            return 0;
+        }
+        ValueAnimator xAnimator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_X);
+        if (xAnimator == null) {
+            return view.getTranslationX();
+        } else {
+            return getChildTag(view, TAG_END_TRANSLATION_X);
+        }
+    }
+
+    /**
+     * Get the end value of the yTranslation animation running on a view or the yTranslation
+     * if no animation is running.
+     */
+    public static float getFinalTranslationY(View view) {
+        if (view == null) {
+            return 0;
+        }
+        ValueAnimator yAnimator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Y);
+        if (yAnimator == null) {
+            return view.getTranslationY();
+        } else {
+            return getChildTag(view, TAG_END_TRANSLATION_Y);
+        }
+    }
+
+    /**
+     * Get the end value of the zTranslation animation running on a view or the zTranslation
+     * if no animation is running.
+     */
+    public static float getFinalTranslationZ(View view) {
+        if (view == null) {
+            return 0;
+        }
+        ValueAnimator zAnimator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Z);
+        if (zAnimator == null) {
+            return view.getTranslationZ();
+        } else {
+            return getChildTag(view, TAG_END_TRANSLATION_Z);
+        }
+    }
+
+    public static boolean isAnimatingY(View child) {
+        return getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y) != null;
+    }
+
+    public void cancelAnimations(View view) {
+        Animator animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_X);
+        if (animator != null) {
+            animator.cancel();
+        }
+        animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Y);
+        if (animator != null) {
+            animator.cancel();
+        }
+        animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Z);
+        if (animator != null) {
+            animator.cancel();
+        }
+        animator = getChildTag(view, TAG_ANIMATOR_ALPHA);
+        if (animator != null) {
+            animator.cancel();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 446a1d4..ab58660 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -96,6 +96,10 @@
         Dependency.get(ColorDisplayController.class).setListener(null);
     }
 
+    public void unmarkTileAsAutoAdded(String tabSpec) {
+        mAutoTracker.setTileRemoved(tabSpec);
+    }
+
     private final ManagedProfileController.Callback mProfileCallback =
             new ManagedProfileController.Callback() {
                 @Override
@@ -104,8 +108,6 @@
                     if (Dependency.get(ManagedProfileController.class).hasActiveProfile()) {
                         mHost.addTile(WORK);
                         mAutoTracker.setTileAdded(WORK);
-                        mHandler.post(() -> Dependency.get(ManagedProfileController.class)
-                                .removeCallback(mProfileCallback));
                     }
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 0b6fd13..b57a366 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -101,7 +101,7 @@
     private KeyguardUpdateMonitor mUpdateMonitor;
     private int mMode;
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    private StatusBarWindowManager mStatusBarWindowManager;
+    private StatusBarWindowController mStatusBarWindowController;
     private DozeScrimController mDozeScrimController;
     private KeyguardViewMediator mKeyguardViewMediator;
     private ScrimController mScrimController;
@@ -125,7 +125,7 @@
         mUpdateMonitor.registerCallback(this);
         Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
         Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver);
-        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
+        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         mDozeScrimController = dozeScrimController;
         mKeyguardViewMediator = keyguardViewMediator;
         mScrimController = scrimController;
@@ -214,17 +214,30 @@
             // notifications would light up first, creating an unpleasant animation.
             // Defer changing the screen brightness by forcing doze brightness on our window
             // until the clock and the notifications are faded out.
-            mStatusBarWindowManager.setForceDozeBrightness(true);
+            mStatusBarWindowController.setForceDozeBrightness(true);
         }
-        if (!wasDeviceInteractive) {
-            if (DEBUG_BIO_WAKELOCK) {
-                Log.i(TAG, "bio wakelock: Authenticated, waking up...");
+        // During wake and unlock, we need to draw black before waking up to avoid abrupt
+        // brightness changes due to display state transitions.
+        boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn();
+        boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled;
+        Runnable wakeUp = ()-> {
+            if (!wasDeviceInteractive) {
+                if (DEBUG_BIO_WAKELOCK) {
+                    Log.i(TAG, "bio wakelock: Authenticated, waking up...");
+                }
+                mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:BIOMETRIC");
             }
-            mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:BIOMETRIC");
+            if (delayWakeUp) {
+                mKeyguardViewMediator.onWakeAndUnlocking();
+            }
+            Trace.beginSection("release wake-and-unlock");
+            releaseBiometricWakeLock();
+            Trace.endSection();
+        };
+
+        if (!delayWakeUp) {
+            wakeUp.run();
         }
-        Trace.beginSection("release wake-and-unlock");
-        releaseBiometricWakeLock();
-        Trace.endSection();
         switch (mMode) {
             case MODE_DISMISS_BOUNCER:
                 Trace.beginSection("MODE_DISMISS");
@@ -256,8 +269,12 @@
                     Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
                     mUpdateMonitor.awakenFromDream();
                 }
-                mStatusBarWindowManager.setStatusBarFocusable(false);
-                mKeyguardViewMediator.onWakeAndUnlocking();
+                mStatusBarWindowController.setStatusBarFocusable(false);
+                if (delayWakeUp) {
+                    mHandler.postDelayed(wakeUp, 50);
+                } else {
+                    mKeyguardViewMediator.onWakeAndUnlocking();
+                }
                 if (mStatusBar.getNavigationBarView() != null) {
                     mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
                 }
@@ -367,7 +384,7 @@
         mHandler.postDelayed(new Runnable() {
             @Override
             public void run() {
-                mStatusBarWindowManager.setForceDozeBrightness(false);
+                mStatusBarWindowController.setForceDozeBrightness(false);
             }
         }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
     }
@@ -378,7 +395,7 @@
 
     private void resetMode() {
         mMode = MODE_NONE;
-        mStatusBarWindowManager.setForceDozeBrightness(false);
+        mStatusBarWindowController.setForceDozeBrightness(false);
         if (mStatusBar.getNavigationBarView() != null) {
             mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 894ea62..587b40d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -134,6 +134,9 @@
                 ((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable);
             }
         }
+        if (mImageDrawable != null) {
+            mImageDrawable.setCallback(mCurrentView);
+        }
     }
 
     public void setVisibility(int visibility) {
@@ -160,12 +163,16 @@
     }
 
     public void setAlpha(float alpha, boolean animate) {
+        setAlpha(alpha, animate, (getAlpha() < alpha) ? FADE_DURATION_IN : FADE_DURATION_OUT);
+    }
+
+    public void setAlpha(float alpha, boolean animate, long duration) {
         if (animate) {
             if (mFadeAnimator != null) {
                 mFadeAnimator.cancel();
             }
             mFadeAnimator = ValueAnimator.ofFloat(getAlpha(), alpha);
-            mFadeAnimator.setDuration(getAlpha() < alpha? FADE_DURATION_IN : FADE_DURATION_OUT);
+            mFadeAnimator.setDuration(duration);
             mFadeAnimator.setInterpolator(getAlpha() < alpha ? ALPHA_IN : ALPHA_OUT);
             mFadeAnimator.addListener(mFadeListener);
             mFadeAnimator.addUpdateListener(mAlphaListener);
@@ -266,6 +273,9 @@
 
     public void setCurrentView(View currentView) {
         mCurrentView = currentView.findViewById(mId);
+        if (mImageDrawable != null) {
+            mImageDrawable.setCallback(mCurrentView);
+        }
     }
 
     public void setVertical(boolean vertical) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index ea70ebb..a781be6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -189,6 +189,14 @@
             state |= DISABLE_SYSTEM_INFO;
             state |= DISABLE_CLOCK;
         }
+
+        // In landscape, the heads up show but shouldHideNotificationIcons() return false
+        // because the visual icon is in notification icon area rather than heads up's space.
+        // whether the notification icon show or not, clock should hide when heads up show.
+        if (mStatusBarComponent.isHeadsUpShouldBeVisible()) {
+            state |= DISABLE_CLOCK;
+        }
+
         if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
             if (mNetworkController.hasEmergencyCryptKeeperText()) {
                 state |= DISABLE_NOTIFICATION_ICONS;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
deleted file mode 100644
index 6f53844..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.content.om.IOverlayManager;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.os.LocaleList;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-
-import com.android.systemui.ConfigurationChangedReceiver;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-public class ConfigurationControllerImpl implements ConfigurationController,
-        ConfigurationChangedReceiver {
-
-    private final ArrayList<ConfigurationListener> mListeners = new ArrayList<>();
-    private final Configuration mLastConfig = new Configuration();
-    private int mDensity;
-    private float mFontScale;
-    private boolean mInCarMode;
-    private int mUiMode;
-    private LocaleList mLocaleList;
-
-    public ConfigurationControllerImpl(Context context) {
-        Configuration currentConfig = context.getResources().getConfiguration();
-        mFontScale = currentConfig.fontScale;
-        mDensity = currentConfig.densityDpi;
-        mInCarMode = (currentConfig.uiMode  & Configuration.UI_MODE_TYPE_MASK)
-                == Configuration.UI_MODE_TYPE_CAR;
-        mUiMode = currentConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
-        mLocaleList = currentConfig.getLocales();
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        // Avoid concurrent modification exception
-        ArrayList<ConfigurationListener> listeners = new ArrayList<>(mListeners);
-
-        listeners.forEach(l -> {
-            if (mListeners.contains(l)) {
-                l.onConfigChanged(newConfig);
-            }
-        });
-        final float fontScale = newConfig.fontScale;
-        final int density = newConfig.densityDpi;
-        int uiMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
-        if (density != mDensity || fontScale != mFontScale
-                || (mInCarMode && uiMode != mUiMode)) {
-            listeners.forEach(l -> {
-                if (mListeners.contains(l)) {
-                    l.onDensityOrFontScaleChanged();
-                }
-            });
-            mDensity = density;
-            mFontScale = fontScale;
-            mUiMode = uiMode;
-        }
-
-        final LocaleList localeList = newConfig.getLocales();
-        if (!localeList.equals(mLocaleList)) {
-            mLocaleList = localeList;
-            listeners.forEach(l -> {
-                if (mListeners.contains(l)) {
-                    l.onLocaleListChanged();
-                }
-            });
-        }
-
-        if ((mLastConfig.updateFrom(newConfig) & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
-                listeners.forEach(l -> {
-                    if (mListeners.contains(l)) {
-                        l.onOverlayChanged();
-                    }
-                });
-        }
-    }
-
-    @Override
-    public void addCallback(ConfigurationListener listener) {
-        mListeners.add(listener);
-        listener.onDensityOrFontScaleChanged();
-    }
-
-    @Override
-    public void removeCallback(ConfigurationListener listener) {
-        mListeners.remove(listener);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
new file mode 100644
index 0000000..81b596c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.content.Context
+import android.content.pm.ActivityInfo
+import android.content.res.Configuration
+import android.os.LocaleList
+
+import com.android.systemui.ConfigurationChangedReceiver
+import com.android.systemui.statusbar.policy.ConfigurationController
+
+import java.util.ArrayList
+
+class ConfigurationControllerImpl(context: Context)
+    : ConfigurationController, ConfigurationChangedReceiver {
+
+    private val listeners: MutableList<ConfigurationController.ConfigurationListener> = ArrayList()
+    private val lastConfig = Configuration()
+    private var density: Int = 0
+    private var fontScale: Float = 0.toFloat()
+    private val inCarMode: Boolean
+    private var uiMode: Int = 0
+    private var localeList: LocaleList? = null
+
+    init {
+        val currentConfig = context.resources.configuration
+        fontScale = currentConfig.fontScale
+        density = currentConfig.densityDpi
+        inCarMode = currentConfig.uiMode and Configuration.UI_MODE_TYPE_MASK ==
+                Configuration.UI_MODE_TYPE_CAR
+        uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
+        localeList = currentConfig.locales
+    }
+
+    override fun notifyThemeChanged() {
+        val listeners = ArrayList(listeners)
+
+        listeners.filterForEach({ this.listeners.contains(it) }) {
+            it.onThemeChanged()
+        }
+    }
+
+    override fun onConfigurationChanged(newConfig: Configuration) {
+        // Avoid concurrent modification exception
+        val listeners = ArrayList(listeners)
+
+        listeners.filterForEach({ this.listeners.contains(it) }) {
+            it.onConfigChanged(newConfig)
+        }
+        val fontScale = newConfig.fontScale
+        val density = newConfig.densityDpi
+        val uiMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
+        val uiModeChanged = uiMode != this.uiMode
+        if (density != this.density || fontScale != this.fontScale ||
+                inCarMode && uiModeChanged) {
+            listeners.filterForEach({ this.listeners.contains(it) }) {
+                it.onDensityOrFontScaleChanged()
+            }
+            this.density = density
+            this.fontScale = fontScale
+        }
+
+        val localeList = newConfig.locales
+        if (localeList != this.localeList) {
+            this.localeList = localeList
+            listeners.filterForEach({ this.listeners.contains(it) }) {
+                it.onLocaleListChanged()
+            }
+        }
+
+        if (uiModeChanged) {
+            this.uiMode = uiMode
+            listeners.filterForEach({ this.listeners.contains(it) }) {
+                it.onUiModeChanged()
+            }
+        }
+
+        if (lastConfig.updateFrom(newConfig) and ActivityInfo.CONFIG_ASSETS_PATHS != 0) {
+            listeners.filterForEach({ this.listeners.contains(it) }) {
+                it.onOverlayChanged()
+            }
+        }
+    }
+
+    override fun addCallback(listener: ConfigurationController.ConfigurationListener) {
+        listeners.add(listener)
+        listener.onDensityOrFontScaleChanged()
+    }
+
+    override fun removeCallback(listener: ConfigurationController.ConfigurationListener) {
+        listeners.remove(listener)
+    }
+}
+
+// This could be done with a Collection.filter and Collection.forEach, but Collection.filter
+// creates a new array to store them in and we really don't need that here, so this provides
+// a little more optimized inline version.
+inline fun <T> Collection<T>.filterForEach(f: (T) -> Boolean, execute: (T) -> Unit) {
+    forEach {
+        if (f.invoke(it)) {
+            execute.invoke(it)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 8f552e3..92a9efe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -40,6 +40,8 @@
     public static final String DOZE_SENSORS_WAKE_UP_FULLY = "doze_sensors_wake_up_fully";
     public static final boolean FORCE_NO_BLANKING =
             SystemProperties.getBoolean("debug.force_no_blanking", false);
+    public static final boolean FORCE_BLANKING =
+            SystemProperties.getBoolean("debug.force_blanking", false);
 
     private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
     private static DozeParameters sInstance;
@@ -183,7 +185,7 @@
      * @return {@code true} if screen needs to be completely black before a power transition.
      */
     public boolean getDisplayNeedsBlanking() {
-        return !FORCE_NO_BLANKING && mContext.getResources().getBoolean(
+        return FORCE_BLANKING || !FORCE_NO_BLANKING && mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_displayBlanksAfterDoze);
     }
 
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 e1936fa..9acaf21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -26,12 +26,12 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.HeadsUpStatusBarView;
-import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 0a26e73..6150c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -22,7 +22,6 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import androidx.collection.ArraySet;
-import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.Region.Op;
 import android.util.Log;
@@ -31,15 +30,16 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.InternalInsetsInfo;
 
-import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.ScreenDecorations;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -48,7 +48,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Stack;
 
 /**
@@ -58,7 +57,6 @@
        ViewTreeObserver.OnComputeInternalInsetsListener, VisualStabilityManager.Callback,
        OnHeadsUpChangedListener, ConfigurationController.ConfigurationListener {
     private static final String TAG = "HeadsUpManagerPhone";
-    private static final boolean DEBUG = false;
 
     private final View mStatusBarWindowView;
     private final NotificationGroupManager mGroupManager;
@@ -81,6 +79,9 @@
     private boolean mIsObserving;
     private int mStatusBarState;
 
+    private final StateListener mStateListener = this::setStatusBarState;
+    private AnimationStateHandler mAnimationStateHandler;
+
     private final Pools.Pool<HeadsUpEntryPhone> mEntryPool = new Pools.Pool<HeadsUpEntryPhone>() {
         private Stack<HeadsUpEntryPhone> mPoolObjects = new Stack<>();
 
@@ -117,10 +118,21 @@
         addListener(new OnHeadsUpChangedListener() {
             @Override
             public void onHeadsUpPinnedModeChanged(boolean hasPinnedNotification) {
-                if (DEBUG) Log.w(TAG, "onHeadsUpPinnedModeChanged");
+                if (Log.isLoggable(TAG, Log.WARN)) {
+                    Log.w(TAG, "onHeadsUpPinnedModeChanged");
+                }
                 updateTouchableRegionListener();
             }
         });
+        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+    }
+
+    public void setAnimationStateHandler(AnimationStateHandler handler) {
+        mAnimationStateHandler = handler;
+    }
+
+    public void destroy() {
+        Dependency.get(StatusBarStateController.class).removeListener(mStateListener);
     }
 
     private void initResources() {
@@ -156,7 +168,7 @@
      */
     public boolean shouldSwallowClick(@NonNull String key) {
         HeadsUpManager.HeadsUpEntry entry = getHeadsUpEntry(key);
-        return entry != null && mClock.currentTimeMillis() < entry.postTime;
+        return entry != null && mClock.currentTimeMillis() < entry.mPostTime;
     }
 
     public void onExpandingFinished() {
@@ -165,9 +177,9 @@
             mReleaseOnExpandFinish = false;
         } else {
             for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) {
-                if (isHeadsUp(entry.key)) {
+                if (contains(entry.key)) {
                     // Maybe the heads-up was removed already
-                    removeHeadsUpEntry(entry);
+                    removeAlertEntry(entry.key);
                 }
             }
         }
@@ -202,7 +214,7 @@
     /**
      * Set the current state of the statusbar.
      */
-    public void setStatusBarState(int statusBarState) {
+    private void setStatusBarState(int statusBarState) {
         mStatusBarState = statusBarState;
     }
 
@@ -238,13 +250,6 @@
         }
     }
 
-    @VisibleForTesting
-    public void removeMinimumDisplayTimeForTesting() {
-        mMinimumDisplayTime = 0;
-        mHeadsUpNotificationDecay = 0;
-        mTouchAcceptanceDelay = 0;
-    }
-
     ///////////////////////////////////////////////////////////////////////////////////////////////
     //  HeadsUpManager public methods overrides:
 
@@ -253,12 +258,6 @@
         return mTrackingHeadsUp;
     }
 
-    @Override
-    public void snooze() {
-        super.snooze();
-        mReleaseOnExpandFinish = true;
-    }
-
     /**
      * React to the removal of the notification in the heads up.
      *
@@ -266,14 +265,15 @@
      * for a bit since it wasn't shown long enough
      */
     @Override
-    public boolean removeNotification(@NonNull String key, boolean ignoreEarliestRemovalTime) {
-        if (wasShownLongEnough(key) || ignoreEarliestRemovalTime) {
-            return super.removeNotification(key, ignoreEarliestRemovalTime);
-        } else {
-            HeadsUpEntryPhone entry = getHeadsUpEntryPhone(key);
-            entry.removeAsSoonAsPossible();
-            return false;
-        }
+    public boolean removeNotification(@NonNull String key, boolean releaseImmediately) {
+        return super.removeNotification(key, canRemoveImmediately(key)
+                || releaseImmediately);
+    }
+
+    @Override
+    public void snooze() {
+        super.snooze();
+        mReleaseOnExpandFinish = true;
     }
 
     public void addSwipedOutNotification(@NonNull String key) {
@@ -355,29 +355,29 @@
 
     @Override
     public void onReorderingAllowed() {
-        mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(false);
+        mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
         for (NotificationData.Entry entry : mEntriesToRemoveWhenReorderingAllowed) {
-            if (isHeadsUp(entry.key)) {
+            if (contains(entry.key)) {
                 // Maybe the heads-up was removed already
-                removeHeadsUpEntry(entry);
+                removeAlertEntry(entry.key);
             }
         }
         mEntriesToRemoveWhenReorderingAllowed.clear();
-        mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(true);
+        mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(true);
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
     //  HeadsUpManager utility (protected) methods overrides:
 
     @Override
-    protected HeadsUpEntry createHeadsUpEntry() {
+    protected HeadsUpEntry createAlertEntry() {
         return mEntryPool.acquire();
     }
 
     @Override
-    protected void releaseHeadsUpEntry(HeadsUpEntry entry) {
-        entry.reset();
-        mEntryPool.release((HeadsUpEntryPhone) entry);
+    protected void onAlertEntryRemoved(AlertEntry alertEntry) {
+        super.onAlertEntryRemoved(alertEntry);
+        mEntryPool.release((HeadsUpEntryPhone) alertEntry);
     }
 
     @Override
@@ -389,7 +389,7 @@
     @Override
     protected void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
         super.dumpInternal(fd, pw, args);
-        pw.print("  mStatusBarState="); pw.println(mStatusBarState);
+        pw.print("  mBarState="); pw.println(mStatusBarState);
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -397,7 +397,7 @@
 
     @Nullable
     private HeadsUpEntryPhone getHeadsUpEntryPhone(@NonNull String key) {
-        return (HeadsUpEntryPhone) getHeadsUpEntry(key);
+        return (HeadsUpEntryPhone) mAlertEntries.get(key);
     }
 
     @Nullable
@@ -405,7 +405,7 @@
         return (HeadsUpEntryPhone) getTopHeadsUpEntry();
     }
 
-    private boolean wasShownLongEnough(@NonNull String key) {
+    private boolean canRemoveImmediately(@NonNull String key) {
         if (mSwipedOutKeys.contains(key)) {
             // We always instantly dismiss views being manually swiped out.
             mSwipedOutKeys.remove(key);
@@ -464,33 +464,29 @@
                     mVisualStabilityManager.addReorderingAllowedCallback(
                             HeadsUpManagerPhone.this);
                 } else if (!mTrackingHeadsUp) {
-                    removeHeadsUpEntry(entry);
+                    removeAlertEntry(entry.key);
                 } else {
                     mEntriesToRemoveAfterExpand.add(entry);
                 }
             };
 
-            super.setEntry(entry, removeHeadsUpRunnable);
-        }
-
-        public boolean wasShownLongEnough() {
-            return earliestRemovaltime < mClock.currentTimeMillis();
+            setEntry(entry, removeHeadsUpRunnable);
         }
 
         @Override
         public void updateEntry(boolean updatePostTime) {
             super.updateEntry(updatePostTime);
 
-            if (mEntriesToRemoveAfterExpand.contains(entry)) {
-                mEntriesToRemoveAfterExpand.remove(entry);
+            if (mEntriesToRemoveAfterExpand.contains(mEntry)) {
+                mEntriesToRemoveAfterExpand.remove(mEntry);
             }
-            if (mEntriesToRemoveWhenReorderingAllowed.contains(entry)) {
-                mEntriesToRemoveWhenReorderingAllowed.remove(entry);
+            if (mEntriesToRemoveWhenReorderingAllowed.contains(mEntry)) {
+                mEntriesToRemoveWhenReorderingAllowed.remove(mEntry);
             }
         }
 
         @Override
-        public void expanded(boolean expanded) {
+        public void setExpanded(boolean expanded) {
             if (this.expanded == expanded) {
                 return;
             }
@@ -503,4 +499,8 @@
             }
         }
     }
+
+    public interface AnimationStateHandler {
+        void setHeadsUpGoingAwayAnimationsAllowed(boolean allowed);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index 182293f..4df1e3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -21,10 +21,10 @@
 import android.view.ViewConfiguration;
 
 import com.android.systemui.Gefingerpoken;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 /**
  * A helper class to handle touches on the heads-up views.
@@ -118,7 +118,7 @@
                     mPanel.startExpandingFromPeek();
                     // This call needs to be after the expansion start otherwise we will get a
                     // flicker of one frame as it's not expanded yet.
-                    mHeadsUpManager.unpinAll();
+                    mHeadsUpManager.unpinAll(true);
                     mPanel.clearNotificationEffects();
                     endMotion();
                     return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 25b97bb..d89bcda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -174,6 +174,7 @@
     private int mIndicationBottomMarginAmbient;
     private float mDarkAmount;
     private int mBurnInXOffset;
+    private int mBurnInYOffset;
 
     public KeyguardBottomAreaView(Context context) {
         this(context, null);
@@ -247,6 +248,8 @@
                 R.dimen.keyguard_indication_margin_bottom);
         mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
                 R.dimen.keyguard_indication_margin_bottom_ambient);
+        mBurnInYOffset = getResources().getDimensionPixelSize(
+                R.dimen.charging_indication_burn_in_prevention_offset_y);
         updateCameraVisibility();
         mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
         mUnlockMethodCache.addListener(this);
@@ -319,6 +322,8 @@
                 R.dimen.keyguard_indication_margin_bottom);
         mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
                 R.dimen.keyguard_indication_margin_bottom_ambient);
+        mBurnInYOffset = getResources().getDimensionPixelSize(
+                R.dimen.charging_indication_burn_in_prevention_offset_y);
         MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams();
         if (mlp.bottomMargin != mIndicationBottomMargin) {
             mlp.bottomMargin = mIndicationBottomMargin;
@@ -562,12 +567,6 @@
             return;
         }
         mDarkAmount = darkAmount;
-        // Let's randomize the bottom margin every time we wake up to avoid burn-in.
-        if (darkAmount == 0) {
-            mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
-                    R.dimen.keyguard_indication_margin_bottom_ambient)
-                    + (int) (Math.random() * mIndicationText.getTextSize());
-        }
         mIndicationArea.setAlpha(MathUtils.lerp(1f, 0.7f, darkAmount));
         mIndicationArea.setTranslationY(MathUtils.lerp(0,
                 mIndicationBottomMargin - mIndicationBottomMarginAmbient, darkAmount));
@@ -844,8 +843,9 @@
     public void dozeTimeTick() {
         if (mDarkAmount == 1) {
             // Move indication every minute to avoid burn-in
-            final int dozeTranslation = mIndicationBottomMargin - mIndicationBottomMarginAmbient;
-            mIndicationArea.setTranslationY(dozeTranslation + (float) Math.random() * 5);
+            int dozeTranslation = mIndicationBottomMargin - mIndicationBottomMarginAmbient;
+            int burnInYOffset = (int) (-mBurnInYOffset + Math.random() * mBurnInYOffset * 2);
+            mIndicationArea.setTranslationY(dozeTranslation + burnInYOffset);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 20ea27a..5630da6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -447,8 +447,8 @@
                 R.color.light_mode_icon_color_single_tone);
         float intensity = textColor == Color.WHITE ? 0 : 1;
         mCarrierLabel.setTextColor(iconColor);
-        mBatteryView.setFillColor(iconColor);
         mIconManager.setTint(iconColor);
+        mBatteryView.setColorsFromContext(mContext);
         Rect tintArea = new Rect(0, 0, 0, 0);
 
         applyDarkness(R.id.battery, tintArea, intensity, iconColor);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 1003833..b84ee03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -22,7 +22,9 @@
 import static com.android.internal.view.RotationPolicy.NATURAL_ROTATION;
 
 import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
 import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
 import static com.android.systemui.OverviewProxyService.OverviewProxyListener;
@@ -33,8 +35,6 @@
 import android.animation.ObjectAnimator;
 import android.annotation.IdRes;
 import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
 import android.app.ActivityTaskManager;
 import android.app.Fragment;
 import android.app.IActivityManager;
@@ -98,7 +98,7 @@
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 import com.android.systemui.statusbar.policy.KeyButtonView;
 import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -181,6 +181,9 @@
         public void onQuickStepStarted() {
             // Use navbar dragging as a signal to hide the rotate button
             setRotateSuggestionButtonState(false);
+
+            // Hide the notifications panel when quick step starts
+            mStatusBar.collapsePanel(true /* animate */);
         }
 
         @Override
@@ -192,8 +195,14 @@
         @Override
         public void onBackButtonAlphaChanged(float alpha, boolean animate) {
             final ButtonDispatcher backButton = mNavigationBarView.getBackButton();
-            backButton.setVisibility(alpha > 0 ? View.VISIBLE : View.INVISIBLE);
-            backButton.setAlpha(alpha, animate);
+            if (QuickStepController.shouldhideBackButton()) {
+                // If property was changed to hide/show back button, going home will trigger
+                // launcher to to change the back button alpha to reflect property change
+                backButton.setVisibility(View.GONE);
+            } else {
+                backButton.setVisibility(alpha > 0 ? View.VISIBLE : View.INVISIBLE);
+                backButton.setAlpha(alpha, animate);
+            }
         }
     };
 
@@ -662,6 +671,10 @@
             nbModeChanged = nbMode != -1;
             if (nbModeChanged) {
                 if (mNavigationBarMode != nbMode) {
+                    if (mNavigationBarMode == MODE_TRANSPARENT
+                            || mNavigationBarMode == MODE_LIGHTS_OUT_TRANSPARENT) {
+                        mNavigationBarView.hideRecentsOnboarding();
+                    }
                     mNavigationBarMode = nbMode;
                     checkNavBarModes();
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index ed1ae10..8c02e1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -75,7 +75,6 @@
     private int mTouchDownY;
     private boolean mDownOnRecents;
     private VelocityTracker mVelocityTracker;
-    private boolean mNotificationsVisibleOnDown;
 
     private boolean mDockWindowEnabled;
     private boolean mDockWindowTouchSlopExceeded;
@@ -108,9 +107,6 @@
     }
 
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
-            mNotificationsVisibleOnDown = !mStatusBar.isPresenterFullyCollapsed();
-        }
         if (!canHandleGestures()) {
             return false;
         }
@@ -275,7 +271,7 @@
     }
 
     private boolean canHandleGestures() {
-        return !mStatusBar.isKeyguardShowing() && !mNotificationsVisibleOnDown;
+        return !mStatusBar.isKeyguardShowing();
     }
 
     private int calculateDragMode() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 6077e79..1892d37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -25,6 +25,7 @@
 import android.animation.LayoutTransition;
 import android.animation.LayoutTransition.TransitionListener;
 import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.annotation.DrawableRes;
@@ -61,6 +62,7 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.DockedStackExistsListener;
+import com.android.systemui.Interpolators;
 import com.android.systemui.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
@@ -121,9 +123,9 @@
     private Rect mTmpRect = new Rect();
 
     private KeyButtonDrawable mBackIcon;
-    private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
-    private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
-    private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
+    private KeyButtonDrawable mHomeDefaultIcon;
+    private KeyButtonDrawable mBackCarModeIcon;
+    private KeyButtonDrawable mHomeCarModeIcon;
     private KeyButtonDrawable mRecentIcon;
     private KeyButtonDrawable mDockedIcon;
     private KeyButtonDrawable mImeIcon;
@@ -263,13 +265,11 @@
 
         @Override
         public boolean performAccessibilityAction(View host, int action, Bundle args) {
-            switch (action) {
-                case R.id.action_toggle_overview:
-                    SysUiServiceProvider.getComponent(getContext(), Recents.class)
-                            .toggleRecentApps();
-                    break;
-                default:
-                    return super.performAccessibilityAction(host, action, args);
+            if (action == R.id.action_toggle_overview) {
+                SysUiServiceProvider.getComponent(getContext(), Recents.class)
+                        .toggleRecentApps();
+            } else {
+                return super.performAccessibilityAction(host, action, args);
             }
             return true;
         }
@@ -461,16 +461,9 @@
                 && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0);
     }
 
-    // TODO(b/80003212): change car mode icons to vector icons.
     private void updateCarModeIcons(Context ctx) {
-        mBackCarModeIcon = getDrawable(ctx,
-                R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
-        mBackLandCarModeIcon = mBackCarModeIcon;
-        mBackAltCarModeIcon = getDrawable(ctx,
-                R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
-        mBackAltLandCarModeIcon = mBackAltCarModeIcon;
-        mHomeCarModeIcon = getDrawable(ctx,
-                R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
+        mBackCarModeIcon = getDrawable(ctx, R.drawable.ic_sysbar_back_carmode);
+        mHomeCarModeIcon = getDrawable(ctx, R.drawable.ic_sysbar_home_carmode);
     }
 
     private void reloadNavIcons() {
@@ -483,14 +476,15 @@
         Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
         Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
 
-        if (oldConfig.orientation != newConfig.orientation
-                || oldConfig.densityDpi != newConfig.densityDpi) {
+        final boolean orientationChange = oldConfig.orientation != newConfig.orientation;
+        final boolean densityChange = oldConfig.densityDpi != newConfig.densityDpi;
+        final boolean dirChange = oldConfig.getLayoutDirection() != newConfig.getLayoutDirection();
+
+        if (orientationChange || densityChange) {
             mDockedIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_docked);
             mHomeDefaultIcon = getHomeDrawable(lightContext, darkContext);
         }
-        if (oldConfig.densityDpi != newConfig.densityDpi
-                || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
-            mBackIcon = getBackDrawable(lightContext, darkContext);
+        if (densityChange || dirChange) {
             mRecentIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_recent);
             mMenuIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_menu);
 
@@ -506,6 +500,9 @@
                 updateCarModeIcons(ctx);
             }
         }
+        if (orientationChange || densityChange || dirChange) {
+            mBackIcon = getBackDrawable(lightContext, darkContext);
+        }
     }
 
     public KeyButtonDrawable getBackDrawable(Context lightContext, Context darkContext) {
@@ -519,17 +516,33 @@
         final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
         KeyButtonDrawable drawable = quickStepEnabled
                 ? getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home_quick_step)
-                : getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home,
-                        false /* hasShadow */);
+                : getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home);
         orientHomeButton(drawable);
         return drawable;
     }
 
     private void orientBackButton(KeyButtonDrawable drawable) {
         final boolean useAltBack =
-            (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
-        drawable.setRotation(useAltBack
-                ? -90 : (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) ? 180 : 0);
+                (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
+        final boolean isRtl = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+        float degrees = useAltBack
+                ? (isRtl ? 270 : -90)
+                : (isRtl ? 180 : 0);
+        if (drawable.getRotation() == degrees) {
+            return;
+        }
+
+        // Animate the back button's rotation to the new degrees and only in portrait move up the
+        // back button to line up with the other buttons
+        float targetY = !mOverviewProxyService.shouldShowSwipeUpUI() && !mVertical && useAltBack
+                ? - getResources().getDimension(R.dimen.navbar_back_button_ime_offset)
+                : 0;
+        ObjectAnimator navBarAnimator = ObjectAnimator.ofPropertyValuesHolder(drawable,
+                PropertyValuesHolder.ofFloat(KeyButtonDrawable.KEY_DRAWABLE_ROTATE, degrees),
+                PropertyValuesHolder.ofFloat(KeyButtonDrawable.KEY_DRAWABLE_TRANSLATE_Y, targetY));
+        navBarAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        navBarAnimator.setDuration(200);
+        navBarAnimator.start();
     }
 
     private void orientHomeButton(KeyButtonDrawable drawable) {
@@ -555,11 +568,9 @@
                 darkContext.getDrawable(icon), hasShadow);
     }
 
-    private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
-            @DrawableRes int darkIcon) {
-        // Legacy image icons using separate light and dark images will not support shadows
-        return KeyButtonDrawable.create(ctx, ctx.getDrawable(lightIcon),
-            ctx.getDrawable(darkIcon), false /* hasShadow */);
+    private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon) {
+        // Legacy image icons using a single image will not support shadows
+        return KeyButtonDrawable.create(ctx, ctx.getDrawable(icon), null, false /* hasShadow */);
     }
 
     private TintedKeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
@@ -574,16 +585,8 @@
         super.setLayoutDirection(layoutDirection);
     }
 
-    private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
-        return landscape
-                ? carMode ? mBackAltLandCarModeIcon : mBackIcon
-                : carMode ? mBackAltCarModeIcon : mBackIcon;
-    }
-
-    private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
-        return landscape
-                ? carMode ? mBackLandCarModeIcon : mBackIcon
-                : carMode ? mBackCarModeIcon : mBackIcon;
+    private KeyButtonDrawable getBackIcon(boolean carMode) {
+        return carMode ? mBackCarModeIcon : mBackIcon;
     }
 
     public void setNavigationIconHints(int hints) {
@@ -623,12 +626,10 @@
         // to recent icon is not required.
         final boolean useAltBack =
                 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
-        KeyButtonDrawable backIcon = useAltBack
-                ? getBackIconWithAlt(mUseCarModeUi, mVertical)
-                : getBackIcon(mUseCarModeUi, mVertical);
+        KeyButtonDrawable backIcon = getBackIcon(mUseCarModeUi);
+        orientBackButton(backIcon);
         KeyButtonDrawable homeIcon = mUseCarModeUi ? mHomeCarModeIcon : mHomeDefaultIcon;
         if (!mUseCarModeUi) {
-            orientBackButton(backIcon);
             orientHomeButton(homeIcon);
         }
         getHomeButton().setImageDrawable(homeIcon);
@@ -662,7 +663,8 @@
         // Always disable recents when alternate car mode UI is active.
         boolean disableRecent = mUseCarModeUi || !isOverviewEnabled();
 
-        boolean disableBack = ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0) && !useAltBack;
+        boolean disableBack = QuickStepController.shouldhideBackButton()
+                || (((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0) && !useAltBack);
 
         // When screen pinning, don't hide back and home when connected service or back and
         // recents buttons when disconnected from launcher service in screen pinning mode,
@@ -771,8 +773,19 @@
                 showSwipeUpUI ? mQuickStepAccessibilityDelegate : null);
     }
 
+    public boolean isNotificationsFullyCollapsed() {
+        return mPanelView.isFullyCollapsed();
+    }
+
+    /**
+     * Updates the {@link WindowManager.LayoutParams.FLAG_SLIPPERY} state dependent on if swipe up
+     * is enabled, or the notifications is fully opened without being in an animated state. If
+     * slippery is enabled, touch events will leave the nav bar window and enter into the fullscreen
+     * app/home window, if not nav bar will receive a cancelled touch event once gesture leaves bar.
+     */
     public void updateSlippery() {
-        setSlippery(!isQuickStepSwipeUpEnabled() || mPanelView.isFullyExpanded());
+        setSlippery(!isQuickStepSwipeUpEnabled() ||
+                (mPanelView.isFullyExpanded() && !mPanelView.isCollapsing()));
     }
 
     private void setSlippery(boolean slippery) {
@@ -886,6 +899,10 @@
 
     public boolean isRotateButtonVisible() { return mShowRotateButton; }
 
+    void hideRecentsOnboarding() {
+        mRecentsOnboarding.hide(true);
+    }
+
     /**
      * @return the button at the given {@param x} and {@param y}.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
index 09833d4..7b9ed88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
@@ -98,6 +98,7 @@
         return mClickableChildren
                 .stream()
                 .filter(v -> v.isAttachedToWindow())
+                .filter(v -> v.isFocusable())
                 .map(v -> new Pair<>(distance(v, event), v))
                 .min(Comparator.comparingInt(f -> f.first))
                 .get().second;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
index 214dda2..9c9b929 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
@@ -60,7 +60,7 @@
         if (mEventBuf.size() == MAX_EVENTS) {
             mEventBuf.remove();
         }
-        mEventBuf.add(new MotionEventCopy(event.getX(), event.getY(), event.getEventTime()));
+        mEventBuf.add(new MotionEventCopy(event.getRawX(), event.getRawY(), event.getEventTime()));
     }
 
     public void computeCurrentVelocity(int units) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 8858381..5fe362f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -22,9 +22,12 @@
 import androidx.annotation.Nullable;
 import android.util.Log;
 
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 
@@ -52,6 +55,12 @@
     private boolean mIsUpdatingUnchangedGroup;
     private HashMap<String, NotificationData.Entry> mPendingNotifications;
 
+    private final StateListener mStateListener = this::setStatusBarState;
+
+    public NotificationGroupManager() {
+        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+    }
+
     public void setOnGroupChangeListener(OnGroupChangeListener listener) {
         mListener = listener;
     }
@@ -171,7 +180,7 @@
      */
     private void cleanUpHeadsUpStatesOnAdd(NotificationGroup group, boolean addIsPending) {
         if (!addIsPending && group.hunSummaryOnNextAddition) {
-            if (!mHeadsUpManager.isHeadsUp(group.summary.key)) {
+            if (!mHeadsUpManager.contains(group.summary.key)) {
                 mHeadsUpManager.showNotification(group.summary);
             }
             group.hunSummaryOnNextAddition = false;
@@ -208,15 +217,17 @@
                 NotificationData.Entry entry = children.get(i);
                 if (onlySummaryAlerts(entry) && entry.row.isHeadsUp()) {
                     releasedChild = true;
-                    mHeadsUpManager.releaseImmediately(entry.key);
+                    mHeadsUpManager.removeNotification(
+                            entry.key, true /* releaseImmediately */);
                 }
             }
             if (isolatedChild != null && onlySummaryAlerts(isolatedChild)
                     && isolatedChild.row.isHeadsUp()) {
                 releasedChild = true;
-                mHeadsUpManager.releaseImmediately(isolatedChild.key);
+                mHeadsUpManager.removeNotification(
+                        isolatedChild.key, true /* releaseImmediately */);
             }
-            if (releasedChild && !mHeadsUpManager.isHeadsUp(group.summary.key)) {
+            if (releasedChild && !mHeadsUpManager.contains(group.summary.key)) {
                 boolean notifyImmediately = (numChildren - numPendingChildren) > 1;
                 if (notifyImmediately) {
                     mHeadsUpManager.showNotification(group.summary);
@@ -355,10 +366,7 @@
         return group != null && group.suppressed;
     }
 
-    public void setStatusBarState(int newState) {
-        if (mBarState == newState) {
-            return;
-        }
+    private void setStatusBarState(int newState) {
         mBarState = newState;
         if (mBarState == StatusBarState.KEYGUARD) {
             collapseAllGroups();
@@ -546,8 +554,8 @@
                     // the notification is actually already removed, no need to do heads-up on it.
                     return;
                 }
-                if (mHeadsUpManager.isHeadsUp(child.key)) {
-                    mHeadsUpManager.updateNotification(child, true);
+                if (mHeadsUpManager.contains(child.key)) {
+                    mHeadsUpManager.updateNotification(child.key, true /* alert */);
                 } else {
                     if (onlySummaryAlerts(entry)) {
                         notificationGroup.lastHeadsUpTransfer = SystemClock.elapsedRealtime();
@@ -556,7 +564,7 @@
                 }
             }
         }
-        mHeadsUpManager.releaseImmediately(entry.key);
+        mHeadsUpManager.removeNotification(entry.key, true /* releaseImmediately */);
     }
 
     private boolean onlySummaryAlerts(NotificationData.Entry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index a5b56eb..b19f57d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -8,21 +8,22 @@
 import androidx.collection.ArrayMap;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import java.util.ArrayList;
 import java.util.function.Function;
@@ -45,7 +46,7 @@
     private NotificationIconContainer mNotificationIcons;
     private NotificationIconContainer mShelfIcons;
     private final Rect mTintArea = new Rect();
-    private NotificationStackScrollLayout mNotificationScrollLayout;
+    private ViewGroup mNotificationScrollLayout;
     private Context mContext;
     private boolean mFullyDark;
     private boolean mHasShelfIconsWhenFullyDark;
@@ -71,8 +72,7 @@
 
         LayoutInflater layoutInflater = LayoutInflater.from(context);
         mNotificationIconArea = inflateIconArea(layoutInflater);
-        mNotificationIcons = (NotificationIconContainer) mNotificationIconArea.findViewById(
-                R.id.notificationIcons);
+        mNotificationIcons = mNotificationIconArea.findViewById(R.id.notificationIcons);
 
         mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 653471d..0a724bd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -35,9 +35,9 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
 import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.statusbar.stack.AnimationFilter;
-import com.android.systemui.statusbar.stack.AnimationProperties;
-import com.android.systemui.statusbar.stack.ViewState;
+import com.android.systemui.statusbar.notification.stack.AnimationFilter;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.ViewState;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -536,7 +536,8 @@
             return 0;
         }
 
-        int translation = (int) (mLastVisibleIconState.xTranslation + mIconSize);
+        int translation = (int) (isLayoutRtl() ? getWidth() - mLastVisibleIconState.xTranslation
+                : mLastVisibleIconState.xTranslation + mIconSize);
         // There's a chance that last translation goes beyond the edge maybe
         return Math.min(getWidth(), translation);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 492efa2..33ddfde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -16,7 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
+        .ExpandAnimationParameters;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -32,6 +33,7 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.PointF;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
@@ -47,35 +49,44 @@
 import android.view.ViewGroup;
 import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityManager;
+import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
 import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.statusbar.stack.AnimationProperties;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.statusbar.policy.ZenModeController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -87,10 +98,26 @@
         ExpandableView.OnHeightChangedListener,
         View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
         KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
-        OnHeadsUpChangedListener, QS.HeightListener {
+        OnHeadsUpChangedListener, QS.HeightListener, ZenModeController.Callback,
+        ConfigurationController.ConfigurationListener {
 
     private static final boolean DEBUG = false;
 
+    /**
+     * Fling expanding QS.
+     */
+    public static final int FLING_EXPAND = 0;
+
+    /**
+     * Fling collapsing QS, potentially stopping when QS becomes QQS.
+     */
+    public static final int FLING_COLLAPSE = 1;
+
+    /**
+     * Fing until QS is completely hidden.
+     */
+    public static final int FLING_HIDE = 2;
+
     // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
     // changed.
     private static final int CAP_HEIGHT = 1456;
@@ -109,17 +136,20 @@
     private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties()
             .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
     private static final FloatProperty<NotificationPanelView> SET_DARK_AMOUNT_PROPERTY =
-            new FloatProperty<NotificationPanelView>("mDarkAmount") {
+            new FloatProperty<NotificationPanelView>("mInterpolatedDarkAmount") {
+
                 @Override
                 public void setValue(NotificationPanelView object, float value) {
-                    object.setDarkAmount(value);
+                    object.setDarkAmount(value, object.mDarkInterpolator.getInterpolation(value));
                 }
 
                 @Override
                 public Float get(NotificationPanelView object) {
-                    return object.mDarkAmount;
+                    return object.mLinearDarkAmount;
                 }
             };
+
+    private Interpolator mDarkInterpolator;
     private final PowerManager mPowerManager;
     private final AccessibilityManager mAccessibilityManager;
 
@@ -156,7 +186,7 @@
     private boolean mKeyguardShowing;
     private boolean mDozing;
     private boolean mDozingOnDown;
-    protected int mStatusBarState;
+    protected int mBarState;
     private float mInitialHeightOnTouch;
     private float mInitialTouchX;
     private float mInitialTouchY;
@@ -239,7 +269,18 @@
     private int mIndicationBottomPadding;
     private int mAmbientIndicationBottomPadding;
     private boolean mIsFullWidth;
-    private float mDarkAmount;
+
+    /**
+     * Current dark amount that follows regular interpolation curve of animation.
+     */
+    private float mInterpolatedDarkAmount;
+
+    /**
+     * Dark amount that animates from 0 to 1 or vice-versa in linear manner, even if the
+     * interpolation curve is different.
+     */
+    private float mLinearDarkAmount;
+
     private float mDarkAmountTarget;
     private boolean mPulsing;
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
@@ -281,6 +322,10 @@
             .setDuration(200)
             .setAnimationFinishListener(mAnimatorListenerAdapter)
             .setCustomInterpolator(PANEL_ALPHA.getProperty(), Interpolators.ALPHA_IN);
+    private final NotificationEntryManager mEntryManager =
+            Dependency.get(NotificationEntryManager.class);
+
+    private final StateListener mListener = this::setBarState;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -293,7 +338,7 @@
         setPanelAlpha(255, false /* animate */);
     }
 
-    public void setStatusBar(StatusBar bar) {
+    private void setStatusBar(StatusBar bar) {
         mStatusBar = bar;
         mKeyguardBottomArea.setStatusBar(mStatusBar);
     }
@@ -323,12 +368,18 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         FragmentHostManager.get(this).addTagListener(QS.TAG, mFragmentListener);
+        Dependency.get(StatusBarStateController.class).addListener(mListener);
+        Dependency.get(ZenModeController.class).addCallback(this);
+        Dependency.get(ConfigurationController.class).addCallback(this);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         FragmentHostManager.get(this).removeTagListener(QS.TAG, mFragmentListener);
+        Dependency.get(StatusBarStateController.class).removeListener(mListener);
+        Dependency.get(ZenModeController.class).removeCallback(this);
+        Dependency.get(ConfigurationController.class).removeCallback(this);
     }
 
     @Override
@@ -375,7 +426,15 @@
         }
     }
 
+    @Override
+    public void onDensityOrFontScaleChanged() {
+        updateShowEmptyShadeView();
+    }
+
+    @Override
     public void onThemeChanged() {
+        updateShowEmptyShadeView();
+
         // Re-inflate the status view group.
         int index = indexOfChild(mKeyguardStatusView);
         removeView(mKeyguardStatusView);
@@ -394,10 +453,10 @@
                 false);
         addView(mKeyguardBottomArea, index);
         initBottomArea();
-        setDarkAmount(mDarkAmount);
+        setDarkAmount(mLinearDarkAmount, mInterpolatedDarkAmount);
 
-        setKeyguardStatusViewVisibility(mStatusBarState, false, false);
-        setKeyguardBottomAreaVisibility(mStatusBarState, false);
+        setKeyguardStatusViewVisibility(mBarState, false, false);
+        setKeyguardBottomAreaVisibility(mBarState, false);
     }
 
     private void initBottomArea() {
@@ -495,7 +554,7 @@
         boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
         boolean animateClock = animate || mAnimateNextPositionUpdate;
         int stackScrollerPadding;
-        if (mStatusBarState != StatusBarState.KEYGUARD) {
+        if (mBarState != StatusBarState.KEYGUARD) {
             stackScrollerPadding = (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight
             +  mQsNotificationTopPadding;
         } else {
@@ -508,7 +567,7 @@
                     getExpandedFraction(),
                     totalHeight,
                     mKeyguardStatusView.getHeight(),
-                    mDarkAmount,
+                    mInterpolatedDarkAmount,
                     mStatusBar.isKeyguardCurrentlySecure(),
                     mPulsing,
                     mBouncerTop);
@@ -551,8 +610,8 @@
                 continue;
             }
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
-                    row.getStatusBarNotification());
+            boolean suppressedSummary = mGroupManager != null
+                    && mGroupManager.isSummaryOfSuppressedGroup(row.getStatusBarNotification());
             if (suppressedSummary) {
                 continue;
             }
@@ -608,7 +667,7 @@
     }
 
     @Override
-    public void resetViews() {
+    public void resetViews(boolean animate) {
         mIsLaunchTransitionFinished = false;
         mBlockTouches = false;
         mUnlockIconActive = false;
@@ -616,11 +675,15 @@
             mAffordanceHelper.reset(false);
             mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
         }
-        closeQs();
         mStatusBar.getGutsManager().closeAndSaveGuts(true /* leavebehind */, true /* force */,
                 true /* controls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
-        mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, false /* animate */,
-                true /* cancelAnimators */);
+        if (animate) {
+            animateCloseQs(true /* animateAway */);
+        } else {
+            closeQs();
+        }
+        mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, animate,
+                !animate /* cancelAnimators */);
         mNotificationStackScroller.resetScrollPosition();
     }
 
@@ -642,7 +705,13 @@
         setQsExpansion(mQsMinExpansionHeight);
     }
 
-    public void animateCloseQs() {
+    /**
+     * Animate QS closing by flinging it.
+     * If QS is expanded, it will collapse into QQS and stop.
+     *
+     * @param animateAway Do not stop when QS becomes QQS. Fling until QS isn't visible anymore.
+     */
+    public void animateCloseQs(boolean animateAway) {
         if (mQsExpansionAnimator != null) {
             if (!mQsAnimatorExpand) {
                 return;
@@ -651,14 +720,7 @@
             mQsExpansionAnimator.cancel();
             setQsExpansion(height);
         }
-        flingSettings(0 /* vel */, false);
-    }
-
-    public void openQs() {
-        cancelQsAnimation();
-        if (mQsExpansionEnabled) {
-            setQsExpansion(mQsMaxExpansionHeight);
-        }
+        flingSettings(0 /* vel */, animateAway ? FLING_HIDE : FLING_COLLAPSE);
     }
 
     public void expandWithQs() {
@@ -671,7 +733,7 @@
 
     public void expandWithoutQs() {
         if (isQsExpanded()) {
-            flingSettings(0 /* velocity */, false /* expand */);
+            flingSettings(0 /* velocity */, FLING_COLLAPSE);
         } else {
             expand(true /* animate */);
         }
@@ -815,12 +877,12 @@
         if (expandsQs) {
             logQsSwipeDown(y);
         }
-        flingSettings(vel, expandsQs && !isCancelMotionEvent);
+        flingSettings(vel, expandsQs && !isCancelMotionEvent ? FLING_EXPAND : FLING_COLLAPSE);
     }
 
     private void logQsSwipeDown(float y) {
         float vel = getCurrentQSVelocity();
-        final int gesture = mStatusBarState == StatusBarState.KEYGUARD
+        final int gesture = mBarState == StatusBarState.KEYGUARD
                 ? MetricsEvent.ACTION_LS_QS
                 : MetricsEvent.ACTION_SHADE_QS_PULL;
         mLockscreenGestureLogger.write(gesture,
@@ -873,7 +935,7 @@
         boolean handled = false;
         if ((!mIsExpanding || mHintAnimationRunning)
                 && !mQsExpanded
-                && mStatusBar.getBarState() != StatusBarState.SHADE
+                && mBarState != StatusBarState.SHADE
                 && !mDozing) {
             handled |= mAffordanceHelper.onTouchEvent(event);
         }
@@ -897,7 +959,7 @@
     private boolean handleQsTouch(MotionEvent event) {
         final int action = event.getActionMasked();
         if (action == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f
-                && mStatusBar.getBarState() != StatusBarState.KEYGUARD && !mQsExpanded
+                && mBarState != StatusBarState.KEYGUARD && !mQsExpanded
                 && mQsExpansionEnabled) {
 
             // Down in the empty area while fully expanded - go to QS.
@@ -991,7 +1053,7 @@
 
     @Override
     protected boolean hasConflictingGestures() {
-        return mStatusBar.getBarState() != StatusBarState.SHADE;
+        return mBarState != StatusBarState.SHADE;
     }
 
     @Override
@@ -1084,7 +1146,8 @@
         mLastOverscroll = 0f;
         mQsExpansionFromOverscroll = false;
         setQsExpansion(mQsExpansionHeight);
-        flingSettings(!mQsExpansionEnabled && open ? 0f : velocity, open && mQsExpansionEnabled,
+        flingSettings(!mQsExpansionEnabled && open ? 0f : velocity,
+                open && mQsExpansionEnabled ? FLING_EXPAND : FLING_COLLAPSE,
                 new Runnable() {
                     @Override
                     public void run() {
@@ -1128,14 +1191,15 @@
         }
     }
 
-    public void setBarState(int statusBarState, boolean keyguardFadingAway,
-            boolean goingToFullShade) {
-        int oldState = mStatusBarState;
+    private void setBarState(int statusBarState) {
+        boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
+        boolean keyguardFadingAway = mKeyguardMonitor.isKeyguardFadingAway();
+        int oldState = mBarState;
         boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD;
         setKeyguardStatusViewVisibility(statusBarState, keyguardFadingAway, goingToFullShade);
         setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);
 
-        mStatusBarState = statusBarState;
+        mBarState = statusBarState;
         mKeyguardShowing = keyguardShowing;
         if (mQs != null) {
             mQs.setKeyguardShowing(mKeyguardShowing);
@@ -1144,8 +1208,8 @@
         if (oldState == StatusBarState.KEYGUARD
                 && (goingToFullShade || statusBarState == StatusBarState.SHADE_LOCKED)) {
             animateKeyguardStatusBarOut();
-            long delay = mStatusBarState == StatusBarState.SHADE_LOCKED
-                    ? 0 : mStatusBar.calculateGoingToFullShadeDelay();
+            long delay = mBarState == StatusBarState.SHADE_LOCKED
+                    ? 0 : mKeyguardMonitor.calculateGoingToFullShadeDelay();
             mQs.animateHeaderSlidingIn(delay);
         } else if (oldState == StatusBarState.SHADE_LOCKED
                 && statusBarState == StatusBarState.KEYGUARD) {
@@ -1154,7 +1218,7 @@
         } else {
             mKeyguardStatusBar.setAlpha(1f);
             mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
-            if (keyguardShowing && oldState != mStatusBarState) {
+            if (keyguardShowing && oldState != mBarState) {
                 mKeyguardBottomArea.onKeyguardShowingChanged();
                 if (mQs != null) {
                     mQs.hideImmediately();
@@ -1203,11 +1267,11 @@
     private void animateKeyguardStatusBarOut() {
         ValueAnimator anim = ValueAnimator.ofFloat(mKeyguardStatusBar.getAlpha(), 0f);
         anim.addUpdateListener(mStatusBarAnimateAlphaListener);
-        anim.setStartDelay(mStatusBar.isKeyguardFadingAway()
-                ? mStatusBar.getKeyguardFadingAwayDelay()
+        anim.setStartDelay(mKeyguardMonitor.isKeyguardFadingAway()
+                ? mKeyguardMonitor.getKeyguardFadingAwayDelay()
                 : 0);
-        anim.setDuration(mStatusBar.isKeyguardFadingAway()
-                ? mStatusBar.getKeyguardFadingAwayDuration() / 2
+        anim.setDuration(mKeyguardMonitor.isKeyguardFadingAway()
+                ? mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2
                 : StackStateAnimator.ANIMATION_DURATION_STANDARD);
         anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
         anim.addListener(new AnimatorListenerAdapter() {
@@ -1251,8 +1315,8 @@
         if (goingToFullShade) {
             mKeyguardBottomArea.animate()
                     .alpha(0f)
-                    .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
-                    .setDuration(mStatusBar.getKeyguardFadingAwayDuration() / 2)
+                    .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
+                    .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2)
                     .setInterpolator(Interpolators.ALPHA_OUT)
                     .withEndAction(mAnimateKeyguardBottomAreaInvisibleEndRunnable)
                     .start();
@@ -1270,7 +1334,7 @@
             boolean goingToFullShade) {
         mKeyguardStatusView.animate().cancel();
         mKeyguardStatusViewAnimating = false;
-        if ((!keyguardFadingAway && mStatusBarState == StatusBarState.KEYGUARD
+        if ((!keyguardFadingAway && mBarState == StatusBarState.KEYGUARD
                 && statusBarState != StatusBarState.KEYGUARD) || goingToFullShade) {
             mKeyguardStatusViewAnimating = true;
             mKeyguardStatusView.animate()
@@ -1281,11 +1345,11 @@
                     .withEndAction(mAnimateKeyguardStatusViewGoneEndRunnable);
             if (keyguardFadingAway) {
                 mKeyguardStatusView.animate()
-                        .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
-                        .setDuration(mStatusBar.getKeyguardFadingAwayDuration()/2)
+                        .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
+                        .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration()/2)
                         .start();
             }
-        } else if (mStatusBarState == StatusBarState.SHADE_LOCKED
+        } else if (mBarState == StatusBarState.SHADE_LOCKED
                 && statusBarState == StatusBarState.KEYGUARD) {
             mKeyguardStatusView.setVisibility(View.VISIBLE);
             mKeyguardStatusViewAnimating = true;
@@ -1320,10 +1384,10 @@
     private void updateQsState() {
         mNotificationStackScroller.setQsExpanded(mQsExpanded);
         mNotificationStackScroller.setScrollingEnabled(
-                mStatusBarState != StatusBarState.KEYGUARD && (!mQsExpanded
+                mBarState != StatusBarState.KEYGUARD && (!mQsExpanded
                         || mQsExpansionFromOverscroll));
         updateEmptyShadeView();
-        mQsNavbarScrim.setVisibility(mStatusBarState == StatusBarState.SHADE && mQsExpanded
+        mQsNavbarScrim.setVisibility(mBarState == StatusBarState.SHADE && mQsExpanded
                 && !mStackScrollerOverscrolling && mQsScrimEnabled
                         ? View.VISIBLE
                         : View.INVISIBLE);
@@ -1345,14 +1409,12 @@
         mQsExpansionHeight = height;
         updateQsExpansion();
         requestScrollerTopPaddingUpdate(false /* animate */);
-        if (mKeyguardShowing) {
-            updateHeaderKeyguardAlpha();
-        }
-        if (mStatusBarState == StatusBarState.SHADE_LOCKED
-                || mStatusBarState == StatusBarState.KEYGUARD) {
+        updateHeaderKeyguardAlpha();
+        if (mBarState == StatusBarState.SHADE_LOCKED
+                || mBarState == StatusBarState.KEYGUARD) {
             updateKeyguardBottomAreaAlpha();
         }
-        if (mStatusBarState == StatusBarState.SHADE && mQsExpanded
+        if (mBarState == StatusBarState.SHADE && mQsExpanded
                 && !mStackScrollerOverscrolling && mQsScrimEnabled) {
             mQsNavbarScrim.setAlpha(getQsExpansionFraction());
         }
@@ -1384,7 +1446,7 @@
             // Upon initialisation when we are not layouted yet we don't want to announce that we
             // are fully expanded, hence the != 0.0f check.
             return getContext().getString(R.string.accessibility_desc_quick_settings);
-        } else if (mStatusBarState == StatusBarState.KEYGUARD) {
+        } else if (mBarState == StatusBarState.KEYGUARD) {
             return getContext().getString(R.string.accessibility_desc_lock_screen);
         } else {
             return getContext().getString(R.string.accessibility_desc_notification_shade);
@@ -1402,7 +1464,7 @@
             // for a nice motion.
             int maxNotificationPadding = mClockPositionResult.stackScrollerPadding;
             int maxQsPadding = mQsMaxExpansionHeight + mQsNotificationTopPadding;
-            int max = mStatusBarState == StatusBarState.KEYGUARD
+            int max = mBarState == StatusBarState.KEYGUARD
                     ? Math.max(maxNotificationPadding, maxQsPadding)
                     : maxQsPadding;
             return (int) interpolate(getExpandedFraction(),
@@ -1453,13 +1515,35 @@
         }
     }
 
-    public void flingSettings(float vel, boolean expand) {
-        flingSettings(vel, expand, null, false /* isClick */);
+    /**
+     * @see #flingSettings(float, int, Runnable, boolean)
+     */
+    public void flingSettings(float vel, int type) {
+        flingSettings(vel, type, null, false /* isClick */);
     }
 
-    protected void flingSettings(float vel, boolean expand, final Runnable onFinishRunnable,
+    /**
+     * Animates QS or QQS as if the user had swiped up or down.
+     *
+     * @param vel Finger velocity or 0 when not initiated by touch events.
+     * @param type Either {@link #FLING_EXPAND}, {@link #FLING_COLLAPSE} or {@link #FLING_HIDE}.
+     * @param onFinishRunnable Runnable to be executed at the end of animation.
+     * @param isClick If originated by click (different interpolator and duration.)
+     */
+    protected void flingSettings(float vel, int type, final Runnable onFinishRunnable,
             boolean isClick) {
-        float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight;
+        float target;
+        switch (type) {
+            case FLING_EXPAND:
+                target = mQsMaxExpansionHeight;
+                break;
+            case FLING_COLLAPSE:
+                target = mQsMinExpansionHeight;
+                break;
+            case FLING_HIDE:
+            default:
+                target = 0;
+        }
         if (target == mQsExpansionHeight) {
             if (onFinishRunnable != null) {
                 onFinishRunnable.run();
@@ -1469,7 +1553,8 @@
 
         // If we move in the opposite direction, reset velocity and use a different duration.
         boolean oppositeDirection = false;
-        if (vel > 0 && !expand || vel < 0 && expand) {
+        boolean expanding = type == FLING_EXPAND;
+        if (vel > 0 && !expanding || vel < 0 && expanding) {
             vel = 0;
             oppositeDirection = true;
         }
@@ -1483,11 +1568,8 @@
         if (oppositeDirection) {
             animator.setDuration(350);
         }
-        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                setQsExpansion((Float) animation.getAnimatedValue());
-            }
+        animator.addUpdateListener(animation -> {
+            setQsExpansion((Float) animation.getAnimatedValue());
         });
         animator.addListener(new AnimatorListenerAdapter() {
             @Override
@@ -1501,7 +1583,7 @@
         });
         animator.start();
         mQsExpansionAnimator = animator;
-        mQsAnimatorExpand = expand;
+        mQsAnimatorExpand = expanding;
     }
 
     /**
@@ -1525,7 +1607,7 @@
     @Override
     protected boolean isScrolledToBottom() {
         if (!isInSettings()) {
-            return mStatusBar.getBarState() == StatusBarState.KEYGUARD
+            return mBarState == StatusBarState.KEYGUARD
                     || mNotificationStackScroller.isScrolledToBottom();
         } else {
             return true;
@@ -1535,7 +1617,7 @@
     @Override
     protected int getMaxPanelHeight() {
         int min = mStatusBarMinHeight;
-        if (mStatusBar.getBarState() != StatusBarState.KEYGUARD
+        if (mBarState != StatusBarState.KEYGUARD
                 && mNotificationStackScroller.getNotGoneChildCount() == 0) {
             int minHeight = (int) (mQsMinExpansionHeight + getOverExpansionAmount());
             min = Math.max(min, minHeight);
@@ -1615,7 +1697,7 @@
         int maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin;
         maxHeight += mNotificationStackScroller.getTopPaddingOverflow();
 
-        if (mStatusBarState == StatusBarState.KEYGUARD) {
+        if (mBarState == StatusBarState.KEYGUARD) {
             int minKeyguardPanelBottom = mClockPositionAlgorithm.getExpandedClockPosition()
                     + mKeyguardStatusView.getHeight()
                     + mNotificationStackScroller.getIntrinsicContentHeight();
@@ -1648,7 +1730,7 @@
             maxQsHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
         }
         float totalHeight = Math.max(
-                maxQsHeight, mStatusBarState == StatusBarState.KEYGUARD
+                maxQsHeight, mBarState == StatusBarState.KEYGUARD
                         ? mClockPositionResult.stackScrollerPadding : 0)
                 + notificationHeight + mNotificationStackScroller.getTopPaddingOverflow();
         if (totalHeight > mNotificationStackScroller.getHeight()) {
@@ -1687,8 +1769,8 @@
     }
 
     private void updateUnlockIcon() {
-        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
-                || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
+        if (mBarState == StatusBarState.KEYGUARD
+                || mBarState == StatusBarState.SHADE_LOCKED) {
             boolean active = getMaxPanelHeight() - getExpandedHeight() > mUnlockMoveDistance;
             KeyguardAffordanceView lockIcon = mKeyguardBottomArea.getLockIcon();
             if (active && !mUnlockIconActive && mTracking) {
@@ -1709,14 +1791,14 @@
      * Hides the header when notifications are colliding with it.
      */
     private void updateHeader() {
-        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+        if (mBarState == StatusBarState.KEYGUARD) {
             updateHeaderKeyguardAlpha();
         }
         updateQsExpansion();
     }
 
     protected float getHeaderTranslation() {
-        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+        if (mBarState == StatusBarState.KEYGUARD) {
             return 0;
         }
         float translation = MathUtils.lerp(-mQsMinExpansionHeight, 0,
@@ -1731,7 +1813,7 @@
      */
     private float getKeyguardContentsAlpha() {
         float alpha;
-        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+        if (mBarState == StatusBarState.KEYGUARD) {
 
             // When on Keyguard, we hide the header as soon as the top card of the notification
             // stack scroller is close enough (collision distance) to the bottom of the header.
@@ -1750,6 +1832,9 @@
     }
 
     private void updateHeaderKeyguardAlpha() {
+        if (!mKeyguardShowing) {
+            return;
+        }
         float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
         mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
                 * mKeyguardStatusBarAnimateAlpha);
@@ -1860,7 +1945,7 @@
         if (mConflictingQsExpansionGesture || mQsExpandImmediate) {
             return;
         }
-        if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+        if (mBarState != StatusBarState.KEYGUARD) {
             mNotificationStackScroller.setOnHeightChangedListener(null);
             if (isPixels) {
                 mNotificationStackScroller.setOverScrolledPixels(
@@ -1881,8 +1966,8 @@
             mQsExpandImmediate = true;
             mNotificationStackScroller.setShouldShowShelfOnly(true);
         }
-        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
-                || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
+        if (mBarState == StatusBarState.KEYGUARD
+                || mBarState == StatusBarState.SHADE_LOCKED) {
             mAffordanceHelper.animateHideLeftRightIcon();
         }
         mNotificationStackScroller.onPanelTrackingStarted();
@@ -1897,14 +1982,14 @@
                     0.0f, true /* onTop */, true /* animate */);
         }
         mNotificationStackScroller.onPanelTrackingStopped();
-        if (expand && (mStatusBar.getBarState() == StatusBarState.KEYGUARD
-                || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED)) {
+        if (expand && (mBarState == StatusBarState.KEYGUARD
+                || mBarState == StatusBarState.SHADE_LOCKED)) {
             if (!mHintAnimationRunning) {
                 mAffordanceHelper.reset(true);
             }
         }
-        if (!expand && (mStatusBar.getBarState() == StatusBarState.KEYGUARD
-                || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED)) {
+        if (!expand && (mBarState == StatusBarState.KEYGUARD
+                || mBarState == StatusBarState.SHADE_LOCKED)) {
             KeyguardAffordanceView lockIcon = mKeyguardBottomArea.getLockIcon();
             lockIcon.setImageAlpha(0.0f, true, 100, Interpolators.FAST_OUT_LINEAR_IN, null);
             lockIcon.setImageScale(2.0f, true, 100, Interpolators.FAST_OUT_LINEAR_IN);
@@ -1919,7 +2004,7 @@
         if (view == null && mQsExpanded) {
             return;
         }
-        if (needsAnimation && mDarkAmount == 0) {
+        if (needsAnimation && mInterpolatedDarkAmount == 0) {
             mAnimateNextPositionUpdate = true;
         }
         ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone();
@@ -1984,10 +2069,12 @@
     public void onClick(View v) {
         onQsExpansionStarted();
         if (mQsExpanded) {
-            flingSettings(0 /* vel */, false /* expand */, null, true /* isClick */);
+            flingSettings(0 /* vel */, FLING_COLLAPSE, null /* onFinishRunnable */,
+                    true /* isClick */);
         } else if (mQsExpansionEnabled) {
             mLockscreenGestureLogger.write(MetricsEvent.ACTION_SHADE_QS_TAP, 0, 0);
-            flingSettings(0 /* vel */, true /* expand */, null, true /* isClick */);
+            flingSettings(0 /* vel */, FLING_EXPAND, null /* onFinishRunnable */,
+                    true /* isClick */);
         }
     }
 
@@ -2176,7 +2263,7 @@
 
     @Override
     public boolean needsAntiFalsing() {
-        return mStatusBarState == StatusBarState.KEYGUARD;
+        return mBarState == StatusBarState.KEYGUARD;
     }
 
     @Override
@@ -2190,7 +2277,7 @@
 
     @Override
     protected boolean shouldUseDismissingAnimation() {
-        return mStatusBarState != StatusBarState.SHADE
+        return mBarState != StatusBarState.SHADE
                 && (!mStatusBar.isKeyguardCurrentlySecure() || !isTracking());
     }
 
@@ -2283,7 +2370,6 @@
     }
 
     private void updateEmptyShadeView() {
-
         // Hide "No notifications" in QS.
         mNotificationStackScroller.updateEmptyShadeView(mShowEmptyShadeView && !mQsExpanded);
     }
@@ -2311,7 +2397,7 @@
 
     @Override
     protected boolean onMiddleClicked() {
-        switch (mStatusBar.getBarState()) {
+        switch (mBarState) {
             case StatusBarState.KEYGUARD:
                 if (!mDozingOnDown) {
                     mLockscreenGestureLogger.write(
@@ -2518,7 +2604,8 @@
     }
 
     private void updateStatusBarIcons() {
-        boolean showIconsWhenExpanded = isFullWidth() && getExpandedHeight() < getOpeningHeight();
+        boolean showIconsWhenExpanded = (isPanelVisibleBecauseOfHeadsUp() || isFullWidth())
+                && getExpandedHeight() < getOpeningHeight();
         if (showIconsWhenExpanded && mNoVisibleNotifications && isOnKeyguard()) {
             showIconsWhenExpanded = false;
         }
@@ -2529,7 +2616,7 @@
     }
 
     private boolean isOnKeyguard() {
-        return mStatusBar.getBarState() == StatusBarState.KEYGUARD;
+        return mBarState == StatusBarState.KEYGUARD;
     }
 
     public void setPanelScrimMinFraction(float minFraction) {
@@ -2653,7 +2740,7 @@
         return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
     }
 
-    public void setGroupManager(NotificationGroupManager groupManager) {
+    private void setGroupManager(NotificationGroupManager groupManager) {
         mGroupManager = groupManager;
     }
 
@@ -2703,19 +2790,22 @@
     };
 
     @Override
-    public void setTouchDisabled(boolean disabled) {
-        super.setTouchDisabled(disabled);
+    public void setTouchAndAnimationDisabled(boolean disabled) {
+        super.setTouchAndAnimationDisabled(disabled);
         if (disabled && mAffordanceHelper.isSwipingInProgress() && !mIsLaunchTransitionRunning) {
             mAffordanceHelper.reset(false /* animate */);
         }
+        mNotificationStackScroller.setAnimationsEnabled(!disabled);
     }
 
-    public void setDozing(boolean dozing, boolean animate) {
+    public void setDozing(boolean dozing, boolean animate,
+            PointF wakeUpTouchLocation) {
+        mNotificationStackScroller.setDark(mDozing, animate, wakeUpTouchLocation);
         if (dozing == mDozing) return;
         mDozing = dozing;
 
-        if (mStatusBarState == StatusBarState.KEYGUARD
-                || mStatusBarState == StatusBarState.SHADE_LOCKED) {
+        if (mBarState == StatusBarState.KEYGUARD
+                || mBarState == StatusBarState.SHADE_LOCKED) {
             updateDozingVisibilities(animate);
         }
 
@@ -2729,20 +2819,28 @@
         }
         mDarkAmountTarget = darkAmount;
         if (animate) {
+            if (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f) {
+                mDarkInterpolator = dozing
+                        ? Interpolators.FAST_OUT_SLOW_IN
+                        : Interpolators.TOUCH_RESPONSE_REVERSE;
+            }
+            mNotificationStackScroller.notifyDarkAnimationStart(dozing);
             mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, darkAmount);
-            mDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-            mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
+            mDarkAnimator.setInterpolator(Interpolators.LINEAR);
+            mDarkAnimator.setDuration(mNotificationStackScroller.getDarkAnimationDuration(dozing));
             mDarkAnimator.start();
         } else {
-            setDarkAmount(darkAmount);
+            setDarkAmount(darkAmount, darkAmount);
         }
     }
 
-    private void setDarkAmount(float amount) {
-        mDarkAmount = amount;
-        mKeyguardStatusView.setDarkAmount(mDarkAmount);
-        mKeyguardBottomArea.setDarkAmount(mDarkAmount);
+    private void setDarkAmount(float linearAmount, float amount) {
+        mInterpolatedDarkAmount = amount;
+        mLinearDarkAmount = linearAmount;
+        mKeyguardStatusView.setDarkAmount(mInterpolatedDarkAmount);
+        mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount);
         positionClockAndNotifications();
+        mNotificationStackScroller.setDarkAmount(linearAmount, mInterpolatedDarkAmount);
     }
 
     public void setPulsing(boolean pulsing) {
@@ -2767,7 +2865,7 @@
     public void dozeTimeTick() {
         mKeyguardStatusView.dozeTimeTick();
         mKeyguardBottomArea.dozeTimeTick();
-        if (mDarkAmount > 0) {
+        if (mInterpolatedDarkAmount > 0) {
             positionClockAndNotifications();
         }
     }
@@ -2836,7 +2934,7 @@
      * security view of the bouncer.
      */
     public void onBouncerPreHideAnimation() {
-        setKeyguardStatusViewVisibility(mStatusBarState, true /* keyguardFadingAway */,
+        setKeyguardStatusViewVisibility(mBarState, true /* keyguardFadingAway */,
                 false /* goingToFullShade */);
     }
 
@@ -2847,4 +2945,83 @@
             mKeyguardStatusBar.dump(fd, pw, args);
         }
     }
+
+    public boolean hasActiveClearableNotifications() {
+        return mNotificationStackScroller.hasActiveClearableNotifications();
+    }
+
+    @Override
+    public void onZenChanged(int zen) {
+        updateShowEmptyShadeView();
+    }
+
+    private void updateShowEmptyShadeView() {
+        boolean showEmptyShadeView =
+                mBarState != StatusBarState.KEYGUARD &&
+                        mEntryManager.getNotificationData().getActiveNotifications().size() == 0;
+        showEmptyShadeView(showEmptyShadeView);
+    }
+
+    public RemoteInputController.Delegate createRemoteInputDelegate() {
+        return mNotificationStackScroller.createDelegate();
+    }
+
+    public void updateNotificationViews() {
+        mNotificationStackScroller.updateSpeedBumpIndex();
+        mNotificationStackScroller.updateFooter();
+        updateShowEmptyShadeView();
+    }
+
+    public void onUpdateRowStates() {
+        mNotificationStackScroller.onUpdateRowStates();
+    }
+
+    public boolean hasPulsingNotifications() {
+        return mNotificationStackScroller.hasPulsingNotifications();
+    }
+
+    public boolean isFullyDark() {
+        return mNotificationStackScroller.isFullyDark();
+    }
+
+    public ActivatableNotificationView getActivatedChild() {
+        return mNotificationStackScroller.getActivatedChild();
+    }
+
+    public void setActivatedChild(ActivatableNotificationView o) {
+        mNotificationStackScroller.setActivatedChild(o);
+    }
+
+    public void setParentNotFullyVisible(boolean parent) {
+        mNotificationStackScroller.setParentNotFullyVisible(parent);
+    }
+
+    public void runAfterAnimationFinished(Runnable r) {
+        mNotificationStackScroller.runAfterAnimationFinished(r);
+    }
+
+    public void setScrollingEnabled(boolean b) {
+        mNotificationStackScroller.setScrollingEnabled(b);
+    }
+
+    public void initDependencies(StatusBar statusBar, NotificationGroupManager groupManager,
+            NotificationShelf notificationShelf,
+            HeadsUpManagerPhone headsUpManager,
+            NotificationIconAreaController notificationIconAreaController,
+            ScrimController scrimController) {
+        setStatusBar(statusBar);
+        setGroupManager(mGroupManager);
+        mNotificationStackScroller.setNotificationPanel(this);
+        mNotificationStackScroller.setIconAreaController(notificationIconAreaController);
+        mNotificationStackScroller.setStatusBar(statusBar);
+        mNotificationStackScroller.setGroupManager(groupManager);
+        mNotificationStackScroller.setHeadsUpManager(headsUpManager);
+        mNotificationStackScroller.setShelf(notificationShelf);
+        mNotificationStackScroller.setScrimController(scrimController);
+        updateShowEmptyShadeView();
+    }
+
+    public void setDrawBackgroundAsSrc(boolean asSrc) {
+        mNotificationStackScroller.setDrawBackgroundAsSrc(asSrc);
+    }
 }
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 641f485..e7ede6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -29,13 +29,11 @@
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
 import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.notification.AboveShelfObserver;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 /**
  * The container with notification stack scroller and quick settings inside.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 5d23494..deac669e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -194,7 +194,7 @@
             pv.collapse(delayed, speedUpFactor);
             waiting = true;
         } else {
-            pv.resetViews();
+            pv.resetViews(false /* animate */);
             pv.setExpandedFraction(0); // just in case
             pv.cancelPeek();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index e4eeec1..bef34f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -45,7 +45,9 @@
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -138,6 +140,9 @@
     private boolean mGestureWaitForTouchSlop;
     private boolean mIgnoreXTouchSlop;
     private boolean mExpandLatencyTracking;
+    protected final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+    protected final StatusBarStateController
+            mStatusBarStateController = Dependency.get(StatusBarStateController.class);
 
     protected void onExpandingFinished() {
         mBar.onExpandingFinished();
@@ -222,16 +227,10 @@
     }
 
     private void trackMovement(MotionEvent event) {
-        // Add movement to velocity tracker using raw screen X and Y coordinates instead
-        // of window coordinates because the window frame may be moving at the same time.
-        float deltaX = event.getRawX() - event.getX();
-        float deltaY = event.getRawY() - event.getY();
-        event.offsetLocation(deltaX, deltaY);
         if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
-        event.offsetLocation(-deltaX, -deltaY);
     }
 
-    public void setTouchDisabled(boolean disabled) {
+    public void setTouchAndAnimationDisabled(boolean disabled) {
         mTouchDisabled = disabled;
         if (mTouchDisabled) {
             cancelHeightAnimator();
@@ -341,7 +340,7 @@
                 }
                 break;
             case MotionEvent.ACTION_POINTER_DOWN:
-                if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+                if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                     mMotionAborted = true;
                     endMotionEvent(event, x, y, true /* forceCancel */);
                     return false;
@@ -474,7 +473,7 @@
                     mStatusBar.isFalsingThresholdNeeded(),
                     mStatusBar.isWakeUpComingFromTouch());
                     // Log collapse gesture if on lock screen.
-                    if (!expand && mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+                    if (!expand && mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                         float displayDensity = mStatusBar.getDisplayDensity();
                         int heightDp = (int) Math.abs((y - mInitialTouchY) / displayDensity);
                         int velocityDp = (int) Math.abs(vel / displayDensity);
@@ -489,7 +488,7 @@
                 mUpdateFlingVelocity = vel;
             }
         } else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking
-                && !mStatusBar.isBouncerShowing() && !mStatusBar.isKeyguardFadingAway()) {
+                && !mStatusBar.isBouncerShowing() && !mKeyguardMonitor.isKeyguardFadingAway()) {
             long timePassed = SystemClock.uptimeMillis() - mDownTime;
             if (timePassed < ViewConfiguration.getLongPressTimeout()) {
                 // Lets show the user that he can actually expand the panel
@@ -603,7 +602,7 @@
                 }
                 break;
             case MotionEvent.ACTION_POINTER_DOWN:
-                if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+                if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                     mMotionAborted = true;
                     if (mVelocityTracker != null) {
                         mVelocityTracker.recycle();
@@ -1240,7 +1239,7 @@
         ));
     }
 
-    public abstract void resetViews();
+    public abstract void resetViews(boolean animate);
 
     protected abstract float getPeekHeight();
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 2516a9b..bd4d790 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -23,6 +23,7 @@
 import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
 import static com.android.systemui.OverviewProxyService.TAG_OPS;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -37,18 +38,24 @@
 import android.graphics.RadialGradient;
 import android.graphics.Rect;
 import android.graphics.Shader;
+import android.hardware.input.InputManager;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.util.FloatProperty;
 import android.util.Log;
 import android.util.Slog;
+import android.view.HapticFeedbackConstants;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewPropertyAnimator;
 import android.view.WindowManagerGlobal;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import androidx.annotation.DimenRes;
 import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
 import com.android.systemui.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
@@ -67,11 +74,27 @@
     private static final float TRACK_SCALE = 0.95f;
     private static final float GRADIENT_WIDTH = .75f;
 
+    /** Experiment to swipe home button left to execute a back key press */
+    private static final String PULL_HOME_GO_BACK_PROP = "persist.quickstepcontroller.homegoesback";
+    private static final String HIDE_BACK_BUTTON_PROP = "persist.quickstepcontroller.hideback";
+    private static final long BACK_BUTTON_FADE_OUT_ALPHA = 60;
+    private static final long BACK_BUTTON_FADE_IN_ALPHA = 150;
+    private static final long BACK_GESTURE_POLL_TIMEOUT = 1000;
+
+    /** When the home-swipe-back gesture is disallowed, make it harder to pull */
+    private static final float DISALLOW_GESTURE_DAMPING_FACTOR = 0.16f;
+
+    /** When dragging the home button too far during back gesture, make it harder to pull */
+    private static final float EXCEED_DRAG_HOME_DAMPING_FACTOR = 0.33f;
+
     private NavigationBarView mNavigationBarView;
 
     private boolean mQuickScrubActive;
     private boolean mAllowGestureDetection;
+    private boolean mBackGestureActive;
+    private boolean mCanPerformBack;
     private boolean mQuickStepStarted;
+    private boolean mNotificationsVisibleOnDown;
     private int mTouchDownX;
     private int mTouchDownY;
     private boolean mDragPositive;
@@ -83,6 +106,7 @@
     private RadialGradient mHighlight;
     private float mHighlightCenter;
     private AnimatorSet mTrackAnimator;
+    private ViewPropertyAnimator mHomeAnimator;
     private ButtonDispatcher mHitTarget;
     private View mCurrentNavigationBarView;
     private boolean mIsInScreenPinning;
@@ -92,11 +116,20 @@
     private final OverviewProxyService mOverviewEventSender;
     private final int mTrackThickness;
     private final int mTrackEndPadding;
+    private final int mHomeBackGestureDragLimit;
     private final Context mContext;
     private final Matrix mTransformGlobalMatrix = new Matrix();
     private final Matrix mTransformLocalMatrix = new Matrix();
     private final Paint mTrackPaint = new Paint();
 
+    public static boolean swipeHomeGoBackGestureEnabled() {
+        return SystemProperties.getBoolean(PULL_HOME_GO_BACK_PROP, false);
+    }
+    public static boolean shouldhideBackButton() {
+        return swipeHomeGoBackGestureEnabled()
+            && SystemProperties.getBoolean(HIDE_BACK_BUTTON_PROP, false);
+    }
+
     private final FloatProperty<QuickStepController> mTrackAlphaProperty =
             new FloatProperty<QuickStepController>("TrackAlpha") {
         @Override
@@ -150,18 +183,34 @@
         }
     };
 
+    private final Runnable mExecuteBackRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (canPerformHomeBackGesture()) {
+                performBack();
+                mHandler.postDelayed(this, BACK_GESTURE_POLL_TIMEOUT);
+            }
+        }
+    };
+
     public QuickStepController(Context context) {
         final Resources res = context.getResources();
         mContext = context;
         mOverviewEventSender = Dependency.get(OverviewProxyService.class);
         mTrackThickness = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_thickness);
         mTrackEndPadding = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_edge_padding);
+        mHomeBackGestureDragLimit =
+                res.getDimensionPixelSize(R.dimen.nav_home_back_gesture_drag_limit);
         mTrackPaint.setAntiAlias(true);
         mTrackPaint.setDither(true);
     }
 
     public void setComponents(NavigationBarView navigationBarView) {
         mNavigationBarView = navigationBarView;
+
+        mNavigationBarView.getBackButton().setVisibility(shouldhideBackButton()
+                ? View.GONE
+                : View.VISIBLE);
     }
 
     /**
@@ -190,7 +239,7 @@
                 mNavigationBarView.getDownHitTarget() == HIT_TARGET_DEAD_ZONE;
         if (mOverviewEventSender.getProxy() == null || (!mNavigationBarView.isQuickScrubEnabled()
                 && !mNavigationBarView.isQuickStepSwipeUpEnabled())) {
-            return false;
+            return deadZoneConsumed;
         }
         mNavigationBarView.requestUnbufferedDispatch(event);
 
@@ -220,7 +269,10 @@
                 mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
                 mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
                 mQuickStepStarted = false;
+                mBackGestureActive = false;
                 mAllowGestureDetection = true;
+                mNotificationsVisibleOnDown = !mNavigationBarView.isNotificationsFullyCollapsed();
+                mCanPerformBack = canPerformHomeBackGesture();
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
@@ -256,8 +308,9 @@
                 }
                 // Decide to start quickstep if dragging away from the navigation bar, otherwise in
                 // the parallel direction, decide to start quickscrub. Only one may run.
-                if (!mQuickScrubActive && exceededSwipeUpTouchSlop) {
-                    if (mNavigationBarView.isQuickStepSwipeUpEnabled()) {
+                if (!mBackGestureActive && !mQuickScrubActive && exceededSwipeUpTouchSlop) {
+                    if (mNavigationBarView.isQuickStepSwipeUpEnabled()
+                            && !mNotificationsVisibleOnDown) {
                         startQuickStep(event);
                     }
                     break;
@@ -275,10 +328,14 @@
                 final boolean allowDrag = !mDragPositive
                         ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
                 float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
-                if (allowDrag) {
+                if (!mQuickScrubActive && !mBackGestureActive && exceededScrubTouchSlop) {
                     // Passing the drag slop then touch slop will start quick step
-                    if (!mQuickScrubActive && exceededScrubTouchSlop) {
+                    if (allowDrag) {
                         startQuickScrub();
+                    } else if (swipeHomeGoBackGestureEnabled()
+                            && mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME
+                            && mDragPositive ? pos < touchDown : pos > touchDown) {
+                        startBackGesture();
                     }
                 }
 
@@ -294,22 +351,53 @@
                     }
                     mHighlightCenter = x;
                     mNavigationBarView.invalidate();
+                } else if (mBackGestureActive) {
+                    int diff = pos - touchDown;
+                    // If dragging the incorrect direction after starting back gesture or unable
+                    // to execute back functionality, then move home but dampen its distance
+                    if (!mCanPerformBack || (mDragPositive ? diff > 0 : diff < 0)) {
+                        diff *= DISALLOW_GESTURE_DAMPING_FACTOR;
+                    } if (Math.abs(diff) > mHomeBackGestureDragLimit) {
+                        // Once the user drags the home button past a certain limit, the distance
+                        // will lessen as the home button dampens showing that it was pulled too far
+                        float distanceAfterDragLimit = (Math.abs(diff) - mHomeBackGestureDragLimit)
+                                * EXCEED_DRAG_HOME_DAMPING_FACTOR;
+                        diff = (int)(distanceAfterDragLimit + mHomeBackGestureDragLimit);
+                        if (mDragPositive) {
+                            diff *= -1;
+                        }
+                    }
+                    moveHomeButton(diff);
                 }
                 break;
             }
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP:
                 endQuickScrub(true /* animate */);
+                endBackGesture();
                 break;
         }
 
-        // Proxy motion events to launcher if not handled by quick scrub
-        // Proxy motion events up/cancel that would be sent after long press on any nav button
-        if (!mQuickScrubActive && !mIsInScreenPinning && (mAllowGestureDetection
-                || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP)) {
+        if (shouldProxyEvents(action)) {
             proxyMotionEvents(event);
         }
-        return mQuickScrubActive || mQuickStepStarted || deadZoneConsumed;
+        return mBackGestureActive || mQuickScrubActive || mQuickStepStarted || deadZoneConsumed;
+    }
+
+    private boolean shouldProxyEvents(int action) {
+        if (!mBackGestureActive && !mQuickScrubActive && !mIsInScreenPinning) {
+            // Allow down, cancel and up events, move and other events are passed if notifications
+            // are not showing and disabled gestures (such as long press) are not executed
+            switch (action) {
+                case MotionEvent.ACTION_DOWN:
+                case MotionEvent.ACTION_CANCEL:
+                case MotionEvent.ACTION_UP:
+                    return true;
+                default:
+                    return !mNotificationsVisibleOnDown && mAllowGestureDetection;
+            }
+        }
+        return false;
     }
 
     @Override
@@ -488,6 +576,42 @@
         }
     }
 
+    private void startBackGesture() {
+        if (!mBackGestureActive) {
+            mBackGestureActive = true;
+            mNavigationBarView.getHomeButton().abortCurrentGesture();
+            if (mCanPerformBack) {
+                if (!shouldhideBackButton()) {
+                    mNavigationBarView.getBackButton().setAlpha(0 /* alpha */, true /* animate */,
+                            BACK_BUTTON_FADE_OUT_ALPHA);
+                }
+                performBack();
+            }
+            mHandler.removeCallbacks(mExecuteBackRunnable);
+            mHandler.postDelayed(mExecuteBackRunnable, BACK_GESTURE_POLL_TIMEOUT);
+        }
+    }
+
+    private void endBackGesture() {
+        if (mBackGestureActive) {
+            mHandler.removeCallbacks(mExecuteBackRunnable);
+            mHomeAnimator = mNavigationBarView.getHomeButton().getCurrentView()
+                    .animate()
+                    .setDuration(BACK_BUTTON_FADE_IN_ALPHA)
+                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+            if (mIsVertical) {
+                mHomeAnimator.translationY(0);
+            } else {
+                mHomeAnimator.translationX(0);
+            }
+            mHomeAnimator.start();
+            if (!shouldhideBackButton()) {
+                mNavigationBarView.getBackButton().setAlpha(
+                        mOverviewEventSender.getBackButtonAlpha(), true /* animate */);
+            }
+        }
+    }
+
     private void animateEnd() {
         if (mTrackAnimator != null) {
             mTrackAnimator.cancel();
@@ -510,10 +634,26 @@
     private void resetQuickScrub() {
         mQuickScrubActive = false;
         mAllowGestureDetection = false;
+        if (mCurrentNavigationBarView != null) {
+            mCurrentNavigationBarView.setAlpha(1f);
+        }
         mCurrentNavigationBarView = null;
         updateHighlight();
     }
 
+    private void moveHomeButton(float pos) {
+        if (mHomeAnimator != null) {
+            mHomeAnimator.cancel();
+            mHomeAnimator = null;
+        }
+        final View homeButton = mNavigationBarView.getHomeButton().getCurrentView();
+        if (mIsVertical) {
+            homeButton.setTranslationY(pos);
+        } else {
+            homeButton.setTranslationX(pos);
+        }
+    }
+
     private void updateHighlight() {
         if (mTrackRect.isEmpty()) {
             return;
@@ -532,6 +672,25 @@
         mTrackPaint.setShader(mHighlight);
     }
 
+    private boolean canPerformHomeBackGesture() {
+        return swipeHomeGoBackGestureEnabled() && mOverviewEventSender.getBackButtonAlpha() > 0;
+    }
+
+    private void performBack() {
+        sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
+        sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
+        mNavigationBarView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+    }
+
+    private void sendEvent(int action, int code) {
+        long when = SystemClock.uptimeMillis();
+        final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
+                0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
+                KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+                InputDevice.SOURCE_KEYBOARD);
+        InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+    }
+
     private boolean proxyMotionEvents(MotionEvent event) {
         final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
         event.transform(mTransformGlobalMatrix);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index f573642..0c361ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -47,7 +47,7 @@
 import com.android.systemui.R;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.statusbar.ScrimView;
-import com.android.systemui.statusbar.stack.ViewState;
+import com.android.systemui.statusbar.notification.stack.ViewState;
 import com.android.systemui.util.AlarmTimeout;
 import com.android.systemui.util.wakelock.DelayedWakeLock;
 import com.android.systemui.util.wakelock.WakeLock;
@@ -113,6 +113,7 @@
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final DozeParameters mDozeParameters;
     private final AlarmTimeout mTimeTicker;
+    private final KeyguardVisibilityCallback mKeyguardVisibilityCallback;
 
     private final SysuiColorExtractor mColorExtractor;
     private GradientColors mLockColors;
@@ -171,6 +172,8 @@
         mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
         mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
         mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+        mKeyguardVisibilityCallback = new KeyguardVisibilityCallback();
+        mKeyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
         mScrimBehindAlphaResValue = mContext.getResources().getFloat(R.dimen.scrim_behind_alpha);
         mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout,
                 "hide_aod_wallpaper", new Handler());
@@ -892,6 +895,16 @@
         for (ScrimState state : ScrimState.values()) {
             state.setHasBackdrop(hasBackdrop);
         }
+
+        // Backdrop event may arrive after state was already applied,
+        // in this case, back-scrim needs to be re-evaluated
+        if (mState == ScrimState.AOD || mState == ScrimState.PULSING) {
+            float newBehindAlpha = mState.getBehindAlpha(mNotificationDensity);
+            if (mCurrentBehindAlpha != newBehindAlpha) {
+                mCurrentBehindAlpha = newBehindAlpha;
+                updateScrims();
+            }
+        }
     }
 
     public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) {
@@ -910,4 +923,16 @@
         default void onCancelled() {
         }
     }
+
+    /**
+     * Simple keyguard callback that updates scrims when keyguard visibility changes.
+     */
+    private class KeyguardVisibilityCallback extends KeyguardUpdateMonitorCallback {
+
+        @Override
+        public void onKeyguardVisibilityChanged(boolean showing) {
+            mNeedsDrawableColorUpdate = true;
+            scheduleUpdate();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index cdbad59..085f7b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -21,7 +21,7 @@
 import android.util.MathUtils;
 
 import com.android.systemui.statusbar.ScrimView;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 /**
  * Possible states of the ScrimController state machine.
@@ -105,7 +105,6 @@
         public void prepare(ScrimState previousState) {
             final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
             mBlankScreen = mDisplayRequiresBlanking;
-            mCurrentBehindAlpha = mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
             mCurrentInFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f;
             mCurrentInFrontTint = Color.BLACK;
             mCurrentBehindTint = Color.BLACK;
@@ -116,6 +115,11 @@
         }
 
         @Override
+        public float getBehindAlpha(float busyness) {
+            return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
+        }
+
+        @Override
         public boolean isLowPowerState() {
             return true;
         }
@@ -129,10 +133,14 @@
         public void prepare(ScrimState previousState) {
             mCurrentInFrontAlpha = 0;
             mCurrentInFrontTint = Color.BLACK;
-            mCurrentBehindAlpha = mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
             mCurrentBehindTint = Color.BLACK;
             mBlankScreen = mDisplayRequiresBlanking;
         }
+
+        @Override
+        public float getBehindAlpha(float busyness) {
+            return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
+        }
     },
 
     /**
@@ -146,7 +154,7 @@
             mAnimationDuration = StatusBar.FADE_KEYGUARD_DURATION;
             mAnimateChange = !mLaunchingAffordanceWithPreview;
 
-            if (previousState == ScrimState.AOD || previousState == ScrimState.PULSING) {
+            if (previousState == ScrimState.AOD) {
                 // Fade from black to transparent when coming directly from AOD
                 updateScrimColor(mScrimInFront, 1, Color.BLACK);
                 updateScrimColor(mScrimBehind, 1, Color.BLACK);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadowKeyDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadowKeyDrawable.java
index 2471e34..8bd8048 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadowKeyDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadowKeyDrawable.java
@@ -28,8 +28,6 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 
-import com.android.systemui.R;
-
 /**
  * A drawable which adds shadow around a child drawable.
  */
@@ -60,6 +58,23 @@
         }
     }
 
+    public void setTranslationX(float x) {
+        setTranslation(x, mState.mTranslationY);
+    }
+
+    public void setTranslationY(float y) {
+        setTranslation(mState.mTranslationX, y);
+    }
+
+    public void setTranslation(float x, float y) {
+        if (mState.mTranslationX != x || mState.mTranslationY != y) {
+            mState.mTranslationX = x;
+            mState.mTranslationY = y;
+            mState.mLastDrawnBitmap = null;
+            invalidateSelf();
+        }
+    }
+
     public void setShadowProperties(int x, int y, int size, int color) {
         if (mState.mShadowOffsetX != x || mState.mShadowOffsetY != y
                 || mState.mShadowSize != size || mState.mShadowColor != color) {
@@ -76,6 +91,14 @@
         return mState.mRotateDegrees;
     }
 
+    public float getTranslationX() {
+        return mState.mTranslationX;
+    }
+
+    public float getTranslationY() {
+        return mState.mTranslationY;
+    }
+
     @Override
     public void draw(Canvas canvas) {
         Rect bounds = getBounds();
@@ -151,6 +174,7 @@
         // Call mutate, so that the pixel allocation by the underlying vector drawable is cleared.
         final Drawable d = mState.mChildState.newDrawable().mutate();
         d.setBounds(0, 0, mState.mBaseWidth, mState.mBaseHeight);
+        canvas.translate(mState.mTranslationX, mState.mTranslationY);
         d.draw(canvas);
 
         if (mState.mShadowSize > 0) {
@@ -168,9 +192,9 @@
             canvas.rotate(mState.mRotateDegrees, width / 2, height / 2);
 
             final float shadowOffsetX = (float) (Math.sin(radians) * mState.mShadowOffsetY
-                    + Math.cos(radians) * mState.mShadowOffsetX);
+                    + Math.cos(radians) * mState.mShadowOffsetX) - mState.mTranslationX;
             final float shadowOffsetY = (float) (Math.cos(radians) * mState.mShadowOffsetY
-                    - Math.sin(radians) * mState.mShadowOffsetX);
+                    - Math.sin(radians) * mState.mShadowOffsetX) - mState.mTranslationY;
 
             canvas.drawBitmap(shadow, offset[0] + shadowOffsetX, offset[1] + shadowOffsetY, paint);
             d.draw(canvas);
@@ -189,6 +213,8 @@
         int mBaseWidth;
         int mBaseHeight;
         float mRotateDegrees;
+        float mTranslationX;
+        float mTranslationY;
         int mShadowOffsetX;
         int mShadowOffsetY;
         int mShadowSize;
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 ae1da56..6d742cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -56,7 +56,6 @@
 import android.app.StatusBarManager;
 import android.app.TaskStackBuilder;
 import android.app.UiModeManager;
-import android.app.WallpaperColors;
 import android.app.WallpaperInfo;
 import android.app.WallpaperManager;
 import android.app.admin.DevicePolicyManager;
@@ -67,8 +66,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
-import android.content.om.IOverlayManager;
-import android.content.om.OverlayInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -151,6 +148,7 @@
 import com.android.systemui.AutoReinflateContainer;
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.Interpolators;
 import com.android.systemui.Prefs;
@@ -188,26 +186,25 @@
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.stackdivider.WindowManagerProxy;
-import com.android.systemui.statusbar.ActivatableNotificationView;
-import com.android.systemui.statusbar.AppOpsListener;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.AppOpsListener;
 import com.android.systemui.statusbar.BackDropView;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.EmptyShadeView;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.FooterView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyboardShortcuts;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationData.Entry;
-import com.android.systemui.statusbar.NotificationEntryManager;
-import com.android.systemui.statusbar.NotificationGutsManager;
-import com.android.systemui.statusbar.NotificationInfo;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationData.Entry;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.row.NotificationInfo;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationLogger;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -215,11 +212,13 @@
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.ScrimView;
-import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.AboveShelfObserver;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -243,20 +242,19 @@
 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.volume.VolumeComponent;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 
 public class StatusBar extends SystemUI implements DemoMode,
-        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
+        ActivityStarter, OnUnlockMethodChangedListener,
         OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
-        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {
+        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter,
+        StatusBarStateController.StateListener {
     public static final boolean MULTIUSER_DEBUG = false;
 
     public static final boolean ENABLE_CHILD_NOTIFICATIONS
@@ -330,12 +328,6 @@
     /** If true, the lockscreen will show a distinct wallpaper */
     private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
 
-    /** Whether to force dark theme if Configuration.UI_MODE_NIGHT_YES. */
-    private static final boolean DARK_THEME_IN_NIGHT_MODE = true;
-
-    /** Whether to switch the device into night mode in battery saver. */
-    private static final boolean NIGHT_MODE_IN_BATTERY_SAVER = true;
-
     /**
      * Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode
      * won't draw anything and uninitialized memory will show through
@@ -379,7 +371,7 @@
     protected StatusBarWindowView mStatusBarWindow;
     protected PhoneStatusBarView mStatusBarView;
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
-    protected StatusBarWindowManager mStatusBarWindowManager;
+    protected StatusBarWindowController mStatusBarWindowController;
     protected UnlockMethodCache mUnlockMethodCache;
     private DozeServiceHost mDozeServiceHost = new DozeServiceHost();
     private boolean mWakeUpComingFromTouch;
@@ -398,14 +390,8 @@
 
     // top bar
     private KeyguardStatusBarView mKeyguardStatusBar;
-    private boolean mLeaveOpenOnKeyguardHide;
     KeyguardIndicationController mKeyguardIndicationController;
 
-    // Keyguard is actually fading away now.
-    protected boolean mKeyguardFadingAway;
-    protected long mKeyguardFadingAwayDelay;
-    protected long mKeyguardFadingAwayDuration;
-
     // RemoteInputView to be activated after unlock
     private View mPendingRemoteInputView;
     private View mPendingWorkRemoteInputView;
@@ -438,12 +424,11 @@
     private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
     private final Rect mLastFullscreenStackBounds = new Rect();
     private final Rect mLastDockedStackBounds = new Rect();
-    private final Rect mTmpRect = new Rect();
 
     // last value sent to window manager
     private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
 
-    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+    private final DisplayMetrics mDisplayMetrics = Dependency.get(DisplayMetrics.class);
 
     // XXX: gesture research
     private final GestureRecorder mGestureRec = DEBUG_GESTURES
@@ -522,9 +507,9 @@
             }
             WallpaperInfo info = wallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
             final boolean supportsAmbientMode = info != null &&
-                    info.getSupportsAmbientMode();
+                    info.supportsAmbientMode();
 
-            mStatusBarWindowManager.setWallpaperSupportsAmbientMode(supportsAmbientMode);
+            mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
             mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
         }
     };
@@ -562,7 +547,7 @@
                         + "mStatusBarKeyguardViewManager was null");
                 return;
             }
-            if (mKeyguardFadingAway) {
+            if (mKeyguardMonitor.isKeyguardFadingAway()) {
                 mStatusBarKeyguardViewManager.onKeyguardFadedAway();
             }
         }
@@ -580,14 +565,14 @@
             = (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class);
     private BatteryController mBatteryController;
     protected boolean mPanelExpanded;
-    private IOverlayManager mOverlayManager;
+    private UiModeManager mUiModeManager;
     private boolean mKeyguardRequested;
     private boolean mIsKeyguard;
     private LogMaker mStatusBarStateLog;
-    private final LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
+    private final LockscreenGestureLogger mLockscreenGestureLogger =
+            Dependency.get(LockscreenGestureLogger.class);
     protected NotificationIconAreaController mNotificationIconAreaController;
     private boolean mReinflateNotificationsOnUserSwitched;
-    protected boolean mClearAllEnabled;
     @Nullable private View mAmbientIndicationContainer;
     private SysuiColorExtractor mColorExtractor;
     private ScreenLifecycle mScreenLifecycle;
@@ -601,6 +586,8 @@
     };
     private boolean mNoAnimationOnNextBarModeChange;
     protected FalsingManager mFalsingManager;
+    private final StatusBarStateController
+            mStatusBarStateController = Dependency.get(StatusBarStateController.class);
 
     private final KeyguardUpdateMonitorCallback mUpdateCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -641,8 +628,7 @@
         mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
         mBatteryController = Dependency.get(BatteryController.class);
         mAssistManager = Dependency.get(AssistManager.class);
-        mOverlayManager = IOverlayManager.Stub.asInterface(
-                ServiceManager.getService(Context.OVERLAY_SERVICE));
+        mUiModeManager = mContext.getSystemService(UiModeManager.class);
         mLockscreenUserManager = Dependency.get(NotificationLockscreenUserManager.class);
         mGutsManager = Dependency.get(NotificationGutsManager.class);
         mMediaManager = Dependency.get(NotificationMediaManager.class);
@@ -655,6 +641,7 @@
 
         mColorExtractor = Dependency.get(SysuiColorExtractor.class);
         mColorExtractor.addOnColorsChangedListener(this);
+        mStatusBarStateController.addListener(this);
 
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
 
@@ -666,7 +653,6 @@
                 R.bool.config_vibrateOnIconAnimation);
         mVibratorHelper = Dependency.get(VibratorHelper.class);
         mScrimSrcModeEnabled = res.getBoolean(R.bool.config_status_bar_scrim_behind_use_src);
-        mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
 
         DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER));
         putComponent(StatusBar.class, this);
@@ -808,12 +794,13 @@
         // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
         mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
         mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
+        NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
         mZenController.addCallback(this);
         mActivityLaunchAnimator = new ActivityLaunchAnimator(mStatusBarWindow,
                 this,
                 mNotificationPanel,
-                mStackScroller);
-        mGutsManager.setUpWithPresenter(this, mEntryManager, mStackScroller, mCheckSaveListener,
+                notifListContainer);
+        mGutsManager.setUpWithPresenter(this, mEntryManager, notifListContainer, mCheckSaveListener,
                 key -> {
                     try {
                         mBarService.onNotificationSettingsViewed(key);
@@ -821,9 +808,7 @@
                         // if we're here we're dead
                     }
                 });
-        mNotificationLogger.setUpWithEntryManager(mEntryManager, mStackScroller);
-        mNotificationPanel.setStatusBar(this);
-        mNotificationPanel.setGroupManager(mGroupManager);
+        mNotificationLogger.setUpWithEntryManager(mEntryManager, notifListContainer);
         mAboveShelfObserver = new AboveShelfObserver(mStackScroller);
         mAboveShelfObserver.setListener(mStatusBarWindow.findViewById(
                 R.id.notification_container_parent));
@@ -833,7 +818,7 @@
                 .createNotificationIconAreaController(context, this);
         inflateShelf();
         mNotificationIconAreaController.setupShelf(mNotificationShelf);
-        mStackScroller.setIconAreaController(mNotificationIconAreaController);
+
         Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
         FragmentHostManager.get(mStatusBarWindow)
                 .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
@@ -892,8 +877,8 @@
         mGroupManager.setHeadsUpManager(mHeadsUpManager);
         putComponent(HeadsUpManager.class, mHeadsUpManager);
 
-        mEntryManager.setUpWithPresenter(this, mStackScroller, this, mHeadsUpManager);
-        mViewHierarchyManager.setUpWithPresenter(this, mEntryManager, mStackScroller);
+        mEntryManager.setUpWithPresenter(this, notifListContainer, this, mHeadsUpManager);
+        mViewHierarchyManager.setUpWithPresenter(this, mEntryManager, notifListContainer);
 
         if (MULTIUSER_DEBUG) {
             mNotificationPanelDebugText = mNotificationPanel.findViewById(R.id.header_debug_info);
@@ -909,15 +894,6 @@
         } catch (RemoteException ex) {
             // no window manager? good luck with that
         }
-        mStackScroller.setLongPressListener(mEntryManager.getNotificationLongClicker());
-        mStackScroller.setStatusBar(this);
-        mStackScroller.setGroupManager(mGroupManager);
-        mStackScroller.setHeadsUpManager(mHeadsUpManager);
-        mGroupManager.setOnGroupChangeListener(mStackScroller);
-        mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller);
-
-        inflateEmptyShadeView();
-        inflateFooterView();
 
         mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop);
         mBackdropFront = mBackdrop.findViewById(R.id.backdrop_front);
@@ -948,10 +924,6 @@
                 if (mDozeServiceHost != null) {
                     mDozeServiceHost.firePowerSaveChanged(isPowerSave);
                 }
-                if (NIGHT_MODE_IN_BATTERY_SAVER) {
-                    mContext.getSystemService(UiModeManager.class).setNightMode(
-                        isPowerSave ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO);
-                }
             }
 
             @Override
@@ -971,8 +943,8 @@
                 scrimBehind, scrimInFront, mLockscreenWallpaper,
                 (state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color),
                 scrimsVisible -> {
-                    if (mStatusBarWindowManager != null) {
-                        mStatusBarWindowManager.setScrimsVisibility(scrimsVisible);
+                    if (mStatusBarWindowController != null) {
+                        mStatusBarWindowController.setScrimsVisibility(scrimsVisible);
                     }
                 }, DozeParameters.getInstance(mContext),
                 mContext.getSystemService(AlarmManager.class));
@@ -980,12 +952,13 @@
             Runnable runnable = () -> {
                 boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE;
                 mScrimController.setDrawBehindAsSrc(asSrc);
-                mStackScroller.setDrawBackgroundAsSrc(asSrc);
+                mNotificationPanel.setDrawBackgroundAsSrc(asSrc);
             };
             mBackdrop.setOnVisibilityChangedRunnable(runnable);
             runnable.run();
         }
-        mStackScroller.setScrimController(mScrimController);
+        mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf,
+                mHeadsUpManager, mNotificationIconAreaController, mScrimController);
         mDozeScrimController = new DozeScrimController(mScrimController, context,
                 DozeParameters.getInstance(context));
 
@@ -1127,11 +1100,10 @@
                 (NotificationShelf) LayoutInflater.from(mContext).inflate(
                         R.layout.status_bar_notification_shelf, mStackScroller, false);
         mNotificationShelf.setOnActivatedListener(this);
-        mStackScroller.setShelf(mNotificationShelf);
         mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
-        mNotificationShelf.setStatusBarState(mState);
     }
 
+    @Override
     public void onDensityOrFontScaleChanged() {
         MessagingMessage.dropCache();
         MessagingGroup.dropCache();
@@ -1156,17 +1128,10 @@
         }
         mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
         mHeadsUpManager.onDensityOrFontScaleChanged();
-
-        inflateFooterView();
-        inflateEmptyShadeView();
-        reevaluateStyles();
     }
 
-    private void onThemeChanged() {
-        reevaluateStyles();
-
-        // Clock and bottom icons
-        mNotificationPanel.onThemeChanged();
+    @Override
+    public void onThemeChanged() {
         // The status bar on the keyguard is a special layout.
         if (mKeyguardStatusBar != null) mKeyguardStatusBar.onThemeChanged();
         // Recreate Indication controller because internal references changed
@@ -1187,11 +1152,6 @@
         }
     }
 
-    private void reevaluateStyles() {
-        updateFooter();
-        updateEmptyShadeView();
-    }
-
     @Override
     public void onOverlayChanged() {
         if (mBrightnessMirrorController != null) {
@@ -1199,32 +1159,16 @@
         }
     }
 
-    private void inflateEmptyShadeView() {
-        if (mStackScroller == null) {
-            return;
-        }
-        mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
-                R.layout.status_bar_no_notifications, mStackScroller, false);
-        mEmptyShadeView.setText(R.string.empty_shade_text);
-        mStackScroller.setEmptyShadeView(mEmptyShadeView);
-    }
+    @Override
+    public void onUiModeChanged() {
+        // UiMode will change the style was already evaluated.
+        // We need to force the re-evaluation to make sure that all parents
+        // are up to date and new attrs will be rettrieved.
+        mContext.getTheme().applyStyle(mContext.getThemeResId(), true);
 
-    @VisibleForTesting
-    protected void inflateFooterView() {
-        if (mStackScroller == null) {
-            return;
+        if (mBrightnessMirrorController != null) {
+            mBrightnessMirrorController.onUiModeChanged();
         }
-
-        mFooterView = (FooterView) LayoutInflater.from(mContext).inflate(
-                R.layout.status_bar_notification_footer, mStackScroller, false);
-        mFooterView.setDismissButtonClickListener(v -> {
-            mMetricsLogger.action(MetricsEvent.ACTION_DISMISS_ALL_NOTES);
-            clearAllNotifications();
-        });
-        mFooterView.setManageButtonClickListener(v -> {
-            manageNotifications();
-        });
-        mStackScroller.setFooterView(mFooterView);
     }
 
     protected void createUserSwitcher() {
@@ -1238,105 +1182,6 @@
                 R.layout.super_status_bar, null);
     }
 
-    public void manageNotifications() {
-        Intent intent = new Intent(Settings.ACTION_ALL_APPS_NOTIFICATION_SETTINGS);
-        startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP);
-    }
-
-    public void clearAllNotifications() {
-        // animate-swipe all dismissable notifications, then animate the shade closed
-        int numChildren = mStackScroller.getChildCount();
-
-        final ArrayList<View> viewsToHide = new ArrayList<>(numChildren);
-        final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren);
-        for (int i = 0; i < numChildren; i++) {
-            final View child = mStackScroller.getChildAt(i);
-            if (child instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                boolean parentVisible = false;
-                boolean hasClipBounds = child.getClipBounds(mTmpRect);
-                if (mStackScroller.canChildBeDismissed(child)) {
-                    viewsToRemove.add(row);
-                    if (child.getVisibility() == View.VISIBLE
-                            && (!hasClipBounds || mTmpRect.height() > 0)) {
-                        viewsToHide.add(child);
-                        parentVisible = true;
-                    }
-                } else if (child.getVisibility() == View.VISIBLE
-                        && (!hasClipBounds || mTmpRect.height() > 0)) {
-                    parentVisible = true;
-                }
-                List<ExpandableNotificationRow> children = row.getNotificationChildren();
-                if (children != null) {
-                    for (ExpandableNotificationRow childRow : children) {
-                        viewsToRemove.add(childRow);
-                        if (parentVisible && row.areChildrenExpanded()
-                                && mStackScroller.canChildBeDismissed(childRow)) {
-                            hasClipBounds = childRow.getClipBounds(mTmpRect);
-                            if (childRow.getVisibility() == View.VISIBLE
-                                    && (!hasClipBounds || mTmpRect.height() > 0)) {
-                                viewsToHide.add(childRow);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        if (viewsToRemove.isEmpty()) {
-            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
-            return;
-        }
-
-        addPostCollapseAction(() -> {
-            mStackScroller.setDismissAllInProgress(false);
-            for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
-                if (mStackScroller.canChildBeDismissed(rowToRemove)) {
-                    mEntryManager.removeNotification(rowToRemove.getEntry().key, null);
-                } else {
-                    rowToRemove.resetTranslation();
-                }
-            }
-            try {
-                mBarService.onClearAllNotifications(mLockscreenUserManager.getCurrentUserId());
-            } catch (Exception ex) {
-            }
-        });
-
-        performDismissAllAnimations(viewsToHide);
-
-    }
-
-    private void performDismissAllAnimations(ArrayList<View> hideAnimatedList) {
-        Runnable animationFinishAction = () -> {
-            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
-        };
-
-        if (hideAnimatedList.isEmpty()) {
-            animationFinishAction.run();
-            return;
-        }
-
-        // let's disable our normal animations
-        mStackScroller.setDismissAllInProgress(true);
-
-        // Decrease the delay for every row we animate to give the sense of
-        // accelerating the swipes
-        int rowDelayDecrement = 10;
-        int currentDelay = 140;
-        int totalDelay = 180;
-        int numItems = hideAnimatedList.size();
-        for (int i = numItems - 1; i >= 0; i--) {
-            View view = hideAnimatedList.get(i);
-            Runnable endRunnable = null;
-            if (i == 0) {
-                endRunnable = animationFinishAction;
-            }
-            mStackScroller.dismissViewAnimated(view, endRunnable, totalDelay, 260);
-            currentDelay = Math.max(50, currentDelay - rowDelayDecrement);
-            totalDelay += currentDelay;
-        }
-    }
-
     protected void startKeyguard() {
         Trace.beginSection("StatusBar#startKeyguard");
         KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
@@ -1409,8 +1254,8 @@
 
     @Override
     public void onPerformRemoveNotification(StatusBarNotification n) {
-        if (mStackScroller.hasPulsingNotifications() &&
-                    !mHeadsUpManager.hasHeadsUpNotifications()) {
+        if (mNotificationPanel.hasPulsingNotifications() &&
+                    !mHeadsUpManager.hasNotifications()) {
             // We were showing a pulse for a notification, but no notifications are pulsing anymore.
             // Finish the pulse.
             mDozeScrimController.pulseOutNow();
@@ -1421,7 +1266,7 @@
     public void updateNotificationViews() {
         // The function updateRowStates depends on both of these being non-null, so check them here.
         // We may be called before they are set from DeviceProvisionedController's callback.
-        if (mStackScroller == null || mScrimController == null) return;
+        if (mScrimController == null) return;
 
         // Do not modify the notifications during collapse.
         if (isCollapsing()) {
@@ -1431,9 +1276,7 @@
 
         mViewHierarchyManager.updateNotificationViews();
 
-        updateSpeedBumpIndex();
-        updateFooter();
-        updateEmptyShadeView();
+        mNotificationPanel.updateNotificationViews();
 
         updateQsExpansionEnabled();
 
@@ -1500,61 +1343,6 @@
         mQSPanel.clickTile(tile);
     }
 
-    @VisibleForTesting
-    protected void updateFooter() {
-        boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications();
-        boolean showFooterView = (showDismissView ||
-                        mEntryManager.getNotificationData().getActiveNotifications().size() != 0)
-                && mState != StatusBarState.KEYGUARD
-                && !mRemoteInputManager.getController().isRemoteInputActive();
-
-        mStackScroller.updateFooterView(showFooterView, showDismissView);
-    }
-
-    /**
-     * Return whether there are any clearable notifications
-     */
-    private boolean hasActiveClearableNotifications() {
-        int childCount = mStackScroller.getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = mStackScroller.getChildAt(i);
-            if (!(child instanceof ExpandableNotificationRow)) {
-                continue;
-            }
-            if (((ExpandableNotificationRow) child).canViewBeDismissed()) {
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    private void updateEmptyShadeView() {
-        boolean showEmptyShadeView =
-                mState != StatusBarState.KEYGUARD &&
-                        mEntryManager.getNotificationData().getActiveNotifications().size() == 0;
-        mNotificationPanel.showEmptyShadeView(showEmptyShadeView);
-    }
-
-    private void updateSpeedBumpIndex() {
-        int speedBumpIndex = 0;
-        int currentIndex = 0;
-        final int N = mStackScroller.getChildCount();
-        for (int i = 0; i < N; i++) {
-            View view = mStackScroller.getChildAt(i);
-            if (view.getVisibility() == View.GONE || !(view instanceof ExpandableNotificationRow)) {
-                continue;
-            }
-            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-            currentIndex++;
-            if (!mEntryManager.getNotificationData().isAmbient(
-                    row.getStatusBarNotification().getKey())) {
-                speedBumpIndex = currentIndex;
-            }
-        }
-        boolean noAmbient = speedBumpIndex == N;
-        mStackScroller.updateSpeedBumpIndex(speedBumpIndex, noAmbient);
-    }
-
     public static boolean isTopLevelChild(Entry entry) {
         return entry.row.getParent() instanceof NotificationStackScrollLayout;
     }
@@ -1571,7 +1359,7 @@
 
         if (SPEW) {
             final boolean clearable = hasActiveNotifications() &&
-                    hasActiveClearableNotifications();
+                    mNotificationPanel.hasActiveClearableNotifications();
             Log.d(TAG, "setAreThereNotifications: N=" +
                     mEntryManager.getNotificationData().getActiveNotifications().size() + " any=" +
                     hasActiveNotifications() + " clearable=" + clearable);
@@ -1701,7 +1489,7 @@
                     mBackdrop.animate().cancel();
                     mBackdrop.setAlpha(1f);
                 }
-                mStatusBarWindowManager.setBackdropShowing(true);
+                mStatusBarWindowController.setBackdropShowing(true);
                 metaDataChanged = true;
                 if (DEBUG_MEDIA) {
                     Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
@@ -1761,9 +1549,9 @@
                     // We are unlocking directly - no animation!
                     mBackdrop.setVisibility(View.GONE);
                     mBackdropBack.setImageDrawable(null);
-                    mStatusBarWindowManager.setBackdropShowing(false);
+                    mStatusBarWindowController.setBackdropShowing(false);
                 } else {
-                    mStatusBarWindowManager.setBackdropShowing(false);
+                    mStatusBarWindowController.setBackdropShowing(false);
                     mBackdrop.animate()
                             .alpha(SRC_MIN_ALPHA)
                             .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
@@ -1775,12 +1563,12 @@
                                 mBackdropBack.setImageDrawable(null);
                                 mHandler.post(mHideBackdropFront);
                             });
-                    if (mKeyguardFadingAway) {
+                    if (mKeyguardMonitor.isKeyguardFadingAway()) {
                         mBackdrop.animate()
                                 // Make it disappear faster, as the focus should be on the activity
                                 // behind.
-                                .setDuration(mKeyguardFadingAwayDuration / 2)
-                                .setStartDelay(mKeyguardFadingAwayDelay)
+                                .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2)
+                                .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
                                 .setInterpolator(Interpolators.LINEAR)
                                 .start();
                     }
@@ -1885,7 +1673,7 @@
     /**
      * Reapplies the disable flags as last requested by StatusBarManager.
      *
-     * This needs to be called if state used by {@link #adjustDisableFlags} changes.
+     * This needs to be called if state used by adjustDisableFlags changes.
      */
     public void recomputeDisableFlags(boolean animate) {
         mCommandQueue.recomputeDisableFlags(animate);
@@ -1895,7 +1683,7 @@
         return new StatusBar.H();
     }
 
-    private void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
+    public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
             int flags) {
         startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags);
     }
@@ -1917,27 +1705,23 @@
     }
 
     public void setQsExpanded(boolean expanded) {
-        mStatusBarWindowManager.setQsExpanded(expanded);
+        mStatusBarWindowController.setQsExpanded(expanded);
         mNotificationPanel.setStatusAccessibilityImportance(expanded
                 ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
                 : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
     }
 
-    public boolean isGoingToNotificationShade() {
-        return mLeaveOpenOnKeyguardHide;
-    }
-
     public boolean isWakeUpComingFromTouch() {
         return mWakeUpComingFromTouch;
     }
 
     public boolean isFalsingThresholdNeeded() {
-        return getBarState() == StatusBarState.KEYGUARD;
+        return mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
     }
 
     @Override
     public boolean isDozing() {
-        return mDozing && mStackScroller.isFullyDark();
+        return mDozing && mNotificationPanel.isFullyDark();
     }
 
     @Override
@@ -2000,31 +1784,31 @@
     @Override
     public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
         if (inPinnedMode) {
-            mStatusBarWindowManager.setHeadsUpShowing(true);
-            mStatusBarWindowManager.setForceStatusBarVisible(true);
+            mStatusBarWindowController.setHeadsUpShowing(true);
+            mStatusBarWindowController.setForceStatusBarVisible(true);
             if (mNotificationPanel.isFullyCollapsed()) {
                 // We need to ensure that the touchable region is updated before the window will be
                 // resized, in order to not catch any touches. A layout will ensure that
                 // onComputeInternalInsets will be called and after that we can resize the layout. Let's
                 // make sure that the window stays small for one frame until the touchableRegion is set.
                 mNotificationPanel.requestLayout();
-                mStatusBarWindowManager.setForceWindowCollapsed(true);
+                mStatusBarWindowController.setForceWindowCollapsed(true);
                 mNotificationPanel.post(() -> {
-                    mStatusBarWindowManager.setForceWindowCollapsed(false);
+                    mStatusBarWindowController.setForceWindowCollapsed(false);
                 });
             }
         } else {
             if (!mNotificationPanel.isFullyCollapsed() || mNotificationPanel.isTracking()) {
                 // We are currently tracking or is open and the shade doesn't need to be kept
                 // open artificially.
-                mStatusBarWindowManager.setHeadsUpShowing(false);
+                mStatusBarWindowController.setHeadsUpShowing(false);
             } else {
                 // we need to keep the panel open artificially, let's wait until the animation
                 // is finished.
                 mHeadsUpManager.setHeadsUpGoingAway(true);
-                mStackScroller.runAfterAnimationFinished(() -> {
+                mNotificationPanel.runAfterAnimationFinished(() -> {
                     if (!mHeadsUpManager.hasPinnedHeadsUp()) {
-                        mStatusBarWindowManager.setHeadsUpShowing(false);
+                        mStatusBarWindowController.setHeadsUpShowing(false);
                         mHeadsUpManager.setHeadsUpGoingAway(false);
                     }
                     mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed();
@@ -2064,9 +1848,9 @@
     public void setPanelExpanded(boolean isExpanded) {
         mPanelExpanded = isExpanded;
         updateHideIconsForBouncer(false /* animate */);
-        mStatusBarWindowManager.setPanelExpanded(isExpanded);
+        mStatusBarWindowController.setPanelExpanded(isExpanded);
         mVisualStabilityManager.setPanelExpanded(isExpanded);
-        if (isExpanded && getBarState() != StatusBarState.KEYGUARD) {
+        if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) {
             if (DEBUG) {
                 Log.v(TAG, "clearing notification effects from setExpandedHeight");
             }
@@ -2078,7 +1862,7 @@
         }
     }
 
-    public NotificationStackScrollLayout getNotificationScrollLayout() {
+    public ViewGroup getNotificationScrollLayout() {
         return mStackScroller;
     }
 
@@ -2099,17 +1883,6 @@
         updateTheme();
     }
 
-    public boolean isUsingDarkTheme() {
-        OverlayInfo themeInfo = null;
-        try {
-            themeInfo = mOverlayManager.getOverlayInfo("com.android.systemui.theme.dark",
-                    mLockscreenUserManager.getCurrentUserId());
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }
-        return themeInfo != null && themeInfo.isEnabled();
-    }
-
     @Nullable
     public View getAmbientIndicationContainer() {
         return mAmbientIndicationContainer;
@@ -2165,6 +1938,10 @@
         }
     }
 
+    public boolean isHeadsUpShouldBeVisible() {
+        return mHeadsUpAppearanceController.shouldBeVisible();
+    }
+
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
@@ -2242,7 +2019,8 @@
                 mNotificationPanel.expand(true /* animate */);
                 mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1);
             } else if (!mNotificationPanel.isInSettings() && !mNotificationPanel.isExpanding()){
-                mNotificationPanel.flingSettings(0 /* velocity */, true /* expand */);
+                mNotificationPanel.flingSettings(0 /* velocity */,
+                        NotificationPanelView.FLING_EXPAND);
                 mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1);
             }
         }
@@ -2279,7 +2057,7 @@
 
         // Expand the window to encompass the full screen in anticipation of the drag.
         // This is only possible to do atomically because the status bar is at the top of the screen!
-        mStatusBarWindowManager.setPanelVisible(true);
+        mStatusBarWindowController.setPanelVisible(true);
 
         visibilityChanged(true);
         recomputeDisableFlags(!force /* animate */);
@@ -2353,7 +2131,7 @@
                 + mNotificationPanel.canPanelBeCollapsed());
         if (mStatusBarWindow != null && mNotificationPanel.canPanelBeCollapsed()) {
             // release focus immediately to kick off focus change transition
-            mStatusBarWindowManager.setStatusBarFocusable(false);
+            mStatusBarWindowController.setStatusBarFocusable(false);
 
             mStatusBarWindow.cancelExpandHelper();
             mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
@@ -2370,6 +2148,22 @@
         mStatusBarKeyguardViewManager.readyForKeyguardDone();
     }
 
+    public void dispatchNotificationsPanelTouchEvent(MotionEvent ev) {
+        if (!panelsEnabled()) {
+            return;
+        }
+        mNotificationPanel.dispatchTouchEvent(ev);
+
+        int action = ev.getAction();
+        if (action == MotionEvent.ACTION_DOWN) {
+            // Start ignoring all touch events coming to status bar window.
+            // TODO: handle case where ACTION_UP is not sent over the binder
+            mStatusBarWindowController.setNotTouchable(true);
+        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+            mStatusBarWindowController.setNotTouchable(false);
+        }
+    }
+
     @Override
     public void animateExpandNotificationsPanel() {
         if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
@@ -2425,8 +2219,8 @@
         visibilityChanged(false);
 
         // Shrink the window to the size of the status bar only
-        mStatusBarWindowManager.setPanelVisible(false);
-        mStatusBarWindowManager.setForceStatusBarVisible(false);
+        mStatusBarWindowController.setPanelVisible(false);
+        mStatusBarWindowController.setForceStatusBarVisible(false);
 
         // Close any guts that might be visible
         mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
@@ -2807,16 +2601,16 @@
             mNotificationPanel.dump(fd, pw, args);
         }
         pw.println("  mStackScroller: ");
-        if (mStackScroller != null) {
+        if (mStackScroller instanceof Dumpable) {
             pw.print  ("      ");
-            mStackScroller.dump(fd, pw, args);
+            ((Dumpable) mStackScroller).dump(fd, pw, args);
         }
         pw.println("  Theme:");
-        if (mOverlayManager == null) {
-            pw.println("    overlay manager not initialized!");
-        } else {
-            pw.println("    dark overlay on: " + isUsingDarkTheme());
-        }
+        String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + "";
+        pw.println("    dark theme: " + nightMode +
+                " (auto: " + UiModeManager.MODE_NIGHT_AUTO +
+                ", yes: " + UiModeManager.MODE_NIGHT_YES +
+                ", no: " + UiModeManager.MODE_NIGHT_NO + ")");
         final boolean lightWpTheme = mContext.getThemeResId() == R.style.Theme_SystemUI_Light;
         pw.println("    light wallpaper theme: " + lightWpTheme);
 
@@ -2899,25 +2693,11 @@
 
     private void addStatusBarWindow() {
         makeStatusBarView();
-        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
+        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         mRemoteInputManager.setUpWithPresenter(this, mEntryManager, this,
-                new RemoteInputController.Delegate() {
-                    public void setRemoteInputActive(NotificationData.Entry entry,
-                            boolean remoteInputActive) {
-                        mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive);
-                        entry.row.notifyHeightChanged(true /* needsAnimation */);
-                        updateFooter();
-                    }
-                    public void lockScrollTo(NotificationData.Entry entry) {
-                        mStackScroller.lockScrollTo(entry.row);
-                    }
-                    public void requestDisallowLongPressAndDismiss() {
-                        mStackScroller.requestDisallowLongPress();
-                        mStackScroller.requestDisallowDismiss();
-                    }
-                });
-        mRemoteInputManager.getController().addCallback(mStatusBarWindowManager);
-        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
+                mNotificationPanel.createRemoteInputDelegate());
+        mRemoteInputManager.getController().addCallback(mStatusBarWindowController);
+        mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
     }
 
     // called by makeStatusbar and also by PhoneStatusBarView
@@ -3116,7 +2896,7 @@
 
     private void executeWhenUnlocked(OnDismissAction action) {
         if (mStatusBarKeyguardViewManager.isShowing()) {
-            mLeaveOpenOnKeyguardHide = true;
+            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
         }
         dismissKeyguardThenExecute(action, null /* cancelAction */, false /* afterKeyguardGone */);
     }
@@ -3129,7 +2909,7 @@
             boolean afterKeyguardGone) {
         if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
                 && mUnlockMethodCache.canSkipBouncer()
-                && !mLeaveOpenOnKeyguardHide
+                && !mStatusBarStateController.leaveOpenOnKeyguardHide()
                 && isPulsing()) {
             // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse.
             // TODO: Factor this transition out of BiometricUnlockController.
@@ -3149,7 +2929,6 @@
     public void onConfigChanged(Configuration newConfig) {
         updateResources();
         updateDisplaySize(); // populates mDisplayMetrics
-        updateTheme();
 
         if (DEBUG) {
             Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
@@ -3228,8 +3007,8 @@
         int oldBarHeight = mNaturalBarHeight;
         mNaturalBarHeight = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
-        if (mStatusBarWindowManager != null && mNaturalBarHeight != oldBarHeight) {
-            mStatusBarWindowManager.setBarHeight(mNaturalBarHeight);
+        if (mStatusBarWindowController != null && mNaturalBarHeight != oldBarHeight) {
+            mStatusBarWindowController.setBarHeight(mNaturalBarHeight);
         }
         mMaxAllowedKeyguardNotifications = res.getInteger(
                 R.integer.keyguard_max_notification_count);
@@ -3378,7 +3157,7 @@
     @Override
     public void postQSRunnableDismissingKeyguard(final Runnable runnable) {
         mHandler.post(() -> {
-            mLeaveOpenOnKeyguardHide = true;
+            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
             executeRunnableDismissingKeyguard(() -> mHandler.post(runnable), null, false, false,
                     false);
         });
@@ -3421,6 +3200,8 @@
         mContext.unregisterReceiver(mBroadcastReceiver);
         mContext.unregisterReceiver(mDemoReceiver);
         mAssistManager.destroy();
+        mHeadsUpManager.destroy();
+        mStatusBarStateController.removeListener(this);
 
         if (mQSPanel != null && mQSPanel.getHost() != null) {
             mQSPanel.getHost().destroy();
@@ -3507,13 +3288,6 @@
         }
     }
 
-    /**
-     * @return The {@link StatusBarState} the status bar is in.
-     */
-    public int getBarState() {
-        return mState;
-    }
-
     @Override
     public boolean isPresenterFullyCollapsed() {
         return mNotificationPanel.isFullyCollapsed();
@@ -3521,7 +3295,7 @@
 
     public void showKeyguard() {
         mKeyguardRequested = true;
-        mLeaveOpenOnKeyguardHide = false;
+        mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
         mPendingRemoteInputView = null;
         updateIsKeyguard();
         mAssistManager.onLockscreenShown();
@@ -3574,11 +3348,10 @@
         }
         mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
         if (mUserSwitcherController != null && mUserSwitcherController.useFullscreenUserSwitcher()) {
-            setBarState(StatusBarState.FULLSCREEN_USER_SWITCHER);
+            mStatusBarStateController.setState(StatusBarState.FULLSCREEN_USER_SWITCHER);
         } else {
-            setBarState(StatusBarState.KEYGUARD);
+            mStatusBarStateController.setState(StatusBarState.KEYGUARD);
         }
-        updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */);
         updatePanelExpansionForKeyguard();
         if (mDraggedDownRow != null) {
             mDraggedDownRow.setUserLocked(false);
@@ -3637,7 +3410,7 @@
             updateScrimController();
             updateMediaMetaData(false, true);
             mNotificationPanel.setAlpha(1);
-            mStackScroller.setParentNotFullyVisible(true);
+            mNotificationPanel.setParentNotFullyVisible(true);
             mNotificationPanel.animate()
                     .alpha(0)
                     .setStartDelay(FADE_KEYGUARD_START_DELAY)
@@ -3693,7 +3466,7 @@
         Log.w(TAG, "Launch transition: Timeout!");
         mNotificationPanel.onAffordanceLaunchEnded();
         releaseGestureWakeLock();
-        mNotificationPanel.resetViews();
+        mNotificationPanel.resetViews(false /* animate */);
     }
 
     private void runLaunchTransitionEndRunnable() {
@@ -3713,14 +3486,14 @@
     public boolean hideKeyguardImpl() {
         mIsKeyguard = false;
         Trace.beginSection("StatusBar#hideKeyguard");
-        boolean staying = mLeaveOpenOnKeyguardHide;
-        setBarState(StatusBarState.SHADE);
+        boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
+        mStatusBarStateController.setState(StatusBarState.SHADE);
         View viewToClick = null;
-        if (mLeaveOpenOnKeyguardHide) {
+        if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
             if (!mKeyguardRequested) {
-                mLeaveOpenOnKeyguardHide = false;
+                mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
             }
-            long delay = calculateGoingToFullShadeDelay();
+            long delay = mKeyguardMonitor.calculateGoingToFullShadeDelay();
             mNotificationPanel.animateToFullShade(delay);
             if (mDraggedDownRow != null) {
                 mDraggedDownRow.setUserLocked(false);
@@ -3739,7 +3512,6 @@
         } else if (!mNotificationPanel.isCollapsing()) {
             instantCollapseNotificationPanel();
         }
-        updateKeyguardState(staying, false /* fromShadeLocked */);
 
         if (viewToClick != null && viewToClick.isAttachedToWindow()) {
             viewToClick.callOnClick();
@@ -3765,15 +3537,10 @@
         }
     }
 
-    public long calculateGoingToFullShadeDelay() {
-        return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
-    }
-
     /**
      * Notifies the status bar that Keyguard is going away very soon.
      */
     public void keyguardGoingAway() {
-
         // Treat Keyguard exit animation as an app transition to achieve nice transition for status
         // bar.
         mKeyguardMonitor.notifyKeyguardGoingAway(true);
@@ -3788,9 +3555,6 @@
      * @param fadeoutDuration the duration of the exit animation, in milliseconds
      */
     public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) {
-        mKeyguardFadingAway = true;
-        mKeyguardFadingAwayDelay = delay;
-        mKeyguardFadingAwayDuration = fadeoutDuration;
         mCommandQueue.appTransitionStarting(startTime + fadeoutDuration
                         - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
                 LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
@@ -3801,15 +3565,10 @@
         mKeyguardMonitor.notifyKeyguardFadingAway(delay, fadeoutDuration);
     }
 
-    public boolean isKeyguardFadingAway() {
-        return mKeyguardFadingAway;
-    }
-
     /**
      * Notifies that the Keyguard fading away animation is done.
      */
     public void finishKeyguardFadingAway() {
-        mKeyguardFadingAway = false;
         mKeyguardMonitor.notifyKeyguardDoneFading();
         mScrimController.setExpansionAffectsAlpha(true);
     }
@@ -3842,71 +3601,10 @@
         }
     }
 
-    protected void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) {
-        Trace.beginSection("StatusBar#updateKeyguardState");
-        if (mState == StatusBarState.KEYGUARD) {
-            mKeyguardIndicationController.setVisible(true);
-            mNotificationPanel.resetViews();
-            if (mKeyguardUserSwitcher != null) {
-                mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked);
-            }
-            if (mStatusBarView != null) mStatusBarView.removePendingHideExpandedRunnables();
-            if (mAmbientIndicationContainer != null) {
-                mAmbientIndicationContainer.setVisibility(View.VISIBLE);
-            }
-        } else {
-            mKeyguardIndicationController.setVisible(false);
-            if (mKeyguardUserSwitcher != null) {
-                mKeyguardUserSwitcher.setKeyguard(false,
-                        goingToFullShade ||
-                        mState == StatusBarState.SHADE_LOCKED ||
-                        fromShadeLocked);
-            }
-            if (mAmbientIndicationContainer != null) {
-                mAmbientIndicationContainer.setVisibility(View.INVISIBLE);
-            }
-        }
-        mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade);
-        updateTheme();
-        updateDozingState();
-        updatePublicMode();
-        updateStackScrollerState(goingToFullShade, fromShadeLocked);
-        mEntryManager.updateNotifications();
-        checkBarModes();
-        updateScrimController();
-        updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
-        mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
-                mUnlockMethodCache.isMethodSecure(),
-                mStatusBarKeyguardViewManager.isOccluded());
-        Trace.endSection();
-    }
-
     /**
      * Switches theme from light to dark and vice-versa.
      */
     protected void updateTheme() {
-        final boolean inflated = mStackScroller != null && mStatusBarWindowManager != null;
-
-        // The system wallpaper defines if QS should be light or dark.
-        WallpaperColors systemColors = mColorExtractor
-                .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
-        final boolean wallpaperWantsDarkTheme = systemColors != null
-                && (systemColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
-        final Configuration config = mContext.getResources().getConfiguration();
-        final boolean nightModeWantsDarkTheme = DARK_THEME_IN_NIGHT_MODE
-                && (config.uiMode & Configuration.UI_MODE_NIGHT_MASK)
-                    == Configuration.UI_MODE_NIGHT_YES;
-        final boolean useDarkTheme = wallpaperWantsDarkTheme || nightModeWantsDarkTheme;
-        if (isUsingDarkTheme() != useDarkTheme) {
-            mUiOffloadThread.submit(() -> {
-                try {
-                    mOverlayManager.setEnabled("com.android.systemui.theme.dark",
-                            useDarkTheme, mLockscreenUserManager.getCurrentUserId());
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Can't change theme", e);
-                }
-            });
-        }
 
         // Lock wallpaper defines the color of the majority of the views, hence we'll use it
         // to set our default theme.
@@ -3915,24 +3613,7 @@
         final int themeResId = lockDarkText ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI;
         if (mContext.getThemeResId() != themeResId) {
             mContext.setTheme(themeResId);
-            if (inflated) {
-                onThemeChanged();
-            }
-        }
-
-        if (inflated) {
-            int which;
-            if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
-                which = WallpaperManager.FLAG_LOCK;
-            } else {
-                which = WallpaperManager.FLAG_SYSTEM;
-            }
-            final boolean useDarkText = mColorExtractor.getColors(which,
-                    true /* ignoreVisibility */).supportsDarkText();
-            mStackScroller.updateDecorViews(useDarkText);
-
-            // Make sure we have the correct navbar/statusbar colors.
-            mStatusBarWindowManager.setKeyguardDark(useDarkText);
+            Dependency.get(ConfigurationController.class).notifyThemeChanged();
         }
     }
 
@@ -3945,31 +3626,14 @@
         boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup())
                 || (mDozing && mDozeServiceHost.shouldAnimateScreenOff() && sleepingFromKeyguard);
 
-        mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation);
         mDozeScrimController.setDozing(mDozing);
         mKeyguardIndicationController.setDozing(mDozing);
-        mNotificationPanel.setDozing(mDozing, animate);
+        mNotificationPanel.setDozing(mDozing, animate, mWakeUpTouchLocation);
+        mNotificationLogger.setDozing(mDozing);
         updateQsExpansionEnabled();
         Trace.endSection();
     }
 
-    public void updateStackScrollerState(boolean goingToFullShade, boolean fromShadeLocked) {
-        if (mStackScroller == null) return;
-        boolean onKeyguard = mState == StatusBarState.KEYGUARD;
-        boolean publicMode = mLockscreenUserManager.isAnyProfilePublicMode();
-        if (mHeadsUpAppearanceController != null) {
-            mHeadsUpAppearanceController.setPublicMode(publicMode);
-        }
-        mStackScroller.setHideSensitive(publicMode, goingToFullShade);
-        mStackScroller.setDimmed(onKeyguard, fromShadeLocked /* animate */);
-        mStackScroller.setExpandingEnabled(!onKeyguard);
-        ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild();
-        mStackScroller.setActivatedChild(null);
-        if (activatedChild != null) {
-            activatedChild.makeInactive(false /* animate */);
-        }
-    }
-
     public void userActivity() {
         if (mState == StatusBarState.KEYGUARD) {
             mKeyguardViewMediatorCallback.userActivity();
@@ -4012,7 +3676,7 @@
             if (mNotificationPanel.isQsDetailShowing()) {
                 mNotificationPanel.closeQsDetail();
             } else {
-                mNotificationPanel.animateCloseQs();
+                mNotificationPanel.animateCloseQs(false /* animateAway */);
             }
             return true;
         }
@@ -4061,7 +3725,7 @@
     @Override
     public void onActivated(ActivatableNotificationView view) {
         onActivated((View) view);
-        mStackScroller.setActivatedChild(view);
+        mNotificationPanel.setActivatedChild(view);
     }
 
     public void onActivated(View view) {
@@ -4069,45 +3733,78 @@
                 MetricsEvent.ACTION_LS_NOTE,
                 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
         mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again);
-        ActivatableNotificationView previousView = mStackScroller.getActivatedChild();
+        ActivatableNotificationView previousView = mNotificationPanel.getActivatedChild();
         if (previousView != null) {
             previousView.makeInactive(true /* animate */);
         }
     }
 
-    /**
-     * @param state The {@link StatusBarState} to set.
-     */
-    public void setBarState(int state) {
+    @Override
+    public void onStatePreChange(int oldState, int newState) {
+
         // If we're visible and switched to SHADE_LOCKED (the user dragged
         // down on the lockscreen), clear notification LED, vibration,
         // ringing.
         // Other transitions are covered in handleVisibleToUserChanged().
-        if (state != mState && mVisible && (state == StatusBarState.SHADE_LOCKED
-                || (state == StatusBarState.SHADE && isGoingToNotificationShade()))) {
+        if (mVisible && (newState == StatusBarState.SHADE_LOCKED
+                || (Dependency.get(StatusBarStateController.class).goingToFullShade()))) {
             clearNotificationEffects();
         }
-        if (state == StatusBarState.KEYGUARD) {
+        if (newState == StatusBarState.KEYGUARD) {
             mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed();
             maybeEscalateHeadsUp();
         }
-        mState = state;
-        mGroupManager.setStatusBarState(state);
-        mHeadsUpManager.setStatusBarState(state);
-        mFalsingManager.setStatusBarState(state);
-        mStatusBarWindowManager.setStatusBarState(state);
-        mStackScroller.setStatusBarState(state);
+    }
+
+    @Override
+    public void onStateChanged(int newState) {
+        mState = newState;
         updateReportRejectedTouchVisibility();
         updateDozing();
         updateTheme();
         touchAutoDim();
-        mNotificationShelf.setStatusBarState(state);
+        Trace.beginSection("StatusBar#updateKeyguardState");
+        if (mState == StatusBarState.KEYGUARD) {
+            mKeyguardIndicationController.setVisible(true);
+            boolean dozingAnimated = mDozingRequested
+                    && DozeParameters.getInstance(mContext).shouldControlScreenOff();
+            mNotificationPanel.resetViews(dozingAnimated);
+            if (mKeyguardUserSwitcher != null) {
+                mKeyguardUserSwitcher.setKeyguard(true,
+                        mStatusBarStateController.fromShadeLocked());
+            }
+            if (mStatusBarView != null) mStatusBarView.removePendingHideExpandedRunnables();
+            if (mAmbientIndicationContainer != null) {
+                mAmbientIndicationContainer.setVisibility(View.VISIBLE);
+            }
+        } else {
+            mKeyguardIndicationController.setVisible(false);
+            if (mKeyguardUserSwitcher != null) {
+                mKeyguardUserSwitcher.setKeyguard(false,
+                        mStatusBarStateController.goingToFullShade() ||
+                                mState == StatusBarState.SHADE_LOCKED ||
+                                mStatusBarStateController.fromShadeLocked());
+            }
+            if (mAmbientIndicationContainer != null) {
+                mAmbientIndicationContainer.setVisibility(View.INVISIBLE);
+            }
+        }
+        updateDozingState();
+        updatePublicMode();
+        mEntryManager.updateNotifications();
+        checkBarModes();
+        updateScrimController();
+        updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
+        mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
+                mUnlockMethodCache.isMethodSecure(),
+                mStatusBarKeyguardViewManager.isOccluded());
+        Trace.endSection();
     }
 
     @Override
     public void onActivationReset(ActivatableNotificationView view) {
-        if (view == mStackScroller.getActivatedChild()) {
-            mStackScroller.setActivatedChild(null);
+        if (view == mNotificationPanel.getActivatedChild()) {
+            mNotificationPanel.setActivatedChild(null);
             onActivationReset((View)view);
         }
     }
@@ -4125,7 +3822,7 @@
         if (!isPresenterFullyCollapsed()) {
             // if we set it not to be focusable when collapsing, we have to undo it when we aborted
             // the closing
-            mStatusBarWindowManager.setStatusBarFocusable(true);
+            mStatusBarWindowController.setStatusBarFocusable(true);
         }
     }
 
@@ -4173,8 +3870,9 @@
         return mMaxKeyguardNotifications;
     }
 
-    public int getMaxNotificationsWhileLocked() {
-        return getMaxNotificationsWhileLocked(false /* recompute */);
+    @Override
+    public void onUpdateRowStates() {
+        mNotificationPanel.onUpdateRowStates();
     }
 
     // TODO: Figure out way to remove these.
@@ -4194,60 +3892,6 @@
         return mNotificationPanel.getKeyguardBottomAreaView();
     }
 
-    // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
-
-
-    /* Only ever called as a consequence of a lockscreen expansion gesture. */
-    @Override
-    public boolean onDraggedDown(View startingChild, int dragLengthY) {
-        if (mState == StatusBarState.KEYGUARD
-                && hasActiveNotifications() && (!isDozing() || isPulsing())) {
-            mLockscreenGestureLogger.write(
-                    MetricsEvent.ACTION_LS_SHADE,
-                    (int) (dragLengthY / mDisplayMetrics.density),
-                    0 /* velocityDp - N/A */);
-
-            // We have notifications, go to locked shade.
-            goToLockedShade(startingChild);
-            if (startingChild instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild;
-                row.onExpandedByGesture(true /* drag down is always an open */);
-            }
-            return true;
-        } else {
-            // abort gesture.
-            return false;
-        }
-    }
-
-    @Override
-    public void onDragDownReset() {
-        mStackScroller.setDimmed(true /* dimmed */, true /* animated */);
-        mStackScroller.resetScrollPosition();
-        mStackScroller.resetCheckSnoozeLeavebehind();
-    }
-
-    @Override
-    public void onCrossedThreshold(boolean above) {
-        mStackScroller.setDimmed(!above /* dimmed */, true /* animate */);
-    }
-
-    @Override
-    public void onTouchSlopExceeded() {
-        mStackScroller.cancelLongPress();
-        mStackScroller.checkSnoozeLeavebehind();
-    }
-
-    @Override
-    public void setEmptyDragAmount(float amount) {
-        mNotificationPanel.setEmptyDragAmount(amount);
-    }
-
-    @Override
-    public boolean isFalsingCheckNeeded() {
-        return mState == StatusBarState.KEYGUARD;
-    }
-
     /**
      * If secure with redaction: Show bouncer, go to unlocked shade.
      *
@@ -4277,25 +3921,24 @@
                 || !mLockscreenUserManager.shouldShowLockscreenNotifications()
                 || mFalsingManager.shouldEnforceBouncer();
         if (mLockscreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
-            mLeaveOpenOnKeyguardHide = true;
+            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
             showBouncerIfKeyguard();
             mDraggedDownRow = row;
             mPendingRemoteInputView = null;
         } else {
             mNotificationPanel.animateToFullShade(0 /* delay */);
-            setBarState(StatusBarState.SHADE_LOCKED);
-            updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */);
+            mStatusBarStateController.setState(StatusBarState.SHADE_LOCKED);
         }
     }
 
     public void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
-        mLeaveOpenOnKeyguardHide = true;
+        mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
         dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */);
     }
 
     @Override
     public void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) {
-        mLeaveOpenOnKeyguardHide = true;
+        mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
         showBouncer(true /* scrimmed */);
         mPendingRemoteInputView = clicked;
     }
@@ -4473,20 +4116,10 @@
      */
     public void goToKeyguard() {
         if (mState == StatusBarState.SHADE_LOCKED) {
-            mStackScroller.onGoToKeyguard();
-            setBarState(StatusBarState.KEYGUARD);
-            updateKeyguardState(false /* goingToFullShade */, true /* fromShadeLocked*/);
+            mStatusBarStateController.setState(StatusBarState.KEYGUARD);
         }
     }
 
-    public long getKeyguardFadingAwayDelay() {
-        return mKeyguardFadingAwayDelay;
-    }
-
-    public long getKeyguardFadingAwayDuration() {
-        return mKeyguardFadingAwayDuration;
-    }
-
     public void setBouncerShowing(boolean bouncerShowing) {
         mBouncerShowing = bouncerShowing;
         if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
@@ -4516,14 +4149,13 @@
             mDeviceInteractive = false;
             mWakeUpComingFromTouch = false;
             mWakeUpTouchLocation = null;
-            mStackScroller.setAnimationsEnabled(false);
             mVisualStabilityManager.setScreenOn(false);
             updateVisibleToUser();
 
             // We need to disable touch events because these might
             // collapse the panel after we expanded it, and thus we would end up with a blank
             // Keyguard.
-            mNotificationPanel.setTouchDisabled(true);
+            mNotificationPanel.setTouchAndAnimationDisabled(true);
             mStatusBarWindow.cancelCurrentTouch();
             if (mLaunchCameraOnFinishedGoingToSleep) {
                 mLaunchCameraOnFinishedGoingToSleep = false;
@@ -4544,9 +4176,8 @@
         @Override
         public void onStartedWakingUp() {
             mDeviceInteractive = true;
-            mStackScroller.setAnimationsEnabled(true);
             mVisualStabilityManager.setScreenOn(true);
-            mNotificationPanel.setTouchDisabled(false);
+            mNotificationPanel.setTouchAndAnimationDisabled(false);
             mDozeServiceHost.stopDozing();
             updateVisibleToUser();
             updateIsKeyguard();
@@ -4733,7 +4364,6 @@
         boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD
                 || mBiometricUnlockController.getMode()
                         == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
-        final boolean alwaysOn = DozeParameters.getInstance(mContext).getAlwaysOn();
         // When in wake-and-unlock we may not have received a change to mState
         // but we still should not be dozing, manually set to false.
         if (mBiometricUnlockController.getMode() ==
@@ -4742,8 +4372,8 @@
         }
         if (mDozing != dozing) {
             mDozing = dozing;
-            mKeyguardViewMediator.setAodShowing(mDozing && alwaysOn);
-            mStatusBarWindowManager.setDozing(mDozing);
+            mKeyguardViewMediator.setAodShowing(mDozing);
+            mStatusBarWindowController.setDozing(mDozing);
             mStatusBarKeyguardViewManager.setDozing(mDozing);
             if (mAmbientIndicationContainer instanceof DozeReceiver) {
                 ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing);
@@ -4858,7 +4488,7 @@
                 @Override
                 public void onPulseStarted() {
                     callback.onPulseStarted();
-                    if (mHeadsUpManager.hasHeadsUpNotifications()) {
+                    if (mHeadsUpManager.hasNotifications()) {
                         // Only pulse the stack scroller if there's actually something to show.
                         // Otherwise just show the always-on screen.
                         setPulsing(true);
@@ -4872,6 +4502,7 @@
                 }
 
                 private void setPulsing(boolean pulsing) {
+                    mKeyguardViewMediator.setPulsing(pulsing);
                     mNotificationPanel.setPulsing(pulsing);
                     mVisualStabilityManager.setPulsing(pulsing);
                     mIgnoreTouchWhilePulsing = false;
@@ -4972,7 +4603,7 @@
 
         @Override
         public void setDozeScreenBrightness(int value) {
-            mStatusBarWindowManager.setDozeScreenBrightness(value);
+            mStatusBarWindowController.setDozeScreenBrightness(value);
         }
 
         @Override
@@ -5016,7 +4647,7 @@
     protected IStatusBarService mBarService;
 
     // all notifications
-    protected NotificationStackScrollLayout mStackScroller;
+    protected ViewGroup mStackScroller;
 
     protected NotificationGroupManager mGroupManager;
 
@@ -5057,7 +4688,6 @@
     protected RecentsComponent mRecents;
 
     protected NotificationShelf mNotificationShelf;
-    protected FooterView mFooterView;
     protected EmptyShadeView mEmptyShadeView;
 
     protected AssistManager mAssistManager;
@@ -5130,7 +4760,7 @@
         final boolean wasOccluded = mIsOccluded;
         dismissKeyguardThenExecute(() -> {
             // TODO: Some of this code may be able to move to NotificationEntryManager.
-            if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) {
+            if (mHeadsUpManager != null && mHeadsUpManager.contains(notificationKey)) {
                 // Release the HUN notification to the shade.
 
                 if (isPresenterFullyCollapsed()) {
@@ -5139,7 +4769,8 @@
                 //
                 // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
                 // become canceled shortly by NoMan, but we can't assume that.
-                mHeadsUpManager.releaseImmediately(notificationKey);
+                mHeadsUpManager.removeNotification(sbn.getKey(),
+                        true /* releaseImmediately */);
             }
             StatusBarNotification parentToCancel = null;
             if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
@@ -5252,7 +4883,7 @@
         if (Looper.getMainLooper().isCurrentThread()) {
             collapsePanel();
         } else {
-            mStackScroller.post(this::collapsePanel);
+            Dependency.get(Dependency.MAIN_HANDLER).post(this::collapsePanel);
         }
     }
 
@@ -5531,33 +5162,6 @@
         }
     }
 
-    /**
-     * Updates expanded, dimmed and locked states of notification rows.
-     */
-    @Override
-    public void onUpdateRowStates() {
-        // The following views will be moved to the end of mStackScroller. This counter represents
-        // the offset from the last child. Initialized to 1 for the very last position. It is post-
-        // incremented in the following "changeViewPosition" calls so that its value is correct for
-        // subsequent calls.
-        int offsetFromEnd = 1;
-        if (mFooterView != null) {
-            mStackScroller.changeViewPosition(mFooterView,
-                    mStackScroller.getChildCount() - offsetFromEnd++);
-        }
-
-        mStackScroller.changeViewPosition(mEmptyShadeView,
-                mStackScroller.getChildCount() - offsetFromEnd++);
-
-        // No post-increment for this call because it is the last one. Make sure to add one if
-        // another "changeViewPosition" call is ever added.
-        mStackScroller.changeViewPosition(mNotificationShelf,
-                mStackScroller.getChildCount() - offsetFromEnd);
-
-        // Scrim opacity varies based on notification count
-        mScrimController.setNotificationCount(mStackScroller.getNotGoneChildCount());
-    }
-
     protected void notifyHeadsUpGoingToSleep() {
         maybeEscalateHeadsUp();
     }
@@ -5604,11 +5208,6 @@
     }
 
     @Override
-    public void onZenChanged(int zen) {
-        updateEmptyShadeView();
-    }
-
-    @Override
     public void showAssistDisclosure() {
         if (mAssistManager != null) {
             mAssistManager.showDisclosure();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 378910a..e8389af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -44,7 +44,9 @@
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -74,7 +76,7 @@
     private static String TAG = "StatusBarKeyguardViewManager";
 
     protected final Context mContext;
-    private final StatusBarWindowManager mStatusBarWindowManager;
+    private final StatusBarWindowController mStatusBarWindowController;
     private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
         @Override
         public void onFullyShown() {
@@ -116,6 +118,7 @@
 
     // Dismiss action to be launched when we stop dozing or the keyguard is gone.
     private DismissWithActionRequest mPendingWakeupAction;
+    private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
 
     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -135,7 +138,7 @@
         mContext = context;
         mViewMediatorCallback = callback;
         mLockPatternUtils = lockPatternUtils;
-        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
+        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback);
     }
 
@@ -190,7 +193,7 @@
      */
     public void show(Bundle options) {
         mShowing = true;
-        mStatusBarWindowManager.setKeyguardShowing(true);
+        mStatusBarWindowController.setKeyguardShowing(true);
         reset(true /* hideBouncerWhenShowing */);
         StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
             StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
@@ -342,11 +345,11 @@
     }
 
     public void setNeedsInput(boolean needsInput) {
-        mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
+        mStatusBarWindowController.setKeyguardNeedsInput(needsInput);
     }
 
     public boolean isUnlockWithWallpaper() {
-        return mStatusBarWindowManager.isShowingWallpaper();
+        return mStatusBarWindowController.isShowingWallpaper();
     }
 
     public void setOccluded(boolean occluded, boolean animate) {
@@ -360,7 +363,7 @@
                         new Runnable() {
                             @Override
                             public void run() {
-                                mStatusBarWindowManager.setKeyguardOccluded(mOccluded);
+                                mStatusBarWindowController.setKeyguardOccluded(mOccluded);
                                 reset(true /* hideBouncerWhenShowing */);
                             }
                         });
@@ -375,7 +378,7 @@
         if (mShowing) {
             mStatusBar.updateMediaMetaData(false, animate && !occluded);
         }
-        mStatusBarWindowManager.setKeyguardOccluded(occluded);
+        mStatusBarWindowController.setKeyguardOccluded(occluded);
 
         // setDozing(false) will call reset once we stop dozing.
         if (!mDozing) {
@@ -425,8 +428,8 @@
             mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
                 @Override
                 public void run() {
-                    mStatusBarWindowManager.setKeyguardShowing(false);
-                    mStatusBarWindowManager.setKeyguardFadingAway(true);
+                    mStatusBarWindowController.setKeyguardShowing(false);
+                    mStatusBarWindowController.setKeyguardFadingAway(true);
                     hideBouncer(true /* destroyView */);
                     updateStates();
                 }
@@ -434,7 +437,7 @@
                 @Override
                 public void run() {
                     mStatusBar.hideKeyguard();
-                    mStatusBarWindowManager.setKeyguardFadingAway(false);
+                    mStatusBarWindowController.setKeyguardFadingAway(false);
                     mViewMediatorCallback.keyguardGone();
                     executeAfterKeyguardGoneAction();
                 }
@@ -456,7 +459,7 @@
             } else {
                 boolean staying = mStatusBar.hideKeyguard();
                 if (!staying) {
-                    mStatusBarWindowManager.setKeyguardFadingAway(true);
+                    mStatusBarWindowController.setKeyguardFadingAway(true);
                     wakeAndUnlockDejank();
                 } else {
                     mStatusBar.finishKeyguardFadingAway();
@@ -464,7 +467,7 @@
                 }
             }
             updateStates();
-            mStatusBarWindowManager.setKeyguardShowing(false);
+            mStatusBarWindowController.setKeyguardShowing(false);
             mViewMediatorCallback.keyguardGone();
         }
         StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
@@ -481,7 +484,7 @@
     }
 
     public void onKeyguardFadedAway() {
-        mContainer.postDelayed(() -> mStatusBarWindowManager.setKeyguardFadingAway(false),
+        mContainer.postDelayed(() -> mStatusBarWindowController.setKeyguardFadingAway(false),
                 100);
         mStatusBar.finishKeyguardFadingAway();
         mBiometricUnlockController.finishKeyguardFadingAway();
@@ -557,8 +560,8 @@
     }
 
     private long getNavBarShowDelay() {
-        if (mStatusBar.isKeyguardFadingAway()) {
-            return mStatusBar.getKeyguardFadingAwayDelay();
+        if (mKeyguardMonitor.isKeyguardFadingAway()) {
+            return mKeyguardMonitor.getKeyguardFadingAwayDelay();
         } else if (mBouncer.isShowing()) {
             return NAV_BAR_SHOW_DELAY_BOUNCER;
         } else {
@@ -599,7 +602,7 @@
         }
 
         if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
-            mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
+            mStatusBarWindowController.setBouncerShowing(bouncerShowing);
             mStatusBar.setBouncerShowing(bouncerShowing);
         }
 
@@ -677,7 +680,7 @@
     }
 
     public boolean isGoingToNotificationShade() {
-        return mStatusBar.isGoingToNotificationShade();
+        return Dependency.get(StatusBarStateController.class).leaveOpenOnKeyguardHide();
     }
 
     public boolean isSecure(int userId) {
@@ -693,6 +696,14 @@
                 false /* delayed */, speedUpFactor);
     }
 
+
+    /**
+     * Called when cancel button in bouncer is pressed.
+     */
+    public void onCancelClicked() {
+        // No-op
+    }
+
     /**
      * Notifies that the user has authenticated by other means than using the bouncer, for example,
      * fingerprint.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
new file mode 100644
index 0000000..167bba6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -0,0 +1,569 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
+import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
+
+import android.app.ActivityManager;
+import android.app.IActivityManager;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.R;
+import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.statusbar.RemoteInputController.Callback;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
+
+/**
+ * Encapsulates all logic for the status bar window state management.
+ */
+public class StatusBarWindowController implements Callback, Dumpable, ConfigurationListener {
+
+    private static final String TAG = "StatusBarWindowController";
+
+    private final Context mContext;
+    private final WindowManager mWindowManager;
+    private final IActivityManager mActivityManager;
+    private final DozeParameters mDozeParameters;
+    private View mStatusBarView;
+    private WindowManager.LayoutParams mLp;
+    private WindowManager.LayoutParams mLpChanged;
+    private boolean mHasTopUi;
+    private boolean mHasTopUiChanged;
+    private int mBarHeight;
+    private final boolean mKeyguardScreenRotation;
+    private float mScreenBrightnessDoze;
+    private final State mCurrentState = new State();
+    private OtherwisedCollapsedListener mListener;
+
+    private final StateListener mStateListener = this::setStatusBarState;
+    private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+
+    public StatusBarWindowController(Context context) {
+        this(context, context.getSystemService(WindowManager.class), ActivityManager.getService(),
+                DozeParameters.getInstance(context));
+    }
+
+    @VisibleForTesting
+    StatusBarWindowController(Context context, WindowManager windowManager,
+            IActivityManager activityManager, DozeParameters dozeParameters) {
+        mContext = context;
+        mWindowManager = windowManager;
+        mActivityManager = activityManager;
+        mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
+        mDozeParameters = dozeParameters;
+        mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
+        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+        Dependency.get(ConfigurationController.class).addCallback(this);
+    }
+
+    private boolean shouldEnableKeyguardScreenRotation() {
+        Resources res = mContext.getResources();
+        return SystemProperties.getBoolean("lockscreen.rot_override", false)
+                || res.getBoolean(R.bool.config_enableLockScreenRotation);
+    }
+
+    /**
+     * Adds the status bar view to the window manager.
+     *
+     * @param statusBarView The view to add.
+     * @param barHeight The height of the status bar in collapsed state.
+     */
+    public void add(View statusBarView, int barHeight) {
+
+        // Now that the status bar window encompasses the sliding panel and its
+        // translucent backdrop, the entire thing is made TRANSLUCENT and is
+        // hardware-accelerated.
+        mLp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                barHeight,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                PixelFormat.TRANSLUCENT);
+        mLp.token = new Binder();
+        mLp.gravity = Gravity.TOP;
+        mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+        mLp.setTitle("StatusBar");
+        mLp.packageName = mContext.getPackageName();
+        mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+        mStatusBarView = statusBarView;
+        mBarHeight = barHeight;
+        mWindowManager.addView(mStatusBarView, mLp);
+        mLpChanged = new WindowManager.LayoutParams();
+        mLpChanged.copyFrom(mLp);
+    }
+
+    public void setDozeScreenBrightness(int value) {
+        mScreenBrightnessDoze = value / 255f;
+    }
+
+    private void setKeyguardDark(boolean dark) {
+        int vis = mStatusBarView.getSystemUiVisibility();
+        if (dark) {
+            vis = vis | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+            vis = vis | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+        } else {
+            vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+            vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+        }
+        mStatusBarView.setSystemUiVisibility(vis);
+    }
+
+    private void applyKeyguardFlags(State state) {
+        if (state.keyguardShowing) {
+            mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+        } else {
+            mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+        }
+
+        final boolean scrimsOccludingWallpaper =
+                state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE;
+        final boolean keyguardOrAod = state.keyguardShowing
+                || (state.dozing && mDozeParameters.getAlwaysOn());
+        if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) {
+            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+        } else {
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+        }
+
+        if (state.dozing) {
+            mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        } else {
+            mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        }
+    }
+
+    private void adjustScreenOrientation(State state) {
+        if (state.isKeyguardShowingAndNotOccluded() || state.dozing) {
+            if (mKeyguardScreenRotation) {
+                mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
+            } else {
+                mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+            }
+        } else {
+            mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+        }
+    }
+
+    private void applyFocusableFlag(State state) {
+        boolean panelFocusable = state.statusBarFocusable && state.panelExpanded;
+        if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput)
+                || ENABLE_REMOTE_INPUT && state.remoteInputActive) {
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        } else {
+            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        }
+
+        mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+    }
+
+    private void applyForceShowNavigationFlag(State state) {
+        if (state.panelExpanded || state.bouncerShowing
+                || ENABLE_REMOTE_INPUT && state.remoteInputActive) {
+            mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
+        } else {
+            mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
+        }
+    }
+
+    private void applyHeight(State state) {
+        boolean expanded = isExpanded(state);
+        if (state.forcePluginOpen) {
+            mListener.setWouldOtherwiseCollapse(expanded);
+            expanded = true;
+        }
+        if (expanded) {
+            mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
+        } else {
+            mLpChanged.height = mBarHeight;
+        }
+    }
+
+    private boolean isExpanded(State state) {
+        return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
+                || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
+                || state.headsUpShowing
+                || state.scrimsVisibility != ScrimController.VISIBILITY_FULLY_TRANSPARENT);
+    }
+
+    private void applyFitsSystemWindows(State state) {
+        boolean fitsSystemWindows = !state.isKeyguardShowingAndNotOccluded();
+        if (mStatusBarView.getFitsSystemWindows() != fitsSystemWindows) {
+            mStatusBarView.setFitsSystemWindows(fitsSystemWindows);
+            mStatusBarView.requestApplyInsets();
+        }
+    }
+
+    private void applyUserActivityTimeout(State state) {
+        if (state.isKeyguardShowingAndNotOccluded()
+                && state.statusBarState == StatusBarState.KEYGUARD
+                && !state.qsExpanded) {
+            mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
+        } else {
+            mLpChanged.userActivityTimeout = -1;
+        }
+    }
+
+    private void applyInputFeatures(State state) {
+        if (state.isKeyguardShowingAndNotOccluded()
+                && state.statusBarState == StatusBarState.KEYGUARD
+                && !state.qsExpanded && !state.forceUserActivity) {
+            mLpChanged.inputFeatures |=
+                    WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+        } else {
+            mLpChanged.inputFeatures &=
+                    ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+        }
+    }
+
+    private void apply(State state) {
+        applyKeyguardFlags(state);
+        applyForceStatusBarVisibleFlag(state);
+        applyFocusableFlag(state);
+        applyForceShowNavigationFlag(state);
+        adjustScreenOrientation(state);
+        applyHeight(state);
+        applyUserActivityTimeout(state);
+        applyInputFeatures(state);
+        applyFitsSystemWindows(state);
+        applyModalFlag(state);
+        applyBrightness(state);
+        applyHasTopUi(state);
+        applySleepToken(state);
+        applyNotTouchable(state);
+        if (mLp.copyFrom(mLpChanged) != 0) {
+            mWindowManager.updateViewLayout(mStatusBarView, mLp);
+        }
+        if (mHasTopUi != mHasTopUiChanged) {
+            try {
+                mActivityManager.setHasTopUi(mHasTopUiChanged);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to call setHasTopUi", e);
+            }
+            mHasTopUi = mHasTopUiChanged;
+        }
+    }
+
+    private void applyForceStatusBarVisibleFlag(State state) {
+        if (state.forceStatusBarVisible) {
+            mLpChanged.privateFlags |= WindowManager
+                    .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
+        } else {
+            mLpChanged.privateFlags &= ~WindowManager
+                    .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
+        }
+    }
+
+    private void applyModalFlag(State state) {
+        if (state.headsUpShowing) {
+            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+        } else {
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+        }
+    }
+
+    private void applyBrightness(State state) {
+        if (state.forceDozeBrightness) {
+            mLpChanged.screenBrightness = mScreenBrightnessDoze;
+        } else {
+            mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
+        }
+    }
+
+    private void applyHasTopUi(State state) {
+        mHasTopUiChanged = isExpanded(state);
+    }
+
+    private void applySleepToken(State state) {
+        if (state.dozing) {
+            mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
+        } else {
+            mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
+        }
+    }
+
+    private void applyNotTouchable(State state) {
+        if (state.notTouchable) {
+            mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
+        } else {
+            mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCHABLE;
+        }
+    }
+
+    public void setKeyguardShowing(boolean showing) {
+        mCurrentState.keyguardShowing = showing;
+        apply(mCurrentState);
+    }
+
+    public void setKeyguardOccluded(boolean occluded) {
+        mCurrentState.keyguardOccluded = occluded;
+        apply(mCurrentState);
+    }
+
+    public void setKeyguardNeedsInput(boolean needsInput) {
+        mCurrentState.keyguardNeedsInput = needsInput;
+        apply(mCurrentState);
+    }
+
+    public void setPanelVisible(boolean visible) {
+        mCurrentState.panelVisible = visible;
+        mCurrentState.statusBarFocusable = visible;
+        apply(mCurrentState);
+    }
+
+    public void setStatusBarFocusable(boolean focusable) {
+        mCurrentState.statusBarFocusable = focusable;
+        apply(mCurrentState);
+    }
+
+    public void setBouncerShowing(boolean showing) {
+        mCurrentState.bouncerShowing = showing;
+        apply(mCurrentState);
+    }
+
+    public void setBackdropShowing(boolean showing) {
+        mCurrentState.backdropShowing = showing;
+        apply(mCurrentState);
+    }
+
+    public void setKeyguardFadingAway(boolean keyguardFadingAway) {
+        mCurrentState.keyguardFadingAway = keyguardFadingAway;
+        apply(mCurrentState);
+    }
+
+    public void setQsExpanded(boolean expanded) {
+        mCurrentState.qsExpanded = expanded;
+        apply(mCurrentState);
+    }
+
+    public void setForceUserActivity(boolean forceUserActivity) {
+        mCurrentState.forceUserActivity = forceUserActivity;
+        apply(mCurrentState);
+    }
+
+    public void setScrimsVisibility(int scrimsVisibility) {
+        mCurrentState.scrimsVisibility = scrimsVisibility;
+        apply(mCurrentState);
+    }
+
+    public void setHeadsUpShowing(boolean showing) {
+        mCurrentState.headsUpShowing = showing;
+        apply(mCurrentState);
+    }
+
+    public void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) {
+        mCurrentState.wallpaperSupportsAmbientMode = supportsAmbientMode;
+        apply(mCurrentState);
+    }
+
+    /**
+     * @param state The {@link StatusBarStateController} of the status bar.
+     */
+    private void setStatusBarState(int state) {
+        mCurrentState.statusBarState = state;
+        apply(mCurrentState);
+    }
+
+    public void setForceStatusBarVisible(boolean forceStatusBarVisible) {
+        mCurrentState.forceStatusBarVisible = forceStatusBarVisible;
+        apply(mCurrentState);
+    }
+
+    /**
+     * Force the window to be collapsed, even if it should theoretically be expanded.
+     * Used for when a heads-up comes in but we still need to wait for the touchable regions to
+     * be computed.
+     */
+    public void setForceWindowCollapsed(boolean force) {
+        mCurrentState.forceCollapsed = force;
+        apply(mCurrentState);
+    }
+
+    public void setPanelExpanded(boolean isExpanded) {
+        mCurrentState.panelExpanded = isExpanded;
+        apply(mCurrentState);
+    }
+
+    @Override
+    public void onRemoteInputActive(boolean remoteInputActive) {
+        mCurrentState.remoteInputActive = remoteInputActive;
+        apply(mCurrentState);
+    }
+
+    /**
+     * Set whether the screen brightness is forced to the value we use for doze mode by the status
+     * bar window.
+     */
+    public void setForceDozeBrightness(boolean forceDozeBrightness) {
+        mCurrentState.forceDozeBrightness = forceDozeBrightness;
+        apply(mCurrentState);
+    }
+
+    public void setDozing(boolean dozing) {
+        mCurrentState.dozing = dozing;
+        apply(mCurrentState);
+    }
+
+    public void setBarHeight(int barHeight) {
+        mBarHeight = barHeight;
+        apply(mCurrentState);
+    }
+
+    public void setForcePluginOpen(boolean forcePluginOpen) {
+        mCurrentState.forcePluginOpen = forcePluginOpen;
+        apply(mCurrentState);
+    }
+
+    public void setNotTouchable(boolean notTouchable) {
+        mCurrentState.notTouchable = notTouchable;
+        apply(mCurrentState);
+    }
+
+    public void setStateListener(OtherwisedCollapsedListener listener) {
+        mListener = listener;
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("StatusBarWindowController state:");
+        pw.println(mCurrentState);
+    }
+
+    public boolean isShowingWallpaper() {
+        return !mCurrentState.backdropShowing;
+    }
+
+    @Override
+    public void onThemeChanged() {
+        StatusBarStateController state = Dependency.get(StatusBarStateController.class);
+        int which;
+        if (state.getState() == StatusBarState.KEYGUARD
+                || state.getState() == StatusBarState.SHADE_LOCKED) {
+            which = WallpaperManager.FLAG_LOCK;
+        } else {
+            which = WallpaperManager.FLAG_SYSTEM;
+        }
+        final boolean useDarkText = mColorExtractor.getColors(which,
+                true /* ignoreVisibility */).supportsDarkText();
+
+        // Make sure we have the correct navbar/statusbar colors.
+        setKeyguardDark(useDarkText);
+    }
+
+    private static class State {
+        boolean keyguardShowing;
+        boolean keyguardOccluded;
+        boolean keyguardNeedsInput;
+        boolean panelVisible;
+        boolean panelExpanded;
+        boolean statusBarFocusable;
+        boolean bouncerShowing;
+        boolean keyguardFadingAway;
+        boolean qsExpanded;
+        boolean headsUpShowing;
+        boolean forceStatusBarVisible;
+        boolean forceCollapsed;
+        boolean forceDozeBrightness;
+        boolean forceUserActivity;
+        boolean backdropShowing;
+        boolean wallpaperSupportsAmbientMode;
+        boolean notTouchable;
+
+        /**
+         * The {@link StatusBar} state from the status bar.
+         */
+        int statusBarState;
+
+        boolean remoteInputActive;
+        boolean forcePluginOpen;
+        boolean dozing;
+        int scrimsVisibility;
+
+        private boolean isKeyguardShowingAndNotOccluded() {
+            return keyguardShowing && !keyguardOccluded;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder result = new StringBuilder();
+            String newLine = "\n";
+            result.append("Window State {");
+            result.append(newLine);
+
+            Field[] fields = this.getClass().getDeclaredFields();
+
+            // Print field names paired with their values
+            for (Field field : fields) {
+                result.append("  ");
+                try {
+                    result.append(field.getName());
+                    result.append(": ");
+                    //requires access to private field:
+                    result.append(field.get(this));
+                } catch (IllegalAccessException ex) {
+                }
+                result.append(newLine);
+            }
+            result.append("}");
+
+            return result.toString();
+        }
+    }
+
+    /**
+     * Custom listener to pipe data back to plugins about whether or not the status bar would be
+     * collapsed if not for the plugin.
+     * TODO: Find cleaner way to do this.
+     */
+    public interface OtherwisedCollapsedListener {
+        void setWouldOtherwiseCollapse(boolean otherwiseCollapse);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
deleted file mode 100644
index fadc0ea..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.phone;
-
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-
-import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
-
-import android.app.ActivityManager;
-import android.app.IActivityManager;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-
-import com.android.keyguard.R;
-import com.android.systemui.Dumpable;
-import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.StatusBarState;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.lang.reflect.Field;
-
-/**
- * Encapsulates all logic for the status bar window state management.
- */
-public class StatusBarWindowManager implements RemoteInputController.Callback, Dumpable {
-
-    private static final String TAG = "StatusBarWindowManager";
-
-    private final Context mContext;
-    private final WindowManager mWindowManager;
-    private final IActivityManager mActivityManager;
-    private final DozeParameters mDozeParameters;
-    private View mStatusBarView;
-    private WindowManager.LayoutParams mLp;
-    private WindowManager.LayoutParams mLpChanged;
-    private boolean mHasTopUi;
-    private boolean mHasTopUiChanged;
-    private int mBarHeight;
-    private final boolean mKeyguardScreenRotation;
-    private float mScreenBrightnessDoze;
-    private final State mCurrentState = new State();
-    private OtherwisedCollapsedListener mListener;
-
-    public StatusBarWindowManager(Context context) {
-        mContext = context;
-        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-        mActivityManager = ActivityManager.getService();
-        mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
-        mDozeParameters = DozeParameters.getInstance(mContext);
-        mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
-    }
-
-    private boolean shouldEnableKeyguardScreenRotation() {
-        Resources res = mContext.getResources();
-        return SystemProperties.getBoolean("lockscreen.rot_override", false)
-                || res.getBoolean(R.bool.config_enableLockScreenRotation);
-    }
-
-    /**
-     * Adds the status bar view to the window manager.
-     *
-     * @param statusBarView The view to add.
-     * @param barHeight The height of the status bar in collapsed state.
-     */
-    public void add(View statusBarView, int barHeight) {
-
-        // Now that the status bar window encompasses the sliding panel and its
-        // translucent backdrop, the entire thing is made TRANSLUCENT and is
-        // hardware-accelerated.
-        mLp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                barHeight,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                        | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
-                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
-                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                        | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
-                PixelFormat.TRANSLUCENT);
-        mLp.token = new Binder();
-        mLp.gravity = Gravity.TOP;
-        mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-        mLp.setTitle("StatusBar");
-        mLp.packageName = mContext.getPackageName();
-        mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        mStatusBarView = statusBarView;
-        mBarHeight = barHeight;
-        mWindowManager.addView(mStatusBarView, mLp);
-        mLpChanged = new WindowManager.LayoutParams();
-        mLpChanged.copyFrom(mLp);
-    }
-
-    public void setDozeScreenBrightness(int value) {
-        mScreenBrightnessDoze = value / 255f;
-    }
-
-    public void setKeyguardDark(boolean dark) {
-        int vis = mStatusBarView.getSystemUiVisibility();
-        if (dark) {
-            vis = vis | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
-            vis = vis | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
-        } else {
-            vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
-            vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
-        }
-        mStatusBarView.setSystemUiVisibility(vis);
-    }
-
-    private void applyKeyguardFlags(State state) {
-        if (state.keyguardShowing) {
-            mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-        } else {
-            mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-        }
-
-        final boolean scrimsOccludingWallpaper =
-                state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE;
-        final boolean keyguardOrAod = state.keyguardShowing
-                || (state.dozing && mDozeParameters.getAlwaysOn());
-        if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) {
-            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-        } else {
-            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-        }
-    }
-
-    private void adjustScreenOrientation(State state) {
-        if (state.isKeyguardShowingAndNotOccluded() || state.dozing) {
-            if (mKeyguardScreenRotation) {
-                mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
-            } else {
-                mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-            }
-        } else {
-            mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-        }
-    }
-
-    private void applyFocusableFlag(State state) {
-        boolean panelFocusable = state.statusBarFocusable && state.panelExpanded;
-        if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput)
-                || ENABLE_REMOTE_INPUT && state.remoteInputActive) {
-            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
-            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        } else {
-            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        }
-
-        mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-    }
-
-    private void applyHeight(State state) {
-        boolean expanded = isExpanded(state);
-        if (state.forcePluginOpen) {
-            mListener.setWouldOtherwiseCollapse(expanded);
-            expanded = true;
-        }
-        if (expanded) {
-            mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
-        } else {
-            mLpChanged.height = mBarHeight;
-        }
-    }
-
-    private boolean isExpanded(State state) {
-        return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
-                || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
-                || state.headsUpShowing
-                || state.scrimsVisibility != ScrimController.VISIBILITY_FULLY_TRANSPARENT);
-    }
-
-    private void applyFitsSystemWindows(State state) {
-        boolean fitsSystemWindows = !state.isKeyguardShowingAndNotOccluded();
-        if (mStatusBarView.getFitsSystemWindows() != fitsSystemWindows) {
-            mStatusBarView.setFitsSystemWindows(fitsSystemWindows);
-            mStatusBarView.requestApplyInsets();
-        }
-    }
-
-    private void applyUserActivityTimeout(State state) {
-        if (state.isKeyguardShowingAndNotOccluded()
-                && state.statusBarState == StatusBarState.KEYGUARD
-                && !state.qsExpanded) {
-            mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
-        } else {
-            mLpChanged.userActivityTimeout = -1;
-        }
-    }
-
-    private void applyInputFeatures(State state) {
-        if (state.isKeyguardShowingAndNotOccluded()
-                && state.statusBarState == StatusBarState.KEYGUARD
-                && !state.qsExpanded && !state.forceUserActivity) {
-            mLpChanged.inputFeatures |=
-                    WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
-        } else {
-            mLpChanged.inputFeatures &=
-                    ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
-        }
-    }
-
-    private void apply(State state) {
-        applyKeyguardFlags(state);
-        applyForceStatusBarVisibleFlag(state);
-        applyFocusableFlag(state);
-        adjustScreenOrientation(state);
-        applyHeight(state);
-        applyUserActivityTimeout(state);
-        applyInputFeatures(state);
-        applyFitsSystemWindows(state);
-        applyModalFlag(state);
-        applyBrightness(state);
-        applyHasTopUi(state);
-        applySleepToken(state);
-        if (mLp.copyFrom(mLpChanged) != 0) {
-            mWindowManager.updateViewLayout(mStatusBarView, mLp);
-        }
-        if (mHasTopUi != mHasTopUiChanged) {
-            try {
-                mActivityManager.setHasTopUi(mHasTopUiChanged);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to call setHasTopUi", e);
-            }
-            mHasTopUi = mHasTopUiChanged;
-        }
-    }
-
-    private void applyForceStatusBarVisibleFlag(State state) {
-        if (state.forceStatusBarVisible) {
-            mLpChanged.privateFlags |= WindowManager
-                    .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
-        } else {
-            mLpChanged.privateFlags &= ~WindowManager
-                    .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
-        }
-    }
-
-    private void applyModalFlag(State state) {
-        if (state.headsUpShowing) {
-            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        } else {
-            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        }
-    }
-
-    private void applyBrightness(State state) {
-        if (state.forceDozeBrightness) {
-            mLpChanged.screenBrightness = mScreenBrightnessDoze;
-        } else {
-            mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
-        }
-    }
-
-    private void applyHasTopUi(State state) {
-        mHasTopUiChanged = isExpanded(state);
-    }
-
-    private void applySleepToken(State state) {
-        if (state.dozing) {
-            mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
-        } else {
-            mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
-        }
-    }
-
-    public void setKeyguardShowing(boolean showing) {
-        mCurrentState.keyguardShowing = showing;
-        apply(mCurrentState);
-    }
-
-    public void setKeyguardOccluded(boolean occluded) {
-        mCurrentState.keyguardOccluded = occluded;
-        apply(mCurrentState);
-    }
-
-    public void setKeyguardNeedsInput(boolean needsInput) {
-        mCurrentState.keyguardNeedsInput = needsInput;
-        apply(mCurrentState);
-    }
-
-    public void setPanelVisible(boolean visible) {
-        mCurrentState.panelVisible = visible;
-        mCurrentState.statusBarFocusable = visible;
-        apply(mCurrentState);
-    }
-
-    public void setStatusBarFocusable(boolean focusable) {
-        mCurrentState.statusBarFocusable = focusable;
-        apply(mCurrentState);
-    }
-
-    public void setBouncerShowing(boolean showing) {
-        mCurrentState.bouncerShowing = showing;
-        apply(mCurrentState);
-    }
-
-    public void setBackdropShowing(boolean showing) {
-        mCurrentState.backdropShowing = showing;
-        apply(mCurrentState);
-    }
-
-    public void setKeyguardFadingAway(boolean keyguardFadingAway) {
-        mCurrentState.keyguardFadingAway = keyguardFadingAway;
-        apply(mCurrentState);
-    }
-
-    public void setQsExpanded(boolean expanded) {
-        mCurrentState.qsExpanded = expanded;
-        apply(mCurrentState);
-    }
-
-    public void setForceUserActivity(boolean forceUserActivity) {
-        mCurrentState.forceUserActivity = forceUserActivity;
-        apply(mCurrentState);
-    }
-
-    public void setScrimsVisibility(int scrimsVisibility) {
-        mCurrentState.scrimsVisibility = scrimsVisibility;
-        apply(mCurrentState);
-    }
-
-    public void setHeadsUpShowing(boolean showing) {
-        mCurrentState.headsUpShowing = showing;
-        apply(mCurrentState);
-    }
-
-    public void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) {
-        mCurrentState.wallpaperSupportsAmbientMode = supportsAmbientMode;
-        apply(mCurrentState);
-    }
-
-    /**
-     * @param state The {@link StatusBarState} of the status bar.
-     */
-    public void setStatusBarState(int state) {
-        mCurrentState.statusBarState = state;
-        apply(mCurrentState);
-    }
-
-    public void setForceStatusBarVisible(boolean forceStatusBarVisible) {
-        mCurrentState.forceStatusBarVisible = forceStatusBarVisible;
-        apply(mCurrentState);
-    }
-
-    /**
-     * Force the window to be collapsed, even if it should theoretically be expanded.
-     * Used for when a heads-up comes in but we still need to wait for the touchable regions to
-     * be computed.
-     */
-    public void setForceWindowCollapsed(boolean force) {
-        mCurrentState.forceCollapsed = force;
-        apply(mCurrentState);
-    }
-
-    public void setPanelExpanded(boolean isExpanded) {
-        mCurrentState.panelExpanded = isExpanded;
-        apply(mCurrentState);
-    }
-
-    @Override
-    public void onRemoteInputActive(boolean remoteInputActive) {
-        mCurrentState.remoteInputActive = remoteInputActive;
-        apply(mCurrentState);
-    }
-
-    /**
-     * Set whether the screen brightness is forced to the value we use for doze mode by the status
-     * bar window.
-     */
-    public void setForceDozeBrightness(boolean forceDozeBrightness) {
-        mCurrentState.forceDozeBrightness = forceDozeBrightness;
-        apply(mCurrentState);
-    }
-
-    public void setDozing(boolean dozing) {
-        mCurrentState.dozing = dozing;
-        apply(mCurrentState);
-    }
-
-    public void setBarHeight(int barHeight) {
-        mBarHeight = barHeight;
-        apply(mCurrentState);
-    }
-
-    public void setForcePluginOpen(boolean forcePluginOpen) {
-        mCurrentState.forcePluginOpen = forcePluginOpen;
-        apply(mCurrentState);
-    }
-
-    public void setStateListener(OtherwisedCollapsedListener listener) {
-        mListener = listener;
-    }
-
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("StatusBarWindowManager state:");
-        pw.println(mCurrentState);
-    }
-
-    public boolean isShowingWallpaper() {
-        return !mCurrentState.backdropShowing;
-    }
-
-    private static class State {
-        boolean keyguardShowing;
-        boolean keyguardOccluded;
-        boolean keyguardNeedsInput;
-        boolean panelVisible;
-        boolean panelExpanded;
-        boolean statusBarFocusable;
-        boolean bouncerShowing;
-        boolean keyguardFadingAway;
-        boolean qsExpanded;
-        boolean headsUpShowing;
-        boolean forceStatusBarVisible;
-        boolean forceCollapsed;
-        boolean forceDozeBrightness;
-        boolean forceUserActivity;
-        boolean backdropShowing;
-        boolean wallpaperSupportsAmbientMode;
-
-        /**
-         * The {@link StatusBar} state from the status bar.
-         */
-        int statusBarState;
-
-        boolean remoteInputActive;
-        boolean forcePluginOpen;
-        boolean dozing;
-        int scrimsVisibility;
-
-        private boolean isKeyguardShowingAndNotOccluded() {
-            return keyguardShowing && !keyguardOccluded;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder result = new StringBuilder();
-            String newLine = "\n";
-            result.append("Window State {");
-            result.append(newLine);
-
-            Field[] fields = this.getClass().getDeclaredFields();
-
-            // Print field names paired with their values
-            for (Field field : fields) {
-                result.append("  ");
-                try {
-                    result.append(field.getName());
-                    result.append(": ");
-                    //requires access to private field:
-                    result.append(field.get(this));
-                } catch (IllegalAccessException ex) {
-                }
-                result.append(newLine);
-            }
-            result.append("}");
-
-            return result.toString();
-        }
-    }
-
-    /**
-     * Custom listener to pipe data back to plugins about whether or not the status bar would be
-     * collapsed if not for the plugin.
-     * TODO: Find cleaner way to do this.
-     */
-    public interface OtherwisedCollapsedListener {
-        void setWouldOtherwiseCollapse(boolean otherwiseCollapse);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index fa763c8..98f1a36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -57,11 +57,13 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.view.FloatingActionMode;
 import com.android.internal.widget.FloatingToolbar;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -95,6 +97,8 @@
     private boolean mTouchActive;
     private boolean mExpandAnimationRunning;
     private boolean mExpandAnimationPending;
+    private final StatusBarStateController
+            mStatusBarStateController = Dependency.get(StatusBarStateController.class);
 
     /**
      * If set to true, the current gesture started below the notch and we need to dispatch touch
@@ -211,7 +215,8 @@
 
     public void setService(StatusBar service) {
         mService = service;
-        setDragDownHelper(new DragDownHelper(getContext(), this, mStackScrollLayout, mService));
+        setDragDownHelper(new DragDownHelper(getContext(), this, mStackScrollLayout,
+                mStackScrollLayout));
     }
 
     @VisibleForTesting
@@ -346,7 +351,7 @@
         boolean intercept = false;
         if (mNotificationPanel.isFullyExpanded()
                 && mStackScrollLayout.getVisibility() == View.VISIBLE
-                && mService.getBarState() == StatusBarState.KEYGUARD
+                && mStatusBarStateController.getState() == StatusBarState.KEYGUARD
                 && !mService.isBouncerShowing()
                 && !mService.isDozing()) {
             intercept = mDragDownHelper.onInterceptTouchEvent(ev);
@@ -371,7 +376,7 @@
             mDoubleTapHelper.onTouchEvent(ev);
             handled = true;
         }
-        if ((mService.getBarState() == StatusBarState.KEYGUARD && !handled)
+        if ((mStatusBarStateController.getState() == StatusBarState.KEYGUARD && !handled)
                 || mDragDownHelper.isDraggingDown()) {
             // we still want to finish our drag down gesture when locking the screen
             handled = mDragDownHelper.onTouchEvent(ev);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index f8f6981..56a177e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -33,9 +33,9 @@
 import com.android.keyguard.AlphaOptimizedLinearLayout;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusIconDisplayable;
-import com.android.systemui.statusbar.stack.AnimationFilter;
-import com.android.systemui.statusbar.stack.AnimationProperties;
-import com.android.systemui.statusbar.stack.ViewState;
+import com.android.systemui.statusbar.notification.stack.AnimationFilter;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.ViewState;
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
index dc1b35d..2ed2edb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
@@ -45,25 +45,18 @@
         final int N = a.getIndexCount();
         for (int i = 0; i < N; i++) {
             int attr = a.getIndex(i);
-            switch (attr) {
-                case R.styleable.UserAvatarView_avatarPadding:
-                    setAvatarPadding(a.getDimension(attr, 0));
-                    break;
-                case R.styleable.UserAvatarView_frameWidth:
-                    setFrameWidth(a.getDimension(attr, 0));
-                    break;
-                case R.styleable.UserAvatarView_framePadding:
-                    setFramePadding(a.getDimension(attr, 0));
-                    break;
-                case R.styleable.UserAvatarView_frameColor:
-                    setFrameColor(a.getColorStateList(attr));
-                    break;
-                case R.styleable.UserAvatarView_badgeDiameter:
-                    setBadgeDiameter(a.getDimension(attr, 0));
-                    break;
-                case R.styleable.UserAvatarView_badgeMargin:
-                    setBadgeMargin(a.getDimension(attr, 0));
-                    break;
+            if (attr == R.styleable.UserAvatarView_avatarPadding) {
+                setAvatarPadding(a.getDimension(attr, 0));
+            } else if (attr == R.styleable.UserAvatarView_frameWidth) {
+                setFrameWidth(a.getDimension(attr, 0));
+            } else if (attr == R.styleable.UserAvatarView_framePadding) {
+                setFramePadding(a.getDimension(attr, 0));
+            } else if (attr == R.styleable.UserAvatarView_frameColor) {
+                setFrameColor(a.getColorStateList(attr));
+            } else if (attr == R.styleable.UserAvatarView_badgeDiameter) {
+                setBadgeDiameter(a.getDimension(attr, 0));
+            } else if (attr == R.styleable.UserAvatarView_badgeMargin) {
+                setBadgeMargin(a.getDimension(attr, 0));
             }
         }
         a.recycle();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 8df51db..1085b06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -239,11 +239,6 @@
     }
 
     @Override
-    public void onScanningStateChanged(boolean started) {
-        // Don't care.
-    }
-
-    @Override
     public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
         cachedDevice.registerCallback(this);
         updateConnected();
@@ -277,12 +272,6 @@
         mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
     }
 
-    @Override
-    public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {}
-
-    @Override
-    public void onAudioModeChanged() {}
-
     private ActuallyCachedState getCachedState(CachedBluetoothDevice device) {
         ActuallyCachedState state = mCachedState.get(device);
         if (state == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index e9bdc68..b198678 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.content.res.Resources;
 import android.util.ArraySet;
-import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
@@ -105,11 +104,9 @@
     }
 
     private void reinflate() {
-        ContextThemeWrapper qsThemeContext =
-                new ContextThemeWrapper(mBrightnessMirror.getContext(), R.style.qs_theme);
         int index = mStatusBarWindow.indexOfChild(mBrightnessMirror);
         mStatusBarWindow.removeView(mBrightnessMirror);
-        mBrightnessMirror = LayoutInflater.from(qsThemeContext).inflate(
+        mBrightnessMirror = LayoutInflater.from(mBrightnessMirror.getContext()).inflate(
                 R.layout.brightness_mirror, mStatusBarWindow, false);
         mStatusBarWindow.addView(mBrightnessMirror, index);
 
@@ -129,6 +126,10 @@
         mBrightnessMirrorListeners.remove(listener);
     }
 
+    public void onUiModeChanged() {
+        reinflate();
+    }
+
     public interface BrightnessMirrorListener {
         void onBrightnessMirrorReinflated(View brightnessMirror);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 2bf62bb..533bd86 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -30,6 +30,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.systemui.R;
 
 import java.io.FileDescriptor;
@@ -41,12 +42,16 @@
 
 import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
 
+import androidx.annotation.VisibleForTesting;
+
+
 /** Platform implementation of the cast controller. **/
 public class CastControllerImpl implements CastController {
     private static final String TAG = "CastController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
+    @GuardedBy("mCallbacks")
     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
     private final MediaRouter mMediaRouter;
     private final ArrayMap<String, RouteInfo> mRoutes = new ArrayMap<>();
@@ -72,7 +77,7 @@
         pw.println("CastController state:");
         pw.print("  mDiscovering="); pw.println(mDiscovering);
         pw.print("  mCallbackRegistered="); pw.println(mCallbackRegistered);
-        pw.print("  mCallbacks.size="); pw.println(mCallbacks.size());
+        pw.print("  mCallbacks.size="); synchronized (mCallbacks) {pw.println(mCallbacks.size());}
         pw.print("  mRoutes.size="); pw.println(mRoutes.size());
         for (int i = 0; i < mRoutes.size(); i++) {
             final RouteInfo route = mRoutes.valueAt(i);
@@ -83,7 +88,9 @@
 
     @Override
     public void addCallback(Callback callback) {
-        mCallbacks.add(callback);
+        synchronized (mCallbacks) {
+            mCallbacks.add(callback);
+        }
         fireOnCastDevicesChanged(callback);
         synchronized (mDiscoveringLock) {
             handleDiscoveryChangeLocked();
@@ -92,7 +99,9 @@
 
     @Override
     public void removeCallback(Callback callback) {
-        mCallbacks.remove(callback);
+        synchronized (mCallbacks) {
+            mCallbacks.remove(callback);
+        }
         synchronized (mDiscoveringLock) {
             handleDiscoveryChangeLocked();
         }
@@ -117,10 +126,16 @@
             mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
                     MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
             mCallbackRegistered = true;
-        } else if (mCallbacks.size() != 0) {
-            mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
-                    MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
-            mCallbackRegistered = true;
+        } else {
+            boolean hasCallbacks = false;
+            synchronized (mCallbacks) {
+                hasCallbacks = mCallbacks.isEmpty();
+            }
+            if (!hasCallbacks) {
+                mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
+                        MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
+                mCallbackRegistered = true;
+            }
         }
     }
 
@@ -248,12 +263,17 @@
         }
     }
 
-    private void fireOnCastDevicesChanged() {
-        for (Callback callback : mCallbacks) {
-            fireOnCastDevicesChanged(callback);
+    @VisibleForTesting
+    void fireOnCastDevicesChanged() {
+        synchronized (mCallbacks) {
+            for (Callback callback : mCallbacks) {
+                fireOnCastDevicesChanged(callback);
+            }
+
         }
     }
 
+
     private void fireOnCastDevicesChanged(Callback callback) {
         callback.onCastDevicesChanged();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
index 3dca371..0e5c8c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -24,10 +24,14 @@
  */
 public interface ConfigurationController extends CallbackController<ConfigurationListener> {
 
+    public void notifyThemeChanged();
+
     interface ConfigurationListener {
         default void onConfigChanged(Configuration newConfig) {}
         default void onDensityOrFontScaleChanged() {}
         default void onOverlayChanged() {}
+        default void onUiModeChanged() {}
+        default void onThemeChanged() {}
         default void onLocaleListChanged() {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index aeda55a..d477587 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -21,56 +21,44 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.os.SystemClock;
-import android.os.Handler;
-import android.os.Looper;
 import android.util.ArrayMap;
 import android.provider.Settings;
 import android.util.Log;
-import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.AlertingNotificationManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.NotificationData;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.Iterator;
-import java.util.stream.Stream;
-import java.util.HashMap;
 import java.util.HashSet;
 
 /**
  * A manager which handles heads up notifications which is a special mode where
  * they simply peek from the top of the screen.
  */
-public class HeadsUpManager {
+public abstract class HeadsUpManager extends AlertingNotificationManager {
     private static final String TAG = "HeadsUpManager";
-    private static final boolean DEBUG = false;
     private static final String SETTING_HEADS_UP_SNOOZE_LENGTH_MS = "heads_up_snooze_length_ms";
 
-    protected final Clock mClock = new Clock();
     protected final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>();
-    protected final Handler mHandler = new Handler(Looper.getMainLooper());
 
     protected final Context mContext;
 
-    protected int mHeadsUpNotificationDecay;
-    protected int mMinimumDisplayTime;
     protected int mTouchAcceptanceDelay;
     protected int mSnoozeLengthMs;
     protected boolean mHasPinnedNotification;
     protected int mUser;
 
-    private final HashMap<String, HeadsUpEntry> mHeadsUpEntries = new HashMap<>();
     private final ArrayMap<String, Long> mSnoozedPackages;
 
     public HeadsUpManager(@NonNull final Context context) {
         mContext = context;
         Resources resources = context.getResources();
         mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time);
-        mHeadsUpNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay);
+        mAutoDismissNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay);
         mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
         mSnoozedPackages = new ArrayMap<>();
         int defaultSnoozeLengthMs =
@@ -85,7 +73,9 @@
                         context.getContentResolver(), SETTING_HEADS_UP_SNOOZE_LENGTH_MS, -1);
                 if (packageSnoozeLengthMs > -1 && packageSnoozeLengthMs != mSnoozeLengthMs) {
                     mSnoozeLengthMs = packageSnoozeLengthMs;
-                    if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs);
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs);
+                    }
                 }
             }
         };
@@ -108,49 +98,14 @@
         mListeners.remove(listener);
     }
 
-    /**
-     * Called when posting a new notification to the heads up.
-     */
-    public void showNotification(@NonNull NotificationData.Entry headsUp) {
-        if (DEBUG) Log.v(TAG, "showNotification");
-        addHeadsUpEntry(headsUp);
-        updateNotification(headsUp, true);
-        headsUp.setInterruption();
-    }
-
-    /**
-     * Called when updating or posting a notification to the heads up.
-     */
-    public void updateNotification(@NonNull NotificationData.Entry headsUp, boolean alert) {
-        if (DEBUG) Log.v(TAG, "updateNotification");
-
-        headsUp.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
-
-        if (alert) {
-            HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(headsUp.key);
-            if (headsUpEntry == null) {
-                // the entry was released before this update (i.e by a listener) This can happen
-                // with the groupmanager
-                return;
-            }
-            headsUpEntry.updateEntry(true /* updatePostTime */);
-            setEntryPinned(headsUpEntry, shouldHeadsUpBecomePinned(headsUp));
+    public void updateNotification(@NonNull String key, boolean alert) {
+        super.updateNotification(key, alert);
+        AlertEntry alertEntry = getHeadsUpEntry(key);
+        if (alert && alertEntry != null) {
+            setEntryPinned((HeadsUpEntry) alertEntry, shouldHeadsUpBecomePinned(alertEntry.mEntry));
         }
     }
 
-    private void addHeadsUpEntry(@NonNull NotificationData.Entry entry) {
-        HeadsUpEntry headsUpEntry = createHeadsUpEntry();
-        // This will also add the entry to the sortedList
-        headsUpEntry.setEntry(entry);
-        mHeadsUpEntries.put(entry.key, headsUpEntry);
-        entry.row.setHeadsUp(true);
-        setEntryPinned(headsUpEntry, shouldHeadsUpBecomePinned(entry));
-        for (OnHeadsUpChangedListener listener : mListeners) {
-            listener.onHeadsUpStateChanged(entry, true);
-        }
-        entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
-    }
-
     protected boolean shouldHeadsUpBecomePinned(@NonNull NotificationData.Entry entry) {
         return hasFullScreenIntent(entry);
     }
@@ -161,8 +116,10 @@
 
     protected void setEntryPinned(
             @NonNull HeadsUpManager.HeadsUpEntry headsUpEntry, boolean isPinned) {
-        if (DEBUG) Log.v(TAG, "setEntryPinned: " + isPinned);
-        ExpandableNotificationRow row = headsUpEntry.entry.row;
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "setEntryPinned: " + isPinned);
+        }
+        ExpandableNotificationRow row = headsUpEntry.mEntry.row;
         if (row.isPinned() != isPinned) {
             row.setPinned(isPinned);
             updatePinnedMode();
@@ -176,20 +133,24 @@
         }
     }
 
-    protected void removeHeadsUpEntry(@NonNull NotificationData.Entry entry) {
-        HeadsUpEntry remove = mHeadsUpEntries.remove(entry.key);
-        onHeadsUpEntryRemoved(remove);
+    @Override
+    protected void onAlertEntryAdded(AlertEntry alertEntry) {
+        NotificationData.Entry entry = alertEntry.mEntry;
+        entry.row.setHeadsUp(true);
+        setEntryPinned((HeadsUpEntry) alertEntry, shouldHeadsUpBecomePinned(entry));
+        for (OnHeadsUpChangedListener listener : mListeners) {
+            listener.onHeadsUpStateChanged(entry, true);
+        }
     }
 
-    protected void onHeadsUpEntryRemoved(@NonNull HeadsUpEntry remove) {
-        NotificationData.Entry entry = remove.entry;
-        entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+    @Override
+    protected void onAlertEntryRemoved(AlertEntry alertEntry) {
+        NotificationData.Entry entry = alertEntry.mEntry;
         entry.row.setHeadsUp(false);
-        setEntryPinned(remove, false /* isPinned */);
+        setEntryPinned((HeadsUpEntry) alertEntry, false /* isPinned */);
         for (OnHeadsUpChangedListener listener : mListeners) {
             listener.onHeadsUpStateChanged(entry, false);
         }
-        releaseHeadsUpEntry(remove);
     }
 
     protected void updatePinnedMode() {
@@ -197,7 +158,7 @@
         if (hasPinnedNotification == mHasPinnedNotification) {
             return;
         }
-        if (DEBUG) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "Pinned mode changed: " + mHasPinnedNotification + " -> " +
                        hasPinnedNotification);
         }
@@ -211,50 +172,6 @@
     }
 
     /**
-     * React to the removal of the notification in the heads up.
-     *
-     * @return true if the notification was removed and false if it still needs to be kept around
-     * for a bit since it wasn't shown long enough
-     */
-    public boolean removeNotification(@NonNull String key, boolean ignoreEarliestRemovalTime) {
-        if (DEBUG) Log.v(TAG, "removeNotification");
-        releaseImmediately(key);
-        return true;
-    }
-
-    /**
-     * Returns if the given notification is in the Heads Up Notification list or not.
-     */
-    public boolean isHeadsUp(@NonNull String key) {
-        return mHeadsUpEntries.containsKey(key);
-    }
-
-    /**
-     * Pushes any current Heads Up notification down into the shade.
-     */
-    public void releaseAllImmediately() {
-        if (DEBUG) Log.v(TAG, "releaseAllImmediately");
-        Iterator<HeadsUpEntry> iterator = mHeadsUpEntries.values().iterator();
-        while (iterator.hasNext()) {
-            HeadsUpEntry entry = iterator.next();
-            iterator.remove();
-            onHeadsUpEntryRemoved(entry);
-        }
-    }
-
-    /**
-     * Pushes the given Heads Up notification down into the shade.
-     */
-    public void releaseImmediately(@NonNull String key) {
-        HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
-        if (headsUpEntry == null) {
-            return;
-        }
-        NotificationData.Entry shadeEntry = headsUpEntry.entry;
-        removeHeadsUpEntry(shadeEntry);
-    }
-
-    /**
      * Returns if the given notification is snoozed or not.
      */
     public boolean isSnoozed(@NonNull String packageName) {
@@ -262,7 +179,9 @@
         Long snoozedUntil = mSnoozedPackages.get(key);
         if (snoozedUntil != null) {
             if (snoozedUntil > mClock.currentTimeMillis()) {
-                if (DEBUG) Log.v(TAG, key + " snoozed");
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, key + " snoozed");
+                }
                 return true;
             }
             mSnoozedPackages.remove(packageName);
@@ -274,9 +193,9 @@
      * Snoozes all current Heads Up Notifications.
      */
     public void snooze() {
-        for (String key : mHeadsUpEntries.keySet()) {
-            HeadsUpEntry entry = mHeadsUpEntries.get(key);
-            String packageName = entry.entry.notification.getPackageName();
+        for (String key : mAlertEntries.keySet()) {
+            AlertEntry entry = getHeadsUpEntry(key);
+            String packageName = entry.mEntry.notification.getPackageName();
             mSnoozedPackages.put(snoozeKey(packageName, mUser),
                     mClock.currentTimeMillis() + mSnoozeLengthMs);
         }
@@ -289,53 +208,27 @@
 
     @Nullable
     protected HeadsUpEntry getHeadsUpEntry(@NonNull String key) {
-        return mHeadsUpEntries.get(key);
+        return (HeadsUpEntry) mAlertEntries.get(key);
     }
 
     /**
-     * Returns the entry of given Heads Up Notification.
-     *
-     * @param key Key of heads up notification
-     */
-    @Nullable
-    public NotificationData.Entry getEntry(@NonNull String key) {
-        HeadsUpEntry entry = mHeadsUpEntries.get(key);
-        return entry != null ? entry.entry : null;
-    }
-
-    /**
-     * Returns the stream of all current Heads Up Notifications.
-     */
-    @NonNull
-    public Stream<NotificationData.Entry> getAllEntries() {
-        return mHeadsUpEntries.values().stream().map(headsUpEntry -> headsUpEntry.entry);
-    }
-
-    /**
-     * Returns the top Heads Up Notification, which appeares to show at first.
+     * Returns the top Heads Up Notification, which appears to show at first.
      */
     @Nullable
     public NotificationData.Entry getTopEntry() {
         HeadsUpEntry topEntry = getTopHeadsUpEntry();
-        return (topEntry != null) ? topEntry.entry : null;
-    }
-
-    /**
-     * Returns if any heads up notification is available or not.
-     */
-    public boolean hasHeadsUpNotifications() {
-        return !mHeadsUpEntries.isEmpty();
+        return (topEntry != null) ? topEntry.mEntry : null;
     }
 
     @Nullable
     protected HeadsUpEntry getTopHeadsUpEntry() {
-        if (mHeadsUpEntries.isEmpty()) {
+        if (mAlertEntries.isEmpty()) {
             return null;
         }
         HeadsUpEntry topEntry = null;
-        for (HeadsUpEntry entry: mHeadsUpEntries.values()) {
+        for (AlertEntry entry: mAlertEntries.values()) {
             if (topEntry == null || entry.compareTo(topEntry) < 0) {
-                topEntry = entry;
+                topEntry = (HeadsUpEntry) entry;
             }
         }
         return topEntry;
@@ -359,8 +252,8 @@
         pw.print("  mSnoozeLengthMs="); pw.println(mSnoozeLengthMs);
         pw.print("  now="); pw.println(mClock.currentTimeMillis());
         pw.print("  mUser="); pw.println(mUser);
-        for (HeadsUpEntry entry: mHeadsUpEntries.values()) {
-            pw.print("  HeadsUpEntry="); pw.println(entry.entry);
+        for (AlertEntry entry: mAlertEntries.values()) {
+            pw.print("  HeadsUpEntry="); pw.println(entry.mEntry);
         }
         int N = mSnoozedPackages.size();
         pw.println("  snoozed packages: " + N);
@@ -378,9 +271,9 @@
     }
 
     private boolean hasPinnedNotificationInternal() {
-        for (String key : mHeadsUpEntries.keySet()) {
-            HeadsUpEntry entry = mHeadsUpEntries.get(key);
-            if (entry.entry.row.isPinned()) {
+        for (String key : mAlertEntries.keySet()) {
+            AlertEntry entry = getHeadsUpEntry(key);
+            if (entry.mEntry.row.isPinned()) {
                 return true;
             }
         }
@@ -389,13 +282,23 @@
 
     /**
      * Unpins all pinned Heads Up Notifications.
+     * @param userUnPinned The unpinned action is trigger by user real operation.
      */
-    public void unpinAll() {
-        for (String key : mHeadsUpEntries.keySet()) {
-            HeadsUpEntry entry = mHeadsUpEntries.get(key);
+    public void unpinAll(boolean userUnPinned) {
+        for (String key : mAlertEntries.keySet()) {
+            HeadsUpEntry entry = getHeadsUpEntry(key);
             setEntryPinned(entry, false /* isPinned */);
             // maybe it got un sticky
             entry.updateEntry(false /* updatePostTime */);
+
+            // when the user unpinned all of HUNs by moving one HUN, all of HUNs should not stay
+            // on the screen.
+            if (userUnPinned && entry.mEntry != null && entry.mEntry.row != null) {
+                ExpandableNotificationRow row = entry.mEntry.row;
+                if (row.mustStayOnScreen()) {
+                    row.setHeadsUpIsVisible();
+                }
+            }
         }
     }
 
@@ -415,8 +318,8 @@
      * one should be ranked higher and 0 if they are equal.
      */
     public int compare(@NonNull NotificationData.Entry a, @NonNull NotificationData.Entry b) {
-        HeadsUpEntry aEntry = getHeadsUpEntry(a.key);
-        HeadsUpEntry bEntry = getHeadsUpEntry(b.key);
+        AlertEntry aEntry = getHeadsUpEntry(a.key);
+        AlertEntry bEntry = getHeadsUpEntry(b.key);
         if (aEntry == null || bEntry == null) {
             return aEntry == null ? 1 : -1;
         }
@@ -428,21 +331,18 @@
      * until it's collapsed again.
      */
     public void setExpanded(@NonNull NotificationData.Entry entry, boolean expanded) {
-        HeadsUpManager.HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(entry.key);
+        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.key);
         if (headsUpEntry != null && entry.row.isPinned()) {
-            headsUpEntry.expanded(expanded);
+            headsUpEntry.setExpanded(expanded);
         }
     }
 
     @NonNull
-    protected HeadsUpEntry createHeadsUpEntry() {
+    @Override
+    protected HeadsUpEntry createAlertEntry() {
         return new HeadsUpEntry();
     }
 
-    protected void releaseHeadsUpEntry(@NonNull HeadsUpEntry entry) {
-        entry.reset();
-    }
-
     public void onDensityOrFontScaleChanged() {
     }
 
@@ -450,108 +350,58 @@
      * This represents a notification and how long it is in a heads up mode. It also manages its
      * lifecycle automatically when created.
      */
-    protected class HeadsUpEntry implements Comparable<HeadsUpEntry> {
-        @Nullable public NotificationData.Entry entry;
-        public long postTime;
+    protected class HeadsUpEntry extends AlertEntry {
         public boolean remoteInputActive;
-        public long earliestRemovaltime;
-        public boolean expanded;
+        protected boolean expanded;
 
-        @Nullable private Runnable mRemoveHeadsUpRunnable;
-
-        public void setEntry(@Nullable final NotificationData.Entry entry) {
-            setEntry(entry, null);
-        }
-
-        public void setEntry(@Nullable final NotificationData.Entry entry,
-                @Nullable Runnable removeHeadsUpRunnable) {
-            this.entry = entry;
-            this.mRemoveHeadsUpRunnable = removeHeadsUpRunnable;
-
-            // The actual post time will be just after the heads-up really slided in
-            postTime = mClock.currentTimeMillis() + mTouchAcceptanceDelay;
-            updateEntry(true /* updatePostTime */);
-        }
-
-        public void updateEntry(boolean updatePostTime) {
-            if (DEBUG) Log.v(TAG, "updateEntry");
-
-            long currentTime = mClock.currentTimeMillis();
-            earliestRemovaltime = currentTime + mMinimumDisplayTime;
-            if (updatePostTime) {
-                postTime = Math.max(postTime, currentTime);
-            }
-            removeAutoRemovalCallbacks();
-
-            if (!isSticky()) {
-                long finishTime = postTime + mHeadsUpNotificationDecay;
-                long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime);
-                mHandler.postDelayed(mRemoveHeadsUpRunnable, removeDelay);
-            }
-        }
-
-        private boolean isSticky() {
-            return (entry.row.isPinned() && expanded)
-                    || remoteInputActive || hasFullScreenIntent(entry);
+        @Override
+        protected boolean isSticky() {
+            return (mEntry.row.isPinned() && expanded)
+                    || remoteInputActive || hasFullScreenIntent(mEntry);
         }
 
         @Override
-        public int compareTo(@NonNull HeadsUpEntry o) {
-            boolean isPinned = entry.row.isPinned();
-            boolean otherPinned = o.entry.row.isPinned();
+        public int compareTo(@NonNull AlertEntry alertEntry) {
+            HeadsUpEntry headsUpEntry = (HeadsUpEntry) alertEntry;
+            boolean isPinned = mEntry.row.isPinned();
+            boolean otherPinned = headsUpEntry.mEntry.row.isPinned();
             if (isPinned && !otherPinned) {
                 return -1;
             } else if (!isPinned && otherPinned) {
                 return 1;
             }
-            boolean selfFullscreen = hasFullScreenIntent(entry);
-            boolean otherFullscreen = hasFullScreenIntent(o.entry);
+            boolean selfFullscreen = hasFullScreenIntent(mEntry);
+            boolean otherFullscreen = hasFullScreenIntent(headsUpEntry.mEntry);
             if (selfFullscreen && !otherFullscreen) {
                 return -1;
             } else if (!selfFullscreen && otherFullscreen) {
                 return 1;
             }
 
-            if (remoteInputActive && !o.remoteInputActive) {
+            if (remoteInputActive && !headsUpEntry.remoteInputActive) {
                 return -1;
-            } else if (!remoteInputActive && o.remoteInputActive) {
+            } else if (!remoteInputActive && headsUpEntry.remoteInputActive) {
                 return 1;
             }
 
-            return postTime < o.postTime ? 1
-                    : postTime == o.postTime ? entry.key.compareTo(o.entry.key)
-                            : -1;
+            return super.compareTo(headsUpEntry);
         }
 
-        public void expanded(boolean expanded) {
+        public void setExpanded(boolean expanded) {
             this.expanded = expanded;
         }
 
+        @Override
         public void reset() {
-            entry = null;
+            super.reset();
             expanded = false;
             remoteInputActive = false;
-            removeAutoRemovalCallbacks();
-            mRemoveHeadsUpRunnable = null;
         }
 
-        public void removeAutoRemovalCallbacks() {
-            if (mRemoveHeadsUpRunnable != null)
-                mHandler.removeCallbacks(mRemoveHeadsUpRunnable);
-        }
-
-        public void removeAsSoonAsPossible() {
-            if (mRemoveHeadsUpRunnable != null) {
-                removeAutoRemovalCallbacks();
-                mHandler.postDelayed(mRemoveHeadsUpRunnable,
-                        earliestRemovaltime - mClock.currentTimeMillis());
-            }
-        }
-    }
-
-    public static class Clock {
-        public long currentTimeMillis() {
-            return SystemClock.elapsedRealtime();
+        @Override
+        protected long calculatePostTime() {
+            // The actual post time will be just after the heads-up really slided in
+            return super.calculatePostTime() + mTouchAcceptanceDelay;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
index 1a85c47..8e31f31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -22,6 +22,7 @@
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
+import android.util.FloatProperty;
 import android.view.Gravity;
 
 import com.android.systemui.R;
@@ -33,6 +34,32 @@
  */
 public class KeyButtonDrawable extends LayerDrawable {
 
+    public static final FloatProperty<KeyButtonDrawable> KEY_DRAWABLE_ROTATE =
+        new FloatProperty<KeyButtonDrawable>("KeyButtonRotation") {
+            @Override
+            public void setValue(KeyButtonDrawable drawable, float degree) {
+                drawable.setRotation(degree);
+            }
+
+            @Override
+            public Float get(KeyButtonDrawable drawable) {
+                return drawable.getRotation();
+            }
+        };
+
+    public static final FloatProperty<KeyButtonDrawable> KEY_DRAWABLE_TRANSLATE_Y =
+        new FloatProperty<KeyButtonDrawable>("KeyButtonTranslateY") {
+            @Override
+            public void setValue(KeyButtonDrawable drawable, float y) {
+                drawable.setTranslationY(y);
+            }
+
+            @Override
+            public Float get(KeyButtonDrawable drawable) {
+                return drawable.getTranslationY();
+            }
+        };
+
     private final boolean mHasDarkDrawable;
 
     public static KeyButtonDrawable create(Context lightContext, Drawable lightDrawable,
@@ -83,4 +110,33 @@
             ((ShadowKeyDrawable) getDrawable(1)).setRotation(degrees);
         }
     }
+
+    public void setTranslationY(float y) {
+        if (getDrawable(0) instanceof ShadowKeyDrawable) {
+            ((ShadowKeyDrawable) getDrawable(0)).setTranslationY(y);
+        }
+        if (mHasDarkDrawable && getDrawable(1) instanceof ShadowKeyDrawable) {
+            ((ShadowKeyDrawable) getDrawable(1)).setTranslationY(y);
+        }
+    }
+
+    public float getRotation() {
+        if (getDrawable(0) instanceof ShadowKeyDrawable) {
+            return ((ShadowKeyDrawable) getDrawable(0)).getRotation();
+        }
+        if (mHasDarkDrawable && getDrawable(1) instanceof ShadowKeyDrawable) {
+            return ((ShadowKeyDrawable) getDrawable(1)).getRotation();
+        }
+        return 0;
+    }
+
+    public float getTranslationY() {
+        if (getDrawable(0) instanceof ShadowKeyDrawable) {
+            return ((ShadowKeyDrawable) getDrawable(0)).getTranslationY();
+        }
+        if (mHasDarkDrawable && getDrawable(1) instanceof ShadowKeyDrawable) {
+            return ((ShadowKeyDrawable) getDrawable(1)).getTranslationY();
+        }
+        return 0;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index ccfbb26..7b42dd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -26,6 +26,7 @@
     boolean isKeyguardGoingAway();
     long getKeyguardFadingAwayDuration();
     long getKeyguardFadingAwayDelay();
+    long calculateGoingToFullShadeDelay();
 
     interface Callback {
         void onKeyguardShowingChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index 5ead02f..10cb09b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -157,6 +157,11 @@
         return mKeyguardFadingAwayDuration;
     }
 
+    @Override
+    public long calculateGoingToFullShadeDelay() {
+        return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
+    }
+
     public void notifyKeyguardGoingAway(boolean keyguardGoingAway) {
         mKeyguardGoingAway = keyguardGoingAway;
     }
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 25261c0..cf39404 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -16,6 +16,12 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN;
+import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
+import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
+import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -55,7 +61,6 @@
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 
-import com.android.systemui.statusbar.policy.MobileSignalController.MobileState;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -65,8 +70,6 @@
 import java.util.List;
 import java.util.Locale;
 
-import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
-
 /** Platform implementation of the network controller. **/
 public class NetworkControllerImpl extends BroadcastReceiver
         implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider,
@@ -849,20 +852,20 @@
                 if (activity != null) {
                     switch (activity) {
                         case "inout":
-                            mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_INOUT);
+                            mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT);
                             break;
                         case "in":
-                            mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_IN);
+                            mWifiSignalController.setActivity(DATA_ACTIVITY_IN);
                             break;
                         case "out":
-                            mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_OUT);
+                            mWifiSignalController.setActivity(DATA_ACTIVITY_OUT);
                             break;
                         default:
-                            mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_NONE);
+                            mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
                             break;
                     }
                 } else {
-                    mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_NONE);
+                    mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
                 }
                 String ssid = args.getString("ssid");
                 if (ssid != null) {
@@ -976,7 +979,7 @@
 
     private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
         SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
-                null, 0, 0, "");
+                null, null, null, "", false, null, null);
         MobileSignalController controller = new MobileSignalController(mContext,
                 mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
                 mSubDefaults, mReceiverHandler.getLooper());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
index 5444f06..5028fd1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.NotificationData;
 
 /**
  * A listener to heads up changes
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 b814478..52b813f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -39,7 +39,6 @@
 import android.view.View;
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.EditorInfo;
@@ -56,10 +55,10 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.notification.NotificationViewWrapper;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 import java.util.function.Consumer;
 
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 cda9d04..dd03162 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -31,7 +31,7 @@
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
@@ -127,19 +127,14 @@
         final int length = arr.getIndexCount();
         for (int i = 0; i < length; i++) {
             int attr = arr.getIndex(i);
-            switch (attr) {
-                case R.styleable.SmartReplyView_spacing:
-                    spacing = arr.getDimensionPixelSize(i, 0);
-                    break;
-                case R.styleable.SmartReplyView_singleLineButtonPaddingHorizontal:
-                    singleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0);
-                    break;
-                case R.styleable.SmartReplyView_doubleLineButtonPaddingHorizontal:
-                    doubleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0);
-                    break;
-                case R.styleable.SmartReplyView_buttonStrokeWidth:
-                    strokeWidth = arr.getDimensionPixelSize(i, 0);
-                    break;
+            if (attr == R.styleable.SmartReplyView_spacing) {
+                spacing = arr.getDimensionPixelSize(i, 0);
+            } else if (attr == R.styleable.SmartReplyView_singleLineButtonPaddingHorizontal) {
+                singleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0);
+            } else if (attr == R.styleable.SmartReplyView_doubleLineButtonPaddingHorizontal) {
+                doubleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0);
+            } else if (attr == R.styleable.SmartReplyView_buttonStrokeWidth) {
+                strokeWidth = arr.getDimensionPixelSize(i, 0);
             }
         }
         arr.recycle();
@@ -173,14 +168,14 @@
                 Math.max(getChildCount(), 1), DECREASING_MEASURED_WIDTH_WITHOUT_PADDING_COMPARATOR);
     }
 
-    public void setRepliesFromRemoteInput(RemoteInput remoteInput, PendingIntent pendingIntent,
+    public void setRepliesFromRemoteInput(
+            RemoteInput remoteInput, PendingIntent pendingIntent,
             SmartReplyController smartReplyController, NotificationData.Entry entry,
-            View smartReplyContainer) {
+            View smartReplyContainer, CharSequence[] choices) {
         mSmartReplyContainer = smartReplyContainer;
         removeAllViews();
         mCurrentBackgroundColor = mDefaultBackgroundColor;
         if (remoteInput != null && pendingIntent != null) {
-            CharSequence[] choices = remoteInput.getChoices();
             if (choices != null) {
                 for (int i = 0; i < choices.length; ++i) {
                     Button replyButton = inflateReplyButton(
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 cf80988..0233ad1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -15,21 +15,19 @@
  */
 package com.android.systemui.statusbar.policy;
 
+import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN;
+import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
+import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
+
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
 import android.net.NetworkScoreManager;
 import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
 import android.text.TextUtils;
-import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
 import com.android.settingslib.wifi.WifiStatusTracker;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -37,10 +35,8 @@
 
 import java.util.Objects;
 
-
 public class WifiSignalController extends
         SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
-    private final AsyncChannel mWifiChannel;
     private final boolean mHasMobileData;
     private final WifiStatusTracker mWifiTracker;
 
@@ -57,12 +53,7 @@
                 connectivityManager, this::handleStatusUpdated);
         mWifiTracker.setListening(true);
         mHasMobileData = hasMobileData;
-        Handler handler = new WifiHandler(Looper.getMainLooper());
-        mWifiChannel = new AsyncChannel();
-        Messenger wifiMessenger = wifiManager.getWifiServiceMessenger();
-        if (wifiMessenger != null) {
-            mWifiChannel.connect(context, handler, wifiMessenger);
-        }
+        wifiManager.registerTrafficStateCallback(new WifiTrafficStateCallback(),  null);
         // WiFi only has one state.
         mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
                 "Wi-Fi Icons",
@@ -124,39 +115,20 @@
 
     @VisibleForTesting
     void setActivity(int wifiActivity) {
-        mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
-                || wifiActivity == WifiManager.DATA_ACTIVITY_IN;
-        mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
-                || wifiActivity == WifiManager.DATA_ACTIVITY_OUT;
+        mCurrentState.activityIn = wifiActivity == DATA_ACTIVITY_INOUT
+                || wifiActivity == DATA_ACTIVITY_IN;
+        mCurrentState.activityOut = wifiActivity == DATA_ACTIVITY_INOUT
+                || wifiActivity == DATA_ACTIVITY_OUT;
         notifyListenersIfNecessary();
     }
 
     /**
      * Handler to receive the data activity on wifi.
      */
-    private class WifiHandler extends Handler {
-        WifiHandler(Looper looper) {
-            super(looper);
-        }
-
+    private class WifiTrafficStateCallback implements WifiManager.TrafficStateCallback {
         @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
-                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        mWifiChannel.sendMessage(Message.obtain(this,
-                                AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
-                    } else {
-                        Log.e(mTag, "Failed to connect to wifi");
-                    }
-                    break;
-                case WifiManager.DATA_ACTIVITY_NOTIFICATION:
-                    setActivity(msg.arg1);
-                    break;
-                default:
-                    // Ignore
-                    break;
-            }
+        public void onStateChanged(int state) {
+            setActivity(state);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
deleted file mode 100644
index db3f0d9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.view.View;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.ActivatableNotificationView;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-
-import java.util.ArrayList;
-
-/**
- * A global state to track all input states for the algorithm.
- */
-public class AmbientState {
-    private ArrayList<View> mDraggedViews = new ArrayList<View>();
-    private int mScrollY;
-    private boolean mDimmed;
-    private ActivatableNotificationView mActivatedChild;
-    private float mOverScrollTopAmount;
-    private float mOverScrollBottomAmount;
-    private int mSpeedBumpIndex = -1;
-    private boolean mDark;
-    private boolean mHideSensitive;
-    private HeadsUpManager mHeadsUpManager;
-    private float mStackTranslation;
-    private int mLayoutHeight;
-    private int mTopPadding;
-    private boolean mShadeExpanded;
-    private float mMaxHeadsUpTranslation;
-    private boolean mDismissAllInProgress;
-    private int mLayoutMinHeight;
-    private NotificationShelf mShelf;
-    private int mZDistanceBetweenElements;
-    private int mBaseZHeight;
-    private int mMaxLayoutHeight;
-    private ActivatableNotificationView mLastVisibleBackgroundChild;
-    private float mCurrentScrollVelocity;
-    private int mStatusBarState;
-    private float mExpandingVelocity;
-    private boolean mPanelTracking;
-    private boolean mExpansionChanging;
-    private boolean mPanelFullWidth;
-    private boolean mPulsing;
-    private boolean mUnlockHintRunning;
-    private boolean mQsCustomizerShowing;
-    private int mIntrinsicPadding;
-    private int mExpandAnimationTopChange;
-    private ExpandableNotificationRow mExpandingNotification;
-    private int mDarkTopPadding;
-    private float mDarkAmount;
-    private boolean mAppearing;
-
-    public AmbientState(Context context) {
-        reload(context);
-    }
-
-    /**
-     * Reload the dimens e.g. if the density changed.
-     */
-    public void reload(Context context) {
-        mZDistanceBetweenElements = getZDistanceBetweenElements(context);
-        mBaseZHeight = getBaseHeight(mZDistanceBetweenElements);
-    }
-
-    private static int getZDistanceBetweenElements(Context context) {
-        return Math.max(1, context.getResources()
-                .getDimensionPixelSize(R.dimen.z_distance_between_notifications));
-    }
-
-    private static int getBaseHeight(int zdistanceBetweenElements) {
-        return 4 * zdistanceBetweenElements;
-    }
-
-    /**
-     * @return the launch height for notifications that are launched
-     */
-    public static int getNotificationLaunchHeight(Context context) {
-        int zDistance = getZDistanceBetweenElements(context);
-        return getBaseHeight(zDistance) * 2;
-    }
-
-    /**
-     * @return the basic Z height on which notifications remain.
-     */
-    public int getBaseZHeight() {
-        return mBaseZHeight;
-    }
-
-    /**
-     * @return the distance in Z between two overlaying notifications.
-     */
-    public int getZDistanceBetweenElements() {
-        return mZDistanceBetweenElements;
-    }
-
-    public int getScrollY() {
-        return mScrollY;
-    }
-
-    public void setScrollY(int scrollY) {
-        this.mScrollY = scrollY;
-    }
-
-    public void onBeginDrag(View view) {
-        mDraggedViews.add(view);
-    }
-
-    public void onDragFinished(View view) {
-        mDraggedViews.remove(view);
-    }
-
-    public ArrayList<View> getDraggedViews() {
-        return mDraggedViews;
-    }
-
-    /**
-     * @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are
-     *               translucent and everything is scaled back a bit.
-     */
-    public void setDimmed(boolean dimmed) {
-        mDimmed = dimmed;
-    }
-
-    /** In dark mode, we draw as little as possible, assuming a black background */
-    public void setDark(boolean dark) {
-        mDark = dark;
-    }
-
-    /** Dark ratio of the status bar **/
-    public void setDarkAmount(float darkAmount) {
-        mDarkAmount = darkAmount;
-    }
-
-    /** Returns the dark ratio of the status bar */
-    public float getDarkAmount() {
-        return mDarkAmount;
-    }
-
-    public void setHideSensitive(boolean hideSensitive) {
-        mHideSensitive = hideSensitive;
-    }
-
-    /**
-     * In dimmed mode, a child can be activated, which happens on the first tap of the double-tap
-     * interaction. This child is then scaled normally and its background is fully opaque.
-     */
-    public void setActivatedChild(ActivatableNotificationView activatedChild) {
-        mActivatedChild = activatedChild;
-    }
-
-    public boolean isDimmed() {
-        return mDimmed;
-    }
-
-    public boolean isDark() {
-        return mDark;
-    }
-
-    public boolean isHideSensitive() {
-        return mHideSensitive;
-    }
-
-    public ActivatableNotificationView getActivatedChild() {
-        return mActivatedChild;
-    }
-
-    public void setOverScrollAmount(float amount, boolean onTop) {
-        if (onTop) {
-            mOverScrollTopAmount = amount;
-        } else {
-            mOverScrollBottomAmount = amount;
-        }
-    }
-
-    public float getOverScrollAmount(boolean top) {
-        return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
-    }
-
-    public int getSpeedBumpIndex() {
-        return mSpeedBumpIndex;
-    }
-
-    public void setSpeedBumpIndex(int shelfIndex) {
-        mSpeedBumpIndex = shelfIndex;
-    }
-
-    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
-        mHeadsUpManager = headsUpManager;
-    }
-
-    public float getStackTranslation() {
-        return mStackTranslation;
-    }
-
-    public void setStackTranslation(float stackTranslation) {
-        mStackTranslation = stackTranslation;
-    }
-
-    public void setLayoutHeight(int layoutHeight) {
-        mLayoutHeight = layoutHeight;
-    }
-
-    public float getTopPadding() {
-        return mTopPadding;
-    }
-
-    public void setTopPadding(int topPadding) {
-        mTopPadding = topPadding;
-    }
-
-    public int getInnerHeight() {
-        return Math.max(Math.min(mLayoutHeight, mMaxLayoutHeight) - mTopPadding, mLayoutMinHeight);
-    }
-
-    public boolean isShadeExpanded() {
-        return mShadeExpanded;
-    }
-
-    public void setShadeExpanded(boolean shadeExpanded) {
-        mShadeExpanded = shadeExpanded;
-    }
-
-    public void setMaxHeadsUpTranslation(float maxHeadsUpTranslation) {
-        mMaxHeadsUpTranslation = maxHeadsUpTranslation;
-    }
-
-    public float getMaxHeadsUpTranslation() {
-        return mMaxHeadsUpTranslation;
-    }
-
-    public void setDismissAllInProgress(boolean dismissAllInProgress) {
-        mDismissAllInProgress = dismissAllInProgress;
-    }
-
-    public boolean isDismissAllInProgress() {
-        return mDismissAllInProgress;
-    }
-
-    public void setLayoutMinHeight(int layoutMinHeight) {
-        mLayoutMinHeight = layoutMinHeight;
-    }
-
-    public void setShelf(NotificationShelf shelf) {
-        mShelf = shelf;
-    }
-
-    @Nullable
-    public NotificationShelf getShelf() {
-        return mShelf;
-    }
-
-    public void setLayoutMaxHeight(int maxLayoutHeight) {
-        mMaxLayoutHeight = maxLayoutHeight;
-    }
-
-    /**
-     * Sets the last visible view of the host layout, that has a background, i.e the very last
-     * view in the shade, without the clear all button.
-     */
-    public void setLastVisibleBackgroundChild(
-            ActivatableNotificationView lastVisibleBackgroundChild) {
-        mLastVisibleBackgroundChild = lastVisibleBackgroundChild;
-    }
-
-    public ActivatableNotificationView getLastVisibleBackgroundChild() {
-        return mLastVisibleBackgroundChild;
-    }
-
-    public void setCurrentScrollVelocity(float currentScrollVelocity) {
-        mCurrentScrollVelocity = currentScrollVelocity;
-    }
-
-    public float getCurrentScrollVelocity() {
-        return mCurrentScrollVelocity;
-    }
-
-    public boolean isOnKeyguard() {
-        return mStatusBarState == StatusBarState.KEYGUARD;
-    }
-
-    public void setStatusBarState(int statusBarState) {
-        mStatusBarState = statusBarState;
-    }
-
-    public void setExpandingVelocity(float expandingVelocity) {
-        mExpandingVelocity = expandingVelocity;
-    }
-
-    public void setExpansionChanging(boolean expansionChanging) {
-        mExpansionChanging = expansionChanging;
-    }
-
-    public boolean isExpansionChanging() {
-        return mExpansionChanging;
-    }
-
-    public float getExpandingVelocity() {
-        return mExpandingVelocity;
-    }
-
-    public void setPanelTracking(boolean panelTracking) {
-        mPanelTracking = panelTracking;
-    }
-
-    public boolean hasPulsingNotifications() {
-        return mPulsing;
-    }
-
-    public void setPulsing(boolean hasPulsing) {
-        mPulsing = hasPulsing;
-    }
-
-    public boolean isPulsing(NotificationData.Entry entry) {
-        if (!mPulsing || mHeadsUpManager == null) {
-            return false;
-        }
-        return mHeadsUpManager.getAllEntries().anyMatch(e -> (e == entry));
-    }
-
-    public boolean isPanelTracking() {
-        return mPanelTracking;
-    }
-
-    public boolean isPanelFullWidth() {
-        return mPanelFullWidth;
-    }
-
-    public void setPanelFullWidth(boolean panelFullWidth) {
-        mPanelFullWidth = panelFullWidth;
-    }
-
-    public void setUnlockHintRunning(boolean unlockHintRunning) {
-        mUnlockHintRunning = unlockHintRunning;
-    }
-
-    public boolean isUnlockHintRunning() {
-        return mUnlockHintRunning;
-    }
-
-    public boolean isQsCustomizerShowing() {
-        return mQsCustomizerShowing;
-    }
-
-    public void setQsCustomizerShowing(boolean qsCustomizerShowing) {
-        mQsCustomizerShowing = qsCustomizerShowing;
-    }
-
-    public void setIntrinsicPadding(int intrinsicPadding) {
-        mIntrinsicPadding = intrinsicPadding;
-    }
-
-    public int getIntrinsicPadding() {
-        return mIntrinsicPadding;
-    }
-
-    /**
-     * Similar to the normal is above shelf logic but doesn't allow it to be above in AOD1.
-     *
-     * @param expandableView the view to check
-     */
-    public boolean isAboveShelf(ExpandableView expandableView) {
-        if (!(expandableView instanceof ExpandableNotificationRow)) {
-            return expandableView.isAboveShelf();
-        }
-        ExpandableNotificationRow row = (ExpandableNotificationRow) expandableView;
-        return row.isAboveShelf() && !isDozingAndNotPulsing(row);
-    }
-
-    /**
-     * @return whether a view is dozing and not pulsing right now
-     */
-    public boolean isDozingAndNotPulsing(ExpandableView view) {
-        if (view instanceof ExpandableNotificationRow) {
-            return isDozingAndNotPulsing((ExpandableNotificationRow) view);
-        }
-        return false;
-    }
-
-    /**
-     * @return whether a row is dozing and not pulsing right now
-     */
-    public boolean isDozingAndNotPulsing(ExpandableNotificationRow row) {
-        return isDark() && !isPulsing(row.getEntry());
-    }
-
-    public void setExpandAnimationTopChange(int expandAnimationTopChange) {
-        mExpandAnimationTopChange = expandAnimationTopChange;
-    }
-
-    public void setExpandingNotification(ExpandableNotificationRow row) {
-        mExpandingNotification = row;
-    }
-
-    public ExpandableNotificationRow getExpandingNotification() {
-        return mExpandingNotification;
-    }
-
-    public int getExpandAnimationTopChange() {
-        return mExpandAnimationTopChange;
-    }
-
-    /**
-     * @return {@code true } when shade is completely dark: in AOD or ambient display.
-     */
-    public boolean isFullyDark() {
-        return mDarkAmount == 1;
-    }
-
-    public void setDarkTopPadding(int darkTopPadding) {
-        mDarkTopPadding = darkTopPadding;
-    }
-
-    public int getDarkTopPadding() {
-        return mDarkTopPadding;
-    }
-
-    public void setAppearing(boolean appearing) {
-        mAppearing = appearing;
-    }
-
-    public boolean isAppearing() {
-        return mAppearing;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
deleted file mode 100644
index fd49b26..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import androidx.collection.ArraySet;
-import android.util.Property;
-import android.view.View;
-
-import java.util.ArrayList;
-
-/**
- * Filters the animations for only a certain type of properties.
- */
-public class AnimationFilter {
-    public static final int NO_DELAY = -1;
-    boolean animateAlpha;
-    boolean animateX;
-    boolean animateY;
-    ArraySet<View> animateYViews = new ArraySet<>();
-    boolean animateZ;
-    boolean animateHeight;
-    boolean animateTopInset;
-    boolean animateDimmed;
-    boolean animateDark;
-    boolean animateHideSensitive;
-    public boolean animateShadowAlpha;
-    boolean hasDelays;
-    boolean hasGoToFullShadeEvent;
-    long customDelay;
-    private ArraySet<Property> mAnimatedProperties = new ArraySet<>();
-
-    public AnimationFilter animateAlpha() {
-        animateAlpha = true;
-        return this;
-    }
-
-    public AnimationFilter animateScale() {
-        animate(View.SCALE_X);
-        animate(View.SCALE_Y);
-        return this;
-    }
-
-    public AnimationFilter animateX() {
-        animateX = true;
-        return this;
-    }
-
-    public AnimationFilter animateY() {
-        animateY = true;
-        return this;
-    }
-
-    public AnimationFilter hasDelays() {
-        hasDelays = true;
-        return this;
-    }
-
-    public AnimationFilter animateZ() {
-        animateZ = true;
-        return this;
-    }
-
-    public AnimationFilter animateHeight() {
-        animateHeight = true;
-        return this;
-    }
-
-    public AnimationFilter animateTopInset() {
-        animateTopInset = true;
-        return this;
-    }
-
-    public AnimationFilter animateDimmed() {
-        animateDimmed = true;
-        return this;
-    }
-
-    public AnimationFilter animateDark() {
-        animateDark = true;
-        return this;
-    }
-
-    public AnimationFilter animateHideSensitive() {
-        animateHideSensitive = true;
-        return this;
-    }
-
-    public AnimationFilter animateShadowAlpha() {
-        animateShadowAlpha = true;
-        return this;
-    }
-
-    public AnimationFilter animateY(View view) {
-        animateYViews.add(view);
-        return this;
-    }
-
-    public boolean shouldAnimateY(View view) {
-        return animateY || animateYViews.contains(view);
-    }
-
-    /**
-     * Combines multiple filters into {@code this} filter, using or as the operand .
-     *
-     * @param events The animation events from the filters to combine.
-     */
-    public void applyCombination(ArrayList<NotificationStackScrollLayout.AnimationEvent> events) {
-        reset();
-        int size = events.size();
-        for (int i = 0; i < size; i++) {
-            NotificationStackScrollLayout.AnimationEvent ev = events.get(i);
-            combineFilter(events.get(i).filter);
-            if (ev.animationType ==
-                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_GO_TO_FULL_SHADE) {
-                hasGoToFullShadeEvent = true;
-            }
-            if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
-                    .ANIMATION_TYPE_HEADS_UP_DISAPPEAR) {
-                customDelay = StackStateAnimator.ANIMATION_DELAY_HEADS_UP;
-            } else if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
-                    .ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
-                // We need both timeouts when clicking, one to delay it and one for the animation
-                // to look nice
-                customDelay = StackStateAnimator.ANIMATION_DELAY_HEADS_UP_CLICKED
-                        + StackStateAnimator.ANIMATION_DELAY_HEADS_UP;
-            } else if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
-                    .ANIMATION_TYPE_PULSE_APPEAR || ev.animationType ==
-                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) {
-                customDelay = StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR / 2;
-            }
-        }
-    }
-
-    public void combineFilter(AnimationFilter filter) {
-        animateAlpha |= filter.animateAlpha;
-        animateX |= filter.animateX;
-        animateY |= filter.animateY;
-        animateYViews.addAll(filter.animateYViews);
-        animateZ |= filter.animateZ;
-        animateHeight |= filter.animateHeight;
-        animateTopInset |= filter.animateTopInset;
-        animateDimmed |= filter.animateDimmed;
-        animateDark |= filter.animateDark;
-        animateHideSensitive |= filter.animateHideSensitive;
-        animateShadowAlpha |= filter.animateShadowAlpha;
-        hasDelays |= filter.hasDelays;
-        mAnimatedProperties.addAll(filter.mAnimatedProperties);
-    }
-
-    public void reset() {
-        animateAlpha = false;
-        animateX = false;
-        animateY = false;
-        animateYViews.clear();
-        animateZ = false;
-        animateHeight = false;
-        animateShadowAlpha = false;
-        animateTopInset = false;
-        animateDimmed = false;
-        animateDark = false;
-        animateHideSensitive = false;
-        hasDelays = false;
-        hasGoToFullShadeEvent = false;
-        customDelay = NO_DELAY;
-        mAnimatedProperties.clear();
-    }
-
-    public AnimationFilter animate(Property property) {
-        mAnimatedProperties.add(property);
-        return this;
-    }
-
-    public boolean shouldAnimateProperty(Property property) {
-        // TODO: migrate all existing animators to properties
-        return mAnimatedProperties.contains(property);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationProperties.java
deleted file mode 100644
index 47df226..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationProperties.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import android.animation.AnimatorListenerAdapter;
-import android.util.ArrayMap;
-import android.util.Property;
-import android.view.View;
-import android.view.animation.Interpolator;
-
-import java.util.HashMap;
-
-/**
- * Properties for a View animation
- */
-public class AnimationProperties {
-    public long duration;
-    public long delay;
-    private ArrayMap<Property, Interpolator> mInterpolatorMap;
-    private AnimatorListenerAdapter mAnimatorListenerAdapter;
-
-    /**
-     * @return an animation filter for this animation.
-     */
-    public AnimationFilter getAnimationFilter() {
-        return new AnimationFilter() {
-            @Override
-            public boolean shouldAnimateProperty(Property property) {
-                return true;
-            }
-        };
-    }
-
-    /**
-     * @return a listener that should be run whenever any property finished its animation
-     */
-    public AnimatorListenerAdapter getAnimationFinishListener() {
-        return mAnimatorListenerAdapter;
-    }
-
-    public AnimationProperties setAnimationFinishListener(AnimatorListenerAdapter listener) {
-        mAnimatorListenerAdapter = listener;
-        return this;
-    }
-
-    public boolean wasAdded(View view) {
-        return false;
-    }
-
-    /**
-     * Get a custom interpolator for a property instead of the normal one.
-     */
-    public Interpolator getCustomInterpolator(View child, Property property) {
-        return mInterpolatorMap != null ? mInterpolatorMap.get(property) : null;
-    }
-
-
-    public void combineCustomInterpolators(AnimationProperties iconAnimationProperties) {
-        ArrayMap<Property, Interpolator> map = iconAnimationProperties.mInterpolatorMap;
-        if (map != null) {
-            if (mInterpolatorMap == null) {
-                mInterpolatorMap = new ArrayMap<>();
-            }
-            mInterpolatorMap.putAll(map);
-        }
-    }
-
-    /**
-     * Set a custom interpolator to use for all views for a property.
-     */
-    public AnimationProperties setCustomInterpolator(Property property, Interpolator interpolator) {
-        if (mInterpolatorMap == null) {
-            mInterpolatorMap = new ArrayMap<>();
-        }
-        mInterpolatorMap.put(property, interpolator);
-        return this;
-    }
-
-    public AnimationProperties setDuration(long duration) {
-        this.duration = duration;
-        return this;
-    }
-
-    public AnimationProperties setDelay(long delay) {
-        this.delay = delay;
-        return this;
-    }
-
-    public AnimationProperties resetCustomInterpolators() {
-        mInterpolatorMap = null;
-        return this;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java
deleted file mode 100644
index a7925aa..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java
+++ /dev/null
@@ -1,488 +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.systemui.statusbar.stack;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.PropertyValuesHolder;
-import android.animation.ValueAnimator;
-import android.view.View;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
-
-/**
-* A state of an expandable view
-*/
-public class ExpandableViewState extends ViewState {
-
-    private static final int TAG_ANIMATOR_HEIGHT = R.id.height_animator_tag;
-    private static final int TAG_ANIMATOR_TOP_INSET = R.id.top_inset_animator_tag;
-    private static final int TAG_ANIMATOR_SHADOW_ALPHA = R.id.shadow_alpha_animator_tag;
-    private static final int TAG_END_HEIGHT = R.id.height_animator_end_value_tag;
-    private static final int TAG_END_TOP_INSET = R.id.top_inset_animator_end_value_tag;
-    private static final int TAG_END_SHADOW_ALPHA = R.id.shadow_alpha_animator_end_value_tag;
-    private static final int TAG_START_HEIGHT = R.id.height_animator_start_value_tag;
-    private static final int TAG_START_TOP_INSET = R.id.top_inset_animator_start_value_tag;
-    private static final int TAG_START_SHADOW_ALPHA = R.id.shadow_alpha_animator_start_value_tag;
-
-    // These are flags such that we can create masks for filtering.
-
-    /**
-     * No known location. This is the default and should not be set after an invocation of the
-     * algorithm.
-     */
-    public static final int LOCATION_UNKNOWN = 0x00;
-
-    /**
-     * The location is the first heads up notification, so on the very top.
-     */
-    public static final int LOCATION_FIRST_HUN = 0x01;
-
-    /**
-     * The location is hidden / scrolled away on the top.
-     */
-    public static final int LOCATION_HIDDEN_TOP = 0x02;
-
-    /**
-     * The location is in the main area of the screen and visible.
-     */
-    public static final int LOCATION_MAIN_AREA = 0x04;
-
-    /**
-     * The location is in the bottom stack and it's peeking
-     */
-    public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x08;
-
-    /**
-     * The location is in the bottom stack and it's hidden.
-     */
-    public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x10;
-
-    /**
-     * The view isn't laid out at all.
-     */
-    public static final int LOCATION_GONE = 0x40;
-
-    /**
-     * The visible locations of a view.
-     */
-    public static final int VISIBLE_LOCATIONS = ExpandableViewState.LOCATION_FIRST_HUN
-            | ExpandableViewState.LOCATION_MAIN_AREA;
-
-    public int height;
-    public boolean dimmed;
-    public boolean dark;
-    public boolean hideSensitive;
-    public boolean belowSpeedBump;
-    public float shadowAlpha;
-    public boolean inShelf;
-
-    /**
-     * A state indicating whether a headsup is currently fully visible, even when not scrolled.
-     * Only valid if the view is heads upped.
-     */
-    public boolean headsUpIsVisible;
-
-    /**
-     * How much the child overlaps with the previous child on top. This is used to
-     * show the background properly when the child on top is translating away.
-     */
-    public int clipTopAmount;
-
-    /**
-     * The index of the view, only accounting for views not equal to GONE
-     */
-    public int notGoneIndex;
-
-    /**
-     * The location this view is currently rendered at.
-     *
-     * <p>See <code>LOCATION_</code> flags.</p>
-     */
-    public int location;
-
-    @Override
-    public void copyFrom(ViewState viewState) {
-        super.copyFrom(viewState);
-        if (viewState instanceof ExpandableViewState) {
-            ExpandableViewState svs = (ExpandableViewState) viewState;
-            height = svs.height;
-            dimmed = svs.dimmed;
-            shadowAlpha = svs.shadowAlpha;
-            dark = svs.dark;
-            hideSensitive = svs.hideSensitive;
-            belowSpeedBump = svs.belowSpeedBump;
-            clipTopAmount = svs.clipTopAmount;
-            notGoneIndex = svs.notGoneIndex;
-            location = svs.location;
-            headsUpIsVisible = svs.headsUpIsVisible;
-        }
-    }
-
-    /**
-     * Applies a {@link ExpandableViewState} to a {@link ExpandableView}.
-     */
-    @Override
-    public void applyToView(View view) {
-        super.applyToView(view);
-        if (view instanceof ExpandableView) {
-            ExpandableView expandableView = (ExpandableView) view;
-
-            int height = expandableView.getActualHeight();
-            int newHeight = this.height;
-
-            // apply height
-            if (height != newHeight) {
-                expandableView.setActualHeight(newHeight, false /* notifyListeners */);
-            }
-
-            float shadowAlpha = expandableView.getShadowAlpha();
-            float newShadowAlpha = this.shadowAlpha;
-
-            // apply shadowAlpha
-            if (shadowAlpha != newShadowAlpha) {
-                expandableView.setShadowAlpha(newShadowAlpha);
-            }
-
-            // apply dimming
-            expandableView.setDimmed(this.dimmed, false /* animate */);
-
-            // apply hiding sensitive
-            expandableView.setHideSensitive(
-                    this.hideSensitive, false /* animated */, 0 /* delay */, 0 /* duration */);
-
-            // apply below shelf speed bump
-            expandableView.setBelowSpeedBump(this.belowSpeedBump);
-
-            // apply dark
-            expandableView.setDark(this.dark, false /* animate */, 0 /* delay */);
-
-            // apply clipping
-            float oldClipTopAmount = expandableView.getClipTopAmount();
-            if (oldClipTopAmount != this.clipTopAmount) {
-                expandableView.setClipTopAmount(this.clipTopAmount);
-            }
-
-            expandableView.setTransformingInShelf(false);
-            expandableView.setInShelf(inShelf);
-
-            if (headsUpIsVisible) {
-                expandableView.setHeadsUpIsVisible();
-            }
-        }
-    }
-
-    @Override
-    public void animateTo(View child, AnimationProperties properties) {
-        super.animateTo(child, properties);
-        if (!(child instanceof ExpandableView)) {
-            return;
-        }
-        ExpandableView expandableView = (ExpandableView) child;
-        AnimationFilter animationFilter = properties.getAnimationFilter();
-
-        // start height animation
-        if (this.height != expandableView.getActualHeight()) {
-            startHeightAnimation(expandableView, properties);
-        }  else {
-            abortAnimation(child, TAG_ANIMATOR_HEIGHT);
-        }
-
-        // start shadow alpha animation
-        if (this.shadowAlpha != expandableView.getShadowAlpha()) {
-            startShadowAlphaAnimation(expandableView, properties);
-        } else {
-            abortAnimation(child, TAG_ANIMATOR_SHADOW_ALPHA);
-        }
-
-        // start top inset animation
-        if (this.clipTopAmount != expandableView.getClipTopAmount()) {
-            startInsetAnimation(expandableView, properties);
-        } else {
-            abortAnimation(child, TAG_ANIMATOR_TOP_INSET);
-        }
-
-        // start dimmed animation
-        expandableView.setDimmed(this.dimmed, animationFilter.animateDimmed);
-
-        // apply below the speed bump
-        expandableView.setBelowSpeedBump(this.belowSpeedBump);
-
-        // start hiding sensitive animation
-        expandableView.setHideSensitive(this.hideSensitive, animationFilter.animateHideSensitive,
-                properties.delay, properties.duration);
-
-        // start dark animation
-        expandableView.setDark(this.dark, animationFilter.animateDark, properties.delay);
-
-        if (properties.wasAdded(child) && !hidden) {
-            expandableView.performAddAnimation(properties.delay, properties.duration,
-                    false /* isHeadsUpAppear */);
-        }
-
-        if (!expandableView.isInShelf() && this.inShelf) {
-            expandableView.setTransformingInShelf(true);
-        }
-        expandableView.setInShelf(this.inShelf);
-
-        if (headsUpIsVisible) {
-            expandableView.setHeadsUpIsVisible();
-        }
-    }
-
-    private void startHeightAnimation(final ExpandableView child, AnimationProperties properties) {
-        Integer previousStartValue = getChildTag(child, TAG_START_HEIGHT);
-        Integer previousEndValue = getChildTag(child, TAG_END_HEIGHT);
-        int newEndValue = this.height;
-        if (previousEndValue != null && previousEndValue == newEndValue) {
-            return;
-        }
-        ValueAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_HEIGHT);
-        AnimationFilter filter = properties.getAnimationFilter();
-        if (!filter.animateHeight) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                int relativeDiff = newEndValue - previousEndValue;
-                int newStartValue = previousStartValue + relativeDiff;
-                values[0].setIntValues(newStartValue, newEndValue);
-                child.setTag(TAG_START_HEIGHT, newStartValue);
-                child.setTag(TAG_END_HEIGHT, newEndValue);
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                child.setActualHeight(newEndValue, false);
-                return;
-            }
-        }
-
-        ValueAnimator animator = ValueAnimator.ofInt(child.getActualHeight(), newEndValue);
-        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                child.setActualHeight((int) animation.getAnimatedValue(),
-                        false /* notifyListeners */);
-            }
-        });
-        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
-        animator.setDuration(newDuration);
-        if (properties.delay > 0 && (previousAnimator == null
-                || previousAnimator.getAnimatedFraction() == 0)) {
-            animator.setStartDelay(properties.delay);
-        }
-        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
-        if (listener != null) {
-            animator.addListener(listener);
-        }
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            boolean mWasCancelled;
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                child.setTag(TAG_ANIMATOR_HEIGHT, null);
-                child.setTag(TAG_START_HEIGHT, null);
-                child.setTag(TAG_END_HEIGHT, null);
-                child.setActualHeightAnimating(false);
-                if (!mWasCancelled && child instanceof ExpandableNotificationRow) {
-                    ((ExpandableNotificationRow) child).setGroupExpansionChanging(
-                            false /* isExpansionChanging */);
-                }
-            }
-
-            @Override
-            public void onAnimationStart(Animator animation) {
-                mWasCancelled = false;
-            }
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                mWasCancelled = true;
-            }
-        });
-        startAnimator(animator, listener);
-        child.setTag(TAG_ANIMATOR_HEIGHT, animator);
-        child.setTag(TAG_START_HEIGHT, child.getActualHeight());
-        child.setTag(TAG_END_HEIGHT, newEndValue);
-        child.setActualHeightAnimating(true);
-    }
-
-    private void startShadowAlphaAnimation(final ExpandableView child,
-            AnimationProperties properties) {
-        Float previousStartValue = getChildTag(child, TAG_START_SHADOW_ALPHA);
-        Float previousEndValue = getChildTag(child, TAG_END_SHADOW_ALPHA);
-        float newEndValue = this.shadowAlpha;
-        if (previousEndValue != null && previousEndValue == newEndValue) {
-            return;
-        }
-        ValueAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_SHADOW_ALPHA);
-        AnimationFilter filter = properties.getAnimationFilter();
-        if (!filter.animateShadowAlpha) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                float relativeDiff = newEndValue - previousEndValue;
-                float newStartValue = previousStartValue + relativeDiff;
-                values[0].setFloatValues(newStartValue, newEndValue);
-                child.setTag(TAG_START_SHADOW_ALPHA, newStartValue);
-                child.setTag(TAG_END_SHADOW_ALPHA, newEndValue);
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                child.setShadowAlpha(newEndValue);
-                return;
-            }
-        }
-
-        ValueAnimator animator = ValueAnimator.ofFloat(child.getShadowAlpha(), newEndValue);
-        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                child.setShadowAlpha((float) animation.getAnimatedValue());
-            }
-        });
-        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
-        animator.setDuration(newDuration);
-        if (properties.delay > 0 && (previousAnimator == null
-                || previousAnimator.getAnimatedFraction() == 0)) {
-            animator.setStartDelay(properties.delay);
-        }
-        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
-        if (listener != null) {
-            animator.addListener(listener);
-        }
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                child.setTag(TAG_ANIMATOR_SHADOW_ALPHA, null);
-                child.setTag(TAG_START_SHADOW_ALPHA, null);
-                child.setTag(TAG_END_SHADOW_ALPHA, null);
-            }
-        });
-        startAnimator(animator, listener);
-        child.setTag(TAG_ANIMATOR_SHADOW_ALPHA, animator);
-        child.setTag(TAG_START_SHADOW_ALPHA, child.getShadowAlpha());
-        child.setTag(TAG_END_SHADOW_ALPHA, newEndValue);
-    }
-
-    private void startInsetAnimation(final ExpandableView child, AnimationProperties properties) {
-        Integer previousStartValue = getChildTag(child, TAG_START_TOP_INSET);
-        Integer previousEndValue = getChildTag(child, TAG_END_TOP_INSET);
-        int newEndValue = this.clipTopAmount;
-        if (previousEndValue != null && previousEndValue == newEndValue) {
-            return;
-        }
-        ValueAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TOP_INSET);
-        AnimationFilter filter = properties.getAnimationFilter();
-        if (!filter.animateTopInset) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                int relativeDiff = newEndValue - previousEndValue;
-                int newStartValue = previousStartValue + relativeDiff;
-                values[0].setIntValues(newStartValue, newEndValue);
-                child.setTag(TAG_START_TOP_INSET, newStartValue);
-                child.setTag(TAG_END_TOP_INSET, newEndValue);
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                child.setClipTopAmount(newEndValue);
-                return;
-            }
-        }
-
-        ValueAnimator animator = ValueAnimator.ofInt(child.getClipTopAmount(), newEndValue);
-        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                child.setClipTopAmount((int) animation.getAnimatedValue());
-            }
-        });
-        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
-        animator.setDuration(newDuration);
-        if (properties.delay > 0 && (previousAnimator == null
-                || previousAnimator.getAnimatedFraction() == 0)) {
-            animator.setStartDelay(properties.delay);
-        }
-        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
-        if (listener != null) {
-            animator.addListener(listener);
-        }
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                child.setTag(TAG_ANIMATOR_TOP_INSET, null);
-                child.setTag(TAG_START_TOP_INSET, null);
-                child.setTag(TAG_END_TOP_INSET, null);
-            }
-        });
-        startAnimator(animator, listener);
-        child.setTag(TAG_ANIMATOR_TOP_INSET, animator);
-        child.setTag(TAG_START_TOP_INSET, child.getClipTopAmount());
-        child.setTag(TAG_END_TOP_INSET, newEndValue);
-    }
-
-    /**
-     * Get the end value of the height animation running on a view or the actualHeight
-     * if no animation is running.
-     */
-    public static int getFinalActualHeight(ExpandableView view) {
-        if (view == null) {
-            return 0;
-        }
-        ValueAnimator heightAnimator = getChildTag(view, TAG_ANIMATOR_HEIGHT);
-        if (heightAnimator == null) {
-            return view.getActualHeight();
-        } else {
-            return getChildTag(view, TAG_END_HEIGHT);
-        }
-    }
-
-    @Override
-    public void cancelAnimations(View view) {
-        super.cancelAnimations(view);
-        Animator animator = getChildTag(view, TAG_ANIMATOR_HEIGHT);
-        if (animator != null) {
-            animator.cancel();
-        }
-        animator = getChildTag(view, TAG_ANIMATOR_SHADOW_ALPHA);
-        if (animator != null) {
-            animator.cancel();
-        }
-        animator = getChildTag(view, TAG_ANIMATOR_TOP_INSET);
-        if (animator != null) {
-            animator.cancel();
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/HeadsUpAppearInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/HeadsUpAppearInterpolator.java
deleted file mode 100644
index 59ce0ca..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/HeadsUpAppearInterpolator.java
+++ /dev/null
@@ -1,52 +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.systemui.statusbar.stack;
-
-import android.graphics.Path;
-import android.view.animation.PathInterpolator;
-
-/**
- * An interpolator specifically designed for the appear animation of heads up notifications.
- */
-public class HeadsUpAppearInterpolator extends PathInterpolator {
-
-    private static float X1 = 250f;
-    private static float X2 = 200f;
-    private static float XTOT = (X1 + X2);;
-
-    public HeadsUpAppearInterpolator() {
-        super(getAppearPath());
-    }
-
-    private static Path getAppearPath() {
-        Path path = new Path();
-        path.moveTo(0, 0);
-        float y1 = 90f;
-        float y2 = 80f;
-        path.cubicTo(X1 * 0.8f / XTOT, y1 / y2,
-                X1 * 0.8f / XTOT, y1 / y2,
-                X1 / XTOT, y1 / y2);
-        path.cubicTo((X1 + X2 * 0.4f) / XTOT, y1 / y2,
-                (X1 + X2 * 0.2f) / XTOT, 1.0f,
-                1.0f , 1.0f);
-        return path;
-    }
-
-    public static float getFractionUntilOvershoot() {
-        return X1 / XTOT;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
deleted file mode 100644
index ffd5494..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ /dev/null
@@ -1,1325 +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.systemui.statusbar.stack;
-
-import android.app.Notification;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.drawable.ColorDrawable;
-import android.service.notification.StatusBarNotification;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.NotificationHeaderView;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RemoteViews;
-import android.widget.TextView;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationHeaderUtil;
-import com.android.systemui.statusbar.notification.HybridGroupManager;
-import com.android.systemui.statusbar.notification.HybridNotificationView;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.notification.NotificationViewWrapper;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A container containing child notifications
- */
-public class NotificationChildrenContainer extends ViewGroup {
-
-    @VisibleForTesting
-    static final int NUMBER_OF_CHILDREN_WHEN_COLLAPSED = 2;
-    @VisibleForTesting
-    static final int NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED = 5;
-    @VisibleForTesting
-    static final int NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED = 8;
-    @VisibleForTesting
-    static final int NUMBER_OF_CHILDREN_WHEN_AMBIENT = 1;
-    private static final AnimationProperties ALPHA_FADE_IN = new AnimationProperties() {
-        private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
-
-        @Override
-        public AnimationFilter getAnimationFilter() {
-            return mAnimationFilter;
-        }
-    }.setDuration(200);
-
-    private final List<View> mDividers = new ArrayList<>();
-    private final List<ExpandableNotificationRow> mChildren = new ArrayList<>();
-    private final HybridGroupManager mHybridGroupManager;
-    private int mChildPadding;
-    private int mDividerHeight;
-    private float mDividerAlpha;
-    private int mNotificationHeaderMargin;
-
-    private int mNotificatonTopPadding;
-    private float mCollapsedBottompadding;
-    private boolean mChildrenExpanded;
-    private ExpandableNotificationRow mContainingNotification;
-    private TextView mOverflowNumber;
-    private ViewState mGroupOverFlowState;
-    private int mRealHeight;
-    private boolean mUserLocked;
-    private int mActualHeight;
-    private boolean mNeverAppliedGroupState;
-    private int mHeaderHeight;
-
-    /**
-     * Whether or not individual notifications that are part of this container will have shadows.
-     */
-    private boolean mEnableShadowOnChildNotifications;
-
-    private NotificationHeaderView mNotificationHeader;
-    private NotificationViewWrapper mNotificationHeaderWrapper;
-    private NotificationHeaderView mNotificationHeaderLowPriority;
-    private NotificationViewWrapper mNotificationHeaderWrapperLowPriority;
-    private ViewGroup mNotificationHeaderAmbient;
-    private NotificationViewWrapper mNotificationHeaderWrapperAmbient;
-    private NotificationHeaderUtil mHeaderUtil;
-    private ViewState mHeaderViewState;
-    private int mClipBottomAmount;
-    private boolean mIsLowPriority;
-    private OnClickListener mHeaderClickListener;
-    private ViewGroup mCurrentHeader;
-
-    private boolean mShowDividersWhenExpanded;
-    private boolean mHideDividersDuringExpand;
-    private int mTranslationForHeader;
-    private int mCurrentHeaderTranslation = 0;
-    private float mHeaderVisibleAmount = 1.0f;
-
-    public NotificationChildrenContainer(Context context) {
-        this(context, null);
-    }
-
-    public NotificationChildrenContainer(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public NotificationChildrenContainer(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public NotificationChildrenContainer(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        mHybridGroupManager = new HybridGroupManager(getContext(), this);
-        initDimens();
-        setClipChildren(false);
-    }
-
-    private void initDimens() {
-        Resources res = getResources();
-        mChildPadding = res.getDimensionPixelSize(R.dimen.notification_children_padding);
-        mDividerHeight = res.getDimensionPixelSize(
-                R.dimen.notification_children_container_divider_height);
-        mDividerAlpha = res.getFloat(R.dimen.notification_divider_alpha);
-        mNotificationHeaderMargin = res.getDimensionPixelSize(
-                R.dimen.notification_children_container_margin_top);
-        mNotificatonTopPadding = res.getDimensionPixelSize(
-                R.dimen.notification_children_container_top_padding);
-        mHeaderHeight = mNotificationHeaderMargin + mNotificatonTopPadding;
-        mCollapsedBottompadding = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.notification_content_margin);
-        mEnableShadowOnChildNotifications =
-                res.getBoolean(R.bool.config_enableShadowOnChildNotifications);
-        mShowDividersWhenExpanded =
-                res.getBoolean(R.bool.config_showDividersWhenGroupNotificationExpanded);
-        mHideDividersDuringExpand =
-                res.getBoolean(R.bool.config_hideDividersDuringExpand);
-        mTranslationForHeader = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.notification_content_margin)
-                - mNotificationHeaderMargin;
-        mHybridGroupManager.initDimens();
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
-        for (int i = 0; i < childCount; i++) {
-            View child = mChildren.get(i);
-            // We need to layout all children even the GONE ones, such that the heights are
-            // calculated correctly as they are used to calculate how many we can fit on the screen
-            child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
-            mDividers.get(i).layout(0, 0, getWidth(), mDividerHeight);
-        }
-        if (mOverflowNumber != null) {
-            boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-            int left = (isRtl ? 0 : getWidth() - mOverflowNumber.getMeasuredWidth());
-            int right = left + mOverflowNumber.getMeasuredWidth();
-            mOverflowNumber.layout(left, 0, right, mOverflowNumber.getMeasuredHeight());
-        }
-        if (mNotificationHeader != null) {
-            mNotificationHeader.layout(0, 0, mNotificationHeader.getMeasuredWidth(),
-                    mNotificationHeader.getMeasuredHeight());
-        }
-        if (mNotificationHeaderLowPriority != null) {
-            mNotificationHeaderLowPriority.layout(0, 0,
-                    mNotificationHeaderLowPriority.getMeasuredWidth(),
-                    mNotificationHeaderLowPriority.getMeasuredHeight());
-        }
-        if (mNotificationHeaderAmbient != null) {
-            mNotificationHeaderAmbient.layout(0, 0,
-                    mNotificationHeaderAmbient.getMeasuredWidth(),
-                    mNotificationHeaderAmbient.getMeasuredHeight());
-        }
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
-        boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
-        int size = MeasureSpec.getSize(heightMeasureSpec);
-        int newHeightSpec = heightMeasureSpec;
-        if (hasFixedHeight || isHeightLimited) {
-            newHeightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
-        }
-        int width = MeasureSpec.getSize(widthMeasureSpec);
-        if (mOverflowNumber != null) {
-            mOverflowNumber.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
-                    newHeightSpec);
-        }
-        int dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY);
-        int height = mNotificationHeaderMargin + mNotificatonTopPadding;
-        int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
-        int collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
-        int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1;
-        for (int i = 0; i < childCount; i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            // We need to measure all children even the GONE ones, such that the heights are
-            // calculated correctly as they are used to calculate how many we can fit on the screen.
-            boolean isOverflow = i == overflowIndex;
-            child.setSingleLineWidthIndention(isOverflow && mOverflowNumber != null &&
-                    !mContainingNotification.isShowingAmbient()
-                    ? mOverflowNumber.getMeasuredWidth() : 0);
-            child.measure(widthMeasureSpec, newHeightSpec);
-            // layout the divider
-            View divider = mDividers.get(i);
-            divider.measure(widthMeasureSpec, dividerHeightSpec);
-            if (child.getVisibility() != GONE) {
-                height += child.getMeasuredHeight() + mDividerHeight;
-            }
-        }
-        mRealHeight = height;
-        if (heightMode != MeasureSpec.UNSPECIFIED) {
-            height = Math.min(height, size);
-        }
-
-        int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
-        if (mNotificationHeader != null) {
-            mNotificationHeader.measure(widthMeasureSpec, headerHeightSpec);
-        }
-        if (mNotificationHeaderLowPriority != null) {
-            headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
-            mNotificationHeaderLowPriority.measure(widthMeasureSpec, headerHeightSpec);
-        }
-        if (mNotificationHeaderAmbient != null) {
-            headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
-            mNotificationHeaderAmbient.measure(widthMeasureSpec, headerHeightSpec);
-        }
-
-        setMeasuredDimension(width, height);
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-
-    @Override
-    public boolean pointInView(float localX, float localY, float slop) {
-        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
-                localY < (mRealHeight + slop);
-    }
-
-    /**
-     * Add a child notification to this view.
-     *
-     * @param row the row to add
-     * @param childIndex the index to add it at, if -1 it will be added at the end
-     */
-    public void addNotification(ExpandableNotificationRow row, int childIndex) {
-        int newIndex = childIndex < 0 ? mChildren.size() : childIndex;
-        mChildren.add(newIndex, row);
-        addView(row);
-        row.setUserLocked(mUserLocked);
-
-        View divider = inflateDivider();
-        addView(divider);
-        mDividers.add(newIndex, divider);
-
-        updateGroupOverflow();
-        row.setContentTransformationAmount(0, false /* isLastChild */);
-        // It doesn't make sense to keep old animations around, lets cancel them!
-        ExpandableNotificationRow.NotificationViewState viewState = row.getViewState();
-        if (viewState != null) {
-            viewState.cancelAnimations(row);
-            row.cancelAppearDrawing();
-        }
-    }
-
-    public void removeNotification(ExpandableNotificationRow row) {
-        int childIndex = mChildren.indexOf(row);
-        mChildren.remove(row);
-        removeView(row);
-
-        final View divider = mDividers.remove(childIndex);
-        removeView(divider);
-        getOverlay().add(divider);
-        CrossFadeHelper.fadeOut(divider, new Runnable() {
-            @Override
-            public void run() {
-                getOverlay().remove(divider);
-            }
-        });
-
-        row.setSystemChildExpanded(false);
-        row.setUserLocked(false);
-        updateGroupOverflow();
-        if (!row.isRemoved()) {
-            mHeaderUtil.restoreNotificationHeader(row);
-        }
-    }
-
-    /**
-     * @return The number of notification children in the container.
-     */
-    public int getNotificationChildCount() {
-        return mChildren.size();
-    }
-
-    public void recreateNotificationHeader(OnClickListener listener) {
-        mHeaderClickListener = listener;
-        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
-        final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
-                notification.getNotification());
-        RemoteViews header = builder.makeNotificationHeader(false /* ambient */);
-        if (mNotificationHeader == null) {
-            mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
-            final View expandButton = mNotificationHeader.findViewById(
-                    com.android.internal.R.id.expand_button);
-            expandButton.setVisibility(VISIBLE);
-            mNotificationHeader.setOnClickListener(mHeaderClickListener);
-            mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
-                    mNotificationHeader, mContainingNotification);
-            addView(mNotificationHeader, 0);
-            invalidate();
-        } else {
-            header.reapply(getContext(), mNotificationHeader);
-        }
-        mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
-        recreateLowPriorityHeader(builder);
-        recreateAmbientHeader(builder);
-        updateHeaderVisibility(false /* animate */);
-        updateChildrenHeaderAppearance();
-    }
-
-    private void recreateAmbientHeader(Notification.Builder builder) {
-        RemoteViews header;
-        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
-        if (builder == null) {
-            builder = Notification.Builder.recoverBuilder(getContext(),
-                    notification.getNotification());
-        }
-        header = builder.makeNotificationHeader(true /* ambient */);
-        if (mNotificationHeaderAmbient == null) {
-            mNotificationHeaderAmbient = (ViewGroup) header.apply(getContext(), this);
-            mNotificationHeaderWrapperAmbient = NotificationViewWrapper.wrap(getContext(),
-                    mNotificationHeaderAmbient, mContainingNotification);
-            mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
-            addView(mNotificationHeaderAmbient, 0);
-            invalidate();
-        } else {
-            header.reapply(getContext(), mNotificationHeaderAmbient);
-        }
-        resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, calculateDesiredHeader());
-        mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
-    }
-
-    /**
-     * Recreate the low-priority header.
-     *
-     * @param builder a builder to reuse. Otherwise the builder will be recovered.
-     */
-    private void recreateLowPriorityHeader(Notification.Builder builder) {
-        RemoteViews header;
-        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
-        if (mIsLowPriority) {
-            if (builder == null) {
-                builder = Notification.Builder.recoverBuilder(getContext(),
-                        notification.getNotification());
-            }
-            header = builder.makeLowPriorityContentView(true /* useRegularSubtext */);
-            if (mNotificationHeaderLowPriority == null) {
-                mNotificationHeaderLowPriority = (NotificationHeaderView) header.apply(getContext(),
-                        this);
-                final View expandButton = mNotificationHeaderLowPriority.findViewById(
-                        com.android.internal.R.id.expand_button);
-                expandButton.setVisibility(VISIBLE);
-                mNotificationHeaderLowPriority.setOnClickListener(mHeaderClickListener);
-                mNotificationHeaderWrapperLowPriority = NotificationViewWrapper.wrap(getContext(),
-                        mNotificationHeaderLowPriority, mContainingNotification);
-                addView(mNotificationHeaderLowPriority, 0);
-                invalidate();
-            } else {
-                header.reapply(getContext(), mNotificationHeaderLowPriority);
-            }
-            mNotificationHeaderWrapperLowPriority.onContentUpdated(mContainingNotification);
-            resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, calculateDesiredHeader());
-        } else {
-            removeView(mNotificationHeaderLowPriority);
-            mNotificationHeaderLowPriority = null;
-            mNotificationHeaderWrapperLowPriority = null;
-        }
-    }
-
-    public void updateChildrenHeaderAppearance() {
-        mHeaderUtil.updateChildrenHeaderAppearance();
-    }
-
-    public void updateGroupOverflow() {
-        int childCount = mChildren.size();
-        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
-        if (childCount > maxAllowedVisibleChildren) {
-            int number = childCount - maxAllowedVisibleChildren;
-            mOverflowNumber = mHybridGroupManager.bindOverflowNumber(mOverflowNumber, number);
-            if (mContainingNotification.isShowingAmbient()) {
-                ExpandableNotificationRow overflowView = mChildren.get(0);
-                HybridNotificationView ambientSingleLineView = overflowView == null ? null
-                        : overflowView.getAmbientSingleLineView();
-                if (ambientSingleLineView != null) {
-                    mHybridGroupManager.bindOverflowNumberAmbient(
-                            ambientSingleLineView.getTitleView(),
-                            mContainingNotification.getStatusBarNotification().getNotification(),
-                            number);
-                }
-            }
-            if (mGroupOverFlowState == null) {
-                mGroupOverFlowState = new ViewState();
-                mNeverAppliedGroupState = true;
-            }
-        } else if (mOverflowNumber != null) {
-            removeView(mOverflowNumber);
-            if (isShown() && isAttachedToWindow()) {
-                final View removedOverflowNumber = mOverflowNumber;
-                addTransientView(removedOverflowNumber, getTransientViewCount());
-                CrossFadeHelper.fadeOut(removedOverflowNumber, new Runnable() {
-                    @Override
-                    public void run() {
-                        removeTransientView(removedOverflowNumber);
-                    }
-                });
-            }
-            mOverflowNumber = null;
-            mGroupOverFlowState = null;
-        }
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        updateGroupOverflow();
-    }
-
-    private View inflateDivider() {
-        return LayoutInflater.from(mContext).inflate(
-                R.layout.notification_children_divider, this, false);
-    }
-
-    public List<ExpandableNotificationRow> getNotificationChildren() {
-        return mChildren;
-    }
-
-    /**
-     * Apply the order given in the list to the children.
-     *
-     * @param childOrder the new list order
-     * @param visualStabilityManager
-     * @param callback
-     * @return whether the list order has changed
-     */
-    public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
-            VisualStabilityManager visualStabilityManager,
-            VisualStabilityManager.Callback callback) {
-        if (childOrder == null) {
-            return false;
-        }
-        boolean result = false;
-        for (int i = 0; i < mChildren.size() && i < childOrder.size(); i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            ExpandableNotificationRow desiredChild = childOrder.get(i);
-            if (child != desiredChild) {
-                if (visualStabilityManager.canReorderNotification(desiredChild)) {
-                    mChildren.remove(desiredChild);
-                    mChildren.add(i, desiredChild);
-                    result = true;
-                } else {
-                    visualStabilityManager.addReorderingAllowedCallback(callback);
-                }
-            }
-        }
-        updateExpansionStates();
-        return result;
-    }
-
-    private void updateExpansionStates() {
-        if (mChildrenExpanded || mUserLocked) {
-            // we don't modify it the group is expanded or if we are expanding it
-            return;
-        }
-        int size = mChildren.size();
-        for (int i = 0; i < size; i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            child.setSystemChildExpanded(i == 0 && size == 1);
-        }
-    }
-
-    /**
-     *
-     * @return the intrinsic size of this children container, i.e the natural fully expanded state
-     */
-    public int getIntrinsicHeight() {
-        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
-        return getIntrinsicHeight(maxAllowedVisibleChildren);
-    }
-
-    /**
-     * @return the intrinsic height with a number of children given
-     *         in @param maxAllowedVisibleChildren
-     */
-    private int getIntrinsicHeight(float maxAllowedVisibleChildren) {
-        if (showingAsLowPriority()) {
-            return mNotificationHeaderLowPriority.getHeight();
-        }
-        int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation;
-        int visibleChildren = 0;
-        int childCount = mChildren.size();
-        boolean firstChild = true;
-        float expandFactor = 0;
-        if (mUserLocked) {
-            expandFactor = getGroupExpandFraction();
-        }
-        boolean childrenExpanded = mChildrenExpanded || mContainingNotification.isShowingAmbient();
-        for (int i = 0; i < childCount; i++) {
-            if (visibleChildren >= maxAllowedVisibleChildren) {
-                break;
-            }
-            if (!firstChild) {
-                if (mUserLocked) {
-                    intrinsicHeight += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
-                            expandFactor);
-                } else {
-                    intrinsicHeight += childrenExpanded ? mDividerHeight : mChildPadding;
-                }
-            } else {
-                if (mUserLocked) {
-                    intrinsicHeight += NotificationUtils.interpolate(
-                            0,
-                            mNotificatonTopPadding + mDividerHeight,
-                            expandFactor);
-                } else {
-                    intrinsicHeight += childrenExpanded
-                            ? mNotificatonTopPadding + mDividerHeight
-                            : 0;
-                }
-                firstChild = false;
-            }
-            ExpandableNotificationRow child = mChildren.get(i);
-            intrinsicHeight += child.getIntrinsicHeight();
-            visibleChildren++;
-        }
-        if (mUserLocked) {
-            intrinsicHeight += NotificationUtils.interpolate(mCollapsedBottompadding, 0.0f,
-                    expandFactor);
-        } else if (!childrenExpanded) {
-            intrinsicHeight += mCollapsedBottompadding;
-        }
-        return intrinsicHeight;
-    }
-
-    /**
-     * Update the state of all its children based on a linear layout algorithm.
-     *  @param resultState the state to update
-     * @param parentState the state of the parent
-     * @param ambientState
-     */
-    public void getState(StackScrollState resultState, ExpandableViewState parentState,
-            AmbientState ambientState) {
-        int childCount = mChildren.size();
-        int yPosition = mNotificationHeaderMargin + mCurrentHeaderTranslation;
-        boolean firstChild = true;
-        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
-        int lastVisibleIndex = maxAllowedVisibleChildren - 1;
-        int firstOverflowIndex = lastVisibleIndex + 1;
-        float expandFactor = 0;
-        boolean expandingToExpandedGroup = mUserLocked && !showingAsLowPriority();
-        if (mUserLocked) {
-            expandFactor = getGroupExpandFraction();
-            firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
-        }
-
-        boolean childrenExpandedAndNotAnimating = mChildrenExpanded
-                && !mContainingNotification.isGroupExpansionChanging();
-        int launchTransitionCompensation = 0;
-        for (int i = 0; i < childCount; i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            if (!firstChild) {
-                if (expandingToExpandedGroup) {
-                    yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
-                            expandFactor);
-                } else {
-                    yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding;
-                }
-            } else {
-                if (expandingToExpandedGroup) {
-                    yPosition += NotificationUtils.interpolate(
-                            0,
-                            mNotificatonTopPadding + mDividerHeight,
-                            expandFactor);
-                } else {
-                    yPosition += mChildrenExpanded ? mNotificatonTopPadding + mDividerHeight : 0;
-                }
-                firstChild = false;
-            }
-
-            ExpandableViewState childState = resultState.getViewStateForView(child);
-            int intrinsicHeight = child.getIntrinsicHeight();
-            childState.height = intrinsicHeight;
-            childState.yTranslation = yPosition + launchTransitionCompensation;
-            childState.hidden = false;
-            // When the group is expanded, the children cast the shadows rather than the parent
-            // so use the parent's elevation here.
-            childState.zTranslation =
-                    (childrenExpandedAndNotAnimating && mEnableShadowOnChildNotifications)
-                    ? parentState.zTranslation
-                    : 0;
-            childState.dimmed = parentState.dimmed;
-            childState.dark = parentState.dark;
-            childState.hideSensitive = parentState.hideSensitive;
-            childState.belowSpeedBump = parentState.belowSpeedBump;
-            childState.clipTopAmount = 0;
-            childState.alpha = 0;
-            if (i < firstOverflowIndex) {
-                childState.alpha = showingAsLowPriority() ? expandFactor : 1.0f;
-            } else if (expandFactor == 1.0f && i <= lastVisibleIndex) {
-                childState.alpha = (mActualHeight - childState.yTranslation) / childState.height;
-                childState.alpha = Math.max(0.0f, Math.min(1.0f, childState.alpha));
-            }
-            childState.location = parentState.location;
-            childState.inShelf = parentState.inShelf;
-            yPosition += intrinsicHeight;
-            if (child.isExpandAnimationRunning()) {
-                launchTransitionCompensation = -ambientState.getExpandAnimationTopChange();
-            }
-
-        }
-        if (mOverflowNumber != null) {
-            ExpandableNotificationRow overflowView = mChildren.get(Math.min(
-                    getMaxAllowedVisibleChildren(true /* likeCollapsed */), childCount) - 1);
-            mGroupOverFlowState.copyFrom(resultState.getViewStateForView(overflowView));
-
-            if (mContainingNotification.isShowingAmbient()) {
-                mGroupOverFlowState.alpha = 0.0f;
-            } else if (!mChildrenExpanded) {
-                HybridNotificationView alignView = overflowView.getSingleLineView();
-                if (alignView != null) {
-                    View mirrorView = alignView.getTextView();
-                    if (mirrorView.getVisibility() == GONE) {
-                        mirrorView = alignView.getTitleView();
-                    }
-                    if (mirrorView.getVisibility() == GONE) {
-                        mirrorView = alignView;
-                    }
-                    mGroupOverFlowState.alpha = mirrorView.getAlpha();
-                    mGroupOverFlowState.yTranslation += NotificationUtils.getRelativeYOffset(
-                            mirrorView, overflowView);
-                }
-            } else {
-                mGroupOverFlowState.yTranslation += mNotificationHeaderMargin;
-                mGroupOverFlowState.alpha = 0.0f;
-            }
-        }
-        if (mNotificationHeader != null) {
-            if (mHeaderViewState == null) {
-                mHeaderViewState = new ViewState();
-            }
-            mHeaderViewState.initFrom(mNotificationHeader);
-            mHeaderViewState.zTranslation = childrenExpandedAndNotAnimating
-                    ? parentState.zTranslation
-                    : 0;
-            mHeaderViewState.yTranslation = mCurrentHeaderTranslation;
-            mHeaderViewState.alpha = mHeaderVisibleAmount;
-            // The hiding is done automatically by the alpha, otherwise we'll pick it up again
-            // in the next frame with the initFrom call above and have an invisible header
-            mHeaderViewState.hidden = false;
-        }
-    }
-
-    /**
-     * When moving into the bottom stack, the bottom visible child in an expanded group adjusts its
-     * height, children in the group after this are gone.
-     *
-     * @param child the child who's height to adjust.
-     * @param parentHeight the height of the parent.
-     * @param childState the state to update.
-     * @param yPosition the yPosition of the view.
-     * @return true if children after this one should be hidden.
-     */
-    private boolean updateChildStateForExpandedGroup(ExpandableNotificationRow child,
-            int parentHeight, ExpandableViewState childState, int yPosition) {
-        final int top = yPosition + child.getClipTopAmount();
-        final int intrinsicHeight = child.getIntrinsicHeight();
-        final int bottom = top + intrinsicHeight;
-        int newHeight = intrinsicHeight;
-        if (bottom >= parentHeight) {
-            // Child is either clipped or gone
-            newHeight = Math.max((parentHeight - top), 0);
-        }
-        childState.hidden = newHeight == 0;
-        childState.height = newHeight;
-        return childState.height != intrinsicHeight && !childState.hidden;
-    }
-
-    @VisibleForTesting
-    int getMaxAllowedVisibleChildren() {
-        return getMaxAllowedVisibleChildren(false /* likeCollapsed */);
-    }
-
-    @VisibleForTesting
-    int getMaxAllowedVisibleChildren(boolean likeCollapsed) {
-        if (mContainingNotification.isShowingAmbient()) {
-            return NUMBER_OF_CHILDREN_WHEN_AMBIENT;
-        }
-        if (!likeCollapsed && (mChildrenExpanded || mContainingNotification.isUserLocked())
-                && !showingAsLowPriority()) {
-            return NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
-        }
-        if (mIsLowPriority || !mContainingNotification.isOnKeyguard()
-                && (mContainingNotification.isExpanded() || mContainingNotification.isHeadsUp())) {
-            return NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED;
-        }
-        return NUMBER_OF_CHILDREN_WHEN_COLLAPSED;
-    }
-
-    public void applyState(StackScrollState state) {
-        int childCount = mChildren.size();
-        ViewState tmpState = new ViewState();
-        float expandFraction = 0.0f;
-        if (mUserLocked) {
-            expandFraction = getGroupExpandFraction();
-        }
-        final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
-                || (mChildrenExpanded && mShowDividersWhenExpanded)
-                || (mContainingNotification.isGroupExpansionChanging()
-                && !mHideDividersDuringExpand);
-        for (int i = 0; i < childCount; i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            ExpandableViewState viewState = state.getViewStateForView(child);
-            viewState.applyToView(child);
-
-            // layout the divider
-            View divider = mDividers.get(i);
-            tmpState.initFrom(divider);
-            tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
-            float alpha = mChildrenExpanded && viewState.alpha != 0 ? mDividerAlpha : 0;
-            if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
-                alpha = NotificationUtils.interpolate(0, 0.5f,
-                        Math.min(viewState.alpha, expandFraction));
-            }
-            tmpState.hidden = !dividersVisible;
-            tmpState.alpha = alpha;
-            tmpState.applyToView(divider);
-            // There is no fake shadow to be drawn on the children
-            child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
-        }
-        if (mGroupOverFlowState != null) {
-            mGroupOverFlowState.applyToView(mOverflowNumber);
-            mNeverAppliedGroupState = false;
-        }
-        if (mHeaderViewState != null) {
-            mHeaderViewState.applyToView(mNotificationHeader);
-        }
-        updateChildrenClipping();
-    }
-
-    private void updateChildrenClipping() {
-        if (mContainingNotification.hasExpandingChild()) {
-            return;
-        }
-        int childCount = mChildren.size();
-        int layoutEnd = mContainingNotification.getActualHeight() - mClipBottomAmount;
-        for (int i = 0; i < childCount; i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            if (child.getVisibility() == GONE) {
-                continue;
-            }
-            float childTop = child.getTranslationY();
-            float childBottom = childTop + child.getActualHeight();
-            boolean visible = true;
-            int clipBottomAmount = 0;
-            if (childTop > layoutEnd) {
-                visible = false;
-            } else if (childBottom > layoutEnd) {
-                clipBottomAmount = (int) (childBottom - layoutEnd);
-            }
-
-            boolean isVisible = child.getVisibility() == VISIBLE;
-            if (visible != isVisible) {
-                child.setVisibility(visible ? VISIBLE : INVISIBLE);
-            }
-
-            child.setClipBottomAmount(clipBottomAmount);
-        }
-    }
-
-    /**
-     * This is called when the children expansion has changed and positions the children properly
-     * for an appear animation.
-     *
-     * @param state the new state we animate to
-     */
-    public void prepareExpansionChanged(StackScrollState state) {
-        // TODO: do something that makes sense, like placing the invisible views correctly
-        return;
-    }
-
-    public void startAnimationToState(StackScrollState state, AnimationProperties properties) {
-        int childCount = mChildren.size();
-        ViewState tmpState = new ViewState();
-        float expandFraction = getGroupExpandFraction();
-        final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
-                || (mChildrenExpanded && mShowDividersWhenExpanded)
-                || (mContainingNotification.isGroupExpansionChanging()
-                && !mHideDividersDuringExpand);
-        for (int i = childCount - 1; i >= 0; i--) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            ExpandableViewState viewState = state.getViewStateForView(child);
-            viewState.animateTo(child, properties);
-
-            // layout the divider
-            View divider = mDividers.get(i);
-            tmpState.initFrom(divider);
-            tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
-            float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
-            if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
-                alpha = NotificationUtils.interpolate(0, 0.5f,
-                        Math.min(viewState.alpha, expandFraction));
-            }
-            tmpState.hidden = !dividersVisible;
-            tmpState.alpha = alpha;
-            tmpState.animateTo(divider, properties);
-            // There is no fake shadow to be drawn on the children
-            child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
-        }
-        if (mOverflowNumber != null) {
-            if (mNeverAppliedGroupState) {
-                float alpha = mGroupOverFlowState.alpha;
-                mGroupOverFlowState.alpha = 0;
-                mGroupOverFlowState.applyToView(mOverflowNumber);
-                mGroupOverFlowState.alpha = alpha;
-                mNeverAppliedGroupState = false;
-            }
-            mGroupOverFlowState.animateTo(mOverflowNumber, properties);
-        }
-        if (mNotificationHeader != null) {
-            mHeaderViewState.applyToView(mNotificationHeader);
-        }
-        updateChildrenClipping();
-    }
-
-    public ExpandableNotificationRow getViewAtPosition(float y) {
-        // find the view under the pointer, accounting for GONE views
-        final int count = mChildren.size();
-        for (int childIdx = 0; childIdx < count; childIdx++) {
-            ExpandableNotificationRow slidingChild = mChildren.get(childIdx);
-            float childTop = slidingChild.getTranslationY();
-            float top = childTop + slidingChild.getClipTopAmount();
-            float bottom = childTop + slidingChild.getActualHeight();
-            if (y >= top && y <= bottom) {
-                return slidingChild;
-            }
-        }
-        return null;
-    }
-
-    public void setChildrenExpanded(boolean childrenExpanded) {
-        mChildrenExpanded = childrenExpanded;
-        updateExpansionStates();
-        if (mNotificationHeader != null) {
-            mNotificationHeader.setExpanded(childrenExpanded);
-        }
-        final int count = mChildren.size();
-        for (int childIdx = 0; childIdx < count; childIdx++) {
-            ExpandableNotificationRow child = mChildren.get(childIdx);
-            child.setChildrenExpanded(childrenExpanded, false);
-        }
-    }
-
-    public void setContainingNotification(ExpandableNotificationRow parent) {
-        mContainingNotification = parent;
-        mHeaderUtil = new NotificationHeaderUtil(mContainingNotification);
-    }
-
-    public ExpandableNotificationRow getContainingNotification() {
-        return mContainingNotification;
-    }
-
-    public NotificationHeaderView getHeaderView() {
-        return mNotificationHeader;
-    }
-
-    public NotificationHeaderView getLowPriorityHeaderView() {
-        return mNotificationHeaderLowPriority;
-    }
-
-    @VisibleForTesting
-    public ViewGroup getCurrentHeaderView() {
-        return mCurrentHeader;
-    }
-
-    public void notifyShowAmbientChanged() {
-        updateHeaderVisibility(false);
-        updateGroupOverflow();
-    }
-
-    private void updateHeaderVisibility(boolean animate) {
-        ViewGroup desiredHeader;
-        ViewGroup currentHeader = mCurrentHeader;
-        desiredHeader = calculateDesiredHeader();
-
-        if (currentHeader == desiredHeader) {
-            return;
-        }
-        if (desiredHeader == mNotificationHeaderAmbient
-                || currentHeader == mNotificationHeaderAmbient) {
-            animate = false;
-        }
-
-        if (animate) {
-            if (desiredHeader != null && currentHeader != null) {
-                currentHeader.setVisibility(VISIBLE);
-                desiredHeader.setVisibility(VISIBLE);
-                NotificationViewWrapper visibleWrapper = getWrapperForView(desiredHeader);
-                NotificationViewWrapper hiddenWrapper = getWrapperForView(currentHeader);
-                visibleWrapper.transformFrom(hiddenWrapper);
-                hiddenWrapper.transformTo(visibleWrapper, () -> updateHeaderVisibility(false));
-                startChildAlphaAnimations(desiredHeader == mNotificationHeader);
-            } else {
-                animate = false;
-            }
-        }
-        if (!animate) {
-            if (desiredHeader != null) {
-                getWrapperForView(desiredHeader).setVisible(true);
-                desiredHeader.setVisibility(VISIBLE);
-            }
-            if (currentHeader != null) {
-                // Wrapper can be null if we were a low priority notification
-                // and just destroyed it by calling setIsLowPriority(false)
-                NotificationViewWrapper wrapper = getWrapperForView(currentHeader);
-                if (wrapper != null) {
-                    wrapper.setVisible(false);
-                }
-                currentHeader.setVisibility(INVISIBLE);
-            }
-        }
-
-        resetHeaderVisibilityIfNeeded(mNotificationHeader, desiredHeader);
-        resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, desiredHeader);
-        resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, desiredHeader);
-
-        mCurrentHeader = desiredHeader;
-    }
-
-    private void resetHeaderVisibilityIfNeeded(View header, View desiredHeader) {
-        if (header == null) {
-            return;
-        }
-        if (header != mCurrentHeader && header != desiredHeader) {
-            getWrapperForView(header).setVisible(false);
-            header.setVisibility(INVISIBLE);
-        }
-        if (header == desiredHeader && header.getVisibility() != VISIBLE) {
-            getWrapperForView(header).setVisible(true);
-            header.setVisibility(VISIBLE);
-        }
-    }
-
-    private ViewGroup calculateDesiredHeader() {
-        ViewGroup desiredHeader;
-        if (mContainingNotification.isShowingAmbient()) {
-            desiredHeader = mNotificationHeaderAmbient;
-        } else if (showingAsLowPriority()) {
-            desiredHeader = mNotificationHeaderLowPriority;
-        } else {
-            desiredHeader = mNotificationHeader;
-        }
-        return desiredHeader;
-    }
-
-    private void startChildAlphaAnimations(boolean toVisible) {
-        float target = toVisible ? 1.0f : 0.0f;
-        float start = 1.0f - target;
-        int childCount = mChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            if (i >= NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED) {
-                break;
-            }
-            ExpandableNotificationRow child = mChildren.get(i);
-            child.setAlpha(start);
-            ViewState viewState = new ViewState();
-            viewState.initFrom(child);
-            viewState.alpha = target;
-            ALPHA_FADE_IN.setDelay(i * 50);
-            viewState.animateTo(child, ALPHA_FADE_IN);
-        }
-    }
-
-
-    private void updateHeaderTransformation() {
-        if (mUserLocked && showingAsLowPriority()) {
-            float fraction = getGroupExpandFraction();
-            mNotificationHeaderWrapper.transformFrom(mNotificationHeaderWrapperLowPriority,
-                    fraction);
-            mNotificationHeader.setVisibility(VISIBLE);
-            mNotificationHeaderWrapperLowPriority.transformTo(mNotificationHeaderWrapper,
-                    fraction);
-        }
-
-    }
-
-    private NotificationViewWrapper getWrapperForView(View visibleHeader) {
-        if (visibleHeader == mNotificationHeader) {
-            return mNotificationHeaderWrapper;
-        }
-        if (visibleHeader == mNotificationHeaderAmbient) {
-            return mNotificationHeaderWrapperAmbient;
-        }
-        return mNotificationHeaderWrapperLowPriority;
-    }
-
-    /**
-     * Called when a groups expansion changes to adjust the background of the header view.
-     *
-     * @param expanded whether the group is expanded.
-     */
-    public void updateHeaderForExpansion(boolean expanded) {
-        if (mNotificationHeader != null) {
-            if (expanded) {
-                ColorDrawable cd = new ColorDrawable();
-                cd.setColor(mContainingNotification.calculateBgColor());
-                mNotificationHeader.setHeaderBackgroundDrawable(cd);
-            } else {
-                mNotificationHeader.setHeaderBackgroundDrawable(null);
-            }
-        }
-    }
-
-    public int getMaxContentHeight() {
-        if (showingAsLowPriority()) {
-            return getMinHeight(NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED, true
-                    /* likeHighPriority */);
-        }
-        int maxContentHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation
-                + mNotificatonTopPadding;
-        int visibleChildren = 0;
-        int childCount = mChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            if (visibleChildren >= NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED) {
-                break;
-            }
-            ExpandableNotificationRow child = mChildren.get(i);
-            float childHeight = child.isExpanded(true /* allowOnKeyguard */)
-                    ? child.getMaxExpandHeight()
-                    : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
-            maxContentHeight += childHeight;
-            visibleChildren++;
-        }
-        if (visibleChildren > 0) {
-            maxContentHeight += visibleChildren * mDividerHeight;
-        }
-        return maxContentHeight;
-    }
-
-    public void setActualHeight(int actualHeight) {
-        if (!mUserLocked) {
-            return;
-        }
-        mActualHeight = actualHeight;
-        float fraction = getGroupExpandFraction();
-        boolean showingLowPriority = showingAsLowPriority();
-        updateHeaderTransformation();
-        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
-        int childCount = mChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            float childHeight;
-            if (showingLowPriority) {
-                childHeight = child.getShowingLayout().getMinHeight(false /* likeGroupExpanded */);
-            } else if (child.isExpanded(true /* allowOnKeyguard */)) {
-                childHeight = child.getMaxExpandHeight();
-            } else {
-                childHeight = child.getShowingLayout().getMinHeight(
-                        true /* likeGroupExpanded */);
-            }
-            if (i < maxAllowedVisibleChildren) {
-                float singleLineHeight = child.getShowingLayout().getMinHeight(
-                        false /* likeGroupExpanded */);
-                child.setActualHeight((int) NotificationUtils.interpolate(singleLineHeight,
-                        childHeight, fraction), false);
-            } else {
-                child.setActualHeight((int) childHeight, false);
-            }
-        }
-    }
-
-    public float getGroupExpandFraction() {
-        int visibleChildrenExpandedHeight = showingAsLowPriority() ? getMaxContentHeight()
-                : getVisibleChildrenExpandHeight();
-        int minExpandHeight = getCollapsedHeight();
-        float factor = (mActualHeight - minExpandHeight)
-                / (float) (visibleChildrenExpandedHeight - minExpandHeight);
-        return Math.max(0.0f, Math.min(1.0f, factor));
-    }
-
-    private int getVisibleChildrenExpandHeight() {
-        int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation
-                + mNotificatonTopPadding + mDividerHeight;
-        int visibleChildren = 0;
-        int childCount = mChildren.size();
-        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
-        for (int i = 0; i < childCount; i++) {
-            if (visibleChildren >= maxAllowedVisibleChildren) {
-                break;
-            }
-            ExpandableNotificationRow child = mChildren.get(i);
-            float childHeight = child.isExpanded(true /* allowOnKeyguard */)
-                    ? child.getMaxExpandHeight()
-                    : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
-            intrinsicHeight += childHeight;
-            visibleChildren++;
-        }
-        return intrinsicHeight;
-    }
-
-    public int getMinHeight() {
-        return getMinHeight(mContainingNotification.isShowingAmbient()
-                ? NUMBER_OF_CHILDREN_WHEN_AMBIENT
-                : NUMBER_OF_CHILDREN_WHEN_COLLAPSED, false /* likeHighPriority */);
-    }
-
-    public int getCollapsedHeight() {
-        return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */),
-                false /* likeHighPriority */);
-    }
-
-    /**
-     * Get the minimum Height for this group.
-     *
-     * @param maxAllowedVisibleChildren the number of children that should be visible
-     * @param likeHighPriority if the height should be calculated as if it were not low priority
-     */
-    private int getMinHeight(int maxAllowedVisibleChildren, boolean likeHighPriority) {
-        if (!likeHighPriority && showingAsLowPriority()) {
-            return mNotificationHeaderLowPriority.getHeight();
-        }
-        int minExpandHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation;
-        int visibleChildren = 0;
-        boolean firstChild = true;
-        int childCount = mChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            if (visibleChildren >= maxAllowedVisibleChildren) {
-                break;
-            }
-            if (!firstChild) {
-                minExpandHeight += mChildPadding;
-            } else {
-                firstChild = false;
-            }
-            ExpandableNotificationRow child = mChildren.get(i);
-            minExpandHeight += child.getSingleLineView().getHeight();
-            visibleChildren++;
-        }
-        minExpandHeight += mCollapsedBottompadding;
-        return minExpandHeight;
-    }
-
-    public boolean showingAsLowPriority() {
-        return mIsLowPriority && !mContainingNotification.isExpanded();
-    }
-
-    public void setDark(boolean dark, boolean fade, long delay) {
-        if (mOverflowNumber != null) {
-            mHybridGroupManager.setOverflowNumberDark(mOverflowNumber, dark, fade, delay);
-        }
-    }
-
-    public void reInflateViews(OnClickListener listener, StatusBarNotification notification) {
-        if (mNotificationHeader != null) {
-            removeView(mNotificationHeader);
-            mNotificationHeader = null;
-        }
-        if (mNotificationHeaderLowPriority != null) {
-            removeView(mNotificationHeaderLowPriority);
-            mNotificationHeaderLowPriority = null;
-        }
-        if (mNotificationHeaderAmbient != null) {
-            removeView(mNotificationHeaderAmbient);
-            mNotificationHeaderAmbient = null;
-        }
-        recreateNotificationHeader(listener);
-        initDimens();
-        for (int i = 0; i < mDividers.size(); i++) {
-            View prevDivider = mDividers.get(i);
-            int index = indexOfChild(prevDivider);
-            removeView(prevDivider);
-            View divider = inflateDivider();
-            addView(divider, index);
-            mDividers.set(i, divider);
-        }
-        removeView(mOverflowNumber);
-        mOverflowNumber = null;
-        mGroupOverFlowState = null;
-        updateGroupOverflow();
-    }
-
-    public void setUserLocked(boolean userLocked) {
-        mUserLocked = userLocked;
-        if (!mUserLocked) {
-            updateHeaderVisibility(false /* animate */);
-        }
-        int childCount = mChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            child.setUserLocked(userLocked && !showingAsLowPriority());
-        }
-    }
-
-    public void onNotificationUpdated() {
-        mHybridGroupManager.setOverflowNumberColor(mOverflowNumber,
-                mContainingNotification.getNotificationColor(),
-                mContainingNotification.getNotificationColorAmbient());
-    }
-
-    public int getPositionInLinearLayout(View childInGroup) {
-        int position = mNotificationHeaderMargin + mCurrentHeaderTranslation
-                + mNotificatonTopPadding;
-
-        for (int i = 0; i < mChildren.size(); i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            boolean notGone = child.getVisibility() != View.GONE;
-            if (notGone) {
-                position += mDividerHeight;
-            }
-            if (child == childInGroup) {
-                return position;
-            }
-            if (notGone) {
-                position += child.getIntrinsicHeight();
-            }
-        }
-        return 0;
-    }
-
-    public void setIconsVisible(boolean iconsVisible) {
-        if (mNotificationHeaderWrapper != null) {
-            NotificationHeaderView header = mNotificationHeaderWrapper.getNotificationHeader();
-            if (header != null) {
-                header.getIcon().setForceHidden(!iconsVisible);
-            }
-        }
-        if (mNotificationHeaderWrapperLowPriority != null) {
-            NotificationHeaderView header
-                    = mNotificationHeaderWrapperLowPriority.getNotificationHeader();
-            if (header != null) {
-                header.getIcon().setForceHidden(!iconsVisible);
-            }
-        }
-    }
-
-    public void setClipBottomAmount(int clipBottomAmount) {
-        mClipBottomAmount = clipBottomAmount;
-        updateChildrenClipping();
-    }
-
-    public void setIsLowPriority(boolean isLowPriority) {
-        mIsLowPriority = isLowPriority;
-        if (mContainingNotification != null) { /* we're not yet set up yet otherwise */
-            recreateLowPriorityHeader(null /* existingBuilder */);
-            updateHeaderVisibility(false /* animate */);
-        }
-        if (mUserLocked) {
-            setUserLocked(mUserLocked);
-        }
-    }
-
-    public NotificationHeaderView getVisibleHeader() {
-        NotificationHeaderView header = mNotificationHeader;
-        if (showingAsLowPriority()) {
-            header = mNotificationHeaderLowPriority;
-        }
-        return header;
-    }
-
-    public void onExpansionChanged() {
-        if (mIsLowPriority) {
-            if (mUserLocked) {
-                setUserLocked(mUserLocked);
-            }
-            updateHeaderVisibility(true /* animate */);
-        }
-    }
-
-    public float getIncreasedPaddingAmount() {
-        if (showingAsLowPriority()) {
-            return 0.0f;
-        }
-        return getGroupExpandFraction();
-    }
-
-    @VisibleForTesting
-    public boolean isUserLocked() {
-        return mUserLocked;
-    }
-
-    public void setCurrentBottomRoundness(float currentBottomRoundness) {
-        boolean last = true;
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            if (child.getVisibility() == View.GONE) {
-                continue;
-            }
-            float bottomRoundness = last ? currentBottomRoundness : 0.0f;
-            child.setBottomRoundness(bottomRoundness, isShown() /* animate */);
-            last = false;
-        }
-    }
-
-    public void setHeaderVisibleAmount(float headerVisibleAmount) {
-        mHeaderVisibleAmount = headerVisibleAmount;
-        mCurrentHeaderTranslation = (int) ((1.0f - headerVisibleAmount) * mTranslationForHeader);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationRoundnessManager.java
deleted file mode 100644
index f98b3d9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationRoundnessManager.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import android.view.View;
-
-import com.android.systemui.statusbar.ActivatableNotificationView;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-
-import java.util.HashSet;
-
-/**
- * A class that manages the roundness for notification views
- */
-class NotificationRoundnessManager implements OnHeadsUpChangedListener {
-
-    private boolean mExpanded;
-    private ActivatableNotificationView mFirst;
-    private ActivatableNotificationView mLast;
-    private HashSet<View> mAnimatedChildren;
-    private Runnable mRoundingChangedCallback;
-    private ExpandableNotificationRow mTrackedHeadsUp;
-    private float mAppearFraction;
-
-    @Override
-    public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
-        updateRounding(headsUp, false /* animate */);
-    }
-
-    @Override
-    public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
-        updateRounding(headsUp, true /* animate */);
-    }
-
-    public void onHeadsupAnimatingAwayChanged(ExpandableNotificationRow row,
-            boolean isAnimatingAway) {
-        updateRounding(row, false /* animate */);
-    }
-
-    private void updateRounding(ActivatableNotificationView view, boolean animate) {
-        float topRoundness = getRoundness(view, true /* top */);
-        float bottomRoundness = getRoundness(view, false /* top */);
-        boolean firstChanged = view.setTopRoundness(topRoundness, animate);
-        boolean secondChanged = view.setBottomRoundness(bottomRoundness, animate);
-        if ((view == mFirst || view == mLast) && (firstChanged || secondChanged)) {
-            mRoundingChangedCallback.run();
-        }
-    }
-
-    private float getRoundness(ActivatableNotificationView view, boolean top) {
-        if ((view.isPinned() || view.isHeadsUpAnimatingAway()) && !mExpanded) {
-            return 1.0f;
-        }
-        if (view == mFirst && top) {
-            return 1.0f;
-        }
-        if (view == mLast && !top) {
-            return 1.0f;
-        }
-        if (view == mTrackedHeadsUp && mAppearFraction <= 0.0f) {
-            // If we're pushing up on a headsup the appear fraction is < 0 and it needs to still be
-            // rounded.
-            return 1.0f;
-        }
-        return 0.0f;
-    }
-
-    public void setExpanded(float expandedHeight, float appearFraction) {
-        mExpanded = expandedHeight != 0.0f;
-        mAppearFraction = appearFraction;
-        if (mTrackedHeadsUp != null) {
-            updateRounding(mTrackedHeadsUp, true);
-        }
-    }
-
-    public void setFirstAndLastBackgroundChild(ActivatableNotificationView first,
-            ActivatableNotificationView last) {
-        boolean firstChanged = mFirst != first;
-        boolean lastChanged = mLast != last;
-        if (!firstChanged && !lastChanged) {
-            return;
-        }
-        ActivatableNotificationView oldFirst = mFirst;
-        ActivatableNotificationView oldLast = mLast;
-        mFirst = first;
-        mLast = last;
-        if (firstChanged && oldFirst != null && !oldFirst.isRemoved()) {
-            updateRounding(oldFirst, oldFirst.isShown());
-        }
-        if (lastChanged && oldLast != null && !oldLast.isRemoved()) {
-            updateRounding(oldLast, oldLast.isShown());
-        }
-        if (mFirst != null) {
-            updateRounding(mFirst, mFirst.isShown() && !mAnimatedChildren.contains(mFirst));
-        }
-        if (mLast != null) {
-            updateRounding(mLast, mLast.isShown() && !mAnimatedChildren.contains(mLast));
-        }
-        mRoundingChangedCallback.run();
-    }
-
-    public void setAnimatedChildren(HashSet<View> animatedChildren) {
-        mAnimatedChildren = animatedChildren;
-    }
-
-    public void setOnRoundingChangedCallback(Runnable roundingChangedCallback) {
-        mRoundingChangedCallback = roundingChangedCallback;
-    }
-
-    public void setTrackingHeadsUp(ExpandableNotificationRow row) {
-        mTrackedHeadsUp = row;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
deleted file mode 100644
index a4e184b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ /dev/null
@@ -1,5226 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
-        .ExpandAnimationParameters;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.TimeAnimator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.FloatRange;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PointF;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.Handler;
-import android.service.notification.StatusBarNotification;
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.core.graphics.ColorUtils;
-import android.util.AttributeSet;
-import android.util.FloatProperty;
-import android.util.Log;
-import android.util.MathUtils;
-import android.util.Pair;
-import android.util.Property;
-import android.view.ContextThemeWrapper;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.WindowInsets;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-import android.widget.OverScroller;
-import android.widget.ScrollView;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.keyguard.KeyguardSliceView;
-import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
-import com.android.systemui.ExpandHelper;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.SwipeHelper;
-import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-import com.android.systemui.statusbar.ActivatableNotificationView;
-import com.android.systemui.statusbar.EmptyShadeView;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
-import com.android.systemui.statusbar.FooterView;
-import com.android.systemui.statusbar.NotificationBlockingHelperManager;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationGuts;
-import com.android.systemui.statusbar.NotificationListContainer;
-import com.android.systemui.statusbar.NotificationLogger;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.NotificationSnooze;
-import com.android.systemui.statusbar.StackScrollerDecorView;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.FakeShadowView;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.NotificationIconAreaController;
-import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.HeadsUpUtil;
-import com.android.systemui.statusbar.policy.ScrollAdapter;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.function.BiConsumer;
-
-/**
- * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
- */
-public class NotificationStackScrollLayout extends ViewGroup
-        implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter,
-        ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener,
-        NotificationMenuRowPlugin.OnMenuEventListener, VisibilityLocationProvider,
-        NotificationListContainer {
-
-    public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
-    private static final String TAG = "StackScroller";
-    private static final boolean DEBUG = false;
-    private static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
-    private static final float RUBBER_BAND_FACTOR_AFTER_EXPAND = 0.15f;
-    private static final float RUBBER_BAND_FACTOR_ON_PANEL_EXPAND = 0.21f;
-    /**
-     * Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
-     */
-    private static final int INVALID_POINTER = -1;
-
-    private ExpandHelper mExpandHelper;
-    private NotificationSwipeHelper mSwipeHelper;
-    private boolean mSwipingInProgress;
-    private int mCurrentStackHeight = Integer.MAX_VALUE;
-    private final Paint mBackgroundPaint = new Paint();
-    private final boolean mShouldDrawNotificationBackground;
-
-    private float mExpandedHeight;
-    private int mOwnScrollY;
-    private int mMaxLayoutHeight;
-
-    private VelocityTracker mVelocityTracker;
-    private OverScroller mScroller;
-    private Runnable mFinishScrollingCallback;
-    private int mTouchSlop;
-    private int mMinimumVelocity;
-    private int mMaximumVelocity;
-    private int mOverflingDistance;
-    private float mMaxOverScroll;
-    private boolean mIsBeingDragged;
-    private int mLastMotionY;
-    private int mDownX;
-    private int mActivePointerId = INVALID_POINTER;
-    private boolean mTouchIsClick;
-    private float mInitialTouchX;
-    private float mInitialTouchY;
-
-    private Paint mDebugPaint;
-    private int mContentHeight;
-    private int mIntrinsicContentHeight;
-    private int mCollapsedSize;
-    private int mPaddingBetweenElements;
-    private int mIncreasedPaddingBetweenElements;
-    private int mMaxTopPadding;
-    private int mRegularTopPadding;
-    private int mDarkTopPadding;
-    // Current padding, will be either mRegularTopPadding or mDarkTopPadding
-    private int mTopPadding;
-    // Distance between AOD separator and shelf
-    private int mDarkSeparatorPadding;
-    private int mBottomMargin;
-    private int mBottomInset = 0;
-    private float mQsExpansionFraction;
-
-    /**
-     * The algorithm which calculates the properties for our children
-     */
-    protected final StackScrollAlgorithm mStackScrollAlgorithm;
-
-    /**
-     * The current State this Layout is in
-     */
-    private StackScrollState mCurrentStackScrollState = new StackScrollState(this);
-    private final AmbientState mAmbientState;
-    private NotificationGroupManager mGroupManager;
-    private HashSet<View> mChildrenToAddAnimated = new HashSet<>();
-    private ArrayList<View> mAddedHeadsUpChildren = new ArrayList<>();
-    private ArrayList<View> mChildrenToRemoveAnimated = new ArrayList<>();
-    private ArrayList<View> mSnappedBackChildren = new ArrayList<>();
-    private ArrayList<View> mDragAnimPendingChildren = new ArrayList<>();
-    private ArrayList<View> mChildrenChangingPositions = new ArrayList<>();
-    private HashSet<View> mFromMoreCardAdditions = new HashSet<>();
-    private ArrayList<AnimationEvent> mAnimationEvents = new ArrayList<>();
-    private ArrayList<View> mSwipedOutViews = new ArrayList<>();
-    private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
-    private boolean mAnimationsEnabled;
-    private boolean mChangePositionInProgress;
-    private boolean mChildTransferInProgress;
-
-    /**
-     * The raw amount of the overScroll on the top, which is not rubber-banded.
-     */
-    private float mOverScrolledTopPixels;
-
-    /**
-     * The raw amount of the overScroll on the bottom, which is not rubber-banded.
-     */
-    private float mOverScrolledBottomPixels;
-    private NotificationLogger.OnChildLocationsChangedListener mListener;
-    private OnOverscrollTopChangedListener mOverscrollTopChangedListener;
-    private ExpandableView.OnHeightChangedListener mOnHeightChangedListener;
-    private OnEmptySpaceClickListener mOnEmptySpaceClickListener;
-    private boolean mNeedsAnimation;
-    private boolean mTopPaddingNeedsAnimation;
-    private boolean mDimmedNeedsAnimation;
-    private boolean mHideSensitiveNeedsAnimation;
-    private boolean mDarkNeedsAnimation;
-    private int mDarkAnimationOriginIndex;
-    private boolean mActivateNeedsAnimation;
-    private boolean mGoToFullShadeNeedsAnimation;
-    private boolean mIsExpanded = true;
-    private boolean mChildrenUpdateRequested;
-    private boolean mIsExpansionChanging;
-    private boolean mPanelTracking;
-    private boolean mExpandingNotification;
-    private boolean mExpandedInThisMotion;
-    private boolean mShouldShowShelfOnly;
-    protected boolean mScrollingEnabled;
-    protected FooterView mFooterView;
-    protected EmptyShadeView mEmptyShadeView;
-    private boolean mDismissAllInProgress;
-    private boolean mFadeNotificationsOnDismiss;
-
-    /**
-     * Was the scroller scrolled to the top when the down motion was observed?
-     */
-    private boolean mScrolledToTopOnFirstDown;
-    /**
-     * The minimal amount of over scroll which is needed in order to switch to the quick settings
-     * when over scrolling on a expanded card.
-     */
-    private float mMinTopOverScrollToEscape;
-    private int mIntrinsicPadding;
-    private float mStackTranslation;
-    private float mTopPaddingOverflow;
-    private boolean mDontReportNextOverScroll;
-    private boolean mDontClampNextScroll;
-    private boolean mNeedViewResizeAnimation;
-    private View mExpandedGroupView;
-    private boolean mEverythingNeedsAnimation;
-
-    /**
-     * The maximum scrollPosition which we are allowed to reach when a notification was expanded.
-     * This is needed to avoid scrolling too far after the notification was collapsed in the same
-     * motion.
-     */
-    private int mMaxScrollAfterExpand;
-    private ExpandableNotificationRow.LongPressListener mLongPressListener;
-
-    private NotificationMenuRowPlugin mCurrMenuRow;
-    private View mTranslatingParentView;
-    private View mMenuExposedView;
-    boolean mCheckForLeavebehind;
-
-    /**
-     * Should in this touch motion only be scrolling allowed? It's true when the scroller was
-     * animating.
-     */
-    private boolean mOnlyScrollingInThisMotion;
-    private boolean mDisallowDismissInThisMotion;
-    private boolean mDisallowScrollingInThisMotion;
-    private long mGoToFullShadeDelay;
-    private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
-            = new ViewTreeObserver.OnPreDrawListener() {
-        @Override
-        public boolean onPreDraw() {
-            updateForcedScroll();
-            updateChildren();
-            mChildrenUpdateRequested = false;
-            getViewTreeObserver().removeOnPreDrawListener(this);
-            return true;
-        }
-    };
-    private StatusBar mStatusBar;
-    private int[] mTempInt2 = new int[2];
-    private boolean mGenerateChildOrderChangedEvent;
-    private HashSet<Runnable> mAnimationFinishedRunnables = new HashSet<>();
-    private HashSet<ExpandableView> mClearTransientViewsWhenFinished = new HashSet<>();
-    private HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations
-            = new HashSet<>();
-    private HeadsUpManagerPhone mHeadsUpManager;
-    private NotificationRoundnessManager mRoundnessManager = new NotificationRoundnessManager();
-    private boolean mTrackingHeadsUp;
-    private ScrimController mScrimController;
-    private boolean mForceNoOverlappingRendering;
-    private final ArrayList<Pair<ExpandableNotificationRow, Boolean>> mTmpList = new ArrayList<>();
-    private FalsingManager mFalsingManager;
-    private boolean mAnimationRunning;
-    private ViewTreeObserver.OnPreDrawListener mRunningAnimationUpdater
-            = new ViewTreeObserver.OnPreDrawListener() {
-        @Override
-        public boolean onPreDraw() {
-            onPreDrawDuringAnimation();
-            return true;
-        }
-    };
-    private Rect mBackgroundBounds = new Rect();
-    private Rect mStartAnimationRect = new Rect();
-    private Rect mEndAnimationRect = new Rect();
-    private Rect mCurrentBounds = new Rect(-1, -1, -1, -1);
-    private boolean mAnimateNextBackgroundBottom;
-    private boolean mAnimateNextBackgroundTop;
-    private ObjectAnimator mBottomAnimator = null;
-    private ObjectAnimator mTopAnimator = null;
-    private ActivatableNotificationView mFirstVisibleBackgroundChild = null;
-    private ActivatableNotificationView mLastVisibleBackgroundChild = null;
-    private int mBgColor;
-    private float mDimAmount;
-    private ValueAnimator mDimAnimator;
-    private ArrayList<ExpandableView> mTmpSortedChildren = new ArrayList<>();
-    private Animator.AnimatorListener mDimEndListener = new AnimatorListenerAdapter() {
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            mDimAnimator = null;
-        }
-    };
-    private ValueAnimator.AnimatorUpdateListener mDimUpdateListener
-            = new ValueAnimator.AnimatorUpdateListener() {
-
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            setDimAmount((Float) animation.getAnimatedValue());
-        }
-    };
-    protected ViewGroup mQsContainer;
-    private boolean mContinuousShadowUpdate;
-    private ViewTreeObserver.OnPreDrawListener mShadowUpdater
-            = new ViewTreeObserver.OnPreDrawListener() {
-
-        @Override
-        public boolean onPreDraw() {
-            updateViewShadows();
-            return true;
-        }
-    };
-    private Comparator<ExpandableView> mViewPositionComparator = new Comparator<ExpandableView>() {
-        @Override
-        public int compare(ExpandableView view, ExpandableView otherView) {
-            float endY = view.getTranslationY() + view.getActualHeight();
-            float otherEndY = otherView.getTranslationY() + otherView.getActualHeight();
-            if (endY < otherEndY) {
-                return -1;
-            } else if (endY > otherEndY) {
-                return 1;
-            } else {
-                // The two notifications end at the same location
-                return 0;
-            }
-        }
-    };
-    private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
-    private boolean mPulsing;
-    private boolean mDrawBackgroundAsSrc;
-    private boolean mFadingOut;
-    private boolean mParentNotFullyVisible;
-    private boolean mGroupExpandedForMeasure;
-    private boolean mScrollable;
-    private View mForcedScroll;
-    private View mNeedingPulseAnimation;
-    private float mDarkAmount = 0f;
-
-    /**
-     * How fast the background scales in the X direction as a factor of the Y expansion.
-     */
-    private float mBackgroundXFactor = 1f;
-    private static final Property<NotificationStackScrollLayout, Float> DARK_AMOUNT =
-            new FloatProperty<NotificationStackScrollLayout>("darkAmount") {
-                @Override
-                public void setValue(NotificationStackScrollLayout object, float value) {
-                    object.setDarkAmount(value);
-                }
-
-                @Override
-                public Float get(NotificationStackScrollLayout object) {
-                    return object.getDarkAmount();
-                }
-            };
-    private ObjectAnimator mDarkAmountAnimator;
-    private boolean mUsingLightTheme;
-    private boolean mQsExpanded;
-    private boolean mForwardScrollable;
-    private boolean mBackwardScrollable;
-    private NotificationShelf mShelf;
-    private int mMaxDisplayedNotifications = -1;
-    private int mStatusBarHeight;
-    private int mMinInteractionHeight;
-    private boolean mNoAmbient;
-    private final Rect mClipRect = new Rect();
-    private boolean mIsClipped;
-    private Rect mRequestedClipBounds;
-    private boolean mInHeadsUpPinnedMode;
-    private boolean mHeadsUpAnimatingAway;
-    private int mStatusBarState;
-    private int mCachedBackgroundColor;
-    private boolean mHeadsUpGoingAwayAnimationsAllowed = true;
-    private Runnable mAnimateScroll = this::animateScroll;
-    private int mCornerRadius;
-    private int mSidePaddings;
-    private final int mSeparatorWidth;
-    private final int mSeparatorThickness;
-    private final Rect mBackgroundAnimationRect = new Rect();
-    private int mAntiBurnInOffsetX;
-    private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>();
-    private int mHeadsUpInset;
-    private HeadsUpAppearanceController mHeadsUpAppearanceController;
-    private NotificationIconAreaController mIconAreaController;
-    private float mVerticalPanelTranslation;
-
-    public NotificationStackScrollLayout(Context context) {
-        this(context, null);
-    }
-
-    public NotificationStackScrollLayout(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        Resources res = getResources();
-
-        mAmbientState = new AmbientState(context);
-        mBgColor = context.getColor(R.color.notification_shade_background_color);
-        int minHeight = res.getDimensionPixelSize(R.dimen.notification_min_height);
-        int maxHeight = res.getDimensionPixelSize(R.dimen.notification_max_height);
-        mExpandHelper = new ExpandHelper(getContext(), this,
-                minHeight, maxHeight);
-        mExpandHelper.setEventSource(this);
-        mExpandHelper.setScrollAdapter(this);
-        mSwipeHelper = new NotificationSwipeHelper(SwipeHelper.X, this, getContext());
-        mStackScrollAlgorithm = createStackScrollAlgorithm(context);
-        initView(context);
-        mFalsingManager = FalsingManager.getInstance(context);
-        mShouldDrawNotificationBackground =
-                res.getBoolean(R.bool.config_drawNotificationBackground);
-        mFadeNotificationsOnDismiss =
-                res.getBoolean(R.bool.config_fadeNotificationsOnDismiss);
-        mSeparatorWidth = res.getDimensionPixelSize(R.dimen.widget_separator_width);
-        mSeparatorThickness = res.getDimensionPixelSize(R.dimen.widget_separator_thickness);
-        mDarkSeparatorPadding = res.getDimensionPixelSize(R.dimen.widget_bottom_separator_padding);
-        mRoundnessManager.setAnimatedChildren(mChildrenToAddAnimated);
-        mRoundnessManager.setOnRoundingChangedCallback(this::invalidate);
-        addOnExpandedHeightListener(mRoundnessManager::setExpanded);
-
-        // Blocking helper manager wants to know the expanded state, update as well.
-        NotificationBlockingHelperManager blockingHelperManager =
-                Dependency.get(NotificationBlockingHelperManager.class);
-        addOnExpandedHeightListener((height, unused) -> {
-            blockingHelperManager.setNotificationShadeExpanded(height);
-        });
-
-        updateWillNotDraw();
-        mBackgroundPaint.setAntiAlias(true);
-        if (DEBUG) {
-            mDebugPaint = new Paint();
-            mDebugPaint.setColor(0xffff0000);
-            mDebugPaint.setStrokeWidth(2);
-            mDebugPaint.setStyle(Paint.Style.STROKE);
-        }
-    }
-
-    @Override
-    public NotificationSwipeActionHelper getSwipeActionHelper() {
-        return mSwipeHelper;
-    }
-
-    @Override
-    public void onMenuClicked(View view, int x, int y, MenuItem item) {
-        if (mLongPressListener == null) {
-            return;
-        }
-        if (view instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-            MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR,
-                    row.getStatusBarNotification().getPackageName());
-        }
-        mLongPressListener.onLongPress(view, x, y, item);
-    }
-
-    @Override
-    public void onMenuReset(View row) {
-        if (mTranslatingParentView != null && row == mTranslatingParentView) {
-            mMenuExposedView = null;
-            mTranslatingParentView = null;
-        }
-    }
-
-    @Override
-    public void onMenuShown(View row) {
-        mMenuExposedView = mTranslatingParentView;
-        if (row instanceof ExpandableNotificationRow) {
-            MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
-                    ((ExpandableNotificationRow) row).getStatusBarNotification()
-                            .getPackageName());
-        }
-        mSwipeHelper.onMenuShown(row);
-    }
-
-    protected void onDraw(Canvas canvas) {
-        if (mShouldDrawNotificationBackground
-                && (mCurrentBounds.top < mCurrentBounds.bottom || mAmbientState.isDark())) {
-            drawBackground(canvas);
-        }
-
-        if (DEBUG) {
-            int y = mTopPadding;
-            canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
-            y = getLayoutHeight();
-            canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
-            y = getHeight() - getEmptyBottomMargin();
-            canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
-        }
-    }
-
-    private void drawBackground(Canvas canvas) {
-        final int lockScreenLeft = mSidePaddings;
-        final int lockScreenRight = getWidth() - mSidePaddings;
-        final int lockScreenTop = mCurrentBounds.top;
-        final int lockScreenBottom = mCurrentBounds.bottom;
-        int separatorWidth = 0;
-        int separatorThickness = 0;
-        if (mIconAreaController.hasShelfIconsWhenFullyDark()) {
-            separatorThickness = mSeparatorThickness;
-            separatorWidth = mSeparatorWidth;
-        }
-        final int darkLeft = getWidth() / 2 - separatorWidth / 2;
-        final int darkRight = darkLeft + separatorWidth;
-        final int darkTop = (int) (mRegularTopPadding + separatorThickness / 2f);
-        final int darkBottom = darkTop + separatorThickness;
-
-        if (mAmbientState.hasPulsingNotifications()) {
-            // No divider, we have a notification icon instead
-        } else if (mAmbientState.isFullyDark()) {
-            // Only draw divider on AOD if we actually have notifications
-            if (mFirstVisibleBackgroundChild != null) {
-                canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint);
-            }
-        } else {
-            float inverseDark = 1 - mDarkAmount;
-            float yProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(inverseDark);
-            float xProgress = Interpolators.FAST_OUT_SLOW_IN
-                    .getInterpolation(inverseDark * mBackgroundXFactor);
-
-            mBackgroundAnimationRect.set(
-                    (int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress),
-                    (int) MathUtils.lerp(darkTop, lockScreenTop, yProgress),
-                    (int) MathUtils.lerp(darkRight, lockScreenRight, xProgress),
-                    (int) MathUtils.lerp(darkBottom, lockScreenBottom, yProgress));
-            if (!mAmbientState.isDark() || mFirstVisibleBackgroundChild != null) {
-                canvas.drawRoundRect(mBackgroundAnimationRect.left, mBackgroundAnimationRect.top,
-                        mBackgroundAnimationRect.right, mBackgroundAnimationRect.bottom,
-                        mCornerRadius, mCornerRadius, mBackgroundPaint);
-            }
-        }
-        updateClipping();
-    }
-
-    private void updateBackgroundDimming() {
-        // No need to update the background color if it's not being drawn.
-        if (!mShouldDrawNotificationBackground) {
-            return;
-        }
-
-        float alpha =
-                BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
-        alpha *= 1f - mDarkAmount;
-        // We need to manually blend in the background color.
-        int scrimColor = mScrimController.getBackgroundColor();
-        int awakeColor = ColorUtils.blendARGB(scrimColor, mBgColor, alpha);
-
-        // Interpolate between semi-transparent notification panel background color
-        // and white AOD separator.
-        float colorInterpolation = Interpolators.DECELERATE_QUINT.getInterpolation(mDarkAmount);
-        int color = ColorUtils.blendARGB(awakeColor, Color.WHITE, colorInterpolation);
-
-        if (mCachedBackgroundColor != color) {
-            mCachedBackgroundColor = color;
-            mBackgroundPaint.setColor(color);
-            invalidate();
-        }
-    }
-
-    private void initView(Context context) {
-        mScroller = new OverScroller(getContext());
-        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
-        setClipChildren(false);
-        final ViewConfiguration configuration = ViewConfiguration.get(context);
-        mTouchSlop = configuration.getScaledTouchSlop();
-        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
-        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
-        mOverflingDistance = configuration.getScaledOverflingDistance();
-
-        Resources res = context.getResources();
-        mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
-        mStackScrollAlgorithm.initView(context);
-        mAmbientState.reload(context);
-        mPaddingBetweenElements = Math.max(1,
-                res.getDimensionPixelSize(R.dimen.notification_divider_height));
-        mIncreasedPaddingBetweenElements =
-                res.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
-        mMinTopOverScrollToEscape = res.getDimensionPixelSize(
-                R.dimen.min_top_overscroll_to_qs);
-        mStatusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
-        mBottomMargin = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom);
-        mSidePaddings = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
-        mMinInteractionHeight = res.getDimensionPixelSize(
-                R.dimen.notification_min_interaction_height);
-        mCornerRadius = res.getDimensionPixelSize(
-                Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius));
-        mHeadsUpInset = mStatusBarHeight + res.getDimensionPixelSize(
-                R.dimen.heads_up_status_bar_padding);
-    }
-
-    public void setDrawBackgroundAsSrc(boolean asSrc) {
-        mDrawBackgroundAsSrc = asSrc;
-        updateSrcDrawing();
-    }
-
-    private void updateSrcDrawing() {
-        if (!mShouldDrawNotificationBackground) {
-            return;
-        }
-
-        mBackgroundPaint.setXfermode(mDrawBackgroundAsSrc && !mFadingOut && !mParentNotFullyVisible
-                ? mSrcMode : null);
-        invalidate();
-    }
-
-    private void notifyHeightChangeListener(ExpandableView view) {
-        notifyHeightChangeListener(view, false /* needsAnimation */);
-    }
-
-    private void notifyHeightChangeListener(ExpandableView view, boolean needsAnimation) {
-        if (mOnHeightChangedListener != null) {
-            mOnHeightChangedListener.onHeightChanged(view, needsAnimation);
-        }
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
-        int width = MeasureSpec.getSize(widthMeasureSpec);
-        int childWidthSpec = MeasureSpec.makeMeasureSpec(width - mSidePaddings * 2,
-                MeasureSpec.getMode(widthMeasureSpec));
-        // We need to measure all children even the GONE ones, such that the heights are calculated
-        // correctly as they are used to calculate how many we can fit on the screen.
-        final int size = getChildCount();
-        for (int i = 0; i < size; i++) {
-            measureChild(getChildAt(i), childWidthSpec, heightMeasureSpec);
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        // we layout all our children centered on the top
-        float centerX = getWidth() / 2.0f;
-        for (int i = 0; i < getChildCount(); i++) {
-            View child = getChildAt(i);
-            // We need to layout all children even the GONE ones, such that the heights are
-            // calculated correctly as they are used to calculate how many we can fit on the screen
-            float width = child.getMeasuredWidth();
-            float height = child.getMeasuredHeight();
-            child.layout((int) (centerX - width / 2.0f),
-                    0,
-                    (int) (centerX + width / 2.0f),
-                    (int) height);
-        }
-        setMaxLayoutHeight(getHeight());
-        updateContentHeight();
-        clampScrollPosition();
-        requestChildrenUpdate();
-        updateFirstAndLastBackgroundViews();
-        updateAlgorithmLayoutMinHeight();
-    }
-
-    private void requestAnimationOnViewResize(ExpandableNotificationRow row) {
-        if (mAnimationsEnabled && (mIsExpanded || row != null && row.isPinned())) {
-            mNeedViewResizeAnimation = true;
-            mNeedsAnimation = true;
-        }
-    }
-
-    public void updateSpeedBumpIndex(int newIndex, boolean noAmbient) {
-        mAmbientState.setSpeedBumpIndex(newIndex);
-        mNoAmbient = noAmbient;
-    }
-
-    @Override
-    public void setChildLocationsChangedListener(
-            NotificationLogger.OnChildLocationsChangedListener listener) {
-        mListener = listener;
-    }
-
-    @Override
-    public boolean isInVisibleLocation(ExpandableNotificationRow row) {
-        ExpandableViewState childViewState = mCurrentStackScrollState.getViewStateForView(row);
-        if (childViewState == null) {
-            return false;
-        }
-        if ((childViewState.location & ExpandableViewState.VISIBLE_LOCATIONS) == 0) {
-            return false;
-        }
-        if (row.getVisibility() != View.VISIBLE) {
-            return false;
-        }
-        return true;
-    }
-
-    private void setMaxLayoutHeight(int maxLayoutHeight) {
-        mMaxLayoutHeight = maxLayoutHeight;
-        mShelf.setMaxLayoutHeight(maxLayoutHeight);
-        updateAlgorithmHeightAndPadding();
-    }
-
-    private void updateAlgorithmHeightAndPadding() {
-        mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding, mDarkAmount);
-        mAmbientState.setLayoutHeight(getLayoutHeight());
-        updateAlgorithmLayoutMinHeight();
-        mAmbientState.setTopPadding(mTopPadding);
-    }
-
-    private void updateAlgorithmLayoutMinHeight() {
-        mAmbientState.setLayoutMinHeight(mQsExpanded || isHeadsUpTransition()
-                ? getLayoutMinHeight() : 0);
-    }
-
-    /**
-     * Updates the children views according to the stack scroll algorithm. Call this whenever
-     * modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
-     */
-    private void updateChildren() {
-        updateScrollStateForAddedChildren();
-        mAmbientState.setCurrentScrollVelocity(mScroller.isFinished()
-                ? 0
-                : mScroller.getCurrVelocity());
-        mAmbientState.setScrollY(mOwnScrollY);
-        mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState);
-        if (!isCurrentlyAnimating() && !mNeedsAnimation) {
-            applyCurrentState();
-        } else {
-            startAnimationToState();
-        }
-    }
-
-    private void onPreDrawDuringAnimation() {
-        mShelf.updateAppearance();
-        updateClippingToTopRoundedCorner();
-        if (!mNeedsAnimation && !mChildrenUpdateRequested) {
-            updateBackground();
-        }
-    }
-
-    private void updateClippingToTopRoundedCorner() {
-        Float clipStart = (float) mTopPadding
-                                 + mStackTranslation
-                                 + mAmbientState.getExpandAnimationTopChange();
-        Float clipEnd = clipStart + mCornerRadius;
-        boolean first = true;
-        for (int i = 0; i < getChildCount(); i++) {
-            ExpandableView child = (ExpandableView) getChildAt(i);
-            if (child.getVisibility() == GONE) {
-                continue;
-            }
-            float start = child.getTranslationY();
-            float end = start + child.getActualHeight();
-            boolean clip = clipStart > start && clipStart < end
-                    || clipEnd >= start && clipEnd <= end;
-            clip &= !(first && mOwnScrollY == 0);
-            child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0)
-                    : ExpandableView.NO_ROUNDNESS);
-            first = false;
-        }
-    }
-
-    private void updateScrollStateForAddedChildren() {
-        if (mChildrenToAddAnimated.isEmpty()) {
-            return;
-        }
-        for (int i = 0; i < getChildCount(); i++) {
-            ExpandableView child = (ExpandableView) getChildAt(i);
-            if (mChildrenToAddAnimated.contains(child)) {
-                int startingPosition = getPositionInLinearLayout(child);
-                float increasedPaddingAmount = child.getIncreasedPaddingAmount();
-                int padding = increasedPaddingAmount == 1.0f ? mIncreasedPaddingBetweenElements
-                        : increasedPaddingAmount == -1.0f ? 0 : mPaddingBetweenElements;
-                int childHeight = getIntrinsicHeight(child) + padding;
-                if (startingPosition < mOwnScrollY) {
-                    // This child starts off screen, so let's keep it offscreen to keep the others visible
-
-                    setOwnScrollY(mOwnScrollY + childHeight);
-                }
-            }
-        }
-        clampScrollPosition();
-    }
-
-    private void updateForcedScroll() {
-        if (mForcedScroll != null && (!mForcedScroll.hasFocus()
-                || !mForcedScroll.isAttachedToWindow())) {
-            mForcedScroll = null;
-        }
-        if (mForcedScroll != null) {
-            ExpandableView expandableView = (ExpandableView) mForcedScroll;
-            int positionInLinearLayout = getPositionInLinearLayout(expandableView);
-            int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
-            int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
-
-            targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange()));
-
-            // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
-            // that it is not visible anymore.
-            if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
-                setOwnScrollY(targetScroll);
-            }
-        }
-    }
-
-    private void requestChildrenUpdate() {
-        if (!mChildrenUpdateRequested) {
-            getViewTreeObserver().addOnPreDrawListener(mChildrenUpdater);
-            mChildrenUpdateRequested = true;
-            invalidate();
-        }
-    }
-
-    private boolean isCurrentlyAnimating() {
-        return mStateAnimator.isRunning();
-    }
-
-    private void clampScrollPosition() {
-        int scrollRange = getScrollRange();
-        if (scrollRange < mOwnScrollY) {
-            setOwnScrollY(scrollRange);
-        }
-    }
-
-    public int getTopPadding() {
-        return mTopPadding;
-    }
-
-    private void setTopPadding(int topPadding, boolean animate) {
-        if (mRegularTopPadding != topPadding) {
-            mRegularTopPadding = topPadding;
-            mDarkTopPadding = topPadding + mDarkSeparatorPadding;
-            mAmbientState.setDarkTopPadding(mDarkTopPadding);
-            updateAlgorithmHeightAndPadding();
-            updateContentHeight();
-            if (animate && mAnimationsEnabled && mIsExpanded) {
-                mTopPaddingNeedsAnimation = true;
-                mNeedsAnimation =  true;
-            }
-            requestChildrenUpdate();
-            notifyHeightChangeListener(null, animate);
-        }
-    }
-
-    /**
-     * Update the height of the panel.
-     *
-     * @param height the expanded height of the panel
-     */
-    public void setExpandedHeight(float height) {
-        mExpandedHeight = height;
-        setIsExpanded(height > 0);
-        int minExpansionHeight = getMinExpansionHeight();
-        if (height < minExpansionHeight) {
-            mClipRect.left = 0;
-            mClipRect.right = getWidth();
-            mClipRect.top = 0;
-            mClipRect.bottom = (int) height;
-            height = minExpansionHeight;
-            setRequestedClipBounds(mClipRect);
-        } else {
-            setRequestedClipBounds(null);
-        }
-        int stackHeight;
-        float translationY;
-        float appearEndPosition = getAppearEndPosition();
-        float appearStartPosition = getAppearStartPosition();
-        float appearFraction = 1.0f;
-        boolean appearing = height < appearEndPosition;
-        mAmbientState.setAppearing(appearing);
-        if (!appearing) {
-            translationY = 0;
-            if (mShouldShowShelfOnly) {
-                stackHeight = mTopPadding + mShelf.getIntrinsicHeight();
-            } else if (mQsExpanded) {
-                int stackStartPosition = mContentHeight - mTopPadding + mIntrinsicPadding;
-                int stackEndPosition = mMaxTopPadding + mShelf.getIntrinsicHeight();
-                if (stackStartPosition <= stackEndPosition) {
-                    stackHeight = stackEndPosition;
-                } else {
-                    stackHeight = (int) NotificationUtils.interpolate(stackStartPosition,
-                            stackEndPosition, mQsExpansionFraction);
-                }
-            } else {
-                stackHeight = (int) height;
-            }
-        } else {
-            appearFraction = getAppearFraction(height);
-            if (appearFraction >= 0) {
-                translationY = NotificationUtils.interpolate(getExpandTranslationStart(), 0,
-                        appearFraction);
-            } else {
-                // This may happen when pushing up a heads up. We linearly push it up from the
-                // start
-                translationY = height - appearStartPosition + getExpandTranslationStart();
-            }
-            if (isHeadsUpTransition()) {
-                stackHeight = mFirstVisibleBackgroundChild.getPinnedHeadsUpHeight();
-                translationY = MathUtils.lerp(mHeadsUpInset - mTopPadding, 0, appearFraction);
-            } else {
-                stackHeight = (int) (height - translationY);
-            }
-        }
-        if (stackHeight != mCurrentStackHeight) {
-            mCurrentStackHeight = stackHeight;
-            updateAlgorithmHeightAndPadding();
-            requestChildrenUpdate();
-        }
-        setStackTranslation(translationY);
-        for (int i = 0; i < mExpandedHeightListeners.size(); i++) {
-            BiConsumer<Float, Float> listener = mExpandedHeightListeners.get(i);
-            listener.accept(mExpandedHeight, appearFraction);
-        }
-    }
-
-    private void setRequestedClipBounds(Rect clipRect) {
-        mRequestedClipBounds = clipRect;
-        updateClipping();
-    }
-
-    /**
-     * Return the height of the content ignoring the footer.
-     */
-    public int getIntrinsicContentHeight() {
-        return mIntrinsicContentHeight;
-    }
-
-    public void updateClipping() {
-        boolean animatingClipping = mDarkAmount > 0 && mDarkAmount < 1;
-        boolean clipped = mRequestedClipBounds != null && !mInHeadsUpPinnedMode
-                && !mHeadsUpAnimatingAway;
-        if (mIsClipped != clipped) {
-            mIsClipped = clipped;
-            updateFadingState();
-        }
-
-        if (animatingClipping) {
-            setClipBounds(mBackgroundAnimationRect);
-        } else if (clipped) {
-            setClipBounds(mRequestedClipBounds);
-        } else {
-            setClipBounds(null);
-        }
-    }
-
-    /**
-     * @return The translation at the beginning when expanding.
-     *         Measured relative to the resting position.
-     */
-    private float getExpandTranslationStart() {
-        return -mTopPadding + getMinExpansionHeight();
-    }
-
-    /**
-     * @return the position from where the appear transition starts when expanding.
-     *         Measured in absolute height.
-     */
-    private float getAppearStartPosition() {
-        if (isHeadsUpTransition()) {
-            return mHeadsUpInset + mFirstVisibleBackgroundChild.getPinnedHeadsUpHeight();
-        }
-        return getMinExpansionHeight();
-    }
-
-    /**
-     * @return the height of the top heads up notification when pinned. This is different from the
-     *         intrinsic height, which also includes whether the notification is system expanded and
-     *         is mainly used when dragging down from a heads up notification.
-     */
-    private int getTopHeadsUpPinnedHeight() {
-        NotificationData.Entry topEntry = mHeadsUpManager.getTopEntry();
-        if (topEntry == null) {
-            return 0;
-        }
-        ExpandableNotificationRow row = topEntry.row;
-        if (row.isChildInGroup()) {
-            final ExpandableNotificationRow groupSummary
-                    = mGroupManager.getGroupSummary(row.getStatusBarNotification());
-            if (groupSummary != null) {
-                row = groupSummary;
-            }
-        }
-        return row.getPinnedHeadsUpHeight();
-    }
-
-    /**
-     * @return the position from where the appear transition ends when expanding.
-     *         Measured in absolute height.
-     */
-    private float getAppearEndPosition() {
-        int appearPosition;
-        int notGoneChildCount = getNotGoneChildCount();
-        if (mEmptyShadeView.getVisibility() == GONE && notGoneChildCount != 0) {
-            if (isHeadsUpTransition()
-                    || (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDark())) {
-                appearPosition = getTopHeadsUpPinnedHeight();
-            } else {
-                appearPosition = 0;
-                if (notGoneChildCount >= 1 && mShelf.getVisibility() != GONE) {
-                    appearPosition += mShelf.getIntrinsicHeight();
-                }
-            }
-        } else {
-            appearPosition = mEmptyShadeView.getHeight();
-        }
-        return appearPosition + (onKeyguard() ? mTopPadding : mIntrinsicPadding);
-    }
-
-    private boolean isHeadsUpTransition() {
-        return mTrackingHeadsUp && mFirstVisibleBackgroundChild != null
-                && mAmbientState.isAboveShelf(mFirstVisibleBackgroundChild);
-    }
-
-    /**
-     * @param height the height of the panel
-     * @return the fraction of the appear animation that has been performed
-     */
-    public float getAppearFraction(float height) {
-        float appearEndPosition = getAppearEndPosition();
-        float appearStartPosition = getAppearStartPosition();
-        return (height - appearStartPosition)
-                / (appearEndPosition - appearStartPosition);
-    }
-
-    public float getStackTranslation() {
-        return mStackTranslation;
-    }
-
-    private void setStackTranslation(float stackTranslation) {
-        if (stackTranslation != mStackTranslation) {
-            mStackTranslation = stackTranslation;
-            mAmbientState.setStackTranslation(stackTranslation);
-            requestChildrenUpdate();
-        }
-    }
-
-    /**
-     * Get the current height of the view. This is at most the msize of the view given by a the
-     * layout but it can also be made smaller by setting {@link #mCurrentStackHeight}
-     *
-     * @return either the layout height or the externally defined height, whichever is smaller
-     */
-    private int getLayoutHeight() {
-        return Math.min(mMaxLayoutHeight, mCurrentStackHeight);
-    }
-
-    public int getFirstItemMinHeight() {
-        final ExpandableView firstChild = getFirstChildNotGone();
-        return firstChild != null ? firstChild.getMinHeight() : mCollapsedSize;
-    }
-
-    public void setLongPressListener(ExpandableNotificationRow.LongPressListener listener) {
-        mLongPressListener = listener;
-    }
-
-    public void setQsContainer(ViewGroup qsContainer) {
-        mQsContainer = qsContainer;
-    }
-
-    /**
-     * Handles cleanup after the given {@code view} has been fully swiped out (including
-     * re-invoking dismiss logic in case the notification has not made its way out yet).
-     */
-    @Override
-    public void onChildDismissed(View view) {
-        ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-        if (!row.isDismissed()) {
-            handleChildViewDismissed(view);
-        }
-        ViewGroup transientContainer = row.getTransientContainer();
-        if (transientContainer != null) {
-            transientContainer.removeTransientView(view);
-        }
-    }
-
-    /**
-     * Starts up notification dismiss and tells the notification, if any, to remove itself from
-     * layout.
-     *
-     * @param view view (e.g. notification) to dismiss from the layout
-     */
-    private void handleChildViewDismissed(View view) {
-        if (mDismissAllInProgress) {
-            return;
-        }
-
-        boolean isBlockingHelperShown = false;
-
-        setSwipingInProgress(false);
-        if (mDragAnimPendingChildren.contains(view)) {
-            // We start the swipe and finish it in the same frame; we don't want a drag animation.
-            mDragAnimPendingChildren.remove(view);
-        }
-        mAmbientState.onDragFinished(view);
-        updateContinuousShadowDrawing();
-
-        if (view instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-            if (row.isHeadsUp()) {
-                mHeadsUpManager.addSwipedOutNotification(row.getStatusBarNotification().getKey());
-            }
-            isBlockingHelperShown =
-                    row.performDismissWithBlockingHelper(false /* fromAccessibility */);
-        }
-
-        if (!isBlockingHelperShown) {
-            mSwipedOutViews.add(view);
-        }
-        mFalsingManager.onNotificationDismissed();
-        if (mFalsingManager.shouldEnforceBouncer()) {
-            mStatusBar.executeRunnableDismissingKeyguard(
-                    null,
-                    null /* cancelAction */,
-                    false /* dismissShade */,
-                    true /* afterKeyguardGone */,
-                    false /* deferred */);
-        }
-    }
-
-    @Override
-    public void onChildSnappedBack(View animView, float targetLeft) {
-        mAmbientState.onDragFinished(animView);
-        updateContinuousShadowDrawing();
-        if (!mDragAnimPendingChildren.contains(animView)) {
-            if (mAnimationsEnabled) {
-                mSnappedBackChildren.add(animView);
-                mNeedsAnimation = true;
-            }
-            requestChildrenUpdate();
-        } else {
-            // We start the swipe and snap back in the same frame, we don't want any animation
-            mDragAnimPendingChildren.remove(animView);
-        }
-        if (mCurrMenuRow != null && targetLeft == 0) {
-            mCurrMenuRow.resetMenu();
-            mCurrMenuRow = null;
-        }
-    }
-
-    @Override
-    public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) {
-        // Returning true prevents alpha fading.
-        return !mFadeNotificationsOnDismiss;
-    }
-
-    @Override
-    public void onBeginDrag(View v) {
-        mFalsingManager.onNotificatonStartDismissing();
-        setSwipingInProgress(true);
-        mAmbientState.onBeginDrag(v);
-        updateContinuousShadowDrawing();
-        if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
-            mDragAnimPendingChildren.add(v);
-            mNeedsAnimation = true;
-        }
-        requestChildrenUpdate();
-    }
-
-    public static boolean isPinnedHeadsUp(View v) {
-        if (v instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-            return row.isHeadsUp() && row.isPinned();
-        }
-        return false;
-    }
-
-    private boolean isHeadsUp(View v) {
-        if (v instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-            return row.isHeadsUp();
-        }
-        return false;
-    }
-
-    @Override
-    public void onDragCancelled(View v) {
-        mFalsingManager.onNotificatonStopDismissing();
-        setSwipingInProgress(false);
-    }
-
-    @Override
-    public float getFalsingThresholdFactor() {
-        return mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
-    }
-
-    @Override
-    public View getChildAtPosition(MotionEvent ev) {
-        View child = getChildAtPosition(ev.getX(), ev.getY());
-        if (child instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            ExpandableNotificationRow parent = row.getNotificationParent();
-            if (parent != null && parent.areChildrenExpanded()
-                    && (parent.areGutsExposed()
-                            || mMenuExposedView == parent
-                        || (parent.getNotificationChildren().size() == 1
-                                && parent.isClearable()))) {
-                // In this case the group is expanded and showing the menu for the
-                // group, further interaction should apply to the group, not any
-                // child notifications so we use the parent of the child. We also do the same
-                // if we only have a single child.
-                child = parent;
-            }
-        }
-        return child;
-    }
-
-    public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) {
-        getLocationOnScreen(mTempInt2);
-        float localTouchY = touchY - mTempInt2[1];
-
-        ExpandableView closestChild = null;
-        float minDist = Float.MAX_VALUE;
-
-        // find the view closest to the location, accounting for GONE views
-        final int count = getChildCount();
-        for (int childIdx = 0; childIdx < count; childIdx++) {
-            ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
-            if (slidingChild.getVisibility() == GONE
-                    || slidingChild instanceof StackScrollerDecorView) {
-                continue;
-            }
-            float childTop = slidingChild.getTranslationY();
-            float top = childTop + slidingChild.getClipTopAmount();
-            float bottom = childTop + slidingChild.getActualHeight()
-                    - slidingChild.getClipBottomAmount();
-
-            float dist = Math.min(Math.abs(top - localTouchY), Math.abs(bottom - localTouchY));
-            if (dist < minDist) {
-                closestChild = slidingChild;
-                minDist = dist;
-            }
-        }
-        return closestChild;
-    }
-
-    @Override
-    public ExpandableView getChildAtRawPosition(float touchX, float touchY) {
-        getLocationOnScreen(mTempInt2);
-        return getChildAtPosition(touchX - mTempInt2[0], touchY - mTempInt2[1]);
-    }
-
-    @Override
-    public ExpandableView getChildAtPosition(float touchX, float touchY) {
-        return getChildAtPosition(touchX, touchY, true /* requireMinHeight */);
-
-    }
-
-    /**
-     * Get the child at a certain screen location.
-     *
-     * @param touchX the x coordinate
-     * @param touchY the y coordinate
-     * @param requireMinHeight Whether a minimum height is required for a child to be returned.
-     * @return the child at the given location.
-     */
-    private ExpandableView getChildAtPosition(float touchX, float touchY,
-            boolean requireMinHeight) {
-        // find the view under the pointer, accounting for GONE views
-        final int count = getChildCount();
-        for (int childIdx = 0; childIdx < count; childIdx++) {
-            ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
-            if (slidingChild.getVisibility() != VISIBLE
-                    || slidingChild instanceof StackScrollerDecorView) {
-                continue;
-            }
-            float childTop = slidingChild.getTranslationY();
-            float top = childTop + slidingChild.getClipTopAmount();
-            float bottom = childTop + slidingChild.getActualHeight()
-                    - slidingChild.getClipBottomAmount();
-
-            // Allow the full width of this view to prevent gesture conflict on Keyguard (phone and
-            // camera affordance).
-            int left = 0;
-            int right = getWidth();
-
-            if ((bottom - top >= mMinInteractionHeight || !requireMinHeight)
-                    && touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
-                if (slidingChild instanceof ExpandableNotificationRow) {
-                    ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
-                    if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
-                            && mHeadsUpManager.getTopEntry().row != row
-                            && mGroupManager.getGroupSummary(
-                                mHeadsUpManager.getTopEntry().row.getStatusBarNotification())
-                                != row) {
-                        continue;
-                    }
-                    return row.getViewAtPosition(touchY - childTop);
-                }
-                return slidingChild;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public boolean canChildBeExpanded(View v) {
-        return v instanceof ExpandableNotificationRow
-                && ((ExpandableNotificationRow) v).isExpandable()
-                && !((ExpandableNotificationRow) v).areGutsExposed()
-                && (mIsExpanded || !((ExpandableNotificationRow) v).isPinned());
-    }
-
-    /* Only ever called as a consequence of an expansion gesture in the shade. */
-    @Override
-    public void setUserExpandedChild(View v, boolean userExpanded) {
-        if (v instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-            if (userExpanded && onKeyguard()) {
-                // Due to a race when locking the screen while touching, a notification may be
-                // expanded even after we went back to keyguard. An example of this happens if
-                // you click in the empty space while expanding a group.
-
-                // We also need to un-user lock it here, since otherwise the content height
-                // calculated might be wrong. We also can't invert the two calls since
-                // un-userlocking it will trigger a layout switch in the content view.
-                row.setUserLocked(false);
-                updateContentHeight();
-                notifyHeightChangeListener(row);
-                return;
-            }
-            row.setUserExpanded(userExpanded, true /* allowChildrenExpansion */);
-            row.onExpandedByGesture(userExpanded);
-        }
-    }
-
-    @Override
-    public void setExpansionCancelled(View v) {
-        if (v instanceof ExpandableNotificationRow) {
-            ((ExpandableNotificationRow) v).setGroupExpansionChanging(false);
-        }
-    }
-
-    @Override
-    public void setUserLockedChild(View v, boolean userLocked) {
-        if (v instanceof ExpandableNotificationRow) {
-            ((ExpandableNotificationRow) v).setUserLocked(userLocked);
-        }
-        cancelLongPress();
-        requestDisallowInterceptTouchEvent(true);
-    }
-
-    @Override
-    public void expansionStateChanged(boolean isExpanding) {
-        mExpandingNotification = isExpanding;
-        if (!mExpandedInThisMotion) {
-            mMaxScrollAfterExpand = mOwnScrollY;
-            mExpandedInThisMotion = true;
-        }
-    }
-
-    @Override
-    public int getMaxExpandHeight(ExpandableView view) {
-        return view.getMaxContentHeight();
-    }
-
-    public void setScrollingEnabled(boolean enable) {
-        mScrollingEnabled = enable;
-    }
-
-    public void lockScrollTo(View v) {
-        if (mForcedScroll == v) {
-            return;
-        }
-        mForcedScroll = v;
-        scrollTo(v);
-    }
-
-    public boolean scrollTo(View v) {
-        ExpandableView expandableView = (ExpandableView) v;
-        int positionInLinearLayout = getPositionInLinearLayout(v);
-        int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
-        int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
-
-        // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
-        // that it is not visible anymore.
-        if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
-            mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
-            mDontReportNextOverScroll = true;
-            animateScroll();
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * @return the scroll necessary to make the bottom edge of {@param v} align with the top of
-     *         the IME.
-     */
-    private int targetScrollForView(ExpandableView v, int positionInLinearLayout) {
-        return positionInLinearLayout + v.getIntrinsicHeight() +
-                getImeInset() - getHeight() + getTopPadding();
-    }
-
-    @Override
-    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        mBottomInset = insets.getSystemWindowInsetBottom();
-
-        int range = getScrollRange();
-        if (mOwnScrollY > range) {
-            // HACK: We're repeatedly getting staggered insets here while the IME is
-            // animating away. To work around that we'll wait until things have settled.
-            removeCallbacks(mReclamp);
-            postDelayed(mReclamp, 50);
-        } else if (mForcedScroll != null) {
-            // The scroll was requested before we got the actual inset - in case we need
-            // to scroll up some more do so now.
-            scrollTo(mForcedScroll);
-        }
-        return insets;
-    }
-
-    private Runnable mReclamp = new Runnable() {
-        @Override
-        public void run() {
-            int range = getScrollRange();
-            mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY);
-            mDontReportNextOverScroll = true;
-            mDontClampNextScroll = true;
-            animateScroll();
-        }
-    };
-
-    public void setExpandingEnabled(boolean enable) {
-        mExpandHelper.setEnabled(enable);
-    }
-
-    private boolean isScrollingEnabled() {
-        return mScrollingEnabled;
-    }
-
-    @Override
-    public boolean canChildBeDismissed(View v) {
-        return StackScrollAlgorithm.canChildBeDismissed(v);
-    }
-
-    @Override
-    public boolean isAntiFalsingNeeded() {
-        return onKeyguard();
-    }
-
-    private boolean onKeyguard() {
-        return mStatusBarState == StatusBarState.KEYGUARD;
-    }
-
-    private void setSwipingInProgress(boolean isSwiped) {
-        mSwipingInProgress = isSwiped;
-        if(isSwiped) {
-            requestDisallowInterceptTouchEvent(true);
-        }
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        mStatusBarHeight = getResources().getDimensionPixelOffset(R.dimen.status_bar_height);
-        float densityScale = getResources().getDisplayMetrics().density;
-        mSwipeHelper.setDensityScale(densityScale);
-        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
-        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
-        initView(getContext());
-    }
-
-    public void dismissViewAnimated(View child, Runnable endRunnable, int delay, long duration) {
-        mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration,
-                true /* isDismissAll */);
-    }
-
-    @Override
-    public void snapViewIfNeeded(ExpandableNotificationRow child) {
-        boolean animate = mIsExpanded || isPinnedHeadsUp(child);
-        // If the child is showing the notification menu snap to that
-        float targetLeft = child.getProvider().isMenuVisible() ? child.getTranslation() : 0;
-        mSwipeHelper.snapChildIfNeeded(child, animate, targetLeft);
-    }
-
-    @Override
-    public ViewGroup getViewParentForNotification(NotificationData.Entry entry) {
-        return this;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        boolean isCancelOrUp = ev.getActionMasked() == MotionEvent.ACTION_CANCEL
-                || ev.getActionMasked()== MotionEvent.ACTION_UP;
-        handleEmptySpaceClick(ev);
-        boolean expandWantsIt = false;
-        if (mIsExpanded && !mSwipingInProgress && !mOnlyScrollingInThisMotion) {
-            if (isCancelOrUp) {
-                mExpandHelper.onlyObserveMovements(false);
-            }
-            boolean wasExpandingBefore = mExpandingNotification;
-            expandWantsIt = mExpandHelper.onTouchEvent(ev);
-            if (mExpandedInThisMotion && !mExpandingNotification && wasExpandingBefore
-                    && !mDisallowScrollingInThisMotion) {
-                dispatchDownEventToScroller(ev);
-            }
-        }
-        boolean scrollerWantsIt = false;
-        if (mIsExpanded && !mSwipingInProgress && !mExpandingNotification
-                && !mDisallowScrollingInThisMotion) {
-            scrollerWantsIt = onScrollTouch(ev);
-        }
-        boolean horizontalSwipeWantsIt = false;
-        if (!mIsBeingDragged
-                && !mExpandingNotification
-                && !mExpandedInThisMotion
-                && !mOnlyScrollingInThisMotion
-                && !mDisallowDismissInThisMotion) {
-            horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);
-        }
-
-        // Check if we need to clear any snooze leavebehinds
-        NotificationGuts guts = mStatusBar.getGutsManager().getExposedGuts();
-        if (guts != null && !isTouchInView(ev, guts)
-                && guts.getGutsContent() instanceof NotificationSnooze) {
-            NotificationSnooze ns = (NotificationSnooze) guts.getGutsContent();
-            if ((ns.isExpanded() && isCancelOrUp)
-                    || (!horizontalSwipeWantsIt && scrollerWantsIt)) {
-                // If the leavebehind is expanded we clear it on the next up event, otherwise we
-                // clear it on the next non-horizontal swipe or expand event.
-                checkSnoozeLeavebehind();
-            }
-        }
-        if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
-            mCheckForLeavebehind = true;
-        }
-        return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt || super.onTouchEvent(ev);
-    }
-
-    private void dispatchDownEventToScroller(MotionEvent ev) {
-        MotionEvent downEvent = MotionEvent.obtain(ev);
-        downEvent.setAction(MotionEvent.ACTION_DOWN);
-        onScrollTouch(downEvent);
-        downEvent.recycle();
-    }
-
-    @Override
-    public boolean onGenericMotionEvent(MotionEvent event) {
-        if (!isScrollingEnabled() || !mIsExpanded || mSwipingInProgress || mExpandingNotification
-                || mDisallowScrollingInThisMotion) {
-            return false;
-        }
-        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_SCROLL: {
-                    if (!mIsBeingDragged) {
-                        final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
-                        if (vscroll != 0) {
-                            final int delta = (int) (vscroll * getVerticalScrollFactor());
-                            final int range = getScrollRange();
-                            int oldScrollY = mOwnScrollY;
-                            int newScrollY = oldScrollY - delta;
-                            if (newScrollY < 0) {
-                                newScrollY = 0;
-                            } else if (newScrollY > range) {
-                                newScrollY = range;
-                            }
-                            if (newScrollY != oldScrollY) {
-                                setOwnScrollY(newScrollY);
-                                return true;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return super.onGenericMotionEvent(event);
-    }
-
-    private boolean onScrollTouch(MotionEvent ev) {
-        if (!isScrollingEnabled()) {
-            return false;
-        }
-        if (isInsideQsContainer(ev) && !mIsBeingDragged) {
-            return false;
-        }
-        mForcedScroll = null;
-        initVelocityTrackerIfNotExists();
-        mVelocityTracker.addMovement(ev);
-
-        final int action = ev.getAction();
-
-        switch (action & MotionEvent.ACTION_MASK) {
-            case MotionEvent.ACTION_DOWN: {
-                if (getChildCount() == 0 || !isInContentBounds(ev)) {
-                    return false;
-                }
-                boolean isBeingDragged = !mScroller.isFinished();
-                setIsBeingDragged(isBeingDragged);
-                /*
-                 * If being flinged and user touches, stop the fling. isFinished
-                 * will be false if being flinged.
-                 */
-                if (!mScroller.isFinished()) {
-                    mScroller.forceFinished(true);
-                }
-
-                // Remember where the motion event started
-                mLastMotionY = (int) ev.getY();
-                mDownX = (int) ev.getX();
-                mActivePointerId = ev.getPointerId(0);
-                break;
-            }
-            case MotionEvent.ACTION_MOVE:
-                final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
-                if (activePointerIndex == -1) {
-                    Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent");
-                    break;
-                }
-
-                final int y = (int) ev.getY(activePointerIndex);
-                final int x = (int) ev.getX(activePointerIndex);
-                int deltaY = mLastMotionY - y;
-                final int xDiff = Math.abs(x - mDownX);
-                final int yDiff = Math.abs(deltaY);
-                if (!mIsBeingDragged && yDiff > mTouchSlop && yDiff > xDiff) {
-                    setIsBeingDragged(true);
-                    if (deltaY > 0) {
-                        deltaY -= mTouchSlop;
-                    } else {
-                        deltaY += mTouchSlop;
-                    }
-                }
-                if (mIsBeingDragged) {
-                    // Scroll to follow the motion event
-                    mLastMotionY = y;
-                    int range = getScrollRange();
-                    if (mExpandedInThisMotion) {
-                        range = Math.min(range, mMaxScrollAfterExpand);
-                    }
-
-                    float scrollAmount;
-                    if (deltaY < 0) {
-                        scrollAmount = overScrollDown(deltaY);
-                    } else {
-                        scrollAmount = overScrollUp(deltaY, range);
-                    }
-
-                    // Calling customOverScrollBy will call onCustomOverScrolled, which
-                    // sets the scrolling if applicable.
-                    if (scrollAmount != 0.0f) {
-                        // The scrolling motion could not be compensated with the
-                        // existing overScroll, we have to scroll the view
-                        customOverScrollBy((int) scrollAmount, mOwnScrollY,
-                                range, getHeight() / 2);
-                        // If we're scrolling, leavebehinds should be dismissed
-                        checkSnoozeLeavebehind();
-                    }
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-                if (mIsBeingDragged) {
-                    final VelocityTracker velocityTracker = mVelocityTracker;
-                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-                    int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
-
-                    if (shouldOverScrollFling(initialVelocity)) {
-                        onOverScrollFling(true, initialVelocity);
-                    } else {
-                        if (getChildCount() > 0) {
-                            if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
-                                float currentOverScrollTop = getCurrentOverScrollAmount(true);
-                                if (currentOverScrollTop == 0.0f || initialVelocity > 0) {
-                                    fling(-initialVelocity);
-                                } else {
-                                    onOverScrollFling(false, initialVelocity);
-                                }
-                            } else {
-                                if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
-                                        getScrollRange())) {
-                                    animateScroll();
-                                }
-                            }
-                        }
-                    }
-                    mActivePointerId = INVALID_POINTER;
-                    endDrag();
-                }
-
-                break;
-            case MotionEvent.ACTION_CANCEL:
-                if (mIsBeingDragged && getChildCount() > 0) {
-                    if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
-                        animateScroll();
-                    }
-                    mActivePointerId = INVALID_POINTER;
-                    endDrag();
-                }
-                break;
-            case MotionEvent.ACTION_POINTER_DOWN: {
-                final int index = ev.getActionIndex();
-                mLastMotionY = (int) ev.getY(index);
-                mDownX = (int) ev.getX(index);
-                mActivePointerId = ev.getPointerId(index);
-                break;
-            }
-            case MotionEvent.ACTION_POINTER_UP:
-                onSecondaryPointerUp(ev);
-                mLastMotionY = (int) ev.getY(ev.findPointerIndex(mActivePointerId));
-                mDownX = (int) ev.getX(ev.findPointerIndex(mActivePointerId));
-                break;
-        }
-        return true;
-    }
-
-    protected boolean isInsideQsContainer(MotionEvent ev) {
-        return ev.getY() < mQsContainer.getBottom();
-    }
-
-    private void onOverScrollFling(boolean open, int initialVelocity) {
-        if (mOverscrollTopChangedListener != null) {
-            mOverscrollTopChangedListener.flingTopOverscroll(initialVelocity, open);
-        }
-        mDontReportNextOverScroll = true;
-        setOverScrollAmount(0.0f, true, false);
-    }
-
-    /**
-     * Perform a scroll upwards and adapt the overscroll amounts accordingly
-     *
-     * @param deltaY The amount to scroll upwards, has to be positive.
-     * @return The amount of scrolling to be performed by the scroller,
-     *         not handled by the overScroll amount.
-     */
-    private float overScrollUp(int deltaY, int range) {
-        deltaY = Math.max(deltaY, 0);
-        float currentTopAmount = getCurrentOverScrollAmount(true);
-        float newTopAmount = currentTopAmount - deltaY;
-        if (currentTopAmount > 0) {
-            setOverScrollAmount(newTopAmount, true /* onTop */,
-                    false /* animate */);
-        }
-        // Top overScroll might not grab all scrolling motion,
-        // we have to scroll as well.
-        float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f;
-        float newScrollY = mOwnScrollY + scrollAmount;
-        if (newScrollY > range) {
-            if (!mExpandedInThisMotion) {
-                float currentBottomPixels = getCurrentOverScrolledPixels(false);
-                // We overScroll on the top
-                setOverScrolledPixels(currentBottomPixels + newScrollY - range,
-                        false /* onTop */,
-                        false /* animate */);
-            }
-            setOwnScrollY(range);
-            scrollAmount = 0.0f;
-        }
-        return scrollAmount;
-    }
-
-    /**
-     * Perform a scroll downward and adapt the overscroll amounts accordingly
-     *
-     * @param deltaY The amount to scroll downwards, has to be negative.
-     * @return The amount of scrolling to be performed by the scroller,
-     *         not handled by the overScroll amount.
-     */
-    private float overScrollDown(int deltaY) {
-        deltaY = Math.min(deltaY, 0);
-        float currentBottomAmount = getCurrentOverScrollAmount(false);
-        float newBottomAmount = currentBottomAmount + deltaY;
-        if (currentBottomAmount > 0) {
-            setOverScrollAmount(newBottomAmount, false /* onTop */,
-                    false /* animate */);
-        }
-        // Bottom overScroll might not grab all scrolling motion,
-        // we have to scroll as well.
-        float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f;
-        float newScrollY = mOwnScrollY + scrollAmount;
-        if (newScrollY < 0) {
-            float currentTopPixels = getCurrentOverScrolledPixels(true);
-            // We overScroll on the top
-            setOverScrolledPixels(currentTopPixels - newScrollY,
-                    true /* onTop */,
-                    false /* animate */);
-            setOwnScrollY(0);
-            scrollAmount = 0.0f;
-        }
-        return scrollAmount;
-    }
-
-    private void onSecondaryPointerUp(MotionEvent ev) {
-        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
-                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
-        final int pointerId = ev.getPointerId(pointerIndex);
-        if (pointerId == mActivePointerId) {
-            // This was our active pointer going up. Choose a new
-            // active pointer and adjust accordingly.
-            // TODO: Make this decision more intelligent.
-            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
-            mLastMotionY = (int) ev.getY(newPointerIndex);
-            mActivePointerId = ev.getPointerId(newPointerIndex);
-            if (mVelocityTracker != null) {
-                mVelocityTracker.clear();
-            }
-        }
-    }
-
-    private void initVelocityTrackerIfNotExists() {
-        if (mVelocityTracker == null) {
-            mVelocityTracker = VelocityTracker.obtain();
-        }
-    }
-
-    private void recycleVelocityTracker() {
-        if (mVelocityTracker != null) {
-            mVelocityTracker.recycle();
-            mVelocityTracker = null;
-        }
-    }
-
-    private void initOrResetVelocityTracker() {
-        if (mVelocityTracker == null) {
-            mVelocityTracker = VelocityTracker.obtain();
-        } else {
-            mVelocityTracker.clear();
-        }
-    }
-
-    public void setFinishScrollingCallback(Runnable runnable) {
-        mFinishScrollingCallback = runnable;
-    }
-
-    private void animateScroll() {
-        if (mScroller.computeScrollOffset()) {
-            int oldY = mOwnScrollY;
-            int y = mScroller.getCurrY();
-
-            if (oldY != y) {
-                int range = getScrollRange();
-                if (y < 0 && oldY >= 0 || y > range && oldY <= range) {
-                    float currVelocity = mScroller.getCurrVelocity();
-                    if (currVelocity >= mMinimumVelocity) {
-                        mMaxOverScroll = Math.abs(currVelocity) / 1000 * mOverflingDistance;
-                    }
-                }
-
-                if (mDontClampNextScroll) {
-                    range = Math.max(range, oldY);
-                }
-                customOverScrollBy(y - oldY, oldY, range,
-                        (int) (mMaxOverScroll));
-            }
-
-            postOnAnimation(mAnimateScroll);
-        } else {
-            mDontClampNextScroll = false;
-            if (mFinishScrollingCallback != null) {
-                mFinishScrollingCallback.run();
-            }
-        }
-    }
-
-    private boolean customOverScrollBy(int deltaY, int scrollY, int scrollRangeY,
-            int maxOverScrollY) {
-
-        int newScrollY = scrollY + deltaY;
-        final int top = -maxOverScrollY;
-        final int bottom = maxOverScrollY + scrollRangeY;
-
-        boolean clampedY = false;
-        if (newScrollY > bottom) {
-            newScrollY = bottom;
-            clampedY = true;
-        } else if (newScrollY < top) {
-            newScrollY = top;
-            clampedY = true;
-        }
-
-        onCustomOverScrolled(newScrollY, clampedY);
-
-        return clampedY;
-    }
-
-    /**
-     * Set the amount of overScrolled pixels which will force the view to apply a rubber-banded
-     * overscroll effect based on numPixels. By default this will also cancel animations on the
-     * same overScroll edge.
-     *
-     * @param numPixels The amount of pixels to overScroll by. These will be scaled according to
-     *                  the rubber-banding logic.
-     * @param onTop Should the effect be applied on top of the scroller.
-     * @param animate Should an animation be performed.
-     */
-    public void setOverScrolledPixels(float numPixels, boolean onTop, boolean animate) {
-        setOverScrollAmount(numPixels * getRubberBandFactor(onTop), onTop, animate, true);
-    }
-
-    /**
-     * Set the effective overScroll amount which will be directly reflected in the layout.
-     * By default this will also cancel animations on the same overScroll edge.
-     *
-     * @param amount The amount to overScroll by.
-     * @param onTop Should the effect be applied on top of the scroller.
-     * @param animate Should an animation be performed.
-     */
-    public void setOverScrollAmount(float amount, boolean onTop, boolean animate) {
-        setOverScrollAmount(amount, onTop, animate, true);
-    }
-
-    /**
-     * Set the effective overScroll amount which will be directly reflected in the layout.
-     *
-     * @param amount The amount to overScroll by.
-     * @param onTop Should the effect be applied on top of the scroller.
-     * @param animate Should an animation be performed.
-     * @param cancelAnimators Should running animations be cancelled.
-     */
-    public void setOverScrollAmount(float amount, boolean onTop, boolean animate,
-            boolean cancelAnimators) {
-        setOverScrollAmount(amount, onTop, animate, cancelAnimators, isRubberbanded(onTop));
-    }
-
-    /**
-     * Set the effective overScroll amount which will be directly reflected in the layout.
-     *
-     * @param amount The amount to overScroll by.
-     * @param onTop Should the effect be applied on top of the scroller.
-     * @param animate Should an animation be performed.
-     * @param cancelAnimators Should running animations be cancelled.
-     * @param isRubberbanded The value which will be passed to
-     *                     {@link OnOverscrollTopChangedListener#onOverscrollTopChanged}
-     */
-    public void setOverScrollAmount(float amount, boolean onTop, boolean animate,
-            boolean cancelAnimators, boolean isRubberbanded) {
-        if (cancelAnimators) {
-            mStateAnimator.cancelOverScrollAnimators(onTop);
-        }
-        setOverScrollAmountInternal(amount, onTop, animate, isRubberbanded);
-    }
-
-    private void setOverScrollAmountInternal(float amount, boolean onTop, boolean animate,
-            boolean isRubberbanded) {
-        amount = Math.max(0, amount);
-        if (animate) {
-            mStateAnimator.animateOverScrollToAmount(amount, onTop, isRubberbanded);
-        } else {
-            setOverScrolledPixels(amount / getRubberBandFactor(onTop), onTop);
-            mAmbientState.setOverScrollAmount(amount, onTop);
-            if (onTop) {
-                notifyOverscrollTopListener(amount, isRubberbanded);
-            }
-            requestChildrenUpdate();
-        }
-    }
-
-    private void notifyOverscrollTopListener(float amount, boolean isRubberbanded) {
-        mExpandHelper.onlyObserveMovements(amount > 1.0f);
-        if (mDontReportNextOverScroll) {
-            mDontReportNextOverScroll = false;
-            return;
-        }
-        if (mOverscrollTopChangedListener != null) {
-            mOverscrollTopChangedListener.onOverscrollTopChanged(amount, isRubberbanded);
-        }
-    }
-
-    public void setOverscrollTopChangedListener(
-            OnOverscrollTopChangedListener overscrollTopChangedListener) {
-        mOverscrollTopChangedListener = overscrollTopChangedListener;
-    }
-
-    public float getCurrentOverScrollAmount(boolean top) {
-        return mAmbientState.getOverScrollAmount(top);
-    }
-
-    public float getCurrentOverScrolledPixels(boolean top) {
-        return top? mOverScrolledTopPixels : mOverScrolledBottomPixels;
-    }
-
-    private void setOverScrolledPixels(float amount, boolean onTop) {
-        if (onTop) {
-            mOverScrolledTopPixels = amount;
-        } else {
-            mOverScrolledBottomPixels = amount;
-        }
-    }
-
-    private void onCustomOverScrolled(int scrollY, boolean clampedY) {
-        // Treat animating scrolls differently; see #computeScroll() for why.
-        if (!mScroller.isFinished()) {
-            setOwnScrollY(scrollY);
-            if (clampedY) {
-                springBack();
-            } else {
-                float overScrollTop = getCurrentOverScrollAmount(true);
-                if (mOwnScrollY < 0) {
-                    notifyOverscrollTopListener(-mOwnScrollY, isRubberbanded(true));
-                } else {
-                    notifyOverscrollTopListener(overScrollTop, isRubberbanded(true));
-                }
-            }
-        } else {
-            setOwnScrollY(scrollY);
-        }
-    }
-
-    private void springBack() {
-        int scrollRange = getScrollRange();
-        boolean overScrolledTop = mOwnScrollY <= 0;
-        boolean overScrolledBottom = mOwnScrollY >= scrollRange;
-        if (overScrolledTop || overScrolledBottom) {
-            boolean onTop;
-            float newAmount;
-            if (overScrolledTop) {
-                onTop = true;
-                newAmount = -mOwnScrollY;
-                setOwnScrollY(0);
-                mDontReportNextOverScroll = true;
-            } else {
-                onTop = false;
-                newAmount = mOwnScrollY - scrollRange;
-                setOwnScrollY(scrollRange);
-            }
-            setOverScrollAmount(newAmount, onTop, false);
-            setOverScrollAmount(0.0f, onTop, true);
-            mScroller.forceFinished(true);
-        }
-    }
-
-    private int getScrollRange() {
-        int scrollRange = Math.max(0, mContentHeight - mMaxLayoutHeight);
-        int imeInset = getImeInset();
-        scrollRange += Math.min(imeInset, Math.max(0, mContentHeight - (getHeight() - imeInset)));
-        return scrollRange;
-    }
-
-    private int getImeInset() {
-        return Math.max(0, mBottomInset - (getRootView().getHeight() - getHeight()));
-    }
-
-    /**
-     * @return the first child which has visibility unequal to GONE
-     */
-    public ExpandableView getFirstChildNotGone() {
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE && child != mShelf) {
-                return (ExpandableView) child;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @return the child before the given view which has visibility unequal to GONE
-     */
-    public ExpandableView getViewBeforeView(ExpandableView view) {
-        ExpandableView previousView = null;
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child == view) {
-                return previousView;
-            }
-            if (child.getVisibility() != View.GONE) {
-                previousView = (ExpandableView) child;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @return The first child which has visibility unequal to GONE which is currently below the
-     *         given translationY or equal to it.
-     */
-    private View getFirstChildBelowTranlsationY(float translationY, boolean ignoreChildren) {
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child.getVisibility() == View.GONE) {
-                continue;
-            }
-            float rowTranslation = child.getTranslationY();
-            if (rowTranslation >= translationY) {
-                return child;
-            } else if (!ignoreChildren && child instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                if (row.isSummaryWithChildren() && row.areChildrenExpanded()) {
-                    List<ExpandableNotificationRow> notificationChildren =
-                            row.getNotificationChildren();
-                    for (int childIndex = 0; childIndex < notificationChildren.size();
-                            childIndex++) {
-                        ExpandableNotificationRow rowChild = notificationChildren.get(childIndex);
-                        if (rowChild.getTranslationY() + rowTranslation >= translationY) {
-                            return rowChild;
-                        }
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @return the last child which has visibility unequal to GONE
-     */
-    public View getLastChildNotGone() {
-        int childCount = getChildCount();
-        for (int i = childCount - 1; i >= 0; i--) {
-            View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE && child != mShelf) {
-                return child;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @return the number of children which have visibility unequal to GONE
-     */
-    public int getNotGoneChildCount() {
-        int childCount = getChildCount();
-        int count = 0;
-        for (int i = 0; i < childCount; i++) {
-            ExpandableView child = (ExpandableView) getChildAt(i);
-            if (child.getVisibility() != View.GONE && !child.willBeGone() && child != mShelf) {
-                count++;
-            }
-        }
-        return count;
-    }
-
-    private void updateContentHeight() {
-        int height = 0;
-        float previousPaddingRequest = mPaddingBetweenElements;
-        float previousPaddingAmount = 0.0f;
-        int numShownItems = 0;
-        boolean finish = false;
-        int maxDisplayedNotifications = mAmbientState.isFullyDark()
-                ? (hasPulsingNotifications() ? 1 : 0)
-                : mMaxDisplayedNotifications;
-
-        for (int i = 0; i < getChildCount(); i++) {
-            ExpandableView expandableView = (ExpandableView) getChildAt(i);
-            boolean footerViewOnLockScreen = expandableView == mFooterView && onKeyguard();
-            if (expandableView.getVisibility() != View.GONE
-                    && !expandableView.hasNoContentHeight() && !footerViewOnLockScreen) {
-                boolean limitReached = maxDisplayedNotifications != -1
-                        && numShownItems >= maxDisplayedNotifications;
-                boolean notificationOnAmbientThatIsNotPulsing = mAmbientState.isFullyDark()
-                        && hasPulsingNotifications()
-                        && expandableView instanceof ExpandableNotificationRow
-                        && !isPulsing(((ExpandableNotificationRow) expandableView).getEntry());
-                if (limitReached || notificationOnAmbientThatIsNotPulsing) {
-                    expandableView = mShelf;
-                    finish = true;
-                }
-                float increasedPaddingAmount = expandableView.getIncreasedPaddingAmount();
-                float padding;
-                if (increasedPaddingAmount >= 0.0f) {
-                    padding = (int) NotificationUtils.interpolate(
-                            previousPaddingRequest,
-                            mIncreasedPaddingBetweenElements,
-                            increasedPaddingAmount);
-                    previousPaddingRequest = (int) NotificationUtils.interpolate(
-                            mPaddingBetweenElements,
-                            mIncreasedPaddingBetweenElements,
-                            increasedPaddingAmount);
-                } else {
-                    int ownPadding = (int) NotificationUtils.interpolate(
-                            0,
-                            mPaddingBetweenElements,
-                            1.0f + increasedPaddingAmount);
-                    if (previousPaddingAmount > 0.0f) {
-                        padding = (int) NotificationUtils.interpolate(
-                                ownPadding,
-                                mIncreasedPaddingBetweenElements,
-                                previousPaddingAmount);
-                    } else {
-                        padding = ownPadding;
-                    }
-                    previousPaddingRequest = ownPadding;
-                }
-                if (height != 0) {
-                    height += padding;
-                }
-                previousPaddingAmount = increasedPaddingAmount;
-                height += expandableView.getIntrinsicHeight();
-                numShownItems++;
-                if (finish) {
-                    break;
-                }
-            }
-        }
-        mIntrinsicContentHeight = height;
-
-        // We don't want to use the toppadding since that might be interpolated and we want
-        // to take the final value of the animation.
-        int topPadding = mAmbientState.isFullyDark() ? mDarkTopPadding : mRegularTopPadding;
-        mContentHeight = height + topPadding + mBottomMargin;
-        updateScrollability();
-        clampScrollPosition();
-        mAmbientState.setLayoutMaxHeight(mContentHeight);
-    }
-
-    private boolean isPulsing(NotificationData.Entry entry) {
-        return mAmbientState.isPulsing(entry);
-    }
-
-    @Override
-    public boolean hasPulsingNotifications() {
-        return mPulsing;
-    }
-
-    private void updateScrollability() {
-        boolean scrollable = !mQsExpanded && getScrollRange() > 0;
-        if (scrollable != mScrollable) {
-            mScrollable = scrollable;
-            setFocusable(scrollable);
-            updateForwardAndBackwardScrollability();
-        }
-    }
-
-    private void updateForwardAndBackwardScrollability() {
-        boolean forwardScrollable = mScrollable && mOwnScrollY < getScrollRange();
-        boolean backwardsScrollable = mScrollable && mOwnScrollY > 0;
-        boolean changed = forwardScrollable != mForwardScrollable
-                || backwardsScrollable != mBackwardScrollable;
-        mForwardScrollable = forwardScrollable;
-        mBackwardScrollable = backwardsScrollable;
-        if (changed) {
-            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
-        }
-    }
-
-    private void updateBackground() {
-        // No need to update the background color if it's not being drawn.
-        if (!mShouldDrawNotificationBackground || mAmbientState.isFullyDark()) {
-            return;
-        }
-
-        updateBackgroundBounds();
-        if (!mCurrentBounds.equals(mBackgroundBounds)) {
-            boolean animate = mAnimateNextBackgroundTop || mAnimateNextBackgroundBottom
-                    || areBoundsAnimating();
-            if (!isExpanded()) {
-                abortBackgroundAnimators();
-                animate = false;
-            }
-            if (animate) {
-                startBackgroundAnimation();
-            } else {
-                mCurrentBounds.set(mBackgroundBounds);
-                applyCurrentBackgroundBounds();
-            }
-        } else {
-            abortBackgroundAnimators();
-        }
-        mAnimateNextBackgroundBottom = false;
-        mAnimateNextBackgroundTop = false;
-    }
-
-    private void abortBackgroundAnimators() {
-        if (mBottomAnimator != null) {
-            mBottomAnimator.cancel();
-        }
-        if (mTopAnimator != null) {
-            mTopAnimator.cancel();
-        }
-    }
-
-    private boolean areBoundsAnimating() {
-        return mBottomAnimator != null || mTopAnimator != null;
-    }
-
-    private void startBackgroundAnimation() {
-        // left and right are always instantly applied
-        mCurrentBounds.left = mBackgroundBounds.left;
-        mCurrentBounds.right = mBackgroundBounds.right;
-        startBottomAnimation();
-        startTopAnimation();
-    }
-
-    private void startTopAnimation() {
-        int previousEndValue = mEndAnimationRect.top;
-        int newEndValue = mBackgroundBounds.top;
-        ObjectAnimator previousAnimator = mTopAnimator;
-        if (previousAnimator != null && previousEndValue == newEndValue) {
-            return;
-        }
-        if (!mAnimateNextBackgroundTop) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                int previousStartValue = mStartAnimationRect.top;
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                values[0].setIntValues(previousStartValue, newEndValue);
-                mStartAnimationRect.top = previousStartValue;
-                mEndAnimationRect.top = newEndValue;
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                setBackgroundTop(newEndValue);
-                return;
-            }
-        }
-        if (previousAnimator != null) {
-            previousAnimator.cancel();
-        }
-        ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundTop",
-                mCurrentBounds.top, newEndValue);
-        Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN;
-        animator.setInterpolator(interpolator);
-        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mStartAnimationRect.top = -1;
-                mEndAnimationRect.top = -1;
-                mTopAnimator = null;
-            }
-        });
-        animator.start();
-        mStartAnimationRect.top = mCurrentBounds.top;
-        mEndAnimationRect.top = newEndValue;
-        mTopAnimator = animator;
-    }
-
-    private void startBottomAnimation() {
-        int previousStartValue = mStartAnimationRect.bottom;
-        int previousEndValue = mEndAnimationRect.bottom;
-        int newEndValue = mBackgroundBounds.bottom;
-        ObjectAnimator previousAnimator = mBottomAnimator;
-        if (previousAnimator != null && previousEndValue == newEndValue) {
-            return;
-        }
-        if (!mAnimateNextBackgroundBottom) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                values[0].setIntValues(previousStartValue, newEndValue);
-                mStartAnimationRect.bottom = previousStartValue;
-                mEndAnimationRect.bottom = newEndValue;
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                setBackgroundBottom(newEndValue);
-                return;
-            }
-        }
-        if (previousAnimator != null) {
-            previousAnimator.cancel();
-        }
-        ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundBottom",
-                mCurrentBounds.bottom, newEndValue);
-        Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN;
-        animator.setInterpolator(interpolator);
-        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mStartAnimationRect.bottom = -1;
-                mEndAnimationRect.bottom = -1;
-                mBottomAnimator = null;
-            }
-        });
-        animator.start();
-        mStartAnimationRect.bottom = mCurrentBounds.bottom;
-        mEndAnimationRect.bottom = newEndValue;
-        mBottomAnimator = animator;
-    }
-
-    private void setBackgroundTop(int top) {
-        mCurrentBounds.top = top;
-        applyCurrentBackgroundBounds();
-    }
-
-    public void setBackgroundBottom(int bottom) {
-        mCurrentBounds.bottom = bottom;
-        applyCurrentBackgroundBounds();
-    }
-
-    private void applyCurrentBackgroundBounds() {
-        // If the background of the notification is not being drawn, then there is no need to
-        // exclude an area in the scrim. Rather, the scrim's color should serve as the background.
-        if (!mShouldDrawNotificationBackground) {
-            return;
-        }
-
-        final boolean awake = mDarkAmount != 0 || mAmbientState.isDark();
-        mScrimController.setExcludedBackgroundArea(
-                mFadingOut || mParentNotFullyVisible || awake || mIsClipped ? null
-                        : mCurrentBounds);
-        invalidate();
-    }
-
-    /**
-     * Update the background bounds to the new desired bounds
-     */
-    private void updateBackgroundBounds() {
-        getLocationInWindow(mTempInt2);
-        mBackgroundBounds.left = mTempInt2[0] + mSidePaddings;
-        mBackgroundBounds.right = mTempInt2[0] + getWidth() - mSidePaddings;
-
-        if (!mIsExpanded) {
-            mBackgroundBounds.top = 0;
-            mBackgroundBounds.bottom = 0;
-            return;
-        }
-        ActivatableNotificationView firstView = mFirstVisibleBackgroundChild;
-        int top = 0;
-        if (firstView != null) {
-            // Round Y up to avoid seeing the background during animation
-            int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView));
-            if (mAnimateNextBackgroundTop
-                    || mTopAnimator == null && mCurrentBounds.top == finalTranslationY
-                    || mTopAnimator != null && mEndAnimationRect.top == finalTranslationY) {
-                // we're ending up at the same location as we are now, lets just skip the animation
-                top = finalTranslationY;
-            } else {
-                top = (int) Math.ceil(firstView.getTranslationY());
-            }
-        }
-        ActivatableNotificationView lastView =
-                mShelf.hasItemsInStableShelf() && mShelf.getVisibility() != GONE
-                        ? mShelf
-                        : mLastVisibleBackgroundChild;
-        int bottom;
-        if (lastView != null) {
-            int finalTranslationY;
-            if (lastView == mShelf) {
-                finalTranslationY = (int) mShelf.getTranslationY();
-            } else {
-                finalTranslationY = (int) ViewState.getFinalTranslationY(lastView);
-            }
-            int finalHeight = ExpandableViewState.getFinalActualHeight(lastView);
-            int finalBottom = finalTranslationY + finalHeight - lastView.getClipBottomAmount();
-            if (mAnimateNextBackgroundBottom
-                    || mBottomAnimator == null && mCurrentBounds.bottom == finalBottom
-                    || mBottomAnimator != null && mEndAnimationRect.bottom == finalBottom) {
-                // we're ending up at the same location as we are now, lets just skip the animation
-                bottom = finalBottom;
-            } else {
-                bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight()
-                        - lastView.getClipBottomAmount());
-            }
-        } else {
-            top = mTopPadding;
-            bottom = top;
-        }
-        if (mStatusBarState != StatusBarState.KEYGUARD) {
-            top = (int) Math.max(mTopPadding + mStackTranslation, top);
-        } else {
-            // otherwise the animation from the shade to the keyguard will jump as it's maxed
-            top = Math.max(0, top);
-        }
-        mBackgroundBounds.top = top;
-        mBackgroundBounds.bottom = Math.max(bottom, top);
-    }
-
-    private ActivatableNotificationView getFirstPinnedHeadsUp() {
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE
-                    && child instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                if (row.isPinned()) {
-                    return row;
-                }
-            }
-        }
-        return null;
-    }
-
-    private ActivatableNotificationView getLastChildWithBackground() {
-        int childCount = getChildCount();
-        for (int i = childCount - 1; i >= 0; i--) {
-            View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
-                    && child != mShelf) {
-                return (ActivatableNotificationView) child;
-            }
-        }
-        return null;
-    }
-
-    private ActivatableNotificationView getFirstChildWithBackground() {
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
-                    && child != mShelf) {
-                return (ActivatableNotificationView) child;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Fling the scroll view
-     *
-     * @param velocityY The initial velocity in the Y direction. Positive
-     *                  numbers mean that the finger/cursor is moving down the screen,
-     *                  which means we want to scroll towards the top.
-     */
-    protected void fling(int velocityY) {
-        if (getChildCount() > 0) {
-            int scrollRange = getScrollRange();
-
-            float topAmount = getCurrentOverScrollAmount(true);
-            float bottomAmount = getCurrentOverScrollAmount(false);
-            if (velocityY < 0 && topAmount > 0) {
-                setOwnScrollY(mOwnScrollY - (int) topAmount);
-                mDontReportNextOverScroll = true;
-                setOverScrollAmount(0, true, false);
-                mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor(true /* onTop */)
-                        * mOverflingDistance + topAmount;
-            } else if (velocityY > 0 && bottomAmount > 0) {
-                setOwnScrollY((int) (mOwnScrollY + bottomAmount));
-                setOverScrollAmount(0, false, false);
-                mMaxOverScroll = Math.abs(velocityY) / 1000f
-                        * getRubberBandFactor(false /* onTop */) * mOverflingDistance
-                        +  bottomAmount;
-            } else {
-                // it will be set once we reach the boundary
-                mMaxOverScroll = 0.0f;
-            }
-            int minScrollY = Math.max(0, scrollRange);
-            if (mExpandedInThisMotion) {
-                minScrollY = Math.min(minScrollY, mMaxScrollAfterExpand);
-            }
-            mScroller.fling(mScrollX, mOwnScrollY, 1, velocityY, 0, 0, 0, minScrollY, 0,
-                    mExpandedInThisMotion && mOwnScrollY >= 0 ? 0 : Integer.MAX_VALUE / 2);
-
-            animateScroll();
-        }
-    }
-
-    /**
-     * @return Whether a fling performed on the top overscroll edge lead to the expanded
-     * overScroll view (i.e QS).
-     */
-    private boolean shouldOverScrollFling(int initialVelocity) {
-        float topOverScroll = getCurrentOverScrollAmount(true);
-        return mScrolledToTopOnFirstDown
-                && !mExpandedInThisMotion
-                && topOverScroll > mMinTopOverScrollToEscape
-                && initialVelocity > 0;
-    }
-
-    /**
-     * Updates the top padding of the notifications, taking {@link #getIntrinsicPadding()} into
-     * account.
-     *
-     * @param qsHeight the top padding imposed by the quick settings panel
-     * @param animate whether to animate the change
-     * @param ignoreIntrinsicPadding if true, {@link #getIntrinsicPadding()} is ignored and
-     *                               {@code qsHeight} is the final top padding
-     */
-    public void updateTopPadding(float qsHeight, boolean animate,
-            boolean ignoreIntrinsicPadding) {
-        int topPadding = (int) qsHeight;
-        int minStackHeight = getLayoutMinHeight();
-        if (topPadding + minStackHeight > getHeight()) {
-            mTopPaddingOverflow = topPadding + minStackHeight - getHeight();
-        } else {
-            mTopPaddingOverflow = 0;
-        }
-        setTopPadding(ignoreIntrinsicPadding ? topPadding : clampPadding(topPadding),
-                animate);
-        setExpandedHeight(mExpandedHeight);
-    }
-
-    public void setMaxTopPadding(int maxTopPadding) {
-        mMaxTopPadding = maxTopPadding;
-    }
-
-    public int getLayoutMinHeight() {
-        if (isHeadsUpTransition()) {
-            return getTopHeadsUpPinnedHeight();
-        }
-        return mShelf.getVisibility() == GONE ? 0 : mShelf.getIntrinsicHeight();
-    }
-
-    public int getFirstChildIntrinsicHeight() {
-        final ExpandableView firstChild = getFirstChildNotGone();
-        int firstChildMinHeight = firstChild != null
-                ? firstChild.getIntrinsicHeight()
-                : mEmptyShadeView != null
-                        ? mEmptyShadeView.getIntrinsicHeight()
-                        : mCollapsedSize;
-        if (mOwnScrollY > 0) {
-            firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
-        }
-        return firstChildMinHeight;
-    }
-
-    public float getTopPaddingOverflow() {
-        return mTopPaddingOverflow;
-    }
-
-    public int getPeekHeight() {
-        final ExpandableView firstChild = getFirstChildNotGone();
-        final int firstChildMinHeight = firstChild != null ? firstChild.getCollapsedHeight()
-                : mCollapsedSize;
-        int shelfHeight = 0;
-        if (mLastVisibleBackgroundChild != null && mShelf.getVisibility() != GONE) {
-            shelfHeight = mShelf.getIntrinsicHeight();
-        }
-        return mIntrinsicPadding + firstChildMinHeight + shelfHeight;
-    }
-
-    private int clampPadding(int desiredPadding) {
-        return Math.max(desiredPadding, mIntrinsicPadding);
-    }
-
-    private float getRubberBandFactor(boolean onTop) {
-        if (!onTop) {
-            return RUBBER_BAND_FACTOR_NORMAL;
-        }
-        if (mExpandedInThisMotion) {
-            return RUBBER_BAND_FACTOR_AFTER_EXPAND;
-        } else if (mIsExpansionChanging || mPanelTracking) {
-            return RUBBER_BAND_FACTOR_ON_PANEL_EXPAND;
-        } else if (mScrolledToTopOnFirstDown) {
-            return 1.0f;
-        }
-        return RUBBER_BAND_FACTOR_NORMAL;
-    }
-
-    /**
-     * Accompanying function for {@link #getRubberBandFactor}: Returns true if the overscroll is
-     * rubberbanded, false if it is technically an overscroll but rather a motion to expand the
-     * overscroll view (e.g. expand QS).
-     */
-    private boolean isRubberbanded(boolean onTop) {
-        return !onTop || mExpandedInThisMotion || mIsExpansionChanging || mPanelTracking
-                || !mScrolledToTopOnFirstDown;
-    }
-
-    private void endDrag() {
-        setIsBeingDragged(false);
-
-        recycleVelocityTracker();
-
-        if (getCurrentOverScrollAmount(true /* onTop */) > 0) {
-            setOverScrollAmount(0, true /* onTop */, true /* animate */);
-        }
-        if (getCurrentOverScrollAmount(false /* onTop */) > 0) {
-            setOverScrollAmount(0, false /* onTop */, true /* animate */);
-        }
-    }
-
-    private void transformTouchEvent(MotionEvent ev, View sourceView, View targetView) {
-        ev.offsetLocation(sourceView.getX(), sourceView.getY());
-        ev.offsetLocation(-targetView.getX(), -targetView.getY());
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        initDownStates(ev);
-        handleEmptySpaceClick(ev);
-        boolean expandWantsIt = false;
-        if (!mSwipingInProgress && !mOnlyScrollingInThisMotion) {
-            expandWantsIt = mExpandHelper.onInterceptTouchEvent(ev);
-        }
-        boolean scrollWantsIt = false;
-        if (!mSwipingInProgress && !mExpandingNotification) {
-            scrollWantsIt = onInterceptTouchEventScroll(ev);
-        }
-        boolean swipeWantsIt = false;
-        if (!mIsBeingDragged
-                && !mExpandingNotification
-                && !mExpandedInThisMotion
-                && !mOnlyScrollingInThisMotion
-                && !mDisallowDismissInThisMotion) {
-            swipeWantsIt = mSwipeHelper.onInterceptTouchEvent(ev);
-        }
-        // Check if we need to clear any snooze leavebehinds
-        boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
-        NotificationGuts guts = mStatusBar.getGutsManager().getExposedGuts();
-        if (!isTouchInView(ev, guts) && isUp && !swipeWantsIt && !expandWantsIt
-                && !scrollWantsIt) {
-            mCheckForLeavebehind = false;
-            mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
-                    false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
-                    false /* resetMenu */);
-        }
-        if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
-            mCheckForLeavebehind = true;
-        }
-        return swipeWantsIt || scrollWantsIt || expandWantsIt || super.onInterceptTouchEvent(ev);
-    }
-
-    private void handleEmptySpaceClick(MotionEvent ev) {
-        switch (ev.getActionMasked()) {
-            case MotionEvent.ACTION_MOVE:
-                if (mTouchIsClick && (Math.abs(ev.getY() - mInitialTouchY) > mTouchSlop
-                        || Math.abs(ev.getX() - mInitialTouchX) > mTouchSlop )) {
-                    mTouchIsClick = false;
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-                if (mStatusBarState != StatusBarState.KEYGUARD && mTouchIsClick &&
-                        isBelowLastNotification(mInitialTouchX, mInitialTouchY)) {
-                    mOnEmptySpaceClickListener.onEmptySpaceClicked(mInitialTouchX, mInitialTouchY);
-                }
-                break;
-        }
-    }
-
-    private void initDownStates(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            mExpandedInThisMotion = false;
-            mOnlyScrollingInThisMotion = !mScroller.isFinished();
-            mDisallowScrollingInThisMotion = false;
-            mDisallowDismissInThisMotion = false;
-            mTouchIsClick = true;
-            mInitialTouchX = ev.getX();
-            mInitialTouchY = ev.getY();
-        }
-    }
-
-    public void setChildTransferInProgress(boolean childTransferInProgress) {
-        mChildTransferInProgress = childTransferInProgress;
-    }
-
-    @Override
-    public void onViewRemoved(View child) {
-        super.onViewRemoved(child);
-        // we only call our internal methods if this is actually a removal and not just a
-        // notification which becomes a child notification
-        if (!mChildTransferInProgress) {
-            onViewRemovedInternal(child, this);
-        }
-    }
-
-    @Override
-    public void cleanUpViewState(View child) {
-        if (child == mTranslatingParentView) {
-            mTranslatingParentView = null;
-        }
-        mCurrentStackScrollState.removeViewStateForView(child);
-    }
-
-    @Override
-    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
-        super.requestDisallowInterceptTouchEvent(disallowIntercept);
-        if (disallowIntercept) {
-            cancelLongPress();
-        }
-    }
-
-    private void onViewRemovedInternal(View child, ViewGroup container) {
-        if (mChangePositionInProgress) {
-            // This is only a position change, don't do anything special
-            return;
-        }
-        ExpandableView expandableView = (ExpandableView) child;
-        expandableView.setOnHeightChangedListener(null);
-        mCurrentStackScrollState.removeViewStateForView(child);
-        updateScrollStateForRemovedChild(expandableView);
-        boolean animationGenerated = generateRemoveAnimation(child);
-        if (animationGenerated) {
-            if (!mSwipedOutViews.contains(child)
-                    || Math.abs(expandableView.getTranslation()) != expandableView.getWidth()) {
-                container.addTransientView(child, 0);
-                expandableView.setTransientContainer(container);
-            }
-        } else {
-            mSwipedOutViews.remove(child);
-        }
-        updateAnimationState(false, child);
-
-        focusNextViewIfFocused(child);
-    }
-
-    private void focusNextViewIfFocused(View view) {
-        if (view instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-            if (row.shouldRefocusOnDismiss()) {
-                View nextView = row.getChildAfterViewWhenDismissed();
-                if (nextView == null) {
-                    View groupParentWhenDismissed = row.getGroupParentWhenDismissed();
-                    nextView = getFirstChildBelowTranlsationY(groupParentWhenDismissed != null
-                            ? groupParentWhenDismissed.getTranslationY()
-                            : view.getTranslationY(), true /* ignoreChildren */);
-                }
-                if (nextView != null) {
-                    nextView.requestAccessibilityFocus();
-                }
-            }
-        }
-
-    }
-
-    private boolean isChildInGroup(View child) {
-        return child instanceof ExpandableNotificationRow
-                && mGroupManager.isChildInGroupWithSummary(
-                        ((ExpandableNotificationRow) child).getStatusBarNotification());
-    }
-
-    /**
-     * Generate a remove animation for a child view.
-     *
-     * @param child The view to generate the remove animation for.
-     * @return Whether an animation was generated.
-     */
-    private boolean generateRemoveAnimation(View child) {
-        if (removeRemovedChildFromHeadsUpChangeAnimations(child)) {
-            mAddedHeadsUpChildren.remove(child);
-            return false;
-        }
-        if (isClickedHeadsUp(child)) {
-            // An animation is already running, add it transiently
-            mClearTransientViewsWhenFinished.add((ExpandableView) child);
-            return true;
-        }
-        if (mIsExpanded && mAnimationsEnabled && !isChildInInvisibleGroup(child)) {
-            if (!mChildrenToAddAnimated.contains(child)) {
-                // Generate Animations
-                mChildrenToRemoveAnimated.add(child);
-                mNeedsAnimation = true;
-                return true;
-            } else {
-                mChildrenToAddAnimated.remove(child);
-                mFromMoreCardAdditions.remove(child);
-                return false;
-            }
-        }
-        return false;
-    }
-
-    private boolean isClickedHeadsUp(View child) {
-        return HeadsUpUtil.isClickedHeadsUpNotification(child);
-    }
-
-    /**
-     * Remove a removed child view from the heads up animations if it was just added there
-     *
-     * @return whether any child was removed from the list to animate
-     */
-    private boolean removeRemovedChildFromHeadsUpChangeAnimations(View child) {
-        boolean hasAddEvent = false;
-        for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
-            ExpandableNotificationRow row = eventPair.first;
-            boolean isHeadsUp = eventPair.second;
-            if (child == row) {
-                mTmpList.add(eventPair);
-                hasAddEvent |= isHeadsUp;
-            }
-        }
-        if (hasAddEvent) {
-            // This child was just added lets remove all events.
-            mHeadsUpChangeAnimations.removeAll(mTmpList);
-            ((ExpandableNotificationRow ) child).setHeadsUpAnimatingAway(false);
-        }
-        mTmpList.clear();
-        return hasAddEvent;
-    }
-
-    /**
-     * @param child the child to query
-     * @return whether a view is not a top level child but a child notification and that group is
-     *         not expanded
-     */
-    private boolean isChildInInvisibleGroup(View child) {
-        if (child instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            ExpandableNotificationRow groupSummary =
-                    mGroupManager.getGroupSummary(row.getStatusBarNotification());
-            if (groupSummary != null && groupSummary != row) {
-                return row.getVisibility() == View.INVISIBLE;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Updates the scroll position when a child was removed
-     *
-     * @param removedChild the removed child
-     */
-    private void updateScrollStateForRemovedChild(ExpandableView removedChild) {
-        int startingPosition = getPositionInLinearLayout(removedChild);
-        float increasedPaddingAmount = removedChild.getIncreasedPaddingAmount();
-        int padding;
-        if (increasedPaddingAmount >= 0) {
-            padding = (int) NotificationUtils.interpolate(
-                    mPaddingBetweenElements,
-                    mIncreasedPaddingBetweenElements,
-                    increasedPaddingAmount);
-        } else {
-            padding = (int) NotificationUtils.interpolate(
-                    0,
-                    mPaddingBetweenElements,
-                    1.0f + increasedPaddingAmount);
-        }
-        int childHeight = getIntrinsicHeight(removedChild) + padding;
-        int endPosition = startingPosition + childHeight;
-        if (endPosition <= mOwnScrollY) {
-            // This child is fully scrolled of the top, so we have to deduct its height from the
-            // scrollPosition
-            setOwnScrollY(mOwnScrollY - childHeight);
-        } else if (startingPosition < mOwnScrollY) {
-            // This child is currently being scrolled into, set the scroll position to the start of
-            // this child
-            setOwnScrollY(startingPosition);
-        }
-    }
-
-    private int getIntrinsicHeight(View view) {
-        if (view instanceof ExpandableView) {
-            ExpandableView expandableView = (ExpandableView) view;
-            return expandableView.getIntrinsicHeight();
-        }
-        return view.getHeight();
-    }
-
-    public int getPositionInLinearLayout(View requestedView) {
-        ExpandableNotificationRow childInGroup = null;
-        ExpandableNotificationRow requestedRow = null;
-        if (isChildInGroup(requestedView)) {
-            // We're asking for a child in a group. Calculate the position of the parent first,
-            // then within the parent.
-            childInGroup = (ExpandableNotificationRow) requestedView;
-            requestedView = requestedRow = childInGroup.getNotificationParent();
-        }
-        int position = 0;
-        float previousPaddingRequest = mPaddingBetweenElements;
-        float previousPaddingAmount = 0.0f;
-        for (int i = 0; i < getChildCount(); i++) {
-            ExpandableView child = (ExpandableView) getChildAt(i);
-            boolean notGone = child.getVisibility() != View.GONE;
-            if (notGone && !child.hasNoContentHeight()) {
-                float increasedPaddingAmount = child.getIncreasedPaddingAmount();
-                float padding;
-                if (increasedPaddingAmount >= 0.0f) {
-                    padding = (int) NotificationUtils.interpolate(
-                            previousPaddingRequest,
-                            mIncreasedPaddingBetweenElements,
-                            increasedPaddingAmount);
-                    previousPaddingRequest = (int) NotificationUtils.interpolate(
-                            mPaddingBetweenElements,
-                            mIncreasedPaddingBetweenElements,
-                            increasedPaddingAmount);
-                } else {
-                    int ownPadding = (int) NotificationUtils.interpolate(
-                            0,
-                            mPaddingBetweenElements,
-                            1.0f + increasedPaddingAmount);
-                    if (previousPaddingAmount > 0.0f) {
-                        padding = (int) NotificationUtils.interpolate(
-                                ownPadding,
-                                mIncreasedPaddingBetweenElements,
-                                previousPaddingAmount);
-                    } else {
-                        padding = ownPadding;
-                    }
-                    previousPaddingRequest = ownPadding;
-                }
-                if (position != 0) {
-                    position += padding;
-                }
-                previousPaddingAmount = increasedPaddingAmount;
-            }
-            if (child == requestedView) {
-                if (requestedRow != null) {
-                    position += requestedRow.getPositionOfChild(childInGroup);
-                }
-                return position;
-            }
-            if (notGone) {
-                position += getIntrinsicHeight(child);
-            }
-        }
-        return 0;
-    }
-
-    @Override
-    public void onViewAdded(View child) {
-        super.onViewAdded(child);
-        onViewAddedInternal(child);
-    }
-
-    private void updateFirstAndLastBackgroundViews() {
-        ActivatableNotificationView firstChild = getFirstChildWithBackground();
-        ActivatableNotificationView lastChild = getLastChildWithBackground();
-        if (mAnimationsEnabled && mIsExpanded) {
-            mAnimateNextBackgroundTop = firstChild != mFirstVisibleBackgroundChild;
-            mAnimateNextBackgroundBottom = lastChild != mLastVisibleBackgroundChild;
-        } else {
-            mAnimateNextBackgroundTop = false;
-            mAnimateNextBackgroundBottom = false;
-        }
-        mFirstVisibleBackgroundChild = firstChild;
-        mLastVisibleBackgroundChild = lastChild;
-        mAmbientState.setLastVisibleBackgroundChild(lastChild);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirstVisibleBackgroundChild,
-                mLastVisibleBackgroundChild);
-        invalidate();
-    }
-
-    private void onViewAddedInternal(View child) {
-        updateHideSensitiveForChild(child);
-        ((ExpandableView) child).setOnHeightChangedListener(this);
-        generateAddAnimation(child, false /* fromMoreCard */);
-        updateAnimationState(child);
-        updateChronometerForChild(child);
-    }
-
-    private void updateHideSensitiveForChild(View child) {
-        if (child instanceof ExpandableView) {
-            ExpandableView expandableView = (ExpandableView) child;
-            expandableView.setHideSensitiveForIntrinsicHeight(mAmbientState.isHideSensitive());
-        }
-    }
-
-    @Override
-    public void notifyGroupChildRemoved(View row, ViewGroup childrenContainer) {
-        onViewRemovedInternal(row, childrenContainer);
-    }
-
-    @Override
-    public void notifyGroupChildAdded(View row) {
-        onViewAddedInternal(row);
-    }
-
-    public void setAnimationsEnabled(boolean animationsEnabled) {
-        mAnimationsEnabled = animationsEnabled;
-        updateNotificationAnimationStates();
-        if (!animationsEnabled) {
-            mSwipedOutViews.clear();
-            mChildrenToRemoveAnimated.clear();
-            clearTemporaryViewsInGroup(this);
-        }
-    }
-
-    private void updateNotificationAnimationStates() {
-        boolean running = mAnimationsEnabled || hasPulsingNotifications();
-        mShelf.setAnimationsEnabled(running);
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            running &= mIsExpanded || isPinnedHeadsUp(child);
-            updateAnimationState(running, child);
-        }
-    }
-
-    private void updateAnimationState(View child) {
-        updateAnimationState((mAnimationsEnabled || hasPulsingNotifications())
-                && (mIsExpanded || isPinnedHeadsUp(child)), child);
-    }
-
-    @Override
-    public void setExpandingNotification(ExpandableNotificationRow row) {
-        mAmbientState.setExpandingNotification(row);
-        requestChildrenUpdate();
-    }
-
-    @Override
-    public void bindRow(ExpandableNotificationRow row) {
-        row.setHeadsUpAnimatingAwayListener(animatingAway -> {
-            mRoundnessManager.onHeadsupAnimatingAwayChanged(row, animatingAway);
-            mHeadsUpAppearanceController.updateHeader(row.getEntry());
-        });
-    }
-
-    @Override
-    public void applyExpandAnimationParams(ExpandAnimationParameters params) {
-        mAmbientState.setExpandAnimationTopChange(params == null ? 0 : params.getTopChange());
-        requestChildrenUpdate();
-    }
-
-    private void updateAnimationState(boolean running, View child) {
-        if (child instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            row.setIconAnimationRunning(running);
-        }
-    }
-
-    public boolean isAddOrRemoveAnimationPending() {
-        return mNeedsAnimation
-                && (!mChildrenToAddAnimated.isEmpty() || !mChildrenToRemoveAnimated.isEmpty());
-    }
-
-    @Override
-    public void generateAddAnimation(View child, boolean fromMoreCard) {
-        if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress) {
-            // Generate Animations
-            mChildrenToAddAnimated.add(child);
-            if (fromMoreCard) {
-                mFromMoreCardAdditions.add(child);
-            }
-            mNeedsAnimation = true;
-        }
-        if (isHeadsUp(child) && mAnimationsEnabled && !mChangePositionInProgress) {
-            mAddedHeadsUpChildren.add(child);
-            mChildrenToAddAnimated.remove(child);
-        }
-    }
-
-    @Override
-    public void changeViewPosition(View child, int newIndex) {
-        int currentIndex = indexOfChild(child);
-
-        if (currentIndex == -1) {
-            boolean isTransient = false;
-            if (child instanceof ExpandableNotificationRow
-                    && ((ExpandableNotificationRow)child).getTransientContainer() != null) {
-                isTransient = true;
-            }
-            Log.e(TAG, "Attempting to re-position "
-                    + (isTransient ? "transient" : "")
-                    + " view {"
-                    + child
-                    + "}");
-            return;
-        }
-
-        if (child != null && child.getParent() == this && currentIndex != newIndex) {
-            mChangePositionInProgress = true;
-            ((ExpandableView)child).setChangingPosition(true);
-            removeView(child);
-            addView(child, newIndex);
-            ((ExpandableView)child).setChangingPosition(false);
-            mChangePositionInProgress = false;
-            if (mIsExpanded && mAnimationsEnabled && child.getVisibility() != View.GONE) {
-                mChildrenChangingPositions.add(child);
-                mNeedsAnimation = true;
-            }
-        }
-    }
-
-    private void startAnimationToState() {
-        if (mNeedsAnimation) {
-            generateAllAnimationEvents();
-            mNeedsAnimation = false;
-        }
-        if (!mAnimationEvents.isEmpty() || isCurrentlyAnimating()) {
-            setAnimationRunning(true);
-            mStateAnimator.startAnimationForEvents(mAnimationEvents, mCurrentStackScrollState,
-                    mGoToFullShadeDelay);
-            mAnimationEvents.clear();
-            updateBackground();
-            updateViewShadows();
-            updateClippingToTopRoundedCorner();
-        } else {
-            applyCurrentState();
-        }
-        mGoToFullShadeDelay = 0;
-    }
-
-    private void generateAllAnimationEvents() {
-        generateHeadsUpAnimationEvents();
-        generateChildRemovalEvents();
-        generateChildAdditionEvents();
-        generatePositionChangeEvents();
-        generateSnapBackEvents();
-        generateDragEvents();
-        generateTopPaddingEvent();
-        generateActivateEvent();
-        generateDimmedEvent();
-        generateHideSensitiveEvent();
-        generateDarkEvent();
-        generateGoToFullShadeEvent();
-        generateViewResizeEvent();
-        generateGroupExpansionEvent();
-        generateAnimateEverythingEvent();
-        generatePulsingAnimationEvent();
-    }
-
-    private void generateHeadsUpAnimationEvents() {
-        for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
-            ExpandableNotificationRow row = eventPair.first;
-            boolean isHeadsUp = eventPair.second;
-            int type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_OTHER;
-            boolean onBottom = false;
-            boolean pinnedAndClosed = row.isPinned() && !mIsExpanded;
-            if (!mIsExpanded && !isHeadsUp) {
-                type = row.wasJustClicked()
-                        ? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
-                        : AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
-                if (row.isChildInGroup()) {
-                    // We can otherwise get stuck in there if it was just isolated
-                    row.setHeadsUpAnimatingAway(false);
-                    continue;
-                }
-            } else {
-                ExpandableViewState viewState = mCurrentStackScrollState.getViewStateForView(row);
-                if (viewState == null) {
-                    // A view state was never generated for this view, so we don't need to animate
-                    // this. This may happen with notification children.
-                    continue;
-                }
-                if (isHeadsUp && (mAddedHeadsUpChildren.contains(row) || pinnedAndClosed)) {
-                    if (pinnedAndClosed || shouldHunAppearFromBottom(viewState)) {
-                        // Our custom add animation
-                        type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR;
-                    } else {
-                        // Normal add animation
-                        type = AnimationEvent.ANIMATION_TYPE_ADD;
-                    }
-                    onBottom = !pinnedAndClosed;
-                }
-            }
-            AnimationEvent event = new AnimationEvent(row, type);
-            event.headsUpFromBottom = onBottom;
-            mAnimationEvents.add(event);
-        }
-        mHeadsUpChangeAnimations.clear();
-        mAddedHeadsUpChildren.clear();
-    }
-
-    private boolean shouldHunAppearFromBottom(ExpandableViewState viewState) {
-        if (viewState.yTranslation + viewState.height < mAmbientState.getMaxHeadsUpTranslation()) {
-            return false;
-        }
-        return true;
-    }
-
-    private void generateGroupExpansionEvent() {
-        // Generate a group expansion/collapsing event if there is such a group at all
-        if (mExpandedGroupView != null) {
-            mAnimationEvents.add(new AnimationEvent(mExpandedGroupView,
-                    AnimationEvent.ANIMATION_TYPE_GROUP_EXPANSION_CHANGED));
-            mExpandedGroupView = null;
-        }
-    }
-
-    private void generateViewResizeEvent() {
-        if (mNeedViewResizeAnimation) {
-            mAnimationEvents.add(
-                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_VIEW_RESIZE));
-        }
-        mNeedViewResizeAnimation = false;
-    }
-
-    private void generateSnapBackEvents() {
-        for (View child : mSnappedBackChildren) {
-            mAnimationEvents.add(new AnimationEvent(child,
-                    AnimationEvent.ANIMATION_TYPE_SNAP_BACK));
-        }
-        mSnappedBackChildren.clear();
-    }
-
-    private void generateDragEvents() {
-        for (View child : mDragAnimPendingChildren) {
-            mAnimationEvents.add(new AnimationEvent(child,
-                    AnimationEvent.ANIMATION_TYPE_START_DRAG));
-        }
-        mDragAnimPendingChildren.clear();
-    }
-
-    private void generateChildRemovalEvents() {
-        for (View child : mChildrenToRemoveAnimated) {
-            boolean childWasSwipedOut = mSwipedOutViews.contains(child);
-
-            // we need to know the view after this one
-            float removedTranslation = child.getTranslationY();
-            boolean ignoreChildren = true;
-            if (child instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                if (row.isRemoved() && row.wasChildInGroupWhenRemoved()) {
-                    removedTranslation = row.getTranslationWhenRemoved();
-                    ignoreChildren = false;
-                }
-                childWasSwipedOut |= Math.abs(row.getTranslation()) == row.getWidth();
-            }
-            if (!childWasSwipedOut) {
-                Rect clipBounds = child.getClipBounds();
-                childWasSwipedOut = clipBounds != null && clipBounds.height() == 0;
-
-                if (childWasSwipedOut && child instanceof ExpandableView) {
-                    // Clean up any potential transient views if the child has already been swiped
-                    // out, as we won't be animating it further (due to its height already being
-                    // clipped to 0.
-                    ViewGroup transientContainer = ((ExpandableView) child).getTransientContainer();
-                    if (transientContainer != null) {
-                        transientContainer.removeTransientView(child);
-                    }
-                }
-            }
-            int animationType = childWasSwipedOut
-                    ? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
-                    : AnimationEvent.ANIMATION_TYPE_REMOVE;
-            AnimationEvent event = new AnimationEvent(child, animationType);
-            event.viewAfterChangingView = getFirstChildBelowTranlsationY(removedTranslation,
-                    ignoreChildren);
-            mAnimationEvents.add(event);
-            mSwipedOutViews.remove(child);
-        }
-        mChildrenToRemoveAnimated.clear();
-    }
-
-    private void generatePositionChangeEvents() {
-        for (View child : mChildrenChangingPositions) {
-            mAnimationEvents.add(new AnimationEvent(child,
-                    AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION));
-        }
-        mChildrenChangingPositions.clear();
-        if (mGenerateChildOrderChangedEvent) {
-            mAnimationEvents.add(new AnimationEvent(null,
-                    AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION));
-            mGenerateChildOrderChangedEvent = false;
-        }
-    }
-
-    private void generateChildAdditionEvents() {
-        for (View child : mChildrenToAddAnimated) {
-            if (mFromMoreCardAdditions.contains(child)) {
-                mAnimationEvents.add(new AnimationEvent(child,
-                        AnimationEvent.ANIMATION_TYPE_ADD,
-                        StackStateAnimator.ANIMATION_DURATION_STANDARD));
-            } else {
-                mAnimationEvents.add(new AnimationEvent(child,
-                        AnimationEvent.ANIMATION_TYPE_ADD));
-            }
-        }
-        mChildrenToAddAnimated.clear();
-        mFromMoreCardAdditions.clear();
-    }
-
-    private void generateTopPaddingEvent() {
-        if (mTopPaddingNeedsAnimation) {
-            AnimationEvent event;
-            if (mAmbientState.isDark()) {
-                event = new AnimationEvent(null /* view */,
-                        AnimationEvent.ANIMATION_TYPE_TOP_PADDING_CHANGED,
-                        KeyguardSliceView.DEFAULT_ANIM_DURATION);
-            } else {
-                event = new AnimationEvent(null /* view */,
-                        AnimationEvent.ANIMATION_TYPE_TOP_PADDING_CHANGED);
-            }
-            mAnimationEvents.add(event);
-        }
-        mTopPaddingNeedsAnimation = false;
-    }
-
-    private void generateActivateEvent() {
-        if (mActivateNeedsAnimation) {
-            mAnimationEvents.add(
-                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_ACTIVATED_CHILD));
-        }
-        mActivateNeedsAnimation = false;
-    }
-
-    private void generateAnimateEverythingEvent() {
-        if (mEverythingNeedsAnimation) {
-            mAnimationEvents.add(
-                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_EVERYTHING));
-        }
-        mEverythingNeedsAnimation = false;
-    }
-
-    private void generateDimmedEvent() {
-        if (mDimmedNeedsAnimation) {
-            mAnimationEvents.add(
-                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_DIMMED));
-        }
-        mDimmedNeedsAnimation = false;
-    }
-
-    private void generateHideSensitiveEvent() {
-        if (mHideSensitiveNeedsAnimation) {
-            mAnimationEvents.add(
-                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_HIDE_SENSITIVE));
-        }
-        mHideSensitiveNeedsAnimation = false;
-    }
-
-    private void generateDarkEvent() {
-        if (mDarkNeedsAnimation) {
-            AnimationEvent ev = new AnimationEvent(null,
-                    AnimationEvent.ANIMATION_TYPE_DARK,
-                    new AnimationFilter()
-                            .animateDark()
-                            .animateY(mShelf));
-            ev.darkAnimationOriginIndex = mDarkAnimationOriginIndex;
-            mAnimationEvents.add(ev);
-            startDarkAmountAnimation();
-        }
-        mDarkNeedsAnimation = false;
-    }
-
-    private void generateGoToFullShadeEvent() {
-        if (mGoToFullShadeNeedsAnimation) {
-            mAnimationEvents.add(
-                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_GO_TO_FULL_SHADE));
-        }
-        mGoToFullShadeNeedsAnimation = false;
-    }
-
-    private boolean onInterceptTouchEventScroll(MotionEvent ev) {
-        if (!isScrollingEnabled()) {
-            return false;
-        }
-        /*
-         * This method JUST determines whether we want to intercept the motion.
-         * If we return true, onMotionEvent will be called and we do the actual
-         * scrolling there.
-         */
-
-        /*
-        * Shortcut the most recurring case: the user is in the dragging
-        * state and is moving their finger.  We want to intercept this
-        * motion.
-        */
-        final int action = ev.getAction();
-        if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
-            return true;
-        }
-
-        switch (action & MotionEvent.ACTION_MASK) {
-            case MotionEvent.ACTION_MOVE: {
-                /*
-                 * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
-                 * whether the user has moved far enough from the original down touch.
-                 */
-
-                /*
-                * Locally do absolute value. mLastMotionY is set to the y value
-                * of the down event.
-                */
-                final int activePointerId = mActivePointerId;
-                if (activePointerId == INVALID_POINTER) {
-                    // If we don't have a valid id, the touch down wasn't on content.
-                    break;
-                }
-
-                final int pointerIndex = ev.findPointerIndex(activePointerId);
-                if (pointerIndex == -1) {
-                    Log.e(TAG, "Invalid pointerId=" + activePointerId
-                            + " in onInterceptTouchEvent");
-                    break;
-                }
-
-                final int y = (int) ev.getY(pointerIndex);
-                final int x = (int) ev.getX(pointerIndex);
-                final int yDiff = Math.abs(y - mLastMotionY);
-                final int xDiff = Math.abs(x - mDownX);
-                if (yDiff > mTouchSlop && yDiff > xDiff) {
-                    setIsBeingDragged(true);
-                    mLastMotionY = y;
-                    mDownX = x;
-                    initVelocityTrackerIfNotExists();
-                    mVelocityTracker.addMovement(ev);
-                }
-                break;
-            }
-
-            case MotionEvent.ACTION_DOWN: {
-                final int y = (int) ev.getY();
-                mScrolledToTopOnFirstDown = isScrolledToTop();
-                if (getChildAtPosition(ev.getX(), y, false /* requireMinHeight */) == null) {
-                    setIsBeingDragged(false);
-                    recycleVelocityTracker();
-                    break;
-                }
-
-                /*
-                 * Remember location of down touch.
-                 * ACTION_DOWN always refers to pointer index 0.
-                 */
-                mLastMotionY = y;
-                mDownX = (int) ev.getX();
-                mActivePointerId = ev.getPointerId(0);
-
-                initOrResetVelocityTracker();
-                mVelocityTracker.addMovement(ev);
-                /*
-                * If being flinged and user touches the screen, initiate drag;
-                * otherwise don't.  mScroller.isFinished should be false when
-                * being flinged.
-                */
-                boolean isBeingDragged = !mScroller.isFinished();
-                setIsBeingDragged(isBeingDragged);
-                break;
-            }
-
-            case MotionEvent.ACTION_CANCEL:
-            case MotionEvent.ACTION_UP:
-                /* Release the drag */
-                setIsBeingDragged(false);
-                mActivePointerId = INVALID_POINTER;
-                recycleVelocityTracker();
-                if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
-                    animateScroll();
-                }
-                break;
-            case MotionEvent.ACTION_POINTER_UP:
-                onSecondaryPointerUp(ev);
-                break;
-        }
-
-        /*
-        * The only time we want to intercept motion events is if we are in the
-        * drag mode.
-        */
-        return mIsBeingDragged;
-    }
-
-    protected StackScrollAlgorithm createStackScrollAlgorithm(Context context) {
-        return new StackScrollAlgorithm(context);
-    }
-
-    /**
-     * @return Whether the specified motion event is actually happening over the content.
-     */
-    private boolean isInContentBounds(MotionEvent event) {
-        return isInContentBounds(event.getY());
-    }
-
-    /**
-     * @return Whether a y coordinate is inside the content.
-     */
-    public boolean isInContentBounds(float y) {
-        return y < getHeight() - getEmptyBottomMargin();
-    }
-
-    private void setIsBeingDragged(boolean isDragged) {
-        mIsBeingDragged = isDragged;
-        if (isDragged) {
-            requestDisallowInterceptTouchEvent(true);
-            cancelLongPress();
-        }
-    }
-
-    @Override
-    public void onWindowFocusChanged(boolean hasWindowFocus) {
-        super.onWindowFocusChanged(hasWindowFocus);
-        if (!hasWindowFocus) {
-            cancelLongPress();
-        }
-    }
-
-    @Override
-    public void clearChildFocus(View child) {
-        super.clearChildFocus(child);
-        if (mForcedScroll == child) {
-            mForcedScroll = null;
-        }
-    }
-
-    public void requestDisallowLongPress() {
-        cancelLongPress();
-    }
-
-    public void requestDisallowDismiss() {
-        mDisallowDismissInThisMotion = true;
-    }
-
-    public void cancelLongPress() {
-        mSwipeHelper.cancelLongPress();
-    }
-
-    @Override
-    public boolean isScrolledToTop() {
-        return mOwnScrollY == 0;
-    }
-
-    @Override
-    public boolean isScrolledToBottom() {
-        return mOwnScrollY >= getScrollRange();
-    }
-
-    @Override
-    public View getHostView() {
-        return this;
-    }
-
-    public int getEmptyBottomMargin() {
-        return Math.max(mMaxLayoutHeight - mContentHeight, 0);
-    }
-
-    public void checkSnoozeLeavebehind() {
-        if (mCheckForLeavebehind) {
-            mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
-                    false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
-                    false /* resetMenu */);
-            mCheckForLeavebehind = false;
-        }
-    }
-
-    public void resetCheckSnoozeLeavebehind() {
-        mCheckForLeavebehind = true;
-    }
-
-    public void onExpansionStarted() {
-        mIsExpansionChanging = true;
-        mAmbientState.setExpansionChanging(true);
-        checkSnoozeLeavebehind();
-    }
-
-    public void onExpansionStopped() {
-        mIsExpansionChanging = false;
-        resetCheckSnoozeLeavebehind();
-        mAmbientState.setExpansionChanging(false);
-        if (!mIsExpanded) {
-            setOwnScrollY(0);
-            mStatusBar.resetUserExpandedStates();
-            clearTemporaryViews();
-            clearUserLockedViews();
-        }
-    }
-
-    private void clearUserLockedViews() {
-        for (int i = 0; i < getChildCount(); i++) {
-            ExpandableView child = (ExpandableView) getChildAt(i);
-            if (child instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                row.setUserLocked(false);
-            }
-        }
-    }
-
-    private void clearTemporaryViews() {
-        // lets make sure nothing is transient anymore
-        clearTemporaryViewsInGroup(this);
-        for (int i = 0; i < getChildCount(); i++) {
-            ExpandableView child = (ExpandableView) getChildAt(i);
-            if (child instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                clearTemporaryViewsInGroup(row.getChildrenContainer());
-            }
-        }
-    }
-
-    private void clearTemporaryViewsInGroup(ViewGroup viewGroup) {
-        while (viewGroup != null && viewGroup.getTransientViewCount() != 0) {
-            viewGroup.removeTransientView(viewGroup.getTransientView(0));
-        }
-    }
-
-    public void onPanelTrackingStarted() {
-        mPanelTracking = true;
-        mAmbientState.setPanelTracking(true);
-    }
-    public void onPanelTrackingStopped() {
-        mPanelTracking = false;
-        mAmbientState.setPanelTracking(false);
-    }
-
-    public void resetScrollPosition() {
-        mScroller.abortAnimation();
-        setOwnScrollY(0);
-    }
-
-    private void setIsExpanded(boolean isExpanded) {
-        boolean changed = isExpanded != mIsExpanded;
-        mIsExpanded = isExpanded;
-        mStackScrollAlgorithm.setIsExpanded(isExpanded);
-        if (changed) {
-            if (!mIsExpanded) {
-                mGroupManager.collapseAllGroups();
-                mExpandHelper.cancelImmediately();
-            }
-            updateNotificationAnimationStates();
-            updateChronometers();
-            requestChildrenUpdate();
-        }
-    }
-
-    private void updateChronometers() {
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            updateChronometerForChild(getChildAt(i));
-        }
-    }
-
-    private void updateChronometerForChild(View child) {
-        if (child instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            row.setChronometerRunning(mIsExpanded);
-        }
-    }
-
-    @Override
-    public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
-        updateContentHeight();
-        updateScrollPositionOnExpandInBottom(view);
-        clampScrollPosition();
-        notifyHeightChangeListener(view, needsAnimation);
-        ExpandableNotificationRow row = view instanceof ExpandableNotificationRow
-                ? (ExpandableNotificationRow) view
-                : null;
-        if (row != null && (row == mFirstVisibleBackgroundChild
-                || row.getNotificationParent() == mFirstVisibleBackgroundChild)) {
-            updateAlgorithmLayoutMinHeight();
-        }
-        if (needsAnimation) {
-            requestAnimationOnViewResize(row);
-        }
-        requestChildrenUpdate();
-    }
-
-    @Override
-    public void onReset(ExpandableView view) {
-        updateAnimationState(view);
-        updateChronometerForChild(view);
-    }
-
-    private void updateScrollPositionOnExpandInBottom(ExpandableView view) {
-        if (view instanceof ExpandableNotificationRow && !onKeyguard()) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-            if (row.isUserLocked() && row != getFirstChildNotGone()) {
-                if (row.isSummaryWithChildren()) {
-                    return;
-                }
-                // We are actually expanding this view
-                float endPosition = row.getTranslationY() + row.getActualHeight();
-                if (row.isChildInGroup()) {
-                    endPosition += row.getNotificationParent().getTranslationY();
-                }
-                int layoutEnd = mMaxLayoutHeight + (int) mStackTranslation;
-                if (row != mLastVisibleBackgroundChild && mShelf.getVisibility() != GONE) {
-                    layoutEnd -= mShelf.getIntrinsicHeight() + mPaddingBetweenElements;
-                }
-                if (endPosition > layoutEnd) {
-                    setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd));
-                    mDisallowScrollingInThisMotion = true;
-                }
-            }
-        }
-    }
-
-    public void setOnHeightChangedListener(
-            ExpandableView.OnHeightChangedListener mOnHeightChangedListener) {
-        this.mOnHeightChangedListener = mOnHeightChangedListener;
-    }
-
-    public void setOnEmptySpaceClickListener(OnEmptySpaceClickListener listener) {
-        mOnEmptySpaceClickListener = listener;
-    }
-
-    public void onChildAnimationFinished() {
-        setAnimationRunning(false);
-        requestChildrenUpdate();
-        runAnimationFinishedRunnables();
-        clearTransient();
-        clearHeadsUpDisappearRunning();
-    }
-
-    private void clearHeadsUpDisappearRunning() {
-        for (int i = 0; i < getChildCount(); i++) {
-            View view = getChildAt(i);
-            if (view instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-                row.setHeadsUpAnimatingAway(false);
-                if (row.isSummaryWithChildren()) {
-                    for (ExpandableNotificationRow child : row.getNotificationChildren()) {
-                        child.setHeadsUpAnimatingAway(false);
-                    }
-                }
-            }
-        }
-    }
-
-    private void clearTransient() {
-        for (ExpandableView view : mClearTransientViewsWhenFinished) {
-            StackStateAnimator.removeTransientView(view);
-        }
-        mClearTransientViewsWhenFinished.clear();
-    }
-
-    private void runAnimationFinishedRunnables() {
-        for (Runnable runnable : mAnimationFinishedRunnables) {
-            runnable.run();
-        }
-        mAnimationFinishedRunnables.clear();
-    }
-
-    /**
-     * See {@link AmbientState#setDimmed}.
-     */
-    public void setDimmed(boolean dimmed, boolean animate) {
-        dimmed &= onKeyguard();
-        mAmbientState.setDimmed(dimmed);
-        if (animate && mAnimationsEnabled) {
-            mDimmedNeedsAnimation = true;
-            mNeedsAnimation =  true;
-            animateDimmed(dimmed);
-        } else {
-            setDimAmount(dimmed ? 1.0f : 0.0f);
-        }
-        requestChildrenUpdate();
-    }
-
-    @VisibleForTesting
-    boolean isDimmed() {
-        return mAmbientState.isDimmed();
-    }
-
-    private void setDimAmount(float dimAmount) {
-        mDimAmount = dimAmount;
-        updateBackgroundDimming();
-    }
-
-    private void animateDimmed(boolean dimmed) {
-        if (mDimAnimator != null) {
-            mDimAnimator.cancel();
-        }
-        float target = dimmed ? 1.0f : 0.0f;
-        if (target == mDimAmount) {
-            return;
-        }
-        mDimAnimator = TimeAnimator.ofFloat(mDimAmount, target);
-        mDimAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_DIMMED_ACTIVATED);
-        mDimAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        mDimAnimator.addListener(mDimEndListener);
-        mDimAnimator.addUpdateListener(mDimUpdateListener);
-        mDimAnimator.start();
-    }
-
-    public void setHideSensitive(boolean hideSensitive, boolean animate) {
-        if (hideSensitive != mAmbientState.isHideSensitive()) {
-            int childCount = getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                ExpandableView v = (ExpandableView) getChildAt(i);
-                v.setHideSensitiveForIntrinsicHeight(hideSensitive);
-            }
-            mAmbientState.setHideSensitive(hideSensitive);
-            if (animate && mAnimationsEnabled) {
-                mHideSensitiveNeedsAnimation = true;
-                mNeedsAnimation =  true;
-            }
-            updateContentHeight();
-            requestChildrenUpdate();
-        }
-    }
-
-    /**
-     * See {@link AmbientState#setActivatedChild}.
-     */
-    public void setActivatedChild(ActivatableNotificationView activatedChild) {
-        mAmbientState.setActivatedChild(activatedChild);
-        if (mAnimationsEnabled) {
-            mActivateNeedsAnimation = true;
-            mNeedsAnimation =  true;
-        }
-        requestChildrenUpdate();
-    }
-
-    public ActivatableNotificationView getActivatedChild() {
-        return mAmbientState.getActivatedChild();
-    }
-
-    private void applyCurrentState() {
-        mCurrentStackScrollState.apply();
-        if (mListener != null) {
-            mListener.onChildLocationsChanged();
-        }
-        runAnimationFinishedRunnables();
-        setAnimationRunning(false);
-        updateBackground();
-        updateViewShadows();
-        updateClippingToTopRoundedCorner();
-    }
-
-    private void updateViewShadows() {
-        // we need to work around an issue where the shadow would not cast between siblings when
-        // their z difference is between 0 and 0.1
-
-        // Lefts first sort by Z difference
-        for (int i = 0; i < getChildCount(); i++) {
-            ExpandableView child = (ExpandableView) getChildAt(i);
-            if (child.getVisibility() != GONE) {
-                mTmpSortedChildren.add(child);
-            }
-        }
-        Collections.sort(mTmpSortedChildren, mViewPositionComparator);
-
-        // Now lets update the shadow for the views
-        ExpandableView previous = null;
-        for (int i = 0; i < mTmpSortedChildren.size(); i++) {
-            ExpandableView expandableView = mTmpSortedChildren.get(i);
-            float translationZ = expandableView.getTranslationZ();
-            float otherZ = previous == null ? translationZ : previous.getTranslationZ();
-            float diff = otherZ - translationZ;
-            if (diff <= 0.0f || diff >= FakeShadowView.SHADOW_SIBLING_TRESHOLD) {
-                // There is no fake shadow to be drawn
-                expandableView.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
-            } else {
-                float yLocation = previous.getTranslationY() + previous.getActualHeight() -
-                        expandableView.getTranslationY() - previous.getExtraBottomPadding();
-                expandableView.setFakeShadowIntensity(
-                        diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD,
-                        previous.getOutlineAlpha(), (int) yLocation,
-                        previous.getOutlineTranslation());
-            }
-            previous = expandableView;
-        }
-
-        mTmpSortedChildren.clear();
-    }
-
-    /**
-     * Update colors of "dismiss" and "empty shade" views.
-     *
-     * @param lightTheme True if light theme should be used.
-     */
-    public void updateDecorViews(boolean lightTheme) {
-        if (lightTheme == mUsingLightTheme) {
-            return;
-        }
-        mUsingLightTheme = lightTheme;
-        Context context = new ContextThemeWrapper(mContext,
-                lightTheme ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI);
-        final int textColor = Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColor);
-        mFooterView.setTextColor(textColor);
-        mEmptyShadeView.setTextColor(textColor);
-    }
-
-    public void goToFullShade(long delay) {
-        mGoToFullShadeNeedsAnimation = true;
-        mGoToFullShadeDelay = delay;
-        mNeedsAnimation = true;
-        requestChildrenUpdate();
-    }
-
-    public void cancelExpandHelper() {
-        mExpandHelper.cancel();
-    }
-
-    public void setIntrinsicPadding(int intrinsicPadding) {
-        mIntrinsicPadding = intrinsicPadding;
-        mAmbientState.setIntrinsicPadding(intrinsicPadding);
-    }
-
-    public int getIntrinsicPadding() {
-        return mIntrinsicPadding;
-    }
-
-    /**
-     * @return the y position of the first notification
-     */
-    public float getNotificationsTopY() {
-        return mTopPadding + getStackTranslation();
-    }
-
-    @Override
-    public boolean shouldDelayChildPressedState() {
-        return true;
-    }
-
-    /**
-     * See {@link AmbientState#setDark}.
-     */
-    public void setDark(boolean dark, boolean animate, @Nullable PointF touchWakeUpScreenLocation) {
-        if (mAmbientState.isDark() == dark) {
-            return;
-        }
-        mAmbientState.setDark(dark);
-        if (animate && mAnimationsEnabled) {
-            mDarkNeedsAnimation = true;
-            mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation);
-            mNeedsAnimation =  true;
-        } else {
-            if (mDarkAmountAnimator != null) {
-                mDarkAmountAnimator.cancel();
-            }
-            setDarkAmount(dark ? 1f : 0f);
-            updateBackground();
-        }
-        requestChildrenUpdate();
-        applyCurrentBackgroundBounds();
-        updateWillNotDraw();
-        notifyHeightChangeListener(mShelf);
-    }
-
-    private void updatePanelTranslation() {
-        setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mDarkAmount);
-    }
-
-    public void setVerticalPanelTranslation(float verticalPanelTranslation) {
-        mVerticalPanelTranslation = verticalPanelTranslation;
-        updatePanelTranslation();
-    }
-
-    /**
-     * Updates whether or not this Layout will perform its own custom drawing (i.e. whether or
-     * not {@link #onDraw(Canvas)} is called). This method should be called whenever the
-     * {@link #mAmbientState}'s dark mode is toggled.
-     */
-    private void updateWillNotDraw() {
-        boolean willDraw = mShouldDrawNotificationBackground || DEBUG;
-        setWillNotDraw(!willDraw);
-    }
-
-    private void setDarkAmount(float darkAmount) {
-        mDarkAmount = darkAmount;
-        boolean wasFullyDark = mAmbientState.isFullyDark();
-        mAmbientState.setDarkAmount(darkAmount);
-        boolean nowFullyDark = mAmbientState.isFullyDark();
-        if (nowFullyDark != wasFullyDark) {
-            updateContentHeight();
-            DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
-            if (nowFullyDark && dozeParameters.shouldControlScreenOff()) {
-                mShelf.fadeInTranslating();
-            }
-            if (mIconAreaController != null) {
-                mIconAreaController.setFullyDark(nowFullyDark);
-            }
-        }
-        updateAlgorithmHeightAndPadding();
-        updateBackgroundDimming();
-        updatePanelTranslation();
-        requestChildrenUpdate();
-    }
-
-    public float getDarkAmount() {
-        return mDarkAmount;
-    }
-
-    /**
-     * Cancel any previous dark animations - to avoid race conditions - and creates a new one.
-     * This function also sets {@code mBackgroundXFactor} based on the current {@code mDarkAmount}.
-     */
-    private void startDarkAmountAnimation() {
-        boolean dark = mAmbientState.isDark();
-        if (mDarkAmountAnimator != null) {
-            mDarkAmountAnimator.cancel();
-        }
-
-        long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
-        // Longer animation when sleeping with more than 1 notification
-        if (dark && getNotGoneChildCount() > 2) {
-            duration *= 1.2f;
-        }
-
-        mDarkAmountAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, mDarkAmount,
-                dark ? 1f : 0);
-        // We only swap the scaling factor if we're fully dark or fully awake to avoid
-        // interpolation issues when playing with the power button.
-        if (mDarkAmount == 0 || mDarkAmount == 1) {
-            mBackgroundXFactor = dark ? 2.5f : 1.5f;
-        }
-        mDarkAmountAnimator.setDuration(duration);
-        mDarkAmountAnimator.setInterpolator(Interpolators.LINEAR);
-        mDarkAmountAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mDarkAmountAnimator = null;
-            }
-        });
-        mDarkAmountAnimator.start();
-    }
-
-    private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
-        if (screenLocation == null || screenLocation.y < mTopPadding) {
-            return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
-        }
-        if (screenLocation.y > getBottomMostNotificationBottom()) {
-            return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_BELOW;
-        }
-        View child = getClosestChildAtRawPosition(screenLocation.x, screenLocation.y);
-        if (child != null) {
-            return getNotGoneIndex(child);
-        } else {
-            return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
-        }
-    }
-
-    private int getNotGoneIndex(View child) {
-        int count = getChildCount();
-        int notGoneIndex = 0;
-        for (int i = 0; i < count; i++) {
-            View v = getChildAt(i);
-            if (child == v) {
-                return notGoneIndex;
-            }
-            if (v.getVisibility() != View.GONE) {
-                notGoneIndex++;
-            }
-        }
-        return -1;
-    }
-
-    public void setFooterView(@NonNull FooterView footerView) {
-        int index = -1;
-        if (mFooterView != null) {
-            index = indexOfChild(mFooterView);
-            removeView(mFooterView);
-        }
-        mFooterView = footerView;
-        addView(mFooterView, index);
-    }
-
-    public void setEmptyShadeView(EmptyShadeView emptyShadeView) {
-        int index = -1;
-        if (mEmptyShadeView != null) {
-            index = indexOfChild(mEmptyShadeView);
-            removeView(mEmptyShadeView);
-        }
-        mEmptyShadeView = emptyShadeView;
-        addView(mEmptyShadeView, index);
-    }
-
-    public void updateEmptyShadeView(boolean visible) {
-        mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
-
-        int oldTextRes = mEmptyShadeView.getTextResource();
-        int newTextRes = mStatusBar.areNotificationsHidden()
-                ? R.string.dnd_suppressing_shade_text : R.string.empty_shade_text;
-        if (oldTextRes != newTextRes) {
-            mEmptyShadeView.setText(newTextRes);
-        }
-    }
-
-    public void updateFooterView(boolean visible, boolean showDismissView) {
-        if (mFooterView == null) {
-            return;
-        }
-        boolean animate = mIsExpanded && mAnimationsEnabled;
-        mFooterView.setVisible(visible, animate);
-        mFooterView.setSecondaryVisible(showDismissView, animate);
-    }
-
-    public void setDismissAllInProgress(boolean dismissAllInProgress) {
-        mDismissAllInProgress = dismissAllInProgress;
-        mAmbientState.setDismissAllInProgress(dismissAllInProgress);
-        handleDismissAllClipping();
-    }
-
-    private void handleDismissAllClipping() {
-        final int count = getChildCount();
-        boolean previousChildWillBeDismissed = false;
-        for (int i = 0; i < count; i++) {
-            ExpandableView child = (ExpandableView) getChildAt(i);
-            if (child.getVisibility() == GONE) {
-                continue;
-            }
-            if (mDismissAllInProgress && previousChildWillBeDismissed) {
-                child.setMinClipTopAmount(child.getClipTopAmount());
-            } else {
-                child.setMinClipTopAmount(0);
-            }
-            previousChildWillBeDismissed = canChildBeDismissed(child);
-        }
-    }
-
-    public boolean isFooterViewNotGone() {
-        return mFooterView != null
-                && mFooterView.getVisibility() != View.GONE
-                && !mFooterView.willBeGone();
-    }
-
-    public boolean isFooterViewContentVisible() {
-        return mFooterView != null && mFooterView.isContentVisible();
-    }
-
-    public int getFooterViewHeight() {
-        return mFooterView == null ? 0 : mFooterView.getHeight() + mPaddingBetweenElements;
-    }
-
-    public int getEmptyShadeViewHeight() {
-        return mEmptyShadeView.getHeight();
-    }
-
-    public float getBottomMostNotificationBottom() {
-        final int count = getChildCount();
-        float max = 0;
-        for (int childIdx = 0; childIdx < count; childIdx++) {
-            ExpandableView child = (ExpandableView) getChildAt(childIdx);
-            if (child.getVisibility() == GONE) {
-                continue;
-            }
-            float bottom = child.getTranslationY() + child.getActualHeight()
-                    - child.getClipBottomAmount();
-            if (bottom > max) {
-                max = bottom;
-            }
-        }
-        return max + getStackTranslation();
-    }
-
-    public void setStatusBar(StatusBar statusBar) {
-        this.mStatusBar = statusBar;
-    }
-
-    public void setGroupManager(NotificationGroupManager groupManager) {
-        this.mGroupManager = groupManager;
-    }
-
-    public void onGoToKeyguard() {
-        requestAnimateEverything();
-    }
-
-    private void requestAnimateEverything() {
-        if (mIsExpanded && mAnimationsEnabled) {
-            mEverythingNeedsAnimation = true;
-            mNeedsAnimation = true;
-            requestChildrenUpdate();
-        }
-    }
-
-    public boolean isBelowLastNotification(float touchX, float touchY) {
-        int childCount = getChildCount();
-        for (int i = childCount - 1; i >= 0; i--) {
-            ExpandableView child = (ExpandableView) getChildAt(i);
-            if (child.getVisibility() != View.GONE) {
-                float childTop = child.getY();
-                if (childTop > touchY) {
-                    // we are above a notification entirely let's abort
-                    return false;
-                }
-                boolean belowChild = touchY > childTop + child.getActualHeight()
-                        - child.getClipBottomAmount();
-                if (child == mFooterView) {
-                    if(!belowChild && !mFooterView.isOnEmptySpace(touchX - mFooterView.getX(),
-                                    touchY - childTop)) {
-                        // We clicked on the dismiss button
-                        return false;
-                    }
-                } else if (child == mEmptyShadeView) {
-                    // We arrived at the empty shade view, for which we accept all clicks
-                    return true;
-                } else if (!belowChild){
-                    // We are on a child
-                    return false;
-                }
-            }
-        }
-        return touchY > mTopPadding + mStackTranslation;
-    }
-
-    @Override
-    public void onGroupExpansionChanged(ExpandableNotificationRow changedRow, boolean expanded) {
-        boolean animated = !mGroupExpandedForMeasure && mAnimationsEnabled
-                && (mIsExpanded || changedRow.isPinned());
-        if (animated) {
-            mExpandedGroupView = changedRow;
-            mNeedsAnimation = true;
-        }
-        changedRow.setChildrenExpanded(expanded, animated);
-        if (!mGroupExpandedForMeasure) {
-            onHeightChanged(changedRow, false /* needsAnimation */);
-        }
-        runAfterAnimationFinished(new Runnable() {
-            @Override
-            public void run() {
-                changedRow.onFinishedExpansionChange();
-            }
-        });
-    }
-
-    @Override
-    public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
-        mStatusBar.requestNotificationUpdate();
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setScrollable(mScrollable);
-        event.setScrollX(mScrollX);
-        event.setScrollY(mOwnScrollY);
-        event.setMaxScrollX(mScrollX);
-        event.setMaxScrollY(getScrollRange());
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        if (mScrollable) {
-            info.setScrollable(true);
-            if (mBackwardScrollable) {
-                info.addAction(
-                        AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
-                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP);
-            }
-            if (mForwardScrollable) {
-                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
-                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_DOWN);
-            }
-        }
-        // Talkback only listenes to scroll events of certain classes, let's make us a scrollview
-        info.setClassName(ScrollView.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
-        if (super.performAccessibilityActionInternal(action, arguments)) {
-            return true;
-        }
-        if (!isEnabled()) {
-            return false;
-        }
-        int direction = -1;
-        switch (action) {
-            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
-                // fall through
-            case android.R.id.accessibilityActionScrollDown:
-                direction = 1;
-                // fall through
-            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
-                // fall through
-            case android.R.id.accessibilityActionScrollUp:
-                final int viewportHeight = getHeight() - mPaddingBottom - mTopPadding - mPaddingTop
-                        - mShelf.getIntrinsicHeight();
-                final int targetScrollY = Math.max(0,
-                        Math.min(mOwnScrollY + direction * viewportHeight, getScrollRange()));
-                if (targetScrollY != mOwnScrollY) {
-                    mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScrollY - mOwnScrollY);
-                    animateScroll();
-                    return true;
-                }
-                break;
-        }
-        return false;
-    }
-
-    @Override
-    public void onGroupsChanged() {
-        mStatusBar.requestNotificationUpdate();
-    }
-
-    public void generateChildOrderChangedEvent() {
-        if (mIsExpanded && mAnimationsEnabled) {
-            mGenerateChildOrderChangedEvent = true;
-            mNeedsAnimation = true;
-            requestChildrenUpdate();
-        }
-    }
-
-    @Override
-    public int getContainerChildCount() {
-        return getChildCount();
-    }
-
-    @Override
-    public View getContainerChildAt(int i) {
-        return getChildAt(i);
-    }
-
-    @Override
-    public void removeContainerView(View v) {
-        removeView(v);
-    }
-
-    @Override
-    public void addContainerView(View v) {
-        addView(v);
-    }
-
-    public void runAfterAnimationFinished(Runnable runnable) {
-        mAnimationFinishedRunnables.add(runnable);
-    }
-
-    public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
-        mHeadsUpManager = headsUpManager;
-        mAmbientState.setHeadsUpManager(headsUpManager);
-        mHeadsUpManager.addListener(mRoundnessManager);
-    }
-
-    public void generateHeadsUpAnimation(ExpandableNotificationRow row, boolean isHeadsUp) {
-        if (mAnimationsEnabled && (isHeadsUp || mHeadsUpGoingAwayAnimationsAllowed)) {
-            mHeadsUpChangeAnimations.add(new Pair<>(row, isHeadsUp));
-            mNeedsAnimation = true;
-            if (!mIsExpanded && !isHeadsUp) {
-                row.setHeadsUpAnimatingAway(true);
-            }
-            requestChildrenUpdate();
-        }
-    }
-
-    public void setShadeExpanded(boolean shadeExpanded) {
-        mAmbientState.setShadeExpanded(shadeExpanded);
-        mStateAnimator.setShadeExpanded(shadeExpanded);
-    }
-
-    /**
-     * Set the boundary for the bottom heads up position. The heads up will always be above this
-     * position.
-     *
-     * @param height the height of the screen
-     * @param bottomBarHeight the height of the bar on the bottom
-     */
-    public void setHeadsUpBoundaries(int height, int bottomBarHeight) {
-        mAmbientState.setMaxHeadsUpTranslation(height - bottomBarHeight);
-        mStateAnimator.setHeadsUpAppearHeightBottom(height);
-        requestChildrenUpdate();
-    }
-
-    public void setTrackingHeadsUp(ExpandableNotificationRow row) {
-        mTrackingHeadsUp = row != null;
-        mRoundnessManager.setTrackingHeadsUp(row);
-    }
-
-    public void setScrimController(ScrimController scrimController) {
-        mScrimController = scrimController;
-        mScrimController.setScrimBehindChangeRunnable(this::updateBackgroundDimming);
-    }
-
-    public void forceNoOverlappingRendering(boolean force) {
-        mForceNoOverlappingRendering = force;
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return !mForceNoOverlappingRendering && super.hasOverlappingRendering();
-    }
-
-    public void setAnimationRunning(boolean animationRunning) {
-        if (animationRunning != mAnimationRunning) {
-            if (animationRunning) {
-                getViewTreeObserver().addOnPreDrawListener(mRunningAnimationUpdater);
-            } else {
-                getViewTreeObserver().removeOnPreDrawListener(mRunningAnimationUpdater);
-            }
-            mAnimationRunning = animationRunning;
-            updateContinuousShadowDrawing();
-        }
-    }
-
-    public boolean isExpanded() {
-        return mIsExpanded;
-    }
-
-    public void setPulsing(boolean pulsing, boolean animated) {
-        if (!mPulsing && !pulsing) {
-            return;
-        }
-        mPulsing = pulsing;
-        mNeedingPulseAnimation = animated ? getFirstChildNotGone() : null;
-        mAmbientState.setPulsing(pulsing);
-        updateNotificationAnimationStates();
-        updateAlgorithmHeightAndPadding();
-        updateContentHeight();
-        requestChildrenUpdate();
-        notifyHeightChangeListener(null, animated);
-        mNeedsAnimation |= animated;
-    }
-
-    private void generatePulsingAnimationEvent() {
-        if (mNeedingPulseAnimation != null) {
-            int type = mPulsing ? AnimationEvent.ANIMATION_TYPE_PULSE_APPEAR
-                    : AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR;
-            mAnimationEvents.add(new AnimationEvent(mNeedingPulseAnimation, type));
-            mNeedingPulseAnimation = null;
-        }
-    }
-
-    public void setFadingOut(boolean fadingOut) {
-        if (fadingOut != mFadingOut) {
-            mFadingOut = fadingOut;
-            updateFadingState();
-        }
-    }
-
-    public void setParentNotFullyVisible(boolean parentNotFullyVisible) {
-        if (mScrimController == null) {
-            // we're not set up yet.
-            return;
-        }
-        if (parentNotFullyVisible != mParentNotFullyVisible) {
-            mParentNotFullyVisible = parentNotFullyVisible;
-            updateFadingState();
-        }
-    }
-
-    private void updateFadingState() {
-        applyCurrentBackgroundBounds();
-        updateSrcDrawing();
-    }
-
-    @Override
-    public void setAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha) {
-        super.setAlpha(alpha);
-        setFadingOut(alpha != 1.0f);
-    }
-
-    public void setQsExpanded(boolean qsExpanded) {
-        mQsExpanded = qsExpanded;
-        updateAlgorithmLayoutMinHeight();
-        updateScrollability();
-    }
-
-    public void setQsExpansionFraction(float qsExpansionFraction) {
-        mQsExpansionFraction = qsExpansionFraction;
-    }
-
-    public void setOwnScrollY(int ownScrollY) {
-        if (ownScrollY != mOwnScrollY) {
-            // We still want to call the normal scrolled changed for accessibility reasons
-            onScrollChanged(mScrollX, ownScrollY, mScrollX, mOwnScrollY);
-            mOwnScrollY = ownScrollY;
-            updateForwardAndBackwardScrollability();
-            requestChildrenUpdate();
-        }
-    }
-
-    public void setShelf(NotificationShelf shelf) {
-        int index = -1;
-        if (mShelf != null) {
-            index = indexOfChild(mShelf);
-            removeView(mShelf);
-        }
-        mShelf = shelf;
-        addView(mShelf, index);
-        mAmbientState.setShelf(shelf);
-        mStateAnimator.setShelf(shelf);
-        shelf.bind(mAmbientState, this);
-    }
-
-    public NotificationShelf getNotificationShelf() {
-        return mShelf;
-    }
-
-    public void setMaxDisplayedNotifications(int maxDisplayedNotifications) {
-        if (mMaxDisplayedNotifications != maxDisplayedNotifications) {
-            mMaxDisplayedNotifications = maxDisplayedNotifications;
-            updateContentHeight();
-            notifyHeightChangeListener(mShelf);
-        }
-    }
-
-    public void setShouldShowShelfOnly(boolean shouldShowShelfOnly) {
-        mShouldShowShelfOnly =  shouldShowShelfOnly;
-        updateAlgorithmLayoutMinHeight();
-    }
-
-    public int getMinExpansionHeight() {
-        return mShelf.getIntrinsicHeight() - (mShelf.getIntrinsicHeight() - mStatusBarHeight) / 2;
-    }
-
-    public void setInHeadsUpPinnedMode(boolean inHeadsUpPinnedMode) {
-        mInHeadsUpPinnedMode = inHeadsUpPinnedMode;
-        updateClipping();
-    }
-
-    public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
-        mHeadsUpAnimatingAway = headsUpAnimatingAway;
-        updateClipping();
-    }
-
-    public void setStatusBarState(int statusBarState) {
-        mStatusBarState = statusBarState;
-        mAmbientState.setStatusBarState(statusBarState);
-    }
-
-    public void setExpandingVelocity(float expandingVelocity) {
-        mAmbientState.setExpandingVelocity(expandingVelocity);
-    }
-
-    public float getOpeningHeight() {
-        if (mEmptyShadeView.getVisibility() == GONE) {
-            return getMinExpansionHeight();
-        } else {
-            return getAppearEndPosition();
-        }
-    }
-
-    public void setIsFullWidth(boolean isFullWidth) {
-        mAmbientState.setPanelFullWidth(isFullWidth);
-    }
-
-    public void setUnlockHintRunning(boolean running) {
-        mAmbientState.setUnlockHintRunning(running);
-    }
-
-    public void setQsCustomizerShowing(boolean isShowing) {
-        mAmbientState.setQsCustomizerShowing(isShowing);
-        requestChildrenUpdate();
-    }
-
-    public void setHeadsUpGoingAwayAnimationsAllowed(boolean headsUpGoingAwayAnimationsAllowed) {
-        mHeadsUpGoingAwayAnimationsAllowed = headsUpGoingAwayAnimationsAllowed;
-    }
-
-    public void setAntiBurnInOffsetX(int antiBurnInOffsetX) {
-        mAntiBurnInOffsetX = antiBurnInOffsetX;
-        updatePanelTranslation();
-    }
-
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println(String.format("[%s: pulsing=%s qsCustomizerShowing=%s visibility=%s"
-                        + " alpha:%f scrollY:%d maxTopPadding:%d showShelfOnly=%s"
-                        + " qsExpandFraction=%f]",
-                this.getClass().getSimpleName(),
-                mPulsing ? "T":"f",
-                mAmbientState.isQsCustomizerShowing() ? "T":"f",
-                getVisibility() == View.VISIBLE ? "visible"
-                        : getVisibility() == View.GONE ? "gone"
-                                : "invisible",
-                getAlpha(),
-                mAmbientState.getScrollY(),
-                mMaxTopPadding,
-                mShouldShowShelfOnly ? "T":"f",
-                mQsExpansionFraction));
-    }
-
-    public boolean isFullyDark() {
-        return mAmbientState.isFullyDark();
-    }
-
-    /**
-     * Add a listener whenever the expanded height changes. The first value passed as an argument
-     * is the expanded height and the second one is the appearFraction.
-     *
-     * @param listener the listener to notify.
-     */
-    public void addOnExpandedHeightListener(BiConsumer<Float, Float> listener) {
-        mExpandedHeightListeners.add(listener);
-    }
-
-    /**
-     * Stop a listener from listening to the expandedHeight.
-     */
-    public void removeOnExpandedHeightListener(BiConsumer<Float, Float> listener) {
-        mExpandedHeightListeners.remove(listener);
-    }
-
-    public void setHeadsUpAppearanceController(
-            HeadsUpAppearanceController headsUpAppearanceController) {
-        mHeadsUpAppearanceController = headsUpAppearanceController;
-    }
-
-    public void setIconAreaController(NotificationIconAreaController controller) {
-        mIconAreaController = controller;
-    }
-
-    /**
-     * A listener that is notified when the empty space below the notifications is clicked on
-     */
-    public interface OnEmptySpaceClickListener {
-        void onEmptySpaceClicked(float x, float y);
-    }
-
-    /**
-     * A listener that gets notified when the overscroll at the top has changed.
-     */
-    public interface OnOverscrollTopChangedListener {
-
-        /**
-         * Notifies a listener that the overscroll has changed.
-         *
-         * @param amount the amount of overscroll, in pixels
-         * @param isRubberbanded if true, this is a rubberbanded overscroll; if false, this is an
-         *                     unrubberbanded motion to directly expand overscroll view (e.g expand
-         *                     QS)
-         */
-        void onOverscrollTopChanged(float amount, boolean isRubberbanded);
-
-        /**
-         * Notify a listener that the scroller wants to escape from the scrolling motion and
-         * start a fling animation to the expanded or collapsed overscroll view (e.g expand the QS)
-         *
-         * @param velocity The velocity that the Scroller had when over flinging
-         * @param open Should the fling open or close the overscroll view.
-         */
-        void flingTopOverscroll(float velocity, boolean open);
-    }
-
-    private class NotificationSwipeHelper extends SwipeHelper
-            implements NotificationSwipeActionHelper {
-        private static final long COVER_MENU_DELAY = 4000;
-        private Runnable mFalsingCheck;
-        private Handler mHandler;
-
-        public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) {
-            super(swipeDirection, callback, context);
-            mHandler = new Handler();
-            mFalsingCheck = new Runnable() {
-                @Override
-                public void run() {
-                    resetExposedMenuView(true /* animate */, true /* force */);
-                }
-            };
-        }
-
-        @Override
-        public void onDownUpdate(View currView, MotionEvent ev) {
-            mTranslatingParentView = currView;
-            if (mCurrMenuRow != null) {
-                mCurrMenuRow.onTouchEvent(currView, ev, 0 /* velocity */);
-            }
-            mCurrMenuRow = null;
-            mHandler.removeCallbacks(mFalsingCheck);
-
-            // Slide back any notifications that might be showing a menu
-            resetExposedMenuView(true /* animate */, false /* force */);
-
-            if (currView instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) currView;
-
-                if (row.getEntry().hasFinishedInitialization()) {
-                    mCurrMenuRow = row.createMenu();
-                    mCurrMenuRow.setSwipeActionHelper(NotificationSwipeHelper.this);
-                    mCurrMenuRow.setMenuClickListener(NotificationStackScrollLayout.this);
-                    mCurrMenuRow.onTouchEvent(currView, ev, 0 /* velocity */);
-                }
-            }
-        }
-
-        @Override
-        public void onMoveUpdate(View view, MotionEvent ev, float translation, float delta) {
-            mHandler.removeCallbacks(mFalsingCheck);
-            if (mCurrMenuRow != null) {
-                mCurrMenuRow.onTouchEvent(view, ev, 0 /* velocity */);
-            }
-        }
-
-        @Override
-        public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
-                float translation) {
-            if (mCurrMenuRow != null) {
-                return mCurrMenuRow.onTouchEvent(animView, ev, velocity);
-            }
-            return false;
-        }
-
-        @Override
-        public void dismissChild(final View view, float velocity,
-                boolean useAccelerateInterpolator) {
-            super.dismissChild(view, velocity, useAccelerateInterpolator);
-            if (mIsExpanded) {
-                // We don't want to quick-dismiss when it's a heads up as this might lead to closing
-                // of the panel early.
-                handleChildViewDismissed(view);
-            }
-            mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
-                    false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
-                    false /* resetMenu */);
-            handleMenuCoveredOrDismissed();
-        }
-
-        @Override
-        public void snapChild(final View animView, final float targetLeft, float velocity) {
-            super.snapChild(animView, targetLeft, velocity);
-            onDragCancelled(animView);
-            if (targetLeft == 0) {
-                handleMenuCoveredOrDismissed();
-            }
-        }
-
-        @Override
-        public void snooze(StatusBarNotification sbn, SnoozeOption snoozeOption) {
-            mStatusBar.setNotificationSnoozed(sbn, snoozeOption);
-        }
-
-        public boolean isFalseGesture(MotionEvent ev) {
-            return super.isFalseGesture(ev);
-        }
-
-        private void handleMenuCoveredOrDismissed() {
-            if (mMenuExposedView != null && mMenuExposedView == mTranslatingParentView) {
-                mMenuExposedView = null;
-            }
-        }
-
-        @Override
-        public Animator getViewTranslationAnimator(View v, float target,
-                AnimatorUpdateListener listener) {
-            if (v instanceof ExpandableNotificationRow) {
-                return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
-            } else {
-                return super.getViewTranslationAnimator(v, target, listener);
-            }
-        }
-
-        @Override
-        public void setTranslation(View v, float translate) {
-            ((ExpandableView) v).setTranslation(translate);
-        }
-
-        @Override
-        public float getTranslation(View v) {
-            return ((ExpandableView) v).getTranslation();
-        }
-
-        @Override
-        public void dismiss(View animView, float velocity) {
-            dismissChild(animView, velocity,
-                    !swipedFastEnough(0, 0) /* useAccelerateInterpolator */);
-        }
-
-        @Override
-        public void snap(View animView, float targetLeft, float velocity) {
-            snapChild(animView, targetLeft, velocity);
-        }
-
-        @Override
-        public boolean swipedFarEnough(float translation, float viewSize) {
-            return swipedFarEnough();
-        }
-
-        @Override
-        public boolean swipedFastEnough(float translation, float velocity) {
-            return swipedFastEnough();
-        }
-
-        @Override
-        public float getMinDismissVelocity() {
-            return getEscapeVelocity();
-        }
-
-        public void onMenuShown(View animView) {
-            onDragCancelled(animView);
-
-            // If we're on the lockscreen we want to false this.
-            if (isAntiFalsingNeeded()) {
-                mHandler.removeCallbacks(mFalsingCheck);
-                mHandler.postDelayed(mFalsingCheck, COVER_MENU_DELAY);
-            }
-        }
-
-        public void closeControlsIfOutsideTouch(MotionEvent ev) {
-            NotificationGuts guts = mStatusBar.getGutsManager().getExposedGuts();
-            View view = null;
-            if (guts != null && !guts.getGutsContent().isLeavebehind()) {
-                // Only close visible guts if they're not a leavebehind.
-                view = guts;
-            } else if (mCurrMenuRow != null && mCurrMenuRow.isMenuVisible()
-                    && mTranslatingParentView != null) {
-                // Checking menu
-                view = mTranslatingParentView;
-            }
-            if (view != null && !isTouchInView(ev, view)) {
-                // Touch was outside visible guts / menu notification, close what's visible
-                mStatusBar.getGutsManager().closeAndSaveGuts(false /* removeLeavebehind */,
-                        false /* force */, true /* removeControls */, -1 /* x */, -1 /* y */,
-                        false /* resetMenu */);
-                resetExposedMenuView(true /* animate */, true /* force */);
-            }
-        }
-
-        public void resetExposedMenuView(boolean animate, boolean force) {
-            if (mMenuExposedView == null
-                    || (!force && mMenuExposedView == mTranslatingParentView)) {
-                // If no menu is showing or it's showing for this view we do nothing.
-                return;
-            }
-            final View prevMenuExposedView = mMenuExposedView;
-            if (animate) {
-                Animator anim = getViewTranslationAnimator(prevMenuExposedView,
-                        0 /* leftTarget */, null /* updateListener */);
-                if (anim != null) {
-                    anim.start();
-                }
-            } else if (mMenuExposedView instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) mMenuExposedView;
-                if (!row.isRemoved()) {
-                    row.resetTranslation();
-                }
-            }
-            mMenuExposedView = null;
-        }
-    }
-
-    private boolean isTouchInView(MotionEvent ev, View view) {
-        if (view == null) {
-            return false;
-        }
-        final int height = (view instanceof ExpandableView)
-                ? ((ExpandableView) view).getActualHeight()
-                : view.getHeight();
-        final int rx = (int) ev.getRawX();
-        final int ry = (int) ev.getRawY();
-        view.getLocationOnScreen(mTempInt2);
-        final int x = mTempInt2[0];
-        final int y = mTempInt2[1];
-        Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
-        boolean ret = rect.contains(rx, ry);
-        return ret;
-    }
-
-    private void updateContinuousShadowDrawing() {
-        boolean continuousShadowUpdate = mAnimationRunning
-                || !mAmbientState.getDraggedViews().isEmpty();
-        if (continuousShadowUpdate != mContinuousShadowUpdate) {
-            if (continuousShadowUpdate) {
-                getViewTreeObserver().addOnPreDrawListener(mShadowUpdater);
-            } else {
-                getViewTreeObserver().removeOnPreDrawListener(mShadowUpdater);
-            }
-            mContinuousShadowUpdate = continuousShadowUpdate;
-        }
-    }
-
-    @Override
-    public void resetExposedMenuView(boolean animate, boolean force) {
-        mSwipeHelper.resetExposedMenuView(animate, force);
-    }
-
-    public void closeControlsIfOutsideTouch(MotionEvent ev) {
-        mSwipeHelper.closeControlsIfOutsideTouch(ev);
-    }
-
-    static class AnimationEvent {
-
-        static AnimationFilter[] FILTERS = new AnimationFilter[] {
-
-                // ANIMATION_TYPE_ADD
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ()
-                        .hasDelays(),
-
-                // ANIMATION_TYPE_REMOVE
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ()
-                        .hasDelays(),
-
-                // ANIMATION_TYPE_REMOVE_SWIPED_OUT
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ()
-                        .hasDelays(),
-
-                // ANIMATION_TYPE_TOP_PADDING_CHANGED
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateDimmed()
-                        .animateZ(),
-
-                // ANIMATION_TYPE_START_DRAG
-                new AnimationFilter()
-                        .animateShadowAlpha(),
-
-                // ANIMATION_TYPE_SNAP_BACK
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight(),
-
-                // ANIMATION_TYPE_ACTIVATED_CHILD
-                new AnimationFilter()
-                        .animateZ(),
-
-                // ANIMATION_TYPE_DIMMED
-                new AnimationFilter()
-                        .animateDimmed(),
-
-                // ANIMATION_TYPE_CHANGE_POSITION
-                new AnimationFilter()
-                        .animateAlpha() // maybe the children change positions
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ(),
-
-                // ANIMATION_TYPE_DARK
-                null, // Unused
-
-                // ANIMATION_TYPE_GO_TO_FULL_SHADE
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateDimmed()
-                        .animateZ()
-                        .hasDelays(),
-
-                // ANIMATION_TYPE_HIDE_SENSITIVE
-                new AnimationFilter()
-                        .animateHideSensitive(),
-
-                // ANIMATION_TYPE_VIEW_RESIZE
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ(),
-
-                // ANIMATION_TYPE_GROUP_EXPANSION_CHANGED
-                new AnimationFilter()
-                        .animateAlpha()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ(),
-
-                // ANIMATION_TYPE_HEADS_UP_APPEAR
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ(),
-
-                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ()
-                        .hasDelays(),
-
-                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ()
-                        .hasDelays(),
-
-                // ANIMATION_TYPE_HEADS_UP_OTHER
-                new AnimationFilter()
-                        .animateShadowAlpha()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ(),
-
-                // ANIMATION_TYPE_EVERYTHING
-                new AnimationFilter()
-                        .animateAlpha()
-                        .animateShadowAlpha()
-                        .animateDark()
-                        .animateDimmed()
-                        .animateHideSensitive()
-                        .animateHeight()
-                        .animateTopInset()
-                        .animateY()
-                        .animateZ(),
-
-                // ANIMATION_TYPE_PULSE_APPEAR
-                new AnimationFilter()
-                        .animateAlpha()
-                        .hasDelays()
-                        .animateY(),
-
-                // ANIMATION_TYPE_PULSE_DISAPPEAR
-                new AnimationFilter()
-                        .animateAlpha()
-                        .hasDelays()
-                        .animateY(),
-        };
-
-        static int[] LENGTHS = new int[] {
-
-                // ANIMATION_TYPE_ADD
-                StackStateAnimator.ANIMATION_DURATION_APPEAR_DISAPPEAR,
-
-                // ANIMATION_TYPE_REMOVE
-                StackStateAnimator.ANIMATION_DURATION_APPEAR_DISAPPEAR,
-
-                // ANIMATION_TYPE_REMOVE_SWIPED_OUT
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_TOP_PADDING_CHANGED
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_START_DRAG
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_SNAP_BACK
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_ACTIVATED_CHILD
-                StackStateAnimator.ANIMATION_DURATION_DIMMED_ACTIVATED,
-
-                // ANIMATION_TYPE_DIMMED
-                StackStateAnimator.ANIMATION_DURATION_DIMMED_ACTIVATED,
-
-                // ANIMATION_TYPE_CHANGE_POSITION
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_DARK
-                StackStateAnimator.ANIMATION_DURATION_WAKEUP,
-
-                // ANIMATION_TYPE_GO_TO_FULL_SHADE
-                StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE,
-
-                // ANIMATION_TYPE_HIDE_SENSITIVE
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_VIEW_RESIZE
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_GROUP_EXPANSION_CHANGED
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_HEADS_UP_APPEAR
-                StackStateAnimator.ANIMATION_DURATION_HEADS_UP_APPEAR,
-
-                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR
-                StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
-
-                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
-                StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
-
-                // ANIMATION_TYPE_HEADS_UP_OTHER
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_EVERYTHING
-                StackStateAnimator.ANIMATION_DURATION_STANDARD,
-
-                // ANIMATION_TYPE_PULSE_APPEAR
-                StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR,
-
-                // ANIMATION_TYPE_PULSE_DISAPPEAR
-                StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR / 2,
-        };
-
-        static final int ANIMATION_TYPE_ADD = 0;
-        static final int ANIMATION_TYPE_REMOVE = 1;
-        static final int ANIMATION_TYPE_REMOVE_SWIPED_OUT = 2;
-        static final int ANIMATION_TYPE_TOP_PADDING_CHANGED = 3;
-        static final int ANIMATION_TYPE_START_DRAG = 4;
-        static final int ANIMATION_TYPE_SNAP_BACK = 5;
-        static final int ANIMATION_TYPE_ACTIVATED_CHILD = 6;
-        static final int ANIMATION_TYPE_DIMMED = 7;
-        static final int ANIMATION_TYPE_CHANGE_POSITION = 8;
-        static final int ANIMATION_TYPE_DARK = 9;
-        static final int ANIMATION_TYPE_GO_TO_FULL_SHADE = 10;
-        static final int ANIMATION_TYPE_HIDE_SENSITIVE = 11;
-        static final int ANIMATION_TYPE_VIEW_RESIZE = 12;
-        static final int ANIMATION_TYPE_GROUP_EXPANSION_CHANGED = 13;
-        static final int ANIMATION_TYPE_HEADS_UP_APPEAR = 14;
-        static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR = 15;
-        static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK = 16;
-        static final int ANIMATION_TYPE_HEADS_UP_OTHER = 17;
-        static final int ANIMATION_TYPE_EVERYTHING = 18;
-        static final int ANIMATION_TYPE_PULSE_APPEAR = 19;
-        static final int ANIMATION_TYPE_PULSE_DISAPPEAR = 20;
-
-        static final int DARK_ANIMATION_ORIGIN_INDEX_ABOVE = -1;
-        static final int DARK_ANIMATION_ORIGIN_INDEX_BELOW = -2;
-
-        final long eventStartTime;
-        final View changingView;
-        final int animationType;
-        final AnimationFilter filter;
-        final long length;
-        View viewAfterChangingView;
-        int darkAnimationOriginIndex;
-        boolean headsUpFromBottom;
-
-        AnimationEvent(View view, int type) {
-            this(view, type, LENGTHS[type]);
-        }
-
-        AnimationEvent(View view, int type, AnimationFilter filter) {
-            this(view, type, LENGTHS[type], filter);
-        }
-
-        AnimationEvent(View view, int type, long length) {
-            this(view, type, length, FILTERS[type]);
-        }
-
-        AnimationEvent(View view, int type, long length, AnimationFilter filter) {
-            eventStartTime = AnimationUtils.currentAnimationTimeMillis();
-            changingView = view;
-            animationType = type;
-            this.length = length;
-            this.filter = filter;
-        }
-
-        /**
-         * Combines the length of several animation events into a single value.
-         *
-         * @param events The events of the lengths to combine.
-         * @return The combined length. Depending on the event types, this might be the maximum of
-         *         all events or the length of a specific event.
-         */
-        static long combineLength(ArrayList<AnimationEvent> events) {
-            long length = 0;
-            int size = events.size();
-            for (int i = 0; i < size; i++) {
-                AnimationEvent event = events.get(i);
-                length = Math.max(length, event.length);
-                if (event.animationType == ANIMATION_TYPE_GO_TO_FULL_SHADE) {
-                    return event.length;
-                }
-            }
-            return length;
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
deleted file mode 100644
index ee006d3..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.EmptyShadeView;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
-import com.android.systemui.statusbar.FooterView;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * The Algorithm of the {@link com.android.systemui.statusbar.stack
- * .NotificationStackScrollLayout} which can be queried for {@link com.android.systemui.statusbar
- * .stack.StackScrollState}
- */
-public class StackScrollAlgorithm {
-
-    private static final String LOG_TAG = "StackScrollAlgorithm";
-
-    private int mPaddingBetweenElements;
-    private int mIncreasedPaddingBetweenElements;
-    private int mCollapsedSize;
-
-    private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
-    private boolean mIsExpanded;
-    private boolean mClipNotificationScrollToTop;
-    private int mStatusBarHeight;
-    private float mHeadsUpInset;
-    private int mPinnedZTranslationExtra;
-
-    public StackScrollAlgorithm(Context context) {
-        initView(context);
-    }
-
-    public void initView(Context context) {
-        initConstants(context);
-    }
-
-    private void initConstants(Context context) {
-        Resources res = context.getResources();
-        mPaddingBetweenElements = res.getDimensionPixelSize(
-                R.dimen.notification_divider_height);
-        mIncreasedPaddingBetweenElements =
-                res.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
-        mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
-        mStatusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
-        mClipNotificationScrollToTop = res.getBoolean(R.bool.config_clipNotificationScrollToTop);
-        mHeadsUpInset = mStatusBarHeight + res.getDimensionPixelSize(
-                R.dimen.heads_up_status_bar_padding);
-        mPinnedZTranslationExtra = res.getDimensionPixelSize(
-                R.dimen.heads_up_pinned_elevation);
-    }
-
-    public void getStackScrollState(AmbientState ambientState, StackScrollState resultState) {
-        // The state of the local variables are saved in an algorithmState to easily subdivide it
-        // into multiple phases.
-        StackScrollAlgorithmState algorithmState = mTempAlgorithmState;
-
-        // First we reset the view states to their default values.
-        resultState.resetViewStates();
-
-        initAlgorithmState(resultState, algorithmState, ambientState);
-
-        updatePositionsForState(resultState, algorithmState, ambientState);
-
-        updateZValuesForState(resultState, algorithmState, ambientState);
-
-        updateHeadsUpStates(resultState, algorithmState, ambientState);
-
-        handleDraggedViews(ambientState, resultState, algorithmState);
-        updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState);
-        updateClipping(resultState, algorithmState, ambientState);
-        updateSpeedBumpState(resultState, algorithmState, ambientState);
-        updateShelfState(resultState, ambientState);
-        getNotificationChildrenStates(resultState, algorithmState, ambientState);
-    }
-
-    private void getNotificationChildrenStates(StackScrollState resultState,
-            StackScrollAlgorithmState algorithmState,
-            AmbientState ambientState) {
-        int childCount = algorithmState.visibleChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            ExpandableView v = algorithmState.visibleChildren.get(i);
-            if (v instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-                row.getChildrenStates(resultState, ambientState);
-            }
-        }
-    }
-
-    private void updateSpeedBumpState(StackScrollState resultState,
-            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
-        int childCount = algorithmState.visibleChildren.size();
-        int belowSpeedBump = ambientState.getSpeedBumpIndex();
-        for (int i = 0; i < childCount; i++) {
-            View child = algorithmState.visibleChildren.get(i);
-            ExpandableViewState childViewState = resultState.getViewStateForView(child);
-
-            // The speed bump can also be gone, so equality needs to be taken when comparing
-            // indices.
-            childViewState.belowSpeedBump = i >= belowSpeedBump;
-        }
-
-    }
-    private void updateShelfState(StackScrollState resultState, AmbientState ambientState) {
-        NotificationShelf shelf = ambientState.getShelf();
-        if (shelf != null) {
-            shelf.updateState(resultState, ambientState);
-        }
-    }
-
-    private void updateClipping(StackScrollState resultState,
-            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
-        float drawStart = !ambientState.isOnKeyguard() ? ambientState.getTopPadding()
-                + ambientState.getStackTranslation() + ambientState.getExpandAnimationTopChange()
-                : 0;
-        float previousNotificationEnd = 0;
-        float previousNotificationStart = 0;
-        int childCount = algorithmState.visibleChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            ExpandableView child = algorithmState.visibleChildren.get(i);
-            ExpandableViewState state = resultState.getViewStateForView(child);
-            if (!child.mustStayOnScreen() || state.headsUpIsVisible) {
-                previousNotificationEnd = Math.max(drawStart, previousNotificationEnd);
-                previousNotificationStart = Math.max(drawStart, previousNotificationStart);
-            }
-            float newYTranslation = state.yTranslation;
-            float newHeight = state.height;
-            float newNotificationEnd = newYTranslation + newHeight;
-            boolean isHeadsUp = (child instanceof ExpandableNotificationRow)
-                    && ((ExpandableNotificationRow) child).isPinned();
-            if (mClipNotificationScrollToTop
-                    && !state.inShelf && newYTranslation < previousNotificationEnd
-                    && (!isHeadsUp || ambientState.isShadeExpanded())) {
-                // The previous view is overlapping on top, clip!
-                float overlapAmount = previousNotificationEnd - newYTranslation;
-                state.clipTopAmount = (int) overlapAmount;
-            } else {
-                state.clipTopAmount = 0;
-            }
-
-            if (!child.isTransparent()) {
-                // Only update the previous values if we are not transparent,
-                // otherwise we would clip to a transparent view.
-                previousNotificationEnd = newNotificationEnd;
-                previousNotificationStart = newYTranslation;
-            }
-        }
-    }
-
-    public static boolean canChildBeDismissed(View v) {
-        if (!(v instanceof ExpandableNotificationRow)) {
-            return false;
-        }
-        ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-        if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
-            return false;
-        }
-        return row.canViewBeDismissed();
-    }
-
-    /**
-     * Updates the dimmed, activated and hiding sensitive states of the children.
-     */
-    private void updateDimmedActivatedHideSensitive(AmbientState ambientState,
-            StackScrollState resultState, StackScrollAlgorithmState algorithmState) {
-        boolean dimmed = ambientState.isDimmed();
-        boolean dark = ambientState.isFullyDark();
-        boolean hideSensitive = ambientState.isHideSensitive();
-        View activatedChild = ambientState.getActivatedChild();
-        int childCount = algorithmState.visibleChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            View child = algorithmState.visibleChildren.get(i);
-            ExpandableViewState childViewState = resultState.getViewStateForView(child);
-            childViewState.dimmed = dimmed;
-            childViewState.dark = dark;
-            childViewState.hideSensitive = hideSensitive;
-            boolean isActivatedChild = activatedChild == child;
-            if (dimmed && isActivatedChild) {
-                childViewState.zTranslation += 2.0f * ambientState.getZDistanceBetweenElements();
-            }
-        }
-    }
-
-    /**
-     * Handle the special state when views are being dragged
-     */
-    private void handleDraggedViews(AmbientState ambientState, StackScrollState resultState,
-            StackScrollAlgorithmState algorithmState) {
-        ArrayList<View> draggedViews = ambientState.getDraggedViews();
-        for (View draggedView : draggedViews) {
-            int childIndex = algorithmState.visibleChildren.indexOf(draggedView);
-            if (childIndex >= 0 && childIndex < algorithmState.visibleChildren.size() - 1) {
-                View nextChild = algorithmState.visibleChildren.get(childIndex + 1);
-                if (!draggedViews.contains(nextChild)) {
-                    // only if the view is not dragged itself we modify its state to be fully
-                    // visible
-                    ExpandableViewState viewState = resultState.getViewStateForView(
-                            nextChild);
-                    // The child below the dragged one must be fully visible
-                    if (ambientState.isShadeExpanded()) {
-                        viewState.shadowAlpha = 1;
-                        viewState.hidden = false;
-                    }
-                }
-
-                // Lets set the alpha to the one it currently has, as its currently being dragged
-                ExpandableViewState viewState = resultState.getViewStateForView(draggedView);
-                // The dragged child should keep the set alpha
-                viewState.alpha = draggedView.getAlpha();
-            }
-        }
-    }
-
-    /**
-     * Initialize the algorithm state like updating the visible children.
-     */
-    private void initAlgorithmState(StackScrollState resultState, StackScrollAlgorithmState state,
-            AmbientState ambientState) {
-        float bottomOverScroll = ambientState.getOverScrollAmount(false /* onTop */);
-
-        int scrollY = ambientState.getScrollY();
-
-        // Due to the overScroller, the stackscroller can have negative scroll state. This is
-        // already accounted for by the top padding and doesn't need an additional adaption
-        scrollY = Math.max(0, scrollY);
-        state.scrollY = (int) (scrollY + bottomOverScroll);
-
-        //now init the visible children and update paddings
-        ViewGroup hostView = resultState.getHostView();
-        int childCount = hostView.getChildCount();
-        state.visibleChildren.clear();
-        state.visibleChildren.ensureCapacity(childCount);
-        state.paddingMap.clear();
-        int notGoneIndex = 0;
-        ExpandableView lastView = null;
-        int firstHiddenIndex = ambientState.isDark()
-                ? (ambientState.hasPulsingNotifications() ? 1 : 0)
-                : childCount;
-
-        // The goal here is to fill the padding map, by iterating over how much padding each child
-        // needs. The map is thereby reused, by first filling it with the padding amount and when
-        // iterating over it again, it's filled with the actual resolved value.
-
-        for (int i = 0; i < childCount; i++) {
-            ExpandableView v = (ExpandableView) hostView.getChildAt(i);
-            if (v.getVisibility() != View.GONE) {
-                if (v == ambientState.getShelf()) {
-                    continue;
-                }
-                if (i >= firstHiddenIndex) {
-                    // we need normal padding now, to be in sync with what the stack calculates
-                    lastView = null;
-                }
-                notGoneIndex = updateNotGoneIndex(resultState, state, notGoneIndex, v);
-                float increasedPadding = v.getIncreasedPaddingAmount();
-                if (increasedPadding != 0.0f) {
-                    state.paddingMap.put(v, increasedPadding);
-                    if (lastView != null) {
-                        Float prevValue = state.paddingMap.get(lastView);
-                        float newValue = getPaddingForValue(increasedPadding);
-                        if (prevValue != null) {
-                            float prevPadding = getPaddingForValue(prevValue);
-                            if (increasedPadding > 0) {
-                                newValue = NotificationUtils.interpolate(
-                                        prevPadding,
-                                        newValue,
-                                        increasedPadding);
-                            } else if (prevValue > 0) {
-                                newValue = NotificationUtils.interpolate(
-                                        newValue,
-                                        prevPadding,
-                                        prevValue);
-                            }
-                        }
-                        state.paddingMap.put(lastView, newValue);
-                    }
-                } else if (lastView != null) {
-
-                    // Let's now resolve the value to an actual padding
-                    float newValue = getPaddingForValue(state.paddingMap.get(lastView));
-                    state.paddingMap.put(lastView, newValue);
-                }
-                if (v instanceof ExpandableNotificationRow) {
-                    ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-
-                    // handle the notgoneIndex for the children as well
-                    List<ExpandableNotificationRow> children =
-                            row.getNotificationChildren();
-                    if (row.isSummaryWithChildren() && children != null) {
-                        for (ExpandableNotificationRow childRow : children) {
-                            if (childRow.getVisibility() != View.GONE) {
-                                ExpandableViewState childState
-                                        = resultState.getViewStateForView(childRow);
-                                childState.notGoneIndex = notGoneIndex;
-                                notGoneIndex++;
-                            }
-                        }
-                    }
-                }
-                lastView = v;
-            }
-        }
-        ExpandableNotificationRow expandingNotification = ambientState.getExpandingNotification();
-        state.indexOfExpandingNotification = expandingNotification != null
-                ? expandingNotification.isChildInGroup()
-                    ? state.visibleChildren.indexOf(expandingNotification.getNotificationParent())
-                    : state.visibleChildren.indexOf(expandingNotification)
-                : -1;
-    }
-
-    private float getPaddingForValue(Float increasedPadding) {
-        if (increasedPadding == null) {
-            return mPaddingBetweenElements;
-        } else if (increasedPadding >= 0.0f) {
-            return NotificationUtils.interpolate(
-                    mPaddingBetweenElements,
-                    mIncreasedPaddingBetweenElements,
-                    increasedPadding);
-        } else {
-            return NotificationUtils.interpolate(
-                    0,
-                    mPaddingBetweenElements,
-                    1.0f + increasedPadding);
-        }
-    }
-
-    private int updateNotGoneIndex(StackScrollState resultState,
-            StackScrollAlgorithmState state, int notGoneIndex,
-            ExpandableView v) {
-        ExpandableViewState viewState = resultState.getViewStateForView(v);
-        viewState.notGoneIndex = notGoneIndex;
-        state.visibleChildren.add(v);
-        notGoneIndex++;
-        return notGoneIndex;
-    }
-
-    /**
-     * Determine the positions for the views. This is the main part of the algorithm.
-     *
-     * @param resultState The result state to update if a change to the properties of a child occurs
-     * @param algorithmState The state in which the current pass of the algorithm is currently in
-     * @param ambientState The current ambient state
-     */
-    private void updatePositionsForState(StackScrollState resultState,
-            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
-
-        // The y coordinate of the current child.
-        float currentYPosition = -algorithmState.scrollY;
-        int childCount = algorithmState.visibleChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            currentYPosition = updateChild(i, resultState, algorithmState, ambientState,
-                    currentYPosition);
-        }
-    }
-
-    protected float updateChild(int i, StackScrollState resultState,
-            StackScrollAlgorithmState algorithmState, AmbientState ambientState,
-            float currentYPosition) {
-        ExpandableView child = algorithmState.visibleChildren.get(i);
-        ExpandableViewState childViewState = resultState.getViewStateForView(child);
-        childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
-        int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
-        int childHeight = getMaxAllowedChildHeight(child);
-        childViewState.yTranslation = currentYPosition;
-        boolean isFooterView = child instanceof FooterView;
-        boolean isEmptyShadeView = child instanceof EmptyShadeView;
-
-        childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
-        float inset = ambientState.getTopPadding() + ambientState.getStackTranslation();
-        if (i <= algorithmState.getIndexOfExpandingNotification()) {
-            inset += ambientState.getExpandAnimationTopChange();
-        }
-        if (child.mustStayOnScreen() && childViewState.yTranslation >= 0) {
-            // Even if we're not scrolled away we're in view and we're also not in the
-            // shelf. We can relax the constraints and let us scroll off the top!
-            float end = childViewState.yTranslation + childViewState.height + inset;
-            childViewState.headsUpIsVisible = end < ambientState.getMaxHeadsUpTranslation();
-        }
-        if (isFooterView) {
-            childViewState.yTranslation = Math.min(childViewState.yTranslation,
-                    ambientState.getInnerHeight() - childHeight);
-        } else if (isEmptyShadeView) {
-            childViewState.yTranslation = ambientState.getInnerHeight() - childHeight
-                    + ambientState.getStackTranslation() * 0.25f;
-        } else {
-            clampPositionToShelf(child, childViewState, ambientState);
-        }
-
-        currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
-        if (currentYPosition <= 0) {
-            childViewState.location = ExpandableViewState.LOCATION_HIDDEN_TOP;
-        }
-        if (childViewState.location == ExpandableViewState.LOCATION_UNKNOWN) {
-            Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
-        }
-
-        childViewState.yTranslation += inset;
-        return currentYPosition;
-    }
-
-    protected int getPaddingAfterChild(StackScrollAlgorithmState algorithmState,
-            ExpandableView child) {
-        return algorithmState.getPaddingAfterChild(child);
-    }
-
-    private void updateHeadsUpStates(StackScrollState resultState,
-            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
-        int childCount = algorithmState.visibleChildren.size();
-        ExpandableNotificationRow topHeadsUpEntry = null;
-        for (int i = 0; i < childCount; i++) {
-            View child = algorithmState.visibleChildren.get(i);
-            if (!(child instanceof ExpandableNotificationRow)) {
-                break;
-            }
-            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            if (!row.isHeadsUp()) {
-                break;
-            }
-            ExpandableViewState childState = resultState.getViewStateForView(row);
-            if (topHeadsUpEntry == null && row.mustStayOnScreen() && !childState.headsUpIsVisible) {
-                topHeadsUpEntry = row;
-                childState.location = ExpandableViewState.LOCATION_FIRST_HUN;
-            }
-            boolean isTopEntry = topHeadsUpEntry == row;
-            float unmodifiedEndLocation = childState.yTranslation + childState.height;
-            if (mIsExpanded) {
-                if (row.mustStayOnScreen() && !childState.headsUpIsVisible) {
-                    // Ensure that the heads up is always visible even when scrolled off
-                    clampHunToTop(ambientState, row, childState);
-                    if (i == 0 && ambientState.isAboveShelf(row)) {
-                        // the first hun can't get off screen.
-                        clampHunToMaxTranslation(ambientState, row, childState);
-                        childState.hidden = false;
-                    }
-                }
-            }
-            if (row.isPinned()) {
-                childState.yTranslation = Math.max(childState.yTranslation, mHeadsUpInset);
-                childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
-                childState.hidden = false;
-                ExpandableViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
-                if (topState != null && !isTopEntry && (!mIsExpanded
-                        || unmodifiedEndLocation < topState.yTranslation + topState.height)) {
-                    // Ensure that a headsUp doesn't vertically extend further than the heads-up at
-                    // the top most z-position
-                    childState.height = row.getIntrinsicHeight();
-                    childState.yTranslation = topState.yTranslation + topState.height
-                            - childState.height;
-                }
-            }
-            if (row.isHeadsUpAnimatingAway()) {
-                childState.hidden = false;
-            }
-        }
-    }
-
-    private void clampHunToTop(AmbientState ambientState, ExpandableNotificationRow row,
-            ExpandableViewState childState) {
-        float newTranslation = Math.max(ambientState.getTopPadding()
-                + ambientState.getStackTranslation(), childState.yTranslation);
-        childState.height = (int) Math.max(childState.height - (newTranslation
-                - childState.yTranslation), row.getCollapsedHeight());
-        childState.yTranslation = newTranslation;
-    }
-
-    private void clampHunToMaxTranslation(AmbientState ambientState, ExpandableNotificationRow row,
-            ExpandableViewState childState) {
-        float newTranslation;
-        float maxHeadsUpTranslation = ambientState.getMaxHeadsUpTranslation();
-        float maxShelfPosition = ambientState.getInnerHeight() + ambientState.getTopPadding()
-                + ambientState.getStackTranslation();
-        maxHeadsUpTranslation = Math.min(maxHeadsUpTranslation, maxShelfPosition);
-        float bottomPosition = maxHeadsUpTranslation - row.getCollapsedHeight();
-        newTranslation = Math.min(childState.yTranslation, bottomPosition);
-        childState.height = (int) Math.min(childState.height, maxHeadsUpTranslation
-                - newTranslation);
-        childState.yTranslation = newTranslation;
-    }
-
-    /**
-     * Clamp the height of the child down such that its end is at most on the beginning of
-     * the shelf.
-     *
-     * @param child
-     * @param childViewState the view state of the child
-     * @param ambientState the ambient state
-     */
-    private void clampPositionToShelf(ExpandableView child,
-            ExpandableViewState childViewState,
-            AmbientState ambientState) {
-        if (ambientState.getShelf() == null) {
-            return;
-        }
-
-        int shelfStart = ambientState.getInnerHeight()
-                - ambientState.getShelf().getIntrinsicHeight();
-        if (ambientState.isAppearing() && !child.isAboveShelf()) {
-            // Don't show none heads-up notifications while in appearing phase.
-            childViewState.yTranslation = Math.max(childViewState.yTranslation, shelfStart);
-        }
-        childViewState.yTranslation = Math.min(childViewState.yTranslation, shelfStart);
-        if (childViewState.yTranslation >= shelfStart) {
-            childViewState.hidden = !child.isExpandAnimationRunning() && !child.hasExpandingChild();
-            childViewState.inShelf = true;
-            childViewState.headsUpIsVisible = false;
-        }
-    }
-
-    protected int getMaxAllowedChildHeight(View child) {
-        if (child instanceof ExpandableView) {
-            ExpandableView expandableView = (ExpandableView) child;
-            return expandableView.getIntrinsicHeight();
-        }
-        return child == null? mCollapsedSize : child.getHeight();
-    }
-
-    /**
-     * Calculate the Z positions for all children based on the number of items in both stacks and
-     * save it in the resultState
-     *  @param resultState The result state to update the zTranslation values
-     * @param algorithmState The state in which the current pass of the algorithm is currently in
-     * @param ambientState The ambient state of the algorithm
-     */
-    private void updateZValuesForState(StackScrollState resultState,
-            StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
-        int childCount = algorithmState.visibleChildren.size();
-        float childrenOnTop = 0.0f;
-        for (int i = childCount - 1; i >= 0; i--) {
-            childrenOnTop = updateChildZValue(i, childrenOnTop,
-                    resultState, algorithmState, ambientState);
-        }
-    }
-
-    protected float updateChildZValue(int i, float childrenOnTop,
-            StackScrollState resultState, StackScrollAlgorithmState algorithmState,
-            AmbientState ambientState) {
-        ExpandableView child = algorithmState.visibleChildren.get(i);
-        ExpandableViewState childViewState = resultState.getViewStateForView(child);
-        int zDistanceBetweenElements = ambientState.getZDistanceBetweenElements();
-        float baseZ = ambientState.getBaseZHeight();
-        if (child.mustStayOnScreen() && !childViewState.headsUpIsVisible
-                && !ambientState.isDozingAndNotPulsing(child)
-                && childViewState.yTranslation < ambientState.getTopPadding()
-                + ambientState.getStackTranslation()) {
-            if (childrenOnTop != 0.0f) {
-                childrenOnTop++;
-            } else {
-                float overlap = ambientState.getTopPadding()
-                        + ambientState.getStackTranslation() - childViewState.yTranslation;
-                childrenOnTop += Math.min(1.0f, overlap / childViewState.height);
-            }
-            childViewState.zTranslation = baseZ
-                    + childrenOnTop * zDistanceBetweenElements;
-        } else if (i == 0 && ambientState.isAboveShelf(child)) {
-            // In case this is a new view that has never been measured before, we don't want to
-            // elevate if we are currently expanded more then the notification
-            int shelfHeight = ambientState.getShelf() == null ? 0 :
-                    ambientState.getShelf().getIntrinsicHeight();
-            float shelfStart = ambientState.getInnerHeight()
-                    - shelfHeight + ambientState.getTopPadding()
-                    + ambientState.getStackTranslation();
-            float notificationEnd = childViewState.yTranslation + child.getPinnedHeadsUpHeight()
-                    + mPaddingBetweenElements;
-            if (shelfStart > notificationEnd) {
-                childViewState.zTranslation = baseZ;
-            } else {
-                float factor = (notificationEnd - shelfStart) / shelfHeight;
-                factor = Math.min(factor, 1.0f);
-                childViewState.zTranslation = baseZ + factor * zDistanceBetweenElements;
-            }
-        } else {
-            childViewState.zTranslation = baseZ;
-        }
-
-        // We need to scrim the notification more from its surrounding content when we are pinned,
-        // and we therefore elevate it higher.
-        // We can use the headerVisibleAmount for this, since the value nicely goes from 0 to 1 when
-        // expanding after which we have a normal elevation again.
-        childViewState.zTranslation += (1.0f - child.getHeaderVisibleAmount())
-                * mPinnedZTranslationExtra;
-        return childrenOnTop;
-    }
-
-    public void setIsExpanded(boolean isExpanded) {
-        this.mIsExpanded = isExpanded;
-    }
-
-    public class StackScrollAlgorithmState {
-
-        /**
-         * The scroll position of the algorithm
-         */
-        public int scrollY;
-
-        /**
-         * The children from the host view which are not gone.
-         */
-        public final ArrayList<ExpandableView> visibleChildren = new ArrayList<ExpandableView>();
-
-        /**
-         * The padding after each child measured in pixels.
-         */
-        public final HashMap<ExpandableView, Float> paddingMap = new HashMap<>();
-        private int indexOfExpandingNotification;
-
-        public int getPaddingAfterChild(ExpandableView child) {
-            Float padding = paddingMap.get(child);
-            if (padding == null) {
-                // Should only happen for the last view
-                return mPaddingBetweenElements;
-            }
-            return (int) padding.floatValue();
-        }
-
-        public int getIndexOfExpandingNotification() {
-            return indexOfExpandingNotification;
-        }
-    }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
deleted file mode 100644
index 588b758..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
-
-import java.util.List;
-import java.util.WeakHashMap;
-
-/**
- * A state of a {@link com.android.systemui.statusbar.stack.NotificationStackScrollLayout} which
- * can be applied to a viewGroup.
- */
-public class StackScrollState {
-
-    private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
-
-    private final ViewGroup mHostView;
-    private WeakHashMap<ExpandableView, ExpandableViewState> mStateMap;
-
-    public StackScrollState(ViewGroup hostView) {
-        mHostView = hostView;
-        mStateMap = new WeakHashMap<>();
-    }
-
-    public ViewGroup getHostView() {
-        return mHostView;
-    }
-
-    public void resetViewStates() {
-        int numChildren = mHostView.getChildCount();
-        for (int i = 0; i < numChildren; i++) {
-            ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
-            resetViewState(child);
-
-            // handling reset for child notifications
-            if (child instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                List<ExpandableNotificationRow> children =
-                        row.getNotificationChildren();
-                if (row.isSummaryWithChildren() && children != null) {
-                    for (ExpandableNotificationRow childRow : children) {
-                        resetViewState(childRow);
-                    }
-                }
-            }
-        }
-    }
-
-    private void resetViewState(ExpandableView view) {
-        ExpandableViewState viewState = mStateMap.get(view);
-        if (viewState == null) {
-            viewState = view.createNewViewState(this);
-            mStateMap.put(view, viewState);
-        }
-        // initialize with the default values of the view
-        viewState.height = view.getIntrinsicHeight();
-        viewState.gone = view.getVisibility() == View.GONE;
-        viewState.alpha = 1f;
-        viewState.shadowAlpha = 1f;
-        viewState.notGoneIndex = -1;
-        viewState.xTranslation = view.getTranslationX();
-        viewState.hidden = false;
-        viewState.scaleX = view.getScaleX();
-        viewState.scaleY = view.getScaleY();
-        viewState.inShelf = false;
-        viewState.headsUpIsVisible = false;
-    }
-
-    public ExpandableViewState getViewStateForView(View requestedView) {
-        return mStateMap.get(requestedView);
-    }
-
-    public void removeViewStateForView(View child) {
-        mStateMap.remove(child);
-    }
-
-    /**
-     * Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
-     * The properties are only applied if they effectively changed.
-     */
-    public void apply() {
-        int numChildren = mHostView.getChildCount();
-        for (int i = 0; i < numChildren; i++) {
-            ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
-            ExpandableViewState state = mStateMap.get(child);
-            if (state == null) {
-                Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
-                        "to the hostView");
-                continue;
-            }
-            if (state.gone) {
-                continue;
-            }
-            state.applyToView(child);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
deleted file mode 100644
index b83a09d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.util.Property;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.Interpolator;
-
-import com.android.keyguard.KeyguardSliceView;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableView;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.StatusBarIconView;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Stack;
-
-/**
- * An stack state animator which handles animations to new StackScrollStates
- */
-public class StackStateAnimator {
-
-    public static final int ANIMATION_DURATION_STANDARD = 360;
-    public static final int ANIMATION_DURATION_WAKEUP = 500;
-    public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448;
-    public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
-    public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;
-    public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150;
-    public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 550;
-    public static final int ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED
-            = (int) (ANIMATION_DURATION_HEADS_UP_APPEAR
-                    * HeadsUpAppearInterpolator.getFractionUntilOvershoot());
-    public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 300;
-    public static final int ANIMATION_DURATION_PULSE_APPEAR =
-            KeyguardSliceView.DEFAULT_ANIM_DURATION;
-    public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240;
-    public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;
-    public static final int ANIMATION_DELAY_PER_ELEMENT_MANUAL = 32;
-    public static final int ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE = 48;
-    public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
-    public static final int ANIMATION_DELAY_HEADS_UP = 120;
-    public static final int ANIMATION_DELAY_HEADS_UP_CLICKED= 120;
-
-    private final int mGoToFullShadeAppearingTranslation;
-    private final int mPulsingAppearingTranslation;
-    private final ExpandableViewState mTmpState = new ExpandableViewState();
-    private final AnimationProperties mAnimationProperties;
-    public NotificationStackScrollLayout mHostLayout;
-    private ArrayList<NotificationStackScrollLayout.AnimationEvent> mNewEvents =
-            new ArrayList<>();
-    private ArrayList<View> mNewAddChildren = new ArrayList<>();
-    private HashSet<View> mHeadsUpAppearChildren = new HashSet<>();
-    private HashSet<View> mHeadsUpDisappearChildren = new HashSet<>();
-    private HashSet<Animator> mAnimatorSet = new HashSet<>();
-    private Stack<AnimatorListenerAdapter> mAnimationListenerPool = new Stack<>();
-    private AnimationFilter mAnimationFilter = new AnimationFilter();
-    private long mCurrentLength;
-    private long mCurrentAdditionalDelay;
-
-    /** The current index for the last child which was not added in this event set. */
-    private int mCurrentLastNotAddedIndex;
-    private ValueAnimator mTopOverScrollAnimator;
-    private ValueAnimator mBottomOverScrollAnimator;
-    private int mHeadsUpAppearHeightBottom;
-    private boolean mShadeExpanded;
-    private ArrayList<ExpandableView> mTransientViewsToRemove = new ArrayList<>();
-    private NotificationShelf mShelf;
-    private float mStatusBarIconLocation;
-    private int[] mTmpLocation = new int[2];
-
-    public StackStateAnimator(NotificationStackScrollLayout hostLayout) {
-        mHostLayout = hostLayout;
-        mGoToFullShadeAppearingTranslation =
-                hostLayout.getContext().getResources().getDimensionPixelSize(
-                        R.dimen.go_to_full_shade_appearing_translation);
-        mPulsingAppearingTranslation =
-                hostLayout.getContext().getResources().getDimensionPixelSize(
-                        R.dimen.pulsing_notification_appear_translation);
-        mAnimationProperties = new AnimationProperties() {
-            @Override
-            public AnimationFilter getAnimationFilter() {
-                return mAnimationFilter;
-            }
-
-            @Override
-            public AnimatorListenerAdapter getAnimationFinishListener() {
-                return getGlobalAnimationFinishedListener();
-            }
-
-            @Override
-            public boolean wasAdded(View view) {
-                return mNewAddChildren.contains(view);
-            }
-
-            @Override
-            public Interpolator getCustomInterpolator(View child, Property property) {
-                if (mHeadsUpAppearChildren.contains(child) && View.TRANSLATION_Y.equals(property)) {
-                    return Interpolators.HEADS_UP_APPEAR;
-                }
-                return null;
-            }
-        };
-    }
-
-    public boolean isRunning() {
-        return !mAnimatorSet.isEmpty();
-    }
-
-    public void startAnimationForEvents(
-            ArrayList<NotificationStackScrollLayout.AnimationEvent> mAnimationEvents,
-            StackScrollState finalState, long additionalDelay) {
-
-        processAnimationEvents(mAnimationEvents, finalState);
-
-        int childCount = mHostLayout.getChildCount();
-        mAnimationFilter.applyCombination(mNewEvents);
-        mCurrentAdditionalDelay = additionalDelay;
-        mCurrentLength = NotificationStackScrollLayout.AnimationEvent.combineLength(mNewEvents);
-        mCurrentLastNotAddedIndex = findLastNotAddedIndex(finalState);
-        for (int i = 0; i < childCount; i++) {
-            final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
-
-            ExpandableViewState viewState = finalState.getViewStateForView(child);
-            if (viewState == null || child.getVisibility() == View.GONE
-                    || applyWithoutAnimation(child, viewState, finalState)) {
-                continue;
-            }
-
-            initAnimationProperties(finalState, child, viewState);
-            viewState.animateTo(child, mAnimationProperties);
-        }
-        if (!isRunning()) {
-            // no child has preformed any animation, lets finish
-            onAnimationFinished();
-        }
-        mHeadsUpAppearChildren.clear();
-        mHeadsUpDisappearChildren.clear();
-        mNewEvents.clear();
-        mNewAddChildren.clear();
-    }
-
-    private void initAnimationProperties(StackScrollState finalState, ExpandableView child,
-            ExpandableViewState viewState) {
-        boolean wasAdded = mAnimationProperties.wasAdded(child);
-        mAnimationProperties.duration = mCurrentLength;
-        adaptDurationWhenGoingToFullShade(child, viewState, wasAdded);
-        mAnimationProperties.delay = 0;
-        if (wasAdded || mAnimationFilter.hasDelays
-                        && (viewState.yTranslation != child.getTranslationY()
-                        || viewState.zTranslation != child.getTranslationZ()
-                        || viewState.alpha != child.getAlpha()
-                        || viewState.height != child.getActualHeight()
-                        || viewState.clipTopAmount != child.getClipTopAmount()
-                        || viewState.dark != child.isDark()
-                        || viewState.shadowAlpha != child.getShadowAlpha())) {
-            mAnimationProperties.delay = mCurrentAdditionalDelay
-                    + calculateChildAnimationDelay(viewState, finalState);
-        }
-    }
-
-    private void adaptDurationWhenGoingToFullShade(ExpandableView child,
-            ExpandableViewState viewState, boolean wasAdded) {
-        if (wasAdded && mAnimationFilter.hasGoToFullShadeEvent) {
-            child.setTranslationY(child.getTranslationY() + mGoToFullShadeAppearingTranslation);
-            float longerDurationFactor = viewState.notGoneIndex - mCurrentLastNotAddedIndex;
-            longerDurationFactor = (float) Math.pow(longerDurationFactor, 0.7f);
-            mAnimationProperties.duration = ANIMATION_DURATION_APPEAR_DISAPPEAR + 50 +
-                    (long) (100 * longerDurationFactor);
-        }
-    }
-
-    /**
-     * Determines if a view should not perform an animation and applies it directly.
-     *
-     * @return true if no animation should be performed
-     */
-    private boolean applyWithoutAnimation(ExpandableView child, ExpandableViewState viewState,
-            StackScrollState finalState) {
-        if (mShadeExpanded) {
-            return false;
-        }
-        if (ViewState.isAnimatingY(child)) {
-            // A Y translation animation is running
-            return false;
-        }
-        if (mHeadsUpDisappearChildren.contains(child) || mHeadsUpAppearChildren.contains(child)) {
-            // This is a heads up animation
-            return false;
-        }
-        if (NotificationStackScrollLayout.isPinnedHeadsUp(child)) {
-            // This is another headsUp which might move. Let's animate!
-            return false;
-        }
-        viewState.applyToView(child);
-        return true;
-    }
-
-    private int findLastNotAddedIndex(StackScrollState finalState) {
-        int childCount = mHostLayout.getChildCount();
-        for (int i = childCount - 1; i >= 0; i--) {
-            final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
-
-            ExpandableViewState viewState = finalState.getViewStateForView(child);
-            if (viewState == null || child.getVisibility() == View.GONE) {
-                continue;
-            }
-            if (!mNewAddChildren.contains(child)) {
-                return viewState.notGoneIndex;
-            }
-        }
-        return -1;
-    }
-
-    private long calculateChildAnimationDelay(ExpandableViewState viewState,
-            StackScrollState finalState) {
-        if (mAnimationFilter.hasGoToFullShadeEvent) {
-            return calculateDelayGoToFullShade(viewState);
-        }
-        if (mAnimationFilter.customDelay != AnimationFilter.NO_DELAY) {
-            return mAnimationFilter.customDelay;
-        }
-        long minDelay = 0;
-        for (NotificationStackScrollLayout.AnimationEvent event : mNewEvents) {
-            long delayPerElement = ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING;
-            switch (event.animationType) {
-                case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD: {
-                    int ownIndex = viewState.notGoneIndex;
-                    int changingIndex = finalState
-                            .getViewStateForView(event.changingView).notGoneIndex;
-                    int difference = Math.abs(ownIndex - changingIndex);
-                    difference = Math.max(0, Math.min(DELAY_EFFECT_MAX_INDEX_DIFFERENCE,
-                            difference - 1));
-                    long delay = (DELAY_EFFECT_MAX_INDEX_DIFFERENCE - difference) * delayPerElement;
-                    minDelay = Math.max(delay, minDelay);
-                    break;
-                }
-                case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT:
-                    delayPerElement = ANIMATION_DELAY_PER_ELEMENT_MANUAL;
-                case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE: {
-                    int ownIndex = viewState.notGoneIndex;
-                    boolean noNextView = event.viewAfterChangingView == null;
-                    View viewAfterChangingView = noNextView
-                            ? mHostLayout.getLastChildNotGone()
-                            : event.viewAfterChangingView;
-                    if (viewAfterChangingView == null) {
-                        // This can happen when the last view in the list is removed.
-                        // Since the shelf is still around and the only view, the code still goes
-                        // in here and tries to calculate the delay for it when case its properties
-                        // have changed.
-                        continue;
-                    }
-                    int nextIndex = finalState
-                            .getViewStateForView(viewAfterChangingView).notGoneIndex;
-                    if (ownIndex >= nextIndex) {
-                        // we only have the view afterwards
-                        ownIndex++;
-                    }
-                    int difference = Math.abs(ownIndex - nextIndex);
-                    difference = Math.max(0, Math.min(DELAY_EFFECT_MAX_INDEX_DIFFERENCE,
-                            difference - 1));
-                    long delay = difference * delayPerElement;
-                    minDelay = Math.max(delay, minDelay);
-                    break;
-                }
-                default:
-                    break;
-            }
-        }
-        return minDelay;
-    }
-
-    private long calculateDelayGoToFullShade(ExpandableViewState viewState) {
-        int shelfIndex = mShelf.getNotGoneIndex();
-        float index = viewState.notGoneIndex;
-        long result = 0;
-        if (index > shelfIndex) {
-            float diff = index - shelfIndex;
-            diff = (float) Math.pow(diff, 0.7f);
-            result += (long) (diff * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE * 0.25);
-            index = shelfIndex;
-        }
-        index = (float) Math.pow(index, 0.7f);
-        result += (long) (index * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE);
-        return result;
-    }
-
-    /**
-     * @return an adapter which ensures that onAnimationFinished is called once no animation is
-     *         running anymore
-     */
-    private AnimatorListenerAdapter getGlobalAnimationFinishedListener() {
-        if (!mAnimationListenerPool.empty()) {
-            return mAnimationListenerPool.pop();
-        }
-
-        // We need to create a new one, no reusable ones found
-        return new AnimatorListenerAdapter() {
-            private boolean mWasCancelled;
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mAnimatorSet.remove(animation);
-                if (mAnimatorSet.isEmpty() && !mWasCancelled) {
-                    onAnimationFinished();
-                }
-                mAnimationListenerPool.push(this);
-            }
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                mWasCancelled = true;
-            }
-
-            @Override
-            public void onAnimationStart(Animator animation) {
-                mWasCancelled = false;
-                mAnimatorSet.add(animation);
-            }
-        };
-    }
-
-    private void onAnimationFinished() {
-        mHostLayout.onChildAnimationFinished();
-
-        for (ExpandableView transientViewsToRemove : mTransientViewsToRemove) {
-            transientViewsToRemove.getTransientContainer()
-                    .removeTransientView(transientViewsToRemove);
-        }
-        mTransientViewsToRemove.clear();
-    }
-
-    /**
-     * Process the animationEvents for a new animation
-     *
-     * @param animationEvents the animation events for the animation to perform
-     * @param finalState the final state to animate to
-     */
-    private void processAnimationEvents(
-            ArrayList<NotificationStackScrollLayout.AnimationEvent> animationEvents,
-            StackScrollState finalState) {
-        for (NotificationStackScrollLayout.AnimationEvent event : animationEvents) {
-            final ExpandableView changingView = (ExpandableView) event.changingView;
-            if (event.animationType ==
-                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD) {
-
-                // This item is added, initialize it's properties.
-                ExpandableViewState viewState = finalState
-                        .getViewStateForView(changingView);
-                if (viewState == null || viewState.gone) {
-                    // The position for this child was never generated, let's continue.
-                    continue;
-                }
-                viewState.applyToView(changingView);
-                mNewAddChildren.add(changingView);
-
-            } else if (event.animationType ==
-                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE) {
-                if (changingView.getVisibility() != View.VISIBLE) {
-                    removeTransientView(changingView);
-                    continue;
-                }
-
-                // Find the amount to translate up. This is needed in order to understand the
-                // direction of the remove animation (either downwards or upwards)
-                ExpandableViewState viewState = finalState
-                        .getViewStateForView(event.viewAfterChangingView);
-                int actualHeight = changingView.getActualHeight();
-                // upwards by default
-                float translationDirection = -1.0f;
-                if (viewState != null) {
-                    float ownPosition = changingView.getTranslationY();
-                    if (changingView instanceof ExpandableNotificationRow
-                            && event.viewAfterChangingView instanceof ExpandableNotificationRow) {
-                        ExpandableNotificationRow changingRow =
-                                (ExpandableNotificationRow) changingView;
-                        ExpandableNotificationRow nextRow =
-                                (ExpandableNotificationRow) event.viewAfterChangingView;
-                        if (changingRow.isRemoved()
-                                && changingRow.wasChildInGroupWhenRemoved()
-                                && !nextRow.isChildInGroup()) {
-                            // the next row isn't actually a child from a group! Let's
-                            // compare absolute positions!
-                            ownPosition = changingRow.getTranslationWhenRemoved();
-                        }
-                    }
-                    // there was a view after this one, Approximate the distance the next child
-                    // travelled
-                    translationDirection = ((viewState.yTranslation
-                            - (ownPosition + actualHeight / 2.0f)) * 2 /
-                            actualHeight);
-                    translationDirection = Math.max(Math.min(translationDirection, 1.0f),-1.0f);
-
-                }
-                changingView.performRemoveAnimation(ANIMATION_DURATION_APPEAR_DISAPPEAR,
-                        0 /* delay */, translationDirection,  false /* isHeadsUpAppear */,
-                        0, new Runnable() {
-                    @Override
-                    public void run() {
-                        removeTransientView(changingView);
-                    }
-                }, null);
-            } else if (event.animationType ==
-                NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT) {
-                if (Math.abs(changingView.getTranslation()) == changingView.getWidth()
-                        && changingView.getTransientContainer() != null) {
-                    changingView.getTransientContainer().removeTransientView(changingView);
-                }
-            } else if (event.animationType == NotificationStackScrollLayout
-                    .AnimationEvent.ANIMATION_TYPE_GROUP_EXPANSION_CHANGED) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) event.changingView;
-                row.prepareExpansionChanged(finalState);
-            } else if (event.animationType == NotificationStackScrollLayout
-                    .AnimationEvent.ANIMATION_TYPE_PULSE_APPEAR) {
-                ExpandableViewState viewState = finalState.getViewStateForView(changingView);
-                if (viewState != null) {
-                    mTmpState.copyFrom(viewState);
-                    mTmpState.yTranslation += mPulsingAppearingTranslation;
-                    mTmpState.alpha = 0;
-                    mTmpState.applyToView(changingView);
-                }
-            } else if (event.animationType == NotificationStackScrollLayout
-                    .AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) {
-                ExpandableViewState viewState = finalState.getViewStateForView(changingView);
-                if (viewState != null) {
-                    viewState.alpha = 0;
-                    // We want to animate the alpha away before the view starts translating,
-                    // otherwise everything will overlap and look xtra ugly.
-                    float originalYTranslation = viewState.yTranslation;
-                    viewState.yTranslation = changingView.getTranslationY();
-                    mAnimationFilter.animateAlpha = true;
-                    mAnimationProperties.duration = ANIMATION_DURATION_PULSE_APPEAR / 2;
-                    viewState.animateTo(changingView, mAnimationProperties);
-                    viewState.yTranslation = originalYTranslation;
-                }
-            } else if (event.animationType == NotificationStackScrollLayout
-                    .AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR) {
-                // This item is added, initialize it's properties.
-                ExpandableViewState viewState = finalState.getViewStateForView(changingView);
-                mTmpState.copyFrom(viewState);
-                if (event.headsUpFromBottom) {
-                    mTmpState.yTranslation = mHeadsUpAppearHeightBottom;
-                } else {
-                    mTmpState.yTranslation = 0;
-                    changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED,
-                            true /* isHeadsUpAppear */);
-                }
-                mHeadsUpAppearChildren.add(changingView);
-                mTmpState.applyToView(changingView);
-            } else if (event.animationType == NotificationStackScrollLayout
-                            .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR ||
-                    event.animationType == NotificationStackScrollLayout
-                            .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
-                mHeadsUpDisappearChildren.add(changingView);
-                Runnable endRunnable = null;
-                // We need some additional delay in case we were removed to make sure we're not
-                // lagging
-                int extraDelay = event.animationType == NotificationStackScrollLayout
-                        .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
-                        ? ANIMATION_DELAY_HEADS_UP_CLICKED
-                        : 0;
-                if (changingView.getParent() == null) {
-                    // This notification was actually removed, so we need to add it transiently
-                    mHostLayout.addTransientView(changingView, 0);
-                    changingView.setTransientContainer(mHostLayout);
-                    mTmpState.initFrom(changingView);
-                    mTmpState.yTranslation = 0;
-                    // We temporarily enable Y animations, the real filter will be combined
-                    // afterwards anyway
-                    mAnimationFilter.animateY = true;
-                    mAnimationProperties.delay = extraDelay + ANIMATION_DELAY_HEADS_UP;
-                    mAnimationProperties.duration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR;
-                    mTmpState.animateTo(changingView, mAnimationProperties);
-                    endRunnable = () -> removeTransientView(changingView);
-                }
-                float targetLocation = 0;
-                boolean needsAnimation = true;
-                if (changingView instanceof ExpandableNotificationRow) {
-                    ExpandableNotificationRow row = (ExpandableNotificationRow) changingView;
-                    if (row.isDismissed()) {
-                        needsAnimation = false;
-                    }
-                    StatusBarIconView icon = row.getEntry().icon;
-                    if (icon.getParent() != null) {
-                        icon.getLocationOnScreen(mTmpLocation);
-                        float iconPosition = mTmpLocation[0] - icon.getTranslationX()
-                                + ViewState.getFinalTranslationX(icon) + icon.getWidth() * 0.25f;
-                        mHostLayout.getLocationOnScreen(mTmpLocation);
-                        targetLocation = iconPosition - mTmpLocation[0];
-                    }
-                }
-
-                if (needsAnimation) {
-                    // We need to add the global animation listener, since once no animations are
-                    // running anymore, the panel will instantly hide itself. We need to wait until
-                    // the animation is fully finished for this though.
-                    changingView.performRemoveAnimation(ANIMATION_DURATION_HEADS_UP_DISAPPEAR
-                                    + ANIMATION_DELAY_HEADS_UP, extraDelay, 0.0f,
-                            true /* isHeadsUpAppear */, targetLocation, endRunnable,
-                            getGlobalAnimationFinishedListener());
-                } else if (endRunnable != null) {
-                    endRunnable.run();
-                }
-            }
-            mNewEvents.add(event);
-        }
-    }
-
-    public static void removeTransientView(ExpandableView viewToRemove) {
-        if (viewToRemove.getTransientContainer() != null) {
-            viewToRemove.getTransientContainer().removeTransientView(viewToRemove);
-        }
-    }
-
-    public void animateOverScrollToAmount(float targetAmount, final boolean onTop,
-            final boolean isRubberbanded) {
-        final float startOverScrollAmount = mHostLayout.getCurrentOverScrollAmount(onTop);
-        if (targetAmount == startOverScrollAmount) {
-            return;
-        }
-        cancelOverScrollAnimators(onTop);
-        ValueAnimator overScrollAnimator = ValueAnimator.ofFloat(startOverScrollAmount,
-                targetAmount);
-        overScrollAnimator.setDuration(ANIMATION_DURATION_STANDARD);
-        overScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                float currentOverScroll = (float) animation.getAnimatedValue();
-                mHostLayout.setOverScrollAmount(
-                        currentOverScroll, onTop, false /* animate */, false /* cancelAnimators */,
-                        isRubberbanded);
-            }
-        });
-        overScrollAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        overScrollAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (onTop) {
-                    mTopOverScrollAnimator = null;
-                } else {
-                    mBottomOverScrollAnimator = null;
-                }
-            }
-        });
-        overScrollAnimator.start();
-        if (onTop) {
-            mTopOverScrollAnimator = overScrollAnimator;
-        } else {
-            mBottomOverScrollAnimator = overScrollAnimator;
-        }
-    }
-
-    public void cancelOverScrollAnimators(boolean onTop) {
-        ValueAnimator currentAnimator = onTop ? mTopOverScrollAnimator : mBottomOverScrollAnimator;
-        if (currentAnimator != null) {
-            currentAnimator.cancel();
-        }
-    }
-
-    public void setHeadsUpAppearHeightBottom(int headsUpAppearHeightBottom) {
-        mHeadsUpAppearHeightBottom = headsUpAppearHeightBottom;
-    }
-
-    public void setShadeExpanded(boolean shadeExpanded) {
-        mShadeExpanded = shadeExpanded;
-    }
-
-    public void setShelf(NotificationShelf shelf) {
-        mShelf = shelf;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
deleted file mode 100644
index 4b3643f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
+++ /dev/null
@@ -1,713 +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.systemui.statusbar.stack;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.ValueAnimator;
-import android.util.Property;
-import android.view.View;
-import android.view.animation.Interpolator;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.ExpandableView;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
-import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.policy.HeadsUpUtil;
-
-/**
- * A state of a view. This can be used to apply a set of view properties to a view with
- * {@link com.android.systemui.statusbar.stack.StackScrollState} or start animations with
- * {@link com.android.systemui.statusbar.stack.StackStateAnimator}.
-*/
-public class ViewState {
-
-    /**
-     * Some animation properties that can be used to update running animations but not creating
-     * any new ones.
-     */
-    protected static final AnimationProperties NO_NEW_ANIMATIONS = new AnimationProperties() {
-        AnimationFilter mAnimationFilter = new AnimationFilter();
-        @Override
-        public AnimationFilter getAnimationFilter() {
-            return mAnimationFilter;
-        }
-    };
-    private static final int TAG_ANIMATOR_TRANSLATION_X = R.id.translation_x_animator_tag;
-    private static final int TAG_ANIMATOR_TRANSLATION_Y = R.id.translation_y_animator_tag;
-    private static final int TAG_ANIMATOR_TRANSLATION_Z = R.id.translation_z_animator_tag;
-    private static final int TAG_ANIMATOR_ALPHA = R.id.alpha_animator_tag;
-    private static final int TAG_END_TRANSLATION_X = R.id.translation_x_animator_end_value_tag;
-    private static final int TAG_END_TRANSLATION_Y = R.id.translation_y_animator_end_value_tag;
-    private static final int TAG_END_TRANSLATION_Z = R.id.translation_z_animator_end_value_tag;
-    private static final int TAG_END_ALPHA = R.id.alpha_animator_end_value_tag;
-    private static final int TAG_START_TRANSLATION_X = R.id.translation_x_animator_start_value_tag;
-    private static final int TAG_START_TRANSLATION_Y = R.id.translation_y_animator_start_value_tag;
-    private static final int TAG_START_TRANSLATION_Z = R.id.translation_z_animator_start_value_tag;
-    private static final int TAG_START_ALPHA = R.id.alpha_animator_start_value_tag;
-
-    private static final AnimatableProperty SCALE_X_PROPERTY
-            = new AnimatableProperty() {
-
-        @Override
-        public int getAnimationStartTag() {
-            return R.id.scale_x_animator_start_value_tag;
-        }
-
-        @Override
-        public int getAnimationEndTag() {
-            return R.id.scale_x_animator_end_value_tag;
-        }
-
-        @Override
-        public int getAnimatorTag() {
-            return R.id.scale_x_animator_tag;
-        }
-
-        @Override
-        public Property getProperty() {
-            return View.SCALE_X;
-        }
-    };
-
-    private static final AnimatableProperty SCALE_Y_PROPERTY
-            = new AnimatableProperty() {
-
-        @Override
-        public int getAnimationStartTag() {
-            return R.id.scale_y_animator_start_value_tag;
-        }
-
-        @Override
-        public int getAnimationEndTag() {
-            return R.id.scale_y_animator_end_value_tag;
-        }
-
-        @Override
-        public int getAnimatorTag() {
-            return R.id.scale_y_animator_tag;
-        }
-
-        @Override
-        public Property getProperty() {
-            return View.SCALE_Y;
-        }
-    };
-
-    public float alpha;
-    public float xTranslation;
-    public float yTranslation;
-    public float zTranslation;
-    public boolean gone;
-    public boolean hidden;
-    public float scaleX = 1.0f;
-    public float scaleY = 1.0f;
-
-    public void copyFrom(ViewState viewState) {
-        alpha = viewState.alpha;
-        xTranslation = viewState.xTranslation;
-        yTranslation = viewState.yTranslation;
-        zTranslation = viewState.zTranslation;
-        gone = viewState.gone;
-        hidden = viewState.hidden;
-        scaleX = viewState.scaleX;
-        scaleY = viewState.scaleY;
-    }
-
-    public void initFrom(View view) {
-        alpha = view.getAlpha();
-        xTranslation = view.getTranslationX();
-        yTranslation = view.getTranslationY();
-        zTranslation = view.getTranslationZ();
-        gone = view.getVisibility() == View.GONE;
-        hidden = view.getVisibility() == View.INVISIBLE;
-        scaleX = view.getScaleX();
-        scaleY = view.getScaleY();
-    }
-
-    /**
-     * Applies a {@link ViewState} to a normal view.
-     */
-    public void applyToView(View view) {
-        if (this.gone) {
-            // don't do anything with it
-            return;
-        }
-
-        // apply xTranslation
-        boolean animatingX = isAnimating(view, TAG_ANIMATOR_TRANSLATION_X);
-        if (animatingX) {
-            updateAnimationX(view);
-        } else if (view.getTranslationX() != this.xTranslation){
-            view.setTranslationX(this.xTranslation);
-        }
-
-        // apply yTranslation
-        boolean animatingY = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y);
-        if (animatingY) {
-            updateAnimationY(view);
-        } else if (view.getTranslationY() != this.yTranslation) {
-            view.setTranslationY(this.yTranslation);
-        }
-
-        // apply zTranslation
-        boolean animatingZ = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Z);
-        if (animatingZ) {
-            updateAnimationZ(view);
-        } else if (view.getTranslationZ() != this.zTranslation) {
-            view.setTranslationZ(this.zTranslation);
-        }
-
-        // apply scaleX
-        boolean animatingScaleX = isAnimating(view, SCALE_X_PROPERTY);
-        if (animatingScaleX) {
-            updateAnimation(view, SCALE_X_PROPERTY, scaleX);
-        } else if (view.getScaleX() != scaleX) {
-            view.setScaleX(scaleX);
-        }
-
-        // apply scaleY
-        boolean animatingScaleY = isAnimating(view, SCALE_Y_PROPERTY);
-        if (animatingScaleY) {
-            updateAnimation(view, SCALE_Y_PROPERTY, scaleY);
-        } else if (view.getScaleY() != scaleY) {
-            view.setScaleY(scaleY);
-        }
-
-        int oldVisibility = view.getVisibility();
-        boolean becomesInvisible = this.alpha == 0.0f
-                || (this.hidden && (!isAnimating(view) || oldVisibility != View.VISIBLE));
-        boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
-        if (animatingAlpha) {
-            updateAlphaAnimation(view);
-        } else if (view.getAlpha() != this.alpha) {
-            // apply layer type
-            boolean becomesFullyVisible = this.alpha == 1.0f;
-            boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
-                    && view.hasOverlappingRendering();
-            int layerType = view.getLayerType();
-            int newLayerType = newLayerTypeIsHardware
-                    ? View.LAYER_TYPE_HARDWARE
-                    : View.LAYER_TYPE_NONE;
-            if (layerType != newLayerType) {
-                view.setLayerType(newLayerType, null);
-            }
-
-            // apply alpha
-            view.setAlpha(this.alpha);
-        }
-
-        // apply visibility
-        int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
-        if (newVisibility != oldVisibility) {
-            if (!(view instanceof ExpandableView) || !((ExpandableView) view).willBeGone()) {
-                // We don't want views to change visibility when they are animating to GONE
-                view.setVisibility(newVisibility);
-            }
-        }
-    }
-
-    public boolean isAnimating(View view) {
-        if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_X)) {
-            return true;
-        }
-        if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y)) {
-            return true;
-        }
-        if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Z)) {
-            return true;
-        }
-        if (isAnimating(view, TAG_ANIMATOR_ALPHA)) {
-            return true;
-        }
-        if (isAnimating(view, SCALE_X_PROPERTY)) {
-            return true;
-        }
-        if (isAnimating(view, SCALE_Y_PROPERTY)) {
-            return true;
-        }
-        return false;
-    }
-
-    private static boolean isAnimating(View view, int tag) {
-        return getChildTag(view, tag) != null;
-    }
-
-    public static boolean isAnimating(View view, AnimatableProperty property) {
-        return getChildTag(view, property.getAnimatorTag()) != null;
-    }
-
-    /**
-     * Start an animation to this viewstate
-     * @param child the view to animate
-     * @param animationProperties the properties of the animation
-     */
-    public void animateTo(View child, AnimationProperties animationProperties) {
-        boolean wasVisible = child.getVisibility() == View.VISIBLE;
-        final float alpha = this.alpha;
-        if (!wasVisible && (alpha != 0 || child.getAlpha() != 0)
-                && !this.gone && !this.hidden) {
-            child.setVisibility(View.VISIBLE);
-        }
-        float childAlpha = child.getAlpha();
-        boolean alphaChanging = this.alpha != childAlpha;
-        if (child instanceof ExpandableView) {
-            // We don't want views to change visibility when they are animating to GONE
-            alphaChanging &= !((ExpandableView) child).willBeGone();
-        }
-
-        // start translationX animation
-        if (child.getTranslationX() != this.xTranslation) {
-            startXTranslationAnimation(child, animationProperties);
-        } else {
-            abortAnimation(child, TAG_ANIMATOR_TRANSLATION_X);
-        }
-
-        // start translationY animation
-        if (child.getTranslationY() != this.yTranslation) {
-            startYTranslationAnimation(child, animationProperties);
-        } else {
-            abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Y);
-        }
-
-        // start translationZ animation
-        if (child.getTranslationZ() != this.zTranslation) {
-            startZTranslationAnimation(child, animationProperties);
-        } else {
-            abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Z);
-        }
-
-        // start scaleX animation
-        if (child.getScaleX() != scaleX) {
-            PropertyAnimator.startAnimation(child, SCALE_X_PROPERTY, scaleX, animationProperties);
-        } else {
-            abortAnimation(child, SCALE_X_PROPERTY.getAnimatorTag());
-        }
-
-        // start scaleX animation
-        if (child.getScaleY() != scaleY) {
-            PropertyAnimator.startAnimation(child, SCALE_Y_PROPERTY, scaleY, animationProperties);
-        } else {
-            abortAnimation(child, SCALE_Y_PROPERTY.getAnimatorTag());
-        }
-
-        // start alpha animation
-        if (alphaChanging) {
-            startAlphaAnimation(child, animationProperties);
-        }  else {
-            abortAnimation(child, TAG_ANIMATOR_ALPHA);
-        }
-    }
-
-    private void updateAlphaAnimation(View view) {
-        startAlphaAnimation(view, NO_NEW_ANIMATIONS);
-    }
-
-    private void startAlphaAnimation(final View child, AnimationProperties properties) {
-        Float previousStartValue = getChildTag(child,TAG_START_ALPHA);
-        Float previousEndValue = getChildTag(child,TAG_END_ALPHA);
-        final float newEndValue = this.alpha;
-        if (previousEndValue != null && previousEndValue == newEndValue) {
-            return;
-        }
-        ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_ALPHA);
-        AnimationFilter filter = properties.getAnimationFilter();
-        if (!filter.animateAlpha) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                float relativeDiff = newEndValue - previousEndValue;
-                float newStartValue = previousStartValue + relativeDiff;
-                values[0].setFloatValues(newStartValue, newEndValue);
-                child.setTag(TAG_START_ALPHA, newStartValue);
-                child.setTag(TAG_END_ALPHA, newEndValue);
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                child.setAlpha(newEndValue);
-                if (newEndValue == 0) {
-                    child.setVisibility(View.INVISIBLE);
-                }
-            }
-        }
-
-        ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.ALPHA,
-                child.getAlpha(), newEndValue);
-        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        // Handle layer type
-        child.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-        animator.addListener(new AnimatorListenerAdapter() {
-            public boolean mWasCancelled;
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                child.setLayerType(View.LAYER_TYPE_NONE, null);
-                if (newEndValue == 0 && !mWasCancelled) {
-                    child.setVisibility(View.INVISIBLE);
-                }
-                // remove the tag when the animation is finished
-                child.setTag(TAG_ANIMATOR_ALPHA, null);
-                child.setTag(TAG_START_ALPHA, null);
-                child.setTag(TAG_END_ALPHA, null);
-            }
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                mWasCancelled = true;
-            }
-
-            @Override
-            public void onAnimationStart(Animator animation) {
-                mWasCancelled = false;
-            }
-        });
-        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
-        animator.setDuration(newDuration);
-        if (properties.delay > 0 && (previousAnimator == null
-                || previousAnimator.getAnimatedFraction() == 0)) {
-            animator.setStartDelay(properties.delay);
-        }
-        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
-        if (listener != null) {
-            animator.addListener(listener);
-        }
-
-        startAnimator(animator, listener);
-        child.setTag(TAG_ANIMATOR_ALPHA, animator);
-        child.setTag(TAG_START_ALPHA, child.getAlpha());
-        child.setTag(TAG_END_ALPHA, newEndValue);
-    }
-
-    private void updateAnimationZ(View view) {
-        startZTranslationAnimation(view, NO_NEW_ANIMATIONS);
-    }
-
-    private void updateAnimation(View view, AnimatableProperty property,
-            float endValue) {
-        PropertyAnimator.startAnimation(view, property, endValue, NO_NEW_ANIMATIONS);
-    }
-
-    private void startZTranslationAnimation(final View child, AnimationProperties properties) {
-        Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Z);
-        Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Z);
-        float newEndValue = this.zTranslation;
-        if (previousEndValue != null && previousEndValue == newEndValue) {
-            return;
-        }
-        ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Z);
-        AnimationFilter filter = properties.getAnimationFilter();
-        if (!filter.animateZ) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                float relativeDiff = newEndValue - previousEndValue;
-                float newStartValue = previousStartValue + relativeDiff;
-                values[0].setFloatValues(newStartValue, newEndValue);
-                child.setTag(TAG_START_TRANSLATION_Z, newStartValue);
-                child.setTag(TAG_END_TRANSLATION_Z, newEndValue);
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                child.setTranslationZ(newEndValue);
-            }
-        }
-
-        ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Z,
-                child.getTranslationZ(), newEndValue);
-        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
-        animator.setDuration(newDuration);
-        if (properties.delay > 0 && (previousAnimator == null
-                || previousAnimator.getAnimatedFraction() == 0)) {
-            animator.setStartDelay(properties.delay);
-        }
-        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
-        if (listener != null) {
-            animator.addListener(listener);
-        }
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                child.setTag(TAG_ANIMATOR_TRANSLATION_Z, null);
-                child.setTag(TAG_START_TRANSLATION_Z, null);
-                child.setTag(TAG_END_TRANSLATION_Z, null);
-            }
-        });
-        startAnimator(animator, listener);
-        child.setTag(TAG_ANIMATOR_TRANSLATION_Z, animator);
-        child.setTag(TAG_START_TRANSLATION_Z, child.getTranslationZ());
-        child.setTag(TAG_END_TRANSLATION_Z, newEndValue);
-    }
-
-    private void updateAnimationX(View view) {
-        startXTranslationAnimation(view, NO_NEW_ANIMATIONS);
-    }
-
-    private void startXTranslationAnimation(final View child, AnimationProperties properties) {
-        Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_X);
-        Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_X);
-        float newEndValue = this.xTranslation;
-        if (previousEndValue != null && previousEndValue == newEndValue) {
-            return;
-        }
-        ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_X);
-        AnimationFilter filter = properties.getAnimationFilter();
-        if (!filter.animateX) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                float relativeDiff = newEndValue - previousEndValue;
-                float newStartValue = previousStartValue + relativeDiff;
-                values[0].setFloatValues(newStartValue, newEndValue);
-                child.setTag(TAG_START_TRANSLATION_X, newStartValue);
-                child.setTag(TAG_END_TRANSLATION_X, newEndValue);
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                child.setTranslationX(newEndValue);
-                return;
-            }
-        }
-
-        ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_X,
-                child.getTranslationX(), newEndValue);
-        Interpolator customInterpolator = properties.getCustomInterpolator(child,
-                View.TRANSLATION_X);
-        Interpolator interpolator =  customInterpolator != null ? customInterpolator
-                : Interpolators.FAST_OUT_SLOW_IN;
-        animator.setInterpolator(interpolator);
-        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
-        animator.setDuration(newDuration);
-        if (properties.delay > 0 && (previousAnimator == null
-                || previousAnimator.getAnimatedFraction() == 0)) {
-            animator.setStartDelay(properties.delay);
-        }
-        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
-        if (listener != null) {
-            animator.addListener(listener);
-        }
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                child.setTag(TAG_ANIMATOR_TRANSLATION_X, null);
-                child.setTag(TAG_START_TRANSLATION_X, null);
-                child.setTag(TAG_END_TRANSLATION_X, null);
-            }
-        });
-        startAnimator(animator, listener);
-        child.setTag(TAG_ANIMATOR_TRANSLATION_X, animator);
-        child.setTag(TAG_START_TRANSLATION_X, child.getTranslationX());
-        child.setTag(TAG_END_TRANSLATION_X, newEndValue);
-    }
-
-    private void updateAnimationY(View view) {
-        startYTranslationAnimation(view, NO_NEW_ANIMATIONS);
-    }
-
-    private void startYTranslationAnimation(final View child, AnimationProperties properties) {
-        Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Y);
-        Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Y);
-        float newEndValue = this.yTranslation;
-        if (previousEndValue != null && previousEndValue == newEndValue) {
-            return;
-        }
-        ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y);
-        AnimationFilter filter = properties.getAnimationFilter();
-        if (!filter.shouldAnimateY(child)) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                float relativeDiff = newEndValue - previousEndValue;
-                float newStartValue = previousStartValue + relativeDiff;
-                values[0].setFloatValues(newStartValue, newEndValue);
-                child.setTag(TAG_START_TRANSLATION_Y, newStartValue);
-                child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                child.setTranslationY(newEndValue);
-                return;
-            }
-        }
-
-        ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Y,
-                child.getTranslationY(), newEndValue);
-        Interpolator customInterpolator = properties.getCustomInterpolator(child,
-                View.TRANSLATION_Y);
-        Interpolator interpolator =  customInterpolator != null ? customInterpolator
-                : Interpolators.FAST_OUT_SLOW_IN;
-        animator.setInterpolator(interpolator);
-        long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
-        animator.setDuration(newDuration);
-        if (properties.delay > 0 && (previousAnimator == null
-                || previousAnimator.getAnimatedFraction() == 0)) {
-            animator.setStartDelay(properties.delay);
-        }
-        AnimatorListenerAdapter listener = properties.getAnimationFinishListener();
-        if (listener != null) {
-            animator.addListener(listener);
-        }
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                HeadsUpUtil.setIsClickedHeadsUpNotification(child, false);
-                child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
-                child.setTag(TAG_START_TRANSLATION_Y, null);
-                child.setTag(TAG_END_TRANSLATION_Y, null);
-                onYTranslationAnimationFinished(child);
-            }
-        });
-        startAnimator(animator, listener);
-        child.setTag(TAG_ANIMATOR_TRANSLATION_Y, animator);
-        child.setTag(TAG_START_TRANSLATION_Y, child.getTranslationY());
-        child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
-    }
-
-    protected void onYTranslationAnimationFinished(View view) {
-        if (hidden && !gone) {
-            view.setVisibility(View.INVISIBLE);
-        }
-    }
-
-    public static void startAnimator(Animator animator, AnimatorListenerAdapter listener) {
-        if (listener != null) {
-            // Even if there's a delay we'd want to notify it of the start immediately.
-            listener.onAnimationStart(animator);
-        }
-        animator.start();
-    }
-
-    public static <T> T getChildTag(View child, int tag) {
-        return (T) child.getTag(tag);
-    }
-
-    protected void abortAnimation(View child, int animatorTag) {
-        Animator previousAnimator = getChildTag(child, animatorTag);
-        if (previousAnimator != null) {
-            previousAnimator.cancel();
-        }
-    }
-
-    /**
-     * Cancel the previous animator and get the duration of the new animation.
-     *
-     * @param duration the new duration
-     * @param previousAnimator the animator which was running before
-     * @return the new duration
-     */
-    public static long cancelAnimatorAndGetNewDuration(long duration,
-            ValueAnimator previousAnimator) {
-        long newDuration = duration;
-        if (previousAnimator != null) {
-            // We take either the desired length of the new animation or the remaining time of
-            // the previous animator, whichever is longer.
-            newDuration = Math.max(previousAnimator.getDuration()
-                    - previousAnimator.getCurrentPlayTime(), newDuration);
-            previousAnimator.cancel();
-        }
-        return newDuration;
-    }
-
-    /**
-     * Get the end value of the xTranslation animation running on a view or the xTranslation
-     * if no animation is running.
-     */
-    public static float getFinalTranslationX(View view) {
-        if (view == null) {
-            return 0;
-        }
-        ValueAnimator xAnimator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_X);
-        if (xAnimator == null) {
-            return view.getTranslationX();
-        } else {
-            return getChildTag(view, TAG_END_TRANSLATION_X);
-        }
-    }
-
-    /**
-     * Get the end value of the yTranslation animation running on a view or the yTranslation
-     * if no animation is running.
-     */
-    public static float getFinalTranslationY(View view) {
-        if (view == null) {
-            return 0;
-        }
-        ValueAnimator yAnimator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Y);
-        if (yAnimator == null) {
-            return view.getTranslationY();
-        } else {
-            return getChildTag(view, TAG_END_TRANSLATION_Y);
-        }
-    }
-
-    /**
-     * Get the end value of the zTranslation animation running on a view or the zTranslation
-     * if no animation is running.
-     */
-    public static float getFinalTranslationZ(View view) {
-        if (view == null) {
-            return 0;
-        }
-        ValueAnimator zAnimator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Z);
-        if (zAnimator == null) {
-            return view.getTranslationZ();
-        } else {
-            return getChildTag(view, TAG_END_TRANSLATION_Z);
-        }
-    }
-
-    public static boolean isAnimatingY(View child) {
-        return getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y) != null;
-    }
-
-    public void cancelAnimations(View view) {
-        Animator animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_X);
-        if (animator != null) {
-            animator.cancel();
-        }
-        animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Y);
-        if (animator != null) {
-            animator.cancel();
-        }
-        animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Z);
-        if (animator != null) {
-            animator.cancel();
-        }
-        animator = getChildTag(view, TAG_ANIMATOR_ALPHA);
-        if (animator != null) {
-            animator.cancel();
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 526e69b..1d4f9b3 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -15,21 +15,25 @@
  */
 package com.android.systemui.tuner;
 
+import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentTransaction;
 import android.os.Bundle;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
 import android.util.Log;
 import android.view.MenuItem;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Toolbar;
 
-import com.android.settingslib.drawer.SettingsDrawerActivity;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceScreen;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.fragments.FragmentService;
 
-public class TunerActivity extends SettingsDrawerActivity implements
+public class TunerActivity extends Activity implements
         PreferenceFragment.OnPreferenceStartFragmentCallback,
         PreferenceFragment.OnPreferenceStartScreenCallback {
 
@@ -37,6 +41,15 @@
 
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        setContentView(R.layout.tuner_activity);
+        Toolbar toolbar = findViewById(R.id.action_bar);
+        if (toolbar != null) {
+            setActionBar(toolbar);
+        }
+
         Dependency.initDependencies(this);
 
         if (getFragmentManager().findFragmentByTag(TAG_TUNER) == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 1bdb7ad..196d9bc 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -119,7 +119,9 @@
         // 3 Removed because of a revert.
         if (oldVersion < 4) {
             // Delay this so that we can wait for everything to be registered first.
-            new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(() -> clearAll(), 5000);
+            final int user = mCurrentUser;
+            new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(
+                    () -> clearAllFromUser(user), 5000);
         }
         setValue(TUNER_VERSION, newVersion);
     }
@@ -221,6 +223,10 @@
 
     @Override
     public void clearAll() {
+        clearAllFromUser(mCurrentUser);
+    }
+
+    public void clearAllFromUser(int user) {
         // A couple special cases.
         Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
         Intent intent = new Intent(DemoMode.ACTION_DEMO);
@@ -231,7 +237,7 @@
             if (ArrayUtils.contains(RESET_BLACKLIST, key)) {
                 continue;
             }
-            Settings.Secure.putString(mContentResolver, key, null);
+            Settings.Secure.putStringForUser(mContentResolver, key, null, user);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
index a901e88..b835909 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
@@ -23,7 +23,7 @@
  */
 public class DelayedWakeLock implements WakeLock {
 
-    private static final long RELEASE_DELAY_MS = 140;
+    private static final long RELEASE_DELAY_MS = 100;
 
     private final Handler mHandler;
     private final WakeLock mInner;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 4a9856b..2cbb78a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -351,11 +351,11 @@
     listItem.setOnSeekBarChangeListener(
         new CarVolumeDialogImpl.VolumeSeekBarChangeListener(volumeGroupId, mCarAudioManager));
     Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon);
-    primaryIcon.setTint(color);
+    primaryIcon.mutate().setTint(color);
     listItem.setPrimaryActionIcon(primaryIcon);
     if (supplementalIconId != 0) {
       Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId);
-      supplementalIcon.setTint(color);
+      supplementalIcon.mutate().setTint(color);
       listItem.setSupplementalIcon(supplementalIcon, true,
           supplementalIconOnClickListener);
     } else {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
index d7c4bbf..c97095e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
@@ -21,11 +21,13 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Resources.NotFoundException;
 import android.media.AudioManager;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.WindowManager;
 
+
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 abstract public class SafetyWarningDialog extends SystemUIDialog
@@ -40,12 +42,18 @@
 
     private long mShowTime;
     private boolean mNewVolumeUp;
+    private boolean mDisableOnVolumeUp;
 
     public SafetyWarningDialog(Context context, AudioManager audioManager) {
         super(context);
         mContext = context;
         mAudioManager = audioManager;
-
+        try {
+            mDisableOnVolumeUp = mContext.getResources().getBoolean(
+                  com.android.internal.R.bool.config_safe_media_disable_on_volume_up);
+        } catch (NotFoundException e) {
+            mDisableOnVolumeUp = true;
+        }
         getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
         setShowForAllUsers(true);
         setMessage(mContext.getString(com.android.internal.R.string.safe_media_volume_warning));
@@ -63,7 +71,8 @@
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && event.getRepeatCount() == 0) {
+        if (mDisableOnVolumeUp && keyCode == KeyEvent.KEYCODE_VOLUME_UP
+            && event.getRepeatCount() == 0) {
             mNewVolumeUp = true;
         }
         return super.onKeyDown(keyCode, event);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index dd55264..2861dff 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -61,7 +61,7 @@
     private final VolumeDialogControllerImpl mController;
     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
             ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
-            | ActivityInfo.CONFIG_ASSETS_PATHS);
+            | ActivityInfo.CONFIG_ASSETS_PATHS | ActivityInfo.CONFIG_UI_MODE);
     private VolumeDialog mDialog;
     private VolumePolicy mVolumePolicy = new VolumePolicy(
             DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT,  // volumeDownToEnterSilent
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 955939c..13c43f7 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -40,13 +40,13 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
 import android.graphics.drawable.ColorDrawable;
 import android.media.AudioManager;
 import android.media.AudioSystem;
@@ -63,7 +63,6 @@
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.view.ContextThemeWrapper;
-import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
@@ -92,7 +91,6 @@
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.plugins.VolumeDialogController.State;
 import com.android.systemui.plugins.VolumeDialogController.StreamState;
-import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
@@ -149,6 +147,8 @@
     private State mState;
     private SafetyWarningDialog mSafetyWarning;
     private boolean mHovering = false;
+    private boolean mShowActiveStreamOnly;
+    private boolean mConfigChanged = false;
 
     public VolumeDialogImpl(Context context) {
         mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
@@ -156,6 +156,7 @@
         mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
         mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
+        mShowActiveStreamOnly = showActiveStreamOnly();
     }
 
     public void init(int windowType, Callback callback) {
@@ -193,16 +194,16 @@
                 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
         mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
         mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast);
-        final WindowManager.LayoutParams lp = mWindow.getAttributes();
+        WindowManager.LayoutParams lp = mWindow.getAttributes();
         lp.format = PixelFormat.TRANSLUCENT;
         lp.setTitle(VolumeDialogImpl.class.getSimpleName());
-        lp.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
         lp.windowAnimations = -1;
         mWindow.setAttributes(lp);
         mWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
 
-        mDialog.setCanceledOnTouchOutside(true);
         mDialog.setContentView(R.layout.volume_dialog);
+        mDialogView = mDialog.findViewById(R.id.volume_dialog);
+        mDialog.setCanceledOnTouchOutside(true);
         mDialog.setOnShowListener(dialog -> {
             if (!isLandscape()) mDialogView.setTranslationX(mDialogView.getWidth() / 2);
             mDialogView.setAlpha(0);
@@ -213,12 +214,14 @@
                     .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
                     .withEndAction(() -> {
                         if (!Prefs.getBoolean(mContext, Prefs.Key.TOUCHED_RINGER_TOGGLE, false)) {
-                            mRingerIcon.postOnAnimationDelayed(mSinglePress, 1500);
+                            if (mRingerIcon != null) {
+                                mRingerIcon.postOnAnimationDelayed(mSinglePress, 1500);
+                            }
                         }
                     })
                     .start();
         });
-        mDialogView = mDialog.findViewById(R.id.volume_dialog);
+
         mDialogView.setOnHoverListener((v, event) -> {
             int action = event.getActionMasked();
             mHovering = (action == MotionEvent.ACTION_HOVER_ENTER)
@@ -227,6 +230,10 @@
             return true;
         });
 
+        lp = mWindow.getAttributes();
+        lp.gravity = ((FrameLayout.LayoutParams) mDialogView.getLayoutParams()).gravity;
+        mWindow.setAttributes(lp);
+
         mActiveTint = Utils.getColorAccent(mContext);
         mActiveAlpha = Color.alpha(mActiveTint.getDefaultColor());
         mInactiveTint = Utils.getColorAttr(mContext, android.R.attr.colorForeground);
@@ -234,8 +241,10 @@
 
         mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
         mRinger = mDialog.findViewById(R.id.ringer);
-        mRingerIcon = mRinger.findViewById(R.id.ringer_icon);
-        mZenIcon = mRinger.findViewById(R.id.dnd_icon);
+        if (mRinger != null) {
+            mRingerIcon = mRinger.findViewById(R.id.ringer_icon);
+            mZenIcon = mRinger.findViewById(R.id.dnd_icon);
+        }
         mSettingsView = mDialog.findViewById(R.id.settings_container);
         mSettingsIcon = mDialog.findViewById(R.id.settings);
 
@@ -420,49 +429,56 @@
     }
 
     public void initSettingsH() {
-        mSettingsView.setVisibility(
-                mDeviceProvisionedController.isCurrentUserSetup() ? VISIBLE : GONE);
-        mSettingsIcon.setOnClickListener(v -> {
-            Events.writeEvent(mContext, Events.EVENT_SETTINGS_CLICK);
-            Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            dismissH(DISMISS_REASON_SETTINGS_CLICKED);
-            Dependency.get(ActivityStarter.class).startActivity(intent, true /* dismissShade */);
-        });
+        if (mSettingsView != null) {
+            mSettingsView.setVisibility(
+                    mDeviceProvisionedController.isCurrentUserSetup() ? VISIBLE : GONE);
+        }
+        if (mSettingsIcon != null) {
+            mSettingsIcon.setOnClickListener(v -> {
+                Events.writeEvent(mContext, Events.EVENT_SETTINGS_CLICK);
+                Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS);
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                dismissH(DISMISS_REASON_SETTINGS_CLICKED);
+                Dependency.get(ActivityStarter.class).startActivity(intent,
+                        true /* dismissShade */);
+            });
+        }
     }
 
     public void initRingerH() {
-        mRingerIcon.setOnClickListener(v -> {
-            Prefs.putBoolean(mContext, Prefs.Key.TOUCHED_RINGER_TOGGLE, true);
-            final StreamState ss = mState.states.get(AudioManager.STREAM_RING);
-            if (ss == null) {
-                return;
-            }
-            // normal -> vibrate -> silent -> normal (skip vibrate if device doesn't have
-            // a vibrator.
-            int newRingerMode;
-            final boolean hasVibrator = mController.hasVibrator();
-            if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
-                if (hasVibrator) {
-                    newRingerMode = AudioManager.RINGER_MODE_VIBRATE;
-                } else {
+        if (mRingerIcon != null) {
+            mRingerIcon.setOnClickListener(v -> {
+                Prefs.putBoolean(mContext, Prefs.Key.TOUCHED_RINGER_TOGGLE, true);
+                final StreamState ss = mState.states.get(AudioManager.STREAM_RING);
+                if (ss == null) {
+                    return;
+                }
+                // normal -> vibrate -> silent -> normal (skip vibrate if device doesn't have
+                // a vibrator.
+                int newRingerMode;
+                final boolean hasVibrator = mController.hasVibrator();
+                if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+                    if (hasVibrator) {
+                        newRingerMode = AudioManager.RINGER_MODE_VIBRATE;
+                    } else {
+                        newRingerMode = AudioManager.RINGER_MODE_SILENT;
+                    }
+                } else if (mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
                     newRingerMode = AudioManager.RINGER_MODE_SILENT;
+                } else {
+                    newRingerMode = AudioManager.RINGER_MODE_NORMAL;
+                    if (ss.level == 0) {
+                        mController.setStreamVolume(AudioManager.STREAM_RING, 1);
+                    }
                 }
-            } else if (mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
-                newRingerMode = AudioManager.RINGER_MODE_SILENT;
-            } else {
-                newRingerMode = AudioManager.RINGER_MODE_NORMAL;
-                if (ss.level == 0) {
-                    mController.setStreamVolume(AudioManager.STREAM_RING, 1);
-                }
-            }
-            Events.writeEvent(mContext, Events.EVENT_RINGER_TOGGLE, newRingerMode);
-            incrementManualToggleCount();
-            updateRingerH();
-            provideTouchFeedbackH(newRingerMode);
-            mController.setRingerMode(newRingerMode, false);
-            maybeShowToastH(newRingerMode);
-        });
+                Events.writeEvent(mContext, Events.EVENT_RINGER_TOGGLE, newRingerMode);
+                incrementManualToggleCount();
+                updateRingerH();
+                provideTouchFeedbackH(newRingerMode);
+                mController.setRingerMode(newRingerMode, false);
+                maybeShowToastH(newRingerMode);
+            });
+        }
         updateRingerH();
     }
 
@@ -536,6 +552,11 @@
         rescheduleTimeoutH();
         mShowing = true;
 
+        if (mConfigChanged) {
+            initDialog();
+            mConfigurableTexts.update();
+            mConfigChanged = false;
+        }
         initSettingsH();
         mDialog.show();
         Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
@@ -587,29 +608,37 @@
         }
     }
 
+    private boolean showActiveStreamOnly() {
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+                || mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION);
+    }
+
     private boolean shouldBeVisibleH(VolumeRow row, VolumeRow activeRow) {
         boolean isActive = row.stream == activeRow.stream;
-        if (row.stream == AudioSystem.STREAM_ACCESSIBILITY) {
-            return mShowA11yStream;
-        }
-
-        // if the active row is accessibility, then continue to display previous
-        // active row since accessibility is displayed under it
-        if (activeRow.stream == AudioSystem.STREAM_ACCESSIBILITY &&
-                row.stream == mPrevActiveStream) {
-            return true;
-        }
 
         if (isActive) {
             return true;
         }
 
-        if (row.defaultStream) {
-            return activeRow.stream == STREAM_RING
-                    || activeRow.stream == STREAM_ALARM
-                    || activeRow.stream == STREAM_VOICE_CALL
-                    || activeRow.stream == STREAM_ACCESSIBILITY
-                    || mDynamic.get(activeRow.stream);
+        if (!mShowActiveStreamOnly) {
+            if (row.stream == AudioSystem.STREAM_ACCESSIBILITY) {
+                return mShowA11yStream;
+            }
+
+            // if the active row is accessibility, then continue to display previous
+            // active row since accessibility is displayed under it
+            if (activeRow.stream == AudioSystem.STREAM_ACCESSIBILITY &&
+                    row.stream == mPrevActiveStream) {
+                return true;
+            }
+
+            if (row.defaultStream) {
+                return activeRow.stream == STREAM_RING
+                        || activeRow.stream == STREAM_ALARM
+                        || activeRow.stream == STREAM_VOICE_CALL
+                        || activeRow.stream == STREAM_ACCESSIBILITY
+                        || mDynamic.get(activeRow.stream);
+            }
         }
 
         return false;
@@ -721,8 +750,12 @@
      * @param enable whether to enable ringer views and hide dnd icon
      */
     private void enableRingerViewsH(boolean enable) {
-        mRingerIcon.setEnabled(enable);
-        mZenIcon.setVisibility(enable ? GONE : VISIBLE);
+        if (mRingerIcon != null) {
+            mRingerIcon.setEnabled(enable);
+        }
+        if (mZenIcon != null) {
+            mZenIcon.setVisibility(enable ? GONE : VISIBLE);
+        }
     }
 
     private void trimObsoleteH() {
@@ -1029,15 +1062,19 @@
     private Runnable mSinglePress = new Runnable() {
         @Override
         public void run() {
-            mRingerIcon.setPressed(true);
-            mRingerIcon.postOnAnimationDelayed(mSingleUnpress, 200);
+            if (mRingerIcon != null) {
+                mRingerIcon.setPressed(true);
+                mRingerIcon.postOnAnimationDelayed(mSingleUnpress, 200);
+            }
         }
     };
 
     private Runnable mSingleUnpress = new Runnable() {
         @Override
         public void run() {
-            mRingerIcon.setPressed(false);
+            if (mRingerIcon != null) {
+                mRingerIcon.setPressed(false);
+            }
         }
     };
 
@@ -1071,8 +1108,7 @@
         @Override
         public void onConfigurationChanged() {
             mDialog.dismiss();
-            initDialog();
-            mConfigurableTexts.update();
+            mConfigChanged = true;
         }
 
         @Override
@@ -1159,7 +1195,7 @@
 
         @Override
         public boolean onTouchEvent(MotionEvent event) {
-            if (isShowing()) {
+            if (mShowing) {
                 if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
                     dismissH(Events.DISMISS_REASON_TOUCH_OUTSIDE);
                     return true;
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index a4120c4..6057614 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -21,48 +21,12 @@
 LOCAL_JACK_FLAGS := --multi-dex native
 LOCAL_DX_FLAGS := --multi-dex
 
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_PROTOC_FLAGS := -I$(LOCAL_PATH)/..
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
-
 LOCAL_PACKAGE_NAME := SystemUITests
 LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-    $(call all-Iaidl-files-under, src) \
-    $(call all-java-files-under, ../src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
-    frameworks/base/packages/SystemUI/res \
-    frameworks/base/packages/SystemUI/res-keyguard \
-
 LOCAL_STATIC_ANDROID_LIBRARIES := \
-    SystemUIPluginLib \
-    SystemUISharedLib \
-    androidx.car_car \
-    androidx.legacy_legacy-support-v4 \
-    androidx.recyclerview_recyclerview \
-    androidx.preference_preference \
-    androidx.appcompat_appcompat \
-    androidx.mediarouter_mediarouter \
-    androidx.palette_palette \
-    androidx.legacy_legacy-preference-v14 \
-    androidx.leanback_leanback \
-    androidx.slice_slice-core \
-    androidx.slice_slice-view \
-    androidx.slice_slice-builders \
-    androidx.arch.core_core-runtime \
-    androidx.lifecycle_lifecycle-extensions \
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    metrics-helper-lib \
-    android-support-test \
-    mockito-target-inline-minus-junit4 \
-    SystemUI-proto \
-    SystemUI-tags \
-    testables \
-    truth-prebuilt \
+    SystemUI-tests
 
 LOCAL_MULTILIB := both
 
@@ -70,7 +34,6 @@
     libdexmakerjvmtiagent \
     libmultiplejvmtiagentsinterferenceagent
 
-
 LOCAL_JAVA_LIBRARIES := \
     android.test.runner \
     telephony-common \
@@ -112,8 +75,6 @@
 LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.systemui.*
 LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := com.android.systemui.tests.*,$(jacoco_exclude)
 
-include frameworks/base/packages/SettingsLib/common.mk
-
 ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
     include $(BUILD_PACKAGE)
 endif
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 1be8322..8b1324a 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -15,6 +15,8 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     package="com.android.systemui.tests">
 
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
@@ -49,6 +51,7 @@
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS" />
 
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
@@ -63,6 +66,27 @@
                 <action android:name="com.android.systemui.action.TEST_ACTION" />
             </intent-filter>
         </receiver>
+
+        <provider
+            android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
+            tools:replace="android:authorities"
+            android:authorities="${applicationId}.lifecycle-tests"
+            android:exported="false"
+            android:enabled="false"
+            android:multiprocess="true" />
+        <provider android:name="com.android.systemui.keyguard.KeyguardSliceProvider"
+            android:authorities="com.android.systemui.test.keyguard.disabled"
+            android:enabled="false"
+            tools:replace="android:authorities"
+            tools:node="remove" />
+
+        <provider
+            android:name="androidx.core.content.FileProvider"
+            android:authorities="com.android.systemui.test.fileprovider"
+            android:exported="false"
+            android:enabled="false"
+            tools:replace="android:authorities"
+            android:grantUriPermissions="true" />
     </application>
 
     <instrumentation android:name="android.testing.TestableInstrumentation"
diff --git a/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java b/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
index 6792bc0..7f83ed6 100644
--- a/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
+++ b/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
 
+import android.content.pm.PackageManager;
 import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
@@ -115,6 +116,13 @@
         filter.add(new ExternalClassNameFilter());
         filter.add(s -> s.startsWith("com.android.systemui")
                 || s.startsWith("com.android.keyguard"));
+
+
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            // If it's not automotive target, exclude automotive classes from the test.
+            excludeAutomotiveClasses(filter);
+        }
+
         try {
             return scanner.getClassPathEntries(filter);
         } catch (IOException e) {
@@ -123,6 +131,13 @@
         return Collections.emptyList();
     }
 
+    private void excludeAutomotiveClasses(ChainedClassNameFilter filter) {
+        // Modifies the passed in filter.
+        filter.add(s -> !s.startsWith("com.android.systemui.statusbar.car."));
+        filter.add(s -> !s.startsWith("com.android.systemui.qs.car."));
+        filter.add(s -> !s.startsWith("com.android.systemui.car."));
+    }
+
     private String getClsStr() {
         return TextUtils.join(",", Arrays.asList(BASE_CLS_WHITELIST)
                 .stream().map(cls -> cls.getSimpleName()).toArray());
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
new file mode 100644
index 0000000..e6e4857
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.keyguard;
+
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Color;
+import android.graphics.Paint.Style;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.text.TextPaint;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.TextClock;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidTestingRunner.class)
+public class KeyguardClockSwitchTest extends SysuiTestCase {
+    private PluginManager mPluginManager;
+
+    @Mock
+    TextClock mClockView;
+    @InjectMocks
+    KeyguardClockSwitch mKeyguardClockSwitch;
+
+    @Before
+    public void setUp() {
+        mPluginManager = mDependency.injectMockDependency(PluginManager.class);
+        LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+        mKeyguardClockSwitch =
+                (KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void onAttachToWindow_addPluginListener() {
+        mKeyguardClockSwitch.onAttachedToWindow();
+
+        ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class);
+        verify(mPluginManager).addPluginListener(listener.capture(), eq(ClockPlugin.class));
+    }
+
+    @Test
+    public void onDetachToWindow_removePluginListener() {
+        mKeyguardClockSwitch.onDetachedFromWindow();
+
+        ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class);
+        verify(mPluginManager).removePluginListener(listener.capture());
+    }
+
+    @Test
+    public void onPluginConnected_showPluginClock() {
+        ClockPlugin plugin = mock(ClockPlugin.class);
+        TextClock pluginView = new TextClock(getContext());
+        when(plugin.getView()).thenReturn(pluginView);
+        TextPaint paint = mock(TextPaint.class);
+        doReturn(paint).when(mClockView).getPaint();
+        PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+
+        listener.onPluginConnected(plugin, null);
+
+        verify(mClockView).setVisibility(GONE);
+        assertThat(plugin.getView().getParent()).isEqualTo(mKeyguardClockSwitch);
+    }
+
+    @Test
+    public void onPluginDisconnected_showDefaultClock() {
+        ClockPlugin plugin = mock(ClockPlugin.class);
+        TextClock pluginView = new TextClock(getContext());
+        when(plugin.getView()).thenReturn(pluginView);
+        mClockView.setVisibility(GONE);
+        mKeyguardClockSwitch.addView(plugin.getView(), -1,
+                new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT));
+        PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+
+        listener.onPluginDisconnected(plugin);
+
+        verify(mClockView).setVisibility(VISIBLE);
+        assertThat(plugin.getView().getParent()).isNull();
+    }
+
+    @Test
+    public void setTextColor_defaultClockSetTextColor() {
+        mKeyguardClockSwitch.setTextColor(Color.YELLOW);
+
+        verify(mClockView).setTextColor(Color.YELLOW);
+    }
+
+    @Test
+    public void setTextColor_pluginClockSetTextColor() {
+        ClockPlugin plugin = mock(ClockPlugin.class);
+        TextClock pluginView = new TextClock(getContext());
+        when(plugin.getView()).thenReturn(pluginView);
+        TextPaint paint = mock(TextPaint.class);
+        doReturn(paint).when(mClockView).getPaint();
+        PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+        listener.onPluginConnected(plugin, null);
+
+        mKeyguardClockSwitch.setTextColor(Color.WHITE);
+
+        verify(plugin).setTextColor(Color.WHITE);
+    }
+
+    @Test
+    public void setStyle_defaultClockSetStyle() {
+        TextPaint paint = mock(TextPaint.class);
+        Style style = mock(Style.class);
+        doReturn(paint).when(mClockView).getPaint();
+
+        mKeyguardClockSwitch.setStyle(style);
+
+        verify(paint).setStyle(style);
+    }
+
+    @Test
+    public void setStyle_pluginClockSetStyle() {
+        ClockPlugin plugin = mock(ClockPlugin.class);
+        TextClock pluginView = new TextClock(getContext());
+        when(plugin.getView()).thenReturn(pluginView);
+        TextPaint paint = mock(TextPaint.class);
+        doReturn(paint).when(mClockView).getPaint();
+        Style style = mock(Style.class);
+        PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+        listener.onPluginConnected(plugin, null);
+
+        mKeyguardClockSwitch.setStyle(style);
+
+        verify(plugin).setStyle(style);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
index d2e8371..4ec30fd 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
@@ -55,7 +55,7 @@
 
     @Test
     public void showSlice_notifiesListener() {
-        ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
+        ListBuilder builder = new ListBuilder(getContext(), mSliceUri, ListBuilder.INFINITY);
         AtomicBoolean notified = new AtomicBoolean();
         mKeyguardSliceView.setContentChangeListener(()-> notified.set(true));
         mKeyguardSliceView.onChanged(builder.build());
@@ -74,13 +74,11 @@
 
     @Test
     public void hasHeader_readsSliceData() {
-        ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
+        ListBuilder builder = new ListBuilder(getContext(), mSliceUri, ListBuilder.INFINITY);
         mKeyguardSliceView.onChanged(builder.build());
         Assert.assertFalse("View should not have a header", mKeyguardSliceView.hasHeader());
 
-        builder.setHeader((ListBuilder.HeaderBuilder headerBuilder) -> {
-            headerBuilder.setTitle("header title!");
-        });
+        builder.setHeader(new ListBuilder.HeaderBuilder().setTitle("header title!"));
         mKeyguardSliceView.onChanged(builder.build());
         Assert.assertTrue("View should have a header", mKeyguardSliceView.hasHeader());
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
index 1d8de2f..9e96df2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
@@ -22,7 +22,6 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.LayoutInflater;
-import android.widget.TextClock;
 
 import com.android.systemui.SysuiTestCase;
 
@@ -40,7 +39,7 @@
     @Mock
     KeyguardSliceView mKeyguardSlice;
     @Mock
-    TextClock mClockView;
+    KeyguardClockSwitch mClockView;
     @InjectMocks
     KeyguardStatusView mKeyguardStatusView;
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index d46a9747..2055519 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -16,14 +16,22 @@
 
 package com.android.keyguard;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.truth.Truth.*;
+
 import android.content.Context;
 import android.content.Intent;
+import android.os.Bundle;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.SysuiTestCase;
 
@@ -70,6 +78,184 @@
                 keyguardUpdateMonitor.hasSimStateJustChanged());
     }
 
+    @Test
+    public void testTelephonyCapable_BootInitState() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimState_Absent() {
+        Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_ABSENT);
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent,null, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isTrue();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimInvalid_ServiceState_InService() {
+        // SERVICE_STATE - IN_SERVICE, but SIM_STATE is invalid TelephonyCapable should be False
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_IN_SERVICE);
+        state.fillInNotifierBundle(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimValid_ServiceState_PowerOff() {
+        // Simulate AirplaneMode case, SERVICE_STATE - POWER_OFF, check TelephonyCapable False
+        // Only receive ServiceState callback IN_SERVICE -> OUT_OF_SERVICE -> POWER_OFF
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_LOADED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_POWER_OFF);
+        state.fillInNotifierBundle(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, true));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isTrue();
+    }
+
+    /* Normal SIM inserted flow
+     * ServiceState:    ---OutOfServie----->PowerOff->OutOfServie--->InService
+     * SimState:        ----NOT_READY---->READY----------------------LOADED>>>
+     * Subscription:    --------null---->null--->"Chunghwa Telecom"-------->>>
+     * System:          -------------------------------BOOT_COMPLETED------>>>
+     * TelephonyCapable:(F)-(F)-(F)-(F)-(F)-(F)-(F)-(F)-(F)-(F)------(T)-(T)>>
+     */
+    @Test
+    public void testTelephonyCapable_BootInitState_ServiceState_OutOfService() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_OUT_OF_SERVICE);
+        state.fillInNotifierBundle(data);
+        intent.putExtras(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_BootInitState_SimState_NotReady() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_OUT_OF_SERVICE);
+        state.fillInNotifierBundle(data);
+        Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_NOT_READY);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_BootInitState_SimState_Ready() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_OUT_OF_SERVICE);
+        state.fillInNotifierBundle(data);
+        Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_READY);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_BootInitState_ServiceState_PowerOff() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_POWER_OFF);
+        state.fillInNotifierBundle(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimValid_ServiceState_InService() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_IN_SERVICE);
+        state.fillInNotifierBundle(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, true));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isTrue();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimValid_SimState_Loaded() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_IN_SERVICE);
+        state.fillInNotifierBundle(data);
+        Intent intentSimState = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        intentSimState.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_LOADED);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intentSimState, data, true));
+        mTestableLooper.processAllMessages();
+        // Even SimState Loaded, still need ACTION_SERVICE_STATE_CHANGED turn on mTelephonyCapable
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+
+        Intent intentServiceState =  new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        intentSimState.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_LOADED);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intentServiceState, data, true));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isTrue();
+    }
+
+    private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
+        int subscription = simInited
+                ? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE;
+        if (data != null) intent.putExtras(data);
+        intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
+        intent.putExtra("subscription", subscription);
+        intent.putExtra("slot", 0/* SLOT 1 */);
+        return intent;
+    }
+
     private class TestableKeyguardUpdateMonitor extends KeyguardUpdateMonitor {
         AtomicBoolean mSimStateChanged = new AtomicBoolean(false);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
index 08c4235..c180ff8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
@@ -25,7 +25,7 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationTestHelper;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index f1bf31d..cc96917 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -21,6 +21,7 @@
 
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -34,8 +35,10 @@
 
 import android.app.Fragment;
 import android.content.res.Configuration;
+import android.os.Handler;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.Display;
 import android.view.View;
@@ -60,6 +63,7 @@
 @SmallTest
 public class ScreenDecorationsTest extends SysuiTestCase {
 
+    private TestableLooper mTestableLooper;
     private ScreenDecorations mScreenDecorations;
     private StatusBar mStatusBar;
     private WindowManager mWindowManager;
@@ -71,6 +75,10 @@
 
     @Before
     public void setup() {
+        mTestableLooper = TestableLooper.get(this);
+        mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+                new Handler(mTestableLooper.getLooper()));
+
         mStatusBar = mock(StatusBar.class);
         mWindowManager = mock(WindowManager.class);
         mView = spy(new StatusBarWindowView(mContext, null));
@@ -88,7 +96,31 @@
 
         mTunerService = mDependency.injectMockDependency(TunerService.class);
 
-        mScreenDecorations = new ScreenDecorations();
+
+        mScreenDecorations = new ScreenDecorations() {
+            @Override
+            public void start() {
+                super.start();
+                mTestableLooper.processAllMessages();
+            }
+
+            @Override
+            Handler startHandlerThread() {
+                return new Handler(mTestableLooper.getLooper());
+            }
+
+            @Override
+            protected void onConfigurationChanged(Configuration newConfig) {
+                super.onConfigurationChanged(newConfig);
+                mTestableLooper.processAllMessages();
+            }
+
+            @Override
+            public void onTuningChanged(String key, String newValue) {
+                super.onTuningChanged(key, newValue);
+                mTestableLooper.processAllMessages();
+            }
+        };
         mScreenDecorations.mContext = mContext;
         mScreenDecorations.mComponents = mContext.getComponents();
 
@@ -195,4 +227,17 @@
         verify(padding).destroy();
     }
 
+    @Test
+    public void testUpdateRoundedCorners() {
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
+        mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 20);
+
+        mScreenDecorations.start();
+        assertEquals(mScreenDecorations.mRoundedDefault, 20);
+
+        mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 5);
+        mScreenDecorations.onConfigurationChanged(null);
+        assertEquals(mScreenDecorations.mRoundedDefault, 5);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index 62d80ac..f45500a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -45,12 +45,12 @@
         boolean[] doneHolder = new boolean[1];
         AmbientDisplayConfiguration config = mock(AmbientDisplayConfiguration.class,
                 noDefaultAnswer(doneHolder));
-        when(config.pulseOnDoubleTapEnabled(anyInt())).thenReturn(false);
-        when(config.pulseOnPickupEnabled(anyInt())).thenReturn(false);
+        when(config.doubleTapGestureEnabled(anyInt())).thenReturn(false);
+        when(config.pickupGestureEnabled(anyInt())).thenReturn(false);
         when(config.pulseOnNotificationEnabled(anyInt())).thenReturn(true);
 
         when(config.doubleTapSensorType()).thenReturn(null);
-        when(config.pulseOnPickupAvailable()).thenReturn(false);
+        when(config.dozePickupSensorAvailable()).thenReturn(false);
 
         doneHolder[0] = true;
         return config;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index 5e12781..eaa0dcf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -34,6 +34,8 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.PowerManager;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -60,6 +62,9 @@
 
     @Before
     public void setUp() throws Exception {
+        Settings.System.putIntForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS, DEFAULT_BRIGHTNESS,
+                UserHandle.USER_CURRENT);
         mServiceFake = new DozeServiceFake();
         mHostFake = new DozeHostFake();
         mSensorManager = new FakeSensorManager(mContext);
@@ -88,6 +93,17 @@
     }
 
     @Test
+    public void testAod_usesLightSensorRespectingUserSetting() throws Exception {
+        int maxBrightness = 3;
+        Settings.System.putIntForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS, maxBrightness,
+                UserHandle.USER_CURRENT);
+
+        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+        assertEquals(maxBrightness, mServiceFake.screenBrightness);
+    }
+
+    @Test
     public void testPausingAod_doesntPauseLightSensor() throws Exception {
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 46e2bfb..a26b1b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -137,7 +137,8 @@
 
     @Test
     public void addZenMode_addedToSlice() {
-        ListBuilder listBuilder = spy(new ListBuilder(getContext(), mProvider.getUri()));
+        ListBuilder listBuilder = spy(new ListBuilder(getContext(), mProvider.getUri(),
+            ListBuilder.INFINITY));
         mProvider.addZenMode(listBuilder);
         verify(listBuilder, never()).addRow(any(ListBuilder.RowBuilder.class));
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index d19715d..a9d49f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -24,6 +24,7 @@
 
 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;
 
@@ -66,6 +67,8 @@
     public static final long BELOW_HYBRID_THRESHOLD = TimeUnit.HOURS.toMillis(2);
     public static final long ABOVE_HYBRID_THRESHOLD = TimeUnit.HOURS.toMillis(4);
     private static final long ABOVE_CHARGE_CYCLE_THRESHOLD = Duration.ofHours(8).toMillis();
+    private static final int OLD_BATTERY_LEVEL_NINE = 9;
+    private static final int OLD_BATTERY_LEVEL_10 = 10;
     private HardwarePropertiesManager mHardProps;
     private WarningsUI mMockWarnings;
     private PowerUI mPowerUI;
@@ -307,8 +310,8 @@
                 .thenReturn(new Estimate(BELOW_HYBRID_THRESHOLD, true));
         mPowerUI.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
 
-        mPowerUI.maybeShowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                ABOVE_WARNING_BUCKET);
+        mPowerUI.maybeShowBatteryWarning(OLD_BATTERY_LEVEL_NINE, UNPLUGGED, UNPLUGGED,
+                ABOVE_WARNING_BUCKET, ABOVE_WARNING_BUCKET);
 
         // reduce battery level to handle time based trigger -> level trigger interactions
         mPowerUI.mBatteryLevel = 10;
@@ -320,9 +323,9 @@
     }
 
     @Test
-    public void testShouldDismissLowBatteryWarning_dismissWhenPowerSaverEnabled() {
+    public void testShouldDismissLowBatteryWarning_dismissWhenPowerSaverEnabledLegacy() {
         mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
+        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(false);
         when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
         when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
 
@@ -334,6 +337,20 @@
     }
 
     @Test
+    public void testShouldNotDismissLowBatteryWarning_dismissWhenPowerSaverEnabledHybrid() {
+        mPowerUI.start();
+        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
+        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
+        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
+
+        // device that gets power saver turned on should dismiss
+        boolean shouldDismiss =
+            mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET,
+                BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, !POWER_SAVER_OFF);
+        assertFalse(shouldDismiss);
+    }
+
+    @Test
     public void testShouldDismissLowBatteryWarning_dismissWhenPlugged() {
         mPowerUI.start();
         when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
@@ -449,6 +466,33 @@
         verify(mMockWarnings, never()).dismissLowBatteryWarning();
     }
 
+    @Test
+    public void testMaybeShowBatteryWarning_onlyQueriesEstimateOnBatteryLevelChangeOrNull() {
+        mPowerUI.start();
+        Estimate estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true);
+        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
+        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
+        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
+        when(mEnhancedEstimates.getEstimate()).thenReturn(estimate);
+        mPowerUI.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
+
+        // we expect that the first time it will query even if the level is the same
+        mPowerUI.mBatteryLevel = 9;
+        mPowerUI.maybeShowBatteryWarning(OLD_BATTERY_LEVEL_NINE, UNPLUGGED, UNPLUGGED,
+                ABOVE_WARNING_BUCKET, ABOVE_WARNING_BUCKET);
+        verify(mEnhancedEstimates, times(1)).getEstimate();
+
+        // We should NOT query again if the battery level hasn't changed
+        mPowerUI.maybeShowBatteryWarning(OLD_BATTERY_LEVEL_NINE, UNPLUGGED, UNPLUGGED,
+                ABOVE_WARNING_BUCKET, ABOVE_WARNING_BUCKET);
+        verify(mEnhancedEstimates, times(1)).getEstimate();
+
+        // Battery level has changed, so we should query again
+        mPowerUI.maybeShowBatteryWarning(OLD_BATTERY_LEVEL_10, UNPLUGGED, UNPLUGGED,
+                ABOVE_WARNING_BUCKET, ABOVE_WARNING_BUCKET);
+        verify(mEnhancedEstimates, times(2)).getEstimate();
+    }
+
     private void setCurrentTemp(float temp) {
         when(mHardProps.getDeviceTemperatures(DEVICE_TEMPERATURE_SKIN, TEMPERATURE_CURRENT))
                 .thenReturn(new float[] { temp });
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java
index 703b4d5..8503962 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java
@@ -41,7 +41,6 @@
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
-@Ignore("failing")
 public class QSFooterImplTest extends LeakCheckedTest {
 
     private QSFooterImpl mFooter;
@@ -60,6 +59,7 @@
     }
 
     @Test
+    @Ignore("failing")
     public void testSettings_UserNotSetup() {
         View settingsButton = mFooter.findViewById(id.settings_button);
         when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 8cece92..4e24354 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -52,7 +52,7 @@
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
 @SmallTest
-@Ignore("failing")
+@Ignore
 public class QSFragmentTest extends SysuiBaseFragmentTest {
 
     private MetricsLogger mMockMetricsLogger;
@@ -62,6 +62,7 @@
     }
 
     @Before
+    @Ignore("failing")
     public void addLeakCheckDependencies() {
         mMockMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
         mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE,
@@ -80,6 +81,7 @@
     }
 
     @Test
+    @Ignore("failing")
     public void testListening() {
         assertEquals(Looper.myLooper(), Looper.getMainLooper());
         QSFragment qs = (QSFragment) mFragment;
@@ -103,6 +105,7 @@
     }
 
     @Test
+    @Ignore("failing")
     public void testSaveState() {
         QSFragment qs = (QSFragment) mFragment;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java
index c3defa4..f89a932 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java
@@ -42,7 +42,7 @@
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
 @SmallTest
-@Ignore("Flaky")
+@Ignore
 public class CarQsFragmentTest extends SysuiBaseFragmentTest {
     public CarQsFragmentTest() {
         super(CarQSFragment.class);
@@ -64,6 +64,7 @@
     }
 
     @Test
+    @Ignore("Flaky")
     public void testLayoutInflation() {
         CarQSFragment fragment = (CarQSFragment) mFragment;
         mFragments.dispatchResume();
@@ -73,6 +74,7 @@
     }
 
     @Test
+    @Ignore("Flaky")
     public void testListening() {
         CarQSFragment qs = (CarQSFragment) mFragment;
         mFragments.dispatchResume();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
new file mode 100644
index 0000000..f04a115
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.systemui.statusbar;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.AlertingNotificationManager;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class AlertingNotificationManagerTest extends SysuiTestCase {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    private static final String TEST_PACKAGE_NAME = "test";
+    private static final int TEST_UID = 0;
+
+    private static final int TEST_MINIMUM_DISPLAY_TIME = 200;
+    private static final int TEST_AUTO_DISMISS_TIME = 500;
+    // Number of notifications to use in tests requiring multiple notifications
+    private static final int TEST_NUM_NOTIFICATIONS = 4;
+    private static final int TEST_TIMEOUT_TIME = 10000;
+    private final Runnable TEST_TIMEOUT_RUNNABLE = () -> mTimedOut = true;
+
+    private AlertingNotificationManager mAlertingNotificationManager;
+
+    protected NotificationData.Entry mEntry;
+    protected Handler mTestHandler;
+    private StatusBarNotification mSbn;
+    private boolean mTimedOut = false;
+
+    @Mock protected ExpandableNotificationRow mRow;
+
+    private final class TestableAlertingNotificationManager extends AlertingNotificationManager {
+        private TestableAlertingNotificationManager() {
+            mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
+            mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
+            mHandler = mTestHandler;
+        }
+
+        @Override
+        protected void onAlertEntryAdded(AlertEntry alertEntry) {}
+
+        @Override
+        protected void onAlertEntryRemoved(AlertEntry alertEntry) {}
+    }
+
+    protected AlertingNotificationManager createAlertingNotificationManager() {
+        return new TestableAlertingNotificationManager();
+    }
+
+    private StatusBarNotification createNewNotification(int id) {
+        Notification.Builder n = new Notification.Builder(mContext, "")
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+        return new StatusBarNotification(
+                TEST_PACKAGE_NAME /* pkg */,
+                TEST_PACKAGE_NAME,
+                id,
+                null /* tag */,
+                TEST_UID,
+                0 /* initialPid */,
+                n.build(),
+                new UserHandle(ActivityManager.getCurrentUser()),
+                null /* overrideGroupKey */,
+                0 /* postTime */);
+    }
+
+    @Before
+    public void setUp() {
+        mTestHandler = Handler.createAsync(Looper.myLooper());
+        mSbn = createNewNotification(0 /* id */);
+        mEntry = new NotificationData.Entry(mSbn);
+        mEntry.row = mRow;
+
+        mAlertingNotificationManager = createAlertingNotificationManager();
+    }
+
+    @Test
+    public void testShowNotification_addsEntry() {
+        mAlertingNotificationManager.showNotification(mEntry);
+
+        assertTrue(mAlertingNotificationManager.contains(mEntry.key));
+        assertTrue(mAlertingNotificationManager.hasNotifications());
+        assertEquals(mEntry, mAlertingNotificationManager.getEntry(mEntry.key));
+    }
+
+    @Test
+    public void testShowNotification_autoDismisses() {
+        mAlertingNotificationManager.showNotification(mEntry);
+        mTestHandler.postDelayed(TEST_TIMEOUT_RUNNABLE, TEST_TIMEOUT_TIME);
+
+        // Wait for remove runnable and then process it immediately
+        TestableLooper.get(this).processMessages(1);
+
+        assertFalse("Test timed out", mTimedOut);
+        assertFalse(mAlertingNotificationManager.contains(mEntry.key));
+    }
+
+    @Test
+    public void testRemoveNotification_removeDeferred() {
+        mAlertingNotificationManager.showNotification(mEntry);
+
+        // Try to remove but defer, since the notification has not been shown long enough.
+        mAlertingNotificationManager.removeNotification(mEntry.key, false /* releaseImmediately */);
+
+        assertTrue(mAlertingNotificationManager.contains(mEntry.key));
+    }
+
+    @Test
+    public void testRemoveNotification_forceRemove() {
+        mAlertingNotificationManager.showNotification(mEntry);
+
+        //Remove forcibly with releaseImmediately = true.
+        mAlertingNotificationManager.removeNotification(mEntry.key, true /* releaseImmediately */);
+
+        assertFalse(mAlertingNotificationManager.contains(mEntry.key));
+    }
+
+    @Test
+    public void testReleaseAllImmediately() {
+        for (int i = 0; i < TEST_NUM_NOTIFICATIONS; i++) {
+            StatusBarNotification sbn = createNewNotification(i);
+            NotificationData.Entry entry = new NotificationData.Entry(sbn);
+            entry.row = mRow;
+            mAlertingNotificationManager.showNotification(entry);
+        }
+
+        mAlertingNotificationManager.releaseAllImmediately();
+
+        assertEquals(0, mAlertingNotificationManager.getAllEntries().count());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsInfoTest.java
deleted file mode 100644
index 660d2dc..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsInfoTest.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static android.app.AppOpsManager.OP_CAMERA;
-import static android.app.AppOpsManager.OP_RECORD_AUDIO;
-import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Notification;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.UiThreadTest;
-import android.util.ArraySet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.CountDownLatch;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@UiThreadTest
-public class AppOpsInfoTest extends SysuiTestCase {
-    private static final String TEST_PACKAGE_NAME = "test_package";
-    private static final int TEST_UID = 1;
-
-    private AppOpsInfo mAppOpsInfo;
-    private final PackageManager mMockPackageManager = mock(PackageManager.class);
-    private final NotificationGuts mGutsParent = mock(NotificationGuts.class);
-    private StatusBarNotification mSbn;
-
-    @Before
-    public void setUp() throws Exception {
-        // Inflate the layout
-        final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
-        mAppOpsInfo = (AppOpsInfo) layoutInflater.inflate(R.layout.app_ops_info, null);
-        mAppOpsInfo.setGutsParent(mGutsParent);
-
-        // PackageManager must return a packageInfo and applicationInfo.
-        final PackageInfo packageInfo = new PackageInfo();
-        packageInfo.packageName = TEST_PACKAGE_NAME;
-        when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt()))
-                .thenReturn(packageInfo);
-        final ApplicationInfo applicationInfo = new ApplicationInfo();
-        applicationInfo.uid = TEST_UID;  // non-zero
-        when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
-                applicationInfo);
-
-        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
-                new Notification(), UserHandle.CURRENT, null, 0);
-    }
-
-    @Test
-    public void testBindNotification_SetsTextApplicationName() {
-        when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
-        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>());
-        final TextView textView = mAppOpsInfo.findViewById(R.id.pkgname);
-        assertTrue(textView.getText().toString().contains("App Name"));
-    }
-
-    @Test
-    public void testBindNotification_SetsPackageIcon() {
-        final Drawable iconDrawable = mock(Drawable.class);
-        when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
-                .thenReturn(iconDrawable);
-        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>());
-        final ImageView iconView = mAppOpsInfo.findViewById(R.id.pkgicon);
-        assertEquals(iconDrawable, iconView.getDrawable());
-    }
-
-    @Test
-    public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        final CountDownLatch latch = new CountDownLatch(1);
-        mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid,
-                ArraySet<Integer> ops) -> {
-            assertEquals(TEST_PACKAGE_NAME, pkg);
-            assertEquals(expectedOps, ops);
-            assertEquals(TEST_UID, uid);
-            latch.countDown();
-        }, mSbn, expectedOps);
-
-        final View settingsButton = mAppOpsInfo.findViewById(R.id.settings);
-        settingsButton.performClick();
-        // Verify that listener was triggered.
-        assertEquals(0, latch.getCount());
-    }
-
-    @Test
-    public void testOk() {
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        final CountDownLatch latch = new CountDownLatch(1);
-        mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid,
-                ArraySet<Integer> ops) -> {
-            assertEquals(TEST_PACKAGE_NAME, pkg);
-            assertEquals(expectedOps, ops);
-            assertEquals(TEST_UID, uid);
-            latch.countDown();
-        }, mSbn, expectedOps);
-
-        final View okButton = mAppOpsInfo.findViewById(R.id.ok);
-        okButton.performClick();
-        assertEquals(1, latch.getCount());
-        verify(mGutsParent, times(1)).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
-    }
-
-    @Test
-    public void testPrompt_camera() {
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
-        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
-        assertEquals("This app is using the camera.", prompt.getText());
-    }
-
-    @Test
-    public void testPrompt_mic() {
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_RECORD_AUDIO);
-        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
-        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
-        assertEquals("This app is using the microphone.", prompt.getText());
-    }
-
-    @Test
-    public void testPrompt_overlay() {
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
-        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
-        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
-        assertEquals("This app is displaying over other apps on your screen.", prompt.getText());
-    }
-
-    @Test
-    public void testPrompt_camera_mic() {
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        expectedOps.add(OP_RECORD_AUDIO);
-        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
-        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
-        assertEquals("This app is using the microphone and camera.", prompt.getText());
-    }
-
-    @Test
-    public void testPrompt_camera_mic_overlay() {
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        expectedOps.add(OP_RECORD_AUDIO);
-        expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
-        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
-        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
-        assertEquals("This app is displaying over other apps on your screen and using"
-                + " the microphone and camera.", prompt.getText());
-    }
-
-    @Test
-    public void testPrompt_camera_overlay() {
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
-        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
-        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
-        assertEquals("This app is displaying over other apps on your screen and using"
-                + " the camera.", prompt.getText());
-    }
-
-    @Test
-    public void testPrompt_mic_overlay() {
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_RECORD_AUDIO);
-        expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
-        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
-        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
-        assertEquals("This app is displaying over other apps on your screen and using"
-                + " the microphone.", prompt.getText());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java
deleted file mode 100644
index 0feaa5a..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.AppOpsManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class AppOpsListenerTest extends SysuiTestCase {
-    private static final String TEST_PACKAGE_NAME = "test";
-    private static final int TEST_UID = 0;
-
-    @Mock private NotificationPresenter mPresenter;
-    @Mock private AppOpsManager mAppOpsManager;
-
-    // Dependency mocks:
-    @Mock private NotificationEntryManager mEntryManager;
-    @Mock private ForegroundServiceController mFsc;
-
-    private AppOpsListener mListener;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
-        mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
-        getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
-        when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
-
-        mListener = new AppOpsListener(mContext);
-    }
-
-    @Test
-    public void testOnlyListenForFewOps() {
-        mListener.setUpWithPresenter(mPresenter, mEntryManager);
-
-        verify(mAppOpsManager, times(1)).startWatchingActive(AppOpsListener.OPS, mListener);
-    }
-
-    @Test
-    public void testStopListening() {
-        mListener.destroy();
-        verify(mAppOpsManager, times(1)).stopWatchingActive(mListener);
-    }
-
-    @Test
-    public void testInformEntryMgrOnAppOpsChange() {
-        mListener.setUpWithPresenter(mPresenter, mEntryManager);
-        mListener.onOpActiveChanged(
-                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
-        TestableLooper.get(this).processAllMessages();
-        verify(mEntryManager, times(1)).updateNotificationsForAppOp(
-                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
-    }
-
-    @Test
-    public void testInformFscOnAppOpsChange() {
-        mListener.setUpWithPresenter(mPresenter, mEntryManager);
-        mListener.onOpActiveChanged(
-                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
-        TestableLooper.get(this).processAllMessages();
-        verify(mFsc, times(1)).onAppOpChanged(
-                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
deleted file mode 100644
index f363cf0..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.AppOpsManager;
-import android.app.NotificationChannel;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.util.ArraySet;
-import android.view.NotificationHeaderView;
-import android.view.View;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
-import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.List;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-public class ExpandableNotificationRowTest extends SysuiTestCase {
-
-    private ExpandableNotificationRow mGroupRow;
-
-    private NotificationTestHelper mNotificationTestHelper;
-    boolean mHeadsUpAnimatingAway = false;
-
-    @Rule public MockitoRule mockito = MockitoJUnit.rule();
-    @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
-
-    @Before
-    public void setUp() throws Exception {
-        mNotificationTestHelper = new NotificationTestHelper(mContext);
-        mGroupRow = mNotificationTestHelper.createGroup();
-        mGroupRow.setHeadsUpAnimatingAwayListener(
-                animatingAway -> mHeadsUpAnimatingAway = animatingAway);
-        mDependency.injectTestDependency(
-                NotificationBlockingHelperManager.class,
-                mBlockingHelperManager);
-    }
-
-    @Test
-    public void testGroupSummaryNotShowingIconWhenPublic() {
-        mGroupRow.setSensitive(true, true);
-        mGroupRow.setHideSensitiveForIntrinsicHeight(true);
-        assertTrue(mGroupRow.isSummaryWithChildren());
-        assertFalse(mGroupRow.isShowingIcon());
-    }
-
-    @Test
-    public void testNotificationHeaderVisibleWhenAnimating() {
-        mGroupRow.setSensitive(true, true);
-        mGroupRow.setHideSensitive(true, false, 0, 0);
-        mGroupRow.setHideSensitive(false, true, 0, 0);
-        assertTrue(mGroupRow.getChildrenContainer().getVisibleHeader().getVisibility()
-                == View.VISIBLE);
-    }
-
-    @Test
-    public void testUserLockedResetEvenWhenNoChildren() {
-        mGroupRow.setUserLocked(true);
-        mGroupRow.removeAllChildren();
-        mGroupRow.setUserLocked(false);
-        assertFalse("The childrencontainer should not be userlocked but is, the state "
-                + "seems out of sync.", mGroupRow.getChildrenContainer().isUserLocked());
-    }
-
-    @Test
-    public void testReinflatedOnDensityChange() {
-        mGroupRow.setUserLocked(true);
-        mGroupRow.removeAllChildren();
-        mGroupRow.setUserLocked(false);
-        NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class);
-        mGroupRow.setChildrenContainer(mockContainer);
-        mGroupRow.onDensityOrFontScaleChanged();
-        verify(mockContainer).reInflateViews(any(), any());
-    }
-
-    @Test
-    public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception {
-        ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
-        row.setSensitive(true, true);
-        row.setHideSensitive(true, false, 0, 0);
-        verify(row).updateShelfIconColor();
-    }
-
-    @Test
-    public void testIconColorShouldBeUpdatedWhenSettingDark() throws Exception {
-        ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
-        row.setDark(true, false, 0);
-        verify(row).updateShelfIconColor();
-    }
-
-    @Test
-    public void testAboveShelfChangedListenerCalled() throws Exception {
-        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
-        AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
-        row.setAboveShelfChangedListener(listener);
-        row.setHeadsUp(true);
-        verify(listener).onAboveShelfStateChanged(true);
-    }
-
-    @Test
-    public void testAboveShelfChangedListenerCalledPinned() throws Exception {
-        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
-        AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
-        row.setAboveShelfChangedListener(listener);
-        row.setPinned(true);
-        verify(listener).onAboveShelfStateChanged(true);
-    }
-
-    @Test
-    public void testAboveShelfChangedListenerCalledHeadsUpGoingAway() throws Exception {
-        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
-        AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
-        row.setAboveShelfChangedListener(listener);
-        row.setHeadsUpAnimatingAway(true);
-        verify(listener).onAboveShelfStateChanged(true);
-    }
-    @Test
-    public void testAboveShelfChangedListenerCalledWhenGoingBelow() throws Exception {
-        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
-        row.setHeadsUp(true);
-        AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
-        row.setAboveShelfChangedListener(listener);
-        row.setAboveShelf(false);
-        verify(listener).onAboveShelfStateChanged(false);
-    }
-
-    @Test
-    public void testClickSound() throws Exception {
-        assertTrue("Should play sounds by default.", mGroupRow.isSoundEffectsEnabled());
-        mGroupRow.setDark(true /* dark */, false /* fade */, 0 /* delay */);
-        mGroupRow.setSecureStateProvider(()-> false);
-        assertFalse("Shouldn't play sounds when dark and trusted.",
-                mGroupRow.isSoundEffectsEnabled());
-        mGroupRow.setSecureStateProvider(()-> true);
-        assertTrue("Should always play sounds when not trusted.",
-                mGroupRow.isSoundEffectsEnabled());
-    }
-
-    @Test
-    public void testSetDismissed_longPressListenerRemoved() {
-        ExpandableNotificationRow.LongPressListener listener =
-                mock(ExpandableNotificationRow.LongPressListener.class);
-        mGroupRow.setLongPressListener(listener);
-        mGroupRow.doLongClickCallback(0,0);
-        verify(listener, times(1)).onLongPress(eq(mGroupRow), eq(0), eq(0),
-                any(NotificationMenuRowPlugin.MenuItem.class));
-        reset(listener);
-
-        mGroupRow.setDismissed(true);
-        mGroupRow.doLongClickCallback(0,0);
-        verify(listener, times(0)).onLongPress(eq(mGroupRow), eq(0), eq(0),
-                any(NotificationMenuRowPlugin.MenuItem.class));
-    }
-
-    @Test
-    public void testShowAppOps_noHeader() {
-        // public notification is custom layout - no header
-        mGroupRow.setSensitive(true, true);
-        mGroupRow.setAppOpsOnClickListener(null);
-        mGroupRow.showAppOpsIcons(null);
-    }
-
-    @Test
-    public void testShowAppOpsIcons_header() {
-        NotificationHeaderView mockHeader = mock(NotificationHeaderView.class);
-
-        NotificationContentView publicLayout = mock(NotificationContentView.class);
-        mGroupRow.setPublicLayout(publicLayout);
-        NotificationContentView privateLayout = mock(NotificationContentView.class);
-        mGroupRow.setPrivateLayout(privateLayout);
-        NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class);
-        when(mockContainer.getNotificationChildCount()).thenReturn(1);
-        when(mockContainer.getHeaderView()).thenReturn(mockHeader);
-        mGroupRow.setChildrenContainer(mockContainer);
-
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS);
-        mGroupRow.showAppOpsIcons(ops);
-
-        verify(mockHeader, times(1)).showAppOpsIcons(ops);
-        verify(privateLayout, times(1)).showAppOpsIcons(ops);
-        verify(publicLayout, times(1)).showAppOpsIcons(ops);
-
-    }
-
-    @Test
-    public void testAppOpsOnClick() {
-        ExpandableNotificationRow.OnAppOpsClickListener l = mock(
-                ExpandableNotificationRow.OnAppOpsClickListener.class);
-        View view = mock(View.class);
-
-        mGroupRow.setAppOpsOnClickListener(l);
-
-        mGroupRow.getAppOpsOnClickListener().onClick(view);
-        verify(l, times(1)).onClick(any(), anyInt(), anyInt(), any());
-    }
-
-    @Test
-    public void testHeadsUpAnimatingAwayListener() {
-        mGroupRow.setHeadsUpAnimatingAway(true);
-        Assert.assertEquals(true, mHeadsUpAnimatingAway);
-        mGroupRow.setHeadsUpAnimatingAway(false);
-        Assert.assertEquals(false, mHeadsUpAnimatingAway);
-    }
-
-    @Test
-    public void testPerformDismissWithBlockingHelper_falseWhenBlockingHelperIsntShown() {
-        when(mBlockingHelperManager.perhapsShowBlockingHelper(
-                eq(mGroupRow), any(NotificationMenuRowPlugin.class))).thenReturn(false);
-
-        assertFalse(
-                mGroupRow.performDismissWithBlockingHelper(false /* fromAccessibility */));
-    }
-
-    @Test
-    public void testPerformDismissWithBlockingHelper_doesntPerformOnGroupSummary() {
-        ExpandableNotificationRow childRow = mGroupRow.getChildrenContainer().getViewAtPosition(0);
-        when(mBlockingHelperManager.perhapsShowBlockingHelper(eq(childRow), any(NotificationMenuRowPlugin.class)))
-                .thenReturn(true);
-
-        assertTrue(
-                childRow.performDismissWithBlockingHelper(false /* fromAccessibility */));
-
-        verify(mBlockingHelperManager, times(1))
-                .perhapsShowBlockingHelper(eq(childRow), any(NotificationMenuRowPlugin.class));
-        verify(mBlockingHelperManager, times(0))
-                .perhapsShowBlockingHelper(eq(mGroupRow), any(NotificationMenuRowPlugin.class));
-    }
-
-    @Test
-    public void testIsBlockingHelperShowing_isCorrectlyUpdated() {
-        mGroupRow.setBlockingHelperShowing(true);
-        assertTrue(mGroupRow.isBlockingHelperShowing());
-
-        mGroupRow.setBlockingHelperShowing(false);
-        assertFalse(mGroupRow.isBlockingHelperShowing());
-    }
-
-    @Test
-    public void testGetNumUniqueChildren_defaultChannel() {
-        assertEquals(1, mGroupRow.getNumUniqueChannels());
-    }
-
-    @Test
-    public void testGetNumUniqueChildren_multiChannel() {
-        List<ExpandableNotificationRow> childRows =
-                mGroupRow.getChildrenContainer().getNotificationChildren();
-        // Give each child a unique channel id/name.
-        int i = 0;
-        for (ExpandableNotificationRow childRow : childRows) {
-            childRow.getEntry().channel =
-                    new NotificationChannel("id" + i, "dinnertime" + i, IMPORTANCE_DEFAULT);
-            i++;
-        }
-
-        assertEquals(3, mGroupRow.getNumUniqueChannels());
-    }
-
-    @Test
-    public void testIconScrollXAfterTranslationAndReset() throws Exception {
-        mGroupRow.setTranslation(50);
-        assertEquals(50, -mGroupRow.getEntry().expandedIcon.getScrollX());
-
-        mGroupRow.resetTranslation();
-        assertEquals(0, mGroupRow.getEntry().expandedIcon.getScrollX());
-    }
-
-    @Test
-    public void testIsExpanded_userExpanded() {
-        mGroupRow.setExpandable(true);
-        Assert.assertFalse(mGroupRow.isExpanded());
-        mGroupRow.setUserExpanded(true);
-        Assert.assertTrue(mGroupRow.isExpanded());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/FooterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/FooterViewTest.java
deleted file mode 100644
index e6fdfa4..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/FooterViewTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class FooterViewTest extends SysuiTestCase {
-
-    FooterView mView;
-
-    @Before
-    public void setUp() {
-        mView = (FooterView) LayoutInflater.from(mContext).inflate(
-                R.layout.status_bar_notification_footer, null, false);
-        mView.setDuration(0);
-    }
-
-    @Test
-    public void testViewsNotNull() {
-        assertNotNull(mView.findContentView());
-        assertNotNull(mView.findSecondaryView());
-    }
-
-    @Test
-    public void setDismissOnClick() {
-        mView.setDismissButtonClickListener(mock(View.OnClickListener.class));
-        assertTrue(mView.findSecondaryView().hasOnClickListeners());
-    }
-
-    @Test
-    public void setManageOnClick() {
-        mView.setManageButtonClickListener(mock(View.OnClickListener.class));
-        assertTrue(mView.findViewById(R.id.manage_text).hasOnClickListeners());
-    }
-
-    @Test
-    public void testPerformVisibilityAnimation() {
-        mView.setVisible(false /* visible */, false /* animate */);
-        assertFalse(mView.isVisible());
-
-        mView.setVisible(true /* visible */, true /* animate */);
-    }
-
-    @Test
-    public void testPerformSecondaryVisibilityAnimation() {
-        mView.setSecondaryVisible(false /* visible */, false /* animate */);
-        assertFalse(mView.isSecondaryVisible());
-
-        mView.setSecondaryVisible(true /* visible */, true /* animate */);
-    }
-}
-
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index 2af0c3e..8129b01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -27,8 +27,13 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.row.NotificationInfo;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
 import org.junit.Before;
@@ -91,6 +96,6 @@
         viewHierarchyManager.setUpWithPresenter(mPresenter, entryManager, mListContainer);
         notificationListener.setUpWithPresenter(mPresenter, entryManager);
 
-        assertFalse(mDependency.hasInstantiatedDependency(StatusBarWindowManager.class));
+        assertFalse(mDependency.hasInstantiatedDependency(StatusBarWindowController.class));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationBlockingHelperManagerTest.java
deleted file mode 100644
index 4366032..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationBlockingHelperManagerTest.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-
-import android.content.Context;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.View;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-/**
- * Tests for {@link NotificationBlockingHelperManager}.
- */
-@SmallTest
-@FlakyTest
-@org.junit.runner.RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
-
-    private NotificationBlockingHelperManager mBlockingHelperManager;
-
-    private NotificationTestHelper mHelper;
-
-    @Mock private NotificationGutsManager mGutsManager;
-    @Mock private NotificationEntryManager mEntryManager;
-    @Mock private NotificationMenuRow mMenuRow;
-    @Mock private NotificationMenuRowPlugin.MenuItem mMenuItem;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        when(mGutsManager.openGuts(
-                any(View.class),
-                anyInt(),
-                anyInt(),
-                any(NotificationMenuRowPlugin.MenuItem.class)))
-                .thenReturn(true);
-        when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem);
-        mDependency.injectTestDependency(NotificationGutsManager.class, mGutsManager);
-        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
-
-        mHelper = new NotificationTestHelper(mContext);
-
-        mBlockingHelperManager = new NotificationBlockingHelperManager(mContext);
-        // By default, have the shade visible/expanded.
-        mBlockingHelperManager.setNotificationShadeExpanded(1f);
-    }
-
-    @Test
-    public void testDismissCurrentBlockingHelper_nullBlockingHelperRow() {
-        // By default, this shouldn't dismiss (no pointers/vars set up!)
-        assertFalse(mBlockingHelperManager.dismissCurrentBlockingHelper());
-        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-    }
-
-    @Test
-    public void testDismissCurrentBlockingHelper_withDetachedBlockingHelperRow() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        row.setBlockingHelperShowing(true);
-        when(row.isAttachedToWindow()).thenReturn(false);
-        mBlockingHelperManager.setBlockingHelperRowForTest(row);
-
-        assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
-        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
-        verify(mEntryManager, times(0)).updateNotifications();
-    }
-
-    @Test
-    public void testDismissCurrentBlockingHelper_withAttachedBlockingHelperRow() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        row.setBlockingHelperShowing(true);
-        when(row.isAttachedToWindow()).thenReturn(true);
-        mBlockingHelperManager.setBlockingHelperRowForTest(row);
-
-        assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
-        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
-        verify(mEntryManager).updateNotifications();
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_shown() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
-
-        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-
-        verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
-    }
-
-
-    @Test
-    public void testPerhapsShowBlockingHelper_shownForLargeGroup() throws Exception {
-        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
-        groupRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
-
-        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
-
-        verify(mGutsManager).openGuts(groupRow, 0, 0, mMenuItem);
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_shownForOnlyChildNotification()
-            throws Exception {
-        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(1);
-        // Explicitly get the children container & call getViewAtPosition on it instead of the row
-        // as other factors such as view expansion may cause us to get the parent row back instead
-        // of the child row.
-        ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
-        childRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
-        assertFalse(childRow.getIsNonblockable());
-
-        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
-
-        verify(mGutsManager).openGuts(childRow, 0, 0, mMenuItem);
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownDueToNeutralUserSentiment() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        row.getEntry().userSentiment = USER_SENTIMENT_NEUTRAL;
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownDueToPositiveUserSentiment()
-            throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        row.getEntry().userSentiment = USER_SENTIMENT_POSITIVE;
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownDueToShadeVisibility() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
-        // Hide the shade
-        mBlockingHelperManager.setNotificationShadeExpanded(0f);
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownDueToNonblockability() throws Exception {
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        when(row.getIsNonblockable()).thenReturn(true);
-        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-    }
-
-    @Test
-    public void testPerhapsShowBlockingHelper_notShownAsNotificationIsInMultipleChildGroup()
-            throws Exception {
-        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(2);
-        // Explicitly get the children container & call getViewAtPosition on it instead of the row
-        // as other factors such as view expansion may cause us to get the parent row back instead
-        // of the child row.
-        ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
-        childRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
-
-        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
-    }
-
-    @Test
-    public void testBlockingHelperShowAndDismiss() throws Exception{
-        ExpandableNotificationRow row = createBlockableRowSpy();
-        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
-        when(row.isAttachedToWindow()).thenReturn(true);
-
-        // Show check
-        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-
-        verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
-
-        // Dismiss check
-        assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
-        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
-        verify(mEntryManager).updateNotifications();
-    }
-
-    @Test
-    public void testNonBlockable_package() {
-        mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
-
-        assertFalse(mBlockingHelperManager.isNonblockable("orange", "pie"));
-
-        assertTrue(mBlockingHelperManager.isNonblockable("banana", "pie"));
-    }
-
-    @Test
-    public void testNonBlockable_channel() {
-        mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
-
-        assertFalse(mBlockingHelperManager.isNonblockable("strawberry", "shortcake"));
-
-        assertTrue(mBlockingHelperManager.isNonblockable("strawberry", "pie"));
-    }
-
-    private ExpandableNotificationRow createBlockableRowSpy() throws Exception {
-        ExpandableNotificationRow row = spy(mHelper.createRow());
-        when(row.getIsNonblockable()).thenReturn(false);
-        return row;
-    }
-
-    private ExpandableNotificationRow createBlockableGroupRowSpy(int numChildren) throws Exception {
-        ExpandableNotificationRow row = spy(mHelper.createGroup(numChildren));
-        when(row.getIsNonblockable()).thenReturn(false);
-        return row;
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
deleted file mode 100644
index 1fb4c37..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyFloat;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.AppOpsManager;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.ArraySet;
-import android.view.NotificationHeaderView;
-import android.view.View;
-
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class NotificationContentViewTest extends SysuiTestCase {
-
-    NotificationContentView mView;
-
-    @Before
-    @UiThreadTest
-    public void setup() {
-        mView = new NotificationContentView(mContext, null);
-        ExpandableNotificationRow row = new ExpandableNotificationRow(mContext, null);
-        ExpandableNotificationRow mockRow = spy(row);
-        doNothing().when(mockRow).updateBackgroundAlpha(anyFloat());
-        doReturn(10).when(mockRow).getIntrinsicHeight();
-
-        mView.setContainingNotification(mockRow);
-        mView.setHeights(10, 20, 30, 40);
-
-        mView.setContractedChild(createViewWithHeight(10));
-        mView.setExpandedChild(createViewWithHeight(20));
-        mView.setHeadsUpChild(createViewWithHeight(30));
-        mView.setAmbientChild(createViewWithHeight(40));
-
-        mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
-        mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
-    }
-
-    private View createViewWithHeight(int height) {
-        View view = new View(mContext, null);
-        view.setMinimumHeight(height);
-        return view;
-    }
-
-    @Test
-    @UiThreadTest
-    public void animationStartType_getsClearedAfterUpdatingVisibilitiesWithoutAnimation() {
-        mView.setHeadsUp(true);
-        mView.setDark(true, false, 0);
-        mView.setDark(false, true, 0);
-        mView.setHeadsUpAnimatingAway(true);
-        Assert.assertFalse(mView.isAnimatingVisibleType());
-    }
-
-    @Test
-    @UiThreadTest
-    public void testShowAppOpsIcons() {
-        NotificationHeaderView mockContracted = mock(NotificationHeaderView.class);
-        when(mockContracted.findViewById(com.android.internal.R.id.notification_header))
-                .thenReturn(mockContracted);
-        NotificationHeaderView mockExpanded = mock(NotificationHeaderView.class);
-        when(mockExpanded.findViewById(com.android.internal.R.id.notification_header))
-                .thenReturn(mockExpanded);
-        NotificationHeaderView mockHeadsUp = mock(NotificationHeaderView.class);
-        when(mockHeadsUp.findViewById(com.android.internal.R.id.notification_header))
-                .thenReturn(mockHeadsUp);
-        NotificationHeaderView mockAmbient = mock(NotificationHeaderView.class);
-        when(mockAmbient.findViewById(com.android.internal.R.id.notification_header))
-                .thenReturn(mockAmbient);
-
-        mView.setContractedChild(mockContracted);
-        mView.setExpandedChild(mockExpanded);
-        mView.setHeadsUpChild(mockHeadsUp);
-        mView.setAmbientChild(mockAmbient);
-
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS);
-        mView.showAppOpsIcons(ops);
-
-        verify(mockContracted, times(1)).showAppOpsIcons(ops);
-        verify(mockExpanded, times(1)).showAppOpsIcons(ops);
-        verify(mockAmbient, never()).showAppOpsIcons(ops);
-        verify(mockHeadsUp, times(1)).showAppOpsIcons(any());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
deleted file mode 100644
index a34588d..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.View;
-import android.widget.RemoteViews;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
-import com.android.systemui.statusbar.notification.NotificationViewWrapper;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-public class NotificationCustomViewWrapperTest extends SysuiTestCase {
-
-    private ExpandableNotificationRow mRow;
-
-    @Before
-    public void setUp() throws Exception {
-        mRow = new NotificationTestHelper(mContext).createRow();
-    }
-
-    @Test
-    public void testBackgroundPersists() {
-        RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.custom_view_dark);
-        View v = views.apply(mContext, null);
-        NotificationViewWrapper wrap = NotificationCustomViewWrapper.wrap(mContext, v, mRow);
-        wrap.onContentUpdated(mRow);
-        Assert.assertTrue("No background set, when applying custom background view",
-                wrap.getCustomBackgroundColor() != 0);
-        views.reapply(mContext, v);
-        wrap.onReinflated();
-        wrap.onContentUpdated(mRow);
-        Assert.assertTrue("Reapplying a custom remote view lost it's background!",
-                wrap.getCustomBackgroundColor() != 0);
-    }
-
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
deleted file mode 100644
index 77522e4..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static android.app.AppOpsManager.OP_ACCEPT_HANDOVER;
-import static android.app.AppOpsManager.OP_CAMERA;
-import static android.app.Notification.CATEGORY_ALARM;
-import static android.app.Notification.CATEGORY_CALL;
-import static android.app.Notification.CATEGORY_EVENT;
-import static android.app.Notification.CATEGORY_MESSAGE;
-import static android.app.Notification.CATEGORY_REMINDER;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.Manifest;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.media.session.MediaSession;
-import android.os.Bundle;
-import android.service.notification.NotificationListenerService;
-import android.service.notification.StatusBarNotification;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.util.ArraySet;
-
-import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-public class NotificationDataTest extends SysuiTestCase {
-
-    private static final int UID_NORMAL = 123;
-    private static final int UID_ALLOW_DURING_SETUP = 456;
-    private static final String TEST_HIDDEN_NOTIFICATION_KEY = "testHiddenNotificationKey";
-    private static final String TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY = "exempt";
-
-    private final StatusBarNotification mMockStatusBarNotification =
-            mock(StatusBarNotification.class);
-    @Mock
-    ForegroundServiceController mFsc;
-    @Mock
-    NotificationData.Environment mEnvironment;
-
-    private final IPackageManager mMockPackageManager = mock(IPackageManager.class);
-    private NotificationData mNotificationData;
-    private ExpandableNotificationRow mRow;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        when(mMockStatusBarNotification.getUid()).thenReturn(UID_NORMAL);
-
-        when(mMockPackageManager.checkUidPermission(
-                eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
-                eq(UID_NORMAL)))
-                .thenReturn(PackageManager.PERMISSION_DENIED);
-        when(mMockPackageManager.checkUidPermission(
-                eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
-                eq(UID_ALLOW_DURING_SETUP)))
-                .thenReturn(PackageManager.PERMISSION_GRANTED);
-
-        mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
-        when(mEnvironment.getGroupManager()).thenReturn(new NotificationGroupManager());
-        when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
-        when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
-        mNotificationData = new TestableNotificationData(mEnvironment);
-        mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class));
-        mRow = new NotificationTestHelper(getContext()).createRow();
-    }
-
-    @Test
-    @UiThreadTest
-    public void testShowNotificationEvenIfUnprovisioned_FalseIfNoExtra() {
-        initStatusBarNotification(false);
-        when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP);
-
-        assertFalse(
-                NotificationData.showNotificationEvenIfUnprovisioned(
-                        mMockPackageManager,
-                        mMockStatusBarNotification));
-    }
-
-    @Test
-    @UiThreadTest
-    public void testShowNotificationEvenIfUnprovisioned_FalseIfNoPermission() {
-        initStatusBarNotification(true);
-
-        assertFalse(
-                NotificationData.showNotificationEvenIfUnprovisioned(
-                        mMockPackageManager,
-                        mMockStatusBarNotification));
-    }
-
-    @Test
-    @UiThreadTest
-    public void testShowNotificationEvenIfUnprovisioned_TrueIfHasPermissionAndExtra() {
-        initStatusBarNotification(true);
-        when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP);
-
-        assertTrue(
-                NotificationData.showNotificationEvenIfUnprovisioned(
-                        mMockPackageManager,
-                        mMockStatusBarNotification));
-    }
-
-    @Test
-    public void testChannelSetWhenAdded() {
-        mNotificationData.add(mRow.getEntry());
-        Assert.assertTrue(mRow.getEntry().channel != null);
-    }
-
-
-
-    @Test
-    public void testAllRelevantNotisTaggedWithAppOps() throws Exception {
-        mNotificationData.add(mRow.getEntry());
-        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow();
-        mNotificationData.add(row2.getEntry());
-        ExpandableNotificationRow diffPkg =
-                new NotificationTestHelper(getContext()).createRow("pkg", 4000);
-        mNotificationData.add(diffPkg.getEntry());
-
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        expectedOps.add(OP_ACCEPT_HANDOVER);
-
-        for (int op : expectedOps) {
-            mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
-                    NotificationTestHelper.PKG, mRow.getEntry().key, true);
-            mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
-                    NotificationTestHelper.PKG, row2.getEntry().key, true);
-        }
-        for (int op : expectedOps) {
-            assertTrue(mRow.getEntry().key + " doesn't have op " + op,
-                    mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(op));
-            assertTrue(row2.getEntry().key + " doesn't have op " + op,
-                    mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(op));
-            assertFalse(diffPkg.getEntry().key + " has op " + op,
-                    mNotificationData.get(diffPkg.getEntry().key).mActiveAppOps.contains(op));
-        }
-    }
-
-    @Test
-    public void testAppOpsRemoval() throws Exception {
-        mNotificationData.add(mRow.getEntry());
-        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow();
-        mNotificationData.add(row2.getEntry());
-
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        expectedOps.add(OP_ACCEPT_HANDOVER);
-
-        for (int op : expectedOps) {
-            mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
-                    NotificationTestHelper.PKG, row2.getEntry().key, true);
-        }
-
-        expectedOps.remove(OP_ACCEPT_HANDOVER);
-        mNotificationData.updateAppOp(OP_ACCEPT_HANDOVER, NotificationTestHelper.UID,
-                NotificationTestHelper.PKG, row2.getEntry().key, false);
-
-        assertTrue(mRow.getEntry().key + " doesn't have op " + OP_CAMERA,
-                mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(OP_CAMERA));
-        assertTrue(row2.getEntry().key + " doesn't have op " + OP_CAMERA,
-                mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(OP_CAMERA));
-        assertFalse(mRow.getEntry().key + " has op " + OP_ACCEPT_HANDOVER,
-                mNotificationData.get(mRow.getEntry().key)
-                        .mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
-        assertFalse(row2.getEntry().key + " has op " + OP_ACCEPT_HANDOVER,
-                mNotificationData.get(row2.getEntry().key)
-                        .mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
-    }
-
-    @Test
-    public void testSuppressSystemAlertNotification() {
-        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
-        when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
-        StatusBarNotification sbn = mRow.getEntry().notification;
-        Bundle bundle = new Bundle();
-        bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[] {"something"});
-        sbn.getNotification().extras = bundle;
-
-        assertTrue(mNotificationData.shouldFilterOut(mRow.getEntry()));
-    }
-
-    @Test
-    public void testDoNotSuppressSystemAlertNotification() {
-        StatusBarNotification sbn = mRow.getEntry().notification;
-        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(mNotificationData.shouldFilterOut(mRow.getEntry()));
-
-        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
-        when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
-
-        assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry()));
-
-        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
-        when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
-
-        assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry()));
-    }
-
-    @Test
-    public void testDoNotSuppressMalformedSystemAlertNotification() {
-        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
-
-        // missing extra
-        assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry()));
-
-        StatusBarNotification sbn = mRow.getEntry().notification;
-        Bundle bundle = new Bundle();
-        bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[] {});
-        sbn.getNotification().extras = bundle;
-
-        // extra missing values
-        assertFalse(mNotificationData.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
-        when(mMockStatusBarNotification.getKey()).thenReturn(TEST_HIDDEN_NOTIFICATION_KEY);
-        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
-        assertTrue(mNotificationData.shouldFilterOut(entry));
-
-        // not hidden
-        when(mMockStatusBarNotification.getKey()).thenReturn("not hidden");
-        entry = new NotificationData.Entry(mMockStatusBarNotification);
-        assertFalse(mNotificationData.shouldFilterOut(entry));
-    }
-
-    @Test
-    public void testGetNotificationsForCurrentUser_shouldFilterNonCurrentUserNotifications()
-            throws Exception {
-        mNotificationData.add(mRow.getEntry());
-        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow();
-        mNotificationData.add(row2.getEntry());
-
-        when(mEnvironment.isNotificationForCurrentProfiles(
-                mRow.getEntry().notification)).thenReturn(false);
-        when(mEnvironment.isNotificationForCurrentProfiles(
-                row2.getEntry().notification)).thenReturn(true);
-        ArrayList<NotificationData.Entry> reuslt =
-                mNotificationData.getNotificationsForCurrentUser();
-
-        assertEquals(reuslt.size(), 1);
-        assertEquals(reuslt.get(0), row2.getEntry());
-    }
-
-    @Test
-    public void testIsExemptFromDndVisualSuppression_foreground() {
-        initStatusBarNotification(false);
-        when(mMockStatusBarNotification.getKey()).thenReturn(
-                TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
-        Notification n = mMockStatusBarNotification.getNotification();
-        n.flags = Notification.FLAG_FOREGROUND_SERVICE;
-        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
-
-        assertTrue(mNotificationData.isExemptFromDndVisualSuppression(entry));
-        assertFalse(mNotificationData.shouldSuppressAmbient(entry));
-    }
-
-    @Test
-    public void testIsExemptFromDndVisualSuppression_media() {
-        initStatusBarNotification(false);
-        when(mMockStatusBarNotification.getKey()).thenReturn(
-                TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
-        Notification n = mMockStatusBarNotification.getNotification();
-        Notification.Builder nb = Notification.Builder.recoverBuilder(mContext, n);
-        nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
-        n = nb.build();
-        when(mMockStatusBarNotification.getNotification()).thenReturn(n);
-        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
-
-        assertTrue(mNotificationData.isExemptFromDndVisualSuppression(entry));
-        assertFalse(mNotificationData.shouldSuppressAmbient(entry));
-    }
-
-    @Test
-    public void testIsExemptFromDndVisualSuppression_system() {
-        initStatusBarNotification(false);
-        when(mMockStatusBarNotification.getKey()).thenReturn(
-                TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
-        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
-        entry.mIsSystemNotification = true;
-
-        assertTrue(mNotificationData.isExemptFromDndVisualSuppression(entry));
-        assertFalse(mNotificationData.shouldSuppressAmbient(entry));
-    }
-
-    @Test
-    public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() {
-        initStatusBarNotification(false);
-        when(mMockStatusBarNotification.getKey()).thenReturn(
-                TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
-        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
-        entry.mIsSystemNotification = true;
-        when(mMockStatusBarNotification.getNotification()).thenReturn(
-                new Notification.Builder(mContext, "").setCategory(CATEGORY_CALL).build());
-
-        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
-        assertTrue(mNotificationData.shouldSuppressAmbient(entry));
-
-        when(mMockStatusBarNotification.getNotification()).thenReturn(
-                new Notification.Builder(mContext, "").setCategory(CATEGORY_REMINDER).build());
-
-        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
-
-        when(mMockStatusBarNotification.getNotification()).thenReturn(
-                new Notification.Builder(mContext, "").setCategory(CATEGORY_ALARM).build());
-
-        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
-
-        when(mMockStatusBarNotification.getNotification()).thenReturn(
-                new Notification.Builder(mContext, "").setCategory(CATEGORY_EVENT).build());
-
-        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
-
-        when(mMockStatusBarNotification.getNotification()).thenReturn(
-                new Notification.Builder(mContext, "").setCategory(CATEGORY_MESSAGE).build());
-
-        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
-    }
-
-    private void initStatusBarNotification(boolean allowDuringSetup) {
-        Bundle bundle = new Bundle();
-        bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
-        Notification notification = new Notification.Builder(mContext, "test")
-                .addExtras(bundle)
-                .build();
-        when(mMockStatusBarNotification.getNotification()).thenReturn(notification);
-    }
-
-    private class TestableNotificationData extends NotificationData {
-        public TestableNotificationData(Environment environment) {
-            super(environment);
-        }
-
-        @Override
-        public NotificationChannel getChannel(String key) {
-            return new NotificationChannel(null, null, 0);
-        }
-
-        @Override
-        protected boolean getRanking(String key, NotificationListenerService.Ranking outRanking) {
-            super.getRanking(key, outRanking);
-            if (key.equals(TEST_HIDDEN_NOTIFICATION_KEY)) {
-                outRanking.populate(key, outRanking.getRank(),
-                        outRanking.matchesInterruptionFilter(),
-                        outRanking.getVisibilityOverride(), outRanking.getSuppressedVisualEffects(),
-                        outRanking.getImportance(), outRanking.getImportanceExplanation(),
-                        outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
-                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true);
-            } else if (key.equals(TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY)) {
-                outRanking.populate(key, outRanking.getRank(),
-                        outRanking.matchesInterruptionFilter(),
-                        outRanking.getVisibilityOverride(), 255,
-                        outRanking.getImportance(), outRanking.getImportanceExplanation(),
-                        outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
-                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true);
-            } else {
-                outRanking.populate(key, outRanking.getRank(),
-                        outRanking.matchesInterruptionFilter(),
-                        outRanking.getVisibilityOverride(), outRanking.getSuppressedVisualEffects(),
-                        outRanking.getImportance(), outRanking.getImportanceExplanation(),
-                        outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
-                        outRanking.canShowBadge(), outRanking.getUserSentiment(), false);
-            }
-            return true;
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
deleted file mode 100644
index afe16cf..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.assertFalse;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.ActivityManager;
-import android.app.AppOpsManager;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.service.notification.NotificationListenerService;
-import android.service.notification.StatusBarNotification;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.util.ArraySet;
-import android.widget.FrameLayout;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-
-import junit.framework.Assert;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class NotificationEntryManagerTest extends SysuiTestCase {
-    private static final String TEST_PACKAGE_NAME = "test";
-    private static final int TEST_UID = 0;
-
-    @Mock private NotificationPresenter mPresenter;
-    @Mock private ExpandableNotificationRow mRow;
-    @Mock private NotificationListContainer mListContainer;
-    @Mock private NotificationEntryManager.Callback mCallback;
-    @Mock private HeadsUpManager mHeadsUpManager;
-    @Mock private NotificationListenerService.RankingMap mRankingMap;
-    @Mock private RemoteInputController mRemoteInputController;
-    @Mock private IStatusBarService mBarService;
-
-    // Dependency mocks:
-    @Mock private ForegroundServiceController mForegroundServiceController;
-    @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
-    @Mock private NotificationGroupManager mGroupManager;
-    @Mock private NotificationGutsManager mGutsManager;
-    @Mock private NotificationRemoteInputManager mRemoteInputManager;
-    @Mock private NotificationMediaManager mMediaManager;
-    @Mock private NotificationListener mNotificationListener;
-    @Mock private DeviceProvisionedController mDeviceProvisionedController;
-    @Mock private VisualStabilityManager mVisualStabilityManager;
-    @Mock private MetricsLogger mMetricsLogger;
-    @Mock private SmartReplyController mSmartReplyController;
-
-    private NotificationData.Entry mEntry;
-    private StatusBarNotification mSbn;
-    private TestableNotificationEntryManager mEntryManager;
-    private CountDownLatch mCountDownLatch;
-
-    private class TestableNotificationEntryManager extends NotificationEntryManager {
-        private final CountDownLatch mCountDownLatch;
-
-        public TestableNotificationEntryManager(Context context, IStatusBarService barService) {
-            super(context);
-            mBarService = barService;
-            mCountDownLatch = new CountDownLatch(1);
-            mUseHeadsUp = true;
-        }
-
-        @Override
-        public void onAsyncInflationFinished(NotificationData.Entry entry) {
-            super.onAsyncInflationFinished(entry);
-
-            mCountDownLatch.countDown();
-        }
-
-        public CountDownLatch getCountDownLatch() {
-            return mCountDownLatch;
-        }
-    }
-
-    private void setUserSentiment(String key, int sentiment) {
-        doAnswer(invocationOnMock -> {
-            NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
-                    invocationOnMock.getArguments()[1];
-            ranking.populate(
-                    key,
-                    0,
-                    false,
-                    0,
-                    0,
-                    NotificationManager.IMPORTANCE_DEFAULT,
-                    null, null,
-                    null, null, null, true, sentiment, false);
-            return true;
-        }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
-    }
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mDependency.injectTestDependency(ForegroundServiceController.class,
-                mForegroundServiceController);
-        mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
-                mLockscreenUserManager);
-        mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
-        mDependency.injectTestDependency(NotificationGutsManager.class, mGutsManager);
-        mDependency.injectTestDependency(NotificationRemoteInputManager.class, mRemoteInputManager);
-        mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager);
-        mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
-        mDependency.injectTestDependency(DeviceProvisionedController.class,
-                mDeviceProvisionedController);
-        mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
-        mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
-        mDependency.injectTestDependency(SmartReplyController.class, mSmartReplyController);
-
-        mCountDownLatch = new CountDownLatch(1);
-
-        when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
-        when(mPresenter.getNotificationLockscreenUserManager()).thenReturn(mLockscreenUserManager);
-        when(mPresenter.getGroupManager()).thenReturn(mGroupManager);
-        when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
-        when(mListContainer.getViewParentForNotification(any())).thenReturn(
-                new FrameLayout(mContext));
-
-        Notification.Builder n = new Notification.Builder(mContext, "")
-                .setSmallIcon(R.drawable.ic_person)
-                .setContentTitle("Title")
-                .setContentText("Text");
-        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
-                0, n.build(), new UserHandle(ActivityManager.getCurrentUser()), null, 0);
-        mEntry = new NotificationData.Entry(mSbn);
-        mEntry.expandedIcon = mock(StatusBarIconView.class);
-
-        mEntryManager = new TestableNotificationEntryManager(mContext, mBarService);
-        mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mCallback, mHeadsUpManager);
-
-        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
-    }
-
-    @Test
-    public void testAddNotification() throws Exception {
-        com.android.systemui.util.Assert.isNotMainThread();
-        TestableLooper.get(this).processAllMessages();
-
-        doAnswer(invocation -> {
-            mCountDownLatch.countDown();
-            return null;
-        }).when(mCallback).onBindRow(any(), any(), any(), any());
-
-        // Post on main thread, otherwise we will be stuck waiting here for the inflation finished
-        // callback forever, since it won't execute until the tests ends.
-        mEntryManager.addNotification(mSbn, mRankingMap);
-        TestableLooper.get(this).processMessages(1);
-        assertTrue(mCountDownLatch.await(10, TimeUnit.SECONDS));
-        assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
-
-        // Check that no inflation error occurred.
-        verify(mBarService, never()).onNotificationError(any(), any(), anyInt(), anyInt(), anyInt(),
-                any(), anyInt());
-        verify(mForegroundServiceController).addNotification(eq(mSbn), anyInt());
-
-        // Row inflation:
-        ArgumentCaptor<NotificationData.Entry> entryCaptor = ArgumentCaptor.forClass(
-                NotificationData.Entry.class);
-        verify(mCallback).onBindRow(entryCaptor.capture(), any(), eq(mSbn), any());
-        NotificationData.Entry entry = entryCaptor.getValue();
-        verify(mRemoteInputManager).bindRow(entry.row);
-
-        // Row content inflation:
-        verify(mCallback).onNotificationAdded(entry);
-        verify(mPresenter).updateNotificationViews();
-
-        assertEquals(mEntryManager.getNotificationData().get(mSbn.getKey()), entry);
-        assertNotNull(entry.row);
-        assertEquals(mEntry.userSentiment,
-                NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
-    }
-
-    @Test
-    public void testUpdateNotification() throws Exception {
-        com.android.systemui.util.Assert.isNotMainThread();
-        TestableLooper.get(this).processAllMessages();
-
-        mEntryManager.getNotificationData().add(mEntry);
-
-        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
-
-        mEntryManager.updateNotification(mSbn, mRankingMap);
-        TestableLooper.get(this).processMessages(1);
-        // Wait for content update.
-        assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
-
-        verify(mBarService, never()).onNotificationError(any(), any(), anyInt(), anyInt(), anyInt(),
-                any(), anyInt());
-
-        verify(mRemoteInputManager).onUpdateNotification(mEntry);
-        verify(mPresenter).updateNotificationViews();
-        verify(mForegroundServiceController).updateNotification(eq(mSbn), anyInt());
-        verify(mCallback).onNotificationUpdated(mSbn);
-        assertNotNull(mEntry.row);
-        assertEquals(mEntry.userSentiment,
-                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
-    }
-
-    @Test
-    public void testRemoveNotification() throws Exception {
-        com.android.systemui.util.Assert.isNotMainThread();
-
-        mEntry.row = mRow;
-        mEntryManager.getNotificationData().add(mEntry);
-
-        mEntryManager.removeNotification(mSbn.getKey(), mRankingMap);
-
-        verify(mBarService, never()).onNotificationError(any(), any(), anyInt(), anyInt(), anyInt(),
-                any(), anyInt());
-
-        verify(mMediaManager).onNotificationRemoved(mSbn.getKey());
-        verify(mRemoteInputManager).onRemoveNotification(mEntry);
-        verify(mSmartReplyController).stopSending(mEntry);
-        verify(mForegroundServiceController).removeNotification(mSbn);
-        verify(mListContainer).cleanUpViewState(mRow);
-        verify(mPresenter).updateNotificationViews();
-        verify(mCallback).onNotificationRemoved(mSbn.getKey(), mSbn);
-        verify(mRow).setRemoved();
-
-        assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
-    }
-
-    @Test
-    public void testRemoveNotification_blockedBySendingSmartReply() throws Exception {
-        com.android.systemui.util.Assert.isNotMainThread();
-
-        mEntry.row = mRow;
-        mEntryManager.getNotificationData().add(mEntry);
-        when(mSmartReplyController.isSendingSmartReply(mEntry.key)).thenReturn(true);
-
-        mEntryManager.removeNotification(mSbn.getKey(), mRankingMap);
-
-        assertNotNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
-        assertTrue(mEntryManager.isNotificationKeptForRemoteInput(mEntry.key));
-    }
-
-    @Test
-    public void testUpdateAppOps_foregroundNoti() {
-        com.android.systemui.util.Assert.isNotMainThread();
-
-        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
-                .thenReturn(mEntry.key);
-        mEntry.row = mRow;
-        mEntryManager.getNotificationData().add(mEntry);
-
-        mEntryManager.updateNotificationsForAppOp(
-                AppOpsManager.OP_CAMERA, mEntry.notification.getUid(),
-                mEntry.notification.getPackageName(), true);
-
-        verify(mPresenter, times(1)).updateNotificationViews();
-        assertTrue(mEntryManager.getNotificationData().get(mEntry.key).mActiveAppOps.contains(
-                AppOpsManager.OP_CAMERA));
-    }
-
-    @Test
-    public void testUpdateAppOps_otherNoti() {
-        com.android.systemui.util.Assert.isNotMainThread();
-
-        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
-                .thenReturn(null);
-        mEntryManager.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
-
-        verify(mPresenter, never()).updateNotificationViews();
-    }
-
-    @Test
-    public void testAddNotificationExistingAppOps() {
-        mEntry.row = mRow;
-        mEntryManager.getNotificationData().add(mEntry);
-        ArraySet<Integer> expected = new ArraySet<>();
-        expected.add(3);
-        expected.add(235);
-        expected.add(1);
-
-        when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(expected);
-        when(mForegroundServiceController.getStandardLayoutKey(
-                mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(mEntry.key);
-
-        mEntryManager.tagForeground(mEntry.notification);
-
-        Assert.assertEquals(expected.size(), mEntry.mActiveAppOps.size());
-        for (int op : expected) {
-            assertTrue("Entry missing op " + op, mEntry.mActiveAppOps.contains(op));
-        }
-    }
-
-    @Test
-    public void testAdd_noExistingAppOps() {
-        mEntry.row = mRow;
-        mEntryManager.getNotificationData().add(mEntry);
-        when(mForegroundServiceController.getStandardLayoutKey(
-                mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(mEntry.key);
-        when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(null);
-
-        mEntryManager.tagForeground(mEntry.notification);
-        Assert.assertEquals(0, mEntry.mActiveAppOps.size());
-    }
-
-    @Test
-    public void testAdd_existingAppOpsNotForegroundNoti() {
-        mEntry.row = mRow;
-        mEntryManager.getNotificationData().add(mEntry);
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(3);
-        ops.add(235);
-        ops.add(1);
-        when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(ops);
-        when(mForegroundServiceController.getStandardLayoutKey(
-                mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn("something else");
-
-        mEntryManager.tagForeground(mEntry.notification);
-        Assert.assertEquals(0, mEntry.mActiveAppOps.size());
-    }
-
-    @Test
-    public void testRebuildWithRemoteInput_noExistingInputNoSpinner() {
-        StatusBarNotification newSbn =
-                mEntryManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false);
-        CharSequence[] messages = newSbn.getNotification().extras
-                .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
-        Assert.assertEquals(1, messages.length);
-        Assert.assertEquals("A Reply", messages[0]);
-        Assert.assertFalse(newSbn.getNotification().extras
-                .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
-        Assert.assertTrue(newSbn.getNotification().extras
-                .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
-    }
-
-    @Test
-    public void testRebuildWithRemoteInput_noExistingInputWithSpinner() {
-        StatusBarNotification newSbn =
-                mEntryManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", true);
-        CharSequence[] messages = newSbn.getNotification().extras
-                .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
-        Assert.assertEquals(1, messages.length);
-        Assert.assertEquals("A Reply", messages[0]);
-        Assert.assertTrue(newSbn.getNotification().extras
-                .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
-        Assert.assertTrue(newSbn.getNotification().extras
-                .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
-    }
-
-    @Test
-    public void testRebuildWithRemoteInput_withExistingInput() {
-        // Setup a notification entry with 1 remote input.
-        StatusBarNotification newSbn =
-                mEntryManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false);
-        NotificationData.Entry entry = new NotificationData.Entry(newSbn);
-
-        // Try rebuilding to add another reply.
-        newSbn = mEntryManager.rebuildNotificationWithRemoteInput(entry, "Reply 2", true);
-        CharSequence[] messages = newSbn.getNotification().extras
-                .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
-        Assert.assertEquals(2, messages.length);
-        Assert.assertEquals("Reply 2", messages[0]);
-        Assert.assertEquals("A Reply", messages[1]);
-    }
-
-    @Test
-    public void testRebuildNotificationForCanceledSmartReplies() {
-        // Try rebuilding to remove spinner and hide buttons.
-        StatusBarNotification newSbn =
-                mEntryManager.rebuildNotificationForCanceledSmartReplies(mEntry);
-        Assert.assertFalse(newSbn.getNotification().extras
-                .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
-        Assert.assertTrue(newSbn.getNotification().extras
-                .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java
deleted file mode 100644
index 72255f3c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsManagerTest.java
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import static android.app.AppOpsManager.OP_CAMERA;
-import static android.app.AppOpsManager.OP_RECORD_AUDIO;
-import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
-
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-import static junit.framework.Assert.assertNotNull;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.times;
-
-import android.app.INotificationManager;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.Handler;
-import android.provider.Settings;
-import android.service.notification.StatusBarNotification;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.util.ArraySet;
-import android.view.View;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoRule;
-import org.mockito.junit.MockitoJUnit;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Tests for {@link NotificationGutsManager}.
- */
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class NotificationGutsManagerTest extends SysuiTestCase {
-    private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
-
-    private NotificationChannel mTestNotificationChannel = new NotificationChannel(
-            TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
-    private TestableLooper mTestableLooper;
-    private Handler mHandler;
-    private NotificationTestHelper mHelper;
-    private NotificationGutsManager mGutsManager;
-
-    @Rule public MockitoRule mockito = MockitoJUnit.rule();
-    @Mock private NotificationPresenter mPresenter;
-    @Mock private NotificationEntryManager mEntryManager;
-    @Mock private NotificationStackScrollLayout mStackScroller;
-    @Mock private NotificationInfo.CheckSaveListener mCheckSaveListener;
-    @Mock private NotificationGutsManager.OnSettingsClickListener mOnSettingsClickListener;
-
-    @Before
-    public void setUp() {
-        mTestableLooper = TestableLooper.get(this);
-        mHandler = Handler.createAsync(mTestableLooper.getLooper());
-
-        mHelper = new NotificationTestHelper(mContext);
-
-        mGutsManager = new NotificationGutsManager(mContext);
-        mGutsManager.setUpWithPresenter(mPresenter, mEntryManager, mStackScroller,
-                mCheckSaveListener, mOnSettingsClickListener);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-    // Test methods:
-
-    @Test
-    public void testOpenAndCloseGuts() {
-        NotificationGuts guts = spy(new NotificationGuts(mContext));
-        when(guts.post(any())).thenAnswer(invocation -> {
-            mHandler.post(((Runnable) invocation.getArguments()[0]));
-            return null;
-        });
-
-        // Test doesn't support animation since the guts view is not attached.
-        doNothing().when(guts).openControls(
-                eq(true) /* shouldDoCircularReveal */,
-                anyInt(),
-                anyInt(),
-                anyBoolean(),
-                any(Runnable.class));
-
-        ExpandableNotificationRow realRow = createTestNotificationRow();
-        NotificationMenuRowPlugin.MenuItem menuItem = createTestMenuItem(realRow);
-
-        ExpandableNotificationRow row = spy(realRow);
-        when(row.getWindowToken()).thenReturn(new Binder());
-        when(row.getGuts()).thenReturn(guts);
-
-        mGutsManager.openGuts(row, 0, 0, menuItem);
-        assertEquals(View.INVISIBLE, guts.getVisibility());
-        mTestableLooper.processAllMessages();
-        verify(guts).openControls(
-                eq(true),
-                anyInt(),
-                anyInt(),
-                anyBoolean(),
-                any(Runnable.class));
-
-        assertEquals(View.VISIBLE, guts.getVisibility());
-        mGutsManager.closeAndSaveGuts(false, false, false, 0, 0, false);
-
-        verify(guts).closeControls(anyBoolean(), anyBoolean(), anyInt(), anyInt(), anyBoolean());
-        verify(row, times(1)).setGutsView(any());
-    }
-
-    @Test
-    public void testChangeDensityOrFontScale() {
-        NotificationGuts guts = spy(new NotificationGuts(mContext));
-        when(guts.post(any())).thenAnswer(invocation -> {
-            mHandler.post(((Runnable) invocation.getArguments()[0]));
-            return null;
-        });
-
-        // Test doesn't support animation since the guts view is not attached.
-        doNothing().when(guts).openControls(
-                eq(true) /* shouldDoCircularReveal */,
-                anyInt(),
-                anyInt(),
-                anyBoolean(),
-                any(Runnable.class));
-
-        ExpandableNotificationRow realRow = createTestNotificationRow();
-        NotificationMenuRowPlugin.MenuItem menuItem = createTestMenuItem(realRow);
-
-        ExpandableNotificationRow row = spy(realRow);
-        when(row.getWindowToken()).thenReturn(new Binder());
-        when(row.getGuts()).thenReturn(guts);
-        doNothing().when(row).inflateGuts();
-
-        mGutsManager.openGuts(row, 0, 0, menuItem);
-        mTestableLooper.processAllMessages();
-        verify(guts).openControls(
-                eq(true),
-                anyInt(),
-                anyInt(),
-                anyBoolean(),
-                any(Runnable.class));
-
-        row.onDensityOrFontScaleChanged();
-        mGutsManager.onDensityOrFontScaleChanged(row);
-        mTestableLooper.processAllMessages();
-
-        mGutsManager.closeAndSaveGuts(false, false, false, 0, 0, false);
-
-        verify(guts).closeControls(anyBoolean(), anyBoolean(), anyInt(), anyInt(), anyBoolean());
-        verify(row, times(2)).setGutsView(any());
-    }
-
-    @Test
-    public void testAppOpsSettingsIntent_camera() {
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(OP_CAMERA);
-        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
-        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
-        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
-        assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
-    }
-
-    @Test
-    public void testAppOpsSettingsIntent_mic() {
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(OP_RECORD_AUDIO);
-        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
-        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
-        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
-        assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
-    }
-
-    @Test
-    public void testAppOpsSettingsIntent_camera_mic() {
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(OP_CAMERA);
-        ops.add(OP_RECORD_AUDIO);
-        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
-        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
-        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
-        assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
-    }
-
-    @Test
-    public void testAppOpsSettingsIntent_overlay() {
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(OP_SYSTEM_ALERT_WINDOW);
-        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
-        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
-        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
-        assertEquals(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, captor.getValue().getAction());
-    }
-
-    @Test
-    public void testAppOpsSettingsIntent_camera_mic_overlay() {
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(OP_CAMERA);
-        ops.add(OP_RECORD_AUDIO);
-        ops.add(OP_SYSTEM_ALERT_WINDOW);
-        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
-        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
-        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
-        assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
-    }
-
-    @Test
-    public void testAppOpsSettingsIntent_camera_overlay() {
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(OP_CAMERA);
-        ops.add(OP_SYSTEM_ALERT_WINDOW);
-        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
-        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
-        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
-        assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
-    }
-
-    @Test
-    public void testAppOpsSettingsIntent_mic_overlay() {
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(OP_RECORD_AUDIO);
-        ops.add(OP_SYSTEM_ALERT_WINDOW);
-        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
-        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
-        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
-        assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
-    }
-
-    @Test
-    public void testInitializeNotificationInfoView_showBlockingHelper() throws Exception {
-        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
-        ExpandableNotificationRow row = spy(mHelper.createRow());
-        row.setBlockingHelperShowing(true);
-        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
-        when(row.getIsNonblockable()).thenReturn(false);
-        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
-
-        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
-
-        verify(notificationInfoView).bindNotification(
-                any(PackageManager.class),
-                any(INotificationManager.class),
-                eq(statusBarNotification.getPackageName()),
-                any(NotificationChannel.class),
-                anyInt(),
-                eq(statusBarNotification),
-                any(NotificationInfo.CheckSaveListener.class),
-                any(NotificationInfo.OnSettingsClickListener.class),
-                any(NotificationInfo.OnAppSettingsClickListener.class),
-                eq(false),
-                eq(true) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */);
-    }
-
-    @Test
-    public void testInitializeNotificationInfoView_dontShowBlockingHelper() throws Exception {
-        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
-        ExpandableNotificationRow row = spy(mHelper.createRow());
-        row.setBlockingHelperShowing(false);
-        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
-        when(row.getIsNonblockable()).thenReturn(false);
-        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
-
-        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
-
-        verify(notificationInfoView).bindNotification(
-                any(PackageManager.class),
-                any(INotificationManager.class),
-                eq(statusBarNotification.getPackageName()),
-                any(NotificationChannel.class),
-                anyInt(),
-                eq(statusBarNotification),
-                any(NotificationInfo.CheckSaveListener.class),
-                any(NotificationInfo.OnSettingsClickListener.class),
-                any(NotificationInfo.OnAppSettingsClickListener.class),
-                eq(false),
-                eq(false) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */);
-    }
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-    // Utility methods:
-
-    private ExpandableNotificationRow createTestNotificationRow() {
-        Notification.Builder nb = new Notification.Builder(mContext,
-                mTestNotificationChannel.getId())
-                                        .setContentTitle("foo")
-                                        .setColorized(true)
-                                        .setFlag(Notification.FLAG_CAN_COLORIZE, true)
-                                        .setSmallIcon(android.R.drawable.sym_def_app_icon);
-
-        try {
-            ExpandableNotificationRow row = mHelper.createRow(nb.build());
-            row.getEntry().channel = mTestNotificationChannel;
-            return row;
-        } catch (Exception e) {
-            fail();
-            return null;
-        }
-    }
-
-    private NotificationMenuRowPlugin.MenuItem createTestMenuItem(ExpandableNotificationRow row) {
-        NotificationMenuRowPlugin menuRow = new NotificationMenuRow(mContext);
-        menuRow.createMenu(row, row.getStatusBarNotification());
-
-        NotificationMenuRowPlugin.MenuItem menuItem = menuRow.getLongpressMenuItem(mContext);
-        assertNotNull(menuItem);
-        return menuItem;
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
deleted file mode 100644
index a72fed4..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ /dev/null
@@ -1,994 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
-import static android.view.View.GONE;
-import static android.view.View.VISIBLE;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.doCallRealMethod;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.INotificationManager;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
-import android.os.IBinder;
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.PollingCheck;
-import android.testing.TestableLooper;
-import android.testing.UiThreadTest;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class NotificationInfoTest extends SysuiTestCase {
-    private static final String TEST_PACKAGE_NAME = "test_package";
-    private static final String TEST_SYSTEM_PACKAGE_NAME = PRINT_SPOOLER_PACKAGE_NAME;
-    private static final int TEST_UID = 1;
-    private static final int MULTIPLE_CHANNEL_COUNT = 2;
-    private static final String TEST_CHANNEL = "test_channel";
-    private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME";
-
-    private TestableLooper mTestableLooper;
-    private NotificationInfo mNotificationInfo;
-    private NotificationChannel mNotificationChannel;
-    private NotificationChannel mDefaultNotificationChannel;
-    private StatusBarNotification mSbn;
-
-    @Rule public MockitoRule mockito = MockitoJUnit.rule();
-    @Mock private MetricsLogger mMetricsLogger;
-    @Mock private INotificationManager mMockINotificationManager;
-    @Mock private PackageManager mMockPackageManager;
-    @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
-
-    @Before
-    public void setUp() throws Exception {
-        mDependency.injectTestDependency(
-                NotificationBlockingHelperManager.class,
-                mBlockingHelperManager);
-        mTestableLooper = TestableLooper.get(this);
-        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
-        mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
-        // Inflate the layout
-        final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
-        mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
-                null);
-        mNotificationInfo.setGutsParent(mock(NotificationGuts.class));
-
-        // PackageManager must return a packageInfo and applicationInfo.
-        final PackageInfo packageInfo = new PackageInfo();
-        packageInfo.packageName = TEST_PACKAGE_NAME;
-        when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt()))
-                .thenReturn(packageInfo);
-        final ApplicationInfo applicationInfo = new ApplicationInfo();
-        applicationInfo.uid = TEST_UID;  // non-zero
-        when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
-                applicationInfo);
-        final PackageInfo systemPackageInfo = new PackageInfo();
-        systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME;
-        when(mMockPackageManager.getPackageInfo(eq(TEST_SYSTEM_PACKAGE_NAME), anyInt()))
-                .thenReturn(systemPackageInfo);
-        when(mMockPackageManager.getPackageInfo(eq("android"), anyInt()))
-                .thenReturn(packageInfo);
-
-        // Package has one channel by default.
-        when(mMockINotificationManager.getNumNotificationChannelsForPackage(
-                eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(1);
-
-        // Some test channels.
-        mNotificationChannel = new NotificationChannel(
-                TEST_CHANNEL, TEST_CHANNEL_NAME, IMPORTANCE_LOW);
-        mDefaultNotificationChannel = new NotificationChannel(
-                NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
-                IMPORTANCE_LOW);
-        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
-                new Notification(), UserHandle.CURRENT, null, 0);
-    }
-
-    // TODO: if tests are taking too long replace this with something that makes the animation
-    // finish instantly.
-    private void waitForUndoButton() {
-        PollingCheck.waitFor(1000,
-                () -> VISIBLE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility());
-    }
-    private void waitForStopButton() {
-        PollingCheck.waitFor(1000,
-                () -> VISIBLE == mNotificationInfo.findViewById(R.id.prompt).getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_SetsTextApplicationName() throws Exception {
-        when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
-        assertTrue(textView.getText().toString().contains("App Name"));
-        assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_SetsPackageIcon() throws Exception {
-        final Drawable iconDrawable = mock(Drawable.class);
-        when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
-                .thenReturn(iconDrawable);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
-        assertEquals(iconDrawable, iconView.getDrawable());
-    }
-
-    @Test
-    public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
-        assertEquals(GONE, groupNameView.getVisibility());
-        final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
-        assertEquals(GONE, groupDividerView.getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_SetsGroupNameIfNonNull() throws Exception {
-        mNotificationChannel.setGroup("test_group_id");
-        final NotificationChannelGroup notificationChannelGroup =
-                new NotificationChannelGroup("test_group_id", "Test Group Name");
-        when(mMockINotificationManager.getNotificationChannelGroupForPackage(
-                eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
-                .thenReturn(notificationChannelGroup);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
-        assertEquals(View.VISIBLE, groupNameView.getVisibility());
-        assertEquals("Test Group Name", groupNameView.getText());
-        final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
-        assertEquals(View.VISIBLE, groupDividerView.getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_SetsTextChannelName() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
-        assertEquals(TEST_CHANNEL_NAME, textView.getText());
-    }
-
-    @Test
-    public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, false);
-        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
-        assertEquals(GONE, textView.getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_DefaultChannelUsesChannelNameIfMoreChannelsExist()
-            throws Exception {
-        // Package has one channel by default.
-        when(mMockINotificationManager.getNumNotificationChannelsForPackage(
-                eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, false);
-        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
-        assertEquals(VISIBLE, textView.getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
-        assertEquals(VISIBLE, textView.getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_BlockButton() throws Exception {
-       mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        final View block = mNotificationInfo.findViewById(R.id.block);
-        final View minimize = mNotificationInfo.findViewById(R.id.minimize);
-        assertEquals(VISIBLE, block.getVisibility());
-        assertEquals(GONE, minimize.getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_MinButton() throws Exception {
-        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        final View block = mNotificationInfo.findViewById(R.id.block);
-        final View minimize = mNotificationInfo.findViewById(R.id.minimize);
-        assertEquals(GONE, block.getVisibility());
-        assertEquals(VISIBLE, minimize.getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
-        final CountDownLatch latch = new CountDownLatch(1);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
-                (View v, NotificationChannel c, int appUid) -> {
-                    assertEquals(mNotificationChannel, c);
-                    latch.countDown();
-                }, null, false);
-
-        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
-        settingsButton.performClick();
-        // Verify that listener was triggered.
-        assertEquals(0, latch.getCount());
-    }
-
-    @Test
-    public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
-        assertTrue(settingsButton.getVisibility() != View.VISIBLE);
-    }
-
-    @Test
-    public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
-                (View v, NotificationChannel c, int appUid) -> {
-                }, null, false);
-        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
-        assertEquals(View.VISIBLE, settingsButton.getVisibility());
-    }
-
-    @Test
-    public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
-        verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
-    }
-
-    @Test
-    public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
-                true);
-        mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
-        verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
-    }
-
-    @Test
-    public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
-        final CountDownLatch latch = new CountDownLatch(1);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null,
-                (View v, NotificationChannel c, int appUid) -> {
-                    assertEquals(null, c);
-                    latch.countDown();
-                }, null, true);
-
-        mNotificationInfo.findViewById(R.id.info).performClick();
-        // Verify that listener was triggered.
-        assertEquals(0, latch.getCount());
-    }
-
-    @Test
-    @UiThreadTest
-    public void testBindNotification_ChannelNameInvisibleWhenBundleFromDifferentChannels()
-            throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
-                null, true);
-        final TextView channelNameView =
-                mNotificationInfo.findViewById(R.id.channel_name);
-        assertEquals(GONE, channelNameView.getVisibility());
-    }
-
-    @Test
-    @UiThreadTest
-    public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
-                null, true);
-        final TextView blockView = mNotificationInfo.findViewById(R.id.block);
-        assertEquals(GONE, blockView.getVisibility());
-    }
-
-    @Test
-    public void testbindNotification_BlockingHelper() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
-                true);
-        final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
-        assertEquals(View.VISIBLE, view.getVisibility());
-        assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
-    }
-
-    @Test
-    public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-        final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
-        assertEquals(View.VISIBLE, view.getVisibility());
-        assertEquals(mContext.getString(R.string.notification_unblockable_desc),
-                view.getText());
-    }
-
-    @Test
-    public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-    }
-
-    @Test
-    public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-    }
-
-    @Test
-    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedMin()
-            throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-    }
-
-    @Test
-    public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
-            throws Exception {
-        int originalImportance = mNotificationChannel.getImportance();
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-
-        mNotificationInfo.handleCloseControls(true, false);
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-        assertEquals(originalImportance, mNotificationChannel.getImportance());
-    }
-
-    @Test
-    public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified()
-            throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-        assertEquals(IMPORTANCE_UNSPECIFIED, mNotificationChannel.getImportance());
-    }
-
-    @Test
-    public void testHandleCloseControls_setsNotificationsDisabledForMultipleChannelNotifications()
-            throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
-                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                false /* isNonblockable */);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1))
-                .setNotificationsEnabledWithImportanceLockForPackage(
-                        anyString(), eq(TEST_UID), eq(false));
-    }
-
-
-    @Test
-    public void testHandleCloseControls_keepsNotificationsEnabledForMultipleChannelNotifications()
-            throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
-                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                false /* isNonblockable */);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1))
-                .setNotificationsEnabledWithImportanceLockForPackage(
-                        anyString(), eq(TEST_UID), eq(false));
-    }
-
-    @Test
-    public void testCloseControls_blockingHelperSavesImportanceForMultipleChannelNotifications()
-            throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
-                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
-
-        NotificationGuts guts = spy(new NotificationGuts(mContext, null));
-        when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
-        doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean());
-        doNothing().when(guts).setExposed(anyBoolean(), anyBoolean());
-        guts.setGutsContent(mNotificationInfo);
-        mNotificationInfo.setGutsParent(guts);
-
-        mNotificationInfo.findViewById(R.id.keep).performClick();
-
-        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1))
-                .setNotificationsEnabledWithImportanceLockForPackage(
-                        anyString(), eq(TEST_UID), eq(true));
-    }
-
-    @Test
-    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing()
-            throws Exception {
-        NotificationInfo.CheckSaveListener listener =
-                mock(NotificationInfo.CheckSaveListener.class);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
-                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
-
-        NotificationGuts guts = spy(new NotificationGuts(mContext, null));
-        when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
-        doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean());
-        doNothing().when(guts).setExposed(anyBoolean(), anyBoolean());
-        guts.setGutsContent(mNotificationInfo);
-        mNotificationInfo.setGutsParent(guts);
-
-        mNotificationInfo.findViewById(R.id.keep).performClick();
-
-        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1))
-                .setNotificationsEnabledWithImportanceLockForPackage(
-                        anyString(), eq(TEST_UID), eq(true));
-    }
-
-    @Test
-    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss()
-            throws Exception {
-        NotificationInfo.CheckSaveListener listener =
-                mock(NotificationInfo.CheckSaveListener.class);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
-                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
-
-        mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
-
-        mTestableLooper.processAllMessages();
-        verify(listener, times(0)).checkSave(any(Runnable.class), eq(mSbn));
-    }
-
-    @Test
-    public void testCloseControls_checkSaveListenerDelaysStopNotifications()
-            throws Exception {
-        NotificationInfo.CheckSaveListener listener =
-                mock(NotificationInfo.CheckSaveListener.class);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
-                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
-
-        mTestableLooper.processAllMessages();
-        verify(listener).checkSave(any(Runnable.class), eq(mSbn));
-    }
-
-    @Test
-    public void testCloseControls_blockingHelperDismissedIfShown() throws Exception {
-        mNotificationInfo.bindNotification(
-                mMockPackageManager,
-                mMockINotificationManager,
-                TEST_PACKAGE_NAME,
-                mNotificationChannel,
-                1 /* numChannels */,
-                mSbn,
-                null /* checkSaveListener */,
-                null /* onSettingsClick */,
-                null /* onAppSettingsClick */,
-                false /* isNonblockable */,
-                true /* isForBlockingHelper */,
-                false /* isUserSentimentNegative */);
-        NotificationGuts guts = mock(NotificationGuts.class);
-        doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
-        mNotificationInfo.setGutsParent(guts);
-
-        mNotificationInfo.closeControls(mNotificationInfo);
-
-        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
-    }
-
-    @Test
-    public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-    }
-
-    @Test
-    public void testBlockChangedCallsUpdateNotificationChannel() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        ArgumentCaptor<NotificationChannel> updated =
-                ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), updated.capture());
-        assertTrue((updated.getValue().getUserLockedFields()
-                & USER_LOCKED_IMPORTANCE) != 0);
-        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
-    }
-
-    @Test
-    public void testBlockChangedCallsUpdateNotificationChannel_blockingHelper() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(
-                mMockPackageManager,
-                mMockINotificationManager,
-                TEST_PACKAGE_NAME,
-                mNotificationChannel,
-                1 /* numChannels */,
-                mSbn,
-                null /* checkSaveListener */,
-                null /* onSettingsClick */,
-                null /* onAppSettingsClick */,
-                false /* isNonblockable */,
-                true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        ArgumentCaptor<NotificationChannel> updated =
-                ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), updated.capture());
-        assertTrue((updated.getValue().getUserLockedFields()
-                & USER_LOCKED_IMPORTANCE) != 0);
-        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
-    }
-
-
-    @Test
-    public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        waitForUndoButton();
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-    }
-
-    @Test
-    public void testMinChangedCallsUpdateNotificationChannel() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        ArgumentCaptor<NotificationChannel> updated =
-                ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), updated.capture());
-        assertTrue((updated.getValue().getUserLockedFields()
-                & USER_LOCKED_IMPORTANCE) != 0);
-        assertEquals(IMPORTANCE_MIN, updated.getValue().getImportance());
-    }
-
-    @Test
-    public void testKeepUpdatesNotificationChannel() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        ArgumentCaptor<NotificationChannel> updated =
-                ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), updated.capture());
-        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
-        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
-    }
-
-    @Test
-    public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.findViewById(R.id.undo).performClick();
-        waitForStopButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        ArgumentCaptor<NotificationChannel> updated =
-                ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), updated.capture());
-        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
-        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
-    }
-
-    @Test
-    public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
-
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        waitForUndoButton();
-        mNotificationInfo.findViewById(R.id.undo).performClick();
-        waitForStopButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        ArgumentCaptor<NotificationChannel> updated =
-                ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), updated.capture());
-        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
-        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
-    }
-
-    @Test
-    public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(false, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
-    }
-
-    @Test
-    public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(false, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
-    }
-
-    @Test
-    public void testCloseControlsDoesNotUpdateIfCheckSaveListenerIsNoOp() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
-                (Runnable saveImportance, StatusBarNotification sbn) -> {
-                }, null, null, true);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
-    }
-
-    @Test
-    public void testCloseControlsUpdatesWhenCheckSaveListenerUsesCallback() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
-                (Runnable saveImportance, StatusBarNotification sbn) -> {
-                    saveImportance.run();
-                }, null, null, false);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
-    }
-
-    @Test
-    public void testDisplaySettingsLink() throws Exception {
-        final CountDownLatch latch = new CountDownLatch(1);
-        final String settingsText = "work chats";
-        final ResolveInfo ri = new ResolveInfo();
-        ri.activityInfo = new ActivityInfo();
-        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
-        ri.activityInfo.name = "something";
-        List<ResolveInfo> ris = new ArrayList<>();
-        ris.add(ri);
-        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
-                .setSettingsText(settingsText).build();
-        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
-                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
-                (View v, Intent intent) -> {
-                    latch.countDown();
-                }, false);
-        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
-        assertEquals(View.VISIBLE, settingsLink.getVisibility());
-        settingsLink.performClick();
-        assertEquals(0, latch.getCount());
-    }
-
-    @Test
-    public void testDisplaySettingsLink_multipleChannels() throws Exception {
-        final CountDownLatch latch = new CountDownLatch(1);
-        final String settingsText = "work chats";
-        final ResolveInfo ri = new ResolveInfo();
-        ri.activityInfo = new ActivityInfo();
-        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
-        ri.activityInfo.name = "something";
-        List<ResolveInfo> ris = new ArrayList<>();
-        ris.add(ri);
-        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
-                .setSettingsText(settingsText).build();
-        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
-                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
-                (View v, Intent intent) -> {
-                    latch.countDown();
-                }, false);
-        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
-        assertEquals(View.VISIBLE, settingsLink.getVisibility());
-        settingsLink.performClick();
-        assertEquals(0, latch.getCount());
-    }
-
-    @Test
-    public void testNoSettingsLink_noHandlingActivity() throws Exception {
-        final String settingsText = "work chats";
-        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(null);
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
-                .setSettingsText(settingsText).build();
-        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
-                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
-                null, false);
-        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
-        assertEquals(GONE, settingsLink.getVisibility());
-    }
-
-    @Test
-    public void testNoSettingsLink_noLinkText() throws Exception {
-        final ResolveInfo ri = new ResolveInfo();
-        ri.activityInfo = new ActivityInfo();
-        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
-        ri.activityInfo.name = "something";
-        List<ResolveInfo> ris = new ArrayList<>();
-        ris.add(ri);
-        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId()).build();
-        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
-                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false);
-        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
-        assertEquals(GONE, settingsLink.getVisibility());
-    }
-
-    @Test
-    public void testBindHeader_noSettingsLinkWhenIsForBlockingHelper() throws Exception {
-        final String settingsText = "work chats";
-        final ResolveInfo ri = new ResolveInfo();
-        ri.activityInfo = new ActivityInfo();
-        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
-        ri.activityInfo.name = "something";
-        List<ResolveInfo> ris = new ArrayList<>();
-        ris.add(ri);
-        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
-                .setSettingsText(settingsText).build();
-        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
-                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
-                true);
-        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
-        assertEquals(GONE, settingsLink.getVisibility());
-    }
-
-
-    @Test
-    public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
-        assertFalse(mNotificationInfo.willBeRemoved());
-    }
-
-    @Test
-    public void testUndoText_min() throws Exception {
-        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        waitForUndoButton();
-        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
-        assertTrue(confirmationText.getText().toString().contains("minimized"));
-    }
-
-    @Test
-    public void testUndoText_block() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
-        assertTrue(confirmationText.getText().toString().contains("won't see"));
-    }
-
-    @Test
-    public void testNoHeaderOnConfirmation() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        assertEquals(GONE, mNotificationInfo.findViewById(R.id.header).getVisibility());
-    }
-
-    @Test
-    public void testHeaderOnUndo() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.findViewById(R.id.undo).performClick();
-        waitForStopButton();
-        assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
index 26f91b3..3cafaf4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
@@ -33,6 +33,8 @@
 import android.testing.TestableLooper;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -40,9 +42,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.HashSet;
-import java.util.Set;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 2401519..a7758a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -41,6 +41,7 @@
 import android.testing.TestableLooper;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
 import com.google.android.collect.Lists;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLoggerTest.java
deleted file mode 100644
index 42bf290..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLoggerTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Notification;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.SysuiTestCase;
-
-import com.google.android.collect.Lists;
-
-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 org.mockito.stubbing.Answer;
-
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class NotificationLoggerTest extends SysuiTestCase {
-    private static final String TEST_PACKAGE_NAME = "test";
-    private static final int TEST_UID = 0;
-
-    @Mock private NotificationPresenter mPresenter;
-    @Mock private NotificationListContainer mListContainer;
-    @Mock private IStatusBarService mBarService;
-    @Mock private NotificationData mNotificationData;
-    @Mock private ExpandableNotificationRow mRow;
-
-    // Dependency mocks:
-    @Mock private NotificationEntryManager mEntryManager;
-    @Mock private NotificationListener mListener;
-
-    private NotificationData.Entry mEntry;
-    private StatusBarNotification mSbn;
-    private TestableNotificationLogger mLogger;
-    private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>();
-
-    @Before
-    public void setUp() throws RemoteException {
-        MockitoAnnotations.initMocks(this);
-        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
-        mDependency.injectTestDependency(NotificationListener.class, mListener);
-
-        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
-
-        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
-                0, new Notification(), UserHandle.CURRENT, null, 0);
-        mEntry = new NotificationData.Entry(mSbn);
-        mEntry.row = mRow;
-
-        mLogger = new TestableNotificationLogger(mBarService);
-        mLogger.setUpWithEntryManager(mEntryManager, mListContainer);
-    }
-
-    @Test
-    public void testOnChildLocationsChangedReportsVisibilityChanged() throws Exception {
-        NotificationVisibility[] newlyVisibleKeys = {
-                NotificationVisibility.obtain(mEntry.key, 0, 1, true)
-        };
-        NotificationVisibility[] noLongerVisibleKeys = {};
-        doAnswer((Answer) invocation -> {
-                    try {
-                        assertArrayEquals(newlyVisibleKeys,
-                                (NotificationVisibility[]) invocation.getArguments()[0]);
-                        assertArrayEquals(noLongerVisibleKeys,
-                                (NotificationVisibility[]) invocation.getArguments()[1]);
-                    } catch (AssertionError error) {
-                        mErrorQueue.offer(error);
-                    }
-                    return null;
-                }
-        ).when(mBarService).onNotificationVisibilityChanged(any(NotificationVisibility[].class),
-                any(NotificationVisibility[].class));
-
-        when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
-        when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
-        mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
-        TestableLooper.get(this).processAllMessages();
-        waitForUiOffloadThread();
-
-        if(!mErrorQueue.isEmpty()) {
-            throw mErrorQueue.poll();
-        }
-
-        // |mEntry| won't change visibility, so it shouldn't be reported again:
-        Mockito.reset(mBarService);
-        mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
-        TestableLooper.get(this).processAllMessages();
-        waitForUiOffloadThread();
-
-        verify(mBarService, never()).onNotificationVisibilityChanged(any(), any());
-    }
-
-    @Test
-    public void testStoppingNotificationLoggingReportsCurrentNotifications()
-            throws Exception {
-        when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
-        when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
-        mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
-        TestableLooper.get(this).processAllMessages();
-        waitForUiOffloadThread();
-        Mockito.reset(mBarService);
-
-        mLogger.stopNotificationLogging();
-        waitForUiOffloadThread();
-        // The visibility objects are recycled by NotificationLogger, so we can't use specific
-        // matchers here.
-        verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any());
-    }
-
-    private class TestableNotificationLogger extends NotificationLogger {
-
-        public TestableNotificationLogger(IStatusBarService barService) {
-            mBarService = barService;
-            // Make this on the current thread so we can wait for it during tests.
-            mHandler = Handler.createAsync(Looper.myLooper());
-        }
-
-        public OnChildLocationsChangedListener
-                getChildLocationsChangedListenerForTest() {
-            return mNotificationLocationsChangedListener;
-        }
-
-        public Handler getHandlerForTest() {
-            return mHandler;
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
deleted file mode 100644
index 2a5a1ee..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.app.Notification;
-import android.service.notification.StatusBarNotification;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
-import android.testing.ViewUtils;
-import android.testing.ViewUtils;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.utils.leaks.LeakCheckedTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-@SmallTest
-public class NotificationMenuRowTest extends LeakCheckedTest {
-
-    @Before
-    public void setup() {
-        injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
-    }
-
-    @Test
-    public void testAttachDetach() {
-        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
-        row.createMenu(null, null);
-        ViewUtils.attachView(row.getMenuView());
-        TestableLooper.get(this).processAllMessages();
-        ViewUtils.detachView(row.getMenuView());
-        TestableLooper.get(this).processAllMessages();
-    }
-
-    @Test
-    public void testRecreateMenu() {
-        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
-        row.createMenu(null, null);
-        assertTrue(row.getMenuView() != null);
-        row.createMenu(null, null);
-        assertTrue(row.getMenuView() != null);
-    }
-
-    @Test
-    public void testResetUncreatedMenu() {
-        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
-        row.resetMenu();
-    }
-
-    @Test
-    public void testNoAppOpsInSlowSwipe() {
-        NotificationMenuRow row = new NotificationMenuRow(mContext);
-        Notification n = mock(Notification.class);
-        StatusBarNotification sbn = mock(StatusBarNotification.class);
-        when(sbn.getNotification()).thenReturn(n);
-        ExpandableNotificationRow parent = mock(ExpandableNotificationRow.class);
-        when(parent.getStatusBarNotification()).thenReturn(sbn);
-        row.createMenu(parent, null);
-
-        ViewGroup container = (ViewGroup) row.getMenuView();
-        // one for snooze and one for noti blocking
-        assertEquals(2, container.getChildCount());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 7a2cb3a..afe2cf6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -19,6 +19,9 @@
 
 import com.android.systemui.SysuiTestCase;
 
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.google.android.collect.Sets;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationSnoozeTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationSnoozeTest.java
deleted file mode 100644
index 756bb1c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationSnoozeTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import android.provider.Settings;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableResources;
-import android.testing.UiThreadTest;
-import android.util.KeyValueListParser;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@UiThreadTest
-public class NotificationSnoozeTest extends SysuiTestCase {
-    private static final int RES_DEFAULT = 2;
-    private static final int[] RES_OPTIONS = {1, 2, 3};
-    private NotificationSnooze mNotificationSnooze;
-    private KeyValueListParser mMockParser;
-
-    @Before
-    public void setUp() throws Exception {
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS, null);
-        TestableResources resources = mContext.getOrCreateTestableResources();
-        resources.addOverride(R.integer.config_notification_snooze_time_default, RES_DEFAULT);
-        resources.addOverride(R.array.config_notification_snooze_times, RES_OPTIONS);
-        mNotificationSnooze = new NotificationSnooze(mContext, null);
-        mMockParser = mock(KeyValueListParser.class);
-    }
-
-    @Test
-    public void testGetOptionsWithNoConfig() throws Exception {
-        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
-        assertEquals(3, result.size());
-        assertEquals(1, result.get(0).getMinutesToSnoozeFor());  // respect order
-        assertEquals(2, result.get(1).getMinutesToSnoozeFor());
-        assertEquals(3, result.get(2).getMinutesToSnoozeFor());
-        assertEquals(2, mNotificationSnooze.getDefaultOption().getMinutesToSnoozeFor());
-    }
-
-    @Test
-    public void testGetOptionsWithInvalidConfig() throws Exception {
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
-                "this is garbage");
-        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
-        assertEquals(3, result.size());
-        assertEquals(1, result.get(0).getMinutesToSnoozeFor());  // respect order
-        assertEquals(2, result.get(1).getMinutesToSnoozeFor());
-        assertEquals(3, result.get(2).getMinutesToSnoozeFor());
-        assertEquals(2, mNotificationSnooze.getDefaultOption().getMinutesToSnoozeFor());
-    }
-
-    @Test
-    public void testGetOptionsWithValidDefault() throws Exception {
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
-                "default=10,options_array=4:5:6:7");
-        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
-        assertNotNull(mNotificationSnooze.getDefaultOption());  // pick one
-    }
-
-    @Test
-    public void testGetOptionsWithValidConfig() throws Exception {
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
-                "default=6,options_array=4:5:6:7");
-        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
-        assertEquals(4, result.size());
-        assertEquals(4, result.get(0).getMinutesToSnoozeFor());  // respect order
-        assertEquals(5, result.get(1).getMinutesToSnoozeFor());
-        assertEquals(6, result.get(2).getMinutesToSnoozeFor());
-        assertEquals(7, result.get(3).getMinutesToSnoozeFor());
-        assertEquals(6, mNotificationSnooze.getDefaultOption().getMinutesToSnoozeFor());
-    }
-
-    @Test
-    public void testGetOptionsWithLongConfig() throws Exception {
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
-                "default=6,options_array=4:5:6:7:8:9:10:11:12:13:14:15:16:17");
-        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
-        assertTrue(result.size() > 3);
-        assertEquals(4, result.get(0).getMinutesToSnoozeFor());  // respect order
-        assertEquals(5, result.get(1).getMinutesToSnoozeFor());
-        assertEquals(6, result.get(2).getMinutesToSnoozeFor());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index c6bcd36..b2170fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -32,7 +32,9 @@
 import android.widget.RemoteViews;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.NotificationInflaterTest;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.NotificationInflaterTest;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -43,8 +45,11 @@
  */
 public class NotificationTestHelper {
 
-    static final String PKG = "com.android.systemui";
-    static final int UID = 1000;
+    /** Package name for testing purposes. */
+    public static final String PKG = "com.android.systemui";
+    /** System UI id for testing purposes. */
+    public static final int UID = 1000;
+
     private static final String GROUP_KEY = "gruKey";
 
     private final Context mContext;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
new file mode 100644
index 0000000..db1e049
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.support.test.filters.SmallTest;
+
+import com.android.internal.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
+public class NotificationUiAdjustmentTest extends SysuiTestCase {
+
+    @Test
+    public void needReinflate_differentLength() {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        Notification.Action action =
+                createActionBuilder("first", R.drawable.ic_corp_icon, pendingIntent).build();
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartActions("first", Collections.emptyList()),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(action))))
+                .isTrue();
+    }
+
+    @Test
+    public void needReinflate_differentLabels() {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        Notification.Action firstAction =
+                createActionBuilder("first", R.drawable.ic_corp_icon, pendingIntent).build();
+        Notification.Action secondAction =
+                createActionBuilder("second", R.drawable.ic_corp_icon, pendingIntent).build();
+
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
+                .isTrue();
+    }
+
+    @Test
+    public void needReinflate_differentIcons() {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        Notification.Action firstAction =
+                createActionBuilder("same", R.drawable.ic_corp_icon, pendingIntent).build();
+        Notification.Action secondAction =
+                createActionBuilder("same", R.drawable.ic_account_circle, pendingIntent)
+                        .build();
+
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
+                .isTrue();
+    }
+
+    @Test
+    public void needReinflate_differentPendingIntent() {
+        PendingIntent firstPendingIntent =
+                PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_VIEW), 0);
+        PendingIntent secondPendingIntent =
+                PendingIntent.getActivity(mContext, 0, new Intent(Intent.ACTION_PROCESS_TEXT), 0);
+        Notification.Action firstAction =
+                createActionBuilder("same", R.drawable.ic_corp_icon, firstPendingIntent)
+                        .build();
+        Notification.Action secondAction =
+                createActionBuilder("same", R.drawable.ic_corp_icon, secondPendingIntent)
+                        .build();
+
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
+                .isTrue();
+    }
+
+    @Test
+    public void needReinflate_differentChoices() {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+
+        RemoteInput firstRemoteInput =
+                createRemoteInput("same", "same", new CharSequence[] {"first"});
+        RemoteInput secondRemoteInput =
+                createRemoteInput("same", "same", new CharSequence[] {"second"});
+
+        Notification.Action firstAction =
+                createActionBuilder("same", R.drawable.ic_corp_icon, pendingIntent)
+                        .addRemoteInput(firstRemoteInput)
+                        .build();
+        Notification.Action secondAction =
+                createActionBuilder("same", R.drawable.ic_corp_icon, pendingIntent)
+                        .addRemoteInput(secondRemoteInput)
+                        .build();
+
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
+                .isTrue();
+    }
+
+    @Test
+    public void needReinflate_differentRemoteInputLabel() {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+
+        RemoteInput firstRemoteInput =
+                createRemoteInput("same", "first", new CharSequence[] {"same"});
+        RemoteInput secondRemoteInput =
+                createRemoteInput("same", "second", new CharSequence[] {"same"});
+
+        Notification.Action firstAction =
+                createActionBuilder("same", R.drawable.ic_corp_icon, pendingIntent)
+                        .addRemoteInput(firstRemoteInput)
+                        .build();
+        Notification.Action secondAction =
+                createActionBuilder("same", R.drawable.ic_corp_icon, pendingIntent)
+                        .addRemoteInput(secondRemoteInput)
+                        .build();
+
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
+                .isTrue();
+    }
+
+    @Test
+    public void needReinflate_negative() {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        RemoteInput firstRemoteInput =
+                createRemoteInput("same", "same", new CharSequence[] {"same"});
+        RemoteInput secondRemoteInput =
+                createRemoteInput("same", "same", new CharSequence[] {"same"});
+
+        Notification.Action firstAction =
+                createActionBuilder("same", R.drawable.ic_corp_icon, pendingIntent)
+                        .addRemoteInput(firstRemoteInput).build();
+        Notification.Action secondAction =
+                createActionBuilder("same", R.drawable.ic_corp_icon, pendingIntent)
+                        .addRemoteInput(secondRemoteInput).build();
+
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions(
+                        "second", Collections.singletonList(secondAction))))
+                .isFalse();
+    }
+
+    @Test
+    public void needReinflate_differentSmartReplies() {
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartReplies("first", new CharSequence[]{"a", "b"}),
+                createUiAdjustmentFromSmartReplies("first", new CharSequence[] {"b", "a"})))
+                .isTrue();
+    }
+
+    @Test
+    public void needReinflate_sameSmartReplies() {
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartReplies("first", new CharSequence[] {"a", "b"}),
+                createUiAdjustmentFromSmartReplies("first", new CharSequence[] {"a", "b"})))
+                .isFalse();
+    }
+
+    private Notification.Action.Builder createActionBuilder(
+            String title, int drawableRes, PendingIntent pendingIntent) {
+        return new Notification.Action.Builder(
+                Icon.createWithResource(mContext, drawableRes), title, pendingIntent);
+    }
+
+    private RemoteInput createRemoteInput(String resultKey, String label, CharSequence[] choices) {
+        return new RemoteInput.Builder(resultKey).setLabel(label).setChoices(choices).build();
+    }
+
+    private NotificationUiAdjustment createUiAdjustmentFromSmartActions(
+            String key, List<Notification.Action> actions) {
+        return new NotificationUiAdjustment(key, actions, new CharSequence[0]);
+    }
+
+    private NotificationUiAdjustment createUiAdjustmentFromSmartReplies(
+            String key, CharSequence[] replies) {
+        return new NotificationUiAdjustment(key, Collections.emptyList(), replies);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 0d0d1f86..15c18e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -34,7 +34,13 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 
 import com.google.android.collect.Lists;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
index e91530d..ada5785 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -33,6 +33,8 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
index 00e9995..b7aa21b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
@@ -26,7 +26,7 @@
 import android.widget.FrameLayout;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationTestHelper;
 
 import org.junit.Assert;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java
new file mode 100644
index 0000000..78be783
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.AppOpsManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationPresenter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class AppOpsListenerTest extends SysuiTestCase {
+    private static final String TEST_PACKAGE_NAME = "test";
+    private static final int TEST_UID = 0;
+
+    @Mock private NotificationPresenter mPresenter;
+    @Mock private AppOpsManager mAppOpsManager;
+
+    // Dependency mocks:
+    @Mock private NotificationEntryManager mEntryManager;
+    @Mock private ForegroundServiceController mFsc;
+
+    private AppOpsListener mListener;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
+        mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
+        getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
+        when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
+
+        mListener = new AppOpsListener(mContext);
+    }
+
+    @Test
+    public void testOnlyListenForFewOps() {
+        mListener.setUpWithPresenter(mPresenter, mEntryManager);
+
+        verify(mAppOpsManager, times(1)).startWatchingActive(AppOpsListener.OPS, mListener);
+    }
+
+    @Test
+    public void testStopListening() {
+        mListener.destroy();
+        verify(mAppOpsManager, times(1)).stopWatchingActive(mListener);
+    }
+
+    @Test
+    public void testInformEntryMgrOnAppOpsChange() {
+        mListener.setUpWithPresenter(mPresenter, mEntryManager);
+        mListener.onOpActiveChanged(
+                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+        TestableLooper.get(this).processAllMessages();
+        verify(mEntryManager, times(1)).updateNotificationsForAppOp(
+                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+    }
+
+    @Test
+    public void testInformFscOnAppOpsChange() {
+        mListener.setUpWithPresenter(mPresenter, mEntryManager);
+        mListener.onOpActiveChanged(
+                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+        TestableLooper.get(this).processAllMessages();
+        verify(mFsc, times(1)).onAppOpChanged(
+                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
new file mode 100644
index 0000000..de5a8a0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import static android.app.AppOpsManager.OP_ACCEPT_HANDOVER;
+import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.Notification.CATEGORY_ALARM;
+import static android.app.Notification.CATEGORY_CALL;
+import static android.app.Notification.CATEGORY_EVENT;
+import static android.app.Notification.CATEGORY_MESSAGE;
+import static android.app.Notification.CATEGORY_REMINDER;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Icon;
+import android.media.session.MediaSession;
+import android.os.Bundle;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.SnoozeCriterion;
+import android.service.notification.StatusBarNotification;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.util.ArraySet;
+
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+public class NotificationDataTest extends SysuiTestCase {
+
+    private static final int UID_NORMAL = 123;
+    private static final int UID_ALLOW_DURING_SETUP = 456;
+    private static final String TEST_HIDDEN_NOTIFICATION_KEY = "testHiddenNotificationKey";
+    private static final String TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY = "exempt";
+    private static final NotificationChannel NOTIFICATION_CHANNEL =
+            new NotificationChannel("id", "name", NotificationChannel.USER_LOCKED_IMPORTANCE);
+
+    private final StatusBarNotification mMockStatusBarNotification =
+            mock(StatusBarNotification.class);
+    @Mock
+    ForegroundServiceController mFsc;
+    @Mock
+    NotificationData.Environment mEnvironment;
+
+    private final IPackageManager mMockPackageManager = mock(IPackageManager.class);
+    private NotificationData mNotificationData;
+    private ExpandableNotificationRow mRow;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(mMockStatusBarNotification.getUid()).thenReturn(UID_NORMAL);
+
+        when(mMockPackageManager.checkUidPermission(
+                eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
+                eq(UID_NORMAL)))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
+        when(mMockPackageManager.checkUidPermission(
+                eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
+                eq(UID_ALLOW_DURING_SETUP)))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+
+        mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
+        when(mEnvironment.getGroupManager()).thenReturn(new NotificationGroupManager());
+        when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
+        when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
+        mNotificationData = new TestableNotificationData(mEnvironment);
+        mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class));
+        mRow = new NotificationTestHelper(getContext()).createRow();
+    }
+
+    @Test
+    @UiThreadTest
+    public void testShowNotificationEvenIfUnprovisioned_FalseIfNoExtra() {
+        initStatusBarNotification(false);
+        when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP);
+
+        assertFalse(
+                NotificationData.showNotificationEvenIfUnprovisioned(
+                        mMockPackageManager,
+                        mMockStatusBarNotification));
+    }
+
+    @Test
+    @UiThreadTest
+    public void testShowNotificationEvenIfUnprovisioned_FalseIfNoPermission() {
+        initStatusBarNotification(true);
+
+        assertFalse(
+                NotificationData.showNotificationEvenIfUnprovisioned(
+                        mMockPackageManager,
+                        mMockStatusBarNotification));
+    }
+
+    @Test
+    @UiThreadTest
+    public void testShowNotificationEvenIfUnprovisioned_TrueIfHasPermissionAndExtra() {
+        initStatusBarNotification(true);
+        when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP);
+
+        assertTrue(
+                NotificationData.showNotificationEvenIfUnprovisioned(
+                        mMockPackageManager,
+                        mMockStatusBarNotification));
+    }
+
+    @Test
+    public void testChannelSetWhenAdded() {
+        mNotificationData.add(mRow.getEntry());
+        assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().channel);
+    }
+
+    @Test
+    public void testAllRelevantNotisTaggedWithAppOps() throws Exception {
+        mNotificationData.add(mRow.getEntry());
+        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow();
+        mNotificationData.add(row2.getEntry());
+        ExpandableNotificationRow diffPkg =
+                new NotificationTestHelper(getContext()).createRow("pkg", 4000);
+        mNotificationData.add(diffPkg.getEntry());
+
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_CAMERA);
+        expectedOps.add(OP_ACCEPT_HANDOVER);
+
+        for (int op : expectedOps) {
+            mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
+                    NotificationTestHelper.PKG, mRow.getEntry().key, true);
+            mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
+                    NotificationTestHelper.PKG, row2.getEntry().key, true);
+        }
+        for (int op : expectedOps) {
+            assertTrue(mRow.getEntry().key + " doesn't have op " + op,
+                    mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(op));
+            assertTrue(row2.getEntry().key + " doesn't have op " + op,
+                    mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(op));
+            assertFalse(diffPkg.getEntry().key + " has op " + op,
+                    mNotificationData.get(diffPkg.getEntry().key).mActiveAppOps.contains(op));
+        }
+    }
+
+    @Test
+    public void testAppOpsRemoval() throws Exception {
+        mNotificationData.add(mRow.getEntry());
+        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow();
+        mNotificationData.add(row2.getEntry());
+
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_CAMERA);
+        expectedOps.add(OP_ACCEPT_HANDOVER);
+
+        for (int op : expectedOps) {
+            mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
+                    NotificationTestHelper.PKG, row2.getEntry().key, true);
+        }
+
+        expectedOps.remove(OP_ACCEPT_HANDOVER);
+        mNotificationData.updateAppOp(OP_ACCEPT_HANDOVER, NotificationTestHelper.UID,
+                NotificationTestHelper.PKG, row2.getEntry().key, false);
+
+        assertTrue(mRow.getEntry().key + " doesn't have op " + OP_CAMERA,
+                mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(OP_CAMERA));
+        assertTrue(row2.getEntry().key + " doesn't have op " + OP_CAMERA,
+                mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(OP_CAMERA));
+        assertFalse(mRow.getEntry().key + " has op " + OP_ACCEPT_HANDOVER,
+                mNotificationData.get(mRow.getEntry().key)
+                        .mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
+        assertFalse(row2.getEntry().key + " has op " + OP_ACCEPT_HANDOVER,
+                mNotificationData.get(row2.getEntry().key)
+                        .mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
+    }
+
+    @Test
+    public void testSuppressSystemAlertNotification() {
+        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
+        when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
+        StatusBarNotification sbn = mRow.getEntry().notification;
+        Bundle bundle = new Bundle();
+        bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[] {"something"});
+        sbn.getNotification().extras = bundle;
+
+        assertTrue(mNotificationData.shouldFilterOut(mRow.getEntry()));
+    }
+
+    @Test
+    public void testDoNotSuppressSystemAlertNotification() {
+        StatusBarNotification sbn = mRow.getEntry().notification;
+        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(mNotificationData.shouldFilterOut(mRow.getEntry()));
+
+        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
+        when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
+
+        assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry()));
+
+        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
+        when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
+
+        assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry()));
+    }
+
+    @Test
+    public void testDoNotSuppressMalformedSystemAlertNotification() {
+        when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
+
+        // missing extra
+        assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry()));
+
+        StatusBarNotification sbn = mRow.getEntry().notification;
+        Bundle bundle = new Bundle();
+        bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[] {});
+        sbn.getNotification().extras = bundle;
+
+        // extra missing values
+        assertFalse(mNotificationData.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
+        when(mMockStatusBarNotification.getKey()).thenReturn(TEST_HIDDEN_NOTIFICATION_KEY);
+        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
+        assertTrue(mNotificationData.shouldFilterOut(entry));
+
+        // not hidden
+        when(mMockStatusBarNotification.getKey()).thenReturn("not hidden");
+        entry = new NotificationData.Entry(mMockStatusBarNotification);
+        assertFalse(mNotificationData.shouldFilterOut(entry));
+    }
+
+    @Test
+    public void testGetNotificationsForCurrentUser_shouldFilterNonCurrentUserNotifications()
+            throws Exception {
+        mNotificationData.add(mRow.getEntry());
+        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext()).createRow();
+        mNotificationData.add(row2.getEntry());
+
+        when(mEnvironment.isNotificationForCurrentProfiles(
+                mRow.getEntry().notification)).thenReturn(false);
+        when(mEnvironment.isNotificationForCurrentProfiles(
+                row2.getEntry().notification)).thenReturn(true);
+        ArrayList<NotificationData.Entry> reuslt =
+                mNotificationData.getNotificationsForCurrentUser();
+
+        assertEquals(reuslt.size(), 1);
+        junit.framework.Assert.assertEquals(reuslt.get(0), row2.getEntry());
+    }
+
+    @Test
+    public void testIsExemptFromDndVisualSuppression_foreground() {
+        initStatusBarNotification(false);
+        when(mMockStatusBarNotification.getKey()).thenReturn(
+                TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
+        Notification n = mMockStatusBarNotification.getNotification();
+        n.flags = Notification.FLAG_FOREGROUND_SERVICE;
+        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
+
+        assertTrue(mNotificationData.isExemptFromDndVisualSuppression(entry));
+        assertFalse(mNotificationData.shouldSuppressAmbient(entry));
+    }
+
+    @Test
+    public void testIsExemptFromDndVisualSuppression_media() {
+        initStatusBarNotification(false);
+        when(mMockStatusBarNotification.getKey()).thenReturn(
+                TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
+        Notification n = mMockStatusBarNotification.getNotification();
+        Notification.Builder nb = Notification.Builder.recoverBuilder(mContext, n);
+        nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
+        n = nb.build();
+        when(mMockStatusBarNotification.getNotification()).thenReturn(n);
+        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
+
+        assertTrue(mNotificationData.isExemptFromDndVisualSuppression(entry));
+        assertFalse(mNotificationData.shouldSuppressAmbient(entry));
+    }
+
+    @Test
+    public void testIsExemptFromDndVisualSuppression_system() {
+        initStatusBarNotification(false);
+        when(mMockStatusBarNotification.getKey()).thenReturn(
+                TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
+        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
+        entry.mIsSystemNotification = true;
+
+        assertTrue(mNotificationData.isExemptFromDndVisualSuppression(entry));
+        assertFalse(mNotificationData.shouldSuppressAmbient(entry));
+    }
+
+    @Test
+    public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() {
+        initStatusBarNotification(false);
+        when(mMockStatusBarNotification.getKey()).thenReturn(
+                TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
+        NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
+        entry.mIsSystemNotification = true;
+        when(mMockStatusBarNotification.getNotification()).thenReturn(
+                new Notification.Builder(mContext, "").setCategory(CATEGORY_CALL).build());
+
+        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+        assertTrue(mNotificationData.shouldSuppressAmbient(entry));
+
+        when(mMockStatusBarNotification.getNotification()).thenReturn(
+                new Notification.Builder(mContext, "").setCategory(CATEGORY_REMINDER).build());
+
+        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+
+        when(mMockStatusBarNotification.getNotification()).thenReturn(
+                new Notification.Builder(mContext, "").setCategory(CATEGORY_ALARM).build());
+
+        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+
+        when(mMockStatusBarNotification.getNotification()).thenReturn(
+                new Notification.Builder(mContext, "").setCategory(CATEGORY_EVENT).build());
+
+        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+
+        when(mMockStatusBarNotification.getNotification()).thenReturn(
+                new Notification.Builder(mContext, "").setCategory(CATEGORY_MESSAGE).build());
+
+        assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+    }
+
+    @Test
+    public void testCreateNotificationDataEntry_RankingUpdate() {
+        Ranking ranking = mock(Ranking.class);
+
+        ArrayList<Notification.Action> smartActions = new ArrayList<>();
+        smartActions.add(createAction());
+        when(ranking.getSmartActions()).thenReturn(smartActions);
+
+        when(ranking.getChannel()).thenReturn(NOTIFICATION_CHANNEL);
+
+        when(ranking.getUserSentiment()).thenReturn(Ranking.USER_SENTIMENT_NEGATIVE);
+
+        SnoozeCriterion snoozeCriterion = new SnoozeCriterion("id", "explanation", "confirmation");
+        ArrayList<SnoozeCriterion> snoozeCriterions = new ArrayList<>();
+        snoozeCriterions.add(snoozeCriterion);
+        when(ranking.getSnoozeCriteria()).thenReturn(snoozeCriterions);
+
+        NotificationData.Entry entry =
+                new NotificationData.Entry(mMockStatusBarNotification, ranking);
+
+        assertEquals(smartActions, entry.smartActions);
+        assertEquals(NOTIFICATION_CHANNEL, entry.channel);
+        assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, entry.userSentiment);
+        assertEquals(snoozeCriterions, entry.snoozeCriteria);
+    }
+
+    private void initStatusBarNotification(boolean allowDuringSetup) {
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
+        Notification notification = new Notification.Builder(mContext, "test")
+                .addExtras(bundle)
+                .build();
+        when(mMockStatusBarNotification.getNotification()).thenReturn(notification);
+    }
+
+    private class TestableNotificationData extends NotificationData {
+        public TestableNotificationData(Environment environment) {
+            super(environment);
+        }
+
+        @Override
+        protected boolean getRanking(String key, Ranking outRanking) {
+            super.getRanking(key, outRanking);
+            if (key.equals(TEST_HIDDEN_NOTIFICATION_KEY)) {
+                outRanking.populate(key, outRanking.getRank(),
+                        outRanking.matchesInterruptionFilter(),
+                        outRanking.getVisibilityOverride(), outRanking.getSuppressedVisualEffects(),
+                        outRanking.getImportance(), outRanking.getImportanceExplanation(),
+                        outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
+                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true,
+                        null, null);
+            } else if (key.equals(TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY)) {
+                outRanking.populate(key, outRanking.getRank(),
+                        outRanking.matchesInterruptionFilter(),
+                        outRanking.getVisibilityOverride(), 255,
+                        outRanking.getImportance(), outRanking.getImportanceExplanation(),
+                        outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
+                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true, null, null);
+            } else {
+                outRanking.populate(key, outRanking.getRank(),
+                        outRanking.matchesInterruptionFilter(),
+                        outRanking.getVisibilityOverride(), outRanking.getSuppressedVisualEffects(),
+                        outRanking.getImportance(), outRanking.getImportanceExplanation(),
+                        outRanking.getOverrideGroupKey(), NOTIFICATION_CHANNEL, null, null,
+                        outRanking.canShowBadge(), outRanking.getUserSentiment(), false, null,
+                        null);
+            }
+            return true;
+        }
+    }
+
+    private Notification.Action createAction() {
+        return new Notification.Action.Builder(
+                Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
+                "action",
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
new file mode 100644
index 0000000..6543bdb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -0,0 +1,534 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.assertFalse;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.ArraySet;
+import android.widget.FrameLayout;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.row.RowInflaterTask;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationEntryManagerTest extends SysuiTestCase {
+    private static final String TEST_PACKAGE_NAME = "test";
+    private static final int TEST_UID = 0;
+
+    @Mock private NotificationPresenter mPresenter;
+    @Mock private ExpandableNotificationRow mRow;
+    @Mock private NotificationListContainer mListContainer;
+    @Mock private NotificationEntryManager.Callback mCallback;
+    @Mock private HeadsUpManager mHeadsUpManager;
+    @Mock private NotificationListenerService.RankingMap mRankingMap;
+    @Mock private RemoteInputController mRemoteInputController;
+    @Mock private IStatusBarService mBarService;
+
+    // Dependency mocks:
+    @Mock private ForegroundServiceController mForegroundServiceController;
+    @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
+    @Mock private NotificationGroupManager mGroupManager;
+    @Mock private NotificationGutsManager mGutsManager;
+    @Mock private NotificationRemoteInputManager mRemoteInputManager;
+    @Mock private NotificationMediaManager mMediaManager;
+    @Mock private NotificationListener mNotificationListener;
+    @Mock private DeviceProvisionedController mDeviceProvisionedController;
+    @Mock private VisualStabilityManager mVisualStabilityManager;
+    @Mock private MetricsLogger mMetricsLogger;
+    @Mock private SmartReplyController mSmartReplyController;
+    @Mock private RowInflaterTask mAsyncInflationTask;
+
+    private NotificationData.Entry mEntry;
+    private StatusBarNotification mSbn;
+    private TestableNotificationEntryManager mEntryManager;
+    private CountDownLatch mCountDownLatch;
+
+    private class TestableNotificationEntryManager extends NotificationEntryManager {
+        private final CountDownLatch mCountDownLatch;
+
+        public TestableNotificationEntryManager(Context context, IStatusBarService barService) {
+            super(context);
+            mBarService = barService;
+            mCountDownLatch = new CountDownLatch(1);
+            mUseHeadsUp = true;
+        }
+
+        @Override
+        public void onAsyncInflationFinished(NotificationData.Entry entry) {
+            super.onAsyncInflationFinished(entry);
+
+            mCountDownLatch.countDown();
+        }
+
+        public CountDownLatch getCountDownLatch() {
+            return mCountDownLatch;
+        }
+    }
+
+    private void setUserSentiment(String key, int sentiment) {
+        doAnswer(invocationOnMock -> {
+            NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
+                    invocationOnMock.getArguments()[1];
+            ranking.populate(
+                    key,
+                    0,
+                    false,
+                    0,
+                    0,
+                    NotificationManager.IMPORTANCE_DEFAULT,
+                    null, null,
+                    null, null, null, true, sentiment, false, null, null);
+            return true;
+        }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
+    }
+
+    private void setSmartActions(String key, ArrayList<Notification.Action> smartActions) {
+        doAnswer(invocationOnMock -> {
+            NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
+                    invocationOnMock.getArguments()[1];
+            ranking.populate(
+                    key,
+                    0,
+                    false,
+                    0,
+                    0,
+                    NotificationManager.IMPORTANCE_DEFAULT,
+                    null, null,
+                    null, null, null, true,
+                    NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false,
+                    smartActions, null);
+            return true;
+        }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mDependency.injectTestDependency(ForegroundServiceController.class,
+                mForegroundServiceController);
+        mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
+                mLockscreenUserManager);
+        mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
+        mDependency.injectTestDependency(NotificationGutsManager.class, mGutsManager);
+        mDependency.injectTestDependency(NotificationRemoteInputManager.class, mRemoteInputManager);
+        mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager);
+        mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
+        mDependency.injectTestDependency(DeviceProvisionedController.class,
+                mDeviceProvisionedController);
+        mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
+        mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
+        mDependency.injectTestDependency(SmartReplyController.class, mSmartReplyController);
+
+        mCountDownLatch = new CountDownLatch(1);
+
+        when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
+        when(mPresenter.getNotificationLockscreenUserManager()).thenReturn(mLockscreenUserManager);
+        when(mPresenter.getGroupManager()).thenReturn(mGroupManager);
+        when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
+        when(mListContainer.getViewParentForNotification(any())).thenReturn(
+                new FrameLayout(mContext));
+
+        Notification.Builder n = new Notification.Builder(mContext, "")
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
+                0, n.build(), new UserHandle(ActivityManager.getCurrentUser()), null, 0);
+        mEntry = new NotificationData.Entry(mSbn);
+        mEntry.expandedIcon = mock(StatusBarIconView.class);
+
+        mEntryManager = new TestableNotificationEntryManager(mContext, mBarService);
+        mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mCallback, mHeadsUpManager);
+
+        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
+    }
+
+    @Test
+    public void testAddNotification() throws Exception {
+        com.android.systemui.util.Assert.isNotMainThread();
+        TestableLooper.get(this).processAllMessages();
+
+        doAnswer(invocation -> {
+            mCountDownLatch.countDown();
+            return null;
+        }).when(mCallback).onBindRow(any(), any(), any(), any());
+
+        // Post on main thread, otherwise we will be stuck waiting here for the inflation finished
+        // callback forever, since it won't execute until the tests ends.
+        mEntryManager.addNotification(mSbn, mRankingMap);
+        TestableLooper.get(this).processMessages(1);
+        assertTrue(mCountDownLatch.await(10, TimeUnit.SECONDS));
+        assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
+
+        // Check that no inflation error occurred.
+        verify(mBarService, never()).onNotificationError(any(), any(), anyInt(), anyInt(), anyInt(),
+                any(), anyInt());
+        verify(mForegroundServiceController).addNotification(eq(mSbn), anyInt());
+
+        // Row inflation:
+        ArgumentCaptor<NotificationData.Entry> entryCaptor = ArgumentCaptor.forClass(
+                NotificationData.Entry.class);
+        verify(mCallback).onBindRow(entryCaptor.capture(), any(), eq(mSbn), any());
+        NotificationData.Entry entry = entryCaptor.getValue();
+        verify(mRemoteInputManager).bindRow(entry.row);
+
+        // Row content inflation:
+        verify(mCallback).onNotificationAdded(entry);
+        verify(mPresenter).updateNotificationViews();
+
+        assertEquals(mEntryManager.getNotificationData().get(mSbn.getKey()), entry);
+        assertNotNull(entry.row);
+        assertEquals(mEntry.userSentiment,
+                NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
+    }
+
+    @Test
+    public void testUpdateNotification() throws Exception {
+        com.android.systemui.util.Assert.isNotMainThread();
+        TestableLooper.get(this).processAllMessages();
+
+        mEntryManager.getNotificationData().add(mEntry);
+
+        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+
+        mEntryManager.updateNotification(mSbn, mRankingMap);
+        TestableLooper.get(this).processMessages(1);
+        // Wait for content update.
+        assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
+
+        verify(mBarService, never()).onNotificationError(any(), any(), anyInt(), anyInt(), anyInt(),
+                any(), anyInt());
+
+        verify(mRemoteInputManager).onUpdateNotification(mEntry);
+        verify(mPresenter).updateNotificationViews();
+        verify(mForegroundServiceController).updateNotification(eq(mSbn), anyInt());
+        verify(mCallback).onNotificationUpdated(mSbn);
+        assertNotNull(mEntry.row);
+        assertEquals(mEntry.userSentiment,
+                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+    }
+
+    @Test
+    public void testRemoveNotification() throws Exception {
+        com.android.systemui.util.Assert.isNotMainThread();
+
+        mEntry.row = mRow;
+        mEntryManager.getNotificationData().add(mEntry);
+
+        mEntryManager.removeNotification(mSbn.getKey(), mRankingMap);
+
+        verify(mBarService, never()).onNotificationError(any(), any(), anyInt(), anyInt(), anyInt(),
+                any(), anyInt());
+
+        verify(mMediaManager).onNotificationRemoved(mSbn.getKey());
+        verify(mRemoteInputManager).onRemoveNotification(mEntry);
+        verify(mSmartReplyController).stopSending(mEntry);
+        verify(mForegroundServiceController).removeNotification(mSbn);
+        verify(mListContainer).cleanUpViewState(mRow);
+        verify(mPresenter).updateNotificationViews();
+        verify(mCallback).onNotificationRemoved(mSbn.getKey(), mSbn);
+        verify(mRow).setRemoved();
+
+        assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
+    }
+
+    @Test
+    public void testRemoveNotification_blockedBySendingSmartReply() throws Exception {
+        com.android.systemui.util.Assert.isNotMainThread();
+
+        mEntry.row = mRow;
+        mEntryManager.getNotificationData().add(mEntry);
+        when(mSmartReplyController.isSendingSmartReply(mEntry.key)).thenReturn(true);
+
+        mEntryManager.removeNotification(mSbn.getKey(), mRankingMap);
+
+        assertNotNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
+        assertTrue(mEntryManager.isNotificationKeptForRemoteInput(mEntry.key));
+    }
+
+    @Test
+    public void testUpdateAppOps_foregroundNoti() {
+        com.android.systemui.util.Assert.isNotMainThread();
+
+        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
+                .thenReturn(mEntry.key);
+        mEntry.row = mRow;
+        mEntryManager.getNotificationData().add(mEntry);
+
+        mEntryManager.updateNotificationsForAppOp(
+                AppOpsManager.OP_CAMERA, mEntry.notification.getUid(),
+                mEntry.notification.getPackageName(), true);
+
+        verify(mPresenter, times(1)).updateNotificationViews();
+        assertTrue(mEntryManager.getNotificationData().get(mEntry.key).mActiveAppOps.contains(
+                AppOpsManager.OP_CAMERA));
+    }
+
+    @Test
+    public void testUpdateAppOps_otherNoti() {
+        com.android.systemui.util.Assert.isNotMainThread();
+
+        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
+                .thenReturn(null);
+        mEntryManager.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
+
+        verify(mPresenter, never()).updateNotificationViews();
+    }
+
+    @Test
+    public void testAddNotificationExistingAppOps() {
+        mEntry.row = mRow;
+        mEntryManager.getNotificationData().add(mEntry);
+        ArraySet<Integer> expected = new ArraySet<>();
+        expected.add(3);
+        expected.add(235);
+        expected.add(1);
+
+        when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
+                mEntry.notification.getPackageName())).thenReturn(expected);
+        when(mForegroundServiceController.getStandardLayoutKey(
+                mEntry.notification.getUserId(),
+                mEntry.notification.getPackageName())).thenReturn(mEntry.key);
+
+        mEntryManager.tagForeground(mEntry.notification);
+
+        Assert.assertEquals(expected.size(), mEntry.mActiveAppOps.size());
+        for (int op : expected) {
+            assertTrue("Entry missing op " + op, mEntry.mActiveAppOps.contains(op));
+        }
+    }
+
+    @Test
+    public void testAdd_noExistingAppOps() {
+        mEntry.row = mRow;
+        mEntryManager.getNotificationData().add(mEntry);
+        when(mForegroundServiceController.getStandardLayoutKey(
+                mEntry.notification.getUserId(),
+                mEntry.notification.getPackageName())).thenReturn(mEntry.key);
+        when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
+                mEntry.notification.getPackageName())).thenReturn(null);
+
+        mEntryManager.tagForeground(mEntry.notification);
+        Assert.assertEquals(0, mEntry.mActiveAppOps.size());
+    }
+
+    @Test
+    public void testAdd_existingAppOpsNotForegroundNoti() {
+        mEntry.row = mRow;
+        mEntryManager.getNotificationData().add(mEntry);
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(3);
+        ops.add(235);
+        ops.add(1);
+        when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
+                mEntry.notification.getPackageName())).thenReturn(ops);
+        when(mForegroundServiceController.getStandardLayoutKey(
+                mEntry.notification.getUserId(),
+                mEntry.notification.getPackageName())).thenReturn("something else");
+
+        mEntryManager.tagForeground(mEntry.notification);
+        Assert.assertEquals(0, mEntry.mActiveAppOps.size());
+    }
+
+    @Test
+    public void testRebuildWithRemoteInput_noExistingInputNoSpinner() {
+        StatusBarNotification newSbn =
+                mEntryManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false);
+        CharSequence[] messages = newSbn.getNotification().extras
+                .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+        Assert.assertEquals(1, messages.length);
+        Assert.assertEquals("A Reply", messages[0]);
+        Assert.assertFalse(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+        Assert.assertTrue(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
+    }
+
+    @Test
+    public void testRebuildWithRemoteInput_noExistingInputWithSpinner() {
+        StatusBarNotification newSbn =
+                mEntryManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", true);
+        CharSequence[] messages = newSbn.getNotification().extras
+                .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+        Assert.assertEquals(1, messages.length);
+        Assert.assertEquals("A Reply", messages[0]);
+        Assert.assertTrue(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+        Assert.assertTrue(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
+    }
+
+    @Test
+    public void testRebuildWithRemoteInput_withExistingInput() {
+        // Setup a notification entry with 1 remote input.
+        StatusBarNotification newSbn =
+                mEntryManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false);
+        NotificationData.Entry entry = new NotificationData.Entry(newSbn);
+
+        // Try rebuilding to add another reply.
+        newSbn = mEntryManager.rebuildNotificationWithRemoteInput(entry, "Reply 2", true);
+        CharSequence[] messages = newSbn.getNotification().extras
+                .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
+        Assert.assertEquals(2, messages.length);
+        Assert.assertEquals("Reply 2", messages[0]);
+        Assert.assertEquals("A Reply", messages[1]);
+    }
+
+    @Test
+    public void testRebuildNotificationForCanceledSmartReplies() {
+        // Try rebuilding to remove spinner and hide buttons.
+        StatusBarNotification newSbn =
+                mEntryManager.rebuildNotificationForCanceledSmartReplies(mEntry);
+        Assert.assertFalse(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
+        Assert.assertTrue(newSbn.getNotification().extras
+                .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
+    }
+
+    @Test
+    public void testUpdateNotificationRanking() {
+        when(mPresenter.isDeviceProvisioned()).thenReturn(true);
+        when(mPresenter.isNotificationForCurrentProfiles(any())).thenReturn(true);
+
+        mEntry.row = mRow;
+        mEntry.setInflationTask(mAsyncInflationTask);
+        mEntryManager.getNotificationData().add(mEntry);
+        setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction())));
+
+        mEntryManager.updateNotificationRanking(mRankingMap);
+        verify(mRow).updateNotification(eq(mEntry));
+        assertEquals(1, mEntry.smartActions.size());
+        assertEquals("action", mEntry.smartActions.get(0).title);
+    }
+
+    @Test
+    public void testUpdateNotificationRanking_noChange() {
+        when(mPresenter.isDeviceProvisioned()).thenReturn(true);
+        when(mPresenter.isNotificationForCurrentProfiles(any())).thenReturn(true);
+
+        mEntry.row = mRow;
+        mEntryManager.getNotificationData().add(mEntry);
+        setSmartActions(mEntry.key, null);
+
+        mEntryManager.updateNotificationRanking(mRankingMap);
+        verify(mRow, never()).updateNotification(eq(mEntry));
+        assertEquals(0, mEntry.smartActions.size());
+    }
+
+    @Test
+    public void testUpdateNotificationRanking_rowNotInflatedYet() {
+        when(mPresenter.isDeviceProvisioned()).thenReturn(true);
+        when(mPresenter.isNotificationForCurrentProfiles(any())).thenReturn(true);
+
+        mEntry.row = null;
+        mEntryManager.getNotificationData().add(mEntry);
+        setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction())));
+
+        mEntryManager.updateNotificationRanking(mRankingMap);
+        verify(mRow, never()).updateNotification(eq(mEntry));
+        assertEquals(1, mEntry.smartActions.size());
+        assertEquals("action", mEntry.smartActions.get(0).title);
+    }
+
+    @Test
+    public void testUpdateNotificationRanking_pendingNotification() {
+        when(mPresenter.isDeviceProvisioned()).thenReturn(true);
+        when(mPresenter.isNotificationForCurrentProfiles(any())).thenReturn(true);
+
+        mEntry.row = null;
+        mEntryManager.mPendingNotifications.put(mEntry.key, mEntry);
+        setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction())));
+
+        mEntryManager.updateNotificationRanking(mRankingMap);
+        verify(mRow, never()).updateNotification(eq(mEntry));
+        assertEquals(1, mEntry.smartActions.size());
+        assertEquals("action", mEntry.smartActions.get(0).title);
+    }
+
+    private Notification.Action createAction() {
+        return new Notification.Action.Builder(
+                Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
+                "action",
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
deleted file mode 100644
index aa8a08c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import static com.android.systemui.statusbar.notification.NotificationInflater.FLAG_REINFLATE_ALL;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.app.Notification;
-import android.content.Context;
-import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.Looper;
-import android.service.notification.StatusBarNotification;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RemoteViews;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.InflationTask;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationTestHelper;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-public class NotificationInflaterTest extends SysuiTestCase {
-
-    private NotificationInflater mNotificationInflater;
-    private Notification.Builder mBuilder;
-    private ExpandableNotificationRow mRow;
-
-    @Before
-    public void setUp() throws Exception {
-        mBuilder = new Notification.Builder(mContext).setSmallIcon(
-                R.drawable.ic_person)
-                .setContentTitle("Title")
-                .setContentText("Text")
-                .setStyle(new Notification.BigTextStyle().bigText("big text"));
-        ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow(
-                mBuilder.build());
-        mRow = spy(row);
-        mNotificationInflater = new NotificationInflater(mRow);
-        mNotificationInflater.setInflationCallback(new NotificationInflater.InflationCallback() {
-            @Override
-            public void handleInflationException(StatusBarNotification notification,
-                    Exception e) {
-            }
-
-            @Override
-            public void onAsyncInflationFinished(NotificationData.Entry entry) {
-            }
-        });
-    }
-
-    @Test
-    public void testIncreasedHeadsUpBeingUsed() {
-        mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
-        Notification.Builder builder = spy(mBuilder);
-        mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
-        verify(builder).createHeadsUpContentView(true);
-    }
-
-    @Test
-    public void testIncreasedHeightBeingUsed() {
-        mNotificationInflater.setUsesIncreasedHeight(true);
-        Notification.Builder builder = spy(mBuilder);
-        mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
-        verify(builder).createContentView(true);
-    }
-
-    @Test
-    public void testInflationCallsUpdated() throws Exception {
-        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
-                mNotificationInflater);
-        verify(mRow).onNotificationUpdated();
-    }
-
-    @Test
-    public void testInflationCallsOnlyRightMethod() throws Exception {
-        mRow.getPrivateLayout().removeAllViews();
-        mRow.getEntry().cachedBigContentView = null;
-        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(
-                NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW), mNotificationInflater);
-        assertTrue(mRow.getPrivateLayout().getChildCount() == 1);
-        assertTrue(mRow.getPrivateLayout().getChildAt(0)
-                == mRow.getPrivateLayout().getExpandedChild());
-        verify(mRow).onNotificationUpdated();
-    }
-
-    @Test
-    public void testInflationThrowsErrorDoesntCallUpdated() throws Exception {
-        mRow.getPrivateLayout().removeAllViews();
-        mRow.getStatusBarNotification().getNotification().contentView
-                = new RemoteViews(mContext.getPackageName(), R.layout.status_bar);
-        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
-                true /* expectingException */, mNotificationInflater);
-        assertTrue(mRow.getPrivateLayout().getChildCount() == 0);
-        verify(mRow, times(0)).onNotificationUpdated();
-    }
-
-    @Test
-    public void testAsyncTaskRemoved() throws Exception {
-        mRow.getEntry().abortTask();
-        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
-                mNotificationInflater);
-        verify(mRow).onNotificationUpdated();
-    }
-
-    @Test
-    public void testRemovedNotInflated() throws Exception {
-        mRow.setRemoved();
-        mNotificationInflater.inflateNotificationViews();
-        Assert.assertNull(mRow.getEntry().getRunningTask());
-    }
-
-    @Test
-    @Ignore
-    public void testInflationIsRetriedIfAsyncFails() throws Exception {
-        NotificationInflater.InflationProgress result =
-                new NotificationInflater.InflationProgress();
-        result.packageContext = mContext;
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        NotificationInflater.applyRemoteView(result,
-                NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW, 0, mRow,
-                false /* redactAmbient */, true /* isNewView */, new RemoteViews.OnClickHandler(),
-                new NotificationInflater.InflationCallback() {
-                    @Override
-                    public void handleInflationException(StatusBarNotification notification,
-                            Exception e) {
-                        countDownLatch.countDown();
-                        throw new RuntimeException("No Exception expected");
-                    }
-
-                    @Override
-                    public void onAsyncInflationFinished(NotificationData.Entry entry) {
-                        countDownLatch.countDown();
-                    }
-                }, mRow.getEntry(), mRow.getPrivateLayout(), null, null, new HashMap<>(),
-                new NotificationInflater.ApplyCallback() {
-                    @Override
-                    public void setResultView(View v) {
-                    }
-
-                    @Override
-                    public RemoteViews getRemoteView() {
-                        return new AsyncFailRemoteView(mContext.getPackageName(),
-                                R.layout.custom_view_dark);
-                    }
-                });
-        assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
-    }
-
-    /* Cancelling requires us to be on the UI thread otherwise we might have a race */
-    @Test
-    public void testSupersedesExistingTask() throws Exception {
-        mNotificationInflater.inflateNotificationViews();
-        mNotificationInflater.setIsLowPriority(true);
-        mNotificationInflater.setIsChildInGroup(true);
-        InflationTask runningTask = mRow.getEntry().getRunningTask();
-        NotificationInflater.AsyncInflationTask asyncInflationTask =
-                (NotificationInflater.AsyncInflationTask) runningTask;
-        Assert.assertSame("Successive inflations don't inherit the previous flags!",
-                asyncInflationTask.getReInflateFlags(),
-                NotificationInflater.FLAG_REINFLATE_ALL);
-        runningTask.abort();
-    }
-
-    @Test
-    public void doesntReapplyDisallowedRemoteView() throws Exception {
-        mBuilder.setStyle(new Notification.MediaStyle());
-        RemoteViews mediaView = mBuilder.createContentView();
-        mBuilder.setStyle(new Notification.DecoratedCustomViewStyle());
-        mBuilder.setCustomContentView(new RemoteViews(getContext().getPackageName(),
-                R.layout.custom_view_dark));
-        RemoteViews decoratedMediaView = mBuilder.createContentView();
-        Assert.assertFalse("The decorated media style doesn't allow a view to be reapplied!",
-                NotificationInflater.canReapplyRemoteView(mediaView, decoratedMediaView));
-    }
-
-    public static void runThenWaitForInflation(Runnable block,
-            NotificationInflater inflater) throws Exception {
-        runThenWaitForInflation(block, false /* expectingException */, inflater);
-    }
-
-    private static void runThenWaitForInflation(Runnable block, boolean expectingException,
-            NotificationInflater inflater) throws Exception {
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        final ExceptionHolder exceptionHolder = new ExceptionHolder();
-        inflater.setInflationCallback(new NotificationInflater.InflationCallback() {
-            @Override
-            public void handleInflationException(StatusBarNotification notification,
-                    Exception e) {
-                if (!expectingException) {
-                    exceptionHolder.setException(e);
-                }
-                countDownLatch.countDown();
-            }
-
-            @Override
-            public void onAsyncInflationFinished(NotificationData.Entry entry) {
-                if (expectingException) {
-                    exceptionHolder.setException(new RuntimeException(
-                            "Inflation finished even though there should be an error"));
-                }
-                countDownLatch.countDown();
-            }
-
-            @Override
-            public boolean doInflateSynchronous() {
-                return true;
-            }
-        });
-        block.run();
-        assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
-        if (exceptionHolder.mException != null) {
-            throw exceptionHolder.mException;
-        }
-    }
-
-    private static class ExceptionHolder {
-        private Exception mException;
-
-        public void setException(Exception exception) {
-            mException = exception;
-        }
-    }
-
-    private class AsyncFailRemoteView extends RemoteViews {
-        Handler mHandler = Handler.createAsync(Looper.getMainLooper());
-
-        public AsyncFailRemoteView(String packageName, int layoutId) {
-            super(packageName, layoutId);
-        }
-
-        @Override
-        public View apply(Context context, ViewGroup parent) {
-            return super.apply(context, parent);
-        }
-
-        @Override
-        public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
-                OnViewAppliedListener listener, OnClickHandler handler) {
-            mHandler.post(() -> listener.onError(new RuntimeException("Failed to inflate async")));
-            return new CancellationSignal();
-        }
-
-        @Override
-        public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
-                OnViewAppliedListener listener) {
-            return applyAsync(context, parent, executor, listener, null);
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
index 7e2e505..63d1e8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
@@ -25,10 +25,10 @@
 import android.view.View;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
index f0ca3ef..6359234 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
@@ -35,11 +35,10 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.stack.AnimationFilter;
-import com.android.systemui.statusbar.stack.AnimationProperties;
-import com.android.systemui.statusbar.stack.ViewState;
+import com.android.systemui.statusbar.notification.stack.AnimationFilter;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.ViewState;
 
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
index 95ce0d8..ffb1c2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
@@ -21,10 +21,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
new file mode 100644
index 0000000..ca62c3b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.logging;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.SysuiTestCase;
+
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.google.android.collect.Lists;
+
+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 org.mockito.stubbing.Answer;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class NotificationLoggerTest extends SysuiTestCase {
+    private static final String TEST_PACKAGE_NAME = "test";
+    private static final int TEST_UID = 0;
+
+    @Mock private NotificationPresenter mPresenter;
+    @Mock private NotificationListContainer mListContainer;
+    @Mock private IStatusBarService mBarService;
+    @Mock private NotificationData mNotificationData;
+    @Mock private ExpandableNotificationRow mRow;
+
+    // Dependency mocks:
+    @Mock private NotificationEntryManager mEntryManager;
+    @Mock private NotificationListener mListener;
+
+    private NotificationData.Entry mEntry;
+    private StatusBarNotification mSbn;
+    private TestableNotificationLogger mLogger;
+    private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>();
+
+    @Before
+    public void setUp() throws RemoteException {
+        MockitoAnnotations.initMocks(this);
+        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
+        mDependency.injectTestDependency(NotificationListener.class, mListener);
+
+        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
+
+        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
+                0, new Notification(), UserHandle.CURRENT, null, 0);
+        mEntry = new NotificationData.Entry(mSbn);
+        mEntry.row = mRow;
+
+        mLogger = new TestableNotificationLogger(mBarService);
+        mLogger.setUpWithEntryManager(mEntryManager, mListContainer);
+    }
+
+    @Test
+    public void testOnChildLocationsChangedReportsVisibilityChanged() throws Exception {
+        NotificationVisibility[] newlyVisibleKeys = {
+                NotificationVisibility.obtain(mEntry.key, 0, 1, true)
+        };
+        NotificationVisibility[] noLongerVisibleKeys = {};
+        doAnswer((Answer) invocation -> {
+                    try {
+                        assertArrayEquals(newlyVisibleKeys,
+                                (NotificationVisibility[]) invocation.getArguments()[0]);
+                        assertArrayEquals(noLongerVisibleKeys,
+                                (NotificationVisibility[]) invocation.getArguments()[1]);
+                    } catch (AssertionError error) {
+                        mErrorQueue.offer(error);
+                    }
+                    return null;
+                }
+        ).when(mBarService).onNotificationVisibilityChanged(any(NotificationVisibility[].class),
+                any(NotificationVisibility[].class));
+
+        when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
+        when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
+        mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
+        TestableLooper.get(this).processAllMessages();
+        waitForUiOffloadThread();
+
+        if(!mErrorQueue.isEmpty()) {
+            throw mErrorQueue.poll();
+        }
+
+        // |mEntry| won't change visibility, so it shouldn't be reported again:
+        Mockito.reset(mBarService);
+        mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
+        TestableLooper.get(this).processAllMessages();
+        waitForUiOffloadThread();
+
+        verify(mBarService, never()).onNotificationVisibilityChanged(any(), any());
+    }
+
+    @Test
+    public void testStoppingNotificationLoggingReportsCurrentNotifications()
+            throws Exception {
+        when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
+        when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
+        mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
+        TestableLooper.get(this).processAllMessages();
+        waitForUiOffloadThread();
+        Mockito.reset(mBarService);
+
+        mLogger.stopNotificationLogging();
+        waitForUiOffloadThread();
+        // The visibility objects are recycled by NotificationLogger, so we can't use specific
+        // matchers here.
+        verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any());
+    }
+
+    private class TestableNotificationLogger extends NotificationLogger {
+
+        public TestableNotificationLogger(IStatusBarService barService) {
+            mBarService = barService;
+            // Make this on the current thread so we can wait for it during tests.
+            mHandler = Handler.createAsync(Looper.myLooper());
+        }
+
+        public OnChildLocationsChangedListener
+                getChildLocationsChangedListenerForTest() {
+            return mNotificationLocationsChangedListener;
+        }
+
+        public Handler getHandlerForTest() {
+            return mHandler;
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
new file mode 100644
index 0000000..dd5cb58
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.UiThreadTest;
+import android.util.ArraySet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@UiThreadTest
+public class AppOpsInfoTest extends SysuiTestCase {
+    private static final String TEST_PACKAGE_NAME = "test_package";
+    private static final int TEST_UID = 1;
+
+    private AppOpsInfo mAppOpsInfo;
+    private final PackageManager mMockPackageManager = mock(PackageManager.class);
+    private final NotificationGuts mGutsParent = mock(NotificationGuts.class);
+    private StatusBarNotification mSbn;
+
+    @Before
+    public void setUp() throws Exception {
+        // Inflate the layout
+        final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+        mAppOpsInfo = (AppOpsInfo) layoutInflater.inflate(R.layout.app_ops_info, null);
+        mAppOpsInfo.setGutsParent(mGutsParent);
+
+        // PackageManager must return a packageInfo and applicationInfo.
+        final PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = TEST_PACKAGE_NAME;
+        when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt()))
+                .thenReturn(packageInfo);
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.uid = TEST_UID;  // non-zero
+        when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
+                applicationInfo);
+
+        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
+                new Notification(), UserHandle.CURRENT, null, 0);
+    }
+
+    @Test
+    public void testBindNotification_SetsTextApplicationName() {
+        when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
+        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>());
+        final TextView textView = mAppOpsInfo.findViewById(R.id.pkgname);
+        assertTrue(textView.getText().toString().contains("App Name"));
+    }
+
+    @Test
+    public void testBindNotification_SetsPackageIcon() {
+        final Drawable iconDrawable = mock(Drawable.class);
+        when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
+                .thenReturn(iconDrawable);
+        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>());
+        final ImageView iconView = mAppOpsInfo.findViewById(R.id.pkgicon);
+        assertEquals(iconDrawable, iconView.getDrawable());
+    }
+
+    @Test
+    public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_CAMERA);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid,
+                ArraySet<Integer> ops) -> {
+            assertEquals(TEST_PACKAGE_NAME, pkg);
+            assertEquals(expectedOps, ops);
+            assertEquals(TEST_UID, uid);
+            latch.countDown();
+        }, mSbn, expectedOps);
+
+        final View settingsButton = mAppOpsInfo.findViewById(R.id.settings);
+        settingsButton.performClick();
+        // Verify that listener was triggered.
+        assertEquals(0, latch.getCount());
+    }
+
+    @Test
+    public void testOk() {
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_CAMERA);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid,
+                ArraySet<Integer> ops) -> {
+            assertEquals(TEST_PACKAGE_NAME, pkg);
+            assertEquals(expectedOps, ops);
+            assertEquals(TEST_UID, uid);
+            latch.countDown();
+        }, mSbn, expectedOps);
+
+        final View okButton = mAppOpsInfo.findViewById(R.id.ok);
+        okButton.performClick();
+        assertEquals(1, latch.getCount());
+        verify(mGutsParent, times(1)).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
+    }
+
+    @Test
+    public void testPrompt_camera() {
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_CAMERA);
+        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+        assertEquals("This app is using the camera.", prompt.getText());
+    }
+
+    @Test
+    public void testPrompt_mic() {
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_RECORD_AUDIO);
+        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+        assertEquals("This app is using the microphone.", prompt.getText());
+    }
+
+    @Test
+    public void testPrompt_overlay() {
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+        assertEquals("This app is displaying over other apps on your screen.", prompt.getText());
+    }
+
+    @Test
+    public void testPrompt_camera_mic() {
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_CAMERA);
+        expectedOps.add(OP_RECORD_AUDIO);
+        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+        assertEquals("This app is using the microphone and camera.", prompt.getText());
+    }
+
+    @Test
+    public void testPrompt_camera_mic_overlay() {
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_CAMERA);
+        expectedOps.add(OP_RECORD_AUDIO);
+        expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+        assertEquals("This app is displaying over other apps on your screen and using"
+                + " the microphone and camera.", prompt.getText());
+    }
+
+    @Test
+    public void testPrompt_camera_overlay() {
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_CAMERA);
+        expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+        assertEquals("This app is displaying over other apps on your screen and using"
+                + " the camera.", prompt.getText());
+    }
+
+    @Test
+    public void testPrompt_mic_overlay() {
+        ArraySet<Integer> expectedOps = new ArraySet<>();
+        expectedOps.add(OP_RECORD_AUDIO);
+        expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+        mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps);
+        TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+        assertEquals("This app is displaying over other apps on your screen and using"
+                + " the microphone.", prompt.getText());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
new file mode 100644
index 0000000..743b307
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.AppOpsManager;
+import android.app.NotificationChannel;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.util.ArraySet;
+import android.view.NotificationHeaderView;
+import android.view.View;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
+import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+public class ExpandableNotificationRowTest extends SysuiTestCase {
+
+    private ExpandableNotificationRow mGroupRow;
+
+    private NotificationTestHelper mNotificationTestHelper;
+    boolean mHeadsUpAnimatingAway = false;
+
+    @Rule public MockitoRule mockito = MockitoJUnit.rule();
+    @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
+
+    @Before
+    public void setUp() throws Exception {
+        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mGroupRow = mNotificationTestHelper.createGroup();
+        mGroupRow.setHeadsUpAnimatingAwayListener(
+                animatingAway -> mHeadsUpAnimatingAway = animatingAway);
+        mDependency.injectTestDependency(
+                NotificationBlockingHelperManager.class,
+                mBlockingHelperManager);
+    }
+
+    @Test
+    public void testGroupSummaryNotShowingIconWhenPublic() {
+        mGroupRow.setSensitive(true, true);
+        mGroupRow.setHideSensitiveForIntrinsicHeight(true);
+        assertTrue(mGroupRow.isSummaryWithChildren());
+        assertFalse(mGroupRow.isShowingIcon());
+    }
+
+    @Test
+    public void testNotificationHeaderVisibleWhenAnimating() {
+        mGroupRow.setSensitive(true, true);
+        mGroupRow.setHideSensitive(true, false, 0, 0);
+        mGroupRow.setHideSensitive(false, true, 0, 0);
+        assertTrue(mGroupRow.getChildrenContainer().getVisibleHeader().getVisibility()
+                == View.VISIBLE);
+    }
+
+    @Test
+    public void testUserLockedResetEvenWhenNoChildren() {
+        mGroupRow.setUserLocked(true);
+        mGroupRow.removeAllChildren();
+        mGroupRow.setUserLocked(false);
+        assertFalse("The childrencontainer should not be userlocked but is, the state "
+                + "seems out of sync.", mGroupRow.getChildrenContainer().isUserLocked());
+    }
+
+    @Test
+    public void testReinflatedOnDensityChange() {
+        mGroupRow.setUserLocked(true);
+        mGroupRow.removeAllChildren();
+        mGroupRow.setUserLocked(false);
+        NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class);
+        mGroupRow.setChildrenContainer(mockContainer);
+        mGroupRow.onDensityOrFontScaleChanged();
+        verify(mockContainer).reInflateViews(any(), any());
+    }
+
+    @Test
+    public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception {
+        ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
+        row.setSensitive(true, true);
+        row.setHideSensitive(true, false, 0, 0);
+        verify(row).updateShelfIconColor();
+    }
+
+    @Test
+    public void testIconColorShouldBeUpdatedWhenSettingDark() throws Exception {
+        ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
+        row.setDark(true, false, 0);
+        verify(row).updateShelfIconColor();
+    }
+
+    @Test
+    public void testAboveShelfChangedListenerCalled() throws Exception {
+        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
+        AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
+        row.setAboveShelfChangedListener(listener);
+        row.setHeadsUp(true);
+        verify(listener).onAboveShelfStateChanged(true);
+    }
+
+    @Test
+    public void testAboveShelfChangedListenerCalledPinned() throws Exception {
+        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
+        AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
+        row.setAboveShelfChangedListener(listener);
+        row.setPinned(true);
+        verify(listener).onAboveShelfStateChanged(true);
+    }
+
+    @Test
+    public void testAboveShelfChangedListenerCalledHeadsUpGoingAway() throws Exception {
+        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
+        AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
+        row.setAboveShelfChangedListener(listener);
+        row.setHeadsUpAnimatingAway(true);
+        verify(listener).onAboveShelfStateChanged(true);
+    }
+    @Test
+    public void testAboveShelfChangedListenerCalledWhenGoingBelow() throws Exception {
+        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
+        row.setHeadsUp(true);
+        AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class);
+        row.setAboveShelfChangedListener(listener);
+        row.setAboveShelf(false);
+        verify(listener).onAboveShelfStateChanged(false);
+    }
+
+    @Test
+    public void testClickSound() throws Exception {
+        assertTrue("Should play sounds by default.", mGroupRow.isSoundEffectsEnabled());
+        mGroupRow.setDark(true /* dark */, false /* fade */, 0 /* delay */);
+        mGroupRow.setSecureStateProvider(()-> false);
+        assertFalse("Shouldn't play sounds when dark and trusted.",
+                mGroupRow.isSoundEffectsEnabled());
+        mGroupRow.setSecureStateProvider(()-> true);
+        assertTrue("Should always play sounds when not trusted.",
+                mGroupRow.isSoundEffectsEnabled());
+    }
+
+    @Test
+    public void testSetDismissed_longPressListenerRemoved() {
+        ExpandableNotificationRow.LongPressListener listener =
+                mock(ExpandableNotificationRow.LongPressListener.class);
+        mGroupRow.setLongPressListener(listener);
+        mGroupRow.doLongClickCallback(0,0);
+        verify(listener, times(1)).onLongPress(eq(mGroupRow), eq(0), eq(0),
+                any(NotificationMenuRowPlugin.MenuItem.class));
+        reset(listener);
+
+        mGroupRow.setDismissed(true);
+        mGroupRow.doLongClickCallback(0,0);
+        verify(listener, times(0)).onLongPress(eq(mGroupRow), eq(0), eq(0),
+                any(NotificationMenuRowPlugin.MenuItem.class));
+    }
+
+    @Test
+    public void testShowAppOps_noHeader() {
+        // public notification is custom layout - no header
+        mGroupRow.setSensitive(true, true);
+        mGroupRow.setAppOpsOnClickListener(null);
+        mGroupRow.showAppOpsIcons(null);
+    }
+
+    @Test
+    public void testShowAppOpsIcons_header() {
+        NotificationHeaderView mockHeader = mock(NotificationHeaderView.class);
+
+        NotificationContentView publicLayout = mock(NotificationContentView.class);
+        mGroupRow.setPublicLayout(publicLayout);
+        NotificationContentView privateLayout = mock(NotificationContentView.class);
+        mGroupRow.setPrivateLayout(privateLayout);
+        NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class);
+        when(mockContainer.getNotificationChildCount()).thenReturn(1);
+        when(mockContainer.getHeaderView()).thenReturn(mockHeader);
+        mGroupRow.setChildrenContainer(mockContainer);
+
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS);
+        mGroupRow.showAppOpsIcons(ops);
+
+        verify(mockHeader, times(1)).showAppOpsIcons(ops);
+        verify(privateLayout, times(1)).showAppOpsIcons(ops);
+        verify(publicLayout, times(1)).showAppOpsIcons(ops);
+
+    }
+
+    @Test
+    public void testAppOpsOnClick() {
+        ExpandableNotificationRow.OnAppOpsClickListener l = mock(
+                ExpandableNotificationRow.OnAppOpsClickListener.class);
+        View view = mock(View.class);
+
+        mGroupRow.setAppOpsOnClickListener(l);
+
+        mGroupRow.getAppOpsOnClickListener().onClick(view);
+        verify(l, times(1)).onClick(any(), anyInt(), anyInt(), any());
+    }
+
+    @Test
+    public void testHeadsUpAnimatingAwayListener() {
+        mGroupRow.setHeadsUpAnimatingAway(true);
+        Assert.assertEquals(true, mHeadsUpAnimatingAway);
+        mGroupRow.setHeadsUpAnimatingAway(false);
+        Assert.assertEquals(false, mHeadsUpAnimatingAway);
+    }
+
+    @Test
+    public void testPerformDismissWithBlockingHelper_falseWhenBlockingHelperIsntShown() {
+        when(mBlockingHelperManager.perhapsShowBlockingHelper(
+                eq(mGroupRow), any(NotificationMenuRowPlugin.class))).thenReturn(false);
+
+        assertFalse(
+                mGroupRow.performDismissWithBlockingHelper(false /* fromAccessibility */));
+    }
+
+    @Test
+    public void testPerformDismissWithBlockingHelper_doesntPerformOnGroupSummary() {
+        ExpandableNotificationRow childRow = mGroupRow.getChildrenContainer().getViewAtPosition(0);
+        when(mBlockingHelperManager.perhapsShowBlockingHelper(eq(childRow), any(NotificationMenuRowPlugin.class)))
+                .thenReturn(true);
+
+        assertTrue(
+                childRow.performDismissWithBlockingHelper(false /* fromAccessibility */));
+
+        verify(mBlockingHelperManager, times(1))
+                .perhapsShowBlockingHelper(eq(childRow), any(NotificationMenuRowPlugin.class));
+        verify(mBlockingHelperManager, times(0))
+                .perhapsShowBlockingHelper(eq(mGroupRow), any(NotificationMenuRowPlugin.class));
+    }
+
+    @Test
+    public void testIsBlockingHelperShowing_isCorrectlyUpdated() {
+        mGroupRow.setBlockingHelperShowing(true);
+        assertTrue(mGroupRow.isBlockingHelperShowing());
+
+        mGroupRow.setBlockingHelperShowing(false);
+        assertFalse(mGroupRow.isBlockingHelperShowing());
+    }
+
+    @Test
+    public void testGetNumUniqueChildren_defaultChannel() {
+        assertEquals(1, mGroupRow.getNumUniqueChannels());
+    }
+
+    @Test
+    public void testGetNumUniqueChildren_multiChannel() {
+        List<ExpandableNotificationRow> childRows =
+                mGroupRow.getChildrenContainer().getNotificationChildren();
+        // Give each child a unique channel id/name.
+        int i = 0;
+        for (ExpandableNotificationRow childRow : childRows) {
+            childRow.getEntry().channel =
+                    new NotificationChannel("id" + i, "dinnertime" + i, IMPORTANCE_DEFAULT);
+            i++;
+        }
+
+        assertEquals(3, mGroupRow.getNumUniqueChannels());
+    }
+
+    @Test
+    public void testIconScrollXAfterTranslationAndReset() throws Exception {
+        mGroupRow.setTranslation(50);
+        assertEquals(50, -mGroupRow.getEntry().expandedIcon.getScrollX());
+
+        mGroupRow.resetTranslation();
+        assertEquals(0, mGroupRow.getEntry().expandedIcon.getScrollX());
+    }
+
+    @Test
+    public void testIsExpanded_userExpanded() {
+        mGroupRow.setExpandable(true);
+        Assert.assertFalse(mGroupRow.isExpanded());
+        mGroupRow.setUserExpanded(true);
+        Assert.assertTrue(mGroupRow.isExpanded());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FooterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FooterViewTest.java
new file mode 100644
index 0000000..aa7889a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FooterViewTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class FooterViewTest extends SysuiTestCase {
+
+    FooterView mView;
+
+    @Before
+    public void setUp() {
+        mView = (FooterView) LayoutInflater.from(mContext).inflate(
+                R.layout.status_bar_notification_footer, null, false);
+        mView.setDuration(0);
+    }
+
+    @Test
+    public void testViewsNotNull() {
+        assertNotNull(mView.findContentView());
+        assertNotNull(mView.findSecondaryView());
+    }
+
+    @Test
+    public void setDismissOnClick() {
+        mView.setDismissButtonClickListener(mock(View.OnClickListener.class));
+        assertTrue(mView.findSecondaryView().hasOnClickListeners());
+    }
+
+    @Test
+    public void setManageOnClick() {
+        mView.setManageButtonClickListener(mock(View.OnClickListener.class));
+        assertTrue(mView.findViewById(R.id.manage_text).hasOnClickListeners());
+    }
+
+    @Test
+    public void testPerformVisibilityAnimation() {
+        mView.setVisible(false /* visible */, false /* animate */);
+        assertFalse(mView.isVisible());
+
+        mView.setVisible(true /* visible */, true /* animate */);
+    }
+
+    @Test
+    public void testPerformSecondaryVisibilityAnimation() {
+        mView.setSecondaryVisible(false /* visible */, false /* animate */);
+        assertFalse(mView.isSecondaryVisible());
+
+        mView.setSecondaryVisible(true /* visible */, true /* animate */);
+    }
+}
+
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
new file mode 100644
index 0000000..4efab53
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import android.content.Context;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.View;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link NotificationBlockingHelperManager}.
+ */
+@SmallTest
+@FlakyTest
+@org.junit.runner.RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
+
+    private NotificationBlockingHelperManager mBlockingHelperManager;
+
+    private NotificationTestHelper mHelper;
+
+    @Mock private NotificationGutsManager mGutsManager;
+    @Mock private NotificationEntryManager mEntryManager;
+    @Mock private NotificationMenuRow mMenuRow;
+    @Mock private NotificationMenuRowPlugin.MenuItem mMenuItem;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mGutsManager.openGuts(
+                any(View.class),
+                anyInt(),
+                anyInt(),
+                any(NotificationMenuRowPlugin.MenuItem.class)))
+                .thenReturn(true);
+        when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem);
+        mDependency.injectTestDependency(NotificationGutsManager.class, mGutsManager);
+        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
+
+        mHelper = new NotificationTestHelper(mContext);
+
+        mBlockingHelperManager = new NotificationBlockingHelperManager(mContext);
+        // By default, have the shade visible/expanded.
+        mBlockingHelperManager.setNotificationShadeExpanded(1f);
+    }
+
+    @Test
+    public void testDismissCurrentBlockingHelper_nullBlockingHelperRow() {
+        // By default, this shouldn't dismiss (no pointers/vars set up!)
+        assertFalse(mBlockingHelperManager.dismissCurrentBlockingHelper());
+        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
+    }
+
+    @Test
+    public void testDismissCurrentBlockingHelper_withDetachedBlockingHelperRow() throws Exception {
+        ExpandableNotificationRow row = createBlockableRowSpy();
+        row.setBlockingHelperShowing(true);
+        when(row.isAttachedToWindow()).thenReturn(false);
+        mBlockingHelperManager.setBlockingHelperRowForTest(row);
+
+        assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
+        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
+
+        verify(mEntryManager, times(0)).updateNotifications();
+    }
+
+    @Test
+    public void testDismissCurrentBlockingHelper_withAttachedBlockingHelperRow() throws Exception {
+        ExpandableNotificationRow row = createBlockableRowSpy();
+        row.setBlockingHelperShowing(true);
+        when(row.isAttachedToWindow()).thenReturn(true);
+        mBlockingHelperManager.setBlockingHelperRowForTest(row);
+
+        assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
+        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
+
+        verify(mEntryManager).updateNotifications();
+    }
+
+    @Test
+    public void testPerhapsShowBlockingHelper_shown() throws Exception {
+        ExpandableNotificationRow row = createBlockableRowSpy();
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+
+        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+
+        verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
+    }
+
+
+    @Test
+    public void testPerhapsShowBlockingHelper_shownForLargeGroup() throws Exception {
+        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
+        groupRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+
+        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
+
+        verify(mGutsManager).openGuts(groupRow, 0, 0, mMenuItem);
+    }
+
+    @Test
+    public void testPerhapsShowBlockingHelper_shownForOnlyChildNotification()
+            throws Exception {
+        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(1);
+        // Explicitly get the children container & call getViewAtPosition on it instead of the row
+        // as other factors such as view expansion may cause us to get the parent row back instead
+        // of the child row.
+        ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
+        childRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        assertFalse(childRow.getIsNonblockable());
+
+        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
+
+        verify(mGutsManager).openGuts(childRow, 0, 0, mMenuItem);
+    }
+
+    @Test
+    public void testPerhapsShowBlockingHelper_notShownDueToNeutralUserSentiment() throws Exception {
+        ExpandableNotificationRow row = createBlockableRowSpy();
+        row.getEntry().userSentiment = USER_SENTIMENT_NEUTRAL;
+
+        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+    }
+
+    @Test
+    public void testPerhapsShowBlockingHelper_notShownDueToPositiveUserSentiment()
+            throws Exception {
+        ExpandableNotificationRow row = createBlockableRowSpy();
+        row.getEntry().userSentiment = USER_SENTIMENT_POSITIVE;
+
+        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+    }
+
+    @Test
+    public void testPerhapsShowBlockingHelper_notShownDueToShadeVisibility() throws Exception {
+        ExpandableNotificationRow row = createBlockableRowSpy();
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        // Hide the shade
+        mBlockingHelperManager.setNotificationShadeExpanded(0f);
+
+        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+    }
+
+    @Test
+    public void testPerhapsShowBlockingHelper_notShownDueToNonblockability() throws Exception {
+        ExpandableNotificationRow row = createBlockableRowSpy();
+        when(row.getIsNonblockable()).thenReturn(true);
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+
+        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+    }
+
+    @Test
+    public void testPerhapsShowBlockingHelper_notShownAsNotificationIsInMultipleChildGroup()
+            throws Exception {
+        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(2);
+        // Explicitly get the children container & call getViewAtPosition on it instead of the row
+        // as other factors such as view expansion may cause us to get the parent row back instead
+        // of the child row.
+        ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
+        childRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+
+        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
+    }
+
+    @Test
+    public void testBlockingHelperShowAndDismiss() throws Exception{
+        ExpandableNotificationRow row = createBlockableRowSpy();
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        when(row.isAttachedToWindow()).thenReturn(true);
+
+        // Show check
+        assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
+
+        verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
+
+        // Dismiss check
+        assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
+        assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
+
+        verify(mEntryManager).updateNotifications();
+    }
+
+    @Test
+    public void testNonBlockable_package() {
+        mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
+
+        assertFalse(mBlockingHelperManager.isNonblockable("orange", "pie"));
+
+        assertTrue(mBlockingHelperManager.isNonblockable("banana", "pie"));
+    }
+
+    @Test
+    public void testNonBlockable_channel() {
+        mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
+
+        assertFalse(mBlockingHelperManager.isNonblockable("strawberry", "shortcake"));
+
+        assertTrue(mBlockingHelperManager.isNonblockable("strawberry", "pie"));
+    }
+
+    private ExpandableNotificationRow createBlockableRowSpy() throws Exception {
+        ExpandableNotificationRow row = spy(mHelper.createRow());
+        when(row.getIsNonblockable()).thenReturn(false);
+        return row;
+    }
+
+    private ExpandableNotificationRow createBlockableGroupRowSpy(int numChildren) throws Exception {
+        ExpandableNotificationRow row = spy(mHelper.createGroup(numChildren));
+        when(row.getIsNonblockable()).thenReturn(false);
+        return row;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
new file mode 100644
index 0000000..c189c95
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.AppOpsManager;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArraySet;
+import android.view.NotificationHeaderView;
+import android.view.View;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationContentViewTest extends SysuiTestCase {
+
+    NotificationContentView mView;
+
+    @Before
+    @UiThreadTest
+    public void setup() {
+        mView = new NotificationContentView(mContext, null);
+        ExpandableNotificationRow row = new ExpandableNotificationRow(mContext, null);
+        ExpandableNotificationRow mockRow = spy(row);
+        doNothing().when(mockRow).updateBackgroundAlpha(anyFloat());
+        doReturn(10).when(mockRow).getIntrinsicHeight();
+
+        mView.setContainingNotification(mockRow);
+        mView.setHeights(10, 20, 30, 40);
+
+        mView.setContractedChild(createViewWithHeight(10));
+        mView.setExpandedChild(createViewWithHeight(20));
+        mView.setHeadsUpChild(createViewWithHeight(30));
+        mView.setAmbientChild(createViewWithHeight(40));
+
+        mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+        mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+    }
+
+    private View createViewWithHeight(int height) {
+        View view = new View(mContext, null);
+        view.setMinimumHeight(height);
+        return view;
+    }
+
+    @Test
+    @UiThreadTest
+    public void animationStartType_getsClearedAfterUpdatingVisibilitiesWithoutAnimation() {
+        mView.setHeadsUp(true);
+        mView.setDark(true, false, 0);
+        mView.setDark(false, true, 0);
+        mView.setHeadsUpAnimatingAway(true);
+        Assert.assertFalse(mView.isAnimatingVisibleType());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testShowAppOpsIcons() {
+        NotificationHeaderView mockContracted = mock(NotificationHeaderView.class);
+        when(mockContracted.findViewById(com.android.internal.R.id.notification_header))
+                .thenReturn(mockContracted);
+        NotificationHeaderView mockExpanded = mock(NotificationHeaderView.class);
+        when(mockExpanded.findViewById(com.android.internal.R.id.notification_header))
+                .thenReturn(mockExpanded);
+        NotificationHeaderView mockHeadsUp = mock(NotificationHeaderView.class);
+        when(mockHeadsUp.findViewById(com.android.internal.R.id.notification_header))
+                .thenReturn(mockHeadsUp);
+        NotificationHeaderView mockAmbient = mock(NotificationHeaderView.class);
+        when(mockAmbient.findViewById(com.android.internal.R.id.notification_header))
+                .thenReturn(mockAmbient);
+
+        mView.setContractedChild(mockContracted);
+        mView.setExpandedChild(mockExpanded);
+        mView.setHeadsUpChild(mockHeadsUp);
+        mView.setAmbientChild(mockAmbient);
+
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS);
+        mView.showAppOpsIcons(ops);
+
+        verify(mockContracted, times(1)).showAppOpsIcons(ops);
+        verify(mockExpanded, times(1)).showAppOpsIcons(ops);
+        verify(mockAmbient, never()).showAppOpsIcons(ops);
+        verify(mockHeadsUp, times(1)).showAppOpsIcons(any());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
new file mode 100644
index 0000000..676cb61
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
+import static junit.framework.Assert.assertNotNull;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+
+import android.app.INotificationManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.ArraySet;
+import android.view.View;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoRule;
+import org.mockito.junit.MockitoJUnit;
+
+/**
+ * Tests for {@link NotificationGutsManager}.
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class NotificationGutsManagerTest extends SysuiTestCase {
+    private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
+
+    private NotificationChannel mTestNotificationChannel = new NotificationChannel(
+            TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+    private TestableLooper mTestableLooper;
+    private Handler mHandler;
+    private NotificationTestHelper mHelper;
+    private NotificationGutsManager mGutsManager;
+
+    @Rule public MockitoRule mockito = MockitoJUnit.rule();
+    @Mock private NotificationPresenter mPresenter;
+    @Mock private NotificationEntryManager mEntryManager;
+    @Mock private NotificationStackScrollLayout mStackScroller;
+    @Mock private NotificationInfo.CheckSaveListener mCheckSaveListener;
+    @Mock private NotificationGutsManager.OnSettingsClickListener mOnSettingsClickListener;
+
+    @Before
+    public void setUp() {
+        mTestableLooper = TestableLooper.get(this);
+        mHandler = Handler.createAsync(mTestableLooper.getLooper());
+
+        mHelper = new NotificationTestHelper(mContext);
+
+        mGutsManager = new NotificationGutsManager(mContext);
+        mGutsManager.setUpWithPresenter(mPresenter, mEntryManager, mStackScroller,
+                mCheckSaveListener, mOnSettingsClickListener);
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    // Test methods:
+
+    @Test
+    public void testOpenAndCloseGuts() {
+        NotificationGuts guts = spy(new NotificationGuts(mContext));
+        when(guts.post(any())).thenAnswer(invocation -> {
+            mHandler.post(((Runnable) invocation.getArguments()[0]));
+            return null;
+        });
+
+        // Test doesn't support animation since the guts view is not attached.
+        doNothing().when(guts).openControls(
+                eq(true) /* shouldDoCircularReveal */,
+                anyInt(),
+                anyInt(),
+                anyBoolean(),
+                any(Runnable.class));
+
+        ExpandableNotificationRow realRow = createTestNotificationRow();
+        NotificationMenuRowPlugin.MenuItem menuItem = createTestMenuItem(realRow);
+
+        ExpandableNotificationRow row = spy(realRow);
+        when(row.getWindowToken()).thenReturn(new Binder());
+        when(row.getGuts()).thenReturn(guts);
+
+        mGutsManager.openGuts(row, 0, 0, menuItem);
+        assertEquals(View.INVISIBLE, guts.getVisibility());
+        mTestableLooper.processAllMessages();
+        verify(guts).openControls(
+                eq(true),
+                anyInt(),
+                anyInt(),
+                anyBoolean(),
+                any(Runnable.class));
+
+        assertEquals(View.VISIBLE, guts.getVisibility());
+        mGutsManager.closeAndSaveGuts(false, false, false, 0, 0, false);
+
+        verify(guts).closeControls(anyBoolean(), anyBoolean(), anyInt(), anyInt(), anyBoolean());
+        verify(row, times(1)).setGutsView(any());
+    }
+
+    @Test
+    public void testChangeDensityOrFontScale() {
+        NotificationGuts guts = spy(new NotificationGuts(mContext));
+        when(guts.post(any())).thenAnswer(invocation -> {
+            mHandler.post(((Runnable) invocation.getArguments()[0]));
+            return null;
+        });
+
+        // Test doesn't support animation since the guts view is not attached.
+        doNothing().when(guts).openControls(
+                eq(true) /* shouldDoCircularReveal */,
+                anyInt(),
+                anyInt(),
+                anyBoolean(),
+                any(Runnable.class));
+
+        ExpandableNotificationRow realRow = createTestNotificationRow();
+        NotificationMenuRowPlugin.MenuItem menuItem = createTestMenuItem(realRow);
+
+        ExpandableNotificationRow row = spy(realRow);
+        when(row.getWindowToken()).thenReturn(new Binder());
+        when(row.getGuts()).thenReturn(guts);
+        doNothing().when(row).inflateGuts();
+
+        mGutsManager.openGuts(row, 0, 0, menuItem);
+        mTestableLooper.processAllMessages();
+        verify(guts).openControls(
+                eq(true),
+                anyInt(),
+                anyInt(),
+                anyBoolean(),
+                any(Runnable.class));
+
+        row.onDensityOrFontScaleChanged();
+        mGutsManager.onDensityOrFontScaleChanged(row);
+        mTestableLooper.processAllMessages();
+
+        mGutsManager.closeAndSaveGuts(false, false, false, 0, 0, false);
+
+        verify(guts).closeControls(anyBoolean(), anyBoolean(), anyInt(), anyInt(), anyBoolean());
+        verify(row, times(2)).setGutsView(any());
+    }
+
+    @Test
+    public void testAppOpsSettingsIntent_camera() {
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(OP_CAMERA);
+        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+        assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
+    }
+
+    @Test
+    public void testAppOpsSettingsIntent_mic() {
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(OP_RECORD_AUDIO);
+        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+        assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
+    }
+
+    @Test
+    public void testAppOpsSettingsIntent_camera_mic() {
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(OP_CAMERA);
+        ops.add(OP_RECORD_AUDIO);
+        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+        assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
+    }
+
+    @Test
+    public void testAppOpsSettingsIntent_overlay() {
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(OP_SYSTEM_ALERT_WINDOW);
+        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+        assertEquals(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, captor.getValue().getAction());
+    }
+
+    @Test
+    public void testAppOpsSettingsIntent_camera_mic_overlay() {
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(OP_CAMERA);
+        ops.add(OP_RECORD_AUDIO);
+        ops.add(OP_SYSTEM_ALERT_WINDOW);
+        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+        assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
+    }
+
+    @Test
+    public void testAppOpsSettingsIntent_camera_overlay() {
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(OP_CAMERA);
+        ops.add(OP_SYSTEM_ALERT_WINDOW);
+        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+        assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
+    }
+
+    @Test
+    public void testAppOpsSettingsIntent_mic_overlay() {
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(OP_RECORD_AUDIO);
+        ops.add(OP_SYSTEM_ALERT_WINDOW);
+        mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
+        assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
+    }
+
+    @Test
+    public void testInitializeNotificationInfoView_showBlockingHelper() throws Exception {
+        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+        ExpandableNotificationRow row = spy(mHelper.createRow());
+        row.setBlockingHelperShowing(true);
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        when(row.getIsNonblockable()).thenReturn(false);
+        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+        verify(notificationInfoView).bindNotification(
+                any(PackageManager.class),
+                any(INotificationManager.class),
+                eq(statusBarNotification.getPackageName()),
+                any(NotificationChannel.class),
+                anyInt(),
+                eq(statusBarNotification),
+                any(NotificationInfo.CheckSaveListener.class),
+                any(NotificationInfo.OnSettingsClickListener.class),
+                any(NotificationInfo.OnAppSettingsClickListener.class),
+                eq(false),
+                eq(false),
+                eq(true) /* isForBlockingHelper */,
+                eq(true) /* isUserSentimentNegative */);
+    }
+
+    @Test
+    public void testInitializeNotificationInfoView_dontShowBlockingHelper() throws Exception {
+        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+        ExpandableNotificationRow row = spy(mHelper.createRow());
+        row.setBlockingHelperShowing(false);
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        when(row.getIsNonblockable()).thenReturn(false);
+        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+        verify(notificationInfoView).bindNotification(
+                any(PackageManager.class),
+                any(INotificationManager.class),
+                eq(statusBarNotification.getPackageName()),
+                any(NotificationChannel.class),
+                anyInt(),
+                eq(statusBarNotification),
+                any(NotificationInfo.CheckSaveListener.class),
+                any(NotificationInfo.OnSettingsClickListener.class),
+                any(NotificationInfo.OnAppSettingsClickListener.class),
+                eq(false),
+                eq(false),
+                eq(false) /* isForBlockingHelper */,
+                eq(true) /* isUserSentimentNegative */);
+    }
+
+    @Test
+    public void testInitializeNotificationInfoView_PassesAlongProvisionedState() throws Exception {
+        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+        ExpandableNotificationRow row = spy(mHelper.createRow());
+        row.setBlockingHelperShowing(false);
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        when(row.getIsNonblockable()).thenReturn(false);
+        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+        when(mPresenter.isDeviceProvisioned()).thenReturn(true);
+
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+        verify(notificationInfoView).bindNotification(
+                any(PackageManager.class),
+                any(INotificationManager.class),
+                eq(statusBarNotification.getPackageName()),
+                any(NotificationChannel.class),
+                anyInt(),
+                eq(statusBarNotification),
+                any(NotificationInfo.CheckSaveListener.class),
+                any(NotificationInfo.OnSettingsClickListener.class),
+                any(NotificationInfo.OnAppSettingsClickListener.class),
+                eq(true),
+                eq(false),
+                eq(false) /* isForBlockingHelper */,
+                eq(true) /* isUserSentimentNegative */);
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    // Utility methods:
+
+    private ExpandableNotificationRow createTestNotificationRow() {
+        Notification.Builder nb = new Notification.Builder(mContext,
+                mTestNotificationChannel.getId())
+                                        .setContentTitle("foo")
+                                        .setColorized(true)
+                                        .setFlag(Notification.FLAG_CAN_COLORIZE, true)
+                                        .setSmallIcon(android.R.drawable.sym_def_app_icon);
+
+        try {
+            ExpandableNotificationRow row = mHelper.createRow(nb.build());
+            row.getEntry().channel = mTestNotificationChannel;
+            return row;
+        } catch (Exception e) {
+            fail();
+            return null;
+        }
+    }
+
+    private NotificationMenuRowPlugin.MenuItem createTestMenuItem(ExpandableNotificationRow row) {
+        NotificationMenuRowPlugin menuRow = new NotificationMenuRow(mContext);
+        menuRow.createMenu(row, row.getStatusBarNotification());
+
+        NotificationMenuRowPlugin.MenuItem menuItem = menuRow.getLongpressMenuItem(mContext);
+        assertNotNull(menuItem);
+        return menuItem;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java
new file mode 100644
index 0000000..81e79d1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+
+import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_REINFLATE_ALL;
+
+import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.Notification;
+import android.content.Context;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.Looper;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.InflationTask;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+public class NotificationInflaterTest extends SysuiTestCase {
+
+    private NotificationInflater mNotificationInflater;
+    private Notification.Builder mBuilder;
+    private ExpandableNotificationRow mRow;
+
+    @Before
+    public void setUp() throws Exception {
+        mBuilder = new Notification.Builder(mContext).setSmallIcon(
+                R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text")
+                .setStyle(new Notification.BigTextStyle().bigText("big text"));
+        ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow(
+                mBuilder.build());
+        mRow = spy(row);
+        mNotificationInflater = new NotificationInflater(mRow);
+        mNotificationInflater.setInflationCallback(new NotificationInflater.InflationCallback() {
+            @Override
+            public void handleInflationException(StatusBarNotification notification,
+                    Exception e) {
+            }
+
+            @Override
+            public void onAsyncInflationFinished(NotificationData.Entry entry) {
+            }
+        });
+    }
+
+    @Test
+    public void testIncreasedHeadsUpBeingUsed() {
+        mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
+        Notification.Builder builder = spy(mBuilder);
+        mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
+        verify(builder).createHeadsUpContentView(true);
+    }
+
+    @Test
+    public void testIncreasedHeightBeingUsed() {
+        mNotificationInflater.setUsesIncreasedHeight(true);
+        Notification.Builder builder = spy(mBuilder);
+        mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
+        verify(builder).createContentView(true);
+    }
+
+    @Test
+    public void testInflationCallsUpdated() throws Exception {
+        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
+                mNotificationInflater);
+        verify(mRow).onNotificationUpdated();
+    }
+
+    @Test
+    public void testInflationCallsOnlyRightMethod() throws Exception {
+        mRow.getPrivateLayout().removeAllViews();
+        mRow.getEntry().cachedBigContentView = null;
+        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(
+                FLAG_REINFLATE_EXPANDED_VIEW), mNotificationInflater);
+        assertTrue(mRow.getPrivateLayout().getChildCount() == 1);
+        assertTrue(mRow.getPrivateLayout().getChildAt(0)
+                == mRow.getPrivateLayout().getExpandedChild());
+        verify(mRow).onNotificationUpdated();
+    }
+
+    @Test
+    public void testInflationThrowsErrorDoesntCallUpdated() throws Exception {
+        mRow.getPrivateLayout().removeAllViews();
+        mRow.getStatusBarNotification().getNotification().contentView
+                = new RemoteViews(mContext.getPackageName(), R.layout.status_bar);
+        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
+                true /* expectingException */, mNotificationInflater);
+        assertTrue(mRow.getPrivateLayout().getChildCount() == 0);
+        verify(mRow, times(0)).onNotificationUpdated();
+    }
+
+    @Test
+    public void testAsyncTaskRemoved() throws Exception {
+        mRow.getEntry().abortTask();
+        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
+                mNotificationInflater);
+        verify(mRow).onNotificationUpdated();
+    }
+
+    @Test
+    public void testRemovedNotInflated() throws Exception {
+        mRow.setRemoved();
+        mNotificationInflater.inflateNotificationViews();
+        Assert.assertNull(mRow.getEntry().getRunningTask());
+    }
+
+    @Test
+    @Ignore
+    public void testInflationIsRetriedIfAsyncFails() throws Exception {
+        NotificationInflater.InflationProgress result =
+                new NotificationInflater.InflationProgress();
+        result.packageContext = mContext;
+        CountDownLatch countDownLatch = new CountDownLatch(1);
+        NotificationInflater.applyRemoteView(result, FLAG_REINFLATE_EXPANDED_VIEW, 0, mRow,
+                false /* redactAmbient */, true /* isNewView */, new RemoteViews.OnClickHandler(),
+                new NotificationInflater.InflationCallback() {
+                    @Override
+                    public void handleInflationException(StatusBarNotification notification,
+                            Exception e) {
+                        countDownLatch.countDown();
+                        throw new RuntimeException("No Exception expected");
+                    }
+
+                    @Override
+                    public void onAsyncInflationFinished(NotificationData.Entry entry) {
+                        countDownLatch.countDown();
+                    }
+                }, mRow.getEntry(), mRow.getPrivateLayout(), null, null, new HashMap<>(),
+                new NotificationInflater.ApplyCallback() {
+                    @Override
+                    public void setResultView(View v) {
+                    }
+
+                    @Override
+                    public RemoteViews getRemoteView() {
+                        return new AsyncFailRemoteView(mContext.getPackageName(),
+                                R.layout.custom_view_dark);
+                    }
+                });
+        assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
+    }
+
+    /* Cancelling requires us to be on the UI thread otherwise we might have a race */
+    @Test
+    public void testSupersedesExistingTask() throws Exception {
+        mNotificationInflater.inflateNotificationViews();
+        mNotificationInflater.setIsLowPriority(true);
+        mNotificationInflater.setIsChildInGroup(true);
+        InflationTask runningTask = mRow.getEntry().getRunningTask();
+        NotificationInflater.AsyncInflationTask asyncInflationTask =
+                (NotificationInflater.AsyncInflationTask) runningTask;
+        Assert.assertSame("Successive inflations don't inherit the previous flags!",
+                asyncInflationTask.getReInflateFlags(),
+                NotificationInflater.FLAG_REINFLATE_ALL);
+        runningTask.abort();
+    }
+
+    @Test
+    public void doesntReapplyDisallowedRemoteView() throws Exception {
+        mBuilder.setStyle(new Notification.MediaStyle());
+        RemoteViews mediaView = mBuilder.createContentView();
+        mBuilder.setStyle(new Notification.DecoratedCustomViewStyle());
+        mBuilder.setCustomContentView(new RemoteViews(getContext().getPackageName(),
+                R.layout.custom_view_dark));
+        RemoteViews decoratedMediaView = mBuilder.createContentView();
+        Assert.assertFalse("The decorated media style doesn't allow a view to be reapplied!",
+                NotificationInflater.canReapplyRemoteView(mediaView, decoratedMediaView));
+    }
+
+    public static void runThenWaitForInflation(Runnable block,
+            NotificationInflater inflater) throws Exception {
+        runThenWaitForInflation(block, false /* expectingException */, inflater);
+    }
+
+    private static void runThenWaitForInflation(Runnable block, boolean expectingException,
+            NotificationInflater inflater) throws Exception {
+        CountDownLatch countDownLatch = new CountDownLatch(1);
+        final ExceptionHolder exceptionHolder = new ExceptionHolder();
+        inflater.setInflationCallback(new NotificationInflater.InflationCallback() {
+            @Override
+            public void handleInflationException(StatusBarNotification notification,
+                    Exception e) {
+                if (!expectingException) {
+                    exceptionHolder.setException(e);
+                }
+                countDownLatch.countDown();
+            }
+
+            @Override
+            public void onAsyncInflationFinished(NotificationData.Entry entry) {
+                if (expectingException) {
+                    exceptionHolder.setException(new RuntimeException(
+                            "Inflation finished even though there should be an error"));
+                }
+                countDownLatch.countDown();
+            }
+
+            @Override
+            public boolean doInflateSynchronous() {
+                return true;
+            }
+        });
+        block.run();
+        assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
+        if (exceptionHolder.mException != null) {
+            throw exceptionHolder.mException;
+        }
+    }
+
+    private static class ExceptionHolder {
+        private Exception mException;
+
+        public void setException(Exception exception) {
+            mException = exception;
+        }
+    }
+
+    private class AsyncFailRemoteView extends RemoteViews {
+        Handler mHandler = Handler.createAsync(Looper.getMainLooper());
+
+        public AsyncFailRemoteView(String packageName, int layoutId) {
+            super(packageName, layoutId);
+        }
+
+        @Override
+        public View apply(Context context, ViewGroup parent) {
+            return super.apply(context, parent);
+        }
+
+        @Override
+        public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
+                OnViewAppliedListener listener, OnClickHandler handler) {
+            mHandler.post(() -> listener.onError(new RuntimeException("Failed to inflate async")));
+            return new CancellationSignal();
+        }
+
+        @Override
+        public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
+                OnViewAppliedListener listener) {
+            return applyAsync(context, parent, executor, listener, null);
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
new file mode 100644
index 0000000..c236fbe
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -0,0 +1,1012 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.INotificationManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.PollingCheck;
+import android.testing.TestableLooper;
+import android.testing.UiThreadTest;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationInfoTest extends SysuiTestCase {
+    private static final String TEST_PACKAGE_NAME = "test_package";
+    private static final String TEST_SYSTEM_PACKAGE_NAME = PRINT_SPOOLER_PACKAGE_NAME;
+    private static final int TEST_UID = 1;
+    private static final int MULTIPLE_CHANNEL_COUNT = 2;
+    private static final String TEST_CHANNEL = "test_channel";
+    private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME";
+
+    private TestableLooper mTestableLooper;
+    private NotificationInfo mNotificationInfo;
+    private NotificationChannel mNotificationChannel;
+    private NotificationChannel mDefaultNotificationChannel;
+    private StatusBarNotification mSbn;
+
+    @Rule public MockitoRule mockito = MockitoJUnit.rule();
+    @Mock private MetricsLogger mMetricsLogger;
+    @Mock private INotificationManager mMockINotificationManager;
+    @Mock private PackageManager mMockPackageManager;
+    @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
+
+    @Before
+    public void setUp() throws Exception {
+        mDependency.injectTestDependency(
+                NotificationBlockingHelperManager.class,
+                mBlockingHelperManager);
+        mTestableLooper = TestableLooper.get(this);
+        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
+        mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
+        // Inflate the layout
+        final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+        mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
+                null);
+        mNotificationInfo.setGutsParent(mock(NotificationGuts.class));
+
+        // PackageManager must return a packageInfo and applicationInfo.
+        final PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = TEST_PACKAGE_NAME;
+        when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt()))
+                .thenReturn(packageInfo);
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.uid = TEST_UID;  // non-zero
+        when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
+                applicationInfo);
+        final PackageInfo systemPackageInfo = new PackageInfo();
+        systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME;
+        when(mMockPackageManager.getPackageInfo(eq(TEST_SYSTEM_PACKAGE_NAME), anyInt()))
+                .thenReturn(systemPackageInfo);
+        when(mMockPackageManager.getPackageInfo(eq("android"), anyInt()))
+                .thenReturn(packageInfo);
+
+        // Package has one channel by default.
+        when(mMockINotificationManager.getNumNotificationChannelsForPackage(
+                eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(1);
+
+        // Some test channels.
+        mNotificationChannel = new NotificationChannel(
+                TEST_CHANNEL, TEST_CHANNEL_NAME, IMPORTANCE_LOW);
+        mDefaultNotificationChannel = new NotificationChannel(
+                NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
+                IMPORTANCE_LOW);
+        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
+                new Notification(), UserHandle.CURRENT, null, 0);
+    }
+
+    // TODO: if tests are taking too long replace this with something that makes the animation
+    // finish instantly.
+    private void waitForUndoButton() {
+        PollingCheck.waitFor(1000,
+                () -> VISIBLE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility());
+    }
+    private void waitForStopButton() {
+        PollingCheck.waitFor(1000,
+                () -> VISIBLE == mNotificationInfo.findViewById(R.id.prompt).getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_SetsTextApplicationName() throws Exception {
+        when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
+        assertTrue(textView.getText().toString().contains("App Name"));
+        assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_SetsPackageIcon() throws Exception {
+        final Drawable iconDrawable = mock(Drawable.class);
+        when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
+                .thenReturn(iconDrawable);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
+        assertEquals(iconDrawable, iconView.getDrawable());
+    }
+
+    @Test
+    public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
+        assertEquals(GONE, groupNameView.getVisibility());
+        final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
+        assertEquals(GONE, groupDividerView.getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_SetsGroupNameIfNonNull() throws Exception {
+        mNotificationChannel.setGroup("test_group_id");
+        final NotificationChannelGroup notificationChannelGroup =
+                new NotificationChannelGroup("test_group_id", "Test Group Name");
+        when(mMockINotificationManager.getNotificationChannelGroupForPackage(
+                eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
+                .thenReturn(notificationChannelGroup);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
+        assertEquals(View.VISIBLE, groupNameView.getVisibility());
+        assertEquals("Test Group Name", groupNameView.getText());
+        final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
+        assertEquals(View.VISIBLE, groupDividerView.getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_SetsTextChannelName() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
+        assertEquals(TEST_CHANNEL_NAME, textView.getText());
+    }
+
+    @Test
+    public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
+                false);
+        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
+        assertEquals(GONE, textView.getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_DefaultChannelUsesChannelNameIfMoreChannelsExist()
+            throws Exception {
+        // Package has one channel by default.
+        when(mMockINotificationManager.getNumNotificationChannelsForPackage(
+                eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
+                false);
+        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
+        assertEquals(VISIBLE, textView.getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
+        assertEquals(VISIBLE, textView.getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_BlockButton() throws Exception {
+       mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final View block = mNotificationInfo.findViewById(R.id.block);
+        final View minimize = mNotificationInfo.findViewById(R.id.minimize);
+        assertEquals(VISIBLE, block.getVisibility());
+        assertEquals(GONE, minimize.getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_MinButton() throws Exception {
+        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final View block = mNotificationInfo.findViewById(R.id.block);
+        final View minimize = mNotificationInfo.findViewById(R.id.minimize);
+        assertEquals(GONE, block.getVisibility());
+        assertEquals(VISIBLE, minimize.getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
+                (View v, NotificationChannel c, int appUid) -> {
+                    assertEquals(mNotificationChannel, c);
+                    latch.countDown();
+                }, null, true, false);
+
+        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
+        settingsButton.performClick();
+        // Verify that listener was triggered.
+        assertEquals(0, latch.getCount());
+    }
+
+    @Test
+    public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
+        assertTrue(settingsButton.getVisibility() != View.VISIBLE);
+    }
+
+    @Test
+    public void testBindNotification_SettingsButtonInvisibleWhenDeviceUnprovisioned()
+            throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
+                (View v, NotificationChannel c, int appUid) -> {
+                    assertEquals(mNotificationChannel, c);
+                }, null, false, false);
+        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
+        assertTrue(settingsButton.getVisibility() != View.VISIBLE);
+    }
+
+    @Test
+    public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
+                (View v, NotificationChannel c, int appUid) -> {
+                }, null, true, false);
+        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
+        assertEquals(View.VISIBLE, settingsButton.getVisibility());
+    }
+
+    @Test
+    public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
+        verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
+    }
+
+    @Test
+    public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
+                true, true);
+        mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
+        verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
+    }
+
+    @Test
+    public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null,
+                (View v, NotificationChannel c, int appUid) -> {
+                    assertEquals(null, c);
+                    latch.countDown();
+                }, null, true, true);
+
+        mNotificationInfo.findViewById(R.id.info).performClick();
+        // Verify that listener was triggered.
+        assertEquals(0, latch.getCount());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testBindNotification_ChannelNameInvisibleWhenBundleFromDifferentChannels()
+            throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
+                null, true, true);
+        final TextView channelNameView =
+                mNotificationInfo.findViewById(R.id.channel_name);
+        assertEquals(GONE, channelNameView.getVisibility());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
+                null, true, true);
+        final TextView blockView = mNotificationInfo.findViewById(R.id.block);
+        assertEquals(GONE, blockView.getVisibility());
+    }
+
+    @Test
+    public void testbindNotification_BlockingHelper() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
+                true, true);
+        final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
+        assertEquals(View.VISIBLE, view.getVisibility());
+        assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
+    }
+
+    @Test
+    public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+        final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
+        assertEquals(View.VISIBLE, view.getVisibility());
+        assertEquals(mContext.getString(R.string.notification_unblockable_desc),
+                view.getText());
+    }
+
+    @Test
+    public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+    }
+
+    @Test
+    public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+    }
+
+    @Test
+    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedMin()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+
+        mNotificationInfo.findViewById(R.id.minimize).performClick();
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+    }
+
+    @Test
+    public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
+            throws Exception {
+        int originalImportance = mNotificationChannel.getImportance();
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+
+        mNotificationInfo.handleCloseControls(true, false);
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+        assertEquals(originalImportance, mNotificationChannel.getImportance());
+    }
+
+    @Test
+    public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+        assertEquals(IMPORTANCE_UNSPECIFIED, mNotificationChannel.getImportance());
+    }
+
+    @Test
+    public void testHandleCloseControls_setsNotificationsDisabledForMultipleChannelNotifications()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
+                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+                true, false /* isNonblockable */);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, times(1))
+                .setNotificationsEnabledWithImportanceLockForPackage(
+                        anyString(), eq(TEST_UID), eq(false));
+    }
+
+
+    @Test
+    public void testHandleCloseControls_keepsNotificationsEnabledForMultipleChannelNotifications()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
+                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+                true, false /* isNonblockable */);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, times(1))
+                .setNotificationsEnabledWithImportanceLockForPackage(
+                        anyString(), eq(TEST_UID), eq(false));
+    }
+
+    @Test
+    public void testCloseControls_blockingHelperSavesImportanceForMultipleChannelNotifications()
+            throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
+                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+                true /* provisioned */,
+                false /* isNonblockable */, true /* isForBlockingHelper */,
+                true /* isUserSentimentNegative */);
+
+        NotificationGuts guts = spy(new NotificationGuts(mContext, null));
+        when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
+        doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean());
+        doNothing().when(guts).setExposed(anyBoolean(), anyBoolean());
+        guts.setGutsContent(mNotificationInfo);
+        mNotificationInfo.setGutsParent(guts);
+
+        mNotificationInfo.findViewById(R.id.keep).performClick();
+
+        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, times(1))
+                .setNotificationsEnabledWithImportanceLockForPackage(
+                        anyString(), eq(TEST_UID), eq(true));
+    }
+
+    @Test
+    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing()
+            throws Exception {
+        NotificationInfo.CheckSaveListener listener =
+                mock(NotificationInfo.CheckSaveListener.class);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+                null /* onSettingsClick */, null /* onAppSettingsClick */ , true /* provisioned */,
+                false /* isNonblockable */, true /* isForBlockingHelper */,
+                true /* isUserSentimentNegative */);
+
+        NotificationGuts guts = spy(new NotificationGuts(mContext, null));
+        when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
+        doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean());
+        doNothing().when(guts).setExposed(anyBoolean(), anyBoolean());
+        guts.setGutsContent(mNotificationInfo);
+        mNotificationInfo.setGutsParent(guts);
+
+        mNotificationInfo.findViewById(R.id.keep).performClick();
+
+        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, times(1))
+                .setNotificationsEnabledWithImportanceLockForPackage(
+                        anyString(), eq(TEST_UID), eq(true));
+    }
+
+    @Test
+    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss()
+            throws Exception {
+        NotificationInfo.CheckSaveListener listener =
+                mock(NotificationInfo.CheckSaveListener.class);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+                false /* isNonblockable */, true /* isForBlockingHelper */,
+                true, true /* isUserSentimentNegative */);
+
+        mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
+
+        mTestableLooper.processAllMessages();
+        verify(listener, times(0)).checkSave(any(Runnable.class), eq(mSbn));
+    }
+
+    @Test
+    public void testCloseControls_checkSaveListenerDelaysStopNotifications()
+            throws Exception {
+        NotificationInfo.CheckSaveListener listener =
+                mock(NotificationInfo.CheckSaveListener.class);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+                null /* onSettingsClick */, null /* onAppSettingsClick */,
+                true /* provisioned */,
+                false /* isNonblockable */, true /* isForBlockingHelper */,
+                true /* isUserSentimentNegative */);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
+
+        mTestableLooper.processAllMessages();
+        verify(listener).checkSave(any(Runnable.class), eq(mSbn));
+    }
+
+    @Test
+    public void testCloseControls_blockingHelperDismissedIfShown() throws Exception {
+        mNotificationInfo.bindNotification(
+                mMockPackageManager,
+                mMockINotificationManager,
+                TEST_PACKAGE_NAME,
+                mNotificationChannel,
+                1 /* numChannels */,
+                mSbn,
+                null /* checkSaveListener */,
+                null /* onSettingsClick */,
+                null /* onAppSettingsClick */,
+                false /* isNonblockable */,
+                true /* isForBlockingHelper */,
+                true,
+                false /* isUserSentimentNegative */);
+        NotificationGuts guts = mock(NotificationGuts.class);
+        doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
+        mNotificationInfo.setGutsParent(guts);
+
+        mNotificationInfo.closeControls(mNotificationInfo);
+
+        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
+    }
+
+    @Test
+    public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+    }
+
+    @Test
+    public void testBlockChangedCallsUpdateNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testBlockChangedCallsUpdateNotificationChannel_blockingHelper() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(
+                mMockPackageManager,
+                mMockINotificationManager,
+                TEST_PACKAGE_NAME,
+                mNotificationChannel,
+                1 /* numChannels */,
+                mSbn,
+                null /* checkSaveListener */,
+                null /* onSettingsClick */,
+                null /* onAppSettingsClick */,
+                true /*provisioned */,
+                false /* isNonblockable */,
+                true /* isForBlockingHelper */,
+                true /* isUserSentimentNegative */);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
+    }
+
+
+    @Test
+    public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+        mNotificationInfo.findViewById(R.id.minimize).performClick();
+        waitForUndoButton();
+
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+    }
+
+    @Test
+    public void testMinChangedCallsUpdateNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+
+        mNotificationInfo.findViewById(R.id.minimize).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_MIN, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testKeepUpdatesNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
+        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
+    }
+
+    @Test
+    public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.findViewById(R.id.undo).performClick();
+        waitForStopButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
+        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
+    }
+
+    @Test
+    public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+
+        mNotificationInfo.findViewById(R.id.minimize).performClick();
+        waitForUndoButton();
+        mNotificationInfo.findViewById(R.id.undo).performClick();
+        waitForStopButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
+        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
+    }
+
+    @Test
+    public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+
+        mNotificationInfo.findViewById(R.id.minimize).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(false, false);
+
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
+    }
+
+    @Test
+    public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(false, false);
+
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
+    }
+
+    @Test
+    public void testCloseControlsDoesNotUpdateIfCheckSaveListenerIsNoOp() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+                (Runnable saveImportance, StatusBarNotification sbn) -> {
+                }, null, null, true, true);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
+    }
+
+    @Test
+    public void testCloseControlsUpdatesWhenCheckSaveListenerUsesCallback() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+                (Runnable saveImportance, StatusBarNotification sbn) -> {
+                    saveImportance.run();
+                }, null, null, true, false);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
+    }
+
+    @Test
+    public void testDisplaySettingsLink() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        final String settingsText = "work chats";
+        final ResolveInfo ri = new ResolveInfo();
+        ri.activityInfo = new ActivityInfo();
+        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
+        ri.activityInfo.name = "something";
+        List<ResolveInfo> ris = new ArrayList<>();
+        ris.add(ri);
+        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
+                .setSettingsText(settingsText).build();
+        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
+                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
+
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
+                (View v, Intent intent) -> {
+                    latch.countDown();
+                }, true, false);
+        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
+        assertEquals(View.VISIBLE, settingsLink.getVisibility());
+        settingsLink.performClick();
+        assertEquals(0, latch.getCount());
+    }
+
+    @Test
+    public void testDisplaySettingsLink_multipleChannels() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        final String settingsText = "work chats";
+        final ResolveInfo ri = new ResolveInfo();
+        ri.activityInfo = new ActivityInfo();
+        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
+        ri.activityInfo.name = "something";
+        List<ResolveInfo> ris = new ArrayList<>();
+        ris.add(ri);
+        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
+                .setSettingsText(settingsText).build();
+        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
+                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
+
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
+                (View v, Intent intent) -> {
+                    latch.countDown();
+                }, true, false);
+        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
+        assertEquals(View.VISIBLE, settingsLink.getVisibility());
+        settingsLink.performClick();
+        assertEquals(0, latch.getCount());
+    }
+
+    @Test
+    public void testNoSettingsLink_noHandlingActivity() throws Exception {
+        final String settingsText = "work chats";
+        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(null);
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
+                .setSettingsText(settingsText).build();
+        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
+                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
+
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
+                null, true, false);
+        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
+        assertEquals(GONE, settingsLink.getVisibility());
+    }
+
+    @Test
+    public void testNoSettingsLink_noLinkText() throws Exception {
+        final ResolveInfo ri = new ResolveInfo();
+        ri.activityInfo = new ActivityInfo();
+        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
+        ri.activityInfo.name = "something";
+        List<ResolveInfo> ris = new ArrayList<>();
+        ris.add(ri);
+        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId()).build();
+        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
+                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
+
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false);
+        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
+        assertEquals(GONE, settingsLink.getVisibility());
+    }
+
+    @Test
+    public void testBindHeader_noSettingsLinkWhenIsForBlockingHelper() throws Exception {
+        final String settingsText = "work chats";
+        final ResolveInfo ri = new ResolveInfo();
+        ri.activityInfo = new ActivityInfo();
+        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
+        ri.activityInfo.name = "something";
+        List<ResolveInfo> ris = new ArrayList<>();
+        ris.add(ri);
+        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
+                .setSettingsText(settingsText).build();
+        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
+                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
+
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
+                true, true);
+        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
+        assertEquals(GONE, settingsLink.getVisibility());
+    }
+
+
+    @Test
+    public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
+        assertFalse(mNotificationInfo.willBeRemoved());
+    }
+
+    @Test
+    public void testUndoText_min() throws Exception {
+        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+
+        mNotificationInfo.findViewById(R.id.minimize).performClick();
+        waitForUndoButton();
+        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+        assertTrue(confirmationText.getText().toString().contains("minimized"));
+    }
+
+    @Test
+    public void testUndoText_block() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+        assertTrue(confirmationText.getText().toString().contains("won't see"));
+    }
+
+    @Test
+    public void testNoHeaderOnConfirmation() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        assertEquals(GONE, mNotificationInfo.findViewById(R.id.header).getVisibility());
+    }
+
+    @Test
+    public void testHeaderOnUndo() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.findViewById(R.id.undo).performClick();
+        waitForStopButton();
+        assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
new file mode 100644
index 0000000..06265e5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.testing.ViewUtils;
+import android.testing.ViewUtils;
+import android.view.ViewGroup;
+
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.utils.leaks.LeakCheckedTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class NotificationMenuRowTest extends LeakCheckedTest {
+
+    @Before
+    public void setup() {
+        injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+    }
+
+    @Test
+    public void testAttachDetach() {
+        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+        row.createMenu(null, null);
+        ViewUtils.attachView(row.getMenuView());
+        TestableLooper.get(this).processAllMessages();
+        ViewUtils.detachView(row.getMenuView());
+        TestableLooper.get(this).processAllMessages();
+    }
+
+    @Test
+    public void testRecreateMenu() {
+        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+        row.createMenu(null, null);
+        assertTrue(row.getMenuView() != null);
+        row.createMenu(null, null);
+        assertTrue(row.getMenuView() != null);
+    }
+
+    @Test
+    public void testResetUncreatedMenu() {
+        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+        row.resetMenu();
+    }
+
+    @Test
+    public void testNoAppOpsInSlowSwipe() {
+        NotificationMenuRow row = new NotificationMenuRow(mContext);
+        Notification n = mock(Notification.class);
+        StatusBarNotification sbn = mock(StatusBarNotification.class);
+        when(sbn.getNotification()).thenReturn(n);
+        ExpandableNotificationRow parent = mock(ExpandableNotificationRow.class);
+        when(parent.getStatusBarNotification()).thenReturn(sbn);
+        row.createMenu(parent, null);
+
+        ViewGroup container = (ViewGroup) row.getMenuView();
+        // one for snooze and one for noti blocking
+        assertEquals(2, container.getChildCount());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSnoozeTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSnoozeTest.java
new file mode 100644
index 0000000..f8f7af0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationSnoozeTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.provider.Settings;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableResources;
+import android.testing.UiThreadTest;
+import android.util.KeyValueListParser;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.mock;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@UiThreadTest
+public class NotificationSnoozeTest extends SysuiTestCase {
+    private static final int RES_DEFAULT = 2;
+    private static final int[] RES_OPTIONS = {1, 2, 3};
+    private NotificationSnooze mNotificationSnooze;
+    private KeyValueListParser mMockParser;
+
+    @Before
+    public void setUp() throws Exception {
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS, null);
+        TestableResources resources = mContext.getOrCreateTestableResources();
+        resources.addOverride(R.integer.config_notification_snooze_time_default, RES_DEFAULT);
+        resources.addOverride(R.array.config_notification_snooze_times, RES_OPTIONS);
+        mNotificationSnooze = new NotificationSnooze(mContext, null);
+        mMockParser = mock(KeyValueListParser.class);
+    }
+
+    @Test
+    public void testGetOptionsWithNoConfig() throws Exception {
+        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
+        assertEquals(3, result.size());
+        assertEquals(1, result.get(0).getMinutesToSnoozeFor());  // respect order
+        assertEquals(2, result.get(1).getMinutesToSnoozeFor());
+        assertEquals(3, result.get(2).getMinutesToSnoozeFor());
+        assertEquals(2, mNotificationSnooze.getDefaultOption().getMinutesToSnoozeFor());
+    }
+
+    @Test
+    public void testGetOptionsWithInvalidConfig() throws Exception {
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
+                "this is garbage");
+        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
+        assertEquals(3, result.size());
+        assertEquals(1, result.get(0).getMinutesToSnoozeFor());  // respect order
+        assertEquals(2, result.get(1).getMinutesToSnoozeFor());
+        assertEquals(3, result.get(2).getMinutesToSnoozeFor());
+        assertEquals(2, mNotificationSnooze.getDefaultOption().getMinutesToSnoozeFor());
+    }
+
+    @Test
+    public void testGetOptionsWithValidDefault() throws Exception {
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
+                "default=10,options_array=4:5:6:7");
+        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
+        assertNotNull(mNotificationSnooze.getDefaultOption());  // pick one
+    }
+
+    @Test
+    public void testGetOptionsWithValidConfig() throws Exception {
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
+                "default=6,options_array=4:5:6:7");
+        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
+        assertEquals(4, result.size());
+        assertEquals(4, result.get(0).getMinutesToSnoozeFor());  // respect order
+        assertEquals(5, result.get(1).getMinutesToSnoozeFor());
+        assertEquals(6, result.get(2).getMinutesToSnoozeFor());
+        assertEquals(7, result.get(3).getMinutesToSnoozeFor());
+        assertEquals(6, mNotificationSnooze.getDefaultOption().getMinutesToSnoozeFor());
+    }
+
+    @Test
+    public void testGetOptionsWithLongConfig() throws Exception {
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
+                "default=6,options_array=4:5:6:7:8:9:10:11:12:13:14:15:16:17");
+        ArrayList<SnoozeOption> result = mNotificationSnooze.getDefaultSnoozeOptions();
+        assertTrue(result.size() > 3);
+        assertEquals(4, result.get(0).getMinutesToSnoozeFor());  // respect order
+        assertEquals(5, result.get(1).getMinutesToSnoozeFor());
+        assertEquals(6, result.get(2).getMinutesToSnoozeFor());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
new file mode 100644
index 0000000..4b94a25
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+public class NotificationCustomViewWrapperTest extends SysuiTestCase {
+
+    private ExpandableNotificationRow mRow;
+
+    @Before
+    public void setUp() throws Exception {
+        mRow = new NotificationTestHelper(mContext).createRow();
+    }
+
+    @Test
+    public void testBackgroundPersists() {
+        RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.custom_view_dark);
+        View v = views.apply(mContext, null);
+        NotificationViewWrapper wrap = NotificationCustomViewWrapper.wrap(mContext, v, mRow);
+        wrap.onContentUpdated(mRow);
+        Assert.assertTrue("No background set, when applying custom background view",
+                wrap.getCustomBackgroundColor() != 0);
+        views.reapply(mContext, v);
+        wrap.onReinflated();
+        wrap.onContentUpdated(mRow);
+        Assert.assertTrue("Reapplying a custom remote view lost it's background!",
+                wrap.getCustomBackgroundColor() != 0);
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
new file mode 100644
index 0000000..087aa59
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.NotificationHeaderView;
+import android.view.View;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+public class NotificationChildrenContainerTest extends SysuiTestCase {
+
+    private ExpandableNotificationRow mGroup;
+    private int mId;
+    private NotificationTestHelper mNotificationTestHelper;
+    private NotificationChildrenContainer mChildrenContainer;
+
+    @Before
+    public void setUp() throws Exception {
+        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mGroup = mNotificationTestHelper.createGroup();
+        mChildrenContainer = mGroup.getChildrenContainer();
+    }
+
+    @Test
+    public void testGetMaxAllowedVisibleChildren_ambient() {
+        mGroup.setShowAmbient(true);
+        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
+            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_AMBIENT);
+    }
+
+    @Test
+    public void testGetMaxAllowedVisibleChildren_lowPriority() {
+        mChildrenContainer.setIsLowPriority(true);
+        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
+            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
+    }
+
+    @Test
+    public void testGetMaxAllowedVisibleChildren_headsUp() {
+        mGroup.setHeadsUp(true);
+        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
+                NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
+    }
+
+    @Test
+    public void testGetMaxAllowedVisibleChildren_lowPriority_expandedChildren() {
+        mChildrenContainer.setIsLowPriority(true);
+        mChildrenContainer.setChildrenExpanded(true);
+        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
+            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
+    }
+
+    @Test
+    public void testGetMaxAllowedVisibleChildren_lowPriority_userLocked() {
+        mChildrenContainer.setIsLowPriority(true);
+        mChildrenContainer.setUserLocked(true);
+        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
+            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
+    }
+
+    @Test
+    public void testGetMaxAllowedVisibleChildren_likeCollapsed() {
+        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(true),
+            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
+    }
+
+
+    @Test
+    public void testGetMaxAllowedVisibleChildren_expandedChildren() {
+        mChildrenContainer.setChildrenExpanded(true);
+        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
+                NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
+    }
+
+    @Test
+    public void testGetMaxAllowedVisibleChildren_userLocked() {
+        mGroup.setUserLocked(true);
+        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
+                NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
+    }
+
+    @Test
+    public void testShowingAsLowPriority_lowPriority() {
+        mChildrenContainer.setIsLowPriority(true);
+        Assert.assertTrue(mChildrenContainer.showingAsLowPriority());
+    }
+
+    @Test
+    public void testShowingAsLowPriority_notLowPriority() {
+        Assert.assertFalse(mChildrenContainer.showingAsLowPriority());
+    }
+
+    @Test
+    public void testShowingAsLowPriority_lowPriority_expanded() {
+        mChildrenContainer.setIsLowPriority(true);
+        mGroup.setExpandable(true);
+        mGroup.setUserExpanded(true, false);
+        Assert.assertFalse(mChildrenContainer.showingAsLowPriority());
+    }
+
+    @Test
+    public void testGetMaxAllowedVisibleChildren_userLocked_expandedChildren_lowPriority() {
+        mGroup.setUserLocked(true);
+        mGroup.setExpandable(true);
+        mGroup.setUserExpanded(true);
+        mChildrenContainer.setIsLowPriority(true);
+        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
+                NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
+    }
+
+    @Test
+    public void testLowPriorityHeaderCleared() {
+        mGroup.setIsLowPriority(true);
+        NotificationHeaderView lowPriorityHeaderView = mChildrenContainer.getLowPriorityHeaderView();
+        Assert.assertTrue(lowPriorityHeaderView.getVisibility() == View.VISIBLE);
+        Assert.assertTrue(lowPriorityHeaderView.getParent() == mChildrenContainer);
+        mGroup.setIsLowPriority(false);
+        Assert.assertTrue(lowPriorityHeaderView.getParent() == null);
+        Assert.assertTrue(mChildrenContainer.getLowPriorityHeaderView() == null);
+    }
+
+    @Test
+    public void testRecreateNotificationHeader_hasHeader() {
+        mChildrenContainer.recreateNotificationHeader(null);
+        Assert.assertNotNull("Children container must have a header after recreation",
+                mChildrenContainer.getCurrentHeaderView());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
new file mode 100644
index 0000000..f2431b4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.View;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashSet;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+public class NotificationRoundnessManagerTest extends SysuiTestCase {
+
+    private NotificationRoundnessManager mRoundnessManager = new NotificationRoundnessManager();
+    private HashSet<View> mAnimatedChildren = new HashSet<>();
+    private Runnable mRoundnessCallback = mock(Runnable.class);
+    private ExpandableNotificationRow mFirst;
+    private ExpandableNotificationRow mSecond;
+
+    @Before
+    public void setUp() throws Exception {
+        NotificationTestHelper testHelper = new NotificationTestHelper(getContext());
+        mFirst = testHelper.createRow();
+        mFirst.setHeadsUpAnimatingAwayListener(animatingAway
+                -> mRoundnessManager.onHeadsupAnimatingAwayChanged(mFirst, animatingAway));
+        mSecond = testHelper.createRow();
+        mSecond.setHeadsUpAnimatingAwayListener(animatingAway
+                -> mRoundnessManager.onHeadsupAnimatingAwayChanged(mSecond, animatingAway));
+        mRoundnessManager.setOnRoundingChangedCallback(mRoundnessCallback);
+        mRoundnessManager.setAnimatedChildren(mAnimatedChildren);
+        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, mFirst);
+        mRoundnessManager.setExpanded(1.0f, 1.0f);
+    }
+
+    @Test
+    public void testCallbackCalledWhenSecondChanged() {
+        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, mSecond);
+        verify(mRoundnessCallback, atLeast(1)).run();
+    }
+
+    @Test
+    public void testCallbackCalledWhenFirstChanged() {
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mFirst);
+        verify(mRoundnessCallback, atLeast(1)).run();
+    }
+
+    @Test
+    public void testRoundnessSetOnLast() {
+        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, mSecond);
+        Assert.assertEquals(1.0f, mSecond.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(0.0f, mSecond.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testRoundnessSetOnNew() {
+        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, null);
+        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testCompleteReplacement() {
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testNotCalledWhenRemoved() {
+        mFirst.setRemoved();
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testRoundedWhenPinnedAndCollapsed() {
+        mFirst.setPinned(true);
+        mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testRoundedWhenGoingAwayAndCollapsed() {
+        mFirst.setHeadsUpAnimatingAway(true);
+        mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testRoundedNormalRoundingWhenExpanded() {
+        mFirst.setHeadsUpAnimatingAway(true);
+        mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.0f /* appearFraction */);
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testTrackingHeadsUpRoundedIfPushingUp() {
+        mRoundnessManager.setExpanded(1.0f /* expandedHeight */, -0.5f /* appearFraction */);
+        mRoundnessManager.setTrackingHeadsUp(mFirst);
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testTrackingHeadsUpNotRoundedIfPushingDown() {
+        mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.5f /* appearFraction */);
+        mRoundnessManager.setTrackingHeadsUp(mFirst);
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testRoundingUpdatedWhenAnimatingAwayTrue() {
+        mRoundnessManager.setExpanded(0.0f, 0.0f);
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mFirst.setHeadsUpAnimatingAway(true);
+        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+
+
+    @Test
+    public void testRoundingUpdatedWhenAnimatingAwayFalse() {
+        mRoundnessManager.setExpanded(0.0f, 0.0f);
+        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mFirst.setHeadsUpAnimatingAway(true);
+        mFirst.setHeadsUpAnimatingAway(false);
+        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
+    }
+}
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
new file mode 100644
index 0000000..c19188c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.systemui.ExpandHelper;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationData.Entry;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.FooterView;
+import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarTest.TestableNotificationEntryManager;
+
+import java.util.ArrayList;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+/**
+ * Tests for {@link NotificationStackScrollLayout}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationStackScrollLayoutTest extends SysuiTestCase {
+
+    private NotificationStackScrollLayout mStackScroller;
+
+    @Rule public MockitoRule mockito = MockitoJUnit.rule();
+    @Mock private StatusBar mBar;
+    @Mock private StatusBarStateController mBarState;
+    @Mock private HeadsUpManagerPhone mHeadsUpManager;
+    @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
+    @Mock private NotificationGroupManager mGroupManager;
+    @Mock private ExpandHelper mExpandHelper;
+    @Mock private EmptyShadeView mEmptyShadeView;
+    @Mock private NotificationData mNotificationData;
+    @Mock private NotificationRemoteInputManager mRemoteInputManager;
+    @Mock private RemoteInputController mRemoteInputController;
+    @Mock private SystemServicesProxy mSystemServicesProxy;
+    private PowerManager mPowerManager;
+    private TestableNotificationEntryManager mEntryManager;
+
+    @Before
+    @UiThreadTest
+    public void setUp() throws Exception {
+        // Inject dependencies before initializing the layout
+        mDependency.injectTestDependency(
+                NotificationBlockingHelperManager.class,
+                mBlockingHelperManager);
+        mDependency.injectTestDependency(StatusBarStateController.class, mBarState);
+        mDependency.injectTestDependency(NotificationRemoteInputManager.class,
+                mRemoteInputManager);
+        when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
+
+        IPowerManager powerManagerService = mock(IPowerManager.class);
+        mPowerManager = new PowerManager(mContext, powerManagerService,
+                Handler.createAsync(Looper.myLooper()));
+
+        mEntryManager = new TestableNotificationEntryManager(mSystemServicesProxy, mPowerManager,
+                mContext);
+        mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, null, null, mNotificationData);
+        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
+
+        NotificationShelf notificationShelf = spy(new NotificationShelf(getContext(), null));
+        mStackScroller = spy(new NotificationStackScrollLayout(getContext()));
+        mStackScroller.setShelf(notificationShelf);
+        mStackScroller.setStatusBar(mBar);
+        mStackScroller.setScrimController(mock(ScrimController.class));
+        mStackScroller.setHeadsUpManager(mHeadsUpManager);
+        mStackScroller.setGroupManager(mGroupManager);
+        mStackScroller.setEmptyShadeView(mEmptyShadeView);
+
+        // Stub out functionality that isn't necessary to test.
+        doNothing().when(mBar)
+                .executeRunnableDismissingKeyguard(any(Runnable.class),
+                        any(Runnable.class),
+                        anyBoolean(),
+                        anyBoolean(),
+                        anyBoolean());
+        doNothing().when(mGroupManager).collapseAllGroups();
+        doNothing().when(mExpandHelper).cancelImmediately();
+        doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean());
+        doNothing().when(notificationShelf).fadeInTranslating();
+    }
+
+    @Test
+    public void testNotDimmedOnKeyguard() {
+        when(mBarState.getState()).thenReturn(StatusBarState.SHADE);
+        mStackScroller.setDimmed(true /* dimmed */, false /* animate */);
+        mStackScroller.setDimmed(true /* dimmed */, true /* animate */);
+        Assert.assertFalse(mStackScroller.isDimmed());
+    }
+
+    @Test
+    public void testAntiBurnInOffset() {
+        final int burnInOffset = 30;
+        mStackScroller.setAntiBurnInOffsetX(burnInOffset);
+        mStackScroller.setDark(false /* dark */, false /* animated */, null /* touch */);
+        Assert.assertEquals(0 /* expected */, mStackScroller.getTranslationX(), 0.01 /* delta */);
+        mStackScroller.setDark(true /* dark */, false /* animated */, null /* touch */);
+        Assert.assertEquals(burnInOffset /* expected */, mStackScroller.getTranslationX(),
+                0.01 /* delta */);
+    }
+
+    @Test
+    public void updateEmptyView_dndSuppressing() {
+        when(mEmptyShadeView.willBeGone()).thenReturn(true);
+        when(mBar.areNotificationsHidden()).thenReturn(true);
+
+        mStackScroller.updateEmptyShadeView(true);
+
+        verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
+    }
+
+    @Test
+    public void updateEmptyView_dndNotSuppressing() {
+        mStackScroller.setEmptyShadeView(mEmptyShadeView);
+        when(mEmptyShadeView.willBeGone()).thenReturn(true);
+        when(mBar.areNotificationsHidden()).thenReturn(false);
+
+        mStackScroller.updateEmptyShadeView(true);
+
+        verify(mEmptyShadeView).setText(R.string.empty_shade_text);
+    }
+
+    @Test
+    public void updateEmptyView_noNotificationsToDndSuppressing() {
+        mStackScroller.setEmptyShadeView(mEmptyShadeView);
+        when(mEmptyShadeView.willBeGone()).thenReturn(true);
+        when(mBar.areNotificationsHidden()).thenReturn(false);
+        mStackScroller.updateEmptyShadeView(true);
+        verify(mEmptyShadeView).setText(R.string.empty_shade_text);
+
+        when(mBar.areNotificationsHidden()).thenReturn(true);
+        mStackScroller.updateEmptyShadeView(true);
+        verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() {
+        mStackScroller.setExpandedHeight(0f);
+        verify(mBlockingHelperManager).setNotificationShadeExpanded(0f);
+        reset(mBlockingHelperManager);
+
+        mStackScroller.setExpandedHeight(100f);
+        verify(mBlockingHelperManager).setNotificationShadeExpanded(100f);
+    }
+
+    @Test
+    public void manageNotifications_visible() {
+        FooterView view = mock(FooterView.class);
+        mStackScroller.setFooterView(view);
+        when(view.willBeGone()).thenReturn(true);
+
+        mStackScroller.updateFooterView(true, false);
+
+        verify(view).setVisible(eq(true), anyBoolean());
+        verify(view).setSecondaryVisible(eq(false), anyBoolean());
+    }
+
+    @Test
+    public void clearAll_visible() {
+        FooterView view = mock(FooterView.class);
+        mStackScroller.setFooterView(view);
+        when(view.willBeGone()).thenReturn(true);
+
+        mStackScroller.updateFooterView(true, true);
+
+        verify(view).setVisible(eq(true), anyBoolean());
+        verify(view).setSecondaryVisible(eq(true), anyBoolean());
+    }
+
+    @Test
+    public void testInflateFooterView() {
+        mStackScroller.inflateFooterView();
+        ArgumentCaptor<FooterView> captor = ArgumentCaptor.forClass(FooterView.class);
+        verify(mStackScroller).setFooterView(captor.capture());
+
+        assertNotNull(captor.getValue().findViewById(R.id.manage_text).hasOnClickListeners());
+        assertNotNull(captor.getValue().findViewById(R.id.dismiss_text).hasOnClickListeners());
+    }
+
+    @Test
+    public void testUpdateFooter_noNotifications() {
+        setBarStateForTest(StatusBarState.SHADE);
+        assertEquals(0, mNotificationData.getActiveNotifications().size());
+
+        mStackScroller.updateFooter();
+        verify(mStackScroller).updateFooterView(false, false);
+    }
+
+    @Test
+    public void testUpdateFooter_remoteInput() {
+        setBarStateForTest(StatusBarState.SHADE);
+        ArrayList<Entry> entries = new ArrayList<>();
+        entries.add(mock(Entry.class));
+        when(mNotificationData.getActiveNotifications()).thenReturn(entries);
+
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        when(row.canViewBeDismissed()).thenReturn(true);
+        when(mStackScroller.getChildCount()).thenReturn(1);
+        when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
+        when(mRemoteInputController.isRemoteInputActive()).thenReturn(true);
+
+        mStackScroller.updateFooter();
+        verify(mStackScroller).updateFooterView(false, true);
+    }
+
+    @Test
+    public void testUpdateFooter_oneClearableNotification() {
+        setBarStateForTest(StatusBarState.SHADE);
+        ArrayList<Entry> entries = new ArrayList<>();
+        entries.add(mock(Entry.class));
+        when(mNotificationData.getActiveNotifications()).thenReturn(entries);
+
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        when(row.canViewBeDismissed()).thenReturn(true);
+        when(mStackScroller.getChildCount()).thenReturn(1);
+        when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
+
+        mStackScroller.updateFooter();
+        verify(mStackScroller).updateFooterView(true, true);
+    }
+
+    @Test
+    public void testUpdateFooter_oneNonClearableNotification() {
+        setBarStateForTest(StatusBarState.SHADE);
+        ArrayList<Entry> entries = new ArrayList<>();
+        entries.add(mock(Entry.class));
+        when(mNotificationData.getActiveNotifications()).thenReturn(entries);
+
+        mStackScroller.updateFooter();
+        verify(mStackScroller).updateFooterView(true, false);
+    }
+
+    @Test
+    public void testUpdateFooter_atEnd() {
+        // add footer
+        mStackScroller.inflateFooterView();
+
+        // add notification
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        when(row.isClearable()).thenReturn(true);
+        mStackScroller.addContainerView(row);
+
+        mStackScroller.onUpdateRowStates();
+
+        // move footer to end
+        verify(mStackScroller).changeViewPosition(any(FooterView.class), eq(-1 /* end */));
+    }
+
+    @Test
+    public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() {
+        clearInvocations(mStackScroller);
+        mStackScroller.onDensityOrFontScaleChanged();
+        verify(mStackScroller).setFooterView(any());
+        verify(mStackScroller).setEmptyShadeView(any());
+    }
+
+    private void setBarStateForTest(int state) {
+        ArgumentCaptor<StatusBarStateController.StateListener> captor =
+                ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
+        verify(mBarState).addListener(captor.capture());
+        captor.getValue().onStateChanged(state);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
new file mode 100644
index 0000000..0d13e97
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.support.test.filters.SmallTest
+import android.testing.AndroidTestingRunner
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class ConfigurationControllerImplTest : SysuiTestCase() {
+
+    private val mConfigurationController =
+            com.android.systemui.statusbar.phone.ConfigurationControllerImpl(mContext)
+
+    @Test
+    fun testThemeChange() {
+        val listener = mock(ConfigurationListener::class.java)
+        mConfigurationController.addCallback(listener)
+
+        mConfigurationController.notifyThemeChanged()
+        verify(listener).onThemeChanged()
+    }
+
+    @Test
+    fun testRemoveListenerDuringCallback() {
+        val listener = mock(ConfigurationListener::class.java)
+        mConfigurationController.addCallback(listener)
+        val listener2 = mock(ConfigurationListener::class.java)
+        mConfigurationController.addCallback(listener2)
+
+        doAnswer {
+            mConfigurationController.removeCallback(listener2)
+            null
+        }.`when`(listener).onThemeChanged()
+
+        mConfigurationController.notifyThemeChanged()
+        verify(listener).onThemeChanged()
+        verify(listener2, never()).onThemeChanged()
+    }
+}
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 fe7bf25..a4004ae 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,8 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyObject;
-import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
@@ -31,23 +29,18 @@
 import android.view.View;
 import android.widget.TextView;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.TestableDependency;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.HeadsUpStatusBarView;
 import com.android.systemui.statusbar.NotificationTestHelper;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.HashSet;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index aa991cb..bdf7cd3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -16,22 +16,13 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.app.ActivityManager;
-import android.app.Instrumentation;
-import android.app.Notification;
-import android.os.UserHandle;
 import android.view.View;
-import android.service.notification.StatusBarNotification;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.AlertingNotificationManager;
+import com.android.systemui.statusbar.AlertingNotificationManagerTest;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 
 import org.junit.Before;
@@ -42,175 +33,54 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.assertFalse;
 
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
-public class HeadsUpManagerPhoneTest extends SysuiTestCase {
+public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest {
     @Rule public MockitoRule rule = MockitoJUnit.rule();
 
-    private static final String TEST_PACKAGE_NAME = "test";
-    private static final int TEST_UID = 0;
-
     private HeadsUpManagerPhone mHeadsUpManager;
 
-    private NotificationData.Entry mEntry;
-    private StatusBarNotification mSbn;
-
     @Mock private NotificationGroupManager mGroupManager;
     @Mock private View mStatusBarWindowView;
-    @Mock private StatusBar mBar;
-    @Mock private ExpandableNotificationRow mRow;
     @Mock private VisualStabilityManager mVSManager;
+    @Mock private StatusBar mBar;
+
+    protected AlertingNotificationManager createAlertingNotificationManager() {
+        return mHeadsUpManager;
+    }
 
     @Before
     public void setUp() {
         when(mVSManager.isReorderingAllowed()).thenReturn(true);
-
-        mHeadsUpManager = new HeadsUpManagerPhone(
-                mContext, mStatusBarWindowView, mGroupManager, mBar, mVSManager);
-
-        Notification.Builder n = new Notification.Builder(mContext, "")
-                .setSmallIcon(R.drawable.ic_person)
-                .setContentTitle("Title")
-                .setContentText("Text");
-        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
-             0, n.build(), new UserHandle(ActivityManager.getCurrentUser()), null, 0);
-
-        mEntry = new NotificationData.Entry(mSbn);
-        mEntry.row = mRow;
-        mEntry.expandedIcon = mock(StatusBarIconView.class);
+        mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarWindowView, mGroupManager,
+                mBar, mVSManager);
+        super.setUp();
+        mHeadsUpManager.mHandler = mTestHandler;
     }
 
     @Test
-    public void testBasicOperations() {
-        // Check the initial state.
-        assertNull(mHeadsUpManager.getEntry(mEntry.key));
-        assertNull(mHeadsUpManager.getTopEntry());
-        assertEquals(0, mHeadsUpManager.getAllEntries().count());
-        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
-
-        // Add a notification.
+    public void testSnooze() {
         mHeadsUpManager.showNotification(mEntry);
 
-        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
-        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
-        assertEquals(1, mHeadsUpManager.getAllEntries().count());
-        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+        mHeadsUpManager.snooze();
 
-        // Update the notification.
-        mHeadsUpManager.updateNotification(mEntry, false);
-
-        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
-        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
-        assertEquals(1, mHeadsUpManager.getAllEntries().count());
-        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
-
-        // Try to remove but defer, since the notification is currenlt visible on display.
-        mHeadsUpManager.removeNotification(mEntry.key, false /* ignoreEarliestRemovalTime */);
-
-        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
-        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
-        assertEquals(1, mHeadsUpManager.getAllEntries().count());
-        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
-
-        // Remove forcibly with ignoreEarliestRemovalTime = true.
-        mHeadsUpManager.removeNotification(mEntry.key, true /* ignoreEarliestRemovalTime */);
-
-        // Check the initial state.
-        assertNull(mHeadsUpManager.getEntry(mEntry.key));
-        assertNull(mHeadsUpManager.getTopEntry());
-        assertEquals(0, mHeadsUpManager.getAllEntries().count());
-        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+        assertTrue(mHeadsUpManager.isSnoozed(mEntry.notification.getPackageName()));
     }
 
     @Test
-    public void testsTimeoutRemoval() {
-        mHeadsUpManager.removeMinimumDisplayTimeForTesting();
-
-        // Check the initial state.
-        assertNull(mHeadsUpManager.getEntry(mEntry.key));
-        assertNull(mHeadsUpManager.getTopEntry());
-        assertEquals(0, mHeadsUpManager.getAllEntries().count());
-        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
-
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-
-        // Run the code on the main thready, not to run an async operations.
-        instrumentation.runOnMainSync(() -> {
-            // Add a notification.
-            mHeadsUpManager.showNotification(mEntry);
-
-            // Ensure the head up is visible before timeout.
-            assertNotNull(mHeadsUpManager.getEntry(mEntry.key));
-            assertNotNull(mHeadsUpManager.getTopEntry());
-            assertEquals(1, mHeadsUpManager.getAllEntries().count());
-            assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
-        });
-        // Wait for the async operations, which removes the heads up notification.
-        waitForIdleSync();
-
-        assertNull(mHeadsUpManager.getEntry(mEntry.key));
-        assertNull(mHeadsUpManager.getTopEntry());
-        assertEquals(0, mHeadsUpManager.getAllEntries().count());
-        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
-    }
-
-    @Test
-    public void releaseImmediately() {
-        // Check the initial state.
-        assertNull(mHeadsUpManager.getEntry(mEntry.key));
-        assertNull(mHeadsUpManager.getTopEntry());
-        assertEquals(0, mHeadsUpManager.getAllEntries().count());
-        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
-
-        // Add a notification.
+    public void testSwipedOutNotification() {
         mHeadsUpManager.showNotification(mEntry);
+        mHeadsUpManager.addSwipedOutNotification(mEntry.key);
 
-        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
-        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
-        assertEquals(1, mHeadsUpManager.getAllEntries().count());
-        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+        // Remove should succeed because the notification is swiped out
+        mHeadsUpManager.removeNotification(mEntry.key, false /* releaseImmediately */);
 
-        // Remove but defer, since the notification is visible on display.
-        mHeadsUpManager.releaseImmediately(mEntry.key);
-
-        assertNull(mHeadsUpManager.getEntry(mEntry.key));
-        assertNull(mHeadsUpManager.getTopEntry());
-        assertEquals(0, mHeadsUpManager.getAllEntries().count());
-        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
-    }
-
-    @Test
-    public void releaseAllImmediately() {
-        // Check the initial state.
-        assertNull(mHeadsUpManager.getEntry(mEntry.key));
-        assertNull(mHeadsUpManager.getTopEntry());
-        assertEquals(0, mHeadsUpManager.getAllEntries().count());
-        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
-
-        // Add a notification.
-        mHeadsUpManager.showNotification(mEntry);
-
-        assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
-        assertEquals(mEntry, mHeadsUpManager.getTopEntry());
-        assertEquals(1, mHeadsUpManager.getAllEntries().count());
-        assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
-
-        // Remove but defer, since the notification is visible on display.
-        mHeadsUpManager.releaseAllImmediately();
-
-        assertNull(mHeadsUpManager.getEntry(mEntry.key));
-        assertNull(mHeadsUpManager.getTopEntry());
-        assertEquals(0, mHeadsUpManager.getAllEntries().count());
-        assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+        assertFalse(mHeadsUpManager.contains(mEntry.key));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
index 667a508..2423e14 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
@@ -171,6 +171,23 @@
         ev.recycle();
     }
 
+    @Test
+    public void testFurtherSelectedWhenCloserNotFocusable() {
+        View closer = mockViewAt(0, 0, 10, 10);
+        View further = mockViewAt(20, 0, 10, 10);
+        closer.setFocusable(false);
+
+        mNearestTouchFrame.addView(closer);
+        mNearestTouchFrame.addView(further);
+        mNearestTouchFrame.onMeasure(0, 0);
+
+        MotionEvent ev = MotionEvent.obtain(0, 0, 0,
+                12 /* x */, 5 /* y */, 0);
+        mNearestTouchFrame.onTouchEvent(ev);
+        verify(further).onTouchEvent(eq(ev));
+        ev.recycle();
+    }
+
     private View mockViewAt(int x, int y, int width, int height) {
         View v = spy(new View(mContext));
         doAnswer(invocation -> {
@@ -187,6 +204,7 @@
         v.setRight(width);
         v.setTop(0);
         v.setBottom(height);
+        v.setFocusable(true);
         return v;
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 89d562a..9c55874 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -152,6 +152,20 @@
     }
 
     @Test
+    public void setHasBackdrop_withAodWallpaperAndAlbumArt() {
+        mScrimController.setWallpaperSupportsAmbientMode(true);
+        mScrimController.transitionTo(ScrimState.AOD);
+        mScrimController.finishAnimationsImmediately();
+        mScrimController.setHasBackdrop(true);
+        mScrimController.finishAnimationsImmediately();
+        // Front scrim should be transparent
+        // Back scrim should be visible with tint
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+        assertScrimTint(mScrimBehind, true /* tinted */);
+        assertScrimTint(mScrimInFront, true /* tinted */);
+    }
+
+    @Test
     public void transitionToAod_withFrontAlphaUpdates() {
         // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
         mScrimController.transitionTo(ScrimState.KEYGUARD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 6933328..be4560b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -68,7 +68,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mDependency.injectMockDependency(StatusBarWindowManager.class);
+        mDependency.injectMockDependency(StatusBarWindowController.class);
         mStatusBarKeyguardViewManager = new TestableStatusBarKeyguardViewManager(getContext(),
                 mViewMediatorCallback, mLockPatternUtils);
         mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index f908dfb..cbba251 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -41,12 +41,10 @@
 import android.app.StatusBarManager;
 import android.app.trust.TrustManager;
 import android.content.Context;
-import android.content.pm.UserInfo;
 import android.hardware.fingerprint.FingerprintManager;
 import android.metrics.LogMaker;
 import android.os.Binder;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.PowerManager;
@@ -59,8 +57,6 @@
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.util.SparseArray;
-import android.view.Gravity;
-import android.view.View;
 import android.view.ViewGroup.LayoutParams;
 
 import com.android.internal.logging.MetricsLogger;
@@ -76,47 +72,43 @@
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.statusbar.ActivatableNotificationView;
-import com.android.systemui.statusbar.AppOpsListener;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.AppOpsListener;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.FooterView;
-import com.android.systemui.statusbar.FooterViewButton;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationData.Entry;
-import com.android.systemui.statusbar.NotificationEntryManager;
-import com.android.systemui.statusbar.NotificationGutsManager;
-import com.android.systemui.statusbar.NotificationListContainer;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationData.Entry;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationLogger;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.function.Predicate;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -143,6 +135,7 @@
     @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
     @Mock private NotificationRemoteInputManager mRemoteInputManager;
     @Mock private RemoteInputController mRemoteInputController;
+    @Mock private StatusBarStateController mStatusBarStateController;
 
     private TestableStatusBar mStatusBar;
     private FakeMetricsLogger mMetricsLogger;
@@ -164,6 +157,7 @@
         mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
         mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class));
         mDependency.injectTestDependency(AppOpsListener.class, mock(AppOpsListener.class));
+        mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController);
 
         mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
         mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
@@ -210,7 +204,7 @@
                 mEntryManager, mScrimController, mBiometricUnlockController,
                 mock(ActivityLaunchAnimator.class), mKeyguardViewMediator,
                 mRemoteInputManager, mock(NotificationGroupManager.class),
-                mock(FalsingManager.class), mock(StatusBarWindowManager.class),
+                mock(FalsingManager.class), mock(StatusBarWindowController.class),
                 mock(NotificationIconAreaController.class), mock(DozeScrimController.class),
                 mock(NotificationShelf.class), mLockscreenUserManager,
                 mock(CommandQueue.class));
@@ -567,7 +561,7 @@
         mStatusBar.mState = StatusBarState.KEYGUARD;
         when(mStatusBar.mLockscreenUserManager.getCurrentProfiles()).thenReturn(
                 new SparseArray<>());
-        mStatusBar.updateKeyguardState(false, false);
+        mStatusBar.onStateChanged(StatusBarState.SHADE);
     }
 
     @Test
@@ -596,85 +590,7 @@
     }
 
     @Test
-    public void testInflateFooterView() {
-        mStatusBar.inflateFooterView();
-        ArgumentCaptor<FooterView> captor = ArgumentCaptor.forClass(FooterView.class);
-        verify(mStackScroller).setFooterView(captor.capture());
 
-        assertNotNull(captor.getValue().findViewById(R.id.manage_text).hasOnClickListeners());
-        assertNotNull(captor.getValue().findViewById(R.id.dismiss_text).hasOnClickListeners());
-    }
-
-    @Test
-    public void testUpdateFooter_noNotifications() {
-        mStatusBar.setBarStateForTest(StatusBarState.SHADE);
-        assertEquals(0, mEntryManager.getNotificationData().getActiveNotifications().size());
-
-        mStatusBar.updateFooter();
-        verify(mStackScroller).updateFooterView(false, false);
-    }
-
-    @Test
-    public void testUpdateFooter_remoteInput() {
-        mStatusBar.setBarStateForTest(StatusBarState.SHADE);
-        ArrayList<Entry> entries = new ArrayList<>();
-        entries.add(mock(Entry.class));
-        when(mNotificationData.getActiveNotifications()).thenReturn(entries);
-
-        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
-        when(row.canViewBeDismissed()).thenReturn(true);
-        when(mStackScroller.getChildCount()).thenReturn(1);
-        when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
-        when(mRemoteInputController.isRemoteInputActive()).thenReturn(true);
-
-        mStatusBar.updateFooter();
-        verify(mStackScroller).updateFooterView(false, true);
-    }
-
-    @Test
-    public void testUpdateFooter_oneClearableNotification() {
-        mStatusBar.setBarStateForTest(StatusBarState.SHADE);
-        ArrayList<Entry> entries = new ArrayList<>();
-        entries.add(mock(Entry.class));
-        when(mNotificationData.getActiveNotifications()).thenReturn(entries);
-
-        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
-        when(row.canViewBeDismissed()).thenReturn(true);
-        when(mStackScroller.getChildCount()).thenReturn(1);
-        when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
-
-        mStatusBar.updateFooter();
-        verify(mStackScroller).updateFooterView(true, true);
-    }
-
-    @Test
-    public void testUpdateFooter_oneNonClearableNotification() {
-        mStatusBar.setBarStateForTest(StatusBarState.SHADE);
-        ArrayList<Entry> entries = new ArrayList<>();
-        entries.add(mock(Entry.class));
-        when(mNotificationData.getActiveNotifications()).thenReturn(entries);
-
-        mStatusBar.updateFooter();
-        verify(mStackScroller).updateFooterView(true, false);
-    }
-
-    @Test
-    public void testUpdateFooter_atEnd() {
-        // add footer
-        mStatusBar.inflateFooterView();
-
-        // add notification
-        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
-        when(row.isClearable()).thenReturn(true);
-        mStackScroller.addContainerView(row);
-
-        mStatusBar.onUpdateRowStates();
-
-        // move footer to end
-        verify(mStackScroller).changeViewPosition(any(FooterView.class), eq(-1 /* end */));
-    }
-
-    @Test
     public void testSetState_changesIsFullScreenUserSwitcherState() {
         mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
         assertFalse(mStatusBar.isFullScreenUserSwitcherState());
@@ -691,20 +607,13 @@
 
         // By default, showKeyguardImpl sets state to KEYGUARD.
         mStatusBar.showKeyguardImpl();
-        assertTrue(mStatusBar.mState == StatusBarState.KEYGUARD);
+        verify(mStatusBarStateController).setState(eq(StatusBarState.KEYGUARD));
 
         // If useFullscreenUserSwitcher is true, state is set to FULLSCREEN_USER_SWITCHER.
         mStatusBar.mUserSwitcherController = mock(UserSwitcherController.class);
         when(mStatusBar.mUserSwitcherController.useFullscreenUserSwitcher()).thenReturn(true);
         mStatusBar.showKeyguardImpl();
-        assertTrue(mStatusBar.mState == StatusBarState.FULLSCREEN_USER_SWITCHER);
-    }
-
-    @Test
-    public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() {
-        mStatusBar.onDensityOrFontScaleChanged();
-        verify(mStackScroller).setFooterView(any());
-        verify(mStackScroller).setEmptyShadeView(any());
+        verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER));
     }
 
     static class TestableStatusBar extends StatusBar {
@@ -722,7 +631,7 @@
                 NotificationRemoteInputManager notificationRemoteInputManager,
                 NotificationGroupManager notificationGroupManager,
                 FalsingManager falsingManager,
-                StatusBarWindowManager statusBarWindowManager,
+                StatusBarWindowController statusBarWindowController,
                 NotificationIconAreaController notificationIconAreaController,
                 DozeScrimController dozeScrimController,
                 NotificationShelf notificationShelf,
@@ -746,11 +655,10 @@
             mBiometricUnlockController = biometricUnlockController;
             mActivityLaunchAnimator = launchAnimator;
             mKeyguardViewMediator = keyguardViewMediator;
-            mClearAllEnabled = true;
             mRemoteInputManager = notificationRemoteInputManager;
             mGroupManager = notificationGroupManager;
             mFalsingManager = falsingManager;
-            mStatusBarWindowManager = statusBarWindowManager;
+            mStatusBarWindowController = statusBarWindowController;
             mNotificationIconAreaController = notificationIconAreaController;
             mDozeScrimController = dozeScrimController;
             mNotificationShelf = notificationShelf;
@@ -780,7 +688,7 @@
 
     }
 
-    private class TestableNotificationEntryManager extends NotificationEntryManager {
+    public static class TestableNotificationEntryManager extends NotificationEntryManager {
 
         public TestableNotificationEntryManager(SystemServicesProxy systemServicesProxy,
                 PowerManager powerManager, Context context) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
new file mode 100644
index 0000000..f8223f6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.IActivityManager;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class StatusBarWindowControllerTest extends SysuiTestCase {
+
+    @Mock
+    private WindowManager mWindowManager;
+    @Mock
+    private DozeParameters mDozeParameters;
+    @Mock
+    private View mStatusBarView;
+    @Mock
+    private IActivityManager mActivityManager;
+
+    private StatusBarWindowController mStatusBarWindowController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mDozeParameters.getAlwaysOn()).thenReturn(true);
+
+        mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
+                mActivityManager, mDozeParameters);
+        mStatusBarWindowController.add(mStatusBarView, 100 /* height */);
+    }
+
+    @Test
+    public void testSetDozing_hidesSystemOverlays() {
+        mStatusBarWindowController.setDozing(true);
+        ArgumentCaptor<WindowManager.LayoutParams> captor =
+                ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+        verify(mWindowManager).updateViewLayout(any(), captor.capture());
+        int flag = captor.getValue().privateFlags
+                & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        assertThat(flag).isNotEqualTo(0);
+
+        reset(mWindowManager);
+        mStatusBarWindowController.setDozing(false);
+        verify(mWindowManager).updateViewLayout(any(), captor.capture());
+        flag = captor.getValue().privateFlags
+                & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        assertThat(flag).isEqualTo(0);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index a068a5e..445a194 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -20,20 +20,17 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.content.Context;
 import android.os.SystemClock;
-import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.MotionEvent;
-import android.view.View;
 
+import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.DragDownHelper;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -49,6 +46,7 @@
 
     @Before
     public void setUp() {
+        mDependency.injectMockDependency(StatusBarStateController.class);
         mView = new StatusBarWindowView(getContext(), null);
         mStatusBar = mock(StatusBar.class);
         mView.setService(mStatusBar);
@@ -58,7 +56,8 @@
 
     @Test
     public void testDragDownHelperCalledWhenDraggingDown() throws Exception {
-        when(mStatusBar.getBarState()).thenReturn(StatusBarState.SHADE);
+        when(Dependency.get(StatusBarStateController.class).getState())
+                .thenReturn(StatusBarState.SHADE);
         when(mDragDownHelper.isDraggingDown()).thenReturn(true);
         long now = SystemClock.elapsedRealtime();
         MotionEvent ev = MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 0 /* x */, 0 /* y */,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
new file mode 100644
index 0000000..1ee7094
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
@@ -0,0 +1,126 @@
+package com.android.systemui.statusbar.policy;
+
+
+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;
+import static org.junit.Assert.fail;
+
+import android.media.MediaRouter;
+import android.media.projection.MediaProjectionInfo;
+import android.media.projection.MediaProjectionManager;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.CastController.Callback;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.junit.Test;
+
+import java.util.ConcurrentModificationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class CastControllerImplTest extends SysuiTestCase {
+
+    @Mock
+    MediaRouter mMediaRouter;
+    @Mock
+    MediaProjectionManager mMediaProjectionManager;
+    @Mock
+    MediaProjectionInfo mProjection;
+
+    private CastControllerImpl mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext.addMockSystemService(MediaRouter.class, mMediaRouter);
+        mContext.addMockSystemService(MediaProjectionManager.class, mMediaProjectionManager);
+        when(mMediaProjectionManager.getActiveProjectionInfo()).thenReturn(mProjection);
+
+        mController = new CastControllerImpl(mContext);
+    }
+
+    @Test
+    public void testAddCallback() {
+        Callback mockCallback = mock(Callback.class);
+
+        mController.addCallback(mockCallback);
+        verify(mockCallback, times(1)).onCastDevicesChanged();
+    }
+
+    @Test
+    public void testRemoveCallback() {
+        Callback mockCallback = mock(Callback.class);
+
+        mController.addCallback(mockCallback);
+        verify(mockCallback, times(1)).onCastDevicesChanged();
+
+        mController.removeCallback(mockCallback);
+        verify(mockCallback, times(1)).onCastDevicesChanged();
+    }
+
+    @Test
+    public void testRemoveCallbackFromEmptyList() {
+        Callback mockCallback = mock(Callback.class);
+
+        mController.removeCallback(mockCallback);
+        verify(mockCallback, never()).onCastDevicesChanged();
+    }
+
+    @Test
+    public void testAddCallbackRemoveCallback_concurrently() throws InterruptedException {
+        int callbackCount = 20;
+        int numThreads = 2 * callbackCount;
+        CountDownLatch startThreadsLatch = new CountDownLatch(1);
+        CountDownLatch threadsDone = new CountDownLatch(numThreads);
+        Callback[] callbackList = new Callback[callbackCount];
+        mController.setDiscovering(true);
+        AtomicBoolean error = new AtomicBoolean(false);
+        for (int cbIndex = 0; cbIndex < callbackCount; cbIndex++) {
+            callbackList[cbIndex] = mock(Callback.class);
+        }
+        for (int i = 0; i < numThreads; i++) {
+            final Callback mCallback = callbackList[i / 2];
+            final boolean shouldAdd = (i % 2 == 0);
+            new Thread() {
+                public void run() {
+                    try {
+                        startThreadsLatch.await(10, TimeUnit.SECONDS);
+                    } catch (InterruptedException e) {
+                        throw new RuntimeException(e);
+                    }
+                    try {
+                        if (shouldAdd) {
+                            mController.addCallback(mCallback);
+                        } else {
+                            mController.removeCallback(mCallback);
+                        }
+                        mController.fireOnCastDevicesChanged();
+                    } catch (ConcurrentModificationException exc) {
+                        error.compareAndSet(false, true);
+                    } finally {
+                        threadsDone.countDown();
+                    }
+                }
+            }.start();
+        }
+        startThreadsLatch.countDown();
+        threadsDone.await(10, TimeUnit.SECONDS);
+        if (error.get()) {
+            fail("Concurrent modification exception");
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
index e1b97bda..a0fb330 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
@@ -36,7 +36,6 @@
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
-@Ignore
 public class LocationControllerImplTest extends SysuiTestCase {
 
     private LocationControllerImpl mLocationController;
@@ -48,6 +47,7 @@
     }
 
     @Test
+    @Ignore("flaky")
     public void testRemoveSelfActive_DoesNotCrash() {
         LocationController.LocationChangeCallback callback = new LocationChangeCallback() {
             @Override
@@ -69,6 +69,7 @@
     }
 
     @Test
+    @Ignore("flaky")
     public void testRemoveSelfSettings_DoesNotCrash() {
         LocationController.LocationChangeCallback callback = new LocationChangeCallback() {
             @Override
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 dff0665..6e3d906 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
@@ -87,15 +87,15 @@
                 WifiIcons.QS_WIFI_SIGNAL_STRENGTH[1][testLevel], testSsid);
 
         // Set to different activity state first to ensure a callback happens.
-        setWifiActivity(WifiManager.DATA_ACTIVITY_IN);
+        setWifiActivity(WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN);
 
-        setWifiActivity(WifiManager.DATA_ACTIVITY_NONE);
+        setWifiActivity(WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE);
         verifyLastQsDataDirection(false, false);
-        setWifiActivity(WifiManager.DATA_ACTIVITY_IN);
+        setWifiActivity(WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN);
         verifyLastQsDataDirection(true, false);
-        setWifiActivity(WifiManager.DATA_ACTIVITY_OUT);
+        setWifiActivity(WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT);
         verifyLastQsDataDirection(false, true);
-        setWifiActivity(WifiManager.DATA_ACTIVITY_INOUT);
+        setWifiActivity(WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT);
         verifyLastQsDataDirection(true, true);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index a6fa4f5..3164c04 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -32,7 +32,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationTestHelper;
 import com.android.systemui.statusbar.RemoteInputController;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index c573ca8..01e6307 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -44,7 +44,7 @@
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 
@@ -375,7 +375,7 @@
         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
                 new Intent(TEST_ACTION), 0);
         RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).setChoices(choices).build();
-        mView.setRepliesFromRemoteInput(input, pendingIntent, mLogger, mEntry, mContainer);
+        mView.setRepliesFromRemoteInput(input, pendingIntent, mLogger, mEntry, mContainer, choices);
     }
 
     /** Builds a {@link ViewGroup} whose measures and layout mirror a {@link SmartReplyView}. */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
deleted file mode 100644
index cfacf0b..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.NotificationHeaderView;
-import android.view.View;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationTestHelper;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-public class NotificationChildrenContainerTest extends SysuiTestCase {
-
-    private ExpandableNotificationRow mGroup;
-    private int mId;
-    private NotificationTestHelper mNotificationTestHelper;
-    private NotificationChildrenContainer mChildrenContainer;
-
-    @Before
-    public void setUp() throws Exception {
-        mNotificationTestHelper = new NotificationTestHelper(mContext);
-        mGroup = mNotificationTestHelper.createGroup();
-        mChildrenContainer = mGroup.getChildrenContainer();
-    }
-
-    @Test
-    public void testGetMaxAllowedVisibleChildren_ambient() {
-        mGroup.setShowAmbient(true);
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
-            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_AMBIENT);
-    }
-
-    @Test
-    public void testGetMaxAllowedVisibleChildren_lowPriority() {
-        mChildrenContainer.setIsLowPriority(true);
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
-            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
-    }
-
-    @Test
-    public void testGetMaxAllowedVisibleChildren_headsUp() {
-        mGroup.setHeadsUp(true);
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
-                NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
-    }
-
-    @Test
-    public void testGetMaxAllowedVisibleChildren_lowPriority_expandedChildren() {
-        mChildrenContainer.setIsLowPriority(true);
-        mChildrenContainer.setChildrenExpanded(true);
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
-            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
-    }
-
-    @Test
-    public void testGetMaxAllowedVisibleChildren_lowPriority_userLocked() {
-        mChildrenContainer.setIsLowPriority(true);
-        mChildrenContainer.setUserLocked(true);
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
-            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
-    }
-
-    @Test
-    public void testGetMaxAllowedVisibleChildren_likeCollapsed() {
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(true),
-            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
-    }
-
-
-    @Test
-    public void testGetMaxAllowedVisibleChildren_expandedChildren() {
-        mChildrenContainer.setChildrenExpanded(true);
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
-                NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
-    }
-
-    @Test
-    public void testGetMaxAllowedVisibleChildren_userLocked() {
-        mGroup.setUserLocked(true);
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
-                NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
-    }
-
-    @Test
-    public void testShowingAsLowPriority_lowPriority() {
-        mChildrenContainer.setIsLowPriority(true);
-        Assert.assertTrue(mChildrenContainer.showingAsLowPriority());
-    }
-
-    @Test
-    public void testShowingAsLowPriority_notLowPriority() {
-        Assert.assertFalse(mChildrenContainer.showingAsLowPriority());
-    }
-
-    @Test
-    public void testShowingAsLowPriority_lowPriority_expanded() {
-        mChildrenContainer.setIsLowPriority(true);
-        mGroup.setExpandable(true);
-        mGroup.setUserExpanded(true, false);
-        Assert.assertFalse(mChildrenContainer.showingAsLowPriority());
-    }
-
-    @Test
-    public void testGetMaxAllowedVisibleChildren_userLocked_expandedChildren_lowPriority() {
-        mGroup.setUserLocked(true);
-        mGroup.setExpandable(true);
-        mGroup.setUserExpanded(true);
-        mChildrenContainer.setIsLowPriority(true);
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
-                NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
-    }
-
-    @Test
-    public void testLowPriorityHeaderCleared() {
-        mGroup.setIsLowPriority(true);
-        NotificationHeaderView lowPriorityHeaderView = mChildrenContainer.getLowPriorityHeaderView();
-        Assert.assertTrue(lowPriorityHeaderView.getVisibility() == View.VISIBLE);
-        Assert.assertTrue(lowPriorityHeaderView.getParent() == mChildrenContainer);
-        mGroup.setIsLowPriority(false);
-        Assert.assertTrue(lowPriorityHeaderView.getParent() == null);
-        Assert.assertTrue(mChildrenContainer.getLowPriorityHeaderView() == null);
-    }
-
-    @Test
-    public void testRecreateNotificationHeader_hasHeader() {
-        mChildrenContainer.recreateNotificationHeader(null);
-        Assert.assertNotNull("Children container must have a header after recreation",
-                mChildrenContainer.getCurrentHeaderView());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationRoundnessManagerTest.java
deleted file mode 100644
index 16e69f4..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationRoundnessManagerTest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.View;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationTestHelper;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.HashSet;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-public class NotificationRoundnessManagerTest extends SysuiTestCase {
-
-    private NotificationRoundnessManager mRoundnessManager = new NotificationRoundnessManager();
-    private HashSet<View> mAnimatedChildren = new HashSet<>();
-    private Runnable mRoundnessCallback = mock(Runnable.class);
-    private ExpandableNotificationRow mFirst;
-    private ExpandableNotificationRow mSecond;
-
-    @Before
-    public void setUp() throws Exception {
-        NotificationTestHelper testHelper = new NotificationTestHelper(getContext());
-        mFirst = testHelper.createRow();
-        mFirst.setHeadsUpAnimatingAwayListener(animatingAway
-                -> mRoundnessManager.onHeadsupAnimatingAwayChanged(mFirst, animatingAway));
-        mSecond = testHelper.createRow();
-        mSecond.setHeadsUpAnimatingAwayListener(animatingAway
-                -> mRoundnessManager.onHeadsupAnimatingAwayChanged(mSecond, animatingAway));
-        mRoundnessManager.setOnRoundingChangedCallback(mRoundnessCallback);
-        mRoundnessManager.setAnimatedChildren(mAnimatedChildren);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, mFirst);
-        mRoundnessManager.setExpanded(1.0f, 1.0f);
-    }
-
-    @Test
-    public void testCallbackCalledWhenSecondChanged() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, mSecond);
-        verify(mRoundnessCallback, atLeast(1)).run();
-    }
-
-    @Test
-    public void testCallbackCalledWhenFirstChanged() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mFirst);
-        verify(mRoundnessCallback, atLeast(1)).run();
-    }
-
-    @Test
-    public void testRoundnessSetOnLast() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, mSecond);
-        Assert.assertEquals(1.0f, mSecond.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mSecond.getCurrentTopRoundness(), 0.0f);
-    }
-
-    @Test
-    public void testRoundnessSetOnNew() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, null);
-        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-
-    @Test
-    public void testCompleteReplacement() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
-        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-
-    @Test
-    public void testNotCalledWhenRemoved() {
-        mFirst.setRemoved();
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
-        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-
-    @Test
-    public void testRoundedWhenPinnedAndCollapsed() {
-        mFirst.setPinned(true);
-        mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
-        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-
-    @Test
-    public void testRoundedWhenGoingAwayAndCollapsed() {
-        mFirst.setHeadsUpAnimatingAway(true);
-        mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
-        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-
-    @Test
-    public void testRoundedNormalRoundingWhenExpanded() {
-        mFirst.setHeadsUpAnimatingAway(true);
-        mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.0f /* appearFraction */);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
-        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-
-    @Test
-    public void testTrackingHeadsUpRoundedIfPushingUp() {
-        mRoundnessManager.setExpanded(1.0f /* expandedHeight */, -0.5f /* appearFraction */);
-        mRoundnessManager.setTrackingHeadsUp(mFirst);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
-        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-
-    @Test
-    public void testTrackingHeadsUpNotRoundedIfPushingDown() {
-        mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.5f /* appearFraction */);
-        mRoundnessManager.setTrackingHeadsUp(mFirst);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
-        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-
-    @Test
-    public void testRoundingUpdatedWhenAnimatingAwayTrue() {
-        mRoundnessManager.setExpanded(0.0f, 0.0f);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
-        mFirst.setHeadsUpAnimatingAway(true);
-        Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-
-
-    @Test
-    public void testRoundingUpdatedWhenAnimatingAwayFalse() {
-        mRoundnessManager.setExpanded(0.0f, 0.0f);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
-        mFirst.setHeadsUpAnimatingAway(true);
-        mFirst.setHeadsUpAnimatingAway(false);
-        Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
-        Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
deleted file mode 100644
index 5400e3b..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.stack;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.systemui.ExpandHelper;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.EmptyShadeView;
-import com.android.systemui.statusbar.FooterView;
-import com.android.systemui.statusbar.NotificationBlockingHelperManager;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.StatusBar;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-/**
- * Tests for {@link NotificationStackScrollLayout}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class NotificationStackScrollLayoutTest extends SysuiTestCase {
-
-    private NotificationStackScrollLayout mStackScroller;
-
-    @Rule public MockitoRule mockito = MockitoJUnit.rule();
-    @Mock private StatusBar mBar;
-    @Mock private HeadsUpManagerPhone mHeadsUpManager;
-    @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
-    @Mock private NotificationGroupManager mGroupManager;
-    @Mock private ExpandHelper mExpandHelper;
-    @Mock private EmptyShadeView mEmptyShadeView;
-
-    @Before
-    @UiThreadTest
-    public void setUp() throws Exception {
-        // Inject dependencies before initializing the layout
-        mDependency.injectTestDependency(
-                NotificationBlockingHelperManager.class,
-                mBlockingHelperManager);
-
-        NotificationShelf notificationShelf = spy(new NotificationShelf(getContext(), null));
-        mStackScroller = new NotificationStackScrollLayout(getContext());
-        mStackScroller.setShelf(notificationShelf);
-        mStackScroller.setStatusBar(mBar);
-        mStackScroller.setScrimController(mock(ScrimController.class));
-        mStackScroller.setHeadsUpManager(mHeadsUpManager);
-        mStackScroller.setGroupManager(mGroupManager);
-        mStackScroller.setEmptyShadeView(mEmptyShadeView);
-
-        // Stub out functionality that isn't necessary to test.
-        doNothing().when(mBar)
-                .executeRunnableDismissingKeyguard(any(Runnable.class),
-                        any(Runnable.class),
-                        anyBoolean(),
-                        anyBoolean(),
-                        anyBoolean());
-        doNothing().when(mGroupManager).collapseAllGroups();
-        doNothing().when(mExpandHelper).cancelImmediately();
-        doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean());
-        doNothing().when(notificationShelf).fadeInTranslating();
-    }
-
-    @Test
-    public void testNotDimmedOnKeyguard() {
-        when(mBar.getBarState()).thenReturn(StatusBarState.SHADE);
-        mStackScroller.setDimmed(true /* dimmed */, false /* animate */);
-        mStackScroller.setDimmed(true /* dimmed */, true /* animate */);
-        Assert.assertFalse(mStackScroller.isDimmed());
-    }
-
-    @Test
-    public void testAntiBurnInOffset() {
-        final int burnInOffset = 30;
-        mStackScroller.setAntiBurnInOffsetX(burnInOffset);
-        mStackScroller.setDark(false /* dark */, false /* animated */, null /* touch */);
-        Assert.assertEquals(0 /* expected */, mStackScroller.getTranslationX(), 0.01 /* delta */);
-        mStackScroller.setDark(true /* dark */, false /* animated */, null /* touch */);
-        Assert.assertEquals(burnInOffset /* expected */, mStackScroller.getTranslationX(),
-                0.01 /* delta */);
-    }
-
-    @Test
-    public void updateEmptyView_dndSuppressing() {
-        when(mEmptyShadeView.willBeGone()).thenReturn(true);
-        when(mBar.areNotificationsHidden()).thenReturn(true);
-
-        mStackScroller.updateEmptyShadeView(true);
-
-        verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
-    }
-
-    @Test
-    public void updateEmptyView_dndNotSuppressing() {
-        mStackScroller.setEmptyShadeView(mEmptyShadeView);
-        when(mEmptyShadeView.willBeGone()).thenReturn(true);
-        when(mBar.areNotificationsHidden()).thenReturn(false);
-
-        mStackScroller.updateEmptyShadeView(true);
-
-        verify(mEmptyShadeView).setText(R.string.empty_shade_text);
-    }
-
-    @Test
-    public void updateEmptyView_noNotificationsToDndSuppressing() {
-        mStackScroller.setEmptyShadeView(mEmptyShadeView);
-        when(mEmptyShadeView.willBeGone()).thenReturn(true);
-        when(mBar.areNotificationsHidden()).thenReturn(false);
-        mStackScroller.updateEmptyShadeView(true);
-        verify(mEmptyShadeView).setText(R.string.empty_shade_text);
-
-        when(mBar.areNotificationsHidden()).thenReturn(true);
-        mStackScroller.updateEmptyShadeView(true);
-        verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
-    }
-
-    @Test
-    @UiThreadTest
-    public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() {
-        mStackScroller.setExpandedHeight(0f);
-        verify(mBlockingHelperManager).setNotificationShadeExpanded(0f);
-        reset(mBlockingHelperManager);
-
-        mStackScroller.setExpandedHeight(100f);
-        verify(mBlockingHelperManager).setNotificationShadeExpanded(100f);
-    }
-
-    @Test
-    public void manageNotifications_visible() {
-        FooterView view = mock(FooterView.class);
-        mStackScroller.setFooterView(view);
-        when(view.willBeGone()).thenReturn(true);
-
-        mStackScroller.updateFooterView(true, false);
-
-        verify(view).setVisible(eq(true), anyBoolean());
-        verify(view).setSecondaryVisible(eq(false), anyBoolean());
-    }
-
-    @Test
-    public void clearAll_visible() {
-        FooterView view = mock(FooterView.class);
-        mStackScroller.setFooterView(view);
-        when(view.willBeGone()).thenReturn(true);
-
-        mStackScroller.updateFooterView(true, true);
-
-        verify(view).setVisible(eq(true), anyBoolean());
-        verify(view).setSecondaryVisible(eq(true), anyBoolean());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
index 9ef30c3..5ddf7a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
@@ -23,4 +23,8 @@
     public FakeConfigurationController(LeakCheckedTest.SysuiLeakCheck sysuiLeakCheck) {
         super(sysuiLeakCheck, "config");
     }
+
+    @Override
+    public void notifyThemeChanged() {
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
index 3f952c3..51b86c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -72,6 +72,11 @@
     }
 
     @Override
+    public long calculateGoingToFullShadeDelay() {
+        return 0;
+    }
+
+    @Override
     public boolean canSkipBouncer() {
         return false;
     }
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 43d60e4..c536dca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -56,10 +56,10 @@
 
 import java.util.function.Predicate;
 
-@Ignore
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
+@Ignore
 public class VolumeDialogImplTest extends SysuiTestCase {
 
     VolumeDialogImpl mDialog;
diff --git a/packages/VpnDialogs/res/values-fr/strings.xml b/packages/VpnDialogs/res/values-fr/strings.xml
index 2b3eace..7180119 100644
--- a/packages/VpnDialogs/res/values-fr/strings.xml
+++ b/packages/VpnDialogs/res/values-fr/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="3183836924226407828">"Demande de connexion"</string>
-    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> souhaite configurer une connexion VPN qui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; s\'affiche en haut de votre écran lorsqu\'une connexion VPN est active."</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> souhaite configurer une connexion VPN qui lui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; s\'affiche en haut de votre écran lorsqu\'une connexion VPN est active."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN connecté"</string>
     <string name="session" msgid="6470628549473641030">"Session :"</string>
     <string name="duration" msgid="3584782459928719435">"Durée :"</string>
diff --git a/packages/VpnDialogs/res/values-ru/strings.xml b/packages/VpnDialogs/res/values-ru/strings.xml
index 3b9b4b55..0543937 100644
--- a/packages/VpnDialogs/res/values-ru/strings.xml
+++ b/packages/VpnDialogs/res/values-ru/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="3183836924226407828">"Запрос на подключение"</string>
-    <string name="warning" msgid="809658604548412033">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" пытается подключиться к сети VPN, чтобы отслеживать трафик. Этот запрос следует принимать, только если вы доверяете источнику.<br/><br/>Когда подключение к сети VPN активно, в верхней части экрана появляется значок &lt;img src=vpn_icon /&gt;."</string>
+    <string name="warning" msgid="809658604548412033">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" пытается подключиться к сети VPN, чтобы отслеживать трафик. Этот запрос следует принимать, только если вы доверяете источнику. <br/><br/>Когда подключение к сети VPN активно, в верхней части экрана появляется значок &lt;img src=vpn_icon /&gt;."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN-подключение установлено"</string>
     <string name="session" msgid="6470628549473641030">"Сеанс:"</string>
     <string name="duration" msgid="3584782459928719435">"Продолжительность:"</string>
diff --git a/packages/VpnDialogs/res/values-ta/strings.xml b/packages/VpnDialogs/res/values-ta/strings.xml
index ffaf93ae..3b4cc57 100644
--- a/packages/VpnDialogs/res/values-ta/strings.xml
+++ b/packages/VpnDialogs/res/values-ta/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="3183836924226407828">"இணைப்புக் கோரிக்கை"</string>
-    <string name="warning" msgid="809658604548412033">"VPN இணைப்பை அமைக்க <xliff:g id="APP">%s</xliff:g> விழைகிறது. அதன்மூலம் இது நெட்வொர்க் டிராஃபிக்கைக் கண்காணிக்கும் அனுமதியைப் பெறும். நம்பகமான மூலத்தை மட்டுமே ஏற்கவும். &lt;br /&gt; &lt;br /&gt; VPN இயக்கத்தில் உள்ளபோது திரையில் மேல் பகுதியில் &lt;img src=vpn_icon /&gt; தோன்றும்."</string>
+    <string name="warning" msgid="809658604548412033">"நெட்வொர்க் டிராஃபிக்கைக் கண்காணிக்க வசதியாக VPN இணைப்பை அமைக்க <xliff:g id="APP">%s</xliff:g> கோருகிறது. நம்பகமான மூலத்தை மட்டுமே ஏற்கவும். &lt;br /&gt; &lt;br /&gt; VPN இயக்கத்தில் உள்ளபோது திரையின் மேல் பகுதியில் &lt;img src=vpn_icon /&gt; தோன்றும்."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN இணைக்கப்பட்டது"</string>
     <string name="session" msgid="6470628549473641030">"அமர்வு:"</string>
     <string name="duration" msgid="3584782459928719435">"காலஅளவு:"</string>
diff --git a/packages/VpnDialogs/res/values-th/strings.xml b/packages/VpnDialogs/res/values-th/strings.xml
index f6dfca5..333ff5f 100644
--- a/packages/VpnDialogs/res/values-th/strings.xml
+++ b/packages/VpnDialogs/res/values-th/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="3183836924226407828">"ขอการเชื่อมต่อ"</string>
-    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ต้องการติดตั้งการเชื่อมต่อ VPN เพื่อให้แอปสามารถตรวจสอบการเข้าใช้งานเครือข่าย โปรดยอมรับหากคุณเชื่อถือแหล่งที่มานี้เท่านั้น &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; จะปรากฏที่ด้านบนหน้าจอเมื่อมีการใช้งาน VPN อยู่"</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ต้องการสร้างการเชื่อมต่อ VPN เพื่อให้แอปสามารถตรวจสอบการเข้าใช้งานเครือข่าย โปรดยอมรับหากคุณเชื่อถือแหล่งที่มานี้เท่านั้น &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; จะปรากฏที่ด้านบนหน้าจอเมื่อมีการใช้งาน VPN อยู่"</string>
     <string name="legacy_title" msgid="192936250066580964">"เชื่อมต่อ VPN แล้ว"</string>
     <string name="session" msgid="6470628549473641030">"เซสชัน"</string>
     <string name="duration" msgid="3584782459928719435">"ระยะเวลา:"</string>
diff --git a/packages/WAPPushManager/AndroidManifest.xml b/packages/WAPPushManager/AndroidManifest.xml
index 89e9d6a..14e6e91 100644
--- a/packages/WAPPushManager/AndroidManifest.xml
+++ b/packages/WAPPushManager/AndroidManifest.xml
@@ -24,7 +24,8 @@
         android:protectionLevel="signatureOrSystem" />
 
     <original-package android:name="com.android.smspush" />
-    <application>
+    <application
+        android:allowClearUserData="false">
         <service android:name=".WapPushManager"
             android:permission="com.android.smspush.WAPPUSH_MANAGER_BIND"
             android:exported="true">
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-af/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-af/strings.xml
index 3eca94e..9811133 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-af/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-af/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Hoekskermuitsnede"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Hoekuitsnede"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-am/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-am/strings.xml
index b6c4de1..2626195 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-am/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-am/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"የማዕዘን ማሳያ ቅርጽ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"የማዕዘን ቅርጽ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ar/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ar/strings.xml
index 9517eb2..c01732d 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ar/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ar/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"صورة مقطوعة لشاشة جانبية"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"صورة مقطوعة جانبية"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-as/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-as/strings.xml
index 1ba9d7a0..361aa39 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-as/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-as/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"কৌণিক ডিছপ্লে কাটআউট"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"কৌণিক কাটআউট"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-az/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-az/strings.xml
index abb4247..4b089a4 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-az/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-az/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Künc ekran kəsimi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Künc kəsimi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-b+sr+Latn/strings.xml
index 41dfd3a..5393410 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-b+sr+Latn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-b+sr+Latn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Izrezana slika u uglu ekrana"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Izrezana slika u uglu ekrana"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-be/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-be/strings.xml
index edd9e65..26c0b18 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-be/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-be/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Зрабіць выраз у кутку экрана"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Выраз у кутку"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bg/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bg/strings.xml
index 681a9b9..849bf57 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bg/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bg/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Ъглов прорез на екрана"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Ъглов прорез"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bn/strings.xml
deleted file mode 100644
index 194949d..0000000
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bn/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"কর্নার ডিসপ্লে কাট-আউট"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bs/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bs/strings.xml
index e79efe6..9ff0218a 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-bs/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Urez ekrana u uglu"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Urez u uglu"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ca/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ca/strings.xml
index 627ef24..3432502 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ca/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ca/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Retall de l\'extrem de la pantalla"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Retall de l\'extrem"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-cs/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-cs/strings.xml
index fd43995..7edff6f 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-cs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-cs/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Rohový výřez displeje"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Rohový výřez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-da/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-da/strings.xml
index ec27419..31b537c 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-da/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-da/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Udskæring i hjørnet af skærmen"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Hak i hjørnet"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-de/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-de/strings.xml
index da7c237..2e142ef 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-de/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-de/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Display-Ausschnitt in der Ecke"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Aussparung in der Ecke"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-el/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-el/strings.xml
index 460a8b6..0cf91dd 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-el/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-el/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Διακοπή γωνιακής οθόνης"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Γωνιακή εγκοπή"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rAU/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rAU/strings.xml
index 1058832..6923006 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rAU/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rAU/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Corner display cut out"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Corner cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rCA/strings.xml
index 1058832..6923006 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rCA/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Corner display cut out"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Corner cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rGB/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rGB/strings.xml
index 1058832..6923006 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rGB/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rGB/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Corner display cut out"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Corner cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rIN/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rIN/strings.xml
index 1058832..6923006 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rIN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rIN/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Corner display cut out"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Corner cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rXC/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rXC/strings.xml
index bdd497a..1edef0b 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rXC/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-en-rXC/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎Corner display cutout‎‏‎‎‏‎"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎Corner cutout‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-es-rUS/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-es-rUS/strings.xml
index a4d8e64..6d41bc0 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-es-rUS/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-es-rUS/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Recorte de la esquina de la pantalla"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Corte de la esquina"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-es/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-es/strings.xml
index a4d8e64..d6d3a1e 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-es/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-es/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Recorte de la esquina de la pantalla"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Recorte de la esquina"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-et/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-et/strings.xml
index 1dec970..6626787 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-et/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-et/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Ekraani nurga väljalõige"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Nurga väljalõige"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-eu/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-eu/strings.xml
index a82e8ea..fd2f646 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-eu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-eu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Pantailaren izkinako mozketa"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Izkinako mozketa"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fa/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fa/strings.xml
index bfbaa5c..0d33978 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fa/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"نمایشگر با گوشه‌های بریده"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"نمایشگر با لبه بریده"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fi/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fi/strings.xml
index 4803b54..2acb982 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fi/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Aukko näytön kulmassa"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Nurkkalovi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fr-rCA/strings.xml
index 4110d51..ecf4e93 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fr-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fr-rCA/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Découpe d\'écran en coin"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Encoche de coin"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fr/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fr/strings.xml
index ff341a2..05c5c2b 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-fr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Encoche d\'angle pour écran"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Encoche d\'angle"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-gl/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-gl/strings.xml
index 7838d69..ae77dbd 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-gl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-gl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Recorte de pantalla na esquina"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Recorte na esquina"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-gu/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-gu/strings.xml
index 0680f7f..3c8c4e6 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-gu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-gu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"ખૂણાનું ડિસ્પ્લે કટઆઉટ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"કોર્નર કટઆઉટ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hi/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hi/strings.xml
deleted file mode 100644
index 01b8d69..0000000
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hi/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"कॉर्नर डिसप्ले कटआउट"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hr/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hr/strings.xml
index f8b2f79..e783abe 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Obrezana slika za kut zaslona"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Obrezana slika"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hu/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hu/strings.xml
index 7658edc..099267d 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Sarokban található képernyőkivágás"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Sarokkivágás"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hy/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hy/strings.xml
index 656ae24..7eb8803 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hy/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-hy/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Էկրանի անկյունի կտրվածք"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Անկյունի կտրվածք"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-in/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-in/strings.xml
index 78247f6..0dc0bfb 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-in/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-in/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Potongan tampilan sudut"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Potongan sudut"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-is/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-is/strings.xml
index 755360f..56ba1b9 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-is/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-is/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Hornskjáskurður"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Hornskurður"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-it/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-it/strings.xml
index 3eadd5f..b282437 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-it/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-it/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Ritaglio display angolo"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Ritaglio angolo"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-iw/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-iw/strings.xml
index bfb4797..1b46b50 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-iw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-iw/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"חיתוך פינות התצוגה"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"מגרעת בפינה"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ja/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ja/strings.xml
index fee2d70..4d8ee73 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ja/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ja/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"画面隅のディスプレイ カットアウト"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"画面隅のカットアウト"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ka/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ka/strings.xml
index 6cea242..a0b6aef 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ka/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ka/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"ეკრანის კუთხის ამოჭრა"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"კუთხის ამოჭრა"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-kk/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-kk/strings.xml
index a2a6948..0f4bc3a 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-kk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-kk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Экран бұрышындағы ойық"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Бұрышынан ойық жасау"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-km/strings.xml
index bbf23c6..feb66be 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-km/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"ស្នាម​ចោះ​ផ្ទាំង​អេក្រង់​នៅ​ជ្រុង"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"ស្នាមចោះ​នៅជ្រុង"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-kn/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-kn/strings.xml
index 7b9879a..50daf09 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-kn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-kn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"ಮೂಲೆಯ ಪ್ರದರ್ಶನ ಕಟೌಟ್"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"ಮೂಲೆಯ ಕಟೌಟ್"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ko/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ko/strings.xml
index 8fafcfa..e56d2d6 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ko/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ko/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"모서리 디스플레이 컷아웃"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"모서리 컷아웃"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ky/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ky/strings.xml
index 4d8c946..98499a1 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ky/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ky/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Бурчтагы дисплей кесиндиси"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Бурчтагы кесинди"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lo/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lo/strings.xml
index 257839d..833f20f 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lo/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lo/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"ແຜ່ນສະແດງມຸມ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"ຮອຍບາກມຸມ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lt/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lt/strings.xml
index e4b01ba..e257b8a 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lt/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Kampinė ekrano išpjova"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Kampinė išpjova"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lv/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lv/strings.xml
index 3087b63..a37d95c 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-lv/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Stūra ekrāna izgriezums"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Stūra izgriezums"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mk/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mk/strings.xml
index 2d0babf..9be5d7a 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Исечок на аголот на екранот"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Исечок на аголот"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ml/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ml/strings.xml
index 6adb3ec..a8baf40 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ml/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ml/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"കോർണർ ഡിസ്‌പ്ലേ കട്ടൗട്ട്"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"കോർണർ കട്ട്ഔട്ട്"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mn/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mn/strings.xml
index 7998f15..b49b481 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Булангийн дэлгэцийг таслах"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Булан гаргаж таслах"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mr/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mr/strings.xml
index a5d2133..435b664 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-mr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"कॉर्नर डिस्प्ले कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"कॉर्नर कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ms/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ms/strings.xml
index 9fccad6..94e2a23 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ms/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ms/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Potongan paparan penjuru"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Potongan penjuru"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-my/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-my/strings.xml
index c56ea8b..8228226 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-my/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-my/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"မျက်နှာပြင်ထောင့် ဖြတ်ညှပ်ပြသမှု"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"ထောင့် ဖြတ်ညှပ်ပြသမှု"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-nb/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-nb/strings.xml
index 731668f..1d61bf2 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-nb/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-nb/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Hjørneskjermutklipp"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Hjørneutklipp"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ne/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ne/strings.xml
index e024d2a..8765aeb 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ne/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ne/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"कुनाको प्रदर्शनसम्बन्धी कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"कुनाको कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-nl/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-nl/strings.xml
index 149041e..5c43d2e 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-nl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-nl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Hoekdisplay-cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Hoek-cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-or/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-or/strings.xml
index 620d36f..adaaaab 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-or/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-or/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"କର୍ନର୍ ଡିସ୍‌ପ୍ଲେ କଟଆଉଟ୍"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"କଣ ଫଳକ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pa/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pa/strings.xml
index 274e791..5b91ea9 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pa/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"ਕਿਨਾਰਿਆਂ ਤੱਕ ਜੁੜੀ ਡਿਸਪਲੇ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"ਕੋਨਾ ਕੱਟਆਊਟ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pl/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pl/strings.xml
index 6768407..ef2714c 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Wycięcie wyświetlacza z narożnikami"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Wycięcie narożne"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt-rBR/strings.xml
index ed7e2b5..2c800c2 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt-rBR/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt-rBR/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Corte de tela de canto"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Corte de canto"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt-rPT/strings.xml
index e4ed794..a03955f 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt-rPT/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt-rPT/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Ecrã com recorte nos cantos"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Recorte nos cantos"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt/strings.xml
index ed7e2b5..2c800c2 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-pt/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Corte de tela de canto"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Corte de canto"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ro/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ro/strings.xml
index eebfe6a..28db495 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ro/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ro/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Decupare ecran pe colț"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Decupajul colțului"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml
index fa8fefb..dc77981 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Сделать вырез в углу экрана"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Сделать вырез в углу"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-si/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-si/strings.xml
index ae833f2..bdecdf4 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-si/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-si/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"කොණ් තිර කට්අවුට්"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"කොණ් කට්අවුට්"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sk/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sk/strings.xml
index 5b40d71..f42bbe86 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Rohový výrez obrazovky"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Rohový výrez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sl/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sl/strings.xml
index 52c5aa1..867700c 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Kotni izrez prikaza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Kotna zareza"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sq/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sq/strings.xml
index cb39653..aa562e3 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sq/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sq/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Prerje e ekranit në qoshe"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Prerje këndore"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sr/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sr/strings.xml
index 4c5701a..0adf1dda 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Изрезана слика у углу екрана"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Изрезана слика у углу екрана"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sv/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sv/strings.xml
index ccc72fd..9e24a43 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sv/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Urklipp av skärmens hörn"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Kantutskärning"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sw/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sw/strings.xml
index 6066426..bf105c4 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-sw/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Mwonekano wenye pengo pembeni"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Mkato kwenye kona"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ta/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ta/strings.xml
index a0a30cf..4c57578 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ta/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ta/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"மூலை கட்அவுட் காட்சி"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"மூலை கட்அவுட்"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-te/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-te/strings.xml
deleted file mode 100644
index 6c10a13..0000000
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-te/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"మూల డిస్‌ప్లే కట్అవుట్‌"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-th/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-th/strings.xml
index 57f49d4..714abb6 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-th/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-th/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"คัตเอาท์ดิสเพลย์แบบมุม"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"คัตเอาท์แบบมุม"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-tl/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-tl/strings.xml
index 3d4552e..a325ca1 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-tl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-tl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Display cutout sa sulok"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Cutout sa sulok"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-tr/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-tr/strings.xml
index a065978..e781320 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-tr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-tr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Köşe ekran kesimi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Köşe kesimi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-uk/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-uk/strings.xml
index 0b6a774..324e154 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-uk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-uk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Відключення кутового дисплея"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Відрізання кутів"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ur/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ur/strings.xml
index 2aeecc6..e7c5152 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ur/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ur/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"کارنر ڈسپلے کٹ آؤٹ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"کارنر کٹ آؤٹ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-uz/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-uz/strings.xml
index 249ff2e..0d19b66 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-uz/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-uz/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Burchak ekran kesimi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Burchak kesimi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-vi/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-vi/strings.xml
index a217bf8..15a66e3 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-vi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-vi/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Cắt hiển thị ở góc"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Vết cắt ở góc"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rCN/strings.xml
index 4cb357b..2d437ae 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rCN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rCN/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"边角显示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"边角刘海屏"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rHK/strings.xml
index 5fcfbc3..997ebac 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rHK/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rHK/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"邊角顯示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"邊角凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rTW/strings.xml
index e6c75b5..997ebac 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rTW/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zh-rTW/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"邊角螢幕凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"邊角凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zu/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zu/strings.xml
index 961d036..4899087 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-zu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4967302169856689448">"Ukusikwa kwekhona lesiboniso"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Ukusikwa kwekhona"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml
index 80d8066..9254b4d 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml
@@ -37,6 +37,8 @@
         @right
     </string>
 
+    <string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation">@*android:string/config_mainBuiltInDisplayCutout</string>
+
     <!-- Whether the display cutout region of the main built-in display should be forced to
          black in software (to avoid aliasing or emulate a cutout that is not physically existent).
      -->
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml
index 754ba72..b08924b 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml
@@ -16,7 +16,7 @@
   -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Corner display cutout</string>
+    <string name="display_cutout_emulation_overlay">Corner cutout</string>
 
 </resources>
 
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-af/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-af/strings.xml
index af108e8..2815df2 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-af/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-af/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dubbelskermuitsnede"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dubbeluitsnede"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-am/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-am/strings.xml
index 8b03bde..f41eadc 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-am/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-am/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"የድርብ ማሳያ ቅርጽ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ድርብ ቅርጽ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ar/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ar/strings.xml
index 34065f8..106ce3d 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ar/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ar/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"صورة مقطوعة لشاشة مزدوجة"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"صورة مقطوعة مزدوجة"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-as/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-as/strings.xml
index 0b93c40..7a780d7 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-as/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-as/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"দ্বৈত ডিছপ্লে কাটআউট"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"দ্বৈত কাটআউট"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-az/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-az/strings.xml
index 732ebe5..612a849 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-az/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-az/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"İkiqat ekran kəsimi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"İkiqat kəsim"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-b+sr+Latn/strings.xml
index 089f20b..d2eb7db 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-b+sr+Latn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-b+sr+Latn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Izrezana slika za duple ekrane"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Izrezana slika za duple ekrane"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-be/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-be/strings.xml
index 1763bd4..1a398c82 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-be/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-be/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Павялічыць выраз на экране ўдвая"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Двайны выраз"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bg/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bg/strings.xml
index 8952d12..09b59756 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bg/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bg/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Двоен прорез на екрана"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Двоен прорез"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bn/strings.xml
deleted file mode 100644
index d1eee2f3..0000000
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bn/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ডবল ডিসপ্লে কাট-আউট"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bs/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bs/strings.xml
index 3c40f98..655db33 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-bs/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dvostruki urez ekrana"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dvostruki urez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ca/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ca/strings.xml
index 096a62d..10d5ae7 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ca/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ca/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Retall de pantalla doble"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Retall doble"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-cs/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-cs/strings.xml
index e979511..2f3aab9 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-cs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-cs/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dvojitý výřez displeje"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dvojitý výřez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-da/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-da/strings.xml
index 27dc82e..3f9bae1 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-da/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-da/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dobbelt udskæring på skærmen"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dobbelt hak"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-de/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-de/strings.xml
index c73fa2d..5fc9176 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-de/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-de/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Doppelter Display-Ausschnitt"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Doppelte Aussparung"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-el/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-el/strings.xml
index c744a45..f3cc093 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-el/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-el/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Διακοπή διπλής οθόνης"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Διπλή εγκοπή"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rAU/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rAU/strings.xml
index 648edfe..31f2a5a 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rAU/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rAU/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Double display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Double cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rCA/strings.xml
index 648edfe..31f2a5a 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rCA/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Double display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Double cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rGB/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rGB/strings.xml
index 648edfe..31f2a5a 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rGB/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rGB/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Double display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Double cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rIN/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rIN/strings.xml
index 648edfe..31f2a5a 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rIN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rIN/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Double display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Double cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rXC/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rXC/strings.xml
index 5d9e709..ea09dde 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rXC/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-en-rXC/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎Double display cutout‎‏‎‎‏‎"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎Double cutout‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-es-rUS/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-es-rUS/strings.xml
index 44cd9be..d57c2fc 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-es-rUS/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-es-rUS/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Recorte de pantalla doble"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Corte doble"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-es/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-es/strings.xml
index 44cd9be..e5d1bff 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-es/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-es/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Recorte de pantalla doble"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Recorte doble"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-et/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-et/strings.xml
index 9edaf8e..1e75a92 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-et/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-et/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Topeltekraani väljalõige"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Topeltväljalõige"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-eu/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-eu/strings.xml
index 18000bd..bd7f8d5 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-eu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-eu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Pantailaren mozketa bikoitza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Mozketa bikoitza"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fa/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fa/strings.xml
index d350822..0b38e68 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fa/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"نمایشگر با لبه دوتایی"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"نمایشگر با لبه بریده دوتایی"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fi/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fi/strings.xml
index 33766fd..5d85064 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fi/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Kaksoisaukko näytössä"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Kaksoislovi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fr-rCA/strings.xml
index 8fa31c4..2ee7917 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fr-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fr-rCA/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Découpe d\'affichage double"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Encoche double"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fr/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fr/strings.xml
index 9f55c9c..2ee7917 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-fr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Encoche pour écran double"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Encoche double"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-gl/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-gl/strings.xml
index 92832da..8d854c8 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-gl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-gl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Recorte de pantalla dobre"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Recorte dobre"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-gu/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-gu/strings.xml
index 43e67a0..b1ca50b 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-gu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-gu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ડબલ ડિસ્પ્લે કટઆઉટ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ડબલ કટઆઉટ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hi/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hi/strings.xml
deleted file mode 100644
index 8412c14..0000000
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hi/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"डबल डिसप्ले कटआउट"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hr/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hr/strings.xml
index 9d7a8ce..655db33 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Obrezana slika za dvostruke zaslone"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dvostruki urez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hu/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hu/strings.xml
index 0af2ad3..acf4f4d4b 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dupla képernyőkivágás"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dupla kivágás"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hy/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hy/strings.xml
index 7907d0a..9994cf9 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hy/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-hy/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Էկրանի կրկնակի կտրվածք"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Կրկնակի կտրվածք"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-in/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-in/strings.xml
index 45f5952..78343e8 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-in/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-in/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Potongan tampilan ganda"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Potongan ganda"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-is/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-is/strings.xml
index 9109489..fe2eefc 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-is/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-is/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Tvöfaldur skjáskurður"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Tvöfaldur skurður"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-it/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-it/strings.xml
index 4aa869e..a1126cc 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-it/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-it/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Ritaglio display doppio"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Ritaglio doppio"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-iw/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-iw/strings.xml
index eff8a8d..2e7aeb0 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-iw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-iw/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"חיתוך תצוגה כפול"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"מגרעת כפולה"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ja/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ja/strings.xml
index 5346e97..dadc8a8 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ja/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ja/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ダブル ディスプレイ カットアウト"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ダブル カットアウト"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ka/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ka/strings.xml
index 515ac25..4ec33c9 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ka/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ka/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ეკრანის ორმაგი ამოჭრა"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ორმაგი ამოჭრა"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-kk/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-kk/strings.xml
index c812d0c..6592e24 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-kk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-kk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Қос дисплейді өшіру"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Ойықты екі есе ұлғайту"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-km/strings.xml
index 0a52444..8a7fcec 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-km/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ស្នាមចោះ​ផ្ទាំង​អេក្រង់​ភ្លោះ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ស្នាមចោះ​ភ្លោះ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-kn/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-kn/strings.xml
index 02500db..e88e045 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-kn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-kn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ಡಬಲ್ ಡಿಸ್‌ಪ್ಲೇ ಕಟೌಟ್"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ಡಬಲ್ ಕಟೌಟ್"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ko/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ko/strings.xml
index 5505f57..fa114f0 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ko/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ko/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"더블 디스플레이 컷아웃"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"이중 컷아웃"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ky/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ky/strings.xml
index baf2f4d..3fc7446 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ky/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ky/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Кош дисплей кесиндиси"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Кош кесинди"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lo/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lo/strings.xml
index 5823a82..f65b1ef 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lo/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lo/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ກ່ອງຂໍ້ຄວາມສະແດງຜົນຄູ່"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ຮອຍບາກຄູ່"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lt/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lt/strings.xml
index 7c1ba7d..f47d060 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lt/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dviguba ekrano išpjova"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dviguba išpjova"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lv/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lv/strings.xml
index 5452e9c..a2810a3 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-lv/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Divkāršs ekrāna izgriezums"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Divkāršs izgriezums"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mk/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mk/strings.xml
index d232838..7b83881 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Двоен исечок на екранот"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Двоен исечок"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ml/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ml/strings.xml
index 9aff47d..21b5ec7 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ml/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ml/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ഇരട്ട ഡിസ്‌പ്ലേ കട്ടൗട്ട്"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ഇരട്ട കട്ട്ഔട്ട്"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mn/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mn/strings.xml
index c43f18a..be8e6a5 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Давхар дэлгэцийг таслах"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Давхар болгож таслах"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mr/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mr/strings.xml
index e2065ac..d574f6c 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-mr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"दुहेरी डिस्प्ले कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"डबल कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ms/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ms/strings.xml
index b3085ef..82197a3 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ms/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ms/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Potongan paparan berganda"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Potongan berganda"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-my/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-my/strings.xml
index 0744f12..2249d6e 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-my/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-my/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"မျက်နှာပြင် အထက်အောက် ဖြတ်ညှပ်ပြသမှု"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"နှစ်ဆင့် ဖြတ်ညှပ်ပြသမှု"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-nb/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-nb/strings.xml
index e4b6c76..b44b117 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-nb/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-nb/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dobbelt skjermutklipp"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dobbelt utklipp"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ne/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ne/strings.xml
index 49f82b9..91ebb8c 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ne/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ne/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"दोहोरो प्रदर्शनसम्बन्धी कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"दोहोरो कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-nl/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-nl/strings.xml
index d46f770..078829f 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-nl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-nl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dubbele display-cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dubbele cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-or/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-or/strings.xml
index 1a5d801..471c007 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-or/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-or/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ଡବଲ୍ ଡିସ୍‌ପ୍ଲେ କଟଆଉଟ୍"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ଯୋଡା ଫଳକ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pa/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pa/strings.xml
index da57fde..afd4eab 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pa/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ਡਿਸਪਲੇ ਦੀ ਦੋਹਰੀ ਵੰਡ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ਦੋਹਰਾ ਕੱਟਆਊਟ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pl/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pl/strings.xml
index fdc9a20..66c20f78 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Podwójne wycięcie wyświetlacza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Wycięcie podwójne"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt-rBR/strings.xml
index 8c05472..fbce009 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt-rBR/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt-rBR/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Corte de tela duplo"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Corte duplo"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt-rPT/strings.xml
index b9c30c6..585c31f 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt-rPT/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt-rPT/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Ecrã duplo com recorte"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Recorte duplo"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt/strings.xml
index 8c05472..fbce009 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-pt/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Corte de tela duplo"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Corte duplo"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ro/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ro/strings.xml
index a22afe6..04d85f0 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ro/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ro/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Decupare dublă pe ecran"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Decupaj dublu"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml
index 14dd606..a02eaf7 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Увеличить вырез на экране вдвое"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Увеличить вырез вдвое"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-si/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-si/strings.xml
index c15208f..274924b 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-si/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-si/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ද්විත්ව තිර කට්අවුට්"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ද්විත්ව කට්අවුට්"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sk/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sk/strings.xml
index 98a74c1..8d65427 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dvojitý výrez obrazovky"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dvojitý výrez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sl/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sl/strings.xml
index 4f12711..66de901 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Izrez dvojnega prikaza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dvojna zareza"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sq/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sq/strings.xml
index 96a68d5..73222ab 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sq/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sq/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Prerje e dyfishtë e ekranit"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Prerje e dyfishtë"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sr/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sr/strings.xml
index 8930813..99b89a2 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Изрезана слика за дупле екране"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Изрезана слика за дупле екране"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sv/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sv/strings.xml
index 42b7aed..aaa6971 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sv/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dubbelt urklipp av skärm"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dubbel utskärning"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sw/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sw/strings.xml
index a39f77d..486e946 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-sw/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Mwonekano wenye mapengo mawili"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Mikato miwili"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ta/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ta/strings.xml
index b3c19b6..e4f96f9 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ta/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ta/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"இரட்டை கட்அவுட் காட்சி"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"இரட்டை கட்அவுட்"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-te/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-te/strings.xml
deleted file mode 100644
index b8573db..0000000
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-te/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"డబుల్ డిస్‌ప్లే కట్అవుట్‌"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-th/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-th/strings.xml
index 8fdd693..0423e86 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-th/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-th/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"ตัดหน้าจอสองด้าน"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"คัตเอาท์แบบคู่"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-tl/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-tl/strings.xml
index e68b5ec..cd959da 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-tl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-tl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Dobleng display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Dobleng cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-tr/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-tr/strings.xml
index 3ae92f0..df91cc8 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-tr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-tr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Çift ekran kesimi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Çift kesim"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-uk/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-uk/strings.xml
index cf6df69..f551429 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-uk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-uk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Відключення подвійного дисплея"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Подвійне відрізання"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ur/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ur/strings.xml
index 3c9666d..f1e44e3 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ur/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ur/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"دوہرا ڈسپلے کٹ آؤٹ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"دوہرا کٹ آؤٹ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-uz/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-uz/strings.xml
index 9e74192..d585d7e 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-uz/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-uz/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Ekran kesimini ikki marta kattalashtirish"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Kesimni ikki marta kattalashtirish"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-vi/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-vi/strings.xml
index 442805a..96096c2 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-vi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-vi/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Cắt hiển thị kép"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Vết cắt kép"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rCN/strings.xml
index 06b1379..43de56f 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rCN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rCN/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"双显示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"双刘海屏"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rHK/strings.xml
index 6da1a7f..9d3371c 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rHK/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rHK/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"雙顯示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"雙凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rTW/strings.xml
index 72932b5..9d3371c 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rTW/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zh-rTW/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"雙螢幕凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"雙凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zu/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zu/strings.xml
index 2e0a5bd..31e57f0 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-zu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5659433562878674546">"Ukusikwa kokuboniswa okukabili"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Ukusika kabiliDouble cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
index ca261f9..80c997a 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
@@ -49,6 +49,8 @@
         @dp
     </string>
 
+    <string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation">@*android:string/config_mainBuiltInDisplayCutout</string>
+
     <!-- Whether the display cutout region of the main built-in display should be forced to
          black in software (to avoid aliasing or emulate a cutout that is not physically existent).
      -->
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
index 68c2dcb..0a106fa 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
@@ -16,7 +16,7 @@
   -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Double display cutout</string>
+    <string name="display_cutout_emulation_overlay">Double cutout</string>
 
 </resources>
 
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-af/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-af/strings.xml
index 98b4303..09316bc 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-af/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-af/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Uitsnede vir smal vertoonskerm"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Smal uitsnede"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-am/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-am/strings.xml
index 2fc0dbe..25cb2cf 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-am/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-am/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"የጠባብ ማሳያ ቅርጽ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ጠባብ ቅርጽ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ar/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ar/strings.xml
index aae2ada..3294bc8 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ar/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ar/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"صورة مقطوعة لشاشة ضيقة"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"صورة مقطوعة ضيقة"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-as/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-as/strings.xml
index 181bcbf..8e535df 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-as/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-as/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ঠেক ডিছপ্লে কাটআউট"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ঠেক কাটআউট"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-az/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-az/strings.xml
index f5b856b..7939aea 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-az/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-az/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Dar ekran profili"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Dar kəsim"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-b+sr+Latn/strings.xml
index 0a9aaaf..d78d344 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-b+sr+Latn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-b+sr+Latn/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Izrezana slika za uske ekrane"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Izrezana slika za uske ekrane"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-be/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-be/strings.xml
index 189f1ccd..d21b0f7 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-be/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-be/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Зрабіць выраз на экране больш вузкім"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Вузкі выраз"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bg/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bg/strings.xml
index d236710..61d90b4 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bg/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bg/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Тесен прорез на екрана"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Тесен прорез"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bn/strings.xml
deleted file mode 100644
index 301d686..0000000
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ন্যারো ডিসপ্লে কাট-আউট"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bs/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bs/strings.xml
index 8ceaac5..8fe6f2d 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-bs/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Uski urez ekrana"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Uski urez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ca/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ca/strings.xml
index ab9061e..106b75c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ca/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ca/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Retall de pantalla estret"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Retall estret"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-cs/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-cs/strings.xml
index 440a2f0..5e56a7b 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-cs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-cs/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Úzký výřez displeje"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Úzký výřez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-da/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-da/strings.xml
index 4372d56..6681a12 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-da/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-da/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Smal udskæring på skærmen"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Smalt hak"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-de/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-de/strings.xml
index a92a24a..3dd023a 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-de/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-de/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Schmaler Display-Ausschnitt"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Schmale Aussparung"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-el/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-el/strings.xml
index 69adde3..21fb5b7 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-el/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-el/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Διακοπή στενής οθόνης"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Στενή εγκοπή"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rAU/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rAU/strings.xml
index bf2624f..2716eae 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rAU/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rAU/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Narrow display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Narrow cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rCA/strings.xml
index bf2624f..2716eae 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rCA/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Narrow display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Narrow cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rGB/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rGB/strings.xml
index bf2624f..2716eae 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rGB/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rGB/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Narrow display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Narrow cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rIN/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rIN/strings.xml
index bf2624f..2716eae 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rIN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rIN/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Narrow display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Narrow cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rXC/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rXC/strings.xml
index 7ba124fb..df51da4 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rXC/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-en-rXC/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎Narrow display cutout‎‏‎‎‏‎"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎Narrow cutout‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-es-rUS/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-es-rUS/strings.xml
index f1d3348..2723d1b 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-es-rUS/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-es-rUS/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Recorte de pantalla estrecho"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Corte estrecho"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-es/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-es/strings.xml
index a17a32c..89ec75f 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-es/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-es/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Recorte estrecho de la pantalla"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Recorte estrecho"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-et/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-et/strings.xml
index 367b221..272280f 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-et/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-et/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Kitsas ekraani väljalõige"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Kitsas väljalõige"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-eu/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-eu/strings.xml
index 0fd9d9b..accdac7 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-eu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-eu/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Pantailaren mozketa estua"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Mozketa estua"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fa/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fa/strings.xml
index 43bfb2e..f3a1185 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fa/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"نمایشگری با لبه باریک"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"لبه باریک"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fi/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fi/strings.xml
index 540fbae..292d5de 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fi/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Kapea aukko näytössä"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Kapea lovi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr-rCA/strings.xml
index d78f8b8..577a948 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr-rCA/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Découpe d\'affichage étroit"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Encoche étroite"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr/strings.xml
index 4ee1b4f..551aa19 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-fr/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Encoche pour écran étroit"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Encoche pour écran étroit"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-gl/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-gl/strings.xml
index 9d01afd..0d1247c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-gl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-gl/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Recorte de pantalla estreito"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Recorte estreito"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-gu/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-gu/strings.xml
index 7d9987e..869842c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-gu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-gu/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"સાંકડું ડિસ્પ્લે કટઆઉટ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"સાંકડું કટઆઉટ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hi/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hi/strings.xml
deleted file mode 100644
index 32d6139..0000000
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"कम जगह वाला डिसप्ले कटआउट"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hr/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hr/strings.xml
index 00eca5b..8fe6f2d 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hr/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Obrezana slika za uske zaslone"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Uski urez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hu/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hu/strings.xml
index bfd2944..18b0722 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hu/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Keskeny képernyőkivágás"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Keskeny kivágás"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hy/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hy/strings.xml
index 2afecc8..a07a1bd 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hy/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-hy/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Էկրանի նեղ կտրվածք"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Նեղ կտրվածք"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-in/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-in/strings.xml
index 7728ab6..717449c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-in/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-in/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Potongan tampilan sempit"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Potongan sempit"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-is/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-is/strings.xml
index 3d86080..a353cef 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-is/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-is/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Mjór skjáskurður"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Mjór skurður"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-it/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-it/strings.xml
index 419c12b..ab96ff6 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-it/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-it/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Ritaglio display stretto"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Ritaglio stretto"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-iw/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-iw/strings.xml
index ffde493..a805dcc 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-iw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-iw/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"חיתוך תצוגה צר"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"מגרעת צרה"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ja/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ja/strings.xml
index 2b6a897..fe83639 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ja/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ja/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"幅狭のディスプレイ カットアウト"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"幅狭のカットアウト"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ka/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ka/strings.xml
index e52a32f..6e23255 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ka/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ka/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ეკრანის ვიწრო ამოჭრა"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ვიწრო ამოჭრა"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-kk/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-kk/strings.xml
index ee0d72d..b5da77d 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-kk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-kk/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Жіңішке экран ойығы"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Тар ойық"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-km/strings.xml
index c1faaa3c..959c9986 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-km/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ស្នាមចោះ​ផ្ទាំងអេក្រង់​តូច"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ស្នាមចោះ​តូច"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-kn/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-kn/strings.xml
index b356b31..87b390c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-kn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-kn/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ಕಿರಿದಾದ ಪ್ರದರ್ಶನ ಕಟೌಟ್"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ಕಿರಿದಾದ ಕಟೌಟ್"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ko/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ko/strings.xml
index 7175d52..20091a5 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ko/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ko/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"좁은 디스플레이 컷아웃"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"좁은 컷아웃"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ky/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ky/strings.xml
index 97308ca..6d49807 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ky/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ky/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Ичке дисплей кесиндиси"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Ичке кесинди"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lo/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lo/strings.xml
index 6a0251b..7e6ee12 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lo/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lo/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ກ່ອງຂໍ້ຄວາມສະແດງຜົນແບບແຄບ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ຮອຍບາກແຄບ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lt/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lt/strings.xml
index cb8a54b..d62db1e 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lt/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Siaura ekrano išpjova"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Siaura išpjova"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lv/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lv/strings.xml
index c87bc3f9..b352a22 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-lv/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Šaurs ekrāna izgriezums"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Šaurs izgriezums"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mk/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mk/strings.xml
index dd93e83..a75c297 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mk/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Тесен исечок на екранот"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Тесен исечок"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ml/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ml/strings.xml
index 3e12f05..cd7e3b9 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ml/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ml/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ഇടുങ്ങിയ ഡി‌സ്‌പ്ലേ കട്ടൗട്ട്"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ഇടുങ്ങിയ കട്ട്ഔട്ട്"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mn/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mn/strings.xml
index 087ed4a..aa2fb6c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mn/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Дэлгэцийг нарийн болгож таслах"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Нарийн болгож таслах"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mr/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mr/strings.xml
index 14a35da..a86cbeb 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-mr/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"अरुंद डिस्प्ले कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"नॅरो कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ms/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ms/strings.xml
index 20edbd7..717449c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ms/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ms/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Potongan paparan sempit"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Potongan sempit"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-my/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-my/strings.xml
index 4f84f2c..287b535 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-my/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-my/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ကျဉ်းမြောင်းသည့် မျက်နှာပြင် ဖြတ်ညှပ်ပြသမှု"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ကျဉ်းမြောင်းစွာ ဖြတ်ညှပ်ပြသမှု"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-nb/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-nb/strings.xml
index 300e988..dbb4c27 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-nb/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-nb/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Smalt skjermutklipp"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Smalt utklipp"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ne/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ne/strings.xml
index 9027414..0a68f0d 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ne/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ne/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"साँघुरो प्रदर्शनसम्बन्धी कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"साँघुरो कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-nl/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-nl/strings.xml
index b6f7f02..5783f5c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-nl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-nl/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Smalle display-cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Smalle cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-or/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-or/strings.xml
index 031edf0..a033d58 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-or/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-or/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ସଙ୍କୀର୍ଣ୍ଣ ଡିସ୍‌ପ୍ଲେ କଟଆଉଟ୍"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ସଂକୀର୍ଣ୍ଣ ଫଳକ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pa/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pa/strings.xml
index ddc0b11..83d3c02 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pa/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"ਤੰਗ ਡਿਸਪਲੇ ਕੱਟਆਊਟ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ਤੰਗ ਕੱਟਆਊਟ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pl/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pl/strings.xml
index f3261de..624e224 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pl/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Wąskie wycięcie wyświetlacza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Wycięcie wąskie"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt-rBR/strings.xml
index 3af25e8..60aa0e7 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt-rBR/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt-rBR/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Corte da tela estreito"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Corte estreito"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt-rPT/strings.xml
index 257c974..0d1247c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt-rPT/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt-rPT/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Ecrã estreito com recorte"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Recorte estreito"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt/strings.xml
index 3af25e8..60aa0e7 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-pt/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Corte da tela estreito"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Corte estreito"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ro/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ro/strings.xml
index 26d5448..ca67203 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ro/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ro/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Decupare ecran îngustă"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Decupaj îngust"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ru/strings.xml
index 0b8693c..207268c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ru/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Сделать вырез на экране уже"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Сузить вырез"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-si/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-si/strings.xml
index 0f4a8ff..7cca5b9 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-si/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-si/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"පටු සංදර්ශක කටවුට්"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"පටු කට්අවුට්"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sk/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sk/strings.xml
index 4cda8d5..72a714e 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sk/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Úzky výrez obrazovky"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Úzky výrez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sl/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sl/strings.xml
index 290df41..a2f3a43 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sl/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Ozek izrez prikaza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Ozka zareza"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sq/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sq/strings.xml
index be0a1e4..14ad99d 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sq/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sq/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Prerje e ngushtë ekrani"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Prerje e ngushtë"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sr/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sr/strings.xml
index d0710ac..9026c36 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sr/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Изрезана слика за уске екране"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Изрезана слика за уске екране"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sv/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sv/strings.xml
index f8c4bc3..3dc8753 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sv/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Smalt urklipp av skärm"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Smal utskärning"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sw/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sw/strings.xml
index 1aa3014..6032125 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-sw/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Mwonekeno wenye pengo jembamba"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Mkato mwembamba"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ta/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ta/strings.xml
index 8481f29..79c3186 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ta/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ta/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"குறுகிய கட்அவுட் காட்சி"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"குறுகிய கட்அவுட்"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-te/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-te/strings.xml
deleted file mode 100644
index 4e71bac..0000000
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-te/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"సన్నని డిస్‌ప్లే కట్అవుట్‌"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-th/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-th/strings.xml
index 4989e86..6506ef9 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-th/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-th/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"คัตเอาท์ดิสเพลย์แบบแคบ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"คัตเอาท์แบบแคบ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-tl/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-tl/strings.xml
index 3c88b3f5..fe34b9a 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-tl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-tl/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Manipis na display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Manipis na cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-tr/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-tr/strings.xml
index d84b758..022f1e3 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-tr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-tr/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Dar ekran kesimi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Dar kesim"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-uk/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-uk/strings.xml
index b5109de..15ebc5d 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-uk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-uk/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Відключення вузького дисплея"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Вузьке відрізання"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ur/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ur/strings.xml
index 5dba372..9dda24e 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ur/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-ur/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"تنگ ڈسپلے کٹ آؤٹ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"تنگ کٹ آؤٹ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-uz/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-uz/strings.xml
index 64bf629..d9f0ca0 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-uz/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-uz/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Ekrandagi kesimni qisqartirish"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Kesimni qisqartirish"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-vi/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-vi/strings.xml
index 0cf0602..c205a7d 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-vi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-vi/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Cắt hiển thị hẹp"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Vết cắt hẹp"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rCN/strings.xml
index 211ea2f..3102576 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rCN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rCN/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"窄型显示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"窄型刘海屏"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rHK/strings.xml
index c187813..505693f 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rHK/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rHK/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"幼身顯示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"幼身凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rTW/strings.xml
index 5799fed..ae50b4a3 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rTW/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zh-rTW/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"窄型螢幕凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"窄型凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zu/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zu/strings.xml
index 785ec6f..7a77583 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-zu/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6129374114103110395">"Ukusikwa kwesiboniso esimcingo"</string>
+    <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"Ukusika okucijile"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
index c22b2e7..6fb3c7f 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
@@ -40,6 +40,8 @@
         @dp
     </string>
 
+    <string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation">@*android:string/config_mainBuiltInDisplayCutout</string>
+
     <!-- Whether the display cutout region of the main built-in display should be forced to
          black in software (to avoid aliasing or emulate a cutout that is not physically existent).
      -->
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml
index 4989677..0bf8330 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml
@@ -18,7 +18,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Narrow display cutout</string>
+    <string name="display_cutout_emulation_overlay">Narrow cutout</string>
 
 </resources>
 
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-af/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-af/strings.xml
index e561329..6018ef4 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-af/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-af/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Uitsnede vir lang vertoonskerm"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Lang uitsnede"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-am/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-am/strings.xml
index 16a82a1..2b299cf 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-am/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-am/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"የረጅም ማሳያ ቅርጽ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ረዥም ቅርጽ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ar/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ar/strings.xml
index 06cab99..4bec886 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ar/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ar/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"صورة مقطوعة لشاشة طويلة"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"صورة مقطوعة طويلة"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-as/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-as/strings.xml
index 6adad3d..e8274b4 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-as/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-as/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ওখ ডিছপ্লে কাটআউট"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ওখ কাটআউট"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-az/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-az/strings.xml
index a14afc4..84af1e2 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-az/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-az/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Uzun ekran profili"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Hündür kəsim"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-b+sr+Latn/strings.xml
index 2212e82..46d30c6 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-b+sr+Latn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-b+sr+Latn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Izrezana slika za visoke ekrane"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Izrezana slika za visoke ekrane"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-be/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-be/strings.xml
index 53bb487..45dc1db 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-be/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-be/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Зрабіць выраз на экране больш высокім"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Высокі выраз"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bg/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bg/strings.xml
index a33cc39..b657d58 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bg/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bg/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Голям прорез на екрана"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Голям прорез"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bn/strings.xml
deleted file mode 100644
index 8513761..0000000
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bn/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"টল ডিসপ্লে কাট-আউট"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bs/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bs/strings.xml
index 4f0ed61..c7b35b6 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-bs/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Dugačak urez ekrana"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Dugačak urez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ca/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ca/strings.xml
index d264e34..4d5c5d3 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ca/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ca/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Retall de pantalla alt"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Retall alt"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-cs/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-cs/strings.xml
index fa5ceee..07ad2bc 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-cs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-cs/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Vysoký výřez displeje"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Vysoký výřez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-da/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-da/strings.xml
index 75e2d5d..b4f65d1 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-da/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-da/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Stor udskæring på skærmen"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Højt hak"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-de/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-de/strings.xml
index 6c65b16..f14479c 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-de/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-de/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Hoher Display-Ausschnitt"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Hohe Aussparung"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-el/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-el/strings.xml
index 1167237..a4815d4 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-el/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-el/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Διακοπή ψηλής οθόνης"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Ψηλή εγκοπή"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rAU/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rAU/strings.xml
index 3a41cbe..fce927c 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rAU/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rAU/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Tall display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Tall cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rCA/strings.xml
index 3a41cbe..fce927c 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rCA/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Tall display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Tall cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rGB/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rGB/strings.xml
index 3a41cbe..fce927c 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rGB/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rGB/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Tall display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Tall cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rIN/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rIN/strings.xml
index 3a41cbe..fce927c 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rIN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rIN/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Tall display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Tall cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rXC/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rXC/strings.xml
index db56bac..01a2d7c 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rXC/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-en-rXC/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‎Tall display cutout‎‏‎‎‏‎"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‏‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‎‏‏‎‎‏‎‎Tall cutout‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-es-rUS/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-es-rUS/strings.xml
index 3223601..5ecec17 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-es-rUS/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-es-rUS/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Recorte de pantalla alto"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Corte alto"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-es/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-es/strings.xml
index 1a73f18..ad06990 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-es/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-es/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Recorte alto de la pantalla"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Recorte alto"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-et/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-et/strings.xml
index ec84069..cdb23cc 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-et/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-et/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Pikk ekraani väljalõige"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Pikk väljalõige"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-eu/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-eu/strings.xml
index 7445925..e141906 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-eu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-eu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Pantailaren mozketa altua"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Mozketa altua"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fa/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fa/strings.xml
index 57990e8..0aece54 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fa/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"نمایشگر با لبه بلند"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"لبه بلند"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fi/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fi/strings.xml
index 4add280..fe4f59b 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fi/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Korkea aukko näytössä"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Korkea lovi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr-rCA/strings.xml
index cf15b14..da3705e 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr-rCA/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Découpe d\'affichage haut"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Encoche grande"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr/strings.xml
index f5db328..58c42b4 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-fr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Encoche pour écran haut"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Encoche pour écran haut"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-gl/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-gl/strings.xml
index 3223601..ad06990 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-gl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-gl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Recorte de pantalla alto"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Recorte alto"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-gu/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-gu/strings.xml
index a9a1f4a..1081d69 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-gu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-gu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ઊંચું ડિસ્પ્લે કટઆઉટ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ઊંચું કટઆઉટ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hi/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hi/strings.xml
deleted file mode 100644
index dbd3e84..0000000
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hi/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"लंबा डिसप्ले कटआउट"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hr/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hr/strings.xml
index 34082f8..5da0b46 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Obrezana slika za visoke zaslone"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Visoki urez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hu/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hu/strings.xml
index 7b871c5..2b00083 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Magas képernyőkivágás"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Magas kivágás"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hy/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hy/strings.xml
index ebff54c..be94922 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hy/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-hy/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Էկրանի բարձր կտրվածք"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Բարձր կտրվածք"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-in/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-in/strings.xml
index 9740135..e74f283 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-in/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-in/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Potongan tampilan tinggi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Potongan tinggi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-is/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-is/strings.xml
index f039cb9..dbeaade 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-is/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-is/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Hár skjáskurður"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Hár skurður"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-it/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-it/strings.xml
index af09afd..cd34197 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-it/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-it/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Ritaglio display alto"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Ritaglio alto"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-iw/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-iw/strings.xml
index faf3630..4034ccd 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-iw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-iw/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"חיתוך תצוגה גבוה"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"מגרעת גבוהה"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ja/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ja/strings.xml
index 86974bc..185c69f 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ja/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ja/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"縦長のディスプレイ カットアウト"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"縦長のカットアウト"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ka/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ka/strings.xml
index f84faba..f117b94 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ka/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ka/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ეკრანის მაღალი ამოჭრა"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"მაღალი ამოჭრა"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-kk/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-kk/strings.xml
index 8747ff0..cf89e6c 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-kk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-kk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Ұзын экран ойығы"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Тігінен ойық жасау"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-km/strings.xml
index 1741d58..eba93ef 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-km/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ស្នាមចោះ​ផ្ទាំងអេក្រង់​ជ្រៅ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ស្នាមចោះ​ជ្រៅ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-kn/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-kn/strings.xml
index ce1beb4..17298df 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-kn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-kn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ಎತ್ತರದ ಪ್ರದರ್ಶನ ಕಟೌಟ್"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ಎತ್ತರದ ಕಟೌಟ್"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ko/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ko/strings.xml
index c91015c..f81a533 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ko/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ko/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"세로로 긴 디스플레이 컷아웃"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"세로로 긴 컷아웃"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ky/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ky/strings.xml
index 0fbf920..c5aa62c 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ky/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ky/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Узун дисплей кесиндиси"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Узун кесинди"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lo/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lo/strings.xml
index f5ed0a84..83ba313 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lo/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lo/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ກ່ອງຂໍ້ຄວາມສະແດງຜົນແບບສູງ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ຮອຍບາກສູງ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lt/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lt/strings.xml
index 9afa5bd..5c0eb8f 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lt/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Ilga ekrano išpjova"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Ilga išpjova"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lv/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lv/strings.xml
index ec80989..4087f99 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-lv/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Augsts ekrāna izgriezums"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Augsts izgriezums"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mk/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mk/strings.xml
index b58b8ff..fcfe2d6 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Висок исечок на екранот"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Висок исечок"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ml/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ml/strings.xml
index 561ac16..c582ddf 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ml/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ml/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ഉയരമുളള ഡി‌സ്‌പ്ലേ കട്ടൗട്ട്"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ഉയരമുളള കട്ട്ഔട്ട്"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mn/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mn/strings.xml
index f45a11c..d42a3da 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Дэлгэцийг өндөр болгож таслах"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Урт болгож таслах"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mr/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mr/strings.xml
index 6f19f27..a8bdf05 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-mr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"उंच डिस्प्ले कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"टॉल कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ms/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ms/strings.xml
index 1847595..e74f283 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ms/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ms/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Potongan paparan tinggi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Potongan tinggi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-my/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-my/strings.xml
index 353d766..71b7397 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-my/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-my/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ရှည်လျားသည့် မျက်နှာပြင် ဖြတ်ညှပ်ပြသမှု"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ရှည်လျားစွာ ဖြတ်ညှပ်ပြသမှု"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-nb/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-nb/strings.xml
index ab1c4c6..ac5dcef 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-nb/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-nb/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Høyt skjermutklipp"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Høyt utklipp"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ne/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ne/strings.xml
index c969172..c83f6b4 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ne/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ne/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"अग्लो प्रदर्शनसम्बन्धी कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"अग्लो कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-nl/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-nl/strings.xml
index d7db4a9..06aa9e8 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-nl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-nl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Grote display-cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Hoge cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-or/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-or/strings.xml
index 2aba08b..198a728 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-or/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-or/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ଉଚ୍ଚ ଡିସ୍‌ପ୍ଲେ କଟଆଉଟ୍"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ଉଚ୍ଚା ଫଳକ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pa/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pa/strings.xml
index b10a5d0..02abc7f 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pa/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"ਲੰਮਾ ਡਿਸਪਲੇ ਕੱਟਆਊਟ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ਲੰਮਾ ਕੱਟਆਊਟ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pl/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pl/strings.xml
index 561947e..d98fe68 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Wysokie wycięcie wyświetlacza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Wycięcie wysokie"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt-rBR/strings.xml
index 893dd76..5ecec17 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt-rBR/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt-rBR/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Corte da tela alto"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Corte alto"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt-rPT/strings.xml
index 817dfec..d801d27 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt-rPT/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt-rPT/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Ecrã grande com recorte"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Recorte grande"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt/strings.xml
index 893dd76..5ecec17 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-pt/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Corte da tela alto"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Corte alto"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ro/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ro/strings.xml
index 32d771c..3f6264e 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ro/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ro/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Decupare ecran înaltă"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Decupaj înalt"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml
index ef1a690..1d1656d 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Сделать вырез на экране выше"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Сделать вырез выше"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-si/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-si/strings.xml
index 6d34b5bd..756ddc3 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-si/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-si/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"උස සංදර්ශක කටවුට්"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"උස කට්අවුට්"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sk/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sk/strings.xml
index 553e08d..6e427f6 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Vysoký výrez obrazovky"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Vysoký výrez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sl/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sl/strings.xml
index 9ad38ca..2e0246a 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Visok izrez prikaza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Visoka zareza"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sq/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sq/strings.xml
index ab6fd63..4586e99 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sq/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sq/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Prerje e lartë ekrani"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Prerje e gjatë"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sr/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sr/strings.xml
index 4f457f6..8ee39b8 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Изрезана слика за високе екране"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Изрезана слика за високе екране"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sv/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sv/strings.xml
index d0be3c3..f64addd 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sv/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Avlångt urklipp av skärm"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Avlång utskärning"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sw/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sw/strings.xml
index 463a703..ff53ff0 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-sw/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Mwonekeno wenye pengo ndefu"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Mkato mrefu"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ta/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ta/strings.xml
index d7ccc78..2ac88fd 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ta/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ta/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"உயரமான கட்அவுட் காட்சி"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"உயரமான கட்அவுட்"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-te/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-te/strings.xml
deleted file mode 100644
index 7de7e93..0000000
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-te/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"పొడవైన డిస్‌ప్లే కట్అవుట్‌"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-th/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-th/strings.xml
index ad6256e..edbd672 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-th/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-th/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"คัตเอาท์ดิสเพลย์แบบสูง"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"คัตเอาท์แบบสูง"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-tl/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-tl/strings.xml
index e9568be..8cf7058 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-tl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-tl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Mataas na display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Mataas na cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-tr/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-tr/strings.xml
index 1e75a40..54216d3 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-tr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-tr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Uzun ekran kesimi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Uzun kesim"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-uk/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-uk/strings.xml
index 94a9369..46747b2 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-uk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-uk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Відключення високого дисплея"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Відрізання по висоті"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ur/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ur/strings.xml
index f45451c..e7186c7 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ur/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ur/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"لمبا ڈسپلے کٹ آؤٹ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"لمبا کٹ آؤٹ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-uz/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-uz/strings.xml
index 6d09785..5efafd5 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-uz/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-uz/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Ekrandagi kesimni balandroq qilish"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Kesimni balandroq qilish"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-vi/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-vi/strings.xml
index 650a30b..d84734f 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-vi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-vi/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Cắt hiển thị cao"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Vết cắt cao"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rCN/strings.xml
index 4e4ff89..4ca659f 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rCN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rCN/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"长型显示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"长型刘海屏"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rHK/strings.xml
index 3aa87e0..dfabd42 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rHK/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rHK/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"長身顯示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"長身凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rTW/strings.xml
index cde32db..41b3770 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rTW/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zh-rTW/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"長型螢幕凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"長型凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zu/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zu/strings.xml
index ff1b633..d1f424a 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-zu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="4955013674374634273">"Ukusikwa kwesiboniso esinde"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Ukusika okude"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
index 401e092..7c29ffb 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
@@ -40,6 +40,8 @@
         @dp
     </string>
 
+    <string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation">@*android:string/config_mainBuiltInDisplayCutout</string>
+
     <!-- Whether the display cutout region of the main built-in display should be forced to
          black in software (to avoid aliasing or emulate a cutout that is not physically existent).
      -->
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml
index 6dcbbd9..bcc7c97 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml
@@ -16,7 +16,7 @@
   -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Tall display cutout</string>
+    <string name="display_cutout_emulation_overlay">Tall cutout</string>
 
 </resources>
 
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-af/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-af/strings.xml
index eda1e76..cb133ac 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-af/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-af/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Uitsnede vir wye vertoonskerm"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Wye uitsnede"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-am/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-am/strings.xml
index c1345dc..63291b9 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-am/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-am/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"የሰፊ ማሳያ ቅርጽ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"ሰፊ ቅርጽ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ar/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ar/strings.xml
index 0a7bfac..144f174 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ar/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ar/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"صورة مقطوعة لشاشة عريضة"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"صورة مقطوعة عريضة"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-as/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-as/strings.xml
index 49373e4..d72d5f7 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-as/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-as/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"বহল ডিছপ্লে কাটআউট"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"বহল কাটআউট"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-az/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-az/strings.xml
index 3a78dfe6..5ea06b2 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-az/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-az/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Geniş ekran profili"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Geniş kəsim"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-b+sr+Latn/strings.xml
index b67afb9..d4160f4 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-b+sr+Latn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-b+sr+Latn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Izrezana slika za široke ekrane"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Izrezana slika za široke ekrane"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-be/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-be/strings.xml
index a3a76f5..7b05ae0 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-be/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-be/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Зрабіць выраз на экране больш шырокім"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Шырокі выраз"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bg/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bg/strings.xml
index d0cf01d..7f52701 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bg/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bg/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Широк прорез на екрана"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Широк прорез"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bn/strings.xml
deleted file mode 100644
index 9ef4739..0000000
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bn/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"ওয়াইড ডিসপ্লে কাট-আউট"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bs/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bs/strings.xml
index 0aaf27f..233d9a9 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-bs/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Široki urez ekrana"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Široki urez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ca/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ca/strings.xml
index c9aa251..ce85aba 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ca/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ca/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Retall de pantalla ample"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Retall ample"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-cs/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-cs/strings.xml
index dcbb256..da6f83a 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-cs/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-cs/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Široký výřez displeje"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Široký výřez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-da/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-da/strings.xml
index b73b6ae..c5f06c1 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-da/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-da/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Bred udskæring på skærmen"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Bredt hak"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-de/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-de/strings.xml
index 20537dc..8056297 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-de/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-de/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Breiter Display-Ausschnitt"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Breite Aussparung"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-el/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-el/strings.xml
index 04c5e387..ce140ec 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-el/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-el/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Διακοπή πλατιάς οθόνης"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Πλατιά εγκοπή"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rAU/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rAU/strings.xml
index cc0e6c7..8eb5da0 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rAU/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rAU/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Wide display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Wide cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rCA/strings.xml
index cc0e6c7..8eb5da0 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rCA/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Wide display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Wide cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rGB/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rGB/strings.xml
index cc0e6c7..8eb5da0 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rGB/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rGB/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Wide display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Wide cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rIN/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rIN/strings.xml
index cc0e6c7..8eb5da0 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rIN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rIN/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Wide display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Wide cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rXC/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rXC/strings.xml
index 9310af8..83689c4 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rXC/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-en-rXC/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎Wide display cutout‎‏‎‎‏‎"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‎Wide cutout‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-es-rUS/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-es-rUS/strings.xml
index c88e12d..d840fce 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-es-rUS/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-es-rUS/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Recorte de pantalla ancho"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Corte ancho"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-es/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-es/strings.xml
index f63e427..155fa53 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-es/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-es/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Recorte ancho de la pantalla"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Recorte ancho"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-et/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-et/strings.xml
index f3643a9..ad54c9f 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-et/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-et/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Lai ekraani väljalõige"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Lai väljalõige"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-eu/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-eu/strings.xml
index f13d7f6..2193551 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-eu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-eu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Pantailaren mozketa zabala"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Mozketa zabala"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fa/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fa/strings.xml
index 13cbe2f..d4c57b1 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fa/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"نمایشگر با لبه پهن"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"لبه پهن"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fi/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fi/strings.xml
index 2568605..1ec4264 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fi/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Leveä aukko näytössä"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Leveä lovi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr-rCA/strings.xml
index 92faa6c..f9b15cf 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr-rCA/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr-rCA/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Découpe d\'affichage large"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Encoche large"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr/strings.xml
index 3e104be..ce8e131 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-fr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Encoche pour écran large"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Encoche pour écran large"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-gl/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-gl/strings.xml
index deafd40..bfef77d 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-gl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-gl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Recorte de pantalla amplo"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Recorte amplo"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-gu/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-gu/strings.xml
index fc08278..0c9f6a7 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-gu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-gu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"પહોળું ડિસ્પ્લે કટઆઉટ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"પહોળું કટઆઉટ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hi/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hi/strings.xml
deleted file mode 100644
index cdea4bb..0000000
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hi/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"चौड़ा डिसप्ले कटआउट"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hr/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hr/strings.xml
index fbb0858..233d9a9 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Obrezana slika za široke zaslone"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Široki urez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hu/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hu/strings.xml
index b9a4729..997f279 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Széles képernyőkivágás"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Széles kivágás"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hy/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hy/strings.xml
index cfe4dbf..e93676c 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hy/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-hy/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Էկրանի լայն կտրվածք"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Լայն կտրվածք"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-in/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-in/strings.xml
index 91440fc..11c5a5f 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-in/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-in/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Potongan tampilan lebar"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Potongan lebar"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-is/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-is/strings.xml
index 367219bd..b248256 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-is/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-is/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Breiður skjáskurður"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Breiður skurður"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-it/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-it/strings.xml
index 5349c40..e0c2c12 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-it/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-it/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Ritaglio display largo"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Ritaglio largo"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-iw/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-iw/strings.xml
index 1a2fdd7..ae100e6 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-iw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-iw/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"חיתוך תצוגה רחב"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"מגרעת רחבה"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ja/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ja/strings.xml
index f0fc0a2..126cf58 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ja/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ja/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"幅広のディスプレイ カットアウト"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"幅広のカットアウト"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ka/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ka/strings.xml
index 8a6b89f..87e6129 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ka/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ka/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"ეკრანის ფართო ამოჭრა"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"ფართო ამოჭრა"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-kk/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-kk/strings.xml
index f3124de..e50f34c 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-kk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-kk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Жалпақ экран ойығы"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Көлденеңінен ойық жасау"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-km/strings.xml
index 6fc8643..a2493a0 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-km/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"ស្នាមចោះ​ផ្ទាំងអេក្រង់​ធំ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"ស្នាមចោះ​ធំ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-kn/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-kn/strings.xml
index f95180d..65730c5 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-kn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-kn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"ವಿಶಾಲ ಪ್ರದರ್ಶನ ಕಟೌಟ್"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"ವಿಶಾಲವಾದ ಕಟೌಟ್"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ko/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ko/strings.xml
index ea4f638..19350ac 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ko/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ko/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"넓은 디스플레이 컷아웃"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"넓은 컷아웃"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ky/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ky/strings.xml
index 735034d..dafd16e 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ky/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ky/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Жазы дисплей кесиндиси"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Жазы кесинди"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lo/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lo/strings.xml
index 8282319..942f9be 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lo/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lo/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"ກ່ອງຂໍ້ຄວາມສະແດງຜົນແບບກວ້າງ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"ຮອຍບາກກວ້າງ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lt/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lt/strings.xml
index a46ae3d..46251b7 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lt/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Plati ekrano išpjova"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Plati išpjova"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lv/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lv/strings.xml
index 9789d8c..50e3947 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-lv/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Plats ekrāna izgriezums"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Plats izgriezums"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mk/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mk/strings.xml
index 025c46e..dbcae0e 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Широк исечок на екранот"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Широк исечок"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ml/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ml/strings.xml
index 9a47565..ba30add 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ml/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ml/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"വിസ്‌തൃതമായ ഡി‌സ്‌പ്ലേ കട്ടൗട്ട്"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"വിസ്‌തൃതമായ കട്ട്ഔട്ട്"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mn/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mn/strings.xml
index a7d8b5a..a6eb666 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mn/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mn/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Дэлгэцийг өргөн болгож таслах"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Өргөн болгож таслах"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mr/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mr/strings.xml
index 50542af..8f97495 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-mr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"रुंद डिस्प्ले कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"वाइड कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ms/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ms/strings.xml
index ad702b7..11c5a5f 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ms/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ms/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Potongan paparan lebar"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Potongan lebar"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-my/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-my/strings.xml
index 94566da..79b9ce3 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-my/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-my/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"မြင်ကွင်းကျယ် မျက်နှာပြင် ဖြတ်ညှပ်ပြသမှု"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"မြင်ကွင်းကျယ် ဖြတ်ညှပ်ပြသမှု"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-nb/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-nb/strings.xml
index c84fc8b..a7d8e63 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-nb/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-nb/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Bredt skjermutklipp"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Bredt utklipp"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ne/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ne/strings.xml
index 718ca43..7a94507 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ne/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ne/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"फराकिलो प्रदर्शनसम्बन्धी कटआउट"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"फराकिलो कटआउट"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-nl/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-nl/strings.xml
index b57cac7..50800e7 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-nl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-nl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Brede display-cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Brede cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-or/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-or/strings.xml
index b146134..9e61674 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-or/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-or/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"ଓସାରିଆ ଡିସ୍‌ପ୍ଲେ କଟଆଉଟ୍"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"ଓସାରିଆ ଫଳକ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pa/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pa/strings.xml
index c86889f..b425aba 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pa/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pa/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"ਚੌੜਾ ਡਿਸਪਲੇ ਕੱਟਆਊਟ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"ਚੌੜਾ ਕੱਟਆਊਟ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pl/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pl/strings.xml
index 082946f..9c6deeb 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Szerokie wycięcie wyświetlacza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Wycięcie szerokie"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt-rBR/strings.xml
index 16491f8..c6dccb6 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt-rBR/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt-rBR/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Corte da tela largo"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Corte largo"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt-rPT/strings.xml
index 03d3631..1a36347 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt-rPT/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt-rPT/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Ecrã largo com recorte"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Recorte largo"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt/strings.xml
index 16491f8..c6dccb6 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-pt/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Corte da tela largo"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Corte largo"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ro/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ro/strings.xml
index a1140a8..ebfeafd 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ro/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ro/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Decupare ecran lată"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Decupaj lat"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ru/strings.xml
index f7d5ec6..1a3e8ef 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ru/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Сделать вырез на экране шире"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Расширить вырез"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-si/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-si/strings.xml
index 1be117b..6adca77 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-si/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-si/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"පුළුල් සංදර්ශක කටවුට්"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"පුළුල් කට්අවුට්"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sk/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sk/strings.xml
index 059e584..e50b31f 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Široký výrez obrazovky"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Široký výrez"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sl/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sl/strings.xml
index 5c5b5a25..b93b5ff 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Širok izrez prikaza"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Široka zareza"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sq/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sq/strings.xml
index 76271ac..f9c295c 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sq/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sq/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Prerje e gjerë ekrani"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Prerje e gjerë"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sr/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sr/strings.xml
index 6670512..6087dd7 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Изрезана слика за широке екране"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Изрезана слика за широке екране"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sv/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sv/strings.xml
index c624c05..47a06e1 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sv/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sv/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Brett urklipp av skärm"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Bred utskärning"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sw/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sw/strings.xml
index 0414e8a..206f6f7 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sw/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-sw/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Mwonekeno wenye pengo pana"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Mkato mpana"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ta/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ta/strings.xml
index 122a8b2..e62e14b 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ta/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ta/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"அகலமான கட்அவுட் காட்சி"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"அகலமான கட்அவுட்"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-te/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-te/strings.xml
deleted file mode 100644
index 1a0a3bf..0000000
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-te/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-  ~ Copyright (C) 2018 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-   -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"వెడల్పైన డిస్‌ప్లే కట్అవుట్‌"</string>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-th/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-th/strings.xml
index f91a7b6..40841d8 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-th/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-th/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"คัตเอาท์ดิสเพลย์แบบกว้าง"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"คัตเอาท์แบบกว้าง"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-tl/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-tl/strings.xml
index 2f82c4bb..7501a22 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-tl/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-tl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Malapad na display cutout"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Malapad na cutout"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-tr/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-tr/strings.xml
index 01d77d58..a3b1f39 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-tr/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-tr/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Geniş ekran kesimi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Geniş kesim"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-uk/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-uk/strings.xml
index 40b5c9d..5c07ce2 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-uk/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-uk/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Відключення широкого дисплея"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Відрізання по ширині"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ur/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ur/strings.xml
index 3bed22a..ad9fe8b 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ur/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-ur/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"چوڑا ڈسپلے کٹ آؤٹ"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"چوڑا کٹ آؤٹ"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-uz/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-uz/strings.xml
index c67c8ca..5aa5fa5 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-uz/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-uz/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Ekrandagi kesimni uzaytirish"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Kesimni uzaytirish"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-vi/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-vi/strings.xml
index c811af0..3ffb81c 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-vi/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-vi/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Cắt hiển thị rộng"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Vết cắt rộng"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rCN/strings.xml
index 8aea673..24efd55 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rCN/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rCN/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"宽型显示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"宽型刘海屏"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rHK/strings.xml
index 8a23136..87ba61b 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rHK/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rHK/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"闊身顯示屏凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"闊身凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rTW/strings.xml
index 9d2921b..f5a57f5 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rTW/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zh-rTW/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"寬型螢幕凹口"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"寬型凹口"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zu/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zu/strings.xml
index 4a96281..ccf0040 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zu/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-zu/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="3249818092477753587">"Ukusikwa kwesiboniso esibanzi"</string>
+    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Ukusika okubanzi"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
index f328b83..5fb8b9e 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
@@ -40,6 +40,8 @@
         @dp
     </string>
 
+    <string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation">@*android:string/config_mainBuiltInDisplayCutout</string>
+
     <!-- Whether the display cutout region of the main built-in display should be forced to
          black in software (to avoid aliasing or emulate a cutout that is not physically existent).
      -->
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml
index f4b9f7e..0fcbdebb 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml
@@ -16,7 +16,7 @@
   -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Wide display cutout</string>
+    <string name="display_cutout_emulation_overlay">Wide cutout</string>
 
 </resources>
 
diff --git a/packages/overlays/SysuiDarkThemeOverlay/Android.mk b/packages/overlays/SysuiDarkThemeOverlay/Android.mk
deleted file mode 100644
index 7b277bc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_RRO_THEME := SysuiDarkTheme
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := SysuiDarkThemeOverlay
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
deleted file mode 100644
index 8b6ee2b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.systemui.theme.dark"
-    android:versionCode="1"
-    android:versionName="1.0">
-    <overlay android:targetPackage="com.android.systemui" android:priority="1"/>
-
-    <application android:label="@string/sysui_overlay_dark" android:hasCode="false"/>
-</manifest>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-af/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-af/strings.xml
deleted file mode 100644
index 33c6982..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-af/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Donker"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-am/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-am/strings.xml
deleted file mode 100644
index 5979569..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-am/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ጨለማ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ar/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ar/strings.xml
deleted file mode 100644
index 7b20c01..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ar/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"داكن"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-as/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-as/strings.xml
deleted file mode 100644
index 0910e7e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-as/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"গাঢ়"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-az/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-az/strings.xml
deleted file mode 100644
index a9db75c..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-az/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Qaranlıq"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index b63dcbc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tamno"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-be/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-be/strings.xml
deleted file mode 100644
index eb875b3..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-be/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Цёмная"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-bg/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-bg/strings.xml
deleted file mode 100644
index 7b39462..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-bg/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Тъмно"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-bn/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-bn/strings.xml
deleted file mode 100644
index 0910e7e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-bn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"গাঢ়"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-bs/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-bs/strings.xml
deleted file mode 100644
index b63dcbc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-bs/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tamno"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ca/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ca/strings.xml
deleted file mode 100644
index 02ee226..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ca/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Fosc"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-cs/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-cs/strings.xml
deleted file mode 100644
index 5d11f07..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-cs/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tmavé"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-da/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-da/strings.xml
deleted file mode 100644
index 460ebe7..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-da/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Mørk"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-de/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-de/strings.xml
deleted file mode 100644
index 4b54b8e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-de/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Dunkel"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-el/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-el/strings.xml
deleted file mode 100644
index c58061d..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-el/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Σκοτεινό"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rAU/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rAU/strings.xml
deleted file mode 100644
index 7c94a51..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Dark"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rCA/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rCA/strings.xml
deleted file mode 100644
index 7c94a51..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Dark"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rGB/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rGB/strings.xml
deleted file mode 100644
index 7c94a51..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Dark"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rIN/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rIN/strings.xml
deleted file mode 100644
index 7c94a51..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Dark"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rXC/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rXC/strings.xml
deleted file mode 100644
index cbdd3d2..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎‎‏‎‏‏‏‏‏‏‎‎Dark‎‏‎‎‏‎"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-es-rUS/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-es-rUS/strings.xml
deleted file mode 100644
index 2717f0f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Oscuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-es/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-es/strings.xml
deleted file mode 100644
index 2717f0f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-es/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Oscuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-et/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-et/strings.xml
deleted file mode 100644
index e0cce05..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-et/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tume"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-eu/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-eu/strings.xml
deleted file mode 100644
index 44cee4c..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-eu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Iluna"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-fa/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-fa/strings.xml
deleted file mode 100644
index fdd1df5..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-fa/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"تیره"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-fi/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-fi/strings.xml
deleted file mode 100644
index 237fe70..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-fi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tumma"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-fr-rCA/strings.xml
deleted file mode 100644
index f92c2ef..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Sombre"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-fr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-fr/strings.xml
deleted file mode 100644
index eac51d3..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-fr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Foncé"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-gl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-gl/strings.xml
deleted file mode 100644
index 300868f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-gl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Escuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-gu/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-gu/strings.xml
deleted file mode 100644
index 6a4cd62f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-gu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ઘેરી"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-hi/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-hi/strings.xml
deleted file mode 100644
index c5bc0e2..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-hi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"गहरे रंग की थीम"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-hr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-hr/strings.xml
deleted file mode 100644
index b63dcbc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-hr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tamno"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-hu/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-hu/strings.xml
deleted file mode 100644
index 84a3ab8..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-hu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Sötét"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-hy/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-hy/strings.xml
deleted file mode 100644
index 555cb64..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-hy/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Մուգ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-in/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-in/strings.xml
deleted file mode 100644
index 391451b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-in/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Gelap"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-is/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-is/strings.xml
deleted file mode 100644
index f4d1531..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-is/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Dökkt"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-it/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-it/strings.xml
deleted file mode 100644
index b59155b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-it/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Scuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-iw/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-iw/strings.xml
deleted file mode 100644
index 3ecf444..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-iw/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"כהה"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ja/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ja/strings.xml
deleted file mode 100644
index 3a2dba0..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ja/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ダーク"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ka/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ka/strings.xml
deleted file mode 100644
index 36bf77e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ka/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"მუქი"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-kk/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-kk/strings.xml
deleted file mode 100644
index 913c0b1..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-kk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Қараңғы"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-km/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-km/strings.xml
deleted file mode 100644
index b56c490..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-km/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ងងឹត"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-kn/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-kn/strings.xml
deleted file mode 100644
index e757116..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-kn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ಕತ್ತಲೆ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ko/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ko/strings.xml
deleted file mode 100644
index ca4ab1e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ko/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"어두움"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ky/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ky/strings.xml
deleted file mode 100644
index e8e8279..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ky/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Караңгы"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-lo/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-lo/strings.xml
deleted file mode 100644
index 0434a41..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-lo/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ມືດ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-lt/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-lt/strings.xml
deleted file mode 100644
index 147779b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-lt/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tamsi"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-lv/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-lv/strings.xml
deleted file mode 100644
index 7a296ec..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-lv/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tumšs"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-mk/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-mk/strings.xml
deleted file mode 100644
index 6be693a..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-mk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Темна"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ml/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ml/strings.xml
deleted file mode 100644
index f8a24fa..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ml/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ഡാർക്ക്"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-mn/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-mn/strings.xml
deleted file mode 100644
index e65d9c7..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-mn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Бараан"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-mr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-mr/strings.xml
deleted file mode 100644
index 854af00..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-mr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"गडद"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ms/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ms/strings.xml
deleted file mode 100644
index 391451b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ms/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Gelap"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-my/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-my/strings.xml
deleted file mode 100644
index 008e9c6..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-my/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"မှောင်သော"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-nb/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-nb/strings.xml
deleted file mode 100644
index 460ebe7..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-nb/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Mørk"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ne/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ne/strings.xml
deleted file mode 100644
index 8f2c5ba..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ne/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"अँध्यारो"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-nl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-nl/strings.xml
deleted file mode 100644
index 33c6982..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-nl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Donker"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-or/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-or/strings.xml
deleted file mode 100644
index d8045bd..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-or/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ଗାଢ଼"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pa/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pa/strings.xml
deleted file mode 100644
index 7110303..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pa/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ਗੂੜ੍ਹਾ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pl/strings.xml
deleted file mode 100644
index 25ca20f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Ciemna"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rBR/strings.xml
deleted file mode 100644
index 300868f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Escuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 300868f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Escuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pt/strings.xml
deleted file mode 100644
index 300868f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Escuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ro/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ro/strings.xml
deleted file mode 100644
index de73f36..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ro/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Întunecată"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ru/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ru/strings.xml
deleted file mode 100644
index b05e844..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ru/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Темный"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-si/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-si/strings.xml
deleted file mode 100644
index f0f5725..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-si/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"අඳුරු"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sk/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sk/strings.xml
deleted file mode 100644
index 5df6895..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tmavý"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sl/strings.xml
deleted file mode 100644
index ad58250..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Temno"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sq/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sq/strings.xml
deleted file mode 100644
index 0e1eae7..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sq/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"E errët"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sr/strings.xml
deleted file mode 100644
index 1561ee2..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Тамно"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sv/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sv/strings.xml
deleted file mode 100644
index 676de42..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sv/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Mörk"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sw/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sw/strings.xml
deleted file mode 100644
index cc1f120..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sw/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Nyeusi"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ta/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ta/strings.xml
deleted file mode 100644
index af98172..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ta/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"டார்க்"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-te/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-te/strings.xml
deleted file mode 100644
index 446455f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-te/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"ముదురు రంగు"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-th/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-th/strings.xml
deleted file mode 100644
index 9e3462b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-th/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"เข้ม"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-tl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-tl/strings.xml
deleted file mode 100644
index 5502d90..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-tl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Madilim"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-tr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-tr/strings.xml
deleted file mode 100644
index 368b398..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-tr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Koyu"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-uk/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-uk/strings.xml
deleted file mode 100644
index 6e67e45..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-uk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Темна тема"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ur/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ur/strings.xml
deleted file mode 100644
index 1d5d6de..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ur/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"گہرا"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-uz/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-uz/strings.xml
deleted file mode 100644
index 957c28f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-uz/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tungi"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-vi/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-vi/strings.xml
deleted file mode 100644
index a458889..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-vi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Tối"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rCN/strings.xml
deleted file mode 100644
index c9b43dc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"深色"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rHK/strings.xml
deleted file mode 100644
index c9b43dc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"深色"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rTW/strings.xml
deleted file mode 100644
index c9b43dc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"深色"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-zu/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-zu/strings.xml
deleted file mode 100644
index 6d328da..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-zu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="sysui_overlay_dark" msgid="557336259295713662">"Emnyama"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/strings.xml
deleted file mode 100644
index 71f48d6..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <string name="sysui_overlay_dark">Dark</string>
-
-</resources>
-
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
deleted file mode 100644
index 41a2940..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <style name="qs_base" parent="android:Theme.DeviceDefault">
-        <item name="android:colorPrimary">@*android:color/primary_device_default_settings</item>
-        <item name="android:colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
-        <item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
-        <item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
-        <item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
-        <item name="android:colorBackgroundFloating">@*android:color/material_grey_900</item>
-        <item name="android:panelColorBackground">@*android:color/material_grey_800</item>
-    </style>
-</resources>
\ No newline at end of file
diff --git a/proto/src/gnss.proto b/proto/src/gnss.proto
index 0168392..1509fc0 100644
--- a/proto/src/gnss.proto
+++ b/proto/src/gnss.proto
@@ -45,6 +45,9 @@
 
   // Power metrics
   optional PowerMetrics power_metrics = 12;
+
+  // Hardware revision (EVT, DVT, PVT etc.)
+  optional string hardware_revision = 13;
 }
 
 // Power metrics
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 73eb37f..2e53a5f 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -941,9 +941,10 @@
     // OS: 6.0
     NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
 
-    // ACTION: App notification settings > Block Notifications
+    // ACTION: App notification settings > Block Notifications or long press on
+    // notification blocks.
     // CATEGORY: SETTINGS
-    // OS: 6.0
+    // OS: 9.0
     ACTION_BAN_APP_NOTES = 147;
 
     // ACTION: Notification shade > Dismiss all button
@@ -2218,6 +2219,7 @@
     // 1: Gesture performed is Nudge
     // 2: Gesture performed is Pickup
     // 4: Gesture performed is Double Tap
+    // 6: Gesture performed is Reach
     ACTION_AMBIENT_GESTURE = 411;
 
     // ---- End N Constants, all N constants go above this line ----
@@ -4083,6 +4085,8 @@
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
     // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS Q, it also added the following fields:
+    // FIELD_AUTOFILL_UPDATE: Whether the UI displayed "UPDATE" instead of "SAVE"
     AUTOFILL_SAVE_UI = 916;
 
     // Tag of a field for the number of saveable ids
@@ -6145,6 +6149,355 @@
     // CATEGORY: SETTINGS
     // OS: Q
     ACTION_FACE_ENROLL = 1505;
+
+    // OPEN: Face Enroll introduction
+    // CATEGORY: SETTINGS
+    // OS: Q
+    FACE_ENROLL_INTRO = 1506;
+
+    // OPEN: Face Enroll introduction
+    // CATEGORY: SETTINGS
+    // OS: Q
+    FACE_ENROLL_ENROLLING = 1507;
+
+    // OPEN: Face Enroll introduction
+    // CATEGORY: SETTINGS
+    // OS: Q
+    FACE_ENROLL_FINISHED = 1508;
+
+    // OPEN: Face Enroll sidecar
+    // CATEGORY: SETTINGS
+    // OS: Q
+    FACE_ENROLL_SIDECAR = 1509;
+
+    // OPEN: Settings > Add face > Error dialog
+    // OS: Q
+    DIALOG_FACE_ERROR = 1510;
+
+    // OPEN: Settings > Security > Face
+    // CATEGORY: SETTINGS
+    // OS: Q
+    FACE = 1511;
+
+    // OPEN: Settings > Acessibility > HearingAid pairing instructions dialog
+    // CATEGORY: SETTINGS
+    // OS: Q
+    DIALOG_ACCESSIBILITY_HEARINGAID = 1512;
+
+    // ACTION: Activity start
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    ACTION_ACTIVITY_START = 1513;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Calling UID
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_CALLING_UID = 1514;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Calling package name
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_CALLING_PACKAGE_NAME = 1515;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Calling UID proc state
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_CALLING_UID_PROC_STATE = 1516;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Calling UID has any visible window
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW = 1517;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Real calling UID
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_REAL_CALLING_UID = 1518;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Real calling UID proc state
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_REAL_CALLING_UID_PROC_STATE = 1519;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Real calling UID has any visible window
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW = 1520;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Target UID
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_TARGET_UID = 1521;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Target UID package name
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_TARGET_PACKAGE_NAME = 1522;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Target UID proc state
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_TARGET_UID_PROC_STATE = 1523;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Target UID has any visible window
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW = 1524;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Target doze whitelist tag
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_TARGET_WHITELIST_TAG = 1525;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Target short component name
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_TARGET_SHORT_COMPONENT_NAME = 1526;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Coming from pending intent
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_COMING_FROM_PENDING_INTENT = 1527;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Intent action
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_INTENT_ACTION = 1528;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Caller app process record process name
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_PROCESS_NAME = 1529;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Caller app process record current proc state
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_CUR_PROC_STATE = 1530;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Caller app process record has client activities
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES = 1531;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Caller app process record has foreground services
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES = 1532;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Caller app process record has foreground activities
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES = 1533;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Caller app process record has top UI
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_HAS_TOP_UI = 1534;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Caller app process record has overlay UI
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_HAS_OVERLAY_UI = 1535;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Caller app process record pending UI clean
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_PENDING_UI_CLEAN = 1536;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Millis since caller app's process record last interaction event
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT = 1537;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Millis since caller app's process record fg interaction
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION = 1538;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Millis since caller app's process record last became unimportant
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT = 1539;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record launch mode
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_LAUNCH_MODE = 1540;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record target activity
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY = 1541;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record flags
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_FLAGS = 1542;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record real activity
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_REAL_ACTIVITY = 1543;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record short component name
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME = 1544;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record process name
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_PROCESS_NAME = 1545;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record is fullscreen
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_IS_FULLSCREEN = 1546;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record is no display
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY = 1547;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Millis since activity was last visible
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE = 1548;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record's resultTo packageName
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME = 1549;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record's resultTo shortComponentName
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME = 1550;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record is visible
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_IS_VISIBLE = 1551;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Activity record is visible ignoring keyguard
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD = 1552;
+
+    // Tagged data for ACTION_ACTIVITY_START.
+    // FIELD: Millis since activity's last launch
+    // CATEGORY: OTHER
+    // OS: Q (will also ship in PQ1A)
+    FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH = 1553;
+
+    // OPEN: Settings > Add face
+    // OS: Q
+    FACE_ENROLL_PREVIEW = 1554;
+
+    // Field used to indicate whether a save request was used to update existing user data.
+    FIELD_AUTOFILL_UPDATE = 1555;
+
+    // OPEN: Settings > Network & Internet > Wi-Fi > Add network
+    // CATEGORY: SETTINGS
+    // OS: Q
+    SETTINGS_WIFI_ADD_NETWORK = 1556;
+
+    // OPEN: Settings > System > Input & Gesture > Reach up gesture
+    // OS: Q
+    SETTINGS_GESTURE_REACH = 1557;
+
+    // OPEN: Emergency dialer opened
+    // CLOSE: Emergency dialer closed
+    //  SUBTYPE: The entry type that user opened emergency dialer
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    EMERGENCY_DIALER = 1558;
+
+    // FIELD: The screen is currently locked
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    FIELD_EMERGENCY_DIALER_IS_SCREEN_LOCKED = 1559;
+
+    // FIELD: Bit flag indicating the actions performed by user
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    FIELD_EMERGENCY_DIALER_USER_ACTIONS = 1560;
+
+    // FIELD: The duration user stayed at emergency dialer
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    FIELD_EMERGENCY_DIALER_DURATION_MS = 1561;
+
+    // ACTION: Making call via emergency dialer
+    //  SUBTYPE: The UI that user made phone call
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    EMERGENCY_DIALER_MAKE_CALL = 1562;
+
+    // FIELD: The phone number type of a call user made
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    FIELD_EMERGENCY_DIALER_PHONE_NUMBER_TYPE = 1563;
+
+    // FIELD: There is a shortcut for the phone number
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    FIELD_EMERGENCY_DIALER_PHONE_NUMBER_HAS_SHORTCUT = 1564;
+
+    // FIELD: The phone is in pocket while using emergency dialer
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    FIELD_EMERGENCY_DIALER_IN_POCKET = 1565;
+
+    // ACTION: The second tap on emergency shortcut to make a phone call
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    EMERGENCY_DIALER_SHORTCUT_CONFIRM_TAP = 1566;
+
+    // FIELD: The time in milliseconds of second tap on shortcut since first tap
+    // CATEGORY: EMERGENCY_DIALER
+    // OS: Q
+    FIELD_EMERGENCY_DIALER_SHORTCUT_TAPS_INTERVAL = 1567;
+
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 33fc5e5..7f8989d 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -470,6 +470,15 @@
   // Counts the occurrences of each link speed (Mbps) level
   // with rssi (dBm) and rssi^2 sums (dBm^2)
   repeated LinkSpeedCount link_speed_counts = 121;
+
+  // Number of times the SarManager failed to register SAR sensor listener
+  optional int32 num_sar_sensor_registration_failures = 122;
+
+  // Histogram of the EAP method type of all installed Passpoint profiles
+  repeated PasspointProfileTypeCount installed_passpoint_profile_type = 123;
+
+  // Hardware revision (EVT, DVT, PVT etc.)
+  optional string hardware_revision = 124;
 }
 
 // Information that gets logged for every WiFi connection.
@@ -805,6 +814,12 @@
 
     // Framework changed Sta interface MAC address
     TYPE_MAC_CHANGE = 17;
+
+    // Wifi is turned on
+    TYPE_WIFI_ENABLED = 18;
+
+    // Wifi is turned off
+    TYPE_WIFI_DISABLED = 19;
   }
 
   enum FrameworkDisconnectReason {
@@ -1611,4 +1626,32 @@
 
   // Firmware alert code. Only valid when the event was triggered by a firmware alert, otherwise -1.
   optional int32 firmware_alert_code = 10 [default = -1];
+}
+
+message PasspointProfileTypeCount {
+  enum EapMethod {
+    // Unknown Type
+    TYPE_UNKNOWN = 0;
+
+    // EAP_TLS (13)
+    TYPE_EAP_TLS = 1;
+
+    // EAP_TTLS (21)
+    TYPE_EAP_TTLS = 2;
+
+    // EAP_SIM (18)
+    TYPE_EAP_SIM = 3;
+
+    // EAP_AKA (23)
+    TYPE_EAP_AKA = 4;
+
+    // EAP_AKA_PRIME (50)
+    TYPE_EAP_AKA_PRIME = 5;
+  }
+
+  // Eap method type set in Passpoint profile
+  optional EapMethod eap_method_type = 1;
+
+  // Num of installed Passpoint profile with same eap method
+  optional int32 count = 2;
 }
\ No newline at end of file
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
index f95af16..b7e05d9 100644
--- a/rs/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -16,6 +16,7 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
 import dalvik.system.CloseGuard;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -73,6 +74,7 @@
     final CloseGuard guard = CloseGuard.get();
     private boolean mDestroyed;
     private String mName;
+    @UnsupportedAppUsage
     RenderScript mRS;
 
     /**
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index 667bf71..b8eb3a1 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -16,6 +16,8 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * <p>An Element represents one item within an {@link
  * android.renderscript.Allocation}.  An Element is roughly equivalent to a C
@@ -1146,6 +1148,7 @@
      * @param dt The DataType for the new element.
      * @return Element
      */
+    @UnsupportedAppUsage
     static Element createUser(RenderScript rs, DataType dt) {
         DataKind dk = DataKind.USER;
         boolean norm = false;
diff --git a/rs/java/android/renderscript/FileA3D.java b/rs/java/android/renderscript/FileA3D.java
index 278d309..9a6b0bc 100644
--- a/rs/java/android/renderscript/FileA3D.java
+++ b/rs/java/android/renderscript/FileA3D.java
@@ -19,6 +19,7 @@
 import java.io.File;
 import java.io.InputStream;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 
@@ -53,6 +54,7 @@
         * @deprecated in API 16
         * RenderScript Mesh object
         **/
+        @UnsupportedAppUsage
         MESH (1);
 
         int mID;
@@ -100,6 +102,7 @@
         * @return type of a renderscript object the index entry
         *         describes
         */
+        @UnsupportedAppUsage
         public EntryType getEntryType() {
             return mEntryType;
         }
@@ -109,6 +112,7 @@
         * Used to load the object described by the index entry
         * @return base renderscript object described by the entry
         */
+        @UnsupportedAppUsage
         public BaseObj getObject() {
             mRS.validate();
             BaseObj obj = internalCreate(mRS, this);
@@ -212,6 +216,7 @@
     *
     * @return entry in the a3d file described by the index
     */
+    @UnsupportedAppUsage
     public IndexEntry getIndexEntry(int index) {
         if(getIndexEntryCount() == 0 || index < 0 || index >= mFileEntries.length) {
             return null;
@@ -284,6 +289,7 @@
     *
     * @return a3d file containing renderscript objects
     */
+    @UnsupportedAppUsage
     static public FileA3D createFromResource(RenderScript rs, Resources res, int id) {
 
         rs.validate();
diff --git a/rs/java/android/renderscript/Font.java b/rs/java/android/renderscript/Font.java
index d5ca31e..583350e 100644
--- a/rs/java/android/renderscript/Font.java
+++ b/rs/java/android/renderscript/Font.java
@@ -23,6 +23,7 @@
 
 import android.os.Environment;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 
@@ -85,6 +86,7 @@
         /**
          * @deprecated in API 16
          */
+        @UnsupportedAppUsage
         ITALIC,
         /**
          * @deprecated in API 16
@@ -236,6 +238,7 @@
      *
      * Returns default font if no match could be found.
      */
+    @UnsupportedAppUsage
     static public Font create(RenderScript rs, Resources res, String familyName, Style fontStyle, float pointSize) {
         String fileName = getFontFileName(familyName, fontStyle);
         String fontPath = Environment.getRootDirectory().getAbsolutePath();
diff --git a/rs/java/android/renderscript/Matrix4f.java b/rs/java/android/renderscript/Matrix4f.java
index 5d5bf5f..026c9fb 100644
--- a/rs/java/android/renderscript/Matrix4f.java
+++ b/rs/java/android/renderscript/Matrix4f.java
@@ -16,6 +16,7 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
 import java.lang.Math;
 
 
@@ -489,5 +490,6 @@
         }
     }
 
+    @UnsupportedAppUsage
     final float[] mMat;
 }
diff --git a/rs/java/android/renderscript/Mesh.java b/rs/java/android/renderscript/Mesh.java
index 9e4f905..5321dcb 100644
--- a/rs/java/android/renderscript/Mesh.java
+++ b/rs/java/android/renderscript/Mesh.java
@@ -16,6 +16,7 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.Vector;
 
 /**
@@ -49,6 +50,7 @@
         * @deprecated in API 16
         * Vertex data will be rendered as a series of points
         */
+        @UnsupportedAppUsage
         POINT (0),
         /**
         * @deprecated in API 16
@@ -64,6 +66,7 @@
         * @deprecated in API 16
         * Vertices will be rendered as individual triangles
         */
+        @UnsupportedAppUsage
         TRIANGLE (3),
         /**
         * @deprecated in API 16
@@ -111,6 +114,7 @@
     * @return vertex data allocation at the given index
     *
     **/
+    @UnsupportedAppUsage
     public Allocation getVertexAllocation(int slot) {
         return mVertexBuffers[slot];
     }
@@ -424,6 +428,7 @@
         /**
         * @deprecated in API 16
         **/
+        @UnsupportedAppUsage
         public AllocationBuilder(RenderScript rs) {
             mRS = rs;
             mVertexTypeCount = 0;
@@ -458,6 +463,7 @@
         *
         * @return this
         **/
+        @UnsupportedAppUsage
         public AllocationBuilder addVertexAllocation(Allocation a) throws IllegalStateException {
             if (mVertexTypeCount >= mVertexTypes.length) {
                 throw new IllegalStateException("Max vertex types exceeded.");
@@ -479,6 +485,7 @@
         *
         * @return this
         **/
+        @UnsupportedAppUsage
         public AllocationBuilder addIndexSetAllocation(Allocation a, Primitive p) {
             Entry indexType = new Entry();
             indexType.a = a;
@@ -495,6 +502,7 @@
         *
         * @return this
         **/
+        @UnsupportedAppUsage
         public AllocationBuilder addIndexSetType(Primitive p) {
             Entry indexType = new Entry();
             indexType.a = null;
@@ -508,6 +516,7 @@
         * Create a Mesh object from the current state of the builder
         *
         **/
+        @UnsupportedAppUsage
         public Mesh create() {
             mRS.validate();
 
@@ -596,6 +605,7 @@
         *              channels are present in the mesh
         *
         **/
+        @UnsupportedAppUsage
         public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
             mRS = rs;
             mVtxCount = 0;
@@ -652,6 +662,7 @@
         * @return this
         *
         **/
+        @UnsupportedAppUsage
         public TriangleMeshBuilder addVertex(float x, float y) {
             if (mVtxSize != 2) {
                 throw new IllegalStateException("add mistmatch with declared components.");
@@ -757,6 +768,7 @@
         *
         * @return this
         **/
+        @UnsupportedAppUsage
         public TriangleMeshBuilder addTriangle(int idx1, int idx2, int idx3) {
             if((idx1 >= mMaxIndex) || (idx1 < 0) ||
                (idx2 >= mMaxIndex) || (idx2 < 0) ||
@@ -789,6 +801,7 @@
         *                             accessible memory
         *
         **/
+        @UnsupportedAppUsage
         public Mesh create(boolean uploadToBufferObject) {
             Element.Builder b = new Element.Builder(mRS);
             b.add(Element.createVector(mRS,
diff --git a/rs/java/android/renderscript/Program.java b/rs/java/android/renderscript/Program.java
index 772021c..e28d646 100644
--- a/rs/java/android/renderscript/Program.java
+++ b/rs/java/android/renderscript/Program.java
@@ -21,6 +21,7 @@
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.util.Log;
 
@@ -45,6 +46,7 @@
      *
      **/
     public enum TextureType {
+        @UnsupportedAppUsage
         TEXTURE_2D (0),
         TEXTURE_CUBE (1);
 
@@ -199,20 +201,30 @@
 
 
     public static class BaseProgramBuilder {
+        @UnsupportedAppUsage
         RenderScript mRS;
+        @UnsupportedAppUsage
         Element mInputs[];
+        @UnsupportedAppUsage
         Element mOutputs[];
+        @UnsupportedAppUsage
         Type mConstants[];
         Type mTextures[];
         TextureType mTextureTypes[];
         String mTextureNames[];
+        @UnsupportedAppUsage
         int mInputCount;
+        @UnsupportedAppUsage
         int mOutputCount;
+        @UnsupportedAppUsage
         int mConstantCount;
+        @UnsupportedAppUsage
         int mTextureCount;
+        @UnsupportedAppUsage
         String mShader;
 
 
+        @UnsupportedAppUsage
         protected BaseProgramBuilder(RenderScript rs) {
             mRS = rs;
             mInputs = new Element[MAX_INPUT];
diff --git a/rs/java/android/renderscript/ProgramFragment.java b/rs/java/android/renderscript/ProgramFragment.java
index 5f71bd1..3dde9b6 100644
--- a/rs/java/android/renderscript/ProgramFragment.java
+++ b/rs/java/android/renderscript/ProgramFragment.java
@@ -16,6 +16,8 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
+
 
 /**
  * @hide
@@ -50,6 +52,7 @@
          *
          * @param rs Context to which the program will belong.
          */
+        @UnsupportedAppUsage
         public Builder(RenderScript rs) {
             super(rs);
         }
@@ -60,6 +63,7 @@
          *
          * @return  ProgramFragment
          */
+        @UnsupportedAppUsage
         public ProgramFragment create() {
             mRS.validate();
             long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
diff --git a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
index 2b647c76..d05d41d 100644
--- a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -16,6 +16,8 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
+
 
 /**
  * @hide
@@ -102,10 +104,12 @@
             /**
              * @deprecated in API 16
              **/
+            @UnsupportedAppUsage
             REPLACE (1),
             /**
              * @deprecated in API 16
              **/
+            @UnsupportedAppUsage
             MODULATE (2),
             /**
              * @deprecated in API 16
@@ -128,6 +132,7 @@
             /**
              * @deprecated in API 16
              **/
+            @UnsupportedAppUsage
             ALPHA (1),
             /**
              * @deprecated in API 16
@@ -136,10 +141,12 @@
             /**
              * @deprecated in API 16
              **/
+            @UnsupportedAppUsage
             RGB (3),
             /**
              * @deprecated in API 16
              **/
+            @UnsupportedAppUsage
             RGBA (4);
 
             int mID;
@@ -228,6 +235,7 @@
          *
          * @param rs Context to which the program will belong.
          */
+        @UnsupportedAppUsage
         public Builder(RenderScript rs) {
             mRS = rs;
             mSlots = new Slot[MAX_TEXTURE];
@@ -248,6 +256,7 @@
          *
          * @return this
          */
+        @UnsupportedAppUsage
         public Builder setTexture(EnvMode env, Format fmt, int slot)
             throws IllegalArgumentException {
             if((slot < 0) || (slot >= MAX_TEXTURE)) {
@@ -277,6 +286,7 @@
          * fragment shader
          *
          **/
+        @UnsupportedAppUsage
         public Builder setVaryingColor(boolean enable) {
             mVaryingColorEnable = enable;
             return this;
@@ -288,6 +298,7 @@
         * state of the builder.
         *
         */
+        @UnsupportedAppUsage
         public ProgramFragmentFixedFunction create() {
             InternalBuilder sb = new InternalBuilder(mRS);
             mNumTextures = 0;
diff --git a/rs/java/android/renderscript/ProgramRaster.java b/rs/java/android/renderscript/ProgramRaster.java
index 8c7c9aa..33000ac 100644
--- a/rs/java/android/renderscript/ProgramRaster.java
+++ b/rs/java/android/renderscript/ProgramRaster.java
@@ -16,6 +16,8 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
+
 
 /**
  * @hide
@@ -124,6 +126,7 @@
         /**
          * @deprecated in API 16
          */
+        @UnsupportedAppUsage
         public Builder(RenderScript rs) {
             mRS = rs;
             mPointSprite = false;
@@ -133,6 +136,7 @@
         /**
          * @deprecated in API 16
          */
+        @UnsupportedAppUsage
         public Builder setPointSpriteEnabled(boolean enable) {
             mPointSprite = enable;
             return this;
@@ -149,6 +153,7 @@
         /**
          * @deprecated in API 16
          */
+        @UnsupportedAppUsage
         public ProgramRaster create() {
             mRS.validate();
             long id = mRS.nProgramRasterCreate(mPointSprite, mCullMode.mID);
diff --git a/rs/java/android/renderscript/ProgramStore.java b/rs/java/android/renderscript/ProgramStore.java
index c0fa9c4..622fe21 100644
--- a/rs/java/android/renderscript/ProgramStore.java
+++ b/rs/java/android/renderscript/ProgramStore.java
@@ -16,6 +16,8 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
+
 
 /**
  * @hide
@@ -45,11 +47,13 @@
         /**
         * Always drawn
         */
+        @UnsupportedAppUsage
         ALWAYS (0),
         /**
         * Drawn if the incoming depth value is less than that in the
         * depth buffer
         */
+        @UnsupportedAppUsage
         LESS (1),
         /**
         * Drawn if the incoming depth value is less or equal to that in
@@ -93,9 +97,11 @@
     */
     public enum BlendSrcFunc {
         ZERO (0),
+        @UnsupportedAppUsage
         ONE (1),
         DST_COLOR (2),
         ONE_MINUS_DST_COLOR (3),
+        @UnsupportedAppUsage
         SRC_ALPHA (4),
         ONE_MINUS_SRC_ALPHA (5),
         DST_ALPHA (6),
@@ -118,11 +124,14 @@
     *
     */
     public enum BlendDstFunc {
+        @UnsupportedAppUsage
         ZERO (0),
+        @UnsupportedAppUsage
         ONE (1),
         SRC_COLOR (2),
         ONE_MINUS_SRC_COLOR (3),
         SRC_ALPHA (4),
+        @UnsupportedAppUsage
         ONE_MINUS_SRC_ALPHA (5),
         DST_ALPHA (6),
         ONE_MINUS_DST_ALPHA (7);
@@ -299,6 +308,7 @@
     *
     *  @param rs Context to which the program will belong.
     **/
+    @UnsupportedAppUsage
     public static ProgramStore BLEND_ALPHA_DEPTH_NONE(RenderScript rs) {
         if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH == null) {
             ProgramStore.Builder builder = new ProgramStore.Builder(rs);
@@ -328,6 +338,7 @@
         BlendDstFunc mBlendDst;
         boolean mDither;
 
+        @UnsupportedAppUsage
         public Builder(RenderScript rs) {
             mRS = rs;
             mDepthFunc = DepthFunc.ALWAYS;
@@ -347,6 +358,7 @@
         *
         * @return this
         */
+        @UnsupportedAppUsage
         public Builder setDepthFunc(DepthFunc func) {
             mDepthFunc = func;
             return this;
@@ -360,6 +372,7 @@
         *
         * @return this
         */
+        @UnsupportedAppUsage
         public Builder setDepthMaskEnabled(boolean enable) {
             mDepthMask = enable;
             return this;
@@ -394,6 +407,7 @@
         *
         * @return this
         */
+        @UnsupportedAppUsage
         public Builder setBlendFunc(BlendSrcFunc src, BlendDstFunc dst) {
             mBlendSrc = src;
             mBlendDst = dst;
@@ -408,6 +422,7 @@
         *
         * @return this
         */
+        @UnsupportedAppUsage
         public Builder setDitherEnabled(boolean enable) {
             mDither = enable;
             return this;
@@ -416,6 +431,7 @@
         /**
         * Creates a program store from the current state of the builder
         */
+        @UnsupportedAppUsage
         public ProgramStore create() {
             mRS.validate();
             long id = mRS.nProgramStoreCreate(mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA,
diff --git a/rs/java/android/renderscript/ProgramVertex.java b/rs/java/android/renderscript/ProgramVertex.java
index 0d7e2d9c..83d9ea7 100644
--- a/rs/java/android/renderscript/ProgramVertex.java
+++ b/rs/java/android/renderscript/ProgramVertex.java
@@ -38,6 +38,8 @@
  **/
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
+
 
 /**
  * @hide
@@ -90,6 +92,7 @@
          *
          * @param rs Context to which the program will belong.
          */
+        @UnsupportedAppUsage
         public Builder(RenderScript rs) {
             super(rs);
         }
@@ -102,6 +105,7 @@
          *          structure
          * @return  self
          */
+        @UnsupportedAppUsage
         public Builder addInput(Element e) throws IllegalStateException {
             // Should check for consistant and non-conflicting names...
             if(mInputCount >= MAX_INPUT) {
@@ -120,6 +124,7 @@
          *
          * @return  ProgramVertex
          */
+        @UnsupportedAppUsage
         public ProgramVertex create() {
             mRS.validate();
             long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
diff --git a/rs/java/android/renderscript/ProgramVertexFixedFunction.java b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
index 45840ae..579d3bb 100644
--- a/rs/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -16,6 +16,8 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
+
 
 /**
  * @hide
@@ -38,6 +40,7 @@
      *
      * @param va allocation containing fixed function matrices
      */
+    @UnsupportedAppUsage
     public void bindConstants(Constants va) {
         mRS.validate();
         bindConstants(va.getAllocation(), 0);
@@ -118,6 +121,7 @@
          *
          * @param rs Context to which the program will belong.
          */
+        @UnsupportedAppUsage
         public Builder(RenderScript rs) {
             mRS = rs;
         }
@@ -170,6 +174,7 @@
          *
          * @return Fixed function emulation ProgramVertex
          */
+        @UnsupportedAppUsage
         public ProgramVertexFixedFunction create() {
             buildShaderString();
 
@@ -215,6 +220,7 @@
         *
         * @param rs Context to which the allocation will belong.
         **/
+        @UnsupportedAppUsage
         public Constants(RenderScript rs) {
             Type constInputType = ProgramVertexFixedFunction.Builder.getConstantInputType(rs);
             mAlloc = Allocation.createTyped(rs, constInputType);
@@ -268,6 +274,7 @@
         *
         * @param m projection matrix
         */
+        @UnsupportedAppUsage
         public void setProjection(Matrix4f m) {
             mProjection.load(m);
             addToBuffer(PROJECTION_OFFSET*4, m);
diff --git a/rs/java/android/renderscript/RSSurfaceView.java b/rs/java/android/renderscript/RSSurfaceView.java
index 5db72d9..561373c 100644
--- a/rs/java/android/renderscript/RSSurfaceView.java
+++ b/rs/java/android/renderscript/RSSurfaceView.java
@@ -16,6 +16,7 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.SurfaceHolder;
@@ -42,6 +43,7 @@
      * must call {@link android.opengl.GLSurfaceView#setRenderer} to
      * register a renderer.
      */
+    @UnsupportedAppUsage
     public RSSurfaceView(Context context) {
         super(context);
         init();
@@ -54,6 +56,7 @@
      * must call {@link android.opengl.GLSurfaceView#setRenderer} to
      * register a renderer.
      */
+    @UnsupportedAppUsage
     public RSSurfaceView(Context context, AttributeSet attrs) {
         super(context, attrs);
         init();
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 0f22568..4293157 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -22,6 +22,7 @@
 import java.util.ArrayList;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.AssetManager;
 import android.graphics.Bitmap;
@@ -103,6 +104,7 @@
      * Detect the bitness of the VM to allow FieldPacker to do the right thing.
      */
     static native int rsnSystemGetPointerSize();
+    @UnsupportedAppUsage
     static int sPointerSize;
 
     static {
@@ -153,6 +155,7 @@
      * @return Always return 1
      *
      */
+    @UnsupportedAppUsage
     public static long getMinorID() {
         return 1;
     }
@@ -833,6 +836,7 @@
 
     native long rsnScriptCCreate(long con, String resName, String cacheDir,
                                  byte[] script, int length);
+    @UnsupportedAppUsage
     synchronized long nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
         validate();
         return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
@@ -1158,6 +1162,7 @@
      * sendToClient} by scripts from this context.
      *
      */
+    @UnsupportedAppUsage
     RSMessageHandler mMessageCallback = null;
 
     public void setMessageHandler(RSMessageHandler msg) {
@@ -1232,6 +1237,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     void validate() {
         if (mContext == 0) {
             throw new RSInvalidStateException("Calling RS with no Context active.");
@@ -1495,6 +1501,7 @@
      * @param sdkVersion The target SDK Version.
      * @return RenderScript
      */
+    @UnsupportedAppUsage
     public static RenderScript create(Context ctx, int sdkVersion) {
         return create(ctx, sdkVersion, ContextType.NORMAL, CREATE_FLAG_NONE);
     }
@@ -1508,6 +1515,7 @@
      * @param flags The OR of the CREATE_FLAG_* options desired
      * @return RenderScript
      */
+    @UnsupportedAppUsage
     private static RenderScript create(Context ctx, int sdkVersion, ContextType ct, int flags) {
         if (sdkVersion < 23) {
             return internalCreate(ctx, sdkVersion, ct, flags);
diff --git a/rs/java/android/renderscript/RenderScriptCacheDir.java b/rs/java/android/renderscript/RenderScriptCacheDir.java
index 95a9d75..1797bef 100644
--- a/rs/java/android/renderscript/RenderScriptCacheDir.java
+++ b/rs/java/android/renderscript/RenderScriptCacheDir.java
@@ -16,6 +16,7 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.File;
 
 /**
@@ -30,11 +31,13 @@
      * @hide
      * @param cacheDir A directory the current process can write to
      */
+    @UnsupportedAppUsage
     public static void setupDiskCache(File cacheDir) {
         // Defer creation of cache path to nScriptCCreate().
         mCacheDir = cacheDir;
     }
 
+    @UnsupportedAppUsage
     static File mCacheDir;
 
 }
diff --git a/rs/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
index be1f899..6fac83e 100644
--- a/rs/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -16,6 +16,7 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.graphics.SurfaceTexture;
 import android.view.Surface;
@@ -65,6 +66,7 @@
         /**
          * @deprecated in API 16
          */
+        @UnsupportedAppUsage
         public SurfaceConfig() {
         }
 
@@ -132,6 +134,7 @@
          * @param minimum
          * @param preferred
          */
+        @UnsupportedAppUsage
         public void setDepth(int minimum, int preferred) {
             validateRange(minimum, preferred, 0, 24);
             mDepthMin = minimum;
@@ -169,6 +172,7 @@
      * @param ctx The context.
      * @param sc The desired format of the primary rendering surface.
      */
+    @UnsupportedAppUsage
     public RenderScriptGL(Context ctx, SurfaceConfig sc) {
         super(ctx);
         mSurfaceConfig = new SurfaceConfig(sc);
@@ -202,6 +206,7 @@
      * @param h
      * @param sur
      */
+    @UnsupportedAppUsage
     public void setSurface(SurfaceHolder sur, int w, int h) {
         validate();
         Surface s = null;
@@ -281,6 +286,7 @@
      *
      * @param s Graphics script to process rendering requests.
      */
+    @UnsupportedAppUsage
     public void bindRootScript(Script s) {
         validate();
         nContextBindRootScript((int)safeID(s));
@@ -293,6 +299,7 @@
      *
      * @param p
      */
+    @UnsupportedAppUsage
     public void bindProgramStore(ProgramStore p) {
         validate();
         nContextBindProgramStore((int)safeID(p));
@@ -317,6 +324,7 @@
      *
      * @param p
      */
+    @UnsupportedAppUsage
     public void bindProgramRaster(ProgramRaster p) {
         validate();
         nContextBindProgramRaster((int)safeID(p));
@@ -329,6 +337,7 @@
      *
      * @param p
      */
+    @UnsupportedAppUsage
     public void bindProgramVertex(ProgramVertex p) {
         validate();
         nContextBindProgramVertex((int)safeID(p));
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index d0d9a11..9ad9aea 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -16,6 +16,7 @@
 
 package android.renderscript;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.SparseArray;
 
 /**
@@ -475,8 +476,10 @@
      *
      */
     public static class Builder {
+        @UnsupportedAppUsage
         RenderScript mRS;
 
+        @UnsupportedAppUsage
         Builder(RenderScript rs) {
             mRS = rs;
         }
diff --git a/sax/tests/saxtests/src/android/sax/ExpatPerformanceTest.java b/sax/tests/saxtests/src/android/sax/ExpatPerformanceTest.java
deleted file mode 100644
index 892c490..0000000
--- a/sax/tests/saxtests/src/android/sax/ExpatPerformanceTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.sax;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.util.Xml;
-import org.kxml2.io.KXmlParser;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import com.android.frameworks.saxtests.R;
-
-public class ExpatPerformanceTest extends AndroidTestCase {
-
-    private static final String TAG = ExpatPerformanceTest.class.getSimpleName();
-
-    private byte[] mXmlBytes;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        InputStream in = mContext.getResources().openRawResource(R.raw.youtube);
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        byte[] buffer = new byte[1024];
-        int length;
-        while ((length = in.read(buffer)) != -1) {
-            out.write(buffer, 0, length);
-        }
-        mXmlBytes = out.toByteArray();
-
-        Log.i("***", "File size: " + (mXmlBytes.length / 1024) + "k");
-    }
-
-    @LargeTest
-    public void testPerformance() throws Exception {
-//        try {
-//            Debug.startMethodTracing("expat3");
-//        for (int i = 0; i < 1; i++) {
-            runJavaPullParser();
-            runSax();
-            runExpatPullParser();
-//        }
-//    } finally {
-//            Debug.stopMethodTracing();
-//        }
-    }
-
-    private InputStream newInputStream() {
-        return new ByteArrayInputStream(mXmlBytes);
-    }
-
-    private void runSax() throws IOException, SAXException {
-        long start = System.currentTimeMillis();
-        Xml.parse(newInputStream(), Xml.Encoding.UTF_8, new DefaultHandler());
-        long elapsed = System.currentTimeMillis() - start;
-        Log.i(TAG, "expat SAX: " + elapsed + "ms");
-    }
-
-    private void runExpatPullParser() throws XmlPullParserException, IOException {
-        long start = System.currentTimeMillis();
-        XmlPullParser pullParser = Xml.newPullParser();
-        pullParser.setInput(newInputStream(), "UTF-8");
-        withPullParser(pullParser);
-        long elapsed = System.currentTimeMillis() - start;
-        Log.i(TAG, "expat pull: " + elapsed + "ms");
-    }
-
-    private void runJavaPullParser() throws XmlPullParserException, IOException {
-        XmlPullParser pullParser;
-        long start = System.currentTimeMillis();
-        pullParser = new KXmlParser();
-        pullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
-        pullParser.setInput(newInputStream(), "UTF-8");
-        withPullParser(pullParser);
-        long elapsed = System.currentTimeMillis() - start;
-        Log.i(TAG, "java pull parser: " + elapsed + "ms");
-    }
-
-    private static void withPullParser(XmlPullParser pullParser)
-            throws IOException, XmlPullParserException {
-        int eventType = pullParser.next();
-        while (eventType != XmlPullParser.END_DOCUMENT) {
-            switch (eventType) {
-                case XmlPullParser.START_TAG:
-                    pullParser.getName();
-//                        int nattrs = pullParser.getAttributeCount();
-//                        for (int i = 0; i < nattrs; ++i) {
-//                            pullParser.getAttributeName(i);
-//                            pullParser.getAttributeValue(i);
-//                        }
-                    break;
-                case XmlPullParser.END_TAG:
-                    pullParser.getName();
-                    break;
-                case XmlPullParser.TEXT:
-                    pullParser.getText();
-                    break;
-            }
-            eventType = pullParser.next();
-        }
-    }
-}
diff --git a/services/Android.bp b/services/Android.bp
index d125adc..bea51be 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -2,6 +2,7 @@
 // ============================================================
 java_library {
     name: "services",
+    installable: true,
 
     dex_preopt: {
         app_image: true,
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 28aa984..46c515f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -860,7 +860,10 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            return mSystemSupport.getMagnificationController().reset(animate);
+            MagnificationController magnificationController =
+                    mSystemSupport.getMagnificationController();
+            return (magnificationController.reset(animate)
+                    || !magnificationController.isMagnifying());
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
index b95d2e6..d767011 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
@@ -145,7 +145,7 @@
 
     private final Listener mListener;
     private final Context mContext;  // Retained for on-demand construction of GestureDetector.
-    protected GestureDetector mGestureDetector;  // Double-tap detector. Visible for test.
+    private final GestureDetector mGestureDetector;  // Double-tap detector.
 
     // Indicates that a single tap has occurred.
     private boolean mFirstTapDetected;
@@ -216,10 +216,34 @@
     // cancelled.
     private static final long CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS = 300;
 
+    /**
+     * Construct the gesture detector for {@link TouchExplorer}.
+     *
+     * @see #AccessibilityGestureDetector(Context, Listener, GestureDetector)
+     */
     AccessibilityGestureDetector(Context context, Listener listener) {
+        this(context, listener, null);
+    }
+
+    /**
+     * Construct the gesture detector for {@link TouchExplorer}.
+     *
+     * @param context A context handle for accessing resources.
+     * @param listener A listener to callback with gesture state or information.
+     * @param detector The gesture detector to handle touch event. If null the default one created
+     *                 in place, or for testing purpose.
+     */
+    AccessibilityGestureDetector(Context context, Listener listener, GestureDetector detector) {
         mListener = listener;
         mContext = context;
 
+        // Break the circular dependency between constructors and let the class to be testable
+        if (detector == null) {
+            mGestureDetector = new GestureDetector(context, this);
+        } else {
+            mGestureDetector = detector;
+        }
+        mGestureDetector.setOnDoubleTapListener(this);
         mGestureDetectionThreshold = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1,
                 context.getResources().getDisplayMetrics()) * GESTURE_CONFIRM_MM;
 
@@ -235,32 +259,23 @@
      * callback on mListener is called, and the return value of the callback is
      * passed to the caller.
      *
-     * @param event The raw motion event.  It's important that this be the raw
+     * @param event The transformed motion event to be handled.
+     * @param rawEvent The raw motion event.  It's important that this be the raw
      * event, before any transformations have been applied, so that measurements
      * can be made in physical units.
      * @param policyFlags Policy flags for the event.
      *
      * @return true if the event is consumed, else false
      */
-    public boolean onMotionEvent(MotionEvent event, int policyFlags) {
-
-        // Construct GestureDetector double-tap detector on demand, so that testable sub-class
-        // can use mock GestureDetector.
-        // TODO: Break the circular dependency between GestureDetector's constructor and
-        // AccessibilityGestureDetector's constructor. Construct GestureDetector in TouchExplorer,
-        // using a GestureDetector listener owned by TouchExplorer, which passes double-tap state
-        // information to AccessibilityGestureDetector.
-        if (mGestureDetector == null) {
-            mGestureDetector = new GestureDetector(mContext, this);
-            mGestureDetector.setOnDoubleTapListener(this);
-        }
-
-        final float x = event.getX();
-        final float y = event.getY();
-        final long time = event.getEventTime();
+    public boolean onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        // The accessibility gesture detector is interested in the movements in physical space,
+        // so it uses the rawEvent to ignore magnification and other transformations.
+        final float x = rawEvent.getX();
+        final float y = rawEvent.getY();
+        final long time = rawEvent.getEventTime();
 
         mPolicyFlags = policyFlags;
-        switch (event.getActionMasked()) {
+        switch (rawEvent.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
                 mDoubleTapDetected = false;
                 mSecondFingerDoubleTap = false;
@@ -311,7 +326,7 @@
                         // timeout, cancel gesture detection.
                         if (timeDelta > threshold) {
                             cancelGesture();
-                            return mListener.onGestureCancelled(event, policyFlags);
+                            return mListener.onGestureCancelled(rawEvent, policyFlags);
                         }
                     }
 
@@ -327,7 +342,7 @@
 
             case MotionEvent.ACTION_UP:
                 if (mDoubleTapDetected) {
-                    return finishDoubleTap(event, policyFlags);
+                    return finishDoubleTap(rawEvent, policyFlags);
                 }
                 if (mGestureStarted) {
                     final float dX = Math.abs(x - mPreviousGestureX);
@@ -335,7 +350,7 @@
                     if (dX >= mMinPixelsBetweenSamplesX || dY >= mMinPixelsBetweenSamplesY) {
                         mStrokeBuffer.add(new GesturePoint(x, y, time));
                     }
-                    return recognizeGesture(event, policyFlags);
+                    return recognizeGesture(rawEvent, policyFlags);
                 }
                 break;
 
@@ -344,7 +359,7 @@
                 // recognizing a gesture.
                 cancelGesture();
 
-                if (event.getPointerCount() == 2) {
+                if (rawEvent.getPointerCount() == 2) {
                     // If this was the second finger, attempt to recognize double
                     // taps on it.
                     mSecondFingerDoubleTap = true;
@@ -360,7 +375,7 @@
                 // If we're detecting taps on the second finger, see if we
                 // should finish the double tap.
                 if (mSecondFingerDoubleTap && mDoubleTapDetected) {
-                    return finishDoubleTap(event, policyFlags);
+                    return finishDoubleTap(rawEvent, policyFlags);
                 }
                 break;
 
@@ -372,7 +387,7 @@
         // If we're detecting taps on the second finger, map events from the
         // finger to the first finger.
         if (mSecondFingerDoubleTap) {
-            MotionEvent newEvent = mapSecondPointerToFirstPointer(event);
+            MotionEvent newEvent = mapSecondPointerToFirstPointer(rawEvent);
             if (newEvent == null) {
                 return false;
             }
@@ -385,7 +400,7 @@
             return false;
         }
 
-        // Pass the event on to the standard gesture detector.
+        // Pass the transformed event on to the standard gesture detector.
         return mGestureDetector.onTouchEvent(event);
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 11b2343..cf08681 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -22,10 +22,8 @@
 import android.util.DebugUtils;
 import android.util.ExceptionUtils;
 import android.util.Log;
-import android.util.Pools.SimplePool;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
-import android.view.Choreographer;
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.InputFilter;
@@ -104,31 +102,12 @@
             | FLAG_FEATURE_AUTOCLICK | FLAG_FEATURE_TOUCH_EXPLORATION
             | FLAG_FEATURE_SCREEN_MAGNIFIER | FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER;
 
-    private final Runnable mProcessBatchedEventsRunnable = new Runnable() {
-        @Override
-        public void run() {
-            final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
-            if (DEBUG) {
-                Slog.i(TAG, "Begin batch processing for frame: " + frameTimeNanos);
-            }
-            processBatchedEvents(frameTimeNanos);
-            if (DEBUG) {
-                Slog.i(TAG, "End batch processing.");
-            }
-            if (mEventQueue != null) {
-                scheduleProcessBatchedEvents();
-            }
-        }
-    };
-
     private final Context mContext;
 
     private final PowerManager mPm;
 
     private final AccessibilityManagerService mAms;
 
-    private final Choreographer mChoreographer;
-
     private boolean mInstalled;
 
     private int mUserId;
@@ -147,8 +126,6 @@
 
     private EventStreamTransformation mEventHandler;
 
-    private MotionEventHolder mEventQueue;
-
     private EventStreamState mMouseStreamState;
 
     private EventStreamState mTouchScreenStreamState;
@@ -160,7 +137,6 @@
         mContext = context;
         mAms = service;
         mPm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mChoreographer = Choreographer.getInstance();
     }
 
     @Override
@@ -274,7 +250,7 @@
             return;
         }
 
-        batchMotionEvent(event, policyFlags);
+        handleMotionEvent(event, policyFlags);
     }
 
     private void processKeyEvent(EventStreamState state, KeyEvent event, int policyFlags) {
@@ -285,68 +261,14 @@
         mEventHandler.onKeyEvent(event, policyFlags);
     }
 
-    private void scheduleProcessBatchedEvents() {
-        mChoreographer.postCallback(Choreographer.CALLBACK_INPUT,
-                mProcessBatchedEventsRunnable, null);
-    }
-
-    private void batchMotionEvent(MotionEvent event, int policyFlags) {
-        if (DEBUG) {
-            Slog.i(TAG, "Batching event: " + event + ", policyFlags: " + policyFlags);
-        }
-        if (mEventQueue == null) {
-            mEventQueue = MotionEventHolder.obtain(event, policyFlags);
-            scheduleProcessBatchedEvents();
-            return;
-        }
-        if (mEventQueue.event.addBatch(event)) {
-            return;
-        }
-        MotionEventHolder holder = MotionEventHolder.obtain(event, policyFlags);
-        holder.next = mEventQueue;
-        mEventQueue.previous = holder;
-        mEventQueue = holder;
-    }
-
-    private void processBatchedEvents(long frameNanos) {
-        MotionEventHolder current = mEventQueue;
-        if (current == null) {
-            return;
-        }
-        while (current.next != null) {
-            current = current.next;
-        }
-        while (true) {
-            if (current == null) {
-                mEventQueue = null;
-                break;
-            }
-            if (current.event.getEventTimeNano() >= frameNanos) {
-                // Finished with this choreographer frame. Do the rest on the next one.
-                current.next = null;
-                break;
-            }
-            handleMotionEvent(current.event, current.policyFlags);
-            MotionEventHolder prior = current;
-            current = current.previous;
-            prior.recycle();
-        }
-    }
-
     private void handleMotionEvent(MotionEvent event, int policyFlags) {
         if (DEBUG) {
-            Slog.i(TAG, "Handling batched event: " + event + ", policyFlags: " + policyFlags);
+            Slog.i(TAG, "Handling motion event: " + event + ", policyFlags: " + policyFlags);
         }
-        // Since we do batch processing it is possible that by the time the
-        // next batch is processed the event handle had been set to null.
-        if (mEventHandler != null) {
-            mPm.userActivity(event.getEventTime(), false);
-            MotionEvent transformedEvent = MotionEvent.obtain(event);
-            mEventHandler.onMotionEvent(transformedEvent, event, policyFlags);
-            transformedEvent.recycle();
-        } else {
-            if (DEBUG) Slog.d(TAG, "mEventHandler == null for " + event);
-        }
+        mPm.userActivity(event.getEventTime(), false);
+        MotionEvent transformedEvent = MotionEvent.obtain(event);
+        mEventHandler.onMotionEvent(transformedEvent, event, policyFlags);
+        transformedEvent.recycle();
     }
 
     @Override
@@ -469,9 +391,6 @@
     }
 
     private void disableFeatures() {
-        // Give the features a chance to process any batched events so we'll keep a consistent
-        // event stream
-        processBatchedEvents(Long.MAX_VALUE);
         if (mMotionEventInjector != null) {
             mAms.setMotionEventInjector(null);
             mMotionEventInjector.onDestroy();
@@ -515,36 +434,6 @@
         /* ignore */
     }
 
-    private static class MotionEventHolder {
-        private static final int MAX_POOL_SIZE = 32;
-        private static final SimplePool<MotionEventHolder> sPool =
-                new SimplePool<MotionEventHolder>(MAX_POOL_SIZE);
-
-        public int policyFlags;
-        public MotionEvent event;
-        public MotionEventHolder next;
-        public MotionEventHolder previous;
-
-        public static MotionEventHolder obtain(MotionEvent event, int policyFlags) {
-            MotionEventHolder holder = sPool.acquire();
-            if (holder == null) {
-                holder = new MotionEventHolder();
-            }
-            holder.event = MotionEvent.obtain(event);
-            holder.policyFlags = policyFlags;
-            return holder;
-        }
-
-        public void recycle() {
-            event.recycle();
-            event = null;
-            policyFlags = 0;
-            next = null;
-            previous = null;
-            sPool.release(this);
-        }
-    }
-
     /**
      * Keeps state of event streams observed for an input device with a certain source.
      * Provides information about whether motion and key events should be processed by accessibility
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 376d16b..6be9550 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -16,12 +16,18 @@
 
 package com.android.server.accessibility;
 
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_MASK;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
 import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_WITH_HARD_KEYBOARD;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN;
 
 import android.Manifest;
 import android.accessibilityservice.AccessibilityService;
@@ -109,6 +115,7 @@
 import com.android.internal.util.IntPair;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
+import com.android.server.SystemService;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -260,6 +267,25 @@
         return getUserStateLocked(mCurrentUserId);
     }
 
+    public static final class Lifecycle extends SystemService {
+        private final AccessibilityManagerService mService;
+
+        public Lifecycle(Context context) {
+            super(context);
+            mService = new AccessibilityManagerService(context);
+        }
+
+        @Override
+        public void onStart() {
+            publishBinderService(Context.ACCESSIBILITY_SERVICE, mService);
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            mService.onBootPhase(phase);
+        }
+    }
+
     /**
      * Creates a new instance.
      *
@@ -296,6 +322,14 @@
         return mFingerprintGestureDispatcher;
     }
 
+    private void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+            if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
+                mAppWidgetService = LocalServices.getService(AppWidgetManagerInternal.class);
+            }
+        }
+    }
+
     private UserState getUserState(int userId) {
         synchronized (mLock) {
             return getUserStateLocked(userId);
@@ -667,6 +701,7 @@
     public int addAccessibilityInteractionConnection(IWindow windowToken,
             IAccessibilityInteractionConnection connection, String packageName,
             int userId) throws RemoteException {
+        final int windowId;
         synchronized (mLock) {
             // We treat calls from a profile as if made by its parent as profiles
             // share the accessibility state of the parent. The call below
@@ -679,7 +714,7 @@
             packageName = mSecurityPolicy.resolveValidReportedPackageLocked(
                     packageName, UserHandle.getCallingAppId(), resolvedUserId);
 
-            final int windowId = sNextWindowId++;
+            windowId = sNextWindowId++;
             // If the window is from a process that runs across users such as
             // the system UI or the system we add it to the global state that
             // is shared across users.
@@ -707,8 +742,10 @@
                             + " and  token: " + windowToken.asBinder());
                 }
             }
-            return windowId;
         }
+        WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class);
+        wm.computeWindowsForAccessibility();
+        return windowId;
     }
 
     @Override
@@ -1530,8 +1567,9 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
+            final String settingValue = builder.toString();
             Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                    settingName, builder.toString(), userId);
+                    settingName, TextUtils.isEmpty(settingValue) ? null : settingValue, userId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -1779,7 +1817,6 @@
         updateDisplayDaltonizerLocked(userState);
         updateDisplayInversionLocked(userState);
         updateMagnificationLocked(userState);
-        updateSoftKeyboardShowModeLocked(userState);
         scheduleUpdateFingerprintGestureHandling(userState);
         scheduleUpdateInputFilter(userState);
         scheduleUpdateClientsIfNeededLocked(userState);
@@ -1973,18 +2010,6 @@
         return false;
     }
 
-    private boolean readSoftKeyboardShowModeChangedLocked(UserState userState) {
-        final int softKeyboardShowMode = Settings.Secure.getIntForUser(
-                mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0,
-                userState.mUserId);
-        if (softKeyboardShowMode != userState.mSoftKeyboardShowMode) {
-            userState.mSoftKeyboardShowMode = softKeyboardShowMode;
-            return true;
-        }
-        return false;
-    }
-
     private void updateTouchExplorationLocked(UserState userState) {
         boolean enabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
         final int serviceCount = userState.mBoundServices.size();
@@ -2183,34 +2208,6 @@
         return false;
     }
 
-    private void updateSoftKeyboardShowModeLocked(UserState userState) {
-        final int userId = userState.mUserId;
-        // Only check whether we need to reset the soft keyboard mode if it is not set to the
-        // default.
-        if ((userId == mCurrentUserId) && (userState.mSoftKeyboardShowMode != 0)) {
-            // Check whether the last AccessibilityService that changed the soft keyboard mode to
-            // something other than the default is still enabled and, if not, remove flag and
-            // reset to the default soft keyboard behavior.
-            boolean serviceChangingSoftKeyboardModeIsEnabled =
-                    userState.mEnabledServices.contains(userState.mServiceChangingSoftKeyboardMode);
-
-            if (!serviceChangingSoftKeyboardModeIsEnabled) {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                            Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
-                            0,
-                            userState.mUserId);
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-                userState.mSoftKeyboardShowMode = 0;
-                userState.mServiceChangingSoftKeyboardMode = null;
-                notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
-            }
-        }
-    }
-
     private void updateFingerprintGestureHandling(UserState userState) {
         final List<AccessibilityServiceConnection> services;
         synchronized (mLock) {
@@ -2445,6 +2442,15 @@
         }
     }
 
+    private void putSecureIntForUser(String key, int value, int userid) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userid);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     class RemoteAccessibilityConnection implements DeathRecipient {
         private final int mUid;
         private final String mPackageName;
@@ -2684,16 +2690,6 @@
         }
     }
 
-    private AppWidgetManagerInternal getAppWidgetManager() {
-        synchronized (mLock) {
-            if (mAppWidgetService == null
-                    && mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
-                mAppWidgetService = LocalServices.getService(AppWidgetManagerInternal.class);
-            }
-            return mAppWidgetService;
-        }
-    }
-
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
             FileDescriptor err, String[] args, ShellCallback callback,
@@ -3022,8 +3018,7 @@
                 return packageName.toString();
             }
             // Appwidget hosts get to pass packages for widgets they host
-            final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager();
-            if (appWidgetManager != null && ArrayUtils.contains(appWidgetManager
+            if (mAppWidgetService != null && ArrayUtils.contains(mAppWidgetService
                             .getHostedWidgetPackages(resolvedUid), packageNameStr)) {
                 return packageName.toString();
             }
@@ -3051,9 +3046,8 @@
             // IMPORTANT: The target package is already vetted to be in the target UID
             String[] uidPackages = new String[]{targetPackage};
             // Appwidget hosts get to pass packages for widgets they host
-            final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager();
-            if (appWidgetManager != null) {
-                final ArraySet<String> widgetPackages = appWidgetManager
+            if (mAppWidgetService != null) {
+                final ArraySet<String> widgetPackages = mAppWidgetService
                         .getHostedWidgetPackages(targetUid);
                 if (widgetPackages != null && !widgetPackages.isEmpty()) {
                     final String[] validPackages = new String[uidPackages.length
@@ -3667,7 +3661,7 @@
 
         public int mLastSentClientState = -1;
 
-        public int mSoftKeyboardShowMode = 0;
+        private int mSoftKeyboardShowMode = 0;
 
         public boolean mIsNavBarMagnificationAssignedToAccessibilityButton;
         public ComponentName mServiceAssignedToAccessibilityButton;
@@ -3728,7 +3722,6 @@
             mServiceAssignedToAccessibilityButton = null;
             mIsNavBarMagnificationAssignedToAccessibilityButton = false;
             mIsAutoclickEnabled = false;
-            mSoftKeyboardShowMode = 0;
         }
 
         public void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
@@ -3750,6 +3743,11 @@
         public void removeServiceLocked(AccessibilityServiceConnection serviceConnection) {
             mBoundServices.remove(serviceConnection);
             serviceConnection.onRemoved();
+            if ((mServiceChangingSoftKeyboardMode != null)
+                    && (mServiceChangingSoftKeyboardMode.equals(
+                            serviceConnection.getServiceInfo().getComponentName()))) {
+                setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
+            }
             // It may be possible to bind a service twice, which confuses the map. Rebuild the map
             // to make sure we can still reach a service
             mComponentNameToServiceMap.clear();
@@ -3776,6 +3774,134 @@
         public Set<ComponentName> getBindingServicesLocked() {
             return mBindingServices;
         }
+
+        public int getSoftKeyboardShowMode() {
+            return mSoftKeyboardShowMode;
+        }
+
+        /**
+         * Set the soft keyboard mode. This mode is a bit odd, as it spans multiple settings.
+         * The ACCESSIBILITY_SOFT_KEYBOARD_MODE setting can be checked by the rest of the system
+         * to see if it should suppress showing the IME. The SHOW_IME_WITH_HARD_KEYBOARD setting
+         * setting can be changed by the user, and prevents the system from suppressing the soft
+         * keyboard when the hard keyboard is connected. The hard keyboard setting needs to defer
+         * to the user's preference, if they have supplied one.
+         *
+         * @param newMode The new mode
+         * @param requester The service requesting the change, so we can undo it when the
+         *                  service stops. Set to null if something other than a service is forcing
+         *                  the change.
+         *
+         * @return Whether or not the soft keyboard mode equals the new mode after the call
+         */
+        public boolean setSoftKeyboardModeLocked(int newMode, @Nullable ComponentName requester) {
+            if ((newMode != SHOW_MODE_AUTO) && (newMode != SHOW_MODE_HIDDEN)
+                    && (newMode != SHOW_MODE_WITH_HARD_KEYBOARD))
+            {
+                Slog.w(LOG_TAG, "Invalid soft keyboard mode");
+                return false;
+            }
+            if (mSoftKeyboardShowMode == newMode) return true;
+
+            if (newMode == SHOW_MODE_WITH_HARD_KEYBOARD) {
+                if (hasUserOverriddenHardKeyboardSettingLocked()) {
+                    // The user has specified a default for this setting
+                    return false;
+                }
+                // Save the original value. But don't do this if the value in settings is already
+                // the new mode. That happens when we start up after a reboot, and we don't want
+                // to overwrite the value we had from when we first started controlling the setting.
+                if (getSoftKeyboardValueFromSettings() != SHOW_MODE_WITH_HARD_KEYBOARD) {
+                    setOriginalHardKeyboardValue(
+                            Settings.Secure.getInt(mContext.getContentResolver(),
+                                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0);
+                }
+                putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 1, mUserId);
+            } else if (mSoftKeyboardShowMode == SHOW_MODE_WITH_HARD_KEYBOARD) {
+                putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
+                        getOriginalHardKeyboardValue() ? 1 : 0, mUserId);
+            }
+
+            saveSoftKeyboardValueToSettings(newMode);
+            mSoftKeyboardShowMode = newMode;
+            mServiceChangingSoftKeyboardMode = requester;
+            notifySoftKeyboardShowModeChangedLocked(mSoftKeyboardShowMode);
+            return true;
+        }
+
+        /**
+         * If the settings are inconsistent with the internal state, make the internal state
+         * match the settings.
+         */
+        public void reconcileSoftKeyboardModeWithSettingsLocked() {
+            final ContentResolver cr = mContext.getContentResolver();
+            final boolean showWithHardKeyboardSettings =
+                    Settings.Secure.getInt(cr, Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0;
+            if (mSoftKeyboardShowMode == SHOW_MODE_WITH_HARD_KEYBOARD) {
+                if (!showWithHardKeyboardSettings) {
+                    // The user has overridden the setting. Respect that and prevent further changes
+                    // to this behavior.
+                    setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
+                    setUserOverridesHardKeyboardSettingLocked();
+                }
+            }
+
+            // If the setting and the internal state are out of sync, set both to default
+            if (getSoftKeyboardValueFromSettings() != mSoftKeyboardShowMode)
+            {
+                Slog.e(LOG_TAG,
+                        "Show IME setting inconsistent with internal state. Overwriting");
+                setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
+                putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                        SHOW_MODE_AUTO, mUserId);
+            }
+        }
+
+        private void setUserOverridesHardKeyboardSettingLocked() {
+            final int softKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
+            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                    softKeyboardSetting | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN,
+                    mUserId);
+        }
+
+        private boolean hasUserOverriddenHardKeyboardSettingLocked() {
+            final int softKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
+            return (softKeyboardSetting & SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN)
+                    != 0;
+        }
+
+        private void setOriginalHardKeyboardValue(boolean originalHardKeyboardValue) {
+            final int oldSoftKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
+            final int newSoftKeyboardSetting = oldSoftKeyboardSetting
+                    & (~SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE)
+                    | ((originalHardKeyboardValue) ? SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE : 0);
+            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                    newSoftKeyboardSetting, mUserId);
+        }
+
+        private void saveSoftKeyboardValueToSettings(int softKeyboardShowMode) {
+            final int oldSoftKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
+            final int newSoftKeyboardSetting = oldSoftKeyboardSetting & (~SHOW_MODE_MASK)
+                    | softKeyboardShowMode;
+            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                    newSoftKeyboardSetting, mUserId);
+        }
+
+        private int getSoftKeyboardValueFromSettings() {
+            return Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                    SHOW_MODE_AUTO) & SHOW_MODE_MASK;
+        }
+
+        private boolean getOriginalHardKeyboardValue() {
+            return (Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0)
+                    & SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE) != 0;
+        }
     }
 
     private final class AccessibilityContentObserver extends ContentObserver {
@@ -3813,6 +3939,9 @@
         private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
 
+        private final Uri mShowImeWithHardKeyboardUri = Settings.Secure.getUriFor(
+                Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
+
         private final Uri mAccessibilityShortcutServiceIdUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
 
@@ -3848,6 +3977,8 @@
             contentResolver.registerContentObserver(
                     mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
+                    mShowImeWithHardKeyboardUri, false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(
                     mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
                     mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL);
@@ -3890,11 +4021,9 @@
                     if (readHighTextContrastEnabledSettingLocked(userState)) {
                         onUserStateChangedLocked(userState);
                     }
-                } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) {
-                    if (readSoftKeyboardShowModeChangedLocked(userState)) {
-                        notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
-                        onUserStateChangedLocked(userState);
-                    }
+                } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)
+                        || mShowImeWithHardKeyboardUri.equals(uri)) {
+                    userState.reconcileSoftKeyboardModeWithSettingsLocked();
                 } else if (mAccessibilityShortcutServiceIdUri.equals(uri)) {
                     if (readAccessibilityShortcutSettingLocked(userState)) {
                         onUserStateChangedLocked(userState);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 105df92..e0eb269 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -111,6 +111,7 @@
         UserState userState = mUserStateWeakReference.get();
         if (userState == null) return;
         userState.removeServiceLocked(this);
+        mSystemSupport.getMagnificationController().resetIfNeeded(mId);
         resetLocked();
     }
 
@@ -218,26 +219,20 @@
             if (!isCalledForCurrentUserLocked()) {
                 return false;
             }
+            final UserState userState = mUserStateWeakReference.get();
+            if (userState == null) return false;
+            return userState.setSoftKeyboardModeLocked(showMode, mComponentName);
         }
-        UserState userState = mUserStateWeakReference.get();
-        if (userState == null) return false;
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            // Keep track of the last service to request a non-default show mode. The show mode
-            // should be restored to default should this service be disabled.
-            userState.mServiceChangingSoftKeyboardMode = (showMode == SHOW_MODE_AUTO)
-                    ? null : mComponentName;
-
-            Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode,
-                    userState.mUserId);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-        return true;
     }
 
     @Override
+    public int getSoftKeyboardShowMode() {
+        final UserState userState = mUserStateWeakReference.get();
+        return (userState != null) ? userState.getSoftKeyboardShowMode() : 0;
+    }
+
+
+    @Override
     public boolean isAccessibilityButtonAvailable() {
         synchronized (mLock) {
             if (!isCalledForCurrentUserLocked()) {
@@ -258,13 +253,12 @@
                 return;
             }
             mWasConnectedAndDied = true;
+            mSystemSupport.getKeyEventDispatcher().flush(this);
             UserState userState = mUserStateWeakReference.get();
             if (userState != null) {
                 userState.serviceDisconnectedLocked(this);
             }
-            if (mId == mSystemSupport.getMagnificationController().getIdOfLastServiceToMagnify()) {
-                mSystemSupport.getMagnificationController().resetIfNeeded(true);
-            }
+            mSystemSupport.getMagnificationController().resetIfNeeded(mId);
             mSystemSupport.onClientChange(false);
         }
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index b697434..b938f3b 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -722,6 +722,19 @@
         }
     }
 
+    /**
+     * Resets magnification if last magnifying service is disabled.
+     *
+     * @param connectionId the connection ID be disabled.
+     * @return {@code true} on success, {@code false} on failure
+     */
+    boolean resetIfNeeded(int connectionId) {
+        if (mIdOfLastServiceToMagnify == connectionId) {
+            return resetIfNeeded(true /*animate*/);
+        }
+        return false;
+    }
+
     void setForceShowMagnifiableBounds(boolean show) {
         if (mRegistered) {
             mWindowManager.setForceShowMagnifiableBounds(show);
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
index 6c6dd5b..8d691ff 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
@@ -247,6 +247,9 @@
         if (mScreenStateReceiver != null) {
             mScreenStateReceiver.unregister();
         }
+        // Check if need to reset when MagnificationGestureHandler is the last magnifying service.
+        mMagnificationController.resetIfNeeded(
+                AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
         clearAndTransitionToStateDetecting();
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 84a8d45..371f932 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -165,8 +165,9 @@
     /**
      * Creates a new instance.
      *
-     * @param inputFilter The input filter associated with this explorer.
      * @param context A context handle for accessing resources.
+     * @param service The service to notify touch interaction and gesture completed and to perform
+     *                action.
      */
     public TouchExplorer(Context context, AccessibilityManagerService service) {
         mContext = context;
@@ -268,10 +269,7 @@
 
         mReceivedPointerTracker.onMotionEvent(rawEvent);
 
-        // The motion detector is interested in the movements in physical space,
-        // so it uses the rawEvent to ignore magnification and other
-        // transformations.
-        if (mGestureDetector.onMotionEvent(rawEvent, policyFlags)) {
+        if (mGestureDetector.onMotionEvent(event, rawEvent, policyFlags)) {
             // Event was handled by the gesture detector.
             return;
         }
@@ -378,6 +376,7 @@
             return false;
         }
 
+        mAms.onTouchInteractionEnd();
         // Remove pending event deliveries.
         mSendHoverEnterAndMoveDelayed.cancel();
         mSendHoverExitDelayed.cancel();
@@ -385,9 +384,9 @@
         if (mSendTouchExplorationEndDelayed.isPending()) {
             mSendTouchExplorationEndDelayed.forceSendAndRemove();
         }
-        if (mSendTouchInteractionEndDelayed.isPending()) {
-            mSendTouchInteractionEndDelayed.forceSendAndRemove();
-        }
+
+        // Announce the end of a new touch interaction.
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
 
         // Try to use the standard accessibility API to click
         if (mAms.performActionOnAccessibilityFocusedItem(
@@ -490,20 +489,25 @@
             case MotionEvent.ACTION_DOWN: {
                 mAms.onTouchInteractionStart();
 
-                sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
-
                 // If we still have not notified the user for the last
                 // touch, we figure out what to do. If were waiting
                 // we resent the delayed callback and wait again.
                 mSendHoverEnterAndMoveDelayed.cancel();
                 mSendHoverExitDelayed.cancel();
 
-                if (mSendTouchExplorationEndDelayed.isPending()) {
-                    mSendTouchExplorationEndDelayed.forceSendAndRemove();
+                // If a touch exploration gesture is in progress send events for its end.
+                if(mTouchExplorationInProgress) {
+                    sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
                 }
 
-                if (mSendTouchInteractionEndDelayed.isPending()) {
+                // Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double tap.
+                if (!mGestureDetector.firstTapDetected()) {
+                    mSendTouchExplorationEndDelayed.forceSendAndRemove();
                     mSendTouchInteractionEndDelayed.forceSendAndRemove();
+                    sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
+                } else {
+                    // Let gesture to handle to avoid duplicated TYPE_TOUCH_INTERACTION_END event.
+                    mSendTouchInteractionEndDelayed.cancel();
                 }
 
                 if (!mGestureDetector.firstTapDetected() && !mTouchExplorationInProgress) {
@@ -575,6 +579,8 @@
                             }
                         }
 
+                        // Remove move history before send injected non-move events
+                        event = MotionEvent.obtainNoHistory(event);
                         if (isDraggingGesture(event)) {
                             // Two pointers moving in the same direction within
                             // a given distance perform a drag.
@@ -605,6 +611,7 @@
 
                         // More than two pointers are delegated to the view hierarchy.
                         mCurrentState = STATE_DELEGATING;
+                        event = MotionEvent.obtainNoHistory(event);
                         sendDownForAllNotInjectedPointers(event, policyFlags);
                     }
                 }
@@ -693,6 +700,8 @@
                             // The two pointers are moving either in different directions or
                             // no close enough => delegate the gesture to the view hierarchy.
                             mCurrentState = STATE_DELEGATING;
+                            // Remove move history before send injected non-move events
+                            event = MotionEvent.obtainNoHistory(event);
                             // Send an event to the end of the drag gesture.
                             sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
                                     policyFlags);
@@ -702,6 +711,7 @@
                     } break;
                     default: {
                         mCurrentState = STATE_DELEGATING;
+                        event = MotionEvent.obtainNoHistory(event);
                         // Send an event to the end of the drag gesture.
                         sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
                                 policyFlags);
@@ -1302,7 +1312,20 @@
 
     @Override
     public String toString() {
-        return LOG_TAG;
+        return "TouchExplorer { " +
+                "mCurrentState: " + getStateSymbolicName(mCurrentState) +
+                ", mDetermineUserIntentTimeout: " + mDetermineUserIntentTimeout +
+                ", mDoubleTapSlop: " + mDoubleTapSlop +
+                ", mDraggingPointerId: " + mDraggingPointerId +
+                ", mLongPressingPointerId: " + mLongPressingPointerId +
+                ", mLongPressingPointerDeltaX: " + mLongPressingPointerDeltaX +
+                ", mLongPressingPointerDeltaY: " + mLongPressingPointerDeltaY +
+                ", mLastTouchedWindowId: " + mLastTouchedWindowId +
+                ", mScaledMinPointerDistanceToUseMiddleLocation: "
+                + mScaledMinPointerDistanceToUseMiddleLocation +
+                ", mTempPoint: " + mTempPoint +
+                ", mTouchExplorationInProgress: " + mTouchExplorationInProgress +
+                " }";
     }
 
     class InjectedPointerTracker {
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index ed3b3e7..ff29311 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -259,6 +259,11 @@
         }
 
         @Override
+        public int getSoftKeyboardShowMode() {
+            return 0;
+        }
+
+        @Override
         public boolean isAccessibilityButtonAvailable() {
             return false;
         }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index c9c7adc..f69b638 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -48,11 +48,6 @@
     }
 
     @Override
-    public void onUnlockUser(int userHandle) {
-        FgThread.getHandler().post(() -> mImpl.onUserUnlocked(userHandle));
-    }
-
-    @Override
     public void onStopUser(int userHandle) {
         mImpl.onUserStopped(userHandle);
     }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index db8ad12..b71d7a7 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -19,7 +19,6 @@
 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 com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
 import android.annotation.UserIdInt;
@@ -2697,7 +2696,12 @@
         }
     }
 
-    void onUserUnlocked(int userId) {
+    /**
+     * This does not use the usual onUserUnlocked() listener mechanism because it is
+     * invoked at a choreographed point in the middle of the user unlock sequence,
+     * before the boot-completed broadcast is issued and the listeners notified.
+     */
+    void handleUserUnlocked(int userId) {
         if (isProfileWithLockedParent(userId)) {
             return;
         }
@@ -2734,7 +2738,7 @@
                 }
             }
         }
-        Slog.i(TAG, "Async processing of onUserUnlocked u" + userId + " took "
+        Slog.i(TAG, "Processing of handleUserUnlocked u" + userId + " took "
                 + (SystemClock.elapsedRealtime() - time) + " ms");
     }
 
@@ -4801,5 +4805,11 @@
                 return widgetPackages;
             }
         }
+
+        @Override
+        public void unlockUser(int userId) {
+            handleUserUnlocked(userId);
+        }
+
     }
 }
diff --git a/services/art-profile b/services/art-profile
index a33527e..3c60eee 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -9258,24 +9258,24 @@
 PLcom/android/server/backup/internal/BackupState;-><init>(Ljava/lang/String;I)V
 PLcom/android/server/backup/internal/BackupState;->values()[Lcom/android/server/backup/internal/BackupState;
 PLcom/android/server/backup/internal/Operation;-><init>(ILcom/android/server/backup/BackupRestoreTask;I)V
-PLcom/android/server/backup/internal/PerformBackupTask;-><init>(Lcom/android/server/backup/BackupManagerService;Lcom/android/server/backup/transport/TransportClient;Ljava/lang/String;Ljava/util/ArrayList;Lcom/android/server/backup/DataChangedJournal;Landroid/app/backup/IBackupObserver;Landroid/app/backup/IBackupManagerMonitor;Lcom/android/server/backup/internal/OnTaskFinishedListener;Ljava/util/List;ZZ)V
-PLcom/android/server/backup/internal/PerformBackupTask;->backupPm()V
-PLcom/android/server/backup/internal/PerformBackupTask;->beginBackup()V
-PLcom/android/server/backup/internal/PerformBackupTask;->clearAgentState()V
-PLcom/android/server/backup/internal/PerformBackupTask;->execute()V
-PLcom/android/server/backup/internal/PerformBackupTask;->executeNextState(Lcom/android/server/backup/internal/BackupState;)V
-PLcom/android/server/backup/internal/PerformBackupTask;->finalizeBackup()V
-PLcom/android/server/backup/internal/PerformBackupTask;->invokeAgentForBackup(Ljava/lang/String;Landroid/app/IBackupAgent;)I
-PLcom/android/server/backup/internal/PerformBackupTask;->invokeNextAgent()V
-PLcom/android/server/backup/internal/PerformBackupTask;->operationComplete(J)V
-PLcom/android/server/backup/internal/PerformBackupTask;->registerTask()V
-PLcom/android/server/backup/internal/PerformBackupTask;->revertAndEndBackup()V
-PLcom/android/server/backup/internal/PerformBackupTask;->unregisterTask()V
-PLcom/android/server/backup/internal/PerformBackupTask;->writeWidgetPayloadIfAppropriate(Ljava/io/FileDescriptor;Ljava/lang/String;)V
 PLcom/android/server/backup/internal/ProvisionedObserver;-><init>(Lcom/android/server/backup/BackupManagerService;Landroid/os/Handler;)V
 PLcom/android/server/backup/internal/RunBackupReceiver;-><init>(Lcom/android/server/backup/BackupManagerService;)V
 PLcom/android/server/backup/internal/RunBackupReceiver;->onReceive(Landroid/content/Context;Landroid/content/Intent;)V
 PLcom/android/server/backup/internal/RunInitializeReceiver;-><init>(Lcom/android/server/backup/BackupManagerService;)V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;-><init>(Lcom/android/server/backup/BackupManagerService;Lcom/android/server/backup/transport/TransportClient;Ljava/lang/String;Ljava/util/List;Lcom/android/server/backup/DataChangedJournal;Landroid/app/backup/IBackupObserver;Landroid/app/backup/IBackupManagerMonitor;Lcom/android/server/backup/internal/OnTaskFinishedListener;Ljava/util/List;ZZ)V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->backupPm()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->beginBackup()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->clearAgentState()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->execute()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->executeNextState(Lcom/android/server/backup/internal/BackupState;)V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->finalizeBackup()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->invokeAgentForBackup(Ljava/lang/String;Landroid/app/IBackupAgent;)I
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->invokeNextAgent()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->operationComplete(J)V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->registerTask()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->revertAndEndBackup()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->unregisterTask()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->writeWidgetPayloadIfAppropriate(Ljava/io/FileDescriptor;Ljava/lang/String;)V
 PLcom/android/server/backup/transport/-$$Lambda$TransportClient$ciIUj0x0CRg93UETUpy2FB5aqCQ;-><init>(Lcom/android/server/backup/transport/TransportClient;Lcom/android/server/backup/transport/TransportConnectionListener;Lcom/android/internal/backup/IBackupTransport;)V
 PLcom/android/server/backup/transport/-$$Lambda$TransportClient$ciIUj0x0CRg93UETUpy2FB5aqCQ;->run()V
 PLcom/android/server/backup/transport/-$$Lambda$TransportClient$uc3fygwQjQIS_JT7mlt-yMBfJcE;-><init>(Ljava/util/concurrent/CompletableFuture;)V
@@ -13303,7 +13303,7 @@
 PLcom/android/server/notification/NotificationManagerService$10;->deleteNotificationChannel(Ljava/lang/String;Ljava/lang/String;)V
 PLcom/android/server/notification/NotificationManagerService$10;->enforcePolicyAccess(ILjava/lang/String;)V
 PLcom/android/server/notification/NotificationManagerService$10;->enforceSystemOrSystemUI(Ljava/lang/String;)V
-PLcom/android/server/notification/NotificationManagerService$10;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;I)V
+PLcom/android/server/notification/NotificationManagerService$10;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;II)V
 PLcom/android/server/notification/NotificationManagerService$10;->finishToken(Ljava/lang/String;Landroid/app/ITransientNotification;)V
 PLcom/android/server/notification/NotificationManagerService$10;->getAppActiveNotifications(Ljava/lang/String;I)Landroid/content/pm/ParceledListSlice;
 PLcom/android/server/notification/NotificationManagerService$10;->getBackupPayload(I)[B
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 41e9d2b..5771748 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -29,6 +29,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -42,10 +43,10 @@
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Parcelable;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -165,9 +166,9 @@
         mContext = context;
         mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext());
 
-        final boolean debug = Build.IS_DEBUGGABLE;
-        Slog.i(TAG, "Setting debug to " + debug);
-        setDebugLocked(debug);
+        setLogLevelFromSettings();
+        setMaxPartitionsFromSettings();
+        setMaxVisibleDatasetsFromSettings();
 
         final IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
@@ -437,12 +438,33 @@
         Slog.i(TAG, "setLogLevel(): " + level);
         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
 
+        final long token = Binder.clearCallingIdentity();
+        try {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.AUTOFILL_LOGGING_LEVEL, level);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private void setLogLevelFromSettings() {
+        final int level = Settings.Global.getInt(
+                mContext.getContentResolver(),
+                Settings.Global.AUTOFILL_LOGGING_LEVEL, AutofillManager.DEFAULT_LOGGING_LEVEL);
         boolean debug = false;
         boolean verbose = false;
-        if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) {
-            debug = verbose = true;
-        } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) {
-            debug = true;
+        if (level != AutofillManager.NO_LOGGING) {
+            if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) {
+                debug = verbose = true;
+            } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) {
+                debug = true;
+            } else {
+                Slog.w(TAG,  "setLogLevelFromSettings(): invalid level: " + level);
+            }
+        }
+        if (debug || sDebug) {
+            Slog.d(TAG, "setLogLevelFromSettings(): level=" + level + ", debug=" + debug
+                    + ", verbose=" + verbose);
         }
         synchronized (mLock) {
             setDebugLocked(debug);
@@ -474,6 +496,22 @@
     void setMaxPartitions(int max) {
         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
         Slog.i(TAG, "setMaxPartitions(): " + max);
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, max);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private void setMaxPartitionsFromSettings() {
+        final int max = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
+                AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE);
+        if (sDebug) Slog.d(TAG, "setMaxPartitionsFromSettings(): " + max);
+
         synchronized (mLock) {
             sPartitionMaxCount = max;
         }
@@ -492,6 +530,21 @@
     void setMaxVisibleDatasets(int max) {
         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
         Slog.i(TAG, "setMaxVisibleDatasets(): " + max);
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, max);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private void setMaxVisibleDatasetsFromSettings() {
+        final int max = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, 0);
+
+        if (sDebug) Slog.d(TAG, "setMaxVisibleDatasetsFromSettings(): " + max);
         synchronized (mLock) {
             sVisibleDatasetsMaxCount = max;
         }
@@ -622,6 +675,38 @@
         return getWhitelistedCompatModePackages(getWhitelistedCompatModePackagesFromSettings());
     }
 
+    private void send(@NonNull IResultReceiver receiver, int value) {
+        try {
+            receiver.send(value, null);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Error async reporting result to client: " + e);
+        }
+    }
+
+    private void send(@NonNull IResultReceiver receiver, @NonNull Bundle value) {
+        try {
+            receiver.send(0, value);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Error async reporting result to client: " + e);
+        }
+    }
+
+    private void send(@NonNull IResultReceiver receiver, @Nullable String value) {
+        send(receiver, AutofillManager.SyncResultReceiver.bundleFor(value));
+    }
+
+    private void send(@NonNull IResultReceiver receiver, @Nullable String[] value) {
+        send(receiver, AutofillManager.SyncResultReceiver.bundleFor(value));
+    }
+
+    private void send(@NonNull IResultReceiver receiver, @Nullable Parcelable value) {
+        send(receiver, AutofillManager.SyncResultReceiver.bundleFor(value));
+    }
+
+    private void send(@NonNull IResultReceiver receiver, boolean value) {
+        send(receiver, value ? 1 : 0);
+    }
+
     @Nullable
     @VisibleForTesting
     static Map<String, String[]> getWhitelistedCompatModePackages(String setting) {
@@ -827,9 +912,10 @@
 
     final class AutoFillManagerServiceStub extends IAutoFillManager.Stub {
         @Override
-        public int addClient(IAutoFillManagerClient client, int userId) {
+        public void addClient(IAutoFillManagerClient client, int userId,
+                @NonNull IResultReceiver receiver) {
+            int flags = 0;
             synchronized (mLock) {
-                int flags = 0;
                 if (getServiceForUserLocked(userId).addClientLocked(client)) {
                     flags |= AutofillManager.FLAG_ADD_CLIENT_ENABLED;
                 }
@@ -839,8 +925,8 @@
                 if (sVerbose) {
                     flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
                 }
-                return flags;
             }
+            send(receiver, flags);
         }
 
         @Override
@@ -874,9 +960,9 @@
         }
 
         @Override
-        public int startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId,
+        public void startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId,
                 Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags,
-                ComponentName componentName, boolean compatMode) {
+                ComponentName componentName, boolean compatMode, IResultReceiver receiver) {
 
             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
@@ -892,61 +978,71 @@
                 throw new IllegalArgumentException(packageName + " is not a valid package", e);
             }
 
+            // TODO(b/112051762): rather than always call AM here, call it on demand on
+            // getPreviousSessionsLocked()? That way we save space / time here, and don't set
+            // a callback on AM unnecessarily (see TODO below :-)
+            final ActivityManagerInternal am = LocalServices
+                    .getService(ActivityManagerInternal.class);
+            // TODO(b/112051762): add a callback method on AM to be notified when a task is finished
+            // so we can clean up sessions kept alive
+            final int taskId = am.getTaskIdForActivity(activityToken, false);
+            final int sessionId;
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
-                return service.startSessionLocked(activityToken, getCallingUid(), appCallback,
-                        autofillId, bounds, value, hasCallback, componentName, compatMode,
-                        mAllowInstantService, flags);
+                sessionId = service.startSessionLocked(activityToken, taskId, getCallingUid(),
+                        appCallback, autofillId, bounds, value, hasCallback, componentName,
+                        compatMode, mAllowInstantService, flags);
             }
+            send(receiver, sessionId);
         }
 
         @Override
-        public FillEventHistory getFillEventHistory() throws RemoteException {
+        public void getFillEventHistory(@NonNull IResultReceiver receiver) throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
 
+            FillEventHistory fillEventHistory = null;
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return service.getFillEventHistory(getCallingUid());
+                    fillEventHistory = service.getFillEventHistory(getCallingUid());
                 } else if (sVerbose) {
                     Slog.v(TAG, "getFillEventHistory(): no service for " + userId);
                 }
             }
-
-            return null;
+            send(receiver, fillEventHistory);
         }
 
         @Override
-        public UserData getUserData() throws RemoteException {
+        public void getUserData(@NonNull IResultReceiver receiver) throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
 
+            UserData userData = null;
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return service.getUserData(getCallingUid());
+                    userData = service.getUserData(getCallingUid());
                 } else if (sVerbose) {
                     Slog.v(TAG, "getUserData(): no service for " + userId);
                 }
             }
-
-            return null;
+            send(receiver, userData);
         }
 
         @Override
-        public String getUserDataId() throws RemoteException {
+        public void getUserDataId(@NonNull IResultReceiver receiver) throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
+            UserData userData = null;
 
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    final UserData userData = service.getUserData(getCallingUid());
-                    return userData == null ? null : userData.getId();
+                    userData = service.getUserData(getCallingUid());
                 } else if (sVerbose) {
                     Slog.v(TAG, "getUserDataId(): no service for " + userId);
                 }
             }
-
-            return null;
+            final String userDataId = userData == null ? null : userData.getId();
+            send(receiver, userDataId);
         }
 
         @Override
@@ -964,89 +1060,96 @@
         }
 
         @Override
-        public boolean isFieldClassificationEnabled() throws RemoteException {
+        public void isFieldClassificationEnabled(@NonNull IResultReceiver receiver)
+                throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
+            boolean enabled = false;
 
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return service.isFieldClassificationEnabled(getCallingUid());
+                    enabled = service.isFieldClassificationEnabled(getCallingUid());
                 } else if (sVerbose) {
                     Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId);
                 }
             }
-
-            return false;
+            send(receiver, enabled);
         }
 
         @Override
-        public String getDefaultFieldClassificationAlgorithm() throws RemoteException {
+        public void getDefaultFieldClassificationAlgorithm(@NonNull IResultReceiver receiver)
+                throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
+            String algorithm = null;
 
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return service.getDefaultFieldClassificationAlgorithm(getCallingUid());
+                    algorithm = service.getDefaultFieldClassificationAlgorithm(getCallingUid());
                 } else {
                     if (sVerbose) {
                         Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId);
                     }
-                    return null;
                }
             }
+            send(receiver, algorithm);
         }
 
         @Override
-        public String[] getAvailableFieldClassificationAlgorithms() throws RemoteException {
+        public void getAvailableFieldClassificationAlgorithms(@NonNull IResultReceiver receiver)
+                throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
+            String[] algorithms = null;
 
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return service.getAvailableFieldClassificationAlgorithms(getCallingUid());
+                    algorithms = service.getAvailableFieldClassificationAlgorithms(getCallingUid());
                 } else {
                     if (sVerbose) {
                         Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId);
                     }
-                    return null;
                 }
             }
+            send(receiver, algorithms);
         }
 
         @Override
-        public ComponentName getAutofillServiceComponentName() throws RemoteException {
+        public void getAutofillServiceComponentName(@NonNull IResultReceiver receiver)
+                throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
 
+            ComponentName componentName = null;
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return service.getServiceComponentName();
+                    componentName = service.getServiceComponentName();
                 } else if (sVerbose) {
                     Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId);
                 }
             }
-
-            return null;
+            send(receiver, componentName);
         }
 
         @Override
-        public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback)
+        public void restoreSession(int sessionId, @NonNull IBinder activityToken,
+                @NonNull IBinder appCallback, @NonNull IResultReceiver receiver)
                 throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
 
+            boolean restored = false;
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = mServicesCache.get(userId);
                 if (service != null) {
-                    return service.restoreSession(sessionId, getCallingUid(), activityToken,
+                    restored = service.restoreSession(sessionId, getCallingUid(), activityToken,
                             appCallback);
                 } else if (sVerbose) {
                     Slog.v(TAG, "restoreSession(): no service for " + userId);
                 }
             }
-
-            return false;
+            send(receiver, restored);
         }
 
         @Override
@@ -1112,23 +1215,27 @@
         }
 
         @Override
-        public boolean isServiceSupported(int userId) {
+        public void isServiceSupported(int userId, @NonNull IResultReceiver receiver) {
+            boolean supported = false;
             synchronized (mLock) {
-                return !mDisabledUsers.get(userId);
+                supported = !mDisabledUsers.get(userId);
             }
+            send(receiver, supported);
         }
 
         @Override
-        public boolean isServiceEnabled(int userId, String packageName) {
+        public void isServiceEnabled(int userId, @NonNull String packageName,
+                @NonNull IResultReceiver receiver) {
+            boolean enabled = false;
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return Objects.equals(packageName, service.getServicePackageName());
+                    enabled = Objects.equals(packageName, service.getServicePackageName());
                 } else if (sVerbose) {
                     Slog.v(TAG, "isServiceEnabled(): no service for " + userId);
                 }
-                return false;
             }
+            send(receiver, enabled);
         }
 
         @Override
@@ -1242,13 +1349,34 @@
             resolver.registerContentObserver(Settings.Global.getUriFor(
                     Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES), false, this,
                     UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.AUTOFILL_LOGGING_LEVEL), false, this,
+                    UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE), false, this,
+                    UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS), false, this,
+                    UserHandle.USER_ALL);
         }
 
         @Override
         public void onChange(boolean selfChange, Uri uri, int userId) {
             if (sVerbose) Slog.v(TAG, "onChange(): uri=" + uri + ", userId=" + userId);
-            synchronized (mLock) {
-                updateCachedServiceLocked(userId);
+            switch (uri.getLastPathSegment()) {
+                case Settings.Global.AUTOFILL_LOGGING_LEVEL:
+                    setLogLevelFromSettings();
+                    break;
+                case Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE:
+                    setMaxPartitionsFromSettings();
+                    break;
+                case Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS:
+                    setMaxVisibleDatasetsFromSettings();
+                    break;
+                default:
+                synchronized (mLock) {
+                    updateCachedServiceLocked(userId);
+                }
             }
         }
     }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 4206d9a..48b3798 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -25,11 +25,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
-import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -82,7 +80,6 @@
 import com.android.server.LocalServices;
 import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
 import com.android.server.autofill.ui.AutoFillUI;
-import com.android.server.wm.ActivityTaskManagerInternal;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -342,7 +339,7 @@
     }
 
     @GuardedBy("mLock")
-    int startSessionLocked(@NonNull IBinder activityToken, int uid,
+    int startSessionLocked(@NonNull IBinder activityToken, int taskId, int uid,
             @NonNull IBinder appCallbackToken, @NonNull AutofillId autofillId,
             @NonNull Rect virtualBounds, @Nullable AutofillValue value, boolean hasCallback,
             @NonNull ComponentName componentName, boolean compatMode,
@@ -375,8 +372,9 @@
         // Occasionally clean up abandoned sessions
         pruneAbandonedSessionsLocked();
 
-        final Session newSession = createSessionByTokenLocked(activityToken, uid, appCallbackToken,
-                hasCallback, componentName, compatMode, bindInstantServiceAllowed, flags);
+        final Session newSession = createSessionByTokenLocked(activityToken, taskId, uid,
+                appCallbackToken, hasCallback, componentName, compatMode, bindInstantServiceAllowed,
+                flags);
         if (newSession == null) {
             return NO_SESSION;
         }
@@ -493,7 +491,7 @@
     }
 
     @GuardedBy("mLock")
-    private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int uid,
+    private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int taskId, int uid,
             @NonNull IBinder appCallbackToken, boolean hasCallback,
             @NonNull ComponentName componentName, boolean compatMode,
             boolean bindInstantServiceAllowed, int flags) {
@@ -513,9 +511,9 @@
         assertCallerLocked(componentName, compatMode);
 
         final Session newSession = new Session(this, mUi, mContext, mHandler, mUserId, mLock,
-                sessionId, uid, activityToken, appCallbackToken, hasCallback, mUiLatencyHistory,
-                mWtfHistory, mInfo.getServiceInfo().getComponentName(), componentName, compatMode,
-                bindInstantServiceAllowed, flags);
+                sessionId, taskId, uid, activityToken, appCallbackToken, hasCallback,
+                mUiLatencyHistory, mWtfHistory, mInfo.getServiceInfo().getComponentName(),
+                componentName, compatMode, bindInstantServiceAllowed, flags);
         mSessions.put(newSession.id, newSession);
 
         return newSession;
@@ -607,6 +605,30 @@
         mSessions.remove(sessionId);
     }
 
+    /**
+     * Ges the previous sessions asked to be kept alive in a given activity task.
+     *
+     * @param session session calling this method (so it's excluded from the result).
+     */
+    @Nullable
+    @GuardedBy("mLock")
+    ArrayList<Session> getPreviousSessionsLocked(@NonNull Session session) {
+        final int size = mSessions.size();
+        ArrayList<Session> previousSessions = null;
+        for (int i = 0; i < size; i++) {
+            final Session previousSession = mSessions.valueAt(i);
+            // TODO(b/112051762): only return sessions asked to be kept alive / add CTS test
+            if (previousSession.taskId == session.taskId && previousSession.id != session.id) {
+                if (previousSessions == null) {
+                    previousSessions = new ArrayList<>(size);
+                }
+                previousSessions.add(previousSession);
+            }
+        }
+        // TODO(b/112051762): remove returned sessions / add CTS test
+        return previousSessions;
+    }
+
     void handleSessionSave(Session session) {
         synchronized (mLock) {
             if (mSessions.get(session.id) == null) {
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index f7b7ceb4..522280e 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -185,7 +185,7 @@
                 mService.setLogLevel(AutofillManager.FLAG_ADD_CLIENT_DEBUG);
                 return 0;
             case "off":
-                mService.setLogLevel(0);
+                mService.setLogLevel(AutofillManager.NO_LOGGING);
                 return 0;
             default:
                 pw.println("Invalid level: " + logLevel);
diff --git a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
index 293f908e..8ee6571 100644
--- a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
+++ b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
@@ -17,8 +17,8 @@
 
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sVerbose;
-import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS;
-import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM;
+import static android.service.autofill.AutofillFieldClassificationService.RESOURCE_AVAILABLE_ALGORITHMS;
+import static android.service.autofill.AutofillFieldClassificationService.RESOURCE_DEFAULT_ALGORITHM;
 
 import android.Manifest;
 import android.annotation.MainThread;
@@ -226,7 +226,7 @@
      */
     @Nullable
     String[] getAvailableAlgorithms() {
-        return getMetadataValue(SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS,
+        return getMetadataValue(RESOURCE_AVAILABLE_ALGORITHMS, "array",
                 (res, id) -> res.getStringArray(id));
     }
 
@@ -235,11 +235,12 @@
      */
     @Nullable
     String getDefaultAlgorithm() {
-        return getMetadataValue(SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM, (res, id) -> res.getString(id));
+        return getMetadataValue(RESOURCE_DEFAULT_ALGORITHM, "string",
+                (res, id) -> res.getString(id));
     }
 
     @Nullable
-    private <T> T getMetadataValue(String field, MetadataParser<T> parser) {
+    private <T> T getMetadataValue(String field, String type, MetadataParser<T> parser) {
         final ServiceInfo serviceInfo = getServiceInfo();
         if (serviceInfo == null) return null;
 
@@ -253,7 +254,7 @@
             return null;
         }
 
-        final int resourceId = serviceInfo.metaData.getInt(field);
+        final int resourceId = res.getIdentifier(field, type, serviceInfo.packageName);
         return parser.get(res, resourceId);
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 4f45a77..420c2be 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -28,6 +28,7 @@
 import android.util.Slog;
 import android.view.WindowManager;
 import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -43,28 +44,32 @@
 
     /**
      * Defines a logging flag that can be dynamically changed at runtime using
-     * {@code cmd autofill set log_level debug}.
+     * {@code cmd autofill set log_level debug} or through
+     * {@link android.provider.Settings.Global#AUTOFILL_LOGGING_LEVEL}.
      */
     public static boolean sDebug = false;
 
     /**
      * Defines a logging flag that can be dynamically changed at runtime using
-     * {@code cmd autofill set log_level verbose}.
+     * {@code cmd autofill set log_level verbose} or through
+     * {@link android.provider.Settings.Global#AUTOFILL_LOGGING_LEVEL}.
      */
     public static boolean sVerbose = false;
 
     /**
      * Maximum number of partitions that can be allowed in a session.
      *
-     * <p>Can be modified using {@code cmd autofill set max_partitions}.
+     * <p>Can be modified using {@code cmd autofill set max_partitions} or through
+     * {@link android.provider.Settings.Global#AUTOFILL_MAX_PARTITIONS_SIZE}.
      */
-    static int sPartitionMaxCount = 10;
+    static int sPartitionMaxCount = AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE;
 
     /**
      * Maximum number of visible datasets in the dataset picker UI, or {@code 0} to use default
      * value from resources.
      *
-     * <p>Can be modified using {@code cmd autofill set max_visible_datasets}.
+     * <p>Can be modified using {@code cmd autofill set max_visible_datasets} or through
+     * {@link android.provider.Settings.Global#AUTOFILL_MAX_VISIBLE_DATASETS}.
      */
     public static int sVisibleDatasetsMaxCount = 0;
 
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 65ad596..ad80cc26 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -123,8 +123,7 @@
     }
 
     public void destroy() {
-        mHandler.sendMessage(obtainMessage(
-                RemoteFillService::handleDestroy, this));
+        mHandler.sendMessage(obtainMessage(RemoteFillService::handleDestroy, this));
     }
 
     private void handleDestroy() {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 18255c5..5a10c1e 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -37,7 +37,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.IAssistDataReceiver;
 import android.app.assist.AssistStructure;
@@ -130,12 +129,15 @@
 
     private static AtomicInteger sIdCounter = new AtomicInteger();
 
-    /** Id of the session */
+    /** ID of the session */
     public final int id;
 
     /** uid the session is for */
     public final int uid;
 
+    /** ID of the task associated with this session's activity */
+    public final int taskId;
+
     /** Flags used to start the session */
     public final int mFlags;
 
@@ -269,7 +271,7 @@
                 // change AssistStructure so it provides a "one-way" writeToParcel() method that
                 // sends all the data
                 try {
-                    structure.ensureData();
+                    structure.ensureDataForAutofill();
                 } catch (RuntimeException e) {
                     wtf(e, "Exception lazy loading assist structure for %s: %s",
                             structure.getActivityComponent(), e);
@@ -288,6 +290,9 @@
                                     componentNameFromApp == null ? "null"
                                             : componentNameFromApp.flattenToShortString()));
                 }
+                // Flags used to start the session.
+                int flags = structure.getFlags();
+
                 if (mCompatMode) {
                     // Sanitize URL bar, if needed
                     final String[] urlBarIds = mService.getUrlBarResourceIdsForCompatMode(
@@ -308,12 +313,10 @@
                             mViewStates.put(urlBarId, viewState);
                         }
                     }
+                    flags |= FillRequest.FLAG_COMPATIBILITY_MODE_REQUEST;
                 }
                 structure.sanitizeForParceling(true);
 
-                // Flags used to start the session.
-                final int flags = structure.getFlags();
-
                 if (mContexts == null) {
                     mContexts = new ArrayList<>(1);
                 }
@@ -330,8 +333,8 @@
                 // until the dispatch happens. The items in the list don't need to be cloned
                 // since we don't hold on them anywhere else. The client state is not touched
                 // by us, so no need to copy.
-                request = new FillRequest(requestId, new ArrayList<>(mContexts),
-                        mClientState, flags);
+                request = new FillRequest(requestId, new ArrayList<>(mContexts), mClientState,
+                        flags);
             }
 
             mRemoteFillService.onFillRequest(request);
@@ -529,14 +532,15 @@
     }
 
     Session(@NonNull AutofillManagerServiceImpl service, @NonNull AutoFillUI ui,
-            @NonNull Context context, @NonNull Handler handler, int userId,
-            @NonNull Object lock, int sessionId, int uid, @NonNull IBinder activityToken,
+            @NonNull Context context, @NonNull Handler handler, int userId, @NonNull Object lock,
+            int sessionId, int taskId, int uid, @NonNull IBinder activityToken,
             @NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory,
-            @NonNull LocalLog wtfHistory,
-            @NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName,
-            boolean compatMode, boolean bindInstantServiceAllowed, int flags) {
+            @NonNull LocalLog wtfHistory, @NonNull ComponentName serviceComponentName,
+            @NonNull ComponentName componentName, boolean compatMode,
+            boolean bindInstantServiceAllowed, int flags) {
         id = sessionId;
         mFlags = flags;
+        this.taskId = taskId;
         this.uid = uid;
         mStartTime = SystemClock.elapsedRealtime();
         mService = service;
@@ -839,7 +843,8 @@
     // FillServiceCallbacks
     @Override
     public void onServiceDied(RemoteFillService service) {
-        // TODO(b/337565347): implement
+        Slog.w(TAG, "removing session because service died");
+        forceRemoveSelfLocked();
     }
 
     // AutoFillUiCallback
@@ -1431,7 +1436,8 @@
     /**
      * Shows the save UI, when session can be saved.
      *
-     * @return {@code true} if session is done, or {@code false} if it's pending user action.
+     * @return {@code true} if session is done and could be removed, or {@code false} if it's
+     * pending user action or the service asked to keep it alive (for multi-screens workflow).
      */
     @GuardedBy("mLock")
     public boolean showSaveLocked() {
@@ -1451,21 +1457,32 @@
          * - autofillValue of at least one id (required or optional) has changed.
          * - there is no Dataset in the last FillResponse whose values of all dataset fields matches
          *   the current values of all fields in the screen.
+         * - server didn't ask to keep session alive
          */
         if (saveInfo == null) {
             if (sVerbose) Slog.v(TAG, "showSaveLocked(): no saveInfo from service");
             return true;
         }
 
+        if ((saveInfo.getFlags() & SaveInfo.FLAG_DELAY_SAVE) != 0) {
+            // TODO(b/112051762): log metrics
+            if (sDebug) Slog.v(TAG, "showSaveLocked(): service asked to delay save");
+            return false;
+        }
+
         final ArrayMap<AutofillId, InternalSanitizer> sanitizers = createSanitizers(saveInfo);
 
         // Cache used to make sure changed fields do not belong to a dataset.
         final ArrayMap<AutofillId, AutofillValue> currentValues = new ArrayMap<>();
-        final ArraySet<AutofillId> allIds = new ArraySet<>();
+        // Savable (optional or required) ids that will be checked against the dataset ids.
+        final ArraySet<AutofillId> savableIds = new ArraySet<>();
 
         final AutofillId[] requiredIds = saveInfo.getRequiredIds();
         boolean allRequiredAreNotEmpty = true;
         boolean atLeastOneChanged = false;
+        // If an autofilled field is changed, we need to change isUpdate to true so the proper UI is
+        // shown.
+        boolean isUpdate = false;
         if (requiredIds != null) {
             for (int i = 0; i < requiredIds.length; i++) {
                 final AutofillId id = requiredIds[i];
@@ -1473,7 +1490,7 @@
                     Slog.w(TAG, "null autofill id on " + Arrays.toString(requiredIds));
                     continue;
                 }
-                allIds.add(id);
+                savableIds.add(id);
                 final ViewState viewState = mViewStates.get(id);
                 if (viewState == null) {
                     Slog.w(TAG, "showSaveLocked(): no ViewState for required " + id);
@@ -1523,6 +1540,8 @@
                             }
                             changed = false;
                         }
+                    } else {
+                        isUpdate = true;
                     }
                     if (changed) {
                         if (sDebug) {
@@ -1536,12 +1555,21 @@
         }
 
         final AutofillId[] optionalIds = saveInfo.getOptionalIds();
+        if (sVerbose) {
+            Slog.v(TAG, "allRequiredAreNotEmpty: " + allRequiredAreNotEmpty + " hasOptional: "
+                    + (optionalIds != null));
+        }
         if (allRequiredAreNotEmpty) {
-            if (!atLeastOneChanged && optionalIds != null) {
+            // Must look up all optional ids in 2 scenarios:
+            // - if no required id changed but an optional id did, it should trigger save / update
+            // - if at least one required id changed but it was not part of a filled dataset, we
+            //   need to check if an optional id is part of a filled datased (in which case we show
+            //   Update instead of Save)
+            if (optionalIds!= null && (!atLeastOneChanged || !isUpdate)) {
                 // No change on required ids yet, look for changes on optional ids.
                 for (int i = 0; i < optionalIds.length; i++) {
                     final AutofillId id = optionalIds[i];
-                    allIds.add(id);
+                    savableIds.add(id);
                     final ViewState viewState = mViewStates.get(id);
                     if (viewState == null) {
                         Slog.w(TAG, "no ViewState for optional " + id);
@@ -1549,17 +1577,27 @@
                     }
                     if ((viewState.getState() & ViewState.STATE_CHANGED) != 0) {
                         final AutofillValue currentValue = viewState.getCurrentValue();
-                        currentValues.put(id, currentValue);
+                        final AutofillValue value = getSanitizedValue(sanitizers, id, currentValue);
+                        if (value == null) {
+                            if (sDebug) {
+                                Slog.d(TAG, "value of opt. field " + id + " failed sanitization");
+                            }
+                            continue;
+                        }
+
+                        currentValues.put(id, value);
                         final AutofillValue filledValue = viewState.getAutofilledValue();
-                        if (currentValue != null && !currentValue.equals(filledValue)) {
+                        if (value != null && !value.equals(filledValue)) {
                             if (sDebug) {
                                 Slog.d(TAG, "found a change on optional " + id + ": " + filledValue
-                                        + " => " + currentValue);
+                                        + " => " + value);
+                            }
+                            if (filledValue != null) {
+                                isUpdate = true;
                             }
                             atLeastOneChanged = true;
-                            break;
                         }
-                    } else {
+                    } else  {
                         // Update current values cache based on initial value
                         final AutofillValue initialValue = getValueFromContextsLocked(id);
                         if (sDebug) {
@@ -1610,16 +1648,16 @@
                                 Helper.getFields(dataset);
                         if (sVerbose) {
                             Slog.v(TAG, "Checking if saved fields match contents of dataset #" + i
-                                    + ": " + dataset + "; allIds=" + allIds);
+                                    + ": " + dataset + "; savableIds=" + savableIds);
                         }
-                        for (int j = 0; j < allIds.size(); j++) {
-                            final AutofillId id = allIds.valueAt(j);
+                        savable_ids_loop: for (int j = 0; j < savableIds.size(); j++) {
+                            final AutofillId id = savableIds.valueAt(j);
                             final AutofillValue currentValue = currentValues.get(id);
                             if (currentValue == null) {
                                 if (sDebug) {
                                     Slog.d(TAG, "dataset has value for field that is null: " + id);
                                 }
-                                continue datasets_loop;
+                                continue savable_ids_loop;
                             }
                             final AutofillValue datasetValue = datasetValues.get(id);
                             if (!currentValue.equals(datasetValue)) {
@@ -1645,14 +1683,13 @@
                 }
 
                 // Use handler so logContextCommitted() is logged first
-                mHandler.sendMessage(obtainMessage(
-                        Session::logSaveShown, this));
+                mHandler.sendMessage(obtainMessage(Session::logSaveShown, this));
 
                 final IAutoFillManagerClient client = getClient();
                 mPendingSaveUi = new PendingUi(mActivityToken, id, client);
                 getUiForShowing().showSaveUi(mService.getServiceLabel(), mService.getServiceIcon(),
                         mService.getServicePackageName(), saveInfo, this,
-                        mComponentName, this, mPendingSaveUi, mCompatMode);
+                        mComponentName, this, mPendingSaveUi, isUpdate, mCompatMode);
                 if (client != null) {
                     try {
                         client.setSaveUiState(id, true);
@@ -1702,12 +1739,14 @@
         return sanitizers;
     }
 
+    // TODO: this method is called a few times in the save process, we should cache its results into
+    // ViewState.
     @Nullable
     private AutofillValue getSanitizedValue(
             @Nullable ArrayMap<AutofillId, InternalSanitizer> sanitizers,
             @NonNull AutofillId id,
-            @NonNull AutofillValue value) {
-        if (sanitizers == null) return value;
+            @Nullable AutofillValue value) {
+        if (sanitizers == null || value == null) return value;
 
         final InternalSanitizer sanitizer = sanitizers.get(id);
         if (sanitizer == null) {
@@ -1769,6 +1808,66 @@
     }
 
     /**
+     * Update the {@link AutofillValue values} of the {@link AssistStructure} before sending it to
+     * the service on save().
+     */
+    private void updateValuesForSaveLocked() {
+        final ArrayMap<AutofillId, InternalSanitizer> sanitizers =
+                createSanitizers(getSaveInfoLocked());
+
+        final int numContexts = mContexts.size();
+        for (int contextNum = 0; contextNum < numContexts; contextNum++) {
+            final FillContext context = mContexts.get(contextNum);
+
+            final ViewNode[] nodes =
+                context.findViewNodesByAutofillIds(getIdsOfAllViewStatesLocked());
+
+            if (sVerbose) Slog.v(TAG, "updateValuesForSaveLocked(): updating " + context);
+
+            for (int viewStateNum = 0; viewStateNum < mViewStates.size(); viewStateNum++) {
+                final ViewState viewState = mViewStates.valueAt(viewStateNum);
+
+                final AutofillId id = viewState.id;
+                final AutofillValue value = viewState.getCurrentValue();
+                if (value == null) {
+                    if (sVerbose) Slog.v(TAG, "updateValuesForSaveLocked(): skipping " + id);
+                    continue;
+                }
+                final ViewNode node = nodes[viewStateNum];
+                if (node == null) {
+                    Slog.w(TAG, "callSaveLocked(): did not find node with id " + id);
+                    continue;
+                }
+                if (sVerbose) {
+                    Slog.v(TAG, "updateValuesForSaveLocked(): updating " + id + " to " + value);
+                }
+
+                AutofillValue sanitizedValue = viewState.getSanitizedValue();
+
+                if (sanitizedValue == null) {
+                    // Field is optional and haven't been sanitized yet.
+                    sanitizedValue = getSanitizedValue(sanitizers, id, value);
+                }
+                if (sanitizedValue != null) {
+                    node.updateAutofillValue(sanitizedValue);
+                } else if (sDebug) {
+                    Slog.d(TAG, "updateValuesForSaveLocked(): not updating field " + id
+                            + " because it failed sanitization");
+                }
+            }
+
+            // Sanitize structure before it's sent to service.
+            context.getStructure().sanitizeForParceling(false);
+
+            if (sVerbose) {
+                Slog.v(TAG, "updateValuesForSaveLocked(): dumping structure of " + context
+                        + " before calling service.save()");
+                context.getStructure().dump(false);
+            }
+        }
+    }
+
+    /**
      * Calls service when user requested save.
      */
     @GuardedBy("mLock")
@@ -1786,66 +1885,49 @@
             return;
         }
 
-        final ArrayMap<AutofillId, InternalSanitizer> sanitizers =
-                createSanitizers(getSaveInfoLocked());
-
-        final int numContexts = mContexts.size();
-
-        for (int contextNum = 0; contextNum < numContexts; contextNum++) {
-            final FillContext context = mContexts.get(contextNum);
-
-            final ViewNode[] nodes =
-                context.findViewNodesByAutofillIds(getIdsOfAllViewStatesLocked());
-
-            if (sVerbose) Slog.v(TAG, "callSaveLocked(): updating " + context);
-
-            for (int viewStateNum = 0; viewStateNum < mViewStates.size(); viewStateNum++) {
-                final ViewState viewState = mViewStates.valueAt(viewStateNum);
-
-                final AutofillId id = viewState.id;
-                final AutofillValue value = viewState.getCurrentValue();
-                if (value == null) {
-                    if (sVerbose) Slog.v(TAG, "callSaveLocked(): skipping " + id);
-                    continue;
-                }
-                final ViewNode node = nodes[viewStateNum];
-                if (node == null) {
-                    Slog.w(TAG, "callSaveLocked(): did not find node with id " + id);
-                    continue;
-                }
-                if (sVerbose) Slog.v(TAG, "callSaveLocked(): updating " + id + " to " + value);
-
-                AutofillValue sanitizedValue = viewState.getSanitizedValue();
-
-                if (sanitizedValue == null) {
-                    // Field is optional and haven't been sanitized yet.
-                    sanitizedValue = getSanitizedValue(sanitizers, id, value);
-                }
-                if (sanitizedValue != null) {
-                    node.updateAutofillValue(sanitizedValue);
-                } else if (sDebug) {
-                    Slog.d(TAG, "Not updating field " + id + " because it failed sanitization");
-                }
-            }
-
-            // Sanitize structure before it's sent to service.
-            context.getStructure().sanitizeForParceling(false);
-
-            if (sVerbose) {
-                Slog.v(TAG, "Dumping structure of " + context + " before calling service.save()");
-                context.getStructure().dump(false);
-            }
-        }
+        updateValuesForSaveLocked();
 
         // Remove pending fill requests as the session is finished.
         cancelCurrentRequestLocked();
 
-        // Dispatch a snapshot of the current contexts list since it may change
-        // until the dispatch happens. The items in the list don't need to be cloned
-        // since we don't hold on them anywhere else. The client state is not touched
-        // by us, so no need to copy.
-        final SaveRequest saveRequest = new SaveRequest(new ArrayList<>(mContexts), mClientState,
-                mSelectedDatasetIds);
+        // Merge the previous sessions that the service asked to be kept alive
+        final ArrayList<Session> previousSessions = mService.getPreviousSessionsLocked(this);
+        final ArrayList<FillContext> contexts;
+        final Bundle clientState;
+        if (previousSessions != null) {
+            if (sDebug) {
+                Slog.d(TAG, "callSaveLocked(): Merging the content of " + previousSessions.size()
+                        + " sessions for task " + taskId);
+            }
+            contexts = new ArrayList<>();
+            for (int i = 0; i < previousSessions.size(); i++) {
+                final Session previousSession = previousSessions.get(i);
+                final ArrayList<FillContext> previousContexts = previousSession.mContexts;
+                if (previousContexts == null) {
+                    Slog.w(TAG, "callSaveLocked(): Not merging null contexts from "
+                            + previousSession.id);
+                    continue;
+                }
+                previousSession.updateValuesForSaveLocked();
+                if (sVerbose) {
+                    Slog.v(TAG, "callSaveLocked(): adding " + previousContexts.size()
+                            + " context from previous session #" + previousSession.id);
+                }
+                contexts.addAll(previousContexts);
+            }
+            contexts.addAll(mContexts);
+            // TODO(b/112051762): decided what to do with client state / add CTS test
+            clientState = mClientState;
+        } else {
+            // Dispatch a snapshot of the current contexts list since it may change
+            // until the dispatch happens. The items in the list don't need to be cloned
+            // since we don't hold on them anywhere else. The client state is not touched
+            // by us, so no need to copy.
+            contexts = new ArrayList<>(mContexts);
+            clientState = mClientState;
+        }
+
+        final SaveRequest saveRequest = new SaveRequest(contexts, clientState, mSelectedDatasetIds);
         mRemoteFillService.onSaveRequest(saveRequest);
     }
 
@@ -2510,6 +2592,7 @@
         final String prefix2 = prefix + "  ";
         pw.print(prefix); pw.print("id: "); pw.println(id);
         pw.print(prefix); pw.print("uid: "); pw.println(uid);
+        pw.print(prefix); pw.print("taskId: "); pw.println(taskId);
         pw.print(prefix); pw.print("flags: "); pw.println(mFlags);
         pw.print(prefix); pw.print("mComponentName: "); pw.println(mComponentName);
         pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index c5e838a..5962406 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -268,9 +268,10 @@
             @Nullable String servicePackageName, @NonNull SaveInfo info,
             @NonNull ValueFinder valueFinder, @NonNull ComponentName componentName,
             @NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingSaveUi,
-            boolean compatMode) {
+            boolean isUpdate, boolean compatMode) {
         if (sVerbose) {
-            Slog.v(TAG, "showSaveUi() for " + componentName.toShortString() + ": " + info);
+            Slog.v(TAG, "showSaveUi(update=" + isUpdate + ") for " + componentName.toShortString()
+                    + ": " + info);
         }
         int numIds = 0;
         numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
@@ -280,6 +281,9 @@
                 .newLogMaker(MetricsEvent.AUTOFILL_SAVE_UI, componentName, servicePackageName,
                         pendingSaveUi.sessionId, compatMode)
                 .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
+        if (isUpdate) {
+            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_UPDATE, 1);
+        }
 
         mHandler.post(() -> {
             if (callback != mCallback) {
@@ -328,7 +332,7 @@
                     }
                     mMetricsLogger.write(log);
                 }
-            }, compatMode);
+            }, isUpdate, compatMode);
         });
     }
 
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 dc84498..9d3d3cb 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -35,6 +35,7 @@
 import android.os.RemoteException;
 import android.service.autofill.BatchUpdates;
 import android.service.autofill.CustomDescription;
+import android.service.autofill.InternalOnClickAction;
 import android.service.autofill.InternalTransformation;
 import android.service.autofill.InternalValidator;
 import android.service.autofill.SaveInfo;
@@ -43,6 +44,7 @@
 import android.util.ArraySet;
 import android.util.Pair;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -81,12 +83,20 @@
         void onDestroy();
     }
 
-    private class OneTimeListener implements OnSaveListener {
+    /**
+     * Wrapper that guarantees that only one callback action (either {@link #onSave()} or
+     * {@link #onCancel(IntentSender)}) is triggered by ignoring further calls after
+     * it's destroyed.
+     *
+     * <p>It's needed becase {@link #onCancel(IntentSender)} is always called when the Save UI
+     * dialog is dismissed.
+     */
+    private class OneActionThenDestroyListener implements OnSaveListener {
 
         private final OnSaveListener mRealListener;
         private boolean mDone;
 
-        OneTimeListener(OnSaveListener realListener) {
+        OneActionThenDestroyListener(OnSaveListener realListener) {
             mRealListener = realListener;
         }
 
@@ -96,7 +106,6 @@
             if (mDone) {
                 return;
             }
-            mDone = true;
             mRealListener.onSave();
         }
 
@@ -106,7 +115,6 @@
             if (mDone) {
                 return;
             }
-            mDone = true;
             mRealListener.onCancel(listener);
         }
 
@@ -126,7 +134,7 @@
 
     private final @NonNull Dialog mDialog;
 
-    private final @NonNull OneTimeListener mListener;
+    private final @NonNull OneActionThenDestroyListener mListener;
 
     private final @NonNull OverlayControl mOverlayControl;
 
@@ -144,9 +152,9 @@
            @Nullable String servicePackageName, @NonNull ComponentName componentName,
            @NonNull SaveInfo info, @NonNull ValueFinder valueFinder,
            @NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener,
-           boolean compatMode) {
+           boolean isUpdate, boolean compatMode) {
         mPendingUi= pendingUi;
-        mListener = new OneTimeListener(listener);
+        mListener = new OneActionThenDestroyListener(listener);
         mOverlayControl = overlayControl;
         mServicePackageName = servicePackageName;
         mComponentName = componentName;
@@ -179,21 +187,29 @@
 
         switch (types.size()) {
             case 1:
-                mTitle = Html.fromHtml(context.getString(R.string.autofill_save_title_with_type,
+                mTitle = Html.fromHtml(context.getString(
+                        isUpdate ? R.string.autofill_update_title_with_type
+                                : R.string.autofill_save_title_with_type,
                         types.valueAt(0), serviceLabel), 0);
                 break;
             case 2:
-                mTitle = Html.fromHtml(context.getString(R.string.autofill_save_title_with_2types,
+                mTitle = Html.fromHtml(context.getString(
+                        isUpdate ? R.string.autofill_update_title_with_2types
+                                : R.string.autofill_save_title_with_2types,
                         types.valueAt(0), types.valueAt(1), serviceLabel), 0);
                 break;
             case 3:
-                mTitle = Html.fromHtml(context.getString(R.string.autofill_save_title_with_3types,
+                mTitle = Html.fromHtml(context.getString(
+                        isUpdate ? R.string.autofill_update_title_with_3types
+                                : R.string.autofill_save_title_with_3types,
                         types.valueAt(0), types.valueAt(1), types.valueAt(2), serviceLabel), 0);
                 break;
             default:
                 // Use generic if more than 3 or invalid type (size 0).
                 mTitle = Html.fromHtml(
-                        context.getString(R.string.autofill_save_title, serviceLabel), 0);
+                        context.getString(isUpdate ? R.string.autofill_update_title
+                                : R.string.autofill_save_title, serviceLabel),
+                        0);
         }
         titleView.setText(mTitle);
 
@@ -228,7 +244,10 @@
         }
         noButton.setOnClickListener((v) -> mListener.onCancel(info.getNegativeActionListener()));
 
-        final View yesButton = view.findViewById(R.id.autofill_save_yes);
+        final TextView yesButton = view.findViewById(R.id.autofill_save_yes);
+        if (isUpdate) {
+            yesButton.setText(R.string.autofill_update_yes);
+        }
         yesButton.setOnClickListener((v) -> mListener.onSave());
 
         mDialog = new Dialog(context, THEME_ID);
@@ -321,7 +340,7 @@
             template.setApplyTheme(THEME_ID);
             final View customSubtitleView = template.apply(context, null, handler);
 
-            // And apply batch updates (if any).
+            // Apply batch updates (if any).
             final ArrayList<Pair<InternalValidator, BatchUpdates>> updates =
                     customDescription.getUpdates();
             if (updates != null) {
@@ -360,6 +379,35 @@
                 }
             }
 
+            // Apply click actions (if any).
+            final SparseArray<InternalOnClickAction> actions = customDescription.getActions();
+            if (actions != null) {
+                final int size = actions.size();
+                if (sDebug) Slog.d(TAG, "custom description has " + size + " actions");
+                if (!(customSubtitleView instanceof ViewGroup)) {
+                    Slog.w(TAG, "cannot apply actions because custom description root is not a "
+                            + "ViewGroup: " + customSubtitleView);
+                } else {
+                    final ViewGroup rootView = (ViewGroup) customSubtitleView;
+                    for (int i = 0; i < size; i++) {
+                        final int id = actions.keyAt(i);
+                        final InternalOnClickAction action = actions.valueAt(i);
+                        final View child = rootView.findViewById(id);
+                        if (child == null) {
+                            Slog.w(TAG, "Ignoring action " + action + " for view " + id
+                                    + " because it's not on " + rootView);
+                            continue;
+                        }
+                        child.setOnClickListener((v) -> {
+                            if (sVerbose) {
+                                Slog.v(TAG, "Applying " + action + " after " + v + " was clicked");
+                            }
+                            action.onClick(rootView);
+                        });
+                    }
+                }
+            }
+
             // Finally, add the custom description to the save UI.
             final ViewGroup subtitleContainer =
                     saveUiView.findViewById(R.id.autofill_save_custom_subtitle);
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index cd1bd67..c26ac17 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -38,6 +38,7 @@
 import android.app.IActivityManager;
 import android.app.IBackupAgent;
 import android.app.PendingIntent;
+import android.app.backup.BackupAgent;
 import android.app.backup.BackupManager;
 import android.app.backup.BackupManagerMonitor;
 import android.app.backup.FullBackup;
@@ -79,6 +80,7 @@
 import android.os.SystemClock;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.os.WorkSource;
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
@@ -102,7 +104,7 @@
 import com.android.server.backup.fullbackup.FullBackupEntry;
 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
 import com.android.server.backup.internal.BackupHandler;
-import com.android.server.backup.internal.BackupRequest;
+import com.android.server.backup.keyvalue.BackupRequest;
 import com.android.server.backup.internal.ClearDataObserver;
 import com.android.server.backup.internal.OnTaskFinishedListener;
 import com.android.server.backup.internal.Operation;
@@ -386,6 +388,16 @@
         return mWakelock;
     }
 
+    /**
+     * Sets the {@link WorkSource} of the {@link PowerManager.WakeLock} returned by {@link
+     * #getWakelock()}.
+     */
+    @VisibleForTesting
+    public void setWorkSource(@Nullable WorkSource workSource) {
+        // TODO: This is for testing, unfortunately WakeLock is final and WorkSource is not exposed
+        mWakelock.setWorkSource(workSource);
+    }
+
     public void setWakelock(PowerManager.WakeLock wakelock) {
         mWakelock = wakelock;
     }
@@ -496,6 +508,7 @@
         mDataDir = dataDir;
     }
 
+    @Nullable
     public DataChangedJournal getJournal() {
         return mJournal;
     }
@@ -704,7 +717,7 @@
      * process-local non-lifecycle agent instance, so we manually set up the context
      * topology for it.
      */
-    public PackageManagerBackupAgent makeMetadataAgent() {
+    public BackupAgent makeMetadataAgent() {
         PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager);
         pmAgent.attach(mContext);
         pmAgent.onCreate();
@@ -784,7 +797,7 @@
     }
 
     @VisibleForTesting
-    BackupManagerService(
+    public BackupManagerService(
             Context context,
             Trampoline parent,
             HandlerThread backupThread,
@@ -1478,8 +1491,8 @@
         }
     }
 
-    // fire off a backup agent, blocking until it attaches or times out
-    @Override
+    /** Fires off a backup agent, blocking until it attaches or times out. */
+    @Nullable
     public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode) {
         IBackupAgent agent = null;
         synchronized (mAgentConnectLock) {
@@ -1527,6 +1540,14 @@
         return agent;
     }
 
+    public void unbindAgent(ApplicationInfo app) {
+        try {
+            mActivityManager.unbindBackupAgent(app);
+        } catch (RemoteException e) {
+            // Can't happen - activity manager is local
+        }
+    }
+
     // clear an application's data, blocking until the operation completes or times out
     // if keepSystemState is true, we intentionally do not also clear system state that
     // would ordinarily also be cleared, because we aren't actually wiping the app back
@@ -1749,6 +1770,16 @@
         }
     }
 
+    public void putOperation(int token, Operation operation) {
+        if (MORE_DEBUG) {
+            Slog.d(TAG, "Adding operation token=" + Integer.toHexString(token) + ", operation type="
+                    + operation.type);
+        }
+        synchronized (mCurrentOpLock) {
+            mCurrentOperations.put(token, operation);
+        }
+    }
+
     public void removeOperation(int token) {
         if (MORE_DEBUG) {
             Slog.d(TAG, "Removing operation token=" + Integer.toHexString(token));
diff --git a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
index f2219a0..a38a0e9 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
@@ -49,9 +49,6 @@
 
   boolean hasBackupPassword();
 
-  // fire off a backup agent, blocking until it attaches or times out
-  IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode);
-
   // Get the restore-set token for the best-available restore set for this package:
   // the active set if possible, else the ancestral one.  Returns zero if none available.
   long getAvailableRestoreToken(String packageName);
diff --git a/services/backup/java/com/android/server/backup/DataChangedJournal.java b/services/backup/java/com/android/server/backup/DataChangedJournal.java
index c2d3829..498185c 100644
--- a/services/backup/java/com/android/server/backup/DataChangedJournal.java
+++ b/services/backup/java/com/android/server/backup/DataChangedJournal.java
@@ -25,6 +25,8 @@
 import java.io.IOException;
 import java.io.RandomAccessFile;
 import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
 
 /**
  * A journal of packages that have indicated that their data has changed (and therefore should be
@@ -64,12 +66,12 @@
     }
 
     /**
-     * Invokes {@link Consumer#accept(String)} with every package name in the journal file.
+     * Invokes {@link Consumer#accept(Object)} with every package name in the journal file.
      *
      * @param consumer The callback.
      * @throws IOException If there is an IO error reading from the file.
      */
-    public void forEach(Consumer consumer) throws IOException {
+    public void forEach(Consumer<String> consumer) throws IOException {
         try (
             BufferedInputStream bufferedInputStream = new BufferedInputStream(
                     new FileInputStream(mFile), BUFFER_SIZE_BYTES);
@@ -83,6 +85,17 @@
     }
 
     /**
+     * Returns a list with the packages in this journal.
+     *
+     * @throws IOException If there is an IO error reading from the file.
+     */
+    public List<String> getPackages() throws IOException {
+        List<String> packages = new ArrayList<>();
+        forEach(packages::add);
+        return packages;
+    }
+
+    /**
      * Deletes the journal from the filesystem.
      *
      * @return {@code true} if successfully deleted journal.
@@ -110,14 +123,6 @@
     }
 
     /**
-     * Consumer for iterating over package names in the journal.
-     */
-    @FunctionalInterface
-    public interface Consumer {
-        void accept(String packageName);
-    }
-
-    /**
      * Creates a new journal with a random file name in the given journal directory.
      *
      * @param journalDirectory The directory where journals are kept.
diff --git a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
index 7f0030a..30ec8ab 100644
--- a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
@@ -9,6 +9,7 @@
 
 import android.app.ApplicationThreadConstants;
 import android.app.IBackupAgent;
+import android.app.backup.IBackupCallback;
 import android.app.backup.FullBackup;
 import android.app.backup.FullBackupDataOutput;
 import android.content.pm.ApplicationInfo;
@@ -20,6 +21,7 @@
 import android.util.Slog;
 
 import com.android.internal.util.Preconditions;
+import com.android.server.backup.remote.ServiceBackupCallback;
 import com.android.server.backup.utils.FullBackupUtils;
 
 import libcore.io.IoUtils;
@@ -47,7 +49,7 @@
     private static final String BACKUP_KEY_VALUE_BACKUP_DATA_FILENAME_SUFFIX = ".data";
     private static final String BACKUP_KEY_VALUE_NEW_STATE_FILENAME_SUFFIX = ".new";
 
-    private BackupManagerServiceInterface mBackupManagerService;
+    private BackupManagerService mBackupManagerService;
     private final PackageManager mPackageManager;
     private final OutputStream mOutput;
     private final PackageInfo mCurrentPackage;
@@ -63,7 +65,7 @@
     private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     public KeyValueAdbBackupEngine(OutputStream output, PackageInfo packageInfo,
-            BackupManagerServiceInterface backupManagerService, PackageManager packageManager,
+            BackupManagerService backupManagerService, PackageManager packageManager,
             File baseStateDir, File dataDir) {
         mOutput = output;
         mCurrentPackage = packageInfo;
@@ -158,10 +160,17 @@
             mBackupManagerService.prepareOperationTimeout(token, kvBackupAgentTimeoutMillis, null,
                     OP_TYPE_BACKUP_WAIT);
 
+            IBackupCallback callback =
+                    new ServiceBackupCallback(
+                            mBackupManagerService.getBackupManagerBinder(), token);
             // Start backup and wait for BackupManagerService to get callback for success or timeout
             agent.doBackup(
-                    mSavedState, mBackupData, mNewState, Long.MAX_VALUE, token,
-                    mBackupManagerService.getBackupManagerBinder(), /*transportFlags=*/ 0);
+                    mSavedState,
+                    mBackupData,
+                    mNewState,
+                    /* quotaBytes */ Long.MAX_VALUE,
+                    callback,
+                    /* transportFlags */ 0);
             if (!mBackupManagerService.waitUntilOperationComplete(token)) {
                 Slog.e(TAG, "Key-value backup failed on package " + packageName);
                 return false;
diff --git a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
index d8411e2..c805783 100644
--- a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
+++ b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
@@ -102,6 +102,12 @@
         }
     }
 
+    public static boolean isScheduled() {
+        synchronized (KeyValueBackupJob.class) {
+            return sScheduled;
+        }
+    }
+
     @Override
     public boolean onStartJob(JobParameters params) {
         synchronized (KeyValueBackupJob.class) {
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index a40afc3..f7c1c10 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -136,7 +136,7 @@
     CountDownLatch mLatch;
     FullBackupJob mJob;             // if a scheduled job needs to be finished afterwards
     IBackupObserver mBackupObserver;
-    IBackupManagerMonitor mMonitor;
+    @Nullable private IBackupManagerMonitor mMonitor;
     boolean mUserInitiated;
     SinglePackageBackupRunner mBackupRunner;
     private final int mBackupRunnerOpToken;
@@ -154,7 +154,7 @@
             IFullBackupRestoreObserver observer,
             String[] whichPackages, boolean updateSchedule,
             FullBackupJob runningJob, CountDownLatch latch, IBackupObserver backupObserver,
-            IBackupManagerMonitor monitor, @Nullable OnTaskFinishedListener listener,
+            @Nullable IBackupManagerMonitor monitor, @Nullable OnTaskFinishedListener listener,
             boolean userInitiated) {
         super(observer);
         this.backupManagerService = backupManagerService;
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index 69f08ae..f66d8cc 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -38,10 +38,11 @@
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.DataChangedJournal;
-import com.android.server.backup.transport.TransportClient;
 import com.android.server.backup.TransportManager;
 import com.android.server.backup.fullbackup.PerformAdbBackupTask;
 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
+import com.android.server.backup.keyvalue.BackupRequest;
+import com.android.server.backup.keyvalue.KeyValueBackupTask;
 import com.android.server.backup.params.AdbBackupParams;
 import com.android.server.backup.params.AdbParams;
 import com.android.server.backup.params.AdbRestoreParams;
@@ -52,9 +53,11 @@
 import com.android.server.backup.params.RestoreParams;
 import com.android.server.backup.restore.PerformAdbRestoreTask;
 import com.android.server.backup.restore.PerformUnifiedRestoreTask;
+import com.android.server.backup.transport.TransportClient;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 
 /**
  * Asynchronous backup/restore handler thread.
@@ -119,8 +122,8 @@
                     break;
                 }
 
-                // snapshot the pending-backup set and work on that
-                ArrayList<BackupRequest> queue = new ArrayList<>();
+                // Snapshot the pending-backup set and work on that.
+                List<String> queue = new ArrayList<>();
                 DataChangedJournal oldJournal = backupManagerService.getJournal();
                 synchronized (backupManagerService.getQueueLock()) {
                     // Do we have any work to do?  Construct the work queue
@@ -128,7 +131,7 @@
                     // the backup.
                     if (backupManagerService.getPendingBackups().size() > 0) {
                         for (BackupRequest b : backupManagerService.getPendingBackups().values()) {
-                            queue.add(b);
+                            queue.add(b.packageName);
                         }
                         if (DEBUG) {
                             Slog.v(TAG, "clearing pending backups");
@@ -150,17 +153,22 @@
                 if (queue.size() > 0) {
                     // Spin up a backup state sequence and set it running
                     try {
-                        String dirName = transport.transportDirName();
                         OnTaskFinishedListener listener =
                                 caller ->
                                         transportManager
                                                 .disposeOfTransportClient(transportClient, caller);
-                        PerformBackupTask pbt = new PerformBackupTask(
-                                backupManagerService, transportClient, dirName, queue,
-                                oldJournal, null, null, listener, Collections.emptyList(), false,
-                                false /* nonIncremental */);
-                        Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
-                        sendMessage(pbtMessage);
+                        KeyValueBackupTask.start(
+                                backupManagerService,
+                                transportClient,
+                                transport.transportDirName(),
+                                queue,
+                                oldJournal,
+                                /* observer */ null,
+                                /* monitor */ null,
+                                listener,
+                                Collections.emptyList(),
+                                /* userInitiated */ false,
+                                /* nonIncremental */ false);
                     } catch (Exception e) {
                         // unable to ask the transport its dir name -- transient failure, since
                         // the above check succeeded.  Try again next time.
@@ -398,20 +406,21 @@
                 if (MORE_DEBUG) {
                     Slog.d(TAG, "MSG_REQUEST_BACKUP observer=" + params.observer);
                 }
-                ArrayList<BackupRequest> kvQueue = new ArrayList<>();
-                for (String packageName : params.kvPackages) {
-                    kvQueue.add(new BackupRequest(packageName));
-                }
                 backupManagerService.setBackupRunning(true);
                 backupManagerService.getWakelock().acquire();
 
-                PerformBackupTask pbt = new PerformBackupTask(
+                KeyValueBackupTask.start(
                         backupManagerService,
-                        params.transportClient, params.dirName,
-                        kvQueue, null, params.observer, params.monitor, params.listener,
-                        params.fullPackages, true, params.nonIncrementalBackup);
-                Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
-                sendMessage(pbtMessage);
+                        params.transportClient,
+                        params.dirName,
+                        params.kvPackages,
+                        /* dataChangedJournal */ null,
+                        params.observer,
+                        params.monitor,
+                        params.listener,
+                        params.fullPackages,
+                        /* userInitiated */ true,
+                        params.nonIncrementalBackup);
                 break;
             }
 
diff --git a/services/backup/java/com/android/server/backup/internal/BackupRequest.java b/services/backup/java/com/android/server/backup/internal/BackupRequest.java
deleted file mode 100644
index 01e4385..0000000
--- a/services/backup/java/com/android/server/backup/internal/BackupRequest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.backup.internal;
-
-import java.util.Objects;
-
-/**
- * Set of backup services that have pending changes.
- */
-public class BackupRequest {
-    public String packageName;
-
-    public BackupRequest(String pkgName) {
-        packageName = pkgName;
-    }
-
-    public String toString() {
-        return "BackupRequest{pkg=" + packageName + "}";
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof BackupRequest)) {
-            return false;
-        }
-        BackupRequest that = (BackupRequest) o;
-        return Objects.equals(packageName, that.packageName);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(packageName);
-    }
-}
diff --git a/services/backup/java/com/android/server/backup/internal/BackupState.java b/services/backup/java/com/android/server/backup/internal/BackupState.java
deleted file mode 100644
index 937b167..0000000
--- a/services/backup/java/com/android/server/backup/internal/BackupState.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.android.server.backup.internal;
-
-/**
- * Current state of the backup.
- */
-enum BackupState {
-    INITIAL,
-    BACKUP_PM,
-    RUNNING_QUEUE,
-    FINAL
-}
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
deleted file mode 100644
index ae43299..0000000
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ /dev/null
@@ -1,1217 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.backup.internal;
-
-import static com.android.server.backup.BackupManagerService.DEBUG;
-import static com.android.server.backup.BackupManagerService.DEBUG_BACKUP_TRACE;
-import static com.android.server.backup.BackupManagerService.KEY_WIDGET_STATE;
-import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.BackupManagerService.OP_PENDING;
-import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP;
-import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
-import static com.android.server.backup.BackupManagerService.PACKAGE_MANAGER_SENTINEL;
-import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT;
-import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
-
-import android.annotation.Nullable;
-import android.app.ApplicationThreadConstants;
-import android.app.IBackupAgent;
-import android.app.backup.BackupDataInput;
-import android.app.backup.BackupDataOutput;
-import android.app.backup.BackupManager;
-import android.app.backup.BackupManagerMonitor;
-import android.app.backup.BackupTransport;
-import android.app.backup.IBackupManagerMonitor;
-import android.app.backup.IBackupObserver;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.SELinux;
-import android.os.UserHandle;
-import android.os.WorkSource;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.util.EventLog;
-import android.util.Slog;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.backup.IBackupTransport;
-import com.android.internal.util.Preconditions;
-import com.android.server.AppWidgetBackupBridge;
-import com.android.server.EventLogTags;
-import com.android.server.backup.BackupAgentTimeoutParameters;
-import com.android.server.backup.BackupRestoreTask;
-import com.android.server.backup.DataChangedJournal;
-import com.android.server.backup.KeyValueBackupJob;
-import com.android.server.backup.PackageManagerBackupAgent;
-import com.android.server.backup.BackupManagerService;
-import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
-import com.android.server.backup.transport.TransportClient;
-import com.android.server.backup.transport.TransportUtils;
-import com.android.server.backup.utils.AppBackupUtils;
-import com.android.server.backup.utils.BackupManagerMonitorUtils;
-import com.android.server.backup.utils.BackupObserverUtils;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * This class handles the process of backing up a given list of key/value backup packages.
- * Also takes in a list of pending dolly backups and kicks them off when key/value backups
- * are done.
- *
- * Flow:
- * If required, backup @pm@.
- * For each pending key/value backup package:
- *     - Bind to agent.
- *     - Call agent.doBackup()
- *     - Wait either for cancel/timeout or operationComplete() callback from the agent.
- * Start task to perform dolly backups.
- *
- * There are three entry points into this class:
- *     - execute() [Called from the handler thread]
- *     - operationComplete(long result) [Called from the handler thread]
- *     - handleCancel(boolean cancelAll) [Can be called from any thread]
- * These methods synchronize on mCancelLock.
- *
- * Interaction with mCurrentOperations:
- *     - An entry for this task is put into mCurrentOperations for the entire lifetime of the
- *       task. This is useful to cancel the task if required.
- *     - An ephemeral entry is put into mCurrentOperations each time we are waiting on for
- *       response from a backup agent. This is used to plumb timeouts and completion callbacks.
- */
-public class PerformBackupTask implements BackupRestoreTask {
-    private static final String TAG = "PerformBackupTask";
-
-    private BackupManagerService backupManagerService;
-    private final Object mCancelLock = new Object();
-
-    private ArrayList<BackupRequest> mQueue;
-    private ArrayList<BackupRequest> mOriginalQueue;
-    private File mStateDir;
-    @Nullable private DataChangedJournal mJournal;
-    private BackupState mCurrentState;
-    private List<String> mPendingFullBackups;
-    private IBackupObserver mObserver;
-    private IBackupManagerMonitor mMonitor;
-
-    private final TransportClient mTransportClient;
-    private final OnTaskFinishedListener mListener;
-    private final PerformFullTransportBackupTask mFullBackupTask;
-    private final int mCurrentOpToken;
-    private volatile int mEphemeralOpToken;
-
-    // carried information about the current in-flight operation
-    private IBackupAgent mAgentBinder;
-    private PackageInfo mCurrentPackage;
-    private File mSavedStateName;
-    private File mBackupDataName;
-    private File mNewStateName;
-    private ParcelFileDescriptor mSavedState;
-    private ParcelFileDescriptor mBackupData;
-    private ParcelFileDescriptor mNewState;
-    private int mStatus;
-    private boolean mFinished;
-    private final boolean mUserInitiated;
-    private final boolean mNonIncremental;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
-
-    private volatile boolean mCancelAll;
-
-    public PerformBackupTask(BackupManagerService backupManagerService,
-            TransportClient transportClient, String dirName,
-            ArrayList<BackupRequest> queue, @Nullable DataChangedJournal journal,
-            IBackupObserver observer, IBackupManagerMonitor monitor,
-            @Nullable OnTaskFinishedListener listener, List<String> pendingFullBackups,
-            boolean userInitiated, boolean nonIncremental) {
-        this.backupManagerService = backupManagerService;
-        mTransportClient = transportClient;
-        mOriginalQueue = queue;
-        mQueue = new ArrayList<>();
-        mJournal = journal;
-        mObserver = observer;
-        mMonitor = monitor;
-        mListener = (listener != null) ? listener : OnTaskFinishedListener.NOP;
-        mPendingFullBackups = pendingFullBackups;
-        mUserInitiated = userInitiated;
-        mNonIncremental = nonIncremental;
-        mAgentTimeoutParameters = Preconditions.checkNotNull(
-                backupManagerService.getAgentTimeoutParameters(),
-                "Timeout parameters cannot be null");
-
-        mStateDir = new File(backupManagerService.getBaseStateDir(), dirName);
-        mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
-
-        mFinished = false;
-
-        synchronized (backupManagerService.getCurrentOpLock()) {
-            if (backupManagerService.isBackupOperationInProgress()) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Skipping backup since one is already in progress.");
-                }
-                mCancelAll = true;
-                mFullBackupTask = null;
-                mCurrentState = BackupState.FINAL;
-                backupManagerService.addBackupTrace("Skipped. Backup already in progress.");
-            } else {
-                mCurrentState = BackupState.INITIAL;
-                CountDownLatch latch = new CountDownLatch(1);
-                String[] fullBackups =
-                        mPendingFullBackups.toArray(new String[mPendingFullBackups.size()]);
-                mFullBackupTask =
-                        new PerformFullTransportBackupTask(backupManagerService,
-                                transportClient,
-                                /*fullBackupRestoreObserver*/ null,
-                                fullBackups, /*updateSchedule*/ false, /*runningJob*/ null,
-                                latch,
-                                mObserver, mMonitor, mListener, mUserInitiated);
-
-                registerTask();
-                backupManagerService.addBackupTrace("STATE => INITIAL");
-            }
-        }
-    }
-
-    /**
-     * Put this task in the repository of running tasks.
-     */
-    private void registerTask() {
-        synchronized (backupManagerService.getCurrentOpLock()) {
-            backupManagerService.getCurrentOperations().put(
-                    mCurrentOpToken, new Operation(OP_PENDING, this, OP_TYPE_BACKUP));
-        }
-    }
-
-    /**
-     * Remove this task from repository of running tasks.
-     */
-    private void unregisterTask() {
-        backupManagerService.removeOperation(mCurrentOpToken);
-    }
-
-    // Main entry point: perform one chunk of work, updating the state as appropriate
-    // and reposting the next chunk to the primary backup handler thread.
-    @Override
-    @GuardedBy("mCancelLock")
-    public void execute() {
-        synchronized (mCancelLock) {
-            switch (mCurrentState) {
-                case INITIAL:
-                    beginBackup();
-                    break;
-
-                case BACKUP_PM:
-                    backupPm();
-                    break;
-
-                case RUNNING_QUEUE:
-                    invokeNextAgent();
-                    break;
-
-                case FINAL:
-                    if (!mFinished) {
-                        finalizeBackup();
-                    } else {
-                        Slog.e(TAG, "Duplicate finish of K/V pass");
-                    }
-                    break;
-            }
-        }
-    }
-
-    // We're starting a backup pass.  Initialize the transport if we haven't already.
-    private void beginBackup() {
-        if (DEBUG_BACKUP_TRACE) {
-            backupManagerService.clearBackupTrace();
-            StringBuilder b = new StringBuilder(256);
-            b.append("beginBackup: [");
-            for (BackupRequest req : mOriginalQueue) {
-                b.append(' ');
-                b.append(req.packageName);
-            }
-            b.append(" ]");
-            backupManagerService.addBackupTrace(b.toString());
-        }
-
-        mAgentBinder = null;
-        mStatus = BackupTransport.TRANSPORT_OK;
-
-        // Sanity check: if the queue is empty we have no work to do.
-        if (mOriginalQueue.isEmpty() && mPendingFullBackups.isEmpty()) {
-            Slog.w(TAG, "Backup begun with an empty queue - nothing to do.");
-            backupManagerService.addBackupTrace("queue empty at begin");
-            executeNextState(BackupState.FINAL);
-            return;
-        }
-
-        // We need to retain the original queue contents in case of transport
-        // failure, but we want a working copy that we can manipulate along
-        // the way.
-        mQueue = (ArrayList<BackupRequest>) mOriginalQueue.clone();
-
-        // When the transport is forcing non-incremental key/value payloads, we send the
-        // metadata only if it explicitly asks for it.
-        boolean skipPm = mNonIncremental;
-
-        // The app metadata pseudopackage might also be represented in the
-        // backup queue if apps have been added/removed since the last time
-        // we performed a backup.  Drop it from the working queue now that
-        // we're committed to evaluating it for backup regardless.
-        for (int i = 0; i < mQueue.size(); i++) {
-            if (PACKAGE_MANAGER_SENTINEL.equals(
-                    mQueue.get(i).packageName)) {
-                if (MORE_DEBUG) {
-                    Slog.i(TAG, "Metadata in queue; eliding");
-                }
-                mQueue.remove(i);
-                skipPm = false;
-                break;
-            }
-        }
-
-        if (DEBUG) {
-            Slog.v(TAG, "Beginning backup of " + mQueue.size() + " targets");
-        }
-        File pmState = new File(mStateDir, PACKAGE_MANAGER_SENTINEL);
-        try {
-            IBackupTransport transport = mTransportClient.connectOrThrow("PBT.beginBackup()");
-            final String transportName = transport.transportDirName();
-            EventLog.writeEvent(EventLogTags.BACKUP_START, transportName);
-
-            // If we haven't stored package manager metadata yet, we must init the transport.
-            if (mStatus == BackupTransport.TRANSPORT_OK && pmState.length() <= 0) {
-                Slog.i(TAG, "Initializing (wiping) backup state and transport storage");
-                backupManagerService.addBackupTrace("initializing transport " + transportName);
-                backupManagerService.resetBackupState(mStateDir);  // Just to make sure.
-                mStatus = transport.initializeDevice();
-
-                backupManagerService.addBackupTrace("transport.initializeDevice() == " + mStatus);
-                if (mStatus == BackupTransport.TRANSPORT_OK) {
-                    EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
-                } else {
-                    EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
-                    Slog.e(TAG, "Transport error in initializeDevice()");
-                }
-            }
-
-            if (skipPm) {
-                Slog.d(TAG, "Skipping backup of package metadata.");
-                executeNextState(BackupState.RUNNING_QUEUE);
-            } else {
-                // As the package manager is running here in the system process we can just set up
-                // its agent directly. Thus we always run this pass because it's cheap and this way
-                // we guarantee that we don't get out of step even if we're selecting among various
-                // transports at run time.
-                if (mStatus == BackupTransport.TRANSPORT_OK) {
-                    executeNextState(BackupState.BACKUP_PM);
-                }
-            }
-        } catch (Exception e) {
-            Slog.e(TAG, "Error in backup thread during init", e);
-            backupManagerService.addBackupTrace("Exception in backup thread during init: " + e);
-            mStatus = BackupTransport.TRANSPORT_ERROR;
-        } finally {
-            // If we've succeeded so far, we will move to the BACKUP_PM state. If something has gone
-            // wrong then that won't have happen so cleanup.
-            backupManagerService.addBackupTrace("exiting prelim: " + mStatus);
-            if (mStatus != BackupTransport.TRANSPORT_OK) {
-                // if things went wrong at this point, we need to
-                // restage everything and try again later.
-                backupManagerService.resetBackupState(mStateDir);  // Just to make sure.
-                // In case of any other error, it's backup transport error.
-                executeNextState(BackupState.FINAL);
-            }
-        }
-    }
-
-    private void backupPm() {
-        try {
-            // The package manager doesn't have a proper <application> etc, but since it's running
-            // here in the system process we can just set up its agent directly and use a synthetic
-            // BackupRequest.
-            PackageManagerBackupAgent pmAgent = backupManagerService.makeMetadataAgent();
-            mStatus = invokeAgentForBackup(
-                    PACKAGE_MANAGER_SENTINEL,
-                    IBackupAgent.Stub.asInterface(pmAgent.onBind()));
-            backupManagerService.addBackupTrace("PMBA invoke: " + mStatus);
-
-            // Because the PMBA is a local instance, it has already executed its backup callback and
-            // returned.  Blow away the lingering (spurious) pending timeout message for it.
-            backupManagerService.getBackupHandler().removeMessages(
-                    MSG_BACKUP_OPERATION_TIMEOUT);
-        } catch (Exception e) {
-            Slog.e(TAG, "Error in backup thread during pm", e);
-            backupManagerService.addBackupTrace("Exception in backup thread during pm: " + e);
-            mStatus = BackupTransport.TRANSPORT_ERROR;
-        } finally {
-            // If we've succeeded so far, invokeAgentForBackup() will have run the PM
-            // metadata and its completion/timeout callback will continue the state
-            // machine chain.  If it failed that won't happen; we handle that now.
-            backupManagerService.addBackupTrace("exiting backupPm: " + mStatus);
-            if (mStatus != BackupTransport.TRANSPORT_OK) {
-                // if things went wrong at this point, we need to
-                // restage everything and try again later.
-                backupManagerService.resetBackupState(mStateDir);  // Just to make sure.
-                executeNextState(BackupState.FINAL);
-            }
-        }
-    }
-
-    // Transport has been initialized and the PM metadata submitted successfully
-    // if that was warranted.  Now we process the single next thing in the queue.
-    private void invokeNextAgent() {
-        mStatus = BackupTransport.TRANSPORT_OK;
-        backupManagerService.addBackupTrace("invoke q=" + mQueue.size());
-
-        // Sanity check that we have work to do.  If not, skip to the end where
-        // we reestablish the wakelock invariants etc.
-        if (mQueue.isEmpty()) {
-            if (MORE_DEBUG) Slog.i(TAG, "queue now empty");
-            executeNextState(BackupState.FINAL);
-            return;
-        }
-
-        // pop the entry we're going to process on this step
-        BackupRequest request = mQueue.get(0);
-        mQueue.remove(0);
-
-        Slog.d(TAG, "starting key/value backup of " + request);
-        backupManagerService.addBackupTrace("launch agent for " + request.packageName);
-
-        // Verify that the requested app exists; it might be something that
-        // requested a backup but was then uninstalled.  The request was
-        // journalled and rather than tamper with the journal it's safer
-        // to sanity-check here.  This also gives us the classname of the
-        // package's backup agent.
-        try {
-            PackageManager pm = backupManagerService.getPackageManager();
-            mCurrentPackage = pm.getPackageInfo(request.packageName,
-                    PackageManager.GET_SIGNING_CERTIFICATES);
-            if (!AppBackupUtils.appIsEligibleForBackup(mCurrentPackage.applicationInfo, pm)) {
-                // The manifest has changed but we had a stale backup request pending.
-                // This won't happen again because the app won't be requesting further
-                // backups.
-                Slog.i(TAG, "Package " + request.packageName
-                        + " no longer supports backup; skipping");
-                backupManagerService.addBackupTrace("skipping - not eligible, completion is noop");
-                // Shouldn't happen in case of requested backup, as pre-check was done in
-                // #requestBackup(), except to app update done concurrently
-                BackupObserverUtils.sendBackupOnPackageResult(mObserver,
-                        mCurrentPackage.packageName,
-                        BackupManager.ERROR_BACKUP_NOT_ALLOWED);
-                executeNextState(BackupState.RUNNING_QUEUE);
-                return;
-            }
-
-            if (AppBackupUtils.appGetsFullBackup(mCurrentPackage)) {
-                // It's possible that this app *formerly* was enqueued for key/value backup,
-                // but has since been updated and now only supports the full-data path.
-                // Don't proceed with a key/value backup for it in this case.
-                Slog.i(TAG, "Package " + request.packageName
-                        + " requests full-data rather than key/value; skipping");
-                backupManagerService.addBackupTrace(
-                        "skipping - fullBackupOnly, completion is noop");
-                // Shouldn't happen in case of requested backup, as pre-check was done in
-                // #requestBackup()
-                BackupObserverUtils.sendBackupOnPackageResult(mObserver,
-                        mCurrentPackage.packageName,
-                        BackupManager.ERROR_BACKUP_NOT_ALLOWED);
-                executeNextState(BackupState.RUNNING_QUEUE);
-                return;
-            }
-
-            if (AppBackupUtils.appIsStopped(mCurrentPackage.applicationInfo)) {
-                // The app has been force-stopped or cleared or just installed,
-                // and not yet launched out of that state, so just as it won't
-                // receive broadcasts, we won't run it for backup.
-                backupManagerService.addBackupTrace("skipping - stopped");
-                BackupObserverUtils.sendBackupOnPackageResult(mObserver,
-                        mCurrentPackage.packageName,
-                        BackupManager.ERROR_BACKUP_NOT_ALLOWED);
-                executeNextState(BackupState.RUNNING_QUEUE);
-                return;
-            }
-
-            IBackupAgent agent = null;
-            try {
-                backupManagerService.getWakelock().setWorkSource(
-                        new WorkSource(mCurrentPackage.applicationInfo.uid));
-                agent = backupManagerService.bindToAgentSynchronous(mCurrentPackage.applicationInfo,
-                        ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
-                backupManagerService.addBackupTrace("agent bound; a? = " + (agent != null));
-                if (agent != null) {
-                    mAgentBinder = agent;
-                    mStatus = invokeAgentForBackup(request.packageName, agent);
-                    // at this point we'll either get a completion callback from the
-                    // agent, or a timeout message on the main handler.  either way, we're
-                    // done here as long as we're successful so far.
-                } else {
-                    // Timeout waiting for the agent
-                    mStatus = BackupTransport.AGENT_ERROR;
-                }
-            } catch (SecurityException ex) {
-                // Try for the next one.
-                Slog.d(TAG, "error in bind/backup", ex);
-                mStatus = BackupTransport.AGENT_ERROR;
-                backupManagerService.addBackupTrace("agent SE");
-            }
-        } catch (NameNotFoundException e) {
-            Slog.d(TAG, "Package does not exist; skipping");
-            backupManagerService.addBackupTrace("no such package");
-            mStatus = BackupTransport.AGENT_UNKNOWN;
-        } finally {
-            backupManagerService.getWakelock().setWorkSource(null);
-
-            // If there was an agent error, no timeout/completion handling will occur.
-            // That means we need to direct to the next state ourselves.
-            if (mStatus != BackupTransport.TRANSPORT_OK) {
-                BackupState nextState = BackupState.RUNNING_QUEUE;
-                mAgentBinder = null;
-
-                // An agent-level failure means we reenqueue this one agent for
-                // a later retry, but otherwise proceed normally.
-                if (mStatus == BackupTransport.AGENT_ERROR) {
-                    if (MORE_DEBUG) {
-                        Slog.i(TAG, "Agent failure for " + request.packageName
-                                + " - restaging");
-                    }
-                    backupManagerService.dataChangedImpl(request.packageName);
-                    mStatus = BackupTransport.TRANSPORT_OK;
-                    if (mQueue.isEmpty()) nextState = BackupState.FINAL;
-                    BackupObserverUtils
-                            .sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
-                                    BackupManager.ERROR_AGENT_FAILURE);
-                } else if (mStatus == BackupTransport.AGENT_UNKNOWN) {
-                    // Failed lookup of the app, so we couldn't bring up an agent, but
-                    // we're otherwise fine.  Just drop it and go on to the next as usual.
-                    mStatus = BackupTransport.TRANSPORT_OK;
-                    BackupObserverUtils
-                            .sendBackupOnPackageResult(mObserver, request.packageName,
-                                    BackupManager.ERROR_PACKAGE_NOT_FOUND);
-                } else {
-                    // Transport-level failure means we reenqueue everything
-                    revertAndEndBackup();
-                    nextState = BackupState.FINAL;
-                }
-
-                executeNextState(nextState);
-            } else {
-                // success case
-                backupManagerService.addBackupTrace("expecting completion/timeout callback");
-            }
-        }
-    }
-
-    private void finalizeBackup() {
-        backupManagerService.addBackupTrace("finishing");
-
-        // Mark packages that we didn't backup (because backup was cancelled, etc.) as needing
-        // backup.
-        for (BackupRequest req : mQueue) {
-            backupManagerService.dataChangedImpl(req.packageName);
-        }
-
-        // Either backup was successful, in which case we of course do not need
-        // this pass's journal any more; or it failed, in which case we just
-        // re-enqueued all of these packages in the current active journal.
-        // Either way, we no longer need this pass's journal.
-        if (mJournal != null && !mJournal.delete()) {
-            Slog.e(TAG, "Unable to remove backup journal file " + mJournal);
-        }
-
-        // If everything actually went through and this is the first time we've
-        // done a backup, we can now record what the current backup dataset token
-        // is.
-        String callerLogString = "PBT.finalizeBackup()";
-        if ((backupManagerService.getCurrentToken() == 0) && (mStatus
-                == BackupTransport.TRANSPORT_OK)) {
-            backupManagerService.addBackupTrace("success; recording token");
-            try {
-                IBackupTransport transport =
-                        mTransportClient.connectOrThrow(callerLogString);
-                backupManagerService.setCurrentToken(transport.getCurrentRestoreSet());
-                backupManagerService.writeRestoreTokens();
-            } catch (Exception e) {
-                // nothing for it at this point, unfortunately, but this will be
-                // recorded the next time we fully succeed.
-                Slog.e(TAG, "Transport threw reporting restore set: " + e.getMessage());
-                backupManagerService.addBackupTrace("transport threw returning token");
-            }
-        }
-
-        // Set up the next backup pass - at this point we can set mBackupRunning
-        // to false to allow another pass to fire, because we're done with the
-        // state machine sequence and the wakelock is refcounted.
-        synchronized (backupManagerService.getQueueLock()) {
-            backupManagerService.setBackupRunning(false);
-            if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
-                // Make sure we back up everything and perform the one-time init
-                if (MORE_DEBUG) {
-                    Slog.d(TAG, "Server requires init; rerunning");
-                }
-                backupManagerService.addBackupTrace("init required; rerunning");
-                try {
-                    String name = backupManagerService.getTransportManager()
-                            .getTransportName(mTransportClient.getTransportComponent());
-                    backupManagerService.getPendingInits().add(name);
-                } catch (Exception e) {
-                    Slog.w(TAG, "Failed to query transport name for init: " + e.getMessage());
-                    // swallow it and proceed; we don't rely on this
-                }
-                clearMetadata();
-                backupManagerService.backupNow();
-            }
-        }
-
-        backupManagerService.clearBackupTrace();
-
-        unregisterTask();
-
-        if (!mCancelAll && mStatus == BackupTransport.TRANSPORT_OK &&
-                mPendingFullBackups != null && !mPendingFullBackups.isEmpty()) {
-            Slog.d(TAG, "Starting full backups for: " + mPendingFullBackups);
-            // Acquiring wakelock for PerformFullTransportBackupTask before its start.
-            backupManagerService.getWakelock().acquire();
-            // The full-backup task is now responsible for calling onFinish() on mListener, which
-            // was the listener we passed it.
-            (new Thread(mFullBackupTask, "full-transport-requested")).start();
-        } else if (mCancelAll) {
-            mListener.onFinished(callerLogString);
-            if (mFullBackupTask != null) {
-                mFullBackupTask.unregisterTask();
-            }
-            BackupObserverUtils.sendBackupFinished(mObserver,
-                    BackupManager.ERROR_BACKUP_CANCELLED);
-        } else {
-            mListener.onFinished(callerLogString);
-            mFullBackupTask.unregisterTask();
-            switch (mStatus) {
-                case BackupTransport.TRANSPORT_OK:
-                case BackupTransport.TRANSPORT_QUOTA_EXCEEDED:
-                case BackupTransport.TRANSPORT_PACKAGE_REJECTED:
-                    BackupObserverUtils.sendBackupFinished(mObserver,
-                            BackupManager.SUCCESS);
-                    break;
-                case BackupTransport.TRANSPORT_NOT_INITIALIZED:
-                    BackupObserverUtils.sendBackupFinished(mObserver,
-                            BackupManager.ERROR_TRANSPORT_ABORTED);
-                    break;
-                case BackupTransport.TRANSPORT_ERROR:
-                default:
-                    BackupObserverUtils.sendBackupFinished(mObserver,
-                            BackupManager.ERROR_TRANSPORT_ABORTED);
-                    break;
-            }
-        }
-        mFinished = true;
-        Slog.i(TAG, "K/V backup pass finished.");
-        // Only once we're entirely finished do we release the wakelock for k/v backup.
-        backupManagerService.getWakelock().release();
-    }
-
-    // Remove the PM metadata state. This will generate an init on the next pass.
-    private void clearMetadata() {
-        final File pmState = new File(mStateDir, PACKAGE_MANAGER_SENTINEL);
-        if (pmState.exists()) pmState.delete();
-    }
-
-    // Invoke an agent's doBackup() and start a timeout message spinning on the main
-    // handler in case it doesn't get back to us.
-    private int invokeAgentForBackup(String packageName, IBackupAgent agent) {
-        if (DEBUG) {
-            Slog.d(TAG, "invokeAgentForBackup on " + packageName);
-        }
-        backupManagerService.addBackupTrace("invoking " + packageName);
-
-        File blankStateName = new File(mStateDir, "blank_state");
-        mSavedStateName = new File(mStateDir, packageName);
-        mBackupDataName = new File(backupManagerService.getDataDir(), packageName + ".data");
-        mNewStateName = new File(mStateDir, packageName + ".new");
-        if (MORE_DEBUG) Slog.d(TAG, "data file: " + mBackupDataName);
-
-        mSavedState = null;
-        mBackupData = null;
-        mNewState = null;
-
-        boolean callingAgent = false;
-        mEphemeralOpToken = backupManagerService.generateRandomIntegerToken();
-        try {
-            // Look up the package info & signatures.  This is first so that if it
-            // throws an exception, there's no file setup yet that would need to
-            // be unraveled.
-            if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) {
-                // The metadata 'package' is synthetic; construct one and make
-                // sure our global state is pointed at it
-                mCurrentPackage = new PackageInfo();
-                mCurrentPackage.packageName = packageName;
-            }
-
-            // In a full backup, we pass a null ParcelFileDescriptor as
-            // the saved-state "file". For key/value backups we pass the old state if
-            // an incremental backup is required, and a blank state otherwise.
-            mSavedState = ParcelFileDescriptor.open(
-                    mNonIncremental ? blankStateName : mSavedStateName,
-                    ParcelFileDescriptor.MODE_READ_ONLY |
-                            ParcelFileDescriptor.MODE_CREATE);  // Make an empty file if necessary
-
-            mBackupData = ParcelFileDescriptor.open(mBackupDataName,
-                    ParcelFileDescriptor.MODE_READ_WRITE |
-                            ParcelFileDescriptor.MODE_CREATE |
-                            ParcelFileDescriptor.MODE_TRUNCATE);
-
-            if (!SELinux.restorecon(mBackupDataName)) {
-                Slog.e(TAG, "SELinux restorecon failed on " + mBackupDataName);
-            }
-
-            mNewState = ParcelFileDescriptor.open(mNewStateName,
-                    ParcelFileDescriptor.MODE_READ_WRITE |
-                            ParcelFileDescriptor.MODE_CREATE |
-                            ParcelFileDescriptor.MODE_TRUNCATE);
-
-            IBackupTransport transport =
-                    mTransportClient.connectOrThrow("PBT.invokeAgentForBackup()");
-
-            final long quota = transport.getBackupQuota(packageName, false /* isFullBackup */);
-            callingAgent = true;
-
-            // Initiate the target's backup pass
-            backupManagerService.addBackupTrace("setting timeout");
-            long kvBackupAgentTimeoutMillis =
-                    mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis();
-            backupManagerService.prepareOperationTimeout(
-                    mEphemeralOpToken, kvBackupAgentTimeoutMillis, this, OP_TYPE_BACKUP_WAIT);
-            backupManagerService.addBackupTrace("calling agent doBackup()");
-
-            agent.doBackup(
-                    mSavedState, mBackupData, mNewState, quota, mEphemeralOpToken,
-                    backupManagerService.getBackupManagerBinder(), transport.getTransportFlags());
-        } catch (Exception e) {
-            Slog.e(TAG, "Error invoking for backup on " + packageName + ". " + e);
-            backupManagerService.addBackupTrace("exception: " + e);
-            EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName,
-                    e.toString());
-            errorCleanup();
-            return callingAgent ? BackupTransport.AGENT_ERROR
-                    : BackupTransport.TRANSPORT_ERROR;
-        } finally {
-            if (mNonIncremental) {
-                blankStateName.delete();
-            }
-        }
-
-        // At this point the agent is off and running.  The next thing to happen will
-        // either be a callback from the agent, at which point we'll process its data
-        // for transport, or a timeout.  Either way the next phase will happen in
-        // response to the TimeoutHandler interface callbacks.
-        backupManagerService.addBackupTrace("invoke success");
-        return BackupTransport.TRANSPORT_OK;
-    }
-
-    private void failAgent(IBackupAgent agent, String message) {
-        try {
-            agent.fail(message);
-        } catch (Exception e) {
-            Slog.w(TAG, "Error conveying failure to " + mCurrentPackage.packageName);
-        }
-    }
-
-    // SHA-1 a byte array and return the result in hex
-    private String SHA1Checksum(byte[] input) {
-        final byte[] checksum;
-        try {
-            MessageDigest md = MessageDigest.getInstance("SHA-1");
-            checksum = md.digest(input);
-        } catch (NoSuchAlgorithmException e) {
-            Slog.e(TAG, "Unable to use SHA-1!");
-            return "00";
-        }
-
-        StringBuffer sb = new StringBuffer(checksum.length * 2);
-        for (int i = 0; i < checksum.length; i++) {
-            sb.append(Integer.toHexString(checksum[i]));
-        }
-        return sb.toString();
-    }
-
-    private void writeWidgetPayloadIfAppropriate(FileDescriptor fd, String pkgName)
-            throws IOException {
-        // TODO: http://b/22388012
-        byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName,
-                UserHandle.USER_SYSTEM);
-        // has the widget state changed since last time?
-        final File widgetFile = new File(mStateDir, pkgName + "_widget");
-        final boolean priorStateExists = widgetFile.exists();
-
-        if (MORE_DEBUG) {
-            if (priorStateExists || widgetState != null) {
-                Slog.i(TAG, "Checking widget update: state=" + (widgetState != null)
-                        + " prior=" + priorStateExists);
-            }
-        }
-
-        if (!priorStateExists && widgetState == null) {
-            // no prior state, no new state => nothing to do
-            return;
-        }
-
-        // if the new state is not null, we might need to compare checksums to
-        // determine whether to update the widget blob in the archive.  If the
-        // widget state *is* null, we know a priori at this point that we simply
-        // need to commit a deletion for it.
-        String newChecksum = null;
-        if (widgetState != null) {
-            newChecksum = SHA1Checksum(widgetState);
-            if (priorStateExists) {
-                final String priorChecksum;
-                try (
-                        FileInputStream fin = new FileInputStream(widgetFile);
-                        DataInputStream in = new DataInputStream(fin)
-                ) {
-                    priorChecksum = in.readUTF();
-                }
-                if (Objects.equals(newChecksum, priorChecksum)) {
-                    // Same checksum => no state change => don't rewrite the widget data
-                    return;
-                }
-            }
-        } // else widget state *became* empty, so we need to commit a deletion
-
-        BackupDataOutput out = new BackupDataOutput(fd);
-        if (widgetState != null) {
-            try (
-                    FileOutputStream fout = new FileOutputStream(widgetFile);
-                    DataOutputStream stateOut = new DataOutputStream(fout)
-            ) {
-                stateOut.writeUTF(newChecksum);
-            }
-
-            out.writeEntityHeader(KEY_WIDGET_STATE, widgetState.length);
-            out.writeEntityData(widgetState, widgetState.length);
-        } else {
-            // Widget state for this app has been removed; commit a deletion
-            out.writeEntityHeader(KEY_WIDGET_STATE, -1);
-            widgetFile.delete();
-        }
-    }
-
-    @Override
-    @GuardedBy("mCancelLock")
-    public void operationComplete(long unusedResult) {
-        backupManagerService.removeOperation(mEphemeralOpToken);
-        synchronized (mCancelLock) {
-            // The agent reported back to us!
-            if (mFinished) {
-                Slog.d(TAG, "operationComplete received after task finished.");
-                return;
-            }
-
-            if (mBackupData == null) {
-                // This callback was racing with our timeout, so we've cleaned up the
-                // agent state already and are on to the next thing.  We have nothing
-                // further to do here: agent state having been cleared means that we've
-                // initiated the appropriate next operation.
-                final String pkg = (mCurrentPackage != null)
-                        ? mCurrentPackage.packageName : "[none]";
-                if (MORE_DEBUG) {
-                    Slog.i(TAG, "Callback after agent teardown: " + pkg);
-                }
-                backupManagerService.addBackupTrace("late opComplete; curPkg = " + pkg);
-                return;
-            }
-
-            final String pkgName = mCurrentPackage.packageName;
-            final long filepos = mBackupDataName.length();
-            FileDescriptor fd = mBackupData.getFileDescriptor();
-            try {
-                // If it's a 3rd party app, see whether they wrote any protected keys
-                // and complain mightily if they are attempting shenanigans.
-                if (mCurrentPackage.applicationInfo != null &&
-                        (mCurrentPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
-                                == 0) {
-                    ParcelFileDescriptor readFd = ParcelFileDescriptor.open(mBackupDataName,
-                            ParcelFileDescriptor.MODE_READ_ONLY);
-                    BackupDataInput in = new BackupDataInput(readFd.getFileDescriptor());
-                    try {
-                        while (in.readNextHeader()) {
-                            final String key = in.getKey();
-                            if (key != null && key.charAt(0) >= 0xff00) {
-                                // Not okay: crash them and bail.
-                                failAgent(mAgentBinder, "Illegal backup key: " + key);
-                                backupManagerService
-                                        .addBackupTrace("illegal key " + key + " from " + pkgName);
-                                EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
-                                        "bad key");
-                                mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
-                                        BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY,
-                                        mCurrentPackage,
-                                        BackupManagerMonitor
-                                                .LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                        BackupManagerMonitorUtils.putMonitoringExtra(null,
-                                                BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY,
-                                                key));
-                                backupManagerService.getBackupHandler().removeMessages(
-                                        MSG_BACKUP_OPERATION_TIMEOUT);
-                                BackupObserverUtils
-                                        .sendBackupOnPackageResult(mObserver, pkgName,
-                                                BackupManager.ERROR_AGENT_FAILURE);
-                                errorCleanup();
-                                if (MORE_DEBUG) {
-                                    Slog.i(TAG, "Agent failure for " + pkgName
-                                            + " with illegal key: " + key + "; dropped");
-                                }
-                                executeNextState(mQueue.isEmpty() ? BackupState.FINAL
-                                        : BackupState.RUNNING_QUEUE);
-                                return;
-                            }
-                            in.skipEntityData();
-                        }
-                    } finally {
-                        if (readFd != null) {
-                            readFd.close();
-                        }
-                    }
-                }
-
-                // Piggyback the widget state payload, if any
-                writeWidgetPayloadIfAppropriate(fd, pkgName);
-            } catch (IOException e) {
-                // Hard disk error; recovery/failure policy TBD.  For now roll back,
-                // but we may want to consider this a transport-level failure (i.e.
-                // we're in such a bad state that we can't contemplate doing backup
-                // operations any more during this pass).
-                Slog.w(TAG, "Unable to save widget state for " + pkgName);
-                try {
-                    Os.ftruncate(fd, filepos);
-                } catch (ErrnoException ee) {
-                    Slog.w(TAG, "Unable to roll back!");
-                }
-            }
-
-            // Spin the data off to the transport and proceed with the next stage.
-            if (MORE_DEBUG) {
-                Slog.v(TAG, "operationComplete(): sending data to transport for "
-                        + pkgName);
-            }
-            backupManagerService.getBackupHandler().removeMessages(MSG_BACKUP_OPERATION_TIMEOUT);
-            clearAgentState();
-            backupManagerService.addBackupTrace("operation complete");
-
-            IBackupTransport transport = mTransportClient.connect("PBT.operationComplete()");
-            ParcelFileDescriptor backupData = null;
-            mStatus = BackupTransport.TRANSPORT_OK;
-            long size = 0;
-            try {
-                TransportUtils.checkTransportNotNull(transport);
-                size = mBackupDataName.length();
-                if (size > 0) {
-                    boolean isNonIncremental = mSavedStateName.length() == 0;
-                    if (mStatus == BackupTransport.TRANSPORT_OK) {
-                        backupData = ParcelFileDescriptor.open(mBackupDataName,
-                                ParcelFileDescriptor.MODE_READ_ONLY);
-                        backupManagerService.addBackupTrace("sending data to transport");
-
-                        int userInitiatedFlag =
-                                mUserInitiated ? BackupTransport.FLAG_USER_INITIATED : 0;
-                        int incrementalFlag =
-                                isNonIncremental
-                                    ? BackupTransport.FLAG_NON_INCREMENTAL
-                                    : BackupTransport.FLAG_INCREMENTAL;
-                        int flags = userInitiatedFlag | incrementalFlag;
-
-                        mStatus = transport.performBackup(mCurrentPackage, backupData, flags);
-                    }
-
-                    if (isNonIncremental
-                        && mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
-                        // TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED is only valid if the backup was
-                        // incremental, as if the backup is non-incremental there is no state to
-                        // clear. This avoids us ending up in a retry loop if the transport always
-                        // returns this code.
-                        Slog.w(TAG,
-                                "Transport requested non-incremental but already the case, error");
-                        backupManagerService.addBackupTrace(
-                                "Transport requested non-incremental but already the case, error");
-                        mStatus = BackupTransport.TRANSPORT_ERROR;
-                    }
-
-                    // TODO - We call finishBackup() for each application backed up, because
-                    // we need to know now whether it succeeded or failed.  Instead, we should
-                    // hold off on finishBackup() until the end, which implies holding off on
-                    // renaming *all* the output state files (see below) until that happens.
-
-                    backupManagerService.addBackupTrace("data delivered: " + mStatus);
-                    if (mStatus == BackupTransport.TRANSPORT_OK) {
-                        backupManagerService.addBackupTrace("finishing op on transport");
-                        mStatus = transport.finishBackup();
-                        backupManagerService.addBackupTrace("finished: " + mStatus);
-                    } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
-                        backupManagerService.addBackupTrace("transport rejected package");
-                    }
-                } else {
-                    if (MORE_DEBUG) {
-                        Slog.i(TAG, "no backup data written; not calling transport");
-                    }
-                    backupManagerService.addBackupTrace("no data to send");
-                    mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
-                            BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
-                            mCurrentPackage,
-                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                            null);
-                }
-
-                if (mStatus == BackupTransport.TRANSPORT_OK) {
-                    // After successful transport, delete the now-stale data
-                    // and juggle the files so that next time we supply the agent
-                    // with the new state file it just created.
-                    mBackupDataName.delete();
-                    mNewStateName.renameTo(mSavedStateName);
-                    BackupObserverUtils
-                            .sendBackupOnPackageResult(mObserver, pkgName, BackupManager.SUCCESS);
-                    EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, pkgName, size);
-                    backupManagerService.logBackupComplete(pkgName);
-                } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
-                    // The transport has rejected backup of this specific package.  Roll it
-                    // back but proceed with running the rest of the queue.
-                    mBackupDataName.delete();
-                    mNewStateName.delete();
-                    BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
-                            BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
-                    EventLogTags.writeBackupAgentFailure(pkgName, "Transport rejected");
-                } else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
-                    BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
-                            BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
-                    EventLog.writeEvent(EventLogTags.BACKUP_QUOTA_EXCEEDED, pkgName);
-
-                } else if (mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
-                    Slog.i(TAG, "Transport lost data, retrying package");
-                    backupManagerService.addBackupTrace(
-                            "Transport lost data, retrying package:" + pkgName);
-                    BackupManagerMonitorUtils.monitorEvent(
-                            mMonitor,
-                            BackupManagerMonitor
-                                    .LOG_EVENT_ID_TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED,
-                            mCurrentPackage,
-                            BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
-                            /*extras=*/ null);
-
-                    mBackupDataName.delete();
-                    mSavedStateName.delete();
-                    mNewStateName.delete();
-
-                    // Immediately retry the package by adding it back to the front of the queue.
-                    // We cannot add @pm@ to the queue because we back it up separately at the start
-                    // of the backup pass in state BACKUP_PM. Instead we retry this state (see
-                    // below).
-                    if (!PACKAGE_MANAGER_SENTINEL.equals(pkgName)) {
-                        mQueue.add(0, new BackupRequest(pkgName));
-                    }
-
-                } else {
-                    // Actual transport-level failure to communicate the data to the backend
-                    BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
-                            BackupManager.ERROR_TRANSPORT_ABORTED);
-                    EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
-                }
-            } catch (Exception e) {
-                BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
-                        BackupManager.ERROR_TRANSPORT_ABORTED);
-                Slog.e(TAG, "Transport error backing up " + pkgName, e);
-                EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
-                mStatus = BackupTransport.TRANSPORT_ERROR;
-            } finally {
-                try {
-                    if (backupData != null) backupData.close();
-                } catch (IOException e) {
-                }
-            }
-
-            final BackupState nextState;
-            if (mStatus == BackupTransport.TRANSPORT_OK
-                    || mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
-                // Success or single-package rejection.  Proceed with the next app if any,
-                // otherwise we're done.
-                nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE;
-
-            } else if (mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
-                // We want to immediately retry the current package.
-                if (PACKAGE_MANAGER_SENTINEL.equals(pkgName)) {
-                    nextState = BackupState.BACKUP_PM;
-                } else {
-                    // This is an ordinary package so we will have added it back into the queue
-                    // above. Thus, we proceed processing the queue.
-                    nextState = BackupState.RUNNING_QUEUE;
-                }
-
-            } else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
-                if (MORE_DEBUG) {
-                    Slog.d(TAG, "Package " + mCurrentPackage.packageName +
-                            " hit quota limit on k/v backup");
-                }
-                if (mAgentBinder != null) {
-                    try {
-                        TransportUtils.checkTransportNotNull(transport);
-                        long quota = transport.getBackupQuota(mCurrentPackage.packageName, false);
-                        mAgentBinder.doQuotaExceeded(size, quota);
-                    } catch (Exception e) {
-                        Slog.e(TAG, "Unable to notify about quota exceeded: " + e.getMessage());
-                    }
-                }
-                nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE;
-            } else {
-                // Any other error here indicates a transport-level failure.  That means
-                // we need to halt everything and reschedule everything for next time.
-                revertAndEndBackup();
-                nextState = BackupState.FINAL;
-            }
-
-            executeNextState(nextState);
-        }
-    }
-
-
-    @Override
-    @GuardedBy("mCancelLock")
-    public void handleCancel(boolean cancelAll) {
-        backupManagerService.removeOperation(mEphemeralOpToken);
-        synchronized (mCancelLock) {
-            if (mFinished) {
-                // We have already cancelled this operation.
-                if (MORE_DEBUG) {
-                    Slog.d(TAG, "Ignoring stale cancel. cancelAll=" + cancelAll);
-                }
-                return;
-            }
-            mCancelAll = cancelAll;
-            final String logPackageName = (mCurrentPackage != null)
-                    ? mCurrentPackage.packageName
-                    : "no_package_yet";
-            Slog.i(TAG, "Cancel backing up " + logPackageName);
-            EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, logPackageName);
-            backupManagerService.addBackupTrace(
-                    "cancel of " + logPackageName + ", cancelAll=" + cancelAll);
-            mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
-                    BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
-                    mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
-                    BackupManagerMonitorUtils.putMonitoringExtra(null,
-                            BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL,
-                            mCancelAll));
-            errorCleanup();
-            if (!cancelAll) {
-                // The current agent either timed out or was cancelled running doBackup().
-                // Restage it for the next time we run a backup pass.
-                // !!! TODO: keep track of failure counts per agent, and blacklist those which
-                // fail repeatedly (i.e. have proved themselves to be buggy).
-                executeNextState(
-                        mQueue.isEmpty() ? BackupState.FINAL : BackupState.RUNNING_QUEUE);
-                backupManagerService.dataChangedImpl(mCurrentPackage.packageName);
-            } else {
-                finalizeBackup();
-            }
-        }
-    }
-
-    private void revertAndEndBackup() {
-        if (MORE_DEBUG) {
-            Slog.i(TAG, "Reverting backup queue - restaging everything");
-        }
-        backupManagerService.addBackupTrace("transport error; reverting");
-
-        // We want to reset the backup schedule based on whatever the transport suggests
-        // by way of retry/backoff time.
-        long delay;
-        try {
-            IBackupTransport transport =
-                    mTransportClient.connectOrThrow("PBT.revertAndEndBackup()");
-            delay = transport.requestBackupTime();
-        } catch (Exception e) {
-            Slog.w(TAG, "Unable to contact transport for recommended backoff: " + e.getMessage());
-            delay = 0;  // use the scheduler's default
-        }
-        KeyValueBackupJob.schedule(backupManagerService.getContext(), delay,
-                backupManagerService.getConstants());
-
-        for (BackupRequest request : mOriginalQueue) {
-            backupManagerService.dataChangedImpl(request.packageName);
-        }
-
-    }
-
-    private void errorCleanup() {
-        mBackupDataName.delete();
-        mNewStateName.delete();
-        clearAgentState();
-    }
-
-    // Cleanup common to both success and failure cases
-    private void clearAgentState() {
-        try {
-            if (mSavedState != null) mSavedState.close();
-        } catch (IOException e) {
-        }
-        try {
-            if (mBackupData != null) mBackupData.close();
-        } catch (IOException e) {
-        }
-        try {
-            if (mNewState != null) mNewState.close();
-        } catch (IOException e) {
-        }
-        synchronized (backupManagerService.getCurrentOpLock()) {
-            // Current-operation callback handling requires the validity of these various
-            // bits of internal state as an invariant of the operation still being live.
-            // This means we make sure to clear all of the state in unison inside the lock.
-            backupManagerService.getCurrentOperations().remove(mEphemeralOpToken);
-            mSavedState = mBackupData = mNewState = null;
-        }
-
-        // If this was a pseudopackage there's no associated Activity Manager state
-        if (mCurrentPackage.applicationInfo != null) {
-            backupManagerService.addBackupTrace("unbinding " + mCurrentPackage.packageName);
-            try {  // unbind even on timeout, just in case
-                backupManagerService.getActivityManager().unbindBackupAgent(
-                        mCurrentPackage.applicationInfo);
-            } catch (RemoteException e) { /* can't happen; activity manager is local */ }
-        }
-    }
-
-    private void executeNextState(BackupState nextState) {
-        if (MORE_DEBUG) {
-            Slog.i(TAG, " => executing next step on "
-                    + this + " nextState=" + nextState);
-        }
-        backupManagerService.addBackupTrace("executeNextState => " + nextState);
-        mCurrentState = nextState;
-        Message msg = backupManagerService.getBackupHandler().obtainMessage(
-                MSG_BACKUP_RESTORE_STEP, this);
-        backupManagerService.getBackupHandler().sendMessage(msg);
-    }
-}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/BackupRequest.java b/services/backup/java/com/android/server/backup/keyvalue/BackupRequest.java
new file mode 100644
index 0000000..67b2f72
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/keyvalue/BackupRequest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.keyvalue;
+
+import java.util.Objects;
+
+/**
+ * Set of backup services that have pending changes.
+ */
+public class BackupRequest {
+    public String packageName;
+
+    public BackupRequest(String pkgName) {
+        packageName = pkgName;
+    }
+
+    public String toString() {
+        return "BackupRequest{pkg=" + packageName + "}";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof BackupRequest)) {
+            return false;
+        }
+        BackupRequest that = (BackupRequest) o;
+        return Objects.equals(packageName, that.packageName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(packageName);
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
new file mode 100644
index 0000000..8fbca4b
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.keyvalue;
+
+import android.annotation.Nullable;
+import android.app.backup.BackupManager;
+import android.app.backup.BackupManagerMonitor;
+import android.app.backup.BackupTransport;
+import android.app.backup.IBackupManagerMonitor;
+import android.app.backup.IBackupObserver;
+import android.content.pm.PackageInfo;
+import android.util.EventLog;
+import android.util.Slog;
+
+import com.android.server.EventLogTags;
+import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.DataChangedJournal;
+import com.android.server.backup.remote.RemoteResult;
+import com.android.server.backup.utils.BackupManagerMonitorUtils;
+import com.android.server.backup.utils.BackupObserverUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+
+/**
+ * Reports events that happen during a key-value backup task to:
+ *
+ * <ul>
+ *   <li>Logcat (main and event buffers).
+ *   <li>Backup observer (see {@link IBackupObserver}).
+ *   <li>Backup manager monitor (see {@link IBackupManagerMonitor}).
+ * </ul>
+ */
+// TODO: In KeyValueBackupTaskTest, remove direct assertions on logcat, observer or monitor and
+//       verify calls to this object. Add these and more assertions to the test of this class.
+class KeyValueBackupReporter {
+    private static final String TAG = "KeyValueBackupTask";
+    private static final boolean DEBUG = BackupManagerService.DEBUG;
+    private static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || true;
+
+    private final BackupManagerService mBackupManagerService;
+    private final IBackupObserver mObserver;
+    @Nullable private IBackupManagerMonitor mMonitor;
+
+    KeyValueBackupReporter(
+            BackupManagerService backupManagerService,
+            IBackupObserver observer,
+            IBackupManagerMonitor monitor) {
+        mBackupManagerService = backupManagerService;
+        mObserver = observer;
+        mMonitor = monitor;
+    }
+
+    /** Returns the monitor or {@code null} if we lost connection to it. */
+    @Nullable
+    IBackupManagerMonitor getMonitor() {
+        return mMonitor;
+    }
+
+    void onSkipBackup() {
+        if (DEBUG) {
+            Slog.d(TAG, "Skipping backup since one is already in progress");
+        }
+    }
+
+    void onEmptyQueueAtStart() {
+        Slog.w(TAG, "Backup begun with an empty queue, nothing to do");
+    }
+
+    void onQueueReady(List<String> queue) {
+        if (DEBUG) {
+            Slog.v(TAG, "Beginning backup of " + queue.size() + " targets");
+        }
+    }
+
+    void onTransportReady(String transportName) {
+        EventLog.writeEvent(EventLogTags.BACKUP_START, transportName);
+    }
+
+    void onInitializeTransport(String transportName) {
+        Slog.i(TAG, "Initializing transport and resetting backup state");
+    }
+
+    void onTransportInitialized(int status) {
+        if (status == BackupTransport.TRANSPORT_OK) {
+            EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
+        } else {
+            EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
+            Slog.e(TAG, "Transport error in initializeDevice()");
+        }
+    }
+
+    void onInitializeTransportError(Exception e) {
+        Slog.e(TAG, "Error during initialization", e);
+    }
+
+    void onSkipPm() {
+        Slog.d(TAG, "Skipping backup of PM metadata");
+    }
+
+    void onExtractPmAgentDataError(Exception e) {
+        Slog.e(TAG, "Error during PM metadata backup", e);
+    }
+
+    void onEmptyQueue() {
+        if (MORE_DEBUG) {
+            Slog.i(TAG, "Queue now empty");
+        }
+    }
+
+    void onStartPackageBackup(String packageName) {
+        Slog.d(TAG, "Starting key-value backup of " + packageName);
+    }
+
+    void onPackageNotEligibleForBackup(String packageName) {
+        Slog.i(TAG, "Package " + packageName + " no longer supports backup, skipping");
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+    }
+
+    void onPackageEligibleForFullBackup(String packageName) {
+        Slog.i(
+                TAG,
+                "Package " + packageName + " performs full-backup rather than key-value, skipping");
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+    }
+
+    void onPackageStopped(String packageName) {
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+    }
+
+    void onBindAgentError(SecurityException e) {
+        Slog.d(TAG, "Error in bind/backup", e);
+    }
+
+    void onAgentUnknown(String packageName) {
+        Slog.d(TAG, "Package does not exist, skipping");
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_PACKAGE_NOT_FOUND);
+    }
+
+    void onAgentError(String packageName) {
+        if (MORE_DEBUG) {
+            Slog.i(TAG, "Agent failure for " + packageName + ", re-staging");
+        }
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_AGENT_FAILURE);
+    }
+
+    void onExtractAgentData(String packageName) {
+        if (DEBUG) {
+            Slog.d(TAG, "Invoking agent on " + packageName);
+        }
+    }
+
+    void onAgentFilesReady(File backupDataFile) {
+        if (MORE_DEBUG) {
+            Slog.d(TAG, "Data file: " + backupDataFile);
+        }
+    }
+
+    void onRestoreconFailed(File backupDataFile) {
+        Slog.e(TAG, "SELinux restorecon failed on " + backupDataFile);
+    }
+
+    void onCallAgentDoBackupError(String packageName, boolean callingAgent, Exception e) {
+        if (callingAgent) {
+            Slog.e(TAG, "Error invoking agent on " + packageName + ": " + e);
+        } else {
+            Slog.e(TAG, "Error before invoking agent on " + packageName + ": " + e);
+        }
+        EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName, e.toString());
+    }
+
+    void onFailAgentError(String packageName) {
+        Slog.w(TAG, "Error conveying failure to " + packageName);
+    }
+
+    void onAgentIllegalKey(PackageInfo packageInfo, String key) {
+        String packageName = packageInfo.packageName;
+        EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName, "bad key");
+        mMonitor =
+                BackupManagerMonitorUtils.monitorEvent(
+                        mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY,
+                        packageInfo,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                        BackupManagerMonitorUtils.putMonitoringExtra(
+                                null, BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY, key));
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_AGENT_FAILURE);
+        if (MORE_DEBUG) {
+            Slog.i(
+                    TAG,
+                    "Agent failure for " + packageName + " with illegal key " + key + ", dropped");
+        }
+    }
+
+    void onReadAgentDataError(String packageName, IOException e) {
+        Slog.w(TAG, "Unable read backup data for " + packageName + ": " + e);
+    }
+
+    void onWriteWidgetDataError(String packageName, IOException e) {
+        Slog.w(TAG, "Unable to save widget data for " + packageName + ": " + e);
+    }
+
+    void onDigestError(NoSuchAlgorithmException e) {
+        Slog.e(TAG, "Unable to use SHA-1!");
+    }
+
+    void onWriteWidgetData(boolean priorStateExists, @Nullable byte[] widgetState) {
+        if (MORE_DEBUG) {
+            Slog.i(
+                    TAG,
+                    "Checking widget update: state="
+                            + (widgetState != null)
+                            + " prior="
+                            + priorStateExists);
+        }
+    }
+
+    void onTruncateDataError() {
+        Slog.w(TAG, "Unable to roll back");
+    }
+
+    void onSendDataToTransport(String packageName) {
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "Sending non-empty data to transport for " + packageName);
+        }
+    }
+
+    void onNonIncrementalAndNonIncrementalRequired() {
+        Slog.e(TAG, "Transport requested non-incremental but already the case");
+    }
+
+    void onEmptyData(PackageInfo packageInfo) {
+        if (MORE_DEBUG) {
+            Slog.i(TAG, "No backup data written, not calling transport");
+        }
+        mMonitor =
+                BackupManagerMonitorUtils.monitorEvent(
+                        mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
+                        packageInfo,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                        null);
+    }
+
+    void onPackageBackupComplete(String packageName, long size) {
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.SUCCESS);
+        EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, packageName, size);
+        mBackupManagerService.logBackupComplete(packageName);
+    }
+
+    void onPackageBackupRejected(String packageName) {
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
+        EventLogTags.writeBackupAgentFailure(packageName, "Transport rejected");
+    }
+
+    void onPackageBackupQuotaExceeded(String packageName) {
+        if (MORE_DEBUG) {
+            Slog.d(TAG, "Package " + packageName + " hit quota limit on key-value backup");
+        }
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
+        EventLog.writeEvent(EventLogTags.BACKUP_QUOTA_EXCEEDED, packageName);
+    }
+
+    void onAgentDoQuotaExceededError(Exception e) {
+        Slog.e(TAG, "Unable to notify about quota exceeded: " + e);
+    }
+
+    void onPackageBackupNonIncrementalRequired(PackageInfo packageInfo) {
+        Slog.i(TAG, "Transport lost data, retrying package");
+        BackupManagerMonitorUtils.monitorEvent(
+                mMonitor,
+                BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED,
+                packageInfo,
+                BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
+                /* extras */ null);
+    }
+
+    void onPackageBackupTransportFailure(String packageName) {
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_TRANSPORT_ABORTED);
+        EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, packageName);
+    }
+
+    void onPackageBackupError(String packageName, Exception e) {
+        Slog.e(TAG, "Transport error backing up " + packageName, e);
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_TRANSPORT_ABORTED);
+        EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, packageName);
+    }
+
+    void onCloseFileDescriptorError(String logName) {
+        Slog.w(TAG, "Error closing " + logName + " file-descriptor");
+    }
+
+    void onCancel() {
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "Cancel received");
+        }
+    }
+
+    void onAgentTimedOut(@Nullable PackageInfo packageInfo) {
+        String packageName = getPackageName(packageInfo);
+        Slog.i(TAG, "Agent " + packageName + " timed out");
+        EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
+        // Time-out used to be implemented as cancel w/ cancelAll = false.
+        // TODO: Change monitoring event to reflect time-out as an event itself.
+        mMonitor =
+                BackupManagerMonitorUtils.monitorEvent(
+                        mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
+                        packageInfo,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
+                        BackupManagerMonitorUtils.putMonitoringExtra(
+                                null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, false));
+    }
+
+    void onAgentCancelled(@Nullable PackageInfo packageInfo) {
+        String packageName = getPackageName(packageInfo);
+        Slog.i(TAG, "Cancel backing up " + packageName);
+        EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
+        mMonitor =
+                BackupManagerMonitorUtils.monitorEvent(
+                        mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
+                        packageInfo,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
+                        BackupManagerMonitorUtils.putMonitoringExtra(
+                                null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, true));
+    }
+
+    private String getPackageName(@Nullable PackageInfo packageInfo) {
+        return (packageInfo != null) ? packageInfo.packageName : "no_package_yet";
+    }
+
+    void onRevertBackup() {
+        if (MORE_DEBUG) {
+            Slog.i(TAG, "Reverting backup queue, re-staging everything");
+        }
+    }
+
+    void onTransportRequestBackupTimeError(Exception e) {
+        Slog.w(TAG, "Unable to contact transport for recommended backoff: " + e);
+    }
+
+    void onRemoteCallReturned(RemoteResult result) {
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "Agent call returned " + result);
+        }
+    }
+
+    void onJournalDeleteFailed(DataChangedJournal journal) {
+        Slog.e(TAG, "Unable to remove backup journal file " + journal);
+    }
+
+    void onSetCurrentTokenError(Exception e) {
+        Slog.e(TAG, "Transport threw reporting restore set: " + e);
+    }
+
+    void onTransportNotInitialized() {
+        if (MORE_DEBUG) {
+            Slog.d(TAG, "Transport requires initialization, rerunning");
+        }
+    }
+
+    void onPendingInitializeTransportError(Exception e) {
+        Slog.w(TAG, "Failed to query transport name for pending init: " + e);
+    }
+
+    void onBackupFinished(int status) {
+        BackupObserverUtils.sendBackupFinished(mObserver, status);
+    }
+
+    void onStartFullBackup(List<String> pendingFullBackups) {
+        Slog.d(TAG, "Starting full backups for: " + pendingFullBackups);
+    }
+
+    void onKeyValueBackupFinished() {
+        Slog.i(TAG, "K/V backup pass finished");
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
new file mode 100644
index 0000000..91af6f1
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -0,0 +1,1094 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.keyvalue;
+
+import static android.os.ParcelFileDescriptor.MODE_CREATE;
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
+import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
+import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
+
+import static com.android.server.backup.BackupManagerService.KEY_WIDGET_STATE;
+import static com.android.server.backup.BackupManagerService.OP_PENDING;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP;
+import static com.android.server.backup.BackupManagerService.PACKAGE_MANAGER_SENTINEL;
+
+import android.annotation.Nullable;
+import android.app.ApplicationThreadConstants;
+import android.app.IBackupAgent;
+import android.app.backup.BackupAgent;
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupManager;
+import android.app.backup.BackupTransport;
+import android.app.backup.IBackupCallback;
+import android.app.backup.IBackupManager;
+import android.app.backup.IBackupManagerMonitor;
+import android.app.backup.IBackupObserver;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.ConditionVariable;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SELinux;
+import android.os.UserHandle;
+import android.os.WorkSource;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.util.Pair;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.backup.IBackupTransport;
+import com.android.internal.util.Preconditions;
+import com.android.server.AppWidgetBackupBridge;
+import com.android.server.backup.BackupAgentTimeoutParameters;
+import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.BackupRestoreTask;
+import com.android.server.backup.DataChangedJournal;
+import com.android.server.backup.KeyValueBackupJob;
+import com.android.server.backup.TransportManager;
+import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
+import com.android.server.backup.internal.OnTaskFinishedListener;
+import com.android.server.backup.internal.Operation;
+import com.android.server.backup.remote.RemoteCall;
+import com.android.server.backup.remote.RemoteCallable;
+import com.android.server.backup.remote.RemoteResult;
+import com.android.server.backup.transport.TransportClient;
+import com.android.server.backup.utils.AppBackupUtils;
+
+import java.io.Closeable;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Represents the task of performing a sequence of key-value backups for a given list of packages.
+ * Method {@link #run()} executes the backups to the transport specified via the {@code
+ * transportClient} parameter in the constructor.
+ *
+ * <p>A few definitions:
+ *
+ * <ul>
+ *   <li>State directory: {@link BackupManagerService#getBaseStateDir()}/&lt;transport&gt;
+ *   <li>State file: {@link
+ *       BackupManagerService#getBaseStateDir()}/&lt;transport&gt;/&lt;package&gt;<br>
+ *       Represents the state of the backup data for a specific package in the current dataset.
+ *   <li>Stage directory: {@link BackupManagerService#getDataDir()}
+ *   <li>Stage file: {@link BackupManagerService#getDataDir()}/&lt;package&gt;.data<br>
+ *       Contains staged data that the agents wrote via {@link BackupDataOutput}, to be transmitted
+ *       to the transport.
+ * </ul>
+ *
+ * If there is no PackageManager (PM) pseudo-package state file in the state directory, the
+ * specified transport will be initialized with {@link IBackupTransport#initializeDevice()}.
+ *
+ * <p>The PM pseudo-package is the first package to be backed-up and sent to the transport in case
+ * of incremental choice. If non-incremental, PM will only be backed-up if specified in the queue,
+ * and if it's the case it will be re-positioned at the head of the queue.
+ *
+ * <p>Before starting, this task will register itself in {@link BackupManagerService} current
+ * operations.
+ *
+ * <p>In summary, this task will for each package:
+ *
+ * <ul>
+ *   <li>Bind to its {@link IBackupAgent}.
+ *   <li>Request transport quota and flags.
+ *   <li>Call {@link IBackupAgent#doBackup(ParcelFileDescriptor, ParcelFileDescriptor,
+ *       ParcelFileDescriptor, long, int, IBackupManager, int)} via {@link RemoteCall} passing the
+ *       old state file descriptor (read), the backup data file descriptor (write), the new state
+ *       file descriptor (write), the quota and the transport flags. This will call {@link
+ *       BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)} with
+ *       the old state file to be read, a {@link BackupDataOutput} object to write the backup data
+ *       and the new state file to write. By writing to {@link BackupDataOutput}, the agent will
+ *       write data to the stage file. The task will block waiting for either:
+ *       <ul>
+ *         <li>Agent response.
+ *         <li>Agent time-out (specified via {@link
+ *             BackupManagerService#getAgentTimeoutParameters()}.
+ *         <li>External cancellation or thread interrupt.
+ *       </ul>
+ *   <li>Unbind the agent.
+ *   <li>Assuming agent response, send the staged data that the agent wrote to disk to the transport
+ *       via {@link IBackupTransport#performBackup(PackageInfo, ParcelFileDescriptor, int)}.
+ *   <li>Call {@link IBackupTransport#finishBackup()} if previous call was successful.
+ *   <li>Save the new state in the state file. During the agent call it was being written to
+ *       &lt;state file&gt;.new, here we rename it and replace the old one.
+ *   <li>Delete the stage file.
+ * </ul>
+ *
+ * In the end, this task will:
+ *
+ * <ul>
+ *   <li>Mark data-changed for the remaining packages in the queue (skipped packages).
+ *   <li>Delete the {@link DataChangedJournal} provided. Note that this should not be the current
+ *       journal.
+ *   <li>Set {@link BackupManagerService} current token as {@link
+ *       IBackupTransport#getCurrentRestoreSet()}, if applicable.
+ *   <li>Add the transport to the list of transports pending initialization ({@link
+ *       BackupManagerService#getPendingInits()}) and kick-off initialization if the transport ever
+ *       returned {@link BackupTransport#TRANSPORT_NOT_INITIALIZED}.
+ *   <li>Unregister the task in current operations.
+ *   <li>Release the wakelock.
+ *   <li>Kick-off {@link PerformFullTransportBackupTask} if a list of full-backup packages was
+ *       provided.
+ * </ul>
+ *
+ * The caller can specify whether this should be an incremental or non-incremental backup. In the
+ * case of non-incremental the agents will be passed an empty old state file, which signals that a
+ * complete backup should be performed.
+ *
+ * <p>This task is designed to run on a dedicated thread, with the exception of the {@link
+ * #handleCancel(boolean)} method, which can be called from any thread.
+ */
+// TODO: Stop poking into BMS state and doing things for it (e.g. synchronizing on public locks)
+// TODO: Consider having the caller responsible for some clean-up (like resetting state)
+// TODO: Distinguish between cancel and time-out where possible for logging/monitoring/observing
+public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
+    private static final String TAG = "KeyValueBackupTask";
+    private static final boolean DEBUG = BackupManagerService.DEBUG;
+    private static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || false;
+    private static final int THREAD_PRIORITY = Process.THREAD_PRIORITY_BACKGROUND;
+    private static final AtomicInteger THREAD_COUNT = new AtomicInteger();
+    private static final String BLANK_STATE_FILE_NAME = "blank_state";
+    private static final String PM_PACKAGE = BackupManagerService.PACKAGE_MANAGER_SENTINEL;
+    @VisibleForTesting
+    public static final String STAGING_FILE_SUFFIX = ".data";
+    @VisibleForTesting
+    public static final String NEW_STATE_FILE_SUFFIX = ".new";
+
+    /**
+     * Creates a new {@link KeyValueBackupTask} for key-value backup operation, spins up a new
+     * dedicated thread and kicks off the operation in it.
+     *
+     * @param backupManagerService The {@link BackupManagerService} system service.
+     * @param transportClient The {@link TransportClient} that contains the transport used for the
+     *     operation.
+     * @param transportDirName The value of {@link IBackupTransport#transportDirName()} for the
+     *     transport whose {@link TransportClient} was provided above.
+     * @param queue The list of package names that will be backed-up.
+     * @param dataChangedJournal The old data-changed journal file that will be deleted when the
+     *     operation finishes (successfully or not) or {@code null}.
+     * @param observer A {@link IBackupObserver}.
+     * @param monitor A {@link IBackupManagerMonitor}.
+     * @param listener A {@link OnTaskFinishedListener} or {@code null}.
+     * @param pendingFullBackups The list of packages that will be passed for a new {@link
+     *     PerformFullTransportBackupTask} operation, which will be started when this finishes.
+     * @param userInitiated Whether this was user-initiated or not.
+     * @param nonIncremental If {@code true}, this will be a complete backup for each package,
+     *     otherwise it will be just an incremental one over the current dataset.
+     * @return The {@link KeyValueBackupTask} that was started.
+     */
+    public static KeyValueBackupTask start(
+            BackupManagerService backupManagerService,
+            TransportClient transportClient,
+            String transportDirName,
+            List<String> queue,
+            @Nullable DataChangedJournal dataChangedJournal,
+            IBackupObserver observer,
+            @Nullable IBackupManagerMonitor monitor,
+            OnTaskFinishedListener listener,
+            List<String> pendingFullBackups,
+            boolean userInitiated,
+            boolean nonIncremental) {
+        KeyValueBackupTask task =
+                new KeyValueBackupTask(
+                        backupManagerService,
+                        transportClient,
+                        transportDirName,
+                        queue,
+                        dataChangedJournal,
+                        observer,
+                        monitor,
+                        listener,
+                        pendingFullBackups,
+                        userInitiated,
+                        nonIncremental);
+        Thread thread = new Thread(task, "key-value-backup-" + THREAD_COUNT.incrementAndGet());
+        if (DEBUG) {
+            Slog.d(TAG, "Spinning thread " + thread.getName());
+        }
+        thread.start();
+        return task;
+    }
+
+    private final BackupManagerService mBackupManagerService;
+    private final PackageManager mPackageManager;
+    private final TransportManager mTransportManager;
+    private final TransportClient mTransportClient;
+    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
+    private final IBackupObserver mObserver;
+    private final KeyValueBackupReporter mReporter;
+    private final OnTaskFinishedListener mTaskFinishedListener;
+    private final boolean mUserInitiated;
+    private final boolean mNonIncremental;
+    private final int mCurrentOpToken;
+    private final File mStateDir;
+    private final List<String> mOriginalQueue;
+    private final List<String> mQueue;
+    private final List<String> mPendingFullBackups;
+    @Nullable private final DataChangedJournal mJournal;
+    @Nullable private PerformFullTransportBackupTask mFullBackupTask;
+
+    private IBackupAgent mAgentBinder;
+    private PackageInfo mCurrentPackage;
+    private File mSavedStateFile;
+    private File mBackupDataFile;
+    private File mNewStateFile;
+    private ParcelFileDescriptor mSavedState;
+    private ParcelFileDescriptor mBackupData;
+    private ParcelFileDescriptor mNewState;
+    private int mStatus;
+
+    /**
+     * This {@link ConditionVariable} is used to signal that the cancel operation has been
+     * received by the task and that no more transport calls will be made. Anyone can call {@link
+     * ConditionVariable#block()} to wait for these conditions to hold true, but there should only
+     * be one place where {@link ConditionVariable#open()} is called. Also there should be no calls
+     * to {@link ConditionVariable#close()}, which means there is only one cancel per backup -
+     * subsequent calls to block will return immediately.
+     */
+    private final ConditionVariable mCancelAcknowledged = new ConditionVariable(false);
+
+    /**
+     * Set it to {@code true} and block on {@code mCancelAcknowledged} to wait for the cancellation.
+     * DO NOT set it to {@code false}.
+     */
+    private volatile boolean mCancelled = false;
+
+    /**
+     * If non-{@code null} there is a pending agent call being made. This call can be cancelled (and
+     * control returned to this task) with {@link RemoteCall#cancel()}.
+     */
+    @Nullable private volatile RemoteCall mPendingCall;
+
+    @VisibleForTesting
+    public KeyValueBackupTask(
+            BackupManagerService backupManagerService,
+            TransportClient transportClient,
+            String transportDirName,
+            List<String> queue,
+            @Nullable DataChangedJournal journal,
+            IBackupObserver observer,
+            @Nullable IBackupManagerMonitor monitor,
+            OnTaskFinishedListener taskFinishedListener,
+            List<String> pendingFullBackups,
+            boolean userInitiated,
+            boolean nonIncremental) {
+        mBackupManagerService = backupManagerService;
+        mTransportManager = backupManagerService.getTransportManager();
+        mPackageManager = backupManagerService.getPackageManager();
+        mTransportClient = transportClient;
+        mOriginalQueue = queue;
+        // We need to retain the original queue contents in case of transport failure
+        mQueue = new ArrayList<>(queue);
+        mJournal = journal;
+        mObserver = observer;
+        mReporter = new KeyValueBackupReporter(backupManagerService, observer, monitor);
+        mTaskFinishedListener = taskFinishedListener;
+        mPendingFullBackups = pendingFullBackups;
+        mUserInitiated = userInitiated;
+        mNonIncremental = nonIncremental;
+        mAgentTimeoutParameters =
+                Preconditions.checkNotNull(
+                        backupManagerService.getAgentTimeoutParameters(),
+                        "Timeout parameters cannot be null");
+        mStateDir = new File(backupManagerService.getBaseStateDir(), transportDirName);
+        mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
+    }
+
+    private void registerTask() {
+        mBackupManagerService.putOperation(
+                mCurrentOpToken, new Operation(OP_PENDING, this, OP_TYPE_BACKUP));
+    }
+
+    private void unregisterTask() {
+        mBackupManagerService.removeOperation(mCurrentOpToken);
+    }
+
+    @Override
+    public void run() {
+        Process.setThreadPriority(THREAD_PRIORITY);
+
+        BackupState state = startBackup();
+        while (state == BackupState.RUNNING_QUEUE || state == BackupState.BACKUP_PM) {
+            if (mCancelled) {
+                state = BackupState.CANCELLED;
+            }
+            switch (state) {
+                case BACKUP_PM:
+                    state = backupPm();
+                    break;
+                case RUNNING_QUEUE:
+                    Pair<BackupState, RemoteResult> stateAndResult = extractNextAgentData();
+                    state = stateAndResult.first;
+                    if (state == null) {
+                        state = handleAgentResult(stateAndResult.second);
+                    }
+                    break;
+            }
+        }
+        finishBackup();
+    }
+
+    private BackupState handleAgentResult(RemoteResult result) {
+        if (result == RemoteResult.FAILED_THREAD_INTERRUPTED) {
+            // Not an explicit cancel, we need to flag it.
+            mCancelled = true;
+            handleAgentCancelled();
+            return BackupState.CANCELLED;
+        }
+        if (result == RemoteResult.FAILED_CANCELLED) {
+            handleAgentCancelled();
+            return BackupState.CANCELLED;
+        }
+        if (result == RemoteResult.FAILED_TIMED_OUT) {
+            handleAgentTimeout();
+            return BackupState.RUNNING_QUEUE;
+        }
+        Preconditions.checkState(result.succeeded());
+        return sendDataToTransport(result.get());
+    }
+
+    @Override
+    public void execute() {}
+
+    @Override
+    public void operationComplete(long unusedResult) {}
+
+    private BackupState startBackup() {
+        synchronized (mBackupManagerService.getCurrentOpLock()) {
+            if (mBackupManagerService.isBackupOperationInProgress()) {
+                mReporter.onSkipBackup();
+                return BackupState.FINAL;
+            }
+        }
+
+        String[] fullBackups = mPendingFullBackups.toArray(new String[mPendingFullBackups.size()]);
+        mFullBackupTask =
+                new PerformFullTransportBackupTask(
+                        mBackupManagerService,
+                        mTransportClient,
+                        /* fullBackupRestoreObserver */ null,
+                        fullBackups,
+                        /* updateSchedule */ false,
+                        /* runningJob */ null,
+                        new CountDownLatch(1),
+                        mObserver,
+                        mReporter.getMonitor(),
+                        mTaskFinishedListener,
+                        mUserInitiated);
+        registerTask();
+
+        mAgentBinder = null;
+        mStatus = BackupTransport.TRANSPORT_OK;
+
+        // Sanity check: if the queue is empty we have no work to do.
+        if (mOriginalQueue.isEmpty() && mPendingFullBackups.isEmpty()) {
+            mReporter.onEmptyQueueAtStart();
+            return BackupState.FINAL;
+        }
+
+        // We only backup PM if it was explicitly in the queue or if it's incremental.
+        boolean backupPm = mQueue.remove(PM_PACKAGE) || !mNonIncremental;
+
+        mReporter.onQueueReady(mQueue);
+        File pmState = new File(mStateDir, PM_PACKAGE);
+        try {
+            IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.startBackup()");
+            String transportName = transport.name();
+            mReporter.onTransportReady(transportName);
+
+            // If we haven't stored PM metadata yet, we must initialize the transport.
+            if (pmState.length() <= 0) {
+                mReporter.onInitializeTransport(transportName);
+                mBackupManagerService.resetBackupState(mStateDir);
+                mStatus = transport.initializeDevice();
+                mReporter.onTransportInitialized(mStatus);
+            }
+        } catch (Exception e) {
+            mReporter.onInitializeTransportError(e);
+            mStatus = BackupTransport.TRANSPORT_ERROR;
+        }
+
+        if (mStatus != BackupTransport.TRANSPORT_OK) {
+            mBackupManagerService.resetBackupState(mStateDir);
+            return BackupState.FINAL;
+        }
+
+        if (!backupPm) {
+            mReporter.onSkipPm();
+            return BackupState.RUNNING_QUEUE;
+        }
+
+        return BackupState.BACKUP_PM;
+    }
+
+    private BackupState backupPm() {
+        RemoteResult agentResult = null;
+        try {
+            mCurrentPackage = new PackageInfo();
+            mCurrentPackage.packageName = PM_PACKAGE;
+
+            // Since PM is running in the system process we can set up its agent directly.
+            BackupAgent pmAgent = mBackupManagerService.makeMetadataAgent();
+            Pair<Integer, RemoteResult> statusAndResult =
+                    extractAgentData(
+                            PM_PACKAGE,
+                            IBackupAgent.Stub.asInterface(pmAgent.onBind()));
+            mStatus = statusAndResult.first;
+            agentResult = statusAndResult.second;
+        } catch (Exception e) {
+            mReporter.onExtractPmAgentDataError(e);
+            mStatus = BackupTransport.TRANSPORT_ERROR;
+        }
+
+        if (mStatus != BackupTransport.TRANSPORT_OK) {
+            mBackupManagerService.resetBackupState(mStateDir);
+            return BackupState.FINAL;
+        }
+
+        Preconditions.checkNotNull(agentResult);
+        return handleAgentResult(agentResult);
+    }
+
+    /**
+     * Returns either:
+     *
+     * <ul>
+     *   <li>(next state, {@code null}): In case we failed to call the agent.
+     *   <li>({@code null}, agent result): In case we successfully called the agent.
+     * </ul>
+     */
+    private Pair<BackupState, RemoteResult> extractNextAgentData() {
+        mStatus = BackupTransport.TRANSPORT_OK;
+
+        if (mQueue.isEmpty()) {
+            mReporter.onEmptyQueue();
+            return Pair.create(BackupState.FINAL, null);
+        }
+
+        String packageName = mQueue.remove(0);
+        mReporter.onStartPackageBackup(packageName);
+
+        // Verify that the requested app is eligible for key-value backup.
+        RemoteResult agentResult = null;
+        try {
+            mCurrentPackage = mPackageManager.getPackageInfo(
+                    packageName, PackageManager.GET_SIGNING_CERTIFICATES);
+            ApplicationInfo applicationInfo = mCurrentPackage.applicationInfo;
+            if (!AppBackupUtils.appIsEligibleForBackup(applicationInfo, mPackageManager)) {
+                // The manifest has changed. This won't happen again because the app won't be
+                // requesting further backups.
+                mReporter.onPackageNotEligibleForBackup(packageName);
+                return Pair.create(BackupState.RUNNING_QUEUE, null);
+            }
+
+            if (AppBackupUtils.appGetsFullBackup(mCurrentPackage)) {
+                // Initially enqueued for key-value backup, but only supports full-backup now.
+                mReporter.onPackageEligibleForFullBackup(packageName);
+                return Pair.create(BackupState.RUNNING_QUEUE, null);
+            }
+
+            if (AppBackupUtils.appIsStopped(applicationInfo)) {
+                // Just as it won't receive broadcasts, we won't run it for backup.
+                mReporter.onPackageStopped(packageName);
+                return Pair.create(BackupState.RUNNING_QUEUE, null);
+            }
+
+            try {
+                mBackupManagerService.setWorkSource(new WorkSource(applicationInfo.uid));
+                IBackupAgent agent =
+                        mBackupManagerService.bindToAgentSynchronous(
+                                applicationInfo,
+                                ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
+                if (agent != null) {
+                    mAgentBinder = agent;
+                    Pair<Integer, RemoteResult> statusAndResult =
+                            extractAgentData(packageName, agent);
+                    mStatus = statusAndResult.first;
+                    agentResult = statusAndResult.second;
+                } else {
+                    // Timeout waiting for the agent to bind.
+                    mStatus = BackupTransport.AGENT_ERROR;
+                }
+            } catch (SecurityException e) {
+                mReporter.onBindAgentError(e);
+                mStatus = BackupTransport.AGENT_ERROR;
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            mStatus = BackupTransport.AGENT_UNKNOWN;
+        } finally {
+            mBackupManagerService.setWorkSource(null);
+        }
+
+        if (mStatus != BackupTransport.TRANSPORT_OK) {
+            mAgentBinder = null;
+
+            if (mStatus == BackupTransport.AGENT_ERROR) {
+                mReporter.onAgentError(packageName);
+                mBackupManagerService.dataChangedImpl(packageName);
+                mStatus = BackupTransport.TRANSPORT_OK;
+                return Pair.create(BackupState.RUNNING_QUEUE, null);
+            }
+
+            if (mStatus == BackupTransport.AGENT_UNKNOWN) {
+                mReporter.onAgentUnknown(packageName);
+                mStatus = BackupTransport.TRANSPORT_OK;
+                return Pair.create(BackupState.RUNNING_QUEUE, null);
+            }
+
+            // Transport-level failure, re-enqueue everything.
+            revertBackup();
+            return Pair.create(BackupState.FINAL, null);
+        }
+
+        // Success: caller will figure out the state based on call result
+        return Pair.create(null, agentResult);
+    }
+
+    private void finishBackup() {
+        // Mark packages that we couldn't backup as pending backup.
+        for (String packageName : mQueue) {
+            mBackupManagerService.dataChangedImpl(packageName);
+        }
+
+        // If backup succeeded, we just invalidated this journal. If not, we've already re-enqueued
+        // the packages and also don't need the journal.
+        if (mJournal != null && !mJournal.delete()) {
+            mReporter.onJournalDeleteFailed(mJournal);
+        }
+
+        String callerLogString = "KVBT.finishBackup()";
+
+        // If we succeeded and this is the first time we've done a backup, we can record the current
+        // backup dataset token.
+        long currentToken = mBackupManagerService.getCurrentToken();
+        if ((mStatus == BackupTransport.TRANSPORT_OK) && (currentToken == 0)) {
+            try {
+                IBackupTransport transport = mTransportClient.connectOrThrow(callerLogString);
+                mBackupManagerService.setCurrentToken(transport.getCurrentRestoreSet());
+                mBackupManagerService.writeRestoreTokens();
+            } catch (Exception e) {
+                // This will be recorded the next time we succeed.
+                mReporter.onSetCurrentTokenError(e);
+            }
+        }
+
+        synchronized (mBackupManagerService.getQueueLock()) {
+            mBackupManagerService.setBackupRunning(false);
+            if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
+                mReporter.onTransportNotInitialized();
+                try {
+                    IBackupTransport transport = mTransportClient.connectOrThrow(callerLogString);
+                    mBackupManagerService.getPendingInits().add(transport.name());
+                    clearPmMetadata();
+                    mBackupManagerService.backupNow();
+                } catch (Exception e) {
+                    mReporter.onPendingInitializeTransportError(e);
+                }
+            }
+        }
+
+        unregisterTask();
+        mReporter.onKeyValueBackupFinished();
+
+        if (mCancelled) {
+            // We acknowledge the cancel as soon as we unregister the task, allowing other backups
+            // to be performed.
+            mCancelAcknowledged.open();
+        }
+
+        if (!mCancelled
+                && mStatus == BackupTransport.TRANSPORT_OK
+                && mFullBackupTask != null
+                && !mPendingFullBackups.isEmpty()) {
+            mReporter.onStartFullBackup(mPendingFullBackups);
+            // The key-value backup has finished but not the overall backup. Full-backup task will:
+            // * Call mObserver.backupFinished() (which is called by mReporter below).
+            // * Call mTaskFinishedListener.onFinished().
+            // * Release the wakelock.
+            (new Thread(mFullBackupTask, "full-transport-requested")).start();
+            return;
+        }
+
+        if (mFullBackupTask != null) {
+            mFullBackupTask.unregisterTask();
+        }
+        mTaskFinishedListener.onFinished(callerLogString);
+        mReporter.onBackupFinished(getBackupFinishedStatus(mCancelled, mStatus));
+        mBackupManagerService.getWakelock().release();
+    }
+
+    private int getBackupFinishedStatus(boolean cancelled, int transportStatus) {
+        if (cancelled) {
+            return BackupManager.ERROR_BACKUP_CANCELLED;
+        }
+        switch (transportStatus) {
+            case BackupTransport.TRANSPORT_OK:
+            case BackupTransport.TRANSPORT_QUOTA_EXCEEDED:
+            case BackupTransport.TRANSPORT_PACKAGE_REJECTED:
+                return BackupManager.SUCCESS;
+            case BackupTransport.TRANSPORT_NOT_INITIALIZED:
+            case BackupTransport.TRANSPORT_ERROR:
+            default:
+                return BackupManager.ERROR_TRANSPORT_ABORTED;
+        }
+    }
+
+    /** Removes PM state, triggering initialization in the next key-value task. */
+    private void clearPmMetadata() {
+        File pmState = new File(mStateDir, PM_PACKAGE);
+        if (pmState.exists()) {
+            pmState.delete();
+        }
+    }
+
+    /**
+     * Returns a {@link Pair}. The first of the pair contains the status. In case the status is
+     * {@link BackupTransport#TRANSPORT_OK}, the second of the pair contains the agent result,
+     * otherwise {@code null}.
+     */
+    private Pair<Integer, RemoteResult> extractAgentData(String packageName, IBackupAgent agent) {
+        mReporter.onExtractAgentData(packageName);
+
+        File blankStateFile = new File(mStateDir, BLANK_STATE_FILE_NAME);
+        mSavedStateFile = new File(mStateDir, packageName);
+        File savedStateFileForAgent = (mNonIncremental) ? blankStateFile : mSavedStateFile;
+        mBackupDataFile =
+                new File(mBackupManagerService.getDataDir(), packageName + STAGING_FILE_SUFFIX);
+        mNewStateFile = new File(mStateDir, packageName + NEW_STATE_FILE_SUFFIX);
+        mReporter.onAgentFilesReady(mBackupDataFile);
+
+        mSavedState = null;
+        mBackupData = null;
+        mNewState = null;
+
+        boolean callingAgent = false;
+        final RemoteResult agentResult;
+        try {
+            // MODE_CREATE to make an empty file if necessary
+            mSavedState = ParcelFileDescriptor.open(
+                    savedStateFileForAgent, MODE_READ_ONLY | MODE_CREATE);
+            mBackupData = ParcelFileDescriptor.open(
+                    mBackupDataFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
+            mNewState = ParcelFileDescriptor.open(
+                    mNewStateFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
+
+            if (!SELinux.restorecon(mBackupDataFile)) {
+                mReporter.onRestoreconFailed(mBackupDataFile);
+            }
+
+            IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.extractAgentData()");
+            long quota = transport.getBackupQuota(packageName, /* isFullBackup */ false);
+            int transportFlags = transport.getTransportFlags();
+            long kvBackupAgentTimeoutMillis =
+                    mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis();
+
+            callingAgent = true;
+            agentResult =
+                    remoteCall(
+                            callback ->
+                                    agent.doBackup(
+                                            mSavedState,
+                                            mBackupData,
+                                            mNewState,
+                                            quota,
+                                            callback,
+                                            transportFlags),
+                            kvBackupAgentTimeoutMillis);
+        } catch (Exception e) {
+            mReporter.onCallAgentDoBackupError(packageName, callingAgent, e);
+            errorCleanup();
+            // TODO: Remove the check on callingAgent when RemoteCall supports local agent calls.
+            int status =
+                    callingAgent ? BackupTransport.AGENT_ERROR : BackupTransport.TRANSPORT_ERROR;
+            return Pair.create(status, null);
+        }
+        blankStateFile.delete();
+
+        return Pair.create(BackupTransport.TRANSPORT_OK, agentResult);
+    }
+
+    private void failAgent(IBackupAgent agent, String message) {
+        try {
+            agent.fail(message);
+        } catch (Exception e) {
+            mReporter.onFailAgentError(mCurrentPackage.packageName);
+        }
+    }
+
+    // SHA-1 a byte array and return the result in hex
+    private String SHA1Checksum(byte[] input) {
+        final byte[] checksum;
+        try {
+            MessageDigest md = MessageDigest.getInstance("SHA-1");
+            checksum = md.digest(input);
+        } catch (NoSuchAlgorithmException e) {
+            mReporter.onDigestError(e);
+            return "00";
+        }
+
+        StringBuilder string = new StringBuilder(checksum.length * 2);
+        for (byte item : checksum) {
+            string.append(Integer.toHexString(item));
+        }
+        return string.toString();
+    }
+
+    private void writeWidgetPayloadIfAppropriate(FileDescriptor fd, String pkgName)
+            throws IOException {
+        // TODO: http://b/22388012
+        byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName, UserHandle.USER_SYSTEM);
+        File widgetFile = new File(mStateDir, pkgName + "_widget");
+        boolean priorStateExists = widgetFile.exists();
+        if (!priorStateExists && widgetState == null) {
+            return;
+        }
+        mReporter.onWriteWidgetData(priorStateExists, widgetState);
+
+        // if the new state is not null, we might need to compare checksums to
+        // determine whether to update the widget blob in the archive.  If the
+        // widget state *is* null, we know a priori at this point that we simply
+        // need to commit a deletion for it.
+        String newChecksum = null;
+        if (widgetState != null) {
+            newChecksum = SHA1Checksum(widgetState);
+            if (priorStateExists) {
+                final String priorChecksum;
+                try (
+                        FileInputStream fin = new FileInputStream(widgetFile);
+                        DataInputStream in = new DataInputStream(fin)
+                ) {
+                    priorChecksum = in.readUTF();
+                }
+                if (Objects.equals(newChecksum, priorChecksum)) {
+                    // Same checksum => no state change => don't rewrite the widget data
+                    return;
+                }
+            }
+        } // else widget state *became* empty, so we need to commit a deletion
+
+        BackupDataOutput out = new BackupDataOutput(fd);
+        if (widgetState != null) {
+            try (
+                    FileOutputStream fout = new FileOutputStream(widgetFile);
+                    DataOutputStream stateOut = new DataOutputStream(fout)
+            ) {
+                stateOut.writeUTF(newChecksum);
+            }
+
+            out.writeEntityHeader(KEY_WIDGET_STATE, widgetState.length);
+            out.writeEntityData(widgetState, widgetState.length);
+        } else {
+            // Widget state for this app has been removed; commit a deletion
+            out.writeEntityHeader(KEY_WIDGET_STATE, -1);
+            widgetFile.delete();
+        }
+    }
+
+    private BackupState sendDataToTransport(long agentResult) {
+        Preconditions.checkState(mBackupData != null);
+
+        String packageName = mCurrentPackage.packageName;
+        ApplicationInfo applicationInfo = mCurrentPackage.applicationInfo;
+        long filePos = mBackupDataFile.length();
+        FileDescriptor fd = mBackupData.getFileDescriptor();
+        boolean writingWidgetData = false;
+        try {
+            // If it's a 3rd party app, crash them if they wrote any protected keys.
+            if (applicationInfo != null &&
+                    (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                ParcelFileDescriptor readFd =
+                        ParcelFileDescriptor.open(mBackupDataFile, MODE_READ_ONLY);
+                BackupDataInput in = new BackupDataInput(readFd.getFileDescriptor());
+                try {
+                    while (in.readNextHeader()) {
+                        String key = in.getKey();
+                        if (key != null && key.charAt(0) >= 0xff00) {
+                            mReporter.onAgentIllegalKey(mCurrentPackage, key);
+                            failAgent(mAgentBinder, "Illegal backup key: " + key);
+                            errorCleanup();
+                            return BackupState.RUNNING_QUEUE;
+                        }
+                        in.skipEntityData();
+                    }
+                } finally {
+                    readFd.close();
+                }
+            }
+
+            writingWidgetData = true;
+            writeWidgetPayloadIfAppropriate(fd, packageName);
+        } catch (IOException e) {
+            if (writingWidgetData) {
+                mReporter.onWriteWidgetDataError(packageName, e);
+            } else {
+                mReporter.onReadAgentDataError(packageName, e);
+            }
+            try {
+                Os.ftruncate(fd, filePos);
+            } catch (ErrnoException ee) {
+                mReporter.onTruncateDataError();
+            }
+        }
+
+        clearAgentState();
+
+        ParcelFileDescriptor backupData = null;
+        mStatus = BackupTransport.TRANSPORT_OK;
+        long size = 0;
+        try {
+            IBackupTransport transport =
+                    mTransportClient.connectOrThrow("KVBT.sendDataToTransport()");
+            size = mBackupDataFile.length();
+            if (size > 0) {
+                boolean isNonIncremental = mSavedStateFile.length() == 0;
+
+                if (mStatus == BackupTransport.TRANSPORT_OK) {
+                    mReporter.onSendDataToTransport(packageName);
+                    backupData = ParcelFileDescriptor.open(mBackupDataFile, MODE_READ_ONLY);
+                    int userInitiatedFlag =
+                            mUserInitiated ? BackupTransport.FLAG_USER_INITIATED : 0;
+                    int incrementalFlag =
+                            isNonIncremental
+                                    ? BackupTransport.FLAG_NON_INCREMENTAL
+                                    : BackupTransport.FLAG_INCREMENTAL;
+                    int flags = userInitiatedFlag | incrementalFlag;
+
+                    mStatus = transport.performBackup(mCurrentPackage, backupData, flags);
+                }
+
+                if (isNonIncremental
+                        && mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
+                    mReporter.onNonIncrementalAndNonIncrementalRequired();
+                    mStatus = BackupTransport.TRANSPORT_ERROR;
+                }
+
+                if (mStatus == BackupTransport.TRANSPORT_OK) {
+                    mStatus = transport.finishBackup();
+                }
+            } else {
+                mReporter.onEmptyData(mCurrentPackage);
+            }
+
+            if (mStatus == BackupTransport.TRANSPORT_OK) {
+                mBackupDataFile.delete();
+                mNewStateFile.renameTo(mSavedStateFile);
+                mReporter.onPackageBackupComplete(packageName, size);
+            } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
+                mBackupDataFile.delete();
+                mNewStateFile.delete();
+                mReporter.onPackageBackupRejected(packageName);
+            } else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
+                // TODO: Should reset files like above?
+                mReporter.onPackageBackupQuotaExceeded(packageName);
+            } else if (mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
+                mReporter.onPackageBackupNonIncrementalRequired(mCurrentPackage);
+                mBackupDataFile.delete();
+                mSavedStateFile.delete();
+                mNewStateFile.delete();
+
+                // Immediately retry the package by adding it back to the front of the queue.
+                // We cannot add @pm@ to the queue because we back it up separately at the start.
+                // Below we request PM backup if that is the case.
+                if (!PM_PACKAGE.equals(packageName)) {
+                    mQueue.add(0, packageName);
+                }
+            } else {
+                mReporter.onPackageBackupTransportFailure(packageName);
+            }
+        } catch (Exception e) {
+            mReporter.onPackageBackupError(packageName, e);
+            mStatus = BackupTransport.TRANSPORT_ERROR;
+        } finally {
+            tryCloseFileDescriptor(backupData, "backup data");
+        }
+
+        final BackupState nextState;
+        if (mStatus == BackupTransport.TRANSPORT_OK
+                || mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
+            nextState = BackupState.RUNNING_QUEUE;
+
+        } else if (mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
+            // We want to immediately retry the current package.
+            if (PM_PACKAGE.equals(packageName)) {
+                nextState = BackupState.BACKUP_PM;
+            } else {
+                // This is an ordinary package so we will have added it back into the queue
+                // above. Thus, we proceed processing the queue.
+                nextState = BackupState.RUNNING_QUEUE;
+            }
+
+        } else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
+            if (mAgentBinder != null) {
+                try {
+                    IBackupTransport transport =
+                            mTransportClient.connectOrThrow("KVBT.sendDataToTransport()");
+                    long quota = transport.getBackupQuota(mCurrentPackage.packageName, false);
+                    mAgentBinder.doQuotaExceeded(size, quota);
+                } catch (Exception e) {
+                    mReporter.onAgentDoQuotaExceededError(e);
+                }
+            }
+            nextState = BackupState.RUNNING_QUEUE;
+        } else {
+            // Any other error here indicates a transport-level failure.  That means
+            // we need to halt everything and reschedule everything for next time.
+            revertBackup();
+            nextState = BackupState.FINAL;
+        }
+
+        return nextState;
+    }
+
+    /**
+     * Cancels this task.
+     *
+     * <p>After this method returns this task won't be registered in {@link BackupManagerService}
+     * anymore, which means there will be no backups running unless there is a racy request
+     * coming from another thread in between. As a consequence there will be no more calls to the
+     * transport originated from this task.
+     *
+     * <p>If this method is executed while an agent is performing a backup, we will stop waiting for
+     * it, disregard its backup data and finalize the task. However, if this method is executed in
+     * between agent calls, the backup data of the last called agent will be sent to
+     * the transport and we will not consider the next agent (nor the rest of the queue), proceeding
+     * to finalize the backup.
+     *
+     * <p>Note: This method is inherently racy since there are no guarantees about how much of the
+     * task will be executed after you made the call.
+     *
+     * @param cancelAll MUST be {@code true}. Will be removed.
+     */
+    @Override
+    public void handleCancel(boolean cancelAll) {
+        // This is called in a thread different from the one that executes method run().
+        Preconditions.checkArgument(cancelAll, "Can't partially cancel a key-value backup task");
+        markCancel();
+        waitCancel();
+    }
+
+    /** Marks this task as cancelled and tries to stop any ongoing agent call. */
+    @VisibleForTesting
+    public void markCancel() {
+        mReporter.onCancel();
+        mCancelled = true;
+        RemoteCall pendingCall = mPendingCall;
+        if (pendingCall != null) {
+            pendingCall.cancel();
+        }
+    }
+
+    /** Waits for this task to be cancelled after call to {@link #markCancel()}. */
+    @VisibleForTesting
+    public void waitCancel() {
+        mCancelAcknowledged.block();
+    }
+
+    private void handleAgentTimeout() {
+        mReporter.onAgentTimedOut(mCurrentPackage);
+        errorCleanup();
+    }
+
+    private void handleAgentCancelled() {
+        mReporter.onAgentCancelled(mCurrentPackage);
+        errorCleanup();
+    }
+
+    private void revertBackup() {
+        mReporter.onRevertBackup();
+        long delay;
+        try {
+            IBackupTransport transport =
+                    mTransportClient.connectOrThrow("KVBT.revertBackup()");
+            delay = transport.requestBackupTime();
+        } catch (Exception e) {
+            mReporter.onTransportRequestBackupTimeError(e);
+            // Use the scheduler's default.
+            delay = 0;
+        }
+        KeyValueBackupJob.schedule(
+                mBackupManagerService.getContext(), delay, mBackupManagerService.getConstants());
+
+        for (String packageName : mOriginalQueue) {
+            mBackupManagerService.dataChangedImpl(packageName);
+        }
+    }
+
+    private void errorCleanup() {
+        mBackupDataFile.delete();
+        mNewStateFile.delete();
+        clearAgentState();
+    }
+
+    private void clearAgentState() {
+        // Cleanup common to both success and failure cases.
+        tryCloseFileDescriptor(mSavedState, "old state");
+        tryCloseFileDescriptor(mBackupData, "backup data");
+        tryCloseFileDescriptor(mNewState, "new state");
+        synchronized (mBackupManagerService.getCurrentOpLock()) {
+            // TODO: Do we still need this?
+            mSavedState = mBackupData = mNewState = null;
+        }
+
+        // For PM metadata (for which applicationInfo is null) there is no agent-bound state.
+        if (mCurrentPackage.applicationInfo != null) {
+            mBackupManagerService.unbindAgent(mCurrentPackage.applicationInfo);
+        }
+    }
+
+    private void tryCloseFileDescriptor(@Nullable Closeable closeable, String logName) {
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (IOException e) {
+                mReporter.onCloseFileDescriptorError(logName);
+            }
+        }
+    }
+
+    private RemoteResult remoteCall(RemoteCallable<IBackupCallback> remoteCallable, long timeoutMs)
+            throws RemoteException {
+        mPendingCall = new RemoteCall(mCancelled, remoteCallable, timeoutMs);
+        RemoteResult result = mPendingCall.call();
+        mReporter.onRemoteCallReturned(result);
+        mPendingCall = null;
+        return result;
+    }
+
+    private enum BackupState {
+        INITIAL,
+        BACKUP_PM,
+        RUNNING_QUEUE,
+        CANCELLED,
+        FINAL
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java b/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java
new file mode 100644
index 0000000..1445cc3
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.remote;
+
+import android.app.backup.IBackupCallback;
+import android.os.RemoteException;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * An implementation of {@link IBackupCallback} that completes the {@link CompletableFuture}
+ * provided in the constructor with a successful {@link RemoteResult}.
+ */
+public class FutureBackupCallback extends IBackupCallback.Stub {
+    private final CompletableFuture<RemoteResult> mFuture;
+
+    FutureBackupCallback(CompletableFuture<RemoteResult> future) {
+        mFuture = future;
+    }
+
+    @Override
+    public void operationComplete(long result) throws RemoteException {
+        mFuture.complete(RemoteResult.successful(result));
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/remote/RemoteCall.java b/services/backup/java/com/android/server/backup/remote/RemoteCall.java
new file mode 100644
index 0000000..ac84811
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/RemoteCall.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.remote;
+
+import android.annotation.WorkerThread;
+import android.app.backup.IBackupCallback;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * A wrapper that encapsulates an outbound call from the system process, converting an asynchronous
+ * operation into a synchronous operation with time-out and cancellation built-in. This was built to
+ * be able to call one-way binder methods that accept a {@link IBackupCallback} as a callback and
+ * handle the result inline.
+ *
+ * <p>Create one {@link RemoteCall} object providing the actual call in the form of a {@link
+ * RemoteCallable} that accepts a {@link IBackupCallback}. Perform the call by calling {@link
+ * #call()}, at which point {@link RemoteCall} will execute the callable providing an implementation
+ * of the callback that communicates the result back to this object. Even if the call returns
+ * straight away (which is the case for one-way methods) the method will only return when either the
+ * callback is called, time-out happens, or someone calls {@link #cancel()}.
+ *
+ * <p>This class was designed to have the method {@link #call()} called only once.
+ */
+// TODO: Kick-off callable in dedicated thread (because of local calls, which are synchronous)
+public class RemoteCall {
+    private final RemoteCallable<IBackupCallback> mCallable;
+    private final CompletableFuture<RemoteResult> mFuture;
+    private final long mTimeoutMs;
+
+    /**
+     * Creates a new {@link RemoteCall} object for a given callable.
+     *
+     * @param callable A function that signals its completion by calling {@link
+     *     IBackupCallback#operationComplete(long)} on the object provided as a parameter.
+     * @param timeoutMs The time in milliseconds after which {@link #call()} will return with {@link
+     *     RemoteResult#FAILED_TIMED_OUT} if the callable hasn't completed and no one canceled. The
+     *     time starts to be counted in {@link #call()}.
+     */
+    public RemoteCall(RemoteCallable<IBackupCallback> callable, long timeoutMs) {
+        this(false, callable, timeoutMs);
+    }
+
+    /**
+     * Same as {@link #RemoteCall(RemoteCallable, long)} but with parameter {@code cancelled}.
+     *
+     * @param cancelled Whether the call has already been canceled. It has the same effect of
+     *     calling {@link #cancel()} before {@link #call()}.
+     * @see #RemoteCall(RemoteCallable, long)
+     */
+    public RemoteCall(boolean cancelled, RemoteCallable<IBackupCallback> callable, long timeoutMs) {
+        mCallable = callable;
+        mTimeoutMs = timeoutMs;
+        mFuture = new CompletableFuture<>();
+        if (cancelled) {
+            cancel();
+        }
+    }
+
+    /**
+     * Kicks-off the callable provided in the constructor and blocks before returning, waiting for
+     * the first of these to happen:
+     *
+     * <ul>
+     *   <li>The callback passed to {@link RemoteCallable} is called with the result. We return a
+     *       successful {@link RemoteResult} with the result.
+     *   <li>Time-out happens. We return {@link RemoteResult#FAILED_TIMED_OUT}.
+     *   <li>Someone calls {@link #cancel()} on this object. We return {@link
+     *       RemoteResult#FAILED_CANCELLED}.
+     * </ul>
+     *
+     * <p>This method can't be called from the main thread and was designed to be called only once.
+     *
+     * @return A {@link RemoteResult} with the result of the operation.
+     * @throws RemoteException If the callable throws it.
+     */
+    @WorkerThread
+    public RemoteResult call() throws RemoteException {
+        // If called on the main-thread we would never get a time-out != 0
+        Preconditions.checkState(
+                !Looper.getMainLooper().isCurrentThread(), "Can't call call() on main thread");
+
+        if (!mFuture.isDone()) {
+            if (mTimeoutMs == 0L) {
+                timeOut();
+            } else {
+                Handler.getMain().postDelayed(this::timeOut, mTimeoutMs);
+                mCallable.call(new FutureBackupCallback(mFuture));
+            }
+        }
+        try {
+            return mFuture.get();
+        } catch (InterruptedException e) {
+            return RemoteResult.FAILED_THREAD_INTERRUPTED;
+        } catch (ExecutionException e) {
+            throw new IllegalStateException("Future unexpectedly completed with an exception");
+        }
+    }
+
+    /**
+     * Attempts to cancel the operation. It will only be successful if executed before the callback
+     * is called and before the time-out.
+     *
+     * <p>This method can be called from any thread, any time, including the same thread that called
+     * {@link #call()} (which is obviously only possible if the former is called before the latter).
+     */
+    public void cancel() {
+        mFuture.complete(RemoteResult.FAILED_CANCELLED);
+    }
+
+    private void timeOut() {
+        mFuture.complete(RemoteResult.FAILED_TIMED_OUT);
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/remote/RemoteCallable.java b/services/backup/java/com/android/server/backup/remote/RemoteCallable.java
new file mode 100644
index 0000000..d2671ff
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/RemoteCallable.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.remote;
+
+import android.os.RemoteException;
+
+/**
+ * Implementations should perform a remote call in {@link #call(Object)}, possibly throwing {@link
+ * RemoteException}.
+ */
+@FunctionalInterface
+public interface RemoteCallable<T> {
+    void call(T input) throws RemoteException;
+}
diff --git a/services/backup/java/com/android/server/backup/remote/RemoteResult.java b/services/backup/java/com/android/server/backup/remote/RemoteResult.java
new file mode 100644
index 0000000..7f4f469
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/RemoteResult.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.remote;
+
+import android.annotation.IntDef;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Represents the result of a {@link RemoteCall}. It can be either {@link #FAILED_TIMED_OUT}, {@link
+ * #FAILED_CANCELLED}, {@link #FAILED_THREAD_INTERRUPTED} or a successful result, in which case
+ * {@link #get()} returns its value.
+ *
+ * <p>Use {@link #succeeded()} to check for successful result, or direct identity comparison to
+ * check for specific failures, like {@code result == RemoteResult.FAILED_CANCELLED}.
+ */
+public class RemoteResult {
+    public static final RemoteResult FAILED_TIMED_OUT = new RemoteResult(Type.FAILED_TIMED_OUT, 0);
+    public static final RemoteResult FAILED_CANCELLED = new RemoteResult(Type.FAILED_CANCELLED, 0);
+    public static final RemoteResult FAILED_THREAD_INTERRUPTED =
+            new RemoteResult(Type.FAILED_THREAD_INTERRUPTED, 0);
+
+    public static RemoteResult successful(long value) {
+        return new RemoteResult(Type.SUCCESS, value);
+    }
+
+    @Type private final int mType;
+    private final long mValue;
+
+    private RemoteResult(@Type int type, long value) {
+        mType = type;
+        mValue = value;
+    }
+
+    public boolean succeeded() {
+        return mType == Type.SUCCESS;
+    }
+
+    /**
+     * Returns the value of this result.
+     *
+     * @throws IllegalStateException in case this is not a successful result.
+     */
+    public long get() {
+        Preconditions.checkState(succeeded(), "Can't obtain value of failed result");
+        return mValue;
+    }
+
+    @Override
+    public String toString() {
+        return "RemoteResult{" + toStringDescription() + "}";
+    }
+
+    private String toStringDescription() {
+        switch (mType) {
+            case Type.SUCCESS:
+                return Long.toString(mValue);
+            case Type.FAILED_TIMED_OUT:
+                return "FAILED_TIMED_OUT";
+            case Type.FAILED_CANCELLED:
+                return "FAILED_CANCELLED";
+            case Type.FAILED_THREAD_INTERRUPTED:
+                return "FAILED_THREAD_INTERRUPTED";
+        }
+        throw new AssertionError("Unknown type");
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof RemoteResult)) {
+            return false;
+        }
+        RemoteResult that = (RemoteResult) o;
+        return mType == that.mType && mValue == that.mValue;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mType, mValue);
+    }
+
+    @IntDef({
+        Type.SUCCESS,
+        Type.FAILED_TIMED_OUT,
+        Type.FAILED_CANCELLED,
+        Type.FAILED_THREAD_INTERRUPTED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface Type {
+        int SUCCESS = 0;
+        int FAILED_TIMED_OUT = 1;
+        int FAILED_CANCELLED = 2;
+        int FAILED_THREAD_INTERRUPTED = 3;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/remote/ServiceBackupCallback.java b/services/backup/java/com/android/server/backup/remote/ServiceBackupCallback.java
new file mode 100644
index 0000000..28d85a6
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/ServiceBackupCallback.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.remote;
+
+import android.app.backup.IBackupCallback;
+import android.app.backup.IBackupManager;
+import android.os.RemoteException;
+
+import com.android.server.backup.BackupManagerService;
+
+/**
+ * An implementation of {@link IBackupCallback} that routes the result to {@link
+ * BackupManagerService} via {@link IBackupManager#opComplete(int, long)} passing the token provided
+ * in the constructor.
+ */
+public class ServiceBackupCallback extends IBackupCallback.Stub {
+    private final IBackupManager mBackupManager;
+    private final int mToken;
+
+    public ServiceBackupCallback(IBackupManager backupManager, int token) {
+        mBackupManager = backupManager;
+        mToken = token;
+    }
+
+    @Override
+    public void operationComplete(long result) throws RemoteException {
+        mBackupManager.opComplete(mToken, result);
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 78b000d..32dbad9 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -30,6 +30,7 @@
 
 
 import android.app.IBackupAgent;
+import android.app.backup.BackupAgent;
 import android.app.backup.IFullBackupRestoreObserver;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.Signature;
@@ -76,7 +77,7 @@
     private final String mCurrentPassword;
     private final String mDecryptPassword;
     private final AtomicBoolean mLatchObject;
-    private final PackageManagerBackupAgent mPackageManagerBackupAgent;
+    private final BackupAgent mPackageManagerBackupAgent;
     private final RestoreDeleteObserver mDeleteObserver = new RestoreDeleteObserver();
 
     private IFullBackupRestoreObserver mObserver;
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 28e9b77..9af952d 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -136,7 +136,14 @@
     /**
      * Checks if the app is in a stopped state.  This is not part of the general "eligible for
      * backup?" check because we *do* still need to restore data to apps in this state (e.g.
-     * newly-installing ones)
+     * newly-installing ones).
+     *
+     * <p>Reasons for such state:
+     * <ul>
+     *     <li>The app has been force-stopped.
+     *     <li>The app has been cleared.
+     *     <li>The app has just been installed.
+     * </ul>
      */
     public static boolean appIsStopped(ApplicationInfo app) {
         return ((app.flags & ApplicationInfo.FLAG_STOPPED) != 0);
diff --git a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
index b23781d..6f08376 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
@@ -21,6 +21,7 @@
 import static com.android.server.backup.BackupManagerService.DEBUG;
 import static com.android.server.backup.BackupManagerService.TAG;
 
+import android.annotation.Nullable;
 import android.app.backup.BackupManagerMonitor;
 import android.app.backup.IBackupManagerMonitor;
 import android.content.pm.PackageInfo;
@@ -44,8 +45,13 @@
      * @param extras - additional event data.
      * @return <code>monitor</code> if call succeeded and <code>null</code> otherwise.
      */
-    public static IBackupManagerMonitor monitorEvent(IBackupManagerMonitor monitor, int id,
-            PackageInfo pkg, int category, Bundle extras) {
+    @Nullable
+    public static IBackupManagerMonitor monitorEvent(
+            @Nullable IBackupManagerMonitor monitor,
+            int id,
+            PackageInfo pkg,
+            int category,
+            Bundle extras) {
         if (monitor != null) {
             try {
                 Bundle bundle = new Bundle();
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index cc5acdf..26ef42f 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2690,7 +2690,7 @@
             errorMsg.append("[mNextNonWakeup=");
             TimeUtils.formatDuration(mNextNonWakeup - nowElapsed, errorMsg);
             errorMsg.append(" set at ");
-            TimeUtils.formatDuration(mNextNonWakeUpSetAt, errorMsg);
+            TimeUtils.formatDuration(mNextNonWakeUpSetAt - nowElapsed, errorMsg);
             errorMsg.append(", mLastWakeup=");
             TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
             errorMsg.append(", timerfd_gettime=" + getNextAlarm(mNativeData, ELAPSED_REALTIME));
@@ -2701,7 +2701,7 @@
             errorMsg.append("[mNextWakeup=");
             TimeUtils.formatDuration(mNextWakeup - nowElapsed, errorMsg);
             errorMsg.append(" set at ");
-            TimeUtils.formatDuration(mNextWakeUpSetAt, errorMsg);
+            TimeUtils.formatDuration(mNextWakeUpSetAt - nowElapsed, errorMsg);
             errorMsg.append(", mLastWakeup=");
             TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
             errorMsg.append(", timerfd_gettime="
@@ -3518,9 +3518,13 @@
 
     private class AlarmThread extends Thread
     {
+        private int mFalseWakeups;
+        private int mWtfThreshold;
         public AlarmThread()
         {
             super("AlarmManager");
+            mFalseWakeups = 0;
+            mWtfThreshold = 10;
         }
 
         public void run()
@@ -3633,6 +3637,17 @@
                                 }
                                 mPendingNonWakeupAlarms.clear();
                             }
+                            if (mLastTimeChangeRealtime != nowELAPSED && triggerList.isEmpty()) {
+                                if (++mFalseWakeups >= mWtfThreshold) {
+                                    Slog.wtf(TAG, "Too many (" + mFalseWakeups
+                                            + ") false wakeups, nowElapsed=" + nowELAPSED);
+                                    if (mWtfThreshold < 100_000) {
+                                        mWtfThreshold *= 10;
+                                    } else {
+                                        mFalseWakeups = 0;
+                                    }
+                                }
+                            }
                             final ArraySet<Pair<String, Integer>> triggerPackages =
                                     new ArraySet<>();
                             for (int i = 0; i < triggerList.size(); i++) {
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 1167e1d..998e441 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -22,6 +22,7 @@
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.AppOpsManagerInternal;
+import android.app.AppOpsManagerInternal.CheckOpsDelegate;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -44,8 +45,10 @@
 import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageManagerInternal;
 import android.provider.Settings;
 import android.util.ArrayMap;
@@ -207,6 +210,8 @@
 
     SparseIntArray mProfileOwners;
 
+    private CheckOpsDelegate mCheckOpsDelegate;
+
     /**
      * All times are in milliseconds. These constants are kept synchronized with the system
      * global Settings. Any access to this class or its fields should be done while
@@ -654,33 +659,35 @@
                     }
                 });
 
-        StorageManagerInternal storageManagerInternal = LocalServices.getService(
-                StorageManagerInternal.class);
-        storageManagerInternal.addExternalStoragePolicy(
-                new StorageManagerInternal.ExternalStorageMountPolicy() {
-                    @Override
-                    public int getMountMode(int uid, String packageName) {
-                        if (Process.isIsolated(uid)) {
-                            return Zygote.MOUNT_EXTERNAL_NONE;
+        if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+            StorageManagerInternal storageManagerInternal = LocalServices.getService(
+                    StorageManagerInternal.class);
+            storageManagerInternal.addExternalStoragePolicy(
+                    new StorageManagerInternal.ExternalStorageMountPolicy() {
+                        @Override
+                        public int getMountMode(int uid, String packageName) {
+                            if (Process.isIsolated(uid)) {
+                                return Zygote.MOUNT_EXTERNAL_NONE;
+                            }
+                            if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
+                                    packageName) != AppOpsManager.MODE_ALLOWED) {
+                                return Zygote.MOUNT_EXTERNAL_NONE;
+                            }
+                            if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
+                                    packageName) != AppOpsManager.MODE_ALLOWED) {
+                                return Zygote.MOUNT_EXTERNAL_READ;
+                            }
+                            return Zygote.MOUNT_EXTERNAL_WRITE;
                         }
-                        if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
-                                packageName) != AppOpsManager.MODE_ALLOWED) {
-                            return Zygote.MOUNT_EXTERNAL_NONE;
-                        }
-                        if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
-                                packageName) != AppOpsManager.MODE_ALLOWED) {
-                            return Zygote.MOUNT_EXTERNAL_READ;
-                        }
-                        return Zygote.MOUNT_EXTERNAL_WRITE;
-                    }
 
-                    @Override
-                    public boolean hasExternalStorage(int uid, String packageName) {
-                        final int mountMode = getMountMode(uid, packageName);
-                        return mountMode == Zygote.MOUNT_EXTERNAL_READ
-                                || mountMode == Zygote.MOUNT_EXTERNAL_WRITE;
-                    }
-                });
+                        @Override
+                        public boolean hasExternalStorage(int uid, String packageName) {
+                            final int mountMode = getMountMode(uid, packageName);
+                            return mountMode == Zygote.MOUNT_EXTERNAL_READ
+                                    || mountMode == Zygote.MOUNT_EXTERNAL_WRITE;
+                        }
+                    });
+        }
     }
 
     public void packageRemoved(int uid, String packageName) {
@@ -1411,15 +1418,39 @@
         }
     }
 
+    public CheckOpsDelegate getAppOpsServiceDelegate() {
+        synchronized (this) {
+            return mCheckOpsDelegate;
+        }
+    }
+
+    public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) {
+        synchronized (this) {
+            mCheckOpsDelegate = delegate;
+        }
+    }
+
     @Override
     public int checkOperation(int code, int uid, String packageName) {
-        verifyIncomingUid(uid);
-        verifyIncomingOp(code);
-        String resolvedPackageName = resolvePackageName(uid, packageName);
-        if (resolvedPackageName == null) {
-            return AppOpsManager.MODE_IGNORED;
-        }
+        final CheckOpsDelegate delegate;
         synchronized (this) {
+            if (mCheckOpsDelegate == null) {
+                return checkOperationImpl(code, uid, packageName);
+            }
+            delegate = mCheckOpsDelegate;
+        }
+        return delegate.checkOperation(code, uid, packageName,
+                    AppOpsService.this::checkOperationImpl);
+    }
+
+    private int checkOperationImpl(int code, int uid, String packageName) {
+        synchronized (this) {
+            verifyIncomingUid(uid);
+            verifyIncomingOp(code);
+            String resolvedPackageName = resolvePackageName(uid, packageName);
+            if (resolvedPackageName == null) {
+                return AppOpsManager.MODE_IGNORED;
+            }
             if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
@@ -1439,20 +1470,33 @@
 
     @Override
     public int checkAudioOperation(int code, int usage, int uid, String packageName) {
-        boolean suspended;
-        try {
-            suspended = isPackageSuspendedForUser(packageName, uid);
-        } catch (IllegalArgumentException ex) {
-            // Package not found.
-            suspended = false;
-        }
-
-        if (suspended) {
-            Slog.i(TAG, "Audio disabled for suspended package=" + packageName + " for uid=" + uid);
-            return AppOpsManager.MODE_IGNORED;
-        }
-
+        final CheckOpsDelegate delegate;
         synchronized (this) {
+            if (mCheckOpsDelegate == null) {
+                return checkAudioOperationImpl(code, usage, uid, packageName);
+            }
+            delegate = mCheckOpsDelegate;
+        }
+        return delegate.checkAudioOperation(code, usage, uid, packageName,
+                AppOpsService.this::checkAudioOperationImpl);
+    }
+
+    private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
+        synchronized (this) {
+            boolean suspended;
+            try {
+                suspended = isPackageSuspendedForUser(packageName, uid);
+            } catch (IllegalArgumentException ex) {
+                // Package not found.
+                suspended = false;
+            }
+
+            if (suspended) {
+                Slog.i(TAG, "Audio disabled for suspended package=" + packageName
+                        + " for uid=" + uid);
+                return AppOpsManager.MODE_IGNORED;
+            }
+
             final int mode = checkRestrictionLocked(code, usage, uid, packageName);
             if (mode != AppOpsManager.MODE_ALLOWED) {
                 return mode;
@@ -1530,10 +1574,10 @@
     }
 
     @Override
-    public int noteProxyOperation(int code, String proxyPackageName,
-            int proxiedUid, String proxiedPackageName) {
+    public int noteProxyOperation(int code, int proxyUid,
+            String proxyPackageName, int proxiedUid, String proxiedPackageName) {
+        verifyIncomingUid(proxyUid);
         verifyIncomingOp(code);
-        final int proxyUid = Binder.getCallingUid();
         String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
         if (resolveProxyPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
@@ -1553,6 +1597,18 @@
 
     @Override
     public int noteOperation(int code, int uid, String packageName) {
+        final CheckOpsDelegate delegate;
+        synchronized (this) {
+            if (mCheckOpsDelegate == null) {
+                return noteOperationImpl(code, uid, packageName);
+            }
+            delegate = mCheckOpsDelegate;
+        }
+        return delegate.noteOperation(code, uid, packageName,
+                AppOpsService.this::noteOperationImpl);
+    }
+
+    private int noteOperationImpl(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
         String resolvedPackageName = resolvePackageName(uid, packageName);
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 5c14459..50f15ca0 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -624,7 +624,7 @@
             // them will get the new sequence number at that point.  (See for example how testing
             // of JobScheduler's BatteryController works.)
             sendBatteryChangedIntentLocked();
-            if (mLastBatteryLevel != mHealthInfo.batteryLevel) {
+            if (mLastBatteryLevel != mHealthInfo.batteryLevel || mLastPlugType != mPlugType) {
                 sendBatteryLevelChangedIntentLocked();
             }
 
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index ce1be6f..9a7c345 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -17,22 +17,31 @@
 package com.android.server;
 
 import android.app.AppGlobals;
+import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArrayMap;
+import android.util.KeyValueListParser;
 import android.util.Slog;
 
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.BinderCallsStats;
+import com.android.internal.os.BinderInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 
 public class BinderCallsStatsService extends Binder {
 
@@ -41,23 +50,132 @@
     private static final String PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
             = "persist.sys.binder_calls_detailed_tracking";
 
-    public static void start() {
-        BinderCallsStatsService service = new BinderCallsStatsService();
-        ServiceManager.addService("binder_calls_stats", service);
-        boolean detailedTrackingEnabled = SystemProperties.getBoolean(
-                PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, false);
+    /** Listens for flag changes. */
+    private static class SettingsObserver extends ContentObserver {
+        private static final String SETTINGS_ENABLED_KEY = "enabled";
+        private static final String SETTINGS_DETAILED_TRACKING_KEY = "detailed_tracking";
+        private static final String SETTINGS_UPLOAD_DATA_KEY = "upload_data";
+        private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
 
-        if (detailedTrackingEnabled) {
-            Slog.i(TAG, "Enabled CPU usage tracking for binder calls. Controlled by "
-                    + PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
-                    + " or via dumpsys binder_calls_stats --enable-detailed-tracking");
-            BinderCallsStats.getInstance().setDetailedTracking(true);
+        private boolean mEnabled;
+        private final Uri mUri = Settings.Global.getUriFor(Settings.Global.BINDER_CALLS_STATS);
+        private final Context mContext;
+        private final KeyValueListParser mParser = new KeyValueListParser(',');
+        private final BinderCallsStats mBinderCallsStats;
+
+        public SettingsObserver(Context context, BinderCallsStats binderCallsStats) {
+            super(BackgroundThread.getHandler());
+            mContext = context;
+            context.getContentResolver().registerContentObserver(mUri, false, this,
+                    UserHandle.USER_SYSTEM);
+            mBinderCallsStats = binderCallsStats;
+            // Always kick once to ensure that we match current state
+            onChange();
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            if (mUri.equals(uri)) {
+                onChange();
+            }
+        }
+
+        public void onChange() {
+            // Do not overwrite the default set manually.
+            if (!SystemProperties.get(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING).isEmpty()) {
+              return;
+            }
+
+            try {
+                    mParser.setString(Settings.Global.getString(mContext.getContentResolver(),
+                            Settings.Global.BINDER_CALLS_STATS));
+            } catch (IllegalArgumentException e) {
+                    Slog.e(TAG, "Bad binder call stats settings", e);
+            }
+            mBinderCallsStats.setDetailedTracking(mParser.getBoolean(
+                    SETTINGS_DETAILED_TRACKING_KEY, BinderCallsStats.DETAILED_TRACKING_DEFAULT));
+            mBinderCallsStats.setSamplingInterval(mParser.getInt(
+                    SETTINGS_SAMPLING_INTERVAL_KEY,
+                    BinderCallsStats.PERIODIC_SAMPLING_INTERVAL_DEFAULT));
+
+
+            final boolean enabled =
+                    mParser.getBoolean(SETTINGS_ENABLED_KEY, BinderCallsStats.ENABLED_DEFAULT);
+            if (mEnabled != enabled) {
+                Binder.setObserver(enabled ? mBinderCallsStats : null);
+                mEnabled = enabled;
+                mBinderCallsStats.reset();
+            }
         }
     }
 
-    public static void reset() {
+    /**
+     * @hide Only for use within the system server.
+     */
+    public static class Internal {
+        private final BinderCallsStats mBinderCallsStats;
+
+        Internal(BinderCallsStats binderCallsStats) {
+            this.mBinderCallsStats = binderCallsStats;
+        }
+
+        public ArrayList<BinderCallsStats.ExportedCallStat> getExportedCallStats() {
+            return mBinderCallsStats.getExportedCallStats();
+        }
+
+        public ArrayMap<String, Integer> getExportedExceptionStats() {
+            return mBinderCallsStats.getExportedExceptionStats();
+        }
+    }
+
+    public static class LifeCycle extends SystemService {
+        private BinderCallsStatsService mService;
+        private BinderCallsStats mBinderCallsStats;
+
+        public LifeCycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            mBinderCallsStats = new BinderCallsStats(new BinderCallsStats.Injector());
+            mService = new BinderCallsStatsService(mBinderCallsStats);
+            publishLocalService(Internal.class, new Internal(mBinderCallsStats));
+            publishBinderService("binder_calls_stats", mService);
+            boolean detailedTrackingEnabled = SystemProperties.getBoolean(
+                    PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, false);
+
+            if (detailedTrackingEnabled) {
+                Slog.i(TAG, "Enabled CPU usage tracking for binder calls. Controlled by "
+                        + PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
+                        + " or via dumpsys binder_calls_stats --enable-detailed-tracking");
+                mBinderCallsStats.setDetailedTracking(true);
+            }
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+                mService.systemReady(getContext());
+                mBinderCallsStats.systemReady(getContext());
+            }
+        }
+    }
+
+    private SettingsObserver mSettingsObserver;
+    private final BinderCallsStats mBinderCallsStats;
+
+    BinderCallsStatsService(BinderCallsStats binderCallsStats) {
+        mBinderCallsStats = binderCallsStats;
+    }
+
+    public void systemReady(Context context) {
+        mSettingsObserver = new SettingsObserver(context, mBinderCallsStats);
+    }
+
+    public void reset() {
         Slog.i(TAG, "Resetting stats");
-        BinderCallsStats.getInstance().reset();
+        mBinderCallsStats.reset();
     }
 
     @Override
@@ -73,12 +191,12 @@
                     return;
                 } else if ("--enable-detailed-tracking".equals(arg)) {
                     SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "1");
-                    BinderCallsStats.getInstance().setDetailedTracking(true);
+                    mBinderCallsStats.setDetailedTracking(true);
                     pw.println("Detailed tracking enabled");
                     return;
                 } else if ("--disable-detailed-tracking".equals(arg)) {
                     SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "");
-                    BinderCallsStats.getInstance().setDetailedTracking(false);
+                    mBinderCallsStats.setDetailedTracking(false);
                     pw.println("Detailed tracking disabled");
                     return;
                 } else if ("-h".equals(arg)) {
@@ -92,7 +210,7 @@
                 }
             }
         }
-        BinderCallsStats.getInstance().dump(pw, getAppIdToPackagesMap(), verbose);
+        mBinderCallsStats.dump(pw, getAppIdToPackagesMap(), verbose);
     }
 
     private Map<Integer, String> getAppIdToPackagesMap() {
@@ -106,7 +224,13 @@
         }
         Map<Integer,String> map = new HashMap<>();
         for (PackageInfo pkg : packages) {
-            map.put(pkg.applicationInfo.uid, pkg.packageName);
+            String name = pkg.packageName;
+            int uid = pkg.applicationInfo.uid;
+            // Use sharedUserId string as package name if there are collisions
+            if (pkg.sharedUserId != null && map.containsKey(uid)) {
+                name = "shared:" + pkg.sharedUserId;
+            }
+            map.put(uid, name);
         }
         return map;
     }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index aa426d3..a07939e 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -53,12 +53,16 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.os.UserManagerInternal.UserRestrictionsListener;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
+import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
+import android.util.Log;
 import android.util.Slog;
 import android.util.StatsLog;
 
@@ -207,7 +211,7 @@
     // bluetooth profile services
     private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
 
-    private final boolean mPermissionReviewRequired;
+    private final boolean mWirelessConsentRequired;
 
     private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
         @Override
@@ -364,8 +368,8 @@
 
         mContext = context;
 
-        mPermissionReviewRequired = context.getResources()
-                .getBoolean(com.android.internal.R.bool.config_permissionReviewRequired);
+        mWirelessConsentRequired = context.getResources()
+                .getBoolean(com.android.internal.R.bool.config_wirelessConsentRequired);
 
         mCrashes = 0;
         mBluetooth = null;
@@ -386,6 +390,15 @@
         mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
         mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
 
+        // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils
+        boolean isHearingAidEnabled;
+        String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS);
+        if (!TextUtils.isEmpty(value)) {
+            isHearingAidEnabled = Boolean.parseBoolean(value);
+            Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled);
+            FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled);
+        }
+
         IntentFilter filter = new IntentFilter();
         filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
         filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
@@ -872,7 +885,7 @@
             mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                     "Need BLUETOOTH ADMIN permission");
 
-            if (!isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName,
+            if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
                     callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
                 return false;
             }
@@ -909,7 +922,7 @@
             mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                     "Need BLUETOOTH ADMIN permission");
 
-            if (isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName,
+            if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName,
                     callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
                 return false;
             }
@@ -932,7 +945,7 @@
 
     private boolean startConsentUiIfNeeded(String packageName,
             int callingUid, String intentAction) throws RemoteException {
-        if (checkBluetoothPermissionWhenPermissionReviewRequired()) {
+        if (checkBluetoothPermissionWhenWirelessConsentRequired()) {
             return false;
         }
         try {
@@ -965,21 +978,18 @@
 
     /**
      * Check if the caller must still pass permission check or if the caller is exempted
-     * from the consent UI via the MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED check.
+     * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check.
      *
      * Commands from some callers may be exempted from triggering the consent UI when
      * enabling bluetooth. This exemption is checked via the
-     * MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED and allows calls to skip
+     * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip
      * the consent UI where it may otherwise be required.
      *
      * @hide
      */
-    private boolean checkBluetoothPermissionWhenPermissionReviewRequired() {
-        if (!mPermissionReviewRequired) {
-            return false;
-        }
+    private boolean checkBluetoothPermissionWhenWirelessConsentRequired() {
         int result = mContext.checkCallingPermission(
-                android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED);
+                android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED);
         return result == PackageManager.PERMISSION_GRANTED;
     }
 
@@ -1161,6 +1171,26 @@
         }
 
         private boolean bindService() {
+            int state = BluetoothAdapter.STATE_OFF;
+            try {
+                mBluetoothLock.readLock().lock();
+                if (mBluetooth != null) {
+                    state = mBluetooth.getState();
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to call getState", e);
+                return false;
+            } finally {
+                mBluetoothLock.readLock().unlock();
+            }
+
+            if (!mEnable || state != BluetoothAdapter.STATE_ON) {
+                if (DBG) {
+                    Slog.d(TAG, "Unable to bindService while Bluetooth is disabled");
+                }
+                return false;
+            }
+
             if (mIntent != null && mService == null && doBind(mIntent, this, 0,
                     UserHandle.CURRENT_OR_SELF)) {
                 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3c94a34..ba5f323 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -500,6 +500,9 @@
 
     private final IpConnectivityLog mMetricsLog;
 
+    @GuardedBy("mBandwidthRequests")
+    private final SparseArray<Integer> mBandwidthRequests = new SparseArray(10);
+
     @VisibleForTesting
     final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
 
@@ -2107,6 +2110,18 @@
                 pw.println("currently holding WakeLock for: " + (duration / 1000) + "s");
             }
             mWakelockLogs.reverseDump(fd, pw, args);
+
+            pw.println();
+            pw.println("bandwidth update requests (by uid):");
+            pw.increaseIndent();
+            synchronized (mBandwidthRequests) {
+                for (int i = 0; i < mBandwidthRequests.size(); i++) {
+                    pw.println("[" + mBandwidthRequests.keyAt(i)
+                            + "]: " + mBandwidthRequests.valueAt(i));
+                }
+            }
+            pw.decreaseIndent();
+
             pw.decreaseIndent();
         }
     }
@@ -2179,8 +2194,7 @@
                     break;
                 }
                 case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
-                    Integer score = (Integer) msg.obj;
-                    if (score != null) updateNetworkScore(nai, score.intValue());
+                    updateNetworkScore(nai, msg.arg1);
                     break;
                 }
                 case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
@@ -2188,7 +2202,7 @@
                         loge("ERROR: already-connected network explicitly selected.");
                     }
                     nai.networkMisc.explicitlySelected = true;
-                    nai.networkMisc.acceptUnvalidated = (boolean) msg.obj;
+                    nai.networkMisc.acceptUnvalidated = msg.arg1 == 1;
                     break;
                 }
                 case NetworkAgent.EVENT_PACKET_KEEPALIVE: {
@@ -2229,6 +2243,7 @@
                         updateCapabilities(oldScore, nai, nai.networkCapabilities);
                         // If score has changed, rebroadcast to NetworkFactories. b/17726566
                         if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
+                        if (valid) handleFreshlyValidatedNetwork(nai);
                     }
                     updateInetCondition(nai);
                     // Let the NetworkAgent know the state of its network
@@ -2323,6 +2338,16 @@
                 mDefaultRequest.networkCapabilities, nai.networkCapabilities);
     }
 
+    private void handleFreshlyValidatedNetwork(NetworkAgentInfo nai) {
+        if (nai == null) return;
+        // If the Private DNS mode is opportunistic, reprogram the DNS servers
+        // in order to restart a validation pass from within netd.
+        final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
+        if (cfg.useTls && TextUtils.isEmpty(cfg.hostname)) {
+            updateDnses(nai.linkProperties, null, nai.network.netId);
+        }
+    }
+
     private void handlePrivateDnsSettingsChanged() {
         final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
 
@@ -4256,6 +4281,14 @@
         }
         if (nai != null) {
             nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
+            synchronized (mBandwidthRequests) {
+                final int uid = Binder.getCallingUid();
+                Integer uidReqs = mBandwidthRequests.get(uid);
+                if (uidReqs == null) {
+                    uidReqs = new Integer(0);
+                }
+                mBandwidthRequests.put(uid, ++uidReqs);
+            }
             return true;
         }
         return false;
@@ -5852,4 +5885,4 @@
             pw.println("    Get airplane mode.");
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/InputContentUriTokenHandler.java b/services/core/java/com/android/server/InputContentUriTokenHandler.java
index 57cdc94..6338b2f 100644
--- a/services/core/java/com/android/server/InputContentUriTokenHandler.java
+++ b/services/core/java/com/android/server/InputContentUriTokenHandler.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
+import android.app.UriGrantsManager;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Binder;
@@ -27,6 +28,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 final class InputContentUriTokenHandler extends IInputContentUriToken.Stub {
 
@@ -63,12 +65,8 @@
                 return;
             }
 
-            try {
-                mPermissionOwnerToken = ActivityManager.getService()
-                        .newUriPermissionOwner("InputContentUriTokenHandler");
-            } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
-            }
+            mPermissionOwnerToken = LocalServices.getService(UriGrantsManagerInternal.class)
+                    .newUriPermissionOwner("InputContentUriTokenHandler");
 
             doTakeLocked(mPermissionOwnerToken);
         }
@@ -78,7 +76,7 @@
         long origId = Binder.clearCallingIdentity();
         try {
             try {
-                ActivityManager.getService().grantUriPermissionFromOwner(
+                UriGrantsManager.getService().grantUriPermissionFromOwner(
                         permissionOwner, mSourceUid, mTargetPackage, mUri,
                         Intent.FLAG_GRANT_READ_URI_PERMISSION, mSourceUserId, mTargetUserId);
             } catch (RemoteException e) {
@@ -96,11 +94,9 @@
                 return;
             }
             try {
-                ActivityManager.getService().revokeUriPermissionFromOwner(
-                        mPermissionOwnerToken, mUri,
-                        Intent.FLAG_GRANT_READ_URI_PERMISSION, mSourceUserId);
-            } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
+                LocalServices.getService(UriGrantsManagerInternal.class)
+                        .revokeUriPermissionFromOwner(mPermissionOwnerToken, mUri,
+                                Intent.FLAG_GRANT_READ_URI_PERMISSION, mSourceUserId);
             } finally {
                 mPermissionOwnerToken = null;
             }
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 4b8ece9..02a62ff 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -51,6 +51,7 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.Manifest;
+import android.accessibilityservice.AccessibilityService;
 import android.annotation.AnyThread;
 import android.annotation.BinderThread;
 import android.annotation.ColorInt;
@@ -888,10 +889,12 @@
                 if (showImeUri.equals(uri)) {
                     updateKeyboardFromSettingsLocked();
                 } else if (accessibilityRequestingNoImeUri.equals(uri)) {
-                    mAccessibilityRequestingNoSoftKeyboard = Settings.Secure.getIntForUser(
+                    final int accessibilitySoftKeyboardSetting = Settings.Secure.getIntForUser(
                             mContext.getContentResolver(),
-                            Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
-                            0, mUserId) == 1;
+                            Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0, mUserId);
+                    mAccessibilityRequestingNoSoftKeyboard =
+                            (accessibilitySoftKeyboardSetting & AccessibilityService.SHOW_MODE_MASK)
+                                    == AccessibilityService.SHOW_MODE_HIDDEN;
                     if (mAccessibilityRequestingNoSoftKeyboard) {
                         final boolean showRequested = mShowRequested;
                         hideCurrentInputLocked(0, null);
@@ -1711,10 +1714,9 @@
     }
 
     @Override
-    public void addClient(IInputMethodClient client,
-            IInputContext inputContext, int uid, int pid) {
-        if (!calledFromValidUser()) {
-            return;
+    public void addClient(IInputMethodClient client, IInputContext inputContext, int uid, int pid) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Only system process can call this method.");
         }
         synchronized (mMethodMap) {
             mClients.put(client.asBinder(), new ClientState(client,
@@ -1724,8 +1726,8 @@
 
     @Override
     public void removeClient(IInputMethodClient client) {
-        if (!calledFromValidUser()) {
-            return;
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Only system process can call this method.");
         }
         synchronized (mMethodMap) {
             ClientState cs = mClients.remove(client.asBinder());
@@ -1913,6 +1915,7 @@
         return startInputInnerLocked();
     }
 
+    @GuardedBy("mMethodMap")
     InputBindResult startInputInnerLocked() {
         if (mCurMethodId == null) {
             return InputBindResult.NO_IME;
@@ -2549,6 +2552,7 @@
         }
     }
 
+    @GuardedBy("mMethodMap")
     boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
         mShowRequested = true;
         if (mAccessibilityRequestingNoSoftKeyboard) {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index de02e81..232c151 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -795,6 +795,7 @@
      * location updates.
      */
     private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
+        private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
         final Identity mIdentity;
         final int mAllowedResolutionLevel;  // resolution level allowed to receiver
 
@@ -838,6 +839,10 @@
                 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
             }
             mWakeLock.setWorkSource(workSource);
+
+            // For a non-reference counted wakelock, each acquire will reset the timeout, and we
+            // only need to release it once.
+            mWakeLock.setReferenceCounted(false);
         }
 
         @Override
@@ -1099,9 +1104,8 @@
         // this must be called while synchronized by caller in a synchronized block
         // containing the sending of the broadcaset
         private void incrementPendingBroadcastsLocked() {
-            if (mPendingBroadcasts++ == 0) {
-                mWakeLock.acquire();
-            }
+            mPendingBroadcasts++;
+            mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
         }
 
         private void decrementPendingBroadcastsLocked() {
@@ -1549,6 +1553,22 @@
         return -1;
     }
 
+    private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
+        switch(allowedResolutionLevel) {
+            case RESOLUTION_LEVEL_COARSE:
+                return AppOpsManager.OPSTR_COARSE_LOCATION;
+            case RESOLUTION_LEVEL_FINE:
+                return AppOpsManager.OPSTR_FINE_LOCATION;
+            case RESOLUTION_LEVEL_NONE:
+                // The client is not allowed to get any location, so both FINE and COARSE ops will
+                // be denied. Pick the most restrictive one to be safe.
+                return AppOpsManager.OPSTR_FINE_LOCATION;
+            default:
+                // Use the most restrictive ops if not sure.
+                return AppOpsManager.OPSTR_FINE_LOCATION;
+        }
+    }
+
     boolean reportLocationAccessNoThrow(
             int pid, int uid, String packageName, int allowedResolutionLevel) {
         int op = resolutionLevelToOp(allowedResolutionLevel);
@@ -2295,7 +2315,7 @@
                 }
 
                 // Don't return stale location to apps with foreground-only location permission.
-                String op = getResolutionPermission(allowedResolutionLevel);
+                String op = resolutionLevelToOpStr(allowedResolutionLevel);
                 long locationAgeMs = SystemClock.elapsedRealtime() -
                         location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
                 if ((locationAgeMs > mLastLocationMaxAgeMs)
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 8402087..f15cd2ad 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -42,6 +42,7 @@
 import android.util.Slog;
 
 import com.android.internal.telephony.IMms;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 import java.util.List;
 
@@ -512,7 +513,7 @@
 
             long token = Binder.clearCallingIdentity();
             try {
-                LocalServices.getService(ActivityManagerInternal.class)
+                LocalServices.getService(UriGrantsManagerInternal.class)
                         .grantUriPermissionFromIntent(callingUid, PHONE_PACKAGE_NAME,
                                 grantIntent, UserHandle.USER_SYSTEM);
 
@@ -523,7 +524,7 @@
                 List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent(
                         intent);
                 if (carrierPackages != null && carrierPackages.size() == 1) {
-                    LocalServices.getService(ActivityManagerInternal.class)
+                    LocalServices.getService(UriGrantsManagerInternal.class)
                             .grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
                                     grantIntent, UserHandle.USER_SYSTEM);
                 }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 74d8755..d829602 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -646,12 +646,7 @@
 
             SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
 
-            try {
-                mConnector.execute("strict", "enable");
-                mStrictEnabled = true;
-            } catch (NativeDaemonConnectorException e) {
-                Log.wtf(TAG, "Failed strict enable", e);
-            }
+            mStrictEnabled = true;
 
             setDataSaverModeEnabled(mDataSaverMode);
 
@@ -1232,25 +1227,25 @@
     public boolean getIpForwardingEnabled() throws IllegalStateException{
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        final NativeDaemonEvent event;
         try {
-            event = mConnector.execute("ipfwd", "status");
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            final boolean isEnabled = mNetdService.ipfwdEnabled();
+            return isEnabled;
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
-
-        // 211 Forwarding enabled
-        event.checkCode(IpFwdStatusResult);
-        return event.getMessage().endsWith("enabled");
     }
 
     @Override
     public void setIpForwardingEnabled(boolean enable) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering");
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            if (enable) {
+                mNetdService.ipfwdEnableForwarding("tethering");
+            } else {
+                mNetdService.ipfwdDisableForwarding("tethering");
+            }
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1376,11 +1371,14 @@
     }
 
     private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
-        final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface);
         try {
-            mConnector.execute(cmd);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            if (add) {
+                mNetdService.ipfwdAddInterfaceForward(fromIface, toIface);
+            } else {
+                mNetdService.ipfwdRemoveInterfaceForward(fromIface, toIface);
+            }
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1495,10 +1493,9 @@
             }
 
             try {
-                mConnector.execute("idletimer", "add", iface, Integer.toString(timeout),
-                        Integer.toString(type));
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+                mNetdService.idletimerAddInterface(iface, timeout, Integer.toString(type));
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
             mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
 
@@ -1529,10 +1526,10 @@
             }
 
             try {
-                mConnector.execute("idletimer", "remove", iface,
-                        Integer.toString(params.timeout), Integer.toString(params.type));
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+                mNetdService.idletimerRemoveInterface(iface,
+                        params.timeout, Integer.toString(params.type));
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
             mActiveIdleTimers.remove(iface);
             mDaemonHandler.post(new Runnable() {
@@ -1810,26 +1807,26 @@
     }
 
     private void applyUidCleartextNetworkPolicy(int uid, int policy) {
-        final String policyString;
+        final int policyValue;
         switch (policy) {
             case StrictMode.NETWORK_POLICY_ACCEPT:
-                policyString = "accept";
+                policyValue = INetd.PENALTY_POLICY_ACCEPT;
                 break;
             case StrictMode.NETWORK_POLICY_LOG:
-                policyString = "log";
+                policyValue = INetd.PENALTY_POLICY_LOG;
                 break;
             case StrictMode.NETWORK_POLICY_REJECT:
-                policyString = "reject";
+                policyValue = INetd.PENALTY_POLICY_REJECT;
                 break;
             default:
                 throw new IllegalArgumentException("Unknown policy " + policy);
         }
 
         try {
-            mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString);
+            mNetdService.strictUidCleartextPenalty(uid, policyValue);
             mUidCleartextPolicy.put(uid, policy);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1847,6 +1844,7 @@
                 return;
             }
 
+            // TODO: remove this code after removing prepareNativeDaemon()
             if (!mStrictEnabled) {
                 // Module isn't enabled yet; stash the requested policy away to
                 // apply later once the daemon is connected.
@@ -2271,6 +2269,7 @@
         return ruleName;
     }
 
+    @GuardedBy("mRulesLock")
     private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
         switch (chain) {
             case FIREWALL_CHAIN_STANDBY:
@@ -2313,9 +2312,9 @@
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
         try {
-            mConnector.execute("clatd", "start", interfaceName);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.clatdStart(interfaceName);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -2324,28 +2323,13 @@
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
         try {
-            mConnector.execute("clatd", "stop", interfaceName);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.clatdStop(interfaceName);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
     @Override
-    public boolean isClatdStarted(String interfaceName) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        final NativeDaemonEvent event;
-        try {
-            event = mConnector.execute("clatd", "status", interfaceName);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-
-        event.checkCode(ClatdStatusResult);
-        return event.getMessage().endsWith("started");
-    }
-
-    @Override
     public void registerNetworkActivityListener(INetworkActivityListener listener) {
         mNetworkActivityListeners.register(listener);
     }
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 3ca3a96..fe9f1b5 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -1,19 +1,5 @@
 # Connectivity / Networking
-per-file ConnectivityService.java=ek@google.com
-per-file ConnectivityService.java=jchalard@google.com
-per-file ConnectivityService.java=lorenzo@google.com
-per-file ConnectivityService.java=satk@google.com
-per-file NetworkManagementService.java=ek@google.com
-per-file NetworkManagementService.java=jchalard@google.com
-per-file NetworkManagementService.java=lorenzo@google.com
-per-file NetworkManagementService.java=satk@google.com
-per-file NsdService.java=ek@google.com
-per-file NsdService.java=jchalard@google.com
-per-file NsdService.java=lorenzo@google.com
-per-file NsdService.java=satk@google.com
+per-file ConnectivityService.java,NetworkManagementService.java,NsdService.java = codewiz@google.com, ek@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
 
-# Vibrator
-per-file VibratorService.java=michaelwr@google.com
-
-# Threads
-per-file DisplayThread.java=michaelwr@google.com
+# Vibrator / Threads
+per-file VibratorService.java, DisplayThread.java = michaelwr@google.com
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 5a25f48..0deaee7 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -16,8 +16,16 @@
 
 package com.android.server;
 
+import static android.app.ActivityManager.UID_OBSERVER_ACTIVE;
+import static android.app.ActivityManager.UID_OBSERVER_GONE;
+
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.IActivityManager;
+import android.app.IUidObserver;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -26,24 +34,30 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.MediaStore;
+import android.provider.Settings;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
-import android.system.StructStat;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.function.pooled.PooledLambda;
 
 import dalvik.system.DexFile;
 import dalvik.system.VMRuntime;
@@ -53,12 +67,13 @@
 import java.io.InputStream;
 import java.io.DataInputStream;
 import java.io.IOException;
-import java.io.EOFException;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
 import java.util.ArrayList;
 
 import java.util.zip.ZipFile;
-import java.util.zip.ZipException;
 import java.util.zip.ZipEntry;
 
 /**
@@ -70,16 +85,51 @@
 public final class PinnerService extends SystemService {
     private static final boolean DEBUG = false;
     private static final String TAG = "PinnerService";
-    private static final int MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); //80MB max
+
     private static final String PIN_META_FILENAME = "pinlist.meta";
     private static final int PAGE_SIZE = (int) Os.sysconf(OsConstants._SC_PAGESIZE);
+    private static final int MATCH_FLAGS = PackageManager.MATCH_DEFAULT_ONLY
+            | PackageManager.MATCH_DIRECT_BOOT_AWARE
+            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+
+    private static final int KEY_CAMERA = 0;
+    private static final int KEY_HOME = 1;
+
+    private static final int MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); // 80MB max for camera app.
+    private static final int MAX_HOME_PIN_SIZE = 6 * (1 << 20); // 6MB max for home app.
+
+    @IntDef({KEY_CAMERA, KEY_HOME})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AppKey {}
 
     private final Context mContext;
-    private final boolean mShouldPinCamera;
+    private final ActivityManagerInternal mAmInternal;
+    private final IActivityManager mAm;
+    private final UserManager mUserManager;
 
-    /* These lists protected by PinnerService monitor lock */
-    private final ArrayList<PinnedFile> mPinnedFiles = new ArrayList<PinnedFile>();
-    private final ArrayList<PinnedFile> mPinnedCameraFiles = new ArrayList<PinnedFile>();
+    /** The list of the statically pinned files. */
+    @GuardedBy("this")
+    private final ArrayList<PinnedFile> mPinnedFiles = new ArrayList<>();
+
+    /** The list of the pinned apps. This is a map from {@link AppKey} to a pinned app. */
+    @GuardedBy("this")
+    private final ArrayMap<Integer, PinnedApp> mPinnedApps = new ArrayMap<>();
+
+    /**
+     * The list of the pinned apps that need to be repinned as soon as the all processes of a given
+     * uid are no longer active. Note that with background dex opt, the new dex/vdex files are only
+     * loaded into the processes once it restarts. So in case background dex opt recompiled these
+     * files, we still need to keep the old ones pinned until the processes restart.
+     * <p>
+     * This is a map from uid to {@link AppKey}
+     */
+    @GuardedBy("this")
+    private final ArrayMap<Integer, Integer> mPendingRepin = new ArrayMap<>();
+
+    /**
+     * A set of {@link AppKey} that are configured to be pinned.
+     */
+    private final ArraySet<Integer> mPinKeys = new ArraySet<>();
 
     private BinderService mBinderService;
     private PinnerHandler mPinnerHandler = null;
@@ -87,13 +137,13 @@
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-          // If this user's camera app has been updated, update pinned files accordingly.
-          if (intent.getAction() == Intent.ACTION_PACKAGE_REPLACED) {
+          // If an app has updated, update pinned files accordingly.
+          if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) {
                 Uri packageUri = intent.getData();
                 String packageName = packageUri.getSchemeSpecificPart();
                 ArraySet<String> updatedPackages = new ArraySet<>();
                 updatedPackages.add(packageName);
-                update(updatedPackages);
+                update(updatedPackages, true /* force */);
             }
         }
     };
@@ -102,14 +152,30 @@
         super(context);
 
         mContext = context;
-        mShouldPinCamera = context.getResources().getBoolean(
+        boolean shouldPinCamera = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_pinnerCameraApp);
+        boolean shouldPinHome = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_pinnerHomeApp);
+        if (shouldPinCamera) {
+            mPinKeys.add(KEY_CAMERA);
+        }
+        if (shouldPinHome) {
+            mPinKeys.add(KEY_HOME);
+        }
         mPinnerHandler = new PinnerHandler(BackgroundThread.get().getLooper());
 
+        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
+        mAm = ActivityManager.getService();
+
+        mUserManager = mContext.getSystemService(UserManager.class);
+
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
         filter.addDataScheme("package");
         mContext.registerReceiver(mBroadcastReceiver, filter);
+
+        registerUidListener();
+        registerUserSetupCompleteListener();
     }
 
     @Override
@@ -122,32 +188,43 @@
         publishLocalService(PinnerService.class, this);
 
         mPinnerHandler.obtainMessage(PinnerHandler.PIN_ONSTART_MSG).sendToTarget();
-        mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, UserHandle.USER_SYSTEM, 0)
-                .sendToTarget();
+        sendPinAppsMessage(UserHandle.USER_SYSTEM);
     }
 
     /**
-     * Pin camera on user switch.
-     * If more than one user is using the device
-     * each user may set a different preference for the camera app.
-     * Make sure that user's preference is pinned into memory.
+     * Repin apps on user switch.
+     * <p>
+     * If more than one user is using the device each user may set a different preference for the
+     * individual apps. Make sure that user's preference is pinned into memory.
      */
     @Override
     public void onSwitchUser(int userHandle) {
-        mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, userHandle, 0).sendToTarget();
+        if (!mUserManager.isManagedProfile(userHandle)) {
+            sendPinAppsMessage(userHandle);
+        }
+    }
+
+    @Override
+    public void onUnlockUser(int userHandle) {
+        if (!mUserManager.isManagedProfile(userHandle)) {
+            sendPinAppsMessage(userHandle);
+        }
     }
 
     /**
      * Update the currently pinned files.
-     * Specifically, this only updates camera pinning.
+     * Specifically, this only updates pinning for the apps that need to be pinned.
      * The other files pinned in onStart will not need to be updated.
      */
-    public void update(ArraySet<String> updatedPackages) {
-        ApplicationInfo cameraInfo = getCameraInfo(UserHandle.USER_SYSTEM);
-        if (cameraInfo != null && updatedPackages.contains(cameraInfo.packageName)) {
-            Slog.i(TAG, "Updating pinned files.");
-            mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, UserHandle.USER_SYSTEM, 0)
-                    .sendToTarget();
+    public void update(ArraySet<String> updatedPackages, boolean force) {
+        int currentUser = ActivityManager.getCurrentUser();
+        for (int i = mPinKeys.size() - 1; i >= 0; i--) {
+            int key = mPinKeys.valueAt(i);
+            ApplicationInfo info = getInfoForKey(key, currentUser);
+            if (info != null && updatedPackages.contains(info.packageName)) {
+                Slog.i(TAG, "Updating pinned files for " + info.packageName + " force=" + force);
+                sendPinAppMessage(key, currentUser, force);
+            }
         }
     }
 
@@ -175,24 +252,99 @@
     }
 
     /**
-     * Handler for camera pinning message
+     * Registers a listener to repin the home app when user setup is complete, as the home intent
+     * initially resolves to setup wizard, but once setup is complete, it will resolve to the
+     * regular home app.
      */
-    private void handlePinCamera(int userHandle) {
-        if (!mShouldPinCamera) return;
-        if (!pinCamera(userHandle)) {
-            if (DEBUG) {
-                Slog.v(TAG, "Failed to pin camera.");
+    private void registerUserSetupCompleteListener() {
+        Uri userSetupCompleteUri = Settings.Secure.getUriFor(
+                Settings.Secure.USER_SETUP_COMPLETE);
+        mContext.getContentResolver().registerContentObserver(userSetupCompleteUri,
+                false, new ContentObserver(null) {
+                    @Override
+                    public void onChange(boolean selfChange, Uri uri) {
+                        if (userSetupCompleteUri.equals(uri)) {
+                            sendPinAppMessage(KEY_HOME, ActivityManager.getCurrentUser(),
+                                    true /* force */);
+                        }
+                    }
+                }, UserHandle.USER_ALL);
+    }
+
+    private void registerUidListener() {
+        try {
+            mAm.registerUidObserver(new IUidObserver.Stub() {
+                @Override
+                public void onUidGone(int uid, boolean disabled) throws RemoteException {
+                    mPinnerHandler.sendMessage(PooledLambda.obtainMessage(
+                            PinnerService::handleUidGone, PinnerService.this, uid));
+                }
+
+                @Override
+                public void onUidActive(int uid) throws RemoteException {
+                    mPinnerHandler.sendMessage(PooledLambda.obtainMessage(
+                            PinnerService::handleUidActive, PinnerService.this, uid));
+                }
+
+                @Override
+                public void onUidIdle(int uid, boolean disabled) throws RemoteException {
+                }
+
+                @Override
+                public void onUidStateChanged(int uid, int procState, long procStateSeq)
+                        throws RemoteException {
+                }
+
+                @Override
+                public void onUidCachedChanged(int uid, boolean cached) throws RemoteException {
+                }
+            }, UID_OBSERVER_GONE | UID_OBSERVER_ACTIVE, 0, "system");
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to register uid observer", e);
+        }
+    }
+
+    private void handleUidGone(int uid) {
+        updateActiveState(uid, false /* active */);
+        int key;
+        synchronized (this) {
+
+            // In case we have a pending repin, repin now. See mPendingRepin for more information.
+            key = mPendingRepin.getOrDefault(uid, -1);
+            if (key == -1) {
+                return;
+            }
+            mPendingRepin.remove(uid);
+        }
+        pinApp(key, ActivityManager.getCurrentUser(), false /* force */);
+    }
+
+    private void handleUidActive(int uid) {
+        updateActiveState(uid, true /* active */);
+    }
+
+    private void updateActiveState(int uid, boolean active) {
+        synchronized (this) {
+            for (int i = mPinnedApps.size() - 1; i >= 0; i--) {
+                PinnedApp app = mPinnedApps.valueAt(i);
+                if (app.uid == uid) {
+                    app.active = active;
+                }
             }
         }
     }
 
-    private void unpinCameraApp() {
-        ArrayList<PinnedFile> pinnedCameraFiles;
+    private void unpinApp(@AppKey int key) {
+        ArrayList<PinnedFile> pinnedAppFiles;
         synchronized (this) {
-            pinnedCameraFiles = new ArrayList<>(mPinnedCameraFiles);
-            mPinnedCameraFiles.clear();
+            PinnedApp app = mPinnedApps.get(key);
+            if (app == null) {
+                return;
+            }
+            mPinnedApps.remove(key);
+            pinnedAppFiles = new ArrayList<>(app.mFiles);
         }
-        for (PinnedFile pinnedFile : pinnedCameraFiles) {
+        for (PinnedFile pinnedFile : pinnedAppFiles) {
             pinnedFile.close();
         }
     }
@@ -202,68 +354,216 @@
     }
 
     private ApplicationInfo getCameraInfo(int userHandle) {
-        //  find the camera via an intent
-        //  use INTENT_ACTION_STILL_IMAGE_CAMERA instead of _SECURE.  On a
-        //  device without a fbe enabled, the _SECURE intent will never get set.
         Intent cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
-        PackageManager pm = mContext.getPackageManager();
-        ResolveInfo cameraResolveInfo = pm.resolveActivityAsUser(cameraIntent,
-                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE
-                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                userHandle);
-        if (cameraResolveInfo == null ) {
-            //this is not necessarily an error
-            if (DEBUG) {
-              Slog.v(TAG, "Unable to resolve camera intent");
-            }
+        ApplicationInfo info = getApplicationInfoForIntent(cameraIntent, userHandle,
+            false /* defaultToSystemApp */);
+
+        // If the STILL_IMAGE_CAMERA intent doesn't resolve, try the _SECURE intent.
+        // We don't use _SECURE first because it will never get set on a device
+        // without File-based Encryption. But if the user has only set the intent
+        // before unlocking their device, we may still be able to identify their
+        // preference using this intent.
+        if (info == null) {
+            cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
+            info = getApplicationInfoForIntent(cameraIntent, userHandle,
+                false /* defaultToSystemApp */);
+        }
+
+        // If the _SECURE intent doesn't resolve, try the original intent but request
+        // the system app for camera if there was more than one result.
+        if (info == null) {
+            cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+            info = getApplicationInfoForIntent(cameraIntent, userHandle,
+                true /* defaultToSystemApp */);
+        }
+        return info;
+    }
+
+    private ApplicationInfo getHomeInfo(int userHandle) {
+        Intent intent = mAmInternal.getHomeIntent();
+        return getApplicationInfoForIntent(intent, userHandle, false);
+    }
+
+    private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle,
+            boolean defaultToSystemApp) {
+        if (intent == null) {
             return null;
         }
 
-        if (isResolverActivity(cameraResolveInfo.activityInfo))
-        {
-            if (DEBUG) {
-              Slog.v(TAG, "cameraIntent returned resolverActivity");
-            }
+        ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivityAsUser(intent,
+                MATCH_FLAGS, userHandle);
+
+        // If this intent can resolve to only one app, choose that one.
+        // Otherwise, if we've requested to default to the system app, return it;
+        // if we have not requested that default, return null if there's more than one option.
+        // If there's more than one system app, return null since we don't know which to pick.
+        if (resolveInfo == null) {
             return null;
         }
 
-        return cameraResolveInfo.activityInfo.applicationInfo;
+        if (!isResolverActivity(resolveInfo.activityInfo)) {
+            return resolveInfo.activityInfo.applicationInfo;
+        }
+
+        if (defaultToSystemApp) {
+            List<ResolveInfo> infoList = mContext.getPackageManager()
+                .queryIntentActivitiesAsUser(intent, MATCH_FLAGS, userHandle);
+            ApplicationInfo systemAppInfo = null;
+            for (ResolveInfo info : infoList) {
+                if ((info.activityInfo.applicationInfo.flags
+                      & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                    if (systemAppInfo == null) {
+                        systemAppInfo = info.activityInfo.applicationInfo;
+                    } else {
+                        // If there's more than one system app, return null due to ambiguity.
+                        return null;
+                    }
+                }
+            }
+            return systemAppInfo;
+        }
+
+        return null;
+    }
+
+    private void sendPinAppsMessage(int userHandle) {
+        mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::pinApps, this,
+                userHandle));
+    }
+
+    private void pinApps(int userHandle) {
+        for (int i = mPinKeys.size() - 1; i >= 0; i--) {
+            int key = mPinKeys.valueAt(i);
+            pinApp(key, userHandle, true /* force */);
+        }
     }
 
     /**
-     * If the camera app is already pinned, unpin and repin it.
+     * @see #pinApp(int, int, boolean)
      */
-    private boolean pinCamera(int userHandle){
-        ApplicationInfo cameraInfo = getCameraInfo(userHandle);
-        if (cameraInfo == null) {
-            return false;
+    private void sendPinAppMessage(int key, int userHandle, boolean force) {
+        mPinnerHandler.sendMessage(PooledLambda.obtainMessage(PinnerService::pinApp, this,
+                key, userHandle, force));
+    }
+
+    /**
+     * Pins an app of a specific type {@code key}.
+     *
+     * @param force If false, this will not repin the app if it's currently active. See
+     *              {@link #mPendingRepin}.
+     */
+    private void pinApp(int key, int userHandle, boolean force) {
+        int uid = getUidForKey(key);
+
+        // In case the app is currently active, don't repin until next process restart. See
+        // mPendingRepin for more information.
+        if (!force && uid != -1) {
+            synchronized (this) {
+                mPendingRepin.put(uid, key);
+            }
+            return;
+        }
+        unpinApp(key);
+        ApplicationInfo info = getInfoForKey(key, userHandle);
+        if (info != null) {
+            pinApp(key, info);
+        }
+    }
+
+    /**
+     * Checks whether the pinned package with {@code key} is active or not.
+
+     * @return The uid of the pinned app, or {@code -1} otherwise.
+     */
+    private int getUidForKey(@AppKey int key) {
+        synchronized (this) {
+            PinnedApp existing = mPinnedApps.get(key);
+            return existing != null && existing.active
+                    ? existing.uid
+                    : -1;
+        }
+    }
+
+    /**
+     * Retrieves the current application info for the given app type.
+     *
+     * @param key The app type to retrieve the info for.
+     * @param userHandle The user id of the current user.
+     */
+    private @Nullable ApplicationInfo getInfoForKey(@AppKey int key, int userHandle) {
+        switch (key) {
+            case KEY_CAMERA:
+                return getCameraInfo(userHandle);
+            case KEY_HOME:
+                return getHomeInfo(userHandle);
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * @return The app type name for {@code key}.
+     */
+    private String getNameForKey(@AppKey int key) {
+        switch (key) {
+            case KEY_CAMERA:
+                return "Camera";
+            case KEY_HOME:
+                return "Home";
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * @return The maximum amount of bytes to be pinned for an app of type {@code key}.
+     */
+    private int getSizeLimitForKey(@AppKey int key) {
+        switch (key) {
+            case KEY_CAMERA:
+                return MAX_CAMERA_PIN_SIZE;
+            case KEY_HOME:
+                return MAX_HOME_PIN_SIZE;
+            default:
+                return 0;
+        }
+    }
+
+    /**
+     * Pins an application.
+     *
+     * @param key The key of the app to pin.
+     * @param appInfo The corresponding app info.
+     */
+    private void pinApp(@AppKey int key, @Nullable ApplicationInfo appInfo) {
+        if (appInfo == null) {
+            return;
         }
 
-        //unpin after checking that the camera intent has resolved
-        //this prevents us from thrashing when switching users with
-        //FBE enabled, because the intent won't resolve until the unlock
-        unpinCameraApp();
+        PinnedApp pinnedApp = new PinnedApp(appInfo);
+        synchronized (this) {
+            mPinnedApps.put(key, pinnedApp);
+        }
 
-        //pin APK
-        String camAPK = cameraInfo.sourceDir;
-        PinnedFile pf = pinFile(camAPK,
-                                MAX_CAMERA_PIN_SIZE,
-                                /*attemptPinIntrospection=*/true);
+        // pin APK
+        int pinSizeLimit = getSizeLimitForKey(key);
+        String apk = appInfo.sourceDir;
+        PinnedFile pf = pinFile(apk, pinSizeLimit, /*attemptPinIntrospection=*/true);
         if (pf == null) {
-            Slog.e(TAG, "Failed to pin " + camAPK);
-            return false;
+            Slog.e(TAG, "Failed to pin " + apk);
+            return;
         }
         if (DEBUG) {
             Slog.i(TAG, "Pinned " + pf.fileName);
         }
         synchronized (this) {
-            mPinnedCameraFiles.add(pf);
+            pinnedApp.mFiles.add(pf);
         }
 
         // determine the ABI from either ApplicationInfo or Build
         String arch = "arm";
-        if (cameraInfo.primaryCpuAbi != null) {
-            if (VMRuntime.is64BitAbi(cameraInfo.primaryCpuAbi)) {
+        if (appInfo.primaryCpuAbi != null) {
+            if (VMRuntime.is64BitAbi(appInfo.primaryCpuAbi)) {
                 arch = arch + "64";
             }
         } else {
@@ -273,32 +573,29 @@
         }
 
         // get the path to the odex or oat file
-        String baseCodePath = cameraInfo.getBaseCodePath();
+        String baseCodePath = appInfo.getBaseCodePath();
         String[] files = null;
         try {
             files = DexFile.getDexFileOutputPaths(baseCodePath, arch);
         } catch (IOException ioe) {}
         if (files == null) {
-            return true;
+            return;
         }
 
         //not pinning the oat/odex is not a fatal error
         for (String file : files) {
-            pf = pinFile(file, MAX_CAMERA_PIN_SIZE, /*attemptPinIntrospection=*/false);
+            pf = pinFile(file, pinSizeLimit, /*attemptPinIntrospection=*/false);
             if (pf != null) {
                 synchronized (this) {
-                    mPinnedCameraFiles.add(pf);
+                    pinnedApp.mFiles.add(pf);
                 }
                 if (DEBUG) {
                     Slog.i(TAG, "Pinned " + pf.fileName);
                 }
             }
         }
-
-        return true;
     }
 
-
     /** mlock length bytes of fileToPin in memory
      *
      * If attemptPinIntrospection is true, then treat the file to pin as a zip file and
@@ -581,24 +878,38 @@
         }
     }
 
-    private synchronized ArrayList<PinnedFile> snapshotPinnedFiles() {
-        int nrPinnedFiles = mPinnedFiles.size() + mPinnedCameraFiles.size();
-        ArrayList<PinnedFile> pinnedFiles = new ArrayList<>(nrPinnedFiles);
-        pinnedFiles.addAll(mPinnedFiles);
-        pinnedFiles.addAll(mPinnedCameraFiles);
-        return pinnedFiles;
-    }
-
     private final class BinderService extends Binder {
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
-            long totalSize = 0;
-            for (PinnedFile pinnedFile : snapshotPinnedFiles()) {
-                pw.format("%s %s\n", pinnedFile.fileName, pinnedFile.bytesPinned);
-                totalSize += pinnedFile.bytesPinned;
+            synchronized (PinnerService.this) {
+                long totalSize = 0;
+                for (PinnedFile pinnedFile : mPinnedFiles) {
+                    pw.format("%s %s\n", pinnedFile.fileName, pinnedFile.bytesPinned);
+                    totalSize += pinnedFile.bytesPinned;
+                }
+                pw.println();
+                for (int key : mPinnedApps.keySet()) {
+                    PinnedApp app = mPinnedApps.get(key);
+                    pw.print(getNameForKey(key));
+                    pw.print(" uid="); pw.print(app.uid);
+                    pw.print(" active="); pw.print(app.active);
+                    pw.println();
+                    for (PinnedFile pf : mPinnedApps.get(key).mFiles) {
+                        pw.print("  "); pw.format("%s %s\n", pf.fileName, pf.bytesPinned);
+                        totalSize += pf.bytesPinned;
+                    }
+                }
+                pw.format("Total size: %s\n", totalSize);
+                pw.println();
+                if (!mPendingRepin.isEmpty()) {
+                    pw.print("Pending repin: ");
+                    for (int key : mPendingRepin.values()) {
+                        pw.print(getNameForKey(key)); pw.print(' ');
+                    }
+                    pw.println();
+                }
             }
-            pw.format("Total size: %s\n", totalSize);
         }
     }
 
@@ -634,8 +945,30 @@
         int length;
     }
 
+    /**
+     * Represents an app that was pinned.
+     */
+    private final class PinnedApp {
+
+        /**
+         * The uid of the package being pinned. This stays constant while the package stays
+         * installed.
+         */
+        final int uid;
+
+        /** Whether it is currently active, i.e. there is a running process from that package. */
+        boolean active;
+
+        /** List of pinned files. */
+        final ArrayList<PinnedFile> mFiles = new ArrayList<>();
+
+        private PinnedApp(ApplicationInfo appInfo) {
+            uid = appInfo.uid;
+            active = mAmInternal.isUidActive(uid);
+        }
+    }
+
     final class PinnerHandler extends Handler {
-        static final int PIN_CAMERA_MSG  = 4000;
         static final int PIN_ONSTART_MSG = 4001;
 
         public PinnerHandler(Looper looper) {
@@ -645,13 +978,6 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-
-                case PIN_CAMERA_MSG:
-                {
-                    handlePinCamera(msg.arg1);
-                }
-                break;
-
                 case PIN_ONSTART_MSG:
                 {
                     handlePinOnStart();
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 92005d2..1746b85 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -24,12 +24,14 @@
 import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
 import static android.os.storage.OnObbStateChangeListener.MOUNTED;
 import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
+
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
 import static com.android.internal.util.XmlUtils.readStringAttribute;
 import static com.android.internal.util.XmlUtils.writeIntAttribute;
 import static com.android.internal.util.XmlUtils.writeLongAttribute;
 import static com.android.internal.util.XmlUtils.writeStringAttribute;
+
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
@@ -47,8 +49,10 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ProviderInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
@@ -77,10 +81,12 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.UserManagerInternal;
 import android.os.storage.DiskInfo;
 import android.os.storage.IObbActionListener;
 import android.os.storage.IStorageEventListener;
@@ -97,15 +103,18 @@
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.DataUnit;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.TimeUtils;
 import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IMediaContainerService;
 import com.android.internal.os.AppFuseMount;
 import com.android.internal.os.BackgroundThread;
@@ -119,11 +128,13 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.server.pm.PackageManagerService;
 import com.android.server.storage.AppFuseBridge;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
 
+import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -153,14 +164,13 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
 
-import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
-
 /**
  * Service responsible for various storage media. Connects to {@code vold} to
  * watch for and manage dynamically added storage, such as SD cards and USB mass
@@ -174,7 +184,12 @@
 
     /* Read during boot to decide whether to enable zram when available */
     private static final String ZRAM_ENABLED_PROPERTY =
-        "persist.sys.zram_enabled";
+            "persist.sys.zram_enabled";
+
+    private static final boolean ENABLE_ISOLATED_STORAGE = SystemProperties
+            .getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false);
+
+    private static final String SHARED_SANDBOX_ID_PREFIX = "shared:";
 
     public static class Lifecycle extends SystemService {
         private StorageManagerService mStorageManagerService;
@@ -267,6 +282,18 @@
      */
     private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
 
+    /**
+     * Similar to {@link #mLock}, never hold this lock while performing downcalls into vold.
+     * Also, never hold this while calling into PackageManagerService since it is used in callbacks
+     * from PackageManagerService.
+     *
+     * If both {@link #mLock} and this lock need to be held, {@link #mLock} should be acquired
+     * before this.
+     *
+     * Use -PL suffix for methods that need to called with this lock held.
+     */
+    private final Object mPackagesLock = new Object();
+
     /** Set of users that we know are unlocked. */
     @GuardedBy("mLock")
     private int[] mLocalUnlockedUsers = EmptyArray.INT;
@@ -296,6 +323,15 @@
     @GuardedBy("mLock")
     private String mMoveTargetUuid;
 
+    @GuardedBy("mPackagesLock")
+    private final SparseArray<ArraySet<String>> mPackages = new SparseArray<>();
+
+    @GuardedBy("mPackagesLock")
+    private final ArrayMap<String, Integer> mAppIds = new ArrayMap<>();
+
+    @GuardedBy("mPackagesLock")
+    private final SparseArray<String> mSandboxIds = new SparseArray<>();
+
     private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
 
     /** Holding lock for AppFuse business */
@@ -416,7 +452,8 @@
     private volatile boolean mDaemonConnected = false;
     private volatile boolean mSecureKeyguardShowing = true;
 
-    private PackageManagerService mPms;
+    private PackageManagerInternal mPmInternal;
+    private UserManagerInternal mUmInternal;
 
     private final Callbacks mCallbacks;
     private final LockPatternUtils mLockPatternUtils;
@@ -791,8 +828,8 @@
                 // System user does not have media provider, so skip.
                 if (user.isSystemOnly()) continue;
 
-                final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
-                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                final ProviderInfo provider = mPmInternal.resolveContentProvider(
+                        MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                         user.id);
                 if (provider != null) {
@@ -868,12 +905,13 @@
             try {
                 mVold.reset();
 
+                pushPackagesInfo();
                 // Tell vold about all existing and started users
                 for (UserInfo user : users) {
                     mVold.onUserAdded(user.id, user.serialNumber);
                 }
                 for (int userId : systemUnlockedUsers) {
-                    mVold.onUserStarted(userId);
+                    mVold.onUserStarted(userId, getPackagesArrayForUser(userId));
                     mStoraged.onUserStarted(userId);
                 }
                 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
@@ -890,7 +928,7 @@
         // staging area is ready so it's ready for zygote-forked apps to
         // bind mount against.
         try {
-            mVold.onUserStarted(userId);
+            mVold.onUserStarted(userId, getPackagesArrayForUser(userId));
             mStoraged.onUserStarted(userId);
         } catch (Exception e) {
             Slog.wtf(TAG, e);
@@ -1146,7 +1184,7 @@
 
     @GuardedBy("mLock")
     private void onVolumeCreatedLocked(VolumeInfo vol) {
-        if (mPms.isOnlyCoreApps()) {
+        if (mPmInternal.isOnlyCoreApps()) {
             Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
             return;
         }
@@ -1394,8 +1432,8 @@
         mCallbacks = new Callbacks(FgThread.get().getLooper());
         mLockPatternUtils = new LockPatternUtils(mContext);
 
-        // XXX: This will go away soon in favor of IMountServiceObserver
-        mPms = (PackageManagerService) ServiceManager.getService("package");
+        mPmInternal = LocalServices.getService(PackageManagerInternal.class);
+        mUmInternal = LocalServices.getService(UserManagerInternal.class);
 
         HandlerThread hthread = new HandlerThread(TAG);
         hthread.start();
@@ -1445,9 +1483,96 @@
     }
 
     private void start() {
+        collectPackagesInfo();
         connect();
     }
 
+    @VisibleForTesting
+    void collectPackagesInfo() {
+        if (!ENABLE_ISOLATED_STORAGE) return;
+
+        resetPackageData();
+        final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
+        final int[] userIds = mUmInternal.getUserIds();
+        for (int userId : userIds) {
+            final List<ApplicationInfo> appInfos
+                    = mContext.getPackageManager().getInstalledApplicationsAsUser(
+                            PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+            synchronized (mPackagesLock) {
+                final ArraySet<String> userPackages = getPackagesForUserPL(userId);
+                for (int i = appInfos.size() - 1; i >= 0; --i) {
+                    if (appInfos.get(i).isInstantApp()) {
+                        continue;
+                    }
+                    final String packageName = appInfos.get(i).packageName;
+                    userPackages.add(packageName);
+
+                    final int appId = UserHandle.getAppId(appInfos.get(i).uid);
+                    mAppIds.put(packageName, appId);
+                    mSandboxIds.put(appId, getSandboxId(packageName, sharedUserIds.get(appId)));
+                }
+            }
+        }
+    }
+
+    private void resetPackageData() {
+        synchronized (mPackagesLock) {
+            mPackages.clear();
+            mAppIds.clear();
+            mSandboxIds.clear();
+        }
+    }
+
+    private static String getSandboxId(String packageName, String sharedUserId) {
+        return sharedUserId == null ? packageName : SHARED_SANDBOX_ID_PREFIX + sharedUserId;
+    }
+    private void pushPackagesInfo() throws RemoteException {
+        if (!ENABLE_ISOLATED_STORAGE) return;
+
+        // Arrays to fill up from {@link #mAppIds}
+        final String[] allPackageNames;
+        final int[] appIdsForPackages;
+
+        // Arrays to fill up from {@link #mSandboxIds}
+        final int[] allAppIds;
+        final String[] sandboxIdsForApps;
+        synchronized (mPackagesLock) {
+            allPackageNames = new String[mAppIds.size()];
+            appIdsForPackages = new int[mAppIds.size()];
+            for (int i = mAppIds.size() - 1; i >= 0; --i) {
+                allPackageNames[i] = mAppIds.keyAt(i);
+                appIdsForPackages[i] = mAppIds.valueAt(i);
+            }
+
+            allAppIds = new int[mSandboxIds.size()];
+            sandboxIdsForApps = new String[mSandboxIds.size()];
+            for (int i = mSandboxIds.size() - 1; i >= 0; --i) {
+                allAppIds[i] = mSandboxIds.keyAt(i);
+                sandboxIdsForApps[i] = mSandboxIds.valueAt(i);
+            }
+        }
+        mVold.addAppIds(allPackageNames, appIdsForPackages);
+        mVold.addSandboxIds(allAppIds, sandboxIdsForApps);
+    }
+
+    @GuardedBy("mPackagesLock")
+    private ArraySet<String> getPackagesForUserPL(int userId) {
+        ArraySet<String> userPackages = mPackages.get(userId);
+        if (userPackages == null) {
+            userPackages = new ArraySet<>();
+            mPackages.put(userId, userPackages);
+        }
+        return userPackages;
+    }
+
+    private String[] getPackagesArrayForUser(int userId) {
+        if (!ENABLE_ISOLATED_STORAGE) return EmptyArray.STRING;
+
+        synchronized (mPackagesLock) {
+            return getPackagesForUserPL(userId).toArray(new String[0]);
+        }
+    }
+
     private void connect() {
         IBinder binder = ServiceManager.getService("storaged");
         if (binder != null) {
@@ -2142,7 +2267,7 @@
             return false;
         }
 
-        final int packageUid = mPms.getPackageUid(packageName,
+        final int packageUid = mPmInternal.getPackageUid(packageName,
                 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
 
         if (DEBUG_OBB) {
@@ -2256,6 +2381,9 @@
                 }
             }, DateUtils.SECOND_IN_MILLIS);
             return 0;
+        } catch (ServiceSpecificException e) {
+            Slog.e(TAG, "fdeCheckPassword failed", e);
+            return e.errorCode;
         } catch (Exception e) {
             Slog.wtf(TAG, e);
             return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
@@ -2963,7 +3091,7 @@
                 bytes += storage.getStorageLowBytes(path);
             }
 
-            mPms.freeStorage(volumeUuid, bytes, flags);
+            mPmInternal.freeStorage(volumeUuid, bytes, flags);
         } catch (IOException e) {
             throw new ParcelableException(e);
         } finally {
@@ -2971,6 +3099,72 @@
         }
     }
 
+    private static final Pattern PATTERN_TRANSLATE = Pattern.compile(
+            "(?i)^(/storage/[^/]+/(?:[0-9]+/)?)(.*)");
+
+    @Override
+    public String translateAppToSystem(String path, String packageName, int userId) {
+        return translateInternal(path, packageName, userId, true);
+    }
+
+    @Override
+    public String translateSystemToApp(String path, String packageName, int userId) {
+        return translateInternal(path, packageName, userId, false);
+    }
+
+    private String translateInternal(String path, String packageName, int userId,
+            boolean toSystem) {
+        if (!ENABLE_ISOLATED_STORAGE) return path;
+
+        if (path.contains("/../")) {
+            throw new SecurityException("Shady looking path " + path);
+        }
+
+        final int uid = mPmInternal.getPackageUid(packageName,
+                PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+        final String sandboxId;
+        synchronized (mPackagesLock) {
+            sandboxId = mSandboxIds.get(UserHandle.getAppId(uid));
+        }
+        if (uid < 0 || sandboxId == null) {
+            throw new IllegalArgumentException("Unknown package " + packageName);
+        }
+
+        final Matcher m = PATTERN_TRANSLATE.matcher(path);
+        if (m.matches()) {
+            final String device = m.group(1);
+            final String devicePath = m.group(2);
+
+            // Does path belong to any packages belonging to this UID? If so,
+            // they get to go straight through to legacy paths.
+            final String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
+            for (String pkg : pkgs) {
+                if (devicePath.startsWith("Android/data/" + pkg + "/") ||
+                        devicePath.startsWith("Android/media/" + pkg + "/") ||
+                        devicePath.startsWith("Android/obb/" + pkg + "/")) {
+                    return path;
+                }
+            }
+
+            if (toSystem) {
+                // Everything else goes into sandbox.
+                return device + "Android/sandbox/" + sandboxId.replace(':', '/') + "/" + devicePath;
+            } else {
+                // Does path belong to this sandbox? If so, leave sandbox.
+                final String sandboxPrefix = "Android/sandbox/" + sandboxId.replace(':', '/') + "/";
+                if (devicePath.startsWith(sandboxPrefix)) {
+                    return device + devicePath.substring(sandboxPrefix.length());
+                }
+
+                // Path isn't valid inside sandbox!
+                throw new SecurityException(
+                        "Path " + path + " isn't valid inside sandbox " + sandboxId);
+            }
+        }
+
+        return path;
+    }
+
     private void addObbStateLocked(ObbState obbState) throws RemoteException {
         final IBinder binder = obbState.getBinder();
         List<ObbState> obbStates = mObbMounts.get(binder);
@@ -3635,6 +3829,8 @@
 
         @Override
         public void onExternalStoragePolicyChanged(int uid, String packageName) {
+            // No runtime storage permissions in isolated storage world, so nothing to do here.
+            if (ENABLE_ISOLATED_STORAGE) return;
             final int mountMode = getExternalStorageMountMode(uid, packageName);
             remountUidExternalStorage(uid, mountMode);
         }
@@ -3671,5 +3867,29 @@
             }
             return true;
         }
+
+        @Override
+        public void mountExternalStorageForApp(String packageName, int appId, String sharedUserId,
+                int userId) {
+            final String sandboxId;
+            synchronized (mPackagesLock) {
+                final ArraySet<String> userPackages = getPackagesForUserPL(userId);
+                // If userPackages is empty, it means the user is not started yet, so no need to
+                // do anything now.
+                if (userPackages.isEmpty() || userPackages.contains(packageName)) {
+                    return;
+                }
+                userPackages.add(packageName);
+                mAppIds.put(packageName, appId);
+                sandboxId = getSandboxId(packageName, sharedUserId);
+                mSandboxIds.put(appId, sandboxId);
+            }
+
+            try {
+                mVold.mountExternalStorageForApp(packageName, appId, sandboxId, userId);
+            } catch (Exception e) {
+                Slog.wtf(TAG, e);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 63584d9..c5b4966 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -18,10 +18,12 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.os.Environment;
 import android.os.SystemClock;
 import android.os.Trace;
 import android.util.Slog;
 
+import java.io.File;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
@@ -36,6 +38,7 @@
     private static final String TAG = "SystemServiceManager";
     private static final int SERVICE_CALL_WARN_TIME_MS = 50;
 
+    private static File sSystemDir;
     private final Context mContext;
     private boolean mSafeMode;
     private boolean mRuntimeRestarted;
@@ -318,6 +321,22 @@
     }
 
     /**
+     * Ensures that the system directory exist creating one if needed.
+     * @deprecated Use {@link Environment#getDataSystemCeDirectory()}
+     * or {@link Environment#getDataSystemDeDirectory()} instead.
+     * @return The system directory.
+     */
+    @Deprecated
+    public static File ensureSystemDir() {
+        if (sSystemDir == null) {
+            File dataDir = Environment.getDataDirectory();
+            sSystemDir = new File(dataDir, "system");
+            sSystemDir.mkdirs();
+        }
+        return sSystemDir;
+    }
+
+    /**
      * Outputs the state of this manager to the System log.
      */
     public void dump() {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index ad9fa40..566ce4f 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -36,6 +36,7 @@
 import android.telephony.CellLocation;
 import android.telephony.DisconnectCause;
 import android.telephony.LocationAccessPolicy;
+import android.telephony.PhoneCapability;
 import android.telephony.PhoneStateListener;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
@@ -47,7 +48,6 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.VoLteServiceState;
-import android.text.TextUtils;
 import android.util.LocalLog;
 
 import com.android.internal.app.IBatteryStats;
@@ -200,6 +200,8 @@
 
     private boolean mCarrierNetworkChangeState = false;
 
+    private PhoneCapability mPhoneCapability = null;
+
     private final LocalLog mLocalLog = new LocalLog(100);
 
     private PreciseDataConnectionState mPreciseDataConnectionState =
@@ -658,6 +660,13 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) {
+                        try {
+                            r.callback.onPhoneCapabilityChanged(mPhoneCapability);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                 }
             }
         } else {
@@ -1453,6 +1462,33 @@
         }
     }
 
+    public void notifyPhoneCapabilityChanged(PhoneCapability capability) {
+        if (!checkNotifyPermission("notifyPhoneCapabilityChanged()")) {
+            return;
+        }
+
+        if (VDBG) {
+            log("notifyPhoneCapabilityChanged: capability=" + capability);
+        }
+
+        synchronized (mRecords) {
+            mPhoneCapability = capability;
+
+            for (Record r : mRecords) {
+                if (r.matchPhoneStateListenerEvent(
+                        PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE)) {
+                    try {
+                        r.callback.onPhoneCapabilityChanged(capability);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -1488,6 +1524,7 @@
             pw.println("mForegroundCallState=" + mForegroundCallState);
             pw.println("mBackgroundCallState=" + mBackgroundCallState);
             pw.println("mVoLteServiceState=" + mVoLteServiceState);
+            pw.println("mPhoneCapability=" + mPhoneCapability);
 
             pw.decreaseIndent();
 
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index c043e18..40f81b3 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -342,6 +342,7 @@
         mMonitor.register(context, null, UserHandle.ALL, true);
     }
 
+    @GuardedBy("mLock")
     private void initializeInternalStateLocked(@UserIdInt int userId) {
         // When DISABLE_PER_PROFILE_SPELL_CHECKER is true, we make sure here that work profile users
         // will never have non-null TextServicesData for their user ID.
@@ -756,6 +757,7 @@
      * @return {@link TextServicesData} for the given user.  {@code null} if spell checker is not
      *         temporarily / permanently available for the specified user
      */
+    @GuardedBy("mLock")
     @Nullable
     private TextServicesData getDataFromCallingUserIdLocked(@UserIdInt int callingUserId) {
         final int spellCheckerOwnerUserId = mSpellCheckerOwnerUserIdMap.get(callingUserId);
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index c29fc7f..cb03255 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -82,6 +82,7 @@
 
     private boolean mCarModeEnabled = false;
     private boolean mCharging = false;
+    private boolean mPowerSave = false;
     private int mDefaultUiModeType;
     private boolean mCarModeKeepsScreenOn;
     private boolean mDeskModeKeepsScreenOn;
@@ -160,7 +161,14 @@
     private final BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            mCharging = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
+            switch (intent.getAction()) {
+                case Intent.ACTION_BATTERY_CHANGED:
+                    mCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
+                    break;
+                case PowerManager.ACTION_POWER_SAVE_MODE_CHANGING:
+                    mPowerSave = intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false);
+                    break;
+            }
             synchronized (mLock) {
                 if (mSystemReady) {
                     updateLocked(0, 0);
@@ -203,8 +211,9 @@
 
         context.registerReceiver(mDockModeReceiver,
                 new IntentFilter(Intent.ACTION_DOCK_EVENT));
-        context.registerReceiver(mBatteryReceiver,
-                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+        IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+        batteryFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
+        context.registerReceiver(mBatteryReceiver, batteryFilter);
 
         mConfiguration.setToDefaults();
 
@@ -457,6 +466,11 @@
             uiMode |= mNightMode << 4;
         }
 
+        if (mPowerSave && !mNightModeLocked) {
+            uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
+            uiMode |= Configuration.UI_MODE_NIGHT_YES;
+        }
+
         if (LOG) {
             Slog.d(TAG,
                 "updateConfigurationLocked: mDockState=" + mDockState
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 95e5518..ae3946a 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -66,6 +66,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Date;
 
 public class VibratorService extends IVibratorService.Stub
@@ -158,6 +159,7 @@
         public final int usageHint;
         public final int uid;
         public final String opPkg;
+        public final String reason;
 
         // The actual effect to be played.
         public VibrationEffect effect;
@@ -167,7 +169,7 @@
         public VibrationEffect originalEffect;
 
         private Vibration(IBinder token, VibrationEffect effect,
-                int usageHint, int uid, String opPkg) {
+                int usageHint, int uid, String opPkg, String reason) {
             this.token = token;
             this.effect = effect;
             this.startTime = SystemClock.elapsedRealtime();
@@ -175,6 +177,7 @@
             this.usageHint = usageHint;
             this.uid = uid;
             this.opPkg = opPkg;
+            this.reason = reason;
         }
 
         public void binderDied() {
@@ -233,7 +236,7 @@
 
         public VibrationInfo toInfo() {
             return new VibrationInfo(
-                    startTimeDebug, effect, originalEffect, usageHint, uid, opPkg);
+                    startTimeDebug, effect, originalEffect, usageHint, uid, opPkg, reason);
         }
     }
 
@@ -244,15 +247,18 @@
         private final int mUsageHint;
         private final int mUid;
         private final String mOpPkg;
+        private final String mReason;
 
         public VibrationInfo(long startTimeDebug, VibrationEffect effect,
-                VibrationEffect originalEffect, int usageHint, int uid, String opPkg) {
+                VibrationEffect originalEffect, int usageHint, int uid,
+                String opPkg, String reason) {
             mStartTimeDebug = startTimeDebug;
             mEffect = effect;
             mOriginalEffect = originalEffect;
             mUsageHint = usageHint;
             mUid = uid;
             mOpPkg = opPkg;
+            mReason = reason;
         }
 
         @Override
@@ -270,6 +276,8 @@
                     .append(mUid)
                     .append(", opPkg: ")
                     .append(mOpPkg)
+                    .append(", reason: ")
+                    .append(mReason)
                     .toString();
         }
     }
@@ -482,9 +490,9 @@
     }
 
     @Override // Binder call
-    public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint,
+    public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint, String reason,
             IBinder token) {
-        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate");
+        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason = " + reason);
         try {
             if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -531,10 +539,11 @@
                     return;
                 }
 
-                Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
+                Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg, reason);
                 linkVibration(vib);
                 long ident = Binder.clearCallingIdentity();
                 try {
+
                     doCancelVibrateLocked();
                     startVibrationLocked(vib);
                     addToPreviousVibrationsLocked(vib);
@@ -1001,8 +1010,8 @@
                 Slog.w(TAG, "Failed to play prebaked effect, no fallback");
                 return 0;
             }
-            Vibration fallbackVib =
-                    new Vibration(vib.token, effect, vib.usageHint, vib.uid, vib.opPkg);
+            Vibration fallbackVib = new Vibration(vib.token, effect, vib.usageHint, vib.uid,
+                    vib.opPkg, vib.reason + " (fallback)");
             final int intensity = getCurrentIntensityLocked(fallbackVib);
             linkVibration(fallbackVib);
             applyVibrationIntensityScalingLocked(fallbackVib, intensity);
@@ -1292,7 +1301,7 @@
                 VibrationEffect effect =
                         VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE);
                 vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN,
-                        mToken);
+                        "Shell Command", mToken);
                 return 0;
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 59093c1..713da30 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -21,6 +21,7 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.system.ErrnoException;
+import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructRlimit;
 import com.android.internal.os.ZygoteConnectionConstants;
@@ -47,6 +48,10 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -95,6 +100,7 @@
         "android.hardware.audio@4.0::IDevicesFactory",
         "android.hardware.bluetooth@1.0::IBluetoothHci",
         "android.hardware.camera.provider@2.4::ICameraProvider",
+        "android.hardware.graphics.allocator@2.0::IAllocator",
         "android.hardware.graphics.composer@2.1::IComposer",
         "android.hardware.media.omx@1.0::IOmx",
         "android.hardware.media.omx@1.0::IOmxStore",
@@ -621,23 +627,38 @@
             mFdHighWaterMark = fdThreshold;
         }
 
+        /**
+         * Dumps open file descriptors and their full paths to a temporary file in {@code mDumpDir}.
+         */
         private void dumpOpenDescriptors() {
+            // We cannot exec lsof to get more info about open file descriptors because a newly
+            // forked process will not have the permissions to readlink. Instead list all open
+            // descriptors from /proc/pid/fd and resolve them.
+            List<String> dumpInfo = new ArrayList<>();
+            String fdDirPath = String.format("/proc/%d/fd/", Process.myPid());
+            File[] fds = new File(fdDirPath).listFiles();
+            if (fds == null) {
+                dumpInfo.add("Unable to list " + fdDirPath);
+            } else {
+                for (File f : fds) {
+                    String fdSymLink = f.getAbsolutePath();
+                    String resolvedPath = "";
+                    try {
+                        resolvedPath = Os.readlink(fdSymLink);
+                    } catch (ErrnoException ex) {
+                        resolvedPath = ex.getMessage();
+                    }
+                    dumpInfo.add(fdSymLink + "\t" + resolvedPath);
+                }
+            }
+
+            // Dump the fds & paths to a temp file.
             try {
                 File dumpFile = File.createTempFile("anr_fd_", "", mDumpDir);
-                java.lang.Process proc = new ProcessBuilder()
-                    .command("/system/bin/lsof", "-p", String.valueOf(Process.myPid()))
-                    .redirectErrorStream(true)
-                    .redirectOutput(dumpFile)
-                    .start();
-
-                int returnCode = proc.waitFor();
-                if (returnCode != 0) {
-                    Slog.w(TAG, "Unable to dump open descriptors, lsof return code: "
-                        + returnCode);
-                    dumpFile.delete();
-                }
-            } catch (IOException | InterruptedException ex) {
-                Slog.w(TAG, "Unable to dump open descriptors: " + ex);
+                Path out = Paths.get(dumpFile.getAbsolutePath());
+                Files.write(out, dumpInfo, StandardCharsets.UTF_8);
+            } catch (IOException ex) {
+                Slog.w(TAG, "Unable to write open descriptors to file: " + ex);
             }
         }
 
diff --git a/services/core/java/com/android/server/am/ActiveInstrumentation.java b/services/core/java/com/android/server/am/ActiveInstrumentation.java
index ff65951..8cd9d188 100644
--- a/services/core/java/com/android/server/am/ActiveInstrumentation.java
+++ b/services/core/java/com/android/server/am/ActiveInstrumentation.java
@@ -139,7 +139,9 @@
         proto.write(ActiveInstrumentationProto.WATCHER, mWatcher.toString());
         proto.write(ActiveInstrumentationProto.UI_AUTOMATION_CONNECTION,
                 mUiAutomationConnection.toString());
-        proto.write(ActiveInstrumentationProto.ARGUMENTS, mArguments.toString());
+        if (mArguments != null) {
+            mArguments.writeToProto(proto, ActiveInstrumentationProto.ARGUMENTS);
+        }
         proto.end(token);
     }
 }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index f7cd5ad..5bf6892 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -65,7 +65,6 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
-import com.android.server.am.ActivityManagerService.NeededUriGrants;
 
 import android.app.ActivityManager;
 import android.app.AppGlobals;
@@ -96,6 +95,7 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.webkit.WebViewZygote;
+import com.android.server.uri.NeededUriGrants;
 
 public final class ActiveServices {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM;
@@ -512,19 +512,18 @@
             fgRequired = false;
         }
 
-        NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
+        NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent(
                 callingUid, r.packageName, service, service.getFlags(), null, r.userId);
 
         // If permissions need a review before any of the app components can run,
         // we do not start the service and launch a review activity if the calling app
         // is in the foreground passing it a pending intent to start the service when
         // review is completed.
-        if (mAm.mPermissionReviewRequired) {
-            // XXX This is not dealing with fgRequired!
-            if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
-                    callingUid, service, callerFg, userId)) {
-                return null;
-            }
+
+        // XXX This is not dealing with fgRequired!
+        if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
+                callingUid, service, callerFg, userId)) {
+            return null;
         }
 
         if (unscheduleServiceRestartLocked(r, callingUid, false)) {
@@ -539,6 +538,11 @@
 
         if (fgRequired) {
             // We are now effectively running a foreground service.
+            ServiceState stracker = r.getTracker();
+            if (stracker != null) {
+                stracker.setForeground(true, mAm.mProcessStats.getMemFactorLocked(),
+                        r.lastActivity);
+            }
             mAm.mAppOpsService.startOperation(AppOpsManager.getToken(mAm.mAppOpsService),
                     AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, true);
         }
@@ -1190,13 +1194,14 @@
                         r.app.pid, r.appInfo.uid, "startForeground");
             }
             boolean alreadyStartedOp = false;
+            boolean stopProcStatsOp = false;
             if (r.fgRequired) {
                 if (DEBUG_SERVICE || DEBUG_BACKGROUND_CHECK) {
                     Slog.i(TAG, "Service called startForeground() as required: " + r);
                 }
                 r.fgRequired = false;
                 r.fgWaiting = false;
-                alreadyStartedOp = true;
+                alreadyStartedOp = stopProcStatsOp = true;
                 mAm.mHandler.removeMessages(
                         ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
             }
@@ -1264,6 +1269,15 @@
                             active.mNumActive++;
                         }
                         r.isForeground = true;
+                        if (!stopProcStatsOp) {
+                            ServiceState stracker = r.getTracker();
+                            if (stracker != null) {
+                                stracker.setForeground(true,
+                                        mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
+                            }
+                        } else {
+                            stopProcStatsOp = false;
+                        }
                         mAm.mAppOpsService.startOperation(
                                 AppOpsManager.getToken(mAm.mAppOpsService),
                                 AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
@@ -1285,6 +1299,15 @@
                     }
                 }
             } finally {
+                if (stopProcStatsOp) {
+                    // We got through to this point with it actively being started foreground,
+                    // and never decided we wanted to keep it like that, so drop it.
+                    ServiceState stracker = r.getTracker();
+                    if (stracker != null) {
+                        stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
+                                r.lastActivity);
+                    }
+                }
                 if (alreadyStartedOp) {
                     // If we had previously done a start op for direct foreground start,
                     // we have cleared the flag so can now drop it.
@@ -1300,6 +1323,11 @@
                     decActiveForegroundAppLocked(smap, r);
                 }
                 r.isForeground = false;
+                ServiceState stracker = r.getTracker();
+                if (stracker != null) {
+                    stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
+                            r.lastActivity);
+                }
                 mAm.mAppOpsService.finishOperation(
                         AppOpsManager.getToken(mAm.mAppOpsService),
                         AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
@@ -1506,75 +1534,73 @@
         // we schedule binding to the service but do not start its process, then
         // we launch a review activity to which is passed a callback to invoke
         // when done to start the bound service's process to completing the binding.
-        if (mAm.mPermissionReviewRequired) {
-            if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
-                    s.packageName, s.userId)) {
+        if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
+                s.packageName, s.userId)) {
 
-                permissionsReviewRequired = true;
+            permissionsReviewRequired = true;
 
-                // Show a permission review UI only for binding from a foreground app
-                if (!callerFg) {
-                    Slog.w(TAG, "u" + s.userId + " Binding to a service in package"
-                            + s.packageName + " requires a permissions review");
-                    return 0;
-                }
+            // Show a permission review UI only for binding from a foreground app
+            if (!callerFg) {
+                Slog.w(TAG, "u" + s.userId + " Binding to a service in package"
+                        + s.packageName + " requires a permissions review");
+                return 0;
+            }
 
-                final ServiceRecord serviceRecord = s;
-                final Intent serviceIntent = service;
+            final ServiceRecord serviceRecord = s;
+            final Intent serviceIntent = service;
 
-                RemoteCallback callback = new RemoteCallback(
-                        new RemoteCallback.OnResultListener() {
-                    @Override
-                    public void onResult(Bundle result) {
-                        synchronized(mAm) {
-                            final long identity = Binder.clearCallingIdentity();
-                            try {
-                                if (!mPendingServices.contains(serviceRecord)) {
-                                    return;
-                                }
-                                // If there is still a pending record, then the service
-                                // binding request is still valid, so hook them up. We
-                                // proceed only if the caller cleared the review requirement
-                                // otherwise we unbind because the user didn't approve.
-                                if (!mAm.getPackageManagerInternalLocked()
-                                        .isPermissionsReviewRequired(
-                                                serviceRecord.packageName,
-                                                serviceRecord.userId)) {
-                                    try {
-                                        bringUpServiceLocked(serviceRecord,
-                                                serviceIntent.getFlags(),
-                                                callerFg, false, false);
-                                    } catch (RemoteException e) {
-                                        /* ignore - local call */
-                                    }
-                                } else {
-                                    unbindServiceLocked(connection);
-                                }
-                            } finally {
-                                Binder.restoreCallingIdentity(identity);
+            RemoteCallback callback = new RemoteCallback(
+                    new RemoteCallback.OnResultListener() {
+                @Override
+                public void onResult(Bundle result) {
+                    synchronized(mAm) {
+                        final long identity = Binder.clearCallingIdentity();
+                        try {
+                            if (!mPendingServices.contains(serviceRecord)) {
+                                return;
                             }
+                            // If there is still a pending record, then the service
+                            // binding request is still valid, so hook them up. We
+                            // proceed only if the caller cleared the review requirement
+                            // otherwise we unbind because the user didn't approve.
+                            if (!mAm.getPackageManagerInternalLocked()
+                                    .isPermissionsReviewRequired(
+                                            serviceRecord.packageName,
+                                            serviceRecord.userId)) {
+                                try {
+                                    bringUpServiceLocked(serviceRecord,
+                                            serviceIntent.getFlags(),
+                                            callerFg, false, false);
+                                } catch (RemoteException e) {
+                                    /* ignore - local call */
+                                }
+                            } else {
+                                unbindServiceLocked(connection);
+                            }
+                        } finally {
+                            Binder.restoreCallingIdentity(identity);
                         }
                     }
-                });
-
-                final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
-                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-                intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
-                intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
-
-                if (DEBUG_PERMISSIONS_REVIEW) {
-                    Slog.i(TAG, "u" + s.userId + " Launching permission review for package "
-                            + s.packageName);
                 }
+            });
 
-                mAm.mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
-                    }
-                });
+            final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
+            intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
+
+            if (DEBUG_PERMISSIONS_REVIEW) {
+                Slog.i(TAG, "u" + s.userId + " Launching permission review for package "
+                        + s.packageName);
             }
+
+            mAm.mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
+                }
+            });
         }
 
         final long origId = Binder.clearCallingIdentity();
@@ -1598,7 +1624,7 @@
             }
 
             mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,
-                    s.appInfo.uid, s.name, s.processName);
+                    s.appInfo.uid, s.appInfo.longVersionCode, s.name, s.processName);
             // Once the apps have become associated, if one of them is caller is ephemeral
             // the target app should now be able to see the calling app
             mAm.grantEphemeralAccessLocked(callerApp.userId, service,
@@ -1606,7 +1632,8 @@
 
             AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
             ConnectionRecord c = new ConnectionRecord(b, activity,
-                    connection, flags, clientLabel, clientIntent);
+                    connection, flags, clientLabel, clientIntent,
+                    callerApp.uid, callerApp.processName);
 
             IBinder binder = connection.asBinder();
             ArrayList<ConnectionRecord> clist = s.connections.get(binder);
@@ -1623,6 +1650,7 @@
                 activity.connections.add(c);
             }
             b.client.connections.add(c);
+            c.startAssociationIfNeeded();
             if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                 b.client.hasAboveClient = true;
             }
@@ -2107,7 +2135,7 @@
     private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) {
         boolean canceled = false;
 
-        if (mAm.isShuttingDownLocked()) {
+        if (mAm.mAtmInternal.isShuttingDown()) {
             Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortName
                     + " - system is shutting down");
             return false;
@@ -2437,7 +2465,7 @@
         if (DEBUG_MU)
             Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
                     + ", ProcessRecord.uid = " + app.uid);
-        r.app = app;
+        r.setProcess(app);
         r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
 
         final boolean newService = app.services.add(r);
@@ -2479,7 +2507,7 @@
                 // Cleanup.
                 if (newService) {
                     app.services.remove(r);
-                    r.app = null;
+                    r.setProcess(null);
                 }
 
                 // Retry.
@@ -2550,7 +2578,7 @@
             r.deliveredStarts.add(si);
             si.deliveryCount++;
             if (si.neededGrants != null) {
-                mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
+                mAm.mUgmInternal.grantUriPermissionUncheckedFromIntent(si.neededGrants,
                         si.getUriPermissionsLocked());
             }
             mAm.grantEphemeralAccessLocked(r.userId, si.intent,
@@ -2663,6 +2691,7 @@
                 // There is still a connection to the service that is
                 // being brought down.  Mark it as dead.
                 cr.serviceDead = true;
+                cr.stopAssociation();
                 try {
                     cr.conn.connected(r.name, null, true);
                 } catch (Exception e) {
@@ -2703,6 +2732,11 @@
                     + r);
             r.fgRequired = false;
             r.fgWaiting = false;
+            ServiceState stracker = r.getTracker();
+            if (stracker != null) {
+                stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
+                        r.lastActivity);
+            }
             mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),
                     AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
             mAm.mHandler.removeMessages(
@@ -2755,6 +2789,11 @@
         cancelForegroundNotificationLocked(r);
         if (r.isForeground) {
             decActiveForegroundAppLocked(smap, r);
+            ServiceState stracker = r.getTracker();
+            if (stracker != null) {
+                stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
+                        r.lastActivity);
+            }
             mAm.mAppOpsService.finishOperation(
                     AppOpsManager.getToken(mAm.mAppOpsService),
                     AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
@@ -2835,6 +2874,7 @@
             }
         }
         b.connections.remove(c);
+        c.stopAssociation();
         if (c.activity != null && c.activity != skipAct) {
             if (c.activity.connections != null) {
                 c.activity.connections.remove(c);
@@ -2865,7 +2905,8 @@
             }
         }
 
-        mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid, s.name);
+        mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid,
+                s.appInfo.longVersionCode, s.name, s.processName);
 
         if (b.connections.size() == 0) {
             b.intent.apps.remove(b.client);
@@ -3056,7 +3097,7 @@
                         updateWhitelistManagerLocked(r.app);
                     }
                 }
-                r.app = null;
+                r.setProcess(null);
             }
         }
     }
@@ -3155,7 +3196,7 @@
                         }
                     }
                 }
-                service.app = null;
+                service.setProcess(null);
                 service.isolatedProc = null;
                 if (mTmpCollectionResults == null) {
                     mTmpCollectionResults = new ArrayList<>();
@@ -3305,7 +3346,7 @@
             if (sr.app != app && sr.app != null && !sr.app.isPersistent()) {
                 sr.app.services.remove(sr);
             }
-            sr.app = null;
+            sr.setProcess(null);
             sr.isolatedProc = null;
             sr.executeNesting = 0;
             sr.forceClearTracker();
@@ -3617,7 +3658,7 @@
             }
 
             app = r.app;
-            if (app != null && app.debugging) {
+            if (app != null && app.isDebugging()) {
                 // The app's being debugged; let it ride
                 return;
             }
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 9f9fe4c..73ffd5c 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -31,13 +32,18 @@
 import static android.view.Display.FLAG_PRIVATE;
 import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
 import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityDisplayProto.FOCUSED_STACK_ID;
 import static com.android.server.am.ActivityDisplayProto.ID;
+import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
 import static com.android.server.am.ActivityDisplayProto.STACKS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityStackSupervisor.TAG_STATES;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
 import android.app.WindowConfiguration;
@@ -141,7 +147,7 @@
                 + " to displayId=" + mDisplayId + " position=" + position);
         addStackReferenceIfNeeded(stack);
         positionChildAt(stack, position);
-        mSupervisor.mService.mAm.updateSleepIfNeededLocked();
+        mSupervisor.mService.updateSleepIfNeededLocked();
     }
 
     void removeChild(ActivityStack stack) {
@@ -149,26 +155,36 @@
                 + " from displayId=" + mDisplayId);
         mStacks.remove(stack);
         removeStackReferenceIfNeeded(stack);
-        mSupervisor.mService.mAm.updateSleepIfNeededLocked();
+        mSupervisor.mService.updateSleepIfNeededLocked();
         onStackOrderChanged();
     }
 
-    void positionChildAtTop(ActivityStack stack) {
-        positionChildAt(stack, mStacks.size());
+    void positionChildAtTop(ActivityStack stack, boolean includingParents) {
+        positionChildAt(stack, mStacks.size(), includingParents);
     }
 
     void positionChildAtBottom(ActivityStack stack) {
-        positionChildAt(stack, 0);
+        positionChildAt(stack, 0, false /* includingParents */);
     }
 
     private void positionChildAt(ActivityStack stack, int position) {
+        positionChildAt(stack, position, false /* includingParents */);
+    }
+
+    private void positionChildAt(ActivityStack stack, int position, boolean includingParents) {
         // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
         //       the position internally, also update the logic here
         mStacks.remove(stack);
         final int insertPosition = getTopInsertPosition(stack, position);
         mStacks.add(insertPosition, stack);
-        mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
-                insertPosition);
+        // Since positionChildAt() is called during the creation process of pinned stacks,
+        // ActivityStack#getWindowContainerController() can be null. In this special case,
+        // since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(),
+        // we don't have to call WindowContainerController#positionChildAt() here.
+        if (stack.getWindowContainerController() != null) {
+            mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
+                    insertPosition, includingParents);
+        }
         onStackOrderChanged();
     }
 
@@ -309,16 +325,6 @@
                     + windowingMode);
         }
 
-        if (windowingMode == WINDOWING_MODE_UNDEFINED) {
-            // TODO: Should be okay to have stacks with with undefined windowing mode long term, but
-            // have to set them to something for now due to logic that depending on them.
-            windowingMode = getWindowingMode(); // Put in current display's windowing mode
-            if (windowingMode == WINDOWING_MODE_UNDEFINED) {
-                // Else fullscreen for now...
-                windowingMode = WINDOWING_MODE_FULLSCREEN;
-            }
-        }
-
         final int stackId = getNextStackId();
         return createStackUnchecked(windowingMode, activityType, stackId, onTop);
     }
@@ -333,6 +339,101 @@
                         this, stackId, mSupervisor, windowingMode, activityType, onTop);
     }
 
+    ActivityStack getFocusedStack() {
+        for (int i = mStacks.size() - 1; i >= 0; --i) {
+            final ActivityStack stack = mStacks.get(i);
+            if (stack.isFocusable() && stack.shouldBeVisible(null /* starting */)) {
+                return stack;
+            }
+        }
+
+        return null;
+    }
+
+    ActivityStack getNextFocusableStack() {
+        return getNextFocusableStack(null /* currentFocus */, false /* ignoreCurrent */);
+    }
+
+    ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) {
+        final int currentWindowingMode = currentFocus != null
+                ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
+
+        ActivityStack candidate = null;
+        for (int i = mStacks.size() - 1; i >= 0; --i) {
+            final ActivityStack stack = mStacks.get(i);
+            if (ignoreCurrent && stack == currentFocus) {
+                continue;
+            }
+            if (!stack.isFocusable() || !stack.shouldBeVisible(null)) {
+                continue;
+            }
+
+            if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+                    && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
+                // If the currently focused stack is in split-screen secondary we save off the
+                // top primary split-screen stack as a candidate for focus because we might
+                // prefer focus to move to an other stack to avoid primary split-screen stack
+                // overlapping with a fullscreen stack when a fullscreen stack is higher in z
+                // than the next split-screen stack. Assistant stack, I am looking at you...
+                // We only move the focus to the primary-split screen stack if there isn't a
+                // better alternative.
+                candidate = stack;
+                continue;
+            }
+            if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
+                // Use the candidate stack since we are now at the secondary split-screen.
+                return candidate;
+            }
+            return stack;
+        }
+        return candidate;
+    }
+
+    ActivityRecord getResumedActivity() {
+        final ActivityStack focusedStack = getFocusedStack();
+        if (focusedStack == null) {
+            return null;
+        }
+        // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
+        // Check if the focused stack has the resumed activity
+        ActivityRecord resumedActivity = focusedStack.getResumedActivity();
+        if (resumedActivity == null || resumedActivity.app == null) {
+            // If there is no registered resumed activity in the stack or it is not running -
+            // try to use previously resumed one.
+            resumedActivity = focusedStack.mPausingActivity;
+            if (resumedActivity == null || resumedActivity.app == null) {
+                // If previously resumed activity doesn't work either - find the topmost running
+                // activity that can be focused.
+                resumedActivity = focusedStack.topRunningActivityLocked(true /* focusableOnly */);
+            }
+        }
+        return resumedActivity;
+    }
+
+    /**
+     * Pause all activities in either all of the stacks or just the back stacks.
+     * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
+     * @param resuming The resuming activity.
+     * @param dontWait The resuming activity isn't going to wait for all activities to be paused
+     *                 before resuming.
+     * @return true if any activity was paused as a result of this call.
+     */
+    boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
+        boolean someActivityPaused = false;
+        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = mStacks.get(stackNdx);
+            // TODO(b/111541062): Check if resumed activity on this display instead
+            if (!mSupervisor.isTopDisplayFocusedStack(stack)
+                    && stack.getResumedActivity() != null) {
+                if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
+                        " mResumedActivity=" + stack.getResumedActivity());
+                someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
+                        dontWait);
+            }
+        }
+        return someActivityPaused;
+    }
+
     /**
      * Removes stacks in the input windowing modes from the system if they are of activity type
      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
@@ -383,11 +484,16 @@
         final int windowingMode = stack.getWindowingMode();
 
         if (activityType == ACTIVITY_TYPE_HOME) {
+            // TODO(b/111363427) Rollback to throws exceptions once we figure out how to properly
+            // deal with home type stack when external display removed
             if (mHomeStack != null && mHomeStack != stack) {
-                throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+                // throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+                //         + mHomeStack + " already exist on display=" + this + " stack=" + stack);
+                Slog.e(TAG, "addStackReferenceIfNeeded: home stack="
                         + mHomeStack + " already exist on display=" + this + " stack=" + stack);
+            } else {
+                mHomeStack = stack;
             }
-            mHomeStack = stack;
         } else if (activityType == ACTIVITY_TYPE_RECENTS) {
             if (mRecentsStack != null && mRecentsStack != stack) {
                 throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
@@ -535,7 +641,21 @@
                 windowingMode = getWindowingMode();
             }
         }
+        return validateWindowingMode(windowingMode, r, task, activityType);
+    }
 
+    /**
+     * Check that the requested windowing-mode is appropriate for the specified task and/or activity
+     * on this display.
+     *
+     * @param windowingMode The windowing-mode to validate.
+     * @param r The {@link ActivityRecord} to check against.
+     * @param task The {@link TaskRecord} to check against.
+     * @param activityType An activity type.
+     * @return The provided windowingMode or the closest valid mode which is appropriate.
+     */
+    int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r,
+        @Nullable TaskRecord task, int activityType) {
         // Make sure the windowing mode we are trying to use makes sense for what is supported.
         final ActivityTaskManagerService service = mSupervisor.mService;
         boolean supportsMultiWindow = service.mSupportsMultiWindow;
@@ -579,7 +699,7 @@
 
     /**
      * Get the topmost stack on the display. It may be different from focused stack, because
-     * focus may be on another display.
+     * some stacks are not focusable (e.g. PiP).
      */
     ActivityStack getTopStack() {
         return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
@@ -715,7 +835,7 @@
 
     boolean shouldSleep() {
         return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
-                && (mSupervisor.mService.mAm.mRunningVoice == null);
+                && (mSupervisor.mService.mRunningVoice == null);
     }
 
     /**
@@ -855,6 +975,16 @@
         final long token = proto.start(fieldId);
         super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
         proto.write(ID, mDisplayId);
+        final ActivityStack focusedStack = getFocusedStack();
+        if (focusedStack != null) {
+            proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
+            final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
+            if (focusedActivity != null) {
+                focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
+            }
+        } else {
+            proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
+        }
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final ActivityStack stack = mStacks.get(stackNdx);
             stack.writeToProto(proto, STACKS);
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 6550d06..2c8f2fc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -67,6 +67,7 @@
     static final String KEY_BOUND_SERVICE_CRASH_RESTART_DURATION = "service_crash_restart_duration";
     static final String KEY_BOUND_SERVICE_CRASH_MAX_RETRY = "service_crash_max_retry";
     static final String KEY_PROCESS_START_ASYNC = "process_start_async";
+    static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time";
 
     private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
     private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
@@ -95,7 +96,7 @@
     private static final long DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION = 30*60_000;
     private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 16;
     private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
-
+    private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000;
 
     // Maximum number of cached processes we will allow.
     public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -207,6 +208,14 @@
     // Indicates if the processes need to be started asynchronously.
     public boolean FLAG_PROCESS_START_ASYNC = DEFAULT_PROCESS_START_ASYNC;
 
+    // The minimum time we allow between requests for the MemoryInfo of a process to
+    // throttle requests from apps.
+    public long MEMORY_INFO_THROTTLE_TIME = DEFAULT_MEMORY_INFO_THROTTLE_TIME;
+
+    // Indicates whether the activity starts logging is enabled.
+    // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
+    boolean mFlagActivityStartsLoggingEnabled;
+
     private final ActivityManagerService mService;
     private ContentResolver mResolver;
     private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -235,6 +244,12 @@
     // memory trimming.
     public int CUR_TRIM_CACHED_PROCESSES;
 
+    private static final Uri ACTIVITY_MANAGER_CONSTANTS_URI = Settings.Global.getUriFor(
+                Settings.Global.ACTIVITY_MANAGER_CONSTANTS);
+
+    private static final Uri ACTIVITY_STARTS_LOGGING_ENABLED_URI = Settings.Global.getUriFor(
+                Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED);
+
     public ActivityManagerConstants(ActivityManagerService service, Handler handler) {
         super(handler);
         mService = service;
@@ -243,9 +258,10 @@
 
     public void start(ContentResolver resolver) {
         mResolver = resolver;
-        mResolver.registerContentObserver(Settings.Global.getUriFor(
-                Settings.Global.ACTIVITY_MANAGER_CONSTANTS), false, this);
+        mResolver.registerContentObserver(ACTIVITY_MANAGER_CONSTANTS_URI, false, this);
+        mResolver.registerContentObserver(ACTIVITY_STARTS_LOGGING_ENABLED_URI, false, this);
         updateConstants();
+        updateActivityStartsLoggingEnabled();
     }
 
     public void setOverrideMaxCachedProcesses(int value) {
@@ -263,7 +279,12 @@
 
     @Override
     public void onChange(boolean selfChange, Uri uri) {
-        updateConstants();
+        if (uri == null) return;
+        if (ACTIVITY_MANAGER_CONSTANTS_URI.equals(uri)) {
+            updateConstants();
+        } else if (ACTIVITY_STARTS_LOGGING_ENABLED_URI.equals(uri)) {
+            updateActivityStartsLoggingEnabled();
+        }
     }
 
     private void updateConstants() {
@@ -332,11 +353,18 @@
                 DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY);
             FLAG_PROCESS_START_ASYNC = mParser.getBoolean(KEY_PROCESS_START_ASYNC,
                     DEFAULT_PROCESS_START_ASYNC);
+            MEMORY_INFO_THROTTLE_TIME = mParser.getLong(KEY_MEMORY_INFO_THROTTLE_TIME,
+                    DEFAULT_MEMORY_INFO_THROTTLE_TIME);
 
             updateMaxCachedProcesses();
         }
     }
 
+    private void updateActivityStartsLoggingEnabled() {
+        mFlagActivityStartsLoggingEnabled = Settings.Global.getInt(mResolver,
+                Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED, 0) == 1;
+    }
+
     private void updateMaxCachedProcesses() {
         CUR_MAX_CACHED_PROCESSES = mOverrideMaxCachedProcesses < 0
                 ? MAX_CACHED_PROCESSES : mOverrideMaxCachedProcesses;
@@ -402,6 +430,14 @@
         pw.println(MAX_SERVICE_INACTIVITY);
         pw.print("  "); pw.print(KEY_BG_START_TIMEOUT); pw.print("=");
         pw.println(BG_START_TIMEOUT);
+        pw.print("  "); pw.print(KEY_BOUND_SERVICE_CRASH_RESTART_DURATION); pw.print("=");
+        pw.println(BOUND_SERVICE_CRASH_RESTART_DURATION);
+        pw.print("  "); pw.print(KEY_BOUND_SERVICE_CRASH_MAX_RETRY); pw.print("=");
+        pw.println(BOUND_SERVICE_MAX_CRASH_RETRY);
+        pw.print("  "); pw.print(KEY_PROCESS_START_ASYNC); pw.print("=");
+        pw.println(FLAG_PROCESS_START_ASYNC);
+        pw.print("  "); pw.print(KEY_MEMORY_INFO_THROTTLE_TIME); pw.print("=");
+        pw.println(MEMORY_INFO_THROTTLE_TIME);
 
         pw.println();
         if (mOverrideMaxCachedProcesses >= 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 89810f9..82805ed 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -56,7 +56,6 @@
 import static android.os.Process.PROC_OUT_LONG;
 import static android.os.Process.PROC_PARENS;
 import static android.os.Process.PROC_SPACE_TERM;
-import static android.os.Process.ProcessStartResult;
 import static android.os.Process.ROOT_UID;
 import static android.os.Process.SCHED_FIFO;
 import static android.os.Process.SCHED_OTHER;
@@ -86,21 +85,12 @@
 import static android.os.Process.setThreadScheduler;
 import static android.os.Process.startWebView;
 import static android.os.Process.zygoteProcess;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
 import static android.provider.Settings.Global.DEBUG_APP;
-import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
 import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
 import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
-import static android.provider.Settings.System.FONT_SCALE;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.internal.util.XmlUtils.readBooleanAttribute;
-import static com.android.internal.util.XmlUtils.readIntAttribute;
-import static com.android.internal.util.XmlUtils.readLongAttribute;
-import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
-import static com.android.internal.util.XmlUtils.writeIntAttribute;
-import static com.android.internal.util.XmlUtils.writeLongAttribute;
+
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK;
@@ -125,7 +115,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_URI_PERMISSION;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_WHITELISTS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BACKUP;
@@ -151,8 +140,6 @@
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.MemoryStatUtil.hasMemcg;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
-import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
-import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
 import android.Manifest;
 import android.Manifest.permission;
@@ -167,15 +154,14 @@
 import android.app.ActivityManagerProto;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
-import android.app.AlertDialog;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal.CheckOpsDelegate;
 import android.app.ApplicationErrorReport;
 import android.app.ApplicationThreadConstants;
 import android.app.BroadcastOptions;
 import android.app.ContentProviderHolder;
 import android.app.Dialog;
-import android.app.GrantedUriPermission;
 import android.app.IActivityController;
 import android.app.IActivityManager;
 import android.app.IApplicationThread;
@@ -202,13 +188,11 @@
 import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
 import android.content.BroadcastReceiver;
-import android.content.ClipData;
 import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.IContentProvider;
 import android.content.IIntentReceiver;
 import android.content.IIntentSender;
@@ -225,6 +209,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageManagerInternal.CheckPermissionDelegate;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PathPermission;
 import android.content.pm.PermissionInfo;
@@ -246,11 +231,11 @@
 import android.net.Uri;
 import android.os.BatteryStats;
 import android.os.Binder;
+import android.os.BinderProxy;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.DropBoxManager;
-import android.os.Environment;
 import android.os.FactoryTest;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -263,10 +248,10 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
 import android.os.Process;
+import android.os.Process.ProcessStartResult;
 import android.os.RemoteCallback;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -284,15 +269,12 @@
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageManagerInternal;
-import android.provider.Downloads;
 import android.provider.Settings;
-import android.service.voice.IVoiceInteractionSession;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.text.style.SuggestionSpan;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.AtomicFile;
 import android.util.DebugUtils;
 import android.util.EventLog;
 import android.util.Log;
@@ -305,7 +287,6 @@
 import android.util.StatsLog;
 import android.util.TimeUtils;
 import android.util.TimingsTraceLog;
-import android.util.Xml;
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
 import android.view.Gravity;
@@ -315,16 +296,12 @@
 import android.view.WindowManager;
 import android.view.autofill.AutofillManagerInternal;
 
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.DumpHeapActivity;
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.ProcessMap;
 import com.android.internal.app.SystemUserHomeActivity;
 import com.android.internal.app.procstats.ProcessStats;
@@ -342,13 +319,13 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastPrintWriter;
-import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.MemInfoReader;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.TriFunction;
 import com.android.server.AlarmManagerInternal;
 import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
-import com.android.server.BinderCallsStatsService;
 import com.android.server.DeviceIdleController;
 import com.android.server.IntentResolver;
 import com.android.server.IoThread;
@@ -362,40 +339,28 @@
 import com.android.server.SystemServiceManager;
 import com.android.server.ThreadPriorityBooster;
 import com.android.server.Watchdog;
-import com.android.server.am.ActivityManagerServiceDumpActivitiesProto;
-import com.android.server.am.ActivityManagerServiceDumpBroadcastsProto;
-import com.android.server.am.ActivityManagerServiceDumpProcessesProto;
 import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
-import com.android.server.am.ActivityManagerServiceDumpServicesProto;
-import com.android.server.am.ActivityManagerServiceProto;
 import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.am.GrantUriProto;
-import com.android.server.am.ImportanceTokenProto;
-import com.android.server.am.MemInfoDumpProto;
 import com.android.server.am.MemoryStatUtil.MemoryStat;
-import com.android.server.am.NeededUriGrantsProto;
-import com.android.server.am.ProcessOomProto;
-import com.android.server.am.ProcessToGcProto;
-import com.android.server.am.StickyBroadcastProto;
 import com.android.server.firewall.IntentFirewall;
 import com.android.server.job.JobSchedulerInternal;
 import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.dex.DexManager;
+import com.android.server.uri.GrantUri;
+import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.utils.PriorityDump;
 import com.android.server.vr.VrManagerInternal;
 import com.android.server.wm.ActivityTaskManagerInternal;
-import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
 import com.android.server.wm.WindowManagerService;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
+import dalvik.system.VMRuntime;
+
+import libcore.util.EmptyArray;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.FileReader;
@@ -405,7 +370,6 @@
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 import java.lang.ref.WeakReference;
-import java.nio.charset.StandardCharsets;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -425,10 +389,7 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
-
-import dalvik.system.VMRuntime;
-import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
+import java.util.function.BiFunction;
 
 public class ActivityManagerService extends IActivityManager.Stub
         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
@@ -500,19 +461,10 @@
     static final int BROADCAST_FG_TIMEOUT = 10*1000;
     static final int BROADCAST_BG_TIMEOUT = 60*1000;
 
-    // How long we wait until we timeout on key dispatching.
-    static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
-
-    // How long we wait until we timeout on key dispatching during instrumentation.
-    static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
-
     // Disable hidden API checks for the newly started instrumentation.
     // Must be kept in sync with Am.
     private static final int INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0;
 
-    // Maximum number of persisted Uri grants a package is allowed
-    static final int MAX_PERSISTED_URI_GRANTS = 128;
-
     static final int MY_PID = myPid();
 
     static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -537,6 +489,9 @@
     // Used to indicate that an app transition should be animated.
     static final boolean ANIMATE = true;
 
+    // If set, we will push process association information in to procstats.
+    static final boolean TRACK_PROCSTATS_ASSOCIATIONS = true;
+
     /**
      * Default value for {@link Settings.Global#NETWORK_ACCESS_TIMEOUT_MS}.
      */
@@ -580,16 +535,11 @@
 
     public final IntentFirewall mIntentFirewall;
 
-    // Whether we should show our dialogs (ANR, crash, etc) or just perform their
-    // default action automatically.  Important for devices without direct input
-    // devices.
-    private boolean mShowDialogs = true;
+    public OomAdjProfiler mOomAdjProfiler = new OomAdjProfiler();
 
     // Whether we should use SCHED_FIFO for UI and RenderThreads.
     private boolean mUseFifoUiScheduling = false;
 
-    private static final String SYSUI_COMPONENT_NAME = "com.android.systemui/.SystemUIService";
-
     BroadcastQueue mFgBroadcastQueue;
     BroadcastQueue mBgBroadcastQueue;
     // Convenient for easy iteration over the queues. Foreground is first
@@ -608,25 +558,6 @@
     }
 
     /**
-     * The last resumed activity. This is identical to the current resumed activity most
-     * of the time but could be different when we're pausing one activity before we resume
-     * another activity.
-     */
-    ActivityRecord mLastResumedActivity;
-
-    /**
-     * The activity that is currently being traced as the active resumed activity.
-     *
-     * @see #updateResumedAppTrace
-     */
-    private @Nullable ActivityRecord mTracedResumedActivity;
-
-    /**
-     * If non-null, we are tracking the time the user spends in the currently focused app.
-     */
-    private AppTimeTracker mCurAppTimeTracker;
-
-    /**
      * The package name of the DeviceOwner. This package is not permitted to have its data cleared.
      */
     String mDeviceOwnerName;
@@ -635,8 +566,6 @@
 
     final AppErrors mAppErrors;
 
-    final AppWarnings mAppWarnings;
-
     /**
      * Dump of the activity state at the time of the last ANR. Cleared after
      * {@link WindowManagerService#LAST_ANR_LIFETIME_DURATION_MSECS}
@@ -665,7 +594,7 @@
                 boolean asProto) {
             if (asProto) return;
             doDump(fd, pw, new String[]{"activities"}, asProto);
-            doDump(fd, pw, new String[]{"service", SYSUI_COMPONENT_NAME}, asProto);
+            doDump(fd, pw, new String[]{"service", "all-platform-critical"}, asProto);
         }
 
         @Override
@@ -679,15 +608,6 @@
         }
     };
 
-    public boolean canShowErrorDialogs() {
-        return mShowDialogs && !mSleeping && !mShuttingDown
-                && !mActivityTaskManager.mKeyguardController.isKeyguardOrAodShowing(DEFAULT_DISPLAY)
-                && !mUserController.hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
-                        mUserController.getCurrentUserId())
-                && !(UserManager.isDeviceInDemoMode(mContext)
-                        && mUserController.getCurrentUser().isDemo());
-    }
-
     private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
             THREAD_PRIORITY_FOREGROUND, LockGuard.INDEX_ACTIVITY);
 
@@ -765,10 +685,42 @@
      * All of the processes we currently have running organized by pid.
      * The keys are the pid running the application.
      *
-     * <p>NOTE: This object is protected by its own lock, NOT the global
-     * activity manager lock!
+     * <p>NOTE: This object is protected by its own lock, NOT the global activity manager lock!
      */
-    final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
+    final PidMap mPidsSelfLocked = new PidMap();
+    final class PidMap {
+        private final SparseArray<ProcessRecord> mPidMap = new SparseArray<>();
+
+        void put(int key, ProcessRecord value) {
+            mPidMap.put(key, value);
+            mAtmInternal.onProcessMapped(key, value.getWindowProcessController());
+        }
+
+        void remove(int pid) {
+            mPidMap.remove(pid);
+            mAtmInternal.onProcessUnMapped(pid);
+        }
+
+        ProcessRecord get(int pid) {
+            return mPidMap.get(pid);
+        }
+
+        int size() {
+            return mPidMap.size();
+        }
+
+        ProcessRecord valueAt(int index) {
+            return mPidMap.valueAt(index);
+        }
+
+        int keyAt(int index) {
+            return mPidMap.keyAt(index);
+        }
+
+        int indexOfKey(int key) {
+            return mPidMap.indexOfKey(key);
+        }
+    }
 
     /**
      * All of the processes that have been forced to be important.  The key
@@ -1001,126 +953,12 @@
      * application is currently being launched and the provider will be
      * removed from this list once it is published.
      */
-    final ArrayList<ContentProviderRecord> mLaunchingProviders
-            = new ArrayList<ContentProviderRecord>();
-
-    /**
-     * File storing persisted {@link #mGrantedUriPermissions}.
-     */
-    private final AtomicFile mGrantFile;
-
-    /** XML constants used in {@link #mGrantFile} */
-    private static final String TAG_URI_GRANTS = "uri-grants";
-    private static final String TAG_URI_GRANT = "uri-grant";
-    private static final String ATTR_USER_HANDLE = "userHandle";
-    private static final String ATTR_SOURCE_USER_ID = "sourceUserId";
-    private static final String ATTR_TARGET_USER_ID = "targetUserId";
-    private static final String ATTR_SOURCE_PKG = "sourcePkg";
-    private static final String ATTR_TARGET_PKG = "targetPkg";
-    private static final String ATTR_URI = "uri";
-    private static final String ATTR_MODE_FLAGS = "modeFlags";
-    private static final String ATTR_CREATED_TIME = "createdTime";
-    private static final String ATTR_PREFIX = "prefix";
-
-    /**
-     * Global set of specific {@link Uri} permissions that have been granted.
-     * This optimized lookup structure maps from {@link UriPermission#targetUid}
-     * to {@link UriPermission#uri} to {@link UriPermission}.
-     */
-    @GuardedBy("this")
-    private final SparseArray<ArrayMap<GrantUri, UriPermission>>
-            mGrantedUriPermissions = new SparseArray<ArrayMap<GrantUri, UriPermission>>();
-
-    public static class GrantUri {
-        public final int sourceUserId;
-        public final Uri uri;
-        public boolean prefix;
-
-        public GrantUri(int sourceUserId, Uri uri, boolean prefix) {
-            this.sourceUserId = sourceUserId;
-            this.uri = uri;
-            this.prefix = prefix;
-        }
-
-        @Override
-        public int hashCode() {
-            int hashCode = 1;
-            hashCode = 31 * hashCode + sourceUserId;
-            hashCode = 31 * hashCode + uri.hashCode();
-            hashCode = 31 * hashCode + (prefix ? 1231 : 1237);
-            return hashCode;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (o instanceof GrantUri) {
-                GrantUri other = (GrantUri) o;
-                return uri.equals(other.uri) && (sourceUserId == other.sourceUserId)
-                        && prefix == other.prefix;
-            }
-            return false;
-        }
-
-        @Override
-        public String toString() {
-            String result = uri.toString() + " [user " + sourceUserId + "]";
-            if (prefix) result += " [prefix]";
-            return result;
-        }
-
-        public String toSafeString() {
-            String result = uri.toSafeString() + " [user " + sourceUserId + "]";
-            if (prefix) result += " [prefix]";
-            return result;
-        }
-
-        public void writeToProto(ProtoOutputStream proto, long fieldId) {
-            long token = proto.start(fieldId);
-            proto.write(GrantUriProto.URI, uri.toString());
-            proto.write(GrantUriProto.SOURCE_USER_ID, sourceUserId);
-            proto.end(token);
-        }
-
-        public static GrantUri resolve(int defaultSourceUserHandle, Uri uri) {
-            if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
-                return new GrantUri(ContentProvider.getUserIdFromUri(uri, defaultSourceUserHandle),
-                        ContentProvider.getUriWithoutUserId(uri), false);
-            } else {
-                return new GrantUri(defaultSourceUserHandle, uri, false);
-            }
-        }
-    }
+    final ArrayList<ContentProviderRecord> mLaunchingProviders = new ArrayList<>();
 
     boolean mSystemProvidersInstalled;
 
     CoreSettingsObserver mCoreSettingsObserver;
 
-    FontScaleSettingObserver mFontScaleSettingObserver;
-
-    private final class FontScaleSettingObserver extends ContentObserver {
-        private final Uri mFontScaleUri = Settings.System.getUriFor(FONT_SCALE);
-        private final Uri mHideErrorDialogsUri = Settings.Global.getUriFor(HIDE_ERROR_DIALOGS);
-
-        public FontScaleSettingObserver() {
-            super(mHandler);
-            ContentResolver resolver = mContext.getContentResolver();
-            resolver.registerContentObserver(mFontScaleUri, false, this, UserHandle.USER_ALL);
-            resolver.registerContentObserver(mHideErrorDialogsUri, false, this,
-                    UserHandle.USER_ALL);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
-            if (mFontScaleUri.equals(uri)) {
-                updateFontScaleIfNeeded(userId);
-            } else if (mHideErrorDialogsUri.equals(uri)) {
-                synchronized (ActivityManagerService.this) {
-                    updateShouldShowDialogsLocked(getGlobalConfiguration());
-                }
-            }
-        }
-    }
-
     DevelopmentSettingsObserver mDevelopmentSettingsObserver;
 
     private final class DevelopmentSettingsObserver extends ContentObserver {
@@ -1280,55 +1118,16 @@
     long mLastPowerCheckUptime;
 
     /**
-     * Set while we are wanting to sleep, to prevent any
-     * activities from being started/resumed.
-     *
-     * TODO(b/33594039): Clarify the actual state transitions represented by mSleeping.
-     *
-     * Currently mSleeping is set to true when transitioning into the sleep state, and remains true
-     * while in the sleep state until there is a pending transition out of sleep, in which case
-     * mSleeping is set to false, and remains false while awake.
-     *
-     * Whether mSleeping can quickly toggled between true/false without the device actually
-     * display changing states is undefined.
-     */
-    private boolean mSleeping = false;
-
-    /**
-     * The process state used for processes that are running the top activities.
-     * This changes between TOP and TOP_SLEEPING to following mSleeping.
-     */
-    int mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
-
-    /**
-     * Set while we are running a voice interaction.  This overrides
-     * sleeping while it is active.
-     */
-    IVoiceInteractionSession mRunningVoice;
-
-    /**
      * For some direct access we need to power manager.
      */
     PowerManagerInternal mLocalPowerManager;
 
     /**
-     * We want to hold a wake lock while running a voice interaction session, since
-     * this may happen with the screen off and we need to keep the CPU running to
-     * be able to continue to interact with the user.
-     */
-    PowerManager.WakeLock mVoiceWakeLock;
-
-    /**
      * State of external calls telling us if the device is awake or asleep.
      */
     private int mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
 
     /**
-     * Set if we are shutting down the system, similar to sleeping.
-     */
-    boolean mShuttingDown = false;
-
-    /**
      * Current sequence id for oom_adj computation traversal.
      */
     int mAdjSeq = 0;
@@ -1602,6 +1401,7 @@
     WindowManagerService mWindowManager;
     ActivityTaskManagerService mActivityTaskManager;
     ActivityTaskManagerInternal mAtmInternal;
+    UriGrantsManagerInternal mUgmInternal;
     final ActivityThread mSystemThread;
 
     private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -1638,8 +1438,6 @@
     static final int WAIT_FOR_DEBUGGER_UI_MSG = 6;
     static final int SERVICE_TIMEOUT_MSG = 12;
     static final int UPDATE_TIME_ZONE = 13;
-    static final int SHOW_UID_ERROR_UI_MSG = 14;
-    static final int SHOW_FINGERPRINT_ERROR_UI_MSG = 15;
     static final int PROC_START_TIMEOUT_MSG = 20;
     static final int KILL_APPLICATION_MSG = 22;
     static final int FINALIZE_PENDING_INTENT_MSG = 23;
@@ -1649,20 +1447,16 @@
     static final int CHECK_EXCESSIVE_POWER_USE_MSG = 27;
     static final int CLEAR_DNS_CACHE_MSG = 28;
     static final int UPDATE_HTTP_PROXY_MSG = 29;
-    static final int SHOW_COMPAT_MODE_DIALOG_UI_MSG = 30;
     static final int DISPATCH_PROCESSES_CHANGED_UI_MSG = 31;
     static final int DISPATCH_PROCESS_DIED_UI_MSG = 32;
     static final int REPORT_MEM_USAGE_MSG = 33;
-    static final int PERSIST_URI_GRANTS_MSG = 38;
     static final int UPDATE_TIME_PREFERENCE_MSG = 41;
     static final int FINISH_BOOTING_MSG = 45;
     static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47;
-    static final int DISMISS_DIALOG_UI_MSG = 48;
     static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 49;
     static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 50;
     static final int DELETE_DUMPHEAP_MSG = 51;
     static final int DISPATCH_UIDS_CHANGED_UI_MSG = 53;
-    static final int REPORT_TIME_TRACKER_MSG = 54;
     static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 56;
     static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 57;
     static final int IDLE_UIDS_MSG = 58;
@@ -1683,7 +1477,6 @@
     static ServiceThread sKillThread = null;
     static KillHandler sKillHandler = null;
 
-    CompatModeDialog mCompatModeDialog;
     long mLastMemUsageReportTime = 0;
 
     /**
@@ -1705,8 +1498,6 @@
 
     PackageManagerInternal mPackageManagerInt;
 
-    final boolean mPermissionReviewRequired;
-
     boolean mHasHeavyWeightFeature;
 
     /**
@@ -1777,7 +1568,7 @@
                         return;
                     }
                     AppErrorResult res = (AppErrorResult) data.get("result");
-                    if (mShowDialogs && !mSleeping && !mShuttingDown) {
+                    if (mAtmInternal.showStrictModeViolationDialog()) {
                         Dialog d = new StrictModeViolationDialog(mUiContext,
                                 ActivityManagerService.this, res, proc);
                         d.show();
@@ -1816,63 +1607,6 @@
                     }
                 }
             } break;
-            case SHOW_UID_ERROR_UI_MSG: {
-                if (mShowDialogs) {
-                    AlertDialog d = new BaseErrorDialog(mUiContext);
-                    d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
-                    d.setCancelable(false);
-                    d.setTitle(mUiContext.getText(R.string.android_system_label));
-                    d.setMessage(mUiContext.getText(R.string.system_error_wipe_data));
-                    d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.ok),
-                            obtainMessage(DISMISS_DIALOG_UI_MSG, d));
-                    d.show();
-                }
-            } break;
-            case SHOW_FINGERPRINT_ERROR_UI_MSG: {
-                if (mShowDialogs) {
-                    AlertDialog d = new BaseErrorDialog(mUiContext);
-                    d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
-                    d.setCancelable(false);
-                    d.setTitle(mUiContext.getText(R.string.android_system_label));
-                    d.setMessage(mUiContext.getText(R.string.system_error_manufacturer));
-                    d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.ok),
-                            obtainMessage(DISMISS_DIALOG_UI_MSG, d));
-                    d.show();
-                }
-            } break;
-            case SHOW_COMPAT_MODE_DIALOG_UI_MSG: {
-                synchronized (ActivityManagerService.this) {
-                    ActivityRecord ar = (ActivityRecord) msg.obj;
-                    if (mCompatModeDialog != null) {
-                        if (mCompatModeDialog.mAppInfo.packageName.equals(
-                                ar.info.applicationInfo.packageName)) {
-                            return;
-                        }
-                        mCompatModeDialog.dismiss();
-                        mCompatModeDialog = null;
-                    }
-                    if (ar != null && false) {
-                        if (mCompatModePackages.getPackageAskCompatModeLocked(
-                                ar.packageName)) {
-                            int mode = mCompatModePackages.computeCompatModeLocked(
-                                    ar.info.applicationInfo);
-                            if (mode == ActivityManager.COMPAT_MODE_DISABLED
-                                    || mode == ActivityManager.COMPAT_MODE_ENABLED) {
-                                mCompatModeDialog = new CompatModeDialog(
-                                        ActivityManagerService.this, mUiContext,
-                                        ar.info.applicationInfo);
-                                mCompatModeDialog.show();
-                            }
-                        }
-                    }
-                }
-                break;
-            }
-            case DISMISS_DIALOG_UI_MSG: {
-                final Dialog d = (Dialog) msg.obj;
-                d.dismiss();
-                break;
-            }
             case DISPATCH_PROCESSES_CHANGED_UI_MSG: {
                 dispatchProcessesChanged();
                 break;
@@ -2098,10 +1832,6 @@
                 thread.start();
                 break;
             }
-            case PERSIST_URI_GRANTS_MSG: {
-                writeGrantedUriPermissions();
-                break;
-            }
             case UPDATE_TIME_PREFERENCE_MSG: {
                 // The user's time format preference might have changed.
                 // For convenience we re-use the Intent extra values.
@@ -2127,7 +1857,7 @@
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                 }
                 if (msg.arg2 != 0) {
-                    enableScreenAfterBoot();
+                    mAtmInternal.enableScreenAfterBoot(mBooted);
                 }
                 break;
             }
@@ -2247,10 +1977,6 @@
                     mMemWatchDumpUid = -1;
                 }
             } break;
-            case REPORT_TIME_TRACKER_MSG: {
-                AppTimeTracker tracker = (AppTimeTracker)msg.obj;
-                tracker.deliverResult(mContext);
-            } break;
             case SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG: {
                 IUiAutomationConnection connection = (IUiAutomationConnection) msg.obj;
                 try {
@@ -2699,16 +2425,13 @@
         mUiContext = null;
         GL_ES_VERSION = 0;
         mAppErrors = null;
-        mAppWarnings = null;
         mAppOpsService = mInjector.getAppOpsService(null, null);
         mBatteryStatsService = null;
         mCompatModePackages = null;
         mConstants = null;
-        mGrantFile = null;
         mHandler = null;
         mHandlerThread = null;
         mIntentFirewall = null;
-        mPermissionReviewRequired = false;
         mProcessCpuThread = null;
         mProcessStats = null;
         mProviderMap = null;
@@ -2734,9 +2457,6 @@
 
         Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
 
-        mPermissionReviewRequired = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_permissionReviewRequired);
-
         mHandlerThread = new ServiceThread(TAG,
                 THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
         mHandlerThread.start();
@@ -2769,11 +2489,7 @@
         mProviderMap = new ProviderMap(this);
         mAppErrors = new AppErrors(mUiContext, this);
 
-        File dataDir = Environment.getDataDirectory();
-        File systemDir = new File(dataDir, "system");
-        systemDir.mkdirs();
-
-        mAppWarnings = new AppWarnings(this, mUiContext, mHandler, mUiHandler, systemDir);
+        final File systemDir = SystemServiceManager.ensureSystemDir();
 
         // TODO: Move creation of battery stats service outside of activity manager service.
         mBatteryStatsService = new BatteryStatsService(systemContext, systemDir, mHandler);
@@ -2782,12 +2498,13 @@
         mOnBattery = DEBUG_POWER ? true
                 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
         mBatteryStatsService.getActiveStatistics().setCallback(this);
+        mOomAdjProfiler.batteryPowerChanged(mOnBattery);
 
         mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
 
         mAppOpsService = mInjector.getAppOpsService(new File(systemDir, "appops.xml"), mHandler);
 
-        mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");
+        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
 
         mUserController = new UserController(this);
 
@@ -2876,6 +2593,7 @@
         Slog.d("AppOps", "AppOpsService published");
         LocalServices.addService(ActivityManagerInternal.class, new LocalService());
         mActivityTaskManager.onActivityManagerInternalAdded();
+        mUgmInternal.onActivityManagerInternalAdded();
         // Wait for the synchronized block started in mProcessCpuThread,
         // so that any other access to mProcessCpuTracker from main thread
         // will be blocked during mProcessCpuTracker initialization.
@@ -2889,12 +2607,9 @@
     }
 
     public void initPowerManagement() {
-        mStackSupervisor.initPowerManagement();
+        mActivityTaskManager.onInitPowerManagement();
         mBatteryStatsService.initPowerManagement();
         mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class);
-        PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
-        mVoiceWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*voice*");
-        mVoiceWakeLock.setReferenceCounted(false);
     }
 
     private ArraySet<String> getBackgroundLaunchBroadcasts() {
@@ -3073,12 +2788,13 @@
             synchronized(mPidsSelfLocked) {
                 mOnBattery = DEBUG_POWER ? true : onBattery;
             }
+            mOomAdjProfiler.batteryPowerChanged(onBattery);
         }
     }
 
     @Override
     public void batteryStatsReset() {
-        BinderCallsStatsService.reset();
+        mOomAdjProfiler.reset();
     }
 
     @Override
@@ -3145,96 +2861,6 @@
         }
     }
 
-    /**
-     * Update AMS states when an activity is resumed. This should only be called by
-     * {@link ActivityStack#onActivityStateChanged(ActivityRecord, ActivityState, String)} when an
-     * activity is resumed.
-     */
-    @GuardedBy("this")
-    void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
-        final TaskRecord task = r.getTask();
-        if (task.isActivityTypeStandard()) {
-            if (mCurAppTimeTracker != r.appTimeTracker) {
-                // We are switching app tracking.  Complete the current one.
-                if (mCurAppTimeTracker != null) {
-                    mCurAppTimeTracker.stop();
-                    mHandler.obtainMessage(
-                            REPORT_TIME_TRACKER_MSG, mCurAppTimeTracker).sendToTarget();
-                    mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker);
-                    mCurAppTimeTracker = null;
-                }
-                if (r.appTimeTracker != null) {
-                    mCurAppTimeTracker = r.appTimeTracker;
-                    startTimeTrackingFocusedActivityLocked();
-                }
-            } else {
-                startTimeTrackingFocusedActivityLocked();
-            }
-        } else {
-            r.appTimeTracker = null;
-        }
-        // TODO: VI Maybe r.task.voiceInteractor || r.voiceInteractor != null
-        // TODO: Probably not, because we don't want to resume voice on switching
-        // back to this activity
-        if (task.voiceInteractor != null) {
-            startRunningVoiceLocked(task.voiceSession, r.info.applicationInfo.uid);
-        } else {
-            finishRunningVoiceLocked();
-
-            if (mLastResumedActivity != null) {
-                final IVoiceInteractionSession session;
-
-                final TaskRecord lastResumedActivityTask = mLastResumedActivity.getTask();
-                if (lastResumedActivityTask != null
-                        && lastResumedActivityTask.voiceSession != null) {
-                    session = lastResumedActivityTask.voiceSession;
-                } else {
-                    session = mLastResumedActivity.voiceSession;
-                }
-
-                if (session != null) {
-                    // We had been in a voice interaction session, but now focused has
-                    // move to something different.  Just finish the session, we can't
-                    // return to it and retain the proper state and synchronization with
-                    // the voice interaction service.
-                    mActivityTaskManager.finishVoiceTask(session);
-                }
-            }
-        }
-
-        if (mLastResumedActivity != null && r.userId != mLastResumedActivity.userId) {
-            mUserController.sendForegroundProfileChanged(r.userId);
-        }
-        updateResumedAppTrace(r);
-        mLastResumedActivity = r;
-
-        mWindowManager.setFocusedApp(r.appToken, true);
-
-        mActivityTaskManager.applyUpdateLockStateLocked(r);
-        mActivityTaskManager.applyUpdateVrModeLocked(r);
-
-        EventLogTags.writeAmSetResumedActivity(
-                r == null ? -1 : r.userId,
-                r == null ? "NULL" : r.shortComponentName,
-                reason);
-    }
-
-    private void updateResumedAppTrace(@Nullable ActivityRecord resumed) {
-        if (mTracedResumedActivity != null) {
-            Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER,
-                    constructResumedTraceName(mTracedResumedActivity.packageName), 0);
-        }
-        if (resumed != null) {
-            Trace.asyncTraceBegin(TRACE_TAG_ACTIVITY_MANAGER,
-                    constructResumedTraceName(resumed.packageName), 0);
-        }
-        mTracedResumedActivity = resumed;
-    }
-
-    private String constructResumedTraceName(String packageName) {
-        return "focused app: " + packageName;
-    }
-
     @Override
     public void setFocusedStack(int stackId) {
         mActivityTaskManager.setFocusedStack(stackId);
@@ -3254,28 +2880,6 @@
         mActivityTaskManager.unregisterTaskStackListener(listener);
     }
 
-    final void showAskCompatModeDialogLocked(ActivityRecord r) {
-        Message msg = Message.obtain();
-        msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
-        msg.obj = r.getTask().askedCompatMode ? null : r;
-        mUiHandler.sendMessage(msg);
-    }
-
-    final AppWarnings getAppWarningsLocked() {
-        return mAppWarnings;
-    }
-
-    /**
-     * Shows app warning dialogs, if necessary.
-     *
-     * @param r activity record for which the warnings may be displayed
-     */
-    final void showAppWarningsIfNeededLocked(ActivityRecord r) {
-        mAppWarnings.showUnsupportedCompileSdkDialogIfNeeded(r);
-        mAppWarnings.showUnsupportedDisplaySizeDialogIfNeeded(r);
-        mAppWarnings.showDeprecatedTargetDialogIfNeeded(r);
-    }
-
     private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
             String what, Object obj, ProcessRecord srcApp) {
         app.lastActivityTime = now;
@@ -3569,6 +3173,14 @@
             // Turn this condition on to cause killing to happen regularly, for testing.
             if (proc.baseProcessTracker != null) {
                 proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss);
+                for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                    ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+                    StatsLog.write(StatsLog.CACHED_KILL_REPORTED,
+                            proc.info.uid,
+                            holder.state.getName(),
+                            holder.state.getPackage(),
+                            proc.lastCachedPss, holder.appVersion);
+                }
             }
             proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
         } else if (proc != null && !keepIfLarge
@@ -3578,6 +3190,14 @@
             if (proc.lastCachedPss >= mProcessList.getCachedRestoreThresholdKb()) {
                 if (proc.baseProcessTracker != null) {
                     proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss);
+                    for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                        ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+                        StatsLog.write(StatsLog.CACHED_KILL_REPORTED,
+                                proc.info.uid,
+                                holder.state.getName(),
+                                holder.state.getPackage(),
+                                proc.lastCachedPss, holder.appVersion);
+                    }
                 }
                 proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
             }
@@ -3953,7 +3573,7 @@
             // the package was initially frozen through KILL_APPLICATION_MSG, so
             // it doesn't hurt to use it again.)
             forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
-                    false, true, false, false, UserHandle.getUserId(app.userId), "start failure");
+                    false, true, false, false, app.userId, "start failure");
             return false;
         }
     }
@@ -3982,8 +3602,8 @@
                             app.pendingStart = false;
                             return;
                         }
-                        app.usingWrapper = invokeWith != null
-                                || SystemProperties.get("wrap." + app.processName) != null;
+                        app.setUsingWrapper(invokeWith != null
+                                || SystemProperties.get("wrap." + app.processName) != null);
                         mPendingStarts.put(startSeq, app);
                     }
                     final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
@@ -3998,8 +3618,7 @@
                         mPendingStarts.remove(startSeq);
                         app.pendingStart = false;
                         forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
-                                false, false, true, false, false,
-                                UserHandle.getUserId(app.userId), "start failure");
+                                false, false, true, false, false, app.userId, "start failure");
                     }
                 }
             });
@@ -4015,8 +3634,7 @@
                 Slog.e(TAG, "Failure starting process " + app.processName, e);
                 app.pendingStart = false;
                 forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
-                        false, false, true, false, false,
-                        UserHandle.getUserId(app.userId), "start failure");
+                        false, false, true, false, false, app.userId, "start failure");
             }
             return app.pid > 0;
         }
@@ -4035,13 +3653,13 @@
                 startResult = startWebView(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
-                        app.info.dataDir, null,
+                        app.info.dataDir, null, app.info.packageName,
                         new String[] {PROC_START_SEQ_IDENT + app.startSeq});
             } else {
                 startResult = Process.start(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
-                        app.info.dataDir, invokeWith,
+                        app.info.dataDir, invokeWith, app.info.packageName,
                         new String[] {PROC_START_SEQ_IDENT + app.startSeq});
             }
             checkTime(startTime, "startProcess: returned from zygote!");
@@ -4079,7 +3697,7 @@
         // Indicates that this process start has been taken care of.
         if (mPendingStarts.get(expectedStartSeq) == null) {
             if (pending.pid == startResult.pid) {
-                pending.usingWrapper = startResult.usingWrapper;
+                pending.setUsingWrapper(startResult.usingWrapper);
                 // TODO: Update already existing clients of usingWrapper
             }
             return false;
@@ -4142,7 +3760,7 @@
         }
         reportUidInfoMessageLocked(TAG, buf.toString(), app.startUid);
         app.setPid(pid);
-        app.usingWrapper = usingWrapper;
+        app.setUsingWrapper(usingWrapper);
         app.pendingStart = false;
         checkTime(app.startTime, "startProcess: starting to update pids map");
         ProcessRecord oldApp;
@@ -4227,7 +3845,7 @@
             aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
             ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                     aInfo.applicationInfo.uid, true);
-            if (app == null || app.instr == null) {
+            if (app == null || app.getActiveInstrumentation() == null) {
                 intent.setFlags(intent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
                 final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
                 // For ANR debugging to verify if the user activity is the one that actually
@@ -4654,44 +4272,6 @@
         mActivityTaskManager.cancelRecentsAnimation(restoreHomeStackPosition);
     }
 
-    @GuardedBy("this")
-    void onLocalVoiceInteractionStartedLocked(IBinder activity,
-            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
-        ActivityRecord activityToCallback = ActivityRecord.forTokenLocked(activity);
-        if (activityToCallback == null) return;
-        activityToCallback.setVoiceSessionLocked(voiceSession);
-
-        // Inform the activity
-        try {
-            activityToCallback.app.getThread().scheduleLocalVoiceInteractionStarted(activity,
-                    voiceInteractor);
-            long token = Binder.clearCallingIdentity();
-            try {
-                startRunningVoiceLocked(voiceSession, activityToCallback.appInfo.uid);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-            // TODO: VI Should we cache the activity so that it's easier to find later
-            // rather than scan through all the stacks and activities?
-        } catch (RemoteException re) {
-            activityToCallback.clearVoiceSessionLocked();
-            // TODO: VI Should this terminate the voice session?
-        }
-    }
-
-    @Override
-    public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake) {
-        synchronized (this) {
-            if (mRunningVoice != null && mRunningVoice.asBinder() == session.asBinder()) {
-                if (keepAwake) {
-                    mVoiceWakeLock.acquire();
-                } else {
-                    mVoiceWakeLock.release();
-                }
-            }
-        }
-    }
-
     /**
      * This is the internal entry point for handling Activity.finish().
      *
@@ -4785,9 +4365,9 @@
         app.clearRecentTasks();
         app.clearActivities();
 
-        if (app.instr != null) {
+        if (app.getActiveInstrumentation() != null) {
             Slog.w(TAG, "Crash of app " + app.processName
-                  + " running instrumentation " + app.instr.mClass);
+                  + " running instrumentation " + app.getActiveInstrumentation().mClass);
             Bundle info = new Bundle();
             info.putString("shortMsg", "Process crashed.");
             finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
@@ -4796,7 +4376,7 @@
         mWindowManager.deferSurfaceLayout();
         try {
             if (!restarting && hasVisibleActivities
-                    && !mStackSupervisor.resumeFocusedStackTopActivityLocked()) {
+                    && !mStackSupervisor.resumeFocusedStacksTopActivitiesLocked()) {
                 // If there was nothing to resume, and we are not already restarting this process, but
                 // there is a visible activity that is hosted by the process...  then make sure all
                 // visible activities are running, taking care of restarting this process.
@@ -4941,7 +4521,7 @@
         // Clean up already done if the process has been re-started.
         if (app.pid == pid && app.thread != null &&
                 app.thread.asBinder() == thread.asBinder()) {
-            boolean doLowMem = app.instr == null;
+            boolean doLowMem = app.getActiveInstrumentation() == null;
             boolean doOomAdj = doLowMem;
             if (!app.killedByAm) {
                 reportUidInfoMessageLocked(TAG,
@@ -5293,11 +4873,9 @@
                     // so it told us to keep those intact -- it's about to emplace app data
                     // that is appropriate for those bits of system state.
                     if (!keepState) {
-                        synchronized (this) {
-                            // Remove all permissions granted from/to this package
-                            removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true,
-                                    false);
-                        }
+                        // Remove all permissions granted from/to this package
+                        mUgmInternal.removeUriPermissionsForPackage(packageName, resolvedUserId,
+                                true, false);
 
                         // Reset notification state
                         INotificationManager inm = NotificationManager.getService();
@@ -5618,28 +5196,70 @@
     @Override
     public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids) {
         enforceNotIsolatedCaller("getProcessMemoryInfo");
+
+        final long now = SystemClock.uptimeMillis();
+        final long lastNow = now - mConstants.MEMORY_INFO_THROTTLE_TIME;
+
+        final int callingPid = Binder.getCallingPid();
+        final int callingUid = Binder.getCallingUid();
+        final int userId = UserHandle.getUserId(callingUid);
+        final boolean allUsers = ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL,
+                callingUid) == PackageManager.PERMISSION_GRANTED;
+        // Check REAL_GET_TASKS to see if they are allowed to access other uids
+        final boolean allUids = mAtmInternal.isGetTasksAllowed(
+                "getProcessMemoryInfo", callingPid, callingUid);
+
         Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
         for (int i=pids.length-1; i>=0; i--) {
-            ProcessRecord proc;
-            int oomAdj;
+            infos[i] = new Debug.MemoryInfo();
+            final ProcessRecord proc;
+            final int oomAdj;
             synchronized (this) {
                 synchronized (mPidsSelfLocked) {
                     proc = mPidsSelfLocked.get(pids[i]);
                     oomAdj = proc != null ? proc.setAdj : 0;
                 }
             }
-            infos[i] = new Debug.MemoryInfo();
-            long startTime = SystemClock.currentThreadTimeMillis();
-            Debug.getMemoryInfo(pids[i], infos[i]);
-            long endTime = SystemClock.currentThreadTimeMillis();
+            if (!allUids || (!allUsers && (proc == null
+                    || UserHandle.getUserId(proc.uid) != userId))) {
+                // The caller is not allow to get information about this other process...
+                // just leave it empty.
+                continue;
+            }
+            if (proc != null && proc.lastMemInfoTime >= lastNow && proc.lastMemInfo != null) {
+                // It hasn't been long enough that we want to take another sample; return
+                // the last one.
+                infos[i].set(proc.lastMemInfo);
+                continue;
+            }
+            final long startTime = SystemClock.currentThreadTimeMillis();
+            final Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
+            Debug.getMemoryInfo(pids[i], memInfo);
+            final long endTime = SystemClock.currentThreadTimeMillis();
+            infos[i].set(memInfo);
             if (proc != null) {
                 synchronized (this) {
+                    proc.lastMemInfo = memInfo;
+                    proc.lastMemInfoTime = SystemClock.uptimeMillis();
                     if (proc.thread != null && proc.setAdj == oomAdj) {
                         // Record this for posterity if the process has been stable.
                         proc.baseProcessTracker.addPss(infos[i].getTotalPss(),
                                 infos[i].getTotalUss(), infos[i].getTotalRss(), false,
-                                ProcessStats.ADD_PSS_EXTERNAL_SLOW, endTime-startTime,
+                                ProcessStats.ADD_PSS_EXTERNAL_SLOW, endTime - startTime,
                                 proc.pkgList.mPkgList);
+                        for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                            ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+                            StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED,
+                                    proc.info.uid,
+                                    holder.state.getName(),
+                                    holder.state.getPackage(),
+                                    infos[i].getTotalPss(),
+                                    infos[i].getTotalUss(),
+                                    infos[i].getTotalRss(),
+                                    ProcessStats.ADD_PSS_EXTERNAL_SLOW,
+                                    endTime-startTime,
+                                    holder.appVersion);
+                        }
                     }
                 }
             }
@@ -5650,6 +5270,16 @@
     @Override
     public long[] getProcessPss(int[] pids) {
         enforceNotIsolatedCaller("getProcessPss");
+
+        final int callingPid = Binder.getCallingPid();
+        final int callingUid = Binder.getCallingUid();
+        final int userId = UserHandle.getUserId(callingUid);
+        final boolean allUsers = ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL,
+                callingUid) == PackageManager.PERMISSION_GRANTED;
+        // Check REAL_GET_TASKS to see if they are allowed to access other uids
+        final boolean allUids = mAtmInternal.isGetTasksAllowed(
+                "getProcessPss", callingPid, callingUid);
+
         long[] pss = new long[pids.length];
         for (int i=pids.length-1; i>=0; i--) {
             ProcessRecord proc;
@@ -5660,6 +5290,11 @@
                     oomAdj = proc != null ? proc.setAdj : 0;
                 }
             }
+            if (!allUids || (!allUsers && UserHandle.getUserId(proc.uid) != userId)) {
+                // The caller is not allow to get information about this other process...
+                // just leave it empty.
+                continue;
+            }
             long[] tmpUss = new long[3];
             long startTime = SystemClock.currentThreadTimeMillis();
             pss[i] = Debug.getPss(pids[i], tmpUss, null);
@@ -5670,6 +5305,16 @@
                         // Record this for posterity if the process has been stable.
                         proc.baseProcessTracker.addPss(pss[i], tmpUss[0], tmpUss[2], false,
                                 ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, proc.pkgList.mPkgList);
+                        for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                            ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+                            StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED,
+                                    proc.info.uid,
+                                    holder.state.getName(),
+                                    holder.state.getPackage(),
+                                    pss[i], tmpUss[0], tmpUss[2],
+                                    ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime,
+                                    holder.appVersion);
+                        }
                     }
                 }
             }
@@ -5863,7 +5508,7 @@
         // Clean-up disabled activities.
         if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
                 packageName, disabledClasses, true, false, userId) && mBooted) {
-            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
             mStackSupervisor.scheduleIdleLocked();
         }
 
@@ -5968,7 +5613,7 @@
         }
 
         // Remove transient permissions granted from/to this package/user
-        removeUriPermissionsForPackageLocked(packageName, userId, false, false);
+        mUgmInternal.removeUriPermissionsForPackage(packageName, userId, false, false);
 
         if (doit) {
             for (i = mBroadcastQueues.length - 1; i >= 0; i--) {
@@ -6037,7 +5682,7 @@
                 }
             }
             if (mBooted) {
-                mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 mStackSupervisor.scheduleIdleLocked();
             }
         }
@@ -6249,7 +5894,7 @@
         if (app == null && startSeq > 0) {
             final ProcessRecord pending = mPendingStarts.get(startSeq);
             if (pending != null && pending.startUid == callingUid
-                    && handleProcessStartedLocked(pending, pid, pending.usingWrapper,
+                    && handleProcessStartedLocked(pending, pid, pending.isUsingWrapper(),
                             startSeq, true)) {
                 app = pending;
             }
@@ -6303,7 +5948,7 @@
         app.forcingToImportant = null;
         updateProcessForegroundLocked(app, false, false);
         app.hasShownUi = false;
-        app.debugging = false;
+        app.setDebugging(false);
         app.cached = false;
         app.killedByAm = false;
         app.killed = false;
@@ -6340,7 +5985,7 @@
                 testMode = mWaitForDebugger
                     ? ApplicationThreadConstants.DEBUG_WAIT
                     : ApplicationThreadConstants.DEBUG_ON;
-                app.debugging = true;
+                app.setDebugging(true);
                 if (mDebugTransient) {
                     mDebugApp = mOrigDebugApp;
                     mWaitForDebugger = mOrigWaitForDebugger;
@@ -6362,13 +6007,15 @@
                                 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
             }
 
-            if (app.instr != null) {
-                notifyPackageUse(app.instr.mClass.getPackageName(),
+            final ActiveInstrumentation instr = app.getActiveInstrumentation();
+
+            if (instr != null) {
+                notifyPackageUse(instr.mClass.getPackageName(),
                                  PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION);
             }
             if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Binding proc "
                     + processName + " with config " + getGlobalConfiguration());
-            ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
+            ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;
             app.compat = compatibilityInfoForPackageLocked(appInfo);
 
             ProfilerInfo profilerInfo = null;
@@ -6385,8 +6032,8 @@
                         preBindAgent = mProfilerInfo.agent;
                     }
                 }
-            } else if (app.instr != null && app.instr.mProfileFile != null) {
-                profilerInfo = new ProfilerInfo(app.instr.mProfileFile, null, 0, false, false,
+            } else if (instr != null && instr.mProfileFile != null) {
+                profilerInfo = new ProfilerInfo(instr.mProfileFile, null, 0, false, false,
                         null, false);
             }
             if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
@@ -6412,10 +6059,9 @@
             }
 
             // We deprecated Build.SERIAL and it is not accessible to
-            // apps that target the v2 security sandbox and to apps that
-            // target APIs higher than O MR1. Since access to the serial
+            // Instant Apps and target APIs higher than O MR1. Since access to the serial
             // is now behind a permission we push down the value.
-            final String buildSerial = (appInfo.targetSandboxVersion < 2
+            final String buildSerial = (!appInfo.isInstantApp()
                     && appInfo.targetSdkVersion < Build.VERSION_CODES.P)
                             ? sTheRealBuildSerial : Build.UNKNOWN;
 
@@ -6423,21 +6069,22 @@
             // currently active instrumentation.  (Note we do this AFTER all of the profiling
             // stuff above because profiling can currently happen only in the primary
             // instrumentation process.)
-            if (mActiveInstrumentation.size() > 0 && app.instr == null) {
-                for (int i = mActiveInstrumentation.size() - 1; i >= 0 && app.instr == null; i--) {
+            if (mActiveInstrumentation.size() > 0 && instr == null) {
+                for (int i = mActiveInstrumentation.size() - 1;
+                        i >= 0 && app.getActiveInstrumentation() == null; i--) {
                     ActiveInstrumentation aInstr = mActiveInstrumentation.get(i);
                     if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) {
                         if (aInstr.mTargetProcesses.length == 0) {
                             // This is the wildcard mode, where every process brought up for
                             // the target instrumentation should be included.
                             if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
-                                app.instr = aInstr;
+                                app.setActiveInstrumentation(aInstr);
                                 aInstr.mRunningProcesses.add(app);
                             }
                         } else {
                             for (String proc : aInstr.mTargetProcesses) {
                                 if (proc.equals(app.processName)) {
-                                    app.instr = aInstr;
+                                    app.setActiveInstrumentation(aInstr);
                                     aInstr.mRunningProcesses.add(app);
                                     break;
                                 }
@@ -6467,16 +6114,17 @@
 
             checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
             mStackSupervisor.getActivityMetricsLogger().notifyBindApplication(app);
+            final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
             if (app.isolatedEntryPoint != null) {
                 // This is an isolated process which should just call an entry point instead of
                 // being bound to an application.
                 thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
-            } else if (app.instr != null) {
+            } else if (instr2 != null) {
                 thread.bindApplication(processName, appInfo, providers,
-                        app.instr.mClass,
-                        profilerInfo, app.instr.mArguments,
-                        app.instr.mWatcher,
-                        app.instr.mUiAutomationConnection, testMode,
+                        instr2.mClass,
+                        profilerInfo, instr2.mArguments,
+                        instr2.mWatcher,
+                        instr2.mUiAutomationConnection, testMode,
                         mBinderTransactionTrackingEnabled, enableTrackAllocation,
                         isRestrictedBackupMode || !normalMode, app.isPersistent(),
                         new Configuration(getGlobalConfiguration()), app.compat,
@@ -6603,16 +6251,6 @@
                 finishBooting ? 1 : 0, enableScreen ? 1 : 0));
     }
 
-    void enableScreenAfterBoot() {
-        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
-                SystemClock.uptimeMillis());
-        mWindowManager.enableScreenAfterBoot();
-
-        synchronized (this) {
-            updateEventDispatchingLocked();
-        }
-    }
-
     @Override
     public void showBootMessage(final CharSequence msg, final boolean always) {
         if (Binder.getCallingUid() != myUid()) {
@@ -6760,7 +6398,7 @@
         }
 
         if (enableScreen) {
-            enableScreenAfterBoot();
+            mAtmInternal.enableScreenAfterBoot(mBooted);
         }
     }
 
@@ -7469,105 +7107,6 @@
         throw new SecurityException(msg);
     }
 
-    /**
-     * Determine if UID is holding permissions required to access {@link Uri} in
-     * the given {@link ProviderInfo}. Final permission checking is always done
-     * in {@link ContentProvider}.
-     */
-    private final boolean checkHoldingPermissionsLocked(
-            IPackageManager pm, ProviderInfo pi, GrantUri grantUri, int uid, final int modeFlags) {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                "checkHoldingPermissionsLocked: uri=" + grantUri + " uid=" + uid);
-        if (UserHandle.getUserId(uid) != grantUri.sourceUserId) {
-            if (ActivityManager.checkComponentPermission(INTERACT_ACROSS_USERS, uid, -1, true)
-                    != PERMISSION_GRANTED) {
-                return false;
-            }
-        }
-        return checkHoldingPermissionsInternalLocked(pm, pi, grantUri, uid, modeFlags, true);
-    }
-
-    private final boolean checkHoldingPermissionsInternalLocked(IPackageManager pm, ProviderInfo pi,
-            GrantUri grantUri, int uid, final int modeFlags, boolean considerUidPermissions) {
-        if (pi.applicationInfo.uid == uid) {
-            return true;
-        } else if (!pi.exported) {
-            return false;
-        }
-
-        boolean readMet = (modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
-        boolean writeMet = (modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
-        try {
-            // check if target holds top-level <provider> permissions
-            if (!readMet && pi.readPermission != null && considerUidPermissions
-                    && (pm.checkUidPermission(pi.readPermission, uid) == PERMISSION_GRANTED)) {
-                readMet = true;
-            }
-            if (!writeMet && pi.writePermission != null && considerUidPermissions
-                    && (pm.checkUidPermission(pi.writePermission, uid) == PERMISSION_GRANTED)) {
-                writeMet = true;
-            }
-
-            // track if unprotected read/write is allowed; any denied
-            // <path-permission> below removes this ability
-            boolean allowDefaultRead = pi.readPermission == null;
-            boolean allowDefaultWrite = pi.writePermission == null;
-
-            // check if target holds any <path-permission> that match uri
-            final PathPermission[] pps = pi.pathPermissions;
-            if (pps != null) {
-                final String path = grantUri.uri.getPath();
-                int i = pps.length;
-                while (i > 0 && (!readMet || !writeMet)) {
-                    i--;
-                    PathPermission pp = pps[i];
-                    if (pp.match(path)) {
-                        if (!readMet) {
-                            final String pprperm = pp.getReadPermission();
-                            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                                    "Checking read perm for " + pprperm + " for " + pp.getPath()
-                                    + ": match=" + pp.match(path)
-                                    + " check=" + pm.checkUidPermission(pprperm, uid));
-                            if (pprperm != null) {
-                                if (considerUidPermissions && pm.checkUidPermission(pprperm, uid)
-                                        == PERMISSION_GRANTED) {
-                                    readMet = true;
-                                } else {
-                                    allowDefaultRead = false;
-                                }
-                            }
-                        }
-                        if (!writeMet) {
-                            final String ppwperm = pp.getWritePermission();
-                            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                                    "Checking write perm " + ppwperm + " for " + pp.getPath()
-                                    + ": match=" + pp.match(path)
-                                    + " check=" + pm.checkUidPermission(ppwperm, uid));
-                            if (ppwperm != null) {
-                                if (considerUidPermissions && pm.checkUidPermission(ppwperm, uid)
-                                        == PERMISSION_GRANTED) {
-                                    writeMet = true;
-                                } else {
-                                    allowDefaultWrite = false;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            // grant unprotected <provider> read/write, if not blocked by
-            // <path-permission> above
-            if (allowDefaultRead) readMet = true;
-            if (allowDefaultWrite) writeMet = true;
-
-        } catch (RemoteException e) {
-            return false;
-        }
-
-        return readMet && writeMet;
-    }
-
     public boolean isAppStartModeDisabled(int uid, String packageName) {
         synchronized (this) {
             return getAppStartModeLocked(uid, packageName, 0, -1, false, true, false)
@@ -7719,6 +7258,20 @@
                 || mPendingTempWhitelist.indexOfKey(uid) >= 0;
     }
 
+    /**
+     * @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on
+     * the whitelist
+     */
+    String getPendingTempWhitelistTagForUidLocked(int uid) {
+        final PendingTempWhitelist ptw = mPendingTempWhitelist.get(uid);
+        return ptw != null ? ptw.tag : null;
+    }
+
+    @VisibleForTesting
+    boolean isActivityStartsLoggingEnabled() {
+        return mConstants.mFlagActivityStartsLoggingEnabled;
+    }
+
     private ProviderInfo getProviderInfoLocked(String authority, int userHandle, int pmFlags) {
         ProviderInfo pi = null;
         ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userHandle);
@@ -7741,67 +7294,6 @@
                 grantEphemeralAccess(userId, intent, targetAppId, ephemeralAppId);
     }
 
-    @GuardedBy("this")
-    private UriPermission findUriPermissionLocked(int targetUid, GrantUri grantUri) {
-        final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
-        if (targetUris != null) {
-            return targetUris.get(grantUri);
-        }
-        return null;
-    }
-
-    @GuardedBy("this")
-    private UriPermission findOrCreateUriPermissionLocked(String sourcePkg,
-            String targetPkg, int targetUid, GrantUri grantUri) {
-        ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
-        if (targetUris == null) {
-            targetUris = Maps.newArrayMap();
-            mGrantedUriPermissions.put(targetUid, targetUris);
-        }
-
-        UriPermission perm = targetUris.get(grantUri);
-        if (perm == null) {
-            perm = new UriPermission(sourcePkg, targetPkg, targetUid, grantUri);
-            targetUris.put(grantUri, perm);
-        }
-
-        return perm;
-    }
-
-    @GuardedBy("this")
-    private final boolean checkUriPermissionLocked(GrantUri grantUri, int uid,
-            final int modeFlags) {
-        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
-        final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
-                : UriPermission.STRENGTH_OWNED;
-
-        // Root gets to do everything.
-        if (uid == 0) {
-            return true;
-        }
-
-        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
-        if (perms == null) return false;
-
-        // First look for exact match
-        final UriPermission exactPerm = perms.get(grantUri);
-        if (exactPerm != null && exactPerm.getStrength(modeFlags) >= minStrength) {
-            return true;
-        }
-
-        // No exact match, look for prefixes
-        final int N = perms.size();
-        for (int i = 0; i < N; i++) {
-            final UriPermission perm = perms.valueAt(i);
-            if (perm.uri.prefix && grantUri.uri.isPathPrefixMatch(perm.uri.uri)
-                    && perm.getStrength(modeFlags) >= minStrength) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
     /**
      * @param uri This uri must NOT contain an embedded userId.
      * @param userId The userId in which the uri is to be resolved.
@@ -7823,395 +7315,8 @@
         if (pid == MY_PID) {
             return PackageManager.PERMISSION_GRANTED;
         }
-        synchronized (this) {
-            return checkUriPermissionLocked(new GrantUri(userId, uri, false), uid, modeFlags)
-                    ? PackageManager.PERMISSION_GRANTED
-                    : PackageManager.PERMISSION_DENIED;
-        }
-    }
-
-    /**
-     * Check if the targetPkg can be granted permission to access uri by
-     * the callingUid using the given modeFlags.  Throws a security exception
-     * if callingUid is not allowed to do this.  Returns the uid of the target
-     * if the URI permission grant should be performed; returns -1 if it is not
-     * needed (for example targetPkg already has permission to access the URI).
-     * If you already know the uid of the target, you can supply it in
-     * lastTargetUid else set that to -1.
-     */
-    @GuardedBy("this")
-    int checkGrantUriPermissionLocked(int callingUid, String targetPkg, GrantUri grantUri,
-            final int modeFlags, int lastTargetUid) {
-        if (!Intent.isAccessUriMode(modeFlags)) {
-            return -1;
-        }
-
-        if (targetPkg != null) {
-            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                    "Checking grant " + targetPkg + " permission to " + grantUri);
-        }
-
-        final IPackageManager pm = AppGlobals.getPackageManager();
-
-        // If this is not a content: uri, we can't do anything with it.
-        if (!ContentResolver.SCHEME_CONTENT.equals(grantUri.uri.getScheme())) {
-            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                    "Can't grant URI permission for non-content URI: " + grantUri);
-            return -1;
-        }
-
-        // Bail early if system is trying to hand out permissions directly; it
-        // must always grant permissions on behalf of someone explicit.
-        final int callingAppId = UserHandle.getAppId(callingUid);
-        if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
-            if ("com.android.settings.files".equals(grantUri.uri.getAuthority())) {
-                // Exempted authority for
-                // 1. cropping user photos and sharing a generated license html
-                //    file in Settings app
-                // 2. sharing a generated license html file in TvSettings app
-            } else {
-                Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"
-                        + " grant to " + grantUri + "; use startActivityAsCaller() instead");
-                return -1;
-            }
-        }
-
-        final String authority = grantUri.uri.getAuthority();
-        final ProviderInfo pi = getProviderInfoLocked(authority, grantUri.sourceUserId,
-                MATCH_DEBUG_TRIAGED_MISSING);
-        if (pi == null) {
-            Slog.w(TAG, "No content provider found for permission check: " +
-                    grantUri.uri.toSafeString());
-            return -1;
-        }
-
-        int targetUid = lastTargetUid;
-        if (targetUid < 0 && targetPkg != null) {
-            try {
-                targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
-                        UserHandle.getUserId(callingUid));
-                if (targetUid < 0) {
-                    if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                            "Can't grant URI permission no uid for: " + targetPkg);
-                    return -1;
-                }
-            } catch (RemoteException ex) {
-                return -1;
-            }
-        }
-
-        // If we're extending a persistable grant, then we always need to create
-        // the grant data structure so that take/release APIs work
-        if ((modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) {
-            return targetUid;
-        }
-
-        if (targetUid >= 0) {
-            // First...  does the target actually need this permission?
-            if (checkHoldingPermissionsLocked(pm, pi, grantUri, targetUid, modeFlags)) {
-                // No need to grant the target this permission.
-                if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                        "Target " + targetPkg + " already has full permission to " + grantUri);
-                return -1;
-            }
-        } else {
-            // First...  there is no target package, so can anyone access it?
-            boolean allowed = pi.exported;
-            if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
-                if (pi.readPermission != null) {
-                    allowed = false;
-                }
-            }
-            if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
-                if (pi.writePermission != null) {
-                    allowed = false;
-                }
-            }
-            if (pi.pathPermissions != null) {
-                final int N = pi.pathPermissions.length;
-                for (int i=0; i<N; i++) {
-                    if (pi.pathPermissions[i] != null
-                            && pi.pathPermissions[i].match(grantUri.uri.getPath())) {
-                        if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
-                            if (pi.pathPermissions[i].getReadPermission() != null) {
-                                allowed = false;
-                            }
-                        }
-                        if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
-                            if (pi.pathPermissions[i].getWritePermission() != null) {
-                                allowed = false;
-                            }
-                        }
-                        break;
-                    }
-                }
-            }
-            if (allowed) {
-                return -1;
-            }
-        }
-
-        /* There is a special cross user grant if:
-         * - The target is on another user.
-         * - Apps on the current user can access the uri without any uid permissions.
-         * In this case, we grant a uri permission, even if the ContentProvider does not normally
-         * grant uri permissions.
-         */
-        boolean specialCrossUserGrant = UserHandle.getUserId(targetUid) != grantUri.sourceUserId
-                && checkHoldingPermissionsInternalLocked(pm, pi, grantUri, callingUid,
-                modeFlags, false /*without considering the uid permissions*/);
-
-        // Second...  is the provider allowing granting of URI permissions?
-        if (!specialCrossUserGrant) {
-            if (!pi.grantUriPermissions) {
-                throw new SecurityException("Provider " + pi.packageName
-                        + "/" + pi.name
-                        + " does not allow granting of Uri permissions (uri "
-                        + grantUri + ")");
-            }
-            if (pi.uriPermissionPatterns != null) {
-                final int N = pi.uriPermissionPatterns.length;
-                boolean allowed = false;
-                for (int i=0; i<N; i++) {
-                    if (pi.uriPermissionPatterns[i] != null
-                            && pi.uriPermissionPatterns[i].match(grantUri.uri.getPath())) {
-                        allowed = true;
-                        break;
-                    }
-                }
-                if (!allowed) {
-                    throw new SecurityException("Provider " + pi.packageName
-                            + "/" + pi.name
-                            + " does not allow granting of permission to path of Uri "
-                            + grantUri);
-                }
-            }
-        }
-
-        // Third...  does the caller itself have permission to access
-        // this uri?
-        if (!checkHoldingPermissionsLocked(pm, pi, grantUri, callingUid, modeFlags)) {
-            // Require they hold a strong enough Uri permission
-            if (!checkUriPermissionLocked(grantUri, callingUid, modeFlags)) {
-                if (android.Manifest.permission.MANAGE_DOCUMENTS.equals(pi.readPermission)) {
-                    throw new SecurityException(
-                            "UID " + callingUid + " does not have permission to " + grantUri
-                                    + "; you could obtain access using ACTION_OPEN_DOCUMENT "
-                                    + "or related APIs");
-                } else {
-                    throw new SecurityException(
-                            "UID " + callingUid + " does not have permission to " + grantUri);
-                }
-            }
-        }
-        return targetUid;
-    }
-
-    /**
-     * @param uri This uri must NOT contain an embedded userId.
-     * @param userId The userId in which the uri is to be resolved.
-     */
-    @Override
-    public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri,
-            final int modeFlags, int userId) {
-        enforceNotIsolatedCaller("checkGrantUriPermission");
-        synchronized(this) {
-            return checkGrantUriPermissionLocked(callingUid, targetPkg,
-                    new GrantUri(userId, uri, false), modeFlags, -1);
-        }
-    }
-
-    @GuardedBy("this")
-    void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, GrantUri grantUri,
-            final int modeFlags, UriPermissionOwner owner) {
-        if (!Intent.isAccessUriMode(modeFlags)) {
-            return;
-        }
-
-        // So here we are: the caller has the assumed permission
-        // to the uri, and the target doesn't.  Let's now give this to
-        // the target.
-
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                "Granting " + targetPkg + "/" + targetUid + " permission to " + grantUri);
-
-        final String authority = grantUri.uri.getAuthority();
-        final ProviderInfo pi = getProviderInfoLocked(authority, grantUri.sourceUserId,
-                MATCH_DEBUG_TRIAGED_MISSING);
-        if (pi == null) {
-            Slog.w(TAG, "No content provider found for grant: " + grantUri.toSafeString());
-            return;
-        }
-
-        if ((modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0) {
-            grantUri.prefix = true;
-        }
-        final UriPermission perm = findOrCreateUriPermissionLocked(
-                pi.packageName, targetPkg, targetUid, grantUri);
-        perm.grantModes(modeFlags, owner);
-    }
-
-    @GuardedBy("this")
-    void grantUriPermissionLocked(int callingUid, String targetPkg, GrantUri grantUri,
-            final int modeFlags, UriPermissionOwner owner, int targetUserId) {
-        if (targetPkg == null) {
-            throw new NullPointerException("targetPkg");
-        }
-        int targetUid;
-        final IPackageManager pm = AppGlobals.getPackageManager();
-        try {
-            targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING, targetUserId);
-        } catch (RemoteException ex) {
-            return;
-        }
-
-        targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, grantUri, modeFlags,
-                targetUid);
-        if (targetUid < 0) {
-            return;
-        }
-
-        grantUriPermissionUncheckedLocked(targetUid, targetPkg, grantUri, modeFlags,
-                owner);
-    }
-
-    static class NeededUriGrants extends ArrayList<GrantUri> {
-        final String targetPkg;
-        final int targetUid;
-        final int flags;
-
-        NeededUriGrants(String targetPkg, int targetUid, int flags) {
-            this.targetPkg = targetPkg;
-            this.targetUid = targetUid;
-            this.flags = flags;
-        }
-
-        void writeToProto(ProtoOutputStream proto, long fieldId) {
-            long token = proto.start(fieldId);
-            proto.write(NeededUriGrantsProto.TARGET_PACKAGE, targetPkg);
-            proto.write(NeededUriGrantsProto.TARGET_UID, targetUid);
-            proto.write(NeededUriGrantsProto.FLAGS, flags);
-
-            final int N = this.size();
-            for (int i=0; i<N; i++) {
-                this.get(i).writeToProto(proto, NeededUriGrantsProto.GRANTS);
-            }
-            proto.end(token);
-        }
-    }
-
-    /**
-     * Like checkGrantUriPermissionLocked, but takes an Intent.
-     */
-    @GuardedBy("this")
-    NeededUriGrants checkGrantUriPermissionFromIntentLocked(int callingUid,
-            String targetPkg, Intent intent, int mode, NeededUriGrants needed, int targetUserId) {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                "Checking URI perm to data=" + (intent != null ? intent.getData() : null)
-                + " clip=" + (intent != null ? intent.getClipData() : null)
-                + " from " + intent + "; flags=0x"
-                + Integer.toHexString(intent != null ? intent.getFlags() : 0));
-
-        if (targetPkg == null) {
-            throw new NullPointerException("targetPkg");
-        }
-
-        if (intent == null) {
-            return null;
-        }
-        Uri data = intent.getData();
-        ClipData clip = intent.getClipData();
-        if (data == null && clip == null) {
-            return null;
-        }
-        // Default userId for uris in the intent (if they don't specify it themselves)
-        int contentUserHint = intent.getContentUserHint();
-        if (contentUserHint == UserHandle.USER_CURRENT) {
-            contentUserHint = UserHandle.getUserId(callingUid);
-        }
-        final IPackageManager pm = AppGlobals.getPackageManager();
-        int targetUid;
-        if (needed != null) {
-            targetUid = needed.targetUid;
-        } else {
-            try {
-                targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
-                        targetUserId);
-            } catch (RemoteException ex) {
-                return null;
-            }
-            if (targetUid < 0) {
-                if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                        "Can't grant URI permission no uid for: " + targetPkg
-                        + " on user " + targetUserId);
-                return null;
-            }
-        }
-        if (data != null) {
-            GrantUri grantUri = GrantUri.resolve(contentUserHint, data);
-            targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, grantUri, mode,
-                    targetUid);
-            if (targetUid > 0) {
-                if (needed == null) {
-                    needed = new NeededUriGrants(targetPkg, targetUid, mode);
-                }
-                needed.add(grantUri);
-            }
-        }
-        if (clip != null) {
-            for (int i=0; i<clip.getItemCount(); i++) {
-                Uri uri = clip.getItemAt(i).getUri();
-                if (uri != null) {
-                    GrantUri grantUri = GrantUri.resolve(contentUserHint, uri);
-                    targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, grantUri, mode,
-                            targetUid);
-                    if (targetUid > 0) {
-                        if (needed == null) {
-                            needed = new NeededUriGrants(targetPkg, targetUid, mode);
-                        }
-                        needed.add(grantUri);
-                    }
-                } else {
-                    Intent clipIntent = clip.getItemAt(i).getIntent();
-                    if (clipIntent != null) {
-                        NeededUriGrants newNeeded = checkGrantUriPermissionFromIntentLocked(
-                                callingUid, targetPkg, clipIntent, mode, needed, targetUserId);
-                        if (newNeeded != null) {
-                            needed = newNeeded;
-                        }
-                    }
-                }
-            }
-        }
-
-        return needed;
-    }
-
-    /**
-     * Like grantUriPermissionUncheckedLocked, but takes an Intent.
-     */
-    @GuardedBy("this")
-    void grantUriPermissionUncheckedFromIntentLocked(NeededUriGrants needed,
-            UriPermissionOwner owner) {
-        if (needed != null) {
-            for (int i=0; i<needed.size(); i++) {
-                GrantUri grantUri = needed.get(i);
-                grantUriPermissionUncheckedLocked(needed.targetUid, needed.targetPkg,
-                        grantUri, needed.flags, owner);
-            }
-        }
-    }
-
-    @GuardedBy("this")
-    void grantUriPermissionFromIntentLocked(int callingUid,
-            String targetPkg, Intent intent, UriPermissionOwner owner, int targetUserId) {
-        NeededUriGrants needed = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg,
-                intent, intent != null ? intent.getFlags() : 0, null, targetUserId);
-        if (needed == null) {
-            return;
-        }
-
-        grantUriPermissionUncheckedFromIntentLocked(needed, owner);
+        return mUgmInternal.checkUriPermission(new GrantUri(userId, uri, false), uid, modeFlags)
+                ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED;
     }
 
     /**
@@ -8242,113 +7347,11 @@
                     | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
                     | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
 
-            grantUriPermissionLocked(r.uid, targetPkg, grantUri, modeFlags, null,
+            mUgmInternal.grantUriPermission(r.uid, targetPkg, grantUri, modeFlags, null,
                     UserHandle.getUserId(r.uid));
         }
     }
 
-    @GuardedBy("this")
-    void removeUriPermissionIfNeededLocked(UriPermission perm) {
-        if (perm.modeFlags == 0) {
-            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
-                    perm.targetUid);
-            if (perms != null) {
-                if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                        "Removing " + perm.targetUid + " permission to " + perm.uri);
-
-                perms.remove(perm.uri);
-                if (perms.isEmpty()) {
-                    mGrantedUriPermissions.remove(perm.targetUid);
-                }
-            }
-        }
-    }
-
-    @GuardedBy("this")
-    private void revokeUriPermissionLocked(String targetPackage, int callingUid, GrantUri grantUri,
-            final int modeFlags) {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                "Revoking all granted permissions to " + grantUri);
-
-        final IPackageManager pm = AppGlobals.getPackageManager();
-        final String authority = grantUri.uri.getAuthority();
-        final ProviderInfo pi = getProviderInfoLocked(authority, grantUri.sourceUserId,
-                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
-        if (pi == null) {
-            Slog.w(TAG, "No content provider found for permission revoke: "
-                    + grantUri.toSafeString());
-            return;
-        }
-
-        // Does the caller have this permission on the URI?
-        if (!checkHoldingPermissionsLocked(pm, pi, grantUri, callingUid, modeFlags)) {
-            // If they don't have direct access to the URI, then revoke any
-            // ownerless URI permissions that have been granted to them.
-            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
-            if (perms != null) {
-                boolean persistChanged = false;
-                for (int i = perms.size()-1; i >= 0; i--) {
-                    final UriPermission perm = perms.valueAt(i);
-                    if (targetPackage != null && !targetPackage.equals(perm.targetPkg)) {
-                        continue;
-                    }
-                    if (perm.uri.sourceUserId == grantUri.sourceUserId
-                            && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
-                        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                                "Revoking non-owned " + perm.targetUid
-                                + " permission to " + perm.uri);
-                        persistChanged |= perm.revokeModes(
-                                modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
-                        if (perm.modeFlags == 0) {
-                            perms.removeAt(i);
-                        }
-                    }
-                }
-                if (perms.isEmpty()) {
-                    mGrantedUriPermissions.remove(callingUid);
-                }
-                if (persistChanged) {
-                    schedulePersistUriGrants();
-                }
-            }
-            return;
-        }
-
-        boolean persistChanged = false;
-
-        // Go through all of the permissions and remove any that match.
-        for (int i = mGrantedUriPermissions.size()-1; i >= 0; i--) {
-            final int targetUid = mGrantedUriPermissions.keyAt(i);
-            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
-
-            for (int j = perms.size()-1; j >= 0; j--) {
-                final UriPermission perm = perms.valueAt(j);
-                if (targetPackage != null && !targetPackage.equals(perm.targetPkg)) {
-                    continue;
-                }
-                if (perm.uri.sourceUserId == grantUri.sourceUserId
-                        && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
-                    if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                                "Revoking " + perm.targetUid + " permission to " + perm.uri);
-                    persistChanged |= perm.revokeModes(
-                            modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION,
-                            targetPackage == null);
-                    if (perm.modeFlags == 0) {
-                        perms.removeAt(j);
-                    }
-                }
-            }
-
-            if (perms.isEmpty()) {
-                mGrantedUriPermissions.removeAt(i);
-            }
-        }
-
-        if (persistChanged) {
-            schedulePersistUriGrants();
-        }
-    }
-
     /**
      * @param uri This uri must NOT contain an embedded userId.
      * @param userId The userId in which the uri is to be resolved.
@@ -8382,497 +7385,11 @@
                 return;
             }
 
-            revokeUriPermissionLocked(targetPackage, r.uid, new GrantUri(userId, uri, false),
+            mUgmInternal.revokeUriPermission(targetPackage, r.uid, new GrantUri(userId, uri, false),
                     modeFlags);
         }
     }
 
-    /**
-     * Remove any {@link UriPermission} granted <em>from</em> or <em>to</em> the
-     * given package.
-     *
-     * @param packageName Package name to match, or {@code null} to apply to all
-     *            packages.
-     * @param userHandle User to match, or {@link UserHandle#USER_ALL} to apply
-     *            to all users.
-     * @param persistable If persistable grants should be removed.
-     * @param targetOnly When {@code true}, only remove permissions where the app is the target,
-     * not source.
-     */
-    @GuardedBy("this")
-    private void removeUriPermissionsForPackageLocked(
-            String packageName, int userHandle, boolean persistable, boolean targetOnly) {
-        if (userHandle == UserHandle.USER_ALL && packageName == null) {
-            throw new IllegalArgumentException("Must narrow by either package or user");
-        }
-
-        boolean persistChanged = false;
-
-        int N = mGrantedUriPermissions.size();
-        for (int i = 0; i < N; i++) {
-            final int targetUid = mGrantedUriPermissions.keyAt(i);
-            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
-
-            // Only inspect grants matching user
-            if (userHandle == UserHandle.USER_ALL
-                    || userHandle == UserHandle.getUserId(targetUid)) {
-                for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
-                    final UriPermission perm = it.next();
-
-                    // Only inspect grants matching package
-                    if (packageName == null || (!targetOnly && perm.sourcePkg.equals(packageName))
-                            || perm.targetPkg.equals(packageName)) {
-                        // Hacky solution as part of fixing a security bug; ignore
-                        // grants associated with DownloadManager so we don't have
-                        // to immediately launch it to regrant the permissions
-                        if (Downloads.Impl.AUTHORITY.equals(perm.uri.uri.getAuthority())
-                                && !persistable) continue;
-
-                        persistChanged |= perm.revokeModes(persistable
-                                ? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
-
-                        // Only remove when no modes remain; any persisted grants
-                        // will keep this alive.
-                        if (perm.modeFlags == 0) {
-                            it.remove();
-                        }
-                    }
-                }
-
-                if (perms.isEmpty()) {
-                    mGrantedUriPermissions.remove(targetUid);
-                    N--;
-                    i--;
-                }
-            }
-        }
-
-        if (persistChanged) {
-            schedulePersistUriGrants();
-        }
-    }
-
-    @Override
-    public IBinder newUriPermissionOwner(String name) {
-        enforceNotIsolatedCaller("newUriPermissionOwner");
-        synchronized(this) {
-            UriPermissionOwner owner = new UriPermissionOwner(this, name);
-            return owner.getExternalTokenLocked();
-        }
-    }
-
-    /**
-     * @param uri This uri must NOT contain an embedded userId.
-     * @param sourceUserId The userId in which the uri is to be resolved.
-     * @param targetUserId The userId of the app that receives the grant.
-     */
-    @Override
-    public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, Uri uri,
-            final int modeFlags, int sourceUserId, int targetUserId) {
-        targetUserId = mUserController.handleIncomingUser(Binder.getCallingPid(),
-                Binder.getCallingUid(), targetUserId, false, ALLOW_FULL_ONLY,
-                "grantUriPermissionFromOwner", null);
-        synchronized(this) {
-            UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
-            if (owner == null) {
-                throw new IllegalArgumentException("Unknown owner: " + token);
-            }
-            if (fromUid != Binder.getCallingUid()) {
-                if (Binder.getCallingUid() != myUid()) {
-                    // Only system code can grant URI permissions on behalf
-                    // of other users.
-                    throw new SecurityException("nice try");
-                }
-            }
-            if (targetPkg == null) {
-                throw new IllegalArgumentException("null target");
-            }
-            if (uri == null) {
-                throw new IllegalArgumentException("null uri");
-            }
-
-            grantUriPermissionLocked(fromUid, targetPkg, new GrantUri(sourceUserId, uri, false),
-                    modeFlags, owner, targetUserId);
-        }
-    }
-
-    /**
-     * @param uri This uri must NOT contain an embedded userId.
-     * @param userId The userId in which the uri is to be resolved.
-     */
-    @Override
-    public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId) {
-        synchronized(this) {
-            UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
-            if (owner == null) {
-                throw new IllegalArgumentException("Unknown owner: " + token);
-            }
-
-            if (uri == null) {
-                owner.removeUriPermissionsLocked(mode);
-            } else {
-                final boolean prefix = (mode & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0;
-                owner.removeUriPermissionLocked(new GrantUri(userId, uri, prefix), mode);
-            }
-        }
-    }
-
-    private void schedulePersistUriGrants() {
-        if (!mHandler.hasMessages(PERSIST_URI_GRANTS_MSG)) {
-            mHandler.sendMessageDelayed(mHandler.obtainMessage(PERSIST_URI_GRANTS_MSG),
-                    10 * DateUtils.SECOND_IN_MILLIS);
-        }
-    }
-
-    private void writeGrantedUriPermissions() {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "writeGrantedUriPermissions()");
-
-        final long startTime = SystemClock.uptimeMillis();
-
-        // Snapshot permissions so we can persist without lock
-        ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
-        synchronized (this) {
-            final int size = mGrantedUriPermissions.size();
-            for (int i = 0; i < size; i++) {
-                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
-                for (UriPermission perm : perms.values()) {
-                    if (perm.persistedModeFlags != 0) {
-                        persist.add(perm.snapshot());
-                    }
-                }
-            }
-        }
-
-        FileOutputStream fos = null;
-        try {
-            fos = mGrantFile.startWrite(startTime);
-
-            XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, StandardCharsets.UTF_8.name());
-            out.startDocument(null, true);
-            out.startTag(null, TAG_URI_GRANTS);
-            for (UriPermission.Snapshot perm : persist) {
-                out.startTag(null, TAG_URI_GRANT);
-                writeIntAttribute(out, ATTR_SOURCE_USER_ID, perm.uri.sourceUserId);
-                writeIntAttribute(out, ATTR_TARGET_USER_ID, perm.targetUserId);
-                out.attribute(null, ATTR_SOURCE_PKG, perm.sourcePkg);
-                out.attribute(null, ATTR_TARGET_PKG, perm.targetPkg);
-                out.attribute(null, ATTR_URI, String.valueOf(perm.uri.uri));
-                writeBooleanAttribute(out, ATTR_PREFIX, perm.uri.prefix);
-                writeIntAttribute(out, ATTR_MODE_FLAGS, perm.persistedModeFlags);
-                writeLongAttribute(out, ATTR_CREATED_TIME, perm.persistedCreateTime);
-                out.endTag(null, TAG_URI_GRANT);
-            }
-            out.endTag(null, TAG_URI_GRANTS);
-            out.endDocument();
-
-            mGrantFile.finishWrite(fos);
-        } catch (IOException e) {
-            if (fos != null) {
-                mGrantFile.failWrite(fos);
-            }
-        }
-    }
-
-    @GuardedBy("this")
-    private void readGrantedUriPermissionsLocked() {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "readGrantedUriPermissions()");
-
-        final long now = System.currentTimeMillis();
-
-        FileInputStream fis = null;
-        try {
-            fis = mGrantFile.openRead();
-            final XmlPullParser in = Xml.newPullParser();
-            in.setInput(fis, StandardCharsets.UTF_8.name());
-
-            int type;
-            while ((type = in.next()) != END_DOCUMENT) {
-                final String tag = in.getName();
-                if (type == START_TAG) {
-                    if (TAG_URI_GRANT.equals(tag)) {
-                        final int sourceUserId;
-                        final int targetUserId;
-                        final int userHandle = readIntAttribute(in,
-                                ATTR_USER_HANDLE, UserHandle.USER_NULL);
-                        if (userHandle != UserHandle.USER_NULL) {
-                            // For backwards compatibility.
-                            sourceUserId = userHandle;
-                            targetUserId = userHandle;
-                        } else {
-                            sourceUserId = readIntAttribute(in, ATTR_SOURCE_USER_ID);
-                            targetUserId = readIntAttribute(in, ATTR_TARGET_USER_ID);
-                        }
-                        final String sourcePkg = in.getAttributeValue(null, ATTR_SOURCE_PKG);
-                        final String targetPkg = in.getAttributeValue(null, ATTR_TARGET_PKG);
-                        final Uri uri = Uri.parse(in.getAttributeValue(null, ATTR_URI));
-                        final boolean prefix = readBooleanAttribute(in, ATTR_PREFIX);
-                        final int modeFlags = readIntAttribute(in, ATTR_MODE_FLAGS);
-                        final long createdTime = readLongAttribute(in, ATTR_CREATED_TIME, now);
-
-                        // Sanity check that provider still belongs to source package
-                        // Both direct boot aware and unaware packages are fine as we
-                        // will do filtering at query time to avoid multiple parsing.
-                        final ProviderInfo pi = getProviderInfoLocked(
-                                uri.getAuthority(), sourceUserId, MATCH_DIRECT_BOOT_AWARE
-                                        | MATCH_DIRECT_BOOT_UNAWARE);
-                        if (pi != null && sourcePkg.equals(pi.packageName)) {
-                            int targetUid = -1;
-                            try {
-                                targetUid = AppGlobals.getPackageManager().getPackageUid(
-                                        targetPkg, MATCH_UNINSTALLED_PACKAGES, targetUserId);
-                            } catch (RemoteException e) {
-                            }
-                            if (targetUid != -1) {
-                                final UriPermission perm = findOrCreateUriPermissionLocked(
-                                        sourcePkg, targetPkg, targetUid,
-                                        new GrantUri(sourceUserId, uri, prefix));
-                                perm.initPersistedModes(modeFlags, createdTime);
-                            }
-                        } else {
-                            Slog.w(TAG, "Persisted grant for " + uri + " had source " + sourcePkg
-                                    + " but instead found " + pi);
-                        }
-                    }
-                }
-            }
-        } catch (FileNotFoundException e) {
-            // Missing grants is okay
-        } catch (IOException e) {
-            Slog.wtf(TAG, "Failed reading Uri grants", e);
-        } catch (XmlPullParserException e) {
-            Slog.wtf(TAG, "Failed reading Uri grants", e);
-        } finally {
-            IoUtils.closeQuietly(fis);
-        }
-    }
-
-    /**
-     * @param uri This uri must NOT contain an embedded userId.
-     * @param toPackage Name of package whose uri is being granted to (if {@code null}, uses
-     * calling uid)
-     * @param userId The userId in which the uri is to be resolved.
-     */
-    @Override
-    public void takePersistableUriPermission(Uri uri, final int modeFlags,
-            @Nullable String toPackage, int userId) {
-        final int uid;
-        if (toPackage != null) {
-            enforceCallingPermission(android.Manifest.permission.FORCE_PERSISTABLE_URI_PERMISSIONS,
-                    "takePersistableUriPermission");
-            uid = mPackageManagerInt.getPackageUid(toPackage, 0, userId);
-        } else {
-            enforceNotIsolatedCaller("takePersistableUriPermission");
-            uid = Binder.getCallingUid();
-        }
-
-        Preconditions.checkFlagsArgument(modeFlags,
-                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
-        synchronized (this) {
-            boolean persistChanged = false;
-            GrantUri grantUri = new GrantUri(userId, uri, false);
-
-            UriPermission exactPerm = findUriPermissionLocked(uid, grantUri);
-            UriPermission prefixPerm = findUriPermissionLocked(uid,
-                    new GrantUri(userId, uri, true));
-
-            final boolean exactValid = (exactPerm != null)
-                    && ((modeFlags & exactPerm.persistableModeFlags) == modeFlags);
-            final boolean prefixValid = (prefixPerm != null)
-                    && ((modeFlags & prefixPerm.persistableModeFlags) == modeFlags);
-
-            if (!(exactValid || prefixValid)) {
-                throw new SecurityException("No persistable permission grants found for UID "
-                        + uid + " and Uri " + grantUri.toSafeString());
-            }
-
-            if (exactValid) {
-                persistChanged |= exactPerm.takePersistableModes(modeFlags);
-            }
-            if (prefixValid) {
-                persistChanged |= prefixPerm.takePersistableModes(modeFlags);
-            }
-
-            persistChanged |= maybePrunePersistedUriGrantsLocked(uid);
-
-            if (persistChanged) {
-                schedulePersistUriGrants();
-            }
-        }
-    }
-
-    /**
-     * @param uri This uri must NOT contain an embedded userId.
-     * @param toPackage Name of the target package whose uri is being released (if {@code null},
-     * uses calling uid)
-     * @param userId The userId in which the uri is to be resolved.
-     */
-    @Override
-    public void releasePersistableUriPermission(Uri uri, final int modeFlags,
-            @Nullable String toPackage, int userId) {
-
-        final int uid;
-        if (toPackage != null) {
-            enforceCallingPermission(android.Manifest.permission.FORCE_PERSISTABLE_URI_PERMISSIONS,
-                    "releasePersistableUriPermission");
-            uid = mPackageManagerInt.getPackageUid(toPackage, 0, userId);
-        } else {
-            enforceNotIsolatedCaller("releasePersistableUriPermission");
-            uid = Binder.getCallingUid();
-        }
-
-        Preconditions.checkFlagsArgument(modeFlags,
-                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
-        synchronized (this) {
-            boolean persistChanged = false;
-
-            UriPermission exactPerm = findUriPermissionLocked(uid,
-                    new GrantUri(userId, uri, false));
-            UriPermission prefixPerm = findUriPermissionLocked(uid,
-                    new GrantUri(userId, uri, true));
-            if (exactPerm == null && prefixPerm == null && toPackage == null) {
-                throw new SecurityException("No permission grants found for UID " + uid
-                        + " and Uri " + uri.toSafeString());
-            }
-
-            if (exactPerm != null) {
-                persistChanged |= exactPerm.releasePersistableModes(modeFlags);
-                removeUriPermissionIfNeededLocked(exactPerm);
-            }
-            if (prefixPerm != null) {
-                persistChanged |= prefixPerm.releasePersistableModes(modeFlags);
-                removeUriPermissionIfNeededLocked(prefixPerm);
-            }
-
-            if (persistChanged) {
-                schedulePersistUriGrants();
-            }
-        }
-    }
-
-    /**
-     * Prune any older {@link UriPermission} for the given UID until outstanding
-     * persisted grants are below {@link #MAX_PERSISTED_URI_GRANTS}.
-     *
-     * @return if any mutations occured that require persisting.
-     */
-    @GuardedBy("this")
-    private boolean maybePrunePersistedUriGrantsLocked(int uid) {
-        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
-        if (perms == null) return false;
-        if (perms.size() < MAX_PERSISTED_URI_GRANTS) return false;
-
-        final ArrayList<UriPermission> persisted = Lists.newArrayList();
-        for (UriPermission perm : perms.values()) {
-            if (perm.persistedModeFlags != 0) {
-                persisted.add(perm);
-            }
-        }
-
-        final int trimCount = persisted.size() - MAX_PERSISTED_URI_GRANTS;
-        if (trimCount <= 0) return false;
-
-        Collections.sort(persisted, new UriPermission.PersistedTimeComparator());
-        for (int i = 0; i < trimCount; i++) {
-            final UriPermission perm = persisted.get(i);
-
-            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
-                    "Trimming grant created at " + perm.persistedCreateTime);
-
-            perm.releasePersistableModes(~0);
-            removeUriPermissionIfNeededLocked(perm);
-        }
-
-        return true;
-    }
-
-    @Override
-    public ParceledListSlice<android.content.UriPermission> getPersistedUriPermissions(
-            String packageName, boolean incoming) {
-        enforceNotIsolatedCaller("getPersistedUriPermissions");
-        Preconditions.checkNotNull(packageName, "packageName");
-
-        final int callingUid = Binder.getCallingUid();
-        final int callingUserId = UserHandle.getUserId(callingUid);
-        final IPackageManager pm = AppGlobals.getPackageManager();
-        try {
-            final int packageUid = pm.getPackageUid(packageName,
-                    MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, callingUserId);
-            if (packageUid != callingUid) {
-                throw new SecurityException(
-                        "Package " + packageName + " does not belong to calling UID " + callingUid);
-            }
-        } catch (RemoteException e) {
-            throw new SecurityException("Failed to verify package name ownership");
-        }
-
-        final ArrayList<android.content.UriPermission> result = Lists.newArrayList();
-        synchronized (this) {
-            if (incoming) {
-                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
-                        callingUid);
-                if (perms == null) {
-                    Slog.w(TAG, "No permission grants found for " + packageName);
-                } else {
-                    for (int j = 0; j < perms.size(); j++) {
-                        final UriPermission perm = perms.valueAt(j);
-                        if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) {
-                            result.add(perm.buildPersistedPublicApiObject());
-                        }
-                    }
-                }
-            } else {
-                final int size = mGrantedUriPermissions.size();
-                for (int i = 0; i < size; i++) {
-                    final ArrayMap<GrantUri, UriPermission> perms =
-                            mGrantedUriPermissions.valueAt(i);
-                    for (int j = 0; j < perms.size(); j++) {
-                        final UriPermission perm = perms.valueAt(j);
-                        if (packageName.equals(perm.sourcePkg) && perm.persistedModeFlags != 0) {
-                            result.add(perm.buildPersistedPublicApiObject());
-                        }
-                    }
-                }
-            }
-        }
-        return new ParceledListSlice<android.content.UriPermission>(result);
-    }
-
-    @Override
-    public ParceledListSlice<GrantedUriPermission> getGrantedUriPermissions(
-            @Nullable String packageName, int userId) {
-        enforceCallingPermission(android.Manifest.permission.GET_APP_GRANTED_URI_PERMISSIONS,
-                "getGrantedUriPermissions");
-
-        final List<GrantedUriPermission> result = new ArrayList<>();
-        synchronized (this) {
-            final int size = mGrantedUriPermissions.size();
-            for (int i = 0; i < size; i++) {
-                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
-                for (int j = 0; j < perms.size(); j++) {
-                    final UriPermission perm = perms.valueAt(j);
-                    if ((packageName == null || packageName.equals(perm.targetPkg))
-                            && perm.targetUserId == userId
-                            && perm.persistedModeFlags != 0) {
-                        result.add(perm.buildGrantedUriPermission());
-                    }
-                }
-            }
-        }
-        return new ParceledListSlice<>(result);
-    }
-
-    @Override
-    public void clearGrantedUriPermissions(String packageName, int userId) {
-        enforceCallingPermission(android.Manifest.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS,
-                "clearGrantedUriPermissions");
-        synchronized(this) {
-            removeUriPermissionsForPackageLocked(packageName, userId, true, true);
-        }
-    }
-
     @Override
     public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
         synchronized (this) {
@@ -9194,7 +7711,8 @@
             // Looking for cross-user grants before enforcing the typical cross-users permissions
             int tmpTargetUserId = mUserController.unsafeConvertIncomingUser(userId);
             if (tmpTargetUserId != UserHandle.getUserId(callingUid)) {
-                if (checkAuthorityGrants(callingUid, cpi, tmpTargetUserId, checkUser)) {
+                if (mUgmInternal.checkAuthorityGrants(
+                        callingUid, cpi, tmpTargetUserId, checkUser)) {
                     return null;
                 }
                 checkedGrants = true;
@@ -9240,7 +7758,8 @@
                 }
             }
         }
-        if (!checkedGrants && checkAuthorityGrants(callingUid, cpi, userId, checkUser)) {
+        if (!checkedGrants
+                && mUgmInternal.checkAuthorityGrants(callingUid, cpi, userId, checkUser)) {
             return null;
         }
 
@@ -9259,43 +7778,9 @@
         return msg;
     }
 
-    /**
-     * Returns if the ContentProvider has granted a uri to callingUid
-     */
-    boolean checkAuthorityGrants(int callingUid, ProviderInfo cpi, int userId, boolean checkUser) {
-        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
-        if (perms != null) {
-            for (int i=perms.size()-1; i>=0; i--) {
-                GrantUri grantUri = perms.keyAt(i);
-                if (grantUri.sourceUserId == userId || !checkUser) {
-                    if (matchesProvider(grantUri.uri, cpi)) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns true if the uri authority is one of the authorities specified in the provider.
-     */
-    boolean matchesProvider(Uri uri, ProviderInfo cpi) {
-        String uriAuth = uri.getAuthority();
-        String cpiAuth = cpi.authority;
-        if (cpiAuth.indexOf(';') == -1) {
-            return cpiAuth.equals(uriAuth);
-        }
-        String[] cpiAuths = cpiAuth.split(";");
-        int length = cpiAuths.length;
-        for (int i = 0; i < length; i++) {
-            if (cpiAuths[i].equals(uriAuth)) return true;
-        }
-        return false;
-    }
-
     ContentProviderConnection incProviderCountLocked(ProcessRecord r,
-            final ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
+            final ContentProviderRecord cpr, IBinder externalProcessToken, int callingUid,
+            String callingTag, boolean stable) {
         if (r != null) {
             for (int i=0; i<r.conProviders.size(); i++) {
                 ContentProviderConnection conn = r.conProviders.get(i);
@@ -9316,6 +7801,7 @@
                 }
             }
             ContentProviderConnection conn = new ContentProviderConnection(cpr, r);
+            conn.startAssociationIfNeeded();
             if (stable) {
                 conn.stableCount = 1;
                 conn.numStableIncs = 1;
@@ -9326,10 +7812,10 @@
             cpr.connections.add(conn);
             r.conProviders.add(conn);
             startAssociationLocked(r.uid, r.processName, r.curProcState,
-                    cpr.uid, cpr.name, cpr.info.processName);
+                    cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
             return conn;
         }
-        cpr.addExternalProcessHandleLocked(externalProcessToken);
+        cpr.addExternalProcessHandleLocked(externalProcessToken, callingUid, callingTag);
         return null;
     }
 
@@ -9348,6 +7834,7 @@
                 conn.unstableCount--;
             }
             if (conn.stableCount == 0 && conn.unstableCount == 0) {
+                conn.stopAssociation();
                 cpr.connections.remove(conn);
                 conn.client.conProviders.remove(conn);
                 if (conn.client.setProcState < PROCESS_STATE_LAST_ACTIVITY) {
@@ -9358,7 +7845,8 @@
                         cpr.proc.lastProviderTime = SystemClock.uptimeMillis();
                     }
                 }
-                stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.name);
+                stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid,
+                        cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
                 return true;
             }
             return false;
@@ -9404,7 +7892,8 @@
     }
 
     private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
-            String name, IBinder token, boolean stable, int userId) {
+            String name, IBinder token, int callingUid, String callingTag, boolean stable,
+            int userId) {
         ContentProviderRecord cpr;
         ContentProviderConnection conn = null;
         ProviderInfo cpi = null;
@@ -9497,7 +7986,7 @@
 
                 // In this case the provider instance already exists, so we can
                 // return it right away.
-                conn = incProviderCountLocked(r, cpr, token, stable);
+                conn = incProviderCountLocked(r, cpr, token, callingUid, callingTag, stable);
                 if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
                     if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
                         // If this is a perceptible app accessing the provider,
@@ -9624,10 +8113,8 @@
                     // If permissions need a review before any of the app components can run,
                     // we return no provider and launch a review activity if the calling app
                     // is in the foreground.
-                    if (mPermissionReviewRequired) {
-                        if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) {
-                            return null;
-                        }
+                    if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) {
+                        return null;
                     }
 
                     try {
@@ -9741,7 +8228,7 @@
                 }
 
                 mProviderMap.putProviderByName(name, cpr);
-                conn = incProviderCountLocked(r, cpr, token, stable);
+                conn = incProviderCountLocked(r, cpr, token, callingUid, callingTag, stable);
                 if (conn != null) {
                     conn.waiting = true;
                 }
@@ -9852,21 +8339,23 @@
         }
         // The incoming user check is now handled in checkContentProviderPermissionLocked() to deal
         // with cross-user grant.
-        return getContentProviderImpl(caller, name, null, stable, userId);
+        return getContentProviderImpl(caller, name, null, Binder.getCallingUid(), null, stable,
+                userId);
     }
 
     public ContentProviderHolder getContentProviderExternal(
-            String name, int userId, IBinder token) {
+            String name, int userId, IBinder token, String tag) {
         enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
             "Do not have permission in call getContentProviderExternal()");
         userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                 userId, false, ALLOW_FULL_ONLY, "getContentProvider", null);
-        return getContentProviderExternalUnchecked(name, token, userId);
+        return getContentProviderExternalUnchecked(name, token, Binder.getCallingUid(),
+                tag != null ? tag : "*external*", userId);
     }
 
     private ContentProviderHolder getContentProviderExternalUnchecked(String name,
-            IBinder token, int userId) {
-        return getContentProviderImpl(null, name, token, true, userId);
+            IBinder token, int callingUid, String callingTag, int userId) {
+        return getContentProviderImpl(null, name, token, callingUid, callingTag, true, userId);
     }
 
     /**
@@ -9988,7 +8477,7 @@
                     }
                     synchronized (dst) {
                         dst.provider = src.provider;
-                        dst.proc = r;
+                        dst.setProcess(r);
                         dst.notifyAll();
                     }
                     updateOomAdjLocked(r, true);
@@ -10156,7 +8645,7 @@
 
         mConstants.start(mContext.getContentResolver());
         mCoreSettingsObserver = new CoreSettingsObserver(this);
-        mFontScaleSettingObserver = new FontScaleSettingObserver();
+        mActivityTaskManager.installSystemProviders();
         mDevelopmentSettingsObserver = new DevelopmentSettingsObserver();
         GlobalSettingsToPropertiesMapper.start(mContext.getContentResolver());
 
@@ -10258,7 +8747,8 @@
         }
         ContentProviderHolder holder = null;
         try {
-            holder = getContentProviderExternalUnchecked(name, null, userId);
+            holder = getContentProviderExternalUnchecked(name, null, callingUid,
+                    "*getmimetype*", userId);
             if (holder != null) {
                 return holder.provider.getType(uri);
             }
@@ -10306,7 +8796,6 @@
     final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
             boolean isolated, int isolatedUid) {
         String proc = customProcess != null ? customProcess : info.processName;
-        BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         final int userId = UserHandle.getUserId(info.uid);
         int uid = info.uid;
         if (isolated) {
@@ -10345,7 +8834,7 @@
             StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, info.uid, uid,
                     StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
         }
-        final ProcessRecord r = new ProcessRecord(this, stats, info, proc, uid);
+        final ProcessRecord r = new ProcessRecord(this, info, proc, uid);
         if (!mBooted && !mBooting
                 && userId == UserHandle.USER_SYSTEM
                 && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
@@ -10424,6 +8913,7 @@
                 abiOverride);
     }
 
+    @GuardedBy("this")
     final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
             boolean disableHiddenApiChecks, String abiOverride) {
         ProcessRecord app;
@@ -10473,7 +8963,8 @@
         final int userId = UserHandle.getCallingUserId();
         final Uri uri = Uri.parse(uriString);
         String name = uri.getAuthority();
-        ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null, userId);
+        ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null,
+                Binder.getCallingUid(), "*opencontent*", userId);
         ParcelFileDescriptor pfd = null;
         if (cph != null) {
             // We record the binder invoker's uid in thread-local storage before
@@ -10502,20 +8993,6 @@
         return pfd;
     }
 
-    // Actually is sleeping or shutting down or whatever else in the future
-    // is an inactive state.
-    boolean isSleepingOrShuttingDownLocked() {
-        return isSleepingLocked() || mShuttingDown;
-    }
-
-    boolean isShuttingDownLocked() {
-        return mShuttingDown;
-    }
-
-    boolean isSleepingLocked() {
-        return mSleeping;
-    }
-
     void reportGlobalUsageEventLocked(int event) {
         mUsageStatsService.reportEvent("android", mUserController.getCurrentUserId(), event);
         int[] profiles = mUserController.getCurrentProfileIds();
@@ -10543,58 +9020,12 @@
                 mServices.updateScreenStateLocked(isAwake);
                 reportCurWakefulnessUsageEventLocked();
                 mActivityTaskManager.onScreenAwakeChanged(isAwake);
+                mOomAdjProfiler.onWakefulnessChanged(wakefulness);
             }
             updateOomAdjLocked();
         }
     }
 
-    @GuardedBy("this")
-    void finishRunningVoiceLocked() {
-        if (mRunningVoice != null) {
-            mRunningVoice = null;
-            mVoiceWakeLock.release();
-            updateSleepIfNeededLocked();
-        }
-    }
-
-    void startTimeTrackingFocusedActivityLocked() {
-        final ActivityRecord resumedActivity = mStackSupervisor.getResumedActivityLocked();
-        if (!mSleeping && mCurAppTimeTracker != null && resumedActivity != null) {
-            mCurAppTimeTracker.start(resumedActivity.packageName);
-        }
-    }
-
-    @GuardedBy("this")
-    void updateSleepIfNeededLocked() {
-        final boolean shouldSleep = !mStackSupervisor.hasAwakeDisplay();
-        final boolean wasSleeping = mSleeping;
-
-        if (!shouldSleep) {
-            // If wasSleeping is true, we need to wake up activity manager state from when
-            // we started sleeping. In either case, we need to apply the sleep tokens, which
-            // will wake up stacks or put them to sleep as appropriate.
-            if (wasSleeping) {
-                mSleeping = false;
-                startTimeTrackingFocusedActivityLocked();
-                mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
-                mStackSupervisor.comeOutOfSleepIfNeededLocked();
-            }
-            mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */);
-            if (wasSleeping) {
-                updateOomAdjLocked();
-            }
-        } else if (!mSleeping && shouldSleep) {
-            mSleeping = true;
-            if (mCurAppTimeTracker != null) {
-                mCurAppTimeTracker.stop();
-            }
-            mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
-            mStackSupervisor.goingToSleepLocked();
-            updateResumedAppTrace(null /* resumed */);
-            updateOomAdjLocked();
-        }
-    }
-
     @Override
     public void notifyCleartextNetwork(int uid, byte[] firstPacket) {
         mHandler.obtainMessage(NOTIFY_CLEARTEXT_NETWORK_MSG, uid, 0, firstPacket).sendToTarget();
@@ -10608,14 +9039,7 @@
                     + android.Manifest.permission.SHUTDOWN);
         }
 
-        boolean timedout = false;
-
-        synchronized(this) {
-            mShuttingDown = true;
-            mStackSupervisor.prepareForShutdownLocked();
-            updateEventDispatchingLocked();
-            timedout = mStackSupervisor.shutdownLocked(timeout);
-        }
+        final boolean timedout = mAtmInternal.shuttingDown(mBooted, timeout);
 
         mAppOpsService.shutdown();
         if (mUsageStatsService != null) {
@@ -10630,24 +9054,6 @@
         return timedout;
     }
 
-    @GuardedBy("this")
-    void startRunningVoiceLocked(IVoiceInteractionSession session, int targetUid) {
-        Slog.d(TAG, "<<<  startRunningVoiceLocked()");
-        mVoiceWakeLock.setWorkSource(new WorkSource(targetUid));
-        if (mRunningVoice == null || mRunningVoice.asBinder() != session.asBinder()) {
-            boolean wasRunningVoice = mRunningVoice != null;
-            mRunningVoice = session;
-            if (!wasRunningVoice) {
-                mVoiceWakeLock.acquire();
-                updateSleepIfNeededLocked();
-            }
-        }
-    }
-
-    private void updateEventDispatchingLocked() {
-        mWindowManager.setEventDispatching(mBooted && !mShuttingDown);
-    }
-
     @Override
     public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing,
             int secondaryDisplayShowing) {
@@ -10877,7 +9283,8 @@
                 if (proc == null) {
                     throw new SecurityException("Unknown process: " + callingPid);
                 }
-                if (proc.instr == null || proc.instr.mUiAutomationConnection == null) {
+                if (proc.getActiveInstrumentation() == null
+                        || proc.getActiveInstrumentation().mUiAutomationConnection == null) {
                     throw new SecurityException("Only an instrumentation process "
                             + "with a UiAutomation can call setUserIsMonkey");
                 }
@@ -11000,89 +9407,6 @@
                 ActivityManager.BUGREPORT_OPTION_WIFI);
     }
 
-
-    public static long getInputDispatchingTimeoutLocked(ActivityRecord r) {
-        if (r == null || !r.hasProcess()) {
-            return KEY_DISPATCHING_TIMEOUT;
-        }
-        return getInputDispatchingTimeoutLocked((ProcessRecord) r.app.mOwner);
-    }
-
-    public static long getInputDispatchingTimeoutLocked(ProcessRecord r) {
-        if (r != null && (r.instr != null || r.usingWrapper)) {
-            return INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
-        }
-        return KEY_DISPATCHING_TIMEOUT;
-    }
-
-    @Override
-    public long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
-        if (checkCallingPermission(android.Manifest.permission.FILTER_EVENTS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires permission "
-                    + android.Manifest.permission.FILTER_EVENTS);
-        }
-        ProcessRecord proc;
-        long timeout;
-        synchronized (this) {
-            synchronized (mPidsSelfLocked) {
-                proc = mPidsSelfLocked.get(pid);
-            }
-            timeout = getInputDispatchingTimeoutLocked(proc);
-        }
-
-        if (inputDispatchingTimedOut(proc, null, null, aboveSystem, reason)) {
-            return -1;
-        }
-
-        return timeout;
-    }
-
-    /**
-     * Handle input dispatching timeouts.
-     * Returns whether input dispatching should be aborted or not.
-     */
-    public boolean inputDispatchingTimedOut(final ProcessRecord proc,
-            final ActivityRecord activity, final ActivityRecord parent,
-            final boolean aboveSystem, String reason) {
-        if (checkCallingPermission(android.Manifest.permission.FILTER_EVENTS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires permission "
-                    + android.Manifest.permission.FILTER_EVENTS);
-        }
-
-        final String annotation;
-        if (reason == null) {
-            annotation = "Input dispatching timed out";
-        } else {
-            annotation = "Input dispatching timed out (" + reason + ")";
-        }
-
-        if (proc != null) {
-            synchronized (this) {
-                if (proc.debugging) {
-                    return false;
-                }
-
-                if (proc.instr != null) {
-                    Bundle info = new Bundle();
-                    info.putString("shortMsg", "keyDispatchingTimedOut");
-                    info.putString("longMsg", annotation);
-                    finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info);
-                    return true;
-                }
-            }
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mAppErrors.appNotResponding(proc, activity, parent, aboveSystem, annotation);
-                }
-            });
-        }
-
-        return true;
-    }
-
     public void registerProcessObserver(IProcessObserver observer) {
         enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                 "registerProcessObserver()");
@@ -11699,7 +10023,7 @@
                     proc.notCachedSinceIdle = true;
                     proc.initialIdlePss = 0;
                     proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, null,
-                            mTestPssMode, isSleepingLocked(), now);
+                            mTestPssMode, mAtmInternal.isSleeping(), now);
                 }
             }
         }
@@ -11853,9 +10177,7 @@
 
         retrieveSettings();
         final int currentUserId = mUserController.getCurrentUserId();
-        synchronized (this) {
-            readGrantedUriPermissionsLocked();
-        }
+        mUgmInternal.onSystemReady();
 
         final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
         if (pmi != null) {
@@ -11899,19 +10221,7 @@
             }
             startHomeActivityLocked(currentUserId, "systemReady");
 
-            try {
-                if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
-                    Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
-                            + " data partition or your device will be unstable.");
-                    mUiHandler.obtainMessage(SHOW_UID_ERROR_UI_MSG).sendToTarget();
-                }
-            } catch (RemoteException e) {
-            }
-
-            if (!Build.isBuildConsistent()) {
-                Slog.e(TAG, "Build fingerprint is not consistent, warning user");
-                mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_UI_MSG).sendToTarget();
-            }
+            mAtmInternal.showSystemReadyErrorDialogsIfNeeded();
 
             long ident = Binder.clearCallingIdentity();
             try {
@@ -11941,7 +10251,7 @@
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
-            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
             mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
 
             BinderInternal.nSetBinderProxyCountWatermarks(6000,5500);
@@ -11952,6 +10262,7 @@
                         public void onLimitReached(int uid) {
                             Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid "
                                     + Process.myUid());
+                            BinderProxy.dumpProxyDebugInfo();
                             if (uid == Process.SYSTEM_UID) {
                                 Slog.i(TAG, "Skipping kill (uid is SYSTEM)");
                             } else {
@@ -12039,6 +10350,15 @@
                         : StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__UNKNOWN
         );
 
+        final int relaunchReason = r == null ? ActivityRecord.RELAUNCH_REASON_NONE
+                        : r.getWindowProcessController().computeRelaunchReason();
+        final String relaunchReasonString = ActivityRecord.relaunchReasonToString(relaunchReason);
+        if (crashInfo.crashTag == null) {
+            crashInfo.crashTag = relaunchReasonString;
+        } else {
+            crashInfo.crashTag = crashInfo.crashTag + " " + relaunchReasonString;
+        }
+
         addErrorToDropBox(eventType, r, processName, null, null, null, null, null, crashInfo);
 
         mAppErrors.crashApplication(r, crashInfo);
@@ -12365,6 +10685,9 @@
         if (Debug.isDebuggerConnected()) {
             sb.append("Debugger: Connected\n");
         }
+        if (crashInfo != null && crashInfo.crashTag != null && !crashInfo.crashTag.isEmpty()) {
+            sb.append("Crash-Tag: ").append(crashInfo.crashTag).append("\n");
+        }
         sb.append("\n");
 
         // Do the rest in a worker thread to avoid blocking the caller on I/O
@@ -12497,6 +10820,7 @@
         return imp;
     }
 
+    @GuardedBy("this")
     private void fillInProcMemInfoLocked(ProcessRecord app,
             ActivityManager.RunningAppProcessInfo outInfo,
             int clientTargetSdk) {
@@ -12639,19 +10963,122 @@
                 this, in, out, err, args, callback, resultReceiver);
     }
 
-    SleepToken acquireSleepToken(String tag, int displayId) {
-        synchronized (this) {
-            final SleepToken token = mStackSupervisor.createSleepTokenLocked(tag, displayId);
-            updateSleepIfNeededLocked();
-            return token;
-        }
-    }
-
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         PriorityDump.dump(mPriorityDumper, fd, pw, args);
     }
 
+    private void dumpEverything(FileDescriptor fd, PrintWriter pw, String[] args, int opti,
+            boolean dumpAll, String dumpPackage, boolean dumpClient, boolean dumpNormalPriority,
+            int dumpAppId) {
+
+        ActiveServices.ServiceDumper sdumper;
+
+        synchronized(this) {
+            mConstants.dump(pw);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+
+            }
+            dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            if (dumpAll || dumpPackage != null) {
+                dumpBroadcastStatsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+                pw.println();
+                if (dumpAll) {
+                    pw.println("-------------------------------------------------------------------------------");
+                }
+            }
+            dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpPermissionsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+            pw.println();
+            sdumper = mServices.newServiceDumperLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+            if (!dumpClient) {
+                if (dumpAll) {
+                    pw.println("-------------------------------------------------------------------------------");
+                }
+                sdumper.dumpLocked();
+            }
+        }
+        // We drop the lock here because we can't call dumpWithClient() with the lock held;
+        // if the caller wants a consistent state for the !dumpClient case, it can call this
+        // method with the lock held.
+        if (dumpClient) {
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            sdumper.dumpWithClient();
+        }
+        synchronized(this) {
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            if (mActivityTaskManager.getRecentTasks() != null) {
+                mActivityTaskManager.getRecentTasks().dump(pw, dumpAll, dumpPackage);
+            }
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpLastANRLocked(pw);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpActivityStarterLocked(pw, dumpPackage);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpActivityContainersLocked(pw);
+            // Activities section is dumped as part of the Critical priority dump. Exclude the
+            // section if priority is Normal.
+            if (!dumpNormalPriority) {
+                pw.println();
+                if (dumpAll) {
+                    pw.println("-------------------------------------------------------------------------------");
+                }
+                dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+            }
+            if (mAssociations.size() > 0) {
+                pw.println();
+                if (dumpAll) {
+                    pw.println("-------------------------------------------------------------------------------");
+                }
+                dumpAssociationsLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+            }
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage, dumpAppId);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            mOomAdjProfiler.dump(pw);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpBinderProxies(pw);
+        }
+    }
+
     /**
      * Wrapper function to print out debug data filtered by specified arguments.
     */
@@ -12810,8 +11237,7 @@
                 }
             } else if ("binder-proxies".equals(cmd)) {
                 if (opti >= args.length) {
-                    dumpBinderProxiesCounts(pw, BinderInternal.nGetBinderProxyPerUidCounts(),
-                            "Counts of Binder Proxies held by SYSTEM");
+                    dumpBinderProxies(pw);
                 } else {
                     String uid = args[opti];
                     opti++;
@@ -12964,166 +11390,19 @@
         // No piece of data specified, dump everything.
         if (dumpCheckinFormat) {
             dumpBroadcastStatsCheckinLocked(fd, pw, args, opti, dumpCheckin, dumpPackage);
-        } else if (dumpClient) {
-            ActiveServices.ServiceDumper sdumper;
-            synchronized (this) {
-                mConstants.dump(pw);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                if (dumpAll || dumpPackage != null) {
-                    dumpBroadcastStatsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                    pw.println();
-                    if (dumpAll) {
-                        pw.println("-------------------------------------------------------------------------------");
-                    }
-                }
-                dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpPermissionsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                sdumper = mServices.newServiceDumperLocked(fd, pw, args, opti, dumpAll,
-                        dumpPackage);
-            }
-            sdumper.dumpWithClient();
-            pw.println();
-            synchronized (this) {
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                if (mActivityTaskManager.getRecentTasks() != null) {
-                    mActivityTaskManager.getRecentTasks().dump(pw, dumpAll, dumpPackage);
-                }
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpLastANRLocked(pw);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpActivityStarterLocked(pw, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpActivityContainersLocked(pw);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
-                if (mAssociations.size() > 0) {
-                    pw.println();
-                    if (dumpAll) {
-                        pw.println("-------------------------------------------------------------------------------");
-                    }
-                    dumpAssociationsLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
-                }
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage, dumpAppId);
-            }
-
         } else {
-            synchronized (this) {
-                mConstants.dump(pw);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
+            if (dumpClient) {
+                // dumpEverything() will take the lock when needed, and momentarily drop
+                // it for dumping client state.
+                dumpEverything(fd, pw, args, opti, dumpAll, dumpPackage, dumpClient,
+                        dumpNormalPriority, dumpAppId);
+            } else {
+                // Take the lock here, so we get a consistent state for the entire dump;
+                // dumpEverything() will take the lock as well, but that is fine.
+                synchronized(this) {
+                    dumpEverything(fd, pw, args, opti, dumpAll, dumpPackage, dumpClient,
+                            dumpNormalPriority, dumpAppId);
                 }
-                dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                if (dumpAll || dumpPackage != null) {
-                    dumpBroadcastStatsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                    pw.println();
-                    if (dumpAll) {
-                        pw.println("-------------------------------------------------------------------------------");
-                    }
-                }
-                dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpPermissionsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                mServices.newServiceDumperLocked(fd, pw, args, opti, dumpAll, dumpPackage)
-                        .dumpLocked();
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                if (mActivityTaskManager.getRecentTasks() != null) {
-                    mActivityTaskManager.getRecentTasks().dump(pw, dumpAll, dumpPackage);
-                }
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpLastANRLocked(pw);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpActivityStarterLocked(pw, dumpPackage);
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpActivityContainersLocked(pw);
-                // Activities section is dumped as part of the Critical priority dump. Exclude the
-                // section if priority is Normal.
-                if (!dumpNormalPriority){
-                    pw.println();
-                    if (dumpAll) {
-                        pw.println("-------------------------------------------------------------------------------");
-                    }
-                    dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
-                }
-                if (mAssociations.size() > 0) {
-                    pw.println();
-                    if (dumpAll) {
-                        pw.println("-------------------------------------------------------------------------------");
-                    }
-                    dumpAssociationsLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
-                }
-                pw.println();
-                if (dumpAll) {
-                    pw.println("-------------------------------------------------------------------------------");
-                }
-                dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage, dumpAppId);
             }
         }
         Binder.restoreCallingIdentity(origId);
@@ -13148,12 +11427,13 @@
 
         final File[] files = new File(ANR_TRACE_DIR).listFiles();
         if (ArrayUtils.isEmpty(files)) {
+            pw.println("  <no ANR has occurred since boot>");
             return;
         }
         // Find the latest file.
         File latest = null;
         for (File f : files) {
-            if (latest == null || latest.getName().compareTo(f.getName()) < 0) {
+            if ((latest == null) || (latest.lastModified() < f.lastModified())) {
                 latest = f;
             }
         }
@@ -13198,8 +11478,8 @@
         boolean needSep = printedAnything;
 
         boolean printed = ActivityStackSupervisor.printThisActivity(pw,
-                mStackSupervisor.getResumedActivityLocked(),
-                dumpPackage, needSep, "  ResumedActivity: ");
+                mStackSupervisor.getTopResumedActivity(),  dumpPackage, needSep,
+                "  ResumedActivity: ");
         if (printed) {
             printedAnything = true;
             needSep = false;
@@ -13343,7 +11623,17 @@
         return printed;
     }
 
-    boolean dumpBinderProxiesCounts(PrintWriter pw, SparseIntArray counts, String header) {
+    void dumpBinderProxyInterfaceCounts(PrintWriter pw, String header) {
+        final BinderProxy.InterfaceCount[] proxyCounts = BinderProxy.getSortedInterfaceCounts(50);
+
+        pw.println(header);
+        for (int i = 0; i < proxyCounts.length; i++) {
+            pw.println("    #" + (i + 1) + ": " + proxyCounts[i]);
+        }
+    }
+
+    boolean dumpBinderProxiesCounts(PrintWriter pw, String header) {
+        SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts();
         if(counts != null) {
             pw.println(header);
             for (int i = 0; i < counts.size(); i++) {
@@ -13371,6 +11661,13 @@
         return false;
     }
 
+    void dumpBinderProxies(PrintWriter pw) {
+        dumpBinderProxyInterfaceCounts(pw,
+                "Top proxy interface names held by SYSTEM");
+        dumpBinderProxiesCounts(pw,
+                "Counts of Binder Proxies held by SYSTEM");
+    }
+
     @GuardedBy("this")
     void dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage, int dumpAppId) {
@@ -13594,7 +11891,8 @@
         }
         if (dumpAll) {
             if (dumpPackage == null) {
-                pw.println("  mConfigWillChange: " + mActivityTaskManager.getFocusedStack().mConfigWillChange);
+                pw.println("  mConfigWillChange: "
+                        + mActivityTaskManager.getTopDisplayFocusedStack().mConfigWillChange);
             }
             if (mCompatModePackages.getPackages().size() > 0) {
                 boolean printed = false;
@@ -13670,14 +11968,7 @@
         if (dumpPackage == null) {
             pw.println("  mWakefulness="
                     + PowerManagerInternal.wakefulnessToString(mWakefulness));
-            pw.println("  mSleepTokens=" + mStackSupervisor.mSleepTokens);
-            pw.println("  mSleeping=" + mSleeping);
-            pw.println("  mShuttingDown=" + mShuttingDown + " mTestPssMode=" + mTestPssMode);
-            if (mRunningVoice != null) {
-                pw.println("  mRunningVoice=" + mRunningVoice);
-                pw.println("  mVoiceWakeLock" + mVoiceWakeLock);
-            }
-            mActivityTaskManager.dumpVrControllerLocked(pw);
+            mActivityTaskManager.dumpSleepStates(pw, mTestPssMode);
         }
         if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
                 || mOrigWaitForDebugger) {
@@ -13692,8 +11983,8 @@
                         + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
             }
         }
-        if (mCurAppTimeTracker != null) {
-            mCurAppTimeTracker.dumpWithHeader(pw, "  ", true);
+        if (mActivityTaskManager.mCurAppTimeTracker != null) {
+            mActivityTaskManager.mCurAppTimeTracker.dumpWithHeader(pw, "  ", true);
         }
         if (mMemWatchProcesses.getMap().size() > 0) {
             pw.println("  Mem watch processes:");
@@ -13972,7 +12263,7 @@
         if (dumpPackage == null) {
             mUserController.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.USER_CONTROLLER);
             getGlobalConfiguration().writeToProto(proto, ActivityManagerServiceDumpProcessesProto.GLOBAL_CONFIGURATION);
-            proto.write(ActivityManagerServiceDumpProcessesProto.CONFIG_WILL_CHANGE, mActivityTaskManager.getFocusedStack().mConfigWillChange);
+            proto.write(ActivityManagerServiceDumpProcessesProto.CONFIG_WILL_CHANGE, mActivityTaskManager.getTopDisplayFocusedStack().mConfigWillChange);
         }
 
         if (mActivityTaskManager.mHomeProcess != null && (dumpPackage == null
@@ -14030,23 +12321,10 @@
             final long sleepToken = proto.start(ActivityManagerServiceDumpProcessesProto.SLEEP_STATUS);
             proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.WAKEFULNESS,
                     PowerManagerInternal.wakefulnessToProtoEnum(mWakefulness));
-            for (SleepToken st : mStackSupervisor.mSleepTokens) {
-                proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEP_TOKENS, st.toString());
-            }
-            proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEPING, mSleeping);
-            proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SHUTTING_DOWN, mShuttingDown);
             proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.TEST_PSS_MODE, mTestPssMode);
             proto.end(sleepToken);
 
-            if (mRunningVoice != null) {
-                final long vrToken = proto.start(ActivityManagerServiceDumpProcessesProto.RUNNING_VOICE);
-                proto.write(ActivityManagerServiceDumpProcessesProto.Voice.SESSION, mRunningVoice.toString());
-                mVoiceWakeLock.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.Voice.WAKELOCK);
-                proto.end(vrToken);
-            }
-
-            mActivityTaskManager.writeVrControllerToProto(
-                    proto, ActivityManagerServiceDumpProcessesProto.VR_CONTROLLER);
+            mActivityTaskManager.writeSleepStateToProto(proto);
         }
 
         if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
@@ -14062,8 +12340,9 @@
             }
         }
 
-        if (mCurAppTimeTracker != null) {
-            mCurAppTimeTracker.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.CURRENT_TRACKER, true);
+        if (mActivityTaskManager.mCurAppTimeTracker != null) {
+            mActivityTaskManager.mCurAppTimeTracker.writeToProto(
+                    proto, ActivityManagerServiceDumpProcessesProto.CURRENT_TRACKER, true);
         }
 
         if (mMemWatchProcesses.getMap().size() > 0) {
@@ -14684,48 +12963,10 @@
     @GuardedBy("this")
     void dumpPermissionsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
-        boolean needSep = false;
-        boolean printedAnything = false;
 
         pw.println("ACTIVITY MANAGER URI PERMISSIONS (dumpsys activity permissions)");
 
-        if (mGrantedUriPermissions.size() > 0) {
-            boolean printed = false;
-            int dumpUid = -2;
-            if (dumpPackage != null) {
-                try {
-                    dumpUid = mContext.getPackageManager().getPackageUidAsUser(dumpPackage,
-                            MATCH_ANY_USER, 0);
-                } catch (NameNotFoundException e) {
-                    dumpUid = -1;
-                }
-            }
-            for (int i=0; i<mGrantedUriPermissions.size(); i++) {
-                int uid = mGrantedUriPermissions.keyAt(i);
-                if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) {
-                    continue;
-                }
-                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
-                if (!printed) {
-                    if (needSep) pw.println();
-                    needSep = true;
-                    pw.println("  Granted Uri Permissions:");
-                    printed = true;
-                    printedAnything = true;
-                }
-                pw.print("  * UID "); pw.print(uid); pw.println(" holds:");
-                for (UriPermission perm : perms.values()) {
-                    pw.print("    "); pw.println(perm);
-                    if (dumpAll) {
-                        perm.dump(pw, "      ");
-                    }
-                }
-            }
-        }
-
-        if (!printedAnything) {
-            pw.println("  (nothing)");
-        }
+        mUgmInternal.dump(pw, dumpAll, dumpPackage);
     }
 
     void dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
@@ -15660,6 +13901,16 @@
                         // Record this for posterity if the process has been stable.
                         r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
                                 reportType, endTime-startTime, r.pkgList.mPkgList);
+                        for (int ipkg = r.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                            ProcessStats.ProcessStateHolder holder = r.pkgList.valueAt(ipkg);
+                            StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED,
+                                    r.info.uid,
+                                    holder.state.getName(),
+                                    holder.state.getPackage(),
+                                    myTotalPss, myTotalUss, myTotalRss, reportType,
+                                    endTime-startTime,
+                                    holder.appVersion);
+                        }
                     }
                 }
 
@@ -16158,6 +14409,15 @@
                     // Record this for posterity if the process has been stable.
                     r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
                             reportType, endTime-startTime, r.pkgList.mPkgList);
+                    for (int ipkg = r.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                        ProcessStats.ProcessStateHolder holder = r.pkgList.valueAt(ipkg);
+                        StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED,
+                                r.info.uid,
+                                holder.state.getName(),
+                                holder.state.getPackage(),
+                                myTotalPss, myTotalUss, myTotalRss, reportType, endTime-startTime,
+                                holder.appVersion);
+                    }
                 }
             }
 
@@ -16427,6 +14687,7 @@
         }
         updateCpuStatsNow();
         long[] memtrackTmp = new long[1];
+        long[] swaptrackTmp = new long[2];
         final List<ProcessCpuTracker.Stats> stats;
         // Get a list of Stats that have vsize > 0
         synchronized (mProcessCpuTracker) {
@@ -16437,12 +14698,13 @@
         final int statsCount = stats.size();
         for (int i = 0; i < statsCount; i++) {
             ProcessCpuTracker.Stats st = stats.get(i);
-            long pss = Debug.getPss(st.pid, null, memtrackTmp);
+            long pss = Debug.getPss(st.pid, swaptrackTmp, memtrackTmp);
             if (pss > 0) {
                 if (infoMap.indexOfKey(st.pid) < 0) {
                     ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid,
                             ProcessList.NATIVE_ADJ, -1, "native", null);
                     mi.pss = pss;
+                    mi.swapPss = swaptrackTmp[1];
                     mi.memtrack = memtrackTmp[0];
                     memInfos.add(mi);
                 }
@@ -16450,14 +14712,17 @@
         }
 
         long totalPss = 0;
+        long totalSwapPss = 0;
         long totalMemtrack = 0;
         for (int i=0, N=memInfos.size(); i<N; i++) {
             ProcessMemInfo mi = memInfos.get(i);
             if (mi.pss == 0) {
-                mi.pss = Debug.getPss(mi.pid, null, memtrackTmp);
+                mi.pss = Debug.getPss(mi.pid, swaptrackTmp, memtrackTmp);
+                mi.swapPss = swaptrackTmp[1];
                 mi.memtrack = memtrackTmp[0];
             }
             totalPss += mi.pss;
+            totalSwapPss += mi.swapPss;
             totalMemtrack += mi.memtrack;
         }
         Collections.sort(memInfos, new Comparator<ProcessMemInfo>() {
@@ -16619,7 +14884,7 @@
         memInfoBuilder.append("\n");
         memInfoBuilder.append("  Lost RAM: ");
         memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb()
-                - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
+                - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
                 - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb()));
         memInfoBuilder.append("\n");
         Slog.i(TAG, "Low on memory:");
@@ -16740,7 +15005,8 @@
                 // clean up this connection, we'll just remove it.
                 cpr.connections.remove(i);
                 if (conn.client.conProviders.remove(conn)) {
-                    stopAssociationLocked(capp.uid, capp.processName, cpr.uid, cpr.name);
+                    stopAssociationLocked(capp.uid, capp.processName, cpr.uid,
+                            cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
                 }
             }
         }
@@ -16816,7 +15082,7 @@
             }
 
             cpr.provider = null;
-            cpr.proc = null;
+            cpr.setProcess(null);
         }
         app.pubProviders.clear();
 
@@ -16831,7 +15097,8 @@
                 ContentProviderConnection conn = app.conProviders.get(i);
                 conn.provider.connections.remove(conn);
                 stopAssociationLocked(app.uid, app.processName, conn.provider.uid,
-                        conn.provider.name);
+                        conn.provider.appInfo.longVersionCode, conn.provider.name,
+                        conn.provider.info.processName);
             }
             app.conProviders.clear();
         }
@@ -17243,12 +15510,6 @@
 
         synchronized(this) {
             // !!! TODO: currently no check here that we're already bound
-            BatteryStatsImpl.Uid.Pkg.Serv ss = null;
-            BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
-            synchronized (stats) {
-                ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
-            }
-
             // Backup agent is now in use, its package can't be stopped.
             try {
                 AppGlobals.getPackageManager().setPackageStoppedState(
@@ -17259,7 +15520,7 @@
                         + app.packageName + ": " + e);
             }
 
-            BackupRecord r = new BackupRecord(ss, app, backupMode);
+            BackupRecord r = new BackupRecord(app, backupMode);
             ComponentName hostingName =
                     (backupMode == ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL)
                             ? new ComponentName(app.packageName, app.backupAgentName)
@@ -18096,13 +16357,13 @@
                                                 intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
 
                                         // Remove all permissions granted from/to this package
-                                        removeUriPermissionsForPackageLocked(ssp, userId, true,
-                                                false);
+                                        mUgmInternal.removeUriPermissionsForPackage(ssp, userId,
+                                                true, false);
 
                                         mActivityTaskManager.getRecentTasks().removeTasksByPackageName(ssp, userId);
 
                                         mServices.forceStopPackageLocked(ssp, userId);
-                                        mAppWarnings.onPackageUninstalled(ssp);
+                                        mAtmInternal.onPackageUninstalled(ssp);
                                         mCompatModePackages.handlePackageUninstalledLocked(ssp);
                                         mBatteryStatsService.notePackageUninstalled(ssp);
                                     }
@@ -18183,7 +16444,7 @@
                     String ssp;
                     if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
                         mCompatModePackages.handlePackageDataClearedLocked(ssp);
-                        mAppWarnings.onPackageDataCleared(ssp);
+                        mAtmInternal.onPackageDataCleared(ssp);
                     }
                     break;
                 }
@@ -18814,7 +17075,7 @@
 
             ProcessRecord app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
                     abiOverride);
-            app.instr = activeInstr;
+            app.setActiveInstrumentation(activeInstr);
             activeInstr.mFinished = false;
             activeInstr.mRunningProcesses.add(app);
             if (!mActiveInstrumentation.contains(activeInstr)) {
@@ -18847,16 +17108,17 @@
     }
 
     void addInstrumentationResultsLocked(ProcessRecord app, Bundle results) {
-        if (app.instr == null) {
+        final ActiveInstrumentation instr = app.getActiveInstrumentation();
+        if (instr == null) {
             Slog.w(TAG, "finishInstrumentation called on non-instrumented: " + app);
             return;
         }
 
-        if (!app.instr.mFinished && results != null) {
-            if (app.instr.mCurResults == null) {
-                app.instr.mCurResults = new Bundle(results);
+        if (!instr.mFinished && results != null) {
+            if (instr.mCurResults == null) {
+                instr.mCurResults = new Bundle(results);
             } else {
-                app.instr.mCurResults.putAll(results);
+                instr.mCurResults.putAll(results);
             }
         }
     }
@@ -18882,35 +17144,38 @@
 
     @GuardedBy("this")
     void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
-        if (app.instr == null) {
+        final ActiveInstrumentation instr = app.getActiveInstrumentation();
+        if (instr == null) {
             Slog.w(TAG, "finishInstrumentation called on non-instrumented: " + app);
             return;
         }
 
-        if (!app.instr.mFinished) {
-            if (app.instr.mWatcher != null) {
-                Bundle finalResults = app.instr.mCurResults;
+        if (!instr.mFinished) {
+            if (instr.mWatcher != null) {
+                Bundle finalResults = instr.mCurResults;
                 if (finalResults != null) {
-                    if (app.instr.mCurResults != null && results != null) {
+                    if (instr.mCurResults != null && results != null) {
                         finalResults.putAll(results);
                     }
                 } else {
                     finalResults = results;
                 }
-                mInstrumentationReporter.reportFinished(app.instr.mWatcher,
-                        app.instr.mClass, resultCode, finalResults);
+                mInstrumentationReporter.reportFinished(instr.mWatcher,
+                        instr.mClass, resultCode, finalResults);
             }
 
             // Can't call out of the system process with a lock held, so post a message.
-            if (app.instr.mUiAutomationConnection != null) {
+            if (instr.mUiAutomationConnection != null) {
+                mAppOpsService.setAppOpsServiceDelegate(null);
+                getPackageManagerInternalLocked().setCheckPermissionDelegate(null);
                 mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
-                        app.instr.mUiAutomationConnection).sendToTarget();
+                        instr.mUiAutomationConnection).sendToTarget();
             }
-            app.instr.mFinished = true;
+            instr.mFinished = true;
         }
 
-        app.instr.removeProcess(app);
-        app.instr = null;
+        instr.removeProcess(app);
+        app.setActiveInstrumentation(null);
 
         forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, false, app.userId,
                 "finished inst");
@@ -18965,13 +17230,9 @@
         return mActivityTaskManager.getFocusedStackInfo();
     }
 
+    @Override
     public Configuration getConfiguration() {
-        Configuration ci;
-        synchronized(this) {
-            ci = new Configuration(getGlobalConfiguration());
-            ci.userSetLocale = false;
-        }
-        return ci;
+        return mActivityTaskManager.getConfiguration();
     }
 
     @Override
@@ -18992,22 +17253,6 @@
         mActivityTaskManager.updatePersistentConfiguration(values, userId);
     }
 
-    private void updateFontScaleIfNeeded(@UserIdInt int userId) {
-        final float scaleFactor = Settings.System.getFloatForUser(mContext.getContentResolver(),
-                FONT_SCALE, 1.0f, userId);
-
-        synchronized (this) {
-            if (getGlobalConfiguration().fontScale == scaleFactor) {
-                return;
-            }
-
-            final Configuration configuration
-                    = mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
-            configuration.fontScale = scaleFactor;
-            mActivityTaskManager.updatePersistentConfiguration(configuration, userId);
-        }
-    }
-
     private void enforceWriteSettingsPermission(String func) {
         int uid = Binder.getCallingUid();
         if (uid == ROOT_UID) {
@@ -19032,29 +17277,6 @@
         return mActivityTaskManager.updateConfiguration(values);
     }
 
-    /**
-     * Decide based on the configuration whether we should show the ANR,
-     * crash, etc dialogs.  The idea is that if there is no affordance to
-     * press the on-screen buttons, or the user experience would be more
-     * greatly impacted than the crash itself, we shouldn't show the dialog.
-     *
-     * A thought: SystemUI might also want to get told about this, the Power
-     * dialog / global actions also might want different behaviors.
-     */
-    void updateShouldShowDialogsLocked(Configuration config) {
-        final boolean inputMethodExists = !(config.keyboard == Configuration.KEYBOARD_NOKEYS
-                                   && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH
-                                   && config.navigation == Configuration.NAVIGATION_NONAV);
-        int modeType = config.uiMode & Configuration.UI_MODE_TYPE_MASK;
-        final boolean uiModeSupportsDialogs = (modeType != Configuration.UI_MODE_TYPE_CAR
-                && !(modeType == Configuration.UI_MODE_TYPE_WATCH && Build.IS_USER)
-                && modeType != Configuration.UI_MODE_TYPE_TELEVISION
-                && modeType != Configuration.UI_MODE_TYPE_VR_HEADSET);
-        final boolean hideDialogsSet = Settings.Global.getInt(mContext.getContentResolver(),
-                HIDE_ERROR_DIALOGS, 0) != 0;
-        mShowDialogs = inputMethodExists && uiModeSupportsDialogs && !hideDialogsSet;
-    }
-
     @Override
     public int getLaunchedFromUid(IBinder activityToken) {
         return mActivityTaskManager.getLaunchedFromUid(activityToken);
@@ -19094,7 +17316,8 @@
     }
 
     Association startAssociationLocked(int sourceUid, String sourceProcess, int sourceState,
-            int targetUid, ComponentName targetComponent, String targetProcess) {
+            int targetUid, long targetVersionCode, ComponentName targetComponent,
+            String targetProcess) {
         if (!mTrackingAssociations) {
             return null;
         }
@@ -19130,7 +17353,7 @@
     }
 
     void stopAssociationLocked(int sourceUid, String sourceProcess, int targetUid,
-            ComponentName targetComponent) {
+            long targetVersionCode, ComponentName targetComponent, String targetProcess) {
         if (!mTrackingAssociations) {
             return;
         }
@@ -19190,6 +17413,129 @@
         }
     }
 
+    private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
+            new ComputeOomAdjWindowCallback();
+
+    private final class ComputeOomAdjWindowCallback
+            implements WindowProcessController.ComputeOomAdjCallback {
+
+        ProcessRecord app;
+        int adj;
+        boolean foregroundActivities;
+        int procState;
+        int schedGroup;
+        int appUid;
+        int logUid;
+        int processStateCurTop;
+
+        void initialize(ProcessRecord app, int adj, boolean foregroundActivities,
+                int procState, int schedGroup, int appUid, int logUid, int processStateCurTop) {
+            this.app = app;
+            this.adj = adj;
+            this.foregroundActivities = foregroundActivities;
+            this.procState = procState;
+            this.schedGroup = schedGroup;
+            this.appUid = appUid;
+            this.logUid = logUid;
+            this.processStateCurTop = processStateCurTop;
+        }
+
+        @Override
+        public void onVisibleActivity() {
+            // App has a visible activity; only upgrade adjustment.
+            if (adj > ProcessList.VISIBLE_APP_ADJ) {
+                adj = ProcessList.VISIBLE_APP_ADJ;
+                app.adjType = "vis-activity";
+                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to vis-activity: " + app);
+                }
+            }
+            if (procState > processStateCurTop) {
+                procState = processStateCurTop;
+                app.adjType = "vis-activity";
+                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                            "Raise procstate to vis-activity (top): " + app);
+                }
+            }
+            if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
+                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+            }
+            app.cached = false;
+            app.empty = false;
+            foregroundActivities = true;
+        }
+
+        @Override
+        public void onPausedActivity() {
+            if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+                app.adjType = "pause-activity";
+                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to pause-activity: "  + app);
+                }
+            }
+            if (procState > processStateCurTop) {
+                procState = processStateCurTop;
+                app.adjType = "pause-activity";
+                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                            "Raise procstate to pause-activity (top): "  + app);
+                }
+            }
+            if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
+                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+            }
+            app.cached = false;
+            app.empty = false;
+            foregroundActivities = true;
+        }
+
+        @Override
+        public void onStoppingActivity(boolean finishing) {
+            if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+                app.adjType = "stop-activity";
+                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                            "Raise adj to stop-activity: "  + app);
+                }
+            }
+
+            // For the process state, we will at this point consider the process to be cached. It
+            // will be cached either as an activity or empty depending on whether the activity is
+            // finishing. We do this so that we can treat the process as cached for purposes of
+            // memory trimming (determining current memory level, trim command to send to process)
+            // since there can be an arbitrary number of stopping processes and they should soon all
+            // go into the cached state.
+            if (!finishing) {
+                if (procState > PROCESS_STATE_LAST_ACTIVITY) {
+                    procState = PROCESS_STATE_LAST_ACTIVITY;
+                    app.adjType = "stop-activity";
+                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                                "Raise procstate to stop-activity: " + app);
+                    }
+                }
+            }
+            app.cached = false;
+            app.empty = false;
+            foregroundActivities = true;
+        }
+
+        @Override
+        public void onOtherActivity() {
+            if (procState > PROCESS_STATE_CACHED_ACTIVITY) {
+                procState = PROCESS_STATE_CACHED_ACTIVITY;
+                app.adjType = "cch-act";
+                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                            "Raise procstate to cached activity: " + app);
+                }
+            }
+        }
+    }
+
     private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
             boolean doingAll, long now) {
         if (mAdjSeq == app.adjSeq) {
@@ -19200,6 +17546,7 @@
                 // The process is being computed, so there is a cycle. We cannot
                 // rely on this process's state.
                 app.containsCycle = true;
+
                 return false;
             }
         }
@@ -19224,6 +17571,7 @@
         final int logUid = mCurOomAdjUid;
 
         int prevAppAdj = app.curAdj;
+        int prevProcState = app.curProcState;
 
         if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
             // The max adjustment doesn't allow this app to be anything
@@ -19272,7 +17620,7 @@
 
         app.systemNoUi = false;
 
-        final int PROCESS_STATE_CUR_TOP = mTopProcessState;
+        final int PROCESS_STATE_CUR_TOP = mAtmInternal.getTopProcessState();
 
         // Determine the importance of the process, starting with most
         // important to least, and assign an appropriate OOM adjustment.
@@ -19301,7 +17649,7 @@
             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app);
             }
-        } else if (app.instr != null) {
+        } else if (app.getActiveInstrumentation() != null) {
             // Don't want to kill running instrumentation.
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
@@ -19361,119 +17709,15 @@
 
         // Examine all activities if not already foreground.
         if (!foregroundActivities && wpc.hasActivities()) {
-            final int[] adjHolder = new int[1];
-            adjHolder[0] = adj;
-            final boolean[] foregroundActivitiesHolder = new boolean[1];
-            foregroundActivitiesHolder[0] = foregroundActivities;
-            int[] procStateHolder = new int[1];
-            procStateHolder[0] = procState;
-            int[] schedGroupHolder = new int[1];
-            schedGroupHolder[0] = schedGroup;
+            mTmpComputeOomAdjWindowCallback.initialize(app, adj, foregroundActivities, procState,
+                    schedGroup, appUid, logUid, PROCESS_STATE_CUR_TOP);
+            final int minLayer = wpc.computeOomAdjFromActivities(
+                    ProcessList.VISIBLE_APP_LAYER_MAX, mTmpComputeOomAdjWindowCallback);
 
-            int minLayer = wpc.computeOomAdjFromActivities(ProcessList.VISIBLE_APP_LAYER_MAX,
-                    new WindowProcessController.ComputeOomAdjCallback() {
-                        @Override
-                        public void onVisibleActivity() {
-                            // App has a visible activity; only upgrade adjustment.
-                            if (adjHolder[0] > ProcessList.VISIBLE_APP_ADJ) {
-                                adjHolder[0] = ProcessList.VISIBLE_APP_ADJ;
-                                app.adjType = "vis-activity";
-                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                            "Raise adj to vis-activity: " + app);
-                                }
-                            }
-                            if (procStateHolder[0] > PROCESS_STATE_CUR_TOP) {
-                                procStateHolder[0] = PROCESS_STATE_CUR_TOP;
-                                app.adjType = "vis-activity";
-                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                            "Raise procstate to vis-activity (top): " + app);
-                                }
-                            }
-                            if (schedGroupHolder[0] < ProcessList.SCHED_GROUP_DEFAULT) {
-                                schedGroupHolder[0] = ProcessList.SCHED_GROUP_DEFAULT;
-                            }
-                            app.cached = false;
-                            app.empty = false;
-                            foregroundActivitiesHolder[0] = true;
-                        }
-
-                        @Override
-                        public void onPausedActivity() {
-                            if (adjHolder[0] > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                                adjHolder[0] = ProcessList.PERCEPTIBLE_APP_ADJ;
-                                app.adjType = "pause-activity";
-                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                            "Raise adj to pause-activity: "  + app);
-                                }
-                            }
-                            if (procStateHolder[0] > PROCESS_STATE_CUR_TOP) {
-                                procStateHolder[0] = PROCESS_STATE_CUR_TOP;
-                                app.adjType = "pause-activity";
-                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                            "Raise procstate to pause-activity (top): "  + app);
-                                }
-                            }
-                            if (schedGroupHolder[0] < ProcessList.SCHED_GROUP_DEFAULT) {
-                                schedGroupHolder[0] = ProcessList.SCHED_GROUP_DEFAULT;
-                            }
-                            app.cached = false;
-                            app.empty = false;
-                            foregroundActivitiesHolder[0] = true;
-                        }
-
-                        @Override
-                        public void onStoppingActivity(boolean finishing) {
-                            if (adjHolder[0] > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                                adjHolder[0] = ProcessList.PERCEPTIBLE_APP_ADJ;
-                                app.adjType = "stop-activity";
-                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                            "Raise adj to stop-activity: "  + app);
-                                }
-                            }
-                            // For the process state, we will at this point consider the process to
-                            // be cached. It will be cached either as an activity or empty depending
-                            // on whether the activity is finishing. We do this so that we can treat
-                            // the process as cached for purposes of memory trimming (determining
-                            // current memory level, trim command to send to process) since there
-                            // can be an arbitrary number of stopping processes and they should soon
-                            // all go into the cached state.
-                            if (!finishing) {
-                                if (procStateHolder[0] > PROCESS_STATE_LAST_ACTIVITY) {
-                                    procStateHolder[0] = PROCESS_STATE_LAST_ACTIVITY;
-                                    app.adjType = "stop-activity";
-                                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                                "Raise procstate to stop-activity: " + app);
-                                    }
-                                }
-                            }
-                            app.cached = false;
-                            app.empty = false;
-                            foregroundActivitiesHolder[0] = true;
-                        }
-
-                        @Override
-                        public void onOtherActivity() {
-                            if (procStateHolder[0] > PROCESS_STATE_CACHED_ACTIVITY) {
-                                procStateHolder[0] = PROCESS_STATE_CACHED_ACTIVITY;
-                                app.adjType = "cch-act";
-                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                            "Raise procstate to cached activity: " + app);
-                                }
-                            }
-                        }
-                    });
-
-            adj = adjHolder[0];
-            foregroundActivities = foregroundActivitiesHolder[0];
-            procState = procStateHolder[0];
-            schedGroup = schedGroupHolder[0];
+            adj = mTmpComputeOomAdjWindowCallback.adj;
+            foregroundActivities = mTmpComputeOomAdjWindowCallback.foregroundActivities;
+            procState = mTmpComputeOomAdjWindowCallback.procState;
+            schedGroup = mTmpComputeOomAdjWindowCallback.schedGroup;
 
             if (adj == ProcessList.VISIBLE_APP_ADJ) {
                 adj += minLayer;
@@ -19696,19 +17940,25 @@
                     // all connected clients.
                     ConnectionRecord cr = clist.get(i);
                     if (cr.binding.client == app) {
-                        // Binding to ourself is not interesting.
+                        // Binding to oneself is not interesting.
                         continue;
                     }
 
+                    boolean trackedProcState = false;
                     if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
                         ProcessRecord client = cr.binding.client;
                         computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
                         if (client.containsCycle) {
-                            // We've detected a cycle. We should ignore this connection and allow
-                            // this process to retry computeOomAdjLocked later in case a later-checked
-                            // connection from a client  would raise its priority legitimately.
+                            // We've detected a cycle. We should retry computeOomAdjLocked later in
+                            // case a later-checked connection from a client  would raise its
+                            // priority legitimately.
                             app.containsCycle = true;
-                            continue;
+                            // If the client has not been completely evaluated, skip using its
+                            // priority. Else use the conservative value for now and look for a
+                            // better state in the next iteration.
+                            if (client.completedAdjSeq < mAdjSeq) {
+                                continue;
+                            }
                         }
                         int clientAdj = client.curRawAdj;
                         int clientProcState = client.curProcState;
@@ -19771,6 +18021,8 @@
                                         newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
                                         schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                         procState = ActivityManager.PROCESS_STATE_PERSISTENT;
+                                        cr.trackProcState(procState, mAdjSeq, now);
+                                        trackedProcState = true;
                                     }
                                 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                         && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
@@ -19856,6 +18108,9 @@
                                         ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
                             }
                         }
+                        if (!trackedProcState) {
+                            cr.trackProcState(clientProcState, mAdjSeq, now);
+                        }
                         if (procState > clientProcState) {
                             procState = clientProcState;
                             if (adjType == null) {
@@ -19932,11 +18187,16 @@
                 }
                 computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
                 if (client.containsCycle) {
-                    // We've detected a cycle. We should ignore this connection and allow
-                    // this process to retry computeOomAdjLocked later in case a later-checked
-                    // connection from a client  would raise its priority legitimately.
+                    // We've detected a cycle. We should retry computeOomAdjLocked later in
+                    // case a later-checked connection from a client  would raise its
+                    // priority legitimately.
                     app.containsCycle = true;
-                    continue;
+                    // If the client has not been completely evaluated, skip using its
+                    // priority. Else use the conservative value for now and look for a
+                    // better state in the next iteration.
+                    if (client.completedAdjSeq < mAdjSeq) {
+                        continue;
+                    }
                 }
                 int clientAdj = client.curRawAdj;
                 int clientProcState = client.curProcState;
@@ -19985,6 +18245,7 @@
                         }
                     }
                 }
+                conn.trackProcState(clientProcState, mAdjSeq, now);
                 if (procState > clientProcState) {
                     procState = clientProcState;
                 }
@@ -20023,8 +18284,10 @@
                 }
                 if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
                     procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
-                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                            "Raise procstate to external provider: " + app);
+                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                                "Raise procstate to external provider: " + app);
+                    }
                 }
             }
         }
@@ -20168,8 +18431,8 @@
         app.foregroundActivities = foregroundActivities;
         app.completedAdjSeq = mAdjSeq;
 
-        // if curAdj is less than prevAppAdj, then this process was promoted
-        return app.curAdj < prevAppAdj;
+        // if curAdj or curProcState improved, then this process was promoted
+        return app.curAdj < prevAppAdj || app.curProcState < prevProcState;
     }
 
     /**
@@ -20182,6 +18445,15 @@
         proc.lastPssTime = now;
         proc.baseProcessTracker.addPss(
                 pss, uss, rss, true, statType, pssDuration, proc.pkgList.mPkgList);
+        for (int ipkg = proc.pkgList.mPkgList.size() - 1; ipkg >= 0; ipkg--) {
+            ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+            StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED,
+                    proc.info.uid,
+                    holder.state.getName(),
+                    holder.state.getPackage(),
+                    pss, uss, rss, statType, pssDuration,
+                    holder.appVersion);
+        }
         if (DEBUG_PSS) Slog.d(TAG_PSS,
                 "pss of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
                 + " state=" + ProcessList.makeProcStateString(procState));
@@ -20322,7 +18594,7 @@
                 app.pssStatType = always ? ProcessStats.ADD_PSS_INTERNAL_ALL_POLL
                         : ProcessStats.ADD_PSS_INTERNAL_ALL_MEM;
                 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
-                        app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
+                        app.procStateMemTracker, mTestPssMode, mAtmInternal.isSleeping(), now);
                 mPendingPssProcesses.add(app);
             }
         }
@@ -20372,7 +18644,7 @@
             }
         }
         return !processingBroadcasts
-                && (isSleepingLocked() || mStackSupervisor.allResumedActivitiesIdle());
+                && (mAtmInternal.isSleeping() || mStackSupervisor.allResumedActivitiesIdle());
     }
 
     /**
@@ -20533,6 +18805,14 @@
                         app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince
                                 + " dur=" + checkDur + " limit=" + cpuLimit, true);
                         app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList);
+                        for (int ipkg = app.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                            ProcessStats.ProcessStateHolder holder = app.pkgList.valueAt(ipkg);
+                            StatsLog.write(StatsLog.EXCESSIVE_CPU_USAGE_REPORTED,
+                                    app.info.uid,
+                                    holder.state.getName(),
+                                    holder.state.getPackage(),
+                                    holder.appVersion);
+                        }
                     }
                 }
                 app.lastCpuTime = app.curCpuTime;
@@ -20706,7 +18986,7 @@
             }
             app.lastStateTime = now;
             app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
-                    app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
+                    app.procStateMemTracker, mTestPssMode, mAtmInternal.isSleeping(), now);
             if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
                     + ProcessList.makeProcStateString(app.setProcState) + " to "
                     + ProcessList.makeProcStateString(app.curProcState) + " next pss in "
@@ -20717,7 +18997,7 @@
                     mTestPssMode)))) {
                 if (requestPssLocked(app, app.setProcState)) {
                     app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
-                            app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
+                            app.procStateMemTracker, mTestPssMode, mAtmInternal.isSleeping(), now);
                 }
             } else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
                     "Not requesting pss of " + app + ": next=" + (app.nextPssTime-now));
@@ -21020,9 +19300,10 @@
         }
     }
 
-    private final ActivityRecord resumedAppLocked() {
-        final ActivityRecord act =
-                mStackSupervisor != null ? mStackSupervisor.getResumedActivityLocked() : null;
+    // TODO(b/111541062): This method is only used for updating OOM adjustments. We need to update
+    // the logic there and in mBatteryStatsService to make them aware of multiple resumed activities
+    private ActivityRecord resumedAppLocked() {
+        final ActivityRecord act = mStackSupervisor.getTopResumedActivity();
         String pkg;
         int uid;
         if (act != null) {
@@ -21035,16 +19316,23 @@
         // Has the UID or resumed package name changed?
         if (uid != mCurResumedUid || (pkg != mCurResumedPackage
                 && (pkg == null || !pkg.equals(mCurResumedPackage)))) {
-            if (mCurResumedPackage != null) {
-                mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_FINISH,
-                        mCurResumedPackage, mCurResumedUid);
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if (mCurResumedPackage != null) {
+                    mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_FINISH,
+                            mCurResumedPackage, mCurResumedUid);
+                }
+                mCurResumedPackage = pkg;
+                mCurResumedUid = uid;
+                if (mCurResumedPackage != null) {
+                    mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_START,
+                            mCurResumedPackage, mCurResumedUid);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
-            mCurResumedPackage = pkg;
-            mCurResumedUid = uid;
-            if (mCurResumedPackage != null) {
-                mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_START,
-                        mCurResumedPackage, mCurResumedUid);
-            }
+
         }
         return act;
     }
@@ -21094,6 +19382,7 @@
 
     @GuardedBy("this")
     final void updateOomAdjLocked() {
+        mOomAdjProfiler.oomAdjStarted();
         final ProcessRecord TOP_APP = getTopAppLocked();
         final long now = SystemClock.uptimeMillis();
         final long nowElapsed = SystemClock.elapsedRealtime();
@@ -21233,7 +19522,7 @@
         // - Continue retrying until no process was promoted.
         // - Iterate from least important to most important.
         int cycleCount = 0;
-        while (retryCycles) {
+        while (retryCycles && cycleCount < 10) {
             cycleCount++;
             retryCycles = false;
 
@@ -21248,12 +19537,14 @@
             for (int i=0; i<N; i++) {
                 ProcessRecord app = mLruProcesses.get(i);
                 if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
+
                     if (computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now)) {
                         retryCycles = true;
                     }
                 }
             }
         }
+
         for (int i=N-1; i>=0; i--) {
             ProcessRecord app = mLruProcesses.get(i);
             if (!app.killedByAm && app.thread != null) {
@@ -21317,6 +19608,8 @@
             }
         }
 
+        mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
+
         incrementProcStateSeqAndNotifyAppsLocked();
 
         mNumServiceProcs = mNewNumServiceProcs;
@@ -21355,10 +19648,12 @@
         }
         if (memFactor != mLastMemoryLevel) {
             EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
+            StatsLog.write(StatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
         }
         mLastMemoryLevel = memFactor;
         mLastNumProcesses = mLruProcesses.size();
-        boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleepingLocked(), now);
+        boolean allChanged = mProcessStats.setMemFactorLocked(
+                memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now);
         final int trackerMemFactor = mProcessStats.getMemFactorLocked();
         if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
             if (mLowRamStartTime == 0) {
@@ -21592,6 +19887,7 @@
                 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
             }
         }
+        mOomAdjProfiler.oomAdjEnded();
     }
 
     @Override
@@ -21943,6 +20239,7 @@
         }
     }
 
+    @GuardedBy("this")
     final void trimApplicationsLocked() {
         // First remove any unused application processes whose package
         // has been removed.
@@ -22463,15 +20760,6 @@
     @VisibleForTesting
     final class LocalService extends ActivityManagerInternal {
         @Override
-        public void grantUriPermissionFromIntent(int callingUid, String targetPkg, Intent intent,
-                int targetUserId) {
-            synchronized (ActivityManagerService.this) {
-                ActivityManagerService.this.grantUriPermissionFromIntentLocked(callingUid,
-                        targetPkg, intent, null, targetUserId);
-            }
-        }
-
-        @Override
         public String checkContentProviderAccess(String authority, int userId) {
             return ActivityManagerService.this.checkContentProviderAccess(authority, userId);
         }
@@ -22746,9 +21034,8 @@
 
         @Override
         public boolean isUserRunning(int userId, int flags) {
-            synchronized (ActivityManagerService.this) {
-                return mUserController.isUserRunning(userId, flags);
-            }
+            // Holding am lock isn't required to call into user controller.
+            return mUserController.isUserRunning(userId, flags);
         }
 
         @Override
@@ -22807,6 +21094,74 @@
             }
             return false;
         }
+
+        @Override
+        public void updateOomAdj() {
+            synchronized (ActivityManagerService.this) {
+                ActivityManagerService.this.updateOomAdjLocked();
+            }
+        }
+
+        @Override
+        public void sendForegroundProfileChanged(int userId) {
+            mUserController.sendForegroundProfileChanged(userId);
+        }
+
+        @Override
+        public boolean shouldConfirmCredentials(int userId) {
+            return mUserController.shouldConfirmCredentials(userId);
+        }
+
+        @Override
+        public int[] getCurrentProfileIds() {
+            return mUserController.getCurrentProfileIds();
+        }
+
+        @Override
+        public UserInfo getCurrentUser() {
+            return mUserController.getCurrentUser();
+        }
+
+        @Override
+        public void ensureNotSpecialUser(int userId) {
+            mUserController.ensureNotSpecialUser(userId);
+        }
+
+        @Override
+        public boolean isCurrentProfile(int userId) {
+            return mUserController.isCurrentProfile(userId);
+        }
+
+        @Override
+        public boolean hasStartedUserState(int userId) {
+            return mUserController.hasStartedUserState(userId);
+        }
+
+        @Override
+        public void finishUserSwitch(Object uss) {
+            mUserController.finishUserSwitch((UserState) uss);
+        }
+
+        @Override
+        public Intent getHomeIntent() {
+            synchronized (ActivityManagerService.this) {
+                return ActivityManagerService.this.getHomeIntent();
+            }
+        }
+
+        @Override
+        public void scheduleAppGcs() {
+            synchronized (ActivityManagerService.this) {
+                ActivityManagerService.this.scheduleAppGcsLocked();
+            }
+        }
+
+        @Override
+        public int getTaskIdForActivity(IBinder token, boolean onlyRoot) {
+            synchronized (ActivityManagerService.this) {
+                return ActivityManagerService.this.getTaskForActivity(token, onlyRoot);
+            }
+        }
     }
 
     /**
@@ -23057,4 +21412,143 @@
             return mNmi != null;
         }
     }
+
+    @Override
+    public void startDelegateShellPermissionIdentity(int delegateUid) {
+        if (UserHandle.getCallingAppId() != Process.SHELL_UID
+                && UserHandle.getCallingAppId() != Process.ROOT_UID) {
+            throw new SecurityException("Only the shell can delegate its permissions");
+        }
+
+        // We allow delegation only to one instrumentation started from the shell
+        synchronized (ActivityManagerService.this) {
+            // If there is a delegate it should be the same instance for app ops and permissions.
+            if (mAppOpsService.getAppOpsServiceDelegate()
+                    != getPackageManagerInternalLocked().getCheckPermissionDelegate()) {
+                throw new IllegalStateException("Bad shell delegate state");
+            }
+
+            // If the delegate is already set up for the target UID, nothing to do.
+            if (mAppOpsService.getAppOpsServiceDelegate() != null) {
+                if (!(mAppOpsService.getAppOpsServiceDelegate() instanceof ShellDelegate)) {
+                    throw new IllegalStateException("Bad shell delegate state");
+                }
+                if (((ShellDelegate) mAppOpsService.getAppOpsServiceDelegate())
+                        .getDelegateUid() != delegateUid) {
+                    throw new SecurityException("Shell can delegate permissions only "
+                            + "to one instrumentation at a time");
+                }
+                return;
+            }
+
+            final int instrCount = mActiveInstrumentation.size();
+            for (int i = 0; i < instrCount; i++) {
+                final ActiveInstrumentation instr = mActiveInstrumentation.get(i);
+                if (instr.mTargetInfo.uid != delegateUid) {
+                    continue;
+                }
+                // If instrumentation started from the shell the connection is not null
+                if (instr.mUiAutomationConnection == null) {
+                    throw new SecurityException("Shell can delegate its permissions" +
+                            " only to an instrumentation started from the shell");
+                }
+
+                // Hook them up...
+                final ShellDelegate shellDelegate = new ShellDelegate(
+                        instr.mTargetInfo.packageName, delegateUid);
+                mAppOpsService.setAppOpsServiceDelegate(shellDelegate);
+                getPackageManagerInternalLocked().setCheckPermissionDelegate(shellDelegate);
+                return;
+            }
+        }
+    }
+
+    @Override
+    public void stopDelegateShellPermissionIdentity() {
+        if (UserHandle.getCallingAppId() != Process.SHELL_UID
+                && UserHandle.getCallingAppId() != Process.ROOT_UID) {
+            throw new SecurityException("Only the shell can delegate its permissions");
+        }
+        synchronized (ActivityManagerService.this) {
+            mAppOpsService.setAppOpsServiceDelegate(null);
+            getPackageManagerInternalLocked().setCheckPermissionDelegate(null);
+        }
+    }
+
+    private class ShellDelegate implements CheckOpsDelegate, CheckPermissionDelegate {
+        private final String mTargetPackageName;
+        private final int mTargetUid;
+
+        ShellDelegate(String targetPacakgeName, int targetUid) {
+            mTargetPackageName = targetPacakgeName;
+            mTargetUid = targetUid;
+        }
+
+        int getDelegateUid() {
+            return mTargetUid;
+        }
+
+        @Override
+        public int checkOperation(int code, int uid, String packageName,
+                TriFunction<Integer, Integer, String, Integer> superImpl) {
+            if (uid == mTargetUid) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    return superImpl.apply(code, Process.SHELL_UID,
+                            "com.android.shell");
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+            return superImpl.apply(code, uid, packageName);
+        }
+
+        @Override
+        public int checkAudioOperation(int code, int usage, int uid, String packageName,
+                QuadFunction<Integer, Integer, Integer, String, Integer> superImpl) {
+            if (uid == mTargetUid) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    return superImpl.apply(code, usage, Process.SHELL_UID,
+                            "com.android.shell");
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+            return superImpl.apply(code, usage, uid, packageName);
+        }
+
+        @Override
+        public int noteOperation(int code, int uid, String packageName,
+                TriFunction<Integer, Integer, String, Integer> superImpl) {
+            if (uid == mTargetUid) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    return mAppOpsService.noteProxyOperation(code, Process.SHELL_UID,
+                            "com.android.shell", uid, packageName);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+            return superImpl.apply(code, uid, packageName);
+        }
+
+        @Override
+        public int checkPermission(String permName, String pkgName, int userId,
+                TriFunction<String, String, Integer, Integer> superImpl) {
+            if (mTargetPackageName.equals(pkgName)) {
+                return superImpl.apply(permName, "com.android.shell", userId);
+            }
+            return superImpl.apply(permName, pkgName, userId);
+        }
+
+        @Override
+        public int checkUidPermission(String permName, int uid,
+                BiFunction<String, Integer, Integer> superImpl) {
+            if (uid == mTargetUid) {
+                return superImpl.apply(permName, Process.SHELL_UID);
+            }
+            return superImpl.apply(permName, uid);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index e6c3475..9de6875 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -16,6 +16,14 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
+import static android.app.ActivityTaskManager.RESIZE_MODE_USER;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.view.Display.INVALID_DISPLAY;
+
+import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
+
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
@@ -102,15 +110,6 @@
 import javax.microedition.khronos.egl.EGLDisplay;
 import javax.microedition.khronos.egl.EGLSurface;
 
-import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
-import static android.app.ActivityTaskManager.RESIZE_MODE_USER;
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.Display.INVALID_DISPLAY;
-
-import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
-
 final class ActivityManagerShellCommand extends ShellCommand {
     public static final String NO_CLASS_ERROR_CODE = "Error type 3";
     private static final String SHELL_PACKAGE_NAME = "com.android.shell";
@@ -2393,8 +2392,6 @@
     int runStack(PrintWriter pw) throws RemoteException {
         String op = getNextArgRequired();
         switch (op) {
-            case "start":
-                return runStackStart(pw);
             case "move-task":
                 return runStackMoveTask(pw);
             case "resize":
@@ -2457,31 +2454,6 @@
         return 0;
     }
 
-    int runStackStart(PrintWriter pw) throws RemoteException {
-        String displayIdStr = getNextArgRequired();
-        int displayId = Integer.parseInt(displayIdStr);
-        Intent intent;
-        try {
-            intent = makeIntent(UserHandle.USER_CURRENT);
-        } catch (URISyntaxException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-
-        final int stackId = mTaskInterface.createStackOnDisplay(displayId);
-        if (stackId != INVALID_STACK_ID) {
-            // TODO: Need proper support if this is used by test...
-//            container.startActivity(intent);
-//            ActivityOptions options = ActivityOptions.makeBasic();
-//            options.setLaunchDisplayId(displayId);
-//            options.setLaunchStackId(stackId);
-//            mInterface.startAct
-//            mInterface.startActivityAsUser(null, null, intent, mimeType,
-//                    null, null, 0, mStartFlags, profilerInfo,
-//                    options != null ? options.toBundle() : null, mUserId);
-        }
-        return 0;
-    }
-
     int runStackMoveTask(PrintWriter pw) throws RemoteException {
         String taskIdStr = getNextArgRequired();
         int taskId = Integer.parseInt(taskIdStr);
@@ -2877,6 +2849,7 @@
             pw.println("  --checkin: output checkin format, resetting data.");
             pw.println("  --C: output checkin format, not resetting data.");
             pw.println("  --proto: output dump in protocol buffer format.");
+            pw.println("  --autofill: dump just the autofill-related state of an activity");
         } else {
             pw.println("Activity manager (activity) commands:");
             pw.println("  help");
@@ -2904,6 +2877,7 @@
             pw.println("          specified then run as the current user.");
             pw.println("      --windowingMode <WINDOWING_MODE>: The windowing mode to launch the activity into.");
             pw.println("      --activityType <ACTIVITY_TYPE>: The activity type to launch the activity as.");
+            pw.println("      --display <DISPLAY_ID>: The display to launch the activity into.");
             pw.println("  start-service [--user <USER_ID> | current] <INTENT>");
             pw.println("      Start a Service.  Options are:");
             pw.println("      --user <USER_ID> | current: Specify which user to run as; if not");
@@ -3068,8 +3042,6 @@
             pw.println("       move-stack <STACK_ID> <DISPLAY_ID>");
             pw.println("           Move <STACK_ID> from its current display to <DISPLAY_ID>.");
             pw.println("  stack [COMMAND] [...]: sub-commands for operating on activity stacks.");
-            pw.println("       start <DISPLAY_ID> <INTENT>");
-            pw.println("           Start a new activity on <DISPLAY_ID> using <INTENT>");
             pw.println("       move-task <TASK_ID> <STACK_ID> [true|false]");
             pw.println("           Move <TASK_ID> from its current stack to the top (true) or");
             pw.println("           bottom (false) of <STACK_ID>.");
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 9b08823..263c34f 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -2,6 +2,7 @@
 
 import static android.app.ActivityManager.START_SUCCESS;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ActivityManager.processStateAmToProto;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -9,6 +10,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ACTIVITY_START;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME;
@@ -21,8 +23,48 @@
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_FLAGS;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_FULLSCREEN;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_LAUNCH_MODE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_PROCESS_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_REAL_ACTIVITY;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_PACKAGE_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID_PROC_STATE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_COMING_FROM_PENDING_INTENT;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INTENT_ACTION;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_CUR_PROC_STATE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_OVERLAY_UI;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_TOP_UI;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PENDING_UI_CLEAN;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PROCESS_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_PROC_STATE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_PACKAGE_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_SHORT_COMPONENT_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_PROC_STATE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_WHITELIST_TAG;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_FILTER;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
@@ -37,6 +79,7 @@
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.dex.ArtManagerInternal;
 import android.content.pm.dex.PackageOptimizationInfo;
@@ -133,7 +176,7 @@
 
     private final class WindowingModeTransitionInfoSnapshot {
         final private ApplicationInfo applicationInfo;
-        final private ProcessRecord processRecord;
+        final private WindowProcessController processRecord;
         final private String packageName;
         final private String launchedActivityName;
         final private String launchedActivityLaunchedFromPackage;
@@ -184,7 +227,7 @@
         mLastLogTimeSecs = now;
 
         mWindowState = WINDOW_STATE_INVALID;
-        ActivityStack stack = mSupervisor.getFocusedStack();
+        ActivityStack stack = mSupervisor.getTopDisplayFocusedStack();
         if (stack == null) {
             return;
         }
@@ -238,7 +281,7 @@
      * @param launchedActivity the activity that is being launched
      */
     void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity) {
-        final ProcessRecord processRecord = findProcessForActivity(launchedActivity);
+        final WindowProcessController processRecord = findProcessForActivity(launchedActivity);
         final boolean processRunning = processRecord != null;
 
         // We consider this a "process switch" if the process of the activity that gets launched
@@ -246,7 +289,7 @@
         // of caches might be purged so the time until it produces the first frame is very
         // interesting.
         final boolean processSwitch = processRecord == null
-                || !processRecord.getWindowProcessController().hasStartedActivity(launchedActivity);
+                || !processRecord.hasStartedActivity(launchedActivity);
 
         notifyActivityLaunched(resultCode, launchedActivity, processRunning, processSwitch);
     }
@@ -612,6 +655,95 @@
                 startupTimeMs);
     }
 
+    void logActivityStart(Intent intent, ProcessRecord callerApp, ActivityRecord r,
+            int callingUid, String callingPackage, int callingUidProcState,
+            boolean callingUidHasAnyVisibleWindow,
+            int realCallingUid, int realCallingUidProcState,
+            boolean realCallingUidHasAnyVisibleWindow,
+            int targetUid, String targetPackage, int targetUidProcState,
+            boolean targetUidHasAnyVisibleWindow, String targetWhitelistTag,
+            boolean comingFromPendingIntent) {
+
+        final long nowElapsed = SystemClock.elapsedRealtime();
+        final long nowUptime = SystemClock.uptimeMillis();
+        final LogMaker builder = new LogMaker(ACTION_ACTIVITY_START);
+        builder.setTimestamp(System.currentTimeMillis());
+        builder.addTaggedData(FIELD_CALLING_UID, callingUid);
+        builder.addTaggedData(FIELD_CALLING_PACKAGE_NAME, callingPackage);
+        builder.addTaggedData(FIELD_CALLING_UID_PROC_STATE,
+                processStateAmToProto(callingUidProcState));
+        builder.addTaggedData(FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW,
+                callingUidHasAnyVisibleWindow ? 1 : 0);
+        builder.addTaggedData(FIELD_REAL_CALLING_UID, realCallingUid);
+        builder.addTaggedData(FIELD_REAL_CALLING_UID_PROC_STATE,
+                processStateAmToProto(realCallingUidProcState));
+        builder.addTaggedData(FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW,
+                realCallingUidHasAnyVisibleWindow ? 1 : 0);
+        builder.addTaggedData(FIELD_TARGET_UID, targetUid);
+        builder.addTaggedData(FIELD_TARGET_PACKAGE_NAME, targetPackage);
+        builder.addTaggedData(FIELD_TARGET_UID_PROC_STATE,
+                processStateAmToProto(targetUidProcState));
+        builder.addTaggedData(FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW,
+                targetUidHasAnyVisibleWindow ? 1 : 0);
+        builder.addTaggedData(FIELD_TARGET_WHITELIST_TAG, targetWhitelistTag);
+        builder.addTaggedData(FIELD_TARGET_SHORT_COMPONENT_NAME, r.shortComponentName);
+        builder.addTaggedData(FIELD_COMING_FROM_PENDING_INTENT, comingFromPendingIntent ? 1 : 0);
+        builder.addTaggedData(FIELD_INTENT_ACTION, intent.getAction());
+        if (callerApp != null) {
+            builder.addTaggedData(FIELD_PROCESS_RECORD_PROCESS_NAME, callerApp.processName);
+            builder.addTaggedData(FIELD_PROCESS_RECORD_CUR_PROC_STATE,
+                    processStateAmToProto(callerApp.curProcState));
+            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES,
+                    callerApp.hasClientActivities ? 1 : 0);
+            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES,
+                    callerApp.hasForegroundServices() ? 1 : 0);
+            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES,
+                    callerApp.foregroundActivities ? 1 : 0);
+            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_TOP_UI, callerApp.hasTopUi ? 1 : 0);
+            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_OVERLAY_UI,
+                    callerApp.hasOverlayUi ? 1 : 0);
+            builder.addTaggedData(FIELD_PROCESS_RECORD_PENDING_UI_CLEAN,
+                    callerApp.pendingUiClean ? 1 : 0);
+            if (callerApp.interactionEventTime != 0) {
+                builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT,
+                        (nowElapsed - callerApp.interactionEventTime));
+            }
+            if (callerApp.fgInteractionTime != 0) {
+                builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION,
+                        (nowElapsed - callerApp.fgInteractionTime));
+            }
+            if (callerApp.whenUnimportant != 0) {
+                builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT,
+                        (nowUptime - callerApp.whenUnimportant));
+            }
+        }
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_LAUNCH_MODE, r.info.launchMode);
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY, r.info.targetActivity);
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_FLAGS, r.info.flags);
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_REAL_ACTIVITY, r.realActivity.toShortString());
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME, r.shortComponentName);
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_PROCESS_NAME, r.processName);
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_FULLSCREEN, r.fullscreen ? 1 : 0);
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY, r.noDisplay ? 1 : 0);
+        if (r.lastVisibleTime != 0) {
+            builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE,
+                    (nowUptime - r.lastVisibleTime));
+        }
+        if (r.resultTo != null) {
+            builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME, r.resultTo.packageName);
+            builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME,
+                    r.resultTo.shortComponentName);
+        }
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE, r.visible ? 1 : 0);
+        builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD,
+                r.visibleIgnoringKeyguard ? 1 : 0);
+        if (r.lastLaunchTime != 0) {
+            builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH,
+                    (nowUptime - r.lastLaunchTime));
+        }
+        mMetricsLogger.write(builder);
+    }
+
     private int getTransitionType(WindowingModeTransitionInfo info) {
         if (info.currentTransitionProcessRunning) {
             if (info.startResult == START_SUCCESS) {
@@ -631,7 +763,7 @@
             return;
         }
 
-        final int pid = info.processRecord.pid;
+        final int pid = info.processRecord.getPid();
         final int uid = info.applicationInfo.uid;
         final MemoryStat memoryStat = readMemoryStatFromFilesystem(uid, pid);
         if (memoryStat == null) {
@@ -651,9 +783,9 @@
                 memoryStat.swapInBytes);
     }
 
-    private ProcessRecord findProcessForActivity(ActivityRecord launchedActivity) {
+    private WindowProcessController findProcessForActivity(ActivityRecord launchedActivity) {
         return launchedActivity != null
-                ? mSupervisor.mService.mAm.mProcessNames.get(
+                ? mSupervisor.mService.mProcessNames.get(
                         launchedActivity.processName, launchedActivity.appInfo.uid)
                 : null;
     }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index d40b9b4..628207c 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -186,6 +186,7 @@
 import com.android.server.AttributeCache;
 import com.android.server.AttributeCache.Entry;
 import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.uri.UriPermissionOwner;
 import com.android.server.wm.AppWindowContainerController;
 import com.android.server.wm.AppWindowContainerListener;
 import com.android.server.wm.ConfigurationContainer;
@@ -338,6 +339,17 @@
     int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
     boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
 
+    // This activity is not being relaunched, or being relaunched for a non-resize reason.
+    static final int RELAUNCH_REASON_NONE = 0;
+    // This activity is being relaunched due to windowing mode change.
+    static final int RELAUNCH_REASON_WINDOWING_MODE_RESIZE = 1;
+    // This activity is being relaunched due to a free-resize operation.
+    static final int RELAUNCH_REASON_FREE_RESIZE = 2;
+    // Marking the reason why this activity is being relaunched. Mainly used to track that this
+    // activity is being relaunched to fulfill a resize request due to compatibility issues, e.g. in
+    // pre-NYC apps that don't have a sense of being resized.
+    int mRelaunchReason = RELAUNCH_REASON_NONE;
+
     TaskDescription taskDescription; // the recents information for this activity
     boolean mLaunchTaskBehind; // this activity is actively being launched with
         // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.
@@ -641,7 +653,7 @@
     }
 
     private void scheduleConfigurationChanged(Configuration config) {
-        if (attachedToProcess()) {
+        if (!attachedToProcess()) {
             if (DEBUG_CONFIGURATION) Slog.w(TAG,
                     "Can't report activity configuration update - client not running"
                             + ", activityRecord=" + this);
@@ -693,9 +705,13 @@
         final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
         if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
             // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
-            // update that here in order
+            // update that here in order. Set the last reported MW state to the same as the PiP
+            // state since we haven't yet actually resized the task (these callbacks need to
+            // preceed the configuration change from the resiez.
+            // TODO(110009072): Once we move these callbacks to the client, remove all logic related
+            // to forcing the update of the picture-in-picture mode as a part of the PiP animation.
             mLastReportedPictureInPictureMode = inPictureInPictureMode;
-            mLastReportedMultiWindowMode = inMultiWindowMode();
+            mLastReportedMultiWindowMode = inPictureInPictureMode;
             final Configuration newConfig = task.computeNewOverrideConfigurationForBounds(
                     targetStackBounds, null);
             schedulePictureInPictureModeChanged(newConfig);
@@ -1024,7 +1040,7 @@
                 (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
                 task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(),
                 appInfo.targetSdkVersion, mRotationAnimationHint,
-                ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L);
+                ActivityTaskManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L);
 
         task.addActivityToTop(this);
 
@@ -1343,13 +1359,8 @@
      * @return Whether AppOps allows this package to enter picture-in-picture.
      */
     private boolean checkEnterPictureInPictureAppOpsState() {
-        try {
-            return service.mAm.getAppOpsService().checkOperation(
-                    OP_PICTURE_IN_PICTURE, appInfo.uid, packageName) == MODE_ALLOWED;
-        } catch (RemoteException e) {
-            // Local call
-        }
-        return false;
+        return service.getAppOpsService().checkOperation(
+                OP_PICTURE_IN_PICTURE, appInfo.uid, packageName) == MODE_ALLOWED;
     }
 
     boolean isAlwaysFocusable() {
@@ -1381,7 +1392,7 @@
 
     UriPermissionOwner getUriPermissionsLocked() {
         if (uriPermissions == null) {
-            uriPermissions = new UriPermissionOwner(service.mAm, this);
+            uriPermissions = new UriPermissionOwner(service.mUgmInternal, this);
         }
         return uriPermissions;
     }
@@ -1424,7 +1435,7 @@
 
     final boolean isSleeping() {
         final ActivityStack stack = getStack();
-        return stack != null ? stack.shouldSleepActivities() : service.mAm.isSleepingLocked();
+        return stack != null ? stack.shouldSleepActivities() : service.isSleepingLocked();
     }
 
     /**
@@ -1433,7 +1444,7 @@
      */
     final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
         // The activity now gets access to the data associated with this Intent.
-        service.mAm.grantUriPermissionFromIntentLocked(callingUid, packageName,
+        service.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
                 intent, getUriPermissionsLocked(), userId);
         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
         boolean unsent = true;
@@ -1593,7 +1604,7 @@
 
     void removeUriPermissionsLocked() {
         if (uriPermissions != null) {
-            uriPermissions.removeUriPermissionsLocked();
+            uriPermissions.removeUriPermissions();
             uriPermissions = null;
         }
     }
@@ -1797,7 +1808,7 @@
         // considers the resumed activity, as normal means will bring the activity from STOPPED
         // to RESUMED. Adding PAUSING in this scenario will lead to double lifecycles.
         if (!isState(STOPPED, STOPPING) || getStack().mTranslucentActivityWaiting != null
-                || mStackSupervisor.getResumedActivityLocked() == this) {
+                || isResumedActivityOnDisplay()) {
             return false;
         }
 
@@ -1882,7 +1893,7 @@
         // TODO: To be more accurate, the mark should be before the onCreate,
         //       not after the onResume. But for subsequent starts, onResume is fine.
         if (hasProcess()) {
-            cpuTimeAtResume = service.mAm.mProcessCpuTracker.getCpuTimeForPid(app.getPid());
+            cpuTimeAtResume = app.getCpuTime();
         } else {
             cpuTimeAtResume = 0; // Couldn't get the cpu time of process
         }
@@ -1934,7 +1945,7 @@
             } else {
                 if (deferRelaunchUntilPaused) {
                     stack.destroyActivityLocked(this, true /* removeFromApp */, "stop-config");
-                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                    mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 } else {
                     mStackSupervisor.updatePreviousProcessLocked(this);
                 }
@@ -2015,7 +2026,7 @@
                 EventLog.writeEvent(AM_ACTIVITY_FULLY_DRAWN_TIME,
                         userId, System.identityHashCode(this), shortComponentName,
                         thisTime, totalTime);
-                StringBuilder sb = service.mAm.mStringBuilder;
+                StringBuilder sb = service.mStringBuilder;
                 sb.setLength(0);
                 sb.append("Fully drawn ");
                 sb.append(shortComponentName);
@@ -2052,7 +2063,7 @@
             EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
                     userId, System.identityHashCode(this), shortComponentName,
                     thisTime, totalTime);
-            StringBuilder sb = service.mAm.mStringBuilder;
+            StringBuilder sb = service.mStringBuilder;
             sb.setLength(0);
             sb.append("Displayed ");
             sb.append(shortComponentName);
@@ -2127,7 +2138,7 @@
                     mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
                             false /* remove */, true /* processPausingActivities */);
                 }
-                service.mAm.scheduleAppGcsLocked();
+                service.scheduleAppGcsLocked();
             }
         }
     }
@@ -2152,13 +2163,11 @@
                     !hasProcess() || app.getPid() == windowPid || windowPid == -1;
         }
         if (windowFromSameProcessAsActivity) {
-            return service.mAm.inputDispatchingTimedOut(
-                    (ProcessRecord) anrApp.mOwner, anrActivity, this, false, reason);
+            return service.inputDispatchingTimedOut(anrApp, anrActivity, this, false, reason);
         } else {
             // In this case another process added windows using this activity token. So, we call the
             // generic service input dispatch timed out method so that the right process is blamed.
-            return service.mAm.inputDispatchingTimedOut(
-                    windowPid, false /* aboveSystem */, reason) < 0;
+            return service.inputDispatchingTimedOut(windowPid, false /* aboveSystem */, reason) < 0;
         }
     }
 
@@ -2167,7 +2176,7 @@
         // another activity to start or has stopped, then the key dispatching
         // timeout should not be caused by this.
         if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) {
-            final ActivityStack stack = mStackSupervisor.getFocusedStack();
+            final ActivityStack stack = mStackSupervisor.getTopDisplayFocusedStack();
             // Try to use the one which is closest to top.
             ActivityRecord r = stack.getResumedActivity();
             if (r == null) {
@@ -2191,7 +2200,7 @@
 
         return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
                 || (mStackSupervisor.isCurrentProfileLocked(userId)
-                && service.mAm.mUserController.isUserRunning(userId, 0 /* flags */));
+                && service.mAmInternal.isUserRunning(userId, 0 /* flags */));
     }
 
     /**
@@ -2357,7 +2366,7 @@
             frozenBeforeDestroy = true;
             if (!service.updateDisplayOverrideConfigurationLocked(config, this,
                     false /* deferResume */, displayId)) {
-                mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
             }
         }
         service.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
@@ -2570,8 +2579,7 @@
         // Update last reported values.
         final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
 
-        setLastReportedConfiguration(service.mAm.getGlobalConfiguration(),
-                newMergedOverrideConfig);
+        setLastReportedConfiguration(service.getGlobalConfiguration(), newMergedOverrideConfig);
 
         if (mState == INITIALIZING) {
             // No need to relaunch or schedule new config for activity that hasn't been launched
@@ -2622,6 +2630,15 @@
             startFreezingScreenLocked(app, globalChanges);
             forceNewConfig = false;
             preserveWindow &= isResizeOnlyChange(changes);
+            final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
+            if (hasResizeChange) {
+                final boolean isDragResizing =
+                        getTask().getWindowContainerController().isDragResizing();
+                mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
+                        : RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+            } else {
+                mRelaunchReason = RELAUNCH_REASON_NONE;
+            }
             if (!attachedToProcess()) {
                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                         "Config is destroying non-running " + this);
@@ -2743,6 +2760,11 @@
                 | CONFIG_SCREEN_LAYOUT)) == 0;
     }
 
+    private static boolean hasResizeChange(int change) {
+        return (change & (CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
+                | CONFIG_SCREEN_LAYOUT)) != 0;
+    }
+
     void relaunchActivityLocked(boolean andResume, boolean preserveWindow) {
         if (service.mSuppressResizeConfigChanges && preserveWindow) {
             configChangeFlags = 0;
@@ -2773,7 +2795,7 @@
             mStackSupervisor.activityRelaunchingLocked(this);
             final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
                     pendingNewIntents, configChangeFlags,
-                    new MergedConfiguration(service.mAm.getGlobalConfiguration(),
+                    new MergedConfiguration(service.getGlobalConfiguration(),
                             getMergedOverrideConfiguration()),
                     preserveWindow);
             final ActivityLifecycleItem lifecycleItem;
@@ -2799,10 +2821,12 @@
             }
             results = null;
             newIntents = null;
-            service.mAm.getAppWarningsLocked().onResumeActivity(this);
-            service.mAm.showAskCompatModeDialogLocked(this);
+            service.getAppWarningsLocked().onResumeActivity(this);
         } else {
-            service.mAm.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this);
+            final ActivityStack stack = getStack();
+            if (stack != null) {
+                stack.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this);
+            }
             setState(PAUSED, "relaunchActivityLocked");
         }
 
@@ -2947,7 +2971,7 @@
         }
         final ActivityRecord r = new ActivityRecord(service, null /* caller */,
                 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType,
-                aInfo, service.mAm.getConfiguration(), null /* resultTo */, null /* resultWho */,
+                aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */,
                 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */,
                 stackSupervisor, null /* options */, null /* sourceRecord */);
 
@@ -3009,10 +3033,30 @@
         return mStackSupervisor.topRunningActivityLocked() == this;
     }
 
+    /**
+     * @return {@code true} if this is the resumed activity on its current display, {@code false}
+     * otherwise.
+     */
+    boolean isResumedActivityOnDisplay() {
+        final ActivityDisplay display = getDisplay();
+        return display != null && this == display.getResumedActivity();
+    }
+
     void registerRemoteAnimations(RemoteAnimationDefinition definition) {
         mWindowContainerController.registerRemoteAnimations(definition);
     }
 
+    static String relaunchReasonToString(int relaunchReason) {
+        switch (relaunchReason) {
+            case RELAUNCH_REASON_WINDOWING_MODE_RESIZE:
+                return "window_resize";
+            case RELAUNCH_REASON_FREE_RESIZE:
+                return "free_resize";
+            default:
+                return null;
+        }
+    }
+
     @Override
     public String toString() {
         if (stringName != null) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index dae145d..fbf2855 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -72,6 +72,8 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_FREE_RESIZE;
+import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
@@ -457,7 +459,7 @@
         mHandler = new ActivityStackHandler(supervisor.mLooper);
         mWindowManager = mService.mWindowManager;
         mStackId = stackId;
-        mCurrentUser = mService.mAm.mUserController.getCurrentUserId();
+        mCurrentUser = mService.mAmInternal.getCurrentUserId();
         mTmpRect2.setEmpty();
         // Set display id before setting activity and window type to make sure it won't affect
         // stacks on a wrong display.
@@ -495,7 +497,10 @@
             if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
                     + reason);
             setResumedActivity(record, reason + " - onActivityStateChanged");
-            mService.mAm.setResumedActivityUncheckLocked(record, reason);
+            if (record == mStackSupervisor.getTopResumedActivity()) {
+                // TODO(b/111361570): Support multiple focused apps in WM
+                mService.setResumedActivityUncheckLocked(record, reason);
+            }
             mStackSupervisor.mRecentTasks.add(record.getTask());
         }
     }
@@ -503,11 +508,21 @@
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
         final int prevWindowingMode = getWindowingMode();
+        final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
         super.onConfigurationChanged(newParentConfig);
         final ActivityDisplay display = getDisplay();
-        if (display != null && prevWindowingMode != getWindowingMode()) {
+        if (display == null) {
+          return;
+        }
+        if (prevWindowingMode != getWindowingMode()) {
             display.onStackWindowingModeChanged(this);
         }
+        if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
+            // Since always on top is only on when the stack is freeform or pinned, the state
+            // can be toggled when the windowing mode changes. We must make sure the stack is
+            // placed properly when always on top state changes.
+            display.positionChildAtTop(this, false /* includingParents */);
+        }
     }
 
     @Override
@@ -525,15 +540,17 @@
         final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack();
         mTmpOptions.setLaunchWindowingMode(preferredWindowingMode);
 
+        int windowingMode = preferredWindowingMode;
         // Need to make sure windowing mode is supported. If we in the process of creating the stack
         // no need to resolve the windowing mode again as it is already resolved to the right mode.
-        int windowingMode = creating
-                ? preferredWindowingMode
-                : display.resolveWindowingMode(
-                        null /* ActivityRecord */, mTmpOptions, topTask, getActivityType());
-        if (splitScreenStack == this && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
-            // Resolution to split-screen secondary for the primary split-screen stack means we want
-            // to go fullscreen.
+        if (!creating) {
+            windowingMode = display.validateWindowingMode(windowingMode,
+                    null /* ActivityRecord */, topTask, getActivityType());
+        }
+        if (splitScreenStack == this
+                && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+            // Resolution to split-screen secondary for the primary split-screen stack means
+            // we want to go fullscreen.
             windowingMode = WINDOWING_MODE_FULLSCREEN;
         }
 
@@ -583,6 +600,9 @@
                 mStackSupervisor.mNoAnimActivities.add(topActivity);
             }
             super.setWindowingMode(windowingMode);
+            // setWindowingMode triggers an onConfigurationChanged cascade which can result in a
+            // different resolved windowing mode (usually when preferredWindowingMode is UNDEFINED).
+            windowingMode = getWindowingMode();
 
             if (creating) {
                 // Nothing else to do if we don't have a window container yet. E.g. call from ctor.
@@ -609,15 +629,6 @@
             mTmpRect2.setEmpty();
             if (windowingMode != WINDOWING_MODE_FULLSCREEN) {
                 mWindowContainerController.getRawBounds(mTmpRect2);
-                if (windowingMode == WINDOWING_MODE_FREEFORM) {
-                    if (topTask != null) {
-                        // TODO: Can we consolidate this and other sites that call this methods?
-                        Rect bounds = topTask().getLaunchBounds();
-                        if (bounds != null) {
-                            mTmpRect2.set(bounds);
-                        }
-                    }
-                }
             }
 
             if (!Objects.equals(getOverrideBounds(), mTmpRect2)) {
@@ -651,7 +662,7 @@
 
         if (!deferEnsuringVisibility) {
             mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
-            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
         }
     }
 
@@ -684,7 +695,7 @@
         mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
         postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
         adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */);
-        mStackSupervisor.resumeFocusedStackTopActivityLocked();
+        mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
         // Update visibility of activities before notifying WM. This way it won't try to resize
         // windows that are no longer visible.
         mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
@@ -837,7 +848,7 @@
         }
     }
 
-    private ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
+    ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
             if (r != null && (!focusableOnly || r.isFocusable())) {
@@ -1042,12 +1053,14 @@
         if (!isActivityTypeHome() && returnsToHomeStack()) {
             // Make sure the home stack is behind this stack since that is where we should return to
             // when this stack is no longer visible.
+            // TODO(b/111541062): Move home stack on the current display
             mStackSupervisor.moveHomeStackToFront(reason + " returnToHome");
         }
 
-        display.positionChildAtTop(this);
+        display.positionChildAtTop(this, true /* includingParents */);
         mStackSupervisor.setFocusStackUnchecked(reason, this);
         if (task != null) {
+            // This also moves the entire hierarchy branch to top, including parents
             insertTaskAtTop(task, null);
             return;
         }
@@ -1073,6 +1086,8 @@
         getDisplay().positionChildAtBottom(this);
         mStackSupervisor.setFocusStackUnchecked(reason, getDisplay().getTopStack());
         if (task != null) {
+            // TODO(b/111541062): We probably don't want to change display z-order to bottom just
+            // because one of its stacks moved to bottom.
             insertTaskAtBottom(task);
             return;
         }
@@ -1429,7 +1444,7 @@
         if (prev == null) {
             if (resuming == null) {
                 Slog.wtf(TAG, "Trying to pause when nothing is resumed");
-                mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
             }
             return false;
         }
@@ -1478,7 +1493,7 @@
 
         // If we are not going to sleep, we want to ensure the device is
         // awake until the next activity is started.
-        if (!uiSleeping && !mService.mAm.isSleepingOrShuttingDownLocked()) {
+        if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
             mStackSupervisor.acquireLaunchWakelock();
         }
 
@@ -1509,7 +1524,7 @@
             // pause, so just treat it as being paused now.
             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
             if (resuming == null) {
-                mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
             }
             return false;
         }
@@ -1601,9 +1616,9 @@
         }
 
         if (resumeNext) {
-            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
+            final ActivityStack topStack = mStackSupervisor.getTopDisplayFocusedStack();
             if (!topStack.shouldSleepOrShutDownActivities()) {
-                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
+                mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(topStack, prev, null);
             } else {
                 checkReadyForSleep();
                 ActivityRecord top = topStack.topRunningActivityLocked();
@@ -1612,7 +1627,7 @@
                     // something. Also if the top activity on the stack is not the just paused
                     // activity, we need to go ahead and resume it to ensure we complete an
                     // in-flight app switch.
-                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                    mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 }
             }
         }
@@ -1622,8 +1637,7 @@
 
             if (prev.hasProcess() && prev.cpuTimeAtResume > 0
                     && mService.mAm.mBatteryStatsService.isOnBattery()) {
-                long diff = mService.mAm.mProcessCpuTracker.getCpuTimeForPid(prev.app.getPid())
-                        - prev.cpuTimeAtResume;
+                long diff = prev.app.getCpuTime() - prev.cpuTimeAtResume;
                 if (diff > 0) {
                     BatteryStatsImpl bsi = mService.mAm.mBatteryStatsService.getActiveStatistics();
                     synchronized (bsi) {
@@ -1725,7 +1739,17 @@
     }
 
     boolean isTopStackOnDisplay() {
-        return getDisplay().isTopStack(this);
+        final ActivityDisplay display = getDisplay();
+        return display != null && display.isTopStack(this);
+    }
+
+    /**
+     * @return {@code true} if this is the focused stack on its current display, {@code false}
+     * otherwise.
+     */
+    boolean isFocusedStackOnDisplay() {
+        final ActivityDisplay display = getDisplay();
+        return display != null && this == display.getFocusedStack();
     }
 
     boolean isTopActivityVisible() {
@@ -1742,9 +1766,6 @@
         if (!isAttached() || mForceHidden) {
             return false;
         }
-        if (mStackSupervisor.isFocusedStack(this)) {
-            return true;
-        }
 
         final ActivityRecord top = topRunningActivityLocked();
         if (top == null && isInStackLocked(starting) == null && !isTopStackOnDisplay()) {
@@ -1874,7 +1895,7 @@
             boolean aboveTop = top != null;
             final boolean stackShouldBeVisible = shouldBeVisible(starting);
             boolean behindFullscreenActivity = !stackShouldBeVisible;
-            boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
+            boolean resumeNextActivity = mStackSupervisor.isTopDisplayFocusedStack(this)
                     && (isInStackLocked(starting) == null);
             final boolean isTopNotPinnedStack =
                     isAttached() && getDisplay().isTopNotPinnedStack(this);
@@ -2285,7 +2306,7 @@
      *
      * NOTE: It is not safe to call this method directly as it can cause an activity in a
      *       non-focused stack to be resumed.
-     *       Use {@link ActivityStackSupervisor#resumeFocusedStackTopActivityLocked} to resume the
+     *       Use {@link ActivityStackSupervisor#resumeFocusedStacksTopActivitiesLocked} to resume the
      *       right activity for the current system state.
      */
     @GuardedBy("mService")
@@ -2398,7 +2419,7 @@
         // Make sure that the user who owns this activity is started.  If not,
         // we will just leave it as is because someone should be bringing
         // another user's activities to the top of the stack.
-        if (!mService.mAm.mUserController.hasStartedUserState(next.userId)) {
+        if (!mService.mAmInternal.hasStartedUserState(next.userId)) {
             Slog.w(TAG, "Skipping resume of top activity " + next
                     + ": user " + next.userId + " is stopped");
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2426,7 +2447,7 @@
 
         boolean lastResumedCanPip = false;
         ActivityRecord lastResumed = null;
-        final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
+        final ActivityStack lastFocusedStack = mStackSupervisor.getTopDisplayLastFocusedStack();
         if (lastFocusedStack != null && lastFocusedStack != this) {
             // So, why aren't we using prev here??? See the param comment on the method. prev doesn't
             // represent the last resumed activity. However, the last focus stack does if it isn't null.
@@ -2448,7 +2469,7 @@
         final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
                 && !lastResumedCanPip;
 
-        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
+        boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
         if (mResumedActivity != null) {
             if (DEBUG_STATES) Slog.d(TAG_STATES,
                     "resumeTopActivityLocked: Pausing " + mResumedActivity);
@@ -2587,7 +2608,7 @@
 
         mStackSupervisor.mNoAnimActivities.clear();
 
-        ActivityStack lastStack = mStackSupervisor.getLastStack();
+        ActivityStack lastStack = mStackSupervisor.getTopDisplayLastFocusedStack();
         if (next.attachedToProcess()) {
             if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                     + " stopped=" + next.stopped + " visible=" + next.visible);
@@ -2637,7 +2658,7 @@
                 // the screen based on the new activity order.
                 boolean notUpdated = true;
 
-                if (mStackSupervisor.isFocusedStack(this)) {
+                if (isFocusedStackOnDisplay()) {
                     // We have special rotation behavior when here is some active activity that
                     // requests specific orientation or Keyguard is locked. Make sure all activity
                     // visibilities are set correctly as well as the transition is updated if needed
@@ -2700,10 +2721,8 @@
                             next.shortComponentName);
 
                     next.sleeping = false;
-                    mService.mAm.getAppWarningsLocked().onResumeActivity(next);
-                    mService.mAm.showAskCompatModeDialogLocked(next);
-                    next.app.setPendingUiCleanAndForceProcessStateUpTo(
-                            mService.mAm.mTopProcessState);
+                    mService.getAppWarningsLocked().onResumeActivity(next);
+                    next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
                     next.clearOptionsLocked();
                     transaction.setLifecycleStateRequest(
                             ResumeActivityItem.obtain(next.app.getReportedProcState(),
@@ -2771,12 +2790,13 @@
 
     private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
             ActivityOptions options, String reason) {
-        if (adjustFocusToNextFocusableStack(reason)) {
+        final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(reason);
+        if (nextFocusedStack != null) {
             // Try to move focus to the next visible stack with a running activity if this
             // stack is not covering the entire screen or is on a secondary display (with no home
             // stack).
-            return mStackSupervisor.resumeFocusedStackTopActivityLocked(
-                    mStackSupervisor.getFocusedStack(), prev, null);
+            return mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(nextFocusedStack, prev,
+                    null /* targetOptions */);
         }
 
         // Let's just start up the Launcher...
@@ -2789,20 +2809,6 @@
                 mStackSupervisor.resumeHomeStackTask(prev, reason);
     }
 
-    private TaskRecord getNextTask(TaskRecord targetTask) {
-        final int index = mTaskHistory.indexOf(targetTask);
-        if (index >= 0) {
-            final int numTasks = mTaskHistory.size();
-            for (int i = index + 1; i < numTasks; ++i) {
-                TaskRecord task = mTaskHistory.get(i);
-                if (task.userId == targetTask.userId) {
-                    return task;
-                }
-            }
-        }
-        return null;
-    }
-
     /** Returns the position the input task should be placed in this stack. */
     int getAdjustedPositionForTask(TaskRecord task, int suggestedPosition,
             ActivityRecord starting) {
@@ -3349,7 +3355,7 @@
             String resultWho, int requestCode, int resultCode, Intent data) {
 
         if (callingUid > 0) {
-            mService.mAm.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
+            mService.mUgmInternal.grantUriPermissionFromIntent(callingUid, r.packageName,
                     data, r.getUriPermissionsLocked(), r.userId);
         }
 
@@ -3389,7 +3395,7 @@
     }
 
     private void adjustFocusedActivityStack(ActivityRecord r, String reason) {
-        if (!mStackSupervisor.isFocusedStack(this) ||
+        if (!mStackSupervisor.isTopDisplayFocusedStack(this) ||
                 ((mResumedActivity != r) && (mResumedActivity != null))) {
             return;
         }
@@ -3417,7 +3423,15 @@
         }
 
         // Move focus to next focusable stack if possible.
-        if (adjustFocusToNextFocusableStack(myReason)) {
+        final ActivityStack nextFocusableStack = adjustFocusToNextFocusableStack(myReason);
+        if (nextFocusableStack != null) {
+            final ActivityRecord top = nextFocusableStack.topRunningActivityLocked();
+            if (top != null && top == mStackSupervisor.getTopResumedActivity()) {
+                // TODO(b/111361570): Remove this and update focused app per-display in
+                // WindowManager every time an activity becomes resumed in
+                // ActivityTaskManagerService#setResumedActivityUncheckLocked().
+                mService.setResumedActivityUncheckLocked(top, reason);
+            }
             return;
         }
 
@@ -3425,21 +3439,25 @@
         mStackSupervisor.moveHomeStackTaskToTop(myReason);
     }
 
-    /** Find next proper focusable stack and make it focused. */
-    boolean adjustFocusToNextFocusableStack(String reason) {
+    /**
+     * Find next proper focusable stack and make it focused.
+     * @return The stack that now got the focus, {@code null} if none found.
+     */
+    ActivityStack adjustFocusToNextFocusableStack(String reason) {
         return adjustFocusToNextFocusableStack(reason, false /* allowFocusSelf */);
     }
 
     /**
      * Find next proper focusable stack and make it focused.
      * @param allowFocusSelf Is the focus allowed to remain on the same stack.
+     * @return The stack that now got the focus, {@code null} if none found.
      */
-    private boolean adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) {
+    private ActivityStack adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) {
         final ActivityStack stack =
                 mStackSupervisor.getNextFocusableStackLocked(this, !allowFocusSelf);
         final String myReason = reason + " adjustFocusToNextFocusableStack";
         if (stack == null) {
-            return false;
+            return null;
         }
 
         final ActivityRecord top = stack.topRunningActivityLocked();
@@ -3447,11 +3465,12 @@
         if (stack.isActivityTypeHome() && (top == null || !top.visible)) {
             // If we will be focusing on the home stack next and its current top activity isn't
             // visible, then use the move the home stack task to top to make the activity visible.
-            return mStackSupervisor.moveHomeStackTaskToTop(reason);
+            mStackSupervisor.moveHomeStackTaskToTop(reason);
+            return stack;
         }
 
         stack.moveToFront(myReason);
-        return true;
+        return stack;
     }
 
     final void stopActivityLocked(ActivityRecord r) {
@@ -3546,7 +3565,7 @@
                 }
             }
         }
-        mService.mAm.updateOomAdjLocked();
+        mService.updateOomAdj();
     }
 
     /**
@@ -3626,7 +3645,7 @@
                         } catch (RemoteException re) {
                             // Ok
                         }
-                        mService.mAm.finishRunningVoiceLocked();
+                        mService.finishRunningVoiceLocked();
                         break;
                     }
                 }
@@ -3634,7 +3653,7 @@
         }
 
         if (didOne) {
-            mService.mAm.updateOomAdjLocked();
+            mService.updateOomAdj();
         }
     }
 
@@ -3663,7 +3682,7 @@
                 }
             }
             if (r.info.applicationInfo.uid > 0) {
-                mService.mAm.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
+                mService.mUgmInternal.grantUriPermissionFromIntent(r.info.applicationInfo.uid,
                         resultTo.packageName, resultData,
                         resultTo.getUriPermissionsLocked(), resultTo.userId);
             }
@@ -3823,7 +3842,7 @@
                     "Moving to STOPPING: "+ r + " (finish requested)");
             r.setState(STOPPING, "finishCurrentActivityLocked");
             if (oomAdj) {
-                mService.mAm.updateOomAdjLocked();
+                mService.updateOomAdj();
             }
             return r;
         }
@@ -3837,7 +3856,7 @@
 
         r.setState(FINISHING, "finishCurrentActivityLocked");
         final boolean finishingActivityInNonFocusedStack
-                = r.getStack() != mStackSupervisor.getFocusedStack()
+                = r.getStack() != mStackSupervisor.getTopDisplayFocusedStack()
                 && prevState == PAUSED && mode == FINISH_AFTER_VISIBLE;
 
         if (mode == FINISH_IMMEDIATELY
@@ -3857,7 +3876,7 @@
                         false /* markFrozenIfConfigChanged */, true /* deferResume */);
             }
             if (activityRemoved) {
-                mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
             }
             if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
                     "destroyActivityLocked: finishCurrentActivityLocked r=" + r +
@@ -3870,7 +3889,7 @@
         if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r);
         mStackSupervisor.mFinishingActivities.add(r);
         r.resumeKeyDispatchingLocked();
-        mStackSupervisor.resumeFocusedStackTopActivityLocked();
+        mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
         return r;
     }
 
@@ -4216,7 +4235,7 @@
             }
         }
         if (activityRemoved) {
-            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
         }
     }
 
@@ -4411,7 +4430,7 @@
             }
         }
 
-        mStackSupervisor.resumeFocusedStackTopActivityLocked();
+        mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
     }
 
     private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
@@ -4464,7 +4483,14 @@
                         hasVisibleActivities = true;
                     }
                     final boolean remove;
-                    if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
+                    if ((r.mRelaunchReason == RELAUNCH_REASON_WINDOWING_MODE_RESIZE
+                            || r.mRelaunchReason == RELAUNCH_REASON_FREE_RESIZE)
+                            && r.launchCount < 3 && !r.finishing) {
+                        // If the process crashed during a resize, always try to relaunch it, unless
+                        // it has failed more than twice. Skip activities that's already finishing
+                        // cleanly by itself.
+                        remove = false;
+                    } else if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
                         // Don't currently have state for the activity, or
                         // it is finishing -- always remove it.
                         remove = true;
@@ -4637,7 +4663,7 @@
                 topActivity.supportsEnterPipOnTaskSwitch = true;
             }
 
-            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
             EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
 
             mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.taskId);
@@ -4708,7 +4734,7 @@
             return true;
         }
 
-        mStackSupervisor.resumeFocusedStackTopActivityLocked();
+        mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
         return true;
     }
 
@@ -4755,7 +4781,7 @@
         if (updatedConfig) {
             // Ensure the resumed state of the focus activity if we updated the configuration of
             // any activity.
-            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
         }
     }
 
@@ -4786,13 +4812,16 @@
                 final TaskRecord task = mTaskHistory.get(i);
                 if (task.isResizeable()) {
                     if (inFreeformWindowingMode()) {
-                        // TODO: Can be removed now since each freeform task is in its own stack.
+                        // TODO(b/71028874): Can be removed since each freeform task is its own
+                        //                   stack.
                         // For freeform stack we don't adjust the size of the tasks to match that
                         // of the stack, but we do try to make sure the tasks are still contained
                         // with the bounds of the stack.
-                        mTmpRect2.set(task.getOverrideBounds());
-                        fitWithinBounds(mTmpRect2, bounds);
-                        task.updateOverrideConfiguration(mTmpRect2);
+                        if (task.getOverrideBounds() != null) {
+                            mTmpRect2.set(task.getOverrideBounds());
+                            fitWithinBounds(mTmpRect2, bounds);
+                            task.updateOverrideConfiguration(mTmpRect2);
+                        }
                     } else {
                         task.updateOverrideConfiguration(taskBounds, insetBounds);
                     }
@@ -4946,7 +4975,7 @@
      */
     void getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType,
             @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed) {
-        boolean focusedStack = mStackSupervisor.getFocusedStack() == this;
+        boolean focusedStack = mStackSupervisor.getTopDisplayFocusedStack() == this;
         boolean topTask = true;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
@@ -5153,9 +5182,9 @@
             // We only need to adjust focused stack if this stack is in focus and we are not in the
             // process of moving the task to the top of the stack that will be focused.
             if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
-                    && mStackSupervisor.isFocusedStack(this)) {
+                    && mStackSupervisor.isTopDisplayFocusedStack(this)) {
                 String myReason = reason + " leftTaskHistoryEmpty";
-                if (!inMultiWindowMode() || !adjustFocusToNextFocusableStack(myReason)) {
+                if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
                     mStackSupervisor.moveHomeStackToFront(myReason);
                 }
             }
@@ -5260,7 +5289,7 @@
         // The task might have already been running and its visibility needs to be synchronized with
         // the visibility of the stack / windows.
         ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
-        mStackSupervisor.resumeFocusedStackTopActivityLocked();
+        mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
     }
 
     private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) {
@@ -5300,7 +5329,7 @@
         // always on top windows. Since the position the stack should be inserted into is calculated
         // properly in {@link ActivityDisplay#getTopInsertPosition()} in both cases, we can just
         // request that the stack is put at top here.
-        display.positionChildAtTop(this);
+        display.positionChildAtTop(this, false /* includingParents */);
     }
 
     void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume,
@@ -5357,16 +5386,16 @@
 
         // Do not sleep activities in this stack if we're marked as focused and the keyguard
         // is in the process of going away.
-        if (mStackSupervisor.getFocusedStack() == this
+        if (mStackSupervisor.getTopDisplayFocusedStack() == this
                 && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) {
             return false;
         }
 
-        return display != null ? display.isSleeping() : mService.mAm.isSleepingLocked();
+        return display != null ? display.isSleeping() : mService.isSleepingLocked();
     }
 
     boolean shouldSleepOrShutDownActivities() {
-        return shouldSleepActivities() || mService.mAm.isShuttingDownLocked();
+        return shouldSleepActivities() || mService.mShuttingDown;
     }
 
     public void writeToProto(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 1cb6be6..9809bfa 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -17,10 +17,8 @@
 package com.android.server.am;
 
 import static android.Manifest.permission.ACTIVITY_EMBEDDING;
-import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.START_ANY_ACTIVITY;
-import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
 import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
@@ -74,8 +72,8 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityManagerService.ANIMATE;
 import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
+import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_NONE;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
@@ -95,6 +93,7 @@
 import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
 import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
 import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
+import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
 import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
 import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 
@@ -199,8 +198,8 @@
     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
     private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
     private static final String TAG_STACK = TAG + POSTFIX_STACK;
-    private static final String TAG_STATES = TAG + POSTFIX_STATES;
     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
+    static final String TAG_STATES = TAG + POSTFIX_STATES;
     static final String TAG_TASKS = TAG + POSTFIX_TASKS;
 
     /** How long we wait until giving up on the last activity telling us it is idle. */
@@ -336,9 +335,6 @@
      * Display.DEFAULT_DISPLAY. */
     ActivityStack mHomeStack;
 
-    /** The stack currently receiving input or launching the next activity. */
-    ActivityStack mFocusedStack;
-
     /** If this is the same as mFocusedStack then the activity on the top of the focused stack has
      * been resumed. If stacks are changing position this will hold the old stack until the new
      * stack becomes resumed after which it will be set to mFocusedStack. */
@@ -624,7 +620,7 @@
         mInitialized = true;
         mRunningTasks = createRunningTasks();
         mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext, mHandler.getLooper());
-        mKeyguardController = new KeyguardController(mService.mAm, this);
+        mKeyguardController = new KeyguardController(mService, this);
 
         mLaunchParamsController = new LaunchParamsController(mService);
         mLaunchParamsController.registerDefaultModifiers(this);
@@ -682,12 +678,62 @@
             calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
         }
 
-        mHomeStack = mFocusedStack = mLastFocusedStack = getDefaultDisplay().getOrCreateStack(
+        final ActivityDisplay defaultDisplay = getDefaultDisplay();
+        mHomeStack = mLastFocusedStack = defaultDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
     }
 
-    ActivityStack getFocusedStack() {
-        return mFocusedStack;
+    ActivityStack getTopDisplayFocusedStack() {
+        mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
+
+        for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
+            final int displayId = mTmpOrderedDisplayIds.get(i);
+            final ActivityDisplay display = mActivityDisplays.get(displayId);
+
+            // If WindowManagerService has encountered the display before we have, ignore as there
+            // will be no stacks present and therefore no activities.
+            if (display == null) {
+                continue;
+            }
+            final ActivityStack focusedStack = display.getFocusedStack();
+            if (focusedStack != null) {
+                return focusedStack;
+            }
+        }
+        return null;
+    }
+
+    ActivityRecord getTopResumedActivity() {
+        if (mWindowManager == null) {
+            return null;
+        }
+
+        final ActivityStack focusedStack = getTopDisplayFocusedStack();
+        if (focusedStack == null) {
+            return null;
+        }
+        final ActivityRecord resumedActivity = focusedStack.getResumedActivity();
+        if (resumedActivity != null && resumedActivity.app != null) {
+            return resumedActivity;
+        }
+        // The top focused stack might not have a resumed activity yet - look on all displays in
+        // focus order.
+        mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
+        for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
+            final int displayId = mTmpOrderedDisplayIds.get(i);
+            final ActivityDisplay display = mActivityDisplays.get(displayId);
+
+            // If WindowManagerService has encountered the display before we have, ignore as there
+            // will be no stacks present and therefore no activities.
+            if (display == null) {
+                continue;
+            }
+            final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity();
+            if (resumedActivityOnDisplay != null) {
+                return resumedActivityOnDisplay;
+            }
+        }
+        return null;
     }
 
     boolean isFocusable(ConfigurationContainer container, boolean alwaysFocusable) {
@@ -698,12 +744,12 @@
         return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable;
     }
 
-    ActivityStack getLastStack() {
+    ActivityStack getTopDisplayLastFocusedStack() {
         return mLastFocusedStack;
     }
 
-    boolean isFocusedStack(ActivityStack stack) {
-        return stack != null && stack == mFocusedStack;
+    boolean isTopDisplayFocusedStack(ActivityStack stack) {
+        return stack != null && stack == getTopDisplayFocusedStack();
     }
 
     /** NOTE: Should only be called from {@link ActivityStack#moveToFront} */
@@ -718,12 +764,12 @@
             }
         }
 
-        if (focusCandidate != mFocusedStack) {
-            mLastFocusedStack = mFocusedStack;
-            mFocusedStack = focusCandidate;
-
+        final ActivityStack currentFocusedStack = getTopDisplayFocusedStack();
+        if (currentFocusedStack != focusCandidate) {
+            mLastFocusedStack = currentFocusedStack;
+            // TODO(b/111541062): Update event log to include focus movements on all displays
             EventLogTags.writeAmFocusedStack(
-                    mCurrentUser, mFocusedStack == null ? -1 : mFocusedStack.getStackId(),
+                    mCurrentUser, focusCandidate == null ? -1 : focusCandidate.getStackId(),
                     mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), reason);
         }
 
@@ -772,7 +818,7 @@
         // Only resume home activity if isn't finishing.
         if (r != null && !r.finishing) {
             moveFocusableActivityStackToFrontLocked(r, myReason);
-            return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
+            return resumeFocusedStacksTopActivitiesLocked(mHomeStack, prev, null);
         }
         return mService.mAm.startHomeActivityLocked(mCurrentUser, myReason);
     }
@@ -912,7 +958,7 @@
                         // result to an activity belonging to userId. Example case: a document
                         // picker for personal files, opened by a work app, should still get locked.
                         if (taskTopActivityIsUser(task, userId)) {
-                            mService.mAm.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskProfileLocked(
+                            mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
                                     task.taskId, userId);
                         }
                     }
@@ -961,21 +1007,6 @@
         return candidateTaskId;
     }
 
-    ActivityRecord getResumedActivityLocked() {
-        ActivityStack stack = mFocusedStack;
-        if (stack == null) {
-            return null;
-        }
-        ActivityRecord resumedActivity = stack.getResumedActivity();
-        if (resumedActivity == null || resumedActivity.app == null) {
-            resumedActivity = stack.mPausingActivity;
-            if (resumedActivity == null || resumedActivity.app == null) {
-                resumedActivity = stack.topRunningActivityLocked();
-            }
-        }
-        return resumedActivity;
-    }
-
     boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
         final String processName = app.processName;
         boolean didSomething = false;
@@ -983,7 +1014,7 @@
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
-                if (!isFocusedStack(stack)) {
+                if (!isTopDisplayFocusedStack(stack)) {
                     continue;
                 }
                 stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
@@ -1018,7 +1049,7 @@
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
-                if (!isFocusedStack(stack) || stack.numActivities() == 0) {
+                if (!isTopDisplayFocusedStack(stack) || stack.numActivities() == 0) {
                     continue;
                 }
                 final ActivityRecord resumedActivity = stack.getResumedActivity();
@@ -1039,7 +1070,7 @@
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
-                if (isFocusedStack(stack)) {
+                if (isTopDisplayFocusedStack(stack)) {
                     final ActivityRecord r = stack.getResumedActivity();
                     if (r != null && !r.isState(RESUMED)) {
                         return false;
@@ -1048,10 +1079,11 @@
             }
         }
         // TODO: Not sure if this should check if all Paused are complete too.
+        final ActivityStack focusedStack = getTopDisplayFocusedStack();
         if (DEBUG_STACK) Slog.d(TAG_STACK,
-                "allResumedActivitiesComplete: mLastFocusedStack changing from=" +
-                mLastFocusedStack + " to=" + mFocusedStack);
-        mLastFocusedStack = mFocusedStack;
+                "allResumedActivitiesComplete: mLastFocusedStack changing from="
+                        + mLastFocusedStack + " to=" + focusedStack);
+        mLastFocusedStack = focusedStack;
         return true;
     }
 
@@ -1084,16 +1116,8 @@
     boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
         boolean someActivityPaused = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                if (!isFocusedStack(stack) && stack.getResumedActivity() != null) {
-                    if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
-                            " mResumedActivity=" + stack.getResumedActivity());
-                    someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
-                            dontWait);
-                }
-            }
+            someActivityPaused |= mActivityDisplays.valueAt(displayNdx)
+                    .pauseBackStacks(userLeaving, resuming, dontWait);
         }
         return someActivityPaused;
     }
@@ -1167,7 +1191,7 @@
             }
         }
         if (changed) {
-            mService.mAm.notifyAll();
+            mService.mGlobalLock.notifyAll();
         }
     }
 
@@ -1197,7 +1221,7 @@
         }
 
         if (changed) {
-            mService.mAm.notifyAll();
+            mService.mGlobalLock.notifyAll();
         }
     }
 
@@ -1218,7 +1242,7 @@
             }
         }
         if (changed) {
-            mService.mAm.notifyAll();
+            mService.mGlobalLock.notifyAll();
         }
     }
 
@@ -1235,7 +1259,7 @@
      * @return The top running activity. {@code null} if none is available.
      */
     ActivityRecord topRunningActivityLocked(boolean considerKeyguardState) {
-        final ActivityStack focusedStack = mFocusedStack;
+        final ActivityStack focusedStack = getTopDisplayFocusedStack();
         ActivityRecord r = focusedStack.topRunningActivityLocked();
         if (r != null && isValidTopRunningActivity(r, considerKeyguardState)) {
             return r;
@@ -1365,7 +1389,7 @@
                 // (e.g. AMS.startActivityAsUser).
                 final long token = Binder.clearCallingIdentity();
                 try {
-                    return mService.mAm.getPackageManagerInternalLocked().resolveIntent(
+                    return mService.getPackageManagerInternalLocked().resolveIntent(
                             intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
                 } finally {
                     Binder.restoreCallingIdentity(token);
@@ -1488,8 +1512,7 @@
                         PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
                 r.sleeping = false;
                 r.forceNewConfig = false;
-                mService.mAm.getAppWarningsLocked().onStartActivity(r);
-                mService.mAm.showAskCompatModeDialogLocked(r);
+                mService.getAppWarningsLocked().onStartActivity(r);
                 r.compat = mService.mAm.compatibilityInfoForPackageLocked(r.info.applicationInfo);
                 ProfilerInfo profilerInfo = null;
                 if (mService.mAm.mProfileApp != null && mService.mAm.mProfileApp.equals(app.processName)) {
@@ -1512,13 +1535,13 @@
 
                 app.hasShownUi = true;
                 app.pendingUiClean = true;
-                app.forceProcessStateUpTo(mService.mAm.mTopProcessState);
+                app.forceProcessStateUpTo(mService.mTopProcessState);
                 // Because we could be starting an Activity in the system process this may not go
                 // across a Binder interface which would create a new Configuration. Consequently
                 // we have to always create a new Configuration here.
 
                 final MergedConfiguration mergedConfiguration = new MergedConfiguration(
-                        mService.mAm.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
+                        mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
                 r.setLastReportedConfiguration(mergedConfiguration);
 
                 logIfTransactionTooLarge(r.intent, r.icicle);
@@ -1617,7 +1640,7 @@
         // launching the initial activity (that is, home), so that it can have
         // a chance to initialize itself while in the background, making the
         // switch back to it faster and look better.
-        if (isFocusedStack(stack)) {
+        if (isTopDisplayFocusedStack(stack)) {
             mService.getActivityStartController().startSetupActivity();
         }
 
@@ -1724,12 +1747,27 @@
         boolean sendHint = forceSend;
 
         if (!sendHint) {
-            // If not forced, send power hint when the activity's process is different than the
-            // current resumed activity.
-            final ActivityRecord resumedActivity = getResumedActivityLocked();
-            sendHint = resumedActivity == null
-                    || resumedActivity.app == null
-                    || !resumedActivity.app.equals(targetActivity.app);
+            // Send power hint if we don't know what we're launching yet
+            sendHint = targetActivity == null || targetActivity.app == null;
+        }
+
+        if (!sendHint) { // targetActivity != null
+            // Send power hint when the activity's process is different than the current resumed
+            // activity on all displays, or if there are no resumed activities in the system.
+            boolean noResumedActivities = true;
+            boolean allFocusedProcessesDiffer = true;
+            for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
+                final ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
+                final ActivityRecord resumedActivity = activityDisplay.getResumedActivity();
+                final WindowProcessController resumedActivityProcess =
+                    resumedActivity == null ? null : resumedActivity.app;
+
+                noResumedActivities &= resumedActivityProcess == null;
+                if (resumedActivityProcess != null) {
+                    allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app);
+                }
+            }
+            sendHint = noResumedActivities || allFocusedProcessesDiffer;
         }
 
         if (sendHint && mService.mAm.mLocalPowerManager != null) {
@@ -1752,7 +1790,7 @@
             ProcessRecord callerApp, ActivityRecord resultRecord, ActivityStack resultStack) {
         final boolean isCallerRecents = mService.getRecentTasks() != null
                 && mService.getRecentTasks().isCallerRecents(callingUid);
-        final int startAnyPerm = mService.mAm.checkPermission(START_ANY_ACTIVITY, callingPid,
+        final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid,
                 callingUid);
         if (startAnyPerm == PERMISSION_GRANTED || (isCallerRecents && launchingInTask)) {
             // If the caller has START_ANY_ACTIVITY, ignore all checks below. In addition, if the
@@ -1831,7 +1869,7 @@
 
         // Check if the caller has enough privileges to embed activities and launch to private
         // displays.
-        final int startAnyPerm = mService.mAm.checkPermission(INTERNAL_SYSTEM_WINDOW, callingPid,
+        final int startAnyPerm = mService.checkPermission(INTERNAL_SYSTEM_WINDOW, callingPid,
                 callingUid);
         if (startAnyPerm == PERMISSION_GRANTED) {
             if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
@@ -1853,7 +1891,7 @@
                 return false;
             }
             // Check if the caller is allowed to embed activities from other apps.
-            if (mService.mAm.checkPermission(ACTIVITY_EMBEDDING, callingPid, callingUid)
+            if (mService.checkPermission(ACTIVITY_EMBEDDING, callingPid, callingUid)
                     == PERMISSION_DENIED && !uidPresentOnDisplay) {
                 if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
                         + " disallow activity embedding without permission.");
@@ -1926,8 +1964,8 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.mAm.mAppOpsService.noteOperation(opCode, callingUid,
-                callingPackage) != AppOpsManager.MODE_ALLOWED) {
+        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage)
+                != AppOpsManager.MODE_ALLOWED) {
             if (!ignoreTargetSecurity) {
                 return ACTIVITY_RESTRICTION_APPOP;
             }
@@ -1960,7 +1998,7 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.mAm.checkPermission(permission, callingPid, callingUid) == PERMISSION_DENIED) {
+        if (mService.checkPermission(permission, callingPid, callingUid) == PERMISSION_DENIED) {
             return ACTIVITY_RESTRICTION_PERMISSION;
         }
 
@@ -1969,8 +2007,8 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.mAm.mAppOpsService.noteOperation(opCode, callingUid,
-                callingPackage) != AppOpsManager.MODE_ALLOWED) {
+        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage)
+                != AppOpsManager.MODE_ALLOWED) {
             return ACTIVITY_RESTRICTION_APPOP;
         }
 
@@ -2048,14 +2086,18 @@
             r.idle = true;
 
             //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
-            if (isFocusedStack(r.getStack()) || fromTimeout) {
+            if (isTopDisplayFocusedStack(r.getStack()) || fromTimeout) {
                 booting = checkFinishBootingLocked();
             }
+
+            // When activity is idle, we consider the relaunch must be successful, so let's clear
+            // the flag.
+            r.mRelaunchReason = RELAUNCH_REASON_NONE;
         }
 
         if (allResumedActivitiesIdle()) {
             if (r != null) {
-                mService.mAm.scheduleAppGcsLocked();
+                mService.scheduleAppGcsLocked();
             }
 
             if (mLaunchingActivity.isHeld()) {
@@ -2112,17 +2154,17 @@
             // Complete user switch
             if (startingUsers != null) {
                 for (int i = 0; i < startingUsers.size(); i++) {
-                    mService.mAm.mUserController.finishUserSwitch(startingUsers.get(i));
+                    mService.mAmInternal.finishUserSwitch(startingUsers.get(i));
                 }
             }
         }
 
-        mService.mAm.trimApplications();
+        mService.mAmInternal.trimApplications();
         //dump();
         //mWindowManager.dump();
 
         if (activityRemoved) {
-            resumeFocusedStackTopActivityLocked();
+            resumeFocusedStacksTopActivitiesLocked();
         }
 
         return r;
@@ -2196,7 +2238,7 @@
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
-                if (isFocusedStack(stack)) {
+                if (isTopDisplayFocusedStack(stack)) {
                     final ActivityRecord resumedActivity = stack.getResumedActivity();
                     if (resumedActivity != null) {
                         fgApp = resumedActivity.app;
@@ -2218,27 +2260,35 @@
         }
     }
 
-    boolean resumeFocusedStackTopActivityLocked() {
-        return resumeFocusedStackTopActivityLocked(null, null, null);
+    boolean resumeFocusedStacksTopActivitiesLocked() {
+        return resumeFocusedStacksTopActivitiesLocked(null, null, null);
     }
 
-    boolean resumeFocusedStackTopActivityLocked(
+    boolean resumeFocusedStacksTopActivitiesLocked(
             ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
 
         if (!readyToResume()) {
             return false;
         }
 
-        if (targetStack != null && isFocusedStack(targetStack)) {
+        if (targetStack != null && targetStack.isTopStackOnDisplay()) {
             return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
         }
 
-        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
-        if (r == null || !r.isState(RESUMED)) {
-            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
-        } else if (r.isState(RESUMED)) {
-            // Kick off any lingering app transitions form the MoveTaskToFront operation.
-            mFocusedStack.executeAppTransition(targetOptions);
+        // Resume all top activities in focused stacks on all displays.
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+            final ActivityStack focusedStack = display.getFocusedStack();
+            if (focusedStack == null) {
+                continue;
+            }
+            final ActivityRecord r = focusedStack.topRunningActivityLocked();
+            if (r == null || !r.isState(RESUMED)) {
+                focusedStack.resumeTopActivityUncheckedLocked(null, null);
+            } else if (r.isState(RESUMED)) {
+                // Kick off any lingering app transitions form the MoveTaskToFront operation.
+                focusedStack.executeAppTransition(targetOptions);
+            }
         }
 
         return false;
@@ -2262,7 +2312,7 @@
      */
     TaskRecord finishTopCrashedActivitiesLocked(WindowProcessController app, String reason) {
         TaskRecord finishedTask = null;
-        ActivityStack focusedStack = getFocusedStack();
+        ActivityStack focusedStack = getTopDisplayFocusedStack();
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             // It is possible that request to finish activity might also remove its task and stack,
@@ -2289,6 +2339,9 @@
         }
     }
 
+    /**
+     * This doesn't just find a task, it also moves the task to front.
+     */
     void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options, String reason,
             boolean forceNonResizeable) {
         final ActivityStack currentStack = task.getStack();
@@ -2452,8 +2505,7 @@
         }
         if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) {
             if (r != null) {
-                // TODO: This should also take in the windowing mode and activity type into account.
-                stack = (T) getValidLaunchStackOnDisplay(displayId, r);
+                stack = (T) getValidLaunchStackOnDisplay(displayId, r, options);
                 if (stack != null) {
                     return stack;
                 }
@@ -2498,12 +2550,7 @@
             }
         }
 
-        if (display == null
-                || !canLaunchOnDisplay(r, display.mDisplayId)
-                // TODO: Can be removed once we figure-out how non-standard types should launch
-                // outside the default display.
-                || (activityType != ACTIVITY_TYPE_STANDARD
-                && activityType != ACTIVITY_TYPE_UNDEFINED)) {
+        if (display == null || !canLaunchOnDisplay(r, display.mDisplayId)) {
             display = getDefaultDisplay();
         }
 
@@ -2525,7 +2572,8 @@
      * @param r Activity that should be launched there.
      * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
      */
-    ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r) {
+    ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
+            @Nullable ActivityOptions options) {
         final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
         if (activityDisplay == null) {
             throw new IllegalArgumentException(
@@ -2547,7 +2595,9 @@
         // If there is no valid stack on the external display - check if new dynamic stack will do.
         if (displayId != DEFAULT_DISPLAY) {
             return activityDisplay.createStack(
-                    r.getWindowingMode(), r.getActivityType(), true /*onTop*/);
+                    options != null ? options.getLaunchWindowingMode() : r.getWindowingMode(),
+                    options != null ? options.getLaunchActivityType() : r.getActivityType(),
+                    true /*onTop*/);
         }
 
         Slog.w(TAG, "getValidLaunchStackOnDisplay: can't launch on displayId " + displayId);
@@ -2561,74 +2611,58 @@
             case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents();
             case ACTIVITY_TYPE_ASSISTANT: return r.isActivityTypeAssistant();
         }
-        switch (stack.getWindowingMode()) {
-            case WINDOWING_MODE_FULLSCREEN: return true;
-            case WINDOWING_MODE_FREEFORM: return r.supportsFreeform();
-            case WINDOWING_MODE_PINNED: return r.supportsPictureInPicture();
-            case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return r.supportsSplitScreenWindowingMode();
-            case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return r.supportsSplitScreenWindowingMode();
+        // There is a 1-to-1 relationship between stack and task when not in
+        // primary split-windowing mode.
+        if (stack.getWindowingMode() != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+            return false;
+        } else {
+            return r.supportsSplitScreenWindowingMode();
         }
-
-        if (!stack.isOnHomeDisplay()) {
-            return r.canBeLaunchedOnDisplay(displayId);
-        }
-        Slog.e(TAG, "isValidLaunchStack: Unexpected stack=" + stack);
-        return false;
     }
 
     /**
-     * Get next focusable stack in the system. This will search across displays and stacks
-     * in last-focused order for a focusable and visible stack, different from the target stack.
+     * Get next focusable stack in the system. This will search through the stack on the same
+     * display as the current focused stack, looking for a focusable and visible stack, different
+     * from the target stack. If no valid candidates will be found, it will then go through all
+     * displays and stacks in last-focused order.
      *
      * @param currentFocus The stack that previously had focus.
      * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next
      *                     candidate.
-     * @return Next focusable {@link ActivityStack}, null if not found.
+     * @return Next focusable {@link ActivityStack}, {@code null} if not found.
      */
-    ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus, boolean ignoreCurrent) {
-        mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
+    ActivityStack getNextFocusableStackLocked(@NonNull ActivityStack currentFocus,
+            boolean ignoreCurrent) {
+        // First look for next focusable stack on the same display
+        final ActivityDisplay preferredDisplay = currentFocus.getDisplay();
+        final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
+                currentFocus, ignoreCurrent);
+        if (preferredFocusableStack != null) {
+            return preferredFocusableStack;
+        }
 
-        final int currentWindowingMode = currentFocus != null
-                ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
-        ActivityStack candidate = null;
+        // Now look through all displays
+        mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
         for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
             final int displayId = mTmpOrderedDisplayIds.get(i);
+            if (displayId == preferredDisplay.mDisplayId) {
+                // We've already checked this one
+                continue;
+            }
             // If a display is registered in WM, it must also be available in AM.
             final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
             if (display == null) {
                 // Looks like the display no longer exists in the system...
                 continue;
             }
-            for (int j = display.getChildCount() - 1; j >= 0; --j) {
-                final ActivityStack stack = display.getChildAt(j);
-                if (ignoreCurrent && stack == currentFocus) {
-                    continue;
-                }
-                if (!stack.isFocusable() || !stack.shouldBeVisible(null)) {
-                    continue;
-                }
-
-                if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
-                        && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
-                    // If the currently focused stack is in split-screen secondary we save off the
-                    // top primary split-screen stack as a candidate for focus because we might
-                    // prefer focus to move to an other stack to avoid primary split-screen stack
-                    // overlapping with a fullscreen stack when a fullscreen stack is higher in z
-                    // than the next split-screen stack. Assistant stack, I am looking at you...
-                    // We only move the focus to the primary-split screen stack if there isn't a
-                    // better alternative.
-                    candidate = stack;
-                    continue;
-                }
-                if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
-                    // Use the candidate stack since we are now at the secondary split-screen.
-                    return candidate;
-                }
-                return stack;
+            final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus,
+                    ignoreCurrent);
+            if (nextFocusableStack != null) {
+                return nextFocusableStack;
             }
         }
 
-        return candidate;
+        return null;
     }
 
     /**
@@ -2648,7 +2682,8 @@
             if (displayId == currentFocus) {
                 continue;
             }
-            final ActivityStack stack = getValidLaunchStackOnDisplay(displayId, r);
+            final ActivityStack stack = getValidLaunchStackOnDisplay(displayId, r,
+                    null /* options */);
             if (stack != null) {
                 return stack;
             }
@@ -2826,7 +2861,7 @@
             }
 
             ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
-            resumeFocusedStackTopActivityLocked();
+            resumeFocusedStacksTopActivitiesLocked();
         } finally {
             mAllowDockedStackResize = true;
             mWindowManager.continueSurfaceLayout();
@@ -3133,7 +3168,7 @@
 
                 if (!proc.shouldKillProcessForRemovedTask(tr)) {
                     // Don't kill process(es) that has an activity in a different task that is also
-                    // in recents.
+                    // in recents, or has an activity not stopped.
                     return;
                 }
 
@@ -3195,12 +3230,12 @@
     }
 
     @Override
-    public void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed) {
+    public void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed, boolean killProcess) {
         if (wasTrimmed) {
             // Task was trimmed from the recent tasks list -- remove the active task record as well
             // since the user won't really be able to go back to it
-            removeTaskByIdLocked(task.taskId, false /* killProcess */,
-                    false /* removeFromRecents */, !PAUSE_IMMEDIATELY, "recent-task-trimmed");
+            removeTaskByIdLocked(task.taskId, killProcess, false /* removeFromRecents */,
+                    !PAUSE_IMMEDIATELY, "recent-task-trimmed");
         }
         task.removedFromRecents();
     }
@@ -3383,7 +3418,7 @@
         // drawn signal is scheduled after the bounds animation start call on the bounds animator
         // thread.
         ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
-        resumeFocusedStackTopActivityLocked();
+        resumeFocusedStacksTopActivitiesLocked();
 
         mService.getTaskChangeNotificationController().notifyActivityPinned(r);
     }
@@ -3404,7 +3439,7 @@
             return false;
         }
 
-        if (stack == mFocusedStack && stack.topRunningActivityLocked() == r) {
+        if (r == getTopResumedActivity()) {
             if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
                     "moveActivityStackToFront: already on top, r=" + r);
             return false;
@@ -3414,6 +3449,11 @@
                 "moveActivityStackToFront: r=" + r);
 
         stack.moveToFront(reason, task);
+        // Report top activity change to tracking services and WM
+        if (r == getTopResumedActivity()) {
+            // TODO(b/111361570): Support multiple focused apps in WM
+            mService.setResumedActivityUncheckLocked(r, reason);
+        }
         return true;
     }
 
@@ -3517,7 +3557,7 @@
                 long timeRemaining = endTime - System.currentTimeMillis();
                 if (timeRemaining > 0) {
                     try {
-                        mService.mAm.wait(timeRemaining);
+                        mService.mGlobalLock.wait(timeRemaining);
                     } catch (InterruptedException e) {
                     }
                 } else {
@@ -3564,13 +3604,13 @@
                     stack.goToSleepIfPossible(false /* shuttingDown */);
                 } else {
                     stack.awakeFromSleepingLocked();
-                    if (isFocusedStack(stack) && !getKeyguardController().isKeyguardOrAodShowing(
-                            display.mDisplayId)) {
+                    if (isTopDisplayFocusedStack(stack) && !getKeyguardController()
+                            .isKeyguardOrAodShowing(display.mDisplayId)) {
                         // If the keyguard is unlocked - resume immediately.
                         // It is possible that the display will not be awake at the time we
                         // process the keyguard going away, which can happen before the sleep token
                         // is released. As a result, it is important we resume the activity here.
-                        resumeFocusedStackTopActivityLocked();
+                        resumeFocusedStacksTopActivitiesLocked();
                     }
                 }
             }
@@ -3599,7 +3639,7 @@
     }
 
     void checkReadyForSleepLocked(boolean allowDelay) {
-        if (!mService.mAm.isSleepingOrShuttingDownLocked()) {
+        if (!mService.isSleepingOrShuttingDownLocked()) {
             // Do not care.
             return;
         }
@@ -3616,8 +3656,8 @@
         if (mGoingToSleep.isHeld()) {
             mGoingToSleep.release();
         }
-        if (mService.mAm.mShuttingDown) {
-            mService.mAm.notifyAll();
+        if (mService.mShuttingDown) {
+            mService.mGlobalLock.notifyAll();
         }
     }
 
@@ -3644,7 +3684,7 @@
         mStoppingActivities.remove(r);
 
         final ActivityStack stack = r.getStack();
-        if (isFocusedStack(stack)) {
+        if (isTopDisplayFocusedStack(stack)) {
             mService.mAm.updateUsageStats(r, true);
         }
         if (allResumedActivitiesComplete()) {
@@ -3792,11 +3832,11 @@
     }
 
     boolean switchUserLocked(int userId, UserState uss) {
-        final int focusStackId = mFocusedStack.getStackId();
+        final int focusStackId = getTopDisplayFocusedStack().getStackId();
         // We dismiss the docked stack whenever we switch users.
         final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack();
         if (dockedStack != null) {
-            moveTasksToFullscreenStackLocked(dockedStack, mFocusedStack == dockedStack);
+            moveTasksToFullscreenStackLocked(dockedStack, dockedStack.isFocusedStackOnDisplay());
         }
         // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
         // also cause all tasks to be moved to the fullscreen stack at a position that is
@@ -3837,7 +3877,7 @@
     /** Checks whether the userid is a profile of the current user. */
     boolean isCurrentProfileLocked(int userId) {
         if (userId == mCurrentUser) return true;
-        return mService.mAm.mUserController.isCurrentProfile(userId);
+        return mService.mAmInternal.isCurrentProfile(userId);
     }
 
     /**
@@ -3884,7 +3924,7 @@
                 final ActivityStack stack = s.getStack();
                 final boolean shouldSleepOrShutDown = stack != null
                         ? stack.shouldSleepOrShutDownActivities()
-                        : mService.mAm.isSleepingOrShuttingDownLocked();
+                        : mService.isSleepingOrShuttingDownLocked();
                 if (!waitingVisible || shouldSleepOrShutDown) {
                     if (!processPausingActivities && s.isState(PAUSING)) {
                         // Defer processing pausing activities in this iteration and reschedule
@@ -3918,7 +3958,7 @@
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 final ActivityRecord r = stack.topRunningActivityLocked();
                 final ActivityState state = r == null ? DESTROYED : r.getState();
-                if (isFocusedStack(stack)) {
+                if (isTopDisplayFocusedStack(stack)) {
                     if (r == null) Slog.e(TAG,
                             "validateTop...: null top activity, stack=" + stack);
                     else {
@@ -3952,7 +3992,7 @@
     }
 
     public void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack);
+        pw.print(prefix); pw.print("mFocusedStack=" + getTopDisplayFocusedStack());
                 pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack);
         pw.print(prefix);
         pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser);
@@ -3978,13 +4018,15 @@
         final long token = proto.start(fieldId);
         super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
         for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
-            ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
+            final ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
             activityDisplay.writeToProto(proto, DISPLAYS);
         }
         getKeyguardController().writeToProto(proto, KEYGUARD_CONTROLLER);
-        if (mFocusedStack != null) {
-            proto.write(FOCUSED_STACK_ID, mFocusedStack.mStackId);
-            ActivityRecord focusedActivity = getResumedActivityLocked();
+        // TODO(b/111541062): Update tests to look for resumed activities on all displays
+        final ActivityStack focusedStack = getTopDisplayFocusedStack();
+        if (focusedStack != null) {
+            proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
+            final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
             if (focusedActivity != null) {
                 focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
             }
@@ -3993,6 +4035,7 @@
         }
         proto.write(IS_HOME_RECENTS_COMPONENT,
                 mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser));
+        mService.getActivityStartController().writeToProto(proto, PENDING_ACTIVITIES);
         proto.end(token);
     }
 
@@ -4017,7 +4060,7 @@
     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name, boolean dumpVisibleStacksOnly,
             boolean dumpFocusedStackOnly) {
         if (dumpFocusedStackOnly) {
-            return mFocusedStack.getDumpActivitiesLocked(name);
+            return getTopDisplayFocusedStack().getDumpActivitiesLocked(name);
         } else {
             ArrayList<ActivityRecord> activities = new ArrayList<>();
             int numDisplays = mActivityDisplays.size();
@@ -4099,6 +4142,8 @@
                 }
                 needSep = printed;
             }
+            printThisActivity(pw, activityDisplay.getResumedActivity(), dumpPackage, needSep,
+                    " ResumedActivity:");
         }
 
         printed |= dumpHistoryList(fd, pw, mFinishingActivities, "  ", "Fin", false, !dumpAll,
@@ -4329,7 +4374,7 @@
                     int displayState = activityDisplay.mDisplay.getState();
                     if (displayState == Display.STATE_OFF && activityDisplay.mOffToken == null) {
                         activityDisplay.mOffToken =
-                                mService.mAm.acquireSleepToken("Display-off", displayId);
+                                mService.acquireSleepToken("Display-off", displayId);
                     } else if (displayState == Display.STATE_ON
                             && activityDisplay.mOffToken != null) {
                         activityDisplay.mOffToken.release();
@@ -4362,7 +4407,7 @@
         if (display != null) {
             display.mAllSleepTokens.remove(token);
             if (display.mAllSleepTokens.isEmpty()) {
-                mService.mAm.updateSleepIfNeededLocked();
+                mService.updateSleepIfNeededLocked();
             }
         }
     }
@@ -4376,7 +4421,7 @@
         }
         display.mAllSleepTokens.clear();
 
-        mService.mAm.updateSleepIfNeededLocked();
+        mService.updateSleepIfNeededLocked();
     }
 
     private StackInfo getStackInfo(ActivityStack stack) {
@@ -4584,9 +4629,12 @@
     }
 
     void setDockedStackMinimized(boolean minimized) {
+        // Get currently focused stack before setting mIsDockMinimized. We do this because if
+        // split-screen is active, primary stack will not be focusable (see #isFocusable) while
+        // still occluding other stacks. This will cause getTopDisplayFocusedStack() to return null.
+        final ActivityStack current = getTopDisplayFocusedStack();
         mIsDockMinimized = minimized;
         if (mIsDockMinimized) {
-            final ActivityStack current = getFocusedStack();
             if (current.inSplitScreenPrimaryWindowingMode()) {
                 // The primary split-screen stack can't be focused while it is minimize, so move
                 // focus to something else.
@@ -4668,12 +4716,12 @@
                 } break;
                 case RESUME_TOP_ACTIVITY_MSG: {
                     synchronized (mService.mGlobalLock) {
-                        resumeFocusedStackTopActivityLocked();
+                        resumeFocusedStacksTopActivitiesLocked();
                     }
                 } break;
                 case SLEEP_TIMEOUT_MSG: {
                     synchronized (mService.mGlobalLock) {
-                        if (mService.mAm.isSleepingOrShuttingDownLocked()) {
+                        if (mService.isSleepingOrShuttingDownLocked()) {
                             Slog.w(TAG, "Sleep timeout!  Sleeping now.");
                             checkReadyForSleepLocked(false /* allowDelay */);
                         }
@@ -4789,7 +4837,7 @@
 
             // If the user must confirm credentials (e.g. when first launching a work app and the
             // Work Challenge is present) let startActivityInPackage handle the intercepting.
-            if (!mService.mAm.mUserController.shouldConfirmCredentials(task.userId)
+            if (!mService.mAmInternal.shouldConfirmCredentials(task.userId)
                     && task.getRootActivity() != null) {
                 final ActivityRecord targetActivity = task.getTopActivity();
 
@@ -4815,7 +4863,7 @@
             return mService.getActivityStartController().startActivityInPackage(
                     task.mCallingUid, callingPid, callingUid, callingPackage, intent, null, null,
                     null, 0, 0, options, userId, task, "startActivityFromRecents",
-                    false /* validateIncomingUser */);
+                    false /* validateIncomingUser */, null /* originatingPendingIntent */);
         } finally {
             if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && task != null) {
                 // If we are launching the task in the docked stack, put it into resizing mode so
@@ -4850,6 +4898,7 @@
      */
     List<IBinder> getTopVisibleActivities() {
         final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
+        final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
         // Traverse all displays.
         for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
             final ActivityDisplay display = mActivityDisplays.valueAt(i);
@@ -4860,7 +4909,7 @@
                 if (stack.shouldBeVisible(null /* starting */)) {
                     final ActivityRecord top = stack.getTopActivity();
                     if (top != null) {
-                        if (stack == mFocusedStack) {
+                        if (stack == topFocusedStack) {
                             topActivityTokens.add(0, top.appToken);
                         } else {
                             topActivityTokens.add(top.appToken);
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index f7ea4b2..6e3a79c 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -40,6 +40,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
 import android.view.RemoteAnimationAdapter;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -240,7 +241,7 @@
             return mService.handleIncomingUser(
                     realCallingPid, realCallingUid, targetUserId, reason);
         } else {
-            mService.mAm.mUserController.ensureNotSpecialUser(targetUserId);
+            mService.mAmInternal.ensureNotSpecialUser(targetUserId);
             return targetUserId;
         }
     }
@@ -248,7 +249,8 @@
     final int startActivityInPackage(int uid, int realCallingPid, int realCallingUid,
             String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags, SafeActivityOptions options,
-            int userId, TaskRecord inTask, String reason, boolean validateIncomingUser) {
+            int userId, TaskRecord inTask, String reason, boolean validateIncomingUser,
+            PendingIntentRecord originatingPendingIntent) {
 
         userId = checkTargetUser(userId, validateIncomingUser, realCallingPid, realCallingUid,
                 reason);
@@ -267,6 +269,7 @@
                 .setActivityOptions(options)
                 .setMayWait(userId)
                 .setInTask(inTask)
+                .setOriginatingPendingIntent(originatingPendingIntent)
                 .execute();
     }
 
@@ -278,10 +281,12 @@
      * @param intents Intents to start.
      * @param userId Start the intents on this user.
      * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID.
+     * @param originatingPendingIntent PendingIntentRecord that originated this activity start or
+     *        null if not originated by PendingIntent
      */
     final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
             String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId,
-            boolean validateIncomingUser) {
+            boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent) {
 
         final String reason = "startActivityInPackage";
 
@@ -290,12 +295,12 @@
 
         // TODO: Switch to user app stacks here.
         return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options,
-                userId, reason);
+                userId, reason, originatingPendingIntent);
     }
 
     int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options,
-            int userId, String reason) {
+            int userId, String reason, PendingIntentRecord originatingPendingIntent) {
         if (intents == null) {
             throw new NullPointerException("intents is null");
         }
@@ -374,6 +379,7 @@
                             // Top activity decides on animation being run, so we allow only for the
                             // top one as otherwise an activity below might consume it.
                             .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/)
+                            .setOriginatingPendingIntent(originatingPendingIntent)
                             .execute();
 
                     if (res < 0) {
@@ -404,7 +410,7 @@
                     "pendingActivityLaunch");
             try {
                 starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags,
-                        resume, null, null, null /* outRecords */);
+                        resume, pal.r.pendingOptions, null, null /* outRecords */);
             } catch (Exception e) {
                 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
                 pal.sendErrorResult(e.getMessage());
@@ -472,4 +478,10 @@
             pw.println("(nothing)");
         }
     }
+
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        for (PendingActivityLaunch activity: mPendingActivityLaunches) {
+            activity.r.writeIdentifierToProto(proto, fieldId);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 171c0bb..177e2f5 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -69,7 +69,6 @@
     private final ActivityTaskManagerService mService;
     private final ActivityStackSupervisor mSupervisor;
     private final Context mServiceContext;
-    private final UserController mUserController;
 
     // UserManager cannot be final as it's not ready when this class is instantiated during boot
     private UserManager mUserManager;
@@ -101,16 +100,15 @@
 
     ActivityStartInterceptor(
             ActivityTaskManagerService service, ActivityStackSupervisor supervisor) {
-        this(service, supervisor, service.mContext, service.mAm.mUserController);
+        this(service, supervisor, service.mContext);
     }
 
     @VisibleForTesting
     ActivityStartInterceptor(ActivityTaskManagerService service, ActivityStackSupervisor supervisor,
-            Context context, UserController userController) {
+            Context context) {
         mService = service;
         mSupervisor = supervisor;
         mServiceContext = context;
-        mUserController = userController;
     }
 
     /**
@@ -239,7 +237,7 @@
                 (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
             return false;
         }
-        final PackageManagerInternal pmi = mService.mAm.getPackageManagerInternalLocked();
+        final PackageManagerInternal pmi = mService.getPackageManagerInternalLocked();
         if (pmi == null) {
             return false;
         }
@@ -298,7 +296,7 @@
      * @return The intercepting intent if needed.
      */
     private Intent interceptWithConfirmCredentialsIfNeeded(ActivityInfo aInfo, int userId) {
-        if (!mUserController.shouldConfirmCredentials(userId)) {
+        if (!mService.mAmInternal.shouldConfirmCredentials(userId)) {
             return null;
         }
         // TODO(b/28935539): should allow certain activities to bypass work challenge
@@ -320,7 +318,7 @@
     private boolean interceptHarmfulAppIfNeeded() {
         CharSequence harmfulAppWarning;
         try {
-            harmfulAppWarning = mService.mAm.getPackageManager()
+            harmfulAppWarning = mService.getPackageManager()
                     .getHarmfulAppWarning(mAInfo.packageName, mUserId);
         } catch (RemoteException ex) {
             return false;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index dac7715..dcf9344 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -99,6 +99,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.voice.IVoiceInteractionSession;
@@ -313,6 +314,7 @@
         int userId;
         WaitResult waitResult;
         int filterCallingUid;
+        PendingIntentRecord originatingPendingIntent;
 
         /**
          * If set to {@code true}, allows this activity start to look into
@@ -369,6 +371,7 @@
             avoidMoveToFront = false;
             allowPendingRemoteAnimationRegistryLookup = true;
             filterCallingUid = UserHandle.USER_NULL;
+            originatingPendingIntent = null;
         }
 
         /**
@@ -407,6 +410,7 @@
             allowPendingRemoteAnimationRegistryLookup
                     = request.allowPendingRemoteAnimationRegistryLookup;
             filterCallingUid = request.filterCallingUid;
+            originatingPendingIntent = request.originatingPendingIntent;
         }
     }
 
@@ -490,7 +494,8 @@
                         mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                         mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                         mRequest.inTask, mRequest.reason,
-                        mRequest.allowPendingRemoteAnimationRegistryLookup);
+                        mRequest.allowPendingRemoteAnimationRegistryLookup,
+                        mRequest.originatingPendingIntent);
             } else {
                 return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                         mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
@@ -500,7 +505,8 @@
                         mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                         mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                         mRequest.outActivity, mRequest.inTask, mRequest.reason,
-                        mRequest.allowPendingRemoteAnimationRegistryLookup);
+                        mRequest.allowPendingRemoteAnimationRegistryLookup,
+                        mRequest.originatingPendingIntent);
             }
         } finally {
             onExecutionComplete();
@@ -532,7 +538,8 @@
             String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
             SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
             ActivityRecord[] outActivity, TaskRecord inTask, String reason,
-            boolean allowPendingRemoteAnimationRegistryLookup) {
+            boolean allowPendingRemoteAnimationRegistryLookup,
+            PendingIntentRecord originatingPendingIntent) {
 
         if (TextUtils.isEmpty(reason)) {
             throw new IllegalArgumentException("Need to specify a reason.");
@@ -545,7 +552,7 @@
                 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
-                inTask, allowPendingRemoteAnimationRegistryLookup);
+                inTask, allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent);
 
         if (outActivity != null) {
             // mLastStartActivityRecord[0] is set in the call to startActivity above.
@@ -575,7 +582,8 @@
             String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
             SafeActivityOptions options,
             boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
-            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
+            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
+            PendingIntentRecord originatingPendingIntent) {
         int err = ActivityManager.START_SUCCESS;
         // Pull the optional Ephemeral Installer-only bundle out of the options early.
         final Bundle verificationBundle
@@ -672,7 +680,7 @@
                     && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
                 try {
                     intent.addCategory(Intent.CATEGORY_VOICE);
-                    if (!mService.mAm.getPackageManager().activitySupportsIntent(
+                    if (!mService.getPackageManager().activitySupportsIntent(
                             intent.getComponent(), intent, resolvedType)) {
                         Slog.w(TAG,
                                 "Activity being started in current voice task does not support voice: "
@@ -690,7 +698,7 @@
             // If the caller is starting a new voice session, just make sure the target
             // is actually allowing it to run this way.
             try {
-                if (!mService.mAm.getPackageManager().activitySupportsIntent(intent.getComponent(),
+                if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
                         intent, resolvedType)) {
                     Slog.w(TAG,
                             "Activity being started in new voice task does not support: "
@@ -771,8 +779,8 @@
         // If permissions need a review before any of the app components can run, we
         // launch the review activity and pass a pending intent to start the activity
         // we are to launching now after the review is completed.
-        if (mService.mAm.mPermissionReviewRequired && aInfo != null) {
-            if (mService.mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
+        if (aInfo != null) {
+            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                     aInfo.packageName, userId)) {
                 IIntentSender target = mService.mAm.getIntentSenderLocked(
                         ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
@@ -802,10 +810,10 @@
                         null /*profilerInfo*/);
 
                 if (DEBUG_PERMISSIONS_REVIEW) {
+                    final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack();
                     Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
                             true, false) + "} from uid " + callingUid + " on display "
-                            + (mSupervisor.mFocusedStack == null
-                            ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
+                            + (focusedStack == null ? DEFAULT_DISPLAY : focusedStack.mDisplayId));
                 }
             }
         }
@@ -826,7 +834,7 @@
 
         ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid,
                 callingUid,
-                callingPackage, intent, resolvedType, aInfo, mService.mAm.getGlobalConfiguration(),
+                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                 mSupervisor, checkedOptions, sourceRecord);
         if (outActivity != null) {
@@ -839,7 +847,7 @@
             r.appTimeTracker = sourceRecord.appTimeTracker;
         }
 
-        final ActivityStack stack = mSupervisor.mFocusedStack;
+        final ActivityStack stack = mSupervisor.getTopDisplayFocusedStack();
 
         // If we are starting an activity that is not from the same uid as the currently resumed
         // one, check whether app switches are allowed.
@@ -857,10 +865,58 @@
         mService.onStartActivitySetDidAppSwitch();
         mController.doPendingActivityLaunches(false);
 
+        maybeLogActivityStart(callingUid, callingPackage, realCallingUid, intent, callerApp, r,
+                originatingPendingIntent);
+
         return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                 true /* doResume */, checkedOptions, inTask, outActivity);
     }
 
+    private void maybeLogActivityStart(int callingUid, String callingPackage, int realCallingUid,
+            Intent intent, ProcessRecord callerApp, ActivityRecord r,
+            PendingIntentRecord originatingPendingIntent) {
+        boolean callerAppHasForegroundActivity = (callerApp != null)
+                ? callerApp.foregroundActivities
+                : false;
+        if (!mService.mAm.isActivityStartsLoggingEnabled() || callerAppHasForegroundActivity
+                || r == null) {
+            // skip logging in this case
+            return;
+        }
+
+        try {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "logActivityStart");
+            final int callingUidProcState = mService.mAm.getUidStateLocked(callingUid);
+            final boolean callingUidHasAnyVisibleWindow =
+                    mService.mWindowManager.isAnyWindowVisibleForUid(callingUid);
+            final int realCallingUidProcState = (callingUid == realCallingUid)
+                    ? callingUidProcState
+                    : mService.mAm.getUidStateLocked(realCallingUid);
+            final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
+                    ? callingUidHasAnyVisibleWindow
+                    : mService.mWindowManager.isAnyWindowVisibleForUid(realCallingUid);
+            final String targetPackage = r.packageName;
+            final int targetUid = (r.appInfo != null) ? r.appInfo.uid : -1;
+            final int targetUidProcState = mService.mAm.getUidStateLocked(targetUid);
+            final boolean targetUidHasAnyVisibleWindow = (targetUid != -1)
+                    ? mService.mWindowManager.isAnyWindowVisibleForUid(targetUid)
+                    : false;
+            final String targetWhitelistTag = (targetUid != -1)
+                    ? mService.mAm.getPendingTempWhitelistTagForUidLocked(targetUid)
+                    : null;
+
+            mSupervisor.getActivityMetricsLogger().logActivityStart(intent, callerApp, r,
+                    callingUid, callingPackage, callingUidProcState,
+                    callingUidHasAnyVisibleWindow,
+                    realCallingUid, realCallingUidProcState,
+                    realCallingUidHasAnyVisibleWindow,
+                    targetUid, targetPackage, targetUidProcState,
+                    targetUidHasAnyVisibleWindow, targetWhitelistTag,
+                    (originatingPendingIntent != null));
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+        }
+    }
 
     /**
      * Creates a launch intent for the given auxiliary resolution data.
@@ -870,7 +926,7 @@
             String resolvedType, int userId) {
         if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) {
             // request phase two resolution
-            mService.mAm.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
+            mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
                     auxiliaryResponse, originalIntent, resolvedType, callingPackage,
                     verificationBundle, userId);
         }
@@ -941,7 +997,8 @@
             ProfilerInfo profilerInfo, WaitResult outResult,
             Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
             int userId, TaskRecord inTask, String reason,
-            boolean allowPendingRemoteAnimationRegistryLookup) {
+            boolean allowPendingRemoteAnimationRegistryLookup,
+            PendingIntentRecord originatingPendingIntent) {
         // Refuse possible leaked file descriptors
         if (intent != null && intent.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -970,7 +1027,7 @@
                 && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
                 && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
                 && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
-                && mService.mAm.getPackageManagerInternalLocked()
+                && mService.getPackageManagerInternalLocked()
                         .isInstantAppInstallerComponent(intent.getComponent())) {
             // intercept intents targeted directly to the ephemeral installer the
             // ephemeral installer should never be started with a raw Intent; instead
@@ -1013,9 +1070,9 @@
         ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
 
         synchronized (mService.mGlobalLock) {
-            final ActivityStack stack = mSupervisor.mFocusedStack;
+            final ActivityStack stack = mSupervisor.getTopDisplayFocusedStack();
             stack.mConfigWillChange = globalConfig != null
-                    && mService.mAm.getGlobalConfiguration().diff(globalConfig) != 0;
+                    && mService.getGlobalConfiguration().diff(globalConfig) != 0;
             if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                     "Starting activity when config will change = " + stack.mConfigWillChange);
 
@@ -1087,7 +1144,7 @@
                     voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                     callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                     ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
-                    allowPendingRemoteAnimationRegistryLookup);
+                    allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent);
 
             Binder.restoreCallingIdentity(origId);
 
@@ -1354,7 +1411,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 ActivityStack topStack = mSupervisor.mFocusedStack;
+        final ActivityStack topStack = mSupervisor.getTopDisplayFocusedStack();
         final ActivityRecord topFocused = topStack.getTopActivity();
         final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
         final boolean dontStart = top != null && mStartActivity.resultTo == null
@@ -1367,7 +1424,7 @@
             // For paranoia, make sure we have correctly resumed the top activity.
             topStack.mLastPausedActivity = null;
             if (mDoResume) {
-                mSupervisor.resumeFocusedStackTopActivityLocked();
+                mSupervisor.resumeFocusedStacksTopActivitiesLocked();
             }
             ActivityOptions.abort(mOptions);
             if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
@@ -1409,7 +1466,7 @@
             return result;
         }
 
-        mService.mAm.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
+        mService.mUgmInternal.grantUriPermissionFromIntent(mCallingUid, mStartActivity.packageName,
                 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
         mService.mAm.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
                 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
@@ -1447,10 +1504,11 @@
                 // will not update the focused stack.  If starting the new activity now allows the
                 // task stack to be focusable, then ensure that we now update the focused stack
                 // accordingly.
-                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
+                if (mTargetStack.isFocusable()
+                        && !mSupervisor.isTopDisplayFocusedStack(mTargetStack)) {
                     mTargetStack.moveToFront("startActivityUnchecked");
                 }
-                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
+                mSupervisor.resumeFocusedStacksTopActivitiesLocked(mTargetStack, mStartActivity,
                         mOptions);
             }
         } else if (mStartActivity != null) {
@@ -1609,8 +1667,8 @@
         if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
             ActivityRecord checkedCaller = sourceRecord;
             if (checkedCaller == null) {
-                checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
-                        mNotTop);
+                checkedCaller = mSupervisor.getTopDisplayFocusedStack()
+                        .topRunningNonDelayedActivityLocked(mNotTop);
             }
             if (!checkedCaller.realActivity.equals(r.realActivity)) {
                 // Caller is not the same as launcher, so always needed.
@@ -1843,7 +1901,7 @@
         // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
         // the same behavior as if a new instance was being started, which means not bringing it
         // to the front if the caller is not itself in the front.
-        final ActivityStack focusStack = mSupervisor.getFocusedStack();
+        final ActivityStack focusStack = mSupervisor.getTopDisplayFocusedStack();
         ActivityRecord curTop = (focusStack == null)
                 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
 
@@ -2022,7 +2080,7 @@
 
     private void resumeTargetStackIfNeeded() {
         if (mDoResume) {
-            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
+            mSupervisor.resumeFocusedStacksTopActivitiesLocked(mTargetStack, null, mOptions);
         } else {
             ActivityOptions.abort(mOptions);
         }
@@ -2102,7 +2160,7 @@
             if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
                 // Can't use target display, lets find a stack on the source display.
                 mTargetStack = mSupervisor.getValidLaunchStackOnDisplay(
-                        sourceStack.mDisplayId, mStartActivity);
+                        sourceStack.mDisplayId, mStartActivity, mOptions);
             }
             if (mTargetStack == null) {
                 // There are no suitable stacks on the target and source display(s). Look on all
@@ -2138,7 +2196,7 @@
                 // For paranoia, make sure we have correctly resumed the top activity.
                 mTargetStack.mLastPausedActivity = null;
                 if (mDoResume) {
-                    mSupervisor.resumeFocusedStackTopActivityLocked();
+                    mSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 }
                 ActivityOptions.abort(mOptions);
                 return START_DELIVERED_TO_TOP;
@@ -2156,7 +2214,7 @@
                 deliverNewIntent(top);
                 mTargetStack.mLastPausedActivity = null;
                 if (mDoResume) {
-                    mSupervisor.resumeFocusedStackTopActivityLocked();
+                    mSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 }
                 return START_DELIVERED_TO_TOP;
             }
@@ -2304,28 +2362,28 @@
         }
 
         final ActivityStack currentStack = task != null ? task.getStack() : null;
+        final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack();
         if (currentStack != null) {
-            if (mSupervisor.mFocusedStack != currentStack) {
+            if (focusedStack != currentStack) {
                 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                         "computeStackFocus: Setting " + "focused stack to r=" + r
                                 + " task=" + task);
             } else {
                 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
-                        "computeStackFocus: Focused stack already="
-                                + mSupervisor.mFocusedStack);
+                        "computeStackFocus: Focused stack already=" + focusedStack);
             }
             return currentStack;
         }
 
         if (canLaunchIntoFocusedStack(r, newTask)) {
             if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
-                    "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
-            return mSupervisor.mFocusedStack;
+                    "computeStackFocus: Have a focused stack=" + focusedStack);
+            return focusedStack;
         }
 
         if (mPreferredDisplayId != DEFAULT_DISPLAY) {
             // Try to put the activity in a stack on a secondary display.
-            stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r);
+            stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r, aOptions);
             if (stack == null) {
                 // If source display is not suitable - look for topmost valid stack in the system.
                 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
@@ -2356,7 +2414,7 @@
     /** Check if provided activity record can launch in currently focused stack. */
     // TODO: This method can probably be consolidated into getLaunchStack() below.
     private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
-        final ActivityStack focusedStack = mSupervisor.mFocusedStack;
+        final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack();
         final boolean canUseFocusedStack;
         if (focusedStack.isActivityTypeAssistant()) {
             canUseFocusedStack = r.isActivityTypeAssistant();
@@ -2406,18 +2464,19 @@
         }
         // Otherwise handle adjacent launch.
 
+        final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack();
         // The parent activity doesn't want to launch the activity on top of itself, but
         // instead tries to put it onto other side in side-by-side mode.
-        final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
+        final ActivityStack parentStack = task != null ? task.getStack(): focusedStack;
 
-        if (parentStack != mSupervisor.mFocusedStack) {
+        if (parentStack != focusedStack) {
             // If task's parent stack is not focused - use it during adjacent launch.
             return parentStack;
         } else {
-            if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
+            if (focusedStack != null && task == focusedStack.topTask()) {
                 // If task is already on top of focused stack - use it. We don't want to move the
                 // existing focused task to adjacent stack, just deliver new intent in this case.
-                return mSupervisor.mFocusedStack;
+                return focusedStack;
             }
 
             if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
@@ -2613,6 +2672,11 @@
         return this;
     }
 
+    ActivityStarter setOriginatingPendingIntent(PendingIntentRecord originatingPendingIntent) {
+        mRequest.originatingPendingIntent = originatingPendingIntent;
+        return this;
+    }
+
     void dump(PrintWriter pw, String prefix) {
         prefix = prefix + "  ";
         pw.print(prefix);
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index d47fb44..11f8bb1 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.BIND_VOICE_INTERACTION;
 import static android.Manifest.permission.CHANGE_CONFIGURATION;
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+import static android.Manifest.permission.FILTER_EVENTS;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
 import static android.Manifest.permission.READ_FRAME_BUFFER;
@@ -26,20 +27,23 @@
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.Manifest.permission.STOP_APP_SWITCHES;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
+import static android.content.pm.PackageManager.FEATURE_PC;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
+import static android.provider.Settings.System.FONT_SCALE;
 import static com.android.server.am.ActivityManagerService.dumpStackTraces;
+import static com.android.server.am.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
+import static com.android.server.am.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
 import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.AppOpsManager.OP_NONE;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -69,7 +73,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IMMERSIVE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
@@ -113,6 +116,26 @@
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
+import android.app.ActivityThread;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.database.ContentObserver;
+import android.os.IUserManager;
+import android.os.PowerManager;
+import android.os.ServiceManager;
+import android.os.Trace;
+import android.os.UserManager;
+import android.os.WorkSource;
+import android.view.WindowManager;
+import com.android.internal.R;
+import com.android.internal.app.IAppOpsService;
+import com.android.server.AppOpsService;
+import com.android.server.SystemServiceManager;
+import com.android.server.pm.UserManagerService;
+import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
 import android.app.IActivityController;
@@ -158,7 +181,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.StrictMode;
 import android.os.SystemClock;
@@ -227,17 +249,33 @@
     private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
 
+    // How long we wait until we timeout on key dispatching.
+    private static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000;
+    // How long we wait until we timeout on key dispatching during instrumentation.
+    private static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000;
+
     Context mContext;
+    /**
+     * This Context is themable and meant for UI display (AlertDialogs, etc.). The theme can
+     * change at runtime. Use mContext for non-UI purposes.
+     */
+    final Context mUiContext;
     H mH;
     UiHandler mUiHandler;
     ActivityManagerService mAm;
     ActivityManagerInternal mAmInternal;
+    UriGrantsManagerInternal mUgmInternal;
+    private PackageManagerInternal mPmInternal;
     /* Global service lock used by the package the owns this service. */
     Object mGlobalLock;
     ActivityStackSupervisor mStackSupervisor;
     WindowManagerService mWindowManager;
+    private UserManagerService mUserManager;
+    private AppOpsService mAppOpsService;
     /** All processes currently running that might have a window organized by name. */
     final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
+    /** All processes we currently have running mapped by pid */
+    final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
     /** This is the process holding what we currently consider to be the "home" activity. */
     WindowProcessController mHomeProcess;
     /**
@@ -314,6 +352,9 @@
      */
     private Configuration mTempConfig = new Configuration();
 
+    /** Temporary to avoid allocations. */
+    final StringBuilder mStringBuilder = new StringBuilder(256);
+
     // Amount of time after a call to stopAppSwitches() during which we will
     // prevent further untrusted switches from happening.
     private static final long APP_SWITCH_DELAY_TIME = 5 * 1000;
@@ -322,12 +363,12 @@
      * The time at which we will allow normal application switches again,
      * after a call to {@link #stopAppSwitches()}.
      */
-    long mAppSwitchesAllowedTime;
+    private long mAppSwitchesAllowedTime;
     /**
      * This is set to true after the first switch after mAppSwitchesAllowedTime
      * is set; any switches after that will clear the time.
      */
-    boolean mDidAppSwitch;
+    private boolean mDidAppSwitch;
 
     IActivityController mController = null;
     boolean mControllerIsAMonkey = false;
@@ -336,7 +377,7 @@
      * Used to retain an update lock when the foreground activity is in
      * immersive mode.
      */
-    final UpdateLock mUpdateLock = new UpdateLock("immersive");
+    private final UpdateLock mUpdateLock = new UpdateLock("immersive");
 
     /**
      * Packages that are being allowed to perform unrestricted app switches.  Mapping is
@@ -345,9 +386,9 @@
     final SparseArray<ArrayMap<String, Integer>> mAllowAppSwitchUids = new SparseArray<>();
 
     /** The dimensions of the thumbnails in the Recents UI. */
-    int mThumbnailWidth;
-    int mThumbnailHeight;
-    float mFullscreenThumbnailScale;
+    private int mThumbnailWidth;
+    private int mThumbnailHeight;
+    private float mFullscreenThumbnailScale;
 
     /**
      * Flag that indicates if multi-window is enabled.
@@ -375,8 +416,94 @@
     // VR Vr2d Display Id.
     int mVr2dDisplayId = INVALID_DISPLAY;
 
+    /**
+     * Set while we are wanting to sleep, to prevent any
+     * activities from being started/resumed.
+     *
+     * TODO(b/33594039): Clarify the actual state transitions represented by mSleeping.
+     *
+     * Currently mSleeping is set to true when transitioning into the sleep state, and remains true
+     * while in the sleep state until there is a pending transition out of sleep, in which case
+     * mSleeping is set to false, and remains false while awake.
+     *
+     * Whether mSleeping can quickly toggled between true/false without the device actually
+     * display changing states is undefined.
+     */
+    private boolean mSleeping = false;
+
+    /**
+     * The process state used for processes that are running the top activities.
+     * This changes between TOP and TOP_SLEEPING to following mSleeping.
+     */
+    int mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
+
+    // Whether we should show our dialogs (ANR, crash, etc) or just perform their default action
+    // automatically. Important for devices without direct input devices.
+    private boolean mShowDialogs = true;
+
+    /** Set if we are shutting down the system, similar to sleeping. */
+    boolean mShuttingDown = false;
+
+    /**
+     * We want to hold a wake lock while running a voice interaction session, since
+     * this may happen with the screen off and we need to keep the CPU running to
+     * be able to continue to interact with the user.
+     */
+    PowerManager.WakeLock mVoiceWakeLock;
+
+    /**
+     * Set while we are running a voice interaction. This overrides sleeping while it is active.
+     */
+    IVoiceInteractionSession mRunningVoice;
+
+    /**
+     * The last resumed activity. This is identical to the current resumed activity most
+     * of the time but could be different when we're pausing one activity before we resume
+     * another activity.
+     */
+    ActivityRecord mLastResumedActivity;
+
+    /**
+     * The activity that is currently being traced as the active resumed activity.
+     *
+     * @see #updateResumedAppTrace
+     */
+    private @Nullable ActivityRecord mTracedResumedActivity;
+
+    /** If non-null, we are tracking the time the user spends in the currently focused app. */
+    AppTimeTracker mCurAppTimeTracker;
+
+    private AppWarnings mAppWarnings;
+
+    private FontScaleSettingObserver mFontScaleSettingObserver;
+
+    private final class FontScaleSettingObserver extends ContentObserver {
+        private final Uri mFontScaleUri = Settings.System.getUriFor(FONT_SCALE);
+        private final Uri mHideErrorDialogsUri = Settings.Global.getUriFor(HIDE_ERROR_DIALOGS);
+
+        public FontScaleSettingObserver() {
+            super(mH);
+            final ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(mFontScaleUri, false, this, UserHandle.USER_ALL);
+            resolver.registerContentObserver(mHideErrorDialogsUri, false, this,
+                    UserHandle.USER_ALL);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
+            if (mFontScaleUri.equals(uri)) {
+                updateFontScaleIfNeeded(userId);
+            } else if (mHideErrorDialogsUri.equals(uri)) {
+                synchronized (mGlobalLock) {
+                    updateShouldShowDialogsLocked(getGlobalConfiguration());
+                }
+            }
+        }
+    }
+
     ActivityTaskManagerService(Context context) {
         mContext = context;
+        mUiContext = ActivityThread.currentActivityThread().getSystemUiContext();
         mLifecycleManager = new ClientLifecycleManager();
     }
 
@@ -386,6 +513,17 @@
         mRecentTasks.onSystemReadyLocked();
     }
 
+    void onInitPowerManagement() {
+        mStackSupervisor.initPowerManagement();
+        final PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+        mVoiceWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*voice*");
+        mVoiceWakeLock.setReferenceCounted(false);
+    }
+
+    void installSystemProviders() {
+        mFontScaleSettingObserver = new FontScaleSettingObserver();
+    }
+
     void retrieveSettings(ContentResolver resolver) {
         final boolean freeformWindowManagement =
                 mContext.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
@@ -404,6 +542,7 @@
         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 isPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
 
         // Transfer any global setting for forcing RTL layout, into a System Property
         SystemProperties.set(DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0");
@@ -436,6 +575,8 @@
             }
             mWindowManager.setForceResizableTasks(mForceResizableActivities);
             mWindowManager.setSupportsPictureInPicture(mSupportsPictureInPicture);
+            mWindowManager.setSupportsFreeformWindowManagement(mSupportsFreeformWindowManagement);
+            mWindowManager.setIsPc(isPc);
             // This happens before any activities are started, so we can change global configuration
             // in-place.
             updateConfigurationLocked(configuration, null, true);
@@ -466,6 +607,8 @@
         mGlobalLock = mAm;
         mH = new H(mAm.mHandlerThread.getLooper());
         mUiHandler = new UiHandler();
+        mAppWarnings = new AppWarnings(
+                this, mUiContext, mH, mUiHandler, SystemServiceManager.ensureSystemDir());
 
         mTempConfig.setToDefaults();
         mTempConfig.setLocales(LocaleList.getDefault());
@@ -485,6 +628,7 @@
 
     void onActivityManagerInternalAdded() {
         mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
+        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
     }
 
     protected ActivityStackSupervisor createStackSupervisor() {
@@ -498,6 +642,26 @@
         mLockTaskController.setWindowManager(wm);
     }
 
+    UserManagerService getUserManager() {
+        if (mUserManager == null) {
+            IBinder b = ServiceManager.getService(Context.USER_SERVICE);
+            mUserManager = (UserManagerService) IUserManager.Stub.asInterface(b);
+        }
+        return mUserManager;
+    }
+
+    AppOpsService getAppOpsService() {
+        if (mAppOpsService == null) {
+            IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
+            mAppOpsService = (AppOpsService) IAppOpsService.Stub.asInterface(b);
+        }
+        return mAppOpsService;
+    }
+
+    boolean hasUserRestriction(String restriction, int userId) {
+        return getUserManager().hasUserRestriction(restriction, userId);
+    }
+
     protected RecentTasks createRecentTasks() {
         return new RecentTasks(this, mStackSupervisor);
     }
@@ -563,7 +727,8 @@
         userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, reason);
         // TODO: Switch to user app stacks here.
         return getActivityStartController().startActivities(caller, -1, callingPackage, intents,
-                resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, reason);
+                resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, reason,
+                null /* originatingPendingIntent */);
     }
 
     @Override
@@ -619,7 +784,7 @@
         synchronized (mGlobalLock) {
             // If this is coming from the currently resumed activity, it is
             // effectively saying that app switches are allowed at this point.
-            final ActivityStack stack = getFocusedStack();
+            final ActivityStack stack = getTopDisplayFocusedStack();
             if (stack.mResumedActivity != null &&
                     stack.mResumedActivity.info.applicationInfo.uid == Binder.getCallingUid()) {
                 mAppSwitchesAllowedTime = 0;
@@ -1045,6 +1210,8 @@
                     if (!res) {
                         Slog.i(TAG, "Removing task failed to finish activity");
                     }
+                    // Explicitly dismissing the activity so reset its relaunch flag.
+                    r.mRelaunchReason = ActivityRecord.RELAUNCH_REASON_NONE;
                 } else {
                     res = tr.getStack().requestFinishActivityLocked(token, resultCode,
                             resultData, "app-request", true);
@@ -1224,7 +1391,7 @@
             r.immersive = immersive;
 
             // update associated state if we're frontmost
-            if (r == mStackSupervisor.getResumedActivityLocked()) {
+            if (r.isResumedActivityOnDisplay()) {
                 if (DEBUG_IMMERSIVE) Slog.d(TAG_IMMERSIVE, "Frontmost changed immersion: "+ r);
                 applyUpdateLockStateLocked(r);
             }
@@ -1265,7 +1432,7 @@
     public boolean isTopActivityImmersive() {
         enforceNotIsolatedCaller("isTopActivityImmersive");
         synchronized (mGlobalLock) {
-            final ActivityRecord r = getFocusedStack().topRunningActivityLocked();
+            final ActivityRecord r = getTopDisplayFocusedStack().topRunningActivityLocked();
             return (r != null) ? r.immersive : false;
         }
     }
@@ -1296,7 +1463,7 @@
         enforceNotIsolatedCaller("getFrontActivityScreenCompatMode");
         ApplicationInfo ai;
         synchronized (mGlobalLock) {
-            final ActivityRecord r = getFocusedStack().topRunningActivityLocked();
+            final ActivityRecord r = getTopDisplayFocusedStack().topRunningActivityLocked();
             if (r == null) {
                 return ActivityManager.COMPAT_MODE_UNKNOWN;
             }
@@ -1312,7 +1479,7 @@
                 "setFrontActivityScreenCompatMode");
         ApplicationInfo ai;
         synchronized (mGlobalLock) {
-            final ActivityRecord r = getFocusedStack().topRunningActivityLocked();
+            final ActivityRecord r = getTopDisplayFocusedStack().topRunningActivityLocked();
             if (r == null) {
                 Slog.w(TAG, "setFrontActivityScreenCompatMode failed: no top activity");
                 return;
@@ -1436,7 +1603,7 @@
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
-                ActivityStack focusedStack = getFocusedStack();
+                ActivityStack focusedStack = getTopDisplayFocusedStack();
                 if (focusedStack != null) {
                     return mStackSupervisor.getStackInfo(focusedStack.mStackId);
                 }
@@ -1462,7 +1629,7 @@
                 final ActivityRecord r = stack.topRunningActivityLocked();
                 if (mStackSupervisor.moveFocusableActivityStackToFrontLocked(
                         r, "setFocusedStack")) {
-                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                    mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 }
             }
         } finally {
@@ -1483,7 +1650,7 @@
                 }
                 final ActivityRecord r = task.topRunningActivityLocked();
                 if (mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, "setFocusedTask")) {
-                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                    mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 }
             }
         } finally {
@@ -1506,6 +1673,19 @@
     }
 
     @Override
+    public void removeAllVisibleRecentTasks() {
+        enforceCallerIsRecentsOrHasPermission(REMOVE_TASKS, "removeAllVisibleRecentTasks()");
+        synchronized (mGlobalLock) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                getRecentTasks().removeAllVisibleTasks();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    @Override
     public boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
         synchronized (mGlobalLock) {
             final ActivityRecord srec = ActivityRecord.forTokenLocked(token);
@@ -1681,7 +1861,7 @@
         synchronized (mGlobalLock) {
             final long origId = Binder.clearCallingIdentity();
             try {
-                getFocusedStack().unhandledBackLocked();
+                getTopDisplayFocusedStack().unhandledBackLocked();
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
@@ -2133,7 +2313,7 @@
             return;
         }
 
-        final ActivityStack stack = mStackSupervisor.getFocusedStack();
+        final ActivityStack stack = mStackSupervisor.getTopDisplayFocusedStack();
         if (stack == null || task != stack.topTask()) {
             throw new IllegalArgumentException("Invalid task, not in foreground");
         }
@@ -2248,10 +2428,7 @@
     public boolean isTopOfTask(IBinder token) {
         synchronized (mGlobalLock) {
             ActivityRecord r = ActivityRecord.isInStackLocked(token);
-            if (r == null) {
-                throw new IllegalArgumentException();
-            }
-            return r.getTask().getTopActivity() == r;
+            return r != null && r.getTask().getTopActivity() == r;
         }
     }
 
@@ -2625,23 +2802,6 @@
     }
 
     @Override
-    public int createStackOnDisplay(int displayId) {
-        mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "createStackOnDisplay()");
-        synchronized (mGlobalLock) {
-            final ActivityDisplay display =
-                    mStackSupervisor.getActivityDisplayOrCreateLocked(displayId);
-            if (display == null) {
-                return INVALID_STACK_ID;
-            }
-            // TODO(multi-display): Have the caller pass in the windowing mode and activity type.
-            final ActivityStack stack = display.createStack(
-                    WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
-                    ON_TOP);
-            return (stack != null) ? stack.mStackId : INVALID_STACK_ID;
-        }
-    }
-
-    @Override
     public void exitFreeformMode(IBinder token) {
         synchronized (mGlobalLock) {
             long ident = Binder.clearCallingIdentity();
@@ -2801,7 +2961,7 @@
                 "enqueueAssistContext()");
 
         synchronized (mGlobalLock) {
-            ActivityRecord activity = getFocusedStack().getTopActivity();
+            ActivityRecord activity = getTopDisplayFocusedStack().getTopActivity();
             if (activity == null) {
                 Slog.w(TAG, "getAssistContextExtras failed: no top activity");
                 return null;
@@ -2929,7 +3089,7 @@
     public boolean isAssistDataAllowedOnCurrentActivity() {
         int userId;
         synchronized (mGlobalLock) {
-            final ActivityStack focusedStack = getFocusedStack();
+            final ActivityStack focusedStack = getTopDisplayFocusedStack();
             if (focusedStack == null || focusedStack.isActivityTypeAssistant()) {
                 return false;
             }
@@ -2949,7 +3109,7 @@
         try {
             synchronized (mGlobalLock) {
                 ActivityRecord caller = ActivityRecord.forTokenLocked(token);
-                ActivityRecord top = getFocusedStack().getTopActivity();
+                ActivityRecord top = getTopDisplayFocusedStack().getTopActivity();
                 if (top != caller) {
                     Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
                             + " is not current top " + top);
@@ -2979,6 +3139,64 @@
         }
     }
 
+    private void onLocalVoiceInteractionStartedLocked(IBinder activity,
+            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
+        ActivityRecord activityToCallback = ActivityRecord.forTokenLocked(activity);
+        if (activityToCallback == null) return;
+        activityToCallback.setVoiceSessionLocked(voiceSession);
+
+        // Inform the activity
+        try {
+            activityToCallback.app.getThread().scheduleLocalVoiceInteractionStarted(activity,
+                    voiceInteractor);
+            long token = Binder.clearCallingIdentity();
+            try {
+                startRunningVoiceLocked(voiceSession, activityToCallback.appInfo.uid);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            // TODO: VI Should we cache the activity so that it's easier to find later
+            // rather than scan through all the stacks and activities?
+        } catch (RemoteException re) {
+            activityToCallback.clearVoiceSessionLocked();
+            // TODO: VI Should this terminate the voice session?
+        }
+    }
+
+    private void startRunningVoiceLocked(IVoiceInteractionSession session, int targetUid) {
+        Slog.d(TAG, "<<<  startRunningVoiceLocked()");
+        mVoiceWakeLock.setWorkSource(new WorkSource(targetUid));
+        if (mRunningVoice == null || mRunningVoice.asBinder() != session.asBinder()) {
+            boolean wasRunningVoice = mRunningVoice != null;
+            mRunningVoice = session;
+            if (!wasRunningVoice) {
+                mVoiceWakeLock.acquire();
+                updateSleepIfNeededLocked();
+            }
+        }
+    }
+
+    void finishRunningVoiceLocked() {
+        if (mRunningVoice != null) {
+            mRunningVoice = null;
+            mVoiceWakeLock.release();
+            updateSleepIfNeededLocked();
+        }
+    }
+
+    @Override
+    public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake) {
+        synchronized (mGlobalLock) {
+            if (mRunningVoice != null && mRunningVoice.asBinder() == session.asBinder()) {
+                if (keepAwake) {
+                    mVoiceWakeLock.acquire();
+                } else {
+                    mVoiceWakeLock.release();
+                }
+            }
+        }
+    }
+
     @Override
     public ComponentName getActivityClassForToken(IBinder token) {
         synchronized (mGlobalLock) {
@@ -3109,7 +3327,7 @@
                     // Caller wants the current split-screen primary stack to be the top stack after
                     // it goes fullscreen, so move it to the front.
                     stack.moveToFront("dismissSplitScreenMode");
-                } else if (mStackSupervisor.isFocusedStack(stack)) {
+                } else if (mStackSupervisor.isTopDisplayFocusedStack(stack)) {
                     // In this case the current split-screen primary stack shouldn't be the top
                     // stack after it goes fullscreen, but it current has focus, so we move the
                     // focus to the top-most split-screen secondary stack next to it.
@@ -3425,7 +3643,7 @@
                 throw new IllegalArgumentException("Activity does not exist; token="
                         + activityToken);
             }
-            return r.getUriPermissionsLocked().getExternalTokenLocked();
+            return r.getUriPermissionsLocked().getExternalToken();
         }
     }
 
@@ -3498,7 +3716,7 @@
                 r.requestedVrComponent = (enabled) ? packageName : null;
 
                 // Update associated state if this activity is currently focused
-                if (r == mStackSupervisor.getResumedActivityLocked()) {
+                if (r.isResumedActivityOnDisplay()) {
                     applyUpdateVrModeLocked(r);
                 }
                 return 0;
@@ -3512,11 +3730,11 @@
     public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
         Slog.i(TAG, "Activity tried to startLocalVoiceInteraction");
         synchronized (mGlobalLock) {
-            ActivityRecord activity = getFocusedStack().getTopActivity();
+            ActivityRecord activity = getTopDisplayFocusedStack().getTopActivity();
             if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
                 throw new SecurityException("Only focused activity can call startVoiceInteraction");
             }
-            if (mAm.mRunningVoice != null || activity.getTask().voiceSession != null
+            if (mRunningVoice != null || activity.getTask().voiceSession != null
                     || activity.voiceSession != null) {
                 Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
                 return;
@@ -3720,10 +3938,10 @@
         mAmInternal.enforceCallingPermission(
                 Manifest.permission.INTERACT_ACROSS_USERS_FULL, "getLastResumedActivityUserId()");
         synchronized (mGlobalLock) {
-            if (mAm.mLastResumedActivity == null) {
+            if (mLastResumedActivity == null) {
                 return getCurrentUserId();
             }
-            return mAm.mLastResumedActivity.userId;
+            return mLastResumedActivity.userId;
         }
     }
 
@@ -3815,7 +4033,7 @@
         synchronized (mGlobalLock) {
             final long origId = Binder.clearCallingIdentity();
             try {
-                mAm.mAppWarnings.alwaysShowUnsupportedCompileSdkWarning(activity);
+                mAppWarnings.alwaysShowUnsupportedCompileSdkWarning(activity);
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
@@ -3925,8 +4143,8 @@
         });
     }
 
-    ActivityStack getFocusedStack() {
-        return mStackSupervisor.getFocusedStack();
+    ActivityStack getTopDisplayFocusedStack() {
+        return mStackSupervisor.getTopDisplayFocusedStack();
     }
 
     /** Pokes the task persister. */
@@ -3949,12 +4167,39 @@
                 || transit == TRANSIT_TASK_TO_FRONT;
     }
 
-    void dumpVrControllerLocked(PrintWriter pw) {
-        pw.println("  mVrController=" + mVrController);
+    void dumpSleepStates(PrintWriter pw, boolean testPssMode) {
+        synchronized (mGlobalLock) {
+            pw.println("  mSleepTokens=" + mStackSupervisor.mSleepTokens);
+            if (mRunningVoice != null) {
+                pw.println("  mRunningVoice=" + mRunningVoice);
+                pw.println("  mVoiceWakeLock" + mVoiceWakeLock);
+            }
+            pw.println("  mSleeping=" + mSleeping);
+            pw.println("  mShuttingDown=" + mShuttingDown + " mTestPssMode=" + testPssMode);
+            pw.println("  mVrController=" + mVrController);
+        }
     }
 
-    void writeVrControllerToProto(ProtoOutputStream proto, long fieldId) {
-        mVrController.writeToProto(proto, fieldId);
+    void writeSleepStateToProto(ProtoOutputStream proto) {
+        for (ActivityTaskManagerInternal.SleepToken st : mStackSupervisor.mSleepTokens) {
+            proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEP_TOKENS,
+                    st.toString());
+        }
+
+        if (mRunningVoice != null) {
+            final long vrToken = proto.start(
+                    ActivityManagerServiceDumpProcessesProto.RUNNING_VOICE);
+            proto.write(ActivityManagerServiceDumpProcessesProto.Voice.SESSION,
+                    mRunningVoice.toString());
+            mVoiceWakeLock.writeToProto(
+                    proto, ActivityManagerServiceDumpProcessesProto.Voice.WAKELOCK);
+            proto.end(vrToken);
+        }
+
+        proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEPING, mSleeping);
+        proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SHUTTING_DOWN,
+                mShuttingDown);
+        mVrController.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.VR_CONTROLLER);
     }
 
     int getCurrentUserId() {
@@ -3967,6 +4212,15 @@
         }
     }
 
+    public Configuration getConfiguration() {
+        Configuration ci;
+        synchronized(mGlobalLock) {
+            ci = new Configuration(getGlobalConfiguration());
+            ci.userSetLocale = false;
+        }
+        return ci;
+    }
+
     /**
      * Current global configuration information. Contains general settings for the entire system,
      * also corresponds to the merged configuration of the default display.
@@ -4129,7 +4383,7 @@
                 mTempConfig, mAmInternal.getCurrentUserId());
 
         // TODO: If our config changes, should we auto dismiss any currently showing dialogs?
-        mAm.updateShouldShowDialogsLocked(mTempConfig);
+        updateShouldShowDialogsLocked(mTempConfig);
 
         AttributeCache ac = AttributeCache.instance();
         if (ac != null) {
@@ -4264,7 +4518,7 @@
 
             final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
             if (isDensityChange && displayId == DEFAULT_DISPLAY) {
-                mAm.mAppWarnings.onDensityChanged();
+                mAppWarnings.onDensityChanged();
 
                 mAm.killAllBackgroundProcessesExcept(N,
                         ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
@@ -4288,6 +4542,300 @@
         return changes;
     }
 
+    private void updateEventDispatchingLocked(boolean booted) {
+        mWindowManager.setEventDispatching(booted && !mShuttingDown);
+    }
+
+    void enableScreenAfterBoot(boolean booted) {
+        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
+                SystemClock.uptimeMillis());
+        mWindowManager.enableScreenAfterBoot();
+
+        synchronized (mGlobalLock) {
+            updateEventDispatchingLocked(booted);
+        }
+    }
+
+    boolean canShowErrorDialogs() {
+        return mShowDialogs && !mSleeping && !mShuttingDown
+                && !mKeyguardController.isKeyguardOrAodShowing(DEFAULT_DISPLAY)
+                && !hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
+                mAmInternal.getCurrentUserId())
+                && !(UserManager.isDeviceInDemoMode(mContext)
+                && mAmInternal.getCurrentUser().isDemo());
+    }
+
+    static long getInputDispatchingTimeoutLocked(ActivityRecord r) {
+        if (r == null || !r.hasProcess()) {
+            return KEY_DISPATCHING_TIMEOUT_MS;
+        }
+        return getInputDispatchingTimeoutLocked(r.app);
+    }
+
+    private static long getInputDispatchingTimeoutLocked(WindowProcessController r) {
+        if (r != null && (r.isInstrumenting() || r.isUsingWrapper())) {
+            return INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
+        }
+        return KEY_DISPATCHING_TIMEOUT_MS;
+    }
+
+    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
+        if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires permission " + FILTER_EVENTS);
+        }
+        WindowProcessController proc;
+        long timeout;
+        synchronized (mGlobalLock) {
+            proc = mPidMap.get(pid);
+            timeout = getInputDispatchingTimeoutLocked(proc);
+        }
+
+        if (inputDispatchingTimedOut(proc, null, null, aboveSystem, reason)) {
+            return -1;
+        }
+
+        return timeout;
+    }
+
+    /**
+     * Handle input dispatching timeouts.
+     * Returns whether input dispatching should be aborted or not.
+     */
+    boolean inputDispatchingTimedOut(final WindowProcessController proc,
+            final ActivityRecord activity, final ActivityRecord parent,
+            final boolean aboveSystem, String reason) {
+        if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires permission " + FILTER_EVENTS);
+        }
+
+        final String annotation;
+        if (reason == null) {
+            annotation = "Input dispatching timed out";
+        } else {
+            annotation = "Input dispatching timed out (" + reason + ")";
+        }
+
+        if (proc != null) {
+            synchronized (mGlobalLock) {
+                if (proc.isDebugging()) {
+                    return false;
+                }
+
+                if (proc.isInstrumenting()) {
+                    Bundle info = new Bundle();
+                    info.putString("shortMsg", "keyDispatchingTimedOut");
+                    info.putString("longMsg", annotation);
+                    mAm.finishInstrumentationLocked(
+                            (ProcessRecord) proc.mOwner, Activity.RESULT_CANCELED, info);
+                    return true;
+                }
+            }
+            mH.post(() -> {
+                mAm.mAppErrors.appNotResponding(
+                        (ProcessRecord) proc.mOwner, activity, parent, aboveSystem, annotation);
+            });
+        }
+
+        return true;
+    }
+
+    /**
+     * Decide based on the configuration whether we should show the ANR,
+     * crash, etc dialogs.  The idea is that if there is no affordance to
+     * press the on-screen buttons, or the user experience would be more
+     * greatly impacted than the crash itself, we shouldn't show the dialog.
+     *
+     * A thought: SystemUI might also want to get told about this, the Power
+     * dialog / global actions also might want different behaviors.
+     */
+    private void updateShouldShowDialogsLocked(Configuration config) {
+        final boolean inputMethodExists = !(config.keyboard == Configuration.KEYBOARD_NOKEYS
+                && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH
+                && config.navigation == Configuration.NAVIGATION_NONAV);
+        int modeType = config.uiMode & Configuration.UI_MODE_TYPE_MASK;
+        final boolean uiModeSupportsDialogs = (modeType != Configuration.UI_MODE_TYPE_CAR
+                && !(modeType == Configuration.UI_MODE_TYPE_WATCH && Build.IS_USER)
+                && modeType != Configuration.UI_MODE_TYPE_TELEVISION
+                && modeType != Configuration.UI_MODE_TYPE_VR_HEADSET);
+        final boolean hideDialogsSet = Settings.Global.getInt(mContext.getContentResolver(),
+                HIDE_ERROR_DIALOGS, 0) != 0;
+        mShowDialogs = inputMethodExists && uiModeSupportsDialogs && !hideDialogsSet;
+    }
+
+    private void updateFontScaleIfNeeded(@UserIdInt int userId) {
+        final float scaleFactor = Settings.System.getFloatForUser(mContext.getContentResolver(),
+                FONT_SCALE, 1.0f, userId);
+
+        synchronized (this) {
+            if (getGlobalConfiguration().fontScale == scaleFactor) {
+                return;
+            }
+
+            final Configuration configuration
+                    = mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
+            configuration.fontScale = scaleFactor;
+            updatePersistentConfiguration(configuration, userId);
+        }
+    }
+
+    // Actually is sleeping or shutting down or whatever else in the future
+    // is an inactive state.
+    boolean isSleepingOrShuttingDownLocked() {
+        return isSleepingLocked() || mShuttingDown;
+    }
+
+    boolean isSleepingLocked() {
+        return mSleeping;
+    }
+
+    /**
+     * Update AMS states when an activity is resumed. This should only be called by
+     * {@link ActivityStack#onActivityStateChanged(
+     * ActivityRecord, ActivityStack.ActivityState, String)} when an activity is resumed.
+     */
+    void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
+        final TaskRecord task = r.getTask();
+        if (task.isActivityTypeStandard()) {
+            if (mCurAppTimeTracker != r.appTimeTracker) {
+                // We are switching app tracking.  Complete the current one.
+                if (mCurAppTimeTracker != null) {
+                    mCurAppTimeTracker.stop();
+                    mH.obtainMessage(
+                            REPORT_TIME_TRACKER_MSG, mCurAppTimeTracker).sendToTarget();
+                    mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker);
+                    mCurAppTimeTracker = null;
+                }
+                if (r.appTimeTracker != null) {
+                    mCurAppTimeTracker = r.appTimeTracker;
+                    startTimeTrackingFocusedActivityLocked();
+                }
+            } else {
+                startTimeTrackingFocusedActivityLocked();
+            }
+        } else {
+            r.appTimeTracker = null;
+        }
+        // TODO: VI Maybe r.task.voiceInteractor || r.voiceInteractor != null
+        // TODO: Probably not, because we don't want to resume voice on switching
+        // back to this activity
+        if (task.voiceInteractor != null) {
+            startRunningVoiceLocked(task.voiceSession, r.info.applicationInfo.uid);
+        } else {
+            finishRunningVoiceLocked();
+
+            if (mLastResumedActivity != null) {
+                final IVoiceInteractionSession session;
+
+                final TaskRecord lastResumedActivityTask = mLastResumedActivity.getTask();
+                if (lastResumedActivityTask != null
+                        && lastResumedActivityTask.voiceSession != null) {
+                    session = lastResumedActivityTask.voiceSession;
+                } else {
+                    session = mLastResumedActivity.voiceSession;
+                }
+
+                if (session != null) {
+                    // We had been in a voice interaction session, but now focused has
+                    // move to something different.  Just finish the session, we can't
+                    // return to it and retain the proper state and synchronization with
+                    // the voice interaction service.
+                    finishVoiceTask(session);
+                }
+            }
+        }
+
+        if (mLastResumedActivity != null && r.userId != mLastResumedActivity.userId) {
+            mAmInternal.sendForegroundProfileChanged(r.userId);
+        }
+        updateResumedAppTrace(r);
+        mLastResumedActivity = r;
+
+        // TODO(b/111361570): Support multiple focused apps in WM
+        mWindowManager.setFocusedApp(r.appToken, true);
+
+        applyUpdateLockStateLocked(r);
+        applyUpdateVrModeLocked(r);
+
+        EventLogTags.writeAmSetResumedActivity(
+                r == null ? -1 : r.userId,
+                r == null ? "NULL" : r.shortComponentName,
+                reason);
+    }
+
+    ActivityTaskManagerInternal.SleepToken acquireSleepToken(String tag, int displayId) {
+        synchronized (mGlobalLock) {
+            final ActivityTaskManagerInternal.SleepToken token = mStackSupervisor.createSleepTokenLocked(tag, displayId);
+            updateSleepIfNeededLocked();
+            return token;
+        }
+    }
+
+    void updateSleepIfNeededLocked() {
+        final boolean shouldSleep = !mStackSupervisor.hasAwakeDisplay();
+        final boolean wasSleeping = mSleeping;
+        boolean updateOomAdj = false;
+
+        if (!shouldSleep) {
+            // If wasSleeping is true, we need to wake up activity manager state from when
+            // we started sleeping. In either case, we need to apply the sleep tokens, which
+            // will wake up stacks or put them to sleep as appropriate.
+            if (wasSleeping) {
+                mSleeping = false;
+                StatsLog.write(StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED,
+                        StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED__STATE__AWAKE);
+                startTimeTrackingFocusedActivityLocked();
+                mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
+                mStackSupervisor.comeOutOfSleepIfNeededLocked();
+            }
+            mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */);
+            if (wasSleeping) {
+                updateOomAdj = true;
+            }
+        } else if (!mSleeping && shouldSleep) {
+            mSleeping = true;
+            StatsLog.write(StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED,
+                    StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED__STATE__ASLEEP);
+            if (mCurAppTimeTracker != null) {
+                mCurAppTimeTracker.stop();
+            }
+            mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
+            mStackSupervisor.goingToSleepLocked();
+            updateResumedAppTrace(null /* resumed */);
+            updateOomAdj = true;
+        }
+        if (updateOomAdj) {
+            mH.post(mAmInternal::updateOomAdj);
+        }
+    }
+
+    void updateOomAdj() {
+        mH.post(mAmInternal::updateOomAdj);
+    }
+
+    // TODO(b/111541062): Update app time tracking to make it aware of multiple resumed activities
+    private void startTimeTrackingFocusedActivityLocked() {
+        final ActivityRecord resumedActivity = mStackSupervisor.getTopResumedActivity();
+        if (!mSleeping && mCurAppTimeTracker != null && resumedActivity != null) {
+            mCurAppTimeTracker.start(resumedActivity.packageName);
+        }
+    }
+
+    private void updateResumedAppTrace(@Nullable ActivityRecord resumed) {
+        if (mTracedResumedActivity != null) {
+            Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER,
+                    constructResumedTraceName(mTracedResumedActivity.packageName), 0);
+        }
+        if (resumed != null) {
+            Trace.asyncTraceBegin(TRACE_TAG_ACTIVITY_MANAGER,
+                    constructResumedTraceName(resumed.packageName), 0);
+        }
+        mTracedResumedActivity = resumed;
+    }
+
+    private String constructResumedTraceName(String packageName) {
+        return "focused app: " + packageName;
+    }
+
     /** Helper method that requests bounds from WM and applies them to stack. */
     private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
         final Rect newStackBounds = new Rect();
@@ -4313,7 +4861,7 @@
     /** Applies latest configuration and/or visibility updates if needed. */
     private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
         boolean kept = true;
-        final ActivityStack mainStack = mStackSupervisor.getFocusedStack();
+        final ActivityStack mainStack = mStackSupervisor.getTopDisplayFocusedStack();
         // mainStack is null during startup.
         if (mainStack != null) {
             if (changes != 0 && starting == null) {
@@ -4336,6 +4884,30 @@
         return kept;
     }
 
+    void scheduleAppGcsLocked() {
+        mH.post(() -> mAmInternal.scheduleAppGcs());
+    }
+
+    /**
+     * Returns the PackageManager. Used by classes hosted by {@link ActivityTaskManagerService}. The
+     * PackageManager could be unavailable at construction time and therefore needs to be accessed
+     * on demand.
+     */
+    IPackageManager getPackageManager() {
+        return AppGlobals.getPackageManager();
+    }
+
+    PackageManagerInternal getPackageManagerInternalLocked() {
+        if (mPmInternal == null) {
+            mPmInternal = LocalServices.getService(PackageManagerInternal.class);
+        }
+        return mPmInternal;
+    }
+
+    AppWarnings getAppWarningsLocked() {
+        return mAppWarnings;
+    }
+
     void logAppTooSlow(WindowProcessController app, long startTime, String msg) {
         if (true || Build.IS_USER) {
             return;
@@ -4396,23 +4968,47 @@
     }
 
     final class H extends Handler {
+        static final int REPORT_TIME_TRACKER_MSG = 1;
+
         public H(Looper looper) {
             super(looper, null, true);
         }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case REPORT_TIME_TRACKER_MSG: {
+                    AppTimeTracker tracker = (AppTimeTracker) msg.obj;
+                    tracker.deliverResult(mContext);
+                } break;
+            }
+        }
     }
 
     final class UiHandler extends Handler {
+        static final int DISMISS_DIALOG_UI_MSG = 1;
 
         public UiHandler() {
             super(com.android.server.UiThread.get().getLooper(), null, true);
         }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case DISMISS_DIALOG_UI_MSG: {
+                    final Dialog d = (Dialog) msg.obj;
+                    d.dismiss();
+                    break;
+                }
+            }
+        }
     }
 
     final class LocalService extends ActivityTaskManagerInternal {
         @Override
         public SleepToken acquireSleepToken(String tag, int displayId) {
             Preconditions.checkNotNull(tag);
-            return mAm.acquireSleepToken(tag, displayId);
+            return ActivityTaskManagerService.this.acquireSleepToken(tag, displayId);
         }
 
         @Override
@@ -4427,7 +5023,7 @@
         public void onLocalVoiceInteractionStarted(IBinder activity,
                 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
             synchronized (mGlobalLock) {
-                mAm.onLocalVoiceInteractionStartedLocked(activity, voiceSession, voiceInteractor);
+                onLocalVoiceInteractionStartedLocked(activity, voiceSession, voiceInteractor);
             }
         }
 
@@ -4498,7 +5094,7 @@
                         packageUid, packageName,
                         intents, resolvedTypes, null /* resultTo */,
                         SafeActivityOptions.fromBundle(bOptions), userId,
-                        false /* validateIncomingUser */);
+                        false /* validateIncomingUser */, null /* originatingPendingIntent */);
             }
         }
 
@@ -4569,7 +5165,7 @@
                 }
                 if (mStackSupervisor.moveFocusableActivityStackToFrontLocked(
                         r, "setFocusedActivity")) {
-                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                    mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 }
             }
         }
@@ -4669,5 +5265,132 @@
                 }
             }
         }
+
+        @Override
+        public int getTopProcessState() {
+            synchronized (mGlobalLock) {
+                return mTopProcessState;
+            }
+        }
+
+        @Override
+        public boolean isSleeping() {
+            synchronized (mGlobalLock) {
+                return isSleepingLocked();
+            }
+        }
+
+        @Override
+        public boolean isShuttingDown() {
+            synchronized (mGlobalLock) {
+                return mShuttingDown;
+            }
+        }
+
+        @Override
+        public boolean shuttingDown(boolean booted, int timeout) {
+            synchronized (mGlobalLock) {
+                mShuttingDown = true;
+                mStackSupervisor.prepareForShutdownLocked();
+                updateEventDispatchingLocked(booted);
+                return mStackSupervisor.shutdownLocked(timeout);
+            }
+        }
+
+        @Override
+        public void enableScreenAfterBoot(boolean booted) {
+            synchronized (mGlobalLock) {
+                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
+                        SystemClock.uptimeMillis());
+                mWindowManager.enableScreenAfterBoot();
+                updateEventDispatchingLocked(booted);
+            }
+        }
+
+        @Override
+        public boolean showStrictModeViolationDialog() {
+            synchronized (mGlobalLock) {
+                return mShowDialogs && !mSleeping && !mShuttingDown;
+            }
+        }
+
+        @Override
+        public void showSystemReadyErrorDialogsIfNeeded() {
+            synchronized (mGlobalLock) {
+                try {
+                    if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
+                        Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
+                                + " data partition or your device will be unstable.");
+                        mUiHandler.post(() -> {
+                            if (mShowDialogs) {
+                                AlertDialog d = new BaseErrorDialog(mUiContext);
+                                d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+                                d.setCancelable(false);
+                                d.setTitle(mUiContext.getText(R.string.android_system_label));
+                                d.setMessage(mUiContext.getText(R.string.system_error_wipe_data));
+                                d.setButton(DialogInterface.BUTTON_POSITIVE,
+                                        mUiContext.getText(R.string.ok),
+                                        mUiHandler.obtainMessage(DISMISS_DIALOG_UI_MSG, d));
+                                d.show();
+                            }
+                        });
+                    }
+                } catch (RemoteException e) {
+                }
+
+                if (!Build.isBuildConsistent()) {
+                    Slog.e(TAG, "Build fingerprint is not consistent, warning user");
+                    mUiHandler.post(() -> {
+                        if (mShowDialogs) {
+                            AlertDialog d = new BaseErrorDialog(mUiContext);
+                            d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+                            d.setCancelable(false);
+                            d.setTitle(mUiContext.getText(R.string.android_system_label));
+                            d.setMessage(mUiContext.getText(R.string.system_error_manufacturer));
+                            d.setButton(DialogInterface.BUTTON_POSITIVE,
+                                    mUiContext.getText(R.string.ok),
+                                    mUiHandler.obtainMessage(DISMISS_DIALOG_UI_MSG, d));
+                            d.show();
+                        }
+                    });
+                }
+            }
+        }
+
+        @Override
+        public long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason) {
+            synchronized (mGlobalLock) {
+                return ActivityTaskManagerService.this.inputDispatchingTimedOut(
+                        pid, aboveSystem, reason);
+            }
+        }
+
+        @Override
+        public void onProcessMapped(int pid, WindowProcessController proc) {
+            synchronized (mGlobalLock) {
+                mPidMap.put(pid, proc);
+            }
+        }
+
+        @Override
+        public void onProcessUnMapped(int pid) {
+            synchronized (mGlobalLock) {
+                mPidMap.remove(pid);
+            }
+        }
+
+        @Override
+        public void onPackageDataCleared(String name) {
+            synchronized (mGlobalLock) {
+                mAppWarnings.onPackageDataCleared(name);
+            }
+        }
+
+        @Override
+        public void onPackageUninstalled(String name) {
+            synchronized (mGlobalLock) {
+                mAppWarnings.onPackageUninstalled(name);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 7db98b3..162f344 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -410,6 +410,10 @@
             RescueParty.notePersistentAppCrash(mContext, r.uid);
         }
 
+        final int relaunchReason = r != null
+                ? r.getWindowProcessController().computeRelaunchReason()
+                : ActivityRecord.RELAUNCH_REASON_NONE;
+
         AppErrorResult result = new AppErrorResult();
         TaskRecord task;
         synchronized (mService) {
@@ -422,11 +426,17 @@
                 return;
             }
 
+            // Suppress crash dialog if the process is being relaunched due to a crash during a free
+            // resize.
+            if (relaunchReason == ActivityRecord.RELAUNCH_REASON_FREE_RESIZE) {
+                return;
+            }
+
             /**
              * If this process was running instrumentation, finish now - it will be handled in
              * {@link ActivityManagerService#handleAppDiedLocked}.
              */
-            if (r != null && r.instr != null) {
+            if (r != null && r.getActiveInstrumentation() != null) {
                 return;
             }
 
@@ -481,7 +491,8 @@
                                     task.intent, null, null, null, 0, 0,
                                     new SafeActivityOptions(ActivityOptions.makeBasic()),
                                     task.userId, null,
-                                    "AppErrors", false /*validateIncomingUser*/);
+                                    "AppErrors", false /*validateIncomingUser*/,
+                                    null /* originatingPendingIntent */);
                         }
                     }
                 }
@@ -493,7 +504,7 @@
                     mService.mStackSupervisor.handleAppCrashLocked(r.getWindowProcessController());
                     if (!r.isPersistent()) {
                         mService.removeProcessLocked(r, false, false, "crash");
-                        mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                        mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                     }
                 } finally {
                     Binder.restoreCallingIdentity(orig);
@@ -733,12 +744,12 @@
                 // annoy the user repeatedly.  Unless it is persistent, since those
                 // processes run critical code.
                 mService.removeProcessLocked(app, false, tryAgain, "crash");
-                mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 if (!showBackground) {
                     return false;
                 }
             }
-            mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
         } else {
             final TaskRecord affectedTask =
                     mService.mStackSupervisor.finishTopCrashedActivitiesLocked(app.getWindowProcessController(), reason);
@@ -824,7 +835,8 @@
                     mService.mUserController.getCurrentUserId()) != 0;
             final boolean crashSilenced = mAppsNotReportingCrashes != null &&
                     mAppsNotReportingCrashes.contains(proc.info.packageName);
-            if ((mService.canShowErrorDialogs() || showBackground) && !crashSilenced
+            if ((mService.mActivityTaskManager.canShowErrorDialogs() || showBackground)
+                    && !crashSilenced
                     && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
                 proc.crashDialog = dialogToShow = new AppErrorDialog(mContext, mService, data);
             } else {
@@ -901,7 +913,7 @@
 
         synchronized (mService) {
             // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
-            if (mService.mShuttingDown) {
+            if (mService.mActivityTaskManager.mShuttingDown) {
                 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
                 return;
             } else if (app.isNotResponding()) {
@@ -1122,7 +1134,7 @@
 
             boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                     Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
-            if (mService.canShowErrorDialogs() || showBackground) {
+            if (mService.mActivityTaskManager.canShowErrorDialogs() || showBackground) {
                 dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
                 proc.anrDialog = dialogToShow;
             } else {
diff --git a/services/core/java/com/android/server/am/AppTaskImpl.java b/services/core/java/com/android/server/am/AppTaskImpl.java
index c22dedc..a1f1ff9 100644
--- a/services/core/java/com/android/server/am/AppTaskImpl.java
+++ b/services/core/java/com/android/server/am/AppTaskImpl.java
@@ -97,7 +97,7 @@
         final int callingUid = Binder.getCallingUid();
         final long origId = Binder.clearCallingIdentity();
         try {
-            synchronized (this) {
+            synchronized (mService.mGlobalLock) {
                 mService.mStackSupervisor.startActivityFromRecents(callingPid, callingUid, mTaskId,
                         null);
             }
diff --git a/services/core/java/com/android/server/am/AppWarnings.java b/services/core/java/com/android/server/am/AppWarnings.java
index 30a3844..a705180 100644
--- a/services/core/java/com/android/server/am/AppWarnings.java
+++ b/services/core/java/com/android/server/am/AppWarnings.java
@@ -17,7 +17,6 @@
 package com.android.server.am;
 
 import android.annotation.UiThread;
-import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -57,9 +56,9 @@
 
     private final HashMap<String, Integer> mPackageFlags = new HashMap<>();
 
-    private final ActivityManagerService mAms;
+    private final ActivityTaskManagerService mAtm;
     private final Context mUiContext;
-    private final ConfigHandler mAmsHandler;
+    private final ConfigHandler mHandler;
     private final UiHandler mUiHandler;
     private final AtomicFile mConfigFile;
 
@@ -81,17 +80,17 @@
      * <p>
      * <strong>Note:</strong> Must be called from the ActivityManagerService thread.
      *
-     * @param ams
+     * @param atm
      * @param uiContext
-     * @param amsHandler
+     * @param handler
      * @param uiHandler
      * @param systemDir
      */
-    public AppWarnings(ActivityManagerService ams, Context uiContext, Handler amsHandler,
+    public AppWarnings(ActivityTaskManagerService atm, Context uiContext, Handler handler,
             Handler uiHandler, File systemDir) {
-        mAms = ams;
+        mAtm = atm;
         mUiContext = uiContext;
-        mAmsHandler = new ConfigHandler(amsHandler.getLooper());
+        mHandler = new ConfigHandler(handler.getLooper());
         mUiHandler = new UiHandler(uiHandler.getLooper());
         mConfigFile = new AtomicFile(new File(systemDir, CONFIG_FILE_NAME), "warnings-config");
 
@@ -104,7 +103,7 @@
      * @param r activity record for which the warning may be displayed
      */
     public void showUnsupportedDisplaySizeDialogIfNeeded(ActivityRecord r) {
-        final Configuration globalConfig = mAms.getGlobalConfiguration();
+        final Configuration globalConfig = mAtm.getGlobalConfiguration();
         if (globalConfig.densityDpi != DisplayMetrics.DENSITY_DEVICE_STABLE
                 && r.appInfo.requiresSmallestWidthDp > globalConfig.smallestScreenWidthDp) {
             mUiHandler.showUnsupportedDisplaySizeDialog(r);
@@ -211,7 +210,7 @@
 
         synchronized (mPackageFlags) {
             mPackageFlags.remove(name);
-            mAmsHandler.scheduleWrite();
+            mHandler.scheduleWrite();
         }
     }
 
@@ -351,7 +350,7 @@
                 } else {
                     mPackageFlags.remove(name);
                 }
-                mAmsHandler.scheduleWrite();
+                mHandler.scheduleWrite();
             }
         }
     }
@@ -430,10 +429,10 @@
     }
 
     /**
-     * Handles messages on the ActivityManagerService thread.
+     * Handles messages on the ActivityTaskManagerService thread.
      */
     private final class ConfigHandler extends Handler {
-        private static final int MSG_WRITE = ActivityManagerService.FIRST_COMPAT_MODE_MSG;
+        private static final int MSG_WRITE = 1;
 
         private static final int DELAY_MSG_WRITE = 10000;
 
diff --git a/services/core/java/com/android/server/am/BackupRecord.java b/services/core/java/com/android/server/am/BackupRecord.java
index 5fa7e6a..40ad383 100644
--- a/services/core/java/com/android/server/am/BackupRecord.java
+++ b/services/core/java/com/android/server/am/BackupRecord.java
@@ -16,8 +16,6 @@
 
 package com.android.server.am;
 
-import com.android.internal.os.BatteryStatsImpl;
-
 import android.content.pm.ApplicationInfo;
 
 /** @hide */
@@ -28,7 +26,6 @@
     public static final int RESTORE = 2;
     public static final int RESTORE_FULL = 3;
     
-    final BatteryStatsImpl.Uid.Pkg.Serv stats;
     String stringName;                     // cached toString() output
     final ApplicationInfo appInfo;         // information about BackupAgent's app
     final int backupMode;                  // full backup / incremental / restore
@@ -36,9 +33,7 @@
 
     // ----- Implementation -----
 
-    BackupRecord(BatteryStatsImpl.Uid.Pkg.Serv _agentStats, ApplicationInfo _appInfo,
-            int _backupMode) {
-        stats = _agentStats;
+    BackupRecord(ApplicationInfo _appInfo, int _backupMode) {
         appInfo = _appInfo;
         backupMode = _backupMode;
     }
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index d9a8818c..2541352 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -15,6 +15,8 @@
  */
 package com.android.server.am;
 
+import static android.net.wifi.WifiManager.WIFI_FEATURE_LINK_LAYER_STATS;
+
 import android.annotation.Nullable;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.BluetoothAdapter;
@@ -410,8 +412,11 @@
 
             if (mWifiManager != null) {
                 try {
-                    wifiReceiver = new SynchronousResultReceiver("wifi");
-                    mWifiManager.requestActivityInfo(wifiReceiver);
+                    // Only fetch WiFi power data if it is supported.
+                    if ((mWifiManager.getSupportedFeatures() & WIFI_FEATURE_LINK_LAYER_STATS) != 0) {
+                        wifiReceiver = new SynchronousResultReceiver("wifi");
+                        mWifiManager.requestActivityInfo(wifiReceiver);
+                    }
                 } catch (RemoteException e) {
                     // Oh well.
                 }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index ef23a83..ab9ba08 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -59,6 +59,7 @@
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.RpmStats;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.ParseUtils;
 import com.android.server.LocalServices;
 
 import java.io.File;
@@ -395,6 +396,7 @@
             mStats.writeToParcel(out, 0);
         }
         byte[] data = out.marshall();
+        if (DBG) Slog.d(TAG, "getStatisticsStream parcel size is:" + data.length);
         out.recycle();
         try {
             return ParcelFileDescriptor.fromData(data, "battery-stats");
@@ -1222,6 +1224,7 @@
         pw.println("  --proto: write the current aggregate stats (without history) in proto format.");
         pw.println("  --history: show only history data.");
         pw.println("  --history-start <num>: show only history data starting at given time offset.");
+        pw.println("  --history-create-events <num>: create <num> of battery history events.");
         pw.println("  --charged: only output data since last charged.");
         pw.println("  --daily: only output full daily data.");
         pw.println("  --reset: reset the stats, clearing all current data.");
@@ -1310,8 +1313,21 @@
                         dumpHelp(pw);
                         return;
                     }
-                    historyStart = Long.parseLong(args[i]);
+                    historyStart = ParseUtils.parseLong(args[i], 0);
                     writeData = true;
+                } else if ("--history-create-events".equals(arg)) {
+                    i++;
+                    if (i >= args.length) {
+                        pw.println("Missing events argument for --history-create-events");
+                        dumpHelp(pw);
+                        return;
+                    }
+                    final long events = ParseUtils.parseLong(args[i], 0);
+                    synchronized (mStats) {
+                        mStats.createFakeHistoryEvents(events);
+                        pw.println("Battery history create events started.");
+                        noOutput = true;
+                    }
                 } else if ("-c".equals(arg)) {
                     useCheckinFormat = true;
                     flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index a9fd51d..b36b5d3 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -664,12 +664,10 @@
         // the broadcast and if the calling app is in the foreground and the broadcast is
         // explicit we launch the review UI passing it a pending intent to send the skipped
         // broadcast.
-        if (mService.mPermissionReviewRequired) {
-            if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
-                    filter.owningUserId)) {
-                r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
-                return;
-            }
+        if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
+                filter.owningUserId)) {
+            r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
+            return;
         }
 
         r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;
@@ -1240,7 +1238,7 @@
         // the broadcast and if the calling app is in the foreground and the broadcast is
         // explicit we launch the review UI passing it a pending intent to send the skipped
         // broadcast.
-        if (mService.mPermissionReviewRequired && !skip) {
+        if (!skip) {
             if (!requestStartTargetPermissionsReviewIfNeededLocked(r,
                     info.activityInfo.packageName, UserHandle.getUserId(
                             info.activityInfo.applicationInfo.uid))) {
@@ -1464,7 +1462,7 @@
         // If the receiver app is being debugged we quietly ignore unresponsiveness, just
         // tidying up and moving on to the next broadcast without crashing or ANRing this
         // app just because it's stopped at a breakpoint.
-        final boolean debugging = (r.curApp != null && r.curApp.debugging);
+        final boolean debugging = (r.curApp != null && r.curApp.isDebugging());
 
         Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
                 + ", started " + (now - r.receiverTime) + "ms ago");
diff --git a/services/core/java/com/android/server/am/CompatModeDialog.java b/services/core/java/com/android/server/am/CompatModeDialog.java
deleted file mode 100644
index 202cc7c..0000000
--- a/services/core/java/com/android/server/am/CompatModeDialog.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.am;
-
-import android.app.ActivityManager;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.view.Gravity;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.Switch;
-
-public final class CompatModeDialog extends Dialog {
-    final ActivityManagerService mService;
-    final ApplicationInfo mAppInfo;
-
-    final Switch mCompatEnabled;
-    final CheckBox mAlwaysShow;
-    final View mHint;
-
-    public CompatModeDialog(ActivityManagerService service, Context context,
-            ApplicationInfo appInfo) {
-        super(context, com.android.internal.R.style.Theme_Holo_Dialog_MinWidth);
-        setCancelable(true);
-        setCanceledOnTouchOutside(true);
-        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
-        getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
-        getWindow().setGravity(Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL);
-        mService = service;
-        mAppInfo = appInfo;
-
-        setContentView(com.android.internal.R.layout.am_compat_mode_dialog);
-        mCompatEnabled = (Switch)findViewById(com.android.internal.R.id.compat_checkbox);
-        mCompatEnabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
-            @Override
-            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                synchronized (mService) {
-                    mService.mCompatModePackages.setPackageScreenCompatModeLocked(
-                            mAppInfo.packageName,
-                            mCompatEnabled.isChecked() ? ActivityManager.COMPAT_MODE_ENABLED
-                                    : ActivityManager.COMPAT_MODE_DISABLED);
-                    updateControls();
-                }
-            }
-        });
-        mAlwaysShow = (CheckBox)findViewById(com.android.internal.R.id.ask_checkbox);
-        mAlwaysShow.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
-            @Override
-            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                synchronized (mService) {
-                    mService.mCompatModePackages.setPackageAskCompatModeLocked(
-                            mAppInfo.packageName, mAlwaysShow.isChecked());
-                    updateControls();
-                }
-            }
-        });
-        mHint = findViewById(com.android.internal.R.id.reask_hint);
-
-        updateControls();
-    }
-
-    void updateControls() {
-        synchronized (mService) {
-            int mode = mService.mCompatModePackages.computeCompatModeLocked(mAppInfo);
-            mCompatEnabled.setChecked(mode == ActivityManager.COMPAT_MODE_ENABLED);
-            boolean ask = mService.mCompatModePackages.getPackageAskCompatModeLocked(
-                    mAppInfo.packageName);
-            mAlwaysShow.setChecked(ask);
-            mHint.setVisibility(ask ? View.INVISIBLE : View.VISIBLE);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index 38254b8..77efbfc 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -317,7 +317,7 @@
 
             scheduleWrite();
 
-            final ActivityStack stack = mService.mActivityTaskManager.getFocusedStack();
+            final ActivityStack stack = mService.mActivityTaskManager.getTopDisplayFocusedStack();
             ActivityRecord starting = stack.restartPackage(packageName);
 
             // Tell all processes that loaded this package about the change.
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index 679024ee..fa8e6c4 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -16,12 +16,18 @@
 
 package com.android.server.am;
 
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+
 import android.app.IServiceConnection;
 import android.app.PendingIntent;
 import android.content.Context;
+import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
 
+import com.android.internal.app.procstats.AssociationState;
+import com.android.internal.app.procstats.ProcessStats;
+
 import java.io.PrintWriter;
 
 /**
@@ -34,6 +40,9 @@
     final int flags;                // Binding options.
     final int clientLabel;          // String resource labeling this client.
     final PendingIntent clientIntent; // How to launch the client.
+    final int clientUid;            // The identity of this connection's client
+    final String clientProcessName; // The source process of this connection's client
+    public AssociationState.SourceState association; // Association tracking
     String stringName;              // Caching of toString.
     boolean serviceDead;            // Well is it?
 
@@ -83,14 +92,54 @@
     }
 
     ConnectionRecord(AppBindRecord _binding, ActivityRecord _activity,
-               IServiceConnection _conn, int _flags,
-               int _clientLabel, PendingIntent _clientIntent) {
+            IServiceConnection _conn, int _flags,
+            int _clientLabel, PendingIntent _clientIntent,
+            int _clientUid, String _clientProcessName) {
         binding = _binding;
         activity = _activity;
         conn = _conn;
         flags = _flags;
         clientLabel = _clientLabel;
         clientIntent = _clientIntent;
+        clientUid = _clientUid;
+        clientProcessName = _clientProcessName;
+    }
+
+    public void startAssociationIfNeeded() {
+        // If we don't already have an active association, create one...  but only if this
+        // is an association between two different processes.
+        if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS
+                && association == null && binding.service.app != null
+                && (binding.service.appInfo.uid != clientUid
+                        || !binding.service.processName.equals(clientProcessName))) {
+            ProcessStats.ProcessStateHolder holder = binding.service.app.pkgList.get(
+                    binding.service.name.getPackageName());
+            if (holder == null) {
+                Slog.wtf(TAG_AM, "No package in referenced service "
+                        + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+            } else if (holder.pkg == null) {
+                Slog.wtf(TAG_AM, "Inactive holder in referenced service "
+                        + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+            } else {
+                association = holder.pkg.getAssociationStateLocked(holder.state,
+                        binding.service.name.getClassName()).startSource(clientUid,
+                        clientProcessName);
+
+            }
+        }
+    }
+
+    public void trackProcState(int procState, int seq, long now) {
+        if (association != null) {
+            association.trackProcState(procState, seq, now);
+        }
+    }
+
+    public void stopAssociation() {
+        if (association != null) {
+            association.stop();
+            association = null;
+        }
     }
 
     public String toString() {
diff --git a/services/core/java/com/android/server/am/ContentProviderConnection.java b/services/core/java/com/android/server/am/ContentProviderConnection.java
index f2c9e2f..f2d4f73 100644
--- a/services/core/java/com/android/server/am/ContentProviderConnection.java
+++ b/services/core/java/com/android/server/am/ContentProviderConnection.java
@@ -18,14 +18,21 @@
 
 import android.os.Binder;
 import android.os.SystemClock;
+import android.util.Slog;
 import android.util.TimeUtils;
 
+import com.android.internal.app.procstats.AssociationState;
+import com.android.internal.app.procstats.ProcessStats;
+
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+
 /**
  * Represents a link between a content provider and client.
  */
 public final class ContentProviderConnection extends Binder {
     public final ContentProviderRecord provider;
     public final ProcessRecord client;
+    public AssociationState.SourceState association;
     public final long createTime;
     public int stableCount;
     public int unstableCount;
@@ -45,6 +52,42 @@
         createTime = SystemClock.elapsedRealtime();
     }
 
+    public void startAssociationIfNeeded() {
+        // If we don't already have an active association, create one...  but only if this
+        // is an association between two different processes.
+        if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS
+                && association == null && provider.proc != null
+                && (provider.appInfo.uid != client.uid
+                        || !provider.info.processName.equals(client.processName))) {
+            ProcessStats.ProcessStateHolder holder = provider.proc.pkgList.get(
+                    provider.name.getPackageName());
+            if (holder == null) {
+                Slog.wtf(TAG_AM, "No package in referenced provider "
+                        + provider.name.toShortString() + ": proc=" + provider.proc);
+            } else if (holder.pkg == null) {
+                Slog.wtf(TAG_AM, "Inactive holder in referenced provider "
+                        + provider.name.toShortString() + ": proc=" + provider.proc);
+            } else {
+                association = holder.pkg.getAssociationStateLocked(holder.state,
+                        provider.name.getClassName()).startSource(client.uid, client.processName);
+
+            }
+        }
+    }
+
+    public void trackProcState(int procState, int seq, long now) {
+        if (association != null) {
+            association.trackProcState(procState, seq, now);
+        }
+    }
+
+    public void stopAssociation() {
+        if (association != null) {
+            association.stop();
+            association = null;
+        }
+    }
+
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
         sb.append("ContentProviderConnection{");
diff --git a/services/core/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
index cd39bcd..2fc4adc 100644
--- a/services/core/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/core/java/com/android/server/am/ContentProviderRecord.java
@@ -16,6 +16,8 @@
 
 package com.android.server.am;
 
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+
 import android.app.ContentProviderHolder;
 import android.content.ComponentName;
 import android.content.IContentProvider;
@@ -26,11 +28,14 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.util.ArrayMap;
 import android.util.Slog;
 
+import com.android.internal.app.procstats.AssociationState;
+import com.android.internal.app.procstats.ProcessStats;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
 
 final class ContentProviderRecord implements ComponentName.WithComponentName {
     final ActivityManagerService service;
@@ -46,7 +51,7 @@
             = new ArrayList<ContentProviderConnection>();
     //final HashSet<ProcessRecord> clients = new HashSet<ProcessRecord>();
     // Handles for non-framework processes supported by this provider
-    HashMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle;
+    ArrayMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle;
     // Count for external process for which we have no handles.
     int externalProcessNoHandleCount;
     ProcessRecord proc; // if non-null, hosting process.
@@ -62,7 +67,8 @@
         appInfo = ai;
         name = _name;
         singleton = _singleton;
-        noReleaseNeeded = uid == 0 || uid == Process.SYSTEM_UID;
+        noReleaseNeeded = (uid == 0 || uid == Process.SYSTEM_UID)
+                && (_name == null || !"com.android.settings".equals(_name.getPackageName()));
     }
 
     public ContentProviderRecord(ContentProviderRecord cpr) {
@@ -83,22 +89,47 @@
         return holder;
     }
 
+    public void setProcess(ProcessRecord proc) {
+        this.proc = proc;
+        if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS) {
+            for (int iconn = connections.size() - 1; iconn >= 0; iconn--) {
+                final ContentProviderConnection conn = connections.get(iconn);
+                if (proc != null) {
+                    conn.startAssociationIfNeeded();
+                } else {
+                    conn.stopAssociation();
+                }
+            }
+            if (externalProcessTokenToHandle != null) {
+                for (int iext = externalProcessTokenToHandle.size() - 1; iext >= 0; iext--) {
+                    final ExternalProcessHandle handle = externalProcessTokenToHandle.valueAt(iext);
+                    if (proc != null) {
+                        handle.startAssociationIfNeeded(this);
+                    } else {
+                        handle.stopAssociation();
+                    }
+                }
+            }
+        }
+    }
+
     public boolean canRunHere(ProcessRecord app) {
         return (info.multiprocess || info.processName.equals(app.processName))
                 && uid == app.info.uid;
     }
 
-    public void addExternalProcessHandleLocked(IBinder token) {
+    public void addExternalProcessHandleLocked(IBinder token, int callingUid, String callingTag) {
         if (token == null) {
             externalProcessNoHandleCount++;
         } else {
             if (externalProcessTokenToHandle == null) {
-                externalProcessTokenToHandle = new HashMap<IBinder, ExternalProcessHandle>();
+                externalProcessTokenToHandle = new ArrayMap<>();
             }
             ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
             if (handle == null) {
-                handle = new ExternalProcessHandle(token);
+                handle = new ExternalProcessHandle(token, callingUid, callingTag);
                 externalProcessTokenToHandle.put(token, handle);
+                handle.startAssociationIfNeeded(this);
             }
             handle.mAcquisitionCount++;
         }
@@ -129,6 +160,7 @@
     private void removeExternalProcessHandleInternalLocked(IBinder token) {
         ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
         handle.unlinkFromOwnDeathLocked();
+        handle.stopAssociation();
         externalProcessTokenToHandle.remove(token);
         if (externalProcessTokenToHandle.size() == 0) {
             externalProcessTokenToHandle = null;
@@ -234,11 +266,16 @@
     private class ExternalProcessHandle implements DeathRecipient {
         private static final String LOG_TAG = "ExternalProcessHanldle";
 
-        private final IBinder mToken;
-        private int mAcquisitionCount;
+        final IBinder mToken;
+        final int mOwningUid;
+        final String mOwningProcessName;
+        int mAcquisitionCount;
+        AssociationState.SourceState mAssociation;
 
-        public ExternalProcessHandle(IBinder token) {
+        public ExternalProcessHandle(IBinder token, int owningUid, String owningProcessName) {
             mToken = token;
+            mOwningUid = owningUid;
+            mOwningProcessName = owningProcessName;
             try {
                 token.linkToDeath(this, 0);
             } catch (RemoteException re) {
@@ -250,6 +287,37 @@
             mToken.unlinkToDeath(this, 0);
         }
 
+        public void startAssociationIfNeeded(ContentProviderRecord provider) {
+            // If we don't already have an active association, create one...  but only if this
+            // is an association between two different processes.
+            if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS
+                    && mAssociation == null && provider.proc != null
+                    && (provider.appInfo.uid != mOwningUid
+                            || !provider.info.processName.equals(mOwningProcessName))) {
+                ProcessStats.ProcessStateHolder holder = provider.proc.pkgList.get(
+                        provider.name.getPackageName());
+                if (holder == null) {
+                    Slog.wtf(TAG_AM, "No package in referenced provider "
+                            + provider.name.toShortString() + ": proc=" + provider.proc);
+                } else if (holder.pkg == null) {
+                    Slog.wtf(TAG_AM, "Inactive holder in referenced provider "
+                            + provider.name.toShortString() + ": proc=" + provider.proc);
+                } else {
+                    mAssociation = holder.pkg.getAssociationStateLocked(holder.state,
+                            provider.name.getClassName()).startSource(mOwningUid,
+                            mOwningProcessName);
+
+                }
+            }
+        }
+
+        public void stopAssociation() {
+            if (mAssociation != null) {
+                mAssociation.stop();
+                mAssociation = null;
+            }
+        }
+
         @Override
         public void binderDied() {
             synchronized (service) {
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 657e0eb..ee4e36f 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -58,7 +58,7 @@
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_AM;
 
-    private final ActivityManagerService mService;
+    private final ActivityTaskManagerService mService;
     private final ActivityStackSupervisor mStackSupervisor;
     private WindowManagerService mWindowManager;
     private boolean mKeyguardShowing;
@@ -72,7 +72,7 @@
     private SleepToken mSleepToken;
     private int mSecondaryDisplayShowing = INVALID_DISPLAY;
 
-    KeyguardController(ActivityManagerService service,
+    KeyguardController(ActivityTaskManagerService service,
             ActivityStackSupervisor stackSupervisor) {
         mService = service;
         mStackSupervisor = stackSupervisor;
@@ -163,7 +163,7 @@
             updateKeyguardSleepToken();
 
             // Some stack visibility might change (e.g. docked stack)
-            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
             mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
             mStackSupervisor.addStartingWindowsForVisibleActivities(true /* taskSwitch */);
             mWindowManager.executeAppTransition();
@@ -272,7 +272,7 @@
                 // Only the top activity of the focused stack on the default display may control
                 // occluded state.
                 if (display.mDisplayId == DEFAULT_DISPLAY
-                        && mStackSupervisor.isFocusedStack(stack)) {
+                        && mStackSupervisor.isTopDisplayFocusedStack(stack)) {
 
                     // A dismissing activity occludes Keyguard in the insecure case for legacy
                     // reasons.
@@ -381,7 +381,7 @@
                 return;
             }
             mStackSupervisor.moveTasksToFullscreenStackLocked(stack,
-                    mStackSupervisor.mFocusedStack == stack);
+                    stack.isFocusedStackOnDisplay());
         }
     }
 
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index 4fd01cd..643c922 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -446,7 +446,7 @@
             return;
         }
         task.performClearTaskLocked();
-        mSupervisor.resumeFocusedStackTopActivityLocked();
+        mSupervisor.resumeFocusedStacksTopActivitiesLocked();
     }
 
     /**
@@ -578,7 +578,7 @@
         if (andResume) {
             mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
                     lockTaskModeState != LOCK_TASK_MODE_NONE);
-            mSupervisor.resumeFocusedStackTopActivityLocked();
+            mSupervisor.resumeFocusedStacksTopActivitiesLocked();
             mWindowManager.executeAppTransition();
         } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
             mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
@@ -653,7 +653,7 @@
         }
 
         if (taskChanged) {
-            mSupervisor.resumeFocusedStackTopActivityLocked();
+            mSupervisor.resumeFocusedStacksTopActivitiesLocked();
         }
     }
 
diff --git a/services/core/java/com/android/server/am/OomAdjProfiler.java b/services/core/java/com/android/server/am/OomAdjProfiler.java
new file mode 100644
index 0000000..6230e0d
--- /dev/null
+++ b/services/core/java/com/android/server/am/OomAdjProfiler.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.os.PowerManagerInternal;
+import android.os.Process;
+import android.os.SystemClock;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.ProcessCpuTracker;
+import com.android.internal.util.RingBuffer;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+import java.io.PrintWriter;
+
+public class OomAdjProfiler {
+    @GuardedBy("this")
+    private boolean mOnBattery;
+    @GuardedBy("this")
+    private boolean mScreenOff;
+
+    @GuardedBy("this")
+    private long mOomAdjStartTimeMs;
+    @GuardedBy("this")
+    private boolean mOomAdjStarted;
+
+    @GuardedBy("this")
+    private CpuTimes mOomAdjRunTime = new CpuTimes();
+    @GuardedBy("this")
+    private CpuTimes mSystemServerCpuTime = new CpuTimes();
+
+    @GuardedBy("this")
+    private long mLastSystemServerCpuTimeMs;
+    @GuardedBy("this")
+    private boolean mSystemServerCpuTimeUpdateScheduled;
+    private final ProcessCpuTracker mProcessCpuTracker = new ProcessCpuTracker(false);
+
+    @GuardedBy("this")
+    final RingBuffer<CpuTimes> mOomAdjRunTimesHist = new RingBuffer<>(CpuTimes.class, 10);
+    @GuardedBy("this")
+    final RingBuffer<CpuTimes> mSystemServerCpuTimesHist = new RingBuffer<>(CpuTimes.class, 10);
+
+    void batteryPowerChanged(boolean onBattery) {
+        synchronized (this) {
+            scheduleSystemServerCpuTimeUpdate();
+            mOnBattery = onBattery;
+        }
+    }
+
+    void onWakefulnessChanged(int wakefulness) {
+        synchronized (this) {
+            scheduleSystemServerCpuTimeUpdate();
+            mScreenOff = wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE;
+        }
+    }
+
+    void oomAdjStarted() {
+        synchronized (this) {
+            mOomAdjStartTimeMs = SystemClock.currentThreadTimeMillis();
+            mOomAdjStarted = true;
+        }
+    }
+
+    void oomAdjEnded() {
+        synchronized (this) {
+            if (!mOomAdjStarted) {
+                return;
+            }
+            mOomAdjRunTime.addCpuTimeMs(SystemClock.currentThreadTimeMillis() - mOomAdjStartTimeMs);
+        }
+    }
+
+    private void scheduleSystemServerCpuTimeUpdate() {
+        synchronized (this) {
+            if (mSystemServerCpuTimeUpdateScheduled) {
+                return;
+            }
+            mSystemServerCpuTimeUpdateScheduled = true;
+            BackgroundThread.getHandler().post(PooledLambda.obtainRunnable(
+                    OomAdjProfiler::updateSystemServerCpuTime,
+                    this, mOnBattery, mScreenOff).recycleOnUse());
+        }
+    }
+
+    private void updateSystemServerCpuTime(boolean onBattery, boolean screenOff) {
+        final long cpuTimeMs = mProcessCpuTracker.getCpuTimeForPid(Process.myPid());
+        synchronized (this) {
+            mSystemServerCpuTime.addCpuTimeMs(
+                    cpuTimeMs - mLastSystemServerCpuTimeMs, onBattery, screenOff);
+            mLastSystemServerCpuTimeMs = cpuTimeMs;
+            mSystemServerCpuTimeUpdateScheduled = false;
+            notifyAll();
+        }
+    }
+
+    void reset() {
+        synchronized (this) {
+            if (mSystemServerCpuTime.isEmpty()) {
+                return;
+            }
+            mOomAdjRunTimesHist.append(mOomAdjRunTime);
+            mSystemServerCpuTimesHist.append(mSystemServerCpuTime);
+            mOomAdjRunTime = new CpuTimes();
+            mSystemServerCpuTime = new CpuTimes();
+        }
+    }
+
+    void dump(PrintWriter pw) {
+        synchronized (this) {
+            if (mSystemServerCpuTimeUpdateScheduled) {
+                while (mSystemServerCpuTimeUpdateScheduled) {
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                    }
+                }
+            } else {
+                updateSystemServerCpuTime(mOnBattery, mScreenOff);
+            }
+
+            pw.println("System server and oomAdj runtimes (ms) in recent battery sessions "
+                    + "(most recent first):");
+            if (!mSystemServerCpuTime.isEmpty()) {
+                pw.print("  ");
+                pw.print("system_server=");
+                pw.print(mSystemServerCpuTime);
+                pw.print("  ");
+                pw.print("oom_adj=");
+                pw.println(mOomAdjRunTime);
+            }
+            final CpuTimes[] systemServerCpuTimes = mSystemServerCpuTimesHist.toArray();
+            final CpuTimes[] oomAdjRunTimes = mOomAdjRunTimesHist.toArray();
+            for (int i = oomAdjRunTimes.length - 1; i >= 0; --i) {
+                pw.print("  ");
+                pw.print("system_server=");
+                pw.print(systemServerCpuTimes[i]);
+                pw.print("  ");
+                pw.print("oom_adj=");
+                pw.println(oomAdjRunTimes[i]);
+            }
+        }
+    }
+
+    private class CpuTimes {
+        private long mOnBatteryTimeMs;
+        private long mOnBatteryScreenOffTimeMs;
+
+        public void addCpuTimeMs(long cpuTimeMs) {
+            addCpuTimeMs(cpuTimeMs, mOnBattery, mScreenOff);
+        }
+
+        public void addCpuTimeMs(long cpuTimeMs, boolean onBattery, boolean screenOff) {
+            if (onBattery) {
+                mOnBatteryTimeMs += cpuTimeMs;
+                if (screenOff) {
+                    mOnBatteryScreenOffTimeMs += cpuTimeMs;
+                }
+            }
+        }
+
+        public boolean isEmpty() {
+            return mOnBatteryTimeMs == 0 && mOnBatteryScreenOffTimeMs == 0;
+        }
+
+        public String toString() {
+            return "[" + mOnBatteryTimeMs + "," + mOnBatteryScreenOffTimeMs + "]";
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index db09165..ee1166e 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -307,7 +307,7 @@
                             } else if (finalIntent.getComponent() != null) {
                                 finalIntent.getComponent().appendShortString(tag);
                             } else if (finalIntent.getData() != null) {
-                                tag.append(finalIntent.getData());
+                                tag.append(finalIntent.getData().toSafeString());
                             }
                             owner.tempWhitelistForPendingIntentLocked(callingPid,
                                     callingUid, uid, duration, tag.toString());
@@ -346,13 +346,15 @@
                                 res = owner.mActivityTaskManager.getActivityStartController().startActivitiesInPackage(
                                         uid, key.packageName, allIntents, allResolvedTypes,
                                         resultTo, mergedOptions, userId,
-                                        false /* validateIncomingUser */);
+                                        false /* validateIncomingUser */,
+                                        this /* originatingPendingIntent */);
                             } else {
                                 res = owner.mActivityTaskManager.getActivityStartController().startActivityInPackage(uid,
                                         callingPid, callingUid, key.packageName, finalIntent,
                                         resolvedType, resultTo, resultWho, requestCode, 0,
                                         mergedOptions, userId, null, "PendingIntentRecord",
-                                        false /* validateIncomingUser */);
+                                        false /* validateIncomingUser */,
+                                        this /* originatingPendingIntent */);
                             }
                         } catch (RuntimeException e) {
                             Slog.w(TAG, "Unable to send startActivity intent", e);
diff --git a/services/core/java/com/android/server/am/ProcessMemInfo.java b/services/core/java/com/android/server/am/ProcessMemInfo.java
index 83d29e2..6c10a2a 100644
--- a/services/core/java/com/android/server/am/ProcessMemInfo.java
+++ b/services/core/java/com/android/server/am/ProcessMemInfo.java
@@ -24,6 +24,7 @@
     final String adjType;
     final String adjReason;
     long pss;
+    long swapPss;
     long memtrack;
 
     public ProcessMemInfo(String _name, int _pid, int _oomAdj, int _procState,
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 5a44ab6..144f18b 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -20,6 +20,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
+import android.os.Debug;
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.EventLog;
@@ -43,6 +44,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.util.ArrayMap;
+import android.util.StatsLog;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
@@ -58,7 +60,6 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessRecord" : TAG_AM;
 
     private final ActivityManagerService mService; // where we came from
-    private final BatteryStatsImpl mBatteryStats; // where to collect runtime statistics
     final ApplicationInfo info; // all about the first app in the process
     final boolean isolated;     // true if this is a special isolated process
     final int uid;              // uid of process; may be different from 'info' if isolated
@@ -91,6 +92,10 @@
             return mPkgList.valueAt(index);
         }
 
+        ProcessStats.ProcessStateHolder get(String pkgName) {
+            return mPkgList.get(pkgName);
+        }
+
         boolean containsKey(Object key) {
             return mPkgList.containsKey(key);
         }
@@ -183,8 +188,9 @@
     int lruSeq;                 // Sequence id for identifying LRU update cycles
     CompatibilityInfo compat;   // last used compatibility mode
     IBinder.DeathRecipient deathRecipient; // Who is watching for the death.
-    ActiveInstrumentation instr;// Set to currently active instrumentation running in process
-    boolean usingWrapper;       // Set to true when process was launched with a wrapper attached
+    private ActiveInstrumentation mInstr; // Set to currently active instrumentation running in
+                                          // process.
+    private boolean mUsingWrapper; // Set to true when process was launched with a wrapper attached
     final ArraySet<BroadcastRecord> curReceivers = new ArraySet<BroadcastRecord>();// receivers currently running in the app
     long whenUnimportant;       // When (uptime) the process last became unimportant
     long lastCpuTime;           // How long proc has run CPU at last check
@@ -202,6 +208,11 @@
     Object adjTarget;           // Debugging: target component impacting oom_adj.
     Runnable crashHandler;      // Optional local handler to be invoked in the process crash.
 
+    // Cache of last retrieve memory info and uptime, to throttle how frequently
+    // apps can requyest it.
+    Debug.MemoryInfo lastMemInfo;
+    long lastMemInfoTime;
+
     // Controller for driving the process state on the window manager side.
     final private WindowProcessController mWindowProcessController;
     // all ServiceRecord running in this process
@@ -228,7 +239,7 @@
     private boolean mNotResponding; // does the app have a not responding dialog?
     Dialog anrDialog;           // dialog being displayed due to app not resp.
     boolean removed;            // has app package been removed from device?
-    boolean debugging;          // was app launched for debugging?
+    private boolean mDebugging; // was app launched for debugging?
     boolean waitedForDebugger;  // has process show wait for debugger dialog?
     Dialog waitDialog;          // current wait for debugger dialog
 
@@ -313,8 +324,8 @@
             pw.println("}");
         }
         pw.print(prefix); pw.print("compat="); pw.println(compat);
-        if (instr != null) {
-            pw.print(prefix); pw.print("instr="); pw.println(instr);
+        if (mInstr != null) {
+            pw.print(prefix); pw.print("mInstr="); pw.println(mInstr);
         }
         pw.print(prefix); pw.print("thread="); pw.println(thread);
         pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
@@ -431,9 +442,9 @@
                     pw.print(" killedByAm="); pw.print(killedByAm);
                     pw.print(" waitingToKill="); pw.println(waitingToKill);
         }
-        if (debugging || mCrashing || crashDialog != null || mNotResponding
+        if (mDebugging || mCrashing || crashDialog != null || mNotResponding
                 || anrDialog != null || bad) {
-            pw.print(prefix); pw.print("debugging="); pw.print(debugging);
+            pw.print(prefix); pw.print("mDebugging="); pw.print(mDebugging);
                     pw.print(" mCrashing="); pw.print(mCrashing);
                     pw.print(" "); pw.print(crashDialog);
                     pw.print(" mNotResponding="); pw.print(mNotResponding);
@@ -502,10 +513,9 @@
         }
     }
 
-    ProcessRecord(ActivityManagerService _service, BatteryStatsImpl _batteryStats,
-            ApplicationInfo _info, String _processName, int _uid) {
+    ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName,
+            int _uid) {
         mService = _service;
-        mBatteryStats = _batteryStats;
         info = _info;
         isolated = _info.uid != _uid;
         uid = _uid;
@@ -536,6 +546,12 @@
             if (origBase != null) {
                 origBase.setState(ProcessStats.STATE_NOTHING,
                         tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList);
+                for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                    StatsLog.write(StatsLog.PROCESS_STATE_CHANGED,
+                            uid, processName, pkgList.keyAt(ipkg),
+                            ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING),
+                            pkgList.valueAt(ipkg).appVersion);
+                }
                 origBase.makeInactive();
             }
             baseProcessTracker = tracker.getProcessStateLocked(info.packageName, uid,
@@ -546,7 +562,7 @@
                 if (holder.state != null && holder.state != origBase) {
                     holder.state.makeInactive();
                 }
-                holder.state = tracker.getProcessStateLocked(pkgList.keyAt(i), uid,
+                tracker.updateProcessStateHolderLocked(holder, pkgList.keyAt(i), uid,
                         info.longVersionCode, processName);
                 if (holder.state != baseProcessTracker) {
                     holder.state.makeActive();
@@ -565,6 +581,12 @@
             if (origBase != null) {
                 origBase.setState(ProcessStats.STATE_NOTHING,
                         tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList);
+                for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                    StatsLog.write(StatsLog.PROCESS_STATE_CHANGED,
+                            uid, processName, pkgList.keyAt(ipkg),
+                            ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING),
+                            pkgList.valueAt(ipkg).appVersion);
+                }
                 origBase.makeInactive();
             }
             baseProcessTracker = null;
@@ -573,6 +595,7 @@
                 if (holder.state != null && holder.state != origBase) {
                     holder.state.makeInactive();
                 }
+                holder.pkg = null;
                 holder.state = null;
             }
         }
@@ -801,8 +824,7 @@
             ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder(
                     versionCode);
             if (baseProcessTracker != null) {
-                holder.state = tracker.getProcessStateLocked(
-                        pkg, uid, versionCode, processName);
+                tracker.updateProcessStateHolderLocked(holder, pkg, uid, versionCode, processName);
                 pkgList.put(pkg, holder);
                 if (holder.state != baseProcessTracker) {
                     holder.state.makeActive();
@@ -827,6 +849,12 @@
     public void forceProcessStateUpTo(int newState) {
         if (mRepProcState > newState) {
             curProcState = mRepProcState = newState;
+            for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                StatsLog.write(StatsLog.PROCESS_STATE_CHANGED,
+                        uid, processName, pkgList.keyAt(ipkg),
+                        ActivityManager.processStateAmToProto(mRepProcState),
+                        pkgList.valueAt(ipkg).appVersion);
+            }
         }
     }
 
@@ -839,6 +867,12 @@
             long now = SystemClock.uptimeMillis();
             baseProcessTracker.setState(ProcessStats.STATE_NOTHING,
                     tracker.getMemFactorLocked(), now, pkgList.mPkgList);
+            for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) {
+                StatsLog.write(StatsLog.PROCESS_STATE_CHANGED,
+                        uid, processName, pkgList.keyAt(ipkg),
+                        ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING),
+                        pkgList.valueAt(ipkg).appVersion);
+            }
             if (N != 1) {
                 for (int i=0; i<N; i++) {
                     ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i);
@@ -848,14 +882,13 @@
 
                 }
                 pkgList.clear();
-                ProcessState ps = tracker.getProcessStateLocked(
-                        info.packageName, uid, info.longVersionCode, processName);
                 ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder(
                         info.longVersionCode);
-                holder.state = ps;
+                tracker.updateProcessStateHolderLocked(holder, info.packageName, uid,
+                        info.longVersionCode, processName);
                 pkgList.put(info.packageName, holder);
-                if (ps != baseProcessTracker) {
-                    ps.makeActive();
+                if (holder.state != baseProcessTracker) {
+                    holder.state.makeActive();
                 }
             }
         } else if (N != 1) {
@@ -891,6 +924,12 @@
 
     void setReportedProcState(int repProcState) {
         mRepProcState = repProcState;
+        for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) {
+            StatsLog.write(StatsLog.PROCESS_STATE_CHANGED,
+                    uid, processName, pkgList.keyAt(ipkg),
+                    ActivityManager.processStateAmToProto(mRepProcState),
+                    pkgList.valueAt(ipkg).appVersion);
+        }
         mWindowProcessController.setReportedProcState(repProcState);
     }
 
@@ -943,6 +982,33 @@
         return mHasForegroundServices;
     }
 
+    void setDebugging(boolean debugging) {
+        mDebugging = debugging;
+        mWindowProcessController.setDebugging(debugging);
+    }
+
+    boolean isDebugging() {
+        return mDebugging;
+    }
+
+    void setUsingWrapper(boolean usingWrapper) {
+        mUsingWrapper = usingWrapper;
+        mWindowProcessController.setUsingWrapper(usingWrapper);
+    }
+
+    boolean isUsingWrapper() {
+        return mUsingWrapper;
+    }
+
+    void setActiveInstrumentation(ActiveInstrumentation instr) {
+        mInstr = instr;
+        mWindowProcessController.setInstrumenting(instr != null);
+    }
+
+    ActiveInstrumentation getActiveInstrumentation() {
+        return mInstr;
+    }
+
     @Override
     public void clearProfilerIfNeeded() {
         synchronized (mService) {
@@ -999,4 +1065,11 @@
         }
     }
 
+    /**
+     * Returns the total time (in milliseconds) spent executing in both user and system code.
+     * Safe to call without lock held.
+     */
+    public long getCpuTime() {
+        return mService.mProcessCpuTracker.getCpuTimeForPid(pid);
+    }
 }
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index c10d81b..8ce650c 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -16,14 +16,12 @@
 
 package com.android.server.am;
 
-import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.service.procstats.ProcessStatsProto;
 import android.service.procstats.ProcessStatsServiceDumpProto;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
@@ -120,11 +118,20 @@
         }
     }
 
+    @GuardedBy("mAm")
+    public void updateProcessStateHolderLocked(ProcessStats.ProcessStateHolder holder,
+            String packageName, int uid, long versionCode, String processName) {
+        holder.pkg = mProcessStats.getPackageStateLocked(packageName, uid, versionCode);
+        holder.state = mProcessStats.getProcessStateLocked(holder.pkg, processName);
+    }
+
+    @GuardedBy("mAm")
     public ProcessState getProcessStateLocked(String packageName,
             int uid, long versionCode, String processName) {
         return mProcessStats.getProcessStateLocked(packageName, uid, versionCode, processName);
     }
 
+    @GuardedBy("mAm")
     public ServiceState getServiceStateLocked(String packageName, int uid,
             long versionCode, String processName, String className) {
         return mProcessStats.getServiceStateLocked(packageName, uid, versionCode, processName,
@@ -174,15 +181,23 @@
         return false;
     }
 
+    @GuardedBy("mAm")
     public int getMemFactorLocked() {
         return mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING ? mProcessStats.mMemFactor : 0;
     }
 
+    @GuardedBy("mAm")
     public void addSysMemUsageLocked(long cachedMem, long freeMem, long zramMem, long kernelMem,
             long nativeMem) {
         mProcessStats.addSysMemUsage(cachedMem, freeMem, zramMem, kernelMem, nativeMem);
     }
 
+    @GuardedBy("mAm")
+    public void updateTrackingAssociationsLocked(int curSeq, long now) {
+        mProcessStats.updateTrackingAssociationsLocked(curSeq, now);
+    }
+
+    @GuardedBy("mAm")
     public boolean shouldWriteNowLocked(long now) {
         if (now > (mLastWriteTime+WRITE_PERIOD)) {
             if (SystemClock.elapsedRealtime()
@@ -196,6 +211,7 @@
         return false;
     }
 
+    @GuardedBy("mAm")
     public void shutdownLocked() {
         Slog.w(TAG, "Writing process stats before shutdown...");
         mProcessStats.mFlags |= ProcessStats.FLAG_SHUTDOWN;
@@ -203,14 +219,17 @@
         mShuttingDown = true;
     }
 
+    @GuardedBy("mAm")
     public void writeStateAsyncLocked() {
         writeStateLocked(false);
     }
 
+    @GuardedBy("mAm")
     public void writeStateSyncLocked() {
         writeStateLocked(true);
     }
 
+    @GuardedBy("mAm")
     private void writeStateLocked(boolean sync) {
         if (mShuttingDown) {
             return;
@@ -220,6 +239,7 @@
         writeStateLocked(sync, commitPending);
     }
 
+    @GuardedBy("mAm")
     public void writeStateLocked(boolean sync, final boolean commit) {
         final long totalTime;
         synchronized (mPendingWriteLock) {
@@ -298,6 +318,7 @@
         }
     }
 
+    @GuardedBy("mAm")
     boolean readLocked(ProcessStats stats, AtomicFile file) {
         try {
             FileInputStream stream = file.openRead();
@@ -342,6 +363,13 @@
                                             + ": " + pkgState.mServices.valueAt(isvc));
 
                                 }
+                                final int NASCS = pkgState.mAssociations.size();
+                                for (int iasc=0; iasc<NASCS; iasc++) {
+                                    Slog.w(TAG, "      Association "
+                                            + pkgState.mServices.keyAt(iasc)
+                                            + ": " + pkgState.mAssociations.valueAt(iasc));
+
+                                }
                             }
                         }
                     }
@@ -383,6 +411,7 @@
         return filesArray;
     }
 
+    @GuardedBy("mAm")
     public void trimHistoricStatesWriteLocked() {
         ArrayList<String> filesArray = getCommittedFiles(MAX_HISTORIC_STATES, false, true);
         if (filesArray == null) {
@@ -395,6 +424,7 @@
         }
     }
 
+    @GuardedBy("mAm")
     boolean dumpFilteredProcessesCsvLocked(PrintWriter pw, String header,
             boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
             boolean sepProcStates, int[] procStates, long now, String reqPackage) {
@@ -582,7 +612,8 @@
             stats.dumpCheckinLocked(pw, reqPackage);
         } else {
             if (dumpDetails || dumpFullDetails) {
-                stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly);
+                stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails, dumpAll,
+                        activeOnly);
             } else {
                 stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
             }
@@ -944,8 +975,8 @@
                 if (checkedIn) pw.print(" (checked in)");
                 pw.println(":");
                 if (dumpDetails || dumpFullDetails) {
-                    processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
-                            activeOnly);
+                    processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails,
+                            dumpAll, activeOnly);
                     if (dumpAll) {
                         pw.print("  mFile="); pw.println(mFile.getBaseFile());
                     }
@@ -1000,7 +1031,7 @@
                                 // much crud.
                                 if (dumpFullDetails) {
                                     processStats.dumpLocked(pw, reqPackage, now, false, false,
-                                            activeOnly);
+                                            false, activeOnly);
                                 } else {
                                     processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
                                 }
@@ -1030,8 +1061,8 @@
                     }
                     pw.println("CURRENT STATS:");
                     if (dumpDetails || dumpFullDetails) {
-                        mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
-                                activeOnly);
+                        mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails,
+                                dumpAll, activeOnly);
                         if (dumpAll) {
                             pw.print("  mFile="); pw.println(mFile.getBaseFile());
                         }
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 749589b..e11e003 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -26,10 +26,12 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
+import static android.os.Process.SYSTEM_UID;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS_TRIM_TASKS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
@@ -78,6 +80,7 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
@@ -103,7 +106,6 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "RecentTasks" : TAG_AM;
     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
     private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
-    private static final boolean TRIMMED = true;
 
     private static final int DEFAULT_INITIAL_CAPACITY = 5;
 
@@ -131,7 +133,7 @@
         /**
          * Called when a task is removed from the recent tasks list.
          */
-        void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed);
+        void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed, boolean killProcess);
     }
 
     /**
@@ -140,7 +142,6 @@
     private final TaskPersister mTaskPersister;
     private final ActivityTaskManagerService mService;
     private final ActivityStackSupervisor mSupervisor;
-    private final UserController mUserController;
 
     /**
      * Keeps track of the static recents package/component which is granted additional permissions
@@ -181,11 +182,9 @@
     private final TaskActivitiesReport mTmpReport = new TaskActivitiesReport();
 
     @VisibleForTesting
-    RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister,
-            UserController userController) {
+    RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
         mService = service;
         mSupervisor = mService.mStackSupervisor;
-        mUserController = userController;
         mTaskPersister = taskPersister;
         mGlobalMaxNumTasks = ActivityTaskManager.getMaxRecentTasksStatic();
         mHasVisibleRecentTasks = true;
@@ -196,7 +195,6 @@
         final Resources res = service.mContext.getResources();
         mService = service;
         mSupervisor = mService.mStackSupervisor;
-        mUserController = service.mAm.mUserController;
         mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this);
         mGlobalMaxNumTasks = ActivityTaskManager.getMaxRecentTasksStatic();
         mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
@@ -289,7 +287,7 @@
      * @return whether the home app is also the active handler of recent tasks.
      */
     boolean isRecentsComponentHomeActivity(int userId) {
-        final ComponentName defaultHomeActivity = mService.mAm.getPackageManagerInternalLocked()
+        final ComponentName defaultHomeActivity = mService.getPackageManagerInternalLocked()
                 .getDefaultHomeActivity(userId);
         return defaultHomeActivity != null && mRecentsComponent != null &&
                 defaultHomeActivity.getPackageName().equals(mRecentsComponent.getPackageName());
@@ -323,9 +321,9 @@
         }
     }
 
-    private void notifyTaskRemoved(TaskRecord task, boolean wasTrimmed) {
+    private void notifyTaskRemoved(TaskRecord task, boolean wasTrimmed, boolean killProcess) {
         for (int i = 0; i < mCallbacks.size(); i++) {
-            mCallbacks.get(i).onRecentTaskRemoved(task, wasTrimmed);
+            mCallbacks.get(i).onRecentTaskRemoved(task, wasTrimmed, killProcess);
         }
     }
 
@@ -500,7 +498,7 @@
             if (tr.userId == userId) {
                 if(DEBUG_TASKS) Slog.i(TAG_TASKS,
                         "remove RecentTask " + tr + " when finishing user" + userId);
-                remove(mTasks.get(i));
+                remove(tr);
             }
         }
     }
@@ -548,6 +546,16 @@
         }
     }
 
+    void removeAllVisibleTasks() {
+        for (int i = mTasks.size() - 1; i >= 0; --i) {
+            final TaskRecord tr = mTasks.get(i);
+            if (isVisibleRecentTask(tr)) {
+                mTasks.remove(i);
+                notifyTaskRemoved(tr, true /* wasTrimmed */, true /* killProcess */);
+            }
+        }
+    }
+
     void cleanupDisabledPackageTasksLocked(String packageName, Set<String> filterByClasses,
             int userId) {
         for (int i = mTasks.size() - 1; i >= 0; --i) {
@@ -592,8 +600,7 @@
             }
             if (task.autoRemoveRecents && task.getTopActivity() == null) {
                 // This situation is broken, and we should just get rid of it now.
-                mTasks.remove(i);
-                notifyTaskRemoved(task, !TRIMMED);
+                remove(task);
                 Slog.w(TAG, "Removing auto-remove without activity: " + task);
                 continue;
             }
@@ -639,8 +646,7 @@
                     if (app == NO_APPLICATION_INFO_TOKEN
                             || (app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
                         // Doesn't exist any more! Good-bye.
-                        mTasks.remove(i);
-                        notifyTaskRemoved(task, !TRIMMED);
+                        remove(task);
                         Slog.w(TAG, "Removing no longer valid recent: " + task);
                         continue;
                     } else {
@@ -705,27 +711,57 @@
             if (intent == null || !callingPackage.equals(intent.getComponent().getPackageName())) {
                 continue;
             }
-            ActivityManager.RecentTaskInfo taskInfo = createRecentTaskInfo(tr);
-            AppTaskImpl taskImpl = new AppTaskImpl(mService, taskInfo.persistentId, callingUid);
+            AppTaskImpl taskImpl = new AppTaskImpl(mService, tr.taskId, callingUid);
             list.add(taskImpl.asBinder());
         }
         return list;
     }
 
+    @VisibleForTesting
+    Set<Integer> getProfileIds(int userId) {
+        Set<Integer> userIds = new ArraySet<>();
+        final List<UserInfo> profiles = mService.getUserManager().getProfiles(userId,
+                false /* enabledOnly */);
+        for (int i = profiles.size() - 1; i >= 0; --i) {
+            userIds.add(profiles.get(i).id);
+        }
+        return userIds;
+    }
+
+    @VisibleForTesting
+    UserInfo getUserInfo(int userId) {
+        return mService.getUserManager().getUserInfo(userId);
+    }
+
+    @VisibleForTesting
+    int[] getCurrentProfileIds() {
+        return mService.mAmInternal.getCurrentProfileIds();
+    }
+
     /**
      * @return the list of recent tasks for presentation.
      */
     ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags,
             boolean getTasksAllowed, boolean getDetailedTasks, int userId, int callingUid) {
+        return new ParceledListSlice<>(getRecentTasksImpl(maxNum, flags, getTasksAllowed,
+                getDetailedTasks, userId, callingUid));
+    }
+
+
+    /**
+     * @return the list of recent tasks for presentation.
+     */
+    ArrayList<ActivityManager.RecentTaskInfo> getRecentTasksImpl(int maxNum, int flags,
+            boolean getTasksAllowed, boolean getDetailedTasks, int userId, int callingUid) {
         final boolean withExcluded = (flags & RECENT_WITH_EXCLUDED) != 0;
 
         if (!mService.mAm.isUserRunning(userId, FLAG_AND_UNLOCKED)) {
             Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents");
-            return ParceledListSlice.emptyList();
+            return new ArrayList<>();
         }
         loadUserRecentsLocked(userId);
 
-        final Set<Integer> includedUsers = mUserController.getProfileIds(userId);
+        final Set<Integer> includedUsers = getProfileIds(userId);
         includedUsers.add(Integer.valueOf(userId));
 
         final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
@@ -772,7 +808,7 @@
             if (i == 0
                     || withExcluded
                     || (tr.intent == null)
-                    || ((tr.intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+                    || ((tr.intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
                     == 0)) {
                 if (!getTasksAllowed) {
                     // If the caller doesn't have the GET_TASKS permission, then only
@@ -809,7 +845,7 @@
                 res.add(rti);
             }
         }
-        return new ParceledListSlice<>(res);
+        return res;
     }
 
     /**
@@ -1021,7 +1057,7 @@
      */
     void remove(TaskRecord task) {
         mTasks.remove(task);
-        notifyTaskRemoved(task, !TRIMMED);
+        notifyTaskRemoved(task, false /* wasTrimmed */, false /* killProcess */);
     }
 
     /**
@@ -1033,17 +1069,17 @@
         // Remove from the end of the list until we reach the max number of recents
         while (recentsCount > mGlobalMaxNumTasks) {
             final TaskRecord tr = mTasks.remove(recentsCount - 1);
-            notifyTaskRemoved(tr, TRIMMED);
+            notifyTaskRemoved(tr, true /* wasTrimmed */, false /* killProcess */);
             recentsCount--;
             if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming over max-recents task=" + tr
                     + " max=" + mGlobalMaxNumTasks);
         }
 
         // Remove any tasks that belong to currently quiet profiles
-        final int[] profileUserIds = mUserController.getCurrentProfileIds();
+        final int[] profileUserIds = getCurrentProfileIds();
         mTmpQuietProfileUserIds.clear();
         for (int userId : profileUserIds) {
-            final UserInfo userInfo = mUserController.getUserInfo(userId);
+            final UserInfo userInfo = getUserInfo(userId);
             if (userInfo != null && userInfo.isManagedProfile() && userInfo.isQuietModeEnabled()) {
                 mTmpQuietProfileUserIds.put(userId, true);
             }
@@ -1087,7 +1123,7 @@
 
             // Task is no longer active, trim it from the list
             mTasks.remove(task);
-            notifyTaskRemoved(task, TRIMMED);
+            notifyTaskRemoved(task, true /* wasTrimmed */, false /* killProcess */);
             notifyTaskPersisterLocked(task, false /* flush */);
         }
     }
@@ -1141,9 +1177,8 @@
             case ACTIVITY_TYPE_ASSISTANT:
                 // Ignore assistant that chose to be excluded from Recents, even if it's a top
                 // task.
-                if ((task.getBaseIntent().getFlags()
-                        & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
-                        == Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) {
+                if ((task.getBaseIntent().getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+                        == FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) {
                     return false;
                 }
         }
@@ -1175,8 +1210,8 @@
     private boolean isInVisibleRange(TaskRecord task, int numVisibleTasks) {
         // Keep the last most task even if it is excluded from recents
         final boolean isExcludeFromRecents =
-                (task.getBaseIntent().getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
-                        == Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+                (task.getBaseIntent().getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+                        == FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
         if (isExcludeFromRecents) {
             if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\texcludeFromRecents=true");
             return numVisibleTasks == 1;
@@ -1242,7 +1277,7 @@
         // callbacks here.
         final TaskRecord removedTask = mTasks.remove(removeIndex);
         if (removedTask != task) {
-            notifyTaskRemoved(removedTask, !TRIMMED);
+            notifyTaskRemoved(removedTask, false /* wasTrimmed */, false /* killProcess */);
             if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming task=" + removedTask
                     + " for addition of task=" + task);
         }
@@ -1494,6 +1529,7 @@
             return;
         }
 
+        // Dump raw recent task list
         boolean printedAnything = false;
         boolean printedHeader = false;
         final int size = mTasks.size();
@@ -1516,6 +1552,30 @@
             }
         }
 
+        // Dump visible recent task list
+        if (mHasVisibleRecentTasks) {
+            // Reset the header flag for the next block
+            printedHeader = false;
+            ArrayList<ActivityManager.RecentTaskInfo> tasks = getRecentTasksImpl(Integer.MAX_VALUE,
+                    0, true /* getTasksAllowed */, false /* getDetailedTasks */,
+                    mService.getCurrentUserId(), SYSTEM_UID);
+            for (int i = 0; i < tasks.size(); i++) {
+                final ActivityManager.RecentTaskInfo taskInfo = tasks.get(i);
+                if (!printedHeader) {
+                    if (printedAnything) {
+                        // Separate from the last block if it printed
+                        pw.println();
+                    }
+                    pw.println("  Visible recent tasks (most recent first):");
+                    printedHeader = true;
+                    printedAnything = true;
+                }
+
+                pw.print("  * RecentTaskInfo #"); pw.print(i); pw.print(": ");
+                taskInfo.dump(pw, "    ");
+            }
+        }
+
         if (!printedAnything) {
             pw.println("  (nothing)");
         }
@@ -1525,33 +1585,11 @@
      * Creates a new RecentTaskInfo from a TaskRecord.
      */
     ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
-        // Compose the recent task info
         ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
-        rti.id = tr.getTopActivity() == null ? INVALID_TASK_ID : tr.taskId;
-        rti.persistentId = tr.taskId;
-        rti.baseIntent = new Intent(tr.getBaseIntent());
-        rti.origActivity = tr.origActivity;
-        rti.realActivity = tr.realActivity;
-        rti.description = tr.lastDescription;
-        rti.stackId = tr.getStackId();
-        rti.userId = tr.userId;
-        rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
-        rti.lastActiveTime = tr.lastActiveTime;
-        rti.affiliatedTaskId = tr.mAffiliatedTaskId;
-        rti.affiliatedTaskColor = tr.mAffiliatedTaskColor;
-        rti.numActivities = 0;
-        if (!tr.matchParentBounds()) {
-            rti.bounds = new Rect(tr.getOverrideBounds());
-        }
-        rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode();
-        rti.resizeMode = tr.mResizeMode;
-        rti.configuration.setTo(tr.getConfiguration());
-
-        tr.getNumRunningActivities(mTmpReport);
-        rti.numActivities = mTmpReport.numActivities;
-        rti.baseActivity = (mTmpReport.base != null) ? mTmpReport.base.intent.getComponent() : null;
-        rti.topActivity = (mTmpReport.top != null) ? mTmpReport.top.intent.getComponent() : null;
-
+        tr.fillTaskInfo(rti, mTmpReport);
+        // Fill in some deprecated values
+        rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
+        rti.persistentId = rti.taskId;
         return rti;
     }
 
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index 1c7ad3f..c5586bb 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -287,7 +287,7 @@
 
                     mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, false);
-                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                    mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
 
                     // No reason to wait for the pausing activity in this case, as the hiding of
                     // surfaces needs to be done immediately.
diff --git a/services/core/java/com/android/server/am/RunningTasks.java b/services/core/java/com/android/server/am/RunningTasks.java
index c860df8..7008cee 100644
--- a/services/core/java/com/android/server/am/RunningTasks.java
+++ b/services/core/java/com/android/server/am/RunningTasks.java
@@ -54,17 +54,15 @@
 
         // Gather all of the tasks across all of the tasks, and add them to the sorted set
         mTmpSortedSet.clear();
-        mTmpStackTasks.clear();
         final int numDisplays = activityDisplays.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
             final ActivityDisplay display = activityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
+                mTmpStackTasks.clear();
                 stack.getRunningTasks(mTmpStackTasks, ignoreActivityType, ignoreWindowingMode,
                         callingUid, allowed);
-                for (int i = mTmpStackTasks.size() - 1; i >= 0; i--) {
-                    mTmpSortedSet.addAll(mTmpStackTasks);
-                }
+                mTmpSortedSet.addAll(mTmpStackTasks);
             }
         }
 
@@ -85,20 +83,10 @@
      * Constructs a {@link RunningTaskInfo} from a given {@param task}.
      */
     private RunningTaskInfo createRunningTaskInfo(TaskRecord task) {
-        task.getNumRunningActivities(mTmpReport);
-
-        final RunningTaskInfo ci = new RunningTaskInfo();
-        ci.id = task.taskId;
-        ci.stackId = task.getStackId();
-        ci.baseActivity = mTmpReport.base.intent.getComponent();
-        ci.topActivity = mTmpReport.top.intent.getComponent();
-        ci.lastActiveTime = task.lastActiveTime;
-        ci.description = task.lastDescription;
-        ci.numActivities = mTmpReport.numActivities;
-        ci.numRunning = mTmpReport.numRunning;
-        ci.supportsSplitScreenMultiWindow = task.supportsSplitScreenWindowingMode();
-        ci.resizeMode = task.mResizeMode;
-        ci.configuration.setTo(task.getConfiguration());
-        return ci;
+        final RunningTaskInfo rti = new RunningTaskInfo();
+        task.fillTaskInfo(rti, mTmpReport);
+        // Fill in some deprecated values
+        rti.id = rti.taskId;
+        return rti;
     }
 }
diff --git a/services/core/java/com/android/server/am/SafeActivityOptions.java b/services/core/java/com/android/server/am/SafeActivityOptions.java
index fef3b86..f7de7f4 100644
--- a/services/core/java/com/android/server/am/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/am/SafeActivityOptions.java
@@ -230,7 +230,7 @@
 
         // Check permission for remote animations
         final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter();
-        if (adapter != null && supervisor.mService.mAm.checkPermission(
+        if (adapter != null && supervisor.mService.checkPermission(
                 CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, callingPid, callingUid)
                         != PERMISSION_GRANTED) {
             final String msg = "Permission Denial: starting " + getIntentString(intent)
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 4d89d015..d8f94c9 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -44,6 +44,8 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
+import com.android.server.uri.NeededUriGrants;
+import com.android.server.uri.UriPermissionOwner;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -129,7 +131,7 @@
         final int id;
         final int callingId;
         final Intent intent;
-        final ActivityManagerService.NeededUriGrants neededGrants;
+        final NeededUriGrants neededGrants;
         long deliveredTime;
         int deliveryCount;
         int doneExecutingCount;
@@ -138,7 +140,7 @@
         String stringName;      // caching of toString
 
         StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent,
-                ActivityManagerService.NeededUriGrants _neededGrants, int _callingId) {
+                NeededUriGrants _neededGrants, int _callingId) {
             sr = _sr;
             taskRemoved = _taskRemoved;
             id = _id;
@@ -149,14 +151,14 @@
 
         UriPermissionOwner getUriPermissionsLocked() {
             if (uriPermissions == null) {
-                uriPermissions = new UriPermissionOwner(sr.ams, this);
+                uriPermissions = new UriPermissionOwner(sr.ams.mUgmInternal, this);
             }
             return uriPermissions;
         }
 
         void removeUriPermissionsLocked() {
             if (uriPermissions != null) {
-                uriPermissions.removeUriPermissionsLocked();
+                uriPermissions.removeUriPermissions();
                 uriPermissions = null;
             }
         }
@@ -500,6 +502,23 @@
         restartTracker.setRestarting(true, memFactor, now);
     }
 
+    public void setProcess(ProcessRecord _proc) {
+        app = _proc;
+        if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS) {
+            for (int conni = connections.size() - 1; conni >= 0; conni--) {
+                ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
+                for (int i = 0; i < cr.size(); i++) {
+                    final ConnectionRecord conn = cr.get(i);
+                    if (_proc != null) {
+                        conn.startAssociationIfNeeded();
+                    } else {
+                        conn.stopAssociation();
+                    }
+                }
+            }
+        }
+    }
+
     public AppBindRecord retrieveAppBindingLocked(Intent intent,
             ProcessRecord app) {
         Intent.FilterComparison filter = new Intent.FilterComparison(intent);
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
new file mode 100644
index 0000000..4ca96a1
--- /dev/null
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -0,0 +1,70 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsActivityManagerDeviceTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsActivityManagerDeviceSdk25TestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsAppTestCases",
+      "options": [
+        {
+          "include-filter": "android.app.cts.TaskDescriptionTest"
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.am."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsActivityManagerDeviceTestCases"
+    },
+    {
+      "name": "CtsActivityManagerDeviceSdk25TestCases"
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.am."
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 05869bb..7256e23 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -16,9 +16,9 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -63,6 +63,7 @@
 import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.TaskRecordProto.ACTIVITIES;
+import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
 import static com.android.server.am.TaskRecordProto.BOUNDS;
 import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER;
 import static com.android.server.am.TaskRecordProto.FULLSCREEN;
@@ -74,7 +75,6 @@
 import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
 import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
 import static com.android.server.am.TaskRecordProto.STACK_ID;
-import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
 
 import static java.lang.Integer.MAX_VALUE;
 
@@ -87,7 +87,7 @@
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.AppGlobals;
-import android.app.IActivityManager;
+import android.app.TaskInfo;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -477,7 +477,7 @@
         mResizeMode = resizeMode;
         mWindowContainerController.setResizeable(resizeMode);
         mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
-        mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+        mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
     }
 
     void setTaskDockedResizing(boolean resizing) {
@@ -551,7 +551,7 @@
                     mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0,
                             preserveWindow);
                     if (!kept) {
-                        mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                        mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                     }
                 }
             }
@@ -657,7 +657,7 @@
         boolean kept = true;
         try {
             final ActivityRecord r = topRunningActivityLocked();
-            final boolean wasFocused = r != null && supervisor.isFocusedStack(sourceStack)
+            final boolean wasFocused = r != null && supervisor.isTopDisplayFocusedStack(sourceStack)
                     && (topRunningActivityLocked() == r);
             final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
             final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
@@ -751,7 +751,7 @@
             // The task might have already been running and its visibility needs to be synchronized
             // with the visibility of the stack / windows.
             supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
-            supervisor.resumeFocusedStackTopActivityLocked();
+            supervisor.resumeFocusedStacksTopActivitiesLocked();
         }
 
         // TODO: Handle incorrect request to move before the actual move, not after.
@@ -1747,6 +1747,14 @@
         return updateOverrideConfiguration(bounds, null /* insetBounds */);
     }
 
+    void setLastNonFullscreenBounds(Rect bounds) {
+        if (mLastNonFullscreenBounds == null) {
+            mLastNonFullscreenBounds = new Rect(bounds);
+        } else {
+            mLastNonFullscreenBounds.set(bounds);
+        }
+    }
+
     /**
      * Update task's override configuration based on the bounds.
      * @param bounds The bounds of the task.
@@ -1768,7 +1776,7 @@
         final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
         if (matchParentBounds) {
             if (!currentBounds.isEmpty() && persistBounds) {
-                mLastNonFullscreenBounds = currentBounds;
+                setLastNonFullscreenBounds(currentBounds);
             }
             setBounds(null);
             newConfig.unset();
@@ -1778,7 +1786,7 @@
             setBounds(mTmpRect);
 
             if (mStack == null || persistBounds) {
-                mLastNonFullscreenBounds = getOverrideBounds();
+                setLastNonFullscreenBounds(getOverrideBounds());
             }
             computeOverrideConfiguration(newConfig, mTmpRect, insetBounds,
                     mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
@@ -1939,6 +1947,35 @@
         }
     }
 
+    /**
+     * Fills in a {@link TaskInfo} with information from this task.
+     * @param info the {@link TaskInfo} to fill in
+     * @param reuseActivitiesReport a temporary activities report that we can reuse to fetch the
+     *                              running activities
+     */
+    void fillTaskInfo(TaskInfo info, TaskActivitiesReport reuseActivitiesReport) {
+        getNumRunningActivities(reuseActivitiesReport);
+        info.userId = userId;
+        info.stackId = getStackId();
+        info.taskId = taskId;
+        info.isRunning = getTopActivity() != null;
+        info.baseIntent = getBaseIntent();
+        info.baseActivity = reuseActivitiesReport.base != null
+                ? reuseActivitiesReport.base.intent.getComponent()
+                : null;
+        info.topActivity = reuseActivitiesReport.top != null
+                ? reuseActivitiesReport.top.intent.getComponent()
+                : null;
+        info.origActivity = origActivity;
+        info.realActivity = realActivity;
+        info.numActivities = reuseActivitiesReport.numActivities;
+        info.lastActiveTime = lastActiveTime;
+        info.taskDescription = new ActivityManager.TaskDescription(lastTaskDescription);
+        info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
+        info.resizeMode = mResizeMode;
+        info.configuration.setTo(getConfiguration());
+    }
+
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("userId="); pw.print(userId);
                 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
diff --git a/services/core/java/com/android/server/am/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java
deleted file mode 100644
index 1e071aa..0000000
--- a/services/core/java/com/android/server/am/UriPermission.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package com.android.server.am;
-
-import android.app.GrantedUriPermission;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.server.am.ActivityManagerService.GrantUri;
-import com.google.android.collect.Sets;
-
-import java.io.PrintWriter;
-import java.util.Comparator;
-
-/**
- * Description of a permission granted to an app to access a particular URI.
- *
- * CTS tests for this functionality can be run with "runtest cts-appsecurity".
- *
- * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
- *      src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
- */
-final class UriPermission {
-    private static final String TAG = "UriPermission";
-
-    public static final int STRENGTH_NONE = 0;
-    public static final int STRENGTH_OWNED = 1;
-    public static final int STRENGTH_GLOBAL = 2;
-    public static final int STRENGTH_PERSISTABLE = 3;
-
-    final int targetUserId;
-    final String sourcePkg;
-    final String targetPkg;
-
-    /** Cached UID of {@link #targetPkg}; should not be persisted */
-    final int targetUid;
-
-    final GrantUri uri;
-
-    /**
-     * Allowed modes. All permission enforcement should use this field. Must
-     * always be a combination of {@link #ownedModeFlags},
-     * {@link #globalModeFlags}, {@link #persistableModeFlags}, and
-     * {@link #persistedModeFlags}. Mutations <em>must</em> only be performed by
-     * the owning class.
-     */
-    int modeFlags = 0;
-
-    /** Allowed modes with active owner. */
-    int ownedModeFlags = 0;
-    /** Allowed modes without explicit owner. */
-    int globalModeFlags = 0;
-    /** Allowed modes that have been offered for possible persisting. */
-    int persistableModeFlags = 0;
-
-    /** Allowed modes that should be persisted across device boots. */
-    int persistedModeFlags = 0;
-
-    /**
-     * Timestamp when {@link #persistedModeFlags} was first defined in
-     * {@link System#currentTimeMillis()} time base.
-     */
-    long persistedCreateTime = INVALID_TIME;
-
-    private static final long INVALID_TIME = Long.MIN_VALUE;
-
-    private ArraySet<UriPermissionOwner> mReadOwners;
-    private ArraySet<UriPermissionOwner> mWriteOwners;
-
-    private String stringName;
-
-    UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) {
-        this.targetUserId = UserHandle.getUserId(targetUid);
-        this.sourcePkg = sourcePkg;
-        this.targetPkg = targetPkg;
-        this.targetUid = targetUid;
-        this.uri = uri;
-    }
-
-    private void updateModeFlags() {
-        final int oldModeFlags = modeFlags;
-        modeFlags = ownedModeFlags | globalModeFlags | persistableModeFlags | persistedModeFlags;
-
-        if (Log.isLoggable(TAG, Log.VERBOSE) && (modeFlags != oldModeFlags)) {
-            Slog.d(TAG,
-                    "Permission for " + targetPkg + " to " + uri + " is changing from 0x"
-                            + Integer.toHexString(oldModeFlags) + " to 0x"
-                            + Integer.toHexString(modeFlags) + " via calling UID "
-                            + Binder.getCallingUid() + " PID " + Binder.getCallingPid(),
-                    new Throwable());
-        }
-    }
-
-    /**
-     * Initialize persisted modes as read from file. This doesn't issue any
-     * global or owner grants.
-     */
-    void initPersistedModes(int modeFlags, long createdTime) {
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
-        persistableModeFlags = modeFlags;
-        persistedModeFlags = modeFlags;
-        persistedCreateTime = createdTime;
-
-        updateModeFlags();
-    }
-
-    void grantModes(int modeFlags, UriPermissionOwner owner) {
-        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
-        if (persistable) {
-            persistableModeFlags |= modeFlags;
-        }
-
-        if (owner == null) {
-            globalModeFlags |= modeFlags;
-        } else {
-            if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
-                addReadOwner(owner);
-            }
-            if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
-                addWriteOwner(owner);
-            }
-        }
-
-        updateModeFlags();
-    }
-
-    /**
-     * @return if mode changes should trigger persisting.
-     */
-    boolean takePersistableModes(int modeFlags) {
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
-        if ((modeFlags & persistableModeFlags) != modeFlags) {
-            Slog.w(TAG, "Requested flags 0x"
-                    + Integer.toHexString(modeFlags) + ", but only 0x"
-                    + Integer.toHexString(persistableModeFlags) + " are allowed");
-            return false;
-        }
-
-        final int before = persistedModeFlags;
-        persistedModeFlags |= (persistableModeFlags & modeFlags);
-
-        if (persistedModeFlags != 0) {
-            persistedCreateTime = System.currentTimeMillis();
-        }
-
-        updateModeFlags();
-        return persistedModeFlags != before;
-    }
-
-    boolean releasePersistableModes(int modeFlags) {
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
-        final int before = persistedModeFlags;
-
-        persistableModeFlags &= ~modeFlags;
-        persistedModeFlags &= ~modeFlags;
-
-        if (persistedModeFlags == 0) {
-            persistedCreateTime = INVALID_TIME;
-        }
-
-        updateModeFlags();
-        return persistedModeFlags != before;
-    }
-
-    /**
-     * @return if mode changes should trigger persisting.
-     */
-    boolean revokeModes(int modeFlags, boolean includingOwners) {
-        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
-        final int before = persistedModeFlags;
-
-        if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
-            if (persistable) {
-                persistableModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
-                persistedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
-            }
-            globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
-            if (mReadOwners != null && includingOwners) {
-                ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
-                for (UriPermissionOwner r : mReadOwners) {
-                    r.removeReadPermission(this);
-                }
-                mReadOwners = null;
-            }
-        }
-        if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
-            if (persistable) {
-                persistableModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
-                persistedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
-            }
-            globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
-            if (mWriteOwners != null && includingOwners) {
-                ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
-                for (UriPermissionOwner r : mWriteOwners) {
-                    r.removeWritePermission(this);
-                }
-                mWriteOwners = null;
-            }
-        }
-
-        if (persistedModeFlags == 0) {
-            persistedCreateTime = INVALID_TIME;
-        }
-
-        updateModeFlags();
-        return persistedModeFlags != before;
-    }
-
-    /**
-     * Return strength of this permission grant for the given flags.
-     */
-    public int getStrength(int modeFlags) {
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-        if ((persistableModeFlags & modeFlags) == modeFlags) {
-            return STRENGTH_PERSISTABLE;
-        } else if ((globalModeFlags & modeFlags) == modeFlags) {
-            return STRENGTH_GLOBAL;
-        } else if ((ownedModeFlags & modeFlags) == modeFlags) {
-            return STRENGTH_OWNED;
-        } else {
-            return STRENGTH_NONE;
-        }
-    }
-
-    private void addReadOwner(UriPermissionOwner owner) {
-        if (mReadOwners == null) {
-            mReadOwners = Sets.newArraySet();
-            ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
-            updateModeFlags();
-        }
-        if (mReadOwners.add(owner)) {
-            owner.addReadPermission(this);
-        }
-    }
-
-    /**
-     * Remove given read owner, updating {@Link #modeFlags} as needed.
-     */
-    void removeReadOwner(UriPermissionOwner owner) {
-        if (!mReadOwners.remove(owner)) {
-            Slog.wtf(TAG, "Unknown read owner " + owner + " in " + this);
-        }
-        if (mReadOwners.size() == 0) {
-            mReadOwners = null;
-            ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
-            updateModeFlags();
-        }
-    }
-
-    private void addWriteOwner(UriPermissionOwner owner) {
-        if (mWriteOwners == null) {
-            mWriteOwners = Sets.newArraySet();
-            ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
-            updateModeFlags();
-        }
-        if (mWriteOwners.add(owner)) {
-            owner.addWritePermission(this);
-        }
-    }
-
-    /**
-     * Remove given write owner, updating {@Link #modeFlags} as needed.
-     */
-    void removeWriteOwner(UriPermissionOwner owner) {
-        if (!mWriteOwners.remove(owner)) {
-            Slog.wtf(TAG, "Unknown write owner " + owner + " in " + this);
-        }
-        if (mWriteOwners.size() == 0) {
-            mWriteOwners = null;
-            ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
-            updateModeFlags();
-        }
-    }
-
-    @Override
-    public String toString() {
-        if (stringName != null) {
-            return stringName;
-        }
-        StringBuilder sb = new StringBuilder(128);
-        sb.append("UriPermission{");
-        sb.append(Integer.toHexString(System.identityHashCode(this)));
-        sb.append(' ');
-        sb.append(uri);
-        sb.append('}');
-        return stringName = sb.toString();
-    }
-
-    void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix);
-        pw.print("targetUserId=" + targetUserId);
-        pw.print(" sourcePkg=" + sourcePkg);
-        pw.println(" targetPkg=" + targetPkg);
-
-        pw.print(prefix);
-        pw.print("mode=0x" + Integer.toHexString(modeFlags));
-        pw.print(" owned=0x" + Integer.toHexString(ownedModeFlags));
-        pw.print(" global=0x" + Integer.toHexString(globalModeFlags));
-        pw.print(" persistable=0x" + Integer.toHexString(persistableModeFlags));
-        pw.print(" persisted=0x" + Integer.toHexString(persistedModeFlags));
-        if (persistedCreateTime != INVALID_TIME) {
-            pw.print(" persistedCreate=" + persistedCreateTime);
-        }
-        pw.println();
-
-        if (mReadOwners != null) {
-            pw.print(prefix);
-            pw.println("readOwners:");
-            for (UriPermissionOwner owner : mReadOwners) {
-                pw.print(prefix);
-                pw.println("  * " + owner);
-            }
-        }
-        if (mWriteOwners != null) {
-            pw.print(prefix);
-            pw.println("writeOwners:");
-            for (UriPermissionOwner owner : mReadOwners) {
-                pw.print(prefix);
-                pw.println("  * " + owner);
-            }
-        }
-    }
-
-    public static class PersistedTimeComparator implements Comparator<UriPermission> {
-        @Override
-        public int compare(UriPermission lhs, UriPermission rhs) {
-            return Long.compare(lhs.persistedCreateTime, rhs.persistedCreateTime);
-        }
-    }
-
-    /**
-     * Snapshot of {@link UriPermission} with frozen
-     * {@link UriPermission#persistedModeFlags} state.
-     */
-    public static class Snapshot {
-        final int targetUserId;
-        final String sourcePkg;
-        final String targetPkg;
-        final GrantUri uri;
-        final int persistedModeFlags;
-        final long persistedCreateTime;
-
-        private Snapshot(UriPermission perm) {
-            this.targetUserId = perm.targetUserId;
-            this.sourcePkg = perm.sourcePkg;
-            this.targetPkg = perm.targetPkg;
-            this.uri = perm.uri;
-            this.persistedModeFlags = perm.persistedModeFlags;
-            this.persistedCreateTime = perm.persistedCreateTime;
-        }
-    }
-
-    public Snapshot snapshot() {
-        return new Snapshot(this);
-    }
-
-    public android.content.UriPermission buildPersistedPublicApiObject() {
-        return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime);
-    }
-
-    public GrantedUriPermission buildGrantedUriPermission() {
-        return new GrantedUriPermission(uri.uri, targetPkg);
-    }
-}
diff --git a/services/core/java/com/android/server/am/UriPermissionOwner.java b/services/core/java/com/android/server/am/UriPermissionOwner.java
deleted file mode 100644
index 8eda38e..0000000
--- a/services/core/java/com/android/server/am/UriPermissionOwner.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.am;
-
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-import android.util.ArraySet;
-import android.util.proto.ProtoOutputStream;
-
-import com.google.android.collect.Sets;
-
-import java.io.PrintWriter;
-import java.util.Iterator;
-
-final class UriPermissionOwner {
-    final ActivityManagerService service;
-    final Object owner;
-
-    Binder externalToken;
-
-    private ArraySet<UriPermission> mReadPerms;
-    private ArraySet<UriPermission> mWritePerms;
-
-    class ExternalToken extends Binder {
-        UriPermissionOwner getOwner() {
-            return UriPermissionOwner.this;
-        }
-    }
-
-    UriPermissionOwner(ActivityManagerService service, Object owner) {
-        this.service = service;
-        this.owner = owner;
-    }
-
-    Binder getExternalTokenLocked() {
-        if (externalToken == null) {
-            externalToken = new ExternalToken();
-        }
-        return externalToken;
-    }
-
-    static UriPermissionOwner fromExternalToken(IBinder token) {
-        if (token instanceof ExternalToken) {
-            return ((ExternalToken)token).getOwner();
-        }
-        return null;
-    }
-
-    void removeUriPermissionsLocked() {
-        removeUriPermissionsLocked(Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-    }
-
-    void removeUriPermissionsLocked(int mode) {
-        removeUriPermissionLocked(null, mode);
-    }
-
-    void removeUriPermissionLocked(ActivityManagerService.GrantUri grantUri, int mode) {
-        if ((mode & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
-                && mReadPerms != null) {
-            Iterator<UriPermission> it = mReadPerms.iterator();
-            while (it.hasNext()) {
-                UriPermission perm = it.next();
-                if (grantUri == null || grantUri.equals(perm.uri)) {
-                    perm.removeReadOwner(this);
-                    service.removeUriPermissionIfNeededLocked(perm);
-                    it.remove();
-                }
-            }
-            if (mReadPerms.isEmpty()) {
-                mReadPerms = null;
-            }
-        }
-        if ((mode & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
-                && mWritePerms != null) {
-            Iterator<UriPermission> it = mWritePerms.iterator();
-            while (it.hasNext()) {
-                UriPermission perm = it.next();
-                if (grantUri == null || grantUri.equals(perm.uri)) {
-                    perm.removeWriteOwner(this);
-                    service.removeUriPermissionIfNeededLocked(perm);
-                    it.remove();
-                }
-            }
-            if (mWritePerms.isEmpty()) {
-                mWritePerms = null;
-            }
-        }
-    }
-
-    public void addReadPermission(UriPermission perm) {
-        if (mReadPerms == null) {
-            mReadPerms = Sets.newArraySet();
-        }
-        mReadPerms.add(perm);
-    }
-
-    public void addWritePermission(UriPermission perm) {
-        if (mWritePerms == null) {
-            mWritePerms = Sets.newArraySet();
-        }
-        mWritePerms.add(perm);
-    }
-
-    public void removeReadPermission(UriPermission perm) {
-        mReadPerms.remove(perm);
-        if (mReadPerms.isEmpty()) {
-            mReadPerms = null;
-        }
-    }
-
-    public void removeWritePermission(UriPermission perm) {
-        mWritePerms.remove(perm);
-        if (mWritePerms.isEmpty()) {
-            mWritePerms = null;
-        }
-    }
-
-    public void dump(PrintWriter pw, String prefix) {
-        if (mReadPerms != null) {
-            pw.print(prefix); pw.print("readUriPermissions="); pw.println(mReadPerms);
-        }
-        if (mWritePerms != null) {
-            pw.print(prefix); pw.print("writeUriPermissions="); pw.println(mWritePerms);
-        }
-    }
-
-    public void writeToProto(ProtoOutputStream proto, long fieldId) {
-        long token = proto.start(fieldId);
-        proto.write(UriPermissionOwnerProto.OWNER, owner.toString());
-        if (mReadPerms != null) {
-            synchronized (mReadPerms) {
-                for (UriPermission p : mReadPerms) {
-                    p.uri.writeToProto(proto, UriPermissionOwnerProto.READ_PERMS);
-                }
-            }
-        }
-        if (mWritePerms != null) {
-            synchronized (mWritePerms) {
-                for (UriPermission p : mWritePerms) {
-                    p.uri.writeToProto(proto, UriPermissionOwnerProto.WRITE_PERMS);
-                }
-            }
-        }
-        proto.end(token);
-    }
-
-    @Override
-    public String toString() {
-        return owner.toString();
-    }
-}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 992179a..bd412fc 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -24,7 +24,6 @@
 import static android.app.ActivityManager.USER_OP_SUCCESS;
 import static android.os.Process.SHELL_UID;
 import static android.os.Process.SYSTEM_UID;
-
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -49,6 +48,7 @@
 import android.app.IUserSwitchObserver;
 import android.app.KeyguardManager;
 import android.app.usage.UsageEvents;
+import android.appwidget.AppWidgetManagerInternal;
 import android.content.Context;
 import android.content.IIntentReceiver;
 import android.content.Intent;
@@ -104,11 +104,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
-import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -259,13 +257,17 @@
     }
 
     void finishUserSwitch(UserState uss) {
-        finishUserBoot(uss);
-        startProfiles();
-        synchronized (mLock) {
-            stopRunningUsersLU(mMaxRunningUsers);
-        }
+        // This call holds the AM lock so we post to the handler.
+        mHandler.post(() -> {
+            finishUserBoot(uss);
+            startProfiles();
+            synchronized (mLock) {
+                stopRunningUsersLU(mMaxRunningUsers);
+            }
+        });
     }
 
+    @GuardedBy("mLock")
     List<Integer> getRunningUsersLU() {
         ArrayList<Integer> runningUsers = new ArrayList<>();
         for (Integer userId : mUserLru) {
@@ -290,6 +292,7 @@
         return runningUsers;
     }
 
+    @GuardedBy("mLock")
     void stopRunningUsersLU(int maxRunningUsers) {
         List<Integer> currentlyRunning = getRunningUsersLU();
         Iterator<Integer> iterator = currentlyRunning.iterator();
@@ -532,6 +535,9 @@
             }
         }
 
+        // Spin up app widgets prior to boot-complete, so they can be ready promptly
+        mInjector.startUserWidgets(userId);
+
         Slog.i(TAG, "Sending BOOT_COMPLETE user #" + userId);
         // Do not report secondary users, runtime restarts or first boot/upgrade
         if (userId == UserHandle.USER_SYSTEM
@@ -592,6 +598,7 @@
      * Stops the user along with its related users. The method calls
      * {@link #getUsersToStopLU(int)} to determine the list of users that should be stopped.
      */
+    @GuardedBy("mLock")
     private int stopUsersLU(final int userId, boolean force, final IStopUserCallback callback) {
         if (userId == UserHandle.USER_SYSTEM) {
             return USER_OP_ERROR_IS_SYSTEM;
@@ -623,6 +630,7 @@
         return USER_OP_SUCCESS;
     }
 
+    @GuardedBy("mLock")
     private void stopSingleUserLU(final int userId, final IStopUserCallback callback) {
         if (DEBUG_MU) Slog.i(TAG, "stopSingleUserLocked userId=" + userId);
         final UserState uss = mStartedUsers.get(userId);
@@ -780,6 +788,7 @@
      * Determines the list of users that should be stopped together with the specified
      * {@code userId}. The returned list includes {@code userId}.
      */
+    @GuardedBy("mLock")
     private @NonNull int[] getUsersToStopLU(int userId) {
         int startedUsersSize = mStartedUsers.size();
         IntArray userIds = new IntArray();
@@ -1365,6 +1374,7 @@
         mUserSwitchObservers.finishBroadcast();
     }
 
+    @GuardedBy("mLock")
     void sendContinueUserSwitchLU(UserState uss, int oldUserId, int newUserId) {
         mCurWaitingUserSwitchCallbacks = null;
         mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
@@ -1573,9 +1583,12 @@
     }
 
     boolean hasStartedUserState(int userId) {
-        return mStartedUsers.get(userId) != null;
+        synchronized (mLock) {
+            return mStartedUsers.get(userId) != null;
+        }
     }
 
+    @GuardedBy("mLock")
     private void updateStartedUserArrayLU() {
         int num = 0;
         for (int i = 0; i < mStartedUsers.size(); i++) {
@@ -1714,6 +1727,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     UserInfo getCurrentUserLU() {
         int userId = mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId;
         return getUserInfo(userId);
@@ -1725,11 +1739,13 @@
         }
     }
 
+    @GuardedBy("mLock")
     int getCurrentOrTargetUserIdLU() {
         return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId;
     }
 
 
+    @GuardedBy("mLock")
     int getCurrentUserIdLU() {
         return mCurrentUserId;
     }
@@ -1740,6 +1756,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private boolean isCurrentUserLU(int userId) {
         return userId == getCurrentOrTargetUserIdLU();
     }
@@ -1749,7 +1766,7 @@
         return ums != null ? ums.getUserIds() : new int[] { 0 };
     }
 
-    UserInfo getUserInfo(int userId) {
+    private UserInfo getUserInfo(int userId) {
         return mInjector.getUserManager().getUserInfo(userId);
     }
 
@@ -1775,7 +1792,7 @@
         return mInjector.getUserManager().exists(userId);
     }
 
-    void enforceShellRestriction(String restriction, int userHandle) {
+    private void enforceShellRestriction(String restriction, int userHandle) {
         if (Binder.getCallingUid() == SHELL_UID) {
             if (userHandle < 0 || hasUserRestriction(restriction, userHandle)) {
                 throw new SecurityException("Shell does not have permission to access user "
@@ -1788,16 +1805,6 @@
         return mInjector.getUserManager().hasUserRestriction(restriction, userId);
     }
 
-    Set<Integer> getProfileIds(int userId) {
-        Set<Integer> userIds = new HashSet<>();
-        final List<UserInfo> profiles = mInjector.getUserManager().getProfiles(userId,
-                false /* enabledOnly */);
-        for (UserInfo user : profiles) {
-            userIds.add(user.id);
-        }
-        return userIds;
-    }
-
     boolean isSameProfileGroup(int callingUserId, int targetUserId) {
         if (callingUserId == targetUserId) {
             return true;
@@ -2170,6 +2177,13 @@
             }
         }
 
+        void startUserWidgets(int userId) {
+            AppWidgetManagerInternal awm = LocalServices.getService(AppWidgetManagerInternal.class);
+            if (awm != null) {
+                awm.unlockUser(userId);
+            }
+        }
+
         void updateUserConfiguration() {
             mService.mActivityTaskManager.updateUserConfiguration();
         }
@@ -2237,7 +2251,7 @@
 
         protected void stackSupervisorResumeFocusedStackTopActivity() {
             synchronized (mService) {
-                mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
             }
         }
 
diff --git a/services/core/java/com/android/server/am/WindowProcessController.java b/services/core/java/com/android/server/am/WindowProcessController.java
index 64a273e..e5551b5 100644
--- a/services/core/java/com/android/server/am/WindowProcessController.java
+++ b/services/core/java/com/android/server/am/WindowProcessController.java
@@ -93,6 +93,12 @@
     private volatile String mRequiredAbi;
     // Running any services that are foreground?
     private volatile boolean mHasForegroundServices;
+    // was app launched for debugging?
+    private volatile boolean mDebugging;
+    // Active instrumentation running in process?
+    private volatile boolean mInstrumenting;
+    // Set to true when process was launched with a wrapper attached
+    private volatile boolean mUsingWrapper;
 
     // Thread currently set for VR scheduling
     int mVrThreadTid;
@@ -189,6 +195,30 @@
         return mRequiredAbi;
     }
 
+    public void setDebugging(boolean debugging) {
+        mDebugging = debugging;
+    }
+
+    boolean isDebugging() {
+        return mDebugging;
+    }
+
+    public void setUsingWrapper(boolean usingWrapper) {
+        mUsingWrapper = usingWrapper;
+    }
+
+    boolean isUsingWrapper() {
+        return mUsingWrapper;
+    }
+
+    public void setInstrumenting(boolean instrumenting) {
+        mInstrumenting = instrumenting;
+    }
+
+    boolean isInstrumenting() {
+        return mInstrumenting;
+    }
+
     public void addPackage(String packageName) {
         synchronized (mAtm.mGlobalLock) {
             mPkgList.add(packageName);
@@ -334,7 +364,12 @@
 
     boolean shouldKillProcessForRemovedTask(TaskRecord tr) {
         for (int k = 0; k < mActivities.size(); k++) {
-            final TaskRecord otherTask = mActivities.get(k).getTask();
+            final ActivityRecord activity = mActivities.get(k);
+            if (!activity.stopped) {
+                // Don't kill process(es) that has an activity not stopped.
+                return false;
+            }
+            final TaskRecord otherTask = activity.getTask();
             if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
                 // Don't kill process(es) that has an activity in a different task that is
                 // also in recents.
@@ -431,6 +466,19 @@
         return minTaskLayer;
     }
 
+    int computeRelaunchReason() {
+        synchronized (mAtm.mGlobalLock) {
+            final int activitiesSize = mActivities.size();
+            for (int i = activitiesSize - 1; i >= 0; i--) {
+                final ActivityRecord r = mActivities.get(i);
+                if (r.mRelaunchReason != ActivityRecord.RELAUNCH_REASON_NONE) {
+                    return r.mRelaunchReason;
+                }
+            }
+        }
+        return ActivityRecord.RELAUNCH_REASON_NONE;
+    }
+
     void clearProfilerIfNeeded() {
         if (mListener == null) return;
         // Posting on handler so WM lock isn't held when we call into AM.
@@ -478,6 +526,11 @@
         mAtm.mH.post(r);
     }
 
+    /** Returns the total time (in milliseconds) spent executing in both user and system code. */
+    public long getCpuTime() {
+        return (mListener != null) ? mListener.getCpuTime() : 0;
+    }
+
     void addRecentTask(TaskRecord task) {
         mRecentTasks.add(task);
     }
diff --git a/services/core/java/com/android/server/am/WindowProcessListener.java b/services/core/java/com/android/server/am/WindowProcessListener.java
index 92e4461..2de3e37 100644
--- a/services/core/java/com/android/server/am/WindowProcessListener.java
+++ b/services/core/java/com/android/server/am/WindowProcessListener.java
@@ -44,4 +44,7 @@
 
     /** Set process package been removed from device. */
     void setRemoved(boolean removed);
+
+    /** Returns the total time (in milliseconds) spent executing in both user and system code. */
+    long getCpuTime();
 }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 6971f71..8caa702 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -57,6 +57,7 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
+import android.hardware.hdmi.HdmiAudioSystemClient;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiPlaybackClient;
 import android.hardware.hdmi.HdmiTvClient;
@@ -926,14 +927,15 @@
         }
 
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
-            mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
-            synchronized (mHdmiManager) {
+            synchronized (mHdmiClientLock) {
+                mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
                 mHdmiTvClient = mHdmiManager.getTvClient();
                 if (mHdmiTvClient != null) {
                     mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
                 }
                 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
                 mHdmiCecSink = false;
+                mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
             }
         }
 
@@ -1054,11 +1056,9 @@
             sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
             sendEnabledSurroundFormats(mContentResolver, true);
         }
-        if (mHdmiManager != null) {
-            synchronized (mHdmiManager) {
-                if (mHdmiTvClient != null) {
-                    setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
-                }
+        synchronized (mHdmiClientLock) {
+            if (mHdmiManager != null && mHdmiTvClient != null) {
+                setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
             }
         }
 
@@ -1763,24 +1763,34 @@
             if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
                 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
             }
-            if (mHdmiManager != null) {
-                synchronized (mHdmiManager) {
+            synchronized (mHdmiClientLock) {
+                if (mHdmiManager != null) {
                     // mHdmiCecSink true => mHdmiPlaybackClient != null
                     if (mHdmiCecSink &&
                             streamTypeAlias == AudioSystem.STREAM_MUSIC &&
                             oldIndex != newIndex) {
-                        synchronized (mHdmiPlaybackClient) {
-                            int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
-                                    KeyEvent.KEYCODE_VOLUME_UP;
-                            final long ident = Binder.clearCallingIdentity();
-                            try {
-                                mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
-                                mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
-                            } finally {
-                                Binder.restoreCallingIdentity(ident);
-                            }
+                        int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
+                                KeyEvent.KEYCODE_VOLUME_UP;
+                        final long ident = Binder.clearCallingIdentity();
+                        try {
+                            mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
+                            mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
+                        } finally {
+                            Binder.restoreCallingIdentity(ident);
                         }
                     }
+
+                    if (mHdmiAudioSystemClient != null &&
+                            mHdmiSystemAudioSupported &&
+                            streamTypeAlias == AudioSystem.STREAM_MUSIC &&
+                            (oldIndex != newIndex || isMuteAdjust)) {
+                        final long identity = Binder.clearCallingIdentity();
+                        mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
+                                isMuteAdjust, getStreamVolume(AudioSystem.STREAM_MUSIC),
+                                getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
+                                isStreamMute(AudioSystem.STREAM_MUSIC));
+                        Binder.restoreCallingIdentity(identity);
+                    }
                 }
             }
         }
@@ -1799,22 +1809,19 @@
     }
 
     private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
-        if (mHdmiManager == null
-                || mHdmiTvClient == null
-                || oldVolume == newVolume
-                || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0) return;
-
         // Sets the audio volume of AVR when we are in system audio mode. The new volume info
         // is tranformed to HDMI-CEC commands and passed through CEC bus.
-        synchronized (mHdmiManager) {
-            if (!mHdmiSystemAudioSupported) return;
-            synchronized (mHdmiTvClient) {
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
+        synchronized (mHdmiClientLock) {
+            if (mHdmiManager == null
+                    || mHdmiTvClient == null
+                    || oldVolume == newVolume
+                    || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
+                    || !mHdmiSystemAudioSupported) return;
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
+            } finally {
+                Binder.restoreCallingIdentity(token);
             }
         }
     }
@@ -2037,6 +2044,20 @@
                 index = mStreamStates[streamType].getIndex(device);
             }
         }
+        synchronized (mHdmiClientLock) {
+            if (mHdmiManager != null &&
+                    mHdmiAudioSystemClient != null &&
+                    mHdmiSystemAudioSupported &&
+                    streamTypeAlias == AudioSystem.STREAM_MUSIC &&
+                    (oldIndex != index)) {
+                final long identity = Binder.clearCallingIdentity();
+                mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
+                        false, getStreamVolume(AudioSystem.STREAM_MUSIC),
+                        getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
+                        isStreamMute(AudioSystem.STREAM_MUSIC));
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
         sendVolumeUpdate(streamType, oldIndex, index, flags);
     }
 
@@ -2177,8 +2198,8 @@
     // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
     // receives volume notification from Audio Receiver.
     private int updateFlagsForSystemAudio(int flags) {
-        if (mHdmiTvClient != null) {
-            synchronized (mHdmiTvClient) {
+        synchronized (mHdmiClientLock) {
+            if (mHdmiTvClient != null) {
                 if (mHdmiSystemAudioSupported &&
                         ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
                     flags &= ~AudioManager.FLAG_SHOW_UI;
@@ -2233,16 +2254,13 @@
     }
 
     private void setSystemAudioMute(boolean state) {
-        if (mHdmiManager == null || mHdmiTvClient == null) return;
-        synchronized (mHdmiManager) {
-            if (!mHdmiSystemAudioSupported) return;
-            synchronized (mHdmiTvClient) {
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    mHdmiTvClient.setSystemAudioMute(state);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
+        synchronized (mHdmiClientLock) {
+            if (mHdmiManager == null || mHdmiTvClient == null || !mHdmiSystemAudioSupported) return;
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mHdmiTvClient.setSystemAudioMute(state);
+            } finally {
+                Binder.restoreCallingIdentity(token);
             }
         }
     }
@@ -2562,12 +2580,12 @@
                 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
                 break;
         }
-        maybeVibrate(effect);
+        maybeVibrate(effect, reason);
         setRingerModeInternal(ringerMode, reason);
         Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
     }
 
-    private boolean maybeVibrate(VibrationEffect effect) {
+    private boolean maybeVibrate(VibrationEffect effect, String reason) {
         if (!mHasVibrator) {
             return false;
         }
@@ -2580,8 +2598,8 @@
         if (effect == null) {
             return false;
         }
-        mVibrator.vibrate(
-                Binder.getCallingUid(), mContext.getOpPackageName(), effect, VIBRATION_ATTRIBUTES);
+        mVibrator.vibrate(Binder.getCallingUid(), mContext.getOpPackageName(), effect,
+                reason, VIBRATION_ATTRIBUTES);
         return true;
     }
 
@@ -3814,6 +3832,10 @@
                             int delay = checkSendBecomingNoisyIntent(
                                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
                                     AudioSystem.DEVICE_NONE);
+                            final String addr = btDevice == null ? "null" : btDevice.getAddress();
+                            mDeviceLogger.log(new AudioEventLogger.StringEvent(
+                                    "A2DP service connected: device addr=" + addr
+                                    + " state=" + state));
                             queueMsgUnderWakeLock(mAudioHandler,
                                     MSG_SET_A2DP_SINK_CONNECTION_STATE,
                                     state,
@@ -4677,7 +4699,14 @@
     public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice device,
                 int state, int profile, boolean suppressNoisyIntent, int a2dpVolume)
     {
+        mDeviceLogger.log(new AudioEventLogger.StringEvent(
+                "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent state=" + state
+                // only querying address as this is the only readily available field on the device
+                + " addr=" + device.getAddress()
+                + " prof=" + profile + " supprNoisy=" + suppressNoisyIntent
+                + " vol=" + a2dpVolume));
         if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, device)) {
+            mDeviceLogger.log(new AudioEventLogger.StringEvent("A2DP connection state ignored"));
             return 0;
         }
         return setBluetoothA2dpDeviceConnectionStateInt(
@@ -5630,7 +5659,7 @@
                 case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
                     {   WiredDeviceConnectionState connectState =
                             (WiredDeviceConnectionState)msg.obj;
-                        mWiredDevLogger.log(new WiredDevConnectEvent(connectState));
+                        mDeviceLogger.log(new WiredDevConnectEvent(connectState));
                         onSetWiredDeviceConnectionState(connectState.mType, connectState.mState,
                                 connectState.mAddress, connectState.mName, connectState.mCaller);
                         mAudioEventWakeLock.release();
@@ -6085,10 +6114,14 @@
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
             address = "";
         }
+        mDeviceLogger.log(new AudioEventLogger.StringEvent(
+                "onBluetoothA2dpDeviceConfigChange addr=" + address));
 
         int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
         synchronized (mConnectedDevices) {
             if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, btDevice)) {
+                mDeviceLogger.log(new AudioEventLogger.StringEvent(
+                        "A2dp config change ignored"));
                 return;
             }
             final String key = makeDeviceListKey(device, address);
@@ -6355,12 +6388,10 @@
                 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
                     mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
                     checkAllFixedVolumeDevices();
-                    if (mHdmiManager != null) {
-                        synchronized (mHdmiManager) {
-                            if (mHdmiPlaybackClient != null) {
-                                mHdmiCecSink = false;
-                                mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
-                            }
+                    synchronized (mHdmiClientLock) {
+                        if (mHdmiManager != null && mHdmiPlaybackClient != null) {
+                            mHdmiCecSink = false;
+                            mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
                         }
                     }
                 }
@@ -6369,8 +6400,8 @@
                 }
             } else {
                 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
-                    if (mHdmiManager != null) {
-                        synchronized (mHdmiManager) {
+                    synchronized (mHdmiClientLock) {
+                        if (mHdmiManager != null) {
                             mHdmiCecSink = false;
                         }
                     }
@@ -7039,8 +7070,8 @@
 
     private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
         public void onComplete(int status) {
-            if (mHdmiManager != null) {
-                synchronized (mHdmiManager) {
+            synchronized (mHdmiClientLock) {
+                if (mHdmiManager != null) {
                     mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
                     // Television devices without CEC service apply software volume on HDMI output
                     if (isPlatformTelevision() && !mHdmiCecSink) {
@@ -7050,43 +7081,49 @@
                 }
             }
         }
-    };
+    }
+
+    private final Object mHdmiClientLock = new Object();
 
     // If HDMI-CEC system audio is supported
     private boolean mHdmiSystemAudioSupported = false;
     // Set only when device is tv.
+    @GuardedBy("mHdmiClientLock")
     private HdmiTvClient mHdmiTvClient;
     // true if the device has system feature PackageManager.FEATURE_LEANBACK.
     // cached HdmiControlManager interface
+    @GuardedBy("mHdmiClientLock")
     private HdmiControlManager mHdmiManager;
     // Set only when device is a set-top box.
+    @GuardedBy("mHdmiClientLock")
     private HdmiPlaybackClient mHdmiPlaybackClient;
     // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
     private boolean mHdmiCecSink;
+    // Set only when device is an audio system.
+    @GuardedBy("mHdmiClientLock")
+    private HdmiAudioSystemClient mHdmiAudioSystemClient;
 
     private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
 
     @Override
     public int setHdmiSystemAudioSupported(boolean on) {
         int device = AudioSystem.DEVICE_NONE;
-        if (mHdmiManager != null) {
-            synchronized (mHdmiManager) {
-                if (mHdmiTvClient == null) {
-                    Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
+        synchronized (mHdmiClientLock) {
+            if (mHdmiManager != null) {
+                if (mHdmiTvClient == null && mHdmiAudioSystemClient == null) {
+                    Log.w(TAG, "Only Hdmi-Cec enabled TV or audio system device supports"
+                            + "system audio mode.");
                     return device;
                 }
-
-                synchronized (mHdmiTvClient) {
-                    if (mHdmiSystemAudioSupported != on) {
-                        mHdmiSystemAudioSupported = on;
-                        final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
-                            AudioSystem.FORCE_NONE;
-                        mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
-                                config, "setHdmiSystemAudioSupported"));
-                        AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config);
-                    }
-                    device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
+                if (mHdmiSystemAudioSupported != on) {
+                    mHdmiSystemAudioSupported = on;
+                    final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
+                        AudioSystem.FORCE_NONE;
+                    mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
+                            config, "setHdmiSystemAudioSupported"));
+                    AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config);
                 }
+                device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
             }
         }
         return device;
@@ -7185,19 +7222,20 @@
     //==========================================================================================
     // AudioService logging and dumpsys
     //==========================================================================================
-    final int LOG_NB_EVENTS_PHONE_STATE = 20;
-    final int LOG_NB_EVENTS_WIRED_DEV_CONNECTION = 30;
-    final int LOG_NB_EVENTS_FORCE_USE = 20;
-    final int LOG_NB_EVENTS_VOLUME = 40;
-    final int LOG_NB_EVENTS_DYN_POLICY = 10;
+    static final int LOG_NB_EVENTS_PHONE_STATE = 20;
+    static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 30;
+    static final int LOG_NB_EVENTS_FORCE_USE = 20;
+    static final int LOG_NB_EVENTS_VOLUME = 40;
+    static final int LOG_NB_EVENTS_DYN_POLICY = 10;
 
     final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
             "phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
 
-    final private AudioEventLogger mWiredDevLogger = new AudioEventLogger(
-            LOG_NB_EVENTS_WIRED_DEV_CONNECTION,
-            "wired device connection (logged before onSetWiredDeviceConnectionState() is executed)"
-            );
+    // logs for wired + A2DP device connections:
+    // - wired: logged before onSetWiredDeviceConnectionState() is executed
+    // - A2DP: logged at reception of method call
+    final private AudioEventLogger mDeviceLogger = new AudioEventLogger(
+            LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP device connection");
 
     final private AudioEventLogger mForceUseLogger = new AudioEventLogger(
             LOG_NB_EVENTS_FORCE_USE,
@@ -7286,7 +7324,7 @@
         pw.println("\nEvent logs:");
         mModeLogger.dump(pw);
         pw.println("\n");
-        mWiredDevLogger.dump(pw);
+        mDeviceLogger.dump(pw);
         pw.println("\n");
         mForceUseLogger.dump(pw);
         pw.println("\n");
diff --git a/services/core/java/com/android/server/biometrics/common/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/common/AuthenticationClient.java
index 6e5858a..a9cf963 100644
--- a/services/core/java/com/android/server/biometrics/common/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/common/AuthenticationClient.java
@@ -21,10 +21,11 @@
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.IBiometricPromptReceiver;
-import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.util.Slog;
 
@@ -35,6 +36,7 @@
  */
 public abstract class AuthenticationClient extends ClientMonitor {
     private long mOpId;
+    private Handler mHandler;
 
     public abstract int handleFailedAttempt();
     public abstract void resetFailedAttempts();
@@ -97,6 +99,7 @@
         mStatusBarService = statusBarService;
         mFingerprintManager = (FingerprintManager) getContext()
                 .getSystemService(Context.FINGERPRINT_SERVICE);
+        mHandler = new Handler(Looper.getMainLooper());
     }
 
     @Override
@@ -114,7 +117,7 @@
         if (mBundle != null) {
             try {
                 if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
-                    mStatusBarService.onFingerprintHelp(
+                    mStatusBarService.onBiometricHelp(
                             mFingerprintManager.getAcquiredString(acquiredInfo, vendorCode));
                 }
                 return false; // acquisition continues
@@ -143,7 +146,7 @@
         }
         if (mBundle != null) {
             try {
-                mStatusBarService.onFingerprintError(
+                mStatusBarService.onBiometricError(
                         mFingerprintManager.getErrorString(error, vendorCode));
             } catch (RemoteException e) {
                 Slog.e(getLogTag(), "Remote exception when sending error", e);
@@ -153,17 +156,18 @@
     }
 
     @Override
-    public boolean onAuthenticated(int fingerId, int groupId) {
+    public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
+            boolean authenticated) {
         boolean result = false;
-        boolean authenticated = fingerId != 0;
 
         // If the fingerprint dialog is showing, notify authentication succeeded
+        // TODO: this goes to BiometricPrompt, split between biometric modalities
         if (mBundle != null) {
             try {
                 if (authenticated) {
-                    mStatusBarService.onFingerprintAuthenticated();
+                    mStatusBarService.onBiometricAuthenticated();
                 } else {
-                    mStatusBarService.onFingerprintHelp(getContext().getResources().getString(
+                    mStatusBarService.onBiometricHelp(getContext().getResources().getString(
                             com.android.internal.R.string.fingerprint_not_recognized));
                 }
             } catch (RemoteException e) {
@@ -180,12 +184,18 @@
                 } else {
                     if (DEBUG) {
                         Slog.v(getLogTag(), "onAuthenticated(owner=" + getOwnerString()
-                                + ", id=" + fingerId + ", gp=" + groupId + ")");
+                                + ", id=" + identifier.getBiometricId());
                     }
-                    Fingerprint fp = !getIsRestricted()
-                            ? new Fingerprint("" /* TODO */, groupId, fingerId, getHalDeviceId())
-                            : null;
-                    listener.onAuthenticationSucceeded(getHalDeviceId(), fp, getTargetUserId());
+
+                    // Explicitly have if/else here to make it super obvious in case the code is
+                    // touched in the future.
+                    if (!getIsRestricted()) {
+                        listener.onAuthenticationSucceeded(
+                                getHalDeviceId(), identifier, getTargetUserId());
+                    } else {
+                        listener.onAuthenticationSucceeded(
+                                getHalDeviceId(), null, getTargetUserId());
+                    }
                 }
             } catch (RemoteException e) {
                 Slog.w(getLogTag(), "Failed to notify Authenticated:", e);
@@ -210,15 +220,19 @@
                             BiometricConstants.BIOMETRIC_ERROR_LOCKOUT :
                             BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
 
-                    // TODO: if the dialog is showing, this error should be delayed. On a similar
-                    // note, AuthenticationClient should override onError and delay all other errors
-                    // as well, if the dialog is showing
-                    listener.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
-
                     // Send the lockout message to the system dialog
                     if (mBundle != null) {
-                        mStatusBarService.onFingerprintError(
+                        mStatusBarService.onBiometricError(
                                 mFingerprintManager.getErrorString(errorCode, 0 /* vendorCode */));
+                        mHandler.postDelayed(() -> {
+                            try {
+                                listener.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
+                            } catch (RemoteException e) {
+                                Slog.w(getLogTag(), "RemoteException while sending error");
+                            }
+                        }, BiometricPrompt.HIDE_DIALOG_DELAY);
+                    } else {
+                        listener.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
                     }
                 } catch (RemoteException e) {
                     Slog.w(getLogTag(), "Failed to notify lockout:", e);
@@ -256,7 +270,7 @@
             // If authenticating with system dialog, show the dialog
             if (mBundle != null) {
                 try {
-                    mStatusBarService.showFingerprintDialog(mBundle, mDialogReceiver);
+                    mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver);
                 } catch (RemoteException e) {
                     Slog.e(getLogTag(), "Unable to show fingerprint dialog", e);
                 }
@@ -294,7 +308,7 @@
             // after BiometricPrompt.HIDE_DIALOG_DELAY
             if (mBundle != null && !mDialogDismissed && !mInLockout) {
                 try {
-                    mStatusBarService.hideFingerprintDialog();
+                    mStatusBarService.hideBiometricDialog();
                 } catch (RemoteException e) {
                     Slog.e(getLogTag(), "Unable to hide fingerprint dialog", e);
                 }
diff --git a/services/core/java/com/android/server/biometrics/common/BiometricService.java b/services/core/java/com/android/server/biometrics/common/BiometricService.java
index 41b1575..5603f2f 100644
--- a/services/core/java/com/android/server/biometrics/common/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/common/BiometricService.java
@@ -58,7 +58,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.server.SystemService;
-import com.android.server.biometrics.face.FaceService;
 import com.android.server.biometrics.fingerprint.FingerprintService;
 
 import java.util.ArrayList;
@@ -577,20 +576,22 @@
         }
     }
 
-    protected void handleAuthenticated(long deviceId, int biometricId, int groupId,
+    protected void handleAuthenticated(BiometricAuthenticator.Identifier identifier,
             ArrayList<Byte> token) {
         ClientMonitor client = mCurrentClient;
-        if (biometricId != 0) {
+        final boolean authenticated = identifier.getBiometricId() != 0;
+
+        if (authenticated) {
             final byte[] byteToken = new byte[token.size()];
             for (int i = 0; i < token.size(); i++) {
                 byteToken[i] = token.get(i);
             }
             KeyStore.getInstance().addAuthToken(byteToken);
         }
-        if (client != null && client.onAuthenticated(biometricId, groupId)) {
+        if (client != null && client.onAuthenticated(identifier, authenticated)) {
             removeClient(client);
         }
-        if (biometricId != 0) {
+        if (authenticated) {
             mPerformanceStats.accept++;
         } else {
             mPerformanceStats.reject++;
diff --git a/services/core/java/com/android/server/biometrics/common/ClientMonitor.java b/services/core/java/com/android/server/biometrics/common/ClientMonitor.java
index 699fc32..1486754 100644
--- a/services/core/java/com/android/server/biometrics/common/ClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/common/ClientMonitor.java
@@ -127,7 +127,8 @@
     // to the next client (e.g. authentication accepts or rejects a biometric).
     public abstract boolean onEnrollResult(BiometricAuthenticator.Identifier identifier,
             int remaining);
-    public abstract boolean onAuthenticated(int biometricId, int groupId);
+    public abstract boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
+            boolean authenticated);
     public abstract boolean onRemoved(BiometricAuthenticator.Identifier identifier,
             int remaining);
     public abstract boolean onEnumerationResult(
diff --git a/services/core/java/com/android/server/biometrics/common/EnrollClient.java b/services/core/java/com/android/server/biometrics/common/EnrollClient.java
index 5744fdb..aee772b 100644
--- a/services/core/java/com/android/server/biometrics/common/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/common/EnrollClient.java
@@ -125,7 +125,8 @@
     }
 
     @Override
-    public boolean onAuthenticated(int biometricId, int groupId) {
+    public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
+            boolean authenticated) {
         if (DEBUG) Slog.w(getLogTag(), "onAuthenticated() called for enroll!");
         return true; // Invalid for EnrollClient
     }
diff --git a/services/core/java/com/android/server/biometrics/common/EnumerateClient.java b/services/core/java/com/android/server/biometrics/common/EnumerateClient.java
index e51c1c6..ee40ee9 100644
--- a/services/core/java/com/android/server/biometrics/common/EnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/common/EnumerateClient.java
@@ -93,7 +93,8 @@
     }
 
     @Override
-    public boolean onAuthenticated(int biometricId, int groupId) {
+    public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
+            boolean authenticated) {
         if (DEBUG) Slog.w(getLogTag(), "onAuthenticated() called for enumerate!");
         return true; // Invalid for Enumerate.
     }
diff --git a/services/core/java/com/android/server/biometrics/common/RemovalClient.java b/services/core/java/com/android/server/biometrics/common/RemovalClient.java
index 23d5539..27c42ab 100644
--- a/services/core/java/com/android/server/biometrics/common/RemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/common/RemovalClient.java
@@ -110,7 +110,8 @@
     }
 
     @Override
-    public boolean onAuthenticated(int biometricId, int groupId) {
+    public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
+            boolean authenticated) {
         if (DEBUG) Slog.w(getLogTag(), "onAuthenticated() called for remove!");
         return true; // Invalid for Remove.
     }
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 35679a88..f8ccef5 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -400,7 +400,8 @@
                 public void onAuthenticated(final long deviceId, final int faceId, final int userId,
                         ArrayList<Byte> token) {
                     mHandler.post(() -> {
-                        FaceService.super.handleAuthenticated(deviceId, faceId, userId, token);
+                        Face face = new Face("", faceId, deviceId);
+                        FaceService.super.handleAuthenticated(face, token);
                     });
                 }
 
diff --git a/services/core/java/com/android/server/biometrics/face/FaceUserState.java b/services/core/java/com/android/server/biometrics/face/FaceUserState.java
index 7d67c62..c438bfb 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceUserState.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceUserState.java
@@ -23,6 +23,7 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.server.biometrics.common.BiometricUserState;
 
 import libcore.io.IoUtils;
@@ -84,7 +85,7 @@
         ArrayList<Face> result = new ArrayList<>(array.size());
         for (int i = 0; i < array.size(); i++) {
             Face f = (Face) array.get(i);
-            result.add(new Face(f.getName(), f.getFaceId(), f.getDeviceId()));
+            result.add(new Face(f.getName(), f.getBiometricId(), f.getDeviceId()));
         }
         return result;
     }
@@ -113,7 +114,7 @@
             for (int i = 0; i < count; i++) {
                 Face f = faces.get(i);
                 serializer.startTag(null, TAG_FACE);
-                serializer.attribute(null, ATTR_FACE_ID, Integer.toString(f.getFaceId()));
+                serializer.attribute(null, ATTR_FACE_ID, Integer.toString(f.getBiometricId()));
                 serializer.attribute(null, ATTR_NAME, f.getName().toString());
                 serializer.attribute(null, ATTR_DEVICE_ID, Long.toString(f.getDeviceId()));
                 serializer.endTag(null, TAG_FACE);
@@ -133,6 +134,7 @@
         }
     }
 
+    @GuardedBy("this")
     @Override
     protected void parseBiometricsLocked(XmlPullParser parser)
             throws IOException, XmlPullParserException {
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index 7004e1b..64b248e 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -528,7 +528,8 @@
         public void onAuthenticated(final long deviceId, final int fingerId, final int groupId,
                 ArrayList<Byte> token) {
             mHandler.post(() -> {
-                FingerprintService.super.handleAuthenticated(deviceId, fingerId, groupId, token);
+                Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId);
+                FingerprintService.super.handleAuthenticated(fp, token);
             });
         }
 
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 5db20b0..c80c0f1 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -21,7 +21,9 @@
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
+import android.app.IUriGrantsManager;
 import android.app.KeyguardManager;
+import android.app.UriGrantsManager;
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.ContentProvider;
@@ -45,10 +47,14 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.util.Slog;
 import android.util.SparseArray;
 
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.uri.UriGrantsManagerInternal;
+import com.android.server.wm.WindowManagerInternal;
 
 import java.io.IOException;
 import java.io.RandomAccessFile;
@@ -143,6 +149,9 @@
         SystemProperties.getBoolean("ro.kernel.qemu", false);
 
     private final IActivityManager mAm;
+    private final IUriGrantsManager mUgm;
+    private final UriGrantsManagerInternal mUgmInternal;
+    private final WindowManagerInternal mWm;
     private final IUserManager mUm;
     private final PackageManager mPm;
     private final AppOpsManager mAppOps;
@@ -159,15 +168,13 @@
         super(context);
 
         mAm = ActivityManager.getService();
+        mUgm = UriGrantsManager.getService();
+        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
+        mWm = LocalServices.getService(WindowManagerInternal.class);
         mPm = getContext().getPackageManager();
         mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
-        IBinder permOwner = null;
-        try {
-            permOwner = mAm.newUriPermissionOwner("clipboard");
-        } catch (RemoteException e) {
-            Slog.w("clipboard", "AM dead", e);
-        }
+        final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
         mPermissionOwner = permOwner;
         if (IS_EMULATOR) {
             mHostClipboardMonitor = new HostClipboardMonitor(
@@ -497,12 +504,10 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             // This will throw SecurityException if caller can't grant
-            mAm.checkGrantUriPermission(sourceUid, null,
+            mUgmInternal.checkGrantUriPermission(sourceUid, null,
                     ContentProvider.getUriWithoutUserId(uri),
                     Intent.FLAG_GRANT_READ_URI_PERMISSION,
                     ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
-        } catch (RemoteException ignored) {
-            // Ignored because we're in same process
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -531,7 +536,7 @@
 
         final long ident = Binder.clearCallingIdentity();
         try {
-            mAm.grantUriPermissionFromOwner(mPermissionOwner, sourceUid, targetPkg,
+            mUgm.grantUriPermissionFromOwner(mPermissionOwner, sourceUid, targetPkg,
                     ContentProvider.getUriWithoutUserId(uri),
                     Intent.FLAG_GRANT_READ_URI_PERMISSION,
                     ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)),
@@ -588,12 +593,10 @@
 
         final long ident = Binder.clearCallingIdentity();
         try {
-            mAm.revokeUriPermissionFromOwner(mPermissionOwner,
+            mUgmInternal.revokeUriPermissionFromOwner(mPermissionOwner,
                     ContentProvider.getUriWithoutUserId(uri),
                     Intent.FLAG_GRANT_READ_URI_PERMISSION,
                     ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
-        } catch (RemoteException ignored) {
-            // Ignored because we're in same process
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -624,18 +627,19 @@
         if (mAppOps.noteOp(op, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
             return false;
         }
-        try {
-            // Installed apps can access the clipboard at any time.
-            if (!AppGlobals.getPackageManager().isInstantApp(callingPackage,
-                        UserHandle.getUserId(callingUid))) {
-                return true;
-            }
-            // Instant apps can only access the clipboard if they are in the foreground.
-            return mAm.isAppForeground(callingUid);
-        } catch (RemoteException e) {
-            Slog.e("clipboard", "Failed to get Instant App status for package " + callingPackage,
-                    e);
-            return false;
+        // The default IME is always allowed to access the clipboard.
+        String defaultIme = Settings.Secure.getStringForUser(getContext().getContentResolver(),
+                Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.getUserId(callingUid));
+        if (defaultIme != null && defaultIme.equals(callingPackage)) {
+            return true;
         }
+
+        // Otherwise only focused applications can access the clipboard.
+        boolean uidFocused = mWm.isUidFocused(callingUid);
+        if (!uidFocused) {
+            Slog.e(TAG, "Denying clipboard access to " + callingPackage
+                    + ", application is not in focus.");
+        }
+        return uidFocused;
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 9b9a380..843ba2e 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -21,7 +21,10 @@
 import static android.net.CaptivePortal.APP_RETURN_WANTED_AS_IS;
 import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;
 import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL;
+import static android.net.metrics.ValidationProbeEvent.DNS_FAILURE;
+import static android.net.metrics.ValidationProbeEvent.DNS_SUCCESS;
 import static android.net.metrics.ValidationProbeEvent.PROBE_FALLBACK;
+import static android.net.metrics.ValidationProbeEvent.PROBE_PRIVDNS;
 
 import android.annotation.Nullable;
 import android.app.PendingIntent;
@@ -258,7 +261,7 @@
     private final WifiManager mWifiManager;
     private final NetworkRequest mDefaultRequest;
     private final IpConnectivityLog mMetricsLog;
-    private final NetworkMonitorSettings mSettings;
+    private final Dependencies mDependencies;
 
     // Configuration values for captive portal detection probes.
     private final String mCaptivePortalUserAgent;
@@ -298,18 +301,19 @@
     // This variable is set before transitioning to the mCaptivePortalState.
     private CaptivePortalProbeResult mLastPortalProbeResult = CaptivePortalProbeResult.FAILED;
 
+    // Random generator to select fallback URL index
+    private final Random mRandom;
     private int mNextFallbackUrlIndex = 0;
 
     public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
             NetworkRequest defaultRequest) {
         this(context, handler, networkAgentInfo, defaultRequest, new IpConnectivityLog(),
-                NetworkMonitorSettings.DEFAULT);
+                Dependencies.DEFAULT);
     }
 
     @VisibleForTesting
     protected NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
-            NetworkRequest defaultRequest, IpConnectivityLog logger,
-            NetworkMonitorSettings settings) {
+            NetworkRequest defaultRequest, IpConnectivityLog logger, Dependencies deps) {
         // Add suffix indicating which NetworkMonitor we're talking about.
         super(TAG + networkAgentInfo.name());
 
@@ -320,9 +324,9 @@
         mContext = context;
         mMetricsLog = logger;
         mConnectivityServiceHandler = handler;
-        mSettings = settings;
+        mDependencies = deps;
         mNetworkAgentInfo = networkAgentInfo;
-        mNetwork = new OneAddressPerFamilyNetwork(networkAgentInfo.network());
+        mNetwork = deps.getNetwork(networkAgentInfo);
         mNetId = mNetwork.netId;
         mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -340,9 +344,10 @@
         mUseHttps = getUseHttpsValidation();
         mCaptivePortalUserAgent = getCaptivePortalUserAgent();
         mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl());
-        mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(settings, context));
+        mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(deps, context));
         mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls();
         mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs();
+        mRandom = deps.getRandom();
 
         start();
     }
@@ -799,8 +804,10 @@
                 final InetAddress[] ips = ResolvUtil.blockingResolveAllLocally(
                         mNetwork, mPrivateDnsProviderHostname, 0 /* aiFlags */);
                 mPrivateDnsConfig = new PrivateDnsConfig(mPrivateDnsProviderHostname, ips);
+                validationLog("Strict mode hostname resolved: " + mPrivateDnsConfig);
             } catch (UnknownHostException uhe) {
                 mPrivateDnsConfig = null;
+                validationLog("Strict mode hostname resolution failed: " + uhe.getMessage());
             }
         }
 
@@ -829,10 +836,21 @@
             final String ONE_TIME_HOSTNAME_SUFFIX = "-dnsotls-ds.metric.gstatic.com";
             final String host = UUID.randomUUID().toString().substring(0, 8) +
                     ONE_TIME_HOSTNAME_SUFFIX;
+            final Stopwatch watch = new Stopwatch().start();
             try {
                 final InetAddress[] ips = mNetworkAgentInfo.network().getAllByName(host);
-                return (ips != null && ips.length > 0);
-            } catch (UnknownHostException uhe) {}
+                final long time = watch.stop();
+                final String strIps = Arrays.toString(ips);
+                final boolean success = (ips != null && ips.length > 0);
+                validationLog(PROBE_PRIVDNS, host, String.format("%dms: %s", time, strIps));
+                logValidationProbe(time, PROBE_PRIVDNS, success ? DNS_SUCCESS : DNS_FAILURE);
+                return success;
+            } catch (UnknownHostException uhe) {
+                final long time = watch.stop();
+                validationLog(PROBE_PRIVDNS, host,
+                        String.format("%dms - Error: %s", time, uhe.getMessage()));
+                logValidationProbe(time, PROBE_PRIVDNS, DNS_FAILURE);
+            }
             return false;
         }
     }
@@ -867,40 +885,38 @@
     public boolean getIsCaptivePortalCheckEnabled() {
         String symbol = Settings.Global.CAPTIVE_PORTAL_MODE;
         int defaultValue = Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT;
-        int mode = mSettings.getSetting(mContext, symbol, defaultValue);
+        int mode = mDependencies.getSetting(mContext, symbol, defaultValue);
         return mode != Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE;
     }
 
     public boolean getUseHttpsValidation() {
-        return mSettings.getSetting(mContext, Settings.Global.CAPTIVE_PORTAL_USE_HTTPS, 1) == 1;
+        return mDependencies.getSetting(mContext, Settings.Global.CAPTIVE_PORTAL_USE_HTTPS, 1) == 1;
     }
 
     public boolean getWifiScansAlwaysAvailableDisabled() {
-        return mSettings.getSetting(mContext, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 0;
+        return mDependencies.getSetting(mContext, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 0;
     }
 
     private String getCaptivePortalServerHttpsUrl() {
-        return mSettings.getSetting(mContext,
+        return mDependencies.getSetting(mContext,
                 Settings.Global.CAPTIVE_PORTAL_HTTPS_URL, DEFAULT_HTTPS_URL);
     }
 
     // Static for direct access by ConnectivityService
     public static String getCaptivePortalServerHttpUrl(Context context) {
-        return getCaptivePortalServerHttpUrl(NetworkMonitorSettings.DEFAULT, context);
+        return getCaptivePortalServerHttpUrl(Dependencies.DEFAULT, context);
     }
 
-    public static String getCaptivePortalServerHttpUrl(
-            NetworkMonitorSettings settings, Context context) {
-        return settings.getSetting(
-                context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL);
+    public static String getCaptivePortalServerHttpUrl(Dependencies deps, Context context) {
+        return deps.getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL);
     }
 
     private URL[] makeCaptivePortalFallbackUrls() {
         try {
             String separator = ",";
-            String firstUrl = mSettings.getSetting(mContext,
+            String firstUrl = mDependencies.getSetting(mContext,
                     Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL);
-            String joinedUrls = firstUrl + separator + mSettings.getSetting(mContext,
+            String joinedUrls = firstUrl + separator + mDependencies.getSetting(mContext,
                     Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS,
                     DEFAULT_OTHER_FALLBACK_URLS);
             List<URL> urls = new ArrayList<>();
@@ -924,7 +940,7 @@
 
     private CaptivePortalProbeSpec[] makeCaptivePortalFallbackProbeSpecs() {
         try {
-            final String settingsValue = mSettings.getSetting(
+            final String settingsValue = mDependencies.getSetting(
                     mContext, Settings.Global.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS, null);
             // Probe specs only used if configured in settings
             if (TextUtils.isEmpty(settingsValue)) {
@@ -940,7 +956,7 @@
     }
 
     private String getCaptivePortalUserAgent() {
-        return mSettings.getSetting(mContext,
+        return mDependencies.getSetting(mContext,
                 Settings.Global.CAPTIVE_PORTAL_USER_AGENT, DEFAULT_USER_AGENT);
     }
 
@@ -949,7 +965,7 @@
             return null;
         }
         int idx = Math.abs(mNextFallbackUrlIndex) % mCaptivePortalFallbackUrls.length;
-        mNextFallbackUrlIndex += new Random().nextInt(); // randomely change url without memory.
+        mNextFallbackUrlIndex += mRandom.nextInt(); // randomly change url without memory.
         return mCaptivePortalFallbackUrls[idx];
     }
 
@@ -958,7 +974,7 @@
             return null;
         }
         // Randomly change spec without memory. Also randomize the first attempt.
-        final int idx = Math.abs(new Random().nextInt()) % mCaptivePortalFallbackSpecs.length;
+        final int idx = Math.abs(mRandom.nextInt()) % mCaptivePortalFallbackSpecs.length;
         return mCaptivePortalFallbackSpecs[idx];
     }
 
@@ -1376,15 +1392,15 @@
     }
 
     @VisibleForTesting
-    public interface NetworkMonitorSettings {
-        int getSetting(Context context, String symbol, int defaultValue);
-        String getSetting(Context context, String symbol, String defaultValue);
+    public static class Dependencies {
+        public Network getNetwork(NetworkAgentInfo networkAgentInfo) {
+            return new OneAddressPerFamilyNetwork(networkAgentInfo.network());
+        }
 
-        static NetworkMonitorSettings DEFAULT = new DefaultNetworkMonitorSettings();
-    }
+        public Random getRandom() {
+            return new Random();
+        }
 
-    @VisibleForTesting
-    public static class DefaultNetworkMonitorSettings implements NetworkMonitorSettings {
         public int getSetting(Context context, String symbol, int defaultValue) {
             return Settings.Global.getInt(context.getContentResolver(), symbol, defaultValue);
         }
@@ -1393,5 +1409,7 @@
             final String value = Settings.Global.getString(context.getContentResolver(), symbol);
             return value != null ? value : defaultValue;
         }
+
+        public static final Dependencies DEFAULT = new Dependencies();
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/OWNERS b/services/core/java/com/android/server/connectivity/OWNERS
index ce50558..7311eee 100644
--- a/services/core/java/com/android/server/connectivity/OWNERS
+++ b/services/core/java/com/android/server/connectivity/OWNERS
@@ -1,6 +1,8 @@
 set noparent
 
+codewiz@google.com
 ek@google.com
 jchalard@google.com
 lorenzo@google.com
+reminv@google.com
 satk@google.com
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 5105941..84bdbba 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -115,7 +115,6 @@
 import com.android.server.connectivity.tethering.IControlsTethering;
 import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
 import com.android.server.connectivity.tethering.OffloadController;
-import com.android.server.connectivity.tethering.SimChangeListener;
 import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
 import com.android.server.connectivity.tethering.TetheringConfiguration;
 import com.android.server.connectivity.tethering.TetheringDependencies;
@@ -201,8 +200,6 @@
     // into a single coherent structure.
     private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams;
     private final VersionedBroadcastListener mCarrierConfigChange;
-    // TODO: Delete SimChangeListener; it's obsolete.
-    private final SimChangeListener mSimChange;
     private final TetheringDependencies mDeps;
 
     private volatile TetheringConfiguration mConfig;
@@ -252,14 +249,6 @@
                     updateConfiguration();
                     reevaluateSimCardProvisioning();
                 });
-        // TODO: Remove SimChangeListener altogether. For now, we retain it
-        // for logging purposes in case we need to debug something that might
-        // be related to changing signals from ACTION_SIM_STATE_CHANGED to
-        // ACTION_CARRIER_CONFIG_CHANGED.
-        mSimChange = new SimChangeListener(
-                mContext, smHandler, () -> {
-                    mLog.log("OBSERVED SIM card change");
-                });
 
         mStateReceiver = new StateReceiver();
 
@@ -1530,7 +1519,6 @@
                     return;
                 }
 
-                mSimChange.startListening();
                 mUpstreamNetworkMonitor.start(mDeps.getDefaultNetworkRequest());
 
                 // TODO: De-duplicate with updateUpstreamWanted() below.
@@ -1546,7 +1534,6 @@
             public void exit() {
                 mOffload.stop();
                 mUpstreamNetworkMonitor.stop();
-                mSimChange.stopListening();
                 notifyDownstreamsOfNewUpstreamIface(null);
                 handleNewUpstreamNetworkState(null);
             }
diff --git a/services/core/java/com/android/server/connectivity/tethering/SimChangeListener.java b/services/core/java/com/android/server/connectivity/tethering/SimChangeListener.java
deleted file mode 100644
index 33c9355..0000000
--- a/services/core/java/com/android/server/connectivity/tethering/SimChangeListener.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.connectivity.tethering;
-
-import static com.android.internal.telephony.IccCardConstants.INTENT_VALUE_ICC_LOADED;
-import static com.android.internal.telephony.IccCardConstants.INTENT_KEY_ICC_STATE;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.util.VersionedBroadcastListener;
-import android.net.util.VersionedBroadcastListener.IntentCallback;
-import android.os.Handler;
-import android.util.Log;
-
-import com.android.internal.telephony.TelephonyIntents;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
-
-
-/**
- * A utility class that runs the provided callback on the provided handler when
- * observing a new SIM card having been loaded.
- *
- * @hide
- */
-public class SimChangeListener extends VersionedBroadcastListener {
-    private static final String TAG = SimChangeListener.class.getSimpleName();
-    private static final boolean DBG = false;
-
-    public SimChangeListener(Context ctx, Handler handler, Runnable onSimCardLoadedCallback) {
-        super(TAG, ctx, handler, makeIntentFilter(), makeCallback(onSimCardLoadedCallback));
-    }
-
-    private static IntentFilter makeIntentFilter() {
-        final IntentFilter filter = new IntentFilter();
-        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
-        return filter;
-    }
-
-    private static Consumer<Intent> makeCallback(Runnable onSimCardLoadedCallback) {
-        return new Consumer<Intent>() {
-            private boolean mSimNotLoadedSeen = false;
-
-            @Override
-            public void accept(Intent intent) {
-                final String state = intent.getStringExtra(INTENT_KEY_ICC_STATE);
-                Log.d(TAG, "got Sim changed to state " + state + ", mSimNotLoadedSeen=" +
-                        mSimNotLoadedSeen);
-
-                if (!INTENT_VALUE_ICC_LOADED.equals(state)) {
-                    mSimNotLoadedSeen = true;
-                    return;
-                }
-
-                if (mSimNotLoadedSeen) {
-                    mSimNotLoadedSeen = false;
-                    onSimCardLoadedCallback.run();
-                }
-            }
-        };
-    }
-}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index fbee86a..9e6b659 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -379,7 +379,7 @@
                     // that adding routes that already exist does not cause an
                     // error (EEXIST is silently ignored).
                     mNMService.addInterfaceToLocalNetwork(mIfaceName, toBeAdded);
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     mLog.e("Failed to add IPv6 routes to local table: " + e);
                 }
 
diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
index 089632d..bfcc629 100644
--- a/services/core/java/com/android/server/content/SyncJobService.java
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -16,12 +16,10 @@
 
 package com.android.server.content;
 
+import android.annotation.Nullable;
 import android.app.job.JobParameters;
 import android.app.job.JobService;
-import android.content.Intent;
 import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.Slog;
@@ -34,78 +32,86 @@
 public class SyncJobService extends JobService {
     private static final String TAG = "SyncManager";
 
-    public static final String EXTRA_MESSENGER = "messenger";
+    private static final Object sLock = new Object();
 
-    private Messenger mMessenger;
+    @GuardedBy("sLock")
+    private static SyncJobService sInstance;
 
-    private final Object mLock = new Object();
+    @GuardedBy("sLock")
+    private static final SparseArray<JobParameters> sJobParamsMap = new SparseArray<>();
 
-    @GuardedBy("mLock")
-    private final SparseArray<JobParameters> mJobParamsMap = new SparseArray<>();
+    @GuardedBy("sLock")
+    private static final SparseBooleanArray sStartedSyncs = new SparseBooleanArray();
 
-    @GuardedBy("mLock")
-    private final SparseBooleanArray mStartedSyncs = new SparseBooleanArray();
+    @GuardedBy("sLock")
+    private static final SparseLongArray sJobStartUptimes = new SparseLongArray();
 
-    @GuardedBy("mLock")
-    private final SparseLongArray mJobStartUptimes = new SparseLongArray();
+    private static final SyncLogger sLogger = SyncLogger.getInstance();
 
-    private final SyncLogger mLogger = SyncLogger.getInstance();
-
-    /**
-     * This service is started by the SyncManager which passes a messenger object to
-     * communicate back with it. It never stops while the device is running.
-     */
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        mMessenger = intent.getParcelableExtra(EXTRA_MESSENGER);
-        Message m = Message.obtain();
-        m.what = SyncManager.SyncHandler.MESSAGE_JOBSERVICE_OBJECT;
-        m.obj = this;
-        sendMessage(m);
-
-        return START_NOT_STICKY;
+    private void updateInstance() {
+        synchronized (SyncJobService.class) {
+            sInstance = this;
+        }
     }
 
-    private void sendMessage(Message message) {
-        if (mMessenger == null) {
-            Slog.e(TAG, "Messenger not initialized.");
-            return;
+    @Nullable
+    private static SyncJobService getInstance() {
+        synchronized (sLock) {
+            if (sInstance == null) {
+                Slog.wtf(TAG, "sInstance == null");
+            }
+            return sInstance;
         }
-        try {
-            mMessenger.send(message);
-        } catch (RemoteException e) {
-            Slog.e(TAG, e.toString());
+    }
+
+    public static boolean isReady() {
+        synchronized (sLock) {
+            return sInstance != null;
         }
     }
 
     @Override
     public boolean onStartJob(JobParameters params) {
+        updateInstance();
 
-        mLogger.purgeOldLogs();
+        sLogger.purgeOldLogs();
+
+        SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
+
+        if (op == null) {
+            Slog.wtf(TAG, "Got invalid job " + params.getJobId());
+            return false;
+        }
+
+        final boolean readyToSync = SyncManager.readyToSync(op.target.userId);
+
+        sLogger.log("onStartJob() jobid=", params.getJobId(), " op=", op,
+                " readyToSync", readyToSync);
+
+        if (!readyToSync) {
+            // If the user isn't unlocked or the device has been provisioned yet, just stop the job
+            // at this point. If it's a non-periodic sync, ask the job scheduler to reschedule it.
+            // If it's a periodic sync, then just wait until the next cycle.
+            final boolean wantsReschedule = !op.isPeriodic;
+            jobFinished(params, wantsReschedule);
+            return true;
+        }
 
         boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
-        synchronized (mLock) {
+        synchronized (sLock) {
             final int jobId = params.getJobId();
-            mJobParamsMap.put(jobId, params);
+            sJobParamsMap.put(jobId, params);
 
-            mStartedSyncs.delete(jobId);
-            mJobStartUptimes.put(jobId, SystemClock.uptimeMillis());
+            sStartedSyncs.delete(jobId);
+            sJobStartUptimes.put(jobId, SystemClock.uptimeMillis());
         }
         Message m = Message.obtain();
         m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC;
-        SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
-
-        mLogger.log("onStartJob() jobid=", params.getJobId(), " op=", op);
-
-        if (op == null) {
-            Slog.e(TAG, "Got invalid job " + params.getJobId());
-            return false;
-        }
         if (isLoggable) {
             Slog.v(TAG, "Got start job message " + op.target);
         }
         m.obj = op;
-        sendMessage(m);
+        SyncManager.sendMessage(m);
         return true;
     }
 
@@ -115,15 +121,22 @@
             Slog.v(TAG, "onStopJob called " + params.getJobId() + ", reason: "
                     + params.getStopReason());
         }
-        final boolean readyToSync = SyncManager.readyToSync();
+        final SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
+        if (op == null) {
+            Slog.wtf(TAG, "Got invalid job " + params.getJobId());
+            return false;
+        }
 
-        mLogger.log("onStopJob() ", mLogger.jobParametersToString(params),
+        final boolean readyToSync = SyncManager.readyToSync(op.target.userId);
+
+        sLogger.log("onStopJob() ", sLogger.jobParametersToString(params),
                 " readyToSync=", readyToSync);
-        synchronized (mLock) {
-            final int jobId = params.getJobId();
-            mJobParamsMap.remove(jobId);
 
-            final long startUptime = mJobStartUptimes.get(jobId);
+        synchronized (sLock) {
+            final int jobId = params.getJobId();
+            sJobParamsMap.remove(jobId);
+
+            final long startUptime = sJobStartUptimes.get(jobId);
             final long nowUptime = SystemClock.uptimeMillis();
             final long runtime = nowUptime - startUptime;
 
@@ -135,61 +148,57 @@
                 // WTF if startSyncH() hasn't happened, *unless* onStopJob() was called too soon.
                 // (1 minute threshold.)
                 // Also don't wtf when it's not ready to sync.
-                if (readyToSync && !mStartedSyncs.get(jobId)) {
+                if (readyToSync && !sStartedSyncs.get(jobId)) {
                     wtf("Job " + jobId + " didn't start: "
                             + " startUptime=" + startUptime
                             + " nowUptime=" + nowUptime
                             + " params=" + jobParametersToString(params));
                 }
-            } else if (runtime < 10 * 1000) {
-                // This happens too in a normal case too, and it's rather too often.
-                // Disable it for now.
-//                // Job stopped too soon. WTF.
-//                wtf("Job " + jobId + " stopped in " + runtime + " ms: "
-//                        + " startUptime=" + startUptime
-//                        + " nowUptime=" + nowUptime
-//                        + " params=" + jobParametersToString(params));
             }
 
-            mStartedSyncs.delete(jobId);
-            mJobStartUptimes.delete(jobId);
+            sStartedSyncs.delete(jobId);
+            sJobStartUptimes.delete(jobId);
         }
         Message m = Message.obtain();
         m.what = SyncManager.SyncHandler.MESSAGE_STOP_SYNC;
-        m.obj = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
-        if (m.obj == null) {
-            return false;
-        }
+        m.obj = op;
 
         // Reschedule if this job was NOT explicitly canceled.
         m.arg1 = params.getStopReason() != JobParameters.REASON_CANCELED ? 1 : 0;
         // Apply backoff only if stop is called due to timeout.
         m.arg2 = params.getStopReason() == JobParameters.REASON_TIMEOUT ? 1 : 0;
 
-        sendMessage(m);
+        SyncManager.sendMessage(m);
         return false;
     }
 
-    public void callJobFinished(int jobId, boolean needsReschedule, String why) {
-        synchronized (mLock) {
-            JobParameters params = mJobParamsMap.get(jobId);
-            mLogger.log("callJobFinished()",
+    public static void callJobFinished(int jobId, boolean needsReschedule, String why) {
+        final SyncJobService instance = getInstance();
+        if (instance != null) {
+            instance.callJobFinishedInner(jobId, needsReschedule, why);
+        }
+    }
+
+    public void callJobFinishedInner(int jobId, boolean needsReschedule, String why) {
+        synchronized (sLock) {
+            JobParameters params = sJobParamsMap.get(jobId);
+            sLogger.log("callJobFinished()",
                     " jobid=", jobId,
                     " needsReschedule=", needsReschedule,
-                    " ", mLogger.jobParametersToString(params),
+                    " ", sLogger.jobParametersToString(params),
                     " why=", why);
             if (params != null) {
                 jobFinished(params, needsReschedule);
-                mJobParamsMap.remove(jobId);
+                sJobParamsMap.remove(jobId);
             } else {
                 Slog.e(TAG, "Job params not found for " + String.valueOf(jobId));
             }
         }
     }
 
-    public void markSyncStarted(int jobId) {
-        synchronized (mLock) {
-            mStartedSyncs.put(jobId, true);
+    public static void markSyncStarted(int jobId) {
+        synchronized (sLock) {
+            sStartedSyncs.put(jobId, true);
         }
     }
 
@@ -203,8 +212,8 @@
         }
     }
 
-    private void wtf(String message) {
-        mLogger.log(message);
+    private static void wtf(String message) {
+        sLogger.log(message);
         Slog.wtf(TAG, message);
     }
 }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 0a640b8..f4d20b3 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -21,6 +21,7 @@
 import android.accounts.AccountManager;
 import android.accounts.AccountManagerInternal;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
@@ -72,7 +73,6 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Messenger;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallback;
@@ -89,6 +89,7 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
+import android.util.SparseBooleanArray;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -227,7 +228,6 @@
     // TODO: add better locking around mRunningAccounts
     private volatile AccountAndUser[] mRunningAccounts = INITIAL_ACCOUNTS_ARRAY;
 
-    volatile private PowerManager.WakeLock mHandleAlarmWakeLock;
     volatile private PowerManager.WakeLock mSyncManagerWakeLock;
     volatile private boolean mDataConnectionIsConnected = false;
     volatile private boolean mStorageIsLow = false;
@@ -238,7 +238,6 @@
     private final IBatteryStats mBatteryStats;
     private JobScheduler mJobScheduler;
     private JobSchedulerInternal mJobSchedulerInternal;
-    private SyncJobService mSyncJobService;
 
     private SyncStorageEngine mSyncStorageEngine;
 
@@ -318,16 +317,6 @@
                 }
             };
 
-    private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            mBootCompleted = true;
-            // Called because it gets all pending jobs and stores them in mScheduledSyncs cache.
-            verifyJobScheduler();
-            mSyncHandler.onBootCompleted();
-        }
-    };
-
     private final BroadcastReceiver mAccountsUpdatedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -371,14 +360,14 @@
         m.sendToTarget();
     }
 
-    private void doDatabaseCleanup() {
+    private void removeStaleAccounts() {
         for (UserInfo user : mUserManager.getUsers(true)) {
             // Skip any partially created/removed users
             if (user.partial) continue;
             Account[] accountsForUser = AccountManagerService.getSingleton().getAccounts(
                     user.id, mContext.getOpPackageName());
 
-            mSyncStorageEngine.doDatabaseCleanup(accountsForUser, user.id);
+            mSyncStorageEngine.removeStaleAccounts(accountsForUser, user.id);
         }
     }
 
@@ -464,8 +453,8 @@
     private final SyncHandler mSyncHandler;
     private final SyncManagerConstants mConstants;
 
-    private volatile boolean mBootCompleted = false;
-    private volatile boolean mJobServiceReady = false;
+    @GuardedBy("mUnlockedUsers")
+    private final SparseBooleanArray mUnlockedUsers = new SparseBooleanArray();
 
     private ConnectivityManager getConnectivityManager() {
         synchronized (this) {
@@ -641,12 +630,6 @@
         IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
         context.registerReceiver(mConnectivityIntentReceiver, intentFilter);
 
-        if (!factoryTest) {
-            intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
-            intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
-            context.registerReceiver(mBootCompletedReceiver, intentFilter);
-        }
-
         intentFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW);
         intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
         context.registerReceiver(mStorageIntentReceiver, intentFilter);
@@ -690,14 +673,6 @@
         mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
                 BatteryStats.SERVICE_NAME));
 
-        // This WakeLock is used to ensure that we stay awake between the time that we receive
-        // a sync alarm notification and when we finish processing it. We need to do this
-        // because we don't do the work in the alarm handler, rather we do it in a message
-        // handler.
-        mHandleAlarmWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
-                HANDLE_SYNC_ALARM_WAKE_LOCK);
-        mHandleAlarmWakeLock.setReferenceCounted(false);
-
         // This WakeLock is used to ensure that we stay awake while running the sync loop
         // message handler. Normally we will hold a sync adapter wake lock while it is being
         // synced but during the execution of the sync loop it might finish a sync for
@@ -715,7 +690,6 @@
                         public void onChange(boolean selfChange) {
                             mProvisioned |= isDeviceProvisioned();
                             if (mProvisioned) {
-                                mSyncHandler.onDeviceProvisioned();
                                 resolver.unregisterContentObserver(this);
                             }
                         }
@@ -744,19 +718,6 @@
                     null, null);
         }
 
-        // Set up the communication channel between the scheduled job and the sync manager.
-        // This is posted to the *main* looper intentionally, to defer calling startService()
-        // until after the lengthy primary boot sequence completes on that thread, to avoid
-        // spurious ANR triggering.
-        final Intent startServiceIntent = new Intent(mContext, SyncJobService.class);
-        startServiceIntent.putExtra(SyncJobService.EXTRA_MESSENGER, new Messenger(mSyncHandler));
-        new Handler(mContext.getMainLooper()).post(new Runnable() {
-            @Override
-            public void run() {
-                mContext.startService(startServiceIntent);
-            }
-        });
-
         // Sync adapters were able to access the synced account without the accounts
         // permission which circumvents our permission model. Therefore, we require
         // sync adapters that don't have access to the account to get user consent.
@@ -768,16 +729,31 @@
         mLogger.log("Sync manager initialized: " + Build.FINGERPRINT);
     }
 
-    public void onStartUser(int userHandle) {
-        mSyncHandler.post(() -> mLogger.log("onStartUser: user=", userHandle));
+    public void onStartUser(int userId) {
+        // Log on the handler to avoid slowing down device boot.
+        mSyncHandler.post(() -> mLogger.log("onStartUser: user=", userId));
     }
 
-    public void onUnlockUser(int userHandle) {
-        mSyncHandler.post(() -> mLogger.log("onUnlockUser: user=", userHandle));
+    public void onUnlockUser(int userId) {
+        synchronized (mUnlockedUsers) {
+            mUnlockedUsers.put(userId, true);
+        }
+        // Log on the handler to avoid slowing down device boot.
+        mSyncHandler.post(() -> mLogger.log("onUnlockUser: user=", userId));
     }
 
-    public void onStopUser(int userHandle) {
-        mSyncHandler.post(() -> mLogger.log("onStopUser: user=", userHandle));
+    public void onStopUser(int userId) {
+        synchronized (mUnlockedUsers) {
+            mUnlockedUsers.put(userId, false);
+        }
+        // Log on the handler to avoid slowing down user switch.
+        mSyncHandler.post(() -> mLogger.log("onStopUser: user=", userId));
+    }
+
+    private boolean isUserUnlocked(int userId) {
+        synchronized (mUnlockedUsers) {
+            return mUnlockedUsers.get(userId);
+        }
     }
 
     public void onBootPhase(int phase) {
@@ -1038,12 +1014,7 @@
                     Bundle finalExtras = new Bundle(extras);
                     String packageName = syncAdapterInfo.componentName.getPackageName();
                     // If the app did not run and has no account access, done
-                    try {
-                        if (!mPackageManagerInternal.wasPackageEverLaunched(packageName, userId)) {
-                            continue;
-                        }
-                    } catch (IllegalArgumentException e) {
-                        // Package not found, race with an uninstall
+                    if (!wasPackageEverLaunched(packageName, userId)) {
                         continue;
                     }
                     mAccountManagerInternal.requestAccountAccess(account.account,
@@ -1820,7 +1791,7 @@
         updateRunningAccounts(null /* Don't sync any target */);
 
         // Clean up the storage engine database
-        mSyncStorageEngine.doDatabaseCleanup(new Account[0], userId);
+        mSyncStorageEngine.removeStaleAccounts(null, userId);
         List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (op.target.userId == userId) {
@@ -2235,8 +2206,13 @@
         mSyncStorageEngine.resetTodayStats(/* force=*/ false);
 
         for (AccountAndUser account : accounts) {
-            pw.printf("Account %s u%d %s\n",
-                    account.account.name, account.userId, account.account.type);
+            final boolean unlocked;
+            synchronized (mUnlockedUsers) {
+                unlocked = mUnlockedUsers.get(account.userId);
+            }
+            pw.printf("Account %s u%d %s%s\n",
+                    account.account.name, account.userId, account.account.type,
+                    (unlocked ? "" : " (locked)"));
 
             pw.println("=======================================================================");
             final PrintTable table = new PrintTable(16);
@@ -2872,13 +2848,29 @@
         }
     }
 
-    /**
-     * @return whether the device is ready to run sync jobs.
-     */
-    public static boolean readyToSync() {
+    @Nullable
+    private static SyncManager getInstance() {
         synchronized (SyncManager.class) {
-            return sInstance != null && sInstance.mProvisioned && sInstance.mBootCompleted
-                    && sInstance.mJobServiceReady;
+            if (sInstance == null) {
+                Slog.wtf(TAG, "sInstance == null"); // Maybe called too early?
+            }
+            return sInstance;
+        }
+    }
+
+    /**
+     * @return whether the device is ready to run sync jobs for a given user.
+     */
+    public static boolean readyToSync(int userId) {
+        final SyncManager instance = getInstance();
+        return (instance != null) && SyncJobService.isReady()
+                && instance.mProvisioned && instance.isUserUnlocked(userId);
+    }
+
+    public static void sendMessage(Message message) {
+        final SyncManager instance = getInstance();
+        if (instance != null) {
+            instance.mSyncHandler.sendMessage(message);
         }
     }
 
@@ -2889,11 +2881,9 @@
     class SyncHandler extends Handler {
         // Messages that can be sent on mHandler.
         private static final int MESSAGE_SYNC_FINISHED = 1;
-        private static final int MESSAGE_RELEASE_MESSAGES_FROM_QUEUE = 2;
         private static final int MESSAGE_SERVICE_CONNECTED = 4;
         private static final int MESSAGE_SERVICE_DISCONNECTED = 5;
         private static final int MESSAGE_CANCEL = 6;
-        static final int MESSAGE_JOBSERVICE_OBJECT = 7;
         static final int MESSAGE_START_SYNC = 10;
         static final int MESSAGE_STOP_SYNC = 11;
         static final int MESSAGE_SCHEDULE_SYNC = 12;
@@ -2910,86 +2900,17 @@
         public final SyncTimeTracker mSyncTimeTracker = new SyncTimeTracker();
         private final HashMap<String, PowerManager.WakeLock> mWakeLocks = Maps.newHashMap();
 
-        private List<Message> mUnreadyQueue = new ArrayList<Message>();
-
-        void onBootCompleted() {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Slog.v(TAG, "Boot completed.");
-            }
-            checkIfDeviceReady();
-        }
-
-        void onDeviceProvisioned() {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "mProvisioned=" + mProvisioned);
-            }
-            checkIfDeviceReady();
-        }
-
-        void checkIfDeviceReady() {
-            if (mProvisioned && mBootCompleted && mJobServiceReady) {
-                synchronized(this) {
-                    mSyncStorageEngine.restoreAllPeriodicSyncs();
-                    // Dispatch any stashed messages.
-                    obtainMessage(MESSAGE_RELEASE_MESSAGES_FROM_QUEUE).sendToTarget();
-                }
-            }
-        }
-
-        /**
-         * Stash any messages that come to the handler before boot is complete or before the device
-         * is properly provisioned (i.e. out of set-up wizard).
-         * {@link #onBootCompleted()} and {@link SyncHandler#onDeviceProvisioned} both
-         * need to come in before we start syncing.
-         * @param msg Message to dispatch at a later point.
-         * @return true if a message was enqueued, false otherwise. This is to avoid losing the
-         * message if we manage to acquire the lock but by the time we do boot has completed.
-         */
-        private boolean tryEnqueueMessageUntilReadyToRun(Message msg) {
-            synchronized (this) {
-                if (!mBootCompleted || !mProvisioned || !mJobServiceReady) {
-                    // Need to copy the message bc looper will recycle it.
-                    Message m = Message.obtain(msg);
-                    mUnreadyQueue.add(m);
-                    return true;
-                } else {
-                    return false;
-                }
-            }
-        }
-
         public SyncHandler(Looper looper) {
             super(looper);
         }
 
         public void handleMessage(Message msg) {
+            // TODO Do we really need this wake lock?? If we actually needed it, this is probably
+            // not the best place to acquire the lock -- it's probably too late, because the device
+            // could have gone to sleep before we reach here.
+            mSyncManagerWakeLock.acquire();
             try {
-                mSyncManagerWakeLock.acquire();
-                // We only want to enqueue sync related messages until device is ready.
-                // Other messages are handled without enqueuing.
-                if (msg.what == MESSAGE_JOBSERVICE_OBJECT) {
-                    Slog.i(TAG, "Got SyncJobService instance.");
-                    mSyncJobService = (SyncJobService) msg.obj;
-                    mJobServiceReady = true;
-                    checkIfDeviceReady();
-                } else if (msg.what == SyncHandler.MESSAGE_ACCOUNTS_UPDATED) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Slog.v(TAG, "handleSyncHandlerMessage: MESSAGE_ACCOUNTS_UPDATED");
-                    }
-                    EndPoint targets = (EndPoint) msg.obj;
-                    updateRunningAccountsH(targets);
-                } else if (msg.what == MESSAGE_RELEASE_MESSAGES_FROM_QUEUE) {
-                    if (mUnreadyQueue != null) {
-                        for (Message m : mUnreadyQueue) {
-                            handleSyncMessage(m);
-                        }
-                        mUnreadyQueue = null;
-                    }
-                } else if (tryEnqueueMessageUntilReadyToRun(msg)) {
-                    // No work to be done.
-                } else {
-                    handleSyncMessage(msg);
-                }
+                handleSyncMessage(msg);
             } finally {
                 mSyncManagerWakeLock.release();
             }
@@ -3001,6 +2922,13 @@
             try {
                 mDataConnectionIsConnected = readDataConnectionState();
                 switch (msg.what) {
+                    case MESSAGE_ACCOUNTS_UPDATED:
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Slog.v(TAG, "handleSyncHandlerMessage: MESSAGE_ACCOUNTS_UPDATED");
+                        }
+                        EndPoint targets = (EndPoint) msg.obj;
+                        updateRunningAccountsH(targets);
+                        break;
                     case MESSAGE_SCHEDULE_SYNC:
                         ScheduleSyncMessagePayload syncPayload =
                                 (ScheduleSyncMessagePayload) msg.obj;
@@ -3069,7 +2997,7 @@
                         if (isLoggable) {
                             Slog.v(TAG, "syncFinished" + payload.activeSyncContext.mSyncOperation);
                         }
-                        mSyncJobService.callJobFinished(
+                        SyncJobService.callJobFinished(
                                 payload.activeSyncContext.mSyncOperation.jobId, false,
                                 "sync finished");
                         runSyncFinishedOrCanceledH(payload.syncResult,
@@ -3119,7 +3047,7 @@
                             // which is a soft error.
                             SyncResult syncResult = new SyncResult();
                             syncResult.stats.numIoExceptions++;
-                            mSyncJobService.callJobFinished(
+                            SyncJobService.callJobFinished(
                                     currentSyncContext.mSyncOperation.jobId, false,
                                     "service disconnected");
                             runSyncFinishedOrCanceledH(syncResult, currentSyncContext);
@@ -3138,7 +3066,7 @@
                             Log.w(TAG, String.format(
                                     "Detected sync making no progress for %s. cancelling.",
                                     monitoredSyncContext));
-                            mSyncJobService.callJobFinished(
+                            SyncJobService.callJobFinished(
                                     monitoredSyncContext.mSyncOperation.jobId, false,
                                     "no network activity");
                             runSyncFinishedOrCanceledH(
@@ -3175,7 +3103,7 @@
         private void deferSyncH(SyncOperation op, long delay, String why) {
             mLogger.log("deferSyncH() ", (op.isPeriodic ? "periodic " : ""),
                     "sync.  op=", op, " delay=", delay, " why=", why);
-            mSyncJobService.callJobFinished(op.jobId, false, why);
+            SyncJobService.callJobFinished(op.jobId, false, why);
             if (op.isPeriodic) {
                 scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
             } else {
@@ -3213,7 +3141,7 @@
             // assume the clock is correct.
             mSyncStorageEngine.setClockValid();
 
-            mSyncJobService.markSyncStarted(op.jobId);
+            SyncJobService.markSyncStarted(op.jobId);
 
             if (mStorageIsLow) {
                 deferSyncH(op, SYNC_DELAY_ON_LOW_STORAGE, "storage low");
@@ -3226,7 +3154,7 @@
                 List<SyncOperation> ops = getAllPendingSyncs();
                 for (SyncOperation syncOperation: ops) {
                     if (syncOperation.sourcePeriodicId == op.jobId) {
-                        mSyncJobService.callJobFinished(op.jobId, false,
+                        SyncJobService.callJobFinished(op.jobId, false,
                                 "periodic sync, pending");
                         return;
                     }
@@ -3235,7 +3163,7 @@
                 // executing according to some backoff criteria.
                 for (ActiveSyncContext asc: mActiveSyncContexts) {
                     if (asc.mSyncOperation.sourcePeriodicId == op.jobId) {
-                        mSyncJobService.callJobFinished(op.jobId, false,
+                        SyncJobService.callJobFinished(op.jobId, false,
                                 "periodic sync, already running");
                         return;
                     }
@@ -3272,13 +3200,13 @@
             switch (syncOpState) {
                 case SYNC_OP_STATE_INVALID_NO_ACCOUNT_ACCESS:
                 case SYNC_OP_STATE_INVALID: {
-                    mSyncJobService.callJobFinished(op.jobId, false,
+                    SyncJobService.callJobFinished(op.jobId, false,
                             "invalid op state: " + syncOpState);
                 } return;
             }
 
             if (!dispatchSyncOperation(op)) {
-                mSyncJobService.callJobFinished(op.jobId, false, "dispatchSyncOperation() failed");
+                SyncJobService.callJobFinished(op.jobId, false, "dispatchSyncOperation() failed");
             }
 
             setAuthorityPendingState(op.target);
@@ -3306,9 +3234,7 @@
             if (mLogger.enabled()) {
                 mLogger.log("updateRunningAccountsH: ", Arrays.toString(mRunningAccounts));
             }
-            if (mBootCompleted) {
-                doDatabaseCleanup();
-            }
+            removeStaleAccounts();
 
             AccountAndUser[] accounts = mRunningAccounts;
             for (ActiveSyncContext currentSyncContext : mActiveSyncContexts) {
@@ -3421,7 +3347,7 @@
                     String packageName = op.owningPackage;
                     final int userId = UserHandle.getUserId(op.owningUid);
                     // If the app did not run and has no account access, done
-                    if (!mPackageManagerInternal.wasPackageEverLaunched(packageName, userId)) {
+                    if (!wasPackageEverLaunched(packageName, userId)) {
                         return;
                     }
                     mAccountManagerInternal.requestAccountAccess(op.target.account,
@@ -3453,7 +3379,7 @@
                 if (op.sourcePeriodicId == syncOperation.jobId || op.jobId == syncOperation.jobId) {
                     ActiveSyncContext asc = findActiveSyncContextH(syncOperation.jobId);
                     if (asc != null) {
-                        mSyncJobService.callJobFinished(syncOperation.jobId, false,
+                        SyncJobService.callJobFinished(syncOperation.jobId, false,
                                 "removePeriodicSyncInternalH");
                         runSyncFinishedOrCanceledH(null, asc);
                     }
@@ -3662,7 +3588,7 @@
                                     false /* no config settings */)) {
                         continue;
                     }
-                    mSyncJobService.callJobFinished(activeSyncContext.mSyncOperation.jobId, false,
+                    SyncJobService.callJobFinished(activeSyncContext.mSyncOperation.jobId, false,
                             why);
                     runSyncFinishedOrCanceledH(null /* cancel => no result */, activeSyncContext);
                 }
@@ -4128,4 +4054,12 @@
     public void resetTodayStats() {
         mSyncStorageEngine.resetTodayStats(/*force=*/ true);
     }
+
+    private boolean wasPackageEverLaunched(String packageName, int userId) {
+        try {
+            return mPackageManagerInternal.wasPackageEverLaunched(packageName, userId);
+        } catch (IllegalArgumentException e) {
+            return false; // Package has been removed.
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 811dc75..391e3b0 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -19,6 +19,7 @@
 import android.accounts.Account;
 import android.accounts.AccountAndUser;
 import android.accounts.AccountManager;
+import android.annotation.Nullable;
 import android.app.backup.BackupManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -1005,7 +1006,7 @@
      * Called when the set of account has changed, given the new array of
      * active accounts.
      */
-    public void doDatabaseCleanup(Account[] accounts, int userId) {
+    public void removeStaleAccounts(@Nullable Account[] accounts, int userId) {
         synchronized (mAuthorities) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Slog.v(TAG, "Updating for new accounts...");
@@ -1014,8 +1015,9 @@
             Iterator<AccountInfo> accIt = mAccounts.values().iterator();
             while (accIt.hasNext()) {
                 AccountInfo acc = accIt.next();
-                if (!ArrayUtils.contains(accounts, acc.accountAndUser.account)
-                        && acc.accountAndUser.userId == userId) {
+                if ((accounts == null) || (
+                        (acc.accountAndUser.userId == userId)
+                        && !ArrayUtils.contains(accounts, acc.accountAndUser.account))) {
                     // This account no longer exists...
                     if (Log.isLoggable(TAG, Log.VERBOSE)) {
                         Slog.v(TAG, "Account removed: " + acc.accountAndUser);
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 1c3342a..b97e904 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -400,6 +400,7 @@
         } else if (mLightSensorEnabled) {
             mLightSensorEnabled = false;
             mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig;
+            mScreenAutoBrightness = -1;
             mRecentLightSamples = 0;
             mAmbientLightRingBuffer.clear();
             mCurrentLightSensorRate = -1;
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 4f53ed4..33525fd 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -46,6 +46,7 @@
 import libcore.io.Streams;
 
 import com.android.server.LocalServices;
+import com.android.server.policy.WindowManagerPolicy;
 
 /**
  * <p>
@@ -63,7 +64,7 @@
 
     // The layer for the electron beam surface.
     // This is currently hardcoded to be one layer above the boot animation.
-    private static final int COLOR_FADE_LAYER = 0x40000001;
+    private static final int COLOR_FADE_LAYER = WindowManagerPolicy.COLOR_FADE_LAYER;
 
     // The number of frames to draw when preparing the animation so that it will
     // be ready to run smoothly.  We use 3 frames because we are triple-buffered.
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 349e1c8..512e851 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -104,6 +104,12 @@
     public static final int FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 10;
 
     /**
+     * Flag: The display cutout of this display is masked.
+     * @hide
+     */
+    public static final int FLAG_MASK_DISPLAY_CUTOUT = 1 << 11;
+
+    /**
      * Touch attachment: Display does not receive touch.
      */
     public static final int TOUCH_NONE = 0;
@@ -453,6 +459,9 @@
         if ((flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
             msg.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD");
         }
+        if ((flags & FLAG_MASK_DISPLAY_CUTOUT) != 0) {
+            msg.append(", FLAG_MASK_DISPLAY_CUTOUT");
+        }
         return msg.toString();
     }
 }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 0a77269..0eff7f5 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -151,6 +151,8 @@
     // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
     private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
 
+    private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";
+
     private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
 
     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
@@ -243,6 +245,15 @@
     // device).
     private Point mStableDisplaySize = new Point();
 
+    // Whether the system has finished booting or not.
+    private boolean mSystemReady;
+
+    // The top inset of the default display.
+    // This gets persisted so that the boot animation knows how to transition from the display's
+    // full size to the size configured by the user. Right now we only persist and animate the top
+    // inset, but theoretically we could do it for all of them.
+    private int mDefaultDisplayTopInset;
+
     // Viewports of the default display and the display that should receive touch
     // input from an external source.  Used by the input system.
     private final DisplayViewport mDefaultViewport = new DisplayViewport();
@@ -301,6 +312,7 @@
         Resources resources = mContext.getResources();
         mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
+        mDefaultDisplayTopInset = SystemProperties.getInt(PROP_DEFAULT_DISPLAY_TOP_INSET, -1);
         float[] lux = getFloatArray(resources.obtainTypedArray(
                 com.android.internal.R.array.config_minimumBrightnessCurveLux));
         float[] nits = getFloatArray(resources.obtainTypedArray(
@@ -311,6 +323,8 @@
         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
         mCurrentUserId = UserHandle.USER_SYSTEM;
+
+        mSystemReady = false;
     }
 
     public void setupSchedulerPolicies() {
@@ -400,6 +414,10 @@
         synchronized (mSyncRoot) {
             mSafeMode = safeMode;
             mOnlyCore = onlyCore;
+            mSystemReady = true;
+            // Just in case the top inset changed before the system was ready. At this point, any
+            // relevant configuration should be in place.
+            recordTopInsetLocked(mLogicalDisplays.get(Display.DEFAULT_DISPLAY));
         }
 
         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
@@ -457,7 +475,7 @@
             LogicalDisplay display = mLogicalDisplays.get(displayId);
             if (display != null) {
                 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
-                    sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+                    handleLogicalDisplayChanged(displayId, display);
                     scheduleTraversalLocked(false);
                 }
             }
@@ -938,6 +956,13 @@
         scheduleTraversalLocked(false);
     }
 
+    private void handleLogicalDisplayChanged(int displayId, @NonNull LogicalDisplay display) {
+        if (displayId == Display.DEFAULT_DISPLAY) {
+            recordTopInsetLocked(display);
+        }
+        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+    }
+
     private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
         final int count = mDisplayDevices.size();
         for (int i = 0; i < count; i++) {
@@ -991,6 +1016,7 @@
         configureColorModeLocked(display, device);
         if (isDefault) {
             recordStableDisplayStatsIfNeededLocked(display);
+            recordTopInsetLocked(display);
         }
 
         mLogicalDisplays.put(displayId, display);
@@ -1039,6 +1065,21 @@
         }
     }
 
+    private void recordTopInsetLocked(@Nullable LogicalDisplay d) {
+        // We must only persist the inset after boot has completed, otherwise we will end up
+        // overwriting the persisted value before the masking flag has been loaded from the
+        // resource overlay.
+        if (!mSystemReady || d == null) {
+            return;
+        }
+        int topInset = d.getInsets().top;
+        if (topInset == mDefaultDisplayTopInset) {
+            return;
+        }
+        mDefaultDisplayTopInset = topInset;
+        SystemProperties.set(PROP_DEFAULT_DISPLAY_TOP_INSET, Integer.toString(topInset));
+    }
+
     private void setStableDisplaySizeLocked(int width, int height) {
         mStableDisplaySize = new Point(width, height);
         try {
@@ -1118,7 +1159,7 @@
                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
                 changed = true;
             } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
-                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+                handleLogicalDisplayChanged(displayId, display);
                 changed = true;
             }
         }
@@ -2165,6 +2206,24 @@
         }
 
         @Override
+        public boolean screenshot(int displayId, Surface outSurface) {
+            synchronized (mSyncRoot) {
+                final LogicalDisplay display = mLogicalDisplays.get(displayId);
+                if (display != null) {
+                    final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
+                    if (device != null) {
+                        final IBinder token = device.getDisplayTokenLocked();
+                        if (token != null) {
+                            SurfaceControl.screenshot(token, outSurface);
+                            return true;
+                        }
+                    }
+                }
+            }
+            return false;
+        }
+
+        @Override
         public DisplayInfo getDisplayInfo(int displayId) {
             return getDisplayInfoInternal(displayId, Process.myUid());
         }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 99412c5..e2c8ef9 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -791,9 +791,6 @@
                     && mAutomaticBrightnessController != null;
 
         final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
-        if (userSetBrightnessChanged) {
-            mTemporaryScreenBrightness = -1;
-        }
 
         // Use the temporary screen brightness if there isn't an override, either from
         // WindowManager or based on the display state.
@@ -1514,11 +1511,13 @@
         }
         if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
             mPendingScreenBrightnessSetting = -1;
+            mTemporaryScreenBrightness = -1;
             return false;
         }
         mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
         mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
         mPendingScreenBrightnessSetting = -1;
+        mTemporaryScreenBrightness = -1;
         return true;
     }
 
@@ -1660,8 +1659,10 @@
         pw.println("  mReportedToPolicy=" +
                 reportedToPolicyToString(mReportedScreenStateToPolicy));
 
-        pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
-                mScreenBrightnessRampAnimator.isAnimating());
+        if (mScreenBrightnessRampAnimator != null) {
+            pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
+                    mScreenBrightnessRampAnimator.isAnimating());
+        }
 
         if (mColorFadeOnAnimator != null) {
             pw.println("  mColorFadeOnAnimator.isStarted()=" +
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index b9a279a..16d82df 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -31,8 +31,6 @@
 import android.os.PowerManager;
 import android.os.SystemProperties;
 import android.os.Trace;
-import android.text.TextUtils;
-import android.util.PathParser;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
@@ -404,8 +402,12 @@
                             && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
                         mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
                     }
-                    mInfo.displayCutout = DisplayCutout.fromResources(res, mInfo.width,
-                            mInfo.height);
+                    if (res.getBoolean(
+                            com.android.internal.R.bool.config_maskMainBuiltInDisplayCutout)) {
+                        mInfo.flags |= DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT;
+                    }
+                    mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res,
+                            mInfo.width, mInfo.height);
                     mInfo.type = Display.TYPE_BUILT_IN;
                     mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
                     mInfo.xDpi = phys.xDpi;
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 23ee56b..5b7c520 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -18,11 +18,14 @@
 
 import android.graphics.Rect;
 import android.hardware.display.DisplayManagerInternal;
+import android.os.SystemProperties;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.SurfaceControl;
 
+import com.android.server.wm.utils.InsetUtils;
+
 import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.List;
@@ -55,6 +58,8 @@
  * </p>
  */
 final class LogicalDisplay {
+    private static final String PROP_MASKING_INSET_TOP = "persist.sys.displayinset.top";
+
     private final DisplayInfo mBaseDisplayInfo = new DisplayInfo();
 
     // The layer stack we use when the display has been blanked to prevent any
@@ -251,14 +256,18 @@
             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
                 mBaseDisplayInfo.flags |= Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
             }
+            Rect maskingInsets = getMaskingInsets(deviceInfo);
+            int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right;
+            int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom;
+
             mBaseDisplayInfo.type = deviceInfo.type;
             mBaseDisplayInfo.address = deviceInfo.address;
             mBaseDisplayInfo.name = deviceInfo.name;
             mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId;
-            mBaseDisplayInfo.appWidth = deviceInfo.width;
-            mBaseDisplayInfo.appHeight = deviceInfo.height;
-            mBaseDisplayInfo.logicalWidth = deviceInfo.width;
-            mBaseDisplayInfo.logicalHeight = deviceInfo.height;
+            mBaseDisplayInfo.appWidth = maskedWidth;
+            mBaseDisplayInfo.appHeight = maskedHeight;
+            mBaseDisplayInfo.logicalWidth = maskedWidth;
+            mBaseDisplayInfo.logicalHeight = maskedHeight;
             mBaseDisplayInfo.rotation = Surface.ROTATION_0;
             mBaseDisplayInfo.modeId = deviceInfo.modeId;
             mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId;
@@ -275,13 +284,15 @@
             mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos;
             mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos;
             mBaseDisplayInfo.state = deviceInfo.state;
-            mBaseDisplayInfo.smallestNominalAppWidth = deviceInfo.width;
-            mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height;
-            mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width;
-            mBaseDisplayInfo.largestNominalAppHeight = deviceInfo.height;
+            mBaseDisplayInfo.smallestNominalAppWidth = maskedWidth;
+            mBaseDisplayInfo.smallestNominalAppHeight = maskedHeight;
+            mBaseDisplayInfo.largestNominalAppWidth = maskedWidth;
+            mBaseDisplayInfo.largestNominalAppHeight = maskedHeight;
             mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid;
             mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName;
-            mBaseDisplayInfo.displayCutout = deviceInfo.displayCutout;
+            boolean maskCutout =
+                    (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
+            mBaseDisplayInfo.displayCutout = maskCutout ? null : deviceInfo.displayCutout;
 
             mPrimaryDisplayDeviceInfo = deviceInfo;
             mInfo = null;
@@ -289,6 +300,29 @@
     }
 
     /**
+     * Return the insets currently applied to the display.
+     *
+     * Note that the base DisplayInfo already takes these insets into account, so if you want to
+     * find out the <b>true</b> size of the display, you need to add them back to the logical
+     * dimensions.
+     */
+    public Rect getInsets() {
+        return getMaskingInsets(mPrimaryDisplayDeviceInfo);
+    }
+
+    /**
+     * Returns insets in ROTATION_0 for areas that are masked.
+     */
+    private static Rect getMaskingInsets(DisplayDeviceInfo deviceInfo) {
+        boolean maskCutout = (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
+        if (maskCutout && deviceInfo.displayCutout != null) {
+            return deviceInfo.displayCutout.getSafeInsets();
+        } else {
+            return new Rect();
+        }
+    }
+
+    /**
      * Applies the layer stack and transformation to the given display device
      * so that it shows the contents of this logical display.
      *
@@ -349,6 +383,12 @@
         int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;
         int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;
 
+        Rect maskingInsets = getMaskingInsets(displayDeviceInfo);
+        InsetUtils.rotateInsets(maskingInsets, orientation);
+        // Don't consider the masked area as available when calculating the scaling below.
+        physWidth -= maskingInsets.left + maskingInsets.right;
+        physHeight -= maskingInsets.top + maskingInsets.bottom;
+
         // Determine whether the width or height is more constrained to be scaled.
         //    physWidth / displayInfo.logicalWidth    => letter box
         // or physHeight / displayInfo.logicalHeight  => pillar box
@@ -375,6 +415,9 @@
         mTempDisplayRect.set(displayRectLeft, displayRectTop,
                 displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
 
+        // Now add back the offset for the masked area.
+        mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top);
+
         mTempDisplayRect.left += mDisplayOffsetX;
         mTempDisplayRect.right += mDisplayOffsetX;
         mTempDisplayRect.top += mDisplayOffsetY;
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 5292d3e5f..ba05b49 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -50,7 +50,6 @@
 import android.service.dreams.DreamManagerInternal;
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
-import android.text.TextUtils;
 import android.util.Slog;
 import android.view.Display;
 
@@ -124,7 +123,7 @@
                 }
             }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
             mContext.getContentResolver().registerContentObserver(
-                    Settings.Secure.getUriFor(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP), false,
+                    Settings.Secure.getUriFor(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE), false,
                     mDozeEnabledObserver, UserHandle.USER_ALL);
             writePulseGestureEnabled();
         }
diff --git a/services/core/java/com/android/server/hdmi/ArcInitiationActionFromAvr.java b/services/core/java/com/android/server/hdmi/ArcInitiationActionFromAvr.java
new file mode 100644
index 0000000..ed17de5
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/ArcInitiationActionFromAvr.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+
+/**
+ * Feature action that handles Audio Return Channel initiated by AVR devices.
+ */
+public class ArcInitiationActionFromAvr extends HdmiCecFeatureAction {
+    // TODO(shubang): add tests
+
+    // State in which waits for ARC response.
+    private static final int STATE_WAITING_FOR_INITIATE_ARC_RESPONSE = 1;
+    private static final int STATE_ARC_INITIATED = 2;
+
+    // the required maximum response time specified in CEC 9.2
+    private static final int TIMEOUT_MS = 1000;
+
+    ArcInitiationActionFromAvr(HdmiCecLocalDevice source) {
+        super(source);
+    }
+
+    @Override
+    boolean start() {
+        audioSystem().setArcStatus(true);
+        mState = STATE_WAITING_FOR_INITIATE_ARC_RESPONSE;
+        addTimer(mState, TIMEOUT_MS);
+        sendInitiateArc();
+        return true;
+    }
+
+    @Override
+    boolean processCommand(HdmiCecMessage cmd) {
+        if (mState != STATE_WAITING_FOR_INITIATE_ARC_RESPONSE) {
+            return false;
+        }
+        switch (cmd.getOpcode()) {
+            case Constants.MESSAGE_FEATURE_ABORT:
+            case Constants.MESSAGE_REPORT_ARC_TERMINATED:
+                audioSystem().setArcStatus(false);
+                finish();
+                return true;
+            case Constants.MESSAGE_REPORT_ARC_INITIATED:
+                mState = STATE_ARC_INITIATED;
+                finish();
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    void handleTimerEvent(int state) {
+        if (mState != state) {
+            return;
+        }
+
+        switch (mState) {
+            case STATE_WAITING_FOR_INITIATE_ARC_RESPONSE:
+                handleInitiateArcTimeout();
+                break;
+        }
+    }
+
+    protected void sendInitiateArc() {
+        sendCommand(HdmiCecMessageBuilder.buildInitiateArc(getSourceAddress(), Constants.ADDR_TV),
+                result -> {
+                    if (result != SendMessageResult.SUCCESS) {
+                        audioSystem().setArcStatus(false);
+                        finish();
+                    }
+                });
+    }
+
+    private void handleInitiateArcTimeout() {
+        HdmiLogger.debug("handleInitiateArcTimeout");
+        audioSystem().setArcStatus(false);
+        finish();
+    }
+
+}
diff --git a/services/core/java/com/android/server/hdmi/ArcTerminationActionFromAvr.java b/services/core/java/com/android/server/hdmi/ArcTerminationActionFromAvr.java
new file mode 100644
index 0000000..7e73321
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/ArcTerminationActionFromAvr.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+
+/**
+ * Feature action that handles Audio Return Channel terminated by AVR devices.
+ */
+public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
+
+    // State in which waits for ARC response.
+    private static final int STATE_WAITING_FOR_INITIATE_ARC_RESPONSE = 1;
+    private static final int STATE_ARC_TERMINATED = 2;
+
+    // the required maximum response time specified in CEC 9.2
+    private static final int TIMEOUT_MS = 1000;
+
+    ArcTerminationActionFromAvr(HdmiCecLocalDevice source) {
+        super(source);
+    }
+
+    @Override
+    boolean start() {
+        mState = STATE_WAITING_FOR_INITIATE_ARC_RESPONSE;
+        addTimer(mState, TIMEOUT_MS);
+        sendTerminateArc();
+        return true;
+    }
+
+    @Override
+    boolean processCommand(HdmiCecMessage cmd) {
+        if (mState != STATE_WAITING_FOR_INITIATE_ARC_RESPONSE) {
+            return false;
+        }
+        switch (cmd.getOpcode()) {
+            case Constants.MESSAGE_REPORT_ARC_TERMINATED:
+                mState = STATE_ARC_TERMINATED;
+                audioSystem().setArcStatus(false);
+                finish();
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    void handleTimerEvent(int state) {
+        if (mState != state) {
+            return;
+        }
+
+        switch (mState) {
+            case STATE_WAITING_FOR_INITIATE_ARC_RESPONSE:
+                handleTerminateArcTimeout();
+                break;
+        }
+    }
+
+    protected void sendTerminateArc() {
+        sendCommand(HdmiCecMessageBuilder.buildTerminateArc(getSourceAddress(), Constants.ADDR_TV),
+            result -> {
+                if (result != SendMessageResult.SUCCESS) {
+                    HdmiLogger.debug("Terminate ARC was not successfully sent.");
+                    finish();
+                }
+            });
+    }
+
+    private void handleTerminateArcTimeout() {
+        HdmiLogger.debug("handleTerminateArcTimeout");
+        finish();
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index a2a55e532..d154830 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -16,12 +16,14 @@
 
 package com.android.server.hdmi;
 
+import android.annotation.IntDef;
 import android.hardware.hdmi.HdmiDeviceInfo;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
- * Defines constants related to HDMI-CEC protocol internal implementation.
- * If a constant will be used in the public api, it should be located in
- * {@link android.hardware.hdmi.HdmiControlManager}.
+ * Defines constants related to HDMI-CEC protocol internal implementation. If a constant will be
+ * used in the public api, it should be located in {@link android.hardware.hdmi.HdmiControlManager}.
  */
 final class Constants {
 
@@ -179,6 +181,46 @@
     static final int MENU_STATE_ACTIVATED = 0;
     static final int MENU_STATE_DEACTIVATED = 1;
 
+    // Audio Format Codes
+    // Refer to CEA Standard (CEA-861-D), Table 37 Audio Format Codes.
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+        AUDIO_CODEC_NONE,
+        AUDIO_CODEC_LPCM,
+        AUDIO_CODEC_DD,
+        AUDIO_CODEC_MPEG1,
+        AUDIO_CODEC_MP3,
+        AUDIO_CODEC_MPEG2,
+        AUDIO_CODEC_AAC,
+        AUDIO_CODEC_DTS,
+        AUDIO_CODEC_ATRAC,
+        AUDIO_CODEC_ONEBITAUDIO,
+        AUDIO_CODEC_DDP,
+        AUDIO_CODEC_DTSHD,
+        AUDIO_CODEC_TRUEHD,
+        AUDIO_CODEC_DST,
+        AUDIO_CODEC_WMAPRO,
+        AUDIO_CODEC_MAX,
+    })
+    public @interface AudioCodec {}
+
+    static final int AUDIO_CODEC_NONE = 0x0;
+    static final int AUDIO_CODEC_LPCM = 0x1; // Support LPCMs
+    static final int AUDIO_CODEC_DD = 0x2; // Support DD
+    static final int AUDIO_CODEC_MPEG1 = 0x3; // Support MPEG1
+    static final int AUDIO_CODEC_MP3 = 0x4; // Support MP3
+    static final int AUDIO_CODEC_MPEG2 = 0x5; // Support MPEG2
+    static final int AUDIO_CODEC_AAC = 0x6; // Support AAC
+    static final int AUDIO_CODEC_DTS = 0x7; // Support DTS
+    static final int AUDIO_CODEC_ATRAC = 0x8; // Support ATRAC
+    static final int AUDIO_CODEC_ONEBITAUDIO = 0x9; // Support One-Bit Audio
+    static final int AUDIO_CODEC_DDP = 0xA; // Support DDP
+    static final int AUDIO_CODEC_DTSHD = 0xB; // Support DTSHD
+    static final int AUDIO_CODEC_TRUEHD = 0xC; // Support MLP/TRUE-HD
+    static final int AUDIO_CODEC_DST = 0xD; // Support DST
+    static final int AUDIO_CODEC_WMAPRO = 0xE; // Support WMA-Pro
+    static final int AUDIO_CODEC_MAX = 0xF;
+
     // Bit mask used to get the routing path of the top level device.
     // When &'d with the path 1.2.2.0 (0x1220), for instance, gives 1.0.0.0.
     static final int ROUTING_PATH_TOP_MASK = 0xF000;
@@ -190,16 +232,31 @@
 
     // Strategy for device polling.
     // Should use "OR(|) operation of POLL_STRATEGY_XXX and POLL_ITERATION_XXX.
-    static final int POLL_STRATEGY_MASK = 0x3;  // first and second bit.
+    static final int POLL_STRATEGY_MASK = 0x3; // first and second bit.
     static final int POLL_STRATEGY_REMOTES_DEVICES = 0x1;
     static final int POLL_STRATEGY_SYSTEM_AUDIO = 0x2;
 
-    static final int POLL_ITERATION_STRATEGY_MASK = 0x30000;  // first and second bit.
+    static final int POLL_ITERATION_STRATEGY_MASK = 0x30000; // first and second bit.
     static final int POLL_ITERATION_IN_ORDER = 0x10000;
     static final int POLL_ITERATION_REVERSE_ORDER = 0x20000;
 
     static final int UNKNOWN_VOLUME = -1;
 
+    // States of property PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON
+    // to decide if turn on the system audio control when power on the device
+    @IntDef({
+        ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON,
+        USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON,
+        NEVER_SYSTEM_AUDIO_CONTROL_ON_POWER_ON
+    })
+    @interface SystemAudioControlOnPowerOn {}
+
+    static final int ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON = 0;
+    static final int USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON = 1;
+    static final int NEVER_SYSTEM_AUDIO_CONTROL_ON_POWER_ON = 2;
+
+    static final String PROPERTY_PREFERRED_ADDRESS_AUDIO_SYSTEM =
+            "persist.sys.hdmi.addr.audiosystem";
     static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "persist.sys.hdmi.addr.playback";
     static final String PROPERTY_PREFERRED_ADDRESS_TV = "persist.sys.hdmi.addr.tv";
 
@@ -219,6 +276,59 @@
     // when it's an active source. True by default.
     static final String PROPERTY_KEEP_AWAKE = "persist.sys.hdmi.keep_awake";
 
+    // TODO(UI): Set this from UI to decide if turn on System Audio Mode when power on the device
+    /**
+     * Property to decide if turn on the system audio control when power on the device.
+     *
+     * <p>Default is always turn on. State must be a valid {@link SystemAudioControlOnPowerOn} int.
+     */
+    static final String PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON =
+            "persist.sys.hdmi.system_audio_control_on_power_on";
+
+    /**
+     * Property to record last state of system audio control before device powered off.
+     * <p>When {@link #PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON} is set to
+     * {@link #USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON}, restoring this state on power on.
+     * <p>State must be true or false. Default true.
+     */
+    static final String PROPERTY_LAST_SYSTEM_AUDIO_CONTROL =
+            "persist.sys.hdmi.last_system_audio_control";
+
+    /**
+     * Property to indicate if device supports ARC or not
+     * <p>Default is true.
+     */
+    static final String PROPERTY_ARC_SUPPORT =
+        "persist.sys.hdmi.property_arc_support";
+
+    /**
+     * Property to save the audio port to switch to when system audio control is on.
+     * <P>Audio system should switch to this port when cec active source is not its child in the tree
+     * or is not itself.
+     *
+     * <p>Default is ARC port.
+     */
+    static final String PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT =
+        "persist.sys.hdmi.property_sytem_audio_mode_audio_port";
+
+    /**
+     * Property to save the ARC port id on system audio device.
+     * <p>When ARC is initiated, this port will be used to turn on ARC.
+     */
+    static final String PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT =
+        "persist.sys.hdmi.property_sytem_audio_device_arc_port";
+
+    /**
+     * Property to strip local audio of amplifier and use local speaker
+     * when TV does not support system audio mode.
+     *
+     * <p>This property applies to device with both audio system/playback types.
+     * <p>True means using local speaker when TV does not support system audio.
+     * <p>False means passing audio to TV. Default is true.
+     */
+    static final String PROPERTY_STRIP_AUDIO_TV_NO_SYSTEM_AUDIO =
+        "persist.sys.hdmi.property_strip_audio_tv_no_system_audio";
+
     static final int RECORDING_TYPE_DIGITAL_RF = 1;
     static final int RECORDING_TYPE_ANALOGUE_RF = 2;
     static final int RECORDING_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 3;
@@ -243,5 +353,7 @@
     static final int DISABLED = 0;
     static final int ENABLED = 1;
 
-    private Constants() { /* cannot be instantiated */ }
+    private Constants() {
+        /* cannot be instantiated */
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
index 2c1a7d5..15ec486 100644
--- a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
+++ b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
@@ -85,7 +85,7 @@
 
     void processAllMessages() {
         // Use the copied buffer.
-        ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<HdmiCecMessage>(mBuffer);
+        ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<>(mBuffer);
         mBuffer.clear();
         for (HdmiCecMessage message : copiedBuffer) {
             mDevice.onMessage(message);
@@ -104,7 +104,7 @@
      *        are associated with
      */
     void processMessagesForDevice(int address) {
-        ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<HdmiCecMessage>(mBuffer);
+        ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<>(mBuffer);
         mBuffer.clear();
         HdmiLogger.debug("Checking message for address:" + address);
         for (HdmiCecMessage message : copiedBuffer) {
@@ -134,7 +134,7 @@
      * @param address logical address of the device to be the active source
      */
     void processActiveSource(int address) {
-        ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<HdmiCecMessage>(mBuffer);
+        ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<>(mBuffer);
         mBuffer.clear();
         for (HdmiCecMessage message : copiedBuffer) {
             if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE
diff --git a/services/core/java/com/android/server/hdmi/DetectTvSystemAudioModeSupportAction.java b/services/core/java/com/android/server/hdmi/DetectTvSystemAudioModeSupportAction.java
new file mode 100644
index 0000000..0495ff8
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/DetectTvSystemAudioModeSupportAction.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+
+import com.android.server.hdmi.HdmiCecLocalDeviceAudioSystem.TvSystemAudioModeSupportedCallback;
+
+/**
+ * Feature action that detects if TV supports system audio control.
+ */
+public class DetectTvSystemAudioModeSupportAction extends HdmiCecFeatureAction {
+
+    // State that waits for <Active Source> once send <Request Active Source>.
+    private static final int STATE_WAITING_FOR_FEATURE_ABORT = 1;
+
+    private TvSystemAudioModeSupportedCallback mCallback;
+    private int mState;
+
+    DetectTvSystemAudioModeSupportAction(HdmiCecLocalDevice source,
+            TvSystemAudioModeSupportedCallback callback) {
+        super(source);
+        mCallback = callback;
+    }
+
+    @Override
+    boolean start() {
+        mState = STATE_WAITING_FOR_FEATURE_ABORT;
+        addTimer(mState, HdmiConfig.TIMEOUT_MS);
+        sendSetSystemAudioMode();
+        return true;
+    }
+
+    @Override
+    boolean processCommand(HdmiCecMessage cmd) {
+        if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) {
+            if (mState != STATE_WAITING_FOR_FEATURE_ABORT) {
+                return false;
+            }
+            finishAction(false);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    void handleTimerEvent(int state) {
+        if (mState != state) {
+            return;
+        }
+
+        switch (mState) {
+            case STATE_WAITING_FOR_FEATURE_ABORT:
+                finishAction(true);
+                break;
+        }
+    }
+
+    protected void sendSetSystemAudioMode() {
+        sendCommand(
+                HdmiCecMessageBuilder.buildSetSystemAudioMode(getSourceAddress(),Constants.ADDR_TV,
+                        true),
+                result -> {
+                    if (result != SendMessageResult.SUCCESS) {
+                        finishAction(false);
+                    }
+                });
+    }
+
+    private void finishAction(boolean supported) {
+        mCallback.onResult(supported);
+        audioSystem().setTvSystemAudioModeSupport(supported);
+        finish();
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
index db8dedb..b75e75f 100755
--- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
@@ -386,6 +386,7 @@
                 return;
             case STATE_WAITING_FOR_VENDOR_ID:
                 queryVendorId(address);
+                return;
             default:
                 return;
         }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
index d26be57..11faa56 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
@@ -256,6 +256,10 @@
         return (HdmiCecLocalDeviceTv) mSource;
     }
 
+    protected final HdmiCecLocalDeviceAudioSystem audioSystem() {
+        return (HdmiCecLocalDeviceAudioSystem) mSource;
+    }
+
     protected final int getSourceAddress() {
         return mSource.getDeviceInfo().getLogicalAddress();
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 2949b92..7860122 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -27,11 +27,9 @@
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
-
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
-
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -39,8 +37,8 @@
 import java.util.List;
 
 /**
- * Class that models a logical CEC device hosted in this system. Handles initialization,
- * CEC commands that call for actions customized per device type.
+ * Class that models a logical CEC device hosted in this system. Handles initialization, CEC
+ * commands that call for actions customized per device type.
  */
 abstract class HdmiCecLocalDevice {
     private static final String TAG = "HdmiCecLocalDevice";
@@ -69,47 +67,60 @@
         public ActiveSource() {
             invalidate();
         }
+
         public ActiveSource(int logical, int physical) {
             logicalAddress = logical;
             physicalAddress = physical;
         }
+
         public static ActiveSource of(ActiveSource source) {
             return new ActiveSource(source.logicalAddress, source.physicalAddress);
         }
+
         public static ActiveSource of(int logical, int physical) {
             return new ActiveSource(logical, physical);
         }
+
         public boolean isValid() {
             return HdmiUtils.isValidAddress(logicalAddress);
         }
+
         public void invalidate() {
             logicalAddress = Constants.ADDR_INVALID;
             physicalAddress = Constants.INVALID_PHYSICAL_ADDRESS;
         }
+
         public boolean equals(int logical, int physical) {
             return logicalAddress == logical && physicalAddress == physical;
         }
+
         @Override
         public boolean equals(Object obj) {
             if (obj instanceof ActiveSource) {
                 ActiveSource that = (ActiveSource) obj;
-                return that.logicalAddress == logicalAddress &&
-                       that.physicalAddress == physicalAddress;
+                return that.logicalAddress == logicalAddress
+                        && that.physicalAddress == physicalAddress;
             }
             return false;
         }
+
         @Override
         public int hashCode() {
             return logicalAddress * 29 + physicalAddress;
         }
+
         @Override
         public String toString() {
             StringBuffer s = new StringBuffer();
-            String logicalAddressString = (logicalAddress == Constants.ADDR_INVALID)
-                    ? "invalid" : String.format("0x%02x", logicalAddress);
+            String logicalAddressString =
+                    (logicalAddress == Constants.ADDR_INVALID)
+                            ? "invalid"
+                            : String.format("0x%02x", logicalAddress);
             s.append("(").append(logicalAddressString);
-            String physicalAddressString = (physicalAddress == Constants.INVALID_PHYSICAL_ADDRESS)
-                    ? "invalid" : String.format("0x%04x", physicalAddress);
+            String physicalAddressString =
+                    (physicalAddress == Constants.INVALID_PHYSICAL_ADDRESS)
+                            ? "invalid"
+                            : String.format("0x%04x", physicalAddress);
             s.append(", ").append(physicalAddressString).append(")");
             return s.toString();
         }
@@ -131,23 +142,24 @@
     // Note that access to this collection should happen in service thread.
     private final ArrayList<HdmiCecFeatureAction> mActions = new ArrayList<>();
 
-    private final Handler mHandler = new Handler () {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_DISABLE_DEVICE_TIMEOUT:
-                    handleDisableDeviceTimeout();
-                    break;
-                case MSG_USER_CONTROL_RELEASE_TIMEOUT:
-                    handleUserControlReleased();
-                    break;
-            }
-        }
-    };
+    private final Handler mHandler =
+            new Handler() {
+                @Override
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case MSG_DISABLE_DEVICE_TIMEOUT:
+                            handleDisableDeviceTimeout();
+                            break;
+                        case MSG_USER_CONTROL_RELEASE_TIMEOUT:
+                            handleUserControlReleased();
+                            break;
+                    }
+                }
+            };
 
     /**
-     * A callback interface to get notified when all pending action is cleared.
-     * It can be called when timeout happened.
+     * A callback interface to get notified when all pending action is cleared. It can be called
+     * when timeout happened.
      */
     interface PendingActionClearedCallback {
         void onCleared(HdmiCecLocalDevice device);
@@ -165,12 +177,14 @@
     // Factory method that returns HdmiCecLocalDevice of corresponding type.
     static HdmiCecLocalDevice create(HdmiControlService service, int deviceType) {
         switch (deviceType) {
-        case HdmiDeviceInfo.DEVICE_TV:
-            return new HdmiCecLocalDeviceTv(service);
-        case HdmiDeviceInfo.DEVICE_PLAYBACK:
-            return new HdmiCecLocalDevicePlayback(service);
-        default:
-            return null;
+            case HdmiDeviceInfo.DEVICE_TV:
+                return new HdmiCecLocalDeviceTv(service);
+            case HdmiDeviceInfo.DEVICE_PLAYBACK:
+                return new HdmiCecLocalDevicePlayback(service);
+            case HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM:
+                return new HdmiCecLocalDeviceAudioSystem(service);
+            default:
+                return null;
         }
     }
 
@@ -181,27 +195,22 @@
         mPendingActionClearedCallback = null;
     }
 
-    /**
-     * Called once a logical address of the local device is allocated.
-     */
+    /** Called once a logical address of the local device is allocated. */
     protected abstract void onAddressAllocated(int logicalAddress, int reason);
 
-    /**
-     * Get the preferred logical address from system properties.
-     */
+    /** Get the preferred logical address from system properties. */
     protected abstract int getPreferredAddress();
 
-    /**
-     * Set the preferred logical address to system properties.
-     */
+    /** Set the preferred logical address to system properties. */
     protected abstract void setPreferredAddress(int addr);
 
     /**
-     * Returns true if the TV input associated with the CEC device is ready
-     * to accept further processing such as input switching. This is used
-     * to buffer certain CEC commands and process it later if the input is not
-     * ready yet. For other types of local devices(non-TV), this method returns
-     * true by default to let the commands be processed right away.
+     * Returns true if the TV input associated with the CEC device is ready to accept further
+     * processing such as input switching.
+     *
+     * <p>This is used to buffer certain CEC commands and process it later if the input is not ready
+     * yet. For other types of local devices(non-TV), this method returns true by default to let the
+     * commands be processed right away.
      */
     protected boolean isInputReady(int deviceId) {
         return true;
@@ -209,7 +218,8 @@
 
     /**
      * Returns true if the local device allows the system to be put to standby.
-     * The default implementation returns true.
+     *
+     * <p>The default implementation returns true.
      */
     protected boolean canGoToStandby() {
         return true;
@@ -264,14 +274,28 @@
                 return handleRoutingChange(message);
             case Constants.MESSAGE_ROUTING_INFORMATION:
                 return handleRoutingInformation(message);
+            case Constants.MESSAGE_REQUEST_ARC_INITIATION:
+                return handleRequestArcInitiate(message);
+            case Constants.MESSAGE_REQUEST_ARC_TERMINATION:
+                return handleRequestArcTermination(message);
             case Constants.MESSAGE_INITIATE_ARC:
                 return handleInitiateArc(message);
             case Constants.MESSAGE_TERMINATE_ARC:
                 return handleTerminateArc(message);
+            case Constants.MESSAGE_REPORT_ARC_INITIATED:
+                return handleReportArcInitiate(message);
+            case Constants.MESSAGE_REPORT_ARC_TERMINATED:
+                return handleReportArcTermination(message);
+            case Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST:
+                return handleSystemAudioModeRequest(message);
             case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE:
                 return handleSetSystemAudioMode(message);
             case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS:
                 return handleSystemAudioModeStatus(message);
+            case Constants.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
+                return handleGiveSystemAudioModeStatus(message);
+            case Constants.MESSAGE_GIVE_AUDIO_STATUS:
+                return handleGiveAudioStatus(message);
             case Constants.MESSAGE_REPORT_AUDIO_STATUS:
                 return handleReportAudioStatus(message);
             case Constants.MESSAGE_STANDBY:
@@ -308,6 +332,10 @@
                 return handleTimerStatus(message);
             case Constants.MESSAGE_RECORD_STATUS:
                 return handleRecordStatus(message);
+            case Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR:
+                return handleRequestShortAudioDescriptor(message);
+            case Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR:
+                return handleReportShortAudioDescriptor(message);
             default:
                 return false;
         }
@@ -331,8 +359,9 @@
         assertRunOnServiceThread();
 
         int physicalAddress = mService.getPhysicalAddress();
-        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
-                mAddress, physicalAddress, mDeviceType);
+        HdmiCecMessage cecMessage =
+                HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+                        mAddress, physicalAddress, mDeviceType);
         mService.sendCecCommand(cecMessage, callback);
         return true;
     }
@@ -341,8 +370,8 @@
     protected boolean handleGiveDeviceVendorId(@Nullable SendMessageCallback callback) {
         assertRunOnServiceThread();
         int vendorId = mService.getVendorId();
-        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
-                mAddress, vendorId);
+        HdmiCecMessage cecMessage =
+                HdmiCecMessageBuilder.buildDeviceVendorIdCommand(mAddress, vendorId);
         mService.sendCecCommand(cecMessage, callback);
         return true;
     }
@@ -351,8 +380,9 @@
     protected boolean handleGetCecVersion(HdmiCecMessage message) {
         assertRunOnServiceThread();
         int version = mService.getCecVersion();
-        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(),
-                message.getSource(), version);
+        HdmiCecMessage cecMessage =
+                HdmiCecMessageBuilder.buildCecVersion(
+                        message.getDestination(), message.getSource(), version);
         mService.sendCecCommand(cecMessage);
         return true;
     }
@@ -393,8 +423,9 @@
         assertRunOnServiceThread();
         // Note that since this method is called after logical address allocation is done,
         // mDeviceInfo should not be null.
-        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand(
-                mAddress, message.getSource(), mDeviceInfo.getDisplayName());
+        HdmiCecMessage cecMessage =
+                HdmiCecMessageBuilder.buildSetOsdNameCommand(
+                        mAddress, message.getSource(), mDeviceInfo.getDisplayName());
         if (cecMessage != null) {
             mService.sendCecCommand(cecMessage);
         } else {
@@ -419,10 +450,18 @@
         return false;
     }
 
+    protected boolean handleGiveSystemAudioModeStatus(HdmiCecMessage message) {
+        return false;
+    }
+
     protected boolean handleSetSystemAudioMode(HdmiCecMessage message) {
         return false;
     }
 
+    protected boolean handleSystemAudioModeRequest(HdmiCecMessage message) {
+        return false;
+    }
+
     protected boolean handleTerminateArc(HdmiCecMessage message) {
         return false;
     }
@@ -431,15 +470,44 @@
         return false;
     }
 
+    protected boolean handleRequestArcInitiate(HdmiCecMessage message) {
+        return false;
+    }
+
+    protected boolean handleRequestArcTermination(HdmiCecMessage message) {
+        return false;
+    }
+
+    protected boolean handleReportArcInitiate(HdmiCecMessage message) {
+        return false;
+    }
+
+    protected boolean handleReportArcTermination(HdmiCecMessage message) {
+        return false;
+    }
+
     protected boolean handleReportAudioStatus(HdmiCecMessage message) {
         return false;
     }
 
+    protected boolean handleGiveAudioStatus(HdmiCecMessage message) {
+        return false;
+    }
+
+    protected boolean handleRequestShortAudioDescriptor(HdmiCecMessage message) {
+        return false;
+    }
+
+    protected boolean handleReportShortAudioDescriptor(HdmiCecMessage message) {
+        return false;
+    }
+
     @ServiceThreadOnly
     protected boolean handleStandby(HdmiCecMessage message) {
         assertRunOnServiceThread();
         // Seq #12
-        if (mService.isControlEnabled() && !mService.isProhibitMode()
+        if (mService.isControlEnabled()
+                && !mService.isProhibitMode()
                 && mService.isPowerOnOrTransient()) {
             mService.standby();
             return true;
@@ -475,7 +543,8 @@
 
         if (keycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
             injectKeyEvent(downTime, KeyEvent.ACTION_DOWN, keycode, keyRepeatCount);
-            mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_USER_CONTROL_RELEASE_TIMEOUT),
+            mHandler.sendMessageDelayed(
+                    Message.obtain(mHandler, MSG_USER_CONTROL_RELEASE_TIMEOUT),
                     FOLLOWER_SAFETY_TIMEOUT);
             return true;
         }
@@ -497,13 +566,23 @@
     }
 
     static void injectKeyEvent(long time, int action, int keycode, int repeat) {
-        KeyEvent keyEvent = KeyEvent.obtain(time, time, action, keycode,
-                repeat, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
-                InputDevice.SOURCE_HDMI, null);
-        InputManager.getInstance().injectInputEvent(keyEvent,
-                InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+        KeyEvent keyEvent =
+                KeyEvent.obtain(
+                        time,
+                        time,
+                        action,
+                        keycode,
+                        repeat,
+                        0,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD,
+                        0,
+                        KeyEvent.FLAG_FROM_SYSTEM,
+                        InputDevice.SOURCE_HDMI,
+                        null);
+        InputManager.getInstance()
+                .injectInputEvent(keyEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
         keyEvent.recycle();
-   }
+    }
 
     static boolean isPowerOnOrToggleCommand(HdmiCecMessage message) {
         byte[] params = message.getParams();
@@ -533,15 +612,17 @@
     }
 
     protected boolean handleGiveDevicePowerStatus(HdmiCecMessage message) {
-        mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPowerStatus(
-                mAddress, message.getSource(), mService.getPowerStatus()));
+        mService.sendCecCommand(
+                HdmiCecMessageBuilder.buildReportPowerStatus(
+                        mAddress, message.getSource(), mService.getPowerStatus()));
         return true;
     }
 
     protected boolean handleMenuRequest(HdmiCecMessage message) {
         // Always report menu active to receive Remote Control.
-        mService.sendCecCommand(HdmiCecMessageBuilder.buildReportMenuStatus(
-                mAddress, message.getSource(), Constants.MENU_STATE_ACTIVATED));
+        mService.sendCecCommand(
+                HdmiCecMessageBuilder.buildReportMenuStatus(
+                        mAddress, message.getSource(), Constants.MENU_STATE_ACTIVATED));
         return true;
     }
 
@@ -550,8 +631,12 @@
     }
 
     protected boolean handleVendorCommand(HdmiCecMessage message) {
-        if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
-                message.getDestination(), message.getParams(), false)) {
+        if (!mService.invokeVendorCommandListenersOnReceived(
+                mDeviceType,
+                message.getSource(),
+                message.getDestination(),
+                message.getParams(),
+                false)) {
             // Vendor command listener may not have been registered yet. Respond with
             // <Feature Abort> [NOT_IN_CORRECT_MODE] so that the sender can try again later.
             mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
@@ -563,12 +648,12 @@
         byte[] params = message.getParams();
         int vendorId = HdmiUtils.threeBytesToInt(params);
         if (vendorId == mService.getVendorId()) {
-            if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
-                    message.getDestination(), params, true)) {
+            if (!mService.invokeVendorCommandListenersOnReceived(
+                    mDeviceType, message.getSource(), message.getDestination(), params, true)) {
                 mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
             }
-        } else if (message.getDestination() != Constants.ADDR_BROADCAST &&
-                message.getSource() != Constants.ADDR_UNREGISTERED) {
+        } else if (message.getDestination() != Constants.ADDR_BROADCAST
+                && message.getSource() != Constants.ADDR_UNREGISTERED) {
             Slog.v(TAG, "Wrong direct vendor command. Replying with <Feature Abort>");
             mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE);
         } else {
@@ -720,8 +805,8 @@
 
     // Remove all actions matched with the given Class type besides |exception|.
     @ServiceThreadOnly
-    <T extends HdmiCecFeatureAction> void removeActionExcept(final Class<T> clazz,
-            final HdmiCecFeatureAction exception) {
+    <T extends HdmiCecFeatureAction> void removeActionExcept(
+            final Class<T> clazz, final HdmiCecFeatureAction exception) {
         assertRunOnServiceThread();
         Iterator<HdmiCecFeatureAction> iter = mActions.iterator();
         while (iter.hasNext()) {
@@ -749,8 +834,7 @@
         }
     }
 
-    void setAutoDeviceOff(boolean enabled) {
-    }
+    void setAutoDeviceOff(boolean enabled) {}
 
     /**
      * Called when a hot-plug event issued.
@@ -758,8 +842,7 @@
      * @param portId id of port where a hot-plug event happened
      * @param connected whether to connected or not on the event
      */
-    void onHotplug(int portId, boolean connected) {
-    }
+    void onHotplug(int portId, boolean connected) {}
 
     final HdmiControlService getService() {
         return mService;
@@ -842,34 +925,34 @@
     /**
      * Called when the system goes to standby mode.
      *
-     * @param initiatedByCec true if this power sequence is initiated
-     *        by the reception the CEC messages like &lt;Standby&gt;
-     * @param standbyAction Intent action that drives the standby process,
-     *        either {@link HdmiControlService#STANDBY_SCREEN_OFF} or
-     *        {@link HdmiControlService#STANDBY_SHUTDOWN}
+     * @param initiatedByCec true if this power sequence is initiated by the reception the CEC
+     *     messages like &lt;Standby&gt;
+     * @param standbyAction Intent action that drives the standby process, either {@link
+     *     HdmiControlService#STANDBY_SCREEN_OFF} or {@link HdmiControlService#STANDBY_SHUTDOWN}
      */
     protected void onStandby(boolean initiatedByCec, int standbyAction) {}
 
     /**
-     * Disable device. {@code callback} is used to get notified when all pending
-     * actions are completed or timeout is issued.
+     * Disable device. {@code callback} is used to get notified when all pending actions are
+     * completed or timeout is issued.
      *
-     * @param initiatedByCec true if this sequence is initiated
-     *        by the reception the CEC messages like &lt;Standby&gt;
+     * @param initiatedByCec true if this sequence is initiated by the reception the CEC messages
+     *     like &lt;Standby&gt;
      * @param originalCallback callback interface to get notified when all pending actions are
-     *        cleared
+     *     cleared
      */
-    protected void disableDevice(boolean initiatedByCec,
-            final PendingActionClearedCallback originalCallback) {
-        mPendingActionClearedCallback = new PendingActionClearedCallback() {
-            @Override
-            public void onCleared(HdmiCecLocalDevice device) {
-                mHandler.removeMessages(MSG_DISABLE_DEVICE_TIMEOUT);
-                originalCallback.onCleared(device);
-            }
-        };
-        mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_DISABLE_DEVICE_TIMEOUT),
-                DEVICE_CLEANUP_TIMEOUT);
+    protected void disableDevice(
+            boolean initiatedByCec, final PendingActionClearedCallback originalCallback) {
+        mPendingActionClearedCallback =
+                new PendingActionClearedCallback() {
+                    @Override
+                    public void onCleared(HdmiCecLocalDevice device) {
+                        mHandler.removeMessages(MSG_DISABLE_DEVICE_TIMEOUT);
+                        originalCallback.onCleared(device);
+                    }
+                };
+        mHandler.sendMessageDelayed(
+                Message.obtain(mHandler, MSG_DISABLE_DEVICE_TIMEOUT), DEVICE_CLEANUP_TIMEOUT);
     }
 
     @ServiceThreadOnly
@@ -908,8 +991,14 @@
         int logicalAddress = findKeyReceiverAddress();
         if (logicalAddress == Constants.ADDR_INVALID || logicalAddress == mAddress) {
             // Don't send key event to invalid device or itself.
-            Slog.w(TAG, "Discard key event: " + keyCode + ", pressed:" + isPressed
-                    + ", receiverAddr=" + logicalAddress);
+            Slog.w(
+                    TAG,
+                    "Discard key event: "
+                            + keyCode
+                            + ", pressed:"
+                            + isPressed
+                            + ", receiverAddr="
+                            + logicalAddress);
         } else if (!action.isEmpty()) {
             action.get(0).processKeyEvent(keyCode, isPressed);
         } else if (isPressed) {
@@ -918,8 +1007,8 @@
     }
 
     /**
-     * Returns the logical address of the device which will receive key events via
-     * {@link #sendKeyEvent}.
+     * Returns the logical address of the device which will receive key events via {@link
+     * #sendKeyEvent}.
      *
      * @see #sendKeyEvent(int, boolean)
      */
@@ -929,15 +1018,13 @@
     }
 
     void sendUserControlPressedAndReleased(int targetAddress, int cecKeycode) {
-        mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlPressed(
-                mAddress, targetAddress, cecKeycode));
-        mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlReleased(
-                mAddress, targetAddress));
+        mService.sendCecCommand(
+                HdmiCecMessageBuilder.buildUserControlPressed(mAddress, targetAddress, cecKeycode));
+        mService.sendCecCommand(
+                HdmiCecMessageBuilder.buildUserControlReleased(mAddress, targetAddress));
     }
 
-    /**
-     * Dump internal status of HdmiCecLocalDevice object.
-     */
+    /** Dump internal status of HdmiCecLocalDevice object. */
     protected void dump(final IndentingPrintWriter pw) {
         pw.println("mDeviceType: " + mDeviceType);
         pw.println("mAddress: " + mAddress);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
new file mode 100644
index 0000000..3845954
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import static com.android.server.hdmi.Constants.ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON;
+import static com.android.server.hdmi.Constants.PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON;
+import static com.android.server.hdmi.Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON;
+
+import android.annotation.Nullable;
+import android.hardware.hdmi.HdmiDeviceInfo;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.os.SystemProperties;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.hdmi.Constants.AudioCodec;
+import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
+
+/**
+ * Represent a logical device of type {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM} residing in Android
+ * system.
+ */
+public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice {
+
+    private static final String TAG = "HdmiCecLocalDeviceAudioSystem";
+
+    // Whether System audio mode is activated or not.
+    // This becomes true only when all system audio sequences are finished.
+    @GuardedBy("mLock")
+    private boolean mSystemAudioActivated;
+
+    // Whether the System Audio Control feature is enabled or not. True by default.
+    @GuardedBy("mLock")
+    private boolean mSystemAudioControlFeatureEnabled;
+
+    private boolean mTvSystemAudioModeSupport;
+
+    // Whether ARC is available or not. "true" means that ARC is established between TV and
+    // AVR as audio receiver.
+    @ServiceThreadOnly private boolean mArcEstablished = false;
+
+    protected HdmiCecLocalDeviceAudioSystem(HdmiControlService service) {
+        super(service, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+        mSystemAudioControlFeatureEnabled = true;
+        // TODO(amyjojo) make System Audio Control controllable by users
+        /*mSystemAudioControlFeatureEnabled =
+        mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true);*/
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected void onStandby(boolean initiatedByCec, int standbyAction) {
+        assertRunOnServiceThread();
+        mTvSystemAudioModeSupport = false;
+        // Record the last state of System Audio Control before going to standby
+        synchronized (mLock) {
+            SystemProperties.set(
+                    Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL,
+                    mSystemAudioActivated ? "true" : "false");
+        }
+        terminateSystemAudioMode();
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected void onAddressAllocated(int logicalAddress, int reason) {
+        assertRunOnServiceThread();
+        mService.sendCecCommand(
+                HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+                        mAddress, mService.getPhysicalAddress(), mDeviceType));
+        mService.sendCecCommand(
+                HdmiCecMessageBuilder.buildDeviceVendorIdCommand(mAddress, mService.getVendorId()));
+        int systemAudioControlOnPowerOnProp =
+                SystemProperties.getInt(
+                        PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON,
+                        ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON);
+        boolean lastSystemAudioControlStatus =
+                SystemProperties.getBoolean(Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, true);
+        systemAudioControlOnPowerOn(systemAudioControlOnPowerOnProp, lastSystemAudioControlStatus);
+        startQueuedActions();
+    }
+
+    @VisibleForTesting
+    protected void systemAudioControlOnPowerOn(
+            int systemAudioOnPowerOnProp, boolean lastSystemAudioControlStatus) {
+        if ((systemAudioOnPowerOnProp == ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON)
+                || ((systemAudioOnPowerOnProp == USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON)
+                        && lastSystemAudioControlStatus)) {
+            addAndStartAction(new SystemAudioInitiationActionFromAvr(this));
+        }
+    }
+
+    @ServiceThreadOnly
+    protected boolean handleActiveSource(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        int logicalAddress = message.getSource();
+        int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
+        ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
+        if (!mActiveSource.equals(activeSource)) {
+            setActiveSource(activeSource);
+        }
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected int getPreferredAddress() {
+        assertRunOnServiceThread();
+        return SystemProperties.getInt(
+                Constants.PROPERTY_PREFERRED_ADDRESS_AUDIO_SYSTEM, Constants.ADDR_UNREGISTERED);
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected void setPreferredAddress(int addr) {
+        assertRunOnServiceThread();
+        SystemProperties.set(
+                Constants.PROPERTY_PREFERRED_ADDRESS_AUDIO_SYSTEM, String.valueOf(addr));
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleReportAudioStatus(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        // TODO(amyjojo): implement report audio status handler
+        HdmiLogger.debug(TAG + "Stub handleReportAudioStatus");
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleInitiateArc(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        // TODO(amyjojo): implement initiate arc handler
+        HdmiLogger.debug(TAG + "Stub handleInitiateArc");
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleReportArcInitiate(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        // TODO(amyjojo): implement report arc initiate handler
+        HdmiLogger.debug(TAG + "Stub handleReportArcInitiate");
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleReportArcTermination(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        // TODO(amyjojo): implement report arc terminate handler
+        HdmiLogger.debug(TAG + "Stub handleReportArcTermination");
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleGiveAudioStatus(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+
+        reportAudioStatus(message);
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleGiveSystemAudioModeStatus(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        mService.sendCecCommand(
+                HdmiCecMessageBuilder.buildReportSystemAudioMode(
+                        mAddress, message.getSource(), mSystemAudioActivated));
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleRequestArcInitiate(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        if (!SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE);
+        } else if (!isDirectConnectToTv()) {
+            HdmiLogger.debug("AVR device is not directly connected with TV");
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
+        } else {
+            addAndStartAction(new ArcInitiationActionFromAvr(this));
+        }
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleRequestArcTermination(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        if (!SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE);
+        } else if (!isArcEnabled()) {
+            HdmiLogger.debug("ARC is not established between TV and AVR device");
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
+        } else {
+            addAndStartAction(new ArcTerminationActionFromAvr(this));
+        }
+        return true;
+    }
+
+    @ServiceThreadOnly
+    protected boolean handleRequestShortAudioDescriptor(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        HdmiLogger.debug(TAG + "Stub handleRequestShortAudioDescriptor");
+        if (!isSystemAudioControlFeatureEnabled()) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+            return true;
+        }
+        if (!isSystemAudioActivated()) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
+            return true;
+        }
+        AudioDeviceInfo deviceInfo = getSystemAudioDeviceInfo();
+        if (deviceInfo == null) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNABLE_TO_DETERMINE);
+            return true;
+        }
+        @AudioCodec int[] audioFormatCodes = parseAudioFormatCodes(message.getParams());
+        byte[] sadBytes = getSupportedShortAudioDescriptors(deviceInfo, audioFormatCodes);
+        if (sadBytes.length == 0) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_INVALID_OPERAND);
+        } else {
+            mService.sendCecCommand(
+                    HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+                            mAddress, message.getSource(), sadBytes));
+        }
+        return true;
+    }
+
+    private byte[] getSupportedShortAudioDescriptors(
+            AudioDeviceInfo deviceInfo, @AudioCodec int[] audioFormatCodes) {
+        // TODO(b/80297701) implement
+        return new byte[] {};
+    }
+
+    @Nullable
+    private AudioDeviceInfo getSystemAudioDeviceInfo() {
+        // TODO(b/80297701) implement
+        // Get the audio device used for system audio mode.
+        return null;
+    }
+
+    @AudioCodec
+    private int[] parseAudioFormatCodes(byte[] params) {
+        @AudioCodec int[] audioFormatCodes = new int[params.length];
+        for (int i = 0; i < params.length; i++) {
+            byte val = params[i];
+            audioFormatCodes[i] =
+                    val >= 1 && val <= Constants.AUDIO_CODEC_MAX ? val : Constants.AUDIO_CODEC_NONE;
+        }
+        return audioFormatCodes;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleSystemAudioModeRequest(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        boolean systemAudioStatusOn = message.getParams().length != 0;
+        if (!setSystemAudioMode(systemAudioStatusOn)) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+            return true;
+        }
+
+        mService.sendCecCommand(
+                HdmiCecMessageBuilder.buildSetSystemAudioMode(
+                        mAddress, Constants.ADDR_BROADCAST, systemAudioStatusOn));
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleSetSystemAudioMode(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        if (!setSystemAudioMode(HdmiUtils.parseCommandParamSystemAudioStatus(message))) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+        }
+        return true;
+    }
+
+    @Override
+    @ServiceThreadOnly
+    protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        if (!setSystemAudioMode(HdmiUtils.parseCommandParamSystemAudioStatus(message))) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+        }
+        return true;
+    }
+
+    @ServiceThreadOnly
+    void setArcStatus(boolean enabled) {
+        // TODO(shubang): add tests
+        assertRunOnServiceThread();
+
+        HdmiLogger.debug("Set Arc Status[old:%b new:%b]", mArcEstablished, enabled);
+        // 1. Enable/disable ARC circuit.
+        enableAudioReturnChannel(enabled);
+        // 2. Notify arc status to audio service.
+        notifyArcStatusToAudioService(enabled);
+        // 3. Update arc status;
+        mArcEstablished = enabled;
+    }
+
+    /** Switch hardware ARC circuit in the system. */
+    @ServiceThreadOnly
+    private void enableAudioReturnChannel(boolean enabled) {
+        assertRunOnServiceThread();
+        mService.enableAudioReturnChannel(
+                SystemProperties.getInt(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT, 0),
+                enabled);
+    }
+
+    private void notifyArcStatusToAudioService(boolean enabled) {
+        // Note that we don't set any name to ARC.
+        mService.getAudioManager()
+                .setWiredDeviceConnectionState(AudioSystem.DEVICE_IN_HDMI, enabled ? 1 : 0, "", "");
+    }
+
+    private void reportAudioStatus(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+
+        int volume = mService.getAudioManager().getStreamVolume(AudioManager.STREAM_MUSIC);
+        boolean mute = mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC);
+        int maxVolume = mService.getAudioManager().getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
+
+        mService.sendCecCommand(
+                HdmiCecMessageBuilder.buildReportAudioStatus(
+                        mAddress, message.getSource(), scaledVolume, mute));
+    }
+
+    protected boolean setSystemAudioMode(boolean newSystemAudioMode) {
+        if (!isSystemAudioControlFeatureEnabled()) {
+            HdmiLogger.debug(
+                    "Cannot turn "
+                            + (newSystemAudioMode ? "on" : "off")
+                            + "system audio mode "
+                            + "because the System Audio Control feature is disabled.");
+            return false;
+        }
+        HdmiLogger.debug(
+                "System Audio Mode change[old:%b new:%b]",
+                mSystemAudioActivated, newSystemAudioMode);
+        // Wake up device if System Audio Control is turned on but device is still on standby
+        if (newSystemAudioMode && mService.isPowerStandbyOrTransient()) {
+            mService.wakeUp();
+        }
+        int targetPhysicalAddress = getActiveSource().physicalAddress;
+        if (newSystemAudioMode && !isPhysicalAddressMeOrBelow(targetPhysicalAddress)) {
+            switchToAudioInput();
+        }
+        // TODO(b/80297700): Mute device when TV terminates the system audio control
+        updateAudioManagerForSystemAudio(newSystemAudioMode);
+        synchronized (mLock) {
+            if (mSystemAudioActivated != newSystemAudioMode) {
+                mSystemAudioActivated = newSystemAudioMode;
+                mService.announceSystemAudioModeChange(newSystemAudioMode);
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Method to check if the target device belongs to the subtree of the current device or not.
+     *
+     * <p>Return true if it does or if the two devices share the same physical address.
+     *
+     * <p>This check assumes both device physical address and target address are valid.
+     *
+     * @param targetPhysicalAddress is the physical address of the target device
+     */
+    protected boolean isPhysicalAddressMeOrBelow(int targetPhysicalAddress) {
+        int myPhysicalAddress = mService.getPhysicalAddress();
+        int xor = targetPhysicalAddress ^ myPhysicalAddress;
+        // Return true if two addresses are the same
+        // or if they only differs for one byte, but not the first byte,
+        // and myPhysicalAddress is 0 after that byte
+        if (xor == 0
+                || ((xor & 0x0f00) == xor && (myPhysicalAddress & 0x0fff) == 0)
+                || ((xor & 0x00f0) == xor && (myPhysicalAddress & 0x00ff) == 0)
+                || ((xor & 0x000f) == xor && (myPhysicalAddress & 0x000f) == 0)) {
+            return true;
+        }
+        return false;
+    }
+
+    protected void switchToAudioInput() {
+        // TODO(b/111396634): switch input according to PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT
+    }
+
+    protected boolean isDirectConnectToTv() {
+        int myPhysicalAddress = mService.getPhysicalAddress();
+        return (myPhysicalAddress & Constants.ROUTING_PATH_TOP_MASK) == myPhysicalAddress;
+    }
+
+    private void updateAudioManagerForSystemAudio(boolean on) {
+        int device = mService.getAudioManager().setHdmiSystemAudioSupported(on);
+        HdmiLogger.debug("[A]UpdateSystemAudio mode[on=%b] output=[%X]", on, device);
+    }
+
+    @ServiceThreadOnly
+    void setSystemAudioControlFeatureEnabled(boolean enabled) {
+        assertRunOnServiceThread();
+        synchronized (mLock) {
+            mSystemAudioControlFeatureEnabled = enabled;
+        }
+    }
+
+    boolean isSystemAudioControlFeatureEnabled() {
+        synchronized (mLock) {
+            return mSystemAudioControlFeatureEnabled;
+        }
+    }
+
+    protected boolean isSystemAudioActivated() {
+        synchronized (mLock) {
+            return mSystemAudioActivated;
+        }
+    }
+
+    protected void terminateSystemAudioMode() {
+        // remove pending initiation actions
+        removeAction(SystemAudioInitiationActionFromAvr.class);
+        if (!isSystemAudioActivated()) {
+            return;
+        }
+
+        if (setSystemAudioMode(false)) {
+            // send <Set System Audio Mode> [“Off”]
+            mService.sendCecCommand(
+                    HdmiCecMessageBuilder.buildSetSystemAudioMode(
+                            mAddress, Constants.ADDR_BROADCAST, false));
+        }
+    }
+
+    /** Reports if System Audio Mode is supported by the connected TV */
+    interface TvSystemAudioModeSupportedCallback {
+
+        /** {@code supported} is true if the TV is connected and supports System Audio Mode. */
+        void onResult(boolean supported);
+    }
+
+    /**
+     * Queries the connected TV to detect if System Audio Mode is supported by the TV.
+     *
+     * <p>This query may take up to 2 seconds to complete.
+     *
+     * <p>The result of the query may be cached until Audio device type is put in standby or loses
+     * its physical address.
+     */
+    void queryTvSystemAudioModeSupport(TvSystemAudioModeSupportedCallback callback) {
+        if (!mTvSystemAudioModeSupport) {
+            addAndStartAction(new DetectTvSystemAudioModeSupportAction(this, callback));
+        } else {
+            callback.onResult(true);
+        }
+    }
+
+    void setTvSystemAudioModeSupport(boolean supported) {
+        mTvSystemAudioModeSupport = supported;
+    }
+
+    @VisibleForTesting
+    protected boolean isArcEnabled() {
+        synchronized (mLock) {
+            return mArcEstablished;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
index fd0ff9d..c005615 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
@@ -16,9 +16,11 @@
 
 package com.android.server.hdmi;
 
+import android.annotation.Nullable;
 import libcore.util.EmptyArray;
 
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * A class to encapsulate HDMI-CEC message used for the devices connected via
@@ -44,6 +46,27 @@
         mParams = Arrays.copyOf(params, params.length);
     }
 
+    @Override
+    public boolean equals(@Nullable Object message) {
+        if (message instanceof HdmiCecMessage) {
+            HdmiCecMessage that = (HdmiCecMessage) message;
+            return this.mSource == that.getSource() &&
+                this.mDestination == that.getDestination() &&
+                this.mOpcode == that.getOpcode() &&
+                Arrays.equals(this.mParams, that.getParams());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+            mSource,
+            mDestination,
+            mOpcode,
+            Arrays.hashCode(mParams));
+    }
+
     /**
      * Return the source address field of the message. It is the logical address
      * of the device which generated the message.
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index 9a51e3c..941c321 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -16,6 +16,8 @@
 
 package com.android.server.hdmi;
 
+import com.android.server.hdmi.Constants.AudioCodec;
+
 import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
 
@@ -211,6 +213,28 @@
     }
 
     /**
+     * Build &lt;Initiate Arc&gt;
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildInitiateArc(int src, int dest) {
+        return buildCommand(src, dest, Constants.MESSAGE_INITIATE_ARC);
+    }
+
+    /**
+     * Build &lt;Terminate Arc&gt;
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildTerminateArc(int src, int dest) {
+        return buildCommand(src, dest, Constants.MESSAGE_TERMINATE_ARC);
+    }
+
+    /**
      * Build &lt;Request Arc Termination&gt;
      *
      * @param src source address of command
@@ -243,6 +267,25 @@
         return buildCommand(src, dest, Constants.MESSAGE_REPORT_ARC_TERMINATED);
     }
 
+
+    /**
+     * Build &lt;Request Short Audio Descriptor&gt; command.
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @param audioFormats the {@link AudioCodec}s desired
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildRequestShortAudioDescriptor(int src, int dest,
+            @AudioCodec int[] audioFormats) {
+        byte[] params = new byte[Math.min(audioFormats.length,4)] ;
+        for (int i = 0; i < params.length ; i++){
+            params[i] = (byte) (audioFormats[i] & 0xff);
+        }
+        return buildCommand(src, dest, Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR, params);
+    }
+
+
     /**
      * Build &lt;Text View On&gt; command.
      *
@@ -255,6 +298,16 @@
     }
 
     /**
+     * Build &lt;Request Active Source&gt; command.
+     *
+     * @param src source address of command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildRequestActiveSource(int src) {
+        return buildCommand(src, Constants.ADDR_BROADCAST, Constants.MESSAGE_REQUEST_ACTIVE_SOURCE);
+    }
+
+    /**
      * Build &lt;Active Source&gt; command.
      *
      * @param src source address of command
@@ -372,6 +425,47 @@
     }
 
     /**
+     * Build &lt;Set System Audio Mode&gt; command.
+     *
+     * @param src source address of command
+     * @param des destination address of command
+     * @param systemAudioStatus whether to set System Audio Mode on or off
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildSetSystemAudioMode(int src, int des, boolean systemAudioStatus) {
+        return buildCommandWithBooleanParam(src, des, Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE,
+            systemAudioStatus
+        );
+    }
+
+    /**
+     * Build &lt;Report System Audio Mode&gt; command.
+     *
+     * @param src source address of command
+     * @param des destination address of command
+     * @param systemAudioStatus whether System Audio Mode is on or off
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildReportSystemAudioMode(int src, int des, boolean systemAudioStatus) {
+        return buildCommandWithBooleanParam(src, des, Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS,
+            systemAudioStatus
+        );
+    }
+
+    /**
+     * Build &lt;Report Short Audio Descriptor&gt; command.
+     *
+     * @param src source address of command
+     * @param des destination address of command
+     * @param sadBytes Short Audio Descriptor in bytes
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildReportShortAudioDescriptor(int src, int des, byte[] sadBytes) {
+        // TODO(b/80297701) validate.
+        return buildCommand(src, des, Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR, sadBytes);
+    }
+
+    /**
      * Build &lt;Give Audio Status&gt; command.
      *
      * @param src source address of command
@@ -383,6 +477,21 @@
     }
 
     /**
+     * Build &lt;Report Audio Status&gt; command.
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @param volume volume level of current device in param
+     * @param mute mute status of current device in param
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildReportAudioStatus(int src, int dest, int volume, boolean mute) {
+        byte status = (byte) ((byte) (mute ? 1 << 7 : 0) | ((byte) volume & 0x7F));
+        byte[] params = new byte[] { status };
+        return buildCommand(src, dest, Constants.MESSAGE_REPORT_AUDIO_STATUS, params);
+    }
+
+    /**
      * Build &lt;User Control Pressed&gt; command.
      *
      * @param src source address of command
@@ -592,6 +701,23 @@
         return new HdmiCecMessage(src, dest, opcode, params);
     }
 
+    /**
+     * Build a {@link HdmiCecMessage} with a boolean param and other given values.
+     *
+     * @param src source address of command
+     * @param des destination address of command
+     * @param opcode opcode for a message
+     * @param param boolean param for building the command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    private static HdmiCecMessage buildCommandWithBooleanParam(int src, int des,
+        int opcode, boolean param) {
+        byte[] params = new byte[]{
+            param ? (byte) 0b1 : 0b0
+        };
+        return buildCommand(src, des, opcode, params);
+    }
+
     private static byte[] physicalAddressToParam(int physicalAddress) {
         return new byte[] {
                 (byte) ((physicalAddress >> 8) & 0xFF),
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index a1753e5..c16d3cd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -96,7 +96,7 @@
 
     static final String PERMISSION = "android.permission.HDMI_CEC";
 
-    // The reason code to initiate intializeCec().
+    // The reason code to initiate initializeCec().
     static final int INITIATED_BY_ENABLE_CEC = 0;
     static final int INITIATED_BY_BOOT_UP = 1;
     static final int INITIATED_BY_SCREEN_ON = 2;
@@ -402,13 +402,16 @@
         if (mCecController != null) {
             if (mHdmiControlEnabled) {
                 initializeCec(INITIATED_BY_BOOT_UP);
+            } else {
+                mCecController.setOption(OptionKey.ENABLE_CEC, false);
             }
         } else {
             Slog.i(TAG, "Device does not support HDMI-CEC.");
             return;
         }
-
-        mMhlController = HdmiMhlControllerStub.create(this);
+        if (mMhlController == null) {
+            mMhlController = HdmiMhlControllerStub.create(this);
+        }
         if (!mMhlController.isReady()) {
             Slog.i(TAG, "Device does not support MHL-control.");
         }
@@ -440,6 +443,11 @@
         mCecController = cecController;
     }
 
+    @VisibleForTesting
+    void setHdmiMhlController(HdmiMhlControllerStub hdmiMhlController) {
+        mMhlController = hdmiMhlController;
+    }
+
     @Override
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
@@ -598,7 +606,8 @@
     }
 
     @ServiceThreadOnly
-    private void allocateLogicalAddress(final ArrayList<HdmiCecLocalDevice> allocatingDevices,
+    @VisibleForTesting
+    protected void allocateLogicalAddress(final ArrayList<HdmiCecLocalDevice> allocatingDevices,
             final int initiatedBy) {
         assertRunOnServiceThread();
         mCecController.clearLogicalAddress();
@@ -665,7 +674,8 @@
     // Initialize HDMI port information. Combine the information from CEC and MHL HAL and
     // keep them in one place.
     @ServiceThreadOnly
-    private void initPortInfo() {
+    @VisibleForTesting
+    protected void initPortInfo() {
         assertRunOnServiceThread();
         HdmiPortInfo[] cecPortInfo = null;
 
@@ -1709,6 +1719,38 @@
         }
 
         @Override
+        public void reportAudioStatus(final int deviceType, final int volume, final int maxVolume,
+                final boolean isMute) {
+            enforceAccessPermission();
+            runOnServiceThread(new Runnable() {
+                @Override
+                public void run() {
+                    HdmiCecLocalDevice device = mCecController.getLocalDevice(deviceType);
+                    if (device == null) {
+                        Slog.w(TAG, "Local device not available");
+                        return;
+                    }
+                    if (audioSystem() == null) {
+                        Slog.w(TAG, "audio system is not available");
+                        return;
+                    }
+                    if (!audioSystem().isSystemAudioActivated()) {
+                        Slog.w(TAG, "audio system is not in system audio mode");
+                        return;
+                    }
+                    int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
+
+                    sendCecCommand(HdmiCecMessageBuilder
+                            .buildReportAudioStatus(
+                                    device.getDeviceInfo().getLogicalAddress(),
+                                    Constants.ADDR_TV,
+                                    scaledVolume,
+                                    isMute));
+                }
+            });
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
             if (!DumpUtils.checkDumpPermission(getContext(), TAG, writer)) return;
             final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -2001,6 +2043,10 @@
         return mLocalDevices.contains(HdmiDeviceInfo.DEVICE_TV);
     }
 
+    boolean isAudioSystemDevice() {
+        return mLocalDevices.contains(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+    }
+
     boolean isTvDeviceEnabled() {
         return isTvDevice() && tv() != null;
     }
@@ -2010,6 +2056,11 @@
                 mCecController.getLocalDevice(HdmiDeviceInfo.DEVICE_PLAYBACK);
     }
 
+    public HdmiCecLocalDeviceAudioSystem audioSystem() {
+        return (HdmiCecLocalDeviceAudioSystem) mCecController.getLocalDevice(
+                HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+    }
+
     AudioManager getAudioManager() {
         return (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
     }
@@ -2071,6 +2122,11 @@
         return mWakeUpMessageReceived;
     }
 
+    @VisibleForTesting
+    boolean isStandbyMessageReceived() {
+        return mStandbyMessageReceived;
+    }
+
     @ServiceThreadOnly
     private void onWakeUp() {
         assertRunOnServiceThread();
@@ -2090,17 +2146,23 @@
     }
 
     @ServiceThreadOnly
-    private void onStandby(final int standbyAction) {
+    @VisibleForTesting
+    protected void onStandby(final int standbyAction) {
         assertRunOnServiceThread();
         mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
         invokeVendorCommandListenersOnControlStateChanged(false,
                 HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY);
-        if (!canGoToStandby()) {
+
+        final List<HdmiCecLocalDevice> devices = getAllLocalDevices();
+
+        if (!isStandbyMessageReceived() && !canGoToStandby()) {
             mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+            for (HdmiCecLocalDevice device : devices) {
+                device.onStandby(mStandbyMessageReceived, standbyAction);
+            }
             return;
         }
 
-        final List<HdmiCecLocalDevice> devices = getAllLocalDevices();
         disableDevices(new PendingActionClearedCallback() {
             @Override
             public void onCleared(HdmiCecLocalDevice device) {
@@ -2173,8 +2235,10 @@
             device.onStandby(mStandbyMessageReceived, standbyAction);
         }
         mStandbyMessageReceived = false;
-        mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, false);
-        mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, DISABLED);
+        if (!isAudioSystemDevice()) {
+            mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, false);
+            mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, DISABLED);
+        }
     }
 
     private void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {
@@ -2322,6 +2386,7 @@
 
     @ServiceThreadOnly
     private void enableHdmiControlService() {
+        mCecController.setOption(OptionKey.ENABLE_CEC, true);
         mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true);
         mMhlController.setOption(OPTION_MHL_ENABLE, ENABLED);
 
@@ -2338,6 +2403,7 @@
                     @Override
                     public void run() {
                         mCecController.setOption(OptionKey.ENABLE_CEC, false);
+                        mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, false);
                         mMhlController.setOption(OPTION_MHL_ENABLE, DISABLED);
                         clearLocalDevices();
                     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index ebe52c0..2309293 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -17,7 +17,6 @@
 package com.android.server.hdmi;
 
 import android.annotation.Nullable;
-import android.os.Build;
 import android.os.SystemClock;
 import android.util.Pair;
 import android.util.Slog;
@@ -41,7 +40,7 @@
 final class HdmiLogger {
     private static final String TAG = "HDMI";
     // Logging duration for same error message.
-    private static final long ERROR_LOG_DURATTION_MILLIS = 20 * 1000;  // 20s
+    private static final long ERROR_LOG_DURATION_MILLIS = 20 * 1000;  // 20s
 
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -134,6 +133,6 @@
     }
 
     private static boolean shouldLogNow(@Nullable Pair<Long, Integer> timing, long curTime) {
-        return timing == null || curTime - timing.first > ERROR_LOG_DURATTION_MILLIS;
+        return timing == null || curTime - timing.first > ERROR_LOG_DURATION_MILLIS;
     }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index 4ac3bba..2a8117f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -114,7 +114,7 @@
      *
      * @param logicalAddress the logical address to verify
      * @param deviceType the device type to check
-     * @throw IllegalArgumentException
+     * @throws IllegalArgumentException
      */
     static void verifyAddressType(int logicalAddress, int deviceType) {
         int actualDeviceType = getTypeFromAddress(logicalAddress);
diff --git a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
index 6893012..a62d0b6 100644
--- a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
+++ b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
@@ -38,7 +38,7 @@
     private static final int INVALID_POWER_STATUS = POWER_STATUS_UNKNOWN - 1;
 
     // Monitoring interval (60s)
-    private static final int MONITIROING_INTERNAL_MS = 60000;
+    private static final int MONITORING_INTERNAL_MS = 60000;
 
     // Timeout once sending <Give Device Power Status>
     private static final int REPORT_POWER_STATUS_TIMEOUT_MS = 5000;
@@ -132,7 +132,7 @@
         mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
 
         // Add both timers, monitoring and timeout.
-        addTimer(STATE_WAIT_FOR_NEXT_MONITORING, MONITIROING_INTERNAL_MS);
+        addTimer(STATE_WAIT_FOR_NEXT_MONITORING, MONITORING_INTERNAL_MS);
         addTimer(STATE_WAIT_FOR_REPORT_POWER_STATUS, REPORT_POWER_STATUS_TIMEOUT_MS);
     }
 
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
index 75a79cb..c70101c 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -35,7 +35,7 @@
      *
      * @param source {@link HdmiCecLocalDevice} instance
      * @param avrAddress address of AV receiver. It should be AUDIO_SYSTEM type
-     * @throw IllegalArugmentException if device type of sourceAddress and avrAddress
+     * @throws IllegalArgumentException if device type of sourceAddress and avrAddress
      *                      is invalid
      */
     RequestArcAction(HdmiCecLocalDevice source, int avrAddress) {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
index 449b208..a5477e8 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -60,7 +60,7 @@
      * @param avrAddress logical address of AVR device
      * @param targetStatus Whether to enable the system audio mode or not
      * @param callback callback interface to be notified when it's done
-     * @throw IllegalArugmentException if device type of sourceAddress and avrAddress is invalid
+     * @throws IllegalArgumentException if device type of sourceAddress and avrAddress is invalid
      */
     SystemAudioAction(HdmiCecLocalDevice source, int avrAddress, boolean targetStatus,
             IHdmiControlCallback callback) {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
index eb5119b..6ddff91 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
@@ -32,7 +32,7 @@
      * @param avrAddress logical address of AVR device
      * @param targetStatus Whether to enable the system audio mode or not
      * @param callback callback interface to be notified when it's done
-     * @throw IllegalArugmentException if device type of tvAddress and avrAddress is invalid
+     * @throws IllegalArgumentException if device type of tvAddress and avrAddress is invalid
      */
     SystemAudioActionFromAvr(HdmiCecLocalDevice source, int avrAddress,
             boolean targetStatus, IHdmiControlCallback callback) {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
index 02ecd13..5c0c272 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
@@ -32,7 +32,7 @@
      * @param avrAddress logical address of AVR device
      * @param targetStatus Whether to enable the system audio mode or not
      * @param callback callback interface to be notified when it's done
-     * @throw IllegalArugmentException if device type of tvAddress is invalid
+     * @throws IllegalArgumentException if device type of tvAddress is invalid
      */
     SystemAudioActionFromTv(HdmiCecLocalDevice sourceAddress, int avrAddress,
             boolean targetStatus, IHdmiControlCallback callback) {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java b/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java
new file mode 100644
index 0000000..d4932f9
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Feature action that handles System Audio Mode initiated by AVR devices.
+ */
+public class SystemAudioInitiationActionFromAvr extends HdmiCecFeatureAction {
+
+    // State that waits for <Active Source> once send <Request Active Source>.
+    private static final int STATE_WAITING_FOR_ACTIVE_SOURCE = 1;
+    @VisibleForTesting
+    static final int MAX_RETRY_COUNT = 5;
+
+    private int mSendRequestActiveSourceRetryCount = 0;
+    private int mSendSetSystemAudioModeRetryCount = 0;
+
+    SystemAudioInitiationActionFromAvr(HdmiCecLocalDevice source) {
+        super(source);
+    }
+
+    @Override
+    boolean start() {
+        if (audioSystem().mActiveSource.physicalAddress == Constants.INVALID_PHYSICAL_ADDRESS) {
+            mState = STATE_WAITING_FOR_ACTIVE_SOURCE;
+            addTimer(mState, HdmiConfig.TIMEOUT_MS);
+            sendRequestActiveSource();
+        } else {
+            queryTvSystemAudioModeSupport();
+        }
+        return true;
+    }
+
+    @Override
+    boolean processCommand(HdmiCecMessage cmd) {
+        switch (cmd.getOpcode()) {
+            case Constants.MESSAGE_ACTIVE_SOURCE:
+                // received <Active Source>
+                if (mState != STATE_WAITING_FOR_ACTIVE_SOURCE) {
+                    return false;
+                }
+                mActionTimer.clearTimerMessage();
+                int physicalAddress = HdmiUtils.twoBytesToInt(cmd.getParams());
+                if (physicalAddress != getSourcePath()) {
+                    audioSystem().setActiveSource(cmd.getSource(), physicalAddress);
+                }
+                queryTvSystemAudioModeSupport();
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    void handleTimerEvent(int state) {
+        if (mState != state) {
+            return;
+        }
+
+        switch (mState) {
+            case STATE_WAITING_FOR_ACTIVE_SOURCE:
+                handleActiveSourceTimeout();
+                break;
+        }
+    }
+
+    protected void sendRequestActiveSource() {
+        sendCommand(HdmiCecMessageBuilder.buildRequestActiveSource(getSourceAddress()),
+                result -> {
+                    if (result != SendMessageResult.SUCCESS) {
+                        if (mSendRequestActiveSourceRetryCount < MAX_RETRY_COUNT) {
+                            mSendRequestActiveSourceRetryCount++;
+                            sendRequestActiveSource();
+                        } else {
+                            audioSystem().setSystemAudioMode(false);
+                            finish();
+                        }
+                    }
+                });
+    }
+
+    protected void sendSetSystemAudioMode(boolean on, int dest) {
+        sendCommand(HdmiCecMessageBuilder.buildSetSystemAudioMode(getSourceAddress(),
+                dest, on), result -> {
+                    if (result != SendMessageResult.SUCCESS) {
+                        if (mSendSetSystemAudioModeRetryCount < MAX_RETRY_COUNT) {
+                            mSendSetSystemAudioModeRetryCount++;
+                            sendSetSystemAudioMode(on, dest);
+                        } else {
+                            audioSystem().setSystemAudioMode(false);
+                            finish();
+                        }
+                    }
+                });
+    }
+
+    private void handleActiveSourceTimeout() {
+        HdmiLogger.debug("Cannot get active source.");
+        audioSystem().setSystemAudioMode(false);
+        finish();
+    }
+
+    private void queryTvSystemAudioModeSupport() {
+        audioSystem().queryTvSystemAudioModeSupport(
+                supported -> {
+                    if (supported) {
+                        if (audioSystem().setSystemAudioMode(true)) {
+                            sendSetSystemAudioMode(true, Constants.ADDR_BROADCAST);
+                        }
+                        finish();
+                    } else {
+                        audioSystem().setSystemAudioMode(false);
+                        finish();
+                    }
+                });
+    }
+
+    private void switchToRelevantInputForDeviceAt(int physicalAddress) {
+        // TODO(shubang): implement this method
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
index d41a36c..13f0f4ae 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
@@ -64,7 +64,7 @@
     }
 
     private void handleSendGiveAudioStatusFailure() {
-        // Inform to all application that the audio status (volumn, mute) of
+        // Inform to all application that the audio status (volume, mute) of
         // the audio amplifier is unknown.
         tv().setAudioStatus(false, Constants.UNKNOWN_VOLUME);
 
diff --git a/services/core/java/com/android/server/input/InputForwarder.java b/services/core/java/com/android/server/input/InputForwarder.java
index 38a1cd7..00af839 100644
--- a/services/core/java/com/android/server/input/InputForwarder.java
+++ b/services/core/java/com/android/server/input/InputForwarder.java
@@ -19,7 +19,6 @@
 import android.app.IInputForwarder;
 import android.hardware.input.InputManagerInternal;
 import android.view.InputEvent;
-import android.view.MotionEvent;
 
 import com.android.server.LocalServices;
 
@@ -40,9 +39,7 @@
 
     @Override
     public boolean forwardEvent(InputEvent event) {
-        if (event instanceof MotionEvent) {
-            ((MotionEvent) event).setDisplayId(mDisplayId);
-        }
+        event.setDisplayId(mDisplayId);
         return mInputManagerInternal.injectInputEvent(event, INJECT_INPUT_EVENT_MODE_ASYNC);
     }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/job/GrantedUriPermissions.java b/services/core/java/com/android/server/job/GrantedUriPermissions.java
index 8fecb8f..005b189 100644
--- a/services/core/java/com/android/server/job/GrantedUriPermissions.java
+++ b/services/core/java/com/android/server/job/GrantedUriPermissions.java
@@ -17,6 +17,7 @@
 package com.android.server.job;
 
 import android.app.IActivityManager;
+import android.app.UriGrantsManager;
 import android.content.ClipData;
 import android.content.ContentProvider;
 import android.content.Intent;
@@ -26,6 +27,8 @@
 import android.os.UserHandle;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
+import com.android.server.LocalServices;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -42,16 +45,14 @@
         mGrantFlags = grantFlags;
         mSourceUserId = UserHandle.getUserId(uid);
         mTag = tag;
-        mPermissionOwner = am.newUriPermissionOwner("job: " + tag);
+        mPermissionOwner = LocalServices
+                .getService(UriGrantsManagerInternal.class).newUriPermissionOwner("job: " + tag);
     }
 
     public void revoke(IActivityManager am) {
         for (int i = mUris.size()-1; i >= 0; i--) {
-            try {
-                am.revokeUriPermissionFromOwner(mPermissionOwner, mUris.get(i),
-                        mGrantFlags, mSourceUserId);
-            } catch (RemoteException e) {
-            }
+            LocalServices.getService(UriGrantsManagerInternal.class).revokeUriPermissionFromOwner(
+                    mPermissionOwner, mUris.get(i), mGrantFlags, mSourceUserId);
         }
         mUris.clear();
     }
@@ -119,8 +120,8 @@
             if (curPerms == null) {
                 curPerms = new GrantedUriPermissions(am, grantFlags, sourceUid, tag);
             }
-            am.grantUriPermissionFromOwner(curPerms.mPermissionOwner, sourceUid, targetPackage,
-                    uri, grantFlags, sourceUserId, targetUserId);
+            UriGrantsManager.getService().grantUriPermissionFromOwner(curPerms.mPermissionOwner,
+                    sourceUid, targetPackage, uri, grantFlags, sourceUserId, targetUserId);
             curPerms.mUris.add(uri);
         } catch (RemoteException e) {
             Slog.e("JobScheduler", "AM dead");
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 0b7c5b9..260633a 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -32,6 +32,7 @@
 import android.app.job.JobProtoEnums;
 import android.app.job.JobScheduler;
 import android.app.job.JobService;
+import android.app.job.JobSnapshot;
 import android.app.job.JobWorkItem;
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
@@ -2724,6 +2725,55 @@
                 (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
                         this, in, out, err, args, callback, resultReceiver);
         }
+
+        /**
+         * <b>For internal system user only!</b>
+         * Returns a list of all currently-executing jobs.
+         */
+        @Override
+        public List<JobInfo> getStartedJobs() {
+            final int uid = Binder.getCallingUid();
+            if (uid != Process.SYSTEM_UID) {
+                throw new SecurityException(
+                    "getStartedJobs() is system internal use only.");
+            }
+
+            final ArrayList<JobInfo> runningJobs;
+
+            synchronized (mLock) {
+                runningJobs = new ArrayList<>(mActiveServices.size());
+                for (JobServiceContext jsc : mActiveServices) {
+                    final JobStatus job = jsc.getRunningJobLocked();
+                    if (job != null) {
+                        runningJobs.add(job.getJob());
+                    }
+                }
+            }
+
+            return runningJobs;
+        }
+
+        /**
+         * <b>For internal system user only!</b>
+         * Returns a snapshot of the state of all jobs known to the system.
+         *
+         * <p class="note">This is a slow operation, so it should be called sparingly.
+         */
+        @Override
+        public List<JobSnapshot> getAllJobSnapshots() {
+            final int uid = Binder.getCallingUid();
+            if (uid != Process.SYSTEM_UID) {
+                throw new SecurityException(
+                    "getAllJobSnapshots() is system internal use only.");
+            }
+            synchronized (mLock) {
+                final ArrayList<JobSnapshot> snapshots = new ArrayList<>(mJobs.size());
+                mJobs.forEachJob((job) -> snapshots.add(
+                        new JobSnapshot(job.getJob(), job.getSatisfiedConstraintFlags(),
+                                isReadyToBeExecutedLocked(job))));
+                return snapshots;
+            }
+        }
     };
 
     // Shell command infrastructure: run the given job immediately
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index 644f2c4..e3c311f 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -16,41 +16,33 @@
 
 package com.android.server.job.controllers;
 
-import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
-
-import android.app.AlarmManager;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.util.ArraySet;
-import android.util.Log;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.am.ActivityManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
+import com.android.server.job.controllers.idle.CarIdlenessTracker;
+import com.android.server.job.controllers.idle.DeviceIdlenessTracker;
+import com.android.server.job.controllers.idle.IdlenessListener;
+import com.android.server.job.controllers.idle.IdlenessTracker;
 
 import java.util.function.Predicate;
 
-public final class IdleController extends StateController {
-    private static final String TAG = "JobScheduler.Idle";
-    private static final boolean DEBUG = JobSchedulerService.DEBUG
-            || Log.isLoggable(TAG, Log.DEBUG);
-
+public final class IdleController extends StateController implements IdlenessListener {
+    private static final String TAG = "JobScheduler.IdleController";
     // Policy: we decide that we're "idle" if the device has been unused /
     // screen off or dreaming or wireless charging dock idle for at least this long
-    private long mInactivityIdleThreshold;
-    private long mIdleWindowSlop;
     final ArraySet<JobStatus> mTrackedTasks = new ArraySet<>();
     IdlenessTracker mIdleTracker;
 
     public IdleController(JobSchedulerService service) {
         super(service);
-        initIdleStateTracking();
+        initIdleStateTracking(mContext);
     }
 
     /**
@@ -74,9 +66,10 @@
     }
 
     /**
-     * Interaction with the task manager service
+     * State-change notifications from the idleness tracker
      */
-    void reportNewIdleState(boolean isIdle) {
+    @Override
+    public void reportNewIdleState(boolean isIdle) {
         synchronized (mLock) {
             for (int i = mTrackedTasks.size()-1; i >= 0; i--) {
                 mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(isIdle);
@@ -89,141 +82,22 @@
      * Idle state tracking, and messaging with the task manager when
      * significant state changes occur
      */
-    private void initIdleStateTracking() {
-        mInactivityIdleThreshold = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_jobSchedulerInactivityIdleThreshold);
-        mIdleWindowSlop = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_jobSchedulerIdleWindowSlop);
-        mIdleTracker = new IdlenessTracker();
-        mIdleTracker.startTracking();
-    }
-
-    final class IdlenessTracker extends BroadcastReceiver {
-        private AlarmManager mAlarm;
-
-        // After construction, mutations of idle/screen-on state will only happen
-        // on the main looper thread, either in onReceive() or in an alarm callback.
-        private boolean mIdle;
-        private boolean mScreenOn;
-        private boolean mDockIdle;
-
-        private AlarmManager.OnAlarmListener mIdleAlarmListener = () -> {
-            handleIdleTrigger();
-        };
-
-        public IdlenessTracker() {
-            mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-
-            // At boot we presume that the user has just "interacted" with the
-            // device in some meaningful way.
-            mIdle = false;
-            mScreenOn = true;
-            mDockIdle = false;
+    private void initIdleStateTracking(Context ctx) {
+        final boolean isCar = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_AUTOMOTIVE);
+        if (isCar) {
+            mIdleTracker = new CarIdlenessTracker();
+        } else {
+            mIdleTracker = new DeviceIdlenessTracker();
         }
-
-        public boolean isIdle() {
-            return mIdle;
-        }
-
-        public void startTracking() {
-            IntentFilter filter = new IntentFilter();
-
-            // Screen state
-            filter.addAction(Intent.ACTION_SCREEN_ON);
-            filter.addAction(Intent.ACTION_SCREEN_OFF);
-
-            // Dreaming state
-            filter.addAction(Intent.ACTION_DREAMING_STARTED);
-            filter.addAction(Intent.ACTION_DREAMING_STOPPED);
-
-            // Debugging/instrumentation
-            filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
-
-            // Wireless charging dock state
-            filter.addAction(Intent.ACTION_DOCK_IDLE);
-            filter.addAction(Intent.ACTION_DOCK_ACTIVE);
-
-            mContext.registerReceiver(this, filter);
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (action.equals(Intent.ACTION_SCREEN_ON)
-                    || action.equals(Intent.ACTION_DREAMING_STOPPED)
-                    || action.equals(Intent.ACTION_DOCK_ACTIVE)) {
-                if (action.equals(Intent.ACTION_DOCK_ACTIVE)) {
-                    if (!mScreenOn) {
-                        // Ignore this intent during screen off
-                        return;
-                    } else {
-                        mDockIdle = false;
-                    }
-                } else {
-                    mScreenOn = true;
-                    mDockIdle = false;
-                }
-                if (DEBUG) {
-                    Slog.v(TAG,"exiting idle : " + action);
-                }
-                //cancel the alarm
-                mAlarm.cancel(mIdleAlarmListener);
-                if (mIdle) {
-                // possible transition to not-idle
-                    mIdle = false;
-                    reportNewIdleState(mIdle);
-                }
-            } else if (action.equals(Intent.ACTION_SCREEN_OFF)
-                    || action.equals(Intent.ACTION_DREAMING_STARTED)
-                    || action.equals(Intent.ACTION_DOCK_IDLE)) {
-                // when the screen goes off or dreaming starts or wireless charging dock in idle,
-                // we schedule the alarm that will tell us when we have decided the device is
-                // truly idle.
-                if (action.equals(Intent.ACTION_DOCK_IDLE)) {
-                    if (!mScreenOn) {
-                        // Ignore this intent during screen off
-                        return;
-                    } else {
-                        mDockIdle = true;
-                    }
-                } else {
-                    mScreenOn = false;
-                    mDockIdle = false;
-                }
-                final long nowElapsed = sElapsedRealtimeClock.millis();
-                final long when = nowElapsed + mInactivityIdleThreshold;
-                if (DEBUG) {
-                    Slog.v(TAG, "Scheduling idle : " + action + " now:" + nowElapsed + " when="
-                            + when);
-                }
-                mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                        when, mIdleWindowSlop, "JS idleness", mIdleAlarmListener, null);
-            } else if (action.equals(ActivityManagerService.ACTION_TRIGGER_IDLE)) {
-                handleIdleTrigger();
-            }
-        }
-
-        private void handleIdleTrigger() {
-            // idle time starts now. Do not set mIdle if screen is on.
-            if (!mIdle && (!mScreenOn || mDockIdle)) {
-                if (DEBUG) {
-                    Slog.v(TAG, "Idle trigger fired @ " + sElapsedRealtimeClock.millis());
-                }
-                mIdle = true;
-                reportNewIdleState(mIdle);
-            } else {
-                if (DEBUG) {
-                    Slog.v(TAG, "TRIGGER_IDLE received but not changing state; idle="
-                            + mIdle + " screen=" + mScreenOn);
-                }
-            }
-        }
+        mIdleTracker.startTracking(ctx, this);
     }
 
     @Override
     public void dumpControllerStateLocked(IndentingPrintWriter pw,
             Predicate<JobStatus> predicate) {
         pw.println("Currently idle: " + mIdleTracker.isIdle());
+        pw.println("Idleness tracker:"); mIdleTracker.dump(pw);
         pw.println();
 
         for (int i = 0; i < mTrackedTasks.size(); i++) {
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index a1e066e..3f8941d 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -694,6 +694,10 @@
         mInternalFlags |= flags;
     }
 
+    public int getSatisfiedConstraintFlags() {
+        return satisfiedConstraints;
+    }
+
     public void maybeAddForegroundExemption(Predicate<Integer> uidForegroundChecker) {
         // Jobs with time constraints shouldn't be exempted.
         if (job.hasEarlyConstraint() || job.hasLateConstraint()) {
diff --git a/services/core/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java b/services/core/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
new file mode 100644
index 0000000..596a4c0
--- /dev/null
+++ b/services/core/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers.idle;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import android.util.Log;
+import android.util.Slog;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.job.JobSchedulerService;
+
+import java.io.PrintWriter;
+
+public final class CarIdlenessTracker extends BroadcastReceiver implements IdlenessTracker {
+    private static final String TAG = "JobScheduler.CarIdlenessTracker";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    public static final String ACTION_GARAGE_MODE_ON =
+            "com.android.server.jobscheduler.GARAGE_MODE_ON";
+    public static final String ACTION_GARAGE_MODE_OFF =
+            "com.android.server.jobscheduler.GARAGE_MODE_OFF";
+
+    public static final String ACTION_FORCE_IDLE = "com.android.server.jobscheduler.FORCE_IDLE";
+    public static final String ACTION_UNFORCE_IDLE = "com.android.server.jobscheduler.UNFORCE_IDLE";
+
+    // After construction, mutations of idle/screen-on state will only happen
+    // on the main looper thread, either in onReceive() or in an alarm callback.
+    private boolean mIdle;
+    private boolean mGarageModeOn;
+    private boolean mForced;
+    private IdlenessListener mIdleListener;
+
+    public CarIdlenessTracker() {
+        // At boot we presume that the user has just "interacted" with the
+        // device in some meaningful way.
+        mIdle = false;
+        mGarageModeOn = false;
+        mForced = false;
+    }
+
+    @Override
+    public boolean isIdle() {
+        return mIdle;
+    }
+
+    @Override
+    public void startTracking(Context context, IdlenessListener listener) {
+        mIdleListener = listener;
+
+        IntentFilter filter = new IntentFilter();
+
+        // State of GarageMode
+        filter.addAction(ACTION_GARAGE_MODE_ON);
+        filter.addAction(ACTION_GARAGE_MODE_OFF);
+
+        // Debugging/instrumentation
+        filter.addAction(ACTION_FORCE_IDLE);
+        filter.addAction(ACTION_UNFORCE_IDLE);
+        filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
+
+        context.registerReceiver(this, filter);
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.print("  mIdle: "); pw.println(mIdle);
+        pw.print("  mGarageModeOn: "); pw.println(mGarageModeOn);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        logIfDebug("Received action: " + action);
+
+        // Check for forced actions
+        if (action.equals(ACTION_FORCE_IDLE)) {
+            logIfDebug("Forcing idle...");
+            setForceIdleState(true);
+        } else if (action.equals(ACTION_UNFORCE_IDLE)) {
+            logIfDebug("Unforcing idle...");
+            setForceIdleState(false);
+        } else if (action.equals(ACTION_GARAGE_MODE_ON)) {
+            logIfDebug("GarageMode is on...");
+            mGarageModeOn = true;
+            updateIdlenessState();
+        } else if (action.equals(ACTION_GARAGE_MODE_OFF)) {
+            logIfDebug("GarageMode is off...");
+            mGarageModeOn = false;
+            updateIdlenessState();
+        } else if (action.equals(ActivityManagerService.ACTION_TRIGGER_IDLE)) {
+            if (!mGarageModeOn) {
+                logIfDebug("Idle trigger fired...");
+                triggerIdlenessOnce();
+            } else {
+                logIfDebug("TRIGGER_IDLE received but not changing state; idle="
+                        + mIdle + " screen=" + mGarageModeOn);
+            }
+        }
+    }
+
+    private void setForceIdleState(boolean forced) {
+        mForced = forced;
+        updateIdlenessState();
+    }
+
+    private void updateIdlenessState() {
+        final boolean newState = (mForced || mGarageModeOn);
+        if (mIdle != newState) {
+            // State of idleness changed. Notifying idleness controller
+            logIfDebug("Device idleness changed. New idle=" + newState);
+            mIdle = newState;
+            mIdleListener.reportNewIdleState(mIdle);
+        } else {
+            // Nothing changed, device idleness is in the same state as new state
+            logIfDebug("Device idleness is the same. Current idle=" + newState);
+        }
+    }
+
+    private void triggerIdlenessOnce() {
+        // This is simply triggering idleness once until some constraint will switch it back off
+        if (mIdle) {
+            // Already in idle state. Nothing to do
+            logIfDebug("Device is already idle");
+        } else {
+            // Going idle once
+            logIfDebug("Device is going idle once");
+            mIdle = true;
+            mIdleListener.reportNewIdleState(mIdle);
+        }
+    }
+
+    private void logIfDebug(String msg) {
+        if (DEBUG) {
+            Slog.v(TAG, msg);
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java b/services/core/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
new file mode 100644
index 0000000..a85bd40
--- /dev/null
+++ b/services/core/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers.idle;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import android.util.Log;
+import android.util.Slog;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.job.JobSchedulerService;
+
+import java.io.PrintWriter;
+
+public final class DeviceIdlenessTracker extends BroadcastReceiver implements IdlenessTracker {
+    private static final String TAG = "JobScheduler.DeviceIdlenessTracker";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    private AlarmManager mAlarm;
+
+    // After construction, mutations of idle/screen-on state will only happen
+    // on the main looper thread, either in onReceive() or in an alarm callback.
+    private long mInactivityIdleThreshold;
+    private long mIdleWindowSlop;
+    private boolean mIdle;
+    private boolean mScreenOn;
+    private boolean mDockIdle;
+    private IdlenessListener mIdleListener;
+
+    private AlarmManager.OnAlarmListener mIdleAlarmListener = () -> {
+        handleIdleTrigger();
+    };
+
+    public DeviceIdlenessTracker() {
+        // At boot we presume that the user has just "interacted" with the
+        // device in some meaningful way.
+        mIdle = false;
+        mScreenOn = true;
+        mDockIdle = false;
+    }
+
+    @Override
+    public boolean isIdle() {
+        return mIdle;
+    }
+
+    @Override
+    public void startTracking(Context context, IdlenessListener listener) {
+        mIdleListener = listener;
+        mInactivityIdleThreshold = context.getResources().getInteger(
+                com.android.internal.R.integer.config_jobSchedulerInactivityIdleThreshold);
+        mIdleWindowSlop = context.getResources().getInteger(
+                com.android.internal.R.integer.config_jobSchedulerIdleWindowSlop);
+        mAlarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+
+        IntentFilter filter = new IntentFilter();
+
+        // Screen state
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+
+        // Dreaming state
+        filter.addAction(Intent.ACTION_DREAMING_STARTED);
+        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
+
+        // Debugging/instrumentation
+        filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
+
+        // Wireless charging dock state
+        filter.addAction(Intent.ACTION_DOCK_IDLE);
+        filter.addAction(Intent.ACTION_DOCK_ACTIVE);
+
+        context.registerReceiver(this, filter);
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.print("  mIdle: "); pw.println(mIdle);
+        pw.print("  mScreenOn: "); pw.println(mScreenOn);
+        pw.print("  mDockIdle: "); pw.println(mDockIdle);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        if (action.equals(Intent.ACTION_SCREEN_ON)
+                || action.equals(Intent.ACTION_DREAMING_STOPPED)
+                || action.equals(Intent.ACTION_DOCK_ACTIVE)) {
+            if (action.equals(Intent.ACTION_DOCK_ACTIVE)) {
+                if (!mScreenOn) {
+                    // Ignore this intent during screen off
+                    return;
+                } else {
+                    mDockIdle = false;
+                }
+            } else {
+                mScreenOn = true;
+                mDockIdle = false;
+            }
+            if (DEBUG) {
+                Slog.v(TAG,"exiting idle : " + action);
+            }
+            //cancel the alarm
+            mAlarm.cancel(mIdleAlarmListener);
+            if (mIdle) {
+            // possible transition to not-idle
+                mIdle = false;
+                mIdleListener.reportNewIdleState(mIdle);
+            }
+        } else if (action.equals(Intent.ACTION_SCREEN_OFF)
+                || action.equals(Intent.ACTION_DREAMING_STARTED)
+                || action.equals(Intent.ACTION_DOCK_IDLE)) {
+            // when the screen goes off or dreaming starts or wireless charging dock in idle,
+            // we schedule the alarm that will tell us when we have decided the device is
+            // truly idle.
+            if (action.equals(Intent.ACTION_DOCK_IDLE)) {
+                if (!mScreenOn) {
+                    // Ignore this intent during screen off
+                    return;
+                } else {
+                    mDockIdle = true;
+                }
+            } else {
+                mScreenOn = false;
+                mDockIdle = false;
+            }
+            final long nowElapsed = sElapsedRealtimeClock.millis();
+            final long when = nowElapsed + mInactivityIdleThreshold;
+            if (DEBUG) {
+                Slog.v(TAG, "Scheduling idle : " + action + " now:" + nowElapsed + " when="
+                        + when);
+            }
+            mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    when, mIdleWindowSlop, "JS idleness", mIdleAlarmListener, null);
+        } else if (action.equals(ActivityManagerService.ACTION_TRIGGER_IDLE)) {
+            handleIdleTrigger();
+        }
+    }
+
+    private void handleIdleTrigger() {
+        // idle time starts now. Do not set mIdle if screen is on.
+        if (!mIdle && (!mScreenOn || mDockIdle)) {
+            if (DEBUG) {
+                Slog.v(TAG, "Idle trigger fired @ " + sElapsedRealtimeClock.millis());
+            }
+            mIdle = true;
+            mIdleListener.reportNewIdleState(mIdle);
+        } else {
+            if (DEBUG) {
+                Slog.v(TAG, "TRIGGER_IDLE received but not changing state; idle="
+                        + mIdle + " screen=" + mScreenOn);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/job/controllers/idle/IdlenessListener.java b/services/core/java/com/android/server/job/controllers/idle/IdlenessListener.java
new file mode 100644
index 0000000..7ffd7cd
--- /dev/null
+++ b/services/core/java/com/android/server/job/controllers/idle/IdlenessListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers.idle;
+
+/**
+ * Interface through which an IdlenessTracker informs the job scheduler of
+ * changes in the device's inactivity state.
+ */
+public interface IdlenessListener {
+    /**
+     * Tell the job scheduler that the device's idle state has changed.
+     *
+     * @param deviceIsIdle {@code true} to indicate that the device is now considered
+     * to be idle; {@code false} to indicate that the device is now being interacted with,
+     * so jobs with idle constraints should not be run.
+     */
+    void reportNewIdleState(boolean deviceIsIdle);
+}
diff --git a/services/core/java/com/android/server/job/controllers/idle/IdlenessTracker.java b/services/core/java/com/android/server/job/controllers/idle/IdlenessTracker.java
new file mode 100644
index 0000000..09f01c2
--- /dev/null
+++ b/services/core/java/com/android/server/job/controllers/idle/IdlenessTracker.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers.idle;
+
+import android.content.Context;
+
+import java.io.PrintWriter;
+
+public interface IdlenessTracker {
+    /**
+     * One-time initialization:  this method is called once, after construction of
+     * the IdlenessTracker instance.  This is when the tracker should actually begin
+     * monitoring whatever signals it consumes in deciding when the device is in a
+     * non-interacting state.  When the idle state changes thereafter, the given
+     * listener must be called to report the new state.
+     */
+    void startTracking(Context context, IdlenessListener listener);
+
+    /**
+     * Report whether the device is currently considered "idle" for purposes of
+     * running scheduled jobs with idleness constraints.
+     *
+     * @return {@code true} if the job scheduler should consider idleness
+     * constraints to be currently satisfied; {@code false} otherwise.
+     */
+    boolean isIdle();
+
+    /**
+     * Dump useful information about tracked idleness-related state in plaintext.
+     */
+    void dump(PrintWriter pw);
+}
diff --git a/services/core/java/com/android/server/location/ContextHubClientManager.java b/services/core/java/com/android/server/location/ContextHubClientManager.java
index 74930c8..4243f02 100644
--- a/services/core/java/com/android/server/location/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/ContextHubClientManager.java
@@ -45,7 +45,7 @@
     /*
      * Local flag to enable debug logging.
      */
-    private static final boolean DEBUG_LOG_ENABLED = true;
+    private static final boolean DEBUG_LOG_ENABLED = false;
 
     /*
      * The context of the service.
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index dc95d41..27509de 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -77,6 +77,11 @@
 
     private static final int OS_APP_INSTANCE = -1;
 
+    /*
+     * Local flag to enable debug logging.
+     */
+    private static final boolean DEBUG_LOG_ENABLED = false;
+
     private final Context mContext;
 
     private final Map<Integer, ContextHubInfo> mContextHubIdToInfoMap;
@@ -779,12 +784,16 @@
 
         int msgVersion = 0;
         int callbacksCount = mCallbacksList.beginBroadcast();
-        Log.d(TAG, "Sending message " + msgType + " version " + msgVersion + " from hubHandle " +
-                contextHubHandle + ", appInstance " + appInstance + ", callBackCount "
-                + callbacksCount);
+        if (DEBUG_LOG_ENABLED) {
+            Log.v(TAG, "Sending message " + msgType + " version " + msgVersion + " from hubHandle "
+                    + contextHubHandle + ", appInstance " + appInstance + ", callBackCount "
+                    + callbacksCount);
+        }
 
         if (callbacksCount < 1) {
-            Log.v(TAG, "No message callbacks registered.");
+            if (DEBUG_LOG_ENABLED) {
+                Log.v(TAG, "No message callbacks registered.");
+            }
             return 0;
         }
 
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 4edd48f..a54811b 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -69,6 +69,7 @@
 import android.provider.Settings;
 import android.provider.Telephony.Carriers;
 import android.telephony.CarrierConfigManager;
+import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
@@ -2507,13 +2508,20 @@
         if (apn == null) {
             return APN_INVALID;
         }
-
+        TelephonyManager phone = (TelephonyManager)
+                mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        // Carrier configuration may override framework roaming state, we need to use the actual
+        // modem roaming state instead of the framework roaming state.
+        boolean isDataRoamingFromRegistration = phone.getServiceState().
+                getDataRoamingFromRegistration();
+        String projection = isDataRoamingFromRegistration ? Carriers.ROAMING_PROTOCOL :
+                Carriers.PROTOCOL;
         String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
         Cursor cursor = null;
         try {
             cursor = mContext.getContentResolver().query(
                     Carriers.CONTENT_URI,
-                    new String[]{Carriers.PROTOCOL},
+                    new String[]{projection},
                     selection,
                     null,
                     Carriers.DEFAULT_SORT_ORDER);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index c6a8712..adfa8d5 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2012,7 +2012,7 @@
         enforceShell();
         final long origId = Binder.clearCallingIdentity();
         try {
-            (new LockSettingsShellCommand(mContext, new LockPatternUtils(mContext))).exec(
+            (new LockSettingsShellCommand(new LockPatternUtils(mContext))).exec(
                     this, in, out, err, args, callback, resultReceiver);
         } finally {
             Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index 4d2cf32..07f23ce 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -21,13 +21,13 @@
 import static com.android.internal.widget.LockPatternUtils.stringToPattern;
 
 import android.app.ActivityManager;
-import android.content.Context;
-import android.os.RemoteException;
 import android.os.ShellCommand;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
 
+import java.io.PrintWriter;
+
 class LockSettingsShellCommand extends ShellCommand {
 
     private static final String COMMAND_SET_PATTERN = "set-pattern";
@@ -38,20 +38,22 @@
     private static final String COMMAND_SET_DISABLED = "set-disabled";
     private static final String COMMAND_VERIFY = "verify";
     private static final String COMMAND_GET_DISABLED = "get-disabled";
+    private static final String COMMAND_HELP = "help";
 
     private int mCurrentUserId;
     private final LockPatternUtils mLockPatternUtils;
-    private final Context mContext;
     private String mOld = "";
     private String mNew = "";
 
-    LockSettingsShellCommand(Context context, LockPatternUtils lockPatternUtils) {
-        mContext = context;
+    LockSettingsShellCommand(LockPatternUtils lockPatternUtils) {
         mLockPatternUtils = lockPatternUtils;
     }
 
     @Override
     public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
         try {
             mCurrentUserId = ActivityManager.getService().getCurrentUser().id;
 
@@ -84,6 +86,9 @@
                 case COMMAND_GET_DISABLED:
                     runGetDisabled();
                     break;
+                case COMMAND_HELP:
+                    onHelp();
+                    break;
                 default:
                     getErrPrintWriter().println("Unknown command: " + cmd);
                     break;
@@ -103,6 +108,43 @@
 
     @Override
     public void onHelp() {
+        try (final PrintWriter pw = getOutPrintWriter();) {
+            pw.println("lockSettings service commands:");
+            pw.println("");
+            pw.println("NOTE: when lock screen is set, all commands require the --old <CREDENTIAL>"
+                    + " argument.");
+            pw.println("");
+            pw.println("  help");
+            pw.println("    Prints this help text.");
+            pw.println("");
+            pw.println("  get-disabled [--old <CREDENTIAL>] [--user USER_ID]");
+            pw.println("    Checks whether lock screen is disabled.");
+            pw.println("");
+            pw.println("  set-disabled [--old <CREDENTIAL>] [--user USER_ID] <true|false>");
+            pw.println("    When true, disables lock screen.");
+            pw.println("");
+            pw.println("  set-pattern [--old <CREDENTIAL>] [--user USER_ID] <PATTERN>");
+            pw.println("    Sets the lock screen as pattern, using the given PATTERN to unlock.");
+            pw.println("");
+            pw.println("  set-pin [--old <CREDENTIAL>] [--user USER_ID] <PIN>");
+            pw.println("    Sets the lock screen as PIN, using the given PIN to unlock.");
+            pw.println("");
+            pw.println("  set-pin [--old <CREDENTIAL>] [--user USER_ID] <PASSWORD>");
+            pw.println("    Sets the lock screen as password, using the given PASSOWRD to unlock.");
+            pw.println("");
+            pw.println("  sp [--old <CREDENTIAL>] [--user USER_ID]");
+            pw.println("    Gets whether synthetic password is enabled.");
+            pw.println("");
+            pw.println("  sp [--old <CREDENTIAL>] [--user USER_ID] <1|0>");
+            pw.println("    Enables / disables synthetic password.");
+            pw.println("");
+            pw.println("  clear [--old <CREDENTIAL>] [--user USER_ID]");
+            pw.println("    Clears the lock credentials.");
+            pw.println("");
+            pw.println("  verify [--old <CREDENTIAL>] [--user USER_ID]");
+            pw.println("    Verifies the lock credentials.");
+            pw.println("");
+        }
     }
 
     private void parseArgs() {
@@ -134,27 +176,27 @@
                 mLockPatternUtils.isSyntheticPasswordEnabled()));
     }
 
-    private void runSetPattern() throws RemoteException {
+    private void runSetPattern() {
         mLockPatternUtils.saveLockPattern(stringToPattern(mNew), mOld, mCurrentUserId);
         getOutPrintWriter().println("Pattern set to '" + mNew + "'");
     }
 
-    private void runSetPassword() throws RemoteException {
+    private void runSetPassword() {
         mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_ALPHABETIC, mCurrentUserId);
         getOutPrintWriter().println("Password set to '" + mNew + "'");
     }
 
-    private void runSetPin() throws RemoteException {
+    private void runSetPin() {
         mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_NUMERIC, mCurrentUserId);
         getOutPrintWriter().println("Pin set to '" + mNew + "'");
     }
 
-    private void runClear() throws RemoteException {
+    private void runClear() {
         mLockPatternUtils.clearLock(mOld, mCurrentUserId);
         getOutPrintWriter().println("Lock credential cleared");
     }
 
-    private void runSetDisabled() throws RemoteException {
+    private void runSetDisabled() {
         final boolean disabled = Boolean.parseBoolean(mNew);
         mLockPatternUtils.setLockScreenDisabled(disabled, mCurrentUserId);
         getOutPrintWriter().println("Lock screen disabled set to " + disabled);
@@ -165,7 +207,7 @@
         getOutPrintWriter().println(isLockScreenDisabled);
     }
 
-    private boolean checkCredential() throws RemoteException {
+    private boolean checkCredential() {
         final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId);
         final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId);
         if (havePassword || havePattern) {
@@ -186,6 +228,9 @@
                         mLockPatternUtils.reportFailedPasswordAttempt(mCurrentUserId);
                     }
                     getOutPrintWriter().println("Old password '" + mOld + "' didn't match");
+                } else {
+                    // Resets the counter for failed password attempts to 0.
+                    mLockPatternUtils.reportSuccessfulPasswordAttempt(mCurrentUserId);
                 }
                 return result;
             } catch (RequestThrottledException e) {
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 442354b..c938f5e 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -255,8 +255,8 @@
         if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
             // Adjust the volume with a handler not to be blocked by other system service.
             int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
-            postAdjustLocalVolume(stream, direction, flags, packageName, uid, useSuggested,
-                    previousFlagPlaySound);
+            postAdjustLocalVolume(stream, direction, flags, packageName, uid, asSystemService,
+                    useSuggested, previousFlagPlaySound);
         } else {
             if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
                 // Nothing to do, the volume cannot be changed
@@ -462,8 +462,11 @@
     }
 
     private void postAdjustLocalVolume(final int stream, final int direction, final int flags,
-            final String packageName, final int uid, final boolean useSuggested,
-            final int previousFlagPlaySound) {
+            final String callingPackageName, final int callingUid, final boolean asSystemService,
+            final boolean useSuggested, final int previousFlagPlaySound) {
+        final String packageName = asSystemService
+                ? mContext.getOpPackageName() : callingPackageName;
+        final int uid = asSystemService ? Process.SYSTEM_UID : callingUid;
         mHandler.post(new Runnable() {
             @Override
             public void run() {
@@ -481,7 +484,7 @@
                         mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
                                 packageName, uid);
                     }
-                } catch (IllegalArgumentException e) {
+                } catch (IllegalArgumentException | SecurityException e) {
                     Log.e(TAG, "Cannot adjust volume: direction=" + direction + ", stream="
                             + stream + ", flags=" + flags + ", packageName=" + packageName
                             + ", uid=" + uid + ", useSuggested=" + useSuggested
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 68b2a58..dc4405f 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1844,7 +1844,7 @@
                             String packageName = getContext().getOpPackageName();
                             mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
                                     flags, packageName, TAG);
-                        } catch (RemoteException e) {
+                        } catch (RemoteException|SecurityException e) {
                             Log.e(TAG, "Error adjusting default volume.", e);
                         } catch (IllegalArgumentException e) {
                             Log.e(TAG, "Cannot adjust volume: direction=" + direction
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index ab482bb..76f9695 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -430,6 +430,8 @@
 
     private final CountDownLatch mAdminDataAvailableLatch = new CountDownLatch(1);
 
+    private volatile boolean mNetworkManagerReady;
+
     /** Defined network policies. */
     @GuardedBy("mNetworkPoliciesSecondLock")
     final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<>();
@@ -626,6 +628,7 @@
         mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     void updatePowerSaveWhitelistUL() {
         try {
             int[] whitelist = mDeviceIdleController.getAppIdWhitelistExceptIdle();
@@ -652,6 +655,7 @@
      *
      * @return whether any uid has been whitelisted.
      */
+    @GuardedBy("mUidRulesFirstLock")
     boolean addDefaultRestrictBackgroundWhitelistUidsUL() {
         final List<UserInfo> users = mUserManager.getUsers();
         final int numberUsers = users.size();
@@ -664,6 +668,7 @@
         return changed;
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private boolean addDefaultRestrictBackgroundWhitelistUidsUL(int userId) {
         final SystemConfig sysConfig = SystemConfig.getInstance();
         final PackageManager pm = mContext.getPackageManager();
@@ -872,6 +877,7 @@
     }
 
     public CountDownLatch networkScoreAndNetworkManagementServiceReady() {
+        mNetworkManagerReady = true;
         final CountDownLatch initCompleteSignal = new CountDownLatch(1);
         mHandler.post(() -> initService(initCompleteSignal));
         return initCompleteSignal;
@@ -1117,6 +1123,7 @@
      * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
      * to show visible notifications as needed.
      */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     void updateNotificationsNL() {
         if (LOGV) Slog.v(TAG, "updateNotificationsNL()");
         Trace.traceBegin(TRACE_TAG_NETWORK, "updateNotificationsNL");
@@ -1263,6 +1270,7 @@
      * @return relevant subId, or {@link #INVALID_SUBSCRIPTION_ID} when no
      *         matching subId found.
      */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private int findRelevantSubIdNL(NetworkTemplate template) {
         // Mobile template is relevant when any active subscriber matches
         for (int i = 0; i < mSubIdToSubscriberId.size(); i++) {
@@ -1282,6 +1290,7 @@
      * Notify that given {@link NetworkTemplate} is over
      * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
      */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private void notifyOverLimitNL(NetworkTemplate template) {
         if (!mOverLimitNotified.contains(template)) {
             mContext.startActivity(buildNetworkOverLimitIntent(mContext.getResources(), template));
@@ -1289,6 +1298,7 @@
         }
     }
 
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private void notifyUnderLimitNL(NetworkTemplate template) {
         mOverLimitNotified.remove(template);
     }
@@ -1459,6 +1469,7 @@
      * @param subId that has its associated NetworkPolicy updated if necessary
      * @return if any policies were updated
      */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private boolean maybeUpdateMobilePolicyCycleAL(int subId, String subscriberId) {
         if (LOGV) Slog.v(TAG, "maybeUpdateMobilePolicyCycleAL()");
 
@@ -1616,6 +1627,7 @@
      * @param shouldNormalizePolicies true iff network policies need to be normalized after the
      *                                update.
      */
+    @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
     void handleNetworkPoliciesUpdateAL(boolean shouldNormalizePolicies) {
         if (shouldNormalizePolicies) {
             normalizePoliciesNL();
@@ -1630,6 +1642,7 @@
      * Proactively control network data connections when they exceed
      * {@link NetworkPolicy#limitBytes}.
      */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     void updateNetworkEnabledNL() {
         if (LOGV) Slog.v(TAG, "updateNetworkEnabledNL()");
         Trace.traceBegin(TRACE_TAG_NETWORK, "updateNetworkEnabledNL");
@@ -1770,6 +1783,7 @@
      * {@link NetworkPolicy} that need to be enforced. When matches found, set
      * remaining quota based on usage cycle and historical stats.
      */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     void updateNetworkRulesNL() {
         if (LOGV) Slog.v(TAG, "updateNetworkRulesNL()");
         Trace.traceBegin(TRACE_TAG_NETWORK, "updateNetworkRulesNL");
@@ -1954,6 +1968,7 @@
      * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
      * have at least a default mobile policy defined.
      */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private void ensureActiveMobilePolicyAL() {
         if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyAL()");
         if (mSuppressDefaultPolicy) return;
@@ -1974,6 +1989,7 @@
      * @param subscriberId that we check for an existing policy
      * @return true if a mobile network policy was added, or false one already existed.
      */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private boolean ensureActiveMobilePolicyAL(int subId, String subscriberId) {
         // Poke around to see if we already have a policy
         final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
@@ -2033,6 +2049,7 @@
      *
      * @return if the policy was modified
      */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private boolean updateDefaultMobilePolicyAL(int subId, NetworkPolicy policy) {
         if (!policy.inferred) {
             if (LOGD) Slog.d(TAG, "Ignoring user-defined policy " + policy);
@@ -2088,6 +2105,7 @@
         }
     }
 
+    @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
     private void readPolicyAL() {
         if (LOGV) Slog.v(TAG, "readPolicyAL()");
 
@@ -2319,6 +2337,7 @@
      * Perform upgrade step of moving any user-defined meterness overrides over
      * into {@link WifiConfiguration}.
      */
+    @GuardedBy({"mNetworkPoliciesSecondLock", "mUidRulesFirstLock"})
     private void upgradeWifiMeteredOverrideAL() {
         boolean modified = false;
         final WifiManager wm = mContext.getSystemService(WifiManager.class);
@@ -2349,6 +2368,7 @@
         }
     }
 
+    @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
     void writePolicyAL() {
         if (LOGV) Slog.v(TAG, "writePolicyAL()");
 
@@ -2520,6 +2540,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private void setUidPolicyUncheckedUL(int uid, int oldPolicy, int policy, boolean persist) {
         setUidPolicyUncheckedUL(uid, policy, false);
 
@@ -2551,6 +2572,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private void setUidPolicyUncheckedUL(int uid, int policy, boolean persist) {
         if (policy == POLICY_NONE) {
             mUidPolicy.delete(uid);
@@ -2598,6 +2620,7 @@
      * Removes any persistable state associated with given {@link UserHandle}, persisting
      * if any changes that are made.
      */
+    @GuardedBy("mUidRulesFirstLock")
     boolean removeUserStateUL(int userId, boolean writePolicy) {
 
         mLogger.removingUserState(userId);
@@ -2699,10 +2722,12 @@
         }
     }
 
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private void normalizePoliciesNL() {
         normalizePoliciesNL(getNetworkPolicies(mContext.getOpPackageName()));
     }
 
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private void normalizePoliciesNL(NetworkPolicy[] policies) {
         mNetworkPolicy.clear();
         for (NetworkPolicy policy : policies) {
@@ -2792,6 +2817,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private void setRestrictBackgroundUL(boolean restrictBackground) {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackgroundUL");
         try {
@@ -3444,11 +3470,13 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private boolean isUidForegroundOnRestrictBackgroundUL(int uid) {
         final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
         return isProcStateAllowedWhileOnRestrictBackground(procState);
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private boolean isUidForegroundOnRestrictPowerUL(int uid) {
         final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
         return isProcStateAllowedWhileIdleOrPowerSaveMode(procState);
@@ -3464,6 +3492,7 @@
      * {@link #updateRulesForDataUsageRestrictionsUL(int)} and
      * {@link #updateRulesForPowerRestrictionsUL(int)}
      */
+    @GuardedBy("mUidRulesFirstLock")
     private void updateUidStateUL(int uid, int uidState) {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateUidStateUL");
         try {
@@ -3490,6 +3519,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private void removeUidStateUL(int uid) {
         final int index = mUidState.indexOfKey(uid);
         if (index >= 0) {
@@ -3534,6 +3564,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     void updateRulesForPowerSaveUL() {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForPowerSaveUL");
         try {
@@ -3544,10 +3575,12 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     void updateRuleForRestrictPowerUL(int uid) {
         updateRulesForWhitelistedPowerSaveUL(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     void updateRulesForDeviceIdleUL() {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForDeviceIdleUL");
         try {
@@ -3558,12 +3591,14 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     void updateRuleForDeviceIdleUL(int uid) {
         updateRulesForWhitelistedPowerSaveUL(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
     }
 
     // NOTE: since both fw_dozable and fw_powersave uses the same map
     // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
+    @GuardedBy("mUidRulesFirstLock")
     private void updateRulesForWhitelistedPowerSaveUL(boolean enabled, int chain,
             SparseIntArray rules) {
         if (enabled) {
@@ -3608,6 +3643,7 @@
      *        {@link #mPowerSaveWhitelistExceptIdleAppIds} for checking if the {@param uid} is
      *        whitelisted.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private boolean isWhitelistedBatterySaverUL(int uid, boolean deviceIdleMode) {
         final int appId = UserHandle.getAppId(uid);
         boolean isWhitelisted = mPowerSaveTempWhitelistAppIds.get(appId)
@@ -3620,6 +3656,7 @@
 
     // NOTE: since both fw_dozable and fw_powersave uses the same map
     // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
+    @GuardedBy("mUidRulesFirstLock")
     private void updateRulesForWhitelistedPowerSaveUL(int uid, boolean enabled, int chain) {
         if (enabled) {
             final boolean isWhitelisted = isWhitelistedBatterySaverUL(uid,
@@ -3632,6 +3669,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     void updateRulesForAppIdleUL() {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForAppIdleUL");
         try {
@@ -3661,6 +3699,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     void updateRuleForAppIdleUL(int uid) {
         if (!isUidValidForBlacklistRules(uid)) return;
 
@@ -3684,6 +3723,7 @@
      * Toggle the firewall standby chain and inform listeners if the uid rules have effectively
      * changed.
      */
+    @GuardedBy("mUidRulesFirstLock")
     void updateRulesForAppIdleParoleUL() {
         boolean paroled = mUsageStats.isAppIdleParoleOn();
         boolean enableChain = !paroled;
@@ -3716,6 +3756,7 @@
      * Update rules that might be changed by {@link #mRestrictBackground},
      * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
      */
+    @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
     private void updateRulesForGlobalChangeAL(boolean restrictedNetworksChanged) {
         if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
@@ -3737,6 +3778,7 @@
     }
 
     // TODO: rename / document to make it clear these are global (not app-specific) rules
+    @GuardedBy("mUidRulesFirstLock")
     private void updateRulesForRestrictPowerUL() {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL");
         try {
@@ -3748,6 +3790,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private void updateRulesForRestrictBackgroundUL() {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictBackgroundUL");
         try {
@@ -3768,6 +3811,7 @@
     }
 
     // TODO: refactor / consolidate all those updateXyz methods, there are way too many of them...
+    @GuardedBy("mUidRulesFirstLock")
     private void updateRulesForAllAppsUL(@RestrictType int type) {
         if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL-" + type);
@@ -3819,6 +3863,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private void updateRulesForTempWhitelistChangeUL(int appId) {
         final List<UserInfo> users = mUserManager.getUsers();
         final int numUsers = users.size();
@@ -3883,6 +3928,7 @@
     /**
      * Clears all state - internal and external - associated with an UID.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private void onUidDeletedUL(int uid) {
         // First cleanup in-memory state synchronously...
         mUidRules.delete(uid);
@@ -3911,6 +3957,7 @@
      *
      * <p>This method changes both the external firewall rules and the internal state.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private void updateRestrictionRulesForUidUL(int uid) {
         // Methods below only changes the firewall rules for the power-related modes.
         updateRuleForDeviceIdleUL(uid);
@@ -4101,6 +4148,7 @@
      * <p>
      * <strong>NOTE: </strong>This method does not update the firewall rules on {@code netd}.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private void updateRulesForPowerRestrictionsUL(int uid) {
         final int oldUidRules = mUidRules.get(uid, RULE_NONE);
 
@@ -4537,6 +4585,7 @@
      * @param uidRules new UID rules; if {@code null}, only toggles chain state.
      * @param toggle whether the chain should be enabled, disabled, or not changed.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private void setUidFirewallRulesUL(int chain, @Nullable SparseIntArray uidRules,
             @ChainToggleType int toggle) {
         if (uidRules != null) {
@@ -4603,6 +4652,7 @@
     /**
      * Add or remove a uid to the firewall blacklist for all network ifaces.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private void enableFirewallChainUL(int chain, boolean enable) {
         if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
                 mFirewallChainStates.get(chain) == enable) {
@@ -4714,6 +4764,7 @@
         mHandler.getLooper().getQueue().addIdleHandler(handler);
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     @VisibleForTesting
     public void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
         mRestrictBackgroundPowerState = result;
@@ -5024,6 +5075,9 @@
 
     private void handleRestrictedPackagesChangeUL(Set<Integer> oldRestrictedUids,
             Set<Integer> newRestrictedUids) {
+        if (!mNetworkManagerReady) {
+            return;
+        }
         if (oldRestrictedUids == null) {
             for (int uid : newRestrictedUids) {
                 updateRulesForDataUsageRestrictionsUL(uid);
@@ -5042,6 +5096,7 @@
         }
     }
 
+    @GuardedBy("mUidRulesFirstLock")
     private boolean isRestrictedByAdminUL(int uid) {
         final Set<Integer> restrictedUids = mMeteredRestrictedUids.get(
                 UserHandle.getUserId(uid));
diff --git a/services/core/java/com/android/server/net/OWNERS b/services/core/java/com/android/server/net/OWNERS
index 64dc98e..2e91f99 100644
--- a/services/core/java/com/android/server/net/OWNERS
+++ b/services/core/java/com/android/server/net/OWNERS
@@ -1,9 +1,11 @@
 set noparent
 
+codewiz@google.com
 ek@google.com
 jchalard@google.com
 jsharkey@android.com
 lorenzo@google.com
+reminv@google.com
 satk@google.com
 silberst@google.com
 sudheersai@google.com
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index c0fbfbb..18f4bc7 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -150,6 +150,7 @@
         try {
             provider.onConnected();
         } catch (RemoteException e) {
+            Slog.e(TAG, "can't connect to service " + info, e);
             // we tried
         }
         if (mCallback != null) {
diff --git a/services/core/java/com/android/server/notification/CriticalNotificationExtractor.java b/services/core/java/com/android/server/notification/CriticalNotificationExtractor.java
new file mode 100644
index 0000000..a899a08
--- /dev/null
+++ b/services/core/java/com/android/server/notification/CriticalNotificationExtractor.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.util.Slog;
+
+/**
+ * Sets the criticality of a notification record. This is used to allow a bypass to all other
+ * ranking signals. It is required in the automotive use case to facilitate placing emergency and
+ * warning notifications above all others. It does not process notifications unless the system
+ * has the automotive feature flag set.
+ * <p>
+ * Note: it is up to the notification ranking system to determine the effect of criticality values
+ * on a notification record
+ *
+ */
+public class CriticalNotificationExtractor implements NotificationSignalExtractor {
+
+    private static final String TAG = "CriticalNotificationExt";
+    private static final boolean DBG = false;
+    private boolean mSupportsCriticalNotifications = false;
+    /** 
+     * Intended to bypass all other ranking, notification should be placed above all others.
+     * In the automotive case, the notification would be used to tell a driver to pull over
+     * immediately 
+     */
+    static final int CRITICAL = 0;
+    /**
+     * Indicates a notification should be place above all notifications except those marked as
+     * critical. In the automotive case this is a check engine light. 
+     */
+    static final int CRITICAL_LOW = 1;
+    /** Normal notification. */
+    static final int NORMAL = 2;
+
+    @Override
+    public void initialize(Context context, NotificationUsageStats usageStats) {
+        if (DBG) Slog.d(TAG, "Initializing  " + getClass().getSimpleName() + ".");
+        mSupportsCriticalNotifications = supportsCriticalNotifications(context);
+    }
+
+    private boolean supportsCriticalNotifications(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0);
+    }
+
+    @Override
+    public RankingReconsideration process(NotificationRecord record) {
+        if (!mSupportsCriticalNotifications) {
+            if (DBG) Slog.d(TAG, "skipping since system does not support critical notification");
+            return null;
+        }
+        if (record == null || record.getNotification() == null) {
+            if (DBG) Slog.d(TAG, "skipping empty notification");
+            return null;
+        }
+        // Note: The use of both CATEGORY_CAR_EMERGENCY and CATEGORY_CAR_WARNING is restricted to
+        // System apps
+        if (record.isCategory(Notification.CATEGORY_CAR_EMERGENCY)) {
+            record.setCriticality(CRITICAL);
+        } else if (record.isCategory(Notification.CATEGORY_CAR_WARNING)) {
+            record.setCriticality(CRITICAL_LOW);
+        } else {
+            record.setCriticality(NORMAL);
+        }
+        return null;
+    }
+
+    @Override
+    public void setConfig(RankingConfig config) {
+    }
+
+    @Override
+    public void setZenHelper(ZenModeHelper helper) {
+    }
+
+}
diff --git a/services/core/java/com/android/server/notification/ImportanceExtractor.java b/services/core/java/com/android/server/notification/ImportanceExtractor.java
index dfdd55b..ca41b74 100644
--- a/services/core/java/com/android/server/notification/ImportanceExtractor.java
+++ b/services/core/java/com/android/server/notification/ImportanceExtractor.java
@@ -41,7 +41,7 @@
             if (DBG) Slog.d(TAG, "missing config");
             return null;
         }
-        record.setUserImportance(record.getChannel().getImportance());
+        record.calculateImportance();
 
         return null;
     }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 5eb7397..efc18ad 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -54,6 +54,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
@@ -116,9 +117,12 @@
     // contains connections to all connected services, including app services
     // and system services
     private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>();
-    // things that will be put into mServices as soon as they're ready
-    private final ArrayList<String> mServicesBinding = new ArrayList<>();
-    private final ArraySet<String> mServicesRebinding = new ArraySet<>();
+    /**
+     * The services that have been bound by us. If the service is also connected, it will also
+     * be in {@link #mServices}.
+     */
+    private final ArrayList<Pair<ComponentName, Integer>> mServicesBound = new ArrayList<>();
+    private final ArraySet<Pair<ComponentName, Integer>> mServicesRebinding = new ArraySet<>();
 
     // lists the component names of all enabled (and therefore potentially connected)
     // app services for current profiles.
@@ -513,6 +517,30 @@
         return false;
     }
 
+    protected boolean isPackageAllowed(String pkg, int userId) {
+        if (pkg == null) {
+            return false;
+        }
+        ArrayMap<Boolean, ArraySet<String>> allowedByType =
+                mApproved.getOrDefault(userId, new ArrayMap<>());
+        for (int i = 0; i < allowedByType.size(); i++) {
+            ArraySet<String> allowed = allowedByType.valueAt(i);
+            for (String allowedEntry : allowed) {
+                ComponentName component = ComponentName.unflattenFromString(allowedEntry);
+                if (component != null) {
+                    if (pkg.equals(component.getPackageName())) {
+                        return true;
+                    }
+                } else {
+                    if (pkg.equals(allowedEntry)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
     public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList) {
         if (DEBUG) Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage
                 + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
@@ -533,6 +561,11 @@
                 if (mEnabledServicesPackageNames.contains(pkgName)) {
                     anyServicesInvolved = true;
                 }
+                for (int uid : uidList) {
+                    if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) {
+                        anyServicesInvolved = true;
+                    }
+                }
             }
 
             if (anyServicesInvolved) {
@@ -596,6 +629,15 @@
                 + service + " " + service.getClass());
     }
 
+    public boolean isSameUser(IInterface service, int userId) {
+        checkNotNull(service);
+        ManagedServiceInfo info = getServiceFromTokenLocked(service);
+        if (info != null) {
+            return info.isSameUser(userId);
+        }
+        return false;
+    }
+
     public void unregisterService(IInterface service, int userid) {
         checkNotNull(service);
         // no need to check permissions; if your service binder is in the list,
@@ -646,7 +688,11 @@
 
             for (int userId : userIds) {
                 if (enabled) {
-                    registerServiceLocked(component, userId);
+                    if (isPackageOrComponentAllowed(component.toString(), userId)) {
+                        registerServiceLocked(component, userId);
+                    } else {
+                        Slog.d(TAG, component + " no longer has permission to be bound");
+                    }
                 } else {
                     unregisterServiceLocked(component, userId);
                 }
@@ -917,13 +963,13 @@
             final boolean isSystem) {
         if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
 
-        final String servicesBindingTag = name.toString() + "/" + userid;
-        if (mServicesBinding.contains(servicesBindingTag)) {
-            Slog.v(TAG, "Not registering " + name + " as bind is already in progress");
+        final Pair<ComponentName, Integer> servicesBindingTag = Pair.create(name, userid);
+        if (mServicesBound.contains(servicesBindingTag)) {
+            Slog.v(TAG, "Not registering " + name + " is already bound");
             // stop registering this thing already! we're working on it
             return;
         }
-        mServicesBinding.add(servicesBindingTag);
+        mServicesBound.add(servicesBindingTag);
 
         final int N = mServices.size();
         for (int i = N - 1; i >= 0; i--) {
@@ -934,11 +980,7 @@
                 Slog.v(TAG, "    disconnecting old " + getCaption() + ": " + info.service);
                 removeServiceLocked(i);
                 if (info.connection != null) {
-                    try {
-                        mContext.unbindService(info.connection);
-                    } catch (IllegalArgumentException e) {
-                        Slog.e(TAG, "failed to unbind " + name, e);
-                    }
+                    unbindService(info.connection, info.component, info.userid);
                 }
             }
         }
@@ -969,11 +1011,11 @@
 
                 @Override
                 public void onServiceConnected(ComponentName name, IBinder binder) {
+                    Slog.v(TAG, getCaption() + " service connected: " + name);
                     boolean added = false;
                     ManagedServiceInfo info = null;
                     synchronized (mMutex) {
                         mServicesRebinding.remove(servicesBindingTag);
-                        mServicesBinding.remove(servicesBindingTag);
                         try {
                             mService = asInterface(binder);
                             info = newServiceInfo(mService, name,
@@ -991,7 +1033,6 @@
 
                 @Override
                 public void onServiceDisconnected(ComponentName name) {
-                    mServicesBinding.remove(servicesBindingTag);
                     Slog.v(TAG, getCaption() + " connection lost: " + name);
                 }
 
@@ -999,12 +1040,7 @@
                 public void onBindingDied(ComponentName name) {
                     Slog.w(TAG, getCaption() + " binding died: " + name);
                     synchronized (mMutex) {
-                        mServicesBinding.remove(servicesBindingTag);
-                        try {
-                            mContext.unbindService(this);
-                        } catch (IllegalArgumentException e) {
-                            Slog.e(TAG, "failed to unbind " + name, e);
-                        }
+                        unbindService(this, name, userid);
                         if (!mServicesRebinding.contains(servicesBindingTag)) {
                             mServicesRebinding.add(servicesBindingTag);
                             mHandler.postDelayed(new Runnable() {
@@ -1024,12 +1060,12 @@
                 serviceConnection,
                 BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT,
                 new UserHandle(userid))) {
-                mServicesBinding.remove(servicesBindingTag);
+                mServicesBound.remove(servicesBindingTag);
                 Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
                 return;
             }
         } catch (SecurityException ex) {
-            mServicesBinding.remove(servicesBindingTag);
+            mServicesBound.remove(servicesBindingTag);
             Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
         }
     }
@@ -1050,13 +1086,7 @@
             if (name.equals(info.component) && info.userid == userid) {
                 removeServiceLocked(i);
                 if (info.connection != null) {
-                    try {
-                        mContext.unbindService(info.connection);
-                    } catch (IllegalArgumentException ex) {
-                        // something happened to the service: we think we have a connection
-                        // but it's bogus.
-                        Slog.e(TAG, getCaption() + " " + name + " could not be unbound: " + ex);
-                    }
+                    unbindService(info.connection, info.component, info.userid);
                 }
             }
         }
@@ -1121,7 +1151,18 @@
     private void unregisterServiceImpl(IInterface service, int userid) {
         ManagedServiceInfo info = removeServiceImpl(service, userid);
         if (info != null && info.connection != null && !info.isGuest(this)) {
-            mContext.unbindService(info.connection);
+            unbindService(info.connection, info.component, info.userid);
+        }
+    }
+
+    private void unbindService(ServiceConnection connection, ComponentName component, int userId) {
+        try {
+            mContext.unbindService(connection);
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, getCaption() + " " + component + " could not be unbound", e);
+        }
+        synchronized (mMutex) {
+            mServicesBound.remove(Pair.create(component, userId));
         }
     }
 
@@ -1173,6 +1214,13 @@
             proto.end(token);
         }
 
+        public boolean isSameUser(int userId) {
+            if (!isEnabledForCurrentProfiles()) {
+                return false;
+            }
+            return this.userid == userId;
+        }
+
         public boolean enabledAndUserMatches(int nid) {
             if (!isEnabledForCurrentProfiles()) {
                 return false;
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 8be8450..decdac6 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -30,6 +30,7 @@
     void onNotificationClear(int callingUid, int callingPid,
             String pkg, String tag, int id, int userId, String key,
             @NotificationStats.DismissalSurface int dismissalSurface,
+            @NotificationStats.DismissalSentiment int dismissalSentiment,
             NotificationVisibility nv);
     void onNotificationError(int callingUid, int callingPid,
             String pkg, String tag, int id,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 52f4461..ce71dd2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -72,7 +72,6 @@
 import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
-import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
 import static com.android.server.utils.PriorityDump.PRIORITY_ARG;
@@ -91,6 +90,7 @@
 import android.app.IActivityManager;
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
+import android.app.IUriGrantsManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
@@ -98,6 +98,7 @@
 import android.app.NotificationManager.Policy;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
+import android.app.UriGrantsManager;
 import android.app.admin.DeviceAdminInfo;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.backup.BackupManager;
@@ -204,6 +205,7 @@
 import com.android.server.notification.ManagedServices.UserProfiles;
 import com.android.server.policy.PhoneWindowManager;
 import com.android.server.statusbar.StatusBarManagerInternal;
+import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
 import libcore.io.IoUtils;
@@ -318,6 +320,8 @@
     private ICompanionDeviceManager mCompanionManager;
     private AccessibilityManager mAccessibilityManager;
     private IDeviceIdleController mDeviceIdleController;
+    private IUriGrantsManager mUgm;
+    private UriGrantsManagerInternal mUgmInternal;
 
     final IBinder mForegroundToken = new Binder();
     private WorkerHandler mHandler;
@@ -329,6 +333,8 @@
 
     private long[] mFallbackVibrationPattern;
     private boolean mUseAttentionLight;
+    boolean mHasLight = true;
+    boolean mLightEnabled;
     boolean mSystemReady;
 
     private boolean mDisableNotificationEffects;
@@ -343,9 +349,9 @@
     private int mInterruptionFilter = NotificationListenerService.INTERRUPTION_FILTER_UNKNOWN;
 
     // for enabling and disabling notification pulse behavior
-    private boolean mScreenOn = true;
+    boolean mScreenOn = true;
     protected boolean mInCall = false;
-    private boolean mNotificationPulseEnabled;
+    boolean mNotificationPulseEnabled;
 
     private Uri mInCallNotificationUri;
     private AudioAttributes mInCallNotificationAudioAttributes;
@@ -384,6 +390,7 @@
     private static final String ATTR_VERSION = "version";
 
     private RankingHelper mRankingHelper;
+    private PreferencesHelper mPreferencesHelper;
 
     private final UserProfiles mUserProfiles = new UserProfiles();
     private NotificationListeners mListeners;
@@ -478,7 +485,7 @@
 
         String defaultDndAccess = getContext().getResources().getString(
                 com.android.internal.R.string.config_defaultDndAccessPackages);
-        if (defaultListenerAccess != null) {
+        if (defaultDndAccess != null) {
             for (String whitelisted :
                     defaultDndAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR)) {
                 try {
@@ -523,8 +530,8 @@
         while (XmlUtils.nextElementWithin(parser, outerDepth)) {
             if (ZenModeConfig.ZEN_TAG.equals(parser.getName())) {
                 mZenModeHelper.readXml(parser, forRestore);
-            } else if (RankingHelper.TAG_RANKING.equals(parser.getName())){
-                mRankingHelper.readXml(parser, forRestore);
+            } else if (PreferencesHelper.TAG_RANKING.equals(parser.getName())){
+                mPreferencesHelper.readXml(parser, forRestore);
             }
             if (mListeners.getConfig().xmlTag.equals(parser.getName())) {
                 mListeners.readXml(parser, mAllowedManagedServicePackages);
@@ -606,7 +613,7 @@
         out.startTag(null, TAG_NOTIFICATION_POLICY);
         out.attribute(null, ATTR_VERSION, Integer.toString(DB_VERSION));
         mZenModeHelper.writeXml(out, forBackup, null);
-        mRankingHelper.writeXml(out, forBackup);
+        mPreferencesHelper.writeXml(out, forBackup);
         mListeners.writeXml(out, forBackup);
         mAssistants.writeXml(out, forBackup);
         mConditionProviders.writeXml(out, forBackup);
@@ -620,15 +627,17 @@
         final String pkg;
         final ITransientNotification callback;
         int duration;
+        int displayId;
         Binder token;
 
         ToastRecord(int pid, String pkg, ITransientNotification callback, int duration,
-                    Binder token) {
+                Binder token, int displayId) {
             this.pid = pid;
             this.pkg = pkg;
             this.callback = callback;
             this.duration = duration;
             this.token = token;
+            this.displayId = displayId;
         }
 
         void update(int duration) {
@@ -691,7 +700,8 @@
         }
 
         @Override
-        public void onNotificationClick(int callingUid, int callingPid, String key, NotificationVisibility nv) {
+        public void onNotificationClick(int callingUid, int callingPid, String key,
+                NotificationVisibility nv) {
             exitIdle();
             synchronized (mNotificationLock) {
                 NotificationRecord r = mNotificationsByKey.get(key);
@@ -748,11 +758,13 @@
         public void onNotificationClear(int callingUid, int callingPid,
                 String pkg, String tag, int id, int userId, String key,
                 @NotificationStats.DismissalSurface int dismissalSurface,
+                @NotificationStats.DismissalSentiment int dismissalSentiment,
                 NotificationVisibility nv) {
             synchronized (mNotificationLock) {
                 NotificationRecord r = mNotificationsByKey.get(key);
                 if (r != null) {
                     r.recordDismissalSurface(dismissalSurface);
+                    r.recordDismissalSentiment(dismissalSentiment);
                 }
             }
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
@@ -788,8 +800,8 @@
         }
 
         @Override
-        public void onNotificationError(int callingUid, int callingPid, String pkg, String tag, int id,
-                int uid, int initialPid, String message, int userId) {
+        public void onNotificationError(int callingUid, int callingPid, String pkg, String tag,
+                int id, int uid, int initialPid, String message, int userId) {
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0, 0, false, userId,
                     REASON_ERROR, null);
         }
@@ -947,7 +959,7 @@
                 // update system notification channels
                 SystemNotificationChannels.createAll(context);
                 mZenModeHelper.updateDefaultZenRules();
-                mRankingHelper.onLocaleChanged(context, ActivityManager.getCurrentUser());
+                mPreferencesHelper.onLocaleChanged(context, ActivityManager.getCurrentUser());
             }
         }
     };
@@ -1031,10 +1043,12 @@
                     uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
                 } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                    uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
                     cancelNotifications = false;
                     hideNotifications = true;
                 } else if (action.equals(Intent.ACTION_PACKAGES_UNSUSPENDED)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                    uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
                     cancelNotifications = false;
                     unhideNotifications = true;
                 } else if (queryRestart) {
@@ -1090,7 +1104,8 @@
                 mListeners.onPackagesChanged(removingPackage, pkgList, uidList);
                 mAssistants.onPackagesChanged(removingPackage, pkgList, uidList);
                 mConditionProviders.onPackagesChanged(removingPackage, pkgList, uidList);
-                mRankingHelper.onPackagesChanged(removingPackage, changeUserId, pkgList, uidList);
+                mPreferencesHelper.onPackagesChanged(
+                        removingPackage, changeUserId, pkgList, uidList);
                 savePolicyFile();
             }
         }
@@ -1150,7 +1165,7 @@
                 final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
                 mUserProfiles.updateCache(context);
                 mZenModeHelper.onUserRemoved(user);
-                mRankingHelper.onUserRemoved(user);
+                mPreferencesHelper.onUserRemoved(user);
                 mListeners.onUserRemoved(user);
                 mConditionProviders.onUserRemoved(user);
                 mAssistants.onUserRemoved(user);
@@ -1196,7 +1211,8 @@
             ContentResolver resolver = getContext().getContentResolver();
             if (uri == null || NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) {
                 boolean pulseEnabled = Settings.System.getIntForUser(resolver,
-                            Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT) != 0;
+                            Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT)
+                        != 0;
                 if (mNotificationPulseEnabled != pulseEnabled) {
                     mNotificationPulseEnabled = pulseEnabled;
                     updateNotificationPulse();
@@ -1207,7 +1223,7 @@
                             Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE, mMaxPackageEnqueueRate);
             }
             if (uri == null || NOTIFICATION_BADGING_URI.equals(uri)) {
-                mRankingHelper.updateBadgingEnabled();
+                mPreferencesHelper.updateBadgingEnabled();
             }
         }
     }
@@ -1329,6 +1345,9 @@
     }
 
     @VisibleForTesting
+    void setPreferencesHelper(PreferencesHelper prefHelper) { mPreferencesHelper = prefHelper; }
+
+    @VisibleForTesting
     void setRankingHandler(RankingHandler rankingHandler) {
         mRankingHandler = rankingHandler;
     }
@@ -1357,7 +1376,8 @@
             ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper,
             NotificationUsageStats usageStats, AtomicFile policyFile,
             ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am,
-            UsageStatsManagerInternal appUsageStats, DevicePolicyManagerInternal dpm) {
+            UsageStatsManagerInternal appUsageStats, DevicePolicyManagerInternal dpm,
+            IUriGrantsManager ugm, UriGrantsManagerInternal ugmInternal) {
         Resources resources = getContext().getResources();
         mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
                 Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1366,6 +1386,8 @@
         mAccessibilityManager =
                 (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
         mAm = am;
+        mUgm = ugm;
+        mUgmInternal = ugmInternal;
         mPackageManager = packageManager;
         mPackageManagerClient = packageManagerClient;
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
@@ -1416,9 +1438,13 @@
                 mRankingHandler.requestSort();
             }
         });
-        mRankingHelper = new RankingHelper(getContext(),
+        mPreferencesHelper = new PreferencesHelper(getContext(),
                 mPackageManagerClient,
                 mRankingHandler,
+                mZenModeHelper);
+        mRankingHelper = new RankingHelper(getContext(),
+                mRankingHandler,
+                mPreferencesHelper,
                 mZenModeHelper,
                 mUsageStats,
                 extractorNames);
@@ -1458,6 +1484,8 @@
         mInCallNotificationVolume = resources.getFloat(R.dimen.config_inCallNotificationVolume);
 
         mUseAttentionLight = resources.getBoolean(R.bool.config_useAttentionLight);
+        mHasLight =
+                resources.getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed);
 
         // Don't start allowing notifications until the setup wizard has run once.
         // After that, including subsequent boots, init with notifications turned on.
@@ -1514,7 +1542,9 @@
                 (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE),
                 getGroupHelper(), ActivityManager.getService(),
                 LocalServices.getService(UsageStatsManagerInternal.class),
-                LocalServices.getService(DevicePolicyManagerInternal.class));
+                LocalServices.getService(DevicePolicyManagerInternal.class),
+                UriGrantsManager.getService(),
+                LocalServices.getService(UriGrantsManagerInternal.class));
 
         // register for various Intents
         IntentFilter filter = new IntentFilter();
@@ -1671,14 +1701,14 @@
             }
         }
         final NotificationChannel preUpdate =
-                mRankingHelper.getNotificationChannel(pkg, uid, channel.getId(), true);
+                mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(), true);
 
-        mRankingHelper.updateNotificationChannel(pkg, uid, channel, true);
+        mPreferencesHelper.updateNotificationChannel(pkg, uid, channel, true);
         maybeNotifyChannelOwner(pkg, uid, preUpdate, channel);
 
         if (!fromListener) {
             final NotificationChannel modifiedChannel =
-                    mRankingHelper.getNotificationChannel(pkg, uid, channel.getId(), false);
+                    mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(), false);
             mListeners.notifyNotificationChannelChanged(
                     pkg, UserHandle.getUserHandleForUid(uid),
                     modifiedChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
@@ -1715,8 +1745,8 @@
         Preconditions.checkNotNull(pkg);
 
         final NotificationChannelGroup preUpdate =
-                mRankingHelper.getNotificationChannelGroup(group.getId(), pkg, uid);
-        mRankingHelper.createNotificationChannelGroup(pkg, uid, group,
+                mPreferencesHelper.getNotificationChannelGroup(group.getId(), pkg, uid);
+        mPreferencesHelper.createNotificationChannelGroup(pkg, uid, group,
                 fromApp);
         if (!fromApp) {
             maybeNotifyChannelGroupOwner(pkg, uid, preUpdate, group);
@@ -1962,11 +1992,12 @@
         // ============================================================================
 
         @Override
-        public void enqueueToast(String pkg, ITransientNotification callback, int duration)
+        public void enqueueToast(String pkg, ITransientNotification callback, int duration,
+                int displayId)
         {
             if (DBG) {
                 Slog.i(TAG, "enqueueToast pkg=" + pkg + " callback=" + callback
-                        + " duration=" + duration);
+                        + " duration=" + duration + " displayId=" + displayId);
             }
 
             if (pkg == null || callback == null) {
@@ -2018,8 +2049,9 @@
                         }
 
                         Binder token = new Binder();
-                        mWindowManagerInternal.addWindowToken(token, TYPE_TOAST, DEFAULT_DISPLAY);
-                        record = new ToastRecord(callingPid, pkg, callback, duration, token);
+                        mWindowManagerInternal.addWindowToken(token, TYPE_TOAST, displayId);
+                        record = new ToastRecord(callingPid, pkg, callback, duration, token,
+                                displayId);
                         mToastQueue.add(record);
                         index = mToastQueue.size() - 1;
                         keepProcessAliveIfNeededLocked(callingPid);
@@ -2070,7 +2102,7 @@
                     int index = indexOfToastLocked(pkg, callback);
                     if (index >= 0) {
                         ToastRecord record = mToastQueue.get(index);
-                        finishTokenLocked(record.token);
+                        finishTokenLocked(record.token, record.displayId);
                     } else {
                         Slog.w(TAG, "Toast already killed. pkg=" + pkg
                                 + " callback=" + callback);
@@ -2119,7 +2151,11 @@
         public void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) {
             enforceSystemOrSystemUI("setNotificationsEnabledForPackage");
 
-            mRankingHelper.setEnabled(pkg, uid, enabled);
+            mPreferencesHelper.setEnabled(pkg, uid, enabled);
+            mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_BAN_APP_NOTES)
+                    .setType(MetricsEvent.TYPE_ACTION)
+                    .setPackageName(pkg)
+                    .setSubtype(enabled ? 1 : 0));
             // Now, cancel any outstanding notifications that are part of a just-disabled app
             if (!enabled) {
                 cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0, true,
@@ -2157,7 +2193,7 @@
                 String pkg, int uid, boolean enabled) {
             setNotificationsEnabledForPackage(pkg, uid, enabled);
 
-            mRankingHelper.setAppImportanceLocked(pkg, uid);
+            mPreferencesHelper.setAppImportanceLocked(pkg, uid);
         }
 
         /**
@@ -2175,25 +2211,25 @@
         public boolean areNotificationsEnabledForPackage(String pkg, int uid) {
             checkCallerIsSystemOrSameApp(pkg);
 
-            return mRankingHelper.getImportance(pkg, uid) != IMPORTANCE_NONE;
+            return mPreferencesHelper.getImportance(pkg, uid) != IMPORTANCE_NONE;
         }
 
         @Override
         public int getPackageImportance(String pkg) {
             checkCallerIsSystemOrSameApp(pkg);
-            return mRankingHelper.getImportance(pkg, Binder.getCallingUid());
+            return mPreferencesHelper.getImportance(pkg, Binder.getCallingUid());
         }
 
         @Override
         public boolean canShowBadge(String pkg, int uid) {
             checkCallerIsSystem();
-            return mRankingHelper.canShowBadge(pkg, uid);
+            return mPreferencesHelper.canShowBadge(pkg, uid);
         }
 
         @Override
         public void setShowBadge(String pkg, int uid, boolean showBadge) {
             checkCallerIsSystem();
-            mRankingHelper.setShowBadge(pkg, uid, showBadge);
+            mPreferencesHelper.setShowBadge(pkg, uid, showBadge);
             savePolicyFile();
         }
 
@@ -2225,12 +2261,12 @@
             for (int i = 0; i < channelsSize; i++) {
                 final NotificationChannel channel = channels.get(i);
                 Preconditions.checkNotNull(channel, "channel in list is null");
-                mRankingHelper.createNotificationChannel(pkg, uid, channel,
+                mPreferencesHelper.createNotificationChannel(pkg, uid, channel,
                         true /* fromTargetApp */, mConditionProviders.isPackageOrComponentAllowed(
                                 pkg, UserHandle.getUserId(uid)));
                 mListeners.notifyNotificationChannelChanged(pkg,
                         UserHandle.getUserHandleForUid(uid),
-                        mRankingHelper.getNotificationChannel(pkg, uid, channel.getId(), false),
+                        mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(), false),
                         NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
             }
             savePolicyFile();
@@ -2253,7 +2289,7 @@
         @Override
         public NotificationChannel getNotificationChannel(String pkg, String channelId) {
             checkCallerIsSystemOrSameApp(pkg);
-            return mRankingHelper.getNotificationChannel(
+            return mPreferencesHelper.getNotificationChannel(
                     pkg, Binder.getCallingUid(), channelId, false /* includeDeleted */);
         }
 
@@ -2261,7 +2297,7 @@
         public NotificationChannel getNotificationChannelForPackage(String pkg, int uid,
                 String channelId, boolean includeDeleted) {
             checkCallerIsSystem();
-            return mRankingHelper.getNotificationChannel(pkg, uid, channelId, includeDeleted);
+            return mPreferencesHelper.getNotificationChannel(pkg, uid, channelId, includeDeleted);
         }
 
         @Override
@@ -2273,10 +2309,10 @@
             }
             cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true,
                     UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
-            mRankingHelper.deleteNotificationChannel(pkg, callingUid, channelId);
+            mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, channelId);
             mListeners.notifyNotificationChannelChanged(pkg,
                     UserHandle.getUserHandleForUid(callingUid),
-                    mRankingHelper.getNotificationChannel(pkg, callingUid, channelId, true),
+                    mPreferencesHelper.getNotificationChannel(pkg, callingUid, channelId, true),
                     NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
             savePolicyFile();
         }
@@ -2284,7 +2320,7 @@
         @Override
         public NotificationChannelGroup getNotificationChannelGroup(String pkg, String groupId) {
             checkCallerIsSystemOrSameApp(pkg);
-            return mRankingHelper.getNotificationChannelGroupWithChannels(
+            return mPreferencesHelper.getNotificationChannelGroupWithChannels(
                     pkg, Binder.getCallingUid(), groupId, false);
         }
 
@@ -2292,7 +2328,7 @@
         public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(
                 String pkg) {
             checkCallerIsSystemOrSameApp(pkg);
-            return mRankingHelper.getNotificationChannelGroups(
+            return mPreferencesHelper.getNotificationChannelGroups(
                     pkg, Binder.getCallingUid(), false, false);
         }
 
@@ -2302,10 +2338,10 @@
 
             final int callingUid = Binder.getCallingUid();
             NotificationChannelGroup groupToDelete =
-                    mRankingHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
+                    mPreferencesHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
             if (groupToDelete != null) {
                 List<NotificationChannel> deletedChannels =
-                        mRankingHelper.deleteNotificationChannelGroup(pkg, callingUid, groupId);
+                        mPreferencesHelper.deleteNotificationChannelGroup(pkg, callingUid, groupId);
                 for (int i = 0; i < deletedChannels.size(); i++) {
                     final NotificationChannel deletedChannel = deletedChannels.get(i);
                     cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannel.getId(), 0, 0,
@@ -2336,47 +2372,47 @@
         public ParceledListSlice<NotificationChannel> getNotificationChannelsForPackage(String pkg,
                 int uid, boolean includeDeleted) {
             enforceSystemOrSystemUI("getNotificationChannelsForPackage");
-            return mRankingHelper.getNotificationChannels(pkg, uid, includeDeleted);
+            return mPreferencesHelper.getNotificationChannels(pkg, uid, includeDeleted);
         }
 
         @Override
         public int getNumNotificationChannelsForPackage(String pkg, int uid,
                 boolean includeDeleted) {
             enforceSystemOrSystemUI("getNumNotificationChannelsForPackage");
-            return mRankingHelper.getNotificationChannels(pkg, uid, includeDeleted)
+            return mPreferencesHelper.getNotificationChannels(pkg, uid, includeDeleted)
                     .getList().size();
         }
 
         @Override
         public boolean onlyHasDefaultChannel(String pkg, int uid) {
             enforceSystemOrSystemUI("onlyHasDefaultChannel");
-            return mRankingHelper.onlyHasDefaultChannel(pkg, uid);
+            return mPreferencesHelper.onlyHasDefaultChannel(pkg, uid);
         }
 
         @Override
         public int getDeletedChannelCount(String pkg, int uid) {
             enforceSystemOrSystemUI("getDeletedChannelCount");
-            return mRankingHelper.getDeletedChannelCount(pkg, uid);
+            return mPreferencesHelper.getDeletedChannelCount(pkg, uid);
         }
 
         @Override
         public int getBlockedChannelCount(String pkg, int uid) {
             enforceSystemOrSystemUI("getBlockedChannelCount");
-            return mRankingHelper.getBlockedChannelCount(pkg, uid);
+            return mPreferencesHelper.getBlockedChannelCount(pkg, uid);
         }
 
         @Override
         public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage(
                 String pkg, int uid, boolean includeDeleted) {
             checkCallerIsSystem();
-            return mRankingHelper.getNotificationChannelGroups(pkg, uid, includeDeleted, true);
+            return mPreferencesHelper.getNotificationChannelGroups(pkg, uid, includeDeleted, true);
         }
 
         @Override
         public NotificationChannelGroup getPopulatedNotificationChannelGroupForPackage(
                 String pkg, int uid, String groupId, boolean includeDeleted) {
             enforceSystemOrSystemUI("getPopulatedNotificationChannelGroupForPackage");
-            return mRankingHelper.getNotificationChannelGroupWithChannels(
+            return mPreferencesHelper.getNotificationChannelGroupWithChannels(
                     pkg, uid, groupId, includeDeleted);
         }
 
@@ -2384,13 +2420,13 @@
         public NotificationChannelGroup getNotificationChannelGroupForPackage(
                 String groupId, String pkg, int uid) {
             enforceSystemOrSystemUI("getNotificationChannelGroupForPackage");
-            return mRankingHelper.getNotificationChannelGroup(groupId, pkg, uid);
+            return mPreferencesHelper.getNotificationChannelGroup(groupId, pkg, uid);
         }
 
         @Override
         public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg) {
             checkCallerIsSystemOrSameApp(pkg);
-            return mRankingHelper.getNotificationChannels(
+            return mPreferencesHelper.getNotificationChannels(
                     pkg, Binder.getCallingUid(), false /* includeDeleted */);
         }
 
@@ -2407,12 +2443,12 @@
         @Override
         public int getBlockedAppCount(int userId) {
             checkCallerIsSystem();
-            return mRankingHelper.getBlockedAppCount(userId);
+            return mPreferencesHelper.getBlockedAppCount(userId);
         }
 
         @Override
         public boolean areChannelsBypassingDnd() {
-            return mRankingHelper.areChannelsBypassingDnd();
+            return mPreferencesHelper.areChannelsBypassingDnd();
         }
 
         @Override
@@ -2435,7 +2471,7 @@
 
             // Reset notification preferences
             if (!fromApp) {
-                mRankingHelper.onPackagesChanged(
+                mPreferencesHelper.onPackagesChanged(
                         true, UserHandle.getCallingUserId(), packages, uids);
             }
 
@@ -2662,24 +2698,30 @@
             try {
                 synchronized (mNotificationLock) {
                     final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
-                    if (keys != null) {
-                        final int N = keys.length;
-                        for (int i = 0; i < N; i++) {
-                            NotificationRecord r = mNotificationsByKey.get(keys[i]);
-                            if (r == null) continue;
-                            final int userId = r.sbn.getUserId();
-                            if (userId != info.userid && userId != UserHandle.USER_ALL &&
-                                    !mUserProfiles.isCurrentProfile(userId)) {
-                                throw new SecurityException("Disallowed call from listener: "
-                                        + info.service);
-                            }
-                            if (!r.isSeen()) {
-                                if (DBG) Slog.d(TAG, "Marking notification as seen " + keys[i]);
-                                reportSeen(r);
-                                r.setSeen();
-                                maybeRecordInterruptionLocked(r);
-                            }
+                    if (keys == null) {
+                        return;
+                    }
+                    ArrayList<NotificationRecord> seen = new ArrayList<>();
+                    final int n = keys.length;
+                    for (int i = 0; i < n; i++) {
+                        NotificationRecord r = mNotificationsByKey.get(keys[i]);
+                        if (r == null) continue;
+                        final int userId = r.sbn.getUserId();
+                        if (userId != info.userid && userId != UserHandle.USER_ALL
+                                && !mUserProfiles.isCurrentProfile(userId)) {
+                            throw new SecurityException("Disallowed call from listener: "
+                                    + info.service);
                         }
+                        seen.add(r);
+                        if (!r.isSeen()) {
+                            if (DBG) Slog.d(TAG, "Marking notification as seen " + keys[i]);
+                            reportSeen(r);
+                            r.setSeen();
+                            maybeRecordInterruptionLocked(r);
+                        }
+                    }
+                    if (!seen.isEmpty()) {
+                        mAssistants.onNotificationsSeenLocked(seen);
                     }
                 }
             } finally {
@@ -3426,7 +3468,8 @@
                     for (int i = 0; i < N; i++) {
                         final NotificationRecord r = mEnqueuedNotifications.get(i);
                         if (Objects.equals(adjustment.getKey(), r.getKey())
-                                && Objects.equals(adjustment.getUser(), r.getUserId())) {
+                                && Objects.equals(adjustment.getUser(), r.getUserId())
+                                && mAssistants.isSameUser(token, r.getUserId())) {
                             applyAdjustment(r, adjustment);
                             r.applyAdjustments();
                             foundEnqueued = true;
@@ -3446,33 +3489,36 @@
         @Override
         public void applyAdjustmentFromAssistant(INotificationListener token,
                 Adjustment adjustment) {
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                synchronized (mNotificationLock) {
-                    mAssistants.checkServiceTokenLocked(token);
-                    NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
-                    applyAdjustment(n, adjustment);
-                }
-                mRankingHandler.requestSort();
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
+            List<Adjustment> adjustments = new ArrayList<>();
+            adjustments.add(adjustment);
+            applyAdjustmentsFromAssistant(token, adjustments);
         }
 
         @Override
         public void applyAdjustmentsFromAssistant(INotificationListener token,
                 List<Adjustment> adjustments) {
 
+            boolean needsSort = false;
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationLock) {
                     mAssistants.checkServiceTokenLocked(token);
                     for (Adjustment adjustment : adjustments) {
-                        NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
-                        applyAdjustment(n, adjustment);
+                        NotificationRecord r = mNotificationsByKey.get(adjustment.getKey());
+                        if (r != null && mAssistants.isSameUser(token, r.getUserId())) {
+                            applyAdjustment(r, adjustment);
+                            r.applyAdjustments();
+                            if (r.getImportance() == IMPORTANCE_NONE) {
+                                cancelNotificationsFromListener(token, new String[]{r.getKey()});
+                            } else {
+                                needsSort = true;
+                            }
+                        }
                     }
                 }
-                mRankingHandler.requestSort();
+                if (needsSort) {
+                    mRankingHandler.requestSort();
+                }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -3507,7 +3553,7 @@
             Preconditions.checkNotNull(user);
             verifyPrivilegedListener(token, user);
 
-            return mRankingHelper.getNotificationChannels(pkg, getUidForPackageAndUser(pkg, user),
+            return mPreferencesHelper.getNotificationChannels(pkg, getUidForPackageAndUser(pkg, user),
                     false /* includeDeleted */);
         }
 
@@ -3520,7 +3566,7 @@
             verifyPrivilegedListener(token, user);
 
             List<NotificationChannelGroup> groups = new ArrayList<>();
-            groups.addAll(mRankingHelper.getNotificationChannelGroups(
+            groups.addAll(mPreferencesHelper.getNotificationChannelGroups(
                     pkg, getUidForPackageAndUser(pkg, user)));
             return new ParceledListSlice<>(groups);
         }
@@ -3701,10 +3747,10 @@
         JSONObject dump = new JSONObject();
         try {
             dump.put("service", "Notification Manager");
-            dump.put("bans", mRankingHelper.dumpBansJson(filter));
-            dump.put("ranking", mRankingHelper.dumpJson(filter));
+            dump.put("bans", mPreferencesHelper.dumpBansJson(filter));
+            dump.put("ranking", mPreferencesHelper.dumpJson(filter));
             dump.put("stats", mUsageStats.dumpJson(filter));
-            dump.put("channels", mRankingHelper.dumpChannelsJson(filter));
+            dump.put("channels", mPreferencesHelper.dumpChannelsJson(filter));
         } catch (JSONException e) {
             e.printStackTrace();
         }
@@ -3777,6 +3823,7 @@
 
             long rankingToken = proto.start(NotificationServiceDumpProto.RANKING_CONFIG);
             mRankingHelper.dump(proto, filter);
+            mPreferencesHelper.dump(proto, filter);
             proto.end(rankingToken);
         }
 
@@ -3843,6 +3890,7 @@
                         pw.println("  ");
                     }
                     pw.println("  mUseAttentionLight=" + mUseAttentionLight);
+                    pw.println("  mHasLight=" + mHasLight);
                     pw.println("  mNotificationPulseEnabled=" + mNotificationPulseEnabled);
                     pw.println("  mSoundNotificationKey=" + mSoundNotificationKey);
                     pw.println("  mVibrateNotificationKey=" + mVibrateNotificationKey);
@@ -3884,6 +3932,9 @@
                 pw.println("\n  Ranking Config:");
                 mRankingHelper.dump(pw, "    ", filter);
 
+                pw.println("\n Notification Preferences:");
+                mPreferencesHelper.dump(pw, "    ", filter);
+
                 pw.println("\n  Notification listeners:");
                 mListeners.dump(pw, filter);
                 pw.print("    mListenerHints: "); pw.println(mListenerHints);
@@ -3947,7 +3998,7 @@
         @Override
         public NotificationChannel getNotificationChannel(String pkg, int uid, String
                 channelId) {
-            return mRankingHelper.getNotificationChannel(pkg, uid, channelId, false);
+            return mPreferencesHelper.getNotificationChannel(pkg, uid, channelId, false);
         }
 
         @Override
@@ -4003,6 +4054,7 @@
                     + " notification=" + notification);
         }
         checkCallerIsSystemOrSameApp(pkg);
+        checkRestrictedCategories(notification);
 
         final int userId = ActivityManager.handleIncomingUser(callingPid,
                 callingUid, incomingUserId, true, false, "enqueueNotification", pkg);
@@ -4043,7 +4095,7 @@
         if (mIsTelevision && (new Notification.TvExtender(notification)).getChannelId() != null) {
             channelId = (new Notification.TvExtender(notification)).getChannelId();
         }
-        final NotificationChannel channel = mRankingHelper.getNotificationChannel(pkg,
+        final NotificationChannel channel = mPreferencesHelper.getNotificationChannel(pkg,
                 notificationUid, channelId, false /* includeDeleted */);
         if (channel == null) {
             final String noChannelStr = "No Channel found for "
@@ -4058,7 +4110,7 @@
                     + ", notificationUid=" + notificationUid
                     + ", notification=" + notification;
             Log.e(TAG, noChannelStr);
-            boolean appNotificationsOff = mRankingHelper.getImportance(pkg, notificationUid)
+            boolean appNotificationsOff = mPreferencesHelper.getImportance(pkg, notificationUid)
                     == NotificationManager.IMPORTANCE_NONE;
 
             if (!appNotificationsOff) {
@@ -4073,7 +4125,7 @@
                 pkg, opPkg, id, tag, notificationUid, callingPid, notification,
                 user, null, System.currentTimeMillis());
         final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
-        r.setIsAppImportanceLocked(mRankingHelper.getIsAppImportanceLocked(pkg, callingUid));
+        r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));
 
         if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
             final boolean fgServiceShown = channel.isFgServiceShown();
@@ -4085,14 +4137,16 @@
                 // an opinion otherwise (and the channel hasn't yet shown a fg service).
                 if (TextUtils.isEmpty(channelId)
                         || NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
-                    r.setImportance(IMPORTANCE_LOW, "Bumped for foreground service");
+                    r.setSystemImportance(IMPORTANCE_LOW);
                 } else {
                     channel.setImportance(IMPORTANCE_LOW);
+                    r.setSystemImportance(IMPORTANCE_LOW);
                     if (!fgServiceShown) {
                         channel.unlockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
                         channel.setFgServiceShown(true);
                     }
-                    mRankingHelper.updateNotificationChannel(pkg, notificationUid, channel, false);
+                    mPreferencesHelper.updateNotificationChannel(
+                            pkg, notificationUid, channel, false);
                     r.updateNotificationChannel(channel);
                 }
             } else if (!fgServiceShown && !TextUtils.isEmpty(channelId)
@@ -4266,11 +4320,7 @@
             usageStats.registerSuspendedByAdmin(r);
             return isPackageSuspended;
         }
-        final boolean isBlocked =
-                mRankingHelper.isGroupBlocked(pkg, callingUid, r.getChannel().getGroup())
-                || mRankingHelper.getImportance(pkg, callingUid)
-                        == NotificationManager.IMPORTANCE_NONE
-                || r.getChannel().getImportance() == NotificationManager.IMPORTANCE_NONE;
+        final boolean isBlocked = isBlocked(r);
         if (isBlocked) {
             Slog.e(TAG, "Suppressing notification from package by user request.");
             usageStats.registerBlocked(r);
@@ -4278,6 +4328,15 @@
         return isBlocked;
     }
 
+    private boolean isBlocked(NotificationRecord r) {
+        final String pkg = r.sbn.getPackageName();
+        final int callingUid = r.sbn.getUid();
+        return mPreferencesHelper.isGroupBlocked(pkg, callingUid, r.getChannel().getGroup())
+                || mPreferencesHelper.getImportance(pkg, callingUid)
+                == NotificationManager.IMPORTANCE_NONE
+                || r.getImportance() == NotificationManager.IMPORTANCE_NONE;
+    }
+
     protected class SnoozeNotificationRunnable implements Runnable {
         private final String mKey;
         private final long mDuration;
@@ -4354,6 +4413,88 @@
         }
     }
 
+    protected class CancelNotificationRunnable implements Runnable {
+        private final int mCallingUid;
+        private final int mCallingPid;
+        private final String mPkg;
+        private final String mTag;
+        private final int mId;
+        private final int mMustHaveFlags;
+        private final int mMustNotHaveFlags;
+        private final boolean mSendDelete;
+        private final int mUserId;
+        private final int mReason;
+        private final int mRank;
+        private final int mCount;
+        private final ManagedServiceInfo mListener;
+
+        CancelNotificationRunnable(final int callingUid, final int callingPid,
+                final String pkg, final String tag, final int id,
+                final int mustHaveFlags, final int mustNotHaveFlags, final boolean sendDelete,
+                final int userId, final int reason, int rank, int count,
+                final ManagedServiceInfo listener) {
+            this.mCallingUid = callingUid;
+            this.mCallingPid = callingPid;
+            this.mPkg = pkg;
+            this.mTag = tag;
+            this.mId = id;
+            this.mMustHaveFlags = mustHaveFlags;
+            this.mMustNotHaveFlags = mustNotHaveFlags;
+            this.mSendDelete = sendDelete;
+            this.mUserId = userId;
+            this.mReason = reason;
+            this.mRank = rank;
+            this.mCount = count;
+            this.mListener = listener;
+        }
+
+        @Override
+        public void run() {
+            String listenerName = mListener == null ? null : mListener.component.toShortString();
+            if (DBG) {
+                EventLogTags.writeNotificationCancel(mCallingUid, mCallingPid, mPkg, mId, mTag,
+                        mUserId, mMustHaveFlags, mMustNotHaveFlags, mReason, listenerName);
+            }
+
+            synchronized (mNotificationLock) {
+                // Look for the notification, searching both the posted and enqueued lists.
+                NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId);
+                if (r != null) {
+                    // The notification was found, check if it should be removed.
+
+                    // Ideally we'd do this in the caller of this method. However, that would
+                    // require the caller to also find the notification.
+                    if (mReason == REASON_CLICK) {
+                        mUsageStats.registerClickedByUser(r);
+                    }
+
+                    if ((r.getNotification().flags & mMustHaveFlags) != mMustHaveFlags) {
+                        return;
+                    }
+                    if ((r.getNotification().flags & mMustNotHaveFlags) != 0) {
+                        return;
+                    }
+
+                    // Cancel the notification.
+                    boolean wasPosted = removeFromNotificationListsLocked(r);
+                    cancelNotificationLocked(
+                            r, mSendDelete, mReason, mRank, mCount, wasPosted, listenerName);
+                    cancelGroupChildrenLocked(r, mCallingUid, mCallingPid, listenerName,
+                            mSendDelete, null);
+                    updateLightsLocked();
+                } else {
+                    // No notification was found, assume that it is snoozed and cancel it.
+                    if (mReason != REASON_SNOOZED) {
+                        final boolean wasSnoozed = mSnoozeHelper.cancel(mUserId, mPkg, mTag, mId);
+                        if (wasSnoozed) {
+                            savePolicyFile();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     protected class EnqueueNotificationRunnable implements Runnable {
         private final NotificationRecord r;
         private final int userId;
@@ -4453,6 +4594,11 @@
                         return;
                     }
 
+                    if (isBlocked(r)) {
+                        Slog.i(TAG, "notification blocked by assistant request");
+                        return;
+                    }
+
                     r.setHidden(isPackageSuspendedLocked(r));
                     NotificationRecord old = mNotificationsByKey.get(key);
                     final StatusBarNotification n = r.sbn;
@@ -4825,6 +4971,8 @@
 
                         buzz = playVibration(record, vibration, hasValidSound);
                     }
+                } else if ((record.getFlags() & Notification.FLAG_INSISTENT) != 0) {
+                    hasValidSound = false;
                 }
             }
         }
@@ -4840,8 +4988,7 @@
         // light
         // release the light
         boolean wasShowLights = mLights.remove(key);
-        if (record.getLight() != null && aboveThreshold
-                && ((record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_LIGHTS) == 0)) {
+        if (canShowLightsLocked(record, aboveThreshold)) {
             mLights.add(key);
             updateLightsLocked();
             if (mUseAttentionLight) {
@@ -4852,7 +4999,19 @@
             updateLightsLocked();
         }
         if (buzz || beep || blink) {
-            record.setInterruptive(true);
+            // Ignore summary updates because we don't display most of the information.
+            if (record.sbn.isGroup() && record.sbn.getNotification().isGroupSummary()) {
+                if (DEBUG_INTERRUPTIVENESS) {
+                    Log.v(TAG, "INTERRUPTIVENESS: "
+                            + record.getKey() + " is not interruptive: summary");
+                }
+            } else {
+                if (DEBUG_INTERRUPTIVENESS) {
+                    Log.v(TAG, "INTERRUPTIVENESS: "
+                            + record.getKey() + " is interruptive: alerted");
+                }
+                record.setInterruptive(true);
+            }
             MetricsLogger.action(record.getLogMaker()
                     .setCategory(MetricsEvent.NOTIFICATION_ALERT)
                     .setType(MetricsEvent.TYPE_OPEN)
@@ -4862,11 +5021,49 @@
     }
 
     @GuardedBy("mNotificationLock")
+    boolean canShowLightsLocked(final NotificationRecord record, boolean aboveThreshold) {
+        // device lacks light
+        if (!mHasLight) {
+            return false;
+        }
+        // user turned lights off globally
+        if (!mNotificationPulseEnabled) {
+            return false;
+        }
+        // the notification/channel has no light
+        if (record.getLight() == null) {
+            return false;
+        }
+        // unimportant notification
+        if (!aboveThreshold) {
+            return false;
+        }
+        // suppressed due to DND
+        if ((record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_LIGHTS) != 0) {
+            return false;
+        }
+        // Suppressed because it's a silent update
+        final Notification notification = record.getNotification();
+        if (record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
+            return false;
+        }
+        // Suppressed because another notification in its group handles alerting
+        if (record.sbn.isGroup() && record.getNotification().suppressAlertingDueToGrouping()) {
+            return false;
+        }
+        // not if in call or the screen's on
+        if (mInCall || mScreenOn) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @GuardedBy("mNotificationLock")
     boolean shouldMuteNotificationLocked(final NotificationRecord record) {
         // Suppressed because it's a silent update
         final Notification notification = record.getNotification();
-        if(record.isUpdate
-                && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
+        if (record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
             return true;
         }
 
@@ -4953,11 +5150,11 @@
                         Thread.sleep(waitMs);
                     } catch (InterruptedException e) { }
                     mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
-                            effect, record.getAudioAttributes());
+                            effect, "Notification (delayed)", record.getAudioAttributes());
                 }).start();
             } else {
                 mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
-                        effect, record.getAudioAttributes());
+                        effect, "Notification", record.getAudioAttributes());
             }
             return true;
         } finally{
@@ -4979,27 +5176,31 @@
     }
 
     protected void playInCallNotification() {
-        new Thread() {
-            @Override
-            public void run() {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
-                    if (player != null) {
-                        if (mCallNotificationToken != null) {
-                            player.stop(mCallNotificationToken);
+        if (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_NORMAL
+                && Settings.Secure.getInt(getContext().getContentResolver(),
+                Settings.Secure.IN_CALL_NOTIFICATION_ENABLED, 1) != 0) {
+            new Thread() {
+                @Override
+                public void run() {
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
+                        if (player != null) {
+                            if (mCallNotificationToken != null) {
+                                player.stop(mCallNotificationToken);
+                            }
+                            mCallNotificationToken = new Binder();
+                            player.play(mCallNotificationToken, mInCallNotificationUri,
+                                    mInCallNotificationAudioAttributes,
+                                    mInCallNotificationVolume, false);
                         }
-                        mCallNotificationToken = new Binder();
-                        player.play(mCallNotificationToken, mInCallNotificationUri,
-                                mInCallNotificationAudioAttributes,
-                                mInCallNotificationVolume, false);
+                    } catch (RemoteException e) {
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
                     }
-                } catch (RemoteException e) {
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
                 }
-            }
-        }.start();
+            }.start();
+        }
     }
 
     @GuardedBy("mToastQueue")
@@ -5044,13 +5245,13 @@
         ToastRecord lastToast = mToastQueue.remove(index);
 
         mWindowManagerInternal.removeWindowToken(lastToast.token, false /* removeWindows */,
-                DEFAULT_DISPLAY);
+                lastToast.displayId);
         // We passed 'false' for 'removeWindows' so that the client has time to stop
         // rendering (as hide above is a one-way message), otherwise we could crash
         // a client which was actively using a surface made from the token. However
         // we need to schedule a timeout to make sure the token is eventually killed
         // one way or another.
-        scheduleKillTokenTimeout(lastToast.token);
+        scheduleKillTokenTimeout(lastToast);
 
         keepProcessAliveIfNeededLocked(record.pid);
         if (mToastQueue.size() > 0) {
@@ -5061,14 +5262,13 @@
         }
     }
 
-    void finishTokenLocked(IBinder t) {
+    void finishTokenLocked(IBinder t, int displayId) {
         mHandler.removeCallbacksAndMessages(t);
         // We pass 'true' for 'removeWindows' to let the WindowManager destroy any
         // remaining surfaces as either the client has called finishToken indicating
         // it has successfully removed the views, or the client has timed out
         // at which point anything goes.
-        mWindowManagerInternal.removeWindowToken(t, true /* removeWindows */,
-                DEFAULT_DISPLAY);
+        mWindowManagerInternal.removeWindowToken(t, true /* removeWindows */, displayId);
     }
 
     @GuardedBy("mToastQueue")
@@ -5092,18 +5292,18 @@
     }
 
     @GuardedBy("mToastQueue")
-    private void scheduleKillTokenTimeout(IBinder token)
+    private void scheduleKillTokenTimeout(ToastRecord r)
     {
-        mHandler.removeCallbacksAndMessages(token);
-        Message m = Message.obtain(mHandler, MESSAGE_FINISH_TOKEN_TIMEOUT, token);
+        mHandler.removeCallbacksAndMessages(r);
+        Message m = Message.obtain(mHandler, MESSAGE_FINISH_TOKEN_TIMEOUT, r);
         mHandler.sendMessageDelayed(m, FINISH_TOKEN_TIMEOUT);
     }
 
-    private void handleKillTokenTimeout(IBinder token)
+    private void handleKillTokenTimeout(ToastRecord record)
     {
-        if (DBG) Slog.d(TAG, "Kill Token Timeout token=" + token);
+        if (DBG) Slog.d(TAG, "Kill Token Timeout token=" + record.token);
         synchronized (mToastQueue) {
-            finishTokenLocked(token);
+            finishTokenLocked(record.token, record.displayId);
         }
     }
 
@@ -5188,6 +5388,8 @@
             ArrayList<ArrayList<SnoozeCriterion>> snoozeCriteriaBefore = new ArrayList<>(N);
             ArrayList<Integer> userSentimentBefore = new ArrayList<>(N);
             ArrayList<Integer> suppressVisuallyBefore = new ArrayList<>(N);
+            ArrayList<ArrayList<Notification.Action>> smartActionsBefore = new ArrayList<>(N);
+            ArrayList<ArrayList<CharSequence>> smartRepliesBefore = new ArrayList<>(N);
             for (int i = 0; i < N; i++) {
                 final NotificationRecord r = mNotificationList.get(i);
                 orderBefore.add(r.getKey());
@@ -5199,6 +5401,8 @@
                 snoozeCriteriaBefore.add(r.getSnoozeCriteria());
                 userSentimentBefore.add(r.getUserSentiment());
                 suppressVisuallyBefore.add(r.getSuppressedVisualEffects());
+                smartActionsBefore.add(r.getSmartActions());
+                smartRepliesBefore.add(r.getSmartReplies());
                 mRankingHelper.extractSignals(r);
             }
             mRankingHelper.sort(mNotificationList);
@@ -5213,7 +5417,9 @@
                         || !Objects.equals(snoozeCriteriaBefore.get(i), r.getSnoozeCriteria())
                         || !Objects.equals(userSentimentBefore.get(i), r.getUserSentiment())
                         || !Objects.equals(suppressVisuallyBefore.get(i),
-                        r.getSuppressedVisualEffects())) {
+                        r.getSuppressedVisualEffects())
+                        || !Objects.equals(smartActionsBefore.get(i), r.getSmartActions())
+                        || !Objects.equals(smartRepliesBefore.get(i), r.getSmartReplies())) {
                     mHandler.scheduleSendRankingUpdate();
                     return;
                 }
@@ -5291,7 +5497,7 @@
                     handleDurationReached((ToastRecord)msg.obj);
                     break;
                 case MESSAGE_FINISH_TOKEN_TIMEOUT:
-                    handleKillTokenTimeout((IBinder)msg.obj);
+                    handleKillTokenTimeout((ToastRecord)msg.obj);
                     break;
                 case MESSAGE_SAVE_POLICY_FILE:
                     handleSavePolicyFile();
@@ -5315,6 +5521,11 @@
             }
         }
 
+        protected void scheduleCancelNotification(CancelNotificationRunnable cancelRunnable) {
+            if (!hasCallbacks(cancelRunnable)) {
+                sendMessage(Message.obtain(this, cancelRunnable));
+            }
+        }
     }
 
     private final class RankingHandlerWorker extends Handler implements RankingHandler
@@ -5543,12 +5754,8 @@
 
         // If we have Uris to grant, but no owner yet, go create one
         if (newUris != null && permissionOwner == null) {
-            try {
-                if (DBG) Slog.d(TAG, key + ": creating owner");
-                permissionOwner = mAm.newUriPermissionOwner("NOTIF:" + key);
-            } catch (RemoteException ignored) {
-                // Ignored because we're in same process
-            }
+            if (DBG) Slog.d(TAG, key + ": creating owner");
+            permissionOwner = mUgmInternal.newUriPermissionOwner("NOTIF:" + key);
         }
 
         // If we have no Uris to grant, but an existing owner, go destroy it
@@ -5556,11 +5763,9 @@
             final long ident = Binder.clearCallingIdentity();
             try {
                 if (DBG) Slog.d(TAG, key + ": destroying owner");
-                mAm.revokeUriPermissionFromOwner(permissionOwner, null, ~0,
+                mUgmInternal.revokeUriPermissionFromOwner(permissionOwner, null, ~0,
                         UserHandle.getUserId(oldRecord.getUid()));
                 permissionOwner = null;
-            } catch (RemoteException ignored) {
-                // Ignored because we're in same process
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -5600,7 +5805,7 @@
 
         final long ident = Binder.clearCallingIdentity();
         try {
-            mAm.grantUriPermissionFromOwner(owner, sourceUid, targetPkg,
+            mUgm.grantUriPermissionFromOwner(owner, sourceUid, targetPkg,
                     ContentProvider.getUriWithoutUserId(uri),
                     Intent.FLAG_GRANT_READ_URI_PERMISSION,
                     ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)),
@@ -5617,12 +5822,11 @@
 
         final long ident = Binder.clearCallingIdentity();
         try {
-            mAm.revokeUriPermissionFromOwner(owner,
+            mUgmInternal.revokeUriPermissionFromOwner(
+                    owner,
                     ContentProvider.getUriWithoutUserId(uri),
                     Intent.FLAG_GRANT_READ_URI_PERMISSION,
                     ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
-        } catch (RemoteException ignored) {
-            // Ignored because we're in same process
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -5647,56 +5851,15 @@
     void cancelNotification(final int callingUid, final int callingPid,
             final String pkg, final String tag, final int id,
             final int mustHaveFlags, final int mustNotHaveFlags, final boolean sendDelete,
-            final int userId, final int reason, int rank, int count, final ManagedServiceInfo listener) {
-
+            final int userId, final int reason, int rank, int count,
+            final ManagedServiceInfo listener) {
         // In enqueueNotificationInternal notifications are added by scheduling the
         // work on the worker handler. Hence, we also schedule the cancel on this
         // handler to avoid a scenario where an add notification call followed by a
         // remove notification call ends up in not removing the notification.
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                String listenerName = listener == null ? null : listener.component.toShortString();
-                if (DBG) EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, id, tag,
-                        userId, mustHaveFlags, mustNotHaveFlags, reason, listenerName);
-
-                synchronized (mNotificationLock) {
-                    // Look for the notification, searching both the posted and enqueued lists.
-                    NotificationRecord r = findNotificationLocked(pkg, tag, id, userId);
-                    if (r != null) {
-                        // The notification was found, check if it should be removed.
-
-                        // Ideally we'd do this in the caller of this method. However, that would
-                        // require the caller to also find the notification.
-                        if (reason == REASON_CLICK) {
-                            mUsageStats.registerClickedByUser(r);
-                        }
-
-                        if ((r.getNotification().flags & mustHaveFlags) != mustHaveFlags) {
-                            return;
-                        }
-                        if ((r.getNotification().flags & mustNotHaveFlags) != 0) {
-                            return;
-                        }
-
-                        // Cancel the notification.
-                        boolean wasPosted = removeFromNotificationListsLocked(r);
-                        cancelNotificationLocked(r, sendDelete, reason, rank, count, wasPosted, listenerName);
-                        cancelGroupChildrenLocked(r, callingUid, callingPid, listenerName,
-                                sendDelete, null);
-                        updateLightsLocked();
-                    } else {
-                        // No notification was found, assume that it is snoozed and cancel it.
-                        if (reason != REASON_SNOOZED) {
-                            final boolean wasSnoozed = mSnoozeHelper.cancel(userId, pkg, tag, id);
-                            if (wasSnoozed) {
-                                savePolicyFile();
-                            }
-                        }
-                    }
-                }
-            }
-        });
+        mHandler.scheduleCancelNotification(new CancelNotificationRunnable(callingUid, callingPid,
+                pkg, tag, id, mustHaveFlags, mustNotHaveFlags, sendDelete, userId, reason, rank,
+                count, listener));
     }
 
     /**
@@ -5806,6 +5969,7 @@
             }
             notificationList.remove(i);
             mNotificationsByKey.remove(r.getKey());
+            r.recordDismissalSentiment(NotificationStats.DISMISS_SENTIMENT_NEUTRAL);
             canceledNotifications.add(r);
             cancelNotificationLocked(r, sendDelete, reason, wasPosted, listenerName);
         }
@@ -6118,6 +6282,26 @@
         checkCallerIsSameApp(pkg);
     }
 
+    /**
+     * Check if the notification is of a category type that is restricted to system use only,
+     * if so throw SecurityException
+     */
+    private void checkRestrictedCategories(final Notification notification) {
+        try {
+            if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) {
+                return;
+            }
+        } catch (RemoteException re) {
+            if (DBG) Log.e(TAG, "Unable to confirm if it's safe to skip category "
+                    + "restrictions check thus the check will be done anyway");
+        }
+        if (Notification.CATEGORY_CAR_EMERGENCY.equals(notification.category)
+                || Notification.CATEGORY_CAR_WARNING.equals(notification.category)
+                || Notification.CATEGORY_CAR_INFORMATION.equals(notification.category)) {
+                    checkCallerIsSystem();
+        }
+    }
+
     private boolean isCallerInstantApp(String pkg) {
         // System is always allowed to act for ephemeral apps.
         if (isCallerSystemOrPhone()) {
@@ -6196,6 +6380,8 @@
         Bundle showBadge = new Bundle();
         Bundle userSentiment = new Bundle();
         Bundle hidden = new Bundle();
+        Bundle smartActions = new Bundle();
+        Bundle smartReplies = new Bundle();
         for (int i = 0; i < N; i++) {
             NotificationRecord record = mNotificationList.get(i);
             if (!isVisibleToListener(record.sbn, info)) {
@@ -6223,6 +6409,8 @@
             showBadge.putBoolean(key, record.canShowBadge());
             userSentiment.putInt(key, record.getUserSentiment());
             hidden.putBoolean(key, record.isHidden());
+            smartActions.putParcelableArrayList(key, record.getSmartActions());
+            smartReplies.putCharSequenceArrayList(key, record.getSmartReplies());
         }
         final int M = keys.size();
         String[] keysAr = keys.toArray(new String[M]);
@@ -6233,7 +6421,8 @@
         }
         return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
                 suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
-                channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden);
+                channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden,
+                smartActions, smartReplies);
     }
 
     boolean hasCompanionDevice(ManagedServiceInfo info) {
@@ -6378,6 +6567,35 @@
             rebindServices(true);
         }
 
+        protected void onNotificationsSeenLocked(ArrayList<NotificationRecord> records) {
+            // There should be only one, but it's a list, so while we enforce
+            // singularity elsewhere, we keep it general here, to avoid surprises.
+            for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
+                ArrayList<String> keys = new ArrayList<>(records.size());
+                for (NotificationRecord r : records) {
+                    boolean sbnVisible = isVisibleToListener(r.sbn, info)
+                            && info.isSameUser(r.getUserId());
+                    if (sbnVisible) {
+                        keys.add(r.getKey());
+                    }
+                }
+
+                if (!keys.isEmpty()) {
+                    mHandler.post(() -> notifySeen(info, keys));
+                }
+            }
+        }
+
+        private void notifySeen(final ManagedServiceInfo info,
+                final ArrayList<String> keys) {
+            final INotificationListener assistant = (INotificationListener) info.service;
+            try {
+                assistant.onNotificationsSeen(keys);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "unable to notify assistant (seen): " + assistant, ex);
+            }
+        }
+
         public void onNotificationEnqueued(final NotificationRecord r) {
             final StatusBarNotification sbn = r.sbn;
             TrimCache trimCache = new TrimCache(sbn);
@@ -6385,7 +6603,8 @@
             // There should be only one, but it's a list, so while we enforce
             // singularity elsewhere, we keep it general here, to avoid surprises.
             for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
-                boolean sbnVisible = isVisibleToListener(sbn, info);
+                boolean sbnVisible = isVisibleToListener(sbn, info)
+                        && info.isSameUser(r.getUserId());
                 if (!sbnVisible) {
                     continue;
                 }
@@ -6394,18 +6613,18 @@
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        notifyEnqueued(info, sbnToPost);
+                        notifyEnqueued(info, sbnToPost, r.getChannel());
                     }
                 });
             }
         }
 
         private void notifyEnqueued(final ManagedServiceInfo info,
-                final StatusBarNotification sbn) {
+                final StatusBarNotification sbn, final NotificationChannel channel) {
             final INotificationListener assistant = (INotificationListener) info.service;
             StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
             try {
-                assistant.onNotificationEnqueued(sbnHolder);
+                assistant.onNotificationEnqueuedWithChannel(sbnHolder, channel);
             } catch (RemoteException ex) {
                 Log.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex);
             }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 75b9f13..fbb42ea 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -49,7 +49,6 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.Adjustment;
@@ -70,6 +69,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 import java.io.PrintWriter;
 import java.lang.reflect.Array;
@@ -96,6 +96,7 @@
     private static final int MAX_LOGTAG_LENGTH = 35;
     final StatusBarNotification sbn;
     IActivityManager mAm;
+    UriGrantsManagerInternal mUgmInternal;
     final int mTargetSdkVersion;
     final int mOriginalFlags;
     private final Context mContext;
@@ -140,8 +141,11 @@
     private int mAuthoritativeRank;
     private String mGlobalSortKey;
     private int mPackageVisibility;
-    private int mUserImportance = IMPORTANCE_UNSPECIFIED;
+    private int mSystemImportance = IMPORTANCE_UNSPECIFIED;
+    private int mAssistantImportance = IMPORTANCE_UNSPECIFIED;
     private int mImportance = IMPORTANCE_UNSPECIFIED;
+    // Field used in global sort key to bypass normal notifications
+    private int mCriticality = CriticalNotificationExtractor.NORMAL;
     private CharSequence mImportanceExplanation = null;
 
     private int mSuppressedVisualEffects = 0;
@@ -159,6 +163,8 @@
     private Light mLight;
     private String mGroupLogTag;
     private String mChannelIdLogTag;
+    private ArrayList<Notification.Action> mSmartActions;
+    private ArrayList<CharSequence> mSmartReplies;
 
     private final List<Adjustment> mAdjustments;
     private final NotificationStats mStats;
@@ -181,6 +187,7 @@
         mTargetSdkVersion = LocalServices.getService(PackageManagerInternal.class)
                 .getPackageTargetSdkVersion(sbn.getPackageName());
         mAm = ActivityManager.getService();
+        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
         mOriginalFlags = sbn.getNotification().flags;
         mRankingTimeMs = calculateRankingTimeMs(0L);
         mCreationTimeMs = sbn.getPostTime();
@@ -193,7 +200,7 @@
         mSound = calculateSound();
         mVibration = calculateVibration();
         mAttributes = calculateAttributes();
-        mImportance = calculateImportance();
+        mImportance = calculateInitialImportance();
         mLight = calculateLights();
         mAdjustments = new ArrayList<>();
         mStats = new NotificationStats();
@@ -316,7 +323,7 @@
         return attributes;
     }
 
-    private int calculateImportance() {
+    private int calculateInitialImportance() {
         final Notification n = sbn.getNotification();
         int importance = getChannel().getImportance();
         int requestedImportance = IMPORTANCE_DEFAULT;
@@ -443,6 +450,8 @@
         pw.println(prefix + "fullscreenIntent=" + notification.fullScreenIntent);
         pw.println(prefix + "contentIntent=" + notification.contentIntent);
         pw.println(prefix + "deleteIntent=" + notification.deleteIntent);
+        pw.println(prefix + "number=" + notification.number);
+        pw.println(prefix + "groupAlertBehavior=" + notification.getGroupAlertBehavior());
 
         pw.print(prefix + "tickerText=");
         if (!TextUtils.isEmpty(notification.tickerText)) {
@@ -518,8 +527,10 @@
         pw.println(prefix + "mRecentlyIntrusive=" + mRecentlyIntrusive);
         pw.println(prefix + "mPackagePriority=" + mPackagePriority);
         pw.println(prefix + "mPackageVisibility=" + mPackageVisibility);
-        pw.println(prefix + "mUserImportance="
-                + NotificationListenerService.Ranking.importanceToString(mUserImportance));
+        pw.println(prefix + "mSystemImportance="
+                + NotificationListenerService.Ranking.importanceToString(mSystemImportance));
+        pw.println(prefix + "mAsstImportance="
+                + NotificationListenerService.Ranking.importanceToString(mAssistantImportance));
         pw.println(prefix + "mImportance="
                 + NotificationListenerService.Ranking.importanceToString(mImportance));
         pw.println(prefix + "mImportanceExplanation=" + mImportanceExplanation);
@@ -628,6 +639,18 @@
                                 Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL));
                     }
                 }
+                if (signals.containsKey(Adjustment.KEY_SMART_ACTIONS)) {
+                    setSmartActions(signals.getParcelableArrayList(Adjustment.KEY_SMART_ACTIONS));
+                }
+                if (signals.containsKey(Adjustment.KEY_SMART_REPLIES)) {
+                    setSmartReplies(signals.getCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES));
+                }
+                if (signals.containsKey(Adjustment.KEY_IMPORTANCE)) {
+                    int importance = signals.getInt(Adjustment.KEY_IMPORTANCE);
+                    importance = Math.max(IMPORTANCE_UNSPECIFIED, importance);
+                    importance = Math.min(IMPORTANCE_HIGH, importance);
+                    setAssistantImportance(importance);
+                }
             }
         }
     }
@@ -641,7 +664,7 @@
         mContactAffinity = contactAffinity;
         if (mImportance < IMPORTANCE_DEFAULT &&
                 mContactAffinity > ValidateNotificationPeople.VALID_CONTACT) {
-            setImportance(IMPORTANCE_DEFAULT, getPeopleExplanation());
+            setSystemImportance(IMPORTANCE_DEFAULT);
         }
     }
 
@@ -680,11 +703,6 @@
         return mPackageVisibility;
     }
 
-    public void setUserImportance(int importance) {
-        mUserImportance = importance;
-        applyUserImportance();
-    }
-
     private String getUserExplanation() {
         if (mUserExplanation == null) {
             mUserExplanation = mContext.getResources().getString(
@@ -693,31 +711,42 @@
         return mUserExplanation;
     }
 
-    private String getPeopleExplanation() {
-        if (mPeopleExplanation == null) {
-            mPeopleExplanation = mContext.getResources().getString(
-                    com.android.internal.R.string.importance_from_person);
-        }
-        return mPeopleExplanation;
+    /**
+     * Sets the importance value the system thinks the record should have.
+     * e.g. bumping up foreground service notifications or people to people notifications.
+     */
+    public void setSystemImportance(int importance) {
+        mSystemImportance = importance;
+        calculateImportance();
     }
 
-    private void applyUserImportance() {
-        if (mUserImportance != IMPORTANCE_UNSPECIFIED) {
-            mImportance = mUserImportance;
-            mImportanceExplanation = getUserExplanation();
-        }
+    /**
+     * Sets the importance value the
+     * {@link android.service.notification.NotificationAssistantService} thinks the record should
+     * have.
+     */
+    public void setAssistantImportance(int importance) {
+        mAssistantImportance = importance;
+        calculateImportance();
     }
 
-    public int getUserImportance() {
-        return mUserImportance;
-    }
-
-    public void setImportance(int importance, CharSequence explanation) {
-        if (importance != IMPORTANCE_UNSPECIFIED) {
-            mImportance = importance;
-            mImportanceExplanation = explanation;
+    /**
+     * Recalculates the importance of the record after fields affecting importance have changed
+     */
+    protected void calculateImportance() {
+        mImportance = calculateInitialImportance();
+        mImportanceExplanation = "app";
+        if (getChannel().isImportanceLocked()) {
+            mImportanceExplanation = "user";
         }
-        applyUserImportance();
+        if (!getChannel().isImportanceLocked() && mAssistantImportance != IMPORTANCE_UNSPECIFIED) {
+            mImportance = mAssistantImportance;
+            mImportanceExplanation = "asst";
+        }
+        if (mSystemImportance != IMPORTANCE_UNSPECIFIED) {
+            mImportance = mSystemImportance;
+            mImportanceExplanation = "system";
+        }
     }
 
     public int getImportance() {
@@ -733,6 +762,19 @@
         return mIntercept;
     }
 
+    /**
+     * Set to affect global sort key.
+     *
+     * @param criticality used in a string based sort thus 0 is the most critical
+     */
+    public void setCriticality(int criticality) {
+        mCriticality = criticality;
+    }
+
+    public int getCriticality() {
+        return mCriticality;
+    }
+
     public boolean isIntercepted() {
         return mIntercept;
     }
@@ -907,7 +949,7 @@
     }
 
     /**
-     * @see RankingHelper#getIsAppImportanceLocked(String, int)
+     * @see PreferencesHelper#getIsAppImportanceLocked(String, int)
      */
     public boolean getIsAppImportanceLocked() {
         return mIsAppImportanceLocked;
@@ -1023,6 +1065,10 @@
         mStats.setDismissalSurface(surface);
     }
 
+    public void recordDismissalSentiment(@NotificationStats.DismissalSentiment int sentiment) {
+        mStats.setDismissalSentiment(sentiment);
+    }
+
     public void recordSnoozed() {
         mStats.setSnoozed();
     }
@@ -1047,6 +1093,22 @@
         mHasSeenSmartReplies = hasSeenSmartReplies;
     }
 
+    public void setSmartActions(ArrayList<Notification.Action> smartActions) {
+        mSmartActions = smartActions;
+    }
+
+    public ArrayList<Notification.Action> getSmartActions() {
+        return mSmartActions;
+    }
+
+    public void setSmartReplies(ArrayList<CharSequence> smartReplies) {
+        mSmartReplies = smartReplies;
+    }
+
+    public ArrayList<CharSequence> getSmartReplies() {
+        return mSmartReplies;
+    }
+
     /**
      * @return all {@link Uri} that should have permission granted to whoever
      *         will be rendering it. This list has already been vetted to only
@@ -1093,7 +1155,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             // This will throw SecurityException if caller can't grant
-            mAm.checkGrantUriPermission(sourceUid, null,
+            mUgmInternal.checkGrantUriPermission(sourceUid, null,
                     ContentProvider.getUriWithoutUserId(uri),
                     Intent.FLAG_GRANT_READ_URI_PERMISSION,
                     ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
@@ -1102,8 +1164,6 @@
                 mGrantableUris = new ArraySet<>();
             }
             mGrantableUris.add(uri);
-        } catch (RemoteException ignored) {
-            // Ignored because we're in same process
         } catch (SecurityException e) {
             if (!userOverriddenUri) {
                 if (mTargetSdkVersion >= Build.VERSION_CODES.P) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
new file mode 100644
index 0000000..432d17c
--- /dev/null
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -0,0 +1,1372 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.metrics.LogMaker;
+import android.os.Build;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.RankingHelperProto;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class PreferencesHelper implements RankingConfig {
+    private static final String TAG = "NotificationPrefHelper";
+    private static final int XML_VERSION = 1;
+
+    @VisibleForTesting
+    static final String TAG_RANKING = "ranking";
+    private static final String TAG_PACKAGE = "package";
+    private static final String TAG_CHANNEL = "channel";
+    private static final String TAG_GROUP = "channelGroup";
+
+    private static final String ATT_VERSION = "version";
+    private static final String ATT_NAME = "name";
+    private static final String ATT_UID = "uid";
+    private static final String ATT_ID = "id";
+    private static final String ATT_PRIORITY = "priority";
+    private static final String ATT_VISIBILITY = "visibility";
+    private static final String ATT_IMPORTANCE = "importance";
+    private static final String ATT_SHOW_BADGE = "show_badge";
+    private static final String ATT_APP_USER_LOCKED_FIELDS = "app_user_locked_fields";
+
+    private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
+    private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
+    private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
+    private static final boolean DEFAULT_SHOW_BADGE = true;
+    /**
+     * Default value for what fields are user locked. See {@link LockableAppFields} for all lockable
+     * fields.
+     */
+    private static final int DEFAULT_LOCKED_APP_FIELDS = 0;
+
+    /**
+     * All user-lockable fields for a given application.
+     */
+    @IntDef({LockableAppFields.USER_LOCKED_IMPORTANCE})
+    public @interface LockableAppFields {
+        int USER_LOCKED_IMPORTANCE = 0x00000001;
+    }
+
+    // pkg|uid => PackagePreferences
+    private final ArrayMap<String, PackagePreferences> mPackagePreferencess = new ArrayMap<>();
+    // pkg => PackagePreferences
+    private final ArrayMap<String, PackagePreferences> mRestoredWithoutUids = new ArrayMap<>();
+
+
+    private final Context mContext;
+    private final PackageManager mPm;
+    private final RankingHandler mRankingHandler;
+    private final ZenModeHelper mZenModeHelper;
+
+    private SparseBooleanArray mBadgingEnabled;
+    private boolean mAreChannelsBypassingDnd;
+
+
+    public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
+            ZenModeHelper zenHelper) {
+        mContext = context;
+        mZenModeHelper = zenHelper;
+        mRankingHandler = rankingHandler;
+        mPm = pm;
+
+        updateBadgingEnabled();
+
+        mAreChannelsBypassingDnd = (mZenModeHelper.getNotificationPolicy().state &
+                NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND) == 1;
+        updateChannelsBypassingDnd();
+
+    }
+
+    public void readXml(XmlPullParser parser, boolean forRestore)
+            throws XmlPullParserException, IOException {
+        int type = parser.getEventType();
+        if (type != XmlPullParser.START_TAG) return;
+        String tag = parser.getName();
+        if (!TAG_RANKING.equals(tag)) return;
+        // Clobber groups and channels with the xml, but don't delete other data that wasn't present
+        // at the time of serialization.
+        mRestoredWithoutUids.clear();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+            tag = parser.getName();
+            if (type == XmlPullParser.END_TAG && TAG_RANKING.equals(tag)) {
+                return;
+            }
+            if (type == XmlPullParser.START_TAG) {
+                if (TAG_PACKAGE.equals(tag)) {
+                    int uid = XmlUtils.readIntAttribute(parser, ATT_UID,
+                            PackagePreferences.UNKNOWN_UID);
+                    String name = parser.getAttributeValue(null, ATT_NAME);
+                    if (!TextUtils.isEmpty(name)) {
+                        if (forRestore) {
+                            try {
+                                //TODO: http://b/22388012
+                                uid = mPm.getPackageUidAsUser(name,
+                                        UserHandle.USER_SYSTEM);
+                            } catch (PackageManager.NameNotFoundException e) {
+                                // noop
+                            }
+                        }
+
+                        PackagePreferences r = getOrCreatePackagePreferences(name, uid,
+                                XmlUtils.readIntAttribute(
+                                        parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE),
+                                XmlUtils.readIntAttribute(parser, ATT_PRIORITY, DEFAULT_PRIORITY),
+                                XmlUtils.readIntAttribute(
+                                        parser, ATT_VISIBILITY, DEFAULT_VISIBILITY),
+                                XmlUtils.readBooleanAttribute(
+                                        parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE));
+                        r.importance = XmlUtils.readIntAttribute(
+                                parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
+                        r.priority = XmlUtils.readIntAttribute(
+                                parser, ATT_PRIORITY, DEFAULT_PRIORITY);
+                        r.visibility = XmlUtils.readIntAttribute(
+                                parser, ATT_VISIBILITY, DEFAULT_VISIBILITY);
+                        r.showBadge = XmlUtils.readBooleanAttribute(
+                                parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE);
+                        r.lockedAppFields = XmlUtils.readIntAttribute(parser,
+                                ATT_APP_USER_LOCKED_FIELDS, DEFAULT_LOCKED_APP_FIELDS);
+
+                        final int innerDepth = parser.getDepth();
+                        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                                && (type != XmlPullParser.END_TAG
+                                || parser.getDepth() > innerDepth)) {
+                            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                                continue;
+                            }
+
+                            String tagName = parser.getName();
+                            // Channel groups
+                            if (TAG_GROUP.equals(tagName)) {
+                                String id = parser.getAttributeValue(null, ATT_ID);
+                                CharSequence groupName = parser.getAttributeValue(null, ATT_NAME);
+                                if (!TextUtils.isEmpty(id)) {
+                                    NotificationChannelGroup group
+                                            = new NotificationChannelGroup(id, groupName);
+                                    group.populateFromXml(parser);
+                                    r.groups.put(id, group);
+                                }
+                            }
+                            // Channels
+                            if (TAG_CHANNEL.equals(tagName)) {
+                                String id = parser.getAttributeValue(null, ATT_ID);
+                                String channelName = parser.getAttributeValue(null, ATT_NAME);
+                                int channelImportance = XmlUtils.readIntAttribute(
+                                        parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
+                                if (!TextUtils.isEmpty(id) && !TextUtils.isEmpty(channelName)) {
+                                    NotificationChannel channel = new NotificationChannel(id,
+                                            channelName, channelImportance);
+                                    if (forRestore) {
+                                        channel.populateFromXmlForRestore(parser, mContext);
+                                    } else {
+                                        channel.populateFromXml(parser);
+                                    }
+                                    r.channels.put(id, channel);
+                                }
+                            }
+                        }
+
+                        try {
+                            deleteDefaultChannelIfNeeded(r);
+                        } catch (PackageManager.NameNotFoundException e) {
+                            Slog.e(TAG, "deleteDefaultChannelIfNeeded - Exception: " + e);
+                        }
+                    }
+                }
+            }
+        }
+        throw new IllegalStateException("Failed to reach END_DOCUMENT");
+    }
+
+    private PackagePreferences getPackagePreferences(String pkg, int uid) {
+        final String key = packagePreferencesKey(pkg, uid);
+        synchronized (mPackagePreferencess) {
+            return mPackagePreferencess.get(key);
+        }
+    }
+
+    private PackagePreferences getOrCreatePackagePreferences(String pkg, int uid) {
+        return getOrCreatePackagePreferences(pkg, uid,
+                DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY, DEFAULT_SHOW_BADGE);
+    }
+
+    private PackagePreferences getOrCreatePackagePreferences(String pkg, int uid, int importance,
+            int priority, int visibility, boolean showBadge) {
+        final String key = packagePreferencesKey(pkg, uid);
+        synchronized (mPackagePreferencess) {
+            PackagePreferences
+                    r = (uid == PackagePreferences.UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg)
+                    : mPackagePreferencess.get(key);
+            if (r == null) {
+                r = new PackagePreferences();
+                r.pkg = pkg;
+                r.uid = uid;
+                r.importance = importance;
+                r.priority = priority;
+                r.visibility = visibility;
+                r.showBadge = showBadge;
+
+                try {
+                    createDefaultChannelIfNeeded(r);
+                } catch (PackageManager.NameNotFoundException e) {
+                    Slog.e(TAG, "createDefaultChannelIfNeeded - Exception: " + e);
+                }
+
+                if (r.uid == PackagePreferences.UNKNOWN_UID) {
+                    mRestoredWithoutUids.put(pkg, r);
+                } else {
+                    mPackagePreferencess.put(key, r);
+                }
+            }
+            return r;
+        }
+    }
+
+    private boolean shouldHaveDefaultChannel(PackagePreferences r) throws
+            PackageManager.NameNotFoundException {
+        final int userId = UserHandle.getUserId(r.uid);
+        final ApplicationInfo applicationInfo =
+                mPm.getApplicationInfoAsUser(r.pkg, 0, userId);
+        if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
+            // O apps should not have the default channel.
+            return false;
+        }
+
+        // Otherwise, this app should have the default channel.
+        return true;
+    }
+
+    private void deleteDefaultChannelIfNeeded(PackagePreferences r) throws
+            PackageManager.NameNotFoundException {
+        if (!r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+            // Not present
+            return;
+        }
+
+        if (shouldHaveDefaultChannel(r)) {
+            // Keep the default channel until upgraded.
+            return;
+        }
+
+        // Remove Default Channel.
+        r.channels.remove(NotificationChannel.DEFAULT_CHANNEL_ID);
+    }
+
+    private void createDefaultChannelIfNeeded(PackagePreferences r) throws
+            PackageManager.NameNotFoundException {
+        if (r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+            r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID).setName(mContext.getString(
+                    com.android.internal.R.string.default_notification_channel_label));
+            return;
+        }
+
+        if (!shouldHaveDefaultChannel(r)) {
+            // Keep the default channel until upgraded.
+            return;
+        }
+
+        // Create Default Channel
+        NotificationChannel channel;
+        channel = new NotificationChannel(
+                NotificationChannel.DEFAULT_CHANNEL_ID,
+                mContext.getString(R.string.default_notification_channel_label),
+                r.importance);
+        channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
+        channel.setLockscreenVisibility(r.visibility);
+        if (r.importance != NotificationManager.IMPORTANCE_UNSPECIFIED) {
+            channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+        }
+        if (r.priority != DEFAULT_PRIORITY) {
+            channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
+        }
+        if (r.visibility != DEFAULT_VISIBILITY) {
+            channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
+        }
+        r.channels.put(channel.getId(), channel);
+    }
+
+    public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
+        out.startTag(null, TAG_RANKING);
+        out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
+
+        synchronized (mPackagePreferencess) {
+            final int N = mPackagePreferencess.size();
+            for (int i = 0; i < N; i++) {
+                final PackagePreferences r = mPackagePreferencess.valueAt(i);
+                //TODO: http://b/22388012
+                if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
+                    continue;
+                }
+                final boolean hasNonDefaultSettings =
+                        r.importance != DEFAULT_IMPORTANCE
+                                || r.priority != DEFAULT_PRIORITY
+                                || r.visibility != DEFAULT_VISIBILITY
+                                || r.showBadge != DEFAULT_SHOW_BADGE
+                                || r.lockedAppFields != DEFAULT_LOCKED_APP_FIELDS
+                                || r.channels.size() > 0
+                                || r.groups.size() > 0;
+                if (hasNonDefaultSettings) {
+                    out.startTag(null, TAG_PACKAGE);
+                    out.attribute(null, ATT_NAME, r.pkg);
+                    if (r.importance != DEFAULT_IMPORTANCE) {
+                        out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
+                    }
+                    if (r.priority != DEFAULT_PRIORITY) {
+                        out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority));
+                    }
+                    if (r.visibility != DEFAULT_VISIBILITY) {
+                        out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility));
+                    }
+                    out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge));
+                    out.attribute(null, ATT_APP_USER_LOCKED_FIELDS,
+                            Integer.toString(r.lockedAppFields));
+
+                    if (!forBackup) {
+                        out.attribute(null, ATT_UID, Integer.toString(r.uid));
+                    }
+
+                    for (NotificationChannelGroup group : r.groups.values()) {
+                        group.writeXml(out);
+                    }
+
+                    for (NotificationChannel channel : r.channels.values()) {
+                        if (forBackup) {
+                            if (!channel.isDeleted()) {
+                                channel.writeXmlForBackup(out, mContext);
+                            }
+                        } else {
+                            channel.writeXml(out);
+                        }
+                    }
+
+                    out.endTag(null, TAG_PACKAGE);
+                }
+            }
+        }
+        out.endTag(null, TAG_RANKING);
+    }
+
+    /**
+     * Gets importance.
+     */
+    @Override
+    public int getImportance(String packageName, int uid) {
+        return getOrCreatePackagePreferences(packageName, uid).importance;
+    }
+
+
+    /**
+     * Returns whether the importance of the corresponding notification is user-locked and shouldn't
+     * be adjusted by an assistant (via means of a blocking helper, for example). For the channel
+     * locking field, see {@link NotificationChannel#USER_LOCKED_IMPORTANCE}.
+     */
+    public boolean getIsAppImportanceLocked(String packageName, int uid) {
+        int userLockedFields = getOrCreatePackagePreferences(packageName, uid).lockedAppFields;
+        return (userLockedFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0;
+    }
+
+    @Override
+    public boolean canShowBadge(String packageName, int uid) {
+        return getOrCreatePackagePreferences(packageName, uid).showBadge;
+    }
+
+    @Override
+    public void setShowBadge(String packageName, int uid, boolean showBadge) {
+        getOrCreatePackagePreferences(packageName, uid).showBadge = showBadge;
+        updateConfig();
+    }
+
+    @Override
+    public boolean isGroupBlocked(String packageName, int uid, String groupId) {
+        if (groupId == null) {
+            return false;
+        }
+        PackagePreferences r = getOrCreatePackagePreferences(packageName, uid);
+        NotificationChannelGroup group = r.groups.get(groupId);
+        if (group == null) {
+            return false;
+        }
+        return group.isBlocked();
+    }
+
+    int getPackagePriority(String pkg, int uid) {
+        return getOrCreatePackagePreferences(pkg, uid).priority;
+    }
+
+    int getPackageVisibility(String pkg, int uid) {
+        return getOrCreatePackagePreferences(pkg, uid).visibility;
+    }
+
+    @Override
+    public void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
+            boolean fromTargetApp) {
+        Preconditions.checkNotNull(pkg);
+        Preconditions.checkNotNull(group);
+        Preconditions.checkNotNull(group.getId());
+        Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName()));
+        PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
+        if (r == null) {
+            throw new IllegalArgumentException("Invalid package");
+        }
+        final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
+        if (!group.equals(oldGroup)) {
+            // will log for new entries as well as name/description changes
+            MetricsLogger.action(getChannelGroupLog(group.getId(), pkg));
+        }
+        if (oldGroup != null) {
+            group.setChannels(oldGroup.getChannels());
+
+            if (fromTargetApp) {
+                group.setBlocked(oldGroup.isBlocked());
+            }
+        }
+        r.groups.put(group.getId(), group);
+    }
+
+    @Override
+    public void createNotificationChannel(String pkg, int uid, NotificationChannel channel,
+            boolean fromTargetApp, boolean hasDndAccess) {
+        Preconditions.checkNotNull(pkg);
+        Preconditions.checkNotNull(channel);
+        Preconditions.checkNotNull(channel.getId());
+        Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
+        PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
+        if (r == null) {
+            throw new IllegalArgumentException("Invalid package");
+        }
+        if (channel.getGroup() != null && !r.groups.containsKey(channel.getGroup())) {
+            throw new IllegalArgumentException("NotificationChannelGroup doesn't exist");
+        }
+        if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId())) {
+            throw new IllegalArgumentException("Reserved id");
+        }
+        NotificationChannel existing = r.channels.get(channel.getId());
+        // Keep most of the existing settings
+        if (existing != null && fromTargetApp) {
+            if (existing.isDeleted()) {
+                existing.setDeleted(false);
+
+                // log a resurrected channel as if it's new again
+                MetricsLogger.action(getChannelLog(channel, pkg).setType(
+                        com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
+            }
+
+            existing.setName(channel.getName().toString());
+            existing.setDescription(channel.getDescription());
+            existing.setBlockableSystem(channel.isBlockableSystem());
+            if (existing.getGroup() == null) {
+                existing.setGroup(channel.getGroup());
+            }
+
+            // Apps are allowed to downgrade channel importance if the user has not changed any
+            // fields on this channel yet.
+            if (existing.getUserLockedFields() == 0 &&
+                    channel.getImportance() < existing.getImportance()) {
+                existing.setImportance(channel.getImportance());
+            }
+
+            // system apps and dnd access apps can bypass dnd if the user hasn't changed any
+            // fields on the channel yet
+            if (existing.getUserLockedFields() == 0 && hasDndAccess) {
+                boolean bypassDnd = channel.canBypassDnd();
+                existing.setBypassDnd(bypassDnd);
+
+                if (bypassDnd != mAreChannelsBypassingDnd) {
+                    updateChannelsBypassingDnd();
+                }
+            }
+
+            updateConfig();
+            return;
+        }
+        if (channel.getImportance() < IMPORTANCE_NONE
+                || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
+            throw new IllegalArgumentException("Invalid importance level");
+        }
+
+        // Reset fields that apps aren't allowed to set.
+        if (fromTargetApp && !hasDndAccess) {
+            channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
+        }
+        if (fromTargetApp) {
+            channel.setLockscreenVisibility(r.visibility);
+        }
+        clearLockedFields(channel);
+        if (channel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
+            channel.setLockscreenVisibility(
+                    NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
+        }
+        if (!r.showBadge) {
+            channel.setShowBadge(false);
+        }
+
+        r.channels.put(channel.getId(), channel);
+        if (channel.canBypassDnd() != mAreChannelsBypassingDnd) {
+            updateChannelsBypassingDnd();
+        }
+        MetricsLogger.action(getChannelLog(channel, pkg).setType(
+                com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
+    }
+
+    void clearLockedFields(NotificationChannel channel) {
+        channel.unlockFields(channel.getUserLockedFields());
+    }
+
+    @Override
+    public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel,
+            boolean fromUser) {
+        Preconditions.checkNotNull(updatedChannel);
+        Preconditions.checkNotNull(updatedChannel.getId());
+        PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
+        if (r == null) {
+            throw new IllegalArgumentException("Invalid package");
+        }
+        NotificationChannel channel = r.channels.get(updatedChannel.getId());
+        if (channel == null || channel.isDeleted()) {
+            throw new IllegalArgumentException("Channel does not exist");
+        }
+        if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
+            updatedChannel.setLockscreenVisibility(
+                    NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
+        }
+        if (fromUser) {
+            updatedChannel.lockFields(channel.getUserLockedFields());
+            lockFieldsForUpdate(channel, updatedChannel);
+        } else {
+            updatedChannel.unlockFields(updatedChannel.getUserLockedFields());
+        }
+        r.channels.put(updatedChannel.getId(), updatedChannel);
+
+        if (onlyHasDefaultChannel(pkg, uid)) {
+            // copy settings to app level so they are inherited by new channels
+            // when the app migrates
+            r.importance = updatedChannel.getImportance();
+            r.priority = updatedChannel.canBypassDnd()
+                    ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT;
+            r.visibility = updatedChannel.getLockscreenVisibility();
+            r.showBadge = updatedChannel.canShowBadge();
+        }
+
+        if (!channel.equals(updatedChannel)) {
+            // only log if there are real changes
+            MetricsLogger.action(getChannelLog(updatedChannel, pkg));
+        }
+
+        if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd) {
+            updateChannelsBypassingDnd();
+        }
+        updateConfig();
+    }
+
+    @Override
+    public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId,
+            boolean includeDeleted) {
+        Preconditions.checkNotNull(pkg);
+        PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
+        if (r == null) {
+            return null;
+        }
+        if (channelId == null) {
+            channelId = NotificationChannel.DEFAULT_CHANNEL_ID;
+        }
+        final NotificationChannel nc = r.channels.get(channelId);
+        if (nc != null && (includeDeleted || !nc.isDeleted())) {
+            return nc;
+        }
+        return null;
+    }
+
+    @Override
+    public void deleteNotificationChannel(String pkg, int uid, String channelId) {
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null) {
+            return;
+        }
+        NotificationChannel channel = r.channels.get(channelId);
+        if (channel != null) {
+            channel.setDeleted(true);
+            LogMaker lm = getChannelLog(channel, pkg);
+            lm.setType(com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_CLOSE);
+            MetricsLogger.action(lm);
+
+            if (mAreChannelsBypassingDnd && channel.canBypassDnd()) {
+                updateChannelsBypassingDnd();
+            }
+        }
+    }
+
+    @Override
+    @VisibleForTesting
+    public void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId) {
+        Preconditions.checkNotNull(pkg);
+        Preconditions.checkNotNull(channelId);
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null) {
+            return;
+        }
+        r.channels.remove(channelId);
+    }
+
+    @Override
+    public void permanentlyDeleteNotificationChannels(String pkg, int uid) {
+        Preconditions.checkNotNull(pkg);
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null) {
+            return;
+        }
+        int N = r.channels.size() - 1;
+        for (int i = N; i >= 0; i--) {
+            String key = r.channels.keyAt(i);
+            if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(key)) {
+                r.channels.remove(key);
+            }
+        }
+    }
+
+    public NotificationChannelGroup getNotificationChannelGroupWithChannels(String pkg,
+            int uid, String groupId, boolean includeDeleted) {
+        Preconditions.checkNotNull(pkg);
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null || groupId == null || !r.groups.containsKey(groupId)) {
+            return null;
+        }
+        NotificationChannelGroup group = r.groups.get(groupId).clone();
+        group.setChannels(new ArrayList<>());
+        int N = r.channels.size();
+        for (int i = 0; i < N; i++) {
+            final NotificationChannel nc = r.channels.valueAt(i);
+            if (includeDeleted || !nc.isDeleted()) {
+                if (groupId.equals(nc.getGroup())) {
+                    group.addChannel(nc);
+                }
+            }
+        }
+        return group;
+    }
+
+    public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
+            int uid) {
+        Preconditions.checkNotNull(pkg);
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null) {
+            return null;
+        }
+        return r.groups.get(groupId);
+    }
+
+    @Override
+    public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
+            int uid, boolean includeDeleted, boolean includeNonGrouped) {
+        Preconditions.checkNotNull(pkg);
+        Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null) {
+            return ParceledListSlice.emptyList();
+        }
+        NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null);
+        int N = r.channels.size();
+        for (int i = 0; i < N; i++) {
+            final NotificationChannel nc = r.channels.valueAt(i);
+            if (includeDeleted || !nc.isDeleted()) {
+                if (nc.getGroup() != null) {
+                    if (r.groups.get(nc.getGroup()) != null) {
+                        NotificationChannelGroup ncg = groups.get(nc.getGroup());
+                        if (ncg == null) {
+                            ncg = r.groups.get(nc.getGroup()).clone();
+                            ncg.setChannels(new ArrayList<>());
+                            groups.put(nc.getGroup(), ncg);
+
+                        }
+                        ncg.addChannel(nc);
+                    }
+                } else {
+                    nonGrouped.addChannel(nc);
+                }
+            }
+        }
+        if (includeNonGrouped && nonGrouped.getChannels().size() > 0) {
+            groups.put(null, nonGrouped);
+        }
+        return new ParceledListSlice<>(new ArrayList<>(groups.values()));
+    }
+
+    public List<NotificationChannel> deleteNotificationChannelGroup(String pkg, int uid,
+            String groupId) {
+        List<NotificationChannel> deletedChannels = new ArrayList<>();
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null || TextUtils.isEmpty(groupId)) {
+            return deletedChannels;
+        }
+
+        r.groups.remove(groupId);
+
+        int N = r.channels.size();
+        for (int i = 0; i < N; i++) {
+            final NotificationChannel nc = r.channels.valueAt(i);
+            if (groupId.equals(nc.getGroup())) {
+                nc.setDeleted(true);
+                deletedChannels.add(nc);
+            }
+        }
+        return deletedChannels;
+    }
+
+    @Override
+    public Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
+            int uid) {
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null) {
+            return new ArrayList<>();
+        }
+        return r.groups.values();
+    }
+
+    @Override
+    public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid,
+            boolean includeDeleted) {
+        Preconditions.checkNotNull(pkg);
+        List<NotificationChannel> channels = new ArrayList<>();
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null) {
+            return ParceledListSlice.emptyList();
+        }
+        int N = r.channels.size();
+        for (int i = 0; i < N; i++) {
+            final NotificationChannel nc = r.channels.valueAt(i);
+            if (includeDeleted || !nc.isDeleted()) {
+                channels.add(nc);
+            }
+        }
+        return new ParceledListSlice<>(channels);
+    }
+
+    /**
+     * True for pre-O apps that only have the default channel, or pre O apps that have no
+     * channels yet. This method will create the default channel for pre-O apps that don't have it.
+     * Should never be true for O+ targeting apps, but that's enforced on boot/when an app
+     * upgrades.
+     */
+    public boolean onlyHasDefaultChannel(String pkg, int uid) {
+        PackagePreferences r = getOrCreatePackagePreferences(pkg, uid);
+        if (r.channels.size() == 1
+                && r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+            return true;
+        }
+        return false;
+    }
+
+    public int getDeletedChannelCount(String pkg, int uid) {
+        Preconditions.checkNotNull(pkg);
+        int deletedCount = 0;
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null) {
+            return deletedCount;
+        }
+        int N = r.channels.size();
+        for (int i = 0; i < N; i++) {
+            final NotificationChannel nc = r.channels.valueAt(i);
+            if (nc.isDeleted()) {
+                deletedCount++;
+            }
+        }
+        return deletedCount;
+    }
+
+    public int getBlockedChannelCount(String pkg, int uid) {
+        Preconditions.checkNotNull(pkg);
+        int blockedCount = 0;
+        PackagePreferences r = getPackagePreferences(pkg, uid);
+        if (r == null) {
+            return blockedCount;
+        }
+        int N = r.channels.size();
+        for (int i = 0; i < N; i++) {
+            final NotificationChannel nc = r.channels.valueAt(i);
+            if (!nc.isDeleted() && IMPORTANCE_NONE == nc.getImportance()) {
+                blockedCount++;
+            }
+        }
+        return blockedCount;
+    }
+
+    public int getBlockedAppCount(int userId) {
+        int count = 0;
+        synchronized (mPackagePreferencess) {
+            final int N = mPackagePreferencess.size();
+            for (int i = 0; i < N; i++) {
+                final PackagePreferences r = mPackagePreferencess.valueAt(i);
+                if (userId == UserHandle.getUserId(r.uid)
+                        && r.importance == IMPORTANCE_NONE) {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+
+    public void updateChannelsBypassingDnd() {
+        synchronized (mPackagePreferencess) {
+            final int numPackagePreferencess = mPackagePreferencess.size();
+            for (int PackagePreferencesIndex = 0; PackagePreferencesIndex < numPackagePreferencess;
+                    PackagePreferencesIndex++) {
+                final PackagePreferences r = mPackagePreferencess.valueAt(PackagePreferencesIndex);
+                final int numChannels = r.channels.size();
+
+                for (int channelIndex = 0; channelIndex < numChannels; channelIndex++) {
+                    NotificationChannel channel = r.channels.valueAt(channelIndex);
+                    if (!channel.isDeleted() && channel.canBypassDnd()) {
+                        // If any channel bypasses DND, synchronize state and return early.
+                        if (!mAreChannelsBypassingDnd) {
+                            mAreChannelsBypassingDnd = true;
+                            updateZenPolicy(true);
+                        }
+                        return;
+                    }
+                }
+            }
+        }
+
+        // If no channels bypass DND, update the zen policy once to disable DND bypass.
+        if (mAreChannelsBypassingDnd) {
+            mAreChannelsBypassingDnd = false;
+            updateZenPolicy(false);
+        }
+    }
+
+    public void updateZenPolicy(boolean areChannelsBypassingDnd) {
+        NotificationManager.Policy policy = mZenModeHelper.getNotificationPolicy();
+        mZenModeHelper.setNotificationPolicy(new NotificationManager.Policy(
+                policy.priorityCategories, policy.priorityCallSenders,
+                policy.priorityMessageSenders, policy.suppressedVisualEffects,
+                (areChannelsBypassingDnd ? NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND
+                        : 0)));
+    }
+
+    public boolean areChannelsBypassingDnd() {
+        return mAreChannelsBypassingDnd;
+    }
+
+    /**
+     * Sets importance.
+     */
+    @Override
+    public void setImportance(String pkgName, int uid, int importance) {
+        getOrCreatePackagePreferences(pkgName, uid).importance = importance;
+        updateConfig();
+    }
+
+    public void setEnabled(String packageName, int uid, boolean enabled) {
+        boolean wasEnabled = getImportance(packageName, uid) != IMPORTANCE_NONE;
+        if (wasEnabled == enabled) {
+            return;
+        }
+        setImportance(packageName, uid,
+                enabled ? DEFAULT_IMPORTANCE : IMPORTANCE_NONE);
+    }
+
+    /**
+     * Sets whether any notifications from the app, represented by the given {@code pkgName} and
+     * {@code uid}, have their importance locked by the user. Locked notifications don't get
+     * considered for sentiment adjustments (and thus never show a blocking helper).
+     */
+    public void setAppImportanceLocked(String packageName, int uid) {
+        PackagePreferences PackagePreferences = getOrCreatePackagePreferences(packageName, uid);
+        if ((PackagePreferences.lockedAppFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0) {
+            return;
+        }
+
+        PackagePreferences.lockedAppFields =
+                PackagePreferences.lockedAppFields | LockableAppFields.USER_LOCKED_IMPORTANCE;
+        updateConfig();
+    }
+
+    @VisibleForTesting
+    void lockFieldsForUpdate(NotificationChannel original, NotificationChannel update) {
+        if (original.canBypassDnd() != update.canBypassDnd()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
+        }
+        if (original.getLockscreenVisibility() != update.getLockscreenVisibility()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
+        }
+        if (original.getImportance() != update.getImportance()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+        }
+        if (original.shouldShowLights() != update.shouldShowLights()
+                || original.getLightColor() != update.getLightColor()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
+        }
+        if (!Objects.equals(original.getSound(), update.getSound())) {
+            update.lockFields(NotificationChannel.USER_LOCKED_SOUND);
+        }
+        if (!Arrays.equals(original.getVibrationPattern(), update.getVibrationPattern())
+                || original.shouldVibrate() != update.shouldVibrate()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
+        }
+        if (original.canShowBadge() != update.canShowBadge()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
+        }
+    }
+
+    public void dump(PrintWriter pw, String prefix,
+            @NonNull NotificationManagerService.DumpFilter filter) {
+        pw.print(prefix);
+        pw.println("per-package config:");
+
+        pw.println("PackagePreferencess:");
+        synchronized (mPackagePreferencess) {
+            dumpPackagePreferencess(pw, prefix, filter, mPackagePreferencess);
+        }
+        pw.println("Restored without uid:");
+        dumpPackagePreferencess(pw, prefix, filter, mRestoredWithoutUids);
+    }
+
+    public void dump(ProtoOutputStream proto,
+            @NonNull NotificationManagerService.DumpFilter filter) {
+        synchronized (mPackagePreferencess) {
+            dumpPackagePreferencess(proto, RankingHelperProto.RECORDS, filter,
+                    mPackagePreferencess);
+        }
+        dumpPackagePreferencess(proto, RankingHelperProto.RECORDS_RESTORED_WITHOUT_UID, filter,
+                mRestoredWithoutUids);
+    }
+
+    private static void dumpPackagePreferencess(PrintWriter pw, String prefix,
+            @NonNull NotificationManagerService.DumpFilter filter,
+            ArrayMap<String, PackagePreferences> PackagePreferencess) {
+        final int N = PackagePreferencess.size();
+        for (int i = 0; i < N; i++) {
+            final PackagePreferences r = PackagePreferencess.valueAt(i);
+            if (filter.matches(r.pkg)) {
+                pw.print(prefix);
+                pw.print("  AppSettings: ");
+                pw.print(r.pkg);
+                pw.print(" (");
+                pw.print(r.uid == PackagePreferences.UNKNOWN_UID ? "UNKNOWN_UID"
+                        : Integer.toString(r.uid));
+                pw.print(')');
+                if (r.importance != DEFAULT_IMPORTANCE) {
+                    pw.print(" importance=");
+                    pw.print(NotificationListenerService.Ranking.importanceToString(r.importance));
+                }
+                if (r.priority != DEFAULT_PRIORITY) {
+                    pw.print(" priority=");
+                    pw.print(Notification.priorityToString(r.priority));
+                }
+                if (r.visibility != DEFAULT_VISIBILITY) {
+                    pw.print(" visibility=");
+                    pw.print(Notification.visibilityToString(r.visibility));
+                }
+                pw.print(" showBadge=");
+                pw.print(Boolean.toString(r.showBadge));
+                pw.println();
+                for (NotificationChannel channel : r.channels.values()) {
+                    pw.print(prefix);
+                    channel.dump(pw, "    ", filter.redact);
+                }
+                for (NotificationChannelGroup group : r.groups.values()) {
+                    pw.print(prefix);
+                    pw.print("  ");
+                    pw.print("  ");
+                    pw.println(group);
+                }
+            }
+        }
+    }
+
+    private static void dumpPackagePreferencess(ProtoOutputStream proto, long fieldId,
+            @NonNull NotificationManagerService.DumpFilter filter,
+            ArrayMap<String, PackagePreferences> PackagePreferencess) {
+        final int N = PackagePreferencess.size();
+        long fToken;
+        for (int i = 0; i < N; i++) {
+            final PackagePreferences r = PackagePreferencess.valueAt(i);
+            if (filter.matches(r.pkg)) {
+                fToken = proto.start(fieldId);
+
+                proto.write(RankingHelperProto.RecordProto.PACKAGE, r.pkg);
+                proto.write(RankingHelperProto.RecordProto.UID, r.uid);
+                proto.write(RankingHelperProto.RecordProto.IMPORTANCE, r.importance);
+                proto.write(RankingHelperProto.RecordProto.PRIORITY, r.priority);
+                proto.write(RankingHelperProto.RecordProto.VISIBILITY, r.visibility);
+                proto.write(RankingHelperProto.RecordProto.SHOW_BADGE, r.showBadge);
+
+                for (NotificationChannel channel : r.channels.values()) {
+                    channel.writeToProto(proto, RankingHelperProto.RecordProto.CHANNELS);
+                }
+                for (NotificationChannelGroup group : r.groups.values()) {
+                    group.writeToProto(proto, RankingHelperProto.RecordProto.CHANNEL_GROUPS);
+                }
+
+                proto.end(fToken);
+            }
+        }
+    }
+
+    public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) {
+        JSONObject ranking = new JSONObject();
+        JSONArray PackagePreferencess = new JSONArray();
+        try {
+            ranking.put("noUid", mRestoredWithoutUids.size());
+        } catch (JSONException e) {
+            // pass
+        }
+        synchronized (mPackagePreferencess) {
+            final int N = mPackagePreferencess.size();
+            for (int i = 0; i < N; i++) {
+                final PackagePreferences r = mPackagePreferencess.valueAt(i);
+                if (filter == null || filter.matches(r.pkg)) {
+                    JSONObject PackagePreferences = new JSONObject();
+                    try {
+                        PackagePreferences.put("userId", UserHandle.getUserId(r.uid));
+                        PackagePreferences.put("packageName", r.pkg);
+                        if (r.importance != DEFAULT_IMPORTANCE) {
+                            PackagePreferences.put("importance",
+                                    NotificationListenerService.Ranking.importanceToString(
+                                            r.importance));
+                        }
+                        if (r.priority != DEFAULT_PRIORITY) {
+                            PackagePreferences.put("priority",
+                                    Notification.priorityToString(r.priority));
+                        }
+                        if (r.visibility != DEFAULT_VISIBILITY) {
+                            PackagePreferences.put("visibility",
+                                    Notification.visibilityToString(r.visibility));
+                        }
+                        if (r.showBadge != DEFAULT_SHOW_BADGE) {
+                            PackagePreferences.put("showBadge", Boolean.valueOf(r.showBadge));
+                        }
+                        JSONArray channels = new JSONArray();
+                        for (NotificationChannel channel : r.channels.values()) {
+                            channels.put(channel.toJson());
+                        }
+                        PackagePreferences.put("channels", channels);
+                        JSONArray groups = new JSONArray();
+                        for (NotificationChannelGroup group : r.groups.values()) {
+                            groups.put(group.toJson());
+                        }
+                        PackagePreferences.put("groups", groups);
+                    } catch (JSONException e) {
+                        // pass
+                    }
+                    PackagePreferencess.put(PackagePreferences);
+                }
+            }
+        }
+        try {
+            ranking.put("PackagePreferencess", PackagePreferencess);
+        } catch (JSONException e) {
+            // pass
+        }
+        return ranking;
+    }
+
+    /**
+     * Dump only the ban information as structured JSON for the stats collector.
+     *
+     * This is intentionally redundant with {#link dumpJson} because the old
+     * scraper will expect this format.
+     *
+     * @param filter
+     * @return
+     */
+    public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter) {
+        JSONArray bans = new JSONArray();
+        Map<Integer, String> packageBans = getPackageBans();
+        for (Map.Entry<Integer, String> ban : packageBans.entrySet()) {
+            final int userId = UserHandle.getUserId(ban.getKey());
+            final String packageName = ban.getValue();
+            if (filter == null || filter.matches(packageName)) {
+                JSONObject banJson = new JSONObject();
+                try {
+                    banJson.put("userId", userId);
+                    banJson.put("packageName", packageName);
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+                bans.put(banJson);
+            }
+        }
+        return bans;
+    }
+
+    public Map<Integer, String> getPackageBans() {
+        synchronized (mPackagePreferencess) {
+            final int N = mPackagePreferencess.size();
+            ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
+            for (int i = 0; i < N; i++) {
+                final PackagePreferences r = mPackagePreferencess.valueAt(i);
+                if (r.importance == IMPORTANCE_NONE) {
+                    packageBans.put(r.uid, r.pkg);
+                }
+            }
+
+            return packageBans;
+        }
+    }
+
+    /**
+     * Dump only the channel information as structured JSON for the stats collector.
+     *
+     * This is intentionally redundant with {#link dumpJson} because the old
+     * scraper will expect this format.
+     *
+     * @param filter
+     * @return
+     */
+    public JSONArray dumpChannelsJson(NotificationManagerService.DumpFilter filter) {
+        JSONArray channels = new JSONArray();
+        Map<String, Integer> packageChannels = getPackageChannels();
+        for (Map.Entry<String, Integer> channelCount : packageChannels.entrySet()) {
+            final String packageName = channelCount.getKey();
+            if (filter == null || filter.matches(packageName)) {
+                JSONObject channelCountJson = new JSONObject();
+                try {
+                    channelCountJson.put("packageName", packageName);
+                    channelCountJson.put("channelCount", channelCount.getValue());
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+                channels.put(channelCountJson);
+            }
+        }
+        return channels;
+    }
+
+    private Map<String, Integer> getPackageChannels() {
+        ArrayMap<String, Integer> packageChannels = new ArrayMap<>();
+        synchronized (mPackagePreferencess) {
+            for (int i = 0; i < mPackagePreferencess.size(); i++) {
+                final PackagePreferences r = mPackagePreferencess.valueAt(i);
+                int channelCount = 0;
+                for (int j = 0; j < r.channels.size(); j++) {
+                    if (!r.channels.valueAt(j).isDeleted()) {
+                        channelCount++;
+                    }
+                }
+                packageChannels.put(r.pkg, channelCount);
+            }
+        }
+        return packageChannels;
+    }
+
+    public void onUserRemoved(int userId) {
+        synchronized (mPackagePreferencess) {
+            int N = mPackagePreferencess.size();
+            for (int i = N - 1; i >= 0; i--) {
+                PackagePreferences PackagePreferences = mPackagePreferencess.valueAt(i);
+                if (UserHandle.getUserId(PackagePreferences.uid) == userId) {
+                    mPackagePreferencess.removeAt(i);
+                }
+            }
+        }
+    }
+
+    protected void onLocaleChanged(Context context, int userId) {
+        synchronized (mPackagePreferencess) {
+            int N = mPackagePreferencess.size();
+            for (int i = 0; i < N; i++) {
+                PackagePreferences PackagePreferences = mPackagePreferencess.valueAt(i);
+                if (UserHandle.getUserId(PackagePreferences.uid) == userId) {
+                    if (PackagePreferences.channels.containsKey(
+                            NotificationChannel.DEFAULT_CHANNEL_ID)) {
+                        PackagePreferences.channels.get(
+                                NotificationChannel.DEFAULT_CHANNEL_ID).setName(
+                                context.getResources().getString(
+                                        R.string.default_notification_channel_label));
+                    }
+                }
+            }
+        }
+    }
+
+    public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList,
+            int[] uidList) {
+        if (pkgList == null || pkgList.length == 0) {
+            return; // nothing to do
+        }
+        boolean updated = false;
+        if (removingPackage) {
+            // Remove notification settings for uninstalled package
+            int size = Math.min(pkgList.length, uidList.length);
+            for (int i = 0; i < size; i++) {
+                final String pkg = pkgList[i];
+                final int uid = uidList[i];
+                synchronized (mPackagePreferencess) {
+                    mPackagePreferencess.remove(packagePreferencesKey(pkg, uid));
+                }
+                mRestoredWithoutUids.remove(pkg);
+                updated = true;
+            }
+        } else {
+            for (String pkg : pkgList) {
+                // Package install
+                final PackagePreferences r = mRestoredWithoutUids.get(pkg);
+                if (r != null) {
+                    try {
+                        r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId);
+                        mRestoredWithoutUids.remove(pkg);
+                        synchronized (mPackagePreferencess) {
+                            mPackagePreferencess.put(packagePreferencesKey(r.pkg, r.uid), r);
+                        }
+                        updated = true;
+                    } catch (PackageManager.NameNotFoundException e) {
+                        // noop
+                    }
+                }
+                // Package upgrade
+                try {
+                    PackagePreferences fullPackagePreferences = getPackagePreferences(pkg,
+                            mPm.getPackageUidAsUser(pkg, changeUserId));
+                    if (fullPackagePreferences != null) {
+                        createDefaultChannelIfNeeded(fullPackagePreferences);
+                        deleteDefaultChannelIfNeeded(fullPackagePreferences);
+                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                }
+            }
+        }
+
+        if (updated) {
+            updateConfig();
+        }
+    }
+
+    private LogMaker getChannelLog(NotificationChannel channel, String pkg) {
+        return new LogMaker(
+                com.android.internal.logging.nano.MetricsProto.MetricsEvent
+                        .ACTION_NOTIFICATION_CHANNEL)
+                .setType(com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_UPDATE)
+                .setPackageName(pkg)
+                .addTaggedData(
+                        com.android.internal.logging.nano.MetricsProto.MetricsEvent
+                                .FIELD_NOTIFICATION_CHANNEL_ID,
+                        channel.getId())
+                .addTaggedData(
+                        com.android.internal.logging.nano.MetricsProto.MetricsEvent
+                                .FIELD_NOTIFICATION_CHANNEL_IMPORTANCE,
+                        channel.getImportance());
+    }
+
+    private LogMaker getChannelGroupLog(String groupId, String pkg) {
+        return new LogMaker(
+                com.android.internal.logging.nano.MetricsProto.MetricsEvent
+                        .ACTION_NOTIFICATION_CHANNEL_GROUP)
+                .setType(com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_UPDATE)
+                .addTaggedData(
+                        com.android.internal.logging.nano.MetricsProto.MetricsEvent
+                                .FIELD_NOTIFICATION_CHANNEL_GROUP_ID,
+                        groupId)
+                .setPackageName(pkg);
+    }
+
+
+    public void updateBadgingEnabled() {
+        if (mBadgingEnabled == null) {
+            mBadgingEnabled = new SparseBooleanArray();
+        }
+        boolean changed = false;
+        // update the cached values
+        for (int index = 0; index < mBadgingEnabled.size(); index++) {
+            int userId = mBadgingEnabled.keyAt(index);
+            final boolean oldValue = mBadgingEnabled.get(userId);
+            final boolean newValue = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.NOTIFICATION_BADGING,
+                    DEFAULT_SHOW_BADGE ? 1 : 0, userId) != 0;
+            mBadgingEnabled.put(userId, newValue);
+            changed |= oldValue != newValue;
+        }
+        if (changed) {
+            updateConfig();
+        }
+    }
+
+    public boolean badgingEnabled(UserHandle userHandle) {
+        int userId = userHandle.getIdentifier();
+        if (userId == UserHandle.USER_ALL) {
+            return false;
+        }
+        if (mBadgingEnabled.indexOfKey(userId) < 0) {
+            mBadgingEnabled.put(userId,
+                    Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                            Settings.Secure.NOTIFICATION_BADGING,
+                            DEFAULT_SHOW_BADGE ? 1 : 0, userId) != 0);
+        }
+        return mBadgingEnabled.get(userId, DEFAULT_SHOW_BADGE);
+    }
+
+    private void updateConfig() {
+        mRankingHandler.requestSort();
+    }
+
+    private static String packagePreferencesKey(String pkg, int uid) {
+        return pkg + "|" + uid;
+    }
+
+    private static class PackagePreferences {
+        static int UNKNOWN_UID = UserHandle.USER_NULL;
+
+        String pkg;
+        int uid = UNKNOWN_UID;
+        int importance = DEFAULT_IMPORTANCE;
+        int priority = DEFAULT_PRIORITY;
+        int visibility = DEFAULT_VISIBILITY;
+        boolean showBadge = DEFAULT_SHOW_BADGE;
+        int lockedAppFields = DEFAULT_LOCKED_APP_FIELDS;
+
+        ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
+        Map<String, NotificationChannelGroup> groups = new ConcurrentHashMap<>();
+    }
+}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 61b5415..b1e9144 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -15,123 +15,37 @@
  */
 package com.android.server.notification;
 
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-
-import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
 import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ParceledListSlice;
-import android.metrics.LogMaker;
-import android.os.Build;
-import android.os.UserHandle;
-import android.provider.Settings.Secure;
-import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.RankingHelperProto;
-import android.service.notification.RankingHelperProto.RecordProto;
-import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Slog;
-import android.util.SparseBooleanArray;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.util.Preconditions;
-import com.android.internal.util.XmlUtils;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
 
-public class RankingHelper implements RankingConfig {
+public class RankingHelper {
     private static final String TAG = "RankingHelper";
 
-    private static final int XML_VERSION = 1;
-
-    static final String TAG_RANKING = "ranking";
-    private static final String TAG_PACKAGE = "package";
-    private static final String TAG_CHANNEL = "channel";
-    private static final String TAG_GROUP = "channelGroup";
-
-    private static final String ATT_VERSION = "version";
-    private static final String ATT_NAME = "name";
-    private static final String ATT_UID = "uid";
-    private static final String ATT_ID = "id";
-    private static final String ATT_PRIORITY = "priority";
-    private static final String ATT_VISIBILITY = "visibility";
-    private static final String ATT_IMPORTANCE = "importance";
-    private static final String ATT_SHOW_BADGE = "show_badge";
-    private static final String ATT_APP_USER_LOCKED_FIELDS = "app_user_locked_fields";
-
-    private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
-    private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
-    private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
-    private static final boolean DEFAULT_SHOW_BADGE = true;
-    /**
-     * Default value for what fields are user locked. See {@link LockableAppFields} for all lockable
-     * fields.
-     */
-    private static final int DEFAULT_LOCKED_APP_FIELDS = 0;
-
-    /**
-     * All user-lockable fields for a given application.
-     */
-    @IntDef({LockableAppFields.USER_LOCKED_IMPORTANCE})
-    public @interface LockableAppFields {
-        int USER_LOCKED_IMPORTANCE = 0x00000001;
-    }
-
     private final NotificationSignalExtractor[] mSignalExtractors;
     private final NotificationComparator mPreliminaryComparator;
     private final GlobalSortKeyComparator mFinalComparator = new GlobalSortKeyComparator();
 
-    private final ArrayMap<String, Record> mRecords = new ArrayMap<>(); // pkg|uid => Record
     private final ArrayMap<String, NotificationRecord> mProxyByGroupTmp = new ArrayMap<>();
-    private final ArrayMap<String, Record> mRestoredWithoutUids = new ArrayMap<>(); // pkg => Record
 
     private final Context mContext;
     private final RankingHandler mRankingHandler;
-    private final PackageManager mPm;
-    private SparseBooleanArray mBadgingEnabled;
 
-    private boolean mAreChannelsBypassingDnd;
-    private ZenModeHelper mZenModeHelper;
 
-    public RankingHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
+    public RankingHelper(Context context, RankingHandler rankingHandler, RankingConfig config,
             ZenModeHelper zenHelper, NotificationUsageStats usageStats, String[] extractorNames) {
         mContext = context;
         mRankingHandler = rankingHandler;
-        mPm = pm;
-        mZenModeHelper= zenHelper;
-
         mPreliminaryComparator = new NotificationComparator(mContext);
 
-        updateBadgingEnabled();
-
         final int N = extractorNames.length;
         mSignalExtractors = new NotificationSignalExtractor[N];
         for (int i = 0; i < N; i++) {
@@ -140,7 +54,7 @@
                 NotificationSignalExtractor extractor =
                         (NotificationSignalExtractor) extractorClass.newInstance();
                 extractor.initialize(mContext, usageStats);
-                extractor.setConfig(this);
+                extractor.setConfig(config);
                 extractor.setZenHelper(zenHelper);
                 mSignalExtractors[i] = extractor;
             } catch (ClassNotFoundException e) {
@@ -151,10 +65,6 @@
                 Slog.w(TAG, "Problem accessing extractor " + extractorNames[i] + ".", e);
             }
         }
-
-        mAreChannelsBypassingDnd = (mZenModeHelper.getNotificationPolicy().state &
-                NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND) == 1;
-        updateChannelsBypassingDnd();
     }
 
     @SuppressWarnings("unchecked")
@@ -184,279 +94,6 @@
         }
     }
 
-    public void readXml(XmlPullParser parser, boolean forRestore)
-            throws XmlPullParserException, IOException {
-        int type = parser.getEventType();
-        if (type != XmlPullParser.START_TAG) return;
-        String tag = parser.getName();
-        if (!TAG_RANKING.equals(tag)) return;
-        // Clobber groups and channels with the xml, but don't delete other data that wasn't present
-        // at the time of serialization.
-        mRestoredWithoutUids.clear();
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
-            tag = parser.getName();
-            if (type == XmlPullParser.END_TAG && TAG_RANKING.equals(tag)) {
-                return;
-            }
-            if (type == XmlPullParser.START_TAG) {
-                if (TAG_PACKAGE.equals(tag)) {
-                    int uid = XmlUtils.readIntAttribute(parser, ATT_UID, Record.UNKNOWN_UID);
-                    String name = parser.getAttributeValue(null, ATT_NAME);
-                    if (!TextUtils.isEmpty(name)) {
-                        if (forRestore) {
-                            try {
-                                //TODO: http://b/22388012
-                                uid = mPm.getPackageUidAsUser(name, UserHandle.USER_SYSTEM);
-                            } catch (NameNotFoundException e) {
-                                // noop
-                            }
-                        }
-
-                        Record r = getOrCreateRecord(name, uid,
-                                XmlUtils.readIntAttribute(
-                                        parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE),
-                                XmlUtils.readIntAttribute(parser, ATT_PRIORITY, DEFAULT_PRIORITY),
-                                XmlUtils.readIntAttribute(
-                                        parser, ATT_VISIBILITY, DEFAULT_VISIBILITY),
-                                XmlUtils.readBooleanAttribute(
-                                        parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE));
-                        r.importance = XmlUtils.readIntAttribute(
-                                parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
-                        r.priority = XmlUtils.readIntAttribute(
-                                parser, ATT_PRIORITY, DEFAULT_PRIORITY);
-                        r.visibility = XmlUtils.readIntAttribute(
-                                parser, ATT_VISIBILITY, DEFAULT_VISIBILITY);
-                        r.showBadge = XmlUtils.readBooleanAttribute(
-                                parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE);
-                        r.lockedAppFields = XmlUtils.readIntAttribute(parser,
-                                ATT_APP_USER_LOCKED_FIELDS, DEFAULT_LOCKED_APP_FIELDS);
-
-                        final int innerDepth = parser.getDepth();
-                        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                                && (type != XmlPullParser.END_TAG
-                                || parser.getDepth() > innerDepth)) {
-                            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                                continue;
-                            }
-
-                            String tagName = parser.getName();
-                            // Channel groups
-                            if (TAG_GROUP.equals(tagName)) {
-                                String id = parser.getAttributeValue(null, ATT_ID);
-                                CharSequence groupName = parser.getAttributeValue(null, ATT_NAME);
-                                if (!TextUtils.isEmpty(id)) {
-                                    NotificationChannelGroup group
-                                            = new NotificationChannelGroup(id, groupName);
-                                    group.populateFromXml(parser);
-                                    r.groups.put(id, group);
-                                }
-                            }
-                            // Channels
-                            if (TAG_CHANNEL.equals(tagName)) {
-                                String id = parser.getAttributeValue(null, ATT_ID);
-                                String channelName = parser.getAttributeValue(null, ATT_NAME);
-                                int channelImportance = XmlUtils.readIntAttribute(
-                                        parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
-                                if (!TextUtils.isEmpty(id) && !TextUtils.isEmpty(channelName)) {
-                                    NotificationChannel channel = new NotificationChannel(id,
-                                            channelName, channelImportance);
-                                    if (forRestore) {
-                                        channel.populateFromXmlForRestore(parser, mContext);
-                                    } else {
-                                        channel.populateFromXml(parser);
-                                    }
-                                    r.channels.put(id, channel);
-                                }
-                            }
-                        }
-
-                        try {
-                            deleteDefaultChannelIfNeeded(r);
-                        } catch (NameNotFoundException e) {
-                            Slog.e(TAG, "deleteDefaultChannelIfNeeded - Exception: " + e);
-                        }
-                    }
-                }
-            }
-        }
-        throw new IllegalStateException("Failed to reach END_DOCUMENT");
-    }
-
-    private static String recordKey(String pkg, int uid) {
-        return pkg + "|" + uid;
-    }
-
-    private Record getRecord(String pkg, int uid) {
-        final String key = recordKey(pkg, uid);
-        synchronized (mRecords) {
-            return mRecords.get(key);
-        }
-    }
-
-    private Record getOrCreateRecord(String pkg, int uid) {
-        return getOrCreateRecord(pkg, uid,
-                DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY, DEFAULT_SHOW_BADGE);
-    }
-
-    private Record getOrCreateRecord(String pkg, int uid, int importance, int priority,
-            int visibility, boolean showBadge) {
-        final String key = recordKey(pkg, uid);
-        synchronized (mRecords) {
-            Record r = (uid == Record.UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg) : mRecords.get(
-                    key);
-            if (r == null) {
-                r = new Record();
-                r.pkg = pkg;
-                r.uid = uid;
-                r.importance = importance;
-                r.priority = priority;
-                r.visibility = visibility;
-                r.showBadge = showBadge;
-
-                try {
-                    createDefaultChannelIfNeeded(r);
-                } catch (NameNotFoundException e) {
-                    Slog.e(TAG, "createDefaultChannelIfNeeded - Exception: " + e);
-                }
-
-                if (r.uid == Record.UNKNOWN_UID) {
-                    mRestoredWithoutUids.put(pkg, r);
-                } else {
-                    mRecords.put(key, r);
-                }
-            }
-            return r;
-        }
-    }
-
-    private boolean shouldHaveDefaultChannel(Record r) throws NameNotFoundException {
-        final int userId = UserHandle.getUserId(r.uid);
-        final ApplicationInfo applicationInfo = mPm.getApplicationInfoAsUser(r.pkg, 0, userId);
-        if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
-            // O apps should not have the default channel.
-            return false;
-        }
-
-        // Otherwise, this app should have the default channel.
-        return true;
-    }
-
-    private void deleteDefaultChannelIfNeeded(Record r) throws NameNotFoundException {
-        if (!r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
-            // Not present
-            return;
-        }
-
-        if (shouldHaveDefaultChannel(r)) {
-            // Keep the default channel until upgraded.
-            return;
-        }
-
-        // Remove Default Channel.
-        r.channels.remove(NotificationChannel.DEFAULT_CHANNEL_ID);
-    }
-
-    private void createDefaultChannelIfNeeded(Record r) throws NameNotFoundException {
-        if (r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
-            r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID).setName(
-                    mContext.getString(R.string.default_notification_channel_label));
-            return;
-        }
-
-        if (!shouldHaveDefaultChannel(r)) {
-            // Keep the default channel until upgraded.
-            return;
-        }
-
-        // Create Default Channel
-        NotificationChannel channel;
-        channel = new NotificationChannel(
-                NotificationChannel.DEFAULT_CHANNEL_ID,
-                mContext.getString(R.string.default_notification_channel_label),
-                r.importance);
-        channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
-        channel.setLockscreenVisibility(r.visibility);
-        if (r.importance != NotificationManager.IMPORTANCE_UNSPECIFIED) {
-            channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
-        }
-        if (r.priority != DEFAULT_PRIORITY) {
-            channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
-        }
-        if (r.visibility != DEFAULT_VISIBILITY) {
-            channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
-        }
-        r.channels.put(channel.getId(), channel);
-    }
-
-    public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
-        out.startTag(null, TAG_RANKING);
-        out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
-
-        synchronized (mRecords) {
-            final int N = mRecords.size();
-            for (int i = 0; i < N; i++) {
-                final Record r = mRecords.valueAt(i);
-                //TODO: http://b/22388012
-                if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
-                    continue;
-                }
-                final boolean hasNonDefaultSettings =
-                        r.importance != DEFAULT_IMPORTANCE
-                            || r.priority != DEFAULT_PRIORITY
-                            || r.visibility != DEFAULT_VISIBILITY
-                            || r.showBadge != DEFAULT_SHOW_BADGE
-                            || r.lockedAppFields != DEFAULT_LOCKED_APP_FIELDS
-                            || r.channels.size() > 0
-                            || r.groups.size() > 0;
-                if (hasNonDefaultSettings) {
-                    out.startTag(null, TAG_PACKAGE);
-                    out.attribute(null, ATT_NAME, r.pkg);
-                    if (r.importance != DEFAULT_IMPORTANCE) {
-                        out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
-                    }
-                    if (r.priority != DEFAULT_PRIORITY) {
-                        out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority));
-                    }
-                    if (r.visibility != DEFAULT_VISIBILITY) {
-                        out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility));
-                    }
-                    out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge));
-                    out.attribute(null, ATT_APP_USER_LOCKED_FIELDS,
-                            Integer.toString(r.lockedAppFields));
-
-                    if (!forBackup) {
-                        out.attribute(null, ATT_UID, Integer.toString(r.uid));
-                    }
-
-                    for (NotificationChannelGroup group : r.groups.values()) {
-                        group.writeXml(out);
-                    }
-
-                    for (NotificationChannel channel : r.channels.values()) {
-                        if (forBackup) {
-                            if (!channel.isDeleted()) {
-                                channel.writeXmlForBackup(out, mContext);
-                            }
-                        } else {
-                            channel.writeXml(out);
-                        }
-                    }
-
-                    out.endTag(null, TAG_PACKAGE);
-                }
-            }
-        }
-        out.endTag(null, TAG_RANKING);
-    }
-
-    private void updateConfig() {
-        final int N = mSignalExtractors.length;
-        for (int i = 0; i < N; i++) {
-            mSignalExtractors[i].setConfig(this);
-        }
-        mRankingHandler.requestSort();
-    }
-
     public void sort(ArrayList<NotificationRecord> notificationList) {
         final int N = notificationList.size();
         // clear global sort keys
@@ -469,6 +106,8 @@
 
         synchronized (mProxyByGroupTmp) {
             // record individual ranking result and nominate proxies for each group
+            // Note: iteration is done backwards such that the index can be used as a sort key
+            // in a string compare below
             for (int i = N - 1; i >= 0; i--) {
                 final NotificationRecord record = notificationList.get(i);
                 record.setAuthoritativeRank(i);
@@ -501,7 +140,8 @@
 
                 boolean isGroupSummary = record.getNotification().isGroupSummary();
                 record.setGlobalSortKey(
-                        String.format("intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x",
+                        String.format("crtcl=0x%04x:intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x",
+                        record.getCriticality(),
                         record.isRecentlyIntrusive()
                                 && record.getImportance() > NotificationManager.IMPORTANCE_MIN
                                 ? '0' : '1',
@@ -521,562 +161,6 @@
         return Collections.binarySearch(notificationList, target, mFinalComparator);
     }
 
-    /**
-     * Gets importance.
-     */
-    @Override
-    public int getImportance(String packageName, int uid) {
-        return getOrCreateRecord(packageName, uid).importance;
-    }
-
-
-    /**
-     * Returns whether the importance of the corresponding notification is user-locked and shouldn't
-     * be adjusted by an assistant (via means of a blocking helper, for example). For the channel
-     * locking field, see {@link NotificationChannel#USER_LOCKED_IMPORTANCE}.
-     */
-    public boolean getIsAppImportanceLocked(String packageName, int uid) {
-        int userLockedFields = getOrCreateRecord(packageName, uid).lockedAppFields;
-        return (userLockedFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0;
-    }
-
-    @Override
-    public boolean canShowBadge(String packageName, int uid) {
-        return getOrCreateRecord(packageName, uid).showBadge;
-    }
-
-    @Override
-    public void setShowBadge(String packageName, int uid, boolean showBadge) {
-        getOrCreateRecord(packageName, uid).showBadge = showBadge;
-        updateConfig();
-    }
-
-    @Override
-    public boolean isGroupBlocked(String packageName, int uid, String groupId) {
-        if (groupId == null) {
-            return false;
-        }
-        Record r = getOrCreateRecord(packageName, uid);
-        NotificationChannelGroup group = r.groups.get(groupId);
-        if (group == null) {
-            return false;
-        }
-        return group.isBlocked();
-    }
-
-    int getPackagePriority(String pkg, int uid) {
-        return getOrCreateRecord(pkg, uid).priority;
-    }
-
-    int getPackageVisibility(String pkg, int uid) {
-        return getOrCreateRecord(pkg, uid).visibility;
-    }
-
-    @Override
-    public void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
-            boolean fromTargetApp) {
-        Preconditions.checkNotNull(pkg);
-        Preconditions.checkNotNull(group);
-        Preconditions.checkNotNull(group.getId());
-        Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName()));
-        Record r = getOrCreateRecord(pkg, uid);
-        if (r == null) {
-            throw new IllegalArgumentException("Invalid package");
-        }
-        final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
-        if (!group.equals(oldGroup)) {
-            // will log for new entries as well as name/description changes
-            MetricsLogger.action(getChannelGroupLog(group.getId(), pkg));
-        }
-        if (oldGroup != null) {
-            group.setChannels(oldGroup.getChannels());
-
-            if (fromTargetApp) {
-                group.setBlocked(oldGroup.isBlocked());
-            }
-        }
-        r.groups.put(group.getId(), group);
-    }
-
-    @Override
-    public void createNotificationChannel(String pkg, int uid, NotificationChannel channel,
-            boolean fromTargetApp, boolean hasDndAccess) {
-        Preconditions.checkNotNull(pkg);
-        Preconditions.checkNotNull(channel);
-        Preconditions.checkNotNull(channel.getId());
-        Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
-        Record r = getOrCreateRecord(pkg, uid);
-        if (r == null) {
-            throw new IllegalArgumentException("Invalid package");
-        }
-        if (channel.getGroup() != null && !r.groups.containsKey(channel.getGroup())) {
-            throw new IllegalArgumentException("NotificationChannelGroup doesn't exist");
-        }
-        if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId())) {
-            throw new IllegalArgumentException("Reserved id");
-        }
-        NotificationChannel existing = r.channels.get(channel.getId());
-        // Keep most of the existing settings
-        if (existing != null && fromTargetApp) {
-            if (existing.isDeleted()) {
-                existing.setDeleted(false);
-
-                // log a resurrected channel as if it's new again
-                MetricsLogger.action(getChannelLog(channel, pkg).setType(
-                        MetricsProto.MetricsEvent.TYPE_OPEN));
-            }
-
-            existing.setName(channel.getName().toString());
-            existing.setDescription(channel.getDescription());
-            existing.setBlockableSystem(channel.isBlockableSystem());
-            if (existing.getGroup() == null) {
-                existing.setGroup(channel.getGroup());
-            }
-
-            // Apps are allowed to downgrade channel importance if the user has not changed any
-            // fields on this channel yet.
-            if (existing.getUserLockedFields() == 0 &&
-                    channel.getImportance() < existing.getImportance()) {
-                existing.setImportance(channel.getImportance());
-            }
-
-            // system apps and dnd access apps can bypass dnd if the user hasn't changed any
-            // fields on the channel yet
-            if (existing.getUserLockedFields() == 0 && hasDndAccess) {
-                boolean bypassDnd = channel.canBypassDnd();
-                existing.setBypassDnd(bypassDnd);
-
-                if (bypassDnd != mAreChannelsBypassingDnd) {
-                    updateChannelsBypassingDnd();
-                }
-            }
-
-            updateConfig();
-            return;
-        }
-        if (channel.getImportance() < IMPORTANCE_NONE
-                || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
-            throw new IllegalArgumentException("Invalid importance level");
-        }
-
-        // Reset fields that apps aren't allowed to set.
-        if (fromTargetApp && !hasDndAccess) {
-            channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
-        }
-        if (fromTargetApp) {
-            channel.setLockscreenVisibility(r.visibility);
-        }
-        clearLockedFields(channel);
-        if (channel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
-            channel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
-        }
-        if (!r.showBadge) {
-            channel.setShowBadge(false);
-        }
-
-        r.channels.put(channel.getId(), channel);
-        if (channel.canBypassDnd() != mAreChannelsBypassingDnd) {
-            updateChannelsBypassingDnd();
-        }
-        MetricsLogger.action(getChannelLog(channel, pkg).setType(
-                MetricsProto.MetricsEvent.TYPE_OPEN));
-    }
-
-    void clearLockedFields(NotificationChannel channel) {
-        channel.unlockFields(channel.getUserLockedFields());
-    }
-
-    @Override
-    public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel,
-            boolean fromUser) {
-        Preconditions.checkNotNull(updatedChannel);
-        Preconditions.checkNotNull(updatedChannel.getId());
-        Record r = getOrCreateRecord(pkg, uid);
-        if (r == null) {
-            throw new IllegalArgumentException("Invalid package");
-        }
-        NotificationChannel channel = r.channels.get(updatedChannel.getId());
-        if (channel == null || channel.isDeleted()) {
-            throw new IllegalArgumentException("Channel does not exist");
-        }
-        if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
-            updatedChannel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
-        }
-        if (!fromUser) {
-            updatedChannel.unlockFields(updatedChannel.getUserLockedFields());
-        }
-        if (fromUser) {
-            updatedChannel.lockFields(channel.getUserLockedFields());
-            lockFieldsForUpdate(channel, updatedChannel);
-        }
-        r.channels.put(updatedChannel.getId(), updatedChannel);
-
-        if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(updatedChannel.getId())) {
-            // copy settings to app level so they are inherited by new channels
-            // when the app migrates
-            r.importance = updatedChannel.getImportance();
-            r.priority = updatedChannel.canBypassDnd()
-                    ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT;
-            r.visibility = updatedChannel.getLockscreenVisibility();
-            r.showBadge = updatedChannel.canShowBadge();
-        }
-
-        if (!channel.equals(updatedChannel)) {
-            // only log if there are real changes
-            MetricsLogger.action(getChannelLog(updatedChannel, pkg));
-        }
-
-        if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd) {
-            updateChannelsBypassingDnd();
-        }
-        updateConfig();
-    }
-
-    @Override
-    public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId,
-            boolean includeDeleted) {
-        Preconditions.checkNotNull(pkg);
-        Record r = getOrCreateRecord(pkg, uid);
-        if (r == null) {
-            return null;
-        }
-        if (channelId == null) {
-            channelId = NotificationChannel.DEFAULT_CHANNEL_ID;
-        }
-        final NotificationChannel nc = r.channels.get(channelId);
-        if (nc != null && (includeDeleted || !nc.isDeleted())) {
-            return nc;
-        }
-        return null;
-    }
-
-    @Override
-    public void deleteNotificationChannel(String pkg, int uid, String channelId) {
-        Record r = getRecord(pkg, uid);
-        if (r == null) {
-            return;
-        }
-        NotificationChannel channel = r.channels.get(channelId);
-        if (channel != null) {
-            channel.setDeleted(true);
-            LogMaker lm = getChannelLog(channel, pkg);
-            lm.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
-            MetricsLogger.action(lm);
-
-            if (mAreChannelsBypassingDnd && channel.canBypassDnd()) {
-                updateChannelsBypassingDnd();
-            }
-        }
-    }
-
-    @Override
-    @VisibleForTesting
-    public void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId) {
-        Preconditions.checkNotNull(pkg);
-        Preconditions.checkNotNull(channelId);
-        Record r = getRecord(pkg, uid);
-        if (r == null) {
-            return;
-        }
-        r.channels.remove(channelId);
-    }
-
-    @Override
-    public void permanentlyDeleteNotificationChannels(String pkg, int uid) {
-        Preconditions.checkNotNull(pkg);
-        Record r = getRecord(pkg, uid);
-        if (r == null) {
-            return;
-        }
-        int N = r.channels.size() - 1;
-        for (int i = N; i >= 0; i--) {
-            String key = r.channels.keyAt(i);
-            if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(key)) {
-                r.channels.remove(key);
-            }
-        }
-    }
-
-    public NotificationChannelGroup getNotificationChannelGroupWithChannels(String pkg,
-            int uid, String groupId, boolean includeDeleted) {
-        Preconditions.checkNotNull(pkg);
-        Record r = getRecord(pkg, uid);
-        if (r == null || groupId == null || !r.groups.containsKey(groupId)) {
-            return null;
-        }
-        NotificationChannelGroup group = r.groups.get(groupId).clone();
-        group.setChannels(new ArrayList<>());
-        int N = r.channels.size();
-        for (int i = 0; i < N; i++) {
-            final NotificationChannel nc = r.channels.valueAt(i);
-            if (includeDeleted || !nc.isDeleted()) {
-                if (groupId.equals(nc.getGroup())) {
-                    group.addChannel(nc);
-                }
-            }
-        }
-        return group;
-    }
-
-    public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
-            int uid) {
-        Preconditions.checkNotNull(pkg);
-        Record r = getRecord(pkg, uid);
-        if (r == null) {
-            return null;
-        }
-        return r.groups.get(groupId);
-    }
-
-    @Override
-    public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
-            int uid, boolean includeDeleted, boolean includeNonGrouped) {
-        Preconditions.checkNotNull(pkg);
-        Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
-        Record r = getRecord(pkg, uid);
-        if (r == null) {
-            return ParceledListSlice.emptyList();
-        }
-        NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null);
-        int N = r.channels.size();
-        for (int i = 0; i < N; i++) {
-            final NotificationChannel nc = r.channels.valueAt(i);
-            if (includeDeleted || !nc.isDeleted()) {
-                if (nc.getGroup() != null) {
-                    if (r.groups.get(nc.getGroup()) != null) {
-                        NotificationChannelGroup ncg = groups.get(nc.getGroup());
-                        if (ncg == null) {
-                            ncg = r.groups.get(nc.getGroup()).clone();
-                            ncg.setChannels(new ArrayList<>());
-                            groups.put(nc.getGroup(), ncg);
-
-                        }
-                        ncg.addChannel(nc);
-                    }
-                } else {
-                    nonGrouped.addChannel(nc);
-                }
-            }
-        }
-        if (includeNonGrouped && nonGrouped.getChannels().size() > 0) {
-            groups.put(null, nonGrouped);
-        }
-        return new ParceledListSlice<>(new ArrayList<>(groups.values()));
-    }
-
-    public List<NotificationChannel> deleteNotificationChannelGroup(String pkg, int uid,
-            String groupId) {
-        List<NotificationChannel> deletedChannels = new ArrayList<>();
-        Record r = getRecord(pkg, uid);
-        if (r == null || TextUtils.isEmpty(groupId)) {
-            return deletedChannels;
-        }
-
-        r.groups.remove(groupId);
-
-        int N = r.channels.size();
-        for (int i = 0; i < N; i++) {
-            final NotificationChannel nc = r.channels.valueAt(i);
-            if (groupId.equals(nc.getGroup())) {
-                nc.setDeleted(true);
-                deletedChannels.add(nc);
-            }
-        }
-        return deletedChannels;
-    }
-
-    @Override
-    public Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
-            int uid) {
-        Record r = getRecord(pkg, uid);
-        if (r == null) {
-            return new ArrayList<>();
-        }
-        return r.groups.values();
-    }
-
-    @Override
-    public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid,
-            boolean includeDeleted) {
-        Preconditions.checkNotNull(pkg);
-        List<NotificationChannel> channels = new ArrayList<>();
-        Record r = getRecord(pkg, uid);
-        if (r == null) {
-            return ParceledListSlice.emptyList();
-        }
-        int N = r.channels.size();
-        for (int i = 0; i < N; i++) {
-            final NotificationChannel nc = r.channels.valueAt(i);
-            if (includeDeleted || !nc.isDeleted()) {
-                channels.add(nc);
-            }
-        }
-        return new ParceledListSlice<>(channels);
-    }
-
-    /**
-     * True for pre-O apps that only have the default channel, or pre O apps that have no
-     * channels yet. This method will create the default channel for pre-O apps that don't have it.
-     * Should never be true for O+ targeting apps, but that's enforced on boot/when an app
-     * upgrades.
-     */
-    public boolean onlyHasDefaultChannel(String pkg, int uid) {
-        Record r = getOrCreateRecord(pkg, uid);
-        if (r.channels.size() == 1
-                && r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
-            return true;
-        }
-        return false;
-    }
-
-    public int getDeletedChannelCount(String pkg, int uid) {
-        Preconditions.checkNotNull(pkg);
-        int deletedCount = 0;
-        Record r = getRecord(pkg, uid);
-        if (r == null) {
-            return deletedCount;
-        }
-        int N = r.channels.size();
-        for (int i = 0; i < N; i++) {
-            final NotificationChannel nc = r.channels.valueAt(i);
-            if (nc.isDeleted()) {
-                deletedCount++;
-            }
-        }
-        return deletedCount;
-    }
-
-    public int getBlockedChannelCount(String pkg, int uid) {
-        Preconditions.checkNotNull(pkg);
-        int blockedCount = 0;
-        Record r = getRecord(pkg, uid);
-        if (r == null) {
-            return blockedCount;
-        }
-        int N = r.channels.size();
-        for (int i = 0; i < N; i++) {
-            final NotificationChannel nc = r.channels.valueAt(i);
-            if (!nc.isDeleted() && IMPORTANCE_NONE == nc.getImportance()) {
-                blockedCount++;
-            }
-        }
-        return blockedCount;
-    }
-
-    public int getBlockedAppCount(int userId) {
-        int count = 0;
-        synchronized (mRecords) {
-            final int N = mRecords.size();
-            for (int i = 0; i < N; i++) {
-                final Record r = mRecords.valueAt(i);
-                if (userId == UserHandle.getUserId(r.uid)
-                        && r.importance == IMPORTANCE_NONE) {
-                    count++;
-                }
-            }
-        }
-        return count;
-    }
-
-    public void updateChannelsBypassingDnd() {
-        synchronized (mRecords) {
-            final int numRecords = mRecords.size();
-            for (int recordIndex = 0; recordIndex < numRecords; recordIndex++) {
-                final Record r = mRecords.valueAt(recordIndex);
-                final int numChannels = r.channels.size();
-
-                for (int channelIndex = 0; channelIndex < numChannels; channelIndex++) {
-                    NotificationChannel channel = r.channels.valueAt(channelIndex);
-                    if (!channel.isDeleted() && channel.canBypassDnd()) {
-                        if (!mAreChannelsBypassingDnd) {
-                            mAreChannelsBypassingDnd = true;
-                            updateZenPolicy(true);
-                        }
-                        return;
-                    }
-                }
-            }
-        }
-
-        if (mAreChannelsBypassingDnd) {
-            mAreChannelsBypassingDnd = false;
-            updateZenPolicy(false);
-        }
-    }
-
-    public void updateZenPolicy(boolean areChannelsBypassingDnd) {
-        NotificationManager.Policy policy = mZenModeHelper.getNotificationPolicy();
-        mZenModeHelper.setNotificationPolicy(new NotificationManager.Policy(
-                policy.priorityCategories, policy.priorityCallSenders,
-                policy.priorityMessageSenders, policy.suppressedVisualEffects,
-                (areChannelsBypassingDnd ? NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND
-                        : 0)));
-    }
-
-    public boolean areChannelsBypassingDnd() {
-        return mAreChannelsBypassingDnd;
-    }
-
-    /**
-     * Sets importance.
-     */
-    @Override
-    public void setImportance(String pkgName, int uid, int importance) {
-        getOrCreateRecord(pkgName, uid).importance = importance;
-        updateConfig();
-    }
-
-    public void setEnabled(String packageName, int uid, boolean enabled) {
-        boolean wasEnabled = getImportance(packageName, uid) != IMPORTANCE_NONE;
-        if (wasEnabled == enabled) {
-            return;
-        }
-        setImportance(packageName, uid,
-                enabled ? DEFAULT_IMPORTANCE : IMPORTANCE_NONE);
-    }
-
-    /**
-     * Sets whether any notifications from the app, represented by the given {@code pkgName} and
-     * {@code uid}, have their importance locked by the user. Locked notifications don't get
-     * considered for sentiment adjustments (and thus never show a blocking helper).
-     */
-    public void setAppImportanceLocked(String packageName, int uid) {
-        Record record = getOrCreateRecord(packageName, uid);
-        if ((record.lockedAppFields & LockableAppFields.USER_LOCKED_IMPORTANCE) != 0) {
-            return;
-        }
-
-        record.lockedAppFields = record.lockedAppFields | LockableAppFields.USER_LOCKED_IMPORTANCE;
-        updateConfig();
-    }
-
-    @VisibleForTesting
-    void lockFieldsForUpdate(NotificationChannel original, NotificationChannel update) {
-        if (original.canBypassDnd() != update.canBypassDnd()) {
-            update.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
-        }
-        if (original.getLockscreenVisibility() != update.getLockscreenVisibility()) {
-            update.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
-        }
-        if (original.getImportance() != update.getImportance()) {
-            update.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
-        }
-        if (original.shouldShowLights() != update.shouldShowLights()
-                || original.getLightColor() != update.getLightColor()) {
-            update.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
-        }
-        if (!Objects.equals(original.getSound(), update.getSound())) {
-            update.lockFields(NotificationChannel.USER_LOCKED_SOUND);
-        }
-        if (!Arrays.equals(original.getVibrationPattern(), update.getVibrationPattern())
-                || original.shouldVibrate() != update.shouldVibrate()) {
-            update.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
-        }
-        if (original.canShowBadge() != update.canShowBadge()) {
-            update.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
-        }
-    }
-
     public void dump(PrintWriter pw, String prefix,
             @NonNull NotificationManagerService.DumpFilter filter) {
         final int N = mSignalExtractors.length;
@@ -1088,16 +172,6 @@
             pw.print("  ");
             pw.println(mSignalExtractors[i].getClass().getSimpleName());
         }
-
-        pw.print(prefix);
-        pw.println("per-package config:");
-
-        pw.println("Records:");
-        synchronized (mRecords) {
-            dumpRecords(pw, prefix, filter, mRecords);
-        }
-        pw.println("Restored without uid:");
-        dumpRecords(pw, prefix, filter, mRestoredWithoutUids);
     }
 
     public void dump(ProtoOutputStream proto,
@@ -1105,375 +179,7 @@
         final int N = mSignalExtractors.length;
         for (int i = 0; i < N; i++) {
             proto.write(RankingHelperProto.NOTIFICATION_SIGNAL_EXTRACTORS,
-                mSignalExtractors[i].getClass().getSimpleName());
-        }
-        synchronized (mRecords) {
-            dumpRecords(proto, RankingHelperProto.RECORDS, filter, mRecords);
-        }
-        dumpRecords(proto, RankingHelperProto.RECORDS_RESTORED_WITHOUT_UID, filter,
-            mRestoredWithoutUids);
-    }
-
-    private static void dumpRecords(ProtoOutputStream proto, long fieldId,
-            @NonNull NotificationManagerService.DumpFilter filter,
-            ArrayMap<String, Record> records) {
-        final int N = records.size();
-        long fToken;
-        for (int i = 0; i < N; i++) {
-            final Record r = records.valueAt(i);
-            if (filter.matches(r.pkg)) {
-                fToken = proto.start(fieldId);
-
-                proto.write(RecordProto.PACKAGE, r.pkg);
-                proto.write(RecordProto.UID, r.uid);
-                proto.write(RecordProto.IMPORTANCE, r.importance);
-                proto.write(RecordProto.PRIORITY, r.priority);
-                proto.write(RecordProto.VISIBILITY, r.visibility);
-                proto.write(RecordProto.SHOW_BADGE, r.showBadge);
-
-                for (NotificationChannel channel : r.channels.values()) {
-                    channel.writeToProto(proto, RecordProto.CHANNELS);
-                }
-                for (NotificationChannelGroup group : r.groups.values()) {
-                    group.writeToProto(proto, RecordProto.CHANNEL_GROUPS);
-                }
-
-                proto.end(fToken);
-            }
+                    mSignalExtractors[i].getClass().getSimpleName());
         }
     }
-
-    private static void dumpRecords(PrintWriter pw, String prefix,
-            @NonNull NotificationManagerService.DumpFilter filter,
-            ArrayMap<String, Record> records) {
-        final int N = records.size();
-        for (int i = 0; i < N; i++) {
-            final Record r = records.valueAt(i);
-            if (filter.matches(r.pkg)) {
-                pw.print(prefix);
-                pw.print("  AppSettings: ");
-                pw.print(r.pkg);
-                pw.print(" (");
-                pw.print(r.uid == Record.UNKNOWN_UID ? "UNKNOWN_UID" : Integer.toString(r.uid));
-                pw.print(')');
-                if (r.importance != DEFAULT_IMPORTANCE) {
-                    pw.print(" importance=");
-                    pw.print(Ranking.importanceToString(r.importance));
-                }
-                if (r.priority != DEFAULT_PRIORITY) {
-                    pw.print(" priority=");
-                    pw.print(Notification.priorityToString(r.priority));
-                }
-                if (r.visibility != DEFAULT_VISIBILITY) {
-                    pw.print(" visibility=");
-                    pw.print(Notification.visibilityToString(r.visibility));
-                }
-                pw.print(" showBadge=");
-                pw.print(Boolean.toString(r.showBadge));
-                pw.println();
-                for (NotificationChannel channel : r.channels.values()) {
-                    pw.print(prefix);
-                    pw.print("  ");
-                    pw.print("  ");
-                    pw.println(channel);
-                }
-                for (NotificationChannelGroup group : r.groups.values()) {
-                    pw.print(prefix);
-                    pw.print("  ");
-                    pw.print("  ");
-                    pw.println(group);
-                }
-            }
-        }
-    }
-
-    public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) {
-        JSONObject ranking = new JSONObject();
-        JSONArray records = new JSONArray();
-        try {
-            ranking.put("noUid", mRestoredWithoutUids.size());
-        } catch (JSONException e) {
-           // pass
-        }
-        synchronized (mRecords) {
-            final int N = mRecords.size();
-            for (int i = 0; i < N; i++) {
-                final Record r = mRecords.valueAt(i);
-                if (filter == null || filter.matches(r.pkg)) {
-                    JSONObject record = new JSONObject();
-                    try {
-                        record.put("userId", UserHandle.getUserId(r.uid));
-                        record.put("packageName", r.pkg);
-                        if (r.importance != DEFAULT_IMPORTANCE) {
-                            record.put("importance", Ranking.importanceToString(r.importance));
-                        }
-                        if (r.priority != DEFAULT_PRIORITY) {
-                            record.put("priority", Notification.priorityToString(r.priority));
-                        }
-                        if (r.visibility != DEFAULT_VISIBILITY) {
-                            record.put("visibility", Notification.visibilityToString(r.visibility));
-                        }
-                        if (r.showBadge != DEFAULT_SHOW_BADGE) {
-                            record.put("showBadge", Boolean.valueOf(r.showBadge));
-                        }
-                        JSONArray channels = new JSONArray();
-                        for (NotificationChannel channel : r.channels.values()) {
-                            channels.put(channel.toJson());
-                        }
-                        record.put("channels", channels);
-                        JSONArray groups = new JSONArray();
-                        for (NotificationChannelGroup group : r.groups.values()) {
-                            groups.put(group.toJson());
-                        }
-                        record.put("groups", groups);
-                    } catch (JSONException e) {
-                        // pass
-                    }
-                    records.put(record);
-                }
-            }
-        }
-        try {
-            ranking.put("records", records);
-        } catch (JSONException e) {
-            // pass
-        }
-        return ranking;
-    }
-
-    /**
-     * Dump only the ban information as structured JSON for the stats collector.
-     *
-     * This is intentionally redundant with {#link dumpJson} because the old
-     * scraper will expect this format.
-     *
-     * @param filter
-     * @return
-     */
-    public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter) {
-        JSONArray bans = new JSONArray();
-        Map<Integer, String> packageBans = getPackageBans();
-        for(Entry<Integer, String> ban : packageBans.entrySet()) {
-            final int userId = UserHandle.getUserId(ban.getKey());
-            final String packageName = ban.getValue();
-            if (filter == null || filter.matches(packageName)) {
-                JSONObject banJson = new JSONObject();
-                try {
-                    banJson.put("userId", userId);
-                    banJson.put("packageName", packageName);
-                } catch (JSONException e) {
-                    e.printStackTrace();
-                }
-                bans.put(banJson);
-            }
-        }
-        return bans;
-    }
-
-    public Map<Integer, String> getPackageBans() {
-        synchronized (mRecords) {
-            final int N = mRecords.size();
-            ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
-            for (int i = 0; i < N; i++) {
-                final Record r = mRecords.valueAt(i);
-                if (r.importance == IMPORTANCE_NONE) {
-                    packageBans.put(r.uid, r.pkg);
-                }
-            }
-
-            return packageBans;
-        }
-    }
-
-    /**
-     * Dump only the channel information as structured JSON for the stats collector.
-     *
-     * This is intentionally redundant with {#link dumpJson} because the old
-     * scraper will expect this format.
-     *
-     * @param filter
-     * @return
-     */
-    public JSONArray dumpChannelsJson(NotificationManagerService.DumpFilter filter) {
-        JSONArray channels = new JSONArray();
-        Map<String, Integer> packageChannels = getPackageChannels();
-        for(Entry<String, Integer> channelCount : packageChannels.entrySet()) {
-            final String packageName = channelCount.getKey();
-            if (filter == null || filter.matches(packageName)) {
-                JSONObject channelCountJson = new JSONObject();
-                try {
-                    channelCountJson.put("packageName", packageName);
-                    channelCountJson.put("channelCount", channelCount.getValue());
-                } catch (JSONException e) {
-                    e.printStackTrace();
-                }
-                channels.put(channelCountJson);
-            }
-        }
-        return channels;
-    }
-
-    private Map<String, Integer> getPackageChannels() {
-        ArrayMap<String, Integer> packageChannels = new ArrayMap<>();
-        synchronized (mRecords) {
-            for (int i = 0; i < mRecords.size(); i++) {
-                final Record r = mRecords.valueAt(i);
-                int channelCount = 0;
-                for (int j = 0; j < r.channels.size(); j++) {
-                    if (!r.channels.valueAt(j).isDeleted()) {
-                        channelCount++;
-                    }
-                }
-                packageChannels.put(r.pkg, channelCount);
-            }
-        }
-        return packageChannels;
-    }
-
-    public void onUserRemoved(int userId) {
-        synchronized (mRecords) {
-            int N = mRecords.size();
-            for (int i = N - 1; i >= 0 ; i--) {
-                Record record = mRecords.valueAt(i);
-                if (UserHandle.getUserId(record.uid) == userId) {
-                    mRecords.removeAt(i);
-                }
-            }
-        }
-    }
-
-    protected void onLocaleChanged(Context context, int userId) {
-        synchronized (mRecords) {
-            int N = mRecords.size();
-            for (int i = 0; i < N; i++) {
-                Record record = mRecords.valueAt(i);
-                if (UserHandle.getUserId(record.uid) == userId) {
-                    if (record.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
-                        record.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID).setName(
-                                context.getResources().getString(
-                                        R.string.default_notification_channel_label));
-                    }
-                }
-            }
-        }
-    }
-
-    public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList,
-            int[] uidList) {
-        if (pkgList == null || pkgList.length == 0) {
-            return; // nothing to do
-        }
-        boolean updated = false;
-        if (removingPackage) {
-            // Remove notification settings for uninstalled package
-            int size = Math.min(pkgList.length, uidList.length);
-            for (int i = 0; i < size; i++) {
-                final String pkg = pkgList[i];
-                final int uid = uidList[i];
-                synchronized (mRecords) {
-                    mRecords.remove(recordKey(pkg, uid));
-                }
-                mRestoredWithoutUids.remove(pkg);
-                updated = true;
-            }
-        } else {
-            for (String pkg : pkgList) {
-                // Package install
-                final Record r = mRestoredWithoutUids.get(pkg);
-                if (r != null) {
-                    try {
-                        r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId);
-                        mRestoredWithoutUids.remove(pkg);
-                        synchronized (mRecords) {
-                            mRecords.put(recordKey(r.pkg, r.uid), r);
-                        }
-                        updated = true;
-                    } catch (NameNotFoundException e) {
-                        // noop
-                    }
-                }
-                // Package upgrade
-                try {
-                    Record fullRecord = getRecord(pkg,
-                            mPm.getPackageUidAsUser(pkg, changeUserId));
-                    if (fullRecord != null) {
-                        createDefaultChannelIfNeeded(fullRecord);
-                        deleteDefaultChannelIfNeeded(fullRecord);
-                    }
-                } catch (NameNotFoundException e) {}
-            }
-        }
-
-        if (updated) {
-            updateConfig();
-        }
-    }
-
-    private LogMaker getChannelLog(NotificationChannel channel, String pkg) {
-        return new LogMaker(MetricsProto.MetricsEvent.ACTION_NOTIFICATION_CHANNEL)
-                .setType(MetricsProto.MetricsEvent.TYPE_UPDATE)
-                .setPackageName(pkg)
-                .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID,
-                        channel.getId())
-                .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE,
-                        channel.getImportance());
-    }
-
-    private LogMaker getChannelGroupLog(String groupId, String pkg) {
-        return new LogMaker(MetricsProto.MetricsEvent.ACTION_NOTIFICATION_CHANNEL_GROUP)
-                .setType(MetricsProto.MetricsEvent.TYPE_UPDATE)
-                .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CHANNEL_GROUP_ID,
-                        groupId)
-                .setPackageName(pkg);
-    }
-
-    public void updateBadgingEnabled() {
-        if (mBadgingEnabled == null) {
-            mBadgingEnabled = new SparseBooleanArray();
-        }
-        boolean changed = false;
-        // update the cached values
-        for (int index = 0; index < mBadgingEnabled.size(); index++) {
-            int userId = mBadgingEnabled.keyAt(index);
-            final boolean oldValue = mBadgingEnabled.get(userId);
-            final boolean newValue = Secure.getIntForUser(mContext.getContentResolver(),
-                    Secure.NOTIFICATION_BADGING,
-                    DEFAULT_SHOW_BADGE ? 1 : 0, userId) != 0;
-            mBadgingEnabled.put(userId, newValue);
-            changed |= oldValue != newValue;
-        }
-        if (changed) {
-            updateConfig();
-        }
-    }
-
-    public boolean badgingEnabled(UserHandle userHandle) {
-        int userId = userHandle.getIdentifier();
-        if (userId == UserHandle.USER_ALL) {
-            return false;
-        }
-        if (mBadgingEnabled.indexOfKey(userId) < 0) {
-            mBadgingEnabled.put(userId,
-                    Secure.getIntForUser(mContext.getContentResolver(),
-                            Secure.NOTIFICATION_BADGING,
-                            DEFAULT_SHOW_BADGE ? 1 : 0, userId) != 0);
-        }
-        return mBadgingEnabled.get(userId, DEFAULT_SHOW_BADGE);
-    }
-
-
-    private static class Record {
-        static int UNKNOWN_UID = UserHandle.USER_NULL;
-
-        String pkg;
-        int uid = UNKNOWN_UID;
-        int importance = DEFAULT_IMPORTANCE;
-        int priority = DEFAULT_PRIORITY;
-        int visibility = DEFAULT_VISIBILITY;
-        boolean showBadge = DEFAULT_SHOW_BADGE;
-        int lockedAppFields = DEFAULT_LOCKED_APP_FIELDS;
-
-        ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
-        Map<String, NotificationChannelGroup> groups = new ConcurrentHashMap<>();
-   }
 }
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index 6760875..b016faf 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -36,7 +36,8 @@
 
 public class ZenLog {
     private static final String TAG = "ZenLog";
-    private static final boolean DEBUG = Build.IS_DEBUGGABLE;
+    // the ZenLog is *very* verbose, so be careful about setting this to true
+    private static final boolean DEBUG = false;
 
     private static final int SIZE = Build.IS_DEBUGGABLE ? 100 : 20;
 
diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java
index 63c0baf..b080a73 100644
--- a/services/core/java/com/android/server/notification/ZenModeConditions.java
+++ b/services/core/java/com/android/server/notification/ZenModeConditions.java
@@ -19,7 +19,6 @@
 import android.content.ComponentName;
 import android.net.Uri;
 import android.service.notification.Condition;
-import android.service.notification.IConditionListener;
 import android.service.notification.IConditionProvider;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.ZenRule;
@@ -27,6 +26,8 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.PrintWriter;
 import java.util.Objects;
 
@@ -36,7 +37,9 @@
 
     private final ZenModeHelper mHelper;
     private final ConditionProviders mConditionProviders;
-    private final ArrayMap<Uri, ComponentName> mSubscriptions = new ArrayMap<>();
+
+    @VisibleForTesting
+    protected final ArrayMap<Uri, ComponentName> mSubscriptions = new ArrayMap<>();
 
     private boolean mFirstEvaluation = true;
 
@@ -59,7 +62,8 @@
         pw.print(prefix); pw.print("mSubscriptions="); pw.println(mSubscriptions);
     }
 
-    public void evaluateConfig(ZenModeConfig config, boolean processSubscriptions) {
+    public void evaluateConfig(ZenModeConfig config, ComponentName trigger,
+            boolean processSubscriptions) {
         if (config == null) return;
         if (config.manualRule != null && config.manualRule.condition != null
                 && !config.manualRule.isTrueOrUnknown()) {
@@ -67,9 +71,9 @@
             config.manualRule = null;
         }
         final ArraySet<Uri> current = new ArraySet<>();
-        evaluateRule(config.manualRule, current, processSubscriptions);
+        evaluateRule(config.manualRule, current, null, processSubscriptions);
         for (ZenRule automaticRule : config.automaticRules.values()) {
-            evaluateRule(automaticRule, current, processSubscriptions);
+            evaluateRule(automaticRule, current, trigger, processSubscriptions);
             updateSnoozing(automaticRule);
         }
 
@@ -102,7 +106,7 @@
     @Override
     public void onServiceAdded(ComponentName component) {
         if (DEBUG) Log.d(TAG, "onServiceAdded " + component);
-        mHelper.setConfig(mHelper.getConfig(), "zmc.onServiceAdded");
+        mHelper.setConfig(mHelper.getConfig(), component, "zmc.onServiceAdded");
     }
 
     @Override
@@ -110,17 +114,22 @@
         if (DEBUG) Log.d(TAG, "onConditionChanged " + id + " " + condition);
         ZenModeConfig config = mHelper.getConfig();
         if (config == null) return;
+        ComponentName trigger = null;
         boolean updated = updateCondition(id, condition, config.manualRule);
         for (ZenRule automaticRule : config.automaticRules.values()) {
             updated |= updateCondition(id, condition, automaticRule);
             updated |= updateSnoozing(automaticRule);
+            if (updated) {
+                trigger = automaticRule.component;
+            }
         }
         if (updated) {
-            mHelper.setConfig(config, "conditionChanged");
+            mHelper.setConfig(config, trigger, "conditionChanged");
         }
     }
 
-    private void evaluateRule(ZenRule rule, ArraySet<Uri> current, boolean processSubscriptions) {
+    private void evaluateRule(ZenRule rule, ArraySet<Uri> current, ComponentName trigger,
+            boolean processSubscriptions) {
         if (rule == null || rule.conditionId == null) return;
         final Uri id = rule.conditionId;
         boolean isSystemCondition = false;
@@ -146,7 +155,9 @@
         if (current != null) {
             current.add(id);
         }
-        if (processSubscriptions) {
+        if (processSubscriptions && ((trigger != null && trigger.equals(rule.component))
+                || isSystemCondition)) {
+            if (DEBUG) Log.d(TAG, "Subscribing to " + rule.component);
             if (mConditionProviders.subscribeIfNecessary(rule.component, rule.conditionId)) {
                 synchronized (mSubscriptions) {
                     mSubscriptions.put(rule.conditionId, rule.component);
diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java
index 71cee05..28cee7a 100644
--- a/services/core/java/com/android/server/notification/ZenModeFiltering.java
+++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java
@@ -117,7 +117,8 @@
     }
 
     public boolean shouldIntercept(int zen, ZenModeConfig config, NotificationRecord record) {
-        if (zen == ZEN_MODE_OFF) {
+        // Zen mode is ignored for critical notifications.
+        if (zen == ZEN_MODE_OFF || isCritical(record)) {
             return false;
         }
         // Make an exception to policy for the notification saying that policy has changed
@@ -207,6 +208,19 @@
         }
     }
 
+    /**
+     * Check if the notification is too critical to be suppressed.
+     *
+     * @param record the record to test for criticality
+     * @return {@code true} if notification is considered critical
+     *
+     * @see CriticalNotificationExtractor for criteria
+     */
+    private boolean isCritical(NotificationRecord record) {
+        // 0 is the most critical
+        return record.getCriticality() < CriticalNotificationExtractor.NORMAL;
+    }
+
     private static boolean shouldInterceptAudience(int source, NotificationRecord record) {
         if (!audienceMatches(source, record.getContactAffinity())) {
             ZenLog.traceIntercepted(record, "!audienceMatches");
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 24fd331..6ac72d3 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -102,7 +102,7 @@
     private final ZenModeFiltering mFiltering;
     protected final RingerModeDelegate mRingerModeDelegate = new
             RingerModeDelegate();
-    private final ZenModeConditions mConditions;
+    @VisibleForTesting protected final ZenModeConditions mConditions;
     private final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
     private final Metrics mMetrics = new Metrics();
     private final ConditionProviders.Config mServiceConfig;
@@ -225,7 +225,7 @@
             config.user = user;
         }
         synchronized (mConfig) {
-            setConfigLocked(config, reason);
+            setConfigLocked(config, null, reason);
         }
         cleanUpZenRules();
     }
@@ -312,7 +312,7 @@
             ZenRule rule = new ZenRule();
             populateZenRule(automaticZenRule, rule, true);
             newConfig.automaticRules.put(rule.id, rule);
-            if (setConfigLocked(newConfig, reason, true)) {
+            if (setConfigLocked(newConfig, reason, rule.component, true)) {
                 return rule.id;
             } else {
                 throw new AndroidRuntimeException("Could not create rule");
@@ -342,7 +342,7 @@
             }
             populateZenRule(automaticZenRule, rule, false);
             newConfig.automaticRules.put(ruleId, rule);
-            return setConfigLocked(newConfig, reason, true);
+            return setConfigLocked(newConfig, reason, rule.component, true);
         }
     }
 
@@ -360,7 +360,7 @@
                 throw new SecurityException(
                         "Cannot delete rules not owned by your condition provider");
             }
-            return setConfigLocked(newConfig, reason, true);
+            return setConfigLocked(newConfig, reason, null, true);
         }
     }
 
@@ -376,7 +376,7 @@
                     newConfig.automaticRules.removeAt(i);
                 }
             }
-            return setConfigLocked(newConfig, reason, true);
+            return setConfigLocked(newConfig, reason, null, true);
         }
     }
 
@@ -508,8 +508,8 @@
 
     public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
         setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
-        Settings.Global.putInt(mContext.getContentResolver(), Global.SHOW_ZEN_SETTINGS_SUGGESTION,
-                0);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0);
     }
 
     private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
@@ -537,7 +537,7 @@
                 newRule.enabler = caller;
                 newConfig.manualRule = newRule;
             }
-            setConfigLocked(newConfig, reason, setRingerMode);
+            setConfigLocked(newConfig, reason, null, setRingerMode);
         }
     }
 
@@ -612,7 +612,11 @@
                 config.manualRule = null;  // don't restore the manual rule
             }
 
-            boolean resetToDefaultRules = true;
+            // booleans to determine whether to reset the rules to the default rules
+            boolean allRulesDisabled = true;
+            boolean hasDefaultRules = config.automaticRules.containsAll(
+                    ZenModeConfig.DEFAULT_RULE_IDS);
+
             long time = System.currentTimeMillis();
             if (config.automaticRules != null && config.automaticRules.size() > 0) {
                 for (ZenRule automaticRule : config.automaticRules.values()) {
@@ -622,29 +626,32 @@
                         automaticRule.condition = null;
                         automaticRule.creationTime = time;
                     }
-                    resetToDefaultRules &= !automaticRule.enabled;
+
+                    allRulesDisabled &= !automaticRule.enabled;
                 }
             }
 
-            if (config.version < ZenModeConfig.XML_VERSION || forRestore) {
-                Settings.Global.putInt(mContext.getContentResolver(),
-                        Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
+            if (!hasDefaultRules && allRulesDisabled
+                    && (forRestore || config.version < ZenModeConfig.XML_VERSION)) {
+                // reset zen automatic rules to default on restore or upgrade if:
+                // - doesn't already have default rules and
+                // - all previous automatic rules were disabled
+                config.automaticRules = new ArrayMap<>();
+                appendDefaultRules(config);
+                reason += ", reset to default rules";
+            }
 
-                // resets zen automatic rules to default
-                // if all prev auto rules were disabled on update
-                if (resetToDefaultRules) {
-                    config.automaticRules = new ArrayMap<>();
-                    appendDefaultRules(config);
-                    reason += ", reset to default rules";
-                }
+            if (config.version < ZenModeConfig.XML_VERSION) {
+                Settings.Secure.putInt(mContext.getContentResolver(),
+                        Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
             } else {
                 // devices not restoring/upgrading already have updated zen settings
-                Settings.Global.putInt(mContext.getContentResolver(),
-                        Global.ZEN_SETTINGS_UPDATED, 1);
+                Settings.Secure.putInt(mContext.getContentResolver(),
+                        Settings.Secure.ZEN_SETTINGS_UPDATED, 1);
             }
             if (DEBUG) Log.d(TAG, reason);
             synchronized (mConfig) {
-                setConfigLocked(config, reason);
+                setConfigLocked(config, null, reason);
             }
         }
     }
@@ -673,7 +680,7 @@
         synchronized (mConfig) {
             final ZenModeConfig newConfig = mConfig.copy();
             newConfig.applyNotificationPolicy(policy);
-            setConfigLocked(newConfig, "setNotificationPolicy");
+            setConfigLocked(newConfig, null, "setNotificationPolicy");
         }
     }
 
@@ -697,7 +704,7 @@
                     }
                 }
             }
-            setConfigLocked(newConfig, "cleanUpZenRules");
+            setConfigLocked(newConfig, null, "cleanUpZenRules");
         }
     }
 
@@ -710,17 +717,19 @@
         }
     }
 
-    public boolean setConfigLocked(ZenModeConfig config, String reason) {
-        return setConfigLocked(config, reason, true /*setRingerMode*/);
+    public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent,
+            String reason) {
+        return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/);
     }
 
-    public void setConfig(ZenModeConfig config, String reason) {
+    public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) {
         synchronized (mConfig) {
-            setConfigLocked(config, reason);
+            setConfigLocked(config, triggeringComponent, reason);
         }
     }
 
-    private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) {
+    private boolean setConfigLocked(ZenModeConfig config, String reason,
+            ComponentName triggeringComponent, boolean setRingerMode) {
         final long identity = Binder.clearCallingIdentity();
         try {
             if (config == null || !config.isValid()) {
@@ -733,7 +742,8 @@
                 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
                 return true;
             }
-            mConditions.evaluateConfig(config, false /*processSubscriptions*/);  // may modify config
+            // may modify config
+            mConditions.evaluateConfig(config, null, false /*processSubscriptions*/);
             mConfigs.put(config.user, config);
             if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
             ZenLog.traceConfig(reason, mConfig, config);
@@ -746,7 +756,7 @@
                 dispatchOnPolicyChanged();
             }
             mConfig = config;
-            mHandler.postApplyConfig(config, reason, setRingerMode);
+            mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode);
             return true;
         } catch (SecurityException e) {
             Log.wtf(TAG, "Invalid rule in config", e);
@@ -756,13 +766,14 @@
         }
     }
 
-    private void applyConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
+    private void applyConfig(ZenModeConfig config, String reason,
+            ComponentName triggeringComponent, boolean setRingerMode) {
         final String val = Integer.toString(config.hashCode());
         Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
         if (!evaluateZenMode(reason, setRingerMode)) {
             applyRestrictions();  // evaluateZenMode will also apply restrictions if changed
         }
-        mConditions.evaluateConfig(config, true /*processSubscriptions*/);
+        mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);
     }
 
     private int getZenModeSetting() {
@@ -820,10 +831,10 @@
                 if (automaticRule.isAutomaticActive()) {
                     if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
                         // automatic rule triggered dnd and user hasn't seen update dnd dialog
-                        if (Settings.Global.getInt(mContext.getContentResolver(),
-                                Global.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) {
-                            Settings.Global.putInt(mContext.getContentResolver(),
-                                    Global.SHOW_ZEN_SETTINGS_SUGGESTION, 1);
+                        if (Settings.Secure.getInt(mContext.getContentResolver(),
+                                Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) {
+                            Settings.Secure.putInt(mContext.getContentResolver(),
+                                    Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 1);
                         }
                         zen = automaticRule.zenMode;
                     }
@@ -1188,13 +1199,20 @@
                 && zen != Global.ZEN_MODE_OFF
                 && !isWatch
                 && Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0;
+                Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
+                && Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
+
+        if (isWatch) {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
+        }
 
         if (showNotification) {
             mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
                     createZenUpgradeNotification());
-            Settings.Global.putInt(mContext.getContentResolver(),
-                    Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
         }
     }
 
@@ -1263,13 +1281,16 @@
 
         private final class ConfigMessageData {
             public final ZenModeConfig config;
+            public ComponentName triggeringComponent;
             public final String reason;
             public final boolean setRingerMode;
 
-            ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode) {
+            ConfigMessageData(ZenModeConfig config, String reason,
+                    ComponentName triggeringComponent, boolean setRingerMode) {
                 this.config = config;
                 this.reason = reason;
                 this.setRingerMode = setRingerMode;
+                this.triggeringComponent = triggeringComponent;
             }
         }
 
@@ -1289,9 +1310,10 @@
             sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
         }
 
-        private void postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
+        private void postApplyConfig(ZenModeConfig config, String reason,
+                ComponentName triggeringComponent, boolean setRingerMode) {
             sendMessage(obtainMessage(MSG_APPLY_CONFIG,
-                    new ConfigMessageData(config, reason, setRingerMode)));
+                    new ConfigMessageData(config, reason, triggeringComponent, setRingerMode)));
         }
 
         @Override
@@ -1306,7 +1328,7 @@
                 case MSG_APPLY_CONFIG:
                     ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
                     applyConfig(applyConfigData.config, applyConfigData.reason,
-                            applyConfigData.setRingerMode);
+                            applyConfigData.triggeringComponent, applyConfigData.setRingerMode);
             }
         }
     }
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index f082271..c738701 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -22,11 +22,14 @@
 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
 import static android.content.Intent.ACTION_USER_ADDED;
 import static android.content.Intent.ACTION_USER_REMOVED;
+import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.SIGNATURE_MATCH;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityThread;
 import android.app.IActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -34,6 +37,7 @@
 import android.content.IntentFilter;
 import android.content.om.IOverlayManager;
 import android.content.om.OverlayInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManagerInternal;
@@ -269,13 +273,30 @@
 
     @Override
     public void onBootPhase(int phase) {
-        if (phase == PHASE_SYSTEM_SERVICES_READY) {
+        if (phase == PHASE_SYSTEM_SERVICES_READY && mInitCompleteSignal != null) {
             ConcurrentUtils.waitForFutureNoInterrupt(mInitCompleteSignal,
                     "Wait for OverlayManagerService init");
             mInitCompleteSignal = null;
         }
     }
 
+    public void updateSystemUiContext() {
+        if (mInitCompleteSignal != null) {
+            ConcurrentUtils.waitForFutureNoInterrupt(mInitCompleteSignal,
+                    "Wait for OverlayManagerService init");
+            mInitCompleteSignal = null;
+        }
+
+        final ApplicationInfo ai;
+        try {
+            ai = mPackageManager.mPackageManager.getApplicationInfo("android",
+                    GET_SHARED_LIBRARY_FILES, UserHandle.USER_SYSTEM);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+        ActivityThread.currentActivityThread().handleSystemApplicationInfoChanged(ai);
+    }
+
     private void initIfNeeded() {
         final UserManager um = getContext().getSystemService(UserManager.class);
         final List<UserInfo> users = um.getUsers(true /*excludeDying*/);
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 0774672..d6ab5f7 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -489,7 +489,7 @@
         PinnerService pinnerService = LocalServices.getService(PinnerService.class);
         if (pinnerService != null) {
             Log.i(TAG, "Pinning optimized code " + updatedPackages);
-            pinnerService.update(updatedPackages);
+            pinnerService.update(updatedPackages, false /* force */);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
new file mode 100644
index 0000000..7d762d9
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -0,0 +1,1878 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
+import static android.content.pm.PackageManagerInternal.PACKAGE_SETUP_WIZARD;
+
+import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
+import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
+import static com.android.server.pm.PackageManagerService.fixProcessName;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.AuxiliaryResolveInfo;
+import android.content.pm.InstantAppResolveInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.ActivityIntentInfo;
+import android.content.pm.PackageParser.ServiceIntentInfo;
+import android.content.pm.PackageUserState;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.LogPrinter;
+import android.util.Pair;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.IntentResolver;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/** Resolves all Android component types [activities, services, providers and receivers]. */
+public class ComponentResolver {
+    private static final String TAG = "PackageManager";
+    private static final boolean DEBUG_FILTERS = false;
+    private static final boolean DEBUG_SHOW_INFO = false;
+
+    /**
+     * The set of all protected actions [i.e. those actions for which a high priority
+     * intent filter is disallowed].
+     */
+    private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>();
+    static {
+        PROTECTED_ACTIONS.add(Intent.ACTION_SEND);
+        PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO);
+        PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE);
+        PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
+    }
+
+    static final Comparator<ResolveInfo> RESOLVE_PRIORITY_SORTER = (r1, r2) -> {
+        int v1 = r1.priority;
+        int v2 = r2.priority;
+        //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
+        if (v1 != v2) {
+            return (v1 > v2) ? -1 : 1;
+        }
+        v1 = r1.preferredOrder;
+        v2 = r2.preferredOrder;
+        if (v1 != v2) {
+            return (v1 > v2) ? -1 : 1;
+        }
+        if (r1.isDefault != r2.isDefault) {
+            return r1.isDefault ? -1 : 1;
+        }
+        v1 = r1.match;
+        v2 = r2.match;
+        //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
+        if (v1 != v2) {
+            return (v1 > v2) ? -1 : 1;
+        }
+        if (r1.system != r2.system) {
+            return r1.system ? -1 : 1;
+        }
+        if (r1.activityInfo != null) {
+            return r1.activityInfo.packageName.compareTo(r2.activityInfo.packageName);
+        }
+        if (r1.serviceInfo != null) {
+            return r1.serviceInfo.packageName.compareTo(r2.serviceInfo.packageName);
+        }
+        if (r1.providerInfo != null) {
+            return r1.providerInfo.packageName.compareTo(r2.providerInfo.packageName);
+        }
+        return 0;
+    };
+
+    private static UserManagerService sUserManager;
+    private static PackageManagerInternal sPackageManagerInternal;
+
+    /**
+     * Locking within package manager is going to get worse before it gets better. Currently,
+     * we need to share the {@link PackageManagerService} lock to prevent deadlocks. This occurs
+     * because in order to safely query the resolvers, we need to obtain this lock. However,
+     * during resolution, we call into the {@link PackageManagerService}. This is _not_ to
+     * operate on data controlled by the service proper, but, to check the state of package
+     * settings [contained in a {@link Settings} object]. However, the {@link Settings} object
+     * happens to be protected by the main {@link PackageManagerService} lock.
+     * <p>
+     * There are a couple potential solutions.
+     * <ol>
+     * <li>Split all of our locks into reader/writer locks. This would allow multiple,
+     * simultaneous read operations and means we don't have to be as cautious about lock
+     * layering. Only when we want to perform a write operation will we ever be in a
+     * position to deadlock the system.</li>
+     * <li>Use the same lock across all classes within the {@code com.android.server.pm}
+     * package. By unifying the lock object, we remove any potential lock layering issues
+     * within the package manager. However, we already have a sense that this lock is
+     * heavily contended and merely adding more dependencies on it will have further
+     * impact.</li>
+     * <li>Implement proper lock ordering within the package manager. By defining the
+     * relative layer of the component [eg. {@link PackageManagerService} is at the top.
+     * Somewhere in the middle would be {@link ComponentResolver}. At the very bottom
+     * would be {@link Settings}.] The ordering would allow higher layers to hold their
+     * lock while calling down. Lower layers must relinquish their lock before calling up.
+     * Since {@link Settings} would live at the lowest layer, the {@link ComponentResolver}
+     * would be able to hold its lock while checking the package setting state.</li>
+     * </ol>
+     */
+    private final Object mLock;
+
+    /** All available activities, for your resolving pleasure. */
+    @GuardedBy("mLock")
+    private final ActivityIntentResolver mActivities = new ActivityIntentResolver();
+
+    /** All available providers, for your resolving pleasure. */
+    @GuardedBy("mLock")
+    private final ProviderIntentResolver mProviders = new ProviderIntentResolver();
+
+    /** All available receivers, for your resolving pleasure. */
+    @GuardedBy("mLock")
+    private final ActivityIntentResolver mReceivers = new ActivityIntentResolver();
+
+    /** All available services, for your resolving pleasure. */
+    @GuardedBy("mLock")
+    private final ServiceIntentResolver mServices = new ServiceIntentResolver();
+
+    /** Mapping from provider authority [first directory in content URI codePath) to provider. */
+    @GuardedBy("mLock")
+    private final ArrayMap<String, PackageParser.Provider> mProvidersByAuthority = new ArrayMap<>();
+
+    /** Whether or not processing protected filters should be deferred. */
+    private boolean mDeferProtectedFilters = true;
+
+    /**
+     * Tracks high priority intent filters for protected actions. During boot, certain
+     * filter actions are protected and should never be allowed to have a high priority
+     * intent filter for them. However, there is one, and only one exception -- the
+     * setup wizard. It must be able to define a high priority intent filter for these
+     * actions to ensure there are no escapes from the wizard. We need to delay processing
+     * of these during boot as we need to inspect at all of the intent filters on the
+     * /system partition in order to know which component is the setup wizard. This can
+     * only ever be non-empty if {@link #mDeferProtectedFilters} is {@code true}.
+     */
+    private List<PackageParser.ActivityIntentInfo> mProtectedFilters;
+
+    ComponentResolver(UserManagerService userManager,
+            PackageManagerInternal packageManagerInternal,
+            Object lock) {
+        sPackageManagerInternal = packageManagerInternal;
+        sUserManager = userManager;
+        mLock = lock;
+    }
+
+    /** Returns the given activity */
+    PackageParser.Activity getActivity(ComponentName component) {
+        synchronized (mLock) {
+            return mActivities.mActivities.get(component);
+        }
+    }
+
+    /** Returns the given provider */
+    PackageParser.Provider getProvider(ComponentName component) {
+        synchronized (mLock) {
+            return mProviders.mProviders.get(component);
+        }
+    }
+
+    /** Returns the given receiver */
+    PackageParser.Activity getReceiver(ComponentName component) {
+        synchronized (mLock) {
+            return mReceivers.mActivities.get(component);
+        }
+    }
+
+    /** Returns the given service */
+    PackageParser.Service getService(ComponentName component) {
+        synchronized (mLock) {
+            return mServices.mServices.get(component);
+        }
+    }
+
+    List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags, int userId) {
+        synchronized (mLock) {
+            return mActivities.queryIntent(intent, resolvedType, flags, userId);
+        }
+    }
+
+    List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
+            List<PackageParser.Activity> activities, int userId) {
+        synchronized (mLock) {
+            return mActivities.queryIntentForPackage(
+                    intent, resolvedType, flags, activities, userId);
+        }
+    }
+
+    List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags, int userId) {
+        synchronized (mLock) {
+            return mProviders.queryIntent(intent, resolvedType, flags, userId);
+        }
+    }
+
+    List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags,
+            List<PackageParser.Provider> providers, int userId) {
+        synchronized (mLock) {
+            return mProviders.queryIntentForPackage(intent, resolvedType, flags, providers, userId);
+        }
+    }
+
+    List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, int flags,
+            int userId) {
+        if (!sUserManager.exists(userId)) {
+            return null;
+        }
+        List<ProviderInfo> providerList = null;
+        synchronized (mLock) {
+            for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) {
+                final PackageParser.Provider p = mProviders.mProviders.valueAt(i);
+                final PackageSetting ps = (PackageSetting) p.owner.mExtras;
+                if (ps == null) {
+                    continue;
+                }
+                if (p.info.authority == null) {
+                    continue;
+                }
+                if (processName != null && (!p.info.processName.equals(processName)
+                        || !UserHandle.isSameApp(p.info.applicationInfo.uid, uid))) {
+                    continue;
+                }
+                // See PM.queryContentProviders()'s javadoc for why we have the metaData parameter.
+                if (metaDataKey != null
+                        && (p.metaData == null || !p.metaData.containsKey(metaDataKey))) {
+                    continue;
+                }
+                final ProviderInfo info = PackageParser.generateProviderInfo(
+                        p, flags, ps.readUserState(userId), userId);
+                if (info == null) {
+                    continue;
+                }
+                if (providerList == null) {
+                    providerList = new ArrayList<>(i + 1);
+                }
+                providerList.add(info);
+            }
+        }
+        return providerList;
+    }
+
+    ProviderInfo queryProvider(String authority, int flags, int userId) {
+        synchronized (mLock) {
+            final PackageParser.Provider p = mProvidersByAuthority.get(authority);
+            if (p == null) {
+                return null;
+            }
+            final PackageSetting ps = (PackageSetting) p.owner.mExtras;
+            if (ps == null) {
+                return null;
+            }
+            return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId), userId);
+        }
+    }
+
+    void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo, boolean safeMode,
+            int userId) {
+        synchronized (mLock) {
+            for (int i = mProvidersByAuthority.size() - 1; i >= 0; --i) {
+                final PackageParser.Provider p = mProvidersByAuthority.valueAt(i);
+                final PackageSetting ps = (PackageSetting) p.owner.mExtras;
+                if (ps == null) {
+                    continue;
+                }
+                if (!p.syncable) {
+                    continue;
+                }
+                if (safeMode
+                        && (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                    continue;
+                }
+                final ProviderInfo info =
+                        PackageParser.generateProviderInfo(p, 0, ps.readUserState(userId), userId);
+                if (info == null) {
+                    continue;
+                }
+                outNames.add(mProvidersByAuthority.keyAt(i));
+                outInfo.add(info);
+            }
+        }
+    }
+
+    List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) {
+        synchronized (mLock) {
+            return mReceivers.queryIntent(intent, resolvedType, flags, userId);
+        }
+    }
+
+    List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags,
+            List<PackageParser.Activity> receivers, int userId) {
+        synchronized (mLock) {
+            return mReceivers.queryIntentForPackage(intent, resolvedType, flags, receivers, userId);
+        }
+    }
+
+    List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags, int userId) {
+        synchronized (mLock) {
+            return mServices.queryIntent(intent, resolvedType, flags, userId);
+        }
+    }
+
+    List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags,
+            List<PackageParser.Service> services, int userId) {
+        synchronized (mLock) {
+            return mServices.queryIntentForPackage(intent, resolvedType, flags, services, userId);
+        }
+    }
+
+    /** Returns {@code true} if the given activity is defined by some package */
+    boolean isActivityDefined(ComponentName component) {
+        synchronized (mLock) {
+            return mActivities.mActivities.get(component) != null;
+        }
+    }
+
+    /** Asserts none of the providers defined in the given package haven't already been defined. */
+    void assertProvidersNotDefined(PackageParser.Package pkg) throws PackageManagerException {
+        synchronized (mLock) {
+            assertProvidersNotDefinedLocked(pkg);
+        }
+    }
+
+    /** Add all components defined in the given package to the internal structures. */
+    void addAllComponents(PackageParser.Package pkg, boolean chatty) {
+        final ArrayList<PackageParser.ActivityIntentInfo> newIntents = new ArrayList<>();
+        synchronized (mLock) {
+            addActivitiesLocked(pkg, newIntents, chatty);
+            addReceiversLocked(pkg, chatty);
+            addProvidersLocked(pkg, chatty);
+            addServicesLocked(pkg, chatty);
+        }
+        final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName(
+                PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM);
+        for (int i = newIntents.size() - 1; i >= 0; --i) {
+            final PackageParser.ActivityIntentInfo intentInfo = newIntents.get(i);
+            final PackageParser.Package disabledPkg = sPackageManagerInternal
+                    .getDisabledPackage(intentInfo.activity.info.packageName);
+            final List<PackageParser.Activity> systemActivities =
+                    disabledPkg != null ? disabledPkg.activities : null;
+            adjustPriority(systemActivities, intentInfo, setupWizardPackage);
+        }
+    }
+
+    /** Removes all components defined in the given package from the internal structures. */
+    void removeAllComponents(PackageParser.Package pkg, boolean chatty) {
+        synchronized (mLock) {
+            removeAllComponentsLocked(pkg, chatty);
+        }
+    }
+
+    /**
+     * Reprocess any protected filters that have been deferred. At this point, we've scanned
+     * all of the filters defined on the /system partition and know the special components.
+     */
+    void fixProtectedFilterPriorities() {
+        if (!mDeferProtectedFilters) {
+            return;
+        }
+        mDeferProtectedFilters = false;
+
+        if (mProtectedFilters == null || mProtectedFilters.size() == 0) {
+            return;
+        }
+        final List<ActivityIntentInfo> protectedFilters = mProtectedFilters;
+        mProtectedFilters = null;
+
+        final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName(
+                PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM);
+        if (DEBUG_FILTERS && setupWizardPackage == null) {
+            Slog.i(TAG, "No setup wizard;"
+                    + " All protected intents capped to priority 0");
+        }
+        for (int i = protectedFilters.size() - 1; i >= 0; --i) {
+            final ActivityIntentInfo filter = protectedFilters.get(i);
+            if (filter.activity.info.packageName.equals(setupWizardPackage)) {
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Found setup wizard;"
+                            + " allow priority " + filter.getPriority() + ";"
+                            + " package: " + filter.activity.info.packageName
+                            + " activity: " + filter.activity.className
+                            + " priority: " + filter.getPriority());
+                }
+                // skip setup wizard; allow it to keep the high priority filter
+                continue;
+            }
+            if (DEBUG_FILTERS) {
+                Slog.i(TAG, "Protected action; cap priority to 0;"
+                        + " package: " + filter.activity.info.packageName
+                        + " activity: " + filter.activity.className
+                        + " origPrio: " + filter.getPriority());
+            }
+            filter.setPriority(0);
+        }
+    }
+
+    void dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
+                : "Activity Resolver Table:", "  ", packageName,
+                dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+            dumpState.setTitlePrinted(true);
+        }
+    }
+
+    void dumpProviderResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
+                : "Provider Resolver Table:", "  ", packageName,
+                dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+            dumpState.setTitlePrinted(true);
+        }
+    }
+
+    void dumpReceiverResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
+                : "Receiver Resolver Table:", "  ", packageName,
+                dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+            dumpState.setTitlePrinted(true);
+        }
+    }
+
+    void dumpServiceResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
+                : "Service Resolver Table:", "  ", packageName,
+                dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+            dumpState.setTitlePrinted(true);
+        }
+    }
+
+    void dumpContentProviders(PrintWriter pw, DumpState dumpState, String packageName) {
+        boolean printedSomething = false;
+        for (PackageParser.Provider p : mProviders.mProviders.values()) {
+            if (packageName != null && !packageName.equals(p.info.packageName)) {
+                continue;
+            }
+            if (!printedSomething) {
+                if (dumpState.onTitlePrinted()) {
+                    pw.println();
+                }
+                pw.println("Registered ContentProviders:");
+                printedSomething = true;
+            }
+            pw.print("  "); p.printComponentShortName(pw); pw.println(":");
+            pw.print("    "); pw.println(p.toString());
+        }
+        printedSomething = false;
+        for (Map.Entry<String, PackageParser.Provider> entry :
+                mProvidersByAuthority.entrySet()) {
+            PackageParser.Provider p = entry.getValue();
+            if (packageName != null && !packageName.equals(p.info.packageName)) {
+                continue;
+            }
+            if (!printedSomething) {
+                if (dumpState.onTitlePrinted()) {
+                    pw.println();
+                }
+                pw.println("ContentProvider Authorities:");
+                printedSomething = true;
+            }
+            pw.print("  ["); pw.print(entry.getKey()); pw.println("]:");
+            pw.print("    "); pw.println(p.toString());
+            if (p.info != null && p.info.applicationInfo != null) {
+                final String appInfo = p.info.applicationInfo.toString();
+                pw.print("      applicationInfo="); pw.println(appInfo);
+            }
+        }
+    }
+
+    void dumpServicePermissions(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (dumpState.onTitlePrinted()) pw.println();
+        pw.println("Service permissions:");
+
+        final Iterator<ServiceIntentInfo> filterIterator = mServices.filterIterator();
+        while (filterIterator.hasNext()) {
+            final ServiceIntentInfo info = filterIterator.next();
+            final ServiceInfo serviceInfo = info.service.info;
+            final String permission = serviceInfo.permission;
+            if (permission != null) {
+                pw.print("    ");
+                pw.print(serviceInfo.getComponentName().flattenToShortString());
+                pw.print(": ");
+                pw.println(permission);
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void addActivitiesLocked(PackageParser.Package pkg,
+            List<PackageParser.ActivityIntentInfo> newIntents, boolean chatty) {
+        final int activitiesSize = pkg.activities.size();
+        StringBuilder r = null;
+        for (int i = 0; i < activitiesSize; i++) {
+            PackageParser.Activity a = pkg.activities.get(i);
+            a.info.processName =
+                    fixProcessName(pkg.applicationInfo.processName, a.info.processName);
+            mActivities.addActivity(a, "activity", newIntents);
+            if (DEBUG_PACKAGE_SCANNING && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (DEBUG_PACKAGE_SCANNING && chatty) {
+            Log.d(TAG, "  Activities: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void addProvidersLocked(PackageParser.Package pkg, boolean chatty) {
+        final int providersSize = pkg.providers.size();
+        StringBuilder r = null;
+        for (int i = 0; i < providersSize; i++) {
+            PackageParser.Provider p = pkg.providers.get(i);
+            p.info.processName = fixProcessName(pkg.applicationInfo.processName,
+                    p.info.processName);
+            mProviders.addProvider(p);
+            p.syncable = p.info.isSyncable;
+            if (p.info.authority != null) {
+                String[] names = p.info.authority.split(";");
+                p.info.authority = null;
+                for (int j = 0; j < names.length; j++) {
+                    if (j == 1 && p.syncable) {
+                        // We only want the first authority for a provider to possibly be
+                        // syncable, so if we already added this provider using a different
+                        // authority clear the syncable flag. We copy the provider before
+                        // changing it because the mProviders object contains a reference
+                        // to a provider that we don't want to change.
+                        // Only do this for the second authority since the resulting provider
+                        // object can be the same for all future authorities for this provider.
+                        p = new PackageParser.Provider(p);
+                        p.syncable = false;
+                    }
+                    if (!mProvidersByAuthority.containsKey(names[j])) {
+                        mProvidersByAuthority.put(names[j], p);
+                        if (p.info.authority == null) {
+                            p.info.authority = names[j];
+                        } else {
+                            p.info.authority = p.info.authority + ";" + names[j];
+                        }
+                        if (DEBUG_PACKAGE_SCANNING && chatty) {
+                            Log.d(TAG, "Registered content provider: " + names[j]
+                                    + ", className = " + p.info.name
+                                    + ", isSyncable = " + p.info.isSyncable);
+                        }
+                    } else {
+                        final PackageParser.Provider other =
+                                mProvidersByAuthority.get(names[j]);
+                        final ComponentName component =
+                                (other != null && other.getComponentName() != null)
+                                        ? other.getComponentName() : null;
+                        final String packageName =
+                                component != null ? component.getPackageName() : "?";
+                        Slog.w(TAG, "Skipping provider name " + names[j]
+                                + " (in package " + pkg.applicationInfo.packageName + ")"
+                                + ": name already used by " + packageName);
+                    }
+                }
+            }
+            if (DEBUG_PACKAGE_SCANNING && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(p.info.name);
+            }
+        }
+        if (DEBUG_PACKAGE_SCANNING && chatty) {
+            Log.d(TAG, "  Providers: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void addReceiversLocked(PackageParser.Package pkg, boolean chatty) {
+        final int receiversSize = pkg.receivers.size();
+        StringBuilder r = null;
+        for (int i = 0; i < receiversSize; i++) {
+            PackageParser.Activity a = pkg.receivers.get(i);
+            a.info.processName = fixProcessName(pkg.applicationInfo.processName,
+                    a.info.processName);
+            mReceivers.addActivity(a, "receiver", null);
+            if (DEBUG_PACKAGE_SCANNING && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (DEBUG_PACKAGE_SCANNING && chatty) {
+            Log.d(TAG, "  Receivers: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void addServicesLocked(PackageParser.Package pkg, boolean chatty) {
+        final int servicesSize = pkg.services.size();
+        StringBuilder r = null;
+        for (int i = 0; i < servicesSize; i++) {
+            PackageParser.Service s = pkg.services.get(i);
+            s.info.processName = fixProcessName(pkg.applicationInfo.processName,
+                    s.info.processName);
+            mServices.addService(s);
+            if (DEBUG_PACKAGE_SCANNING && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(s.info.name);
+            }
+        }
+        if (DEBUG_PACKAGE_SCANNING && chatty) {
+            Log.d(TAG, "  Services: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+
+    /**
+     * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
+     * MODIFIED. Do not pass in a list that should not be changed.
+     */
+    private static <T> void getIntentListSubset(List<ActivityIntentInfo> intentList,
+            IterGenerator<T> generator, Iterator<T> searchIterator) {
+        // loop through the set of actions; every one must be found in the intent filter
+        while (searchIterator.hasNext()) {
+            // we must have at least one filter in the list to consider a match
+            if (intentList.size() == 0) {
+                break;
+            }
+
+            final T searchAction = searchIterator.next();
+
+            // loop through the set of intent filters
+            final Iterator<ActivityIntentInfo> intentIter = intentList.iterator();
+            while (intentIter.hasNext()) {
+                final ActivityIntentInfo intentInfo = intentIter.next();
+                boolean selectionFound = false;
+
+                // loop through the intent filter's selection criteria; at least one
+                // of them must match the searched criteria
+                final Iterator<T> intentSelectionIter = generator.generate(intentInfo);
+                while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
+                    final T intentSelection = intentSelectionIter.next();
+                    if (intentSelection != null && intentSelection.equals(searchAction)) {
+                        selectionFound = true;
+                        break;
+                    }
+                }
+
+                // the selection criteria wasn't found in this filter's set; this filter
+                // is not a potential match
+                if (!selectionFound) {
+                    intentIter.remove();
+                }
+            }
+        }
+    }
+
+    private static boolean isProtectedAction(ActivityIntentInfo filter) {
+        final Iterator<String> actionsIter = filter.actionsIterator();
+        while (actionsIter != null && actionsIter.hasNext()) {
+            final String filterAction = actionsIter.next();
+            if (PROTECTED_ACTIONS.contains(filterAction)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Finds a privileged activity that matches the specified activity names.
+     */
+    private static PackageParser.Activity findMatchingActivity(
+            List<PackageParser.Activity> activityList, ActivityInfo activityInfo) {
+        for (PackageParser.Activity sysActivity : activityList) {
+            if (sysActivity.info.name.equals(activityInfo.name)) {
+                return sysActivity;
+            }
+            if (sysActivity.info.name.equals(activityInfo.targetActivity)) {
+                return sysActivity;
+            }
+            if (sysActivity.info.targetActivity != null) {
+                if (sysActivity.info.targetActivity.equals(activityInfo.name)) {
+                    return sysActivity;
+                }
+                if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) {
+                    return sysActivity;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Adjusts the priority of the given intent filter according to policy.
+     * <p>
+     * <ul>
+     * <li>The priority for non privileged applications is capped to '0'</li>
+     * <li>The priority for protected actions on privileged applications is capped to '0'</li>
+     * <li>The priority for unbundled updates to privileged applications is capped to the
+     *      priority defined on the system partition</li>
+     * </ul>
+     * <p>
+     * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
+     * allowed to obtain any priority on any action.
+     */
+    private void adjustPriority(List<PackageParser.Activity> systemActivities,
+            ActivityIntentInfo intent, String setupWizardPackage) {
+        // nothing to do; priority is fine as-is
+        if (intent.getPriority() <= 0) {
+            return;
+        }
+
+        final ActivityInfo activityInfo = intent.activity.info;
+        final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
+
+        final boolean privilegedApp =
+                ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
+        if (!privilegedApp) {
+            // non-privileged applications can never define a priority >0
+            if (DEBUG_FILTERS) {
+                Slog.i(TAG, "Non-privileged app; cap priority to 0;"
+                        + " package: " + applicationInfo.packageName
+                        + " activity: " + intent.activity.className
+                        + " origPrio: " + intent.getPriority());
+            }
+            intent.setPriority(0);
+            return;
+        }
+
+        if (systemActivities == null) {
+            // the system package is not disabled; we're parsing the system partition
+            if (isProtectedAction(intent)) {
+                if (mDeferProtectedFilters) {
+                    // We can't deal with these just yet. No component should ever obtain a
+                    // >0 priority for a protected actions, with ONE exception -- the setup
+                    // wizard. The setup wizard, however, cannot be known until we're able to
+                    // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
+                    // until all intent filters have been processed. Chicken, meet egg.
+                    // Let the filter temporarily have a high priority and rectify the
+                    // priorities after all system packages have been scanned.
+                    if (mProtectedFilters == null) {
+                        mProtectedFilters = new ArrayList<>();
+                    }
+                    mProtectedFilters.add(intent);
+                    if (DEBUG_FILTERS) {
+                        Slog.i(TAG, "Protected action; save for later;"
+                                + " package: " + applicationInfo.packageName
+                                + " activity: " + intent.activity.className
+                                + " origPrio: " + intent.getPriority());
+                    }
+                    return;
+                } else {
+                    if (DEBUG_FILTERS && setupWizardPackage == null) {
+                        Slog.i(TAG, "No setup wizard;"
+                                + " All protected intents capped to priority 0");
+                    }
+                    if (intent.activity.info.packageName.equals(setupWizardPackage)) {
+                        if (DEBUG_FILTERS) {
+                            Slog.i(TAG, "Found setup wizard;"
+                                    + " allow priority " + intent.getPriority() + ";"
+                                    + " package: " + intent.activity.info.packageName
+                                    + " activity: " + intent.activity.className
+                                    + " priority: " + intent.getPriority());
+                        }
+                        // setup wizard gets whatever it wants
+                        return;
+                    }
+                    if (DEBUG_FILTERS) {
+                        Slog.i(TAG, "Protected action; cap priority to 0;"
+                                + " package: " + intent.activity.info.packageName
+                                + " activity: " + intent.activity.className
+                                + " origPrio: " + intent.getPriority());
+                    }
+                    intent.setPriority(0);
+                    return;
+                }
+            }
+            // privileged apps on the system image get whatever priority they request
+            return;
+        }
+
+        // privileged app unbundled update ... try to find the same activity
+        final PackageParser.Activity foundActivity =
+                findMatchingActivity(systemActivities, activityInfo);
+        if (foundActivity == null) {
+            // this is a new activity; it cannot obtain >0 priority
+            if (DEBUG_FILTERS) {
+                Slog.i(TAG, "New activity; cap priority to 0;"
+                        + " package: " + applicationInfo.packageName
+                        + " activity: " + intent.activity.className
+                        + " origPrio: " + intent.getPriority());
+            }
+            intent.setPriority(0);
+            return;
+        }
+
+        // found activity, now check for filter equivalence
+
+        // a shallow copy is enough; we modify the list, not its contents
+        final List<ActivityIntentInfo> intentListCopy = new ArrayList<>(foundActivity.intents);
+        final List<ActivityIntentInfo> foundFilters = mActivities.findFilters(intent);
+
+        // find matching action subsets
+        final Iterator<String> actionsIterator = intent.actionsIterator();
+        if (actionsIterator != null) {
+            getIntentListSubset(intentListCopy, new ActionIterGenerator(), actionsIterator);
+            if (intentListCopy.size() == 0) {
+                // no more intents to match; we're not equivalent
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Mismatched action; cap priority to 0;"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(0);
+                return;
+            }
+        }
+
+        // find matching category subsets
+        final Iterator<String> categoriesIterator = intent.categoriesIterator();
+        if (categoriesIterator != null) {
+            getIntentListSubset(intentListCopy, new CategoriesIterGenerator(), categoriesIterator);
+            if (intentListCopy.size() == 0) {
+                // no more intents to match; we're not equivalent
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Mismatched category; cap priority to 0;"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(0);
+                return;
+            }
+        }
+
+        // find matching schemes subsets
+        final Iterator<String> schemesIterator = intent.schemesIterator();
+        if (schemesIterator != null) {
+            getIntentListSubset(intentListCopy, new SchemesIterGenerator(), schemesIterator);
+            if (intentListCopy.size() == 0) {
+                // no more intents to match; we're not equivalent
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(0);
+                return;
+            }
+        }
+
+        // find matching authorities subsets
+        final Iterator<IntentFilter.AuthorityEntry> authoritiesIterator =
+                intent.authoritiesIterator();
+        if (authoritiesIterator != null) {
+            getIntentListSubset(intentListCopy, new AuthoritiesIterGenerator(),
+                    authoritiesIterator);
+            if (intentListCopy.size() == 0) {
+                // no more intents to match; we're not equivalent
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Mismatched authority; cap priority to 0;"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(0);
+                return;
+            }
+        }
+
+        // we found matching filter(s); app gets the max priority of all intents
+        int cappedPriority = 0;
+        for (int i = intentListCopy.size() - 1; i >= 0; --i) {
+            cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority());
+        }
+        if (intent.getPriority() > cappedPriority) {
+            if (DEBUG_FILTERS) {
+                Slog.i(TAG, "Found matching filter(s);"
+                        + " cap priority to " + cappedPriority + ";"
+                        + " package: " + applicationInfo.packageName
+                        + " activity: " + intent.activity.className
+                        + " origPrio: " + intent.getPriority());
+            }
+            intent.setPriority(cappedPriority);
+            return;
+        }
+        // all this for nothing; the requested priority was <= what was on the system
+    }
+
+    @GuardedBy("mLock")
+    private void removeAllComponentsLocked(PackageParser.Package pkg, boolean chatty) {
+        int componentSize;
+        StringBuilder r;
+        int i;
+
+        componentSize = pkg.activities.size();
+        r = null;
+        for (i = 0; i < componentSize; i++) {
+            PackageParser.Activity a = pkg.activities.get(i);
+            mActivities.removeActivity(a, "activity");
+            if (DEBUG_REMOVE && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (DEBUG_REMOVE && chatty) {
+            Log.d(TAG, "  Activities: " + (r == null ? "<NONE>" : r));
+        }
+
+        componentSize = pkg.providers.size();
+        r = null;
+        for (i = 0; i < componentSize; i++) {
+            PackageParser.Provider p = pkg.providers.get(i);
+            mProviders.removeProvider(p);
+            if (p.info.authority == null) {
+                // Another content provider with this authority existed when this app was
+                // installed, so this authority is null. Ignore it as we don't have to
+                // unregister the provider.
+                continue;
+            }
+            String[] names = p.info.authority.split(";");
+            for (int j = 0; j < names.length; j++) {
+                if (mProvidersByAuthority.get(names[j]) == p) {
+                    mProvidersByAuthority.remove(names[j]);
+                    if (DEBUG_REMOVE && chatty) {
+                        Log.d(TAG, "Unregistered content provider: " + names[j]
+                                + ", className = " + p.info.name + ", isSyncable = "
+                                + p.info.isSyncable);
+                    }
+                }
+            }
+            if (DEBUG_REMOVE && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(p.info.name);
+            }
+        }
+        if (DEBUG_REMOVE && chatty) {
+            Log.d(TAG, "  Providers: " + (r == null ? "<NONE>" : r));
+        }
+
+        componentSize = pkg.receivers.size();
+        r = null;
+        for (i = 0; i < componentSize; i++) {
+            PackageParser.Activity a = pkg.receivers.get(i);
+            mReceivers.removeActivity(a, "receiver");
+            if (DEBUG_REMOVE && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (DEBUG_REMOVE && chatty) {
+            Log.d(TAG, "  Receivers: " + (r == null ? "<NONE>" : r));
+        }
+
+        componentSize = pkg.services.size();
+        r = null;
+        for (i = 0; i < componentSize; i++) {
+            PackageParser.Service s = pkg.services.get(i);
+            mServices.removeService(s);
+            if (DEBUG_REMOVE && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(s.info.name);
+            }
+        }
+        if (DEBUG_REMOVE && chatty) {
+            Log.d(TAG, "  Services: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void assertProvidersNotDefinedLocked(PackageParser.Package pkg)
+            throws PackageManagerException {
+        final int providersSize = pkg.providers.size();
+        int i;
+        for (i = 0; i < providersSize; i++) {
+            PackageParser.Provider p = pkg.providers.get(i);
+            if (p.info.authority != null) {
+                final String[] names = p.info.authority.split(";");
+                for (int j = 0; j < names.length; j++) {
+                    if (mProvidersByAuthority.containsKey(names[j])) {
+                        final PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
+                        final String otherPackageName =
+                                (other != null && other.getComponentName() != null)
+                                        ? other.getComponentName().getPackageName() : "?";
+                        throw new PackageManagerException(
+                                INSTALL_FAILED_CONFLICTING_PROVIDER,
+                                "Can't install because provider name " + names[j]
+                                        + " (in package " + pkg.applicationInfo.packageName
+                                        + ") is already used by " + otherPackageName);
+                    }
+                }
+            }
+        }
+    }
+
+    private static final class ActivityIntentResolver
+            extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
+        @Override
+        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
+                boolean defaultOnly, int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+        }
+
+        List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+                int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            mFlags = flags;
+            return super.queryIntent(intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+                    userId);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
+                int flags, List<PackageParser.Activity> packageActivities, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            if (packageActivities == null) {
+                return null;
+            }
+            mFlags = flags;
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int activitiesSize = packageActivities.size();
+            ArrayList<PackageParser.ActivityIntentInfo[]> listCut = new ArrayList<>(activitiesSize);
+
+            ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
+            for (int i = 0; i < activitiesSize; ++i) {
+                intentFilters = packageActivities.get(i).intents;
+                if (intentFilters != null && intentFilters.size() > 0) {
+                    PackageParser.ActivityIntentInfo[] array =
+                            new PackageParser.ActivityIntentInfo[intentFilters.size()];
+                    intentFilters.toArray(array);
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+        }
+
+        private void addActivity(PackageParser.Activity a, String type,
+                List<PackageParser.ActivityIntentInfo> newIntents) {
+            mActivities.put(a.getComponentName(), a);
+            if (DEBUG_SHOW_INFO) {
+                final CharSequence label = a.info.nonLocalizedLabel != null
+                        ? a.info.nonLocalizedLabel
+                        : a.info.name;
+                Log.v(TAG, "  " + type + " " + label + ":");
+            }
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "    Class=" + a.info.name);
+            }
+            final int intentsSize = a.intents.size();
+            for (int j = 0; j < intentsSize; j++) {
+                PackageParser.ActivityIntentInfo intent = a.intents.get(j);
+                if (newIntents != null && "activity".equals(type)) {
+                    newIntents.add(intent);
+                }
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                if (!intent.debugCheck()) {
+                    Log.w(TAG, "==> For Activity " + a.info.name);
+                }
+                addFilter(intent);
+            }
+        }
+
+        private void removeActivity(PackageParser.Activity a, String type) {
+            mActivities.remove(a.getComponentName());
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  " + type + " "
+                        + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
+                                : a.info.name) + ":");
+                Log.v(TAG, "    Class=" + a.info.name);
+            }
+            final int intentsSize = a.intents.size();
+            for (int j = 0; j < intentsSize; j++) {
+                PackageParser.ActivityIntentInfo intent = a.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                removeFilter(intent);
+            }
+        }
+
+        @Override
+        protected boolean allowFilterResult(
+                PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
+            ActivityInfo filterAi = filter.activity.info;
+            for (int i = dest.size() - 1; i >= 0; --i) {
+                ActivityInfo destAi = dest.get(i).activityInfo;
+                if (destAi.name == filterAi.name && destAi.packageName == filterAi.packageName) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        protected ActivityIntentInfo[] newArray(int size) {
+            return new ActivityIntentInfo[size];
+        }
+
+        @Override
+        protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
+            if (!sUserManager.exists(userId)) return true;
+            PackageParser.Package p = filter.activity.owner;
+            if (p != null) {
+                PackageSetting ps = (PackageSetting) p.mExtras;
+                if (ps != null) {
+                    // System apps are never considered stopped for purposes of
+                    // filtering, because there may be no way for the user to
+                    // actually re-launch them.
+                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
+                            && ps.getStopped(userId);
+                }
+            }
+            return false;
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                PackageParser.ActivityIntentInfo info) {
+            return packageName.equals(info.activity.owner.packageName);
+        }
+
+        @Override
+        protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
+                int match, int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            if (!sPackageManagerInternal.isEnabledAndMatches(info.activity.info, mFlags, userId)) {
+                return null;
+            }
+            final PackageParser.Activity activity = info.activity;
+            PackageSetting ps = (PackageSetting) activity.owner.mExtras;
+            if (ps == null) {
+                return null;
+            }
+            final PackageUserState userState = ps.readUserState(userId);
+            ActivityInfo ai =
+                    PackageParser.generateActivityInfo(activity, mFlags, userState, userId);
+            if (ai == null) {
+                return null;
+            }
+            final boolean matchExplicitlyVisibleOnly =
+                    (mFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
+            final boolean matchVisibleToInstantApp =
+                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+            final boolean componentVisible =
+                    matchVisibleToInstantApp
+                    && info.isVisibleToInstantApp()
+                    && (!matchExplicitlyVisibleOnly || info.isExplicitlyVisibleToInstantApp());
+            final boolean matchInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            // throw out filters that aren't visible to ephemeral apps
+            if (matchVisibleToInstantApp && !(componentVisible || userState.instantApp)) {
+                return null;
+            }
+            // throw out instant app filters if we're not explicitly requesting them
+            if (!matchInstantApp && userState.instantApp) {
+                return null;
+            }
+            // throw out instant app filters if updates are available; will trigger
+            // instant app resolution
+            if (userState.instantApp && ps.isUpdateAvailable()) {
+                return null;
+            }
+            final ResolveInfo res = new ResolveInfo();
+            res.activityInfo = ai;
+            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
+                res.filter = info;
+            }
+            res.handleAllWebDataURI = info.handleAllWebDataURI();
+            res.priority = info.getPriority();
+            res.preferredOrder = activity.owner.mPreferredOrder;
+            //System.out.println("Result: " + res.activityInfo.className +
+            //                   " = " + res.priority);
+            res.match = match;
+            res.isDefault = info.hasDefault;
+            res.labelRes = info.labelRes;
+            res.nonLocalizedLabel = info.nonLocalizedLabel;
+            if (sPackageManagerInternal.userNeedsBadging(userId)) {
+                res.noResourceId = true;
+            } else {
+                res.icon = info.icon;
+            }
+            res.iconResourceId = info.icon;
+            res.system = res.activityInfo.applicationInfo.isSystemApp();
+            res.isInstantAppAvailable = userState.instantApp;
+            return res;
+        }
+
+        @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
+        protected void dumpFilter(PrintWriter out, String prefix,
+                PackageParser.ActivityIntentInfo filter) {
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(filter.activity)));
+            out.print(' ');
+            filter.activity.printComponentShortName(out);
+            out.print(" filter ");
+            out.println(Integer.toHexString(System.identityHashCode(filter)));
+        }
+
+        @Override
+        protected Object filterToLabel(PackageParser.ActivityIntentInfo filter) {
+            return filter.activity;
+        }
+
+        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
+            PackageParser.Activity activity = (PackageParser.Activity) label;
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(activity)));
+            out.print(' ');
+            activity.printComponentShortName(out);
+            if (count > 1) {
+                out.print(" ("); out.print(count); out.print(" filters)");
+            }
+            out.println();
+        }
+
+        // Keys are String (activity class name), values are Activity.
+        private final ArrayMap<ComponentName, PackageParser.Activity> mActivities =
+                new ArrayMap<>();
+        private int mFlags;
+    }
+
+    private static final class ProviderIntentResolver
+            extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
+        @Override
+        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
+                boolean defaultOnly, int userId) {
+            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+        }
+
+        List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+                int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            mFlags = flags;
+            return super.queryIntent(intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+                    userId);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
+                int flags, List<PackageParser.Provider> packageProviders, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            if (packageProviders == null) {
+                return null;
+            }
+            mFlags = flags;
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int providersSize = packageProviders.size();
+            ArrayList<PackageParser.ProviderIntentInfo[]> listCut = new ArrayList<>(providersSize);
+
+            ArrayList<PackageParser.ProviderIntentInfo> intentFilters;
+            for (int i = 0; i < providersSize; ++i) {
+                intentFilters = packageProviders.get(i).intents;
+                if (intentFilters != null && intentFilters.size() > 0) {
+                    PackageParser.ProviderIntentInfo[] array =
+                            new PackageParser.ProviderIntentInfo[intentFilters.size()];
+                    intentFilters.toArray(array);
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+        }
+
+        void addProvider(PackageParser.Provider p) {
+            if (mProviders.containsKey(p.getComponentName())) {
+                Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
+                return;
+            }
+
+            mProviders.put(p.getComponentName(), p);
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  "
+                        + (p.info.nonLocalizedLabel != null
+                                ? p.info.nonLocalizedLabel
+                                : p.info.name)
+                        + ":");
+                Log.v(TAG, "    Class=" + p.info.name);
+            }
+            final int intentsSize = p.intents.size();
+            int j;
+            for (j = 0; j < intentsSize; j++) {
+                PackageParser.ProviderIntentInfo intent = p.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                if (!intent.debugCheck()) {
+                    Log.w(TAG, "==> For Provider " + p.info.name);
+                }
+                addFilter(intent);
+            }
+        }
+
+        void removeProvider(PackageParser.Provider p) {
+            mProviders.remove(p.getComponentName());
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  " + (p.info.nonLocalizedLabel != null
+                        ? p.info.nonLocalizedLabel
+                        : p.info.name) + ":");
+                Log.v(TAG, "    Class=" + p.info.name);
+            }
+            final int intentsSize = p.intents.size();
+            int j;
+            for (j = 0; j < intentsSize; j++) {
+                PackageParser.ProviderIntentInfo intent = p.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                removeFilter(intent);
+            }
+        }
+
+        @Override
+        protected boolean allowFilterResult(
+                PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) {
+            ProviderInfo filterPi = filter.provider.info;
+            for (int i = dest.size() - 1; i >= 0; i--) {
+                ProviderInfo destPi = dest.get(i).providerInfo;
+                if (destPi.name == filterPi.name
+                        && destPi.packageName == filterPi.packageName) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        protected PackageParser.ProviderIntentInfo[] newArray(int size) {
+            return new PackageParser.ProviderIntentInfo[size];
+        }
+
+        @Override
+        protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return true;
+            }
+            PackageParser.Package p = filter.provider.owner;
+            if (p != null) {
+                PackageSetting ps = (PackageSetting) p.mExtras;
+                if (ps != null) {
+                    // System apps are never considered stopped for purposes of
+                    // filtering, because there may be no way for the user to
+                    // actually re-launch them.
+                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
+                            && ps.getStopped(userId);
+                }
+            }
+            return false;
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                PackageParser.ProviderIntentInfo info) {
+            return packageName.equals(info.provider.owner.packageName);
+        }
+
+        @Override
+        protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter,
+                int match, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            final PackageParser.ProviderIntentInfo info = filter;
+            if (!sPackageManagerInternal.isEnabledAndMatches(info.provider.info, mFlags, userId)) {
+                return null;
+            }
+            final PackageParser.Provider provider = info.provider;
+            PackageSetting ps = (PackageSetting) provider.owner.mExtras;
+            if (ps == null) {
+                return null;
+            }
+            final PackageUserState userState = ps.readUserState(userId);
+            final boolean matchVisibleToInstantApp = (mFlags
+                    & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            // throw out filters that aren't visible to instant applications
+            if (matchVisibleToInstantApp
+                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+                return null;
+            }
+            // throw out instant application filters if we're not explicitly requesting them
+            if (!isInstantApp && userState.instantApp) {
+                return null;
+            }
+            // throw out instant application filters if updates are available; will trigger
+            // instant application resolution
+            if (userState.instantApp && ps.isUpdateAvailable()) {
+                return null;
+            }
+            ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
+                    userState, userId);
+            if (pi == null) {
+                return null;
+            }
+            final ResolveInfo res = new ResolveInfo();
+            res.providerInfo = pi;
+            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
+                res.filter = filter;
+            }
+            res.priority = info.getPriority();
+            res.preferredOrder = provider.owner.mPreferredOrder;
+            res.match = match;
+            res.isDefault = info.hasDefault;
+            res.labelRes = info.labelRes;
+            res.nonLocalizedLabel = info.nonLocalizedLabel;
+            res.icon = info.icon;
+            res.system = res.providerInfo.applicationInfo.isSystemApp();
+            return res;
+        }
+
+        @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
+        protected void dumpFilter(PrintWriter out, String prefix,
+                PackageParser.ProviderIntentInfo filter) {
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(filter.provider)));
+            out.print(' ');
+            filter.provider.printComponentShortName(out);
+            out.print(" filter ");
+            out.println(Integer.toHexString(System.identityHashCode(filter)));
+        }
+
+        @Override
+        protected Object filterToLabel(PackageParser.ProviderIntentInfo filter) {
+            return filter.provider;
+        }
+
+        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
+            final PackageParser.Provider provider = (PackageParser.Provider) label;
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(provider)));
+            out.print(' ');
+            provider.printComponentShortName(out);
+            if (count > 1) {
+                out.print(" (");
+                out.print(count);
+                out.print(" filters)");
+            }
+            out.println();
+        }
+
+        private final ArrayMap<ComponentName, PackageParser.Provider> mProviders = new ArrayMap<>();
+        private int mFlags;
+    }
+
+    private static final class ServiceIntentResolver
+            extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
+        @Override
+        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
+                boolean defaultOnly, int userId) {
+            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+        }
+
+        List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+                int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            mFlags = flags;
+            return super.queryIntent(intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+                    userId);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
+                int flags, List<PackageParser.Service> packageServices, int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            if (packageServices == null) {
+                return null;
+            }
+            mFlags = flags;
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int servicesSize = packageServices.size();
+            ArrayList<PackageParser.ServiceIntentInfo[]> listCut = new ArrayList<>(servicesSize);
+
+            ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
+            for (int i = 0; i < servicesSize; ++i) {
+                intentFilters = packageServices.get(i).intents;
+                if (intentFilters != null && intentFilters.size() > 0) {
+                    PackageParser.ServiceIntentInfo[] array =
+                            new PackageParser.ServiceIntentInfo[intentFilters.size()];
+                    intentFilters.toArray(array);
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+        }
+
+        void addService(PackageParser.Service s) {
+            mServices.put(s.getComponentName(), s);
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  "
+                        + (s.info.nonLocalizedLabel != null
+                        ? s.info.nonLocalizedLabel : s.info.name) + ":");
+                Log.v(TAG, "    Class=" + s.info.name);
+            }
+            final int intentsSize = s.intents.size();
+            int j;
+            for (j = 0; j < intentsSize; j++) {
+                PackageParser.ServiceIntentInfo intent = s.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                if (!intent.debugCheck()) {
+                    Log.w(TAG, "==> For Service " + s.info.name);
+                }
+                addFilter(intent);
+            }
+        }
+
+        void removeService(PackageParser.Service s) {
+            mServices.remove(s.getComponentName());
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  " + (s.info.nonLocalizedLabel != null
+                        ? s.info.nonLocalizedLabel : s.info.name) + ":");
+                Log.v(TAG, "    Class=" + s.info.name);
+            }
+            final int intentsSize = s.intents.size();
+            int j;
+            for (j = 0; j < intentsSize; j++) {
+                PackageParser.ServiceIntentInfo intent = s.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                removeFilter(intent);
+            }
+        }
+
+        @Override
+        protected boolean allowFilterResult(
+                PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
+            ServiceInfo filterSi = filter.service.info;
+            for (int i = dest.size() - 1; i >= 0; --i) {
+                ServiceInfo destAi = dest.get(i).serviceInfo;
+                if (destAi.name == filterSi.name
+                        && destAi.packageName == filterSi.packageName) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        protected PackageParser.ServiceIntentInfo[] newArray(int size) {
+            return new PackageParser.ServiceIntentInfo[size];
+        }
+
+        @Override
+        protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
+            if (!sUserManager.exists(userId)) return true;
+            PackageParser.Package p = filter.service.owner;
+            if (p != null) {
+                PackageSetting ps = (PackageSetting) p.mExtras;
+                if (ps != null) {
+                    // System apps are never considered stopped for purposes of
+                    // filtering, because there may be no way for the user to
+                    // actually re-launch them.
+                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
+                            && ps.getStopped(userId);
+                }
+            }
+            return false;
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                PackageParser.ServiceIntentInfo info) {
+            return packageName.equals(info.service.owner.packageName);
+        }
+
+        @Override
+        protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
+                int match, int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo) filter;
+            if (!sPackageManagerInternal.isEnabledAndMatches(info.service.info, mFlags, userId)) {
+                return null;
+            }
+            final PackageParser.Service service = info.service;
+            PackageSetting ps = (PackageSetting) service.owner.mExtras;
+            if (ps == null) {
+                return null;
+            }
+            final PackageUserState userState = ps.readUserState(userId);
+            ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
+                    userState, userId);
+            if (si == null) {
+                return null;
+            }
+            final boolean matchVisibleToInstantApp =
+                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            // throw out filters that aren't visible to ephemeral apps
+            if (matchVisibleToInstantApp
+                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+                return null;
+            }
+            // throw out ephemeral filters if we're not explicitly requesting them
+            if (!isInstantApp && userState.instantApp) {
+                return null;
+            }
+            // throw out instant app filters if updates are available; will trigger
+            // instant app resolution
+            if (userState.instantApp && ps.isUpdateAvailable()) {
+                return null;
+            }
+            final ResolveInfo res = new ResolveInfo();
+            res.serviceInfo = si;
+            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
+                res.filter = filter;
+            }
+            res.priority = info.getPriority();
+            res.preferredOrder = service.owner.mPreferredOrder;
+            res.match = match;
+            res.isDefault = info.hasDefault;
+            res.labelRes = info.labelRes;
+            res.nonLocalizedLabel = info.nonLocalizedLabel;
+            res.icon = info.icon;
+            res.system = res.serviceInfo.applicationInfo.isSystemApp();
+            return res;
+        }
+
+        @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
+        protected void dumpFilter(PrintWriter out, String prefix,
+                PackageParser.ServiceIntentInfo filter) {
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(filter.service)));
+            out.print(' ');
+            filter.service.printComponentShortName(out);
+            out.print(" filter ");
+            out.print(Integer.toHexString(System.identityHashCode(filter)));
+            if (filter.service.info.permission != null) {
+                out.print(" permission "); out.println(filter.service.info.permission);
+            } else {
+                out.println();
+            }
+        }
+
+        @Override
+        protected Object filterToLabel(PackageParser.ServiceIntentInfo filter) {
+            return filter.service;
+        }
+
+        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
+            final PackageParser.Service service = (PackageParser.Service) label;
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(service)));
+            out.print(' ');
+            service.printComponentShortName(out);
+            if (count > 1) {
+                out.print(" ("); out.print(count); out.print(" filters)");
+            }
+            out.println();
+        }
+
+        // Keys are String (activity class name), values are Activity.
+        private final ArrayMap<ComponentName, PackageParser.Service> mServices = new ArrayMap<>();
+        private int mFlags;
+    }
+
+    static final class InstantAppIntentResolver
+            extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter,
+            AuxiliaryResolveInfo.AuxiliaryFilter> {
+        /**
+         * The result that has the highest defined order. Ordering applies on a
+         * per-package basis. Mapping is from package name to Pair of order and
+         * EphemeralResolveInfo.
+         * <p>
+         * NOTE: This is implemented as a field variable for convenience and efficiency.
+         * By having a field variable, we're able to track filter ordering as soon as
+         * a non-zero order is defined. Otherwise, multiple loops across the result set
+         * would be needed to apply ordering. If the intent resolver becomes re-entrant,
+         * this needs to be contained entirely within {@link #filterResults}.
+         */
+        final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult =
+                new ArrayMap<>();
+
+        @Override
+        protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) {
+            return new AuxiliaryResolveInfo.AuxiliaryFilter[size];
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                AuxiliaryResolveInfo.AuxiliaryFilter responseObj) {
+            return true;
+        }
+
+        @Override
+        protected AuxiliaryResolveInfo.AuxiliaryFilter newResult(
+                AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            final String packageName = responseObj.resolveInfo.getPackageName();
+            final Integer order = responseObj.getOrder();
+            final Pair<Integer, InstantAppResolveInfo> lastOrderResult =
+                    mOrderResult.get(packageName);
+            // ordering is enabled and this item's order isn't high enough
+            if (lastOrderResult != null && lastOrderResult.first >= order) {
+                return null;
+            }
+            final InstantAppResolveInfo res = responseObj.resolveInfo;
+            if (order > 0) {
+                // non-zero order, enable ordering
+                mOrderResult.put(packageName, new Pair<>(order, res));
+            }
+            return responseObj;
+        }
+
+        @Override
+        protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
+            // only do work if ordering is enabled [most of the time it won't be]
+            if (mOrderResult.size() == 0) {
+                return;
+            }
+            int resultSize = results.size();
+            for (int i = 0; i < resultSize; i++) {
+                final InstantAppResolveInfo info = results.get(i).resolveInfo;
+                final String packageName = info.getPackageName();
+                final Pair<Integer, InstantAppResolveInfo> savedInfo =
+                        mOrderResult.get(packageName);
+                if (savedInfo == null) {
+                    // package doesn't having ordering
+                    continue;
+                }
+                if (savedInfo.second == info) {
+                    // circled back to the highest ordered item; remove from order list
+                    mOrderResult.remove(packageName);
+                    if (mOrderResult.size() == 0) {
+                        // no more ordered items
+                        break;
+                    }
+                    continue;
+                }
+                // item has a worse order, remove it from the result list
+                results.remove(i);
+                resultSize--;
+                i--;
+            }
+        }
+    }
+
+    /** Generic to create an {@link Iterator} for a data type */
+    static class IterGenerator<E> {
+        public Iterator<E> generate(ActivityIntentInfo info) {
+            return null;
+        }
+    }
+
+    /** Create an {@link Iterator} for intent actions */
+    static class ActionIterGenerator extends IterGenerator<String> {
+        @Override
+        public Iterator<String> generate(ActivityIntentInfo info) {
+            return info.actionsIterator();
+        }
+    }
+
+    /** Create an {@link Iterator} for intent categories */
+    static class CategoriesIterGenerator extends IterGenerator<String> {
+        @Override
+        public Iterator<String> generate(ActivityIntentInfo info) {
+            return info.categoriesIterator();
+        }
+    }
+
+    /** Create an {@link Iterator} for intent schemes */
+    static class SchemesIterGenerator extends IterGenerator<String> {
+        @Override
+        public Iterator<String> generate(ActivityIntentInfo info) {
+            return info.schemesIterator();
+        }
+    }
+
+    /** Create an {@link Iterator} for intent authorities */
+    static class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
+        @Override
+        public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) {
+            return info.authoritiesIterator();
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index f0807b9..72f11f7 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -34,6 +34,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.server.SystemService;
 
+import dalvik.system.BlockGuard;
 import dalvik.system.VMRuntime;
 
 import java.io.FileDescriptor;
@@ -239,6 +240,11 @@
             long[] ceDataInodes, String[] codePaths, PackageStats stats)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
+        if (codePaths != null) {
+            for (String codePath : codePaths) {
+                BlockGuard.getVmPolicy().onPathAccess(codePath);
+            }
+        }
         try {
             final long[] res = mInstalld.getAppSize(uuid, packageNames, userId, flags,
                     appId, ceDataInodes, codePaths);
@@ -296,6 +302,9 @@
             @Nullable String profileName, @Nullable String dexMetadataPath,
             @Nullable String compilationReason) throws InstallerException {
         assertValidInstructionSet(instructionSet);
+        BlockGuard.getVmPolicy().onPathAccess(apkPath);
+        BlockGuard.getVmPolicy().onPathAccess(outputPath);
+        BlockGuard.getVmPolicy().onPathAccess(dexMetadataPath);
         if (!checkBeforeRemote()) return;
         try {
             mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
@@ -319,6 +328,7 @@
     public boolean dumpProfiles(int uid, String packageName, String profileName, String codePath)
             throws InstallerException {
         if (!checkBeforeRemote()) return false;
+        BlockGuard.getVmPolicy().onPathAccess(codePath);
         try {
             return mInstalld.dumpProfiles(uid, packageName, profileName, codePath);
         } catch (Exception e) {
@@ -339,6 +349,8 @@
     public void idmap(String targetApkPath, String overlayApkPath, int uid)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(targetApkPath);
+        BlockGuard.getVmPolicy().onPathAccess(overlayApkPath);
         try {
             mInstalld.idmap(targetApkPath, overlayApkPath, uid);
         } catch (Exception e) {
@@ -348,6 +360,7 @@
 
     public void removeIdmap(String overlayApkPath) throws InstallerException {
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(overlayApkPath);
         try {
             mInstalld.removeIdmap(overlayApkPath);
         } catch (Exception e) {
@@ -358,6 +371,7 @@
     public void rmdex(String codePath, String instructionSet) throws InstallerException {
         assertValidInstructionSet(instructionSet);
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(codePath);
         try {
             mInstalld.rmdex(codePath, instructionSet);
         } catch (Exception e) {
@@ -367,6 +381,7 @@
 
     public void rmPackageDir(String packageDir) throws InstallerException {
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(packageDir);
         try {
             mInstalld.rmPackageDir(packageDir);
         } catch (Exception e) {
@@ -439,6 +454,7 @@
     public void linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32,
             int userId) throws InstallerException {
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(nativeLibPath32);
         try {
             mInstalld.linkNativeLibraryDirectory(uuid, packageName, nativeLibPath32, userId);
         } catch (Exception e) {
@@ -459,6 +475,8 @@
     public void linkFile(String relativePath, String fromBase, String toBase)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(fromBase);
+        BlockGuard.getVmPolicy().onPathAccess(toBase);
         try {
             mInstalld.linkFile(relativePath, fromBase, toBase);
         } catch (Exception e) {
@@ -469,6 +487,8 @@
     public void moveAb(String apkPath, String instructionSet, String outputPath)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(apkPath);
+        BlockGuard.getVmPolicy().onPathAccess(outputPath);
         try {
             mInstalld.moveAb(apkPath, instructionSet, outputPath);
         } catch (Exception e) {
@@ -479,6 +499,8 @@
     public void deleteOdex(String apkPath, String instructionSet, String outputPath)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(apkPath);
+        BlockGuard.getVmPolicy().onPathAccess(outputPath);
         try {
             mInstalld.deleteOdex(apkPath, instructionSet, outputPath);
         } catch (Exception e) {
@@ -489,6 +511,7 @@
     public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(filePath);
         try {
             mInstalld.installApkVerity(filePath, verityInput, contentSize);
         } catch (Exception e) {
@@ -499,6 +522,7 @@
     public void assertFsverityRootHashMatches(String filePath, @NonNull byte[] expectedHash)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
+        BlockGuard.getVmPolicy().onPathAccess(filePath);
         try {
             mInstalld.assertFsverityRootHashMatches(filePath, expectedHash);
         } catch (Exception e) {
@@ -512,6 +536,7 @@
             assertValidInstructionSet(isas[i]);
         }
         if (!checkBeforeRemote()) return false;
+        BlockGuard.getVmPolicy().onPathAccess(apkPath);
         try {
             return mInstalld.reconcileSecondaryDexFile(apkPath, packageName, uid, isas,
                     volumeUuid, flags);
@@ -523,6 +548,7 @@
     public byte[] hashSecondaryDexFile(String dexPath, String packageName, int uid,
             @Nullable String volumeUuid, int flags) throws InstallerException {
         if (!checkBeforeRemote()) return new byte[0];
+        BlockGuard.getVmPolicy().onPathAccess(dexPath);
         try {
             return mInstalld.hashSecondaryDexFile(dexPath, packageName, uid, volumeUuid, flags);
         } catch (Exception e) {
@@ -571,6 +597,8 @@
     public boolean prepareAppProfile(String pkg, @UserIdInt int userId, @AppIdInt int appId,
             String profileName, String codePath, String dexMetadataPath) throws InstallerException {
         if (!checkBeforeRemote()) return false;
+        BlockGuard.getVmPolicy().onPathAccess(codePath);
+        BlockGuard.getVmPolicy().onPathAccess(dexMetadataPath);
         try {
             return mInstalld.prepareAppProfile(pkg, userId, appId, profileName, codePath,
                     dexMetadataPath);
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index fde13ac..06f67cd 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -134,6 +134,7 @@
         mCookiePersistence = new CookiePersistence(BackgroundThread.getHandler().getLooper());
     }
 
+    @GuardedBy("mService.mPackages")
     public byte[] getInstantAppCookieLPw(@NonNull String packageName,
             @UserIdInt int userId) {
         // Only installed packages can get their own cookie
@@ -157,6 +158,7 @@
         return null;
     }
 
+    @GuardedBy("mService.mPackages")
     public boolean setInstantAppCookieLPw(@NonNull String packageName,
             @Nullable byte[] cookie, @UserIdInt int userId) {
         if (cookie != null && cookie.length > 0) {
@@ -249,6 +251,7 @@
 
     }
 
+    @GuardedBy("mService.mPackages")
     public @Nullable List<InstantAppInfo> getInstantAppsLPr(@UserIdInt int userId) {
         List<InstantAppInfo> installedApps = getInstalledInstantApplicationsLPr(userId);
         List<InstantAppInfo> uninstalledApps = getUninstalledInstantApplicationsLPr(userId);
@@ -261,6 +264,7 @@
         return uninstalledApps;
     }
 
+    @GuardedBy("mService.mPackages")
     public void onPackageInstalledLPw(@NonNull PackageParser.Package pkg, @NonNull int[] userIds) {
         PackageSetting ps = (PackageSetting) pkg.mExtras;
         if (ps == null) {
@@ -331,6 +335,7 @@
         }
     }
 
+    @GuardedBy("mService.mPackages")
     public void onPackageUninstalledLPw(@NonNull PackageParser.Package pkg,
             @NonNull int[] userIds) {
         PackageSetting ps = (PackageSetting) pkg.mExtras;
@@ -356,6 +361,7 @@
         }
     }
 
+    @GuardedBy("mService.mPackages")
     public void onUserRemovedLPw(int userId) {
         if (mUninstalledInstantApps != null) {
             mUninstalledInstantApps.remove(userId);
@@ -394,6 +400,7 @@
         return instantGrantList.get(instantAppId);
     }
 
+    @GuardedBy("mService.mPackages")
     public void grantInstantAccessLPw(@UserIdInt int userId, @Nullable Intent intent,
             int targetAppId, int instantAppId) {
         if (mInstalledInstantAppUids == null) {
@@ -428,6 +435,7 @@
         instantGrantList.put(instantAppId, true /*granted*/);
     }
 
+    @GuardedBy("mService.mPackages")
     public void addInstantAppLPw(@UserIdInt int userId, int instantAppId) {
         if (mInstalledInstantAppUids == null) {
             mInstalledInstantAppUids = new SparseArray<>();
@@ -440,6 +448,7 @@
         instantAppList.put(instantAppId, true /*installed*/);
     }
 
+    @GuardedBy("mService.mPackages")
     private void removeInstantAppLPw(@UserIdInt int userId, int instantAppId) {
         // remove from the installed list
         if (mInstalledInstantAppUids == null) {
@@ -465,6 +474,7 @@
         }
     }
 
+    @GuardedBy("mService.mPackages")
     private void removeAppLPw(@UserIdInt int userId, int targetAppId) {
         // remove from the installed list
         if (mInstantGrants == null) {
@@ -477,6 +487,7 @@
         targetAppList.delete(targetAppId);
     }
 
+    @GuardedBy("mService.mPackages")
     private void addUninstalledInstantAppLPw(@NonNull PackageParser.Package pkg,
             @UserIdInt int userId) {
         InstantAppInfo uninstalledApp = createInstantAppInfoForPackage(
@@ -531,11 +542,13 @@
         }
     }
 
+    @GuardedBy("mService.mPackages")
     boolean hasInstantApplicationMetadataLPr(String packageName, int userId) {
         return hasUninstalledInstantAppStateLPr(packageName, userId)
                 || hasInstantAppMetadataLPr(packageName, userId);
     }
 
+    @GuardedBy("mService.mPackages")
     public void deleteInstantApplicationMetadataLPw(@NonNull String packageName,
             @UserIdInt int userId) {
         removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) ->
@@ -552,6 +565,7 @@
         }
     }
 
+    @GuardedBy("mService.mPackages")
     private void removeUninstalledInstantAppStateLPw(
             @NonNull Predicate<UninstalledInstantAppState> criteria, @UserIdInt int userId) {
         if (mUninstalledInstantApps == null) {
@@ -579,6 +593,7 @@
         }
     }
 
+    @GuardedBy("mService.mPackages")
     private boolean hasUninstalledInstantAppStateLPr(String packageName, @UserIdInt int userId) {
         if (mUninstalledInstantApps == null) {
             return false;
@@ -797,6 +812,7 @@
         return false;
     }
 
+    @GuardedBy("mService.mPackages")
     private @Nullable List<InstantAppInfo> getInstalledInstantApplicationsLPr(
             @UserIdInt int userId) {
         List<InstantAppInfo> result = null;
@@ -851,6 +867,7 @@
         }
     }
 
+    @GuardedBy("mService.mPackages")
     private @Nullable List<InstantAppInfo> getUninstalledInstantApplicationsLPr(
             @UserIdInt int userId) {
         List<UninstalledInstantAppState> uninstalledAppStates =
@@ -923,6 +940,7 @@
         return uninstalledAppState.mInstantAppInfo;
     }
 
+    @GuardedBy("mService.mPackages")
     private @Nullable List<UninstalledInstantAppState> getUninstalledInstantAppStatesLPr(
             @UserIdInt int userId) {
         List<UninstalledInstantAppState> uninstalledAppStates = null;
@@ -1158,15 +1176,13 @@
     private final class CookiePersistence extends Handler {
         private static final long PERSIST_COOKIE_DELAY_MILLIS = 1000L; /* one second */
 
-        // In case you wonder why we stash the cookies aside, we use
-        // the user id for the message id and the package for the payload.
-        // Handler allows removing messages by id and tag where the
-        // tag is compared using ==. So to allow cancelling the
-        // pending persistence for an app under a given user we use
-        // the fact that package are cached by the system so the ==
-        // comparison would match and we end up with a way to cancel
-        // persisting the cookie for a user and package.
-        private final SparseArray<ArrayMap<PackageParser.Package, SomeArgs>> mPendingPersistCookies
+        // The cookies are cached per package name per user-id in this sparse
+        // array. The caching is so that pending persistence can be canceled within
+        // a short interval. To ensure we still return pending persist cookies
+        // for a package that uninstalled and reinstalled while the persistence
+        // was still pending, we use the package name as a key for
+        // mPendingPersistCookies, since that stays stable across reinstalls.
+        private final SparseArray<ArrayMap<String, SomeArgs>> mPendingPersistCookies
                 = new SparseArray<>();
 
         public CookiePersistence(Looper looper) {
@@ -1196,10 +1212,10 @@
 
         public @Nullable byte[] getPendingPersistCookieLPr(@NonNull PackageParser.Package pkg,
                 @UserIdInt int userId) {
-            ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser =
+            ArrayMap<String, SomeArgs> pendingWorkForUser =
                     mPendingPersistCookies.get(userId);
             if (pendingWorkForUser != null) {
-                SomeArgs state = pendingWorkForUser.get(pkg);
+                SomeArgs state = pendingWorkForUser.get(pkg.packageName);
                 if (state != null) {
                     return (byte[]) state.arg1;
                 }
@@ -1219,7 +1235,7 @@
         private void addPendingPersistCookieLPw(@UserIdInt int userId,
                 @NonNull PackageParser.Package pkg, @NonNull byte[] cookie,
                 @NonNull File cookieFile) {
-            ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser =
+            ArrayMap<String, SomeArgs> pendingWorkForUser =
                     mPendingPersistCookies.get(userId);
             if (pendingWorkForUser == null) {
                 pendingWorkForUser = new ArrayMap<>();
@@ -1228,16 +1244,16 @@
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = cookie;
             args.arg2 = cookieFile;
-            pendingWorkForUser.put(pkg, args);
+            pendingWorkForUser.put(pkg.packageName, args);
         }
 
         private SomeArgs removePendingPersistCookieLPr(@NonNull PackageParser.Package pkg,
                 @UserIdInt int userId) {
-            ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser =
+            ArrayMap<String, SomeArgs> pendingWorkForUser =
                     mPendingPersistCookies.get(userId);
             SomeArgs state = null;
             if (pendingWorkForUser != null) {
-                state = pendingWorkForUser.remove(pkg);
+                state = pendingWorkForUser.remove(pkg.packageName);
                 if (pendingWorkForUser.isEmpty()) {
                     mPendingPersistCookies.remove(userId);
                 }
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index 19cefb8..9bd3924 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -36,9 +36,9 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
-import android.content.pm.InstantAppRequest;
 import android.content.pm.AuxiliaryResolveInfo;
 import android.content.pm.InstantAppIntentFilter;
+import android.content.pm.InstantAppRequest;
 import android.content.pm.InstantAppResolveInfo;
 import android.content.pm.InstantAppResolveInfo.InstantAppDigest;
 import android.metrics.LogMaker;
@@ -458,8 +458,8 @@
             }
             return Collections.emptyList();
         }
-        final PackageManagerService.InstantAppIntentResolver instantAppResolver =
-                new PackageManagerService.InstantAppIntentResolver();
+        final ComponentResolver.InstantAppIntentResolver instantAppResolver =
+                new ComponentResolver.InstantAppIntentResolver();
         for (int j = instantAppFilters.size() - 1; j >= 0; --j) {
             final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j);
             final List<IntentFilter> splitFilters = instantAppFilter.getFilters();
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 320affb..cf47d4e 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -365,10 +365,12 @@
                 continue;
             }
 
-            // If the path is in /system, /vendor or /product, ignore. It will have been
-            // ota-dexopted into /data/ota and moved into the dalvik-cache already.
-            if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")
-                    || pkg.codePath.startsWith("/product")) {
+            // If the path is in /system, /vendor, /product or /product_services, ignore. It will
+            // have been ota-dexopted into /data/ota and moved into the dalvik-cache already.
+            if (pkg.codePath.startsWith("/system")
+                    || pkg.codePath.startsWith("/vendor")
+                    || pkg.codePath.startsWith("/product")
+                    || pkg.codePath.startsWith("/product_services")) {
                 continue;
             }
 
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index b0be4a9..95c70d5 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -34,6 +34,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.pm.Installer.InstallerException;
+import com.android.server.pm.dex.ArtManagerService;
 import com.android.server.pm.dex.DexManager;
 import com.android.server.pm.dex.DexoptOptions;
 import com.android.server.pm.dex.DexoptUtils;
@@ -289,7 +290,8 @@
             mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags,
                     compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo,
                     false /* downgrade*/, pkg.applicationInfo.targetSdkVersion,
-                    profileName, dexMetadataPath, getReasonName(compilationReason));
+                    profileName, dexMetadataPath,
+                    getAugmentedReasonName(compilationReason, dexMetadataPath != null));
 
             if (packageStats != null) {
                 long endTime = System.currentTimeMillis();
@@ -302,6 +304,12 @@
         }
     }
 
+    private String getAugmentedReasonName(int compilationReason, boolean useDexMetadata) {
+        String annotation = useDexMetadata
+                ? ArtManagerService.DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : "";
+        return getReasonName(compilationReason) + annotation;
+    }
+
     /**
      * Performs dexopt on the secondary dex {@code path} belonging to the app {@code info}.
      *
@@ -409,7 +417,7 @@
                 // TODO(calin): maybe add a separate call.
                 mInstaller.dexopt(path, info.uid, info.packageName, isa, /*dexoptNeeded*/ 0,
                         /*oatDir*/ null, dexoptFlags,
-                        compilerFilter, info.volumeUuid, classLoaderContext, info.seInfoUser,
+                        compilerFilter, info.volumeUuid, classLoaderContext, info.seInfo,
                         options.isDowngrade(), info.targetSdkVersion, /*profileName*/ null,
                         /*dexMetadataPath*/ null, getReasonName(reason));
             }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index fa934fe..d305032 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -685,13 +685,14 @@
                 // inserted above to hold the session active.
                 try {
                     final Int64Ref last = new Int64Ref(0);
-                    FileUtils.copy(incomingFd.getFileDescriptor(), targetFd, (long progress) -> {
-                        if (params.sizeBytes > 0) {
-                            final long delta = progress - last.value;
-                            last.value = progress;
-                            addClientProgress((float) delta / (float) params.sizeBytes);
-                        }
-                    }, null, lengthBytes);
+                    FileUtils.copy(incomingFd.getFileDescriptor(), targetFd, lengthBytes, null,
+                            Runnable::run, (long progress) -> {
+                                if (params.sizeBytes > 0) {
+                                    final long delta = progress - last.value;
+                                    last.value = progress;
+                                    addClientProgress((float) delta / (float) params.sizeBytes);
+                                }
+                            });
                 } finally {
                     IoUtils.closeQuietly(targetFd);
                     IoUtils.closeQuietly(incomingFd);
@@ -930,6 +931,10 @@
     @GuardedBy("mLock")
     private void commitLocked()
             throws PackageManagerException {
+        if (mRelinquished) {
+            Slog.d(TAG, "Ignoring commit after previous commit relinquished control");
+            return;
+        }
         if (mDestroyed) {
             throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
         }
@@ -942,10 +947,10 @@
         Preconditions.checkNotNull(mResolvedBaseFile);
 
         if (needToAskForPermissionsLocked()) {
-            // User needs to accept permissions; give installer an intent they
-            // can use to involve user.
-            final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
-            intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
+            // User needs to confirm installation; give installer an intent they can use to involve
+            // user.
+            final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
+            intent.setPackage(mPm.getPackageInstallerPackageName());
             intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
             try {
                 mRemoteObserver.onUserActionRequired(intent);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c536e4d..2925523 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -24,6 +24,7 @@
 import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
 import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
+import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
 import static android.content.Intent.ACTION_MAIN;
 import static android.content.Intent.CATEGORY_DEFAULT;
 import static android.content.Intent.CATEGORY_HOME;
@@ -44,7 +45,6 @@
 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
 import static android.content.pm.PackageManager.INSTALL_EXTERNAL;
 import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
-import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID;
@@ -90,10 +90,12 @@
 import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDWR;
+
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
 import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
 import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
+import static com.android.server.pm.ComponentResolver.RESOLVE_PRIORITY_SORTER;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
@@ -157,7 +159,6 @@
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.InstantAppRequest;
-import android.content.pm.InstantAppResolveInfo;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.KeySet;
@@ -169,14 +170,13 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageManagerInternal.CheckPermissionDelegate;
 import android.content.pm.PackageManagerInternal.PackageListObserver;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.ActivityIntentInfo;
-import android.content.pm.PackageParser.Package;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.PackageParser.ParseFlags;
-import android.content.pm.PackageParser.ServiceIntentInfo;
 import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
 import android.content.pm.PackageStats;
@@ -253,6 +253,7 @@
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.ExceptionUtils;
+import android.util.IntArray;
 import android.util.Log;
 import android.util.LogPrinter;
 import android.util.LongSparseArray;
@@ -293,7 +294,6 @@
 import com.android.server.DeviceIdleController;
 import com.android.server.EventLogTags;
 import com.android.server.FgThread;
-import com.android.server.IntentResolver;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
 import com.android.server.ServiceThread;
@@ -321,6 +321,11 @@
 import com.android.server.storage.DeviceStorageMonitorInternal;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
+import dalvik.system.CloseGuard;
+import dalvik.system.VMRuntime;
+
+import libcore.io.IoUtils;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -365,10 +370,6 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Predicate;
 
-import dalvik.system.CloseGuard;
-import dalvik.system.VMRuntime;
-import libcore.io.IoUtils;
-
 /**
  * Keep track of all those APKs everywhere.
  * <p>
@@ -413,12 +414,10 @@
     public static final boolean DEBUG_INSTALL = false;
     public static final boolean DEBUG_REMOVE = false;
     private static final boolean DEBUG_BROADCASTS = false;
-    private static final boolean DEBUG_SHOW_INFO = false;
     private static final boolean DEBUG_PACKAGE_INFO = false;
     private static final boolean DEBUG_INTENT_MATCHING = false;
     public static final boolean DEBUG_PACKAGE_SCANNING = false;
     private static final boolean DEBUG_VERIFY = false;
-    private static final boolean DEBUG_FILTERS = false;
     public static final boolean DEBUG_PERMISSIONS = false;
     private static final boolean DEBUG_SHARED_LIBRARIES = false;
     public static final boolean DEBUG_COMPRESSION = Build.IS_DEBUGGABLE;
@@ -447,27 +446,27 @@
     private static final int SHELL_UID = Process.SHELL_UID;
     private static final int SE_UID = Process.SE_UID;
 
-    static final int SCAN_NO_DEX = 1<<0;
-    static final int SCAN_UPDATE_SIGNATURE = 1<<1;
-    static final int SCAN_NEW_INSTALL = 1<<2;
-    static final int SCAN_UPDATE_TIME = 1<<3;
-    static final int SCAN_BOOTING = 1<<4;
-    static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<6;
-    static final int SCAN_REQUIRE_KNOWN = 1<<7;
-    static final int SCAN_MOVE = 1<<8;
-    static final int SCAN_INITIAL = 1<<9;
-    static final int SCAN_CHECK_ONLY = 1<<10;
-    static final int SCAN_DONT_KILL_APP = 1<<11;
-    static final int SCAN_IGNORE_FROZEN = 1<<12;
-    static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1<<13;
-    static final int SCAN_AS_INSTANT_APP = 1<<14;
-    static final int SCAN_AS_FULL_APP = 1<<15;
-    static final int SCAN_AS_VIRTUAL_PRELOAD = 1<<16;
-    static final int SCAN_AS_SYSTEM = 1<<17;
-    static final int SCAN_AS_PRIVILEGED = 1<<18;
-    static final int SCAN_AS_OEM = 1<<19;
-    static final int SCAN_AS_VENDOR = 1<<20;
-    static final int SCAN_AS_PRODUCT = 1<<21;
+    static final int SCAN_NO_DEX = 1 << 0;
+    static final int SCAN_UPDATE_SIGNATURE = 1 << 1;
+    static final int SCAN_NEW_INSTALL = 1 << 2;
+    static final int SCAN_UPDATE_TIME = 1 << 3;
+    static final int SCAN_BOOTING = 1 << 4;
+    static final int SCAN_REQUIRE_KNOWN = 1 << 7;
+    static final int SCAN_MOVE = 1 << 8;
+    static final int SCAN_INITIAL = 1 << 9;
+    static final int SCAN_CHECK_ONLY = 1 << 10;
+    static final int SCAN_DONT_KILL_APP = 1 << 11;
+    static final int SCAN_IGNORE_FROZEN = 1 << 12;
+    static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1 << 13;
+    static final int SCAN_AS_INSTANT_APP = 1 << 14;
+    static final int SCAN_AS_FULL_APP = 1 << 15;
+    static final int SCAN_AS_VIRTUAL_PRELOAD = 1 << 16;
+    static final int SCAN_AS_SYSTEM = 1 << 17;
+    static final int SCAN_AS_PRIVILEGED = 1 << 18;
+    static final int SCAN_AS_OEM = 1 << 19;
+    static final int SCAN_AS_VENDOR = 1 << 20;
+    static final int SCAN_AS_PRODUCT = 1 << 21;
+    static final int SCAN_AS_PRODUCT_SERVICES = 1 << 22;
 
     @IntDef(flag = true, prefix = { "SCAN_" }, value = {
             SCAN_NO_DEX,
@@ -475,7 +474,6 @@
             SCAN_NEW_INSTALL,
             SCAN_UPDATE_TIME,
             SCAN_BOOTING,
-            SCAN_DELETE_DATA_ON_FAILURES,
             SCAN_REQUIRE_KNOWN,
             SCAN_MOVE,
             SCAN_INITIAL,
@@ -574,6 +572,8 @@
 
     private static final String PRODUCT_OVERLAY_DIR = "/product/overlay";
 
+    private static final String PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
+
     /** Canonical intent used to identify what counts as a "web browser" app */
     private static final Intent sBrowserIntent;
     static {
@@ -584,18 +584,6 @@
         sBrowserIntent.addFlags(Intent.FLAG_IGNORE_EPHEMERAL);
     }
 
-    /**
-     * The set of all protected actions [i.e. those actions for which a high priority
-     * intent filter is disallowed].
-     */
-    private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>();
-    static {
-        PROTECTED_ACTIONS.add(Intent.ACTION_SEND);
-        PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO);
-        PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE);
-        PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
-    }
-
     // Compilation reasons.
     public static final int REASON_UNKNOWN = -1;
     public static final int REASON_FIRST_BOOT = 0;
@@ -697,20 +685,6 @@
      * are package location.
      */
     final private ArrayMap<String, File> mExpectingBetter = new ArrayMap<>();
-    /**
-     * Tracks high priority intent filters for protected actions. During boot, certain
-     * filter actions are protected and should never be allowed to have a high priority
-     * intent filter for them. However, there is one, and only one exception -- the
-     * setup wizard. It must be able to define a high priority intent filter for these
-     * actions to ensure there are no escapes from the wizard. We need to delay processing
-     * of these during boot as we need to look at all of the system packages in order
-     * to know which component is the setup wizard.
-     */
-    private final List<PackageParser.ActivityIntentInfo> mProtectedFilters = new ArrayList<>();
-    /**
-     * Whether or not processing protected filters should be deferred.
-     */
-    private boolean mDeferProtectedFilters = true;
 
     /**
      * Tracks existing system packages prior to receiving an OTA. Keys are package name.
@@ -908,24 +882,6 @@
     final ArrayMap<String, LongSparseArray<SharedLibraryEntry>> mStaticLibsByDeclaringPackage =
             new ArrayMap<>();
 
-    // All available activities, for your resolving pleasure.
-    final ActivityIntentResolver mActivities =
-            new ActivityIntentResolver();
-
-    // All available receivers, for your resolving pleasure.
-    final ActivityIntentResolver mReceivers =
-            new ActivityIntentResolver();
-
-    // All available services, for your resolving pleasure.
-    final ServiceIntentResolver mServices = new ServiceIntentResolver();
-
-    // All available providers, for your resolving pleasure.
-    final ProviderIntentResolver mProviders = new ProviderIntentResolver();
-
-    // Mapping from provider base names (first directory in content URI codePath)
-    // to the provider information.
-    final ArrayMap<String, PackageParser.Provider> mProvidersByAuthority = new ArrayMap<>();
-
     // Mapping from instrumentation class names to info about them.
     final ArrayMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
             new ArrayMap<>();
@@ -956,7 +912,7 @@
     private final OnPermissionChangeListeners mOnPermissionChangeListeners;
 
     // Cache of users who need badging.
-    SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray();
+    private final SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray();
 
     /** Token for keys in mPendingVerification. */
     private int mPendingVerificationToken = 0;
@@ -996,6 +952,7 @@
     final DefaultPermissionGrantPolicy mDefaultPermissionPolicy;
     private final PermissionManagerInternal mPermissionManager;
 
+    private final ComponentResolver mComponentResolver;
     // List of packages names to keep cached, even if they are uninstalled for all users
     private List<String> mKeepUninstalledPackages;
 
@@ -1031,6 +988,9 @@
         void receiveVerificationResponse(int verificationId);
     }
 
+    @GuardedBy("mPackages")
+    private CheckPermissionDelegate mCheckPermissionDelegate;
+
     private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> {
         private Context mContext;
         private ComponentName mIntentFilterVerifierComponent;
@@ -1387,6 +1347,7 @@
     final @Nullable String mRequiredVerifierPackage;
     final @NonNull String mRequiredInstallerPackage;
     final @NonNull String mRequiredUninstallerPackage;
+    final String mRequiredPermissionControllerPackage;
     final @Nullable String mSetupWizardPackage;
     final @Nullable String mStorageManagerPackage;
     final @Nullable String mSystemTextClassifierPackage;
@@ -2407,6 +2368,9 @@
                     PackageManagerInternal.class, new PackageManagerInternalImpl());
             sUserManager = new UserManagerService(context, this,
                     new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
+            mComponentResolver = new ComponentResolver(sUserManager,
+                    LocalServices.getService(PackageManagerInternal.class),
+                    mPackages);
             mPermissionManager = PermissionManagerService.create(context,
                     new DefaultPermissionGrantedCallback() {
                         @Override
@@ -2417,7 +2381,8 @@
                         }
                     }, mPackages /*externalLock*/);
             mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
-            mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);
+            mSettings = new Settings(Environment.getDataDirectory(),
+                    mPermissionManager.getPermissionSettings(), mPackages);
         }
         }
         mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
@@ -2515,7 +2480,7 @@
                 }
             }
 
-            if (mFirstBoot) {
+            if (!mOnlyCore && mFirstBoot) {
                 requestCopyPreoptedFiles();
             }
 
@@ -2561,6 +2526,8 @@
 
             mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
 
+            int preUpgradeSdkVersion = ver.sdkVersion;
+
             // save off the names of pre-existing system packages prior to scanning; we don't
             // want to automatically grant runtime permissions for new system apps
             if (mPromoteSystemApps) {
@@ -2583,9 +2550,10 @@
                 scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
             }
 
-            // Collect vendor/product overlay packages. (Do this before scanning any apps.)
-            // For security and version matching reason, only consider
-            // overlay packages if they reside in the right directory.
+            // Collect vendor/product/product_services overlay packages. (Do this before scanning
+            // any apps.)
+            // For security and version matching reason, only consider overlay packages if they
+            // reside in the right directory.
             scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                     mDefParseFlags
                     | PackageParser.PARSE_IS_SYSTEM_DIR,
@@ -2600,6 +2568,13 @@
                     | SCAN_AS_SYSTEM
                     | SCAN_AS_PRODUCT,
                     0);
+            scanDirTracedLI(new File(PRODUCT_SERVICES_OVERLAY_DIR),
+                    mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
+                    scanFlags
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_PRODUCT_SERVICES,
+                    0);
 
             mParallelPackageParserCallback.findStaticOverlayPackages();
 
@@ -2711,7 +2686,7 @@
                     | SCAN_AS_OEM,
                     0);
 
-            // Collected privileged product packages.
+            // Collected privileged /product packages.
             File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
             try {
                 privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
@@ -2727,7 +2702,7 @@
                     | SCAN_AS_PRIVILEGED,
                     0);
 
-            // Collect ordinary product packages.
+            // Collect ordinary /product packages.
             File productAppDir = new File(Environment.getProductDirectory(), "app");
             try {
                 productAppDir = productAppDir.getCanonicalFile();
@@ -2742,6 +2717,39 @@
                     | SCAN_AS_PRODUCT,
                     0);
 
+            // Collected privileged /product_services packages.
+            File privilegedProductServicesAppDir =
+                    new File(Environment.getProductServicesDirectory(), "priv-app");
+            try {
+                privilegedProductServicesAppDir =
+                        privilegedProductServicesAppDir.getCanonicalFile();
+            } catch (IOException e) {
+                // failed to look up canonical path, continue with original one
+            }
+            scanDirTracedLI(privilegedProductServicesAppDir,
+                    mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
+                    scanFlags
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_PRODUCT_SERVICES
+                    | SCAN_AS_PRIVILEGED,
+                    0);
+
+            // Collect ordinary /product_services packages.
+            File productServicesAppDir = new File(Environment.getProductServicesDirectory(), "app");
+            try {
+                productServicesAppDir = productServicesAppDir.getCanonicalFile();
+            } catch (IOException e) {
+                // failed to look up canonical path, continue with original one
+            }
+            scanDirTracedLI(productServicesAppDir,
+                    mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
+                    scanFlags
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_PRODUCT_SERVICES,
+                    0);
+
             // Prune any system packages that no longer exist.
             final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
             // Stub packages must either be replaced with full versions in the /data
@@ -2946,6 +2954,23 @@
                                     scanFlags
                                     | SCAN_AS_SYSTEM
                                     | SCAN_AS_PRODUCT;
+                        } else if (FileUtils.contains(privilegedProductServicesAppDir, scanFile)) {
+                            reparseFlags =
+                                    mDefParseFlags |
+                                    PackageParser.PARSE_IS_SYSTEM_DIR;
+                            rescanFlags =
+                                    scanFlags
+                                    | SCAN_AS_SYSTEM
+                                    | SCAN_AS_PRODUCT_SERVICES
+                                    | SCAN_AS_PRIVILEGED;
+                        } else if (FileUtils.contains(productServicesAppDir, scanFile)) {
+                            reparseFlags =
+                                    mDefParseFlags |
+                                    PackageParser.PARSE_IS_SYSTEM_DIR;
+                            rescanFlags =
+                                    scanFlags
+                                    | SCAN_AS_SYSTEM
+                                    | SCAN_AS_PRODUCT_SERVICES;
                         } else {
                             Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                             continue;
@@ -2989,38 +3014,10 @@
             // Resolve protected action filters. Only the setup wizard is allowed to
             // have a high priority filter for these actions.
             mSetupWizardPackage = getSetupWizardPackageName();
-            if (mProtectedFilters.size() > 0) {
-                if (DEBUG_FILTERS && mSetupWizardPackage == null) {
-                    Slog.i(TAG, "No setup wizard;"
-                        + " All protected intents capped to priority 0");
-                }
-                for (ActivityIntentInfo filter : mProtectedFilters) {
-                    if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
-                        if (DEBUG_FILTERS) {
-                            Slog.i(TAG, "Found setup wizard;"
-                                + " allow priority " + filter.getPriority() + ";"
-                                + " package: " + filter.activity.info.packageName
-                                + " activity: " + filter.activity.className
-                                + " priority: " + filter.getPriority());
-                        }
-                        // skip setup wizard; allow it to keep the high priority filter
-                        continue;
-                    }
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Protected action; cap priority to 0;"
-                                + " package: " + filter.activity.info.packageName
-                                + " activity: " + filter.activity.className
-                                + " origPrio: " + filter.getPriority());
-                    }
-                    filter.setPriority(0);
-                }
-            }
+            mComponentResolver.fixProtectedFilterPriorities();
 
             mSystemTextClassifierPackage = getSystemTextClassifierPackageName();
 
-            mDeferProtectedFilters = false;
-            mProtectedFilters.clear();
-
             // Now that we know all of the shared libraries, update all clients to have
             // the correct library paths.
             updateAllSharedLibrariesLPw(null);
@@ -3078,7 +3075,7 @@
             // all defined users.
             if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
                 for (UserInfo user : sUserManager.getUsers(true)) {
-                    mSettings.applyDefaultPreferredAppsLPw(this, user.id);
+                    mSettings.applyDefaultPreferredAppsLPw(user.id);
                     applyFactoryDefaultBrowserLPw(user.id);
                     primeDomainVerificationsLPw(user.id);
                 }
@@ -3154,6 +3151,58 @@
 
             checkDefaultBrowser();
 
+            // If a granted permission is split, all new permissions should be granted too
+            if (mIsUpgrade) {
+                final int callingUid = getCallingUid();
+
+                final int numSplitPerms = PackageParser.SPLIT_PERMISSIONS.length;
+                for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
+                    final PackageParser.SplitPermissionInfo splitPerm =
+                            PackageParser.SPLIT_PERMISSIONS[splitPermNum];
+                    final String rootPerm = splitPerm.rootPerm;
+
+                    if (preUpgradeSdkVersion >= splitPerm.targetSdk) {
+                        continue;
+                    }
+
+                    final int numPackages = mPackages.size();
+                    for (int packageNum = 0; packageNum < numPackages; packageNum++) {
+                        final PackageParser.Package pkg = mPackages.valueAt(packageNum);
+
+                        if (pkg.applicationInfo.targetSdkVersion >= splitPerm.targetSdk
+                                || !pkg.requestedPermissions.contains(rootPerm)) {
+                            continue;
+                        }
+
+                        final int userId = UserHandle.getUserId(pkg.applicationInfo.uid);
+                        final String pkgName = pkg.packageName;
+
+                        if (checkPermission(rootPerm, pkgName, userId) == PERMISSION_DENIED) {
+                            continue;
+                        }
+
+                        final String[] newPerms = splitPerm.newPerms;
+
+                        final int numNewPerms = newPerms.length;
+                        for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
+                            final String newPerm = newPerms[newPermNum];
+                            if (checkPermission(newPerm, pkgName, userId) == PERMISSION_GRANTED) {
+                                continue;
+                            }
+
+                            if (DEBUG_PERMISSIONS) {
+                                Slog.v(TAG, "Granting " + newPerm + " to " + pkgName
+                                        + " as the root permission " + rootPerm
+                                        + " is already granted");
+                            }
+
+                            mPermissionManager.grantRuntimePermission(newPerm, pkgName, true,
+                                    callingUid, userId, null);
+                        }
+                    }
+                }
+            }
+
             // clear only after permissions and other defaults have been updated
             mExistingSystemPackages.clear();
             mPromoteSystemApps = false;
@@ -3185,6 +3234,7 @@
                 mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                         PackageManager.SYSTEM_SHARED_LIBRARY_SHARED,
                         SharedLibraryInfo.VERSION_UNDEFINED);
+                mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();
             } else {
                 mRequiredVerifierPackage = null;
                 mRequiredInstallerPackage = null;
@@ -3193,6 +3243,7 @@
                 mIntentFilterVerifier = null;
                 mServicesSystemSharedLibraryPackageName = null;
                 mSharedSystemSharedLibraryPackageName = null;
+                mRequiredPermissionControllerPackage = null;
             }
 
             mInstallerService = new PackageInstallerService(context, this);
@@ -3383,6 +3434,7 @@
         return dstCodePath;
     }
 
+    @GuardedBy("mPackages")
     private void updateInstantAppInstallerLocked(String modifiedPackage) {
         // we're only interested in updating the installer appliction when 1) it's not
         // already set or 2) the modified package is the installer
@@ -3539,6 +3591,25 @@
         return resolveInfo.getComponentInfo().packageName;
     }
 
+    private @NonNull String getRequiredPermissionControllerLPr() {
+        final Intent intent = new Intent(Intent.ACTION_MANAGE_PERMISSIONS);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+
+        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
+        if (matches.size() == 1) {
+            ResolveInfo resolveInfo = matches.get(0);
+            if (!resolveInfo.activityInfo.applicationInfo.isPrivilegedApp()) {
+                throw new RuntimeException("The permissions manager must be a privileged app");
+            }
+            return matches.get(0).getComponentInfo().packageName;
+        } else {
+            throw new RuntimeException("There must be exactly one permissions manager; found "
+                    + matches);
+        }
+    }
+
     private @NonNull ComponentName getIntentFilterVerifierComponentNameLPr() {
         final Intent intent = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
 
@@ -3637,6 +3708,7 @@
         return null;
     }
 
+    @GuardedBy("mPackages")
     private @Nullable ActivityInfo getInstantAppInstallerLPr() {
         String[] orderedActions = Build.IS_ENG
                 ? new String[]{
@@ -3703,6 +3775,7 @@
         return matches.get(0).getComponentInfo().getComponentName();
     }
 
+    @GuardedBy("mPackages")
     private void primeDomainVerificationsLPw(int userId) {
         if (DEBUG_DOMAIN_VERIFICATION) {
             Slog.d(TAG, "Priming domain verifications in user " + userId);
@@ -3756,6 +3829,7 @@
         scheduleWriteSettingsLocked();
     }
 
+    @GuardedBy("mPackages")
     private void applyFactoryDefaultBrowserLPw(int userId) {
         // The default browser app's package name is stored in a string resource,
         // with a product-specific overlay used for vendor customization.
@@ -3779,6 +3853,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private void calculateDefaultBrowserLPw(int userId) {
         List<String> allBrowsers = resolveAllBrowserApps(userId);
         final String browserPkg = (allBrowsers.size() == 1) ? allBrowsers.get(0) : null;
@@ -4096,7 +4171,7 @@
     private boolean isComponentVisibleToInstantApp(
             @Nullable ComponentName component, @ComponentType int type) {
         if (type == TYPE_ACTIVITY) {
-            final PackageParser.Activity activity = mActivities.mActivities.get(component);
+            final PackageParser.Activity activity = mComponentResolver.getActivity(component);
             if (activity == null) {
                 return false;
             }
@@ -4106,7 +4181,7 @@
                     (activity.info.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
             return visibleToInstantApp && explicitlyVisibleToInstantApp;
         } else if (type == TYPE_RECEIVER) {
-            final PackageParser.Activity activity = mReceivers.mActivities.get(component);
+            final PackageParser.Activity activity = mComponentResolver.getReceiver(component);
             if (activity == null) {
                 return false;
             }
@@ -4116,12 +4191,12 @@
                     (activity.info.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
             return visibleToInstantApp && !explicitlyVisibleToInstantApp;
         } else if (type == TYPE_SERVICE) {
-            final PackageParser.Service service = mServices.mServices.get(component);
+            final PackageParser.Service service = mComponentResolver.getService(component);
             return service != null
                     ? (service.info.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
                     : false;
         } else if (type == TYPE_PROVIDER) {
-            final PackageParser.Provider provider = mProviders.mProviders.get(component);
+            final PackageParser.Provider provider = mComponentResolver.getProvider(component);
             return provider != null
                     ? (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
                     : false;
@@ -4139,6 +4214,7 @@
      *
      * @see #canViewInstantApps(int, int)
      */
+    @GuardedBy("mPackages")
     private boolean filterAppAccessLPr(@Nullable PackageSetting ps, int callingUid,
             @Nullable ComponentName component, @ComponentType int componentType, int userId) {
         // if we're in an isolated process, get the real calling UID
@@ -4196,10 +4272,12 @@
     /**
      * @see #filterAppAccessLPr(PackageSetting, int, ComponentName, int, int)
      */
+    @GuardedBy("mPackages")
     private boolean filterAppAccessLPr(@Nullable PackageSetting ps, int callingUid, int userId) {
         return filterAppAccessLPr(ps, callingUid, null, TYPE_UNKNOWN, userId);
     }
 
+    @GuardedBy("mPackages")
     private boolean filterSharedLibPackageLPr(@Nullable PackageSetting ps, int uid, int userId,
             int flags) {
         // Callers can access only the libs they depend on, otherwise they need to explicitly
@@ -4398,6 +4476,7 @@
                 ? ParceledListSlice.emptyList() : new ParceledListSlice<>(permissionList);
     }
 
+    @GuardedBy("mPackages")
     private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
             int filterCallingUid, int userId) {
         if (!sUserManager.exists(userId)) return null;
@@ -4483,6 +4562,7 @@
         return null;
     }
 
+    @GuardedBy("mPackages")
     private String normalizePackageNameLPr(String packageName) {
         String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
         return normalizedPackageName != null ? normalizedPackageName : packageName;
@@ -4864,7 +4944,7 @@
         }
 
         synchronized (mPackages) {
-            PackageParser.Activity a = mActivities.mActivities.get(component);
+            PackageParser.Activity a = mComponentResolver.getActivity(component);
 
             if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
@@ -4910,7 +4990,7 @@
             }
             final int callingUid = Binder.getCallingUid();
             final int callingUserId = UserHandle.getUserId(callingUid);
-            PackageParser.Activity a = mActivities.mActivities.get(component);
+            PackageParser.Activity a = mComponentResolver.getActivity(component);
             if (a == null) {
                 return false;
             }
@@ -4939,7 +5019,7 @@
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get receiver info");
         synchronized (mPackages) {
-            PackageParser.Activity a = mReceivers.mActivities.get(component);
+            PackageParser.Activity a = mComponentResolver.getReceiver(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getReceiverInfo " + component + ": " + a);
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
@@ -5021,6 +5101,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private List<VersionedPackage> getPackagesUsingSharedLibraryLPr(
             SharedLibraryInfo libInfo, int flags, int userId) {
         List<VersionedPackage> versionedPackages = null;
@@ -5076,7 +5157,7 @@
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get service info");
         synchronized (mPackages) {
-            PackageParser.Service s = mServices.mServices.get(component);
+            PackageParser.Service s = mComponentResolver.getService(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getServiceInfo " + component + ": " + s);
             if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) {
@@ -5100,7 +5181,7 @@
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get provider info");
         synchronized (mPackages) {
-            PackageParser.Provider p = mProviders.mProviders.get(component);
+            PackageParser.Provider p = mComponentResolver.getProvider(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getProviderInfo " + component + ": " + p);
             if (p != null && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
@@ -5176,6 +5257,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private void updateSequenceNumberLP(PackageSetting pkgSetting, int[] userList) {
         for (int i = userList.length - 1; i >= 0; --i) {
             final int userId = userList[i];
@@ -5260,11 +5342,35 @@
 
     @Override
     public int checkPermission(String permName, String pkgName, int userId) {
+        final CheckPermissionDelegate checkPermissionDelegate;
+        synchronized (mPackages) {
+            if (mCheckPermissionDelegate == null)  {
+                return checkPermissionImpl(permName, pkgName, userId);
+            }
+            checkPermissionDelegate = mCheckPermissionDelegate;
+        }
+        return checkPermissionDelegate.checkPermission(permName, pkgName, userId,
+                PackageManagerService.this::checkPermissionImpl);
+    }
+
+    private int checkPermissionImpl(String permName, String pkgName, int userId) {
         return mPermissionManager.checkPermission(permName, pkgName, getCallingUid(), userId);
     }
 
     @Override
     public int checkUidPermission(String permName, int uid) {
+        final CheckPermissionDelegate checkPermissionDelegate;
+        synchronized (mPackages) {
+            if (mCheckPermissionDelegate == null)  {
+                return checkUidPermissionImpl(permName, uid);
+            }
+            checkPermissionDelegate = mCheckPermissionDelegate;
+        }
+        return checkPermissionDelegate.checkUidPermission(permName, uid,
+                PackageManagerService.this::checkUidPermissionImpl);
+    }
+
+    private int checkUidPermissionImpl(String permName, int uid) {
         synchronized (mPackages) {
             final String[] packageNames = getPackagesForUid(uid);
             final PackageParser.Package pkg = (packageNames != null && packageNames.length > 0)
@@ -5310,6 +5416,12 @@
     @Override
     public String getPermissionControllerPackageName() {
         synchronized (mPackages) {
+            return mRequiredPermissionControllerPackage;
+        }
+    }
+
+    String getPackageInstallerPackageName() {
+        synchronized (mPackages) {
             return mRequiredInstallerPackage;
         }
     }
@@ -6185,6 +6297,7 @@
         return true;
     }
 
+    @GuardedBy("mPackages")
     private ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType,
             int flags, List<ResolveInfo> query, boolean debug, int userId) {
         final int N = query.size();
@@ -6249,17 +6362,17 @@
                 && intent.hasCategory(CATEGORY_DEFAULT);
     }
 
-    private boolean isDeviceProvisioned() {
-        return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
-                android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1;
-    }
-
     // TODO: handle preferred activities missing while user has amnesia
     ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags,
             List<ResolveInfo> query, int priority, boolean always,
             boolean removeMatches, boolean debug, int userId) {
         if (!sUserManager.exists(userId)) return null;
         final int callingUid = Binder.getCallingUid();
+        // Do NOT hold the packages lock; this calls up into the settings provider which
+        // could cause a deadlock.
+        final boolean isDeviceProvisioned =
+                android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+                        android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1;
         flags = updateFlagsForResolve(
                 flags, userId, intent, callingUid, false /*includeInstantApps*/);
         intent = updateIntentForResolve(intent);
@@ -6339,7 +6452,7 @@
                             }
                         }
                         final boolean excludeSetupWizardHomeActivity = isHomeIntent(intent)
-                                && !isDeviceProvisioned();
+                                && !isDeviceProvisioned;
                         if (ai == null) {
                             // Do not remove launcher's preferred activity during SetupWizard
                             // due to it may not install yet
@@ -6622,7 +6735,7 @@
                 }
 
                 // Check for results in the current profile.
-                result = filterIfNotSystemUser(mActivities.queryIntent(
+                result = filterIfNotSystemUser(mComponentResolver.queryActivities(
                         intent, resolvedType, flags, userId), userId);
                 addInstant = isInstantAppResolutionAllowed(intent, result, userId,
                         false /*skipPackageCheck*/);
@@ -6679,10 +6792,8 @@
                 final PackageParser.Package pkg = mPackages.get(pkgName);
                 result = null;
                 if (pkg != null) {
-                    result = filterIfNotSystemUser(
-                            mActivities.queryIntentForPackage(
-                                    intent, resolvedType, flags, pkg.activities, userId),
-                            userId);
+                    result = filterIfNotSystemUser(mComponentResolver.queryActivities(
+                            intent, resolvedType, flags, pkg.activities, userId), userId);
                 }
                 if (result == null || result.size() == 0) {
                     // the caller wants to resolve for a particular package; however, there
@@ -6700,7 +6811,7 @@
                     result, intent, resolvedType, flags, userId, resolveForStart);
         }
         if (sortResult) {
-            Collections.sort(result, mResolvePrioritySorter);
+            Collections.sort(result, RESOLVE_PRIORITY_SORTER);
         }
         return applyPostResolutionFilter(
                 result, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
@@ -6714,7 +6825,9 @@
         ResolveInfo localInstantApp = null;
         boolean blockResolution = false;
         if (!alreadyResolvedLocally) {
-            final List<ResolveInfo> instantApps = mActivities.queryIntent(intent, resolvedType,
+            final List<ResolveInfo> instantApps = mComponentResolver.queryActivities(
+                    intent,
+                    resolvedType,
                     flags
                         | PackageManager.GET_RESOLVED_FILTER
                         | PackageManager.MATCH_INSTANT
@@ -6820,7 +6933,7 @@
                 sourceUserId)) {
             return null;
         }
-        List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent,
+        List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
                 resolvedType, flags, parentUserId);
 
         if (resultTargetUser == null || resultTargetUser.isEmpty()) {
@@ -7260,7 +7373,7 @@
     private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter, Intent intent,
             String resolvedType, int flags, int sourceUserId) {
         int targetUserId = filter.getTargetUserId();
-        List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent,
+        List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
                 resolvedType, flags, targetUserId);
         if (resultTargetUser != null && isUserEnabled(targetUserId)) {
             // If all the matches in the target profile are suspended, return null.
@@ -7568,14 +7681,14 @@
             String pkgName = intent.getPackage();
             if (pkgName == null) {
                 final List<ResolveInfo> result =
-                        mReceivers.queryIntent(intent, resolvedType, flags, userId);
+                        mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
                 return applyPostResolutionFilter(
                         result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
                         intent);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
-                final List<ResolveInfo> result = mReceivers.queryIntentForPackage(
+                final List<ResolveInfo> result = mComponentResolver.queryReceivers(
                         intent, resolvedType, flags, pkg.receivers, userId);
                 return applyPostResolutionFilter(
                         result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
@@ -7672,13 +7785,13 @@
             String pkgName = intent.getPackage();
             if (pkgName == null) {
                 return applyPostServiceResolutionFilter(
-                        mServices.queryIntent(intent, resolvedType, flags, userId),
+                        mComponentResolver.queryServices(intent, resolvedType, flags, userId),
                         instantAppPkgName);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
                 return applyPostServiceResolutionFilter(
-                        mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
+                        mComponentResolver.queryServices(intent, resolvedType, flags, pkg.services,
                                 userId),
                         instantAppPkgName);
             }
@@ -7790,14 +7903,14 @@
             String pkgName = intent.getPackage();
             if (pkgName == null) {
                 return applyPostContentProviderResolutionFilter(
-                        mProviders.queryIntent(intent, resolvedType, flags, userId),
+                        mComponentResolver.queryProviders(intent, resolvedType, flags, userId),
                         instantAppPkgName);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
                 return applyPostContentProviderResolutionFilter(
-                        mProviders.queryIntentForPackage(
-                        intent, resolvedType, flags, pkg.providers, userId),
+                        mComponentResolver.queryProviders(intent, resolvedType, flags,
+                                pkg.providers, userId),
                         instantAppPkgName);
             }
             return Collections.emptyList();
@@ -8210,26 +8323,22 @@
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId, name);
         final int callingUid = Binder.getCallingUid();
-        synchronized (mPackages) {
-            final PackageParser.Provider provider = mProvidersByAuthority.get(name);
-            PackageSetting ps = provider != null
-                    ? mSettings.mPackages.get(provider.owner.packageName)
-                    : null;
-            if (ps != null) {
-                // provider not enabled
-                if (!mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)) {
-                    return null;
-                }
-                final ComponentName component =
-                        new ComponentName(provider.info.packageName, provider.info.name);
-                if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
-                    return null;
-                }
-                return PackageParser.generateProviderInfo(
-                        provider, flags, ps.readUserState(userId), userId);
-            }
+        final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId);
+        if (providerInfo == null) {
             return null;
         }
+        if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) {
+            return null;
+        }
+        synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName);
+            final ComponentName component =
+                    new ComponentName(providerInfo.packageName, providerInfo.name);
+            if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
+                return null;
+            }
+            return providerInfo;
+        }
     }
 
     /**
@@ -8240,28 +8349,8 @@
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return;
         }
-        // reader
-        synchronized (mPackages) {
-            final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProvidersByAuthority
-                    .entrySet().iterator();
-            final int userId = UserHandle.getCallingUserId();
-            while (i.hasNext()) {
-                Map.Entry<String, PackageParser.Provider> entry = i.next();
-                PackageParser.Provider p = entry.getValue();
-                PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
-
-                if (ps != null && p.syncable
-                        && (!mSafeMode || (p.info.applicationInfo.flags
-                                &ApplicationInfo.FLAG_SYSTEM) != 0)) {
-                    ProviderInfo info = PackageParser.generateProviderInfo(p, 0,
-                            ps.readUserState(userId), userId);
-                    if (info != null) {
-                        outNames.add(entry.getKey());
-                        outInfo.add(info);
-                    }
-                }
-            }
-        }
+        mComponentResolver.querySyncProviders(
+                outNames, outInfo, mSafeMode, UserHandle.getCallingUserId());
     }
 
     @Override
@@ -8273,43 +8362,30 @@
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForComponent(flags, userId, processName);
         ArrayList<ProviderInfo> finalList = null;
-        // reader
+        final List<ProviderInfo> matchList =
+                mComponentResolver.queryProviders(processName, metaDataKey, uid, flags, userId);
+        final int listSize = (matchList == null ? 0 : matchList.size());
         synchronized (mPackages) {
-            final Iterator<PackageParser.Provider> i = mProviders.mProviders.values().iterator();
-            while (i.hasNext()) {
-                final PackageParser.Provider p = i.next();
-                PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
-                if (ps != null && p.info.authority != null
-                        && (processName == null
-                                || (p.info.processName.equals(processName)
-                                        && UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
-                        && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
-
-                    // See PM.queryContentProviders()'s javadoc for why we have the metaData
-                    // parameter.
-                    if (metaDataKey != null
-                            && (p.metaData == null || !p.metaData.containsKey(metaDataKey))) {
-                        continue;
-                    }
-                    final ComponentName component =
-                            new ComponentName(p.info.packageName, p.info.name);
-                    if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
-                        continue;
-                    }
-                    if (finalList == null) {
-                        finalList = new ArrayList<>(3);
-                    }
-                    ProviderInfo info = PackageParser.generateProviderInfo(p, flags,
-                            ps.readUserState(userId), userId);
-                    if (info != null) {
-                        finalList.add(info);
-                    }
+            for (int i = 0; i < listSize; i++) {
+                final ProviderInfo providerInfo = matchList.get(i);
+                if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) {
+                    continue;
                 }
+                final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName);
+                final ComponentName component =
+                        new ComponentName(providerInfo.packageName, providerInfo.name);
+                if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
+                    continue;
+                }
+                if (finalList == null) {
+                    finalList = new ArrayList<>(listSize - i);
+                }
+                finalList.add(providerInfo);
             }
         }
 
         if (finalList != null) {
-            finalList.sort(mProviderInitOrderSorter);
+            finalList.sort(sProviderInitOrderSorter);
             return new ParceledListSlice<>(finalList);
         }
 
@@ -8513,6 +8589,7 @@
      *  Traces a package scan.
      *  @see #scanPackageLI(File, int, int, long, UserHandle)
      */
+    @GuardedBy("mInstallLock")
     private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags,
             int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]");
@@ -8527,6 +8604,7 @@
      *  Scans a package and returns the newly parsed package.
      *  Returns {@code null} in case of errors and the error code is stored in mLastScanError
      */
+    @GuardedBy({"mInstallLock", "mPackages"})
     private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
             long currentTime, UserHandle user) throws PackageManagerException {
         if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
@@ -8558,6 +8636,7 @@
      *  Scans a package and returns the newly parsed package.
      *  @throws PackageManagerException on a parse error.
      */
+    @GuardedBy({"mInstallLock", "mPackages"})
     private PackageParser.Package scanPackageChildLI(PackageParser.Package pkg,
             final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
             @Nullable UserHandle user)
@@ -8650,6 +8729,7 @@
      * structures and the package is made available to the rest of the system.
      * <p>NOTE: The return value should be removed. It's the passed in package object.
      */
+    @GuardedBy({"mInstallLock", "mPackages"})
     private PackageParser.Package addForInitLI(PackageParser.Package pkg,
             @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
             @Nullable UserHandle user)
@@ -8788,15 +8868,16 @@
                     + " better than this " + pkg.getLongVersionCode());
         }
 
-        // Verify certificates against what was last scanned. If it is an updated priv app, we will
-        // force re-collecting certificate.
-        final boolean forceCollect = PackageManagerServiceUtils.isApkVerificationForced(
-                disabledPkgSetting);
+        // Verify certificates against what was last scanned. If there was an upgrade and this is an
+        // app in a system partition, or if this is an updated priv app, we will force re-collecting
+        // certificate.
+        final boolean forceCollect = (mIsUpgrade && scanSystemPartition)
+                || PackageManagerServiceUtils.isApkVerificationForced(disabledPkgSetting);
         // Full APK verification can be skipped during certificate collection, only if the file is
         // in verified partition, or can be verified on access (when apk verity is enabled). In both
         // cases, only data in Signing Block is verified instead of the whole file.
-        final boolean skipVerify = ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) ||
-                (forceCollect && canSkipFullPackageVerification(pkg));
+        final boolean skipVerify = scanSystemPartition
+                || (forceCollect && canSkipFullPackageVerification(pkg));
         collectCertificatesLI(pkgSetting, pkg, forceCollect, skipVerify);
 
         // Reset profile if the application version is changed
@@ -8853,15 +8934,20 @@
             }
         }
 
-        final PackageParser.Package scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags
+        final ScanResult scanResult = scanPackageNewLI(pkg, parseFlags, scanFlags
                 | SCAN_UPDATE_SIGNATURE, currentTime, user);
+        if (scanResult.success) {
+            synchronized (mPackages) {
+                commitScanResultLocked(scanResult);
+            }
+        }
 
         if (shouldHideSystemApp) {
             synchronized (mPackages) {
                 mSettings.disableSystemPackageLPw(pkg.packageName, true);
             }
         }
-        return scannedPkg;
+        return scanResult.pkgSetting.pkg;
     }
 
     private static void renameStaticSharedLibraryPackage(PackageParser.Package pkg) {
@@ -8870,8 +8956,7 @@
                 + pkg.staticSharedLibVersion);
     }
 
-    private static String fixProcessName(String defProcessName,
-            String processName) {
+    static String fixProcessName(String defProcessName, String processName) {
         if (processName == null) {
             return defProcessName;
         }
@@ -8892,6 +8977,20 @@
         }
     }
 
+    /**
+     * Enforces that only the system UID or shell's UID can call a method exposed
+     * via Binder.
+     *
+     * @param message used as message if SecurityException is thrown
+     * @throws SecurityException if the caller is not system or shell
+     */
+    private static void enforceSystemOrShell(String message) {
+        final int uid = Binder.getCallingUid();
+        if (uid != Process.SYSTEM_UID && uid != Process.SHELL_UID) {
+            throw new SecurityException(message);
+        }
+    }
+
     @Override
     public void performFstrimIfNeeded() {
         enforceSystemOrRoot("Only the system can request fstrim");
@@ -9150,6 +9249,16 @@
     }
 
     @GuardedBy("mPackages")
+    public CheckPermissionDelegate getCheckPermissionDelegateLocked() {
+        return mCheckPermissionDelegate;
+    }
+
+    @GuardedBy("mPackages")
+    public void setCheckPermissionDelegateLocked(CheckPermissionDelegate delegate) {
+        mCheckPermissionDelegate = delegate;
+    }
+
+    @GuardedBy("mPackages")
     private void notifyPackageUseLocked(String packageName, int reason) {
         final PackageParser.Package p = mPackages.get(packageName);
         if (p == null) {
@@ -9363,7 +9472,13 @@
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return false;
         }
-        return BackgroundDexOptService.runIdleOptimizationsNow(this, mContext, packageNames);
+        enforceSystemOrShell("runBackgroundDexoptJob");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return BackgroundDexOptService.runIdleOptimizationsNow(this, mContext, packageNames);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     List<PackageParser.Package> findSharedNonSystemLibraries(PackageParser.Package p) {
@@ -9525,6 +9640,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
         if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
             Slog.w(TAG, "Unable to update from " + oldPkg.name
@@ -9540,6 +9656,7 @@
         return true;
     }
 
+    @GuardedBy("mInstallLock")
     void removeCodePathLI(File codePath) {
         if (codePath.isDirectory()) {
             try {
@@ -9667,6 +9784,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private void addSharedLibraryLPr(Set<String> usesLibraryFiles,
             SharedLibraryEntry file,
             PackageParser.Package changingLib) {
@@ -9692,6 +9810,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private void updateSharedLibrariesLPr(PackageParser.Package pkg,
             PackageParser.Package changingLib) throws PackageManagerException {
         if (pkg == null) {
@@ -9724,6 +9843,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private Set<String> addSharedLibrariesLPw(@NonNull List<String> requestedLibraries,
             @Nullable long[] requiredVersions, @Nullable String[][] requiredCertDigests,
             @NonNull String packageName, @Nullable PackageParser.Package changingLib,
@@ -9835,6 +9955,7 @@
         return false;
     }
 
+    @GuardedBy("mPackages")
     private ArrayList<PackageParser.Package> updateAllSharedLibrariesLPw(
             PackageParser.Package changingPkg) {
         ArrayList<PackageParser.Package> res = null;
@@ -9870,7 +9991,8 @@
         return res;
     }
 
-    private PackageParser.Package scanPackageTracedLI(PackageParser.Package pkg,
+    @GuardedBy({"mInstallLock", "mPackages"})
+    private List<ScanResult> scanPackageTracedLI(PackageParser.Package pkg,
             final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
             @Nullable UserHandle user) throws PackageManagerException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
@@ -9887,16 +10009,16 @@
             scanFlags &= ~SCAN_CHECK_ONLY;
         }
 
-        final PackageParser.Package scannedPkg;
+        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+        final List<ScanResult> scanResults = new ArrayList<>(1 + childCount);
         try {
             // Scan the parent
-            scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags, currentTime, user);
+            scanResults.add(scanPackageNewLI(pkg, parseFlags, scanFlags, currentTime, user));
             // Scan the children
-            final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
             for (int i = 0; i < childCount; i++) {
                 PackageParser.Package childPkg = pkg.childPackages.get(i);
-                scanPackageNewLI(childPkg, parseFlags,
-                        scanFlags, currentTime, user);
+                scanResults.add(scanPackageNewLI(childPkg, parseFlags,
+                        scanFlags, currentTime, user));
             }
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -9906,11 +10028,13 @@
             return scanPackageTracedLI(pkg, parseFlags, scanFlags, currentTime, user);
         }
 
-        return scannedPkg;
+        return scanResults;
     }
 
     /** The result of a package scan. */
     private static class ScanResult {
+        /** The request that initiated the scan that produced this result. */
+        public final ScanRequest request;
         /** Whether or not the package scan was successful */
         public final boolean success;
         /**
@@ -9921,9 +10045,10 @@
         /** ABI code paths that have changed in the package scan */
         @Nullable public final List<String> changedAbiCodePath;
         public ScanResult(
-                boolean success,
+                ScanRequest request, boolean success,
                 @Nullable PackageSetting pkgSetting,
                 @Nullable List<String> changedAbiCodePath) {
+            this.request = request;
             this.success = success;
             this.pkgSetting = pkgSetting;
             this.changedAbiCodePath = changedAbiCodePath;
@@ -9995,6 +10120,7 @@
      * <li>{@link #SCAN_AS_OEM}</li>
      * <li>{@link #SCAN_AS_VENDOR}</li>
      * <li>{@link #SCAN_AS_PRODUCT}</li>
+     * <li>{@link #SCAN_AS_PRODUCT_SERVICES}</li>
      * <li>{@link #SCAN_AS_INSTANT_APP}</li>
      * <li>{@link #SCAN_AS_VIRTUAL_PRELOAD}</li>
      * </ul>
@@ -10021,6 +10147,10 @@
                     & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) {
                 scanFlags |= SCAN_AS_PRODUCT;
             }
+            if ((disabledPkgSetting.pkgPrivateFlags
+                    & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0) {
+                scanFlags |= SCAN_AS_PRODUCT_SERVICES;
+            }
         }
         if (pkgSetting != null) {
             final int userId = ((user == null) ? 0 : user.getIdentifier());
@@ -10065,8 +10195,8 @@
     // the results / removing app data needs to be moved up a level to the callers of this
     // method. Also, we need to solve the problem of potentially creating a new shared user
     // setting. That can probably be done later and patch things up after the fact.
-    @GuardedBy("mInstallLock")
-    private PackageParser.Package scanPackageNewLI(@NonNull PackageParser.Package pkg,
+    @GuardedBy({"mInstallLock", "mPackages"})
+    private ScanResult scanPackageNewLI(@NonNull PackageParser.Package pkg,
             final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
             @Nullable UserHandle user) throws PackageManagerException {
 
@@ -10102,28 +10232,30 @@
                                 + " packages=" + sharedUserSetting.packages);
                 }
             }
+            final ScanRequest request = new ScanRequest(pkg, sharedUserSetting,
+                    pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting,
+                    originalPkgSetting, realPkgName, parseFlags, scanFlags,
+                    (pkg == mPlatformPackage), user);
+            return scanPackageOnlyLI(request, mFactoryTest, currentTime);
+        }
+    }
 
-            boolean scanSucceeded = false;
-            try {
-                final ScanRequest request = new ScanRequest(pkg, sharedUserSetting,
-                        pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting,
-                        originalPkgSetting, realPkgName, parseFlags, scanFlags,
-                        (pkg == mPlatformPackage), user);
-                final ScanResult result = scanPackageOnlyLI(request, mFactoryTest, currentTime);
-                if (result.success) {
-                    commitScanResultsLocked(request, result);
+
+    private void commitSuccessfulScanResults(@NonNull List<ScanResult> results)
+            throws PackageManagerException {
+        synchronized(mPackages) {
+            for (ScanResult result : results) {
+                // failures should have been caught earlier, but in case it wasn't,
+                // let's double check
+                if (!result.success) {
+                    throw new PackageManagerException(
+                            "Scan failed for " + result.request.pkg.packageName);
                 }
-                scanSucceeded = true;
-            } finally {
-                  if (!scanSucceeded && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
-                      // DELETE_DATA_ON_FAILURES is only used by frozen paths
-                      destroyAppDataLIF(pkg, UserHandle.USER_ALL,
-                              StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
-                      destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
-                  }
+            }
+            for (ScanResult result : results) {
+                commitScanResultLocked(result);
             }
         }
-        return pkg;
     }
 
     /**
@@ -10133,9 +10265,9 @@
      * This needs to be fixed so, once we get to this point, no errors are
      * possible and the system is not left in an inconsistent state.
      */
-    @GuardedBy("mPackages")
-    private void commitScanResultsLocked(@NonNull ScanRequest request, @NonNull ScanResult result)
-            throws PackageManagerException {
+    @GuardedBy({"mPackages", "mInstallLock"})
+    private void commitScanResultLocked(@NonNull ScanResult result) throws PackageManagerException {
+        final ScanRequest request = result.request;
         final PackageParser.Package pkg = request.pkg;
         final PackageParser.Package oldPkg = request.oldPkg;
         final @ParseFlags int parseFlags = request.parseFlags;
@@ -10716,7 +10848,7 @@
             pkgSetting.volumeUuid = volumeUuid;
         }
 
-        return new ScanResult(true, pkgSetting, changedAbiCodePath);
+        return new ScanResult(request, true, pkgSetting, changedAbiCodePath);
     }
 
     /**
@@ -10861,6 +10993,10 @@
             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT;
         }
 
+        if ((scanFlags & SCAN_AS_PRODUCT_SERVICES) != 0) {
+            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES;
+        }
+
         // Check if the package is signed with the same key as the platform package.
         if (PLATFORM_PACKAGE_NAME.equals(pkg.packageName) ||
                 (platformPkg != null && compareSignatures(
@@ -11114,27 +11250,7 @@
             // package isn't already installed, since we don't want to break
             // things that are installed.
             if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
-                final int N = pkg.providers.size();
-                int i;
-                for (i=0; i<N; i++) {
-                    PackageParser.Provider p = pkg.providers.get(i);
-                    if (p.info.authority != null) {
-                        String names[] = p.info.authority.split(";");
-                        for (int j = 0; j < names.length; j++) {
-                            if (mProvidersByAuthority.containsKey(names[j])) {
-                                PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
-                                final String otherPackageName =
-                                        ((other != null && other.getComponentName() != null) ?
-                                                other.getComponentName().getPackageName() : "?");
-                                throw new PackageManagerException(
-                                        INSTALL_FAILED_CONFLICTING_PROVIDER,
-                                        "Can't install because provider name " + names[j]
-                                                + " (in package " + pkg.applicationInfo.packageName
-                                                + ") is already used by " + otherPackageName);
-                            }
-                        }
-                    }
-                }
+                mComponentResolver.assertProvidersNotDefined(pkg);
             }
 
             // Verify that packages sharing a user with a privileged app are marked as privileged.
@@ -11432,125 +11548,7 @@
             KeySetManagerService ksms = mSettings.mKeySetManagerService;
             ksms.addScannedPackageLPw(pkg);
 
-            int N = pkg.providers.size();
-            StringBuilder r = null;
-            int i;
-            for (i=0; i<N; i++) {
-                PackageParser.Provider p = pkg.providers.get(i);
-                p.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        p.info.processName);
-                mProviders.addProvider(p);
-                p.syncable = p.info.isSyncable;
-                if (p.info.authority != null) {
-                    String names[] = p.info.authority.split(";");
-                    p.info.authority = null;
-                    for (int j = 0; j < names.length; j++) {
-                        if (j == 1 && p.syncable) {
-                            // We only want the first authority for a provider to possibly be
-                            // syncable, so if we already added this provider using a different
-                            // authority clear the syncable flag. We copy the provider before
-                            // changing it because the mProviders object contains a reference
-                            // to a provider that we don't want to change.
-                            // Only do this for the second authority since the resulting provider
-                            // object can be the same for all future authorities for this provider.
-                            p = new PackageParser.Provider(p);
-                            p.syncable = false;
-                        }
-                        if (!mProvidersByAuthority.containsKey(names[j])) {
-                            mProvidersByAuthority.put(names[j], p);
-                            if (p.info.authority == null) {
-                                p.info.authority = names[j];
-                            } else {
-                                p.info.authority = p.info.authority + ";" + names[j];
-                            }
-                            if (DEBUG_PACKAGE_SCANNING) {
-                                if (chatty)
-                                    Log.d(TAG, "Registered content provider: " + names[j]
-                                            + ", className = " + p.info.name + ", isSyncable = "
-                                            + p.info.isSyncable);
-                            }
-                        } else {
-                            PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
-                            Slog.w(TAG, "Skipping provider name " + names[j] +
-                                    " (in package " + pkg.applicationInfo.packageName +
-                                    "): name already used by "
-                                    + ((other != null && other.getComponentName() != null)
-                                            ? other.getComponentName().getPackageName() : "?"));
-                        }
-                    }
-                }
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(p.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Providers: " + r);
-            }
-
-            N = pkg.services.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Service s = pkg.services.get(i);
-                s.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        s.info.processName);
-                mServices.addService(s);
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(s.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Services: " + r);
-            }
-
-            N = pkg.receivers.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Activity a = pkg.receivers.get(i);
-                a.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        a.info.processName);
-                mReceivers.addActivity(a, "receiver");
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(a.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Receivers: " + r);
-            }
-
-            N = pkg.activities.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Activity a = pkg.activities.get(i);
-                a.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        a.info.processName);
-                mActivities.addActivity(a, "activity");
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(a.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Activities: " + r);
-            }
+            mComponentResolver.addAllComponents(pkg, chatty);
 
             // Don't allow ephemeral applications to define new permissions groups.
             if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
@@ -11568,9 +11566,10 @@
                 mPermissionManager.addAllPermissions(pkg, chatty);
             }
 
-            N = pkg.instrumentation.size();
-            r = null;
-            for (i=0; i<N; i++) {
+            int collectionSize = pkg.instrumentation.size();
+            StringBuilder r = null;
+            int i;
+            for (i = 0; i < collectionSize; i++) {
                 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
                 a.info.packageName = pkg.applicationInfo.packageName;
                 a.info.sourceDir = pkg.applicationInfo.sourceDir;
@@ -11601,9 +11600,9 @@
             }
 
             if (pkg.protectedBroadcasts != null) {
-                N = pkg.protectedBroadcasts.size();
+                collectionSize = pkg.protectedBroadcasts.size();
                 synchronized (mProtectedBroadcasts) {
-                    for (i = 0; i < N; i++) {
+                    for (i = 0; i < collectionSize; i++) {
                         mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
                     }
                 }
@@ -11954,6 +11953,8 @@
             codeRoot = Environment.getOdmDirectory();
         } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) {
             codeRoot = Environment.getProductDirectory();
+        } else if (FileUtils.contains(Environment.getProductServicesDirectory(), codePath)) {
+            codeRoot = Environment.getProductServicesDirectory();
         } else {
             // Unrecognized code path; take its top real segment as the apk root:
             // e.g. /something/app/blah.apk => /something
@@ -12220,104 +12221,15 @@
     }
 
     void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
-        int N = pkg.providers.size();
+        mComponentResolver.removeAllComponents(pkg, chatty);
+
+        final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
+        mPermissionManager.removeAllPermissions(pkg, allPackageNames, mPermissionCallback, chatty);
+
+        final int instrumentationSize = pkg.instrumentation.size();
         StringBuilder r = null;
         int i;
-        for (i=0; i<N; i++) {
-            PackageParser.Provider p = pkg.providers.get(i);
-            mProviders.removeProvider(p);
-            if (p.info.authority == null) {
-
-                /* There was another ContentProvider with this authority when
-                 * this app was installed so this authority is null,
-                 * Ignore it as we don't have to unregister the provider.
-                 */
-                continue;
-            }
-            String names[] = p.info.authority.split(";");
-            for (int j = 0; j < names.length; j++) {
-                if (mProvidersByAuthority.get(names[j]) == p) {
-                    mProvidersByAuthority.remove(names[j]);
-                    if (DEBUG_REMOVE) {
-                        if (chatty)
-                            Log.d(TAG, "Unregistered content provider: " + names[j]
-                                    + ", className = " + p.info.name + ", isSyncable = "
-                                    + p.info.isSyncable);
-                    }
-                }
-            }
-            if (DEBUG_REMOVE && chatty) {
-                if (r == null) {
-                    r = new StringBuilder(256);
-                } else {
-                    r.append(' ');
-                }
-                r.append(p.info.name);
-            }
-        }
-        if (r != null) {
-            if (DEBUG_REMOVE) Log.d(TAG, "  Providers: " + r);
-        }
-
-        N = pkg.services.size();
-        r = null;
-        for (i=0; i<N; i++) {
-            PackageParser.Service s = pkg.services.get(i);
-            mServices.removeService(s);
-            if (chatty) {
-                if (r == null) {
-                    r = new StringBuilder(256);
-                } else {
-                    r.append(' ');
-                }
-                r.append(s.info.name);
-            }
-        }
-        if (r != null) {
-            if (DEBUG_REMOVE) Log.d(TAG, "  Services: " + r);
-        }
-
-        N = pkg.receivers.size();
-        r = null;
-        for (i=0; i<N; i++) {
-            PackageParser.Activity a = pkg.receivers.get(i);
-            mReceivers.removeActivity(a, "receiver");
-            if (DEBUG_REMOVE && chatty) {
-                if (r == null) {
-                    r = new StringBuilder(256);
-                } else {
-                    r.append(' ');
-                }
-                r.append(a.info.name);
-            }
-        }
-        if (r != null) {
-            if (DEBUG_REMOVE) Log.d(TAG, "  Receivers: " + r);
-        }
-
-        N = pkg.activities.size();
-        r = null;
-        for (i=0; i<N; i++) {
-            PackageParser.Activity a = pkg.activities.get(i);
-            mActivities.removeActivity(a, "activity");
-            if (DEBUG_REMOVE && chatty) {
-                if (r == null) {
-                    r = new StringBuilder(256);
-                } else {
-                    r.append(' ');
-                }
-                r.append(a.info.name);
-            }
-        }
-        if (r != null) {
-            if (DEBUG_REMOVE) Log.d(TAG, "  Activities: " + r);
-        }
-
-        mPermissionManager.removeAllPermissions(pkg, chatty);
-
-        N = pkg.instrumentation.size();
-        r = null;
-        for (i=0; i<N; i++) {
+        for (i = 0; i < instrumentationSize; i++) {
             PackageParser.Instrumentation a = pkg.instrumentation.get(i);
             mInstrumentation.remove(a.getComponentName());
             if (DEBUG_REMOVE && chatty) {
@@ -12337,7 +12249,8 @@
         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
             // Only system apps can hold shared libraries.
             if (pkg.libraryNames != null) {
-                for (i = 0; i < pkg.libraryNames.size(); i++) {
+                final int libraryNamesSize = pkg.libraryNames.size();
+                for (i = 0; i < libraryNamesSize; i++) {
                     String name = pkg.libraryNames.get(i);
                     if (removeSharedLibraryLPw(name, 0)) {
                         if (DEBUG_REMOVE && chatty) {
@@ -12374,1135 +12287,6 @@
         }
     }
 
-
-    final class ActivityIntentResolver
-            extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
-            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
-        }
-
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
-                int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            mFlags = flags;
-            return super.queryIntent(intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    userId);
-        }
-
-        public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            if (packageActivities == null) {
-                return null;
-            }
-            mFlags = flags;
-            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final int N = packageActivities.size();
-            ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
-                new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
-
-            ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
-            for (int i = 0; i < N; ++i) {
-                intentFilters = packageActivities.get(i).intents;
-                if (intentFilters != null && intentFilters.size() > 0) {
-                    PackageParser.ActivityIntentInfo[] array =
-                            new PackageParser.ActivityIntentInfo[intentFilters.size()];
-                    intentFilters.toArray(array);
-                    listCut.add(array);
-                }
-            }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
-        }
-
-        /**
-         * Finds a privileged activity that matches the specified activity names.
-         */
-        private PackageParser.Activity findMatchingActivity(
-                List<PackageParser.Activity> activityList, ActivityInfo activityInfo) {
-            for (PackageParser.Activity sysActivity : activityList) {
-                if (sysActivity.info.name.equals(activityInfo.name)) {
-                    return sysActivity;
-                }
-                if (sysActivity.info.name.equals(activityInfo.targetActivity)) {
-                    return sysActivity;
-                }
-                if (sysActivity.info.targetActivity != null) {
-                    if (sysActivity.info.targetActivity.equals(activityInfo.name)) {
-                        return sysActivity;
-                    }
-                    if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) {
-                        return sysActivity;
-                    }
-                }
-            }
-            return null;
-        }
-
-        public class IterGenerator<E> {
-            public Iterator<E> generate(ActivityIntentInfo info) {
-                return null;
-            }
-        }
-
-        public class ActionIterGenerator extends IterGenerator<String> {
-            @Override
-            public Iterator<String> generate(ActivityIntentInfo info) {
-                return info.actionsIterator();
-            }
-        }
-
-        public class CategoriesIterGenerator extends IterGenerator<String> {
-            @Override
-            public Iterator<String> generate(ActivityIntentInfo info) {
-                return info.categoriesIterator();
-            }
-        }
-
-        public class SchemesIterGenerator extends IterGenerator<String> {
-            @Override
-            public Iterator<String> generate(ActivityIntentInfo info) {
-                return info.schemesIterator();
-            }
-        }
-
-        public class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
-            @Override
-            public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) {
-                return info.authoritiesIterator();
-            }
-        }
-
-        /**
-         * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
-         * MODIFIED. Do not pass in a list that should not be changed.
-         */
-        private <T> void getIntentListSubset(List<ActivityIntentInfo> intentList,
-                IterGenerator<T> generator, Iterator<T> searchIterator) {
-            // loop through the set of actions; every one must be found in the intent filter
-            while (searchIterator.hasNext()) {
-                // we must have at least one filter in the list to consider a match
-                if (intentList.size() == 0) {
-                    break;
-                }
-
-                final T searchAction = searchIterator.next();
-
-                // loop through the set of intent filters
-                final Iterator<ActivityIntentInfo> intentIter = intentList.iterator();
-                while (intentIter.hasNext()) {
-                    final ActivityIntentInfo intentInfo = intentIter.next();
-                    boolean selectionFound = false;
-
-                    // loop through the intent filter's selection criteria; at least one
-                    // of them must match the searched criteria
-                    final Iterator<T> intentSelectionIter = generator.generate(intentInfo);
-                    while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
-                        final T intentSelection = intentSelectionIter.next();
-                        if (intentSelection != null && intentSelection.equals(searchAction)) {
-                            selectionFound = true;
-                            break;
-                        }
-                    }
-
-                    // the selection criteria wasn't found in this filter's set; this filter
-                    // is not a potential match
-                    if (!selectionFound) {
-                        intentIter.remove();
-                    }
-                }
-            }
-        }
-
-        private boolean isProtectedAction(ActivityIntentInfo filter) {
-            final Iterator<String> actionsIter = filter.actionsIterator();
-            while (actionsIter != null && actionsIter.hasNext()) {
-                final String filterAction = actionsIter.next();
-                if (PROTECTED_ACTIONS.contains(filterAction)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        /**
-         * Adjusts the priority of the given intent filter according to policy.
-         * <p>
-         * <ul>
-         * <li>The priority for non privileged applications is capped to '0'</li>
-         * <li>The priority for protected actions on privileged applications is capped to '0'</li>
-         * <li>The priority for unbundled updates to privileged applications is capped to the
-         *      priority defined on the system partition</li>
-         * </ul>
-         * <p>
-         * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
-         * allowed to obtain any priority on any action.
-         */
-        private void adjustPriority(
-                List<PackageParser.Activity> systemActivities, ActivityIntentInfo intent) {
-            // nothing to do; priority is fine as-is
-            if (intent.getPriority() <= 0) {
-                return;
-            }
-
-            final ActivityInfo activityInfo = intent.activity.info;
-            final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
-
-            final boolean privilegedApp =
-                    ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
-            if (!privilegedApp) {
-                // non-privileged applications can never define a priority >0
-                if (DEBUG_FILTERS) {
-                    Slog.i(TAG, "Non-privileged app; cap priority to 0;"
-                            + " package: " + applicationInfo.packageName
-                            + " activity: " + intent.activity.className
-                            + " origPrio: " + intent.getPriority());
-                }
-                intent.setPriority(0);
-                return;
-            }
-
-            if (systemActivities == null) {
-                // the system package is not disabled; we're parsing the system partition
-                if (isProtectedAction(intent)) {
-                    if (mDeferProtectedFilters) {
-                        // We can't deal with these just yet. No component should ever obtain a
-                        // >0 priority for a protected actions, with ONE exception -- the setup
-                        // wizard. The setup wizard, however, cannot be known until we're able to
-                        // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
-                        // until all intent filters have been processed. Chicken, meet egg.
-                        // Let the filter temporarily have a high priority and rectify the
-                        // priorities after all system packages have been scanned.
-                        mProtectedFilters.add(intent);
-                        if (DEBUG_FILTERS) {
-                            Slog.i(TAG, "Protected action; save for later;"
-                                    + " package: " + applicationInfo.packageName
-                                    + " activity: " + intent.activity.className
-                                    + " origPrio: " + intent.getPriority());
-                        }
-                        return;
-                    } else {
-                        if (DEBUG_FILTERS && mSetupWizardPackage == null) {
-                            Slog.i(TAG, "No setup wizard;"
-                                + " All protected intents capped to priority 0");
-                        }
-                        if (intent.activity.info.packageName.equals(mSetupWizardPackage)) {
-                            if (DEBUG_FILTERS) {
-                                Slog.i(TAG, "Found setup wizard;"
-                                    + " allow priority " + intent.getPriority() + ";"
-                                    + " package: " + intent.activity.info.packageName
-                                    + " activity: " + intent.activity.className
-                                    + " priority: " + intent.getPriority());
-                            }
-                            // setup wizard gets whatever it wants
-                            return;
-                        }
-                        if (DEBUG_FILTERS) {
-                            Slog.i(TAG, "Protected action; cap priority to 0;"
-                                    + " package: " + intent.activity.info.packageName
-                                    + " activity: " + intent.activity.className
-                                    + " origPrio: " + intent.getPriority());
-                        }
-                        intent.setPriority(0);
-                        return;
-                    }
-                }
-                // privileged apps on the system image get whatever priority they request
-                return;
-            }
-
-            // privileged app unbundled update ... try to find the same activity
-            final PackageParser.Activity foundActivity =
-                    findMatchingActivity(systemActivities, activityInfo);
-            if (foundActivity == null) {
-                // this is a new activity; it cannot obtain >0 priority
-                if (DEBUG_FILTERS) {
-                    Slog.i(TAG, "New activity; cap priority to 0;"
-                            + " package: " + applicationInfo.packageName
-                            + " activity: " + intent.activity.className
-                            + " origPrio: " + intent.getPriority());
-                }
-                intent.setPriority(0);
-                return;
-            }
-
-            // found activity, now check for filter equivalence
-
-            // a shallow copy is enough; we modify the list, not its contents
-            final List<ActivityIntentInfo> intentListCopy =
-                    new ArrayList<>(foundActivity.intents);
-            final List<ActivityIntentInfo> foundFilters = findFilters(intent);
-
-            // find matching action subsets
-            final Iterator<String> actionsIterator = intent.actionsIterator();
-            if (actionsIterator != null) {
-                getIntentListSubset(
-                        intentListCopy, new ActionIterGenerator(), actionsIterator);
-                if (intentListCopy.size() == 0) {
-                    // no more intents to match; we're not equivalent
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Mismatched action; cap priority to 0;"
-                                + " package: " + applicationInfo.packageName
-                                + " activity: " + intent.activity.className
-                                + " origPrio: " + intent.getPriority());
-                    }
-                    intent.setPriority(0);
-                    return;
-                }
-            }
-
-            // find matching category subsets
-            final Iterator<String> categoriesIterator = intent.categoriesIterator();
-            if (categoriesIterator != null) {
-                getIntentListSubset(intentListCopy, new CategoriesIterGenerator(),
-                        categoriesIterator);
-                if (intentListCopy.size() == 0) {
-                    // no more intents to match; we're not equivalent
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Mismatched category; cap priority to 0;"
-                                + " package: " + applicationInfo.packageName
-                                + " activity: " + intent.activity.className
-                                + " origPrio: " + intent.getPriority());
-                    }
-                    intent.setPriority(0);
-                    return;
-                }
-            }
-
-            // find matching schemes subsets
-            final Iterator<String> schemesIterator = intent.schemesIterator();
-            if (schemesIterator != null) {
-                getIntentListSubset(intentListCopy, new SchemesIterGenerator(),
-                        schemesIterator);
-                if (intentListCopy.size() == 0) {
-                    // no more intents to match; we're not equivalent
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
-                                + " package: " + applicationInfo.packageName
-                                + " activity: " + intent.activity.className
-                                + " origPrio: " + intent.getPriority());
-                    }
-                    intent.setPriority(0);
-                    return;
-                }
-            }
-
-            // find matching authorities subsets
-            final Iterator<IntentFilter.AuthorityEntry>
-                    authoritiesIterator = intent.authoritiesIterator();
-            if (authoritiesIterator != null) {
-                getIntentListSubset(intentListCopy,
-                        new AuthoritiesIterGenerator(),
-                        authoritiesIterator);
-                if (intentListCopy.size() == 0) {
-                    // no more intents to match; we're not equivalent
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Mismatched authority; cap priority to 0;"
-                                + " package: " + applicationInfo.packageName
-                                + " activity: " + intent.activity.className
-                                + " origPrio: " + intent.getPriority());
-                    }
-                    intent.setPriority(0);
-                    return;
-                }
-            }
-
-            // we found matching filter(s); app gets the max priority of all intents
-            int cappedPriority = 0;
-            for (int i = intentListCopy.size() - 1; i >= 0; --i) {
-                cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority());
-            }
-            if (intent.getPriority() > cappedPriority) {
-                if (DEBUG_FILTERS) {
-                    Slog.i(TAG, "Found matching filter(s);"
-                            + " cap priority to " + cappedPriority + ";"
-                            + " package: " + applicationInfo.packageName
-                            + " activity: " + intent.activity.className
-                            + " origPrio: " + intent.getPriority());
-                }
-                intent.setPriority(cappedPriority);
-                return;
-            }
-            // all this for nothing; the requested priority was <= what was on the system
-        }
-
-        public final void addActivity(PackageParser.Activity a, String type) {
-            mActivities.put(a.getComponentName(), a);
-            if (DEBUG_SHOW_INFO)
-                Log.v(
-                TAG, "  " + type + " " +
-                (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
-            if (DEBUG_SHOW_INFO)
-                Log.v(TAG, "    Class=" + a.info.name);
-            final int NI = a.intents.size();
-            for (int j=0; j<NI; j++) {
-                PackageParser.ActivityIntentInfo intent = a.intents.get(j);
-                if ("activity".equals(type)) {
-                    final PackageSetting ps =
-                            mSettings.getDisabledSystemPkgLPr(intent.activity.info.packageName);
-                    final List<PackageParser.Activity> systemActivities =
-                            ps != null && ps.pkg != null ? ps.pkg.activities : null;
-                    adjustPriority(systemActivities, intent);
-                }
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                if (!intent.debugCheck()) {
-                    Log.w(TAG, "==> For Activity " + a.info.name);
-                }
-                addFilter(intent);
-            }
-        }
-
-        public final void removeActivity(PackageParser.Activity a, String type) {
-            mActivities.remove(a.getComponentName());
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  " + type + " "
-                        + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
-                                : a.info.name) + ":");
-                Log.v(TAG, "    Class=" + a.info.name);
-            }
-            final int NI = a.intents.size();
-            for (int j=0; j<NI; j++) {
-                PackageParser.ActivityIntentInfo intent = a.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                removeFilter(intent);
-            }
-        }
-
-        @Override
-        protected boolean allowFilterResult(
-                PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
-            ActivityInfo filterAi = filter.activity.info;
-            for (int i=dest.size()-1; i>=0; i--) {
-                ActivityInfo destAi = dest.get(i).activityInfo;
-                if (destAi.name == filterAi.name
-                        && destAi.packageName == filterAi.packageName) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        @Override
-        protected ActivityIntentInfo[] newArray(int size) {
-            return new ActivityIntentInfo[size];
-        }
-
-        @Override
-        protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
-            if (!sUserManager.exists(userId)) return true;
-            PackageParser.Package p = filter.activity.owner;
-            if (p != null) {
-                PackageSetting ps = (PackageSetting)p.mExtras;
-                if (ps != null) {
-                    // System apps are never considered stopped for purposes of
-                    // filtering, because there may be no way for the user to
-                    // actually re-launch them.
-                    return (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
-                            && ps.getStopped(userId);
-                }
-            }
-            return false;
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName,
-                PackageParser.ActivityIntentInfo info) {
-            return packageName.equals(info.activity.owner.packageName);
-        }
-
-        @Override
-        protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
-                int match, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            if (!mSettings.isEnabledAndMatchLPr(info.activity.info, mFlags, userId)) {
-                return null;
-            }
-            final PackageParser.Activity activity = info.activity;
-            PackageSetting ps = (PackageSetting) activity.owner.mExtras;
-            if (ps == null) {
-                return null;
-            }
-            final PackageUserState userState = ps.readUserState(userId);
-            ActivityInfo ai =
-                    PackageParser.generateActivityInfo(activity, mFlags, userState, userId);
-            if (ai == null) {
-                return null;
-            }
-            final boolean matchExplicitlyVisibleOnly =
-                    (mFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
-            final boolean matchVisibleToInstantApp =
-                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-            final boolean componentVisible =
-                    matchVisibleToInstantApp
-                    && info.isVisibleToInstantApp()
-                    && (!matchExplicitlyVisibleOnly || info.isExplicitlyVisibleToInstantApp());
-            final boolean matchInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
-            // throw out filters that aren't visible to ephemeral apps
-            if (matchVisibleToInstantApp && !(componentVisible || userState.instantApp)) {
-                return null;
-            }
-            // throw out instant app filters if we're not explicitly requesting them
-            if (!matchInstantApp && userState.instantApp) {
-                return null;
-            }
-            // throw out instant app filters if updates are available; will trigger
-            // instant app resolution
-            if (userState.instantApp && ps.isUpdateAvailable()) {
-                return null;
-            }
-            final ResolveInfo res = new ResolveInfo();
-            res.activityInfo = ai;
-            if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
-                res.filter = info;
-            }
-            res.handleAllWebDataURI = info.handleAllWebDataURI();
-            res.priority = info.getPriority();
-            res.preferredOrder = activity.owner.mPreferredOrder;
-            //System.out.println("Result: " + res.activityInfo.className +
-            //                   " = " + res.priority);
-            res.match = match;
-            res.isDefault = info.hasDefault;
-            res.labelRes = info.labelRes;
-            res.nonLocalizedLabel = info.nonLocalizedLabel;
-            if (userNeedsBadging(userId)) {
-                res.noResourceId = true;
-            } else {
-                res.icon = info.icon;
-            }
-            res.iconResourceId = info.icon;
-            res.system = res.activityInfo.applicationInfo.isSystemApp();
-            res.isInstantAppAvailable = userState.instantApp;
-            return res;
-        }
-
-        @Override
-        protected void sortResults(List<ResolveInfo> results) {
-            results.sort(mResolvePrioritySorter);
-        }
-
-        @Override
-        protected void dumpFilter(PrintWriter out, String prefix,
-                PackageParser.ActivityIntentInfo filter) {
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(filter.activity)));
-                    out.print(' ');
-                    filter.activity.printComponentShortName(out);
-                    out.print(" filter ");
-                    out.println(Integer.toHexString(System.identityHashCode(filter)));
-        }
-
-        @Override
-        protected Object filterToLabel(PackageParser.ActivityIntentInfo filter) {
-            return filter.activity;
-        }
-
-        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
-            PackageParser.Activity activity = (PackageParser.Activity)label;
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(activity)));
-                    out.print(' ');
-                    activity.printComponentShortName(out);
-            if (count > 1) {
-                out.print(" ("); out.print(count); out.print(" filters)");
-            }
-            out.println();
-        }
-
-        // Keys are String (activity class name), values are Activity.
-        private final ArrayMap<ComponentName, PackageParser.Activity> mActivities
-                = new ArrayMap<>();
-        private int mFlags;
-    }
-
-    private final class ServiceIntentResolver
-            extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, int userId) {
-            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
-        }
-
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
-                int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            mFlags = flags;
-            return super.queryIntent(intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    userId);
-        }
-
-        public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            if (packageServices == null) {
-                return null;
-            }
-            mFlags = flags;
-            final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final int N = packageServices.size();
-            ArrayList<PackageParser.ServiceIntentInfo[]> listCut = new ArrayList<>(N);
-
-            ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
-            for (int i = 0; i < N; ++i) {
-                intentFilters = packageServices.get(i).intents;
-                if (intentFilters != null && intentFilters.size() > 0) {
-                    PackageParser.ServiceIntentInfo[] array =
-                            new PackageParser.ServiceIntentInfo[intentFilters.size()];
-                    intentFilters.toArray(array);
-                    listCut.add(array);
-                }
-            }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
-        }
-
-        public final void addService(PackageParser.Service s) {
-            mServices.put(s.getComponentName(), s);
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  "
-                        + (s.info.nonLocalizedLabel != null
-                        ? s.info.nonLocalizedLabel : s.info.name) + ":");
-                Log.v(TAG, "    Class=" + s.info.name);
-            }
-            final int NI = s.intents.size();
-            int j;
-            for (j=0; j<NI; j++) {
-                PackageParser.ServiceIntentInfo intent = s.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                if (!intent.debugCheck()) {
-                    Log.w(TAG, "==> For Service " + s.info.name);
-                }
-                addFilter(intent);
-            }
-        }
-
-        public final void removeService(PackageParser.Service s) {
-            mServices.remove(s.getComponentName());
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  " + (s.info.nonLocalizedLabel != null
-                        ? s.info.nonLocalizedLabel : s.info.name) + ":");
-                Log.v(TAG, "    Class=" + s.info.name);
-            }
-            final int NI = s.intents.size();
-            int j;
-            for (j=0; j<NI; j++) {
-                PackageParser.ServiceIntentInfo intent = s.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                removeFilter(intent);
-            }
-        }
-
-        @Override
-        protected boolean allowFilterResult(
-                PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
-            ServiceInfo filterSi = filter.service.info;
-            for (int i=dest.size()-1; i>=0; i--) {
-                ServiceInfo destAi = dest.get(i).serviceInfo;
-                if (destAi.name == filterSi.name
-                        && destAi.packageName == filterSi.packageName) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        @Override
-        protected PackageParser.ServiceIntentInfo[] newArray(int size) {
-            return new PackageParser.ServiceIntentInfo[size];
-        }
-
-        @Override
-        protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
-            if (!sUserManager.exists(userId)) return true;
-            PackageParser.Package p = filter.service.owner;
-            if (p != null) {
-                PackageSetting ps = (PackageSetting)p.mExtras;
-                if (ps != null) {
-                    // System apps are never considered stopped for purposes of
-                    // filtering, because there may be no way for the user to
-                    // actually re-launch them.
-                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
-                            && ps.getStopped(userId);
-                }
-            }
-            return false;
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName,
-                PackageParser.ServiceIntentInfo info) {
-            return packageName.equals(info.service.owner.packageName);
-        }
-
-        @Override
-        protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
-                int match, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
-            if (!mSettings.isEnabledAndMatchLPr(info.service.info, mFlags, userId)) {
-                return null;
-            }
-            final PackageParser.Service service = info.service;
-            PackageSetting ps = (PackageSetting) service.owner.mExtras;
-            if (ps == null) {
-                return null;
-            }
-            final PackageUserState userState = ps.readUserState(userId);
-            ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
-                    userState, userId);
-            if (si == null) {
-                return null;
-            }
-            final boolean matchVisibleToInstantApp =
-                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
-            // throw out filters that aren't visible to ephemeral apps
-            if (matchVisibleToInstantApp
-                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
-                return null;
-            }
-            // throw out ephemeral filters if we're not explicitly requesting them
-            if (!isInstantApp && userState.instantApp) {
-                return null;
-            }
-            // throw out instant app filters if updates are available; will trigger
-            // instant app resolution
-            if (userState.instantApp && ps.isUpdateAvailable()) {
-                return null;
-            }
-            final ResolveInfo res = new ResolveInfo();
-            res.serviceInfo = si;
-            if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
-                res.filter = filter;
-            }
-            res.priority = info.getPriority();
-            res.preferredOrder = service.owner.mPreferredOrder;
-            res.match = match;
-            res.isDefault = info.hasDefault;
-            res.labelRes = info.labelRes;
-            res.nonLocalizedLabel = info.nonLocalizedLabel;
-            res.icon = info.icon;
-            res.system = res.serviceInfo.applicationInfo.isSystemApp();
-            return res;
-        }
-
-        @Override
-        protected void sortResults(List<ResolveInfo> results) {
-            results.sort(mResolvePrioritySorter);
-        }
-
-        @Override
-        protected void dumpFilter(PrintWriter out, String prefix,
-                PackageParser.ServiceIntentInfo filter) {
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(filter.service)));
-                    out.print(' ');
-                    filter.service.printComponentShortName(out);
-                    out.print(" filter ");
-                    out.print(Integer.toHexString(System.identityHashCode(filter)));
-                    if (filter.service.info.permission != null) {
-                        out.print(" permission "); out.println(filter.service.info.permission);
-                    } else {
-                        out.println();
-                    }
-        }
-
-        @Override
-        protected Object filterToLabel(PackageParser.ServiceIntentInfo filter) {
-            return filter.service;
-        }
-
-        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
-            PackageParser.Service service = (PackageParser.Service)label;
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(service)));
-                    out.print(' ');
-                    service.printComponentShortName(out);
-            if (count > 1) {
-                out.print(" ("); out.print(count); out.print(" filters)");
-            }
-            out.println();
-        }
-
-//        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
-//            final Iterator<ResolveInfo> i = resolveInfoList.iterator();
-//            final List<ResolveInfo> retList = Lists.newArrayList();
-//            while (i.hasNext()) {
-//                final ResolveInfo resolveInfo = (ResolveInfo) i;
-//                if (isEnabledLP(resolveInfo.serviceInfo)) {
-//                    retList.add(resolveInfo);
-//                }
-//            }
-//            return retList;
-//        }
-
-        // Keys are String (activity class name), values are Activity.
-        private final ArrayMap<ComponentName, PackageParser.Service> mServices = new ArrayMap<>();
-        private int mFlags;
-    }
-
-    private final class ProviderIntentResolver
-            extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, int userId) {
-            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
-        }
-
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
-                int userId) {
-            if (!sUserManager.exists(userId))
-                return null;
-            mFlags = flags;
-            return super.queryIntent(intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    userId);
-        }
-
-        public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                int flags, ArrayList<PackageParser.Provider> packageProviders, int userId) {
-            if (!sUserManager.exists(userId))
-                return null;
-            if (packageProviders == null) {
-                return null;
-            }
-            mFlags = flags;
-            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final int N = packageProviders.size();
-            ArrayList<PackageParser.ProviderIntentInfo[]> listCut = new ArrayList<>(N);
-
-            ArrayList<PackageParser.ProviderIntentInfo> intentFilters;
-            for (int i = 0; i < N; ++i) {
-                intentFilters = packageProviders.get(i).intents;
-                if (intentFilters != null && intentFilters.size() > 0) {
-                    PackageParser.ProviderIntentInfo[] array =
-                            new PackageParser.ProviderIntentInfo[intentFilters.size()];
-                    intentFilters.toArray(array);
-                    listCut.add(array);
-                }
-            }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
-        }
-
-        public final void addProvider(PackageParser.Provider p) {
-            if (mProviders.containsKey(p.getComponentName())) {
-                Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
-                return;
-            }
-
-            mProviders.put(p.getComponentName(), p);
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  "
-                        + (p.info.nonLocalizedLabel != null
-                                ? p.info.nonLocalizedLabel : p.info.name) + ":");
-                Log.v(TAG, "    Class=" + p.info.name);
-            }
-            final int NI = p.intents.size();
-            int j;
-            for (j = 0; j < NI; j++) {
-                PackageParser.ProviderIntentInfo intent = p.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                if (!intent.debugCheck()) {
-                    Log.w(TAG, "==> For Provider " + p.info.name);
-                }
-                addFilter(intent);
-            }
-        }
-
-        public final void removeProvider(PackageParser.Provider p) {
-            mProviders.remove(p.getComponentName());
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  " + (p.info.nonLocalizedLabel != null
-                        ? p.info.nonLocalizedLabel : p.info.name) + ":");
-                Log.v(TAG, "    Class=" + p.info.name);
-            }
-            final int NI = p.intents.size();
-            int j;
-            for (j = 0; j < NI; j++) {
-                PackageParser.ProviderIntentInfo intent = p.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                removeFilter(intent);
-            }
-        }
-
-        @Override
-        protected boolean allowFilterResult(
-                PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) {
-            ProviderInfo filterPi = filter.provider.info;
-            for (int i = dest.size() - 1; i >= 0; i--) {
-                ProviderInfo destPi = dest.get(i).providerInfo;
-                if (destPi.name == filterPi.name
-                        && destPi.packageName == filterPi.packageName) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        @Override
-        protected PackageParser.ProviderIntentInfo[] newArray(int size) {
-            return new PackageParser.ProviderIntentInfo[size];
-        }
-
-        @Override
-        protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) {
-            if (!sUserManager.exists(userId))
-                return true;
-            PackageParser.Package p = filter.provider.owner;
-            if (p != null) {
-                PackageSetting ps = (PackageSetting) p.mExtras;
-                if (ps != null) {
-                    // System apps are never considered stopped for purposes of
-                    // filtering, because there may be no way for the user to
-                    // actually re-launch them.
-                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
-                            && ps.getStopped(userId);
-                }
-            }
-            return false;
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName,
-                PackageParser.ProviderIntentInfo info) {
-            return packageName.equals(info.provider.owner.packageName);
-        }
-
-        @Override
-        protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter,
-                int match, int userId) {
-            if (!sUserManager.exists(userId))
-                return null;
-            final PackageParser.ProviderIntentInfo info = filter;
-            if (!mSettings.isEnabledAndMatchLPr(info.provider.info, mFlags, userId)) {
-                return null;
-            }
-            final PackageParser.Provider provider = info.provider;
-            PackageSetting ps = (PackageSetting) provider.owner.mExtras;
-            if (ps == null) {
-                return null;
-            }
-            final PackageUserState userState = ps.readUserState(userId);
-            final boolean matchVisibleToInstantApp =
-                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
-            // throw out filters that aren't visible to instant applications
-            if (matchVisibleToInstantApp
-                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
-                return null;
-            }
-            // throw out instant application filters if we're not explicitly requesting them
-            if (!isInstantApp && userState.instantApp) {
-                return null;
-            }
-            // throw out instant application filters if updates are available; will trigger
-            // instant application resolution
-            if (userState.instantApp && ps.isUpdateAvailable()) {
-                return null;
-            }
-            ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
-                    userState, userId);
-            if (pi == null) {
-                return null;
-            }
-            final ResolveInfo res = new ResolveInfo();
-            res.providerInfo = pi;
-            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
-                res.filter = filter;
-            }
-            res.priority = info.getPriority();
-            res.preferredOrder = provider.owner.mPreferredOrder;
-            res.match = match;
-            res.isDefault = info.hasDefault;
-            res.labelRes = info.labelRes;
-            res.nonLocalizedLabel = info.nonLocalizedLabel;
-            res.icon = info.icon;
-            res.system = res.providerInfo.applicationInfo.isSystemApp();
-            return res;
-        }
-
-        @Override
-        protected void sortResults(List<ResolveInfo> results) {
-            results.sort(mResolvePrioritySorter);
-        }
-
-        @Override
-        protected void dumpFilter(PrintWriter out, String prefix,
-                PackageParser.ProviderIntentInfo filter) {
-            out.print(prefix);
-            out.print(
-                    Integer.toHexString(System.identityHashCode(filter.provider)));
-            out.print(' ');
-            filter.provider.printComponentShortName(out);
-            out.print(" filter ");
-            out.println(Integer.toHexString(System.identityHashCode(filter)));
-        }
-
-        @Override
-        protected Object filterToLabel(PackageParser.ProviderIntentInfo filter) {
-            return filter.provider;
-        }
-
-        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
-            PackageParser.Provider provider = (PackageParser.Provider)label;
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(provider)));
-                    out.print(' ');
-                    provider.printComponentShortName(out);
-            if (count > 1) {
-                out.print(" ("); out.print(count); out.print(" filters)");
-            }
-            out.println();
-        }
-
-        private final ArrayMap<ComponentName, PackageParser.Provider> mProviders
-                = new ArrayMap<>();
-        private int mFlags;
-    }
-
-    static final class InstantAppIntentResolver
-            extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter,
-            AuxiliaryResolveInfo.AuxiliaryFilter> {
-        /**
-         * The result that has the highest defined order. Ordering applies on a
-         * per-package basis. Mapping is from package name to Pair of order and
-         * EphemeralResolveInfo.
-         * <p>
-         * NOTE: This is implemented as a field variable for convenience and efficiency.
-         * By having a field variable, we're able to track filter ordering as soon as
-         * a non-zero order is defined. Otherwise, multiple loops across the result set
-         * would be needed to apply ordering. If the intent resolver becomes re-entrant,
-         * this needs to be contained entirely within {@link #filterResults}.
-         */
-        final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult = new ArrayMap<>();
-
-        @Override
-        protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) {
-            return new AuxiliaryResolveInfo.AuxiliaryFilter[size];
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName,
-                AuxiliaryResolveInfo.AuxiliaryFilter responseObj) {
-            return true;
-        }
-
-        @Override
-        protected AuxiliaryResolveInfo.AuxiliaryFilter newResult(
-                AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId) {
-            if (!sUserManager.exists(userId)) {
-                return null;
-            }
-            final String packageName = responseObj.resolveInfo.getPackageName();
-            final Integer order = responseObj.getOrder();
-            final Pair<Integer, InstantAppResolveInfo> lastOrderResult =
-                    mOrderResult.get(packageName);
-            // ordering is enabled and this item's order isn't high enough
-            if (lastOrderResult != null && lastOrderResult.first >= order) {
-                return null;
-            }
-            final InstantAppResolveInfo res = responseObj.resolveInfo;
-            if (order > 0) {
-                // non-zero order, enable ordering
-                mOrderResult.put(packageName, new Pair<>(order, res));
-            }
-            return responseObj;
-        }
-
-        @Override
-        protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
-            // only do work if ordering is enabled [most of the time it won't be]
-            if (mOrderResult.size() == 0) {
-                return;
-            }
-            int resultSize = results.size();
-            for (int i = 0; i < resultSize; i++) {
-                final InstantAppResolveInfo info = results.get(i).resolveInfo;
-                final String packageName = info.getPackageName();
-                final Pair<Integer, InstantAppResolveInfo> savedInfo = mOrderResult.get(packageName);
-                if (savedInfo == null) {
-                    // package doesn't having ordering
-                    continue;
-                }
-                if (savedInfo.second == info) {
-                    // circled back to the highest ordered item; remove from order list
-                    mOrderResult.remove(packageName);
-                    if (mOrderResult.size() == 0) {
-                        // no more ordered items
-                        break;
-                    }
-                    continue;
-                }
-                // item has a worse order, remove it from the result list
-                results.remove(i);
-                resultSize--;
-                i--;
-            }
-        }
-    }
-
-    private static final Comparator<ResolveInfo> mResolvePrioritySorter = (r1, r2) -> {
-        int v1 = r1.priority;
-        int v2 = r2.priority;
-        //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
-        if (v1 != v2) {
-            return (v1 > v2) ? -1 : 1;
-        }
-        v1 = r1.preferredOrder;
-        v2 = r2.preferredOrder;
-        if (v1 != v2) {
-            return (v1 > v2) ? -1 : 1;
-        }
-        if (r1.isDefault != r2.isDefault) {
-            return r1.isDefault ? -1 : 1;
-        }
-        v1 = r1.match;
-        v2 = r2.match;
-        //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
-        if (v1 != v2) {
-            return (v1 > v2) ? -1 : 1;
-        }
-        if (r1.system != r2.system) {
-            return r1.system ? -1 : 1;
-        }
-        if (r1.activityInfo != null) {
-            return r1.activityInfo.packageName.compareTo(r2.activityInfo.packageName);
-        }
-        if (r1.serviceInfo != null) {
-            return r1.serviceInfo.packageName.compareTo(r2.serviceInfo.packageName);
-        }
-        if (r1.providerInfo != null) {
-            return r1.providerInfo.packageName.compareTo(r2.providerInfo.packageName);
-        }
-        return 0;
-    };
-
-    private static final Comparator<ProviderInfo> mProviderInitOrderSorter = (p1, p2) -> {
-        final int v1 = p1.initOrder;
-        final int v2 = p2.initOrder;
-        return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
-    };
-
     @Override
     public void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
             final int flags, final String targetPkg, final IIntentReceiver finishedReceiver,
@@ -13542,6 +12326,12 @@
         }
     }
 
+    private static final Comparator<ProviderInfo> sProviderInitOrderSorter = (p1, p2) -> {
+        final int v1 = p1.initOrder;
+        final int v2 = p2.initOrder;
+        return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
+    };
+
     @Override
     public void notifyPackageRemoved(String packageName) {
         final PackageListObserver[] observers;
@@ -13995,11 +12785,12 @@
         info.sendPackageRemovedBroadcasts(true /*killApp*/);
     }
 
-    private void sendPackagesSuspendedForUser(String[] pkgList, int userId, boolean suspended,
-            PersistableBundle launcherExtras) {
+    private void sendPackagesSuspendedForUser(String[] pkgList, int[] uidList, int userId,
+            boolean suspended, PersistableBundle launcherExtras) {
         if (pkgList.length > 0) {
             Bundle extras = new Bundle(1);
             extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
+            extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
             if (launcherExtras != null) {
                 extras.putBundle(Intent.EXTRA_LAUNCHER_EXTRAS,
                         new Bundle(launcherExtras.deepCopy()));
@@ -14181,6 +12972,7 @@
         }
 
         final List<String> changedPackagesList = new ArrayList<>(packageNames.length);
+        final IntArray changedUids = new IntArray(packageNames.length);
         final List<String> unactionedPackages = new ArrayList<>(packageNames.length);
         final long callingId = Binder.clearCallingIdentity();
         try {
@@ -14208,6 +13000,7 @@
                     pkgSetting.setSuspended(suspended, callingPackage, dialogMessage, appExtras,
                             launcherExtras, userId);
                     changedPackagesList.add(packageName);
+                    changedUids.add(UserHandle.getUid(userId, pkgSetting.appId));
                 }
             }
         } finally {
@@ -14216,7 +13009,8 @@
         if (!changedPackagesList.isEmpty()) {
             final String[] changedPackages = changedPackagesList.toArray(
                     new String[changedPackagesList.size()]);
-            sendPackagesSuspendedForUser(changedPackages, userId, suspended, launcherExtras);
+            sendPackagesSuspendedForUser(
+                    changedPackages, changedUids.toArray(), userId, suspended, launcherExtras);
             sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, appExtras, userId);
             synchronized (mPackages) {
                 scheduleWritePackageRestrictionsLocked(userId);
@@ -14331,12 +13125,14 @@
 
     private void unsuspendForSuspendingPackages(Predicate<String> packagePredicate, int userId) {
         final List<String> affectedPackages = new ArrayList<>();
+        final IntArray affectedUids = new IntArray();
         synchronized (mPackages) {
             for (PackageSetting ps : mSettings.mPackages.values()) {
                 final PackageUserState pus = ps.readUserState(userId);
                 if (pus.suspended && packagePredicate.test(pus.suspendingPackage)) {
                     ps.setSuspended(false, null, null, null, null, userId);
                     affectedPackages.add(ps.name);
+                    affectedUids.add(UserHandle.getUid(userId, ps.getAppId()));
                 }
             }
         }
@@ -14344,7 +13140,8 @@
             final String[] packageArray = affectedPackages.toArray(
                     new String[affectedPackages.size()]);
             sendMyPackageSuspendedOrUnsuspended(packageArray, false, null, userId);
-            sendPackagesSuspendedForUser(packageArray, userId, false, null);
+            sendPackagesSuspendedForUser(
+                    packageArray, affectedUids.toArray(), userId, false, null);
             // Write package restrictions immediately to avoid an inconsistent state.
             mSettings.writePackageRestrictionsLPr(userId);
         }
@@ -14389,6 +13186,12 @@
             return false;
         }
 
+        if (packageName.equals(mRequiredPermissionControllerPackage)) {
+            Slog.w(TAG, "Cannot suspend package \"" + packageName
+                    + "\": required for permissions management");
+            return false;
+        }
+
         if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
             Slog.w(TAG, "Cannot suspend package \"" + packageName
                     + "\": protected package");
@@ -15739,7 +14542,7 @@
          * Rename package into final resting place. All paths on the given
          * scanned package should be updated to reflect the rename.
          */
-        abstract boolean doRename(int status, PackageParser.Package pkg, String oldCodePath);
+        abstract boolean doRename(int status, PackageParser.Package pkg);
         abstract int doPostInstall(int status, int uid);
 
         /** @see PackageSettingBase#codePathString */
@@ -15915,7 +14718,7 @@
             return status;
         }
 
-        boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
+        boolean doRename(int status, PackageParser.Package pkg) {
             if (status != PackageManager.INSTALL_SUCCEEDED) {
                 cleanUp();
                 return false;
@@ -16074,7 +14877,7 @@
             return status;
         }
 
-        boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
+        boolean doRename(int status, PackageParser.Package pkg) {
             if (status != PackageManager.INSTALL_SUCCEEDED) {
                 cleanUp(move.toUuid);
                 return false;
@@ -16268,14 +15071,18 @@
         }
 
         try {
-            PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags, scanFlags,
+            final PackageParser.Package newPackage;
+            List<ScanResult> scanResults = scanPackageTracedLI(pkg, parseFlags, scanFlags,
                     System.currentTimeMillis(), user);
-
+            commitSuccessfulScanResults(scanResults);
+            // TODO(b/109941548): Child packages may return >1 result with the first being the base;
+            // we need to treat child packages as an atomic install and remove this hack
+            final ScanResult basePackageScanResult = scanResults.get(0);
+            newPackage = basePackageScanResult.pkgSetting.pkg;
             updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
 
             if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                 prepareAppDataAfterInstallLIF(newPackage);
-
             } else {
                 // Remove package from internal structures, but keep around any
                 // data that might have already existed
@@ -16283,6 +15090,9 @@
                         PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
             }
         } catch (PackageManagerException e) {
+            destroyAppDataLIF(pkg, UserHandle.USER_ALL,
+                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+            destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
             res.setError("Package couldn't be installed in " + pkg.codePath, e);
         }
 
@@ -16480,13 +15290,16 @@
             final boolean oem = isOemApp(oldPackage);
             final boolean vendor = isVendorApp(oldPackage);
             final boolean product = isProductApp(oldPackage);
+            final boolean productServices = isProductServicesApp(oldPackage);
+
             final @ParseFlags int systemParseFlags = parseFlags;
             final @ScanFlags int systemScanFlags = scanFlags
                     | SCAN_AS_SYSTEM
                     | (privileged ? SCAN_AS_PRIVILEGED : 0)
                     | (oem ? SCAN_AS_OEM : 0)
                     | (vendor ? SCAN_AS_VENDOR : 0)
-                    | (product ? SCAN_AS_PRODUCT : 0);
+                    | (product ? SCAN_AS_PRODUCT : 0)
+                    | (productServices ? SCAN_AS_PRODUCT_SERVICES : 0);
 
             replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags,
                     user, allUsers, installerPackageName, res, installReason);
@@ -16539,8 +15352,10 @@
                     | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
 
             try {
-                final PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags,
+                final List<ScanResult> scanResults = scanPackageTracedLI(pkg, parseFlags,
                         scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
+                commitSuccessfulScanResults(scanResults);
+                final PackageParser.Package newPackage = scanResults.get(0).pkgSetting.pkg;
                 updateSettingsLI(newPackage, installerPackageName, allUsers, res, user,
                         installReason);
 
@@ -16678,8 +15493,11 @@
 
         PackageParser.Package newPackage = null;
         try {
+            final List<ScanResult> scanResults =
+                    scanPackageTracedLI(pkg, parseFlags, scanFlags, 0, user);
             // Add the package to the internal data structures
-            newPackage = scanPackageTracedLI(pkg, parseFlags, scanFlags, 0, user);
+            commitSuccessfulScanResults(scanResults);
+            newPackage = scanResults.get(0).pkgSetting.pkg;
 
             // Set the update and install times
             PackageSetting deletedPkgSetting = (PackageSetting) deletedPackage.mExtras;
@@ -16736,7 +15554,9 @@
             }
             // Add back the old system package
             try {
-                scanPackageTracedLI(deletedPackage, parseFlags, SCAN_UPDATE_SIGNATURE, 0, user);
+                final List<ScanResult> scanResults = scanPackageTracedLI(
+                        deletedPackage, parseFlags, SCAN_UPDATE_SIGNATURE, 0, user);
+                commitSuccessfulScanResults(scanResults);
             } catch (PackageManagerException e) {
                 Slog.e(TAG, "Failed to restore original package: " + e.getMessage());
             }
@@ -16812,6 +15632,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private void enableSystemPackageLPw(PackageParser.Package pkg) {
         // Enable the parent package
         mSettings.enableSystemPackageLPw(pkg.packageName);
@@ -16823,6 +15644,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private boolean disableSystemPackageLPw(PackageParser.Package oldPkg,
             PackageParser.Package newPkg) {
         // Disable the parent package (parent always replaced)
@@ -16837,6 +15659,7 @@
         return disabled;
     }
 
+    @GuardedBy("mPackages")
     private void setInstallerPackageNameLPw(PackageParser.Package pkg,
             String installerPackageName) {
         // Enable the parent package
@@ -16955,17 +15778,92 @@
 
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
     }
+    private static class InstallRequest {
+        final InstallArgs args;
+        final PackageInstalledInfo res;
 
+        private InstallRequest(InstallArgs args, PackageInstalledInfo res) {
+            this.args = args;
+            this.res = res;
+        }
+    }
+
+    @GuardedBy({"mInstallLock", "mPackages"})
     private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) {
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
-            installPackageLI(args, res);
+            installPackagesLI(Collections.singletonList(new InstallRequest(args, res)));
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
     }
 
-    private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
+    private static class CommitRequest {
+        final Map<String, ReconciledPackage> reconciledPackages;
+
+        private CommitRequest(Map<String, ReconciledPackage> reconciledPackages) {
+            this.reconciledPackages = reconciledPackages;
+        }
+    }
+    private static class ReconcileRequest {
+        final Map<String, ScanResult> scannedPackages;
+
+        private ReconcileRequest(Map<String, ScanResult> scannedPackages) {
+            this.scannedPackages = scannedPackages;
+        }
+    }
+    private static class ReconcileFailure extends PackageManagerException {
+        public ReconcileFailure(String message) {
+            super("Invalid reconcile request: " + message);
+        }
+    };
+
+    /**
+     * A container of all data needed to commit a package to in-memory data structures and to disk.
+     * Ideally most of the data contained in this class will move into a PackageSetting it contains.
+     */
+    private static class ReconciledPackage {}
+
+    @GuardedBy("mPackages")
+    private static Map<String, ReconciledPackage> reconcilePackagesLocked(
+            final ReconcileRequest request) throws ReconcileFailure {
+        return Collections.emptyMap();
+    }
+
+    @GuardedBy("mPackages")
+    private boolean commitPackagesLocked(final CommitRequest request) {
+        return true;
+    }
+
+    @GuardedBy({"mInstallLock", "mPackages", "PackageManagerService.mPackages"})
+    private void installPackagesLI(List<InstallRequest> requests) {
+        Map<String, ScanResult> scans = new ArrayMap<>(requests.size());
+        for (InstallRequest request : requests) {
+            // TODO(b/109941548): remove this once we've pulled everything from it and into scan,
+            // reconcile or commit.
+            preparePackageLI(request.args, request.res);
+
+            // TODO(b/109941548): scan package and get result
+        }
+        ReconcileRequest reconcileRequest = new ReconcileRequest(scans);
+        Map<String, ReconciledPackage> reconciledPackages;
+        try {
+            reconciledPackages = reconcilePackagesLocked(reconcileRequest);
+        } catch (ReconcileFailure e) {
+            // TODO(b/109941548): set install args error
+            return;
+        }
+        CommitRequest request = new CommitRequest(reconciledPackages);
+        if (!commitPackagesLocked(request)) {
+            // TODO(b/109941548): set install args error
+            return;
+        }
+        // TODO(b/109941548) post-commit actions (dex-opt, etc.)
+    }
+
+    @Deprecated
+    @GuardedBy("mInstallLock")
+    private void preparePackageLI(InstallArgs args, PackageInstalledInfo res) {
         final int installFlags = args.installFlags;
         final String installerPackageName = args.installerPackageName;
         final String volumeUuid = args.volumeUuid;
@@ -17043,13 +15941,6 @@
                         "Instant app package must target at least O");
                 return;
             }
-            if (pkg.applicationInfo.targetSandboxVersion != 2) {
-                Slog.w(TAG, "Instant app package " + pkg.packageName
-                        + " does not target targetSandboxVersion 2");
-                res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
-                        "Instant app package must use targetSandboxVersion 2");
-                return;
-            }
             if (pkg.mSharedUserId != null) {
                 Slog.w(TAG, "Instant app package " + pkg.packageName
                         + " may not declare sharedUserId.");
@@ -17137,7 +16028,6 @@
 
         // Get rid of all references to package scan path via parser.
         pp = null;
-        String oldCodePath = null;
         boolean systemApp = false;
         synchronized (mPackages) {
             // Check if installing already existing package
@@ -17249,7 +16139,6 @@
                     }
                 }
 
-                oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
                 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
                     systemApp = (ps.pkg.applicationInfo.flags &
                             ApplicationInfo.FLAG_SYSTEM) != 0;
@@ -17399,7 +16288,7 @@
             }
         }
 
-        if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
+        if (!args.doRename(res.returnCode, pkg)) {
             res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
             return;
         }
@@ -17471,7 +16360,7 @@
                 replacePackageLIF(pkg, parseFlags, scanFlags, args.user,
                         installerPackageName, res, args.installReason);
             } else {
-                installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
+                installNewPackageLIF(pkg, parseFlags, scanFlags,
                         args.user, installerPackageName, volumeUuid, res, args.installReason);
             }
         }
@@ -17665,6 +16554,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private boolean needsNetworkVerificationLPr(ActivityIntentInfo filter) {
         final ComponentName cn  = filter.activity.getComponentName();
         final String packageName = cn.getPackageName();
@@ -17718,6 +16608,11 @@
         return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
     }
 
+    private static boolean isProductServicesApp(PackageParser.Package pkg) {
+        return (pkg.applicationInfo.privateFlags
+                & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
+    }
+
     private static boolean hasDomainURLs(PackageParser.Package pkg) {
         return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
     }
@@ -17899,6 +16794,7 @@
         return pkg.packageName;
     }
 
+    @GuardedBy("mPackages")
     private String resolveInternalPackageNameLPr(String packageName, long versionCode) {
         // Handle renamed packages
         String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
@@ -18456,10 +17352,13 @@
             final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
             final File privilegedOdmAppDir = new File(Environment.getOdmDirectory(), "priv-app");
             final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
-            return path.startsWith(privilegedAppDir.getCanonicalPath())
-                    || path.startsWith(privilegedVendorAppDir.getCanonicalPath())
-                    || path.startsWith(privilegedOdmAppDir.getCanonicalPath())
-                    || path.startsWith(privilegedProductAppDir.getCanonicalPath());
+            final File privilegedProductServicesAppDir =
+                    new File(Environment.getProductServicesDirectory(), "priv-app");
+            return path.startsWith(privilegedAppDir.getCanonicalPath() + "/")
+                    || path.startsWith(privilegedVendorAppDir.getCanonicalPath() + "/")
+                    || path.startsWith(privilegedOdmAppDir.getCanonicalPath() + "/")
+                    || path.startsWith(privilegedProductAppDir.getCanonicalPath() + "/")
+                    || path.startsWith(privilegedProductServicesAppDir.getCanonicalPath() + "/");
         } catch (IOException e) {
             Slog.e(TAG, "Unable to access code path " + path);
         }
@@ -18468,7 +17367,7 @@
 
     static boolean locationIsOem(String path) {
         try {
-            return path.startsWith(Environment.getOemDirectory().getCanonicalPath());
+            return path.startsWith(Environment.getOemDirectory().getCanonicalPath() + "/");
         } catch (IOException e) {
             Slog.e(TAG, "Unable to access code path " + path);
         }
@@ -18477,8 +17376,8 @@
 
     static boolean locationIsVendor(String path) {
         try {
-            return path.startsWith(Environment.getVendorDirectory().getCanonicalPath())
-                    || path.startsWith(Environment.getOdmDirectory().getCanonicalPath());
+            return path.startsWith(Environment.getVendorDirectory().getCanonicalPath() + "/")
+                    || path.startsWith(Environment.getOdmDirectory().getCanonicalPath() + "/");
         } catch (IOException e) {
             Slog.e(TAG, "Unable to access code path " + path);
         }
@@ -18487,7 +17386,17 @@
 
     static boolean locationIsProduct(String path) {
         try {
-            return path.startsWith(Environment.getProductDirectory().getCanonicalPath());
+            return path.startsWith(Environment.getProductDirectory().getCanonicalPath() + "/");
+        } catch (IOException e) {
+            Slog.e(TAG, "Unable to access code path " + path);
+        }
+        return false;
+    }
+
+    static boolean locationIsProductServices(String path) {
+        try {
+            return path.startsWith(
+              Environment.getProductServicesDirectory().getCanonicalPath() + "/");
         } catch (IOException e) {
             Slog.e(TAG, "Unable to access code path " + path);
         }
@@ -18621,6 +17530,9 @@
         if (locationIsProduct(codePathString)) {
             scanFlags |= SCAN_AS_PRODUCT;
         }
+        if (locationIsProductServices(codePathString)) {
+            scanFlags |= SCAN_AS_PRODUCT_SERVICES;
+        }
 
         final File codePath = new File(codePathString);
         final PackageParser.Package pkg =
@@ -18965,6 +17877,7 @@
         return ret;
     }
 
+    @GuardedBy("mPackages")
     private void markPackageUninstalledForUserLPw(PackageSetting ps, UserHandle user) {
         final int[] userIds = (user == null || user.getIdentifier() == UserHandle.USER_ALL)
                 ? sUserManager.getUserIds() : new int[] {user.getIdentifier()};
@@ -19239,6 +18152,7 @@
      *
      * @param userId The device user for which to do a reset.
      */
+    @GuardedBy("mPackages")
     private void resetUserChangesToRuntimePermissionsAndFlagsLPw(int userId) {
         final int packageCount = mPackages.size();
         for (int i = 0; i < packageCount; i++) {
@@ -19258,6 +18172,7 @@
      * @param ps The package for which to reset.
      * @param userId The device user for which to do a reset.
      */
+    @GuardedBy("mPackages")
     private void resetUserChangesToRuntimePermissionsAndFlagsLPw(
             final PackageSetting ps, final int userId) {
         if (ps.pkg == null) {
@@ -19312,8 +18227,7 @@
             // If permission review is enabled and this is a legacy app, mark the
             // permission as requiring a review as this is the initial state.
             int flags = 0;
-            if (mSettings.mPermissions.mPermissionReviewRequired
-                    && ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+            if (ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M && bp.isRuntime()) {
                 flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
             }
             if (permissionsState.updatePermissionFlags(bp, userId, userSettableMask, flags)) {
@@ -19466,6 +18380,7 @@
                 "Shame on you for calling the hidden API getPackageSizeInfo(). Shame!");
     }
 
+    @GuardedBy("mInstallLock")
     private boolean getPackageSizeInfoLI(String packageName, int userId, PackageStats stats) {
         final PackageSetting ps;
         synchronized (mPackages) {
@@ -19500,6 +18415,7 @@
         return true;
     }
 
+    @GuardedBy("mPackages")
     private int getUidTargetSdkVersionLockedLPr(int uid) {
         Object obj = mSettings.getUserIdLPr(uid);
         if (obj instanceof SharedUserSetting) {
@@ -19523,6 +18439,7 @@
         return Build.VERSION_CODES.CUR_DEVELOPMENT;
     }
 
+    @GuardedBy("mPackages")
     private int getPackageTargetSdkVersionLockedLPr(String packageName) {
         final PackageParser.Package p = mPackages.get(packageName);
         if (p != null) {
@@ -19718,6 +18635,7 @@
     }
 
     /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+    @GuardedBy("mPackages")
     boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
         ArrayList<PreferredActivity> removed = null;
         boolean changed = false;
@@ -19756,6 +18674,7 @@
     }
 
     /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+    @GuardedBy("mPackages")
     private void clearIntentFilterVerificationsLPw(int userId) {
         final int packageCount = mPackages.size();
         for (int i = 0; i < packageCount; i++) {
@@ -19765,6 +18684,7 @@
     }
 
     /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+    @GuardedBy("mPackages")
     void clearIntentFilterVerificationsLPw(String packageName, int userId) {
         if (userId == UserHandle.USER_ALL) {
             if (mSettings.removeIntentFilterVerificationLPw(packageName,
@@ -19805,7 +18725,7 @@
         try {
             synchronized (mPackages) {
                 clearPackagePreferredActivitiesLPw(null, userId);
-                mSettings.applyDefaultPreferredAppsLPw(this, userId);
+                mSettings.applyDefaultPreferredAppsLPw(userId);
                 // TODO: We have to reset the default SMS and Phone. This requires
                 // significant refactoring to keep all default apps in the package
                 // manager (cleaner but more work) or have the services provide
@@ -20175,6 +19095,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private void serializeRuntimePermissionGrantsLPr(XmlSerializer serializer, final int userId)
             throws IOException {
         serializer.startTag(null, TAG_ALL_GRANTS);
@@ -20234,6 +19155,7 @@
         serializer.endTag(null, TAG_ALL_GRANTS);
     }
 
+    @GuardedBy("mPackages")
     private void processRestoredPermissionGrantsLPr(XmlPullParser parser, int userId)
             throws XmlPullParserException, IOException {
         String pkgName = null;
@@ -20967,7 +19889,8 @@
     }
 
     @Override
-    public int getComponentEnabledSetting(ComponentName component, int userId) {
+    public int getComponentEnabledSetting(@NonNull ComponentName component, int userId) {
+        if (component == null) return COMPONENT_ENABLED_STATE_DEFAULT;
         if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
         int callingUid = Binder.getCallingUid();
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
@@ -21016,6 +19939,8 @@
         CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this,
                 mContext.getContentResolver(), UserHandle.USER_SYSTEM);
 
+        disableSkuSpecificApps();
+
         // Read the compatibilty setting when the system is ready.
         boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
                 mContext.getContentResolver(),
@@ -21041,7 +19966,7 @@
                 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
                 removed.clear();
                 for (PreferredActivity pa : pir.filterSet()) {
-                    if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
+                    if (!mComponentResolver.isActivityDefined(pa.mPref.mComponent)) {
                         removed.add(pa);
                     }
                 }
@@ -21102,15 +20027,20 @@
         mDexManager.systemReady();
         mPackageDexOptimizer.systemReady();
 
-        StorageManagerInternal StorageManagerInternal = LocalServices.getService(
+        StorageManagerInternal storageManagerInternal = LocalServices.getService(
                 StorageManagerInternal.class);
-        StorageManagerInternal.addExternalStoragePolicy(
+        storageManagerInternal.addExternalStoragePolicy(
                 new StorageManagerInternal.ExternalStorageMountPolicy() {
             @Override
             public int getMountMode(int uid, String packageName) {
                 if (Process.isIsolated(uid)) {
                     return Zygote.MOUNT_EXTERNAL_NONE;
                 }
+                if (SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+                    return checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED
+                            ? Zygote.MOUNT_EXTERNAL_FULL
+                            : Zygote.MOUNT_EXTERNAL_WRITE;
+                }
                 if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
                     return Zygote.MOUNT_EXTERNAL_DEFAULT;
                 }
@@ -21184,6 +20114,7 @@
                 this, in, out, err, args, callback, resultReceiver);
     }
 
+    @SuppressWarnings("resource")
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
@@ -21514,32 +20445,16 @@
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_ACTIVITY_RESOLVERS)) {
-                if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
-                        : "Activity Resolver Table:", "  ", packageName,
-                        dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
-                    dumpState.setTitlePrinted(true);
-                }
+                mComponentResolver.dumpActivityResolvers(pw, dumpState, packageName);
             }
             if (!checkin && dumpState.isDumping(DumpState.DUMP_RECEIVER_RESOLVERS)) {
-                if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
-                        : "Receiver Resolver Table:", "  ", packageName,
-                        dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
-                    dumpState.setTitlePrinted(true);
-                }
+                mComponentResolver.dumpReceiverResolvers(pw, dumpState, packageName);
             }
             if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_RESOLVERS)) {
-                if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
-                        : "Service Resolver Table:", "  ", packageName,
-                        dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
-                    dumpState.setTitlePrinted(true);
-                }
+                mComponentResolver.dumpServiceResolvers(pw, dumpState, packageName);
             }
             if (!checkin && dumpState.isDumping(DumpState.DUMP_CONTENT_RESOLVERS)) {
-                if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
-                        : "Provider Resolver Table:", "  ", packageName,
-                        dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
-                    dumpState.setTitlePrinted(true);
-                }
+                mComponentResolver.dumpProviderResolvers(pw, dumpState, packageName);
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
@@ -21641,40 +20556,7 @@
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
-                boolean printedSomething = false;
-                for (PackageParser.Provider p : mProviders.mProviders.values()) {
-                    if (packageName != null && !packageName.equals(p.info.packageName)) {
-                        continue;
-                    }
-                    if (!printedSomething) {
-                        if (dumpState.onTitlePrinted())
-                            pw.println();
-                        pw.println("Registered ContentProviders:");
-                        printedSomething = true;
-                    }
-                    pw.print("  "); p.printComponentShortName(pw); pw.println(":");
-                    pw.print("    "); pw.println(p.toString());
-                }
-                printedSomething = false;
-                for (Map.Entry<String, PackageParser.Provider> entry :
-                        mProvidersByAuthority.entrySet()) {
-                    PackageParser.Provider p = entry.getValue();
-                    if (packageName != null && !packageName.equals(p.info.packageName)) {
-                        continue;
-                    }
-                    if (!printedSomething) {
-                        if (dumpState.onTitlePrinted())
-                            pw.println();
-                        pw.println("ContentProvider Authorities:");
-                        printedSomething = true;
-                    }
-                    pw.print("  ["); pw.print(entry.getKey()); pw.println("]:");
-                    pw.print("    "); pw.println(p.toString());
-                    if (p.info != null && p.info.applicationInfo != null) {
-                        final String appInfo = p.info.applicationInfo.toString();
-                        pw.print("      applicationInfo="); pw.println(appInfo);
-                    }
-                }
+                mComponentResolver.dumpContentProviders(pw, dumpState, packageName);
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
@@ -21756,21 +20638,7 @@
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_PERMISSIONS)
                     && packageName == null) {
-                if (dumpState.onTitlePrinted()) pw.println();
-                pw.println("Service permissions:");
-
-                final Iterator<ServiceIntentInfo> filterIterator = mServices.filterIterator();
-                while (filterIterator.hasNext()) {
-                    final ServiceIntentInfo info = filterIterator.next();
-                    final ServiceInfo serviceInfo = info.service.info;
-                    final String permission = serviceInfo.permission;
-                    if (permission != null) {
-                        pw.print("    ");
-                        pw.print(serviceInfo.getComponentName().flattenToShortString());
-                        pw.print(": ");
-                        pw.println(permission);
-                    }
-                }
+                mComponentResolver.dumpServicePermissions(pw, dumpState, packageName);
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_DEXOPT)) {
@@ -21806,6 +20674,27 @@
         }
     }
 
+    //TODO: b/111402650
+    private void disableSkuSpecificApps() {
+        String apkList[] = mContext.getResources().getStringArray(
+                R.array.config_disableApksUnlessMatchedSku_apk_list);
+        String skuArray[] = mContext.getResources().getStringArray(
+                R.array.config_disableApkUnlessMatchedSku_skus_list);
+        if (ArrayUtils.isEmpty(apkList)) {
+           return;
+        }
+        String sku = SystemProperties.get("ro.boot.hardware.sku");
+        if (!TextUtils.isEmpty(sku) && ArrayUtils.contains(skuArray, sku)) {
+            return;
+        }
+        for (String packageName : apkList) {
+            setSystemAppHiddenUntilInstalled(packageName, true);
+            for (UserInfo user : sUserManager.getUsers(false)) {
+                setSystemAppInstallState(packageName, false, user.id);
+            }
+        }
+    }
+
     private void dumpProto(FileDescriptor fd) {
         final ProtoOutputStream proto = new ProtoOutputStream(fd);
 
@@ -21879,6 +20768,8 @@
         }
     }
 
+    @GuardedBy("mPackages")
+    @SuppressWarnings("resource")
     private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
         ipw.println();
@@ -21906,6 +20797,8 @@
         }
     }
 
+    @GuardedBy("mPackages")
+    @SuppressWarnings("resource")
     private void dumpCompilerStatsLPr(PrintWriter pw, String packageName) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
         ipw.println();
@@ -22283,6 +21176,7 @@
         }
     }
 
+    @GuardedBy("mInstallLock")
     private void reconcileAppsDataLI(String volumeUuid, int userId, int flags,
             boolean migrateAppData) {
         reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppData, false /* onlyCoreApps */);
@@ -22298,6 +21192,7 @@
      * correct for all installed apps.
      * @return list of skipped non-core packages (if {@code onlyCoreApps} is true)
      */
+    @GuardedBy("mInstallLock")
     private List<String> reconcileAppsDataLI(String volumeUuid, int userId, int flags,
             boolean migrateAppData, boolean onlyCoreApps) {
         Slog.v(TAG, "reconcileAppsData for " + volumeUuid + " u" + userId + " 0x"
@@ -22517,6 +21412,12 @@
         }
 
         prepareAppDataContentsLeafLIF(pkg, userId, flags);
+        final StorageManagerInternal storageManagerInternal
+                = LocalServices.getService(StorageManagerInternal.class);
+        if (storageManagerInternal != null) {
+            storageManagerInternal.mountExternalStorageForApp(
+                    pkg.packageName, appId, pkg.mSharedUserId, userId);
+        }
     }
 
     private void prepareAppDataContentsLIF(PackageParser.Package pkg, int userId, int flags) {
@@ -23045,6 +21946,7 @@
      * that are no longer in use by any other user.
      * @param userHandle the user being removed
      */
+    @GuardedBy("mPackages")
     private void removeUnusedPackagesLPw(UserManagerService userManager, final int userHandle) {
         final boolean DEBUG_CLEAN_APKS = false;
         int [] users = userManager.getUserIds();
@@ -23106,17 +22008,10 @@
     void onNewUserCreated(final int userId) {
         mDefaultPermissionPolicy.grantDefaultPermissions(userId);
         synchronized(mPackages) {
-            // If permission review for legacy apps is required, we represent
-            // dagerous permissions for such apps as always granted runtime
-            // permissions to keep per user flag state whether review is needed.
-            // Hence, if a new user is added we have to propagate dangerous
-            // permission grants for these legacy apps.
-            if (mSettings.mPermissions.mPermissionReviewRequired) {
-// NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
-                mPermissionManager.updateAllPermissions(
-                        StorageManager.UUID_PRIVATE_INTERNAL, true, mPackages.values(),
-                        mPermissionCallback);
-            }
+            // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
+            mPermissionManager.updateAllPermissions(
+                    StorageManager.UUID_PRIVATE_INTERNAL, true, mPackages.values(),
+                    mPermissionCallback);
         }
     }
 
@@ -23323,6 +22218,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private void deletePackageIfUnusedLPr(final String packageName) {
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps == null) {
@@ -23689,6 +22585,8 @@
                     return mRequiredVerifierPackage;
                 case PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER:
                     return mSystemTextClassifierPackage;
+                case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER:
+                    return mRequiredPermissionControllerPackage;
             }
             return null;
         }
@@ -23934,6 +22832,20 @@
         }
 
         @Override
+        public boolean isEnabledAndMatches(ComponentInfo info, int flags, int userId) {
+            synchronized (mPackages) {
+                return mSettings.isEnabledAndMatchLPr(info, flags, userId);
+            }
+        }
+
+        @Override
+        public boolean userNeedsBadging(int userId) {
+            synchronized (mPackages) {
+                return PackageManagerService.this.userNeedsBadging(userId);
+            }
+        }
+
+        @Override
         public void grantRuntimePermission(String packageName, String permName, int userId,
                 boolean overridePolicy) {
             PackageManagerService.this.mPermissionManager.grantRuntimePermission(
@@ -24009,7 +22921,7 @@
         }
 
         @Override
-        public boolean isLegacySystemApp(Package pkg) {
+        public boolean isLegacySystemApp(PackageParser.Package pkg) {
             synchronized (mPackages) {
                 final PackageSetting ps = (PackageSetting) pkg.mExtras;
                 return mPromoteSystemApps
@@ -24132,7 +23044,7 @@
         public boolean canAccessComponent(int callingUid, ComponentName component, int userId) {
             synchronized (mPackages) {
                 final PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
-                return !PackageManagerService.this.filterAppAccessLPr(
+                return ps != null && !PackageManagerService.this.filterAppAccessLPr(
                         ps, callingUid, component, TYPE_UNKNOWN, userId);
             }
         }
@@ -24150,6 +23062,48 @@
                 PackageManagerService.this.notifyPackageUseLocked(packageName, reason);
             }
         }
+
+        @Override
+        public CheckPermissionDelegate getCheckPermissionDelegate() {
+            synchronized (mPackages) {
+                return PackageManagerService.this.getCheckPermissionDelegateLocked();
+            }
+        }
+
+        @Override
+        public void setCheckPermissionDelegate(CheckPermissionDelegate delegate) {
+            synchronized (mPackages) {
+                PackageManagerService.this.setCheckPermissionDelegateLocked(delegate);
+            }
+        }
+
+        @Override
+        public SparseArray<String> getAppsWithSharedUserIds() {
+            synchronized (mPackages) {
+                return getAppsWithSharedUserIdsLocked();
+            }
+        }
+
+        @Override
+        public boolean isOnlyCoreApps() {
+            return PackageManagerService.this.isOnlyCoreApps();
+        }
+
+        @Override
+        public void freeStorage(String volumeUuid, long bytes, int storageFlags)
+                throws IOException {
+            PackageManagerService.this.freeStorage(volumeUuid, bytes, storageFlags);
+        }
+    }
+
+    private SparseArray<String> getAppsWithSharedUserIdsLocked() {
+        final SparseArray<String> sharedUserIds = new SparseArray<>();
+        synchronized (mPackages) {
+            for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
+                sharedUserIds.put(UserHandle.getAppId(setting.userId), setting.name);
+            }
+        }
+        return sharedUserIds;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index d06437e..f2c0395 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -25,7 +25,6 @@
 import android.accounts.IAccountManager;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.Application;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.IIntentReceiver;
@@ -67,7 +66,6 @@
 import android.os.IUserManager;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
-import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
 import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
@@ -84,11 +82,17 @@
 import android.text.format.DateUtils;
 import android.util.ArraySet;
 import android.util.PrintWriterPrinter;
+
 import com.android.internal.content.PackageHelper;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
+
 import dalvik.system.DexFile;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -96,10 +100,6 @@
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.attribute.FileAttribute;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -110,10 +110,7 @@
 import java.util.WeakHashMap;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
 
 class PackageManagerShellCommand extends ShellCommand {
     /** Path for streaming APK content */
@@ -547,6 +544,10 @@
                     case "-e":
                         listEnabled = true;
                         break;
+                    case "-a":
+                        getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
+                        getFlags |= PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS;
+                        break;
                     case "-f":
                         showSourceDir = true;
                         break;
@@ -1773,6 +1774,15 @@
         }
     }
 
+    private boolean isProductServicesApp(String pkg) {
+        try {
+            final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
+            return info != null && info.applicationInfo.isProductServices();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
     private int runGetPrivappPermissions() {
         final String pkg = getNextArg();
         if (pkg == null) {
@@ -1785,6 +1795,9 @@
             privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
         } else if (isProductApp(pkg)) {
             privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
+        } else if (isProductServicesApp(pkg)) {
+            privAppPermissions = SystemConfig.getInstance()
+                    .getProductServicesPrivAppPermissions(pkg);
         } else {
             privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
         }
@@ -1806,6 +1819,9 @@
             privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
         } else if (isProductApp(pkg)) {
             privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
+        } else if (isProductServicesApp(pkg)) {
+            privAppPermissions = SystemConfig.getInstance()
+                    .getProductServicesPrivAppDenyPermissions(pkg);
         } else {
             privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
         }
@@ -2419,30 +2435,30 @@
 
     private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
             boolean logSuccess) throws RemoteException {
-        final PrintWriter pw = getOutPrintWriter();
-        final ParcelFileDescriptor fd;
-        if (STDIN_PATH.equals(inPath)) {
-            fd = new ParcelFileDescriptor(getInFileDescriptor());
-        } else if (inPath != null) {
-            fd = openFileForSystem(inPath, "r");
-            if (fd == null) {
-                return -1;
-            }
-            sizeBytes = fd.getStatSize();
-            if (sizeBytes < 0) {
-                getErrPrintWriter().println("Unable to get size of: " + inPath);
-                return -1;
-            }
-        } else {
-            fd = new ParcelFileDescriptor(getInFileDescriptor());
-        }
-        if (sizeBytes <= 0) {
-            getErrPrintWriter().println("Error: must specify a APK size");
-            return 1;
-        }
-
         PackageInstaller.Session session = null;
         try {
+            final PrintWriter pw = getOutPrintWriter();
+            final ParcelFileDescriptor fd;
+            if (STDIN_PATH.equals(inPath)) {
+                fd = ParcelFileDescriptor.dup(getInFileDescriptor());
+            } else if (inPath != null) {
+                fd = openFileForSystem(inPath, "r");
+                if (fd == null) {
+                    return -1;
+                }
+                sizeBytes = fd.getStatSize();
+                if (sizeBytes < 0) {
+                    getErrPrintWriter().println("Unable to get size of: " + inPath);
+                    return -1;
+                }
+            } else {
+                fd = ParcelFileDescriptor.dup(getInFileDescriptor());
+            }
+            if (sizeBytes <= 0) {
+                getErrPrintWriter().println("Error: must specify a APK size");
+                return 1;
+            }
+
             session = new PackageInstaller.Session(
                     mInterface.getPackageInstaller().openSession(sessionId));
             session.write(splitName, 0, sizeBytes, fd);
@@ -2688,6 +2704,7 @@
         pw.println("    Prints all packages; optionally only those whose name contains");
         pw.println("    the text in FILTER.  Options are:");
         pw.println("      -f: see their associated file");
+        pw.println("      -a: all known packages");
         pw.println("      -d: filter to only show disabled packages");
         pw.println("      -e: filter to only show enabled packages");
         pw.println("      -s: filter to only show system packages");
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index ea05b74..727fb15 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -148,6 +148,10 @@
         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
     }
 
+    public boolean isProductServices() {
+        return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
+    }
+
     public boolean isForwardLocked() {
         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
     }
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 7c92045..239dc99 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -63,6 +63,7 @@
                 | ApplicationInfo.PRIVATE_FLAG_OEM
                 | ApplicationInfo.PRIVATE_FLAG_VENDOR
                 | ApplicationInfo.PRIVATE_FLAG_PRODUCT
+                | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES
                 | ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK
                 | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d17697b..8dd1a0f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -44,6 +44,7 @@
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.PackageCleanItem;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
 import android.content.pm.PermissionInfo;
@@ -88,6 +89,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.XmlUtils;
+import com.android.server.LocalServices;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.permission.BasePermission;
 import com.android.server.pm.permission.PermissionSettings;
@@ -422,11 +424,8 @@
     /** Settings and other information about permissions */
     final PermissionSettings mPermissions;
 
-    Settings(PermissionSettings permissions, Object lock) {
-        this(Environment.getDataDirectory(), permissions, lock);
-    }
-
-    Settings(File dataDir, PermissionSettings permission, Object lock) {
+    Settings(File dataDir, PermissionSettings permission,
+            Object lock) {
         mLock = lock;
         mPermissions = permission;
         mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
@@ -850,7 +849,8 @@
         pkgSetting.pkgPrivateFlags &= ~(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
                 | ApplicationInfo.PRIVATE_FLAG_OEM
                 | ApplicationInfo.PRIVATE_FLAG_VENDOR
-                | ApplicationInfo.PRIVATE_FLAG_PRODUCT);
+                | ApplicationInfo.PRIVATE_FLAG_PRODUCT
+                | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES);
         pkgSetting.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
         pkgSetting.pkgPrivateFlags |=
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
@@ -860,6 +860,8 @@
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR;
         pkgSetting.pkgPrivateFlags |=
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT;
+        pkgSetting.pkgPrivateFlags |=
+                pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES;
         pkgSetting.primaryCpuAbiString = primaryCpuAbi;
         pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
         if (childPkgNames != null) {
@@ -3232,8 +3234,10 @@
         return true;
     }
 
-    void applyDefaultPreferredAppsLPw(PackageManagerService service, int userId) {
+    void applyDefaultPreferredAppsLPw(int userId) {
         // First pull data from any pre-installed apps.
+        final PackageManagerInternal pmInternal =
+                LocalServices.getService(PackageManagerInternal.class);
         for (PackageSetting ps : mPackages.values()) {
             if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0 && ps.pkg != null
                     && ps.pkg.preferredActivityFilters != null) {
@@ -3241,8 +3245,8 @@
                         = ps.pkg.preferredActivityFilters;
                 for (int i=0; i<intents.size(); i++) {
                     PackageParser.ActivityIntentInfo aii = intents.get(i);
-                    applyDefaultPreferredActivityLPw(service, aii, new ComponentName(
-                            ps.name, aii.activity.className), userId);
+                    applyDefaultPreferredActivityLPw(pmInternal, aii, new ComponentName(
+                                    ps.name, aii.activity.className), userId);
                 }
             }
         }
@@ -3290,7 +3294,7 @@
                             + " does not start with 'preferred-activities'");
                     continue;
                 }
-                readDefaultPreferredActivitiesLPw(service, parser, userId);
+                readDefaultPreferredActivitiesLPw(parser, userId);
             } catch (XmlPullParserException e) {
                 Slog.w(TAG, "Error reading apps file " + f, e);
             } catch (IOException e) {
@@ -3306,8 +3310,8 @@
         }
     }
 
-    private void applyDefaultPreferredActivityLPw(PackageManagerService service,
-            IntentFilter tmpPa, ComponentName cn, int userId) {
+    private void applyDefaultPreferredActivityLPw(
+            PackageManagerInternal pmInternal, IntentFilter tmpPa, ComponentName cn, int userId) {
         // The initial preferences only specify the target activity
         // component and intent-filter, not the set of matches.  So we
         // now need to query for the matches to build the correct
@@ -3332,27 +3336,31 @@
         boolean doNonData = true;
         boolean hasSchemes = false;
 
-        for (int ischeme=0; ischeme<tmpPa.countDataSchemes(); ischeme++) {
+        final int dataSchemesCount = tmpPa.countDataSchemes();
+        for (int ischeme = 0; ischeme < dataSchemesCount; ischeme++) {
             boolean doScheme = true;
-            String scheme = tmpPa.getDataScheme(ischeme);
+            final String scheme = tmpPa.getDataScheme(ischeme);
             if (scheme != null && !scheme.isEmpty()) {
                 hasSchemes = true;
             }
-            for (int issp=0; issp<tmpPa.countDataSchemeSpecificParts(); issp++) {
+            final int dataSchemeSpecificPartsCount = tmpPa.countDataSchemeSpecificParts();
+            for (int issp = 0; issp < dataSchemeSpecificPartsCount; issp++) {
                 Uri.Builder builder = new Uri.Builder();
                 builder.scheme(scheme);
                 PatternMatcher ssp = tmpPa.getDataSchemeSpecificPart(issp);
                 builder.opaquePart(ssp.getPath());
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setData(builder.build());
-                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                         scheme, ssp, null, null, userId);
                 doScheme = false;
             }
-            for (int iauth=0; iauth<tmpPa.countDataAuthorities(); iauth++) {
+            final int dataAuthoritiesCount = tmpPa.countDataAuthorities();
+            for (int iauth = 0; iauth < dataAuthoritiesCount; iauth++) {
                 boolean doAuth = true;
-                IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(iauth);
-                for (int ipath=0; ipath<tmpPa.countDataPaths(); ipath++) {
+                final IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(iauth);
+                final int dataPathsCount = tmpPa.countDataPaths();
+                for (int ipath = 0; ipath < dataPathsCount; ipath++) {
                     Uri.Builder builder = new Uri.Builder();
                     builder.scheme(scheme);
                     if (auth.getHost() != null) {
@@ -3362,7 +3370,7 @@
                     builder.path(path.getPath());
                     Intent finalIntent = new Intent(intent);
                     finalIntent.setData(builder.build());
-                    applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                    applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                             scheme, null, auth, path, userId);
                     doAuth = doScheme = false;
                 }
@@ -3374,7 +3382,7 @@
                     }
                     Intent finalIntent = new Intent(intent);
                     finalIntent.setData(builder.build());
-                    applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                    applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                             scheme, null, auth, null, userId);
                     doScheme = false;
                 }
@@ -3384,7 +3392,7 @@
                 builder.scheme(scheme);
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setData(builder.build());
-                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                         scheme, null, null, null, userId);
             }
             doNonData = false;
@@ -3400,129 +3408,134 @@
                         Intent finalIntent = new Intent(intent);
                         builder.scheme(scheme);
                         finalIntent.setDataAndType(builder.build(), mimeType);
-                        applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                        applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                                 scheme, null, null, null, userId);
                     }
                 }
             } else {
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setType(mimeType);
-                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                         null, null, null, null, userId);
             }
             doNonData = false;
         }
 
         if (doNonData) {
-            applyDefaultPreferredActivityLPw(service, intent, flags, cn,
+            applyDefaultPreferredActivityLPw(pmInternal, intent, flags, cn,
                     null, null, null, null, userId);
         }
     }
 
-    private void applyDefaultPreferredActivityLPw(PackageManagerService service,
-            Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
+    private void applyDefaultPreferredActivityLPw(PackageManagerInternal pmInternal, Intent intent,
+            int flags, ComponentName cn, String scheme, PatternMatcher ssp,
             IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
-        flags = service.updateFlagsForResolve(flags, userId, intent, Binder.getCallingUid(), false);
-        List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
-                intent.getType(), flags, 0);
-        if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent
-                + " results: " + ri);
+        final List<ResolveInfo> ri =
+                pmInternal.queryIntentActivities(intent, flags, Binder.getCallingUid(), 0);
+        if (PackageManagerService.DEBUG_PREFERRED) {
+            Log.d(TAG, "Queried " + intent + " results: " + ri);
+        }
         int systemMatch = 0;
         int thirdPartyMatch = 0;
-        if (ri != null && ri.size() > 1) {
-            boolean haveAct = false;
-            ComponentName haveNonSys = null;
-            ComponentName[] set = new ComponentName[ri.size()];
-            for (int i=0; i<ri.size(); i++) {
-                ActivityInfo ai = ri.get(i).activityInfo;
-                set[i] = new ComponentName(ai.packageName, ai.name);
-                if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
-                    if (ri.get(i).match >= thirdPartyMatch) {
-                        // Keep track of the best match we find of all third
-                        // party apps, for use later to determine if we actually
-                        // want to set a preferred app for this intent.
-                        if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
-                                + ai.packageName + "/" + ai.name + ": non-system!");
-                        haveNonSys = set[i];
-                        break;
+        final int numMatches = (ri == null ? 0 : ri.size());
+        if (numMatches <= 1) {
+            Slog.w(TAG, "No potential matches found for " + intent
+                    + " while setting preferred " + cn.flattenToShortString());
+            return;
+        }
+        boolean haveAct = false;
+        ComponentName haveNonSys = null;
+        ComponentName[] set = new ComponentName[ri.size()];
+        for (int i = 0; i < numMatches; i++) {
+            final ActivityInfo ai = ri.get(i).activityInfo;
+            set[i] = new ComponentName(ai.packageName, ai.name);
+            if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                if (ri.get(i).match >= thirdPartyMatch) {
+                    // Keep track of the best match we find of all third
+                    // party apps, for use later to determine if we actually
+                    // want to set a preferred app for this intent.
+                    if (PackageManagerService.DEBUG_PREFERRED) {
+                        Log.d(TAG, "Result " + ai.packageName + "/" + ai.name + ": non-system!");
                     }
-                } else if (cn.getPackageName().equals(ai.packageName)
-                        && cn.getClassName().equals(ai.name)) {
-                    if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
-                            + ai.packageName + "/" + ai.name + ": default!");
-                    haveAct = true;
-                    systemMatch = ri.get(i).match;
-                } else {
-                    if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
-                            + ai.packageName + "/" + ai.name + ": skipped");
+                    haveNonSys = set[i];
+                    break;
                 }
-            }
-            if (haveNonSys != null && thirdPartyMatch < systemMatch) {
-                // If we have a matching third party app, but its match is not as
-                // good as the built-in system app, then we don't want to actually
-                // consider it a match because presumably the built-in app is still
-                // the thing we want users to see by default.
-                haveNonSys = null;
-            }
-            if (haveAct && haveNonSys == null) {
-                IntentFilter filter = new IntentFilter();
-                if (intent.getAction() != null) {
-                    filter.addAction(intent.getAction());
+            } else if (cn.getPackageName().equals(ai.packageName)
+                    && cn.getClassName().equals(ai.name)) {
+                if (PackageManagerService.DEBUG_PREFERRED) {
+                    Log.d(TAG, "Result " + ai.packageName + "/" + ai.name + ": default!");
                 }
-                if (intent.getCategories() != null) {
-                    for (String cat : intent.getCategories()) {
-                        filter.addCategory(cat);
-                    }
-                }
-                if ((flags & MATCH_DEFAULT_ONLY) != 0) {
-                    filter.addCategory(Intent.CATEGORY_DEFAULT);
-                }
-                if (scheme != null) {
-                    filter.addDataScheme(scheme);
-                }
-                if (ssp != null) {
-                    filter.addDataSchemeSpecificPart(ssp.getPath(), ssp.getType());
-                }
-                if (auth != null) {
-                    filter.addDataAuthority(auth);
-                }
-                if (path != null) {
-                    filter.addDataPath(path);
-                }
-                if (intent.getType() != null) {
-                    try {
-                        filter.addDataType(intent.getType());
-                    } catch (IntentFilter.MalformedMimeTypeException ex) {
-                        Slog.w(TAG, "Malformed mimetype " + intent.getType() + " for " + cn);
-                    }
-                }
-                PreferredActivity pa = new PreferredActivity(filter, systemMatch, set, cn, true);
-                editPreferredActivitiesLPw(userId).addFilter(pa);
-            } else if (haveNonSys == null) {
-                StringBuilder sb = new StringBuilder();
-                sb.append("No component ");
-                sb.append(cn.flattenToShortString());
-                sb.append(" found setting preferred ");
-                sb.append(intent);
-                sb.append("; possible matches are ");
-                for (int i=0; i<set.length; i++) {
-                    if (i > 0) sb.append(", ");
-                    sb.append(set[i].flattenToShortString());
-                }
-                Slog.w(TAG, sb.toString());
+                haveAct = true;
+                systemMatch = ri.get(i).match;
             } else {
-                Slog.i(TAG, "Not setting preferred " + intent + "; found third party match "
-                        + haveNonSys.flattenToShortString());
+                if (PackageManagerService.DEBUG_PREFERRED) {
+                    Log.d(TAG, "Result " + ai.packageName + "/" + ai.name + ": skipped");
+                }
             }
+        }
+        if (haveNonSys != null && thirdPartyMatch < systemMatch) {
+            // If we have a matching third party app, but its match is not as
+            // good as the built-in system app, then we don't want to actually
+            // consider it a match because presumably the built-in app is still
+            // the thing we want users to see by default.
+            haveNonSys = null;
+        }
+        if (haveAct && haveNonSys == null) {
+            IntentFilter filter = new IntentFilter();
+            if (intent.getAction() != null) {
+                filter.addAction(intent.getAction());
+            }
+            if (intent.getCategories() != null) {
+                for (String cat : intent.getCategories()) {
+                    filter.addCategory(cat);
+                }
+            }
+            if ((flags & MATCH_DEFAULT_ONLY) != 0) {
+                filter.addCategory(Intent.CATEGORY_DEFAULT);
+            }
+            if (scheme != null) {
+                filter.addDataScheme(scheme);
+            }
+            if (ssp != null) {
+                filter.addDataSchemeSpecificPart(ssp.getPath(), ssp.getType());
+            }
+            if (auth != null) {
+                filter.addDataAuthority(auth);
+            }
+            if (path != null) {
+                filter.addDataPath(path);
+            }
+            if (intent.getType() != null) {
+                try {
+                    filter.addDataType(intent.getType());
+                } catch (IntentFilter.MalformedMimeTypeException ex) {
+                    Slog.w(TAG, "Malformed mimetype " + intent.getType() + " for " + cn);
+                }
+            }
+            PreferredActivity pa = new PreferredActivity(filter, systemMatch, set, cn, true);
+            editPreferredActivitiesLPw(userId).addFilter(pa);
+        } else if (haveNonSys == null) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("No component ");
+            sb.append(cn.flattenToShortString());
+            sb.append(" found setting preferred ");
+            sb.append(intent);
+            sb.append("; possible matches are ");
+            for (int i = 0; i < set.length; i++) {
+                if (i > 0) sb.append(", ");
+                sb.append(set[i].flattenToShortString());
+            }
+            Slog.w(TAG, sb.toString());
         } else {
-            Slog.w(TAG, "No potential matches found for " + intent + " while setting preferred "
-                    + cn.flattenToShortString());
+            Slog.i(TAG, "Not setting preferred " + intent + "; found third party match "
+                    + haveNonSys.flattenToShortString());
         }
     }
 
-    private void readDefaultPreferredActivitiesLPw(PackageManagerService service,
-            XmlPullParser parser, int userId)
+    private void readDefaultPreferredActivitiesLPw(XmlPullParser parser, int userId)
             throws XmlPullParserException, IOException {
+        final PackageManagerInternal pmInternal =
+                LocalServices.getService(PackageManagerInternal.class);
         int outerDepth = parser.getDepth();
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -3535,8 +3548,8 @@
             if (tagName.equals(TAG_ITEM)) {
                 PreferredActivity tmpPa = new PreferredActivity(parser);
                 if (tmpPa.mPref.getParseError() == null) {
-                    applyDefaultPreferredActivityLPw(service, tmpPa, tmpPa.mPref.mComponent,
-                            userId);
+                    applyDefaultPreferredActivityLPw(
+                            pmInternal, tmpPa, tmpPa.mPref.mComponent, userId);
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Error in package manager settings: <preferred-activity> "
@@ -4151,7 +4164,7 @@
             }
         }
         synchronized (mPackages) {
-            applyDefaultPreferredAppsLPw(service, userHandle);
+            applyDefaultPreferredAppsLPw(userHandle);
         }
     }
 
@@ -4445,6 +4458,7 @@
             ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY",
             ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR",
             ApplicationInfo.PRIVATE_FLAG_PRODUCT, "PRODUCT",
+            ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES, "PRODUCT_SERVICES",
             ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",
     };
 
@@ -5172,10 +5186,12 @@
             mPersistenceLock = persistenceLock;
         }
 
+        @GuardedBy("Settings.this.mLock")
         public boolean areDefaultRuntimPermissionsGrantedLPr(int userId) {
             return mDefaultPermissionsGranted.get(userId);
         }
 
+        @GuardedBy("Settings.this.mLock")
         public void onDefaultRuntimePermissionsGrantedLPr(int userId) {
             mFingerprints.put(userId, Build.FINGERPRINT);
             writePermissionsForUserAsyncLPr(userId);
@@ -5186,6 +5202,7 @@
             writePermissionsSync(userId);
         }
 
+        @GuardedBy("Settings.this.mLock")
         public void writePermissionsForUserAsyncLPr(int userId) {
             final long currentTimeMillis = SystemClock.uptimeMillis();
 
@@ -5354,6 +5371,7 @@
             }
         }
 
+        @GuardedBy("Settings.this.mLock")
         private void onUserRemovedLPw(int userId) {
             // Make sure we do not
             mHandler.removeMessages(userId);
@@ -5387,6 +5405,7 @@
             getUserRuntimePermissionsFile(userId).delete();
         }
 
+        @GuardedBy("Settings.this.mLock")
         public void readStateForUserSyncLPr(int userId) {
             File permissionsFile = getUserRuntimePermissionsFile(userId);
             if (!permissionsFile.exists()) {
@@ -5439,6 +5458,7 @@
 
         // Private internals
 
+        @GuardedBy("Settings.this.mLock")
         private void parseRuntimePermissionsLPr(XmlPullParser parser, int userId)
                 throws IOException, XmlPullParserException {
             final int outerDepth = parser.getDepth();
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index ca08415..c94d209 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -64,7 +64,7 @@
 
     public void writeToProto(ProtoOutputStream proto, long fieldId) {
         long token = proto.start(fieldId);
-        proto.write(PackageServiceDumpProto.SharedUserProto.USER_ID, userId);
+        proto.write(PackageServiceDumpProto.SharedUserProto.UID, userId);
         proto.write(PackageServiceDumpProto.SharedUserProto.NAME, name);
         proto.end(token);
     }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 46935f0..c18ca25 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -684,6 +684,7 @@
     }
 
     /** Assume permissions already checked and caller's identity cleared */
+    @GuardedBy("mUsersLock")
     private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly, boolean fullInfo) {
         IntArray profileIds = getProfileIdsLU(userId, enabledOnly);
         ArrayList<UserInfo> users = new ArrayList<>(profileIds.size());
@@ -706,6 +707,7 @@
     /**
      *  Assume permissions already checked and caller's identity cleared
      */
+    @GuardedBy("mUsersLock")
     private IntArray getProfileIdsLU(int userId, boolean enabledOnly) {
         UserInfo user = getUserInfoLU(userId);
         IntArray result = new IntArray(mUsers.size());
@@ -784,6 +786,7 @@
         return mLocalService.getProfileParentId(userHandle);
     }
 
+    @GuardedBy("mUsersLock")
     private UserInfo getProfileParentLU(int userHandle) {
         UserInfo profile = getUserInfoLU(userHandle);
         if (profile == null) {
@@ -1206,6 +1209,7 @@
     /*
      * Should be locked on mUsers before calling this.
      */
+    @GuardedBy("mUsersLock")
     private UserInfo getUserInfoLU(int userId) {
         final UserData userData = mUsers.get(userId);
         // If it is partial and not in the process of being removed, return as unknown user.
@@ -1216,6 +1220,7 @@
         return userData != null ? userData.info : null;
     }
 
+    @GuardedBy("mUsersLock")
     private UserData getUserDataLU(int userId) {
         final UserData userData = mUsers.get(userId);
         // If it is partial and not in the process of being removed, return as unknown user.
@@ -1718,6 +1723,7 @@
     }
 
     // Package private for the inner class.
+    @GuardedBy("mRestrictionsLock")
     void applyUserRestrictionsLR(int userId) {
         updateUserRestrictionsInternalLR(null, userId);
     }
@@ -1798,6 +1804,7 @@
         }
     }
 
+    @GuardedBy("mUsersLock")
     private int getAliveUsersExcludingGuestsCountLU() {
         int aliveUserCount = 0;
         final int totalUserCount = mUsers.size();
@@ -1971,6 +1978,7 @@
         }
     }
 
+    @GuardedBy({"mRestrictionsLock", "mPackagesLock"})
     private void readUserListLP() {
         if (!mUserListFile.exists()) {
             fallbackToSingleUserLP();
@@ -2068,6 +2076,7 @@
      * Upgrade steps between versions, either for fixing bugs or changing the data format.
      * @param oldGlobalUserRestrictions Pre-O global device policy restrictions.
      */
+    @GuardedBy({"mRestrictionsLock", "mPackagesLock"})
     private void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions) {
         final int originalVersion = mUserVersion;
         int userVersion = mUserVersion;
@@ -2148,6 +2157,7 @@
         }
     }
 
+    @GuardedBy({"mPackagesLock", "mRestrictionsLock"})
     private void fallbackToSingleUserLP() {
         int flags = UserInfo.FLAG_INITIALIZED;
         // In split system user mode, the admin and primary flags are assigned to the first human
@@ -2317,6 +2327,7 @@
      *   <user id="2"></user>
      * </users>
      */
+    @GuardedBy({"mRestrictionsLock", "mPackagesLock"})
     private void writeUserListLP() {
         if (DBG) {
             debug("writeUserList");
@@ -4060,6 +4071,7 @@
         }
     }
 
+    @GuardedBy("mUsersLock")
     @VisibleForTesting
     int getFreeProfileBadgeLU(int parentUserId) {
         int maxManagedProfiles = getMaxManagedProfiles();
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 9ca02ba..3f28ee6 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -574,13 +574,13 @@
                                 Settings.Secure.DOZE_ALWAYS_ON, 0, userId);
                         android.provider.Settings.Secure.putIntForUser(
                                 context.getContentResolver(),
-                                Settings.Secure.DOZE_PULSE_ON_PICK_UP, 0, userId);
+                                Settings.Secure.DOZE_PICK_UP_GESTURE, 0, userId);
                         android.provider.Settings.Secure.putIntForUser(
                                 context.getContentResolver(),
                                 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, 0, userId);
                         android.provider.Settings.Secure.putIntForUser(
                                 context.getContentResolver(),
-                                Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, 0, userId);
+                                Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, 0, userId);
                     }
                     break;
                 case UserManager.DISALLOW_CONFIG_LOCATION:
@@ -684,9 +684,9 @@
 
             case android.provider.Settings.Secure.DOZE_ENABLED:
             case android.provider.Settings.Secure.DOZE_ALWAYS_ON:
-            case android.provider.Settings.Secure.DOZE_PULSE_ON_PICK_UP:
+            case android.provider.Settings.Secure.DOZE_PICK_UP_GESTURE:
             case android.provider.Settings.Secure.DOZE_PULSE_ON_LONG_PRESS:
-            case android.provider.Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP:
+            case android.provider.Settings.Secure.DOZE_DOUBLE_TAP_GESTURE:
                 if ("0".equals(value)) {
                     return false;
                 }
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 0ba7822..21daa39 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -519,6 +519,11 @@
     private static final int TRON_COMPILATION_REASON_AB_OTA = 6;
     private static final int TRON_COMPILATION_REASON_INACTIVE = 7;
     private static final int TRON_COMPILATION_REASON_SHARED = 8;
+    private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA = 9;
+
+    // The annotation to add as a suffix to the compilation reason when dexopt was
+    // performed with dex metadata.
+    public static final String DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION = "-dm";
 
     /**
      * Convert the compilation reason to an int suitable to be logged to TRON.
@@ -534,6 +539,10 @@
             case "ab-ota" : return TRON_COMPILATION_REASON_AB_OTA;
             case "inactive" : return TRON_COMPILATION_REASON_INACTIVE;
             case "shared" : return TRON_COMPILATION_REASON_SHARED;
+            // This is a special marker for dex metadata installation that does not
+            // have an equivalent as a system property.
+            case "install" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION :
+                return TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA;
             default: return TRON_COMPILATION_REASON_UNKNOWN;
         }
     }
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 1d002ef..8202580 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -39,6 +39,7 @@
 
 import com.android.server.pm.DumpState;
 import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.PackageSetting;
 import com.android.server.pm.PackageSettingBase;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -374,8 +375,10 @@
     }
 
     public void enforceDeclaredUsedAndRuntimeOrDevelopment(PackageParser.Package pkg) {
+        final PackageSetting pkgSetting = (PackageSetting) pkg.mExtras;
+        final PermissionsState permsState = pkgSetting.getPermissionsState();
         int index = pkg.requestedPermissions.indexOf(name);
-        if (index == -1) {
+        if (!permsState.hasRequestedPermission(name) && index == -1) {
             throw new SecurityException("Package " + pkg.packageName
                     + " has not requested permission " + name);
         }
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 1ae59cb..5befc1f 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -25,7 +25,6 @@
 import android.app.DownloadManager;
 import android.app.admin.DevicePolicyManager;
 import android.companion.CompanionDeviceManager;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -45,6 +44,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.print.PrintManager;
@@ -53,7 +53,6 @@
 import android.provider.MediaStore;
 import android.provider.Telephony.Sms.Intents;
 import android.security.Credentials;
-import android.service.textclassifier.TextClassifierService;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -169,10 +168,34 @@
         SENSORS_PERMISSIONS.add(Manifest.permission.BODY_SENSORS);
     }
 
+    @Deprecated
     private static final Set<String> STORAGE_PERMISSIONS = new ArraySet<>();
     static {
-        STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
-        STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+        // STOPSHIP(b/112545973): remove once feature enabled by default
+        if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+            STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+            STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+        }
+    }
+
+    private static final Set<String> MEDIA_AURAL_PERMISSIONS = new ArraySet<>();
+    static {
+        // STOPSHIP(b/112545973): remove once feature enabled by default
+        if (SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+            MEDIA_AURAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_AUDIO);
+            MEDIA_AURAL_PERMISSIONS.add(Manifest.permission.WRITE_MEDIA_AUDIO);
+        }
+    }
+
+    private static final Set<String> MEDIA_VISUAL_PERMISSIONS = new ArraySet<>();
+    static {
+        // STOPSHIP(b/112545973): remove once feature enabled by default
+        if (SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+            MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_IMAGES);
+            MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.WRITE_MEDIA_IMAGES);
+            MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VIDEO);
+            MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.WRITE_MEDIA_VIDEO);
+        }
     }
 
     private static final int MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS = 1;
@@ -404,6 +427,8 @@
                 MediaStore.AUTHORITY, userId);
         if (mediaStorePackage != null) {
             grantRuntimePermissions(mediaStorePackage, STORAGE_PERMISSIONS, true, userId);
+            grantRuntimePermissions(mediaStorePackage, MEDIA_AURAL_PERMISSIONS, true, userId);
+            grantRuntimePermissions(mediaStorePackage, MEDIA_VISUAL_PERMISSIONS, true, userId);
             grantRuntimePermissions(mediaStorePackage, PHONE_PERMISSIONS, true, userId);
         }
 
@@ -615,6 +640,7 @@
         if (galleryPackage != null
                 && doesPackageSupportRuntimePermissions(galleryPackage)) {
             grantRuntimePermissions(galleryPackage, STORAGE_PERMISSIONS, userId);
+            grantRuntimePermissions(galleryPackage, MEDIA_VISUAL_PERMISSIONS, userId);
         }
 
         // Email
@@ -724,6 +750,7 @@
         if (musicPackage != null
                 && doesPackageSupportRuntimePermissions(musicPackage)) {
             grantRuntimePermissions(musicPackage, STORAGE_PERMISSIONS, userId);
+            grantRuntimePermissions(musicPackage, MEDIA_AURAL_PERMISSIONS, userId);
         }
 
         // Home
@@ -1193,12 +1220,27 @@
         }
     }
 
-    private void grantRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
-            boolean systemFixed, boolean ignoreSystemPackage, int userId) {
+    private void grantRuntimePermissions(PackageParser.Package pkg,
+            Set<String> permissionsWithoutSplits, boolean systemFixed, boolean ignoreSystemPackage,
+            int userId) {
         if (pkg.requestedPermissions.isEmpty()) {
             return;
         }
 
+        final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
+
+        // Automatically attempt to grant split permissions to older APKs
+        final int numSplitPerms = PackageParser.SPLIT_PERMISSIONS.length;
+        for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
+            final PackageParser.SplitPermissionInfo splitPerm =
+                    PackageParser.SPLIT_PERMISSIONS[splitPermNum];
+
+            if (pkg.applicationInfo.targetSdkVersion < splitPerm.targetSdk
+                    && permissionsWithoutSplits.contains(splitPerm.rootPerm)) {
+                Collections.addAll(permissions, splitPerm.newPerms);
+            }
+        }
+
         List<String> requestedPermissions = pkg.requestedPermissions;
         Set<String> grantablePermissions = null;
 
@@ -1358,6 +1400,11 @@
         if (dir.isDirectory() && dir.canRead()) {
             Collections.addAll(ret, dir.listFiles());
         }
+        dir = new File(Environment.getProductServicesDirectory(),
+                "etc/default-permissions");
+        if (dir.isDirectory() && dir.canRead()) {
+            Collections.addAll(ret, dir.listFiles());
+        }
         // For IoT devices, we check the oem partition for default permissions for each app.
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED, 0)) {
             dir = new File(Environment.getOemDirectory(), "etc/default-permissions");
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
index a042fed..80a5fbb 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -21,19 +21,11 @@
 import android.content.pm.PackageParser;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManager.PermissionInfoFlags;
-import android.content.pm.PackageParser.Permission;
-
-import com.android.server.pm.SharedUserSetting;
-import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 /**
  * Internal interfaces to be used by other components within the system server.
@@ -115,7 +107,11 @@
      */
     public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
     public abstract void addAllPermissionGroups(@NonNull PackageParser.Package pkg, boolean chatty);
-    public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
+    public abstract void removeAllPermissions(
+            @NonNull PackageParser.Package pkg,
+            @NonNull List<String> allPackageNames,
+            @Nullable PermissionCallback permissionCallback,
+            boolean chatty);
     public abstract boolean addDynamicPermission(@NonNull PermissionInfo info, boolean async,
             int callingUid, @Nullable PermissionCallback callback);
     public abstract void removeDynamicPermission(@NonNull String permName, int callingUid,
@@ -189,4 +185,4 @@
 
     /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
     public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
-}
\ No newline at end of file
+}
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 7f2d5c3..c4f90a12 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -31,6 +31,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
@@ -38,6 +39,7 @@
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.metrics.LogMaker;
+import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
@@ -159,7 +161,7 @@
         mLock = externalLock;
         mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
         mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
-        mSettings = new PermissionSettings(context, mLock);
+        mSettings = new PermissionSettings(mLock);
 
         mHandlerThread = new ServiceThread(TAG,
                 Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
@@ -476,8 +478,9 @@
                                         " to " + newPermissionGroupName);
 
                                 try {
-                                    revokeRuntimePermission(permissionName, packageName, false,
-                                            Process.SYSTEM_UID, userId, permissionCallback);
+                                    revokeRuntimePermission(permissionName, packageName,
+                                            mSettings.getPermission(permissionName), false,
+                                            Process.SYSTEM_UID, userId, permissionCallback, false);
                                 } catch (IllegalArgumentException e) {
                                     Slog.e(TAG, "Could not revoke " + permissionName + " from "
                                             + packageName, e);
@@ -570,9 +573,59 @@
 
     }
 
-    private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) {
+    private void revokeAllPermissions(
+            @NonNull List<BasePermission> bps,
+            @NonNull List<String> allPackageNames,
+            @Nullable PermissionCallback permissionCallback) {
+        AsyncTask.execute(() -> {
+            final int numRemovedPermissions = bps.size();
+            for (int permissionNum = 0; permissionNum < numRemovedPermissions; permissionNum++) {
+                final int[] userIds = mUserManagerInt.getUserIds();
+                final int numUserIds = userIds.length;
+
+                final int numPackages = allPackageNames.size();
+                for (int packageNum = 0; packageNum < numPackages; packageNum++) {
+                    final String packageName = allPackageNames.get(packageNum);
+                    final ApplicationInfo applicationInfo = mPackageManagerInt.getApplicationInfo(
+                            packageName, 0, Process.SYSTEM_UID, UserHandle.USER_SYSTEM);
+                    if (applicationInfo != null
+                            && applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+                        continue;
+                    }
+                    for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
+                        final int userId = userIds[userIdNum];
+                        final String permissionName = bps.get(permissionNum).getName();
+                        if (checkPermission(permissionName, packageName, UserHandle.USER_SYSTEM,
+                                userId) == PackageManager.PERMISSION_GRANTED) {
+                            try {
+                                revokeRuntimePermission(
+                                        permissionName,
+                                        packageName,
+                                        bps.get(permissionNum),
+                                        false,
+                                        Process.SYSTEM_UID,
+                                        userId,
+                                        permissionCallback,
+                                        true);
+                            } catch (IllegalArgumentException e) {
+                                Slog.e(TAG, "Could not revoke " + permissionName + " from "
+                                        + packageName, e);
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    private void removeAllPermissions(
+            @NonNull PackageParser.Package pkg,
+            @NonNull List<String> allPackageNames,
+            @Nullable PermissionCallback permissionCallback,
+            boolean chatty) {
         synchronized (mLock) {
             int N = pkg.permissions.size();
+            List<BasePermission> bps = new ArrayList<BasePermission>(N);
             StringBuilder r = null;
             for (int i=0; i<N; i++) {
                 PackageParser.Permission p = pkg.permissions.get(i);
@@ -581,6 +634,9 @@
                     bp = mSettings.mPermissionTrees.get(p.info.name);
                 }
                 if (bp != null && bp.isPermission(p)) {
+                    if ((p.info.getProtection() & PermissionInfo.PROTECTION_DANGEROUS) != 0) {
+                        bps.add(bp);
+                    }
                     bp.setPermission(null);
                     if (DEBUG_REMOVE && chatty) {
                         if (r == null) {
@@ -599,6 +655,7 @@
                     }
                 }
             }
+            revokeAllPermissions(bps, allPackageNames, permissionCallback);
             if (r != null) {
                 if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
             }
@@ -788,10 +845,7 @@
                     // their permissions as always granted runtime ones since we need
                     // to keep the review required permission flag per user while an
                     // install permission's state is shared across all users.
-                    if (!appSupportsRuntimePermissions && !mSettings.mPermissionReviewRequired) {
-                        // For legacy apps dangerous permissions are install time ones.
-                        grant = GRANT_INSTALL;
-                    } else if (origPermissions.hasInstallPermission(bp.getName())) {
+                    if (origPermissions.hasInstallPermission(bp.getName())) {
                         // For legacy apps that became modern, install becomes runtime.
                         grant = GRANT_UPGRADE;
                     } else if (isLegacySystemApp) {
@@ -877,7 +931,7 @@
                                         updatedUserIds = ArrayUtils.appendInt(
                                                 updatedUserIds, userId);
                                     }
-                                    if (!mSettings.mPermissionReviewRequired || !revokeOnUpgrade) {
+                                    if (!revokeOnUpgrade) {
                                         if (permissionsState.grantRuntimePermission(bp, userId) ==
                                                 PermissionsState.PERMISSION_OPERATION_FAILURE) {
                                             // If we cannot put the permission as it was,
@@ -888,8 +942,7 @@
                                     }
 
                                     // If the app supports runtime permissions no need for a review.
-                                    if (mSettings.mPermissionReviewRequired
-                                            && appSupportsRuntimePermissions
+                                    if (appSupportsRuntimePermissions
                                             && (flags & PackageManager
                                                     .FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
                                         flags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
@@ -897,8 +950,7 @@
                                         updatedUserIds = ArrayUtils.appendInt(
                                                 updatedUserIds, userId);
                                     }
-                                } else if (mSettings.mPermissionReviewRequired
-                                        && !appSupportsRuntimePermissions) {
+                                } else if (!appSupportsRuntimePermissions) {
                                     // For legacy apps that need a permission review, every new
                                     // runtime permission is granted but it is pending a review.
                                     // We also need to review only platform defined runtime
@@ -1045,6 +1097,10 @@
         } else if (pkg.isProduct()) {
             wlPermissions =
                     SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName);
+        } else if (pkg.isProductServices()) {
+            wlPermissions =
+                    SystemConfig.getInstance().getProductServicesPrivAppPermissions(
+                            pkg.packageName);
         } else {
             wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
         }
@@ -1077,6 +1133,9 @@
                     } else if (pkg.isProduct()) {
                         deniedPermissions = SystemConfig.getInstance()
                                 .getProductPrivAppDenyPermissions(pkg.packageName);
+                    } else if (pkg.isProductServices()) {
+                        deniedPermissions = SystemConfig.getInstance()
+                                .getProductServicesPrivAppDenyPermissions(pkg.packageName);
                     } else {
                         deniedPermissions = SystemConfig.getInstance()
                                 .getPrivAppDenyPermissions(pkg.packageName);
@@ -1215,9 +1274,15 @@
                 // we still want to blindly grant it to old apps.
                 allowed = true;
             }
+            // TODO (moltmann): The installer now shares the platforms signature. Hence it does not
+            //                  need a separate flag anymore. Hence we need to check which
+            //                  permissions are needed by the permission controller
             if (!allowed && bp.isInstaller()
-                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
-                            PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM))) {
+                    && (pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
+                            PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM))
+                    || pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
+                            PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER,
+                            UserHandle.USER_SYSTEM)))) {
                 // If this permission is to be granted to the system installer and
                 // this app is an installer, then it gets the permission.
                 allowed = true;
@@ -1272,10 +1337,6 @@
     }
 
     private boolean isPermissionsReviewRequired(PackageParser.Package pkg, int userId) {
-        if (!mSettings.mPermissionReviewRequired) {
-            return false;
-        }
-
         // Permission review applies only to apps not supporting the new permission model.
         if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) {
             return false;
@@ -1377,7 +1438,7 @@
                         grantRuntimePermission(permission, pkg.packageName, false, callingUid,
                                 userId, callback);
                     }
-                } else if (mSettings.mPermissionReviewRequired) {
+                } else {
                     // In permission review mode we clear the review flag when we
                     // are asked to install the app with all permissions granted.
                     if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
@@ -1428,8 +1489,7 @@
         // their permissions as always granted runtime ones since we need
         // to keep the review required permission flag per user while an
         // install permission's state is shared across all users.
-        if (mSettings.mPermissionReviewRequired
-                && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
+        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
                 && bp.isRuntime()) {
             return;
         }
@@ -1511,9 +1571,10 @@
         }
 
     }
-
-    private void revokeRuntimePermission(String permName, String packageName,
-            boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) {
+    
+    private void revokeRuntimePermission(String permName, String packageName, BasePermission bp,
+            boolean overridePolicy, int callingUid, int userId, PermissionCallback callback,
+            boolean permissionRemoved) {
         if (!mUserManagerInt.exists(userId)) {
             Log.e(TAG, "No such user:" + userId);
             return;
@@ -1538,7 +1599,7 @@
         if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        final BasePermission bp = mSettings.getPermissionLocked(permName);
+
         if (bp == null) {
             throw new IllegalArgumentException("Unknown permission: " + permName);
         }
@@ -1549,8 +1610,7 @@
         // their permissions as always granted runtime ones since we need
         // to keep the review required permission flag per user while an
         // install permission's state is shared across all users.
-        if (mSettings.mPermissionReviewRequired
-                && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
+        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
                 && bp.isRuntime()) {
             return;
         }
@@ -2001,6 +2061,7 @@
         }
     }
 
+    @GuardedBy({"mSettings.mLock", "mLock"})
     private int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
         int size = 0;
         for (BasePermission perm : mSettings.mPermissions.values()) {
@@ -2009,6 +2070,7 @@
         return size;
     }
 
+    @GuardedBy({"mSettings.mLock", "mLock"})
     private void enforcePermissionCapLocked(PermissionInfo info, BasePermission tree) {
         // We calculate the max size of permissions defined by this uid and throw
         // if that plus the size of 'info' would exceed our stated maximum.
@@ -2094,8 +2156,10 @@
             PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);
         }
         @Override
-        public void removeAllPermissions(Package pkg, boolean chatty) {
-            PermissionManagerService.this.removeAllPermissions(pkg, chatty);
+        public void removeAllPermissions(Package pkg, List<String> allPackageNames,
+                PermissionCallback permissionCallback, boolean chatty) {
+            PermissionManagerService.this.removeAllPermissions(
+                    pkg, allPackageNames, permissionCallback, chatty);
         }
         @Override
         public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid,
@@ -2131,7 +2195,8 @@
                 boolean overridePolicy, int callingUid, int userId,
                 PermissionCallback callback) {
             PermissionManagerService.this.revokeRuntimePermission(permName, packageName,
-                    overridePolicy, callingUid, userId, callback);
+                    mSettings.getPermission(permName), overridePolicy, callingUid, userId,
+                    callback, false);
         }
         @Override
         public void updatePermissions(String packageName, Package pkg, boolean replaceGrant,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionSettings.java b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
index b3f2833..9208032 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionSettings.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
@@ -47,8 +47,6 @@
  */
 public class PermissionSettings {
 
-    public final boolean mPermissionReviewRequired;
-
     /**
      * All of the permissions known to the system. The mapping is from permission
      * name to permission object.
@@ -82,9 +80,7 @@
 
     private final Object mLock;
 
-    PermissionSettings(@NonNull Context context, @NonNull Object lock) {
-        mPermissionReviewRequired =
-                context.getResources().getBoolean(R.bool.config_permissionReviewRequired);
+    PermissionSettings(@NonNull Object lock) {
         mLock = lock;
     }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java
index 11df380..5e66bfc3 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java
@@ -20,9 +20,9 @@
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+
 import com.android.internal.util.ArrayUtils;
 
 import java.util.ArrayList;
@@ -291,6 +291,13 @@
     }
 
     /**
+     * Returns whether the state has any known request for the given permission name,
+     * whether or not it has been granted.
+     */
+    public boolean hasRequestedPermission(String name) {
+        return mPermissions != null && (mPermissions.get(name) != null);
+    }
+    /**
      * Gets all permissions for a given device user id regardless if they
      * are install time or runtime permissions.
      *
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index eca6f9f..14c985c 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -196,7 +196,7 @@
     }
 
     protected boolean skipAnimation() {
-        return false;
+        return !mWin.isDrawnLw();
     }
 
     private int computeStateLw(boolean wasVis, boolean wasAnim, WindowState win, boolean change) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b99f8d6..d15271c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -76,6 +76,7 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
@@ -127,7 +128,6 @@
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
-import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
 import static com.android.server.wm.WindowManagerPolicyProto.FOCUSED_APP_TOKEN;
@@ -222,7 +222,6 @@
 import android.speech.RecognizerIntent;
 import android.telecom.TelecomManager;
 import android.util.ArraySet;
-import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.LongSparseArray;
@@ -268,7 +267,6 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
-import com.android.internal.policy.KeyguardDismissCallback;
 import com.android.internal.policy.PhoneWindow;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.ArrayUtils;
@@ -287,8 +285,12 @@
 import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
 import com.android.server.wm.AppTransition;
 import com.android.server.wm.DisplayFrames;
+import com.android.server.wm.DisplayPolicy;
+import com.android.server.wm.DisplayRotation;
+import com.android.server.wm.WindowFrames;
 import com.android.server.wm.WindowManagerInternal;
 import com.android.server.wm.WindowManagerInternal.AppTransitionListener;
+import com.android.server.wm.utils.InsetUtils;
 
 import java.io.File;
 import java.io.FileReader;
@@ -497,8 +499,6 @@
     WindowState mStatusBar = null;
     private final int[] mStatusBarHeightForRotation = new int[4];
     WindowState mNavigationBar = null;
-    boolean mHasNavigationBar = false;
-    boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
     @NavigationBarPosition
     int mNavigationBarPosition = NAV_BAR_BOTTOM;
     int[] mNavigationBarHeightForRotationDefault = new int[4];
@@ -553,8 +553,6 @@
     volatile boolean mRecentsVisible;
     volatile boolean mNavBarVirtualKeyHapticFeedbackEnabled = true;
     volatile boolean mPictureInPictureVisible;
-    // Written by vr manager thread, only read in this class.
-    volatile private boolean mPersistentVrModeEnabled;
     volatile private boolean mDismissImeOnBackKeyPressed;
 
     // Used to hold the last user key used to wake the device.  This helps us prevent up events
@@ -564,40 +562,18 @@
     int mRecentAppsHeldModifiers;
     boolean mLanguageSwitchKeyPressed;
 
-    int mLidState = LID_ABSENT;
     int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
     boolean mHaveBuiltInKeyboard;
 
     boolean mSystemReady;
     boolean mSystemBooted;
-    boolean mHdmiPlugged;
     HdmiControl mHdmiControl;
     IUiModeManager mUiModeManager;
     int mUiMode;
-    int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
-    int mLidOpenRotation;
-    int mCarDockRotation;
-    int mDeskDockRotation;
-    int mUndockedHdmiRotation;
-    int mDemoHdmiRotation;
-    boolean mDemoHdmiRotationLock;
-    int mDemoRotation;
-    boolean mDemoRotationLock;
 
     boolean mWakeGestureEnabledSetting;
     MyWakeGestureListener mWakeGestureListener;
 
-    // Default display does not rotate, apps that require non-default orientation will have to
-    // have the orientation emulated.
-    private boolean mForceDefaultOrientation = false;
-
-    int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
-    int mUserRotation = Surface.ROTATION_0;
-
-    boolean mSupportAutoRotation;
-    int mAllowAllRotations = -1;
-    boolean mCarDockEnablesAccelerometer;
-    boolean mDeskDockEnablesAccelerometer;
     int mLidKeyboardAccessibility;
     int mLidNavigationAccessibility;
     boolean mLidControlsScreenLock;
@@ -610,14 +586,6 @@
     int mLongPressOnBackBehavior;
     int mShortPressOnSleepBehavior;
     int mShortPressOnWindowBehavior;
-    volatile boolean mAwake;
-    boolean mScreenOnEarly;
-    boolean mScreenOnFully;
-    ScreenOnListener mScreenOnListener;
-    boolean mKeyguardDrawComplete;
-    boolean mWindowManagerDrawComplete;
-    boolean mOrientationSensorEnabled = false;
-    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mHasSoftInput = false;
     boolean mTranslucentDecorEnabled = true;
     boolean mUseTvRouting;
@@ -629,8 +597,10 @@
 
     int mPointerLocationMode = 0; // guarded by mLock
 
-    // The last window we were told about in focusChanged.
+    // The windows we were told about in focusChanged.
     WindowState mFocusedWindow;
+    WindowState mLastFocusedWindow;
+
     IApplicationToken mFocusedApp;
 
     PointerLocationView mPointerLocationView;
@@ -661,15 +631,7 @@
 
     InputConsumer mInputConsumer = null;
 
-    static final Rect mTmpParentFrame = new Rect();
-    static final Rect mTmpDisplayFrame = new Rect();
-    static final Rect mTmpOverscanFrame = new Rect();
-    static final Rect mTmpContentFrame = new Rect();
-    static final Rect mTmpVisibleFrame = new Rect();
-    static final Rect mTmpDecorFrame = new Rect();
-    static final Rect mTmpStableFrame = new Rect();
-    static final Rect mTmpNavigationFrame = new Rect();
-    static final Rect mTmpOutsetFrame = new Rect();
+    private final WindowFrames mWindowFrames = new WindowFrames();
     private static final Rect mTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
     private static final Rect mTmpRect = new Rect();
 
@@ -732,18 +694,14 @@
     // Behavior of Back button while in-call and screen on
     int mIncallBackBehavior;
 
-    // Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION)
-    int mShowRotationSuggestions;
-
     // Whether system navigation keys are enabled
     boolean mSystemNavigationKeysEnabled;
 
-    Display mDisplay;
-
-    int mLandscapeRotation = 0;  // default landscape rotation
-    int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
-    int mPortraitRotation = 0;   // default portrait rotation
-    int mUpsideDownRotation = 0; // "other" portrait rotation
+    // TODO(b/111361251): Remove default when the dependencies are multi-display ready.
+    Display mDefaultDisplay;
+    DisplayRotation mDefaultDisplayRotation;
+    DisplayPolicy mDefaultDisplayPolicy;
+    WindowOrientationListener mDefaultOrientationListener;
 
     // What we do when the user long presses on home
     private int mLongPressOnHomeBehavior;
@@ -956,6 +914,7 @@
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                     mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                             android.Manifest.permission.USER_ACTIVITY);
+                    break;
                 case MSG_RINGER_TOGGLE_CHORD:
                     handleRingerChordGesture();
                     break;
@@ -966,7 +925,7 @@
     private UEventObserver mHDMIObserver = new UEventObserver() {
         @Override
         public void onUEvent(UEventObserver.UEvent event) {
-            setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
+            mDefaultDisplayPolicy.setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
         }
     };
 
@@ -991,12 +950,6 @@
                     Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.ACCELEROMETER_ROTATION), false, this,
-                    UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.USER_ROTATION), false, this,
-                    UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
                     Settings.System.SCREEN_OFF_TIMEOUT), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
@@ -1009,9 +962,6 @@
                     Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS), false, this,
-                    UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.VOLUME_HUSH_GESTURE), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.Global.getUriFor(
@@ -1038,7 +988,8 @@
         public void onWakeUp() {
             synchronized (mLock) {
                 if (shouldEnableWakeGestureLp()) {
-                    performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
+                    performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false,
+                            "Wake Up");
                     wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
                             "android.policy:GESTURE");
                 }
@@ -1046,53 +997,11 @@
         }
     }
 
-    class MyOrientationListener extends WindowOrientationListener {
-
-        private SparseArray<Runnable> mRunnableCache;
-
-        MyOrientationListener(Context context, Handler handler) {
-            super(context, handler);
-            mRunnableCache = new SparseArray<>(5);
-        }
-
-        private class UpdateRunnable implements Runnable {
-            private final int mRotation;
-            UpdateRunnable(int rotation) {
-                mRotation = rotation;
-            }
-
-            @Override
-            public void run() {
-                // send interaction hint to improve redraw performance
-                mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
-                if (isRotationChoicePossible(mCurrentAppOrientation)) {
-                    final boolean isValid = isValidRotationChoice(mCurrentAppOrientation,
-                            mRotation);
-                    sendProposedRotationChangeToStatusBarInternal(mRotation, isValid);
-                } else {
-                    updateRotation(false);
-                }
-            }
-        }
-
-        @Override
-        public void onProposedRotationChanged(int rotation) {
-            if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
-            Runnable r = mRunnableCache.get(rotation, null);
-            if (r == null){
-                r = new UpdateRunnable(rotation);
-                mRunnableCache.put(rotation, r);
-            }
-            mHandler.post(r);
-        }
-    }
-    MyOrientationListener mOrientationListener;
-
     final IPersistentVrStateCallbacks mPersistentVrModeListener =
             new IPersistentVrStateCallbacks.Stub() {
         @Override
         public void onPersistentVrStateChanged(boolean enabled) {
-            mPersistentVrModeEnabled = enabled;
+            mDefaultDisplayPolicy.setPersistentVrModeEnabled(enabled);
         }
     };
 
@@ -1174,100 +1083,6 @@
         }
     }
 
-    /*
-     * We always let the sensor be switched on by default except when
-     * the user has explicitly disabled sensor based rotation or when the
-     * screen is switched off.
-     */
-    boolean needSensorRunningLp() {
-        if (mSupportAutoRotation) {
-            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
-                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
-                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
-                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
-                // If the application has explicitly requested to follow the
-                // orientation, then we need to turn the sensor on.
-                return true;
-            }
-        }
-        if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
-                (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
-                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
-                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
-            // enable accelerometer if we are docked in a dock that enables accelerometer
-            // orientation management,
-            return true;
-        }
-        if (mUserRotationMode == USER_ROTATION_LOCKED) {
-            // If the setting for using the sensor by default is enabled, then
-            // we will always leave it on.  Note that the user could go to
-            // a window that forces an orientation that does not use the
-            // sensor and in theory we could turn it off... however, when next
-            // turning it on we won't have a good value for the current
-            // orientation for a little bit, which can cause orientation
-            // changes to lag, so we'd like to keep it always on.  (It will
-            // still be turned off when the screen is off.)
-
-            // When locked we can provide rotation suggestions users can approve to change the
-            // current screen rotation. To do this the sensor needs to be running.
-            return mSupportAutoRotation &&
-                    mShowRotationSuggestions == Settings.Secure.SHOW_ROTATION_SUGGESTIONS_ENABLED;
-        }
-        return mSupportAutoRotation;
-    }
-
-    /*
-     * Various use cases for invoking this function
-     * screen turning off, should always disable listeners if already enabled
-     * screen turned on and current app has sensor based orientation, enable listeners
-     * if not already enabled
-     * screen turned on and current app does not have sensor orientation, disable listeners if
-     * already enabled
-     * screen turning on and current app has sensor based orientation, enable listeners if needed
-     * screen turning on and current app has nosensor based orientation, do nothing
-     */
-    void updateOrientationListenerLp() {
-        if (!mOrientationListener.canDetectOrientation()) {
-            // If sensor is turned off or nonexistent for some reason
-            return;
-        }
-        // Could have been invoked due to screen turning on or off or
-        // change of the currently visible window's orientation.
-        if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
-                + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
-                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
-                + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
-                + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
-
-        boolean disable = true;
-        // Note: We postpone the rotating of the screen until the keyguard as well as the
-        // window manager have reported a draw complete or the keyguard is going away in dismiss
-        // mode.
-        if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete))) {
-            if (needSensorRunningLp()) {
-                disable = false;
-                //enable listener if not already enabled
-                if (!mOrientationSensorEnabled) {
-                    // Don't clear the current sensor orientation if the keyguard is going away in
-                    // dismiss mode. This allows window manager to use the last sensor reading to
-                    // determine the orientation vs. falling back to the last known orientation if
-                    // the sensor reading was cleared which can cause it to relaunch the app that
-                    // will show in the wrong orientation first before correcting leading to app
-                    // launch delays.
-                    mOrientationListener.enable(true /* clearCurrentRotation */);
-                    if(localLOGV) Slog.v(TAG, "Enabling listeners");
-                    mOrientationSensorEnabled = true;
-                }
-            }
-        }
-        //check if sensors need to be disabled
-        if (disable && mOrientationSensorEnabled) {
-            mOrientationListener.disable();
-            if(localLOGV) Slog.v(TAG, "Disabling listeners");
-            mOrientationSensorEnabled = false;
-        }
-    }
-
     private void interceptBackKeyDown() {
         MetricsLogger.count(mContext, "key_back_down", 1);
         // Reset back key state for long press
@@ -1493,7 +1308,7 @@
     }
 
     private void powerPress(long eventTime, boolean interactive, int count) {
-        if (mScreenOnEarly && !mScreenOnFully) {
+        if (mDefaultDisplayPolicy.isScreenOnEarly() && !mDefaultDisplayPolicy.isScreenOnFully()) {
             Slog.i(TAG, "Suppressed redundant power key press while "
                     + "already in the process of turning the screen on.");
             return;
@@ -1611,19 +1426,22 @@
             break;
         case LONG_PRESS_POWER_GLOBAL_ACTIONS:
             mPowerKeyHandled = true;
-            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+                    "Power - Long Press - Global Actions");
             showGlobalActionsInternal();
             break;
         case LONG_PRESS_POWER_SHUT_OFF:
         case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
             mPowerKeyHandled = true;
-            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+                    "Power - Long Press - Shut Off");
             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
             mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
             break;
         case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST:
             mPowerKeyHandled = true;
-            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+                    "Power - Long Press - Go To Voice Assist");
             final boolean keyguardActive = mKeyguardDelegate == null
                     ? false
                     : mKeyguardDelegate.isShowing();
@@ -1645,7 +1463,8 @@
             break;
         case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS:
             mPowerKeyHandled = true;
-            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+                    "Power - Very Long Press - Show Global Actions");
             showGlobalActionsInternal();
             break;
         }
@@ -1800,7 +1619,8 @@
         @Override
         public void run() {
             mEndCallKeyHandled = true;
-            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+                    "End Call - Long Press - Show Global Actions");
             showGlobalActionsInternal();
         }
     };
@@ -1927,7 +1747,8 @@
             return;
         }
         mHomeConsumed = true;
-        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+                "Home - Long Press");
         switch (mLongPressOnHomeBehavior) {
             case LONG_PRESS_HOME_ALL_APPS:
                 launchAllAppsAction();
@@ -1993,6 +1814,14 @@
         return mContext.getResources().getConfiguration().isScreenRound();
     }
 
+    @Override
+    public void setDefaultDisplay(DisplayContentInfo displayContentInfo) {
+        mDefaultDisplay = displayContentInfo.getDisplay();
+        mDefaultDisplayRotation = displayContentInfo.getDisplayRotation();
+        mDefaultDisplayPolicy = mDefaultDisplayRotation.getDisplayPolicy();
+        mDefaultOrientationListener = mDefaultDisplayRotation.getOrientationListener();
+    }
+
     /** {@inheritDoc} */
     @Override
     public void init(Context context, IWindowManager windowManager,
@@ -2049,10 +1878,6 @@
 
         mHandler = new PolicyHandler();
         mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
-        mOrientationListener = new MyOrientationListener(mContext, mHandler);
-        try {
-            mOrientationListener.setCurrentRotation(windowManager.getDefaultDisplayRotation());
-        } catch (RemoteException ex) { }
         mSettingsObserver = new SettingsObserver(mHandler);
         mSettingsObserver.observe();
         mShortcutManager = new ShortcutManager(context);
@@ -2083,20 +1908,6 @@
         mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                 "PhoneWindowManager.mPowerKeyWakeLock");
         mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
-        mSupportAutoRotation = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_supportAutoRotation);
-        mLidOpenRotation = readRotation(
-                com.android.internal.R.integer.config_lidOpenRotation);
-        mCarDockRotation = readRotation(
-                com.android.internal.R.integer.config_carDockRotation);
-        mDeskDockRotation = readRotation(
-                com.android.internal.R.integer.config_deskDockRotation);
-        mUndockedHdmiRotation = readRotation(
-                com.android.internal.R.integer.config_undockedHdmiRotation);
-        mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
-        mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
         mLidKeyboardAccessibility = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lidKeyboardAccessibility);
         mLidNavigationAccessibility = mContext.getResources().getInteger(
@@ -2170,8 +1981,8 @@
         Intent intent = context.registerReceiver(mDockReceiver, filter);
         if (intent != null) {
             // Retrieve current sticky dock event broadcast.
-            mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
-                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
+            mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+                    Intent.EXTRA_DOCK_STATE_UNDOCKED));
         }
 
         // register for dream-related broadcasts
@@ -2225,11 +2036,11 @@
                     }
                     @Override
                     public void onDown() {
-                        mOrientationListener.onTouchStart();
+                        mDefaultOrientationListener.onTouchStart();
                     }
                     @Override
                     public void onUpOrCancel() {
-                        mOrientationListener.onTouchEnd();
+                        mDefaultOrientationListener.onTouchEnd();
                     }
                     @Override
                     public void onMouseHoverAtTop() {
@@ -2336,110 +2147,12 @@
                 com.android.internal.R.integer.config_navBarOpacityMode);
     }
 
-    @Override
-    public void setInitialDisplaySize(Display display, int width, int height, int density) {
-        // This method might be called before the policy has been fully initialized
-        // or for other displays we don't care about.
-        // TODO(multi-display): Define policy for secondary displays.
-        if (mContext == null || display.getDisplayId() != DEFAULT_DISPLAY) {
-            return;
-        }
-        mDisplay = display;
-
-        final Resources res = mContext.getResources();
-        int shortSize, longSize;
-        if (width > height) {
-            shortSize = height;
-            longSize = width;
-            mLandscapeRotation = Surface.ROTATION_0;
-            mSeascapeRotation = Surface.ROTATION_180;
-            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
-                mPortraitRotation = Surface.ROTATION_90;
-                mUpsideDownRotation = Surface.ROTATION_270;
-            } else {
-                mPortraitRotation = Surface.ROTATION_270;
-                mUpsideDownRotation = Surface.ROTATION_90;
-            }
-        } else {
-            shortSize = width;
-            longSize = height;
-            mPortraitRotation = Surface.ROTATION_0;
-            mUpsideDownRotation = Surface.ROTATION_180;
-            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
-                mLandscapeRotation = Surface.ROTATION_270;
-                mSeascapeRotation = Surface.ROTATION_90;
-            } else {
-                mLandscapeRotation = Surface.ROTATION_90;
-                mSeascapeRotation = Surface.ROTATION_270;
-            }
-        }
-
-        // SystemUI (status bar) layout policy
-        int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
-        int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
-
-        // Allow the navigation bar to move on non-square small devices (phones).
-        mNavigationBarCanMove = width != height && shortSizeDp < 600;
-
-        mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
-
-        // Allow a system property to override this. Used by the emulator.
-        // See also hasNavigationBar().
-        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
-        if ("1".equals(navBarOverride)) {
-            mHasNavigationBar = false;
-        } else if ("0".equals(navBarOverride)) {
-            mHasNavigationBar = true;
-        }
-
-        // For demo purposes, allow the rotation of the HDMI display to be controlled.
-        // By default, HDMI locks rotation to landscape.
-        if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
-            mDemoHdmiRotation = mPortraitRotation;
-        } else {
-            mDemoHdmiRotation = mLandscapeRotation;
-        }
-        mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
-
-        // For demo purposes, allow the rotation of the remote display to be controlled.
-        // By default, remote display locks rotation to landscape.
-        if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
-            mDemoRotation = mPortraitRotation;
-        } else {
-            mDemoRotation = mLandscapeRotation;
-        }
-        mDemoRotationLock = SystemProperties.getBoolean(
-                "persist.demo.rotationlock", false);
-
-        // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
-        // http://developer.android.com/guide/practices/screens_support.html#range
-        // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
-        // so if the orientation is forced, we need to respect that no matter what.
-        final boolean isCar = mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_AUTOMOTIVE);
-        // For TV, it's usually 960dp x 540dp, ignore the size limitation.
-        // so if the orientation is forced, we need to respect that no matter what.
-        final boolean isTv = mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_LEANBACK);
-        mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
-                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
-                // For debug purposes the next line turns this feature off with:
-                // $ adb shell setprop config.override_forced_orient true
-                // $ adb shell wm size reset
-                !"true".equals(SystemProperties.get("config.override_forced_orient"));
-    }
-
     /**
      * @return whether the navigation bar can be hidden, e.g. the device has a
      *         navigation bar and touch exploration is not enabled
      */
     private boolean canHideNavigationBar() {
-        return mHasNavigationBar;
-    }
-
-    @Override
-    public boolean isDefaultOrientationForced() {
-        return mForceDefaultOrientation;
+        return mDefaultDisplayPolicy.hasNavigationBar();
     }
 
     public void updateSettings() {
@@ -2468,15 +2181,6 @@
                     .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
                 mRingerToggleChord = Settings.Secure.VOLUME_HUSH_OFF;
             }
-            // Configure rotation suggestions.
-            int showRotationSuggestions = Settings.Secure.getIntForUser(resolver,
-                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
-                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS_DEFAULT,
-                    UserHandle.USER_CURRENT);
-            if (mShowRotationSuggestions != showRotationSuggestions) {
-                mShowRotationSuggestions = showRotationSuggestions;
-                updateOrientationListenerLp(); // Enable, disable the orientation listener
-            }
 
             // Configure wake gesture.
             boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
@@ -2487,24 +2191,6 @@
                 updateWakeGestureListenerLp();
             }
 
-            // Configure rotation lock.
-            int userRotation = Settings.System.getIntForUser(resolver,
-                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
-                    UserHandle.USER_CURRENT);
-            if (mUserRotation != userRotation) {
-                mUserRotation = userRotation;
-                updateRotation = true;
-            }
-            int userRotationMode = Settings.System.getIntForUser(resolver,
-                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
-                            WindowManagerPolicy.USER_ROTATION_FREE :
-                                    WindowManagerPolicy.USER_ROTATION_LOCKED;
-            if (mUserRotationMode != userRotationMode) {
-                mUserRotationMode = userRotationMode;
-                updateRotation = true;
-                updateOrientationListenerLp();
-            }
-
             if (mSystemReady) {
                 int pointerLocation = Settings.System.getIntForUser(resolver,
                         Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
@@ -2545,8 +2231,8 @@
     }
 
     private boolean shouldEnableWakeGestureLp() {
-        return mWakeGestureEnabledSetting && !mAwake
-                && (!mLidControlsSleep || mLidState != LID_CLOSED)
+        return mWakeGestureEnabledSetting && !mDefaultDisplayPolicy.isAwake()
+                && (!mLidControlsSleep || mDefaultDisplayPolicy.getLidState() != LID_CLOSED)
                 && mWakeGestureListener.isSupported();
     }
 
@@ -2586,24 +2272,6 @@
         }
     }
 
-    private int readRotation(int resID) {
-        try {
-            int rotation = mContext.getResources().getInteger(resID);
-            switch (rotation) {
-                case 0:
-                    return Surface.ROTATION_0;
-                case 90:
-                    return Surface.ROTATION_90;
-                case 180:
-                    return Surface.ROTATION_180;
-                case 270:
-                    return Surface.ROTATION_270;
-            }
-        } catch (Resources.NotFoundException e) {
-            // fall through
-        }
-        return -1;
-    }
 
     /** {@inheritDoc} */
     @Override
@@ -2832,7 +2500,7 @@
     }
 
     void readLidState() {
-        mLidState = mWindowManagerFuncs.getLidState();
+        mDefaultDisplayPolicy.setLidState(mWindowManagerFuncs.getLidState());
     }
 
     private void readCameraLensCoverState() {
@@ -2840,11 +2508,12 @@
     }
 
     private boolean isHidden(int accessibilityMode) {
+        final int lidState = mDefaultDisplayPolicy.getLidState();
         switch (accessibilityMode) {
             case 1:
-                return mLidState == LID_CLOSED;
+                return lidState == LID_CLOSED;
             case 2:
-                return mLidState == LID_OPEN;
+                return lidState == LID_OPEN;
             default:
                 return false;
         }
@@ -2876,53 +2545,62 @@
     }
 
     @Override
-    public void onOverlayChangedLw() {
-        onConfigurationChanged();
+    public void onOverlayChangedLw(DisplayContentInfo displayContentInfo) {
+        onConfigurationChanged(displayContentInfo);
     }
 
     @Override
-    public void onConfigurationChanged() {
+    public void onConfigurationChanged(DisplayContentInfo displayContentInfo) {
+        final DisplayRotation displayRotation = displayContentInfo.getDisplayRotation();
         // TODO(multi-display): Define policy for secondary displays.
-        Context uiContext = getSystemUiContext();
-        final Resources res = uiContext.getResources();
+        if (!displayRotation.isDefaultDisplay) {
+            return;
+        }
 
-        mStatusBarHeightForRotation[mPortraitRotation] =
-                mStatusBarHeightForRotation[mUpsideDownRotation] = res.getDimensionPixelSize(
+        final Context uiContext = getSystemUiContext();
+        final Resources res = uiContext.getResources();
+        final int portraitRotation = displayRotation.getPortraitRotation();
+        final int upsideDownRotation = displayRotation.getUpsideDownRotation();
+        final int landscapeRotation = displayRotation.getLandscapeRotation();
+        final int seascapeRotation = displayRotation.getSeascapeRotation();
+
+        mStatusBarHeightForRotation[portraitRotation] =
+                mStatusBarHeightForRotation[upsideDownRotation] = res.getDimensionPixelSize(
                                 com.android.internal.R.dimen.status_bar_height_portrait);
-        mStatusBarHeightForRotation[mLandscapeRotation] =
-                mStatusBarHeightForRotation[mSeascapeRotation] = res.getDimensionPixelSize(
+        mStatusBarHeightForRotation[landscapeRotation] =
+                mStatusBarHeightForRotation[seascapeRotation] = res.getDimensionPixelSize(
                         com.android.internal.R.dimen.status_bar_height_landscape);
 
         // Height of the navigation bar when presented horizontally at bottom
-        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
-        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
+        mNavigationBarHeightForRotationDefault[portraitRotation] =
+        mNavigationBarHeightForRotationDefault[upsideDownRotation] =
                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
-        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
-        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
+        mNavigationBarHeightForRotationDefault[landscapeRotation] =
+        mNavigationBarHeightForRotationDefault[seascapeRotation] = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.navigation_bar_height_landscape);
 
         // Width of the navigation bar when presented vertically along one side
-        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
-        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
-        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
-        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
+        mNavigationBarWidthForRotationDefault[portraitRotation] =
+        mNavigationBarWidthForRotationDefault[upsideDownRotation] =
+        mNavigationBarWidthForRotationDefault[landscapeRotation] =
+        mNavigationBarWidthForRotationDefault[seascapeRotation] =
                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
 
         if (ALTERNATE_CAR_MODE_NAV_SIZE) {
             // Height of the navigation bar when presented horizontally at bottom
-            mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
-            mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
+            mNavigationBarHeightForRotationInCarMode[portraitRotation] =
+            mNavigationBarHeightForRotationInCarMode[upsideDownRotation] =
                     res.getDimensionPixelSize(
                             com.android.internal.R.dimen.navigation_bar_height_car_mode);
-            mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
-            mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
+            mNavigationBarHeightForRotationInCarMode[landscapeRotation] =
+            mNavigationBarHeightForRotationInCarMode[seascapeRotation] = res.getDimensionPixelSize(
                     com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
 
             // Width of the navigation bar when presented vertically along one side
-            mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
-            mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
-            mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
-            mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
+            mNavigationBarWidthForRotationInCarMode[portraitRotation] =
+            mNavigationBarWidthForRotationInCarMode[upsideDownRotation] =
+            mNavigationBarWidthForRotationInCarMode[landscapeRotation] =
+            mNavigationBarWidthForRotationInCarMode[seascapeRotation] =
                     res.getDimensionPixelSize(
                             com.android.internal.R.dimen.navigation_bar_width_car_mode);
         }
@@ -2951,10 +2629,10 @@
             int displayId, DisplayCutout displayCutout) {
         int width = fullWidth;
         // TODO(multi-display): Support navigation bar on secondary displays.
-        if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
+        if (displayId == DEFAULT_DISPLAY && mDefaultDisplayPolicy.hasNavigationBar()) {
             // For a basic navigation bar, when we are in landscape mode we place
             // the navigation bar to the side.
-            if (mNavigationBarCanMove && fullWidth > fullHeight) {
+            if (mDefaultDisplayPolicy.navigationBarCanMove() && fullWidth > fullHeight) {
                 width -= getNavigationBarWidth(rotation, uiMode);
             }
         }
@@ -2977,10 +2655,10 @@
             int displayId, DisplayCutout displayCutout) {
         int height = fullHeight;
         // TODO(multi-display): Support navigation bar on secondary displays.
-        if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
+        if (displayId == DEFAULT_DISPLAY && mDefaultDisplayPolicy.hasNavigationBar()) {
             // For a basic navigation bar, when we are in portrait mode we place
             // the navigation bar to the bottom.
-            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
+            if (!mDefaultDisplayPolicy.navigationBarCanMove() || fullWidth < fullHeight) {
                 height -= getNavigationBarHeight(rotation, uiMode);
             }
         }
@@ -3068,8 +2746,8 @@
         // In that case, we want to continue hiding the IME until the windows have completed
         // drawing. This way, we know that the IME can be safely shown since the other windows are
         // now shown.
-        final boolean hideIme =
-                win.isInputMethodWindow() && (mAodShowing || !mWindowManagerDrawComplete);
+        final boolean hideIme = win.isInputMethodWindow()
+                && (mAodShowing || !mDefaultDisplayPolicy.isWindowManagerDrawComplete());
         return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
                 || hideDockDivider || hideIme;
     }
@@ -3332,6 +3010,9 @@
             mNavigationBar = null;
             mNavigationBarController.setWindow(null);
         }
+        if (mLastFocusedWindow == win) {
+            mLastFocusedWindow = null;
+        }
         mScreenDecorWindows.remove(win);
     }
 
@@ -3444,7 +3125,7 @@
     @Override
     public void selectRotationAnimationLw(int anim[]) {
         // If the screen is off or non-interactive, force a jumpcut.
-        final boolean forceJumpcut = !mScreenOnFully || !okToAnimate();
+        final boolean forceJumpcut = !mDefaultDisplayPolicy.isScreenOnFully() || !okToAnimate();
         if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
                 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
                 + (mTopFullscreenOpaqueWindowState == null ?
@@ -3851,7 +3532,7 @@
             // 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 (mPersistentVrModeEnabled) {
+            if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {
                 final InputDevice d = event.getDevice();
                 if (d != null && !d.isExternal()) {
                     return -1;
@@ -4249,7 +3930,8 @@
     }
 
     private void launchAssistLongPressAction() {
-        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+                "Assist - Long Press");
         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
 
         // launch the search activity
@@ -4391,17 +4073,9 @@
             if (isKeyguardShowingAndNotOccluded()) {
                 // don't launch home if keyguard showing
                 return;
-            } else if (mKeyguardOccluded && mKeyguardDelegate.isShowing()) {
-                mKeyguardDelegate.dismiss(new KeyguardDismissCallback() {
-                    @Override
-                    public void onDismissSucceeded() throws RemoteException {
-                        mHandler.post(() -> {
-                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
-                        });
-                    }
-                }, null /* message */);
-                return;
-            } else if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
+            }
+
+            if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
                 // when in keyguard restricted mode, must first verify unlock
                 // before launching home
                 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
@@ -4535,16 +4209,15 @@
 
     @Override
     // TODO: Should probably be moved into DisplayFrames.
-    public boolean getLayoutHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
-            DisplayFrames displayFrames, Rect outFrame, Rect outContentInsets, Rect outStableInsets,
+    public boolean getLayoutHintLw(LayoutParams attrs, Rect taskBounds,
+            DisplayFrames displayFrames, boolean floatingStack, Rect outFrame,
+            Rect outContentInsets, Rect outStableInsets,
             Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout) {
         final int fl = PolicyControl.getWindowFlags(null, attrs);
         final int pfl = attrs.privateFlags;
         final int requestedSysUiVis = PolicyControl.getSystemUiVisibility(null, attrs);
         final int sysUiVis = requestedSysUiVis | getImpliedSysUiFlagsForLayout(attrs);
         final int displayRotation = displayFrames.mRotation;
-        final int displayWidth = displayFrames.mDisplayWidth;
-        final int displayHeight = displayFrames.mDisplayHeight;
 
         final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
         if (useOutsets) {
@@ -4568,45 +4241,40 @@
         final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
 
         if (layoutInScreenAndInsetDecor && !screenDecor) {
-            int availRight, availBottom;
             if (canHideNavigationBar() &&
                     (sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
                 outFrame.set(displayFrames.mUnrestricted);
-                availRight = displayFrames.mUnrestricted.right;
-                availBottom = displayFrames.mUnrestricted.bottom;
             } else {
                 outFrame.set(displayFrames.mRestricted);
-                availRight = displayFrames.mRestricted.right;
-                availBottom = displayFrames.mRestricted.bottom;
             }
-            outStableInsets.set(displayFrames.mStable.left, displayFrames.mStable.top,
-                    availRight - displayFrames.mStable.right,
-                    availBottom - displayFrames.mStable.bottom);
 
-            if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
+            final Rect sf;
+            if (floatingStack) {
+                sf = null;
+            } else {
+                sf = displayFrames.mStable;
+            }
+
+            final Rect cf;
+            if (floatingStack) {
+                cf = null;
+            } else if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
                 if ((fl & FLAG_FULLSCREEN) != 0) {
-                    outContentInsets.set(displayFrames.mStableFullscreen.left,
-                            displayFrames.mStableFullscreen.top,
-                            availRight - displayFrames.mStableFullscreen.right,
-                            availBottom - displayFrames.mStableFullscreen.bottom);
+                    cf = displayFrames.mStableFullscreen;
                 } else {
-                    outContentInsets.set(outStableInsets);
+                    cf = displayFrames.mStable;
                 }
             } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
-                outContentInsets.setEmpty();
+                cf = displayFrames.mOverscan;
             } else {
-                outContentInsets.set(displayFrames.mCurrent.left, displayFrames.mCurrent.top,
-                        availRight - displayFrames.mCurrent.right,
-                        availBottom - displayFrames.mCurrent.bottom);
+                cf = displayFrames.mCurrent;
             }
 
             if (taskBounds != null) {
-                calculateRelevantTaskInsets(taskBounds, outContentInsets,
-                        displayWidth, displayHeight);
-                calculateRelevantTaskInsets(taskBounds, outStableInsets,
-                        displayWidth, displayHeight);
                 outFrame.intersect(taskBounds);
             }
+            InsetUtils.insetsBetweenFrames(outFrame, cf, outContentInsets);
+            InsetUtils.insetsBetweenFrames(outFrame, sf, outStableInsets);
             outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame)
                     .getDisplayCutout());
             return mForceShowSystemBars;
@@ -4627,22 +4295,6 @@
         }
     }
 
-    /**
-     * For any given task bounds, the insets relevant for these bounds given the insets relevant
-     * for the entire display.
-     */
-    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
-            int displayHeight) {
-        mTmpRect.set(0, 0, displayWidth, displayHeight);
-        mTmpRect.inset(inOutInsets);
-        mTmpRect.intersect(taskBounds);
-        int leftInset = mTmpRect.left - taskBounds.left;
-        int topInset = mTmpRect.top - taskBounds.top;
-        int rightInset = taskBounds.right - mTmpRect.right;
-        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
-        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
-    }
-
     private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
         return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
@@ -4658,17 +4310,8 @@
         mDockLayer = 0x10000000;
         mStatusBarLayer = -1;
 
-        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
-        final Rect pf = mTmpParentFrame;
-        final Rect df = mTmpDisplayFrame;
-        final Rect of = mTmpOverscanFrame;
-        final Rect vf = mTmpVisibleFrame;
-        final Rect dcf = mTmpDecorFrame;
-        vf.set(displayFrames.mDock);
-        of.set(displayFrames.mDock);
-        df.set(displayFrames.mDock);
-        pf.set(displayFrames.mDock);
-        dcf.setEmpty();  // Decor frame N/A for system bars.
+        mWindowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
+        mWindowFrames.setParentFrameWasClippedByDisplayCutout(false);
 
         if (displayFrames.mDisplayId == DEFAULT_DISPLAY) {
             // For purposes of putting out fake window up to steal focus, we will
@@ -4685,9 +4328,9 @@
             if (!isKeyguardShowing) {
                 navTranslucent &= areTranslucentBarsAllowed();
             }
-            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
-                    && mStatusBar.getAttrs().height == MATCH_PARENT
-                    && mStatusBar.getAttrs().width == MATCH_PARENT;
+            boolean statusBarForcesShowingNavigation = !isKeyguardShowing && mStatusBar != null
+                    && (mStatusBar.getAttrs().privateFlags
+                            & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
 
             // When the navigation bar isn't visible, we put up a fake input window to catch all
             // touch events. This way we can detect when the user presses anywhere to bring back the
@@ -4701,7 +4344,8 @@
             } else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) {
                 mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
                         INPUT_CONSUMER_NAVIGATION,
-                        (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
+                        (channel, looper) -> new HideNavInputEventReceiver(channel, looper),
+                        displayFrames.mDisplayId);
                 // As long as mInputConsumer is active, hover events are not dispatched to the app
                 // and the pointer icon is likely to become stale. Hide it to avoid confusion.
                 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
@@ -4711,16 +4355,15 @@
             // be hidden (because of the screen aspect ratio), then take that into account.
             navVisible |= !canHideNavigationBar();
 
-            boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, dcf,
-                    navVisible, navTranslucent, navAllowedHidden, statusBarExpandedNotKeyguard);
+            boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, navVisible,
+                    navTranslucent, navAllowedHidden, statusBarForcesShowingNavigation);
             if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock);
-            updateSysUiVisibility |= layoutStatusBar(
-                    displayFrames, pf, df, of, vf, dcf, sysui, isKeyguardShowing);
+            updateSysUiVisibility |= layoutStatusBar(displayFrames, sysui, isKeyguardShowing);
             if (updateSysUiVisibility) {
                 updateSystemUiVisibilityLw();
             }
         }
-        layoutScreenDecorWindows(displayFrames, pf, df, dcf);
+        layoutScreenDecorWindows(displayFrames);
 
         if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
             // Make sure that the zone we're avoiding for the cutout is at least as tall as the
@@ -4731,11 +4374,18 @@
         }
     }
 
-    private void layoutScreenDecorWindows(DisplayFrames displayFrames, Rect pf, Rect df, Rect dcf) {
+    private void layoutScreenDecorWindows(DisplayFrames displayFrames) {
         if (mScreenDecorWindows.isEmpty()) {
             return;
         }
 
+        mTmpRect.setEmpty();
+        mWindowFrames.setFrames(displayFrames.mDock /* parentFrame */,
+                displayFrames.mDock /* displayFrame */, displayFrames.mDock /* overscanFrame */,
+                displayFrames.mDock /* contentFrame */, displayFrames.mDock /* visibleFrame */,
+                mTmpRect /* decorFrame */, displayFrames.mDock /* stableFrame */,
+                displayFrames.mDock /* outsetFrame */);
+
         final int displayId = displayFrames.mDisplayId;
         final Rect dockFrame = displayFrames.mDock;
         final int displayHeight = displayFrames.mDisplayHeight;
@@ -4748,10 +4398,7 @@
                 continue;
             }
 
-            w.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, df /* overlayFrame */,
-                    df /* contentFrame */, df /* visibleFrame */, dcf /* decorFrame */,
-                    df /* stableFrame */, df /* outsetFrame */, displayFrames.mDisplayCutout,
-                    false /* parentFrameWasClippedByDisplayCutout */);
+            w.computeFrameLw(mWindowFrames);
             final Rect frame = w.getFrameLw();
 
             if (frame.left <= 0 && frame.top <= 0) {
@@ -4796,25 +4443,24 @@
         displayFrames.mRestrictedOverscan.set(dockFrame);
     }
 
-    private boolean layoutStatusBar(DisplayFrames displayFrames, Rect pf, Rect df, Rect of, Rect vf,
-            Rect dcf, int sysui, boolean isKeyguardShowing) {
+    private boolean layoutStatusBar(DisplayFrames displayFrames, int sysui,
+            boolean isKeyguardShowing) {
         // decide where the status bar goes ahead of time
         if (mStatusBar == null) {
             return false;
         }
         // apply any navigation bar insets
-        of.set(displayFrames.mUnrestricted);
-        df.set(displayFrames.mUnrestricted);
-        pf.set(displayFrames.mUnrestricted);
-        vf.set(displayFrames.mStable);
+        mTmpRect.setEmpty();
+        mWindowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
+                displayFrames.mUnrestricted /* displayFrame */,
+                displayFrames.mStable /* overscanFrame */, displayFrames.mStable /* contentFrame */,
+                displayFrames.mStable /* visibleFrame */, mTmpRect /* decorFrame */,
+                displayFrames.mStable /* stableFrame */, displayFrames.mStable /* outsetFrame */);
 
         mStatusBarLayer = mStatusBar.getSurfaceLayer();
 
         // Let the status bar determine its size.
-        mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
-                vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
-                dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */,
-                displayFrames.mDisplayCutout, false /* parentFrameWasClippedByDisplayCutout */);
+        mStatusBar.computeFrameLw(mWindowFrames);
 
         // For layout, the status bar is always at the top with our fixed height.
         displayFrames.mStable.top = displayFrames.mUnrestricted.top
@@ -4861,12 +4507,14 @@
         return mStatusBarController.checkHiddenLw();
     }
 
-    private boolean layoutNavigationBar(DisplayFrames displayFrames, int uiMode, Rect dcf,
-            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
-            boolean statusBarExpandedNotKeyguard) {
+    private boolean layoutNavigationBar(DisplayFrames displayFrames, int uiMode, boolean navVisible,
+            boolean navTranslucent, boolean navAllowedHidden,
+            boolean statusBarForcesShowingNavigation) {
         if (mNavigationBar == null) {
             return false;
         }
+
+        final Rect navigationFrame = mWindowFrames.mParentFrame;
         boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
         // Force the navigation bar to its appropriate place and size. We need to do this directly,
         // instead of relying on it to bubble up from the nav bar, because this needs to change
@@ -4885,7 +4533,7 @@
             // It's a system nav bar or a portrait screen; nav bar goes on bottom.
             final int top = cutoutSafeUnrestricted.bottom
                     - getNavigationBarHeight(rotation, uiMode);
-            mTmpNavigationFrame.set(0, top, displayWidth, displayFrames.mUnrestricted.bottom);
+            navigationFrame.set(0, top, displayWidth, displayFrames.mUnrestricted.bottom);
             displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -4895,7 +4543,7 @@
                         = displayFrames.mRestrictedOverscan.bottom = top;
             } else {
                 // We currently want to hide the navigation UI - unless we expanded the status bar.
-                mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
+                mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
             }
             if (navVisible && !navTranslucent && !navAllowedHidden
                     && !mNavigationBar.isAnimatingLw()
@@ -4908,7 +4556,7 @@
             // Landscape screen; nav bar goes to the right.
             final int left = cutoutSafeUnrestricted.right
                     - getNavigationBarWidth(rotation, uiMode);
-            mTmpNavigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
+            navigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
             displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -4918,7 +4566,7 @@
                         = displayFrames.mRestrictedOverscan.right = left;
             } else {
                 // We currently want to hide the navigation UI - unless we expanded the status bar.
-                mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
+                mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
             }
             if (navVisible && !navTranslucent && !navAllowedHidden
                     && !mNavigationBar.isAnimatingLw()
@@ -4931,7 +4579,7 @@
             // Seascape screen; nav bar goes to the left.
             final int right = cutoutSafeUnrestricted.left
                     + getNavigationBarWidth(rotation, uiMode);
-            mTmpNavigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
+            navigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
             displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -4941,7 +4589,7 @@
                         displayFrames.mRestrictedOverscan.left = right;
             } else {
                 // We currently want to hide the navigation UI - unless we expanded the status bar.
-                mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
+                mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
             }
             if (navVisible && !navTranslucent && !navAllowedHidden
                     && !mNavigationBar.isAnimatingLw()
@@ -4959,19 +4607,24 @@
         displayFrames.mContent.set(dockFrame);
         mStatusBarLayer = mNavigationBar.getSurfaceLayer();
         // And compute the final frame.
-        mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
-                mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe, mTmpNavigationFrame, dcf,
-                mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe,
-                displayFrames.mDisplayCutout, false /* parentFrameWasClippedByDisplayCutout */);
+        mTmpRect.setEmpty();
+        mWindowFrames.setFrames(navigationFrame /* parentFrame */,
+                navigationFrame /* displayFrame */, navigationFrame /* overscanFrame */,
+                displayFrames.mDisplayCutoutSafe /* contentFrame */,
+                navigationFrame /* visibleFrame */, mTmpRect /* decorFrame */,
+                navigationFrame /* stableFrame */,
+                displayFrames.mDisplayCutoutSafe /* outsetFrame */);
+
+        mNavigationBar.computeFrameLw(mWindowFrames);
         mNavigationBarController.setContentFrame(mNavigationBar.getContentFrameLw());
 
-        if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
+        if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame);
         return mNavigationBarController.checkHiddenLw();
     }
 
     @NavigationBarPosition
     private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
-        if (mNavigationBarCanMove && displayWidth > displayHeight) {
+        if (mDefaultDisplayPolicy.navigationBarCanMove() && displayWidth > displayHeight) {
             if (displayRotation == Surface.ROTATION_270) {
                 return NAV_BAR_LEFT;
             } else {
@@ -5093,17 +4746,19 @@
         final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs);
         final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs);
 
-        final Rect pf = mTmpParentFrame;
-        final Rect df = mTmpDisplayFrame;
-        final Rect of = mTmpOverscanFrame;
-        final Rect cf = mTmpContentFrame;
-        final Rect vf = mTmpVisibleFrame;
-        final Rect dcf = mTmpDecorFrame;
-        final Rect sf = mTmpStableFrame;
-        Rect osf = null;
+        final Rect pf = mWindowFrames.mParentFrame;
+        final Rect df = mWindowFrames.mDisplayFrame;
+        final Rect of = mWindowFrames.mOverscanFrame;
+        final Rect cf = mWindowFrames.mContentFrame;
+        final Rect vf = mWindowFrames.mVisibleFrame;
+        final Rect dcf = mWindowFrames.mDecorFrame;
+        final Rect sf = mWindowFrames.mStableFrame;
         dcf.setEmpty();
+        mWindowFrames.mOutsetFrame.setEmpty();
+        mWindowFrames.setParentFrameWasClippedByDisplayCutout(false);
+        mWindowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
 
-        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
+        final boolean hasNavBar = (isDefaultDisplay && mDefaultDisplayPolicy.hasNavigationBar()
                 && mNavigationBar != null && mNavigationBar.isVisibleLw());
 
         final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
@@ -5421,7 +5076,6 @@
             }
         }
 
-        boolean parentFrameWasClippedByDisplayCutout = false;
         final int cutoutMode = attrs.layoutInDisplayCutoutMode;
         final boolean attachedInParent = attached != null && !layoutInScreen;
         final boolean requestedHideNavigation =
@@ -5472,7 +5126,7 @@
             if (!attachedInParent && !floatingInScreenWindow) {
                 mTmpRect.set(pf);
                 pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
-                parentFrameWasClippedByDisplayCutout |= !mTmpRect.equals(pf);
+                mWindowFrames.setParentFrameWasClippedByDisplayCutout(!mTmpRect.equals(pf));
             }
             // Make sure that NO_LIMITS windows clipped to the display don't extend under the
             // cutout.
@@ -5500,7 +5154,7 @@
         // apply the outsets to floating dialogs, because they wouldn't make sense there.
         final boolean useOutsets = shouldUseOutsets(attrs, fl);
         if (isDefaultDisplay && useOutsets) {
-            osf = mTmpOutsetFrame;
+            final Rect osf = mWindowFrames.mOutsetFrame;
             osf.set(cf.left, cf.top, cf.right, cf.bottom);
             int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
             if (outset > 0) {
@@ -5528,10 +5182,9 @@
                 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
                 + " dcf=" + dcf.toShortString()
                 + " sf=" + sf.toShortString()
-                + " osf=" + (osf == null ? "null" : osf.toShortString()));
+                + " osf=" + mWindowFrames.mOutsetFrame.toShortString());
 
-        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf, displayFrames.mDisplayCutout,
-                parentFrameWasClippedByDisplayCutout);
+        win.computeFrameLw(mWindowFrames);
         // Dock windows carve out the bottom of the screen, so normal windows
         // can't appear underneath them.
         if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
@@ -5690,7 +5343,7 @@
         }
 
         // Take note if a window wants to acquire a sleep token.
-        if (win.isVisibleLw() && (attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0
+        if ((attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0
                 && win.canAcquireSleepToken()) {
             mWindowSleepTokenNeeded = true;
         }
@@ -5746,20 +5399,21 @@
                 mStatusBarController.setShowTransparent(true /* transparent */);
             }
 
-            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
-            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
-                    && statusBarAttrs.width == MATCH_PARENT;
+            boolean statusBarForcesShowingNavigation
+                    = (mStatusBar.getAttrs().privateFlags
+                            & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
             boolean topAppHidesStatusBar = topAppHidesStatusBar();
             if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
-                    || statusBarExpanded) {
+                    || statusBarForcesShowingNavigation) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
                 if (mStatusBarController.setBarShowingLw(true)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT;
                 }
                 // Maintain fullscreen layout until incoming animation is complete.
                 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
-                // Transient status bar on the lockscreen is not allowed
-                if ((mForceStatusBarFromKeyguard || statusBarExpanded)
+                // Transient status bar is not allowed if status bar is on lockscreen or status bar
+                // is expecting the navigation keys from the user.
+                if ((mForceStatusBarFromKeyguard || statusBarForcesShowingNavigation)
                         && mStatusBarController.isTransientShowing()) {
                     mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
                             mLastSystemUiFlags, mLastSystemUiFlags);
@@ -5901,7 +5555,8 @@
     @Override
     public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
         mFocusedWindow = newFocus;
-        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
+        mLastFocusedWindow = lastFocus;
+        if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
             // If the navigation bar has been hidden or shown, we need to do another
             // layout pass to update that window.
             return FINISH_LAYOUT_REDO_LAYOUT;
@@ -5914,11 +5569,11 @@
     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
         // lid changed state
         final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
-        if (newLidState == mLidState) {
+        if (newLidState == mDefaultDisplayPolicy.getLidState()) {
             return;
         }
 
-        mLidState = newLidState;
+        mDefaultDisplayPolicy.setLidState(newLidState);
         applyLidSwitchState();
         updateRotation(true);
 
@@ -5953,17 +5608,6 @@
         mCameraLensCoverState = lensCoverState;
     }
 
-    void setHdmiPlugged(boolean plugged) {
-        if (mHdmiPlugged != plugged) {
-            mHdmiPlugged = plugged;
-            updateRotation(true, true);
-            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
-            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-        }
-    }
-
     void initializeHdmiState() {
         final int oldMask = StrictMode.allowThreadDiskReadsMask();
         try {
@@ -6003,8 +5647,7 @@
         }
         // This dance forces the code in setHdmiPlugged to run.
         // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
-        mHdmiPlugged = !plugged;
-        setHdmiPlugged(!mHdmiPlugged);
+        mDefaultDisplayPolicy.setHdmiPlugged(plugged, true /* force */);
     }
 
 
@@ -6395,7 +6038,8 @@
         }
 
         if (useHapticFeedback) {
-            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
+            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false,
+                    "Virtual Key - Press");
         }
 
         if (isWakeKey) {
@@ -6444,16 +6088,6 @@
     }
 
     /**
-     * Notify the StatusBar that system rotation suggestion has changed.
-     */
-    private void sendProposedRotationChangeToStatusBarInternal(int rotation, boolean isValid) {
-        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
-        if (statusBar != null) {
-            statusBar.onProposedRotationChanged(rotation, isValid);
-        }
-    }
-
-    /**
      * Returns true if the key can have global actions attached to it.
      * We reserve all power management keys for the system since they require
      * very careful handling.
@@ -6482,7 +6116,7 @@
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_DOWN:
             case KeyEvent.KEYCODE_VOLUME_MUTE:
-                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
+                return mDefaultDisplayPolicy.getDockMode() != Intent.EXTRA_DOCK_STATE_UNDOCKED;
 
             // ignore media and camera keys
             case KeyEvent.KEYCODE_MUTE:
@@ -6530,7 +6164,8 @@
     }
 
     private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
-        final boolean displayOff = (mDisplay == null || mDisplay.getState() == STATE_OFF);
+        final boolean displayOff = (mDefaultDisplay == null
+                || mDefaultDisplay.getState() == STATE_OFF);
 
         if (displayOff && !mHasFeatureWatch) {
             return false;
@@ -6680,8 +6315,8 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
-                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
-                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
+                mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+                        Intent.EXTRA_DOCK_STATE_UNDOCKED));
             } else {
                 try {
                     IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
@@ -6691,9 +6326,7 @@
                 }
             }
             updateRotation(true);
-            synchronized (mLock) {
-                updateOrientationListenerLp();
-            }
+            mDefaultDisplayRotation.updateOrientationListener();
         }
     };
 
@@ -6721,6 +6354,7 @@
                 // and then updates our own bookkeeping based on the now-
                 // current user.
                 mSettingsObserver.onChange(false);
+                mDefaultDisplayRotation.onUserSwitch();
 
                 // force a re-application of focused window sysui visibility.
                 // the window may never have been shown for this user
@@ -6794,15 +6428,16 @@
 
         mGoingToSleep = false;
         mRequestedOrGoingToSleep = false;
+        mDefaultDisplayPolicy.setAwake(false);
 
         // We must get this work done here because the power manager will drop
         // the wake lock and let the system suspend once this function returns.
         synchronized (mLock) {
-            mAwake = false;
             updateWakeGestureListenerLp();
-            updateOrientationListenerLp();
             updateLockScreenTimeout();
         }
+        mDefaultDisplayRotation.updateOrientationListener();
+
         if (mKeyguardDelegate != null) {
             mKeyguardDelegate.onFinishedGoingToSleep(why,
                     mCameraGestureTriggeredDuringGoingToSleep);
@@ -6816,17 +6451,17 @@
         EventLog.writeEvent(70000, 1);
         if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
 
+        mDefaultDisplayPolicy.setAwake(true);
+
         // Since goToSleep performs these functions synchronously, we must
         // do the same here.  We cannot post this work to a handler because
         // that might cause it to become reordered with respect to what
         // may happen in a future call to goToSleep.
         synchronized (mLock) {
-            mAwake = true;
-
             updateWakeGestureListenerLp();
-            updateOrientationListenerLp();
             updateLockScreenTimeout();
         }
+        mDefaultDisplayRotation.updateOrientationListener();
 
         if (mKeyguardDelegate != null) {
             mKeyguardDelegate.onStartedWakingUp();
@@ -6863,16 +6498,14 @@
     }
 
     private void finishKeyguardDrawn() {
-        synchronized (mLock) {
-            if (!mScreenOnEarly || mKeyguardDrawComplete) {
-                return; // We are not awake yet or we have already informed of this event.
-            }
+        if (!mDefaultDisplayPolicy.finishKeyguardDrawn()) {
+            return;
+        }
 
-            mKeyguardDrawComplete = true;
+        synchronized (mLock) {
             if (mKeyguardDelegate != null) {
                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
             }
-            mWindowManagerDrawComplete = false;
         }
 
         // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
@@ -6887,18 +6520,13 @@
         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
 
         updateScreenOffSleepToken(true);
+        mDefaultDisplayPolicy.screenTurnedOff();
         synchronized (mLock) {
-            mScreenOnEarly = false;
-            mScreenOnFully = false;
-            mKeyguardDrawComplete = false;
-            mWindowManagerDrawComplete = false;
-            mScreenOnListener = null;
-            updateOrientationListenerLp();
-
             if (mKeyguardDelegate != null) {
                 mKeyguardDelegate.onScreenTurnedOff();
             }
         }
+        mDefaultDisplayRotation.updateOrientationListener();
         reportScreenStateToVrManager(false);
     }
 
@@ -6915,13 +6543,9 @@
         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
 
         updateScreenOffSleepToken(false);
-        synchronized (mLock) {
-            mScreenOnEarly = true;
-            mScreenOnFully = false;
-            mKeyguardDrawComplete = false;
-            mWindowManagerDrawComplete = false;
-            mScreenOnListener = screenOnListener;
+        mDefaultDisplayPolicy.screenTurnedOn(screenOnListener);
 
+        synchronized (mLock) {
             if (mKeyguardDelegate != null && mKeyguardDelegate.hasKeyguard()) {
                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
                 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
@@ -6964,46 +6588,29 @@
     }
 
     private void finishWindowsDrawn() {
-        synchronized (mLock) {
-            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
-                return; // Screen is not turned on or we did already handle this case earlier.
-            }
-
-            mWindowManagerDrawComplete = true;
+        if (!mDefaultDisplayPolicy.finishWindowsDrawn()) {
+            return;
         }
 
         finishScreenTurningOn();
     }
 
     private void finishScreenTurningOn() {
-        synchronized (mLock) {
-            // We have just finished drawing screen content. Since the orientation listener
-            // gets only installed when all windows are drawn, we try to install it again.
-            updateOrientationListenerLp();
+        // We have just finished drawing screen content. Since the orientation listener
+        // gets only installed when all windows are drawn, we try to install it again.
+        mDefaultDisplayRotation.updateOrientationListener();
+
+        final ScreenOnListener listener = mDefaultDisplayPolicy.getScreenOnListener();
+        if (!mDefaultDisplayPolicy.finishScreenTurningOn()) {
+            return; // Spurious or not ready yet.
         }
-        final ScreenOnListener listener;
+
         final boolean enableScreen;
+        final boolean awake = mDefaultDisplayPolicy.isAwake();
         synchronized (mLock) {
-            if (DEBUG_WAKEUP) Slog.d(TAG,
-                    "finishScreenTurningOn: mAwake=" + mAwake
-                            + ", mScreenOnEarly=" + mScreenOnEarly
-                            + ", mScreenOnFully=" + mScreenOnFully
-                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
-                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
-
-            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
-                    || (mAwake && !mKeyguardDrawComplete)) {
-                return; // spurious or not ready yet
-            }
-
-            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
-            listener = mScreenOnListener;
-            mScreenOnListener = null;
-            mScreenOnFully = true;
-
             // Remember the first time we draw the keyguard so we know when we're done with
             // the main part of booting and can enable the screen and hide boot messages.
-            if (!mKeyguardDrawnOnce && mAwake) {
+            if (!mKeyguardDrawnOnce && awake) {
                 mKeyguardDrawnOnce = true;
                 enableScreen = true;
                 if (mBootMessageNeedsHiding) {
@@ -7044,14 +6651,12 @@
 
     @Override
     public boolean isScreenOn() {
-        synchronized (mLock) {
-            return mScreenOnEarly;
-        }
+        return mDefaultDisplayPolicy.isScreenOnEarly();
     }
 
     @Override
     public boolean okToAnimate() {
-        return mAwake && !mGoingToSleep;
+        return mDefaultDisplayPolicy.isAwake() && !mGoingToSleep;
     }
 
     /** {@inheritDoc} */
@@ -7161,7 +6766,7 @@
         outInsets.setEmpty();
 
         // Only navigation bar
-        if (mHasNavigationBar) {
+        if (mDefaultDisplayPolicy.hasNavigationBar()) {
             int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
             if (position == NAV_BAR_BOTTOM) {
                 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
@@ -7195,7 +6800,8 @@
     public boolean isDockSideAllowed(int dockSide, int originalDockSide, int displayWidth,
             int displayHeight, int displayRotation) {
         final int barPosition = navigationBarPosition(displayWidth, displayHeight, displayRotation);
-        return isDockSideAllowed(dockSide, originalDockSide, barPosition, mNavigationBarCanMove);
+        return isDockSideAllowed(dockSide, originalDockSide, barPosition,
+                mDefaultDisplayPolicy.navigationBarCanMove());
     }
 
     @VisibleForTesting
@@ -7232,293 +6838,6 @@
     }
 
     @Override
-    public int rotationForOrientationLw(int orientation, int lastRotation, boolean defaultDisplay) {
-        if (false) {
-            Slog.v(TAG, "rotationForOrientationLw(orient="
-                        + orientation + ", last=" + lastRotation
-                        + "); user=" + mUserRotation + " "
-                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
-                            ? "USER_ROTATION_LOCKED" : "")
-                        );
-        }
-
-        if (mForceDefaultOrientation) {
-            return Surface.ROTATION_0;
-        }
-
-        synchronized (mLock) {
-            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
-            if (sensorRotation < 0) {
-                sensorRotation = lastRotation;
-            }
-
-            final int preferredRotation;
-            if (!defaultDisplay) {
-                // For secondary displays we ignore things like displays sensors, docking mode and
-                // rotation lock, and always prefer a default rotation.
-                preferredRotation = Surface.ROTATION_0;
-            } else if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
-                // Ignore sensor when lid switch is open and rotation is forced.
-                preferredRotation = mLidOpenRotation;
-            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
-                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
-                // Ignore sensor when in car dock unless explicitly enabled.
-                // This case can override the behavior of NOSENSOR, and can also
-                // enable 180 degree rotation while docked.
-                preferredRotation = mCarDockEnablesAccelerometer
-                        ? sensorRotation : mCarDockRotation;
-            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
-                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
-                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
-                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
-                // Ignore sensor when in desk dock unless explicitly enabled.
-                // This case can override the behavior of NOSENSOR, and can also
-                // enable 180 degree rotation while docked.
-                preferredRotation = mDeskDockEnablesAccelerometer
-                        ? sensorRotation : mDeskDockRotation;
-            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
-                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
-                // Note that the dock orientation overrides the HDMI orientation.
-                preferredRotation = mDemoHdmiRotation;
-            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
-                    && mUndockedHdmiRotation >= 0) {
-                // Ignore sensor when plugged into HDMI and an undocked orientation has
-                // been specified in the configuration (only for legacy devices without
-                // full multi-display support).
-                // Note that the dock orientation overrides the HDMI orientation.
-                preferredRotation = mUndockedHdmiRotation;
-            } else if (mDemoRotationLock) {
-                // Ignore sensor when demo rotation lock is enabled.
-                // Note that the dock orientation and HDMI rotation lock override this.
-                preferredRotation = mDemoRotation;
-            } else if (mPersistentVrModeEnabled) {
-                // While in VR, apps always prefer a portrait rotation. This does not change
-                // any apps that explicitly set landscape, but does cause sensors be ignored,
-                // and ignored any orientation lock that the user has set (this conditional
-                // should remain above the ORIENTATION_LOCKED conditional below).
-                preferredRotation = mPortraitRotation;
-            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
-                // Application just wants to remain locked in the last rotation.
-                preferredRotation = lastRotation;
-            } else if (!mSupportAutoRotation) {
-                // If we don't support auto-rotation then bail out here and ignore
-                // the sensor and any rotation lock settings.
-                preferredRotation = -1;
-            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
-                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
-                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
-                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
-                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
-                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
-                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
-                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
-                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
-                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
-                // Otherwise, use sensor only if requested by the application or enabled
-                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
-                if (mAllowAllRotations < 0) {
-                    // Can't read this during init() because the context doesn't
-                    // have display metrics at that time so we cannot determine
-                    // tablet vs. phone then.
-                    mAllowAllRotations = mContext.getResources().getBoolean(
-                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
-                }
-                if (sensorRotation != Surface.ROTATION_180
-                        || mAllowAllRotations == 1
-                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
-                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
-                    preferredRotation = sensorRotation;
-                } else {
-                    preferredRotation = lastRotation;
-                }
-            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
-                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
-                // Apply rotation lock.  Does not apply to NOSENSOR.
-                // The idea is that the user rotation expresses a weak preference for the direction
-                // of gravity and as NOSENSOR is never affected by gravity, then neither should
-                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
-                preferredRotation = mUserRotation;
-            } else {
-                // No overriding preference.
-                // We will do exactly what the application asked us to do.
-                preferredRotation = -1;
-            }
-
-            switch (orientation) {
-                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
-                    // Return portrait unless overridden.
-                    if (isAnyPortrait(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    return mPortraitRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
-                    // Return landscape unless overridden.
-                    if (isLandscapeOrSeascape(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    return mLandscapeRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
-                    // Return reverse portrait unless overridden.
-                    if (isAnyPortrait(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    return mUpsideDownRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
-                    // Return seascape unless overridden.
-                    if (isLandscapeOrSeascape(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    return mSeascapeRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
-                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
-                    // Return either landscape rotation.
-                    if (isLandscapeOrSeascape(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    if (isLandscapeOrSeascape(lastRotation)) {
-                        return lastRotation;
-                    }
-                    return mLandscapeRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
-                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
-                    // Return either portrait rotation.
-                    if (isAnyPortrait(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    if (isAnyPortrait(lastRotation)) {
-                        return lastRotation;
-                    }
-                    return mPortraitRotation;
-
-                default:
-                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
-                    // just return the preferred orientation we already calculated.
-                    if (preferredRotation >= 0) {
-                        return preferredRotation;
-                    }
-                    return Surface.ROTATION_0;
-            }
-        }
-    }
-
-    @Override
-    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
-        switch (orientation) {
-            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
-            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
-            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
-                return isAnyPortrait(rotation);
-
-            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
-            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
-            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
-                return isLandscapeOrSeascape(rotation);
-
-            default:
-                return true;
-        }
-    }
-
-    @Override
-    public void setRotationLw(int rotation) {
-        mOrientationListener.setCurrentRotation(rotation);
-    }
-
-    public boolean isRotationChoicePossible(int orientation) {
-        // Rotation choice is only shown when the user is in locked mode.
-        if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
-
-        // We should only enable rotation choice if the rotation isn't forced by the lid, dock,
-        // demo, hdmi, vr, etc mode
-
-        // Determine if the rotation is currently forced
-        if (mForceDefaultOrientation) {
-            return false; // Rotation is forced to default orientation
-
-        } else if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
-            return false; // Rotation is forced mLidOpenRotation
-
-        } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && !mCarDockEnablesAccelerometer) {
-            return false; // Rotation forced to mCarDockRotation
-
-        } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
-                || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
-                || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
-                && !mDeskDockEnablesAccelerometer) {
-            return false; // Rotation forced to mDeskDockRotation
-
-        } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
-            return false; // Rotation forced to mDemoHdmiRotation
-
-        } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
-                && mUndockedHdmiRotation >= 0) {
-            return false; // Rotation forced to mUndockedHdmiRotation
-
-        } else if (mDemoRotationLock) {
-            return false; // Rotation forced to mDemoRotation
-
-        } else if (mPersistentVrModeEnabled) {
-            return false; // Rotation forced to mPortraitRotation
-
-        } else if (!mSupportAutoRotation) {
-            return false;
-        }
-
-        // Ensure that some rotation choice is possible for the given orientation
-        switch (orientation) {
-            case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
-            case ActivityInfo.SCREEN_ORIENTATION_USER:
-            case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
-            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
-            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
-                // NOSENSOR description is ambiguous, in reality WM ignores user choice
-                return true;
-        }
-
-        // Rotation is forced, should be controlled by system
-        return false;
-    }
-
-    public boolean isValidRotationChoice(int orientation, final int preferredRotation) {
-        // Determine if the given app orientation is compatible with the provided rotation choice
-        switch (orientation) {
-            case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
-                // Works with any of the 4 rotations
-                return preferredRotation >= 0;
-
-            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
-                // It's possible for the user pref to be set at 180 because of FULL_USER. This would
-                // make switching to USER_PORTRAIT appear at 180. Provide choice to back to portrait
-                // but never to go to 180.
-                return preferredRotation == mPortraitRotation;
-
-            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
-                // Works landscape or seascape
-                return isLandscapeOrSeascape(preferredRotation);
-
-            case ActivityInfo.SCREEN_ORIENTATION_USER:
-            case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
-                // Works with any rotation except upside down
-                return (preferredRotation >= 0) && (preferredRotation != mUpsideDownRotation);
-        }
-
-        return false;
-    }
-
-    private boolean isLandscapeOrSeascape(int rotation) {
-        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
-    }
-
-    private boolean isAnyPortrait(int rotation) {
-        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
-    }
-
-    @Override
     public int getUserRotationMode() {
         return Settings.System.getIntForUser(mContext.getContentResolver(),
                 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
@@ -7553,7 +6872,8 @@
     public void setSafeMode(boolean safeMode) {
         mSafeMode = safeMode;
         if (safeMode) {
-            performHapticFeedbackLw(null, HapticFeedbackConstants.SAFE_MODE_ENABLED, true);
+            performHapticFeedbackLw(null, HapticFeedbackConstants.SAFE_MODE_ENABLED, true,
+                    "Safe Mode Enabled");
         }
     }
 
@@ -7590,8 +6910,8 @@
 
         readCameraLensCoverState();
         updateUiMode();
+        mDefaultDisplayRotation.updateOrientationListener();
         synchronized (mLock) {
-            updateOrientationListenerLp();
             mSystemReady = true;
             mHandler.post(new Runnable() {
                 @Override
@@ -7629,9 +6949,7 @@
 
     @Override
     public boolean canDismissBootAnimation() {
-        synchronized (mLock) {
-            return mKeyguardDrawComplete;
-        }
+        return mDefaultDisplayPolicy.isKeyguardDrawComplete();
     }
 
     ProgressDialog mBootMsgDialog = null;
@@ -7731,7 +7049,7 @@
             }
         }
 
-        if (mAwake && mNotifyUserActivity) {
+        if (mDefaultDisplayPolicy.isAwake() && mNotifyUserActivity) {
             mHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
                     USER_ACTIVITY_NOTIFICATION_DELAY);
             mNotifyUserActivity = false;
@@ -7774,7 +7092,7 @@
 
     private void updateLockScreenTimeout() {
         synchronized (mScreenLockTimeout) {
-            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
+            final boolean enable = (mAllowLockscreenWhenOn && mDefaultDisplayPolicy.isAwake() &&
                     mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
             if (mLockScreenTimerActive != enable) {
                 if (enable) {
@@ -7829,10 +7147,11 @@
     }
 
     private void applyLidSwitchState() {
-        if (mLidState == LID_CLOSED && mLidControlsSleep) {
+        final int lidState = mDefaultDisplayPolicy.getLidState();
+        if (lidState == LID_CLOSED && mLidControlsSleep) {
             goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
                     PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
-        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
+        } else if (lidState == LID_CLOSED && mLidControlsScreenLock) {
             mWindowManagerFuncs.lockDeviceNow();
         }
 
@@ -7854,17 +7173,8 @@
 
     void updateRotation(boolean alwaysSendConfiguration) {
         try {
-            //set orientation on WindowManager
-            mWindowManager.updateRotation(alwaysSendConfiguration, false);
-        } catch (RemoteException e) {
-            // Ignore
-        }
-    }
-
-    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
-        try {
-            //set orientation on WindowManager
-            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
+            // Set orientation on WindowManager.
+            mWindowManager.updateRotation(alwaysSendConfiguration, false /* forceRelayout */);
         } catch (RemoteException e) {
             // Ignore
         }
@@ -7897,12 +7207,14 @@
             if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
                 intent = mDeskDockIntent;
             }
-        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
-                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
-                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
-                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
-            // Always launch dock home from home when watch is docked, if it exists.
-            intent = mDeskDockIntent;
+        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH) {
+            final int dockMode = mDefaultDisplayPolicy.getDockMode();
+            if (dockMode == Intent.EXTRA_DOCK_STATE_DESK
+                    || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
+                    || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK) {
+                // Always launch dock home from home when watch is docked, if it exists.
+                intent = mDeskDockIntent;
+            }
         } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
             if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
                 intent = mVrHeadsetHomeIntent;
@@ -8017,23 +7329,14 @@
         return true;
     }
 
-    @Override
-    public void setCurrentOrientationLw(int newOrientation) {
-        synchronized (mLock) {
-            if (newOrientation != mCurrentAppOrientation) {
-                mCurrentAppOrientation = newOrientation;
-                updateOrientationListenerLp();
-            }
-        }
-    }
-
     private boolean isTheaterModeEnabled() {
         return Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.THEATER_MODE_ON, 0) == 1;
     }
 
     @Override
-    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
+    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always,
+            String reason) {
         if (!mVibrator.hasVibrator()) {
             return false;
         }
@@ -8057,7 +7360,7 @@
             owningUid = android.os.Process.myUid();
             owningPackage = mContext.getOpPackageName();
         }
-        mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
+        mVibrator.vibrate(owningUid, owningPackage, effect, reason, VIBRATION_ATTRIBUTES);
         return true;
     }
 
@@ -8127,10 +7430,19 @@
         if (winCandidate == null) {
             return 0;
         }
+
+        // The immersive mode confirmation should never affect the system bar visibility, otherwise
+        // it will unhide the navigation bar and hide itself.
         if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
-            // The immersive mode confirmation should never affect the system bar visibility,
-            // otherwise it will unhide the navigation bar and hide itself.
-            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
+
+            // The immersive mode confirmation took the focus from mLastFocusedWindow which was
+            // controlling the system ui visibility. So if mLastFocusedWindow can still receive
+            // keys, we let it keep controlling the visibility.
+            final boolean lastFocusCanReceiveKeys =
+                    (mLastFocusedWindow != null && mLastFocusedWindow.canReceiveKeys());
+            winCandidate = isStatusBarKeyguard() ? mStatusBar
+                    : lastFocusCanReceiveKeys ? mLastFocusedWindow
+                    : mTopFullscreenOpaqueWindowState;
             if (winCandidate == null) {
                 return 0;
             }
@@ -8344,7 +7656,8 @@
         final long now = SystemClock.uptimeMillis();
         final boolean pendingPanic = mPendingPanicGestureUptime != 0
                 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
-        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
+        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard()
+                && mDefaultDisplayPolicy.isKeyguardDrawComplete()) {
             // The user performed the panic gesture recently, we're about to hide the bars,
             // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
             mPendingPanicGestureUptime = 0;
@@ -8487,7 +7800,7 @@
     // overridden by qemu.hw.mainkeys in the emulator.
     @Override
     public boolean hasNavigationBar() {
-        return mHasNavigationBar;
+        return mDefaultDisplayPolicy.hasNavigationBar();
     }
 
     @Override
@@ -8532,19 +7845,21 @@
     }
 
     @Override
-    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
+    public boolean shouldRotateSeamlessly(DisplayRotation displayRotation, int oldRotation,
+            int newRotation) {
         // For the upside down rotation we don't rotate seamlessly as the navigation
         // bar moves position.
         // Note most apps (using orientation:sensor or user as opposed to fullSensor)
         // will not enter the reverse portrait orientation, so actually the
         // orientation won't change at all.
-        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
+        if (oldRotation == displayRotation.getUpsideDownRotation()
+                || newRotation == displayRotation.getUpsideDownRotation()) {
             return false;
         }
         // If the navigation bar can't change sides, then it will
         // jump when we change orientations and we don't rotate
         // seamlessly.
-        if (!mNavigationBarCanMove) {
+        if (!displayRotation.getDisplayPolicy().navigationBarCanMove()) {
             return false;
         }
         int delta = newRotation - oldRotation;
@@ -8578,12 +7893,13 @@
     public void writeToProto(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         proto.write(LAST_SYSTEM_UI_FLAGS, mLastSystemUiFlags);
-        proto.write(ROTATION_MODE, mUserRotationMode);
-        proto.write(ROTATION, mUserRotation);
-        proto.write(ORIENTATION, mCurrentAppOrientation);
-        proto.write(SCREEN_ON_FULLY, mScreenOnFully);
-        proto.write(KEYGUARD_DRAW_COMPLETE, mKeyguardDrawComplete);
-        proto.write(WINDOW_MANAGER_DRAW_COMPLETE, mWindowManagerDrawComplete);
+        proto.write(ROTATION_MODE, mDefaultDisplayRotation.getUserRotationMode());
+        proto.write(ROTATION, mDefaultDisplayRotation.getUserRotation());
+        proto.write(ORIENTATION, mDefaultDisplayRotation.getCurrentAppOrientation());
+        proto.write(SCREEN_ON_FULLY, mDefaultDisplayPolicy.isScreenOnFully());
+        proto.write(KEYGUARD_DRAW_COMPLETE, mDefaultDisplayPolicy.isKeyguardDrawComplete());
+        proto.write(WINDOW_MANAGER_DRAW_COMPLETE,
+                mDefaultDisplayPolicy.isWindowManagerDrawComplete());
         if (mFocusedApp != null) {
             proto.write(FOCUSED_APP_TOKEN, mFocusedApp.toString());
         }
@@ -8605,8 +7921,8 @@
         proto.write(FORCE_STATUS_BAR_FROM_KEYGUARD, mForceStatusBarFromKeyguard);
         mStatusBarController.writeToProto(proto, STATUS_BAR);
         mNavigationBarController.writeToProto(proto, NAVIGATION_BAR);
-        if (mOrientationListener != null) {
-            mOrientationListener.writeToProto(proto, ORIENTATION_LISTENER);
+        if (mDefaultOrientationListener != null) {
+            mDefaultOrientationListener.writeToProto(proto, ORIENTATION_LISTENER);
         }
         if (mKeyguardDelegate != null) {
             mKeyguardDelegate.writeToProto(proto, KEYGUARD_DELEGATE);
@@ -8619,13 +7935,8 @@
         pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
                 pw.print(" mSystemReady="); pw.print(mSystemReady);
                 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
-        pw.print(prefix); pw.print("mLidState=");
-                pw.print(WindowManagerFuncs.lidStateToString(mLidState));
-                pw.print(" mLidOpenRotation=");
-                pw.println(Surface.rotationToString(mLidOpenRotation));
         pw.print(prefix); pw.print("mCameraLensCoverState=");
-                pw.print(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState));
-                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
+                pw.println(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState));
         if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
                 || mForceClearedSystemUiFlags != 0) {
             pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
@@ -8643,27 +7954,9 @@
                 pw.println(mWakeGestureEnabledSetting);
 
         pw.print(prefix);
-                pw.print("mSupportAutoRotation="); pw.print(mSupportAutoRotation);
-                pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled);
-        pw.print(prefix); pw.print("mUiMode="); pw.print(Configuration.uiModeToString(mUiMode));
-                pw.print(" mDockMode="); pw.println(Intent.dockStateToString(mDockMode));
-        pw.print(prefix); pw.print("mEnableCarDockHomeCapture=");
-                pw.print(mEnableCarDockHomeCapture);
-                pw.print(" mCarDockRotation=");
-                pw.print(Surface.rotationToString(mCarDockRotation));
-                pw.print(" mDeskDockRotation=");
-                pw.println(Surface.rotationToString(mDeskDockRotation));
-        pw.print(prefix); pw.print("mUserRotationMode=");
-                pw.print(WindowManagerPolicy.userRotationModeToString(mUserRotationMode));
-                pw.print(" mUserRotation="); pw.print(Surface.rotationToString(mUserRotation));
-                pw.print(" mAllowAllRotations=");
-                pw.println(allowAllRotationsToString(mAllowAllRotations));
-        pw.print(prefix); pw.print("mCurrentAppOrientation=");
-                pw.println(ActivityInfo.screenOrientationToString(mCurrentAppOrientation));
-        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
-                pw.print(mCarDockEnablesAccelerometer);
-                pw.print(" mDeskDockEnablesAccelerometer=");
-                pw.println(mDeskDockEnablesAccelerometer);
+                pw.print("mUiMode=");
+                pw.print(Configuration.uiModeToString(mUiMode));
+                pw.print("mEnableCarDockHomeCapture="); pw.println(mEnableCarDockHomeCapture);
         pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
                 pw.print(mLidKeyboardAccessibility);
                 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
@@ -8713,12 +8006,6 @@
                 pw.print(" mEndcallBehavior=");
                 pw.println(endcallBehaviorToString(mEndcallBehavior));
         pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
-        pw.print(prefix);
-                pw.print("mAwake="); pw.print(mAwake);
-                pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
-                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
-        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
-                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
         pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
                 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
         pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
@@ -8773,19 +8060,6 @@
         pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
                 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
                 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
-        pw.print(prefix); pw.print("mLandscapeRotation=");
-                pw.print(Surface.rotationToString(mLandscapeRotation));
-                pw.print(" mSeascapeRotation=");
-                pw.println(Surface.rotationToString(mSeascapeRotation));
-        pw.print(prefix); pw.print("mPortraitRotation=");
-                pw.print(Surface.rotationToString(mPortraitRotation));
-                pw.print(" mUpsideDownRotation=");
-                pw.println(Surface.rotationToString(mUpsideDownRotation));
-        pw.print(prefix); pw.print("mDemoHdmiRotation=");
-                pw.print(Surface.rotationToString(mDemoHdmiRotation));
-                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
-        pw.print(prefix); pw.print("mUndockedHdmiRotation=");
-                pw.println(Surface.rotationToString(mUndockedHdmiRotation));
         if (mHasFeatureLeanback) {
             pw.print(prefix);
             pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
@@ -8803,8 +8077,8 @@
         if (mWakeGestureListener != null) {
             mWakeGestureListener.dump(pw, prefix);
         }
-        if (mOrientationListener != null) {
-            mOrientationListener.dump(pw, prefix);
+        if (mDefaultOrientationListener != null) {
+            mDefaultOrientationListener.dump(pw, prefix);
         }
         if (mBurnInProtectionHelper != null) {
             mBurnInProtectionHelper.dump(prefix, pw);
@@ -8817,19 +8091,6 @@
         mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + "  ");
     }
 
-    private static String allowAllRotationsToString(int allowAll) {
-        switch (allowAll) {
-            case -1:
-                return "unknown";
-            case 0:
-                return "false";
-            case 1:
-                return "true";
-            default:
-                return Integer.toString(allowAll);
-        }
-    }
-
     private static String endcallBehaviorToString(int behavior) {
         StringBuilder sb = new StringBuilder();
         if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0 ) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 9fbe419..b55adeb 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -71,7 +71,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -94,6 +93,8 @@
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
 import com.android.server.wm.DisplayFrames;
+import com.android.server.wm.DisplayRotation;
+import com.android.server.wm.WindowFrames;
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import java.io.PrintWriter;
@@ -157,6 +158,8 @@
     int FINISH_LAYOUT_REDO_WALLPAPER = 0x0004;
     /** Need to recompute animations */
     int FINISH_LAYOUT_REDO_ANIM = 0x0008;
+    /** Layer for the screen off animation */
+    int COLOR_FADE_LAYER = 0x40000001;
 
     /**
      * Register shortcuts for window manager to dispatch.
@@ -175,7 +178,7 @@
     /**
      * Called when the resource overlays change.
      */
-    default void onOverlayChangedLw() {}
+    default void onOverlayChangedLw(DisplayContentInfo displayContentInfo) {}
 
     /**
      * Interface to the Window Manager state associated with a particular
@@ -198,35 +201,10 @@
          * getFrame() if so desired.  Must be called with the window manager
          * lock held.
          *
-         * @param parentFrame The frame of the parent container this window
-         * is in, used for computing its basic position.
-         * @param displayFrame The frame of the overall display in which this
-         * window can appear, used for constraining the overall dimensions
-         * of the window.
-         * @param overlayFrame The frame within the display that is inside
-         * of the overlay region.
-         * @param contentFrame The frame within the display in which we would
-         * like active content to appear.  This will cause windows behind to
-         * be resized to match the given content frame.
-         * @param visibleFrame The frame within the display that the window
-         * is actually visible, used for computing its visible insets to be
-         * given to windows behind.
-         * This can be used as a hint for scrolling (avoiding resizing)
-         * the window to make certain that parts of its content
-         * are visible.
-         * @param decorFrame The decor frame specified by policy specific to this window,
-         * to use for proper cropping during animation.
-         * @param stableFrame The frame around which stable system decoration is positioned.
-         * @param outsetFrame The frame that includes areas that aren't part of the surface but we
-         * want to treat them as such.
-         * @param displayCutout the display cutout
-         * @param parentFrameWasClippedByDisplayCutout true if the parent frame would have been
-         * different if there was no display cutout.
+         * @param windowFrames Container for all the window frames that affect how the window is
+         *                     laid out.
          */
-        public void computeFrameLw(Rect parentFrame, Rect displayFrame,
-                Rect overlayFrame, Rect contentFrame, Rect visibleFrame, Rect decorFrame,
-                Rect stableFrame, @Nullable Rect outsetFrame, WmDisplayCutout displayCutout,
-                boolean parentFrameWasClippedByDisplayCutout);
+        public void computeFrameLw(WindowFrames windowFrames);
 
         /**
          * Retrieve the current frame of the window that has been assigned by
@@ -492,6 +470,9 @@
          */
         boolean canAcquireSleepToken();
 
+        /** @return true if this window desires key events. */
+        boolean canReceiveKeys();
+
         /**
          * Writes {@link com.android.server.wm.IdentifierProto} to stream.
          */
@@ -545,7 +526,7 @@
          * Add a input consumer which will consume all input events going to any window below it.
          */
         public InputConsumer createInputConsumer(Looper looper, String name,
-                InputEventReceiver.Factory inputEventReceiverFactory);
+                InputEventReceiver.Factory inputEventReceiverFactory, int displayId);
 
         /**
          * Returns a code that describes the current state of the lid switch.
@@ -658,6 +639,27 @@
          * The keyguard showing state has changed
          */
         void onKeyguardShowingAndNotOccludedChanged();
+
+        DisplayContentInfo getDefaultDisplayContentInfo();
+    }
+
+    /**
+     * Provides the rotation of a device.
+     *
+     * @see com.android.server.policy.WindowOrientationListener
+     */
+    public interface RotationSource {
+        int getProposedRotation();
+
+        void setCurrentRotation(int rotation);
+    }
+
+    /**
+     * Interface to get public information of a display content.
+     */
+    public interface DisplayContentInfo {
+        DisplayRotation getDisplayRotation();
+        Display getDisplay();
     }
 
     /** Window has been added to the screen. */
@@ -689,6 +691,11 @@
     public final int USER_ROTATION_LOCKED = 1;
 
     /**
+     * Set the default display content to provide basic functions for the policy.
+     */
+    public void setDefaultDisplay(DisplayContentInfo displayContentInfo);
+
+    /**
      * Perform initialization of the policy.
      *
      * @param context The system context we are running in.
@@ -697,17 +704,6 @@
             WindowManagerFuncs windowManagerFuncs);
 
     /**
-     * @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true.
-     */
-    public boolean isDefaultOrientationForced();
-
-    /**
-     * Called by window manager once it has the initial, default native
-     * display dimensions.
-     */
-    public void setInitialDisplaySize(Display display, int width, int height, int density);
-
-    /**
      * Check permissions when adding a window.
      *
      * @param attrs The window's LayoutParams.
@@ -1180,6 +1176,7 @@
      * @param taskBounds The bounds of the task this window is on or {@code null} if no task is
      *                   associated with the window.
      * @param displayFrames display frames.
+     * @param floatingStack Whether the window's stack is floating.
      * @param outFrame The frame of the window.
      * @param outContentInsets The areas covered by system windows, expressed as positive insets.
      * @param outStableInsets The areas covered by stable system windows irrespective of their
@@ -1190,8 +1187,8 @@
      *         See {@link #isNavBarForcedShownLw(WindowState)}.
      */
     default boolean getLayoutHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
-            DisplayFrames displayFrames, Rect outFrame, Rect outContentInsets,
-            Rect outStableInsets, Rect outOutsets,
+            DisplayFrames displayFrames, boolean floatingStack,
+            Rect outFrame, Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout) {
         return false;
     }
@@ -1429,44 +1426,6 @@
     public boolean isShowingDreamLw();
 
     /**
-     * Given an orientation constant, returns the appropriate surface rotation,
-     * taking into account sensors, docking mode, rotation lock, and other factors.
-     *
-     * @param orientation An orientation constant, such as
-     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
-     * @param lastRotation The most recently used rotation.
-     * @param defaultDisplay Flag indicating whether the rotation is computed for the default
-     *                       display. Currently for all non-default displays sensors, docking mode,
-     *                       rotation lock and other factors are ignored.
-     * @return The surface rotation to use.
-     */
-    public int rotationForOrientationLw(@ActivityInfo.ScreenOrientation int orientation,
-            int lastRotation, boolean defaultDisplay);
-
-    /**
-     * Given an orientation constant and a rotation, returns true if the rotation
-     * has compatible metrics to the requested orientation.  For example, if
-     * the application requested landscape and got seascape, then the rotation
-     * has compatible metrics; if the application requested portrait and got landscape,
-     * then the rotation has incompatible metrics; if the application did not specify
-     * a preference, then anything goes.
-     *
-     * @param orientation An orientation constant, such as
-     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
-     * @param rotation The rotation to check.
-     * @return True if the rotation is compatible with the requested orientation.
-     */
-    public boolean rotationHasCompatibleMetricsLw(@ActivityInfo.ScreenOrientation int orientation,
-            int rotation);
-
-    /**
-     * Called by the window manager when the rotation changes.
-     *
-     * @param rotation The new rotation.
-     */
-    public void setRotationLw(int rotation);
-
-    /**
      * Called when the system is mostly done booting to set whether
      * the system should go into safe mode.
      */
@@ -1506,12 +1465,11 @@
      */
     public void enableScreenAfterBoot();
 
-    public void setCurrentOrientationLw(@ActivityInfo.ScreenOrientation int newOrientation);
-
     /**
      * Call from application to perform haptic feedback on its window.
      */
-    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always);
+    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always,
+            String reason);
 
     /**
      * Called when we have started keeping the screen on because a window
@@ -1721,9 +1679,10 @@
     /**
      * Called when the configuration has changed, and it's safe to load new values from resources.
      */
-    public void onConfigurationChanged();
+    public void onConfigurationChanged(DisplayContentInfo displayContentInfo);
 
-    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation);
+    public boolean shouldRotateSeamlessly(DisplayRotation displayRotation,
+            int oldRotation, int newRotation);
 
     /**
      * Called when System UI has been started.
@@ -1752,8 +1711,8 @@
     }
 
     /**
-     * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
-     * on the next user activity.
+     * Requests that the WindowManager sends
+     * WindowManagerPolicyConstants#ACTION_USER_ACTIVITY_NOTIFICATION on the next user activity.
      */
     public void requestUserActivityNotification();
 
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index 1508c9e..d5adb5e 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -204,6 +204,10 @@
         }
     }
 
+    public Handler getHandler() {
+        return mHandler;
+    }
+
     /**
      * Sets the current rotation.
      *
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index d445611..b4dafc9 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -585,9 +585,9 @@
     }
 
     /**
-     * Called when wireless charging has started so as to provide user feedback (sound and visual).
+     * Called when wireless charging has started - to provide user feedback (sound and visual).
      */
-    public void onWirelessChargingStarted(int batteryLevel) {
+    public void onWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
         if (DEBUG) {
             Slog.d(TAG, "onWirelessChargingStarted");
         }
@@ -596,13 +596,14 @@
         Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
         msg.setAsynchronous(true);
         msg.arg1 = batteryLevel;
+        msg.arg2 = userId;
         mHandler.sendMessage(msg);
     }
 
     /**
-     * Called when wired charging has started so as to provide user feedback
+     * Called when wired charging has started - to provide user feedback
      */
-    public void onWiredChargingStarted() {
+    public void onWiredChargingStarted(@UserIdInt int userId) {
         if (DEBUG) {
             Slog.d(TAG, "onWiredChargingStarted");
         }
@@ -610,6 +611,7 @@
         mSuspendBlocker.acquire();
         Message msg = mHandler.obtainMessage(MSG_WIRED_CHARGING_STARTED);
         msg.setAsynchronous(true);
+        msg.arg1 = userId;
         mHandler.sendMessage(msg);
     }
 
@@ -748,10 +750,10 @@
     /**
      * Plays the wireless charging sound for both wireless and non-wireless charging
      */
-    private void playChargingStartedSound() {
+    private void playChargingStartedSound(@UserIdInt int userId) {
         final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
                 Settings.Global.CHARGING_STARTED_SOUND);
-        if (isChargingFeedbackEnabled() && soundPath != null) {
+        if (isChargingFeedbackEnabled(userId) && soundPath != null) {
             final Uri soundUri = Uri.parse("file://" + soundPath);
             if (soundUri != null) {
                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
@@ -763,17 +765,17 @@
         }
     }
 
-    private void showWirelessChargingStarted(int batteryLevel) {
-        playWirelessChargingVibration();
-        playChargingStartedSound();
+    private void showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
+        playWirelessChargingVibration(userId);
+        playChargingStartedSound(userId);
         if (mStatusBarManagerInternal != null) {
             mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
         }
         mSuspendBlocker.release();
     }
 
-    private void showWiredChargingStarted() {
-        playChargingStartedSound();
+    private void showWiredChargingStarted(@UserIdInt int userId) {
+        playChargingStartedSound(userId);
         mSuspendBlocker.release();
     }
 
@@ -781,17 +783,17 @@
         mTrustManager.setDeviceLockedForUser(userId, true /*locked*/);
     }
 
-    private void playWirelessChargingVibration() {
-        final boolean vibrateEnabled = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.CHARGING_VIBRATION_ENABLED, 0) != 0;
-        if (vibrateEnabled && isChargingFeedbackEnabled()) {
+    private void playWirelessChargingVibration(@UserIdInt int userId) {
+        final boolean vibrateEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
+        if (vibrateEnabled && isChargingFeedbackEnabled(userId)) {
             mVibrator.vibrate(WIRELESS_CHARGING_VIBRATION_EFFECT, VIBRATION_ATTRIBUTES);
         }
     }
 
-    private boolean isChargingFeedbackEnabled() {
-        final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
+    private boolean isChargingFeedbackEnabled(@UserIdInt int userId) {
+        final boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.CHARGING_SOUNDS_ENABLED, 1, userId) != 0;
         final boolean dndOff = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
                 == Settings.Global.ZEN_MODE_OFF;
@@ -813,7 +815,7 @@
                     sendNextBroadcast();
                     break;
                 case MSG_WIRELESS_CHARGING_STARTED:
-                    showWirelessChargingStarted(msg.arg1);
+                    showWirelessChargingStarted(msg.arg1, msg.arg2);
                     break;
                 case MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED:
                     sendBrightnessBoostChangedBroadcast();
@@ -822,7 +824,7 @@
                     lockProfile(msg.arg1);
                     break;
                 case MSG_WIRED_CHARGING_STARTED:
-                    showWiredChargingStarted();
+                    showWiredChargingStarted(msg.arg1);
                     break;
             }
         }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9468dd7..91d4717 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -288,6 +288,9 @@
     private long mLastWakeTime;
     private long mLastSleepTime;
 
+    // Last reason the device went to sleep.
+    private int mLastSleepReason;
+
     // Timestamp of the last call to user activity.
     private long mLastUserActivityTime;
     private long mLastUserActivityTimeNoChangeLights;
@@ -1433,6 +1436,7 @@
             }
 
             mLastSleepTime = eventTime;
+            mLastSleepReason = reason;
             mSandmanSummoned = true;
             setWakefulnessLocked(WAKEFULNESS_DOZING, reason);
 
@@ -1705,9 +1709,9 @@
                 if (mBootCompleted) {
                     if (mIsPowered && !BatteryManager.isPlugWired(oldPlugType)
                             && BatteryManager.isPlugWired(mPlugType)) {
-                        mNotifier.onWiredChargingStarted();
+                        mNotifier.onWiredChargingStarted(mForegroundProfile);
                     } else if (dockedOnWirelessCharger) {
-                        mNotifier.onWirelessChargingStarted(mBatteryLevel);
+                        mNotifier.onWirelessChargingStarted(mBatteryLevel, mForegroundProfile);
                     }
                 }
             }
@@ -3266,6 +3270,7 @@
             pw.println("  mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
             pw.println("  mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
             pw.println("  mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
+            pw.println("  mLastSleepReason=" + PowerManager.sleepReasonToString(mLastSleepReason));
             pw.println("  mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
             pw.println("  mLastUserActivityTimeNoChangeLights="
                     + TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights));
@@ -4404,6 +4409,19 @@
             }
         }
 
+        @Override // Binder call
+        public int getLastSleepReason() {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return getLastSleepReasonInternal();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         /**
          * Reboots the device.
          *
@@ -4619,6 +4637,12 @@
         }
     }
 
+    private int getLastSleepReasonInternal() {
+        synchronized (mLock) {
+            return mLastSleepReason;
+        }
+    }
+
     private final class LocalService extends PowerManagerInternal {
         @Override
         public void setScreenBrightnessOverrideFromWindowManager(int screenBrightness) {
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
index dd6d71e..20ceed43 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
@@ -72,7 +72,7 @@
     @GuardedBy("mLock")
     private int mBatteryLevel;
 
-    /** Whether the battery level is considered to be "low" or not.*/
+    /** Whether the battery level is considered to be "low" or not. */
     @GuardedBy("mLock")
     private boolean mIsBatteryLevelLow;
 
@@ -84,6 +84,9 @@
     @GuardedBy("mLock")
     private boolean mSettingBatterySaverEnabledSticky;
 
+    /** Config flag to track if battery saver's sticky behaviour is disabled. */
+    private final boolean mBatterySaverStickyBehaviourDisabled;
+
     /**
      * Previously known value of Global.LOW_POWER_MODE_TRIGGER_LEVEL.
      * (Currently only used in dumpsys.)
@@ -124,6 +127,9 @@
         mLock = lock;
         mContext = context;
         mBatterySaverController = batterySaverController;
+
+        mBatterySaverStickyBehaviourDisabled = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled);
     }
 
     private boolean isBatterySaverEnabled() {
@@ -190,6 +196,7 @@
         h.postDelayed(r, delayMillis);
     }
 
+    @GuardedBy("mLock")
     void refreshSettingsLocked() {
         final boolean lowPowerModeEnabled = getGlobalSetting(
                 Settings.Global.LOW_POWER_MODE, 0) != 0;
@@ -208,6 +215,7 @@
      *
      * Note this will be called before {@link #onBootCompleted} too.
      */
+    @GuardedBy("mLock")
     @VisibleForTesting
     void setSettingsLocked(boolean batterySaverEnabled, boolean batterySaverEnabledSticky,
             int batterySaverTriggerThreshold) {
@@ -282,6 +290,7 @@
     /**
      * Decide whether to auto-start / stop battery saver.
      */
+    @GuardedBy("mLock")
     private void doAutoBatterySaverLocked() {
         if (DEBUG) {
             Slog.d(TAG, "doAutoBatterySaverLocked: mBootCompleted=" + mBootCompleted
@@ -304,7 +313,7 @@
                     BatterySaverController.REASON_PLUGGED_IN,
                     "Plugged in");
 
-        } else if (mSettingBatterySaverEnabledSticky) {
+        } else if (mSettingBatterySaverEnabledSticky && !mBatterySaverStickyBehaviourDisabled) {
             // Re-enable BS.
             enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ true,
                     BatterySaverController.REASON_STICKY_RESTORE,
@@ -345,6 +354,7 @@
      * Actually enable / disable battery saver. Write the new state to the global settings
      * and propagate it to {@link #mBatterySaverController}.
      */
+    @GuardedBy("mLock")
     private void enableBatterySaverLocked(boolean enable, boolean manual, int intReason,
             String strReason) {
         if (DEBUG) {
@@ -383,8 +393,9 @@
         putGlobalSetting(Global.LOW_POWER_MODE, enable ? 1 : 0);
 
         if (manual) {
-            mSettingBatterySaverEnabledSticky = enable;
-            putGlobalSetting(Global.LOW_POWER_MODE_STICKY, enable ? 1 : 0);
+            mSettingBatterySaverEnabledSticky = !mBatterySaverStickyBehaviourDisabled && enable;
+            putGlobalSetting(Global.LOW_POWER_MODE_STICKY,
+                    mSettingBatterySaverEnabledSticky ? 1 : 0);
         }
         mBatterySaverController.enableBatterySaver(enable, intReason);
 
@@ -395,6 +406,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void updateSnoozingLocked(boolean snoozing, String reason) {
         if (mBatterySaverSnoozing == snoozing) {
             return;
@@ -449,6 +461,8 @@
             pw.println(mSettingBatterySaverEnabledSticky);
             pw.print("  mSettingBatterySaverTriggerThreshold=");
             pw.println(mSettingBatterySaverTriggerThreshold);
+            pw.print("  mBatterySaverStickyBehaviourDisabled=");
+            pw.println(mBatterySaverStickyBehaviourDisabled);
         }
     }
 
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
index f53a5dc..8213205 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
@@ -484,6 +484,7 @@
                 (BatterySaverState.MASK << BatterySaverState.SHIFT) |
                 (InteractiveState.MASK << InteractiveState.SHIFT);
 
+        @GuardedBy("BatterySavingStats.this.mLock")
         public void transitionStateLocked(
                 int newState, long now, int batteryLevel, int batteryPercent) {
             final boolean stateChanging =
@@ -503,6 +504,7 @@
             mLastState = newState;
         }
 
+        @GuardedBy("BatterySavingStats.this.mLock")
         void reportLocked(int state, long deltaTimeMs,
                 int startBatteryLevelUa, int startBatteryLevelPercent,
                 int endBatteryLevelUa, int endBatteryLevelPercent) {
diff --git a/services/core/java/com/android/server/slice/PinnedSliceState.java b/services/core/java/com/android/server/slice/PinnedSliceState.java
index 4e7fb96..e139ab8 100644
--- a/services/core/java/com/android/server/slice/PinnedSliceState.java
+++ b/services/core/java/com/android/server/slice/PinnedSliceState.java
@@ -154,8 +154,8 @@
     }
 
     ContentProviderClient getClient() {
-        ContentProviderClient client =
-                mService.getContext().getContentResolver().acquireContentProviderClient(mUri);
+        ContentProviderClient client = mService.getContext().getContentResolver()
+                .acquireUnstableContentProviderClient(mUri);
         if (client == null) return null;
         client.setDetectNotResponding(SLICE_TIMEOUT);
         return client;
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index ea34346..73775b4 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -42,6 +42,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.os.Binder;
@@ -218,12 +219,12 @@
     }
 
     @Override
-    public int checkSlicePermission(Uri uri, String pkg, int pid, int uid,
+    public int checkSlicePermission(Uri uri, String callingPkg, String pkg, int pid, int uid,
             String[] autoGrantPermissions) {
         int userId = UserHandle.getUserId(uid);
         if (pkg == null) {
             for (String p : mContext.getPackageManager().getPackagesForUid(uid)) {
-                if (checkSlicePermission(uri, p, pid, uid, autoGrantPermissions)
+                if (checkSlicePermission(uri, callingPkg, p, pid, uid, autoGrantPermissions)
                         == PERMISSION_GRANTED) {
                     return PERMISSION_GRANTED;
                 }
@@ -236,9 +237,9 @@
         if (mPermissions.hasPermission(pkg, userId, uri)) {
             return PackageManager.PERMISSION_GRANTED;
         }
-        if (autoGrantPermissions != null) {
+        if (autoGrantPermissions != null && callingPkg != null) {
             // Need to own the Uri to call in with permissions to grant.
-            enforceOwner(pkg, uri, userId);
+            enforceOwner(callingPkg, uri, userId);
             for (String perm : autoGrantPermissions) {
                 if (mContext.checkPermission(perm, pid, uid) == PERMISSION_GRANTED) {
                     int providerUser = ContentProvider.getUserIdFromUri(uri, userId);
@@ -390,36 +391,17 @@
     }
 
     protected int checkAccess(String pkg, Uri uri, int uid, int pid) {
-        return checkSlicePermission(uri, pkg, uid, pid, null);
+        return checkSlicePermission(uri, null, pkg, uid, pid, null);
     }
 
     private String getProviderPkg(Uri uri, int user) {
         long ident = Binder.clearCallingIdentity();
         try {
-            IBinder token = new Binder();
-            IActivityManager activityManager = ActivityManager.getService();
-            ContentProviderHolder holder = null;
             String providerName = getUriWithoutUserId(uri).getAuthority();
-            try {
-                try {
-                    holder = activityManager.getContentProviderExternal(
-                            providerName, getUserIdFromUri(uri, user), token);
-                    if (holder != null && holder.info != null) {
-                        return holder.info.packageName;
-                    } else {
-                        return null;
-                    }
-                } finally {
-                    if (holder != null && holder.provider != null) {
-                        activityManager.removeContentProviderExternal(providerName, token);
-                    }
-                }
-            } catch (RemoteException e) {
-                // Can't happen.
-                throw e.rethrowAsRuntimeException();
-            }
+            ProviderInfo provider = mContext.getPackageManager().resolveContentProviderAsUser(
+                    providerName, 0, getUserIdFromUri(uri, user));
+            return provider.packageName;
         } finally {
-            // I know, the double finally seems ugly, but seems safest for the identity.
             Binder.restoreCallingIdentity(ident);
         }
     }
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 4d65440..59673d0 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -19,7 +19,6 @@
 import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
 import android.app.AlarmManager.OnAlarmListener;
-import android.app.PendingIntent;
 import android.app.ProcessMemoryState;
 import android.app.StatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -44,6 +43,7 @@
 import android.os.IBinder;
 import android.os.IStatsCompanionService;
 import android.os.IStatsManager;
+import android.os.IStoraged;
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
@@ -55,27 +55,40 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.telephony.ModemActivityInfo;
 import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.StatsLog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.os.BinderCallsStats.ExportedCallStat;
 import com.android.internal.os.KernelCpuSpeedReader;
-import com.android.internal.os.KernelUidCpuTimeReader;
-import com.android.internal.os.KernelUidCpuClusterTimeReader;
 import com.android.internal.os.KernelUidCpuActiveTimeReader;
+import com.android.internal.os.KernelUidCpuClusterTimeReader;
 import com.android.internal.os.KernelUidCpuFreqTimeReader;
+import com.android.internal.os.KernelUidCpuTimeReader;
 import com.android.internal.os.KernelWakelockReader;
 import com.android.internal.os.KernelWakelockStats;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.util.DumpUtils;
+import com.android.server.BinderCallsStatsService;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.storage.DiskStatsFileLogger;
+import com.android.server.storage.DiskStatsLoggingService;
+
+import libcore.io.IoUtils;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
 
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -84,6 +97,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
@@ -324,6 +338,7 @@
                             PackageManager pm = context.getPackageManager();
                             String app = intent.getData().getSchemeSpecificPart();
                             sStatsd.informOnePackageRemoved(app, uid);
+                            StatsLog.write(StatsLog.GENERIC_ATOM, uid, 1000);
                         }
                     } else {
                         PackageManager pm = context.getPackageManager();
@@ -332,6 +347,7 @@
                         String app = intent.getData().getSchemeSpecificPart();
                         PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
                         sStatsd.informOnePackage(app, uid, pi.getLongVersionCode());
+                        StatsLog.write(StatsLog.GENERIC_ATOM, uid, 1001);
                     }
                 } catch (Exception e) {
                     Slog.w(TAG, "Failed to inform statsd of an app update", e);
@@ -858,14 +874,6 @@
         pulledData.add(e);
     }
 
-    private void pullDiskSpace(int tagId, List<StatsLogEventWrapper> pulledData) {
-        StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 3);
-        e.writeLong(mStatFsData.getAvailableBytes());
-        e.writeLong(mStatFsSystem.getAvailableBytes());
-        e.writeLong(mStatFsTemp.getAvailableBytes());
-        pulledData.add(e);
-    }
-
     private void pullSystemUpTime(int tagId, List<StatsLogEventWrapper> pulledData) {
         StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 1);
         e.writeLong(SystemClock.uptimeMillis());
@@ -891,6 +899,228 @@
         }
     }
 
+    private void pullBinderCallsStats(int tagId, List<StatsLogEventWrapper> pulledData) {
+        BinderCallsStatsService.Internal binderStats =
+                LocalServices.getService(BinderCallsStatsService.Internal.class);
+        if (binderStats == null) {
+            return;
+        }
+
+        List<ExportedCallStat> callStats = binderStats.getExportedCallStats();
+        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+        for (ExportedCallStat callStat : callStats) {
+            StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 13 /* fields */);
+            e.writeInt(callStat.uid);
+            e.writeString(callStat.className);
+            e.writeString(callStat.methodName);
+            e.writeLong(callStat.callCount);
+            e.writeLong(callStat.exceptionCount);
+            e.writeLong(callStat.latencyMicros);
+            e.writeLong(callStat.maxLatencyMicros);
+            e.writeLong(callStat.cpuTimeMicros);
+            e.writeLong(callStat.maxCpuTimeMicros);
+            e.writeLong(callStat.maxReplySizeBytes);
+            e.writeLong(callStat.maxRequestSizeBytes);
+            e.writeLong(callStat.recordedCallCount);
+            e.writeInt(callStat.screenInteractive ? 1 : 0);
+            pulledData.add(e);
+        }
+    }
+
+    private void pullBinderCallsStatsExceptions(int tagId, List<StatsLogEventWrapper> pulledData) {
+        BinderCallsStatsService.Internal binderStats =
+                LocalServices.getService(BinderCallsStatsService.Internal.class);
+        if (binderStats == null) {
+            return;
+        }
+
+        ArrayMap<String, Integer> exceptionStats = binderStats.getExportedExceptionStats();
+        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+        for (Entry<String, Integer> entry : exceptionStats.entrySet()) {
+            StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 2 /* fields */);
+            e.writeString(entry.getKey());
+            e.writeInt(entry.getValue());
+            pulledData.add(e);
+        }
+    }
+
+    private void pullDiskStats(int tagId, List<StatsLogEventWrapper> pulledData) {
+        // Run a quick-and-dirty performance test: write 512 bytes
+        byte[] junk = new byte[512];
+        for (int i = 0; i < junk.length; i++) junk[i] = (byte) i;  // Write nonzero bytes
+
+        File tmp = new File(Environment.getDataDirectory(), "system/statsdperftest.tmp");
+        FileOutputStream fos = null;
+        IOException error = null;
+
+        long before = SystemClock.elapsedRealtime();
+        try {
+            fos = new FileOutputStream(tmp);
+            fos.write(junk);
+        } catch (IOException e) {
+            error = e;
+        } finally {
+            try {
+                if (fos != null) fos.close();
+            } catch (IOException e) {
+                // Do nothing.
+            }
+        }
+
+        long latency = SystemClock.elapsedRealtime() - before;
+        if (tmp.exists()) tmp.delete();
+
+        if (error != null) {
+            Slog.e(TAG, "Error performing diskstats latency test");
+            latency = -1;
+        }
+        // File based encryption.
+        boolean fileBased = StorageManager.isFileEncryptedNativeOnly();
+
+        //Recent disk write speed. Binder call to storaged.
+        int writeSpeed = -1;
+        try {
+            IBinder binder = ServiceManager.getService("storaged");
+            if (binder == null) {
+                Slog.e(TAG, "storaged not found");
+            }
+            IStoraged storaged = IStoraged.Stub.asInterface(binder);
+            writeSpeed = storaged.getRecentPerf();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "storaged not found");
+        }
+
+        // Add info pulledData.
+        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+        StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+        e.writeLong(latency);
+        e.writeBoolean(fileBased);
+        e.writeInt(writeSpeed);
+        pulledData.add(e);
+    }
+
+    private void pullDirectoryUsage(int tagId, List<StatsLogEventWrapper> pulledData) {
+        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+        StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
+        StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath());
+        StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
+
+        StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+        e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__DATA);
+        e.writeLong(statFsData.getAvailableBytes());
+        e.writeLong(statFsData.getTotalBytes());
+        pulledData.add(e);
+
+        e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+        e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE);
+        e.writeLong(statFsCache.getAvailableBytes());
+        e.writeLong(statFsCache.getTotalBytes());
+        pulledData.add(e);
+
+        e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+        e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM);
+        e.writeLong(statFsSystem.getAvailableBytes());
+        e.writeLong(statFsSystem.getTotalBytes());
+        pulledData.add(e);
+    }
+
+    private void pullAppSize(int tagId, List<StatsLogEventWrapper> pulledData) {
+        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+        try {
+            String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
+            JSONObject json = new JSONObject(jsonStr);
+            long cache_time = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L);
+            JSONArray pkg_names = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY);
+            JSONArray app_sizes = json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY);
+            JSONArray app_data_sizes = json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY);
+            JSONArray app_cache_sizes = json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY);
+            // Sanity check: Ensure all 4 lists have the same length.
+            int length = pkg_names.length();
+            if (app_sizes.length() != length || app_data_sizes.length() != length
+                    || app_cache_sizes.length() != length) {
+                Slog.e(TAG, "formatting error in diskstats cache file!");
+                return;
+            }
+            for (int i = 0; i < length; i++) {
+                StatsLogEventWrapper e =
+                        new StatsLogEventWrapper(elapsedNanos, tagId, 5 /* fields */);
+                e.writeString(pkg_names.getString(i));
+                e.writeLong(app_sizes.optLong(i, -1L));
+                e.writeLong(app_data_sizes.optLong(i, -1L));
+                e.writeLong(app_cache_sizes.optLong(i, -1L));
+                e.writeLong(cache_time);
+                pulledData.add(e);
+            }
+        } catch (IOException | JSONException e) {
+            Slog.e(TAG, "exception reading diskstats cache file", e);
+        }
+    }
+
+    private void pullCategorySize(int tagId, List<StatsLogEventWrapper> pulledData) {
+        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+        try {
+            String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
+            JSONObject json = new JSONObject(jsonStr);
+            long cacheTime = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L);
+
+            StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE);
+            e.writeLong(json.optLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY, -1L));
+            e.writeLong(cacheTime);
+            pulledData.add(e);
+
+            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE);
+            e.writeLong(json.optLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY, -1L));
+            e.writeLong(cacheTime);
+            pulledData.add(e);
+
+            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE);
+            e.writeLong(json.optLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY, -1L));
+            e.writeLong(cacheTime);
+            pulledData.add(e);
+
+            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS);
+            e.writeLong(json.optLong(DiskStatsFileLogger.PHOTOS_KEY, -1L));
+            e.writeLong(cacheTime);
+            pulledData.add(e);
+
+            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS);
+            e.writeLong(json.optLong(DiskStatsFileLogger.VIDEOS_KEY, -1L));
+            e.writeLong(cacheTime);
+            pulledData.add(e);
+
+            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__AUDIO);
+            e.writeLong(json.optLong(DiskStatsFileLogger.AUDIO_KEY, -1L));
+            e.writeLong(cacheTime);
+            pulledData.add(e);
+
+            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS);
+            e.writeLong(json.optLong(DiskStatsFileLogger.DOWNLOADS_KEY, -1L));
+            e.writeLong(cacheTime);
+            pulledData.add(e);
+
+            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM);
+            e.writeLong(json.optLong(DiskStatsFileLogger.SYSTEM_KEY, -1L));
+            e.writeLong(cacheTime);
+            pulledData.add(e);
+
+            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
+            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__OTHER);
+            e.writeLong(json.optLong(DiskStatsFileLogger.MISC_KEY, -1L));
+            e.writeLong(cacheTime);
+            pulledData.add(e);
+        } catch (IOException | JSONException e) {
+            Slog.e(TAG, "exception reading diskstats cache file", e);
+        }
+    }
+
     /**
      * Pulls various data.
      */
@@ -965,14 +1195,34 @@
                 pullSystemElapsedRealtime(tagId, ret);
                 break;
             }
-            case StatsLog.DISK_SPACE: {
-                pullDiskSpace(tagId, ret);
-                break;
-            }
             case StatsLog.PROCESS_MEMORY_STATE: {
                 pullProcessMemoryState(tagId, ret);
                 break;
             }
+            case StatsLog.BINDER_CALLS: {
+                pullBinderCallsStats(tagId, ret);
+                break;
+            }
+            case StatsLog.BINDER_CALLS_EXCEPTIONS: {
+                pullBinderCallsStatsExceptions(tagId, ret);
+                break;
+            }
+            case StatsLog.DISK_STATS: {
+                pullDiskStats(tagId, ret);
+                break;
+            }
+            case StatsLog.DIRECTORY_USAGE: {
+                pullDirectoryUsage(tagId, ret);
+                break;
+            }
+            case StatsLog.APP_SIZE: {
+                pullAppSize(tagId, ret);
+                break;
+            }
+            case StatsLog.CATEGORY_SIZE: {
+                pullCategorySize(tagId, ret);
+                break;
+            }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
@@ -1152,6 +1402,7 @@
         }
     }
 
+    @GuardedBy("StatsCompanionService.sStatsdLock")
     private void forgetEverythingLocked() {
         sStatsd = null;
         mContext.unregisterReceiver(mAppUpdateReceiver);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 738b0ca..b8c9be7 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -80,6 +80,7 @@
     private int mDisabled2 = 0;
 
     private final Object mLock = new Object();
+    private final DeathRecipient mDeathRecipient = new DeathRecipient();
     // encompasses lights-out mode and other flags defined on View
     private int mSystemUiVisibility = 0;
     private int mFullscreenStackSysUiVisibility;
@@ -93,6 +94,23 @@
     private IBinder mImeToken = null;
     private int mCurrentUserId;
 
+    private class DeathRecipient implements IBinder.DeathRecipient {
+        public void binderDied() {
+            mBar.asBinder().unlinkToDeath(this,0);
+            mBar = null;
+            notifyBarAttachChanged();
+        }
+
+        public void linkToDeath() {
+            try {
+                mBar.asBinder().linkToDeath(mDeathRecipient,0);
+            } catch (RemoteException e) {
+                Slog.e(TAG,"Unable to register Death Recipient for status bar", e);
+            }
+        }
+
+    }
+
     private class DisableRecord implements IBinder.DeathRecipient {
         int userId;
         String pkg;
@@ -547,50 +565,50 @@
     }
 
     @Override
-    public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
+    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
         if (mBar != null) {
             try {
-                mBar.showFingerprintDialog(bundle, receiver);
+                mBar.showBiometricDialog(bundle, receiver);
             } catch (RemoteException ex) {
             }
         }
     }
 
     @Override
-    public void onFingerprintAuthenticated() {
+    public void onBiometricAuthenticated() {
         if (mBar != null) {
             try {
-                mBar.onFingerprintAuthenticated();
+                mBar.onBiometricAuthenticated();
             } catch (RemoteException ex) {
             }
         }
     }
 
     @Override
-    public void onFingerprintHelp(String message) {
+    public void onBiometricHelp(String message) {
         if (mBar != null) {
             try {
-                mBar.onFingerprintHelp(message);
+                mBar.onBiometricHelp(message);
             } catch (RemoteException ex) {
             }
         }
     }
 
     @Override
-    public void onFingerprintError(String error) {
+    public void onBiometricError(String error) {
         if (mBar != null) {
             try {
-                mBar.onFingerprintError(error);
+                mBar.onBiometricError(error);
             } catch (RemoteException ex) {
             }
         }
     }
 
     @Override
-    public void hideFingerprintDialog() {
+    public void hideBiometricDialog() {
         if (mBar != null) {
             try {
-                mBar.hideFingerprintDialog();
+                mBar.hideBiometricDialog();
             } catch (RemoteException ex) {
             }
         }
@@ -859,16 +877,7 @@
 
         Slog.i(TAG, "registerStatusBar bar=" + bar);
         mBar = bar;
-        try {
-            mBar.asBinder().linkToDeath(new DeathRecipient() {
-                @Override
-                public void binderDied() {
-                    mBar = null;
-                    notifyBarAttachChanged();
-                }
-            }, 0);
-        } catch (RemoteException e) {
-        }
+        mDeathRecipient.linkToDeath();
         notifyBarAttachChanged();
         synchronized (mIcons) {
             for (String slot : mIcons.keySet()) {
@@ -1044,14 +1053,16 @@
 
     @Override
     public void onNotificationClear(String pkg, String tag, int id, int userId, String key,
-            @NotificationStats.DismissalSurface int dismissalSurface, NotificationVisibility nv) {
+            @NotificationStats.DismissalSurface int dismissalSurface,
+            @NotificationStats.DismissalSentiment int dismissalSentiment,
+            NotificationVisibility nv) {
         enforceStatusBarService();
         final int callingUid = Binder.getCallingUid();
         final int callingPid = Binder.getCallingPid();
         long identity = Binder.clearCallingIdentity();
         try {
             mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, tag, id, userId,
-                    key, dismissalSurface, nv);
+                    key, dismissalSurface, dismissalSentiment, nv);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 2742b0f..d36ab3f 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -28,6 +28,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.service.textclassifier.ITextClassificationCallback;
 import android.service.textclassifier.ITextClassifierService;
 import android.service.textclassifier.ITextLinksCallback;
@@ -38,16 +39,22 @@
 import android.view.textclassifier.SelectionEvent;
 import android.view.textclassifier.TextClassification;
 import android.view.textclassifier.TextClassificationContext;
+import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassificationSessionId;
+import android.view.textclassifier.TextClassifier;
 import android.view.textclassifier.TextLinks;
 import android.view.textclassifier.TextSelection;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FunctionalUtils;
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayDeque;
 import java.util.Queue;
 
@@ -242,10 +249,12 @@
         }
     }
 
+    @GuardedBy("mLock")
     private UserState getCallingUserStateLocked() {
         return getUserStateLocked(UserHandle.getCallingUserId());
     }
 
+    @GuardedBy("mLock")
     private UserState getUserStateLocked(int userId) {
         UserState result = mUserStates.get(userId);
         if (result == null) {
@@ -255,10 +264,19 @@
         return result;
     }
 
+    @GuardedBy("mLock")
     UserState peekUserStateLocked(int userId) {
         return mUserStates.get(userId);
     }
 
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+        if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, fout)) return;
+        IndentingPrintWriter pw = new IndentingPrintWriter(fout, "  ");
+        TextClassificationManager tcm = mContext.getSystemService(TextClassificationManager.class);
+        tcm.dump(pw);
+    }
+
     private static final class PendingRequest implements IBinder.DeathRecipient {
 
         @Nullable private final IBinder mBinder;
@@ -374,6 +392,7 @@
             }
         }
 
+        @GuardedBy("mLock")
         private boolean bindIfHasPendingRequestsLocked() {
             return !mPendingRequests.isEmpty() && bindLocked();
         }
@@ -382,6 +401,7 @@
          * @return true if the service is bound or in the process of being bound.
          *      Returns false otherwise.
          */
+        @GuardedBy("mLock")
         private boolean bindLocked() {
             if (isBoundLocked() || mBinding) {
                 return true;
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 8a135b8..3291a45 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -47,7 +47,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.service.trust.TrustAgentService;
 import android.text.TextUtils;
@@ -61,7 +60,6 @@
 import android.view.WindowManagerGlobal;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.SystemService;
@@ -432,13 +430,20 @@
         for (int i = 0; i < userInfos.size(); i++) {
             UserInfo info = userInfos.get(i);
 
-            if (info == null || info.partial || !info.isEnabled() || info.guestToRemove
-                    || !info.supportsSwitchToByUser()) {
+            if (info == null || info.partial || !info.isEnabled() || info.guestToRemove) {
                 continue;
             }
 
             int id = info.id;
             boolean secure = mLockPatternUtils.isSecure(id);
+
+            if (!info.supportsSwitchToByUser()) {
+                if (info.isManagedProfile() && !secure) {
+                    setDeviceLockedForUser(id, false);
+                }
+                continue;
+            }
+
             boolean trusted = aggregateIsTrusted(id);
             boolean showingKeyguard = true;
             boolean biometricAuthenticated = false;
@@ -993,7 +998,8 @@
             enforceReportPermission();
             final long identity = Binder.clearCallingIdentity();
             try {
-                if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+                if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
+                        && mLockPatternUtils.isSecure(userId)) {
                     synchronized (mDeviceLockedForUser) {
                         mDeviceLockedForUser.put(userId, locked);
                     }
diff --git a/services/core/java/com/android/server/uri/GrantUri.java b/services/core/java/com/android/server/uri/GrantUri.java
new file mode 100644
index 0000000..c694264
--- /dev/null
+++ b/services/core/java/com/android/server/uri/GrantUri.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.uri;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.am.GrantUriProto;
+
+/** A {@link Uri} that can be granted to app an to access with the right permission. */
+public class GrantUri {
+    public final int sourceUserId;
+    public final Uri uri;
+    public boolean prefix;
+
+    public GrantUri(int sourceUserId, Uri uri, boolean prefix) {
+        this.sourceUserId = sourceUserId;
+        this.uri = uri;
+        this.prefix = prefix;
+    }
+
+    @Override
+    public int hashCode() {
+        int hashCode = 1;
+        hashCode = 31 * hashCode + sourceUserId;
+        hashCode = 31 * hashCode + uri.hashCode();
+        hashCode = 31 * hashCode + (prefix ? 1231 : 1237);
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof GrantUri) {
+            GrantUri other = (GrantUri) o;
+            return uri.equals(other.uri) && (sourceUserId == other.sourceUserId)
+                    && prefix == other.prefix;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        String result = uri.toString() + " [user " + sourceUserId + "]";
+        if (prefix) result += " [prefix]";
+        return result;
+    }
+
+    public String toSafeString() {
+        String result = uri.toSafeString() + " [user " + sourceUserId + "]";
+        if (prefix) result += " [prefix]";
+        return result;
+    }
+
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        long token = proto.start(fieldId);
+        proto.write(GrantUriProto.URI, uri.toString());
+        proto.write(GrantUriProto.SOURCE_USER_ID, sourceUserId);
+        proto.end(token);
+    }
+
+    public static GrantUri resolve(int defaultSourceUserHandle, Uri uri) {
+        if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+            return new GrantUri(ContentProvider.getUserIdFromUri(uri, defaultSourceUserHandle),
+                    ContentProvider.getUriWithoutUserId(uri), false);
+        } else {
+            return new GrantUri(defaultSourceUserHandle, uri, false);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/uri/NeededUriGrants.java b/services/core/java/com/android/server/uri/NeededUriGrants.java
new file mode 100644
index 0000000..87a2641
--- /dev/null
+++ b/services/core/java/com/android/server/uri/NeededUriGrants.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.uri;
+
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.am.NeededUriGrantsProto;
+
+import java.util.ArrayList;
+
+/** List of {@link GrantUri} a process needs. */
+public class NeededUriGrants extends ArrayList<GrantUri> {
+    final String targetPkg;
+    final int targetUid;
+    final int flags;
+
+    public NeededUriGrants(String targetPkg, int targetUid, int flags) {
+        this.targetPkg = targetPkg;
+        this.targetUid = targetUid;
+        this.flags = flags;
+    }
+
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        long token = proto.start(fieldId);
+        proto.write(NeededUriGrantsProto.TARGET_PACKAGE, targetPkg);
+        proto.write(NeededUriGrantsProto.TARGET_UID, targetUid);
+        proto.write(NeededUriGrantsProto.FLAGS, flags);
+
+        final int N = this.size();
+        for (int i = 0; i < N; i++) {
+            this.get(i).writeToProto(proto, NeededUriGrantsProto.GRANTS);
+        }
+        proto.end(token);
+    }
+}
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerInternal.java b/services/core/java/com/android/server/uri/UriGrantsManagerInternal.java
new file mode 100644
index 0000000..2f50fcb
--- /dev/null
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerInternal.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.uri;
+
+import android.content.Intent;
+import android.content.pm.ProviderInfo;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+
+/**
+ * Uri Grants local system service interface.
+ * @hide Only for use within system server
+ */
+public interface UriGrantsManagerInternal {
+    void onSystemReady();
+    void onActivityManagerInternalAdded();
+    void removeUriPermissionIfNeeded(UriPermission perm);
+    void grantUriPermission(int callingUid, String targetPkg, GrantUri grantUri,
+            final int modeFlags, UriPermissionOwner owner, int targetUserId);
+    void revokeUriPermission(String targetPackage, int callingUid,
+            GrantUri grantUri, final int modeFlags);
+    boolean checkUriPermission(GrantUri grantUri, int uid, final int modeFlags);
+    int checkGrantUriPermission(int callingUid, String targetPkg, GrantUri grantUri,
+            final int modeFlags, int lastTargetUid);
+    int checkGrantUriPermission(
+            int callingUid, String targetPkg, Uri uri, int modeFlags, int userId);
+    NeededUriGrants checkGrantUriPermissionFromIntent(int callingUid,
+            String targetPkg, Intent intent, int mode, NeededUriGrants needed, int targetUserId);
+    /**
+     * Grant Uri permissions from one app to another. This method only extends
+     * permission grants if {@code callingUid} has permission to them.
+     */
+    void grantUriPermissionFromIntent(int callingUid,
+            String targetPkg, Intent intent, int targetUserId);
+    void grantUriPermissionFromIntent(int callingUid,
+            String targetPkg, Intent intent, UriPermissionOwner owner, int targetUserId);
+    void grantUriPermissionUncheckedFromIntent(
+            NeededUriGrants needed, UriPermissionOwner owner);
+    IBinder newUriPermissionOwner(String name);
+    /**
+     * Remove any {@link UriPermission} granted <em>from</em> or <em>to</em> the
+     * given package.
+     *
+     * @param packageName Package name to match, or {@code null} to apply to all
+     *            packages.
+     * @param userHandle User to match, or {@link UserHandle#USER_ALL} to apply
+     *            to all users.
+     * @param persistable If persistable grants should be removed.
+     * @param targetOnly When {@code true}, only remove permissions where the app is the target,
+     * not source.
+     */
+    void removeUriPermissionsForPackage(
+            String packageName, int userHandle, boolean persistable, boolean targetOnly);
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param userId The userId in which the uri is to be resolved.
+     */
+    void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId);
+    boolean checkAuthorityGrants(
+            int callingUid, ProviderInfo cpi, int userId, boolean checkUser);
+    void dump(PrintWriter pw, boolean dumpAll, String dumpPackage);
+}
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
new file mode 100644
index 0000000..9a7e75e
--- /dev/null
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -0,0 +1,1490 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.uri;
+
+import static android.Manifest.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS;
+import static android.Manifest.permission.FORCE_PERSISTABLE_URI_PERMISSIONS;
+import static android.Manifest.permission.GET_APP_GRANTED_URI_PERMISSIONS;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
+import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.myUid;
+
+import static com.android.internal.util.XmlUtils.readBooleanAttribute;
+import static com.android.internal.util.XmlUtils.readIntAttribute;
+import static com.android.internal.util.XmlUtils.readLongAttribute;
+import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
+import static com.android.internal.util.XmlUtils.writeIntAttribute;
+import static com.android.internal.util.XmlUtils.writeLongAttribute;
+import static com.android.server.uri.UriGrantsManagerService.H.PERSIST_URI_GRANTS_MSG;
+
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.AppGlobals;
+import android.app.GrantedUriPermission;
+import android.app.IUriGrantsManager;
+import android.content.ClipData;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.PathPermission;
+import android.content.pm.ProviderInfo;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Downloads;
+import android.text.format.DateUtils;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
+import com.android.server.IoThread;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.SystemServiceManager;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/** Manages uri grants. */
+public class UriGrantsManagerService extends IUriGrantsManager.Stub {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "UriGrantsManagerService";
+    // Maximum number of persisted Uri grants a package is allowed
+    private static final int MAX_PERSISTED_URI_GRANTS = 128;
+
+    private final Object mLock = new Object();
+    private final Context mContext;
+    private final H mH;
+    ActivityManagerInternal mAmInternal;
+    PackageManagerInternal mPmInternal;
+
+    /** File storing persisted {@link #mGrantedUriPermissions}. */
+    private final AtomicFile mGrantFile;
+
+    /** XML constants used in {@link #mGrantFile} */
+    private static final String TAG_URI_GRANTS = "uri-grants";
+    private static final String TAG_URI_GRANT = "uri-grant";
+    private static final String ATTR_USER_HANDLE = "userHandle";
+    private static final String ATTR_SOURCE_USER_ID = "sourceUserId";
+    private static final String ATTR_TARGET_USER_ID = "targetUserId";
+    private static final String ATTR_SOURCE_PKG = "sourcePkg";
+    private static final String ATTR_TARGET_PKG = "targetPkg";
+    private static final String ATTR_URI = "uri";
+    private static final String ATTR_MODE_FLAGS = "modeFlags";
+    private static final String ATTR_CREATED_TIME = "createdTime";
+    private static final String ATTR_PREFIX = "prefix";
+
+    /**
+     * Global set of specific {@link Uri} permissions that have been granted.
+     * This optimized lookup structure maps from {@link UriPermission#targetUid}
+     * to {@link UriPermission#uri} to {@link UriPermission}.
+     */
+    private final SparseArray<ArrayMap<GrantUri, UriPermission>>
+            mGrantedUriPermissions = new SparseArray<>();
+
+    private UriGrantsManagerService(Context context) {
+        mContext = context;
+        mH = new H(IoThread.get().getLooper());
+        final File systemDir = SystemServiceManager.ensureSystemDir();
+        mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");
+    }
+
+    private void start() {
+        LocalServices.addService(UriGrantsManagerInternal.class, new LocalService());
+    }
+
+    void onActivityManagerInternalAdded() {
+        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
+    }
+
+    public static final class Lifecycle extends SystemService {
+        private final UriGrantsManagerService mService;
+
+        public Lifecycle(Context context) {
+            super(context);
+            mService = new UriGrantsManagerService(context);
+        }
+
+        @Override
+        public void onStart() {
+            publishBinderService(Context.URI_GRANTS_SERVICE, mService);
+            mService.start();
+        }
+
+        public UriGrantsManagerService getService() {
+            return mService;
+        }
+    }
+
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param sourceUserId The userId in which the uri is to be resolved.
+     * @param targetUserId The userId of the app that receives the grant.
+     */
+    @Override
+    public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, Uri uri,
+            final int modeFlags, int sourceUserId, int targetUserId) {
+        targetUserId = mAmInternal.handleIncomingUser(Binder.getCallingPid(),
+                Binder.getCallingUid(), targetUserId, false, ALLOW_FULL_ONLY,
+                "grantUriPermissionFromOwner", null);
+        synchronized(mLock) {
+            UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
+            if (owner == null) {
+                throw new IllegalArgumentException("Unknown owner: " + token);
+            }
+            if (fromUid != Binder.getCallingUid()) {
+                if (Binder.getCallingUid() != myUid()) {
+                    // Only system code can grant URI permissions on behalf
+                    // of other users.
+                    throw new SecurityException("nice try");
+                }
+            }
+            if (targetPkg == null) {
+                throw new IllegalArgumentException("null target");
+            }
+            if (uri == null) {
+                throw new IllegalArgumentException("null uri");
+            }
+
+            grantUriPermission(fromUid, targetPkg, new GrantUri(sourceUserId, uri, false),
+                    modeFlags, owner, targetUserId);
+        }
+    }
+
+    @Override
+    public ParceledListSlice<android.content.UriPermission> getPersistedUriPermissions(
+            String packageName, boolean incoming) {
+        enforceNotIsolatedCaller("getPersistedUriPermissions");
+        Preconditions.checkNotNull(packageName, "packageName");
+
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        final IPackageManager pm = AppGlobals.getPackageManager();
+        try {
+            final int packageUid = pm.getPackageUid(packageName,
+                    MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, callingUserId);
+            if (packageUid != callingUid) {
+                throw new SecurityException(
+                        "Package " + packageName + " does not belong to calling UID " + callingUid);
+            }
+        } catch (RemoteException e) {
+            throw new SecurityException("Failed to verify package name ownership");
+        }
+
+        final ArrayList<android.content.UriPermission> result = Lists.newArrayList();
+        synchronized (mLock) {
+            if (incoming) {
+                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
+                        callingUid);
+                if (perms == null) {
+                    Slog.w(TAG, "No permission grants found for " + packageName);
+                } else {
+                    for (int j = 0; j < perms.size(); j++) {
+                        final UriPermission perm = perms.valueAt(j);
+                        if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) {
+                            result.add(perm.buildPersistedPublicApiObject());
+                        }
+                    }
+                }
+            } else {
+                final int size = mGrantedUriPermissions.size();
+                for (int i = 0; i < size; i++) {
+                    final ArrayMap<GrantUri, UriPermission> perms =
+                            mGrantedUriPermissions.valueAt(i);
+                    for (int j = 0; j < perms.size(); j++) {
+                        final UriPermission perm = perms.valueAt(j);
+                        if (packageName.equals(perm.sourcePkg) && perm.persistedModeFlags != 0) {
+                            result.add(perm.buildPersistedPublicApiObject());
+                        }
+                    }
+                }
+            }
+        }
+        return new ParceledListSlice<>(result);
+    }
+
+    @Override
+    public ParceledListSlice<GrantedUriPermission> getGrantedUriPermissions(
+            @Nullable String packageName, int userId) {
+        mAmInternal.enforceCallingPermission(
+                GET_APP_GRANTED_URI_PERMISSIONS, "getGrantedUriPermissions");
+
+        final List<GrantedUriPermission> result = new ArrayList<>();
+        synchronized (mLock) {
+            final int size = mGrantedUriPermissions.size();
+            for (int i = 0; i < size; i++) {
+                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+                for (int j = 0; j < perms.size(); j++) {
+                    final UriPermission perm = perms.valueAt(j);
+                    if ((packageName == null || packageName.equals(perm.targetPkg))
+                            && perm.targetUserId == userId
+                            && perm.persistedModeFlags != 0) {
+                        result.add(perm.buildGrantedUriPermission());
+                    }
+                }
+            }
+        }
+        return new ParceledListSlice<>(result);
+    }
+
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param toPackage Name of package whose uri is being granted to (if {@code null}, uses
+     * calling uid)
+     * @param userId The userId in which the uri is to be resolved.
+     */
+    @Override
+    public void takePersistableUriPermission(Uri uri, final int modeFlags,
+            @Nullable String toPackage, int userId) {
+        final int uid;
+        if (toPackage != null) {
+            mAmInternal.enforceCallingPermission(FORCE_PERSISTABLE_URI_PERMISSIONS,
+                    "takePersistableUriPermission");
+            uid = getPmInternal().getPackageUid(toPackage, 0, userId);
+        } else {
+            enforceNotIsolatedCaller("takePersistableUriPermission");
+            uid = Binder.getCallingUid();
+        }
+
+        Preconditions.checkFlagsArgument(modeFlags,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        synchronized (mLock) {
+            boolean persistChanged = false;
+            GrantUri grantUri = new GrantUri(userId, uri, false);
+
+            UriPermission exactPerm = findUriPermissionLocked(uid, grantUri);
+            UriPermission prefixPerm = findUriPermissionLocked(uid,
+                    new GrantUri(userId, uri, true));
+
+            final boolean exactValid = (exactPerm != null)
+                    && ((modeFlags & exactPerm.persistableModeFlags) == modeFlags);
+            final boolean prefixValid = (prefixPerm != null)
+                    && ((modeFlags & prefixPerm.persistableModeFlags) == modeFlags);
+
+            if (!(exactValid || prefixValid)) {
+                throw new SecurityException("No persistable permission grants found for UID "
+                        + uid + " and Uri " + grantUri.toSafeString());
+            }
+
+            if (exactValid) {
+                persistChanged |= exactPerm.takePersistableModes(modeFlags);
+            }
+            if (prefixValid) {
+                persistChanged |= prefixPerm.takePersistableModes(modeFlags);
+            }
+
+            persistChanged |= maybePrunePersistedUriGrants(uid);
+
+            if (persistChanged) {
+                schedulePersistUriGrants();
+            }
+        }
+    }
+
+    @Override
+    public void clearGrantedUriPermissions(String packageName, int userId) {
+        mAmInternal.enforceCallingPermission(
+                CLEAR_APP_GRANTED_URI_PERMISSIONS, "clearGrantedUriPermissions");
+        synchronized(mLock) {
+            removeUriPermissionsForPackage(packageName, userId, true, true);
+        }
+    }
+
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param toPackage Name of the target package whose uri is being released (if {@code null},
+     * uses calling uid)
+     * @param userId The userId in which the uri is to be resolved.
+     */
+    @Override
+    public void releasePersistableUriPermission(Uri uri, final int modeFlags,
+            @Nullable String toPackage, int userId) {
+
+        final int uid;
+        if (toPackage != null) {
+            mAmInternal.enforceCallingPermission(FORCE_PERSISTABLE_URI_PERMISSIONS,
+                    "releasePersistableUriPermission");
+            uid = getPmInternal().getPackageUid(toPackage, 0, userId);
+        } else {
+            enforceNotIsolatedCaller("releasePersistableUriPermission");
+            uid = Binder.getCallingUid();
+        }
+
+        Preconditions.checkFlagsArgument(modeFlags,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        synchronized (mLock) {
+            boolean persistChanged = false;
+
+            UriPermission exactPerm = findUriPermissionLocked(uid,
+                    new GrantUri(userId, uri, false));
+            UriPermission prefixPerm = findUriPermissionLocked(uid,
+                    new GrantUri(userId, uri, true));
+            if (exactPerm == null && prefixPerm == null && toPackage == null) {
+                throw new SecurityException("No permission grants found for UID " + uid
+                        + " and Uri " + uri.toSafeString());
+            }
+
+            if (exactPerm != null) {
+                persistChanged |= exactPerm.releasePersistableModes(modeFlags);
+                removeUriPermissionIfNeeded(exactPerm);
+            }
+            if (prefixPerm != null) {
+                persistChanged |= prefixPerm.releasePersistableModes(modeFlags);
+                removeUriPermissionIfNeeded(prefixPerm);
+            }
+
+            if (persistChanged) {
+                schedulePersistUriGrants();
+            }
+        }
+    }
+
+    /**
+     * Remove any {@link UriPermission} granted <em>from</em> or <em>to</em> the
+     * given package.
+     *
+     * @param packageName Package name to match, or {@code null} to apply to all
+     *            packages.
+     * @param userHandle User to match, or {@link UserHandle#USER_ALL} to apply
+     *            to all users.
+     * @param persistable If persistable grants should be removed.
+     * @param targetOnly When {@code true}, only remove permissions where the app is the target,
+     * not source.
+     */
+    void removeUriPermissionsForPackage(
+            String packageName, int userHandle, boolean persistable, boolean targetOnly) {
+        if (userHandle == UserHandle.USER_ALL && packageName == null) {
+            throw new IllegalArgumentException("Must narrow by either package or user");
+        }
+
+        boolean persistChanged = false;
+
+        int N = mGrantedUriPermissions.size();
+        for (int i = 0; i < N; i++) {
+            final int targetUid = mGrantedUriPermissions.keyAt(i);
+            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+
+            // Only inspect grants matching user
+            if (userHandle == UserHandle.USER_ALL
+                    || userHandle == UserHandle.getUserId(targetUid)) {
+                for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
+                    final UriPermission perm = it.next();
+
+                    // Only inspect grants matching package
+                    if (packageName == null || (!targetOnly && perm.sourcePkg.equals(packageName))
+                            || perm.targetPkg.equals(packageName)) {
+                        // Hacky solution as part of fixing a security bug; ignore
+                        // grants associated with DownloadManager so we don't have
+                        // to immediately launch it to regrant the permissions
+                        if (Downloads.Impl.AUTHORITY.equals(perm.uri.uri.getAuthority())
+                                && !persistable) continue;
+
+                        persistChanged |= perm.revokeModes(persistable
+                                ? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
+
+                        // Only remove when no modes remain; any persisted grants
+                        // will keep this alive.
+                        if (perm.modeFlags == 0) {
+                            it.remove();
+                        }
+                    }
+                }
+
+                if (perms.isEmpty()) {
+                    mGrantedUriPermissions.remove(targetUid);
+                    N--;
+                    i--;
+                }
+            }
+        }
+
+        if (persistChanged) {
+            schedulePersistUriGrants();
+        }
+    }
+
+    /** Returns if the ContentProvider has granted a uri to callingUid */
+    boolean checkAuthorityGrants(int callingUid, ProviderInfo cpi, int userId, boolean checkUser) {
+        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+        if (perms != null) {
+            for (int i = perms.size() - 1; i >= 0; i--) {
+                GrantUri grantUri = perms.keyAt(i);
+                if (grantUri.sourceUserId == userId || !checkUser) {
+                    if (matchesProvider(grantUri.uri, cpi)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /** Returns true if the uri authority is one of the authorities specified in the provider. */
+    private boolean matchesProvider(Uri uri, ProviderInfo cpi) {
+        String uriAuth = uri.getAuthority();
+        String cpiAuth = cpi.authority;
+        if (cpiAuth.indexOf(';') == -1) {
+            return cpiAuth.equals(uriAuth);
+        }
+        String[] cpiAuths = cpiAuth.split(";");
+        int length = cpiAuths.length;
+        for (int i = 0; i < length; i++) {
+            if (cpiAuths[i].equals(uriAuth)) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Prune any older {@link UriPermission} for the given UID until outstanding
+     * persisted grants are below {@link #MAX_PERSISTED_URI_GRANTS}.
+     *
+     * @return if any mutations occured that require persisting.
+     */
+    private boolean maybePrunePersistedUriGrants(int uid) {
+        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
+        if (perms == null) return false;
+        if (perms.size() < MAX_PERSISTED_URI_GRANTS) return false;
+
+        final ArrayList<UriPermission> persisted = Lists.newArrayList();
+        for (UriPermission perm : perms.values()) {
+            if (perm.persistedModeFlags != 0) {
+                persisted.add(perm);
+            }
+        }
+
+        final int trimCount = persisted.size() - MAX_PERSISTED_URI_GRANTS;
+        if (trimCount <= 0) return false;
+
+        Collections.sort(persisted, new UriPermission.PersistedTimeComparator());
+        for (int i = 0; i < trimCount; i++) {
+            final UriPermission perm = persisted.get(i);
+
+            if (DEBUG) Slog.v(TAG, "Trimming grant created at " + perm.persistedCreateTime);
+
+            perm.releasePersistableModes(~0);
+            removeUriPermissionIfNeeded(perm);
+        }
+
+        return true;
+    }
+
+    /** Like checkGrantUriPermission, but takes an Intent. */
+    NeededUriGrants checkGrantUriPermissionFromIntent(int callingUid,
+            String targetPkg, Intent intent, int mode, NeededUriGrants needed, int targetUserId) {
+        if (DEBUG) Slog.v(TAG,
+                "Checking URI perm to data=" + (intent != null ? intent.getData() : null)
+                        + " clip=" + (intent != null ? intent.getClipData() : null)
+                        + " from " + intent + "; flags=0x"
+                        + Integer.toHexString(intent != null ? intent.getFlags() : 0));
+
+        if (targetPkg == null) {
+            throw new NullPointerException("targetPkg");
+        }
+
+        if (intent == null) {
+            return null;
+        }
+        Uri data = intent.getData();
+        ClipData clip = intent.getClipData();
+        if (data == null && clip == null) {
+            return null;
+        }
+        // Default userId for uris in the intent (if they don't specify it themselves)
+        int contentUserHint = intent.getContentUserHint();
+        if (contentUserHint == UserHandle.USER_CURRENT) {
+            contentUserHint = UserHandle.getUserId(callingUid);
+        }
+        final IPackageManager pm = AppGlobals.getPackageManager();
+        int targetUid;
+        if (needed != null) {
+            targetUid = needed.targetUid;
+        } else {
+            try {
+                targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING, targetUserId);
+            } catch (RemoteException ex) {
+                return null;
+            }
+            if (targetUid < 0) {
+                if (DEBUG) Slog.v(TAG, "Can't grant URI permission no uid for: " + targetPkg
+                        + " on user " + targetUserId);
+                return null;
+            }
+        }
+        if (data != null) {
+            GrantUri grantUri = GrantUri.resolve(contentUserHint, data);
+            targetUid = checkGrantUriPermission(callingUid, targetPkg, grantUri, mode, targetUid);
+            if (targetUid > 0) {
+                if (needed == null) {
+                    needed = new NeededUriGrants(targetPkg, targetUid, mode);
+                }
+                needed.add(grantUri);
+            }
+        }
+        if (clip != null) {
+            for (int i=0; i<clip.getItemCount(); i++) {
+                Uri uri = clip.getItemAt(i).getUri();
+                if (uri != null) {
+                    GrantUri grantUri = GrantUri.resolve(contentUserHint, uri);
+                    targetUid = checkGrantUriPermission(callingUid, targetPkg,
+                            grantUri, mode, targetUid);
+                    if (targetUid > 0) {
+                        if (needed == null) {
+                            needed = new NeededUriGrants(targetPkg, targetUid, mode);
+                        }
+                        needed.add(grantUri);
+                    }
+                } else {
+                    Intent clipIntent = clip.getItemAt(i).getIntent();
+                    if (clipIntent != null) {
+                        NeededUriGrants newNeeded = checkGrantUriPermissionFromIntent(
+                                callingUid, targetPkg, clipIntent, mode, needed, targetUserId);
+                        if (newNeeded != null) {
+                            needed = newNeeded;
+                        }
+                    }
+                }
+            }
+        }
+
+        return needed;
+    }
+
+    void grantUriPermissionFromIntent(int callingUid,
+            String targetPkg, Intent intent, UriPermissionOwner owner, int targetUserId) {
+        NeededUriGrants needed = checkGrantUriPermissionFromIntent(callingUid, targetPkg,
+                intent, intent != null ? intent.getFlags() : 0, null, targetUserId);
+        if (needed == null) {
+            return;
+        }
+
+        grantUriPermissionUncheckedFromIntent(needed, owner);
+    }
+
+    void readGrantedUriPermissions() {
+        if (DEBUG) Slog.v(TAG, "readGrantedUriPermissions()");
+
+        final long now = System.currentTimeMillis();
+
+        FileInputStream fis = null;
+        try {
+            fis = mGrantFile.openRead();
+            final XmlPullParser in = Xml.newPullParser();
+            in.setInput(fis, StandardCharsets.UTF_8.name());
+
+            int type;
+            while ((type = in.next()) != END_DOCUMENT) {
+                final String tag = in.getName();
+                if (type == START_TAG) {
+                    if (TAG_URI_GRANT.equals(tag)) {
+                        final int sourceUserId;
+                        final int targetUserId;
+                        final int userHandle = readIntAttribute(in,
+                                ATTR_USER_HANDLE, UserHandle.USER_NULL);
+                        if (userHandle != UserHandle.USER_NULL) {
+                            // For backwards compatibility.
+                            sourceUserId = userHandle;
+                            targetUserId = userHandle;
+                        } else {
+                            sourceUserId = readIntAttribute(in, ATTR_SOURCE_USER_ID);
+                            targetUserId = readIntAttribute(in, ATTR_TARGET_USER_ID);
+                        }
+                        final String sourcePkg = in.getAttributeValue(null, ATTR_SOURCE_PKG);
+                        final String targetPkg = in.getAttributeValue(null, ATTR_TARGET_PKG);
+                        final Uri uri = Uri.parse(in.getAttributeValue(null, ATTR_URI));
+                        final boolean prefix = readBooleanAttribute(in, ATTR_PREFIX);
+                        final int modeFlags = readIntAttribute(in, ATTR_MODE_FLAGS);
+                        final long createdTime = readLongAttribute(in, ATTR_CREATED_TIME, now);
+
+                        // Sanity check that provider still belongs to source package
+                        // Both direct boot aware and unaware packages are fine as we
+                        // will do filtering at query time to avoid multiple parsing.
+                        final ProviderInfo pi = getProviderInfo(uri.getAuthority(), sourceUserId,
+                                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
+                        if (pi != null && sourcePkg.equals(pi.packageName)) {
+                            int targetUid = -1;
+                            try {
+                                targetUid = AppGlobals.getPackageManager().getPackageUid(
+                                        targetPkg, MATCH_UNINSTALLED_PACKAGES, targetUserId);
+                            } catch (RemoteException e) {
+                            }
+                            if (targetUid != -1) {
+                                final UriPermission perm = findOrCreateUriPermission(
+                                        sourcePkg, targetPkg, targetUid,
+                                        new GrantUri(sourceUserId, uri, prefix));
+                                perm.initPersistedModes(modeFlags, createdTime);
+                            }
+                        } else {
+                            Slog.w(TAG, "Persisted grant for " + uri + " had source " + sourcePkg
+                                    + " but instead found " + pi);
+                        }
+                    }
+                }
+            }
+        } catch (FileNotFoundException e) {
+            // Missing grants is okay
+        } catch (IOException e) {
+            Slog.wtf(TAG, "Failed reading Uri grants", e);
+        } catch (XmlPullParserException e) {
+            Slog.wtf(TAG, "Failed reading Uri grants", e);
+        } finally {
+            IoUtils.closeQuietly(fis);
+        }
+    }
+
+    private UriPermission findOrCreateUriPermission(String sourcePkg,
+            String targetPkg, int targetUid, GrantUri grantUri) {
+        ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
+        if (targetUris == null) {
+            targetUris = Maps.newArrayMap();
+            mGrantedUriPermissions.put(targetUid, targetUris);
+        }
+
+        UriPermission perm = targetUris.get(grantUri);
+        if (perm == null) {
+            perm = new UriPermission(sourcePkg, targetPkg, targetUid, grantUri);
+            targetUris.put(grantUri, perm);
+        }
+
+        return perm;
+    }
+
+    private void grantUriPermissionUnchecked(int targetUid, String targetPkg, GrantUri grantUri,
+            final int modeFlags, UriPermissionOwner owner) {
+        if (!Intent.isAccessUriMode(modeFlags)) {
+            return;
+        }
+
+        // So here we are: the caller has the assumed permission to the uri, and the target doesn't.
+        // Let's now give this to the target.
+
+        if (DEBUG) Slog.v(TAG,
+                "Granting " + targetPkg + "/" + targetUid + " permission to " + grantUri);
+
+        final String authority = grantUri.uri.getAuthority();
+        final ProviderInfo pi = getProviderInfo(authority, grantUri.sourceUserId,
+                MATCH_DEBUG_TRIAGED_MISSING);
+        if (pi == null) {
+            Slog.w(TAG, "No content provider found for grant: " + grantUri.toSafeString());
+            return;
+        }
+
+        if ((modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0) {
+            grantUri.prefix = true;
+        }
+        final UriPermission perm = findOrCreateUriPermission(
+                pi.packageName, targetPkg, targetUid, grantUri);
+        perm.grantModes(modeFlags, owner);
+    }
+
+    /** Like grantUriPermissionUnchecked, but takes an Intent. */
+    void grantUriPermissionUncheckedFromIntent(NeededUriGrants needed, UriPermissionOwner owner) {
+        if (needed == null) {
+            return;
+        }
+        for (int i=0; i<needed.size(); i++) {
+            GrantUri grantUri = needed.get(i);
+            grantUriPermissionUnchecked(needed.targetUid, needed.targetPkg,
+                    grantUri, needed.flags, owner);
+        }
+    }
+
+    void grantUriPermission(int callingUid, String targetPkg, GrantUri grantUri,
+            final int modeFlags, UriPermissionOwner owner, int targetUserId) {
+        if (targetPkg == null) {
+            throw new NullPointerException("targetPkg");
+        }
+        int targetUid;
+        final IPackageManager pm = AppGlobals.getPackageManager();
+        try {
+            targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING, targetUserId);
+        } catch (RemoteException ex) {
+            return;
+        }
+
+        targetUid = checkGrantUriPermission(callingUid, targetPkg, grantUri, modeFlags, targetUid);
+        if (targetUid < 0) {
+            return;
+        }
+
+        grantUriPermissionUnchecked(targetUid, targetPkg, grantUri, modeFlags, owner);
+    }
+
+    void revokeUriPermission(String targetPackage, int callingUid, GrantUri grantUri,
+            final int modeFlags) {
+        if (DEBUG) Slog.v(TAG, "Revoking all granted permissions to " + grantUri);
+
+        final IPackageManager pm = AppGlobals.getPackageManager();
+        final String authority = grantUri.uri.getAuthority();
+        final ProviderInfo pi = getProviderInfo(authority, grantUri.sourceUserId,
+                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
+        if (pi == null) {
+            Slog.w(TAG, "No content provider found for permission revoke: "
+                    + grantUri.toSafeString());
+            return;
+        }
+
+        // Does the caller have this permission on the URI?
+        if (!checkHoldingPermissions(pm, pi, grantUri, callingUid, modeFlags)) {
+            // If they don't have direct access to the URI, then revoke any
+            // ownerless URI permissions that have been granted to them.
+            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+            if (perms != null) {
+                boolean persistChanged = false;
+                for (int i = perms.size()-1; i >= 0; i--) {
+                    final UriPermission perm = perms.valueAt(i);
+                    if (targetPackage != null && !targetPackage.equals(perm.targetPkg)) {
+                        continue;
+                    }
+                    if (perm.uri.sourceUserId == grantUri.sourceUserId
+                            && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
+                        if (DEBUG) Slog.v(TAG, "Revoking non-owned "
+                                + perm.targetUid + " permission to " + perm.uri);
+                        persistChanged |= perm.revokeModes(
+                                modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
+                        if (perm.modeFlags == 0) {
+                            perms.removeAt(i);
+                        }
+                    }
+                }
+                if (perms.isEmpty()) {
+                    mGrantedUriPermissions.remove(callingUid);
+                }
+                if (persistChanged) {
+                    schedulePersistUriGrants();
+                }
+            }
+            return;
+        }
+
+        boolean persistChanged = false;
+
+        // Go through all of the permissions and remove any that match.
+        for (int i = mGrantedUriPermissions.size()-1; i >= 0; i--) {
+            final int targetUid = mGrantedUriPermissions.keyAt(i);
+            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+
+            for (int j = perms.size()-1; j >= 0; j--) {
+                final UriPermission perm = perms.valueAt(j);
+                if (targetPackage != null && !targetPackage.equals(perm.targetPkg)) {
+                    continue;
+                }
+                if (perm.uri.sourceUserId == grantUri.sourceUserId
+                        && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
+                    if (DEBUG) Slog.v(TAG,
+                            "Revoking " + perm.targetUid + " permission to " + perm.uri);
+                    persistChanged |= perm.revokeModes(
+                            modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION,
+                            targetPackage == null);
+                    if (perm.modeFlags == 0) {
+                        perms.removeAt(j);
+                    }
+                }
+            }
+
+            if (perms.isEmpty()) {
+                mGrantedUriPermissions.removeAt(i);
+            }
+        }
+
+        if (persistChanged) {
+            schedulePersistUriGrants();
+        }
+    }
+
+    /**
+     * Determine if UID is holding permissions required to access {@link Uri} in
+     * the given {@link ProviderInfo}. Final permission checking is always done
+     * in {@link ContentProvider}.
+     */
+    private boolean checkHoldingPermissions(
+            IPackageManager pm, ProviderInfo pi, GrantUri grantUri, int uid, final int modeFlags) {
+        if (DEBUG) Slog.v(TAG, "checkHoldingPermissions: uri=" + grantUri + " uid=" + uid);
+        if (UserHandle.getUserId(uid) != grantUri.sourceUserId) {
+            if (ActivityManager.checkComponentPermission(INTERACT_ACROSS_USERS, uid, -1, true)
+                    != PERMISSION_GRANTED) {
+                return false;
+            }
+        }
+        return checkHoldingPermissionsInternal(pm, pi, grantUri, uid, modeFlags, true);
+    }
+
+    private boolean checkHoldingPermissionsInternal(IPackageManager pm, ProviderInfo pi,
+            GrantUri grantUri, int uid, final int modeFlags, boolean considerUidPermissions) {
+        if (pi.applicationInfo.uid == uid) {
+            return true;
+        } else if (!pi.exported) {
+            return false;
+        }
+
+        boolean readMet = (modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
+        boolean writeMet = (modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
+        try {
+            // check if target holds top-level <provider> permissions
+            if (!readMet && pi.readPermission != null && considerUidPermissions
+                    && (pm.checkUidPermission(pi.readPermission, uid) == PERMISSION_GRANTED)) {
+                readMet = true;
+            }
+            if (!writeMet && pi.writePermission != null && considerUidPermissions
+                    && (pm.checkUidPermission(pi.writePermission, uid) == PERMISSION_GRANTED)) {
+                writeMet = true;
+            }
+
+            // track if unprotected read/write is allowed; any denied
+            // <path-permission> below removes this ability
+            boolean allowDefaultRead = pi.readPermission == null;
+            boolean allowDefaultWrite = pi.writePermission == null;
+
+            // check if target holds any <path-permission> that match uri
+            final PathPermission[] pps = pi.pathPermissions;
+            if (pps != null) {
+                final String path = grantUri.uri.getPath();
+                int i = pps.length;
+                while (i > 0 && (!readMet || !writeMet)) {
+                    i--;
+                    PathPermission pp = pps[i];
+                    if (pp.match(path)) {
+                        if (!readMet) {
+                            final String pprperm = pp.getReadPermission();
+                            if (DEBUG) Slog.v(TAG,
+                                    "Checking read perm for " + pprperm + " for " + pp.getPath()
+                                            + ": match=" + pp.match(path)
+                                            + " check=" + pm.checkUidPermission(pprperm, uid));
+                            if (pprperm != null) {
+                                if (considerUidPermissions && pm.checkUidPermission(pprperm, uid)
+                                        == PERMISSION_GRANTED) {
+                                    readMet = true;
+                                } else {
+                                    allowDefaultRead = false;
+                                }
+                            }
+                        }
+                        if (!writeMet) {
+                            final String ppwperm = pp.getWritePermission();
+                            if (DEBUG) Slog.v(TAG,
+                                    "Checking write perm " + ppwperm + " for " + pp.getPath()
+                                            + ": match=" + pp.match(path)
+                                            + " check=" + pm.checkUidPermission(ppwperm, uid));
+                            if (ppwperm != null) {
+                                if (considerUidPermissions && pm.checkUidPermission(ppwperm, uid)
+                                        == PERMISSION_GRANTED) {
+                                    writeMet = true;
+                                } else {
+                                    allowDefaultWrite = false;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            // grant unprotected <provider> read/write, if not blocked by
+            // <path-permission> above
+            if (allowDefaultRead) readMet = true;
+            if (allowDefaultWrite) writeMet = true;
+
+        } catch (RemoteException e) {
+            return false;
+        }
+
+        return readMet && writeMet;
+    }
+
+    private void removeUriPermissionIfNeeded(UriPermission perm) {
+        if (perm.modeFlags != 0) {
+            return;
+        }
+        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
+                perm.targetUid);
+        if (perms == null) {
+            return;
+        }
+        if (DEBUG) Slog.v(TAG, "Removing " + perm.targetUid + " permission to " + perm.uri);
+
+        perms.remove(perm.uri);
+        if (perms.isEmpty()) {
+            mGrantedUriPermissions.remove(perm.targetUid);
+        }
+    }
+
+    private UriPermission findUriPermissionLocked(int targetUid, GrantUri grantUri) {
+        final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
+        if (targetUris != null) {
+            return targetUris.get(grantUri);
+        }
+        return null;
+    }
+
+    private void schedulePersistUriGrants() {
+        if (!mH.hasMessages(PERSIST_URI_GRANTS_MSG)) {
+            mH.sendMessageDelayed(mH.obtainMessage(PERSIST_URI_GRANTS_MSG),
+                    10 * DateUtils.SECOND_IN_MILLIS);
+        }
+    }
+
+    private void enforceNotIsolatedCaller(String caller) {
+        if (UserHandle.isIsolated(Binder.getCallingUid())) {
+            throw new SecurityException("Isolated process not allowed to call " + caller);
+        }
+    }
+
+    private ProviderInfo getProviderInfo(String authority, int userHandle, int pmFlags) {
+        ProviderInfo pi = null;
+        try {
+            pi = AppGlobals.getPackageManager().resolveContentProvider(
+                    authority, PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags,
+                    userHandle);
+        } catch (RemoteException ex) {
+        }
+        return pi;
+    }
+
+    /**
+     * Check if the targetPkg can be granted permission to access uri by
+     * the callingUid using the given modeFlags.  Throws a security exception
+     * if callingUid is not allowed to do this.  Returns the uid of the target
+     * if the URI permission grant should be performed; returns -1 if it is not
+     * needed (for example targetPkg already has permission to access the URI).
+     * If you already know the uid of the target, you can supply it in
+     * lastTargetUid else set that to -1.
+     */
+    int checkGrantUriPermission(int callingUid, String targetPkg, GrantUri grantUri,
+            final int modeFlags, int lastTargetUid) {
+        if (!Intent.isAccessUriMode(modeFlags)) {
+            return -1;
+        }
+
+        if (targetPkg != null) {
+            if (DEBUG) Slog.v(TAG, "Checking grant " + targetPkg + " permission to " + grantUri);
+        }
+
+        final IPackageManager pm = AppGlobals.getPackageManager();
+
+        // If this is not a content: uri, we can't do anything with it.
+        if (!ContentResolver.SCHEME_CONTENT.equals(grantUri.uri.getScheme())) {
+            if (DEBUG) Slog.v(TAG, "Can't grant URI permission for non-content URI: " + grantUri);
+            return -1;
+        }
+
+        // Bail early if system is trying to hand out permissions directly; it
+        // must always grant permissions on behalf of someone explicit.
+        final int callingAppId = UserHandle.getAppId(callingUid);
+        if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
+            if ("com.android.settings.files".equals(grantUri.uri.getAuthority())) {
+                // Exempted authority for
+                // 1. cropping user photos and sharing a generated license html
+                //    file in Settings app
+                // 2. sharing a generated license html file in TvSettings app
+            } else {
+                Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"
+                        + " grant to " + grantUri + "; use startActivityAsCaller() instead");
+                return -1;
+            }
+        }
+
+        final String authority = grantUri.uri.getAuthority();
+        final ProviderInfo pi = getProviderInfo(authority, grantUri.sourceUserId,
+                MATCH_DEBUG_TRIAGED_MISSING);
+        if (pi == null) {
+            Slog.w(TAG, "No content provider found for permission check: " +
+                    grantUri.uri.toSafeString());
+            return -1;
+        }
+
+        int targetUid = lastTargetUid;
+        if (targetUid < 0 && targetPkg != null) {
+            try {
+                targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
+                        UserHandle.getUserId(callingUid));
+                if (targetUid < 0) {
+                    if (DEBUG) Slog.v(TAG, "Can't grant URI permission no uid for: " + targetPkg);
+                    return -1;
+                }
+            } catch (RemoteException ex) {
+                return -1;
+            }
+        }
+
+        // Figure out the value returned when access is allowed
+        final int allowedResult;
+        if ((modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) {
+            // If we're extending a persistable grant, then we need to return
+            // "targetUid" so that we always create a grant data structure to
+            // support take/release APIs
+            allowedResult = targetUid;
+        } else {
+            // Otherwise, we can return "-1" to indicate that no grant data
+            // structures need to be created
+            allowedResult = -1;
+        }
+
+        if (targetUid >= 0) {
+            // First...  does the target actually need this permission?
+            if (checkHoldingPermissions(pm, pi, grantUri, targetUid, modeFlags)) {
+                // No need to grant the target this permission.
+                if (DEBUG) Slog.v(TAG,
+                        "Target " + targetPkg + " already has full permission to " + grantUri);
+                return allowedResult;
+            }
+        } else {
+            // First...  there is no target package, so can anyone access it?
+            boolean allowed = pi.exported;
+            if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+                if (pi.readPermission != null) {
+                    allowed = false;
+                }
+            }
+            if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+                if (pi.writePermission != null) {
+                    allowed = false;
+                }
+            }
+            if (pi.pathPermissions != null) {
+                final int N = pi.pathPermissions.length;
+                for (int i=0; i<N; i++) {
+                    if (pi.pathPermissions[i] != null
+                            && pi.pathPermissions[i].match(grantUri.uri.getPath())) {
+                        if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+                            if (pi.pathPermissions[i].getReadPermission() != null) {
+                                allowed = false;
+                            }
+                        }
+                        if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+                            if (pi.pathPermissions[i].getWritePermission() != null) {
+                                allowed = false;
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            if (allowed) {
+                return allowedResult;
+            }
+        }
+
+        /* There is a special cross user grant if:
+         * - The target is on another user.
+         * - Apps on the current user can access the uri without any uid permissions.
+         * In this case, we grant a uri permission, even if the ContentProvider does not normally
+         * grant uri permissions.
+         */
+        boolean specialCrossUserGrant = UserHandle.getUserId(targetUid) != grantUri.sourceUserId
+                && checkHoldingPermissionsInternal(pm, pi, grantUri, callingUid,
+                modeFlags, false /*without considering the uid permissions*/);
+
+        // Second...  is the provider allowing granting of URI permissions?
+        if (!specialCrossUserGrant) {
+            if (!pi.grantUriPermissions) {
+                throw new SecurityException("Provider " + pi.packageName
+                        + "/" + pi.name
+                        + " does not allow granting of Uri permissions (uri "
+                        + grantUri + ")");
+            }
+            if (pi.uriPermissionPatterns != null) {
+                final int N = pi.uriPermissionPatterns.length;
+                boolean allowed = false;
+                for (int i=0; i<N; i++) {
+                    if (pi.uriPermissionPatterns[i] != null
+                            && pi.uriPermissionPatterns[i].match(grantUri.uri.getPath())) {
+                        allowed = true;
+                        break;
+                    }
+                }
+                if (!allowed) {
+                    throw new SecurityException("Provider " + pi.packageName
+                            + "/" + pi.name
+                            + " does not allow granting of permission to path of Uri "
+                            + grantUri);
+                }
+            }
+        }
+
+        // Third...  does the caller itself have permission to access this uri?
+        if (!checkHoldingPermissions(pm, pi, grantUri, callingUid, modeFlags)) {
+            // Require they hold a strong enough Uri permission
+            if (!checkUriPermission(grantUri, callingUid, modeFlags)) {
+                if (android.Manifest.permission.MANAGE_DOCUMENTS.equals(pi.readPermission)) {
+                    throw new SecurityException(
+                            "UID " + callingUid + " does not have permission to " + grantUri
+                                    + "; you could obtain access using ACTION_OPEN_DOCUMENT "
+                                    + "or related APIs");
+                } else {
+                    throw new SecurityException(
+                            "UID " + callingUid + " does not have permission to " + grantUri);
+                }
+            }
+        }
+        return targetUid;
+    }
+
+    /**
+     * @param userId The userId in which the uri is to be resolved.
+     */
+    int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri, int modeFlags,
+            int userId) {
+        return checkGrantUriPermission(callingUid, targetPkg,
+                new GrantUri(userId, uri, false), modeFlags, -1);
+    }
+
+    boolean checkUriPermission(GrantUri grantUri, int uid, final int modeFlags) {
+        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+        final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
+                : UriPermission.STRENGTH_OWNED;
+
+        // Root gets to do everything.
+        if (uid == 0) {
+            return true;
+        }
+
+        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
+        if (perms == null) return false;
+
+        // First look for exact match
+        final UriPermission exactPerm = perms.get(grantUri);
+        if (exactPerm != null && exactPerm.getStrength(modeFlags) >= minStrength) {
+            return true;
+        }
+
+        // No exact match, look for prefixes
+        final int N = perms.size();
+        for (int i = 0; i < N; i++) {
+            final UriPermission perm = perms.valueAt(i);
+            if (perm.uri.prefix && grantUri.uri.isPathPrefixMatch(perm.uri.uri)
+                    && perm.getStrength(modeFlags) >= minStrength) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private void writeGrantedUriPermissions() {
+        if (DEBUG) Slog.v(TAG, "writeGrantedUriPermissions()");
+
+        final long startTime = SystemClock.uptimeMillis();
+
+        // Snapshot permissions so we can persist without lock
+        ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
+        synchronized (this) {
+            final int size = mGrantedUriPermissions.size();
+            for (int i = 0; i < size; i++) {
+                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+                for (UriPermission perm : perms.values()) {
+                    if (perm.persistedModeFlags != 0) {
+                        persist.add(perm.snapshot());
+                    }
+                }
+            }
+        }
+
+        FileOutputStream fos = null;
+        try {
+            fos = mGrantFile.startWrite(startTime);
+
+            XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
+            out.startDocument(null, true);
+            out.startTag(null, TAG_URI_GRANTS);
+            for (UriPermission.Snapshot perm : persist) {
+                out.startTag(null, TAG_URI_GRANT);
+                writeIntAttribute(out, ATTR_SOURCE_USER_ID, perm.uri.sourceUserId);
+                writeIntAttribute(out, ATTR_TARGET_USER_ID, perm.targetUserId);
+                out.attribute(null, ATTR_SOURCE_PKG, perm.sourcePkg);
+                out.attribute(null, ATTR_TARGET_PKG, perm.targetPkg);
+                out.attribute(null, ATTR_URI, String.valueOf(perm.uri.uri));
+                writeBooleanAttribute(out, ATTR_PREFIX, perm.uri.prefix);
+                writeIntAttribute(out, ATTR_MODE_FLAGS, perm.persistedModeFlags);
+                writeLongAttribute(out, ATTR_CREATED_TIME, perm.persistedCreateTime);
+                out.endTag(null, TAG_URI_GRANT);
+            }
+            out.endTag(null, TAG_URI_GRANTS);
+            out.endDocument();
+
+            mGrantFile.finishWrite(fos);
+        } catch (IOException e) {
+            if (fos != null) {
+                mGrantFile.failWrite(fos);
+            }
+        }
+    }
+
+    private PackageManagerInternal getPmInternal() {
+        // Don't need to synchonize; worst-case scenario LocalServices will be called twice.
+        if (mPmInternal == null) {
+            mPmInternal = LocalServices.getService(PackageManagerInternal.class);
+        }
+        return mPmInternal;
+    }
+
+    final class H extends Handler {
+        static final int PERSIST_URI_GRANTS_MSG = 1;
+
+        public H(Looper looper) {
+            super(looper, null, true);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case PERSIST_URI_GRANTS_MSG: {
+                    writeGrantedUriPermissions();
+                    break;
+                }
+            }
+        }
+    }
+
+    final class LocalService implements UriGrantsManagerInternal {
+
+        @Override
+        public void removeUriPermissionIfNeeded(UriPermission perm) {
+            synchronized (mLock) {
+                UriGrantsManagerService.this.removeUriPermissionIfNeeded(perm);
+            }
+        }
+
+        @Override
+        public void grantUriPermission(int callingUid, String targetPkg, GrantUri grantUri,
+                int modeFlags, UriPermissionOwner owner, int targetUserId) {
+            synchronized (mLock) {
+                UriGrantsManagerService.this.grantUriPermission(
+                        callingUid, targetPkg, grantUri, modeFlags, owner, targetUserId);
+            }
+        }
+
+        @Override
+        public void revokeUriPermission(String targetPackage, int callingUid, GrantUri grantUri,
+                int modeFlags) {
+            synchronized (mLock) {
+                UriGrantsManagerService.this.revokeUriPermission(
+                        targetPackage, callingUid, grantUri, modeFlags);
+            }
+        }
+
+        @Override
+        public boolean checkUriPermission(GrantUri grantUri, int uid, int modeFlags) {
+            synchronized (mLock) {
+                return UriGrantsManagerService.this.checkUriPermission(grantUri, uid, modeFlags);
+            }
+        }
+
+        @Override
+        public int checkGrantUriPermission(int callingUid, String targetPkg, GrantUri uri,
+                int modeFlags, int userId) {
+            synchronized (mLock) {
+                return UriGrantsManagerService.this.checkGrantUriPermission(
+                        callingUid, targetPkg, uri, modeFlags, userId);
+            }
+        }
+
+        @Override
+        public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri, int modeFlags,
+                int userId) {
+            enforceNotIsolatedCaller("checkGrantUriPermission");
+            synchronized (mLock) {
+                return UriGrantsManagerService.this.checkGrantUriPermission(
+                        callingUid, targetPkg, uri, modeFlags, userId);
+            }
+        }
+
+        @Override
+        public NeededUriGrants checkGrantUriPermissionFromIntent(int callingUid, String targetPkg,
+                Intent intent, int mode, NeededUriGrants needed, int targetUserId) {
+            synchronized (mLock) {
+                return UriGrantsManagerService.this.checkGrantUriPermissionFromIntent(
+                        callingUid, targetPkg, intent, mode, needed, targetUserId);
+            }
+        }
+
+        @Override
+        public void grantUriPermissionFromIntent(int callingUid, String targetPkg, Intent intent,
+                int targetUserId) {
+            synchronized (mLock) {
+                UriGrantsManagerService.this.grantUriPermissionFromIntent(
+                        callingUid, targetPkg, intent, null, targetUserId);
+            }
+        }
+
+        @Override
+        public void grantUriPermissionFromIntent(int callingUid, String targetPkg, Intent intent,
+                UriPermissionOwner owner, int targetUserId) {
+            synchronized (mLock) {
+                UriGrantsManagerService.this.grantUriPermissionFromIntent(
+                        callingUid, targetPkg, intent, owner, targetUserId);
+            }
+        }
+
+        @Override
+        public void grantUriPermissionUncheckedFromIntent(NeededUriGrants needed,
+                UriPermissionOwner owner) {
+            synchronized (mLock) {
+                UriGrantsManagerService.this.grantUriPermissionUncheckedFromIntent(needed, owner);
+            }
+        }
+
+        @Override
+        public void onSystemReady() {
+            synchronized (mLock) {
+                UriGrantsManagerService.this.readGrantedUriPermissions();
+            }
+        }
+
+        @Override
+        public void onActivityManagerInternalAdded() {
+            synchronized (mLock) {
+                UriGrantsManagerService.this.onActivityManagerInternalAdded();
+            }
+        }
+
+        @Override
+        public IBinder newUriPermissionOwner(String name) {
+            enforceNotIsolatedCaller("newUriPermissionOwner");
+            synchronized(mLock) {
+                UriPermissionOwner owner = new UriPermissionOwner(this, name);
+                return owner.getExternalToken();
+            }
+        }
+
+        @Override
+        public void removeUriPermissionsForPackage(String packageName, int userHandle,
+                boolean persistable, boolean targetOnly) {
+            synchronized(mLock) {
+                UriGrantsManagerService.this.removeUriPermissionsForPackage(
+                        packageName, userHandle, persistable, targetOnly);
+            }
+        }
+
+        @Override
+        public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId) {
+            synchronized(mLock) {
+                final UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
+                if (owner == null) {
+                    throw new IllegalArgumentException("Unknown owner: " + token);
+                }
+
+                if (uri == null) {
+                    owner.removeUriPermissions(mode);
+                } else {
+                    final boolean prefix = (mode & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0;
+                    owner.removeUriPermission(new GrantUri(userId, uri, prefix), mode);
+                }
+            }
+        }
+
+        @Override
+        public boolean checkAuthorityGrants(int callingUid, ProviderInfo cpi, int userId,
+                boolean checkUser) {
+            synchronized(mLock) {
+                return UriGrantsManagerService.this.checkAuthorityGrants(
+                        callingUid, cpi, userId, checkUser);
+            }
+        }
+
+        @Override
+        public void dump(PrintWriter pw, boolean dumpAll, String dumpPackage) {
+            synchronized(mLock) {
+                boolean needSep = false;
+                boolean printedAnything = false;
+                if (mGrantedUriPermissions.size() > 0) {
+                    boolean printed = false;
+                    int dumpUid = -2;
+                    if (dumpPackage != null) {
+                        try {
+                            dumpUid = mContext.getPackageManager().getPackageUidAsUser(dumpPackage,
+                                    MATCH_ANY_USER, 0);
+                        } catch (PackageManager.NameNotFoundException e) {
+                            dumpUid = -1;
+                        }
+                    }
+                    for (int i = 0; i < mGrantedUriPermissions.size(); i++) {
+                        int uid = mGrantedUriPermissions.keyAt(i);
+                        if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) {
+                            continue;
+                        }
+                        final ArrayMap<GrantUri, UriPermission> perms =
+                                mGrantedUriPermissions.valueAt(i);
+                        if (!printed) {
+                            if (needSep) pw.println();
+                            needSep = true;
+                            pw.println("  Granted Uri Permissions:");
+                            printed = true;
+                            printedAnything = true;
+                        }
+                        pw.print("  * UID "); pw.print(uid); pw.println(" holds:");
+                        for (UriPermission perm : perms.values()) {
+                            pw.print("    "); pw.println(perm);
+                            if (dumpAll) {
+                                perm.dump(pw, "      ");
+                            }
+                        }
+                    }
+                }
+
+                if (!printedAnything) {
+                    pw.println("  (nothing)");
+                }
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/uri/UriPermission.java b/services/core/java/com/android/server/uri/UriPermission.java
new file mode 100644
index 0000000..bd6348a
--- /dev/null
+++ b/services/core/java/com/android/server/uri/UriPermission.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.uri;
+
+import android.app.GrantedUriPermission;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+
+import com.google.android.collect.Sets;
+
+import java.io.PrintWriter;
+import java.util.Comparator;
+
+/**
+ * Description of a permission granted to an app to access a particular URI.
+ *
+ * CTS tests for this functionality can be run with "runtest cts-appsecurity".
+ *
+ * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
+ *      src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+ */
+final class UriPermission {
+    private static final String TAG = "UriPermission";
+
+    public static final int STRENGTH_NONE = 0;
+    public static final int STRENGTH_OWNED = 1;
+    public static final int STRENGTH_GLOBAL = 2;
+    public static final int STRENGTH_PERSISTABLE = 3;
+
+    final int targetUserId;
+    final String sourcePkg;
+    final String targetPkg;
+
+    /** Cached UID of {@link #targetPkg}; should not be persisted */
+    final int targetUid;
+
+    final GrantUri uri;
+
+    /**
+     * Allowed modes. All permission enforcement should use this field. Must
+     * always be a combination of {@link #ownedModeFlags},
+     * {@link #globalModeFlags}, {@link #persistableModeFlags}, and
+     * {@link #persistedModeFlags}. Mutations <em>must</em> only be performed by
+     * the owning class.
+     */
+    int modeFlags = 0;
+
+    /** Allowed modes with active owner. */
+    int ownedModeFlags = 0;
+    /** Allowed modes without explicit owner. */
+    int globalModeFlags = 0;
+    /** Allowed modes that have been offered for possible persisting. */
+    int persistableModeFlags = 0;
+
+    /** Allowed modes that should be persisted across device boots. */
+    int persistedModeFlags = 0;
+
+    /**
+     * Timestamp when {@link #persistedModeFlags} was first defined in
+     * {@link System#currentTimeMillis()} time base.
+     */
+    long persistedCreateTime = INVALID_TIME;
+
+    private static final long INVALID_TIME = Long.MIN_VALUE;
+
+    private ArraySet<UriPermissionOwner> mReadOwners;
+    private ArraySet<UriPermissionOwner> mWriteOwners;
+
+    private String stringName;
+
+    UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) {
+        this.targetUserId = UserHandle.getUserId(targetUid);
+        this.sourcePkg = sourcePkg;
+        this.targetPkg = targetPkg;
+        this.targetUid = targetUid;
+        this.uri = uri;
+    }
+
+    private void updateModeFlags() {
+        final int oldModeFlags = modeFlags;
+        modeFlags = ownedModeFlags | globalModeFlags | persistableModeFlags | persistedModeFlags;
+
+        if (Log.isLoggable(TAG, Log.VERBOSE) && (modeFlags != oldModeFlags)) {
+            Slog.d(TAG,
+                    "Permission for " + targetPkg + " to " + uri + " is changing from 0x"
+                            + Integer.toHexString(oldModeFlags) + " to 0x"
+                            + Integer.toHexString(modeFlags) + " via calling UID "
+                            + Binder.getCallingUid() + " PID " + Binder.getCallingPid(),
+                    new Throwable());
+        }
+    }
+
+    /**
+     * Initialize persisted modes as read from file. This doesn't issue any
+     * global or owner grants.
+     */
+    void initPersistedModes(int modeFlags, long createdTime) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        persistableModeFlags = modeFlags;
+        persistedModeFlags = modeFlags;
+        persistedCreateTime = createdTime;
+
+        updateModeFlags();
+    }
+
+    void grantModes(int modeFlags, UriPermissionOwner owner) {
+        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        if (persistable) {
+            persistableModeFlags |= modeFlags;
+        }
+
+        if (owner == null) {
+            globalModeFlags |= modeFlags;
+        } else {
+            if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+                addReadOwner(owner);
+            }
+            if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+                addWriteOwner(owner);
+            }
+        }
+
+        updateModeFlags();
+    }
+
+    /**
+     * @return if mode changes should trigger persisting.
+     */
+    boolean takePersistableModes(int modeFlags) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        if ((modeFlags & persistableModeFlags) != modeFlags) {
+            Slog.w(TAG, "Requested flags 0x"
+                    + Integer.toHexString(modeFlags) + ", but only 0x"
+                    + Integer.toHexString(persistableModeFlags) + " are allowed");
+            return false;
+        }
+
+        final int before = persistedModeFlags;
+        persistedModeFlags |= (persistableModeFlags & modeFlags);
+
+        if (persistedModeFlags != 0) {
+            persistedCreateTime = System.currentTimeMillis();
+        }
+
+        updateModeFlags();
+        return persistedModeFlags != before;
+    }
+
+    boolean releasePersistableModes(int modeFlags) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        final int before = persistedModeFlags;
+
+        persistableModeFlags &= ~modeFlags;
+        persistedModeFlags &= ~modeFlags;
+
+        if (persistedModeFlags == 0) {
+            persistedCreateTime = INVALID_TIME;
+        }
+
+        updateModeFlags();
+        return persistedModeFlags != before;
+    }
+
+    /**
+     * @return if mode changes should trigger persisting.
+     */
+    boolean revokeModes(int modeFlags, boolean includingOwners) {
+        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        final int before = persistedModeFlags;
+
+        if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+            if (persistable) {
+                persistableModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+                persistedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+            }
+            globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+            if (mReadOwners != null && includingOwners) {
+                ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+                for (UriPermissionOwner r : mReadOwners) {
+                    r.removeReadPermission(this);
+                }
+                mReadOwners = null;
+            }
+        }
+        if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+            if (persistable) {
+                persistableModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+                persistedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+            }
+            globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+            if (mWriteOwners != null && includingOwners) {
+                ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+                for (UriPermissionOwner r : mWriteOwners) {
+                    r.removeWritePermission(this);
+                }
+                mWriteOwners = null;
+            }
+        }
+
+        if (persistedModeFlags == 0) {
+            persistedCreateTime = INVALID_TIME;
+        }
+
+        updateModeFlags();
+        return persistedModeFlags != before;
+    }
+
+    /**
+     * Return strength of this permission grant for the given flags.
+     */
+    public int getStrength(int modeFlags) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        if ((persistableModeFlags & modeFlags) == modeFlags) {
+            return STRENGTH_PERSISTABLE;
+        } else if ((globalModeFlags & modeFlags) == modeFlags) {
+            return STRENGTH_GLOBAL;
+        } else if ((ownedModeFlags & modeFlags) == modeFlags) {
+            return STRENGTH_OWNED;
+        } else {
+            return STRENGTH_NONE;
+        }
+    }
+
+    private void addReadOwner(UriPermissionOwner owner) {
+        if (mReadOwners == null) {
+            mReadOwners = Sets.newArraySet();
+            ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
+            updateModeFlags();
+        }
+        if (mReadOwners.add(owner)) {
+            owner.addReadPermission(this);
+        }
+    }
+
+    /**
+     * Remove given read owner, updating {@Link #modeFlags} as needed.
+     */
+    void removeReadOwner(UriPermissionOwner owner) {
+        if (!mReadOwners.remove(owner)) {
+            Slog.wtf(TAG, "Unknown read owner " + owner + " in " + this);
+        }
+        if (mReadOwners.size() == 0) {
+            mReadOwners = null;
+            ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+            updateModeFlags();
+        }
+    }
+
+    private void addWriteOwner(UriPermissionOwner owner) {
+        if (mWriteOwners == null) {
+            mWriteOwners = Sets.newArraySet();
+            ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+            updateModeFlags();
+        }
+        if (mWriteOwners.add(owner)) {
+            owner.addWritePermission(this);
+        }
+    }
+
+    /**
+     * Remove given write owner, updating {@Link #modeFlags} as needed.
+     */
+    void removeWriteOwner(UriPermissionOwner owner) {
+        if (!mWriteOwners.remove(owner)) {
+            Slog.wtf(TAG, "Unknown write owner " + owner + " in " + this);
+        }
+        if (mWriteOwners.size() == 0) {
+            mWriteOwners = null;
+            ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+            updateModeFlags();
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("UriPermission{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(uri);
+        sb.append('}');
+        return stringName = sb.toString();
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix);
+        pw.print("targetUserId=" + targetUserId);
+        pw.print(" sourcePkg=" + sourcePkg);
+        pw.println(" targetPkg=" + targetPkg);
+
+        pw.print(prefix);
+        pw.print("mode=0x" + Integer.toHexString(modeFlags));
+        pw.print(" owned=0x" + Integer.toHexString(ownedModeFlags));
+        pw.print(" global=0x" + Integer.toHexString(globalModeFlags));
+        pw.print(" persistable=0x" + Integer.toHexString(persistableModeFlags));
+        pw.print(" persisted=0x" + Integer.toHexString(persistedModeFlags));
+        if (persistedCreateTime != INVALID_TIME) {
+            pw.print(" persistedCreate=" + persistedCreateTime);
+        }
+        pw.println();
+
+        if (mReadOwners != null) {
+            pw.print(prefix);
+            pw.println("readOwners:");
+            for (UriPermissionOwner owner : mReadOwners) {
+                pw.print(prefix);
+                pw.println("  * " + owner);
+            }
+        }
+        if (mWriteOwners != null) {
+            pw.print(prefix);
+            pw.println("writeOwners:");
+            for (UriPermissionOwner owner : mReadOwners) {
+                pw.print(prefix);
+                pw.println("  * " + owner);
+            }
+        }
+    }
+
+    public static class PersistedTimeComparator implements Comparator<UriPermission> {
+        @Override
+        public int compare(UriPermission lhs, UriPermission rhs) {
+            return Long.compare(lhs.persistedCreateTime, rhs.persistedCreateTime);
+        }
+    }
+
+    /**
+     * Snapshot of {@link UriPermission} with frozen
+     * {@link UriPermission#persistedModeFlags} state.
+     */
+    public static class Snapshot {
+        final int targetUserId;
+        final String sourcePkg;
+        final String targetPkg;
+        final GrantUri uri;
+        final int persistedModeFlags;
+        final long persistedCreateTime;
+
+        private Snapshot(UriPermission perm) {
+            this.targetUserId = perm.targetUserId;
+            this.sourcePkg = perm.sourcePkg;
+            this.targetPkg = perm.targetPkg;
+            this.uri = perm.uri;
+            this.persistedModeFlags = perm.persistedModeFlags;
+            this.persistedCreateTime = perm.persistedCreateTime;
+        }
+    }
+
+    public Snapshot snapshot() {
+        return new Snapshot(this);
+    }
+
+    public android.content.UriPermission buildPersistedPublicApiObject() {
+        return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime);
+    }
+
+    public GrantedUriPermission buildGrantedUriPermission() {
+        return new GrantedUriPermission(uri.uri, targetPkg);
+    }
+}
diff --git a/services/core/java/com/android/server/uri/UriPermissionOwner.java b/services/core/java/com/android/server/uri/UriPermissionOwner.java
new file mode 100644
index 0000000..f814dc6
--- /dev/null
+++ b/services/core/java/com/android/server/uri/UriPermissionOwner.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.uri;
+
+import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
+import static android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.util.ArraySet;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.am.UriPermissionOwnerProto;
+import com.google.android.collect.Sets;
+
+import java.io.PrintWriter;
+import java.util.Iterator;
+
+public class UriPermissionOwner {
+    private final UriGrantsManagerInternal mService;
+    private final Object mOwner;
+
+    private Binder externalToken;
+
+    private ArraySet<UriPermission> mReadPerms;
+    private ArraySet<UriPermission> mWritePerms;
+
+    class ExternalToken extends Binder {
+        UriPermissionOwner getOwner() {
+            return UriPermissionOwner.this;
+        }
+    }
+
+    public UriPermissionOwner(UriGrantsManagerInternal service, Object owner) {
+        mService = service;
+        mOwner = owner;
+    }
+
+    public Binder getExternalToken() {
+        if (externalToken == null) {
+            externalToken = new ExternalToken();
+        }
+        return externalToken;
+    }
+
+    static UriPermissionOwner fromExternalToken(IBinder token) {
+        if (token instanceof ExternalToken) {
+            return ((ExternalToken)token).getOwner();
+        }
+        return null;
+    }
+
+    public void removeUriPermissions() {
+        removeUriPermissions(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
+    }
+
+    void removeUriPermissions(int mode) {
+        removeUriPermission(null, mode);
+    }
+
+    void removeUriPermission(GrantUri grantUri, int mode) {
+        if ((mode & FLAG_GRANT_READ_URI_PERMISSION) != 0 && mReadPerms != null) {
+            Iterator<UriPermission> it = mReadPerms.iterator();
+            while (it.hasNext()) {
+                UriPermission perm = it.next();
+                if (grantUri == null || grantUri.equals(perm.uri)) {
+                    perm.removeReadOwner(this);
+                    mService.removeUriPermissionIfNeeded(perm);
+                    it.remove();
+                }
+            }
+            if (mReadPerms.isEmpty()) {
+                mReadPerms = null;
+            }
+        }
+        if ((mode & FLAG_GRANT_WRITE_URI_PERMISSION) != 0
+                && mWritePerms != null) {
+            Iterator<UriPermission> it = mWritePerms.iterator();
+            while (it.hasNext()) {
+                UriPermission perm = it.next();
+                if (grantUri == null || grantUri.equals(perm.uri)) {
+                    perm.removeWriteOwner(this);
+                    mService.removeUriPermissionIfNeeded(perm);
+                    it.remove();
+                }
+            }
+            if (mWritePerms.isEmpty()) {
+                mWritePerms = null;
+            }
+        }
+    }
+
+    public void addReadPermission(UriPermission perm) {
+        if (mReadPerms == null) {
+            mReadPerms = Sets.newArraySet();
+        }
+        mReadPerms.add(perm);
+    }
+
+    public void addWritePermission(UriPermission perm) {
+        if (mWritePerms == null) {
+            mWritePerms = Sets.newArraySet();
+        }
+        mWritePerms.add(perm);
+    }
+
+    public void removeReadPermission(UriPermission perm) {
+        mReadPerms.remove(perm);
+        if (mReadPerms.isEmpty()) {
+            mReadPerms = null;
+        }
+    }
+
+    public void removeWritePermission(UriPermission perm) {
+        mWritePerms.remove(perm);
+        if (mWritePerms.isEmpty()) {
+            mWritePerms = null;
+        }
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        if (mReadPerms != null) {
+            pw.print(prefix); pw.print("readUriPermissions="); pw.println(mReadPerms);
+        }
+        if (mWritePerms != null) {
+            pw.print(prefix); pw.print("writeUriPermissions="); pw.println(mWritePerms);
+        }
+    }
+
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        long token = proto.start(fieldId);
+        proto.write(UriPermissionOwnerProto.OWNER, mOwner.toString());
+        if (mReadPerms != null) {
+            synchronized (mReadPerms) {
+                for (UriPermission p : mReadPerms) {
+                    p.uri.writeToProto(proto, UriPermissionOwnerProto.READ_PERMS);
+                }
+            }
+        }
+        if (mWritePerms != null) {
+            synchronized (mWritePerms) {
+                for (UriPermission p : mWritePerms) {
+                    p.uri.writeToProto(proto, UriPermissionOwnerProto.WRITE_PERMS);
+                }
+            }
+        }
+        proto.end(token);
+    }
+
+    @Override
+    public String toString() {
+        return mOwner.toString();
+    }
+}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 547ab0e..c8bd211 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -51,7 +51,6 @@
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
-import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapRegionDecoder;
@@ -76,7 +75,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.service.wallpaper.IWallpaperConnection;
 import android.service.wallpaper.IWallpaperEngine;
 import android.service.wallpaper.IWallpaperService;
@@ -338,102 +336,6 @@
         }
     }
 
-    /**
-     * Observes changes of theme settings. It will check whether to call
-     * notifyWallpaperColorsChanged by the current theme and updated theme.
-     * The light theme and dark theme are controlled by the hint values in Wallpaper colors,
-     * threrfore, if light theme mode is chosen, HINT_SUPPORTS_DARK_THEME in hint will be
-     * removed and then notify listeners.
-     */
-    private class ThemeSettingsObserver extends ContentObserver {
-
-        public ThemeSettingsObserver(Handler handler) {
-            super(handler);
-        }
-
-        public void startObserving(Context context) {
-            context.getContentResolver().registerContentObserver(
-                    Settings.Secure.getUriFor(Settings.Secure.THEME_MODE),
-                    false,
-                    this);
-        }
-
-        public void stopObserving(Context context) {
-            context.getContentResolver().unregisterContentObserver(this);
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            onThemeSettingsChanged();
-        }
-    }
-
-    /**
-     * Check whether to call notifyWallpaperColorsChanged. Assumed that the theme mode
-     * was wallpaper theme mode and dark wallpaper was set, therefoe, the theme was dark.
-     * Then theme mode changing to dark theme mode, however, theme should not update since
-     * theme was dark already.
-     */
-    private boolean needUpdateLocked(WallpaperColors colors, int themeMode) {
-        if (colors == null) {
-            return false;
-        }
-
-        if (themeMode == mThemeMode) {
-            return false;
-        }
-
-        boolean result = true;
-        boolean supportDarkTheme =
-                (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
-        switch (themeMode) {
-            case Settings.Secure.THEME_MODE_WALLPAPER:
-                if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) {
-                    result = supportDarkTheme;
-                } else {
-                    result = !supportDarkTheme;
-                }
-                break;
-            case Settings.Secure.THEME_MODE_LIGHT:
-                if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) {
-                    result = supportDarkTheme;
-                }
-                break;
-            case Settings.Secure.THEME_MODE_DARK:
-                if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) {
-                    result = !supportDarkTheme;
-                }
-                break;
-            default:
-                Slog.w(TAG, "unkonwn theme mode " + themeMode);
-                return false;
-        }
-        mThemeMode = themeMode;
-        return result;
-    }
-
-    void onThemeSettingsChanged() {
-        WallpaperData wallpaper;
-        synchronized (mLock) {
-            wallpaper = mWallpaperMap.get(mCurrentUserId);
-            int updatedThemeMode = Settings.Secure.getInt(
-                    mContext.getContentResolver(), Settings.Secure.THEME_MODE,
-                    Settings.Secure.THEME_MODE_WALLPAPER);
-
-            if (DEBUG) {
-                Slog.v(TAG, "onThemeSettingsChanged, mode = " + updatedThemeMode);
-            }
-
-            if (!needUpdateLocked(wallpaper.primaryColors, updatedThemeMode)) {
-                return;
-            }
-        }
-
-        if (wallpaper != null) {
-            notifyWallpaperColorsChanged(wallpaper, FLAG_SYSTEM);
-        }
-    }
-
     void notifyLockWallpaperChanged() {
         final IWallpaperManagerCallback cb = mKeyguardListener;
         if (cb != null) {
@@ -511,7 +413,6 @@
                 }
                 userAllColorListeners.finishBroadcast();
             }
-            wallpaperColors = getThemeColorsLocked(wallpaperColors);
         }
 
         final int count = colorListeners.size();
@@ -580,40 +481,6 @@
     }
 
     /**
-     * We can easily change theme by modified colors hint. This function will check
-     * current theme mode and return the WallpaperColors fit current theme mode.
-     * If color need modified, it will return a copied WallpaperColors which
-     * its ColorsHint is modified to fit current theme mode.
-     *
-     * @param colors a wallpaper primary colors representation
-     */
-    private WallpaperColors getThemeColorsLocked(WallpaperColors colors) {
-        if (colors == null) {
-            Slog.w(TAG, "Cannot get theme colors because WallpaperColors is null.");
-            return null;
-        }
-
-        int colorHints = colors.getColorHints();
-        boolean supportDarkTheme = (colorHints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
-        if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER ||
-                (mThemeMode == Settings.Secure.THEME_MODE_LIGHT && !supportDarkTheme) ||
-                (mThemeMode == Settings.Secure.THEME_MODE_DARK && supportDarkTheme)) {
-            return colors;
-        }
-
-        WallpaperColors themeColors = new WallpaperColors(colors.getPrimaryColor(),
-                colors.getSecondaryColor(), colors.getTertiaryColor());
-
-        if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) {
-            colorHints &= ~WallpaperColors.HINT_SUPPORTS_DARK_THEME;
-        } else if (mThemeMode == Settings.Secure.THEME_MODE_DARK) {
-            colorHints |= WallpaperColors.HINT_SUPPORTS_DARK_THEME;
-        }
-        themeColors.setColorHints(colorHints);
-        return themeColors;
-    }
-
-    /**
      * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
      * for display.
      */
@@ -809,7 +676,6 @@
     final SparseArray<Boolean> mUserRestorecon = new SparseArray<Boolean>();
     int mCurrentUserId = UserHandle.USER_NULL;
     boolean mInAmbientMode;
-    int mThemeMode;
 
     static class WallpaperData {
 
@@ -868,7 +734,6 @@
         long lastDiedTime;
         boolean wallpaperUpdating;
         WallpaperObserver wallpaperObserver;
-        ThemeSettingsObserver themeSettingsObserver;
 
         /**
          * List of callbacks registered they should each be notified when the wallpaper is changed.
@@ -1100,7 +965,7 @@
                     }
                     mPaddingChanged = false;
                 }
-                if (mInfo != null && mInfo.getSupportsAmbientMode()) {
+                if (mInfo != null && mInfo.supportsAmbientMode()) {
                     try {
                         mEngine.setInAmbientMode(mInAmbientMode, false /* animated */);
                     } catch (RemoteException e) {
@@ -1414,10 +1279,6 @@
                 wallpaper.wallpaperObserver.stopWatching();
                 wallpaper.wallpaperObserver = null;
             }
-            if (wallpaper.themeSettingsObserver != null) {
-                wallpaper.themeSettingsObserver.stopObserving(mContext);
-                wallpaper.themeSettingsObserver = null;
-            }
         }
     }
 
@@ -1501,13 +1362,6 @@
                 systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
                 systemWallpaper.wallpaperObserver.startWatching();
             }
-            if (systemWallpaper.themeSettingsObserver == null) {
-                systemWallpaper.themeSettingsObserver = new ThemeSettingsObserver(null);
-                systemWallpaper.themeSettingsObserver.startObserving(mContext);
-            }
-            mThemeMode = Settings.Secure.getInt(
-                    mContext.getContentResolver(), Settings.Secure.THEME_MODE,
-                    Settings.Secure.THEME_MODE_WALLPAPER);
             switchWallpaper(systemWallpaper, reply);
         }
 
@@ -1923,7 +1777,7 @@
             mInAmbientMode = inAmbienMode;
             final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
             if (data != null && data.connection != null && data.connection.mInfo != null
-                    && data.connection.mInfo.getSupportsAmbientMode()) {
+                    && data.connection.mInfo.supportsAmbientMode()) {
                 engine = data.connection.mEngine;
             } else {
                 engine = null;
@@ -1981,7 +1835,7 @@
         }
 
         synchronized (mLock) {
-            return getThemeColorsLocked(wallpaperData.primaryColors);
+            return wallpaperData.primaryColors;
         }
     }
 
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
index 39e28c7..3199ed4 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
@@ -66,6 +66,12 @@
     private int setWebViewImplementation() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         String shellChosenPackage = getNextArg();
+        if (shellChosenPackage == null) {
+            pw.println("Failed to switch, no PACKAGE provided.");
+            pw.println("");
+            helpSetWebViewImplementation();
+            return 1;
+        }
         String newPackage = mInterface.changeProviderAndSetting(shellChosenPackage);
         if (shellChosenPackage.equals(newPackage)) {
             pw.println("Success");
@@ -85,6 +91,12 @@
         return 0;
     }
 
+    public void helpSetWebViewImplementation() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("  set-webview-implementation PACKAGE");
+        pw.println("    Set the WebView implementation to the specified package.");
+    }
+
     @Override
     public void onHelp() {
         PrintWriter pw = getOutPrintWriter();
@@ -99,8 +111,7 @@
         pw.println("  disable-redundant-packages");
         pw.println("    Disallow installing and enabling fallback packages when a more-preferred");
         pw.println("    package is available.");
-        pw.println("  set-webview-implementation PACKAGE");
-        pw.println("    Set the WebView implementation to the specified package.");
+        helpSetWebViewImplementation();
         pw.println("  enable-multiprocess");
         pw.println("    Enable multi-process mode for WebView");
         pw.println("  disable-multiprocess");
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdater.java b/services/core/java/com/android/server/webkit/WebViewUpdater.java
index 3e72d981..f270715 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdater.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdater.java
@@ -504,20 +504,20 @@
 
     private static boolean providerHasValidSignature(WebViewProviderInfo provider,
             PackageInfo packageInfo, SystemInterface systemInterface) {
-        if (systemInterface.systemIsDebuggable()) {
-            return true;
-        }
-        // If no signature is declared, instead check whether the package is included in the
-        // system.
-        if (provider.signatures == null || provider.signatures.length == 0) {
-            return packageInfo.applicationInfo.isSystemApp();
-        }
+        // Skip checking signatures on debuggable builds, for development purposes.
+        if (systemInterface.systemIsDebuggable()) return true;
+
+        // Allow system apps to be valid providers regardless of signature.
+        if (packageInfo.applicationInfo.isSystemApp()) return true;
+
+        // We don't support packages with multiple signatures.
         if (packageInfo.signatures.length != 1) return false;
 
-        // Return whether the package signature matches any of the valid signatures
+        // If any of the declared signatures match the package signature, it's valid.
         for (Signature signature : provider.signatures) {
             if (signature.equals(packageInfo.signatures[0])) return true;
         }
+
         return false;
     }
 
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index a6ec3cf..e449111 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -119,13 +119,13 @@
         }
     }
 
-    public void performComputeChangedWindowsNotLocked() {
+    public void performComputeChangedWindowsNotLocked(boolean forceSend) {
         WindowsForAccessibilityObserver observer = null;
         synchronized (mService) {
             observer = mWindowsForAccessibilityObserver;
         }
         if (observer != null) {
-            observer.performComputeChangedWindowsNotLocked();
+            observer.performComputeChangedWindowsNotLocked(forceSend);
         }
     }
 
@@ -193,7 +193,7 @@
             observer = mWindowsForAccessibilityObserver;
         }
         if (observer != null) {
-            observer.performComputeChangedWindowsNotLocked();
+            observer.performComputeChangedWindowsNotLocked(false);
         }
     }
 
@@ -549,7 +549,8 @@
                     touchableRegion.getBounds(touchableFrame);
                     RectF windowFrame = mTempRectF;
                     windowFrame.set(touchableFrame);
-                    windowFrame.offset(-windowState.mFrame.left, -windowState.mFrame.top);
+                    windowFrame.offset(-windowState.getFrameLw().left,
+                            -windowState.getFrameLw().top);
                     matrix.mapRect(windowFrame);
                     Region windowBounds = mTempRegion2;
                     windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
@@ -1010,12 +1011,12 @@
             mHandler = new MyHandler(mService.mH.getLooper());
             mRecurringAccessibilityEventsIntervalMillis = ViewConfiguration
                     .getSendRecurringAccessibilityEventsInterval();
-            computeChangedWindows();
+            computeChangedWindows(true);
         }
 
-        public void performComputeChangedWindowsNotLocked() {
+        public void performComputeChangedWindowsNotLocked(boolean forceSend) {
             mHandler.removeMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS);
-            computeChangedWindows();
+            computeChangedWindows(forceSend);
         }
 
         public void scheduleComputeChangedWindowsLocked() {
@@ -1025,7 +1026,12 @@
             }
         }
 
-        public void computeChangedWindows() {
+        /**
+         * Check if windows have changed, and send them to the accessibilty subsystem if they have.
+         *
+         * @param forceSend Send the windows the accessibility even if they haven't changed.
+         */
+        public void computeChangedWindows(boolean forceSend) {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "computeChangedWindows()");
             }
@@ -1170,36 +1176,38 @@
                 visibleWindows.clear();
                 addedWindows.clear();
 
-                // We computed the windows and if they changed notify the client.
-                if (mOldWindows.size() != windows.size()) {
-                    // Different size means something changed.
-                    windowsChanged = true;
-                } else if (!mOldWindows.isEmpty() || !windows.isEmpty()) {
-                    // Since we always traverse windows from high to low layer
-                    // the old and new windows at the same index should be the
-                    // same, otherwise something changed.
-                    for (int i = 0; i < windowCount; i++) {
-                        WindowInfo oldWindow = mOldWindows.get(i);
-                        WindowInfo newWindow = windows.get(i);
-                        // We do not care for layer changes given the window
-                        // order does not change. This brings no new information
-                        // to the clients.
-                        if (windowChangedNoLayer(oldWindow, newWindow)) {
-                            windowsChanged = true;
-                            break;
+                if (!forceSend) {
+                    // We computed the windows and if they changed notify the client.
+                    if (mOldWindows.size() != windows.size()) {
+                        // Different size means something changed.
+                        windowsChanged = true;
+                    } else if (!mOldWindows.isEmpty() || !windows.isEmpty()) {
+                        // Since we always traverse windows from high to low layer
+                        // the old and new windows at the same index should be the
+                        // same, otherwise something changed.
+                        for (int i = 0; i < windowCount; i++) {
+                            WindowInfo oldWindow = mOldWindows.get(i);
+                            WindowInfo newWindow = windows.get(i);
+                            // We do not care for layer changes given the window
+                            // order does not change. This brings no new information
+                            // to the clients.
+                            if (windowChangedNoLayer(oldWindow, newWindow)) {
+                                windowsChanged = true;
+                                break;
+                            }
                         }
                     }
                 }
 
-                if (windowsChanged) {
+                if (forceSend || windowsChanged) {
                     cacheWindows(windows);
                 }
             }
 
             // Now we do not hold the lock, so send the windows over.
-            if (windowsChanged) {
+            if (forceSend || windowsChanged) {
                 if (DEBUG) {
-                    Log.i(LOG_TAG, "Windows changed:" + windows);
+                    Log.i(LOG_TAG, "Windows changed or force sending:" + windows);
                 }
                 mCallback.onWindowsForAccessibilityChanged(windows);
             } else {
@@ -1222,7 +1230,7 @@
             // Move to origin as all transforms are captured by the matrix.
             RectF windowFrame = mTempRectF;
             windowFrame.set(touchableFrame);
-            windowFrame.offset(-windowState.mFrame.left, -windowState.mFrame.top);
+            windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top);
 
             // Map the frame to get what appears on the screen.
             Matrix matrix = mTempMatrix;
@@ -1344,7 +1352,7 @@
             public void handleMessage(Message message) {
                 switch (message.what) {
                     case MESSAGE_COMPUTE_CHANGED_WINDOWS: {
-                        computeChangedWindows();
+                        computeChangedWindows(false);
                     } break;
                 }
             }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 3885cf9..83075ed 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -266,4 +266,19 @@
     public abstract void onProcessAdded(WindowProcessController proc);
     public abstract void onProcessRemoved(String name, int uid);
     public abstract void onCleanUpApplicationRecord(WindowProcessController proc);
+    public abstract int getTopProcessState();
+
+    public abstract boolean isSleeping();
+    public abstract boolean isShuttingDown();
+    public abstract boolean shuttingDown(boolean booted, int timeout);
+    public abstract void enableScreenAfterBoot(boolean booted);
+    public abstract boolean showStrictModeViolationDialog();
+    public abstract void showSystemReadyErrorDialogsIfNeeded();
+
+    public abstract long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason);
+    public abstract void onProcessMapped(int pid, WindowProcessController proc);
+    public abstract void onProcessUnMapped(int pid);
+
+    public abstract void onPackageDataCleared(String name);
+    public abstract void onPackageUninstalled(String name);
 }
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 4f15c5d..36280dd 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -648,7 +648,7 @@
     public void pauseKeyDispatching() {
         synchronized (mWindowMap) {
             if (mContainer != null) {
-                mService.mInputMonitor.pauseDispatchingLw(mContainer);
+                mContainer.getDisplayContent().getInputMonitor().pauseDispatchingLw(mContainer);
             }
         }
     }
@@ -656,7 +656,7 @@
     public void resumeKeyDispatching() {
         synchronized (mWindowMap) {
             if (mContainer != null) {
-                mService.mInputMonitor.resumeDispatchingLw(mContainer);
+                mContainer.getDisplayContent().getInputMonitor().resumeDispatchingLw(mContainer);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index fa6079c..b775918 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -78,6 +78,7 @@
 import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
 import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
 import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
 
 import android.annotation.CallSuper;
 import android.app.Activity;
@@ -264,6 +265,12 @@
      */
     private boolean mWillCloseOrEnterPip;
 
+    /** Layer used to constrain the animation to a token's stack bounds. */
+    SurfaceControl mAnimationBoundsLayer;
+
+    /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
+    boolean mNeedsAnimationBoundsLayer;
+
     AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
             DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
             boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
@@ -449,13 +456,13 @@
                     + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
 
             if (changed) {
-                mService.mInputMonitor.setUpdateInputWindowsNeededLw();
+                getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
                 if (performLayout) {
                     mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                             false /*updateInputWindows*/);
                     mService.mWindowPlacerLocked.performSurfacePlacement();
                 }
-                mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+                getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
             }
         }
 
@@ -677,7 +684,7 @@
             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this);
             mService.mFocusedApp = null;
             mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
-            mService.mInputMonitor.setFocusedAppLw(null);
+            getDisplayContent().getInputMonitor().setFocusedAppLw(null);
         }
 
         if (!delayed) {
@@ -1523,7 +1530,7 @@
             if (mLetterbox == null) {
                 mLetterbox = new Letterbox(() -> makeChildSurface(null));
             }
-            mLetterbox.layout(getParent().getBounds(), w.mFrame);
+            mLetterbox.layout(getParent().getBounds(), w.getFrameLw());
         } else if (mLetterbox != null) {
             mLetterbox.hide();
         }
@@ -1720,6 +1727,20 @@
         return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
     }
 
+    /**
+     * Creates a layer to apply crop to an animation.
+     */
+    private SurfaceControl createAnimationBoundsLayer(Transaction t) {
+        if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
+        final SurfaceControl.Builder builder = makeAnimationLeash()
+                .setParent(getAnimationLeashParent())
+                .setName(getSurfaceControl() + " - animation-bounds")
+                .setSize(getSurfaceWidth(), getSurfaceHeight());
+        final SurfaceControl boundsLayer = builder.build();
+        t.show(boundsLayer);
+        return boundsLayer;
+    }
+
     boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
             boolean isVoiceInteraction) {
 
@@ -1753,12 +1774,15 @@
                 adapter = mService.mAppTransition.getRemoteAnimationController()
                         .createAnimationAdapter(this, mTmpPoint, mTmpRect);
             } else {
+                final int appStackClipMode = mService.mAppTransition.getAppStackClipMode();
+                mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
+
                 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
                 if (a != null) {
                     adapter = new LocalAnimationAdapter(
                             new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
                                     mService.mAppTransition.canSkipFirstFrame(),
-                                    mService.mAppTransition.getAppStackClipMode(),
+                                    appStackClipMode,
                                     true /* isAppAnimation */),
                             mService.mSurfaceAnimationRunner);
                     if (a.getZAdjustment() == Animation.ZORDER_TOP) {
@@ -1808,7 +1832,7 @@
             // won't exactly match the final freeform window frame (e.g. when overlapping with
             // the status bar). In that case we need to use the final frame.
             if (freeform) {
-                frame.set(win.mFrame);
+                frame.set(win.getFrameLw());
             } else if (win.isLetterboxedAppWindow()) {
                 frame.set(getTask().getBounds());
             } else if (win.isDockedResizing()) {
@@ -1816,7 +1840,7 @@
                 // animation target (which will be different than the task bounds)
                 frame.set(getTask().getParent().getBounds());
             } else {
-                frame.set(win.mContainingFrame);
+                frame.set(win.getContainingFrame());
             }
             surfaceInsets = win.getAttrs().surfaceInsets;
             // XXX(b/72757033): These are insets relative to the window frame, but we're really
@@ -1858,6 +1882,11 @@
     @Override
     public void onAnimationLeashDestroyed(Transaction t) {
         super.onAnimationLeashDestroyed(t);
+        if (mAnimationBoundsLayer != null) {
+            t.destroy(mAnimationBoundsLayer);
+            mAnimationBoundsLayer = null;
+        }
+
         if (mAnimatingAppWindowTokenRegistry != null) {
             mAnimatingAppWindowTokenRegistry.notifyFinished(this);
         }
@@ -1908,6 +1937,26 @@
         if (mAnimatingAppWindowTokenRegistry != null) {
             mAnimatingAppWindowTokenRegistry.notifyStarting(this);
         }
+
+        // If the animation needs to be cropped then an animation bounds layer is created as a child
+        // of the pinned stack or animation layer. The leash is then reparented to this new layer.
+        if (mNeedsAnimationBoundsLayer) {
+            final TaskStack stack = getStack();
+            if (stack == null) {
+                return;
+            }
+            mAnimationBoundsLayer = createAnimationBoundsLayer(t);
+
+            // Set clip rect to stack bounds.
+            mTmpRect.setEmpty();
+            stack.getBounds(mTmpRect);
+
+            // Crop to stack bounds.
+            t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
+
+            // Reparent leash to animation bounds layer.
+            t.reparent(leash, mAnimationBoundsLayer.getHandle());
+        }
     }
 
     /**
@@ -1927,6 +1976,7 @@
         mTransit = TRANSIT_UNSET;
         mTransitFlags = 0;
         mNeedsZBoost = false;
+        mNeedsAnimationBoundsLayer = false;
 
         setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
                 "AppWindowToken");
@@ -2022,7 +2072,7 @@
         if (win == null) {
             return;
         }
-        final Rect frame = win.mFrame;
+        final Rect frame = win.getFrameLw();
         final int thumbnailDrawableRes = getTask().mUserId == mService.mCurrentUserId
                 ? R.drawable.ic_account_circle
                 : R.drawable.ic_corp_badge;
@@ -2034,7 +2084,8 @@
         }
         mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
         final Animation animation =
-                mService.mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(win.mFrame);
+                mService.mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
+                        win.getFrameLw());
         mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
                 frame.top));
     }
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index 1977e12..fff1fa4 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -56,6 +56,7 @@
                     .setParent(null) // TODO: Work-around for b/69259549
                     .build();
 
+            transaction.setLayerStack(surface, dc.getDisplayId());
             transaction.setAlpha(surface, 1);
             transaction.setLayer(surface, layer);
             transaction.show(surface);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 0a49c13..a693071 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -31,11 +31,13 @@
 import android.os.Debug;
 import android.util.ArrayMap;
 import android.util.Slog;
+import android.view.Choreographer;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -112,6 +114,7 @@
     private final Interpolator mFastOutSlowInInterpolator;
     private boolean mFinishAnimationAfterTransition = false;
     private final AnimationHandler mAnimationHandler;
+    private Choreographer mChoreographer;
 
     private static final int WAIT_FOR_DRAW_TIMEOUT_MS = 3000;
 
@@ -123,6 +126,12 @@
         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.fast_out_slow_in);
         mAnimationHandler = animationHandler;
+        if (animationHandler != null) {
+            // If an animation handler is provided, then ensure that it runs on the sf vsync tick
+            handler.runWithScissors(() -> mChoreographer = Choreographer.getSfInstance(),
+                    0 /* timeout */);
+            animationHandler.setProvider(new SfVsyncFrameCallbackProvider(mChoreographer));
+        }
     }
 
     @VisibleForTesting
@@ -196,12 +205,6 @@
 
         @Override
         public void onAnimationStart(Animator animation) {
-            if (!mTarget.isAttached()) {
-                // No point of trying to animate something that isn't attached to the hierarchy
-                // anymore.
-                cancel();
-            }
-
             if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
                     + " mPrevSchedulePipModeChangedState=" + mPrevSchedulePipModeChangedState
                     + " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState);
@@ -216,13 +219,15 @@
             // Ensure that we have prepared the target for animation before we trigger any size
             // changes, so it can swap surfaces in to appropriate modes, or do as it wishes
             // otherwise.
+            boolean continueAnimation;
             if (mPrevSchedulePipModeChangedState == NO_PIP_MODE_CHANGED_CALLBACKS) {
-                mTarget.onAnimationStart(mSchedulePipModeChangedState ==
+                continueAnimation = mTarget.onAnimationStart(mSchedulePipModeChangedState ==
                         SCHEDULE_PIP_MODE_CHANGED_ON_START, false /* forceUpdate */);
 
                 // When starting an animation from fullscreen, pause here and wait for the
                 // windows-drawn signal before we start the rest of the transition down into PiP.
-                if (mMoveFromFullscreen && mTarget.shouldDeferStartOnMoveToFullscreen()) {
+                if (continueAnimation && mMoveFromFullscreen
+                        && mTarget.shouldDeferStartOnMoveToFullscreen()) {
                     pause();
                 }
             } else if (mPrevSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END &&
@@ -231,8 +236,19 @@
                 // client will not currently receive any picture-in-picture mode change callbacks.
                 // However, we still need to report to them that they are leaving PiP, so this will
                 // force an update via a mode changed callback.
-                mTarget.onAnimationStart(true /* schedulePipModeChangedCallback */,
-                        true /* forceUpdate */);
+                continueAnimation = mTarget.onAnimationStart(
+                        true /* schedulePipModeChangedCallback */, true /* forceUpdate */);
+            } else {
+                // The animation is already running, but we should check that the TaskStack is still
+                // valid before continuing with the animation
+                continueAnimation = mTarget.isAttached();
+            }
+
+            if (!continueAnimation) {
+                // No point of trying to animate something that isn't attached to the hierarchy
+                // anymore.
+                cancel();
+                return;
             }
 
             // Immediately update the task bounds if they have to become larger, but preserve
@@ -354,6 +370,9 @@
             if (DEBUG) Slog.d(TAG, "cancel: mTarget=" + mTarget);
             mSkipAnimationEnd = true;
             super.cancel();
+
+            // Reset the thread priority of the animation thread if the bounds animation is canceled
+            updateBooster();
         }
 
         /**
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
index d66b42f..5cb80de 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
@@ -30,8 +30,9 @@
      *
      * @param schedulePipModeChangedCallback whether or not to schedule the PiP mode changed
      * callbacks
+     * @return whether to continue the animation
      */
-    void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate);
+    boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate);
 
     /**
      * @return Whether the animation should be paused waiting for the windows to draw before
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f74216a..49638a9 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -20,7 +20,6 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
@@ -59,12 +58,25 @@
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static com.android.server.wm.DisplayContentProto.ABOVE_APP_WINDOWS;
+import static com.android.server.wm.DisplayContentProto.BELOW_APP_WINDOWS;
+import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES;
+import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO;
+import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER;
+import static com.android.server.wm.DisplayContentProto.DPI;
+import static com.android.server.wm.DisplayContentProto.ID;
+import static com.android.server.wm.DisplayContentProto.IME_WINDOWS;
+import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER;
+import static com.android.server.wm.DisplayContentProto.ROTATION;
+import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
+import static com.android.server.wm.DisplayContentProto.STACKS;
+import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
@@ -101,19 +113,7 @@
 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
-import static com.android.server.wm.DisplayProto.ABOVE_APP_WINDOWS;
-import static com.android.server.wm.DisplayProto.BELOW_APP_WINDOWS;
-import static com.android.server.wm.DisplayProto.DISPLAY_FRAMES;
-import static com.android.server.wm.DisplayProto.DISPLAY_INFO;
-import static com.android.server.wm.DisplayProto.DOCKED_STACK_DIVIDER_CONTROLLER;
-import static com.android.server.wm.DisplayProto.DPI;
-import static com.android.server.wm.DisplayProto.ID;
-import static com.android.server.wm.DisplayProto.IME_WINDOWS;
-import static com.android.server.wm.DisplayProto.PINNED_STACK_CONTROLLER;
-import static com.android.server.wm.DisplayProto.ROTATION;
-import static com.android.server.wm.DisplayProto.SCREEN_ROTATION_ANIMATION;
-import static com.android.server.wm.DisplayProto.STACKS;
-import static com.android.server.wm.DisplayProto.WINDOW_CONTAINER;
+import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
 
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
@@ -122,7 +122,6 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Matrix;
-import android.graphics.Path;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
@@ -141,6 +140,7 @@
 import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
+import android.view.Gravity;
 import android.view.InputDevice;
 import android.view.MagnificationSpec;
 import android.view.Surface;
@@ -173,7 +173,8 @@
  * IMPORTANT: No method from this class should ever be used without holding
  * WindowManagerService.mWindowMap.
  */
-class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
+class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer>
+        implements WindowManagerPolicy.DisplayContentInfo {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
 
     /** Unique identifier of this stack. */
@@ -234,6 +235,8 @@
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
     private final Display mDisplay;
     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+    private final DisplayPolicy mDisplayPolicy;
+    private DisplayRotation mDisplayRotation;
     DisplayFrames mDisplayFrames;
 
     /**
@@ -303,8 +306,12 @@
     // Accessed directly by all users.
     private boolean mLayoutNeeded;
     int pendingLayoutChanges;
+    int mDeferredRotationPauseCount;
+
     // TODO(multi-display): remove some of the usages.
+    @VisibleForTesting
     boolean isDefaultDisplay;
+
     /**
      * Flag indicating whether WindowManager should override info for this display in
      * DisplayManager.
@@ -400,6 +407,8 @@
 
     private MagnificationSpec mMagnificationSpec;
 
+    private InputMonitor mInputMonitor;
+
     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
         WindowStateAnimator winAnimator = w.mWinAnimator;
         final AppWindowToken atoken = w.mAppToken;
@@ -578,9 +587,9 @@
                     w.mAppToken.layoutLetterbox(w);
                 }
 
-                if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.mFrame
-                        + " mContainingFrame=" + w.mContainingFrame
-                        + " mDisplayFrame=" + w.mDisplayFrame);
+                if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.getFrameLw()
+                        + " mContainingFrame=" + w.getContainingFrame()
+                        + " mDisplayFrame=" + w.getDisplayFrameLw());
             }
         }
     };
@@ -606,9 +615,9 @@
                 w.prelayout();
                 mService.mPolicy.layoutWindowLw(w, w.getParentWindow(), mDisplayFrames);
                 w.mLayoutSeq = mLayoutSeq;
-                if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
-                        + " mContainingFrame=" + w.mContainingFrame
-                        + " mDisplayFrame=" + w.mDisplayFrame);
+                if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrameLw()
+                        + " mContainingFrame=" + w.getContainingFrame()
+                        + " mDisplayFrame=" + w.getDisplayFrameLw());
             }
         } else if (w.mAttrs.type == TYPE_DREAM) {
             // Don't layout windows behind a dream, so that if it does stuff like hide the
@@ -759,6 +768,13 @@
         mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
         initializeDisplayBaseInfo();
+        mDisplayPolicy = new DisplayPolicy(service);
+        mDisplayRotation = new DisplayRotation(service, this);
+        if (isDefaultDisplay) {
+            // The policy may be invoked right after here, so it requires the necessary default
+            // fields of this display content.
+            mService.mPolicy.setDefaultDisplay(this);
+        }
         mDividerControllerLocked = new DockedStackDividerController(service, this);
         mPinnedStackControllerLocked = new PinnedStackController(service, this);
 
@@ -797,6 +813,10 @@
         // TODO(b/62541591): evaluate whether this is the best spot to declare the
         // {@link DisplayContent} ready for use.
         mDisplayReady = true;
+
+        // TODO(b/112081256): Use independent InputMonitor.
+        mInputMonitor = isDefaultDisplay ? new InputMonitor(service, mDisplayId)
+                : mService.getDefaultDisplayContentLocked().mInputMonitor;
     }
 
     boolean isReady() {
@@ -900,7 +920,8 @@
         appToken.onRemovedFromDisplay();
     }
 
-    Display getDisplay() {
+    @Override
+    public Display getDisplay() {
         return mDisplay;
     }
 
@@ -912,6 +933,20 @@
         return mDisplayMetrics;
     }
 
+    DisplayPolicy getDisplayPolicy() {
+        return mDisplayPolicy;
+    }
+
+    @Override
+    public DisplayRotation getDisplayRotation() {
+        return mDisplayRotation;
+    }
+
+    @VisibleForTesting
+    void setDisplayRotation(DisplayRotation displayRotation) {
+        mDisplayRotation = displayRotation;
+    }
+
     int getRotation() {
         return mRotation;
     }
@@ -919,6 +954,7 @@
     @VisibleForTesting
     void setRotation(int newRotation) {
         mRotation = newRotation;
+        mDisplayRotation.setRotation(newRotation);
     }
 
     int getLastOrientation() {
@@ -942,6 +978,67 @@
     }
 
     /**
+     * Temporarily pauses rotation changes until resumed.
+     *
+     * This can be used to prevent rotation changes from occurring while the user is
+     * performing certain operations, such as drag and drop.
+     *
+     * This call nests and must be matched by an equal number of calls to
+     * {@link #resumeRotationLocked}.
+     */
+    void pauseRotationLocked() {
+        mDeferredRotationPauseCount++;
+    }
+
+    /**
+     * Resumes normal rotation changes after being paused.
+     */
+    void resumeRotationLocked() {
+        if (mDeferredRotationPauseCount <= 0) {
+            return;
+        }
+
+        mDeferredRotationPauseCount--;
+        if (mDeferredRotationPauseCount == 0) {
+            updateRotationAndSendNewConfigIfNeeded();
+        }
+    }
+
+    /**
+     * If this is true we have updated our desired orientation, but not yet changed the real
+     * orientation our applied our screen rotation animation. For example, because a previous
+     * screen rotation was in progress.
+     *
+     * @return {@code true} if the there is an ongoing rotation change.
+     */
+    boolean rotationNeedsUpdate() {
+        final int lastOrientation = getLastOrientation();
+        final int oldRotation = getRotation();
+        final boolean oldAltOrientation = getAltOrientation();
+
+        final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
+        final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
+                lastOrientation, rotation);
+        if (oldRotation == rotation && oldAltOrientation == altOrientation) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Update rotation of the display and send configuration if the rotation is changed.
+     *
+     * @return {@code true} if the rotation has been changed and the new config is sent.
+     */
+    boolean updateRotationAndSendNewConfigIfNeeded() {
+        final boolean changed = updateRotationUnchecked(false /* forceUpdate */);
+        if (changed) {
+            mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
+        }
+        return changed;
+    }
+
+    /**
      * Update rotation of the display.
      *
      * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
@@ -964,7 +1061,7 @@
     boolean updateRotationUnchecked(boolean forceUpdate) {
         ScreenRotationAnimation screenRotationAnimation;
         if (!forceUpdate) {
-            if (mService.mDeferredRotationPauseCount > 0) {
+            if (mDeferredRotationPauseCount > 0) {
                 // Rotation updates have been paused temporarily.  Defer the update until
                 // updates have been resumed.
                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
@@ -999,13 +1096,12 @@
         final int oldRotation = mRotation;
         final int lastOrientation = mLastOrientation;
         final boolean oldAltOrientation = mAltOrientation;
-        final int rotation = mService.mPolicy.rotationForOrientationLw(lastOrientation, oldRotation,
-                isDefaultDisplay);
+        final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id="
                 + mDisplayId + " based on lastOrientation=" + lastOrientation
                 + " and oldRotation=" + oldRotation);
-        boolean mayRotateSeamlessly = mService.mPolicy.shouldRotateSeamlessly(oldRotation,
-                rotation);
+        boolean mayRotateSeamlessly = mService.mPolicy.shouldRotateSeamlessly(mDisplayRotation,
+                oldRotation, rotation);
 
         if (mayRotateSeamlessly) {
             final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated);
@@ -1036,7 +1132,7 @@
         //       an orientation that has different metrics than it expected.
         //       eg. Portrait instead of Landscape.
 
-        final boolean altOrientation = !mService.mPolicy.rotationHasCompatibleMetricsLw(
+        final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
                 lastOrientation, rotation);
 
         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
@@ -1058,16 +1154,12 @@
             mService.mWaitingForConfig = true;
         }
 
-        mRotation = rotation;
+        setRotation(rotation);
         mAltOrientation = altOrientation;
-        if (isDefaultDisplay) {
-            mService.mPolicy.setRotationLw(rotation);
-        }
 
         mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
-        mService.mH.removeMessages(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT);
-        mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
-                WINDOW_FREEZE_TIMEOUT_DURATION);
+        mService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
+                this, WINDOW_FREEZE_TIMEOUT_DURATION);
 
         setLayoutNeeded();
         final int[] anim = new int[2];
@@ -1106,6 +1198,11 @@
             }
         }
 
+        forAllWindows(w -> {
+            w.forceSeamlesslyRotateIfAllowed(oldRotation, rotation);
+        }, true /* traverseTopToBottom */);
+
+        // TODO(b/111504081): Consolidate seamless rotation logic.
         if (rotateSeamlessly) {
             seamlesslyRotate(getPendingTransaction(), oldRotation, rotation);
         }
@@ -1124,9 +1221,8 @@
         }, true /* traverseTopToBottom */);
 
         if (rotateSeamlessly) {
-            mService.mH.removeMessages(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT);
-            mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT,
-                    SEAMLESS_ROTATION_TIMEOUT_DURATION);
+            mService.mH.sendNewMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT,
+                    this, SEAMLESS_ROTATION_TIMEOUT_DURATION);
         }
 
         for (int i = mService.mRotationWatchers.size() - 1; i >= 0; i--) {
@@ -1153,8 +1249,23 @@
     }
 
     void configureDisplayPolicy() {
-        mService.mPolicy.setInitialDisplaySize(getDisplay(),
-                mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity);
+        final int width = mBaseDisplayWidth;
+        final int height = mBaseDisplayHeight;
+        final int shortSize;
+        final int longSize;
+        if (width > height) {
+            shortSize = height;
+            longSize = width;
+        } else {
+            shortSize = width;
+            longSize = height;
+        }
+
+        final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
+        final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
+
+        mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
+        mDisplayPolicy.configure(width, height, shortSizeDp);
 
         mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
@@ -1249,11 +1360,21 @@
                     cutout, mInitialDisplayWidth, mInitialDisplayHeight);
         }
         final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
-        final Path bounds = cutout.getBounds().getBoundaryPath();
+        final List<Rect> bounds = WmDisplayCutout.computeSafeInsets(
+                        cutout, mInitialDisplayWidth, mInitialDisplayHeight)
+                .getDisplayCutout().getBoundingRects();
         transformPhysicalToLogicalCoordinates(rotation, mInitialDisplayWidth, mInitialDisplayHeight,
                 mTmpMatrix);
-        bounds.transform(mTmpMatrix);
-        return WmDisplayCutout.computeSafeInsets(DisplayCutout.fromBounds(bounds),
+        final Region region = Region.obtain();
+        for (int i = 0; i < bounds.size(); i++) {
+            final Rect rect = bounds.get(i);
+            final RectF rectF = new RectF(bounds.get(i));
+            mTmpMatrix.mapRect(rectF);
+            rectF.round(rect);
+            region.op(rect, Op.UNION);
+        }
+
+        return WmDisplayCutout.computeSafeInsets(DisplayCutout.fromBounds(region),
                 rotated ? mInitialDisplayHeight : mInitialDisplayWidth,
                 rotated ? mInitialDisplayWidth : mInitialDisplayHeight);
     }
@@ -1268,9 +1389,7 @@
         final int dw = displayInfo.logicalWidth;
         final int dh = displayInfo.logicalHeight;
         config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
-        // TODO: Probably best to set this based on some setting in the display content object,
-        // so the display can be configured for things like fullscreen.
-        config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        config.windowConfiguration.setWindowingMode(getWindowingMode());
 
         final float density = mDisplayMetrics.density;
         config.screenWidthDp =
@@ -1498,6 +1617,54 @@
         }
     }
 
+    /**
+     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
+     * theme attribute) on devices that feature a physical options menu key attempt to position
+     * their menu panel window along the edge of the screen nearest the physical menu key.
+     * This lowers the travel distance between invoking the menu panel and selecting
+     * a menu option.
+     *
+     * This method helps control where that menu is placed. Its current implementation makes
+     * assumptions about the menu key and its relationship to the screen based on whether
+     * the device's natural orientation is portrait (width < height) or landscape.
+     *
+     * The menu key is assumed to be located along the bottom edge of natural-portrait
+     * devices and along the right edge of natural-landscape devices. If these assumptions
+     * do not hold for the target device, this method should be changed to reflect that.
+     *
+     * @return A {@link Gravity} value for placing the options menu window.
+     */
+    int getPreferredOptionsPanelGravity() {
+        final int rotation = getRotation();
+        if (mInitialDisplayWidth < mInitialDisplayHeight) {
+            // On devices with a natural orientation of portrait.
+            switch (rotation) {
+                default:
+                case Surface.ROTATION_0:
+                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+                case Surface.ROTATION_90:
+                    return Gravity.RIGHT | Gravity.BOTTOM;
+                case Surface.ROTATION_180:
+                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+                case Surface.ROTATION_270:
+                    return Gravity.START | Gravity.BOTTOM;
+            }
+        }
+
+        // On devices with a natural orientation of landscape.
+        switch (rotation) {
+            default:
+            case Surface.ROTATION_0:
+                return Gravity.RIGHT | Gravity.BOTTOM;
+            case Surface.ROTATION_90:
+                return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+            case Surface.ROTATION_180:
+                return Gravity.START | Gravity.BOTTOM;
+            case Surface.ROTATION_270:
+                return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+        }
+    }
+
     DockedStackDividerController getDockedDividerController() {
         return mDividerControllerLocked;
     }
@@ -1883,8 +2050,8 @@
         getParent().positionChildAt(position, this, includingParents);
     }
 
-    void positionStackAt(int position, TaskStack child) {
-        mTaskStackContainers.positionChildAt(position, child, false /* includingParents */);
+    void positionStackAt(int position, TaskStack child, boolean includingParents) {
+        mTaskStackContainers.positionChildAt(position, child, includingParents);
         layoutAndAssignWindowLayersIfNeeded();
     }
 
@@ -2011,6 +2178,8 @@
                 }
             }
             mService.mAnimator.removeDisplayLocked(mDisplayId);
+            mWindowingLayer.release();
+            mOverlayLayer.release();
         } finally {
             mRemovingDisplay = false;
         }
@@ -2272,6 +2441,8 @@
 
         pw.println();
         pw.print(prefix); pw.print("mLayoutSeq="); pw.println(mLayoutSeq);
+        pw.print(prefix);
+        pw.print("mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
 
         pw.println();
         pw.println(prefix + "Application tokens in top down Z order:");
@@ -2316,6 +2487,12 @@
 
         pw.println();
         mDisplayFrames.dump(prefix, pw);
+        pw.println();
+        mDisplayPolicy.dump(prefix, pw);
+        pw.println();
+        mDisplayRotation.dump(prefix, pw);
+        pw.println();
+        mInputMonitor.dump(pw, "  ");
     }
 
     @Override
@@ -2426,9 +2603,9 @@
             assignWindowLayers(false /* setLayoutNeeded */);
         }
 
-        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
+        mInputMonitor.setUpdateInputWindowsNeededLw();
         mService.mWindowPlacerLocked.performSurfacePlacement();
-        mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+        mInputMonitor.updateInputWindowsLw(false /*force*/);
     }
 
     /** Returns true if a leaked surface was destroyed */
@@ -2866,7 +3043,7 @@
                 mWallpaperController.adjustWallpaperWindows(this);
             }
 
-            if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
+            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
                 if (mService.updateOrientationFromAppTokensLocked(mDisplayId)) {
                     setLayoutNeeded();
@@ -3011,10 +3188,10 @@
         forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
 
         // Window frames may have changed. Tell the input dispatcher about it.
-        mService.mInputMonitor.layoutInputConsumers(dw, dh);
-        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
+        mInputMonitor.layoutInputConsumers(dw, dh);
+        mInputMonitor.setUpdateInputWindowsNeededLw();
         if (updateInputWindows) {
-            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+            mInputMonitor.updateInputWindowsLw(false /*force*/);
         }
 
         mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
@@ -3341,11 +3518,16 @@
 
         private void addStackReferenceIfNeeded(TaskStack stack) {
             if (stack.isActivityTypeHome()) {
+                // TODO(b/111363427) Rollback to throws exceptions once we figure out how to
+                // properly deal with home type stack when external display removed
                 if (mHomeStack != null) {
-                    throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+                    // throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+                    //        + mHomeStack + " already exist on display=" + this + " stack=" + stack);
+                    Slog.e(TAG, "addStackReferenceIfNeeded: home stack="
                             + mHomeStack + " already exist on display=" + this + " stack=" + stack);
+                } else {
+                    mHomeStack = stack;
                 }
-                mHomeStack = stack;
             }
             final int windowingMode = stack.getWindowingMode();
             if (windowingMode == WINDOWING_MODE_PINNED) {
@@ -3457,7 +3639,7 @@
             } else {
                 // Other stacks need to be below the always-on-top stacks.
                 maxPosition = belowAlwaysOnTopPosition !=
-                        POSITION_BOTTOM ? belowAlwaysOnTopPosition : topChildPosition;
+                        POSITION_BOTTOM ? belowAlwaysOnTopPosition : 0;
             }
 
             int targetPosition = requestedPosition;
@@ -3726,6 +3908,19 @@
         }
 
         @Override
+        SurfaceControl.Builder makeChildSurface(WindowContainer child) {
+            final SurfaceControl.Builder builder = super.makeChildSurface(child);
+            if (child instanceof WindowToken && ((WindowToken) child).mRoundedCornerOverlay) {
+                // To draw above the ColorFade layer during the screen off transition, the
+                // rounded corner overlays need to be at the root of the surface hierarchy.
+                // TODO: move the ColorLayer into the display overlay layer such that this is not
+                // necessary anymore.
+                builder.setParent(null);
+            }
+            return builder;
+        }
+
+        @Override
         void assignChildLayers(SurfaceControl.Transaction t) {
             assignChildLayers(t, null /* imeContainer */);
         }
@@ -3741,6 +3936,10 @@
                     wt.assignRelativeLayer(t, mTaskStackContainers.getSplitScreenDividerAnchor(), 1);
                     continue;
                 }
+                if (wt.mRoundedCornerOverlay) {
+                    wt.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1);
+                    continue;
+                }
                 wt.assignLayer(t, j);
                 wt.assignChildLayers(t);
 
@@ -4044,4 +4243,8 @@
     private boolean canUpdateImeTarget() {
         return mDeferUpdateImeTargetCount == 0;
     }
+
+    InputMonitor getInputMonitor() {
+        return mInputMonitor;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
new file mode 100644
index 0000000..9151ddf
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED;
+import static android.view.WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.content.Intent;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
+import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
+
+import java.io.PrintWriter;
+
+/**
+ * The policy that provides the basic behaviors and states of a display to show UI.
+ */
+public class DisplayPolicy {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayPolicy" : TAG_WM;
+
+    private final WindowManagerService mService;
+    private final Object mLock;
+
+    private final boolean mCarDockEnablesAccelerometer;
+    private final boolean mDeskDockEnablesAccelerometer;
+
+    private volatile int mLidState = LID_ABSENT;
+    private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+    private volatile boolean mHdmiPlugged;
+
+    private volatile boolean mHasNavigationBar;
+    // Can the navigation bar ever move to the side?
+    private volatile boolean mNavigationBarCanMove;
+
+    // Written by vr manager thread, only read in this class.
+    private volatile boolean mPersistentVrModeEnabled;
+
+    private volatile boolean mAwake;
+    private volatile boolean mScreenOnEarly;
+    private volatile boolean mScreenOnFully;
+    private volatile ScreenOnListener mScreenOnListener;
+
+    private volatile boolean mKeyguardDrawComplete;
+    private volatile boolean mWindowManagerDrawComplete;
+
+    DisplayPolicy(WindowManagerService service) {
+        mService = service;
+        mLock = service.getWindowManagerLock();
+        mCarDockEnablesAccelerometer = service.mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
+        mDeskDockEnablesAccelerometer = service.mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
+    }
+
+    void configure(int width, int height, int shortSizeDp) {
+        // Allow the navigation bar to move on non-square small devices (phones).
+        mNavigationBarCanMove = width != height && shortSizeDp < 600;
+
+        mHasNavigationBar = mService.mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_showNavigationBar);
+
+        // Allow a system property to override this. Used by the emulator.
+        // See also hasNavigationBar().
+        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
+        if ("1".equals(navBarOverride)) {
+            mHasNavigationBar = false;
+        } else if ("0".equals(navBarOverride)) {
+            mHasNavigationBar = true;
+        }
+    }
+
+    public void setHdmiPlugged(boolean plugged) {
+        setHdmiPlugged(plugged, false /* force */);
+    }
+
+    public void setHdmiPlugged(boolean plugged, boolean force) {
+        if (force || mHdmiPlugged != plugged) {
+            mHdmiPlugged = plugged;
+            mService.updateRotation(true /* alwaysSendConfiguration */, true /* forceRelayout */);
+            final Intent intent = new Intent(ACTION_HDMI_PLUGGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
+            mService.mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+        }
+    }
+
+    boolean isHdmiPlugged() {
+        return mHdmiPlugged;
+    }
+
+    boolean isCarDockEnablesAccelerometer() {
+        return mCarDockEnablesAccelerometer;
+    }
+
+    boolean isDeskDockEnablesAccelerometer() {
+        return mDeskDockEnablesAccelerometer;
+    }
+
+    public void setPersistentVrModeEnabled(boolean persistentVrModeEnabled) {
+        mPersistentVrModeEnabled = persistentVrModeEnabled;
+    }
+
+    public boolean isPersistentVrModeEnabled() {
+        return mPersistentVrModeEnabled;
+    }
+
+    public void setDockMode(int dockMode) {
+        mDockMode = dockMode;
+    }
+
+    public int getDockMode() {
+        return mDockMode;
+    }
+
+    public boolean hasNavigationBar() {
+        return mHasNavigationBar;
+    }
+
+    public boolean navigationBarCanMove() {
+        return mNavigationBarCanMove;
+    }
+
+    public void setLidState(int lidState) {
+        mLidState = lidState;
+    }
+
+    public int getLidState() {
+        return mLidState;
+    }
+
+    public void setAwake(boolean awake) {
+        mAwake = awake;
+    }
+
+    public boolean isAwake() {
+        return mAwake;
+    }
+
+    public boolean isScreenOnEarly() {
+        return mScreenOnEarly;
+    }
+
+    public boolean isScreenOnFully() {
+        return mScreenOnFully;
+    }
+
+    public boolean isKeyguardDrawComplete() {
+        return mKeyguardDrawComplete;
+    }
+
+    public boolean isWindowManagerDrawComplete() {
+        return mWindowManagerDrawComplete;
+    }
+
+    public ScreenOnListener getScreenOnListener() {
+        return mScreenOnListener;
+    }
+
+    public void screenTurnedOn(ScreenOnListener screenOnListener) {
+        synchronized (mLock) {
+            mScreenOnEarly = true;
+            mScreenOnFully = false;
+            mKeyguardDrawComplete = false;
+            mWindowManagerDrawComplete = false;
+            mScreenOnListener = screenOnListener;
+        }
+    }
+
+    public void screenTurnedOff() {
+        synchronized (mLock) {
+            mScreenOnEarly = false;
+            mScreenOnFully = false;
+            mKeyguardDrawComplete = false;
+            mWindowManagerDrawComplete = false;
+            mScreenOnListener = null;
+        }
+    }
+
+    /** Return false if we are not awake yet or we have already informed of this event. */
+    public boolean finishKeyguardDrawn() {
+        synchronized (mLock) {
+            if (!mScreenOnEarly || mKeyguardDrawComplete) {
+                return false;
+            }
+
+            mKeyguardDrawComplete = true;
+            mWindowManagerDrawComplete = false;
+        }
+        return true;
+    }
+
+    /** Return false if screen is not turned on or we did already handle this case earlier. */
+    public boolean finishWindowsDrawn() {
+        synchronized (mLock) {
+            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
+                return false;
+            }
+
+            mWindowManagerDrawComplete = true;
+        }
+        return true;
+    }
+
+    /** Return false if it is not ready to turn on. */
+    public boolean finishScreenTurningOn() {
+        synchronized (mLock) {
+            if (DEBUG_SCREEN_ON) Slog.d(TAG,
+                    "finishScreenTurningOn: mAwake=" + mAwake
+                            + ", mScreenOnEarly=" + mScreenOnEarly
+                            + ", mScreenOnFully=" + mScreenOnFully
+                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
+                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+
+            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
+                    || (mAwake && !mKeyguardDrawComplete)) {
+                return false;
+            }
+
+            if (DEBUG_SCREEN_ON) Slog.i(TAG, "Finished screen turning on...");
+            mScreenOnListener = null;
+            mScreenOnFully = true;
+        }
+        return true;
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        pw.println(prefix + "DisplayPolicy");
+        pw.print(prefix + "  mCarDockEnablesAccelerometer=" + mCarDockEnablesAccelerometer);
+        pw.println(" mDeskDockEnablesAccelerometer=" + mDeskDockEnablesAccelerometer);
+        pw.print(prefix + "  mDockMode=" + Intent.dockStateToString(mDockMode));
+        pw.println(" mLidState=" + WindowManagerFuncs.lidStateToString(mLidState));
+        pw.print(prefix + "  mAwake=" + mAwake);
+        pw.print(" mScreenOnEarly=" + mScreenOnEarly);
+        pw.println(" mScreenOnFully=" + mScreenOnFully);
+        pw.print(prefix + "  mKeyguardDrawComplete=" + mKeyguardDrawComplete);
+        pw.println(" mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+        pw.println(prefix + "  mHdmiPlugged=" + mHdmiPlugged);
+    }
+}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
new file mode 100644
index 0000000..685c444
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -0,0 +1,881 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.hardware.power.V1_0.PowerHint;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Surface;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
+import com.android.server.UiThread;
+import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.policy.WindowOrientationListener;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
+import java.io.PrintWriter;
+
+/**
+ * Defines the mapping between orientation and rotation of a display.
+ * Non-public methods are assumed to run inside WM lock.
+ */
+public class DisplayRotation {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayRotation" : TAG_WM;
+
+    private final WindowManagerService mService;
+    private final DisplayPolicy mDisplayPolicy;
+    private final Context mContext;
+    private final Object mLock;
+
+    public final boolean isDefaultDisplay;
+    private final boolean mSupportAutoRotation;
+    private final int mLidOpenRotation;
+    private final int mCarDockRotation;
+    private final int mDeskDockRotation;
+    private final int mUndockedHdmiRotation;
+
+    private OrientationListener mOrientationListener;
+    private StatusBarManagerInternal mStatusBarManagerInternal;
+    private SettingsObserver mSettingsObserver;
+
+    // Default display does not rotate, apps that require non-default orientation will have to
+    // have the orientation emulated.
+    private boolean mForceDefaultOrientation;
+
+    private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+    @VisibleForTesting
+    int mLandscapeRotation;  // default landscape
+    @VisibleForTesting
+    int mSeascapeRotation;   // "other" landscape, 180 degrees from mLandscapeRotation
+    @VisibleForTesting
+    int mPortraitRotation;   // default portrait
+    @VisibleForTesting
+    int mUpsideDownRotation; // "other" portrait
+
+    // Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION)
+    private int mShowRotationSuggestions;
+
+    private int mAllowAllRotations = -1;
+    private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
+    private int mUserRotation = Surface.ROTATION_0;
+
+    private int mDemoHdmiRotation;
+    private int mDemoRotation;
+    private boolean mDemoHdmiRotationLock;
+    private boolean mDemoRotationLock;
+
+    DisplayRotation(WindowManagerService service, DisplayContent displayContent) {
+        this(service, displayContent, displayContent.getDisplayPolicy(),
+                service.mContext, service.getWindowManagerLock());
+    }
+
+    @VisibleForTesting
+    DisplayRotation(WindowManagerService service, DisplayContent displayContent,
+            DisplayPolicy displayPolicy, Context context, Object lock) {
+        mService = service;
+        mDisplayPolicy = displayPolicy;
+        mContext = context;
+        mLock = lock;
+        isDefaultDisplay = displayContent.isDefaultDisplay;
+
+        mSupportAutoRotation = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_supportAutoRotation);
+        mLidOpenRotation = readRotation(
+                com.android.internal.R.integer.config_lidOpenRotation);
+        mCarDockRotation = readRotation(
+                com.android.internal.R.integer.config_carDockRotation);
+        mDeskDockRotation = readRotation(
+                com.android.internal.R.integer.config_deskDockRotation);
+        mUndockedHdmiRotation = readRotation(
+                com.android.internal.R.integer.config_undockedHdmiRotation);
+
+        if (isDefaultDisplay) {
+            final Handler uiHandler = UiThread.getHandler();
+            mOrientationListener = new OrientationListener(mContext, uiHandler);
+            mOrientationListener.setCurrentRotation(displayContent.getRotation());
+            mSettingsObserver = new SettingsObserver(uiHandler);
+            mSettingsObserver.observe();
+        }
+    }
+
+    private int readRotation(int resID) {
+        try {
+            final int rotation = mContext.getResources().getInteger(resID);
+            switch (rotation) {
+                case 0:
+                    return Surface.ROTATION_0;
+                case 90:
+                    return Surface.ROTATION_90;
+                case 180:
+                    return Surface.ROTATION_180;
+                case 270:
+                    return Surface.ROTATION_270;
+            }
+        } catch (Resources.NotFoundException e) {
+            // fall through
+        }
+        return -1;
+    }
+
+    void configure(int width, int height, int shortSizeDp, int longSizeDp) {
+        final Resources res = mContext.getResources();
+        if (width > height) {
+            mLandscapeRotation = Surface.ROTATION_0;
+            mSeascapeRotation = Surface.ROTATION_180;
+            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
+                mPortraitRotation = Surface.ROTATION_90;
+                mUpsideDownRotation = Surface.ROTATION_270;
+            } else {
+                mPortraitRotation = Surface.ROTATION_270;
+                mUpsideDownRotation = Surface.ROTATION_90;
+            }
+        } else {
+            mPortraitRotation = Surface.ROTATION_0;
+            mUpsideDownRotation = Surface.ROTATION_180;
+            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
+                mLandscapeRotation = Surface.ROTATION_270;
+                mSeascapeRotation = Surface.ROTATION_90;
+            } else {
+                mLandscapeRotation = Surface.ROTATION_90;
+                mSeascapeRotation = Surface.ROTATION_270;
+            }
+        }
+
+        // For demo purposes, allow the rotation of the HDMI display to be controlled.
+        // By default, HDMI locks rotation to landscape.
+        if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
+            mDemoHdmiRotation = mPortraitRotation;
+        } else {
+            mDemoHdmiRotation = mLandscapeRotation;
+        }
+        mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
+
+        // For demo purposes, allow the rotation of the remote display to be controlled.
+        // By default, remote display locks rotation to landscape.
+        if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
+            mDemoRotation = mPortraitRotation;
+        } else {
+            mDemoRotation = mLandscapeRotation;
+        }
+        mDemoRotationLock = SystemProperties.getBoolean("persist.demo.rotationlock", false);
+
+        // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
+        // http://developer.android.com/guide/practices/screens_support.html#range
+        // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
+        // so if the orientation is forced, we need to respect that no matter what.
+        final boolean isCar = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_AUTOMOTIVE);
+        // For TV, it's usually 960dp x 540dp, ignore the size limitation.
+        // so if the orientation is forced, we need to respect that no matter what.
+        final boolean isTv = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_LEANBACK);
+        mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
+                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
+                // For debug purposes the next line turns this feature off with:
+                // $ adb shell setprop config.override_forced_orient true
+                // $ adb shell wm size reset
+                !"true".equals(SystemProperties.get("config.override_forced_orient"));
+    }
+
+    void setRotation(int rotation) {
+        if (mOrientationListener != null) {
+            mOrientationListener.setCurrentRotation(rotation);
+        }
+    }
+
+    void setCurrentOrientation(int newOrientation) {
+        if (newOrientation != mCurrentAppOrientation) {
+            mCurrentAppOrientation = newOrientation;
+            if (isDefaultDisplay) {
+                updateOrientationListenerLw();
+            }
+        }
+    }
+
+    /** @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true. */
+    boolean isDefaultOrientationForced() {
+        return mForceDefaultOrientation;
+    }
+
+    public int getLandscapeRotation() {
+        return mLandscapeRotation;
+    }
+
+    public int getSeascapeRotation() {
+        return mSeascapeRotation;
+    }
+
+    public int getPortraitRotation() {
+        return mPortraitRotation;
+    }
+
+    public int getUpsideDownRotation() {
+        return mUpsideDownRotation;
+    }
+
+    public int getCurrentAppOrientation() {
+        return mCurrentAppOrientation;
+    }
+
+    public DisplayPolicy getDisplayPolicy() {
+        return mDisplayPolicy;
+    }
+
+    public WindowOrientationListener getOrientationListener() {
+        return mOrientationListener;
+    }
+
+    public int getUserRotation() {
+        return mUserRotation;
+    }
+
+    public int getUserRotationMode() {
+        return mUserRotationMode;
+    }
+
+    public void updateOrientationListener() {
+        synchronized (mLock) {
+            updateOrientationListenerLw();
+        }
+    }
+
+    /**
+     * Various use cases for invoking this function:
+     * <li>Screen turning off, should always disable listeners if already enabled.</li>
+     * <li>Screen turned on and current app has sensor based orientation, enable listeners
+     *     if not already enabled.</li>
+     * <li>Screen turned on and current app does not have sensor orientation, disable listeners
+     *     if already enabled.</li>
+     * <li>Screen turning on and current app has sensor based orientation, enable listeners
+     *     if needed.</li>
+     * <li>screen turning on and current app has nosensor based orientation, do nothing.</li>
+     */
+    private void updateOrientationListenerLw() {
+        if (mOrientationListener == null || !mOrientationListener.canDetectOrientation()) {
+            // If sensor is turned off or nonexistent for some reason.
+            return;
+        }
+
+        final boolean screenOnEarly = mDisplayPolicy.isScreenOnEarly();
+        final boolean awake = mDisplayPolicy.isAwake();
+        final boolean keyguardDrawComplete = mDisplayPolicy.isKeyguardDrawComplete();
+        final boolean windowManagerDrawComplete = mDisplayPolicy.isWindowManagerDrawComplete();
+
+        // Could have been invoked due to screen turning on or off or
+        // change of the currently visible window's orientation.
+        if (DEBUG_ORIENTATION) Slog.v(TAG, "screenOnEarly=" + screenOnEarly
+                + ", awake=" + awake + ", currentAppOrientation=" + mCurrentAppOrientation
+                + ", orientationSensorEnabled=" + mOrientationListener.mEnabled
+                + ", keyguardDrawComplete=" + keyguardDrawComplete
+                + ", windowManagerDrawComplete=" + windowManagerDrawComplete);
+
+        boolean disable = true;
+        // Note: We postpone the rotating of the screen until the keyguard as well as the
+        // window manager have reported a draw complete or the keyguard is going away in dismiss
+        // mode.
+        if (screenOnEarly && awake && ((keyguardDrawComplete && windowManagerDrawComplete))) {
+            if (needSensorRunning()) {
+                disable = false;
+                // Enable listener if not already enabled.
+                if (!mOrientationListener.mEnabled) {
+                    // Don't clear the current sensor orientation if the keyguard is going away in
+                    // dismiss mode. This allows window manager to use the last sensor reading to
+                    // determine the orientation vs. falling back to the last known orientation if
+                    // the sensor reading was cleared which can cause it to relaunch the app that
+                    // will show in the wrong orientation first before correcting leading to app
+                    // launch delays.
+                    mOrientationListener.enable(true /* clearCurrentRotation */);
+                }
+            }
+        }
+        // Check if sensors need to be disabled.
+        if (disable && mOrientationListener.mEnabled) {
+            mOrientationListener.disable();
+        }
+    }
+
+    /**
+     * We always let the sensor be switched on by default except when
+     * the user has explicitly disabled sensor based rotation or when the
+     * screen is switched off.
+     */
+    private boolean needSensorRunning() {
+        if (mSupportAutoRotation) {
+            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
+                // If the application has explicitly requested to follow the
+                // orientation, then we need to turn the sensor on.
+                return true;
+            }
+        }
+
+        final int dockMode = mDisplayPolicy.getDockMode();
+        if ((mDisplayPolicy.isCarDockEnablesAccelerometer()
+                && dockMode == Intent.EXTRA_DOCK_STATE_CAR)
+                || (mDisplayPolicy.isDeskDockEnablesAccelerometer()
+                        && (dockMode == Intent.EXTRA_DOCK_STATE_DESK
+                                || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+                                || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
+            // Enable accelerometer if we are docked in a dock that enables accelerometer
+            // orientation management.
+            return true;
+        }
+
+        if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
+            // If the setting for using the sensor by default is enabled, then
+            // we will always leave it on.  Note that the user could go to
+            // a window that forces an orientation that does not use the
+            // sensor and in theory we could turn it off... however, when next
+            // turning it on we won't have a good value for the current
+            // orientation for a little bit, which can cause orientation
+            // changes to lag, so we'd like to keep it always on.  (It will
+            // still be turned off when the screen is off.)
+
+            // When locked we can provide rotation suggestions users can approve to change the
+            // current screen rotation. To do this the sensor needs to be running.
+            return mSupportAutoRotation &&
+                    mShowRotationSuggestions == Settings.Secure.SHOW_ROTATION_SUGGESTIONS_ENABLED;
+        }
+        return mSupportAutoRotation;
+    }
+
+    /**
+     * Given an orientation constant, returns the appropriate surface rotation,
+     * taking into account sensors, docking mode, rotation lock, and other factors.
+     *
+     * @param orientation An orientation constant, such as
+     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
+     * @param lastRotation The most recently used rotation.
+     * @param defaultDisplay Flag indicating whether the rotation is computed for the default
+     *                       display. Currently for all non-default displays sensors, docking mode,
+     *                       rotation lock and other factors are ignored.
+     * @return The surface rotation to use.
+     */
+    int rotationForOrientation(int orientation, int lastRotation) {
+        if (DEBUG_ORIENTATION) {
+            Slog.v(TAG, "rotationForOrientation(orient="
+                        + orientation + ", last=" + lastRotation
+                        + "); user=" + mUserRotation + " "
+                        + (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
+                            ? "USER_ROTATION_LOCKED" : "")
+                        );
+        }
+
+        if (mForceDefaultOrientation) {
+            return Surface.ROTATION_0;
+        }
+
+        int sensorRotation = mOrientationListener != null
+                ? mOrientationListener.getProposedRotation() // may be -1
+                : -1;
+        if (sensorRotation < 0) {
+            sensorRotation = lastRotation;
+        }
+
+        final int lidState = mDisplayPolicy.getLidState();
+        final int dockMode = mDisplayPolicy.getDockMode();
+        final boolean hdmiPlugged = mDisplayPolicy.isHdmiPlugged();
+        final boolean carDockEnablesAccelerometer =
+                mDisplayPolicy.isCarDockEnablesAccelerometer();
+        final boolean deskDockEnablesAccelerometer =
+                mDisplayPolicy.isDeskDockEnablesAccelerometer();
+
+        final int preferredRotation;
+        if (!isDefaultDisplay) {
+            // For secondary displays we ignore things like displays sensors, docking mode and
+            // rotation lock, and always prefer a default rotation.
+            preferredRotation = Surface.ROTATION_0;
+        } else if (lidState == LID_OPEN && mLidOpenRotation >= 0) {
+            // Ignore sensor when lid switch is open and rotation is forced.
+            preferredRotation = mLidOpenRotation;
+        } else if (dockMode == Intent.EXTRA_DOCK_STATE_CAR
+                && (carDockEnablesAccelerometer || mCarDockRotation >= 0)) {
+            // Ignore sensor when in car dock unless explicitly enabled.
+            // This case can override the behavior of NOSENSOR, and can also
+            // enable 180 degree rotation while docked.
+            preferredRotation = carDockEnablesAccelerometer ? sensorRotation : mCarDockRotation;
+        } else if ((dockMode == Intent.EXTRA_DOCK_STATE_DESK
+                || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+                || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
+                && (deskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
+            // Ignore sensor when in desk dock unless explicitly enabled.
+            // This case can override the behavior of NOSENSOR, and can also
+            // enable 180 degree rotation while docked.
+            preferredRotation = deskDockEnablesAccelerometer ? sensorRotation : mDeskDockRotation;
+        } else if (hdmiPlugged && mDemoHdmiRotationLock) {
+            // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
+            // Note that the dock orientation overrides the HDMI orientation.
+            preferredRotation = mDemoHdmiRotation;
+        } else if (hdmiPlugged && dockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
+                && mUndockedHdmiRotation >= 0) {
+            // Ignore sensor when plugged into HDMI and an undocked orientation has
+            // been specified in the configuration (only for legacy devices without
+            // full multi-display support).
+            // Note that the dock orientation overrides the HDMI orientation.
+            preferredRotation = mUndockedHdmiRotation;
+        } else if (mDemoRotationLock) {
+            // Ignore sensor when demo rotation lock is enabled.
+            // Note that the dock orientation and HDMI rotation lock override this.
+            preferredRotation = mDemoRotation;
+        } else if (mDisplayPolicy.isPersistentVrModeEnabled()) {
+            // While in VR, apps always prefer a portrait rotation. This does not change
+            // any apps that explicitly set landscape, but does cause sensors be ignored,
+            // and ignored any orientation lock that the user has set (this conditional
+            // should remain above the ORIENTATION_LOCKED conditional below).
+            preferredRotation = mPortraitRotation;
+        } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
+            // Application just wants to remain locked in the last rotation.
+            preferredRotation = lastRotation;
+        } else if (!mSupportAutoRotation) {
+            // If we don't support auto-rotation then bail out here and ignore
+            // the sensor and any rotation lock settings.
+            preferredRotation = -1;
+        } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
+                        && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
+                                || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+                                || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
+                                || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
+                                || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
+                || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
+                || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+                || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
+                || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
+            // Otherwise, use sensor only if requested by the application or enabled
+            // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
+            if (mAllowAllRotations < 0) {
+                // Can't read this during init() because the context doesn't
+                // have display metrics at that time so we cannot determine
+                // tablet vs. phone then.
+                mAllowAllRotations = mContext.getResources().getBoolean(
+                        com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
+            }
+            if (sensorRotation != Surface.ROTATION_180
+                    || mAllowAllRotations == 1
+                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
+                preferredRotation = sensorRotation;
+            } else {
+                preferredRotation = lastRotation;
+            }
+        } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
+                && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+            // Apply rotation lock.  Does not apply to NOSENSOR.
+            // The idea is that the user rotation expresses a weak preference for the direction
+            // of gravity and as NOSENSOR is never affected by gravity, then neither should
+            // NOSENSOR be affected by rotation lock (although it will be affected by docks).
+            preferredRotation = mUserRotation;
+        } else {
+            // No overriding preference.
+            // We will do exactly what the application asked us to do.
+            preferredRotation = -1;
+        }
+
+        switch (orientation) {
+            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
+                // Return portrait unless overridden.
+                if (isAnyPortrait(preferredRotation)) {
+                    return preferredRotation;
+                }
+                return mPortraitRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
+                // Return landscape unless overridden.
+                if (isLandscapeOrSeascape(preferredRotation)) {
+                    return preferredRotation;
+                }
+                return mLandscapeRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+                // Return reverse portrait unless overridden.
+                if (isAnyPortrait(preferredRotation)) {
+                    return preferredRotation;
+                }
+                return mUpsideDownRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+                // Return seascape unless overridden.
+                if (isLandscapeOrSeascape(preferredRotation)) {
+                    return preferredRotation;
+                }
+                return mSeascapeRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+                // Return either landscape rotation.
+                if (isLandscapeOrSeascape(preferredRotation)) {
+                    return preferredRotation;
+                }
+                if (isLandscapeOrSeascape(lastRotation)) {
+                    return lastRotation;
+                }
+                return mLandscapeRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+                // Return either portrait rotation.
+                if (isAnyPortrait(preferredRotation)) {
+                    return preferredRotation;
+                }
+                if (isAnyPortrait(lastRotation)) {
+                    return lastRotation;
+                }
+                return mPortraitRotation;
+
+            default:
+                // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
+                // just return the preferred orientation we already calculated.
+                if (preferredRotation >= 0) {
+                    return preferredRotation;
+                }
+                return Surface.ROTATION_0;
+        }
+    }
+
+    private boolean isLandscapeOrSeascape(int rotation) {
+        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
+    }
+
+    private boolean isAnyPortrait(int rotation) {
+        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
+    }
+
+    /**
+     * Given an orientation constant and a rotation, returns true if the rotation
+     * has compatible metrics to the requested orientation.  For example, if
+     * the application requested landscape and got seascape, then the rotation
+     * has compatible metrics; if the application requested portrait and got landscape,
+     * then the rotation has incompatible metrics; if the application did not specify
+     * a preference, then anything goes.
+     *
+     * @param orientation An orientation constant, such as
+     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
+     * @param rotation The rotation to check.
+     * @return True if the rotation is compatible with the requested orientation.
+     */
+    boolean rotationHasCompatibleMetrics(int orientation, int rotation) {
+        switch (orientation) {
+            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
+            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+                return isAnyPortrait(rotation);
+
+            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
+            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+                return isLandscapeOrSeascape(rotation);
+
+            default:
+                return true;
+        }
+    }
+
+    private boolean isValidRotationChoice(final int preferredRotation) {
+        // Determine if the given app orientation is compatible with the provided rotation choice.
+        switch (mCurrentAppOrientation) {
+            case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
+                // Works with any of the 4 rotations.
+                return preferredRotation >= 0;
+
+            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+                // It's possible for the user pref to be set at 180 because of FULL_USER. This would
+                // make switching to USER_PORTRAIT appear at 180. Provide choice to back to portrait
+                // but never to go to 180.
+                return preferredRotation == mPortraitRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+                // Works landscape or seascape.
+                return isLandscapeOrSeascape(preferredRotation);
+
+            case ActivityInfo.SCREEN_ORIENTATION_USER:
+            case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
+                // Works with any rotation except upside down.
+                return (preferredRotation >= 0) && (preferredRotation != mUpsideDownRotation);
+        }
+
+        return false;
+    }
+
+    private boolean isRotationChoicePossible(int orientation) {
+        // Rotation choice is only shown when the user is in locked mode.
+        if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
+
+        // We should only enable rotation choice if the rotation isn't forced by the lid, dock,
+        // demo, hdmi, vr, etc mode.
+
+        // Determine if the rotation is currently forced.
+        if (mForceDefaultOrientation) {
+            return false; // Rotation is forced to default orientation.
+        }
+
+        final int lidState = mDisplayPolicy.getLidState();
+        if (lidState == LID_OPEN && mLidOpenRotation >= 0) {
+            return false; // Rotation is forced mLidOpenRotation.
+        }
+
+        final int dockMode = mDisplayPolicy.getDockMode();
+        final boolean carDockEnablesAccelerometer = false;
+        if (dockMode == Intent.EXTRA_DOCK_STATE_CAR && !carDockEnablesAccelerometer) {
+            return false; // Rotation forced to mCarDockRotation.
+        }
+
+        final boolean deskDockEnablesAccelerometer =
+                mDisplayPolicy.isDeskDockEnablesAccelerometer();
+        if ((dockMode == Intent.EXTRA_DOCK_STATE_DESK
+                || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+                || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
+                && !deskDockEnablesAccelerometer) {
+            return false; // Rotation forced to mDeskDockRotation.
+        }
+
+        final boolean hdmiPlugged = mDisplayPolicy.isHdmiPlugged();
+        if (hdmiPlugged && mDemoHdmiRotationLock) {
+            return false; // Rotation forced to mDemoHdmiRotation.
+
+        } else if (hdmiPlugged && dockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
+                && mUndockedHdmiRotation >= 0) {
+            return false; // Rotation forced to mUndockedHdmiRotation.
+
+        } else if (mDemoRotationLock) {
+            return false; // Rotation forced to mDemoRotation.
+
+        } else if (mDisplayPolicy.isPersistentVrModeEnabled()) {
+            return false; // Rotation forced to mPortraitRotation.
+
+        } else if (!mSupportAutoRotation) {
+            return false;
+        }
+
+        // Ensure that some rotation choice is possible for the given orientation.
+        switch (orientation) {
+            case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
+            case ActivityInfo.SCREEN_ORIENTATION_USER:
+            case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
+            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+                // NOSENSOR description is ambiguous, in reality WM ignores user choice.
+                return true;
+        }
+
+        // Rotation is forced, should be controlled by system.
+        return false;
+    }
+
+    /** Notify the StatusBar that system rotation suggestion has changed. */
+    private void sendProposedRotationChangeToStatusBarInternal(int rotation, boolean isValid) {
+        if (mStatusBarManagerInternal == null) {
+            mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
+        }
+        if (mStatusBarManagerInternal != null) {
+            mStatusBarManagerInternal.onProposedRotationChanged(rotation, isValid);
+        }
+    }
+
+    private static String allowAllRotationsToString(int allowAll) {
+        switch (allowAll) {
+            case -1:
+                return "unknown";
+            case 0:
+                return "false";
+            case 1:
+                return "true";
+            default:
+                return Integer.toString(allowAll);
+        }
+    }
+
+    public void onUserSwitch() {
+        if (mSettingsObserver != null) {
+            mSettingsObserver.onChange(false);
+        }
+    }
+
+    /** Return whether the rotation settings has changed. */
+    private boolean updateSettings() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        boolean shouldUpdateRotation = false;
+
+        synchronized (mLock) {
+            boolean shouldUpdateOrientationListener = false;
+
+            // Configure rotation suggestions.
+            final int showRotationSuggestions = Settings.Secure.getIntForUser(resolver,
+                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
+                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS_DEFAULT,
+                    UserHandle.USER_CURRENT);
+            if (mShowRotationSuggestions != showRotationSuggestions) {
+                mShowRotationSuggestions = showRotationSuggestions;
+                shouldUpdateOrientationListener = true;
+            }
+
+            // Configure rotation lock.
+            final int userRotation = Settings.System.getIntForUser(resolver,
+                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
+                    UserHandle.USER_CURRENT);
+            if (mUserRotation != userRotation) {
+                mUserRotation = userRotation;
+                shouldUpdateRotation = true;
+            }
+
+            final int userRotationMode = Settings.System.getIntForUser(resolver,
+                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0
+                            ? WindowManagerPolicy.USER_ROTATION_FREE
+                            : WindowManagerPolicy.USER_ROTATION_LOCKED;
+            if (mUserRotationMode != userRotationMode) {
+                mUserRotationMode = userRotationMode;
+                shouldUpdateOrientationListener = true;
+                shouldUpdateRotation = true;
+            }
+
+            if (shouldUpdateOrientationListener) {
+                updateOrientationListenerLw(); // Enable or disable the orientation listener.
+            }
+        }
+
+        return shouldUpdateRotation;
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        pw.println(prefix + "DisplayRotation");
+        pw.println(prefix + "  mCurrentAppOrientation="
+                + ActivityInfo.screenOrientationToString(mCurrentAppOrientation));
+        pw.print(prefix + "  mLandscapeRotation=" + Surface.rotationToString(mLandscapeRotation));
+        pw.println(" mSeascapeRotation=" + Surface.rotationToString(mSeascapeRotation));
+        pw.print(prefix + "  mPortraitRotation=" + Surface.rotationToString(mPortraitRotation));
+        pw.println(" mUpsideDownRotation=" + Surface.rotationToString(mUpsideDownRotation));
+
+        pw.print(prefix + "  mSupportAutoRotation=" + mSupportAutoRotation);
+        if (mOrientationListener != null) {
+            pw.print(" mOrientationSensorEnabled=" + mOrientationListener.mEnabled);
+        }
+        pw.println();
+
+        pw.print(prefix + "  mCarDockRotation=" + Surface.rotationToString(mCarDockRotation));
+        pw.println(" mDeskDockRotation=" + Surface.rotationToString(mDeskDockRotation));
+        pw.print(prefix + "  mUserRotationMode="
+                + WindowManagerPolicy.userRotationModeToString(mUserRotationMode));
+        pw.print(" mUserRotation=" + Surface.rotationToString(mUserRotation));
+        pw.println(" mAllowAllRotations=" + allowAllRotationsToString(mAllowAllRotations));
+
+        pw.print(prefix + "  mDemoHdmiRotation=" + Surface.rotationToString(mDemoHdmiRotation));
+        pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
+        pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
+        pw.println(prefix + "  mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
+    }
+
+    private class OrientationListener extends WindowOrientationListener {
+        final SparseArray<Runnable> mRunnableCache = new SparseArray<>(5);
+        boolean mEnabled;
+
+        OrientationListener(Context context, Handler handler) {
+            super(context, handler);
+        }
+
+        private class UpdateRunnable implements Runnable {
+            final int mRotation;
+
+            UpdateRunnable(int rotation) {
+                mRotation = rotation;
+            }
+
+            @Override
+            public void run() {
+                // Send interaction hint to improve redraw performance.
+                mService.mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
+                if (isRotationChoicePossible(mCurrentAppOrientation)) {
+                    final boolean isValid = isValidRotationChoice(mRotation);
+                    sendProposedRotationChangeToStatusBarInternal(mRotation, isValid);
+                } else {
+                    mService.updateRotation(false /* alwaysSendConfiguration */,
+                            false /* forceRelayout */);
+                }
+            }
+        }
+
+        @Override
+        public void onProposedRotationChanged(int rotation) {
+            if (DEBUG_ORIENTATION) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
+            Runnable r = mRunnableCache.get(rotation, null);
+            if (r == null) {
+                r = new UpdateRunnable(rotation);
+                mRunnableCache.put(rotation, r);
+            }
+            getHandler().post(r);
+        }
+
+        @Override
+        public void enable(boolean clearCurrentRotation) {
+            super.enable(clearCurrentRotation);
+            mEnabled = true;
+            if (DEBUG_ORIENTATION) Slog.v(TAG, "Enabling listeners");
+        }
+
+        @Override
+        public void disable() {
+            super.disable();
+            mEnabled = false;
+            if (DEBUG_ORIENTATION) Slog.v(TAG, "Disabling listeners");
+        }
+    }
+
+    private class SettingsObserver extends ContentObserver {
+        SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        void observe() {
+            final ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS), false, this,
+                    UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.ACCELEROMETER_ROTATION), false, this,
+                    UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.USER_ROTATION), false, this,
+                    UserHandle.USER_ALL);
+            updateSettings();
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            if (updateSettings()) {
+                mService.updateRotation(true /* alwaysSendConfiguration */,
+                        false /* forceRelayout */);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
index 97b64dc..bbb690f 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplaySettings.java
@@ -19,12 +19,19 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
+import android.app.WindowConfiguration;
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.os.Environment;
+import android.provider.Settings;
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.Xml;
+import android.view.Display;
+import android.view.DisplayInfo;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 
@@ -43,37 +50,48 @@
 /**
  * Current persistent settings about a display
  */
-public class DisplaySettings {
+class DisplaySettings {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplaySettings" : TAG_WM;
 
+    private final WindowManagerService mService;
     private final AtomicFile mFile;
     private final HashMap<String, Entry> mEntries = new HashMap<String, Entry>();
 
-    public static class Entry {
-        public final String name;
-        public int overscanLeft;
-        public int overscanTop;
-        public int overscanRight;
-        public int overscanBottom;
+    private static class Entry {
+        private final String name;
+        private int overscanLeft;
+        private int overscanTop;
+        private int overscanRight;
+        private int overscanBottom;
+        private int windowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
-        public Entry(String _name) {
+        private Entry(String _name) {
             name = _name;
         }
     }
 
-    public DisplaySettings() {
-        File dataDir = Environment.getDataDirectory();
-        File systemDir = new File(dataDir, "system");
-        mFile = new AtomicFile(new File(systemDir, "display_settings.xml"), "wm-displays");
+    DisplaySettings(WindowManagerService service) {
+        this(service, new File(Environment.getDataDirectory(), "system"));
     }
 
-    public void getOverscanLocked(String name, String uniqueId, Rect outRect) {
+    @VisibleForTesting
+    DisplaySettings(WindowManagerService service, File folder) {
+        mService = service;
+        mFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays");
+    }
+
+    private Entry getEntry(String name, String uniqueId) {
         // Try to get the entry with the unique if possible.
         // Else, fall back on the display name.
         Entry entry;
         if (uniqueId == null || (entry = mEntries.get(uniqueId)) == null) {
             entry = mEntries.get(name);
         }
+        return entry;
+    }
+
+    private void getOverscanLocked(String name, String uniqueId, Rect outRect) {
+        final Entry entry = getEntry(name, uniqueId);
         if (entry != null) {
             outRect.left = entry.overscanLeft;
             outRect.top = entry.overscanTop;
@@ -84,7 +102,7 @@
         }
     }
 
-    public void setOverscanLocked(String uniqueId, String name, int left, int top, int right,
+    void setOverscanLocked(String uniqueId, String name, int left, int top, int right,
             int bottom) {
         if (left == 0 && top == 0 && right == 0 && bottom == 0) {
             // Right now all we are storing is overscan; if there is no overscan,
@@ -105,7 +123,47 @@
         entry.overscanBottom = bottom;
     }
 
-    public void readSettingsLocked() {
+    private int getWindowingModeLocked(String name, String uniqueId, int displayId) {
+        final Entry entry = getEntry(name, uniqueId);
+        int windowingMode = entry != null ? entry.windowingMode
+                : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+        // This display used to be in freeform, but we don't support freeform anymore, so fall
+        // back to fullscreen.
+        if (windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
+                && !mService.mSupportsFreeformWindowManagement) {
+            return WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+        }
+        // No record is present so use default windowing mode policy.
+        if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
+            if (displayId == Display.DEFAULT_DISPLAY) {
+                windowingMode = (mService.mIsPc && mService.mSupportsFreeformWindowManagement)
+                        ? WindowConfiguration.WINDOWING_MODE_FREEFORM
+                        : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+            } else {
+                windowingMode = mService.mSupportsFreeformWindowManagement
+                        ? WindowConfiguration.WINDOWING_MODE_FREEFORM
+                        : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+            }
+        }
+        return windowingMode;
+    }
+
+    void applySettingsToDisplayLocked(DisplayContent dc) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+
+        // Setting windowing mode first, because it may override overscan values later.
+        dc.setWindowingMode(getWindowingModeLocked(displayInfo.name, displayInfo.uniqueId,
+                dc.getDisplayId()));
+
+        final Rect rect = new Rect();
+        getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
+        displayInfo.overscanLeft = rect.left;
+        displayInfo.overscanTop = rect.top;
+        displayInfo.overscanRight = rect.right;
+        displayInfo.overscanBottom = rect.bottom;
+    }
+
+    void readSettingsLocked() {
         FileInputStream stream;
         try {
             stream = mFile.openRead();
@@ -169,11 +227,15 @@
     }
 
     private int getIntAttribute(XmlPullParser parser, String name) {
+        return getIntAttribute(parser, name, 0 /* defaultValue */);
+    }
+
+    private int getIntAttribute(XmlPullParser parser, String name, int defaultValue) {
         try {
             String str = parser.getAttributeValue(null, name);
-            return str != null ? Integer.parseInt(str) : 0;
+            return str != null ? Integer.parseInt(str) : defaultValue;
         } catch (NumberFormatException e) {
-            return 0;
+            return defaultValue;
         }
     }
 
@@ -186,12 +248,14 @@
             entry.overscanTop = getIntAttribute(parser, "overscanTop");
             entry.overscanRight = getIntAttribute(parser, "overscanRight");
             entry.overscanBottom = getIntAttribute(parser, "overscanBottom");
+            entry.windowingMode = getIntAttribute(parser, "windowingMode",
+                    WindowConfiguration.WINDOWING_MODE_UNDEFINED);
             mEntries.put(name, entry);
         }
         XmlUtils.skipCurrentTag(parser);
     }
 
-    public void writeSettingsLocked() {
+    void writeSettingsLocked() {
         FileOutputStream stream;
         try {
             stream = mFile.startWrite();
@@ -221,6 +285,9 @@
                 if (entry.overscanBottom != 0) {
                     out.attribute(null, "overscanBottom", Integer.toString(entry.overscanBottom));
                 }
+                if (entry.windowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
+                    out.attribute(null, "windowingMode", Integer.toString(entry.windowingMode));
+                }
                 out.endTag(null, "display");
             }
 
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index a1639c2..74a8a35 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -76,7 +76,8 @@
     /**
      * Positions the task stack at the given position in the task stack container.
      */
-    public void positionChildAt(StackWindowController child, int position) {
+    public void positionChildAt(StackWindowController child, int position,
+            boolean includingParents) {
         synchronized (mWindowMap) {
             if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskStackAt: positioning stack=" + child
                     + " at " + position);
@@ -90,7 +91,7 @@
                         "positionTaskStackAt: could not find stack=" + this);
                 return;
             }
-            mContainer.positionStackAt(position, child.mContainer);
+            mContainer.positionStackAt(position, child.mContainer, includingParents);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DragAndDropPermissionsHandler.java b/services/core/java/com/android/server/wm/DragAndDropPermissionsHandler.java
index 51d5eea..20a13334 100644
--- a/services/core/java/com/android/server/wm/DragAndDropPermissionsHandler.java
+++ b/services/core/java/com/android/server/wm/DragAndDropPermissionsHandler.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
+import android.app.UriGrantsManager;
 import android.content.ClipData;
 import android.net.Uri;
 import android.os.Binder;
@@ -25,6 +26,8 @@
 import android.os.RemoteException;
 
 import com.android.internal.view.IDragAndDropPermissions;
+import com.android.server.LocalServices;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 import java.util.ArrayList;
 
@@ -72,7 +75,7 @@
         long origId = Binder.clearCallingIdentity();
         try {
             for (int i = 0; i < mUris.size(); i++) {
-                ActivityManager.getService().grantUriPermissionFromOwner(
+                UriGrantsManager.getService().grantUriPermissionFromOwner(
                         permissionOwner, mSourceUid, mTargetPackage, mUris.get(i), mMode,
                         mSourceUserId, mTargetUserId);
             }
@@ -86,7 +89,8 @@
         if (mActivityToken != null || mPermissionOwnerToken != null) {
             return;
         }
-        mPermissionOwnerToken = ActivityManager.getService().newUriPermissionOwner("drop");
+        mPermissionOwnerToken = LocalServices.getService(UriGrantsManagerInternal.class)
+                .newUriPermissionOwner("drop");
         mTransientToken = transientToken;
         mTransientToken.linkToDeath(this, 0);
 
@@ -117,9 +121,9 @@
             mTransientToken = null;
         }
 
+        UriGrantsManagerInternal ugm = LocalServices.getService(UriGrantsManagerInternal.class);
         for (int i = 0; i < mUris.size(); ++i) {
-            ActivityManager.getService().revokeUriPermissionFromOwner(
-                    permissionOwner, mUris.get(i), mMode, mSourceUserId);
+            ugm.revokeUriPermissionFromOwner(permissionOwner, mUris.get(i), mMode, mSourceUserId);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index fc370d9..f42e979 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -151,6 +151,7 @@
                     mDragState.mUid = callerUid;
                     mDragState.mOriginalAlpha = alpha;
                     mDragState.mToken = dragToken;
+                    mDragState.mDisplayContent = displayContent;
 
                     final Display display = displayContent.getDisplay();
                     if (!mCallback.get().registerInputChannel(
@@ -160,7 +161,6 @@
                         return null;
                     }
 
-                    mDragState.mDisplayContent = displayContent;
                     mDragState.mData = data;
                     mDragState.broadcastDragStartedLocked(touchX, touchY);
                     mDragState.overridePointerIconLocked(touchSource);
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 1ac9b88..5483602 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -143,7 +143,7 @@
             mDragDropController.sendHandlerMessage(
                     MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT, mInputInterceptor);
             mInputInterceptor = null;
-            mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+            mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
         }
 
         // Send drag end broadcast if drag start has been sent.
@@ -255,7 +255,7 @@
             if (DEBUG_ORIENTATION) {
                 Slog.d(TAG_WM, "Pausing rotation during drag");
             }
-            mService.pauseRotationLocked();
+            mDisplayContent.pauseRotationLocked();
         }
 
         void tearDown() {
@@ -274,7 +274,7 @@
             if (DEBUG_ORIENTATION) {
                 Slog.d(TAG_WM, "Resuming rotation after drag");
             }
-            mService.resumeRotationLocked();
+            mDisplayContent.resumeRotationLocked();
         }
     }
 
@@ -296,7 +296,7 @@
             Slog.e(TAG_WM, "Duplicate register of drag input channel");
         } else {
             mInputInterceptor = new InputInterceptor(display);
-            mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+            mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java
new file mode 100644
index 0000000..f5e6e72
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import android.graphics.Matrix;
+import android.view.DisplayInfo;
+import android.view.Surface.Rotation;
+
+import com.android.server.wm.utils.CoordinateTransforms;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * Helper class for forced seamless rotation.
+ *
+ * Works by transforming the window token back into the old display rotation.
+ *
+ * Uses deferTransactionUntil instead of latching on the buffer size to allow for seamless 180
+ * degree rotations.
+ * TODO(b/111504081): Consolidate seamless rotation logic.
+ */
+public class ForcedSeamlessRotator {
+
+    private final Matrix mTransform = new Matrix();
+    private final float[] mFloat9 = new float[9];
+    private final int mOldRotation;
+    private final int mNewRotation;
+
+    public ForcedSeamlessRotator(int oldRotation, int newRotation, DisplayInfo info) {
+        mOldRotation = oldRotation;
+        mNewRotation = newRotation;
+
+        final boolean flipped = info.rotation == ROTATION_90 || info.rotation == ROTATION_270;
+        final int h = flipped ? info.logicalWidth : info.logicalHeight;
+        final int w = flipped ? info.logicalHeight : info.logicalWidth;
+
+        final Matrix tmp = new Matrix();
+        CoordinateTransforms.transformLogicalToPhysicalCoordinates(oldRotation, w, h, mTransform);
+        CoordinateTransforms.transformPhysicalToLogicalCoordinates(newRotation, w, h, tmp);
+        mTransform.postConcat(tmp);
+    }
+
+    /**
+     * Applies a transform to the window token's surface that undoes the effect of the global
+     * display rotation.
+     */
+    public void unrotate(WindowToken token) {
+        token.getPendingTransaction().setMatrix(token.getSurfaceControl(), mTransform, mFloat9);
+    }
+
+    /**
+     * Returns the rotation of the display before it started rotating.
+     *
+     * @return the old rotation of the display
+     */
+    @Rotation
+    public int getOldRotation() {
+        return mOldRotation;
+    }
+
+    /**
+     * Removes the transform to the window token's surface that undoes the effect of the global
+     * display rotation.
+     *
+     * Removing the transform and the result of the WindowState's layout are both tied to the
+     * WindowState's next frame, such that they apply at the same time the client draws the
+     * window in the new orientation.
+     */
+    public void finish(WindowToken token, WindowState win) {
+        mTransform.reset();
+        token.getPendingTransaction().setMatrix(token.mSurfaceControl, mTransform, mFloat9);
+        if (win.mWinAnimator.mSurfaceController != null) {
+            token.getPendingTransaction().deferTransactionUntil(token.mSurfaceControl,
+                    win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(),
+                    win.getFrameNumber());
+            win.getPendingTransaction().deferTransactionUntil(win.mSurfaceControl,
+                    win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(),
+                    win.getFrameNumber());
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.print("{old="); pw.print(mOldRotation); pw.print(", new="); pw.print(mNewRotation);
+        pw.print("}");
+    }
+
+    @Override
+    public String toString() {
+        StringWriter sw = new StringWriter();
+        dump(new PrintWriter(sw));
+        return "ForcedSeamlessRotator" + sw.toString();
+    }
+}
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index d40db8c..6a08f4d 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -40,7 +40,7 @@
     final UserHandle mClientUser;
 
     InputConsumerImpl(WindowManagerService service, IBinder token, String name,
-            InputChannel inputChannel, int clientPid, UserHandle clientUser) {
+            InputChannel inputChannel, int clientPid, UserHandle clientUser, int displayId) {
         mService = service;
         mToken = token;
         mName = name;
@@ -63,8 +63,7 @@
         mApplicationHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, null,
-                Display.DEFAULT_DISPLAY);
+        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, null, displayId);
         mWindowHandle.name = name;
         mWindowHandle.inputChannel = mServerChannel;
         mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
@@ -128,7 +127,9 @@
     public void binderDied() {
         synchronized (mService.getWindowManagerLock()) {
             // Clean up the input consumer
-            mService.mInputMonitor.destroyInputConsumer(mName);
+            final InputMonitor inputMonitor =
+                    mService.mRoot.getDisplayContent(mWindowHandle.displayId).getInputMonitor();
+            inputMonitor.destroyInputConsumer(mName);
             unlinkFromDeathRecipient();
         }
     }
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
new file mode 100644
index 0000000..b5e2f01
--- /dev/null
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -0,0 +1,275 @@
+package com.android.server.wm;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.app.ActivityManager;
+import android.os.Debug;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+
+import com.android.server.input.InputApplicationHandle;
+import com.android.server.input.InputManagerService;
+import com.android.server.input.InputWindowHandle;
+
+import java.io.PrintWriter;
+
+final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
+    private final WindowManagerService mService;
+
+    // Set to true when the first input device configuration change notification
+    // is received to indicate that the input devices are ready.
+    private final Object mInputDevicesReadyMonitor = new Object();
+    private boolean mInputDevicesReady;
+
+    // When true, prevents input dispatch from proceeding until set to false again.
+    private boolean mInputDispatchFrozen;
+
+    // The reason the input is currently frozen or null if the input isn't frozen.
+    private String mInputFreezeReason = null;
+
+    // When true, input dispatch proceeds normally.  Otherwise all events are dropped.
+    // Initially false, so that input does not get dispatched until boot is finished at
+    // which point the ActivityManager will enable dispatching.
+    private boolean mInputDispatchEnabled;
+
+    public InputManagerCallback(WindowManagerService service) {
+        mService = service;
+    }
+
+    /**
+     * Notifies the window manager about a broken input channel.
+     *
+     * Called by the InputManager.
+     */
+    @Override
+    public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+        if (inputWindowHandle == null) {
+            return;
+        }
+
+        synchronized (mService.mWindowMap) {
+            WindowState windowState = (WindowState) inputWindowHandle.windowState;
+            if (windowState != null) {
+                Slog.i(TAG_WM, "WINDOW DIED " + windowState);
+                windowState.removeIfPossible();
+            }
+        }
+    }
+
+    /**
+     * Notifies the window manager about an application that is not responding.
+     * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
+     *
+     * Called by the InputManager.
+     */
+    @Override
+    public long notifyANR(InputApplicationHandle inputApplicationHandle,
+            InputWindowHandle inputWindowHandle, String reason) {
+        AppWindowToken appWindowToken = null;
+        WindowState windowState = null;
+        boolean aboveSystem = false;
+        synchronized (mService.mWindowMap) {
+            if (inputWindowHandle != null) {
+                windowState = (WindowState) inputWindowHandle.windowState;
+                if (windowState != null) {
+                    appWindowToken = windowState.mAppToken;
+                }
+            }
+            if (appWindowToken == null && inputApplicationHandle != null) {
+                appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken;
+            }
+
+            if (windowState != null) {
+                Slog.i(TAG_WM, "Input event dispatching timed out "
+                        + "sending to " + windowState.mAttrs.getTitle()
+                        + ".  Reason: " + reason);
+                // Figure out whether this window is layered above system windows.
+                // We need to do this here to help the activity manager know how to
+                // layer its ANR dialog.
+                int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
+                        TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
+                aboveSystem = windowState.mBaseLayer > systemAlertLayer;
+            } else if (appWindowToken != null) {
+                Slog.i(TAG_WM, "Input event dispatching timed out "
+                        + "sending to application " + appWindowToken.stringName
+                        + ".  Reason: " + reason);
+            } else {
+                Slog.i(TAG_WM, "Input event dispatching timed out "
+                        + ".  Reason: " + reason);
+            }
+
+            mService.saveANRStateLocked(appWindowToken, windowState, reason);
+        }
+
+        // All the calls below need to happen without the WM lock held since they call into AM.
+        mService.mAmInternal.saveANRState(reason);
+
+        if (appWindowToken != null && appWindowToken.appToken != null) {
+            // Notify the activity manager about the timeout and let it decide whether
+            // to abort dispatching or keep waiting.
+            final AppWindowContainerController controller = appWindowToken.getController();
+            final boolean abort = controller != null
+                    && controller.keyDispatchingTimedOut(reason,
+                    (windowState != null) ? windowState.mSession.mPid : -1);
+            if (!abort) {
+                // The activity manager declined to abort dispatching.
+                // Wait a bit longer and timeout again later.
+                return appWindowToken.mInputDispatchingTimeoutNanos;
+            }
+        } else if (windowState != null) {
+            // Notify the activity manager about the timeout and let it decide whether
+            // to abort dispatching or keep waiting.
+            long timeout = mService.mAtmInternal.inputDispatchingTimedOut(
+                    windowState.mSession.mPid, aboveSystem, reason);
+            if (timeout >= 0) {
+                // The activity manager declined to abort dispatching.
+                // Wait a bit longer and timeout again later.
+                return timeout * 1000000L; // nanoseconds
+            }
+        }
+        return 0; // abort dispatching
+    }
+
+    /** Notifies that the input device configuration has changed. */
+    @Override
+    public void notifyConfigurationChanged() {
+        // TODO(multi-display): Notify proper displays that are associated with this input device.
+        mService.sendNewConfiguration(DEFAULT_DISPLAY);
+
+        synchronized (mInputDevicesReadyMonitor) {
+            if (!mInputDevicesReady) {
+                mInputDevicesReady = true;
+                mInputDevicesReadyMonitor.notifyAll();
+            }
+        }
+    }
+
+    /** Notifies that the lid switch changed state. */
+    @Override
+    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
+        mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
+    }
+
+    /** Notifies that the camera lens cover state has changed. */
+    @Override
+    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
+        mService.mPolicy.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
+    }
+
+    /**
+     * Provides an opportunity for the window manager policy to intercept early key
+     * processing as soon as the key has been read from the device.
+     */
+    @Override
+    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
+        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
+    }
+
+    /**
+     * Provides an opportunity for the window manager policy to intercept early motion event
+     * processing when the device is in a non-interactive state since these events are normally
+     * dropped.
+     */
+    @Override
+    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+        return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
+                whenNanos, policyFlags);
+    }
+
+    /**
+     * Provides an opportunity for the window manager policy to process a key before
+     * ordinary dispatch.
+     */
+    @Override
+    public long interceptKeyBeforeDispatching(
+            InputWindowHandle focus, KeyEvent event, int policyFlags) {
+        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+        return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
+    }
+
+    /**
+     * Provides an opportunity for the window manager policy to process a key that
+     * the application did not handle.
+     */
+    @Override
+    public KeyEvent dispatchUnhandledKey(
+            InputWindowHandle focus, KeyEvent event, int policyFlags) {
+        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+        return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
+    }
+
+    /** Callback to get pointer layer. */
+    @Override
+    public int getPointerLayer() {
+        return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
+                * WindowManagerService.TYPE_LAYER_MULTIPLIER
+                + WindowManagerService.TYPE_LAYER_OFFSET;
+    }
+
+    /** Waits until the built-in input devices have been configured. */
+    public boolean waitForInputDevicesReady(long timeoutMillis) {
+        synchronized (mInputDevicesReadyMonitor) {
+            if (!mInputDevicesReady) {
+                try {
+                    mInputDevicesReadyMonitor.wait(timeoutMillis);
+                } catch (InterruptedException ex) {
+                }
+            }
+            return mInputDevicesReady;
+        }
+    }
+
+    public void freezeInputDispatchingLw() {
+        if (!mInputDispatchFrozen) {
+            if (DEBUG_INPUT) {
+                Slog.v(TAG_WM, "Freezing input dispatching");
+            }
+
+            mInputDispatchFrozen = true;
+
+            if (DEBUG_INPUT) {
+                mInputFreezeReason = Debug.getCallers(6);
+            }
+            updateInputDispatchModeLw();
+        }
+    }
+
+    public void thawInputDispatchingLw() {
+        if (mInputDispatchFrozen) {
+            if (DEBUG_INPUT) {
+                Slog.v(TAG_WM, "Thawing input dispatching");
+            }
+
+            mInputDispatchFrozen = false;
+            mInputFreezeReason = null;
+            updateInputDispatchModeLw();
+        }
+    }
+
+    public void setEventDispatchingLw(boolean enabled) {
+        if (mInputDispatchEnabled != enabled) {
+            if (DEBUG_INPUT) {
+                Slog.v(TAG_WM, "Setting event dispatching to " + enabled);
+            }
+
+            mInputDispatchEnabled = enabled;
+            updateInputDispatchModeLw();
+        }
+    }
+
+    private void updateInputDispatchModeLw() {
+        mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        if (mInputFreezeReason != null) {
+            pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 281e0a844..c4beb55 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
 import static android.view.WindowManager.INPUT_CONSUMER_PIP;
 import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
@@ -24,7 +23,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
@@ -33,24 +31,19 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
-import android.app.ActivityManager;
 import android.graphics.Rect;
-import android.os.Debug;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Process;
-import android.os.RemoteException;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
 import android.view.InputChannel;
 import android.view.InputEventReceiver;
-import android.view.KeyEvent;
-import android.view.WindowManager;
 
 import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputManagerService;
 import com.android.server.input.InputWindowHandle;
 import com.android.server.policy.WindowManagerPolicy;
 
@@ -59,23 +52,12 @@
 import java.util.Set;
 import java.util.function.Consumer;
 
-final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
+final class InputMonitor {
     private final WindowManagerService mService;
 
     // Current window with input focus for keys and other non-touch events.  May be null.
     private WindowState mInputFocus;
 
-    // When true, prevents input dispatch from proceeding until set to false again.
-    private boolean mInputDispatchFrozen;
-
-    // The reason the input is currently frozen or null if the input isn't frozen.
-    private String mInputFreezeReason = null;
-
-    // When true, input dispatch proceeds normally.  Otherwise all events are dropped.
-    // Initially false, so that input does not get dispatched until boot is finished at
-    // which point the ActivityManager will enable dispatching.
-    private boolean mInputDispatchEnabled;
-
     // When true, need to call updateInputWindowsLw().
     private boolean mUpdateInputWindowsNeeded = true;
 
@@ -84,19 +66,12 @@
     private int mInputWindowHandleCount;
     private InputWindowHandle mFocusedInputWindowHandle;
 
-    private boolean mAddInputConsumerHandle;
-    private boolean mAddPipInputConsumerHandle;
-    private boolean mAddWallpaperInputConsumerHandle;
-    private boolean mAddRecentsAnimationInputConsumerHandle;
     private boolean mDisableWallpaperTouchEvents;
     private final Rect mTmpRect = new Rect();
     private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer =
             new UpdateInputForAllWindowsConsumer();
 
-    // Set to true when the first input device configuration change notification
-    // is received to indicate that the input devices are ready.
-    private final Object mInputDevicesReadyMonitor = new Object();
-    private boolean mInputDevicesReady;
+    private int mDisplayId;
 
     /**
      * The set of input consumer added to the window manager by name, which consumes input events
@@ -112,8 +87,9 @@
         EventReceiverInputConsumer(WindowManagerService service, InputMonitor monitor,
                                    Looper looper, String name,
                                    InputEventReceiver.Factory inputEventReceiverFactory,
-                                   int clientPid, UserHandle clientUser) {
-            super(service, null /* token */, name, null /* inputChannel */, clientPid, clientUser);
+                                   int clientPid, UserHandle clientUser, int displayId) {
+            super(service, null /* token */, name, null /* inputChannel */, clientPid, clientUser,
+                    displayId);
             mInputMonitor = monitor;
             mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
                     mClientChannel, looper);
@@ -129,8 +105,9 @@
         }
     }
 
-    public InputMonitor(WindowManagerService service) {
+    public InputMonitor(WindowManagerService service, int displayId) {
         mService = service;
+        mDisplayId = displayId;
     }
 
     private void addInputConsumer(String name, InputConsumerImpl consumer) {
@@ -155,9 +132,8 @@
         return false;
     }
 
-    InputConsumerImpl getInputConsumer(String name, int displayId) {
-        // TODO(multi-display): Allow input consumers on non-default displays?
-        return (displayId == DEFAULT_DISPLAY) ? mInputConsumers.get(name) : null;
+    InputConsumerImpl getInputConsumer(String name) {
+        return mInputConsumers.get(name);
     }
 
     void layoutInputConsumers(int dw, int dh) {
@@ -169,12 +145,12 @@
     WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
             InputEventReceiver.Factory inputEventReceiverFactory) {
         if (mInputConsumers.containsKey(name)) {
-            throw new IllegalStateException("Existing input consumer found with name: " + name);
+            throw new IllegalStateException("Existing input consumer found with name: " + name
+                    + ", display: " + mDisplayId);
         }
-
         final EventReceiverInputConsumer consumer = new EventReceiverInputConsumer(mService,
                 this, looper, name, inputEventReceiverFactory, Process.myPid(),
-                UserHandle.SYSTEM);
+                UserHandle.SYSTEM, mDisplayId);
         addInputConsumer(name, consumer);
         return consumer;
     }
@@ -182,11 +158,12 @@
     void createInputConsumer(IBinder token, String name, InputChannel inputChannel, int clientPid,
             UserHandle clientUser) {
         if (mInputConsumers.containsKey(name)) {
-            throw new IllegalStateException("Existing input consumer found with name: " + name);
+            throw new IllegalStateException("Existing input consumer found with name: " + name
+                    + ", display: " + mDisplayId);
         }
 
         final InputConsumerImpl consumer = new InputConsumerImpl(mService, token, name,
-                inputChannel, clientPid, clientUser);
+                inputChannel, clientPid, clientUser, mDisplayId);
         switch (name) {
             case INPUT_CONSUMER_WALLPAPER:
                 consumer.mWindowHandle.hasWallpaper = true;
@@ -200,100 +177,6 @@
         addInputConsumer(name, consumer);
     }
 
-    /* Notifies the window manager about a broken input channel.
-     *
-     * Called by the InputManager.
-     */
-    @Override
-    public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
-        if (inputWindowHandle == null) {
-            return;
-        }
-
-        synchronized (mService.mWindowMap) {
-            WindowState windowState = (WindowState) inputWindowHandle.windowState;
-            if (windowState != null) {
-                Slog.i(TAG_WM, "WINDOW DIED " + windowState);
-                windowState.removeIfPossible();
-            }
-        }
-    }
-
-    /* Notifies the window manager about an application that is not responding.
-     * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
-     *
-     * Called by the InputManager.
-     */
-    @Override
-    public long notifyANR(InputApplicationHandle inputApplicationHandle,
-            InputWindowHandle inputWindowHandle, String reason) {
-        AppWindowToken appWindowToken = null;
-        WindowState windowState = null;
-        boolean aboveSystem = false;
-        synchronized (mService.mWindowMap) {
-            if (inputWindowHandle != null) {
-                windowState = (WindowState) inputWindowHandle.windowState;
-                if (windowState != null) {
-                    appWindowToken = windowState.mAppToken;
-                }
-            }
-            if (appWindowToken == null && inputApplicationHandle != null) {
-                appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken;
-            }
-
-            if (windowState != null) {
-                Slog.i(TAG_WM, "Input event dispatching timed out "
-                        + "sending to " + windowState.mAttrs.getTitle()
-                        + ".  Reason: " + reason);
-                // Figure out whether this window is layered above system windows.
-                // We need to do this here to help the activity manager know how to
-                // layer its ANR dialog.
-                int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
-                        TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
-                aboveSystem = windowState.mBaseLayer > systemAlertLayer;
-            } else if (appWindowToken != null) {
-                Slog.i(TAG_WM, "Input event dispatching timed out "
-                        + "sending to application " + appWindowToken.stringName
-                        + ".  Reason: " + reason);
-            } else {
-                Slog.i(TAG_WM, "Input event dispatching timed out "
-                        + ".  Reason: " + reason);
-            }
-
-            mService.saveANRStateLocked(appWindowToken, windowState, reason);
-        }
-
-        // All the calls below need to happen without the WM lock held since they call into AM.
-        mService.mAmInternal.saveANRState(reason);
-
-        if (appWindowToken != null && appWindowToken.appToken != null) {
-            // Notify the activity manager about the timeout and let it decide whether
-            // to abort dispatching or keep waiting.
-            final AppWindowContainerController controller = appWindowToken.getController();
-            final boolean abort = controller != null
-                    && controller.keyDispatchingTimedOut(reason,
-                            (windowState != null) ? windowState.mSession.mPid : -1);
-            if (!abort) {
-                // The activity manager declined to abort dispatching.
-                // Wait a bit longer and timeout again later.
-                return appWindowToken.mInputDispatchingTimeoutNanos;
-            }
-        } else if (windowState != null) {
-            try {
-                // Notify the activity manager about the timeout and let it decide whether
-                // to abort dispatching or keep waiting.
-                long timeout = ActivityManager.getService().inputDispatchingTimedOut(
-                        windowState.mSession.mPid, aboveSystem, reason);
-                if (timeout >= 0) {
-                    // The activity manager declined to abort dispatching.
-                    // Wait a bit longer and timeout again later.
-                    return timeout * 1000000L; // nanoseconds
-                }
-            } catch (RemoteException ex) {
-            }
-        }
-        return 0; // abort dispatching
-    }
 
     private void addInputWindowHandle(final InputWindowHandle windowHandle) {
         if (mInputWindowHandles == null) {
@@ -324,8 +207,9 @@
         inputWindowHandle.ownerPid = child.mSession.mPid;
         inputWindowHandle.ownerUid = child.mSession.mUid;
         inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
+        inputWindowHandle.displayId = child.getDisplayId();
 
-        final Rect frame = child.mFrame;
+        final Rect frame = child.getFrameLw();
         inputWindowHandle.frameLeft = frame.left;
         inputWindowHandle.frameTop = frame.top;
         inputWindowHandle.frameRight = frame.right;
@@ -413,87 +297,6 @@
         if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
     }
 
-    /* Notifies that the input device configuration has changed. */
-    @Override
-    public void notifyConfigurationChanged() {
-        // TODO(multi-display): Notify proper displays that are associated with this input device.
-        mService.sendNewConfiguration(DEFAULT_DISPLAY);
-
-        synchronized (mInputDevicesReadyMonitor) {
-            if (!mInputDevicesReady) {
-                mInputDevicesReady = true;
-                mInputDevicesReadyMonitor.notifyAll();
-            }
-        }
-    }
-
-    /* Waits until the built-in input devices have been configured. */
-    public boolean waitForInputDevicesReady(long timeoutMillis) {
-        synchronized (mInputDevicesReadyMonitor) {
-            if (!mInputDevicesReady) {
-                try {
-                    mInputDevicesReadyMonitor.wait(timeoutMillis);
-                } catch (InterruptedException ex) {
-                }
-            }
-            return mInputDevicesReady;
-        }
-    }
-
-    /* Notifies that the lid switch changed state. */
-    @Override
-    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
-        mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
-    }
-
-    /* Notifies that the camera lens cover state has changed. */
-    @Override
-    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
-        mService.mPolicy.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
-    }
-
-    /* Provides an opportunity for the window manager policy to intercept early key
-     * processing as soon as the key has been read from the device. */
-    @Override
-    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
-        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
-    }
-
-    /* Provides an opportunity for the window manager policy to intercept early motion event
-     * processing when the device is in a non-interactive state since these events are normally
-     * dropped. */
-    @Override
-    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
-        return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
-                whenNanos, policyFlags);
-    }
-
-    /* Provides an opportunity for the window manager policy to process a key before
-     * ordinary dispatch. */
-    @Override
-    public long interceptKeyBeforeDispatching(
-            InputWindowHandle focus, KeyEvent event, int policyFlags) {
-        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
-        return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
-    }
-
-    /* Provides an opportunity for the window manager policy to process a key that
-     * the application did not handle. */
-    @Override
-    public KeyEvent dispatchUnhandledKey(
-            InputWindowHandle focus, KeyEvent event, int policyFlags) {
-        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
-        return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
-    }
-
-    /* Callback to get pointer layer. */
-    @Override
-    public int getPointerLayer() {
-        return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
-                * WindowManagerService.TYPE_LAYER_MULTIPLIER
-                + WindowManagerService.TYPE_LAYER_OFFSET;
-    }
-
     /* Called when the current input focus changes.
      * Layer assignment is assumed to be complete by the time this is called.
      */
@@ -554,52 +357,7 @@
         }
     }
 
-    public void freezeInputDispatchingLw() {
-        if (!mInputDispatchFrozen) {
-            if (DEBUG_INPUT) {
-                Slog.v(TAG_WM, "Freezing input dispatching");
-            }
-
-            mInputDispatchFrozen = true;
-
-            if (DEBUG_INPUT || true) {
-                mInputFreezeReason = Debug.getCallers(6);
-            }
-            updateInputDispatchModeLw();
-        }
-    }
-
-    public void thawInputDispatchingLw() {
-        if (mInputDispatchFrozen) {
-            if (DEBUG_INPUT) {
-                Slog.v(TAG_WM, "Thawing input dispatching");
-            }
-
-            mInputDispatchFrozen = false;
-            mInputFreezeReason = null;
-            updateInputDispatchModeLw();
-        }
-    }
-
-    public void setEventDispatchingLw(boolean enabled) {
-        if (mInputDispatchEnabled != enabled) {
-            if (DEBUG_INPUT) {
-                Slog.v(TAG_WM, "Setting event dispatching to " + enabled);
-            }
-
-            mInputDispatchEnabled = enabled;
-            updateInputDispatchModeLw();
-        }
-    }
-
-    private void updateInputDispatchModeLw() {
-        mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
-    }
-
     void dump(PrintWriter pw, String prefix) {
-        if (mInputFreezeReason != null) {
-            pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
-        }
         final Set<String> inputConsumerKeys = mInputConsumers.keySet();
         if (!inputConsumerKeys.isEmpty()) {
             pw.println(prefix + "InputConsumers:");
@@ -610,41 +368,52 @@
     }
 
     private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
-
         InputConsumerImpl navInputConsumer;
         InputConsumerImpl pipInputConsumer;
         InputConsumerImpl wallpaperInputConsumer;
         InputConsumerImpl recentsAnimationInputConsumer;
+
+        private boolean mAddInputConsumerHandle;
+        private boolean mAddPipInputConsumerHandle;
+        private boolean mAddWallpaperInputConsumerHandle;
+        private boolean mAddRecentsAnimationInputConsumerHandle;
+
         boolean inDrag;
         WallpaperController wallpaperController;
 
         private void updateInputWindows(boolean inDrag) {
+            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "updateInputWindows");
 
-            // TODO: multi-display
-            navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
-            pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
-            wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
-            recentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION,
-                    DEFAULT_DISPLAY);
+            navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION);
+            pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP);
+            wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER);
+            recentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
+
             mAddInputConsumerHandle = navInputConsumer != null;
             mAddPipInputConsumerHandle = pipInputConsumer != null;
             mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
             mAddRecentsAnimationInputConsumerHandle = recentsAnimationInputConsumer != null;
+
             mTmpRect.setEmpty();
             mDisableWallpaperTouchEvents = false;
             this.inDrag = inDrag;
             wallpaperController = mService.mRoot.mWallpaperController;
 
-            mService.mRoot.forAllWindows(this, true /* traverseTopToBottom */);
+            // TODO(b/112081256): Use independent InputMonitor for each display.
+            mService.mRoot/*.getDisplayContent(mDisplayId)*/.forAllWindows(this,
+                    true /* traverseTopToBottom */);
             if (mAddWallpaperInputConsumerHandle) {
                 // No visible wallpaper found, add the wallpaper input consumer at the end.
                 addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
             }
 
             // Send windows to native code.
+            // TODO: Update Input windows and focus by display?
             mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);
 
             clearInputWindowHandlesLw();
+
+            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
         }
 
         @Override
@@ -669,7 +438,7 @@
                 if (recentsAnimationController != null
                         && recentsAnimationController.hasInputConsumerForApp(w.mAppToken)) {
                     if (recentsAnimationController.updateInputConsumerForApp(
-                            recentsAnimationInputConsumer, hasFocus)) {
+                            recentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
                         addInputWindowHandle(recentsAnimationInputConsumer.mWindowHandle);
                         mAddRecentsAnimationInputConsumerHandle = false;
                     }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 6f5fea9..dea4076 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -53,6 +53,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
+import com.android.server.input.InputWindowHandle;
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 import com.android.server.wm.utils.InsetUtils;
 
@@ -201,7 +202,9 @@
                     }
 
                     mInputConsumerEnabled = enabled;
-                    mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+                    final InputMonitor inputMonitor =
+                            mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
+                    inputMonitor.updateInputWindowsLw(true /*force*/);
                     mService.scheduleAnimationLocked();
                 }
             } finally {
@@ -312,12 +315,9 @@
     @VisibleForTesting
     AnimationAdapter addAnimation(Task task, boolean isRecentTaskInvisible) {
         if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "addAnimation(" + task.getName() + ")");
-        // TODO: Refactor this to use the task's animator
-        final SurfaceAnimator anim = new SurfaceAnimator(task, null /* animationFinishedCallback */,
-                mService);
         final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task,
                 isRecentTaskInvisible);
-        anim.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
+        task.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
         task.commitPendingTransaction();
         mPendingAnimations.add(taskAdapter);
         return taskAdapter;
@@ -361,6 +361,11 @@
                     new RemoteAnimationTarget[appAnimations.size()]);
             mPendingStart = false;
 
+            // Perform layout if it was scheduled before to make sure that we get correct content
+            // insets for the target app window after a rotation
+            final DisplayContent displayContent = mService.mRoot.getDisplayContent(mDisplayId);
+            displayContent.performLayout(false /* initial */, false /* updateInputWindows */);
+
             final Rect minimizedHomeBounds = mTargetAppToken != null
                     && mTargetAppToken.inSplitScreenSecondaryWindowingMode()
                             ? mMinimizedHomeBounds
@@ -369,8 +374,7 @@
                     && mTargetAppToken.findMainWindow() != null
                             ? mTargetAppToken.findMainWindow().mContentInsets
                             : null;
-            mRunner.onAnimationStart(mController, appTargets, contentInsets,
-                    minimizedHomeBounds);
+            mRunner.onAnimationStart(mController, appTargets, contentInsets, minimizedHomeBounds);
             if (DEBUG_RECENTS_ANIMATIONS) {
                 Slog.d(TAG, "startAnimation(): Notify animation start:");
                 for (int i = 0; i < mPendingAnimations.size(); i++) {
@@ -438,8 +442,10 @@
         mCanceled = true;
 
         // Clear associated input consumers
-        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
-        mService.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
+        final InputMonitor inputMonitor =
+                mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
+        inputMonitor.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
+        inputMonitor.updateInputWindowsLw(true /*force*/);
 
         // We have deferred all notifications to the target app as a part of the recents animation,
         // so if we are actually transitioning there, notify again here
@@ -497,7 +503,7 @@
         return mInputConsumerEnabled && isAnimatingApp(appToken);
     }
 
-    boolean updateInputConsumerForApp(InputConsumerImpl recentsAnimationInputConsumer,
+    boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
             boolean hasFocus) {
         // Update the input consumer touchable region to match the target app main window
         final WindowState targetAppMainWindow = mTargetAppToken != null
@@ -505,8 +511,8 @@
                 : null;
         if (targetAppMainWindow != null) {
             targetAppMainWindow.getBounds(mTmpRect);
-            recentsAnimationInputConsumer.mWindowHandle.hasFocus = hasFocus;
-            recentsAnimationInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
+            inputWindowHandle.hasFocus = hasFocus;
+            inputWindowHandle.touchableRegion.set(mTmpRect);
             return true;
         }
         return false;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index a709c55..d8cbb26 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -16,9 +16,46 @@
 
 package com.android.server.wm;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.RootWindowContainerProto.DISPLAYS;
+import static com.android.server.wm.RootWindowContainerProto.WINDOWS;
+import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
+import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
+import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
+import static com.android.server.wm.WindowManagerService.logSurface;
+import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
+import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
+
 import android.annotation.CallSuper;
 import android.content.res.Configuration;
-import android.graphics.Rect;
 import android.hardware.power.V1_0.PowerHint;
 import android.os.Binder;
 import android.os.Debug;
@@ -26,7 +63,6 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -43,51 +79,11 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.server.EventLogTags;
 
-import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Consumer;
 
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.INVALID_DISPLAY;
-import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
-import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
-import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
-import static com.android.server.wm.WindowManagerService.logSurface;
-import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
-import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
-import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
-import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
-import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
-import static com.android.server.wm.RootWindowContainerProto.DISPLAYS;
-import static com.android.server.wm.RootWindowContainerProto.WINDOWS;
-import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
-
 /** Root {@link WindowContainer} for the device. */
 class RootWindowContainer extends WindowContainer<DisplayContent> {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
@@ -134,6 +130,9 @@
     // transaction from the global transaction.
     private final SurfaceControl.Transaction mDisplayTransaction = new SurfaceControl.Transaction();
 
+    private final Consumer<DisplayContent> mDisplayContentConfigChangesConsumer =
+            mService.mPolicy::onConfigurationChanged;
+
     private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
         if (w.mHasSurface) {
             try {
@@ -221,16 +220,11 @@
 
         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
 
-        final DisplayInfo displayInfo = dc.getDisplayInfo();
-        final Rect rect = new Rect();
-        mService.mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
-        displayInfo.overscanLeft = rect.left;
-        displayInfo.overscanTop = rect.top;
-        displayInfo.overscanRight = rect.right;
-        displayInfo.overscanBottom = rect.bottom;
+        mService.mDisplaySettings.applySettingsToDisplayLocked(dc);
+
         if (mService.mDisplayManagerInternal != null) {
             mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
-                    displayId, displayInfo);
+                    displayId, dc.getDisplayInfo());
             dc.configureDisplayPolicy();
 
             // Tap Listeners are supported for:
@@ -303,6 +297,18 @@
         return null;
     }
 
+    /** Returns the window token for the input binder if it exist in the system. */
+    WindowToken getWindowToken(IBinder binder) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final DisplayContent dc = mChildren.get(i);
+            final WindowToken wtoken = dc.getWindowToken(binder);
+            if (wtoken != null) {
+                return wtoken;
+            }
+        }
+        return null;
+    }
+
     /** Returns the display object the input window token is currently mapped on. */
     DisplayContent getWindowTokenDisplay(WindowToken token) {
         if (token == null) {
@@ -379,7 +385,7 @@
         prepareFreezingTaskBounds();
         super.onConfigurationChanged(newParentConfig);
 
-        mService.mPolicy.onConfigurationChanged();
+        forAllDisplays(mDisplayContentConfigChangesConsumer);
     }
 
     /**
@@ -724,7 +730,9 @@
         }
 
         // Finally update all input windows now that the window changes have stabilized.
-        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+        forAllDisplays(dc -> {
+            dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
+        });
 
         mService.setHoldScreenLocked(mHoldScreen);
         if (!mService.mDisplayFrozen) {
@@ -746,22 +754,7 @@
 
         if (mUpdateRotation) {
             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
-            // TODO(multi-display): Update rotation for different displays separately.
-            final int displayId = defaultDisplay.getDisplayId();
-            if (defaultDisplay.updateRotationUnchecked()) {
-                mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
-            } else {
-                mUpdateRotation = false;
-            }
-            // Update rotation of VR virtual display separately. Currently this is the only kind of
-            // secondary display that can be rotated because of the single-display limitations in
-            // PhoneWindowManager.
-            final DisplayContent vrDisplay = mService.mVr2dDisplayId != INVALID_DISPLAY
-                    ? getDisplayContent(mService.mVr2dDisplayId) : null;
-            if (vrDisplay != null && vrDisplay.updateRotationUnchecked()) {
-                mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mService.mVr2dDisplayId)
-                        .sendToTarget();
-            }
+            mUpdateRotation = updateRotationUnchecked();
         }
 
         if (mService.mWaitingForDrawnCallback != null ||
@@ -799,7 +792,9 @@
         }
 
         if (updateInputWindowsNeeded) {
-            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+            forAllDisplays(dc -> {
+                dc.getInputMonitor().updateInputWindowsLw(false /*force*/);
+            });
         }
         mService.setFocusTaskRegionLocked(null);
         if (touchExcludeRegionUpdateDisplays != null) {
@@ -958,6 +953,19 @@
         return displayHasContent;
     }
 
+    boolean updateRotationUnchecked() {
+        boolean changed = false;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final DisplayContent displayContent = mChildren.get(i);
+            if (displayContent.updateRotationUnchecked()) {
+                changed = true;
+                mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
+                        .sendToTarget();
+            }
+        }
+        return changed;
+    }
+
     boolean copyAnimToLayoutParams() {
         boolean doRequest = false;
 
@@ -1093,4 +1101,15 @@
     void scheduleAnimation() {
         mService.scheduleAnimationLocked();
     }
+
+    /**
+     * For all display at or below this call the callback.
+     *
+     * @param callback Callback to be called for every display.
+     */
+    void forAllDisplays(Consumer<DisplayContent> callback) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            callback.accept(mChildren.get(i));
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index fa8a5c6..df97027 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -16,20 +16,18 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
+import static com.android.server.wm.ScreenRotationAnimationProto.ANIMATION_RUNNING;
+import static com.android.server.wm.ScreenRotationAnimationProto.STARTED;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
 import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER;
-import static com.android.server.wm.ScreenRotationAnimationProto.ANIMATION_RUNNING;
-import static com.android.server.wm.ScreenRotationAnimationProto.STARTED;
 
 import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.Rect;
-import android.os.IBinder;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
@@ -37,7 +35,6 @@
 import android.view.Surface;
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl;
-import android.view.SurfaceSession;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Transformation;
@@ -268,24 +265,24 @@
                     .setSecure(isSecure)
                     .build();
 
-            // capture a screenshot into the surface we just created
-            // TODO(multidisplay): we should use the proper display
-            final int displayId = SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN;
-            final IBinder displayHandle = SurfaceControl.getBuiltInDisplay(displayId);
-            // This null check below is to guard a race condition where WMS didn't have a chance to
-            // respond to display disconnection before handling rotation , that surfaceflinger may
-            // return a null handle here because it doesn't think that display is valid anymore.
-            if (displayHandle != null) {
-                Surface sur = new Surface();
-                sur.copyFrom(mSurfaceControl);
-                SurfaceControl.screenshot(displayHandle, sur);
+            // In case display bounds change, screenshot buffer and surface may mismatch so set a
+            // scaling mode.
+            SurfaceControl.Transaction t2 = new SurfaceControl.Transaction();
+            t2.setOverrideScalingMode(mSurfaceControl, Surface.SCALING_MODE_SCALE_TO_WINDOW);
+            t2.apply(true /* sync */);
+
+            // Capture a screenshot into the surface we just created.
+            final int displayId = display.getDisplayId();
+            final Surface surface = new Surface();
+            surface.copyFrom(mSurfaceControl);
+            if (mService.mDisplayManagerInternal.screenshot(displayId, surface)) {
                 t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
                 t.setAlpha(mSurfaceControl, 0);
                 t.show(mSurfaceControl);
-                sur.destroy();
             } else {
-                Slog.w(TAG, "Built-in display " + displayId + " is null.");
+                Slog.w(TAG, "Unable to take screenshot of display " + displayId);
             }
+            surface.destroy();
         } catch (OutOfResourcesException e) {
             Slog.w(TAG, "Unable to allocate freeze surface", e);
         }
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 4003d5a..5cf5e0d 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -189,15 +189,6 @@
     }
 
     @Override
-    public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
-            int viewVisibility, Rect outContentInsets, Rect outStableInsets,
-            InputChannel outInputChannel) {
-        return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY,
-                new Rect() /* outFrame */, outContentInsets, outStableInsets, null /* outOutsets */,
-                new DisplayCutout.ParcelableWrapper()  /* cutout */, outInputChannel);
-    }
-
-    @Override
     public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
             int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
             Rect outStableInsets, Rect outOutsets,
@@ -207,13 +198,6 @@
     }
 
     @Override
-    public int addWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
-            int viewVisibility, Rect outContentInsets, Rect outStableInsets) {
-        return addToDisplayWithoutInputChannel(window, seq, attrs, viewVisibility,
-                Display.DEFAULT_DISPLAY, outContentInsets, outStableInsets);
-    }
-
-    @Override
     public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
             int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) {
         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
@@ -303,7 +287,7 @@
             try {
                 return mService.mPolicy.performHapticFeedbackLw(
                         mService.windowForClientLocked(this, window, true),
-                        effectId, always);
+                        effectId, always, null);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 2bfff26..cb50460 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -26,6 +26,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.annotation.Nullable;
+import android.hardware.power.V1_0.PowerHint;
+import android.os.PowerManagerInternal;
 import android.util.ArrayMap;
 import android.view.Choreographer;
 import android.view.SurfaceControl;
@@ -57,6 +59,7 @@
     private final AnimationHandler mAnimationHandler;
     private final Transaction mFrameTransaction;
     private final AnimatorFactory mAnimatorFactory;
+    private final PowerManagerInternal mPowerManagerInternal;
     private boolean mApplyScheduled;
 
     @GuardedBy("mLock")
@@ -70,13 +73,15 @@
     @GuardedBy("mLock")
     private boolean mAnimationStartDeferred;
 
-    SurfaceAnimationRunner() {
-        this(null /* callbackProvider */, null /* animatorFactory */, new Transaction());
+    SurfaceAnimationRunner(PowerManagerInternal powerManagerInternal) {
+        this(null /* callbackProvider */, null /* animatorFactory */, new Transaction(),
+                powerManagerInternal);
     }
 
     @VisibleForTesting
     SurfaceAnimationRunner(@Nullable AnimationFrameCallbackProvider callbackProvider,
-            AnimatorFactory animatorFactory, Transaction frameTransaction) {
+            AnimatorFactory animatorFactory, Transaction frameTransaction,
+            PowerManagerInternal powerManagerInternal) {
         SurfaceAnimationThread.getHandler().runWithScissors(() -> mChoreographer = getSfInstance(),
                 0 /* timeout */);
         mFrameTransaction = frameTransaction;
@@ -87,6 +92,7 @@
         mAnimatorFactory = animatorFactory != null
                 ? animatorFactory
                 : SfValueAnimator::new;
+        mPowerManagerInternal = powerManagerInternal;
     }
 
     /**
@@ -231,6 +237,7 @@
         synchronized (mLock) {
             startPendingAnimationsLocked();
         }
+        mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
     }
 
     private void scheduleApplyTransaction() {
diff --git a/services/core/java/com/android/server/wm/TEST_MAPPING b/services/core/java/com/android/server/wm/TEST_MAPPING
new file mode 100644
index 0000000..e885afa
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TEST_MAPPING
@@ -0,0 +1,42 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsWindowManagerDeviceTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.wm."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsWindowManagerDeviceTestCases"
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.wm."
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 2da77a1..71f34c9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -409,7 +409,7 @@
      * @param out Rect containing the max visible bounds.
      * @return true if the task has some visible app windows; false otherwise.
      */
-    boolean getMaxVisibleBounds(Rect out) {
+    private boolean getMaxVisibleBounds(Rect out) {
         boolean foundTop = false;
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final AppWindowToken token = mChildren.get(i);
@@ -422,22 +422,11 @@
                 continue;
             }
             if (!foundTop) {
-                out.set(win.mVisibleFrame);
                 foundTop = true;
-                continue;
+                out.setEmpty();
             }
-            if (win.mVisibleFrame.left < out.left) {
-                out.left = win.mVisibleFrame.left;
-            }
-            if (win.mVisibleFrame.top < out.top) {
-                out.top = win.mVisibleFrame.top;
-            }
-            if (win.mVisibleFrame.right > out.right) {
-                out.right = win.mVisibleFrame.right;
-            }
-            if (win.mVisibleFrame.bottom > out.bottom) {
-                out.bottom = win.mVisibleFrame.bottom;
-            }
+
+            win.getMaxVisibleBounds(out);
         }
         return foundTop;
     }
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 30f46a0..8effc6b 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -97,7 +97,7 @@
     private final WindowManagerService mService;
     private final IActivityTaskManager mActivityManager;
     private WindowPositionerEventReceiver mInputEventReceiver;
-    private Display mDisplay;
+    private DisplayContent mDisplayContent;
     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
     private Rect mTmpRect = new Rect();
     private int mSideMargin;
@@ -209,6 +209,7 @@
                     // Post back to WM to handle clean-ups. We still need the input
                     // event handler for the last finishInputEvent()!
                     mService.mTaskPositioningController.finishTaskPositioning();
+                    mTask.getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/);
                 }
                 handled = true;
             } catch (Exception e) {
@@ -250,8 +251,8 @@
             return;
         }
 
-        mDisplay = display;
-        mDisplay.getMetrics(mDisplayMetrics);
+        mDisplayContent = displayContent;
+        display.getMetrics(mDisplayMetrics);
         final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
         mServerChannel = channels[0];
         mClientChannel = channels[1];
@@ -267,7 +268,7 @@
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
         mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
-                mDisplay.getDisplayId());
+                display.getDisplayId());
         mDragWindowHandle.name = TAG;
         mDragWindowHandle.inputChannel = mServerChannel;
         mDragWindowHandle.layer = mService.getDragLayerLocked();
@@ -292,7 +293,7 @@
         mDragWindowHandle.frameLeft = 0;
         mDragWindowHandle.frameTop = 0;
         final Point p = new Point();
-        mDisplay.getRealSize(p);
+        display.getRealSize(p);
         mDragWindowHandle.frameRight = p.x;
         mDragWindowHandle.frameBottom = p.y;
 
@@ -300,12 +301,12 @@
         if (DEBUG_ORIENTATION) {
             Slog.d(TAG, "Pausing rotation during re-position");
         }
-        mService.pauseRotationLocked();
+        mDisplayContent.pauseRotationLocked();
 
         mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
         mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
         mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
-        mDisplay.getRealSize(mMaxVisibleSize);
+        display.getRealSize(mMaxVisibleSize);
 
         mDragEnded = false;
     }
@@ -331,14 +332,14 @@
 
         mDragWindowHandle = null;
         mDragApplicationHandle = null;
-        mDisplay = null;
         mDragEnded = true;
 
         // Resume rotations after a drag.
         if (DEBUG_ORIENTATION) {
             Slog.d(TAG, "Resuming rotation after re-position");
         }
-        mService.resumeRotationLocked();
+        mDisplayContent.resumeRotationLocked();
+        mDisplayContent = null;
     }
 
     void startDrag(WindowState win, boolean resize, boolean preserveOrientation, float startX,
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 7d36650..9cdc6b7 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -38,7 +38,6 @@
 class TaskPositioningController {
     private final WindowManagerService mService;
     private final InputManagerService mInputManager;
-    private final InputMonitor mInputMonitor;
     private final IActivityTaskManager mActivityManager;
     private final Handler mHandler;
 
@@ -54,9 +53,8 @@
     }
 
     TaskPositioningController(WindowManagerService service, InputManagerService inputManager,
-            InputMonitor inputMonitor, IActivityTaskManager activityManager, Looper looper) {
+            IActivityTaskManager activityManager, Looper looper) {
         mService = service;
-        mInputMonitor = inputMonitor;
         mInputManager = inputManager;
         mActivityManager = activityManager;
         mHandler = new Handler(looper);
@@ -129,7 +127,7 @@
         Display display = displayContent.getDisplay();
         mTaskPositioner = TaskPositioner.create(mService);
         mTaskPositioner.register(displayContent);
-        mInputMonitor.updateInputWindowsLw(true /*force*/);
+        displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
 
         // We need to grab the touch focus so that the touch events during the
         // resizing/scrolling are not sent to the app. 'win' is the main window
@@ -145,7 +143,7 @@
             Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
             mTaskPositioner.unregister();
             mTaskPositioner = null;
-            mInputMonitor.updateInputWindowsLw(true /*force*/);
+            displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
             return false;
         }
 
@@ -161,7 +159,6 @@
                 if (mTaskPositioner != null) {
                     mTaskPositioner.unregister();
                     mTaskPositioner = null;
-                    mInputMonitor.updateInputWindowsLw(true /*force*/);
                 }
             }
         });
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 733a248..6c8572a 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -38,7 +38,6 @@
 import android.view.RenderNode;
 import android.view.SurfaceControl;
 import android.view.ThreadedRenderer;
-import android.view.View;
 import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -219,15 +218,32 @@
         return TaskSnapshotSurface.create(mService, token, snapshot);
     }
 
-    private TaskSnapshot snapshotTask(Task task) {
-        final AppWindowToken top = task.getTopChild();
-        if (top == null) {
-            return null;
+    /**
+     * Find the window for a given task to take a snapshot. Top child of the task is usually the one
+     * we're looking for, but during app transitions, trampoline activities can appear in the
+     * children, which should be ignored.
+     */
+    @Nullable private AppWindowToken findAppTokenForSnapshot(Task task) {
+        for (int i = task.getChildCount() - 1; i >= 0; --i) {
+            final AppWindowToken appWindowToken = task.getChildAt(i);
+            if (appWindowToken == null || !appWindowToken.isSurfaceShowing()
+                    || appWindowToken.findMainWindow() == null) {
+                continue;
+            }
+            final boolean hasVisibleChild = appWindowToken.forAllWindows(
+                    // Ensure at least one window for the top app is visible before attempting to
+                    // take a screenshot. Visible here means that the WSA surface is shown and has
+                    // an alpha greater than 0.
+                    ws -> ws.mWinAnimator != null && ws.mWinAnimator.getShown()
+                            && ws.mWinAnimator.mLastAlpha > 0f, true  /* traverseTopToBottom */);
+            if (hasVisibleChild) {
+                return appWindowToken;
+            }
         }
-        final WindowState mainWindow = top.findMainWindow();
-        if (mainWindow == null) {
-            return null;
-        }
+        return null;
+    }
+
+    @Nullable private TaskSnapshot snapshotTask(Task task) {
         if (!mService.mPolicy.isScreenOn()) {
             if (DEBUG_SCREENSHOT) {
                 Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
@@ -235,49 +251,49 @@
             return null;
         }
         if (task.getSurfaceControl() == null) {
-            return null;
-        }
-
-        if (top.hasCommittedReparentToAnimationLeash()) {
             if (DEBUG_SCREENSHOT) {
-                Slog.w(TAG_WM, "Failed to take screenshot. App is animating " + top);
+                Slog.w(TAG_WM, "Failed to take screenshot. No surface control for " + task);
             }
             return null;
         }
 
-        final boolean hasVisibleChild = top.forAllWindows(
-                // Ensure at least one window for the top app is visible before attempting to take
-                // a screenshot. Visible here means that the WSA surface is shown and has an alpha
-                // greater than 0.
-                ws -> (ws.mAppToken == null || ws.mAppToken.isSurfaceShowing())
-                        && ws.mWinAnimator != null && ws.mWinAnimator.getShown()
-                        && ws.mWinAnimator.mLastAlpha > 0f, true);
-
-        if (!hasVisibleChild) {
+        final AppWindowToken appWindowToken = findAppTokenForSnapshot(task);
+        if (appWindowToken == null) {
             if (DEBUG_SCREENSHOT) {
                 Slog.w(TAG_WM, "Failed to take screenshot. No visible windows for " + task);
             }
             return null;
         }
+        if (appWindowToken.hasCommittedReparentToAnimationLeash()) {
+            if (DEBUG_SCREENSHOT) {
+                Slog.w(TAG_WM, "Failed to take screenshot. App is animating " + appWindowToken);
+            }
+            return null;
+        }
 
         final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
         final float scaleFraction = isLowRamDevice ? REDUCED_SCALE : 1f;
         task.getBounds(mTmpRect);
         mTmpRect.offsetTo(0, 0);
 
+        final WindowState mainWindow = appWindowToken.findMainWindow();
+        if (mainWindow == null) {
+            Slog.w(TAG_WM, "Failed to take screenshot. No main window for " + task);
+            return null;
+        }
         final GraphicBuffer buffer = SurfaceControl.captureLayers(
                 task.getSurfaceControl().getHandle(), mTmpRect, scaleFraction);
-        final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
         if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) {
             if (DEBUG_SCREENSHOT) {
                 Slog.w(TAG_WM, "Failed to take screenshot for " + task);
             }
             return null;
         }
-        return new TaskSnapshot(buffer, top.getConfiguration().orientation,
+        final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
+        return new TaskSnapshot(buffer, appWindowToken.getConfiguration().orientation,
                 getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
                 true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
-                !top.fillsParent() || isWindowTranslucent);
+                !appWindowToken.fillsParent() || isWindowTranslucent);
     }
 
     private boolean shouldDisableSnapshots() {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index e01cebd..2b84937 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -751,7 +751,7 @@
             // be inserted into is calculated properly in
             // {@link DisplayContent#findPositionForStack()} in both cases, we can just request that
             // the stack is put at top here.
-            mDisplayContent.positionStackAt(POSITION_TOP, this);
+            mDisplayContent.positionStackAt(POSITION_TOP, this, false /* includingParents */);
         }
     }
 
@@ -1645,9 +1645,14 @@
     }
 
     @Override  // AnimatesBounds
-    public void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
+    public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
         // Hold the lock since this is called from the BoundsAnimator running on the UiThread
         synchronized (mService.mWindowMap) {
+            if (!isAttached()) {
+                // Don't run the animation if the stack is already detached
+                return false;
+            }
+
             mBoundsAnimatingRequested = false;
             mBoundsAnimating = true;
             mCancelCurrentBoundsAnimation = false;
@@ -1677,6 +1682,7 @@
                 controller.updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate);
             }
         }
+        return true;
     }
 
     @Override  // AnimatesBounds
@@ -1720,41 +1726,47 @@
 
     @Override
     public boolean isAttached() {
-        return mDisplayContent != null;
+        synchronized (mService.mWindowMap) {
+            return mDisplayContent != null;
+        }
     }
 
     /**
      * Called immediately prior to resizing the tasks at the end of the pinned stack animation.
      */
     public void onPipAnimationEndResize() {
-        mBoundsAnimating = false;
-        for (int i = 0; i < mChildren.size(); i++) {
-            final Task t = mChildren.get(i);
-            t.clearPreserveNonFloatingState();
+        synchronized (mService.mWindowMap) {
+            mBoundsAnimating = false;
+            for (int i = 0; i < mChildren.size(); i++) {
+                final Task t = mChildren.get(i);
+                t.clearPreserveNonFloatingState();
+            }
+            mService.requestTraversal();
         }
-        mService.requestTraversal();
     }
 
     @Override
     public boolean shouldDeferStartOnMoveToFullscreen() {
-        // Workaround for the recents animation -- normally we need to wait for the new activity to
-        // show before starting the PiP animation, but because we start and show the home activity
-        // early for the recents animation prior to the PiP animation starting, there is no
-        // subsequent all-drawn signal. In this case, we can skip the pause when the home stack is
-        // already visible and drawn.
-        final TaskStack homeStack = mDisplayContent.getHomeStack();
-        if (homeStack == null) {
-            return true;
+        synchronized (mService.mWindowMap) {
+            // Workaround for the recents animation -- normally we need to wait for the new activity
+            // to show before starting the PiP animation, but because we start and show the home
+            // activity early for the recents animation prior to the PiP animation starting, there
+            // is no subsequent all-drawn signal. In this case, we can skip the pause when the home
+            // stack is already visible and drawn.
+            final TaskStack homeStack = mDisplayContent.getHomeStack();
+            if (homeStack == null) {
+                return true;
+            }
+            final Task homeTask = homeStack.getTopChild();
+            if (homeTask == null) {
+                return true;
+            }
+            final AppWindowToken homeApp = homeTask.getTopVisibleAppToken();
+            if (!homeTask.isVisible() || homeApp == null) {
+                return true;
+            }
+            return !homeApp.allDrawn;
         }
-        final Task homeTask = homeStack.getTopChild();
-        if (homeTask == null) {
-            return true;
-        }
-        final AppWindowToken homeApp = homeTask.getTopVisibleAppToken();
-        if (!homeTask.isVisible() || homeApp == null) {
-            return true;
-        }
-        return !homeApp.allDrawn;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index d83f28c..8b634b1 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -209,6 +209,12 @@
         }
     }
 
+    public boolean isDragResizing() {
+        synchronized (mWindowMap) {
+            return mContainer.isDragResizing();
+        }
+    }
+
     void reportSnapshotChanged(TaskSnapshot snapshot) {
         mHandler.obtainMessage(H.REPORT_SNAPSHOT_CHANGED, snapshot).sendToTarget();
     }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index c63da77..3d349ce 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -295,7 +295,7 @@
         float defaultWallpaperX = wallpaperWin.isRtl() ? 1f : 0f;
         float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : defaultWallpaperX;
         float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
-        int availw = wallpaperWin.mFrame.right - wallpaperWin.mFrame.left - dw;
+        int availw = wallpaperWin.getFrameLw().right - wallpaperWin.getFrameLw().left - dw;
         int offset = availw > 0 ? -(int)(availw * wpx + .5f) : 0;
         if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
             offset += mLastWallpaperDisplayOffsetX;
@@ -310,7 +310,7 @@
 
         float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
         float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
-        int availh = wallpaperWin.mFrame.bottom - wallpaperWin.mFrame.top - dh;
+        int availh = wallpaperWin.getFrameLw().bottom - wallpaperWin.getFrameLw().top - dh;
         offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
         if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
             offset += mLastWallpaperDisplayOffsetY;
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 548e23a..825255e 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -99,13 +99,7 @@
         tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
         t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
         t.setAlpha(leash, tmp.transformation.getAlpha());
-        if (mStackClipMode == STACK_CLIP_NONE) {
-            t.setWindowCrop(leash, tmp.transformation.getClipRect());
-        } else if (mStackClipMode == STACK_CLIP_AFTER_ANIM) {
-            mTmpRect.set(mStackBounds);
-            // Offset stack bounds to stack position so the final crop is in screen space.
-            mTmpRect.offsetTo(mPosition.x, mPosition.y);
-            t.setFinalCrop(leash, mTmpRect);
+        if (mStackClipMode == STACK_CLIP_NONE || mStackClipMode == STACK_CLIP_AFTER_ANIM) {
             t.setWindowCrop(leash, tmp.transformation.getClipRect());
         } else {
             mTmpRect.set(mStackBounds);
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
new file mode 100644
index 0000000..5f41df7
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.wm.WindowFramesProto.CONTAINING_FRAME;
+import static com.android.server.wm.WindowFramesProto.CONTENT_FRAME;
+import static com.android.server.wm.WindowFramesProto.CUTOUT;
+import static com.android.server.wm.WindowFramesProto.DECOR_FRAME;
+import static com.android.server.wm.WindowFramesProto.DISPLAY_FRAME;
+import static com.android.server.wm.WindowFramesProto.FRAME;
+import static com.android.server.wm.WindowFramesProto.OUTSET_FRAME;
+import static com.android.server.wm.WindowFramesProto.OVERSCAN_FRAME;
+import static com.android.server.wm.WindowFramesProto.PARENT_FRAME;
+import static com.android.server.wm.WindowFramesProto.VISIBLE_FRAME;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.util.proto.ProtoOutputStream;
+
+import java.io.PrintWriter;
+import android.view.DisplayCutout;
+
+import com.android.server.wm.utils.WmDisplayCutout;
+
+/**
+ * Container class for all the window frames that affect how windows are laid out.
+ *
+ * TODO(b/111611553): Investigate which frames are still needed and which are duplicates
+ */
+public class WindowFrames {
+
+    /**
+     * In most cases, this is the area of the entire screen.
+     *
+     * TODO(b/111611553): The name is unclear and most likely should be swapped with
+     * {@link #mDisplayFrame}
+     * TODO(b/111611553): In some cases, it also includes top insets, like for IME. Determine
+     * whether this is still necessary to do.
+     */
+    public final Rect mParentFrame = new Rect();
+
+    /**
+     * The entire screen area of the {@link TaskStack} this window is in. Usually equal to the
+     * screen area of the device.
+     *
+     * TODO(b/111611553): The name is unclear and most likely should be swapped with
+     * {@link #mParentFrame}
+    */
+    public final Rect mDisplayFrame = new Rect();
+
+    /**
+     * The region of the display frame that the display type supports displaying content on. This
+     * is mostly a special case for TV where some displays don’t have the entire display usable.
+     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} flag can be used to
+     * allow window display contents to extend into the overscan region.
+     */
+    public final Rect mOverscanFrame = new Rect();
+
+    /**
+     * Legacy stuff. Generally equal to the content frame expect when the IME for older apps
+     * displays hint text.
+     */
+    public final Rect mVisibleFrame = new Rect();
+
+    /**
+     * The area not occupied by the status and navigation bars. So, if both status and navigation
+     * bars are visible, the decor frame is equal to the stable frame.
+     */
+    public final Rect mDecorFrame = new Rect();
+
+    /**
+     * Equal to the decor frame if the IME (e.g. keyboard) is not present. Equal to the decor frame
+     * minus the area occupied by the IME if the IME is present.
+     */
+    public final Rect mContentFrame = new Rect();
+
+    /**
+     * The display frame minus the stable insets. This value is always constant regardless of if
+     * the status bar or navigation bar is visible.
+     */
+    public final Rect mStableFrame = new Rect();
+
+    /**
+     * Frame that includes dead area outside of the surface but where we want to pretend that it's
+     * possible to draw.
+     */
+    final public Rect mOutsetFrame = new Rect();
+
+    /**
+     * Similar to {@link #mDisplayFrame}
+     *
+     * TODO: Why is this different than mDisplayFrame
+     */
+    final Rect mContainingFrame = new Rect();
+
+    /**
+     * "Real" frame that the application sees, in display coordinate space.
+     */
+    final Rect mFrame = new Rect();
+
+    /**
+     * The last real frame that was reported to the client.
+     */
+    final Rect mLastFrame = new Rect();
+
+    /**
+     * Whether the parent frame would have been different if there was no display cutout.
+     */
+    private boolean mParentFrameWasClippedByDisplayCutout;
+
+    /**
+     * Part of the display that has been cut away. See {@link DisplayCutout}.
+     */
+    WmDisplayCutout mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+
+    /**
+     * The last cutout that has been reported to the client.
+     */
+    WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+
+    public WindowFrames() {
+    }
+
+    public WindowFrames(Rect parentFrame, Rect displayFrame, Rect overscanFrame, Rect contentFrame,
+            Rect visibleFrame, Rect decorFrame, Rect stableFrame, Rect outsetFrame) {
+        setFrames(parentFrame, displayFrame, overscanFrame, contentFrame, visibleFrame, decorFrame,
+                stableFrame, outsetFrame);
+    }
+
+    public void setFrames(Rect parentFrame, Rect displayFrame, Rect overscanFrame,
+            Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
+            Rect outsetFrame) {
+        mParentFrame.set(parentFrame);
+        mDisplayFrame.set(displayFrame);
+        mOverscanFrame.set(overscanFrame);
+        mContentFrame.set(contentFrame);
+        mVisibleFrame.set(visibleFrame);
+        mDecorFrame.set(decorFrame);
+        mStableFrame.set(stableFrame);
+        mOutsetFrame.set(outsetFrame);
+    }
+
+    public void setParentFrameWasClippedByDisplayCutout(
+            boolean parentFrameWasClippedByDisplayCutout) {
+        mParentFrameWasClippedByDisplayCutout = parentFrameWasClippedByDisplayCutout;
+    }
+
+    boolean parentFrameWasClippedByDisplayCutout() {
+        return mParentFrameWasClippedByDisplayCutout;
+    }
+
+    public void setDisplayCutout(WmDisplayCutout displayCutout) {
+        mDisplayCutout = displayCutout;
+    }
+
+    /**
+     * @return true if the width or height has changed since last reported to the client.
+     */
+    boolean didFrameSizeChange() {
+        return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height());
+    }
+
+    /**
+     * @return true if the display cutout has changed since last reported to the client.
+     */
+    boolean didDisplayCutoutChange() {
+        return !mLastDisplayCutout.equals(mDisplayCutout);
+    }
+
+    public void writeToProto(@NonNull ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+        mParentFrame.writeToProto(proto, PARENT_FRAME);
+        mContentFrame.writeToProto(proto, CONTENT_FRAME);
+        mDisplayFrame.writeToProto(proto, DISPLAY_FRAME);
+        mOverscanFrame.writeToProto(proto, OVERSCAN_FRAME);
+        mVisibleFrame.writeToProto(proto, VISIBLE_FRAME);
+        mDecorFrame.writeToProto(proto, DECOR_FRAME);
+        mOutsetFrame.writeToProto(proto, OUTSET_FRAME);
+        mContainingFrame.writeToProto(proto, CONTAINING_FRAME);
+        mFrame.writeToProto(proto, FRAME);
+        mDisplayCutout.getDisplayCutout().writeToProto(proto, CUTOUT);
+        proto.end(token);
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("Frames: containing=");
+                mContainingFrame.printShortString(pw);
+                pw.print(" parent="); mParentFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print("    display=");
+                mDisplayFrame.printShortString(pw);
+                pw.print(" overscan="); mOverscanFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print("    content=");
+                mContentFrame.printShortString(pw);
+                pw.print(" visible="); mVisibleFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print("    decor=");
+                mDecorFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print("    outset=");
+                mOutsetFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
+                pw.print(" last="); mLastFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print(" cutout=" + mDisplayCutout.getDisplayCutout());
+                pw.print(" last=" + mLastDisplayCutout.getDisplayCutout());
+                pw.println();
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 0c65518..44783f8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -410,7 +410,7 @@
     public abstract boolean isDockedDividerResizing();
 
     /**
-     * Requests the window manager to recompute the windows for accessibility.
+     * Requests the window manager to resend the windows for accessibility.
      */
     public abstract void computeWindowsForAccessibility();
 
@@ -436,4 +436,9 @@
      * the window token is not found.
      */
     public abstract int getWindowOwnerUserId(IBinder windowToken);
+
+    /**
+     * Returns {@code true} if a Window owned by {@code uid} has focus.
+     */
+    public abstract boolean isUidFocused(int uid);
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 399078a..158d09a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -226,7 +226,6 @@
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
 
 import com.android.internal.R;
-import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
@@ -269,6 +268,7 @@
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+
 /** {@hide} */
 public class WindowManagerService extends IWindowManager.Stub
         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
@@ -563,6 +563,8 @@
 
     boolean mForceResizableTasks = false;
     boolean mSupportsPictureInPicture = false;
+    boolean mSupportsFreeformWindowManagement = false;
+    boolean mIsPc = false;
 
     boolean mDisableTransitionAnimation = false;
 
@@ -583,7 +585,6 @@
     }
 
     ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>();
-    int mDeferredRotationPauseCount;
     final WallpaperVisibilityListeners mWallpaperVisibilityListeners =
             new WallpaperVisibilityListeners();
 
@@ -952,7 +953,7 @@
                 com.android.internal.R.bool.config_disableTransitionAnimation);
         mInputManager = inputManager; // Must be before createDisplayContentLocked.
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
-        mDisplaySettings = new DisplaySettings();
+        mDisplaySettings = new DisplaySettings(this);
         mDisplaySettings.readSettingsLocked();
 
         mPolicy = policy;
@@ -1011,7 +1012,6 @@
         mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
 
         final AnimationHandler animationHandler = new AnimationHandler();
-        animationHandler.setProvider(new SfVsyncFrameCallbackProvider());
         mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,
                 AnimationThread.getHandler(), animationHandler);
 
@@ -1069,13 +1069,13 @@
                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
         mHoldingScreenWakeLock.setReferenceCounted(false);
 
-        mSurfaceAnimationRunner = new SurfaceAnimationRunner();
+        mSurfaceAnimationRunner = new SurfaceAnimationRunner(mPowerManagerInternal);
 
         mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
 
         mTaskPositioningController = new TaskPositioningController(
-                this, mInputManager, mInputMonitor, mActivityTaskManager, mH.getLooper());
+                this, mInputManager, mActivityTaskManager, mH.getLooper());
         mDragDropController = new DragDropController(this, mH.getLooper());
 
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
@@ -1101,9 +1101,8 @@
         showEmulatorDisplayOverlayIfNeeded();
     }
 
-
-    public InputMonitor getInputMonitor() {
-        return mInputMonitor;
+    public InputManagerCallback getInputManagerCallback() {
+        return mInputManagerCallback;
     }
 
     @Override
@@ -1152,7 +1151,7 @@
                 throw new IllegalStateException("Display has not been initialialized");
             }
 
-            final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);
 
             if (displayContent == null) {
                 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
@@ -1366,7 +1365,7 @@
             // UID, otherwise we allow unlimited duration. When a UID looses focus we
             // schedule hiding all of its toast windows.
             if (type == TYPE_TOAST) {
-                if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) {
+                if (!displayContent.canAddToastWindowForUid(callingUid)) {
                     Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
                     return WindowManagerGlobal.ADD_DUPLICATE_ADD;
                 }
@@ -1469,14 +1468,18 @@
             displayFrames.onDisplayInfoUpdated(displayInfo,
                     displayContent.calculateDisplayCutoutForRotation(displayInfo.rotation));
             final Rect taskBounds;
+            final boolean floatingStack;
             if (atoken != null && atoken.getTask() != null) {
                 taskBounds = mTmpRect;
                 atoken.getTask().getBounds(mTmpRect);
+                floatingStack = atoken.getTask().isFloating();
             } else {
                 taskBounds = null;
+                floatingStack = false;
             }
-            if (mPolicy.getLayoutHintLw(win.mAttrs, taskBounds, displayFrames, outFrame,
-                    outContentInsets, outStableInsets, outOutsets, outDisplayCutout)) {
+            if (mPolicy.getLayoutHintLw(win.mAttrs, taskBounds, displayFrames, floatingStack,
+                    outFrame, outContentInsets, outStableInsets, outOutsets,
+                    outDisplayCutout)) {
                 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
             }
 
@@ -1487,7 +1490,7 @@
                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
             }
 
-            mInputMonitor.setUpdateInputWindowsNeededLw();
+            displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
 
             boolean focusChanged = false;
             if (win.canReceiveKeys()) {
@@ -1507,9 +1510,10 @@
             win.getParent().assignChildLayers();
 
             if (focusChanged) {
-                mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
+                displayContent.getInputMonitor().setInputFocusLw(mCurrentFocus,
+                        false /*updateInputWindows*/);
             }
-            mInputMonitor.updateInputWindowsLw(false /*force*/);
+            displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
 
             if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
                     + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
@@ -1536,9 +1540,20 @@
      * that corresponds to a display just added to DisplayManager has not yet been created. This
      * usually means that the call of this method was initiated from outside of Activity or Window
      * Manager. In most cases the regular getter should be used.
+     * @param displayId The preferred display Id.
+     * @param token The window token associated with the window we are trying to get display for.
+     *              if not null then the display of the window token will be returned. Set to null
+     *              is there isn't an a token associated with the request.
      * @see RootWindowContainer#getDisplayContent(int)
      */
-    private DisplayContent getDisplayContentOrCreate(int displayId) {
+    private DisplayContent getDisplayContentOrCreate(int displayId, IBinder token) {
+        if (token != null) {
+            final WindowToken wToken = mRoot.getWindowToken(token);
+            if (wToken != null) {
+                return wToken.getDisplayContent();
+            }
+        }
+
         DisplayContent displayContent = mRoot.getDisplayContent(displayId);
 
         // Create an instance if possible instead of waiting for the ActivityManagerService to drive
@@ -1593,7 +1608,7 @@
         }
         // We use the visible frame, because we want the animation to morph the window from what
         // was visible to the user to the final destination of the new window.
-        Rect frame = replacedWindow.mVisibleFrame;
+        Rect frame = replacedWindow.getVisibleFrameLw();
         // We treat this as if this activity was opening, so we can trigger the app transition
         // animation and piggy-back on existing transition animation infrastructure.
         mOpeningApps.add(atoken);
@@ -1722,7 +1737,7 @@
             }
         }
 
-        mInputMonitor.updateInputWindowsLw(true /*force*/);
+        dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
     }
 
     void setInputMethodWindowLocked(WindowState win) {
@@ -1829,7 +1844,7 @@
                 outDisplayFrame.setEmpty();
                 return;
             }
-            outDisplayFrame.set(win.mDisplayFrame);
+            outDisplayFrame.set(win.getDisplayFrameLw());
         }
     }
 
@@ -1891,6 +1906,14 @@
             }
 
             win.setFrameNumber(frameNumber);
+
+            // TODO(b/111504081): Consolidate seamless rotation logic.
+            if (win.mPendingForcedSeamlessRotate != null && !mWaitingForConfig) {
+                win.mPendingForcedSeamlessRotate.finish(win.mToken, win);
+                win.mFinishForcedSeamlessRotateFrameNumber = win.getFrameNumber();
+                win.mPendingForcedSeamlessRotate = null;
+            }
+
             int attrChanges = 0;
             int flagChanges = 0;
             if (attrs != null) {
@@ -2034,7 +2057,7 @@
                 try {
                     result = createSurfaceControl(outSurface, result, win, winAnimator);
                 } catch (Exception e) {
-                    mInputMonitor.updateInputWindowsLw(true /*force*/);
+                    win.getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/);
 
                     Slog.w(TAG_WM, "Exception thrown when creating surface for client "
                              + client + " (" + win.mAttrs.getTitle() + ")",
@@ -2080,12 +2103,9 @@
             }
 
             if (focusMayChange) {
-                //System.out.println("Focus may change: " + win.mAttrs.getTitle());
-                if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                        false /*updateInputWindows*/)) {
+                if (updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/)) {
                     imMayMove = false;
                 }
-                //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
             }
 
             // updateFocusedWindowLocked() already assigned layers so we only need to
@@ -2164,9 +2184,9 @@
             win.mLastRelayoutContentInsets.set(win.mContentInsets);
             outVisibleInsets.set(win.mVisibleInsets);
             outStableInsets.set(win.mStableInsets);
-            outCutout.set(win.mDisplayCutout.getDisplayCutout());
+            outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
             outOutsets.set(win.mOutsets);
-            outBackdropFrame.set(win.getBackdropFrame(win.mFrame));
+            outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
             if (localLOGV) Slog.v(
                 TAG_WM, "Relayout given client " + client.asBinder()
                 + ", requestedWidth=" + requestedWidth
@@ -2180,8 +2200,6 @@
 
             result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
 
-            mInputMonitor.updateInputWindowsLw(true /*force*/);
-
             if (DEBUG_LAYOUT) {
                 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
             }
@@ -2331,6 +2349,12 @@
 
         synchronized(mWindowMap) {
             final DisplayContent dc = mRoot.getDisplayContent(displayId);
+            if (dc == null) {
+                Slog.w(TAG_WM, "addWindowToken: Attempted to add token: " + binder
+                        + " for non-exiting displayId=" + displayId);
+                return;
+            }
+
             WindowToken token = dc.getWindowToken(binder);
             if (token != null) {
                 Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
@@ -2370,7 +2394,7 @@
                     return;
                 }
 
-                mInputMonitor.updateInputWindowsLw(true /*force*/);
+                dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -2471,10 +2495,7 @@
                 dc.setLastOrientation(req);
                 //send a message to Policy indicating orientation change to take
                 //action like disabling/enabling sensors etc.,
-                // TODO(multi-display): Implement policy for secondary displays.
-                if (dc.isDefaultDisplay) {
-                    mPolicy.setCurrentOrientationLw(req);
-                }
+                dc.getDisplayRotation().setCurrentOrientation(req);
                 return dc.updateRotationUnchecked(forceUpdate);
             }
             return false;
@@ -2483,27 +2504,6 @@
         }
     }
 
-    // If this is true we have updated our desired orientation, but not yet
-    // changed the real orientation our applied our screen rotation animation.
-    // For example, because a previous screen rotation was in progress.
-    boolean rotationNeedsUpdateLocked() {
-        // TODO(multi-display): Check for updates on all displays. Need to have per-display policy
-        // to implement WindowManagerPolicy#rotationForOrientationLw() correctly.
-        final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
-        final int lastOrientation = defaultDisplayContent.getLastOrientation();
-        final int oldRotation = defaultDisplayContent.getRotation();
-        final boolean oldAltOrientation = defaultDisplayContent.getAltOrientation();
-
-        final int rotation = mPolicy.rotationForOrientationLw(lastOrientation, oldRotation,
-                true /* defaultDisplay */);
-        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
-                lastOrientation, rotation);
-        if (oldRotation == rotation && oldAltOrientation == altOrientation) {
-            return false;
-        }
-        return true;
-    }
-
     @Override
     public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) {
@@ -2559,7 +2559,7 @@
             if (changed) {
                 AppWindowToken prev = mFocusedApp;
                 mFocusedApp = newFocus;
-                mInputMonitor.setFocusedAppLw(newFocus);
+                mFocusedApp.getDisplayContent().getInputMonitor().setFocusedAppLw(newFocus);
                 setFocusTaskRegionLocked(prev);
             }
 
@@ -3467,7 +3467,7 @@
             if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
 
             // Enable input dispatch.
-            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
+            mInputManagerCallback.setEventDispatchingLw(mEventDispatchingEnabled);
         }
 
         try {
@@ -3822,37 +3822,6 @@
         updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
     }
 
-    /**
-     * Temporarily pauses rotation changes until resumed.
-     *
-     * This can be used to prevent rotation changes from occurring while the user is
-     * performing certain operations, such as drag and drop.
-     *
-     * This call nests and must be matched by an equal number of calls to
-     * {@link #resumeRotationLocked}.
-     */
-    void pauseRotationLocked() {
-        mDeferredRotationPauseCount += 1;
-    }
-
-    /**
-     * Resumes normal rotation changes after being paused.
-     */
-    void resumeRotationLocked() {
-        if (mDeferredRotationPauseCount > 0) {
-            mDeferredRotationPauseCount -= 1;
-            if (mDeferredRotationPauseCount == 0) {
-                // TODO(multi-display): Update rotation for different displays separately.
-                final DisplayContent displayContent = getDefaultDisplayContentLocked();
-                final boolean changed = displayContent.updateRotationUnchecked();
-                if (changed) {
-                    mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
-                            .sendToTarget();
-                }
-            }
-        }
-    }
-
     private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
         if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked:"
                 + " alwaysSendConfiguration=" + alwaysSendConfiguration
@@ -3863,28 +3832,31 @@
         long origId = Binder.clearCallingIdentity();
 
         try {
-            // TODO(multi-display): Update rotation for different displays separately.
-            final boolean rotationChanged;
-            final int displayId;
             synchronized (mWindowMap) {
-                final DisplayContent displayContent = getDefaultDisplayContentLocked();
-                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
-                rotationChanged = displayContent.updateRotationUnchecked();
-                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-                if (!rotationChanged || forceRelayout) {
-                    displayContent.setLayoutNeeded();
+                boolean layoutNeeded = false;
+                final int displayCount = mRoot.mChildren.size();
+                for (int i = 0; i < displayCount; ++i) {
+                    final DisplayContent displayContent = mRoot.mChildren.get(i);
+                    Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
+                    final boolean rotationChanged = displayContent.updateRotationUnchecked();
+                    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+
+                    if (!rotationChanged || forceRelayout) {
+                        displayContent.setLayoutNeeded();
+                        layoutNeeded = true;
+                    }
+                    if (rotationChanged || alwaysSendConfiguration) {
+                        mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
+                                .sendToTarget();
+                    }
+                }
+
+                if (layoutNeeded) {
                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                             "updateRotation: performSurfacePlacement");
                     mWindowPlacerLocked.performSurfacePlacement();
                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 }
-                displayId = displayContent.getDisplayId();
-            }
-
-            if (rotationChanged || alwaysSendConfiguration) {
-                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: sendNewConfiguration");
-                sendNewConfiguration(displayId);
-                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -3893,6 +3865,13 @@
     }
 
     @Override
+    public WindowManagerPolicy.DisplayContentInfo getDefaultDisplayContentInfo() {
+        synchronized (mWindowMap) {
+            return getDefaultDisplayContentLocked();
+        }
+    }
+
+    @Override
     public int getDefaultDisplayRotation() {
         synchronized (mWindowMap) {
             return getDefaultDisplayContentLocked().getRotation();
@@ -3906,6 +3885,15 @@
 
     @Override
     public int watchRotation(IRotationWatcher watcher, int displayId) {
+        final DisplayContent displayContent;
+        synchronized (mWindowMap) {
+            displayContent = mRoot.getDisplayContent(displayId);
+        }
+        if (displayContent == null) {
+            throw new IllegalArgumentException("Trying to register rotation event "
+                    + "for invalid display: " + displayId);
+        }
+
         final IBinder watcherBinder = watcher.asBinder();
         IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
             @Override
@@ -3933,7 +3921,7 @@
                 // Client died, no cleanup needed.
             }
 
-            return getDefaultDisplayRotation();
+            return displayContent.getRotation();
         }
     }
 
@@ -3978,56 +3966,14 @@
         }
     }
 
-    /**
-     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
-     * theme attribute) on devices that feature a physical options menu key attempt to position
-     * their menu panel window along the edge of the screen nearest the physical menu key.
-     * This lowers the travel distance between invoking the menu panel and selecting
-     * a menu option.
-     *
-     * This method helps control where that menu is placed. Its current implementation makes
-     * assumptions about the menu key and its relationship to the screen based on whether
-     * the device's natural orientation is portrait (width < height) or landscape.
-     *
-     * The menu key is assumed to be located along the bottom edge of natural-portrait
-     * devices and along the right edge of natural-landscape devices. If these assumptions
-     * do not hold for the target device, this method should be changed to reflect that.
-     *
-     * @return A {@link Gravity} value for placing the options menu window
-     */
     @Override
-    public int getPreferredOptionsPanelGravity() {
+    public int getPreferredOptionsPanelGravity(int displayId) {
         synchronized (mWindowMap) {
-            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
-            final DisplayContent displayContent = getDefaultDisplayContentLocked();
-            final int rotation = displayContent.getRotation();
-            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
-                // On devices with a natural orientation of portrait
-                switch (rotation) {
-                    default:
-                    case Surface.ROTATION_0:
-                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-                    case Surface.ROTATION_90:
-                        return Gravity.RIGHT | Gravity.BOTTOM;
-                    case Surface.ROTATION_180:
-                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-                    case Surface.ROTATION_270:
-                        return Gravity.START | Gravity.BOTTOM;
-                }
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                return Gravity.CENTER | Gravity.BOTTOM;
             }
-
-            // On devices with a natural orientation of landscape
-            switch (rotation) {
-                default:
-                case Surface.ROTATION_0:
-                    return Gravity.RIGHT | Gravity.BOTTOM;
-                case Surface.ROTATION_90:
-                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-                case Surface.ROTATION_180:
-                    return Gravity.START | Gravity.BOTTOM;
-                case Surface.ROTATION_270:
-                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-            }
+            return displayContent.getPreferredOptionsPanelGravity();
         }
     }
 
@@ -4436,7 +4382,7 @@
     // Input Events and Focus Management
     // -------------------------------------------------------------
 
-    final InputMonitor mInputMonitor = new InputMonitor(this);
+    final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);
     private boolean mEventDispatchingEnabled;
 
     @Override
@@ -4448,7 +4394,7 @@
         synchronized (mWindowMap) {
             mEventDispatchingEnabled = enabled;
             if (mDisplayEnabled) {
-                mInputMonitor.setEventDispatchingLw(enabled);
+                mInputManagerCallback.setEventDispatchingLw(enabled);
             }
         }
     }
@@ -4473,7 +4419,7 @@
     }
 
     public boolean detectSafeMode() {
-        if (!mInputMonitor.waitForInputDevicesReady(
+        if (!mInputManagerCallback.waitForInputDevicesReady(
                 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
             Slog.w(TAG_WM, "Devices still not ready after waiting "
                    + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
@@ -4718,9 +4664,9 @@
                 } break;
 
                 case WINDOW_FREEZE_TIMEOUT: {
-                    // TODO(multidisplay): Can non-default displays rotate?
+                    final DisplayContent displayContent = (DisplayContent) msg.obj;
                     synchronized (mWindowMap) {
-                        getDefaultDisplayContentLocked().onWindowFreezeTimeout();
+                        displayContent.onWindowFreezeTimeout();
                     }
                     break;
                 }
@@ -5033,11 +4979,9 @@
                 }
                 break;
                 case SEAMLESS_ROTATION_TIMEOUT: {
-                    // Rotation only supported on primary display.
-                    // TODO(multi-display)
-                    synchronized(mWindowMap) {
-                        final DisplayContent dc = getDefaultDisplayContentLocked();
-                        dc.onSeamlessRotationTimeout();
+                    final DisplayContent displayContent = (DisplayContent) msg.obj;
+                    synchronized (mWindowMap) {
+                        displayContent.onSeamlessRotationTimeout();
                     }
                 }
                 break;
@@ -5077,6 +5021,12 @@
                 Slog.v(TAG_WM, "handleMessage: exit");
             }
         }
+
+        /** Remove the previous messages with the same 'what' and 'obj' then send the new one. */
+        void sendNewMessageDelayed(int what, Object obj, long delayMillis) {
+            removeMessages(what, obj);
+            sendMessageDelayed(obtainMessage(what, obj), delayMillis);
+        }
     }
 
     void destroyPreservedSurfaceLocked() {
@@ -5540,8 +5490,7 @@
                 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
                 // XXX should probably keep timeout from
                 // when we first froze the display.
-                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
-                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
+                mH.sendNewMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, w.getDisplayContent(),
                         WINDOW_FREEZE_TIMEOUT_DURATION);
             }
         }
@@ -5666,9 +5615,9 @@
             boolean imWindowChanged = false;
             if (mInputMethodWindow != null) {
                 final WindowState prevTarget = mInputMethodTarget;
+
                 final WindowState newTarget =
                         displayContent.computeImeTarget(true /* updateImeTarget*/);
-
                 imWindowChanged = prevTarget != newTarget;
 
                 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
@@ -5724,7 +5673,7 @@
             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
                 // If we defer assigning layers, then the caller is responsible for
                 // doing this part.
-                mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
+                displayContent.getInputMonitor().setInputFocusLw(mCurrentFocus, updateInputWindows);
             }
 
             displayContent.adjustForImeIfNeeded();
@@ -5771,7 +5720,7 @@
         // As a result, we only track the display that has initially froze the screen.
         mFrozenDisplayId = displayContent.getDisplayId();
 
-        mInputMonitor.freezeInputDispatchingLw();
+        mInputManagerCallback.freezeInputDispatchingLw();
 
         // Clear the last input window -- that is just used for
         // clean transitions between IMEs, and if we are freezing
@@ -5788,8 +5737,7 @@
         }
 
         mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN);
-        // TODO(multidisplay): rotation on non-default displays
-        if (CUSTOM_SCREEN_ROTATION && displayContent.isDefaultDisplay) {
+        if (CUSTOM_SCREEN_ROTATION) {
             mExitAnimId = exitAnim;
             mEnterAnimId = enterAnim;
             ScreenRotationAnimation screenRotationAnimation =
@@ -5803,7 +5751,7 @@
 
             displayContent.updateDisplayInfo();
             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
-                    mPolicy.isDefaultOrientationForced(), isSecure,
+                    displayContent.getDisplayRotation().isDefaultOrientationForced(), isSecure,
                     this);
             mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
                     screenRotationAnimation);
@@ -5838,7 +5786,7 @@
         final int displayId = mFrozenDisplayId;
         mFrozenDisplayId = INVALID_DISPLAY;
         mDisplayFrozen = false;
-        mInputMonitor.thawInputDispatchingLw();
+        mInputManagerCallback.thawInputDispatchingLw();
         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
         StringBuilder sb = new StringBuilder(128);
         sb.append("Screen frozen for ");
@@ -6078,24 +6026,41 @@
 
     @Override
     public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
-            InputEventReceiver.Factory inputEventReceiverFactory) {
+            InputEventReceiver.Factory inputEventReceiverFactory, int displayId) {
         synchronized (mWindowMap) {
-            return mInputMonitor.createInputConsumer(looper, name, inputEventReceiverFactory);
+            DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent != null) {
+                return displayContent.getInputMonitor().createInputConsumer(looper, name,
+                        inputEventReceiverFactory);
+            } else {
+                return null;
+            }
         }
     }
 
     @Override
     public void createInputConsumer(IBinder token, String name, InputChannel inputChannel) {
         synchronized (mWindowMap) {
-            mInputMonitor.createInputConsumer(token, name, inputChannel, Binder.getCallingPid(),
-                    Binder.getCallingUserHandle());
+            // TODO(b/112049699): Fix this for multiple displays. There is only one inputChannel
+            // here to accept the return value.
+            DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+            if (display != null) {
+                display.getInputMonitor().createInputConsumer(token, name, inputChannel,
+                        Binder.getCallingPid(), Binder.getCallingUserHandle());
+            }
         }
     }
 
     @Override
     public boolean destroyInputConsumer(String name) {
         synchronized (mWindowMap) {
-            return mInputMonitor.destroyInputConsumer(name);
+            // TODO(b/112049699): Fix this for multiple displays. For consistency with
+            // createInputConsumer above.
+            DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+            if (display != null) {
+                return display.getInputMonitor().destroyInputConsumer(name);
+            }
+            return false;
         }
     }
 
@@ -6214,6 +6179,17 @@
     }
 
     /**
+     * Returns true if the callingUid has any window currently visible to the user.
+     */
+    public boolean isAnyWindowVisibleForUid(int callingUid) {
+        synchronized (mWindowMap) {
+            return mRoot.forAllWindows(w -> {
+                return w.getOwningUid() == callingUid && w.isVisible();
+            }, true /* traverseTopToBottom */);
+        }
+    }
+
+    /**
      * Called when a task has been removed from the recent tasks list.
      * <p>
      * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window
@@ -6439,7 +6415,7 @@
                 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
                 pw.println();
 
-        mInputMonitor.dump(pw, "  ");
+        mInputManagerCallback.dump(pw, "  ");
         mUnknownAppVisibilityController.dump(pw, "  ");
         mTaskSnapshotController.dump(pw, "  ");
 
@@ -6474,7 +6450,6 @@
                     pw.print(defaultDisplayContent.getLastWindowForcedOrientation());
                     pw.print(" mLastOrientation=");
                             pw.println(defaultDisplayContent.getLastOrientation());
-            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
             pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
                     pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
                     pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
@@ -6759,8 +6734,10 @@
 
     public void onOverlayChanged() {
         synchronized (mWindowMap) {
-            mPolicy.onOverlayChangedLw();
-            getDefaultDisplayContentLocked().updateDisplayInfo();
+            mRoot.forAllDisplays(displayContent -> {
+                mPolicy.onOverlayChangedLw(displayContent);
+                displayContent.updateDisplayInfo();
+            });
             requestTraversal();
         }
     }
@@ -6917,16 +6894,26 @@
         }
     }
 
+    public void setSupportsFreeformWindowManagement(boolean supportsFreeformWindowManagement) {
+        synchronized (mWindowMap) {
+            mSupportsFreeformWindowManagement = supportsFreeformWindowManagement;
+        }
+    }
+
+    public void setIsPc(boolean isPc) {
+        synchronized (mWindowMap) {
+            mIsPc = isPc;
+        }
+    }
+
     static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
         return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
     }
 
     @Override
     public void registerDockedStackListener(IDockedStackListener listener) {
-        if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
-                "registerDockedStackListener()")) {
-            return;
-        }
+        mAtmInternal.enforceCallerIsRecentsOrHasPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
+                "registerDockedStackListener()");
         synchronized (mWindowMap) {
             // TODO(multi-display): The listener is registered on the default display only.
             getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
@@ -7088,19 +7075,24 @@
 
     @Override
     public void dontOverrideDisplayInfo(int displayId) {
-        synchronized (mWindowMap) {
-            final DisplayContent dc = getDisplayContentOrCreate(displayId);
-            if (dc == null) {
-                throw new IllegalArgumentException(
-                        "Trying to register a non existent display.");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mWindowMap) {
+                final DisplayContent dc = getDisplayContentOrCreate(displayId, null);
+                if (dc == null) {
+                    throw new IllegalArgumentException(
+                            "Trying to register a non existent display.");
+                }
+                // We usually set the override info in DisplayManager so that we get consistent
+                // values when displays are changing. However, we don't do this for displays that
+                // serve as containers for ActivityViews because we don't want letter-/pillar-boxing
+                // during resize.
+                dc.mShouldOverrideDisplayConfiguration = false;
+                mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId,
+                        null /* info */);
             }
-            // We usually set the override info in DisplayManager so that we get consistent
-            // values when displays are changing. However, we don't do this for displays that
-            // serve as containers for ActivityViews because we don't want letter-/pillar-boxing
-            // during resize.
-            dc.mShouldOverrideDisplayConfiguration = false;
-            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId,
-                    null /* info */);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
@@ -7139,11 +7131,7 @@
             }
             finishSeamlessRotation();
 
-            final DisplayContent displayContent = w.getDisplayContent();
-            if (displayContent.updateRotationUnchecked()) {
-                mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
-                        .sendToTarget();
-            }
+            w.getDisplayContent().updateRotationAndSendNewConfigIfNeeded();
         }
     }
 
@@ -7273,7 +7261,7 @@
             synchronized (mWindowMap) {
                 WindowState windowState = mWindowMap.get(token);
                 if (windowState != null) {
-                    outBounds.set(windowState.mFrame);
+                    outBounds.set(windowState.getFrameLw());
                 } else {
                     outBounds.setEmpty();
                 }
@@ -7414,7 +7402,7 @@
                 accessibilityController = mAccessibilityController;
             }
             if (accessibilityController != null) {
-                accessibilityController.performComputeChangedWindowsNotLocked();
+                accessibilityController.performComputeChangedWindowsNotLocked(true);
             }
         }
 
@@ -7448,6 +7436,13 @@
                 return UserHandle.USER_NULL;
             }
         }
+
+        @Override
+        public boolean isUidFocused(int uid) {
+            synchronized (mWindowMap) {
+                return mCurrentFocus != null ? uid == mCurrentFocus.getOwningUid() : false;
+            }
+        }
     }
 
     void registerAppFreezeListener(AppFreezeListener listener) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c8c4b58..58fb7a0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -119,15 +119,10 @@
 import static com.android.server.wm.WindowStateProto.ANIMATOR;
 import static com.android.server.wm.WindowStateProto.ATTRIBUTES;
 import static com.android.server.wm.WindowStateProto.CHILD_WINDOWS;
-import static com.android.server.wm.WindowStateProto.CONTAINING_FRAME;
-import static com.android.server.wm.WindowStateProto.CONTENT_FRAME;
 import static com.android.server.wm.WindowStateProto.CONTENT_INSETS;
-import static com.android.server.wm.WindowStateProto.CUTOUT;
-import static com.android.server.wm.WindowStateProto.DECOR_FRAME;
 import static com.android.server.wm.WindowStateProto.DESTROYING;
-import static com.android.server.wm.WindowStateProto.DISPLAY_FRAME;
 import static com.android.server.wm.WindowStateProto.DISPLAY_ID;
-import static com.android.server.wm.WindowStateProto.FRAME;
+import static com.android.server.wm.WindowStateProto.FINISHED_FORCED_SEAMLESS_ROTATION_FRAME;
 import static com.android.server.wm.WindowStateProto.GIVEN_CONTENT_INSETS;
 import static com.android.server.wm.WindowStateProto.HAS_SURFACE;
 import static com.android.server.wm.WindowStateProto.IDENTIFIER;
@@ -135,10 +130,8 @@
 import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
 import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
 import static com.android.server.wm.WindowStateProto.OUTSETS;
-import static com.android.server.wm.WindowStateProto.OUTSET_FRAME;
-import static com.android.server.wm.WindowStateProto.OVERSCAN_FRAME;
 import static com.android.server.wm.WindowStateProto.OVERSCAN_INSETS;
-import static com.android.server.wm.WindowStateProto.PARENT_FRAME;
+import static com.android.server.wm.WindowStateProto.PENDING_FORCED_SEAMLESS_ROTATION;
 import static com.android.server.wm.WindowStateProto.REMOVED;
 import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT;
 import static com.android.server.wm.WindowStateProto.REQUESTED_HEIGHT;
@@ -149,9 +142,9 @@
 import static com.android.server.wm.WindowStateProto.SURFACE_POSITION;
 import static com.android.server.wm.WindowStateProto.SYSTEM_UI_VISIBILITY;
 import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
-import static com.android.server.wm.WindowStateProto.VISIBLE_FRAME;
 import static com.android.server.wm.WindowStateProto.VISIBLE_INSETS;
 import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
 import static com.android.server.wm.utils.CoordinateTransforms.transformRect;
 import static com.android.server.wm.utils.CoordinateTransforms.transformToRotation;
 
@@ -282,6 +275,15 @@
     private boolean mDragResizing;
     private boolean mDragResizingChangeReported = true;
     private int mResizeMode;
+    /**
+     * Special mode that is intended only for the rounded corner overlay: during rotation
+     * transition, we un-rotate the window token such that the window appears as it did before the
+     * rotation.
+     * TODO(b/111504081): Consolidate seamless rotation logic.
+     */
+    final boolean mForceSeamlesslyRotate;
+    ForcedSeamlessRotator mPendingForcedSeamlessRotate;
+    long mFinishForcedSeamlessRotateFrameNumber;
 
     private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
 
@@ -358,9 +360,6 @@
     private final Rect mLastOutsets = new Rect();
     private boolean mOutsetsChanged = false;
 
-    /** Part of the display that has been cut away. See {@link DisplayCutout}. */
-    WmDisplayCutout mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
-    private WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
     private boolean mDisplayCutoutChanged;
 
     /**
@@ -401,50 +400,12 @@
     float mLastHScale=1, mLastVScale=1;
     final Matrix mTmpMatrix = new Matrix();
 
-    // "Real" frame that the application sees, in display coordinate space.
-    final Rect mFrame = new Rect();
-    final Rect mLastFrame = new Rect();
     private boolean mFrameSizeChanged = false;
     // Frame that is scaled to the application's coordinate space when in
     // screen size compatibility mode.
     final Rect mCompatFrame = new Rect();
 
-    final Rect mContainingFrame = new Rect();
-
-    final Rect mParentFrame = new Rect();
-
-    /** Whether the parent frame would have been different if there was no display cutout. */
-    private boolean mParentFrameWasClippedByDisplayCutout;
-
-    // The entire screen area of the {@link TaskStack} this window is in. Usually equal to the
-    // screen area of the device.
-    final Rect mDisplayFrame = new Rect();
-
-    // The region of the display frame that the display type supports displaying content on. This
-    // is mostly a special case for TV where some displays don’t have the entire display usable.
-    // {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} flag can be used to allow
-    // window display contents to extend into the overscan region.
-    private final Rect mOverscanFrame = new Rect();
-
-    // The display frame minus the stable insets. This value is always constant regardless of if
-    // the status bar or navigation bar is visible.
-    private final Rect mStableFrame = new Rect();
-
-    // The area not occupied by the status and navigation bars. So, if both status and navigation
-    // bars are visible, the decor frame is equal to the stable frame.
-    final Rect mDecorFrame = new Rect();
-
-    // Equal to the decor frame if the IME (e.g. keyboard) is not present. Equal to the decor frame
-    // minus the area occupied by the IME if the IME is present.
-    private final Rect mContentFrame = new Rect();
-
-    // Legacy stuff. Generally equal to the content frame expect when the IME for older apps
-    // displays hint text.
-    final Rect mVisibleFrame = new Rect();
-
-    // Frame that includes dead area outside of the surface but where we want to pretend that it's
-    // possible to draw.
-    private final Rect mOutsetFrame = new Rect();
+    private final WindowFrames mWindowFrames = new WindowFrames();
 
     /**
      * Usually empty. Set to the task's tempInsetFrame. See
@@ -671,6 +632,18 @@
 
     private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
 
+    void forceSeamlesslyRotateIfAllowed(int oldRotation, int rotation) {
+        if (mForceSeamlesslyRotate) {
+            if (mPendingForcedSeamlessRotate != null) {
+                oldRotation = mPendingForcedSeamlessRotate.getOldRotation();
+            }
+
+            mPendingForcedSeamlessRotate = new ForcedSeamlessRotator(
+                    oldRotation, rotation, getDisplayInfo());
+            mPendingForcedSeamlessRotate.unrotate(this.mToken);
+        }
+    }
+
     interface PowerManagerWrapper {
         void wakeUp(long time, String reason);
 
@@ -717,6 +690,7 @@
         mSeq = seq;
         mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
         mPowerManagerWrapper = powerManagerWrapper;
+        mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
         if (localLOGV) Slog.v(
             TAG, "Window " + this + " client=" + c.asBinder()
             + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -850,10 +824,7 @@
     }
 
     @Override
-    public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overscanFrame,
-            Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
-            Rect outsetFrame, WmDisplayCutout displayCutout,
-            boolean parentFrameWasClippedByDisplayCutout) {
+    public void computeFrameLw(WindowFrames windowFrames) {
         if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
             // This window is being replaced and either already got information that it's being
             // removed or we are still waiting for some information. Because of this we don't
@@ -862,7 +833,8 @@
             return;
         }
         mHaveFrame = true;
-        mParentFrameWasClippedByDisplayCutout = parentFrameWasClippedByDisplayCutout;
+        mWindowFrames.setParentFrameWasClippedByDisplayCutout(
+                windowFrames.parentFrameWasClippedByDisplayCutout());
 
         final Task task = getTask();
         final boolean inFullscreenContainer = inFullscreenContainer();
@@ -892,36 +864,39 @@
         final int layoutYDiff;
         if (inFullscreenContainer || layoutInParentFrame()) {
             // We use the parent frame as the containing frame for fullscreen and child windows
-            mContainingFrame.set(parentFrame);
-            mDisplayFrame.set(displayFrame);
-            layoutDisplayFrame = displayFrame;
-            layoutContainingFrame = parentFrame;
+            mWindowFrames.mContainingFrame.set(windowFrames.mParentFrame);
+            mWindowFrames.mDisplayFrame.set(windowFrames.mDisplayFrame);
+            layoutDisplayFrame = windowFrames.mDisplayFrame;
+            layoutContainingFrame = windowFrames.mParentFrame;
             layoutXDiff = 0;
             layoutYDiff = 0;
         } else {
-            getBounds(mContainingFrame);
+            getBounds(mWindowFrames.mContainingFrame);
             if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
 
                 // If the bounds are frozen, we still want to translate the window freely and only
                 // freeze the size.
                 Rect frozen = mAppToken.mFrozenBounds.peek();
-                mContainingFrame.right = mContainingFrame.left + frozen.width();
-                mContainingFrame.bottom = mContainingFrame.top + frozen.height();
+                mWindowFrames.mContainingFrame.right =
+                        mWindowFrames.mContainingFrame.left + frozen.width();
+                mWindowFrames.mContainingFrame.bottom =
+                        mWindowFrames.mContainingFrame.top + frozen.height();
             }
             final WindowState imeWin = mService.mInputMethodWindow;
             // IME is up and obscuring this window. Adjust the window position so it is visible.
             if (imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget()) {
-                if (inFreeformWindowingMode()
-                        && mContainingFrame.bottom > contentFrame.bottom) {
+                if (inFreeformWindowingMode() && mWindowFrames.mContainingFrame.bottom
+                        > windowFrames.mContentFrame.bottom) {
                     // In freeform we want to move the top up directly.
                     // TODO: Investigate why this is contentFrame not parentFrame.
-                    mContainingFrame.top -= mContainingFrame.bottom - contentFrame.bottom;
-                } else if (!inPinnedWindowingMode()
-                        && mContainingFrame.bottom > parentFrame.bottom) {
+                    mWindowFrames.mContainingFrame.top -= mWindowFrames.mContainingFrame.bottom
+                            - windowFrames.mContentFrame.bottom;
+                } else if (!inPinnedWindowingMode() && mWindowFrames.mContainingFrame.bottom
+                        > windowFrames.mParentFrame.bottom) {
                     // 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 pinned stack, they are handled separately in the PinnedStackController.
-                    mContainingFrame.bottom = parentFrame.bottom;
+                    mWindowFrames.mContainingFrame.bottom = windowFrames.mParentFrame.bottom;
                 }
             }
 
@@ -929,8 +904,8 @@
                 // In floating modes (e.g. freeform, pinned) we have only to set the rectangle
                 // if it wasn't set already. No need to intersect it with the (visible)
                 // "content frame" since it is allowed to be outside the visible desktop.
-                if (mContainingFrame.isEmpty()) {
-                    mContainingFrame.set(contentFrame);
+                if (mWindowFrames.mContainingFrame.isEmpty()) {
+                    mWindowFrames.mContainingFrame.set(windowFrames.mContentFrame);
                 }
             }
 
@@ -940,31 +915,39 @@
                 // PIP edge case: When going from pinned to fullscreen, we apply a
                 // tempInsetFrame for the full task - but we're still at the start of the animation.
                 // To prevent a jump if there's a letterbox, restrict to the parent frame.
-                mInsetFrame.intersectUnchecked(parentFrame);
-                mContainingFrame.intersectUnchecked(parentFrame);
+                mInsetFrame.intersectUnchecked(windowFrames.mParentFrame);
+                mWindowFrames.mContainingFrame.intersectUnchecked(windowFrames.mParentFrame);
             }
 
-            mDisplayFrame.set(mContainingFrame);
-            layoutXDiff = !mInsetFrame.isEmpty() ? mInsetFrame.left - mContainingFrame.left : 0;
-            layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0;
-            layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame;
+            mWindowFrames.mDisplayFrame.set(mWindowFrames.mContainingFrame);
+            layoutXDiff =
+                    !mInsetFrame.isEmpty() ? mInsetFrame.left - mWindowFrames.mContainingFrame.left
+                            : 0;
+            layoutYDiff =
+                    !mInsetFrame.isEmpty() ? mInsetFrame.top - mWindowFrames.mContainingFrame.top
+                            : 0;
+            layoutContainingFrame =
+                    !mInsetFrame.isEmpty() ? mInsetFrame : mWindowFrames.mContainingFrame;
             mTmpRect.set(0, 0, dc.getDisplayInfo().logicalWidth, dc.getDisplayInfo().logicalHeight);
-            subtractInsets(mDisplayFrame, layoutContainingFrame, displayFrame, mTmpRect);
+            subtractInsets(mWindowFrames.mDisplayFrame, layoutContainingFrame,
+                    windowFrames.mDisplayFrame, mTmpRect);
             if (!layoutInParentFrame()) {
-                subtractInsets(mContainingFrame, layoutContainingFrame, parentFrame, mTmpRect);
-                subtractInsets(mInsetFrame, layoutContainingFrame, parentFrame, mTmpRect);
+                subtractInsets(mWindowFrames.mContainingFrame, layoutContainingFrame,
+                        windowFrames.mParentFrame, mTmpRect);
+                subtractInsets(mInsetFrame, layoutContainingFrame, windowFrames.mParentFrame,
+                        mTmpRect);
             }
-            layoutDisplayFrame = displayFrame;
+            layoutDisplayFrame = windowFrames.mDisplayFrame;
             layoutDisplayFrame.intersect(layoutContainingFrame);
         }
 
-        final int pw = mContainingFrame.width();
-        final int ph = mContainingFrame.height();
+        final int pw = mWindowFrames.mContainingFrame.width();
+        final int ph = mWindowFrames.mContainingFrame.height();
 
-        if (!mParentFrame.equals(parentFrame)) {
+        if (!mWindowFrames.mParentFrame.equals(windowFrames.mParentFrame)) {
             //Slog.i(TAG_WM, "Window " + this + " content frame from " + mParentFrame
             //        + " to " + parentFrame);
-            mParentFrame.set(parentFrame);
+            mWindowFrames.mParentFrame.set(windowFrames.mParentFrame);
             mContentChanged = true;
         }
         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
@@ -973,146 +956,161 @@
             mContentChanged = true;
         }
 
-        mOverscanFrame.set(overscanFrame);
-        mContentFrame.set(contentFrame);
-        mVisibleFrame.set(visibleFrame);
-        mDecorFrame.set(decorFrame);
-        mStableFrame.set(stableFrame);
-        final boolean hasOutsets = outsetFrame != null;
+        mWindowFrames.mOverscanFrame.set(windowFrames.mOverscanFrame);
+        mWindowFrames.mContentFrame.set(windowFrames.mContentFrame);
+        mWindowFrames.mVisibleFrame.set(windowFrames.mVisibleFrame);
+        mWindowFrames.mDecorFrame.set(windowFrames.mDecorFrame);
+        mWindowFrames.mStableFrame.set(windowFrames.mStableFrame);
+        final boolean hasOutsets = !windowFrames.mOutsetFrame.isEmpty();
         if (hasOutsets) {
-            mOutsetFrame.set(outsetFrame);
+            mWindowFrames.mOutsetFrame.set(windowFrames.mOutsetFrame);
         }
 
-        final int fw = mFrame.width();
-        final int fh = mFrame.height();
+        final int fw = mWindowFrames.mFrame.width();
+        final int fh = mWindowFrames.mFrame.height();
 
         applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
 
         // Calculate the outsets before the content frame gets shrinked to the window frame.
         if (hasOutsets) {
-            mOutsets.set(Math.max(mContentFrame.left - mOutsetFrame.left, 0),
-                    Math.max(mContentFrame.top - mOutsetFrame.top, 0),
-                    Math.max(mOutsetFrame.right - mContentFrame.right, 0),
-                    Math.max(mOutsetFrame.bottom - mContentFrame.bottom, 0));
+            mOutsets.set(
+                    Math.max(mWindowFrames.mContentFrame.left - mWindowFrames.mOutsetFrame.left, 0),
+                    Math.max(mWindowFrames.mContentFrame.top - mWindowFrames.mOutsetFrame.top, 0),
+                    Math.max(mWindowFrames.mOutsetFrame.right - mWindowFrames.mContentFrame.right,
+                            0),
+                    Math.max(mWindowFrames.mOutsetFrame.bottom - mWindowFrames.mContentFrame.bottom,
+                            0));
         } else {
             mOutsets.set(0, 0, 0, 0);
         }
 
         // Make sure the content and visible frames are inside of the
         // final window frame.
-        if (windowsAreFloating && !mFrame.isEmpty()) {
+        if (windowsAreFloating && !mWindowFrames.mFrame.isEmpty()) {
             // For pinned workspace the frame isn't limited in any particular
             // way since SystemUI controls the bounds. For freeform however
             // we want to keep things inside the content frame.
-            final Rect limitFrame = task.inPinnedWindowingMode() ? mFrame : mContentFrame;
+            final Rect limitFrame = task.inPinnedWindowingMode() ? mWindowFrames.mFrame
+                    : mWindowFrames.mContentFrame;
             // Keep the frame out of the blocked system area, limit it in size to the content area
             // and make sure that there is always a minimum visible so that the user can drag it
             // into a usable area..
-            final int height = Math.min(mFrame.height(), limitFrame.height());
-            final int width = Math.min(limitFrame.width(), mFrame.width());
+            final int height = Math.min(mWindowFrames.mFrame.height(), limitFrame.height());
+            final int width = Math.min(limitFrame.width(), mWindowFrames.mFrame.width());
             final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
             final int minVisibleHeight = Math.min(height, WindowManagerService.dipToPixel(
                     MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics));
             final int minVisibleWidth = Math.min(width, WindowManagerService.dipToPixel(
                     MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics));
             final int top = Math.max(limitFrame.top,
-                    Math.min(mFrame.top, limitFrame.bottom - minVisibleHeight));
+                    Math.min( mWindowFrames.mFrame.top, limitFrame.bottom - minVisibleHeight));
             final int left = Math.max(limitFrame.left + minVisibleWidth - width,
-                    Math.min(mFrame.left, limitFrame.right - minVisibleWidth));
-            mFrame.set(left, top, left + width, top + height);
-            mContentFrame.set(mFrame);
-            mVisibleFrame.set(mContentFrame);
-            mStableFrame.set(mContentFrame);
+                    Math.min( mWindowFrames.mFrame.left, limitFrame.right - minVisibleWidth));
+            mWindowFrames.mFrame.set(left, top, left + width, top + height);
+            mWindowFrames.mContentFrame.set( mWindowFrames.mFrame);
+            mWindowFrames.mVisibleFrame.set(mWindowFrames.mContentFrame);
+            mWindowFrames.mStableFrame.set(mWindowFrames.mContentFrame);
         } else if (mAttrs.type == TYPE_DOCK_DIVIDER) {
-            dc.getDockedDividerController().positionDockedStackedDivider(mFrame);
-            mContentFrame.set(mFrame);
-            if (!mFrame.equals(mLastFrame)) {
+            dc.getDockedDividerController().positionDockedStackedDivider(mWindowFrames.mFrame);
+            mWindowFrames.mContentFrame.set(mWindowFrames.mFrame);
+            if (!mWindowFrames.mFrame.equals(mWindowFrames.mLastFrame)) {
                 mMovedByResize = true;
             }
         } else {
-            mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
-                    Math.max(mContentFrame.top, mFrame.top),
-                    Math.min(mContentFrame.right, mFrame.right),
-                    Math.min(mContentFrame.bottom, mFrame.bottom));
+            mWindowFrames.mContentFrame.set(
+                    Math.max(mWindowFrames.mContentFrame.left, mWindowFrames.mFrame.left),
+                    Math.max(mWindowFrames.mContentFrame.top, mWindowFrames.mFrame.top),
+                    Math.min(mWindowFrames.mContentFrame.right, mWindowFrames.mFrame.right),
+                    Math.min(mWindowFrames.mContentFrame.bottom, mWindowFrames.mFrame.bottom));
 
-            mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left),
-                    Math.max(mVisibleFrame.top, mFrame.top),
-                    Math.min(mVisibleFrame.right, mFrame.right),
-                    Math.min(mVisibleFrame.bottom, mFrame.bottom));
+            mWindowFrames.mVisibleFrame.set(
+                    Math.max(mWindowFrames.mVisibleFrame.left, mWindowFrames.mFrame.left),
+                    Math.max(mWindowFrames.mVisibleFrame.top, mWindowFrames.mFrame.top),
+                    Math.min(mWindowFrames.mVisibleFrame.right, mWindowFrames.mFrame.right),
+                    Math.min(mWindowFrames.mVisibleFrame.bottom, mWindowFrames.mFrame.bottom));
 
-            mStableFrame.set(Math.max(mStableFrame.left, mFrame.left),
-                    Math.max(mStableFrame.top, mFrame.top),
-                    Math.min(mStableFrame.right, mFrame.right),
-                    Math.min(mStableFrame.bottom, mFrame.bottom));
+            mWindowFrames.mStableFrame.set(
+                    Math.max(mWindowFrames.mStableFrame.left, mWindowFrames.mFrame.left),
+                    Math.max(mWindowFrames.mStableFrame.top, mWindowFrames.mFrame.top),
+                    Math.min(mWindowFrames.mStableFrame.right, mWindowFrames.mFrame.right),
+                    Math.min(mWindowFrames.mStableFrame.bottom, mWindowFrames.mFrame.bottom));
         }
 
         if (inFullscreenContainer && !windowsAreFloating) {
             // Windows that are not fullscreen can be positioned outside of the display frame,
             // but that is not a reason to provide them with overscan insets.
-            mOverscanInsets.set(Math.max(mOverscanFrame.left - layoutContainingFrame.left, 0),
-                    Math.max(mOverscanFrame.top - layoutContainingFrame.top, 0),
-                    Math.max(layoutContainingFrame.right - mOverscanFrame.right, 0),
-                    Math.max(layoutContainingFrame.bottom - mOverscanFrame.bottom, 0));
+            mOverscanInsets.set(
+                    Math.max(mWindowFrames.mOverscanFrame.left - layoutContainingFrame.left, 0),
+                    Math.max(mWindowFrames.mOverscanFrame.top - layoutContainingFrame.top, 0),
+                    Math.max(layoutContainingFrame.right - mWindowFrames.mOverscanFrame.right, 0),
+                    Math.max(layoutContainingFrame.bottom - mWindowFrames.mOverscanFrame.bottom,
+                            0));
         }
 
         if (mAttrs.type == TYPE_DOCK_DIVIDER) {
             // For the docked divider, we calculate the stable insets like a full-screen window
             // so it can use it to calculate the snap positions.
-            final WmDisplayCutout c = displayCutout.calculateRelativeTo(mDisplayFrame);
-            mTmpRect.set(mDisplayFrame);
+            final WmDisplayCutout c = windowFrames.mDisplayCutout.calculateRelativeTo(
+                    mWindowFrames.mDisplayFrame);
+            mTmpRect.set(mWindowFrames.mDisplayFrame);
             mTmpRect.inset(c.getDisplayCutout().getSafeInsets());
-            mTmpRect.intersectUnchecked(mStableFrame);
+            mTmpRect.intersectUnchecked(mWindowFrames.mStableFrame);
 
-            mStableInsets.set(Math.max(mTmpRect.left - mDisplayFrame.left, 0),
-                    Math.max(mTmpRect.top - mDisplayFrame.top, 0),
-                    Math.max(mDisplayFrame.right - mTmpRect.right, 0),
-                    Math.max(mDisplayFrame.bottom - mTmpRect.bottom, 0));
+            mStableInsets.set(Math.max(mTmpRect.left - mWindowFrames.mDisplayFrame.left, 0),
+                    Math.max(mTmpRect.top - mWindowFrames.mDisplayFrame.top, 0),
+                    Math.max(mWindowFrames.mDisplayFrame.right - mTmpRect.right, 0),
+                    Math.max(mWindowFrames.mDisplayFrame.bottom - mTmpRect.bottom, 0));
 
             // The divider doesn't care about insets in any case, so set it to empty so we don't
             // trigger a relayout when moving it.
             mContentInsets.setEmpty();
             mVisibleInsets.setEmpty();
-            displayCutout = WmDisplayCutout.NO_CUTOUT;
+            windowFrames.setDisplayCutout(WmDisplayCutout.NO_CUTOUT);
         } else {
             getDisplayContent().getBounds(mTmpRect);
             // Override right and/or bottom insets in case if the frame doesn't fit the screen in
             // non-fullscreen mode.
             boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer
-                    && mFrame.right > mTmpRect.right;
+                    && mWindowFrames.mFrame.right > mTmpRect.right;
             boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
-                    && mFrame.bottom > mTmpRect.bottom;
-            mContentInsets.set(mContentFrame.left - mFrame.left,
-                    mContentFrame.top - mFrame.top,
-                    overrideRightInset ? mTmpRect.right - mContentFrame.right
-                            : mFrame.right - mContentFrame.right,
-                    overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom
-                            : mFrame.bottom - mContentFrame.bottom);
+                    && mWindowFrames.mFrame.bottom > mTmpRect.bottom;
+            mContentInsets.set(mWindowFrames.mContentFrame.left - mWindowFrames.mFrame.left,
+                    mWindowFrames.mContentFrame.top - mWindowFrames.mFrame.top,
+                    overrideRightInset ? mTmpRect.right - mWindowFrames.mContentFrame.right
+                            : mWindowFrames.mFrame.right - mWindowFrames.mContentFrame.right,
+                    overrideBottomInset ? mTmpRect.bottom - mWindowFrames.mContentFrame.bottom
+                            : mWindowFrames.mFrame.bottom - mWindowFrames.mContentFrame.bottom);
 
-            mVisibleInsets.set(mVisibleFrame.left - mFrame.left,
-                    mVisibleFrame.top - mFrame.top,
-                    overrideRightInset ? mTmpRect.right - mVisibleFrame.right
-                            : mFrame.right - mVisibleFrame.right,
-                    overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom
-                            : mFrame.bottom - mVisibleFrame.bottom);
+            mVisibleInsets.set(mWindowFrames.mVisibleFrame.left - mWindowFrames.mFrame.left,
+                    mWindowFrames.mVisibleFrame.top - mWindowFrames.mFrame.top,
+                    overrideRightInset ? mTmpRect.right - mWindowFrames.mVisibleFrame.right
+                            : mWindowFrames.mFrame.right - mWindowFrames.mVisibleFrame.right,
+                    overrideBottomInset ? mTmpRect.bottom - mWindowFrames.mVisibleFrame.bottom
+                            : mWindowFrames.mFrame.bottom - mWindowFrames.mVisibleFrame.bottom);
 
-            mStableInsets.set(Math.max(mStableFrame.left - mFrame.left, 0),
-                    Math.max(mStableFrame.top - mFrame.top, 0),
-                    overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0)
-                            : Math.max(mFrame.right - mStableFrame.right, 0),
-                    overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0)
-                            :  Math.max(mFrame.bottom - mStableFrame.bottom, 0));
+            mStableInsets.set(
+                    Math.max(mWindowFrames.mStableFrame.left - mWindowFrames.mFrame.left, 0),
+                    Math.max(mWindowFrames.mStableFrame.top - mWindowFrames.mFrame.top, 0),
+                    overrideRightInset ? Math.max(mTmpRect.right - mWindowFrames.mStableFrame.right,
+                            0) : Math.max(
+                            mWindowFrames.mFrame.right - mWindowFrames.mStableFrame.right, 0),
+                    overrideBottomInset ? Math.max(
+                            mTmpRect.bottom - mWindowFrames.mStableFrame.bottom, 0) : Math.max(
+                            mWindowFrames.mFrame.bottom - mWindowFrames.mStableFrame.bottom, 0));
         }
 
-        mDisplayCutout = displayCutout.calculateRelativeTo(mFrame);
+
+        mWindowFrames.setDisplayCutout(
+                windowFrames.mDisplayCutout.calculateRelativeTo(windowFrames.mFrame));
 
         // Offset the actual frame by the amount layout frame is off.
-        mFrame.offset(-layoutXDiff, -layoutYDiff);
+        mWindowFrames.mFrame.offset(-layoutXDiff, -layoutYDiff);
         mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
-        mContentFrame.offset(-layoutXDiff, -layoutYDiff);
-        mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
-        mStableFrame.offset(-layoutXDiff, -layoutYDiff);
+        mWindowFrames.mContentFrame.offset(-layoutXDiff, -layoutYDiff);
+        mWindowFrames.mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
+        mWindowFrames.mStableFrame.offset(-layoutXDiff, -layoutYDiff);
 
-        mCompatFrame.set(mFrame);
+        mCompatFrame.set(mWindowFrames.mFrame);
         if (mEnforceSizeCompat) {
             // If there is a size compatibility scale being applied to the
             // window, we need to apply this to its insets so that they are
@@ -1128,12 +1126,13 @@
             mCompatFrame.scale(mInvGlobalScale);
         }
 
-        if (mIsWallpaper && (fw != mFrame.width() || fh != mFrame.height())) {
+        if (mIsWallpaper && (fw != mWindowFrames.mFrame.width()
+                || fh != mWindowFrames.mFrame.height())) {
             final DisplayContent displayContent = getDisplayContent();
             if (displayContent != null) {
                 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-                getDisplayContent().mWallpaperController.updateWallpaperOffset(
-                        this, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
+                getDisplayContent().mWallpaperController.updateWallpaperOffset(this,
+                        displayInfo.logicalWidth, displayInfo.logicalHeight, false);
             }
         }
 
@@ -1141,7 +1140,7 @@
                 "Resolving (mRequestedWidth="
                 + mRequestedWidth + ", mRequestedheight="
                 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
-                + "): frame=" + mFrame.toShortString()
+                + "): frame=" + mWindowFrames.mFrame.toShortString()
                 + " ci=" + mContentInsets.toShortString()
                 + " vi=" + mVisibleInsets.toShortString()
                 + " si=" + mStableInsets.toShortString()
@@ -1162,31 +1161,47 @@
 
     @Override
     public Rect getFrameLw() {
-        return mFrame;
+        return mWindowFrames.mFrame;
     }
 
     @Override
     public Rect getDisplayFrameLw() {
-        return mDisplayFrame;
+        return mWindowFrames.mDisplayFrame;
     }
 
     @Override
     public Rect getOverscanFrameLw() {
-        return mOverscanFrame;
+        return mWindowFrames.mOverscanFrame;
     }
 
     @Override
     public Rect getContentFrameLw() {
-        return mContentFrame;
+        return mWindowFrames.mContentFrame;
     }
 
     @Override
     public Rect getVisibleFrameLw() {
-        return mVisibleFrame;
+        return mWindowFrames.mVisibleFrame;
     }
 
     Rect getStableFrameLw() {
-        return mStableFrame;
+        return mWindowFrames.mStableFrame;
+    }
+
+    Rect getDecorFrame() {
+        return mWindowFrames.mDecorFrame;
+    }
+
+    Rect getParentFrame() {
+        return mWindowFrames.mParentFrame;
+    }
+
+    Rect getContainingFrame() {
+        return mWindowFrames.mContainingFrame;
+    }
+
+    WmDisplayCutout getWmDisplayCutout() {
+        return mWindowFrames.mDisplayCutout;
     }
 
     @Override
@@ -1245,9 +1260,8 @@
         mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets);
         mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets);
         mOutsetsChanged |= !mLastOutsets.equals(mOutsets);
-        mFrameSizeChanged |= (mLastFrame.width() != mFrame.width()) ||
-                (mLastFrame.height() != mFrame.height());
-        mDisplayCutoutChanged |= !mLastDisplayCutout.equals(mDisplayCutout);
+        mFrameSizeChanged |= mWindowFrames.didFrameSizeChange();
+        mDisplayCutoutChanged |= mWindowFrames.didDisplayCutoutChange();
         return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged
                 || mOutsetsChanged || mFrameSizeChanged || mDisplayCutoutChanged;
     }
@@ -1282,12 +1296,12 @@
                 && !isDragResizingChangeReported();
 
         if (localLOGV) Slog.v(TAG_WM, "Resizing " + this + ": configChanged=" + configChanged
-                + " dragResizingChanged=" + dragResizingChanged + " last=" + mLastFrame
-                + " frame=" + mFrame);
+                + " dragResizingChanged=" + dragResizingChanged
+                + " last=" + mWindowFrames.mLastFrame + " frame=" + mWindowFrames.mFrame);
 
         // We update mLastFrame always rather than in the conditional with the last inset
         // variables, because mFrameSizeChanged only tracks the width and height changing.
-        mLastFrame.set(mFrame);
+        mWindowFrames.mLastFrame.set(mWindowFrames.mFrame);
 
         if (mContentInsetsChanged
                 || mVisibleInsetsChanged
@@ -1442,13 +1456,13 @@
             }
         }
 
-        bounds.set(mVisibleFrame);
+        bounds.set(mWindowFrames.mVisibleFrame);
         if (intersectWithStackBounds) {
             bounds.intersect(mTmpRect);
         }
 
         if (bounds.isEmpty()) {
-            bounds.set(mFrame);
+            bounds.set(mWindowFrames.mFrame);
             if (intersectWithStackBounds) {
                 bounds.intersect(mTmpRect);
             }
@@ -1805,8 +1819,8 @@
 
         // Frame has moved, containing content frame has also moved, and we're not currently
         // animating... let's do something.
-        final int left = mFrame.left;
-        final int top = mFrame.top;
+        final int left = mWindowFrames.mFrame.left;
+        final int top = mWindowFrames.mFrame.top;
         final Task task = getTask();
         final boolean adjustedForMinimizedDockOrIme = task != null
                 && (task.mStack.isAdjustedForMinimizedDockedStack()
@@ -1840,7 +1854,8 @@
     private boolean hasMoved() {
         return mHasSurface && (mContentChanged || mMovedByResize)
                 && !mAnimatingExit
-                && (mFrame.top != mLastFrame.top || mFrame.left != mLastFrame.left)
+                && (mWindowFrames.mFrame.top != mWindowFrames.mLastFrame.top
+                    || mWindowFrames.mFrame.left != mWindowFrames.mLastFrame.left)
                 && (!mIsChildWindow || !getParentWindow().hasMoved());
     }
 
@@ -1854,8 +1869,9 @@
 
     boolean fillsDisplay() {
         final DisplayInfo displayInfo = getDisplayInfo();
-        return mFrame.left <= 0 && mFrame.top <= 0
-                && mFrame.right >= displayInfo.appWidth && mFrame.bottom >= displayInfo.appHeight;
+        return mWindowFrames.mFrame.left <= 0 && mWindowFrames.mFrame.top <= 0
+                && mWindowFrames.mFrame.right >= displayInfo.appWidth
+                && mWindowFrames.mFrame.bottom >= displayInfo.appHeight;
     }
 
     /** Returns true if last applied config was not yet requested by client. */
@@ -2016,7 +2032,7 @@
                     // Set up a replacement input channel since the app is now dead.
                     // We need to catch tapping on the dead window to restart the app.
                     openInputChannel(null);
-                    mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+                    getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/);
                     return;
                 }
 
@@ -2083,7 +2099,7 @@
                 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
         mService.mWindowPlacerLocked.performSurfacePlacement();
         if (focusChanged) {
-            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+            getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
         }
     }
 
@@ -2493,8 +2509,8 @@
         return getWindowConfiguration().keepVisibleDeadAppWindowOnScreen();
     }
 
-    /** @return true if this window desires key events. */
-    boolean canReceiveKeys() {
+    @Override
+    public boolean canReceiveKeys() {
         return isVisibleOrAdding()
                 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
                 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
@@ -2889,10 +2905,10 @@
             // All window frames that are fullscreen extend above status bar, but some don't extend
             // below navigation bar. Thus, check for display frame for top/left and stable frame for
             // bottom right.
-            if (win.mFrame.left <= win.mDisplayFrame.left
-                    && win.mFrame.top <= win.mDisplayFrame.top
-                    && win.mFrame.right >= win.mStableFrame.right
-                    && win.mFrame.bottom >= win.mStableFrame.bottom) {
+            if (win.getFrameLw().left <= win.getDisplayFrameLw().left
+                    && win.getFrameLw().top <= win.getDisplayFrameLw().top
+                    && win.getFrameLw().right >= win.getStableFrameLw().right
+                    && win.getFrameLw().bottom >= win.getStableFrameLw().bottom) {
                 // Is a fullscreen window, like the clock alarm. Show to everyone.
                 return false;
             }
@@ -2909,7 +2925,7 @@
     }
 
     void getTouchableRegion(Region outRegion) {
-        final Rect frame = mFrame;
+        final Rect frame = mWindowFrames.mFrame;
         switch (mTouchableInsets) {
             default:
             case TOUCHABLE_INSETS_FRAME:
@@ -2994,7 +3010,7 @@
             if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING)
                 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
 
-            final Rect frame = mFrame;
+            final Rect frame = mWindowFrames.mFrame;
             final Rect overscanInsets = mLastOverscanInsets;
             final Rect contentInsets = mLastContentInsets;
             final Rect visibleInsets = mLastVisibleInsets;
@@ -3003,7 +3019,7 @@
             final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING;
             final boolean reportOrientation = mReportOrientationChanged;
             final int displayId = getDisplayId();
-            final DisplayCutout displayCutout = mDisplayCutout.getDisplayCutout();
+            final DisplayCutout displayCutout = getWmDisplayCutout().getDisplayCutout();
             if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
                     && mClient instanceof IWindow.Stub) {
                 // To prevent deadlock simulate one-way call if win.mClient is a local object.
@@ -3136,7 +3152,7 @@
             // Only windows with an AppWindowToken are letterboxed.
             return false;
         }
-        if (!mParentFrameWasClippedByDisplayCutout) {
+        if (!mWindowFrames.parentFrameWasClippedByDisplayCutout()) {
             // Cutout didn't make a difference, no letterbox
             return false;
         }
@@ -3159,7 +3175,7 @@
      */
     private boolean frameCoversEntireAppTokenBounds() {
         mTmpRect.set(mAppToken.getBounds());
-        mTmpRect.intersectUnchecked(mFrame);
+        mTmpRect.intersectUnchecked(mWindowFrames.mFrame);
         return mAppToken.getBounds().equals(mTmpRect);
     }
 
@@ -3261,10 +3277,7 @@
         proto.write(STACK_ID, getStackId());
         mAttrs.writeToProto(proto, ATTRIBUTES);
         mGivenContentInsets.writeToProto(proto, GIVEN_CONTENT_INSETS);
-        mFrame.writeToProto(proto, FRAME);
-        mContainingFrame.writeToProto(proto, CONTAINING_FRAME);
-        mParentFrame.writeToProto(proto, PARENT_FRAME);
-        mContentFrame.writeToProto(proto, CONTENT_FRAME);
+        mWindowFrames.writeToProto(proto, WINDOW_FRAMES);
         mContentInsets.writeToProto(proto, CONTENT_INSETS);
         mAttrs.surfaceInsets.writeToProto(proto, SURFACE_INSETS);
         mSurfacePosition.writeToProto(proto, SURFACE_POSITION);
@@ -3279,21 +3292,20 @@
         proto.write(SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
         proto.write(HAS_SURFACE, mHasSurface);
         proto.write(IS_READY_FOR_DISPLAY, isReadyForDisplay());
-        mDisplayFrame.writeToProto(proto, DISPLAY_FRAME);
-        mOverscanFrame.writeToProto(proto, OVERSCAN_FRAME);
-        mVisibleFrame.writeToProto(proto, VISIBLE_FRAME);
-        mDecorFrame.writeToProto(proto, DECOR_FRAME);
-        mOutsetFrame.writeToProto(proto, OUTSET_FRAME);
         mOverscanInsets.writeToProto(proto, OVERSCAN_INSETS);
         mVisibleInsets.writeToProto(proto, VISIBLE_INSETS);
         mStableInsets.writeToProto(proto, STABLE_INSETS);
         mOutsets.writeToProto(proto, OUTSETS);
-        mDisplayCutout.getDisplayCutout().writeToProto(proto, CUTOUT);
         proto.write(REMOVE_ON_EXIT, mRemoveOnExit);
         proto.write(DESTROYING, mDestroying);
         proto.write(REMOVED, mRemoved);
         proto.write(IS_ON_SCREEN, isOnScreen());
         proto.write(IS_VISIBLE, isVisible());
+        if (mForceSeamlesslyRotate) {
+            proto.write(PENDING_FORCED_SEAMLESS_ROTATION, mPendingForcedSeamlessRotate != null);
+            proto.write(FINISHED_FORCED_SEAMLESS_ROTATION_FRAME,
+                    mFinishForcedSeamlessRotateFrameNumber);
+        }
         proto.end(token);
     }
 
@@ -3405,30 +3417,12 @@
         pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
                 pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay());
                 pw.print(" mWindowRemovalAllowed="); pw.println(mWindowRemovalAllowed);
-        if (dumpAll) {
-            pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
-                    pw.print(" last="); mLastFrame.printShortString(pw);
-                    pw.println();
-        }
         if (mEnforceSizeCompat) {
             pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
                     pw.println();
         }
         if (dumpAll) {
-            pw.print(prefix); pw.print("Frames: containing=");
-                    mContainingFrame.printShortString(pw);
-                    pw.print(" parent="); mParentFrame.printShortString(pw);
-                    pw.println();
-            pw.print(prefix); pw.print("    display="); mDisplayFrame.printShortString(pw);
-                    pw.print(" overscan="); mOverscanFrame.printShortString(pw);
-                    pw.println();
-            pw.print(prefix); pw.print("    content="); mContentFrame.printShortString(pw);
-                    pw.print(" visible="); mVisibleFrame.printShortString(pw);
-                    pw.println();
-            pw.print(prefix); pw.print("    decor="); mDecorFrame.printShortString(pw);
-                    pw.println();
-            pw.print(prefix); pw.print("    outset="); mOutsetFrame.printShortString(pw);
-                    pw.println();
+            mWindowFrames.dump(pw, prefix);
             pw.print(prefix); pw.print("Cur insets: overscan=");
                     mOverscanInsets.printShortString(pw);
                     pw.print(" content="); mContentInsets.printShortString(pw);
@@ -3436,8 +3430,6 @@
                     pw.print(" stable="); mStableInsets.printShortString(pw);
                     pw.print(" surface="); mAttrs.surfaceInsets.printShortString(pw);
                     pw.print(" outsets="); mOutsets.printShortString(pw);
-            pw.print(" cutout=" + mDisplayCutout.getDisplayCutout());
-                    pw.println();
             pw.print(prefix); pw.print("Lst insets: overscan=");
                     mLastOverscanInsets.printShortString(pw);
                     pw.print(" content="); mLastContentInsets.printShortString(pw);
@@ -3445,7 +3437,6 @@
                     pw.print(" stable="); mLastStableInsets.printShortString(pw);
                     pw.print(" physical="); mLastOutsets.printShortString(pw);
                     pw.print(" outset="); mLastOutsets.printShortString(pw);
-                    pw.print(" cutout=" + mLastDisplayCutout);
                     pw.println();
         }
         super.dump(pw, prefix, dumpAll);
@@ -3470,6 +3461,16 @@
             pw.print(prefix); pw.print("mLastFreezeDuration=");
                     TimeUtils.formatDuration(mLastFreezeDuration, pw); pw.println();
         }
+        if (mForceSeamlesslyRotate) {
+            pw.print(prefix); pw.print("forceSeamlesslyRotate: pending=");
+            if (mPendingForcedSeamlessRotate != null) {
+                mPendingForcedSeamlessRotate.dump(pw);
+            } else {
+                pw.print("null");
+            }
+            pw.print(" finishedFrameNumber="); pw.print(mFinishForcedSeamlessRotateFrameNumber);
+            pw.println();
+        }
         if (mHScale != 1 || mVScale != 1) {
             pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
                     pw.print(" mVScale="); pw.println(mVScale);
@@ -3609,16 +3610,16 @@
         // Set mFrame
         Gravity.apply(mAttrs.gravity, w, h, containingFrame,
                 (int) (x + mAttrs.horizontalMargin * pw),
-                (int) (y + mAttrs.verticalMargin * ph), mFrame);
+                (int) (y + mAttrs.verticalMargin * ph), mWindowFrames.mFrame);
 
         // Now make sure the window fits in the overall display frame.
         if (fitToDisplay) {
-            Gravity.applyDisplay(mAttrs.gravity, displayFrame, mFrame);
+            Gravity.applyDisplay(mAttrs.gravity, displayFrame, mWindowFrames.mFrame);
         }
 
         // We need to make sure we update the CompatFrame as it is used for
         // cropping decisions, etc, on systems where we lack a decor layer.
-        mCompatFrame.set(mFrame);
+        mCompatFrame.set(mWindowFrames.mFrame);
         if (mEnforceSizeCompat) {
             // See comparable block in computeFrameLw.
             mCompatFrame.scale(mInvGlobalScale);
@@ -3731,7 +3732,7 @@
     }
 
     float translateToWindowX(float x) {
-        float winX = x - mFrame.left;
+        float winX = x - mWindowFrames.mFrame.left;
         if (mEnforceSizeCompat) {
             winX *= mGlobalScale;
         }
@@ -3739,7 +3740,7 @@
     }
 
     float translateToWindowY(float y) {
-        float winY = y - mFrame.top;
+        float winY = y - mWindowFrames.mFrame.top;
         if (mEnforceSizeCompat) {
             winY *= mGlobalScale;
         }
@@ -3891,7 +3892,8 @@
         final boolean isAccessibilityOverlay =
                 windowInfo.type == WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
         if (TextUtils.isEmpty(windowInfo.title) && (isPanelWindow || isAccessibilityOverlay)) {
-            windowInfo.title = mAttrs.getTitle();
+            final CharSequence title = mAttrs.getTitle();
+            windowInfo.title = TextUtils.isEmpty(title) ? null : title;
         }
         windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor;
         windowInfo.focused = isFocused();
@@ -4303,7 +4305,7 @@
         // The decor frame is used to specify the region not covered by the system
         // decorations (nav bar, status bar). In case this is empty, for example with
         // FLAG_TRANSLUCENT_NAVIGATION, we don't need to do any cropping.
-        if (mDecorFrame.isEmpty()) {
+        if (mWindowFrames.mDecorFrame.isEmpty()) {
             return true;
         }
 
@@ -4348,12 +4350,12 @@
      * by system decorations.
      */
     private void calculateSystemDecorRect(Rect systemDecorRect) {
-        final Rect decorRect = mDecorFrame;
-        final int width = mFrame.width();
-        final int height = mFrame.height();
+        final Rect decorRect = mWindowFrames.mDecorFrame;
+        final int width = mWindowFrames.mFrame.width();
+        final int height = mWindowFrames.mFrame.height();
 
-        final int left = mFrame.left;
-        final int top = mFrame.top;
+        final int left = mWindowFrames.mFrame.left;
+        final int top = mWindowFrames.mFrame.top;
 
         // Initialize the decor rect to the entire frame.
         if (isDockedResizing()) {
@@ -4499,12 +4501,12 @@
         mLastVisibleInsets.set(mVisibleInsets);
         mLastStableInsets.set(mStableInsets);
         mLastOutsets.set(mOutsets);
-        mLastDisplayCutout = mDisplayCutout;
+        mWindowFrames.mLastDisplayCutout = mWindowFrames.mDisplayCutout;
     }
 
     void startAnimation(Animation anim) {
         final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
-        anim.initialize(mFrame.width(), mFrame.height(),
+        anim.initialize(mWindowFrames.mFrame.width(), mWindowFrames.mFrame.height(),
                 displayInfo.appWidth, displayInfo.appHeight);
         anim.restrictDuration(MAX_ANIMATION_DURATION);
         anim.scaleCurrentDuration(mService.getWindowAnimationScaleLocked());
@@ -4519,7 +4521,8 @@
         if (DEBUG_ANIM) Slog.v(TAG, "Setting move animation on " + this);
         final Point oldPosition = new Point();
         final Point newPosition = new Point();
-        transformFrameToSurfacePosition(mLastFrame.left, mLastFrame.top, oldPosition);
+        transformFrameToSurfacePosition(mWindowFrames.mLastFrame.left, mWindowFrames.mLastFrame.top,
+                oldPosition);
         transformFrameToSurfacePosition(left, top, newPosition);
         final AnimationAdapter adapter = new LocalAnimationAdapter(
                 new MoveAnimationSpec(oldPosition.x, oldPosition.y, newPosition.x, newPosition.y),
@@ -4554,8 +4557,8 @@
         final WindowContainer parent = getParent();
         if (isChildWindow()) {
             final WindowState parentWindow = getParentWindow();
-            x += parentWindow.mFrame.left - parentWindow.mAttrs.surfaceInsets.left;
-            y += parentWindow.mFrame.top - parentWindow.mAttrs.surfaceInsets.top;
+            x += parentWindow.mWindowFrames.mFrame.left - parentWindow.mAttrs.surfaceInsets.left;
+            y += parentWindow.mWindowFrames.mFrame.top - parentWindow.mAttrs.surfaceInsets.top;
         } else if (parent != null) {
             final Rect parentBounds = parent.getBounds();
             x += parentBounds.left;
@@ -4708,9 +4711,13 @@
             return;
         }
 
-        transformFrameToSurfacePosition(mFrame.left, mFrame.top, mSurfacePosition);
+        transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top,
+                mSurfacePosition);
 
-        if (!mSurfaceAnimator.hasLeash() && !mLastSurfacePosition.equals(mSurfacePosition)) {
+        // Freeze position while we're unrotated, so the surface remains at the position it was
+        // prior to the rotation.
+        if (!mSurfaceAnimator.hasLeash() && mPendingForcedSeamlessRotate == null &&
+                !mLastSurfacePosition.equals(mSurfacePosition)) {
             t.setPosition(mSurfaceControl, mSurfacePosition.x, mSurfacePosition.y);
             mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y);
             if (surfaceInsetsChanging() && mWinAnimator.hasSurface()) {
@@ -4734,8 +4741,8 @@
             // Since the parent was outset by its surface insets, we need to undo the outsetting
             // with insetting by the same amount.
             final WindowState parent = getParentWindow();
-            outPoint.offset(-parent.mFrame.left + parent.mAttrs.surfaceInsets.left,
-                    -parent.mFrame.top + parent.mAttrs.surfaceInsets.top);
+            outPoint.offset(-parent.mWindowFrames.mFrame.left + parent.mAttrs.surfaceInsets.left,
+                    -parent.mWindowFrames.mFrame.top + parent.mAttrs.surfaceInsets.top);
         } else if (parentWindowContainer != null) {
             final Rect parentBounds = parentWindowContainer.getBounds();
             outPoint.offset(-parentBounds.left, -parentBounds.top);
@@ -4865,7 +4872,9 @@
 
     @Override
     void seamlesslyRotate(Transaction t, int oldRotation, int newRotation) {
-        if (!isVisibleNow() || mIsWallpaper) {
+        // Invisible windows, the wallpaper, and force seamlessly rotated windows do not participate
+        // in the regular seamless rotation animation.
+        if (!isVisibleNow() || mIsWallpaper || mForceSeamlesslyRotate) {
             return;
         }
         final Matrix transform = mTmpMatrix;
@@ -4876,7 +4885,7 @@
         // we recompute the coordinates of mFrame in the new orientation, so the surface can be
         // properly placed.
         transformToRotation(oldRotation, newRotation, getDisplayInfo(), transform);
-        transformRect(transform, mFrame, null /* tmpRectF */);
+        transformRect(transform, mWindowFrames.mFrame, null /* tmpRectF */);
 
         updateSurfacePosition(t);
         mWinAnimator.seamlesslyRotate(t, oldRotation, newRotation);
@@ -4886,6 +4895,26 @@
         super.seamlesslyRotate(t, oldRotation, newRotation);
     }
 
+    public void getMaxVisibleBounds(Rect out) {
+        if (out.isEmpty()) {
+            out.set(mWindowFrames.mVisibleFrame);
+            return;
+        }
+
+        if (mWindowFrames.mVisibleFrame.left < out.left) {
+            out.left = mWindowFrames.mVisibleFrame.left;
+        }
+        if (mWindowFrames.mVisibleFrame.top < out.top) {
+            out.top = mWindowFrames.mVisibleFrame.top;
+        }
+        if (mWindowFrames.mVisibleFrame.right > out.right) {
+            out.right = mWindowFrames.mVisibleFrame.right;
+        }
+        if (mWindowFrames.mVisibleFrame.bottom > out.bottom) {
+            out.bottom = mWindowFrames.mVisibleFrame.bottom;
+        }
+    }
+
     private final class MoveAnimationSpec implements AnimationSpec {
 
         private final long mDuration;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 14e0e13..7966d5b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -540,13 +540,13 @@
         }
 
         if (WindowManagerService.localLOGV) Slog.v(TAG, "Got surface: " + mSurfaceController
-                + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top
+                + ", set left=" + w.getFrameLw().left + " top=" + w.getFrameLw().top
                 + ", animLayer=" + mAnimLayer);
 
         if (SHOW_LIGHT_TRANSACTIONS) {
             Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
             WindowManagerService.logSurface(w, "CREATE pos=("
-                    + w.mFrame.left + "," + w.mFrame.top + ") ("
+                    + w.getFrameLw().left + "," + w.getFrameLw().top + ") ("
                     + width + "x" + height + "), layer=" + mAnimLayer + " HIDE", false);
         }
 
@@ -686,12 +686,16 @@
         final int displayId = mWin.getDisplayId();
         final ScreenRotationAnimation screenRotationAnimation =
                 mAnimator.getScreenRotationAnimationLocked(displayId);
-        final boolean screenAnimation =
-                screenRotationAnimation != null && screenRotationAnimation.isAnimating();
+        // TODO(b/111504081): Consolidate seamless rotation logic.
+        final boolean windowParticipatesInScreenRotationAnimation =
+                !mWin.mForceSeamlesslyRotate;
+        final boolean screenAnimation = screenRotationAnimation != null
+                && screenRotationAnimation.isAnimating()
+                && windowParticipatesInScreenRotationAnimation;
 
         if (screenAnimation) {
             // cache often used attributes locally
-            final Rect frame = mWin.mFrame;
+            final Rect frame = mWin.getFrameLw();
             final float tmpFloats[] = mService.mTmpFloats;
             final Matrix tmpMatrix = mWin.mTmpMatrix;
 
@@ -799,6 +803,13 @@
             return false;
         }
 
+        // During forced seamless rotation, the surface bounds get updated with the crop in the
+        // new rotation, which is not compatible with showing the surface in the old rotation.
+        // To work around that we disable cropping for such windows, as it is not necessary anyways.
+        if (w.mForceSeamlesslyRotate) {
+            return false;
+        }
+
         // If we're animating, the wallpaper should only
         // be updated at the end of the animation.
         if (w.mAttrs.type == TYPE_WALLPAPER) {
@@ -811,7 +822,7 @@
         w.calculatePolicyCrop(mSystemDecorRect);
 
         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
-                + w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
+                + w.getDecorFrame() + " mSystemDecorRect=" + mSystemDecorRect);
 
         final Task task = w.getTask();
         final boolean fullscreen = w.fillsDisplay() || (task != null && task.isFullscreen());
@@ -931,9 +942,9 @@
 
             // Make sure that what we're animating to and from is actually the right size in case
             // the window cannot take up the full screen.
-            mTmpStackBounds.intersectUnchecked(w.mParentFrame);
-            mTmpSourceBounds.intersectUnchecked(w.mParentFrame);
-            mTmpAnimatingBounds.intersectUnchecked(w.mParentFrame);
+            mTmpStackBounds.intersectUnchecked(w.getParentFrame());
+            mTmpSourceBounds.intersectUnchecked(w.getParentFrame());
+            mTmpAnimatingBounds.intersectUnchecked(w.getParentFrame());
 
             if (!mTmpSourceBounds.isEmpty()) {
                 // Get the final target stack bounds, if we are not animating, this is just the
@@ -1498,14 +1509,16 @@
         }
     }
 
+    // TODO(b/111504081): Consolidate seamless rotation logic.
+    @Deprecated
     void seamlesslyRotate(SurfaceControl.Transaction t, int oldRotation, int newRotation) {
         final WindowState w = mWin;
 
         // We rotated the screen, but have not received a new buffer with the correct size yet. In
         // the mean time, we rotate the buffer we have to the new orientation.
         final Matrix transform = mService.mTmpTransform;
-        transformToRotation(oldRotation, newRotation, w.mFrame.width(), w.mFrame.height(),
-                transform);
+        transformToRotation(oldRotation, newRotation, w.getFrameLw().width(),
+                w.getFrameLw().height(), transform);
         transform.getValues(mService.mTmpFloats);
 
         float DsDx = mService.mTmpFloats[Matrix.MSCALE_X];
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index aced8e4..d6f9ac3 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
@@ -569,7 +570,7 @@
             // animation after the old one finally finishes. It's better to defer the
             // app transition.
             if (screenRotationAnimation != null && screenRotationAnimation.isAnimating() &&
-                    mService.rotationNeedsUpdateLocked()) {
+                    mService.getDefaultDisplayContentLocked().rotationNeedsUpdate()) {
                 if (DEBUG_APP_TRANSITIONS) {
                     Slog.v(TAG, "Delaying app transition for screen rotation animation to finish");
                 }
@@ -636,10 +637,15 @@
             return transit;
         }
 
-        // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
         final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
-        final WindowState oldWallpaper = mWallpaperControllerLocked.isWallpaperTargetAnimating()
-                ? null : wallpaperTarget;
+        final boolean showWallpaper = wallpaperTarget != null
+                && (wallpaperTarget.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
+        // If wallpaper is animating or wallpaperTarget doesn't have SHOW_WALLPAPER flag set,
+        // don't consider upgrading to wallpaper transition.
+        final WindowState oldWallpaper =
+                (mWallpaperControllerLocked.isWallpaperTargetAnimating() || !showWallpaper)
+                        ? null
+                        : wallpaperTarget;
         final ArraySet<AppWindowToken> openingApps = mService.mOpeningApps;
         final ArraySet<AppWindowToken> closingApps = mService.mClosingApps;
         final AppWindowToken topOpeningApp = getTopApp(mService.mOpeningApps,
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index b97460a..e411c0a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -270,12 +270,6 @@
         dc.reParentWindowToken(this);
         mDisplayContent = dc;
 
-        // The rounded corner overlay should not be rotated. We ensure that by moving it outside
-        // the windowing layer.
-        if (mRoundedCornerOverlay) {
-            mDisplayContent.reparentToOverlay(mPendingTransaction, mSurfaceControl);
-        }
-
         // TODO(b/36740756): One day this should perhaps be hooked
         // up with goodToGo, so we don't move a window
         // to another display before the window behind
diff --git a/services/core/java/com/android/server/wm/utils/InsetUtils.java b/services/core/java/com/android/server/wm/utils/InsetUtils.java
index b4a998a..f5cc0d5 100644
--- a/services/core/java/com/android/server/wm/utils/InsetUtils.java
+++ b/services/core/java/com/android/server/wm/utils/InsetUtils.java
@@ -16,7 +16,11 @@
 
 package com.android.server.wm.utils;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Rect;
+import android.view.Surface;
+
 
 /**
  * Utility methods to handle insets represented as rects.
@@ -27,6 +31,32 @@
     }
 
     /**
+     * Transforms insets given in one rotation into insets in a different rotation.
+     *
+     * @param inOutInsets the insets to transform, is set to the transformed insets
+     * @param rotationDelta the delta between the new and old rotation.
+     *                      Must be one of Surface.ROTATION_0/90/180/270.
+     */
+    public static void rotateInsets(Rect inOutInsets, int rotationDelta) {
+        final Rect r = inOutInsets;
+        switch (rotationDelta) {
+            case Surface.ROTATION_0:
+                return;
+            case Surface.ROTATION_90:
+                r.set(r.top, r.right, r.bottom, r.left);
+                break;
+            case Surface.ROTATION_180:
+                r.set(r.right, r.bottom, r.left, r.top);
+                break;
+            case Surface.ROTATION_270:
+                r.set(r.bottom, r.left, r.top, r.right);
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown rotation: " + rotationDelta);
+        }
+    }
+
+    /**
      * Adds {@code insetsToAdd} to {@code inOutInsets}.
      */
     public static void addInsets(Rect inOutInsets, Rect insetsToAdd) {
@@ -35,4 +65,30 @@
         inOutInsets.right += insetsToAdd.right;
         inOutInsets.bottom += insetsToAdd.bottom;
     }
+
+    /**
+     * Calculates the insets from the {@code outerFrame} to the {@code innerFrame}.
+     *
+     * Note that if a side of the outer frame is not actually on the outside, the inset for that
+     * side will be clamped to zero.
+     *
+     * @param outerFrame the reference frame from which the insets are calculated
+     * @param innerFrame the inset frame, to which the insets are calculated,
+     *                   or null to clear the insets.
+     * @param outInsets is set to the result of the inset calculation.
+     */
+    public static void insetsBetweenFrames(@NonNull Rect outerFrame, @Nullable Rect innerFrame,
+            @NonNull Rect outInsets) {
+        if (innerFrame == null) {
+            outInsets.setEmpty();
+            return;
+        }
+        final int w = outerFrame.width();
+        final int h = outerFrame.height();
+        outInsets.set(
+                Math.min(w, Math.max(0, innerFrame.left - outerFrame.left)),
+                Math.min(h, Math.max(0, innerFrame.top - outerFrame.top)),
+                Math.min(w, Math.max(0, outerFrame.right - innerFrame.right)),
+                Math.min(h, Math.max(0, outerFrame.bottom - innerFrame.bottom)));
+    }
 }
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 89efe12..becde73 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -2,6 +2,8 @@
     name: "libservices.core",
     defaults: ["libservices.core-libs"],
 
+    cpp_std: "c++17",
+
     cflags: [
         "-Wall",
         "-Werror",
@@ -57,17 +59,6 @@
         "frameworks/native/services",
         "system/gatekeeper/include",
     ],
-
-    product_variables: {
-        arc: {
-            cflags: [
-                "-DUSE_ARC",
-            ],
-            srcs: [
-                "com_android_server_ArcVideoService.cpp",
-            ],
-        }
-    }
 }
 
 cc_defaults {
@@ -142,7 +133,9 @@
             shared_libs: [
                 "libarcbridge",
                 "libarcbridgeservice",
-                "libarcvideobridge",
+                "libarctimer",
+                "libbase",
+                "libcap",
                 "libchrome",
                 "libmojo",
             ],
diff --git a/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp b/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp
index 81d46f3..777d344 100644
--- a/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp
+++ b/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp
@@ -106,7 +106,7 @@
         mQueueCond.notify_one();
     }
 
-    if (mThread.get_id() == std::thread::id()) {
+    if (mThread.get_id() == std::this_thread::get_id()) {
         // you can't self-join a thread, but it's ok when calling from our sub-task
         ALOGD("About to stop native callback thread %p", this);
         mThread.detach();
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index 921eed9..e79612f 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -194,7 +194,9 @@
         uint32_t alarm_idx = events[i].data.u32;
         uint64_t unused;
         ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
-        if (err < 0) {
+        // Worth evaluating even if read fails with EAGAIN, since epoll_wait
+        // returned. (see b/78560047#comment34)
+        if (err < 0 && errno != EAGAIN) {
             if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
                 result |= ANDROID_ALARM_TIME_CHANGE_MASK;
             } else {
@@ -348,7 +350,7 @@
     }
 
     for (size_t i = 0; i < fds.size(); i++) {
-        fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
+        fds[i] = timerfd_create(android_alarm_to_clockid[i], TFD_NONBLOCK);
         if (fds[i] < 0) {
             log_timerfd_create_error(android_alarm_to_clockid[i]);
             close(epollfd);
diff --git a/services/core/jni/com_android_server_ArcVideoService.cpp b/services/core/jni/com_android_server_ArcVideoService.cpp
deleted file mode 100644
index f93cd90..0000000
--- a/services/core/jni/com_android_server_ArcVideoService.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "ArcVideoService"
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <media/arcvideobridge/IArcVideoBridge.h>
-#include <utils/Log.h>
-
-#include <base/bind.h>
-#include <base/bind_helpers.h>
-#include <mojo/edk/embedder/embedder.h>
-#include <mojo/public/cpp/bindings/binding.h>
-
-#include <arc/ArcBridgeSupport.h>
-#include <arc/ArcService.h>
-#include <arc/Future.h>
-#include <arc/IArcBridgeService.h>
-#include <arc/MojoProcessSupport.h>
-#include <components/arc/common/video.mojom.h>
-
-namespace {
-
-// [MinVersion] of OnVideoInstanceReady method in arc_bridge.mojom.
-constexpr int kMinimumArcBridgeHostVersion = 6;
-
-void onCaptureResult(arc::Future<arc::MojoBootstrapResult>* future, uint32_t version,
-                     mojo::ScopedHandle handle, const std::string& token) {
-    mojo::edk::ScopedPlatformHandle scoped_platform_handle;
-    MojoResult result =
-            mojo::edk::PassWrappedPlatformHandle(handle.release().value(), &scoped_platform_handle);
-    if (result != MOJO_RESULT_OK) {
-        ALOGE("Received invalid file descriptor.");
-        future->set(arc::MojoBootstrapResult());
-        return;
-    }
-
-    base::ScopedFD fd(scoped_platform_handle.release().handle);
-    future->set(arc::MojoBootstrapResult(std::move(fd), token, version));
-}
-
-}  // namespace
-
-namespace arc {
-
-class VideoService : public mojom::VideoInstance,
-                     public ArcService,
-                     public android::BnArcVideoBridge {
-public:
-    explicit VideoService(MojoProcessSupport* mojoProcessSupport)
-          : mMojoProcessSupport(mojoProcessSupport), mBinding(this) {
-        mMojoProcessSupport->arc_bridge_support().requestArcBridgeProxyAsync(
-                this, kMinimumArcBridgeHostVersion);
-    }
-
-    ~VideoService() override { mMojoProcessSupport->disconnect(&mBinding, &mHostPtr); }
-
-    // VideoInstance overrides:
-    void InitDeprecated(mojom::VideoHostPtr hostPtr) override {
-        Init(std::move(hostPtr), base::Bind(&base::DoNothing));
-    }
-
-    void Init(mojom::VideoHostPtr hostPtr, const InitCallback& callback) override {
-        ALOGV("Init");
-        mHostPtr = std::move(hostPtr);
-        // A method must be called while we are still in a Mojo thread so the
-        // proxy can perform lazy initialization and be able to be called from
-        // non-Mojo threads later.
-        // This also caches the version number so it can be obtained by calling
-        // .version().
-        mHostPtr.QueryVersion(base::Bind(
-            [](const InitCallback& callback, uint32_t version) {
-                ALOGI("VideoService ready (version=%d)", version);
-                callback.Run();
-            },
-            callback));
-        ALOGV("Init done");
-    }
-
-    // ArcService overrides:
-    void ready(mojom::ArcBridgeHostPtr* bridgeHost) override {
-        (*bridgeHost)->OnVideoInstanceReady(mBinding.CreateInterfacePtrAndBind());
-    }
-
-    void versionMismatch(uint32_t version) override {
-        ALOGE("ArcBridgeHost version %d, does not support video (version %d)\n", version,
-              kMinimumArcBridgeHostVersion);
-    }
-
-    // BnArcVideoBridge overrides:
-    MojoBootstrapResult bootstrapVideoAcceleratorFactory() override {
-        ALOGV("VideoService::bootstrapVideoAcceleratorFactory");
-
-        Future<MojoBootstrapResult> future;
-        mMojoProcessSupport->mojo_thread().getTaskRunner()->PostTask(
-                FROM_HERE, base::Bind(&VideoService::bootstrapVideoAcceleratorFactoryOnMojoThread,
-                                      base::Unretained(this), &future));
-        return future.get();
-    }
-
-    int32_t hostVersion() override {
-        ALOGV("VideoService::hostVersion");
-        return mHostPtr.version();
-    }
-
-private:
-    void bootstrapVideoAcceleratorFactoryOnMojoThread(Future<MojoBootstrapResult>* future) {
-        if (!mHostPtr) {
-            ALOGE("mHostPtr is not ready yet");
-            future->set(MojoBootstrapResult());
-            return;
-        }
-        mHostPtr->OnBootstrapVideoAcceleratorFactory(
-                base::Bind(&onCaptureResult, base::Unretained(future), mHostPtr.version()));
-    }
-
-    // Outlives VideoService.
-    MojoProcessSupport* const mMojoProcessSupport;
-    mojo::Binding<mojom::VideoInstance> mBinding;
-    mojom::VideoHostPtr mHostPtr;
-};
-
-}  // namespace arc
-
-namespace android {
-
-int register_android_server_ArcVideoService() {
-    defaultServiceManager()->addService(
-            String16("android.os.IArcVideoBridge"),
-            new arc::VideoService(arc::MojoProcessSupport::getLeakyInstance()));
-    return 0;
-}
-
-}  // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 0ebef37..bb6e684 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -54,9 +54,6 @@
 int register_android_server_GraphicsStatsService(JNIEnv* env);
 int register_android_hardware_display_DisplayViewport(JNIEnv* env);
 int register_android_server_net_NetworkStatsService(JNIEnv* env);
-#ifdef USE_ARC
-int register_android_server_ArcVideoService();
-#endif
 };
 
 using namespace android;
@@ -104,8 +101,5 @@
     register_android_server_GraphicsStatsService(env);
     register_android_hardware_display_DisplayViewport(env);
     register_android_server_net_NetworkStatsService(env);
-#ifdef USE_ARC
-    register_android_server_ArcVideoService();
-#endif
     return JNI_VERSION_1_4;
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9ef806e..664a837 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -233,6 +233,7 @@
 import com.android.server.pm.UserRestrictionsUtils;
 import com.android.server.storage.DeviceStorageMonitorInternal;
 
+import com.android.server.uri.UriGrantsManagerInternal;
 import com.google.android.collect.Sets;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -4578,10 +4579,12 @@
         enforceFullCrossUsersPermission(userHandle);
         synchronized (getLockObject()) {
             if (!isCallerWithSystemUid()) {
-                // This API can only be called by an active device admin,
-                // so try to retrieve it to check that the caller is one.
-                getActiveAdminForCallerLocked(
-                        null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent);
+                // This API can be called by an active device admin or by keyguard code.
+                if (mContext.checkCallingPermission(permission.ACCESS_KEYGUARD_SECURE_STORAGE)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    getActiveAdminForCallerLocked(
+                            null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent);
+                }
             }
 
             DevicePolicyData policy = getUserDataUnchecked(getCredentialOwner(userHandle, parent));
@@ -5465,7 +5468,14 @@
                 if (generationResult != KeyChain.KEY_GEN_SUCCESS) {
                     Log.e(LOG_TAG, String.format(
                             "KeyChain failed to generate a keypair, error %d.", generationResult));
-                    return false;
+                    switch (generationResult) {
+                        case KeyChain.KEY_GEN_STRONGBOX_UNAVAILABLE:
+                            throw new ServiceSpecificException(
+                                    DevicePolicyManager.KEY_GEN_STRONGBOX_UNAVAILABLE,
+                                    String.format("KeyChain error: %d", generationResult));
+                        default:
+                            return false;
+                    }
                 }
 
                 // Set a grant for the caller here so that when the client calls
@@ -6966,7 +6976,7 @@
                 intent.putExtra(DeviceAdminReceiver.EXTRA_BUGREPORT_HASH, bugreportHash);
                 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
-                LocalServices.getService(ActivityManagerInternal.class)
+                LocalServices.getService(UriGrantsManagerInternal.class)
                         .grantUriPermissionFromIntent(Process.SHELL_UID,
                                 mOwners.getDeviceOwnerComponent().getPackageName(),
                                 intent, mOwners.getDeviceOwnerUserId());
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1f1b3f8..2f6fca4 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -28,6 +28,8 @@
 import android.content.res.Configuration;
 import android.content.res.Resources.Theme;
 import android.database.sqlite.SQLiteCompatibilityWalFlags;
+import android.database.sqlite.SQLiteGlobal;
+import android.hardware.display.DisplayManagerInternal;
 import android.os.BaseBundle;
 import android.os.Binder;
 import android.os.Build;
@@ -118,6 +120,7 @@
 import com.android.server.tv.TvInputManagerService;
 import com.android.server.tv.TvRemoteService;
 import com.android.server.twilight.TwilightService;
+import com.android.server.uri.UriGrantsManagerService;
 import com.android.server.usage.UsageStatsService;
 import com.android.server.vr.VrManagerService;
 import com.android.server.webkit.WebViewUpdateService;
@@ -235,6 +238,8 @@
             "com.android.server.timedetector.TimeDetectorService$Lifecycle";
     private static final String TIME_ZONE_DETECTOR_SERVICE_CLASS =
             "com.android.server.timezonedetector.TimeZoneDetectorService$Lifecycle";
+    private static final String ACCESSIBILITY_MANAGER_SERVICE_CLASS =
+            "com.android.server.accessibility.AccessibilityManagerService$Lifecycle";
 
     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
 
@@ -352,6 +357,10 @@
             Binder.setWarnOnBlocking(true);
             // The system server should always load safe labels
             PackageItemInfo.setForceSafeLabels(true);
+
+            // Default to FULL within the system server.
+            SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;
+
             // Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized
             SQLiteCompatibilityWalFlags.init(null);
 
@@ -560,6 +569,11 @@
         mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
         traceEnd();
 
+        // Uri Grants Manager.
+        traceBeginAndSlog("UriGrantsManagerService");
+        mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);
+        traceEnd();
+
         // Activity manager runs the show.
         traceBeginAndSlog("StartActivityManager");
         // TODO: Might need to move after migration to WM.
@@ -681,9 +695,17 @@
 
         // Manages Overlay packages
         traceBeginAndSlog("StartOverlayManagerService");
-        mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
+        OverlayManagerService overlayManagerService = new OverlayManagerService(
+                mSystemContext, installer);
+        mSystemServiceManager.startService(overlayManagerService);
         traceEnd();
 
+        if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) {
+            // DisplayManager needs the overlay immediately.
+            overlayManagerService.updateSystemUiContext();
+            LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged();
+        }
+
         // The sensor service needs access to package manager service, app ops
         // service, and permissions service, therefore we start it after them.
         // Start sensor service in a separate thread. Completion should be checked
@@ -722,7 +744,7 @@
 
         // Tracks cpu time spent in binder calls
         traceBeginAndSlog("StartBinderCallsStatsService");
-        BinderCallsStatsService.start();
+        mSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);
         traceEnd();
     }
 
@@ -901,7 +923,7 @@
             }
 
             traceBeginAndSlog("StartInputManager");
-            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
+            inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
             inputManager.start();
             traceEnd();
 
@@ -957,8 +979,7 @@
 
             traceBeginAndSlog("StartAccessibilityManagerService");
             try {
-                ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,
-                        new AccessibilityManagerService(context));
+                mSystemServiceManager.startService(ACCESSIBILITY_MANAGER_SERVICE_CLASS);
             } catch (Throwable e) {
                 reportWtf("starting Accessibility Manager", e);
             }
@@ -1551,13 +1572,15 @@
             }
             traceEnd();
 
-            traceBeginAndSlog("StartPruneInstantAppsJobService");
-            try {
-                PruneInstantAppsJobService.schedule(context);
-            } catch (Throwable e) {
-                reportWtf("StartPruneInstantAppsJobService", e);
+            if (!isWatch) {
+                traceBeginAndSlog("StartPruneInstantAppsJobService");
+                try {
+                    PruneInstantAppsJobService.schedule(context);
+                } catch (Throwable e) {
+                    reportWtf("StartPruneInstantAppsJobService", e);
+                }
+                traceEnd();
             }
-            traceEnd();
 
             // LauncherAppsService uses ShortcutService.
             traceBeginAndSlog("StartShortcutServiceLifecycle");
diff --git a/services/net/OWNERS b/services/net/OWNERS
index ce50558..7311eee 100644
--- a/services/net/OWNERS
+++ b/services/net/OWNERS
@@ -1,6 +1,8 @@
 set noparent
 
+codewiz@google.com
 ek@google.com
 jchalard@google.com
 lorenzo@google.com
+reminv@google.com
 satk@google.com
diff --git a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
index 91e6bd6..11f2b61 100644
--- a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
@@ -24,10 +24,17 @@
  */
 class DhcpDiscoverPacket extends DhcpPacket {
     /**
+     * The IP address of the client which sent this packet.
+     */
+    final Inet4Address mSrcIp;
+
+    /**
      * Generates a DISCOVER packet with the specified parameters.
      */
-    DhcpDiscoverPacket(int transId, short secs, byte[] clientMac, boolean broadcast) {
-        super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
+    DhcpDiscoverPacket(int transId, short secs, Inet4Address relayIp, byte[] clientMac,
+            boolean broadcast, Inet4Address srcIp) {
+        super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast);
+        mSrcIp = srcIp;
     }
 
     public String toString() {
@@ -41,8 +48,8 @@
      */
     public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
         ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
-        fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp,
-                srcUdp, result, DHCP_BOOTREQUEST, mBroadcast);
+        fillInPacket(encap, INADDR_BROADCAST, mSrcIp, destUdp, srcUdp, result, DHCP_BOOTREQUEST,
+                mBroadcast);
         result.flip();
         return result;
     }
diff --git a/services/net/java/android/net/dhcp/DhcpLease.java b/services/net/java/android/net/dhcp/DhcpLease.java
new file mode 100644
index 0000000..d2a15b3
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpLease.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.MacAddress;
+import android.os.SystemClock;
+import android.text.TextUtils;
+
+import com.android.internal.util.HexDump;
+
+import java.net.Inet4Address;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * An IPv4 address assignment done through DHCPv4.
+ * @hide
+ */
+public class DhcpLease {
+    public static final long EXPIRATION_NEVER = Long.MAX_VALUE;
+    public static final String HOSTNAME_NONE = null;
+
+    @Nullable
+    private final byte[] mClientId;
+    @NonNull
+    private final MacAddress mHwAddr;
+    @NonNull
+    private final Inet4Address mNetAddr;
+    /**
+     * Expiration time for the lease, to compare with {@link SystemClock#elapsedRealtime()}.
+     */
+    private final long mExpTime;
+    @Nullable
+    private final String mHostname;
+
+    public DhcpLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address netAddr, long expTime, @Nullable String hostname) {
+        mClientId = (clientId == null ? null : Arrays.copyOf(clientId, clientId.length));
+        mHwAddr = hwAddr;
+        mNetAddr = netAddr;
+        mExpTime = expTime;
+        mHostname = hostname;
+    }
+
+    @Nullable
+    public byte[] getClientId() {
+        if (mClientId == null) {
+            return null;
+        }
+        return Arrays.copyOf(mClientId, mClientId.length);
+    }
+
+    @NonNull
+    public MacAddress getHwAddr() {
+        return mHwAddr;
+    }
+
+    @Nullable
+    public String getHostname() {
+        return mHostname;
+    }
+
+    @NonNull
+    public Inet4Address getNetAddr() {
+        return mNetAddr;
+    }
+
+    public long getExpTime() {
+        return mExpTime;
+    }
+
+    /**
+     * Push back the expiration time of this lease. If the provided time is sooner than the original
+     * expiration time, the lease time will not be updated.
+     *
+     * <p>The lease hostname is updated with the provided one if set.
+     * @return A {@link DhcpLease} with expiration time set to max(expTime, currentExpTime)
+     */
+    public DhcpLease renewedLease(long expTime, @Nullable String hostname) {
+        return new DhcpLease(mClientId, mHwAddr, mNetAddr, Math.max(expTime, mExpTime),
+                (hostname == null ? mHostname : hostname));
+    }
+
+    public boolean matchesClient(@Nullable byte[] clientId, @NonNull MacAddress hwAddr) {
+        if (mClientId != null) {
+            return Arrays.equals(mClientId, clientId);
+        } else {
+            return clientId == null && mHwAddr.equals(hwAddr);
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof DhcpLease)) {
+            return false;
+        }
+        final DhcpLease other = (DhcpLease)obj;
+        return Arrays.equals(mClientId, other.mClientId)
+                && mHwAddr.equals(other.mHwAddr)
+                && mNetAddr.equals(other.mNetAddr)
+                && mExpTime == other.mExpTime
+                && TextUtils.equals(mHostname, other.mHostname);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mClientId, mHwAddr, mNetAddr, mHostname, mExpTime);
+    }
+
+    static String clientIdToString(byte[] bytes) {
+        if (bytes == null) {
+            return "null";
+        }
+        return HexDump.toHexString(bytes);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("clientId: %s, hwAddr: %s, netAddr: %s, expTime: %d, hostname: %s",
+                clientIdToString(mClientId), mHwAddr.toString(), mNetAddr, mExpTime, mHostname);
+    }
+}
diff --git a/services/net/java/android/net/dhcp/DhcpLeaseRepository.java b/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
new file mode 100644
index 0000000..7e57c9f4
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
@@ -0,0 +1,538 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import static android.net.NetworkUtils.inet4AddressToIntHTH;
+import static android.net.NetworkUtils.intToInet4AddressHTH;
+import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTH;
+import static android.net.dhcp.DhcpLease.EXPIRATION_NEVER;
+import static android.net.util.NetworkConstants.IPV4_ADDR_BITS;
+
+import static java.lang.Math.min;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.IpPrefix;
+import android.net.MacAddress;
+import android.net.util.SharedLog;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+
+import java.net.Inet4Address;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Function;
+
+/**
+ * A repository managing IPv4 address assignments through DHCPv4.
+ *
+ * <p>This class is not thread-safe. All public methods should be called on a common thread or
+ * use some synchronization mechanism.
+ *
+ * <p>Methods are optimized for a small number of allocated leases, assuming that most of the time
+ * only 2~10 addresses will be allocated, which is the common case. Managing a large number of
+ * addresses is supported but will be slower: some operations have complexity in O(num_leases).
+ * @hide
+ */
+class DhcpLeaseRepository {
+    public static final byte[] CLIENTID_UNSPEC = null;
+    public static final Inet4Address INETADDR_UNSPEC = null;
+
+    @NonNull
+    private final SharedLog mLog;
+    @NonNull
+    private final Clock mClock;
+
+    @NonNull
+    private IpPrefix mPrefix;
+    @NonNull
+    private Set<Inet4Address> mReservedAddrs;
+    private int mSubnetAddr;
+    private int mSubnetMask;
+    private int mNumAddresses;
+    private long mLeaseTimeMs;
+
+    public static class Clock {
+        /**
+         * @see SystemClock#elapsedRealtime()
+         */
+        public long elapsedRealtime() {
+            return SystemClock.elapsedRealtime();
+        }
+    }
+
+    /**
+     * Next timestamp when committed or declined leases should be checked for expired ones. This
+     * will always be lower than or equal to the time for the first lease to expire: it's OK not to
+     * update this when removing entries, but it must always be updated when adding/updating.
+     */
+    private long mNextExpirationCheck = EXPIRATION_NEVER;
+
+    static class DhcpLeaseException extends Exception {
+        DhcpLeaseException(String message) {
+            super(message);
+        }
+    }
+
+    static class OutOfAddressesException extends DhcpLeaseException {
+        OutOfAddressesException(String message) {
+            super(message);
+        }
+    }
+
+    static class InvalidAddressException extends DhcpLeaseException {
+        InvalidAddressException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * Leases by IP address
+     */
+    private final ArrayMap<Inet4Address, DhcpLease> mCommittedLeases = new ArrayMap<>();
+
+    /**
+     * Map address -> expiration timestamp in ms. Addresses are guaranteed to be valid as defined
+     * by {@link #isValidAddress(Inet4Address)}, but are not necessarily otherwise available for
+     * assignment.
+     */
+    private final LinkedHashMap<Inet4Address, Long> mDeclinedAddrs = new LinkedHashMap<>();
+
+    public DhcpLeaseRepository(@NonNull IpPrefix prefix, @NonNull Set<Inet4Address> reservedAddrs,
+            long leaseTimeMs, @NonNull SharedLog log, @NonNull Clock clock) {
+        updateParams(prefix, reservedAddrs, leaseTimeMs);
+        mLog = log;
+        mClock = clock;
+    }
+
+    public void updateParams(@NonNull IpPrefix prefix, @NonNull Set<Inet4Address> reservedAddrs,
+            long leaseTimeMs) {
+        mPrefix = prefix;
+        mReservedAddrs = Collections.unmodifiableSet(new HashSet<>(reservedAddrs));
+        mSubnetMask = prefixLengthToV4NetmaskIntHTH(prefix.getPrefixLength());
+        mSubnetAddr = inet4AddressToIntHTH((Inet4Address) prefix.getAddress()) & mSubnetMask;
+        mNumAddresses = 1 << (IPV4_ADDR_BITS - prefix.getPrefixLength());
+        mLeaseTimeMs = leaseTimeMs;
+
+        cleanMap(mCommittedLeases);
+        cleanMap(mDeclinedAddrs);
+    }
+
+    /**
+     * From a map keyed by {@link Inet4Address}, remove entries where the key is invalid (as
+     * specified by {@link #isValidAddress(Inet4Address)}), or is a reserved address.
+     */
+    private <T> void cleanMap(Map<Inet4Address, T> map) {
+        final Iterator<Entry<Inet4Address, T>> it = map.entrySet().iterator();
+        while (it.hasNext()) {
+            final Inet4Address addr = it.next().getKey();
+            if (!isValidAddress(addr) || mReservedAddrs.contains(addr)) {
+                it.remove();
+            }
+        }
+    }
+
+    /**
+     * Get a DHCP offer, to reply to a DHCPDISCOVER. Follows RFC2131 #4.3.1.
+     *
+     * @param clientId Client identifier option if specified, or {@link #CLIENTID_UNSPEC}
+     * @param relayAddr Internet address of the relay (giaddr), can be {@link Inet4Address#ANY}
+     * @param reqAddr Requested address by the client (option 50), or {@link #INETADDR_UNSPEC}
+     * @param hostname Client-provided hostname, or {@link DhcpLease#HOSTNAME_NONE}
+     * @throws OutOfAddressesException The server does not have any available address
+     * @throws InvalidAddressException The lease was requested from an unsupported subnet
+     */
+    @NonNull
+    public DhcpLease getOffer(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address relayAddr,
+            @Nullable Inet4Address reqAddr, @Nullable String hostname)
+            throws OutOfAddressesException, InvalidAddressException {
+        final long currentTime = mClock.elapsedRealtime();
+        final long expTime = currentTime + mLeaseTimeMs;
+
+        removeExpiredLeases(currentTime);
+
+        // As per #4.3.1, addresses are assigned based on the relay address if present. This
+        // implementation only assigns addresses if the relayAddr is inside our configured subnet.
+        // This also applies when the client requested a specific address for consistency between
+        // requests, and with older behavior.
+        if (isIpAddrOutsidePrefix(mPrefix, relayAddr)) {
+            throw new InvalidAddressException("Lease requested by relay from outside of subnet");
+        }
+
+        final DhcpLease currentLease = findByClient(clientId, hwAddr);
+        final DhcpLease newLease;
+        if (currentLease != null) {
+            newLease = currentLease.renewedLease(expTime, hostname);
+            mLog.log("Offering extended lease " + newLease);
+            // Do not update lease time in the map: the offer is not committed yet.
+        } else if (reqAddr != null && isValidAddress(reqAddr) && isAvailable(reqAddr)) {
+            newLease = new DhcpLease(clientId, hwAddr, reqAddr, expTime, hostname);
+            mLog.log("Offering requested lease " + newLease);
+        } else {
+            newLease = makeNewOffer(clientId, hwAddr, expTime, hostname);
+            mLog.log("Offering new generated lease " + newLease);
+        }
+        return newLease;
+    }
+
+    private static boolean isIpAddrOutsidePrefix(IpPrefix prefix, Inet4Address addr) {
+        return addr != null && !addr.equals(Inet4Address.ANY) && !prefix.contains(addr);
+    }
+
+    @Nullable
+    private DhcpLease findByClient(@Nullable byte[] clientId, @NonNull MacAddress hwAddr) {
+        for (DhcpLease lease : mCommittedLeases.values()) {
+            if (lease.matchesClient(clientId, hwAddr)) {
+                return lease;
+            }
+        }
+
+        // Note this differs from dnsmasq behavior, which would match by hwAddr if clientId was
+        // given but no lease keyed on clientId matched. This would prevent one interface from
+        // obtaining multiple leases with different clientId.
+        return null;
+    }
+
+    /**
+     * Make a lease conformant to a client DHCPREQUEST or renew the client's existing lease,
+     * commit it to the repository and return it.
+     *
+     * <p>This method always succeeds and commits the lease if it does not throw, and has no side
+     * effects if it throws.
+     *
+     * @param clientId Client identifier option if specified, or {@link #CLIENTID_UNSPEC}
+     * @param reqAddr Requested address by the client (option 50), or {@link #INETADDR_UNSPEC}
+     * @param sidSet Whether the server identifier was set in the request
+     * @return The newly created or renewed lease
+     * @throws InvalidAddressException The client provided an address that conflicts with its
+     *                                 current configuration, or other committed/reserved leases.
+     */
+    @NonNull
+    public DhcpLease requestLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address clientAddr, @Nullable Inet4Address reqAddr, boolean sidSet,
+            @Nullable String hostname) throws InvalidAddressException {
+        final long currentTime = mClock.elapsedRealtime();
+        removeExpiredLeases(currentTime);
+        final DhcpLease assignedLease = findByClient(clientId, hwAddr);
+
+        final Inet4Address leaseAddr = reqAddr != null ? reqAddr : clientAddr;
+        if (assignedLease != null) {
+            if (sidSet && reqAddr != null) {
+                // Client in SELECTING state; remove any current lease before creating a new one.
+                mCommittedLeases.remove(assignedLease.getNetAddr());
+            } else if (!assignedLease.getNetAddr().equals(leaseAddr)) {
+                // reqAddr null (RENEWING/REBINDING): client renewing its own lease for clientAddr.
+                // reqAddr set with sid not set (INIT-REBOOT): client verifying configuration.
+                // In both cases, throw if clientAddr or reqAddr does not match the known lease.
+                throw new InvalidAddressException("Incorrect address for client in " +
+                        (reqAddr != null ? "INIT-REBOOT" : "RENEWING/REBINDING"));
+            }
+        }
+
+        // In the init-reboot case, RFC2131 #4.3.2 says that the server must not reply if
+        // assignedLease == null, but dnsmasq will let the client use the requested address if
+        // available, when configured with --dhcp-authoritative. This is preferable to avoid issues
+        // if the server lost the lease DB: the client would not get a reply because the server
+        // does not know their lease.
+        // Similarly in RENEWING/REBINDING state, create a lease when possible if the
+        // client-provided lease is unknown.
+        final DhcpLease lease =
+                checkClientAndMakeLease(clientId, hwAddr, leaseAddr, hostname, currentTime);
+        mLog.logf("DHCPREQUEST assignedLease %s, reqAddr=%s, sidSet=%s: created/renewed lease %s",
+                assignedLease, reqAddr, sidSet, lease);
+        return lease;
+    }
+
+    /**
+     * Check that the client can request the specified address, make or renew the lease if yes, and
+     * commit it.
+     *
+     * <p>This method always succeeds and returns the lease if it does not throw, and has no
+     * side-effect if it throws.
+     *
+     * @return The newly created or renewed, committed lease
+     * @throws InvalidAddressException The client provided an address that conflicts with its
+     *                                 current configuration, or other committed/reserved leases.
+     */
+    private DhcpLease checkClientAndMakeLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address addr, @Nullable String hostname, long currentTime)
+            throws InvalidAddressException {
+        final long expTime = currentTime + mLeaseTimeMs;
+        final DhcpLease currentLease = mCommittedLeases.getOrDefault(addr, null);
+        if (currentLease != null && !currentLease.matchesClient(clientId, hwAddr)) {
+            throw new InvalidAddressException("Address in use");
+        }
+
+        final DhcpLease lease;
+        if (currentLease == null) {
+            if (isValidAddress(addr) && !mReservedAddrs.contains(addr)) {
+                lease = new DhcpLease(clientId, hwAddr, addr, expTime, hostname);
+            } else {
+                throw new InvalidAddressException("Lease not found and address unavailable");
+            }
+        } else {
+            lease = currentLease.renewedLease(expTime, hostname);
+        }
+        commitLease(lease);
+        return lease;
+    }
+
+    private void commitLease(@NonNull DhcpLease lease) {
+        mCommittedLeases.put(lease.getNetAddr(), lease);
+        maybeUpdateEarliestExpiration(lease.getExpTime());
+    }
+
+    /**
+     * Delete a committed lease from the repository.
+     *
+     * @return true if a lease matching parameters was found.
+     */
+    public boolean releaseLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            @NonNull Inet4Address addr) {
+        final DhcpLease currentLease = mCommittedLeases.getOrDefault(addr, null);
+        if (currentLease == null) {
+            mLog.w("Could not release unknown lease for " + addr);
+            return false;
+        }
+        if (currentLease.matchesClient(clientId, hwAddr)) {
+            mCommittedLeases.remove(addr);
+            mLog.log("Released lease " + currentLease);
+            return true;
+        }
+        mLog.w(String.format("Not releasing lease %s: does not match client (cid %s, hwAddr %s)",
+                currentLease, DhcpLease.clientIdToString(clientId), hwAddr));
+        return false;
+    }
+
+    public void markLeaseDeclined(@NonNull Inet4Address addr) {
+        if (mDeclinedAddrs.containsKey(addr) || !isValidAddress(addr)) {
+            mLog.logf("Not marking %s as declined: already declined or not assignable", addr);
+            return;
+        }
+        final long expTime = mClock.elapsedRealtime() + mLeaseTimeMs;
+        mDeclinedAddrs.put(addr, expTime);
+        mLog.logf("Marked %s as declined expiring %d", addr, expTime);
+        maybeUpdateEarliestExpiration(expTime);
+    }
+
+    /**
+     * Get the list of currently valid committed leases in the repository.
+     */
+    @NonNull
+    public List<DhcpLease> getCommittedLeases() {
+        removeExpiredLeases(mClock.elapsedRealtime());
+        return new ArrayList<>(mCommittedLeases.values());
+    }
+
+    /**
+     * Get the set of addresses that have been marked as declined in the repository.
+     */
+    @NonNull
+    public Set<Inet4Address> getDeclinedAddresses() {
+        removeExpiredLeases(mClock.elapsedRealtime());
+        return new HashSet<>(mDeclinedAddrs.keySet());
+    }
+
+    /**
+     * Given the expiration time of a new committed lease or declined address, update
+     * {@link #mNextExpirationCheck} so it stays lower than or equal to the time for the first lease
+     * to expire.
+     */
+    private void maybeUpdateEarliestExpiration(long expTime) {
+        if (expTime < mNextExpirationCheck) {
+            mNextExpirationCheck = expTime;
+        }
+    }
+
+    /**
+     * Remove expired entries from a map keyed by {@link Inet4Address}.
+     *
+     * @param tag Type of lease in the map, for logging
+     * @param getExpTime Functor returning the expiration time for an object in the map.
+     *                   Must not return null.
+     * @return The lowest expiration time among entries remaining in the map
+     */
+    private <T> long removeExpired(long currentTime, @NonNull Map<Inet4Address, T> map,
+            @NonNull String tag, @NonNull Function<T, Long> getExpTime) {
+        final Iterator<Entry<Inet4Address, T>> it = map.entrySet().iterator();
+        long firstExpiration = EXPIRATION_NEVER;
+        while (it.hasNext()) {
+            final Entry<Inet4Address, T> lease = it.next();
+            final long expTime = getExpTime.apply(lease.getValue());
+            if (expTime <= currentTime) {
+                mLog.logf("Removing expired %s lease for %s (expTime=%s, currentTime=%s)",
+                        tag, lease.getKey(), expTime, currentTime);
+                it.remove();
+            } else {
+                firstExpiration = min(firstExpiration, expTime);
+            }
+        }
+        return firstExpiration;
+    }
+
+    /**
+     * Go through committed and declined leases and remove the expired ones.
+     */
+    private void removeExpiredLeases(long currentTime) {
+        if (currentTime < mNextExpirationCheck) {
+            return;
+        }
+
+        final long commExp = removeExpired(
+                currentTime, mCommittedLeases, "committed", DhcpLease::getExpTime);
+        final long declExp = removeExpired(
+                currentTime, mDeclinedAddrs, "declined", Function.identity());
+
+        mNextExpirationCheck = min(commExp, declExp);
+    }
+
+    private boolean isAvailable(@NonNull Inet4Address addr) {
+        return !mReservedAddrs.contains(addr) && !mCommittedLeases.containsKey(addr);
+    }
+
+    /**
+     * Get the 0-based index of an address in the subnet.
+     *
+     * <p>Given ordering of addresses 5.6.7.8 < 5.6.7.9 < 5.6.8.0, the index on a subnet is defined
+     * so that the first address is 0, the second 1, etc. For example on a /16, 192.168.0.0 -> 0,
+     * 192.168.0.1 -> 1, 192.168.1.0 -> 256
+     *
+     */
+    private int getAddrIndex(int addr) {
+        return addr & ~mSubnetMask;
+    }
+
+    private int getAddrByIndex(int index) {
+        return mSubnetAddr | index;
+    }
+
+    /**
+     * Get a valid address starting from the supplied one.
+     *
+     * <p>This only checks that the address is numerically valid for assignment, not whether it is
+     * already in use. The return value is always inside the configured prefix, even if the supplied
+     * address is not.
+     *
+     * <p>If the provided address is valid, it is returned as-is. Otherwise, the next valid
+     * address (with the ordering in {@link #getAddrIndex(int)}) is returned.
+     */
+    private int getValidAddress(int addr) {
+        final int lastByteMask = 0xff;
+        int addrIndex = getAddrIndex(addr); // 0-based index of the address in the subnet
+
+        // Some OSes do not handle addresses in .255 or .0 correctly: avoid those.
+        final int lastByte = getAddrByIndex(addrIndex) & lastByteMask;
+        if (lastByte == lastByteMask) {
+            // Avoid .255 address, and .0 address that follows
+            addrIndex = (addrIndex + 2) % mNumAddresses;
+        } else if (lastByte == 0) {
+            // Avoid .0 address
+            addrIndex = (addrIndex + 1) % mNumAddresses;
+        }
+
+        // Do not use first or last address of range
+        if (addrIndex == 0 || addrIndex == mNumAddresses - 1) {
+            // Always valid and not end of range since prefixLength is at most 30 in serving params
+            addrIndex = 1;
+        }
+        return getAddrByIndex(addrIndex);
+    }
+
+    /**
+     * Returns whether the address is in the configured subnet and part of the assignable range.
+     */
+    private boolean isValidAddress(Inet4Address addr) {
+        final int intAddr = inet4AddressToIntHTH(addr);
+        return getValidAddress(intAddr) == intAddr;
+    }
+
+    private int getNextAddress(int addr) {
+        final int addrIndex = getAddrIndex(addr);
+        final int nextAddress = getAddrByIndex((addrIndex + 1) % mNumAddresses);
+        return getValidAddress(nextAddress);
+    }
+
+    /**
+     * Calculate a first candidate address for a client by hashing the hardware address.
+     *
+     * <p>This will be a valid address as checked by {@link #getValidAddress(int)}, but may be
+     * in use.
+     *
+     * @return An IPv4 address encoded as 32-bit int
+     */
+    private int getFirstClientAddress(MacAddress hwAddr) {
+        // This follows dnsmasq behavior. Advantages are: clients will often get the same
+        // offers for different DISCOVER even if the lease was not yet accepted or has expired,
+        // and address generation will generally not need to loop through many allocated addresses
+        // until it finds a free one.
+        int hash = 0;
+        for (byte b : hwAddr.toByteArray()) {
+            hash += b + (b << 8) + (b << 16);
+        }
+        // This implementation will not always result in the same IPs as dnsmasq would give out in
+        // Android <= P, because it includes invalid and reserved addresses in mNumAddresses while
+        // the configured ranges for dnsmasq did not.
+        final int addrIndex = hash % mNumAddresses;
+        return getValidAddress(getAddrByIndex(addrIndex));
+    }
+
+    /**
+     * Create a lease that can be offered to respond to a client DISCOVER.
+     *
+     * <p>This method always succeeds and returns the lease if it does not throw. If no non-declined
+     * address is available, it will try to offer the oldest declined address if valid.
+     *
+     * @throws OutOfAddressesException The server has no address left to offer
+     */
+    private DhcpLease makeNewOffer(@Nullable byte[] clientId, @NonNull MacAddress hwAddr,
+            long expTime, @Nullable String hostname) throws OutOfAddressesException {
+        int intAddr = getFirstClientAddress(hwAddr);
+        // Loop until a free address is found, or there are no more addresses.
+        // There is slightly less than this many usable addresses, but some extra looping is OK
+        for (int i = 0; i < mNumAddresses; i++) {
+            final Inet4Address addr = intToInet4AddressHTH(intAddr);
+            if (isAvailable(addr) && !mDeclinedAddrs.containsKey(addr)) {
+                return new DhcpLease(clientId, hwAddr, addr, expTime, hostname);
+            }
+            intAddr = getNextAddress(intAddr);
+        }
+
+        // Try freeing DECLINEd addresses if out of addresses.
+        final Iterator<Inet4Address> it = mDeclinedAddrs.keySet().iterator();
+        while (it.hasNext()) {
+            final Inet4Address addr = it.next();
+            it.remove();
+            mLog.logf("Out of addresses in address pool: dropped declined addr %s", addr);
+            // isValidAddress() is always verified for entries in mDeclinedAddrs.
+            // However declined addresses may have been requested (typically by the machine that was
+            // already using the address) after being declined.
+            if (isAvailable(addr)) {
+                return new DhcpLease(clientId, hwAddr, addr, expTime, hostname);
+            }
+        }
+
+        throw new OutOfAddressesException("No address available for offer");
+    }
+}
diff --git a/services/net/java/android/net/dhcp/DhcpNakPacket.java b/services/net/java/android/net/dhcp/DhcpNakPacket.java
index 6458232..ef9af52 100644
--- a/services/net/java/android/net/dhcp/DhcpNakPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpNakPacket.java
@@ -26,11 +26,9 @@
     /**
      * Generates a NAK packet with the specified parameters.
      */
-    DhcpNakPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp,
-                  Inet4Address nextIp, Inet4Address relayIp,
-                  byte[] clientMac) {
-        super(transId, secs, INADDR_ANY, INADDR_ANY, nextIp, relayIp,
-            clientMac, false);
+    DhcpNakPacket(int transId, short secs, Inet4Address nextIp, Inet4Address relayIp,
+            byte[] clientMac, boolean broadcast) {
+        super(transId, secs, INADDR_ANY, INADDR_ANY, nextIp, relayIp, clientMac, broadcast);
     }
 
     public String toString() {
@@ -43,11 +41,11 @@
      */
     public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
         ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
-        Inet4Address destIp = mClientIp;
-        Inet4Address srcIp = mYourIp;
+        // Constructor does not set values for layers <= 3: use empty values
+        Inet4Address destIp = INADDR_ANY;
+        Inet4Address srcIp = INADDR_ANY;
 
-        fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
-            DHCP_BOOTREPLY, mBroadcast);
+        fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result, DHCP_BOOTREPLY, mBroadcast);
         result.flip();
         return result;
     }
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index d90a4a2..888821a 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -1,5 +1,6 @@
 package android.net.dhcp;
 
+import android.annotation.Nullable;
 import android.net.DhcpResults;
 import android.net.LinkAddress;
 import android.net.NetworkUtils;
@@ -204,6 +205,7 @@
     protected static final byte DHCP_MESSAGE_TYPE_DECLINE = 4;
     protected static final byte DHCP_MESSAGE_TYPE_ACK = 5;
     protected static final byte DHCP_MESSAGE_TYPE_NAK = 6;
+    protected static final byte DHCP_MESSAGE_TYPE_RELEASE = 7;
     protected static final byte DHCP_MESSAGE_TYPE_INFORM = 8;
 
     /**
@@ -252,6 +254,7 @@
      * DHCP Optional Type: DHCP Client Identifier
      */
     protected static final byte DHCP_CLIENT_IDENTIFIER = 61;
+    protected byte[] mClientId;
 
     /**
      * DHCP zero-length option code: pad
@@ -281,7 +284,7 @@
     protected final Inet4Address mClientIp;
     protected final Inet4Address mYourIp;
     private final Inet4Address mNextIp;
-    private final Inet4Address mRelayIp;
+    protected final Inet4Address mRelayIp;
 
     /**
      * Does the client request a broadcast response?
@@ -338,13 +341,28 @@
         return mClientMac;
     }
 
+    // TODO: refactor DhcpClient to set clientId when constructing packets and remove
+    // hasExplicitClientId logic
     /**
-     * Returns the client ID. This follows RFC 2132 and is based on the hardware address.
+     * Returns whether a client ID was set in the options for this packet.
+     */
+    public boolean hasExplicitClientId() {
+        return mClientId != null;
+    }
+
+    /**
+     * Returns the client ID. If not set explicitly, this follows RFC 2132 and creates a client ID
+     * based on the hardware address.
      */
     public byte[] getClientId() {
-        byte[] clientId = new byte[mClientMac.length + 1];
-        clientId[0] = CLIENT_ID_ETHER;
-        System.arraycopy(mClientMac, 0, clientId, 1, mClientMac.length);
+        final byte[] clientId;
+        if (hasExplicitClientId()) {
+            clientId = Arrays.copyOf(mClientId, mClientId.length);
+        } else {
+            clientId = new byte[mClientMac.length + 1];
+            clientId[0] = CLIENT_ID_ETHER;
+            System.arraycopy(mClientMac, 0, clientId, 1, mClientMac.length);
+        }
         return clientId;
     }
 
@@ -531,8 +549,10 @@
 
     /**
      * Adds an optional parameter containing an array of bytes.
+     *
+     * <p>This method is a no-op if the payload argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, byte[] payload) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable byte[] payload) {
         if (payload != null) {
             if (payload.length > MAX_OPTION_LEN) {
                 throw new IllegalArgumentException("DHCP option too long: "
@@ -546,8 +566,10 @@
 
     /**
      * Adds an optional parameter containing an IP address.
+     *
+     * <p>This method is a no-op if the address argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, Inet4Address addr) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable Inet4Address addr) {
         if (addr != null) {
             addTlv(buf, type, addr.getAddress());
         }
@@ -555,8 +577,10 @@
 
     /**
      * Adds an optional parameter containing a list of IP addresses.
+     *
+     * <p>This method is a no-op if the addresses argument is null or empty.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, List<Inet4Address> addrs) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable List<Inet4Address> addrs) {
         if (addrs == null || addrs.size() == 0) return;
 
         int optionLen = 4 * addrs.size();
@@ -574,9 +598,11 @@
     }
 
     /**
-     * Adds an optional parameter containing a short integer
+     * Adds an optional parameter containing a short integer.
+     *
+     * <p>This method is a no-op if the value argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, Short value) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable Short value) {
         if (value != null) {
             buf.put(type);
             buf.put((byte) 2);
@@ -585,9 +611,11 @@
     }
 
     /**
-     * Adds an optional parameter containing a simple integer
+     * Adds an optional parameter containing a simple integer.
+     *
+     * <p>This method is a no-op if the value argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, Integer value) {
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable Integer value) {
         if (value != null) {
             buf.put(type);
             buf.put((byte) 4);
@@ -597,12 +625,16 @@
 
     /**
      * Adds an optional parameter containing an ASCII string.
+     *
+     * <p>This method is a no-op if the string argument is null.
      */
-    protected static void addTlv(ByteBuffer buf, byte type, String str) {
-        try {
-            addTlv(buf, type, str.getBytes("US-ASCII"));
-        } catch (UnsupportedEncodingException e) {
-           throw new IllegalArgumentException("String is not US-ASCII: " + str);
+    protected static void addTlv(ByteBuffer buf, byte type, @Nullable String str) {
+        if (str != null) {
+            try {
+                addTlv(buf, type, str.getBytes("US-ASCII"));
+            } catch (UnsupportedEncodingException e) {
+                throw new IllegalArgumentException("String is not US-ASCII: " + str);
+            }
         }
     }
 
@@ -740,6 +772,7 @@
         Inet4Address nextIp;
         Inet4Address relayIp;
         byte[] clientMac;
+        byte[] clientId = null;
         List<Inet4Address> dnsServers = new ArrayList<>();
         List<Inet4Address> gateways = new ArrayList<>();  // aka router
         Inet4Address serverIdentifier = null;
@@ -1038,8 +1071,8 @@
                 throw new ParseException(DhcpErrorEvent.DHCP_NO_MSG_TYPE,
                         "No DHCP message type option");
             case DHCP_MESSAGE_TYPE_DISCOVER:
-                newPacket = new DhcpDiscoverPacket(
-                    transactionId, secs, clientMac, broadcast);
+                newPacket = new DhcpDiscoverPacket(transactionId, secs, relayIp, clientMac,
+                        broadcast, ipSrc);
                 break;
             case DHCP_MESSAGE_TYPE_OFFER:
                 newPacket = new DhcpOfferPacket(
@@ -1047,7 +1080,7 @@
                 break;
             case DHCP_MESSAGE_TYPE_REQUEST:
                 newPacket = new DhcpRequestPacket(
-                    transactionId, secs, clientIp, clientMac, broadcast);
+                    transactionId, secs, clientIp, relayIp, clientMac, broadcast);
                 break;
             case DHCP_MESSAGE_TYPE_DECLINE:
                 newPacket = new DhcpDeclinePacket(
@@ -1060,8 +1093,15 @@
                 break;
             case DHCP_MESSAGE_TYPE_NAK:
                 newPacket = new DhcpNakPacket(
-                    transactionId, secs, clientIp, yourIp, nextIp, relayIp,
-                    clientMac);
+                        transactionId, secs, nextIp, relayIp, clientMac, broadcast);
+                break;
+            case DHCP_MESSAGE_TYPE_RELEASE:
+                if (serverIdentifier == null) {
+                    throw new ParseException(DhcpErrorEvent.MISC_ERROR,
+                            "DHCPRELEASE without server identifier");
+                }
+                newPacket = new DhcpReleasePacket(
+                        transactionId, serverIdentifier, clientIp, relayIp, clientMac);
                 break;
             case DHCP_MESSAGE_TYPE_INFORM:
                 newPacket = new DhcpInformPacket(
@@ -1074,6 +1114,7 @@
         }
 
         newPacket.mBroadcastAddress = bcAddr;
+        newPacket.mClientId = clientId;
         newPacket.mDnsServers = dnsServers;
         newPacket.mDomainName = domainName;
         newPacket.mGateways = gateways;
@@ -1173,8 +1214,8 @@
      */
     public static ByteBuffer buildDiscoverPacket(int encap, int transactionId,
         short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams) {
-        DhcpPacket pkt = new DhcpDiscoverPacket(
-            transactionId, secs, clientMac, broadcast);
+        DhcpPacket pkt = new DhcpDiscoverPacket(transactionId, secs, INADDR_ANY /* relayIp */,
+                clientMac, broadcast, INADDR_ANY /* srcIp */);
         pkt.mRequestedParams = expectedParams;
         return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT);
     }
@@ -1223,12 +1264,11 @@
     /**
      * Builds a DHCP-NAK packet from the required specified parameters.
      */
-    public static ByteBuffer buildNakPacket(int encap, int transactionId,
-        Inet4Address serverIpAddr, Inet4Address clientIpAddr, byte[] mac) {
-        DhcpPacket pkt = new DhcpNakPacket(transactionId, (short) 0, clientIpAddr,
-            serverIpAddr, serverIpAddr, serverIpAddr, mac);
-        pkt.mMessage = "requested address not available";
-        pkt.mRequestedIp = clientIpAddr;
+    public static ByteBuffer buildNakPacket(int encap, int transactionId, Inet4Address serverIpAddr,
+            byte[] mac, boolean broadcast, String message) {
+        DhcpPacket pkt = new DhcpNakPacket(
+                transactionId, (short) 0, serverIpAddr, serverIpAddr, mac, broadcast);
+        pkt.mMessage = message;
         return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER);
     }
 
@@ -1240,7 +1280,7 @@
         byte[] clientMac, Inet4Address requestedIpAddress,
         Inet4Address serverIdentifier, byte[] requestedParams, String hostName) {
         DhcpPacket pkt = new DhcpRequestPacket(transactionId, secs, clientIp,
-            clientMac, broadcast);
+                INADDR_ANY /* relayIp */, clientMac, broadcast);
         pkt.mRequestedIp = requestedIpAddress;
         pkt.mServerIdentifier = serverIdentifier;
         pkt.mHostName = hostName;
diff --git a/services/net/java/android/net/dhcp/DhcpPacketListener.java b/services/net/java/android/net/dhcp/DhcpPacketListener.java
new file mode 100644
index 0000000..498fd93
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpPacketListener.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import android.annotation.Nullable;
+import android.net.util.FdEventsReader;
+import android.net.util.PacketReader;
+import android.os.Handler;
+import android.system.Os;
+
+import java.io.FileDescriptor;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
+/**
+ * A {@link FdEventsReader} to receive and parse {@link DhcpPacket}.
+ * @hide
+ */
+abstract class DhcpPacketListener extends FdEventsReader<DhcpPacketListener.Payload> {
+    static final class Payload {
+        final byte[] bytes = new byte[DhcpPacket.MAX_LENGTH];
+        Inet4Address srcAddr;
+    }
+
+    public DhcpPacketListener(Handler handler) {
+        super(handler, new Payload());
+    }
+
+    @Override
+    protected int recvBufSize(Payload buffer) {
+        return buffer.bytes.length;
+    }
+
+    @Override
+    protected final void handlePacket(Payload recvbuf, int length) {
+        if (recvbuf.srcAddr == null) {
+            return;
+        }
+
+        try {
+            final DhcpPacket packet = DhcpPacket.decodeFullPacket(recvbuf.bytes, length,
+                    DhcpPacket.ENCAP_BOOTP);
+            onReceive(packet, recvbuf.srcAddr);
+        } catch (DhcpPacket.ParseException e) {
+            logParseError(recvbuf.bytes, length, e);
+        }
+    }
+
+    @Override
+    protected int readPacket(FileDescriptor fd, Payload packetBuffer) throws Exception {
+        final InetSocketAddress addr = new InetSocketAddress();
+        final int read = Os.recvfrom(
+                fd, packetBuffer.bytes, 0, packetBuffer.bytes.length, 0 /* flags */, addr);
+
+        // Buffers with null srcAddr will be dropped in handlePacket()
+        packetBuffer.srcAddr = inet4AddrOrNull(addr);
+        return read;
+    }
+
+    @Nullable
+    private static Inet4Address inet4AddrOrNull(InetSocketAddress addr) {
+        return addr.getAddress() instanceof Inet4Address
+                ? (Inet4Address) addr.getAddress()
+                : null;
+    }
+
+    protected abstract void onReceive(DhcpPacket packet, Inet4Address srcAddr);
+    protected abstract void logParseError(byte[] packet, int length, DhcpPacket.ParseException e);
+}
diff --git a/services/net/java/android/net/dhcp/DhcpReleasePacket.java b/services/net/java/android/net/dhcp/DhcpReleasePacket.java
new file mode 100644
index 0000000..3958303
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpReleasePacket.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+
+/**
+ * Implements DHCP-RELEASE
+ */
+class DhcpReleasePacket extends DhcpPacket {
+
+    final Inet4Address mClientAddr;
+
+    /**
+     * Generates a RELEASE packet with the specified parameters.
+     */
+    public DhcpReleasePacket(int transId, Inet4Address serverId, Inet4Address clientAddr,
+            Inet4Address relayIp, byte[] clientMac) {
+        super(transId, (short)0, clientAddr, INADDR_ANY /* yourIp */, INADDR_ANY /* nextIp */,
+                relayIp, clientMac, false /* broadcast */);
+        mServerIdentifier = serverId;
+        mClientAddr = clientAddr;
+    }
+
+
+    @Override
+    public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
+        ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+        fillInPacket(encap, mServerIdentifier /* destIp */, mClientIp /* srcIp */, destUdp, srcUdp,
+                result, DHCP_BOOTREPLY, mBroadcast);
+        result.flip();
+        return result;
+    }
+
+    @Override
+    void finishPacket(ByteBuffer buffer) {
+        addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_RELEASE);
+        addTlv(buffer, DHCP_CLIENT_IDENTIFIER, getClientId());
+        addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier);
+        addCommonClientTlvs(buffer);
+        addTlvEnd(buffer);
+    }
+}
diff --git a/services/net/java/android/net/dhcp/DhcpRequestPacket.java b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
index 4f9aa01..231d0457 100644
--- a/services/net/java/android/net/dhcp/DhcpRequestPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
@@ -28,9 +28,9 @@
     /**
      * Generates a REQUEST packet with the specified parameters.
      */
-    DhcpRequestPacket(int transId, short secs, Inet4Address clientIp, byte[] clientMac,
-                      boolean broadcast) {
-        super(transId, secs, clientIp, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
+    DhcpRequestPacket(int transId, short secs, Inet4Address clientIp, Inet4Address relayIp,
+            byte[] clientMac, boolean broadcast) {
+        super(transId, secs, clientIp, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast);
     }
 
     public String toString() {
diff --git a/services/net/java/android/net/dhcp/DhcpServingParams.java b/services/net/java/android/net/dhcp/DhcpServingParams.java
new file mode 100644
index 0000000..ba9d116
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpServingParams.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
+import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
+import static android.net.util.NetworkConstants.IPV4_MAX_MTU;
+import static android.net.util.NetworkConstants.IPV4_MIN_MTU;
+
+import static java.lang.Integer.toUnsignedLong;
+
+import android.annotation.NonNull;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+
+import java.net.Inet4Address;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Parameters used by the DhcpServer to serve requests.
+ *
+ * <p>Instances are immutable. Use {@link DhcpServingParams.Builder} to instantiate.
+ * @hide
+ */
+public class DhcpServingParams {
+    public static final int MTU_UNSET = 0;
+    public static final int MIN_PREFIX_LENGTH = 16;
+    public static final int MAX_PREFIX_LENGTH = 30;
+
+    /** Server inet address and prefix to serve */
+    @NonNull
+    public final LinkAddress serverAddr;
+
+    /**
+     * Default routers to be advertised to DHCP clients. May be empty.
+     * This set is provided by {@link DhcpServingParams.Builder} and is immutable.
+     */
+    @NonNull
+    public final Set<Inet4Address> defaultRouters;
+
+    /**
+     * DNS servers to be advertised to DHCP clients. May be empty.
+     * This set is provided by {@link DhcpServingParams.Builder} and is immutable.
+     */
+    @NonNull
+    public final Set<Inet4Address> dnsServers;
+
+    /**
+     * Excluded addresses that the DHCP server is not allowed to assign to clients.
+     * This set is provided by {@link DhcpServingParams.Builder} and is immutable.
+     */
+    @NonNull
+    public final Set<Inet4Address> excludedAddrs;
+
+    // DHCP uses uint32. Use long for clearer code, and check range when building.
+    public final long dhcpLeaseTimeSecs;
+    public final int linkMtu;
+
+    /**
+     * Checked exception thrown when some parameters used to build {@link DhcpServingParams} are
+     * missing or invalid.
+     */
+    public static class InvalidParameterException extends Exception {
+        public InvalidParameterException(String message) {
+            super(message);
+        }
+    }
+
+    private DhcpServingParams(@NonNull LinkAddress serverAddr,
+            @NonNull Set<Inet4Address> defaultRouters,
+            @NonNull Set<Inet4Address> dnsServers, @NonNull Set<Inet4Address> excludedAddrs,
+            long dhcpLeaseTimeSecs, int linkMtu) {
+        this.serverAddr = serverAddr;
+        this.defaultRouters = defaultRouters;
+        this.dnsServers = dnsServers;
+        this.excludedAddrs = excludedAddrs;
+        this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
+        this.linkMtu = linkMtu;
+    }
+
+    @NonNull
+    public Inet4Address getServerInet4Addr() {
+        return (Inet4Address) serverAddr.getAddress();
+    }
+
+    /**
+     * Get the served prefix mask as an IPv4 address.
+     *
+     * <p>For example, if the served prefix is 192.168.42.0/24, this will return 255.255.255.0.
+     */
+    @NonNull
+    public Inet4Address getPrefixMaskAsAddress() {
+        return getPrefixMaskAsInet4Address(serverAddr.getPrefixLength());
+    }
+
+    /**
+     * Get the server broadcast address.
+     *
+     * <p>For example, if the server {@link LinkAddress} is 192.168.42.1/24, this will return
+     * 192.168.42.255.
+     */
+    @NonNull
+    public Inet4Address getBroadcastAddress() {
+        return NetworkUtils.getBroadcastAddress(getServerInet4Addr(), serverAddr.getPrefixLength());
+    }
+
+    /**
+     * Utility class to create new instances of {@link DhcpServingParams} while checking validity
+     * of the parameters.
+     */
+    public static class Builder {
+        private LinkAddress serverAddr;
+        private Set<Inet4Address> defaultRouters;
+        private Set<Inet4Address> dnsServers;
+        private Set<Inet4Address> excludedAddrs;
+        private long dhcpLeaseTimeSecs;
+        private int linkMtu = MTU_UNSET;
+
+        /**
+         * Set the server address and served prefix for the DHCP server.
+         *
+         * <p>This parameter is required.
+         */
+        public Builder setServerAddr(@NonNull LinkAddress serverAddr) {
+            this.serverAddr = serverAddr;
+            return this;
+        }
+
+        /**
+         * Set the default routers to be advertised to DHCP clients.
+         *
+         * <p>Each router must be inside the served prefix. This may be an empty set, but it must
+         * always be set explicitly before building the {@link DhcpServingParams}.
+         */
+        public Builder setDefaultRouters(@NonNull Set<Inet4Address> defaultRouters) {
+            this.defaultRouters = defaultRouters;
+            return this;
+        }
+
+        /**
+         * Set the DNS servers to be advertised to DHCP clients.
+         *
+         * <p>This may be an empty set, but it must always be set explicitly before building the
+         * {@link DhcpServingParams}.
+         */
+        public Builder setDnsServers(@NonNull Set<Inet4Address> dnsServers) {
+            this.dnsServers = dnsServers;
+            return this;
+        }
+
+        /**
+         * Set excluded addresses that the DHCP server is not allowed to assign to clients.
+         *
+         * <p>This parameter is optional. DNS servers and default routers are always excluded
+         * and do not need to be set here.
+         */
+        public Builder setExcludedAddrs(@NonNull Set<Inet4Address> excludedAddrs) {
+            this.excludedAddrs = excludedAddrs;
+            return this;
+        }
+
+        /**
+         * Set the lease time for leases assigned by the DHCP server.
+         *
+         * <p>This parameter is required.
+         */
+        public Builder setDhcpLeaseTimeSecs(long dhcpLeaseTimeSecs) {
+            this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
+            return this;
+        }
+
+        /**
+         * Set the link MTU to be advertised to DHCP clients.
+         *
+         * <p>If set to {@link #MTU_UNSET}, no MTU will be advertised to clients. This parameter
+         * is optional and defaults to {@link #MTU_UNSET}.
+         */
+        public Builder setLinkMtu(int linkMtu) {
+            this.linkMtu = linkMtu;
+            return this;
+        }
+
+        /**
+         * Create a new {@link DhcpServingParams} instance based on parameters set in the builder.
+         *
+         * <p>This method has no side-effects. If it does not throw, a valid
+         * {@link DhcpServingParams} is returned.
+         * @return The constructed parameters.
+         * @throws InvalidParameterException At least one parameter is missing or invalid.
+         */
+        @NonNull
+        public DhcpServingParams build() throws InvalidParameterException {
+            if (serverAddr == null) {
+                throw new InvalidParameterException("Missing serverAddr");
+            }
+            if (defaultRouters == null) {
+                throw new InvalidParameterException("Missing defaultRouters");
+            }
+            if (dnsServers == null) {
+                // Empty set is OK, but enforce explicitly setting it
+                throw new InvalidParameterException("Missing dnsServers");
+            }
+            if (dhcpLeaseTimeSecs <= 0 || dhcpLeaseTimeSecs > toUnsignedLong(INFINITE_LEASE)) {
+                throw new InvalidParameterException("Invalid lease time: " + dhcpLeaseTimeSecs);
+            }
+            if (linkMtu != MTU_UNSET && (linkMtu < IPV4_MIN_MTU || linkMtu > IPV4_MAX_MTU)) {
+                throw new InvalidParameterException("Invalid link MTU: " + linkMtu);
+            }
+            if (!serverAddr.isIPv4()) {
+                throw new InvalidParameterException("serverAddr must be IPv4");
+            }
+            if (serverAddr.getPrefixLength() < MIN_PREFIX_LENGTH
+                    || serverAddr.getPrefixLength() > MAX_PREFIX_LENGTH) {
+                throw new InvalidParameterException("Prefix length is not in supported range");
+            }
+
+            final IpPrefix prefix = makeIpPrefix(serverAddr);
+            for (Inet4Address addr : defaultRouters) {
+                if (!prefix.contains(addr)) {
+                    throw new InvalidParameterException(String.format(
+                            "Default router %s is not in server prefix %s", addr, serverAddr));
+                }
+            }
+
+            final Set<Inet4Address> excl = new HashSet<>();
+            if (excludedAddrs != null) {
+                excl.addAll(excludedAddrs);
+            }
+            excl.add((Inet4Address) serverAddr.getAddress());
+            excl.addAll(defaultRouters);
+            excl.addAll(dnsServers);
+
+            return new DhcpServingParams(serverAddr,
+                    Collections.unmodifiableSet(new HashSet<>(defaultRouters)),
+                    Collections.unmodifiableSet(new HashSet<>(dnsServers)),
+                    Collections.unmodifiableSet(excl),
+                    dhcpLeaseTimeSecs, linkMtu);
+        }
+    }
+
+    @NonNull
+    static IpPrefix makeIpPrefix(@NonNull LinkAddress addr) {
+        return new IpPrefix(addr.getAddress(), addr.getPrefixLength());
+    }
+}
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index 7f821ff..b77da28 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -524,7 +524,7 @@
                 return false;
             }
             // There no more than one IPv4 address
-            if (ipAddresses.stream().filter(Inet4Address.class::isInstance).count() > 1) {
+            if (ipAddresses.stream().filter(LinkAddress::isIPv4).count() > 1) {
                 return false;
             }
 
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
index 5af3c29..cfcba3a 100644
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ b/services/net/java/android/net/netlink/NetlinkSocket.java
@@ -59,10 +59,9 @@
         final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage";
         final long IO_TIMEOUT = 300L;
 
-        FileDescriptor fd;
+        final FileDescriptor fd = forProto(nlProto);
 
         try {
-            fd = forProto(nlProto);
             connectToKernel(fd);
             sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT);
             final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT);
@@ -96,9 +95,9 @@
         } catch (SocketException e) {
             Log.e(TAG, errPrefix, e);
             throw new ErrnoException(errPrefix, EIO, e);
+        } finally {
+            IoUtils.closeQuietly(fd);
         }
-
-        IoUtils.closeQuietly(fd);
     }
 
     public static FileDescriptor forProto(int nlProto) throws ErrnoException {
diff --git a/services/net/java/android/net/util/FdEventsReader.java b/services/net/java/android/net/util/FdEventsReader.java
new file mode 100644
index 0000000..575444f
--- /dev/null
+++ b/services/net/java/android/net/util/FdEventsReader.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util;
+
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.MessageQueue;
+import android.system.ErrnoException;
+import android.system.OsConstants;
+
+import libcore.io.IoUtils;
+
+import java.io.FileDescriptor;
+
+
+/**
+ * This class encapsulates the mechanics of registering a file descriptor
+ * with a thread's Looper and handling read events (and errors).
+ *
+ * Subclasses MUST implement createFd() and SHOULD override handlePacket(). They MAY override
+ * onStop() and onStart().
+ *
+ * Subclasses can expect a call life-cycle like the following:
+ *
+ *     [1] when a client calls start(), createFd() is called, followed by the onStart() hook if all
+ *         goes well. Implementations may override onStart() for additional initialization.
+ *
+ *     [2] yield, waiting for read event or error notification:
+ *
+ *             [a] readPacket() && handlePacket()
+ *
+ *             [b] if (no error):
+ *                     goto 2
+ *                 else:
+ *                     goto 3
+ *
+ *     [3] when a client calls stop(), the onStop() hook is called (unless already stopped or never
+ *         started). Implementations may override onStop() for additional cleanup.
+ *
+ * The packet receive buffer is recycled on every read call, so subclasses
+ * should make any copies they would like inside their handlePacket()
+ * implementation.
+ *
+ * All public methods MUST only be called from the same thread with which
+ * the Handler constructor argument is associated.
+ *
+ * @hide
+ */
+public abstract class FdEventsReader<BufferType> {
+    private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR;
+    private static final int UNREGISTER_THIS_FD = 0;
+
+    @NonNull
+    private final Handler mHandler;
+    @NonNull
+    private final MessageQueue mQueue;
+    @NonNull
+    private final BufferType mBuffer;
+    @Nullable
+    private FileDescriptor mFd;
+    private long mPacketsReceived;
+
+    protected static void closeFd(FileDescriptor fd) {
+        IoUtils.closeQuietly(fd);
+    }
+
+    protected FdEventsReader(@NonNull Handler h, @NonNull BufferType buffer) {
+        mHandler = h;
+        mQueue = mHandler.getLooper().getQueue();
+        mBuffer = buffer;
+    }
+
+    public final void start() {
+        if (onCorrectThread()) {
+            createAndRegisterFd();
+        } else {
+            mHandler.post(() -> {
+                logError("start() called from off-thread", null);
+                createAndRegisterFd();
+            });
+        }
+    }
+
+    public final void stop() {
+        if (onCorrectThread()) {
+            unregisterAndDestroyFd();
+        } else {
+            mHandler.post(() -> {
+                logError("stop() called from off-thread", null);
+                unregisterAndDestroyFd();
+            });
+        }
+    }
+
+    @NonNull
+    public Handler getHandler() { return mHandler; }
+
+    protected abstract int recvBufSize(@NonNull BufferType buffer);
+
+    public int recvBufSize() { return recvBufSize(mBuffer); }
+
+    /**
+     * Get the number of successful calls to {@link #readPacket(FileDescriptor, Object)}.
+     *
+     * <p>A call was successful if {@link #readPacket(FileDescriptor, Object)} returned a value > 0.
+     */
+    public final long numPacketsReceived() { return mPacketsReceived; }
+
+    /**
+     * Subclasses MUST create the listening socket here, including setting
+     * all desired socket options, interface or address/port binding, etc.
+     */
+    @Nullable
+    protected abstract FileDescriptor createFd();
+
+    /**
+     * Implementations MUST return the bytes read or throw an Exception.
+     *
+     * <p>The caller may throw a {@link ErrnoException} with {@link OsConstants#EAGAIN} or
+     * {@link OsConstants#EINTR}, in which case {@link FdEventsReader} will ignore the buffer
+     * contents and respectively wait for further input or retry the read immediately. For all other
+     * exceptions, the {@link FdEventsReader} will be stopped with no more interactions with this
+     * method.
+     */
+    protected abstract int readPacket(@NonNull FileDescriptor fd, @NonNull BufferType buffer)
+            throws Exception;
+
+    /**
+     * Called by the main loop for every packet.  Any desired copies of
+     * |recvbuf| should be made in here, as the underlying byte array is
+     * reused across all reads.
+     */
+    protected void handlePacket(@NonNull BufferType recvbuf, int length) {}
+
+    /**
+     * Called by the main loop to log errors.  In some cases |e| may be null.
+     */
+    protected void logError(@NonNull String msg, @Nullable Exception e) {}
+
+    /**
+     * Called by start(), if successful, just prior to returning.
+     */
+    protected void onStart() {}
+
+    /**
+     * Called by stop() just prior to returning.
+     */
+    protected void onStop() {}
+
+    private void createAndRegisterFd() {
+        if (mFd != null) return;
+
+        try {
+            mFd = createFd();
+            if (mFd != null) {
+                // Force the socket to be non-blocking.
+                IoUtils.setBlocking(mFd, false);
+            }
+        } catch (Exception e) {
+            logError("Failed to create socket: ", e);
+            closeFd(mFd);
+            mFd = null;
+        }
+
+        if (mFd == null) return;
+
+        mQueue.addOnFileDescriptorEventListener(
+                mFd,
+                FD_EVENTS,
+                (fd, events) -> {
+                    // Always call handleInput() so read/recvfrom are given
+                    // a proper chance to encounter a meaningful errno and
+                    // perhaps log a useful error message.
+                    if (!isRunning() || !handleInput()) {
+                        unregisterAndDestroyFd();
+                        return UNREGISTER_THIS_FD;
+                    }
+                    return FD_EVENTS;
+                });
+        onStart();
+    }
+
+    private boolean isRunning() { return (mFd != null) && mFd.valid(); }
+
+    // Keep trying to read until we get EAGAIN/EWOULDBLOCK or some fatal error.
+    private boolean handleInput() {
+        while (isRunning()) {
+            final int bytesRead;
+
+            try {
+                bytesRead = readPacket(mFd, mBuffer);
+                if (bytesRead < 1) {
+                    if (isRunning()) logError("Socket closed, exiting", null);
+                    break;
+                }
+                mPacketsReceived++;
+            } catch (ErrnoException e) {
+                if (e.errno == OsConstants.EAGAIN) {
+                    // We've read everything there is to read this time around.
+                    return true;
+                } else if (e.errno == OsConstants.EINTR) {
+                    continue;
+                } else {
+                    if (isRunning()) logError("readPacket error: ", e);
+                    break;
+                }
+            } catch (Exception e) {
+                if (isRunning()) logError("readPacket error: ", e);
+                break;
+            }
+
+            try {
+                handlePacket(mBuffer, bytesRead);
+            } catch (Exception e) {
+                logError("handlePacket error: ", e);
+                break;
+            }
+        }
+
+        return false;
+    }
+
+    private void unregisterAndDestroyFd() {
+        if (mFd == null) return;
+
+        mQueue.removeOnFileDescriptorEventListener(mFd);
+        closeFd(mFd);
+        mFd = null;
+        onStop();
+    }
+
+    private boolean onCorrectThread() {
+        return (mHandler.getLooper() == Looper.myLooper());
+    }
+}
diff --git a/services/net/java/android/net/util/NetworkConstants.java b/services/net/java/android/net/util/NetworkConstants.java
index de04fd0..3defe56 100644
--- a/services/net/java/android/net/util/NetworkConstants.java
+++ b/services/net/java/android/net/util/NetworkConstants.java
@@ -77,10 +77,12 @@
     /**
      * IPv4 constants.
      *
-     * See als:
+     * See also:
      *     - https://tools.ietf.org/html/rfc791
      */
     public static final int IPV4_HEADER_MIN_LEN = 20;
+    public static final int IPV4_MIN_MTU = 68;
+    public static final int IPV4_MAX_MTU = 65_535;
     public static final int IPV4_IHL_MASK = 0xf;
     public static final int IPV4_FLAGS_OFFSET = 6;
     public static final int IPV4_FRAGMENT_MASK = 0x1fff;
diff --git a/services/net/java/android/net/util/PacketReader.java b/services/net/java/android/net/util/PacketReader.java
index 10da2a5..4aec6b6 100644
--- a/services/net/java/android/net/util/PacketReader.java
+++ b/services/net/java/android/net/util/PacketReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,236 +16,46 @@
 
 package android.net.util;
 
-import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
-import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+import static java.lang.Math.max;
 
-import android.annotation.Nullable;
 import android.os.Handler;
-import android.os.Looper;
-import android.os.MessageQueue;
-import android.os.MessageQueue.OnFileDescriptorEventListener;
-import android.system.ErrnoException;
 import android.system.Os;
-import android.system.OsConstants;
-
-import libcore.io.IoUtils;
 
 import java.io.FileDescriptor;
-import java.io.IOException;
-
 
 /**
- * This class encapsulates the mechanics of registering a file descriptor
- * with a thread's Looper and handling read events (and errors).
- *
- * Subclasses MUST implement createFd() and SHOULD override handlePacket().
-
- * Subclasses can expect a call life-cycle like the following:
- *
- *     [1] start() calls createFd() and (if all goes well) onStart()
- *
- *     [2] yield, waiting for read event or error notification:
- *
- *             [a] readPacket() && handlePacket()
- *
- *             [b] if (no error):
- *                     goto 2
- *                 else:
- *                     goto 3
- *
- *     [3] stop() calls onStop() if not previously stopped
- *
- * The packet receive buffer is recycled on every read call, so subclasses
- * should make any copies they would like inside their handlePacket()
- * implementation.
- *
- * All public methods MUST only be called from the same thread with which
- * the Handler constructor argument is associated.
+ * Specialization of {@link FdEventsReader} that reads packets into a byte array.
  *
  * TODO: rename this class to something more correctly descriptive (something
  * like [or less horrible than] FdReadEventsHandler?).
  *
  * @hide
  */
-public abstract class PacketReader {
-    private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR;
-    private static final int UNREGISTER_THIS_FD = 0;
+public abstract class PacketReader extends FdEventsReader<byte[]> {
 
     public static final int DEFAULT_RECV_BUF_SIZE = 2 * 1024;
 
-    private final Handler mHandler;
-    private final MessageQueue mQueue;
-    private final byte[] mPacket;
-    private FileDescriptor mFd;
-    private long mPacketsReceived;
-
-    protected static void closeFd(FileDescriptor fd) {
-        IoUtils.closeQuietly(fd);
-    }
-
     protected PacketReader(Handler h) {
         this(h, DEFAULT_RECV_BUF_SIZE);
     }
 
-    protected PacketReader(Handler h, int recvbufsize) {
-        mHandler = h;
-        mQueue = mHandler.getLooper().getQueue();
-        mPacket = new byte[Math.max(recvbufsize, DEFAULT_RECV_BUF_SIZE)];
+    protected PacketReader(Handler h, int recvBufSize) {
+        super(h, new byte[max(recvBufSize, DEFAULT_RECV_BUF_SIZE)]);
     }
 
-    public final void start() {
-        if (onCorrectThread()) {
-            createAndRegisterFd();
-        } else {
-            mHandler.post(() -> {
-                logError("start() called from off-thread", null);
-                createAndRegisterFd();
-            });
-        }
+    @Override
+    protected final int recvBufSize(byte[] buffer) {
+        return buffer.length;
     }
 
-    public final void stop() {
-        if (onCorrectThread()) {
-            unregisterAndDestroyFd();
-        } else {
-            mHandler.post(() -> {
-                logError("stop() called from off-thread", null);
-                unregisterAndDestroyFd();
-            });
-        }
-    }
-
-    public Handler getHandler() { return mHandler; }
-
-    public final int recvBufSize() { return mPacket.length; }
-
-    public final long numPacketsReceived() { return mPacketsReceived; }
-
-    /**
-     * Subclasses MUST create the listening socket here, including setting
-     * all desired socket options, interface or address/port binding, etc.
-     */
-    protected abstract FileDescriptor createFd();
-
     /**
      * Subclasses MAY override this to change the default read() implementation
      * in favour of, say, recvfrom().
      *
      * Implementations MUST return the bytes read or throw an Exception.
      */
+    @Override
     protected int readPacket(FileDescriptor fd, byte[] packetBuffer) throws Exception {
         return Os.read(fd, packetBuffer, 0, packetBuffer.length);
     }
-
-    /**
-     * Called by the main loop for every packet.  Any desired copies of
-     * |recvbuf| should be made in here, as the underlying byte array is
-     * reused across all reads.
-     */
-    protected void handlePacket(byte[] recvbuf, int length) {}
-
-    /**
-     * Called by the main loop to log errors.  In some cases |e| may be null.
-     */
-    protected void logError(String msg, Exception e) {}
-
-    /**
-     * Called by start(), if successful, just prior to returning.
-     */
-    protected void onStart() {}
-
-    /**
-     * Called by stop() just prior to returning.
-     */
-    protected void onStop() {}
-
-    private void createAndRegisterFd() {
-        if (mFd != null) return;
-
-        try {
-            mFd = createFd();
-            if (mFd != null) {
-                // Force the socket to be non-blocking.
-                IoUtils.setBlocking(mFd, false);
-            }
-        } catch (Exception e) {
-            logError("Failed to create socket: ", e);
-            closeFd(mFd);
-            mFd = null;
-            return;
-        }
-
-        if (mFd == null) return;
-
-        mQueue.addOnFileDescriptorEventListener(
-                mFd,
-                FD_EVENTS,
-                new OnFileDescriptorEventListener() {
-                    @Override
-                    public int onFileDescriptorEvents(FileDescriptor fd, int events) {
-                        // Always call handleInput() so read/recvfrom are given
-                        // a proper chance to encounter a meaningful errno and
-                        // perhaps log a useful error message.
-                        if (!isRunning() || !handleInput()) {
-                            unregisterAndDestroyFd();
-                            return UNREGISTER_THIS_FD;
-                        }
-                        return FD_EVENTS;
-                    }
-                });
-        onStart();
-    }
-
-    private boolean isRunning() { return (mFd != null) && mFd.valid(); }
-
-    // Keep trying to read until we get EAGAIN/EWOULDBLOCK or some fatal error.
-    private boolean handleInput() {
-        while (isRunning()) {
-            final int bytesRead;
-
-            try {
-                bytesRead = readPacket(mFd, mPacket);
-                if (bytesRead < 1) {
-                    if (isRunning()) logError("Socket closed, exiting", null);
-                    break;
-                }
-                mPacketsReceived++;
-            } catch (ErrnoException e) {
-                if (e.errno == OsConstants.EAGAIN) {
-                    // We've read everything there is to read this time around.
-                    return true;
-                } else if (e.errno == OsConstants.EINTR) {
-                    continue;
-                } else {
-                    if (isRunning()) logError("readPacket error: ", e);
-                    break;
-                }
-            } catch (Exception e) {
-                if (isRunning()) logError("readPacket error: ", e);
-                break;
-            }
-
-            try {
-                handlePacket(mPacket, bytesRead);
-            } catch (Exception e) {
-                logError("handlePacket error: ", e);
-                break;
-            }
-        }
-
-        return false;
-    }
-
-    private void unregisterAndDestroyFd() {
-        if (mFd == null) return;
-
-        mQueue.removeOnFileDescriptorEventListener(mFd);
-        closeFd(mFd);
-        mFd = null;
-        onStop();
-    }
-
-    private boolean onCorrectThread() {
-        return (mHandler.getLooper() == Looper.myLooper());
-    }
 }
diff --git a/services/net/java/android/net/util/SharedLog.java b/services/net/java/android/net/util/SharedLog.java
index bbd3d13..f7bf393 100644
--- a/services/net/java/android/net/util/SharedLog.java
+++ b/services/net/java/android/net/util/SharedLog.java
@@ -16,6 +16,7 @@
 
 package android.net.util;
 
+import android.annotation.NonNull;
 import android.text.TextUtils;
 import android.util.LocalLog;
 import android.util.Log;
@@ -90,6 +91,13 @@
         Log.e(mTag, record(Category.ERROR, msg));
     }
 
+    /**
+     * Log an error due to an exception, with the exception stacktrace.
+     */
+    public void e(@NonNull String msg, @NonNull Throwable e) {
+        Log.e(mTag, record(Category.ERROR, msg + ": " + e.getMessage()), e);
+    }
+
     public void i(String msg) {
         Log.i(mTag, record(Category.NONE, msg));
     }
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index c1c32c2..774a3bc 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -708,8 +708,10 @@
         @Override
         public void onServiceDisconnected(ComponentName name) {
             synchronized (mLock) {
-                clearClientLocked();
-                mRemoteInstance = null;
+                if (mRemoteInstance != null) {
+                    clearClientLocked();
+                    mRemoteInstance = null;
+                }
             }
         }
     }
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index 4fbc14c..e8266a5 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -243,7 +243,7 @@
             intent.setData(Uri.fromParts("printjob", printJob.getId().flattenToString(), null));
             intent.putExtra(PrintManager.EXTRA_PRINT_DOCUMENT_ADAPTER, adapter.asBinder());
             intent.putExtra(PrintManager.EXTRA_PRINT_JOB, printJob);
-            intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, packageName);
+            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
 
             IntentSender intentSender = PendingIntent.getActivityAsUser(
                     mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
diff --git a/services/robotests/README b/services/robotests/README
new file mode 100644
index 0000000..3c68292
--- /dev/null
+++ b/services/robotests/README
@@ -0,0 +1,23 @@
+This folder is for Robolectric tests inside the platform.
+
+To add a test class annotate it as follows:
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderClasses({ClassUnderTest.class, DependencyClasses.class})
+@SystemLoaderPackages({"com.android.server.yourmodule"})
+
+Robolectric loads some classes that it decides from versioned jars of the framework. Since we are
+part of the framework some of our classes get loaded from these jars. This is NOT what we want, we
+want to test against what we wrote in the tree. Because of this we use a custom test runner,
+FrameworkRobolectricTestRunner, that bypasses these jars and loads certain classes from the system
+class loader.
+
+To specify which classes to load use either @SystemLoaderClasses or @SystemLoaderPackages. In
+practice:
+* You MUST put the class under test here.
+* If you encounter any exceptions that might be caused by a different version of the class being
+loaded, such as NoSuchMethodException, put the class involved in the exception in this annotation
+and try again.
+
+Check Android.mk file for more info.
diff --git a/services/robotests/src/android/app/backup/ForwardingBackupAgent.java b/services/robotests/src/android/app/backup/ForwardingBackupAgent.java
new file mode 100644
index 0000000..4ff5b7c
--- /dev/null
+++ b/services/robotests/src/android/app/backup/ForwardingBackupAgent.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app.backup;
+
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Useful for spying in {@link BackupAgent} instances since their {@link BackupAgent#onBind()} is
+ * final and always points to the original instance, instead of the spy.
+ *
+ * <p>To use, construct a spy of the desired {@link BackupAgent}, spying on the methods of interest.
+ * Then, where you need to pass the agent, use {@link ForwardingBackupAgent#forward(BackupAgent)}
+ * with the spy.
+ */
+public class ForwardingBackupAgent extends BackupAgent {
+    /** Returns a {@link BackupAgent} that forwards method calls to {@code backupAgent}. */
+    public static BackupAgent forward(BackupAgent backupAgent) {
+        return new ForwardingBackupAgent(backupAgent);
+    }
+
+    private final BackupAgent mBackupAgent;
+
+    private ForwardingBackupAgent(BackupAgent backupAgent) {
+        mBackupAgent = backupAgent;
+    }
+
+    @Override
+    public void onCreate() {
+        mBackupAgent.onCreate();
+    }
+
+    @Override
+    public void onDestroy() {
+        mBackupAgent.onDestroy();
+    }
+
+    @Override
+    public void onBackup(
+            ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)
+            throws IOException {
+        mBackupAgent.onBackup(oldState, data, newState);
+    }
+
+    @Override
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+            throws IOException {
+        mBackupAgent.onRestore(data, appVersionCode, newState);
+    }
+
+    @Override
+    public void onRestore(BackupDataInput data, long appVersionCode, ParcelFileDescriptor newState)
+            throws IOException {
+        mBackupAgent.onRestore(data, appVersionCode, newState);
+    }
+
+    @Override
+    public void onFullBackup(FullBackupDataOutput data) throws IOException {
+        mBackupAgent.onFullBackup(data);
+    }
+
+    @Override
+    public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
+        mBackupAgent.onQuotaExceeded(backupDataBytes, quotaBytes);
+    }
+
+    @Override
+    public void onRestoreFile(
+            ParcelFileDescriptor data, long size, File destination, int type, long mode, long mtime)
+            throws IOException {
+        mBackupAgent.onRestoreFile(data, size, destination, type, mode, mtime);
+    }
+
+    @Override
+    protected void onRestoreFile(
+            ParcelFileDescriptor data,
+            long size,
+            int type,
+            String domain,
+            String path,
+            long mode,
+            long mtime)
+            throws IOException {
+        mBackupAgent.onRestoreFile(data, size, type, domain, path, mode, mtime);
+    }
+
+    @Override
+    public void onRestoreFinished() {
+        mBackupAgent.onRestoreFinished();
+    }
+
+    @Override
+    public void attach(Context context) {
+        mBackupAgent.attach(context);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index d16bc26..91a8857 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -16,7 +16,7 @@
 
 package com.android.server.backup;
 
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThread;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startSilentBackupThread;
 import static com.android.server.backup.testing.TransportData.backupTransport;
 import static com.android.server.backup.testing.TransportData.d2dTransport;
 import static com.android.server.backup.testing.TransportData.localTransport;
@@ -45,7 +45,7 @@
 import android.os.PowerSaveState;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import com.android.server.backup.internal.BackupRequest;
+import com.android.server.backup.testing.BackupManagerServiceTestUtils;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportNotRegisteredException;
@@ -55,7 +55,7 @@
 import com.android.server.testing.shadows.ShadowBackupPolicyEnforcer;
 import com.android.server.testing.shadows.ShadowBinder;
 import com.android.server.testing.shadows.ShadowKeyValueBackupJob;
-import com.android.server.testing.shadows.ShadowPerformBackupTask;
+import com.android.server.testing.shadows.ShadowKeyValueBackupTask;
 import java.io.File;
 import java.util.List;
 import org.junit.After;
@@ -68,11 +68,9 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implements;
 import org.robolectric.shadows.ShadowContextWrapper;
-import org.robolectric.shadows.ShadowLog;
 import org.robolectric.shadows.ShadowLooper;
 import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.shadows.ShadowSettings;
-import org.robolectric.shadows.ShadowSystemClock;
 
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
@@ -104,7 +102,10 @@
         mTransport = backupTransport();
         mTransportName = mTransport.transportName;
 
-        mBackupThread = startBackupThread(this::uncaughtException);
+        // Unrelated exceptions are thrown in the backup thread. Until we mock everything properly
+        // we should not fail tests because of this. This is not flakiness, the exceptions thrown
+        // don't interfere with the tests.
+        mBackupThread = startSilentBackupThread(TAG);
         mShadowBackupLooper = shadowOf(mBackupThread.getLooper());
 
         ContextWrapper context = RuntimeEnvironment.application;
@@ -113,8 +114,10 @@
         mShadowContext = shadowOf(context);
 
         File cacheDir = mContext.getCacheDir();
-        mBaseStateDir = new File(cacheDir, "base_state_dir");
-        mDataDir = new File(cacheDir, "data_dir");
+        // Corresponds to /data/backup
+        mBaseStateDir = new File(cacheDir, "base_state");
+        // Corresponds to /cache/backup_stage
+        mDataDir = new File(cacheDir, "data");
 
         ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null);
     }
@@ -126,13 +129,6 @@
         ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null);
     }
 
-    private void uncaughtException(Thread thread, Throwable e) {
-        // Unrelated exceptions are thrown in the backup thread. Until we mock everything properly
-        // we should not fail tests because of this. This is not flakiness, the exceptions thrown
-        // don't interfere with the tests.
-        ShadowLog.e(TAG, "Uncaught exception in test thread " + thread.getName(), e);
-    }
-
     /* Tests for destination string */
 
     @Test
@@ -670,7 +666,7 @@
     }
 
     private void tearDownForRequestBackup() {
-        ShadowPerformBackupTask.reset();
+        ShadowKeyValueBackupTask.reset();
     }
 
     @Test
@@ -757,12 +753,12 @@
 
         assertThat(result).isEqualTo(BackupManager.SUCCESS);
         verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_BACKUP_NOT_ALLOWED);
-        // TODO: We probably don't need to kick-off PerformBackupTask when list is empty
+        // TODO: We probably don't need to kick-off KeyValueBackupTask when list is empty
         tearDownForRequestBackup();
     }
 
     @Test
-    @Config(shadows = ShadowPerformBackupTask.class)
+    @Config(shadows = ShadowKeyValueBackupTask.class)
     public void testRequestBackup_whenPackageIsKeyValue() throws Exception {
         setUpForRequestBackup(PACKAGE_1);
         BackupManagerService backupManagerService = createBackupManagerServiceForRequestBackup();
@@ -771,15 +767,15 @@
 
         mShadowBackupLooper.runToEndOfTasks();
         assertThat(result).isEqualTo(BackupManager.SUCCESS);
-        ShadowPerformBackupTask shadowTask = ShadowPerformBackupTask.getLastCreated();
-        assertThat(shadowTask.getQueue()).containsExactly(new BackupRequest(PACKAGE_1));
+        ShadowKeyValueBackupTask shadowTask = ShadowKeyValueBackupTask.getLastCreated();
+        assertThat(shadowTask.getQueue()).containsExactly(PACKAGE_1);
         assertThat(shadowTask.getPendingFullBackups()).isEmpty();
-        // TODO: Assert more about PerformBackupTask
+        // TODO: Assert more about KeyValueBackupTask
         tearDownForRequestBackup();
     }
 
     @Test
-    @Config(shadows = ShadowPerformBackupTask.class)
+    @Config(shadows = ShadowKeyValueBackupTask.class)
     public void testRequestBackup_whenPackageIsFullBackup() throws Exception {
         setUpForRequestBackup(PACKAGE_1);
         ShadowAppBackupUtils.setAppGetsFullBackup(PACKAGE_1);
@@ -789,10 +785,10 @@
 
         mShadowBackupLooper.runToEndOfTasks();
         assertThat(result).isEqualTo(BackupManager.SUCCESS);
-        ShadowPerformBackupTask shadowTask = ShadowPerformBackupTask.getLastCreated();
+        ShadowKeyValueBackupTask shadowTask = ShadowKeyValueBackupTask.getLastCreated();
         assertThat(shadowTask.getQueue()).isEmpty();
         assertThat(shadowTask.getPendingFullBackups()).containsExactly(PACKAGE_1);
-        // TODO: Assert more about PerformBackupTask
+        // TODO: Assert more about KeyValueBackupTask
         tearDownForRequestBackup();
     }
 
@@ -864,22 +860,8 @@
     }
 
     private BackupManagerService createInitializedBackupManagerService() {
-        BackupManagerService backupManagerService =
-                new BackupManagerService(
-                        mContext,
-                        new Trampoline(mContext),
-                        mBackupThread,
-                        mBaseStateDir,
-                        mDataDir,
-                        mTransportManager);
-        mShadowBackupLooper.runToEndOfTasks();
-        // Handler instances have their own clock, so advancing looper (with runToEndOfTasks())
-        // above does NOT advance the handlers' clock, hence whenever a handler post messages with
-        // specific time to the looper the time of those messages will be before the looper's time.
-        // To fix this we advance SystemClock as well since that is from where the handlers read
-        // time.
-        ShadowSystemClock.setCurrentTimeMillis(mShadowBackupLooper.getScheduler().getCurrentTime());
-        return backupManagerService;
+        return BackupManagerServiceTestUtils.createInitializedBackupManagerService(
+                mContext, mBackupThread, mBaseStateDir, mDataDir, mTransportManager);
     }
 
     private void setUpPowerManager(BackupManagerService backupManagerService) {
diff --git a/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
new file mode 100644
index 0000000..dd0a58d
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.Handler;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class KeyValueBackupJobTest {
+    private Context mContext;
+    private BackupManagerConstants mConstants;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = RuntimeEnvironment.application;
+        mConstants = new BackupManagerConstants(Handler.getMain(), mContext.getContentResolver());
+        mConstants.start();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mConstants.stop();
+        KeyValueBackupJob.cancel(mContext);
+    }
+
+    @Test
+    public void testIsScheduled_beforeScheduling_returnsFalse() {
+        boolean isScheduled = KeyValueBackupJob.isScheduled();
+
+        assertThat(isScheduled).isFalse();
+    }
+
+    @Test
+    public void testIsScheduled_afterScheduling_returnsTrue() {
+        KeyValueBackupJob.schedule(mContext, mConstants);
+
+        boolean isScheduled = KeyValueBackupJob.isScheduled();
+
+        assertThat(isScheduled).isTrue();
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
deleted file mode 100644
index 88a51a5..0000000
--- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
+++ /dev/null
@@ -1,821 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.backup;
-
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper;
-import static com.android.server.backup.testing.TestUtils.uncheck;
-import static com.android.server.backup.testing.TransportData.backupTransport;
-import static com.google.common.truth.Truth.assertThat;
-import static java.util.Collections.emptyList;
-import static java.util.stream.Collectors.toCollection;
-import static java.util.stream.Collectors.toList;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.intThat;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.robolectric.Shadows.shadowOf;
-
-import android.app.Application;
-import android.app.IBackupAgent;
-import android.app.backup.BackupAgent;
-import android.app.backup.BackupDataInput;
-import android.app.backup.BackupDataOutput;
-import android.app.backup.BackupManager;
-import android.app.backup.BackupTransport;
-import android.app.backup.IBackupManager;
-import android.app.backup.IBackupManagerMonitor;
-import android.app.backup.IBackupObserver;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.DeadObjectException;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.platform.test.annotations.Presubmit;
-import android.util.Pair;
-import com.android.internal.backup.IBackupTransport;
-import com.android.server.backup.internal.BackupHandler;
-import com.android.server.backup.internal.BackupRequest;
-import com.android.server.backup.internal.OnTaskFinishedListener;
-import com.android.server.backup.internal.PerformBackupTask;
-import com.android.server.backup.testing.TransportData;
-import com.android.server.backup.testing.TransportTestUtils;
-import com.android.server.backup.testing.TransportTestUtils.TransportMock;
-import com.android.server.backup.transport.TransportClient;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
-import com.android.server.testing.shadows.ShadowBackupDataInput;
-import com.android.server.testing.shadows.ShadowBackupDataOutput;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Stream;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLooper;
-import org.robolectric.shadows.ShadowPackageManager;
-import org.robolectric.shadows.ShadowQueuedWork;
-
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {
-            ShadowBackupDataInput.class,
-            ShadowBackupDataOutput.class,
-            ShadowQueuedWork.class
-        })
-@SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
-@SystemLoaderClasses({IBackupTransport.class, IBackupAgent.class, PackageInfo.class})
-@Presubmit
-public class PerformBackupTaskTest {
-    private static final String PACKAGE_1 = "com.example.package1";
-    private static final String PACKAGE_2 = "com.example.package2";
-
-    @Mock private BackupManagerService mBackupManagerService;
-    @Mock private TransportManager mTransportManager;
-    @Mock private DataChangedJournal mDataChangedJournal;
-    @Mock private IBackupObserver mObserver;
-    @Mock private IBackupManagerMonitor mMonitor;
-    @Mock private OnTaskFinishedListener mListener;
-    private TransportData mTransport;
-    private ShadowLooper mShadowBackupLooper;
-    private BackupHandler mBackupHandler;
-    private PowerManager.WakeLock mWakeLock;
-    private ShadowPackageManager mShadowPackageManager;
-    private FakeIBackupManager mBackupManager;
-    private File mBaseStateDir;
-    private Application mApplication;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        mTransport = backupTransport();
-
-        mApplication = RuntimeEnvironment.application;
-        File cacheDir = mApplication.getCacheDir();
-        mBaseStateDir = new File(cacheDir, "base_state_dir");
-        File dataDir = new File(cacheDir, "data_dir");
-        assertThat(mBaseStateDir.mkdir()).isTrue();
-        assertThat(dataDir.mkdir()).isTrue();
-
-        PackageManager packageManager = mApplication.getPackageManager();
-        mShadowPackageManager = shadowOf(packageManager);
-
-        mWakeLock = createBackupWakeLock(mApplication);
-
-        Looper backupLooper = startBackupThreadAndGetLooper();
-        mShadowBackupLooper = shadowOf(backupLooper);
-
-        Handler mainHandler = new Handler(Looper.getMainLooper());
-        BackupAgentTimeoutParameters agentTimeoutParameters =
-                new BackupAgentTimeoutParameters(mainHandler, mApplication.getContentResolver());
-        agentTimeoutParameters.start();
-
-        // We need to mock BMS timeout parameters before initializing the BackupHandler since
-        // the constructor of BackupHandler relies on the timeout parameters.
-        when(mBackupManagerService.getAgentTimeoutParameters()).thenReturn(agentTimeoutParameters);
-        mBackupHandler = new BackupHandler(mBackupManagerService, backupLooper);
-
-        mBackupManager = spy(FakeIBackupManager.class);
-
-        BackupManagerConstants constants =
-                new BackupManagerConstants(mainHandler, mApplication.getContentResolver());
-        constants.start();
-
-        setUpBackupManagerServiceBasics(
-                mBackupManagerService,
-                mApplication,
-                mTransportManager,
-                packageManager,
-                mBackupHandler,
-                mWakeLock,
-                agentTimeoutParameters);
-        when(mBackupManagerService.getBaseStateDir()).thenReturn(mBaseStateDir);
-        when(mBackupManagerService.getDataDir()).thenReturn(dataDir);
-        when(mBackupManagerService.getBackupManagerBinder()).thenReturn(mBackupManager);
-        when(mBackupManagerService.getConstants()).thenReturn(constants);
-        when(mBackupManagerService.makeMetadataAgent()).thenAnswer(invocation -> createPmAgent());
-    }
-
-    @Test
-    public void testRunTask_whenTransportProvidesFlags_passesThemToTheAgent() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        AgentMock agentMock = setUpAgent(PACKAGE_1);
-        int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
-        when(transportMock.transport.getTransportFlags()).thenReturn(flags);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        verify(agentMock.agent)
-                .onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
-    }
-
-    @Test
-    public void testRunTask_whenTransportDoesNotProvidesFlags() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        AgentMock agentMock = setUpAgent(PACKAGE_1);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        verify(agentMock.agent).onBackup(any(), argThat(dataOutputWithTransportFlags(0)), any());
-    }
-
-    @Test
-    public void testRunTask_whenTransportProvidesFlagsAndMultipleAgents_passesToAll()
-            throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        List<AgentMock> agentMocks = setUpAgents(PACKAGE_1, PACKAGE_2);
-        BackupAgent agent1 = agentMocks.get(0).agent;
-        BackupAgent agent2 = agentMocks.get(1).agent;
-        int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
-        when(transportMock.transport.getTransportFlags()).thenReturn(flags);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        PACKAGE_1,
-                        PACKAGE_2);
-
-        runTask(task);
-
-        verify(agent1).onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
-        verify(agent2).onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
-    }
-
-    @Test
-    public void testRunTask_whenTransportChangeFlagsAfterTaskCreation() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        AgentMock agentMock = setUpAgent(PACKAGE_1);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-        int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
-        when(transportMock.transport.getTransportFlags()).thenReturn(flags);
-
-        runTask(task);
-
-        verify(agentMock.agent)
-                .onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
-    }
-
-    @Test
-    public void testRunTask_callsListenerAndObserver() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        setUpAgent(PACKAGE_1);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        verify(mListener).onFinished(any());
-        verify(mObserver).backupFinished(eq(BackupManager.SUCCESS));
-    }
-
-    @Test
-    public void testRunTask_releasesWakeLock() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        setUpAgent(PACKAGE_1);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        assertThat(mWakeLock.isHeld()).isFalse();
-    }
-
-    @Test
-    public void testRunTask_callsTransportPerformBackupWithAgentData() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        IBackupTransport transportBinder = transportMock.transport;
-        AgentMock agentMock = setUpAgent(PACKAGE_1);
-        agentOnBackupDo(
-                agentMock.agent,
-                (oldState, dataOutput, newState) -> {
-                    writeData(dataOutput, "key1", "foo".getBytes());
-                    writeData(dataOutput, "key2", "bar".getBytes());
-                });
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-        // We need to verify at call time because the file is deleted right after
-        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
-                .then(this::mockAndVerifyTransportPerformBackupData);
-
-        runTask(task);
-
-        // Already verified data in mockAndVerifyPerformBackupData
-        verify(transportBinder).performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
-    }
-
-    private int mockAndVerifyTransportPerformBackupData(InvocationOnMock invocation)
-            throws IOException {
-        ParcelFileDescriptor data = invocation.getArgument(1);
-
-        // Verifying that what we passed to the transport is what the agent wrote
-        BackupDataInput dataInput = new BackupDataInput(data.getFileDescriptor());
-
-        // "key1" => "foo"
-        assertThat(dataInput.readNextHeader()).isTrue();
-        assertThat(dataInput.getKey()).isEqualTo("key1");
-        int size1 = dataInput.getDataSize();
-        byte[] data1 = new byte[size1];
-        dataInput.readEntityData(data1, 0, size1);
-        assertThat(data1).isEqualTo("foo".getBytes());
-
-        // "key2" => "bar"
-        assertThat(dataInput.readNextHeader()).isTrue();
-        assertThat(dataInput.getKey()).isEqualTo("key2");
-        int size2 = dataInput.getDataSize();
-        byte[] data2 = new byte[size2];
-        dataInput.readEntityData(data2, 0, size2);
-        assertThat(data2).isEqualTo("bar".getBytes());
-
-        // No more
-        assertThat(dataInput.readNextHeader()).isFalse();
-
-        return BackupTransport.TRANSPORT_OK;
-    }
-
-    @Test
-    public void testRunTask_whenPerformBackupSucceeds_callsTransportFinishBackup()
-            throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        IBackupTransport transportBinder = transportMock.transport;
-        setUpAgentWithData(PACKAGE_1);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
-                .thenReturn(BackupTransport.TRANSPORT_OK);
-
-        runTask(task);
-
-        verify(transportBinder).finishBackup();
-    }
-
-    @Test
-    public void testRunTask_whenProhibitedKey_failsAgent() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        AgentMock agentMock = setUpAgent(PACKAGE_1);
-        agentOnBackupDo(
-                agentMock.agent,
-                (oldState, dataOutput, newState) -> {
-                    char prohibitedChar = 0xff00;
-                    writeData(dataOutput, prohibitedChar + "key", "foo".getBytes());
-                });
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        verify(mListener).onFinished(any());
-        verify(mObserver).onResult(eq(PACKAGE_1), eq(BackupManager.ERROR_AGENT_FAILURE));
-        verify(agentMock.agentBinder).fail(any());
-        verify(mObserver).backupFinished(BackupManager.SUCCESS);
-    }
-
-    @Test
-    public void testRunTask_whenFirstAgentKeyProhibitedButLastPermitted() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        List<AgentMock> agentMocks = setUpAgents(PACKAGE_1, PACKAGE_2);
-        AgentMock agentMock1 = agentMocks.get(0);
-        AgentMock agentMock2 = agentMocks.get(1);
-        agentOnBackupDo(
-                agentMock1.agent,
-                (oldState, dataOutput, newState) -> {
-                    char prohibitedChar = 0xff00;
-                    writeData(dataOutput, prohibitedChar + "key", "foo".getBytes());
-                });
-        agentOnBackupDo(
-                agentMock2.agent,
-                (oldState, dataOutput, newState) -> {
-                    writeData(dataOutput, "key", "bar".getBytes());
-                });
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        PACKAGE_1,
-                        PACKAGE_2);
-
-        runTask(task);
-
-        verify(mListener).onFinished(any());
-        verify(mObserver).onResult(eq(PACKAGE_1), eq(BackupManager.ERROR_AGENT_FAILURE));
-        verify(agentMock1.agentBinder).fail(any());
-        verify(mObserver).onResult(eq(PACKAGE_2), eq(BackupManager.SUCCESS));
-        verify(mObserver).backupFinished(BackupManager.SUCCESS);
-    }
-
-    @Test
-    public void testRunTask_whenTransportUnavailable() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport.unavailable());
-        setUpAgentWithData(PACKAGE_1);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        verify(mListener).onFinished(any());
-        verify(mObserver).backupFinished(eq(BackupManager.ERROR_TRANSPORT_ABORTED));
-    }
-
-    @Test
-    public void testRunTask_whenTransportRejectsPackage() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        setUpAgentWithData(PACKAGE_1);
-        when(transportMock.transport.performBackup(
-                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
-                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
-        verify(mObserver).backupFinished(BackupManager.SUCCESS);
-    }
-
-    @Test
-    public void testRunTask_whenTransportRejectsFirstPackageButLastSucceeds() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        IBackupTransport transportBinder = transportMock.transport;
-        setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
-        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
-                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
-        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt()))
-                .thenReturn(BackupTransport.TRANSPORT_OK);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        PACKAGE_1,
-                        PACKAGE_2);
-
-        runTask(task);
-
-        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
-        verify(mObserver).onResult(PACKAGE_2, BackupManager.SUCCESS);
-        verify(mObserver).backupFinished(BackupManager.SUCCESS);
-    }
-
-    @Test
-    public void testRunTask_whenTransportRejectsLastPackageButFirstSucceeds() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        IBackupTransport transportBinder = transportMock.transport;
-        setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
-        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
-                .thenReturn(BackupTransport.TRANSPORT_OK);
-        when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt()))
-                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        PACKAGE_1,
-                        PACKAGE_2);
-
-        runTask(task);
-
-        verify(mObserver).onResult(PACKAGE_1, BackupManager.SUCCESS);
-        verify(mObserver).onResult(PACKAGE_2, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
-        verify(mObserver).backupFinished(BackupManager.SUCCESS);
-    }
-
-    @Test
-    public void testRunTask_whenTransportReturnsQuotaExceeded() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
-        when(transportMock.transport.performBackup(
-                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
-                .thenReturn(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
-        verify(mObserver).backupFinished(BackupManager.SUCCESS);
-        verify(agentMock.agent).onQuotaExceeded(anyLong(), anyLong());
-    }
-
-    @Test
-    public void testRunTask_whenAgentUnknown() throws Exception {
-        // Not calling setUpAgent()
-        TransportMock transportMock = setUpTransport(mTransport);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
-
-        runTask(task);
-
-        verify(transportMock.transport, never()).performBackup(any(), any(), anyInt());
-        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_PACKAGE_NOT_FOUND);
-        verify(mObserver).backupFinished(BackupManager.SUCCESS);
-    }
-
-    @Test
-    public void testRunTask_whenNonIncrementalAndTransportRequestsNonIncremental()
-            throws Exception {
-        // It's going to be non-incremental because we haven't created any previous state
-        TransportMock transportMock = setUpTransport(mTransport);
-        setUpAgentWithData(PACKAGE_1);
-        when(transportMock.transport.performBackup(
-                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
-                .thenReturn(BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        true,
-                        PACKAGE_1);
-
-        runTask(task);
-
-        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_ABORTED);
-        verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
-    }
-
-    @Test
-    public void testRunTask_whenIncrementalAndTransportRequestsNonIncremental() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
-        IBackupTransport transport = transportMock.transport;
-        when(transport.performBackup(
-                        argThat(packageInfo(PACKAGE_1)),
-                        any(),
-                        intThat(flags -> (flags & BackupTransport.FLAG_INCREMENTAL) != 0)))
-                .thenReturn(BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED);
-        when(transport.performBackup(
-                        argThat(packageInfo(PACKAGE_1)),
-                        any(),
-                        intThat(flags -> (flags & BackupTransport.FLAG_NON_INCREMENTAL) != 0)))
-                .thenReturn(BackupTransport.TRANSPORT_OK);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        false,
-                        PACKAGE_1);
-        // Write content to be incremental
-        Files.write(
-                Paths.get(mBaseStateDir.getAbsolutePath(), mTransport.transportDirName, PACKAGE_1),
-                "existent".getBytes());
-
-        runTask(task);
-
-        verify(agentMock.agent, times(2)).onBackup(any(), any(), any());
-        verify(mObserver).onResult(PACKAGE_1, BackupManager.SUCCESS);
-        verify(mObserver).backupFinished(BackupManager.SUCCESS);
-    }
-
-    @Test
-    public void testRunTask_whenQueueEmpty() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient, mTransport.transportDirName, true);
-
-        runTask(task);
-
-        verify(mObserver).backupFinished(eq(BackupManager.SUCCESS));
-    }
-
-    @Test
-    public void testRunTask_whenIncrementalAndTransportUnavailableDuringPmBackup()
-            throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        IBackupTransport transportBinder = transportMock.transport;
-        setUpAgent(PACKAGE_1);
-        when(transportBinder.getBackupQuota(
-                        eq(BackupManagerService.PACKAGE_MANAGER_SENTINEL), anyBoolean()))
-                .thenThrow(DeadObjectException.class);
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        false,
-                        PACKAGE_1);
-
-        runTask(task);
-
-        verify(mListener).onFinished(any());
-        verify(mObserver).backupFinished(eq(BackupManager.ERROR_TRANSPORT_ABORTED));
-    }
-
-    @Test
-    public void testRunTask_whenIncrementalAndAgentFails() throws Exception {
-        TransportMock transportMock = setUpTransport(mTransport);
-        createFakePmAgent();
-        PerformBackupTask task =
-                createPerformBackupTask(
-                        transportMock.transportClient,
-                        mTransport.transportDirName,
-                        false,
-                        PACKAGE_1);
-
-        runTask(task);
-
-        verify(mListener).onFinished(any());
-        verify(mObserver).backupFinished(eq(BackupManager.ERROR_TRANSPORT_ABORTED));
-    }
-
-    private void runTask(PerformBackupTask task) {
-        Message message = mBackupHandler.obtainMessage(BackupHandler.MSG_BACKUP_RESTORE_STEP, task);
-        mBackupHandler.sendMessage(message);
-        while (mShadowBackupLooper.getScheduler().areAnyRunnable()) {
-            mShadowBackupLooper.runToEndOfTasks();
-        }
-    }
-
-    private TransportMock setUpTransport(TransportData transport) throws Exception {
-        TransportMock transportMock =
-                TransportTestUtils.setUpTransport(mTransportManager, transport);
-        File stateDir = new File(mBaseStateDir, transport.transportDirName);
-        assertThat(stateDir.mkdir()).isTrue();
-        return transportMock;
-    }
-
-    private List<AgentMock> setUpAgents(String... packageNames) {
-        return Stream.of(packageNames).map(this::setUpAgent).collect(toList());
-    }
-
-    private AgentMock setUpAgent(String packageName) {
-        try {
-            PackageInfo packageInfo = new PackageInfo();
-            packageInfo.packageName = packageName;
-            packageInfo.applicationInfo = new ApplicationInfo();
-            packageInfo.applicationInfo.flags = ApplicationInfo.FLAG_ALLOW_BACKUP;
-            packageInfo.applicationInfo.backupAgentName = "BackupAgent" + packageName;
-            packageInfo.applicationInfo.packageName = packageName;
-            mShadowPackageManager.setApplicationEnabledSetting(
-                    packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
-            mShadowPackageManager.addPackage(packageInfo);
-            BackupAgent backupAgent = spy(BackupAgent.class);
-            IBackupAgent backupAgentBinder =
-                    spy(IBackupAgent.Stub.asInterface(backupAgent.onBind()));
-            // Don't crash our only process (in production code this would crash the app, not us)
-            doNothing().when(backupAgentBinder).fail(any());
-            when(mBackupManagerService.bindToAgentSynchronous(
-                            eq(packageInfo.applicationInfo), anyInt()))
-                    .thenReturn(backupAgentBinder);
-            return new AgentMock(backupAgentBinder, backupAgent);
-        } catch (RemoteException e) {
-            // Never happens, compiler happy
-            throw new AssertionError(e);
-        }
-    }
-
-    private List<AgentMock> setUpAgentsWithData(String... packageNames) {
-        return Stream.of(packageNames).map(this::setUpAgentWithData).collect(toList());
-    }
-
-    private AgentMock setUpAgentWithData(String packageName) {
-        AgentMock agentMock = setUpAgent(packageName);
-        uncheck(
-                () ->
-                        agentOnBackupDo(
-                                agentMock.agent,
-                                (oldState, dataOutput, newState) ->
-                                        writeData(dataOutput, "key", packageName.getBytes())));
-        return agentMock;
-    }
-
-    private PerformBackupTask createPerformBackupTask(
-            TransportClient transportClient, String transportDirName, String... packages) {
-        return createPerformBackupTask(transportClient, transportDirName, true, packages);
-    }
-
-    private PerformBackupTask createPerformBackupTask(
-            TransportClient transportClient,
-            String transportDirName,
-            boolean nonIncremental,
-            String... packages) {
-        ArrayList<BackupRequest> backupRequests =
-                Stream.of(packages).map(BackupRequest::new).collect(toCollection(ArrayList::new));
-        mWakeLock.acquire();
-        PerformBackupTask task =
-                new PerformBackupTask(
-                        mBackupManagerService,
-                        transportClient,
-                        transportDirName,
-                        backupRequests,
-                        mDataChangedJournal,
-                        mObserver,
-                        mMonitor,
-                        mListener,
-                        emptyList(),
-                        /* userInitiated */ false,
-                        nonIncremental);
-        mBackupManager.setUp(mBackupHandler, task);
-        return task;
-    }
-
-    private PackageManagerBackupAgent createPmAgent() {
-        PackageManagerBackupAgent pmAgent =
-                new PackageManagerBackupAgent(mApplication.getPackageManager());
-        pmAgent.attach(mApplication);
-        pmAgent.onCreate();
-        return pmAgent;
-    }
-
-    /**
-     * Returns an implementation of PackageManagerBackupAgent that throws RuntimeException in {@link
-     * BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)}
-     */
-    private PackageManagerBackupAgent createFakePmAgent() {
-        PackageManagerBackupAgent fakePmAgent =
-                new FakePackageManagerBackupAgent(mApplication.getPackageManager());
-        fakePmAgent.attach(mApplication);
-        fakePmAgent.onCreate();
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(fakePmAgent);
-        return fakePmAgent;
-    }
-
-    /** Matches {@link PackageInfo} whose package name is {@code packageName}. */
-    private static ArgumentMatcher<PackageInfo> packageInfo(String packageName) {
-        // We have to test for packageInfo nulity because of Mockito's own stubbing with argThat().
-        // E.g. if you do:
-        //
-        //   1. when(object.method(argThat(str -> str.equals("foo")))).thenReturn(0)
-        //   2. when(object.method(argThat(str -> str.equals("bar")))).thenReturn(2)
-        //
-        // The second line will throw NPE because it will call lambda 1 with null, since argThat()
-        // returns null. So we guard against that by checking for null.
-        return packageInfo -> packageInfo != null && packageName.equals(packageInfo.packageName);
-    }
-
-    private static ArgumentMatcher<BackupDataOutput> dataOutputWithTransportFlags(int flags) {
-        return dataOutput -> dataOutput.getTransportFlags() == flags;
-    }
-
-    private static void writeData(BackupDataOutput dataOutput, String key, byte[] data)
-            throws IOException {
-        dataOutput.writeEntityHeader(key, data.length);
-        dataOutput.writeEntityData(data, data.length);
-    }
-
-    private static void agentOnBackupDo(BackupAgent agent, BackupAgentOnBackup function)
-            throws Exception {
-        doAnswer(function).when(agent).onBackup(any(), any(), any());
-    }
-
-    @FunctionalInterface
-    private interface BackupAgentOnBackup extends Answer<Void> {
-        void onBackup(
-                ParcelFileDescriptor oldState,
-                BackupDataOutput dataOutput,
-                ParcelFileDescriptor newState)
-                throws IOException;
-
-        @Override
-        default Void answer(InvocationOnMock invocation) throws Throwable {
-            onBackup(
-                    invocation.getArgument(0),
-                    invocation.getArgument(1),
-                    invocation.getArgument(2));
-            return null;
-        }
-    }
-
-    private static class AgentMock {
-        private final IBackupAgent agentBinder;
-        private final BackupAgent agent;
-
-        private AgentMock(IBackupAgent agentBinder, BackupAgent agent) {
-            this.agentBinder = agentBinder;
-            this.agent = agent;
-        }
-    }
-
-    private abstract static class FakeIBackupManager extends IBackupManager.Stub {
-        private Handler mBackupHandler;
-        private BackupRestoreTask mTask;
-
-        public FakeIBackupManager() {}
-
-        private void setUp(Handler backupHandler, BackupRestoreTask task) {
-            mBackupHandler = backupHandler;
-            mTask = task;
-        }
-
-        @Override
-        public void opComplete(int token, long result) throws RemoteException {
-            assertThat(mTask).isNotNull();
-            Message message =
-                    mBackupHandler.obtainMessage(
-                            BackupHandler.MSG_OP_COMPLETE, Pair.create(mTask, result));
-            mBackupHandler.sendMessage(message);
-        }
-    }
-
-    private static class FakePackageManagerBackupAgent extends PackageManagerBackupAgent {
-        public FakePackageManagerBackupAgent(PackageManager packageMgr) {
-            super(packageMgr);
-        }
-
-        @Override
-        public void onBackup(
-                ParcelFileDescriptor oldState,
-                BackupDataOutput data,
-                ParcelFileDescriptor newState) {
-            throw new RuntimeException();
-        }
-    }
-}
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
new file mode 100644
index 0000000..9d6b8d5
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -0,0 +1,2287 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.keyvalue;
+
+import static android.app.backup.BackupManager.ERROR_AGENT_FAILURE;
+import static android.app.backup.BackupManager.ERROR_BACKUP_NOT_ALLOWED;
+import static android.app.backup.BackupManager.ERROR_PACKAGE_NOT_FOUND;
+import static android.app.backup.BackupManager.ERROR_TRANSPORT_ABORTED;
+import static android.app.backup.BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED;
+import static android.app.backup.BackupManager.SUCCESS;
+import static android.app.backup.ForwardingBackupAgent.forward;
+
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createInitializedBackupManagerService;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBinderCallerAndApplicationAsSystem;
+import static com.android.server.backup.testing.PackageData.PM_PACKAGE;
+import static com.android.server.backup.testing.PackageData.fullBackupPackage;
+import static com.android.server.backup.testing.PackageData.keyValuePackage;
+import static com.android.server.backup.testing.TestUtils.assertEventLogged;
+import static com.android.server.backup.testing.TestUtils.messagesInLooper;
+import static com.android.server.backup.testing.TestUtils.uncheck;
+import static com.android.server.backup.testing.TestUtils.waitUntil;
+import static com.android.server.backup.testing.TransportData.backupTransport;
+import static com.android.server.backup.testing.Utils.oneTimeIterable;
+
+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.anyLong;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.intThat;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+import static org.robolectric.shadow.api.Shadow.extract;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static java.util.Collections.emptyList;
+import static java.util.stream.Collectors.toList;
+
+import android.annotation.Nullable;
+import android.app.Application;
+import android.app.IBackupAgent;
+import android.app.backup.BackupAgent;
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupManager;
+import android.app.backup.BackupTransport;
+import android.app.backup.IBackupCallback;
+import android.app.backup.IBackupManager;
+import android.app.backup.IBackupManagerMonitor;
+import android.app.backup.IBackupObserver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.ConditionVariable;
+import android.os.DeadObjectException;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.util.Pair;
+
+import com.android.internal.backup.IBackupTransport;
+import com.android.server.EventLogTags;
+import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.BackupRestoreTask;
+import com.android.server.backup.DataChangedJournal;
+import com.android.server.backup.KeyValueBackupJob;
+import com.android.server.backup.PackageManagerBackupAgent;
+import com.android.server.backup.TransportManager;
+import com.android.server.backup.internal.BackupHandler;
+import com.android.server.backup.internal.OnTaskFinishedListener;
+import com.android.server.backup.testing.PackageData;
+import com.android.server.backup.testing.TestUtils.ThrowingRunnable;
+import com.android.server.backup.testing.TransportData;
+import com.android.server.backup.testing.TransportTestUtils;
+import com.android.server.backup.testing.TransportTestUtils.TransportMock;
+import com.android.server.backup.testing.Utils;
+import com.android.server.backup.transport.TransportClient;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderClasses;
+import com.android.server.testing.SystemLoaderPackages;
+import com.android.server.testing.shadows.FrameworkShadowLooper;
+import com.android.server.testing.shadows.ShadowBackupDataInput;
+import com.android.server.testing.shadows.ShadowBackupDataOutput;
+import com.android.server.testing.shadows.ShadowEventLog;
+
+import com.google.common.truth.IterableSubject;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowPackageManager;
+import org.robolectric.shadows.ShadowQueuedWork;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Stream;
+
+// TODO: When returning to RUNNING_QUEUE vs FINAL, RUNNING_QUEUE sets status = OK. Why? Verify?
+// TODO: Check queue in general, behavior w/ multiple packages
+// TODO: Test PM invocation
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+        manifest = Config.NONE,
+        sdk = 26,
+        shadows = {
+            FrameworkShadowLooper.class,
+            ShadowBackupDataInput.class,
+            ShadowBackupDataOutput.class,
+            ShadowEventLog.class,
+            ShadowQueuedWork.class,
+        })
+@SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
+@SystemLoaderClasses({IBackupTransport.class, IBackupAgent.class, PackageInfo.class})
+@Presubmit
+public class KeyValueBackupTaskTest {
+    private static final PackageData PACKAGE_1 = keyValuePackage(1);
+    private static final PackageData PACKAGE_2 = keyValuePackage(2);
+    private static final String BACKUP_AGENT_SHARED_PREFS_SYNCHRONIZER_CLASS =
+            "android.app.backup.BackupAgent$SharedPrefsSynchronizer";
+
+    @Mock private TransportManager mTransportManager;
+    @Mock private DataChangedJournal mOldJournal;
+    @Mock private IBackupObserver mObserver;
+    @Mock private IBackupManagerMonitor mMonitor;
+    @Mock private OnTaskFinishedListener mListener;
+    private BackupManagerService mBackupManagerService;
+    private TransportData mTransport;
+    private ShadowLooper mShadowBackupLooper;
+    private Handler mBackupHandler;
+    private PowerManager.WakeLock mWakeLock;
+    private ShadowPackageManager mShadowPackageManager;
+    private FakeIBackupManager mBackupManager;
+    private File mBaseStateDir;
+    private File mDataDir;
+    private Application mApplication;
+    private ShadowApplication mShadowApplication;
+    private Looper mMainLooper;
+    private FrameworkShadowLooper mShadowMainLooper;
+    private Context mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mTransport = backupTransport();
+
+        mApplication = RuntimeEnvironment.application;
+        mShadowApplication = shadowOf(mApplication);
+        mContext = mApplication;
+
+        mMainLooper = Looper.getMainLooper();
+        mShadowMainLooper = extract(mMainLooper);
+
+        File cacheDir = mApplication.getCacheDir();
+        // Corresponds to /data/backup
+        mBaseStateDir = new File(cacheDir, "base_state");
+        // Corresponds to /cache/backup_stage
+        mDataDir = new File(cacheDir, "data");
+        // We create here simulating init.rc
+        mDataDir.mkdirs();
+        assertThat(mDataDir.isDirectory()).isTrue();
+
+        PackageManager packageManager = mApplication.getPackageManager();
+        mShadowPackageManager = shadowOf(packageManager);
+
+        mWakeLock = createBackupWakeLock(mApplication);
+
+        mBackupManager = spy(FakeIBackupManager.class);
+
+        // Needed to be able to use a real BMS instead of a mock
+        setUpBinderCallerAndApplicationAsSystem(mApplication);
+        mBackupManagerService =
+                spy(
+                        createInitializedBackupManagerService(
+                                mContext, mBaseStateDir, mDataDir, mTransportManager));
+        setUpBackupManagerServiceBasics(
+                mBackupManagerService,
+                mApplication,
+                mTransportManager,
+                packageManager,
+                mBackupManagerService.getBackupHandler(),
+                mWakeLock,
+                mBackupManagerService.getAgentTimeoutParameters());
+        when(mBackupManagerService.getBaseStateDir()).thenReturn(mBaseStateDir);
+        when(mBackupManagerService.getDataDir()).thenReturn(mDataDir);
+        when(mBackupManagerService.getBackupManagerBinder()).thenReturn(mBackupManager);
+
+        mBackupHandler = mBackupManagerService.getBackupHandler();
+        mShadowBackupLooper = shadowOf(mBackupHandler.getLooper());
+        ShadowEventLog.setUp();
+    }
+
+    @Test
+    public void testRunTask_whenQueueEmpty_updatesBookkeeping() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, true);
+
+        runTask(task);
+
+        assertThat(mBackupManagerService.getPendingInits()).isEmpty();
+        assertThat(mBackupManagerService.isBackupRunning()).isFalse();
+        assertThat(mBackupManagerService.getCurrentOperations().size()).isEqualTo(0);
+        verify(mOldJournal).delete();
+    }
+
+    @Test
+    public void testRunTask_whenQueueEmpty_releasesWakeLock() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, true);
+
+        runTask(task);
+
+        assertThat(mWakeLock.isHeld()).isFalse();
+    }
+
+    @Test
+    public void testRunTask_whenQueueEmpty_doesNotProduceData() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, true);
+
+        runTask(task);
+
+        assertDirectory(getStateDirectory(mTransport)).isEmpty();
+        assertDirectory(mDataDir.toPath()).isEmpty();
+    }
+
+    @Test
+    public void testRunTask_whenQueueEmpty_doesNotCallTransport() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, true);
+
+        runTask(task);
+
+        verify(transportMock.transport, never()).initializeDevice();
+        verify(transportMock.transport, never()).performBackup(any(), any(), anyInt());
+        verify(transportMock.transport, never()).finishBackup();
+    }
+
+    @Test
+    public void testRunTask_whenQueueEmpty_notifiesCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(mBackupManagerService.getCurrentToken()).thenReturn(0L);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, true);
+
+        runTask(task);
+
+        verify(mListener).onFinished(any());
+        verify(mObserver, never()).onResult(any(), anyInt());
+        verify(mObserver).backupFinished(SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenQueueEmpty_doesNotChangeStateFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, true);
+        Files.write(getStateFile(mTransport, PM_PACKAGE), "pmState".getBytes());
+        Files.write(getStateFile(mTransport, PACKAGE_1), "packageState".getBytes());
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PM_PACKAGE)))
+                .isEqualTo("pmState".getBytes());
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1)))
+                .isEqualTo("packageState".getBytes());
+    }
+
+    @Test
+    public void testRunTask_whenOnePackageAndTransportUnavailable() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport.unavailable());
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mListener).onFinished(any());
+        verify(mObserver).backupFinished(ERROR_TRANSPORT_ABORTED);
+        assertBackupPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenOnePackage_logsBackupStartEvent() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertEventLogged(EventLogTags.BACKUP_START, mTransport.transportName);
+    }
+
+    @Test
+    public void testRunTask_whenOnePackage_releasesWakeLock() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(mWakeLock.isHeld()).isFalse();
+    }
+
+    @Test
+    public void testRunTask_whenOnePackage_updatesBookkeeping() throws Exception {
+        // Transport has to be initialized to not reset current token
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        mBackupManagerService.setCurrentToken(0L);
+        when(transportMock.transport.getCurrentRestoreSet()).thenReturn(1234L);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(mBackupManagerService.getPendingInits()).isEmpty();
+        assertThat(mBackupManagerService.isBackupRunning()).isFalse();
+        assertThat(mBackupManagerService.getCurrentOperations().size()).isEqualTo(0);
+        assertThat(mBackupManagerService.getCurrentToken()).isEqualTo(1234L);
+        verify(mBackupManagerService).writeRestoreTokens();
+        verify(mOldJournal).delete();
+    }
+
+    @Test
+    public void testRunTask_whenPackageWithOldStateAndIncremental_passesOldStateToAgent()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        false,
+                        PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        assertThat(agentMock.oldState).isEqualTo("oldState".getBytes());
+    }
+
+    @Test
+    public void testRunTask_whenPackageWithOldStateAndNonIncremental_passesEmptyOldStateToAgent()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        true,
+                        PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        assertThat(agentMock.oldState).isEqualTo(new byte[0]);
+    }
+
+    @Test
+    public void testRunTask_whenNonPmPackageAndNonIncremental_doesNotBackUpPm() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PackageManagerBackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        true,
+                        PACKAGE_1);
+
+        runTask(task);
+
+        verify(pmAgent, never()).onBackup(any(), any(), any());
+    }
+
+    @Test
+    public void testRunTask_whenNonPmPackageAndPmAndNonIncremental_backsUpPm() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PackageManagerBackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        true,
+                        PACKAGE_1,
+                        PM_PACKAGE);
+
+        runTask(task);
+
+        verify(pmAgent).onBackup(any(), any(), any());
+    }
+
+    @Test
+    public void testRunTask_whenNonPmPackageAndIncremental_backsUpPm() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        PackageManagerBackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        false,
+                        PACKAGE_1);
+
+        runTask(task);
+
+        verify(pmAgent).onBackup(any(), any(), any());
+    }
+
+    @Test
+    public void testRunTask_whenOnePackageAndNoPmState_initializesTransportAndResetsState()
+            throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        // Need 2 packages to be able to verify state of package not involved in the task
+        setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        deletePmStateFile();
+        Files.write(getStateFile(mTransport, PACKAGE_2), "package2State".getBytes());
+
+        runTask(task);
+
+        verify(transportMock.transport).initializeDevice();
+        verify(mBackupManagerService).resetBackupState(getStateDirectory(mTransport).toFile());
+        // Verifying that it deleted all the states (can't verify package 1 because it generated a
+        // new state in this task execution)
+        assertThat(Files.exists(getStateFile(mTransport, PACKAGE_2))).isFalse();
+        assertEventLogged(EventLogTags.BACKUP_INITIALIZE);
+    }
+
+    @Test
+    public void testRunTask_whenOnePackageAndWithPmState_doesNotInitializeTransportOrResetState()
+            throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        createPmStateFile();
+        Files.write(getStateFile(mTransport, PACKAGE_2), "package2State".getBytes());
+
+        runTask(task);
+
+        verify(transportMock.transport, never()).initializeDevice();
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_2)))
+                .isEqualTo("package2State".getBytes());
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsErrorForInitialization() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        when(transportMock.transport.initializeDevice())
+                .thenReturn(BackupTransport.TRANSPORT_ERROR);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        deletePmStateFile();
+
+        runTask(task);
+
+        // First for initialization and second because of the transport failure
+        verify(mBackupManagerService, times(2))
+                .resetBackupState(getStateDirectory(mTransport).toFile());
+        verify(agentMock.agent, never()).onBackup(any(), any(), any());
+        verify(transportMock.transport, never()).performBackup(any(), any(), anyInt());
+        assertBackupPendingFor(PACKAGE_1);
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
+    }
+
+    @Test
+    public void testRunTask_whenTransportThrowsDuringInitialization() throws Exception {
+        TransportMock transportMock = setUpTransport(mTransport);
+        when(transportMock.transport.initializeDevice()).thenThrow(RemoteException.class);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        deletePmStateFile();
+
+        runTask(task);
+
+        // First for initialization and second because of the transport failure
+        verify(mBackupManagerService, times(2))
+                .resetBackupState(getStateDirectory(mTransport).toFile());
+        verify(agentMock.agent, never()).onBackup(any(), any(), any());
+        verify(transportMock.transport, never()).performBackup(any(), any(), anyInt());
+        assertBackupPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenPackageNotEligibleForBackup() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1.backupNotAllowed());
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(agentMock.agent, never()).onBackup(any(), any(), any());
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_BACKUP_NOT_ALLOWED);
+        verify(mObserver).backupFinished(SUCCESS);
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenPackageDoesFullBackup() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        PackageData packageData = fullBackupPackage(1);
+        AgentMock agentMock = setUpAgentWithData(packageData);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, packageData);
+
+        runTask(task);
+
+        verify(agentMock.agent, never()).onBackup(any(), any(), any());
+        verify(agentMock.agent, never()).onFullBackup(any());
+        verify(mObserver).onResult(packageData.packageName, ERROR_BACKUP_NOT_ALLOWED);
+        verify(mObserver).backupFinished(SUCCESS);
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenPackageIsStopped() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1.stopped());
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(agentMock.agent, never()).onBackup(any(), any(), any());
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_BACKUP_NOT_ALLOWED);
+        verify(mObserver).backupFinished(SUCCESS);
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenPackageUnknown() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        // Not calling setUpAgent()
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_PACKAGE_NOT_FOUND);
+        verify(mObserver).backupFinished(SUCCESS);
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenCallingAgent_setsWakeLockWorkSource() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    // In production (for non-system agents) the call is asynchronous, but here is
+                    // synchronous, so it's fine to verify here.
+                    // Verify has set work source and hasn't unset yet.
+                    verify(mBackupManagerService)
+                            .setWorkSource(
+                                    argThat(workSource -> workSource.get(0) == PACKAGE_1.uid));
+                    verify(mBackupManagerService, never()).setWorkSource(null);
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        // More verifications inside agent call above
+        verify(mBackupManagerService).setWorkSource(null);
+    }
+
+    /**
+     * Agent unavailable means {@link BackupManagerService#bindToAgentSynchronous(ApplicationInfo,
+     * int)} returns {@code null}.
+     *
+     * @see #setUpAgent(PackageData)
+     */
+    @Test
+    public void testRunTask_whenAgentUnavailable() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1.unavailable());
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).setWorkSource(null);
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
+        verify(mObserver).backupFinished(BackupManager.SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenBindToAgentThrowsSecurityException() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        doThrow(SecurityException.class)
+                .when(mBackupManagerService)
+                .bindToAgentSynchronous(argThat(applicationInfo(PACKAGE_1)), anyInt());
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).setWorkSource(null);
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
+        verify(mObserver).backupFinished(BackupManager.SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenTransportGetBackupQuotaThrows_notifiesCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
+                .thenThrow(DeadObjectException.class);
+        setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mObserver, never()).onResult(eq(PACKAGE_1.packageName), anyInt());
+        verify(mObserver).backupFinished(ERROR_TRANSPORT_ABORTED);
+        verify(mListener).onFinished(any());
+    }
+
+    @Test
+    public void testRunTask_whenTransportGetBackupQuotaThrows_cleansUp() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
+                .thenThrow(DeadObjectException.class);
+        setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).setWorkSource(null);
+        verify(mBackupManagerService).unbindAgent(argThat(applicationInfo(PACKAGE_1)));
+    }
+
+    @Test
+    public void testRunTask_whenTransportGetBackupQuotaThrows_doesNotTouchFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
+                .thenThrow(DeadObjectException.class);
+        setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "packageState".getBytes());
+
+        runTask(task);
+
+        assertThat(Files.exists(getTemporaryStateFile(mTransport, PACKAGE_1))).isFalse();
+        assertThat(Files.exists(getStagingFile(PACKAGE_1))).isFalse();
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1)))
+                .isEqualTo("packageState".getBytes());
+    }
+
+    @Test
+    public void testRunTask_whenTransportGetBackupQuotaThrows_revertsOperation() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
+                .thenThrow(DeadObjectException.class);
+        setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(transportMock.transport).requestBackupTime();
+        assertBackupPendingFor(PACKAGE_1);
+        assertThat(KeyValueBackupJob.isScheduled()).isTrue();
+    }
+
+    /**
+     * For local agents the exception is thrown in our stack, so it hits the catch clause around
+     * invocation earlier than the {@link KeyValueBackupTask#operationComplete(long)} code-path,
+     * invalidating the latter. Note that this happens because {@link
+     * BackupManagerService#opComplete(int, long)} schedules the actual execution to the backup
+     * handler.
+     */
+    @Test
+    public void testRunTask_whenLocalAgentOnBackupThrows() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    throw new RuntimeException();
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).setWorkSource(null);
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
+        verify(mObserver).backupFinished(SUCCESS);
+        assertEventLogged(
+                EventLogTags.BACKUP_AGENT_FAILURE,
+                PACKAGE_1.packageName,
+                new RuntimeException().toString());
+        assertBackupPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenTransportProvidesFlags_passesThemToTheAgent() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
+        when(transportMock.transport.getTransportFlags()).thenReturn(flags);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(agentMock.agent)
+                .onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
+    }
+
+    @Test
+    public void testRunTask_whenTransportDoesNotProvidesFlags() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(agentMock.agent).onBackup(any(), argThat(dataOutputWithTransportFlags(0)), any());
+    }
+
+    @Test
+    public void testRunTask_whenTransportProvidesFlagsAndMultipleAgents_passesToAll()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
+        when(transportMock.transport.getTransportFlags()).thenReturn(flags);
+        List<AgentMock> agentMocks = setUpAgents(PACKAGE_1, PACKAGE_2);
+        BackupAgent agent1 = agentMocks.get(0).agent;
+        BackupAgent agent2 = agentMocks.get(1).agent;
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        PACKAGE_1,
+                        PACKAGE_2);
+
+        runTask(task);
+
+        verify(agent1).onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
+        verify(agent2).onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
+    }
+
+    @Test
+    public void testRunTask_whenTransportChangeFlagsAfterTaskCreation() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
+        when(transportMock.transport.getTransportFlags()).thenReturn(flags);
+
+        runTask(task);
+
+        verify(agentMock.agent)
+                .onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any());
+    }
+
+    @Test
+    public void testRunTask_whenAgentUsesProhibitedKey_failsAgent() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    char prohibitedChar = 0xff00;
+                    writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(agentMock.agentBinder).fail(any());
+        verify(mBackupManagerService).unbindAgent(argThat(applicationInfo(PACKAGE_1)));
+    }
+
+    @Test
+    public void testRunTask_whenAgentUsesProhibitedKey_updatesAndCleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    char prohibitedChar = 0xff00;
+                    writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1)))
+                .isEqualTo("oldState".getBytes());
+        assertThat(Files.exists(getTemporaryStateFile(mTransport, PACKAGE_1))).isFalse();
+        assertThat(Files.exists(getStagingFile(PACKAGE_1))).isFalse();
+    }
+
+    @Test
+    public void testRunTask_whenAgentUsesProhibitedKey_doesNotCallTransport() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    char prohibitedChar = 0xff00;
+                    writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+    }
+
+    @Test
+    public void testRunTask_whenAgentUsesProhibitedKey_notifiesCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    char prohibitedChar = 0xff00;
+                    writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        verify(mListener).onFinished(any());
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
+        verify(mObserver).backupFinished(SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenAgentUsesProhibitedKey_logsAgentFailureEvent() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    char prohibitedChar = 0xff00;
+                    writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        assertEventLogged(EventLogTags.BACKUP_AGENT_FAILURE, PACKAGE_1.packageName, "bad key");
+    }
+
+    @Test
+    public void testRunTask_whenFirstAgentUsesProhibitedKeyButLastAgentUsesPermittedKey()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        List<AgentMock> agentMocks = setUpAgents(PACKAGE_1, PACKAGE_2);
+        AgentMock agentMock1 = agentMocks.get(0);
+        AgentMock agentMock2 = agentMocks.get(1);
+        agentOnBackupDo(
+                agentMock1,
+                (oldState, dataOutput, newState) -> {
+                    char prohibitedChar = 0xff00;
+                    writeData(dataOutput, prohibitedChar + "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        agentOnBackupDo(
+                agentMock2,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        PACKAGE_1,
+                        PACKAGE_2);
+
+        runTask(task);
+
+        verify(mListener).onFinished(any());
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
+        verify(agentMock1.agentBinder).fail(any());
+        verify(mObserver).onResult(PACKAGE_2.packageName, SUCCESS);
+        verify(mObserver).backupFinished(SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenAgentDoesNotWriteData_doesNotCallTransport() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    // No-op
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+    }
+
+    @Test
+    public void testRunTask_whenAgentDoesNotWriteData_logsEvents() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    // No-op
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertEventLogged(EventLogTags.BACKUP_PACKAGE, PACKAGE_1.packageName, 0L);
+        verify(mBackupManagerService).logBackupComplete(PACKAGE_1.packageName);
+    }
+
+    @Test
+    public void testRunTask_whenAgentDoesNotWriteData_notifiesCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    // No-op
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mObserver).onResult(PACKAGE_1.packageName, SUCCESS);
+        verify(mObserver).backupFinished(SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenAgentDoesNotWriteData_updatesBookkeeping() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    // No-op
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenAgentDoesNotWriteData_updatesAndCleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    // No-op
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1))).isEqualTo(new byte[0]);
+        assertThat(Files.exists(getTemporaryStateFile(mTransport, PACKAGE_1))).isFalse();
+        assertThat(Files.exists(getStagingFile(PACKAGE_1))).isFalse();
+    }
+
+    @Test
+    public void testRunTask_whenAgentWritesData_callsTransportPerformBackupWithAgentData()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        Path backupDataPath = createTemporaryFile();
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .then(copyBackupDataTo(backupDataPath));
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key1", "data1".getBytes());
+                    writeData(dataOutput, "key2", "data2".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(transportMock.transport)
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+        // Now verify data sent
+        try (FileInputStream inputStream = new FileInputStream(backupDataPath.toFile())) {
+            BackupDataInput backupData = new BackupDataInput(inputStream.getFD());
+            assertDataHasKeyValue(backupData, "key1", "data1".getBytes());
+            assertDataHasKeyValue(backupData, "key2", "data2".getBytes());
+            assertThat(backupData.readNextHeader()).isFalse();
+        }
+    }
+
+    @Test
+    public void testRunTask_whenPerformBackupSucceeds_callsTransportFinishBackup()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_OK);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        // First for PM, then for the package
+        verify(transportMock.transport, times(2)).finishBackup();
+    }
+
+    @Test
+    public void testRunTask_whenFinishBackupSucceeds_updatesAndCleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.finishBackup()).thenReturn(BackupTransport.TRANSPORT_OK);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1)))
+                .isEqualTo("newState".getBytes());
+        assertThat(Files.exists(getTemporaryStateFile(mTransport, PACKAGE_1))).isFalse();
+        assertThat(Files.exists(getStagingFile(PACKAGE_1))).isFalse();
+    }
+
+    @Test
+    public void testRunTask_whenFinishBackupSucceeds_logsBackupPackageEvent() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        Path backupData = createTemporaryFile();
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .then(copyBackupDataTo(backupData));
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertEventLogged(
+                EventLogTags.BACKUP_PACKAGE, PACKAGE_1.packageName, Files.size(backupData));
+    }
+
+    @Test
+    public void testRunTask_whenFinishBackupSucceeds_notifiesCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).logBackupComplete(PACKAGE_1.packageName);
+        verify(mObserver).onResult(PACKAGE_1.packageName, SUCCESS);
+        verify(mObserver).backupFinished(SUCCESS);
+        verify(mListener).onFinished(any());
+    }
+
+    @Test
+    public void testRunTask_whenFinishBackupSucceeds_updatesBookkeeping() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsPackage_doesNotCallFinishBackup() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        // Called only for PM
+        verify(transportMock.transport, times(1)).finishBackup();
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsPackage_updatesAndCleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1)))
+                .isEqualTo("oldState".getBytes());
+        assertThat(Files.exists(getTemporaryStateFile(mTransport, PACKAGE_1))).isFalse();
+        assertThat(Files.exists(getStagingFile(PACKAGE_1))).isFalse();
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsPackage_logsAgentFailureEvent() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertEventLogged(
+                EventLogTags.BACKUP_AGENT_FAILURE, PACKAGE_1.packageName, "Transport rejected");
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsPackage_notifiesCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_TRANSPORT_PACKAGE_REJECTED);
+        verify(mObserver).backupFinished(SUCCESS);
+        verify(mListener).onFinished(any());
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsPackage_updatesBookkeeping() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsFirstPackageButLastSucceeds() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_2)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_OK);
+        setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        PACKAGE_1,
+                        PACKAGE_2);
+
+        runTask(task);
+
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_TRANSPORT_PACKAGE_REJECTED);
+        verify(mObserver).onResult(PACKAGE_2.packageName, SUCCESS);
+        verify(mObserver).backupFinished(SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenTransportRejectsLastPackageButFirstSucceeds() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_OK);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_2)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        PACKAGE_1,
+                        PACKAGE_2);
+
+        runTask(task);
+
+        verify(mObserver).onResult(PACKAGE_1.packageName, SUCCESS);
+        verify(mObserver).onResult(PACKAGE_2.packageName, ERROR_TRANSPORT_PACKAGE_REJECTED);
+        verify(mObserver).backupFinished(SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsQuotaExceeded() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
+                .thenReturn(1234L);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mObserver)
+                .onResult(PACKAGE_1.packageName, BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
+        verify(mObserver).backupFinished(SUCCESS);
+        verify(agentMock.agent).onQuotaExceeded(anyLong(), eq(1234L));
+        assertEventLogged(EventLogTags.BACKUP_QUOTA_EXCEEDED, PACKAGE_1.packageName);
+        assertBackupNotPendingFor(PACKAGE_1);
+        // TODO: Assert about state/staging files (possible bug)
+    }
+
+    @Test
+    public void testRunTask_whenNonIncrementalAndTransportRequestsNonIncremental()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        true,
+                        PACKAGE_1);
+        // Delete to be non-incremental
+        Files.deleteIfExists(getStateFile(mTransport, PACKAGE_1));
+
+        runTask(task);
+
+        // Error because it was non-incremental already, so transport can't request it
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_TRANSPORT_ABORTED);
+        verify(mObserver).backupFinished(ERROR_TRANSPORT_ABORTED);
+    }
+
+    @Test
+    public void testRunTask_whenIncrementalAndTransportRequestsNonIncremental() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        Path incrementalData = createTemporaryFile();
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)),
+                        any(),
+                        intThat(flags -> (flags & BackupTransport.FLAG_INCREMENTAL) != 0)))
+                .thenAnswer(
+                        copyBackupDataAndReturn(
+                                incrementalData,
+                                BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED));
+        Path nonIncrementalData = createTemporaryFile();
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)),
+                        any(),
+                        intThat(flags -> (flags & BackupTransport.FLAG_NON_INCREMENTAL) != 0)))
+                .thenAnswer(
+                        copyBackupDataAndReturn(nonIncrementalData, BackupTransport.TRANSPORT_OK));
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    // agentMock.oldState has already been updated by now.
+                    if (agentMock.oldState.length > 0) {
+                        writeData(dataOutput, "key", "dataForIncremental".getBytes());
+                        writeState(newState, "stateForIncremental".getBytes());
+                    } else {
+                        writeData(dataOutput, "key", "dataForNonIncremental".getBytes());
+                        writeState(newState, "stateForNonIncremental".getBytes());
+                    }
+                });
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        false,
+                        PACKAGE_1);
+        // Write state to be incremental
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        verify(agentMock.agent, times(2)).onBackup(any(), any(), any());
+        byte[] oldStateDuringIncremental = agentMock.oldStateHistory.get(0);
+        byte[] oldStateDuringNonIncremental = agentMock.oldStateHistory.get(1);
+        assertThat(oldStateDuringIncremental).isEqualTo("oldState".getBytes());
+        assertThat(oldStateDuringNonIncremental).isEqualTo(new byte[0]);
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1)))
+                .isEqualTo("stateForNonIncremental".getBytes());
+        try (FileInputStream inputStream = new FileInputStream(incrementalData.toFile())) {
+            BackupDataInput backupData = new BackupDataInput(inputStream.getFD());
+            assertDataHasKeyValue(backupData, "key", "dataForIncremental".getBytes());
+            assertThat(backupData.readNextHeader()).isFalse();
+        }
+        try (FileInputStream inputStream = new FileInputStream(nonIncrementalData.toFile())) {
+            BackupDataInput backupData = new BackupDataInput(inputStream.getFD());
+            assertDataHasKeyValue(backupData, "key", "dataForNonIncremental".getBytes());
+            assertThat(backupData.readNextHeader()).isFalse();
+        }
+        verify(mObserver).onResult(PACKAGE_1.packageName, SUCCESS);
+        verify(mObserver).backupFinished(SUCCESS);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsError_notifiesCorrectly() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_ERROR);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_TRANSPORT_ABORTED);
+        verify(mObserver).backupFinished(ERROR_TRANSPORT_ABORTED);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsError_logsBackupTransportFailureEvent()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_ERROR);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_FAILURE, PACKAGE_1.packageName);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsError_revertsOperation() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_ERROR);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(transportMock.transport).requestBackupTime();
+        assertBackupPendingFor(PACKAGE_1);
+        assertThat(KeyValueBackupJob.isScheduled()).isTrue();
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsError_updatesAndCleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_ERROR);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes());
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1)))
+                .isEqualTo("oldState".getBytes());
+        // TODO: These should be true (Bug)
+        // assertThat(Files.exists(getTemporaryStateFile(mTransport, PACKAGE_1))).isFalse();
+        // assertThat(Files.exists(getStagingFile(PACKAGE_1))).isFalse();
+    }
+
+    @Test
+    public void testRunTask_whenTransportGetBackupQuotaThrowsForPm() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.getBackupQuota(PM_PACKAGE.packageName, false))
+                .thenThrow(DeadObjectException.class);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mListener).onFinished(any());
+        verify(mObserver).backupFinished(ERROR_TRANSPORT_ABORTED);
+        assertEventLogged(
+                EventLogTags.BACKUP_AGENT_FAILURE,
+                PM_PACKAGE.packageName,
+                new DeadObjectException().toString());
+    }
+
+    @Test
+    public void testRunTask_whenPmAgentFails() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        PackageManagerBackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mListener).onFinished(any());
+        verify(mObserver).backupFinished(eq(ERROR_TRANSPORT_ABORTED));
+        assertEventLogged(
+                EventLogTags.BACKUP_AGENT_FAILURE,
+                PM_PACKAGE.packageName,
+                new RuntimeException().toString());
+    }
+
+    @Test
+    public void testRunTask_whenBackupRunning_doesNotThrow() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(mBackupManagerService.isBackupOperationInProgress()).thenReturn(true);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName);
+
+        runTask(task);
+    }
+
+    @Test
+    public void
+            testRunTask_whenMarkCancelDuringFirstAgentOnBackup_doesNotCallTransportAfterWaitCancel()
+                    throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        setUpAgentsWithData(PACKAGE_2);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        PACKAGE_1,
+                        PACKAGE_2);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                    runInWorkerThread(task::markCancel);
+                });
+
+        ConditionVariable taskFinished = runTaskAsync(task);
+
+        verifyAndUnblockAgentCalls(2);
+        task.waitCancel();
+        reset(transportMock.transport);
+        taskFinished.block();
+        verifyZeroInteractions(transportMock.transport);
+    }
+
+    @Test
+    public void testRunTask_whenMarkCancelDuringAgentOnBackup_doesNotCallTransportForPackage()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                    runInWorkerThread(task::markCancel);
+                });
+
+        ConditionVariable taskFinished = runTaskAsync(task);
+
+        verifyAndUnblockAgentCalls(2);
+        taskFinished.block();
+        // For PM
+        verify(transportMock.transport, times(1)).finishBackup();
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+    }
+
+    @Test
+    public void testRunTask_whenMarkCancelDuringTransportPerformBackup_callsTransportForPackage()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenAnswer(
+                        invocation -> {
+                            runInWorkerThread(task::markCancel);
+                            return BackupTransport.TRANSPORT_OK;
+                        });
+
+        ConditionVariable taskFinished = runTaskAsync(task);
+
+        verifyAndUnblockAgentCalls(2);
+        taskFinished.block();
+        InOrder inOrder = inOrder(transportMock.transport);
+        inOrder.verify(transportMock.transport)
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+        inOrder.verify(transportMock.transport).finishBackup();
+    }
+
+    @Test
+    public void
+            testRunTask_whenMarkCancelDuringSecondAgentOnBackup_callsTransportForFirstPackageButNotForSecond()
+                    throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        AgentMock agentMock = setUpAgent(PACKAGE_2);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        PACKAGE_1,
+                        PACKAGE_2);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                    runInWorkerThread(task::markCancel);
+                });
+
+        ConditionVariable taskFinished = runTaskAsync(task);
+
+        verifyAndUnblockAgentCalls(3);
+        taskFinished.block();
+        InOrder inOrder = inOrder(transportMock.transport);
+        inOrder.verify(transportMock.transport)
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+        inOrder.verify(transportMock.transport).finishBackup();
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt());
+    }
+
+    @Test
+    public void
+            testRunTask_whenMarkCancelDuringTransportPerformBackupForFirstPackage_callsTransportForFirstPackageButNotForSecond()
+                    throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentsWithData(PACKAGE_1, PACKAGE_2);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient,
+                        mTransport.transportDirName,
+                        PACKAGE_1,
+                        PACKAGE_2);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
+                .thenAnswer(
+                        invocation -> {
+                            runInWorkerThread(task::markCancel);
+                            return BackupTransport.TRANSPORT_OK;
+                        });
+
+        ConditionVariable taskFinished = runTaskAsync(task);
+
+        verifyAndUnblockAgentCalls(2);
+        taskFinished.block();
+        InOrder inOrder = inOrder(transportMock.transport);
+        inOrder.verify(transportMock.transport)
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+        inOrder.verify(transportMock.transport).finishBackup();
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt());
+    }
+
+    @Test
+    public void testRunTask_afterMarkCancel_doesNotCallAgentOrTransport() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        task.markCancel();
+
+        runTask(task);
+
+        verify(agentMock.agent, never()).onBackup(any(), any(), any());
+        verify(transportMock.transport, never()).performBackup(any(), any(), anyInt());
+        verify(transportMock.transport, never()).finishBackup();
+    }
+
+    @Test
+    public void testWaitCancel_afterCancelledTaskFinished_returns() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        task.markCancel();
+        runTask(task);
+
+        task.waitCancel();
+    }
+
+    @Test
+    public void testWaitCancel_whenMarkCancelDuringAgentOnBackup_unregistersTask() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                    runInWorkerThread(task::markCancel);
+                });
+        ConditionVariable taskFinished = runTaskAsync(task);
+        verifyAndUnblockAgentCalls(1);
+        boolean backupInProgressDuringBackup = mBackupManagerService.isBackupOperationInProgress();
+        assertThat(backupInProgressDuringBackup).isTrue();
+        verifyAndUnblockAgentCalls(1);
+
+        task.waitCancel();
+
+        boolean backupInProgressAfterWaitCancel =
+                mBackupManagerService.isBackupOperationInProgress();
+        assertThat(backupInProgressDuringBackup).isTrue();
+        assertThat(backupInProgressAfterWaitCancel).isFalse();
+        taskFinished.block();
+    }
+
+    @Test
+    public void testMarkCancel_afterTaskFinished_returns() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
+        KeyValueBackupTask task =
+                createKeyValueBackupTask(
+                        transportMock.transportClient, mTransport.transportDirName, PACKAGE_1);
+        runTask(task);
+
+        task.markCancel();
+    }
+
+    private void runTask(KeyValueBackupTask task) {
+        // Pretend we are not on the main-thread to prevent RemoteCall from complaining
+        mShadowMainLooper.setCurrentThread(false);
+        task.run();
+        mShadowMainLooper.reset();
+        assertTaskPostConditions();
+    }
+
+    private ConditionVariable runTaskAsync(KeyValueBackupTask task) {
+        return runInWorkerThreadAsync(task::run);
+    }
+
+    private static ConditionVariable runInWorkerThreadAsync(ThrowingRunnable runnable) {
+        ConditionVariable finished = new ConditionVariable(false);
+        new Thread(
+                        () -> {
+                            uncheck(runnable);
+                            finished.open();
+                        },
+                        "test-worker-thread")
+                .start();
+        return finished;
+    }
+
+    private static void runInWorkerThread(ThrowingRunnable runnable) {
+        runInWorkerThreadAsync(runnable).block();
+    }
+
+    /**
+     * If you have kicked-off the task with {@link #runTaskAsync(KeyValueBackupTask)}, call this to
+     * unblock the task thread that will be waiting for the agent's {@link
+     * IBackupAgent#doBackup(ParcelFileDescriptor, ParcelFileDescriptor, ParcelFileDescriptor, long,
+     * IBackupCallback, int)}.
+     *
+     * @param times The number of {@link IBackupAgent#doBackup(ParcelFileDescriptor,
+     *     ParcelFileDescriptor, ParcelFileDescriptor, long, IBackupCallback, int)} calls. Remember
+     *     to count PM calls.
+     */
+    private void verifyAndUnblockAgentCalls(int times)
+            throws InterruptedException, TimeoutException {
+        // HACK: IBackupAgent.doBackup() posts a runnable to the front of the main-thread queue and
+        // immediately waits for its execution. In Robolectric, if we are in the main-thread this
+        // runnable is executed inline (this is called unpaused looper), that's why when we run the
+        // task in the main-thread (runTask() as opposed to runTaskAsync()) we don't need to call
+        // this method. However, if we are not in the main-thread nobody executes the runnable for
+        // us, thus IBackupAgent code will be stuck waiting for someone to execute the runnable.
+        // This method waits for that *specific* runnable, identifying it via class name, and then
+        // idles the main looper (for 0 seconds because it's posted at the front of the queue),
+        // which executes the method.
+        for (int i = 0; i < times; i++) {
+            waitUntil(() -> messagesInLooper(mMainLooper, this::isSharedPrefsSynchronizer) > 0);
+            mShadowMainLooper.idle();
+        }
+    }
+
+    private boolean isSharedPrefsSynchronizer(@Nullable Message message) {
+        String className = BACKUP_AGENT_SHARED_PREFS_SYNCHRONIZER_CLASS;
+        return message != null
+                && message.getCallback() != null
+                && className.equals(message.getCallback().getClass().getName());
+    }
+
+    private TransportMock setUpTransport(TransportData transport) throws Exception {
+        TransportMock transportMock =
+                TransportTestUtils.setUpTransport(mTransportManager, transport);
+        Files.createDirectories(getStateDirectory(transport));
+        return transportMock;
+    }
+
+    /** Sets up the transport and writes a PM state file in the transport state directory. */
+    private TransportMock setUpInitializedTransport(TransportData transport) throws Exception {
+        TransportMock transportMock = setUpTransport(transport);
+        createPmStateFile(transport);
+        return transportMock;
+    }
+
+    private Path getStateDirectory(TransportData transport) {
+        return mBaseStateDir.toPath().resolve(transport.transportDirName);
+    }
+
+    private Path getStateFile(TransportData transport, PackageData packageData) {
+        return getStateDirectory(transport).resolve(packageData.packageName);
+    }
+
+    private Path getTemporaryStateFile(TransportData transport, PackageData packageData) {
+        return getStateDirectory(transport)
+                .resolve(packageData.packageName + KeyValueBackupTask.NEW_STATE_FILE_SUFFIX);
+    }
+
+    private Path getStagingDirectory() {
+        return mDataDir.toPath();
+    }
+
+    private Path getStagingFile(PackageData packageData) {
+        return getStagingDirectory()
+                .resolve(packageData.packageName + KeyValueBackupTask.STAGING_FILE_SUFFIX);
+    }
+
+    private List<AgentMock> setUpAgents(PackageData... packageNames) {
+        return Stream.of(packageNames).map(this::setUpAgent).collect(toList());
+    }
+
+    private AgentMock setUpAgent(PackageData packageData) {
+        try {
+            mShadowPackageManager.setApplicationEnabledSetting(
+                    packageData.packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
+            PackageInfo packageInfo = getPackageInfo(packageData);
+            mShadowPackageManager.addPackage(packageInfo);
+            mShadowApplication.sendBroadcast(getPackageAddedIntent(packageData));
+            // Run the backup looper because on the receiver we post MSG_SCHEDULE_BACKUP_PACKAGE
+            mShadowBackupLooper.runToEndOfTasks();
+            BackupAgent backupAgent = spy(BackupAgent.class);
+            IBackupAgent backupAgentBinder =
+                    spy(IBackupAgent.Stub.asInterface(backupAgent.onBind()));
+            // Don't crash our only process (in production code this would crash the app, not us)
+            doNothing().when(backupAgentBinder).fail(any());
+            if (packageData.available) {
+                doReturn(backupAgentBinder)
+                        .when(mBackupManagerService)
+                        .bindToAgentSynchronous(argThat(applicationInfo(packageData)), anyInt());
+            } else {
+                doReturn(null)
+                        .when(mBackupManagerService)
+                        .bindToAgentSynchronous(argThat(applicationInfo(packageData)), anyInt());
+            }
+            return new AgentMock(backupAgentBinder, backupAgent);
+        } catch (RemoteException e) {
+            // Never happens, compiler happy
+            throw new AssertionError(e);
+        }
+    }
+
+    private PackageInfo getPackageInfo(PackageData packageData) {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = packageData.packageName;
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.uid = packageData.uid;
+        packageInfo.applicationInfo.flags = packageData.flags();
+        packageInfo.applicationInfo.backupAgentName = packageData.agentName;
+        packageInfo.applicationInfo.packageName = packageData.packageName;
+        return packageInfo;
+    }
+
+    private Intent getPackageAddedIntent(PackageData packageData) {
+        Intent intent =
+                new Intent(
+                        Intent.ACTION_PACKAGE_ADDED,
+                        Uri.parse("package:" + packageData.packageName));
+        intent.putExtra(Intent.EXTRA_UID, packageData.uid);
+        intent.putExtra(Intent.EXTRA_REPLACING, false);
+        intent.putExtra(Intent.EXTRA_USER_HANDLE, 0);
+        return intent;
+    }
+
+    private List<AgentMock> setUpAgentsWithData(PackageData... packages) {
+        return Stream.of(packages).map(this::setUpAgentWithData).collect(toList());
+    }
+
+    private AgentMock setUpAgentWithData(PackageData packageData) {
+        AgentMock agentMock = setUpAgent(packageData);
+        String packageName = packageData.packageName;
+        uncheck(
+                () ->
+                        agentOnBackupDo(
+                                agentMock,
+                                (oldState, dataOutput, newState) -> {
+                                    writeData(dataOutput, "key", ("data" + packageName).getBytes());
+                                    writeState(newState, ("state" + packageName).getBytes());
+                                }));
+        return agentMock;
+    }
+
+    private KeyValueBackupTask createKeyValueBackupTask(
+            TransportClient transportClient, String transportDirName, PackageData... packages) {
+        return createKeyValueBackupTask(transportClient, transportDirName, false, packages);
+    }
+
+    private KeyValueBackupTask createKeyValueBackupTask(
+            TransportClient transportClient,
+            String transportDirName,
+            boolean nonIncremental,
+            PackageData... packages) {
+        List<String> queue =
+                Stream.of(packages).map(packageData -> packageData.packageName).collect(toList());
+        mBackupManagerService.getPendingBackups().clear();
+        // mOldJournal is a mock, but it would be the value returned by BMS.getJournal() now
+        mBackupManagerService.setJournal(null);
+        mWakeLock.acquire();
+        KeyValueBackupTask task =
+                new KeyValueBackupTask(
+                        mBackupManagerService,
+                        transportClient,
+                        transportDirName,
+                        queue,
+                        mOldJournal,
+                        mObserver,
+                        mMonitor,
+                        mListener,
+                        emptyList(),
+                        /* userInitiated */ false,
+                        nonIncremental);
+        mBackupManager.setUp(mBackupHandler, task);
+        return task;
+    }
+
+    private PackageManagerBackupAgent createPmAgent() {
+        PackageManagerBackupAgent pmAgent =
+                new PackageManagerBackupAgent(mApplication.getPackageManager());
+        pmAgent.attach(mApplication);
+        pmAgent.onCreate();
+        return pmAgent;
+    }
+
+    /**
+     * Returns an implementation of PackageManagerBackupAgent that throws RuntimeException in {@link
+     * BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)}
+     */
+    private PackageManagerBackupAgent createThrowingPmAgent(RuntimeException exception) {
+        PackageManagerBackupAgent pmAgent =
+                new ThrowingPackageManagerBackupAgent(mApplication.getPackageManager(), exception);
+        pmAgent.attach(mApplication);
+        pmAgent.onCreate();
+        return pmAgent;
+    }
+
+    /** Matches {@link PackageInfo} whose package name is {@code packageData.packageName}. */
+    private static ArgumentMatcher<PackageInfo> packageInfo(PackageData packageData) {
+        // We have to test for packageInfo nulity because of Mockito's own stubbing with argThat().
+        // E.g. if you do:
+        //
+        //   1. when(object.method(argThat(str -> str.equals("foo")))).thenReturn(0)
+        //   2. when(object.method(argThat(str -> str.equals("bar")))).thenReturn(2)
+        //
+        // The second line will throw NPE because it will call lambda 1 with null, since argThat()
+        // returns null. So we guard against that by checking for null.
+        return packageInfo ->
+                packageInfo != null && packageData.packageName.equals(packageInfo.packageName);
+    }
+
+    /** Matches {@link ApplicationInfo} whose package name is {@code packageData.packageName}. */
+    private static ArgumentMatcher<ApplicationInfo> applicationInfo(PackageData packageData) {
+        return applicationInfo ->
+                applicationInfo != null
+                        && packageData.packageName.equals(applicationInfo.packageName);
+    }
+
+    private static ArgumentMatcher<BackupDataOutput> dataOutputWithTransportFlags(int flags) {
+        return dataOutput -> dataOutput.getTransportFlags() == flags;
+    }
+
+    private static void writeData(BackupDataOutput dataOutput, String key, byte[] data)
+            throws IOException {
+        dataOutput.writeEntityHeader(key, data.length);
+        dataOutput.writeEntityData(data, data.length);
+    }
+
+    private static void writeState(ParcelFileDescriptor newState, byte[] state) throws IOException {
+        OutputStream outputStream = new FileOutputStream(newState.getFileDescriptor());
+        outputStream.write(state);
+        outputStream.flush();
+    }
+
+    /**
+     * This is to prevent the following:
+     *
+     * <ul>
+     *   <li>The transport being initialized with {@link IBackupTransport#initializeDevice()}
+     *   <li>{@link BackupManagerService#resetBackupState(File)} being called, which will:
+     *       <ul>
+     *         <li>Reset processed packages journal.
+     *         <li>Reset current token to 0.
+     *         <li>Delete state files.
+     *         <li>Mark data changed for every key-value participant.
+     *       </ul>
+     * </ul>
+     */
+    private void createPmStateFile() throws IOException {
+        createPmStateFile(mTransport);
+    }
+
+    /** @see #createPmStateFile() */
+    private void createPmStateFile(TransportData transport) throws IOException {
+        Files.write(getStateFile(transport, PM_PACKAGE), "pmState".getBytes());
+    }
+
+    /**
+     * Forces transport initialization and call to {@link
+     * BackupManagerService#resetBackupState(File)}
+     */
+    private void deletePmStateFile() throws IOException {
+        Files.deleteIfExists(getStateFile(mTransport, PM_PACKAGE));
+    }
+
+    /**
+     * Implements {@code function} for {@link BackupAgent#onBackup(ParcelFileDescriptor,
+     * BackupDataOutput, ParcelFileDescriptor)} of {@code agentMock} and populates {@link
+     * AgentMock#oldState}.
+     */
+    private static void agentOnBackupDo(AgentMock agentMock, BackupAgentOnBackup function)
+            throws Exception {
+        doAnswer(
+                        (BackupAgentOnBackup)
+                                (oldState, dataOutput, newState) -> {
+                                    ByteArrayOutputStream outputStream =
+                                            new ByteArrayOutputStream();
+                                    Utils.transferStreamedData(
+                                            new FileInputStream(oldState.getFileDescriptor()),
+                                            outputStream);
+                                    agentMock.oldState = outputStream.toByteArray();
+                                    agentMock.oldStateHistory.add(agentMock.oldState);
+                                    function.onBackup(oldState, dataOutput, newState);
+                                })
+                .when(agentMock.agent)
+                .onBackup(any(), any(), any());
+    }
+
+    /**
+     * Returns an {@link Answer} that can be used for mocking {@link
+     * IBackupTransport#performBackup(PackageInfo, ParcelFileDescriptor, int)} that copies the
+     * backup data received to {@code backupDataPath} and returns {@code result}.
+     */
+    private static Answer<Integer> copyBackupDataAndReturn(Path backupDataPath, int result) {
+        return invocation -> {
+            ParcelFileDescriptor backupDataParcelFd = invocation.getArgument(1);
+            FileDescriptor backupDataFd = backupDataParcelFd.getFileDescriptor();
+            Files.copy(new FileInputStream(backupDataFd), backupDataPath, REPLACE_EXISTING);
+            backupDataParcelFd.close();
+            return result;
+        };
+    }
+
+    /**
+     * Same as {@link #copyBackupDataAndReturn(Path, int)}} with {@code result =
+     * BackupTransport.TRANSPORT_OK}.
+     */
+    private static Answer<Integer> copyBackupDataTo(Path backupDataPath) {
+        return copyBackupDataAndReturn(backupDataPath, BackupTransport.TRANSPORT_OK);
+    }
+
+    private Path createTemporaryFile() throws IOException {
+        return Files.createTempFile(mContext.getCacheDir().toPath(), "backup", ".tmp");
+    }
+
+    private static IterableSubject<
+                    ? extends IterableSubject<?, Path, Iterable<Path>>, Path, Iterable<Path>>
+            assertDirectory(Path directory) throws IOException {
+        return assertThat(oneTimeIterable(Files.newDirectoryStream(directory).iterator()))
+                .named("directory " + directory);
+    }
+
+    private static void assertJournalDoesNotContain(
+            @Nullable DataChangedJournal journal, String packageName) throws IOException {
+        List<String> packages = (journal == null) ? emptyList() : journal.getPackages();
+        assertThat(packages).doesNotContain(packageName);
+    }
+
+    private void assertBackupPendingFor(PackageData packageData) throws IOException {
+        String packageName = packageData.packageName;
+        // We verify the current journal, NOT the old one passed to KeyValueBackupTask constructor
+        assertThat(mBackupManagerService.getJournal().getPackages()).contains(packageName);
+        assertThat(mBackupManagerService.getPendingBackups()).containsKey(packageName);
+    }
+
+    private void assertBackupNotPendingFor(PackageData packageData) throws IOException {
+        String packageName = packageData.packageName;
+        // We verify the current journal, NOT the old one passed to KeyValueBackupTask constructor
+        assertJournalDoesNotContain(mBackupManagerService.getJournal(), packageName);
+        assertThat(mBackupManagerService.getPendingBackups()).doesNotContainKey(packageName);
+    }
+
+    private void assertDataHasKeyValue(BackupDataInput backupData, String key, byte[] value)
+            throws IOException {
+        assertThat(backupData.readNextHeader()).isTrue();
+        assertThat(backupData.getKey()).isEqualTo(key);
+        int size = backupData.getDataSize();
+        byte[] data1 = new byte[size];
+        backupData.readEntityData(data1, 0, size);
+        assertThat(data1).isEqualTo(value);
+    }
+
+    /**
+     * Put conditions that should *always* be true after task execution.
+     *
+     * <p>Note: We should generally NOT do this. For every different set of pre-conditions that
+     * result in different code-paths being executed there should be one test method verifying these
+     * post-conditions. Since there were a couple of methods here already and these post-conditions
+     * are pretty serious to be neglected it was decided to over-verify in this case.
+     */
+    private void assertTaskPostConditions() {
+        assertThat(mWakeLock.isHeld()).isFalse();
+    }
+
+    @FunctionalInterface
+    private interface BackupAgentOnBackup extends Answer<Void> {
+        void onBackup(
+                ParcelFileDescriptor oldState,
+                BackupDataOutput dataOutput,
+                ParcelFileDescriptor newState)
+                throws IOException;
+
+        @Override
+        default Void answer(InvocationOnMock invocation) throws Throwable {
+            onBackup(
+                    invocation.getArgument(0),
+                    invocation.getArgument(1),
+                    invocation.getArgument(2));
+            return null;
+        }
+    }
+
+    private static class AgentMock {
+        private final IBackupAgent agentBinder;
+        private final BackupAgent agent;
+        private final List<byte[]> oldStateHistory = new ArrayList<>();
+        private byte[] oldState;
+
+        private AgentMock(IBackupAgent agentBinder, BackupAgent agent) {
+            this.agentBinder = agentBinder;
+            this.agent = agent;
+        }
+    }
+
+    private abstract static class FakeIBackupManager extends IBackupManager.Stub {
+        private Handler mBackupHandler;
+        private BackupRestoreTask mTask;
+
+        public FakeIBackupManager() {}
+
+        private void setUp(Handler backupHandler, BackupRestoreTask task) {
+            mBackupHandler = backupHandler;
+            mTask = task;
+        }
+
+        @Override
+        public void opComplete(int token, long result) throws RemoteException {
+            assertThat(mTask).isNotNull();
+            Message message =
+                    mBackupHandler.obtainMessage(
+                            BackupHandler.MSG_OP_COMPLETE, Pair.create(mTask, result));
+            mBackupHandler.sendMessage(message);
+        }
+    }
+
+    private static class ThrowingPackageManagerBackupAgent extends PackageManagerBackupAgent {
+        private final RuntimeException mException;
+
+        ThrowingPackageManagerBackupAgent(
+                PackageManager packageManager, RuntimeException exception) {
+            super(packageManager);
+            mException = exception;
+        }
+
+        @Override
+        public void onBackup(
+                ParcelFileDescriptor oldState,
+                BackupDataOutput data,
+                ParcelFileDescriptor newState) {
+            throw mException;
+        }
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
new file mode 100644
index 0000000..aec207d
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.remote;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import java.util.concurrent.CompletableFuture;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class FutureBackupCallbackTest {
+    @Test
+    public void testOperationComplete_completesFuture() throws Exception {
+        CompletableFuture<RemoteResult> future = new CompletableFuture<>();
+        FutureBackupCallback callback = new FutureBackupCallback(future);
+
+        callback.operationComplete(7);
+
+        assertThat(future.get()).isEqualTo(RemoteResult.successful(7));
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
new file mode 100644
index 0000000..55db616
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.remote;
+
+import static com.android.server.backup.testing.TestUtils.runToEndOfTasks;
+import static com.android.server.backup.testing.TestUtils.uncheck;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.IBackupCallback;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.backup.testing.TestUtils.ThrowingRunnable;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class RemoteCallTest {
+    /** A {@link RemoteCallable} that calls the callback immediately. */
+    private final RemoteCallable<IBackupCallback> IMMEDIATE_CALLABLE =
+            callback -> callback.operationComplete(0);
+
+    @Mock private RemoteCallable<IBackupCallback> mCallable;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testCall_whenCancelledAndImmediateCallableAndTimeOut0_returnsCancel()
+            throws Exception {
+        RemoteCall remoteCall = new RemoteCall(true, IMMEDIATE_CALLABLE, 0);
+
+        RemoteResult result = runInWorkerThread(remoteCall::call);
+
+        assertThat(result).isEqualTo(RemoteResult.FAILED_CANCELLED);
+    }
+
+    @Test
+    public void testCall_whenCancelledAndImmediateCallableAndTimeOut0_doesNotCallCallable()
+            throws Exception {
+        RemoteCall remoteCall = new RemoteCall(true, IMMEDIATE_CALLABLE, 0);
+
+        runInWorkerThread(remoteCall::call);
+
+        verify(mCallable, never()).call(any());
+    }
+
+    @Test
+    public void testCall_whenImmediateCallableAndTimeOut0AndCancelIsCalledBeforeCall_returnsCancel()
+            throws Exception {
+        RemoteCall remoteCall = new RemoteCall(IMMEDIATE_CALLABLE, 0);
+        remoteCall.cancel();
+
+        RemoteResult result = runInWorkerThread(remoteCall::call);
+
+        assertThat(result).isEqualTo(RemoteResult.FAILED_CANCELLED);
+    }
+
+    @Test
+    public void
+            testCall_whenImmediateCallableAndTimeOut0AndCancelIsCalledBeforeCall_doesNotCallCallable()
+                    throws Exception {
+        RemoteCall remoteCall = new RemoteCall(IMMEDIATE_CALLABLE, 0);
+        remoteCall.cancel();
+
+        runInWorkerThread(remoteCall::call);
+
+        verify(mCallable, never()).call(any());
+    }
+
+    @Test
+    public void testCall_whenImmediateCallableAndTimeOut0_returnsTimeOut() throws Exception {
+        RemoteCall remoteCall = new RemoteCall(IMMEDIATE_CALLABLE, 0);
+
+        RemoteResult result = runInWorkerThread(remoteCall::call);
+
+        assertThat(result).isEqualTo(RemoteResult.FAILED_TIMED_OUT);
+    }
+
+    @Test
+    public void testCall_whenTimeOut0_doesNotCallCallable() throws Exception {
+        RemoteCall remoteCall = new RemoteCall(mCallable, 0);
+
+        runInWorkerThread(remoteCall::call);
+
+        verify(mCallable, never()).call(any());
+    }
+
+    @Test
+    public void testCall_whenTimesOutBeforeCallbackIsCalled_returnsTimeOut() throws Exception {
+        ConditionVariable scheduled = new ConditionVariable(false);
+        RemoteCall remoteCall =
+                new RemoteCall(
+                        callback -> {
+                            postDelayed(
+                                    Handler.getMain(), () -> callback.operationComplete(0), 1000);
+                            scheduled.open();
+                        },
+                        500);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        // Method runToEndOfTasks() will execute what was posted to the main handler, which is the
+        // completion of the callback and the time-out (that was scheduled by RemoteCall). But to be
+        // able to execute everything we have to ensure that runToEndOfTasks() is called *after*
+        // everything has been scheduled, that's why we use the condition variable scheduled, that
+        // is set to true (i.e. opened) when everything is scheduled, allowing us to run the tasks.
+        scheduled.block();
+        runToEndOfTasks(Looper.getMainLooper());
+        assertThat(result.get()).isEqualTo(RemoteResult.FAILED_TIMED_OUT);
+    }
+
+    @Test
+    public void testCall_whenTimesOutBeforeCancelIsCalled_returnsTimeOut() throws Exception {
+        ConditionVariable scheduled = new ConditionVariable(false);
+        RemoteCall remoteCall = new RemoteCall(callback -> scheduled.open(), 500);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        scheduled.block();
+        runToEndOfTasks(Looper.getMainLooper());
+        remoteCall.cancel();
+        assertThat(result.get()).isEqualTo(RemoteResult.FAILED_TIMED_OUT);
+    }
+
+    @Test
+    public void testCall_whenCallbackIsCalledBeforeTimeOut_returnsSuccess() throws Exception {
+        ConditionVariable scheduled = new ConditionVariable(false);
+        RemoteCall remoteCall =
+                new RemoteCall(
+                        callback -> {
+                            postDelayed(
+                                    Handler.getMain(), () -> callback.operationComplete(3), 500);
+                            scheduled.open();
+                        },
+                        1000);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        scheduled.block();
+        runToEndOfTasks(Looper.getMainLooper());
+        assertThat(result.get()).isEqualTo(RemoteResult.successful(3));
+    }
+
+    @Test
+    public void testCall_whenCallbackIsCalledBeforeCancel_returnsSuccess() throws Exception {
+        CompletableFuture<IBackupCallback> callbackFuture = new CompletableFuture<>();
+        RemoteCall remoteCall = new RemoteCall(callbackFuture::complete, 1000);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        // callbackFuture.get() will return when callable is executed (i.e. inside
+        // remoteCall.call()), at which point we can complete it.
+        IBackupCallback callback = callbackFuture.get();
+        callback.operationComplete(3);
+        remoteCall.cancel();
+        assertThat(result.get()).isEqualTo(RemoteResult.successful(3));
+    }
+
+    @Test
+    public void testCall_whenCancelIsCalledBeforeCallbackButAfterCall_returnsCancel()
+            throws Exception {
+        CompletableFuture<IBackupCallback> callbackFuture = new CompletableFuture<>();
+        RemoteCall remoteCall = new RemoteCall(callbackFuture::complete, 1000);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        IBackupCallback callback = callbackFuture.get();
+        remoteCall.cancel();
+        callback.operationComplete(3);
+        assertThat(result.get()).isEqualTo(RemoteResult.FAILED_CANCELLED);
+    }
+
+    @Test
+    public void testCall_whenCancelIsCalledBeforeTimeOutButAfterCall_returnsCancel()
+            throws Exception {
+        ConditionVariable scheduled = new ConditionVariable(false);
+        RemoteCall remoteCall = new RemoteCall(callback -> scheduled.open(), 1000);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        scheduled.block();
+        remoteCall.cancel();
+        runToEndOfTasks(Looper.getMainLooper());
+        assertThat(result.get()).isEqualTo(RemoteResult.FAILED_CANCELLED);
+    }
+
+    private static <T> Future<T> runInWorkerThreadAsync(Callable<T> supplier) {
+        CompletableFuture<T> future = new CompletableFuture<>();
+        new Thread(() -> future.complete(uncheck(supplier)), "test-worker-thread").start();
+        return future;
+    }
+
+    private static <T> T runInWorkerThread(Callable<T> supplier) throws Exception {
+        return runInWorkerThreadAsync(supplier).get();
+    }
+
+    /** Unchecked version of {@link Handler#postDelayed(Runnable, long)}. */
+    private static void postDelayed(Handler handler, ThrowingRunnable runnable, long delayMillis) {
+        handler.postDelayed(() -> uncheck(runnable), delayMillis);
+    }
+
+    /** Unchecked version of {@link Handler#post(Runnable)}. */
+    private static void post(Handler handler, ThrowingRunnable runnable) {
+        handler.post(() -> uncheck(runnable));
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
new file mode 100644
index 0000000..f1c4f27
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.remote;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.expectThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class RemoteResultTest {
+    @Test
+    public void testSucceeded_whenSuccessfulResult_returnsTrue() {
+        RemoteResult result = RemoteResult.successful(3);
+
+        boolean succeeded = result.succeeded();
+
+        assertThat(succeeded).isTrue();
+    }
+
+    @Test
+    public void testSucceeded_whenFailedResults_returnsFalse() {
+        boolean timeOutSucceeded = RemoteResult.FAILED_TIMED_OUT.succeeded();
+        boolean cancelledSucceeded = RemoteResult.FAILED_CANCELLED.succeeded();
+        boolean threadInterruptedSucceeded = RemoteResult.FAILED_THREAD_INTERRUPTED.succeeded();
+
+        assertThat(timeOutSucceeded).isFalse();
+        assertThat(cancelledSucceeded).isFalse();
+        assertThat(threadInterruptedSucceeded).isFalse();
+    }
+
+    @Test
+    public void testGet_whenSuccessfulResult_returnsValue() {
+        RemoteResult result = RemoteResult.successful(7);
+
+        long value = result.get();
+
+        assertThat(value).isEqualTo(7);
+    }
+
+    @Test
+    public void testGet_whenFailedResult_throws() {
+        RemoteResult result = RemoteResult.FAILED_TIMED_OUT;
+
+        expectThrows(IllegalStateException.class, result::get);
+    }
+
+    @Test
+    public void testToString() {
+        assertThat(RemoteResult.successful(3).toString()).isEqualTo("RemoteResult{3}");
+        assertThat(RemoteResult.FAILED_TIMED_OUT.toString())
+                .isEqualTo("RemoteResult{FAILED_TIMED_OUT}");
+        assertThat(RemoteResult.FAILED_CANCELLED.toString())
+                .isEqualTo("RemoteResult{FAILED_CANCELLED}");
+        assertThat(RemoteResult.FAILED_THREAD_INTERRUPTED.toString())
+                .isEqualTo("RemoteResult{FAILED_THREAD_INTERRUPTED}");
+    }
+
+    @Test
+    public void testEquals() {
+        assertThat(RemoteResult.successful(3).equals(RemoteResult.successful(3))).isTrue();
+        assertThat(RemoteResult.successful(3).equals(RemoteResult.successful(7))).isFalse();
+        assertThat(RemoteResult.successful(-1).equals(RemoteResult.successful(1))).isFalse();
+        assertThat(RemoteResult.successful(Long.MAX_VALUE).equals(RemoteResult.successful(-1)))
+                .isFalse();
+        assertThat(RemoteResult.successful(3).equals(RemoteResult.FAILED_TIMED_OUT)).isFalse();
+        assertThat(RemoteResult.successful(3).equals("3")).isFalse();
+        assertThat(RemoteResult.successful(3).equals(null)).isFalse();
+        assertThat(RemoteResult.FAILED_TIMED_OUT.equals(RemoteResult.FAILED_TIMED_OUT)).isTrue();
+        assertThat(RemoteResult.FAILED_TIMED_OUT.equals(RemoteResult.FAILED_CANCELLED)).isFalse();
+    }
+
+    /** @see Object#hashCode() */
+    @Test
+    public void testHashCode() {
+        RemoteResult result3 = RemoteResult.successful(3);
+        assertThat(result3.hashCode()).isEqualTo(result3.hashCode());
+        assertThat(result3.hashCode()).isEqualTo(RemoteResult.successful(3).hashCode());
+        assertThat(RemoteResult.FAILED_TIMED_OUT.hashCode())
+                .isEqualTo(RemoteResult.FAILED_TIMED_OUT.hashCode());
+        assertThat(RemoteResult.FAILED_CANCELLED.hashCode())
+                .isEqualTo(RemoteResult.FAILED_CANCELLED.hashCode());
+        assertThat(RemoteResult.FAILED_THREAD_INTERRUPTED.hashCode())
+                .isEqualTo(RemoteResult.FAILED_THREAD_INTERRUPTED.hashCode());
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
new file mode 100644
index 0000000..e0d3c0c
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.remote;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.IBackupManager;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class ServiceBackupCallbackTest {
+    @Test
+    public void testOperationComplete_callsBackupManagerOpComplete() throws Exception {
+        IBackupManager backupManager = mock(IBackupManager.class);
+        ServiceBackupCallback callback = new ServiceBackupCallback(backupManager, 0x68e);
+
+        callback.operationComplete(7);
+
+        verify(backupManager).opComplete(0x68e, 7);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
index 92d6bbd..2717120 100644
--- a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
+++ b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -19,6 +19,9 @@
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper;
+
+import static com.android.server.backup.testing.TestUtils.assertEventLogged;
+import static com.android.server.backup.testing.TestUtils.assertEventNotLogged;
 import static com.android.server.backup.testing.TransportData.backupTransport;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -77,10 +80,9 @@
 
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
-    manifest = Config.NONE,
-    sdk = 26,
-    shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class}
-)
+        manifest = Config.NONE,
+        sdk = 26,
+        shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class})
 @SystemLoaderPackages({"com.android.server.backup"})
 @Presubmit
 public class ActiveRestoreSessionTest {
@@ -130,6 +132,7 @@
 
         mWakeLock = createBackupWakeLock(application);
 
+        // TODO: Migrate to use spy(createInitializedBackupManagerService())
         setUpBackupManagerServiceBasics(
                 mBackupManagerService,
                 application,
@@ -210,7 +213,7 @@
         mShadowBackupLooper.runToEndOfTasks();
         assertThat(result).isEqualTo(0);
         verify(mObserver).restoreSetsAvailable(aryEq(new RestoreSet[0]));
-        assertThat(ShadowEventLog.hasEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE)).isFalse();
+        assertEventNotLogged(EventLogTags.RESTORE_TRANSPORT_FAILURE);
     }
 
     @Test
@@ -225,7 +228,7 @@
         mShadowBackupLooper.runToEndOfTasks();
         assertThat(result).isEqualTo(0);
         verify(mObserver).restoreSetsAvailable(isNull());
-        assertThat(ShadowEventLog.hasEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE)).isTrue();
+        assertEventLogged(EventLogTags.RESTORE_TRANSPORT_FAILURE);
         verify(mTransportManager)
                 .disposeOfTransportClient(eq(transportMock.transportClient), any());
         assertThat(mWakeLock.isHeld()).isFalse();
diff --git a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
index 5a886e3..603a471 100644
--- a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
@@ -16,46 +16,131 @@
 
 package com.android.server.backup.testing;
 
+import static com.android.server.backup.testing.TestUtils.runToEndOfTasks;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
 
+import android.annotation.Nullable;
 import android.app.Application;
 import android.app.IActivityManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.PowerManager;
+import android.os.Process;
 import android.util.SparseArray;
 
 import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.Trampoline;
 import com.android.server.backup.TransportManager;
-import com.android.server.backup.internal.BackupHandler;
+import com.android.server.backup.internal.Operation;
 
+import org.mockito.stubbing.Answer;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowBinder;
+import org.robolectric.shadows.ShadowLog;
+
+import java.io.File;
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.concurrent.atomic.AtomicReference;
 
 /** Test utils for {@link BackupManagerService} and friends. */
 public class BackupManagerServiceTestUtils {
-    /** Sets up basic mocks for {@link BackupManagerService}. */
+    /**
+     * If the class-under-test is going to execute methods as the system, it's a good idea to also
+     * call {@link #setUpBinderCallerAndApplicationAsSystem(Application)} before this method.
+     */
+    public static BackupManagerService createInitializedBackupManagerService(
+            Context context, File baseStateDir, File dataDir, TransportManager transportManager) {
+        return createInitializedBackupManagerService(
+                context, startBackupThread(null), baseStateDir, dataDir, transportManager);
+    }
+
+    public static BackupManagerService createInitializedBackupManagerService(
+            Context context,
+            HandlerThread backupThread,
+            File baseStateDir,
+            File dataDir,
+            TransportManager transportManager) {
+        BackupManagerService backupManagerService =
+                new BackupManagerService(
+                        context,
+                        new Trampoline(context),
+                        backupThread,
+                        baseStateDir,
+                        dataDir,
+                        transportManager);
+        runToEndOfTasks(backupThread.getLooper());
+        return backupManagerService;
+    }
+
+    /**
+     * Sets up basic mocks for {@link BackupManagerService} mock. If {@code backupManagerService} is
+     * a spy, make sure you provide in the arguments the same objects that the original object uses.
+     *
+     * <p>If the class-under-test is going to execute methods as the system, it's a good idea to
+     * also call {@link #setUpBinderCallerAndApplicationAsSystem(Application)}.
+     */
+    @SuppressWarnings("ResultOfMethodCallIgnored")
     public static void setUpBackupManagerServiceBasics(
             BackupManagerService backupManagerService,
-            Context context,
+            Application application,
             TransportManager transportManager,
             PackageManager packageManager,
-            BackupHandler backupHandler,
+            Handler backupHandler,
             PowerManager.WakeLock wakeLock,
             BackupAgentTimeoutParameters agentTimeoutParameters) {
-        when(backupManagerService.getContext()).thenReturn(context);
+
+        when(backupManagerService.getContext()).thenReturn(application);
         when(backupManagerService.getTransportManager()).thenReturn(transportManager);
         when(backupManagerService.getPackageManager()).thenReturn(packageManager);
         when(backupManagerService.getBackupHandler()).thenReturn(backupHandler);
         when(backupManagerService.getCurrentOpLock()).thenReturn(new Object());
         when(backupManagerService.getQueueLock()).thenReturn(new Object());
-        when(backupManagerService.getCurrentOperations()).thenReturn(new SparseArray<>());
         when(backupManagerService.getActivityManager()).thenReturn(mock(IActivityManager.class));
         when(backupManagerService.getWakelock()).thenReturn(wakeLock);
         when(backupManagerService.getAgentTimeoutParameters()).thenReturn(agentTimeoutParameters);
+
+        AccessorMock backupEnabled = mockAccessor(false);
+        doAnswer(backupEnabled.getter).when(backupManagerService).isBackupEnabled();
+        doAnswer(backupEnabled.setter).when(backupManagerService).setBackupEnabled(anyBoolean());
+
+        AccessorMock backupRunning = mockAccessor(false);
+        doAnswer(backupEnabled.getter).when(backupManagerService).isBackupRunning();
+        doAnswer(backupRunning.setter).when(backupManagerService).setBackupRunning(anyBoolean());
+    }
+
+    public static void setUpBinderCallerAndApplicationAsSystem(Application application) {
+        ShadowBinder.setCallingUid(Process.SYSTEM_UID);
+        ShadowBinder.setCallingPid(1211);
+        ShadowApplication shadowApplication = shadowOf(application);
+        shadowApplication.grantPermissions("android.permission.BACKUP");
+        shadowApplication.grantPermissions("android.permission.CONFIRM_FULL_BACKUP");
+    }
+
+    /**
+     * Returns one getter {@link Answer<T>} and one setter {@link Answer<T>} to be easily passed to
+     * Mockito mocking facilities.
+     *
+     * @param defaultValue Value returned by the getter if there was no setter call until then.
+     */
+    public static <T> AccessorMock<T> mockAccessor(T defaultValue) {
+        AtomicReference<T> holder = new AtomicReference<>(defaultValue);
+        return new AccessorMock<>(
+                invocation -> holder.get(),
+                invocation -> {
+                    holder.set(invocation.getArgument(0));
+                    return null;
+                });
     }
 
     public static PowerManager.WakeLock createBackupWakeLock(Application application) {
@@ -88,12 +173,38 @@
      * @return The backup thread.
      * @see #startBackupThreadAndGetLooper()
      */
-    public static HandlerThread startBackupThread(UncaughtExceptionHandler exceptionHandler) {
+    public static HandlerThread startBackupThread(
+            @Nullable UncaughtExceptionHandler exceptionHandler) {
         HandlerThread backupThread = new HandlerThread("backup");
         backupThread.setUncaughtExceptionHandler(exceptionHandler);
         backupThread.start();
         return backupThread;
     }
 
+    /**
+     * Similar to {@link #startBackupThread(UncaughtExceptionHandler)} but logging uncaught
+     * exceptions to logcat.
+     *
+     * @param tag Tag used for logging exceptions.
+     * @return The backup thread.
+     * @see #startBackupThread(UncaughtExceptionHandler)
+     */
+    public static HandlerThread startSilentBackupThread(String tag) {
+        return startBackupThread(
+                (thread, e) ->
+                        ShadowLog.e(
+                                tag, "Uncaught exception in test thread " + thread.getName(), e));
+    }
+
     private BackupManagerServiceTestUtils() {}
+
+    public static class AccessorMock<T> {
+        public Answer<T> getter;
+        public Answer<T> setter;
+
+        private AccessorMock(Answer<T> getter, Answer<T> setter) {
+            this.getter = getter;
+            this.setter = setter;
+        }
+    }
 }
diff --git a/services/robotests/src/com/android/server/backup/testing/PackageData.java b/services/robotests/src/com/android/server/backup/testing/PackageData.java
new file mode 100644
index 0000000..f9177a8
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/PackageData.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.testing;
+
+import android.annotation.IntDef;
+import android.content.pm.ApplicationInfo;
+import android.os.Process;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+// TODO: Preconditions is not available, include its target in dependencies
+public class PackageData {
+    public static final PackageData PM_PACKAGE = new PmPackageData();
+
+    public static PackageData keyValuePackage(int identifier) {
+        return androidPackage(identifier, BackupStatus.KEY_VALUE_BACKUP);
+    }
+
+    public static PackageData fullBackupPackage(int identifier) {
+        return androidPackage(identifier, BackupStatus.FULL_BACKUP);
+    }
+
+    /** Returns {@link PackageData} for unique package identifier {@code identifier}. */
+    public static PackageData androidPackage(int identifier) {
+        return androidPackage(identifier, BackupStatus.KEY_VALUE_BACKUP);
+    }
+
+    public final String packageName;
+    public final String agentName;
+    @BackupStatus public final int backupStatus;
+    public final boolean available;
+    public final boolean stopped;
+    public final int uid;
+
+    private PackageData(
+            String packageName,
+            String agentName,
+            int backupStatus,
+            boolean stopped,
+            boolean available,
+            int uid) {
+        // checkArgument(!stopped || !available, "stopped => !available")
+
+        this.packageName = packageName;
+        this.agentName = agentName;
+        this.backupStatus = backupStatus;
+        this.stopped = stopped;
+        this.available = available;
+        this.uid = uid;
+    }
+
+    public int flags() {
+        int flags = 0;
+        if (backupStatus != BackupStatus.BACKUP_NOT_ALLOWED) {
+            flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        }
+        if (backupStatus == BackupStatus.FULL_BACKUP) {
+            flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
+        }
+        if (stopped) {
+            flags |= ApplicationInfo.FLAG_STOPPED;
+        }
+        return flags;
+    }
+
+    public PackageData backupNotAllowed() {
+        return new PackageData(
+                packageName, agentName, BackupStatus.BACKUP_NOT_ALLOWED, stopped, available, uid);
+    }
+
+    public PackageData stopped() {
+        return new PackageData(packageName, agentName, backupStatus, true, false, uid);
+    }
+
+    public PackageData unavailable() {
+        return new PackageData(packageName, agentName, backupStatus, stopped, false, uid);
+    }
+
+    public boolean isPm() {
+        return this == PM_PACKAGE;
+    }
+
+    private static PackageData androidPackage(int identifier, @BackupStatus int backupStatus) {
+        // checkArgument(identifier >= 0, "identifier can't be < 0");
+
+        String packageName = "com.sample.package" + identifier;
+        return new PackageData(
+                packageName,
+                packageName + ".BackupAgent",
+                backupStatus,
+                false,
+                true,
+                Process.FIRST_APPLICATION_UID + identifier);
+    }
+
+    private static class PmPackageData extends PackageData {
+        private PmPackageData() {
+            super(
+                    "@pm@",
+                    "com.android.server.backup.PackageManagerBackupAgent",
+                    BackupStatus.KEY_VALUE_BACKUP,
+                    false,
+                    true,
+                    Process.SYSTEM_UID);
+        }
+
+        @Override
+        public int flags() {
+            throw new UnsupportedOperationException("PM \"package\" has no flags");
+        }
+
+        @Override
+        public PackageData backupNotAllowed() {
+            throw new UnsupportedOperationException("PM \"package\" has backup allowed");
+        }
+
+        @Override
+        public PackageData stopped() {
+            throw new UnsupportedOperationException("PM \"package\" can't be stopped");
+        }
+
+        @Override
+        public PackageData unavailable() {
+            throw new UnsupportedOperationException("PM \"package\" is always available");
+        }
+    }
+
+    @IntDef({
+        BackupStatus.KEY_VALUE_BACKUP,
+        BackupStatus.FULL_BACKUP,
+        BackupStatus.BACKUP_NOT_ALLOWED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BackupStatus {
+        int KEY_VALUE_BACKUP = 0;
+        int FULL_BACKUP = 1;
+        int BACKUP_NOT_ALLOWED = 2;
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/TestUtils.java b/services/robotests/src/com/android/server/backup/testing/TestUtils.java
index 3c84424..df4d457 100644
--- a/services/robotests/src/com/android/server/backup/testing/TestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/TestUtils.java
@@ -18,21 +18,86 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import org.robolectric.shadows.ShadowLog;
+import static org.robolectric.Shadows.shadowOf;
 
+import android.os.Looper;
+import android.os.Message;
+import android.os.MessageQueue;
+
+import com.android.server.testing.shadows.ShadowEventLog;
+
+import org.robolectric.shadows.ShadowLog;
+import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowSystemClock;
+
+import java.util.Arrays;
 import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.Predicate;
+import java.util.function.Supplier;
 
 public class TestUtils {
-    /** Reset logcat with {@link ShadowLog#reset()} before the test case */
+    private static final long TIMEOUT_MS = 3000;
+    private static final long STEP_MS = 50;
+
+    /**
+     * Counts the number of messages in the looper {@code looper} that satisfy {@code
+     * messageFilter}.
+     */
+    public static int messagesInLooper(Looper looper, Predicate<Message> messageFilter) {
+        MessageQueue queue = looper.getQueue();
+        int i = 0;
+        for (Message m = shadowOf(queue).getHead(); m != null; m = shadowOf(m).getNext()) {
+            if (messageFilter.test(m)) {
+                i += 1;
+            }
+        }
+        return i;
+    }
+
+    public static void waitUntil(Supplier<Boolean> condition)
+            throws InterruptedException, TimeoutException {
+        waitUntil(condition, STEP_MS, TIMEOUT_MS);
+    }
+
+    public static void waitUntil(Supplier<Boolean> condition, long stepMs, long timeoutMs)
+            throws InterruptedException, TimeoutException {
+        long deadline = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutMs);
+        while (true) {
+            if (condition.get()) {
+                return;
+            }
+            if (System.nanoTime() > deadline) {
+                throw new TimeoutException("Test timed-out waiting for condition");
+            }
+            Thread.sleep(stepMs);
+        }
+    }
+
+    /** Version of {@link ShadowLooper#runToEndOfTasks()} that also advances the system clock. */
+    public static void runToEndOfTasks(Looper looper) {
+        ShadowLooper shadowLooper = shadowOf(looper);
+        shadowLooper.runToEndOfTasks();
+        // Handler instances have their own clock, so advancing looper (with runToEndOfTasks())
+        // above does NOT advance the handlers' clock, hence whenever a handler post messages with
+        // specific time to the looper the time of those messages will be before the looper's time.
+        // To fix this we advance SystemClock as well since that is from where the handlers read
+        // time.
+        ShadowSystemClock.setCurrentTimeMillis(shadowLooper.getScheduler().getCurrentTime());
+    }
+
+    /** Reset logcat with {@link ShadowLog#reset()} before the test case. */
     public static void assertLogcatAtMost(String tag, int level) {
         assertThat(ShadowLog.getLogsForTag(tag).stream().allMatch(logItem -> logItem.type <= level))
+                .named("All logs <= " + level)
                 .isTrue();
     }
 
-    /** Reset logcat with {@link ShadowLog#reset()} before the test case */
+    /** Reset logcat with {@link ShadowLog#reset()} before the test case. */
     public static void assertLogcatAtLeast(String tag, int level) {
         assertThat(ShadowLog.getLogsForTag(tag).stream().anyMatch(logItem -> logItem.type >= level))
+                .named("Any log >= " + level)
                 .isTrue();
     }
 
@@ -40,6 +105,20 @@
         assertThat(ShadowLog.getLogsForTag(tag).stream().anyMatch(predicate)).isTrue();
     }
 
+    /** Declare shadow {@link ShadowEventLog} to use this. */
+    public static void assertEventLogged(int tag, Object... values) {
+        assertThat(ShadowEventLog.getEntries())
+                .named("Event logs")
+                .contains(new ShadowEventLog.Entry(tag, Arrays.asList(values)));
+    }
+
+    /** Declare shadow {@link ShadowEventLog} to use this. */
+    public static void assertEventNotLogged(int tag, Object... values) {
+        assertThat(ShadowEventLog.getEntries())
+                .named("Event logs")
+                .doesNotContain(new ShadowEventLog.Entry(tag, Arrays.asList(values)));
+    }
+
     /**
      * Calls {@link Runnable#run()} and returns if no exception is thrown. Otherwise, if the
      * exception is unchecked, rethrow it; if it's checked wrap in a {@link RuntimeException} and
diff --git a/services/robotests/src/com/android/server/backup/testing/TransportData.java b/services/robotests/src/com/android/server/backup/testing/TransportData.java
index 9feaa8e..4c67180 100644
--- a/services/robotests/src/com/android/server/backup/testing/TransportData.java
+++ b/services/robotests/src/com/android/server/backup/testing/TransportData.java
@@ -20,6 +20,8 @@
 import android.content.ComponentName;
 import android.content.Intent;
 
+import com.android.server.backup.testing.TransportTestUtils.TransportStatus;
+
 public class TransportData {
     // No constants since new Intent() can't be called in static context because of Robolectric
     public static TransportData backupTransport() {
@@ -66,19 +68,17 @@
                 "dataManagementLabel");
     }
 
-    @TransportTestUtils.TransportStatus
-    public int transportStatus;
+    @TransportStatus public int transportStatus;
     public final String transportName;
     private final String transportComponentShort;
-    @Nullable
-    public String transportDirName;
+    @Nullable public String transportDirName;
     @Nullable public Intent configurationIntent;
     @Nullable public String currentDestinationString;
     @Nullable public Intent dataManagementIntent;
     @Nullable public String dataManagementLabel;
 
     private TransportData(
-            @TransportTestUtils.TransportStatus int transportStatus,
+            @TransportStatus int transportStatus,
             String transportName,
             String transportComponentShort,
             String transportDirName,
@@ -105,7 +105,7 @@
             Intent dataManagementIntent,
             String dataManagementLabel) {
         this(
-                TransportTestUtils.TransportStatus.REGISTERED_AVAILABLE,
+                TransportStatus.REGISTERED_AVAILABLE,
                 transportName,
                 transportComponentShort,
                 transportDirName,
@@ -125,7 +125,7 @@
 
     public TransportData unavailable() {
         return new TransportData(
-                TransportTestUtils.TransportStatus.REGISTERED_UNAVAILABLE,
+                TransportStatus.REGISTERED_UNAVAILABLE,
                 transportName,
                 transportComponentShort,
                 transportDirName,
@@ -137,7 +137,7 @@
 
     public TransportData unregistered() {
         return new TransportData(
-                TransportTestUtils.TransportStatus.UNREGISTERED,
+                TransportStatus.UNREGISTERED,
                 transportName,
                 transportComponentShort,
                 transportDirName,
diff --git a/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java b/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
index 5844131..6625443 100644
--- a/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java
@@ -26,13 +26,13 @@
 
 import static java.util.stream.Collectors.toList;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.os.RemoteException;
-import android.support.annotation.IntDef;
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.backup.TransportManager;
@@ -42,6 +42,8 @@
 
 import org.robolectric.shadows.ShadowPackageManager;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 import java.util.stream.Stream;
 
@@ -209,6 +211,7 @@
         TransportStatus.REGISTERED_UNAVAILABLE,
         TransportStatus.UNREGISTERED
     })
+    @Retention(RetentionPolicy.SOURCE)
     public @interface TransportStatus {
         int REGISTERED_AVAILABLE = 0;
         int REGISTERED_UNAVAILABLE = 1;
diff --git a/services/robotests/src/com/android/server/backup/testing/Utils.java b/services/robotests/src/com/android/server/backup/testing/Utils.java
new file mode 100644
index 0000000..bd8b4ef
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/Utils.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.testing;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Iterator;
+
+public class Utils {
+    public static final int BUFFER_SIZE = 8192;
+
+    public static void transferStreamedData(InputStream in, OutputStream out) throws IOException {
+        transferStreamedData(in, out, BUFFER_SIZE);
+    }
+
+    public static void transferStreamedData(InputStream in, OutputStream out, int bufferSize)
+            throws IOException {
+        byte[] buffer = new byte[bufferSize];
+        int read;
+        while ((read = in.read(buffer)) != -1) {
+            out.write(buffer, 0, read);
+        }
+    }
+
+    public static <T> Iterable<T> oneTimeIterable(Iterator<T> iterator) {
+        return () -> iterator;
+    }
+
+    private Utils() {}
+}
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
index 49ef581f..f843b50 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
@@ -17,6 +17,7 @@
 package com.android.server.backup.transport;
 
 import static com.android.server.backup.TransportManager.SERVICE_ACTION_TRANSPORT_HOST;
+import static com.android.server.backup.testing.TestUtils.assertEventLogged;
 import static com.android.server.backup.testing.TestUtils.assertLogcatAtLeast;
 import static com.android.server.backup.testing.TestUtils.assertLogcatAtMost;
 
@@ -70,15 +71,14 @@
 
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
-    manifest = Config.NONE,
-    sdk = 26,
-    shadows = {
-        ShadowEventLog.class,
-        ShadowCloseGuard.class,
-        ShadowSlog.class,
-        FrameworkShadowLooper.class
-    }
-)
+        manifest = Config.NONE,
+        sdk = 26,
+        shadows = {
+            ShadowEventLog.class,
+            ShadowCloseGuard.class,
+            ShadowSlog.class,
+            FrameworkShadowLooper.class
+        })
 @SystemLoaderPackages({"com.android.server.backup"})
 @Presubmit
 public class TransportClientTest {
@@ -279,7 +279,7 @@
     }
 
     @Test
-    public void testConnectAsync_beforeFrameworkCall_logsBoundTransition() {
+    public void testConnectAsync_beforeFrameworkCall_logsBoundTransitionEvent() {
         ShadowEventLog.setUp();
 
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
@@ -288,7 +288,7 @@
     }
 
     @Test
-    public void testConnectAsync_afterOnServiceConnected_logsBoundAndConnectedTransitions() {
+    public void testConnectAsync_afterOnServiceConnected_logsBoundAndConnectedTransitionEvents() {
         ShadowEventLog.setUp();
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
@@ -300,7 +300,7 @@
     }
 
     @Test
-    public void testConnectAsync_afterOnBindingDied_logsBoundAndUnboundTransitions() {
+    public void testConnectAsync_afterOnBindingDied_logsBoundAndUnboundTransitionEvents() {
         ShadowEventLog.setUp();
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
@@ -372,7 +372,7 @@
     }
 
     @Test
-    public void testUnbind_whenConnected_logsDisconnectedAndUnboundTransitions() {
+    public void testUnbind_whenConnected_logsDisconnectedAndUnboundTransitionEvents() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -385,7 +385,8 @@
     }
 
     @Test
-    public void testOnServiceDisconnected_whenConnected_logsDisconnectedAndUnboundTransitions() {
+    public void
+            testOnServiceDisconnected_whenConnected_logsDisconnectedAndUnboundTransitionEvents() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -398,7 +399,7 @@
     }
 
     @Test
-    public void testOnBindingDied_whenConnected_logsDisconnectedAndUnboundTransitions() {
+    public void testOnBindingDied_whenConnected_logsDisconnectedAndUnboundTransitionEvents() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -539,10 +540,6 @@
         return future.get();
     }
 
-    private void assertEventLogged(int tag, Object... values) {
-        assertThat(ShadowEventLog.hasEvent(tag, values)).isTrue();
-    }
-
     private ServiceConnection verifyBindServiceAsUserAndCaptureServiceConnection(Context context) {
         ArgumentCaptor<ServiceConnection> connectionCaptor =
                 ArgumentCaptor.forClass(ServiceConnection.class);
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
index 8016a8b..bc47dd5 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
@@ -33,6 +33,7 @@
  */
 @Implements(BackupDataInput.class)
 public class ShadowBackupDataInput {
+    private FileDescriptor mFileDescriptor;
     private ObjectInputStream mInput;
     private int mSize;
     private String mKey;
@@ -40,17 +41,14 @@
 
     @Implementation
     public void __constructor__(FileDescriptor fd) {
-        try {
-            mInput = new ObjectInputStream(new FileInputStream(fd));
-        } catch (IOException e) {
-            throw new AssertionError(e);
-        }
+        mFileDescriptor = fd;
     }
 
     @Implementation
     public boolean readNextHeader() throws IOException {
         mHeaderReady = false;
         try {
+            ensureInput();
             mSize = mInput.readInt();
         } catch (EOFException e) {
             return false;
@@ -93,4 +91,22 @@
             throw new IllegalStateException("Entity header not read");
         }
     }
+
+    /**
+     * Lazily initializing input to avoid throwing exception when stream is completely empty in
+     * constructor (Java Object IO writes/reads some header data).
+     *
+     * @throws EOFException When the input is empty.
+     */
+    private void ensureInput() throws EOFException {
+        if (mInput == null) {
+            try {
+                mInput = new ObjectInputStream(new FileInputStream(mFileDescriptor));
+            } catch (EOFException e) {
+                throw e;
+            } catch (IOException e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
index 0415235..ca04008 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
@@ -33,18 +33,14 @@
  */
 @Implements(BackupDataOutput.class)
 public class ShadowBackupDataOutput {
+    private FileDescriptor mFileDescriptor;
+    private ObjectOutputStream mOutput;
     private long mQuota;
     private int mTransportFlags;
-    private ObjectOutputStream mOutput;
 
     @Implementation
     public void __constructor__(FileDescriptor fd, long quota, int transportFlags) {
-        try {
-            // This writes 4 bytes
-            mOutput = new ObjectOutputStream(new FileOutputStream(fd));
-        } catch (IOException e) {
-            throw new AssertionError(e);
-        }
+        mFileDescriptor = fd;
         mQuota = quota;
         mTransportFlags = transportFlags;
     }
@@ -61,6 +57,7 @@
 
     @Implementation
     public int writeEntityHeader(String key, int dataSize) throws IOException {
+        ensureOutput();
         final int size;
         try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
             writeEntityHeader(new ObjectOutputStream(byteStream), key, dataSize);
@@ -80,8 +77,24 @@
 
     @Implementation
     public int writeEntityData(byte[] data, int size) throws IOException {
+        ensureOutput();
         mOutput.write(data, 0, size);
         mOutput.flush();
         return size;
     }
+
+    /**
+     * Lazily initializing output to avoid writing the header data below for when there is no data
+     * (Java Object IO writes/reads some header data).
+     */
+    private void ensureOutput() {
+        if (mOutput == null) {
+            try {
+                // This writes 4 bytes: Java Object IO writes/reads some header data
+                mOutput = new ObjectOutputStream(new FileOutputStream(mFileDescriptor));
+            } catch (IOException e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java b/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
index 4625684..3df1723 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
@@ -24,10 +24,12 @@
 import java.util.Arrays;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
 
+/** Don't forget to call {@link ShadowEventLog#setUp()} before every test. */
 @Implements(EventLog.class)
 public class ShadowEventLog {
-    private final static LinkedHashSet<Entry> ENTRIES = new LinkedHashSet<>();
+    private static final LinkedHashSet<Entry> ENTRIES = new LinkedHashSet<>();
 
     @Implementation
     public static int writeEvent(int tag, Object... values) {
@@ -36,11 +38,16 @@
         return 0;
     }
 
-    public static boolean hasEvent(int tag, Object... values) {
-        return ENTRIES.contains(new Entry(tag, Arrays.asList(values)));
+    @Implementation
+    public static int writeEvent(int tag, String string) {
+        return writeEvent(tag, (Object) string);
     }
 
-    /** Clears the entries */
+    public static Set<Entry> getEntries() {
+        return new LinkedHashSet<>(ENTRIES);
+    }
+
+    /** Clears the entries. */
     public static void setUp() {
         ENTRIES.clear();
     }
@@ -68,5 +75,10 @@
             result = 31 * result + values.hashCode();
             return result;
         }
+
+        @Override
+        public String toString() {
+            return "Entry{" + tag + ", " + values + '}';
+        }
     }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
new file mode 100644
index 0000000..aeda2dc
--- /dev/null
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.testing.shadows;
+
+import android.annotation.Nullable;
+import android.app.backup.IBackupManagerMonitor;
+import android.app.backup.IBackupObserver;
+
+import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.DataChangedJournal;
+import com.android.server.backup.internal.OnTaskFinishedListener;
+import com.android.server.backup.keyvalue.KeyValueBackupTask;
+import com.android.server.backup.transport.TransportClient;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.List;
+
+@Implements(KeyValueBackupTask.class)
+public class ShadowKeyValueBackupTask {
+    @Nullable private static ShadowKeyValueBackupTask sLastShadow;
+
+    /**
+     * Retrieves the shadow for the last {@link KeyValueBackupTask} object created.
+     *
+     * @return The shadow or {@code null} if no object created since last {@link #reset()}.
+     */
+    @Nullable
+    public static ShadowKeyValueBackupTask getLastCreated() {
+        return sLastShadow;
+    }
+
+    public static void reset() {
+        sLastShadow = null;
+    }
+
+    private OnTaskFinishedListener mListener;
+    private List<String> mQueue;
+    private List<String> mPendingFullBackups;
+
+    @Implementation
+    public void __constructor__(
+            BackupManagerService backupManagerService,
+            TransportClient transportClient,
+            String dirName,
+            List<String> queue,
+            @Nullable DataChangedJournal journal,
+            IBackupObserver observer,
+            IBackupManagerMonitor monitor,
+            @Nullable OnTaskFinishedListener listener,
+            List<String> pendingFullBackups,
+            boolean userInitiated,
+            boolean nonIncremental) {
+        mListener = listener;
+        mQueue = queue;
+        mPendingFullBackups = pendingFullBackups;
+        sLastShadow = this;
+    }
+
+    @Implementation
+    public void execute() {
+        mListener.onFinished("ShadowKeyValueBackupTask.execute()");
+    }
+
+    public List<String> getQueue() {
+        return mQueue;
+    }
+
+    public List<String> getPendingFullBackups() {
+        return mPendingFullBackups;
+    }
+}
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowPerformBackupTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowPerformBackupTask.java
deleted file mode 100644
index 7c10377..0000000
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowPerformBackupTask.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.testing.shadows;
-
-import android.annotation.Nullable;
-import android.app.backup.IBackupManagerMonitor;
-import android.app.backup.IBackupObserver;
-
-import com.android.server.backup.BackupManagerService;
-import com.android.server.backup.DataChangedJournal;
-import com.android.server.backup.internal.BackupRequest;
-import com.android.server.backup.internal.OnTaskFinishedListener;
-import com.android.server.backup.internal.PerformBackupTask;
-import com.android.server.backup.transport.TransportClient;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@Implements(PerformBackupTask.class)
-public class ShadowPerformBackupTask {
-    @Nullable private static ShadowPerformBackupTask sLastShadow;
-
-    /**
-     * Retrieves the shadow for the last {@link PerformBackupTask} object created.
-     *
-     * @return The shadow or {@code null} if no object created since last {@link #reset()}.
-     */
-    @Nullable
-    public static ShadowPerformBackupTask getLastCreated() {
-        return sLastShadow;
-    }
-
-    public static void reset() {
-        sLastShadow = null;
-    }
-
-    private OnTaskFinishedListener mListener;
-    private ArrayList<BackupRequest> mQueue;
-    private List<String> mPendingFullBackups;
-
-    @Implementation
-    public void __constructor__(
-            BackupManagerService backupManagerService,
-            TransportClient transportClient,
-            String dirName,
-            ArrayList<BackupRequest> queue,
-            @Nullable DataChangedJournal journal,
-            IBackupObserver observer,
-            IBackupManagerMonitor monitor,
-            @Nullable OnTaskFinishedListener listener,
-            List<String> pendingFullBackups,
-            boolean userInitiated,
-            boolean nonIncremental) {
-        mListener = listener;
-        mQueue = queue;
-        mPendingFullBackups = pendingFullBackups;
-        sLastShadow = this;
-    }
-
-    @Implementation
-    public void execute() {
-        mListener.onFinished("ShadowPerformBackupTask.execute()");
-    }
-
-    public List<BackupRequest> getQueue() {
-        return mQueue;
-    }
-
-    public List<String> getPendingFullBackups() {
-        return mPendingFullBackups;
-    }
-}
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index a85f21c..43f319e 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -22,7 +22,7 @@
     services.net \
     services.usage \
     guava \
-    android-support-test \
+    androidx-test \
     mockito-target-minus-junit4 \
     platform-test-annotations \
     ShortcutManagerTestUtils \
@@ -41,6 +41,7 @@
 
 LOCAL_JAVA_LIBRARIES := \
     android.hidl.manager-V1.0-java \
+    android.hardware.tv.cec-V1.0-java \
     android.test.mock \
     android.test.base android.test.runner \
 
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index a8efe81..348e201 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -65,6 +65,7 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.SUSPEND_APPS"/>
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/>
+    <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/>
 
     <!-- Uses API introduced in O (26) -->
     <uses-sdk android:minSdkVersion="1"
@@ -220,7 +221,7 @@
     </application>
 
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.frameworks.servicestests"
         android:label="Frameworks Services Tests" />
 </manifest>
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index 5ac68d4..4d653b9 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -28,7 +28,7 @@
     <option name="test-tag" value="FrameworksServicesTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.servicestests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
index 918807d0..1f63d61 100644
--- a/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -20,10 +20,11 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.ObjectUtils;
 import com.android.server.AlarmManagerService.Alarm;
 
diff --git a/services/tests/servicestests/src/com/android/server/AppOpsUpgradeTest.java b/services/tests/servicestests/src/com/android/server/AppOpsUpgradeTest.java
index 4d77fab..aac96a1d 100644
--- a/services/tests/servicestests/src/com/android/server/AppOpsUpgradeTest.java
+++ b/services/tests/servicestests/src/com/android/server/AppOpsUpgradeTest.java
@@ -25,13 +25,14 @@
 import android.content.res.AssetManager;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.Xml;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
index 933b3d6b4..910aad7f 100644
--- a/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
@@ -60,12 +60,13 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings.Global;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
 import android.util.ArraySet;
 import android.util.Pair;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
 import com.android.server.AppStateTracker.Listener;
diff --git a/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java b/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
index 106f9e8..cb12ba7 100644
--- a/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
@@ -17,28 +17,25 @@
 package com.android.server;
 
 import static junit.framework.Assert.*;
+
 import static org.mockito.Mockito.*;
 
 import android.hardware.health.V2_0.IHealth;
 import android.hidl.manager.V1_0.IServiceManager;
 import android.hidl.manager.V1_0.IServiceNotification;
-import android.os.RemoteException;
-import android.support.test.filters.SmallTest;
 import android.test.AndroidTestCase;
-import android.util.Slog;
+
+import androidx.test.filters.SmallTest;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
 
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.NoSuchElementException;
 
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.Spy;
-import org.mockito.invocation.InvocationOnMock;
-
-
 public class BatteryServiceTest extends AndroidTestCase {
 
     @Mock IServiceManager mMockedManager;
diff --git a/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java b/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java
index 69c1499..9ba3308 100644
--- a/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java
+++ b/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java
@@ -18,10 +18,8 @@
 
 import static junit.framework.Assert.*;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import junit.framework.Assert;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
index 33e4165..2ec6830 100644
--- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
@@ -33,12 +33,13 @@
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
-import android.view.KeyEvent;
 import android.util.MutableBoolean;
+import android.view.KeyEvent;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -46,17 +47,16 @@
 import com.android.server.LocalServices;
 import com.android.server.statusbar.StatusBarManagerInternal;
 
-import java.util.List;
-
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
+
 /**
  * Unit tests for {@link GestureLauncherService}.
  * runtest frameworks-services -c com.android.server.GestureLauncherServiceTest
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java
index c9180a9..4bac200 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java
@@ -29,10 +29,11 @@
 import static org.junit.Assert.assertTrue;
 
 import android.net.NetworkPolicyManager;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -52,7 +53,7 @@
  * Install: adb install -r \
  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
  * Run: adb shell am instrument -e class com.android.server.NetworkManagementInternalTest -w \
- *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ *     com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 17babe9..eb28e1a 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -114,8 +114,6 @@
 import android.os.SimpleClock;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionPlan;
@@ -128,6 +126,9 @@
 import android.util.Range;
 import android.util.RecurrenceRule;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
@@ -135,9 +136,6 @@
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsManagerInternal;
 
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
 import com.google.common.util.concurrent.AbstractFuture;
 
 import org.junit.After;
@@ -154,6 +152,9 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.InputStream;
@@ -190,7 +191,7 @@
     m -j32 FrameworksServicesTests && adb install -r -g \
     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
     adb shell am instrument -e class "com.android.server.NetworkPolicyManagerServiceTest" -w \
-    "com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner"
+    "com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner"
  * </code></pre>
  */
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 4176d2a..e9e96c9 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -24,14 +24,12 @@
 import static junit.framework.Assert.fail;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyListOf;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -47,7 +45,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.res.Resources;
-import android.database.ContentObserver;
 import android.net.INetworkRecommendationProvider;
 import android.net.INetworkScoreCache;
 import android.net.NetworkKey;
@@ -69,9 +66,10 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.devicepolicy.MockUtils;
 
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index 6874624..52428e8 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -34,7 +34,6 @@
 import android.app.AppOpsManager;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -45,14 +44,14 @@
 import android.net.NetworkScorerAppData;
 import android.os.Bundle;
 import android.provider.Settings;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.R;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
new file mode 100644
index 0000000..43438b9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.os.UserHandle;
+import android.os.UserManagerInternal;
+import android.os.storage.StorageManagerInternal;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.SparseArray;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StorageManagerServiceTest {
+
+    private StorageManagerService mService;
+
+    @Mock private Context mContext;
+    @Mock private PackageManager mPm;
+    @Mock private PackageManagerInternal mPmi;
+    @Mock private UserManagerInternal mUmi;
+
+    private static final String PKG_GREY = "com.grey";
+    private static final String PKG_RED = "com.red";
+    private static final String PKG_BLUE = "com.blue";
+
+    private static final int UID_GREY = 10000;
+    private static final int UID_COLORS = 10001;
+
+    private static final String NAME_COLORS = "colors";
+
+    private static ApplicationInfo buildApplicationInfo(String packageName, int uid) {
+        final ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = packageName;
+        ai.uid = uid;
+        return ai;
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        LocalServices.removeServiceForTest(StorageManagerInternal.class);
+
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
+        LocalServices.addService(PackageManagerInternal.class, mPmi);
+        LocalServices.removeServiceForTest(UserManagerInternal.class);
+        LocalServices.addService(UserManagerInternal.class, mUmi);
+
+        when(mContext.getPackageManager()).thenReturn(mPm);
+
+        when(mUmi.getUserIds()).thenReturn(new int[] { 0 });
+
+        {
+            final SparseArray<String> res = new SparseArray<>();
+            res.put(UID_COLORS, NAME_COLORS);
+            when(mPmi.getAppsWithSharedUserIds()).thenReturn(res);
+        }
+
+        {
+            final List<ApplicationInfo> res = new ArrayList<>();
+            res.add(buildApplicationInfo(PKG_GREY, UID_GREY));
+            res.add(buildApplicationInfo(PKG_RED, UID_COLORS));
+            res.add(buildApplicationInfo(PKG_BLUE, UID_COLORS));
+            when(mPm.getInstalledApplicationsAsUser(anyInt(), anyInt())).thenReturn(res);
+        }
+
+        when(mPmi.getPackageUid(eq(PKG_GREY), anyInt(), anyInt())).thenReturn(UID_GREY);
+        when(mPmi.getPackageUid(eq(PKG_RED), anyInt(), anyInt())).thenReturn(UID_COLORS);
+        when(mPmi.getPackageUid(eq(PKG_BLUE), anyInt(), anyInt())).thenReturn(UID_COLORS);
+
+        when(mPm.getPackagesForUid(eq(UID_GREY))).thenReturn(new String[] { PKG_GREY });
+        when(mPm.getPackagesForUid(eq(UID_COLORS))).thenReturn(new String[] { PKG_RED, PKG_BLUE });
+
+        mService = new StorageManagerService(mContext);
+        mService.collectPackagesInfo();
+    }
+
+    @Test
+    public void testNone() throws Exception {
+        assertTranslation(
+                "/dev/null",
+                "/dev/null", PKG_GREY);
+        assertTranslation(
+                "/dev/null",
+                "/dev/null", PKG_RED);
+    }
+
+    @Test
+    public void testPrimary() throws Exception {
+        assertTranslation(
+                "/storage/emulated/0/Android/sandbox/com.grey/foo.jpg",
+                "/storage/emulated/0/foo.jpg", PKG_GREY);
+        assertTranslation(
+                "/storage/emulated/0/Android/sandbox/shared/colors/foo.jpg",
+                "/storage/emulated/0/foo.jpg", PKG_RED);
+    }
+
+    @Test
+    public void testSecondary() throws Exception {
+        assertTranslation(
+                "/storage/0000-0000/Android/sandbox/com.grey/foo/bar.jpg",
+                "/storage/0000-0000/foo/bar.jpg", PKG_GREY);
+        assertTranslation(
+                "/storage/0000-0000/Android/sandbox/shared/colors/foo/bar.jpg",
+                "/storage/0000-0000/foo/bar.jpg", PKG_RED);
+    }
+
+    @Test
+    public void testLegacy() throws Exception {
+        // Accessing their own paths goes straight through
+        assertTranslation(
+                "/storage/emulated/0/Android/data/com.grey/foo.jpg",
+                "/storage/emulated/0/Android/data/com.grey/foo.jpg", PKG_GREY);
+
+        // Accessing other package paths goes into sandbox
+        assertTranslation(
+                "/storage/emulated/0/Android/sandbox/shared/colors/"
+                        + "Android/data/com.grey/foo.jpg",
+                "/storage/emulated/0/Android/data/com.grey/foo.jpg", PKG_RED);
+    }
+
+    @Test
+    public void testLegacyShared() throws Exception {
+        // Accessing their own paths goes straight through
+        assertTranslation(
+                "/storage/emulated/0/Android/data/com.red/foo.jpg",
+                "/storage/emulated/0/Android/data/com.red/foo.jpg", PKG_RED);
+        assertTranslation(
+                "/storage/emulated/0/Android/data/com.red/foo.jpg",
+                "/storage/emulated/0/Android/data/com.red/foo.jpg", PKG_BLUE);
+
+        // Accessing other package paths goes into sandbox
+        assertTranslation(
+                "/storage/emulated/0/Android/sandbox/com.grey/"
+                        + "Android/data/com.red/foo.jpg",
+                "/storage/emulated/0/Android/data/com.red/foo.jpg", PKG_GREY);
+    }
+
+    @Test
+    public void testSecurity() throws Exception {
+        // Shady paths should throw
+        try {
+            mService.translateAppToSystem(
+                    "/storage/emulated/0/../foo.jpg",
+                    PKG_GREY, UserHandle.USER_SYSTEM);
+            fail();
+        } catch (SecurityException expected) {
+        }
+
+        // Sandboxes can't see system paths
+        try {
+            mService.translateSystemToApp(
+                    "/storage/emulated/0/foo.jpg",
+                    PKG_GREY, UserHandle.USER_SYSTEM);
+            fail();
+        } catch (SecurityException expected) {
+        }
+
+        // Sandboxes can't see paths in other sandboxes
+        try {
+            mService.translateSystemToApp(
+                    "/storage/emulated/0/Android/sandbox/shared/colors/foo.jpg",
+                    PKG_GREY, UserHandle.USER_SYSTEM);
+            fail();
+        } catch (SecurityException expected) {
+        }
+    }
+
+    private void assertTranslation(String system, String sandbox, String packageName)
+            throws Exception {
+        assertEquals(system,
+                mService.translateAppToSystem(sandbox, packageName, UserHandle.USER_SYSTEM));
+        assertEquals(sandbox,
+                mService.translateSystemToApp(system, packageName, UserHandle.USER_SYSTEM));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
index 6e76b67..4d229ef 100644
--- a/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
+++ b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
@@ -18,14 +18,14 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.runner.AndroidJUnit4;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
 /**
  * Unit tests for {@link WatchdogDiagnostics}
  */
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java
index 14abb8a1..1c025cf 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java
@@ -46,23 +46,8 @@
     private static final int PATH_STEP_PIXELS = 200;
     private static final long PATH_STEP_MILLISEC = 100;
 
-    /**
-     * AccessibilitGestureDetector that can mock double-tap detector.
-     */
-    private class AccessibilityGestureDetectorTestable extends AccessibilityGestureDetector {
-        public AccessibilityGestureDetectorTestable(Context context, Listener listener) {
-            super(context, listener);
-        }
-
-        protected void setDoubleTapDetector(GestureDetector gestureDetector) {
-            mGestureDetector = gestureDetector;
-            mGestureDetector.setOnDoubleTapListener(this);
-        }
-    }
-
-
     // Data used by all tests
-    private AccessibilityGestureDetectorTestable mDetector;
+    private AccessibilityGestureDetector mDetector;
     private AccessibilityGestureDetector.Listener mResultListener;
 
 
@@ -87,9 +72,8 @@
 
         // Construct a testable AccessibilityGestureDetector.
         mResultListener = mock(AccessibilityGestureDetector.Listener.class);
-        mDetector = new AccessibilityGestureDetectorTestable(contextMock, mResultListener);
         GestureDetector doubleTapDetectorMock = mock(GestureDetector.class);
-        mDetector.setDoubleTapDetector(doubleTapDetectorMock);
+        mDetector = new AccessibilityGestureDetector(contextMock, mResultListener, doubleTapDetectorMock);
     }
 
 
@@ -195,7 +179,7 @@
                     point.x, point.y, 0);
 
             // Send event.
-            mDetector.onMotionEvent(event, policyFlags);
+            mDetector.onMotionEvent(event, event, policyFlags);
             eventTimeMs += PATH_STEP_MILLISEC;
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java
index 5d09e31..4c0f38a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java
@@ -18,6 +18,7 @@
 
 import static junit.framework.TestCase.assertFalse;
 import static junit.framework.TestCase.assertSame;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -30,13 +31,14 @@
 import android.app.Instrumentation;
 import android.os.Looper;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IAccessibilityManager;
 import android.view.accessibility.IAccessibilityManagerClient;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.IntPair;
 
 import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index e5c6c6e..412e844 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -141,4 +141,15 @@
         when(mMockUserState.getBindingServicesLocked())
                 .thenReturn(new HashSet<>(Arrays.asList(componentName)));
     }
+
+    @Test
+    public void binderDied_keysGetFlushed() {
+        IBinder mockBinder = mock(IBinder.class);
+        setServiceBinding(COMPONENT_NAME);
+        mConnection.bindLocked();
+        mConnection.onServiceConnected(COMPONENT_NAME, mockBinder);
+        mConnection.binderDied();
+        assertTrue(mConnection.getServiceInfo().crashed);
+        verify(mMockKeyEventDispatcher).flush(mConnection);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java b/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
index 1819398..236b458 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
@@ -19,6 +19,7 @@
 import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertFalse;
 import static junit.framework.TestCase.assertTrue;
+
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyObject;
@@ -30,11 +31,6 @@
 import static org.mockito.Mockito.when;
 import static org.mockito.hamcrest.MockitoHamcrest.argThat;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 import android.content.Context;
 import android.os.Handler;
 import android.os.IPowerManager;
@@ -42,9 +38,10 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.RemoteException;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.KeyEvent;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.accessibility.KeyEventDispatcher.KeyEventFilter;
 import com.android.server.policy.WindowManagerPolicy;
 
@@ -56,6 +53,11 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * Tests for KeyEventDispatcher
  */
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/KeyboardInterceptorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/KeyboardInterceptorTest.java
index ceb3f9d..851e221 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/KeyboardInterceptorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/KeyboardInterceptorTest.java
@@ -23,14 +23,19 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.mockito.hamcrest.MockitoHamcrest.argThat;
 
-import org.hamcrest.BaseMatcher;
+import android.os.Looper;
+import android.view.KeyEvent;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.policy.WindowManagerPolicy.WindowState;
+
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeMatcher;
 import org.junit.Before;
@@ -42,13 +47,6 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
-import android.os.Looper;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.KeyEvent;
-
-import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.policy.WindowManagerPolicy.WindowState;
-
 /**
  * Tests for KeyboardInterceptor
  */
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
index d3a30909..f9d264b 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
@@ -17,9 +17,9 @@
 package com.android.server.accessibility;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Matchers.eq;
@@ -43,9 +43,10 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.MagnificationSpec;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.R;
 import com.android.server.wm.WindowManagerInternal;
 import com.android.server.wm.WindowManagerInternal.MagnificationCallbacks;
@@ -453,6 +454,20 @@
     }
 
     @Test
+    public void testResetIfNeeded_resetsOnlyIfLastMagnifyingServiceIsDisabled() {
+        mMagnificationController.register();
+        PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
+        mMagnificationController
+                .setScale(2.0f, startCenter.x, startCenter.y, false, SERVICE_ID_1);
+        mMagnificationController
+                .setScale(1.5f, startCenter.x, startCenter.y, false, SERVICE_ID_2);
+        assertFalse(mMagnificationController.resetIfNeeded(SERVICE_ID_1));
+        assertTrue(mMagnificationController.isMagnifying());
+        assertTrue(mMagnificationController.resetIfNeeded(SERVICE_ID_2));
+        assertFalse(mMagnificationController.isMagnifying());
+    }
+
+    @Test
     public void testSetUserId_resetsOnlyIfIdChanges() {
         final int userId1 = 1;
         final int userId2 = 2;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
index 23fe0ff..79e4d70 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
@@ -35,12 +35,13 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.os.Message;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.DebugUtils;
 import android.view.InputDevice;
 import android.view.MotionEvent;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.testutils.OffsettableClock;
 import com.android.server.testutils.TestHandler;
 
@@ -50,7 +51,6 @@
 
 import java.util.function.IntConsumer;
 
-
 /**
  * Tests the state transitions of {@link MagnificationGestureHandler}
  *
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index 6cacb1f..5f0fa87 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -19,6 +19,7 @@
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
 import static android.view.WindowManagerPolicyConstants.FLAG_PASS_TO_USER;
+
 import static org.hamcrest.CoreMatchers.allOf;
 import static org.hamcrest.CoreMatchers.anyOf;
 import static org.hamcrest.CoreMatchers.everyItem;
@@ -45,18 +46,14 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
-import android.util.Pair;
 import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
 import android.view.accessibility.AccessibilityEvent;
+
+import androidx.test.runner.AndroidJUnit4;
+
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.hamcrest.TypeSafeMatcher;
@@ -66,6 +63,10 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * Tests for MotionEventInjector
  */
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/TouchExplorerTest.java
new file mode 100644
index 0000000..c47885f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/TouchExplorerTest.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.os.SystemClock;
+import android.util.DebugUtils;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class TouchExplorerTest {
+
+    public static final int STATE_TOUCH_EXPLORING = 0x00000001;
+    public static final int STATE_DRAGGING = 0x00000002;
+    public static final int STATE_DELEGATING = 0x00000004;
+
+    private static final int FLAG_1FINGER = 0x8000;
+    private static final int FLAG_2FINGERS = 0x0100;
+    private static final int FLAG_3FINGERS = 0x0200;
+    private static final int FLAG_MOVING = 0x00010000;
+    private static final int FLAG_MOVING_DIFF_DIRECTION = 0x00020000;
+
+    private static final int STATE_TOUCH_EXPLORING_1FINGER = STATE_TOUCH_EXPLORING | FLAG_1FINGER;
+    private static final int STATE_TOUCH_EXPLORING_2FINGER = STATE_TOUCH_EXPLORING | FLAG_2FINGERS;
+    private static final int STATE_TOUCH_EXPLORING_3FINGER = STATE_TOUCH_EXPLORING | FLAG_3FINGERS;
+    private static final int STATE_MOVING_2FINGERS = STATE_TOUCH_EXPLORING_2FINGER | FLAG_MOVING;
+    private static final int STATE_MOVING_3FINGERS = STATE_TOUCH_EXPLORING_3FINGER | FLAG_MOVING;
+    private static final int STATE_DRAGGING_2FINGERS = STATE_DRAGGING | FLAG_2FINGERS;
+    private static final int STATE_PINCH_2FINGERS =
+            STATE_TOUCH_EXPLORING_2FINGER | FLAG_MOVING_DIFF_DIRECTION;
+    private static final float DEFAULT_X = 301f;
+    private static final float DEFAULT_Y = 299f;
+
+    private EventStreamTransformation mCaptor;
+    private MotionEvent mLastEvent;
+    private TouchExplorer mTouchExplorer;
+    private long mLastDownTime = Integer.MIN_VALUE;
+
+    /**
+     * {@link TouchExplorer#sendDownForAllNotInjectedPointers} injecting events with the same object
+     * is resulting {@link ArgumentCaptor} to capture events with last state. Before implementation
+     * change, this helper class will save copies to verify the result.
+     */
+    private class EventCaptor implements EventStreamTransformation {
+        List<MotionEvent> mEvents = new ArrayList<>();
+
+        @Override
+        public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+            mEvents.add(0, event.copy());
+        }
+
+        @Override
+        public void setNext(EventStreamTransformation next) {
+        }
+
+        @Override
+        public EventStreamTransformation getNext() {
+            return null;
+        }
+    }
+
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getContext();
+        AccessibilityManagerService ams = new AccessibilityManagerService(context);
+        mCaptor = new EventCaptor();
+        mTouchExplorer = new TouchExplorer(context, ams);
+        mTouchExplorer.setNext(mCaptor);
+    }
+
+    @Test
+    public void testTwoFingersMove_shouldDelegatingAndInjectActionDownPointerDown() {
+        goFromStateIdleTo(STATE_MOVING_2FINGERS);
+
+        assertState(STATE_DELEGATING);
+        assertCapturedEvents(
+                MotionEvent.ACTION_DOWN,
+                MotionEvent.ACTION_POINTER_DOWN);
+        assertCapturedEventsNoHistory();
+    }
+
+    @Test
+    public void testTwoFingersDrag_shouldDraggingAndActionDown() {
+        goFromStateIdleTo(STATE_DRAGGING_2FINGERS);
+
+        assertState(STATE_DRAGGING);
+        assertCapturedEvents(MotionEvent.ACTION_DOWN);
+        assertCapturedEventsNoHistory();
+    }
+
+    @Test
+    public void testTwoFingersNotDrag_shouldDelegatingAndActionUpDownPointerDown() {
+        // only from dragging state, and withMoveHistory no dragging
+        goFromStateIdleTo(STATE_PINCH_2FINGERS);
+
+        assertState(STATE_DELEGATING);
+        assertCapturedEvents(
+                /* goto dragging state */ MotionEvent.ACTION_DOWN,
+                /* leave dragging state */ MotionEvent.ACTION_UP,
+                MotionEvent.ACTION_DOWN,
+                MotionEvent.ACTION_POINTER_DOWN);
+        assertCapturedEventsNoHistory();
+    }
+
+    @Test
+    public void testThreeFingersMove_shouldDelegatingAnd3ActionPointerDown() {
+        goFromStateIdleTo(STATE_MOVING_3FINGERS);
+
+        assertState(STATE_DELEGATING);
+        assertCapturedEvents(
+                MotionEvent.ACTION_DOWN,
+                MotionEvent.ACTION_POINTER_DOWN,
+                MotionEvent.ACTION_POINTER_DOWN);
+        assertCapturedEventsNoHistory();
+    }
+
+    private static MotionEvent fromTouchscreen(MotionEvent ev) {
+        ev.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        return ev;
+    }
+
+    private static PointF p(int x, int y) {
+        return new PointF(x, y);
+    }
+
+    private static String stateToString(int state) {
+        return DebugUtils.valueToString(TouchExplorerTest.class, "STATE_", state);
+    }
+
+    private void goFromStateIdleTo(int state) {
+        try {
+            switch (state) {
+                case STATE_TOUCH_EXPLORING: {
+                    mTouchExplorer.onDestroy();
+                }
+                break;
+                case STATE_TOUCH_EXPLORING_1FINGER: {
+                    goFromStateIdleTo(STATE_TOUCH_EXPLORING);
+                    send(downEvent());
+                }
+                break;
+                case STATE_TOUCH_EXPLORING_2FINGER: {
+                    goFromStateIdleTo(STATE_TOUCH_EXPLORING_1FINGER);
+                    send(pointerDownEvent());
+                }
+                break;
+                case STATE_TOUCH_EXPLORING_3FINGER: {
+                    goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER);
+                    send(thirdPointerDownEvent());
+                }
+                break;
+                case STATE_MOVING_2FINGERS: {
+                    goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER);
+                    moveEachPointers(mLastEvent, p(10, 0), p(5, 10));
+                    send(mLastEvent);
+                }
+                break;
+                case STATE_DRAGGING_2FINGERS: {
+                    goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER);
+                    moveEachPointers(mLastEvent, p(10, 0), p(10, 0));
+                    send(mLastEvent);
+                }
+                break;
+                case STATE_PINCH_2FINGERS: {
+                    goFromStateIdleTo(STATE_DRAGGING_2FINGERS);
+                    moveEachPointers(mLastEvent, p(10, 0), p(-10, 1));
+                    send(mLastEvent);
+                }
+                break;
+                case STATE_MOVING_3FINGERS: {
+                    goFromStateIdleTo(STATE_TOUCH_EXPLORING_3FINGER);
+                    moveEachPointers(mLastEvent, p(1, 0), p(1, 0), p(1, 0));
+                    send(mLastEvent);
+                }
+                break;
+                default:
+                    throw new IllegalArgumentException("Illegal state: " + state);
+            }
+        } catch (Throwable t) {
+            throw new RuntimeException("Failed to go to state " + stateToString(state), t);
+        }
+    }
+
+    private void send(MotionEvent event) {
+        final MotionEvent sendEvent = fromTouchscreen(event);
+        mLastEvent = sendEvent;
+        try {
+            mTouchExplorer.onMotionEvent(sendEvent, sendEvent, /* policyFlags */ 0);
+        } catch (Throwable t) {
+            throw new RuntimeException("Exception while handling " + sendEvent, t);
+        }
+    }
+
+    private void assertState(int expect) {
+        final String expectState = "STATE_" + stateToString(expect);
+        assertTrue(String.format("Expect state: %s, but: %s", expectState, mTouchExplorer),
+                mTouchExplorer.toString().contains(expectState));
+    }
+
+    private void assertCapturedEvents(int... actionsInOrder) {
+        final int eventCount = actionsInOrder.length;
+        assertEquals(eventCount, getCapturedEvents().size());
+        for (int i = 0; i < eventCount; i++) {
+            assertEquals(actionsInOrder[eventCount - i - 1], getCapturedEvent(i).getActionMasked());
+        }
+    }
+
+    private void assertCapturedEventsNoHistory() {
+        for (MotionEvent e : getCapturedEvents()) {
+            assertEquals(0, e.getHistorySize());
+        }
+    }
+
+    private MotionEvent getCapturedEvent(int index) {
+        return getCapturedEvents().get(index);
+    }
+
+    private List<MotionEvent> getCapturedEvents() {
+        return ((EventCaptor) mCaptor).mEvents;
+    }
+
+    private MotionEvent downEvent() {
+        mLastDownTime = SystemClock.uptimeMillis();
+        return fromTouchscreen(
+                MotionEvent.obtain(mLastDownTime, mLastDownTime, MotionEvent.ACTION_DOWN, DEFAULT_X,
+                        DEFAULT_Y, 0));
+    }
+
+    private MotionEvent pointerDownEvent() {
+        final int secondPointerId = 0x0100;
+        final int action = MotionEvent.ACTION_POINTER_DOWN | secondPointerId;
+        final float[] x = new float[]{DEFAULT_X, DEFAULT_X + 29};
+        final float[] y = new float[]{DEFAULT_Y, DEFAULT_Y + 28};
+        return manyPointerEvent(action, x, y);
+    }
+
+    private MotionEvent thirdPointerDownEvent() {
+        final int thirdPointerId = 0x0200;
+        final int action = MotionEvent.ACTION_POINTER_DOWN | thirdPointerId;
+        final float[] x = new float[]{DEFAULT_X, DEFAULT_X + 29, DEFAULT_X + 59};
+        final float[] y = new float[]{DEFAULT_Y, DEFAULT_Y + 28, DEFAULT_Y + 58};
+        return manyPointerEvent(action, x, y);
+    }
+
+    private void moveEachPointers(MotionEvent event, PointF... points) {
+        final float[] x = new float[points.length];
+        final float[] y = new float[points.length];
+        for (int i = 0; i < points.length; i++) {
+            x[i] = event.getX(i) + points[i].x;
+            y[i] = event.getY(i) + points[i].y;
+        }
+        MotionEvent newEvent = manyPointerEvent(MotionEvent.ACTION_MOVE, x, y);
+        event.setAction(MotionEvent.ACTION_MOVE);
+        // add history count
+        event.addBatch(newEvent);
+    }
+
+    private MotionEvent manyPointerEvent(int action, float[] x, float[] y) {
+        return manyPointerEvent(action, x, y, mLastDownTime);
+    }
+
+    private MotionEvent manyPointerEvent(int action, float[] x, float[] y, long downTime) {
+        final int len = x.length;
+
+        final MotionEvent.PointerProperties[] pp = new MotionEvent.PointerProperties[len];
+        for (int i = 0; i < len; i++) {
+            MotionEvent.PointerProperties pointerProperty = new MotionEvent.PointerProperties();
+            pointerProperty.id = i;
+            pointerProperty.toolType = MotionEvent.TOOL_TYPE_FINGER;
+            pp[i] = pointerProperty;
+        }
+
+        final MotionEvent.PointerCoords[] pc = new MotionEvent.PointerCoords[len];
+        for (int i = 0; i < len; i++) {
+            MotionEvent.PointerCoords pointerCoord = new MotionEvent.PointerCoords();
+            pointerCoord.x = x[i];
+            pointerCoord.y = y[i];
+            pc[i] = pointerCoord;
+        }
+
+        return MotionEvent.obtain(
+                /* downTime */ SystemClock.uptimeMillis(),
+                /* eventTime */ downTime,
+                /* action */ action,
+                /* pointerCount */ pc.length,
+                /* pointerProperties */ pp,
+                /* pointerCoords */ pc,
+                /* metaState */ 0,
+                /* buttonState */ 0,
+                /* xPrecision */ 1.0f,
+                /* yPrecision */ 1.0f,
+                /* deviceId */ 0,
+                /* edgeFlags */ 0,
+                /* source */ InputDevice.SOURCE_TOUCHSCREEN,
+                /* flags */ 0);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 149ef15..7a96f4c 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -17,6 +17,7 @@
 package com.android.server.accounts;
 
 import static android.database.sqlite.SQLiteDatabase.deleteDatabase;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
@@ -25,7 +26,6 @@
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.nullable;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -35,11 +35,10 @@
 import android.accounts.CantAddAccountActivity;
 import android.accounts.IAccountManagerResponse;
 import android.app.AppOpsManager;
+import android.app.INotificationManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
-import android.app.INotificationManager;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -48,6 +47,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
 import android.content.pm.UserInfo;
@@ -67,7 +67,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
-import com.android.frameworks.servicestests.R;
 import com.android.server.LocalServices;
 
 import org.mockito.ArgumentCaptor;
@@ -90,7 +89,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 
-
 /**
  * Tests for {@link AccountManagerService}.
  * <p>Run with:<pre>
@@ -98,7 +96,7 @@
  * adb install -r ${OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
  * adb shell am instrument -w -e package com.android.server.accounts \
  * com.android.frameworks.servicestests\
- * /android.support.test.runner.AndroidJUnitRunner
+ * /androidx.test.runner.AndroidJUnitRunner
  * </pre>
  */
 public class AccountManagerServiceTest extends AndroidTestCase {
@@ -114,6 +112,7 @@
     @Mock private IAccountManagerResponse mMockAccountManagerResponse;
     @Mock private IBinder mMockBinder;
     @Mock private INotificationManager mMockNotificationManager;
+    @Mock private PackageManagerInternal mMockPackageManagerInternal;
 
     @Captor private ArgumentCaptor<Intent> mIntentCaptor;
     @Captor private ArgumentCaptor<Bundle> mBundleCaptor;
@@ -158,6 +157,9 @@
         when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
                 mMockDevicePolicyManager);
         when(mMockAccountManagerResponse.asBinder()).thenReturn(mMockBinder);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(true);
+        LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
 
         Context realTestContext = getContext();
         MyMockContext mockContext = new MyMockContext(realTestContext, mMockContext);
@@ -177,6 +179,7 @@
             cdl.countDown();
         });
         cdl.await(1, TimeUnit.SECONDS);
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
         super.tearDown();
     }
 
@@ -610,6 +613,8 @@
                 any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
         when(mMockPackageManager.checkSignatures(
                 anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
 
         final CountDownLatch latch = new CountDownLatch(1);
         Response response = new Response(latch, mMockAccountManagerResponse);
@@ -626,7 +631,7 @@
         waitForLatch(latch);
         verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
         verify(mMockAccountManagerResponse).onError(
-                eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString());
+                eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), anyString());
     }
 
     @SmallTest
@@ -792,6 +797,8 @@
                 any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
         when(mMockPackageManager.checkSignatures(
                 anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
 
         final CountDownLatch latch = new CountDownLatch(1);
         Response response = new Response(latch, mMockAccountManagerResponse);
@@ -808,7 +815,7 @@
         waitForLatch(latch);
         verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
         verify(mMockAccountManagerResponse).onError(
-                eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString());
+                eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), anyString());
     }
 
     @SmallTest
@@ -1092,6 +1099,8 @@
                 any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
         when(mMockPackageManager.checkSignatures(
                 anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
 
         final CountDownLatch latch = new CountDownLatch(1);
         Response response = new Response(latch, mMockAccountManagerResponse);
@@ -1106,7 +1115,7 @@
         waitForLatch(latch);
         verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
         verify(mMockAccountManagerResponse).onError(
-                eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString());
+                eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), anyString());
     }
 
     @SmallTest
@@ -1352,6 +1361,8 @@
         unlockSystemUser();
         when(mMockPackageManager.checkSignatures(anyInt(), anyInt()))
                     .thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
         try {
             mAms.removeAccountAsUser(
                 mMockAccountManagerResponse, // response
@@ -1688,6 +1699,8 @@
                 any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
         when(mMockPackageManager.checkSignatures(
                 anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
 
         final CountDownLatch latch = new CountDownLatch(1);
         Response response = new Response(latch, mMockAccountManagerResponse);
@@ -1701,7 +1714,7 @@
         waitForLatch(latch);
         verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
         verify(mMockAccountManagerResponse).onError(
-                eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString());
+                eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), anyString());
     }
 
     @SmallTest
@@ -1959,6 +1972,8 @@
                 any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
         when(mMockPackageManager.checkSignatures(
                 anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
 
         final CountDownLatch latch = new CountDownLatch(1);
         Response response = new Response(latch, mMockAccountManagerResponse);
@@ -1974,7 +1989,7 @@
         waitForLatch(latch);
         verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
         verify(mMockAccountManagerResponse).onError(
-                eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString());
+                eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), anyString());
     }
 
     @SmallTest
@@ -2097,6 +2112,8 @@
                 any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
         when(mMockPackageManager.checkSignatures(
                 anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
 
         final CountDownLatch latch = new CountDownLatch(1);
         Response response = new Response(latch, mMockAccountManagerResponse);
@@ -2110,7 +2127,7 @@
 
         verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
         verify(mMockAccountManagerResponse).onError(
-                eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString());
+                eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), anyString());
     }
 
     @SmallTest
@@ -2230,6 +2247,8 @@
                 any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
         when(mMockPackageManager.checkSignatures(
                 anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
 
         final CountDownLatch latch = new CountDownLatch(1);
         Response response = new Response(latch, mMockAccountManagerResponse);
@@ -2245,7 +2264,7 @@
 
         verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
         verify(mMockAccountManagerResponse).onError(
-                eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString());
+                eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), anyString());
     }
 
     @SmallTest
@@ -2332,6 +2351,8 @@
         unlockSystemUser();
         when(mMockPackageManager.checkSignatures(anyInt(), anyInt()))
                     .thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
         try {
             mAms.editProperties(
                 mMockAccountManagerResponse, // response
@@ -2621,6 +2642,8 @@
                 PackageManager.PERMISSION_DENIED);
         when(mMockPackageManager.checkSignatures(anyInt(), anyInt()))
                     .thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+        when(mMockPackageManagerInternal.hasSignatureCapability(anyInt(), anyInt(), anyInt()))
+                .thenReturn(false);
 
         final CountDownLatch latch = new CountDownLatch(1);
         Response response = new Response(latch, mMockAccountManagerResponse);
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
index 5d0c23f..72c22fd 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
@@ -17,14 +17,21 @@
 
 package com.android.server.accounts;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 import android.accounts.Account;
 import android.content.Context;
 import android.database.Cursor;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+import android.os.Build;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Pair;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -35,11 +42,6 @@
 import java.util.List;
 import java.util.Map;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
 /**
  * Tests for {@link AccountsDb}.
  * <p>Run with:<pre>
@@ -47,7 +49,7 @@
  * adb install \
  * -r out/target/product/marlin/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  * adb shell am instrument -e class com.android.server.accounts.AccountsDbTest \
- * -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ * -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  * </pre>
  */
 @RunWith(AndroidJUnit4.class)
@@ -85,6 +87,12 @@
 
     @Test
     public void testCeNotAvailableInitially() {
+        // If the CE database is not attached to the DE database then any calls that modify the CE
+        // database will result in a Log.wtf call that will crash this process on eng builds. To
+        // allow the test to run through to completion skip this test on eng builds.
+        if (Build.IS_ENG) {
+            return;
+        }
         Account account = new Account("name", "example.com");
         long id = mAccountsDb.insertCeAccount(account, "");
         assertEquals("Insert into CE should fail until CE database is attached", -1, id);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
index 583a9dd..9de64f2 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
@@ -16,28 +16,29 @@
 
 package com.android.server.am;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.app.ActivityOptions;
 import android.content.pm.ActivityInfo;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.am.LaunchParamsController.LaunchParams;
-import org.junit.runner.RunWith;
+
 import org.junit.Before;
 import org.junit.Test;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.doAnswer;
-
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for exercising resizing bounds due to activity options.
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
index bce87dc..9a7488e 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
@@ -21,8 +21,9 @@
 
 import android.app.ActivityManagerInternal;
 import android.os.SystemClock;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -43,7 +44,7 @@
  * Install: adb install -r \
  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
  * Run: adb shell am instrument -e class com.android.server.am.ActivityManagerInternalTest -w \
- *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ *     com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @RunWith(AndroidJUnit4.class)
 public class ActivityManagerInternalTest {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index c70d1e1..47ce879 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -28,6 +28,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.util.DebugUtils.valueToString;
+
 import static com.android.server.am.ActivityManagerInternalTest.CustomThread;
 import static com.android.server.am.ActivityManagerService.DISPATCH_UIDS_CHANGED_UI_MSG;
 import static com.android.server.am.ActivityManagerService.Injector;
@@ -62,11 +63,11 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 
-import com.android.internal.os.BatteryStatsImpl;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.AppOpsService;
 
 import org.junit.After;
@@ -98,7 +99,7 @@
  * Install: adb install -r \
  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
  * Run: adb shell am instrument -e class com.android.server.am.ActivityManagerServiceTest -w \
- *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ *     com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -121,7 +122,6 @@
     @Mock private Context mContext;
     @Mock private AppOpsService mAppOpsService;
     @Mock private PackageManager mPackageManager;
-    @Mock private BatteryStatsImpl mBatteryStatsImpl;
 
     private TestInjector mInjector;
     private ActivityManagerService mAms;
@@ -258,8 +258,7 @@
         uidRec.hasInternetPermission = true;
         mAms.mActiveUids.put(uid, uidRec);
 
-        final ProcessRecord appRec = new ProcessRecord(null, mBatteryStatsImpl,
-                new ApplicationInfo(), TAG, uid);
+        final ProcessRecord appRec = new ProcessRecord(mAms, new ApplicationInfo(), TAG, uid);
         appRec.thread = Mockito.mock(IApplicationThread.class);
         mAms.mLruProcesses.add(appRec);
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityOptionsTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityOptionsTest.java
new file mode 100644
index 0000000..d15bff4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityOptionsTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.ActivityOptions;
+import android.os.Bundle;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * atest FrameworksServicesTests:ActivityOptionsTest
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ActivityOptionsTest {
+
+    @Test
+    public void testMerge_NoClobber() {
+        // Construct some options with set values
+        ActivityOptions opts = ActivityOptions.makeBasic();
+        opts.setLaunchDisplayId(Integer.MAX_VALUE);
+        opts.setLaunchActivityType(ACTIVITY_TYPE_STANDARD);
+        opts.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        opts.setAvoidMoveToFront();
+        opts.setLaunchTaskId(Integer.MAX_VALUE);
+        opts.setLockTaskEnabled(true);
+        opts.setRotationAnimationHint(ROTATION_ANIMATION_ROTATE);
+        opts.setTaskOverlay(true, true);
+        opts.setSplitScreenCreateMode(SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
+        Bundle optsBundle = opts.toBundle();
+
+        // Try and merge the constructed options with a new set of options
+        optsBundle.putAll(ActivityOptions.makeBasic().toBundle());
+
+        // Ensure the set values are not clobbered
+        ActivityOptions restoredOpts = ActivityOptions.fromBundle(optsBundle);
+        assertEquals(Integer.MAX_VALUE, restoredOpts.getLaunchDisplayId());
+        assertEquals(ACTIVITY_TYPE_STANDARD, restoredOpts.getLaunchActivityType());
+        assertEquals(WINDOWING_MODE_FULLSCREEN, restoredOpts.getLaunchWindowingMode());
+        assertEquals(true, restoredOpts.getAvoidMoveToFront());
+        assertEquals(Integer.MAX_VALUE, restoredOpts.getLaunchTaskId());
+        assertEquals(true, restoredOpts.getLockTaskMode());
+        assertEquals(ROTATION_ANIMATION_ROTATE, restoredOpts.getRotationAnimationHint());
+        assertEquals(true, restoredOpts.getTaskOverlay());
+        assertEquals(true, restoredOpts.canTaskOverlayResume());
+        assertEquals(SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
+                restoredOpts.getSplitScreenCreateMode());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index dd3e5a8..2338744 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -22,11 +22,7 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.view.Display.DEFAULT_DISPLAY;
 
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
-import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
 import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
-import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
@@ -53,14 +49,14 @@
 import android.app.servertransaction.PauseActivityItem;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.MutableBoolean;
 
-import org.junit.runner.RunWith;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.invocation.InvocationOnMock;
 
 /**
@@ -136,7 +132,8 @@
         assertFalse(pauseFound.value);
 
         // Clear focused stack
-        mActivity.mStackSupervisor.mFocusedStack = null;
+        final ActivityDisplay display = mActivity.mStackSupervisor.getDefaultDisplay();
+        when(display.getFocusedStack()).thenReturn(null);
 
         // In the unfocused stack, the activity should move to paused.
         mActivity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index f92ca5f..20df2ae 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -27,8 +27,7 @@
 import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
 
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.am.ActivityStackSupervisor
-        .MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -47,10 +46,11 @@
 import android.app.WaitResult;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseIntArray;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -84,12 +84,12 @@
     }
 
     /**
-     * This test ensures that we do not try to restore a task based off an invalid task id. The
-     * stack supervisor is a test version so there will be no tasks present. We should expect
-     * {@code null} to be returned in this case.
+     * This test ensures that we do not try to restore a task based off an invalid task id. We
+     * should expect {@code null} to be returned in this case.
      */
     @Test
     public void testRestoringInvalidTask() throws Exception {
+        ((TestActivityDisplay) mSupervisor.getDefaultDisplay()).removeAllTasks();
         TaskRecord task = mSupervisor.anyTaskForIdLocked(0 /*taskId*/,
                 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null, false /* onTop */);
         assertNull(task);
@@ -109,7 +109,7 @@
                 .setStack(mFullscreenStack).build();
         final TaskRecord secondTask = secondActivity.getTask();
 
-        mSupervisor.setFocusStackUnchecked("testReplacingTaskInPinnedStack", mFullscreenStack);
+        mFullscreenStack.moveToFront("testReplacingTaskInPinnedStack");
 
         // Ensure full screen stack has both tasks.
         ensureStackPlacement(mFullscreenStack, firstTask, secondTask);
@@ -239,7 +239,7 @@
         doReturn(displaySleeping).when(display).isSleeping();
         doReturn(keyguardShowing).when(keyguard).isKeyguardOrAodShowing(anyInt());
 
-        mSupervisor.mFocusedStack = isFocusedStack ? stack : null;
+        doReturn(isFocusedStack ? stack : null).when(display).getFocusedStack();
         mSupervisor.applySleepTokensLocked(true);
         verify(stack, times(expectWakeFromSleep ? 1 : 0)).awakeFromSleepingLocked();
         verify(stack, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked(
@@ -253,12 +253,11 @@
 
         doAnswer((InvocationOnMock invocationOnMock) -> {
             final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0);
-            displayIds.put(0, unknownDisplayId);
+            displayIds.put(0, 0);
+            displayIds.put(1, unknownDisplayId);
             return null;
         }).when(mSupervisor.mWindowManager).getDisplaysInFocusOrder(any());
 
-        mSupervisor.mFocusedStack = mock(ActivityStack.class);
-
         // Supervisor should skip over the non-existent display.
         assertEquals(null, mSupervisor.topRunningActivityLocked());
     }
@@ -330,8 +329,9 @@
     @Test
     public void testTopRunningActivity() throws Exception {
         // Create stack to hold focus
-        final ActivityStack emptyStack = mService.mStackSupervisor.getDefaultDisplay()
-                .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
+        final ActivityStack emptyStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         final KeyguardController keyguard = mSupervisor.getKeyguardController();
         final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
@@ -339,11 +339,9 @@
         final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
                 .setStack(stack).build();
 
-        mSupervisor.mFocusedStack = emptyStack;
-
         doAnswer((InvocationOnMock invocationOnMock) -> {
             final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0);
-            displayIds.put(0, mSupervisor.getDefaultDisplay().mDisplayId);
+            displayIds.put(0, display.mDisplayId);
             return null;
         }).when(mSupervisor.mWindowManager).getDisplaysInFocusOrder(any());
 
@@ -359,7 +357,8 @@
                 true /* considerKeyguardState */));
 
         // Change focus to stack with activity.
-        mSupervisor.mFocusedStack = stack;
+        stack.moveToFront("focusChangeToTestStack");
+        assertEquals(stack, display.getFocusedStack());
         assertEquals(activity, mService.mStackSupervisor.topRunningActivityLocked());
         assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked(
                 true /* considerKeyguardState */));
@@ -377,10 +376,12 @@
                 true /* considerKeyguardState */));
 
         // Change focus back to empty stack
-        mSupervisor.mFocusedStack = emptyStack;
-        // Ensure the show when locked activity is returned when not the focused stack
-        assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked());
-        assertEquals(showWhenLockedActivity, mService.mStackSupervisor.topRunningActivityLocked(
+        emptyStack.moveToFront("focusChangeToEmptyStack");
+        assertEquals(emptyStack, display.getFocusedStack());
+        // Looking for running activity only in top and focused stack, so nothing should be returned
+        // from empty stack.
+        assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked());
+        assertEquals(null, mService.mStackSupervisor.topRunningActivityLocked(
                 true /* considerKeyguardState */));
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 4094716..59b0890 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -34,23 +34,20 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 
 import android.content.pm.ActivityInfo;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 
-import org.junit.runner.RunWith;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for the {@link ActivityStack} class.
@@ -167,7 +164,7 @@
     public void testStopActivityWhenActivityDestroyed() throws Exception {
         final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
         r.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
-        mSupervisor.setFocusStackUnchecked("testStopActivityWithDestroy", mStack);
+        mStack.moveToFront("testStopActivityWithDestroy");
         mStack.stopActivityLocked(r);
         // Mostly testing to make sure there is a crash in the call part, so if we get here we are
         // good-to-go!
@@ -507,6 +504,15 @@
         // Ensure, when always on top is turned off for a stack, the stack is put just below all
         // other always on top stacks.
         assertTrue(mDefaultDisplay.getStackAbove(alwaysOnTopStack2) == alwaysOnTopStack);
+        alwaysOnTopStack2.setAlwaysOnTop(true);
+
+        // Ensure always on top state changes properly when windowing mode changes.
+        alwaysOnTopStack2.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        assertFalse(alwaysOnTopStack2.isAlwaysOnTop());
+        assertTrue(mDefaultDisplay.getStackAbove(alwaysOnTopStack2) == alwaysOnTopStack);
+        alwaysOnTopStack2.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertTrue(alwaysOnTopStack2.isAlwaysOnTop());
+        assertTrue(mDefaultDisplay.getStackAbove(alwaysOnTopStack2) == pinnedStack);
     }
 
     @Test
@@ -537,9 +543,20 @@
 
     private <T extends ActivityStack> T createStackForShouldBeVisibleTest(
             ActivityDisplay display, int windowingMode, int activityType, boolean onTop) {
-        final T stack = display.createStack(windowingMode, activityType, onTop);
-        final ActivityRecord r = new ActivityBuilder(mService).setUid(0).setStack(stack)
-                .setCreateTask(true).build();
+        final T stack;
+        if (activityType == ACTIVITY_TYPE_HOME) {
+            // Home stack and activity are created in ActivityTestsBase#setupActivityManagerService
+            stack = mDefaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+            if (onTop) {
+                mDefaultDisplay.positionChildAtTop(stack, false /* includingParents */);
+            } else {
+                mDefaultDisplay.positionChildAtBottom(stack);
+            }
+        } else {
+            stack = display.createStack(windowingMode, activityType, onTop);
+            final ActivityRecord r = new ActivityBuilder(mService).setUid(0).setStack(stack)
+                    .setCreateTask(true).build();
+        }
         return stack;
     }
 
@@ -645,14 +662,13 @@
 
     private void verifyShouldSleepActivities(boolean focusedStack,
             boolean keyguardGoingAway, boolean displaySleeping, boolean expected) {
-        mSupervisor.mFocusedStack = focusedStack ? mStack : null;
-
         final ActivityDisplay display = mock(ActivityDisplay.class);
         final KeyguardController keyguardController = mSupervisor.getKeyguardController();
 
         doReturn(display).when(mSupervisor).getActivityDisplay(anyInt());
         doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway();
         doReturn(displaySleeping).when(display).isSleeping();
+        doReturn(focusedStack ? mStack : null).when(mSupervisor).getTopDisplayFocusedStack();
 
         assertEquals(expected, mStack.shouldSleepActivities());
     }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
index f5ae46cd..e1ebbcf 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
@@ -19,25 +19,26 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
-import android.app.IApplicationThread;
-import android.content.Intent;
-import android.os.UserHandle;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
-import com.android.server.am.ActivityStarter.Factory;
-
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.IApplicationThread;
+import android.content.Intent;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
+import com.android.server.am.ActivityStarter.Factory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.Random;
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
index 7f55824..86541b9 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.when;
 
+import android.app.ActivityManagerInternal;
 import android.app.KeyguardManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Context;
@@ -38,12 +39,13 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
 import android.testing.DexmakerShareClassLoaderRule;
 
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.app.HarmfulAppWarningActivity;
 import com.android.internal.app.SuspendedAppActivity;
 import com.android.internal.app.UnlaunchableAppActivity;
-import com.android.internal.app.HarmfulAppWarningActivity;
 import com.android.server.LocalServices;
 import com.android.server.pm.PackageManagerService;
 
@@ -94,11 +96,11 @@
     @Mock
     private UserManager mUserManager;
     @Mock
-    private UserController mUserController;
-    @Mock
     private KeyguardManager mKeyguardManager;
     @Mock
     private PackageManagerService mPackageManager;
+    @Mock
+    private ActivityManagerInternal mAmInternal;
 
     private ActivityStartInterceptor mInterceptor;
     private ActivityInfo mAInfo = new ActivityInfo();
@@ -107,18 +109,22 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mService.mAm = mAm;
-        mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext,
-                mUserController);
+        mService.mAmInternal = mAmInternal;
+        mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext);
         mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID,
                 TEST_START_FLAGS, TEST_CALLING_PACKAGE);
 
+        // Mock ActivityManagerInternal
+        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+        LocalServices.addService(ActivityManagerInternal.class, mAmInternal);
+
         // Mock DevicePolicyManagerInternal
         LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
         LocalServices.addService(DevicePolicyManagerInternal.class,
                 mDevicePolicyManager);
         when(mDevicePolicyManager.createShowAdminSupportIntent(TEST_USER_ID, true))
                 .thenReturn(ADMIN_SUPPORT_INTENT);
-        when(mAm.getPackageManagerInternalLocked()).thenReturn(mPackageManagerInternal);
+        when(mService.getPackageManagerInternalLocked()).thenReturn(mPackageManagerInternal);
 
         // Mock UserManager
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
@@ -131,7 +137,7 @@
                 thenReturn(CONFIRM_CREDENTIALS_INTENT);
 
         // Mock PackageManager
-        when(mAm.getPackageManager()).thenReturn(mPackageManager);
+        when(mService.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.getHarmfulAppWarning(TEST_PACKAGE_NAME, TEST_USER_ID))
                 .thenReturn(null);
 
@@ -193,7 +199,7 @@
     @Test
     public void testWorkChallenge() {
         // GIVEN that the user the activity is starting as is currently locked
-        when(mUserController.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
+        when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
 
         // THEN calling intercept returns true
         mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index 267e689..d032eb5 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -32,28 +32,8 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-
-import android.app.ActivityOptions;
-import android.app.IApplicationThread;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ActivityInfo.WindowLayout;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.platform.test.annotations.Presubmit;
-import android.service.voice.IVoiceInteractionSession;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.Gravity;
-
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
 import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
+
 import static com.android.server.am.ActivityManagerService.ANIMATE;
 
 import static org.junit.Assert.assertEquals;
@@ -63,20 +43,58 @@
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyObject;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityOptions;
+import android.app.IApplicationThread;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ActivityInfo.WindowLayout;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.service.voice.IVoiceInteractionSession;
+import android.view.Gravity;
+
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
+import static com.android.server.am.ActivityManagerService.ANIMATE;
+import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyObject;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+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.times;
 
-import com.android.internal.os.BatteryStatsImpl;
-import com.android.server.am.ActivityStarter.Factory;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
 import com.android.server.am.TaskRecord.TaskRecordFactory;
 
-import java.util.ArrayList;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for the {@link ActivityStarter} class.
@@ -91,6 +109,7 @@
     private ActivityTaskManagerService mService;
     private ActivityStarter mStarter;
     private ActivityStartController mController;
+    private ActivityMetricsLogger mActivityMetricsLogger;
 
     private static final int PRECONDITION_NO_CALLER_APP = 1;
     private static final int PRECONDITION_NO_INTENT_COMPONENT = 1 << 1;
@@ -104,11 +123,17 @@
     private static final int PRECONDITION_CANNOT_START_ANY_ACTIVITY = 1 << 9;
     private static final int PRECONDITION_DISALLOW_APP_SWITCHING = 1 << 10;
 
+    private static final int FAKE_CALLING_UID = 666;
+    private static final int FAKE_REAL_CALLING_UID = 667;
+    private static final String FAKE_CALLING_PACKAGE = "com.whatever.dude";
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
         mService = createActivityTaskManagerService();
         mController = mock(ActivityStartController.class);
+        mActivityMetricsLogger = mock(ActivityMetricsLogger.class);
+        clearInvocations(mActivityMetricsLogger);
         mStarter = new ActivityStarter(mController, mService, mService.mStackSupervisor,
                 mock(ActivityStartInterceptor.class));
     }
@@ -200,8 +225,7 @@
 
         // If no caller app, return {@code null} {@link ProcessRecord}.
         final ProcessRecord record = containsConditions(preconditions, PRECONDITION_NO_CALLER_APP)
-                ? null : new ProcessRecord(service.mAm, mock(BatteryStatsImpl.class),
-                mock(ApplicationInfo.class), null, 0);
+                ? null : new ProcessRecord(service.mAm, mock(ApplicationInfo.class), null, 0);
 
         doReturn(record).when(service.mAm).getRecordForAppLocked(anyObject());
 
@@ -312,9 +336,6 @@
                 .setCreateStack(false)
                 .build();
 
-        // supervisor needs a focused stack.
-        mService.mStackSupervisor.mFocusedStack = stack;
-
         // use factory that only returns spy task.
         final TaskRecordFactory factory = mock(TaskRecordFactory.class);
         TaskRecord.setTaskRecordFactory(factory);
@@ -328,6 +349,16 @@
         doReturn(stack).when(mService.mStackSupervisor)
                 .getLaunchStack(any(), any(), any(), anyBoolean(), anyInt());
 
+        // Set up mock package manager internal and make sure no unmocked methods are called
+        PackageManagerInternal mockPackageManager = mock(PackageManagerInternal.class,
+                invocation -> {
+                    throw new RuntimeException("Not stubbed");
+                });
+        doReturn(mockPackageManager).when(mService.mAm).getPackageManagerInternalLocked();
+
+        // Never review permissions
+        doReturn(false).when(mockPackageManager).isPermissionsReviewRequired(any(), anyInt());
+
         final Intent intent = new Intent();
         intent.addFlags(launchFlags);
         intent.setComponent(ActivityBuilder.getDefaultComponent());
@@ -404,8 +435,8 @@
         reusableActivity.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
 
         // Set focus back to primary.
-        mService.mStackSupervisor.setFocusStackUnchecked("testSplitScreenDeliverToTop",
-                focusActivity.getStack());
+        final ActivityStack focusStack = focusActivity.getStack();
+        focusStack.moveToFront("testSplitScreenDeliverToTop");
 
         doReturn(reusableActivity).when(mService.mStackSupervisor).findTaskLocked(any(), anyInt());
 
@@ -453,6 +484,7 @@
     @Test
     public void testTaskModeViolation() {
         final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
+        ((TestActivityDisplay) display).removeAllTasks();
         assertNoTasks(display);
 
         final ActivityStarter starter = prepareStarter(0);
@@ -472,4 +504,46 @@
             assertTrue(stack.getAllTasks().isEmpty());
         }
     }
+
+    /**
+     * This test ensures that activity starts are not being logged when the logging is disabled.
+     */
+    @Test
+    public void testActivityStartsLogging_noLoggingWhenDisabled() {
+        doReturn(false).when(mService.mAm).isActivityStartsLoggingEnabled();
+        doReturn(mActivityMetricsLogger).when(mService.mStackSupervisor).getActivityMetricsLogger();
+
+        ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK);
+        starter.setReason("testActivityStartsLogging_noLoggingWhenDisabled").execute();
+
+        // verify logging wasn't done
+        verify(mActivityMetricsLogger, never()).logActivityStart(any(), any(), any(), anyInt(),
+                any(), anyInt(), anyBoolean(), anyInt(), anyInt(), anyBoolean(), anyInt(), any(),
+                anyInt(), anyBoolean(), any(), anyBoolean());
+    }
+
+    /**
+     * This test ensures that activity starts are being logged when the logging is enabled.
+     */
+    @Test
+    public void testActivityStartsLogging_logsWhenEnabled() {
+        // note: conveniently this package doesn't have any activity visible
+        doReturn(true).when(mService.mAm).isActivityStartsLoggingEnabled();
+        doReturn(mActivityMetricsLogger).when(mService.mStackSupervisor).getActivityMetricsLogger();
+
+        ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)
+                .setCallingUid(FAKE_CALLING_UID)
+                .setRealCallingUid(FAKE_REAL_CALLING_UID)
+                .setCallingPackage(FAKE_CALLING_PACKAGE)
+                .setOriginatingPendingIntent(null);
+
+        starter.setReason("testActivityStartsLogging_logsWhenEnabled").execute();
+
+        // verify the above activity start was logged
+        verify(mActivityMetricsLogger, times(1)).logActivityStart(any(), any(), any(),
+                eq(FAKE_CALLING_UID), eq(FAKE_CALLING_PACKAGE), anyInt(), anyBoolean(),
+                eq(FAKE_REAL_CALLING_UID), anyInt(), anyBoolean(), anyInt(),
+                eq(ActivityBuilder.getDefaultComponent().getPackageName()), anyInt(), anyBoolean(),
+                any(), eq(false));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 1dd7b4c..9c0b525 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -16,23 +16,32 @@
 
 package com.android.server.am;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
+
+import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
+import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
+
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
+import android.content.pm.PackageManagerInternal;
+import com.android.server.uri.UriGrantsManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.DisplayWindowController;
 
 import org.junit.Rule;
@@ -53,23 +62,29 @@
 import android.os.Looper;
 import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionSession;
-import android.support.test.InstrumentationRegistry;
 import android.testing.DexmakerShareClassLoaderRule;
+import android.util.SparseIntArray;
 
+import androidx.test.InstrumentationRegistry;
 
 import com.android.internal.app.IVoiceInteractor;
-
 import com.android.server.AttributeCache;
 import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.DisplayWindowController;
 import com.android.server.wm.PinnedStackWindowController;
 import com.android.server.wm.StackWindowController;
 import com.android.server.wm.TaskWindowContainerController;
 import com.android.server.wm.WindowManagerService;
 import com.android.server.wm.WindowTestUtils;
+import com.android.server.uri.UriGrantsManagerInternal;
+
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
 
+import java.util.List;
 
 /**
  * A base class to handle common operations in activity related unit tests.
@@ -95,6 +110,7 @@
         if (!sOneTimeSetupDone) {
             sOneTimeSetupDone = true;
             MockitoAnnotations.initMocks(this);
+            AttributeCache.init(mContext);
         }
         mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
         mHandlerThread.start();
@@ -106,32 +122,44 @@
     }
 
     protected ActivityTaskManagerService createActivityTaskManagerService() {
-        final TestActivityTaskManagerService atm = spy(new TestActivityTaskManagerService(mContext));
+        final TestActivityTaskManagerService atm =
+                spy(new TestActivityTaskManagerService(mContext));
         setupActivityManagerService(atm);
         return atm;
     }
 
-    protected ActivityManagerService createActivityManagerService() {
-        final TestActivityTaskManagerService atm = spy(new TestActivityTaskManagerService(mContext));
+    ActivityManagerService createActivityManagerService() {
+        final TestActivityTaskManagerService atm =
+                spy(new TestActivityTaskManagerService(mContext));
         return setupActivityManagerService(atm);
     }
 
     ActivityManagerService setupActivityManagerService(TestActivityTaskManagerService atm) {
-        final ActivityManagerService am = spy(new TestActivityManagerService(mContext, atm));
+        final TestActivityManagerService am = spy(new TestActivityManagerService(mContext, atm));
         setupActivityManagerService(am, atm);
-        AttributeCache.init(mContext);
         return am;
     }
 
-    void setupActivityManagerService(ActivityManagerService am, ActivityTaskManagerService atm) {
+    void setupActivityManagerService(
+            TestActivityManagerService am, TestActivityTaskManagerService atm) {
         atm.setActivityManagerService(am);
-        atm.mAmInternal = am.new LocalService();
+        atm.mAmInternal = am.getLocalService();
+        am.mAtmInternal = atm.getLocalService();
         // Makes sure the supervisor is using with the spy object.
         atm.mStackSupervisor.setService(atm);
         doReturn(mock(IPackageManager.class)).when(am).getPackageManager();
         doNothing().when(am).grantEphemeralAccessLocked(anyInt(), any(), anyInt(), anyInt());
         am.mWindowManager = prepareMockWindowManager();
         atm.setWindowManager(am.mWindowManager);
+
+        // Put a home stack on the default display, so that we'll always have something focusable.
+        final TestActivityStackSupervisor supervisor =
+                (TestActivityStackSupervisor) atm.mStackSupervisor;
+        supervisor.mHomeStack = supervisor.mDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_HOME, ON_TOP);
+        final TaskRecord task = new TaskBuilder(atm.mStackSupervisor)
+                .setStack(supervisor.mHomeStack).build();
+        new ActivityBuilder(atm).setTask(task).build();
     }
 
     /**
@@ -245,7 +273,8 @@
         private ComponentName mComponent;
         private String mPackage;
         private int mFlags = 0;
-        private int mTaskId = 0;
+        // Task id 0 is reserved in ARC for the home app.
+        private int mTaskId = 1;
         private int mUserId = 0;
         private IVoiceInteractionSession mVoiceSession;
         private boolean mCreateStack = true;
@@ -324,7 +353,7 @@
             task.userId = mUserId;
 
             if (mStack != null) {
-                mSupervisor.setFocusStackUnchecked("test", mStack);
+                mStack.moveToFront("test");
                 mStack.addTask(task, true, "creating test task");
                 task.setStack(mStack);
                 task.setWindowContainerController();
@@ -355,6 +384,8 @@
 
     protected static class TestActivityTaskManagerService extends ActivityTaskManagerService {
         private LockTaskController mLockTaskController;
+        private ActivityTaskManagerInternal mInternal;
+        private PackageManagerInternal mPmInternal;
 
         TestActivityTaskManagerService(Context context) {
             super(context);
@@ -363,6 +394,7 @@
             mSupportsSplitScreenMultiWindow = true;
             mSupportsFreeformWindowManagement = true;
             mSupportsPictureInPicture = true;
+            mUgmInternal = mock(UriGrantsManagerInternal.class);
         }
 
         @Override
@@ -407,16 +439,34 @@
         protected ActivityStackSupervisor createTestSupervisor() {
             return new TestActivityStackSupervisor(this, mH.getLooper());
         }
+
+        ActivityTaskManagerInternal getLocalService() {
+            if (mInternal == null) {
+                mInternal = new ActivityTaskManagerService.LocalService();
+            }
+            return mInternal;
+        }
+
+        PackageManagerInternal getPackageManagerInternalLocked() {
+            if (mPmInternal == null) {
+                mPmInternal = mock(PackageManagerInternal.class);
+                doReturn(false).when(mPmInternal).isPermissionsReviewRequired(anyString(), anyInt());
+            }
+            return mPmInternal;
+        }
     }
 
     /**
      * An {@link ActivityManagerService} subclass which provides a test
      * {@link ActivityStackSupervisor}.
      */
-    protected static class TestActivityManagerService extends ActivityManagerService {
+    static class TestActivityManagerService extends ActivityManagerService {
+
+        private ActivityManagerInternal mInternal;
 
         TestActivityManagerService(Context context, TestActivityTaskManagerService atm) {
             super(context, atm);
+            mUgmInternal = mock(UriGrantsManagerInternal.class);
         }
 
         @Override
@@ -427,6 +477,13 @@
         Configuration getGlobalConfiguration() {
             return mContext.getResources().getConfiguration();
         }
+
+        ActivityManagerInternal getLocalService() {
+            if (mInternal == null) {
+                mInternal = new LocalService();
+            }
+            return mInternal;
+        }
     }
 
     /**
@@ -461,13 +518,6 @@
         ActivityDisplay getDefaultDisplay() {
             return mDisplay;
         }
-
-        // Just return the current front task. This is called internally so we cannot use spy to mock this out.
-        @Override
-        ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus,
-                boolean ignoreCurrent) {
-            return mFocusedStack;
-        }
     }
 
     protected static class TestActivityDisplay extends ActivityDisplay {
@@ -504,6 +554,15 @@
         protected DisplayWindowController createWindowContainerController() {
             return mock(DisplayWindowController.class);
         }
+
+        void removeAllTasks() {
+            for (int i = 0; i < getChildCount(); i++) {
+                final ActivityStack stack = getChildAt(i);
+                for (TaskRecord task : (List<TaskRecord>) stack.getAllTasks()) {
+                    stack.removeTask(task, "removeAllTasks", REMOVE_TASK_MODE_DESTROYING);
+                }
+            }
+        }
     }
 
     private static WindowManagerService prepareMockWindowManager() {
@@ -517,6 +576,12 @@
             return null;
         }).when(service).inSurfaceTransaction(any());
 
+        doAnswer((InvocationOnMock invocationOnMock) -> {
+            final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0);
+            displayIds.put(0, 0);
+            return null;
+        }).when(service).getDisplaysInFocusOrder(any());
+
         return service;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
index 3d11c4c..87d367f 100644
--- a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
@@ -18,10 +18,11 @@
 
 import android.content.Context;
 import android.os.Handler;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.AppOpsService;
 
@@ -66,7 +67,7 @@
     @UiThreadTest
     public void testCreateWorks() throws Exception {
         AppErrorDialog.Data data = new AppErrorDialog.Data();
-        data.proc = new ProcessRecord(null, null, mContext.getApplicationInfo(), "name", 12345);
+        data.proc = new ProcessRecord(null, mContext.getApplicationInfo(), "name", 12345);
         data.result = new AppErrorResult();
 
         AppErrorDialog dialog = new AppErrorDialog(mContext, mService, data);
diff --git a/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java b/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
index f74d116..a030210 100644
--- a/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
@@ -42,12 +42,13 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 import android.view.IWindowManager;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.am.AssistDataRequester.AssistDataRequesterCallbacks;
 
 import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java b/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java
index 3257389..62c5734 100644
--- a/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java
@@ -25,8 +25,9 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java b/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java
index ef6d5e8..b4ad183 100644
--- a/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java
@@ -9,8 +9,9 @@
 import android.app.servertransaction.ClientTransaction;
 import android.os.Binder;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
index da30c11..fe8256e 100644
--- a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
@@ -26,18 +26,18 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.AppOpsService;
 
 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.Mock;
@@ -58,7 +58,7 @@
  * Install: adb install -r \
  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
  * Run: adb shell am instrument -e class com.android.server.am.CoreSettingsObserverTest -w \
- *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ *     com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java b/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
index d9b3e1c..765aaad 100644
--- a/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
@@ -18,11 +18,12 @@
 
 import android.content.ContentResolver;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.test.FakeSettingsProvider;
 
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
index fbe552d..d4bab2e 100644
--- a/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
@@ -16,20 +16,14 @@
 
 package com.android.server.am;
 
-import android.app.ActivityOptions;
-import android.content.pm.ActivityInfo.WindowLayout;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.server.am.LaunchParamsController.LaunchParams;
-import org.junit.runner.RunWith;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
-
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doNothing;
@@ -40,12 +34,19 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+import android.app.ActivityOptions;
+import android.content.pm.ActivityInfo.WindowLayout;
+import android.platform.test.annotations.Presubmit;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.am.LaunchParamsController.LaunchParams;
+import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for exercising {@link LaunchParamsController}.
diff --git a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
index f46d712..863a0d8 100644
--- a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
@@ -52,12 +52,13 @@
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
 import android.telecom.TelecomManager;
 import android.testing.DexmakerShareClassLoaderRule;
 import android.util.Pair;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
index 5518ca5..06c7437 100644
--- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
@@ -16,15 +16,15 @@
 
 package com.android.server.am;
 
+import static com.android.server.am.MemoryStatUtil.MemoryStat;
 import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromMemcg;
 import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromProcfs;
-import static com.android.server.am.MemoryStatUtil.MemoryStat;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
index e73661b..1c4e0f6 100644
--- a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
@@ -20,16 +20,14 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-import android.annotation.Nullable;
 import android.app.ActivityOptions;
-import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.ArrayMap;
 import android.view.RemoteAnimationAdapter;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.testutils.OffsettableClock;
 import com.android.server.testutils.TestHandler;
 
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index a4e4409..ba82487 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -35,14 +36,12 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 
-import static java.lang.Integer.MAX_VALUE;
-
 import android.app.ActivityManager.RecentTaskInfo;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityTaskManager;
+import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -51,24 +50,26 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.os.Debug;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.MutableLong;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.am.RecentTasks.Callbacks;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import static java.lang.Integer.MAX_VALUE;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -108,37 +109,6 @@
 
     private CallbacksRecorder mCallbacksRecorder;
 
-    class TestUserController extends UserController {
-        TestUserController(ActivityManagerService service) {
-            super(service);
-        }
-
-        @Override
-        int[] getCurrentProfileIds() {
-            return new int[] { TEST_USER_0_ID, TEST_QUIET_USER_ID };
-        }
-
-        @Override
-        Set<Integer> getProfileIds(int userId) {
-            Set<Integer> profileIds = new HashSet<>();
-            profileIds.add(TEST_USER_0_ID);
-            profileIds.add(TEST_QUIET_USER_ID);
-            return profileIds;
-        }
-
-        @Override
-        UserInfo getUserInfo(int userId) {
-            switch (userId) {
-                case TEST_USER_0_ID:
-                case TEST_USER_1_ID:
-                    return DEFAULT_USER_INFO;
-                case TEST_QUIET_USER_ID:
-                    return QUIET_USER_INFO;
-            }
-            return null;
-        }
-    }
-
     @Before
     @Override
     public void setUp() throws Exception {
@@ -146,11 +116,12 @@
 
         mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
         mService = spy(new MyTestActivityTaskManagerService(mContext));
-        final ActivityManagerService am = spy(new MyTestActivityManagerService(mContext, mService));
+        final TestActivityManagerService am =
+                spy(new MyTestActivityManagerService(mContext, mService));
         setupActivityManagerService(am, mService);
         mRecentTasks = (TestRecentTasks) mService.getRecentTasks();
         mRecentTasks.loadParametersFromResources(mContext.getResources());
-        mHomeStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+        mHomeStack = mService.mStackSupervisor.getDefaultDisplay().getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
@@ -306,13 +277,11 @@
     public void testAddTaskCompatibleActivityType_expectRemove() throws Exception {
         // Test with undefined activity type since the type is not persisted by the task persister
         // and we want to ensure that a new task will match a restored task
-        Configuration config1 = new Configuration();
-        config1.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
         TaskRecord task1 = createTaskBuilder(".Task1")
                 .setFlags(FLAG_ACTIVITY_NEW_TASK)
                 .setStack(mStack)
                 .build();
-        task1.onConfigurationChanged(config1);
+        setTaskActivityType(task1, ACTIVITY_TYPE_UNDEFINED);
         assertTrue(task1.getActivityType() == ACTIVITY_TYPE_UNDEFINED);
         mRecentTasks.add(task1);
         mCallbacksRecorder.clear();
@@ -332,14 +301,12 @@
 
     @Test
     public void testAddTaskCompatibleActivityTypeDifferentUser_expectNoRemove() throws Exception {
-        Configuration config1 = new Configuration();
-        config1.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
         TaskRecord task1 = createTaskBuilder(".Task1")
                 .setFlags(FLAG_ACTIVITY_NEW_TASK)
                 .setStack(mStack)
                 .setUserId(TEST_USER_0_ID)
                 .build();
-        task1.onConfigurationChanged(config1);
+        setTaskActivityType(task1, ACTIVITY_TYPE_UNDEFINED);
         assertTrue(task1.getActivityType() == ACTIVITY_TYPE_UNDEFINED);
         mRecentTasks.add(task1);
         mCallbacksRecorder.clear();
@@ -359,24 +326,20 @@
 
     @Test
     public void testAddTaskCompatibleWindowingMode_expectRemove() throws Exception {
-        Configuration config1 = new Configuration();
-        config1.windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED);
         TaskRecord task1 = createTaskBuilder(".Task1")
                 .setFlags(FLAG_ACTIVITY_NEW_TASK)
                 .setStack(mStack)
                 .build();
-        task1.onConfigurationChanged(config1);
+        setTaskWindowingMode(task1, WINDOWING_MODE_UNDEFINED);
         assertTrue(task1.getWindowingMode() == WINDOWING_MODE_UNDEFINED);
         mRecentTasks.add(task1);
         mCallbacksRecorder.clear();
 
-        Configuration config2 = new Configuration();
-        config2.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         TaskRecord task2 = createTaskBuilder(".Task1")
                 .setFlags(FLAG_ACTIVITY_NEW_TASK)
                 .setStack(mStack)
                 .build();
-        task2.onConfigurationChanged(config2);
+        setTaskWindowingMode(task2, WINDOWING_MODE_FULLSCREEN);
         assertTrue(task2.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
         mRecentTasks.add(task2);
 
@@ -389,23 +352,19 @@
 
     @Test
     public void testAddTaskIncompatibleWindowingMode_expectNoRemove() throws Exception {
-        Configuration config1 = new Configuration();
-        config1.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         TaskRecord task1 = createTaskBuilder(".Task1")
                 .setFlags(FLAG_ACTIVITY_NEW_TASK)
                 .setStack(mStack)
                 .build();
-        task1.onConfigurationChanged(config1);
+        setTaskWindowingMode(task1, WINDOWING_MODE_FULLSCREEN);
         assertTrue(task1.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
         mRecentTasks.add(task1);
 
-        Configuration config2 = new Configuration();
-        config2.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
         TaskRecord task2 = createTaskBuilder(".Task1")
                 .setFlags(FLAG_ACTIVITY_NEW_TASK)
                 .setStack(mStack)
                 .build();
-        task2.onConfigurationChanged(config2);
+        setTaskWindowingMode(task2, WINDOWING_MODE_PINNED);
         assertTrue(task2.getWindowingMode() == WINDOWING_MODE_PINNED);
         mRecentTasks.add(task2);
 
@@ -674,6 +633,43 @@
     }
 
     @Test
+    public void testRemoveAllVisibleTasks() throws Exception {
+        mRecentTasks.setParameters(-1 /* min */, 3 /* max */, 100 /* ms */);
+
+        // Create some set of tasks, some of which are visible and some are not
+        TaskRecord t1 = createTaskBuilder("com.android.pkg1", ".Task1").build();
+        mRecentTasks.add(t1);
+        mRecentTasks.add(setTaskActivityType(
+                createTaskBuilder("com.android.pkg1", ".HomeTask").build(),
+                ACTIVITY_TYPE_HOME));
+        TaskRecord t2 = createTaskBuilder("com.android.pkg2", ".Task2").build();
+        mRecentTasks.add(t2);
+        mRecentTasks.add(setTaskWindowingMode(
+                createTaskBuilder("com.android.pkg1", ".PipTask").build(),
+                WINDOWING_MODE_PINNED));
+        TaskRecord t3 = createTaskBuilder("com.android.pkg3", ".Task3").build();
+        mRecentTasks.add(t3);
+
+        // Create some more tasks that are out of visible range, but are still visible
+        TaskRecord t4 = createTaskBuilder("com.android.pkg3", ".Task4").build();
+        mRecentTasks.add(t4);
+        TaskRecord t5 = createTaskBuilder("com.android.pkg3", ".Task5").build();
+        mRecentTasks.add(t5);
+
+        // Create some more tasks that are out of the active session range, but are still visible
+        TaskRecord t6 = createTaskBuilder("com.android.pkg3", ".Task6").build();
+        t6.lastActiveTime = SystemClock.elapsedRealtime() - 200;
+        mRecentTasks.add(t6);
+        TaskRecord t7 = createTaskBuilder("com.android.pkg3", ".Task7").build();
+        t7.lastActiveTime = SystemClock.elapsedRealtime() - 200;
+        mRecentTasks.add(t7);
+
+        // Remove all the visible tasks and ensure that they are removed
+        mRecentTasks.removeAllVisibleTasks();
+        assertTrimmed(t1, t2, t3, t4, t5, t6, t7);
+    }
+
+    @Test
     public void testNotRecentsComponent_denyApiAccess() throws Exception {
         doReturn(PackageManager.PERMISSION_DENIED).when(mService)
                 .checkGetTasksPermission(anyString(), anyInt(), anyInt());
@@ -784,6 +780,22 @@
         return task;
     }
 
+    private TaskRecord setTaskActivityType(TaskRecord task,
+            @WindowConfiguration.ActivityType int activityType) {
+        Configuration config1 = new Configuration();
+        config1.windowConfiguration.setActivityType(activityType);
+        task.onConfigurationChanged(config1);
+        return task;
+    }
+
+    private TaskRecord setTaskWindowingMode(TaskRecord task,
+            @WindowConfiguration.WindowingMode int windowingMode) {
+        Configuration config1 = new Configuration();
+        config1.windowConfiguration.setWindowingMode(windowingMode);
+        task.onConfigurationChanged(config1);
+        return task;
+    }
+
     private boolean arrayContainsUser(int[] userIds, int targetUserId) {
         Arrays.sort(userIds);
         return Arrays.binarySearch(userIds, targetUserId) >= 0;
@@ -829,7 +841,7 @@
 
         @Override
         protected RecentTasks createRecentTasks() {
-            return new TestRecentTasks(this, mTaskPersister, new TestUserController(mAm));
+            return new TestRecentTasks(this, mTaskPersister);
         }
 
         @Override
@@ -910,7 +922,7 @@
         }
 
         @Override
-        public void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed) {
+        public void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed, boolean killProcess) {
             if (wasTrimmed) {
                 trimmed.add(task);
             }
@@ -954,9 +966,33 @@
 
         boolean lastAllowed;
 
-        TestRecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister,
-                UserController userController) {
-            super(service, taskPersister, userController);
+        TestRecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
+            super(service, taskPersister);
+        }
+
+        @Override
+        Set<Integer> getProfileIds(int userId) {
+            Set<Integer> profileIds = new HashSet<>();
+            profileIds.add(TEST_USER_0_ID);
+            profileIds.add(TEST_QUIET_USER_ID);
+            return profileIds;
+        }
+
+        @Override
+        UserInfo getUserInfo(int userId) {
+            switch (userId) {
+                case TEST_USER_0_ID:
+                case TEST_USER_1_ID:
+                    return DEFAULT_USER_INFO;
+                case TEST_QUIET_USER_ID:
+                    return QUIET_USER_INFO;
+            }
+            return null;
+        }
+
+        @Override
+        int[] getCurrentProfileIds() {
+            return new int[] { TEST_USER_0_ID, TEST_QUIET_USER_ID };
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java b/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
index b642d26..f15b5f7 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
@@ -19,9 +19,10 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
+
 import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
@@ -33,11 +34,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.IRecentsAnimationRunner;
-import com.android.server.AttributeCache;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
index 944f20f..283c027 100644
--- a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
@@ -30,11 +30,12 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -42,7 +43,7 @@
 import java.util.ArrayList;
 
 /**
- * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+ * atest FrameworksServicesTests:RunningTasksTest
  */
 @MediumTest
 @Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java b/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java
index 168bc17..8e4e7e6 100644
--- a/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java
@@ -20,9 +20,10 @@
 
 import android.app.ActivityOptions;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
index f71a6e7..f5b8f78 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
@@ -16,31 +16,25 @@
 
 package com.android.server.am;
 
-import android.content.pm.ActivityInfo.WindowLayout;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import android.view.Gravity;
-
-import org.junit.runner.RunWith;
-import org.junit.Before;
-import org.junit.Test;
-
-import org.mockito.invocation.InvocationOnMock;
-
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 
 import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
 
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.doAnswer;
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
 
+import android.content.pm.ActivityInfo.WindowLayout;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.Gravity;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for exercising resizing task bounds.
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
index 9e6055d..8d54bc2 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
@@ -44,7 +44,11 @@
         super.setUp();
         mUserManager = UserManager.get(getContext());
         mTaskPersister = new TaskPersister(getContext().getFilesDir());
-        testUserId = createUser(TEST_USER_NAME, 0);
+        // In ARC, the maximum number of supported users is one, which is different from the ones of
+        // most phones (more than 4). This prevents TaskPersisterTest from creating another user for
+        // test. However, since guest users can be added as much as possible, we create guest user
+        // in the test.
+        testUserId = createUser(TEST_USER_NAME, UserInfo.FLAG_GUEST);
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
index 72851d01..fa8a09c 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
@@ -29,20 +29,17 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.content.res.XmlResourceParser;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.service.voice.IVoiceInteractionSession;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Xml;
 
-import com.android.frameworks.servicestests.R;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.app.IVoiceInteractor;
 import com.android.server.am.TaskRecord.TaskRecordFactory;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -57,9 +54,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Reader;
-import java.nio.file.Files;
 import java.util.ArrayList;
-import java.util.Comparator;
 
 /**
  * Tests for exercising {@link TaskRecord}.
@@ -156,9 +151,9 @@
 
     private TaskRecord createTaskRecord(int taskId) {
         return new TaskRecord(mService.mActivityTaskManager, taskId, new Intent(), null, null, null,
-                null, null, false,
-                false, false, 0, 10050, null, new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0,
-                null, 0, false, false, false, 0, 0);
+                ActivityBuilder.getDefaultComponent(), null, false, false, false, 0, 10050, null,
+                new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0, 0
+        );
     }
 
     private static class TestTaskRecordFactory extends TaskRecordFactory {
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java b/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
index 8e87a5f..3f7c714 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
@@ -16,7 +16,8 @@
 
 package com.android.server.am;
 
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -33,23 +34,25 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.content.res.Resources.Theme;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.text.TextUtils;
-import android.util.Pair;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.annotations.GuardedBy;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class TaskStackChangedListenerTest {
@@ -140,10 +143,10 @@
         assertEquals(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, params[1]);
     }
 
-    @Test
     /**
      * Tests for onTaskCreated, onTaskMovedToFront, onTaskRemoved and onTaskRemovalStarted.
      */
+    @Test
     public void testTaskChangeCallBacks() throws Exception {
         final Object[] params = new Object[2];
         final CountDownLatch taskCreatedLaunchLatch = new CountDownLatch(1);
@@ -181,6 +184,7 @@
 
         final ActivityTaskChangeCallbacks activity =
                 (ActivityTaskChangeCallbacks) startTestActivity(ActivityTaskChangeCallbacks.class);
+        activity.setDetachedFromWindowLatch(onDetachedFromWindowLatch);
         final int id = activity.getTaskId();
 
         // Test for onTaskCreated.
@@ -207,22 +211,24 @@
         assertEquals(1, taskRemovedLatch.getCount());
         waitForCallback(taskRemovedLatch);
         assertEquals(id, params[0]);
+        waitForCallback(onDetachedFromWindowLatch);
         assertTrue(activity.onDetachedFromWindowCalled);
     }
 
     /**
      * Starts the provided activity and returns the started instance.
      */
-    private Activity startTestActivity(Class<?> activityClass) {
+    private TestActivity startTestActivity(Class<?> activityClass) throws InterruptedException {
         final Context context = InstrumentationRegistry.getContext();
         final ActivityMonitor monitor =
                 new ActivityMonitor(activityClass.getName(), null, false);
         InstrumentationRegistry.getInstrumentation().addMonitor(monitor);
         context.startActivity(new Intent(context, activityClass));
-        final Activity activity = monitor.waitForActivityWithTimeout(1000);
+        final TestActivity activity = (TestActivity)monitor.waitForActivityWithTimeout(1000);
         if (activity == null) {
             throw new RuntimeException("Timed out waiting for Activity");
         }
+        activity.waitForResumeStateChange(true);
         return activity;
     }
 
@@ -240,7 +246,43 @@
         }catch (InterruptedException e) {}
     }
 
-    public static class ActivityA extends Activity {
+    public static class TestActivity extends Activity {
+        boolean mIsResumed = false;
+
+        @Override
+        protected void onPostResume() {
+            super.onPostResume();
+            synchronized (this) {
+                mIsResumed = true;
+                notifyAll();
+            }
+        }
+
+        @Override
+        protected void onPause() {
+            super.onPause();
+            synchronized (this) {
+                mIsResumed = false;
+                notifyAll();
+            }
+        }
+
+        /**
+         * If isResumed is {@code true}, sleep the thread until the activity is resumed.
+         * if {@code false}, sleep the thread until the activity is paused.
+         */
+        public void waitForResumeStateChange(boolean isResumed) throws InterruptedException {
+            synchronized (this) {
+                if (mIsResumed == isResumed) {
+                    return;
+                }
+                wait(5000);
+            }
+            assertTrue("The activity resume state change timed out", mIsResumed == isResumed);
+        }
+    }
+
+    public static class ActivityA extends TestActivity {
 
         private boolean mActivityBLaunched = false;
 
@@ -256,7 +298,7 @@
         }
     }
 
-    public static class ActivityB extends Activity {
+    public static class ActivityB extends TestActivity {
 
         @Override
         protected void onPostResume() {
@@ -269,7 +311,7 @@
         }
     }
 
-    public static class ActivityRequestedOrientationChange extends Activity {
+    public static class ActivityRequestedOrientationChange extends TestActivity {
         @Override
         protected void onPostResume() {
             super.onPostResume();
@@ -278,7 +320,7 @@
         }
     }
 
-    public static class ActivityTaskDescriptionChange extends Activity {
+    public static class ActivityTaskDescriptionChange extends TestActivity {
         @Override
         protected void onPostResume() {
             super.onPostResume();
@@ -287,12 +329,18 @@
         }
     }
 
-    public static class ActivityTaskChangeCallbacks extends Activity {
-        public boolean onDetachedFromWindowCalled = false;;
+    public static class ActivityTaskChangeCallbacks extends TestActivity {
+        boolean onDetachedFromWindowCalled = false;
+        CountDownLatch onDetachedFromWindowCountDownLatch;
 
         @Override
         public void onDetachedFromWindow() {
             onDetachedFromWindowCalled = true;
+            onDetachedFromWindowCountDownLatch.countDown();
+        }
+
+        void setDetachedFromWindowLatch(CountDownLatch countDownLatch) {
+            onDetachedFromWindowCountDownLatch = countDownLatch;
         }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java b/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java
index 7f397d6..7e0dfcf 100644
--- a/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java
@@ -31,9 +31,10 @@
 import android.app.AppOpsManager.OnOpActiveChangedListener;
 import android.content.Context;
 import android.os.Process;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/appops/AppOpsServiceTest.java b/services/tests/servicestests/src/com/android/server/appops/AppOpsServiceTest.java
index 45e2865..4ae9bea 100644
--- a/services/tests/servicestests/src/com/android/server/appops/AppOpsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/appops/AppOpsServiceTest.java
@@ -31,9 +31,10 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index 1bb93cc..f3c76b6 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -53,7 +53,6 @@
 import java.util.Random;
 import java.util.concurrent.CountDownLatch;
 
-
 /**
  * Tests for {@link AppWidgetManager} and {@link AppWidgetServiceImpl}.
  *
@@ -61,7 +60,7 @@
  adb install \
  -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  adb shell am instrument -e class com.android.server.appwidget.AppWidgetServiceImplTest \
- -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 public class AppWidgetServiceImplTest extends InstrumentationTestCase {
diff --git a/services/tests/servicestests/src/com/android/server/backup/BackupPasswordManagerTest.java b/services/tests/servicestests/src/com/android/server/backup/BackupPasswordManagerTest.java
index bc16297..2dc0ee1 100644
--- a/services/tests/servicestests/src/com/android/server/backup/BackupPasswordManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/BackupPasswordManagerTest.java
@@ -17,7 +17,6 @@
 package com.android.server.backup;
 
 import static com.android.server.testutils.TestUtils.assertExpectException;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyString;
@@ -25,8 +24,9 @@
 
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.backup.utils.PasswordUtils;
 
diff --git a/services/tests/servicestests/src/com/android/server/backup/DataChangedJournalTest.java b/services/tests/servicestests/src/com/android/server/backup/DataChangedJournalTest.java
index c27fd07..f588c4f 100644
--- a/services/tests/servicestests/src/com/android/server/backup/DataChangedJournalTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/DataChangedJournalTest.java
@@ -19,8 +19,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -36,6 +37,7 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.util.ArrayList;
+import java.util.function.Consumer;
 
 @SmallTest
 @Presubmit
@@ -47,7 +49,7 @@
 
     @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
 
-    @Mock private DataChangedJournal.Consumer mConsumer;
+    @Mock private Consumer<String> mConsumer;
 
     private File mFile;
     private DataChangedJournal mJournal;
diff --git a/services/tests/servicestests/src/com/android/server/backup/ProcessedPackagesJournalTest.java b/services/tests/servicestests/src/com/android/server/backup/ProcessedPackagesJournalTest.java
index b4a1f18..cf4f975 100644
--- a/services/tests/servicestests/src/com/android/server/backup/ProcessedPackagesJournalTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/ProcessedPackagesJournalTest.java
@@ -19,8 +19,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.google.android.collect.Sets;
 
diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
index bbd999b..79eba68 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -43,8 +43,9 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/backup/restore/PerformAdbRestoreTaskTest.java b/services/tests/servicestests/src/com/android/server/backup/restore/PerformAdbRestoreTaskTest.java
index 05f4c13..00c6391 100644
--- a/services/tests/servicestests/src/com/android/server/backup/restore/PerformAdbRestoreTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/restore/PerformAdbRestoreTaskTest.java
@@ -20,9 +20,10 @@
 
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.servicestests.R;
 
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
index 2d5afad..525135c 100644
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
+++ b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
@@ -134,7 +134,12 @@
     }
 
     @Override
-    public boolean isPermissionReviewModeEnabled() {
+    public boolean arePermissionsIndividuallyControlled() {
+        return false;
+    }
+
+    @Override
+    public boolean isWirelessConsentModeEnabled() {
         return false;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
index 6801bd2..9fcdf2d 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
@@ -20,7 +20,6 @@
 
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
@@ -31,8 +30,9 @@
 import android.content.pm.SigningInfo;
 import android.os.Process;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.testutils.PackageManagerStub;
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
index c40b411..d3fd89c 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
@@ -18,9 +18,9 @@
 
 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY;
 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_ID;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION;
 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION;
-import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -33,8 +33,9 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java
index ebe6133..cdffd35 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java
@@ -23,8 +23,9 @@
 import android.app.backup.IBackupObserver;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/DataStreamFileCodecTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/DataStreamFileCodecTest.java
index bfb95c1..efd4603 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/DataStreamFileCodecTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/DataStreamFileCodecTest.java
@@ -19,8 +19,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java
index 2f56598..9b861a4 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java
@@ -24,8 +24,9 @@
 import android.app.backup.IFullBackupRestoreObserver;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupUtilsTest.java
index 4e3de64..ae0452a 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupUtilsTest.java
@@ -25,8 +25,9 @@
 
 import android.os.ParcelFileDescriptor;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
@@ -40,7 +41,6 @@
 import java.io.EOFException;
 import java.io.File;
 import java.io.FileOutputStream;
-import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Random;
 
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/SparseArrayUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/SparseArrayUtilsTest.java
index db55120..679e098 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/SparseArrayUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/SparseArrayUtilsTest.java
@@ -19,10 +19,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.google.android.collect.Sets;
 
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
index 2830a74..12f2991 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
@@ -29,8 +29,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
@@ -47,13 +45,14 @@
 import android.os.Bundle;
 import android.os.Process;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.servicestests.R;
-import com.android.server.backup.FileMetadata;
 import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.FileMetadata;
 import com.android.server.backup.restore.PerformAdbRestoreTask;
 import com.android.server.backup.restore.RestorePolicy;
 import com.android.server.backup.testutils.PackageManagerStub;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java
index 175fdd8..be05245 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java
@@ -28,7 +28,7 @@
  -w com.android.frameworks.servicestests
 
 
- -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 public class DevicePolicyConstantsTest extends AndroidTestCase {
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 a23636c..e37a6c1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -117,7 +117,7 @@
  adb install \
    -r ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest \
-   -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+   -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
 
  (mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
  *
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
index 939a272..34edd9f 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
@@ -33,11 +33,12 @@
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
 import android.test.AndroidTestCase;
 import android.test.mock.MockPackageManager;
 import android.view.inputmethod.InputMethodInfo;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.internal.R;
 import com.android.internal.view.IInputMethodManager;
 
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 cb6a747..5899bb0 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -16,12 +16,12 @@
 
 package com.android.server.devicepolicy;
 
-import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
-
 import android.content.ComponentName;
 import android.os.UserHandle;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
+
 /**
  * Tests for the DeviceOwner object that saves & loads device and policy owner information.
  * run this test with:
@@ -29,7 +29,7 @@
  adb install \
    -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  adb shell am instrument -e class com.android.server.devicepolicy.OwnersTest \
-   -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+   -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
 
  (mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
  */
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
index e4e9701..e51859b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
@@ -20,6 +20,7 @@
 import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_DUPLICATE_OR_OVERLAP;
 import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE;
 import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_LONG;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -27,10 +28,10 @@
 import android.app.admin.FreezePeriod;
 import android.app.admin.SystemUpdatePolicy;
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.Pair;
 import android.util.Xml;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.FastXmlSerializer;
 
 import org.junit.Test;
@@ -50,7 +51,6 @@
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-
 /**
  * Unit tests for {@link android.app.admin.SystemUpdatePolicy}.
  * Throughout this test, we use "MM-DD" format to denote dates without year.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
index e3e61ac..2005dd9 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
@@ -30,7 +30,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.Environment;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.runner.AndroidJUnit4;
 import android.util.Log;
 
 import com.android.server.devicepolicy.TransferOwnershipMetadataManager.Injector;
diff --git a/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java
index 8502e69..e8e6ded 100644
--- a/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java
@@ -25,9 +25,10 @@
 import android.hardware.display.AmbientBrightnessDayStats;
 import android.os.SystemClock;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
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 284d443..e6ca03b 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -30,11 +30,11 @@
 import android.content.res.TypedArray;
 import android.hardware.display.BrightnessConfiguration;
 import android.os.PowerManager;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.MathUtils;
 import android.util.Spline;
-import android.util.Slog;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -531,8 +531,8 @@
     @Test
     public void testGammaCorrectionChangeAtEdges() {
         // The algorithm behaves differently at the edges, because gamma correction there tends to
-        // be extreme. If we add a user data point at (x0, y0+0.3), the adjustment should be
-        // 0.3*2 = 0.6, resulting in a gamma of 3**-0.6 = ~0.52.
+        // be extreme. If we add a user data point at (x0, y0+0.3), the adjustment should be 0.3,
+        // resulting in a gamma of 3**-0.6 = ~0.52.
         final int x0 = 100;
         final int x2 = 2500;
         final int x4 = 4900;
@@ -547,17 +547,15 @@
         assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */);
         assertEquals(y4, strategy.getBrightness(x4), 0.01f /* tolerance */);
         // Rollin':
-        float increase = 0.3f;
-        float adjustment = increase * 2;
+        float adjustment = 0.3f;
         float gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment);
-        strategy.addUserDataPoint(x0, y0 + increase);
-        assertEquals(y0 + increase, strategy.getBrightness(x0), 0.01f /* tolerance */);
+        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 */);
-        // Similarly, if we set a user data point at (x4, 1.0), the adjustment should be (1-y4)*2.
-        increase = 1.0f - y4;
-        adjustment = increase * 2;
+        // 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 */);
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 75dc96f..ece9f42 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -46,11 +46,12 @@
 import android.os.SystemClock;
 import android.os.UserManager;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.AtomicFile;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
index 6bd8011..53711a6 100644
--- a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
@@ -16,6 +16,10 @@
 
 package com.android.server.display;
 
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.Mockito.doReturn;
+
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.AlarmManager;
@@ -26,10 +30,11 @@
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.provider.Settings.System;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.app.ColorDisplayController;
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.LocalServices;
@@ -37,24 +42,22 @@
 import com.android.server.twilight.TwilightListener;
 import com.android.server.twilight.TwilightManager;
 import com.android.server.twilight.TwilightState;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
 import java.util.Calendar;
 import java.util.HashMap;
-import java.time.LocalTime;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-import static com.google.common.truth.Truth.assertWithMessage;
-import static org.mockito.Mockito.doReturn;
-
 @RunWith(AndroidJUnit4.class)
 public class ColorDisplayServiceTest {
 
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 675000e..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,23 +22,21 @@
 import static org.junit.Assert.assertTrue;
 
 import android.hardware.display.BrightnessConfiguration;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.AtomicFile;
 import android.util.Pair;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.io.FileInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.FileNotFoundException;
-import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 
 @SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
new file mode 100644
index 0000000..48c8902
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.annotation.Nullable;
+import android.app.Instrumentation;
+import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.os.Looper;
+import android.os.test.TestLooper;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link ArcTerminationActionFromAvr} */
+@SmallTest
+@RunWith(JUnit4.class)
+public class ArcTerminationActionFromAvrTest {
+
+    private HdmiDeviceInfo mDeviceInfoForTests;
+    private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem;
+    private ArcTerminationActionFromAvr mAction;
+
+    private TestLooper mTestLooper = new TestLooper();
+    private boolean mSendCecCommandSuccess;
+    private boolean mShouldDispatchReportArcTerminated;
+    private boolean mArcEnabled;
+    private boolean mSetArcStatusCalled;
+    private Instrumentation mInstrumentation;
+
+    @Before
+    public void setUp() {
+        mDeviceInfoForTests = new HdmiDeviceInfo(1000, 1);
+
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+
+        HdmiControlService hdmiControlService =
+                new HdmiControlService(mInstrumentation.getTargetContext()) {
+                    @Override
+                    void sendCecCommand(
+                            HdmiCecMessage command, @Nullable SendMessageCallback callback) {
+                        switch (command.getOpcode()) {
+                            case Constants.MESSAGE_TERMINATE_ARC:
+                                if (callback != null) {
+                                    callback.onSendCompleted(
+                                            mSendCecCommandSuccess
+                                                    ? SendMessageResult.SUCCESS
+                                                    : SendMessageResult.NACK);
+                                }
+                                if (mShouldDispatchReportArcTerminated) {
+                                    mHdmiCecLocalDeviceAudioSystem.dispatchMessage(
+                                            HdmiCecMessageBuilder.buildReportArcTerminated(
+                                                    Constants.ADDR_TV,
+                                                    mHdmiCecLocalDeviceAudioSystem.mAddress));
+                                }
+                                break;
+                            default:
+                                throw new IllegalArgumentException("Unexpected message");
+                        }
+                    }
+
+                    @Override
+                    boolean isPowerStandby() {
+                        return false;
+                    }
+
+                    @Override
+                    boolean isAddressAllocated() {
+                        return true;
+                    }
+
+                    @Override
+                    Looper getServiceLooper() {
+                        return mTestLooper.getLooper();
+                    }
+                };
+
+        mHdmiCecLocalDeviceAudioSystem =
+                new HdmiCecLocalDeviceAudioSystem(hdmiControlService) {
+                    @Override
+                    HdmiDeviceInfo getDeviceInfo() {
+                        return mDeviceInfoForTests;
+                    }
+
+                    @Override
+                    void setArcStatus(boolean enabled) {
+                        mSetArcStatusCalled = true;
+                        mArcEnabled = enabled;
+                    }
+                };
+        mHdmiCecLocalDeviceAudioSystem.init();
+        Looper looper = mTestLooper.getLooper();
+        hdmiControlService.setIoLooper(looper);
+
+        mArcEnabled = true;
+        mAction = new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem);
+    }
+
+    @Test
+    public void testSendMessage_NotSuccess() {
+        mSendCecCommandSuccess = false;
+        mShouldDispatchReportArcTerminated = false;
+        mSetArcStatusCalled = false;
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
+
+        mTestLooper.dispatchAll();
+        assertThat(mSetArcStatusCalled).isFalse();
+        assertThat(mArcEnabled).isTrue();
+    }
+
+    @Test
+    public void testReportArcTerminated_NotReceived() {
+        mSendCecCommandSuccess = true;
+        mShouldDispatchReportArcTerminated = false;
+        mSetArcStatusCalled = false;
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
+
+        mTestLooper.moveTimeForward(1000);
+        mTestLooper.dispatchAll();
+        assertThat(mSetArcStatusCalled).isFalse();
+        assertThat(mArcEnabled).isTrue();
+    }
+
+    @Test
+    public void testReportArcTerminated_Received() {
+        mSendCecCommandSuccess = true;
+        mShouldDispatchReportArcTerminated = true;
+        mSetArcStatusCalled = false;
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
+
+        mTestLooper.moveTimeForward(1000);
+        mTestLooper.dispatchAll();
+        assertThat(mSetArcStatusCalled).isTrue();
+        assertThat(mArcEnabled).isFalse();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DetectTvSystemAudioModeSupportActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DetectTvSystemAudioModeSupportActionTest.java
new file mode 100644
index 0000000..3736df5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/DetectTvSystemAudioModeSupportActionTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import static org.junit.Assert.assertEquals;
+
+import android.annotation.Nullable;
+import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.os.Looper;
+import android.os.test.TestLooper;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import com.android.server.hdmi.HdmiCecLocalDeviceAudioSystem.TvSystemAudioModeSupportedCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link DetectTvSystemAudioModeSupportAction} class. */
+@SmallTest
+@RunWith(JUnit4.class)
+public class DetectTvSystemAudioModeSupportActionTest {
+
+    private HdmiDeviceInfo mDeviceInfoForTests;
+    private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem;
+    private DetectTvSystemAudioModeSupportAction mAction;
+
+    private TestLooper mTestLooper = new TestLooper();
+    private boolean mSendCecCommandSuccess;
+    private boolean mShouldDispatchFeatureAbort;
+    private Boolean mSupported;
+
+    @Before
+    public void SetUp() {
+        mDeviceInfoForTests = new HdmiDeviceInfo(1001, 1234);
+        HdmiControlService hdmiControlService =
+                new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
+
+                    @Override
+                    void sendCecCommand(
+                            HdmiCecMessage command, @Nullable SendMessageCallback callback) {
+                        switch (command.getOpcode()) {
+                            case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE:
+                                if (callback != null) {
+                                    callback.onSendCompleted(
+                                            mSendCecCommandSuccess
+                                                    ? SendMessageResult.SUCCESS
+                                                    : SendMessageResult.NACK);
+                                }
+                                if (mShouldDispatchFeatureAbort) {
+                                    mHdmiCecLocalDeviceAudioSystem.dispatchMessage(
+                                            HdmiCecMessageBuilder.buildFeatureAbortCommand(
+                                                    Constants.ADDR_TV,
+                                                    mHdmiCecLocalDeviceAudioSystem.mAddress,
+                                                    Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE,
+                                                    Constants.ABORT_UNRECOGNIZED_OPCODE));
+                                }
+                                break;
+                            default:
+                                throw new IllegalArgumentException("Unexpected message");
+                        }
+                    }
+
+                    @Override
+                    boolean isPowerStandby() {
+                        return false;
+                    }
+
+                    @Override
+                    boolean isAddressAllocated() {
+                        return true;
+                    }
+
+                    @Override
+                    Looper getServiceLooper() {
+                        return mTestLooper.getLooper();
+                    }
+                };
+        mHdmiCecLocalDeviceAudioSystem =
+                new HdmiCecLocalDeviceAudioSystem(hdmiControlService) {
+                    @Override
+                    HdmiDeviceInfo getDeviceInfo() {
+                        return mDeviceInfoForTests;
+                    }
+                };
+        mHdmiCecLocalDeviceAudioSystem.init();
+        Looper looper = mTestLooper.getLooper();
+        hdmiControlService.setIoLooper(looper);
+
+        mAction =
+                new DetectTvSystemAudioModeSupportAction(
+                        mHdmiCecLocalDeviceAudioSystem,
+                        new TvSystemAudioModeSupportedCallback() {
+                            public void onResult(boolean supported) {
+                                mSupported = Boolean.valueOf(supported);
+                            }
+                        });
+        mSupported = null;
+    }
+
+    @Test
+    public void testSendCecCommandNotSucceed() {
+        mSendCecCommandSuccess = false;
+        mShouldDispatchFeatureAbort = false;
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
+        mTestLooper.dispatchAll();
+        assertEquals(Boolean.FALSE, mSupported);
+    }
+
+    @Test
+    public void testFeatureAbort() {
+        mSendCecCommandSuccess = true;
+        mShouldDispatchFeatureAbort = true;
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
+        mTestLooper.dispatchAll();
+        assertEquals(Boolean.FALSE, mSupported);
+    }
+
+    @Test
+    public void testSupported() {
+        mSendCecCommandSuccess = true;
+        mShouldDispatchFeatureAbort = false;
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction);
+        mTestLooper.moveTimeForward(2000);
+        mTestLooper.dispatchAll();
+        assertEquals(Boolean.TRUE, mSupported);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
new file mode 100644
index 0000000..7484edd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiPortInfo;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.os.MessageQueue;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.hdmi.HdmiCecController.NativeWrapper;
+import java.util.ArrayList;
+import java.util.List;
+
+/** Fake {@link NativeWrapper} useful for testing. */
+final class FakeNativeWrapper implements NativeWrapper {
+    private final int[] mPollAddressResponse =
+            new int[] {
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+                SendMessageResult.NACK,
+            };
+
+    private final List<HdmiCecMessage> mResultMessages = new ArrayList<>();
+    private HdmiCecMessage mResultMessage;
+    private int mMyPhysicalAddress = 0;
+
+    @Override
+    public long nativeInit(HdmiCecController handler, MessageQueue messageQueue) {
+        return 1L;
+    }
+
+    @Override
+    public int nativeSendCecCommand(
+            long controllerPtr, int srcAddress, int dstAddress, byte[] body) {
+        if (body.length == 0) {
+            return mPollAddressResponse[dstAddress];
+        } else {
+            mResultMessages.add(HdmiCecMessageBuilder.of(srcAddress, dstAddress, body));
+        }
+        return SendMessageResult.SUCCESS;
+    }
+
+    @Override
+    public int nativeAddLogicalAddress(long controllerPtr, int logicalAddress) {
+        return 0;
+    }
+
+    @Override
+    public void nativeClearLogicalAddress(long controllerPtr) {}
+
+    @Override
+    public int nativeGetPhysicalAddress(long controllerPtr) {
+        return mMyPhysicalAddress;
+    }
+
+    @Override
+    public int nativeGetVersion(long controllerPtr) {
+        return 0;
+    }
+
+    @Override
+    public int nativeGetVendorId(long controllerPtr) {
+        return 0;
+    }
+
+    @Override
+    public HdmiPortInfo[] nativeGetPortInfos(long controllerPtr) {
+        HdmiPortInfo[] hdmiPortInfo = new HdmiPortInfo[1];
+        hdmiPortInfo[0] = new HdmiPortInfo(1, 1, 0x1000, true, true, true);
+        return hdmiPortInfo;
+    }
+
+    @Override
+    public void nativeSetOption(long controllerPtr, int flag, boolean enabled) {}
+
+    @Override
+    public void nativeSetLanguage(long controllerPtr, String language) {}
+
+    @Override
+    public void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag) {}
+
+    @Override
+    public boolean nativeIsConnected(long controllerPtr, int port) {
+        return false;
+    }
+
+    public List<HdmiCecMessage> getResultMessages() {
+        return new ArrayList<>(mResultMessages);
+    }
+
+    public HdmiCecMessage getOnlyResultMessage() throws Exception {
+        if (mResultMessages.size() != 1) {
+            throw new Exception("There is not exactly one message");
+        }
+        return mResultMessages.get(0);
+    }
+
+    public void setPollAddressResponse(int logicalAddress, int response) {
+        mPollAddressResponse[logicalAddress] = response;
+    }
+
+    @VisibleForTesting
+    protected void setPhysicalAddress(int physicalAddress) {
+        mMyPhysicalAddress = physicalAddress;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
index 1089f69..da840be 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
@@ -15,16 +15,6 @@
  */
 package com.android.server.hdmi;
 
-import android.content.Context;
-import android.hardware.hdmi.HdmiPortInfo;
-import android.os.Looper;
-import android.os.MessageQueue;
-import android.os.test.TestLooper;
-import android.support.test.filters.SmallTest;
-import android.util.Log;
-import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
-import com.android.server.hdmi.HdmiCecController.NativeWrapper;
-
 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM;
 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_PLAYBACK;
 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;
@@ -36,81 +26,25 @@
 import static com.android.server.hdmi.Constants.ADDR_TV;
 import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
 import static junit.framework.Assert.assertEquals;
+
+import android.content.Context;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.os.Looper;
+import android.os.test.TestLooper;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
-/**
- * Tests for {@link com.android.server.hdmi.HdmiCecController} class.
- */
+/** Tests for {@link com.android.server.hdmi.HdmiCecController} class. */
 @SmallTest
 @RunWith(JUnit4.class)
 public class HdmiCecControllerTest {
 
-    private static final class NativeWrapperImpl implements NativeWrapper {
-
-        @Override
-        public long nativeInit(HdmiCecController handler, MessageQueue messageQueue) {
-            return 1L;
-        }
-
-        @Override
-        public int nativeSendCecCommand(long controllerPtr, int srcAddress, int dstAddress,
-            byte[] body) {
-            return mOccupied[srcAddress] ? 0 : 1;
-        }
-
-        @Override
-        public int nativeAddLogicalAddress(long controllerPtr, int logicalAddress) {
-            return 0;
-        }
-
-        @Override
-        public void nativeClearLogicalAddress(long controllerPtr) {
-
-        }
-
-        @Override
-        public int nativeGetPhysicalAddress(long controllerPtr) {
-            return 0;
-        }
-
-        @Override
-        public int nativeGetVersion(long controllerPtr) {
-            return 0;
-        }
-
-        @Override
-        public int nativeGetVendorId(long controllerPtr) {
-            return 0;
-        }
-
-        @Override
-        public HdmiPortInfo[] nativeGetPortInfos(long controllerPtr) {
-            return new HdmiPortInfo[0];
-        }
-
-        @Override
-        public void nativeSetOption(long controllerPtr, int flag, boolean enabled) {
-
-        }
-
-        @Override
-        public void nativeSetLanguage(long controllerPtr, String language) {
-
-        }
-
-        @Override
-        public void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag) {
-
-        }
-
-        @Override
-        public boolean nativeIsConnected(long controllerPtr, int port) {
-            return false;
-        }
-    }
+    private FakeNativeWrapper mNativeWrapper;
 
     private class MyHdmiControlService extends HdmiControlService {
 
@@ -129,17 +63,16 @@
         }
     }
 
-    private static final String TAG = HdmiCecControllerTest.class.getSimpleName();
     private HdmiControlService mHdmiControlService;
     private HdmiCecController mHdmiCecController;
-    private static boolean[] mOccupied = new boolean[15];
     private int mLogicalAddress = 16;
-    private AllocateAddressCallback mCallback = new AllocateAddressCallback() {
-        @Override
-        public void onAllocated(int deviceType, int logicalAddress) {
-            mLogicalAddress = logicalAddress;
-        }
-    };
+    private AllocateAddressCallback mCallback =
+            new AllocateAddressCallback() {
+                @Override
+                public void onAllocated(int deviceType, int logicalAddress) {
+                    mLogicalAddress = logicalAddress;
+                }
+            };
     private Looper mMyLooper;
     private TestLooper mTestLooper = new TestLooper();
 
@@ -147,18 +80,15 @@
     public void SetUp() {
         mMyLooper = mTestLooper.getLooper();
         mMyLooper = mTestLooper.getLooper();
-        mHdmiControlService = new MyHdmiControlService(null);
-        mHdmiCecController = HdmiCecController.createWithNativeWrapper(
-            mHdmiControlService, new NativeWrapperImpl());
+        mHdmiControlService = new MyHdmiControlService(InstrumentationRegistry.getTargetContext());
+        mNativeWrapper = new FakeNativeWrapper();
+        mHdmiCecController =
+                HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
     }
 
-    /**
-     * Tests for {@link HdmiCecController#allocateLogicalAddress}
-     */
+    /** Tests for {@link HdmiCecController#allocateLogicalAddress} */
     @Test
     public void testAllocatLogicalAddress_TvDevicePreferredNotOcupied() {
-        mOccupied[ADDR_TV] = false;
-        mOccupied[ADDR_SPECIFIC_USE] = false;
         mHdmiCecController.allocateLogicalAddress(DEVICE_TV, ADDR_TV, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_TV, mLogicalAddress);
@@ -166,8 +96,7 @@
 
     @Test
     public void testAllocatLogicalAddress_TvDeviceNonPreferredNotOcupied() {
-        mOccupied[ADDR_TV] = false;
-        mOccupied[ADDR_SPECIFIC_USE] = false;
+
         mHdmiCecController.allocateLogicalAddress(DEVICE_TV, ADDR_UNREGISTERED, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_TV, mLogicalAddress);
@@ -175,8 +104,7 @@
 
     @Test
     public void testAllocatLogicalAddress_TvDeviceNonPreferredFirstOcupied() {
-        mOccupied[ADDR_TV] = true;
-        mOccupied[ADDR_SPECIFIC_USE] = false;
+        mNativeWrapper.setPollAddressResponse(ADDR_TV, SendMessageResult.SUCCESS);
         mHdmiCecController.allocateLogicalAddress(DEVICE_TV, ADDR_UNREGISTERED, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_SPECIFIC_USE, mLogicalAddress);
@@ -184,8 +112,8 @@
 
     @Test
     public void testAllocatLogicalAddress_TvDeviceNonPreferredAllOcupied() {
-        mOccupied[ADDR_TV] = true;
-        mOccupied[ADDR_SPECIFIC_USE] = true;
+        mNativeWrapper.setPollAddressResponse(ADDR_TV, SendMessageResult.SUCCESS);
+        mNativeWrapper.setPollAddressResponse(ADDR_SPECIFIC_USE, SendMessageResult.SUCCESS);
         mHdmiCecController.allocateLogicalAddress(DEVICE_TV, ADDR_UNREGISTERED, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
@@ -193,27 +121,23 @@
 
     @Test
     public void testAllocatLogicalAddress_AudioSystemNonPreferredNotOcupied() {
-        mOccupied[ADDR_AUDIO_SYSTEM] = false;
         mHdmiCecController.allocateLogicalAddress(
-            DEVICE_AUDIO_SYSTEM, ADDR_UNREGISTERED, mCallback);
+                DEVICE_AUDIO_SYSTEM, ADDR_UNREGISTERED, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_AUDIO_SYSTEM, mLogicalAddress);
     }
 
     @Test
     public void testAllocatLogicalAddress_AudioSystemNonPreferredAllOcupied() {
-        mOccupied[ADDR_AUDIO_SYSTEM] = true;
+        mNativeWrapper.setPollAddressResponse(ADDR_AUDIO_SYSTEM, SendMessageResult.SUCCESS);
         mHdmiCecController.allocateLogicalAddress(
-            DEVICE_AUDIO_SYSTEM, ADDR_UNREGISTERED, mCallback);
+                DEVICE_AUDIO_SYSTEM, ADDR_UNREGISTERED, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
     }
 
     @Test
     public void testAllocatLogicalAddress_PlaybackPreferredNotOccupied() {
-        mOccupied[ADDR_PLAYBACK_1] = false;
-        mOccupied[ADDR_PLAYBACK_2] = false;
-        mOccupied[ADDR_PLAYBACK_3] = false;
         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_PLAYBACK_1, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_PLAYBACK_1, mLogicalAddress);
@@ -221,20 +145,14 @@
 
     @Test
     public void testAllocatLogicalAddress_PlaybackPreferredOcuppied() {
-        mOccupied[ADDR_PLAYBACK_1] = true;
-        mOccupied[ADDR_PLAYBACK_2] = false;
-        mOccupied[ADDR_PLAYBACK_3] = false;
-        mHdmiCecController.allocateLogicalAddress(
-            DEVICE_PLAYBACK, ADDR_PLAYBACK_1, mCallback);
+        mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
+        mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_PLAYBACK_1, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_PLAYBACK_2, mLogicalAddress);
     }
 
     @Test
     public void testAllocatLogicalAddress_PlaybackNoPreferredNotOcuppied() {
-        mOccupied[ADDR_PLAYBACK_1] = false;
-        mOccupied[ADDR_PLAYBACK_2] = false;
-        mOccupied[ADDR_PLAYBACK_3] = false;
         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_PLAYBACK_1, mLogicalAddress);
@@ -242,9 +160,7 @@
 
     @Test
     public void testAllocatLogicalAddress_PlaybackNoPreferredFirstOcuppied() {
-        mOccupied[ADDR_PLAYBACK_1] = true;
-        mOccupied[ADDR_PLAYBACK_2] = false;
-        mOccupied[ADDR_PLAYBACK_3] = false;
+        mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_PLAYBACK_2, mLogicalAddress);
@@ -252,9 +168,8 @@
 
     @Test
     public void testAllocatLogicalAddress_PlaybackNonPreferredFirstTwoOcuppied() {
-        mOccupied[ADDR_PLAYBACK_1] = true;
-        mOccupied[ADDR_PLAYBACK_2] = true;
-        mOccupied[ADDR_PLAYBACK_3] = false;
+        mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
+        mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_2, SendMessageResult.SUCCESS);
         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_PLAYBACK_3, mLogicalAddress);
@@ -262,9 +177,9 @@
 
     @Test
     public void testAllocatLogicalAddress_PlaybackNonPreferredAllOcupied() {
-        mOccupied[ADDR_PLAYBACK_1] = true;
-        mOccupied[ADDR_PLAYBACK_2] = true;
-        mOccupied[ADDR_PLAYBACK_3] = true;
+        mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
+        mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_2, SendMessageResult.SUCCESS);
+        mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_3, SendMessageResult.SUCCESS);
         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
         mTestLooper.dispatchAll();
         assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
new file mode 100644
index 0000000..9e3a0ea
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
+import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
+import static com.android.server.hdmi.Constants.ADDR_TV;
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+import static com.android.server.hdmi.HdmiControlService.STANDBY_SCREEN_OFF;
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.media.AudioManager;
+import android.os.Looper;
+import android.os.SystemProperties;
+import android.os.test.TestLooper;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+
+@SmallTest
+@RunWith(JUnit4.class)
+/** Tests for {@link HdmiCecLocalDeviceAudioSystem} class. */
+public class HdmiCecLocalDeviceAudioSystemTest {
+
+    private static final HdmiCecMessage MESSAGE_REQUEST_SAD_LCPM =
+            HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                    ADDR_TV, ADDR_AUDIO_SYSTEM, new int[] {Constants.AUDIO_CODEC_LPCM});
+
+    private HdmiControlService mHdmiControlService;
+    private HdmiCecController mHdmiCecController;
+    private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem;
+    private FakeNativeWrapper mNativeWrapper;
+    private Looper mMyLooper;
+    private TestLooper mTestLooper = new TestLooper();
+    private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+    private int mMusicVolume;
+    private int mMusicMaxVolume;
+    private boolean mMusicMute;
+
+    @Before
+    public void setUp() {
+        mHdmiControlService =
+                new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
+                    @Override
+                    AudioManager getAudioManager() {
+                        return new AudioManager() {
+                            @Override
+                            public int getStreamVolume(int streamType) {
+                                switch (streamType) {
+                                    case STREAM_MUSIC:
+                                        return mMusicVolume;
+                                    default:
+                                        return 0;
+                                }
+                            }
+
+                            @Override
+                            public boolean isStreamMute(int streamType) {
+                                switch (streamType) {
+                                    case STREAM_MUSIC:
+                                        return mMusicMute;
+                                    default:
+                                        return false;
+                                }
+                            }
+
+                            @Override
+                            public int getStreamMaxVolume(int streamType) {
+                                switch (streamType) {
+                                    case STREAM_MUSIC:
+                                        return mMusicMaxVolume;
+                                    default:
+                                        return 100;
+                                }
+                            }
+
+                            @Override
+                            public void adjustStreamVolume(
+                                    int streamType, int direction, int flags) {
+                                switch (streamType) {
+                                    case STREAM_MUSIC:
+                                        if (direction == AudioManager.ADJUST_UNMUTE) {
+                                            mMusicMute = false;
+                                        } else if (direction == AudioManager.ADJUST_MUTE) {
+                                            mMusicMute = true;
+                                        }
+                                    default:
+                                }
+                            }
+
+                            @Override
+                            public void setWiredDeviceConnectionState(
+                                int type, int state, String address, String name) {
+                                // Do nothing.
+                            }
+                        };
+                    }
+
+                    @Override
+                    void wakeUp() {}
+                };
+
+        mMyLooper = mTestLooper.getLooper();
+        mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(mHdmiControlService);
+        mHdmiCecLocalDeviceAudioSystem.init();
+        mHdmiControlService.setIoLooper(mMyLooper);
+        mNativeWrapper = new FakeNativeWrapper();
+        mHdmiCecController =
+                HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+        mHdmiControlService.setCecController(mHdmiCecController);
+        mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+        mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+        mLocalDevices.add(mHdmiCecLocalDeviceAudioSystem);
+        mHdmiControlService.initPortInfo();
+        // No TV device interacts with AVR so system audio control won't be turned on here
+        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+        mTestLooper.dispatchAll();
+        SystemProperties.set(Constants.PROPERTY_ARC_SUPPORT, "true");
+    }
+
+    @Test
+    public void handleGiveAudioStatus_volume_10_mute_true() {
+        mMusicVolume = 10;
+        mMusicMute = true;
+        mMusicMaxVolume = 20;
+        int scaledVolume = VolumeControlAction.scaleToCecVolume(10, mMusicMaxVolume);
+        HdmiCecMessage expectedMessage =
+                HdmiCecMessageBuilder.buildReportAudioStatus(
+                        ADDR_AUDIO_SYSTEM, ADDR_TV, scaledVolume, true);
+        HdmiCecMessage messageGive =
+                HdmiCecMessageBuilder.buildGiveAudioStatus(ADDR_TV, ADDR_AUDIO_SYSTEM);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveAudioStatus(messageGive))
+                .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+    }
+
+    @Test
+    public void handleGiveSystemAudioModeStatus_originalOff() {
+        HdmiCecMessage expectedMessage =
+                HdmiCecMessageBuilder.buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, false);
+        HdmiCecMessage messageGive =
+                HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(ADDR_TV, ADDR_AUDIO_SYSTEM);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive))
+                .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+    }
+
+    @Ignore("b/80297700")
+    @Test
+    public void handleRequestShortAudioDescriptor_featureDisabled() throws Exception {
+        HdmiCecMessage expectedMessage =
+                HdmiCecMessageBuilder.buildFeatureAbortCommand(
+                        ADDR_AUDIO_SYSTEM,
+                        ADDR_TV,
+                        Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR,
+                        Constants.ABORT_REFUSED);
+
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(false);
+        assertThat(
+                        mHdmiCecLocalDeviceAudioSystem.handleRequestShortAudioDescriptor(
+                                MESSAGE_REQUEST_SAD_LCPM))
+                .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
+    }
+
+    @Test
+    public void handleRequestShortAudioDescriptor_samOff() throws Exception {
+        HdmiCecMessage expectedMessage =
+                HdmiCecMessageBuilder.buildFeatureAbortCommand(
+                        ADDR_AUDIO_SYSTEM,
+                        ADDR_TV,
+                        Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR,
+                        Constants.ABORT_NOT_IN_CORRECT_MODE);
+
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(false);
+        assertThat(
+                        mHdmiCecLocalDeviceAudioSystem.handleRequestShortAudioDescriptor(
+                                MESSAGE_REQUEST_SAD_LCPM))
+                .isEqualTo(true);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
+    }
+
+    @Test
+    public void handleRequestShortAudioDescriptor_noAudioDeviceInfo() throws Exception {
+        HdmiCecMessage expectedMessage =
+                HdmiCecMessageBuilder.buildFeatureAbortCommand(
+                        ADDR_AUDIO_SYSTEM,
+                        ADDR_TV,
+                        Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR,
+                        Constants.ABORT_UNABLE_TO_DETERMINE);
+
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(true);
+        assertThat(
+                        mHdmiCecLocalDeviceAudioSystem.handleRequestShortAudioDescriptor(
+                                MESSAGE_REQUEST_SAD_LCPM))
+                .isEqualTo(true);
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
+    }
+
+    @Test
+    public void handleSetSystemAudioMode_setOn_orignalOff() {
+        mMusicMute = true;
+        HdmiCecMessage messageSet =
+                HdmiCecMessageBuilder.buildSetSystemAudioMode(ADDR_TV, ADDR_AUDIO_SYSTEM, true);
+        HdmiCecMessage messageGive =
+                HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(ADDR_TV, ADDR_AUDIO_SYSTEM);
+        // Check if originally off
+        HdmiCecMessage expectedMessage =
+                HdmiCecMessageBuilder.buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, false);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive))
+                .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+        // Check if correctly turned on
+        expectedMessage =
+                HdmiCecMessageBuilder.buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, true);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleSetSystemAudioMode(messageSet))
+                .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive))
+                .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+        assertThat(mMusicMute).isFalse();
+    }
+
+    @Ignore("b/80297700")
+    @Test
+    public void handleSystemAudioModeRequest_turnOffByTv() {
+        assertThat(mMusicMute).isFalse();
+        // Check if feature correctly turned off
+        HdmiCecMessage messageGive =
+                HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(ADDR_TV, ADDR_AUDIO_SYSTEM);
+        HdmiCecMessage messageRequestOff =
+                HdmiCecMessageBuilder.buildSystemAudioModeRequest(
+                        ADDR_TV, ADDR_AUDIO_SYSTEM, 2, false);
+        HdmiCecMessage expectedMessage =
+                HdmiCecMessageBuilder.buildSetSystemAudioMode(
+                        ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleSystemAudioModeRequest(messageRequestOff))
+                .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+        expectedMessage =
+                HdmiCecMessageBuilder.buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, false);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive))
+                .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+        assertThat(mMusicMute).isTrue();
+    }
+
+    @Ignore("b/80297700")
+    @Test
+    public void onStandbyAudioSystem_currentSystemAudioControlOn() {
+        // Set system audio control on first
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(true);
+        // Check if standby correctly turns off the feature
+        mHdmiCecLocalDeviceAudioSystem.onStandby(false, STANDBY_SCREEN_OFF);
+        mTestLooper.dispatchAll();
+        HdmiCecMessage expectedMessage =
+                HdmiCecMessageBuilder.buildSetSystemAudioMode(
+                        ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false);
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+        assertThat(mMusicMute).isTrue();
+    }
+
+    @Test
+    public void systemAudioControlOnPowerOn_alwaysOn() {
+        mHdmiCecLocalDeviceAudioSystem.removeAction(SystemAudioInitiationActionFromAvr.class);
+        mHdmiCecLocalDeviceAudioSystem.systemAudioControlOnPowerOn(
+                Constants.ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON, true);
+        assertThat(
+                        mHdmiCecLocalDeviceAudioSystem.getActions(
+                                SystemAudioInitiationActionFromAvr.class))
+                .isNotEmpty();
+    }
+
+    @Test
+    public void systemAudioControlOnPowerOn_neverOn() {
+        mHdmiCecLocalDeviceAudioSystem.removeAction(SystemAudioInitiationActionFromAvr.class);
+        mHdmiCecLocalDeviceAudioSystem.systemAudioControlOnPowerOn(
+                Constants.NEVER_SYSTEM_AUDIO_CONTROL_ON_POWER_ON, false);
+        assertThat(
+                        mHdmiCecLocalDeviceAudioSystem.getActions(
+                                SystemAudioInitiationActionFromAvr.class))
+                .isEmpty();
+    }
+
+    @Test
+    public void systemAudioControlOnPowerOn_useLastState_off() {
+        mHdmiCecLocalDeviceAudioSystem.removeAction(SystemAudioInitiationActionFromAvr.class);
+        mHdmiCecLocalDeviceAudioSystem.systemAudioControlOnPowerOn(
+                Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON, false);
+        assertThat(
+                        mHdmiCecLocalDeviceAudioSystem.getActions(
+                                SystemAudioInitiationActionFromAvr.class))
+                .isEmpty();
+    }
+
+    @Test
+    public void systemAudioControlOnPowerOn_useLastState_on() {
+        mHdmiCecLocalDeviceAudioSystem.removeAction(SystemAudioInitiationActionFromAvr.class);
+        mHdmiCecLocalDeviceAudioSystem.systemAudioControlOnPowerOn(
+                Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON, true);
+        assertThat(
+                        mHdmiCecLocalDeviceAudioSystem.getActions(
+                                SystemAudioInitiationActionFromAvr.class))
+                .isNotEmpty();
+    }
+
+    @Test
+    public void handleActiveSource_updateActiveSource() {
+        HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000);
+        ActiveSource expectedActiveSource = new ActiveSource(ADDR_TV, 0x0000);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleActiveSource(message))
+                .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource().equals(expectedActiveSource))
+                .isTrue();
+    }
+
+    @Test
+    public void terminateSystemAudioMode_systemAudioModeOff() {
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(false);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isFalse();
+        mMusicMute = false;
+        HdmiCecMessage message =
+                HdmiCecMessageBuilder.buildSetSystemAudioMode(
+                        ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false);
+        mHdmiCecLocalDeviceAudioSystem.terminateSystemAudioMode();
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isFalse();
+        assertThat(mMusicMute).isFalse();
+        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(message);
+    }
+
+    @Ignore("b/80297700")
+    @Test
+    public void terminateSystemAudioMode_systemAudioModeOn() {
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(true);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isTrue();
+        mMusicMute = false;
+        HdmiCecMessage expectedMessage =
+                HdmiCecMessageBuilder.buildSetSystemAudioMode(
+                        ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false);
+        mHdmiCecLocalDeviceAudioSystem.terminateSystemAudioMode();
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isFalse();
+        assertThat(mMusicMute).isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+    }
+
+    @Test
+    public void isPhysicalAddressMeOrBelow_isMe() {
+        int targetPhysicalAddress = 0x1000;
+        mNativeWrapper.setPhysicalAddress(0x1000);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress))
+            .isTrue();
+    }
+
+    @Test
+    public void isPhysicalAddressMeOrBelow_isBelow() {
+        int targetPhysicalAddress = 0x1100;
+        mNativeWrapper.setPhysicalAddress(0x1000);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress))
+            .isTrue();
+    }
+
+    @Test
+    public void isPhysicalAddressMeOrBelow_neitherMeNorBelow() {
+        int targetPhysicalAddress = 0x3000;
+        mNativeWrapper.setPhysicalAddress(0x2000);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress))
+            .isFalse();
+
+        targetPhysicalAddress = 0x2200;
+        mNativeWrapper.setPhysicalAddress(0x3300);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress))
+            .isFalse();
+
+        targetPhysicalAddress = 0x2213;
+        mNativeWrapper.setPhysicalAddress(0x2212);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress))
+            .isFalse();
+
+        targetPhysicalAddress = 0x2340;
+        mNativeWrapper.setPhysicalAddress(0x2310);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isPhysicalAddressMeOrBelow(targetPhysicalAddress))
+            .isFalse();
+    }
+
+    @Test
+    public void handleRequestArcInitiate_isNotDirectConnectedToTv() {
+        HdmiCecMessage message = HdmiCecMessageBuilder
+            .buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM);
+        HdmiCecMessage expectedMessage = HdmiCecMessageBuilder
+            .buildFeatureAbortCommand(
+                ADDR_AUDIO_SYSTEM, ADDR_TV,
+                Constants.MESSAGE_REQUEST_ARC_INITIATION,
+                Constants.ABORT_NOT_IN_CORRECT_MODE);
+        mNativeWrapper.setPhysicalAddress(0x1100);
+
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message))
+            .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+    }
+
+    @Test
+    public void handleRequestArcInitiate_startArcInitiationActionFromAvr() {
+        HdmiCecMessage message = HdmiCecMessageBuilder
+            .buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM);
+        mNativeWrapper.setPhysicalAddress(0x1000);
+        mHdmiCecLocalDeviceAudioSystem.removeAction(
+            ArcInitiationActionFromAvr.class);
+
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message))
+            .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiCecLocalDeviceAudioSystem
+            .getActions(ArcInitiationActionFromAvr.class)).isNotEmpty();
+    }
+
+    @Test
+    public void handleRequestArcTerminate_arcIsOn_startTerminationActionFromAvr() {
+        mHdmiCecLocalDeviceAudioSystem.setArcStatus(true);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isTrue();
+
+        HdmiCecMessage message = HdmiCecMessageBuilder
+            .buildRequestArcTermination(ADDR_TV, ADDR_AUDIO_SYSTEM);
+        mHdmiCecLocalDeviceAudioSystem.removeAction(
+            ArcTerminationActionFromAvr.class);
+
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcTermination(message))
+            .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiCecLocalDeviceAudioSystem
+            .getActions(ArcTerminationActionFromAvr.class)).isNotEmpty();
+    }
+
+    @Test
+    public void handleRequestArcTerminate_arcIsNotOn() {
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
+        HdmiCecMessage message = HdmiCecMessageBuilder
+            .buildRequestArcTermination(ADDR_TV, ADDR_AUDIO_SYSTEM);
+        HdmiCecMessage expectedMessage = HdmiCecMessageBuilder
+            .buildFeatureAbortCommand(
+                ADDR_AUDIO_SYSTEM, ADDR_TV,
+                Constants.MESSAGE_REQUEST_ARC_TERMINATION,
+                Constants.ABORT_NOT_IN_CORRECT_MODE);
+
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcTermination(message))
+            .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+    }
+
+    @Test
+    public void handleRequestArcInit_arcIsNotSupported() {
+        HdmiCecMessage message = HdmiCecMessageBuilder
+            .buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM);
+        HdmiCecMessage expectedMessage = HdmiCecMessageBuilder
+            .buildFeatureAbortCommand(
+                ADDR_AUDIO_SYSTEM, ADDR_TV,
+                Constants.MESSAGE_REQUEST_ARC_INITIATION,
+                Constants.ABORT_UNRECOGNIZED_OPCODE);
+        SystemProperties.set(Constants.PROPERTY_ARC_SUPPORT, "false");
+
+        assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message))
+            .isTrue();
+        mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+    }
+}
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 78cb56b..910af78 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -16,106 +16,45 @@
 package com.android.server.hdmi;
 
 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;
+
+import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
 import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
 import static com.android.server.hdmi.Constants.ADDR_TV;
 import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
 import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID;
 import static com.android.server.hdmi.Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
-import android.hardware.hdmi.HdmiPortInfo;
+import android.hardware.hdmi.HdmiControlManager;
 import android.os.test.TestLooper;
-import android.support.test.filters.SmallTest;
-import android.os.MessageQueue;
-import com.android.server.hdmi.HdmiCecController.NativeWrapper;
-import junit.framework.Assert;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
 import java.util.Arrays;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.util.Arrays;
+
 @SmallTest
 @RunWith(JUnit4.class)
-/**
- * Tests for {@link HdmiCecLocalDevice} class.
- */
+/** Tests for {@link HdmiCecLocalDevice} class. */
 public class HdmiCecLocalDeviceTest {
 
-    private static final class NativeWrapperImpl implements NativeWrapper {
-
-        @Override
-        public long nativeInit(HdmiCecController handler, MessageQueue messageQueue) {
-            return 1L;
-        }
-
-        @Override
-        public int nativeSendCecCommand(long controllerPtr, int srcAddress, int dstAddress,
-            byte[] body) {
-            return SendCecCommandFactory(srcAddress, dstAddress, body);
-        }
-
-        @Override
-        public int nativeAddLogicalAddress(long controllerPtr, int logicalAddress) {
-            return 0;
-        }
-
-        @Override
-        public void nativeClearLogicalAddress(long controllerPtr) {
-
-        }
-
-        @Override
-        public int nativeGetPhysicalAddress(long controllerPtr) {
-            return mPhysicalAddr;
-        }
-
-        @Override
-        public int nativeGetVersion(long controllerPtr) {
-            return 0;
-        }
-
-        @Override
-        public int nativeGetVendorId(long controllerPtr) {
-            return 0;
-        }
-
-        @Override
-        public HdmiPortInfo[] nativeGetPortInfos(long controllerPtr) {
-            return new HdmiPortInfo[0];
-        }
-
-        @Override
-        public void nativeSetOption(long controllerPtr, int flag, boolean enabled) {
-
-        }
-
-        @Override
-        public void nativeSetLanguage(long controllerPtr, String language) {
-
-        }
-
-        @Override
-        public void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag) {
-
-        }
-
-        @Override
-        public boolean nativeIsConnected(long controllerPtr, int port) {
-            return false;
-        }
-    }
-
     private static int SendCecCommandFactory(int srcAddress, int dstAddress, byte[] body) {
-        switch(body[0] & 0xFF) {
-            /** {@link Constants#MESSAGE_GIVE_PHYSICAL_ADDRESS} */
+        switch (body[0] & 0xFF) {
+                /** {@link Constants#MESSAGE_GIVE_PHYSICAL_ADDRESS} */
             case MESSAGE_REPORT_PHYSICAL_ADDRESS:
             case MESSAGE_DEVICE_VENDOR_ID:
-                return srcAddress == mSrcAddr &&
-                    dstAddress == mDesAddr &&
-                    Arrays.equals(Arrays.copyOfRange(body, 1, body.length), param)? 0 : 1;
+                return srcAddress == mSrcAddr
+                                && dstAddress == mDesAddr
+                                && Arrays.equals(Arrays.copyOfRange(body, 1, body.length), param)
+                        ? 0
+                        : 1;
             default:
                 return 1;
         }
@@ -123,15 +62,12 @@
 
     private class MyHdmiCecLocalDevice extends HdmiCecLocalDevice {
 
-
         protected MyHdmiCecLocalDevice(HdmiControlService service, int deviceType) {
             super(service, deviceType);
         }
 
         @Override
-        protected void onAddressAllocated(int logicalAddress, int reason) {
-
-        }
+        protected void onAddressAllocated(int logicalAddress, int reason) {}
 
         @Override
         protected int getPreferredAddress() {
@@ -139,9 +75,7 @@
         }
 
         @Override
-        protected void setPreferredAddress(int addr) {
-
-        }
+        protected void setPreferredAddress(int addr) {}
     }
 
     private MyHdmiCecLocalDevice mHdmiLocalDevice;
@@ -154,29 +88,54 @@
     private int callbackResult;
     private HdmiCecMessageValidator mMessageValidator;
     private static byte[] param;
+    private boolean mStandbyMessageReceived;
+    private boolean isControlEnabled;
+    private int mPowerStatus;
 
     @Before
     public void SetUp() {
-        mHdmiControlService = new HdmiControlService(null);
+        mHdmiControlService =
+                new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
+                    @Override
+                    boolean isControlEnabled() {
+                        return isControlEnabled;
+                    }
+
+                    @Override
+                    boolean isPowerOnOrTransient() {
+                        return mPowerStatus == HdmiControlManager.POWER_STATUS_ON
+                                || mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
+                    }
+
+                    @Override
+                    void standby() {
+                        mStandbyMessageReceived = true;
+                    }
+                };
         mHdmiControlService.setIoLooper(mTestLooper.getLooper());
-        mHdmiCecController = HdmiCecController.createWithNativeWrapper(
-            mHdmiControlService, new NativeWrapperImpl());
+        mHdmiCecController =
+                HdmiCecController.createWithNativeWrapper(
+                        mHdmiControlService, new FakeNativeWrapper());
         mHdmiControlService.setCecController(mHdmiCecController);
-        mHdmiLocalDevice = new MyHdmiCecLocalDevice(
-            mHdmiControlService, DEVICE_TV);
-        mMessageValidator = new HdmiCecMessageValidator(mHdmiControlService){
-            @Override
-            int isValid(HdmiCecMessage message) {
-                return HdmiCecMessageValidator.OK;
-            }
-        };
+        mHdmiLocalDevice = new MyHdmiCecLocalDevice(mHdmiControlService, DEVICE_TV);
+        mMessageValidator =
+                new HdmiCecMessageValidator(mHdmiControlService) {
+                    @Override
+                    int isValid(HdmiCecMessage message) {
+                        return HdmiCecMessageValidator.OK;
+                    }
+                };
         mHdmiControlService.setMessageValidator(mMessageValidator);
     }
 
     @Test
     public void dispatchMessage_desNotValid() {
-        HdmiCecMessage msg = new HdmiCecMessage(
-            ADDR_TV, ADDR_TV, Constants.MESSAGE_CEC_VERSION, HdmiCecMessage.EMPTY_PARAM);
+        HdmiCecMessage msg =
+                new HdmiCecMessage(
+                        ADDR_TV,
+                        ADDR_TV,
+                        Constants.MESSAGE_CEC_VERSION,
+                        HdmiCecMessage.EMPTY_PARAM);
         boolean handleResult = mHdmiLocalDevice.dispatchMessage(msg);
         assertFalse(handleResult);
     }
@@ -185,18 +144,19 @@
     public void handleGivePhysicalAddress_success() {
         mSrcAddr = ADDR_UNREGISTERED;
         mDesAddr = ADDR_BROADCAST;
-        param = new byte[] {
-            (byte) ((mPhysicalAddr >> 8) & 0xFF),
-            (byte) (mPhysicalAddr & 0xFF),
-            (byte) (DEVICE_TV & 0xFF)
-        };
+        param =
+                new byte[] {
+                    (byte) ((mPhysicalAddr >> 8) & 0xFF),
+                    (byte) (mPhysicalAddr & 0xFF),
+                    (byte) (DEVICE_TV & 0xFF)
+                };
         callbackResult = -1;
-        boolean handleResult = mHdmiLocalDevice.handleGivePhysicalAddress(
-            (int finalResult) -> callbackResult = finalResult);
+        boolean handleResult =
+                mHdmiLocalDevice.handleGivePhysicalAddress(
+                        (int finalResult) -> callbackResult = finalResult);
         mTestLooper.dispatchAll();
         /**
-         * Test if CecMessage is sent successfully
-         * SendMessageResult#SUCCESS is defined in HAL as 0
+         * Test if CecMessage is sent successfully SendMessageResult#SUCCESS is defined in HAL as 0
          */
         assertEquals(0, callbackResult);
         assertTrue(handleResult);
@@ -207,15 +167,21 @@
         mSrcAddr = ADDR_UNREGISTERED;
         mDesAddr = ADDR_BROADCAST;
         /** nativeGetVendorId returns 0 */
-        param = new byte[] {
-            (byte) ((0 >> 8) & 0xFF),
-            (byte) (0 & 0xFF),
-            (byte) (0 & 0xFF)
-        };
+        param = new byte[] {(byte) ((0 >> 8) & 0xFF), (byte) (0 & 0xFF), (byte) (0 & 0xFF)};
         callbackResult = -1;
         mHdmiLocalDevice.handleGiveDeviceVendorId(
-            (int finalResult) -> callbackResult = finalResult);
+                (int finalResult) -> callbackResult = finalResult);
         mTestLooper.dispatchAll();
         assertEquals(0, callbackResult);
     }
+
+    @Test
+    public void handleStandby_isPowerOn() {
+        mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
+        isControlEnabled = true;
+        assertFalse(mStandbyMessageReceived);
+        mHdmiLocalDevice.handleStandby(
+                HdmiCecMessageBuilder.buildStandby(ADDR_TV, ADDR_AUDIO_SYSTEM));
+        assertTrue(mStandbyMessageReceived);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
new file mode 100644
index 0000000..c7809d3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
+import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
+import static com.android.server.hdmi.Constants.ADDR_TV;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.hardware.hdmi.HdmiDeviceInfo;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+/** Tests for {@link HdmiCecMessageBuilder}.. */
+public class HdmiCecMessageBuilderTest {
+
+    @Test
+    public void buildReportPhysicalAddressCommand() {
+        HdmiCecMessage message =
+                HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+                        ADDR_PLAYBACK_1, 0x1234, HdmiDeviceInfo.DEVICE_PLAYBACK);
+        assertThat(message).isEqualTo(buildMessage("4f:84:12:34:04"));
+    }
+
+    @Test
+    public void buildRequestShortAudioDescriptor() {
+        HdmiCecMessage message =
+                HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+                        ADDR_TV,
+                        ADDR_AUDIO_SYSTEM,
+                        new int[] {Constants.AUDIO_CODEC_AAC, Constants.AUDIO_CODEC_LPCM});
+        assertThat(message).isEqualTo(buildMessage("05:A4:06:01"));
+    }
+
+    /**
+     * Build a CEC message from a hex byte string with bytes separated by {@code :}.
+     *
+     * <p>This format is used by both cec-client and www.cec-o-matic.com
+     */
+    private static HdmiCecMessage buildMessage(String message) {
+        String[] parts = message.split(":");
+        int src = Integer.parseInt(parts[0].substring(0, 1), 16);
+        int dest = Integer.parseInt(parts[0].substring(1, 2), 16);
+        int opcode = Integer.parseInt(parts[1], 16);
+        byte[] params = new byte[parts.length - 2];
+        for (int i = 0; i < params.length; i++) {
+            params[i] = Byte.parseByte(parts[i + 2], 16);
+        }
+        return new HdmiCecMessage(src, dest, opcode, params);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
new file mode 100644
index 0000000..18c9a65
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM;
+import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_PLAYBACK;
+
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.os.Looper;
+import android.os.test.TestLooper;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+
+/**
+ * Tests for {@link HdmiControlService} class.
+ */
+@SmallTest
+@RunWith(JUnit4.class)
+public class HdmiControlServiceTest {
+
+    private class HdmiCecLocalDeviceMyDevice extends HdmiCecLocalDevice {
+
+        private boolean mCanGoToStandby;
+        private boolean mIsStandby;
+        private boolean mIsDisabled;
+
+        protected HdmiCecLocalDeviceMyDevice(HdmiControlService service, int deviceType) {
+            super(service, deviceType);
+        }
+
+        @Override
+        protected void onAddressAllocated(int logicalAddress, int reason) {}
+
+        @Override
+        protected int getPreferredAddress() {
+            return 0;
+        }
+
+        @Override
+        protected void setPreferredAddress(int addr) {}
+
+        @Override
+        protected boolean canGoToStandby() {
+            return mCanGoToStandby;
+        }
+
+        @Override
+        protected void disableDevice(
+                boolean initiatedByCec, final PendingActionClearedCallback originalCallback) {
+            mIsDisabled = true;
+            originalCallback.onCleared(this);
+        }
+
+        @Override
+        protected void onStandby(boolean initiatedByCec, int standbyAction) {
+            mIsStandby = true;
+        }
+
+        protected boolean isStandby() {
+            return mIsStandby;
+        }
+
+        protected boolean isDisabled() {
+            return mIsDisabled;
+        }
+
+        protected void setCanGoToStandby(boolean canGoToStandby) {
+            mCanGoToStandby = canGoToStandby;
+        }
+    }
+
+    private static final String TAG = "HdmiControlServiceTest";
+    private HdmiControlService mHdmiControlService;
+    private HdmiCecController mHdmiCecController;
+    private HdmiCecLocalDeviceMyDevice mMyAudioSystemDevice;
+    private HdmiCecLocalDeviceMyDevice mMyPlaybackDevice;
+    private FakeNativeWrapper mNativeWrapper;
+    private Looper mMyLooper;
+    private TestLooper mTestLooper = new TestLooper();
+    private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+    private boolean mStandbyMessageReceived;
+
+    @Before
+    public void SetUp() {
+        mHdmiControlService =
+                new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
+                    @Override
+                    boolean isStandbyMessageReceived() {
+                        return mStandbyMessageReceived;
+                    }
+                };
+        mMyLooper = mTestLooper.getLooper();
+
+        mMyAudioSystemDevice =
+                new HdmiCecLocalDeviceMyDevice(mHdmiControlService, DEVICE_AUDIO_SYSTEM);
+        mMyPlaybackDevice = new HdmiCecLocalDeviceMyDevice(mHdmiControlService, DEVICE_PLAYBACK);
+        mMyAudioSystemDevice.init();
+        mMyPlaybackDevice.init();
+
+        mHdmiControlService.setIoLooper(mMyLooper);
+
+        mNativeWrapper = new FakeNativeWrapper();
+        mHdmiCecController =
+                HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+        mHdmiControlService.setCecController(mHdmiCecController);
+        mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+        mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+
+        mLocalDevices.add(mMyAudioSystemDevice);
+        mLocalDevices.add(mMyPlaybackDevice);
+        mHdmiControlService.initPortInfo();
+        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+
+        mTestLooper.dispatchAll();
+    }
+
+    @Test
+    public void onStandby_notByCec_cannotGoToStandby() {
+        mStandbyMessageReceived = false;
+        mMyPlaybackDevice.setCanGoToStandby(false);
+
+        mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF);
+        assertTrue(mMyPlaybackDevice.isStandby());
+        assertTrue(mMyAudioSystemDevice.isStandby());
+        assertFalse(mMyPlaybackDevice.isDisabled());
+        assertFalse(mMyAudioSystemDevice.isDisabled());
+    }
+
+    @Test
+    public void onStandby_byCec() {
+        mStandbyMessageReceived = true;
+
+        mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF);
+        assertTrue(mMyPlaybackDevice.isStandby());
+        assertTrue(mMyAudioSystemDevice.isStandby());
+        assertTrue(mMyPlaybackDevice.isDisabled());
+        assertTrue(mMyAudioSystemDevice.isDisabled());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
new file mode 100644
index 0000000..d914b9a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.annotation.Nullable;
+import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.media.AudioManager;
+import android.os.Looper;
+import android.os.test.TestLooper;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link SystemAudioInitiationActionFromAvr} */
+@SmallTest
+@RunWith(JUnit4.class)
+public class SystemAudioInitiationActionFromAvrTest {
+
+    private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem;
+    private TestLooper mTestLooper = new TestLooper();
+
+    private boolean mShouldDispatchActiveSource;
+    private boolean mTvSystemAudioModeSupport;
+    private int mTryCountBeforeSucceed;
+    private HdmiDeviceInfo mDeviceInfoForTests;
+
+    private int mMsgRequestActiveSourceCount;
+    private int mMsgSetSystemAudioModeCount;
+    private int mQueryTvSystemAudioModeSupportCount;
+
+    @Before
+    public void SetUp() {
+        mDeviceInfoForTests = new HdmiDeviceInfo(1001, 1234);
+        HdmiControlService hdmiControlService =
+                new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
+
+                    @Override
+                    void sendCecCommand(
+                            HdmiCecMessage command, @Nullable SendMessageCallback callback) {
+                        switch (command.getOpcode()) {
+                            case Constants.MESSAGE_REQUEST_ACTIVE_SOURCE:
+                                mMsgRequestActiveSourceCount++;
+                                if (mTryCountBeforeSucceed >= mMsgRequestActiveSourceCount
+                                        && callback != null) {
+                                    callback.onSendCompleted(SendMessageResult.NACK);
+                                    break;
+                                }
+                                if (mShouldDispatchActiveSource) {
+                                    mHdmiCecLocalDeviceAudioSystem.dispatchMessage(
+                                            HdmiCecMessageBuilder.buildActiveSource(
+                                                    Constants.ADDR_TV, 1002));
+                                }
+                                break;
+                            case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE:
+                                mMsgSetSystemAudioModeCount++;
+                                if (mTryCountBeforeSucceed >= mMsgSetSystemAudioModeCount
+                                        && callback != null) {
+                                    callback.onSendCompleted(SendMessageResult.NACK);
+                                }
+                                break;
+                            default:
+                                throw new IllegalArgumentException("Unexpected message");
+                        }
+                    }
+
+                    @Override
+                    AudioManager getAudioManager() {
+                        return new AudioManager() {
+
+                            @Override
+                            public int setHdmiSystemAudioSupported(boolean on) {
+                                return 0;
+                            }
+
+                            @Override
+                            public int getStreamVolume(int streamType) {
+                                return 0;
+                            }
+
+                            @Override
+                            public boolean isStreamMute(int streamType) {
+                                return false;
+                            }
+
+                            @Override
+                            public int getStreamMaxVolume(int streamType) {
+                                return 100;
+                            }
+
+                            @Override
+                            public void adjustStreamVolume(
+                                    int streamType, int direction, int flags) {}
+                        };
+                    }
+
+                    @Override
+                    boolean isPowerStandby() {
+                        return false;
+                    }
+
+                    @Override
+                    boolean isAddressAllocated() {
+                        return true;
+                    }
+
+                    @Override
+                    void wakeUp() {}
+
+                    @Override
+                    int getPhysicalAddress() {
+                        return 0;
+                    }
+                };
+        mHdmiCecLocalDeviceAudioSystem =
+                new HdmiCecLocalDeviceAudioSystem(hdmiControlService) {
+                    @Override
+                    void queryTvSystemAudioModeSupport(
+                            TvSystemAudioModeSupportedCallback callback) {
+                        mQueryTvSystemAudioModeSupportCount++;
+                        if (callback != null) {
+                            callback.onResult(mTvSystemAudioModeSupport);
+                        }
+                    }
+
+                    @Override
+                    HdmiDeviceInfo getDeviceInfo() {
+                        return mDeviceInfoForTests;
+                    }
+                };
+        mHdmiCecLocalDeviceAudioSystem.init();
+        Looper looper = mTestLooper.getLooper();
+        hdmiControlService.setIoLooper(looper);
+    }
+
+    @Test
+    public void testNoActiveSourceMessageReceived() {
+        resetTestVariables();
+        mShouldDispatchActiveSource = false;
+
+        assertThat(mHdmiCecLocalDeviceAudioSystem.mActiveSource.physicalAddress)
+                .isEqualTo(Constants.INVALID_PHYSICAL_ADDRESS);
+
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
+                new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
+        mTestLooper.dispatchAll();
+
+        assertThat(mMsgRequestActiveSourceCount).isEqualTo(1);
+        assertThat(mMsgSetSystemAudioModeCount).isEqualTo(0);
+        assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(0);
+        assertFalse(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
+
+        assertThat(mHdmiCecLocalDeviceAudioSystem.mActiveSource.physicalAddress)
+                .isEqualTo(Constants.INVALID_PHYSICAL_ADDRESS);
+    }
+
+    @Test
+    public void testTvNotSupport() {
+        resetTestVariables();
+        mShouldDispatchActiveSource = true;
+        mTvSystemAudioModeSupport = false;
+
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
+                new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
+        mTestLooper.dispatchAll();
+
+        assertThat(mMsgRequestActiveSourceCount).isEqualTo(1);
+        assertThat(mMsgSetSystemAudioModeCount).isEqualTo(0);
+        assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
+        assertFalse(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
+    }
+
+    @Test
+    public void testTvSupport() {
+        resetTestVariables();
+        mShouldDispatchActiveSource = true;
+        mTvSystemAudioModeSupport = true;
+
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
+                new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
+        mTestLooper.dispatchAll();
+
+        assertThat(mMsgRequestActiveSourceCount).isEqualTo(1);
+        assertThat(mMsgSetSystemAudioModeCount).isEqualTo(1);
+        assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
+        assertTrue(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
+
+        assertThat(mHdmiCecLocalDeviceAudioSystem.mActiveSource.physicalAddress).isEqualTo(1002);
+    }
+
+    @Test
+    public void testKnownActiveSource() {
+        resetTestVariables();
+        mTvSystemAudioModeSupport = true;
+        mHdmiCecLocalDeviceAudioSystem.mActiveSource.physicalAddress = 1001;
+
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
+                new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
+        mTestLooper.dispatchAll();
+
+        assertThat(mMsgRequestActiveSourceCount).isEqualTo(0);
+        assertThat(mMsgSetSystemAudioModeCount).isEqualTo(1);
+        assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
+        assertTrue(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
+    }
+
+    @Test
+    public void testRetry() {
+        resetTestVariables();
+        mTvSystemAudioModeSupport = true;
+        mShouldDispatchActiveSource = true;
+        mTryCountBeforeSucceed = 3;
+        assertThat(mTryCountBeforeSucceed)
+                .isAtMost(SystemAudioInitiationActionFromAvr.MAX_RETRY_COUNT);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.mActiveSource.physicalAddress)
+                .isEqualTo(Constants.INVALID_PHYSICAL_ADDRESS);
+
+        mHdmiCecLocalDeviceAudioSystem.addAndStartAction(
+                new SystemAudioInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem));
+        mTestLooper.dispatchAll();
+
+        assertThat(mMsgRequestActiveSourceCount).isEqualTo(4);
+        assertThat(mMsgSetSystemAudioModeCount).isEqualTo(4);
+        assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
+        assertTrue(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
+    }
+
+    private void resetTestVariables() {
+        mMsgRequestActiveSourceCount = 0;
+        mMsgSetSystemAudioModeCount = 0;
+        mQueryTvSystemAudioModeSupportCount = 0;
+        mTryCountBeforeSucceed = 0;
+        mHdmiCecLocalDeviceAudioSystem.mActiveSource.physicalAddress =
+                Constants.INVALID_PHYSICAL_ADDRESS;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
index 14b118e..be8e569 100644
--- a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
@@ -38,11 +38,12 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.servicestests.apps.jobtestapp.TestJobActivity;
 
 import org.junit.After;
diff --git a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
index 83bd9fc..e62e07d 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
@@ -29,13 +29,14 @@
 import android.content.pm.PackageManagerInternal;
 import android.os.Build;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.LocalServices;
 import com.android.server.job.controllers.JobStatus;
 
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 4ee2ff4..543f51cba 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -22,12 +22,13 @@
 import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.RenamingDelegatingContext;
 import android.util.Log;
 import android.util.Pair;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.HexDump;
 import com.android.server.IoThread;
 import com.android.server.LocalServices;
diff --git a/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java
index d78af22..1752479 100644
--- a/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -21,7 +21,8 @@
 import android.app.job.JobInfo;
 import android.content.ComponentName;
 import android.os.SystemClock;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.job.JobSchedulerService;
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
index 424c08c..a28a5a1 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
@@ -29,32 +29,28 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static java.io.FileDescriptor.*;
-
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.Binder;
-import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.widget.LockPatternUtils;
 
-import junit.framework.Assert;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.io.FileDescriptor;
+import static java.io.FileDescriptor.*;
 
 /**
  * Test class for {@link LockSettingsShellCommand}.
@@ -80,7 +76,7 @@
         MockitoAnnotations.initMocks(this);
         final Context context = InstrumentationRegistry.getTargetContext();
         mUserId = ActivityManager.getCurrentUser();
-        mCommand = new LockSettingsShellCommand(context, mLockPatternUtils);
+        mCommand = new LockSettingsShellCommand(mLockPatternUtils);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/MockWeaverService.java b/services/tests/servicestests/src/com/android/server/locksettings/MockWeaverService.java
index 34831cd..7fb1278 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/MockWeaverService.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/MockWeaverService.java
@@ -15,7 +15,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 
-public class MockWeaverService implements IWeaver {
+public class MockWeaverService extends IWeaver.Stub {
 
     private static final int MAX_SLOTS = 8;
     private static final int KEY_LENGTH = 256 / 8;
@@ -55,54 +55,4 @@
             cb.onValues(WeaverStatus.FAILED, response);
         }
     }
-
-    @Override
-    public IHwBinder asBinder() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public ArrayList<String> interfaceChain() throws RemoteException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String interfaceDescriptor() throws RemoteException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setHALInstrumentation() throws RemoteException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean linkToDeath(DeathRecipient recipient, long cookie) throws RemoteException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void ping() throws RemoteException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public DebugInfo getDebugInfo() throws RemoteException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void notifySyspropsChanged() throws RemoteException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean unlinkToDeath(DeathRecipient recipient) throws RemoteException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public ArrayList<byte[]> getHashChain() throws RemoteException {
-        throw new UnsupportedOperationException();
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 90947f4..8a9e5d1 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -20,9 +20,9 @@
 import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PASSWORD;
 import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PATTERN;
 import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PIN;
+
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -31,7 +31,6 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
@@ -50,9 +49,10 @@
 import android.security.keystore.recovery.RecoveryController;
 import android.security.keystore.recovery.TrustedRootCertificates;
 import android.security.keystore.recovery.WrappedApplicationKey;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java
index fae48c6..f832d3c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java
@@ -22,8 +22,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.google.common.collect.ImmutableMap;
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
index 0f0e3f3..13436e7 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
@@ -32,9 +32,10 @@
 import android.content.Context;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java
index fd8b319..48afb8b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java
@@ -25,9 +25,10 @@
 import android.security.keystore.AndroidKeyStoreSecretKey;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 8e86a87..b15863d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -23,6 +23,7 @@
 import static android.security.keystore.recovery.RecoveryController.ERROR_INVALID_CERTIFICATE;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
@@ -35,16 +36,14 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.Manifest;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
-import android.Manifest;
 import android.os.Binder;
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
-import android.security.KeyStore;
-import android.security.keystore.AndroidKeyStoreProvider;
 import android.security.keystore.AndroidKeyStoreSecretKey;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
@@ -53,9 +52,10 @@
 import android.security.keystore.recovery.RecoveryCertPath;
 import android.security.keystore.recovery.TrustedRootCertificates;
 import android.security.keystore.recovery.WrappedApplicationKey;
-import android.support.test.filters.SmallTest;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
@@ -75,19 +75,16 @@
 
 import java.io.File;
 import java.nio.charset.StandardCharsets;
-import java.security.UnrecoverableKeyException;
 import java.security.cert.CertPath;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
-import java.util.concurrent.Executors;
 import java.util.Map;
 import java.util.Random;
+import java.util.concurrent.Executors;
 
-import javax.crypto.Cipher;
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
-import javax.crypto.spec.GCMParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 
 @SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java
index acc200f..33038aa 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java
@@ -8,9 +8,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/SecureBoxTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/SecureBoxTest.java
index 35ec23b..15b0708 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/SecureBoxTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/SecureBoxTest.java
@@ -17,11 +17,16 @@
 package com.android.server.locksettings.recoverablekeystore;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.testng.Assert.assertThrows;
 import static org.testng.Assert.expectThrows;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
@@ -31,9 +36,8 @@
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.spec.ECPrivateKeySpec;
+
 import javax.crypto.AEADBadTagException;
-import org.junit.Test;
-import org.junit.runner.RunWith;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java
index 67436cc..944d6e0 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java
@@ -3,8 +3,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.security.keystore.recovery.TrustedRootCertificates;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.widget.LockPatternUtils;
 
@@ -13,6 +14,7 @@
 
 import java.util.HashMap;
 import java.util.Map;
+
 import javax.crypto.SecretKey;
 
 @SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java
index 56122a7..b5ee60e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java
@@ -24,8 +24,9 @@
 import android.security.keystore.AndroidKeyStoreSecretKey;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertUtilsTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertUtilsTest.java
index 9279698..1cbebff 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertUtilsTest.java
@@ -18,13 +18,17 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static java.nio.charset.StandardCharsets.UTF_8;
-
 import static org.testng.Assert.assertThrows;
 import static org.testng.Assert.expectThrows;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.w3c.dom.Element;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.io.InputStream;
 import java.security.KeyPairGenerator;
@@ -39,10 +43,6 @@
 import java.util.Collections;
 import java.util.List;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.w3c.dom.Element;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public final class CertUtilsTest {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java
index 52269d9..bbcc411 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java
@@ -21,17 +21,17 @@
 import static org.testng.Assert.assertThrows;
 import static org.testng.Assert.expectThrows;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import java.security.cert.CertPath;
-import java.security.cert.X509Certificate;
-import java.util.List;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.security.cert.CertPath;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public final class CertXmlTest {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/SigXmlTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/SigXmlTest.java
index 4d87006..45adb4b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/SigXmlTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/SigXmlTest.java
@@ -21,8 +21,8 @@
 import static org.testng.Assert.assertThrows;
 import static org.testng.Assert.expectThrows;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/TestData.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/TestData.java
index 5eb4166..c5792ad 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/TestData.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/TestData.java
@@ -17,7 +17,8 @@
 package com.android.server.locksettings.recoverablekeystore.certificate;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
+
+import androidx.test.InstrumentationRegistry;
 
 import com.google.common.io.ByteStreams;
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java
index a23ac0f..880255d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java
@@ -22,9 +22,9 @@
 import android.security.keystore.recovery.KeyChainSnapshot;
 import android.security.keystore.recovery.KeyDerivationParams;
 import android.security.keystore.recovery.WrappedApplicationKey;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.locksettings.recoverablekeystore.TestData;
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
index 9b09dd1a..7130b42 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
@@ -18,24 +18,25 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static java.nio.charset.StandardCharsets.UTF_8;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RootOfTrustEntry;
+import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
-import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
-import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RootOfTrustEntry;
-import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;
+import static java.nio.charset.StandardCharsets.UTF_8;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
index 940745e..6a26f8c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
@@ -17,25 +17,27 @@
 package com.android.server.locksettings.recoverablekeystore.storage;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.content.Context;
+import android.security.keystore.recovery.RecoveryController;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.locksettings.recoverablekeystore.TestData;
+import com.android.server.locksettings.recoverablekeystore.WrappedKey;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import android.content.Context;
-import android.security.keystore.recovery.RecoveryController;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.server.locksettings.recoverablekeystore.TestData;
-import com.android.server.locksettings.recoverablekeystore.WrappedKey;
-
 import java.io.File;
 import java.nio.charset.StandardCharsets;
 import java.security.KeyPairGenerator;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java
index bb0474e..c2d1440 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java
@@ -22,8 +22,8 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
index ad14c3a..e8614af 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
@@ -12,9 +12,10 @@
 import android.security.keystore.recovery.KeyChainSnapshot;
 import android.security.keystore.recovery.KeyDerivationParams;
 import android.security.keystore.recovery.WrappedApplicationKey;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.locksettings.recoverablekeystore.TestData;
 
diff --git a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
index 28b54ef..fe7a376 100644
--- a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
@@ -20,10 +20,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import com.android.frameworks.servicestests.R;
-import com.android.servicestests.aidl.ICmdReceiverService;
-import com.android.servicestests.aidl.INetworkStateObserver;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -34,13 +30,17 @@
 import android.os.IBinder;
 import android.os.SystemClock;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.servicestests.aidl.ICmdReceiverService;
+import com.android.servicestests.aidl.INetworkStateObserver;
+
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
@@ -64,7 +64,7 @@
  * Install: adb install -r \
  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
  * Run: adb shell am instrument -e class com.android.server.net.ConnOnActivityStartTest -w \
- *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ *     com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
index 9f4b754..7767a28 100644
--- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
@@ -27,9 +27,10 @@
 import android.net.NetworkUtils;
 import android.net.ProxyInfo;
 import android.net.StaticIpConfiguration;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulDigestsTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulDigestsTests.java
index a34f95e..be56855 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulDigestsTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulDigestsTests.java
@@ -19,8 +19,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.HexDump;
 
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java
index ccd3cdd..b5a354c 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java
@@ -17,7 +17,6 @@
 package com.android.server.net.watchlist;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -30,9 +29,10 @@
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.ServiceThread;
 
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/PrivacyUtilsTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/PrivacyUtilsTests.java
index 6f2237f..9d2c409 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/PrivacyUtilsTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/PrivacyUtilsTests.java
@@ -21,8 +21,9 @@
 import static org.junit.Assert.assertTrue;
 
 import android.privacy.DifferentialPrivacyEncoder;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/ReportEncoderTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/ReportEncoderTests.java
index cb4f6c5..bf125f8 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/ReportEncoderTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/ReportEncoderTests.java
@@ -19,9 +19,13 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.service.nano.NetworkWatchlistAppResultProto;
+import com.android.service.nano.NetworkWatchlistReportProto;
 
 import org.junit.After;
 import org.junit.Before;
@@ -35,9 +39,6 @@
 import java.io.InputStreamReader;
 import java.util.HashMap;
 
-import com.android.service.nano.NetworkWatchlistReportProto;
-import com.android.service.nano.NetworkWatchlistAppResultProto;
-
 /**
  * runtest frameworks-services -c com.android.server.net.watchlist.ReportEncoderTests
  */
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java
index 678f018..fa61c59 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java
@@ -18,13 +18,14 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.HexDump;
 
@@ -40,8 +41,6 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
-import java.util.Arrays;
-
 
 /**
  * runtest frameworks-services -c com.android.server.net.watchlist.WatchlistConfigTests
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
index 8399dac..8bbad8d 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
@@ -17,11 +17,12 @@
 package com.android.server.net.watchlist;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.doAnswer;
-
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
 
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -32,21 +33,18 @@
 import android.os.FileUtils;
 import android.os.Looper;
 import android.os.UserManager;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.InstrumentationRegistry;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
 
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistSettingsTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistSettingsTests.java
index 07158af..03b1c41 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistSettingsTests.java
@@ -20,9 +20,10 @@
 import static org.junit.Assert.assertNotEquals;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.HexDump;
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java
index b2eb572..6591d6f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java
@@ -22,10 +22,11 @@
 import android.content.pm.PackageStats;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.ArrayUtils;
 
 import org.junit.After;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index cdac516..111fb74 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -18,7 +18,8 @@
 
 import android.content.IIntentReceiver;
 import android.os.Bundle;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -106,4 +107,24 @@
         // TODO: test that sendApplicationHiddenForUser() actually fills in
         // broadcastUsers
     }
+
+    @Test
+    public void testPartitions() throws Exception {
+        String[] partitions = { "system", "vendor", "odm", "oem", "product", "product_services" };
+        String[] appdir = { "app", "priv-app" };
+        for (int i = 0; i < partitions.length; i++) {
+            for (int j = 0; j < appdir.length; j++) {
+                String canonical = new File("/" + partitions[i]).getCanonicalPath();
+                String path = String.format("%s/%s/A.apk", canonical, appdir[j]);
+
+                Assert.assertEquals(j == 1 && i != 3,
+                    PackageManagerService.locationIsPrivileged(path));
+
+                Assert.assertEquals(i == 1 || i == 2, PackageManagerService.locationIsVendor(path));
+                Assert.assertEquals(i == 3, PackageManagerService.locationIsOem(path));
+                Assert.assertEquals(i == 4, PackageManagerService.locationIsProduct(path));
+                Assert.assertEquals(i == 5, PackageManagerService.locationIsProductServices(path));
+            }
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 97ff94f..ee41c0b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -42,14 +42,15 @@
 import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.LongSparseArray;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.os.AtomicFile;
 import com.android.server.LocalServices;
 import com.android.server.pm.permission.PermissionManagerInternal;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 2f6e2c2..318ed3a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.server.pm;
 
+import static org.junit.Assert.*;
+
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ConfigurationInfo;
@@ -28,9 +30,18 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import libcore.io.IoUtils;
 
 import java.io.File;
 import java.lang.reflect.Array;
@@ -42,16 +53,6 @@
 import java.util.List;
 import java.util.Set;
 
-import static org.junit.Assert.*;
-
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import libcore.io.IoUtils;
-
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class PackageParserTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
index 2a4ea8c..4a33ca3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -24,10 +24,11 @@
 
 import android.content.pm.PackageUserState;
 import android.os.PersistableBundle;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
index d665094..41489dc 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
@@ -17,9 +17,10 @@
 package com.android.server.pm;
 
 import android.content.pm.PackageParser;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import junit.framework.Assert;
 
 import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 6c6c9932..fa73447 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -117,7 +117,7 @@
  adb install \
  -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest1 \
- -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
index ca1e6af..ae01b40 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
@@ -37,7 +37,7 @@
  adb install \
  -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest10 \
- -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 public class ShortcutManagerTest10 extends BaseShortcutManagerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index fcdadac..76d52fd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -50,8 +50,6 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
 import java.io.Writer;
 import java.util.Locale;
 
@@ -62,7 +60,7 @@
  adb install \
  -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest2 \
- -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index e9a329c..8a489d2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -56,7 +56,7 @@
  adb install \
  -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest8 \
- -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
 
  * TODO for CTS
  * - Foreground check.
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
index 012024f1..edb9df5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -44,7 +44,7 @@
  adb install \
  -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest9 \
- -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 public class ShortcutManagerTest9 extends BaseShortcutManagerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
index c186e48..f115b9c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -41,9 +41,6 @@
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
@@ -52,6 +49,10 @@
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.servicestests.apps.suspendtestapp.SuspendTestActivity;
 import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java
index bb35beb..c489cf0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java
@@ -16,15 +16,22 @@
 
 package com.android.server.pm;
 
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.os.FileUtils;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -39,19 +46,13 @@
 import java.util.Arrays;
 import java.util.Collections;
 
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 /**
  * <p>Run with:<pre>
  * m FrameworksServicesTests &&
  * adb install \
  * -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  * adb shell am instrument -e class com.android.server.pm.UserDataPreparerTest \
- * -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ * -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  * </pre>
  */
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
index 304e0e9..d6f7e37 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
@@ -24,11 +24,12 @@
 import android.content.pm.UserInfo;
 import android.os.RemoteException;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
index c314de4..8dd8967 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
@@ -24,20 +24,21 @@
 import android.os.Looper;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.IconDrawableFactory;
 
-import com.android.server.LocalServices;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import java.util.List;
+import com.android.server.LocalServices;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.List;
+
 /**
  * <p>Run with:<pre>
  * runtest -c com.android.server.pm.UserManagerServiceCreateProfileTest frameworks-services
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java
index 35967fb..a9ce618 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java
@@ -16,12 +16,17 @@
 
 package com.android.server.pm;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import android.content.pm.UserInfo;
 import android.os.Looper;
 import android.os.UserManagerInternal;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.MediumTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.LocalServices;
 
@@ -31,17 +36,13 @@
 
 import java.util.LinkedHashSet;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
 /**
  * <p>Run with:<pre>
  * m FrameworksServicesTests &&
  * adb install \
  * -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  * adb shell am instrument -e class com.android.server.pm.UserManagerServiceIdRecyclingTest \
- * -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ * -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  * </pre>
  */
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index 092119e..806c71a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -16,16 +16,21 @@
 
 package com.android.server.pm;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.content.pm.UserInfo;
 import android.os.Looper;
 import android.os.Parcel;
-import android.os.UserManagerInternal;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.MediumTest;
+import android.os.UserManagerInternal;
 import android.text.TextUtils;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.LocalServices;
 import com.android.server.pm.UserManagerService.UserData;
 
@@ -38,10 +43,6 @@
 import java.io.DataOutputStream;
 import java.util.List;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
 /**
  * <p>Run with:<pre>
  * runtest -c com.android.server.pm.UserManagerServiceUserInfoTest frameworks-services
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
index 882bf32..2cc5323 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
@@ -35,7 +35,7 @@
    adb install \
      -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
    adb shell am instrument -e class com.android.server.pm.UserRestrictionsUtilsTest \
-     -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+     -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  * </pre>
  */
 @SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
index caa1d02..13612a1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
@@ -17,24 +17,22 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.Package;
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
-import android.test.MoreAsserts;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import android.test.MoreAsserts;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.backup.BackupUtils;
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java
index bf8d405..87c3cd2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java
@@ -16,13 +16,19 @@
 
 package com.android.server.pm.dex;
 
+import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
-import android.content.pm.PackageInfo;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.os.storage.StorageManager;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
 
@@ -40,14 +46,6 @@
 
 import java.util.Arrays;
 
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-
-import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
-import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class DexLoggerTests {
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 147347d..416a616 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
@@ -16,16 +16,40 @@
 
 package com.android.server.pm.dex;
 
+import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
+import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.os.Build;
 import android.os.UserHandle;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.pm.Installer;
 
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
+
 import dalvik.system.DelegateLastClassLoader;
 import dalvik.system.PathClassLoader;
 import dalvik.system.VMRuntime;
@@ -38,31 +62,6 @@
 import java.util.List;
 import java.util.Map;
 
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-import org.mockito.quality.Strictness;
-
-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 static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
-import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class DexManagerTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
index 93064bc..62589eb 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
@@ -19,19 +19,19 @@
 
 import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.PackageManagerServiceCompilerMapping;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class DexoptOptionsTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 150f7f0..77f517b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -16,9 +16,8 @@
 
 package com.android.server.pm.dex;
 
-import com.android.server.pm.PackageDexOptimizer;
-
 import static com.android.server.pm.PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -26,17 +25,18 @@
 import static org.junit.Assert.fail;
 
 import android.content.pm.ApplicationInfo;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import dalvik.system.DelegateLastClassLoader;
 import dalvik.system.DexClassLoader;
 import dalvik.system.PathClassLoader;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 import java.io.File;
 import java.util.Arrays;
 import java.util.Collections;
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 69a148d..3e93dcf 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
@@ -16,16 +16,27 @@
 
 package com.android.server.pm.dex;
 
-import android.os.Build;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import dalvik.system.VMRuntime;
+import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
+import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
 
-import java.util.Collections;
+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.os.Build;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import dalvik.system.VMRuntime;
+
 import java.io.IOException;
 import java.io.StringReader;
 import java.io.StringWriter;
@@ -35,16 +46,6 @@
 import java.util.Map;
 import java.util.Set;
 
-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 static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
-import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PackageDexUsageTests {
diff --git a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
index 7487d44..b238e43 100644
--- a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
+++ b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
@@ -25,20 +25,12 @@
 import android.view.IApplicationToken;
 import android.view.WindowManager;
 
+import com.android.server.wm.WindowFrames;
 import com.android.server.wm.utils.WmDisplayCutout;
 
 public class FakeWindowState implements WindowManagerPolicy.WindowState {
 
-    public final Rect parentFrame = new Rect();
-    public final Rect displayFrame = new Rect();
-    public final Rect overscanFrame = new Rect();
-    public final Rect contentFrame = new Rect();
-    public final Rect visibleFrame = new Rect();
-    public final Rect decorFrame = new Rect();
-    public final Rect stableFrame = new Rect();
-    public Rect outsetFrame = new Rect();
-
-    public WmDisplayCutout displayCutout;
+    private WindowFrames windowFrames;
 
     public WindowManager.LayoutParams attrs;
     public int displayId;
@@ -61,44 +53,41 @@
     }
 
     @Override
-    public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overlayFrame,
-            Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
-            @Nullable Rect outsetFrame, WmDisplayCutout displayCutout,
-            boolean parentFrameWasClippedByDisplayCutout) {
-        this.parentFrame.set(parentFrame);
-        this.displayFrame.set(displayFrame);
-        this.overscanFrame.set(overlayFrame);
-        this.contentFrame.set(contentFrame);
-        this.visibleFrame.set(visibleFrame);
-        this.decorFrame.set(decorFrame);
-        this.stableFrame.set(stableFrame);
-        this.outsetFrame = outsetFrame == null ? null : new Rect(outsetFrame);
-        this.displayCutout = displayCutout;
+    public void computeFrameLw(WindowFrames windowFrames) {
+        this.windowFrames = windowFrames;
     }
 
     @Override
     public Rect getFrameLw() {
-        return parentFrame;
+        return windowFrames.mParentFrame;
     }
 
     @Override
     public Rect getDisplayFrameLw() {
-        return displayFrame;
+        return windowFrames.mDisplayFrame;
     }
 
     @Override
     public Rect getOverscanFrameLw() {
-        return overscanFrame;
+        return windowFrames.mOverscanFrame;
     }
 
     @Override
     public Rect getContentFrameLw() {
-        return contentFrame;
+        return windowFrames.mContentFrame;
     }
 
     @Override
     public Rect getVisibleFrameLw() {
-        return visibleFrame;
+        return windowFrames.mVisibleFrame;
+    }
+
+    public Rect getStableFrame() {
+        return windowFrames.mStableFrame;
+    }
+
+    public Rect getDecorFrame() {
+        return windowFrames.mDecorFrame;
     }
 
     @Override
@@ -255,6 +244,9 @@
     }
 
     @Override
+    public boolean canReceiveKeys() { return false; }
+
+    @Override
     public void writeIdentifierToProto(ProtoOutputStream proto, long fieldId){
         throw new UnsupportedOperationException("not implemented");
     }
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java
index 7e18ce7..cce6ba7 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java
@@ -22,16 +22,15 @@
 import static android.view.Surface.ROTATION_90;
 
 import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
 
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.Display;
 import android.view.DisplayInfo;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
index 97a716f..fee761d 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
@@ -22,7 +22,6 @@
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -40,11 +39,12 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.DisplayCutout;
 import android.view.WindowManager;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -76,11 +76,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetByTopBottom(mAppWindow.parentFrame, 0, 0);
-        assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0);
-        assertInsetBy(mAppWindow.displayFrame, 0, 0, 0, 0);
+        assertInsetByTopBottom(mAppWindow.getFrameLw(), 0, 0);
+        assertInsetByTopBottom(mAppWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDecorFrame(), 0, 0);
+        assertInsetBy(mAppWindow.getDisplayFrameLw(), 0, 0, 0, 0);
     }
 
     @Test
@@ -91,11 +91,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetByTopBottom(mAppWindow.parentFrame, 0, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.decorFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.displayFrame, 0, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getFrameLw(), 0, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDecorFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT);
     }
 
     @Test
@@ -107,11 +107,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetByTopBottom(mAppWindow.parentFrame, 0, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.decorFrame, 0, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.displayFrame, 0, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getFrameLw(), 0, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDecorFrame(), 0, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT);
     }
 
     @Test
@@ -132,11 +132,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetByTopBottom(mAppWindow.parentFrame, 0, 0);
-        assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0);
-        assertInsetByTopBottom(mAppWindow.displayFrame, 0, 0);
+        assertInsetByTopBottom(mAppWindow.getFrameLw(), 0, 0);
+        assertInsetByTopBottom(mAppWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDecorFrame(), 0, 0);
+        assertInsetByTopBottom(mAppWindow.getDisplayFrameLw(), 0, 0);
     }
 
     @Test
@@ -149,11 +149,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetByTopBottom(mAppWindow.parentFrame, STATUS_BAR_HEIGHT, 0);
-        assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0);
-        assertInsetByTopBottom(mAppWindow.displayFrame, STATUS_BAR_HEIGHT, 0);
+        assertInsetByTopBottom(mAppWindow.getFrameLw(), STATUS_BAR_HEIGHT, 0);
+        assertInsetByTopBottom(mAppWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDecorFrame(), 0, 0);
+        assertInsetByTopBottom(mAppWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0);
     }
 
     @Test
@@ -166,11 +166,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetByTopBottom(mAppWindow.parentFrame, 0, 0);
-        assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0);
-        assertInsetBy(mAppWindow.displayFrame, 0, 0, 0, 0);
+        assertInsetByTopBottom(mAppWindow.getFrameLw(), 0, 0);
+        assertInsetByTopBottom(mAppWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDecorFrame(), 0, 0);
+        assertInsetBy(mAppWindow.getDisplayFrameLw(), 0, 0, 0, 0);
     }
 
     @Test
@@ -183,11 +183,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetByTopBottom(mAppWindow.parentFrame, STATUS_BAR_HEIGHT, 0);
-        assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0);
-        assertInsetByTopBottom(mAppWindow.displayFrame, STATUS_BAR_HEIGHT, 0);
+        assertInsetByTopBottom(mAppWindow.getFrameLw(), STATUS_BAR_HEIGHT, 0);
+        assertInsetByTopBottom(mAppWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDecorFrame(), 0, 0);
+        assertInsetByTopBottom(mAppWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0);
     }
 
     @Test
@@ -201,11 +201,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetByTopBottom(mAppWindow.parentFrame, 0, 0);
-        assertInsetByTopBottom(mAppWindow.stableFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.contentFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.decorFrame, 0, 0);
-        assertInsetByTopBottom(mAppWindow.displayFrame, 0, 0);
+        assertInsetByTopBottom(mAppWindow.getFrameLw(), 0, 0);
+        assertInsetByTopBottom(mAppWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDecorFrame(), 0, 0);
+        assertInsetByTopBottom(mAppWindow.getDisplayFrameLw(), 0, 0);
     }
 
 
@@ -218,12 +218,12 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetBy(mAppWindow.parentFrame, DISPLAY_CUTOUT_HEIGHT, 0, 0, 0);
-        assertInsetBy(mAppWindow.stableFrame, 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
-        assertInsetBy(mAppWindow.contentFrame,
+        assertInsetBy(mAppWindow.getFrameLw(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0);
+        assertInsetBy(mAppWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
+        assertInsetBy(mAppWindow.getContentFrameLw(),
                 DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
-        assertInsetBy(mAppWindow.decorFrame, 0, 0, 0, 0);
-        assertInsetBy(mAppWindow.displayFrame, DISPLAY_CUTOUT_HEIGHT, 0, 0, 0);
+        assertInsetBy(mAppWindow.getDecorFrame(), 0, 0, 0, 0);
+        assertInsetBy(mAppWindow.getDisplayFrameLw(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0);
     }
 
     @Test
@@ -235,12 +235,12 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetBy(mAppWindow.parentFrame, 0, 0, DISPLAY_CUTOUT_HEIGHT, 0);
-        assertInsetBy(mAppWindow.stableFrame, NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0);
-        assertInsetBy(mAppWindow.contentFrame,
+        assertInsetBy(mAppWindow.getFrameLw(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0);
+        assertInsetBy(mAppWindow.getStableFrame(), NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0);
+        assertInsetBy(mAppWindow.getContentFrameLw(),
                 NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, DISPLAY_CUTOUT_HEIGHT, 0);
-        assertInsetBy(mAppWindow.decorFrame, 0, 0, 0, 0);
-        assertInsetBy(mAppWindow.displayFrame, 0, 0, DISPLAY_CUTOUT_HEIGHT, 0);
+        assertInsetBy(mAppWindow.getDecorFrame(), 0, 0, 0, 0);
+        assertInsetBy(mAppWindow.getDisplayFrameLw(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0);
     }
 
     @Test
@@ -254,11 +254,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetBy(mAppWindow.parentFrame, DISPLAY_CUTOUT_HEIGHT, 0, 0, 0);
-        assertInsetBy(mAppWindow.stableFrame, 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
-        assertInsetBy(mAppWindow.contentFrame,
+        assertInsetBy(mAppWindow.getFrameLw(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0);
+        assertInsetBy(mAppWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
+        assertInsetBy(mAppWindow.getContentFrameLw(),
                 DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
-        assertInsetBy(mAppWindow.decorFrame, 0, 0, 0, 0);
+        assertInsetBy(mAppWindow.getDecorFrame(), 0, 0, 0, 0);
     }
 
     @Test
@@ -274,8 +274,8 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetByTopBottom(mAppWindow.parentFrame, 0, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mAppWindow.displayFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getFrameLw(), 0, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
     }
 
     @Test
@@ -290,11 +290,11 @@
         mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
         mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
 
-        assertInsetBy(mAppWindow.parentFrame, 0, 0, 0, 0);
-        assertInsetBy(mAppWindow.stableFrame, 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
-        assertInsetBy(mAppWindow.contentFrame,
+        assertInsetBy(mAppWindow.getFrameLw(), 0, 0, 0, 0);
+        assertInsetBy(mAppWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
+        assertInsetBy(mAppWindow.getContentFrameLw(),
                 DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
-        assertInsetBy(mAppWindow.decorFrame, 0, 0, 0, 0);
+        assertInsetBy(mAppWindow.getDecorFrame(), 0, 0, 0, 0);
     }
 
     @Test
@@ -309,8 +309,8 @@
         final Rect stable = new Rect();
         final Rect outsets = new Rect();
         final DisplayCutout.ParcelableWrapper cutout = new DisplayCutout.ParcelableWrapper();
-        mPolicy.getLayoutHintLw(mAppWindow.attrs, null /* taskBounds */, mFrames, frame, content,
-                stable, outsets, cutout);
+        mPolicy.getLayoutHintLw(mAppWindow.attrs, null /* taskBounds */, mFrames,
+                false /* floatingStack */, frame, content, stable, outsets, cutout);
 
         assertThat(frame, equalTo(mFrames.mUnrestricted));
         assertThat(content, equalTo(new Rect()));
@@ -331,8 +331,8 @@
         final DisplayCutout.ParcelableWrapper outDisplayCutout =
                 new DisplayCutout.ParcelableWrapper();
 
-        mPolicy.getLayoutHintLw(mAppWindow.attrs, null, mFrames, outFrame, outContentInsets,
-                outStableInsets, outOutsets, outDisplayCutout);
+        mPolicy.getLayoutHintLw(mAppWindow.attrs, null, mFrames, false /* floatingStack */,
+                outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout);
 
         assertThat(outFrame, is(mFrames.mUnrestricted));
         assertThat(outContentInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT)));
@@ -355,8 +355,35 @@
         final DisplayCutout.ParcelableWrapper outDisplayCutout =
                 new DisplayCutout.ParcelableWrapper();
 
-        mPolicy.getLayoutHintLw(mAppWindow.attrs, taskBounds, mFrames, outFrame, outContentInsets,
-                outStableInsets, outOutsets, outDisplayCutout);
+        mPolicy.getLayoutHintLw(mAppWindow.attrs, taskBounds, mFrames, false /* floatingStack */,
+                outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout);
+
+        assertThat(outFrame, is(taskBounds));
+        assertThat(outContentInsets, is(new Rect()));
+        assertThat(outStableInsets, is(new Rect()));
+        assertThat(outOutsets, is(new Rect()));
+        assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper()));
+    }
+
+    @Test
+    public void layoutHint_appWindowInTask_outsideContentFrame() {
+        // Initialize DisplayFrames
+        mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+
+        // Task is in the nav bar area (usually does not happen, but this is similar enough to the
+        // possible overlap with the IME)
+        final Rect taskBounds = new Rect(100, mFrames.mContent.bottom + 1,
+                200, mFrames.mContent.bottom + 10);
+
+        final Rect outFrame = new Rect();
+        final Rect outContentInsets = new Rect();
+        final Rect outStableInsets = new Rect();
+        final Rect outOutsets = new Rect();
+        final DisplayCutout.ParcelableWrapper outDisplayCutout =
+                new DisplayCutout.ParcelableWrapper();
+
+        mPolicy.getLayoutHintLw(mAppWindow.attrs, taskBounds, mFrames, true /* floatingStack */,
+                outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout);
 
         assertThat(outFrame, is(taskBounds));
         assertThat(outContentInsets, is(new Rect()));
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTest.java
index 30665b5..d92d7e0 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTest.java
@@ -19,6 +19,10 @@
 import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.DOCKED_TOP;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
@@ -28,13 +32,9 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.DOCKED_BOTTOM;
-import static android.view.WindowManager.DOCKED_LEFT;
-import static android.view.WindowManager.DOCKED_RIGHT;
-import static android.view.WindowManager.DOCKED_TOP;
 
-import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
 import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
+import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
 import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;
 
 import static org.junit.Assert.assertEquals;
@@ -44,10 +44,11 @@
 
 import android.graphics.PixelFormat;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.WindowManager;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
index 2c47a94..acd065e 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
@@ -34,12 +34,11 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Matrix;
-import android.graphics.Path;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.os.IBinder;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
 import android.testing.TestableResources;
 import android.util.Pair;
 import android.view.Display;
@@ -52,8 +51,11 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IAccessibilityManager;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
 import com.android.server.wm.DisplayFrames;
+import com.android.server.wm.WindowTestUtils.TestDisplayContent;
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import org.junit.Before;
@@ -122,7 +124,6 @@
         mNavigationBar.attrs.gravity = Gravity.BOTTOM;
 
         mPolicy.addWindow(mNavigationBar);
-        mPolicy.mHasNavigationBar = true;
         mPolicy.mLastSystemUiFlags |= View.NAVIGATION_BAR_TRANSPARENT;
     }
 
@@ -172,15 +173,14 @@
     }
 
     private static DisplayCutout displayCutoutForRotation(int rotation) {
-        Path p = new Path();
-        p.addRect(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT,
-                Path.Direction.CCW);
+        RectF rectF = new RectF(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT);
 
         Matrix m = new Matrix();
         transformPhysicalToLogicalCoordinates(rotation, DISPLAY_WIDTH, DISPLAY_HEIGHT, m);
-        p.transform(m);
+        m.mapRect(rectF);
 
-        return DisplayCutout.fromBounds(p);
+        return DisplayCutout.fromBoundingRect((int) rectF.left, (int) rectF.top,
+                (int) rectF.right, (int) rectF.bottom);
     }
 
     static class TestContextWrapper extends ContextWrapper {
@@ -245,12 +245,10 @@
                 policy[0].mAccessibilityManager = new AccessibilityManager(context,
                         mock(IAccessibilityManager.class), UserHandle.USER_CURRENT);
                 policy[0].mSystemGestures = mock(SystemGesturesPointerEventListener.class);
-                policy[0].mNavigationBarCanMove = true;
-                policy[0].mPortraitRotation = ROTATION_0;
-                policy[0].mLandscapeRotation = ROTATION_90;
-                policy[0].mUpsideDownRotation = ROTATION_180;
-                policy[0].mSeascapeRotation = ROTATION_270;
-                policy[0].onConfigurationChanged();
+
+                final TestDisplayContent displayContent = TestDisplayContent.create(context);
+                policy[0].setDefaultDisplay(displayContent);
+                policy[0].onConfigurationChanged(displayContent);
             });
             return policy[0];
         }
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
index 5b24725..fd04970 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
@@ -23,11 +23,13 @@
 import static org.mockito.Mockito.when;
 
 import android.content.ContentResolver;
+import android.content.res.Resources;
 import android.provider.Settings.Global;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContext;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.google.common.base.Objects;
 
 import org.junit.Before;
@@ -48,12 +50,18 @@
     private BatterySaverController mMockBatterySaverController;
     private Device mDevice;
     private TestableBatterySaverStateMachine mTarget;
+    private Resources mMockResources;
 
     private class MyMockContext extends MockContext {
         @Override
         public ContentResolver getContentResolver() {
             return mMockContextResolver;
         }
+
+        @Override
+        public Resources getResources() {
+            return mMockResources;
+        }
     }
 
     private DevicePersistedState mPersistedState;
@@ -157,11 +165,15 @@
         mMockContext = new MyMockContext();
         mMockContextResolver = mock(ContentResolver.class);
         mMockBatterySaverController = mock(BatterySaverController.class);
+        mMockResources = mock(Resources.class);
 
         doAnswer((inv) -> mDevice.batterySaverEnabled = inv.getArgument(0))
                 .when(mMockBatterySaverController).enableBatterySaver(anyBoolean(), anyInt());
         when(mMockBatterySaverController.isEnabled())
                 .thenAnswer((inv) -> mDevice.batterySaverEnabled);
+        when(mMockResources.getBoolean(
+                com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled))
+                .thenReturn(false);
 
         mPersistedState = new DevicePersistedState();
         initDevice();
@@ -173,7 +185,6 @@
         mTarget = new TestableBatterySaverStateMachine();
 
         mDevice.pushBatteryStatus();
-        mDevice.pushGlobalSettings();
         mTarget.onBootCompleted();
     }
 
@@ -498,8 +509,83 @@
     }
 
     @Test
-    public void testNoAutoBatterySaver_fromAdb() {
+    public void testAutoBatterySaver_withStickyDisabled() {
+        when(mMockResources.getBoolean(
+                com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled))
+                .thenReturn(true);
+        initDevice();
+        mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
 
+        mTarget.setBatterySaverEnabledManually(true);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(100, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        mDevice.setBatteryLevel(30);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+        assertEquals(true, mPersistedState.batteryLow);
+
+        mDevice.setBatteryLevel(80);
+
+        assertEquals(false, mDevice.batterySaverEnabled); // Not sticky.
+        assertEquals(80, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        mDevice.setPowered(true);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(80, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        mDevice.setBatteryLevel(30);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+        assertEquals(true, mPersistedState.batteryLow);
+
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled); // Restores BS.
+        assertEquals(30, mPersistedState.batteryLevel);
+        assertEquals(true, mPersistedState.batteryLow);
+
+        mDevice.setPowered(true);
+        mDevice.setBatteryLevel(90);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(90, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        initDevice();
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(90, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        mDevice.setPowered(false);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(90, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        mTarget.setBatterySaverEnabledManually(false);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(90, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+
+        initDevice();
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(90, mPersistedState.batteryLevel);
+        assertEquals(false, mPersistedState.batteryLow);
+    }
+
+    @Test
+    public void testNoAutoBatterySaver_fromAdb() {
         assertEquals(0, mDevice.getLowPowerModeTriggerLevel());
 
         assertEquals(false, mDevice.batterySaverEnabled);
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
index 9bd4cc3..ba61fd2 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
@@ -25,8 +25,9 @@
 import static org.mockito.Mockito.verify;
 
 import android.metrics.LogMaker;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/CpuFrequenciesTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/CpuFrequenciesTest.java
index f72ec34..8371e9c 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/CpuFrequenciesTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/CpuFrequenciesTest.java
@@ -17,10 +17,11 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java
index 7324fe6..89c7dd4 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java
@@ -27,14 +27,14 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
-import android.hardware.camera2.impl.GetCommand;
 import android.os.Handler;
 import android.os.Looper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -48,7 +48,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
-
 /**
  atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/power/batterysaver/FileUpdaterTest.java
  */
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeZoneDetectorStrategyTest.java b/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeZoneDetectorStrategyTest.java
index 62f1433..9e00077 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeZoneDetectorStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeZoneDetectorStrategyTest.java
@@ -28,9 +28,10 @@
 import android.icu.util.Calendar;
 import android.icu.util.GregorianCalendar;
 import android.icu.util.TimeZone;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.TimestampedValue;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
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 ed74cd7..45fef76 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -31,15 +31,16 @@
 import android.app.timedetector.TimeSignal;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.TimestampedValue;
 
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.timedetector.TimeDetectorStrategy.Callback;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import com.android.server.timedetector.TimeDetectorStrategy.Callback;
-
 import java.io.PrintWriter;
 
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyTest.java
index 301ded4..239d413 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyTest.java
@@ -18,9 +18,10 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.runner.AndroidJUnit4;
 import android.util.TimestampedValue;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/services/tests/servicestests/src/com/android/server/timezone/CheckTokenTest.java b/services/tests/servicestests/src/com/android/server/timezone/CheckTokenTest.java
index 9603a06..f7d282b 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/CheckTokenTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/CheckTokenTest.java
@@ -16,16 +16,16 @@
 
 package com.android.server.timezone;
 
-import org.junit.Test;
-
-import android.support.test.filters.SmallTest;
-
-import java.io.IOException;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
 
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.io.IOException;
+
 @SmallTest
 public class CheckTokenTest {
 
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java
index 74013b7..090db11 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java
@@ -16,26 +16,28 @@
 
 package com.android.server.timezone;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
 import static junit.framework.Assert.assertTrue;
+
 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.fail;
 
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
 @SmallTest
 public class PackageStatusStorageTest {
     private static final PackageVersions VALID_PACKAGE_VERSIONS = new PackageVersions(1, 2);
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusTest.java
index c0ae81e..9b45f05 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusTest.java
@@ -16,13 +16,13 @@
 
 package com.android.server.timezone;
 
-import org.junit.Test;
-
-import android.support.test.filters.SmallTest;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
 @SmallTest
 public class PackageStatusTest {
 
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
index d9f4adf..1356ea2 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
@@ -16,27 +16,6 @@
 
 package com.android.server.timezone;
 
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import android.app.timezone.RulesUpdaterContract;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.TimeZoneRulesDataContract;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.time.Clock;
-import java.time.Instant;
-import java.time.ZoneId;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -48,6 +27,28 @@
 import static org.mockito.Mockito.when;
 import static org.mockito.hamcrest.MockitoHamcrest.argThat;
 
+import android.app.timezone.RulesUpdaterContract;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.TimeZoneRulesDataContract;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+
 /**
  * White box interaction / unit testing of the {@link PackageTracker}.
  */
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageVersionsTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageVersionsTest.java
index a470f8f..9ffc4e9 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageVersionsTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageVersionsTest.java
@@ -16,13 +16,13 @@
 
 package com.android.server.timezone;
 
-import org.junit.Test;
-
-import android.support.test.filters.SmallTest;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
 @SmallTest
 public class PackageVersionsTest {
 
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 19d31cf..0936fff 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
@@ -17,8 +17,9 @@
 package com.android.server.timezonedetector;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
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 8461166..869f8fa0 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -37,11 +37,9 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
-
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
@@ -58,12 +56,13 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
 import android.view.Display;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.SystemService;
 
 import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
index 84475bb..047addd 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
@@ -19,13 +19,13 @@
 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 android.app.PendingIntent;
 import android.os.HandlerThread;
 import android.os.Looper;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java b/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java
index da45d81..4eb2474 100644
--- a/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java
@@ -18,14 +18,16 @@
 
 import static com.android.server.utils.PriorityDump.dump;
 
-import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertSame;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Matchers.same;
 import static org.mockito.Mockito.verify;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
+
 import com.android.server.utils.PriorityDump.PriorityDumper;
 
 import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java b/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java
index 9c010a0..2dd8817 100644
--- a/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java
@@ -24,9 +24,10 @@
 import android.os.Message;
 import android.os.SystemClock;
 import android.service.wallpaper.WallpaperService;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
index dca09af..bf89cd0 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -19,15 +19,12 @@
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.Signature;
 import android.os.Build;
 import android.os.Bundle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.util.Base64;
 import android.webkit.UserPackage;
@@ -35,17 +32,18 @@
 import android.webkit.WebViewProviderInfo;
 import android.webkit.WebViewProviderResponse;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-
 import org.mockito.ArgumentMatcher;
-import org.mockito.Mockito;
 import org.mockito.Matchers;
+import org.mockito.Mockito;
 
 import java.lang.Integer;
 import java.util.concurrent.CountDownLatch;
 
-
 /**
  * Tests for WebViewUpdateService
  runtest --path frameworks/base/services/tests/servicestests/ \
diff --git a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java b/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
index 164c80b..b5fe8b1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
@@ -18,27 +18,22 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.mockito.ArgumentMatchers.any;
+
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 
-import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
index be7d781..3053c41 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
@@ -20,13 +20,15 @@
 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index e0645b1..fcd8a39e4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -16,26 +16,28 @@
 
 package com.android.server.wm;
 
-import android.support.test.filters.FlakyTest;
-import org.junit.Test;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.content.res.Configuration.EMPTY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+
 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.fail;
 
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.wm.WindowTestUtils.TestTaskWindowContainerController;
 
+import org.junit.Test;
+
 /**
  * Test class for {@link AppWindowContainerController}.
  *
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
new file mode 100644
index 0000000..e3ab5cf
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.SurfaceControl.Transaction;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import android.view.SurfaceControl;
+
+import com.android.server.wm.WindowTestUtils.TestAppWindowToken;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Animation related tests for the {@link AppWindowToken} class.
+ *
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:com.android.server.wm.AppWindowTokenAnimationTests
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AppWindowTokenAnimationTests extends WindowTestsBase {
+
+    private TestAppWindowToken mToken;
+
+    @Mock
+    private Transaction mTransaction;
+    @Mock
+    private AnimationAdapter mSpec;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+
+        mToken = createTestAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD);
+        mToken.setPendingTransaction(mTransaction);
+    }
+
+    @Test
+    public void clipAfterAnim_boundsLayerIsCreated() throws Exception {
+        mToken.mNeedsAnimationBoundsLayer = true;
+
+        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        verify(mTransaction).reparent(eq(mToken.getSurfaceControl()),
+                eq(mToken.mSurfaceAnimator.mLeash.getHandle()));
+        verify(mTransaction).reparent(eq(mToken.mSurfaceAnimator.mLeash),
+                eq(mToken.mAnimationBoundsLayer.getHandle()));
+    }
+
+    @Test
+    public void clipAfterAnim_boundsLayerIsDestroyed() throws Exception {
+        mToken.mNeedsAnimationBoundsLayer = true;
+        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash;
+        final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer;
+        final ArgumentCaptor<SurfaceAnimator.OnAnimationFinishedCallback> callbackCaptor =
+                ArgumentCaptor.forClass(
+                        SurfaceAnimator.OnAnimationFinishedCallback.class);
+        verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
+
+        callbackCaptor.getValue().onAnimationFinished(mSpec);
+        verify(mTransaction).destroy(eq(leash));
+        verify(mTransaction).destroy(eq(animationBoundsLayer));
+        assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse();
+    }
+
+    @Test
+    public void clipAfterAnimCancelled_boundsLayerIsDestroyed() throws Exception {
+        mToken.mNeedsAnimationBoundsLayer = true;
+        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash;
+        final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer;
+
+        mToken.mSurfaceAnimator.cancelAnimation();
+        verify(mTransaction).destroy(eq(leash));
+        verify(mTransaction).destroy(eq(animationBoundsLayer));
+        assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse();
+    }
+
+    @Test
+    public void clipNoneAnim_boundsLayerIsNotCreated() throws Exception {
+        mToken.mNeedsAnimationBoundsLayer = false;
+
+        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        verify(mTransaction).reparent(eq(mToken.getSurfaceControl()),
+                eq(mToken.mSurfaceAnimator.mLeash.getHandle()));
+        assertThat(mToken.mAnimationBoundsLayer).isNull();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index f6599dc..6d31dfb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -16,16 +16,6 @@
 
 package com.android.server.wm;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.Surface;
-import android.view.WindowManager;
-
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
@@ -38,10 +28,26 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_UNSET;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 /**
  * Tests for the {@link AppWindowToken} class.
  *
@@ -162,6 +168,9 @@
         sWm.mDisplayReady = true;
         sWm.mDisplayEnabled = true;
 
+        final DisplayRotation spiedRotation = spy(mDisplayContent.getDisplayRotation());
+        mDisplayContent.setDisplayRotation(spiedRotation);
+
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
         attrs.setTitle("AppWindow");
@@ -169,20 +178,21 @@
         mToken.addWindow(appWindow);
 
         // Set initial orientation and update.
-        performRotation(Surface.ROTATION_90);
+        performRotation(spiedRotation, Surface.ROTATION_90);
         appWindow.resizeReported = false;
 
         // Update the rotation to perform 180 degree rotation and check that resize was reported.
-        performRotation(Surface.ROTATION_270);
+        performRotation(spiedRotation, Surface.ROTATION_270);
         assertTrue(appWindow.resizeReported);
+
         appWindow.removeImmediately();
     }
 
-    private void performRotation(int rotationToReport) {
-        ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = rotationToReport;
+    private void performRotation(DisplayRotation spiedRotation, int rotationToReport) {
+        doReturn(rotationToReport).when(spiedRotation).rotationForOrientation(anyInt(), anyInt());
         sWm.updateRotation(false, false);
-        // Simulate animator finishing orientation change
-        sWm.mRoot.mOrientationChangeComplete = true;
+        // Prevent the next rotation from being deferred by animation.
+        sWm.mAnimator.setScreenRotationAnimationLocked(mDisplayContent.getDisplayId(), null);
         sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index ff631e7..12be0b3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -21,34 +21,31 @@
 import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
 import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+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.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.wm.BoundsAnimationController.BoundsAnimator;
 import com.android.server.wm.WindowManagerInternal.AppTransitionListener;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-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 com.android.server.wm.BoundsAnimationController.BoundsAnimator;
-
 /**
  * Test class for {@link BoundsAnimationController} to ensure that it sends the right callbacks
  * depending on the various interactions.
@@ -151,11 +148,13 @@
         }
 
         @Override
-        public void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
+        public boolean onAnimationStart(boolean schedulePipModeChangedCallback,
+                boolean forceUpdate) {
             mAwaitingAnimationStart = false;
             mAnimationStarted = true;
             mSchedulePipModeChangedOnStart = schedulePipModeChangedCallback;
             mForcePipModeChangedCallback = forceUpdate;
+            return true;
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/ConfigurationContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/ConfigurationContainerTests.java
index 192e156..2b8214d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ConfigurationContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ConfigurationContainerTests.java
@@ -28,13 +28,16 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
 import static android.content.res.Configuration.EMPTY;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import android.content.res.Configuration;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
index 6769e40..21555e3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
@@ -29,10 +29,11 @@
 
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index ec068db..0d40c5e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -17,6 +17,8 @@
 package com.android.server.wm;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
@@ -28,6 +30,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
 
 import static org.hamcrest.Matchers.is;
@@ -35,28 +38,32 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 import android.annotation.SuppressLint;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.DisplayMetrics;
 import android.util.SparseIntArray;
 import android.view.DisplayCutout;
+import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.Surface;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.wm.utils.WmDisplayCutout;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -349,34 +356,36 @@
      */
     @Test
     public void testMaxUiWidth() throws Exception {
+        // Prevent base display metrics for test from being updated to the value of real display.
+        final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
         final int baseWidth = 1440;
         final int baseHeight = 2560;
         final int baseDensity = 300;
 
-        mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
+        displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
 
         final int maxWidth = 300;
         final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
         final int resultingDensity = (maxWidth * baseDensity) / baseWidth;
 
-        mDisplayContent.setMaxUiWidth(maxWidth);
-        verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
+        displayContent.setMaxUiWidth(maxWidth);
+        verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
 
         // Assert setting values again does not change;
-        mDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
-        verifySizes(mDisplayContent, maxWidth, resultingHeight, resultingDensity);
+        displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
+        verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
 
         final int smallerWidth = 200;
         final int smallerHeight = 400;
         final int smallerDensity = 100;
 
         // Specify smaller dimension, verify that it is honored
-        mDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
-        verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
+        displayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity);
+        verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
 
         // Verify that setting the max width to a greater value than the base width has no effect
-        mDisplayContent.setMaxUiWidth(maxWidth);
-        verifySizes(mDisplayContent, smallerWidth, smallerHeight, smallerDensity);
+        displayContent.setMaxUiWidth(maxWidth);
+        verifySizes(displayContent, smallerWidth, smallerHeight, smallerDensity);
     }
 
     /**
@@ -384,10 +393,12 @@
      */
     @Test
     public void testAlwaysOnTopStackLocation() {
-        final TaskStack alwaysOnTopStack = createTaskStackOnDisplay(mDisplayContent);
+        final TaskStack alwaysOnTopStack = createStackControllerOnStackOnDisplay(
+                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
         final Task task = createTaskInStack(alwaysOnTopStack, 0 /* userId */);
         alwaysOnTopStack.setAlwaysOnTop(true);
-        mDisplayContent.positionStackAt(POSITION_TOP, alwaysOnTopStack);
+        mDisplayContent.positionStackAt(POSITION_TOP, alwaysOnTopStack,
+                false /* includingParents */);
         assertTrue(alwaysOnTopStack.isAlwaysOnTop());
         // Ensure always on top state is synced to the children of the stack.
         assertTrue(alwaysOnTopStack.getTopChild().isAlwaysOnTop());
@@ -398,16 +409,19 @@
         assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
         assertEquals(pinnedStack, mDisplayContent.getTopStack());
 
-        final TaskStack anotherAlwaysOnTopStack = createTaskStackOnDisplay(mDisplayContent);
+        final TaskStack anotherAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
+                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
         anotherAlwaysOnTopStack.setAlwaysOnTop(true);
-        mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack);
+        mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack,
+                false /* includingParents */);
         assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
         int topPosition = mDisplayContent.getStacks().size() - 1;
         // Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
         // existing alwaysOnTop stack.
         assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
 
-        final TaskStack nonAlwaysOnTopStack = createTaskStackOnDisplay(mDisplayContent);
+        final TaskStack nonAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
+                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
         assertEquals(mDisplayContent, nonAlwaysOnTopStack.getDisplayContent());
         topPosition = mDisplayContent.getStacks().size() - 1;
         // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
@@ -415,12 +429,21 @@
         assertEquals(nonAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 3));
 
         anotherAlwaysOnTopStack.setAlwaysOnTop(false);
-        mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack);
+        mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack,
+                false /* includingParents */);
         assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        topPosition = mDisplayContent.getStacks().size() - 1;
         // Ensure, when always on top is turned off for a stack, the stack is put just below all
         // other always on top stacks.
         assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
+        anotherAlwaysOnTopStack.setAlwaysOnTop(true);
+
+        // Ensure always on top state changes properly when windowing mode changes.
+        anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
+        assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
+        anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
+        assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
     }
 
     /**
@@ -463,22 +486,42 @@
     @Test
     public void testDisplayCutout_rot90() throws Exception {
         synchronized (sWm.getWindowManagerLock()) {
-            final DisplayContent dc = createNewDisplay();
-            dc.mInitialDisplayWidth = 200;
-            dc.mInitialDisplayHeight = 400;
-            Rect r1 = new Rect(80, 0, 120, 10);
+            // Prevent mInitialDisplayCutout from being updated from real display (e.g. null
+            // if the device has no cutout).
+            final DisplayContent dc = createDisplayNoUpdateDisplayInfo();
+            // Rotation may use real display info to compute bound, so here also uses the
+            // same width and height.
+            final int displayWidth = dc.mInitialDisplayWidth;
+            final int displayHeight = dc.mInitialDisplayHeight;
+            final int cutoutWidth = 40;
+            final int cutoutHeight = 10;
+            final int left = (displayWidth - cutoutWidth) / 2;
+            final int top = 0;
+            final int right = (displayWidth + cutoutWidth) / 2;
+            final int bottom = cutoutHeight;
+
+            final Rect r1 = new Rect(left, top, right, bottom);
             final DisplayCutout cutout = new WmDisplayCutout(
                     fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom), null)
-                    .computeSafeInsets(200, 400).getDisplayCutout();
+                    .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout();
 
             dc.mInitialDisplayCutout = cutout;
             dc.setRotation(Surface.ROTATION_90);
             dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
 
-            final Rect r = new Rect(0, 80, 10, 120);
+            // ----o----------      -------------
+            // |   |     |   |      |
+            // |   ------o   |      o---
+            // |             |      |  |
+            // |             |  ->  |  |
+            // |             |      ---o
+            // |             |      |
+            // |             |      -------------
+            final Rect r = new Rect(top, left, bottom, right);
             assertEquals(new WmDisplayCutout(
                     fromBoundingRect(r.left, r.top, r.right, r.bottom), null)
-                    .computeSafeInsets(400, 200).getDisplayCutout(), dc.getDisplayInfo().displayCutout);
+                    .computeSafeInsets(displayHeight, displayWidth)
+                    .getDisplayCutout(), dc.getDisplayInfo().displayCutout);
         }
     }
 
@@ -533,6 +576,31 @@
                 .setDisplayInfoOverrideFromWindowManager(dc.getDisplayId(), null);
     }
 
+    @Test
+    public void testGetPreferredOptionsPanelGravityFromDifferentDisplays() {
+        final DisplayContent portraitDisplay = createNewDisplay();
+        portraitDisplay.mInitialDisplayHeight = 2000;
+        portraitDisplay.mInitialDisplayWidth = 1000;
+
+        portraitDisplay.setRotation(Surface.ROTATION_0);
+        assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
+        portraitDisplay.setRotation(Surface.ROTATION_90);
+        assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId()));
+
+        final DisplayContent landscapeDisplay = createNewDisplay();
+        landscapeDisplay.mInitialDisplayHeight = 1000;
+        landscapeDisplay.mInitialDisplayWidth = 2000;
+
+        landscapeDisplay.setRotation(Surface.ROTATION_0);
+        assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
+        landscapeDisplay.setRotation(Surface.ROTATION_90);
+        assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
+    }
+
+    private boolean isOptionsPanelAtRight(int displayId) {
+        return (sWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
+    }
+
     private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
                              int expectedBaseHeight, int expectedBaseDensity) {
         assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
@@ -540,6 +608,16 @@
         assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity);
     }
 
+    /**
+     * Create DisplayContent that does not update display base/initial values from device to keep
+     * the values set by test.
+     */
+    private DisplayContent createDisplayNoUpdateDisplayInfo() {
+        final DisplayContent displayContent = spy(createNewDisplay());
+        doNothing().when(displayContent).updateDisplayInfo();
+        return displayContent;
+    }
+
     private void assertForAllWindowsOrder(List<WindowState> expectedWindowsBottomToTop) {
         final LinkedList<WindowState> actualWindows = new LinkedList<>();
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
new file mode 100644
index 0000000..07eafa5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.server.wm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.app.WindowConfiguration;
+import android.platform.test.annotations.Presubmit;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class DisplaySettingsTests extends WindowTestsBase {
+
+    private File mTestFolder;
+    private DisplaySettings mTarget;
+
+    private DisplayContent mPrimaryDisplay;
+    private DisplayContent mSecondaryDisplay;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mTestFolder = InstrumentationRegistry.getContext().getCacheDir();
+        deleteRecursively(mTestFolder);
+
+        sWm.setSupportsFreeformWindowManagement(false);
+        sWm.setIsPc(false);
+
+        mTarget = new DisplaySettings(sWm, mTestFolder);
+        mTarget.readSettingsLocked();
+
+        mPrimaryDisplay = sWm.getDefaultDisplayContentLocked();
+        mSecondaryDisplay = createNewDisplay();
+        assertNotEquals(Display.DEFAULT_DISPLAY, mSecondaryDisplay.getDisplayId());
+    }
+
+    @Test
+    public void testPrimaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+        mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+                mPrimaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testPrimaryDisplayDefaultToFullscreenWithFreeformSupportNonPc() {
+        sWm.setSupportsFreeformWindowManagement(true);
+
+        mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+                mPrimaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testPrimaryDisplayDefaultToFreeformWithFreeformIsPc() {
+        sWm.setSupportsFreeformWindowManagement(true);
+        sWm.setIsPc(true);
+
+        mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
+                mPrimaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testSecondaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+        mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+                mSecondaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportNonPc() {
+        sWm.setSupportsFreeformWindowManagement(true);
+
+        mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
+                mSecondaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportIsPc() {
+        sWm.setSupportsFreeformWindowManagement(true);
+        sWm.setIsPc(true);
+
+        mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
+                mSecondaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testDefaultToZeroOverscan() {
+        mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        assertOverscan(mPrimaryDisplay, 0 /* left */, 0 /* top */, 0 /* right */, 0 /* bottom */);
+    }
+
+    @Test
+    public void testPersistOverscanInSameInstance() {
+        final DisplayInfo info = mPrimaryDisplay.getDisplayInfo();
+        mTarget.setOverscanLocked(info.uniqueId, info.name, 1 /* left */, 2 /* top */,
+                3 /* right */, 4 /* bottom */);
+
+        mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        assertOverscan(mPrimaryDisplay, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
+    }
+
+    @Test
+    public void testPersistOverscanAcrossInstances() {
+        final DisplayInfo info = mPrimaryDisplay.getDisplayInfo();
+        mTarget.setOverscanLocked(info.uniqueId, info.name, 1 /* left */, 2 /* top */,
+                3 /* right */, 4 /* bottom */);
+        mTarget.writeSettingsLocked();
+
+        DisplaySettings target = new DisplaySettings(sWm, mTestFolder);
+        target.readSettingsLocked();
+
+        target.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        assertOverscan(mPrimaryDisplay, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
+    }
+
+    private static void assertOverscan(DisplayContent display, int left, int top, int right,
+            int bottom) {
+        final DisplayInfo info = display.getDisplayInfo();
+
+        assertEquals(left, info.overscanLeft);
+        assertEquals(top, info.overscanTop);
+        assertEquals(right, info.overscanRight);
+        assertEquals(bottom, info.overscanBottom);
+    }
+
+    private static boolean deleteRecursively(File file) {
+        if (file.isFile()) {
+            return file.delete();
+        }
+
+        boolean fullyDeleted = true;
+        final File[] files = file.listFiles();
+        for (File child : files) {
+            fullyDeleted &= deleteRecursively(child);
+        }
+        fullyDeleted &= file.delete();
+        return fullyDeleted;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
index a09656c..7125246 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
@@ -19,9 +19,11 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
@@ -33,25 +35,29 @@
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.InputChannel;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.View;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.LocalServices;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Tests for the {@link DragDropController} class.
  *
- * atest com.android.server.wm.DragDropControllerTests
+ * atest FrameworksServicesTests:com.android.server.wm.DragDropControllerTests
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -113,7 +119,7 @@
         mTarget = new TestDragDropController(sWm, sWm.mH.getLooper());
         mDisplayContent = spy(mDisplayContent);
         mWindow = createDropTargetWindow("Drag test window", 0);
-        when(mDisplayContent.getTouchableWinAtPointLocked(0, 0)).thenReturn(mWindow);
+        doReturn(mWindow).when(mDisplayContent).getTouchableWinAtPointLocked(0, 0);
         when(sWm.mInputManager.transferTouchFocus(any(), any())).thenReturn(true);
 
         synchronized (sWm.mWindowMap) {
@@ -154,8 +160,7 @@
     public void testPerformDrag_NullDataToOtherUser() throws Exception {
         final WindowState otherUsersWindow =
                 createDropTargetWindow("Other user's window", 1 * UserHandle.PER_USER_RANGE);
-        when(mDisplayContent.getTouchableWinAtPointLocked(10, 10))
-                .thenReturn(otherUsersWindow);
+        doReturn(otherUsersWindow).when(mDisplayContent).getTouchableWinAtPointLocked(10, 10);
 
         dragFlow(0, null, 10, 10);
     }
diff --git a/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java
index 96745fa..7222a99 100644
--- a/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java
@@ -2,18 +2,6 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
-import android.os.RemoteException;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.IPinnedStackListener;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -23,6 +11,19 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.view.IPinnedStackListener;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
 @SmallTest
 @Presubmit
 @RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index a2af9b8..e7c45d5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -19,8 +19,10 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.Display.DEFAULT_DISPLAY;
+
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
+
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeast;
@@ -31,11 +33,14 @@
 import android.os.Binder;
 import android.os.IInterface;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.IRecentsAnimationRunner;
 import android.view.SurfaceControl;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 95361f0..7d19baa 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -31,9 +31,6 @@
 import android.os.Binder;
 import android.os.IInterface;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.IRemoteAnimationFinishedCallback;
 import android.view.IRemoteAnimationRunner;
 import android.view.RemoteAnimationAdapter;
@@ -41,6 +38,9 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.testutils.OffsettableClock;
 import com.android.server.testutils.TestHandler;
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
diff --git a/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java
index 204e26c..c1db6a6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -1,16 +1,16 @@
 package com.android.server.wm;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import static org.junit.Assert.assertTrue;
 
 import android.content.res.Configuration;
 import android.graphics.Rect;
-
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 
-import static org.junit.Assert.assertTrue;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for the {@link RootWindowContainer} class.
diff --git a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
index a2ccee4..60025f0 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
@@ -32,6 +32,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
 import static org.junit.Assert.assertEquals;
 
 import android.app.Activity;
@@ -46,9 +47,6 @@
 import android.media.ImageReader;
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Pair;
 import android.view.Display;
 import android.view.DisplayInfo;
@@ -57,6 +55,10 @@
 import android.view.WindowManager;
 import android.widget.TextView;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -255,16 +257,32 @@
      * Asserts the top inset of {@param activity} is equal to {@param expected} waiting as needed.
      */
     private void assertTopInsetEquals(Activity activity, int expected) throws Exception {
-        waitFor(() -> getInsets(activity).getSystemWindowInsetTop() == expected);
+        waitForTopInsetEqual(activity, expected);
         assertEquals(expected, getInsets(activity).getSystemWindowInsetTop());
     }
 
+    private void waitForTopInsetEqual(Activity activity, int expected) {
+        waitFor(() -> getInsets(activity).getSystemWindowInsetTop() == expected);
+    }
+
     /**
      * Asserts the inset at {@param side} of {@param activity} is equal to {@param expected}
      * waiting as needed.
      */
     private void assertInsetGreaterOrEqual(Activity activity, int side, int expected)
             throws Exception {
+        waitForInsetGreaterOrEqual(activity, side, expected);
+
+        final WindowInsets insets = getInsets(activity);
+        switch (side) {
+            case TOP: assertGreaterOrEqual(insets.getSystemWindowInsetTop(), expected); break;
+            case BOTTOM: assertGreaterOrEqual(insets.getSystemWindowInsetBottom(), expected); break;
+            case LEFT: assertGreaterOrEqual(insets.getSystemWindowInsetLeft(), expected); break;
+            case RIGHT: assertGreaterOrEqual(insets.getSystemWindowInsetRight(), expected); break;
+        }
+    }
+
+    private void waitForInsetGreaterOrEqual(Activity activity, int side, int expected) {
         waitFor(() -> {
             final WindowInsets insets = getInsets(activity);
             switch (side) {
@@ -275,14 +293,6 @@
                 default: return true;
             }
         });
-
-        final WindowInsets insets = getInsets(activity);
-        switch (side) {
-            case TOP: assertGreaterOrEqual(insets.getSystemWindowInsetTop(), expected); break;
-            case BOTTOM: assertGreaterOrEqual(insets.getSystemWindowInsetBottom(), expected); break;
-            case LEFT: assertGreaterOrEqual(insets.getSystemWindowInsetLeft(), expected); break;
-            case RIGHT: assertGreaterOrEqual(insets.getSystemWindowInsetRight(), expected); break;
-        }
     }
 
     /** Asserts that the first entry is greater than or equal to the second entry. */
diff --git a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
index ab0a2bd..9f2645c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
@@ -16,20 +16,20 @@
 
 package com.android.server.wm;
 
-import android.graphics.Rect;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.graphics.Rect;
+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;
+
 /**
  * Test class for {@link StackWindowController}.
  *
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index edac8a5..4551c36 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -16,28 +16,23 @@
 
 package com.android.server.wm;
 
-import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.animation.AnimationHandler;
 import android.animation.AnimationHandler.AnimationFrameCallbackProvider;
 import android.animation.ValueAnimator;
 import android.graphics.Matrix;
 import android.graphics.Point;
+import android.os.PowerManagerInternal;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
 import android.view.Choreographer;
 import android.view.Choreographer.FrameCallback;
 import android.view.SurfaceControl;
@@ -45,8 +40,11 @@
 import android.view.animation.Animation;
 import android.view.animation.TranslateAnimation;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
-import com.android.server.wm.SurfaceAnimationRunner.AnimatorFactory;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -56,6 +54,8 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import java.util.concurrent.CountDownLatch;
 
 /**
@@ -71,6 +71,7 @@
     @Mock SurfaceControl mMockSurface;
     @Mock Transaction mMockTransaction;
     @Mock AnimationSpec mMockAnimationSpec;
+    @Mock PowerManagerInternal mMockPowerManager;
     @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
     private SurfaceAnimationRunner mSurfaceAnimationRunner;
@@ -81,7 +82,7 @@
         super.setUp();
         mFinishCallbackLatch = new CountDownLatch(1);
         mSurfaceAnimationRunner = new SurfaceAnimationRunner(null /* callbackProvider */, null,
-                mMockTransaction);
+                mMockTransaction, mMockPowerManager);
     }
 
     private void finishedCallback() {
@@ -113,7 +114,7 @@
     @Test
     public void testCancel_notStarted() throws Exception {
         mSurfaceAnimationRunner = new SurfaceAnimationRunner(new NoOpFrameCallbackProvider(), null,
-                mMockTransaction);
+                mMockTransaction, mMockPowerManager);
         mSurfaceAnimationRunner
                 .startAnimation(createTranslateAnimation(), mMockSurface, mMockTransaction,
                 this::finishedCallback);
@@ -126,7 +127,7 @@
     @Test
     public void testCancel_running() throws Exception {
         mSurfaceAnimationRunner = new SurfaceAnimationRunner(new NoOpFrameCallbackProvider(), null,
-                mMockTransaction);
+                mMockTransaction, mMockPowerManager);
         mSurfaceAnimationRunner.startAnimation(createTranslateAnimation(), mMockSurface,
                 mMockTransaction, this::finishedCallback);
         waitUntilNextFrame();
@@ -156,7 +157,7 @@
                     listener.onAnimationUpdate(animation);
                 });
             }
-        }, mMockTransaction);
+        }, mMockTransaction, mMockPowerManager);
         when(mMockAnimationSpec.getDuration()).thenReturn(200L);
         mSurfaceAnimationRunner.startAnimation(mMockAnimationSpec, mMockSurface, mMockTransaction,
                 this::finishedCallback);
@@ -184,6 +185,19 @@
         assertFinishCallbackCalled();
     }
 
+    @Test
+    public void testPowerHint() throws Exception {
+        mSurfaceAnimationRunner = new SurfaceAnimationRunner(new NoOpFrameCallbackProvider(), null,
+                mMockTransaction, mMockPowerManager);
+        mSurfaceAnimationRunner.startAnimation(createTranslateAnimation(), mMockSurface,
+                mMockTransaction, this::finishedCallback);
+        waitUntilNextFrame();
+
+        // TODO: For some reason we don't have access to PowerHint definition from the tests. For
+        // now let's just verify that we got some kind of hint.
+        verify(mMockPowerManager).powerHint(anyInt(), anyInt());
+    }
+
     private void waitUntilNextFrame() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         mSurfaceAnimationRunner.mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT,
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 16b8458..7b5e8de 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -28,14 +28,15 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Builder;
 import android.view.SurfaceControl.Transaction;
 import android.view.SurfaceSession;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.wm.SurfaceAnimator.Animatable;
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 
@@ -46,8 +47,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.ArrayList;
-
 /**
  * Test class for {@link SurfaceAnimatorTest}.
  *
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
index dc6bbbf..17b7fc1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
@@ -16,31 +16,32 @@
 
 package com.android.server.wm;
 
-import android.app.IActivityManager;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.app.IActivityTaskManager;
-import android.graphics.Rect;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.Display;
-import org.mockito.Mockito;
-
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
 import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
 import static com.android.server.wm.WindowManagerService.dipToPixel;
 import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
 import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.app.IActivityTaskManager;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
 /**
  * Tests for the {@link TaskPositioner} class.
  *
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
index 6070516..ced0847 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -27,9 +28,11 @@
 import static org.mockito.Mockito.when;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.InputChannel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index 649de4a..c9d8004 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -17,12 +17,14 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 5650050..efce063 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -19,17 +19,19 @@
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.WindowManager.TRANSIT_UNSET;
+
 import static com.android.server.wm.TaskSnapshotController.*;
+
 import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.google.android.collect.Sets;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 325d42a..600b2e5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -18,23 +18,24 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
 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.app.ActivityManager.TaskSnapshot;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
-
 import android.view.View;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.wm.TaskSnapshotPersister.RemoveObsoleteFilesQueueItem;
 
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 8b86043..6f4f173 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -28,7 +28,8 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
+
+import androidx.test.InstrumentationRegistry;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index b19373e..91074b9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
@@ -35,10 +36,11 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.Surface;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.wm.TaskSnapshotSurface.Window;
 
 import org.junit.Test;
@@ -59,7 +61,7 @@
     private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
             int windowFlags, Rect taskBounds) {
         final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888,
-                GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
+                GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER);
         final TaskSnapshot snapshot = new TaskSnapshot(buffer,
                 ORIENTATION_PORTRAIT, contentInsets, false, 1.0f, true /* isRealSnapshot */,
                 WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
index ca1994f..9fa5ba4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -18,20 +18,20 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
 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 android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.Before;
-import org.junit.After;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 
 /**
  * Tests for the {@link DisplayContent.TaskStackContainers} container in {@link DisplayContent}.
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
index eaf71f0..53a1185 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
@@ -16,21 +16,19 @@
 
 package com.android.server.wm;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 
 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 android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for the {@link TaskStack} class.
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index 1dd9365..edd7664 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
@@ -16,17 +16,19 @@
 
 package com.android.server.wm;
 
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+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;
+
 /**
  * Test class for {@link TaskWindowContainerController}.
  *
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index ee028ba..5fb8997 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -19,6 +19,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
 import android.annotation.Nullable;
@@ -30,7 +31,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.proto.ProtoOutputStream;
-import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.IWindow;
 import android.view.IWindowManager;
@@ -72,14 +72,7 @@
 
     }
 
-    @Override
-    public boolean isDefaultOrientationForced() {
-        return false;
-    }
-
-    @Override
-    public void setInitialDisplaySize(Display display, int width, int height, int density) {
-
+    public void setDefaultDisplay(DisplayContentInfo displayContentInfo) {
     }
 
     @Override
@@ -159,9 +152,11 @@
         final WindowManagerService wm = mWmSupplier.get();
         synchronized (wm.mWindowMap) {
             atoken = wm.mRoot.getAppWindowToken(appToken);
+            IWindow iWindow = mock(IWindow.class);
+            doReturn(mock(IBinder.class)).when(iWindow).asBinder();
             window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, atoken,
                     "Starting window", 0 /* ownerId */, false /* internalWindows */, wm,
-                    mock(Session.class), mock(IWindow.class));
+                    mock(Session.class), iWindow);
             atoken.startingWindow = window;
         }
         if (mRunnableWhenAddingSplashScreen != null) {
@@ -386,22 +381,6 @@
     public void onKeyguardOccludedChangedLw(boolean occluded) {
     }
 
-    @Override
-    public int rotationForOrientationLw(int orientation, int lastRotation, boolean defaultDisplay) {
-        return rotationToReport;
-    }
-
-    @Override
-    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
-        return true;
-    }
-
-    @Override
-    public void setRotationLw(int rotation) {
-
-    }
-
-    @Override
     public void setSafeMode(boolean safeMode) {
 
     }
@@ -437,13 +416,8 @@
     }
 
     @Override
-    public void setCurrentOrientationLw(int newOrientation) {
-
-    }
-
-    @Override
     public boolean performHapticFeedbackLw(WindowState win, int effectId,
-            boolean always) {
+            boolean always, String reason) {
         return false;
     }
 
@@ -559,12 +533,13 @@
     }
 
     @Override
-    public void onConfigurationChanged() {
+    public void onConfigurationChanged(DisplayContentInfo displayContentInfo) {
 
     }
 
     @Override
-    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
+    public boolean shouldRotateSeamlessly(DisplayRotation displayRotation, int oldRotation,
+            int newRotation) {
         return false;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index a5c47de..3ac97027 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -19,8 +19,9 @@
 import static junit.framework.Assert.assertTrue;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/WallpaperControllerTests.java
index 71ead20..882e789 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -11,8 +11,9 @@
 import android.graphics.Bitmap;
 import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
index ca520ed..827d938 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -28,12 +28,13 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.SurfaceControl;
 import android.view.animation.Animation;
 import android.view.animation.ClipRectAnimation;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -70,8 +71,6 @@
                 true /* isAppAnimation */);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
-        verify(mTransaction).setFinalCrop(eq(mSurfaceControl),
-                argThat(rect -> rect.equals(mStackBounds)));
     }
 
     @Test
@@ -83,9 +82,6 @@
                 true /* isAppAnimation */);
         windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
         verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
-        verify(mTransaction).setFinalCrop(eq(mSurfaceControl),
-                argThat(rect -> rect.left == 20 && rect.top == 40 && rect.right == 30
-                        && rect.bottom == 50));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
index 10d7aad..e7cc285 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
@@ -16,17 +16,6 @@
 
 package com.android.server.wm;
 
-import org.junit.Test;
-
-import android.app.WindowConfiguration;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.DisplayInfo;
-
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -35,9 +24,21 @@
 import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
 import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE;
 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertTrue;
+
+import android.app.WindowConfiguration;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.DisplayInfo;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
 
 /**
  * Test class to for {@link android.app.WindowConfiguration}.
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
index 502cb6e..6b1feb8 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
@@ -16,21 +16,22 @@
 
 package com.android.server.wm;
 
-import android.app.WindowConfiguration;
-import android.content.res.Configuration;
-import android.support.test.filters.FlakyTest;
-import org.junit.Test;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.content.res.Configuration.EMPTY;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.content.res.Configuration;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+
 /**
  * Test class for {@link WindowContainerController}.
  *
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index f8b2828..dc763b9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -16,20 +16,6 @@
 
 package com.android.server.wm;
 
-import android.support.test.filters.FlakyTest;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import java.util.Comparator;
-
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
@@ -44,7 +30,6 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyFloat;
 import static org.mockito.Mockito.eq;
@@ -53,6 +38,21 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Comparator;
+
 /**
  * Test class for {@link WindowContainer}.
  *
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
index e076399..ffc8622 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -20,19 +20,19 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Matchers.eq;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import org.mockito.Mock;
-
 import java.util.function.Consumer;
 
 /**
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 5a56332..ea3a3d0 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -16,29 +16,31 @@
 
 package com.android.server.wm;
 
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import static android.view.DisplayCutout.fromBoundingRect;
+import static android.view.WindowManager.LayoutParams.FILL_PARENT;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import android.app.ActivityManager.TaskDescription;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IWindow;
 import android.view.WindowManager;
 
-import static android.view.DisplayCutout.fromBoundingRect;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.FILL_PARENT;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.wm.utils.WmDisplayCutout;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 /**
  * Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery.
  *
@@ -51,6 +53,7 @@
 
     private WindowToken mWindowToken;
     private final IWindow mIWindow = new TestIWindow();
+    private final Rect mEmptyRect = new Rect();
 
     class WindowStateWithTask extends WindowState {
         final Task mTask;
@@ -120,13 +123,52 @@
         mStubStack = new TaskStack(sWm, 0, null);
     }
 
-    public void assertRect(Rect rect, int left, int top, int right, int bottom) {
+    // Do not use this function directly in the tests below. Instead, use more explicit function
+    // such as assertFlame().
+    private void assertRect(Rect rect, int left, int top, int right, int bottom) {
         assertEquals(left, rect.left);
         assertEquals(top, rect.top);
         assertEquals(right, rect.right);
         assertEquals(bottom, rect.bottom);
     }
 
+    private void assertContentInset(WindowState w, int left, int top, int right, int bottom) {
+        assertRect(w.mContentInsets, left, top, right, bottom);
+    }
+
+    private void assertVisibleInset(WindowState w, int left, int top, int right, int bottom) {
+        assertRect(w.mVisibleInsets, left, top, right, bottom);
+    }
+
+    private void assertStableInset(WindowState w, int left, int top, int right, int bottom) {
+        assertRect(w.mStableInsets, left, top, right, bottom);
+    }
+
+    private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
+        assertRect(w.getFrameLw(), left, top, right, bottom);
+    }
+
+    private void assertContentFrame(WindowState w, Rect expectedRect) {
+        assertRect(w.getContentFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
+                expectedRect.bottom);
+    }
+
+    private void assertVisibleFrame(WindowState w, Rect expectedRect) {
+        assertRect(w.getVisibleFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
+                expectedRect.bottom);
+    }
+
+    private void assertStableFrame(WindowState w, Rect expectedRect) {
+        assertRect(w.getStableFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
+                expectedRect.bottom);
+    }
+
+    private void assertPolicyCrop(WindowStateWithTask w, int left, int top, int right, int bottom) {
+        Rect policyCrop = new Rect();
+        w.calculatePolicyCrop(policyCrop);
+        assertRect(policyCrop, left, top, right, bottom);
+    }
+
     @Test
     public void testLayoutInFullscreenTaskInsets() throws Exception {
         Task task = new TaskWithBounds(null); // fullscreen task doesn't use bounds for computeFrame
@@ -160,28 +202,28 @@
         // When mFrame extends past cf, the content insets are
         // the difference between mFrame and ContentFrame. Visible
         // and stable frames work the same way.
-        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame,0, 0, 1000, 1000);
-        assertRect(w.mContentInsets, 0, topContentInset, 0, bottomContentInset);
-        assertRect(w.mVisibleInsets, 0, topVisibleInset, 0, bottomVisibleInset);
-        assertRect(w.mStableInsets, leftStableInset, 0, rightStableInset, 0);
-        // The frames remain as passed in shrunk to the window frame
-        assertTrue(cf.equals(w.getContentFrameLw()));
-        assertTrue(vf.equals(w.getVisibleFrameLw()));
-        assertTrue(sf.equals(w.getStableFrameLw()));
-        // On the other hand mFrame doesn't extend past cf we won't get any insets
+        final WindowFrames windowFrames = new WindowFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, 0, 0, 1000, 1000);
+        assertContentInset(w, 0, topContentInset, 0, bottomContentInset);
+        assertVisibleInset(w, 0, topVisibleInset, 0, bottomVisibleInset);
+        assertStableInset(w, leftStableInset, 0, rightStableInset, 0);
+        assertContentFrame(w, cf);
+        assertVisibleFrame(w, vf);
+        assertStableFrame(w, sf);
+        // On the other hand getFrame() doesn't extend past cf we won't get any insets
         w.mAttrs.x = 100;
         w.mAttrs.y = 100;
         w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT
         w.mRequestedWidth = 100;
         w.mRequestedHeight = 100;
-        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, 100, 100, 200, 200);
-        assertRect(w.mContentInsets, 0, 0, 0, 0);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, 100, 100, 200, 200);
+        assertContentInset(w, 0, 0, 0, 0);
         // In this case the frames are shrunk to the window frame.
-        assertTrue(w.mFrame.equals(w.getContentFrameLw()));
-        assertTrue(w.mFrame.equals(w.getVisibleFrameLw()));
-        assertTrue(w.mFrame.equals(w.getStableFrameLw()));
+        assertContentFrame(w, w.getFrameLw());
+        assertVisibleFrame(w, w.getFrameLw());
+        assertStableFrame(w, w.getFrameLw());
     }
 
     @Test
@@ -196,25 +238,26 @@
 
         // Here the window has FILL_PARENT, FILL_PARENT
         // so we expect it to fill the entire available frame.
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, 0, 0, 1000, 1000);
+        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, pf);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, 0, 0, 1000, 1000);
 
         // It can select various widths and heights within the bounds.
         // Strangely the window attribute width is ignored for normal windows
         // and we use mRequestedWidth/mRequestedHeight
         w.mAttrs.width = 300;
         w.mAttrs.height = 300;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
+        w.computeFrameLw(windowFrames);
         // Explicit width and height without requested width/height
         // gets us nothing.
-        assertRect(w.mFrame, 0, 0, 0, 0);
+        assertFrame(w, 0, 0, 0, 0);
 
         w.mRequestedWidth = 300;
         w.mRequestedHeight = 300;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
+        w.computeFrameLw(windowFrames);
         // With requestedWidth/Height we can freely choose our size within the
         // parent bounds.
-        assertRect(w.mFrame, 0, 0, 300, 300);
+        assertFrame(w, 0, 0, 300, 300);
 
         // With FLAG_SCALED though, requestedWidth/height is used to control
         // the unscaled surface size, and mAttrs.width/height becomes the
@@ -224,23 +267,23 @@
         w.mRequestedWidth = -1;
         w.mAttrs.width = 100;
         w.mAttrs.height = 100;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, 0, 0, 100, 100);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, 0, 0, 100, 100);
         w.mAttrs.flags = 0;
 
         // But sizes too large will be clipped to the containing frame
         w.mRequestedWidth = 1200;
         w.mRequestedHeight = 1200;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, 0, 0, 1000, 1000);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, 0, 0, 1000, 1000);
 
         // Before they are clipped though windows will be shifted
         w.mAttrs.x = 300;
         w.mAttrs.y = 300;
         w.mRequestedWidth = 1000;
         w.mRequestedHeight = 1000;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, 0, 0, 1000, 1000);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, 0, 0, 1000, 1000);
 
         // If there is room to move around in the parent frame the window will be shifted according
         // to gravity.
@@ -249,17 +292,17 @@
         w.mRequestedWidth = 300;
         w.mRequestedHeight = 300;
         w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, 700, 0, 1000, 300);
+        w.computeFrameLw(windowFrames);
+         assertFrame(w, 700, 0, 1000, 300);
         w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, 700, 700, 1000, 1000);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, 700, 700, 1000, 1000);
         // Window specified  x and y are interpreted as offsets in the opposite
         // direction of gravity
         w.mAttrs.x = 100;
         w.mAttrs.y = 100;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, 600, 600, 900, 900);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, 600, 600, 900, 900);
     }
 
     @Test
@@ -279,25 +322,27 @@
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, null, WmDisplayCutout.NO_CUTOUT, false);
+        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, mEmptyRect);
+        w.computeFrameLw(windowFrames);
         // For non fullscreen tasks the containing frame is based off the
         // task bounds not the parent frame.
-        assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
-        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
-        assertRect(w.mContentInsets, 0, 0, 0, 0);
+        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
+        assertContentFrame(w, taskBounds);
+        assertContentInset(w, 0, 0, 0, 0);
 
         pf.set(0, 0, logicalWidth, logicalHeight);
         // We still produce insets against the containing frame the same way.
         final int cfRight = logicalWidth / 2;
         final int cfBottom = logicalHeight / 2;
         final Rect cf = new Rect(0, 0, cfRight, cfBottom);
-        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
+        windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
         int contentInsetRight = taskRight - cfRight;
         int contentInsetBottom = taskBottom - cfBottom;
-        assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
-        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
-                taskBottom - contentInsetBottom);
+        assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
+        assertContentFrame(w, new Rect(taskLeft, taskTop, taskRight - contentInsetRight,
+                taskBottom - contentInsetBottom));
 
         pf.set(0, 0, logicalWidth, logicalHeight);
         // However if we set temp inset bounds, the insets will be computed
@@ -308,13 +353,14 @@
         final int insetRight = insetLeft + (taskRight - taskLeft);
         final int insetBottom = insetTop + (taskBottom - taskTop);
         task.mInsetBounds.set(insetLeft, insetTop, insetRight, insetBottom);
-        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, WmDisplayCutout.NO_CUTOUT, false);
-        assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
+        windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
         contentInsetRight = insetRight - cfRight;
         contentInsetBottom = insetBottom - cfBottom;
-        assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
-        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
-                taskBottom - contentInsetBottom);
+        assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
+        assertContentFrame(w, new Rect(taskLeft, taskTop, taskRight - contentInsetRight,
+                taskBottom - contentInsetBottom));
     }
 
     @Test
@@ -336,41 +382,38 @@
         final Rect vf = cf;
         final Rect sf = vf;
         // We use a decor content frame with insets to produce cropping.
-        Rect dcf = cf;
+        Rect dcf = new Rect(cf);
 
-        final Rect policyCrop = new Rect();
+        final WindowFrames windowFrames = new WindowFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
+        w.computeFrameLw(windowFrames);
+        assertPolicyCrop(w, 0, cf.top, logicalWidth, cf.bottom);
 
-        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT, false);
-        w.calculatePolicyCrop(policyCrop);
-        assertRect(policyCrop, 0, cf.top, logicalWidth, cf.bottom);
-
-        dcf.setEmpty();
+        windowFrames.mDecorFrame.setEmpty();
         // Likewise with no decor frame we would get no crop
-        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT, false);
-        w.calculatePolicyCrop(policyCrop);
-        assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);
+        w.computeFrameLw(windowFrames);
+        assertPolicyCrop(w, 0, 0, logicalWidth, logicalHeight);
 
         // Now we set up a window which doesn't fill the entire decor frame.
         // Normally it would be cropped to it's frame but in the case of docked resizing
         // we need to account for the fact the windows surface will be made
         // fullscreen and thus also make the crop fullscreen.
+
+        windowFrames.setFrames(pf, pf, pf, pf, pf, pf, pf, pf);
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
         w.mAttrs.width = logicalWidth / 2;
         w.mAttrs.height = logicalHeight / 2;
         w.mRequestedWidth = logicalWidth / 2;
         w.mRequestedHeight = logicalHeight / 2;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
+        w.computeFrameLw(windowFrames);
 
-        w.calculatePolicyCrop(policyCrop);
         // Normally the crop is shrunk from the decor frame
         // to the computed window frame.
-        assertRect(policyCrop, 0, 0, logicalWidth / 2, logicalHeight / 2);
+        assertPolicyCrop(w, 0, 0, logicalWidth / 2, logicalHeight / 2);
 
         w.mDockedResizingForTest = true;
-        w.calculatePolicyCrop(policyCrop);
         // But if we are docked resizing it won't be, however we will still be
         // shrunk to the decor frame and the display.
-        assertRect(policyCrop, 0, 0,
+        assertPolicyCrop(w, 0, 0,
                 Math.min(pf.width(), displayInfo.logicalWidth),
                 Math.min(pf.height(), displayInfo.logicalHeight));
     }
@@ -394,14 +437,13 @@
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
-        w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
-                pf /* contentFrame */, pf /* visibleFrame */, pf /* decorFrame */,
-                pf /* stableFrame */, null /* outsetFrame */, WmDisplayCutout.NO_CUTOUT, false);
+        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, mEmptyRect);
+        w.computeFrameLw(windowFrames);
         // For non fullscreen tasks the containing frame is based off the
         // task bounds not the parent frame.
-        assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
-        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
-        assertRect(w.mContentInsets, 0, 0, 0, 0);
+        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
+        assertContentFrame(w, taskBounds);
+        assertContentInset(w, 0, 0, 0, 0);
 
         // Now simulate switch to fullscreen for letterboxed app.
         final int xInset = logicalWidth / 10;
@@ -412,13 +454,11 @@
         w.mAppToken.onOverrideConfigurationChanged(config);
         pf.set(0, 0, logicalWidth, logicalHeight);
         task.mFullscreenForTest = true;
-
-        w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
-                cf /* contentFrame */, cf /* visibleFrame */, pf /* decorFrame */,
-                cf /* stableFrame */, null /* outsetFrame */, WmDisplayCutout.NO_CUTOUT, false);
-        assertEquals(cf, w.mFrame);
-        assertEquals(cf, w.getContentFrameLw());
-        assertRect(w.mContentInsets, 0, 0, 0, 0);
+        windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
+        w.computeFrameLw(windowFrames);
+        assertFrame(w, cf.left, cf.top, cf.right, cf.bottom);
+        assertContentFrame(w, cf);
+        assertContentInset(w, 0, 0, 0, 0);
     }
 
     @Test
@@ -433,12 +473,14 @@
         final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
                 fromBoundingRect(500, 0, 550, 50), pf.width(), pf.height());
 
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, cutout, false);
+        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, pf);
+        windowFrames.setDisplayCutout(cutout);
+        w.computeFrameLw(windowFrames);
 
-        assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetTop(), 50);
-        assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetBottom(), 0);
-        assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetLeft(), 0);
-        assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetRight(), 0);
+        assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetTop(), 50);
+        assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetBottom(), 0);
+        assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetLeft(), 0);
+        assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetRight(), 0);
     }
 
     @Test
@@ -455,12 +497,14 @@
         final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
                 fromBoundingRect(500, 0, 550, 50), pf.width(), pf.height());
 
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, cutout, false);
+        final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, pf);
+        windowFrames.setDisplayCutout(cutout);
+        w.computeFrameLw(windowFrames);
 
-        assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetTop(), 50);
-        assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetBottom(), 0);
-        assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetLeft(), 0);
-        assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetRight(), 0);
+        assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetTop(), 50);
+        assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetBottom(), 0);
+        assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetLeft(), 0);
+        assertEquals(w.getWmDisplayCutout().getDisplayCutout().getSafeInsetRight(), 0);
     }
 
     private WindowStateWithTask createWindow(Task task, int width, int height) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
index d13c3c9..6664756 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
@@ -33,9 +33,10 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
-import android.support.test.InstrumentationRegistry;
 import android.view.InputChannel;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.server.LocalServices;
 import com.android.server.input.InputManagerService;
 import com.android.server.policy.WindowManagerPolicy;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
index 6cf6d7b..570a853 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
@@ -20,8 +20,9 @@
 import static org.junit.Assert.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Rule;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 9f113ad..645015f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -16,19 +16,6 @@
 
 package com.android.server.wm;
 
-import android.graphics.Rect;
-import android.view.SurfaceControl;
-import android.view.WindowManager;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import java.util.LinkedList;
-
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
@@ -52,7 +39,6 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
@@ -61,6 +47,20 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.SurfaceControl;
+import android.view.WindowManager;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.LinkedList;
+
 /**
  * Tests for the {@link WindowState} class.
  *
@@ -364,15 +364,15 @@
         app.mSurfaceControl = mock(SurfaceControl.class);
         app.mWinAnimator.mSurfaceController = mock(WindowSurfaceController.class);
         try {
-            app.mFrame.set(10, 20, 60, 80);
+            app.getFrameLw().set(10, 20, 60, 80);
 
             app.seamlesslyRotate(t, ROTATION_0, ROTATION_90);
 
             assertTrue(app.mSeamlesslyRotated);
             assertEquals(new Rect(20, mDisplayInfo.logicalWidth - 60,
-                    80, mDisplayInfo.logicalWidth - 10), app.mFrame);
+                    80, mDisplayInfo.logicalWidth - 10), app.getFrameLw());
 
-            verify(t).setPosition(app.mSurfaceControl, app.mFrame.left, app.mFrame.top);
+            verify(t).setPosition(app.mSurfaceControl, app.getFrameLw().left, app.getFrameLw().top);
             verify(app.mWinAnimator.mSurfaceController).setPosition(t, 0, 50, false);
             verify(app.mWinAnimator.mSurfaceController).setMatrix(t, 0, -1, 1, 0, false);
         } finally {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java
index e173b7d..057f047 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java
@@ -20,13 +20,15 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+
 import static junit.framework.Assert.assertEquals;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.WindowManager;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index 2e4740b..a1b1640 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -22,8 +22,12 @@
 import android.graphics.Rect;
 import android.os.Binder;
 import android.os.IBinder;
+import android.view.Display;
 import android.view.IApplicationToken;
 import android.view.IWindow;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
 import android.view.WindowManager;
 
 import static android.app.AppOpsManager.OP_NONE;
@@ -58,6 +62,37 @@
         return service;
     }
 
+    /** An extension of {@link DisplayContent} to gain package scoped access. */
+    public static class TestDisplayContent extends DisplayContent {
+
+        private TestDisplayContent(Display display, WindowManagerService service,
+                WallpaperController wallpaperController, DisplayWindowController controller) {
+            super(display, service, wallpaperController, controller);
+        }
+
+        /** Create a mocked default {@link DisplayContent}. */
+        public static TestDisplayContent create(Context context) {
+            final TestDisplayContent displayContent = mock(TestDisplayContent.class);
+            displayContent.isDefaultDisplay = true;
+
+            final DisplayPolicy displayPolicy = mock(DisplayPolicy.class);
+            when(displayPolicy.navigationBarCanMove()).thenReturn(true);
+            when(displayPolicy.hasNavigationBar()).thenReturn(true);
+
+            final DisplayRotation displayRotation = new DisplayRotation(
+                    mock(WindowManagerService.class), displayContent, displayPolicy,
+                    context, new Object());
+            displayRotation.mPortraitRotation = Surface.ROTATION_0;
+            displayRotation.mLandscapeRotation = Surface.ROTATION_90;
+            displayRotation.mUpsideDownRotation = Surface.ROTATION_180;
+            displayRotation.mSeascapeRotation = Surface.ROTATION_270;
+
+            when(displayContent.getDisplayRotation()).thenReturn(displayRotation);
+
+            return displayContent;
+        }
+    }
+
     /**
      * Creates a mock instance of {@link StackWindowController}.
      */
@@ -113,6 +148,7 @@
     /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
     public static class TestAppWindowToken extends AppWindowToken {
         boolean mOnTop = false;
+        private Transaction mPendingTransactionOverride;
 
         private TestAppWindowToken(DisplayContent dc) {
             super(dc.mService, new IApplicationToken.Stub() {
@@ -158,6 +194,17 @@
         boolean isOnTop() {
             return mOnTop;
         }
+
+        void setPendingTransaction(Transaction transaction) {
+            mPendingTransactionOverride = transaction;
+        }
+
+        @Override
+        public Transaction getPendingTransaction() {
+            return mPendingTransactionOverride == null
+                    ? super.getPendingTransaction()
+                    : mPendingTransactionOverride;
+        }
     }
 
     static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 473a287..5db0867 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -16,30 +16,12 @@
 
 package com.android.server.wm;
 
+import static android.app.AppOpsManager.OP_NONE;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.View.VISIBLE;
-
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.hardware.display.DisplayManagerGlobal;
-import android.testing.DexmakerShareClassLoaderRule;
-import android.util.Log;
-import android.view.Display;
-import android.view.DisplayInfo;
-import org.junit.Assert;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.view.IWindow;
-import android.view.WindowManager;
-
-import static android.app.AppOpsManager.OP_NONE;
 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+import static android.view.View.VISIBLE;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
@@ -52,10 +34,29 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+
 import static org.mockito.Mockito.mock;
 
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManagerGlobal;
+import android.testing.DexmakerShareClassLoaderRule;
+import android.util.Log;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.IWindow;
+import android.view.WindowManager;
+
+import androidx.test.InstrumentationRegistry;
+
 import com.android.server.AttributeCache;
 
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+
 import java.util.HashSet;
 import java.util.LinkedList;
 
@@ -157,7 +158,11 @@
         // If @After throws an exception, the error isn't logged. This will make sure any failures
         // in the tear down are clear. This can be removed when b/37850063 is fixed.
         try {
-            final LinkedList<WindowState> nonCommonWindows = new LinkedList();
+            // Test may schedule to perform surface placement or other messages. Wait until a
+            // stable state to clean up for consistency.
+            waitUntilHandlersIdle();
+
+            final LinkedList<WindowState> nonCommonWindows = new LinkedList<>();
 
             synchronized (sWm.mWindowMap) {
                 sWm.mRoot.forAllWindows(w -> {
@@ -170,7 +175,12 @@
                     nonCommonWindows.pollLast().removeImmediately();
                 }
 
-                mDisplayContent.removeImmediately();
+                for (int i = sWm.mRoot.mChildren.size() - 1; i >= 0; --i) {
+                    final DisplayContent displayContent = sWm.mRoot.mChildren.get(i);
+                    if (!displayContent.isDefaultDisplay) {
+                        displayContent.removeImmediately();
+                    }
+                }
                 sWm.mInputMethodTarget = null;
                 sWm.mClosingApps.clear();
                 sWm.mOpeningApps.clear();
@@ -231,6 +241,11 @@
     }
 
     AppWindowToken createAppWindowToken(DisplayContent dc, int windowingMode, int activityType) {
+        return createTestAppWindowToken(dc, windowingMode, activityType);
+    }
+
+    WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int
+            windowingMode, int activityType) {
         final TaskStack stack = createStackControllerOnStackOnDisplay(windowingMode, activityType,
                 dc).mContainer;
         final Task task = createTaskInStack(stack, 0 /* userId */);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
index e3b7174..3732486 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -16,23 +16,24 @@
 
 package com.android.server.wm;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+
 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.mock;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for the {@link WindowToken} class.
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
index 5085254..bbc6550 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
@@ -29,12 +29,13 @@
 
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.filters.FlakyTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.proto.ProtoOutputStream;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.Preconditions;
 import com.android.server.wm.WindowManagerTraceProto;
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index 547be55..8f9fb1b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -27,19 +27,19 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.filters.FlakyTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
index 361522c..f82b012 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
@@ -99,7 +99,7 @@
 
         checkPoint(0, W).transformsTo(0, 0);
         checkPoint(H, 0).transformsTo(W, H);
-}
+    }
 
     @Test
     public void transformLogicalToPhysicalCoordinates_rot180() {
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java
index d0f0fe3..3364aef 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java
@@ -16,13 +16,18 @@
 
 package com.android.server.wm.utils;
 
+import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+
 import static junit.framework.Assert.assertEquals;
 
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.Pair;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -39,5 +44,29 @@
         InsetUtils.addInsets(rect1, rect2);
         assertEquals(new Rect(60, 80, 100, 120), rect1);
     }
+
+    @Test
+    public void rotate() {
+        final Rect original = new Rect(1, 2, 3, 4);
+
+        assertEquals("rot0", original, rotateCopy(original, ROTATION_0));
+
+        final Rect rot90 = rotateCopy(original, ROTATION_90);
+        assertEquals("rot90", new Rect(2, 3, 4, 1), rot90);
+
+        final Rect rot180 = rotateCopy(original, ROTATION_180);
+        assertEquals("rot180", new Rect(3, 4, 1, 2), rot180);
+        assertEquals("rot90(rot90)=rot180", rotateCopy(rot90, ROTATION_90), rot180);
+
+        final Rect rot270 = rotateCopy(original, ROTATION_270);
+        assertEquals("rot270", new Rect(4, 1, 2, 3), rot270);
+        assertEquals("rot90(rot180)=rot270", rotateCopy(rot180, ROTATION_90), rot270);
+    }
+
+    private static Rect rotateCopy(Rect insets, int rotationDelta) {
+        final Rect copy = new Rect(insets);
+        InsetUtils.rotateInsets(copy, rotationDelta);
+        return copy;
+    }
 }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/RotationCacheTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/RotationCacheTest.java
index 6bbc7eb..5d08920 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/RotationCacheTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/utils/RotationCacheTest.java
@@ -24,14 +24,12 @@
 import static org.junit.Assert.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Pair;
 
-import com.android.server.wm.utils.RotationCache.RotationDependentComputation;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import org.hamcrest.Matchers;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
index f7addf6..9ce3dca 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
@@ -25,11 +25,12 @@
 
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Size;
 import android.view.DisplayCutout;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
index ae0b0f9..7e7decf 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := androidx-test ub-uiautomator
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_SRC_FILES += ../../src/com/android/server/pm/SuspendPackagesTest.java
diff --git a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
index eec852b..56d3a20 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
@@ -13,14 +13,20 @@
  */
 package com.android.server;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.when;
 
 import android.content.pm.PackageManagerInternal;
+import android.net.Uri;
 import android.os.Build;
 import android.support.test.InstrumentationRegistry;
 import android.testing.TestableContext;
 
+import com.android.server.uri.UriGrantsManagerInternal;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.mockito.Mock;
@@ -28,6 +34,7 @@
 
 public class UiServiceTestCase {
     @Mock protected PackageManagerInternal mPmi;
+    @Mock protected UriGrantsManagerInternal mUgmInternal;
 
     protected static final String PKG_N_MR1 = "com.example.n_mr1";
     protected static final String PKG_O = "com.example.o";
@@ -64,5 +71,10 @@
                             return Build.VERSION_CODES.CUR_DEVELOPMENT;
                     }
                 });
+
+        LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
+        LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
+        when(mUgmInternal.checkGrantUriPermission(
+                anyInt(), anyString(), any(Uri.class), anyInt(), anyInt())).thenReturn(-1);
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 7809999..59eab3f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -19,7 +19,9 @@
 import static android.app.Notification.GROUP_ALERT_CHILDREN;
 import static android.app.Notification.GROUP_ALERT_SUMMARY;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
 
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNull;
@@ -149,6 +151,9 @@
         mService.setFallbackVibrationPattern(FALLBACK_VIBRATION_PATTERN);
         mService.setUsageStats(mUsageStats);
         mService.setAccessibilityManager(accessibilityManager);
+        mService.mScreenOn = false;
+        mService.mInCall = false;
+        mService.mNotificationPulseEnabled = true;
     }
 
     //
@@ -190,6 +195,11 @@
                 true /* noisy */, false /* buzzy*/, false /* lights */);
     }
 
+    private NotificationRecord getInsistentBeepyOnceNotification() {
+        return getNotificationRecord(mId, true /* insistent */, true /* once */,
+                true /* noisy */, false /* buzzy*/, false /* lights */);
+    }
+
     private NotificationRecord getInsistentBeepyLeanbackNotification() {
         return getLeanbackNotificationRecord(mId, true /* insistent */, false /* once */,
                 true /* noisy */, false /* buzzy*/, false /* lights */);
@@ -216,8 +226,13 @@
     }
 
     private NotificationRecord getLightsNotification() {
+        return getNotificationRecord(mId, false /* insistent */, false /* once */,
+                false /* noisy */, false /* buzzy*/, true /* lights */);
+    }
+
+    private NotificationRecord getLightsOnceNotification() {
         return getNotificationRecord(mId, false /* insistent */, true /* once */,
-                false /* noisy */, true /* buzzy*/, true /* lights */);
+                false /* noisy */, false /* buzzy*/, true /* lights */);
     }
 
     private NotificationRecord getCustomLightsNotification() {
@@ -244,6 +259,12 @@
                 groupKey, groupAlertBehavior, false);
     }
 
+    private NotificationRecord getLightsNotificationRecord(String groupKey,
+            int groupAlertBehavior) {
+        return getNotificationRecord(mId, false, false, false, false, true /*lights*/, true, true,
+                true, groupKey, groupAlertBehavior, false);
+    }
+
     private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
             boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration,
             boolean defaultSound, boolean defaultLights, String groupKey, int groupAlertBehavior,
@@ -343,22 +364,23 @@
 
     private void verifyNeverVibrate() {
         verify(mVibrator, never()).vibrate(anyInt(), anyString(), (VibrationEffect) anyObject(),
-                (AudioAttributes) anyObject());
+                anyString(), (AudioAttributes) anyObject());
     }
 
     private void verifyVibrate() {
         verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateOnceMatcher),
-                (AudioAttributes) anyObject());
+                anyString(), (AudioAttributes) anyObject());
     }
 
     private void verifyVibrateLooped() {
         verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateLoopMatcher),
-                (AudioAttributes) anyObject());
+                anyString(), (AudioAttributes) anyObject());
     }
 
     private void verifyDelayedVibrateLooped() {
         verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
-                argThat(mVibrateLoopMatcher), (AudioAttributes) anyObject());
+                argThat(mVibrateLoopMatcher), anyString(),
+                (AudioAttributes) anyObject());
     }
 
     private void verifyStopVibrate() {
@@ -369,6 +391,10 @@
         verify(mVibrator, never()).cancel();
     }
 
+    private void verifyNeverLights() {
+        verify(mLight, never()).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
+    }
+
     private void verifyLights() {
         verify(mLight, times(1)).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
     }
@@ -385,7 +411,7 @@
     @Test
     public void testLights() throws Exception {
         NotificationRecord r = getLightsNotification();
-        r.setImportance(NotificationManager.IMPORTANCE_DEFAULT, "for testing");
+        r.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
 
         mService.buzzBeepBlinkLocked(r);
 
@@ -428,7 +454,7 @@
     @Test
     public void testNoInterruptionForMin() throws Exception {
         NotificationRecord r = getBeepyNotification();
-        r.setImportance(NotificationManager.IMPORTANCE_MIN, "foo");
+        r.setSystemImportance(NotificationManager.IMPORTANCE_MIN);
 
         mService.buzzBeepBlinkLocked(r);
 
@@ -507,6 +533,24 @@
         assertFalse(s.isInterruptive());
     }
 
+    /**
+     * Tests the case where the user re-posts a {@link Notification} with looping sound where
+     * {@link Notification.Builder#setOnlyAlertOnce(true)} has been called.  This should silence
+     * the sound associated with the notification.
+     * @throws Exception
+     */
+    @Test
+    public void testNoisyOnceUpdateDoesCancelAudio() throws Exception {
+        NotificationRecord r = getInsistentBeepyNotification();
+        NotificationRecord s = getInsistentBeepyOnceNotification();
+        s.isUpdate = true;
+
+        mService.buzzBeepBlinkLocked(r);
+        mService.buzzBeepBlinkLocked(s);
+
+        verifyStopAudio();
+    }
+
     @Test
     public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception {
         NotificationRecord r = getBeepyNotification();
@@ -603,7 +647,8 @@
         VibrationEffect effect = VibrationEffect.createWaveform(r.getVibration(), -1);
 
         verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
-                eq(effect), (AudioAttributes) anyObject());
+                eq(effect), anyString(),
+                (AudioAttributes) anyObject());
         assertTrue(r.isInterruptive());
     }
 
@@ -637,7 +682,7 @@
         mService.buzzBeepBlinkLocked(r);
 
         verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
-                eq(FALLBACK_VIBRATION), (AudioAttributes) anyObject());
+                eq(FALLBACK_VIBRATION), anyString(), (AudioAttributes) anyObject());
         verify(mRingtonePlayer, never()).playAsync
                 (anyObject(), anyObject(), anyBoolean(), anyObject());
         assertTrue(r.isInterruptive());
@@ -712,7 +757,8 @@
         mService.buzzBeepBlinkLocked(summary);
 
         verifyBeepLooped();
-        assertTrue(summary.isInterruptive());
+        // summaries are never interruptive for notification counts
+        assertFalse(summary.isInterruptive());
     }
 
     @Test
@@ -969,7 +1015,7 @@
     @Test
     public void testA11yMinInitialPost() throws Exception {
         NotificationRecord r = getQuietNotification();
-        r.setImportance(IMPORTANCE_MIN, "");
+        r.setSystemImportance(IMPORTANCE_MIN);
         mService.buzzBeepBlinkLocked(r);
         verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt());
     }
@@ -990,6 +1036,156 @@
         verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
     }
 
+    @Test
+    public void testLightsScreenOn() {
+        mService.mScreenOn = true;
+        NotificationRecord r = getLightsNotification();
+        mService.buzzBeepBlinkLocked(r);
+        verifyNeverLights();
+        assertFalse(r.isInterruptive());
+    }
+
+    @Test
+    public void testLightsInCall() {
+        mService.mInCall = true;
+        NotificationRecord r = getLightsNotification();
+        mService.buzzBeepBlinkLocked(r);
+        verifyNeverLights();
+        assertFalse(r.isInterruptive());
+    }
+
+    @Test
+    public void testLightsSilentUpdate() {
+        NotificationRecord r = getLightsOnceNotification();
+        mService.buzzBeepBlinkLocked(r);
+        verifyLights();
+        assertTrue(r.isInterruptive());
+
+        r = getLightsOnceNotification();
+        r.isUpdate = true;
+        mService.buzzBeepBlinkLocked(r);
+        // checks that lights happened once, i.e. this new call didn't trigger them again
+        verifyLights();
+        assertFalse(r.isInterruptive());
+    }
+
+    @Test
+    public void testLightsUnimportant() {
+        NotificationRecord r = getLightsNotification();
+        r.setSystemImportance(IMPORTANCE_LOW);
+        mService.buzzBeepBlinkLocked(r);
+        verifyNeverLights();
+        assertFalse(r.isInterruptive());
+    }
+
+    @Test
+    public void testLightsNoLights() {
+        NotificationRecord r = getQuietNotification();
+        mService.buzzBeepBlinkLocked(r);
+        verifyNeverLights();
+        assertFalse(r.isInterruptive());
+    }
+
+    @Test
+    public void testLightsNoLightOnDevice() {
+        mService.mHasLight = false;
+        NotificationRecord r = getLightsNotification();
+        mService.buzzBeepBlinkLocked(r);
+        verifyNeverLights();
+        assertFalse(r.isInterruptive());
+    }
+
+    @Test
+    public void testLightsLightsOffGlobally() {
+        mService.mNotificationPulseEnabled = false;
+        NotificationRecord r = getLightsNotification();
+        mService.buzzBeepBlinkLocked(r);
+        verifyNeverLights();
+        assertFalse(r.isInterruptive());
+    }
+
+    @Test
+    public void testLightsDndIntercepted() {
+        NotificationRecord r = getLightsNotification();
+        r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
+        mService.buzzBeepBlinkLocked(r);
+        verifyNeverLights();
+        assertFalse(r.isInterruptive());
+    }
+
+    @Test
+    public void testGroupAlertSummaryNoLightsChild() {
+        NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
+
+        mService.buzzBeepBlinkLocked(child);
+
+        verifyNeverLights();
+        assertFalse(child.isInterruptive());
+    }
+
+    @Test
+    public void testGroupAlertSummaryLightsSummary() {
+        NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
+        summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
+
+        mService.buzzBeepBlinkLocked(summary);
+
+        verifyLights();
+        // summaries should never count for interruptiveness counts
+        assertFalse(summary.isInterruptive());
+    }
+
+    @Test
+    public void testGroupAlertSummaryLightsNonGroupChild() {
+        NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_SUMMARY);
+
+        mService.buzzBeepBlinkLocked(nonGroup);
+
+        verifyLights();
+        assertTrue(nonGroup.isInterruptive());
+    }
+
+    @Test
+    public void testGroupAlertChildNoLightsSummary() {
+        NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
+        summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
+
+        mService.buzzBeepBlinkLocked(summary);
+
+        verifyNeverLights();
+        assertFalse(summary.isInterruptive());
+    }
+
+    @Test
+    public void testGroupAlertChildLightsChild() {
+        NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
+
+        mService.buzzBeepBlinkLocked(child);
+
+        verifyLights();
+        assertTrue(child.isInterruptive());
+    }
+
+    @Test
+    public void testGroupAlertChildLightsNonGroupSummary() {
+        NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_CHILDREN);
+
+        mService.buzzBeepBlinkLocked(nonGroup);
+
+        verifyLights();
+        assertTrue(nonGroup.isInterruptive());
+    }
+
+    @Test
+    public void testGroupAlertAllLightsGroup() {
+        NotificationRecord group = getLightsNotificationRecord("a", GROUP_ALERT_ALL);
+
+        mService.buzzBeepBlinkLocked(group);
+
+        verifyLights();
+        assertTrue(group.isInterruptive());
+    }
+
     static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
         private final int mRepeatIndex;
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/CriticalNotificationExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/CriticalNotificationExtractorTest.java
new file mode 100644
index 0000000..1409da1
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/CriticalNotificationExtractorTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.testing.TestableContext;
+
+import com.android.server.UiServiceTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class CriticalNotificationExtractorTest extends UiServiceTestCase {
+    @Mock
+    private PackageManager mPackageManagerClient;
+    private TestableContext mContext = spy(getContext());
+    private CriticalNotificationExtractor mExtractor;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext.setMockPackageManager(mPackageManagerClient);
+        mExtractor = new CriticalNotificationExtractor();
+    }
+
+    /** confirm there is no affect on notifcations if the automotive feature flag is not set */
+    @Test
+    public void testExtractCritically_nonsupporting() throws Exception {
+        when(mPackageManagerClient.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
+                .thenReturn(false);
+        mExtractor.initialize(mContext, null);
+
+        assertCriticality(Notification.CATEGORY_CAR_EMERGENCY,
+                CriticalNotificationExtractor.NORMAL);
+
+        assertCriticality(Notification.CATEGORY_CAR_WARNING, CriticalNotificationExtractor.NORMAL);
+
+        assertCriticality(Notification.CATEGORY_CAR_INFORMATION,
+                CriticalNotificationExtractor.NORMAL);
+
+        assertCriticality(Notification.CATEGORY_CALL,
+                CriticalNotificationExtractor.NORMAL);
+    }
+
+    @Test
+    public void testExtractCritically() throws Exception {
+        when(mPackageManagerClient.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
+                .thenReturn(true);
+        mExtractor.initialize(mContext, null);
+
+        assertCriticality(Notification.CATEGORY_CAR_EMERGENCY,
+                CriticalNotificationExtractor.CRITICAL);
+
+        assertCriticality(Notification.CATEGORY_CAR_WARNING,
+                CriticalNotificationExtractor.CRITICAL_LOW);
+
+        assertCriticality(Notification.CATEGORY_CAR_INFORMATION,
+                CriticalNotificationExtractor.NORMAL);
+
+        assertCriticality(Notification.CATEGORY_CALL,
+                CriticalNotificationExtractor.NORMAL);
+    }
+
+    private void assertCriticality(String cat, int criticality) {
+        NotificationRecord info = generateRecord(cat);
+        mExtractor.process(info);
+        assertThat(info.getCriticality(), is(criticality));
+    }
+
+
+    private NotificationRecord generateRecord(String category) {
+        NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
+        final Notification.Builder builder = new Notification.Builder(getContext())
+                .setContentTitle("foo")
+                .setCategory(category)
+                .setSmallIcon(android.R.drawable.sym_def_app_icon);
+        Notification n = builder.build();
+        StatusBarNotification sbn = new StatusBarNotification("", "", 0, "", 0,
+                0, n, UserHandle.ALL, null, System.currentTimeMillis());
+        return new NotificationRecord(getContext(), sbn, channel);
+    }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ImportanceExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ImportanceExtractorTest.java
index 73d5961..abc6e3c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ImportanceExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ImportanceExtractorTest.java
@@ -79,7 +79,7 @@
     //
 
     @Test
-    public void testAppPreferenceChannelNone() throws Exception {
+    public void testAppPreferenceChannelNone() {
         ImportanceExtractor extractor = new ImportanceExtractor();
         extractor.setConfig(mConfig);
 
@@ -93,12 +93,12 @@
 
         extractor.process(r);
 
-        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, r.getUserImportance());
+        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, r.getImportance());
         assertEquals(notificationImportance, r.getImportance());
     }
 
     @Test
-    public void testAppPreferenceChannelPreference() throws Exception {
+    public void testAppPreferenceChannelPreference() {
         ImportanceExtractor extractor = new ImportanceExtractor();
         extractor.setConfig(mConfig);
 
@@ -111,6 +111,6 @@
 
         extractor.process(r);
 
-        assertEquals(r.getUserImportance(), NotificationManager.IMPORTANCE_HIGH);
+        assertEquals(r.getImportance(), NotificationManager.IMPORTANCE_HIGH);
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index d0a656c..95d4a15 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -474,6 +475,59 @@
     }
 
     @Test
+    public void testIsPackageAllowed() {
+        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
+            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
+                    mIpm, approvalLevel);
+            writeExpectedValuesToSettings(approvalLevel);
+            service.migrateToXml();
+
+            verifyExpectedApprovedPackages(service);
+        }
+    }
+
+    @Test
+    public void testUpgradeAppBindsNewServices() throws Exception {
+        // If the primary and secondary lists contain component names, only those components within
+        // the package should be matched
+        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
+                mIpm,
+                ManagedServices.APPROVAL_BY_PACKAGE);
+
+        List<String> packages = new ArrayList<>();
+        packages.add("package");
+        addExpectedServices(service, packages, 0);
+
+        // only 2 components are approved per package
+        mExpectedPrimaryComponentNames.clear();
+        mExpectedPrimaryPackages.clear();
+        mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2");
+        mExpectedSecondaryComponentNames.clear();
+        mExpectedSecondaryPackages.clear();
+
+        loadXml(service);
+
+        // new component expected
+        mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2:package/C3");
+
+        service.onPackagesChanged(false, new String[]{"package"}, new int[]{0});
+
+        // verify the 3 components per package are enabled (bound)
+        verifyExpectedBoundEntries(service, true);
+
+        // verify the last component per package is not enabled/we don't try to bind to it
+        for (String pkg : packages) {
+            ComponentName unapprovedAdditionalComponent =
+                    ComponentName.unflattenFromString(pkg + "/C3");
+            assertFalse(
+                    service.isComponentEnabledForCurrentProfiles(
+                            unapprovedAdditionalComponent));
+            verify(mIpm, never()).getServiceInfo(
+                    eq(unapprovedAdditionalComponent), anyInt(), anyInt());
+        }
+    }
+
+    @Test
     public void testSetPackageOrComponentEnabled() throws Exception {
         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
@@ -640,6 +694,20 @@
         }
     }
 
+    @Test
+    public void testIsSameUser() {
+        IInterface service = mock(IInterface.class);
+        when(service.asBinder()).thenReturn(mock(IBinder.class));
+        ManagedServices services = new TestManagedServices(getContext(), mLock, mUserProfiles,
+                mIpm, APPROVAL_BY_PACKAGE);
+        services.registerService(service, null, 10);
+        ManagedServices.ManagedServiceInfo info = services.checkServiceTokenLocked(service);
+        info.isSystem = true;
+
+        assertFalse(services.isSameUser(service, 0));
+        assertTrue(services.isSameUser(service, 10));
+    }
+
     private void loadXml(ManagedServices service) throws Exception {
         final StringBuffer xml = new StringBuffer();
         xml.append("<" + service.getConfig().xmlTag + ">\n");
@@ -729,7 +797,7 @@
                     if (service.mApprovalLevel == APPROVAL_BY_PACKAGE) {
                         assertTrue(packageOrComponent,
                                 service.isComponentEnabledForPackage(packageOrComponent));
-                        for (int i = 1; i <= 3; i ++) {
+                        for (int i = 1; i <= 3; i++) {
                             ComponentName componentName = ComponentName.unflattenFromString(
                                     packageOrComponent +"/C" + i);
                             assertTrue(service.isComponentEnabledForCurrentProfiles(
@@ -774,6 +842,39 @@
         }
     }
 
+
+    private void verifyExpectedApprovedPackages(ManagedServices service) {
+        verifyExpectedApprovedPackages(service, true);
+        verifyExpectedApprovedPackages(service, false);
+    }
+
+    private void verifyExpectedApprovedPackages(ManagedServices service, boolean primary) {
+        ArrayMap<Integer, String> verifyMap = primary
+                ? mExpectedPrimary.get(service.mApprovalLevel)
+                : mExpectedSecondary.get(service.mApprovalLevel);
+        verifyExpectedApprovedPackages(service, verifyMap);
+    }
+
+    private void verifyExpectedApprovedPackages(ManagedServices service,
+            ArrayMap<Integer, String> verifyMap) {
+        for (int userId : verifyMap.keySet()) {
+            for (String verifyValue : verifyMap.get(userId).split(":")) {
+                if (!TextUtils.isEmpty(verifyValue)) {
+                    ComponentName component = ComponentName.unflattenFromString(verifyValue);
+                    if (component != null ) {
+                        assertTrue("service type " + service.mApprovalLevel + ":"
+                                        + verifyValue + " is not allowed for user " + userId,
+                                service.isPackageAllowed(component.getPackageName(), userId));
+                    } else {
+                        assertTrue("service type " + service.mApprovalLevel + ":"
+                                        + verifyValue + " is not allowed for user " + userId,
+                                service.isPackageAllowed(verifyValue, userId));
+                    }
+                }
+            }
+        }
+    }
+
     private void writeExpectedValuesToSettings(int approvalLevel) {
         for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
             Settings.Secure.putStringForUser(getContext().getContentResolver(), SETTING,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
index fd674f0..f17a30d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
@@ -25,6 +25,9 @@
 
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.service.notification.Adjustment;
@@ -54,6 +57,9 @@
         ArrayList<String> people = new ArrayList<>();
         people.add("you");
         signals.putStringArrayList(Adjustment.KEY_PEOPLE, people);
+        ArrayList<Notification.Action> smartActions = new ArrayList<>();
+        smartActions.add(createAction());
+        signals.putParcelableArrayList(Adjustment.KEY_SMART_ACTIONS, smartActions);
         Adjustment adjustment = new Adjustment("pkg", r.getKey(), signals, "", 0);
         r.addAdjustment(adjustment);
 
@@ -66,6 +72,7 @@
         assertTrue(r.getGroupKey().contains(GroupHelper.AUTOGROUP_KEY));
         assertEquals(people, r.getPeopleOverride());
         assertEquals(snoozeCriteria, r.getSnoozeCriteria());
+        assertEquals(smartActions, r.getSmartActions());
     }
 
     @Test
@@ -114,4 +121,11 @@
                 0, n, UserHandle.ALL, null, System.currentTimeMillis());
        return new NotificationRecord(getContext(), sbn, channel);
     }
+
+    private Notification.Action createAction() {
+        return new Notification.Action.Builder(
+                Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
+                "action",
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
index 7ee0501..b30bb4b3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
@@ -110,7 +110,7 @@
         mRecordMinCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
                 callPkg, 1, "minCall", callUid, callUid, n1,
                 new UserHandle(userId), "", 2000), getDefaultChannel());
-        mRecordMinCall.setUserImportance(NotificationManager.IMPORTANCE_MIN);
+        mRecordMinCall.setSystemImportance(NotificationManager.IMPORTANCE_MIN);
 
         Notification n2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_CALL)
@@ -119,7 +119,7 @@
         mRecordHighCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
                 callPkg, 1, "highcall", callUid, callUid, n2,
                 new UserHandle(userId), "", 1999), getDefaultChannel());
-        mRecordHighCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+        mRecordHighCall.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
 
         Notification n3 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setStyle(new Notification.MediaStyle()
@@ -128,14 +128,14 @@
         mRecordDefaultMedia = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "media", uid2, uid2, n3, new UserHandle(userId),
                 "", 1499), getDefaultChannel());
-        mRecordDefaultMedia.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
+        mRecordDefaultMedia.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
 
         Notification n4 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setStyle(new Notification.MessagingStyle("sender!")).build();
         mRecordInlineReply = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "inlinereply", uid2, uid2, n4, new UserHandle(userId),
                 "", 1599), getDefaultChannel());
-        mRecordInlineReply.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+        mRecordInlineReply.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
         mRecordInlineReply.setPackagePriority(Notification.PRIORITY_MAX);
 
         if (smsPkg != null) {
@@ -144,7 +144,7 @@
             mRecordSms = new NotificationRecord(mContext, new StatusBarNotification(smsPkg,
                     smsPkg, 1, "sms", smsUid, smsUid, n5, new UserHandle(userId),
                     "", 1299), getDefaultChannel());
-            mRecordSms.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
+            mRecordSms.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
         }
 
         Notification n6 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
@@ -152,20 +152,20 @@
                 pkg2, 1, "starred", uid2, uid2, n6, new UserHandle(userId),
                 "", 1259), getDefaultChannel());
         mRecordStarredContact.setContactAffinity(ValidateNotificationPeople.STARRED_CONTACT);
-        mRecordStarredContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
+        mRecordStarredContact.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
 
         Notification n7 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
         mRecordContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "contact", uid2, uid2, n7, new UserHandle(userId),
                 "", 1259), getDefaultChannel());
         mRecordContact.setContactAffinity(ValidateNotificationPeople.VALID_CONTACT);
-        mRecordContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
+        mRecordContact.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
 
         Notification n8 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
         mRecordUrgent = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "urgent", uid2, uid2, n8, new UserHandle(userId),
                 "", 1258), getDefaultChannel());
-        mRecordUrgent.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+        mRecordUrgent.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
 
         Notification n9 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_MESSAGE)
@@ -175,7 +175,7 @@
         mRecordCheater = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "cheater", uid2, uid2, n9, new UserHandle(userId),
                 "", 9258), getDefaultChannel());
-        mRecordCheater.setUserImportance(NotificationManager.IMPORTANCE_LOW);
+        mRecordCheater.setSystemImportance(NotificationManager.IMPORTANCE_LOW);
         mRecordCheater.setPackagePriority(Notification.PRIORITY_MAX);
 
         Notification n10 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
@@ -183,7 +183,7 @@
         mRecordEmail = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "email", uid2, uid2, n10, new UserHandle(userId),
                 "", 1599), getDefaultChannel());
-        mRecordEmail.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+        mRecordEmail.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
 
         Notification n11 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_MESSAGE)
@@ -192,7 +192,7 @@
         mRecordCheaterColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "cheater", uid2, uid2, n11, new UserHandle(userId),
                 "", 9258), getDefaultChannel());
-        mRecordCheaterColorized.setUserImportance(NotificationManager.IMPORTANCE_LOW);
+        mRecordCheaterColorized.setSystemImportance(NotificationManager.IMPORTANCE_LOW);
 
         Notification n12 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_MESSAGE)
@@ -202,7 +202,7 @@
         mNoMediaSessionMedia = new NotificationRecord(mContext, new StatusBarNotification(
                 pkg2, pkg2, 1, "cheater", uid2, uid2, n12, new UserHandle(userId),
                 "", 9258), getDefaultChannel());
-        mNoMediaSessionMedia.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
+        mNoMediaSessionMedia.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
 
         Notification n13 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
@@ -211,7 +211,7 @@
         mRecordColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "colorized", uid2, uid2, n13,
                 new UserHandle(userId), "", 1999), getDefaultChannel());
-        mRecordHighCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+        mRecordHighCall.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
 
         Notification n14 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_CALL)
@@ -221,7 +221,7 @@
         mRecordColorizedCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
                 callPkg, 1, "colorizedCall", callUid, callUid, n14,
                 new UserHandle(userId), "", 1999), getDefaultChannel());
-        mRecordColorizedCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+        mRecordColorizedCall.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
     }
 
     @Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index ef9ba78..f255d49 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -31,11 +31,14 @@
 import static org.mockito.Mockito.when;
 
 import android.app.INotificationManager;
+import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.PendingIntent;
 import android.content.Intent;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.Parcel;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.NotificationRankingUpdate;
@@ -91,6 +94,8 @@
             assertEquals(getShowBadge(i), ranking.canShowBadge());
             assertEquals(getUserSentiment(i), ranking.getUserSentiment());
             assertEquals(getHidden(i), ranking.isSuspended());
+            assertActionsEqual(getSmartActions(key, i), ranking.getSmartActions());
+            assertEquals(getSmartReplies(key, i), ranking.getSmartReplies());
         }
     }
 
@@ -107,6 +112,8 @@
         int[] importance = new int[mKeys.length];
         Bundle userSentiment = new Bundle();
         Bundle mHidden = new Bundle();
+        Bundle smartActions = new Bundle();
+        Bundle smartReplies = new Bundle();
 
         for (int i = 0; i < mKeys.length; i++) {
             String key = mKeys[i];
@@ -124,11 +131,14 @@
             showBadge.putBoolean(key, getShowBadge(i));
             userSentiment.putInt(key, getUserSentiment(i));
             mHidden.putBoolean(key, getHidden(i));
+            smartActions.putParcelableArrayList(key, getSmartActions(key, i));
+            smartReplies.putCharSequenceArrayList(key, getSmartReplies(key, i));
         }
         NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
                 interceptedKeys.toArray(new String[0]), visibilityOverrides,
                 suppressedVisualEffects, importance, explanation, overrideGroupKeys,
-                channels, overridePeople, snoozeCriteria, showBadge, userSentiment, mHidden);
+                channels, overridePeople, snoozeCriteria, showBadge, userSentiment, mHidden,
+                smartActions, smartReplies);
         return update;
     }
 
@@ -196,6 +206,37 @@
         return snooze;
     }
 
+    private ArrayList<Notification.Action> getSmartActions(String key, int index) {
+        ArrayList<Notification.Action> actions = new ArrayList<>();
+        for (int i = 0; i < index; i++) {
+            PendingIntent intent = PendingIntent.getBroadcast(
+                    getContext(),
+                    index /*requestCode*/,
+                    new Intent("ACTION_" + key),
+                    0 /*flags*/);
+            actions.add(new Notification.Action.Builder(null /*icon*/, key, intent).build());
+        }
+        return actions;
+    }
+
+    private ArrayList<CharSequence> getSmartReplies(String key, int index) {
+        ArrayList<CharSequence> choices = new ArrayList<>();
+        for (int i = 0; i < index; i++) {
+            choices.add("choice_" + key + "_" + i);
+        }
+        return choices;
+    }
+
+    private void assertActionsEqual(
+            List<Notification.Action> expecteds, List<Notification.Action> actuals) {
+        assertEquals(expecteds.size(), actuals.size());
+        for (int i = 0; i < expecteds.size(); i++) {
+            Notification.Action expected = expecteds.get(i);
+            Notification.Action actual = actuals.get(i);
+            assertEquals(expected.title, actual.title);
+        }
+    }
+
     public static class TestListenerService extends NotificationListenerService {
         private final IBinder binder = new LocalBinder();
 
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 45a3c41..0ff124e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -36,6 +36,10 @@
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
 import static android.os.Build.VERSION_CODES.O_MR1;
 import static android.os.Build.VERSION_CODES.P;
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_NEGATIVE;
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_NEUTRAL;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -50,7 +54,6 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -69,7 +72,7 @@
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
-import android.app.admin.DeviceAdminInfo;
+import android.app.IUriGrantsManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.usage.UsageStatsManagerInternal;
 import android.companion.ICompanionDeviceManager;
@@ -83,7 +86,6 @@
 import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
 import android.graphics.Color;
-import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Binder;
@@ -96,7 +98,6 @@
 import android.provider.MediaStore;
 import android.provider.Settings.Secure;
 import android.service.notification.Adjustment;
-import android.service.notification.INotificationListener;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationStats;
 import android.service.notification.NotifyingApp;
@@ -109,14 +110,17 @@
 import android.text.Html;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
+import android.util.Log;
 
 import com.android.internal.R;
 import com.android.internal.statusbar.NotificationVisibility;
+import com.android.server.LocalServices;
 import com.android.server.UiServiceTestCase;
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
 import com.android.server.notification.NotificationManagerService.NotificationListeners;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 import org.junit.After;
 import org.junit.Before;
@@ -158,6 +162,7 @@
     private TestableLooper mTestableLooper;
     @Mock
     private RankingHelper mRankingHelper;
+    @Mock private PreferencesHelper mPreferencesHelper;
     AtomicFile mPolicyFile;
     File mFile;
     @Mock
@@ -186,10 +191,15 @@
     IBinder mPermOwner;
     @Mock
     IActivityManager mAm;
+    @Mock
+    IUriGrantsManager mUgm;
+    @Mock
+    UriGrantsManagerInternal mUgmInternal;
 
     // Use a Testable subclass so we can simulate calls from the system without failing.
     private static class TestableNotificationManagerService extends NotificationManagerService {
         int countSystemChecks = 0;
+        boolean isSystemUid = true;
 
         public TestableNotificationManagerService(Context context) {
             super(context);
@@ -198,13 +208,13 @@
         @Override
         protected boolean isCallingUidSystem() {
             countSystemChecks++;
-            return true;
+            return isSystemUid;
         }
 
         @Override
         protected boolean isCallerSystemOrPhone() {
             countSystemChecks++;
-            return true;
+            return isSystemUid;
         }
 
         @Override
@@ -232,6 +242,9 @@
                 Secure.NOTIFICATION_BADGING, 1,
                 UserHandle.getUserHandleForUid(mUid).getIdentifier());
 
+        LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
+        LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
+
         mService = new TestableNotificationManagerService(mContext);
 
         // Use this testable looper.
@@ -250,7 +263,7 @@
         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
-        when(mAm.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
+        when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
 
         // write to a test file; the system file isn't readable from tests
         mFile = new File(mContext.getCacheDir(), "test.xml");
@@ -282,7 +295,7 @@
                     mListeners, mAssistants, mConditionProviders,
                     mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
                     mGroupHelper, mAm, mAppUsageStats,
-                    mock(DevicePolicyManagerInternal.class));
+                    mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal);
         } catch (SecurityException e) {
             if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
                 throw e;
@@ -600,8 +613,8 @@
     @Test
     public void testBlockedNotifications_blockedChannelGroup() throws Exception {
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.isGroupBlocked(anyString(), anyInt(), anyString())).thenReturn(true);
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).thenReturn(true);
 
         NotificationChannel channel = new NotificationChannel("id", "name",
                 NotificationManager.IMPORTANCE_HIGH);
@@ -639,6 +652,98 @@
         assertNull(mService.getNotificationRecord(sbn.getKey()));
     }
 
+    /**
+     * Confirm the system user on automotive devices can use car categories
+     */
+    @Test
+    public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
+                .thenReturn(true);
+        List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
+                Notification.CATEGORY_CAR_WARNING,
+                Notification.CATEGORY_CAR_INFORMATION);
+        int id = 0;
+        for (String category: categories) {
+            final StatusBarNotification sbn =
+                    generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
+            sbn.getNotification().category = category;
+            mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+                    sbn.getId(), sbn.getNotification(), sbn.getUserId());
+        }
+        waitForIdle();
+        assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
+    }
+
+
+    /**
+     * Confirm restricted notification categories only apply to automotive.
+     */
+    @Test
+    public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
+        mService.isSystemUid = false;
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
+                .thenReturn(false);
+        List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
+                Notification.CATEGORY_CAR_WARNING,
+                Notification.CATEGORY_CAR_INFORMATION);
+        int id = 0;
+        for (String category: categories) {
+            final StatusBarNotification sbn =
+                    generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
+            sbn.getNotification().category = category;
+            mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+                    sbn.getId(), sbn.getNotification(), sbn.getUserId());
+        }
+        waitForIdle();
+        assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
+    }
+
+    /**
+     * Confirm if a non-system user tries to use the car categories on a automotive device that
+     * they will get a security exception
+     */
+    @Test
+    public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
+        mService.isSystemUid = false;
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
+                .thenReturn(true);
+        List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
+                Notification.CATEGORY_CAR_WARNING,
+                Notification.CATEGORY_CAR_INFORMATION);
+        for (String category: categories) {
+            final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
+            sbn.getNotification().category = category;
+            try {
+                mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+                        sbn.getId(), sbn.getNotification(), sbn.getUserId());
+                fail("Calls from non system apps should not allow use of restricted categories");
+            } catch (SecurityException e) {
+                // pass
+            }
+        }
+        waitForIdle();
+        assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
+    }
+
+    @Test
+    public void testBlockedNotifications_blockedByAssistant() throws Exception {
+        when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
+
+        NotificationChannel channel = new NotificationChannel("id", "name",
+                NotificationManager.IMPORTANCE_HIGH);
+        NotificationRecord r = generateNotificationRecord(channel);
+        mService.addEnqueuedNotification(r);
+
+        r.setAssistantImportance(IMPORTANCE_NONE);
+
+        NotificationManagerService.PostNotificationRunnable runnable =
+                mService.new PostNotificationRunnable(r.getKey());
+        runnable.run();
+        waitForIdle();
+
+        verify(mUsageStats, never()).registerPostedByApp(any());
+    }
+
     @Test
     public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
@@ -1222,36 +1327,36 @@
     @Test
     public void testTvExtenderChannelOverride_onTv() throws Exception {
         mService.setIsTelevision(true);
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannel(
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannel(
                 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
                         new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
 
         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
                 generateNotificationRecord(null, tv).getNotification(), 0);
-        verify(mRankingHelper, times(1)).getNotificationChannel(
+        verify(mPreferencesHelper, times(1)).getNotificationChannel(
                 anyString(), anyInt(), eq("foo"), anyBoolean());
     }
 
     @Test
     public void testTvExtenderChannelOverride_notOnTv() throws Exception {
         mService.setIsTelevision(false);
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannel(
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannel(
                 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
                 mTestNotificationChannel);
 
         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
                 generateNotificationRecord(null, tv).getNotification(), 0);
-        verify(mRankingHelper, times(1)).getNotificationChannel(
+        verify(mPreferencesHelper, times(1)).getNotificationChannel(
                 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
     }
 
     @Test
     public void testUpdateAppNotifyCreatorBlock() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
 
         mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
@@ -1265,7 +1370,7 @@
 
     @Test
     public void testUpdateAppNotifyCreatorUnblock() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
 
         mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
@@ -1279,8 +1384,8 @@
 
     @Test
     public void testUpdateChannelNotifyCreatorBlock() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
                 .thenReturn(mTestNotificationChannel);
 
@@ -1305,8 +1410,8 @@
         NotificationChannel existingChannel =
                 new NotificationChannel(mTestNotificationChannel.getId(),
                         mTestNotificationChannel.getName(), IMPORTANCE_NONE);
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
                 .thenReturn(existingChannel);
 
@@ -1327,8 +1432,8 @@
         NotificationChannel existingChannel =
                 new NotificationChannel(mTestNotificationChannel.getId(),
                         mTestNotificationChannel.getName(), IMPORTANCE_MAX);
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
                 .thenReturn(existingChannel);
 
@@ -1339,8 +1444,8 @@
     @Test
     public void testUpdateGroupNotifyCreatorBlock() throws Exception {
         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
                 .thenReturn(existing);
 
         NotificationChannelGroup updated = new NotificationChannelGroup("id", "name");
@@ -1362,8 +1467,8 @@
     public void testUpdateGroupNotifyCreatorUnblock() throws Exception {
         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
         existing.setBlocked(true);
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
                 .thenReturn(existing);
 
         mBinderService.updateNotificationChannelGroupForPackage(
@@ -1382,8 +1487,8 @@
     @Test
     public void testUpdateGroupNoNotifyCreatorOtherChanges() throws Exception {
         NotificationChannelGroup existing = new NotificationChannelGroup("id", "name");
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannelGroup(eq(existing.getId()), eq(PKG), anyInt()))
                 .thenReturn(existing);
 
         mBinderService.updateNotificationChannelGroupForPackage(
@@ -1396,12 +1501,12 @@
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
                 .thenReturn(mTestNotificationChannel);
         NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
-        when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+        when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(channel2.getId()), anyBoolean()))
                 .thenReturn(channel2);
 
@@ -1421,7 +1526,7 @@
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
         NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
 
@@ -1441,9 +1546,9 @@
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         mTestNotificationChannel.setLightColor(Color.CYAN);
-        when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+        when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
                 .thenReturn(mTestNotificationChannel);
 
@@ -1459,8 +1564,8 @@
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
                 .thenReturn(mTestNotificationChannel);
         reset(mListeners);
@@ -1476,8 +1581,8 @@
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
-        mService.setRankingHelper(mRankingHelper);
-        when(mRankingHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
                 .thenReturn(ncg);
         reset(mListeners);
         mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
@@ -1488,18 +1593,18 @@
 
     @Test
     public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
-        when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+        when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
                 .thenReturn(mTestNotificationChannel);
 
         mBinderService.updateNotificationChannelFromPrivilegedListener(
                 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
 
-        verify(mRankingHelper, times(1)).updateNotificationChannel(
+        verify(mPreferencesHelper, times(1)).updateNotificationChannel(
                 anyString(), anyInt(), any(), anyBoolean());
 
         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
@@ -1509,7 +1614,7 @@
 
     @Test
     public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         List<String> associations = new ArrayList<>();
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
 
@@ -1521,7 +1626,7 @@
             // pass
         }
 
-        verify(mRankingHelper, never()).updateNotificationChannel(
+        verify(mPreferencesHelper, never()).updateNotificationChannel(
                 anyString(), anyInt(), any(), anyBoolean());
 
         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
@@ -1531,7 +1636,7 @@
 
     @Test
     public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
@@ -1548,7 +1653,7 @@
             // pass
         }
 
-        verify(mRankingHelper, never()).updateNotificationChannel(
+        verify(mPreferencesHelper, never()).updateNotificationChannel(
                 anyString(), anyInt(), any(), anyBoolean());
 
         verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
@@ -1558,7 +1663,7 @@
 
     @Test
     public void testGetNotificationChannelFromPrivilegedListener_success() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
@@ -1566,13 +1671,13 @@
         mBinderService.getNotificationChannelsFromPrivilegedListener(
                 null, PKG, Process.myUserHandle());
 
-        verify(mRankingHelper, times(1)).getNotificationChannels(
+        verify(mPreferencesHelper, times(1)).getNotificationChannels(
                 anyString(), anyInt(), anyBoolean());
     }
 
     @Test
     public void testGetNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         List<String> associations = new ArrayList<>();
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
 
@@ -1584,13 +1689,13 @@
             // pass
         }
 
-        verify(mRankingHelper, never()).getNotificationChannels(
+        verify(mPreferencesHelper, never()).getNotificationChannels(
                 anyString(), anyInt(), anyBoolean());
     }
 
     @Test
     public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
@@ -1606,13 +1711,13 @@
             // pass
         }
 
-        verify(mRankingHelper, never()).getNotificationChannels(
+        verify(mPreferencesHelper, never()).getNotificationChannels(
                 anyString(), anyInt(), anyBoolean());
     }
 
     @Test
     public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
@@ -1620,12 +1725,12 @@
         mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
                 null, PKG, Process.myUserHandle());
 
-        verify(mRankingHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
+        verify(mPreferencesHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
     }
 
     @Test
     public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         List<String> associations = new ArrayList<>();
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
 
@@ -1637,12 +1742,12 @@
             // pass
         }
 
-        verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
+        verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
     }
 
     @Test
     public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         List<String> associations = new ArrayList<>();
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         mListener = mock(ManagedServices.ManagedServiceInfo.class);
@@ -1657,7 +1762,7 @@
             // pass
         }
 
-        verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
+        verify(mPreferencesHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
     }
 
     @Test
@@ -2182,7 +2287,7 @@
 
     @Test
     public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
-        mService.setRankingHelper(mRankingHelper);
+        mService.setPreferencesHelper(mPreferencesHelper);
         NotificationManagerService.WorkerHandler handler = mock(
                 NotificationManagerService.WorkerHandler.class);
         mService.setHandler(handler);
@@ -2378,23 +2483,125 @@
 
         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
-                r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD, nv);
+                r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
+                NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
         waitForIdle();
 
         assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
     }
 
     @Test
+    public void testStats_dismissalSentiment() throws Exception {
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mService.addNotification(r);
+
+        final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
+        mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
+                r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
+                NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
+        waitForIdle();
+
+        assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
+                r.getStats().getDismissalSentiment());
+    }
+
+    @Test
+    public void testApplyAdjustmentMultiUser() throws Exception {
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mService.addNotification(r);
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mService.setHandler(handler);
+
+        when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
+
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_USER_SENTIMENT,
+                USER_SENTIMENT_NEGATIVE);
+        Adjustment adjustment = new Adjustment(
+                r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
+        mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+
+        waitForIdle();
+
+        verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
+    }
+
+    @Test
+    public void testAssistantIBlockingTriggersCancel() throws Exception {
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mService.addNotification(r);
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mService.setHandler(handler);
+
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_IMPORTANCE, IMPORTANCE_NONE);
+        Adjustment adjustment = new Adjustment(
+                r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
+        when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+        mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+
+        waitForIdle();
+
+        verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
+        verify(handler, times(1)).scheduleCancelNotification(any());
+    }
+
+    @Test
+    public void testApplyEnqueuedAdjustmentFromAssistant_singleUser() throws Exception {
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mService.addEnqueuedNotification(r);
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mService.setHandler(handler);
+        when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
+
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_USER_SENTIMENT,
+                USER_SENTIMENT_NEGATIVE);
+        Adjustment adjustment = new Adjustment(
+                r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
+        mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
+
+        assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment());
+    }
+
+    @Test
+    public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mService.addEnqueuedNotification(r);
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mService.setHandler(handler);
+        when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(false);
+
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_USER_SENTIMENT,
+                USER_SENTIMENT_NEGATIVE);
+        Adjustment adjustment = new Adjustment(
+                r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
+        mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
+
+        assertEquals(USER_SENTIMENT_NEUTRAL, r.getUserSentiment());
+
+        waitForIdle();
+
+        verify(handler, timeout(300).times(0)).scheduleSendRankingUpdate();
+    }
+
+    @Test
     public void testUserSentimentChangeTriggersUpdate() throws Exception {
         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         mService.addNotification(r);
         NotificationManagerService.WorkerHandler handler = mock(
                 NotificationManagerService.WorkerHandler.class);
         mService.setHandler(handler);
+        when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
 
         Bundle signals = new Bundle();
         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
-                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+                USER_SENTIMENT_NEGATIVE);
         Adjustment adjustment = new Adjustment(
                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
         mBinderService.applyAdjustmentFromAssistant(null, adjustment);
@@ -2411,10 +2618,11 @@
         NotificationManagerService.WorkerHandler handler = mock(
                 NotificationManagerService.WorkerHandler.class);
         mService.setHandler(handler);
+        when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
 
         Bundle signals = new Bundle();
         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
-                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+                USER_SENTIMENT_NEGATIVE);
         Adjustment adjustment = new Adjustment(
                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
@@ -2431,15 +2639,16 @@
         NotificationManagerService.WorkerHandler handler = mock(
                 NotificationManagerService.WorkerHandler.class);
         mService.setHandler(handler);
+        when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
 
         Bundle signals = new Bundle();
         signals.putInt(Adjustment.KEY_USER_SENTIMENT,
-                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+                USER_SENTIMENT_NEGATIVE);
         Adjustment adjustment = new Adjustment(
                 r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
         mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
 
-        assertEquals(NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE,
+        assertEquals(USER_SENTIMENT_NEGATIVE,
                 r.getUserSentiment());
     }
 
@@ -2577,13 +2786,14 @@
                 PKG, PKG, 0, "tag", mUid, 0, nbA.build(), new UserHandle(mUid), null, 0), c);
 
         // First post means we grant access to both
-        reset(mAm);
-        when(mAm.newUriPermissionOwner(any())).thenReturn(new Binder());
+        reset(mUgm);
+        reset(mUgmInternal);
+        when(mUgmInternal.newUriPermissionOwner(any())).thenReturn(new Binder());
         mService.updateUriPermissions(recordA, null, mContext.getPackageName(),
                 UserHandle.USER_SYSTEM);
-        verify(mAm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
+        verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
-        verify(mAm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
+        verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
                 eq(message2.getDataUri()), anyInt(), anyInt(), anyInt());
 
         Notification.Builder nbB = new Notification.Builder(mContext, c.getId())
@@ -2594,24 +2804,24 @@
                 PKG, 0, "tag", mUid, 0, nbB.build(), new UserHandle(mUid), null, 0), c);
 
         // Update means we drop access to first
-        reset(mAm);
+        reset(mUgmInternal);
         mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
                 UserHandle.USER_SYSTEM);
-        verify(mAm, times(1)).revokeUriPermissionFromOwner(any(), eq(message1.getDataUri()),
-                anyInt(), anyInt());
+        verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
+                eq(message1.getDataUri()), anyInt(), anyInt());
 
         // Update back means we grant access to first again
-        reset(mAm);
+        reset(mUgm);
         mService.updateUriPermissions(recordA, recordB, mContext.getPackageName(),
                 UserHandle.USER_SYSTEM);
-        verify(mAm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
+        verify(mUgm, times(1)).grantUriPermissionFromOwner(any(), anyInt(), any(),
                 eq(message1.getDataUri()), anyInt(), anyInt(), anyInt());
 
         // And update to empty means we drop everything
-        reset(mAm);
+        reset(mUgmInternal);
         mService.updateUriPermissions(null, recordB, mContext.getPackageName(),
                 UserHandle.USER_SYSTEM);
-        verify(mAm, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
+        verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(), eq(null),
                 anyInt(), anyInt());
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index e286991..11b086c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -16,6 +16,9 @@
 package com.android.server.notification;
 
 import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.service.notification.NotificationListenerService.Ranking
         .USER_SENTIMENT_NEGATIVE;
 import static android.service.notification.NotificationListenerService.Ranking
@@ -34,8 +37,6 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
@@ -48,6 +49,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.Color;
+import android.graphics.drawable.Icon;
 import android.media.AudioAttributes;
 import android.metrics.LogMaker;
 import android.net.Uri;
@@ -59,10 +61,11 @@
 import android.service.notification.StatusBarNotification;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Slog;
 
+import com.android.internal.R;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.UiServiceTestCase;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -70,6 +73,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
 import java.util.Objects;
 
 @SmallTest
@@ -305,14 +309,14 @@
 
     @Test
     public void testImportance_locked_preUpgrade() throws Exception {
-        defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        defaultChannel.setImportance(IMPORTANCE_LOW);
         defaultChannel.lockFields(USER_LOCKED_IMPORTANCE);
         StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
                 false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
-        assertEquals(NotificationManager.IMPORTANCE_LOW, record.getImportance());
+        assertEquals(IMPORTANCE_LOW, record.getImportance());
     }
 
     @Test
@@ -646,7 +650,8 @@
     @Test
     public void testCalculateGrantableUris_PappProvided() throws RemoteException {
         IActivityManager am = mock(IActivityManager.class);
-        when(am.checkGrantUriPermission(anyInt(), eq(null), any(),
+        UriGrantsManagerInternal ugm = mock(UriGrantsManagerInternal.class);
+        when(ugm.checkGrantUriPermission(anyInt(), eq(null), any(Uri.class),
                 anyInt(), anyInt())).thenThrow(new SecurityException());
 
         Notification n = mock(Notification.class);
@@ -655,6 +660,7 @@
                 new StatusBarNotification(PKG_P, PKG_P, id1, tag1, uid, uid, n, mUser, null, uid);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         record.mAm = am;
+        record.mUgmInternal = ugm;
 
         try {
             record.calculateGrantableUris();
@@ -667,8 +673,9 @@
     @Test
     public void testCalculateGrantableUris_PuserOverridden() throws RemoteException {
         IActivityManager am = mock(IActivityManager.class);
-        when(am.checkGrantUriPermission(anyInt(), eq(null), any(),
-                anyInt(), anyInt())).thenThrow(SecurityException.class);
+        UriGrantsManagerInternal ugm = mock(UriGrantsManagerInternal.class);
+        when(ugm.checkGrantUriPermission(anyInt(), eq(null), any(Uri.class),
+                anyInt(), anyInt())).thenThrow(new SecurityException());
 
         channel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
         Notification n = mock(Notification.class);
@@ -684,8 +691,9 @@
     @Test
     public void testCalculateGrantableUris_prePappProvided() throws RemoteException {
         IActivityManager am = mock(IActivityManager.class);
-        when(am.checkGrantUriPermission(anyInt(), eq(null), any(),
-                anyInt(), anyInt())).thenThrow(SecurityException.class);
+        UriGrantsManagerInternal ugm = mock(UriGrantsManagerInternal.class);
+        when(ugm.checkGrantUriPermission(anyInt(), eq(null), any(Uri.class),
+                anyInt(), anyInt())).thenThrow(new SecurityException());
 
         Notification n = mock(Notification.class);
         when(n.getChannelId()).thenReturn(channel.getId());
@@ -697,4 +705,89 @@
         record.calculateGrantableUris();
         // should not throw
     }
+
+    @Test
+    public void testSmartActions() {
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertNull(record.getSmartActions());
+
+        ArrayList<Notification.Action> smartActions = new ArrayList<>();
+        smartActions.add(new Notification.Action.Builder(
+                Icon.createWithResource(getContext(), R.drawable.btn_default),
+                "text", null).build());
+        record.setSmartActions(smartActions);
+        assertEquals(smartActions, record.getSmartActions());
+    }
+
+    @Test
+    public void testUpdateNotificationChannel() {
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        assertEquals(channel.getImportance(), record.getImportance());
+
+        record.updateNotificationChannel(
+                new NotificationChannel(channelId, "", channel.getImportance() - 1));
+
+        assertEquals(channel.getImportance() - 1, record.getImportance());
+    }
+
+    @Test
+    public void testCalculateImportance_systemImportance() {
+        channel.setImportance(IMPORTANCE_HIGH);
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        record.setSystemImportance(IMPORTANCE_LOW);
+        assertEquals(IMPORTANCE_LOW, record.getImportance());
+
+        record = new NotificationRecord(mMockContext, sbn, channel);
+        channel.lockFields(USER_LOCKED_IMPORTANCE);
+
+        record.setSystemImportance(IMPORTANCE_LOW);
+        assertEquals(IMPORTANCE_LOW, record.getImportance());
+    }
+
+    @Test
+    public void testCalculateImportance_asstImportance() {
+        channel.setImportance(IMPORTANCE_HIGH);
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        record.setAssistantImportance(IMPORTANCE_LOW);
+        assertEquals(IMPORTANCE_LOW, record.getImportance());
+
+        // assistant ignored if user expressed preference
+        record = new NotificationRecord(mMockContext, sbn, channel);
+        channel.lockFields(USER_LOCKED_IMPORTANCE);
+
+        record.setAssistantImportance(IMPORTANCE_LOW);
+        assertEquals(channel.getImportance(), record.getImportance());
+    }
+
+    @Test
+    public void testCalculateImportance_asstImportanceChannelUpdate() {
+        channel.setImportance(IMPORTANCE_HIGH);
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        record.setAssistantImportance(IMPORTANCE_LOW);
+        assertEquals(IMPORTANCE_LOW, record.getImportance());
+
+        record.updateNotificationChannel(
+                new NotificationChannel(channelId, "", IMPORTANCE_DEFAULT));
+
+        assertEquals(IMPORTANCE_LOW, record.getImportance());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationStatsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationStatsTest.java
index 0a630f4..bae8564 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationStatsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationStatsTest.java
@@ -16,6 +16,8 @@
 package com.android.server.notification;
 
 import static android.service.notification.NotificationStats.DISMISSAL_PEEK;
+import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEGATIVE;
+import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_POSITIVE;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -46,6 +48,7 @@
         assertFalse(stats.hasViewedSettings());
         assertFalse(stats.hasSnoozed());
         assertEquals(NotificationStats.DISMISSAL_NOT_DISMISSED, stats.getDismissalSurface());
+        assertEquals(NotificationStats.DISMISS_SENTIMENT_UNKNOWN, stats.getDismissalSentiment());
     }
 
     @Test
@@ -97,10 +100,19 @@
     }
 
     @Test
+    public void testDismissalSentiment() {
+        NotificationStats stats = new NotificationStats();
+        stats.setDismissalSentiment(DISMISS_SENTIMENT_NEGATIVE);
+        assertEquals(DISMISS_SENTIMENT_NEGATIVE, stats.getDismissalSentiment());
+        assertFalse(stats.hasInteracted());
+    }
+
+    @Test
     public void testWriteToParcel() {
         NotificationStats stats = new NotificationStats();
         stats.setViewedSettings();
         stats.setDismissalSurface(NotificationStats.DISMISSAL_AOD);
+        stats.setDismissalSentiment(NotificationStats.DISMISS_SENTIMENT_POSITIVE);
         Parcel parcel = Parcel.obtain();
         stats.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
new file mode 100644
index 0000000..73adf25
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -0,0 +1,1790 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MAX;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.app.NotificationManager;
+import android.content.ContentProvider;
+import android.content.Context;
+import android.content.IContentProvider;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.media.AudioAttributes;
+import android.net.Uri;
+import android.os.Build;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableContentResolver;
+import android.util.ArrayMap;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.server.UiServiceTestCase;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ThreadLocalRandom;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PreferencesHelperTest extends UiServiceTestCase {
+    private static final int UID_N_MR1 = 0;
+    private static final UserHandle USER = UserHandle.of(0);
+    private static final int UID_O = 1111;
+    private static final String SYSTEM_PKG = "android";
+    private static final int SYSTEM_UID= 1000;
+    private static final UserHandle USER2 = UserHandle.of(10);
+    private static final String TEST_CHANNEL_ID = "test_channel_id";
+    private static final String TEST_AUTHORITY = "test";
+    private static final Uri SOUND_URI =
+            Uri.parse("content://" + TEST_AUTHORITY + "/internal/audio/media/10");
+    private static final Uri CANONICAL_SOUND_URI =
+            Uri.parse("content://" + TEST_AUTHORITY
+                    + "/internal/audio/media/10?title=Test&canonical=1");
+
+    @Mock NotificationUsageStats mUsageStats;
+    @Mock RankingHandler mHandler;
+    @Mock PackageManager mPm;
+    @Mock IContentProvider mTestIContentProvider;
+    @Mock Context mContext;
+    @Mock ZenModeHelper mMockZenModeHelper;
+
+    private NotificationManager.Policy mTestNotificationPolicy;
+
+    private PreferencesHelper mHelper;
+    private AudioAttributes mAudioAttributes;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        UserHandle user = UserHandle.ALL;
+
+        final ApplicationInfo legacy = new ApplicationInfo();
+        legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+        final ApplicationInfo upgrade = new ApplicationInfo();
+        upgrade.targetSdkVersion = Build.VERSION_CODES.O;
+        when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy);
+        when(mPm.getApplicationInfoAsUser(eq(PKG_O), anyInt(), anyInt())).thenReturn(upgrade);
+        when(mPm.getApplicationInfoAsUser(eq(SYSTEM_PKG), anyInt(), anyInt())).thenReturn(upgrade);
+        when(mPm.getPackageUidAsUser(eq(PKG_N_MR1), anyInt())).thenReturn(UID_N_MR1);
+        when(mPm.getPackageUidAsUser(eq(PKG_O), anyInt())).thenReturn(UID_O);
+        when(mPm.getPackageUidAsUser(eq(SYSTEM_PKG), anyInt())).thenReturn(SYSTEM_UID);
+        PackageInfo info = mock(PackageInfo.class);
+        info.signatures = new Signature[] {mock(Signature.class)};
+        when(mPm.getPackageInfoAsUser(eq(SYSTEM_PKG), anyInt(), anyInt())).thenReturn(info);
+        when(mPm.getPackageInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt()))
+                .thenReturn(mock(PackageInfo.class));
+        when(mContext.getResources()).thenReturn(
+                InstrumentationRegistry.getContext().getResources());
+        when(mContext.getContentResolver()).thenReturn(
+                InstrumentationRegistry.getContext().getContentResolver());
+        when(mContext.getPackageManager()).thenReturn(mPm);
+        when(mContext.getApplicationInfo()).thenReturn(legacy);
+        // most tests assume badging is enabled
+        TestableContentResolver contentResolver = getContext().getContentResolver();
+        contentResolver.setFallbackToExisting(false);
+        Secure.putIntForUser(contentResolver,
+                Secure.NOTIFICATION_BADGING, 1, UserHandle.getUserId(UID_N_MR1));
+
+        ContentProvider testContentProvider = mock(ContentProvider.class);
+        when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider);
+        contentResolver.addProvider(TEST_AUTHORITY, testContentProvider);
+
+        when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI)))
+                .thenReturn(CANONICAL_SOUND_URI);
+        when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
+                .thenReturn(CANONICAL_SOUND_URI);
+        when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
+                .thenReturn(SOUND_URI);
+
+        mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
+                NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND);
+        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        resetZenModeHelper();
+
+        mAudioAttributes = new AudioAttributes.Builder()
+                .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+                .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+                .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
+                .build();
+    }
+
+    private NotificationChannel getDefaultChannel() {
+        return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
+                IMPORTANCE_LOW);
+    }
+
+    private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, boolean forBackup,
+            String... channelIds)
+            throws Exception {
+        XmlSerializer serializer = new FastXmlSerializer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+        serializer.startDocument(null, true);
+        mHelper.writeXml(serializer, forBackup);
+        serializer.endDocument();
+        serializer.flush();
+        for (String channelId : channelIds) {
+            mHelper.permanentlyDeleteNotificationChannel(pkg, uid, channelId);
+        }
+        return baos;
+    }
+
+    private void loadStreamXml(ByteArrayOutputStream stream, boolean forRestore) throws Exception {
+        loadByteArrayXml(stream.toByteArray(), forRestore);
+    }
+
+    private void loadByteArrayXml(byte[] byteArray, boolean forRestore) throws Exception {
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(byteArray)), null);
+        parser.nextTag();
+        mHelper.readXml(parser, forRestore);
+    }
+
+    private void compareChannels(NotificationChannel expected, NotificationChannel actual) {
+        assertEquals(expected.getId(), actual.getId());
+        assertEquals(expected.getName(), actual.getName());
+        assertEquals(expected.getDescription(), actual.getDescription());
+        assertEquals(expected.shouldVibrate(), actual.shouldVibrate());
+        assertEquals(expected.shouldShowLights(), actual.shouldShowLights());
+        assertEquals(expected.getImportance(), actual.getImportance());
+        assertEquals(expected.getLockscreenVisibility(), actual.getLockscreenVisibility());
+        assertEquals(expected.getSound(), actual.getSound());
+        assertEquals(expected.canBypassDnd(), actual.canBypassDnd());
+        assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern()));
+        assertEquals(expected.getGroup(), actual.getGroup());
+        assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes());
+        assertEquals(expected.getLightColor(), actual.getLightColor());
+    }
+
+    private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) {
+        assertEquals(expected.getId(), actual.getId());
+        assertEquals(expected.getName(), actual.getName());
+        assertEquals(expected.getDescription(), actual.getDescription());
+        assertEquals(expected.isBlocked(), actual.isBlocked());
+    }
+
+    private NotificationChannel getChannel() {
+        return new NotificationChannel("id", "name", IMPORTANCE_LOW);
+    }
+
+    private NotificationChannel findChannel(List<NotificationChannel> channels, String id) {
+        for (NotificationChannel channel : channels) {
+            if (channel.getId().equals(id)) {
+                return channel;
+            }
+        }
+        return null;
+    }
+
+    private void resetZenModeHelper() {
+        reset(mMockZenModeHelper);
+        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
+    }
+
+    @Test
+    public void testChannelXml() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
+        ncg.setBlocked(true);
+        ncg.setDescription("group desc");
+        NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel2.setDescription("descriptions for all");
+        channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
+        channel2.enableLights(true);
+        channel2.setBypassDnd(true);
+        channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        channel2.enableVibration(true);
+        channel2.setGroup(ncg.getId());
+        channel2.setVibrationPattern(new long[]{100, 67, 145, 156});
+        channel2.setLightColor(Color.BLUE);
+
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false);
+
+        mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true);
+        mHelper.setAppImportanceLocked(PKG_N_MR1, UID_N_MR1);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, channel1.getId(),
+                channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
+        mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_N_MR1}, new int[]{
+                UID_N_MR1});
+
+        loadStreamXml(baos, false);
+
+        assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
+        assertTrue(mHelper.getIsAppImportanceLocked(PKG_N_MR1, UID_N_MR1));
+        assertEquals(channel1, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
+        compareChannels(channel2,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
+
+        List<NotificationChannelGroup> actualGroups =
+                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, false, true).getList();
+        boolean foundNcg = false;
+        for (NotificationChannelGroup actual : actualGroups) {
+            if (ncg.getId().equals(actual.getId())) {
+                foundNcg = true;
+                compareGroups(ncg, actual);
+            } else if (ncg2.getId().equals(actual.getId())) {
+                compareGroups(ncg2, actual);
+            }
+        }
+        assertTrue(foundNcg);
+
+        boolean foundChannel2Group = false;
+        for (NotificationChannelGroup actual : actualGroups) {
+            if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) {
+                foundChannel2Group = true;
+                break;
+            }
+        }
+        assertTrue(foundChannel2Group);
+    }
+
+    @Test
+    public void testChannelXmlForBackup() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
+        NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel2.setDescription("descriptions for all");
+        channel2.setSound(SOUND_URI, mAudioAttributes);
+        channel2.enableLights(true);
+        channel2.setBypassDnd(true);
+        channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        channel2.enableVibration(false);
+        channel2.setGroup(ncg.getId());
+        channel2.setLightColor(Color.BLUE);
+        NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH);
+        channel3.enableVibration(true);
+
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false);
+        mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false);
+
+        mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true);
+
+        mHelper.setImportance(PKG_O, UID_O, IMPORTANCE_NONE);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel1.getId(),
+                channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
+        mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_N_MR1, PKG_O},
+                new int[]{UID_N_MR1, UID_O});
+
+        mHelper.setShowBadge(PKG_O, UID_O, true);
+
+        loadStreamXml(baos, true);
+
+        assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG_O, UID_O));
+        assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
+        assertEquals(channel1, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
+        compareChannels(channel2,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
+        compareChannels(channel3,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId(), false));
+
+        List<NotificationChannelGroup> actualGroups =
+                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, false, true).getList();
+        boolean foundNcg = false;
+        for (NotificationChannelGroup actual : actualGroups) {
+            if (ncg.getId().equals(actual.getId())) {
+                foundNcg = true;
+                compareGroups(ncg, actual);
+            } else if (ncg2.getId().equals(actual.getId())) {
+                compareGroups(ncg2, actual);
+            }
+        }
+        assertTrue(foundNcg);
+
+        boolean foundChannel2Group = false;
+        for (NotificationChannelGroup actual : actualGroups) {
+            if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) {
+                foundChannel2Group = true;
+                break;
+            }
+        }
+        assertTrue(foundChannel2Group);
+    }
+
+    @Test
+    public void testBackupXml_backupCanonicalizedSoundUri() throws Exception {
+        NotificationChannel channel =
+                new NotificationChannel("id", "name", IMPORTANCE_LOW);
+        channel.setSound(SOUND_URI, mAudioAttributes);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel.getId());
+
+        // Testing that in restore we are given the canonical version
+        loadStreamXml(baos, true);
+        verify(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
+    }
+
+    @Test
+    public void testRestoreXml_withExistentCanonicalizedSoundUri() throws Exception {
+        Uri localUri = Uri.parse("content://" + TEST_AUTHORITY + "/local/url");
+        Uri canonicalBasedOnLocal = localUri.buildUpon()
+                .appendQueryParameter("title", "Test")
+                .appendQueryParameter("canonical", "1")
+                .build();
+        when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
+                .thenReturn(canonicalBasedOnLocal);
+        when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
+                .thenReturn(localUri);
+        when(mTestIContentProvider.uncanonicalize(any(), eq(canonicalBasedOnLocal)))
+                .thenReturn(localUri);
+
+        NotificationChannel channel =
+                new NotificationChannel("id", "name", IMPORTANCE_LOW);
+        channel.setSound(SOUND_URI, mAudioAttributes);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel.getId());
+
+        loadStreamXml(baos, true);
+
+        NotificationChannel actualChannel = mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, channel.getId(), false);
+        assertEquals(localUri, actualChannel.getSound());
+    }
+
+    @Test
+    public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception {
+        Thread.sleep(3000);
+        when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
+                .thenReturn(null);
+        when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
+                .thenReturn(null);
+
+        NotificationChannel channel =
+                new NotificationChannel("id", "name", IMPORTANCE_LOW);
+        channel.setSound(SOUND_URI, mAudioAttributes);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel.getId());
+
+        loadStreamXml(baos, true);
+
+        NotificationChannel actualChannel = mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, channel.getId(), false);
+        assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound());
+    }
+
+
+    /**
+     * Although we don't make backups with uncanonicalized uris anymore, we used to, so we have to
+     * handle its restore properly.
+     */
+    @Test
+    public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception {
+        // Not a local uncanonicalized uri, simulating that it fails to exist locally
+        when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI))).thenReturn(null);
+        String id = "id";
+        String backupWithUncanonicalizedSoundUri = "<ranking version=\"1\">\n"
+                + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
+                + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" "
+                + "sound=\"" + SOUND_URI + "\" "
+                + "usage=\"6\" content_type=\"0\" flags=\"1\" show_badge=\"true\" />\n"
+                + "<channel id=\"miscellaneous\" name=\"Uncategorized\" usage=\"5\" "
+                + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+                + "</package>\n"
+                + "</ranking>\n";
+
+        loadByteArrayXml(backupWithUncanonicalizedSoundUri.getBytes(), true);
+
+        NotificationChannel actualChannel = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, id, false);
+        assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound());
+    }
+
+    @Test
+    public void testBackupRestoreXml_withNullSoundUri() throws Exception {
+        NotificationChannel channel =
+                new NotificationChannel("id", "name", IMPORTANCE_LOW);
+        channel.setSound(null, mAudioAttributes);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel.getId());
+
+        loadStreamXml(baos, true);
+
+        NotificationChannel actualChannel = mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, channel.getId(), false);
+        assertEquals(null, actualChannel.getSound());
+    }
+
+    @Test
+    public void testChannelXml_backup() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
+        NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        NotificationChannel channel3 =
+                new NotificationChannel("id3", "name3", IMPORTANCE_LOW);
+        channel3.setGroup(ncg.getId());
+
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false);
+
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId());
+        mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg.getId());
+        assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel1.getId(),
+                channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
+        mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_N_MR1}, new int[]{
+                UID_N_MR1});
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+                null);
+        parser.nextTag();
+        mHelper.readXml(parser, true);
+
+        assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
+        assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId(), false));
+        assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG_N_MR1, UID_N_MR1));
+        //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG_N_MR1, UID_N_MR1));
+        assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
+    }
+
+    @Test
+    public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception {
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false,
+                NotificationChannel.DEFAULT_CHANNEL_ID);
+
+        loadStreamXml(baos, false);
+
+        final NotificationChannel updated = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                NotificationChannel.DEFAULT_CHANNEL_ID, false);
+        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance());
+        assertFalse(updated.canBypassDnd());
+        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, updated.getLockscreenVisibility());
+        assertEquals(0, updated.getUserLockedFields());
+    }
+
+    @Test
+    public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception {
+        final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG_N_MR1,
+                UID_N_MR1,
+                NotificationChannel.DEFAULT_CHANNEL_ID, false);
+        defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false,
+                NotificationChannel.DEFAULT_CHANNEL_ID);
+
+        loadStreamXml(baos, false);
+
+        assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance());
+    }
+
+    @Test
+    public void testChannelXml_upgradeCreateDefaultChannel() throws Exception {
+        final String preupgradeXml = "<ranking version=\"1\">\n"
+                + "<package name=\"" + PKG_N_MR1
+                + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH
+                + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\""
+                + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + UID_N_MR1 + "\" />\n"
+                + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" visibility=\""
+                + Notification.VISIBILITY_PRIVATE + "\" />\n"
+                + "</ranking>";
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
+                null);
+        parser.nextTag();
+        mHelper.readXml(parser, false);
+
+        final NotificationChannel updated1 =
+            mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false);
+        assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance());
+        assertTrue(updated1.canBypassDnd());
+        assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility());
+        assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE
+                | NotificationChannel.USER_LOCKED_PRIORITY
+                | NotificationChannel.USER_LOCKED_VISIBILITY,
+                updated1.getUserLockedFields());
+
+        // No Default Channel created for updated packages
+        assertEquals(null, mHelper.getNotificationChannel(PKG_O, UID_O,
+                NotificationChannel.DEFAULT_CHANNEL_ID, false));
+    }
+
+    @Test
+    public void testChannelXml_upgradeDeletesDefaultChannel() throws Exception {
+        final NotificationChannel defaultChannel = mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false);
+        assertTrue(defaultChannel != null);
+        ByteArrayOutputStream baos =
+                writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, NotificationChannel.DEFAULT_CHANNEL_ID);
+        // Load package at higher sdk.
+        final ApplicationInfo upgraded = new ApplicationInfo();
+        upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
+        when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(upgraded);
+        loadStreamXml(baos, false);
+
+        // Default Channel should be gone.
+        assertEquals(null, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                NotificationChannel.DEFAULT_CHANNEL_ID, false));
+    }
+
+    @Test
+    public void testDeletesDefaultChannelAfterChannelIsCreated() throws Exception {
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false);
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false,
+                NotificationChannel.DEFAULT_CHANNEL_ID, "bananas");
+
+        // Load package at higher sdk.
+        final ApplicationInfo upgraded = new ApplicationInfo();
+        upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
+        when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(upgraded);
+        loadStreamXml(baos, false);
+
+        // Default Channel should be gone.
+        assertEquals(null, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                NotificationChannel.DEFAULT_CHANNEL_ID, false));
+    }
+
+    @Test
+    public void testLoadingOldChannelsDoesNotDeleteNewlyCreatedChannels() throws Exception {
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false,
+                NotificationChannel.DEFAULT_CHANNEL_ID, "bananas");
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false);
+
+        loadStreamXml(baos, false);
+
+        // Should still have the newly created channel that wasn't in the xml.
+        assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "bananas", false) != null);
+    }
+
+    @Test
+    public void testCreateChannel_blocked() throws Exception {
+        mHelper.setImportance(PKG_N_MR1, UID_N_MR1, IMPORTANCE_NONE);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false);
+    }
+
+    @Test
+    public void testCreateChannel_badImportance() throws Exception {
+        try {
+            mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                    new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1),
+                    true, false);
+            fail("Was allowed to create a channel with invalid importance");
+        } catch (IllegalArgumentException e) {
+            // yay
+        }
+        try {
+            mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                    new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED),
+                    true, false);
+            fail("Was allowed to create a channel with invalid importance");
+        } catch (IllegalArgumentException e) {
+            // yay
+        }
+        try {
+            mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                    new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1),
+                    true, false);
+            fail("Was allowed to create a channel with invalid importance");
+        } catch (IllegalArgumentException e) {
+            // yay
+        }
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false);
+    }
+
+
+    @Test
+    public void testUpdate() throws Exception {
+        // no fields locked by user
+        final NotificationChannel channel =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
+        channel.enableLights(true);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false);
+
+        // same id, try to update all fields
+        final NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes);
+        channel2.enableLights(false);
+        channel2.setBypassDnd(false);
+        channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true);
+
+        // all fields should be changed
+        assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false));
+
+        verify(mHandler, times(1)).requestSort();
+    }
+
+    @Test
+    public void testUpdate_preUpgrade_updatesAppFields() throws Exception {
+        mHelper.setImportance(PKG_N_MR1, UID_N_MR1, IMPORTANCE_UNSPECIFIED);
+        assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
+        assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1));
+        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
+                mHelper.getPackageVisibility(PKG_N_MR1, UID_N_MR1));
+        assertFalse(mHelper.getIsAppImportanceLocked(PKG_N_MR1, UID_N_MR1));
+
+        NotificationChannel defaultChannel = mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false);
+
+        defaultChannel.setShowBadge(false);
+        defaultChannel.setImportance(IMPORTANCE_NONE);
+        defaultChannel.setBypassDnd(true);
+        defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+
+        mHelper.setAppImportanceLocked(PKG_N_MR1, UID_N_MR1);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true);
+
+        // ensure app level fields are changed
+        assertFalse(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
+        assertEquals(Notification.PRIORITY_MAX, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1));
+        assertEquals(Notification.VISIBILITY_SECRET, mHelper.getPackageVisibility(PKG_N_MR1,
+                UID_N_MR1));
+        assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG_N_MR1, UID_N_MR1));
+        assertTrue(mHelper.getIsAppImportanceLocked(PKG_N_MR1, UID_N_MR1));
+    }
+
+    @Test
+    public void testUpdate_postUpgrade_noUpdateAppFields() throws Exception {
+        final NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+
+        mHelper.createNotificationChannel(PKG_O, UID_O, channel, false, false);
+        assertTrue(mHelper.canShowBadge(PKG_O, UID_O));
+        assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_O, UID_O));
+        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
+                mHelper.getPackageVisibility(PKG_O, UID_O));
+
+        channel.setShowBadge(false);
+        channel.setImportance(IMPORTANCE_NONE);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+
+        mHelper.updateNotificationChannel(PKG_O, UID_O, channel, true);
+
+        // ensure app level fields are not changed
+        assertTrue(mHelper.canShowBadge(PKG_O, UID_O));
+        assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_O, UID_O));
+        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
+                mHelper.getPackageVisibility(PKG_O, UID_O));
+        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_O,
+                UID_O));
+        assertFalse(mHelper.getIsAppImportanceLocked(PKG_O, UID_O));
+    }
+
+    @Test
+    public void testUpdate_preUpgrade_noUpdateAppFieldsWithMultipleChannels() throws Exception {
+        final NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false);
+        assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
+        assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1));
+        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
+                mHelper.getPackageVisibility(PKG_N_MR1, UID_N_MR1));
+
+        channel.setShowBadge(false);
+        channel.setImportance(IMPORTANCE_NONE);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true);
+
+        NotificationChannel defaultChannel = mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false);
+
+        defaultChannel.setShowBadge(false);
+        defaultChannel.setImportance(IMPORTANCE_NONE);
+        defaultChannel.setBypassDnd(true);
+        defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true);
+
+        // ensure app level fields are not changed
+        assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
+        assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1));
+        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
+                mHelper.getPackageVisibility(PKG_N_MR1, UID_N_MR1));
+        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_N_MR1,
+                UID_N_MR1));
+    }
+
+    @Test
+    public void testGetNotificationChannel_ReturnsNullForUnknownChannel() throws Exception {
+        assertEquals(null, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "garbage", false));
+    }
+
+    @Test
+    public void testCreateChannel_CannotChangeHiddenFields() throws Exception {
+        final NotificationChannel channel =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
+        channel.enableLights(true);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        channel.setShowBadge(true);
+        int lockMask = 0;
+        for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
+            lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
+        }
+        channel.lockFields(lockMask);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+
+        NotificationChannel savedChannel =
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false);
+
+        assertEquals(channel.getName(), savedChannel.getName());
+        assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
+        assertFalse(savedChannel.canBypassDnd());
+        assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
+        assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
+
+        verify(mHandler, never()).requestSort();
+    }
+
+    @Test
+    public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception {
+        final NotificationChannel channel =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
+        channel.enableLights(true);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        channel.setShowBadge(true);
+        int lockMask = 0;
+        for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
+            lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
+        }
+        channel.lockFields(lockMask);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+
+        NotificationChannel savedChannel =
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false);
+
+        assertEquals(channel.getName(), savedChannel.getName());
+        assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
+        assertFalse(savedChannel.canBypassDnd());
+        assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
+        assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
+    }
+
+    @Test
+    public void testClearLockedFields() throws Exception {
+        final NotificationChannel channel = getChannel();
+        mHelper.clearLockedFields(channel);
+        assertEquals(0, channel.getUserLockedFields());
+
+        channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY
+                | NotificationChannel.USER_LOCKED_IMPORTANCE);
+        mHelper.clearLockedFields(channel);
+        assertEquals(0, channel.getUserLockedFields());
+    }
+
+    @Test
+    public void testLockFields_soundAndVibration() throws Exception {
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
+
+        final NotificationChannel update1 = getChannel();
+        update1.setSound(new Uri.Builder().scheme("test").build(),
+                new AudioAttributes.Builder().build());
+        update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true);
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
+                | NotificationChannel.USER_LOCKED_SOUND,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false)
+                        .getUserLockedFields());
+
+        NotificationChannel update2 = getChannel();
+        update2.enableVibration(true);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true);
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
+                        | NotificationChannel.USER_LOCKED_SOUND
+                        | NotificationChannel.USER_LOCKED_VIBRATION,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false)
+                        .getUserLockedFields());
+    }
+
+    @Test
+    public void testLockFields_vibrationAndLights() throws Exception {
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
+
+        final NotificationChannel update1 = getChannel();
+        update1.setVibrationPattern(new long[]{7945, 46 ,246});
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true);
+        assertEquals(NotificationChannel.USER_LOCKED_VIBRATION,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update2 = getChannel();
+        update2.enableLights(true);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true);
+        assertEquals(NotificationChannel.USER_LOCKED_VIBRATION
+                        | NotificationChannel.USER_LOCKED_LIGHTS,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false)
+                        .getUserLockedFields());
+    }
+
+    @Test
+    public void testLockFields_lightsAndImportance() throws Exception {
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
+
+        final NotificationChannel update1 = getChannel();
+        update1.setLightColor(Color.GREEN);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true);
+        assertEquals(NotificationChannel.USER_LOCKED_LIGHTS,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update2 = getChannel();
+        update2.setImportance(IMPORTANCE_DEFAULT);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true);
+        assertEquals(NotificationChannel.USER_LOCKED_LIGHTS
+                        | NotificationChannel.USER_LOCKED_IMPORTANCE,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false)
+                        .getUserLockedFields());
+    }
+
+    @Test
+    public void testLockFields_visibilityAndDndAndBadge() throws Exception {
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
+        assertEquals(0,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel().getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update1 = getChannel();
+        update1.setBypassDnd(true);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true);
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update2 = getChannel();
+        update2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true);
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
+                        | NotificationChannel.USER_LOCKED_VISIBILITY,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update3 = getChannel();
+        update3.setShowBadge(false);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update3, true);
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
+                        | NotificationChannel.USER_LOCKED_VISIBILITY
+                        | NotificationChannel.USER_LOCKED_SHOW_BADGE,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update3.getId(), false)
+                        .getUserLockedFields());
+    }
+
+    @Test
+    public void testDeleteNonExistentChannel() throws Exception {
+        mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, "does not exist");
+    }
+
+    @Test
+    public void testGetDeletedChannel() throws Exception {
+        NotificationChannel channel = getChannel();
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
+        channel.enableLights(true);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        channel.enableVibration(true);
+        channel.setVibrationPattern(new long[]{100, 67, 145, 156});
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId());
+
+        // Does not return deleted channel
+        NotificationChannel response =
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false);
+        assertNull(response);
+
+        // Returns deleted channel
+        response = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), true);
+        compareChannels(channel, response);
+        assertTrue(response.isDeleted());
+    }
+
+    @Test
+    public void testGetDeletedChannels() throws Exception {
+        Map<String, NotificationChannel> channelMap = new HashMap<>();
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
+        channel.enableLights(true);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
+        channel.enableVibration(true);
+        channel.setVibrationPattern(new long[]{100, 67, 145, 156});
+        channelMap.put(channel.getId(), channel);
+        NotificationChannel channel2 =
+                new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
+        channelMap.put(channel2.getId(), channel2);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false);
+
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId());
+
+        // Returns only non-deleted channels
+        List<NotificationChannel> channels =
+                mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList();
+        assertEquals(2, channels.size());   // Default channel + non-deleted channel
+        for (NotificationChannel nc : channels) {
+            if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
+                compareChannels(channel2, nc);
+            }
+        }
+
+        // Returns deleted channels too
+        channels = mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList();
+        assertEquals(3, channels.size());               // Includes default channel
+        for (NotificationChannel nc : channels) {
+            if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
+                compareChannels(channelMap.get(nc.getId()), nc);
+            }
+        }
+    }
+
+    @Test
+    public void testGetDeletedChannelCount() throws Exception {
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        NotificationChannel channel2 =
+                new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel3 =
+                new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_HIGH);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false);
+
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId());
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId());
+
+        assertEquals(2, mHelper.getDeletedChannelCount(PKG_N_MR1, UID_N_MR1));
+        assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID_O));
+    }
+
+    @Test
+    public void testGetBlockedChannelCount() throws Exception {
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        NotificationChannel channel2 =
+                new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_NONE);
+        NotificationChannel channel3 =
+                new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_NONE);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false);
+
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId());
+
+        assertEquals(1, mHelper.getBlockedChannelCount(PKG_N_MR1, UID_N_MR1));
+        assertEquals(0, mHelper.getBlockedChannelCount("pkg2", UID_O));
+    }
+
+    @Test
+    public void testCreateAndDeleteCanChannelsBypassDnd() throws Exception {
+        // create notification channel that can't bypass dnd
+        // expected result: areChannelsBypassingDnd = false
+        // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false
+        NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
+        resetZenModeHelper();
+
+        // create notification channel that can bypass dnd
+        // expected result: areChannelsBypassingDnd = true
+        NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel2.setBypassDnd(true);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, true);
+        assertTrue(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
+
+        // delete channels
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId());
+        assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
+        resetZenModeHelper();
+
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId());
+        assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
+    }
+
+    @Test
+    public void testUpdateCanChannelsBypassDnd() throws Exception {
+        // create notification channel that can't bypass dnd
+        // expected result: areChannelsBypassingDnd = false
+        // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false
+        NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
+        resetZenModeHelper();
+
+        // update channel so it CAN bypass dnd:
+        // expected result: areChannelsBypassingDnd = true
+        channel.setBypassDnd(true);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true);
+        assertTrue(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
+
+        // update channel so it can't bypass dnd:
+        // expected result: areChannelsBypassingDnd = false
+        channel.setBypassDnd(false);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true);
+        assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
+    }
+
+    @Test
+    public void testSetupNewZenModeHelper_canBypass() {
+        // start notification policy off with mAreChannelsBypassingDnd = true, but
+        // RankingHelper should change to false
+        mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
+                NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND);
+        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
+    }
+
+    @Test
+    public void testSetupNewZenModeHelper_cannotBypass() {
+        // start notification policy off with mAreChannelsBypassingDnd = false
+        mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0);
+        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
+        resetZenModeHelper();
+    }
+
+    @Test
+    public void testCreateDeletedChannel() throws Exception {
+        long[] vibration = new long[]{100, 67, 145, 156};
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel.setVibrationPattern(vibration);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId());
+
+        NotificationChannel newChannel = new NotificationChannel(
+                channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
+        newChannel.setVibrationPattern(new long[]{100});
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel, true, false);
+
+        // No long deleted, using old settings
+        compareChannels(channel,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel.getId(), false));
+    }
+
+    @Test
+    public void testOnlyHasDefaultChannel() throws Exception {
+        assertTrue(mHelper.onlyHasDefaultChannel(PKG_N_MR1, UID_N_MR1));
+        assertFalse(mHelper.onlyHasDefaultChannel(PKG_O, UID_O));
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
+        assertFalse(mHelper.onlyHasDefaultChannel(PKG_N_MR1, UID_N_MR1));
+    }
+
+    @Test
+    public void testCreateChannel_defaultChannelId() throws Exception {
+        try {
+            mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel(
+                    NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true, false);
+            fail("Allowed to create default channel");
+        } catch (IllegalArgumentException e) {
+            // pass
+        }
+    }
+
+    @Test
+    public void testCreateChannel_alreadyExists() throws Exception {
+        long[] vibration = new long[]{100, 67, 145, 156};
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel.setVibrationPattern(vibration);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+
+        NotificationChannel newChannel = new NotificationChannel(
+                channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
+        newChannel.setVibrationPattern(new long[]{100});
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel, true, false);
+
+        // Old settings not overridden
+        compareChannels(channel,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel.getId(), false));
+    }
+
+    @Test
+    public void testCreateChannel_noOverrideSound() throws Exception {
+        Uri sound = new Uri.Builder().scheme("test").build();
+        final NotificationChannel channel = new NotificationChannel("id2", "name2",
+                 NotificationManager.IMPORTANCE_DEFAULT);
+        channel.setSound(sound, mAudioAttributes);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+        assertEquals(sound, mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, channel.getId(), false).getSound());
+    }
+
+    @Test
+    public void testPermanentlyDeleteChannels() throws Exception {
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false);
+
+        mHelper.permanentlyDeleteNotificationChannels(PKG_N_MR1, UID_N_MR1);
+
+        // Only default channel remains
+        assertEquals(1, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList().size());
+    }
+
+    @Test
+    public void testDeleteGroup() throws Exception {
+        NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted");
+        NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted");
+        NotificationChannel nonGroupedNonDeletedChannel =
+                new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH);
+        NotificationChannel groupedButNotDeleted =
+                new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT);
+        groupedButNotDeleted.setGroup("not");
+        NotificationChannel groupedAndDeleted =
+                new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT);
+        groupedAndDeleted.setGroup("totally");
+
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, notDeleted, true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, deleted, true);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nonGroupedNonDeletedChannel, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedButNotDeleted, true, false);
+
+        mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, deleted.getId());
+
+        assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG_N_MR1, UID_N_MR1));
+        assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG_N_MR1, UID_N_MR1));
+
+        assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), false));
+        compareChannels(groupedAndDeleted,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), true));
+
+        compareChannels(groupedButNotDeleted,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedButNotDeleted.getId(), false));
+        compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, nonGroupedNonDeletedChannel.getId(), false));
+
+        // notDeleted
+        assertEquals(1, mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).size());
+
+        verify(mHandler, never()).requestSort();
+    }
+
+    @Test
+    public void testOnUserRemoved() throws Exception {
+        int[] user0Uids = {98, 235, 16, 3782};
+        int[] user1Uids = new int[user0Uids.length];
+        for (int i = 0; i < user0Uids.length; i++) {
+            user1Uids[i] = UserHandle.PER_USER_RANGE + user0Uids[i];
+
+            final ApplicationInfo legacy = new ApplicationInfo();
+            legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+            when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy);
+
+            // create records with the default channel for all user 0 and user 1 uids
+            mHelper.getImportance(PKG_N_MR1, user0Uids[i]);
+            mHelper.getImportance(PKG_N_MR1, user1Uids[i]);
+        }
+
+        mHelper.onUserRemoved(1);
+
+        // user 0 records remain
+        for (int i = 0; i < user0Uids.length; i++) {
+            assertEquals(1,
+                    mHelper.getNotificationChannels(PKG_N_MR1, user0Uids[i], false).getList().size());
+        }
+        // user 1 records are gone
+        for (int i = 0; i < user1Uids.length; i++) {
+            assertEquals(0,
+                    mHelper.getNotificationChannels(PKG_N_MR1, user1Uids[i], false).getList().size());
+        }
+    }
+
+    @Test
+    public void testOnPackageChanged_packageRemoval() throws Exception {
+        // Deleted
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+
+        mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{
+                UID_N_MR1});
+
+        assertEquals(0, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList().size());
+
+        // Not deleted
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+
+        mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{
+                UID_N_MR1});
+        assertEquals(2, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size());
+    }
+
+    @Test
+    public void testOnPackageChanged_packageRemoval_importance() throws Exception {
+        mHelper.setImportance(PKG_N_MR1, UID_N_MR1, NotificationManager.IMPORTANCE_HIGH);
+
+        mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{
+                UID_N_MR1});
+
+        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_N_MR1,
+                UID_N_MR1));
+    }
+
+    @Test
+    public void testOnPackageChanged_packageRemoval_groups() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+        NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true);
+
+        mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{
+                UID_N_MR1});
+
+        assertEquals(0,
+                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList().size());
+    }
+
+    @Test
+    public void testOnPackageChange_downgradeTargetSdk() throws Exception {
+        // create channel as api 26
+        mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false);
+
+        // install new app version targeting 25
+        final ApplicationInfo legacy = new ApplicationInfo();
+        legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+        when(mPm.getApplicationInfoAsUser(eq(PKG_O), anyInt(), anyInt())).thenReturn(legacy);
+        mHelper.onPackagesChanged(
+                false, UserHandle.USER_SYSTEM, new String[]{PKG_O}, new int[]{UID_O});
+
+        // make sure the default channel was readded
+        //assertEquals(2, mHelper.getNotificationChannels(PKG_O, UID_O, false).getList().size());
+        assertNotNull(mHelper.getNotificationChannel(
+                PKG_O, UID_O, NotificationChannel.DEFAULT_CHANNEL_ID, false));
+    }
+
+    @Test
+    public void testRecordDefaults() throws Exception {
+        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_N_MR1,
+                UID_N_MR1));
+        assertEquals(true, mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
+        assertEquals(1, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size());
+    }
+
+    @Test
+    public void testCreateGroup() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+        assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).iterator().next());
+        verify(mHandler, never()).requestSort();
+    }
+
+    @Test
+    public void testCannotCreateChannel_badGroup() throws Exception {
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1.setGroup("garbage");
+        try {
+            mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+            fail("Created a channel with a bad group");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testCannotCreateChannel_goodGroup() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1.setGroup(ncg.getId());
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+
+        assertEquals(ncg.getId(),
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false).getGroup());
+    }
+
+    @Test
+    public void testGetChannelGroups() throws Exception {
+        NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, unused, true);
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+        NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true);
+
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1.setGroup(ncg.getId());
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+        NotificationChannel channel1a =
+                new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1a.setGroup(ncg.getId());
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1a, true, false);
+
+        NotificationChannel channel2 =
+                new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setGroup(ncg2.getId());
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false);
+
+        NotificationChannel channel3 =
+                new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false);
+
+        List<NotificationChannelGroup> actual =
+                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList();
+        assertEquals(3, actual.size());
+        for (NotificationChannelGroup group : actual) {
+            if (group.getId() == null) {
+                assertEquals(2, group.getChannels().size()); // misc channel too
+                assertTrue(channel3.getId().equals(group.getChannels().get(0).getId())
+                        || channel3.getId().equals(group.getChannels().get(1).getId()));
+            } else if (group.getId().equals(ncg.getId())) {
+                assertEquals(2, group.getChannels().size());
+                if (group.getChannels().get(0).getId().equals(channel1.getId())) {
+                    assertTrue(group.getChannels().get(1).getId().equals(channel1a.getId()));
+                } else if (group.getChannels().get(0).getId().equals(channel1a.getId())) {
+                    assertTrue(group.getChannels().get(1).getId().equals(channel1.getId()));
+                } else {
+                    fail("expected channel not found");
+                }
+            } else if (group.getId().equals(ncg2.getId())) {
+                assertEquals(1, group.getChannels().size());
+                assertEquals(channel2.getId(), group.getChannels().get(0).getId());
+            }
+        }
+    }
+
+    @Test
+    public void testGetChannelGroups_noSideEffects() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1.setGroup(ncg.getId());
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+        mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList();
+
+        channel1.setImportance(IMPORTANCE_LOW);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true);
+
+        List<NotificationChannelGroup> actual =
+                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList();
+
+        assertEquals(2, actual.size());
+        for (NotificationChannelGroup group : actual) {
+            if (Objects.equals(group.getId(), ncg.getId())) {
+                assertEquals(1, group.getChannels().size());
+            }
+        }
+    }
+
+    @Test
+    public void testCreateChannel_updateName() throws Exception {
+        NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
+        NotificationChannel actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
+        assertEquals("hello", actual.getName());
+
+        nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
+
+        actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
+        assertEquals("goodbye", actual.getName());
+        assertEquals(IMPORTANCE_DEFAULT, actual.getImportance());
+
+        verify(mHandler, times(1)).requestSort();
+    }
+
+    @Test
+    public void testCreateChannel_addToGroup() throws Exception {
+        NotificationChannelGroup group = new NotificationChannelGroup("group", "");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
+        NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
+        NotificationChannel actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
+        assertNull(actual.getGroup());
+
+        nc = new NotificationChannel("id", "hello", IMPORTANCE_HIGH);
+        nc.setGroup(group.getId());
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
+
+        actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
+        assertNotNull(actual.getGroup());
+        assertEquals(IMPORTANCE_DEFAULT, actual.getImportance());
+
+        verify(mHandler, times(1)).requestSort();
+    }
+
+    @Test
+    public void testDumpChannelsJson() throws Exception {
+        final ApplicationInfo upgrade = new ApplicationInfo();
+        upgrade.targetSdkVersion = Build.VERSION_CODES.O;
+        try {
+            when(mPm.getApplicationInfoAsUser(
+                    anyString(), anyInt(), anyInt())).thenReturn(upgrade);
+        } catch (PackageManager.NameNotFoundException e) {
+        }
+        ArrayMap<String, Integer> expectedChannels = new ArrayMap<>();
+        int numPackages = ThreadLocalRandom.current().nextInt(1, 5);
+        for (int i = 0; i < numPackages; i++) {
+            String pkgName = "pkg" + i;
+            int numChannels = ThreadLocalRandom.current().nextInt(1, 10);
+            for (int j = 0; j < numChannels; j++) {
+                mHelper.createNotificationChannel(pkgName, UID_N_MR1,
+                        new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true, false);
+            }
+            expectedChannels.put(pkgName, numChannels);
+        }
+
+        // delete the first channel of the first package
+        String pkg = expectedChannels.keyAt(0);
+        mHelper.deleteNotificationChannel("pkg" + 0, UID_N_MR1, "0");
+        // dump should not include deleted channels
+        int count = expectedChannels.get(pkg);
+        expectedChannels.put(pkg, count - 1);
+
+        JSONArray actual = mHelper.dumpChannelsJson(new NotificationManagerService.DumpFilter());
+        assertEquals(numPackages, actual.length());
+        for (int i = 0; i < numPackages; i++) {
+            JSONObject object = actual.getJSONObject(i);
+            assertTrue(expectedChannels.containsKey(object.get("packageName")));
+            assertEquals(expectedChannels.get(object.get("packageName")).intValue(),
+                    object.getInt("channelCount"));
+        }
+    }
+
+    @Test
+    public void testBadgingOverrideTrue() throws Exception {
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 1,
+                USER.getIdentifier());
+        mHelper.updateBadgingEnabled(); // would be called by settings observer
+        assertTrue(mHelper.badgingEnabled(USER));
+    }
+
+    @Test
+    public void testBadgingOverrideFalse() throws Exception {
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 0,
+                USER.getIdentifier());
+        mHelper.updateBadgingEnabled(); // would be called by settings observer
+        assertFalse(mHelper.badgingEnabled(USER));
+    }
+
+    @Test
+    public void testBadgingForUserAll() throws Exception {
+        try {
+            mHelper.badgingEnabled(UserHandle.ALL);
+        } catch (Exception e) {
+            fail("just don't throw");
+        }
+    }
+
+    @Test
+    public void testBadgingOverrideUserIsolation() throws Exception {
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 0,
+                USER.getIdentifier());
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 1,
+                USER2.getIdentifier());
+        mHelper.updateBadgingEnabled(); // would be called by settings observer
+        assertFalse(mHelper.badgingEnabled(USER));
+        assertTrue(mHelper.badgingEnabled(USER2));
+    }
+
+    @Test
+    public void testOnLocaleChanged_updatesDefaultChannels() throws Exception {
+        String newLabel = "bananas!";
+        final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG_N_MR1,
+                UID_N_MR1,
+                NotificationChannel.DEFAULT_CHANNEL_ID, false);
+        assertFalse(newLabel.equals(defaultChannel.getName()));
+
+        Resources res = mock(Resources.class);
+        when(mContext.getResources()).thenReturn(res);
+        when(res.getString(com.android.internal.R.string.default_notification_channel_label))
+                .thenReturn(newLabel);
+
+        mHelper.onLocaleChanged(mContext, USER.getIdentifier());
+
+        assertEquals(newLabel, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1,
+                NotificationChannel.DEFAULT_CHANNEL_ID, false).getName());
+    }
+
+    @Test
+    public void testIsGroupBlocked_noGroup() throws Exception {
+        assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, null));
+
+        assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, "non existent group"));
+    }
+
+    @Test
+    public void testIsGroupBlocked_notBlocked() throws Exception {
+        NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
+
+        assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+    }
+
+    @Test
+    public void testIsGroupBlocked_blocked() throws Exception {
+        NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
+        group.setBlocked(true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, false);
+
+        assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+    }
+
+    @Test
+    public void testIsGroup_appCannotResetBlock() throws Exception {
+        NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
+        NotificationChannelGroup group2 = group.clone();
+        group2.setBlocked(true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group2, false);
+        assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+
+        NotificationChannelGroup group3 = group.clone();
+        group3.setBlocked(false);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true);
+        assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+    }
+
+    @Test
+    public void testGetNotificationChannelGroupWithChannels() throws Exception {
+        NotificationChannelGroup group = new NotificationChannelGroup("group", "");
+        NotificationChannelGroup other = new NotificationChannelGroup("something else", "");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, other, true);
+
+        NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
+        a.setGroup(group.getId());
+        NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_DEFAULT);
+        b.setGroup(other.getId());
+        NotificationChannel c = new NotificationChannel("c", "c", IMPORTANCE_DEFAULT);
+        c.setGroup(group.getId());
+        NotificationChannel d = new NotificationChannel("d", "d", IMPORTANCE_DEFAULT);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, a, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, b, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, c, true, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, d, true, false);
+        mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, c.getId());
+
+        NotificationChannelGroup retrieved = mHelper.getNotificationChannelGroupWithChannels(
+                PKG_N_MR1, UID_N_MR1, group.getId(), true);
+        assertEquals(2, retrieved.getChannels().size());
+        compareChannels(a, findChannel(retrieved.getChannels(), a.getId()));
+        compareChannels(c, findChannel(retrieved.getChannels(), c.getId()));
+
+        retrieved = mHelper.getNotificationChannelGroupWithChannels(
+                PKG_N_MR1, UID_N_MR1, group.getId(), false);
+        assertEquals(1, retrieved.getChannels().size());
+        compareChannels(a, findChannel(retrieved.getChannels(), a.getId()));
+    }
+
+    @Test
+    public void testAndroidPkgCannotBypassDnd_creation() {
+        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
+        test.setBypassDnd(true);
+
+        mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, test, true, false);
+
+        assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false)
+                .canBypassDnd());
+    }
+
+    @Test
+    public void testDndPkgCanBypassDnd_creation() {
+        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
+        test.setBypassDnd(true);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, test, true, true);
+
+        assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "A", false).canBypassDnd());
+    }
+
+    @Test
+    public void testNormalPkgCannotBypassDnd_creation() {
+        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
+        test.setBypassDnd(true);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, 1000, test, true, false);
+
+        assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, 1000, "A", false).canBypassDnd());
+    }
+
+    @Test
+    public void testAndroidPkgCannotBypassDnd_update() throws Exception {
+        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
+        mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, test, true, false);
+
+        NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW);
+        update.setBypassDnd(true);
+        mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, update, true, false);
+
+        assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false)
+                .canBypassDnd());
+    }
+
+    @Test
+    public void testDndPkgCanBypassDnd_update() throws Exception {
+        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, test, true, true);
+
+        NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW);
+        update.setBypassDnd(true);
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, update, true, true);
+
+        assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "A", false).canBypassDnd());
+    }
+
+    @Test
+    public void testNormalPkgCannotBypassDnd_update() {
+        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
+        mHelper.createNotificationChannel(PKG_N_MR1, 1000, test, true, false);
+        NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW);
+        update.setBypassDnd(true);
+        mHelper.createNotificationChannel(PKG_N_MR1, 1000, update, true, false);
+        assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, 1000, "A", false).canBypassDnd());
+    }
+
+    @Test
+    public void testGetBlockedAppCount_noApps() {
+        assertEquals(0, mHelper.getBlockedAppCount(0));
+    }
+
+    @Test
+    public void testGetBlockedAppCount_noAppsForUserId() {
+        mHelper.setEnabled(PKG_N_MR1, 100, false);
+        assertEquals(0, mHelper.getBlockedAppCount(9));
+    }
+
+    @Test
+    public void testGetBlockedAppCount_appsForUserId() {
+        mHelper.setEnabled(PKG_N_MR1, 1020, false);
+        mHelper.setEnabled(PKG_N_MR1, 1030, false);
+        mHelper.setEnabled(PKG_N_MR1, 1060, false);
+        mHelper.setEnabled(PKG_N_MR1, 1000, true);
+        assertEquals(3, mHelper.getBlockedAppCount(0));
+    }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 98c6ec4..5638cb36 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -15,35 +15,17 @@
  */
 package com.android.server.notification;
 
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_MAX;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.fail;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.Notification;
 import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
 import android.content.ContentProvider;
 import android.content.Context;
@@ -52,46 +34,26 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
-import android.content.res.Resources;
-import android.graphics.Color;
 import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.TestableContentResolver;
-import android.util.ArrayMap;
-import android.util.Xml;
 
-import com.android.internal.util.FastXmlSerializer;
 import com.android.server.UiServiceTestCase;
 
-import org.json.JSONArray;
-import org.json.JSONObject;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
 
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.ThreadLocalRandom;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -118,6 +80,7 @@
     @Mock IContentProvider mTestIContentProvider;
     @Mock Context mContext;
     @Mock ZenModeHelper mMockZenModeHelper;
+    @Mock RankingConfig mConfig;
 
     private NotificationManager.Policy mTestNotificationPolicy;
     private Notification mNotiGroupGSortA;
@@ -179,9 +142,8 @@
         mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
                 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND);
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
-        mHelper = new RankingHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
+        mHelper = new RankingHelper(getContext(), mHandler, mConfig, mMockZenModeHelper,
                 mUsageStats, new String[] {ImportanceExtractor.class.getName()});
-        resetZenModeHelper();
 
         mNotiGroupGSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setContentTitle("A")
@@ -240,77 +202,43 @@
                 IMPORTANCE_LOW);
     }
 
-    private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, boolean forBackup,
-            String... channelIds)
-            throws Exception {
-        XmlSerializer serializer = new FastXmlSerializer();
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
-        serializer.startDocument(null, true);
-        mHelper.writeXml(serializer, forBackup);
-        serializer.endDocument();
-        serializer.flush();
-        for (String channelId : channelIds) {
-            mHelper.permanentlyDeleteNotificationChannel(pkg, uid, channelId);
-        }
-        return baos;
+    @Test
+    public void testSortShouldRespectCritical() throws Exception {
+        ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(7);
+        NotificationRecord critical = generateRecord(0);
+        NotificationRecord critical_ish = generateRecord(1);
+        NotificationRecord critical_notAtAll = generateRecord(100);
+
+        notificationList.add(critical_ish);
+        notificationList.add(mRecordGroupGSortA);
+        notificationList.add(critical_notAtAll);
+        notificationList.add(mRecordGroupGSortB);
+        notificationList.add(mRecordNoGroup);
+        notificationList.add(mRecordNoGroupSortA);
+        notificationList.add(critical);
+        mHelper.sort(notificationList);
+
+        assertTrue(mHelper.indexOf(notificationList, critical) == 0);
+        assertTrue(mHelper.indexOf(notificationList, critical_ish) == 1);
+        assertTrue(mHelper.indexOf(notificationList, critical_notAtAll) == 6);
     }
 
-    private void loadStreamXml(ByteArrayOutputStream stream, boolean forRestore) throws Exception {
-        loadByteArrayXml(stream.toByteArray(), forRestore);
-    }
-
-    private void loadByteArrayXml(byte[] byteArray, boolean forRestore) throws Exception {
-        XmlPullParser parser = Xml.newPullParser();
-        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(byteArray)), null);
-        parser.nextTag();
-        mHelper.readXml(parser, forRestore);
-    }
-
-    private void compareChannels(NotificationChannel expected, NotificationChannel actual) {
-        assertEquals(expected.getId(), actual.getId());
-        assertEquals(expected.getName(), actual.getName());
-        assertEquals(expected.getDescription(), actual.getDescription());
-        assertEquals(expected.shouldVibrate(), actual.shouldVibrate());
-        assertEquals(expected.shouldShowLights(), actual.shouldShowLights());
-        assertEquals(expected.getImportance(), actual.getImportance());
-        assertEquals(expected.getLockscreenVisibility(), actual.getLockscreenVisibility());
-        assertEquals(expected.getSound(), actual.getSound());
-        assertEquals(expected.canBypassDnd(), actual.canBypassDnd());
-        assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern()));
-        assertEquals(expected.getGroup(), actual.getGroup());
-        assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes());
-        assertEquals(expected.getLightColor(), actual.getLightColor());
-    }
-
-    private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) {
-        assertEquals(expected.getId(), actual.getId());
-        assertEquals(expected.getName(), actual.getName());
-        assertEquals(expected.getDescription(), actual.getDescription());
-        assertEquals(expected.isBlocked(), actual.isBlocked());
-    }
-
-    private NotificationChannel getChannel() {
-        return new NotificationChannel("id", "name", IMPORTANCE_LOW);
-    }
-
-    private NotificationChannel findChannel(List<NotificationChannel> channels, String id) {
-        for (NotificationChannel channel : channels) {
-            if (channel.getId().equals(id)) {
-                return channel;
-            }
-        }
-        return null;
-    }
-
-    private void resetZenModeHelper() {
-        reset(mMockZenModeHelper);
-        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
+    private NotificationRecord generateRecord(int criticality) {
+        NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
+        final Notification.Builder builder = new Notification.Builder(getContext())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon);
+        Notification n = builder.build();
+        StatusBarNotification sbn = new StatusBarNotification("", "", 0, "", 0,
+                0, n, UserHandle.ALL, null, System.currentTimeMillis());
+        NotificationRecord notificationRecord = new NotificationRecord(getContext(), sbn, channel);
+        notificationRecord.setCriticality(criticality);
+        return notificationRecord;
     }
 
     @Test
     public void testFindAfterRankingWithASplitGroup() throws Exception {
-        ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(3);
+        ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(4);
         notificationList.add(mRecordGroupGSortA);
         notificationList.add(mRecordGroupGSortB);
         notificationList.add(mRecordNoGroup);
@@ -357,1496 +285,4 @@
         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>();
         mHelper.sort(notificationList);
     }
-
-    @Test
-    public void testChannelXml() throws Exception {
-        NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
-        ncg.setBlocked(true);
-        ncg.setDescription("group desc");
-        NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
-        NotificationChannel channel1 =
-                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
-        NotificationChannel channel2 =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        channel2.setDescription("descriptions for all");
-        channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
-        channel2.enableLights(true);
-        channel2.setBypassDnd(true);
-        channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-        channel2.enableVibration(true);
-        channel2.setGroup(ncg.getId());
-        channel2.setVibrationPattern(new long[]{100, 67, 145, 156});
-        channel2.setLightColor(Color.BLUE);
-
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
-        mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-        mHelper.createNotificationChannel(PKG, UID, channel2, false, false);
-
-        mHelper.setShowBadge(PKG, UID, true);
-        mHelper.setAppImportanceLocked(PKG, UID);
-
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(),
-                channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
-        mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID});
-
-        loadStreamXml(baos, false);
-
-        assertTrue(mHelper.canShowBadge(PKG, UID));
-        assertTrue(mHelper.getIsAppImportanceLocked(PKG, UID));
-        assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
-        compareChannels(channel2,
-                mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
-
-        List<NotificationChannelGroup> actualGroups =
-                mHelper.getNotificationChannelGroups(PKG, UID, false, true).getList();
-        boolean foundNcg = false;
-        for (NotificationChannelGroup actual : actualGroups) {
-            if (ncg.getId().equals(actual.getId())) {
-                foundNcg = true;
-                compareGroups(ncg, actual);
-            } else if (ncg2.getId().equals(actual.getId())) {
-                compareGroups(ncg2, actual);
-            }
-        }
-        assertTrue(foundNcg);
-
-        boolean foundChannel2Group = false;
-        for (NotificationChannelGroup actual : actualGroups) {
-            if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) {
-                foundChannel2Group = true;
-                break;
-            }
-        }
-        assertTrue(foundChannel2Group);
-    }
-
-    @Test
-    public void testChannelXmlForBackup() throws Exception {
-        NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
-        NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
-        NotificationChannel channel1 =
-                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
-        NotificationChannel channel2 =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        channel2.setDescription("descriptions for all");
-        channel2.setSound(SOUND_URI, mAudioAttributes);
-        channel2.enableLights(true);
-        channel2.setBypassDnd(true);
-        channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-        channel2.enableVibration(false);
-        channel2.setGroup(ncg.getId());
-        channel2.setLightColor(Color.BLUE);
-        NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH);
-        channel3.enableVibration(true);
-
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
-        mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-        mHelper.createNotificationChannel(PKG, UID, channel2, false, false);
-        mHelper.createNotificationChannel(PKG, UID, channel3, false, false);
-        mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true, false);
-
-        mHelper.setShowBadge(PKG, UID, true);
-
-        mHelper.setImportance(UPDATED_PKG, UID2, IMPORTANCE_NONE);
-
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(),
-                channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
-        mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG, UPDATED_PKG},
-                new int[]{UID, UID2});
-
-        mHelper.setShowBadge(UPDATED_PKG, UID2, true);
-
-        loadStreamXml(baos, true);
-
-        assertEquals(IMPORTANCE_NONE, mHelper.getImportance(UPDATED_PKG, UID2));
-        assertTrue(mHelper.canShowBadge(PKG, UID));
-        assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
-        compareChannels(channel2,
-                mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
-        compareChannels(channel3,
-                mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false));
-
-        List<NotificationChannelGroup> actualGroups =
-                mHelper.getNotificationChannelGroups(PKG, UID, false, true).getList();
-        boolean foundNcg = false;
-        for (NotificationChannelGroup actual : actualGroups) {
-            if (ncg.getId().equals(actual.getId())) {
-                foundNcg = true;
-                compareGroups(ncg, actual);
-            } else if (ncg2.getId().equals(actual.getId())) {
-                compareGroups(ncg2, actual);
-            }
-        }
-        assertTrue(foundNcg);
-
-        boolean foundChannel2Group = false;
-        for (NotificationChannelGroup actual : actualGroups) {
-            if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) {
-                foundChannel2Group = true;
-                break;
-            }
-        }
-        assertTrue(foundChannel2Group);
-    }
-
-    @Test
-    public void testBackupXml_backupCanonicalizedSoundUri() throws Exception {
-        NotificationChannel channel =
-                new NotificationChannel("id", "name", IMPORTANCE_LOW);
-        channel.setSound(SOUND_URI, mAudioAttributes);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId());
-
-        // Testing that in restore we are given the canonical version
-        loadStreamXml(baos, true);
-        verify(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
-    }
-
-    @Test
-    public void testRestoreXml_withExistentCanonicalizedSoundUri() throws Exception {
-        Uri localUri = Uri.parse("content://" + TEST_AUTHORITY + "/local/url");
-        Uri canonicalBasedOnLocal = localUri.buildUpon()
-                .appendQueryParameter("title", "Test")
-                .appendQueryParameter("canonical", "1")
-                .build();
-        when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(canonicalBasedOnLocal);
-        when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(localUri);
-        when(mTestIContentProvider.uncanonicalize(any(), eq(canonicalBasedOnLocal)))
-                .thenReturn(localUri);
-
-        NotificationChannel channel =
-                new NotificationChannel("id", "name", IMPORTANCE_LOW);
-        channel.setSound(SOUND_URI, mAudioAttributes);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId());
-
-        loadStreamXml(baos, true);
-
-        NotificationChannel actualChannel = mHelper.getNotificationChannel(
-                PKG, UID, channel.getId(), false);
-        assertEquals(localUri, actualChannel.getSound());
-    }
-
-    @Test
-    public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception {
-        Thread.sleep(3000);
-        when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(null);
-        when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(null);
-
-        NotificationChannel channel =
-                new NotificationChannel("id", "name", IMPORTANCE_LOW);
-        channel.setSound(SOUND_URI, mAudioAttributes);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId());
-
-        loadStreamXml(baos, true);
-
-        NotificationChannel actualChannel = mHelper.getNotificationChannel(
-                PKG, UID, channel.getId(), false);
-        assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound());
-    }
-
-
-    /**
-     * Although we don't make backups with uncanonicalized uris anymore, we used to, so we have to
-     * handle its restore properly.
-     */
-    @Test
-    public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception {
-        // Not a local uncanonicalized uri, simulating that it fails to exist locally
-        when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI))).thenReturn(null);
-        String id = "id";
-        String backupWithUncanonicalizedSoundUri = "<ranking version=\"1\">\n"
-                + "<package name=\"com.android.server.notification\" show_badge=\"true\">\n"
-                + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" "
-                + "sound=\"" + SOUND_URI + "\" "
-                + "usage=\"6\" content_type=\"0\" flags=\"1\" show_badge=\"true\" />\n"
-                + "<channel id=\"miscellaneous\" name=\"Uncategorized\" usage=\"5\" "
-                + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
-                + "</package>\n"
-                + "</ranking>\n";
-
-        loadByteArrayXml(backupWithUncanonicalizedSoundUri.getBytes(), true);
-
-        NotificationChannel actualChannel = mHelper.getNotificationChannel(PKG, UID, id, false);
-        assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound());
-    }
-
-    @Test
-    public void testBackupRestoreXml_withNullSoundUri() throws Exception {
-        NotificationChannel channel =
-                new NotificationChannel("id", "name", IMPORTANCE_LOW);
-        channel.setSound(null, mAudioAttributes);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId());
-
-        loadStreamXml(baos, true);
-
-        NotificationChannel actualChannel = mHelper.getNotificationChannel(
-                PKG, UID, channel.getId(), false);
-        assertEquals(null, actualChannel.getSound());
-    }
-
-    @Test
-    public void testChannelXml_backup() throws Exception {
-        NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
-        NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
-        NotificationChannel channel1 =
-                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
-        NotificationChannel channel2 =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        NotificationChannel channel3 =
-                new NotificationChannel("id3", "name3", IMPORTANCE_LOW);
-        channel3.setGroup(ncg.getId());
-
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
-        mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-        mHelper.createNotificationChannel(PKG, UID, channel2, false, false);
-        mHelper.createNotificationChannel(PKG, UID, channel3, true, false);
-
-        mHelper.deleteNotificationChannel(PKG, UID, channel1.getId());
-        mHelper.deleteNotificationChannelGroup(PKG, UID, ncg.getId());
-        assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
-
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(),
-                channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
-        mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID});
-
-        XmlPullParser parser = Xml.newPullParser();
-        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
-                null);
-        parser.nextTag();
-        mHelper.readXml(parser, true);
-
-        assertNull(mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
-        assertNull(mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false));
-        assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG, UID));
-        //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID));
-        assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
-    }
-
-    @Test
-    public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception {
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
-                NotificationChannel.DEFAULT_CHANNEL_ID);
-
-        loadStreamXml(baos, false);
-
-        final NotificationChannel updated = mHelper.getNotificationChannel(PKG, UID,
-                NotificationChannel.DEFAULT_CHANNEL_ID, false);
-        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance());
-        assertFalse(updated.canBypassDnd());
-        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, updated.getLockscreenVisibility());
-        assertEquals(0, updated.getUserLockedFields());
-    }
-
-    @Test
-    public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception {
-        final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID,
-                NotificationChannel.DEFAULT_CHANNEL_ID, false);
-        defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mHelper.updateNotificationChannel(PKG, UID, defaultChannel, true);
-
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
-                NotificationChannel.DEFAULT_CHANNEL_ID);
-
-        loadStreamXml(baos, false);
-
-        assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel(
-                PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance());
-    }
-
-    @Test
-    public void testChannelXml_upgradeCreateDefaultChannel() throws Exception {
-        final String preupgradeXml = "<ranking version=\"1\">\n"
-                + "<package name=\"" + PKG
-                + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH
-                + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\""
-                + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + UID + "\" />\n"
-                + "<package name=\"" + UPDATED_PKG + "\" uid=\"" + UID2 + "\" visibility=\""
-                + Notification.VISIBILITY_PRIVATE + "\" />\n"
-                + "</ranking>";
-        XmlPullParser parser = Xml.newPullParser();
-        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
-                null);
-        parser.nextTag();
-        mHelper.readXml(parser, false);
-
-        final NotificationChannel updated1 =
-            mHelper.getNotificationChannel(PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false);
-        assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance());
-        assertTrue(updated1.canBypassDnd());
-        assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility());
-        assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE
-                | NotificationChannel.USER_LOCKED_PRIORITY
-                | NotificationChannel.USER_LOCKED_VISIBILITY,
-                updated1.getUserLockedFields());
-
-        // No Default Channel created for updated packages
-        assertEquals(null, mHelper.getNotificationChannel(UPDATED_PKG, UID2,
-                NotificationChannel.DEFAULT_CHANNEL_ID, false));
-    }
-
-    @Test
-    public void testChannelXml_upgradeDeletesDefaultChannel() throws Exception {
-        final NotificationChannel defaultChannel = mHelper.getNotificationChannel(
-                PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false);
-        assertTrue(defaultChannel != null);
-        ByteArrayOutputStream baos =
-                writeXmlAndPurge(PKG, UID, false, NotificationChannel.DEFAULT_CHANNEL_ID);
-        // Load package at higher sdk.
-        final ApplicationInfo upgraded = new ApplicationInfo();
-        upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
-        when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded);
-        loadStreamXml(baos, false);
-
-        // Default Channel should be gone.
-        assertEquals(null, mHelper.getNotificationChannel(PKG, UID,
-                NotificationChannel.DEFAULT_CHANNEL_ID, false));
-    }
-
-    @Test
-    public void testDeletesDefaultChannelAfterChannelIsCreated() throws Exception {
-        mHelper.createNotificationChannel(PKG, UID,
-                new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false);
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
-                NotificationChannel.DEFAULT_CHANNEL_ID, "bananas");
-
-        // Load package at higher sdk.
-        final ApplicationInfo upgraded = new ApplicationInfo();
-        upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
-        when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded);
-        loadStreamXml(baos, false);
-
-        // Default Channel should be gone.
-        assertEquals(null, mHelper.getNotificationChannel(PKG, UID,
-                NotificationChannel.DEFAULT_CHANNEL_ID, false));
-    }
-
-    @Test
-    public void testLoadingOldChannelsDoesNotDeleteNewlyCreatedChannels() throws Exception {
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
-                NotificationChannel.DEFAULT_CHANNEL_ID, "bananas");
-        mHelper.createNotificationChannel(PKG, UID,
-                new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false);
-
-        loadStreamXml(baos, false);
-
-        // Should still have the newly created channel that wasn't in the xml.
-        assertTrue(mHelper.getNotificationChannel(PKG, UID, "bananas", false) != null);
-    }
-
-    @Test
-    public void testCreateChannel_blocked() throws Exception {
-        mHelper.setImportance(PKG, UID, IMPORTANCE_NONE);
-
-        mHelper.createNotificationChannel(PKG, UID,
-                new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false);
-    }
-
-    @Test
-    public void testCreateChannel_badImportance() throws Exception {
-        try {
-            mHelper.createNotificationChannel(PKG, UID,
-                    new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1),
-                    true, false);
-            fail("Was allowed to create a channel with invalid importance");
-        } catch (IllegalArgumentException e) {
-            // yay
-        }
-        try {
-            mHelper.createNotificationChannel(PKG, UID,
-                    new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED),
-                    true, false);
-            fail("Was allowed to create a channel with invalid importance");
-        } catch (IllegalArgumentException e) {
-            // yay
-        }
-        try {
-            mHelper.createNotificationChannel(PKG, UID,
-                    new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1),
-                    true, false);
-            fail("Was allowed to create a channel with invalid importance");
-        } catch (IllegalArgumentException e) {
-            // yay
-        }
-        mHelper.createNotificationChannel(PKG, UID,
-                new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true, false);
-        mHelper.createNotificationChannel(PKG, UID,
-                new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false);
-    }
-
-
-    @Test
-    public void testUpdate() throws Exception {
-        // no fields locked by user
-        final NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
-        channel.enableLights(true);
-        channel.setBypassDnd(true);
-        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-
-        mHelper.createNotificationChannel(PKG, UID, channel, false, false);
-
-        // same id, try to update all fields
-        final NotificationChannel channel2 =
-                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
-        channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes);
-        channel2.enableLights(false);
-        channel2.setBypassDnd(false);
-        channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
-
-        mHelper.updateNotificationChannel(PKG, UID, channel2, true);
-
-        // all fields should be changed
-        assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false));
-
-        verify(mHandler, times(1)).requestSort();
-    }
-
-    @Test
-    public void testUpdate_preUpgrade_updatesAppFields() throws Exception {
-        mHelper.setImportance(PKG, UID, IMPORTANCE_UNSPECIFIED);
-        assertTrue(mHelper.canShowBadge(PKG, UID));
-        assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID));
-        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
-                mHelper.getPackageVisibility(PKG, UID));
-        assertFalse(mHelper.getIsAppImportanceLocked(PKG, UID));
-
-        NotificationChannel defaultChannel = mHelper.getNotificationChannel(
-                PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false);
-
-        defaultChannel.setShowBadge(false);
-        defaultChannel.setImportance(IMPORTANCE_NONE);
-        defaultChannel.setBypassDnd(true);
-        defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-
-        mHelper.setAppImportanceLocked(PKG, UID);
-        mHelper.updateNotificationChannel(PKG, UID, defaultChannel, true);
-
-        // ensure app level fields are changed
-        assertFalse(mHelper.canShowBadge(PKG, UID));
-        assertEquals(Notification.PRIORITY_MAX, mHelper.getPackagePriority(PKG, UID));
-        assertEquals(Notification.VISIBILITY_SECRET, mHelper.getPackageVisibility(PKG, UID));
-        assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG, UID));
-        assertTrue(mHelper.getIsAppImportanceLocked(PKG, UID));
-    }
-
-    @Test
-    public void testUpdate_postUpgrade_noUpdateAppFields() throws Exception {
-        final NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-
-        mHelper.createNotificationChannel(PKG, UID, channel, false, false);
-        assertTrue(mHelper.canShowBadge(PKG, UID));
-        assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID));
-        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
-                mHelper.getPackageVisibility(PKG, UID));
-
-        channel.setShowBadge(false);
-        channel.setImportance(IMPORTANCE_NONE);
-        channel.setBypassDnd(true);
-        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-
-        mHelper.updateNotificationChannel(PKG, UID, channel, true);
-
-        // ensure app level fields are not changed
-        assertTrue(mHelper.canShowBadge(PKG, UID));
-        assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID));
-        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
-                mHelper.getPackageVisibility(PKG, UID));
-        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID));
-    }
-
-    @Test
-    public void testGetNotificationChannel_ReturnsNullForUnknownChannel() throws Exception {
-        assertEquals(null, mHelper.getNotificationChannel(PKG, UID, "garbage", false));
-    }
-
-    @Test
-    public void testCreateChannel_CannotChangeHiddenFields() throws Exception {
-        final NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
-        channel.enableLights(true);
-        channel.setBypassDnd(true);
-        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-        channel.setShowBadge(true);
-        int lockMask = 0;
-        for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
-            lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
-        }
-        channel.lockFields(lockMask);
-
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-
-        NotificationChannel savedChannel =
-                mHelper.getNotificationChannel(PKG, UID, channel.getId(), false);
-
-        assertEquals(channel.getName(), savedChannel.getName());
-        assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
-        assertFalse(savedChannel.canBypassDnd());
-        assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
-        assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
-
-        verify(mHandler, never()).requestSort();
-    }
-
-    @Test
-    public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception {
-        final NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
-        channel.enableLights(true);
-        channel.setBypassDnd(true);
-        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-        channel.setShowBadge(true);
-        int lockMask = 0;
-        for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
-            lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
-        }
-        channel.lockFields(lockMask);
-
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-
-        NotificationChannel savedChannel =
-                mHelper.getNotificationChannel(PKG, UID, channel.getId(), false);
-
-        assertEquals(channel.getName(), savedChannel.getName());
-        assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
-        assertFalse(savedChannel.canBypassDnd());
-        assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
-        assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
-    }
-
-    @Test
-    public void testClearLockedFields() throws Exception {
-        final NotificationChannel channel = getChannel();
-        mHelper.clearLockedFields(channel);
-        assertEquals(0, channel.getUserLockedFields());
-
-        channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY
-                | NotificationChannel.USER_LOCKED_IMPORTANCE);
-        mHelper.clearLockedFields(channel);
-        assertEquals(0, channel.getUserLockedFields());
-    }
-
-    @Test
-    public void testLockFields_soundAndVibration() throws Exception {
-        mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false);
-
-        final NotificationChannel update1 = getChannel();
-        update1.setSound(new Uri.Builder().scheme("test").build(),
-                new AudioAttributes.Builder().build());
-        update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
-        mHelper.updateNotificationChannel(PKG, UID, update1, true);
-        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
-                | NotificationChannel.USER_LOCKED_SOUND,
-                mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
-                        .getUserLockedFields());
-
-        NotificationChannel update2 = getChannel();
-        update2.enableVibration(true);
-        mHelper.updateNotificationChannel(PKG, UID, update2, true);
-        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
-                        | NotificationChannel.USER_LOCKED_SOUND
-                        | NotificationChannel.USER_LOCKED_VIBRATION,
-                mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
-                        .getUserLockedFields());
-    }
-
-    @Test
-    public void testLockFields_vibrationAndLights() throws Exception {
-        mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false);
-
-        final NotificationChannel update1 = getChannel();
-        update1.setVibrationPattern(new long[]{7945, 46 ,246});
-        mHelper.updateNotificationChannel(PKG, UID, update1, true);
-        assertEquals(NotificationChannel.USER_LOCKED_VIBRATION,
-                mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
-                        .getUserLockedFields());
-
-        final NotificationChannel update2 = getChannel();
-        update2.enableLights(true);
-        mHelper.updateNotificationChannel(PKG, UID, update2, true);
-        assertEquals(NotificationChannel.USER_LOCKED_VIBRATION
-                        | NotificationChannel.USER_LOCKED_LIGHTS,
-                mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
-                        .getUserLockedFields());
-    }
-
-    @Test
-    public void testLockFields_lightsAndImportance() throws Exception {
-        mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false);
-
-        final NotificationChannel update1 = getChannel();
-        update1.setLightColor(Color.GREEN);
-        mHelper.updateNotificationChannel(PKG, UID, update1, true);
-        assertEquals(NotificationChannel.USER_LOCKED_LIGHTS,
-                mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
-                        .getUserLockedFields());
-
-        final NotificationChannel update2 = getChannel();
-        update2.setImportance(IMPORTANCE_DEFAULT);
-        mHelper.updateNotificationChannel(PKG, UID, update2, true);
-        assertEquals(NotificationChannel.USER_LOCKED_LIGHTS
-                        | NotificationChannel.USER_LOCKED_IMPORTANCE,
-                mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
-                        .getUserLockedFields());
-    }
-
-    @Test
-    public void testLockFields_visibilityAndDndAndBadge() throws Exception {
-        mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false);
-        assertEquals(0,
-                mHelper.getNotificationChannel(PKG, UID, getChannel().getId(), false)
-                        .getUserLockedFields());
-
-        final NotificationChannel update1 = getChannel();
-        update1.setBypassDnd(true);
-        mHelper.updateNotificationChannel(PKG, UID, update1, true);
-        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY,
-                mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
-                        .getUserLockedFields());
-
-        final NotificationChannel update2 = getChannel();
-        update2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-        mHelper.updateNotificationChannel(PKG, UID, update2, true);
-        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
-                        | NotificationChannel.USER_LOCKED_VISIBILITY,
-                mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
-                        .getUserLockedFields());
-
-        final NotificationChannel update3 = getChannel();
-        update3.setShowBadge(false);
-        mHelper.updateNotificationChannel(PKG, UID, update3, true);
-        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
-                        | NotificationChannel.USER_LOCKED_VISIBILITY
-                        | NotificationChannel.USER_LOCKED_SHOW_BADGE,
-                mHelper.getNotificationChannel(PKG, UID, update3.getId(), false)
-                        .getUserLockedFields());
-    }
-
-    @Test
-    public void testDeleteNonExistentChannel() throws Exception {
-        mHelper.deleteNotificationChannelGroup(PKG, UID, "does not exist");
-    }
-
-    @Test
-    public void testGetDeletedChannel() throws Exception {
-        NotificationChannel channel = getChannel();
-        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
-        channel.enableLights(true);
-        channel.setBypassDnd(true);
-        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-        channel.enableVibration(true);
-        channel.setVibrationPattern(new long[]{100, 67, 145, 156});
-
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
-
-        // Does not return deleted channel
-        NotificationChannel response =
-                mHelper.getNotificationChannel(PKG, UID, channel.getId(), false);
-        assertNull(response);
-
-        // Returns deleted channel
-        response = mHelper.getNotificationChannel(PKG, UID, channel.getId(), true);
-        compareChannels(channel, response);
-        assertTrue(response.isDeleted());
-    }
-
-    @Test
-    public void testGetDeletedChannels() throws Exception {
-        Map<String, NotificationChannel> channelMap = new HashMap<>();
-        NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
-        channel.enableLights(true);
-        channel.setBypassDnd(true);
-        channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
-        channel.enableVibration(true);
-        channel.setVibrationPattern(new long[]{100, 67, 145, 156});
-        channelMap.put(channel.getId(), channel);
-        NotificationChannel channel2 =
-                new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
-        channelMap.put(channel2.getId(), channel2);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        mHelper.createNotificationChannel(PKG, UID, channel2, true, false);
-
-        mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
-
-        // Returns only non-deleted channels
-        List<NotificationChannel> channels =
-                mHelper.getNotificationChannels(PKG, UID, false).getList();
-        assertEquals(2, channels.size());   // Default channel + non-deleted channel
-        for (NotificationChannel nc : channels) {
-            if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
-                compareChannels(channel2, nc);
-            }
-        }
-
-        // Returns deleted channels too
-        channels = mHelper.getNotificationChannels(PKG, UID, true).getList();
-        assertEquals(3, channels.size());               // Includes default channel
-        for (NotificationChannel nc : channels) {
-            if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
-                compareChannels(channelMap.get(nc.getId()), nc);
-            }
-        }
-    }
-
-    @Test
-    public void testGetDeletedChannelCount() throws Exception {
-        NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        NotificationChannel channel2 =
-                new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
-        NotificationChannel channel3 =
-                new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_HIGH);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        mHelper.createNotificationChannel(PKG, UID, channel2, true, false);
-        mHelper.createNotificationChannel(PKG, UID, channel3, true, false);
-
-        mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
-        mHelper.deleteNotificationChannel(PKG, UID, channel3.getId());
-
-        assertEquals(2, mHelper.getDeletedChannelCount(PKG, UID));
-        assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID2));
-    }
-
-    @Test
-    public void testGetBlockedChannelCount() throws Exception {
-        NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        NotificationChannel channel2 =
-                new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_NONE);
-        NotificationChannel channel3 =
-                new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_NONE);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        mHelper.createNotificationChannel(PKG, UID, channel2, true, false);
-        mHelper.createNotificationChannel(PKG, UID, channel3, true, false);
-
-        mHelper.deleteNotificationChannel(PKG, UID, channel3.getId());
-
-        assertEquals(1, mHelper.getBlockedChannelCount(PKG, UID));
-        assertEquals(0, mHelper.getBlockedChannelCount("pkg2", UID2));
-    }
-
-    @Test
-    public void testCreateAndDeleteCanChannelsBypassDnd() throws Exception {
-        // create notification channel that can't bypass dnd
-        // expected result: areChannelsBypassingDnd = false
-        // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false
-        NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
-        resetZenModeHelper();
-
-        // create notification channel that can bypass dnd
-        // expected result: areChannelsBypassingDnd = true
-        NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        channel2.setBypassDnd(true);
-        mHelper.createNotificationChannel(PKG, UID, channel2, true, true);
-        assertTrue(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
-        resetZenModeHelper();
-
-        // delete channels
-        mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
-        assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
-        resetZenModeHelper();
-
-        mHelper.deleteNotificationChannel(PKG, UID, channel2.getId());
-        assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
-        resetZenModeHelper();
-    }
-
-    @Test
-    public void testUpdateCanChannelsBypassDnd() throws Exception {
-        // create notification channel that can't bypass dnd
-        // expected result: areChannelsBypassingDnd = false
-        // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false
-        NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
-        resetZenModeHelper();
-
-        // update channel so it CAN bypass dnd:
-        // expected result: areChannelsBypassingDnd = true
-        channel.setBypassDnd(true);
-        mHelper.updateNotificationChannel(PKG, UID, channel, true);
-        assertTrue(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
-        resetZenModeHelper();
-
-        // update channel so it can't bypass dnd:
-        // expected result: areChannelsBypassingDnd = false
-        channel.setBypassDnd(false);
-        mHelper.updateNotificationChannel(PKG, UID, channel, true);
-        assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
-        resetZenModeHelper();
-    }
-
-    @Test
-    public void testSetupNewZenModeHelper_canBypass() {
-        // start notification policy off with mAreChannelsBypassingDnd = true, but
-        // RankingHelper should change to false
-        mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
-                NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND);
-        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
-        mHelper = new RankingHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mUsageStats, new String[] {ImportanceExtractor.class.getName()});
-        assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
-        resetZenModeHelper();
-    }
-
-    @Test
-    public void testSetupNewZenModeHelper_cannotBypass() {
-        // start notification policy off with mAreChannelsBypassingDnd = false
-        mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0);
-        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
-        mHelper = new RankingHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mUsageStats, new String[] {ImportanceExtractor.class.getName()});
-        assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
-        resetZenModeHelper();
-    }
-
-    @Test
-    public void testCreateDeletedChannel() throws Exception {
-        long[] vibration = new long[]{100, 67, 145, 156};
-        NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        channel.setVibrationPattern(vibration);
-
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
-
-        NotificationChannel newChannel = new NotificationChannel(
-                channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
-        newChannel.setVibrationPattern(new long[]{100});
-
-        mHelper.createNotificationChannel(PKG, UID, newChannel, true, false);
-
-        // No long deleted, using old settings
-        compareChannels(channel,
-                mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false));
-    }
-
-    @Test
-    public void testOnlyHasDefaultChannel() throws Exception {
-        assertTrue(mHelper.onlyHasDefaultChannel(PKG, UID));
-        assertFalse(mHelper.onlyHasDefaultChannel(UPDATED_PKG, UID2));
-
-        mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false);
-        assertFalse(mHelper.onlyHasDefaultChannel(PKG, UID));
-    }
-
-    @Test
-    public void testCreateChannel_defaultChannelId() throws Exception {
-        try {
-            mHelper.createNotificationChannel(PKG, UID, new NotificationChannel(
-                    NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true, false);
-            fail("Allowed to create default channel");
-        } catch (IllegalArgumentException e) {
-            // pass
-        }
-    }
-
-    @Test
-    public void testCreateChannel_alreadyExists() throws Exception {
-        long[] vibration = new long[]{100, 67, 145, 156};
-        NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        channel.setVibrationPattern(vibration);
-
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-
-        NotificationChannel newChannel = new NotificationChannel(
-                channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
-        newChannel.setVibrationPattern(new long[]{100});
-
-        mHelper.createNotificationChannel(PKG, UID, newChannel, true, false);
-
-        // Old settings not overridden
-        compareChannels(channel,
-                mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false));
-    }
-
-    @Test
-    public void testCreateChannel_noOverrideSound() throws Exception {
-        Uri sound = new Uri.Builder().scheme("test").build();
-        final NotificationChannel channel = new NotificationChannel("id2", "name2",
-                 NotificationManager.IMPORTANCE_DEFAULT);
-        channel.setSound(sound, mAudioAttributes);
-        mHelper.createNotificationChannel(PKG, UID, channel, true, false);
-        assertEquals(sound, mHelper.getNotificationChannel(
-                PKG, UID, channel.getId(), false).getSound());
-    }
-
-    @Test
-    public void testPermanentlyDeleteChannels() throws Exception {
-        NotificationChannel channel1 =
-                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
-        NotificationChannel channel2 =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-
-        mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-        mHelper.createNotificationChannel(PKG, UID, channel2, false, false);
-
-        mHelper.permanentlyDeleteNotificationChannels(PKG, UID);
-
-        // Only default channel remains
-        assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
-    }
-
-    @Test
-    public void testDeleteGroup() throws Exception {
-        NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted");
-        NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted");
-        NotificationChannel nonGroupedNonDeletedChannel =
-                new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH);
-        NotificationChannel groupedButNotDeleted =
-                new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT);
-        groupedButNotDeleted.setGroup("not");
-        NotificationChannel groupedAndDeleted =
-                new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT);
-        groupedAndDeleted.setGroup("totally");
-
-        mHelper.createNotificationChannelGroup(PKG, UID, notDeleted, true);
-        mHelper.createNotificationChannelGroup(PKG, UID, deleted, true);
-        mHelper.createNotificationChannel(PKG, UID, nonGroupedNonDeletedChannel, true, false);
-        mHelper.createNotificationChannel(PKG, UID, groupedAndDeleted, true, false);
-        mHelper.createNotificationChannel(PKG, UID, groupedButNotDeleted, true, false);
-
-        mHelper.deleteNotificationChannelGroup(PKG, UID, deleted.getId());
-
-        assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG, UID));
-        assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG, UID));
-
-        assertNull(mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), false));
-        compareChannels(groupedAndDeleted,
-                mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), true));
-
-        compareChannels(groupedButNotDeleted,
-                mHelper.getNotificationChannel(PKG, UID, groupedButNotDeleted.getId(), false));
-        compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel(
-                PKG, UID, nonGroupedNonDeletedChannel.getId(), false));
-
-        // notDeleted
-        assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID).size());
-
-        verify(mHandler, never()).requestSort();
-    }
-
-    @Test
-    public void testOnUserRemoved() throws Exception {
-        int[] user0Uids = {98, 235, 16, 3782};
-        int[] user1Uids = new int[user0Uids.length];
-        for (int i = 0; i < user0Uids.length; i++) {
-            user1Uids[i] = UserHandle.PER_USER_RANGE + user0Uids[i];
-
-            final ApplicationInfo legacy = new ApplicationInfo();
-            legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
-            when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy);
-
-            // create records with the default channel for all user 0 and user 1 uids
-            mHelper.getImportance(PKG, user0Uids[i]);
-            mHelper.getImportance(PKG, user1Uids[i]);
-        }
-
-        mHelper.onUserRemoved(1);
-
-        // user 0 records remain
-        for (int i = 0; i < user0Uids.length; i++) {
-            assertEquals(1,
-                    mHelper.getNotificationChannels(PKG, user0Uids[i], false).getList().size());
-        }
-        // user 1 records are gone
-        for (int i = 0; i < user1Uids.length; i++) {
-            assertEquals(0,
-                    mHelper.getNotificationChannels(PKG, user1Uids[i], false).getList().size());
-        }
-    }
-
-    @Test
-    public void testOnPackageChanged_packageRemoval() throws Exception {
-        // Deleted
-        NotificationChannel channel1 =
-                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
-        mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-
-        mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
-
-        assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
-
-        // Not deleted
-        mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-
-        mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
-        assertEquals(2, mHelper.getNotificationChannels(PKG, UID, false).getList().size());
-    }
-
-    @Test
-    public void testOnPackageChanged_packageRemoval_importance() throws Exception {
-        mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_HIGH);
-
-        mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
-
-        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID));
-    }
-
-    @Test
-    public void testOnPackageChanged_packageRemoval_groups() throws Exception {
-        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
-        NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
-
-        mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
-
-        assertEquals(0,
-                mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList().size());
-    }
-
-    @Test
-    public void testOnPackageChange_downgradeTargetSdk() throws Exception {
-        // create channel as api 26
-        mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true, false);
-
-        // install new app version targeting 25
-        final ApplicationInfo legacy = new ApplicationInfo();
-        legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
-        when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(legacy);
-        mHelper.onPackagesChanged(
-                false, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2});
-
-        // make sure the default channel was readded
-        //assertEquals(2, mHelper.getNotificationChannels(UPDATED_PKG, UID2, false).getList().size());
-        assertNotNull(mHelper.getNotificationChannel(
-                UPDATED_PKG, UID2, NotificationChannel.DEFAULT_CHANNEL_ID, false));
-    }
-
-    @Test
-    public void testRecordDefaults() throws Exception {
-        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID));
-        assertEquals(true, mHelper.canShowBadge(PKG, UID));
-        assertEquals(1, mHelper.getNotificationChannels(PKG, UID, false).getList().size());
-    }
-
-    @Test
-    public void testCreateGroup() throws Exception {
-        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
-        assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG, UID).iterator().next());
-        verify(mHandler, never()).requestSort();
-    }
-
-    @Test
-    public void testCannotCreateChannel_badGroup() throws Exception {
-        NotificationChannel channel1 =
-                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
-        channel1.setGroup("garbage");
-        try {
-            mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-            fail("Created a channel with a bad group");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    @Test
-    public void testCannotCreateChannel_goodGroup() throws Exception {
-        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
-        NotificationChannel channel1 =
-                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
-        channel1.setGroup(ncg.getId());
-        mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-
-        assertEquals(ncg.getId(),
-                mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false).getGroup());
-    }
-
-    @Test
-    public void testGetChannelGroups() throws Exception {
-        NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s");
-        mHelper.createNotificationChannelGroup(PKG, UID, unused, true);
-        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
-        NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
-
-        NotificationChannel channel1 =
-                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
-        channel1.setGroup(ncg.getId());
-        mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-        NotificationChannel channel1a =
-                new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH);
-        channel1a.setGroup(ncg.getId());
-        mHelper.createNotificationChannel(PKG, UID, channel1a, true, false);
-
-        NotificationChannel channel2 =
-                new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH);
-        channel2.setGroup(ncg2.getId());
-        mHelper.createNotificationChannel(PKG, UID, channel2, true, false);
-
-        NotificationChannel channel3 =
-                new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH);
-        mHelper.createNotificationChannel(PKG, UID, channel3, true, false);
-
-        List<NotificationChannelGroup> actual =
-                mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList();
-        assertEquals(3, actual.size());
-        for (NotificationChannelGroup group : actual) {
-            if (group.getId() == null) {
-                assertEquals(2, group.getChannels().size()); // misc channel too
-                assertTrue(channel3.getId().equals(group.getChannels().get(0).getId())
-                        || channel3.getId().equals(group.getChannels().get(1).getId()));
-            } else if (group.getId().equals(ncg.getId())) {
-                assertEquals(2, group.getChannels().size());
-                if (group.getChannels().get(0).getId().equals(channel1.getId())) {
-                    assertTrue(group.getChannels().get(1).getId().equals(channel1a.getId()));
-                } else if (group.getChannels().get(0).getId().equals(channel1a.getId())) {
-                    assertTrue(group.getChannels().get(1).getId().equals(channel1.getId()));
-                } else {
-                    fail("expected channel not found");
-                }
-            } else if (group.getId().equals(ncg2.getId())) {
-                assertEquals(1, group.getChannels().size());
-                assertEquals(channel2.getId(), group.getChannels().get(0).getId());
-            }
-        }
-    }
-
-    @Test
-    public void testGetChannelGroups_noSideEffects() throws Exception {
-        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
-        mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
-
-        NotificationChannel channel1 =
-                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
-        channel1.setGroup(ncg.getId());
-        mHelper.createNotificationChannel(PKG, UID, channel1, true, false);
-        mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList();
-
-        channel1.setImportance(IMPORTANCE_LOW);
-        mHelper.updateNotificationChannel(PKG, UID, channel1, true);
-
-        List<NotificationChannelGroup> actual =
-                mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList();
-
-        assertEquals(2, actual.size());
-        for (NotificationChannelGroup group : actual) {
-            if (Objects.equals(group.getId(), ncg.getId())) {
-                assertEquals(1, group.getChannels().size());
-            }
-        }
-    }
-
-    @Test
-    public void testCreateChannel_updateName() throws Exception {
-        NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
-        mHelper.createNotificationChannel(PKG, UID, nc, true, false);
-        NotificationChannel actual = mHelper.getNotificationChannel(PKG, UID, "id", false);
-        assertEquals("hello", actual.getName());
-
-        nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH);
-        mHelper.createNotificationChannel(PKG, UID, nc, true, false);
-
-        actual = mHelper.getNotificationChannel(PKG, UID, "id", false);
-        assertEquals("goodbye", actual.getName());
-        assertEquals(IMPORTANCE_DEFAULT, actual.getImportance());
-
-        verify(mHandler, times(1)).requestSort();
-    }
-
-    @Test
-    public void testCreateChannel_addToGroup() throws Exception {
-        NotificationChannelGroup group = new NotificationChannelGroup("group", "");
-        mHelper.createNotificationChannelGroup(PKG, UID, group, true);
-        NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
-        mHelper.createNotificationChannel(PKG, UID, nc, true, false);
-        NotificationChannel actual = mHelper.getNotificationChannel(PKG, UID, "id", false);
-        assertNull(actual.getGroup());
-
-        nc = new NotificationChannel("id", "hello", IMPORTANCE_HIGH);
-        nc.setGroup(group.getId());
-        mHelper.createNotificationChannel(PKG, UID, nc, true, false);
-
-        actual = mHelper.getNotificationChannel(PKG, UID, "id", false);
-        assertNotNull(actual.getGroup());
-        assertEquals(IMPORTANCE_DEFAULT, actual.getImportance());
-
-        verify(mHandler, times(1)).requestSort();
-    }
-
-    @Test
-    public void testDumpChannelsJson() throws Exception {
-        final ApplicationInfo upgrade = new ApplicationInfo();
-        upgrade.targetSdkVersion = Build.VERSION_CODES.O;
-        try {
-            when(mPm.getApplicationInfoAsUser(
-                    anyString(), anyInt(), anyInt())).thenReturn(upgrade);
-        } catch (PackageManager.NameNotFoundException e) {
-        }
-        ArrayMap<String, Integer> expectedChannels = new ArrayMap<>();
-        int numPackages = ThreadLocalRandom.current().nextInt(1, 5);
-        for (int i = 0; i < numPackages; i++) {
-            String pkgName = "pkg" + i;
-            int numChannels = ThreadLocalRandom.current().nextInt(1, 10);
-            for (int j = 0; j < numChannels; j++) {
-                mHelper.createNotificationChannel(pkgName, UID,
-                        new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true, false);
-            }
-            expectedChannels.put(pkgName, numChannels);
-        }
-
-        // delete the first channel of the first package
-        String pkg = expectedChannels.keyAt(0);
-        mHelper.deleteNotificationChannel("pkg" + 0, UID, "0");
-        // dump should not include deleted channels
-        int count = expectedChannels.get(pkg);
-        expectedChannels.put(pkg, count - 1);
-
-        JSONArray actual = mHelper.dumpChannelsJson(new NotificationManagerService.DumpFilter());
-        assertEquals(numPackages, actual.length());
-        for (int i = 0; i < numPackages; i++) {
-            JSONObject object = actual.getJSONObject(i);
-            assertTrue(expectedChannels.containsKey(object.get("packageName")));
-            assertEquals(expectedChannels.get(object.get("packageName")).intValue(),
-                    object.getInt("channelCount"));
-        }
-    }
-
-    @Test
-    public void testBadgingOverrideTrue() throws Exception {
-        Secure.putIntForUser(getContext().getContentResolver(),
-                Secure.NOTIFICATION_BADGING, 1,
-                USER.getIdentifier());
-        mHelper.updateBadgingEnabled(); // would be called by settings observer
-        assertTrue(mHelper.badgingEnabled(USER));
-    }
-
-    @Test
-    public void testBadgingOverrideFalse() throws Exception {
-        Secure.putIntForUser(getContext().getContentResolver(),
-                Secure.NOTIFICATION_BADGING, 0,
-                USER.getIdentifier());
-        mHelper.updateBadgingEnabled(); // would be called by settings observer
-        assertFalse(mHelper.badgingEnabled(USER));
-    }
-
-    @Test
-    public void testBadgingForUserAll() throws Exception {
-        try {
-            mHelper.badgingEnabled(UserHandle.ALL);
-        } catch (Exception e) {
-            fail("just don't throw");
-        }
-    }
-
-    @Test
-    public void testBadgingOverrideUserIsolation() throws Exception {
-        Secure.putIntForUser(getContext().getContentResolver(),
-                Secure.NOTIFICATION_BADGING, 0,
-                USER.getIdentifier());
-        Secure.putIntForUser(getContext().getContentResolver(),
-                Secure.NOTIFICATION_BADGING, 1,
-                USER2.getIdentifier());
-        mHelper.updateBadgingEnabled(); // would be called by settings observer
-        assertFalse(mHelper.badgingEnabled(USER));
-        assertTrue(mHelper.badgingEnabled(USER2));
-    }
-
-    @Test
-    public void testOnLocaleChanged_updatesDefaultChannels() throws Exception {
-        String newLabel = "bananas!";
-        final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID,
-                NotificationChannel.DEFAULT_CHANNEL_ID, false);
-        assertFalse(newLabel.equals(defaultChannel.getName()));
-
-        Resources res = mock(Resources.class);
-        when(mContext.getResources()).thenReturn(res);
-        when(res.getString(com.android.internal.R.string.default_notification_channel_label))
-                .thenReturn(newLabel);
-
-        mHelper.onLocaleChanged(mContext, USER.getIdentifier());
-
-        assertEquals(newLabel, mHelper.getNotificationChannel(PKG, UID,
-                NotificationChannel.DEFAULT_CHANNEL_ID, false).getName());
-    }
-
-    @Test
-    public void testIsGroupBlocked_noGroup() throws Exception {
-        assertFalse(mHelper.isGroupBlocked(PKG, UID, null));
-
-        assertFalse(mHelper.isGroupBlocked(PKG, UID, "non existent group"));
-    }
-
-    @Test
-    public void testIsGroupBlocked_notBlocked() throws Exception {
-        NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
-        mHelper.createNotificationChannelGroup(PKG, UID, group, true);
-
-        assertFalse(mHelper.isGroupBlocked(PKG, UID, group.getId()));
-    }
-
-    @Test
-    public void testIsGroupBlocked_blocked() throws Exception {
-        NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
-        mHelper.createNotificationChannelGroup(PKG, UID, group, true);
-        group.setBlocked(true);
-        mHelper.createNotificationChannelGroup(PKG, UID, group, false);
-
-        assertTrue(mHelper.isGroupBlocked(PKG, UID, group.getId()));
-    }
-
-    @Test
-    public void testIsGroup_appCannotResetBlock() throws Exception {
-        NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
-        mHelper.createNotificationChannelGroup(PKG, UID, group, true);
-        NotificationChannelGroup group2 = group.clone();
-        group2.setBlocked(true);
-        mHelper.createNotificationChannelGroup(PKG, UID, group2, false);
-        assertTrue(mHelper.isGroupBlocked(PKG, UID, group.getId()));
-
-        NotificationChannelGroup group3 = group.clone();
-        group3.setBlocked(false);
-        mHelper.createNotificationChannelGroup(PKG, UID, group3, true);
-        assertTrue(mHelper.isGroupBlocked(PKG, UID, group.getId()));
-    }
-
-    @Test
-    public void testGetNotificationChannelGroupWithChannels() throws Exception {
-        NotificationChannelGroup group = new NotificationChannelGroup("group", "");
-        NotificationChannelGroup other = new NotificationChannelGroup("something else", "");
-        mHelper.createNotificationChannelGroup(PKG, UID, group, true);
-        mHelper.createNotificationChannelGroup(PKG, UID, other, true);
-
-        NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
-        a.setGroup(group.getId());
-        NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_DEFAULT);
-        b.setGroup(other.getId());
-        NotificationChannel c = new NotificationChannel("c", "c", IMPORTANCE_DEFAULT);
-        c.setGroup(group.getId());
-        NotificationChannel d = new NotificationChannel("d", "d", IMPORTANCE_DEFAULT);
-
-        mHelper.createNotificationChannel(PKG, UID, a, true, false);
-        mHelper.createNotificationChannel(PKG, UID, b, true, false);
-        mHelper.createNotificationChannel(PKG, UID, c, true, false);
-        mHelper.createNotificationChannel(PKG, UID, d, true, false);
-        mHelper.deleteNotificationChannel(PKG, UID, c.getId());
-
-        NotificationChannelGroup retrieved = mHelper.getNotificationChannelGroupWithChannels(
-                PKG, UID, group.getId(), true);
-        assertEquals(2, retrieved.getChannels().size());
-        compareChannels(a, findChannel(retrieved.getChannels(), a.getId()));
-        compareChannels(c, findChannel(retrieved.getChannels(), c.getId()));
-
-        retrieved = mHelper.getNotificationChannelGroupWithChannels(
-                PKG, UID, group.getId(), false);
-        assertEquals(1, retrieved.getChannels().size());
-        compareChannels(a, findChannel(retrieved.getChannels(), a.getId()));
-    }
-
-    @Test
-    public void testAndroidPkgCannotBypassDnd_creation() {
-        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
-        test.setBypassDnd(true);
-
-        mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, test, true, false);
-
-        assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false)
-                .canBypassDnd());
-    }
-
-    @Test
-    public void testDndPkgCanBypassDnd_creation() {
-        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
-        test.setBypassDnd(true);
-
-        mHelper.createNotificationChannel(PKG, UID, test, true, true);
-
-        assertTrue(mHelper.getNotificationChannel(PKG, UID, "A", false).canBypassDnd());
-    }
-
-    @Test
-    public void testNormalPkgCannotBypassDnd_creation() {
-        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
-        test.setBypassDnd(true);
-
-        mHelper.createNotificationChannel(PKG, 1000, test, true, false);
-
-        assertFalse(mHelper.getNotificationChannel(PKG, 1000, "A", false).canBypassDnd());
-    }
-
-    @Test
-    public void testAndroidPkgCannotBypassDnd_update() throws Exception {
-        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
-        mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, test, true, false);
-
-        NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW);
-        update.setBypassDnd(true);
-        mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, update, true, false);
-
-        assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false)
-                .canBypassDnd());
-    }
-
-    @Test
-    public void testDndPkgCanBypassDnd_update() throws Exception {
-        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
-        mHelper.createNotificationChannel(PKG, UID, test, true, true);
-
-        NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW);
-        update.setBypassDnd(true);
-        mHelper.createNotificationChannel(PKG, UID, update, true, true);
-
-        assertTrue(mHelper.getNotificationChannel(PKG, UID, "A", false).canBypassDnd());
-    }
-
-    @Test
-    public void testNormalPkgCannotBypassDnd_update() {
-        NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
-        mHelper.createNotificationChannel(PKG, 1000, test, true, false);
-        NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW);
-        update.setBypassDnd(true);
-        mHelper.createNotificationChannel(PKG, 1000, update, true, false);
-        assertFalse(mHelper.getNotificationChannel(PKG, 1000, "A", false).canBypassDnd());
-    }
-
-    @Test
-    public void testGetBlockedAppCount_noApps() {
-        assertEquals(0, mHelper.getBlockedAppCount(0));
-    }
-
-    @Test
-    public void testGetBlockedAppCount_noAppsForUserId() {
-        mHelper.setEnabled(PKG, 100, false);
-        assertEquals(0, mHelper.getBlockedAppCount(9));
-    }
-
-    @Test
-    public void testGetBlockedAppCount_appsForUserId() {
-        mHelper.setEnabled(PKG, 1020, false);
-        mHelper.setEnabled(PKG, 1030, false);
-        mHelper.setEnabled(PKG, 1060, false);
-        mHelper.setEnabled(PKG, 1000, true);
-        assertEquals(3, mHelper.getBlockedAppCount(0));
-    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
index 96ac935..110e3fe 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
@@ -333,6 +333,17 @@
     }
 
     @Test
+    public void testMaybeSetNextAlarm_expiredOldAlarm() {
+        mScheduleInfo.exitAtAlarm = true;
+        mScheduleInfo.nextAlarm = 998;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
+
+        mScheduleCalendar.maybeSetNextAlarm(1000, 1001);
+
+        assertEquals(1001, mScheduleInfo.nextAlarm);
+    }
+
+    @Test
     @FlakyTest
     public void testIsInSchedule_inScheduleOvernight() {
         Calendar cal = new GregorianCalendar();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
index c0bd7cc..d335450 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
@@ -171,4 +171,17 @@
 
         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_OFF, config, r));
     }
+
+    @Test
+    public void testSuppressAnything_bypass_ZenModeOn() {
+        NotificationRecord r = getNotificationRecord();
+        r.setCriticality(CriticalNotificationExtractor.CRITICAL);
+        when(r.sbn.getPackageName()).thenReturn("bananas");
+        ZenModeConfig config = mock(ZenModeConfig.class);
+
+        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, config, r));
+
+        r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
+        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, config, r));
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index afc1263..91f4bc8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -38,6 +38,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.NotificationManager;
 import android.content.ComponentName;
@@ -49,8 +50,10 @@
 import android.media.AudioManagerInternal;
 import android.media.VolumePolicy;
 import android.media.AudioSystem;
+import android.net.Uri;
 import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.service.notification.Condition;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.ScheduleInfo;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -61,9 +64,9 @@
 
 import com.android.internal.R;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.server.notification.ManagedServices.UserProfiles;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.UiServiceTestCase;
-import android.util.Slog;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -83,7 +86,7 @@
 @TestableLooper.RunWithLooper
 public class ZenModeHelperTest extends UiServiceTestCase {
 
-    @Mock ConditionProviders mConditionProviders;
+    ConditionProviders mConditionProviders;
     @Mock NotificationManager mNotificationManager;
     @Mock private Resources mResources;
     private TestableLooper mTestableLooper;
@@ -103,6 +106,9 @@
         when(mResources.getString(R.string.zen_mode_default_events_name)).thenReturn("events");
         when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
 
+        mConditionProviders = new ConditionProviders(mContext, new UserProfiles(),
+                AppGlobals.getPackageManager());
+        mConditionProviders.addSystemProvider(new CountdownConditionProvider());
         mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(),
                 mConditionProviders));
     }
@@ -116,7 +122,7 @@
         mZenModeHelperSpy.writeXml(serializer, forBackup, version);
         serializer.endDocument();
         serializer.flush();
-        mZenModeHelperSpy.setConfig(new ZenModeConfig(), "writing xml");
+        mZenModeHelperSpy.setConfig(new ZenModeConfig(), null, "writing xml");
         return baos;
     }
 
@@ -290,23 +296,39 @@
 
     @Test
     public void testZenUpgradeNotification() {
-        // shows zen upgrade notification if stored settings says to shows, boot is completed
+        // shows zen upgrade notification if stored settings says to shows,
+        // zen has not been updated, boot is completed
         // and we're setting zen mode on
-        Settings.Global.putInt(mContentResolver, Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0);
         mZenModeHelperSpy.mIsBootComplete = true;
         mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
 
         verify(mZenModeHelperSpy, times(1)).createZenUpgradeNotification();
         verify(mNotificationManager, times(1)).notify(eq(ZenModeHelper.TAG),
                 eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
-        assertEquals(0, Settings.Global.getInt(mContentResolver,
-                Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, -1));
+        assertEquals(0, Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, -1));
     }
 
     @Test
     public void testNoZenUpgradeNotification() {
         // doesn't show upgrade notification if stored settings says don't show
-        Settings.Global.putInt(mContentResolver, Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0);
+        mZenModeHelperSpy.mIsBootComplete = true;
+        mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+
+        verify(mZenModeHelperSpy, never()).createZenUpgradeNotification();
+        verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG),
+                eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
+    }
+
+    @Test
+    public void testNoZenUpgradeNotificationZenUpdated() {
+        // doesn't show upgrade notification since zen was already updated
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 1);
         mZenModeHelperSpy.mIsBootComplete = true;
         mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
 
@@ -615,10 +637,40 @@
     }
 
     @Test
-    public void testReadXml() throws Exception {
+    public void testReadXmlRestore() throws Exception {
         setupZenConfig();
 
-        // automatic zen rule is enabled on upgrade so rules should not be overriden by default
+        // one enabled automatic rule
+        ArrayMap<String, ZenModeConfig.ZenRule> automaticRules = new ArrayMap<>();
+        ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo customRuleInfo = new ScheduleInfo();
+        customRule.enabled = true;
+        customRule.creationTime = 0;
+        customRule.id = "customRule";
+        customRule.name = "Custom Rule";
+        customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        customRule.component = new ComponentName("test", "test");
+        customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
+        automaticRules.put("customRule", customRule);
+        mZenModeHelperSpy.mConfig.automaticRules = automaticRules;
+
+        ZenModeConfig original = mZenModeHelperSpy.mConfig.copy();
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(false, null);
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, true);
+        assertEquals(original.hashCode(), mZenModeHelperSpy.mConfig.hashCode());
+        assertEquals(original, mZenModeHelperSpy.mConfig);
+    }
+
+    @Test
+    public void testReadXmlRulesNotOverriden() throws Exception {
+        setupZenConfig();
+
+        // automatic zen rule is enabled on upgrade so rules should not be overriden to default
         ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRule = new ArrayMap<>();
         ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
         final ScheduleInfo weeknights = new ScheduleInfo();
@@ -629,8 +681,6 @@
         enabledAutoRule.put("customRule", customRule);
         mZenModeHelperSpy.mConfig.automaticRules = enabledAutoRule;
 
-        ZenModeConfig expected = mZenModeHelperSpy.mConfig.copy();
-
         // set previous version
         ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
         XmlPullParser parser = Xml.newPullParser();
@@ -648,7 +698,7 @@
         String xml = "<zen version=\"6\" user=\"0\">\n"
                 + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
                 + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
-                + "visualScreenOff=\"false\" alarms=\"true\" "
+                + "visualScreenOff=\"true\" alarms=\"true\" "
                 + "media=\"true\" system=\"false\" />\n"
                 + "<disallow visualEffects=\"511\" />"
                 + "</zen>";
@@ -664,7 +714,7 @@
         xml = "<zen version=\"6\" user=\"0\">\n"
                 + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
                 + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
-                + "visualScreenOn=\"false\" alarms=\"true\" "
+                + "visualScreenOn=\"true\" alarms=\"true\" "
                 + "media=\"true\" system=\"false\" />\n"
                 + "<disallow visualEffects=\"511\" />"
                 + "</zen>";
@@ -683,7 +733,7 @@
         String xml = "<zen version=\"6\" user=\"0\">\n"
                 + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
                 + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
-                + "visualScreenOff=\"false\" visualScreenOn=\"false\" alarms=\"true\" "
+                + "visualScreenOff=\"true\" visualScreenOn=\"true\" alarms=\"true\" "
                 + "media=\"true\" system=\"false\" />\n"
                 + "<disallow visualEffects=\"511\" />"
                 + "</zen>";
@@ -702,7 +752,7 @@
         String xml = "<zen version=\"6\" user=\"0\">\n"
                 + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
                 + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
-                + "visualScreenOff=\"true\" visualScreenOn=\"true\" alarms=\"true\" "
+                + "visualScreenOff=\"false\" visualScreenOn=\"false\" alarms=\"true\" "
                 + "media=\"true\" system=\"false\" />\n"
                 + "<disallow visualEffects=\"511\" />"
                 + "</zen>";
@@ -721,7 +771,7 @@
         xml = "<zen version=\"6\" user=\"0\">\n"
                 + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
                 + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
-                + "visualScreenOff=\"false\" visualScreenOn=\"true\" alarms=\"true\" "
+                + "visualScreenOff=\"true\" visualScreenOn=\"false\" alarms=\"true\" "
                 + "media=\"true\" system=\"false\" />\n"
                 + "<disallow visualEffects=\"511\" />"
                 + "</zen>";
@@ -737,7 +787,7 @@
         xml = "<zen version=\"6\" user=\"0\">\n"
                 + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
                 + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
-                + "visualScreenOff=\"true\" visualScreenOn=\"false\" alarms=\"true\" "
+                + "visualScreenOff=\"false\" visualScreenOn=\"true\" alarms=\"true\" "
                 + "media=\"true\" system=\"false\" />\n"
                 + "<disallow visualEffects=\"511\" />"
                 + "</zen>";
@@ -756,7 +806,8 @@
     public void testReadXmlResetDefaultRules() throws Exception {
         setupZenConfig();
 
-        // no enabled automatic zen rule, so rules should be overriden by default rules
+        // no enabled automatic zen rules and no default rules
+        // so rules should be overriden by default rules
         mZenModeHelperSpy.mConfig.automaticRules = new ArrayMap<>();
 
         // set previous version
@@ -782,17 +833,17 @@
     public void testReadXmlAllDisabledRulesResetDefaultRules() throws Exception {
         setupZenConfig();
 
-        // all automatic zen rules are diabled on upgrade so rules should be overriden by default
-        // rules
-        ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRule = new ArrayMap<>();
+        // all automatic zen rules are disabled on upgrade (and default rules don't already exist)
+        // so rules should be overriden by default rules
+        ArrayMap<String, ZenModeConfig.ZenRule> disabledAutoRule = new ArrayMap<>();
         ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
         final ScheduleInfo weeknights = new ScheduleInfo();
         customRule.enabled = false;
         customRule.name = "Custom Rule";
         customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
-        enabledAutoRule.put("customRule", customRule);
-        mZenModeHelperSpy.mConfig.automaticRules = enabledAutoRule;
+        disabledAutoRule.put("customRule", customRule);
+        mZenModeHelperSpy.mConfig.automaticRules = disabledAutoRule;
 
         // set previous version
         ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
@@ -813,6 +864,131 @@
         setupZenConfigMaintained();
     }
 
+    @Test
+    public void testReadXmlOnlyOneDefaultRuleExists() throws Exception {
+        setupZenConfig();
+
+        // all automatic zen rules are disabled on upgrade and only one default rule exists
+        // so rules should be overriden to the default rules
+        ArrayMap<String, ZenModeConfig.ZenRule> automaticRules = new ArrayMap<>();
+        ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo customRuleInfo = new ScheduleInfo();
+        customRule.enabled = false;
+        customRule.name = "Custom Rule";
+        customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
+        automaticRules.put("customRule", customRule);
+
+        ZenModeConfig.ZenRule defaultScheduleRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo defaultScheduleRuleInfo = new ScheduleInfo();
+        defaultScheduleRule.enabled = false;
+        defaultScheduleRule.name = "Default Schedule Rule";
+        defaultScheduleRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        defaultScheduleRule.conditionId = ZenModeConfig.toScheduleConditionId(
+                defaultScheduleRuleInfo);
+        defaultScheduleRule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
+        automaticRules.put(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID, defaultScheduleRule);
+
+        mZenModeHelperSpy.mConfig.automaticRules = automaticRules;
+
+        // set previous version
+        ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        // check default rules
+        ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelperSpy.mConfig.automaticRules;
+        assertTrue(rules.size() != 0);
+        for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) {
+            assertTrue(rules.containsKey(defaultId));
+        }
+        assertFalse(rules.containsKey("customRule"));
+
+        setupZenConfigMaintained();
+    }
+
+    @Test
+    public void testReadXmlDefaultRulesExist() throws Exception {
+        setupZenConfig();
+
+        // Default rules exist so rules should not be overridden by defaults
+        ArrayMap<String, ZenModeConfig.ZenRule> automaticRules = new ArrayMap<>();
+        ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo customRuleInfo = new ScheduleInfo();
+        customRule.enabled = false;
+        customRule.name = "Custom Rule";
+        customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
+        automaticRules.put("customRule", customRule);
+
+        ZenModeConfig.ZenRule defaultScheduleRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo defaultScheduleRuleInfo = new ScheduleInfo();
+        defaultScheduleRule.enabled = false;
+        defaultScheduleRule.name = "Default Schedule Rule";
+        defaultScheduleRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        defaultScheduleRule.conditionId = ZenModeConfig.toScheduleConditionId(
+                defaultScheduleRuleInfo);
+        defaultScheduleRule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
+        automaticRules.put(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID, defaultScheduleRule);
+
+        ZenModeConfig.ZenRule defaultEventRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo defaultEventRuleInfo = new ScheduleInfo();
+        defaultEventRule.enabled = false;
+        defaultEventRule.name = "Default Event Rule";
+        defaultEventRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        defaultEventRule.conditionId = ZenModeConfig.toScheduleConditionId(
+                defaultEventRuleInfo);
+        defaultEventRule.id = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
+        automaticRules.put(ZenModeConfig.EVENTS_DEFAULT_RULE_ID, defaultEventRule);
+
+        mZenModeHelperSpy.mConfig.automaticRules = automaticRules;
+
+        // set previous version
+        ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        // check default rules
+        ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelperSpy.mConfig.automaticRules;
+        assertTrue(rules.size() != 0);
+        for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) {
+            assertTrue(rules.containsKey(defaultId));
+        }
+        assertTrue(rules.containsKey("customRule"));
+
+        setupZenConfigMaintained();
+    }
+
+    @Test
+    public void testCountdownConditionSubscription() throws Exception {
+        ZenModeConfig config = new ZenModeConfig();
+        mZenModeHelperSpy.mConfig = config;
+        mZenModeHelperSpy.mConditions.evaluateConfig(mZenModeHelperSpy.mConfig, null, true);
+        assertEquals(0, mZenModeHelperSpy.mConditions.mSubscriptions.size());
+
+        mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
+        Uri conditionId = ZenModeConfig.toCountdownConditionId(9000000, false);
+        mZenModeHelperSpy.mConfig.manualRule.conditionId = conditionId;
+        mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("android",
+                CountdownConditionProvider.class.getName());
+        mZenModeHelperSpy.mConfig.manualRule.condition = new Condition(conditionId, "", "", "", 0,
+                Condition.STATE_TRUE, Condition.FLAG_RELEVANT_NOW);
+        mZenModeHelperSpy.mConfig.manualRule.enabled = true;
+        ZenModeConfig originalConfig = mZenModeHelperSpy.mConfig.copy();
+
+        mZenModeHelperSpy.mConditions.evaluateConfig(mZenModeHelperSpy.mConfig, null, true);
+
+        assertEquals(true, ZenModeConfig.isValidCountdownConditionId(conditionId));
+        assertEquals(originalConfig, mZenModeHelperSpy.mConfig);
+        assertEquals(1, mZenModeHelperSpy.mConditions.mSubscriptions.size());
+    }
+
     private void setupZenConfig() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         mZenModeHelperSpy.mConfig.allowAlarms = false;
@@ -824,12 +1000,7 @@
         mZenModeHelperSpy.mConfig.allowEvents = true;
         mZenModeHelperSpy.mConfig.allowRepeatCallers= true;
         mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
-        mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
-        mZenModeHelperSpy.mConfig.manualRule.zenMode =
-                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("a", "a");
-        mZenModeHelperSpy.mConfig.manualRule.enabled = true;
-        mZenModeHelperSpy.mConfig.manualRule.snoozing = true;
+        mZenModeHelperSpy.mConfig.manualRule = null;
     }
 
     private void setupZenConfigMaintained() {
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index 3c4e333..82e0fbe 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -1,16 +1,16 @@
 package com.android.server.slice;
 
+import static android.testing.TestableContentResolver.UNSTABLE;
+
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -71,11 +71,12 @@
         mSliceService = mock(SliceManagerService.class);
         when(mSliceService.getContext()).thenReturn(mContext);
         when(mSliceService.getLock()).thenReturn(new Object());
-        when(mSliceService.getHandler()).thenReturn(new Handler(TestableLooper.get(this).getLooper()));
+        when(mSliceService.getHandler()).thenReturn(
+                new Handler(TestableLooper.get(this).getLooper()));
         mContentProvider = mock(ContentProvider.class);
         mIContentProvider = mock(IContentProvider.class);
         when(mContentProvider.getIContentProvider()).thenReturn(mIContentProvider);
-        mContext.getContentResolver().addProvider(AUTH, mContentProvider);
+        mContext.getContentResolver().addProvider(AUTH, mContentProvider, UNSTABLE);
         mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI, "pkg");
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
index 1db8967..6d4f5f8 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -120,7 +120,8 @@
                 .thenReturn(PERMISSION_DENIED);
         when(mContextSpy.checkPermission("perm2", Process.myPid(), Process.myUid()))
                 .thenReturn(PERMISSION_GRANTED);
-        mService.checkSlicePermission(TEST_URI, mContext.getPackageName(), Process.myPid(),
+        mService.checkSlicePermission(TEST_URI, mContext.getPackageName(),
+                mContext.getPackageName(), Process.myPid(),
                 Process.myUid(), testPerms);
 
         verify(mContextSpy).checkPermission(eq("perm1"), eq(Process.myPid()), eq(Process.myUid()));
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 9c62700..77cb749 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -1452,6 +1452,23 @@
         TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw);
         pw.println();
 
+        pw.print("  mStrongUsageTimeoutMillis=");
+        TimeUtils.formatDuration(mStrongUsageTimeoutMillis, pw);
+        pw.println();
+        pw.print("  mNotificationSeenTimeoutMillis=");
+        TimeUtils.formatDuration(mNotificationSeenTimeoutMillis, pw);
+        pw.println();
+        pw.print("  mSyncAdapterTimeoutMillis=");
+        TimeUtils.formatDuration(mSyncAdapterTimeoutMillis, pw);
+        pw.println();
+        pw.print("  mSystemInteractionTimeoutMillis=");
+        TimeUtils.formatDuration(mSystemInteractionTimeoutMillis, pw);
+        pw.println();
+
+        pw.print("  mPredictionTimeoutMillis=");
+        TimeUtils.formatDuration(mPredictionTimeoutMillis, pw);
+        pw.println();
+
         pw.print("  mExemptedSyncScheduledNonDozeTimeoutMillis=");
         TimeUtils.formatDuration(mExemptedSyncScheduledNonDozeTimeoutMillis, pw);
         pw.println();
@@ -1462,6 +1479,14 @@
         TimeUtils.formatDuration(mExemptedSyncStartTimeoutMillis, pw);
         pw.println();
 
+        pw.print("  mSystemUpdateUsageTimeoutMillis=");
+        TimeUtils.formatDuration(mSystemUpdateUsageTimeoutMillis, pw);
+        pw.println();
+
+        pw.print("  mStableChargingThresholdMillis=");
+        TimeUtils.formatDuration(mStableChargingThresholdMillis, pw);
+        pw.println();
+
         pw.println();
         pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
         pw.print(" mAppIdleTempParoled="); pw.print(mAppIdleTempParoled);
@@ -1910,4 +1935,3 @@
         }
     }
 }
-
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 0dce738..4b7e21f 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -27,7 +27,9 @@
 
 import java.util.List;
 
-class IntervalStats {
+import com.android.internal.annotations.VisibleForTesting;
+
+public class IntervalStats {
     public long beginTime;
     public long endTime;
     public long lastTimeSaved;
@@ -149,7 +151,11 @@
                 && eventType != UsageEvents.Event.STANDBY_BUCKET_CHANGED;
     }
 
-    void update(String packageName, long timeStamp, int eventType) {
+    /**
+     * @hide
+     */
+    @VisibleForTesting
+    public void update(String packageName, long timeStamp, int eventType) {
         UsageStats usageStats = getOrCreateUsageStats(packageName);
 
         // TODO(adamlesinski): Ensure that we recover from incorrect event sequences
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 61d6b7d..d12eda75 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -155,8 +155,6 @@
 
     @Override
     public boolean isQuotaSupported(String volumeUuid, String callingPackage) {
-        enforcePermission(Binder.getCallingUid(), callingPackage);
-
         try {
             return mInstaller.isQuotaSupported(volumeUuid);
         } catch (InstallerException e) {
@@ -166,8 +164,6 @@
 
     @Override
     public boolean isReservedSupported(String volumeUuid, String callingPackage) {
-        enforcePermission(Binder.getCallingUid(), callingPackage);
-
         if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) {
             return SystemProperties.getBoolean(StorageManager.PROP_HAS_RESERVED, false);
         } else {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 9705469..5ab5dc2 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -42,7 +42,7 @@
 /**
  * Provides an interface to query for UsageStat data from an XML database.
  */
-class UsageStatsDatabase {
+public class UsageStatsDatabase {
     private static final int CURRENT_VERSION = 3;
 
     // Current version of the backup schema
@@ -369,7 +369,7 @@
     /**
      * Figures out what to extract from the given IntervalStats object.
      */
-    interface StatCombiner<T> {
+    public interface StatCombiner<T> {
 
         /**
          * Implementations should extract interesting from <code>stats</code> and add it
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 5239fe5..dd1ddfa 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -924,8 +924,7 @@
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
-            final int packageUid = mPackageManagerInternal.getPackageUid(packageName,
-                    PackageManager.MATCH_ANY_USER, userId);
+            final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
             // If the calling app is asking about itself, continue, else check for permission.
             if (packageUid != callingUid) {
                 if (!hasPermission(callingPackage)) {
@@ -974,7 +973,8 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 final int packageUid = mPackageManagerInternal.getPackageUid(packageName,
-                        PackageManager.MATCH_ANY_USER, userId);
+                        PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_AWARE, userId);
                 // Caller cannot set their own standby state
                 if (packageUid == callingUid) {
                     throw new IllegalArgumentException("Cannot set your own standby bucket");
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 4efe0b5..9b194e9 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -64,6 +64,9 @@
     private String mLastBackgroundedPackage;
     private final int mUserId;
 
+    // STOPSHIP: Temporary member variable for debugging b/110930764.
+    private UsageEvents.Event mLastEvent;
+
     private static final long[] INTERVAL_LENGTH = new long[] {
             UnixCalendar.DAY_IN_MILLIS, UnixCalendar.WEEK_IN_MILLIS,
             UnixCalendar.MONTH_IN_MILLIS, UnixCalendar.YEAR_IN_MILLIS
@@ -156,6 +159,8 @@
                     + eventToString(event.mEventType));
         }
 
+        mLastEvent = new UsageEvents.Event(event);
+
         if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
             // Need to rollover
             rolloverStats(event.mTimeStamp);
@@ -306,6 +311,36 @@
                 Slog.d(TAG, mLogPrefix + "Requesting stats after " + beginTime + " but latest is "
                         + currentStats.endTime);
             }
+
+            // STOPSHIP: Temporary logging for b/110930764.
+            if (intervalType == UsageStatsManager.INTERVAL_DAILY
+                    && mLastEvent != null && mLastEvent.mTimeStamp >= beginTime) {
+                final IntervalStats diskStats = mDatabase.getLatestUsageStats(
+                        UsageStatsManager.INTERVAL_DAILY);
+                StringBuilder sb = new StringBuilder(256);
+                sb.append("Last 24 hours of UsageStats missing! timeRange : ");
+                sb.append(beginTime);
+                sb.append(", ");
+                sb.append(endTime);
+                sb.append("\nLast reported Usage Event time : ");
+                sb.append(mLastEvent.mTimeStamp);
+                if (currentStats == null) {
+                    sb.append("\nNo in memory event stats available.");
+                } else {
+                    sb.append("\nLast in memory event time : ");
+                    sb.append(currentStats.endTime);
+                    sb.append("\nLast save time: ");
+                    sb.append(currentStats.lastTimeSaved);
+                }
+                if (diskStats == null) {
+                    sb.append("\nNo on disk event stats available.");
+                } else {
+                    sb.append("\nLast on disk event time : ");
+                    sb.append(diskStats.endTime);
+                }
+                Slog.wtf(TAG, sb.toString());
+            }
+
             // Nothing newer available.
             return null;
         }
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptor.java
index 3fc5fe3..ff67667 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptor.java
@@ -126,6 +126,9 @@
     public static final int REQUEST_GET_CONFIGURATION  = 0x08;
     public static final int REQUEST_SET_CONFIGURATION  = 0x09;
 
+    // USB control transfer timeout
+    public static final int USB_CONTROL_TRANSFER_TIMEOUT_MS = 200;
+
     /**
      * @throws IllegalArgumentException
      */
@@ -224,7 +227,7 @@
                         0,
                         sStringBuffer,
                         0xFF,
-                        0);
+                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
                 if (rdo >= 0) {
                     usbStr = new String(sStringBuffer, 2, rdo - 2, "UTF-16LE");
                 } else {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 92aa152..57e9f66 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -244,7 +244,7 @@
                 Slog.w(TAG, "setKeepAwake does not match active session");
                 return;
             }
-            mAm.setVoiceKeepAwake(mActiveSession.mSession, keepAwake);
+            mAtm.setVoiceKeepAwake(mActiveSession.mSession, keepAwake);
         } catch (RemoteException e) {
             throw new IllegalStateException("Unexpected remote error", e);
         }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 01f5d9c..57729b5 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -30,6 +30,7 @@
 import android.app.ActivityTaskManager;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
+import android.app.UriGrantsManager;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.content.ClipData;
@@ -62,6 +63,7 @@
 import com.android.server.am.AssistDataRequester;
 import com.android.server.am.AssistDataRequester.AssistDataRequesterCallbacks;
 import com.android.server.statusbar.StatusBarManagerInternal;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -82,6 +84,7 @@
     final int mCallingUid;
     final Handler mHandler;
     final IActivityManager mAm;
+    final UriGrantsManagerInternal mUgmInternal;
     final IWindowManager mIWindowManager;
     final AppOpsManager mAppOps;
     final IBinder mPermissionOwner;
@@ -141,19 +144,15 @@
         mCallingUid = callingUid;
         mHandler = handler;
         mAm = ActivityManager.getService();
+        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
         mIWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
         mAppOps = context.getSystemService(AppOpsManager.class);
         mAssistDataRequester = new AssistDataRequester(mContext, mIWindowManager,
                 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE),
                 this, mLock, OP_ASSIST_STRUCTURE, OP_ASSIST_SCREENSHOT);
-        IBinder permOwner = null;
-        try {
-            permOwner = mAm.newUriPermissionOwner("voicesession:"
+        final IBinder permOwner = mUgmInternal.newUriPermissionOwner("voicesession:"
                     + component.flattenToShortString());
-        } catch (RemoteException e) {
-            Slog.w("voicesession", "AM dead", e);
-        }
         mPermissionOwner = permOwner;
         mBindIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
         mBindIntent.setComponent(mSessionComponentName);
@@ -303,13 +302,14 @@
         long ident = Binder.clearCallingIdentity();
         try {
             // This will throw SecurityException for us.
-            mAm.checkGrantUriPermission(srcUid, null, ContentProvider.getUriWithoutUserId(uri),
-                    mode, ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(srcUid)));
+            mUgmInternal.checkGrantUriPermission(srcUid, null,
+                    ContentProvider.getUriWithoutUserId(uri), mode,
+                    ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(srcUid)));
             // No security exception, do the grant.
             int sourceUserId = ContentProvider.getUserIdFromUri(uri, mUser);
             uri = ContentProvider.getUriWithoutUserId(uri);
-            mAm.grantUriPermissionFromOwner(mPermissionOwner, srcUid, destPkg,
-                    uri, FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, mUser);
+            UriGrantsManager.getService().grantUriPermissionFromOwner(mPermissionOwner, srcUid,
+                    destPkg, uri, FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, mUser);
         } catch (RemoteException e) {
         } catch (SecurityException e) {
             Slog.w(TAG, "Can't propagate permission", e);
@@ -352,12 +352,8 @@
                     } catch (RemoteException e) {
                     }
                 }
-                try {
-                    mAm.revokeUriPermissionFromOwner(mPermissionOwner, null,
-                            FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION,
-                            mUser);
-                } catch (RemoteException e) {
-                }
+                mUgmInternal.revokeUriPermissionFromOwner(mPermissionOwner, null,
+                        FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION, mUser);
                 if (mSession != null) {
                     try {
                         ActivityTaskManager.getService().finishVoiceTask(mSession);
diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java
index 33013ac..eb202a7 100644
--- a/telecomm/java/android/telecom/AudioState.java
+++ b/telecomm/java/android/telecom/AudioState.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -53,8 +54,11 @@
     private static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
             ROUTE_SPEAKER;
 
+    @UnsupportedAppUsage
     private final boolean isMuted;
+    @UnsupportedAppUsage
     private final int route;
+    @UnsupportedAppUsage
     private final int supportedRouteMask;
 
     public AudioState(boolean muted, int route, int supportedRouteMask) {
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 1c0e260..096cf37d 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -308,6 +309,7 @@
          * Call can be upgraded to a video call.
          * @hide
          */
+        @UnsupportedAppUsage
         public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
 
         /**
diff --git a/telecomm/java/android/telecom/CallRedirectionService.java b/telecomm/java/android/telecom/CallRedirectionService.java
new file mode 100644
index 0000000..9c874bf
--- /dev/null
+++ b/telecomm/java/android/telecom/CallRedirectionService.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.telecom;
+
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+
+import com.android.internal.os.SomeArgs;
+import com.android.internal.telecom.ICallRedirectionService;
+import com.android.internal.telecom.ICallRedirectionAdapter;
+
+/**
+ * This service can be implemented to interact between Telecom and its implementor
+ * for making outgoing call with optional redirection/cancellation purposes.
+ *
+ * <p>
+ * Below is an example manifest registration for a {@code CallRedirectionService}.
+ * <pre>
+ * {@code
+ * <service android:name="your.package.YourCallRedirectionServiceImplementation"
+ *          android:permission="android.permission.BIND_REDIRECTION_SERVICE">
+ *      <intent-filter>
+ *          <action android:name="android.telecom.CallRedirectionService"/>
+ *      </intent-filter>
+ * </service>
+ * }
+ * </pre>
+ */
+public abstract class CallRedirectionService extends Service {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE = "android.telecom.CallRedirectionService";
+
+    /**
+     * An adapter to inform Telecom the response from the implementor of the Call
+     * Redirection service
+     */
+    private ICallRedirectionAdapter mCallRedirectionAdapter;
+
+    /**
+     * Telecom calls this method to inform the implemented {@link CallRedirectionService} of
+     * a new outgoing call which is being placed.
+     * @param handle the phone number dialed by the user
+     * @param targetPhoneAccount the {@link PhoneAccountHandle} on which the call will be placed.
+     */
+    public abstract void onPlaceCall(Uri handle, PhoneAccountHandle targetPhoneAccount);
+
+    /**
+     * The implemented {@link CallRedirectionService} calls this method to response a request
+     * received via {@link #onPlaceCall(Uri, PhoneAccountHandle)} to inform Telecom that no changes
+     * are required to the outgoing call, and that the call should be placed as-is.
+     */
+    public final void placeCallUnmodified() {
+        try {
+            mCallRedirectionAdapter.placeCallUnmodified();
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * The implemented {@link CallRedirectionService} calls this method to response a request
+     * received via {@link #onPlaceCall(Uri, PhoneAccountHandle)} to inform Telecom that changes
+     * are required to the phone number or/and {@link PhoneAccountHandle} for the outgoing call.
+     * @param handle the new phone number to dial
+     * @param targetPhoneAccount the {@link PhoneAccountHandle} to use when placing the call.
+     *                           If {@code null}, no change will be made to the
+     *                           {@link PhoneAccountHandle} used to place the call.
+     */
+    public final void redirectCall(Uri handle, PhoneAccountHandle targetPhoneAccount) {
+        try {
+            mCallRedirectionAdapter.redirectCall(handle, targetPhoneAccount);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * The implemented {@link CallRedirectionService} calls this method to response a request
+     * received via {@link #onPlaceCall(Uri, PhoneAccountHandle)} to inform Telecom that an outgoing
+     * call should be canceled entirely.
+     */
+    public final void cancelCall() {
+        try {
+            mCallRedirectionAdapter.cancelCall();
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * A handler message to process the attempt to place call with redirection service from Telecom
+     */
+    private static final int MSG_PLACE_CALL = 1;
+
+    /**
+     * A handler to process the attempt to place call with redirection service from Telecom
+     */
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_PLACE_CALL:
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        mCallRedirectionAdapter = (ICallRedirectionAdapter) args.arg1;
+                        onPlaceCall((Uri) args.arg2, (PhoneAccountHandle) args.arg3);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+            }
+        }
+    };
+
+    private final class CallRedirectionBinder extends ICallRedirectionService.Stub {
+
+        /**
+         * Telecom calls this method to inform the CallRedirectionService of a new outgoing call
+         * which is about to be placed.
+         * @param handle the phone number dialed by the user
+         * @param targetPhoneAccount the URI of the number the user dialed
+         */
+        @Override
+        public void placeCall(ICallRedirectionAdapter adapter, Uri handle,
+                              PhoneAccountHandle targetPhoneAccount) {
+            Log.v(this, "placeCall");
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = adapter;
+            args.arg2 = handle;
+            args.arg3 = targetPhoneAccount;
+            mHandler.obtainMessage(MSG_PLACE_CALL, args).sendToTarget();
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.v(this, "onBind");
+        return new CallRedirectionBinder();
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        Log.v(this, "onUnbind");
+        return false;
+    }
+}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 3e97c8f..3d2b397 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -23,6 +23,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Notification;
 import android.bluetooth.BluetoothDevice;
 import android.content.Intent;
@@ -843,6 +844,7 @@
         public void onRemoteRttRequest(Connection c) {}
         /** @hide */
         public void onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle) {}
+        public void onConnectionTimeReset(Connection c) {}
     }
 
     /**
@@ -854,6 +856,8 @@
         private final OutputStreamWriter mPipeToInCall;
         private final ParcelFileDescriptor mFdFromInCall;
         private final ParcelFileDescriptor mFdToInCall;
+
+        private final FileInputStream mFromInCallFileInputStream;
         private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
 
         /**
@@ -862,11 +866,11 @@
         public RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall) {
             mFdFromInCall = fromInCall;
             mFdToInCall = toInCall;
+            mFromInCallFileInputStream = new FileInputStream(fromInCall.getFileDescriptor());
 
             // Wrap the FileInputStream in a Channel so that it's interruptible.
             mPipeFromInCall = new InputStreamReader(
-                    Channels.newInputStream(Channels.newChannel(
-                            new FileInputStream(fromInCall.getFileDescriptor()))));
+                    Channels.newInputStream(Channels.newChannel(mFromInCallFileInputStream)));
             mPipeToInCall = new OutputStreamWriter(
                     new FileOutputStream(toInCall.getFileDescriptor()));
         }
@@ -914,7 +918,7 @@
          * not entered any new text yet.
          */
         public String readImmediately() throws IOException {
-            if (mPipeFromInCall.ready()) {
+            if (mFromInCallFileInputStream.available() > 0) {
                 return read();
             } else {
                 return null;
@@ -1277,6 +1281,7 @@
          * @param looper The looper.
          * @hide
          */
+        @UnsupportedAppUsage
         public VideoProvider(Looper looper) {
             mBinder = new VideoProvider.VideoProviderBinder();
             mMessageHandler = new VideoProvider.VideoProviderHandler(looper);
@@ -2370,6 +2375,16 @@
     }
 
     /**
+     * @hide
+     * Resets the cdma connection time.
+     */
+    public final void resetConnectionTime() {
+        for (Listener l : mListeners) {
+            l.onConnectionTimeReset(this);
+        }
+    }
+
+    /**
      * Returns the connections or conferences with which this connection can be conferenced.
      */
     public final List<Conferenceable> getConferenceables() {
@@ -2808,9 +2823,21 @@
     public void onReject(String replyMessage) {}
 
     /**
-     * Notifies the Connection of a request to silence the ringer.
-     *
-     * @hide
+     * Notifies this Connection of a request to silence the ringer.
+     * <p>
+     * The ringer may be silenced by any of the following methods:
+     * <ul>
+     *     <li>{@link TelecomManager#silenceRinger()}</li>
+     *     <li>The user presses the volume-down button while a call is ringing.</li>
+     * </ul>
+     * <p>
+     * Self-managed {@link ConnectionService} implementations should override this method in their
+     * {@link Connection} implementation and implement logic to silence their app's ringtone.  If
+     * your app set the ringtone as part of the incoming call {@link Notification} (see
+     * {@link #onShowIncomingCallUi()}), it should re-post the notification now, except call
+     * {@link android.app.Notification.Builder#setOnlyAlertOnce(boolean)} with {@code true}.  This
+     * will ensure the ringtone sound associated with your {@link android.app.NotificationChannel}
+     * stops playing.
      */
     public void onSilence() {}
 
@@ -2887,7 +2914,29 @@
      * <p>
      * You should trigger the display of the incoming call user interface for your application by
      * showing a {@link Notification} with a full-screen {@link Intent} specified.
-     * For example:
+     *
+     * In your application code, you should create a {@link android.app.NotificationChannel} for
+     * incoming call notifications from your app:
+     * <pre><code>
+     * NotificationChannel channel = new NotificationChannel(YOUR_CHANNEL_ID, "Incoming Calls",
+     *          NotificationManager.IMPORTANCE_MAX);
+     * // other channel setup stuff goes here.
+     *
+     * // We'll use the default system ringtone for our incoming call notification channel.  You can
+     * // use your own audio resource here.
+     * Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
+     * channel.setSound(ringtoneUri, new AudioAttributes.Builder()
+     *          // Setting the AudioAttributes is important as it identifies the purpose of your
+     *          // notification sound.
+     *          .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+     *          .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+     *      .build());
+     *
+     * NotificationManager mgr = getSystemService(NotificationManager.class);
+     * mgr.createNotificationChannel(channel);
+     * </code></pre>
+     * When it comes time to post a notification for your incoming call, ensure it uses your
+     * incoming call {@link android.app.NotificationChannel}.
      * <pre><code>
      *     // Create an intent which triggers your fullscreen incoming call user interface.
      *     Intent intent = new Intent(Intent.ACTION_MAIN, null);
@@ -2913,11 +2962,14 @@
      *     builder.setContentTitle("Your notification title");
      *     builder.setContentText("Your notification content.");
      *
-     *     // Use builder.addAction(..) to add buttons to answer or reject the call.
+     *     // Set notification as insistent to cause your ringtone to loop.
+     *     Notification notification = builder.build();
+     *     notification.flags |= Notification.FLAG_INSISTENT;
      *
+     *     // Use builder.addAction(..) to add buttons to answer or reject the call.
      *     NotificationManager notificationManager = mContext.getSystemService(
      *         NotificationManager.class);
-     *     notificationManager.notify(YOUR_TAG, YOUR_ID, builder.build());
+     *     notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, notification);
      * </code></pre>
      */
     public void onShowIncomingCallUi() {}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 2291090..61adcdd 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -1474,6 +1474,13 @@
                 mAdapter.onPhoneAccountChanged(id, pHandle);
             }
         }
+
+        public void onConnectionTimeReset(Connection c) {
+            String id = mIdByConnection.get(c);
+            if (id != null) {
+                mAdapter.resetConnectionTime(id);
+            }
+        }
     };
 
     /** {@inheritDoc} */
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 0d319bb..520e7ed 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -255,6 +255,18 @@
     }
 
     /**
+        * Resets the cdma connection time.
+        */
+    void resetConnectionTime(String callId) {
+        for (IConnectionServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.resetConnectionTime(callId, Log.getExternalSession());
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /**
      * Indicates that the call no longer exists. Can be used with either a call or a conference
      * call.
      *
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 3e1bf77..78d65e6 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -610,6 +610,11 @@
         public void onConnectionServiceFocusReleased(Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_CONNECTION_SERVICE_FOCUS_RELEASED).sendToTarget();
         }
+
+        @Override
+        public void resetConnectionTime(String callId, Session.Info sessionInfo) {
+            // Do nothing
+        }
     };
 
     public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index bd25ab2..1aeeca7 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -47,13 +47,19 @@
  * before the telecom service will bind to its {@code InCallService} implementation.
  * <p>
  * Below is an example manifest registration for an {@code InCallService}. The meta-data
- * ({@link TelecomManager#METADATA_IN_CALL_SERVICE_UI}) indicates that this particular
+ * {@link TelecomManager#METADATA_IN_CALL_SERVICE_UI} indicates that this particular
  * {@code InCallService} implementation intends to replace the built-in in-call UI.
+ * The meta-data {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} indicates that this
+ * {@link InCallService} will play the ringtone for incoming calls.  See
+ * <a href="#incomingCallNotification">below</a> for more information on showing the incoming call
+ * UI and playing the ringtone in your app.
  * <pre>
  * {@code
  * <service android:name="your.package.YourInCallServiceImplementation"
  *          android:permission="android.permission.BIND_INCALL_SERVICE">
  *      <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
+ *      <meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING"
+ *          android:value="true" />
  *      <intent-filter>
  *          <action android:name="android.telecom.InCallService"/>
  *      </intent-filter>
@@ -80,6 +86,72 @@
  * to see if they would like your application to be the new default phone app.  See the
  * {@link TelecomManager#ACTION_CHANGE_DEFAULT_DIALER} intent documentation for more information on
  * how to do this.
+ * <p id="incomingCallNotification">
+ * <h2>Showing the Incoming Call Notification</h2>
+ * When your app receives a new incoming call via {@link InCallService#onCallAdded(Call)}, it is
+ * responsible for displaying an incoming call UI for the incoming call.  It should do this using
+ * {@link android.app.NotificationManager} APIs to post a new incoming call notification.
+ * <p>
+ * Where your app declares the meta-data {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING}, it
+ * is responsible for playing the ringtone for incoming calls.  Your app should create a
+ * {@link android.app.NotificationChannel} which specifies the desired ringtone.  For example:
+ * <pre><code>
+ * NotificationChannel channel = new NotificationChannel(YOUR_CHANNEL_ID, "Incoming Calls",
+ *          NotificationManager.IMPORTANCE_MAX);
+ * // other channel setup stuff goes here.
+ *
+ * // We'll use the default system ringtone for our incoming call notification channel.  You can
+ * // use your own audio resource here.
+ * Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
+ * channel.setSound(ringtoneUri, new AudioAttributes.Builder()
+ *          // Setting the AudioAttributes is important as it identifies the purpose of your
+ *          // notification sound.
+ *          .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+ *          .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ *      .build());
+ *
+ * NotificationManager mgr = getSystemService(NotificationManager.class);
+ * mgr.createNotificationChannel(channel);
+ * </code></pre>
+ * <p>
+ * When your app receives a new incoming call, it creates a {@link android.app.Notification} for the
+ * incoming call and associates it with your incoming call notification channel. You can specify a
+ * {@link android.app.PendingIntent} on the notification which will launch your full screen
+ * incoming call UI.  The notification manager framework will display your notification as a
+ * heads-up notification if the user is actively using the phone.  When the user is not using the
+ * phone, your full-screen incoming call UI is used instead.
+ * For example:
+ * <pre><code>
+ * // Create an intent which triggers your fullscreen incoming call user interface.
+ * Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ * intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
+ * intent.setClass(context, YourIncomingCallActivity.class);
+ * PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, 0);
+ *
+ * // Build the notification as an ongoing high priority item; this ensures it will show as
+ * // a heads up notification which slides down over top of the current content.
+ * final Notification.Builder builder = new Notification.Builder(context);
+ * builder.setOngoing(true);
+ * builder.setPriority(Notification.PRIORITY_HIGH);
+ *
+ * // Set notification content intent to take user to the fullscreen UI if user taps on the
+ * // notification body.
+ * builder.setContentIntent(pendingIntent);
+ * // Set full screen intent to trigger display of the fullscreen UI when the notification
+ * // manager deems it appropriate.
+ * builder.setFullScreenIntent(pendingIntent, true);
+ *
+ * // Setup notification content.
+ * builder.setSmallIcon( yourIconResourceId );
+ * builder.setContentTitle("Your notification title");
+ * builder.setContentText("Your notification content.");
+ *
+ * // Use builder.addAction(..) to add buttons to answer or reject the call.
+ *
+ * NotificationManager notificationManager = mContext.getSystemService(
+ *     NotificationManager.class);
+ * notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, builder.build());
+ * </code></pre>
  */
 public abstract class InCallService extends Service {
 
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 6212a77..8b0211e 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -117,6 +118,7 @@
     }
 
     /** The unique ID of the call. */
+    @UnsupportedAppUsage
     public String getId() {
         return mId;
     }
@@ -130,6 +132,7 @@
      * Reason for disconnection, as described by {@link android.telecomm.DisconnectCause}. Valid
      * when call state is {@link CallState#DISCONNECTED}.
      */
+    @UnsupportedAppUsage
     public DisconnectCause getDisconnectCause() {
         return mDisconnectCause;
     }
@@ -155,11 +158,13 @@
     }
 
     /** The time that the call switched to the active state. */
+    @UnsupportedAppUsage
     public long getConnectTimeMillis() {
         return mConnectTimeMillis;
     }
 
     /** The endpoint to which the call is connected. */
+    @UnsupportedAppUsage
     public Uri getHandle() {
         return mHandle;
     }
@@ -300,6 +305,7 @@
     }
 
     /** Responsible for creating ParcelableCall objects for deserialized Parcels. */
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<ParcelableCall> CREATOR =
             new Parcelable.Creator<ParcelableCall> () {
         @Override
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 99f94f2..d3ccd2c 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.bluetooth.BluetoothDevice;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -330,6 +331,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public final void setProximitySensorOn() {
         mInCallAdapter.turnProximitySensorOn();
     }
@@ -345,6 +347,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public final void setProximitySensorOff(boolean screenOnImmediately) {
         mInCallAdapter.turnProximitySensorOff(screenOnImmediately);
     }
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 77b510d..279804e 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -40,7 +41,9 @@
  * See {@link PhoneAccount}, {@link TelecomManager}.
  */
 public final class PhoneAccountHandle implements Parcelable {
+    @UnsupportedAppUsage
     private final ComponentName mComponentName;
+    @UnsupportedAppUsage
     private final String mId;
     private final UserHandle mUserHandle;
 
@@ -164,6 +167,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     private PhoneAccountHandle(Parcel in) {
         this(ComponentName.CREATOR.createFromParcel(in),
                 in.readString(),
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index bb4b483..9821dcb 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -466,6 +466,11 @@
                 Log.w(this, "onRemoteRttRequest called on a remote conference");
             }
         }
+
+        @Override
+        public void resetConnectionTime(String callId, Session.Info sessionInfo) {
+            // Do nothing
+        }
     };
 
     private final ConnectionServiceAdapterServant mServant =
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 75572b3..48c1e24 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -20,6 +20,7 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -376,6 +377,7 @@
      * The phone number of the call used by Telecom to determine which call should be handed over.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String EXTRA_IS_HANDOVER = "android.telecom.extra.IS_HANDOVER";
 
     /**
@@ -493,6 +495,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int TTY_MODE_OFF = 0;
 
     /**
@@ -652,6 +655,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static TelecomManager from(Context context) {
         return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
     }
@@ -721,6 +725,7 @@
      * @return The user outgoing phone account selected by the user.
      * @hide
      */
+    @UnsupportedAppUsage
     public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
         try {
             if (isServiceConnected()) {
@@ -736,6 +741,7 @@
      * Sets the user-chosen default for making outgoing phone calls.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
         try {
             if (isServiceConnected()) {
@@ -773,6 +779,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PhoneAccountHandle getSimCallManager(int userId) {
         try {
             if (isServiceConnected()) {
@@ -876,6 +883,7 @@
      * @return A list of {@code PhoneAccountHandle} objects.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<PhoneAccountHandle> getCallCapablePhoneAccounts(boolean includeDisabledAccounts) {
         try {
             if (isServiceConnected()) {
@@ -1109,6 +1117,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setDefaultDialer(String packageName) {
         try {
             if (isServiceConnected()) {
@@ -1126,6 +1135,7 @@
      * @return package name for the system dialer package or null if no system dialer is preloaded.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSystemDialerPackage() {
         try {
             if (isServiceConnected()) {
@@ -1413,6 +1423,7 @@
      * - {@link TelecomManager#TTY_MODE_VCO}
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCurrentTtyMode() {
         try {
             if (isServiceConnected()) {
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index bae58ff..2c7fecb 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
@@ -217,6 +218,7 @@
         mTargetSdkVersion = sdkVersion;
     }
 
+    @UnsupportedAppUsage
     public void destroy() {
         unregisterCallback(mCallback);
     }
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index 90ed36f..bbac8eb 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -377,6 +378,7 @@
          * @param maxZoom Maximum zoom supported by camera.
          * @hide
          */
+        @UnsupportedAppUsage
         public CameraCapabilities(int width, int height, boolean zoomSupported, float maxZoom) {
             mWidth = width;
             mHeight = height;
diff --git a/telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl b/telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl
new file mode 100644
index 0000000..46bf983
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telecom;
+
+import android.net.Uri;
+import android.telecom.PhoneAccountHandle;
+
+/**
+ * Internal remote callback interface for call redirection services.
+ *
+ * @see android.telecom.CallRedirectionService
+ *
+ * {@hide}
+ */
+oneway interface ICallRedirectionAdapter {
+    void cancelCall();
+
+    void placeCallUnmodified();
+
+    void redirectCall(in Uri handle, in PhoneAccountHandle targetPhoneAccount);
+}
diff --git a/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl b/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl
new file mode 100644
index 0000000..d8d360b
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telecom;
+
+import android.net.Uri;
+import android.telecom.PhoneAccountHandle;
+
+import com.android.internal.telecom.ICallRedirectionAdapter;
+
+/**
+ * Internal remote interface for a call redirection service.
+ *
+ * @see android.telecom.CallRedirectionService
+ *
+ * @hide
+ */
+oneway interface ICallRedirectionService {
+    void placeCall(in ICallRedirectionAdapter adapter, in Uri handle,
+            in PhoneAccountHandle targetPhoneAccount);
+}
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index be474bd..0157a58 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -121,4 +121,6 @@
     in Session.Info sessionInfo);
 
     void onConnectionServiceFocusReleased(in Session.Info sessionInfo);
+
+    void resetConnectionTime(String callIdi, in Session.Info sessionInfo);
 }
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 8283e97..b9de374 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -19,6 +19,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.job.JobService;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -373,6 +374,7 @@
          * Return cursor for table query.
          * @hide
          */
+        @UnsupportedAppUsage
         public static Cursor query(ContentResolver cr, String[] projection,
                 String where, String orderBy) {
             return cr.query(CONTENT_URI, projection, where,
@@ -403,6 +405,7 @@
          * @return the URI for the new message
          * @hide
          */
+        @UnsupportedAppUsage
         public static Uri addMessageToUri(ContentResolver resolver,
                 Uri uri, String address, String body, String subject,
                 Long date, boolean read, boolean deliveryReport) {
@@ -425,6 +428,7 @@
          * @return the URI for the new message
          * @hide
          */
+        @UnsupportedAppUsage
         public static Uri addMessageToUri(int subId, ContentResolver resolver,
                 Uri uri, String address, String body, String subject,
                 Long date, boolean read, boolean deliveryReport) {
@@ -447,6 +451,7 @@
          * @return the URI for the new message
          * @hide
          */
+        @UnsupportedAppUsage
         public static Uri addMessageToUri(ContentResolver resolver,
                 Uri uri, String address, String body, String subject,
                 Long date, boolean read, boolean deliveryReport, long threadId) {
@@ -471,6 +476,7 @@
          * @return the URI for the new message
          * @hide
          */
+        @UnsupportedAppUsage
         public static Uri addMessageToUri(int subId, ContentResolver resolver,
                 Uri uri, String address, String body, String subject,
                 Long date, boolean read, boolean deliveryReport, long threadId) {
@@ -503,6 +509,7 @@
          * @return true if the operation succeeded
          * @hide
          */
+        @UnsupportedAppUsage
         public static boolean moveMessageToFolder(Context context,
                 Uri uri, int folder, int error) {
             if (uri == null) {
@@ -546,6 +553,7 @@
          * outgoing message.
          * @hide
          */
+        @UnsupportedAppUsage
         public static boolean isOutgoingFolder(int messageType) {
             return  (messageType == MESSAGE_TYPE_FAILED)
                     || (messageType == MESSAGE_TYPE_OUTBOX)
@@ -587,6 +595,7 @@
              * @return the URI for the new message
              * @hide
              */
+            @UnsupportedAppUsage
             public static Uri addMessage(ContentResolver resolver,
                     String address, String body, String subject, Long date,
                     boolean read) {
@@ -607,6 +616,7 @@
              * @return the URI for the new message
              * @hide
              */
+            @UnsupportedAppUsage
             public static Uri addMessage(int subId, ContentResolver resolver,
                     String address, String body, String subject, Long date, boolean read) {
                 return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
@@ -647,6 +657,7 @@
              * @return the URI for the new message
              * @hide
              */
+            @UnsupportedAppUsage
             public static Uri addMessage(ContentResolver resolver,
                     String address, String body, String subject, Long date) {
                 return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
@@ -665,6 +676,7 @@
              * @return the URI for the new message
              * @hide
              */
+            @UnsupportedAppUsage
             public static Uri addMessage(int subId, ContentResolver resolver,
                     String address, String body, String subject, Long date) {
                 return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
@@ -692,6 +704,7 @@
            /**
             * @hide
             */
+            @UnsupportedAppUsage
             public static Uri addMessage(ContentResolver resolver,
                     String address, String body, String subject, Long date) {
                 return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
@@ -710,6 +723,7 @@
              * @return the URI for the new message
              * @hide
              */
+            @UnsupportedAppUsage
             public static Uri addMessage(int subId, ContentResolver resolver,
                     String address, String body, String subject, Long date) {
                 return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
@@ -756,6 +770,7 @@
              * @return the URI for the new message
              * @hide
              */
+            @UnsupportedAppUsage
             public static Uri addMessage(ContentResolver resolver,
                     String address, String body, String subject, Long date,
                     boolean deliveryReport, long threadId) {
@@ -1935,12 +1950,14 @@
      */
     public static final class Threads implements ThreadsColumns {
 
+        @UnsupportedAppUsage
         private static final String[] ID_PROJECTION = { BaseColumns._ID };
 
         /**
          * Private {@code content://} style URL for this table. Used by
          * {@link #getOrCreateThreadId(android.content.Context, java.util.Set)}.
          */
+        @UnsupportedAppUsage
         private static final Uri THREAD_ID_CONTENT_URI = Uri.parse(
                 "content://mms-sms/threadID");
 
@@ -2069,6 +2086,7 @@
          * </ul>
          * @hide
          */
+        @UnsupportedAppUsage
         public static final Pattern NAME_ADDR_EMAIL_PATTERN =
                 Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
 
@@ -2096,6 +2114,7 @@
          * Helper method to extract email address from address string.
          * @hide
          */
+        @UnsupportedAppUsage
         public static String extractAddrSpec(String address) {
             Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
 
@@ -2112,6 +2131,7 @@
          * @return true if address is an email address; false otherwise.
          * @hide
          */
+        @UnsupportedAppUsage
         public static boolean isEmailAddress(String address) {
             if (TextUtils.isEmpty(address)) {
                 return false;
@@ -2129,6 +2149,7 @@
          * @return true if number is a phone number; false otherwise.
          * @hide
          */
+        @UnsupportedAppUsage
         public static boolean isPhoneNumber(String number) {
             if (TextUtils.isEmpty(number)) {
                 return false;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 014af5c..97068a6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -22,6 +22,7 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
@@ -80,6 +81,30 @@
     public static final String
             KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
 
+    /**
+     * Boolean indicating if the "Call forwarding" item is visible in the Call Settings menu.
+     * true means visible. false means gone.
+     * @hide
+     */
+    public static final String KEY_CALL_FORWARDING_VISIBILITY_BOOL =
+            "call_forwarding_visibility_bool";
+
+    /**
+     * Boolean indicating if the "Caller ID" item is visible in the Additional Settings menu.
+     * true means visible. false means gone.
+     * @hide
+     */
+    public static final String KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL =
+            "additional_settings_caller_id_visibility_bool";
+
+    /**
+     * Boolean indicating if the "Call Waiting" item is visible in the Additional Settings menu.
+     * true means visible. false means gone.
+     * @hide
+     */
+    public static final String KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL =
+            "additional_settings_call_waiting_visibility_bool";
+
    /**
     * Boolean indicating if the "Call barring" item is visible in the Call Settings menu.
     * true means visible. false means gone.
@@ -138,10 +163,20 @@
     /**
      * Flag indicating whether radio is to be restarted on error PDP_FAIL_REGULAR_DEACTIVATION
      * This is false by default.
+     *
+     * @deprecated Use {@link #KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY} instead
      */
-    public static final String
-            KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL =
-                    "restart_radio_on_pdp_fail_regular_deactivation_bool";
+    @Deprecated
+    public static final String KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL =
+            "restart_radio_on_pdp_fail_regular_deactivation_bool";
+
+    /**
+     * A list of failure cause codes that will trigger a modem restart when telephony receiving
+     * one of those during data setup. The cause codes are defined in 3GPP TS 24.008 Annex I and
+     * TS 24.301 Annex B.
+     */
+    public static final String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY =
+            "radio_restart_failure_causes_int_array";
 
     /**
      * If true, enable vibration (haptic feedback) for key presses in the EmergencyDialer activity.
@@ -200,6 +235,13 @@
     public static final String
             KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
 
+    /**
+     * A string array containing numbers that shouldn't be included in the call log.
+     * @hide
+     */
+    public static final String KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY =
+            "unloggable_numbers_string_array";
+
     /** If true, removes the Voice Privacy option from Call Settings */
     public static final String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
 
@@ -1181,6 +1223,7 @@
      * disable_metered_apns}
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY =
             "carrier_default_actions_on_redirection_string_array";
 
@@ -1469,6 +1512,15 @@
             "always_play_remote_hold_tone_bool";
 
     /**
+     * When true, the Telephony stack will automatically turn off airplane mode and retry a wifi
+     * emergency call over the cell network if the initial attempt at dialing was met with a SIP 308
+     * error.
+     * @hide
+     */
+    public static final String KEY_AUTO_RETRY_FAILED_WIFI_EMERGENCY_CALL =
+            "auto_retry_failed_wifi_emergency_call";
+
+    /**
      * When true, indicates that adding a call is disabled when there is an ongoing video call
      * or when there is an ongoing call on wifi which was downgraded from video and VoWifi is
      * turned off.
@@ -1784,6 +1836,7 @@
      * Key identifying if voice call barring notification is required to be shown to the user.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL =
             "disable_voice_barring_notification_bool";
 
@@ -1988,6 +2041,15 @@
     public static final String KEY_UNDELIVERED_SMS_MESSAGE_EXPIRATION_TIME =
             "undelivered_sms_message_expiration_time";
 
+    /**
+     * Specifies a carrier-defined {@link CallRedirectionService} which Telecom will bind
+     * to for outgoing calls.  An empty string indicates that no carrier-defined
+     * {@link CallRedirectionService} is specified.
+     * @hide
+     */
+    public static final String KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING =
+            "call_redirection_service_component_name_string";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -1996,8 +2058,10 @@
         sDefaults.putBoolean(KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL, true);
         sDefaults.putBoolean(KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_PLAY_REMOTE_HOLD_TONE_BOOL, false);
+        sDefaults.putBoolean(KEY_AUTO_RETRY_FAILED_WIFI_EMERGENCY_CALL, false);
         sDefaults.putBoolean(KEY_ADDITIONAL_CALL_SETTING_BOOL, true);
         sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL, false);
+        sDefaults.putStringArray(KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_ALLOW_LOCAL_DTMF_TONES_BOOL, true);
         sDefaults.putBoolean(KEY_PLAY_CALL_RECORDING_TONE_BOOL, false);
         sDefaults.putBoolean(KEY_APN_EXPAND_BOOL, true);
@@ -2046,6 +2110,9 @@
 
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false);
         sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, false);
+        sDefaults.putBoolean(KEY_CALL_FORWARDING_VISIBILITY_BOOL, true);
+        sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL, true);
+        sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL, true);
         sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
         sDefaults.putBoolean(KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL, false);
         sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
@@ -2067,6 +2134,7 @@
         sDefaults.putBoolean(KEY_WORLD_PHONE_BOOL, false);
         sDefaults.putBoolean(KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
         sDefaults.putBoolean(KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL, false);
+        sDefaults.putIntArray(KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY, new int[]{});
         sDefaults.putInt(KEY_VOLTE_REPLACEMENT_RAT_INT, 0);
         sDefaults.putString(KEY_DEFAULT_SIM_CALL_MANAGER_STRING, "");
         sDefaults.putString(KEY_VVM_DESTINATION_NUMBER_STRING, "");
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 890a6ea..76a0026 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -17,14 +17,11 @@
 package android.telephony;
 
 import android.annotation.CallSuper;
-import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 /**
@@ -32,44 +29,6 @@
  * CellIdentityXxx which represents cell identity for specific network access technology.
  */
 public abstract class CellIdentity implements Parcelable {
-    /**
-     * Cell identity type
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "TYPE_", value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA})
-    public @interface Type {}
-
-    /**
-     * Unknown cell identity type
-     * @hide
-     */
-    public static final int TYPE_UNKNOWN        = 0;
-    /**
-     * GSM cell identity type
-     * @hide
-     */
-    public static final int TYPE_GSM            = 1;
-    /**
-     * CDMA cell identity type
-     * @hide
-     */
-    public static final int TYPE_CDMA           = 2;
-    /**
-     * LTE cell identity type
-     * @hide
-     */
-    public static final int TYPE_LTE            = 3;
-    /**
-     * WCDMA cell identity type
-     * @hide
-     */
-    public static final int TYPE_WCDMA          = 4;
-    /**
-     * TDS-CDMA cell identity type
-     * @hide
-     */
-    public static final int TYPE_TDSCDMA        = 5;
 
     /** @hide */
     public static final int INVALID_CHANNEL_NUMBER = -1;
@@ -138,7 +97,9 @@
      * @hide
      * @return The type of the cell identity
      */
-    public @Type int getType() { return mType; }
+    public @CellInfo.Type int getType() {
+        return mType;
+    }
 
     /**
      * Returns the channel number of the cell identity.
@@ -168,6 +129,12 @@
         return mAlphaShort;
     }
 
+    /**
+     * @return a CellLocation object for this CellIdentity
+     * @hide
+     */
+    public abstract CellLocation asCellLocation();
+
     @Override
     public boolean equals(Object other) {
         if (!(other instanceof CellIdentity)) {
@@ -175,7 +142,10 @@
         }
 
         CellIdentity o = (CellIdentity) other;
-        return TextUtils.equals(mAlphaLong, o.mAlphaLong)
+        return mType == o.mType
+                && TextUtils.equals(mMccStr, o.mMccStr)
+                && TextUtils.equals(mMncStr, o.mMncStr)
+                && TextUtils.equals(mAlphaLong, o.mAlphaLong)
                 && TextUtils.equals(mAlphaShort, o.mAlphaShort);
     }
 
@@ -214,11 +184,12 @@
                 public CellIdentity createFromParcel(Parcel in) {
                     int type = in.readInt();
                     switch (type) {
-                        case TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
-                        case TYPE_WCDMA: return CellIdentityWcdma.createFromParcelBody(in);
-                        case TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
-                        case TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
-                        case TYPE_TDSCDMA: return CellIdentityTdscdma.createFromParcelBody(in);
+                        case CellInfo.TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
+                        case CellInfo.TYPE_WCDMA: return CellIdentityWcdma.createFromParcelBody(in);
+                        case CellInfo.TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
+                        case CellInfo.TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
+                        case CellInfo.TYPE_TDSCDMA:
+                            return CellIdentityTdscdma.createFromParcelBody(in);
                         default: throw new IllegalArgumentException("Bad Cell identity Parcel");
                     }
                 }
@@ -233,4 +204,4 @@
     protected void log(String s) {
         Rlog.w(mTag, s);
     }
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 58a2c45..9218bdc 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -17,8 +17,9 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
-import android.text.TextUtils;
+import android.telephony.cdma.CdmaCellLocation;
 
 import java.util.Objects;
 
@@ -54,7 +55,7 @@
      * @hide
      */
     public CellIdentityCdma() {
-        super(TAG, TYPE_CDMA, null, null, null, null);
+        super(TAG, CellInfo.TYPE_CDMA, null, null, null, null);
         mNetworkId = Integer.MAX_VALUE;
         mSystemId = Integer.MAX_VALUE;
         mBasestationId = Integer.MAX_VALUE;
@@ -74,6 +75,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat) {
         this(nid, sid, bid, lon, lat, null, null);
     }
@@ -94,7 +96,7 @@
      */
     public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat, String alphal,
                              String alphas) {
-        super(TAG, TYPE_CDMA, null, null, alphal, alphas);
+        super(TAG, CellInfo.TYPE_CDMA, null, null, alphal, alphas);
         mNetworkId = nid;
         mSystemId = sid;
         mBasestationId = bid;
@@ -176,6 +178,18 @@
                 super.hashCode());
     }
 
+    /** @hide */
+    @Override
+    public CdmaCellLocation asCellLocation() {
+        CdmaCellLocation cl = new CdmaCellLocation();
+        int bsid = mBasestationId != Integer.MAX_VALUE ? mBasestationId : -1;
+        int sid = mSystemId != Integer.MAX_VALUE ? mSystemId : -1;
+        int nid = mNetworkId != Integer.MAX_VALUE ? mNetworkId : -1;
+        // lat and long already use Integer.MAX_VALUE for invalid/unknown
+        cl.setCellLocationData(bsid, mLatitude, mLongitude, sid, nid);
+        return cl;
+    }
+
     @Override
     public boolean equals(Object other) {
         if (this == other) {
@@ -213,7 +227,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_CDMA);
+        super.writeToParcel(dest, CellInfo.TYPE_CDMA);
         dest.writeInt(mNetworkId);
         dest.writeInt(mSystemId);
         dest.writeInt(mBasestationId);
@@ -223,7 +237,7 @@
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityCdma(Parcel in) {
-        super(TAG, TYPE_CDMA, in);
+        super(TAG, CellInfo.TYPE_CDMA, in);
         mNetworkId = in.readInt();
         mSystemId = in.readInt();
         mBasestationId = in.readInt();
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index c697880fa..cb9dbf3 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -17,7 +17,9 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
+import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 
 import java.util.Objects;
@@ -34,15 +36,18 @@
     // 16-bit GSM Cell Identity described in TS 27.007, 0..65535
     private final int mCid;
     // 16-bit GSM Absolute RF Channel Number
+    @UnsupportedAppUsage
     private final int mArfcn;
     // 6-bit Base Station Identity Code
+    @UnsupportedAppUsage
     private final int mBsic;
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public CellIdentityGsm() {
-        super(TAG, TYPE_GSM, null, null, null, null);
+        super(TAG, CellInfo.TYPE_GSM, null, null, null, null);
         mLac = Integer.MAX_VALUE;
         mCid = Integer.MAX_VALUE;
         mArfcn = Integer.MAX_VALUE;
@@ -92,7 +97,7 @@
      */
     public CellIdentityGsm(int lac, int cid, int arfcn, int bsic, String mccStr,
                             String mncStr, String alphal, String alphas) {
-        super(TAG, TYPE_GSM, mccStr, mncStr, alphal, alphas);
+        super(TAG, CellInfo.TYPE_GSM, mccStr, mncStr, alphal, alphas);
         mLac = lac;
         mCid = cid;
         mArfcn = arfcn;
@@ -194,6 +199,17 @@
         return Integer.MAX_VALUE;
     }
 
+    /** @hide */
+    @Override
+    public GsmCellLocation asCellLocation() {
+        GsmCellLocation cl = new GsmCellLocation();
+        int lac = mLac != Integer.MAX_VALUE ? mLac : -1;
+        int cid = mCid != Integer.MAX_VALUE ? mCid : -1;
+        cl.setLacAndCid(lac, cid);
+        cl.setPsc(-1);
+        return cl;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(mLac, mCid, super.hashCode());
@@ -237,7 +253,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_GSM);
+        super.writeToParcel(dest, CellInfo.TYPE_GSM);
         dest.writeInt(mLac);
         dest.writeInt(mCid);
         dest.writeInt(mArfcn);
@@ -246,7 +262,7 @@
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityGsm(Parcel in) {
-        super(TAG, TYPE_GSM, in);
+        super(TAG, CellInfo.TYPE_GSM, in);
         mLac = in.readInt();
         mCid = in.readInt();
         mArfcn = in.readInt();
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 177fced..b44e891 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -17,7 +17,9 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
+import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 
 import java.util.Objects;
@@ -36,6 +38,7 @@
     // 16-bit tracking area code
     private final int mTac;
     // 18-bit Absolute RF Channel Number
+    @UnsupportedAppUsage
     private final int mEarfcn;
     // cell bandwidth, in kHz
     private final int mBandwidth;
@@ -43,8 +46,9 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public CellIdentityLte() {
-        super(TAG, TYPE_LTE, null, null, null, null);
+        super(TAG, CellInfo.TYPE_LTE, null, null, null, null);
         mCi = Integer.MAX_VALUE;
         mPci = Integer.MAX_VALUE;
         mTac = Integer.MAX_VALUE;
@@ -62,6 +66,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) {
         this(ci, pci, tac, Integer.MAX_VALUE, Integer.MAX_VALUE, String.valueOf(mcc),
                 String.valueOf(mnc), null, null);
@@ -99,7 +104,7 @@
      */
     public CellIdentityLte(int ci, int pci, int tac, int earfcn, int bandwidth, String mccStr,
             String mncStr, String alphal, String alphas) {
-        super(TAG, TYPE_LTE, mccStr, mncStr, alphal, alphas);
+        super(TAG, CellInfo.TYPE_LTE, mccStr, mncStr, alphal, alphas);
         mCi = ci;
         mPci = pci;
         mTac = tac;
@@ -196,6 +201,28 @@
         return mEarfcn;
     }
 
+    /**
+     * A hack to allow tunneling of LTE information via GsmCellLocation
+     * so that older Network Location Providers can return some information
+     * on LTE only networks, see bug 9228974.
+     *
+     * The tunnel'd LTE information is returned as follows:
+     *   LAC = TAC field
+     *   CID = CI field
+     *   PSC = 0.
+     *
+     * @hide
+     */
+    @Override
+    public GsmCellLocation asCellLocation() {
+        GsmCellLocation cl = new GsmCellLocation();
+        int tac = mTac != Integer.MAX_VALUE ? mTac : -1;
+        int cid = mCi != Integer.MAX_VALUE ? mCi : -1;
+        cl.setLacAndCid(tac, cid);
+        cl.setPsc(0);
+        return cl;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(mCi, mPci, mTac, super.hashCode());
@@ -241,7 +268,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_LTE);
+        super.writeToParcel(dest, CellInfo.TYPE_LTE);
         dest.writeInt(mCi);
         dest.writeInt(mPci);
         dest.writeInt(mTac);
@@ -251,7 +278,7 @@
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityLte(Parcel in) {
-        super(TAG, TYPE_LTE, in);
+        super(TAG, CellInfo.TYPE_LTE, in);
         mCi = in.readInt();
         mPci = in.readInt();
         mTac = in.readInt();
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 18ab6d4..5a9e474 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -16,9 +16,8 @@
 
 package android.telephony;
 
-import android.annotation.Nullable;
 import android.os.Parcel;
-import android.text.TextUtils;
+import android.telephony.gsm.GsmCellLocation;
 
 import java.util.Objects;
 
@@ -35,15 +34,18 @@
     private final int mCid;
     // 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown.
     private final int mCpid;
+    // 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
+    private final int mUarfcn;
 
     /**
      * @hide
      */
     public CellIdentityTdscdma() {
-        super(TAG, TYPE_TDSCDMA, null, null, null, null);
+        super(TAG, CellInfo.TYPE_TDSCDMA, null, null, null, null);
         mLac = Integer.MAX_VALUE;
         mCid = Integer.MAX_VALUE;
         mCpid = Integer.MAX_VALUE;
+        mUarfcn = Integer.MAX_VALUE;
     }
 
     /**
@@ -52,11 +54,12 @@
      * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
      * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
      * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+     * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
      *
      * @hide
      */
-    public CellIdentityTdscdma(int mcc, int mnc, int lac, int cid, int cpid) {
-        this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid, null, null);
+    public CellIdentityTdscdma(int mcc, int mnc, int lac, int cid, int cpid, int uarfcn) {
+        this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid, uarfcn, null, null);
     }
 
     /**
@@ -65,39 +68,24 @@
      * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
      * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
      * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
-     *
-     * FIXME: This is a temporary constructor to facilitate migration.
-     * @hide
-     */
-    public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid) {
-        super(TAG, TYPE_TDSCDMA, mcc, mnc, null, null);
-        mLac = lac;
-        mCid = cid;
-        mCpid = cpid;
-    }
-
-    /**
-     * @param mcc 3-digit Mobile Country Code in string format
-     * @param mnc 2 or 3-digit Mobile Network Code in string format
-     * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
-     * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
-     * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+     * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
      * @param alphal long alpha Operator Name String or Enhanced Operator Name String
      * @param alphas short alpha Operator Name String or Enhanced Operator Name String
      *
      * @hide
      */
-    public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid,
+    public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid, int uarfcn,
             String alphal, String alphas) {
-        super(TAG, TYPE_TDSCDMA, mcc, mnc, alphal, alphas);
+        super(TAG, CellInfo.TYPE_TDSCDMA, mcc, mnc, alphal, alphas);
         mLac = lac;
         mCid = cid;
         mCpid = cpid;
+        mUarfcn = uarfcn;
     }
 
     private CellIdentityTdscdma(CellIdentityTdscdma cid) {
         this(cid.mMccStr, cid.mMncStr, cid.mLac, cid.mCid,
-                cid.mCpid, cid.mAlphaLong, cid.mAlphaShort);
+                cid.mCpid, cid.mUarfcn, cid.mAlphaLong, cid.mAlphaShort);
     }
 
     CellIdentityTdscdma copy() {
@@ -141,9 +129,21 @@
         return mCpid;
     }
 
+    /** @hide */
     @Override
-    public int hashCode() {
-        return Objects.hash(mLac, mCid, mCpid, super.hashCode());
+    public int getChannelNumber() {
+        return mUarfcn;
+    }
+
+    /** @hide */
+    @Override
+    public GsmCellLocation asCellLocation() {
+        GsmCellLocation cl = new GsmCellLocation();
+        int lac = mLac != Integer.MAX_VALUE ? mLac : -1;
+        int cid = mCid != Integer.MAX_VALUE ? mCid : -1;
+        cl.setLacAndCid(lac, cid);
+        cl.setPsc(-1); // There is no PSC for TD-SCDMA; not using this for CPI to stem shenanigans
+        return cl;
     }
 
     @Override
@@ -157,24 +157,29 @@
         }
 
         CellIdentityTdscdma o = (CellIdentityTdscdma) other;
-        return TextUtils.equals(mMccStr, o.mMccStr)
-                && TextUtils.equals(mMncStr, o.mMncStr)
-                && mLac == o.mLac
+        return  mLac == o.mLac
                 && mCid == o.mCid
                 && mCpid == o.mCpid
+                && mUarfcn == o.mUarfcn
                 && super.equals(other);
     }
 
     @Override
+    public int hashCode() {
+        return Objects.hash(mLac, mCid, mCpid, mUarfcn, super.hashCode());
+    }
+
+    @Override
     public String toString() {
         return new StringBuilder(TAG)
         .append(":{ mMcc=").append(mMccStr)
         .append(" mMnc=").append(mMncStr)
+        .append(" mAlphaLong=").append(mAlphaLong)
+        .append(" mAlphaShort=").append(mAlphaShort)
         .append(" mLac=").append(mLac)
         .append(" mCid=").append(mCid)
         .append(" mCpid=").append(mCpid)
-        .append(" mAlphaLong=").append(mAlphaLong)
-        .append(" mAlphaShort=").append(mAlphaShort)
+        .append(" mUarfcn=").append(mUarfcn)
         .append("}").toString();
     }
 
@@ -182,19 +187,20 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_TDSCDMA);
+        super.writeToParcel(dest, CellInfo.TYPE_TDSCDMA);
         dest.writeInt(mLac);
         dest.writeInt(mCid);
         dest.writeInt(mCpid);
+        dest.writeInt(mUarfcn);
     }
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityTdscdma(Parcel in) {
-        super(TAG, TYPE_TDSCDMA, in);
+        super(TAG, CellInfo.TYPE_TDSCDMA, in);
         mLac = in.readInt();
         mCid = in.readInt();
         mCpid = in.readInt();
-
+        mUarfcn = in.readInt();
         if (DBG) log(toString());
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 984483e..727d990 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -17,7 +17,9 @@
 package android.telephony;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
+import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 
 import java.util.Objects;
@@ -35,14 +37,15 @@
     private final int mCid;
     // 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
     private final int mPsc;
-    // 16-bit UMTS Absolute RF Channel Number
+    // 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.4
+    @UnsupportedAppUsage
     private final int mUarfcn;
 
     /**
      * @hide
      */
     public CellIdentityWcdma() {
-        super(TAG, TYPE_TDSCDMA, null, null, null, null);
+        super(TAG, CellInfo.TYPE_WCDMA, null, null, null, null);
         mLac = Integer.MAX_VALUE;
         mCid = Integer.MAX_VALUE;
         mPsc = Integer.MAX_VALUE;
@@ -70,7 +73,7 @@
      * @param lac 16-bit Location Area Code, 0..65535
      * @param cid 28-bit UMTS Cell Identity
      * @param psc 9-bit UMTS Primary Scrambling Code
-     * @param uarfcn 16-bit UMTS Absolute RF Channel Number
+     * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
      *
      * @hide
      */
@@ -83,7 +86,7 @@
      * @param lac 16-bit Location Area Code, 0..65535
      * @param cid 28-bit UMTS Cell Identity
      * @param psc 9-bit UMTS Primary Scrambling Code
-     * @param uarfcn 16-bit UMTS Absolute RF Channel Number
+     * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
      * @param mccStr 3-digit Mobile Country Code in string format
      * @param mncStr 2 or 3-digit Mobile Network Code in string format
      * @param alphal long alpha Operator Name String or Enhanced Operator Name String
@@ -93,7 +96,7 @@
      */
     public CellIdentityWcdma (int lac, int cid, int psc, int uarfcn,
                               String mccStr, String mncStr, String alphal, String alphas) {
-        super(TAG, TYPE_WCDMA, mccStr, mncStr, alphal, alphas);
+        super(TAG, CellInfo.TYPE_WCDMA, mccStr, mncStr, alphal, alphas);
         mLac = lac;
         mCid = cid;
         mPsc = psc;
@@ -189,6 +192,19 @@
         return mUarfcn;
     }
 
+    /** @hide */
+    @Override
+    public GsmCellLocation asCellLocation() {
+        GsmCellLocation cl = new GsmCellLocation();
+        int lac = mLac != Integer.MAX_VALUE ? mLac : -1;
+        int cid = mCid != Integer.MAX_VALUE ? mCid : -1;
+        int psc = mPsc != Integer.MAX_VALUE ? mPsc : -1;
+        cl.setLacAndCid(lac, cid);
+        cl.setPsc(psc);
+
+        return cl;
+    }
+
     @Override
     public boolean equals(Object other) {
         if (this == other) {
@@ -227,7 +243,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        super.writeToParcel(dest, TYPE_WCDMA);
+        super.writeToParcel(dest, CellInfo.TYPE_WCDMA);
         dest.writeInt(mLac);
         dest.writeInt(mCid);
         dest.writeInt(mPsc);
@@ -236,7 +252,7 @@
 
     /** Construct from Parcel, type has already been processed */
     private CellIdentityWcdma(Parcel in) {
-        super(TAG, TYPE_WCDMA, in);
+        super(TAG, CellInfo.TYPE_WCDMA, in);
         mLac = in.readInt();
         mCid = in.readInt();
         mPsc = in.readInt();
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 9232ed7..4fe1b01 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -17,8 +17,11 @@
 package android.telephony;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -27,27 +30,60 @@
  */
 public abstract class CellInfo implements Parcelable {
 
-    // Type fields for parceling
-    /** @hide */
-    protected static final int TYPE_GSM = 1;
-    /** @hide */
-    protected static final int TYPE_CDMA = 2;
-    /** @hide */
-    protected static final int TYPE_LTE = 3;
-    /** @hide */
-    protected static final int TYPE_WCDMA = 4;
+    /**
+     * Cell identity type
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "TYPE_", value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA})
+    public @interface Type {}
+    /**
+     * Unknown cell identity type
+     * @hide
+     */
+    public static final int TYPE_UNKNOWN        = 0;
+    /**
+     * GSM cell identity type
+     * @hide
+     */
+    public static final int TYPE_GSM            = 1;
+    /**
+     * CDMA cell identity type
+     * @hide
+     */
+    public static final int TYPE_CDMA           = 2;
+    /**
+     * LTE cell identity type
+     * @hide
+     */
+    public static final int TYPE_LTE            = 3;
+    /**
+     * WCDMA cell identity type
+     * @hide
+     */
+    public static final int TYPE_WCDMA          = 4;
+    /**
+     * TD-SCDMA cell identity type
+     * @hide
+     */
+    public static final int TYPE_TDSCDMA        = 5;
 
     // Type to distinguish where time stamp gets recorded.
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_UNKNOWN = 0;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_ANTENNA = 1;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_MODEM = 2;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_OEM_RIL = 3;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int TIMESTAMP_TYPE_JAVA_RIL = 4;
 
     /** @hide */
@@ -121,6 +157,14 @@
         mTimeStamp = timeStamp;
     }
 
+    /** @hide */
+    @NonNull
+    public abstract CellIdentity getCellIdentity();
+
+    /** @hide */
+    @NonNull
+    public abstract CellSignalStrength getCellSignalStrength();
+
     /**
      * Gets the connection status of this cell.
      *
@@ -146,9 +190,11 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTimeStampType() {
         return mTimeStampType;
     }
+
     /** @hide */
     public void setTimeStampType(int timeStampType) {
         if (timeStampType < TIMESTAMP_TYPE_UNKNOWN || timeStampType > TIMESTAMP_TYPE_JAVA_RIL) {
@@ -184,6 +230,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private static String timeStampTypeToString(int type) {
         switch (type) {
             case 1:
@@ -260,6 +307,7 @@
                     case TYPE_CDMA: return CellInfoCdma.createFromParcelBody(in);
                     case TYPE_LTE: return CellInfoLte.createFromParcelBody(in);
                     case TYPE_WCDMA: return CellInfoWcdma.createFromParcelBody(in);
+                    case TYPE_TDSCDMA: return CellInfoTdscdma.createFromParcelBody(in);
                     default: throw new RuntimeException("Bad CellInfo Parcel");
                 }
         }
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index 6f2f1f6..f67733d 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -16,12 +16,13 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
 
 /**
- * Immutable cell information from a point in time.
+ * A {@link CellInfo} representing a CDMA cell that provides identity and measurement info.
  */
 public final class CellInfoCdma extends CellInfo implements Parcelable {
 
@@ -32,6 +33,7 @@
     private CellSignalStrengthCdma mCellSignalStrengthCdma;
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellInfoCdma() {
         super();
         mCellIdentityCdma = new CellIdentityCdma();
@@ -39,20 +41,24 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellInfoCdma(CellInfoCdma ci) {
         super(ci);
         this.mCellIdentityCdma = ci.mCellIdentityCdma.copy();
         this.mCellSignalStrengthCdma = ci.mCellSignalStrengthCdma.copy();
     }
 
+    @Override
     public CellIdentityCdma getCellIdentity() {
         return mCellIdentityCdma;
     }
     /** @hide */
+    @UnsupportedAppUsage
     public void setCellIdentity(CellIdentityCdma cid) {
         mCellIdentityCdma = cid;
     }
 
+    @Override
     public CellSignalStrengthCdma getCellSignalStrength() {
         return mCellSignalStrengthCdma;
     }
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index 1bedddb..7211de1 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -16,12 +16,13 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
 
 /**
- * Immutable cell information from a point in time.
+ * A {@link CellInfo} representing a GSM cell that provides identity and measurement info.
  */
 public final class CellInfoGsm extends CellInfo implements Parcelable {
 
@@ -32,6 +33,7 @@
     private CellSignalStrengthGsm mCellSignalStrengthGsm;
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellInfoGsm() {
         super();
         mCellIdentityGsm = new CellIdentityGsm();
@@ -45,6 +47,7 @@
         this.mCellSignalStrengthGsm = ci.mCellSignalStrengthGsm.copy();
     }
 
+    @Override
     public CellIdentityGsm getCellIdentity() {
         return mCellIdentityGsm;
     }
@@ -53,6 +56,7 @@
         mCellIdentityGsm = cid;
     }
 
+    @Override
     public CellSignalStrengthGsm getCellSignalStrength() {
         return mCellSignalStrengthGsm;
     }
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 287c9f0..389f643 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -16,12 +16,13 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
 
 /**
- * Immutable cell information from a point in time.
+ * A {@link CellInfo} representing an LTE cell that provides identity and measurement info.
  */
 public final class CellInfoLte extends CellInfo implements Parcelable {
 
@@ -32,6 +33,7 @@
     private CellSignalStrengthLte mCellSignalStrengthLte;
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellInfoLte() {
         super();
         mCellIdentityLte = new CellIdentityLte();
@@ -45,21 +47,25 @@
         this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy();
     }
 
+    @Override
     public CellIdentityLte getCellIdentity() {
         if (DBG) log("getCellIdentity: " + mCellIdentityLte);
         return mCellIdentityLte;
     }
     /** @hide */
+    @UnsupportedAppUsage
     public void setCellIdentity(CellIdentityLte cid) {
         if (DBG) log("setCellIdentity: " + cid);
         mCellIdentityLte = cid;
     }
 
+    @Override
     public CellSignalStrengthLte getCellSignalStrength() {
         if (DBG) log("getCellSignalStrength: " + mCellSignalStrengthLte);
         return mCellSignalStrengthLte;
     }
     /** @hide */
+    @UnsupportedAppUsage
     public void setCellSignalStrength(CellSignalStrengthLte css) {
         if (DBG) log("setCellSignalStrength: " + css);
         mCellSignalStrengthLte = css;
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
new file mode 100644
index 0000000..40cadde
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A {@link CellInfo} representing a TD-SCDMA cell that provides identity and measurement info.
+ *
+ * @hide
+ */
+public final class CellInfoTdscdma extends CellInfo implements Parcelable {
+
+    private static final String LOG_TAG = "CellInfoTdscdma";
+    private static final boolean DBG = false;
+
+    private CellIdentityTdscdma mCellIdentityTdscdma;
+    private CellSignalStrengthTdscdma mCellSignalStrengthTdscdma;
+
+    /** @hide */
+    public CellInfoTdscdma() {
+        super();
+        mCellIdentityTdscdma = new CellIdentityTdscdma();
+        mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma();
+    }
+
+    /** @hide */
+    public CellInfoTdscdma(CellInfoTdscdma ci) {
+        super(ci);
+        this.mCellIdentityTdscdma = ci.mCellIdentityTdscdma.copy();
+        this.mCellSignalStrengthTdscdma = ci.mCellSignalStrengthTdscdma.copy();
+    }
+
+    @Override
+    public CellIdentityTdscdma getCellIdentity() {
+        return mCellIdentityTdscdma;
+    }
+    /** @hide */
+    public void setCellIdentity(CellIdentityTdscdma cid) {
+        mCellIdentityTdscdma = cid;
+    }
+
+    @Override
+    public CellSignalStrengthTdscdma getCellSignalStrength() {
+        return mCellSignalStrengthTdscdma;
+    }
+    /** @hide */
+    public void setCellSignalStrength(CellSignalStrengthTdscdma css) {
+        mCellSignalStrengthTdscdma = css;
+    }
+
+    /**
+     * @return hash code
+     */
+    @Override
+    public int hashCode() {
+        return Objects.hash(super.hashCode(), mCellIdentityTdscdma, mCellSignalStrengthTdscdma);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!super.equals(other)) {
+            return false;
+        }
+        try {
+            CellInfoTdscdma o = (CellInfoTdscdma) other;
+            return mCellIdentityTdscdma.equals(o.mCellIdentityTdscdma)
+                    && mCellSignalStrengthTdscdma.equals(o.mCellSignalStrengthTdscdma);
+        } catch (ClassCastException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("CellInfoTdscdma:{");
+        sb.append(super.toString());
+        sb.append(" ").append(mCellIdentityTdscdma);
+        sb.append(" ").append(mCellSignalStrengthTdscdma);
+        sb.append("}");
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags, TYPE_TDSCDMA);
+        mCellIdentityTdscdma.writeToParcel(dest, flags);
+        mCellSignalStrengthTdscdma.writeToParcel(dest, flags);
+    }
+
+    /**
+     * Construct a CellInfoTdscdma object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellInfoTdscdma(Parcel in) {
+        super(in);
+        mCellIdentityTdscdma = CellIdentityTdscdma.CREATOR.createFromParcel(in);
+        mCellSignalStrengthTdscdma = CellSignalStrengthTdscdma.CREATOR.createFromParcel(in);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellInfoTdscdma> CREATOR = new Creator<CellInfoTdscdma>() {
+        @Override
+        public CellInfoTdscdma createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellInfoTdscdma[] newArray(int size) {
+            return new CellInfoTdscdma[size];
+        }
+    };
+
+    /** @hide */
+    protected static CellInfoTdscdma createFromParcelBody(Parcel in) {
+        return new CellInfoTdscdma(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Rlog.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index 0615702..4f9dcb1 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -20,8 +20,10 @@
 import android.os.Parcelable;
 import android.telephony.Rlog;
 
+import java.util.Objects;
+
 /**
- * Immutable cell information from a point in time.
+ * A {@link CellInfo} representing a WCDMA cell that provides identity and measurement info.
  */
 public final class CellInfoWcdma extends CellInfo implements Parcelable {
 
@@ -45,6 +47,7 @@
         this.mCellSignalStrengthWcdma = ci.mCellSignalStrengthWcdma.copy();
     }
 
+    @Override
     public CellIdentityWcdma getCellIdentity() {
         return mCellIdentityWcdma;
     }
@@ -53,6 +56,7 @@
         mCellIdentityWcdma = cid;
     }
 
+    @Override
     public CellSignalStrengthWcdma getCellSignalStrength() {
         return mCellSignalStrengthWcdma;
     }
@@ -66,7 +70,7 @@
      */
     @Override
     public int hashCode() {
-        return super.hashCode() + mCellIdentityWcdma.hashCode() + mCellSignalStrengthWcdma.hashCode();
+        return Objects.hash(super.hashCode(), mCellIdentityWcdma, mCellSignalStrengthWcdma);
     }
 
     @Override
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index 5bcaa6e..0133153 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -20,6 +20,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.cdma.CdmaCellLocation;
 import android.telephony.gsm.GsmCellLocation;
 import com.android.internal.telephony.ITelephony;
@@ -57,6 +58,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static CellLocation newFromBundle(Bundle bundle) {
         // TelephonyManager.getDefault().getCurrentPhoneType() handles the case when
         // ITelephony interface is not up yet.
@@ -73,11 +75,13 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract void fillInNotifierBundle(Bundle bundle);
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public abstract boolean isEmpty();
 
     /**
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index 183f96d..aa6b207 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -104,7 +104,10 @@
     }
 
     /**
-     * Get signal level as an int from 0..4
+     * Retrieve an abstract level value for the overall signal strength.
+     *
+     * @return a single integer from 0 to 4 representing the general signal quality.
+     *     0 represents very poor signal strength while 4 represents a very strong signal strength.
      */
     @Override
     public int getLevel() {
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 8687cd1..1e8d119 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
@@ -34,11 +35,15 @@
     private static final int GSM_SIGNAL_STRENGTH_GOOD = 8;
     private static final int GSM_SIGNAL_STRENGTH_MODERATE = 5;
 
+    @UnsupportedAppUsage
     private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
+    @UnsupportedAppUsage
     private int mBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+    @UnsupportedAppUsage
     private int mTimingAdvance; // range from 0-219 or Integer.MAX_VALUE if unknown
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellSignalStrengthGsm() {
         setDefaultValues();
     }
@@ -82,7 +87,10 @@
     }
 
     /**
-     * Get signal level as an int from 0..4
+     * Retrieve an abstract level value for the overall signal strength.
+     *
+     * @return a single integer from 0 to 4 representing the general signal quality.
+     *     0 represents very poor signal strength while 4 represents a very strong signal strength.
      */
     @Override
     public int getLevel() {
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 7e86966..ed7d4b2 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
@@ -30,14 +31,21 @@
     private static final String LOG_TAG = "CellSignalStrengthLte";
     private static final boolean DBG = false;
 
+    @UnsupportedAppUsage
     private int mSignalStrength;
+    @UnsupportedAppUsage
     private int mRsrp;
+    @UnsupportedAppUsage
     private int mRsrq;
+    @UnsupportedAppUsage
     private int mRssnr;
+    @UnsupportedAppUsage
     private int mCqi;
+    @UnsupportedAppUsage
     private int mTimingAdvance;
 
     /** @hide */
+    @UnsupportedAppUsage
     public CellSignalStrengthLte() {
         setDefaultValues();
     }
@@ -86,7 +94,10 @@
     }
 
     /**
-     * Get signal level as an int from 0..4
+     * Retrieve an abstract level value for the overall signal strength.
+     *
+     * @return a single integer from 0 to 4 representing the general signal quality.
+     *     0 represents very poor signal strength while 4 represents a very strong signal strength.
      */
     @Override
     public int getLevel() {
@@ -121,6 +132,8 @@
 
     /**
      * Get reference signal received quality
+     *
+     * @return the RSRQ if available or Integer.MAX_VALUE if unavailable.
      */
     public int getRsrq() {
         return mRsrq;
@@ -128,13 +141,17 @@
 
     /**
      * Get reference signal signal-to-noise ratio
+     *
+     * @return the RSSNR if available or Integer.MAX_VALUE if unavailable.
      */
     public int getRssnr() {
         return mRssnr;
     }
 
     /**
-     * Get reference signal received power
+     * Get reference signal received power in dBm
+     *
+     * @return the RSRP of the measured cell.
      */
     public int getRsrp() {
         return mRsrp;
@@ -142,13 +159,17 @@
 
     /**
      * Get channel quality indicator
+     *
+     * @return the CQI if available or Integer.MAX_VALUE if unavailable.
      */
     public int getCqi() {
         return mCqi;
     }
 
     /**
-     * Get signal strength as dBm
+     * Get signal strength in dBm
+     *
+     * @return the RSRP of the measured cell.
      */
     @Override
     public int getDbm() {
@@ -175,7 +196,8 @@
      * Get the timing advance value for LTE, as a value in range of 0..1282.
      * Integer.MAX_VALUE is reported when there is no active RRC
      * connection. Refer to 3GPP 36.213 Sec 4.2.3
-     * @return the LTE timing advance, if available.
+     *
+     * @return the LTE timing advance if available or Integer.MAX_VALUE if unavailable.
      */
     public int getTimingAdvance() {
         return mTimingAdvance;
diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
new file mode 100644
index 0000000..41859a3
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Tdscdma signal strength related information.
+ *
+ * @hide
+ */
+public final class CellSignalStrengthTdscdma extends CellSignalStrength implements Parcelable {
+
+    private static final String LOG_TAG = "CellSignalStrengthTdscdma";
+    private static final boolean DBG = false;
+
+    private static final int TDSCDMA_SIGNAL_STRENGTH_GREAT = 12;
+    private static final int TDSCDMA_SIGNAL_STRENGTH_GOOD = 8;
+    private static final int TDSCDMA_SIGNAL_STRENGTH_MODERATE = 5;
+
+    private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
+                                 // or Integer.MAX_VALUE if unknown
+    private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
+                               // Integer.MAX_VALUE if unknown
+    private int mRscp; // Pilot power (0-96, 255) as defined in TS 27.007 8.69 or Integer.MAX_VALUE
+                       // if unknown
+
+    /** @hide */
+    public CellSignalStrengthTdscdma() {
+        setDefaultValues();
+    }
+
+    /** @hide */
+    public CellSignalStrengthTdscdma(int ss, int ber, int rscp) {
+        mSignalStrength = ss;
+        mBitErrorRate = ber;
+        mRscp = rscp;
+    }
+
+    /** @hide */
+    public CellSignalStrengthTdscdma(CellSignalStrengthTdscdma s) {
+        copyFrom(s);
+    }
+
+    /** @hide */
+    protected void copyFrom(CellSignalStrengthTdscdma s) {
+        mSignalStrength = s.mSignalStrength;
+        mBitErrorRate = s.mBitErrorRate;
+        mRscp = s.mRscp;
+    }
+
+    /** @hide */
+    @Override
+    public CellSignalStrengthTdscdma copy() {
+        return new CellSignalStrengthTdscdma(this);
+    }
+
+    /** @hide */
+    @Override
+    public void setDefaultValues() {
+        mSignalStrength = Integer.MAX_VALUE;
+        mBitErrorRate = Integer.MAX_VALUE;
+        mRscp = Integer.MAX_VALUE;
+    }
+
+    /**
+     * Retrieve an abstract level value for the overall signal strength.
+     *
+     * @return a single integer from 0 to 4 representing the general signal quality.
+     *     0 represents very poor signal strength while 4 represents a very strong signal strength.
+     */
+    @Override
+    public int getLevel() {
+        int level;
+
+        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+        // asu = 0 (-113dB or less) is very weak
+        // signal, its better to show 0 bars to the user in such cases.
+        // asu = 99 is a special case, where the signal strength is unknown.
+        int asu = mSignalStrength;
+        if (asu <= 2 || asu == 99) {
+            level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        } else if (asu >= TDSCDMA_SIGNAL_STRENGTH_GREAT) {
+            level = SIGNAL_STRENGTH_GREAT;
+        } else if (asu >= TDSCDMA_SIGNAL_STRENGTH_GOOD) {
+            level = SIGNAL_STRENGTH_GOOD;
+        } else if (asu >= TDSCDMA_SIGNAL_STRENGTH_MODERATE) {
+            level = SIGNAL_STRENGTH_MODERATE;
+        } else {
+            level = SIGNAL_STRENGTH_POOR;
+        }
+        if (DBG) log("getLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get the signal strength as dBm
+     */
+    @Override
+    public int getDbm() {
+        int dBm;
+
+        int level = mSignalStrength;
+        int asu = (level == 99 ? Integer.MAX_VALUE : level);
+        if (asu != Integer.MAX_VALUE) {
+            dBm = -113 + (2 * asu);
+        } else {
+            dBm = Integer.MAX_VALUE;
+        }
+        if (DBG) log("getDbm=" + dBm);
+        return dBm;
+    }
+
+    /**
+     * Get the signal level as an asu value between 0..31, 99 is unknown
+     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     */
+    @Override
+    public int getAsuLevel() {
+        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+        // asu = 0 (-113dB or less) is very weak
+        // signal, its better to show 0 bars to the user in such cases.
+        // asu = 99 is a special case, where the signal strength is unknown.
+        int level = mSignalStrength;
+        if (DBG) log("getAsuLevel=" + level);
+        return level;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mSignalStrength, mBitErrorRate);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        CellSignalStrengthTdscdma s;
+
+        try {
+            s = (CellSignalStrengthTdscdma) o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return mSignalStrength == s.mSignalStrength
+                && mBitErrorRate == s.mBitErrorRate
+                && mRscp == s.mRscp;
+    }
+
+    /**
+     * @return string representation.
+     */
+    @Override
+    public String toString() {
+        return "CellSignalStrengthTdscdma:"
+                + " ss=" + mSignalStrength
+                + " ber=" + mBitErrorRate
+                + " rscp=" + mRscp;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(mSignalStrength);
+        dest.writeInt(mBitErrorRate);
+        dest.writeInt(mRscp);
+    }
+
+    /**
+     * Construct a SignalStrength object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellSignalStrengthTdscdma(Parcel in) {
+        mSignalStrength = in.readInt();
+        mBitErrorRate = in.readInt();
+        mRscp = in.readInt();
+        if (DBG) log("CellSignalStrengthTdscdma(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Parcelable.Creator<CellSignalStrengthTdscdma> CREATOR =
+            new Parcelable.Creator<CellSignalStrengthTdscdma>() {
+        @Override
+        public CellSignalStrengthTdscdma createFromParcel(Parcel in) {
+            return new CellSignalStrengthTdscdma(in);
+        }
+
+        @Override
+        public CellSignalStrengthTdscdma[] newArray(int size) {
+            return new CellSignalStrengthTdscdma[size];
+        }
+    };
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Rlog.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index dd32a96..66e0882 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Rlog;
@@ -34,8 +35,16 @@
     private static final int WCDMA_SIGNAL_STRENGTH_GOOD = 8;
     private static final int WCDMA_SIGNAL_STRENGTH_MODERATE = 5;
 
+    @UnsupportedAppUsage
     private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
-    private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+                                 // or Integer.MAX_VALUE if unknown
+    @UnsupportedAppUsage
+    private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
+                               // Integer.MAX_VALUE if unknown
+    private int mRscp; // bit error rate (0-96, 255) as defined in TS 27.007 8.69 or
+                       // Integer.MAX_VALUE if unknown
+    private int mEcNo; // signal to noise radio (0-49, 255) as defined in TS 27.007 8.69 or
+                       // Integer.MAX_VALUE if unknown
 
     /** @hide */
     public CellSignalStrengthWcdma() {
@@ -43,9 +52,11 @@
     }
 
     /** @hide */
-    public CellSignalStrengthWcdma(int ss, int ber) {
+    public CellSignalStrengthWcdma(int ss, int ber, int rscp, int ecno) {
         mSignalStrength = ss;
         mBitErrorRate = ber;
+        mRscp = rscp;
+        mEcNo = ecno;
     }
 
     /** @hide */
@@ -57,6 +68,8 @@
     protected void copyFrom(CellSignalStrengthWcdma s) {
         mSignalStrength = s.mSignalStrength;
         mBitErrorRate = s.mBitErrorRate;
+        mRscp = s.mRscp;
+        mEcNo = s.mEcNo;
     }
 
     /** @hide */
@@ -70,10 +83,15 @@
     public void setDefaultValues() {
         mSignalStrength = Integer.MAX_VALUE;
         mBitErrorRate = Integer.MAX_VALUE;
+        mRscp = Integer.MAX_VALUE;
+        mEcNo = Integer.MAX_VALUE;
     }
 
     /**
-     * Get signal level as an int from 0..4
+     * Retrieve an abstract level value for the overall signal strength.
+     *
+     * @return a single integer from 0 to 4 representing the general signal quality.
+     *     0 represents very poor signal strength while 4 represents a very strong signal strength.
      */
     @Override
     public int getLevel() {
@@ -145,7 +163,10 @@
             return false;
         }
 
-        return mSignalStrength == s.mSignalStrength && mBitErrorRate == s.mBitErrorRate;
+        return mSignalStrength == s.mSignalStrength
+                && mBitErrorRate == s.mBitErrorRate
+                && mRscp == s.mRscp
+                && mEcNo == s.mEcNo;
     }
 
     /**
@@ -155,7 +176,9 @@
     public String toString() {
         return "CellSignalStrengthWcdma:"
                 + " ss=" + mSignalStrength
-                + " ber=" + mBitErrorRate;
+                + " ber=" + mBitErrorRate
+                + " rscp=" + mRscp
+                + " ecno=" + mEcNo;
     }
 
     /** Implement the Parcelable interface */
@@ -164,6 +187,8 @@
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
         dest.writeInt(mSignalStrength);
         dest.writeInt(mBitErrorRate);
+        dest.writeInt(mRscp);
+        dest.writeInt(mEcNo);
     }
 
     /**
@@ -173,6 +198,8 @@
     private CellSignalStrengthWcdma(Parcel in) {
         mSignalStrength = in.readInt();
         mBitErrorRate = in.readInt();
+        mRscp = in.readInt();
+        mEcNo = in.readInt();
         if (DBG) log("CellSignalStrengthWcdma(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 4fa304a..ee5cdc2 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Contains disconnect call causes generated by the framework and the RIL.
  * @hide
@@ -329,6 +331,7 @@
     }
 
     /** Returns descriptive string for the specified disconnect cause. */
+    @UnsupportedAppUsage
     public static String toString(int cause) {
         switch (cause) {
         case NOT_DISCONNECTED:
diff --git a/telephony/java/android/telephony/ModemInfo.java b/telephony/java/android/telephony/ModemInfo.java
new file mode 100644
index 0000000..564effe
--- /dev/null
+++ b/telephony/java/android/telephony/ModemInfo.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Information of a single logical modem indicating
+ * its id, supported rats and whether it supports voice or data, etc.
+ * @hide
+ */
+public class ModemInfo implements Parcelable {
+    public final int modemId;
+    public final int rat; /* bitset */
+    public final boolean isVoiceSupported;
+    public final boolean isDataSupported;
+
+    public ModemInfo(int modemId, int rat, boolean isVoiceSupported, boolean isDataSupported) {
+        this.modemId = modemId;
+        this.rat = rat;
+        this.isVoiceSupported = isVoiceSupported;
+        this.isDataSupported = isDataSupported;
+    }
+
+    public ModemInfo(Parcel in) {
+        modemId = in.readInt();
+        rat = in.readInt();
+        isVoiceSupported = in.readBoolean();
+        isDataSupported = in.readBoolean();
+    }
+
+    @Override
+    public String toString() {
+        return "modemId=" + modemId + " rat=" + rat + " isVoiceSupported:" + isVoiceSupported
+                + " isDataSupported:" + isDataSupported;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(modemId, rat, isVoiceSupported, isDataSupported);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof ModemInfo) || hashCode() != o.hashCode()) {
+            return false;
+        }
+
+        if (this == o) {
+            return true;
+        }
+
+        ModemInfo s = (ModemInfo) o;
+
+        return (modemId == s.modemId
+                && rat == s.rat
+                && isVoiceSupported == s.isVoiceSupported
+                && isDataSupported == s.isDataSupported);
+    }
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    public @ContentsFlags int describeContents() {
+        return 0;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    public void writeToParcel(Parcel dest, @WriteFlags int flags) {
+        dest.writeInt(modemId);
+        dest.writeInt(rat);
+        dest.writeBoolean(isVoiceSupported);
+        dest.writeBoolean(isDataSupported);
+    }
+
+    public static final Parcelable.Creator<ModemInfo> CREATOR = new Parcelable.Creator() {
+        public ModemInfo createFromParcel(Parcel in) {
+            return new ModemInfo(in);
+        }
+
+        public ModemInfo[] newArray(int size) {
+            return new ModemInfo[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index 25851e3..8e99518 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -16,16 +16,17 @@
 
 package android.telephony;
 
-import android.os.Parcel;
-import android.os.Parcelable;
-import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
 import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
 import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
-import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
 import static android.telephony.TelephonyManager.NETWORK_TYPE_HSDPA;
-import static android.telephony.TelephonyManager.NETWORK_TYPE_HSUPA;
 import static android.telephony.TelephonyManager.NETWORK_TYPE_HSPA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_HSUPA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
 
+import android.annotation.UnsupportedAppUsage;
+import android.os.Parcel;
+import android.os.Parcelable;
 
 
 /**
@@ -47,24 +48,29 @@
      * In GSM, mRssi is the Received RSSI;
      * In UMTS, mRssi is the Level index of CPICH Received Signal Code Power
      */
+    @UnsupportedAppUsage
     private int mRssi;
     /**
      * CID in 16 bits format in GSM. Return UNKNOWN_CID in UMTS and CMDA.
      */
+    @UnsupportedAppUsage
     private int mCid;
     /**
      * LAC in 16 bits format in GSM. Return UNKNOWN_CID in UMTS and CMDA.
      */
+    @UnsupportedAppUsage
     private int mLac;
     /**
      * Primary Scrambling Code in 9 bits format in UMTS
      * Return UNKNOWN_CID in GSM and CMDA.
      */
+    @UnsupportedAppUsage
     private int mPsc;
     /**
      * Radio network type, value is one of following
      * TelephonyManager.NETWORK_TYPE_XXXXXX.
      */
+    @UnsupportedAppUsage
     private int mNetworkType;
 
     /**
@@ -100,6 +106,39 @@
         mCid = cid;
     }
 
+    /** @hide */
+    public NeighboringCellInfo(final CellInfoGsm info) {
+        mNetworkType = TelephonyManager.NETWORK_TYPE_GPRS;
+
+        mRssi = info.getCellSignalStrength().getAsuLevel();
+        if (mRssi == Integer.MAX_VALUE) mRssi = UNKNOWN_RSSI;
+
+        mLac = info.getCellIdentity().getLac();
+        if (mLac == Integer.MAX_VALUE) mLac = UNKNOWN_CID;
+
+        mCid = info.getCellIdentity().getCid();
+        if (mCid == Integer.MAX_VALUE) mCid = UNKNOWN_CID;
+
+        mPsc = UNKNOWN_CID;
+    }
+
+    /** @hide */
+    public NeighboringCellInfo(final CellInfoWcdma info) {
+        mNetworkType = TelephonyManager.NETWORK_TYPE_UMTS;
+
+        mRssi = info.getCellSignalStrength().getAsuLevel();
+        if (mRssi == Integer.MAX_VALUE) mRssi = UNKNOWN_RSSI;
+
+        mLac = info.getCellIdentity().getLac();
+        if (mLac == Integer.MAX_VALUE) mLac = UNKNOWN_CID;
+
+        mCid = info.getCellIdentity().getCid();
+        if (mCid == Integer.MAX_VALUE) mCid = UNKNOWN_CID;
+
+        mPsc = info.getCellIdentity().getPsc();
+        if (mPsc == Integer.MAX_VALUE) mPsc = UNKNOWN_CID;
+    }
+
     /**
      * Initialize the object from rssi, location string, and radioType
      * radioType is one of following
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index bba779d..c393155 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -21,6 +21,7 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.AccessNetworkConstants.TransportType;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -59,15 +60,15 @@
     /** Not registered. The device is not currently searching a new operator to register */
     public static final int REG_STATE_NOT_REG_NOT_SEARCHING = 0;
     /** Registered on home network */
-    public static final int REG_STATE_HOME = 1;
+    public static final int REG_STATE_HOME                  = 1;
     /** Not registered. The device is currently searching a new operator to register */
-    public static final int REG_STATE_NOT_REG_SEARCHING = 2;
+    public static final int REG_STATE_NOT_REG_SEARCHING     = 2;
     /** Registration denied */
-    public static final int REG_STATE_DENIED = 3;
+    public static final int REG_STATE_DENIED                = 3;
     /** Registration state is unknown */
-    public static final int REG_STATE_UNKNOWN = 4;
+    public static final int REG_STATE_UNKNOWN               = 4;
     /** Registered on roaming network */
-    public static final int REG_STATE_ROAMING = 5;
+    public static final int REG_STATE_ROAMING               = 5;
 
     /**
      * Supported service type
@@ -79,24 +80,24 @@
                     SERVICE_TYPE_EMERGENCY})
     public @interface ServiceType {}
 
-    public static final int SERVICE_TYPE_VOICE = 1;
-    public static final int SERVICE_TYPE_DATA = 2;
-    public static final int SERVICE_TYPE_SMS = 3;
-    public static final int SERVICE_TYPE_VIDEO = 4;
-    public static final int SERVICE_TYPE_EMERGENCY = 5;
-
-    /** {@link AccessNetworkConstants.TransportType}*/
-    private final int mTransportType;
+    public static final int SERVICE_TYPE_VOICE      = 1;
+    public static final int SERVICE_TYPE_DATA       = 2;
+    public static final int SERVICE_TYPE_SMS        = 3;
+    public static final int SERVICE_TYPE_VIDEO      = 4;
+    public static final int SERVICE_TYPE_EMERGENCY  = 5;
 
     @Domain
     private final int mDomain;
 
+    /** {@link TransportType} */
+    private final int mTransportType;
+
     @RegState
     private final int mRegState;
 
     private final int mAccessNetworkTechnology;
 
-    private final int mReasonForDenial;
+    private final int mRejectCause;
 
     private final boolean mEmergencyOnly;
 
@@ -112,22 +113,35 @@
     private DataSpecificRegistrationStates mDataSpecificStates;
 
     /**
-     * @param transportType Transport type. Must be {@link AccessNetworkConstants.TransportType}
-     * @param domain Network domain. Must be DOMAIN_CS or DOMAIN_PS.
-     * @param regState Network registration state.
-     * @param accessNetworkTechnology See TelephonyManager NETWORK_TYPE_XXXX.
-     * @param reasonForDenial Reason for denial if the registration state is DENIED.
-     * @param availableServices The supported service.
-     * @param cellIdentity The identity representing a unique cell
+     * @param domain Network domain. Must be a {@link Domain}. For {@link TransportType#WLAN}
+     * transport, this must set to {@link #DOMAIN_PS}.
+     * @param transportType Transport type. Must be one of the{@link TransportType}.
+     * @param regState Network registration state. Must be one of the {@link RegState}. For
+     * {@link TransportType#WLAN} transport, only {@link #REG_STATE_HOME} and
+     * {@link #REG_STATE_NOT_REG_NOT_SEARCHING} are valid states.
+     * @param accessNetworkTechnology Access network technology. Must be one of TelephonyManager
+     * NETWORK_TYPE_XXXX. For {@link TransportType#WLAN} transport, set to
+     * {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
+     * @param rejectCause Reason for denial if the registration state is {@link #REG_STATE_DENIED}.
+     * Depending on {@code accessNetworkTechnology}, the values are defined in 3GPP TS 24.008
+     * 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA. If
+     * the reject cause is not supported or unknown, set it to 0.
+     * // TODO: Add IWLAN reject cause reference
+     * @param emergencyOnly True if this registration is for emergency only.
+     * @param availableServices The list of the supported services. Each element must be one of
+     * the {@link ServiceType}.
+     * @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
+     * information is not available.
      */
-    public NetworkRegistrationState(int transportType, int domain, int regState,
-            int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
-            int[] availableServices, @Nullable CellIdentity cellIdentity) {
-        mTransportType = transportType;
+    public NetworkRegistrationState(@Domain int domain, int transportType, @RegState int regState,
+                                    int accessNetworkTechnology, int rejectCause,
+                                    boolean emergencyOnly, int[] availableServices,
+                                    @Nullable CellIdentity cellIdentity) {
         mDomain = domain;
+        mTransportType = transportType;
         mRegState = regState;
         mAccessNetworkTechnology = accessNetworkTechnology;
-        mReasonForDenial = reasonForDenial;
+        mRejectCause = rejectCause;
         mAvailableServices = availableServices;
         mCellIdentity = cellIdentity;
         mEmergencyOnly = emergencyOnly;
@@ -137,12 +151,14 @@
      * Constructor for voice network registration states.
      * @hide
      */
-    public NetworkRegistrationState(int transportType, int domain, int regState,
-            int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
-            int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
-            int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
-        this(transportType, domain, regState, accessNetworkTechnology,
-                reasonForDenial, emergencyOnly, availableServices, cellIdentity);
+    public NetworkRegistrationState(int domain, int transportType, int regState,
+                                    int accessNetworkTechnology, int rejectCause,
+                                    boolean emergencyOnly, int[] availableServices,
+                                    @Nullable CellIdentity cellIdentity, boolean cssSupported,
+                                    int roamingIndicator, int systemIsInPrl,
+                                    int defaultRoamingIndicator) {
+        this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
+                availableServices, cellIdentity);
 
         mVoiceSpecificStates = new VoiceSpecificRegistrationStates(cssSupported, roamingIndicator,
                 systemIsInPrl, defaultRoamingIndicator);
@@ -152,21 +168,22 @@
      * Constructor for data network registration states.
      * @hide
      */
-    public NetworkRegistrationState(int transportType, int domain, int regState,
-            int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
-            int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls) {
-        this(transportType, domain, regState, accessNetworkTechnology,
-                reasonForDenial, emergencyOnly, availableServices, cellIdentity);
+    public NetworkRegistrationState(int domain, int transportType, int regState,
+                                    int accessNetworkTechnology, int rejectCause,
+                                    boolean emergencyOnly, int[] availableServices,
+                                    @Nullable CellIdentity cellIdentity, int maxDataCalls) {
+        this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
+                availableServices, cellIdentity);
 
         mDataSpecificStates = new DataSpecificRegistrationStates(maxDataCalls);
     }
 
     protected NetworkRegistrationState(Parcel source) {
-        mTransportType = source.readInt();
         mDomain = source.readInt();
+        mTransportType = source.readInt();
         mRegState = source.readInt();
         mAccessNetworkTechnology = source.readInt();
-        mReasonForDenial = source.readInt();
+        mRejectCause = source.readInt();
         mEmergencyOnly = source.readBoolean();
         mAvailableServices = source.createIntArray();
         mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader());
@@ -211,10 +228,10 @@
     }
 
     /**
-     * @return Reason for denial from network.
+     * @return Network reject cause
      */
-    public int getReasonForDenial() {
-        return mReasonForDenial;
+    public int getRejectCause() {
+        return mRejectCause;
     }
 
     /**
@@ -260,12 +277,12 @@
     @Override
     public String toString() {
         return new StringBuilder("NetworkRegistrationState{")
-                .append("transportType=").append(mTransportType)
                 .append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
+                .append("transportType=").append(mTransportType)
                 .append(" regState=").append(regStateToString(mRegState))
                 .append(" accessNetworkTechnology=")
                 .append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
-                .append(" reasonForDenial=").append(mReasonForDenial)
+                .append(" rejectCause=").append(mRejectCause)
                 .append(" emergencyEnabled=").append(mEmergencyOnly)
                 .append(" supportedServices=").append(mAvailableServices)
                 .append(" cellIdentity=").append(mCellIdentity)
@@ -276,8 +293,8 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mTransportType, mDomain, mRegState, mAccessNetworkTechnology,
-                mReasonForDenial, mEmergencyOnly, mAvailableServices, mCellIdentity,
+        return Objects.hash(mDomain, mTransportType, mRegState, mAccessNetworkTechnology,
+                mRejectCause, mEmergencyOnly, mAvailableServices, mCellIdentity,
                 mVoiceSpecificStates, mDataSpecificStates);
     }
 
@@ -290,11 +307,11 @@
         }
 
         NetworkRegistrationState other = (NetworkRegistrationState) o;
-        return mTransportType == other.mTransportType
-                && mDomain == other.mDomain
+        return mDomain == other.mDomain
+                && mTransportType == other.mTransportType
                 && mRegState == other.mRegState
                 && mAccessNetworkTechnology == other.mAccessNetworkTechnology
-                && mReasonForDenial == other.mReasonForDenial
+                && mRejectCause == other.mRejectCause
                 && mEmergencyOnly == other.mEmergencyOnly
                 && (mAvailableServices == other.mAvailableServices
                     || Arrays.equals(mAvailableServices, other.mAvailableServices))
@@ -305,11 +322,11 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mTransportType);
         dest.writeInt(mDomain);
+        dest.writeInt(mTransportType);
         dest.writeInt(mRegState);
         dest.writeInt(mAccessNetworkTechnology);
-        dest.writeInt(mReasonForDenial);
+        dest.writeInt(mRejectCause);
         dest.writeBoolean(mEmergencyOnly);
         dest.writeIntArray(mAvailableServices);
         dest.writeParcelable(mCellIdentity, 0);
diff --git a/telephony/java/android/telephony/PhoneCapability.aidl b/telephony/java/android/telephony/PhoneCapability.aidl
new file mode 100644
index 0000000..5de8d4a
--- /dev/null
+++ b/telephony/java/android/telephony/PhoneCapability.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.telephony;
+
+parcelable PhoneCapability;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
new file mode 100644
index 0000000..2ebfa53
--- /dev/null
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Define capability of a modem group. That is, the capabilities
+ * are shared between those modems defined by list of modem IDs.
+ * @hide
+ */
+public class PhoneCapability implements Parcelable {
+    public final int maxActiveVoiceCalls;
+    public final int maxActiveData;
+    public final int max5G;
+    public final List<ModemInfo> logicalModemList;
+
+    public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G,
+            List<ModemInfo> logicalModemList) {
+        this.maxActiveVoiceCalls = maxActiveVoiceCalls;
+        this.maxActiveData = maxActiveData;
+        this.max5G = max5G;
+        // Make sure it's not null.
+        this.logicalModemList = logicalModemList == null ? new ArrayList<>() : logicalModemList;
+    }
+
+    @Override
+    public String toString() {
+        return "maxActiveVoiceCalls=" + maxActiveVoiceCalls + " maxActiveData=" + maxActiveData
+                + " max5G=" + max5G + "logicalModemList:"
+                + Arrays.toString(logicalModemList.toArray());
+    }
+
+    private PhoneCapability(Parcel in) {
+        maxActiveVoiceCalls = in.readInt();
+        maxActiveData = in.readInt();
+        max5G = in.readInt();
+        logicalModemList = new ArrayList<>();
+        in.readList(logicalModemList, ModemInfo.class.getClassLoader());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(maxActiveVoiceCalls, maxActiveData, max5G, logicalModemList);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof PhoneCapability) || hashCode() != o.hashCode()) {
+            return false;
+        }
+
+        if (this == o) {
+            return true;
+        }
+
+        PhoneCapability s = (PhoneCapability) o;
+
+        return (maxActiveVoiceCalls == s.maxActiveVoiceCalls
+                && maxActiveData == s.maxActiveData
+                && max5G == s.max5G
+                && logicalModemList.equals(s.logicalModemList));
+    }
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    public @Parcelable.ContentsFlags int describeContents() {
+        return 0;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) {
+        dest.writeInt(maxActiveVoiceCalls);
+        dest.writeInt(maxActiveData);
+        dest.writeInt(max5G);
+        dest.writeList(logicalModemList);
+    }
+
+    public static final Parcelable.Creator<PhoneCapability> CREATOR = new Parcelable.Creator() {
+        public PhoneCapability createFromParcel(Parcel in) {
+            return new PhoneCapability(in);
+        }
+
+        public PhoneCapability[] newArray(int size) {
+            return new PhoneCapability[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index f7dee99..ac6bcaa 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -19,6 +19,7 @@
 import com.android.i18n.phonenumbers.AsYouTypeFormatter;
 import com.android.i18n.phonenumbers.PhoneNumberUtil;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.PhoneNumberUtils;
 import android.text.Editable;
 import android.text.Selection;
@@ -50,6 +51,7 @@
      */
     private boolean mStopFormatting;
 
+    @UnsupportedAppUsage
     private AsYouTypeFormatter mFormatter;
 
     /**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index fadfc91..f6e8d34 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -23,6 +23,7 @@
 import com.android.i18n.phonenumbers.ShortNumberInfo;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -279,6 +280,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String extractNetworkPortionAlt(String phoneNumber) {
         if (phoneNumber == null) {
             return null;
@@ -352,6 +354,7 @@
      * RFC 3601 says pause is 'p' and tonewait is 'w'.
      * @hide
      */
+    @UnsupportedAppUsage
     public static String convertPreDial(String phoneNumber) {
         if (phoneNumber == null) {
             return null;
@@ -464,6 +467,7 @@
     /**
      * @hide only for testing.
      */
+    @UnsupportedAppUsage
     public static boolean compare(String a, String b, boolean useStrictComparation) {
         return (useStrictComparation ? compareStrictly(a, b) : compareLoosely(a, b));
     }
@@ -482,6 +486,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean
     compareLoosely(String a, String b) {
         int ia, ib;
@@ -579,6 +584,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean
     compareStrictly(String a, String b) {
         return compareStrictly(a, b, true);
@@ -587,6 +593,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean
     compareStrictly(String a, String b, boolean acceptInvalidCCCPrefix) {
         if (a == null || b == null) {
@@ -1260,6 +1267,7 @@
      * @deprecated Use link #formatNumber(String phoneNumber, String defaultCountryIso) instead
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static String formatNumber(String source, int defaultFormattingType) {
         SpannableStringBuilder text = new SpannableStringBuilder(source);
         formatNumber(text, defaultFormattingType);
@@ -1720,6 +1728,7 @@
     //
     // However, in order to loose match 650-555-1212 and 555-1212, we need to set the min match
     // to 7.
+    @UnsupportedAppUsage
     static final int MIN_MATCH = 7;
 
     /**
@@ -1744,6 +1753,7 @@
      *         listed in the RIL / SIM, otherwise return false.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isEmergencyNumber(int subId, String number) {
         // Return true only if the specified number *exactly* matches
         // one of the emergency numbers listed by the RIL / SIM.
@@ -1794,6 +1804,7 @@
      *         same digits as any of those emergency numbers.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isPotentialEmergencyNumber(int subId, String number) {
         // Check against the emergency numbers listed by the RIL / SIM,
         // and *don't* require an exact match.
@@ -1858,6 +1869,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isEmergencyNumber(String number, String defaultCountryIso) {
             return isEmergencyNumber(getDefaultVoiceSubId(), number, defaultCountryIso);
     }
@@ -2081,6 +2093,7 @@
      * is currently in.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isLocalEmergencyNumber(Context context, int subId, String number) {
         return isLocalEmergencyNumberInternal(subId, number,
                                               context,
@@ -2109,6 +2122,7 @@
      * @see android.location.CountryDetector
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isPotentialLocalEmergencyNumber(Context context, String number) {
         return isPotentialLocalEmergencyNumber(context, getDefaultVoiceSubId(), number);
     }
@@ -2135,6 +2149,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isPotentialLocalEmergencyNumber(Context context, int subId,
             String number) {
         return isLocalEmergencyNumberInternal(subId, number,
@@ -2244,6 +2259,7 @@
      * to read the VM number.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isVoiceMailNumber(Context context, int subId, String number) {
         String vmNumber, mdn;
         try {
@@ -2390,6 +2406,7 @@
      *
      * @hide TODO: pending API Council approval
      */
+    @UnsupportedAppUsage
     public static String cdmaCheckAndProcessPlusCode(String dialStr) {
         if (!TextUtils.isEmpty(dialStr)) {
             if (isReallyDialable(dialStr.charAt(0)) &&
@@ -2569,6 +2586,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
         return createTtsSpannable(phoneNumber);
     }
@@ -2680,6 +2698,7 @@
      * i.e. NXX-NXX-XXXX, N is any digit 2-9 and X is any digit 0-9
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isNanp (String dialStr) {
         boolean retVal = false;
         if (dialStr != null) {
@@ -2727,6 +2746,7 @@
      * @param number
      * @return true if number contains @
      */
+    @UnsupportedAppUsage
     public static boolean isUriNumber(String number) {
         // Note we allow either "@" or "%40" to indicate a URI, in case
         // the passed-in string is URI-escaped.  (Neither "@" nor "%40"
@@ -2744,6 +2764,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String getUsernameFromUriNumber(String number) {
         // The delimiter between username and domain name can be
         // either "@" or "%40" (the URI-escaped equivalent.)
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 8420165..bd6a59d 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -17,16 +17,16 @@
 package android.telephony;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.telecom.TelecomManager;
 
 import com.android.internal.telephony.IPhoneStateListener;
 
-import java.util.List;
 import java.lang.ref.WeakReference;
+import java.util.List;
 
 /**
  * A listener class for monitoring changes in specific telephony states
@@ -171,6 +171,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int LISTEN_PRECISE_CALL_STATE                       = 0x00000800;
 
     /**
@@ -271,11 +272,20 @@
      */
     public static final int LISTEN_PHYSICAL_CHANNEL_CONFIGURATION          = 0x00100000;
 
+    /**
+     *  Listen for changes to the phone capability.
+     *
+     *  @see #onPhoneCapabilityChanged
+     *  @hide
+     */
+    public static final int LISTEN_PHONE_CAPABILITY_CHANGE                 = 0x00200000;
+
     /*
      * Subscription used to listen to the phone state changes
      * @hide
      */
     /** @hide */
+    @UnsupportedAppUsage
     protected Integer mSubId;
 
     private final Handler mHandler;
@@ -293,6 +303,7 @@
      * using a particular non-null Looper.
      * @hide
      */
+    @UnsupportedAppUsage
     public PhoneStateListener(Looper looper) {
         this(null, looper);
     }
@@ -303,6 +314,7 @@
      * own non-null Looper use PhoneStateListener(int subId, Looper looper) below.
      * @hide
      */
+    @UnsupportedAppUsage
     public PhoneStateListener(Integer subId) {
         this(subId, Looper.myLooper());
     }
@@ -312,6 +324,7 @@
      * and non-null Looper.
      * @hide
      */
+    @UnsupportedAppUsage
     public PhoneStateListener(Integer subId, Looper looper) {
         if (DBG) log("ctor: subId=" + subId + " looper=" + looper);
         mSubId = subId;
@@ -389,6 +402,10 @@
                         PhoneStateListener.this.onPhysicalChannelConfigurationChanged(
                                 (List<PhysicalChannelConfig>)msg.obj);
                         break;
+                    case LISTEN_PHONE_CAPABILITY_CHANGE:
+                        PhoneStateListener.this.onPhoneCapabilityChanged(
+                                (PhoneCapability) msg.obj);
+                        break;
                 }
             }
         };
@@ -515,6 +532,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void onOtaspChanged(int otaspMode) {
         // default implementation empty
     }
@@ -532,6 +550,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void onPreciseCallStateChanged(PreciseCallState callState) {
         // default implementation empty
     }
@@ -541,6 +560,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void onPreciseDataConnectionStateChanged(
             PreciseDataConnectionState dataConnectionState) {
         // default implementation empty
@@ -551,6 +571,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void onDataConnectionRealTimeInfoChanged(
             DataConnectionRealTimeInfo dcRtInfo) {
         // default implementation empty
@@ -562,6 +583,7 @@
      * @param stateInfo is the current LTE network information
      * @hide
      */
+    @UnsupportedAppUsage
     public void onVoLteServiceStateChanged(VoLteServiceState stateInfo) {
     }
 
@@ -608,11 +630,22 @@
      * @param rawData is the byte array of the OEM hook raw data.
      * @hide
      */
+    @UnsupportedAppUsage
     public void onOemHookRawEvent(byte[] rawData) {
         // default implementation empty
     }
 
     /**
+     * Callback invoked when phone capability changes. Requires
+     * the READ_PRIVILEGED_PHONE_STATE permission.
+     * @param capability the new phone capability
+     * @hide
+     */
+    public void onPhoneCapabilityChanged(PhoneCapability capability) {
+        // default implementation empty
+    }
+
+    /**
      * Callback invoked when telephony has received notice from a carrier
      * app that a network action that could result in connectivity loss
      * has been requested by an app using
@@ -739,8 +772,13 @@
         public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
             send(LISTEN_PHYSICAL_CHANNEL_CONFIGURATION, 0, 0, configs);
         }
+
+        public void onPhoneCapabilityChanged(PhoneCapability capability) {
+            send(LISTEN_PHONE_CAPABILITY_CHANGE, 0, 0, capability);
+        }
     }
 
+    @UnsupportedAppUsage
     IPhoneStateListener callback = new IPhoneStateListenerStub(this);
 
     private void log(String s) {
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index f246416..ed5c26a 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.DisconnectCause;
@@ -71,6 +72,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PreciseCallState(int ringingCall, int foregroundCall, int backgroundCall,
             int disconnectCause, int preciseDisconnectCause) {
         mRingingCallState = ringingCall;
@@ -113,6 +115,7 @@
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
      */
+    @UnsupportedAppUsage
     public int getRingingCallState() {
         return mRingingCallState;
     }
@@ -131,6 +134,7 @@
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
      */
+    @UnsupportedAppUsage
     public int getForegroundCallState() {
         return mForegroundCallState;
     }
@@ -149,6 +153,7 @@
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
      * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
      */
+    @UnsupportedAppUsage
     public int getBackgroundCallState() {
         return mBackgroundCallState;
     }
@@ -195,6 +200,7 @@
      * @see DisconnectCause#CDMA_ACCESS_BLOCKED
      * @see DisconnectCause#ERROR_UNSPECIFIED
      */
+    @UnsupportedAppUsage
     public int getDisconnectCause() {
         return mDisconnectCause;
     }
@@ -233,6 +239,7 @@
      * @see PreciseDisconnectCause#CDMA_ACCESS_BLOCKED
      * @see PreciseDisconnectCause#ERROR_UNSPECIFIED
      */
+    @UnsupportedAppUsage
     public int getPreciseDisconnectCause() {
         return mPreciseDisconnectCause;
     }
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 31c9a9e..b258f52 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.TelephonyManager;
@@ -53,6 +54,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PreciseDataConnectionState(int state, int networkType,
             String apnType, String apn, String reason,
             LinkProperties linkProperties, String failCause) {
@@ -95,6 +97,7 @@
      * @see TelephonyManager#DATA_CONNECTED
      * @see TelephonyManager#DATA_SUSPENDED
      */
+    @UnsupportedAppUsage
     public int getDataConnectionState() {
         return mState;
     }
@@ -119,6 +122,7 @@
      * @see TelephonyManager#NETWORK_TYPE_EHRPD
      * @see TelephonyManager#NETWORK_TYPE_HSPAP
      */
+    @UnsupportedAppUsage
     public int getDataConnectionNetworkType() {
         return mNetworkType;
     }
@@ -126,6 +130,7 @@
     /**
      * Get data connection APN type
      */
+    @UnsupportedAppUsage
     public String getDataConnectionAPNType() {
         return mAPNType;
     }
@@ -133,6 +138,7 @@
     /**
      * Get data connection APN.
      */
+    @UnsupportedAppUsage
     public String getDataConnectionAPN() {
         return mAPN;
     }
@@ -140,6 +146,7 @@
     /**
      * Get data connection change reason.
      */
+    @UnsupportedAppUsage
     public String getDataConnectionChangeReason() {
         return mReason;
     }
@@ -147,6 +154,7 @@
     /**
      * Get the properties of the network link.
      */
+    @UnsupportedAppUsage
     public LinkProperties getDataConnectionLinkProperties() {
         return mLinkProperties;
     }
@@ -154,6 +162,7 @@
     /**
      * Get data connection fail cause, in case there was a failure.
      */
+    @UnsupportedAppUsage
     public String getDataConnectionFailCause() {
         return mFailCause;
     }
diff --git a/telephony/java/android/telephony/PreciseDisconnectCause.java b/telephony/java/android/telephony/PreciseDisconnectCause.java
index 46e2adb..2acaf34 100644
--- a/telephony/java/android/telephony/PreciseDisconnectCause.java
+++ b/telephony/java/android/telephony/PreciseDisconnectCause.java
@@ -332,6 +332,8 @@
     public static final int SIP_NOT_REACHABLE                                = 1320;
     /** Others */
     public static final int SIP_CLIENT_ERROR                                 = 1321;
+    /** 481 : Transaction Does Not Exist */
+    public static final int SIP_TRANSACTION_DOES_NOT_EXIST                   = 1322;
     /** 5xx responses
      *  501 : Server Internal Error
      */
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index d657bae..1d79988 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -77,6 +78,7 @@
      *        in RadioAccessFamily. It's a bit mask value to represent
      *        the support type.
      */
+    @UnsupportedAppUsage
     public RadioAccessFamily(int phoneId, int radioAccessFamily) {
         mPhoneId = phoneId;
         mRadioAccessFamily = radioAccessFamily;
@@ -87,6 +89,7 @@
      *
      * @return phone ID
      */
+    @UnsupportedAppUsage
     public int getPhoneId() {
         return mPhoneId;
     }
@@ -96,6 +99,7 @@
      *
      * @return radio access family
      */
+    @UnsupportedAppUsage
     public int getRadioAccessFamily() {
         return mRadioAccessFamily;
     }
@@ -150,6 +154,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     public static int getRafFromNetworkType(int type) {
         int raf;
 
@@ -263,6 +268,7 @@
         return TelephonyManager.NETWORK_CLASS_UNKNOWN;
     }
 
+    @UnsupportedAppUsage
     public static int getNetworkTypeFromRaf(int raf) {
         int type;
 
diff --git a/telephony/java/android/telephony/Rlog.java b/telephony/java/android/telephony/Rlog.java
index e0b46e1..5f2fa33 100644
--- a/telephony/java/android/telephony/Rlog.java
+++ b/telephony/java/android/telephony/Rlog.java
@@ -20,6 +20,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.Base64;
 
 import java.security.MessageDigest;
@@ -38,6 +39,7 @@
     private Rlog() {
     }
 
+    @UnsupportedAppUsage
     public static int v(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.VERBOSE, tag, msg);
     }
@@ -47,28 +49,34 @@
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int d(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.DEBUG, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int d(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.DEBUG, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int i(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.INFO, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int i(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.INFO, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int w(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.WARN, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int w(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.WARN, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
@@ -78,10 +86,12 @@
         return Log.println_native(Log.LOG_ID_RADIO, Log.WARN, tag, Log.getStackTraceString(tr));
     }
 
+    @UnsupportedAppUsage
     public static int e(String tag, String msg) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.ERROR, tag, msg);
     }
 
+    @UnsupportedAppUsage
     public static int e(String tag, String msg, Throwable tr) {
         return Log.println_native(Log.LOG_ID_RADIO, Log.ERROR, tag,
                 msg + '\n' + Log.getStackTraceString(tr));
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ae999c3..2ee1a09 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -169,6 +170,7 @@
      * IWLAN
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int RIL_RADIO_TECHNOLOGY_IWLAN = 18;
 
     /**
@@ -233,6 +235,7 @@
     private String mDataOperatorAlphaLong;
     private String mDataOperatorAlphaShort;
     private String mDataOperatorNumeric;
+    @UnsupportedAppUsage
     private boolean mIsManualNetworkSelection;
 
     private boolean mIsEmergencyOnly;
@@ -240,16 +243,24 @@
     private int mRilVoiceRadioTechnology;
     private int mRilDataRadioTechnology;
 
+    @UnsupportedAppUsage
     private boolean mCssIndicator;
+    @UnsupportedAppUsage
     private int mNetworkId;
+    @UnsupportedAppUsage
     private int mSystemId;
+    @UnsupportedAppUsage
     private int mCdmaRoamingIndicator;
+    @UnsupportedAppUsage
     private int mCdmaDefaultRoamingIndicator;
+    @UnsupportedAppUsage
     private int mCdmaEriIconIndex;
+    @UnsupportedAppUsage
     private int mCdmaEriIconMode;
 
     private boolean mIsDataRoamingFromRegistration;
 
+    @UnsupportedAppUsage
     private boolean mIsUsingCarrierAggregation;
 
     private int mChannelNumber;
@@ -294,6 +305,7 @@
      * @return newly created ServiceState
      * @hide
      */
+    @UnsupportedAppUsage
     public static ServiceState newFromBundle(Bundle m) {
         ServiceState ret;
         ret = new ServiceState();
@@ -442,6 +454,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getVoiceRegState() {
         return mVoiceRegState;
     }
@@ -456,6 +469,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDataRegState() {
         return mDataRegState;
     }
@@ -516,6 +530,7 @@
      * @return roaming status
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean getVoiceRoaming() {
         return mVoiceRoamingType != ROAMING_TYPE_NOT_ROAMING;
     }
@@ -525,6 +540,7 @@
      * @return roaming type
      * @hide
      */
+    @UnsupportedAppUsage
     public int getVoiceRoamingType() {
         return mVoiceRoamingType;
     }
@@ -534,6 +550,7 @@
      * @return roaming type
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean getDataRoaming() {
         return mDataRoamingType != ROAMING_TYPE_NOT_ROAMING;
     }
@@ -545,6 +562,7 @@
      * once the data registration phase has completed.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDataRoamingFromRegistration(boolean dataRoaming) {
         mIsDataRoamingFromRegistration = dataRoaming;
     }
@@ -563,6 +581,7 @@
      * @return roaming type
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDataRoamingType() {
         return mDataRoamingType;
     }
@@ -570,6 +589,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isEmergencyOnly() {
         return mIsEmergencyOnly;
     }
@@ -577,6 +597,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaRoamingIndicator(){
         return this.mCdmaRoamingIndicator;
     }
@@ -584,6 +605,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaDefaultRoamingIndicator(){
         return this.mCdmaDefaultRoamingIndicator;
     }
@@ -591,6 +613,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaEriIconIndex() {
         return this.mCdmaEriIconIndex;
     }
@@ -598,6 +621,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaEriIconMode() {
         return this.mCdmaEriIconMode;
     }
@@ -619,6 +643,7 @@
      * @return long name of operator
      * @hide
      */
+    @UnsupportedAppUsage
     public String getVoiceOperatorAlphaLong() {
         return mVoiceOperatorAlphaLong;
     }
@@ -648,6 +673,7 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
+    @UnsupportedAppUsage
     public String getVoiceOperatorAlphaShort() {
         return mVoiceOperatorAlphaShort;
     }
@@ -657,6 +683,7 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
+    @UnsupportedAppUsage
     public String getDataOperatorAlphaShort() {
         return mDataOperatorAlphaShort;
     }
@@ -700,6 +727,7 @@
      * @return numeric format of operator, null if unregistered or unknown
      * @hide
      */
+    @UnsupportedAppUsage
     public String getVoiceOperatorNumeric() {
         return mVoiceOperatorNumeric;
     }
@@ -709,6 +737,7 @@
      * @return numeric format of operator, null if unregistered or unknown
      * @hide
      */
+    @UnsupportedAppUsage
     public String getDataOperatorNumeric() {
         return mDataOperatorNumeric;
     }
@@ -794,6 +823,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String rilRadioTechnologyToString(int rt) {
         String rtString;
 
@@ -968,12 +998,14 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setVoiceRegState(int state) {
         mVoiceRegState = state;
         if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setVoiceRegState=" + mVoiceRegState);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDataRegState(int state) {
         mDataRegState = state;
         if (VDBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRegState=" + mDataRegState);
@@ -997,21 +1029,25 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setVoiceRoaming(boolean roaming) {
         mVoiceRoamingType = (roaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setVoiceRoamingType(int type) {
         mVoiceRoamingType = type;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDataRoaming(boolean dataRoaming) {
         mDataRoamingType = (dataRoaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDataRoamingType(int type) {
         mDataRoamingType = type;
     }
@@ -1019,6 +1055,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setEmergencyOnly(boolean emergencyOnly) {
         mIsEmergencyOnly = emergencyOnly;
     }
@@ -1026,6 +1063,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaRoamingIndicator(int roaming) {
         this.mCdmaRoamingIndicator = roaming;
     }
@@ -1033,6 +1071,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaDefaultRoamingIndicator (int roaming) {
         this.mCdmaDefaultRoamingIndicator = roaming;
     }
@@ -1040,6 +1079,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaEriIconIndex(int index) {
         this.mCdmaEriIconIndex = index;
     }
@@ -1047,6 +1087,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCdmaEriIconMode(int mode) {
         this.mCdmaEriIconMode = mode;
     }
@@ -1080,6 +1121,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setOperatorAlphaLong(String longName) {
         mVoiceOperatorAlphaLong = longName;
         mDataOperatorAlphaLong = longName;
@@ -1106,6 +1148,7 @@
      * @param b second obj
      * @return true if two objects equal or both are null
      */
+    @UnsupportedAppUsage
     private static boolean equalsHandlesNulls (Object a, Object b) {
         return (a == null) ? (b == null) : a.equals (b);
     }
@@ -1116,6 +1159,7 @@
      * @param m intent notifier map
      * @hide
      */
+    @UnsupportedAppUsage
     private void setFromNotifierBundle(Bundle m) {
         mVoiceRegState = m.getInt("voiceRegState");
         mDataRegState = m.getInt("dataRegState");
@@ -1149,6 +1193,7 @@
      * @param m intent notifier Bundle
      * @hide
      */
+    @UnsupportedAppUsage
     public void fillInNotifierBundle(Bundle m) {
         m.putInt("voiceRegState", mVoiceRegState);
         m.putInt("dataRegState", mDataRegState);
@@ -1221,6 +1266,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setCssIndicator(int css) {
         this.mCssIndicator = (css != 0);
     }
@@ -1233,10 +1279,12 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getRilVoiceRadioTechnology() {
         return this.mRilVoiceRadioTechnology;
     }
     /** @hide */
+    @UnsupportedAppUsage
     public int getRilDataRadioTechnology() {
         return this.mRilDataRadioTechnology;
     }
@@ -1245,6 +1293,7 @@
      * @Deprecated to be removed Q3 2013 use {@link #getRilDataRadioTechnology} or
      * {@link #getRilVoiceRadioTechnology}
      */
+    @UnsupportedAppUsage
     public int getRadioTechnology() {
         Rlog.e(LOG_TAG, "ServiceState.getRadioTechnology() DEPRECATED will be removed *******");
         return getRilDataRadioTechnology();
@@ -1374,16 +1423,19 @@
 
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getDataNetworkType() {
         return rilRadioTechnologyToNetworkType(mRilDataRadioTechnology);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getVoiceNetworkType() {
         return rilRadioTechnologyToNetworkType(mRilVoiceRadioTechnology);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getCssIndicator() {
         return this.mCssIndicator ? 1 : 0;
     }
@@ -1407,6 +1459,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isGsm(int radioTechnology) {
         return radioTechnology == RIL_RADIO_TECHNOLOGY_GPRS
                 || radioTechnology == RIL_RADIO_TECHNOLOGY_EDGE
@@ -1424,6 +1477,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isCdma(int radioTechnology) {
         return radioTechnology == RIL_RADIO_TECHNOLOGY_IS95A
                 || radioTechnology == RIL_RADIO_TECHNOLOGY_IS95B
@@ -1441,11 +1495,13 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean bearerBitmapHasCdma(int radioTechnologyBitmap) {
         return (RIL_RADIO_CDMA_TECHNOLOGY_BITMASK & radioTechnologyBitmap) != 0;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean bitmaskHasTech(int bearerBitmask, int radioTech) {
         if (bearerBitmask == 0) {
             return true;
@@ -1517,6 +1573,7 @@
      * voice SS. The voice SS is only used if it is IN_SERVICE (otherwise the base SS is returned).
      * @hide
      * */
+    @UnsupportedAppUsage
     public static ServiceState mergeServiceStates(ServiceState baseSs, ServiceState voiceSs) {
         if (voiceSs.mVoiceRegState != STATE_IN_SERVICE) {
             return baseSs;
@@ -1569,13 +1626,14 @@
     /**
      * Get the network registration states with given transport type and domain.
      *
+     * @param domain The network domain. Must be {@link NetworkRegistrationState#DOMAIN_CS} or
+     * {@link NetworkRegistrationState#DOMAIN_PS}.
      * @param transportType The transport type. See {@link AccessNetworkConstants.TransportType}
-     * @param domain The network domain. Must be DOMAIN_CS or DOMAIN_PS.
      * @return The matching NetworkRegistrationState.
      * @hide
      */
     @SystemApi
-    public NetworkRegistrationState getNetworkRegistrationStates(int transportType, int domain) {
+    public NetworkRegistrationState getNetworkRegistrationStates(int domain, int transportType) {
         synchronized (mNetworkRegistrationStates) {
             for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
                 if (networkRegistrationState.getTransportType() == transportType
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 95abb91..ed758a9 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -36,21 +37,27 @@
     private static final boolean DBG = false;
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN
             = TelephonyProtoEnums.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; // = 0
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_POOR
             = TelephonyProtoEnums.SIGNAL_STRENGTH_POOR; // = 1
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_MODERATE
             = TelephonyProtoEnums.SIGNAL_STRENGTH_MODERATE; // = 2
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_GOOD
             = TelephonyProtoEnums.SIGNAL_STRENGTH_GOOD; // = 3
     /** @hide */
+    @UnsupportedAppUsage
     public static final int SIGNAL_STRENGTH_GREAT
             = TelephonyProtoEnums.SIGNAL_STRENGTH_GREAT; // = 4
     /** @hide */
+    @UnsupportedAppUsage
     public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
     /** @hide */
     public static final String[] SIGNAL_STRENGTH_NAMES = {
@@ -75,24 +82,39 @@
     private static final String MEASUMENT_TYPE_RSCP = "rscp";
 
     /** Parameters reported by the Radio */
+    @UnsupportedAppUsage
     private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
+    @UnsupportedAppUsage
     private int mGsmBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+    @UnsupportedAppUsage
     private int mCdmaDbm;   // This value is the RSSI value
+    @UnsupportedAppUsage
     private int mCdmaEcio;  // This value is the Ec/Io
+    @UnsupportedAppUsage
     private int mEvdoDbm;   // This value is the EVDO RSSI value
+    @UnsupportedAppUsage
     private int mEvdoEcio;  // This value is the EVDO Ec/Io
+    @UnsupportedAppUsage
     private int mEvdoSnr;   // Valid values are 0-8.  8 is the highest signal to noise ratio
+    @UnsupportedAppUsage
     private int mLteSignalStrength;
+    @UnsupportedAppUsage
     private int mLteRsrp;
+    @UnsupportedAppUsage
     private int mLteRsrq;
+    @UnsupportedAppUsage
     private int mLteRssnr;
+    @UnsupportedAppUsage
     private int mLteCqi;
+    @UnsupportedAppUsage
     private int mTdScdmaRscp; // Valid values are -24...-120dBm or INVALID if unknown
     private int mWcdmaSignalStrength;
     private int mWcdmaRscpAsu;  // the WCDMA RSCP in ASU as reported from the HAL
+    @UnsupportedAppUsage
     private int mWcdmaRscp;     // the WCDMA RSCP in dBm
 
     /** Parameters from the framework */
+    @UnsupportedAppUsage
     private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
                                 // signal strength level
     private boolean mIsGsm; // This value is set by the ServiceStateTracker
@@ -121,6 +143,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static SignalStrength newFromBundle(Bundle m) {
         SignalStrength ret;
         ret = new SignalStrength();
@@ -133,6 +156,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public SignalStrength() {
         this(true);
     }
@@ -145,6 +169,7 @@
      * @return newly created SignalStrength
      * @hide
      */
+    @UnsupportedAppUsage
     public SignalStrength(boolean gsmFlag) {
         mGsmSignalStrength = 99;
         mGsmBitErrorRate = -1;
@@ -247,6 +272,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public SignalStrength(SignalStrength s) {
         copyFrom(s);
     }
@@ -254,6 +280,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected void copyFrom(SignalStrength s) {
         mGsmSignalStrength = s.mGsmSignalStrength;
         mGsmBitErrorRate = s.mGsmBitErrorRate;
@@ -284,6 +311,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public SignalStrength(Parcel in) {
         if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
 
@@ -351,6 +379,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
         public SignalStrength createFromParcel(Parcel in) {
             return new SignalStrength(in);
@@ -372,6 +401,7 @@
      *      Valid values for all signalstrength fields
      * @hide
      */
+    @UnsupportedAppUsage
     public void validateInput() {
         if (DBG) log("Signal before validate=" + this);
         // TS 27.007 8.5
@@ -546,26 +576,31 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteSignalStrength() {
         return mLteSignalStrength;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteRsrp() {
         return mLteRsrp;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteRsrq() {
         return mLteRsrq;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteRssnr() {
         return mLteRssnr;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getLteCqi() {
         return mLteCqi;
     }
@@ -594,6 +629,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getAsuLevel() {
         int asuLevel = 0;
         if (mIsGsm) {
@@ -629,6 +665,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDbm() {
         int dBm = INVALID;
 
@@ -661,6 +698,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getGsmDbm() {
         int dBm;
 
@@ -680,6 +718,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getGsmLevel() {
         int level;
 
@@ -702,6 +741,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getGsmAsuLevel() {
         // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
         // asu = 0 (-113dB or less) is very weak
@@ -717,6 +757,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaLevel() {
         final int cdmaDbm = getCdmaDbm();
         final int cdmaEcio = getCdmaEcio();
@@ -746,6 +787,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getCdmaAsuLevel() {
         final int cdmaDbm = getCdmaDbm();
         final int cdmaEcio = getCdmaEcio();
@@ -777,6 +819,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getEvdoLevel() {
         int evdoDbm = getEvdoDbm();
         int evdoSnr = getEvdoSnr();
@@ -805,6 +848,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getEvdoAsuLevel() {
         int evdoDbm = getEvdoDbm();
         int evdoSnr = getEvdoSnr();
@@ -835,6 +879,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getLteDbm() {
         return mLteRsrp;
     }
@@ -844,6 +889,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getLteLevel() {
         /*
          * TS 36.214 Physical Layer Section 5.1.3
@@ -930,6 +976,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getLteAsuLevel() {
         int lteAsuLevel = 99;
         int lteDbm = getLteDbm();
@@ -973,6 +1020,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTdScdmaDbm() {
         return this.mTdScdmaRscp;
     }
@@ -985,6 +1033,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTdScdmaLevel() {
         final int tdScdmaDbm = getTdScdmaDbm();
         int level;
@@ -1006,6 +1055,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTdScdmaAsuLevel() {
         final int tdScdmaDbm = getTdScdmaDbm();
         int tdScdmaAsuLevel;
@@ -1245,6 +1295,7 @@
      * @param m intent notifier map
      * @hide
      */
+    @UnsupportedAppUsage
     private void setFromNotifierBundle(Bundle m) {
         mGsmSignalStrength = m.getInt("GsmSignalStrength");
         mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
@@ -1282,6 +1333,7 @@
      * @param m intent notifier Bundle
      * @hide
      */
+    @UnsupportedAppUsage
     public void fillInNotifierBundle(Bundle m) {
         m.putInt("GsmSignalStrength", mGsmSignalStrength);
         m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 38bc640..ea408bf 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -19,6 +19,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
 import android.content.ActivityNotFoundException;
@@ -88,6 +89,7 @@
             new ArrayMap<Integer, SmsManager>();
 
     /** A concrete subscription id, or the pseudo DEFAULT_SUBSCRIPTION_ID */
+    @UnsupportedAppUsage
     private int mSubId;
 
     /*
@@ -272,6 +274,17 @@
     private static final int SMS_PICK = 2;
 
     /**
+     * 3gpp2 SMS priority is not specified
+     * @hide
+     */
+    public static final int SMS_MESSAGE_PRIORITY_NOT_SPECIFIED = -1;
+    /**
+     * 3gpp SMS period is not specified
+     * @hide
+     */
+    public static final int SMS_MESSAGE_PERIOD_NOT_SPECIFIED = -1;
+
+    /**
      * Send a text based SMS.
      *
      * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
@@ -440,6 +453,7 @@
      * @throws IllegalArgumentException if destinationAddress or text are empty
      * {@hide}
      */
+    @UnsupportedAppUsage
     public void sendTextMessage(
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent,
@@ -461,11 +475,11 @@
         }
 
         if (priority < 0x00 || priority > 0x03) {
-            throw new IllegalArgumentException("Invalid priority");
+            priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
         }
 
         if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) {
-            throw new IllegalArgumentException("Invalid validity period");
+            validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
         }
 
         try {
@@ -493,6 +507,7 @@
      * PendingIntent, int, boolean, int)
      * @hide
      */
+    @UnsupportedAppUsage
     public void sendTextMessageWithoutPersisting(
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent, int priority,
@@ -718,12 +733,14 @@
      * @throws IllegalArgumentException if destinationAddress or data are empty
      * {@hide}
      */
+    @UnsupportedAppUsage
     public void sendMultipartTextMessage(
             String destinationAddress, String scAddress, ArrayList<String> parts,
             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
             int priority, boolean expectMore, int validityPeriod) {
         sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
-                deliveryIntents, true /* persistMessage*/);
+                deliveryIntents, true /* persistMessage*/, priority, expectMore,
+                validityPeriod);
     }
 
     private void sendMultipartTextMessageInternal(
@@ -738,11 +755,11 @@
         }
 
         if (priority < 0x00 || priority > 0x03) {
-            throw new IllegalArgumentException("Invalid priority");
+           priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
         }
 
         if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) {
-            throw new IllegalArgumentException("Invalid validity period");
+           validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
         }
 
         if (parts.size() > 1) {
@@ -985,6 +1002,7 @@
      * @throws IllegalArgumentException if pdu is NULL
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) {
         boolean success = false;
 
@@ -1015,6 +1033,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean
     deleteMessageFromIcc(int messageIndex) {
         boolean success = false;
@@ -1049,6 +1068,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
         boolean success = false;
 
@@ -1075,6 +1095,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public ArrayList<SmsMessage> getAllMessagesFromIcc() {
         List<SmsRawData> records = null;
 
@@ -1187,6 +1208,7 @@
      * @throws IllegalArgumentException if endMessageId < startMessageId
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
         boolean success = false;
 
@@ -1229,6 +1251,7 @@
      * @throws IllegalArgumentException if endMessageId < startMessageId
      * {@hide}
      */
+    @UnsupportedAppUsage
     public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
         boolean success = false;
 
@@ -1346,6 +1369,7 @@
      * @return true if enabled, false otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isSMSPromptEnabled() {
         ISms iccISms = null;
         try {
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 57f89e3..91e24a9 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -20,6 +20,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.StringDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.os.Binder;
 import android.text.TextUtils;
@@ -107,18 +108,21 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public SmsMessageBase mWrappedSmsMessage;
 
     /** Indicates the subId
      *
      * @hide
      */
+    @UnsupportedAppUsage
     private int mSubId = 0;
 
     /** set Subscription information
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSubId(int subId) {
         mSubId = subId;
     }
@@ -127,6 +131,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getSubId() {
         return mSubId;
     }
@@ -368,6 +373,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static ArrayList<String> fragmentText(String text) {
         // This function is for MO SMS
         TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
@@ -822,6 +828,7 @@
      *
      * @return true if Cdma format should be used for MO SMS, false otherwise.
      */
+    @UnsupportedAppUsage
     private static boolean useCdmaFormatForMoSms() {
         // IMS is registered with SMS support, check the SMS format supported
         return useCdmaFormatForMoSms(SubscriptionManager.getDefaultSmsSubscriptionId());
@@ -836,6 +843,7 @@
      *
      * @return true if Cdma format should be used for MO SMS, false otherwise.
      */
+    @UnsupportedAppUsage
     private static boolean useCdmaFormatForMoSms(int subId) {
         SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
         if (!smsManager.isImsSmsSupported()) {
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 936505c..ec26622 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -33,9 +34,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.DisplayMetrics;
+import android.util.Log;
 
 import java.util.Arrays;
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -105,12 +106,12 @@
     /**
      * Mobile Country Code
      */
-    private int mMcc;
+    private String mMcc;
 
     /**
      * Mobile Network Code
      */
-    private int mMnc;
+    private String mMnc;
 
     /**
      * ISO Country code for the subscription's provider
@@ -135,34 +136,35 @@
     private String mCardId;
 
     /**
-     * @hide
+     * Whether the subscription is opportunistic.
      */
-    public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
-        CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
-        Bitmap icon, int mcc, int mnc, String countryIso) {
-        this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
-            roaming, icon, mcc, mnc, countryIso, false /* isEmbedded */,
-            null /* accessRules */, null /* accessRules */);
-    }
+    private boolean mIsOpportunistic;
+
+    /**
+     * SubId of the parent subscription, if there is one.
+     */
+    private int mParentSubId;
 
     /**
      * @hide
      */
     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
-            Bitmap icon, int mcc, int mnc, String countryIso,  boolean isEmbedded,
-            @Nullable UiccAccessRule[] accessRules) {
-        this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
-                roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, null /* cardId */);
-    }
-
-    /**
-     * @hide
-     */
-    public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
-            CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
-            Bitmap icon, int mcc, int mnc, String countryIso, boolean isEmbedded,
+            Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
             @Nullable UiccAccessRule[] accessRules, String cardId) {
+        this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
+                roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardId,
+                false, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+    }
+
+    /**
+     * @hide
+     */
+    public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
+            CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
+            Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
+            @Nullable UiccAccessRule[] accessRules, String cardId, boolean isOpportunistic,
+            int parentSubId) {
         this.mId = id;
         this.mIccId = iccId;
         this.mSimSlotIndex = simSlotIndex;
@@ -179,6 +181,8 @@
         this.mIsEmbedded = isEmbedded;
         this.mAccessRules = accessRules;
         this.mCardId = cardId;
+        this.mIsOpportunistic = isOpportunistic;
+        this.mParentSubId = parentSubId;
     }
 
     /**
@@ -213,6 +217,7 @@
      * Sets the name displayed to the user that identifies this subscription
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDisplayName(CharSequence name) {
         this.mDisplayName = name;
     }
@@ -237,6 +242,7 @@
      * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getNameSource() {
         return this.mNameSource;
     }
@@ -295,6 +301,7 @@
      * Sets the color displayed to the user that identifies this subscription
      * @hide
      */
+    @UnsupportedAppUsage
     public void setIconTint(int iconTint) {
         this.mIconTint = iconTint;
     }
@@ -316,15 +323,43 @@
 
     /**
      * @return the MCC.
+     * @deprecated Use {@link #getMccString()} instead.
      */
+    @Deprecated
     public int getMcc() {
-        return this.mMcc;
+        try {
+            return this.mMcc == null ? 0 : Integer.valueOf(this.mMcc);
+        } catch (NumberFormatException e) {
+            Log.w(SubscriptionInfo.class.getSimpleName(), "MCC string is not a number");
+            return 0;
+        }
     }
 
     /**
      * @return the MNC.
+     * @deprecated Use {@link #getMncString()} instead.
      */
+    @Deprecated
     public int getMnc() {
+        try {
+            return this.mMnc == null ? 0 : Integer.valueOf(this.mMnc);
+        } catch (NumberFormatException e) {
+            Log.w(SubscriptionInfo.class.getSimpleName(), "MNC string is not a number");
+            return 0;
+        }
+    }
+
+    /**
+     * @return The MCC, as a string.
+     */
+    public String getMccString() {
+        return this.mMcc;
+    }
+
+    /**
+     * @return The MNC, as a string.
+     */
+    public String getMncString() {
         return this.mMnc;
     }
 
@@ -341,6 +376,29 @@
     }
 
     /**
+     * An opportunistic subscription connects to a network that is
+     * limited in functionality and / or coverage.
+     *
+     * @return whether subscription is opportunistic.
+     */
+    public boolean isOpportunistic() {
+        return mIsOpportunistic;
+    }
+
+    /**
+     * Used in scenarios where a child subscription is bundled with a primary parent subscription.
+     * The child subscription will typically be opportunistic (see {@link #isOpportunistic()})
+     * and will be used to provide data services where available, with the parent being the primary
+     * fallback subscription.
+     *
+     * @return subId of parent subscription if it’s bundled with a primary subscription.
+     * If there isn't one, {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}
+     */
+    public int getParentSubId() {
+        return mParentSubId;
+    }
+
+    /**
      * Checks whether the app with the given context is authorized to manage this subscription
      * according to its metadata. Only supported for embedded subscriptions (if {@link #isEmbedded}
      * returns true).
@@ -425,17 +483,19 @@
             int iconTint = source.readInt();
             String number = source.readString();
             int dataRoaming = source.readInt();
-            int mcc = source.readInt();
-            int mnc = source.readInt();
+            String mcc = source.readString();
+            String mnc = source.readString();
             String countryIso = source.readString();
             Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
             boolean isEmbedded = source.readBoolean();
             UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
             String cardId = source.readString();
+            boolean isOpportunistic = source.readBoolean();
+            int parentSubId = source.readInt();
 
             return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
                     nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
-                    isEmbedded, accessRules, cardId);
+                    isEmbedded, accessRules, cardId, isOpportunistic, parentSubId);
         }
 
         @Override
@@ -455,13 +515,15 @@
         dest.writeInt(mIconTint);
         dest.writeString(mNumber);
         dest.writeInt(mDataRoaming);
-        dest.writeInt(mMcc);
-        dest.writeInt(mMnc);
+        dest.writeString(mMcc);
+        dest.writeString(mMnc);
         dest.writeString(mCountryIso);
         mIconBitmap.writeToParcel(dest, flags);
         dest.writeBoolean(mIsEmbedded);
         dest.writeTypedArray(mAccessRules, flags);
         dest.writeString(mCardId);
+        dest.writeBoolean(mIsOpportunistic);
+        dest.writeInt(mParentSubId);
     }
 
     @Override
@@ -494,6 +556,7 @@
                 + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
                 + " mnc " + mMnc + " isEmbedded " + mIsEmbedded
                 + " accessRules " + Arrays.toString(mAccessRules)
-                + " cardId=" + cardIdToPrint + "}";
+                + " cardId=" + cardIdToPrint + " isOpportunistic " + mIsOpportunistic
+                + " parentSubId=" + mParentSubId + "}";
     }
 }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index ece646c..119733e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -28,7 +28,9 @@
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.app.BroadcastOptions;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
@@ -43,6 +45,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.telephony.euicc.EuiccManager;
 import android.util.DisplayMetrics;
 
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -84,6 +87,7 @@
 
     /** Indicates the caller wants the default sub id. */
     /** @hide */
+    @UnsupportedAppUsage
     public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE;
 
     /**
@@ -106,6 +110,7 @@
     public static final int MAX_SUBSCRIPTION_ID_VALUE = DEFAULT_SUBSCRIPTION_ID - 1;
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
 
     /**
@@ -183,6 +188,7 @@
      * The name_source is from the user
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int NAME_SOURCE_USER_INPUT = 2;
 
     /**
@@ -253,6 +259,20 @@
     public static final int SIM_PROVISIONED = 0;
 
     /**
+     * TelephonyProvider column name for the MCC associated with a SIM, stored as a string.
+     * <P>Type: TEXT (String)</P>
+     * @hide
+     */
+    public static final String MCC_STRING = "mcc_string";
+
+    /**
+     * TelephonyProvider column name for the MNC associated with a SIM, stored as a string.
+     * <P>Type: TEXT (String)</P>
+     * @hide
+     */
+    public static final String MNC_STRING = "mnc_string";
+
+    /**
      * TelephonyProvider column name for the MCC associated with a SIM.
      * <P>Type: INTEGER (int)</P>
      * @hide
@@ -287,7 +307,7 @@
      * <P>Type: TEXT (String)</P>
      * @hide
      */
-     public static final String CARD_ID = "card_id";
+    public static final String CARD_ID = "card_id";
 
     /**
      * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from
@@ -419,6 +439,24 @@
     public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled";
 
     /**
+     * TelephonyProvider column name for whether a subscription is opportunistic, that is,
+     * whether the network it connects to is limited in functionality or coverage.
+     * For example, CBRS.
+     * IS_EMBEDDED should always be true.
+     * <p>Type: INTEGER (int), 1 for opportunistic or 0 for non-opportunistic.
+     * @hide
+     */
+    public static final String IS_OPPORTUNISTIC = "is_opportunistic";
+
+    /**
+     * TelephonyProvider column name for subId of parent subscription of an opportunistic
+     * subscription.
+     * if the parent sub id is valid, then is_opportunistic should always to true.
+     * @hide
+     */
+    public static final String PARENT_SUB_ID = "parent_sub_id";
+
+    /**
      * Broadcast Action: The user has changed one of the default subs related to
      * data, phone calls, or sms</p>
      *
@@ -581,6 +619,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public SubscriptionManager(Context context) {
         if (DBG) logd("SubscriptionManager created");
         mContext = context;
@@ -759,6 +798,7 @@
      * include those that were inserted before, maybe empty but not null.
      * @hide
      */
+    @UnsupportedAppUsage
     public List<SubscriptionInfo> getAllSubscriptionInfoList() {
         if (VDBG) logd("[getAllSubscriptionInfoList]+");
 
@@ -930,6 +970,7 @@
      * all subscriptions that have been seen.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getAllSubscriptionInfoCount() {
         if (VDBG) logd("[getAllSubscriptionInfoCount]+");
 
@@ -1035,26 +1076,12 @@
      * @return the number of records updated
      * @hide
      */
+    @UnsupportedAppUsage
     public int setIconTint(int tint, int subId) {
         if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId);
-        if (!isValidSubscriptionId(subId)) {
-            logd("[setIconTint]- fail");
-            return -1;
-        }
-
-        int result = 0;
-
-        try {
-            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
-            if (iSub != null) {
-                result = iSub.setIconTint(tint, subId);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return result;
-
+        return setSubscriptionPropertyHelper(subId, "setIconTint",
+                (iSub)-> iSub.setIconTint(tint, subId)
+        );
     }
 
     /**
@@ -1077,29 +1104,15 @@
      * @return the number of records updated or < 0 if invalid subId
      * @hide
      */
+    @UnsupportedAppUsage
     public int setDisplayName(String displayName, int subId, long nameSource) {
         if (VDBG) {
             logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId
                     + " nameSource:" + nameSource);
         }
-        if (!isValidSubscriptionId(subId)) {
-            logd("[setDisplayName]- fail");
-            return -1;
-        }
-
-        int result = 0;
-
-        try {
-            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
-            if (iSub != null) {
-                result = iSub.setDisplayNameUsingSrc(displayName, subId, nameSource);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return result;
-
+        return setSubscriptionPropertyHelper(subId, "setDisplayName",
+                (iSub)-> iSub.setDisplayNameUsingSrc(displayName, subId, nameSource)
+        );
     }
 
     /**
@@ -1109,25 +1122,15 @@
      * @return the number of records updated
      * @hide
      */
+    @UnsupportedAppUsage
     public int setDisplayNumber(String number, int subId) {
-        if (number == null || !isValidSubscriptionId(subId)) {
+        if (number == null) {
             logd("[setDisplayNumber]- fail");
             return -1;
         }
-
-        int result = 0;
-
-        try {
-            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
-            if (iSub != null) {
-                result = iSub.setDisplayNumber(number, subId);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return result;
-
+        return setSubscriptionPropertyHelper(subId, "setDisplayNumber",
+                (iSub)-> iSub.setDisplayNumber(number, subId)
+        );
     }
 
     /**
@@ -1137,25 +1140,12 @@
      * @return the number of records updated
      * @hide
      */
+    @UnsupportedAppUsage
     public int setDataRoaming(int roaming, int subId) {
         if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId);
-        if (roaming < 0 || !isValidSubscriptionId(subId)) {
-            logd("[setDataRoaming]- fail");
-            return -1;
-        }
-
-        int result = 0;
-
-        try {
-            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
-            if (iSub != null) {
-                result = iSub.setDataRoaming(roaming, subId);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return result;
+        return setSubscriptionPropertyHelper(subId, "setDataRoaming",
+                (iSub)->iSub.setDataRoaming(roaming, subId)
+        );
     }
 
     /**
@@ -1164,6 +1154,7 @@
      * SIM_NOT_INSERTED or < 0 if an invalid slot index
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getSlotIndex(int subId) {
         if (!isValidSubscriptionId(subId)) {
             if (DBG) {
@@ -1187,6 +1178,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static int[] getSubId(int slotIndex) {
         if (!isValidSlotIndex(slotIndex)) {
             logd("[getSubId]- fail");
@@ -1208,6 +1200,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static int getPhoneId(int subId) {
         if (!isValidSubscriptionId(subId)) {
             if (DBG) {
@@ -1305,11 +1298,13 @@
      * @return the SubscriptionInfo for the default voice subscription.
      * @hide
      */
+    @UnsupportedAppUsage
     public SubscriptionInfo getDefaultVoiceSubscriptionInfo() {
         return getActiveSubscriptionInfo(getDefaultVoiceSubscriptionId());
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static int getDefaultVoicePhoneId() {
         return getPhoneId(getDefaultVoiceSubscriptionId());
     }
@@ -1338,6 +1333,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDefaultSmsSubId(int subId) {
         if (VDBG) logd("setDefaultSmsSubId sub id = " + subId);
         try {
@@ -1363,6 +1359,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getDefaultSmsPhoneId() {
         return getPhoneId(getDefaultSmsSubscriptionId());
     }
@@ -1391,6 +1388,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setDefaultDataSubId(int subId) {
         if (VDBG) logd("setDataSubscription sub id = " + subId);
         try {
@@ -1411,11 +1409,13 @@
      * @return the SubscriptionInfo for the default data subscription.
      * @hide
      */
+    @UnsupportedAppUsage
     public SubscriptionInfo getDefaultDataSubscriptionInfo() {
         return getActiveSubscriptionInfo(getDefaultDataSubscriptionId());
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getDefaultDataPhoneId() {
         return getPhoneId(getDefaultDataSubscriptionId());
     }
@@ -1454,6 +1454,7 @@
      * an invalid subscription id, i.e. < 0.
      * @hide
      */
+    @UnsupportedAppUsage
     public void clearDefaultsForInactiveSubIds() {
         if (VDBG) logd("clearDefaultsForInactiveSubIds");
         try {
@@ -1470,6 +1471,7 @@
      * @return true if a valid subId else false
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isValidSubscriptionId(int subId) {
         return subId > INVALID_SUBSCRIPTION_ID ;
     }
@@ -1479,21 +1481,25 @@
      * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean isUsableSubIdValue(int subId) {
         return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isValidSlotIndex(int slotIndex) {
         return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSimCount();
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static boolean isValidPhoneId(int phoneId) {
         return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount();
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
         int[] subIds = SubscriptionManager.getSubId(phoneId);
         if (subIds != null && subIds.length > 0) {
@@ -1504,6 +1510,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) {
         if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
@@ -1519,6 +1526,7 @@
      *         is never null but the length maybe 0.
      * @hide
      */
+    @UnsupportedAppUsage
     public @NonNull int[] getActiveSubscriptionIdList() {
         int[] subId = null;
 
@@ -1677,6 +1685,7 @@
      * @return Resources associated with Subscription.
      * @hide
      */
+    @UnsupportedAppUsage
     public static Resources getResourcesForSubId(Context context, int subId) {
         final SubscriptionInfo subInfo =
                 SubscriptionManager.from(context).getActiveSubscriptionInfo(subId);
@@ -1700,6 +1709,7 @@
      * and the SIM providing the subscription is present in a slot and in "LOADED" state.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isActiveSubId(int subId) {
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -1980,4 +1990,114 @@
         }
         return false;
     }
+
+    /**
+     * Set preferred default data.
+     * Set on which slot default data will be on.
+     *
+     * @param slotId which slot is preferred to for cellular data.
+     * @hide
+     *
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setPreferredData(int slotId) {
+        if (VDBG) logd("[setPreferredData]+ slotId:" + slotId);
+        setSubscriptionPropertyHelper(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+                "setPreferredData", (iSub)-> iSub.setPreferredData(slotId));
+    }
+
+    /**
+     * Get User downloaded Profiles.
+     *
+     *  Provide all available user downloaded profile on the phone.
+     *  @param slotId on which phone the switch will operate on
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    List<SubscriptionInfo> getOpportunisticSubscriptions(int slotId) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        List<SubscriptionInfo> subInfoList = null;
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                subInfoList = iSub.getOpportunisticSubscriptions(slotId, pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        if (subInfoList == null) {
+            subInfoList = new ArrayList<>();
+        }
+
+        return subInfoList;
+    }
+
+    /**
+     * Switch to a certain subscription
+     *
+     *  @param subId sub id
+     *  @param callbackIntent pending intent that will be sent after operation is done.
+     */
+    @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+    public void switchToSubscription(int subId, PendingIntent callbackIntent) {
+        EuiccManager euiccManager = new EuiccManager(mContext);
+        euiccManager.switchToSubscription(subId, callbackIntent);
+    }
+
+    /**
+     * Set opportunistic by simInfo index
+     *
+     * @param opportunistic whether it’s opportunistic subscription.
+     * @param subId the unique SubscriptionInfo index in database
+     * @return the number of records updated
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public int setOpportunistic(boolean opportunistic, int subId) {
+        if (VDBG) logd("[setOpportunistic]+ opportunistic:" + opportunistic + " subId:" + subId);
+        return setSubscriptionPropertyHelper(subId, "setOpportunistic",
+                (iSub)-> iSub.setOpportunistic(opportunistic, subId));
+    }
+
+    /**
+     * Set parent subId by simInfo index
+     *
+     * @param parentSubId subId of its parent subscription.
+     * @param subId the unique SubscriptionInfo index in database
+     * @return the number of records updated
+     * @hide
+     *
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public int setParentSubId(int parentSubId, int subId) {
+        if (VDBG) logd("[setParentSubId]+ parentSubId:" + parentSubId + " subId:" + subId);
+        return setSubscriptionPropertyHelper(subId, "parentSubId",
+                (iSub)-> iSub.setParentSubId(parentSubId, subId));
+    }
+
+    private interface CallISubMethodHelper {
+        int callMethod(ISub iSub) throws RemoteException;
+    }
+
+    private int setSubscriptionPropertyHelper(int subId, String methodName,
+            CallISubMethodHelper helper) {
+        if (!isValidSubscriptionId(subId)) {
+            logd("[" + methodName + "]" + "- fail");
+            return -1;
+        }
+
+        int result = 0;
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                result = helper.callMethod(iSub);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return result;
+    }
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index f84cf7b7..26bf7f8 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -28,6 +28,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
@@ -155,6 +156,7 @@
 
     private final Context mContext;
     private final int mSubId;
+    @UnsupportedAppUsage
     private SubscriptionManager mSubscriptionManager;
     private TelephonyScanManager mTelephonyScanManager;
 
@@ -168,18 +170,24 @@
      **/
     /** @hide */
     public enum MultiSimVariants {
+        @UnsupportedAppUsage
         DSDS,
+        @UnsupportedAppUsage
         DSDA,
+        @UnsupportedAppUsage
         TSTS,
+        @UnsupportedAppUsage
         UNKNOWN
     };
 
     /** @hide */
+    @UnsupportedAppUsage
     public TelephonyManager(Context context) {
       this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public TelephonyManager(Context context, int subId) {
         mSubId = subId;
         Context appContext = context.getApplicationContext();
@@ -192,6 +200,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     private TelephonyManager() {
         mContext = null;
         mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -201,6 +210,7 @@
 
     /** @hide
     /* @deprecated - use getSystemService as described above */
+    @UnsupportedAppUsage
     public static TelephonyManager getDefault() {
         return sInstance;
     }
@@ -228,6 +238,7 @@
      * Returns UNKNOWN for others
      */
     /** {@hide} */
+    @UnsupportedAppUsage
     public MultiSimVariants getMultiSimConfiguration() {
         String mSimConfig =
             SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG);
@@ -288,6 +299,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static TelephonyManager from(Context context) {
         return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
     }
@@ -319,6 +331,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public boolean isMultiSimEnabled() {
         return (multiSimConfig.equals("dsds") || multiSimConfig.equals("dsda") ||
             multiSimConfig.equals("tsts"));
@@ -672,6 +685,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     @Deprecated
+    @UnsupportedAppUsage
     public static final String ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED =
             "android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED";
 
@@ -1206,6 +1220,7 @@
      */
     /** {@hide} */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getDeviceSoftwareVersion(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
@@ -1312,6 +1327,33 @@
     }
 
     /**
+     * Returns the Type Allocation Code from the IMEI. Return null if Type Allocation Code is not
+     * available.
+     */
+    public String getTypeAllocationCode() {
+        return getTypeAllocationCode(getSlotIndex());
+    }
+
+    /**
+     * Returns the Type Allocation Code from the IMEI. Return null if Type Allocation Code is not
+     * available.
+     *
+     * @param slotIndex of which Type Allocation Code is returned
+     */
+    public String getTypeAllocationCode(int slotIndex) {
+        ITelephony telephony = getITelephony();
+        if (telephony == null) return null;
+
+        try {
+            return telephony.getTypeAllocationCodeForSlot(slotIndex);
+        } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            return null;
+        }
+    }
+
+    /**
      * Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
      *
      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -1347,6 +1389,33 @@
     }
 
     /**
+     * Returns the Manufacturer Code from the MEID. Return null if Manufacturer Code is not
+     * available.
+     */
+    public String getManufacturerCode() {
+        return getManufacturerCode(getSlotIndex());
+    }
+
+    /**
+     * Returns the Manufacturer Code from the MEID. Return null if Manufacturer Code is not
+     * available.
+     *
+     * @param slotIndex of which Type Allocation Code is returned
+     */
+    public String getManufacturerCode(int slotIndex) {
+        ITelephony telephony = getITelephony();
+        if (telephony == null) return null;
+
+        try {
+            return telephony.getManufacturerCodeForSlot(slotIndex);
+        } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            return null;
+        }
+    }
+
+    /**
      * Returns the Network Access Identifier (NAI). Return null if NAI is not available.
      *
      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -1364,6 +1433,7 @@
      *  @param slotIndex of which Nai is returned
      */
     /** {@hide}*/
+    @UnsupportedAppUsage
     public String getNai(int slotIndex) {
         int[] subId = SubscriptionManager.getSubId(slotIndex);
         if (subId == null) {
@@ -1490,7 +1560,7 @@
      * @return List of NeighboringCellInfo or null if info unavailable.
      *
      * @deprecated Use {@link #getAllCellInfo} which returns a superset of the information
-     *             from NeighboringCellInfo.
+     *             from NeighboringCellInfo, including LTE cell information.
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
@@ -1499,7 +1569,8 @@
             ITelephony telephony = getITelephony();
             if (telephony == null)
                 return null;
-            return telephony.getNeighboringCellInfo(mContext.getOpPackageName());
+            return telephony.getNeighboringCellInfo(mContext.getOpPackageName(),
+                    mContext.getApplicationInfo().targetSdkVersion);
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -1602,6 +1673,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     private int getPhoneTypeFromProperty(int phoneId) {
         String type = getTelephonyProperty(phoneId,
                 TelephonyProperties.CURRENT_ACTIVE_PHONE, null);
@@ -1636,6 +1708,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getPhoneType(int networkMode) {
         switch(networkMode) {
         case RILConstants.NETWORK_MODE_CDMA:
@@ -1681,6 +1754,7 @@
     /**
      * The contents of the /proc/cmdline file
      */
+    @UnsupportedAppUsage
     private static String getProcCmdLine()
     {
         String cmdline = "";
@@ -1727,6 +1801,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getLteOnCdmaModeStatic() {
         int retVal;
         int curVal;
@@ -1782,6 +1857,7 @@
      * @param subId
      * @hide
      */
+    @UnsupportedAppUsage
     public String getNetworkOperatorName(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, "");
@@ -1809,6 +1885,7 @@
      * @param subId
      * @hide
      */
+    @UnsupportedAppUsage
     public String getNetworkOperator(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getNetworkOperatorForPhone(phoneId);
@@ -1825,6 +1902,7 @@
      * @param phoneId
      * @hide
      **/
+    @UnsupportedAppUsage
     public String getNetworkOperatorForPhone(int phoneId) {
         return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
      }
@@ -1887,6 +1965,7 @@
      * @param subId
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isNetworkRoaming(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return Boolean.parseBoolean(getTelephonyProperty(phoneId,
@@ -1915,6 +1994,7 @@
      * @param subId for which Network CountryIso is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getNetworkCountryIso(int subId) {
         return getNetworkCountryIsoForPhone(getPhoneId(subId));
     }
@@ -1930,6 +2010,7 @@
      * @param phoneId for which Network CountryIso is returned
      */
     /** {@hide} */
+    @UnsupportedAppUsage
     public String getNetworkCountryIsoForPhone(int phoneId) {
         try {
             ITelephony telephony = getITelephony();
@@ -1985,6 +2066,7 @@
     /** Current network is IWLAN */
     public static final int NETWORK_TYPE_IWLAN = TelephonyProtoEnums.NETWORK_TYPE_IWLAN; // = 18.
     /** Current network is LTE_CA {@hide} */
+    @UnsupportedAppUsage
     public static final int NETWORK_TYPE_LTE_CA = TelephonyProtoEnums.NETWORK_TYPE_LTE_CA; // = 19.
 
     /** Max network type number. Update as new types are added. Don't add negative types. {@hide} */
@@ -2037,6 +2119,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+   @UnsupportedAppUsage
    public int getNetworkType(int subId) {
        try {
            ITelephony telephony = getITelephony();
@@ -2099,6 +2182,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getDataNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -2134,6 +2218,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getVoiceNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -2161,10 +2246,13 @@
     /** Unknown network class. {@hide} */
     public static final int NETWORK_CLASS_UNKNOWN = 0;
     /** Class of broadly defined "2G" networks. {@hide} */
+    @UnsupportedAppUsage
     public static final int NETWORK_CLASS_2_G = 1;
     /** Class of broadly defined "3G" networks. {@hide} */
+    @UnsupportedAppUsage
     public static final int NETWORK_CLASS_3_G = 2;
     /** Class of broadly defined "4G" networks. {@hide} */
+    @UnsupportedAppUsage
     public static final int NETWORK_CLASS_4_G = 3;
 
     /**
@@ -2173,6 +2261,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getNetworkClass(int networkType) {
         switch (networkType) {
             case NETWORK_TYPE_GPRS:
@@ -2209,6 +2298,7 @@
      *
      * @hide pending API council review
      */
+    @UnsupportedAppUsage
     public String getNetworkTypeName() {
         return getNetworkTypeName(getNetworkType());
     }
@@ -2221,6 +2311,7 @@
      *
      */
     /** {@hide} */
+    @UnsupportedAppUsage
     public static String getNetworkTypeName(int type) {
         switch (type) {
             case NETWORK_TYPE_GPRS:
@@ -2420,6 +2511,7 @@
      */
     /** {@hide} */
     // FIXME Input argument slotIndex should be of type int
+    @UnsupportedAppUsage
     public boolean hasIccCard(int slotIndex) {
 
         try {
@@ -2583,6 +2675,7 @@
      * @param subId for which SimOperator is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperator(int subId) {
         return getSimOperatorNumeric(subId);
     }
@@ -2596,6 +2689,7 @@
      * @see #getSimState
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorNumeric() {
         int subId = mSubId;
         if (!SubscriptionManager.isUsableSubIdValue(subId)) {
@@ -2624,6 +2718,7 @@
      * @param subId for which SimOperator is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorNumeric(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimOperatorNumericForPhone(phoneId);
@@ -2637,6 +2732,7 @@
      * @param phoneId for which SimOperator is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorNumericForPhone(int phoneId) {
         return getTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
@@ -2663,6 +2759,7 @@
      * @param subId for which SimOperatorName is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorName(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimOperatorNameForPhone(phoneId);
@@ -2673,6 +2770,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimOperatorNameForPhone(int phoneId) {
          return getTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "");
@@ -2691,6 +2789,7 @@
      * @param subId for which SimCountryIso is returned
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimCountryIso(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimCountryIsoForPhone(phoneId);
@@ -2701,6 +2800,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getSimCountryIsoForPhone(int phoneId) {
         return getTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
@@ -2727,6 +2827,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getSimSerialNumber(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -2752,6 +2853,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getLteOnCdmaMode() {
         return getLteOnCdmaMode(getSubId());
     }
@@ -2767,6 +2869,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getLteOnCdmaMode(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -2874,6 +2977,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getSubscriberId(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3054,6 +3158,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getGroupIdLevel1(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3103,6 +3208,7 @@
             android.Manifest.permission.READ_SMS,
             android.Manifest.permission.READ_PHONE_NUMBERS
     })
+    @UnsupportedAppUsage
     public String getLine1Number(int subId) {
         String number = null;
         try {
@@ -3189,6 +3295,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getLine1AlphaTag(int subId) {
         String alphaTag = null;
         try {
@@ -3223,6 +3330,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable String[] getMergedSubscriberIds() {
         try {
             ITelephony telephony = getITelephony();
@@ -3241,6 +3349,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getMsisdn() {
         return getMsisdn(getSubId());
     }
@@ -3253,6 +3362,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getMsisdn(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3286,6 +3396,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getVoiceMailNumber(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3845,6 +3956,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getVoiceMessageCount() {
         return getVoiceMessageCount(getSubId());
     }
@@ -3855,6 +3967,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getVoiceMessageCount(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -3890,6 +4003,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getVoiceMailAlphaTag(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3936,6 +4050,7 @@
      * @return the IMPI, or null if not present or not loaded
      * @hide
      */
+    @UnsupportedAppUsage
     public String getIsimImpi() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3956,6 +4071,7 @@
      * @return the IMS domain name, or null if not present or not loaded
      * @hide
      */
+    @UnsupportedAppUsage
     public String getIsimDomain() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3977,6 +4093,7 @@
      *      not present or not loaded
      * @hide
      */
+    @UnsupportedAppUsage
     public String[] getIsimImpu() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3995,6 +4112,7 @@
    /**
     * @hide
     */
+    @UnsupportedAppUsage
     private IPhoneSubInfo getSubscriberInfo() {
         // get it each time because that process crashes a lot
         return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
@@ -4060,6 +4178,7 @@
      * @param subId the subscription to check call state for.
      * @hide
      */
+    @UnsupportedAppUsage
     public @CallState int getCallState(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getCallStateForSlot(phoneId);
@@ -4171,6 +4290,7 @@
    /**
     * @hide
     */
+    @UnsupportedAppUsage
     private ITelephony getITelephony() {
         return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
     }
@@ -4255,6 +4375,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getCdmaEriIconIndex(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4289,6 +4410,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public int getCdmaEriIconMode(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4319,6 +4441,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @UnsupportedAppUsage
     public String getCdmaEriText(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4791,6 +4914,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String nvReadItem(int itemID) {
         try {
             ITelephony telephony = getITelephony();
@@ -4871,6 +4995,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean nvResetConfig(int resetType) {
         try {
             ITelephony telephony = getITelephony();
@@ -4907,6 +5032,7 @@
      * {@see SubscriptionManager#getDefaultVoiceSubscriptionId()}
      * {@see SubscriptionManager#getDefaultSmsSubscriptionId()}
      */
+    @UnsupportedAppUsage
     private int getSubId(int preferredSubId) {
         if (SubscriptionManager.isUsableSubIdValue(mSubId)) {
             return mSubId;
@@ -4935,6 +5061,7 @@
      * {@see SubscriptionManager#getDefaultVoiceSubscriptionId()}
      * {@see SubscriptionManager#getDefaultSmsSubscriptionId()}
      */
+    @UnsupportedAppUsage
     private int getPhoneId(int preferredSubId) {
         return SubscriptionManager.getPhoneId(getSubId(preferredSubId));
     }
@@ -4950,6 +5077,7 @@
      * {@hide}
      */
     @VisibleForTesting
+    @UnsupportedAppUsage
     public int getSlotIndex() {
         int slotIndex = SubscriptionManager.getSlotIndex(getSubId());
         if (slotIndex == SubscriptionManager.SIM_NOT_INSERTED) {
@@ -4963,6 +5091,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void setTelephonyProperty(int phoneId, String property, String value) {
         String propVal = "";
         String p[] = null;
@@ -5040,6 +5169,7 @@
      * @return The value at the given index of settings.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int getIntAtIndex(android.content.ContentResolver cr,
             String name, int index)
             throws android.provider.Settings.SettingNotFoundException {
@@ -5072,6 +5202,7 @@
      * @return true if the value was set, false on database errors
      * @hide
      */
+    @UnsupportedAppUsage
     public static boolean putIntAtIndex(android.content.ContentResolver cr,
             String name, int index, int value) {
         String data = "";
@@ -5113,6 +5244,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String getTelephonyProperty(int phoneId, String property, String defaultVal) {
         String propVal = null;
         String prop = SystemProperties.get(property);
@@ -5133,12 +5265,14 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static String getTelephonyProperty(String property, String defaultVal) {
         String propVal = SystemProperties.get(property);
         return propVal == null ? defaultVal : propVal;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getSimCount() {
         // FIXME Need to get it from Telephony Dev Controller when that gets implemented!
         // and then this method shouldn't be used at all!
@@ -5175,6 +5309,7 @@
      *         not present or not loaded
      * @hide
      */
+    @UnsupportedAppUsage
     public String[] getIsimPcscf() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -5255,6 +5390,7 @@
      *   Authentication error, no memory space available in EFMUK
      * @hide
      */
+    @UnsupportedAppUsage
     public String getIccAuthentication(int subId, int appType, int authType, String data) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -5417,6 +5553,7 @@
      * Corresponds to features defined in ImsFeature.
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable IImsRegistration getImsRegistration(int slotIndex, int feature) {
         try {
             ITelephony telephony = getITelephony();
@@ -5436,6 +5573,7 @@
      * Corresponds to features defined in ImsFeature.
      * @hide
      */
+    @UnsupportedAppUsage
     public @Nullable IImsConfig getImsConfig(int slotIndex, int feature) {
         try {
             ITelephony telephony = getITelephony();
@@ -5454,6 +5592,7 @@
      * @param Registration state
      * @hide
      */
+    @UnsupportedAppUsage
     public void setImsRegistrationState(boolean registered) {
         try {
             ITelephony telephony = getITelephony();
@@ -5474,6 +5613,7 @@
      * @return the preferred network type, defined in RILConstants.java.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getPreferredNetworkType(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -5622,6 +5762,7 @@
      * @return true on success; false on any failure.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setPreferredNetworkType(int subId, int networkType) {
         try {
             ITelephony telephony = getITelephony();
@@ -5796,6 +5937,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setRoamingOverride(List<String> gsmRoamingList,
             List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
             List<String> cdmaNonRoamingList) {
@@ -6609,14 +6751,12 @@
     @Deprecated
     public boolean isTtyModeSupported() {
         try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                return telephony.isTtyModeSupported();
+            TelecomManager telecomManager = TelecomManager.from(mContext);
+            if (telecomManager != null) {
+                return telecomManager.isTtySupported();
             }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#isTtyModeSupported", e);
         } catch (SecurityException e) {
-            Log.e(TAG, "Permission error calling ITelephony#isTtyModeSupported", e);
+            Log.e(TAG, "Permission error calling TelecomManager#isTtySupported", e);
         }
         return false;
     }
@@ -6668,6 +6808,7 @@
      * @see SubscriptionManager#getDefaultSubscriptionId()
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isImsRegistered() {
        try {
            return getITelephony().isImsRegistered(getSubId());
@@ -6684,6 +6825,7 @@
      * @see SubscriptionManager#getDefaultSubscriptionId()
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isVolteAvailable() {
         try {
             return getITelephony().isVolteAvailable(getSubId());
@@ -6700,6 +6842,7 @@
      * @return true if VT is available, or false if it is unavailable or unknown.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isVideoTelephonyAvailable() {
         try {
             return getITelephony().isVideoTelephonyAvailable(getSubId());
@@ -6714,6 +6857,7 @@
      * @return true if VoWiFi is available, or false if it is unavailable or unknown.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isWifiCallingAvailable() {
        try {
            return getITelephony().isWifiCallingAvailable(getSubId());
@@ -6756,6 +6900,7 @@
     *
     * @hide
     */
+    @UnsupportedAppUsage
     public void setSimOperatorNumericForPhone(int phoneId, String numeric) {
         setTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, numeric);
@@ -6776,6 +6921,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSimOperatorNameForPhone(int phoneId, String name) {
         setTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, name);
@@ -6796,6 +6942,7 @@
     *
     * @hide
     */
+    @UnsupportedAppUsage
     public void setSimCountryIsoForPhone(int phoneId, String iso) {
         setTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, iso);
@@ -6816,6 +6963,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSimStateForPhone(int phoneId, String state) {
         setTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_SIM_STATE, state);
@@ -6921,6 +7069,7 @@
      * @param version baseband version
      * @hide
      */
+    @UnsupportedAppUsage
     public void setBasebandVersionForPhone(int phoneId, String version) {
         setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_BASEBAND_VERSION, version);
     }
@@ -6986,6 +7135,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPhoneType(int phoneId, int type) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             TelephonyManager.setTelephonyProperty(phoneId,
@@ -7015,6 +7165,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public String getOtaSpNumberSchemaForPhone(int phoneId, String defaultValue) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             return TelephonyManager.getTelephonyProperty(phoneId,
@@ -7102,6 +7253,7 @@
      * @param name the alphabetic name of current registered operator.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNetworkOperatorNameForPhone(int phoneId, String name) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, name);
@@ -7124,6 +7276,7 @@
      * @param operator the numeric name (MCC+MNC) of current registered operator
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNetworkOperatorNumericForPhone(int phoneId, String numeric) {
         setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, numeric);
     }
@@ -7144,6 +7297,7 @@
      * @param isRoaming is network in romaing state or not
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNetworkRoamingForPhone(int phoneId, boolean isRoaming) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
@@ -7171,6 +7325,7 @@
      * @param type the network type currently in use on the device for data transmission
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDataNetworkTypeForPhone(int phoneId, int type) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
             setTelephonyProperty(phoneId,
@@ -7183,6 +7338,7 @@
      * Returns the subscription ID for the given phone account.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
         int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         try {
@@ -7274,6 +7430,7 @@
      * either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information.
      * @hide
      */
+    @UnsupportedAppUsage
     public ServiceState getServiceStateForSubscriber(int subId) {
         try {
             ITelephony service = getITelephony();
@@ -7934,4 +8091,23 @@
         }
         return UNKNOWN_CARRIER_ID_LIST_VERSION;
     }
+
+
+    /**
+     * How many modems can have simultaneous data connections.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public int getNumberOfModemsWithSimultaneousDataConnections() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getNumberOfModemsWithSimultaneousDataConnections(
+                        getSubId(), mContext.getOpPackageName());
+            }
+        } catch (RemoteException ex) {
+            // This could happen if binder process crashes.
+        }
+        return 0;
+    }
 }
diff --git a/telephony/java/android/telephony/VoLteServiceState.java b/telephony/java/android/telephony/VoLteServiceState.java
index afef601b..25bb8b4 100644
--- a/telephony/java/android/telephony/VoLteServiceState.java
+++ b/telephony/java/android/telephony/VoLteServiceState.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -77,6 +78,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public VoLteServiceState(int srvccState) {
         initialize();
 
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index 7c10569..ee602c0 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -16,6 +16,7 @@
 
 package android.telephony.cdma;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.telephony.CellLocation;
 
@@ -23,6 +24,7 @@
  * Represents the cell location on a CDMA phone.
  */
 public class CdmaCellLocation extends CellLocation {
+    @UnsupportedAppUsage
     private int mBaseStationId = -1;
 
     /**
@@ -36,6 +38,7 @@
      * to 1296000, both values inclusive (corresponding to a range of -90
      * to +90 degrees). Integer.MAX_VALUE is considered invalid value.
      */
+    @UnsupportedAppUsage
     private int mBaseStationLatitude = INVALID_LAT_LONG;
 
     /**
@@ -44,9 +47,12 @@
      * to 2592000, both values inclusive (corresponding to a range of -180
      * to +180 degrees). Integer.MAX_VALUE is considered invalid value.
      */
+    @UnsupportedAppUsage
     private int mBaseStationLongitude = INVALID_LAT_LONG;
 
+    @UnsupportedAppUsage
     private int mSystemId = -1;
+    @UnsupportedAppUsage
     private int mNetworkId = -1;
 
     /**
@@ -200,6 +206,7 @@
      * @param b second obj
      * @return true if two objects equal or both are null
      */
+    @UnsupportedAppUsage
     private static boolean equalsHandlesNulls(Object a, Object b) {
         return (a == null) ? (b == null) : a.equals (b);
     }
diff --git a/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl
new file mode 100644
index 0000000..9c80cb7
--- /dev/null
+++ b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.data;
+
+import android.telephony.data.IQualifiedNetworksServiceCallback;
+
+/**
+ * {@hide}
+ */
+interface IQualifiedNetworksService
+{
+    oneway void createNetworkAvailabilityUpdater(int slotId, IQualifiedNetworksServiceCallback callback);
+    oneway void removeNetworkAvailabilityUpdater(int slotId);
+}
diff --git a/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl b/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl
new file mode 100644
index 0000000..e8e1f01
--- /dev/null
+++ b/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.data;
+
+/**
+ * The qualified networks service call back interface
+ * @hide
+ */
+oneway interface IQualifiedNetworksServiceCallback
+{
+    void onQualifiedNetworkTypesChanged(int apnType, in int[] qualifiedNetworkTypesList);
+}
diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java
new file mode 100644
index 0000000..bb89f19
--- /dev/null
+++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.data;
+
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.Rlog;
+import android.telephony.data.ApnSetting.ApnType;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Base class of the qualified networks service. Services that extend QualifiedNetworksService must
+ * register the service in their AndroidManifest to be detected by the framework. They must be
+ * protected by the permission "android.permission.BIND_TELEPHONY_QUALIFIED_NETWORKS_SERVICE".
+ * The qualified networks service definition in the manifest must follow the following format:
+ * ...
+ * <service android:name=".xxxQualifiedNetworksService"
+ *     android:permission="android.permission.BIND_TELEPHONY_QUALIFIED_NETWORKS_SERVICE" >
+ *     <intent-filter>
+ *         <action android:name="android.telephony.data.QualifiedNetworksService" />
+ *     </intent-filter>
+ * </service>
+ * @hide
+ */
+@SystemApi
+public abstract class QualifiedNetworksService extends Service {
+    private static final String TAG = QualifiedNetworksService.class.getSimpleName();
+
+    public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE =
+            "android.telephony.data.QualifiedNetworksService";
+
+    private static final int QNS_CREATE_NETWORK_AVAILABILITY_UPDATER                = 1;
+    private static final int QNS_REMOVE_NETWORK_AVAILABILITY_UPDATER                = 2;
+    private static final int QNS_REMOVE_ALL_NETWORK_AVAILABILITY_UPDATERS           = 3;
+    private static final int QNS_UPDATE_QUALIFIED_NETWORKS                          = 4;
+
+    private final HandlerThread mHandlerThread;
+
+    private final QualifiedNetworksServiceHandler mHandler;
+
+    private final SparseArray<NetworkAvailabilityUpdater> mUpdaters = new SparseArray<>();
+
+    /** @hide */
+    @VisibleForTesting
+    public final IQualifiedNetworksServiceWrapper mBinder = new IQualifiedNetworksServiceWrapper();
+
+    /**
+     * The abstract class of the network availability updater implementation. The vendor qualified
+     * network service must extend this class to report the available networks for data
+     * connection setup. Note that each instance of network availability updater is associated with
+     * one physical SIM slot.
+     */
+    public abstract class NetworkAvailabilityUpdater implements AutoCloseable {
+        private final int mSlotIndex;
+
+        private IQualifiedNetworksServiceCallback mCallback;
+
+        /**
+         * Qualified networks for each APN type. Key is the {@link ApnType}, value is the array
+         * of available networks.
+         */
+        private SparseArray<int[]> mQualifiedNetworkTypesList = new SparseArray<>();
+
+        /**
+         * Constructor
+         * @param slotIndex SIM slot index the network availability updater associated with.
+         */
+        public NetworkAvailabilityUpdater(int slotIndex) {
+            mSlotIndex = slotIndex;
+        }
+
+        /**
+         * @return SIM slot index the network availability updater associated with.
+         */
+        public final int getSlotIndex() {
+            return mSlotIndex;
+        }
+
+        private void registerForQualifiedNetworkTypesChanged(
+                IQualifiedNetworksServiceCallback callback) {
+            mCallback = callback;
+
+            // Force sending the qualified networks upon registered.
+            if (mCallback != null) {
+                for (int i = 0; i < mQualifiedNetworkTypesList.size(); i++) {
+                    try {
+                        mCallback.onQualifiedNetworkTypesChanged(
+                                mQualifiedNetworkTypesList.keyAt(i),
+                                mQualifiedNetworkTypesList.valueAt(i));
+                    } catch (RemoteException e) {
+                        loge("Failed to call onQualifiedNetworksChanged. " + e);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Update the qualified networks list. Network availability updater must invoke this method
+         * whenever the qualified networks changes. If this method is never invoked for certain
+         * APN type, then frameworks will always use the default (i.e. cellular) data and network
+         * service.
+         *
+         * @param apnType APN type of the qualified networks
+         * @param qualifiedNetworkTypes List of network types which are qualified for data
+         * connection setup for {@link @apnType} in the preferred order. Each element in the array
+         * is a {@link AccessNetworkType}. An empty list or null indicates no networks are qualified
+         * for data setup.
+         */
+        public final void updateQualifiedNetworkTypes(@ApnType int apnType,
+                                                      int[] qualifiedNetworkTypes) {
+            mHandler.obtainMessage(QNS_UPDATE_QUALIFIED_NETWORKS, mSlotIndex, apnType,
+                    qualifiedNetworkTypes).sendToTarget();
+        }
+
+        private void onUpdateQualifiedNetworkTypes(@ApnType int apnType,
+                                                   int[] qualifiedNetworkTypes) {
+            mQualifiedNetworkTypesList.put(apnType, qualifiedNetworkTypes);
+            if (mCallback != null) {
+                try {
+                    mCallback.onQualifiedNetworkTypesChanged(apnType, qualifiedNetworkTypes);
+                } catch (RemoteException e) {
+                    loge("Failed to call onQualifiedNetworksChanged. " + e);
+                }
+            }
+        }
+
+        /**
+         * Called when the qualified networks updater is removed. The extended class should
+         * implement this method to perform clean up works.
+         */
+        @Override
+        public abstract void close();
+    }
+
+    private class QualifiedNetworksServiceHandler extends Handler {
+        QualifiedNetworksServiceHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            IQualifiedNetworksServiceCallback callback;
+            final int slotIndex = message.arg1;
+            NetworkAvailabilityUpdater updater = mUpdaters.get(slotIndex);
+
+            switch (message.what) {
+                case QNS_CREATE_NETWORK_AVAILABILITY_UPDATER:
+                    if (mUpdaters.get(slotIndex) != null) {
+                        loge("Network availability updater for slot " + slotIndex
+                                + " already existed.");
+                        return;
+                    }
+
+                    updater = createNetworkAvailabilityUpdater(slotIndex);
+                    if (updater != null) {
+                        mUpdaters.put(slotIndex, updater);
+
+                        callback = (IQualifiedNetworksServiceCallback) message.obj;
+                        updater.registerForQualifiedNetworkTypesChanged(callback);
+                    } else {
+                        loge("Failed to create network availability updater. slot index = "
+                                + slotIndex);
+                    }
+                    break;
+
+                case QNS_REMOVE_NETWORK_AVAILABILITY_UPDATER:
+                    if (updater != null) {
+                        updater.close();
+                        mUpdaters.remove(slotIndex);
+                    }
+                    break;
+
+                case QNS_REMOVE_ALL_NETWORK_AVAILABILITY_UPDATERS:
+                    for (int i = 0; i < mUpdaters.size(); i++) {
+                        updater = mUpdaters.get(i);
+                        if (updater != null) {
+                            updater.close();
+                        }
+                    }
+                    mUpdaters.clear();
+                    break;
+
+                case QNS_UPDATE_QUALIFIED_NETWORKS:
+                    if (updater == null) break;
+                    updater.onUpdateQualifiedNetworkTypes(message.arg2, (int[]) message.obj);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Default constructor.
+     */
+    public QualifiedNetworksService() {
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+
+        mHandler = new QualifiedNetworksServiceHandler(mHandlerThread.getLooper());
+        log("Qualified networks service created");
+    }
+
+    /**
+     * Create the instance of {@link NetworkAvailabilityUpdater}. Vendor qualified network service
+     * must override this method to facilitate the creation of {@link NetworkAvailabilityUpdater}
+     * instances. The system will call this method after binding the qualified networks service for
+     * each active SIM slot index.
+     *
+     * @param slotIndex SIM slot index the qualified networks service associated with.
+     * @return Qualified networks service instance
+     */
+    public abstract NetworkAvailabilityUpdater createNetworkAvailabilityUpdater(int slotIndex);
+
+    /** @hide */
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (intent == null || !QUALIFIED_NETWORKS_SERVICE_INTERFACE.equals(intent.getAction())) {
+            loge("Unexpected intent " + intent);
+            return null;
+        }
+        return mBinder;
+    }
+
+    /** @hide */
+    @Override
+    public boolean onUnbind(Intent intent) {
+        mHandler.obtainMessage(QNS_REMOVE_ALL_NETWORK_AVAILABILITY_UPDATERS).sendToTarget();
+        return false;
+    }
+
+    /** @hide */
+    @Override
+    public void onDestroy() {
+        mHandlerThread.quit();
+    }
+
+    /**
+     * A wrapper around IQualifiedNetworksService that forwards calls to implementations of
+     * {@link QualifiedNetworksService}.
+     */
+    private class IQualifiedNetworksServiceWrapper extends IQualifiedNetworksService.Stub {
+        @Override
+        public void createNetworkAvailabilityUpdater(int slotIndex,
+                                                     IQualifiedNetworksServiceCallback callback) {
+            mHandler.obtainMessage(QNS_CREATE_NETWORK_AVAILABILITY_UPDATER, slotIndex, 0,
+                    callback).sendToTarget();
+        }
+
+        @Override
+        public void removeNetworkAvailabilityUpdater(int slotIndex) {
+            mHandler.obtainMessage(QNS_REMOVE_NETWORK_AVAILABILITY_UPDATER, slotIndex, 0)
+                    .sendToTarget();
+        }
+    }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private void loge(String s) {
+        Rlog.e(TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index edf3b08..f1d5bdd 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -17,6 +17,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -59,6 +60,7 @@
      */
     @Nullable
     @Deprecated
+    @UnsupportedAppUsage
     public final String encodedActivationCode;
 
     @Nullable private String confirmationCode;
@@ -188,6 +190,7 @@
      * @deprecated - Do not use.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setCarrierName(String carrierName) {
         this.carrierName = carrierName;
     }
@@ -234,6 +237,7 @@
      * @deprecated - Do not use.
      */
     @Deprecated
+    @UnsupportedAppUsage
     public void setAccessRules(UiccAccessRule[] accessRules) {
         this.accessRules = Arrays.asList(accessRules);
     }
diff --git a/telephony/java/android/telephony/euicc/EuiccInfo.java b/telephony/java/android/telephony/euicc/EuiccInfo.java
index a4adf05..28855b2 100644
--- a/telephony/java/android/telephony/euicc/EuiccInfo.java
+++ b/telephony/java/android/telephony/euicc/EuiccInfo.java
@@ -16,6 +16,7 @@
 package android.telephony.euicc;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -43,6 +44,7 @@
             };
 
     @Nullable
+    @UnsupportedAppUsage
     private final String osVersion;
 
     /**
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index 1717802..98ce333 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -16,6 +16,7 @@
 
 package android.telephony.gsm;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.telephony.CellLocation;
 
@@ -91,6 +92,7 @@
      * Set the primary scrambling code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPsc(int psc) {
         mPsc = psc;
     }
diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index 2831127..34b8884 100644
--- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -30,30 +31,37 @@
     // Refer to ImsUtInterface#CDIV_CF_XXX
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mCondition;
     // 0: disabled, 1: enabled
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mStatus;
     // 0x91: International, 0x81: Unknown
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mToA;
     // Service class
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mServiceClass;
     // Number (it will not include the "sip" or "tel" URI scheme)
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public String mNumber;
     // No reply timer for CF
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter.
+    @UnsupportedAppUsage
     public int mTimeSeconds;
 
     /** @hide */
     // TODO: Will be removed in the future, use public constructor instead.
+    @UnsupportedAppUsage
     public ImsCallForwardInfo() {
     }
 
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 350dfe3..f0d3c89 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -260,8 +261,10 @@
     /** @hide */
     public int mServiceType;
     /** @hide */
+    @UnsupportedAppUsage
     public int mCallType;
     /** @hide */
+    @UnsupportedAppUsage
     public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
 
     /**
@@ -287,8 +290,10 @@
      * a {@link android.os.Binder}.
      */
     /** @hide */
+    @UnsupportedAppUsage
     public Bundle mCallExtras;
     /** @hide */
+    @UnsupportedAppUsage
     public ImsStreamMediaProfile mMediaProfile;
 
     /** @hide */
@@ -568,6 +573,7 @@
      * See {@link #presentationToOir(int)}.
      * @hide
      */
+    @UnsupportedAppUsage
     public static int presentationToOIR(int presentation) {
         switch (presentation) {
             case PhoneConstants.PRESENTATION_RESTRICTED:
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index d03c7e1..8d18ae8 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -58,6 +59,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public ImsExternalCallState(int callId, Uri address, boolean isPullable, int callState,
             int callType, boolean isCallheld) {
         mCallId = callId;
@@ -87,6 +89,7 @@
         mCallId = in.readInt();
         ClassLoader classLoader = ImsExternalCallState.class.getClassLoader();
         mAddress = in.readParcelable(classLoader);
+        mLocalAddress = in.readParcelable(classLoader);
         mIsPullable = (in.readInt() != 0);
         mCallState = in.readInt();
         mCallType = in.readInt();
@@ -103,6 +106,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mCallId);
         out.writeParcelable(mAddress, 0);
+        out.writeParcelable(mLocalAddress, 0);
         out.writeInt(mIsPullable ? 1 : 0);
         out.writeInt(mCallState);
         out.writeInt(mCallType);
@@ -131,6 +135,11 @@
         return mAddress;
     }
 
+    /** @hide */
+    public Uri getLocalAddress() {
+        return mLocalAddress;
+    }
+
     public boolean isCallPullable() {
         return mIsPullable;
     }
@@ -151,6 +160,7 @@
     public String toString() {
         return "ImsExternalCallState { mCallId = " + mCallId +
                 ", mAddress = " + Log.pii(mAddress) +
+                ", mLocalAddress = " + Log.pii(mLocalAddress) +
                 ", mIsPullable = " + mIsPullable +
                 ", mCallState = " + mCallState +
                 ", mCallType = " + mCallType +
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 81f2fe7..b981f05 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -163,6 +164,8 @@
     public static final int CODE_SIP_NOT_REACHABLE = 341;
     // Others
     public static final int CODE_SIP_CLIENT_ERROR = 342;
+    // 481 Transaction Does Not Exist
+    public static final int CODE_SIP_TRANSACTION_DOES_NOT_EXIST = 343;
     // 5xx responses
     // 501 : Server Internal Error
     public static final int CODE_SIP_SERVER_INTERNAL_ERROR = 351;
@@ -581,12 +584,15 @@
 
     // For main reason code
     /** @hide */
+    @UnsupportedAppUsage
     public int mCode;
     // For the extra code value; it depends on the code value.
     /** @hide */
+    @UnsupportedAppUsage
     public int mExtraCode;
     // For the additional message of the reason info.
     /** @hide */
+    @UnsupportedAppUsage
     public String mExtraMessage;
 
     /** @hide */
@@ -603,6 +609,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public ImsReasonInfo(int code, int extraCode) {
         mCode = code;
         mExtraCode = extraCode;
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index c6f8622..3a784c1 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -16,10 +16,15 @@
 
 package android.telephony.ims;
 
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Provides the result to the update operation for the supplementary service configuration.
  *
@@ -34,16 +39,45 @@
     public static final int DISABLED = 0;
     public static final int ENABLED = 1;
 
+    /**
+     * Provision status of service
+     */
+    /** @hide */
+    @IntDef({
+            SERVICE_PROVISIONING_UNKNOWN,
+            SERVICE_NOT_PROVISIONED,
+            SERVICE_PROVISIONED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ServiceProvisionStatus {}
+    /**
+     * Unknown provision status for the service.
+     */
+    public static final int SERVICE_PROVISIONING_UNKNOWN = (-1);
+    /**
+     * Service is not provisioned.
+     */
+    public static final int SERVICE_NOT_PROVISIONED = 0;
+    /**
+     * Service is provisioned.
+     */
+    public static final int SERVICE_PROVISIONED = 1;
+
     // 0: disabled, 1: enabled
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter!
+    @UnsupportedAppUsage
     public int mStatus;
     /** @hide */
     // TODO: Make private, do not modify this field directly, use getter!
+    @UnsupportedAppUsage
     public String mIcbNum;
+    /** @hide */
+    public int mProvisionStatus = SERVICE_PROVISIONING_UNKNOWN;
 
     /**@hide*/
     // TODO: Remove! Do not use this constructor, instead use public version.
+    @UnsupportedAppUsage
     public ImsSsInfo() {
     }
 
@@ -74,16 +108,30 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mStatus);
         out.writeString(mIcbNum);
+        out.writeInt(mProvisionStatus);
     }
 
     @Override
     public String toString() {
-        return super.toString() + ", Status: " + ((mStatus == 0) ? "disabled" : "enabled");
+        return super.toString() + ", Status: " + ((mStatus == 0) ? "disabled" : "enabled")
+                + ", ProvisionStatus: " + provisionStatusToString(mProvisionStatus);
+    }
+
+    private static String provisionStatusToString(int pStatus) {
+        switch (pStatus) {
+            case SERVICE_NOT_PROVISIONED:
+                return "Service not provisioned";
+             case SERVICE_PROVISIONED:
+                return "Service provisioned";
+             default:
+                return "Service provisioning unknown";
+        }
     }
 
     private void readFromParcel(Parcel in) {
         mStatus = in.readInt();
         mIcbNum = in.readString();
+        mProvisionStatus = in.readInt();
     }
 
     public static final Creator<ImsSsInfo> CREATOR =
@@ -112,4 +160,15 @@
     public String getIcbNum() {
         return mIcbNum;
     }
+
+    /**
+     * @return Supplementary Service Provision status. Valid Values are:
+     *     {@link #SERVICE_PROVISIONING_UNKNOWN},
+     *     {@link #SERVICE_NOT_PROVISIONED},
+     *     {@link #SERVICE_PROVISIONED}
+     */
+    @ServiceProvisionStatus
+    public int getProvisionStatus() {
+        return mProvisionStatus;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index 137106a..52d72b5 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -82,13 +83,16 @@
 
     // Audio related information
     /** @hide */
+    @UnsupportedAppUsage
     public int mAudioQuality;
     /** @hide */
+    @UnsupportedAppUsage
     public int mAudioDirection;
     // Video related information
     /** @hide */
     public int mVideoQuality;
     /** @hide */
+    @UnsupportedAppUsage
     public int mVideoDirection;
     // Rtt related information
     /** @hide */
@@ -156,6 +160,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public ImsStreamMediaProfile() {
         mAudioQuality = AUDIO_QUALITY_NONE;
         mAudioDirection = DIRECTION_SEND_RECEIVE;
diff --git a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index b4f60b9..1772401 100644
--- a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
@@ -179,6 +180,7 @@
      * Returns binder object which can be used across IPC methods.
      * @hide
      */
+    @UnsupportedAppUsage
     public final IImsVideoCallProvider getInterface() {
         return mBinder;
     }
diff --git a/telephony/java/android/telephony/ims/compat/ImsService.java b/telephony/java/android/telephony/ims/compat/ImsService.java
index cf1efb3..2750e51 100644
--- a/telephony/java/android/telephony/ims/compat/ImsService.java
+++ b/telephony/java/android/telephony/ims/compat/ImsService.java
@@ -17,6 +17,7 @@
 package android.telephony.ims.compat;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
@@ -86,6 +87,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     protected final IBinder mImsServiceController = new IImsServiceController.Stub() {
 
         @Override
diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
index 0a12cae..e8fcac1 100644
--- a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
@@ -17,6 +17,7 @@
 package android.telephony.ims.compat.feature;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.os.IInterface;
@@ -104,10 +105,12 @@
         mSlotId = slotId;
     }
 
+    @UnsupportedAppUsage
     public int getFeatureState() {
         return mState;
     }
 
+    @UnsupportedAppUsage
     protected final void setFeatureState(@ImsState int state) {
         if (mState != state) {
             mState = state;
diff --git a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
index d3d17f4..40ea208 100644
--- a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
@@ -20,6 +20,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsCallSessionListener;
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
index e5ed825..23de2fd 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
@@ -28,6 +28,7 @@
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsVideoCallProvider;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.ims.ImsCallSession;
 
 /**
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
index 2c325ba8..e55c3d0 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
@@ -16,6 +16,7 @@
 
 package android.telephony.ims.compat.stub;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
 import android.os.RemoteException;
@@ -58,6 +59,7 @@
 
     ImsConfigStub mImsConfigStub;
 
+    @UnsupportedAppUsage
     public ImsConfigImplBase(Context context) {
         mImsConfigStub = new ImsConfigStub(this, context);
     }
@@ -162,6 +164,7 @@
     public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException {
     }
 
+    @UnsupportedAppUsage
     public IImsConfig getIImsConfig() { return mImsConfigStub; }
 
     /**
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
index b2aa080..976c2be 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
@@ -19,6 +19,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.ims.ImsCallForwardInfo;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.ImsSsData;
diff --git a/telephony/java/com/android/ims/internal/uce/common/CapInfo.java b/telephony/java/com/android/ims/internal/uce/common/CapInfo.java
index 56969a8..a9847ba 100644
--- a/telephony/java/com/android/ims/internal/uce/common/CapInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/common/CapInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.common;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -73,6 +74,7 @@
     /**
      * Constructor for the CapInfo class.
      */
+    @UnsupportedAppUsage
     public CapInfo() {
     };
 
@@ -80,6 +82,7 @@
     /**
      * Checks whether IM is supported.
      */
+    @UnsupportedAppUsage
     public boolean isImSupported() {
         return mImSupported;
     }
@@ -87,6 +90,7 @@
     /**
      * Sets IM as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setImSupported(boolean imSupported) {
         this.mImSupported = imSupported;
     }
@@ -94,6 +98,7 @@
     /**
      * Checks whether FT Thumbnail is supported.
      */
+    @UnsupportedAppUsage
     public boolean isFtThumbSupported() {
         return mFtThumbSupported;
     }
@@ -101,6 +106,7 @@
     /**
      * Sets FT thumbnail as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setFtThumbSupported(boolean ftThumbSupported) {
         this.mFtThumbSupported = ftThumbSupported;
     }
@@ -110,6 +116,7 @@
     /**
      * Checks whether FT Store and Forward is supported
      */
+    @UnsupportedAppUsage
     public boolean isFtSnFSupported() {
         return  mFtSnFSupported;
     }
@@ -117,6 +124,7 @@
     /**
      * Sets FT Store and Forward as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setFtSnFSupported(boolean  ftSnFSupported) {
         this.mFtSnFSupported =  ftSnFSupported;
     }
@@ -124,6 +132,7 @@
    /**
     * Checks whether File transfer HTTP is supported.
     */
+   @UnsupportedAppUsage
    public boolean isFtHttpSupported() {
        return  mFtHttpSupported;
    }
@@ -131,6 +140,7 @@
    /**
     * Sets File transfer HTTP as supported or not supported.
     */
+   @UnsupportedAppUsage
    public void setFtHttpSupported(boolean  ftHttpSupported) {
        this.mFtHttpSupported =  ftHttpSupported;
    }
@@ -138,6 +148,7 @@
     /**
      * Checks whether FT is supported.
      */
+    @UnsupportedAppUsage
     public boolean isFtSupported() {
         return mFtSupported;
     }
@@ -145,6 +156,7 @@
     /**
      * Sets FT as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setFtSupported(boolean ftSupported) {
         this.mFtSupported = ftSupported;
     }
@@ -152,6 +164,7 @@
     /**
      * Checks whether IS is supported.
      */
+    @UnsupportedAppUsage
     public boolean isIsSupported() {
         return mIsSupported;
     }
@@ -159,6 +172,7 @@
     /**
      * Sets IS as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setIsSupported(boolean isSupported) {
         this.mIsSupported = isSupported;
     }
@@ -166,6 +180,7 @@
     /**
      * Checks whether video sharing is supported during a CS call.
      */
+    @UnsupportedAppUsage
     public boolean isVsDuringCSSupported() {
         return mVsDuringCSSupported;
     }
@@ -174,6 +189,7 @@
      *  Sets video sharing as supported or not supported during a CS
      *  call.
      */
+    @UnsupportedAppUsage
     public void setVsDuringCSSupported(boolean vsDuringCSSupported) {
         this.mVsDuringCSSupported = vsDuringCSSupported;
     }
@@ -182,6 +198,7 @@
      *  Checks whether video sharing outside a voice call is
      *   supported.
      */
+    @UnsupportedAppUsage
     public boolean isVsSupported() {
         return mVsSupported;
     }
@@ -189,6 +206,7 @@
     /**
      * Sets video sharing as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setVsSupported(boolean vsSupported) {
         this.mVsSupported = vsSupported;
     }
@@ -196,6 +214,7 @@
     /**
      * Checks whether social presence is supported.
      */
+    @UnsupportedAppUsage
     public boolean isSpSupported() {
         return mSpSupported;
     }
@@ -203,6 +222,7 @@
     /**
      * Sets social presence as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setSpSupported(boolean spSupported) {
         this.mSpSupported = spSupported;
     }
@@ -211,6 +231,7 @@
      * Checks whether capability discovery via presence is
      * supported.
      */
+    @UnsupportedAppUsage
     public boolean isCdViaPresenceSupported() {
         return mCdViaPresenceSupported;
     }
@@ -219,6 +240,7 @@
      * Sets capability discovery via presence as supported or not
      * supported.
      */
+    @UnsupportedAppUsage
     public void setCdViaPresenceSupported(boolean cdViaPresenceSupported) {
         this.mCdViaPresenceSupported = cdViaPresenceSupported;
     }
@@ -226,6 +248,7 @@
     /**
      * Checks whether IP voice call is supported.
      */
+    @UnsupportedAppUsage
     public boolean isIpVoiceSupported() {
         return mIpVoiceSupported;
     }
@@ -233,6 +256,7 @@
     /**
      * Sets IP voice call as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setIpVoiceSupported(boolean ipVoiceSupported) {
         this.mIpVoiceSupported = ipVoiceSupported;
     }
@@ -240,6 +264,7 @@
     /**
      * Checks whether IP video call is supported.
      */
+    @UnsupportedAppUsage
     public boolean isIpVideoSupported() {
         return mIpVideoSupported;
     }
@@ -247,6 +272,7 @@
     /**
      * Sets IP video call as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setIpVideoSupported(boolean ipVideoSupported) {
         this.mIpVideoSupported = ipVideoSupported;
     }
@@ -255,6 +281,7 @@
     * Checks whether Geo location Pull using File Transfer is
     * supported.
     */
+   @UnsupportedAppUsage
    public boolean isGeoPullFtSupported() {
        return mGeoPullFtSupported;
    }
@@ -263,6 +290,7 @@
     * Sets Geo location Pull using File Transfer as supported or
     * not supported.
     */
+   @UnsupportedAppUsage
    public void setGeoPullFtSupported(boolean geoPullFtSupported) {
        this.mGeoPullFtSupported = geoPullFtSupported;
    }
@@ -270,6 +298,7 @@
     /**
      * Checks whether Geo Pull is supported.
      */
+    @UnsupportedAppUsage
     public boolean isGeoPullSupported() {
         return mGeoPullSupported;
     }
@@ -277,6 +306,7 @@
     /**
      * Sets Geo Pull as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setGeoPullSupported(boolean geoPullSupported) {
         this.mGeoPullSupported = geoPullSupported;
     }
@@ -284,6 +314,7 @@
     /**
      * Checks whether Geo Push is supported.
      */
+    @UnsupportedAppUsage
     public boolean isGeoPushSupported() {
         return mGeoPushSupported;
     }
@@ -291,6 +322,7 @@
     /**
      * Sets Geo Push as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setGeoPushSupported(boolean geoPushSupported) {
         this.mGeoPushSupported = geoPushSupported;
     }
@@ -298,6 +330,7 @@
     /**
      * Checks whether short messaging is supported.
      */
+    @UnsupportedAppUsage
     public boolean isSmSupported() {
         return mSmSupported;
     }
@@ -305,6 +338,7 @@
     /**
      * Sets short messaging as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setSmSupported(boolean smSupported) {
         this.mSmSupported = smSupported;
     }
@@ -312,18 +346,22 @@
     /**
      * Checks whether store/forward and group chat are supported.
      */
+    @UnsupportedAppUsage
     public boolean isFullSnFGroupChatSupported() {
         return mFullSnFGroupChatSupported;
     }
 
+    @UnsupportedAppUsage
     public boolean isRcsIpVoiceCallSupported() {
         return mRcsIpVoiceCallSupported;
     }
 
+    @UnsupportedAppUsage
     public boolean isRcsIpVideoCallSupported() {
         return mRcsIpVideoCallSupported;
     }
 
+    @UnsupportedAppUsage
     public boolean isRcsIpVideoOnlyCallSupported() {
         return mRcsIpVideoOnlyCallSupported;
     }
@@ -331,16 +369,20 @@
     /**
      * Sets store/forward and group chat supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setFullSnFGroupChatSupported(boolean fullSnFGroupChatSupported) {
         this.mFullSnFGroupChatSupported = fullSnFGroupChatSupported;
     }
 
+    @UnsupportedAppUsage
     public void setRcsIpVoiceCallSupported(boolean rcsIpVoiceCallSupported) {
         this.mRcsIpVoiceCallSupported = rcsIpVoiceCallSupported;
     }
+    @UnsupportedAppUsage
     public void setRcsIpVideoCallSupported(boolean rcsIpVideoCallSupported) {
         this.mRcsIpVideoCallSupported = rcsIpVideoCallSupported;
     }
+    @UnsupportedAppUsage
     public void setRcsIpVideoOnlyCallSupported(boolean rcsIpVideoOnlyCallSupported) {
         this.mRcsIpVideoOnlyCallSupported = rcsIpVideoOnlyCallSupported;
     }
@@ -351,17 +393,20 @@
     }
 
     /** Sets the list of supported extensions. */
+    @UnsupportedAppUsage
     public void setExts(String[] exts) {
         this.mExts = exts;
     }
 
 
     /** Gets the time stamp for when to query again. */
+    @UnsupportedAppUsage
     public long getCapTimestamp() {
         return mCapTimestamp;
     }
 
     /** Sets the time stamp for when to query again. */
+    @UnsupportedAppUsage
     public void setCapTimestamp(long capTimestamp) {
         this.mCapTimestamp = capTimestamp;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/common/StatusCode.java b/telephony/java/com/android/ims/internal/uce/common/StatusCode.java
index ad9b669..3921cfb 100644
--- a/telephony/java/com/android/ims/internal/uce/common/StatusCode.java
+++ b/telephony/java/com/android/ims/internal/uce/common/StatusCode.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.common;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -71,12 +72,14 @@
      * Constructor for the StatusCode class.
      * @hide
      */
+    @UnsupportedAppUsage
     public StatusCode() {}
 
     /**
      *  Gets the status code.
      *  @hide
      */
+    @UnsupportedAppUsage
     public int getStatusCode() {
         return mStatusCode;
     }
@@ -85,6 +88,7 @@
      *  Sets the status code.
      *  @hide
      */
+    @UnsupportedAppUsage
     public void setStatusCode(int nStatusCode) {
         this.mStatusCode = nStatusCode;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/common/UceLong.java b/telephony/java/com/android/ims/internal/uce/common/UceLong.java
index fd07fe8..7207899 100644
--- a/telephony/java/com/android/ims/internal/uce/common/UceLong.java
+++ b/telephony/java/com/android/ims/internal/uce/common/UceLong.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.common;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -32,6 +33,7 @@
      * Constructor for the UceLong class.
      * @hide
      */
+    @UnsupportedAppUsage
     public UceLong() {
     };
 
@@ -39,6 +41,7 @@
      * Gets the long value.
      * @hide
      */
+    @UnsupportedAppUsage
     public long getUceLong() {
         return mUceLong;
     }
@@ -47,6 +50,7 @@
      * Sets the long value.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUceLong(long uceLong) {
         this.mUceLong = uceLong;
     }
@@ -54,6 +58,7 @@
     /** Get the client ID as integer value.
      *  @hide
      */
+    @UnsupportedAppUsage
     public int getClientId() {
         return mClientId;
     }
@@ -62,6 +67,7 @@
      * Set the client ID as integer value.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setClientId(int nClientId) {
         this.mClientId = nClientId;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java b/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
index c570f49..bcb9f2d 100644
--- a/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
@@ -15,6 +15,7 @@
  */
 package com.android.ims.internal.uce.options;
 
+import android.annotation.UnsupportedAppUsage;
 import com.android.ims.internal.uce.common.CapInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -30,10 +31,12 @@
         return new OptionsCapInfo();
     }
 
+    @UnsupportedAppUsage
     public String getSdp() {
         return mSdp;
     }
 
+    @UnsupportedAppUsage
     public void setSdp(String sdp) {
         this.mSdp = sdp;
     }
@@ -41,16 +44,19 @@
     /**
      * Constructor for the OptionsCapInfo class.
      */
+    @UnsupportedAppUsage
     public OptionsCapInfo() {
         mCapInfo = new CapInfo();
     };
 
+    @UnsupportedAppUsage
     public CapInfo getCapInfo() {
         return mCapInfo;
     }
     /**
      * Sets the CapInfo
      */
+    @UnsupportedAppUsage
     public void setCapInfo(CapInfo capInfo) {
         this.mCapInfo = capInfo;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java b/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java
index 35f769c..14c64ac 100644
--- a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java
+++ b/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java
@@ -17,6 +17,7 @@
 package com.android.ims.internal.uce.options;
 
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -55,6 +56,7 @@
      * Sets the command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(int nCmdId) {
         this.mCmdId = nCmdId;
     }
@@ -63,6 +65,7 @@
      * Constructor for the OptionsCDCmdId class.
      * @hide
      */
+    @UnsupportedAppUsage
     public OptionsCmdId(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java b/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
index dab191c..4af3e6e 100644
--- a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
+++ b/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
@@ -19,6 +19,7 @@
 import com.android.ims.internal.uce.common.StatusCode;
 import com.android.ims.internal.uce.common.CapInfo;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -41,6 +42,7 @@
      * Sets the command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(OptionsCmdId cmdId) {
         this.mCmdId = cmdId;
     }
@@ -56,6 +58,7 @@
     /**
        Sets the user data.
        @hide  */
+    @UnsupportedAppUsage
     public void setUserData(int userData) {
         this.mUserData = userData;
     }
@@ -72,6 +75,7 @@
      * Sets the status code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setStatus(StatusCode status) {
         this.mStatus = status;
     }
@@ -80,6 +84,7 @@
      * Constructor for the OptionsCmdStatus class.
      * @hide
      */
+    @UnsupportedAppUsage
     public OptionsCmdStatus() {
         mStatus = new StatusCode();
         mCapInfo = new CapInfo();
@@ -96,6 +101,7 @@
      * Sets the CapInfo
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCapInfo(CapInfo capInfo) {
         this.mCapInfo = capInfo;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java b/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
index 0b9dd21..c5f333d 100644
--- a/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
+++ b/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.options;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -41,6 +42,7 @@
      * Sets the Options command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(OptionsCmdId cmdId) {
         this.mCmdId = cmdId;
     }
@@ -57,6 +59,7 @@
      * Sets the request ID
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRequestId(int requestId) {
         this.mRequestId = requestId;
     }
@@ -73,6 +76,7 @@
      * Sets the SIP response code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSipResponseCode(int sipResponseCode) {
         this.mSipResponseCode = sipResponseCode;
     }
@@ -89,6 +93,7 @@
      * Sets the SIP response code reason phrase.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setReasonPhrase(String reasonPhrase) {
         this.mReasonPhrase = reasonPhrase;
     }
@@ -105,6 +110,7 @@
      * Sets the SIP retryAfter sec value
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRetryAfter(int retryAfter) {
         this.mRetryAfter = retryAfter;
     }
@@ -113,6 +119,7 @@
      * Constructor for the OptionsSipResponse class.
      * @hide
      */
+    @UnsupportedAppUsage
     public OptionsSipResponse() {
         mCmdId = new OptionsCmdId();
     };
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java
index 60fc226..745df5b 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java
@@ -18,6 +18,7 @@
 
 import com.android.ims.internal.uce.common.CapInfo;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -26,12 +27,14 @@
 public class PresCapInfo implements Parcelable {
 
     private CapInfo mCapInfo;
+    @UnsupportedAppUsage
     private String mContactUri = "";
 
     /**
      * Gets the UCE capability information.
      * @hide
      */
+    @UnsupportedAppUsage
     public CapInfo getCapInfo() {
         return mCapInfo;
     }
@@ -48,6 +51,7 @@
      *  Gets the contact URI.
      *  @hide
      */
+    @UnsupportedAppUsage
     public String getContactUri() {
         return mContactUri;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java b/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java
index 395f3e8..41020ec 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -57,6 +58,7 @@
      * Sets the command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(int nCmdId) {
         this.mCmdId = nCmdId;
     }
@@ -66,6 +68,7 @@
     * Constructor for the PresCmdId class.
     * @hide
     */
+    @UnsupportedAppUsage
     public PresCmdId(){};
 
 
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java b/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
index a5b498b..ff8069c 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
@@ -18,6 +18,7 @@
 
 import com.android.ims.internal.uce.common.StatusCode;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -42,6 +43,7 @@
      * Sets the command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(PresCmdId cmdId) {
         this.mCmdId = cmdId;
     }
@@ -58,6 +60,7 @@
      * Sets the user data.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUserData(int userData) {
         this.mUserData = userData;
     }
@@ -73,6 +76,7 @@
      * Sets the status code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setStatus(StatusCode status) {
         this.mStatus = status;
     }
@@ -89,6 +93,7 @@
      * Sets the request ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRequestId(int requestId) {
         this.mRequestId = requestId;
     }
@@ -97,6 +102,7 @@
      * Constructor for the PresCmdStatus class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresCmdStatus() {
         mStatus = new StatusCode();
     };
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java b/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
index 3e8531a..87193e3 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -65,6 +66,7 @@
      * Sets the publish trigger type.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPublishTrigeerType(int nPublishTriggerType) {
         this.mPublishTriggerType = nPublishTriggerType;
     }
@@ -74,6 +76,7 @@
      * Constructor for the PresPublishTriggerType class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresPublishTriggerType(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java
index a073a23..237c999 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -38,6 +39,7 @@
      * Sets the Presence service resource instance information.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setInstanceInfo(PresResInstanceInfo instanceInfo) {
         this.mInstanceInfo = instanceInfo;
     }
@@ -54,6 +56,7 @@
      * Sets the resource URI.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setResUri(String resUri) {
         this.mResUri = resUri;
     }
@@ -70,6 +73,7 @@
      * Sets the display name.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDisplayName(String displayName) {
         this.mDisplayName = displayName;
     }
@@ -79,6 +83,7 @@
     * Constructor for the PresResInstanceInfo class.
     * @hide
     */
+    @UnsupportedAppUsage
     public PresResInfo() {
         mInstanceInfo = new PresResInstanceInfo();
     };
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
index 430cff1..29699ea 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import java.util.Arrays;
@@ -59,6 +60,7 @@
      * Sets the resource instance state.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setResInstanceState(int nResInstanceState) {
         this.mResInstanceState = nResInstanceState;
     }
@@ -75,6 +77,7 @@
      * Sets the resource ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setResId(String resourceId) {
         this.mId = resourceId;
     }
@@ -93,6 +96,7 @@
      * code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setReason(String reason) {
         this.mReason = reason;
     }
@@ -109,6 +113,7 @@
      * Sets the entity URI.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPresentityUri(String presentityUri) {
         this.mPresentityUri = presentityUri;
     }
@@ -125,6 +130,7 @@
      * Sets the tuple information.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setTupleInfo(PresTupleInfo[] tupleInfo) {
         this.mTupleInfoArray = new PresTupleInfo[tupleInfo.length];
         this.mTupleInfoArray = tupleInfo;
@@ -135,6 +141,7 @@
     * Constructor for the PresResInstanceInfo class.
     * @hide
     */
+    @UnsupportedAppUsage
     public PresResInstanceInfo(){
 
     };
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
index 987dd77..ab46e4b 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -60,6 +61,7 @@
      * Sets the URI.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUri(String uri) {
         this.mUri = uri;
     }
@@ -76,6 +78,7 @@
      * Sets the version.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setVersion(int version) {
         this.mVersion = version;
     }
@@ -92,6 +95,7 @@
      * Sets the RLMI state.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setFullState(boolean fullState) {
         this.mFullState = fullState;
     }
@@ -108,6 +112,7 @@
      * Sets the RLMI list name.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setListName(String listName) {
         this.mListName = listName;
     }
@@ -124,6 +129,7 @@
      * Sets the subscription request ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRequestId(int requestId) {
         this.mRequestId = requestId;
     }
@@ -140,6 +146,7 @@
      * Sets the presence subscription state.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPresSubscriptionState(PresSubscriptionState presSubscriptionState) {
         this.mPresSubscriptionState = presSubscriptionState;
     }
@@ -156,6 +163,7 @@
      * Sets the presence subscription expiration time.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSubscriptionExpireTime(int subscriptionExpireTime) {
         this.mSubscriptionExpireTime = subscriptionExpireTime;
     }
@@ -172,6 +180,7 @@
      * Sets the presence subscription terminated reason.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSubscriptionTerminatedReason(String subscriptionTerminatedReason) {
         this.mSubscriptionTerminatedReason = subscriptionTerminatedReason;
     }
@@ -180,6 +189,7 @@
      * Constructor for the PresTupleInfo class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresRlmiInfo(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
index f7b7264..83ba722 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -45,6 +46,7 @@
      * Gets the media type.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getMediaType() {
         return mMediaCap;
     }
@@ -61,6 +63,7 @@
      * Gets the service ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getServiceId() {
         return mServiceID;
     }
@@ -76,6 +79,7 @@
      * Gets the service description.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getServiceDesc() {
         return mServiceDesc;
     }
@@ -92,6 +96,7 @@
      * Gets the service version.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getServiceVer() {
         return mServiceVer;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java b/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java
index 456b443..5e42592 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,6 +33,7 @@
      * Gets the Presence command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresCmdId getCmdId() {
         return mCmdId;
     }
@@ -40,6 +42,7 @@
      * Sets the Presence command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(PresCmdId cmdId) {
         this.mCmdId = cmdId;
     }
@@ -48,6 +51,7 @@
      * Gets the request ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getRequestId() {
         return mRequestId;
     }
@@ -56,6 +60,7 @@
      * Sets the request ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRequestId(int requestId) {
         this.mRequestId = requestId;
     }
@@ -64,6 +69,7 @@
      * Gets the SIP response code.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getSipResponseCode() {
         return mSipResponseCode;
     }
@@ -72,6 +78,7 @@
      * Sets the SIP response code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSipResponseCode(int sipResponseCode) {
         this.mSipResponseCode = sipResponseCode;
     }
@@ -82,6 +89,7 @@
      * code.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getReasonPhrase() {
         return mReasonPhrase;
     }
@@ -90,6 +98,7 @@
      * Sets the SIP response code reason phrase.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setReasonPhrase(String reasonPhrase) {
         this.mReasonPhrase = reasonPhrase;
     }
@@ -98,6 +107,7 @@
      * Gets the SIP retryAfter sec value.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getRetryAfter() {
         return mRetryAfter;
     }
@@ -106,6 +116,7 @@
      * Sets the SIP retryAfter sec value
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRetryAfter(int retryAfter) {
         this.mRetryAfter = retryAfter;
     }
@@ -114,6 +125,7 @@
      * Constructor for the PresSipResponse class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresSipResponse(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java b/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
index 872bc23..bee928c 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -77,6 +78,7 @@
      * Constructor for the PresSubscriptionState class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresSubscriptionState() {    };
 
     /**
@@ -92,6 +94,7 @@
      * Sets the Presence subscription state.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPresSubscriptionState(int nPresSubscriptionState) {
         this.mPresSubscriptionState = nPresSubscriptionState;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
index e1867c5..7a47786 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -39,6 +40,7 @@
      * Sets the feature tag.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setFeatureTag(String featureTag) {
         this.mFeatureTag = featureTag;
     }
@@ -54,6 +56,7 @@
      * Sets the contact URI.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setContactUri(String contactUri) {
         this.mContactUri = contactUri;
     }
@@ -70,6 +73,7 @@
      * Sets the timestamp.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setTimestamp(String timestamp) {
         this.mTimestamp = timestamp;
     }
@@ -78,6 +82,7 @@
      * Constructor for the PresTupleInfo class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresTupleInfo(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 0d315e5..1ebb697 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -21,6 +21,7 @@
 import android.telephony.SignalStrength;
 import android.telephony.CellInfo;
 import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
@@ -50,5 +51,6 @@
     void onOemHookRawEvent(in byte[] rawData);
     void onCarrierNetworkChange(in boolean active);
     void onUserMobileDataStateChanged(in boolean enabled);
+    void onPhoneCapabilityChanged(in PhoneCapability capability);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ISmsBaseImpl.java b/telephony/java/com/android/internal/telephony/ISmsBaseImpl.java
deleted file mode 100644
index cc1d105..0000000
--- a/telephony/java/com/android/internal/telephony/ISmsBaseImpl.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/* Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.internal.telephony;
-
-import android.app.PendingIntent;
-import android.net.Uri;
-import java.lang.UnsupportedOperationException;
-import java.util.List;
-
-public class ISmsBaseImpl extends ISms.Stub {
-
-    @Override
-    public List<SmsRawData> getAllMessagesFromIccEfForSubscriber(int subId, String callingPkg) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean updateMessageOnIccEfForSubscriber(int subId, String callingPkg,
-             int messageIndex, int newStatus, byte[] pdu) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean copyMessageToIccEfForSubscriber(int subId, String callingPkg, int status,
-            byte[] pdu, byte[] smsc) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendDataForSubscriber(int subId, String callingPkg, String destAddr,
-            String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendDataForSubscriberWithSelfPermissions(int subId, String callingPkg,
-            String destAddr, String scAddr, int destPort, byte[] data,
-            PendingIntent sentIntent, PendingIntent deliveryIntent)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendTextForSubscriber(int subId, String callingPkg, String destAddr,
-            String scAddr, String text, PendingIntent sentIntent,
-            PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendTextForSubscriberWithSelfPermissions(int subId, String callingPkg,
-            String destAddr, String scAddr, String text, PendingIntent sentIntent,
-            PendingIntent deliveryIntent, boolean persistMessage)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendTextForSubscriberWithOptions(int subId, String callingPkg, String destAddr,
-            String scAddr, String text, PendingIntent sentIntent,
-            PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp,
-            int priority, boolean expectMore, int validityPeriod)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void injectSmsPduForSubscriber(
-            int subId, byte[] pdu, String format, PendingIntent receivedIntent)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendMultipartTextForSubscriber(int subId, String callingPkg,
-            String destinationAddress, String scAddress,
-            List<String> parts, List<PendingIntent> sentIntents,
-            List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendMultipartTextForSubscriberWithOptions(int subId, String callingPkg,
-            String destinationAddress, String scAddress,
-            List<String> parts, List<PendingIntent> sentIntents,
-            List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp,
-            int priority, boolean expectMore, int validityPeriod)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean enableCellBroadcastForSubscriber(int subId, int messageIdentifier, int ranType)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean disableCellBroadcastForSubscriber(int subId, int messageIdentifier, int ranType)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean enableCellBroadcastRangeForSubscriber(int subId, int startMessageId,
-            int endMessageId, int ranType) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean disableCellBroadcastRangeForSubscriber(int subId, int startMessageId,
-            int endMessageId, int ranType) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getPremiumSmsPermission(String packageName) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getPremiumSmsPermissionForSubscriber(int subId, String packageName)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setPremiumSmsPermission(String packageName, int permission) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setPremiumSmsPermissionForSubscriber(int subId, String packageName,
-            int permission) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean isImsSmsSupportedForSubscriber(int subId) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean isSmsSimPickActivityNeeded(int subId) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getPreferredSmsSubscription() throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String getImsSmsFormatForSubscriber(int subId) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean isSMSPromptEnabled() throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendStoredText(int subId, String callingPkg, Uri messageUri, String scAddress,
-            PendingIntent sentIntent, PendingIntent deliveryIntent)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendStoredMultipartText(int subId, String callingPkg, Uri messageUri,
-                String scAddress, List<PendingIntent> sentIntents,
-                List<PendingIntent> deliveryIntents) throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent)
-            throws UnsupportedOperationException {
-        throw new UnsupportedOperationException();
-    }
-}
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
new file mode 100644
index 0000000..1cdf44d
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.app.PendingIntent;
+import android.net.Uri;
+
+import java.util.List;
+
+/**
+ * Base class for ISms that facilitates forward compatibility with new features.
+ */
+public class ISmsImplBase extends ISms.Stub {
+
+    @Override
+    public List<SmsRawData> getAllMessagesFromIccEfForSubscriber(int subId, String callingPkg) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean updateMessageOnIccEfForSubscriber(int subId, String callingPkg, int messageIndex,
+            int newStatus, byte[] pdu) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean copyMessageToIccEfForSubscriber(int subId, String callingPkg, int status,
+            byte[] pdu, byte[] smsc) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendDataForSubscriber(int subId, String callingPkg, String destAddr,
+            String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendDataForSubscriberWithSelfPermissions(int subId, String callingPkg,
+            String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendTextForSubscriber(int subId, String callingPkg, String destAddr,
+            String scAddr, String text, PendingIntent sentIntent,
+            PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendTextForSubscriberWithSelfPermissions(int subId, String callingPkg,
+            String destAddr, String scAddr, String text, PendingIntent sentIntent,
+            PendingIntent deliveryIntent, boolean persistMessage) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendTextForSubscriberWithOptions(int subId, String callingPkg, String destAddr,
+            String scAddr, String text, PendingIntent sentIntent,
+            PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp,
+            int priority, boolean expectMore, int validityPeriod) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void injectSmsPduForSubscriber(
+            int subId, byte[] pdu, String format, PendingIntent receivedIntent) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendMultipartTextForSubscriber(int subId, String callingPkg,
+            String destinationAddress, String scAddress,
+            List<String> parts, List<PendingIntent> sentIntents,
+            List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendMultipartTextForSubscriberWithOptions(int subId, String callingPkg,
+            String destinationAddress, String scAddress,
+            List<String> parts, List<PendingIntent> sentIntents,
+            List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp,
+            int priority, boolean expectMore, int validityPeriod) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean enableCellBroadcastForSubscriber(int subId, int messageIdentifier, int ranType) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean disableCellBroadcastForSubscriber(int subId, int messageIdentifier,
+            int ranType) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean enableCellBroadcastRangeForSubscriber(int subId, int startMessageId,
+            int endMessageId, int ranType) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean disableCellBroadcastRangeForSubscriber(int subId, int startMessageId,
+            int endMessageId, int ranType) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getPremiumSmsPermission(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getPremiumSmsPermissionForSubscriber(int subId, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setPremiumSmsPermission(String packageName, int permission) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setPremiumSmsPermissionForSubscriber(int subId, String packageName,
+            int permission) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isImsSmsSupportedForSubscriber(int subId) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isSmsSimPickActivityNeeded(int subId) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getPreferredSmsSubscription() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getImsSmsFormatForSubscriber(int subId) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isSMSPromptEnabled() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendStoredText(int subId, String callingPkg, Uri messageUri, String scAddress,
+            PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendStoredMultipartText(int subId, String callingPkg, Uri messageUri,
+            String scAddress, List<PendingIntent> sentIntents,
+            List<PendingIntent> deliveryIntents) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent) {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 5e015e0..6521f0b 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -156,6 +156,42 @@
      */
     int setDataRoaming(int roaming, int subId);
 
+    /**
+     * Switch to a certain subscription
+     *
+     * @param opportunistic whether it’s opportunistic subscription.
+     * @param subId the unique SubscriptionInfo index in database
+     * @return the number of records updated
+     */
+    int setOpportunistic(boolean opportunistic, int subId);
+
+    /**
+     * Set parent subId by simInfo index
+     *
+     * @param parentSubId: subId of its parent subscription.
+     * @param subId the unique SubscriptionInfo index in database
+     * @return the number of records updated
+     */
+    int setParentSubId(int parentSubId, int subId);
+
+    /**
+     * Set preferred default data.
+     * Set on which slot default data will be on.
+     *
+     * @param slotId which slot is preferred to for cellular data.
+     * @hide
+     *
+     */
+    int setPreferredData(int slotId);
+
+    /**
+     * Get User downloaded Profiles.
+     *
+     *  Provide all available user downloaded profile on the phone.
+     *  @param slotId on which phone the switch will operate on
+     */
+    List<SubscriptionInfo> getOpportunisticSubscriptions(int slotId, String callingPackage);
+
     int getSlotIndex(int subId);
 
     int[] getSubId(int slotIndex);
@@ -186,7 +222,7 @@
 
     int[] getActiveSubIdList();
 
-    void setSubscriptionProperty(int subId, String propKey, String propValue);
+    int setSubscriptionProperty(int subId, String propKey, String propValue);
 
     String getSubscriptionProperty(int subId, String propKey, String callingPackage);
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 84a18b4..c59a739 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -390,7 +390,7 @@
     /**
      * Returns the neighboring cell information of the device.
      */
-    List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);
+    List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg, int targetSdk);
 
      int getCallState();
 
@@ -1195,6 +1195,13 @@
     String getImeiForSlot(int slotIndex, String callingPackage);
 
     /**
+     * Returns the Type Allocation Code from the IMEI for the given slot.
+     *
+     * @param slotIndex - Which slot to retrieve the Type Allocation Code from.
+     */
+    String getTypeAllocationCodeForSlot(int slotIndex);
+
+    /**
      * Returns the MEID for the given slot.
      *
      * @param slotIndex - device slot.
@@ -1205,6 +1212,13 @@
     String getMeidForSlot(int slotIndex, String callingPackage);
 
     /**
+     * Returns the Manufacturer Code from the MEID for the given slot.
+     *
+     * @param slotIndex - Which slot to retrieve the Manufacturer Code from.
+     */
+    String getManufacturerCodeForSlot(int slotIndex);
+
+    /**
      * Returns the device software version.
      *
      * @param slotIndex - device slot.
@@ -1517,4 +1531,10 @@
      * @hide
      */
     void refreshUiccProfile(int subId);
+
+    /**
+     * How many modems can have simultaneous data connections.
+     * @hide
+     */
+    int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 0127db9..e0e1a7b 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -21,6 +21,7 @@
 import android.net.NetworkCapabilities;
 import android.os.Bundle;
 import android.telephony.CellInfo;
+import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -74,4 +75,5 @@
     void notifySubscriptionInfoChanged();
     void notifyCarrierNetworkChange(in boolean active);
     void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state);
+    void notifyPhoneCapabilityChanged(in PhoneCapability capability);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 49fbd8f..3a26350 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -16,15 +16,6 @@
 
 package com.android.internal.telephony;
 
-/**
- * TODO: This should probably not be an interface see
- * http://www.javaworld.com/javaworld/javaqa/2001-06/01-qa-0608-constants.html and google with
- * http://www.google.com/search?q=interface+constants&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a
- *
- * Also they should all probably be static final.
- */
-
-import android.os.SystemProperties;
 import android.telephony.TelephonyManager;
 
 /**
@@ -231,13 +222,6 @@
     int LCE_STOPPED = 0;
     int LCE_ACTIVE = 1;
 
-/*
-cat include/telephony/ril.h | \
-   egrep '^#define' | \
-   sed -re 's/^#define +([^ ]+)* +([^ ]+)/    int \1 = \2;/' \
-   >>java/android/com.android.internal.telephony/gsm/RILConstants.java
-*/
-
     /**
      * No restriction at all including voice/SMS/USSD/SS/AV64
      * and packet data.
@@ -272,6 +256,18 @@
     public static final int DATA_PROFILE_OEM_BASE  = 1000;
     public static final int DATA_PROFILE_INVALID   = 0xFFFFFFFF;
 
+    /**
+     * The request/response/unsol message IDs below match RIL.h through Android O-MR1.
+     *
+     * RIL.h is at hardware/ril/include/telephony.ril.h; RIL support is deprecated and may
+     * be removed in the future.
+     *
+     * Messages defined after O-MR1 have no corresponding definition in RIL.h.
+     * P-and-later messages start at RIL_REQUEST_HAL_NON_RIL_BASE and
+     * RIL_UNSOL_HAL_NON_RIL_BASE.
+     */
+
+    /* Requests begin */
     int RIL_REQUEST_GET_SIM_STATUS = 1;
     int RIL_REQUEST_ENTER_SIM_PIN = 2;
     int RIL_REQUEST_ENTER_SIM_PUK = 3;
@@ -415,15 +411,20 @@
     int RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION = 141;
     int RIL_REQUEST_START_NETWORK_SCAN = 142;
     int RIL_REQUEST_STOP_NETWORK_SCAN = 143;
-    int RIL_REQUEST_GET_SLOT_STATUS = 144;
-    int RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING = 145;
-    int RIL_REQUEST_START_KEEPALIVE = 146;
-    int RIL_REQUEST_STOP_KEEPALIVE = 147;
-    int RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA = 148;
-    int RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA = 149;
+    int RIL_REQUEST_START_KEEPALIVE = 144;
+    int RIL_REQUEST_STOP_KEEPALIVE = 145;
 
+    /* The following requests are not defined in RIL.h */
+    int RIL_REQUEST_HAL_NON_RIL_BASE = 200;
+    int RIL_REQUEST_GET_SLOT_STATUS = 200;
+    int RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING = 201;
+    int RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA = 202;
+    int RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA = 203;
+
+    /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
 
+    /* Unsols begin */
     int RIL_UNSOL_RESPONSE_BASE = 1000;
     int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
     int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
@@ -475,7 +476,10 @@
     int RIL_UNSOL_MODEM_RESTART = 1047;
     int RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION = 1048;
     int RIL_UNSOL_NETWORK_SCAN_RESULT = 1049;
-    int RIL_UNSOL_ICC_SLOT_STATUS = 1050;
-    int RIL_UNSOL_KEEPALIVE_STATUS = 1051;
-    int RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG = 1052;
+    int RIL_UNSOL_KEEPALIVE_STATUS = 1050;
+
+    /* The following unsols are not defined in RIL.h */
+    int RIL_UNSOL_HAL_NON_RIL_BASE = 1100;
+    int RIL_UNSOL_ICC_SLOT_STATUS = 1100;
+    int RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG = 1101;
 }
diff --git a/telephony/java/com/android/internal/telephony/SmsConstants.java b/telephony/java/com/android/internal/telephony/SmsConstants.java
index 2449108..0aba468 100644
--- a/telephony/java/com/android/internal/telephony/SmsConstants.java
+++ b/telephony/java/com/android/internal/telephony/SmsConstants.java
@@ -58,7 +58,11 @@
      * See TS 23.038.
      */
     public enum MessageClass{
-        UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
+        UNKNOWN,
+        CLASS_0,
+        CLASS_1,
+        CLASS_2,
+        CLASS_3;
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 51369d0..5ecb43e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -15,7 +15,6 @@
  */
 
 package com.android.internal.telephony;
-import android.content.Intent;
 
 import android.content.Intent;
 import android.telephony.SubscriptionManager;
diff --git a/test-base/Android.bp b/test-base/Android.bp
index a0e3985..0b8a02a 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -19,7 +19,7 @@
 // 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.
-java_library {
+java_sdk_library {
     name: "android.test.base",
 
     srcs: ["src/**/*.java"],
@@ -28,11 +28,38 @@
       javacflags: ["-Xep:DepAnn:ERROR"],
     },
 
+    hostdex: true,
+
+    api_packages: [
+        "android.test",
+        "android.test.suitebuilder.annotation",
+        "com.android.internal.util",
+        "junit.framework",
+    ],
+
+    droiddoc_options: ["stubsourceonly"],
+    compile_dex: true,
+}
+
+// Build the android.test.base_static library
+// ==========================================
+// This is only intended for inclusion in the android.test.runner-minus-junit,
+// robolectric_android-all-stub and repackaged.android.test.* libraries.
+// Must not be used elewhere.
+java_library_static {
+    name: "android.test.base_static",
+    installable: false,
+
+    srcs: ["src/**/*.java"],
+
+    errorprone: {
+        javacflags: ["-Xep:DepAnn:ERROR"],
+    },
+
     // Needs to be consistent with the repackaged version of this make target.
     java_version: "1.8",
 
     sdk_version: "current",
-    hostdex: true,
 }
 
 // Build the legacy-test library
@@ -42,9 +69,10 @@
 // Also contains the com.android.internal.util.Predicate[s] classes.
 java_library {
     name: "legacy-test",
+    installable: true,
 
     sdk_version: "current",
-    static_libs: ["android.test.base"],
+    static_libs: ["android.test.base_static"],
 }
 
 // Build the repackaged.android.test.base library
@@ -55,7 +83,7 @@
     name: "repackaged.android.test.base",
 
     sdk_version: "current",
-    static_libs: ["android.test.base"],
+    static_libs: ["android.test.base_static"],
 
     jarjar_rules: "jarjar-rules.txt",
     // Pin java_version until jarjar is certified to support later versions. http://b/72703434
@@ -82,37 +110,3 @@
     ],
 }
 
-droiddoc {
-    name: "android-test-base-api-stubs-gen-docs",
-    srcs: [
-        "src/**/*.java",
-    ],
-    custom_template: "droiddoc-templates-sdk",
-    installable: false,
-    args: "-stubpackages android.test:" +
-          "android.test.suitebuilder.annotation:" +
-          "com.android.internal.util:" +
-          "junit.framework -stubsourceonly -nodocs",
-    sdk_version: "current",
-    api_tag_name: "ANDROID_TEST_BASE",
-    api_filename: "android-test-base-api.txt",
-    removed_api_filename: "android-test-base-removed.txt",
-}
-
-// Build the android.test.base.stubs library
-// =========================================
-java_library_static {
-    name: "android.test.base.stubs",
-    srcs: [
-        ":android-test-base-api-stubs-gen-docs",
-    ],
-    product_variables: {
-        pdk: {
-            enabled: false,
-        },
-        unbundled_build: {
-            enabled: false,
-        },
-    },
-    sdk_version: "current",
-}
diff --git a/test-base/Android.mk b/test-base/Android.mk
index baf5726..a9d30cf 100644
--- a/test-base/Android.mk
+++ b/test-base/Android.mk
@@ -16,50 +16,6 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
-ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
-
-ANDROID_TEST_BASE_API_FILE := $(LOCAL_PATH)/api/android-test-base-current.txt
-ANDROID_TEST_BASE_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-base-removed.txt
-
-full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.test.base.stubs,,COMMON)/classes.jar
-# Archive a copy of the classes.jar in SDK build.
-$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.base.stubs.jar)
-
-# Check that the android.test.base.stubs library has not changed
-# ==============================================================
-
-# Check that the API we're building hasn't changed from the not-yet-released
-# SDK version.
-$(eval $(call check-api, \
-    check-android-test-base-api-current, \
-    $(ANDROID_TEST_BASE_API_FILE), \
-    $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_API_FILE), \
-    $(ANDROID_TEST_BASE_REMOVED_API_FILE), \
-    $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_REMOVED_API_FILE), \
-    -error 2 -error 3 -error 4 -error 5 -error 6 \
-    -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
-    -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
-    -error 25 -error 26 -error 27, \
-    cat $(LOCAL_PATH)/api/apicheck_msg_android_test_base.txt, \
-    check-android-test-base-api, \
-    $(OUT_DOCS)/android-test-base-api-stubs-gen-docs-stubs.srcjar \
-    ))
-
-.PHONY: check-android-test-base-api
-checkapi: check-android-test-base-api
-
-.PHONY: update-android-test-base-api
-update-api: update-android-test-base-api
-
-update-android-test-base-api: $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_API_FILE) | $(ACP)
-	@echo Copying current.txt
-	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_API_FILE) $(ANDROID_TEST_BASE_API_FILE)
-	@echo Copying removed.txt
-	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_REMOVED_API_FILE) $(ANDROID_TEST_BASE_REMOVED_API_FILE)
-
-endif  # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
-
 ifeq ($(HOST_OS),linux)
 # Build the legacy-performance-test-hostdex library
 # =================================================
diff --git a/test-base/api/apicheck_msg_android_test_base.txt b/test-base/api/apicheck_msg_android_test_base.txt
deleted file mode 100644
index 144aecc..0000000
--- a/test-base/api/apicheck_msg_android_test_base.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-******************************
-You have tried to change the API from what has been previously approved.
-
-To make these errors go away, you have two choices:
-   1) You can add "@hide" javadoc comments to the methods, etc. listed in the
-      errors above.
-
-   2) You can update android-test-base-current.txt by executing the following command:
-         make update-android-test-base-api
-
-      To submit the revised android-test-base-current.txt to the main Android repository,
-      you will need approval.
-******************************
-
-
-
diff --git a/test-base/api/android-test-base-current.txt b/test-base/api/current.txt
similarity index 100%
rename from test-base/api/android-test-base-current.txt
rename to test-base/api/current.txt
diff --git a/test-base/api/android-test-base-removed.txt b/test-base/api/removed.txt
similarity index 100%
copy from test-base/api/android-test-base-removed.txt
copy to test-base/api/removed.txt
diff --git a/test-base/api/android-test-base-removed.txt b/test-base/api/system-current.txt
similarity index 100%
copy from test-base/api/android-test-base-removed.txt
copy to test-base/api/system-current.txt
diff --git a/test-base/api/android-test-base-removed.txt b/test-base/api/system-removed.txt
similarity index 100%
rename from test-base/api/android-test-base-removed.txt
rename to test-base/api/system-removed.txt
diff --git a/test-base/api/android-test-base-removed.txt b/test-base/api/test-current.txt
similarity index 100%
copy from test-base/api/android-test-base-removed.txt
copy to test-base/api/test-current.txt
diff --git a/test-base/api/android-test-base-removed.txt b/test-base/api/test-removed.txt
similarity index 100%
copy from test-base/api/android-test-base-removed.txt
copy to test-base/api/test-removed.txt
diff --git a/test-legacy/Android.bp b/test-legacy/Android.bp
index d2af8a9..833c714 100644
--- a/test-legacy/Android.bp
+++ b/test-legacy/Android.bp
@@ -25,7 +25,7 @@
     static_libs: [
         "android.test.base-minus-junit",
         "android.test.runner-minus-junit",
-        "android.test.mock",
+        "android.test.mock.impl",
     ],
 
     no_framework_libs: true,
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 51fa86b..5eba017 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -16,92 +16,15 @@
 
 // Build the android.test.mock library
 // ===================================
-java_library {
+java_sdk_library {
     name: "android.test.mock",
 
-    java_version: "1.8",
     srcs: ["src/**/*.java"],
 
-    no_framework_libs: true,
-    libs: [
-        "framework",
+    api_packages: [
+        "android.test.mock",
     ],
-}
 
-doc_defaults {
-    name:"android.test.mock.docs-defaults",
-    srcs: ["src/android/test/mock/**/*.java"],
-
-    // Includes the main framework source to ensure that doclava has access to the
-    // visibility information for the base classes of the mock classes. Without it
-    // otherwise hidden methods could be visible.
-    srcs_lib: "framework",
-    srcs_lib_whitelist_dirs: ["core/java"],
     srcs_lib_whitelist_pkgs: ["android"],
-    libs: [
-        "core-oj",
-        "core-libart",
-        "framework",
-        "conscrypt",
-        "okhttp",
-        "bouncycastle",
-        "ext",
-    ],
-    local_sourcepaths: ["src/android/test/mock"],
-    custom_template: "droiddoc-templates-sdk",
-    installable: false,
-}
-
-android_test_mock_docs_args =
-    "-hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128 " +
-    "-stubpackages android.test.mock " +
-    "-nodocs "
-
-droiddoc {
-    name: "android.test.mock.docs",
-    defaults: ["android.test.mock.docs-defaults"],
-
-    api_tag_name: "ANDROID_TEST_MOCK",
-    api_filename: "api/android-test-mock-current.txt",
-    removed_api_filename: "api/android-test-mock-removed.txt",
-
-    args: android_test_mock_docs_args,
-}
-
-droiddoc {
-    name: "android.test.mock.docs-system",
-    defaults: ["android.test.mock.docs-defaults"],
-
-    api_tag_name: "ANDROID_TEST_MOCK_SYSTEM",
-    api_filename: "api/android-test-mock-system-current.txt",
-    removed_api_filename: "api/android-test-mock-system-removed.txt",
-
-    args: android_test_mock_docs_args +
-        "-showAnnotation android.annotation.SystemApi ",
-}
-
-java_library_static {
-    name: "android.test.mock.stubs",
-    srcs: [":android.test.mock.docs"],
-    sdk_version: "current",
-    product_variables: {
-        unbundled_build: {
-            // Unbundled apps will use the prebuilt one
-            // prebuilts/sdk/current
-            enabled: false,
-        },
-    },
-}
-
-java_library_static {
-    name: "android.test.mock.stubs-system",
-    srcs: [":android.test.mock.docs-system"],
-    sdk_version: "system_current",
-    product_variables: {
-        unbundled_build: {
-            // Unbundled apps will use the prebuilt one
-            // prebuilts/sdk/system_current
-            enabled: false,
-        },
-    },
+    compile_dex: true,
 }
diff --git a/test-mock/Android.mk b/test-mock/Android.mk
deleted file mode 100644
index 73a7340..0000000
--- a/test-mock/Android.mk
+++ /dev/null
@@ -1,93 +0,0 @@
-#
-# Copyright (C) 2008 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-# Archive a copy of the classes.jar in SDK build.
-full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.test.mock.stubs,,COMMON)/classes.jar
-$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.stubs.jar)
-
-# Check that the android.test.mock.stubs library has not changed
-# ==============================================================
-ANDROID_TEST_MOCK_API_FILE := $(LOCAL_PATH)/api/android-test-mock-current.txt
-ANDROID_TEST_MOCK_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-mock-removed.txt
-
-# Check that the API we're building hasn't changed from the not-yet-released
-# SDK version.
-$(eval $(call check-api, \
-    check-android-test-mock-api-current, \
-    $(ANDROID_TEST_MOCK_API_FILE), \
-    $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_API_FILE), \
-    $(ANDROID_TEST_MOCK_REMOVED_API_FILE), \
-    $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_REMOVED_API_FILE), \
-    -error 2 -error 3 -error 4 -error 5 -error 6 \
-    -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
-    -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
-    -error 25 -error 26 -error 27, \
-    cat $(LOCAL_PATH)/api/apicheck_msg_android_test_mock.txt, \
-    check-android-test-mock-api, \
-    $(OUT_DOCS)/android.test.mock.docs-stubs.srcjar \
-    ))
-
-.PHONY: check-android-test-mock-api
-checkapi: check-android-test-mock-api
-
-.PHONY: update-android-test-mock-api
-update-api: update-android-test-mock-api
-
-update-android-test-mock-api: $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_API_FILE) | $(ACP)
-	@echo Copying current.txt
-	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_API_FILE) $(ANDROID_TEST_MOCK_API_FILE)
-	@echo Copying removed.txt
-	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_REMOVED_API_FILE) $(ANDROID_TEST_MOCK_REMOVED_API_FILE)
-
-# Archive a copy of the classes.jar in SDK build.
-full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.test.mock.stubs-system,,COMMON)/classes.jar
-$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.stubs_system.jar)
-
-# Check that the android.test.mock.stubs-system library has not changed
-# =====================================================================
-ANDROID_TEST_MOCK_SYSTEM_API_FILE := $(LOCAL_PATH)/api/android-test-mock-system-current.txt
-ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-mock-system-removed.txt
-
-# Check that the API we're building hasn't changed from the not-yet-released
-# SDK version.
-$(eval $(call check-api, \
-    check-android-test-mock-system-api-current, \
-    $(ANDROID_TEST_MOCK_SYSTEM_API_FILE), \
-    $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_API_FILE), \
-    $(ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE), \
-    $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE), \
-    -error 2 -error 3 -error 4 -error 5 -error 6 \
-    -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
-    -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
-    -error 25 -error 26 -error 27, \
-    cat $(LOCAL_PATH)/api/apicheck_msg_android_test_mock-system.txt, \
-    check-android-test-mock-system-api, \
-    $(OUT_DOCS)/android.test.mock.docs-system-stubs.srcjar \
-    ))
-
-.PHONY: check-android-test-mock-system-api
-checkapi: check-android-test-mock-system-api
-
-.PHONY: update-android-test-mock-system-api
-update-api: update-android-test-mock-system-api
-
-update-android-test-mock-system-api: $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_API_FILE) | $(ACP)
-	@echo Copying current.txt
-	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_API_FILE) $(ANDROID_TEST_MOCK_SYSTEM_API_FILE)
-	@echo Copying removed.txt
-	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE) $(ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE)
diff --git a/test-mock/api/android-test-mock-current.txt b/test-mock/api/android-test-mock-current.txt
deleted file mode 100644
index f3b253c..0000000
--- a/test-mock/api/android-test-mock-current.txt
+++ /dev/null
@@ -1,303 +0,0 @@
-package android.test.mock {
-
-  public deprecated class MockAccountManager {
-    method public static android.accounts.AccountManager newMockAccountManager(android.content.Context);
-  }
-
-  public deprecated class MockApplication extends android.app.Application {
-    ctor public MockApplication();
-  }
-
-  public class MockContentProvider extends android.content.ContentProvider {
-    ctor protected MockContentProvider();
-    ctor public MockContentProvider(android.content.Context);
-    ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
-    method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>);
-    method public static deprecated void attachInfoForTesting(android.content.ContentProvider, android.content.Context, android.content.pm.ProviderInfo);
-    method public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
-    method public java.lang.String getType(android.net.Uri);
-    method public android.net.Uri insert(android.net.Uri, android.content.ContentValues);
-    method public boolean onCreate();
-    method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle);
-    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
-    method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
-  }
-
-  public class MockContentResolver extends android.content.ContentResolver {
-    ctor public MockContentResolver();
-    ctor public MockContentResolver(android.content.Context);
-    method public void addProvider(java.lang.String, android.content.ContentProvider);
-  }
-
-  public class MockContext extends android.content.Context {
-    ctor public MockContext();
-    method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
-    method public int checkCallingOrSelfPermission(java.lang.String);
-    method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
-    method public int checkCallingPermission(java.lang.String);
-    method public int checkCallingUriPermission(android.net.Uri, int);
-    method public int checkPermission(java.lang.String, int, int);
-    method public int checkSelfPermission(java.lang.String);
-    method public int checkUriPermission(android.net.Uri, int, int, int);
-    method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
-    method public void clearWallpaper();
-    method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createContextForSplit(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.Context createDeviceProtectedStorageContext();
-    method public android.content.Context createDisplayContext(android.view.Display);
-    method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public java.lang.String[] databaseList();
-    method public boolean deleteDatabase(java.lang.String);
-    method public boolean deleteFile(java.lang.String);
-    method public boolean deleteSharedPreferences(java.lang.String);
-    method public void enforceCallingOrSelfPermission(java.lang.String, java.lang.String);
-    method public void enforceCallingOrSelfUriPermission(android.net.Uri, int, java.lang.String);
-    method public void enforceCallingPermission(java.lang.String, java.lang.String);
-    method public void enforceCallingUriPermission(android.net.Uri, int, java.lang.String);
-    method public void enforcePermission(java.lang.String, int, int, java.lang.String);
-    method public void enforceUriPermission(android.net.Uri, int, int, int, java.lang.String);
-    method public void enforceUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int, java.lang.String);
-    method public java.lang.String[] fileList();
-    method public android.content.Context getApplicationContext();
-    method public android.content.pm.ApplicationInfo getApplicationInfo();
-    method public android.content.res.AssetManager getAssets();
-    method public java.io.File getCacheDir();
-    method public java.lang.ClassLoader getClassLoader();
-    method public java.io.File getCodeCacheDir();
-    method public android.content.ContentResolver getContentResolver();
-    method public java.io.File getDataDir();
-    method public java.io.File getDatabasePath(java.lang.String);
-    method public java.io.File getDir(java.lang.String, int);
-    method public java.io.File getExternalCacheDir();
-    method public java.io.File[] getExternalCacheDirs();
-    method public java.io.File getExternalFilesDir(java.lang.String);
-    method public java.io.File[] getExternalFilesDirs(java.lang.String);
-    method public java.io.File[] getExternalMediaDirs();
-    method public java.io.File getFileStreamPath(java.lang.String);
-    method public java.io.File getFilesDir();
-    method public android.os.Looper getMainLooper();
-    method public java.io.File getNoBackupFilesDir();
-    method public java.io.File getObbDir();
-    method public java.io.File[] getObbDirs();
-    method public java.lang.String getPackageCodePath();
-    method public android.content.pm.PackageManager getPackageManager();
-    method public java.lang.String getPackageName();
-    method public java.lang.String getPackageResourcePath();
-    method public android.content.res.Resources getResources();
-    method public android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
-    method public java.lang.Object getSystemService(java.lang.String);
-    method public java.lang.String getSystemServiceName(java.lang.Class<?>);
-    method public android.content.res.Resources.Theme getTheme();
-    method public android.graphics.drawable.Drawable getWallpaper();
-    method public int getWallpaperDesiredMinimumHeight();
-    method public int getWallpaperDesiredMinimumWidth();
-    method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isDeviceProtectedStorage();
-    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
-    method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
-    method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
-    method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
-    method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler);
-    method public android.graphics.drawable.Drawable peekWallpaper();
-    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
-    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, int);
-    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
-    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler, int);
-    method public void removeStickyBroadcast(android.content.Intent);
-    method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
-    method public void revokeUriPermission(android.net.Uri, int);
-    method public void revokeUriPermission(java.lang.String, android.net.Uri, int);
-    method public void sendBroadcast(android.content.Intent);
-    method public void sendBroadcast(android.content.Intent, java.lang.String);
-    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
-    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
-    method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
-    method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
-    method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
-    method public void sendStickyBroadcast(android.content.Intent);
-    method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
-    method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
-    method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
-    method public void setTheme(int);
-    method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
-    method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
-    method public void startActivities(android.content.Intent[]);
-    method public void startActivities(android.content.Intent[], android.os.Bundle);
-    method public void startActivity(android.content.Intent);
-    method public void startActivity(android.content.Intent, android.os.Bundle);
-    method public android.content.ComponentName startForegroundService(android.content.Intent);
-    method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
-    method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
-    method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
-    method public android.content.ComponentName startService(android.content.Intent);
-    method public boolean stopService(android.content.Intent);
-    method public void unbindService(android.content.ServiceConnection);
-    method public void unregisterReceiver(android.content.BroadcastReceiver);
-  }
-
-  public deprecated class MockCursor implements android.database.Cursor {
-    ctor public MockCursor();
-    method public void close();
-    method public void copyStringToBuffer(int, android.database.CharArrayBuffer);
-    method public deprecated void deactivate();
-    method public byte[] getBlob(int);
-    method public int getColumnCount();
-    method public int getColumnIndex(java.lang.String);
-    method public int getColumnIndexOrThrow(java.lang.String);
-    method public java.lang.String getColumnName(int);
-    method public java.lang.String[] getColumnNames();
-    method public int getCount();
-    method public double getDouble(int);
-    method public android.os.Bundle getExtras();
-    method public float getFloat(int);
-    method public int getInt(int);
-    method public long getLong(int);
-    method public android.net.Uri getNotificationUri();
-    method public int getPosition();
-    method public short getShort(int);
-    method public java.lang.String getString(int);
-    method public int getType(int);
-    method public boolean getWantsAllOnMoveCalls();
-    method public boolean isAfterLast();
-    method public boolean isBeforeFirst();
-    method public boolean isClosed();
-    method public boolean isFirst();
-    method public boolean isLast();
-    method public boolean isNull(int);
-    method public boolean move(int);
-    method public boolean moveToFirst();
-    method public boolean moveToLast();
-    method public boolean moveToNext();
-    method public boolean moveToPosition(int);
-    method public boolean moveToPrevious();
-    method public void registerContentObserver(android.database.ContentObserver);
-    method public void registerDataSetObserver(android.database.DataSetObserver);
-    method public deprecated boolean requery();
-    method public android.os.Bundle respond(android.os.Bundle);
-    method public void setExtras(android.os.Bundle);
-    method public void setNotificationUri(android.content.ContentResolver, android.net.Uri);
-    method public void unregisterContentObserver(android.database.ContentObserver);
-    method public void unregisterDataSetObserver(android.database.DataSetObserver);
-  }
-
-  public deprecated class MockDialogInterface implements android.content.DialogInterface {
-    ctor public MockDialogInterface();
-    method public void cancel();
-    method public void dismiss();
-  }
-
-  public deprecated class MockPackageManager extends android.content.pm.PackageManager {
-    ctor public MockPackageManager();
-    method public void addPackageToPreferred(java.lang.String);
-    method public boolean addPermission(android.content.pm.PermissionInfo);
-    method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
-    method public void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
-    method public boolean canRequestPackageInstalls();
-    method public java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
-    method public int checkPermission(java.lang.String, java.lang.String);
-    method public int checkSignatures(java.lang.String, java.lang.String);
-    method public int checkSignatures(int, int);
-    method public void clearInstantAppCookie();
-    method public void clearPackagePreferredActivities(java.lang.String);
-    method public java.lang.String[] currentToCanonicalPackageNames(java.lang.String[]);
-    method public void extendVerificationTimeout(int, int, long);
-    method public android.graphics.drawable.Drawable getActivityBanner(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.graphics.drawable.Drawable getActivityBanner(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.graphics.drawable.Drawable getActivityIcon(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.graphics.drawable.Drawable getActivityIcon(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.pm.ActivityInfo getActivityInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.graphics.drawable.Drawable getActivityLogo(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.graphics.drawable.Drawable getActivityLogo(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public java.util.List<android.content.IntentFilter> getAllIntentFilters(java.lang.String);
-    method public java.util.List<android.content.pm.PermissionGroupInfo> getAllPermissionGroups(int);
-    method public android.graphics.drawable.Drawable getApplicationBanner(android.content.pm.ApplicationInfo);
-    method public android.graphics.drawable.Drawable getApplicationBanner(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public int getApplicationEnabledSetting(java.lang.String);
-    method public android.graphics.drawable.Drawable getApplicationIcon(android.content.pm.ApplicationInfo);
-    method public android.graphics.drawable.Drawable getApplicationIcon(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
-    method public android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
-    method public android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.pm.ChangedPackages getChangedPackages(int);
-    method public int getComponentEnabledSetting(android.content.ComponentName);
-    method public android.graphics.drawable.Drawable getDefaultActivityIcon();
-    method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
-    method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
-    method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
-    method public java.lang.String getInstallerPackageName(java.lang.String);
-    method public byte[] getInstantAppCookie();
-    method public int getInstantAppCookieMaxBytes();
-    method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.Intent getLaunchIntentForPackage(java.lang.String);
-    method public android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
-    method public java.lang.String getNameForUid(int);
-    method public int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public int[] getPackageGids(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.pm.PackageInstaller getPackageInstaller();
-    method public int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public java.lang.String[] getPackagesForUid(int);
-    method public java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int);
-    method public android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
-    method public java.util.List<android.content.pm.PackageInfo> getPreferredPackages(int);
-    method public android.content.pm.ProviderInfo getProviderInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.pm.ActivityInfo getReceiverInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.res.Resources getResourcesForActivity(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo);
-    method public android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
-    method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
-    method public java.lang.String[] getSystemSharedLibraryNames();
-    method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
-    method public android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
-    method public android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
-    method public java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
-    method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
-    method public boolean hasSystemFeature(java.lang.String);
-    method public boolean hasSystemFeature(java.lang.String, int);
-    method public boolean isInstantApp();
-    method public boolean isInstantApp(java.lang.String);
-    method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
-    method public boolean isSafeMode();
-    method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
-    method public java.util.List<android.content.pm.ProviderInfo> queryContentProviders(java.lang.String, int, int);
-    method public java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int);
-    method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(android.content.Intent, int);
-    method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], android.content.Intent, int);
-    method public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int);
-    method public java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
-    method public java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public void removePackageFromPreferred(java.lang.String);
-    method public void removePermission(java.lang.String);
-    method public android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
-    method public android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
-    method public android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
-    method public android.content.pm.ResolveInfo resolveServiceAsUser(android.content.Intent, int, int);
-    method public void setApplicationCategoryHint(java.lang.String, int);
-    method public void setApplicationEnabledSetting(java.lang.String, int, int);
-    method public void setComponentEnabledSetting(android.content.ComponentName, int, int);
-    method public void setInstallerPackageName(java.lang.String, java.lang.String);
-    method public void updateInstantAppCookie(byte[]);
-    method public void verifyPendingInstall(int, int);
-  }
-
-  public deprecated class MockResources extends android.content.res.Resources {
-    ctor public MockResources();
-    method public int getColor(int) throws android.content.res.Resources.NotFoundException;
-    method public android.content.res.ColorStateList getColorStateList(int) throws android.content.res.Resources.NotFoundException;
-    method public android.graphics.drawable.Drawable getDrawable(int) throws android.content.res.Resources.NotFoundException;
-    method public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics);
-  }
-
-  public deprecated class MockService {
-    method public static <T extends android.app.Service> void attachForTesting(android.app.Service, android.content.Context, java.lang.String, android.app.Application);
-  }
-
-}
-
diff --git a/test-mock/api/apicheck_msg_android_test_mock-system.txt b/test-mock/api/apicheck_msg_android_test_mock-system.txt
deleted file mode 100644
index 3a97117..0000000
--- a/test-mock/api/apicheck_msg_android_test_mock-system.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-******************************
-You have tried to change the API from what has been previously approved.
-
-To make these errors go away, you have two choices:
-   1) You can add "@hide" javadoc comments to the methods, etc. listed in the
-      errors above.
-
-   2) You can update android-test-mock-current.txt by executing the following command:
-         make update-android-test-mock-system-api
-
-      To submit the revised android-test-mock-system-current.txt to the main Android repository,
-      you will need approval.
-******************************
-
-
-
diff --git a/test-mock/api/apicheck_msg_android_test_mock.txt b/test-mock/api/apicheck_msg_android_test_mock.txt
deleted file mode 100644
index e388935..0000000
--- a/test-mock/api/apicheck_msg_android_test_mock.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-******************************
-You have tried to change the API from what has been previously approved.
-
-To make these errors go away, you have two choices:
-   1) You can add "@hide" javadoc comments to the methods, etc. listed in the
-      errors above.
-
-   2) You can update android-test-mock-current.txt by executing the following command:
-         make update-android-test-mock-api
-
-      To submit the revised android-test-mock-current.txt to the main Android repository,
-      you will need approval.
-******************************
-
-
-
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
new file mode 100644
index 0000000..fc9b4c6
--- /dev/null
+++ b/test-mock/api/current.txt
@@ -0,0 +1,304 @@
+package android.test.mock {
+
+  public deprecated class MockAccountManager {
+    method public static android.accounts.AccountManager newMockAccountManager(android.content.Context);
+  }
+
+  public deprecated class MockApplication extends android.app.Application {
+    ctor public MockApplication();
+  }
+
+  public class MockContentProvider extends android.content.ContentProvider {
+    ctor protected MockContentProvider();
+    ctor public MockContentProvider(android.content.Context);
+    ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
+    method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>);
+    method public static deprecated void attachInfoForTesting(android.content.ContentProvider, android.content.Context, android.content.pm.ProviderInfo);
+    method public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+    method public java.lang.String getType(android.net.Uri);
+    method public android.net.Uri insert(android.net.Uri, android.content.ContentValues);
+    method public boolean onCreate();
+    method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle);
+    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
+  }
+
+  public class MockContentResolver extends android.content.ContentResolver {
+    ctor public MockContentResolver();
+    ctor public MockContentResolver(android.content.Context);
+    method public void addProvider(java.lang.String, android.content.ContentProvider);
+  }
+
+  public class MockContext extends android.content.Context {
+    ctor public MockContext();
+    method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
+    method public int checkCallingOrSelfPermission(java.lang.String);
+    method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
+    method public int checkCallingPermission(java.lang.String);
+    method public int checkCallingUriPermission(android.net.Uri, int);
+    method public int checkPermission(java.lang.String, int, int);
+    method public int checkSelfPermission(java.lang.String);
+    method public int checkUriPermission(android.net.Uri, int, int, int);
+    method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
+    method public void clearWallpaper();
+    method public android.content.Context createConfigurationContext(android.content.res.Configuration);
+    method public android.content.Context createContextForSplit(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.Context createDeviceProtectedStorageContext();
+    method public android.content.Context createDisplayContext(android.view.Display);
+    method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.lang.String[] databaseList();
+    method public boolean deleteDatabase(java.lang.String);
+    method public boolean deleteFile(java.lang.String);
+    method public boolean deleteSharedPreferences(java.lang.String);
+    method public void enforceCallingOrSelfPermission(java.lang.String, java.lang.String);
+    method public void enforceCallingOrSelfUriPermission(android.net.Uri, int, java.lang.String);
+    method public void enforceCallingPermission(java.lang.String, java.lang.String);
+    method public void enforceCallingUriPermission(android.net.Uri, int, java.lang.String);
+    method public void enforcePermission(java.lang.String, int, int, java.lang.String);
+    method public void enforceUriPermission(android.net.Uri, int, int, int, java.lang.String);
+    method public void enforceUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int, java.lang.String);
+    method public java.lang.String[] fileList();
+    method public android.content.Context getApplicationContext();
+    method public android.content.pm.ApplicationInfo getApplicationInfo();
+    method public android.content.res.AssetManager getAssets();
+    method public java.io.File getCacheDir();
+    method public java.lang.ClassLoader getClassLoader();
+    method public java.io.File getCodeCacheDir();
+    method public android.content.ContentResolver getContentResolver();
+    method public java.io.File getDataDir();
+    method public java.io.File getDatabasePath(java.lang.String);
+    method public java.io.File getDir(java.lang.String, int);
+    method public java.io.File getExternalCacheDir();
+    method public java.io.File[] getExternalCacheDirs();
+    method public java.io.File getExternalFilesDir(java.lang.String);
+    method public java.io.File[] getExternalFilesDirs(java.lang.String);
+    method public java.io.File[] getExternalMediaDirs();
+    method public java.io.File getFileStreamPath(java.lang.String);
+    method public java.io.File getFilesDir();
+    method public android.os.Looper getMainLooper();
+    method public java.io.File getNoBackupFilesDir();
+    method public java.io.File getObbDir();
+    method public java.io.File[] getObbDirs();
+    method public java.lang.String getPackageCodePath();
+    method public android.content.pm.PackageManager getPackageManager();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getPackageResourcePath();
+    method public android.content.res.Resources getResources();
+    method public android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
+    method public java.lang.Object getSystemService(java.lang.String);
+    method public java.lang.String getSystemServiceName(java.lang.Class<?>);
+    method public android.content.res.Resources.Theme getTheme();
+    method public android.graphics.drawable.Drawable getWallpaper();
+    method public int getWallpaperDesiredMinimumHeight();
+    method public int getWallpaperDesiredMinimumWidth();
+    method public void grantUriPermission(java.lang.String, android.net.Uri, int);
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
+    method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
+    method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
+    method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler);
+    method public android.graphics.drawable.Drawable peekWallpaper();
+    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
+    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, int);
+    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
+    method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler, int);
+    method public void removeStickyBroadcast(android.content.Intent);
+    method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void revokeUriPermission(android.net.Uri, int);
+    method public void revokeUriPermission(java.lang.String, android.net.Uri, int);
+    method public void sendBroadcast(android.content.Intent);
+    method public void sendBroadcast(android.content.Intent, java.lang.String);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
+    method public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
+    method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendStickyBroadcast(android.content.Intent);
+    method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+    method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+    method public void setTheme(int);
+    method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException;
+    method public void setWallpaper(java.io.InputStream) throws java.io.IOException;
+    method public void startActivities(android.content.Intent[]);
+    method public void startActivities(android.content.Intent[], android.os.Bundle);
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle);
+    method public android.content.ComponentName startForegroundService(android.content.Intent);
+    method public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
+    method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
+    method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
+    method public android.content.ComponentName startService(android.content.Intent);
+    method public boolean stopService(android.content.Intent);
+    method public void unbindService(android.content.ServiceConnection);
+    method public void unregisterReceiver(android.content.BroadcastReceiver);
+  }
+
+  public deprecated class MockCursor implements android.database.Cursor {
+    ctor public MockCursor();
+    method public void close();
+    method public void copyStringToBuffer(int, android.database.CharArrayBuffer);
+    method public deprecated void deactivate();
+    method public byte[] getBlob(int);
+    method public int getColumnCount();
+    method public int getColumnIndex(java.lang.String);
+    method public int getColumnIndexOrThrow(java.lang.String);
+    method public java.lang.String getColumnName(int);
+    method public java.lang.String[] getColumnNames();
+    method public int getCount();
+    method public double getDouble(int);
+    method public android.os.Bundle getExtras();
+    method public float getFloat(int);
+    method public int getInt(int);
+    method public long getLong(int);
+    method public android.net.Uri getNotificationUri();
+    method public int getPosition();
+    method public short getShort(int);
+    method public java.lang.String getString(int);
+    method public int getType(int);
+    method public boolean getWantsAllOnMoveCalls();
+    method public boolean isAfterLast();
+    method public boolean isBeforeFirst();
+    method public boolean isClosed();
+    method public boolean isFirst();
+    method public boolean isLast();
+    method public boolean isNull(int);
+    method public boolean move(int);
+    method public boolean moveToFirst();
+    method public boolean moveToLast();
+    method public boolean moveToNext();
+    method public boolean moveToPosition(int);
+    method public boolean moveToPrevious();
+    method public void registerContentObserver(android.database.ContentObserver);
+    method public void registerDataSetObserver(android.database.DataSetObserver);
+    method public deprecated boolean requery();
+    method public android.os.Bundle respond(android.os.Bundle);
+    method public void setExtras(android.os.Bundle);
+    method public void setNotificationUri(android.content.ContentResolver, android.net.Uri);
+    method public void unregisterContentObserver(android.database.ContentObserver);
+    method public void unregisterDataSetObserver(android.database.DataSetObserver);
+  }
+
+  public deprecated class MockDialogInterface implements android.content.DialogInterface {
+    ctor public MockDialogInterface();
+    method public void cancel();
+    method public void dismiss();
+  }
+
+  public deprecated class MockPackageManager extends android.content.pm.PackageManager {
+    ctor public MockPackageManager();
+    method public void addPackageToPreferred(java.lang.String);
+    method public boolean addPermission(android.content.pm.PermissionInfo);
+    method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
+    method public void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+    method public boolean canRequestPackageInstalls();
+    method public java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
+    method public int checkPermission(java.lang.String, java.lang.String);
+    method public int checkSignatures(java.lang.String, java.lang.String);
+    method public int checkSignatures(int, int);
+    method public void clearInstantAppCookie();
+    method public void clearPackagePreferredActivities(java.lang.String);
+    method public java.lang.String[] currentToCanonicalPackageNames(java.lang.String[]);
+    method public void extendVerificationTimeout(int, int, long);
+    method public android.graphics.drawable.Drawable getActivityBanner(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.graphics.drawable.Drawable getActivityBanner(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.graphics.drawable.Drawable getActivityIcon(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.graphics.drawable.Drawable getActivityIcon(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ActivityInfo getActivityInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.graphics.drawable.Drawable getActivityLogo(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.graphics.drawable.Drawable getActivityLogo(android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.util.List<android.content.IntentFilter> getAllIntentFilters(java.lang.String);
+    method public java.util.List<android.content.pm.PermissionGroupInfo> getAllPermissionGroups(int);
+    method public android.graphics.drawable.Drawable getApplicationBanner(android.content.pm.ApplicationInfo);
+    method public android.graphics.drawable.Drawable getApplicationBanner(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public int getApplicationEnabledSetting(java.lang.String);
+    method public android.graphics.drawable.Drawable getApplicationIcon(android.content.pm.ApplicationInfo);
+    method public android.graphics.drawable.Drawable getApplicationIcon(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
+    method public android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
+    method public android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ChangedPackages getChangedPackages(int);
+    method public int getComponentEnabledSetting(android.content.ComponentName);
+    method public android.graphics.drawable.Drawable getDefaultActivityIcon();
+    method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
+    method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
+    method public java.lang.String getInstallerPackageName(java.lang.String);
+    method public byte[] getInstantAppCookie();
+    method public int getInstantAppCookieMaxBytes();
+    method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.Intent getLaunchIntentForPackage(java.lang.String);
+    method public android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
+    method public java.lang.String getNameForUid(int);
+    method public int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public int[] getPackageGids(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.PackageInstaller getPackageInstaller();
+    method public int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.lang.String[] getPackagesForUid(int);
+    method public java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int);
+    method public android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
+    method public java.util.List<android.content.pm.PackageInfo> getPreferredPackages(int);
+    method public android.content.pm.ProviderInfo getProviderInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ActivityInfo getReceiverInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.res.Resources getResourcesForActivity(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo);
+    method public android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
+    method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
+    method public java.lang.String[] getSystemSharedLibraryNames();
+    method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
+    method public android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
+    method public java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
+    method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public boolean hasSystemFeature(java.lang.String);
+    method public boolean hasSystemFeature(java.lang.String, int);
+    method public boolean isInstantApp();
+    method public boolean isInstantApp(java.lang.String);
+    method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
+    method public boolean isSafeMode();
+    method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
+    method public java.util.List<android.content.pm.ProviderInfo> queryContentProviders(java.lang.String, int, int);
+    method public java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int);
+    method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(android.content.Intent, int);
+    method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], android.content.Intent, int);
+    method public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int);
+    method public java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
+    method public java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public void removePackageFromPreferred(java.lang.String);
+    method public void removePermission(java.lang.String);
+    method public android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
+    method public android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
+    method public android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
+    method public android.content.pm.ResolveInfo resolveServiceAsUser(android.content.Intent, int, int);
+    method public void setApplicationCategoryHint(java.lang.String, int);
+    method public void setApplicationEnabledSetting(java.lang.String, int, int);
+    method public void setComponentEnabledSetting(android.content.ComponentName, int, int);
+    method public void setInstallerPackageName(java.lang.String, java.lang.String);
+    method public void updateInstantAppCookie(byte[]);
+    method public void verifyPendingInstall(int, int);
+  }
+
+  public deprecated class MockResources extends android.content.res.Resources {
+    ctor public MockResources();
+    method public int getColor(int) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.ColorStateList getColorStateList(int) throws android.content.res.Resources.NotFoundException;
+    method public android.graphics.drawable.Drawable getDrawable(int) throws android.content.res.Resources.NotFoundException;
+    method public android.graphics.Movie getMovie(int) throws android.content.res.Resources.NotFoundException;
+    method public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics);
+  }
+
+  public deprecated class MockService {
+    method public static <T extends android.app.Service> void attachForTesting(android.app.Service, android.content.Context, java.lang.String, android.app.Application);
+  }
+
+}
+
diff --git a/test-mock/api/android-test-mock-removed.txt b/test-mock/api/removed.txt
similarity index 100%
rename from test-mock/api/android-test-mock-removed.txt
rename to test-mock/api/removed.txt
diff --git a/test-mock/api/android-test-mock-system-current.txt b/test-mock/api/system-current.txt
similarity index 100%
rename from test-mock/api/android-test-mock-system-current.txt
rename to test-mock/api/system-current.txt
diff --git a/test-mock/api/android-test-mock-system-removed.txt b/test-mock/api/system-removed.txt
similarity index 100%
rename from test-mock/api/android-test-mock-system-removed.txt
rename to test-mock/api/system-removed.txt
diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
new file mode 100644
index 0000000..f1ec000
--- /dev/null
+++ b/test-mock/api/test-current.txt
@@ -0,0 +1,22 @@
+package android.test.mock {
+
+  public class MockContext extends android.content.Context {
+    method public java.lang.String getOpPackageName();
+  }
+
+  public deprecated class MockPackageManager extends android.content.pm.PackageManager {
+    method public boolean arePermissionsIndividuallyControlled();
+    method public java.lang.String getDefaultBrowserPackageNameAsUser(int);
+    method public int getInstallReason(java.lang.String, android.os.UserHandle);
+    method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
+    method public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
+    method public java.lang.String[] getNamesForUids(int[]);
+    method public java.lang.String getPermissionControllerPackageName();
+    method public java.lang.String getServicesSystemSharedLibraryPackageName();
+    method public java.lang.String getSharedSystemSharedLibraryPackageName();
+    method public void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
+    method public void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
+  }
+
+}
+
diff --git a/test-mock/api/android-test-mock-system-removed.txt b/test-mock/api/test-removed.txt
similarity index 100%
copy from test-mock/api/android-test-mock-system-removed.txt
copy to test-mock/api/test-removed.txt
diff --git a/test-mock/src/android/test/mock/MockPackageManager.java b/test-mock/src/android/test/mock/MockPackageManager.java
index c2aca6b..89734e3 100644
--- a/test-mock/src/android/test/mock/MockPackageManager.java
+++ b/test-mock/src/android/test/mock/MockPackageManager.java
@@ -159,7 +159,13 @@
 
     /** @hide */
     @Override
-    public boolean isPermissionReviewModeEnabled() {
+    public boolean arePermissionsIndividuallyControlled() {
+        return false;
+    }
+
+    /** @hide */
+    @Override
+    public boolean isWirelessConsentModeEnabled() {
         return false;
     }
 
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index b50ba3b..ea615b9 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -16,22 +16,32 @@
 
 // Build the android.test.runner library
 // =====================================
-java_library {
+java_sdk_library {
     name: "android.test.runner",
 
-    // Needs to be consistent with the repackaged version of this make target.
-    java_version: "1.8",
     srcs: ["src/**/*.java"],
 
     errorprone: {
         javacflags: ["-Xep:DepAnn:ERROR"],
     },
 
-    sdk_version: "current",
     libs: [
         "android.test.base",
-        "android.test.mock.stubs",
+        "android.test.mock",
     ],
+    stub_only_libs: [
+        "android.test.base",
+        "android.test.mock",
+    ],
+    api_packages: [
+        "android.test",
+        "android.test.suitebuilder",
+        "junit.runner",
+        "junit.textui",
+    ],
+
+    droiddoc_options: ["stubsourceonly"],
+    compile_dex: true
 }
 
 // Build the android.test.runner-minus-junit library
@@ -45,8 +55,8 @@
 
     sdk_version: "current",
     libs: [
-        "android.test.base",
-        "android.test.mock.stubs",
+        "android.test.base_static",
+        "android.test.mock",
         "junit",
     ],
 }
@@ -69,7 +79,7 @@
 
     sdk_version: "current",
     libs: [
-        "android.test.base",
+        "android.test.base_static",
     ],
 
     jarjar_rules: "jarjar-rules.txt",
@@ -77,47 +87,3 @@
     java_version: "1.8",
 }
 
-droiddoc {
-    name: "android-test-runner-api-stubs-gen-docs",
-    srcs: [
-        "src/**/*.java",
-    ],
-    libs: [
-        "core-oj",
-        "core-libart",
-        "framework",
-        "android.test.base",
-        "android.test.mock",
-    ],
-    custom_template: "droiddoc-templates-sdk",
-    installable: false,
-    args: "-stubpackages android.test:" +
-          "android.test.suitebuilder:" +
-          "junit.runner:" +
-          "junit.textui -stubsourceonly -nodocs",
-    api_tag_name: "ANDROID_TEST_RUNNER",
-    api_filename: "android-test-runner-current.txt",
-    removed_api_filename: "android-test-runner-removed.txt",
-}
-
-// Build the android.test.runner.stubs library
-// =========================================
-java_library_static {
-    name: "android.test.runner.stubs",
-    srcs: [
-        ":android-test-runner-api-stubs-gen-docs",
-    ],
-    libs: [
-        "android.test.base.stubs",
-        "android.test.mock.stubs",
-    ],
-    product_variables: {
-        pdk: {
-            enabled: false,
-        },
-        unbundled_build: {
-            enabled: false,
-        },
-    },
-    sdk_version: "current",
-}
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index b70d249..18bde85 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -16,49 +16,5 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
-ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
-
-ANDROID_TEST_RUNNER_API_FILE := $(LOCAL_PATH)/api/android-test-runner-current.txt
-ANDROID_TEST_RUNNER_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-runner-removed.txt
-
-full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.test.runner.stubs,,COMMON)/classes.jar
-# Archive a copy of the classes.jar in SDK build.
-$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.runner.stubs.jar)
-
-# Check that the android.test.runner.stubs library has not changed
-# ================================================================
-
-# Check that the API we're building hasn't changed from the not-yet-released
-# SDK version.
-$(eval $(call check-api, \
-    check-android-test-runner-api-current, \
-    $(ANDROID_TEST_RUNNER_API_FILE), \
-    $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_API_FILE), \
-    $(ANDROID_TEST_RUNNER_REMOVED_API_FILE), \
-    $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_REMOVED_API_FILE), \
-    -error 2 -error 3 -error 4 -error 5 -error 6 \
-    -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
-    -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
-    -error 25 -error 26 -error 27, \
-    cat $(LOCAL_PATH)/api/apicheck_msg_android_test_runner.txt, \
-    check-android-test-runner-api, \
-    $(OUT_DOCS)/android-test-runner-api-stubs-gen-docs-stubs.srcjar  \
-    ))
-
-.PHONY: check-android-test-runner-api
-checkapi: check-android-test-runner-api
-
-.PHONY: update-android-test-runner-api
-update-api: update-android-test-runner-api
-
-update-android-test-runner-api: $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_API_FILE) | $(ACP)
-	@echo Copying current.txt
-	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_API_FILE) $(ANDROID_TEST_RUNNER_API_FILE)
-	@echo Copying removed.txt
-	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_REMOVED_API_FILE) $(ANDROID_TEST_RUNNER_REMOVED_API_FILE)
-
-endif  # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
-
 # additionally, build unit tests in a separate .apk
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/test-runner/api/apicheck_msg_android_test_runner.txt b/test-runner/api/apicheck_msg_android_test_runner.txt
deleted file mode 100644
index cf2d15e..0000000
--- a/test-runner/api/apicheck_msg_android_test_runner.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-******************************
-You have tried to change the API from what has been previously approved.
-
-To make these errors go away, you have two choices:
-   1) You can add "@hide" javadoc comments to the methods, etc. listed in the
-      errors above.
-
-   2) You can update android-test-runner-current.txt by executing the following command:
-         make update-android-test-runner-api
-
-      To submit the revised android-test-runner-current.txt to the main Android repository,
-      you will need approval.
-******************************
-
-
-
diff --git a/test-runner/api/android-test-runner-current.txt b/test-runner/api/current.txt
similarity index 100%
rename from test-runner/api/android-test-runner-current.txt
rename to test-runner/api/current.txt
diff --git a/test-runner/api/android-test-runner-removed.txt b/test-runner/api/removed.txt
similarity index 100%
copy from test-runner/api/android-test-runner-removed.txt
copy to test-runner/api/removed.txt
diff --git a/test-runner/api/android-test-runner-removed.txt b/test-runner/api/system-current.txt
similarity index 100%
copy from test-runner/api/android-test-runner-removed.txt
copy to test-runner/api/system-current.txt
diff --git a/test-runner/api/android-test-runner-removed.txt b/test-runner/api/system-removed.txt
similarity index 100%
rename from test-runner/api/android-test-runner-removed.txt
rename to test-runner/api/system-removed.txt
diff --git a/test-runner/api/android-test-runner-removed.txt b/test-runner/api/test-current.txt
similarity index 100%
copy from test-runner/api/android-test-runner-removed.txt
copy to test-runner/api/test-current.txt
diff --git a/test-runner/api/android-test-runner-removed.txt b/test-runner/api/test-removed.txt
similarity index 100%
copy from test-runner/api/android-test-runner-removed.txt
copy to test-runner/api/test-removed.txt
diff --git a/tests/ActivityViewTest/Android.mk b/tests/ActivityViewTest/Android.mk
new file mode 100644
index 0000000..9c80764
--- /dev/null
+++ b/tests/ActivityViewTest/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := ActivityViewTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/tests/ActivityViewTest/AndroidManifest.xml b/tests/ActivityViewTest/AndroidManifest.xml
new file mode 100644
index 0000000..de54cc9
--- /dev/null
+++ b/tests/ActivityViewTest/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.google.android.test.activityview">
+    <uses-permission android:name="android.permission.INJECT_EVENTS"/>
+    <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"/>
+    <uses-permission android:name="android.permission.ACTIVITY_EMBEDDING"/>
+    <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
+
+    <uses-sdk android:targetSdkVersion="27"/>
+    <application android:label="ActivityViewTest">
+        <activity android:name=".ActivityViewMainActivity"
+                  android:label="AV Main"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".ActivityViewActivity"
+                  android:label="AV"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
+        </activity>
+
+        <activity android:name=".ActivityViewResizeActivity"
+                  android:label="AV Resize"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
+        </activity>
+
+        <activity android:name=".ActivityViewScrollActivity"
+                  android:label="AV Scroll"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
+        </activity>
+
+        <activity android:name=".ActivityViewTestActivity"
+                  android:resizeableActivity="true"
+                  android:theme="@*android:style/Theme.NoTitleBar"
+                  android:exported="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/ActivityViewTest/res/layout/activity_view_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_activity.xml
new file mode 100644
index 0000000..67c01f8
--- /dev/null
+++ b/tests/ActivityViewTest/res/layout/activity_view_activity.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:background="#cfd8dc">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/activity_launch_button"
+            android:layout_width="200dp"
+            android:layout_height="wrap_content"
+            android:text="Launch test activity" />
+
+        <Button
+            android:id="@+id/activity_pick_launch_button"
+            android:layout_width="200dp"
+            android:layout_height="wrap_content"
+            android:text="Launch from picker" />
+
+    </LinearLayout>
+
+    <ActivityView
+        android:id="@+id/activity_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
new file mode 100644
index 0000000..ba2e911
--- /dev/null
+++ b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <Button
+        android:id="@+id/activity_view_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Test ActivityView"
+        android:textAllCaps="false"/>
+
+    <Button
+        android:id="@+id/scroll_activity_view_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Test Scroll ActivityView"
+        android:textAllCaps="false"/>
+
+    <Button
+        android:id="@+id/resize_activity_view_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Test Resize ActivityView"
+        android:textAllCaps="false"/>
+
+</LinearLayout>
diff --git a/tests/ActivityViewTest/res/layout/activity_view_resize_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_resize_activity.xml
new file mode 100644
index 0000000..18d86e3
--- /dev/null
+++ b/tests/ActivityViewTest/res/layout/activity_view_resize_activity.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:background="#cfd8dc">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/activity_launch_button"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:text="Launch" />
+
+        <Button
+            android:id="@+id/activity_resize_button"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:text="Resize" />
+    </LinearLayout>
+
+    <SeekBar
+        android:id="@+id/activity_view_seek_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <ActivityView
+        android:id="@+id/activity_view"
+        android:layout_width="match_parent"
+        android:layout_height="600dp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/ActivityViewTest/res/layout/activity_view_scroll_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_scroll_activity.xml
new file mode 100644
index 0000000..879c2c20
--- /dev/null
+++ b/tests/ActivityViewTest/res/layout/activity_view_scroll_activity.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical" android:layout_width="match_parent"
+              android:layout_height="match_parent">
+
+    <Button
+        android:id="@+id/activity_launch_button"
+        android:layout_width="100dp"
+        android:layout_height="wrap_content"
+        android:text="Launch" />
+
+    <ScrollView
+        android:id="@+id/activity_view_host_scroll_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:color="#cfd8dc">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical" >
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="300dp"
+                android:layout_gravity="center_horizontal"
+                android:background="#eeeeee" />
+
+            <ActivityView
+                android:id="@+id/activity_view"
+                android:layout_width="match_parent"
+                android:layout_height="300dp"
+                android:background="#fce4ec" />
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="300dp"
+                android:layout_gravity="center_horizontal"
+                android:background="#eeeeee" />
+        </LinearLayout>
+    </ScrollView>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/ActivityViewTest/res/layout/activity_view_test_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_test_activity.xml
new file mode 100644
index 0000000..f7ec562
--- /dev/null
+++ b/tests/ActivityViewTest/res/layout/activity_view_test_activity.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="#ffe0b2">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:orientation="vertical"
+        android:background="#00000000" >
+        <TextView
+            android:id="@+id/test_activity_title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textColor="@android:color/black"
+            android:background="#00000000"
+            android:gravity="center" />
+        <TextView
+            android:id="@+id/test_activity_touch_state"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textColor="@android:color/black"
+            android:background="#00000000"
+            android:gravity="center" />
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/test_activity_width_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textColor="@android:color/black"
+        android:background="#00000000"
+        android:gravity="center" />
+
+    <TextView
+        android:id="@+id/test_activity_height_text"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentEnd="true"
+        android:textColor="@android:color/black"
+        android:background="#00000000"
+        android:gravity="center" />
+
+    <View
+        android:id="@+id/touch_intercept_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#00000000"
+    />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java
new file mode 100644
index 0000000..1548d6e
--- /dev/null
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activityview;
+
+import android.app.Activity;
+import android.app.ActivityView;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.Button;
+
+public class ActivityViewActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_view_activity);
+
+        final ActivityView activityView = findViewById(R.id.activity_view);
+        final Button launchButton = findViewById(R.id.activity_launch_button);
+        launchButton.setOnClickListener(v -> {
+            final Intent intent = new Intent(this, ActivityViewTestActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+            activityView.startActivity(intent);
+        });
+        final Button pickActivityLaunchButton = findViewById(R.id.activity_pick_launch_button);
+        pickActivityLaunchButton.setOnClickListener(v -> {
+            final Intent intent = Intent.makeMainActivity(null);
+            final Intent chooser = Intent.createChooser(intent,
+                    "Pick an app to launch in ActivityView");
+            if (intent.resolveActivity(getPackageManager()) != null) {
+                chooser.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+                activityView.startActivity(chooser);
+            }
+        });
+    }
+}
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
new file mode 100644
index 0000000..66f0c6a
--- /dev/null
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activityview;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class ActivityViewMainActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_view_main_activity);
+
+        findViewById(R.id.activity_view_button).setOnClickListener(
+                v -> startActivity(new Intent(this, ActivityViewActivity.class)));
+
+        findViewById(R.id.scroll_activity_view_button).setOnClickListener(
+                v -> startActivity(new Intent(this, ActivityViewScrollActivity.class)));
+
+        findViewById(R.id.resize_activity_view_button).setOnClickListener(
+                v -> startActivity(new Intent(this, ActivityViewResizeActivity.class)));
+    }
+}
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewResizeActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewResizeActivity.java
new file mode 100644
index 0000000..8860a77
--- /dev/null
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewResizeActivity.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activityview;
+
+import android.app.Activity;
+import android.app.ActivityView;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+
+public class ActivityViewResizeActivity extends Activity {
+    private static final int SMALL_SIZE = 600;
+    private static final int LARGE_SIZE = 1200;
+
+    private ActivityView mActivityView;
+
+    private boolean mFlipSize;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_view_resize_activity);
+
+        mActivityView = findViewById(R.id.activity_view);
+
+        final Button launchButton = findViewById(R.id.activity_launch_button);
+        launchButton.setOnClickListener(v -> {
+            final Intent intent = new Intent(this, ActivityViewTestActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+            mActivityView.startActivity(intent);
+        });
+        final Button resizeButton = findViewById(R.id.activity_resize_button);
+        if (resizeButton != null) {
+            resizeButton.setOnClickListener(v -> {
+                LinearLayout.LayoutParams params =
+                        (LinearLayout.LayoutParams) mActivityView.getLayoutParams();
+                params.height = mFlipSize ? SMALL_SIZE : LARGE_SIZE;
+                mFlipSize = !mFlipSize;
+                mActivityView.setLayoutParams(params);
+            });
+        }
+        final SeekBar seekBar = findViewById(R.id.activity_view_seek_bar);
+        if (seekBar != null) {
+            seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+                @Override
+                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                    final LinearLayout.LayoutParams params =
+                            (LinearLayout.LayoutParams) mActivityView.getLayoutParams();
+                    params.height = SMALL_SIZE + progress * 10;
+                    mActivityView.setLayoutParams(params);
+                }
+
+                @Override
+                public void onStartTrackingTouch(SeekBar seekBar) {
+                }
+
+                @Override
+                public void onStopTrackingTouch(SeekBar seekBar) {
+                }
+            });
+        }
+    }
+}
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewScrollActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewScrollActivity.java
new file mode 100644
index 0000000..5654366
--- /dev/null
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewScrollActivity.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activityview;
+
+import android.app.Activity;
+import android.app.ActivityView;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+public class ActivityViewScrollActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_view_scroll_activity);
+
+        final ActivityView activityView = findViewById(R.id.activity_view);
+        final Button launchButton = findViewById(R.id.activity_launch_button);
+        launchButton.setOnClickListener(v -> {
+            final Intent intent = new Intent(this, ActivityViewTestActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+            activityView.startActivity(intent);
+        });
+        findViewById(R.id.activity_view_host_scroll_view).setOnScrollChangeListener(
+                (View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
+                        -> activityView.onLocationChanged());
+    }
+}
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
new file mode 100644
index 0000000..0d62786
--- /dev/null
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activityview;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.widget.TextView;
+
+public class ActivityViewTestActivity extends Activity implements View.OnTouchListener {
+
+    private TextView mTextView;
+    private TextView mWidthTextView;
+    private TextView mHeightTextView;
+    private TextView mTouchStateTextView;
+    private View mTouchInterceptView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_view_test_activity);
+
+        mTextView = findViewById(R.id.test_activity_title);
+        mWidthTextView = findViewById(R.id.test_activity_width_text);
+        mHeightTextView = findViewById(R.id.test_activity_height_text);
+        mTouchStateTextView = findViewById(R.id.test_activity_touch_state);
+        mTouchInterceptView = findViewById(R.id.touch_intercept_view);
+        mTouchInterceptView.setOnTouchListener(this);
+        ViewTreeObserver viewTreeObserver = mTouchInterceptView.getViewTreeObserver();
+        if (viewTreeObserver.isAlive()) {
+            viewTreeObserver.addOnGlobalLayoutListener(this::updateDimensionTexts);
+        }
+        updateStateText("CREATED");
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        updateStateText("STARTED");
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        updateStateText("RESUMED");
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        updateStateText("PAUSED");
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        updateStateText("STOPPED");
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateDimensionTexts();
+    }
+
+    private void updateStateText(String state) {
+        mTextView.setText(state);
+    }
+
+    private void updateDimensionTexts() {
+        mWidthTextView.setText("" + mTouchInterceptView.getWidth());
+        mHeightTextView.setText("" + mTouchInterceptView.getHeight());
+    }
+
+    private void updateTouchState(MotionEvent event) {
+        switch (event.getAction()) {
+            case ACTION_DOWN:
+            case ACTION_MOVE:
+                mTouchStateTextView.setText("[" + event.getX() + "," + event.getY() + "]");
+                break;
+            case ACTION_UP:
+            case ACTION_CANCEL:
+                mTouchStateTextView.setText("");
+                break;
+        }
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        updateTouchState(event);
+        return true;
+    }
+}
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index e247951..e509d2d 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -17,8 +17,10 @@
 package com.android.server.pm;
 
 import android.app.AlarmManager;
+import android.app.UiAutomation;
 import android.content.Context;
 import android.os.Environment;
+import android.os.ParcelFileDescriptor;
 import android.os.SystemProperties;
 import android.os.storage.StorageManager;
 import android.support.test.InstrumentationRegistry;
@@ -34,6 +36,7 @@
 import org.junit.runners.JUnit4;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -141,27 +144,17 @@
     // Run the command and return the stdout.
     private static String runShellCommand(String cmd) throws IOException {
         Log.i(TAG, String.format("running command: '%s'", cmd));
-        long startTime = System.nanoTime();
-        Process p = Runtime.getRuntime().exec(cmd);
-        int res;
-        try {
-            res = p.waitFor();
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
+        ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .executeShellCommand(cmd);
+        byte[] buf = new byte[512];
+        int bytesRead;
+        FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+        StringBuilder stdout = new StringBuilder();
+        while ((bytesRead = fis.read(buf)) != -1) {
+            stdout.append(new String(buf, 0, bytesRead));
         }
-        String stdout = inputStreamToString(p.getInputStream());
-        String stderr = inputStreamToString(p.getErrorStream());
-        long elapsedTime = System.nanoTime() - startTime;
-        Log.i(TAG, String.format("ran command: '%s' in %d ms with return code %d", cmd,
-                TimeUnit.NANOSECONDS.toMillis(elapsedTime), res));
-        Log.i(TAG, "stdout");
-        Log.i(TAG, stdout);
-        Log.i(TAG, "stderr");
-        Log.i(TAG, stderr);
-        if (res != 0) {
-            throw new RuntimeException(String.format("failed command: '%s'", cmd));
-        }
-        return stdout;
+        fis.close();
+        return stdout.toString();
     }
 
     // Run the command and return the stdout split by lines.
diff --git a/tests/FlickerTests/Android.mk b/tests/FlickerTests/Android.mk
new file mode 100644
index 0000000..3c70f8b
--- /dev/null
+++ b/tests/FlickerTests/Android.mk
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := FlickerTests
+LOCAL_MODULE_TAGS := tests optional
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_CERTIFICATE := platform
+LOCAL_COMPATIBILITY_SUITE := device-tests
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    flickertestapplib \
+    flickerlib \
+    truth-prebuilt \
+    app-helpers-core
+
+include $(BUILD_PACKAGE)
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/FlickerTests/AndroidManifest.xml b/tests/FlickerTests/AndroidManifest.xml
new file mode 100644
index 0000000..ba63940
--- /dev/null
+++ b/tests/FlickerTests/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.server.wm.flicker">
+
+    <uses-sdk android:minSdkVersion="27" android:targetSdkVersion="27"/>
+    <!-- Read and write traces from external storage -->
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <!-- Capture screen contents -->
+    <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
+    <!-- Run layers trace -->
+    <uses-permission android:name="android.permission.HARDWARE_TEST"/>
+    <application>
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.wm.flicker"
+                     android:label="WindowManager Flicker Tests">
+    </instrumentation>
+</manifest>
\ No newline at end of file
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
new file mode 100644
index 0000000..b31235b
--- /dev/null
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright 2018 Google Inc. All Rights Reserved.
+ -->
+<configuration description="Runs WindowManager Flicker Tests">
+    <option name="test-tag" value="FlickerTests" />
+    <target_preparer class="com.google.android.tradefed.targetprep.GoogleDeviceSetup">
+        <!-- keeps the screen on during tests -->
+        <option name="screen-always-on" value="on" />
+        <!-- prevents the phone from restarting -->
+        <option name="force-skip-system-props" value="true" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true"/>
+        <option name="test-file-name" value="FlickerTests.apk"/>
+        <option name="test-file-name" value="FlickerTestApp.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.server.wm.flicker"/>
+        <option name="shell-timeout" value="6600s" />
+        <option name="test-timeout" value="6000s" />
+        <option name="hidden-api-checks" value="false" />
+    </test>
+    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+        <option name="directory-keys" value="/sdcard/flicker" />
+        <option name="collect-on-run-ended-only" value="true" />
+    </metrics_collector>
+</configuration>
diff --git a/tests/FlickerTests/README.md b/tests/FlickerTests/README.md
new file mode 100644
index 0000000..a7c9e20
--- /dev/null
+++ b/tests/FlickerTests/README.md
@@ -0,0 +1,146 @@
+# Flicker Test Library
+
+## Motivation
+Detect *flicker* &mdash; any discontinuous, or unpredictable behavior seen during UI transitions that is not due to performance. This is often the result of a logic error in the code and difficult to identify because the issue is transient and at times difficult to reproduce. This library helps create integration tests between `SurfaceFlinger`, `WindowManager` and `SystemUI` to identify flicker.
+
+## Adding a Test
+The library builds and runs UI transitions, captures Winscope traces and exposes common assertions that can be tested against each trace.
+
+### Building Transitions
+Start by defining common or error prone transitions using `TransitionRunner`.
+```java
+// Example: Build a transition that cold launches an app from launcher
+TransitionRunner transition = TransitionRunner.newBuilder()
+                // Specify a tag to identify the transition (optional)
+                .withTag("OpenAppCold_" + testApp.getLauncherName())
+
+                // Specify preconditions to setup the device
+                // Wake up device and go to home screen
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+
+                // Setup transition under test
+                // Press the home button and close the app to test a cold start
+                .runBefore(device::pressHome)
+                .runBefore(testApp::exit)
+
+                // Run the transition under test
+                // Open the app and wait for UI to be idle
+                // This is the part of the transition that will be tested.
+                .run(testApp::open)
+                .run(device::waitForIdle)
+
+                // Perform any tear downs
+                // Close the app
+                .runAfterAll(testApp::exit)
+
+                // Number of times to repeat the transition to catch any flaky issues
+                .repeat(5);
+```
+
+
+Run the transition to get a list of `TransitionResult` for each time the transition is repeated.
+```java
+    List<TransitionResult> results = transition.run();
+```
+`TransitionResult` contains paths to test artifacts such as Winscope traces and screen recordings.
+
+
+### Checking Assertions
+Each `TransitionResult` can be tested using an extension of the Google Truth library, `LayersTraceSubject` and `WmTraceSubject`. They try to balance test principles set out by Google Truth (not supporting nested assertions, keeping assertions simple) with providing support for common assertion use cases.
+
+Each trace can be represented as a ordered collection of trace entries, with an associated timestamp. Each trace entry has common assertion checks. The trace subjects expose methods to filter the range of entries and test for changing assertions.
+
+```java
+    TransitionResult result = results.get(0);
+    Rect displayBounds = getDisplayBounds();
+
+    // check all trace entries
+    assertThat(result).coversRegion(displayBounds).forAllEntries();
+
+    // check a range of entries
+    assertThat(result).coversRegion(displayBounds).forRange(startTime, endTime);
+
+    // check first entry
+    assertThat(result).coversRegion(displayBounds).inTheBeginning();
+
+    // check last entry
+    assertThat(result).coversRegion(displayBounds).atTheEnd();
+
+    // check a change in assertions, e.g. wallpaper window is visible,
+    // then wallpaper window becomes and stays invisible
+    assertThat(result)
+                .showsBelowAppWindow("wallpaper")
+                .then()
+                .hidesBelowAppWindow("wallpaper")
+                .forAllEntries();
+```
+
+All assertions return `Result` which contains a `success` flag, `assertionName` string identifier, and `reason` string to provide actionable details to the user. The `reason` string is build along the way with all the details as to why the assertions failed and any hints which might help the user determine the root cause. Failed assertion message will also contain a path to the trace that was tested. Example of a failed test:
+
+```
+    java.lang.AssertionError: Not true that <com.android.server.wm.flicker.LayersTrace@65da4cc>
+    Layers Trace can be found in: /layers_trace_emptyregion.pb
+    Timestamp: 2308008331271
+    Assertion: coversRegion
+    Reason:   Region to test: Rect(0, 0 - 1440, 2880)
+    first empty point: 0, 99
+    visible regions:
+    StatusBar#0Rect(0, 0 - 1440, 98)
+    NavigationBar#0Rect(0, 2712 - 1440, 2880)
+    ScreenDecorOverlay#0Rect(0, 0 - 1440, 91)
+    ...
+        at com.google.common.truth.FailureStrategy.fail(FailureStrategy.java:24)
+        ...
+```
+
+---
+
+## Running Tests
+
+The tests can be run as any other Android JUnit tests. `platform_testing/tests/flicker` uses the library to test common UI transitions. Run `atest FlickerTest` to execute these tests.
+
+---
+
+## Other Topics
+### Monitors
+Monitors capture test artifacts for each transition run. They are started before each iteration of the test transition (after the `runBefore` calls) and stopped after the transition is completed. Each iteration will produce a new test artifact. The following monitors are available:
+
+#### LayersTraceMonitor
+Captures Layers trace. This monitor is started by default. Build a transition with `skipLayersTrace()` to disable this monitor.
+#### WindowManagerTraceMonitor
+Captures Window Manager trace. This monitor is started by default. Build a transition with `skipWindowManagerTrace()` to disable this monitor.
+#### WindowAnimationFrameStatsMonitor
+Captures WindowAnimationFrameStats for the transition. This monitor is started by default and is used to eliminate *janky* runs. If an iteration has skipped frames, as determined by WindowAnimationFrameStats, the results for the iteration is skipped. If the list of results is empty after all iterations are completed, then the test should fail. Build a transition with `includeJankyRuns()` to disable this monitor.
+#### ScreenRecorder
+Captures screen to a video file. This monitor is disabled by default. Build a transition with `recordEachRun()` to capture each transition or build with `recordAllRuns()` to capture every transition including setup and teardown.
+
+---
+
+### Extending Assertions
+
+To add a new assertion, add a function to one of the trace entry classes, `LayersTrace.Entry` or `WindowManagerTrace.Entry`.
+
+```java
+    // Example adds an assertion to the check if layer is hidden by parent.
+    Result isHiddenByParent(String layerName) {
+        // Result should contain a details if assertion fails for any reason
+        // such as if layer is not found or layer is not hidden by parent
+        // or layer has no parent.
+        // ...
+    }
+```
+Then add a function to the trace subject `LayersTraceSubject` or `WmTraceSubject` which will add the assertion for testing. When the assertion is evaluated, the trace will first be filtered then the assertion will be applied to the remaining entries.
+
+```java
+    public LayersTraceSubject isHiddenByParent(String layerName) {
+        mChecker.add(entry -> entry.isHiddenByParent(layerName),
+                "isHiddenByParent(" + layerName + ")");
+        return this;
+    }
+```
+
+To use the new assertion:
+```java
+    // Check if "Chrome" layer is hidden by parent in the first trace entry.
+    assertThat(result).isHiddenByParent("Chrome").inTheBeginning();
+```
\ No newline at end of file
diff --git a/tests/FlickerTests/TEST_MAPPING b/tests/FlickerTests/TEST_MAPPING
new file mode 100644
index 0000000..55a6147
--- /dev/null
+++ b/tests/FlickerTests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "postsubmit": [
+    {
+      "name": "FlickerTests"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/lib/Android.mk b/tests/FlickerTests/lib/Android.mk
new file mode 100644
index 0000000..6a8dfe8
--- /dev/null
+++ b/tests/FlickerTests/lib/Android.mk
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := flickerlib
+LOCAL_MODULE_TAGS := tests optional
+# sign this with platform cert, so this test is allowed to call private platform apis
+LOCAL_CERTIFICATE := platform
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := \
+   ub-janktesthelper \
+   cts-amwm-util \
+   platformprotosnano \
+   layersprotosnano \
+   truth-prebuilt \
+   sysui-helper \
+   launcher-helper-lib \
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := flickerautomationhelperlib
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := src/com/android/server/wm/flicker/AutomationUtils.java \
+    src/com/android/server/wm/flicker/WindowUtils.java
+LOCAL_STATIC_JAVA_LIBRARIES := sysui-helper \
+    launcher-helper-lib \
+    compatibility-device-util
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/Assertions.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/Assertions.java
new file mode 100644
index 0000000..84f9f871
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/Assertions.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+
+/**
+ * Collection of functional interfaces and classes representing assertions and their associated
+ * results. Assertions are functions that are applied over a single trace entry and returns a
+ * result which includes a detailed reason if the assertion fails.
+ */
+class Assertions {
+    /**
+     * Checks assertion on a single trace entry.
+     *
+     * @param <T> trace entry type to perform the assertion on.
+     */
+    @FunctionalInterface
+    interface TraceAssertion<T> extends Function<T, Result> {
+        /**
+         * Returns an assertion that represents the logical negation of this assertion.
+         *
+         * @return a assertion that represents the logical negation of this assertion
+         */
+        default TraceAssertion<T> negate() {
+            return (T t) -> apply(t).negate();
+        }
+    }
+
+    /**
+     * Checks assertion on a single layers trace entry.
+     */
+    @FunctionalInterface
+    interface LayersTraceAssertion extends TraceAssertion<LayersTrace.Entry> {
+
+    }
+
+    /**
+     * Utility class to store assertions with an identifier to help generate more useful debug
+     * data when dealing with multiple assertions.
+     */
+    static class NamedAssertion<T> {
+        final TraceAssertion<T> assertion;
+        final String name;
+
+        NamedAssertion(TraceAssertion<T> assertion, String name) {
+            this.assertion = assertion;
+            this.name = name;
+        }
+    }
+
+    /**
+     * Contains the result of an assertion including the reason for failed assertions.
+     */
+    static class Result {
+        static final String NEGATION_PREFIX = "!";
+        final boolean success;
+        final long timestamp;
+        final String assertionName;
+        final String reason;
+
+        Result(boolean success, long timestamp, String assertionName, String reason) {
+            this.success = success;
+            this.timestamp = timestamp;
+            this.assertionName = assertionName;
+            this.reason = reason;
+        }
+
+        Result(boolean success, String reason) {
+            this.success = success;
+            this.reason = reason;
+            this.assertionName = "";
+            this.timestamp = 0;
+        }
+
+        /**
+         * Returns the negated {@code Result} and adds a negation prefix to the assertion name.
+         */
+        Result negate() {
+            String negatedAssertionName;
+            if (this.assertionName.startsWith(NEGATION_PREFIX)) {
+                negatedAssertionName = this.assertionName.substring(NEGATION_PREFIX.length() + 1);
+            } else {
+                negatedAssertionName = NEGATION_PREFIX + this.assertionName;
+            }
+            return new Result(!this.success, this.timestamp, negatedAssertionName, this.reason);
+        }
+
+        boolean passed() {
+            return this.success;
+        }
+
+        boolean failed() {
+            return !this.success;
+        }
+
+        @Override
+        public String toString() {
+            return "Timestamp: " + prettyTimestamp(timestamp)
+                    + "\nAssertion: " + assertionName
+                    + "\nReason:   " + reason;
+        }
+
+        private String prettyTimestamp(long timestamp_ns) {
+            StringBuilder prettyTimestamp = new StringBuilder();
+            TimeUnit[] timeUnits = {TimeUnit.HOURS, TimeUnit.MINUTES, TimeUnit.SECONDS, TimeUnit
+                    .MILLISECONDS};
+            String[] unitSuffixes = {"h", "m", "s", "ms"};
+
+            for (int i = 0; i < timeUnits.length; i++) {
+                long convertedTime = timeUnits[i].convert(timestamp_ns, TimeUnit.NANOSECONDS);
+                timestamp_ns -= TimeUnit.NANOSECONDS.convert(convertedTime, timeUnits[i]);
+                prettyTimestamp.append(convertedTime).append(unitSuffixes[i]);
+            }
+
+            return prettyTimestamp.toString();
+        }
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AssertionsChecker.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AssertionsChecker.java
new file mode 100644
index 0000000..3c65d3c
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AssertionsChecker.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import com.android.server.wm.flicker.Assertions.NamedAssertion;
+import com.android.server.wm.flicker.Assertions.Result;
+import com.android.server.wm.flicker.Assertions.TraceAssertion;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Captures some of the common logic in {@link LayersTraceSubject} and {@link WmTraceSubject}
+ * used to filter trace entries and combine multiple assertions.
+ *
+ * @param <T> trace entry type
+ */
+public class AssertionsChecker<T extends ITraceEntry> {
+    private boolean mFilterEntriesByRange = false;
+    private long mFilterStartTime = 0;
+    private long mFilterEndTime = 0;
+    private AssertionOption mOption = AssertionOption.NONE;
+    private List<NamedAssertion<T>> mAssertions = new LinkedList<>();
+
+    void add(Assertions.TraceAssertion<T> assertion, String name) {
+        mAssertions.add(new NamedAssertion<>(assertion, name));
+    }
+
+    void filterByRange(long startTime, long endTime) {
+        mFilterEntriesByRange = true;
+        mFilterStartTime = startTime;
+        mFilterEndTime = endTime;
+    }
+
+    private void setOption(AssertionOption option) {
+        if (mOption != AssertionOption.NONE && option != mOption) {
+            throw new IllegalArgumentException("Cannot use " + mOption + " option with "
+                    + option + " option.");
+        }
+        mOption = option;
+    }
+
+    public void checkFirstEntry() {
+        setOption(AssertionOption.CHECK_FIRST_ENTRY);
+    }
+
+    public void checkLastEntry() {
+        setOption(AssertionOption.CHECK_LAST_ENTRY);
+    }
+
+    public void checkChangingAssertions() {
+        setOption(AssertionOption.CHECK_CHANGING_ASSERTIONS);
+    }
+
+
+    /**
+     * Filters trace entries then runs assertions returning a list of failures.
+     *
+     * @param entries list of entries to perform assertions on
+     * @return list of failed assertion results
+     */
+    List<Result> test(List<T> entries) {
+        List<T> filteredEntries;
+        List<Result> failures;
+
+        if (mFilterEntriesByRange) {
+            filteredEntries = entries.stream()
+                    .filter(e -> ((e.getTimestamp() >= mFilterStartTime)
+                            && (e.getTimestamp() <= mFilterEndTime)))
+                    .collect(Collectors.toList());
+        } else {
+            filteredEntries = entries;
+        }
+
+        switch (mOption) {
+            case CHECK_CHANGING_ASSERTIONS:
+                return assertChanges(filteredEntries);
+            case CHECK_FIRST_ENTRY:
+                return assertEntry(filteredEntries.get(0));
+            case CHECK_LAST_ENTRY:
+                return assertEntry(filteredEntries.get(filteredEntries.size() - 1));
+        }
+        return assertAll(filteredEntries);
+    }
+
+    /**
+     * Steps through each trace entry checking if provided assertions are true in the order they
+     * are added. Each assertion must be true for at least a single trace entry.
+     *
+     * This can be used to check for asserting a change in property over a trace. Such as visibility
+     * for a window changes from true to false or top-most window changes from A to Bb and back to A
+     * again.
+     */
+    private List<Result> assertChanges(List<T> entries) {
+        List<Result> failures = new ArrayList<>();
+        int entryIndex = 0;
+        int assertionIndex = 0;
+        int lastPassedAssertionIndex = -1;
+
+        if (mAssertions.size() == 0) {
+            return failures;
+        }
+
+        while (assertionIndex < mAssertions.size() && entryIndex < entries.size()) {
+            TraceAssertion<T> currentAssertion = mAssertions.get(assertionIndex).assertion;
+            Result result = currentAssertion.apply(entries.get(entryIndex));
+            if (result.passed()) {
+                lastPassedAssertionIndex = assertionIndex;
+                entryIndex++;
+                continue;
+            }
+
+            if (lastPassedAssertionIndex != assertionIndex) {
+                failures.add(result);
+                break;
+            }
+            assertionIndex++;
+
+            if (assertionIndex == mAssertions.size()) {
+                failures.add(result);
+                break;
+            }
+        }
+
+        if (failures.isEmpty()) {
+            if (assertionIndex != mAssertions.size() - 1) {
+                String reason = "\nAssertion " + mAssertions.get(assertionIndex).name
+                        + " never became false";
+                reason += "\nPassed assertions: " + mAssertions.stream().limit(assertionIndex)
+                        .map(assertion -> assertion.name).collect(Collectors.joining(","));
+                reason += "\nUntested assertions: " + mAssertions.stream().skip(assertionIndex + 1)
+                        .map(assertion -> assertion.name).collect(Collectors.joining(","));
+
+                Result result = new Result(false /* success */, 0 /* timestamp */,
+                        "assertChanges", "Not all assertions passed." + reason);
+                failures.add(result);
+            }
+        }
+        return failures;
+    }
+
+    private List<Result> assertEntry(T entry) {
+        List<Result> failures = new ArrayList<>();
+        for (NamedAssertion<T> assertion : mAssertions) {
+            Result result = assertion.assertion.apply(entry);
+            if (result.failed()) {
+                failures.add(result);
+            }
+        }
+        return failures;
+    }
+
+    private List<Result> assertAll(List<T> entries) {
+        return mAssertions.stream().flatMap(
+                assertion -> entries.stream()
+                        .map(assertion.assertion)
+                        .filter(Result::failed))
+                .collect(Collectors.toList());
+    }
+
+    private enum AssertionOption {
+        NONE,
+        CHECK_CHANGING_ASSERTIONS,
+        CHECK_FIRST_ENTRY,
+        CHECK_LAST_ENTRY,
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java
new file mode 100644
index 0000000..6bac675
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static android.os.SystemClock.sleep;
+import static android.system.helpers.OverviewHelper.isRecentsInLauncher;
+import static android.view.Surface.ROTATION_0;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.launcherhelper.LauncherStrategyFactory;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Configurator;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.util.Log;
+import android.util.Rational;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+/**
+ * Collection of UI Automation helper functions.
+ */
+public class AutomationUtils {
+    private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
+    private static final long FIND_TIMEOUT = 10000;
+    private static final long LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout() * 2L;
+    private static final String TAG = "FLICKER";
+
+    public static void wakeUpAndGoToHomeScreen() {
+        UiDevice device = UiDevice.getInstance(InstrumentationRegistry
+                .getInstrumentation());
+        try {
+            device.wakeUp();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+        device.pressHome();
+    }
+
+    /**
+     * Sets {@link android.app.UiAutomation#waitForIdle(long, long)} global timeout to 0 causing
+     * the {@link android.app.UiAutomation#waitForIdle(long, long)} function to timeout instantly.
+     * This removes some delays when using the UIAutomator library required to create fast UI
+     * transitions.
+     */
+    static void setFastWait() {
+        Configurator.getInstance().setWaitForIdleTimeout(0);
+    }
+
+    /**
+     * Reverts {@link android.app.UiAutomation#waitForIdle(long, long)} to default behavior.
+     */
+    static void setDefaultWait() {
+        Configurator.getInstance().setWaitForIdleTimeout(10000);
+    }
+
+    public static boolean isQuickstepEnabled(UiDevice device) {
+        return device.findObject(By.res(SYSTEMUI_PACKAGE, "recent_apps")) == null;
+    }
+
+    public static void openQuickstep(UiDevice device) {
+        if (isQuickstepEnabled(device)) {
+            int height = device.getDisplayHeight();
+            UiObject2 navBar = device.findObject(By.res(SYSTEMUI_PACKAGE, "navigation_bar_frame"));
+
+            Rect navBarVisibleBounds;
+
+            // TODO(vishnun) investigate why this object cannot be found.
+            if (navBar != null) {
+                navBarVisibleBounds = navBar.getVisibleBounds();
+            } else {
+                Log.e(TAG, "Could not find nav bar, infer location");
+                navBarVisibleBounds = WindowUtils.getNavigationBarPosition(ROTATION_0);
+            }
+
+            // Swipe from nav bar to 2/3rd down the screen.
+            device.swipe(
+                    navBarVisibleBounds.centerX(), navBarVisibleBounds.centerY(),
+                    navBarVisibleBounds.centerX(), height * 2 / 3,
+                    (navBarVisibleBounds.centerY() - height * 2 / 3) / 100); // 100 px/step
+        } else {
+            try {
+                device.pressRecentApps();
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        BySelector RECENTS = By.res(SYSTEMUI_PACKAGE, "recents_view");
+
+        // use a long timeout to wait until recents populated
+        if (device.wait(
+                Until.findObject(isRecentsInLauncher()
+                        ? getLauncherOverviewSelector(device) : RECENTS),
+                10000) == null) {
+            fail("Recents didn't appear");
+        }
+        device.waitForIdle();
+    }
+
+    static void clearRecents(UiDevice device) {
+        if (isQuickstepEnabled(device)) {
+            openQuickstep(device);
+
+            for (int i = 0; i < 5; i++) {
+                device.swipe(device.getDisplayWidth() / 2,
+                        device.getDisplayHeight() / 2, device.getDisplayWidth(),
+                        device.getDisplayHeight() / 2,
+                        5);
+
+                BySelector clearAllSelector = By.res("com.google.android.apps.nexuslauncher",
+                        "clear_all_button");
+                UiObject2 clearAllButton = device.wait(Until.findObject(clearAllSelector), 100);
+                if (clearAllButton != null) {
+                    clearAllButton.click();
+                    return;
+                }
+            }
+        }
+    }
+
+    private static BySelector getLauncherOverviewSelector(UiDevice device) {
+        return By.res(device.getLauncherPackageName(), "overview_panel");
+    }
+
+    private static void longPressRecents(UiDevice device) {
+        BySelector recentsSelector = By.res(SYSTEMUI_PACKAGE, "recent_apps");
+        UiObject2 recentsButton = device.wait(Until.findObject(recentsSelector), FIND_TIMEOUT);
+        assertNotNull("Unable to find recents button", recentsButton);
+        recentsButton.click(LONG_PRESS_TIMEOUT);
+    }
+
+    public static void launchSplitScreen(UiDevice device) {
+        String mLauncherPackage = LauncherStrategyFactory.getInstance(device)
+                .getLauncherStrategy().getSupportedLauncherPackage();
+
+        if (isQuickstepEnabled(device)) {
+            // Quickstep enabled
+            openQuickstep(device);
+
+            BySelector overviewIconSelector = By.res(mLauncherPackage, "icon")
+                    .clazz(View.class);
+            UiObject2 overviewIcon = device.wait(Until.findObject(overviewIconSelector),
+                    FIND_TIMEOUT);
+            assertNotNull("Unable to find app icon in Overview", overviewIcon);
+            overviewIcon.click();
+
+            BySelector splitscreenButtonSelector = By.text("Split screen");
+            UiObject2 splitscreenButton = device.wait(Until.findObject(splitscreenButtonSelector),
+                    FIND_TIMEOUT);
+            assertNotNull("Unable to find Split screen button in Overview", overviewIcon);
+            splitscreenButton.click();
+        } else {
+            // Classic long press recents
+            longPressRecents(device);
+        }
+        // Wait for animation to complete.
+        sleep(2000);
+    }
+
+    public static void exitSplitScreen(UiDevice device) {
+        if (isQuickstepEnabled(device)) {
+            // Quickstep enabled
+            BySelector dividerSelector = By.res(SYSTEMUI_PACKAGE, "docked_divider_handle");
+            UiObject2 divider = device.wait(Until.findObject(dividerSelector), FIND_TIMEOUT);
+            assertNotNull("Unable to find Split screen divider", divider);
+
+            // Drag the split screen divider to the top of the screen
+            divider.drag(new Point(device.getDisplayWidth() / 2, 0), 400);
+        } else {
+            // Classic long press recents
+            longPressRecents(device);
+        }
+        // Wait for animation to complete.
+        sleep(2000);
+    }
+
+    static void resizeSplitScreen(UiDevice device, Rational windowHeightRatio) {
+        BySelector dividerSelector = By.res(SYSTEMUI_PACKAGE, "docked_divider_handle");
+        UiObject2 divider = device.wait(Until.findObject(dividerSelector), FIND_TIMEOUT);
+        assertNotNull("Unable to find Split screen divider", divider);
+        int destHeight =
+                (int) (WindowUtils.getDisplayBounds().height() * windowHeightRatio.floatValue());
+        // Drag the split screen divider to so that the ratio of top window height and bottom
+        // window height is windowHeightRatio
+        device.drag(divider.getVisibleBounds().centerX(), divider.getVisibleBounds().centerY(),
+                device.getDisplayWidth() / 2, destHeight, 10);
+        //divider.drag(new Point(device.getDisplayWidth() / 2, destHeight), 400)
+        divider = device.wait(Until.findObject(dividerSelector), FIND_TIMEOUT);
+
+        // Wait for animation to complete.
+        sleep(2000);
+    }
+
+    static void closePipWindow(UiDevice device) {
+        UiObject2 pipWindow = device.findObject(
+                By.res(SYSTEMUI_PACKAGE, "background"));
+        pipWindow.click();
+        UiObject2 exitPipObject = device.findObject(
+                By.res(SYSTEMUI_PACKAGE, "dismiss"));
+        exitPipObject.click();
+        // Wait for animation to complete.
+        sleep(2000);
+    }
+
+    static void expandPipWindow(UiDevice device) {
+        UiObject2 pipWindow = device.findObject(
+                By.res(SYSTEMUI_PACKAGE, "background"));
+        pipWindow.click();
+        pipWindow.click();
+    }
+
+    public static void stopPackage(Context context, String packageName) {
+        runShellCommand("am force-stop " + packageName);
+        int packageUid;
+        try {
+            packageUid = context.getPackageManager().getPackageUid(packageName, /* flags= */0);
+        } catch (PackageManager.NameNotFoundException e) {
+            return;
+        }
+        while (targetPackageIsRunning(packageUid)) {
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+                //ignore
+            }
+        }
+    }
+
+    private static boolean targetPackageIsRunning(int uid) {
+        final String result = runShellCommand(
+                String.format("cmd activity get-uid-state %d", uid));
+        return !result.contains("(NONEXISTENT)");
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/ITraceEntry.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/ITraceEntry.java
new file mode 100644
index 0000000..9525f41
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/ITraceEntry.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+/**
+ * Common interface for Layer and WindowManager trace entries.
+ */
+interface ITraceEntry {
+    /**
+     * @return timestamp of current entry
+     */
+    long getTimestamp();
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTrace.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTrace.java
new file mode 100644
index 0000000..660ec0f
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTrace.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.surfaceflinger.nano.Layers.LayerProto;
+import android.surfaceflinger.nano.Layers.RectProto;
+import android.surfaceflinger.nano.Layers.RegionProto;
+import android.surfaceflinger.nano.Layerstrace.LayersTraceFileProto;
+import android.surfaceflinger.nano.Layerstrace.LayersTraceProto;
+import android.util.SparseArray;
+
+import com.android.server.wm.flicker.Assertions.Result;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * Contains a collection of parsed Layers trace entries and assertions to apply over
+ * a single entry.
+ *
+ * Each entry is parsed into a list of {@link LayersTrace.Entry} objects.
+ */
+public class LayersTrace {
+    final private List<Entry> mEntries;
+    @Nullable
+    final private Path mSource;
+
+    private LayersTrace(List<Entry> entries, Path source) {
+        this.mEntries = entries;
+        this.mSource = source;
+    }
+
+    /**
+     * Parses {@code LayersTraceFileProto} from {@code data} and uses the proto to generates a list
+     * of trace entries, storing the flattened layers into its hierarchical structure.
+     *
+     * @param data   binary proto data
+     * @param source Path to source of data for additional debug information
+     */
+    static LayersTrace parseFrom(byte[] data, Path source) {
+        List<Entry> entries = new ArrayList<>();
+        LayersTraceFileProto fileProto;
+        try {
+            fileProto = LayersTraceFileProto.parseFrom(data);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        for (LayersTraceProto traceProto : fileProto.entry) {
+            Entry entry = Entry.fromFlattenedLayers(traceProto.elapsedRealtimeNanos,
+                    traceProto.layers.layers);
+            entries.add(entry);
+        }
+        return new LayersTrace(entries, source);
+    }
+
+    /**
+     * Parses {@code LayersTraceFileProto} from {@code data} and uses the proto to generates a list
+     * of trace entries, storing the flattened layers into its hierarchical structure.
+     *
+     * @param data binary proto data
+     */
+    static LayersTrace parseFrom(byte[] data) {
+        return parseFrom(data, null);
+    }
+
+    List<Entry> getEntries() {
+        return mEntries;
+    }
+
+    Entry getEntry(long timestamp) {
+        Optional<Entry> entry = mEntries.stream()
+                .filter(e -> e.getTimestamp() == timestamp)
+                .findFirst();
+        if (!entry.isPresent()) {
+            throw new RuntimeException("Entry does not exist for timestamp " + timestamp);
+        }
+        return entry.get();
+    }
+
+    Optional<Path> getSource() {
+        return Optional.ofNullable(mSource);
+    }
+
+    /**
+     * Represents a single Layer trace entry.
+     */
+    static class Entry implements ITraceEntry {
+        private long mTimestamp;
+        private List<Layer> mRootLayers; // hierarchical representation of layers
+        private List<Layer> mFlattenedLayers = null;
+
+        private Entry(long timestamp, List<Layer> rootLayers) {
+            this.mTimestamp = timestamp;
+            this.mRootLayers = rootLayers;
+        }
+
+        /**
+         * Constructs the layer hierarchy from a flattened list of layers.
+         */
+        static Entry fromFlattenedLayers(long timestamp, LayerProto[] protos) {
+            SparseArray<Layer> layerMap = new SparseArray<>();
+            ArrayList<Layer> orphans = new ArrayList<>();
+            for (LayerProto proto : protos) {
+                int id = proto.id;
+                int parentId = proto.parent;
+
+                Layer newLayer = layerMap.get(id);
+                if (newLayer == null) {
+                    newLayer = new Layer(proto);
+                    layerMap.append(id, newLayer);
+                } else if (newLayer.mProto != null) {
+                    throw new RuntimeException("Duplicate layer id found:" + id);
+                } else {
+                    newLayer.mProto = proto;
+                    orphans.remove(newLayer);
+                }
+
+                // add parent placeholder
+                if (layerMap.get(parentId) == null) {
+                    Layer orphanLayer = new Layer(null);
+                    layerMap.append(parentId, orphanLayer);
+                    orphans.add(orphanLayer);
+                }
+                layerMap.get(parentId).addChild(newLayer);
+                newLayer.addParent(layerMap.get(parentId));
+            }
+
+            // Fail if we find orphan layers.
+            orphans.remove(layerMap.get(-1));
+            orphans.forEach(orphan -> {
+                String childNodes = orphan.mChildren.stream().map(node ->
+                        Integer.toString(node.getId())).collect(Collectors.joining(", "));
+                int orphanId = orphan.mChildren.get(0).mProto.parent;
+                throw new RuntimeException(
+                        "Failed to parse layers trace. Found orphan layers with parent "
+                                + "layer id:" + orphanId + " : " + childNodes);
+            });
+
+            return new Entry(timestamp, layerMap.get(-1).mChildren);
+        }
+
+        /**
+         * Extracts {@link Rect} from {@link RectProto}.
+         */
+        private static Rect extract(RectProto proto) {
+            return new Rect(proto.left, proto.top, proto.right, proto.bottom);
+        }
+
+        /**
+         * Extracts {@link Rect} from {@link RegionProto} by returning a rect that encompasses all
+         * the rects making up the region.
+         */
+        private static Rect extract(RegionProto regionProto) {
+            Rect region = new Rect();
+            for (RectProto proto : regionProto.rect) {
+                region.union(proto.left, proto.top, proto.right, proto.bottom);
+            }
+            return region;
+        }
+
+        /**
+         * Checks if a region specified by {@code testRect} is covered by all visible layers.
+         */
+        Result coversRegion(Rect testRect) {
+            String assertionName = "coversRegion";
+            Collection<Layer> layers = asFlattenedLayers();
+
+            for (int x = testRect.left; x < testRect.right; x++) {
+                for (int y = testRect.top; y < testRect.bottom; y++) {
+                    boolean emptyRegionFound = true;
+                    for (Layer layer : layers) {
+                        if (layer.isInvisible() || layer.isHiddenByParent()) {
+                            continue;
+                        }
+                        for (RectProto rectProto : layer.mProto.visibleRegion.rect) {
+                            Rect r = extract(rectProto);
+                            if (r.contains(x, y)) {
+                                y = r.bottom;
+                                emptyRegionFound = false;
+                            }
+                        }
+                    }
+                    if (emptyRegionFound) {
+                        String reason = "Region to test: " + testRect
+                                + "\nfirst empty point: " + x + ", " + y;
+                        reason += "\nvisible regions:";
+                        for (Layer layer : layers) {
+                            if (layer.isInvisible() || layer.isHiddenByParent()) {
+                                continue;
+                            }
+                            Rect r = extract(layer.mProto.visibleRegion);
+                            reason += "\n" + layer.mProto.name + r.toString();
+                        }
+                        return new Result(false /* success */, this.mTimestamp, assertionName,
+                                reason);
+                    }
+                }
+            }
+            String info = "Region covered: " + testRect;
+            return new Result(true /* success */, this.mTimestamp, assertionName, info);
+        }
+
+        /**
+         * Checks if a layer with name {@code layerName} has a visible region
+         * {@code expectedVisibleRegion}.
+         */
+        Result hasVisibleRegion(String layerName, Rect expectedVisibleRegion) {
+            String assertionName = "hasVisibleRegion";
+            String reason = "Could not find " + layerName;
+            for (Layer layer : asFlattenedLayers()) {
+                if (layer.mProto.name.contains(layerName)) {
+                    if (layer.isHiddenByParent()) {
+                        reason = layer.getHiddenByParentReason();
+                        continue;
+                    }
+                    if (layer.isInvisible()) {
+                        reason = layer.getVisibilityReason();
+                        continue;
+                    }
+                    Rect visibleRegion = extract(layer.mProto.visibleRegion);
+                    if (visibleRegion.equals(expectedVisibleRegion)) {
+                        return new Result(true /* success */, this.mTimestamp, assertionName,
+                                layer.mProto.name + "has visible region " + expectedVisibleRegion);
+                    }
+                    reason = layer.mProto.name + " has visible region:" + visibleRegion + " "
+                            + "expected:" + expectedVisibleRegion;
+                }
+            }
+            return new Result(false /* success */, this.mTimestamp, assertionName, reason);
+        }
+
+        /**
+         * Checks if a layer with name {@code layerName} is visible.
+         */
+        Result isVisible(String layerName) {
+            String assertionName = "isVisible";
+            String reason = "Could not find " + layerName;
+            for (Layer layer : asFlattenedLayers()) {
+                if (layer.mProto.name.contains(layerName)) {
+                    if (layer.isHiddenByParent()) {
+                        reason = layer.getHiddenByParentReason();
+                        continue;
+                    }
+                    if (layer.isInvisible()) {
+                        reason = layer.getVisibilityReason();
+                        continue;
+                    }
+                    return new Result(true /* success */, this.mTimestamp, assertionName,
+                            layer.mProto.name + " is visible");
+                }
+            }
+            return new Result(false /* success */, this.mTimestamp, assertionName, reason);
+        }
+
+        @Override
+        public long getTimestamp() {
+            return mTimestamp;
+        }
+
+        List<Layer> getRootLayers() {
+            return mRootLayers;
+        }
+
+        List<Layer> asFlattenedLayers() {
+            if (mFlattenedLayers == null) {
+                mFlattenedLayers = new ArrayList<>();
+                ArrayList<Layer> pendingLayers = new ArrayList<>(this.mRootLayers);
+                while (!pendingLayers.isEmpty()) {
+                    Layer layer = pendingLayers.remove(0);
+                    mFlattenedLayers.add(layer);
+                    pendingLayers.addAll(layer.mChildren);
+                }
+            }
+            return mFlattenedLayers;
+        }
+
+        Rect getVisibleBounds(String layerName) {
+            List<Layer> layers = asFlattenedLayers();
+            for (Layer layer : layers) {
+                if (layer.mProto.name.contains(layerName) && layer.isVisible()) {
+                    return extract(layer.mProto.visibleRegion);
+                }
+            }
+            return new Rect(0, 0, 0, 0);
+        }
+    }
+
+    /**
+     * Represents a single layer with links to its parent and child layers.
+     */
+    static class Layer {
+        @Nullable
+        LayerProto mProto;
+        List<Layer> mChildren;
+        @Nullable
+        Layer mParent = null;
+
+        private Layer(LayerProto proto) {
+            this.mProto = proto;
+            this.mChildren = new ArrayList<>();
+        }
+
+        private void addChild(Layer childLayer) {
+            this.mChildren.add(childLayer);
+        }
+
+        private void addParent(Layer parentLayer) {
+            this.mParent = parentLayer;
+        }
+
+        int getId() {
+            return mProto.id;
+        }
+
+        boolean isActiveBufferEmpty() {
+            return this.mProto.activeBuffer == null || this.mProto.activeBuffer.height == 0
+                    || this.mProto.activeBuffer.width == 0;
+        }
+
+        boolean isVisibleRegionEmpty() {
+            if (this.mProto.visibleRegion == null) {
+                return true;
+            }
+            Rect visibleRect = Entry.extract(this.mProto.visibleRegion);
+            return visibleRect.height() == 0 || visibleRect.width() == 0;
+        }
+
+        boolean isHidden() {
+            return (this.mProto.flags & /* FLAG_HIDDEN */ 0x1) != 0x0;
+        }
+
+        boolean isVisible() {
+            return (!isActiveBufferEmpty() || isColorLayer()) &&
+                    !isHidden() && this.mProto.color.a > 0 && !isVisibleRegionEmpty();
+        }
+
+        boolean isColorLayer() {
+            return this.mProto.type.equals("ColorLayer");
+        }
+
+        boolean isRootLayer() {
+            return mParent == null || mParent.mProto == null;
+        }
+
+        boolean isInvisible() {
+            return !isVisible();
+        }
+
+        boolean isHiddenByParent() {
+            return !isRootLayer() && (mParent.isHidden() || mParent.isHiddenByParent());
+        }
+
+        String getHiddenByParentReason() {
+            String reason = "Layer " + mProto.name;
+            if (isHiddenByParent()) {
+                reason += " is hidden by parent: " + mParent.mProto.name;
+            } else {
+                reason += " is not hidden by parent: " + mParent.mProto.name;
+            }
+            return reason;
+        }
+
+        String getVisibilityReason() {
+            String reason = "Layer " + mProto.name;
+            if (isVisible()) {
+                reason += " is visible:";
+            } else {
+                reason += " is invisible:";
+                if (this.mProto.activeBuffer == null) {
+                    reason += " activeBuffer=null";
+                } else if (this.mProto.activeBuffer.height == 0) {
+                    reason += " activeBuffer.height=0";
+                } else if (this.mProto.activeBuffer.width == 0) {
+                    reason += " activeBuffer.width=0";
+                }
+                if (!isColorLayer()) {
+                    reason += " type != ColorLayer";
+                }
+                if (isHidden()) {
+                    reason += " flags=" + this.mProto.flags + " (FLAG_HIDDEN set)";
+                }
+                if (this.mProto.color.a == 0) {
+                    reason += " color.a=0";
+                }
+                if (isVisibleRegionEmpty()) {
+                    reason += " visible region is empty";
+                }
+            }
+            return reason;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTraceSubject.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTraceSubject.java
new file mode 100644
index 0000000..b4c97e4
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/LayersTraceSubject.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.google.common.truth.Truth.assertAbout;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.annotation.Nullable;
+import android.graphics.Rect;
+
+import com.android.server.wm.flicker.Assertions.Result;
+import com.android.server.wm.flicker.LayersTrace.Entry;
+import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
+
+import com.google.common.truth.FailureStrategy;
+import com.google.common.truth.Subject;
+import com.google.common.truth.SubjectFactory;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Truth subject for {@link LayersTrace} objects.
+ */
+public class LayersTraceSubject extends Subject<LayersTraceSubject, LayersTrace> {
+    // Boiler-plate Subject.Factory for LayersTraceSubject
+    private static final SubjectFactory<LayersTraceSubject, LayersTrace> FACTORY =
+            new SubjectFactory<LayersTraceSubject, LayersTrace>() {
+                @Override
+                public LayersTraceSubject getSubject(
+                        FailureStrategy fs, @Nullable LayersTrace target) {
+                    return new LayersTraceSubject(fs, target);
+                }
+            };
+
+    private AssertionsChecker<Entry> mChecker = new AssertionsChecker<>();
+
+    private LayersTraceSubject(FailureStrategy fs, @Nullable LayersTrace subject) {
+        super(fs, subject);
+    }
+
+    // User-defined entry point
+    public static LayersTraceSubject assertThat(@Nullable LayersTrace entry) {
+        return assertAbout(FACTORY).that(entry);
+    }
+
+    // User-defined entry point
+    public static LayersTraceSubject assertThat(@Nullable TransitionResult result) {
+        LayersTrace entries = LayersTrace.parseFrom(result.getLayersTrace(),
+                result.getLayersTracePath());
+        return assertWithMessage(result.toString()).about(FACTORY).that(entries);
+    }
+
+    // Static method for getting the subject factory (for use with assertAbout())
+    public static SubjectFactory<LayersTraceSubject, LayersTrace> entries() {
+        return FACTORY;
+    }
+
+    public void forAllEntries() {
+        test();
+    }
+
+    public void forRange(long startTime, long endTime) {
+        mChecker.filterByRange(startTime, endTime);
+        test();
+    }
+
+    public LayersTraceSubject then() {
+        mChecker.checkChangingAssertions();
+        return this;
+    }
+
+    public void inTheBeginning() {
+        if (getSubject().getEntries().isEmpty()) {
+            fail("No entries found.");
+        }
+        mChecker.checkFirstEntry();
+        test();
+    }
+
+    public void atTheEnd() {
+        if (getSubject().getEntries().isEmpty()) {
+            fail("No entries found.");
+        }
+        mChecker.checkLastEntry();
+        test();
+    }
+
+    private void test() {
+        List<Result> failures = mChecker.test(getSubject().getEntries());
+        if (!failures.isEmpty()) {
+            String failureLogs = failures.stream().map(Result::toString)
+                    .collect(Collectors.joining("\n"));
+            String tracePath = "";
+            if (getSubject().getSource().isPresent()) {
+                tracePath = "\nLayers Trace can be found in: "
+                        + getSubject().getSource().get().toAbsolutePath() + "\n";
+            }
+            fail(tracePath + failureLogs);
+        }
+    }
+
+    public LayersTraceSubject coversRegion(Rect rect) {
+        mChecker.add(entry -> entry.coversRegion(rect),
+                "coversRegion(" + rect + ")");
+        return this;
+    }
+
+    public LayersTraceSubject hasVisibleRegion(String layerName, Rect size) {
+        mChecker.add(entry -> entry.hasVisibleRegion(layerName, size),
+                "hasVisibleRegion(" + layerName + size + ")");
+        return this;
+    }
+
+    public LayersTraceSubject showsLayer(String layerName) {
+        mChecker.add(entry -> entry.isVisible(layerName),
+                "showsLayer(" + layerName + ")");
+        return this;
+    }
+
+    public LayersTraceSubject hidesLayer(String layerName) {
+        mChecker.add(entry -> entry.isVisible(layerName).negate(),
+                "hidesLayer(" + layerName + ")");
+        return this;
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java
new file mode 100644
index 0000000..f6e8192
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import android.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.support.test.InstrumentationRegistry;
+import android.util.Log;
+
+import com.android.server.wm.flicker.monitor.ITransitionMonitor;
+import com.android.server.wm.flicker.monitor.LayersTraceMonitor;
+import com.android.server.wm.flicker.monitor.ScreenRecorder;
+import com.android.server.wm.flicker.monitor.WindowAnimationFrameStatsMonitor;
+import com.android.server.wm.flicker.monitor.WindowManagerTraceMonitor;
+
+import com.google.common.io.Files;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Builds and runs UI transitions capturing test artifacts.
+ *
+ * User can compose a transition from simpler steps, specifying setup and teardown steps. During
+ * a transition, Layers trace, WindowManager trace, screen recordings and window animation frame
+ * stats can be captured.
+ *
+ * <pre>
+ * Transition builder options:
+ *  {@link TransitionBuilder#run(Runnable)} run transition under test. Monitors will be started
+ *  before the transition and stopped after the transition is completed.
+ *  {@link TransitionBuilder#repeat(int)} repeat transitions under test multiple times recording
+ *  result for each run.
+ *  {@link TransitionBuilder#withTag(String)} specify a string identifier used to prefix logs and
+ *  artifacts generated.
+ *  {@link TransitionBuilder#runBeforeAll(Runnable)} run setup transitions once before all other
+ *  transition are run to set up an initial state on device.
+ *  {@link TransitionBuilder#runBefore(Runnable)} run setup transitions before each test transition
+ *  run.
+ *  {@link TransitionBuilder#runAfter(Runnable)} run teardown transitions after each test
+ *  transition.
+ *  {@link TransitionBuilder#runAfter(Runnable)} run teardown transitions once after all
+ *  other transition  are run.
+ *  {@link TransitionBuilder#includeJankyRuns()} disables {@link WindowAnimationFrameStatsMonitor}
+ *  to monitor janky frames. If janky frames are detected, then the test run is skipped. This
+ *  monitor is enabled by default.
+ *  {@link TransitionBuilder#skipLayersTrace()} disables {@link LayersTraceMonitor} used to
+ *  capture Layers trace during a transition. This monitor is enabled by default.
+ *  {@link TransitionBuilder#skipWindowManagerTrace()} disables {@link WindowManagerTraceMonitor}
+ *  used to capture WindowManager trace during a transition. This monitor is enabled by
+ *  default.
+ *  {@link TransitionBuilder#recordAllRuns()} records the screen contents and saves it to a file.
+ *  All the runs including setup and teardown transitions are included in the recording. This
+ *  monitor is used for debugging purposes.
+ *  {@link TransitionBuilder#recordEachRun()} records the screen contents during test transitions
+ *  and saves it to a file for each run. This monitor is used for debugging purposes.
+ *
+ * Example transition to capture WindowManager and Layers trace when opening a test app:
+ * {@code
+ * TransitionRunner.newBuilder()
+ *      .withTag("OpenTestAppFast")
+ *      .runBeforeAll(UiAutomationLib::wakeUp)
+ *      .runBeforeAll(UiAutomationLib::UnlockDevice)
+ *      .runBeforeAll(UiAutomationLib::openTestApp)
+ *      .runBefore(UiAutomationLib::closeTestApp)
+ *      .run(UiAutomationLib::openTestApp)
+ *      .runAfterAll(UiAutomationLib::closeTestApp)
+ *      .repeat(5)
+ *      .build()
+ *      .run();
+ * }
+ * </pre>
+ */
+class TransitionRunner {
+    private static final String TAG = "FLICKER";
+    private final ScreenRecorder mScreenRecorder;
+    private final WindowManagerTraceMonitor mWmTraceMonitor;
+    private final LayersTraceMonitor mLayersTraceMonitor;
+    private final WindowAnimationFrameStatsMonitor mFrameStatsMonitor;
+
+    private final List<ITransitionMonitor> mAllRunsMonitors;
+    private final List<ITransitionMonitor> mPerRunMonitors;
+    private final List<Runnable> mBeforeAlls;
+    private final List<Runnable> mBefores;
+    private final List<Runnable> mTransitions;
+    private final List<Runnable> mAfters;
+    private final List<Runnable> mAfterAlls;
+
+    private final int mIterations;
+    private final String mTestTag;
+
+    @Nullable
+    private List<TransitionResult> mResults = null;
+
+    private TransitionRunner(TransitionBuilder builder) {
+        mScreenRecorder = builder.mScreenRecorder;
+        mWmTraceMonitor = builder.mWmTraceMonitor;
+        mLayersTraceMonitor = builder.mLayersTraceMonitor;
+        mFrameStatsMonitor = builder.mFrameStatsMonitor;
+
+        mAllRunsMonitors = builder.mAllRunsMonitors;
+        mPerRunMonitors = builder.mPerRunMonitors;
+        mBeforeAlls = builder.mBeforeAlls;
+        mBefores = builder.mBefores;
+        mTransitions = builder.mTransitions;
+        mAfters = builder.mAfters;
+        mAfterAlls = builder.mAfterAlls;
+
+        mIterations = builder.mIterations;
+        mTestTag = builder.mTestTag;
+    }
+
+    static TransitionBuilder newBuilder() {
+        return new TransitionBuilder();
+    }
+
+    /**
+     * Runs the composed transition and calls monitors at the appropriate stages. If jank monitor
+     * is enabled, transitions with jank are skipped.
+     *
+     * @return itself
+     */
+    TransitionRunner run() {
+        mResults = new ArrayList<>();
+        mAllRunsMonitors.forEach(ITransitionMonitor::start);
+        mBeforeAlls.forEach(Runnable::run);
+        for (int iteration = 0; iteration < mIterations; iteration++) {
+            mBefores.forEach(Runnable::run);
+            mPerRunMonitors.forEach(ITransitionMonitor::start);
+            mTransitions.forEach(Runnable::run);
+            mPerRunMonitors.forEach(ITransitionMonitor::stop);
+            mAfters.forEach(Runnable::run);
+            if (runJankFree() && mFrameStatsMonitor.jankyFramesDetected()) {
+                String msg = String.format("Skipping iteration %d/%d for test %s due to jank. %s",
+                        iteration, mIterations - 1, mTestTag, mFrameStatsMonitor.toString());
+                Log.e(TAG, msg);
+                continue;
+            }
+            mResults.add(saveResult(iteration));
+        }
+        mAfterAlls.forEach(Runnable::run);
+        mAllRunsMonitors.forEach(monitor -> {
+            monitor.stop();
+            Path path = monitor.save(mTestTag);
+            Log.e(TAG, "Video saved to " + path.toString());
+        });
+        return this;
+    }
+
+    /**
+     * Returns a list of transition results.
+     *
+     * @return list of transition results.
+     */
+    List<TransitionResult> getResults() {
+        if (mResults == null) {
+            throw new IllegalStateException("Results do not exist!");
+        }
+        return mResults;
+    }
+
+    /**
+     * Deletes all transition results that are not marked for saving.
+     *
+     * @return list of transition results.
+     */
+    void deleteResults() {
+        if (mResults == null) {
+            return;
+        }
+        mResults.stream()
+                .filter(TransitionResult::canDelete)
+                .forEach(TransitionResult::delete);
+        mResults = null;
+    }
+
+    /**
+     * Saves monitor results to file.
+     *
+     * @return object containing paths to test artifacts
+     */
+    private TransitionResult saveResult(int iteration) {
+        Path windowTrace = null;
+        Path layerTrace = null;
+        Path screenCaptureVideo = null;
+
+        if (mPerRunMonitors.contains(mWmTraceMonitor)) {
+            windowTrace = mWmTraceMonitor.save(mTestTag, iteration);
+        }
+        if (mPerRunMonitors.contains(mLayersTraceMonitor)) {
+            layerTrace = mLayersTraceMonitor.save(mTestTag, iteration);
+        }
+        if (mPerRunMonitors.contains(mScreenRecorder)) {
+            screenCaptureVideo = mScreenRecorder.save(mTestTag, iteration);
+        }
+        return new TransitionResult(layerTrace, windowTrace, screenCaptureVideo);
+    }
+
+    private boolean runJankFree() {
+        return mPerRunMonitors.contains(mFrameStatsMonitor);
+    }
+
+    public String getTestTag() {
+        return mTestTag;
+    }
+
+    /**
+     * Stores paths to all test artifacts.
+     */
+    @VisibleForTesting
+    public static class TransitionResult {
+        @Nullable
+        final Path layersTrace;
+        @Nullable
+        final Path windowManagerTrace;
+        @Nullable
+        final Path screenCaptureVideo;
+        private boolean flaggedForSaving;
+
+        TransitionResult(@Nullable Path layersTrace, @Nullable Path windowManagerTrace,
+                @Nullable Path screenCaptureVideo) {
+            this.layersTrace = layersTrace;
+            this.windowManagerTrace = windowManagerTrace;
+            this.screenCaptureVideo = screenCaptureVideo;
+        }
+
+        void flagForSaving() {
+            flaggedForSaving = true;
+        }
+
+        boolean canDelete() {
+            return !flaggedForSaving;
+        }
+
+        boolean layersTraceExists() {
+            return layersTrace != null && layersTrace.toFile().exists();
+        }
+
+        byte[] getLayersTrace() {
+            try {
+                return Files.toByteArray(this.layersTrace.toFile());
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        Path getLayersTracePath() {
+            return layersTrace;
+        }
+
+        boolean windowManagerTraceExists() {
+            return windowManagerTrace != null && windowManagerTrace.toFile().exists();
+        }
+
+        public byte[] getWindowManagerTrace() {
+            try {
+                return Files.toByteArray(this.windowManagerTrace.toFile());
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        Path getWindowManagerTracePath() {
+            return windowManagerTrace;
+        }
+
+        boolean screenCaptureVideoExists() {
+            return screenCaptureVideo != null && screenCaptureVideo.toFile().exists();
+        }
+
+        Path screenCaptureVideoPath() {
+            return screenCaptureVideo;
+        }
+
+        void delete() {
+            if (layersTraceExists()) layersTrace.toFile().delete();
+            if (windowManagerTraceExists()) windowManagerTrace.toFile().delete();
+            if (screenCaptureVideoExists()) screenCaptureVideo.toFile().delete();
+        }
+    }
+
+    /**
+     * Builds a {@link TransitionRunner} instance.
+     */
+    static class TransitionBuilder {
+        private ScreenRecorder mScreenRecorder;
+        private WindowManagerTraceMonitor mWmTraceMonitor;
+        private LayersTraceMonitor mLayersTraceMonitor;
+        private WindowAnimationFrameStatsMonitor mFrameStatsMonitor;
+
+        private List<ITransitionMonitor> mAllRunsMonitors = new LinkedList<>();
+        private List<ITransitionMonitor> mPerRunMonitors = new LinkedList<>();
+        private List<Runnable> mBeforeAlls = new LinkedList<>();
+        private List<Runnable> mBefores = new LinkedList<>();
+        private List<Runnable> mTransitions = new LinkedList<>();
+        private List<Runnable> mAfters = new LinkedList<>();
+        private List<Runnable> mAfterAlls = new LinkedList<>();
+
+        private boolean mRunJankFree = true;
+        private boolean mCaptureWindowManagerTrace = true;
+        private boolean mCaptureLayersTrace = true;
+        private boolean mRecordEachRun = false;
+        private int mIterations = 1;
+        private String mTestTag = "";
+
+        private boolean mRecordAllRuns = false;
+
+        TransitionBuilder() {
+            mScreenRecorder = new ScreenRecorder();
+            mWmTraceMonitor = new WindowManagerTraceMonitor();
+            mLayersTraceMonitor = new LayersTraceMonitor();
+            mFrameStatsMonitor = new
+                    WindowAnimationFrameStatsMonitor(InstrumentationRegistry.getInstrumentation());
+        }
+
+        TransitionRunner build() {
+            if (mCaptureWindowManagerTrace) {
+                mPerRunMonitors.add(mWmTraceMonitor);
+            }
+
+            if (mCaptureLayersTrace) {
+                mPerRunMonitors.add(mLayersTraceMonitor);
+            }
+
+            if (mRunJankFree) {
+                mPerRunMonitors.add(mFrameStatsMonitor);
+            }
+
+            if (mRecordAllRuns) {
+                mAllRunsMonitors.add(mScreenRecorder);
+            }
+
+            if (mRecordEachRun) {
+                mPerRunMonitors.add(mScreenRecorder);
+            }
+
+            return new TransitionRunner(this);
+        }
+
+        TransitionBuilder runBeforeAll(Runnable runnable) {
+            mBeforeAlls.add(runnable);
+            return this;
+        }
+
+        TransitionBuilder runBefore(Runnable runnable) {
+            mBefores.add(runnable);
+            return this;
+        }
+
+        TransitionBuilder run(Runnable runnable) {
+            mTransitions.add(runnable);
+            return this;
+        }
+
+        TransitionBuilder runAfter(Runnable runnable) {
+            mAfters.add(runnable);
+            return this;
+        }
+
+        TransitionBuilder runAfterAll(Runnable runnable) {
+            mAfterAlls.add(runnable);
+            return this;
+        }
+
+        TransitionBuilder repeat(int iterations) {
+            mIterations = iterations;
+            return this;
+        }
+
+        TransitionBuilder skipWindowManagerTrace() {
+            mCaptureWindowManagerTrace = false;
+            return this;
+        }
+
+        TransitionBuilder skipLayersTrace() {
+            mCaptureLayersTrace = false;
+            return this;
+        }
+
+        TransitionBuilder includeJankyRuns() {
+            mRunJankFree = false;
+            return this;
+        }
+
+        TransitionBuilder recordEachRun() {
+            if (mRecordAllRuns) {
+                throw new IllegalArgumentException("Invalid option with recordAllRuns");
+            }
+            mRecordEachRun = true;
+            return this;
+        }
+
+        TransitionBuilder recordAllRuns() {
+            if (mRecordEachRun) {
+                throw new IllegalArgumentException("Invalid option with recordEachRun");
+            }
+            mRecordAllRuns = true;
+            return this;
+        }
+
+        TransitionBuilder withTag(String testTag) {
+            mTestTag = testTag;
+            return this;
+        }
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowManagerTrace.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowManagerTrace.java
new file mode 100644
index 0000000..e3592eb
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowManagerTrace.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import android.annotation.Nullable;
+
+import com.android.server.wm.flicker.Assertions.Result;
+import com.android.server.wm.nano.AppWindowTokenProto;
+import com.android.server.wm.nano.StackProto;
+import com.android.server.wm.nano.TaskProto;
+import com.android.server.wm.nano.WindowManagerTraceFileProto;
+import com.android.server.wm.nano.WindowManagerTraceProto;
+import com.android.server.wm.nano.WindowStateProto;
+import com.android.server.wm.nano.WindowTokenProto;
+
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Contains a collection of parsed WindowManager trace entries and assertions to apply over
+ * a single entry.
+ *
+ * Each entry is parsed into a list of {@link WindowManagerTrace.Entry} objects.
+ */
+public class WindowManagerTrace {
+    private static final int DEFAULT_DISPLAY = 0;
+    private final List<Entry> mEntries;
+    @Nullable
+    final private Path mSource;
+
+    private WindowManagerTrace(List<Entry> entries, Path source) {
+        this.mEntries = entries;
+        this.mSource = source;
+    }
+
+    /**
+     * Parses {@code WindowManagerTraceFileProto} from {@code data} and uses the proto to
+     * generates a list of trace entries.
+     *
+     * @param data   binary proto data
+     * @param source Path to source of data for additional debug information
+     */
+    static WindowManagerTrace parseFrom(byte[] data, Path source) {
+        List<Entry> entries = new ArrayList<>();
+
+        WindowManagerTraceFileProto fileProto;
+        try {
+            fileProto = WindowManagerTraceFileProto.parseFrom(data);
+        } catch (InvalidProtocolBufferNanoException e) {
+            throw new RuntimeException(e);
+        }
+        for (WindowManagerTraceProto entryProto : fileProto.entry) {
+            entries.add(new Entry(entryProto));
+        }
+        return new WindowManagerTrace(entries, source);
+    }
+
+    static WindowManagerTrace parseFrom(byte[] data) {
+        return parseFrom(data, null);
+    }
+
+    public List<Entry> getEntries() {
+        return mEntries;
+    }
+
+    Entry getEntry(long timestamp) {
+        Optional<Entry> entry = mEntries.stream()
+                .filter(e -> e.getTimestamp() == timestamp)
+                .findFirst();
+        if (!entry.isPresent()) {
+            throw new RuntimeException("Entry does not exist for timestamp " + timestamp);
+        }
+        return entry.get();
+    }
+
+    Optional<Path> getSource() {
+        return Optional.ofNullable(mSource);
+    }
+
+    /**
+     * Represents a single WindowManager trace entry.
+     */
+    static class Entry implements ITraceEntry {
+        private final WindowManagerTraceProto mProto;
+
+        Entry(WindowManagerTraceProto proto) {
+            mProto = proto;
+        }
+
+        private static Result isWindowVisible(String windowTitle,
+                WindowTokenProto[] windowTokenProtos) {
+            boolean titleFound = false;
+            for (WindowTokenProto windowToken : windowTokenProtos) {
+                for (WindowStateProto windowState : windowToken.windows) {
+                    if (windowState.identifier.title.contains(windowTitle)) {
+                        titleFound = true;
+                        if (isVisible(windowState)) {
+                            return new Result(true /* success */,
+                                    windowState.identifier.title + " is visible");
+                        }
+                    }
+                }
+            }
+
+            String reason;
+            if (!titleFound) {
+                reason = windowTitle + " cannot be found";
+            } else {
+                reason = windowTitle + " is invisible";
+            }
+            return new Result(false /* success */, reason);
+        }
+
+        private static boolean isVisible(WindowStateProto windowState) {
+            return windowState.windowContainer.visible;
+        }
+
+        @Override
+        public long getTimestamp() {
+            return mProto.elapsedRealtimeNanos;
+        }
+
+        /**
+         * Returns window title of the top most visible app window.
+         */
+        private String getTopVisibleAppWindow() {
+            StackProto[] stacks = mProto.windowManagerService.rootWindowContainer
+                    .displays[DEFAULT_DISPLAY].stacks;
+            for (StackProto stack : stacks) {
+                for (TaskProto task : stack.tasks) {
+                    for (AppWindowTokenProto token : task.appWindowTokens) {
+                        for (WindowStateProto windowState : token.windowToken.windows) {
+                            if (windowState.windowContainer.visible) {
+                                return task.appWindowTokens[0].name;
+                            }
+                        }
+                    }
+                }
+            }
+
+            return "";
+        }
+
+        /**
+         * Checks if aboveAppWindow with {@code windowTitle} is visible.
+         */
+        Result isAboveAppWindowVisible(String windowTitle) {
+            WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
+                    .rootWindowContainer
+                    .displays[DEFAULT_DISPLAY].aboveAppWindows;
+            Result result = isWindowVisible(windowTitle, windowTokenProtos);
+            return new Result(result.success, getTimestamp(), "showsAboveAppWindow", result.reason);
+        }
+
+        /**
+         * Checks if belowAppWindow with {@code windowTitle} is visible.
+         */
+        Result isBelowAppWindowVisible(String windowTitle) {
+            WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
+                    .rootWindowContainer
+                    .displays[DEFAULT_DISPLAY].belowAppWindows;
+            Result result = isWindowVisible(windowTitle, windowTokenProtos);
+            return new Result(result.success, getTimestamp(), "isBelowAppWindowVisible",
+                    result.reason);
+        }
+
+        /**
+         * Checks if imeWindow with {@code windowTitle} is visible.
+         */
+        Result isImeWindowVisible(String windowTitle) {
+            WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
+                    .rootWindowContainer
+                    .displays[DEFAULT_DISPLAY].imeWindows;
+            Result result = isWindowVisible(windowTitle, windowTokenProtos);
+            return new Result(result.success, getTimestamp(), "isImeWindowVisible",
+                    result.reason);
+        }
+
+        /**
+         * Checks if app window with {@code windowTitle} is on top.
+         */
+        Result isVisibleAppWindowOnTop(String windowTitle) {
+            String topAppWindow = getTopVisibleAppWindow();
+            boolean success = topAppWindow.contains(windowTitle);
+            String reason = "wanted=" + windowTitle + " found=" + topAppWindow;
+            return new Result(success, getTimestamp(), "isAppWindowOnTop", reason);
+        }
+
+        /**
+         * Checks if app window with {@code windowTitle} is visible.
+         */
+        Result isAppWindowVisible(String windowTitle) {
+            final String assertionName = "isAppWindowVisible";
+            boolean titleFound = false;
+            StackProto[] stacks = mProto.windowManagerService.rootWindowContainer
+                    .displays[DEFAULT_DISPLAY].stacks;
+            for (StackProto stack : stacks) {
+                for (TaskProto task : stack.tasks) {
+                    for (AppWindowTokenProto token : task.appWindowTokens) {
+                        if (token.name.contains(windowTitle)) {
+                            titleFound = true;
+                            for (WindowStateProto windowState : token.windowToken.windows) {
+                                if (windowState.windowContainer.visible) {
+                                    return new Result(true /* success */, getTimestamp(),
+                                            assertionName, "Window " + token.name +
+                                            "is visible");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            String reason;
+            if (!titleFound) {
+                reason = "Window " + windowTitle + " cannot be found";
+            } else {
+                reason = "Window " + windowTitle + " is invisible";
+            }
+            return new Result(false /* success */, getTimestamp(), assertionName, reason);
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java
new file mode 100644
index 0000000..0da8761
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.support.test.InstrumentationRegistry;
+import android.view.Surface;
+import android.view.WindowManager;
+
+/**
+ * Helper functions to retrieve system window sizes and positions.
+ */
+class WindowUtils {
+
+    static Rect getDisplayBounds() {
+        Point display = new Point();
+        WindowManager wm =
+                (WindowManager) InstrumentationRegistry.getContext().getSystemService(
+                        Context.WINDOW_SERVICE);
+        wm.getDefaultDisplay().getRealSize(display);
+        return new Rect(0, 0, display.x, display.y);
+    }
+
+    private static int getCurrentRotation() {
+        WindowManager wm =
+                (WindowManager) InstrumentationRegistry.getContext().getSystemService(
+                        Context.WINDOW_SERVICE);
+        return wm.getDefaultDisplay().getRotation();
+    }
+
+    static Rect getDisplayBounds(int requestedRotation) {
+        Rect displayBounds = getDisplayBounds();
+        int currentDisplayRotation = getCurrentRotation();
+
+        boolean displayIsRotated = (currentDisplayRotation == Surface.ROTATION_90 ||
+                currentDisplayRotation == Surface.ROTATION_270);
+
+        boolean requestedDisplayIsRotated = requestedRotation == Surface.ROTATION_90 ||
+                requestedRotation == Surface.ROTATION_270;
+
+        // if the current orientation changes with the requested rotation,
+        // flip height and width of display bounds.
+        if (displayIsRotated != requestedDisplayIsRotated) {
+            return new Rect(0, 0, displayBounds.height(), displayBounds.width());
+        }
+
+        return new Rect(0, 0, displayBounds.width(), displayBounds.height());
+    }
+
+
+    static Rect getAppPosition(int requestedRotation) {
+        Rect displayBounds = getDisplayBounds();
+        int currentDisplayRotation = getCurrentRotation();
+
+        boolean displayIsRotated = currentDisplayRotation == Surface.ROTATION_90 ||
+                currentDisplayRotation == Surface.ROTATION_270;
+
+        boolean requestedAppIsRotated = requestedRotation == Surface.ROTATION_90 ||
+                requestedRotation == Surface.ROTATION_270;
+
+        // display size will change if the display is reflected. Flip height and width of app if the
+        // requested rotation is different from the current rotation.
+        if (displayIsRotated != requestedAppIsRotated) {
+            return new Rect(0, 0, displayBounds.height(), displayBounds.width());
+        }
+
+        return new Rect(0, 0, displayBounds.width(), displayBounds.height());
+    }
+
+    static Rect getStatusBarPosition(int requestedRotation) {
+        Resources resources = InstrumentationRegistry.getContext().getResources();
+        String resourceName;
+        Rect displayBounds = getDisplayBounds();
+        int width;
+        if (requestedRotation == Surface.ROTATION_0 || requestedRotation == Surface.ROTATION_180) {
+            resourceName = "status_bar_height_portrait";
+            width = Math.min(displayBounds.width(), displayBounds.height());
+        } else {
+            resourceName = "status_bar_height_landscape";
+            width = Math.max(displayBounds.width(), displayBounds.height());
+        }
+
+        int resourceId = resources.getIdentifier(resourceName, "dimen", "android");
+        int height = resources.getDimensionPixelSize(resourceId);
+
+        return new Rect(0, 0, width, height);
+    }
+
+    static Rect getNavigationBarPosition(int requestedRotation) {
+        Resources resources = InstrumentationRegistry.getContext().getResources();
+        Rect displayBounds = getDisplayBounds();
+        int displayWidth = Math.min(displayBounds.width(), displayBounds.height());
+        int displayHeight = Math.max(displayBounds.width(), displayBounds.height());
+        int resourceId;
+        if (requestedRotation == Surface.ROTATION_0 || requestedRotation == Surface.ROTATION_180) {
+            resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
+            int height = resources.getDimensionPixelSize(resourceId);
+            return new Rect(0, displayHeight - height, displayWidth, displayHeight);
+        } else {
+            resourceId = resources.getIdentifier("navigation_bar_width", "dimen", "android");
+            int width = resources.getDimensionPixelSize(resourceId);
+            // swap display dimensions in landscape or seascape mode
+            int temp = displayHeight;
+            displayHeight = displayWidth;
+            displayWidth = temp;
+            if (requestedRotation == Surface.ROTATION_90) {
+                return new Rect(0, 0, width, displayHeight);
+            } else {
+                return new Rect(displayWidth - width, 0, displayWidth, displayHeight);
+            }
+        }
+    }
+
+    static int getNavigationBarHeight() {
+        Resources resources = InstrumentationRegistry.getContext().getResources();
+        int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
+        return resources.getDimensionPixelSize(resourceId);
+    }
+
+    static int getDockedStackDividerInset() {
+        Resources resources = InstrumentationRegistry.getContext().getResources();
+        int resourceId = resources.getIdentifier("docked_stack_divider_insets", "dimen",
+                "android");
+        return resources.getDimensionPixelSize(resourceId);
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WmTraceSubject.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WmTraceSubject.java
new file mode 100644
index 0000000..1fc7d59
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WmTraceSubject.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.google.common.truth.Truth.assertAbout;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.annotation.Nullable;
+
+import com.android.server.wm.flicker.Assertions.Result;
+import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
+
+import com.google.common.truth.FailureStrategy;
+import com.google.common.truth.Subject;
+import com.google.common.truth.SubjectFactory;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * Truth subject for {@link WindowManagerTrace} objects.
+ */
+public class WmTraceSubject extends Subject<WmTraceSubject, WindowManagerTrace> {
+    // Boiler-plate Subject.Factory for WmTraceSubject
+    private static final SubjectFactory<WmTraceSubject, WindowManagerTrace> FACTORY =
+            new SubjectFactory<WmTraceSubject, WindowManagerTrace>() {
+                @Override
+                public WmTraceSubject getSubject(
+                        FailureStrategy fs, @Nullable WindowManagerTrace target) {
+                    return new WmTraceSubject(fs, target);
+                }
+            };
+
+    private AssertionsChecker<WindowManagerTrace.Entry> mChecker = new AssertionsChecker<>();
+
+    private WmTraceSubject(FailureStrategy fs, @Nullable WindowManagerTrace subject) {
+        super(fs, subject);
+    }
+
+    // User-defined entry point
+    public static WmTraceSubject assertThat(@Nullable WindowManagerTrace entry) {
+        return assertAbout(FACTORY).that(entry);
+    }
+
+    // User-defined entry point
+    public static WmTraceSubject assertThat(@Nullable TransitionResult result) {
+        WindowManagerTrace entries = WindowManagerTrace.parseFrom(result.getWindowManagerTrace(),
+                result.getWindowManagerTracePath());
+        return assertWithMessage(result.toString()).about(FACTORY).that(entries);
+    }
+
+    // Static method for getting the subject factory (for use with assertAbout())
+    public static SubjectFactory<WmTraceSubject, WindowManagerTrace> entries() {
+        return FACTORY;
+    }
+
+    public void forAllEntries() {
+        test();
+    }
+
+    public void forRange(long startTime, long endTime) {
+        mChecker.filterByRange(startTime, endTime);
+        test();
+    }
+
+    public WmTraceSubject then() {
+        mChecker.checkChangingAssertions();
+        return this;
+    }
+
+    public void inTheBeginning() {
+        if (getSubject().getEntries().isEmpty()) {
+            fail("No entries found.");
+        }
+        mChecker.checkFirstEntry();
+        test();
+    }
+
+    public void atTheEnd() {
+        if (getSubject().getEntries().isEmpty()) {
+            fail("No entries found.");
+        }
+        mChecker.checkLastEntry();
+        test();
+    }
+
+    private void test() {
+        List<Result> failures = mChecker.test(getSubject().getEntries());
+        if (!failures.isEmpty()) {
+            Optional<Path> failureTracePath = getSubject().getSource();
+            String failureLogs = failures.stream().map(Result::toString)
+                    .collect(Collectors.joining("\n"));
+            String tracePath = "";
+            if (failureTracePath.isPresent()) {
+                tracePath = "\nWindowManager Trace can be found in: "
+                        + failureTracePath.get().toAbsolutePath() + "\n";
+            }
+            fail(tracePath + failureLogs);
+        }
+    }
+
+    public WmTraceSubject showsAboveAppWindow(String partialWindowTitle) {
+        mChecker.add(entry -> entry.isAboveAppWindowVisible(partialWindowTitle),
+                "showsAboveAppWindow(" + partialWindowTitle + ")");
+        return this;
+    }
+
+    public WmTraceSubject hidesAboveAppWindow(String partialWindowTitle) {
+        mChecker.add(entry -> entry.isAboveAppWindowVisible(partialWindowTitle).negate(),
+                "hidesAboveAppWindow" + "(" + partialWindowTitle + ")");
+        return this;
+    }
+
+    public WmTraceSubject showsBelowAppWindow(String partialWindowTitle) {
+        mChecker.add(entry -> entry.isBelowAppWindowVisible(partialWindowTitle),
+                "showsBelowAppWindow(" + partialWindowTitle + ")");
+        return this;
+    }
+
+    public WmTraceSubject hidesBelowAppWindow(String partialWindowTitle) {
+        mChecker.add(entry -> entry.isBelowAppWindowVisible(partialWindowTitle).negate(),
+                "hidesBelowAppWindow" + "(" + partialWindowTitle + ")");
+        return this;
+    }
+
+    public WmTraceSubject showsImeWindow(String partialWindowTitle) {
+        mChecker.add(entry -> entry.isImeWindowVisible(partialWindowTitle),
+                "showsBelowAppWindow(" + partialWindowTitle + ")");
+        return this;
+    }
+
+    public WmTraceSubject hidesImeWindow(String partialWindowTitle) {
+        mChecker.add(entry -> entry.isImeWindowVisible(partialWindowTitle).negate(),
+                "hidesImeWindow" + "(" + partialWindowTitle + ")");
+        return this;
+    }
+
+    public WmTraceSubject showsAppWindowOnTop(String partialWindowTitle) {
+        mChecker.add(
+                entry -> {
+                    Result result = entry.isAppWindowVisible(partialWindowTitle);
+                    if (result.passed()) {
+                        result = entry.isVisibleAppWindowOnTop(partialWindowTitle);
+                    }
+                    return result;
+                },
+                "showsAppWindowOnTop(" + partialWindowTitle + ")"
+        );
+        return this;
+    }
+
+    public WmTraceSubject hidesAppWindowOnTop(String partialWindowTitle) {
+        mChecker.add(
+                entry -> {
+                    Result result = entry.isAppWindowVisible(partialWindowTitle).negate();
+                    if (result.failed()) {
+                        result = entry.isVisibleAppWindowOnTop(partialWindowTitle).negate();
+                    }
+                    return result;
+                },
+                "hidesAppWindowOnTop(" + partialWindowTitle + ")"
+        );
+        return this;
+    }
+
+    public WmTraceSubject showsAppWindow(String partialWindowTitle) {
+        mChecker.add(entry -> entry.isAppWindowVisible(partialWindowTitle),
+                "showsAppWindow(" + partialWindowTitle + ")");
+        return this;
+    }
+
+    public WmTraceSubject hidesAppWindow(String partialWindowTitle) {
+        mChecker.add(entry -> entry.isAppWindowVisible(partialWindowTitle).negate(),
+                "hidesAppWindow(" + partialWindowTitle + ")");
+        return this;
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ITransitionMonitor.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ITransitionMonitor.java
new file mode 100644
index 0000000..67e0ecc
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ITransitionMonitor.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import android.os.Environment;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Collects test artifacts during a UI transition.
+ */
+public interface ITransitionMonitor {
+    Path OUTPUT_DIR = Paths.get(Environment.getExternalStorageDirectory().toString(), "flicker");
+
+    /**
+     * Starts monitor.
+     */
+    void start();
+
+    /**
+     * Stops monitor.
+     */
+    void stop();
+
+    /**
+     * Saves any monitor artifacts to file adding {@code testTag} and {@code iteration}
+     * to the file name.
+     *
+     * @param testTag   suffix added to artifact name
+     * @param iteration suffix added to artifact name
+     *
+     * @return Path to saved artifact
+     */
+    default Path save(String testTag, int iteration) {
+        return save(testTag + "_" + iteration);
+    }
+
+    /**
+     * Saves any monitor artifacts to file adding {@code testTag} to the file name.
+     *
+     * @param testTag suffix added to artifact name
+     *
+     * @return Path to saved artifact
+     */
+    default Path save(String testTag) {
+        throw new UnsupportedOperationException("Save not implemented for this monitor");
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java
new file mode 100644
index 0000000..c55d068
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/**
+ * Captures Layers trace from SurfaceFlinger.
+ */
+public class LayersTraceMonitor extends TraceMonitor {
+    private static final String TAG = "LayersTraceMonitor";
+    private IBinder mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
+
+    public LayersTraceMonitor() {
+        traceFileName = "layers_trace.pb";
+    }
+
+    @Override
+    public void start() {
+        setEnabled(true);
+    }
+
+    @Override
+    public void stop() {
+        setEnabled(false);
+    }
+
+    @Override
+    public boolean isEnabled() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken("android.ui.ISurfaceComposer");
+        mSurfaceFlinger.transact(/* LAYER_TRACE_STATUS_CODE */ 1026,
+                data, reply, 0 /* flags */);
+        return reply.readBoolean();
+    }
+
+    private void setEnabled(boolean isEnabled) {
+        Parcel data = null;
+        try {
+            if (mSurfaceFlinger != null) {
+                data = Parcel.obtain();
+                data.writeInterfaceToken("android.ui.ISurfaceComposer");
+                data.writeInt(isEnabled ? 1 : 0);
+                mSurfaceFlinger.transact( /* LAYER_TRACE_CONTROL_CODE */ 1025,
+                        data, null, 0 /* flags */);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not set layer tracing." + e.toString());
+        } finally {
+            if (data != null) {
+                data.recycle();
+            }
+        }
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ScreenRecorder.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ScreenRecorder.java
new file mode 100644
index 0000000..4787586
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/ScreenRecorder.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Captures screen contents and saves it as a mp4 video file.
+ */
+public class ScreenRecorder implements ITransitionMonitor {
+    @VisibleForTesting
+    static final Path DEFAULT_OUTPUT_PATH = OUTPUT_DIR.resolve("transition.mp4");
+    private static final String TAG = "FLICKER";
+    private Thread recorderThread;
+
+    @VisibleForTesting
+    static Path getPath(String testTag) {
+        return OUTPUT_DIR.resolve(testTag + ".mp4");
+    }
+
+    @Override
+    public void start() {
+        OUTPUT_DIR.toFile().mkdirs();
+        String command = "screenrecord " + DEFAULT_OUTPUT_PATH;
+        recorderThread = new Thread(() -> {
+            try {
+                Runtime.getRuntime().exec(command);
+            } catch (IOException e) {
+                Log.e(TAG, "Error executing " + command, e);
+            }
+        });
+        recorderThread.start();
+    }
+
+    @Override
+    public void stop() {
+        runShellCommand("killall -s 2 screenrecord");
+        try {
+            recorderThread.join();
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
+    @Override
+    public Path save(String testTag) {
+        try {
+            return Files.move(DEFAULT_OUTPUT_PATH, getPath(testTag),
+                    REPLACE_EXISTING);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/TraceMonitor.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/TraceMonitor.java
new file mode 100644
index 0000000..0e154ec
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/TraceMonitor.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
+import android.os.RemoteException;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Locale;
+
+/**
+ * Base class for monitors containing common logic to read the trace
+ * as a byte array and save the trace to another location.
+ */
+public abstract class TraceMonitor implements ITransitionMonitor {
+    public static final String TAG = "FLICKER";
+    private static final String TRACE_DIR = "/data/misc/wmtrace/";
+
+    String traceFileName;
+
+    abstract boolean isEnabled() throws RemoteException;
+
+    /**
+     * Saves trace file to the external storage directory suffixing the name with the testtag
+     * and iteration.
+     *
+     * Moves the trace file from the default location via a shell command since the test app
+     * does not have security privileges to access /data/misc/wmtrace.
+     *
+     * @param testTag suffix added to trace name used to identify trace
+     *
+     * @return Path to saved trace file
+     */
+    @Override
+    public Path save(String testTag) {
+        OUTPUT_DIR.toFile().mkdirs();
+        Path traceFileCopy = getOutputTraceFilePath(testTag);
+        String copyCommand = String.format(Locale.getDefault(), "mv %s%s %s", TRACE_DIR,
+                traceFileName, traceFileCopy.toString());
+        runShellCommand(copyCommand);
+        return traceFileCopy;
+    }
+
+    @VisibleForTesting
+    Path getOutputTraceFilePath(String testTag) {
+        return OUTPUT_DIR.resolve(traceFileName + "_" + testTag);
+    }
+}
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitor.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitor.java
new file mode 100644
index 0000000..717d187
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitor.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import static android.view.FrameStats.UNDEFINED_TIME_NANO;
+
+import android.app.Instrumentation;
+import android.util.Log;
+import android.view.FrameStats;
+
+/**
+ * Monitors {@link android.view.WindowAnimationFrameStats} to detect janky frames.
+ *
+ * Adapted from {@link android.support.test.jank.internal.WindowAnimationFrameStatsMonitorImpl}
+ * using the same threshold to determine jank.
+ */
+public class WindowAnimationFrameStatsMonitor implements ITransitionMonitor {
+
+    private static final String TAG = "FLICKER";
+    // Maximum normalized error in frame duration before the frame is considered janky
+    private static final double MAX_ERROR = 0.5f;
+    // Maximum normalized frame duration before the frame is considered a pause
+    private static final double PAUSE_THRESHOLD = 15.0f;
+    private Instrumentation mInstrumentation;
+    private FrameStats stats;
+    private int numJankyFrames;
+    private long mLongestFrameNano = 0L;
+
+
+    /**
+     * Constructs a WindowAnimationFrameStatsMonitor instance.
+     */
+    public WindowAnimationFrameStatsMonitor(Instrumentation instrumentation) {
+        mInstrumentation = instrumentation;
+    }
+
+    private void analyze() {
+        int frameCount = stats.getFrameCount();
+        long refreshPeriodNano = stats.getRefreshPeriodNano();
+
+        // Skip first frame
+        for (int i = 2; i < frameCount; i++) {
+            // Handle frames that have not been presented.
+            if (stats.getFramePresentedTimeNano(i) == UNDEFINED_TIME_NANO) {
+                // The animation must not have completed. Warn and break out of the loop.
+                Log.w(TAG, "Skipping fenced frame.");
+                break;
+            }
+            long frameDurationNano = stats.getFramePresentedTimeNano(i) -
+                    stats.getFramePresentedTimeNano(i - 1);
+            double normalized = (double) frameDurationNano / refreshPeriodNano;
+            if (normalized < PAUSE_THRESHOLD) {
+                if (normalized > 1.0f + MAX_ERROR) {
+                    numJankyFrames++;
+                }
+                mLongestFrameNano = Math.max(mLongestFrameNano, frameDurationNano);
+            }
+        }
+    }
+
+    @Override
+    public void start() {
+        // Clear out any previous data
+        numJankyFrames = 0;
+        mLongestFrameNano = 0;
+        mInstrumentation.getUiAutomation().clearWindowAnimationFrameStats();
+    }
+
+    @Override
+    public void stop() {
+        stats = mInstrumentation.getUiAutomation().getWindowAnimationFrameStats();
+        analyze();
+    }
+
+    public boolean jankyFramesDetected() {
+        return stats.getFrameCount() > 0 && numJankyFrames > 0;
+    }
+
+    @Override
+    public String toString() {
+        return stats.toString() +
+                " RefreshPeriodNano:" + stats.getRefreshPeriodNano() +
+                " NumJankyFrames:" + numJankyFrames +
+                " LongestFrameNano:" + mLongestFrameNano;
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitor.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitor.java
new file mode 100644
index 0000000..ae160b68
--- /dev/null
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import android.os.RemoteException;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+
+/**
+ * Captures WindowManager trace from WindowManager.
+ */
+public class WindowManagerTraceMonitor extends TraceMonitor {
+    private IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+
+    public WindowManagerTraceMonitor() {
+        traceFileName = "wm_trace.pb";
+    }
+
+    @Override
+    public void start() {
+        try {
+            wm.startWindowTrace();
+        } catch (RemoteException e) {
+            throw new RuntimeException("Could not start trace", e);
+        }
+    }
+
+    @Override
+    public void stop() {
+        try {
+            wm.stopWindowTrace();
+        } catch (RemoteException e) {
+            throw new RuntimeException("Could not stop trace", e);
+        }
+    }
+
+    @Override
+    public boolean isEnabled() throws RemoteException{
+        return wm.isWindowTraceEnabled();
+    }
+}
diff --git a/tests/FlickerTests/lib/test/Android.mk b/tests/FlickerTests/lib/test/Android.mk
new file mode 100644
index 0000000..0e3f58d
--- /dev/null
+++ b/tests/FlickerTests/lib/test/Android.mk
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := FlickerLibTest
+LOCAL_MODULE_TAGS := tests optional
+# sign this with platform cert, so this test is allowed to call private platform apis
+LOCAL_CERTIFICATE := platform
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_COMPATIBILITY_SUITE := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    platform-test-annotations \
+    truth-prebuilt \
+    platformprotosnano \
+    layersprotosnano \
+    flickerlib
+
+include $(BUILD_PACKAGE)
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/FlickerTests/lib/test/AndroidManifest.xml b/tests/FlickerTests/lib/test/AndroidManifest.xml
new file mode 100644
index 0000000..d30172d
--- /dev/null
+++ b/tests/FlickerTests/lib/test/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright 2018 Google Inc. All Rights Reserved.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.server.wm.flicker">
+
+    <uses-sdk android:minSdkVersion="27" android:targetSdkVersion="27"/>
+    <!-- Read and write traces from external storage -->
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <!-- Capture screen contents -->
+    <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
+    <!-- Run layers trace -->
+    <uses-permission android:name="android.permission.HARDWARE_TEST"/>
+    <application android:label="FlickerLibTest">
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.wm.flicker"
+                     android:label="WindowManager Flicker Lib Test">
+    </instrumentation>
+
+</manifest>
\ No newline at end of file
diff --git a/tests/FlickerTests/lib/test/AndroidTest.xml b/tests/FlickerTests/lib/test/AndroidTest.xml
new file mode 100644
index 0000000..e4cc298
--- /dev/null
+++ b/tests/FlickerTests/lib/test/AndroidTest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright 2018 Google Inc. All Rights Reserved.
+ -->
+<configuration description="Config for WindowManager Flicker Tests">
+    <target_preparer class="com.google.android.tradefed.targetprep.GoogleDeviceSetup">
+        <!-- keeps the screen on during tests -->
+        <option name="screen-always-on" value="on" />
+        <!-- prevents the phone from restarting -->
+        <option name="force-skip-system-props" value="true" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true"/>
+        <option name="test-file-name" value="FlickerLibTest.apk"/>
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.server.wm.flicker"/>
+        <option name="hidden-api-checks" value="false" />
+    </test>
+</configuration>
diff --git a/tests/FlickerTests/lib/test/assets/testdata/layers_trace_emptyregion.pb b/tests/FlickerTests/lib/test/assets/testdata/layers_trace_emptyregion.pb
new file mode 100644
index 0000000..98ee6f3
--- /dev/null
+++ b/tests/FlickerTests/lib/test/assets/testdata/layers_trace_emptyregion.pb
Binary files differ
diff --git a/tests/FlickerTests/lib/test/assets/testdata/layers_trace_invalid_layer_visibility.pb b/tests/FlickerTests/lib/test/assets/testdata/layers_trace_invalid_layer_visibility.pb
new file mode 100644
index 0000000..20572d7
--- /dev/null
+++ b/tests/FlickerTests/lib/test/assets/testdata/layers_trace_invalid_layer_visibility.pb
Binary files differ
diff --git a/tests/FlickerTests/lib/test/assets/testdata/layers_trace_orphanlayers.pb b/tests/FlickerTests/lib/test/assets/testdata/layers_trace_orphanlayers.pb
new file mode 100644
index 0000000..af40797
--- /dev/null
+++ b/tests/FlickerTests/lib/test/assets/testdata/layers_trace_orphanlayers.pb
Binary files differ
diff --git a/tests/FlickerTests/lib/test/assets/testdata/wm_trace_openchrome.pb b/tests/FlickerTests/lib/test/assets/testdata/wm_trace_openchrome.pb
new file mode 100644
index 0000000..b3f3170
--- /dev/null
+++ b/tests/FlickerTests/lib/test/assets/testdata/wm_trace_openchrome.pb
Binary files differ
diff --git a/tests/FlickerTests/lib/test/assets/testdata/wm_trace_openchrome2.pb b/tests/FlickerTests/lib/test/assets/testdata/wm_trace_openchrome2.pb
new file mode 100644
index 0000000..b3b73ce
--- /dev/null
+++ b/tests/FlickerTests/lib/test/assets/testdata/wm_trace_openchrome2.pb
Binary files differ
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/AssertionsCheckerTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/AssertionsCheckerTest.java
new file mode 100644
index 0000000..8e7fe1b
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/AssertionsCheckerTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.server.wm.flicker.Assertions.Result;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Contains {@link AssertionsChecker} tests.
+ * To run this test: {@code atest FlickerLibTest:AssertionsCheckerTest}
+ */
+public class AssertionsCheckerTest {
+
+    /**
+     * Returns a list of SimpleEntry objects with {@code data} and incremental timestamps starting
+     * at 0.
+     */
+    private static List<SimpleEntry> getTestEntries(int... data) {
+        List<SimpleEntry> entries = new ArrayList<>();
+        for (int i = 0; i < data.length; i++) {
+            entries.add(new SimpleEntry(i, data[i]));
+        }
+        return entries;
+    }
+
+    @Test
+    public void canCheckAllEntries() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.add(SimpleEntry::isData42, "isData42");
+
+        List<Result> failures = checker.test(getTestEntries(1, 1, 1, 1, 1));
+
+        assertThat(failures).hasSize(5);
+    }
+
+    @Test
+    public void canCheckFirstEntry() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.checkFirstEntry();
+        checker.add(SimpleEntry::isData42, "isData42");
+
+        List<Result> failures = checker.test(getTestEntries(1, 1, 1, 1, 1));
+
+        assertThat(failures).hasSize(1);
+        assertThat(failures.get(0).timestamp).isEqualTo(0);
+    }
+
+    @Test
+    public void canCheckLastEntry() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.checkLastEntry();
+        checker.add(SimpleEntry::isData42, "isData42");
+
+        List<Result> failures = checker.test(getTestEntries(1, 1, 1, 1, 1));
+
+        assertThat(failures).hasSize(1);
+        assertThat(failures.get(0).timestamp).isEqualTo(4);
+    }
+
+    @Test
+    public void canCheckRangeOfEntries() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.filterByRange(1, 2);
+        checker.add(SimpleEntry::isData42, "isData42");
+
+        List<Result> failures = checker.test(getTestEntries(1, 42, 42, 1, 1));
+
+        assertThat(failures).hasSize(0);
+    }
+
+    @Test
+    public void emptyRangePasses() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.filterByRange(9, 10);
+        checker.add(SimpleEntry::isData42, "isData42");
+
+        List<Result> failures = checker.test(getTestEntries(1, 1, 1, 1, 1));
+
+        assertThat(failures).isEmpty();
+    }
+
+    @Test
+    public void canCheckChangingAssertions() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.add(SimpleEntry::isData42, "isData42");
+        checker.add(SimpleEntry::isData0, "isData0");
+        checker.checkChangingAssertions();
+
+        List<Result> failures = checker.test(getTestEntries(42, 0, 0, 0, 0));
+
+        assertThat(failures).isEmpty();
+    }
+
+    @Test
+    public void canCheckChangingAssertions_withNoAssertions() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.checkChangingAssertions();
+
+        List<Result> failures = checker.test(getTestEntries(42, 0, 0, 0, 0));
+
+        assertThat(failures).isEmpty();
+    }
+
+    @Test
+    public void canCheckChangingAssertions_withSingleAssertion() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.add(SimpleEntry::isData42, "isData42");
+        checker.checkChangingAssertions();
+
+        List<Result> failures = checker.test(getTestEntries(42, 42, 42, 42, 42));
+
+        assertThat(failures).isEmpty();
+    }
+
+    @Test
+    public void canFailCheckChangingAssertions_ifStartingAssertionFails() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.add(SimpleEntry::isData42, "isData42");
+        checker.add(SimpleEntry::isData0, "isData0");
+        checker.checkChangingAssertions();
+
+        List<Result> failures = checker.test(getTestEntries(0, 0, 0, 0, 0));
+
+        assertThat(failures).hasSize(1);
+    }
+
+    @Test
+    public void canFailCheckChangingAssertions_ifStartingAssertionAlwaysPasses() {
+        AssertionsChecker<SimpleEntry> checker = new AssertionsChecker<>();
+        checker.add(SimpleEntry::isData42, "isData42");
+        checker.add(SimpleEntry::isData0, "isData0");
+        checker.checkChangingAssertions();
+
+        List<Result> failures = checker.test(getTestEntries(0, 0, 0, 0, 0));
+
+        assertThat(failures).hasSize(1);
+    }
+
+    static class SimpleEntry implements ITraceEntry {
+        long timestamp;
+        int data;
+
+        SimpleEntry(long timestamp, int data) {
+            this.timestamp = timestamp;
+            this.data = data;
+        }
+
+        @Override
+        public long getTimestamp() {
+            return timestamp;
+        }
+
+        Result isData42() {
+            return new Result(this.data == 42, this.timestamp, "is42", "");
+        }
+
+        Result isData0() {
+            return new Result(this.data == 0, this.timestamp, "is42", "");
+        }
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/AssertionsTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/AssertionsTest.java
new file mode 100644
index 0000000..7fd178c
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/AssertionsTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.server.wm.flicker.Assertions.Result;
+
+import org.junit.Test;
+
+/**
+ * Contains {@link Assertions} tests.
+ * To run this test: {@code atest FlickerLibTest:AssertionsTest}
+ */
+public class AssertionsTest {
+    @Test
+    public void traceEntryAssertionCanNegateResult() {
+        Assertions.TraceAssertion<Integer> assertNumEquals42 =
+                getIntegerTraceEntryAssertion();
+
+        assertThat(assertNumEquals42.apply(1).success).isFalse();
+        assertThat(assertNumEquals42.negate().apply(1).success).isTrue();
+
+        assertThat(assertNumEquals42.apply(42).success).isTrue();
+        assertThat(assertNumEquals42.negate().apply(42).success).isFalse();
+    }
+
+    @Test
+    public void resultCanBeNegated() {
+        String reason = "Everything is fine!";
+        Result result = new Result(true, 0, "TestAssert", reason);
+        Result negatedResult = result.negate();
+        assertThat(negatedResult.success).isFalse();
+        assertThat(negatedResult.reason).isEqualTo(reason);
+        assertThat(negatedResult.assertionName).isEqualTo("!TestAssert");
+    }
+
+    private Assertions.TraceAssertion<Integer> getIntegerTraceEntryAssertion() {
+        return (num) -> {
+            if (num == 42) {
+                return new Result(true, "Num equals 42");
+            }
+            return new Result(false, "Num doesn't equal 42, actual:" + num);
+        };
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceSubjectTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceSubjectTest.java
new file mode 100644
index 0000000..d06c5d7
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceSubjectTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.LayersTraceSubject.assertThat;
+import static com.android.server.wm.flicker.TestFileUtils.readTestFile;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.fail;
+
+import android.graphics.Rect;
+
+import org.junit.Test;
+
+import java.nio.file.Paths;
+
+/**
+ * Contains {@link LayersTraceSubject} tests.
+ * To run this test: {@code atest FlickerLibTest:LayersTraceSubjectTest}
+ */
+public class LayersTraceSubjectTest {
+    private static final Rect displayRect = new Rect(0, 0, 1440, 2880);
+
+    private static LayersTrace readLayerTraceFromFile(String relativePath) {
+        try {
+            return LayersTrace.parseFrom(readTestFile(relativePath), Paths.get(relativePath));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testCanDetectEmptyRegionFromLayerTrace() {
+        LayersTrace layersTraceEntries = readLayerTraceFromFile("layers_trace_emptyregion.pb");
+        try {
+            assertThat(layersTraceEntries).coversRegion(displayRect).forAllEntries();
+            fail("Assertion passed");
+        } catch (AssertionError e) {
+            assertWithMessage("Contains path to trace")
+                    .that(e.getMessage()).contains("layers_trace_emptyregion.pb");
+            assertWithMessage("Contains timestamp")
+                    .that(e.getMessage()).contains("0h38m28s8ms");
+            assertWithMessage("Contains assertion function")
+                    .that(e.getMessage()).contains("coversRegion");
+            assertWithMessage("Contains debug info")
+                    .that(e.getMessage()).contains("Region to test: " + displayRect);
+            assertWithMessage("Contains debug info")
+                    .that(e.getMessage()).contains("first empty point: 0, 99");
+        }
+    }
+
+    @Test
+    public void testCanDetectIncorrectVisibilityFromLayerTrace() {
+        LayersTrace layersTraceEntries = readLayerTraceFromFile(
+                "layers_trace_invalid_layer_visibility.pb");
+        try {
+            assertThat(layersTraceEntries).showsLayer("com.android.server.wm.flicker.testapp")
+                    .then().hidesLayer("com.android.server.wm.flicker.testapp").forAllEntries();
+            fail("Assertion passed");
+        } catch (AssertionError e) {
+            assertWithMessage("Contains path to trace")
+                    .that(e.getMessage()).contains("layers_trace_invalid_layer_visibility.pb");
+            assertWithMessage("Contains timestamp")
+                    .that(e.getMessage()).contains("70h13m14s303ms");
+            assertWithMessage("Contains assertion function")
+                    .that(e.getMessage()).contains("!isVisible");
+            assertWithMessage("Contains debug info")
+                    .that(e.getMessage()).contains(
+                    "com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp"
+                            + ".SimpleActivity#0 is visible");
+        }
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceTest.java
new file mode 100644
index 0000000..42b2aca
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceTest.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.TestFileUtils.readTestFile;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.support.test.InstrumentationRegistry;
+import android.view.WindowManager;
+
+import org.junit.Test;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Contains {@link LayersTrace} tests.
+ * To run this test: {@code atest FlickerLibTest:LayersTraceTest}
+ */
+public class LayersTraceTest {
+    private static LayersTrace readLayerTraceFromFile(String relativePath) {
+        try {
+            return LayersTrace.parseFrom(readTestFile(relativePath));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static Rect getDisplayBounds() {
+        Point display = new Point();
+        WindowManager wm =
+                (WindowManager) InstrumentationRegistry.getContext().getSystemService(
+                        Context.WINDOW_SERVICE);
+        wm.getDefaultDisplay().getRealSize(display);
+        return new Rect(0, 0, display.x, display.y);
+    }
+
+    @Test
+    public void canParseAllLayers() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_emptyregion.pb");
+        assertThat(trace.getEntries()).isNotEmpty();
+        assertThat(trace.getEntries().get(0).getTimestamp()).isEqualTo(2307984557311L);
+        assertThat(trace.getEntries().get(trace.getEntries().size() - 1).getTimestamp())
+                .isEqualTo(2308521813510L);
+        List<LayersTrace.Layer> flattenedLayers = trace.getEntries().get(0).asFlattenedLayers();
+        String msg = "Layers:\n" + flattenedLayers.stream().map(layer -> layer.mProto.name)
+                .collect(Collectors.joining("\n\t"));
+        assertWithMessage(msg).that(flattenedLayers).hasSize(47);
+    }
+
+    @Test
+    public void canParseVisibleLayers() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_emptyregion.pb");
+        assertThat(trace.getEntries()).isNotEmpty();
+        assertThat(trace.getEntries().get(0).getTimestamp()).isEqualTo(2307984557311L);
+        assertThat(trace.getEntries().get(trace.getEntries().size() - 1).getTimestamp())
+                .isEqualTo(2308521813510L);
+        List<LayersTrace.Layer> flattenedLayers = trace.getEntries().get(0).asFlattenedLayers();
+        List<LayersTrace.Layer> visibleLayers = flattenedLayers.stream()
+                .filter(layer -> layer.isVisible() && !layer.isHiddenByParent())
+                .collect(Collectors.toList());
+
+        String msg = "Visible Layers:\n" + visibleLayers.stream()
+                .map(layer -> layer.mProto.name)
+                .collect(Collectors.joining("\n\t"));
+
+        assertWithMessage(msg).that(visibleLayers).hasSize(9);
+    }
+
+    @Test
+    public void canParseLayerHierarchy() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_emptyregion.pb");
+        assertThat(trace.getEntries()).isNotEmpty();
+        assertThat(trace.getEntries().get(0).getTimestamp()).isEqualTo(2307984557311L);
+        assertThat(trace.getEntries().get(trace.getEntries().size() - 1).getTimestamp())
+                .isEqualTo(2308521813510L);
+        List<LayersTrace.Layer> layers = trace.getEntries().get(0).getRootLayers();
+        assertThat(layers).hasSize(2);
+        assertThat(layers.get(0).mChildren).hasSize(layers.get(0).mProto.children.length);
+        assertThat(layers.get(1).mChildren).hasSize(layers.get(1).mProto.children.length);
+    }
+
+    // b/76099859
+    @Test
+    public void canDetectOrphanLayers() {
+        try {
+            readLayerTraceFromFile(
+                    "layers_trace_orphanlayers.pb");
+            fail("Failed to detect orphaned layers.");
+        } catch (RuntimeException exception) {
+            assertThat(exception.getMessage()).contains(
+                    "Failed to parse layers trace. Found orphan layers "
+                            + "with parent layer id:1006 : 49");
+        }
+    }
+
+    // b/75276931
+    @Test
+    public void canDetectUncoveredRegion() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_emptyregion.pb");
+        LayersTrace.Entry entry = trace.getEntry(2308008331271L);
+
+        Assertions.Result result = entry.coversRegion(getDisplayBounds());
+
+        assertThat(result.failed()).isTrue();
+        assertThat(result.reason).contains("Region to test: Rect(0, 0 - 1440, 2880)");
+        assertThat(result.reason).contains("first empty point: 0, 99");
+        assertThat(result.reason).contains("visible regions:");
+        assertWithMessage("Reason contains list of visible regions")
+                .that(result.reason).contains("StatusBar#0Rect(0, 0 - 1440, 98");
+    }
+
+    // Visible region tests
+    @Test
+    public void canTestLayerVisibleRegion_layerDoesNotExist() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_emptyregion.pb");
+        LayersTrace.Entry entry = trace.getEntry(2308008331271L);
+
+        final Rect expectedVisibleRegion = new Rect(0, 0, 1, 1);
+        Assertions.Result result = entry.hasVisibleRegion("ImaginaryLayer",
+                expectedVisibleRegion);
+
+        assertThat(result.failed()).isTrue();
+        assertThat(result.reason).contains("Could not find ImaginaryLayer");
+    }
+
+    @Test
+    public void canTestLayerVisibleRegion_layerDoesNotHaveExpectedVisibleRegion() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_emptyregion.pb");
+        LayersTrace.Entry entry = trace.getEntry(2307993020072L);
+
+        final Rect expectedVisibleRegion = new Rect(0, 0, 1, 1);
+        Assertions.Result result = entry.hasVisibleRegion("NexusLauncherActivity#2",
+                expectedVisibleRegion);
+
+        assertThat(result.failed()).isTrue();
+        assertThat(result.reason).contains(
+                "Layer com.google.android.apps.nexuslauncher/com.google.android.apps"
+                        + ".nexuslauncher.NexusLauncherActivity#2 is invisible: activeBuffer=null"
+                        + " type != ColorLayer flags=1 (FLAG_HIDDEN set) visible region is empty");
+    }
+
+    @Test
+    public void canTestLayerVisibleRegion_layerIsHiddenByParent() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_emptyregion.pb");
+        LayersTrace.Entry entry = trace.getEntry(2308455948035L);
+
+        final Rect expectedVisibleRegion = new Rect(0, 0, 1, 1);
+        Assertions.Result result = entry.hasVisibleRegion(
+                "SurfaceView - com.android.chrome/com.google.android.apps.chrome.Main",
+                expectedVisibleRegion);
+
+        assertThat(result.failed()).isTrue();
+        assertThat(result.reason).contains(
+                "Layer SurfaceView - com.android.chrome/com.google.android.apps.chrome.Main#0 is "
+                        + "hidden by parent: com.android.chrome/com.google.android.apps.chrome"
+                        + ".Main#0");
+    }
+
+    @Test
+    public void canTestLayerVisibleRegion_incorrectRegionSize() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_emptyregion.pb");
+        LayersTrace.Entry entry = trace.getEntry(2308008331271L);
+
+        final Rect expectedVisibleRegion = new Rect(0, 0, 1440, 99);
+        Assertions.Result result = entry.hasVisibleRegion(
+                "StatusBar",
+                expectedVisibleRegion);
+
+        assertThat(result.failed()).isTrue();
+        assertThat(result.reason).contains("StatusBar#0 has visible "
+                + "region:Rect(0, 0 - 1440, 98) expected:Rect(0, 0 - 1440, 99)");
+    }
+
+    @Test
+    public void canTestLayerVisibleRegion() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_emptyregion.pb");
+        LayersTrace.Entry entry = trace.getEntry(2308008331271L);
+
+        final Rect expectedVisibleRegion = new Rect(0, 0, 1440, 98);
+        Assertions.Result result = entry.hasVisibleRegion("StatusBar", expectedVisibleRegion);
+
+        assertThat(result.passed()).isTrue();
+    }
+
+    @Test
+    public void canTestLayerVisibleRegion_layerIsNotVisible() {
+        LayersTrace trace = readLayerTraceFromFile(
+                "layers_trace_invalid_layer_visibility.pb");
+        LayersTrace.Entry entry = trace.getEntry(252794268378458L);
+
+        Assertions.Result result = entry.isVisible("com.android.server.wm.flicker.testapp");
+        assertThat(result.failed()).isTrue();
+        assertThat(result.reason).contains(
+                "Layer com.android.server.wm.flicker.testapp/com.android.server.wm.flicker"
+                        + ".testapp.SimpleActivity#0 is invisible: type != ColorLayer visible "
+                        + "region is empty");
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TestFileUtils.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TestFileUtils.java
new file mode 100644
index 0000000..5a24e6d
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TestFileUtils.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+
+import com.google.common.io.ByteStreams;
+
+import java.io.InputStream;
+
+/**
+ * Helper functions for test file resources.
+ */
+class TestFileUtils {
+    static byte[] readTestFile(String relativePath) throws Exception {
+        Context context = InstrumentationRegistry.getContext();
+        InputStream in = context.getResources().getAssets().open("testdata/" + relativePath);
+        return ByteStreams.toByteArray(in);
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TransitionRunnerTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TransitionRunnerTest.java
new file mode 100644
index 0000000..9c5e2059a
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TransitionRunnerTest.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.os.Environment;
+
+import com.android.server.wm.flicker.TransitionRunner.TransitionBuilder;
+import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
+import com.android.server.wm.flicker.monitor.LayersTraceMonitor;
+import com.android.server.wm.flicker.monitor.ScreenRecorder;
+import com.android.server.wm.flicker.monitor.WindowAnimationFrameStatsMonitor;
+import com.android.server.wm.flicker.monitor.WindowManagerTraceMonitor;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.List;
+
+/**
+ * Contains {@link TransitionRunner} tests.
+ * {@code atest FlickerLibTest:TransitionRunnerTest}
+ */
+public class TransitionRunnerTest {
+    @Mock
+    private SimpleUiTransitions mTransitionsMock;
+    @Mock
+    private ScreenRecorder mScreenRecorderMock;
+    @Mock
+    private WindowManagerTraceMonitor mWindowManagerTraceMonitorMock;
+    @Mock
+    private LayersTraceMonitor mLayersTraceMonitorMock;
+    @Mock
+    private WindowAnimationFrameStatsMonitor mWindowAnimationFrameStatsMonitor;
+    @InjectMocks
+    private TransitionBuilder mTransitionBuilder;
+
+    @Before
+    public void init() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void transitionsRunInOrder() {
+        TransitionRunner.newBuilder()
+                .runBeforeAll(mTransitionsMock::turnOnDevice)
+                .runBefore(mTransitionsMock::openApp)
+                .run(mTransitionsMock::performMagic)
+                .runAfter(mTransitionsMock::closeApp)
+                .runAfterAll(mTransitionsMock::cleanUpTracks)
+                .skipLayersTrace()
+                .skipWindowManagerTrace()
+                .build()
+                .run();
+
+        InOrder orderVerifier = inOrder(mTransitionsMock);
+        orderVerifier.verify(mTransitionsMock).turnOnDevice();
+        orderVerifier.verify(mTransitionsMock).openApp();
+        orderVerifier.verify(mTransitionsMock).performMagic();
+        orderVerifier.verify(mTransitionsMock).closeApp();
+        orderVerifier.verify(mTransitionsMock).cleanUpTracks();
+    }
+
+    @Test
+    public void canCombineTransitions() {
+        TransitionRunner.newBuilder()
+                .runBeforeAll(mTransitionsMock::turnOnDevice)
+                .runBeforeAll(mTransitionsMock::turnOnDevice)
+                .runBefore(mTransitionsMock::openApp)
+                .runBefore(mTransitionsMock::openApp)
+                .run(mTransitionsMock::performMagic)
+                .run(mTransitionsMock::performMagic)
+                .runAfter(mTransitionsMock::closeApp)
+                .runAfter(mTransitionsMock::closeApp)
+                .runAfterAll(mTransitionsMock::cleanUpTracks)
+                .runAfterAll(mTransitionsMock::cleanUpTracks)
+                .skipLayersTrace()
+                .skipWindowManagerTrace()
+                .build()
+                .run();
+
+        final int wantedNumberOfInvocations = 2;
+        verify(mTransitionsMock, times(wantedNumberOfInvocations)).turnOnDevice();
+        verify(mTransitionsMock, times(wantedNumberOfInvocations)).openApp();
+        verify(mTransitionsMock, times(wantedNumberOfInvocations)).performMagic();
+        verify(mTransitionsMock, times(wantedNumberOfInvocations)).closeApp();
+        verify(mTransitionsMock, times(wantedNumberOfInvocations)).cleanUpTracks();
+    }
+
+    @Test
+    public void emptyTransitionPasses() {
+        List<TransitionResult> results = TransitionRunner.newBuilder()
+                .skipLayersTrace()
+                .skipWindowManagerTrace()
+                .build()
+                .run()
+                .getResults();
+        assertThat(results).hasSize(1);
+        assertThat(results.get(0).layersTraceExists()).isFalse();
+        assertThat(results.get(0).windowManagerTraceExists()).isFalse();
+        assertThat(results.get(0).screenCaptureVideoExists()).isFalse();
+    }
+
+    @Test
+    public void canRepeatTransitions() {
+        final int wantedNumberOfInvocations = 10;
+        TransitionRunner.newBuilder()
+                .runBeforeAll(mTransitionsMock::turnOnDevice)
+                .runBefore(mTransitionsMock::openApp)
+                .run(mTransitionsMock::performMagic)
+                .runAfter(mTransitionsMock::closeApp)
+                .runAfterAll(mTransitionsMock::cleanUpTracks)
+                .repeat(wantedNumberOfInvocations)
+                .skipLayersTrace()
+                .skipWindowManagerTrace()
+                .build()
+                .run();
+        verify(mTransitionsMock).turnOnDevice();
+        verify(mTransitionsMock, times(wantedNumberOfInvocations)).openApp();
+        verify(mTransitionsMock, times(wantedNumberOfInvocations)).performMagic();
+        verify(mTransitionsMock, times(wantedNumberOfInvocations)).closeApp();
+        verify(mTransitionsMock).cleanUpTracks();
+    }
+
+    private void emptyTask() {
+
+    }
+
+    @Test
+    public void canCaptureWindowManagerTrace() {
+        mTransitionBuilder
+                .run(this::emptyTask)
+                .includeJankyRuns()
+                .skipLayersTrace()
+                .withTag("mCaptureWmTraceTransitionRunner")
+                .build().run();
+        InOrder orderVerifier = inOrder(mWindowManagerTraceMonitorMock);
+        orderVerifier.verify(mWindowManagerTraceMonitorMock).start();
+        orderVerifier.verify(mWindowManagerTraceMonitorMock).stop();
+        orderVerifier.verify(mWindowManagerTraceMonitorMock)
+                .save("mCaptureWmTraceTransitionRunner", 0);
+        verifyNoMoreInteractions(mWindowManagerTraceMonitorMock);
+    }
+
+    @Test
+    public void canCaptureLayersTrace() {
+        mTransitionBuilder
+                .run(this::emptyTask)
+                .includeJankyRuns()
+                .skipWindowManagerTrace()
+                .withTag("mCaptureLayersTraceTransitionRunner")
+                .build().run();
+        InOrder orderVerifier = inOrder(mLayersTraceMonitorMock);
+        orderVerifier.verify(mLayersTraceMonitorMock).start();
+        orderVerifier.verify(mLayersTraceMonitorMock).stop();
+        orderVerifier.verify(mLayersTraceMonitorMock)
+                .save("mCaptureLayersTraceTransitionRunner", 0);
+        verifyNoMoreInteractions(mLayersTraceMonitorMock);
+    }
+
+    @Test
+    public void canRecordEachRun() throws IOException {
+        mTransitionBuilder
+                .run(this::emptyTask)
+                .withTag("mRecordEachRun")
+                .recordEachRun()
+                .includeJankyRuns()
+                .skipLayersTrace()
+                .skipWindowManagerTrace()
+                .repeat(2)
+                .build().run();
+        InOrder orderVerifier = inOrder(mScreenRecorderMock);
+        orderVerifier.verify(mScreenRecorderMock).start();
+        orderVerifier.verify(mScreenRecorderMock).stop();
+        orderVerifier.verify(mScreenRecorderMock).save("mRecordEachRun", 0);
+        orderVerifier.verify(mScreenRecorderMock).start();
+        orderVerifier.verify(mScreenRecorderMock).stop();
+        orderVerifier.verify(mScreenRecorderMock).save("mRecordEachRun", 1);
+        verifyNoMoreInteractions(mScreenRecorderMock);
+    }
+
+    @Test
+    public void canRecordAllRuns() throws IOException {
+        doReturn(Paths.get(Environment.getExternalStorageDirectory().getAbsolutePath(),
+                "mRecordAllRuns.mp4")).when(mScreenRecorderMock).save("mRecordAllRuns");
+        mTransitionBuilder
+                .run(this::emptyTask)
+                .recordAllRuns()
+                .includeJankyRuns()
+                .skipLayersTrace()
+                .skipWindowManagerTrace()
+                .withTag("mRecordAllRuns")
+                .repeat(2)
+                .build().run();
+        InOrder orderVerifier = inOrder(mScreenRecorderMock);
+        orderVerifier.verify(mScreenRecorderMock).start();
+        orderVerifier.verify(mScreenRecorderMock).stop();
+        orderVerifier.verify(mScreenRecorderMock).save("mRecordAllRuns");
+        verifyNoMoreInteractions(mScreenRecorderMock);
+    }
+
+    @Test
+    public void canSkipJankyRuns() {
+        doReturn(false).doReturn(true).doReturn(false)
+                .when(mWindowAnimationFrameStatsMonitor).jankyFramesDetected();
+        List<TransitionResult> results = mTransitionBuilder
+                .run(this::emptyTask)
+                .skipLayersTrace()
+                .skipWindowManagerTrace()
+                .repeat(3)
+                .build().run().getResults();
+        assertThat(results).hasSize(2);
+    }
+
+    public static class SimpleUiTransitions {
+        public void turnOnDevice() {
+        }
+
+        public void openApp() {
+        }
+
+        public void performMagic() {
+        }
+
+        public void closeApp() {
+        }
+
+        public void cleanUpTracks() {
+        }
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/WindowManagerTraceTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/WindowManagerTraceTest.java
new file mode 100644
index 0000000..4927871
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/WindowManagerTraceTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.TestFileUtils.readTestFile;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.server.wm.flicker.Assertions.Result;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Contains {@link WindowManagerTrace} tests.
+ * To run this test: {@code atest FlickerLibTest:WindowManagerTraceTest}
+ */
+public class WindowManagerTraceTest {
+    private WindowManagerTrace mTrace;
+
+    private static WindowManagerTrace readWindowManagerTraceFromFile(String relativePath) {
+        try {
+            return WindowManagerTrace.parseFrom(readTestFile(relativePath));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Before
+    public void setup() {
+        mTrace = readWindowManagerTraceFromFile("wm_trace_openchrome.pb");
+    }
+
+    @Test
+    public void canParseAllEntries() {
+        assertThat(mTrace.getEntries().get(0).getTimestamp()).isEqualTo(241777211939236L);
+        assertThat(mTrace.getEntries().get(mTrace.getEntries().size() - 1).getTimestamp()).isEqualTo
+                (241779809471942L);
+    }
+
+    @Test
+    public void canDetectAboveAppWindowVisibility() {
+        WindowManagerTrace.Entry entry = mTrace.getEntry(241777211939236L);
+        Result result = entry.isAboveAppWindowVisible("NavigationBar");
+        assertThat(result.passed()).isTrue();
+    }
+
+    @Test
+    public void canDetectBelowAppWindowVisibility() {
+        WindowManagerTrace.Entry entry = mTrace.getEntry(241777211939236L);
+        Result result = entry.isBelowAppWindowVisible("wallpaper");
+        assertThat(result.passed()).isTrue();
+    }
+
+    @Test
+    public void canDetectAppWindowVisibility() {
+        WindowManagerTrace.Entry entry = mTrace.getEntry(241777211939236L);
+        Result result = entry.isAppWindowVisible("com.google.android.apps.nexuslauncher");
+        assertThat(result.passed()).isTrue();
+    }
+
+    @Test
+    public void canFailWithReasonForVisibilityChecks_windowNotFound() {
+        WindowManagerTrace.Entry entry = mTrace.getEntry(241777211939236L);
+        Result result = entry.isAboveAppWindowVisible("ImaginaryWindow");
+        assertThat(result.failed()).isTrue();
+        assertThat(result.reason).contains("ImaginaryWindow cannot be found");
+    }
+
+    @Test
+    public void canFailWithReasonForVisibilityChecks_windowNotVisible() {
+        WindowManagerTrace.Entry entry = mTrace.getEntry(241777211939236L);
+        Result result = entry.isAboveAppWindowVisible("AssistPreviewPanel");
+        assertThat(result.failed()).isTrue();
+        assertThat(result.reason).contains("AssistPreviewPanel is invisible");
+    }
+
+    @Test
+    public void canDetectAppZOrder() {
+        WindowManagerTrace.Entry entry = mTrace.getEntry(241778130296410L);
+        Result result = entry.isVisibleAppWindowOnTop("com.google.android.apps.chrome");
+        assertThat(result.passed()).isTrue();
+    }
+
+    @Test
+    public void canFailWithReasonForZOrderChecks_windowNotOnTop() {
+        WindowManagerTrace.Entry entry = mTrace.getEntry(241778130296410L);
+        Result result = entry.isVisibleAppWindowOnTop("com.google.android.apps.nexuslauncher");
+        assertThat(result.failed()).isTrue();
+        assertThat(result.reason).contains("wanted=com.google.android.apps.nexuslauncher");
+        assertThat(result.reason).contains("found=com.android.chrome/"
+                + "com.google.android.apps.chrome.Main");
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/WmTraceSubjectTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/WmTraceSubjectTest.java
new file mode 100644
index 0000000..d547a18
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/WmTraceSubjectTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.TestFileUtils.readTestFile;
+import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
+
+import org.junit.Test;
+
+/**
+ * Contains {@link WmTraceSubject} tests.
+ * To run this test: {@code atest FlickerLibTest:WmTraceSubjectTest}
+ */
+public class WmTraceSubjectTest {
+    private static WindowManagerTrace readWmTraceFromFile(String relativePath) {
+        try {
+            return WindowManagerTrace.parseFrom(readTestFile(relativePath));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testCanTransitionInAppWindow() {
+        WindowManagerTrace trace = readWmTraceFromFile("wm_trace_openchrome2.pb");
+
+        assertThat(trace).showsAppWindowOnTop("com.google.android.apps.nexuslauncher/"
+                + ".NexusLauncherActivity").forRange(174684850717208L, 174685957511016L);
+        assertThat(trace).showsAppWindowOnTop(
+                "com.google.android.apps.nexuslauncher/.NexusLauncherActivity")
+                .then()
+                .showsAppWindowOnTop("com.android.chrome")
+                .forAllEntries();
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/LayersTraceMonitorTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/LayersTraceMonitorTest.java
new file mode 100644
index 0000000..dbd6761
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/LayersTraceMonitorTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import static android.surfaceflinger.nano.Layerstrace.LayersTraceFileProto.MAGIC_NUMBER_H;
+import static android.surfaceflinger.nano.Layerstrace.LayersTraceFileProto.MAGIC_NUMBER_L;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.surfaceflinger.nano.Layerstrace.LayersTraceFileProto;
+
+import com.google.common.io.Files;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+
+/**
+ * Contains {@link LayersTraceMonitor} tests.
+ * To run this test: {@code atest FlickerLibTest:LayersTraceMonitorTest}
+ */
+public class LayersTraceMonitorTest {
+    private LayersTraceMonitor mLayersTraceMonitor;
+
+    @Before
+    public void setup() {
+        mLayersTraceMonitor = new LayersTraceMonitor();
+    }
+
+    @After
+    public void teardown() {
+        mLayersTraceMonitor.stop();
+        mLayersTraceMonitor.getOutputTraceFilePath("captureLayersTrace").toFile().delete();
+    }
+
+    @Test
+    public void canStartLayersTrace() throws Exception {
+        mLayersTraceMonitor.start();
+        assertThat(mLayersTraceMonitor.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void canStopLayersTrace() throws Exception {
+        mLayersTraceMonitor.start();
+        assertThat(mLayersTraceMonitor.isEnabled()).isTrue();
+        mLayersTraceMonitor.stop();
+        assertThat(mLayersTraceMonitor.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void captureLayersTrace() throws Exception {
+        mLayersTraceMonitor.start();
+        mLayersTraceMonitor.stop();
+        File testFile = mLayersTraceMonitor.save("captureLayersTrace").toFile();
+        assertThat(testFile.exists()).isTrue();
+        byte[] trace = Files.toByteArray(testFile);
+        assertThat(trace.length).isGreaterThan(0);
+        LayersTraceFileProto mLayerTraceFileProto = LayersTraceFileProto.parseFrom(trace);
+        assertThat(mLayerTraceFileProto.magicNumber).isEqualTo(
+                (long) MAGIC_NUMBER_H << 32 | MAGIC_NUMBER_L);
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/ScreenRecorderTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/ScreenRecorderTest.java
new file mode 100644
index 0000000..e73eecc
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/ScreenRecorderTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import static android.os.SystemClock.sleep;
+
+import static com.android.server.wm.flicker.monitor.ScreenRecorder.DEFAULT_OUTPUT_PATH;
+import static com.android.server.wm.flicker.monitor.ScreenRecorder.getPath;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Contains {@link ScreenRecorder} tests.
+ * To run this test: {@code atest FlickerLibTest:ScreenRecorderTest}
+ */
+public class ScreenRecorderTest {
+    private static final String TEST_VIDEO_FILENAME = "test.mp4";
+    private ScreenRecorder mScreenRecorder;
+
+    @Before
+    public void setup() {
+        mScreenRecorder = new ScreenRecorder();
+    }
+
+    @After
+    public void teardown() {
+        DEFAULT_OUTPUT_PATH.toFile().delete();
+        getPath(TEST_VIDEO_FILENAME).toFile().delete();
+    }
+
+    @Test
+    public void videoIsRecorded() {
+        mScreenRecorder.start();
+        sleep(100);
+        mScreenRecorder.stop();
+        File file = DEFAULT_OUTPUT_PATH.toFile();
+        assertThat(file.exists()).isTrue();
+    }
+
+    @Test
+    public void videoCanBeSaved() {
+        mScreenRecorder.start();
+        sleep(100);
+        mScreenRecorder.stop();
+        mScreenRecorder.save(TEST_VIDEO_FILENAME);
+        File file = getPath(TEST_VIDEO_FILENAME).toFile();
+        assertThat(file.exists()).isTrue();
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java
new file mode 100644
index 0000000..f7fa0d5
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import static com.android.server.wm.flicker.AutomationUtils.wakeUpAndGoToHomeScreen;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Contains {@link WindowAnimationFrameStatsMonitor} tests.
+ * To run this test: {@code atest FlickerLibTest:WindowAnimationFrameStatsMonitorTest}
+ */
+public class WindowAnimationFrameStatsMonitorTest {
+    private WindowAnimationFrameStatsMonitor mWindowAnimationFrameStatsMonitor;
+
+    @Before
+    public void setup() {
+        mWindowAnimationFrameStatsMonitor = new WindowAnimationFrameStatsMonitor(
+                InstrumentationRegistry.getInstrumentation());
+        wakeUpAndGoToHomeScreen();
+    }
+
+    // TODO(vishnun)
+    @Ignore("Disabled until app-helper libraries are available.")
+    @Test
+    public void captureWindowAnimationFrameStats() throws Exception {
+        mWindowAnimationFrameStatsMonitor.start();
+        //AppHelperWrapper.getInstance().getHelper(CHROME).open();
+        //AppHelperWrapper.getInstance().getHelper(CHROME).exit();
+        mWindowAnimationFrameStatsMonitor.stop();
+    }
+}
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitorTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitorTest.java
new file mode 100644
index 0000000..56284d7
--- /dev/null
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowManagerTraceMonitorTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.monitor;
+
+import static com.android.server.wm.nano.WindowManagerTraceFileProto.MAGIC_NUMBER_H;
+import static com.android.server.wm.nano.WindowManagerTraceFileProto.MAGIC_NUMBER_L;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.server.wm.nano.WindowManagerTraceFileProto;
+
+import com.google.common.io.Files;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+
+/**
+ * Contains {@link WindowManagerTraceMonitor} tests.
+ * To run this test: {@code atest FlickerLibTest:WindowManagerTraceMonitorTest}
+ */
+public class WindowManagerTraceMonitorTest {
+    private WindowManagerTraceMonitor mWindowManagerTraceMonitor;
+
+    @Before
+    public void setup() {
+        mWindowManagerTraceMonitor = new WindowManagerTraceMonitor();
+    }
+
+    @After
+    public void teardown() {
+        mWindowManagerTraceMonitor.stop();
+        mWindowManagerTraceMonitor.getOutputTraceFilePath("captureWindowTrace").toFile().delete();
+    }
+
+    @Test
+    public void canStartWindowTrace() throws Exception {
+        mWindowManagerTraceMonitor.start();
+        assertThat(mWindowManagerTraceMonitor.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void canStopWindowTrace() throws Exception {
+        mWindowManagerTraceMonitor.start();
+        assertThat(mWindowManagerTraceMonitor.isEnabled()).isTrue();
+        mWindowManagerTraceMonitor.stop();
+        assertThat(mWindowManagerTraceMonitor.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void captureWindowTrace() throws Exception {
+        mWindowManagerTraceMonitor.start();
+        mWindowManagerTraceMonitor.stop();
+        File testFile = mWindowManagerTraceMonitor.save("captureWindowTrace").toFile();
+        assertThat(testFile.exists()).isTrue();
+        byte[] trace = Files.toByteArray(testFile);
+        assertThat(trace.length).isGreaterThan(0);
+        WindowManagerTraceFileProto mWindowTraceFileProto = WindowManagerTraceFileProto.parseFrom(
+                trace);
+        assertThat(mWindowTraceFileProto.magicNumber).isEqualTo(
+                (long) MAGIC_NUMBER_H << 32 | MAGIC_NUMBER_L);
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
new file mode 100644
index 0000000..34f4ebb
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static android.view.Surface.rotationToString;
+
+import static com.android.server.wm.flicker.CommonTransitions.changeAppRotation;
+import static com.android.server.wm.flicker.WindowUtils.getAppPosition;
+import static com.android.server.wm.flicker.WindowUtils.getNavigationBarPosition;
+import static com.android.server.wm.flicker.WindowUtils.getStatusBarPosition;
+import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
+
+import android.graphics.Rect;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.util.Log;
+import android.view.Surface;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Cycle through supported app rotations.
+ * To run this test: {@code atest FlickerTest:ChangeAppRotationTest}
+ */
+@RunWith(Parameterized.class)
+@LargeTest
+public class ChangeAppRotationTest extends FlickerTestBase {
+    private int beginRotation;
+    private int endRotation;
+
+    public ChangeAppRotationTest(String beginRotationName, String endRotationName,
+            int beginRotation, int endRotation) {
+        this.testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "SimpleApp");
+        this.beginRotation = beginRotation;
+        this.endRotation = endRotation;
+    }
+
+    @Parameters(name = "{0}-{1}")
+    public static Collection<Object[]> getParams() {
+        int[] supportedRotations =
+                {Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270};
+        Collection<Object[]> params = new ArrayList<>();
+        for (int begin : supportedRotations) {
+            for (int end : supportedRotations) {
+                if (begin != end) {
+                    params.add(new Object[]{rotationToString(begin), rotationToString(end), begin,
+                            end});
+                }
+            }
+        }
+        return params;
+    }
+
+    @Before
+    public void runTransition() {
+        super.runTransition(
+                changeAppRotation(testApp, uiDevice, beginRotation, endRotation).build());
+    }
+
+    @Test
+    public void checkVisibility_navBarWindowIsAlwaysVisible() {
+        checkResults(result -> assertThat(result)
+                .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarWindowIsAlwaysVisible() {
+        checkResults(result -> assertThat(result)
+                .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkPosition_navBarLayerRotatesAndScales() {
+        Rect startingPos = getNavigationBarPosition(beginRotation);
+        Rect endingPos = getNavigationBarPosition(endRotation);
+        checkResults(result -> {
+                    LayersTraceSubject.assertThat(result)
+                            .hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
+                            .inTheBeginning();
+                    LayersTraceSubject.assertThat(result)
+                            .hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, endingPos).atTheEnd();
+                }
+        );
+    }
+
+    @Test
+    public void checkPosition_appLayerRotates() {
+        Rect startingPos = getAppPosition(beginRotation);
+        Rect endingPos = getAppPosition(endRotation);
+        Log.e(TAG, "startingPos=" + startingPos + " endingPos=" + endingPos);
+        checkResults(result -> {
+                    LayersTraceSubject.assertThat(result)
+                            .hasVisibleRegion(testApp.getPackage(), startingPos).inTheBeginning();
+                    LayersTraceSubject.assertThat(result)
+                            .hasVisibleRegion(testApp.getPackage(), endingPos).atTheEnd();
+                }
+        );
+    }
+
+    @Test
+    public void checkPosition_statusBarLayerScales() {
+        Rect startingPos = getStatusBarPosition(beginRotation);
+        Rect endingPos = getStatusBarPosition(endRotation);
+        checkResults(result -> {
+                    LayersTraceSubject.assertThat(result)
+                            .hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, startingPos)
+                            .inTheBeginning();
+                    LayersTraceSubject.assertThat(result)
+                            .hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, endingPos).atTheEnd();
+                }
+        );
+    }
+
+    @Test
+    public void checkVisibility_navBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries());
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToAppTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToAppTest.java
new file mode 100644
index 0000000..2b62fcf
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToAppTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.CommonTransitions.editTextLoseFocusToApp;
+import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
+
+import android.platform.helpers.IAppHelper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test IME window closing back to app window transitions.
+ * To run this test: {@code atest FlickerTests:CloseImeWindowToAppTest}
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class CloseImeWindowToAppTest extends FlickerTestBase {
+
+    private static final String IME_WINDOW_TITLE = "InputMethod";
+    private IAppHelper mImeTestApp = new StandardAppHelper(
+            InstrumentationRegistry.getInstrumentation(),
+            "com.android.server.wm.flicker.testapp", "ImeApp");
+
+    @Before
+    public void runTransition() {
+        super.runTransition(editTextLoseFocusToApp(uiDevice)
+                .includeJankyRuns().build());
+    }
+
+    @Test
+    public void checkVisibility_imeLayerBecomesInvisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(IME_WINDOW_TITLE)
+                .then()
+                .hidesLayer(IME_WINDOW_TITLE)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_imeAppLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(mImeTestApp.getPackage())
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_imeAppWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAppWindowOnTop(mImeTestApp.getPackage())
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkCoveredRegion_noUncoveredRegions() {
+        checkResults(result -> LayersTraceSubject.assertThat(result).coversRegion(
+                getDisplayBounds()).forAllEntries());
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
new file mode 100644
index 0000000..42b161f
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.CommonTransitions.editTextLoseFocusToHome;
+import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
+
+import android.platform.helpers.IAppHelper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test IME window closing to home transitions.
+ * To run this test: {@code atest FlickerTests:CloseImeWindowToHomeTest}
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class CloseImeWindowToHomeTest extends FlickerTestBase {
+
+    private static final String IME_WINDOW_TITLE = "InputMethod";
+    private IAppHelper mImeTestApp = new StandardAppHelper(
+            InstrumentationRegistry.getInstrumentation(),
+            "com.android.server.wm.flicker.testapp", "ImeApp");
+
+    @Before
+    public void runTransition() {
+        super.runTransition(editTextLoseFocusToHome(uiDevice)
+                .includeJankyRuns().build());
+    }
+
+    @Test
+    public void checkVisibility_imeWindowBecomesInvisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsImeWindow(IME_WINDOW_TITLE)
+                .then()
+                .hidesImeWindow(IME_WINDOW_TITLE)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_imeLayerBecomesInvisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(IME_WINDOW_TITLE)
+                .then()
+                .hidesLayer(IME_WINDOW_TITLE)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_imeAppLayerBecomesInvisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(mImeTestApp.getPackage())
+                .then()
+                .hidesLayer(mImeTestApp.getPackage())
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_imeAppWindowBecomesInvisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAppWindowOnTop(mImeTestApp.getPackage())
+                .then()
+                .hidesAppWindowOnTop(mImeTestApp.getPackage())
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkCoveredRegion_noUncoveredRegions() {
+        checkResults(result -> LayersTraceSubject.assertThat(result).coversRegion(
+                getDisplayBounds()).forAllEntries());
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java
new file mode 100644
index 0000000..92bb1ea
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static android.os.SystemClock.sleep;
+import static android.view.Surface.rotationToString;
+
+import static com.android.server.wm.flicker.AutomationUtils.clearRecents;
+import static com.android.server.wm.flicker.AutomationUtils.closePipWindow;
+import static com.android.server.wm.flicker.AutomationUtils.exitSplitScreen;
+import static com.android.server.wm.flicker.AutomationUtils.expandPipWindow;
+import static com.android.server.wm.flicker.AutomationUtils.launchSplitScreen;
+import static com.android.server.wm.flicker.AutomationUtils.stopPackage;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.platform.helpers.IAppHelper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.util.Rational;
+import android.view.Surface;
+
+import com.android.server.wm.flicker.TransitionRunner.TransitionBuilder;
+
+/**
+ * Collection of common transitions which can be used to test different apps or scenarios.
+ */
+class CommonTransitions {
+
+    public static final int ITERATIONS = 1;
+    private static final String TAG = "FLICKER";
+    private static final long APP_LAUNCH_TIMEOUT = 10000;
+
+    private static void setRotation(UiDevice device, int rotation) {
+        try {
+            switch (rotation) {
+                case Surface.ROTATION_270:
+                    device.setOrientationLeft();
+                    break;
+
+                case Surface.ROTATION_90:
+                    device.setOrientationRight();
+                    break;
+
+                case Surface.ROTATION_0:
+                default:
+                    device.setOrientationNatural();
+            }
+            // Wait for animation to complete
+            sleep(3000);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static void clickEditTextWidget(UiDevice device, IAppHelper testApp) {
+        UiObject2 editText = device.findObject(By.res(testApp.getPackage(), "plain_text_input"));
+        editText.click();
+        sleep(500);
+    }
+
+    private static void clickEnterPipButton(UiDevice device, IAppHelper testApp) {
+        UiObject2 enterPipButton = device.findObject(By.res(testApp.getPackage(), "enter_pip"));
+        enterPipButton.click();
+        sleep(500);
+    }
+
+    static TransitionBuilder openAppWarm(IAppHelper testApp, UiDevice
+            device) {
+        return TransitionRunner.newBuilder()
+                .withTag("OpenAppWarm_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBeforeAll(testApp::open)
+                .runBefore(device::pressHome)
+                .runBefore(device::waitForIdle)
+                .run(testApp::open)
+                .runAfterAll(testApp::exit)
+                .runAfterAll(AutomationUtils::setDefaultWait)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder closeAppWithBackKey(IAppHelper testApp, UiDevice
+            device) {
+        return TransitionRunner.newBuilder()
+                .withTag("closeAppWithBackKey_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(testApp::open)
+                .runBefore(device::waitForIdle)
+                .run(device::pressBack)
+                .run(device::waitForIdle)
+                .runAfterAll(testApp::exit)
+                .runAfterAll(AutomationUtils::setDefaultWait)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder closeAppWithHomeKey(IAppHelper testApp, UiDevice
+            device) {
+        return TransitionRunner.newBuilder()
+                .withTag("closeAppWithHomeKey_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(testApp::open)
+                .runBefore(device::waitForIdle)
+                .run(device::pressHome)
+                .run(device::waitForIdle)
+                .runAfterAll(testApp::exit)
+                .runAfterAll(AutomationUtils::setDefaultWait)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder getOpenAppCold(IAppHelper testApp,
+            UiDevice device) {
+        return TransitionRunner.newBuilder()
+                .withTag("OpenAppCold_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(device::pressHome)
+                .runBefore(testApp::exit)
+                .runBefore(device::waitForIdle)
+                .run(testApp::open)
+                .runAfterAll(testApp::exit)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder changeAppRotation(IAppHelper testApp, UiDevice
+            device, int beginRotation, int endRotation) {
+        return TransitionRunner.newBuilder()
+                .withTag("changeAppRotation_" + testApp.getLauncherName()
+                        + rotationToString(beginRotation) + "_" +
+                        rotationToString(endRotation))
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBeforeAll(testApp::open)
+                .runBefore(() -> setRotation(device, beginRotation))
+                .run(() -> setRotation(device, endRotation))
+                .runAfterAll(testApp::exit)
+                .runAfterAll(() -> setRotation(device, Surface.ROTATION_0))
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder changeAppRotation(Intent intent, String intentId, Context context,
+            UiDevice
+                    device, int beginRotation, int endRotation) {
+        final String testTag = "changeAppRotation_" + intentId + "_" +
+                rotationToString(beginRotation) + "_" + rotationToString(endRotation);
+        return TransitionRunner.newBuilder()
+                .withTag(testTag)
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBeforeAll(() -> {
+                            context.startActivity(intent);
+                            device.wait(Until.hasObject(By.pkg(intent.getComponent()
+                                        .getPackageName()).depth(0)), APP_LAUNCH_TIMEOUT);
+                        }
+                )
+                .runBefore(() -> setRotation(device, beginRotation))
+                .run(() -> setRotation(device, endRotation))
+                .runAfterAll(() -> stopPackage(context, intent.getComponent().getPackageName()))
+                .runAfterAll(() -> setRotation(device, Surface.ROTATION_0))
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder appToSplitScreen(IAppHelper testApp, UiDevice device) {
+        return TransitionRunner.newBuilder()
+                .withTag("appToSplitScreen_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(testApp::open)
+                .runBefore(device::waitForIdle)
+                .runBefore(() -> sleep(500))
+                .run(() -> launchSplitScreen(device))
+                .runAfter(() -> exitSplitScreen(device))
+                .runAfterAll(testApp::exit)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder splitScreenToLauncher(IAppHelper testApp, UiDevice device) {
+        return TransitionRunner.newBuilder()
+                .withTag("splitScreenToLauncher_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(testApp::open)
+                .runBefore(device::waitForIdle)
+                .runBefore(() -> launchSplitScreen(device))
+                .run(() -> exitSplitScreen(device))
+                .runAfterAll(testApp::exit)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder editTextSetFocus(UiDevice device) {
+        IAppHelper testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "ImeApp");
+        return TransitionRunner.newBuilder()
+                .withTag("editTextSetFocus_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(device::pressHome)
+                .runBefore(testApp::open)
+                .run(() -> clickEditTextWidget(device, testApp))
+                .runAfterAll(testApp::exit)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder resizeSplitScreen(IAppHelper testAppTop, IAppHelper testAppBottom,
+            UiDevice device, Rational startRatio, Rational stopRatio) {
+        String testTag = "resizeSplitScreen_" + testAppTop.getLauncherName() + "_" +
+                testAppBottom.getLauncherName() + "_" +
+                startRatio.toString().replace("/", ":") + "_to_" +
+                stopRatio.toString().replace("/", ":");
+        return TransitionRunner.newBuilder()
+                .withTag(testTag)
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBeforeAll(() -> clearRecents(device))
+                .runBefore(testAppBottom::open)
+                .runBefore(device::pressHome)
+                .runBefore(testAppTop::open)
+                .runBefore(device::waitForIdle)
+                .runBefore(() -> launchSplitScreen(device))
+                .runBefore(() -> {
+                    UiObject2 snapshot = device.findObject(
+                            By.res("com.google.android.apps.nexuslauncher", "snapshot"));
+                    snapshot.click();
+                })
+                .runBefore(() -> AutomationUtils.resizeSplitScreen(device, startRatio))
+                .run(() -> AutomationUtils.resizeSplitScreen(device, stopRatio))
+                .runAfter(() -> exitSplitScreen(device))
+                .runAfter(device::pressHome)
+                .runAfterAll(testAppTop::exit)
+                .runAfterAll(testAppBottom::exit)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder editTextLoseFocusToHome(UiDevice device) {
+        IAppHelper testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "ImeApp");
+        return TransitionRunner.newBuilder()
+                .withTag("editTextLoseFocusToHome_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(device::pressHome)
+                .runBefore(testApp::open)
+                .runBefore(() -> clickEditTextWidget(device, testApp))
+                .run(device::pressHome)
+                .run(device::waitForIdle)
+                .runAfterAll(testApp::exit)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder editTextLoseFocusToApp(UiDevice device) {
+        IAppHelper testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "ImeApp");
+        return TransitionRunner.newBuilder()
+                .withTag("editTextLoseFocusToApp_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(device::pressHome)
+                .runBefore(testApp::open)
+                .runBefore(() -> clickEditTextWidget(device, testApp))
+                .run(device::pressBack)
+                .run(device::waitForIdle)
+                .runAfterAll(testApp::exit)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder enterPipMode(UiDevice device) {
+        IAppHelper testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "PipApp");
+        return TransitionRunner.newBuilder()
+                .withTag("enterPipMode_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(device::pressHome)
+                .runBefore(testApp::open)
+                .run(() -> clickEnterPipButton(device, testApp))
+                .runAfter(() -> closePipWindow(device))
+                .runAfterAll(testApp::exit)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder exitPipModeToHome(UiDevice device) {
+        IAppHelper testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "PipApp");
+        return TransitionRunner.newBuilder()
+                .withTag("exitPipModeToHome_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(device::pressHome)
+                .runBefore(testApp::open)
+                .runBefore(() -> clickEnterPipButton(device, testApp))
+                .run(() -> closePipWindow(device))
+                .run(device::waitForIdle)
+                .runAfterAll(testApp::exit)
+                .repeat(ITERATIONS);
+    }
+
+    static TransitionBuilder exitPipModeToApp(UiDevice device) {
+        IAppHelper testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "PipApp");
+        return TransitionRunner.newBuilder()
+                .withTag("exitPipModeToApp_" + testApp.getLauncherName())
+                .runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
+                .runBefore(device::pressHome)
+                .runBefore(testApp::open)
+                .runBefore(() -> clickEnterPipButton(device, testApp))
+                .run(() -> expandPipWindow(device))
+                .run(device::waitForIdle)
+                .runAfterAll(testApp::exit)
+                .repeat(ITERATIONS);
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.java
new file mode 100644
index 0000000..fec248c
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import android.platform.helpers.IAppHelper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.UiDevice;
+import android.util.Rational;
+import android.view.Surface;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests to help debug individual transitions, capture video recordings and create test cases.
+ */
+@Ignore("Used for debugging transitions used in FlickerTests.")
+@RunWith(AndroidJUnit4.class)
+public class DebugTest {
+    private IAppHelper testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+            "com.android.server.wm.flicker.testapp", "SimpleApp");
+    private UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+    /**
+     * atest FlickerTest:DebugTests#openAppCold
+     */
+    @Test
+    public void openAppCold() {
+        CommonTransitions.getOpenAppCold(testApp, uiDevice).recordAllRuns().build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#openAppWarm
+     */
+    @Test
+    public void openAppWarm() {
+        CommonTransitions.openAppWarm(testApp, uiDevice).recordAllRuns().build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#changeOrientationFromNaturalToLeft
+     */
+    @Test
+    public void changeOrientationFromNaturalToLeft() {
+        CommonTransitions.changeAppRotation(testApp, uiDevice, Surface.ROTATION_0,
+                Surface.ROTATION_270).recordAllRuns().build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#closeAppWithBackKey
+     */
+    @Test
+    public void closeAppWithBackKey() {
+        CommonTransitions.closeAppWithBackKey(testApp, uiDevice).recordAllRuns().build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#closeAppWithHomeKey
+     */
+    @Test
+    public void closeAppWithHomeKey() {
+        CommonTransitions.closeAppWithHomeKey(testApp, uiDevice).recordAllRuns().build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#openAppToSplitScreen
+     */
+    @Test
+    public void openAppToSplitScreen() {
+        CommonTransitions.appToSplitScreen(testApp, uiDevice).includeJankyRuns().recordAllRuns()
+                .build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#splitScreenToLauncher
+     */
+    @Test
+    public void splitScreenToLauncher() {
+        CommonTransitions.splitScreenToLauncher(testApp,
+                uiDevice).includeJankyRuns().recordAllRuns()
+                .build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#resizeSplitScreen
+     */
+    @Test
+    public void resizeSplitScreen() {
+        IAppHelper bottomApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "ImeApp");
+        CommonTransitions.resizeSplitScreen(testApp, bottomApp, uiDevice, new Rational(1, 3),
+                new Rational(2, 3)).includeJankyRuns().recordEachRun().build().run();
+    }
+
+    // IME tests
+
+    /**
+     * atest FlickerTest:DebugTests#editTextSetFocus
+     */
+    @Test
+    public void editTextSetFocus() {
+        CommonTransitions.editTextSetFocus(uiDevice).includeJankyRuns().recordEachRun()
+                .build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#editTextLoseFocusToHome
+     */
+    @Test
+    public void editTextLoseFocusToHome() {
+        CommonTransitions.editTextLoseFocusToHome(uiDevice).includeJankyRuns().recordEachRun()
+                .build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#editTextLoseFocusToApp
+     */
+    @Test
+    public void editTextLoseFocusToApp() {
+        CommonTransitions.editTextLoseFocusToHome(uiDevice).includeJankyRuns().recordEachRun()
+                .build().run();
+    }
+
+    // PIP tests
+
+    /**
+     * atest FlickerTest:DebugTests#enterPipMode
+     */
+    @Test
+    public void enterPipMode() {
+        CommonTransitions.enterPipMode(uiDevice).includeJankyRuns().recordEachRun().build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#exitPipModeToHome
+     */
+    @Test
+    public void exitPipModeToHome() {
+        CommonTransitions.exitPipModeToHome(uiDevice).includeJankyRuns().recordEachRun()
+                .build().run();
+    }
+
+    /**
+     * atest FlickerTest:DebugTests#exitPipModeToApp
+     */
+    @Test
+    public void exitPipModeToApp() {
+        CommonTransitions.exitPipModeToApp(uiDevice).includeJankyRuns().recordEachRun()
+                .build().run();
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java b/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java
new file mode 100644
index 0000000..7061b23
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.AutomationUtils.setDefaultWait;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.platform.helpers.IAppHelper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.UiDevice;
+import android.util.Log;
+
+import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
+
+import org.junit.After;
+import org.junit.AfterClass;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Base class of all Flicker test that performs common functions for all flicker tests:
+ * <p>
+ * - 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.
+ */
+public class FlickerTestBase {
+    public static final String TAG = "FLICKER";
+    static final String NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar";
+    static final String STATUS_BAR_WINDOW_TITLE = "StatusBar";
+    static final String DOCKED_STACK_DIVIDER = "DockedStackDivider";
+    private static HashMap<String, List<TransitionResult>> transitionResults =
+            new HashMap<>();
+    IAppHelper testApp;
+    UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+    private List<TransitionResult> results;
+    private TransitionResult lastResult = null;
+
+    /**
+     * Teardown any system settings and clean up test artifacts from the file system.
+     *
+     * Note: test artifacts for failed tests will remain on the device.
+     */
+    @AfterClass
+    public static void teardown() {
+        setDefaultWait();
+        transitionResults.values().stream()
+                .flatMap(List::stream)
+                .forEach(result -> {
+                    if (result.canDelete()) {
+                        result.delete();
+                    } else {
+                        if (result.layersTraceExists()) {
+                            Log.e(TAG, "Layers trace saved to " + result.getLayersTracePath());
+                        }
+                        if (result.windowManagerTraceExists()) {
+                            Log.e(TAG, "WindowManager trace saved to " + result
+                                    .getWindowManagerTracePath
+                                            ());
+                        }
+                        if (result.screenCaptureVideoExists()) {
+                            Log.e(TAG, "Screen capture video saved to " + result
+                                    .screenCaptureVideo.toString());
+                        }
+                    }
+                });
+    }
+
+    /**
+     * Runs a transition, returns a cached result if the transition has run before.
+     */
+    void runTransition(TransitionRunner transition) {
+        if (transitionResults.containsKey(transition.getTestTag())) {
+            results = transitionResults.get(transition.getTestTag());
+            return;
+        }
+        results = transition.run().getResults();
+        /* Fail if we don't have any results due to jank */
+        assertWithMessage("No results to test because all transition runs were invalid because "
+                + "of Jank").that(results).isNotEmpty();
+        transitionResults.put(transition.getTestTag(), results);
+    }
+
+    /**
+     * Goes through a list of transition results and checks assertions on each result.
+     */
+    void checkResults(Consumer<TransitionResult> assertion) {
+
+        for (TransitionResult result : results) {
+            lastResult = result;
+            assertion.accept(result);
+        }
+        lastResult = null;
+    }
+
+    /**
+     * Kludge to mark a file for saving. If {@code checkResults} fails, the last result is not
+     * cleared. This indicates the assertion failed for the result, so mark it for saving.
+     */
+    @After
+    public void markArtifactsForSaving() {
+        if (lastResult != null) {
+            lastResult.flagForSaving();
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppColdTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppColdTest.java
new file mode 100644
index 0000000..7e71369
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppColdTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.CommonTransitions.getOpenAppCold;
+import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
+import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test cold launch app from launcher.
+ * To run this test: {@code atest FlickerTests:OpenAppColdTest}
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class OpenAppColdTest extends FlickerTestBase {
+
+    public OpenAppColdTest() {
+        this.testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "SimpleApp");
+    }
+
+    @Before
+    public void runTransition() {
+        super.runTransition(getOpenAppCold(testApp, uiDevice).build());
+    }
+
+    @Test
+    public void checkVisibility_navBarWindowIsAlwaysVisible() {
+        checkResults(result -> assertThat(result)
+                .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarWindowIsAlwaysVisible() {
+        checkResults(result -> assertThat(result)
+                .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_wallpaperWindowBecomesInvisible() {
+        checkResults(result -> assertThat(result)
+                .showsBelowAppWindow("wallpaper")
+                .then()
+                .hidesBelowAppWindow("wallpaper")
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkZOrder_appWindowReplacesLauncherAsTopWindow() {
+        checkResults(result -> assertThat(result)
+                .showsAppWindowOnTop(
+                        "com.google.android.apps.nexuslauncher/.NexusLauncherActivity")
+                .then()
+                .showsAppWindowOnTop(testApp.getPackage())
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkCoveredRegion_noUncoveredRegions() {
+        checkResults(result -> LayersTraceSubject.assertThat(result).coversRegion(
+                getDisplayBounds()).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_navBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_wallpaperLayerBecomesInvisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer("wallpaper")
+                .then()
+                .hidesLayer("wallpaper")
+                .forAllEntries());
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppToSplitScreenTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppToSplitScreenTest.java
new file mode 100644
index 0000000..745569a
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppToSplitScreenTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.CommonTransitions.appToSplitScreen;
+import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test open app to split screen.
+ * To run this test: {@code atest FlickerTests:OpenAppToSplitScreenTest}
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class OpenAppToSplitScreenTest extends FlickerTestBase {
+
+    public OpenAppToSplitScreenTest() {
+        this.testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "SimpleApp");
+    }
+
+    @Before
+    public void runTransition() {
+        super.runTransition(appToSplitScreen(testApp, uiDevice).includeJankyRuns().build());
+    }
+
+    @Test
+    public void checkVisibility_navBarWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_dividerWindowBecomesVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .hidesAboveAppWindow(DOCKED_STACK_DIVIDER)
+                .then()
+                .showsAboveAppWindow(DOCKED_STACK_DIVIDER)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkCoveredRegion_noUncoveredRegions() {
+        checkResults(result ->
+                LayersTraceSubject.assertThat(result)
+                        .coversRegion(getDisplayBounds()).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_navBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_dividerLayerBecomesVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .hidesLayer(DOCKED_STACK_DIVIDER)
+                .then()
+                .showsLayer(DOCKED_STACK_DIVIDER)
+                .forAllEntries());
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppWarmTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppWarmTest.java
new file mode 100644
index 0000000..de7639d
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppWarmTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.CommonTransitions.openAppWarm;
+import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
+import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test warm launch app.
+ * To run this test: {@code atest FlickerTests:OpenAppWarmTest}
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class OpenAppWarmTest extends FlickerTestBase {
+
+    public OpenAppWarmTest() {
+        this.testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "SimpleApp");
+    }
+
+    @Before
+    public void runTransition() {
+        super.runTransition(openAppWarm(testApp, uiDevice).build());
+    }
+
+    @Test
+    public void checkVisibility_navBarIsAlwaysVisible() {
+        checkResults(result -> assertThat(result)
+                .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarIsAlwaysVisible() {
+        checkResults(result -> assertThat(result)
+                .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_wallpaperBecomesInvisible() {
+        checkResults(result -> assertThat(result)
+                .showsBelowAppWindow("wallpaper")
+                .then()
+                .hidesBelowAppWindow("wallpaper")
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkZOrder_appWindowReplacesLauncherAsTopWindow() {
+        checkResults(result -> assertThat(result)
+                .showsAppWindowOnTop(
+                        "com.google.android.apps.nexuslauncher/.NexusLauncherActivity")
+                .then()
+                .showsAppWindowOnTop(testApp.getPackage())
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkCoveredRegion_noUncoveredRegions() {
+        checkResults(result -> LayersTraceSubject.assertThat(result).coversRegion(
+                getDisplayBounds()).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_navBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_wallpaperLayerBecomesInvisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer("wallpaper")
+                .then()
+                .hidesLayer("wallpaper")
+                .forAllEntries());
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenImeWindowTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenImeWindowTest.java
new file mode 100644
index 0000000..1bd519c
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenImeWindowTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.CommonTransitions.editTextSetFocus;
+import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
+
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test IME window opening transitions.
+ * To run this test: {@code atest FlickerTests:OpenImeWindowTest}
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class OpenImeWindowTest extends FlickerTestBase {
+
+    private static final String IME_WINDOW_TITLE = "InputMethod";
+
+    @Before
+    public void runTransition() {
+        super.runTransition(editTextSetFocus(uiDevice)
+                .includeJankyRuns().build());
+    }
+
+    @Test
+    public void checkVisibility_imeWindowBecomesVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .hidesImeWindow(IME_WINDOW_TITLE)
+                .then()
+                .showsImeWindow(IME_WINDOW_TITLE)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_imeLayerBecomesVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .hidesLayer(IME_WINDOW_TITLE)
+                .then()
+                .showsLayer(IME_WINDOW_TITLE)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkCoveredRegion_noUncoveredRegions() {
+        checkResults(result -> LayersTraceSubject.assertThat(result).coversRegion(
+                getDisplayBounds()).forAllEntries());
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ResizeSplitScreenTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/ResizeSplitScreenTest.java
new file mode 100644
index 0000000..8a15cbd
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ResizeSplitScreenTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.CommonTransitions.resizeSplitScreen;
+import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
+import static com.android.server.wm.flicker.WindowUtils.getDockedStackDividerInset;
+import static com.android.server.wm.flicker.WindowUtils.getNavigationBarHeight;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.graphics.Rect;
+import android.platform.helpers.IAppHelper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Rational;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test split screen resizing window transitions.
+ * To run this test: {@code atest FlickerTests:ResizeSplitScreenTest}
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class ResizeSplitScreenTest extends FlickerTestBase {
+
+    public ResizeSplitScreenTest() {
+        this.testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "SimpleApp");
+    }
+
+    @Before
+    public void runTransition() {
+        IAppHelper bottomApp = new StandardAppHelper(InstrumentationRegistry
+                .getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "ImeApp");
+        super.runTransition(resizeSplitScreen(testApp, bottomApp, uiDevice, new Rational(1, 3),
+                new Rational(2, 3)).includeJankyRuns().build());
+    }
+
+    @Test
+    public void checkVisibility_navBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(NAVIGATION_BAR_WINDOW_TITLE)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(STATUS_BAR_WINDOW_TITLE)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_topAppLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer("SimpleActivity")
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_bottomAppLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer("ImeActivity")
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_dividerLayerIsAlwaysVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(DOCKED_STACK_DIVIDER)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkPosition_appsStartingBounds() {
+        Rect displayBounds = getDisplayBounds();
+        checkResults(result -> {
+            LayersTrace entries = LayersTrace.parseFrom(result.getLayersTrace(),
+                    result.getLayersTracePath());
+
+            assertThat(entries.getEntries()).isNotEmpty();
+            Rect startingDividerBounds = entries.getEntries().get(0).getVisibleBounds
+                    (DOCKED_STACK_DIVIDER);
+
+            Rect startingTopAppBounds = new Rect(0, 0, startingDividerBounds.right,
+                    startingDividerBounds.top + getDockedStackDividerInset());
+
+            Rect startingBottomAppBounds = new Rect(0,
+                    startingDividerBounds.bottom - getDockedStackDividerInset(),
+                    displayBounds.right,
+                    displayBounds.bottom - getNavigationBarHeight());
+
+            LayersTraceSubject.assertThat(result)
+                    .hasVisibleRegion("SimpleActivity", startingTopAppBounds)
+                    .inTheBeginning();
+
+            LayersTraceSubject.assertThat(result)
+                    .hasVisibleRegion("ImeActivity", startingBottomAppBounds)
+                    .inTheBeginning();
+        });
+    }
+
+    @Test
+    public void checkPosition_appsEndingBounds() {
+        Rect displayBounds = getDisplayBounds();
+        checkResults(result -> {
+            LayersTrace entries = LayersTrace.parseFrom(result.getLayersTrace(),
+                    result.getLayersTracePath());
+
+            assertThat(entries.getEntries()).isNotEmpty();
+            Rect endingDividerBounds = entries.getEntries().get(
+                    entries.getEntries().size() - 1).getVisibleBounds(
+                    DOCKED_STACK_DIVIDER);
+
+            Rect startingTopAppBounds = new Rect(0, 0, endingDividerBounds.right,
+                    endingDividerBounds.top + getDockedStackDividerInset());
+
+            Rect startingBottomAppBounds = new Rect(0,
+                    endingDividerBounds.bottom - getDockedStackDividerInset(),
+                    displayBounds.right,
+                    displayBounds.bottom - getNavigationBarHeight());
+
+            LayersTraceSubject.assertThat(result)
+                    .hasVisibleRegion("SimpleActivity", startingTopAppBounds)
+                    .atTheEnd();
+
+            LayersTraceSubject.assertThat(result)
+                    .hasVisibleRegion("ImeActivity", startingBottomAppBounds)
+                    .atTheEnd();
+        });
+    }
+
+    @Test
+    public void checkVisibility_navBarWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE)
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_topAppWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAppWindow("SimpleActivity")
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_bottomAppWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAppWindow("ImeActivity")
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_dividerWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAboveAppWindow(DOCKED_STACK_DIVIDER)
+                .forAllEntries());
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
new file mode 100644
index 0000000..3eab68d
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static android.view.Surface.rotationToString;
+
+import static com.android.server.wm.flicker.CommonTransitions.changeAppRotation;
+import static com.android.server.wm.flicker.WindowUtils.getAppPosition;
+import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
+import static com.android.server.wm.flicker.WindowUtils.getNavigationBarPosition;
+import static com.android.server.wm.flicker.testapp.ActivityOptions.EXTRA_STARVE_UI_THREAD;
+import static com.android.server.wm.flicker.testapp.ActivityOptions.SEAMLESS_ACTIVITY_COMPONENT_NAME;
+
+import android.content.Intent;
+import android.graphics.Rect;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.view.Surface;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Cycle through supported app rotations using seamless rotations.
+ * To run this test: {@code atest FlickerTests:SeamlessAppRotationTest}
+ */
+@LargeTest
+@RunWith(Parameterized.class)
+public class SeamlessAppRotationTest extends FlickerTestBase {
+    private int mBeginRotation;
+    private int mEndRotation;
+    private Intent mIntent;
+
+    public SeamlessAppRotationTest(String testId, Intent intent, int beginRotation,
+            int endRotation) {
+        this.mIntent = intent;
+        this.mBeginRotation = beginRotation;
+        this.mEndRotation = endRotation;
+    }
+
+    @Parameters(name = "{0}")
+    public static Collection<Object[]> getParams() {
+        int[] supportedRotations =
+                {Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270};
+        Collection<Object[]> params = new ArrayList<>();
+
+        ArrayList<Intent> testIntents = new ArrayList<>();
+
+        // launch test activity that supports seamless rotation
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setComponent(SEAMLESS_ACTIVITY_COMPONENT_NAME);
+        testIntents.add(intent);
+
+        // launch test activity that supports seamless rotation with a busy UI thread to miss frames
+        // when the app is asked to redraw
+        intent = new Intent(intent);
+        intent.putExtra(EXTRA_STARVE_UI_THREAD, true);
+        testIntents.add(intent);
+
+        for (Intent testIntent : testIntents) {
+            for (int begin : supportedRotations) {
+                for (int end : supportedRotations) {
+                    if (begin != end) {
+                        String testId = rotationToString(begin) + "_" + rotationToString(end);
+                        if (testIntent.getExtras() != null &&
+                                testIntent.getExtras().getBoolean(EXTRA_STARVE_UI_THREAD)) {
+                            testId += "_" + "BUSY_UI_THREAD";
+                        }
+                        params.add(new Object[]{testId, testIntent, begin, end});
+                    }
+                }
+            }
+        }
+        return params;
+    }
+
+    @Before
+    public void runTransition() {
+        String intentId = "";
+        if (mIntent.getExtras() != null &&
+                mIntent.getExtras().getBoolean(EXTRA_STARVE_UI_THREAD)) {
+            intentId = "BUSY_UI_THREAD";
+        }
+
+        super.runTransition(
+                changeAppRotation(mIntent, intentId, InstrumentationRegistry.getContext(),
+                        uiDevice, mBeginRotation, mEndRotation).repeat(5).build());
+    }
+
+    @Test
+    public void checkVisibility_navBarWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkPosition_navBarLayerRotatesAndScales() {
+        Rect startingPos = getNavigationBarPosition(mBeginRotation);
+        Rect endingPos = getNavigationBarPosition(mEndRotation);
+        if (startingPos.equals(endingPos)) {
+            checkResults(result -> LayersTraceSubject.assertThat(result)
+                    .hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
+                    .forAllEntries());
+        } else {
+            checkResults(result -> LayersTraceSubject.assertThat(result)
+                    .hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
+                    .inTheBeginning());
+            checkResults(result -> LayersTraceSubject.assertThat(result)
+                    .hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, endingPos)
+                    .atTheEnd());
+        }
+    }
+
+    @Test
+    public void checkPosition_appLayerRotates() {
+        Rect startingPos = getAppPosition(mBeginRotation);
+        Rect endingPos = getAppPosition(mEndRotation);
+        if (startingPos.equals(endingPos)) {
+            checkResults(result -> LayersTraceSubject.assertThat(result)
+                    .hasVisibleRegion(mIntent.getComponent().getPackageName(), startingPos)
+                    .forAllEntries());
+        } else {
+            checkResults(result -> LayersTraceSubject.assertThat(result)
+                    .hasVisibleRegion(mIntent.getComponent().getPackageName(), startingPos)
+                    .then()
+                    .hasVisibleRegion(mIntent.getComponent().getPackageName(), endingPos)
+                    .forAllEntries());
+        }
+    }
+
+    @Test
+    public void checkCoveredRegion_noUncoveredRegions() {
+        Rect startingBounds = getDisplayBounds(mBeginRotation);
+        Rect endingBounds = getDisplayBounds(mEndRotation);
+        if (startingBounds.equals(endingBounds)) {
+            checkResults(result ->
+                    LayersTraceSubject.assertThat(result)
+                            .coversRegion(startingBounds)
+                            .forAllEntries());
+        } else {
+            checkResults(result ->
+                    LayersTraceSubject.assertThat(result)
+                            .coversRegion(startingBounds)
+                            .then()
+                            .coversRegion(endingBounds)
+                            .forAllEntries());
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/SplitScreenToLauncherTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/SplitScreenToLauncherTest.java
new file mode 100644
index 0000000..40bd4e9
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/SplitScreenToLauncherTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import static com.android.server.wm.flicker.CommonTransitions.splitScreenToLauncher;
+import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test open app to split screen.
+ * To run this test: {@code atest FlickerTests:SplitScreenToLauncherTest}
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class SplitScreenToLauncherTest extends FlickerTestBase {
+
+    public SplitScreenToLauncherTest() {
+        this.testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+                "com.android.server.wm.flicker.testapp", "SimpleApp");
+    }
+
+    @Before
+    public void runTransition() {
+        super.runTransition(splitScreenToLauncher(testApp, uiDevice).includeJankyRuns().build());
+    }
+
+    @Test
+    public void checkCoveredRegion_noUncoveredRegions() {
+        checkResults(result ->
+                LayersTraceSubject.assertThat(result)
+                        .coversRegion(getDisplayBounds()).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_dividerLayerBecomesInVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(DOCKED_STACK_DIVIDER)
+                .then()
+                .hidesLayer(DOCKED_STACK_DIVIDER)
+                .forAllEntries());
+    }
+
+    @FlakyTest(bugId = 79686616)
+    @Test
+    public void checkVisibility_appLayerBecomesInVisible() {
+        checkResults(result -> LayersTraceSubject.assertThat(result)
+                .showsLayer(testApp.getPackage())
+                .then()
+                .hidesLayer(testApp.getPackage())
+                .forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_navBarWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_statusBarWindowIsAlwaysVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries());
+    }
+
+    @Test
+    public void checkVisibility_dividerWindowBecomesInVisible() {
+        checkResults(result -> WmTraceSubject.assertThat(result)
+                .showsAboveAppWindow(DOCKED_STACK_DIVIDER)
+                .then()
+                .hidesAboveAppWindow(DOCKED_STACK_DIVIDER)
+                .forAllEntries());
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/StandardAppHelper.java b/tests/FlickerTests/src/com/android/server/wm/flicker/StandardAppHelper.java
new file mode 100644
index 0000000..79a0220
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/StandardAppHelper.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker;
+
+import android.app.Instrumentation;
+import android.platform.helpers.AbstractStandardAppHelper;
+
+/**
+ * Class to take advantage of {@code IAppHelper} interface so the same test can be run against
+ * first party and third party apps.
+ */
+public class StandardAppHelper extends AbstractStandardAppHelper {
+    private final String mPackageName;
+    private final String mLauncherName;
+
+    public StandardAppHelper(Instrumentation instr, String packageName, String launcherName) {
+        super(instr);
+        mPackageName = packageName;
+        mLauncherName = launcherName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getPackage() {
+        return mPackageName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getLauncherName() {
+        return mLauncherName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void dismissInitialDialogs() {
+
+    }
+}
diff --git a/tests/FlickerTests/test-apps/Android.mk b/tests/FlickerTests/test-apps/Android.mk
new file mode 100644
index 0000000..9af9f444
--- /dev/null
+++ b/tests/FlickerTests/test-apps/Android.mk
@@ -0,0 +1,15 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+include $(call all-subdir-makefiles)
diff --git a/tests/FlickerTests/test-apps/flickerapp/Android.mk b/tests/FlickerTests/test-apps/flickerapp/Android.mk
new file mode 100644
index 0000000..b916900
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := FlickerTestApp
+LOCAL_MODULE_TAGS := tests optional
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SDK_VERSION := current
+LOCAL_COMPATIBILITY_SUITE := device-tests
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := flickertestapplib
+LOCAL_MODULE_TAGS := tests optional
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := src/com/android/server/wm/flicker/testapp/ActivityOptions.java
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
new file mode 100644
index 0000000..b694172
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.wm.flicker.testapp">
+
+    <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="27"/>
+    <application
+        android:allowBackup="false"
+        android:supportsRtl="true">
+        <activity android:name=".SimpleActivity"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.SimpleActivity"
+                  android:label="SimpleApp">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity android:name=".ImeActivity"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivity"
+                  android:label="ImeApp">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity android:name=".PipActivity"
+                  android:resizeableActivity="true"
+                  android:supportsPictureInPicture="true"
+                  android:configChanges=
+                      "screenSize|smallestScreenSize|screenLayout|orientation"
+                  android:taskAffinity="com.android.server.wm.flicker.testapp.PipActivity"
+                  android:label="PipApp">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity android:name=".SeamlessRotationActivity"
+                  android:taskAffinity=
+                      "com.android.server.wm.flicker.testapp.SeamlessRotationActivity"
+                  android:configChanges="orientation|screenSize"
+                  android:label="SeamlessApp">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml
new file mode 100644
index 0000000..d5eb023
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/holo_green_light">
+    <EditText android:id="@+id/plain_text_input"
+              android:layout_height="wrap_content"
+              android:layout_width="match_parent"
+              android:inputType="text"/>
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
new file mode 100644
index 0000000..2c58d91
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_pip.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/holo_blue_bright">
+    <Button android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/enter_pip"
+            android:text="Enter PIP"/>
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_simple.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_simple.xml
new file mode 100644
index 0000000..5d94e51
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_simple.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/holo_orange_light">
+
+</LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
new file mode 100644
index 0000000..1899411
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.testapp;
+
+import android.content.ComponentName;
+
+public class ActivityOptions {
+    public static final String EXTRA_STARVE_UI_THREAD = "StarveUiThread";
+    public static final ComponentName SEAMLESS_ACTIVITY_COMPONENT_NAME =
+            new ComponentName("com.android.server.wm.flicker.testapp",
+                    "com.android.server.wm.flicker.testapp.SeamlessRotationActivity");
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivity.java
new file mode 100644
index 0000000..df60460
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.testapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+public class ImeActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        WindowManager.LayoutParams p = getWindow().getAttributes();
+        p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
+                .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        getWindow().setAttributes(p);
+        setContentView(R.layout.activity_ime);
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
new file mode 100644
index 0000000..9a8f399
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.testapp;
+
+import android.app.Activity;
+import android.app.PictureInPictureParams;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.Rational;
+import android.view.WindowManager;
+import android.widget.Button;
+
+public class PipActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        WindowManager.LayoutParams p = getWindow().getAttributes();
+        p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
+                .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        getWindow().setAttributes(p);
+        setContentView(R.layout.activity_pip);
+        Button enterPip = (Button) findViewById(R.id.enter_pip);
+
+        PictureInPictureParams params = new PictureInPictureParams.Builder()
+                .setAspectRatio(new Rational(1, 1))
+                .setSourceRectHint(new Rect(0, 0, 100, 100))
+                .build();
+
+        enterPip.setOnClickListener((v) -> enterPictureInPictureMode(params));
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java
new file mode 100644
index 0000000..3a0c1c9
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SeamlessRotationActivity.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.testapp;
+
+import static android.os.SystemClock.sleep;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+
+import static com.android.server.wm.flicker.testapp.ActivityOptions.EXTRA_STARVE_UI_THREAD;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.view.Window;
+import android.view.WindowManager;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class SeamlessRotationActivity extends Activity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        enableSeamlessRotation();
+        setContentView(R.layout.activity_simple);
+        boolean starveUiThread = getIntent().getExtras() != null &&
+                getIntent().getExtras().getBoolean(EXTRA_STARVE_UI_THREAD);
+        if (starveUiThread) {
+            starveUiThread();
+        }
+    }
+
+    private void starveUiThread() {
+        Handler handler = new Handler(Looper.getMainLooper(), (Message unused) -> {
+            sleep(20);
+            return true;
+        });
+        new Timer().schedule(new TimerTask() {
+            @Override
+            public void run() {
+                handler.sendEmptyMessage(0);
+            }
+        }, 0, 21);
+    }
+
+    private void enableSeamlessRotation() {
+        WindowManager.LayoutParams p = getWindow().getAttributes();
+        p.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+        p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
+                .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+                WindowManager.LayoutParams.FLAG_FULLSCREEN);
+        getWindow().setAttributes(p);
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SimpleActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SimpleActivity.java
new file mode 100644
index 0000000..699abf8
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/SimpleActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.testapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+public class SimpleActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        WindowManager.LayoutParams p = getWindow().getAttributes();
+        p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
+                .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        getWindow().setAttributes(p);
+        setContentView(R.layout.activity_simple);
+    }
+}
diff --git a/tests/Internal/res/xml/livewallpaper.xml b/tests/Internal/res/xml/livewallpaper.xml
index dbb0e47..6b5e84e 100644
--- a/tests/Internal/res/xml/livewallpaper.xml
+++ b/tests/Internal/res/xml/livewallpaper.xml
@@ -16,5 +16,4 @@
   -->
 <wallpaper
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-    androidprv:supportsAmbientMode="true"/>
\ No newline at end of file
+    android:supportsAmbientMode="true"/>
\ No newline at end of file
diff --git a/tests/Internal/src/android/app/WallpaperInfoTest.java b/tests/Internal/src/android/app/WallpaperInfoTest.java
index 9d26270..98045ae 100644
--- a/tests/Internal/src/android/app/WallpaperInfoTest.java
+++ b/tests/Internal/src/android/app/WallpaperInfoTest.java
@@ -55,13 +55,13 @@
 
         // Defined as true in the XML
         assertTrue("supportsAmbientMode should be true, as defined in the XML.",
-                wallpaperInfo.getSupportsAmbientMode());
+                wallpaperInfo.supportsAmbientMode());
         Parcel parcel = Parcel.obtain();
         wallpaperInfo.writeToParcel(parcel, 0 /* flags */);
         parcel.setDataPosition(0);
         WallpaperInfo fromParcel = WallpaperInfo.CREATOR.createFromParcel(parcel);
         assertTrue("supportsAmbientMode should have been restored from parcelable",
-                fromParcel.getSupportsAmbientMode());
+                fromParcel.supportsAmbientMode());
         parcel.recycle();
     }
 }
diff --git a/tests/SystemMemoryTest/Android.mk b/tests/SystemMemoryTest/Android.mk
new file mode 100644
index 0000000..09a1618
--- /dev/null
+++ b/tests/SystemMemoryTest/Android.mk
@@ -0,0 +1,17 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tests/SystemMemoryTest/README.txt b/tests/SystemMemoryTest/README.txt
new file mode 100644
index 0000000..de5042c
--- /dev/null
+++ b/tests/SystemMemoryTest/README.txt
@@ -0,0 +1,21 @@
+This directory contains a test for system server memory use.
+
+Directory structure
+===================
+device
+  - those parts of the test that run on device.
+
+host
+  - those parts of the test that run on host.
+
+Running the test
+================
+
+You can manually run the test as follows:
+
+  make tradefed-all system-memory-test SystemMemoryTestDevice
+  tradefed.sh run commandAndExit template/local_min --template:map test=system-memory-test
+
+This installs and runs the test on device. You can see the metrics in the
+tradefed output.
+
diff --git a/tests/SystemMemoryTest/device/Android.mk b/tests/SystemMemoryTest/device/Android.mk
new file mode 100644
index 0000000..75408df
--- /dev/null
+++ b/tests/SystemMemoryTest/device/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_PACKAGE_NAME := SystemMemoryTestDevice
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_COMPATIBILITY_SUITE := general-tests
+include $(BUILD_PACKAGE)
diff --git a/tests/SystemMemoryTest/device/AndroidManifest.xml b/tests/SystemMemoryTest/device/AndroidManifest.xml
new file mode 100644
index 0000000..e5e7844f
--- /dev/null
+++ b/tests/SystemMemoryTest/device/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.sysmem.device">
+
+    <uses-sdk android:minSdkVersion="19" />
+
+    <instrumentation
+            android:name="com.android.tests.sysmem.device.Cujs"
+            android:targetPackage="com.android.tests.sysmem.device" />
+
+    <application
+            android:allowBackup="false"
+            android:label="System Memory Test">
+    </application>
+</manifest>
diff --git a/tests/SystemMemoryTest/device/src/com/android/tests/sysmem/device/Cujs.java b/tests/SystemMemoryTest/device/src/com/android/tests/sysmem/device/Cujs.java
new file mode 100644
index 0000000..6c0c593
--- /dev/null
+++ b/tests/SystemMemoryTest/device/src/com/android/tests/sysmem/device/Cujs.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.sysmem.device;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Critical user journeys used to exercise the system for test, driven from
+ * the device.
+ */
+public class Cujs extends Instrumentation {
+
+    private static final String TAG = "SystemMemoryTest";
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        start();
+    }
+
+    @Override
+    public void onStart() {
+        // TODO: Exercise the system in more interesting ways.
+        // Mostly what matters is that whatever we do here is sustainable: it
+        // can be repeated indefinitely on the system without causing
+        // problems.  For example, launching activities is fine. Installing
+        // applications is only fine if we also uninstall them as part of the
+        // test.
+        try {
+            Log.i(TAG, "Sleeping for 10 seconds...");
+            Thread.sleep(10 * 1000);
+        } catch (InterruptedException ignored) {
+        }
+
+        finish(Activity.RESULT_OK, null);
+    }
+}
diff --git a/tests/SystemMemoryTest/host/Android.mk b/tests/SystemMemoryTest/host/Android.mk
new file mode 100644
index 0000000..a516e38
--- /dev/null
+++ b/tests/SystemMemoryTest/host/Android.mk
@@ -0,0 +1,23 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_MODULE := system-memory-test
+LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := tradefed
+LOCAL_COMPATIBILITY_SUITE := general-tests
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tests/SystemMemoryTest/host/AndroidTest.xml b/tests/SystemMemoryTest/host/AndroidTest.xml
new file mode 100644
index 0000000..6d2c95f
--- /dev/null
+++ b/tests/SystemMemoryTest/host/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs the system memory tests">
+    <option name="test-suite-tag" value="system-memory-test" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="SystemMemoryTestDevice.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.HostTest" >
+        <option name="class" value="com.android.tests.sysmem.host.MemoryTest" />
+    </test>
+</configuration>
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
new file mode 100644
index 0000000..579d972
--- /dev/null
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.tests.sysmem.host;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+
+/**
+ * Critical user journeys with which to exercise the system, driven from the
+ * host.
+ */
+public class Cujs {
+    private ITestDevice device;
+
+    public Cujs(ITestDevice device) {
+        this.device = device;
+    }
+
+    /**
+     * Runs the critical user journeys.
+     */
+    public void run() throws DeviceNotAvailableException {
+        // Invoke the Device Cujs instrumentation to run the cujs.
+        // TODO: Consider exercising the system in other interesting ways as
+        // well.
+        String command = "am instrument -w com.android.tests.sysmem.device/.Cujs";
+        device.executeShellCommand(command);
+    }
+}
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java
new file mode 100644
index 0000000..bbec065
--- /dev/null
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.tests.sysmem.host;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestMetrics;
+import com.android.tradefed.testtype.IDeviceTest;
+import java.io.IOException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class MemoryTest implements IDeviceTest {
+
+    @Rule public TestMetrics testMetrics = new TestMetrics();
+    @Rule public TestLogData testLogs = new TestLogData();
+
+    private ITestDevice testDevice;
+    private int iterations = 0;     // Number of times cujs have been run.
+    private Metrics metrics;
+    private Cujs cujs;
+
+    @Override
+    public void setDevice(ITestDevice device) {
+        testDevice = device;
+        metrics = new Metrics(device, testMetrics, testLogs);
+        cujs = new Cujs(device);
+    }
+
+    @Override
+    public ITestDevice getDevice() {
+        return testDevice;
+    }
+
+    // Invoke a single iteration of running the cujs.
+    private void runCujs() throws DeviceNotAvailableException {
+        cujs.run();
+        iterations++;
+    }
+
+    // Sample desired memory.
+    private void sample()
+            throws DeviceNotAvailableException, IOException, Metrics.MetricsException {
+        metrics.sample(String.format("%03d", iterations));
+    }
+
+    @Test
+    public void run() throws Exception {
+        sample();   // Sample before running cujs
+        runCujs();
+        sample();   // Sample after first iteration of cujs
+
+        // Run cujs in a loop to highlight memory leaks.
+        for (int i = 0; i < 5; ++i) {
+            for (int j = 0; j < 5; j++) {
+                runCujs();
+            }
+            sample();
+        }
+    }
+}
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
new file mode 100644
index 0000000..7de092a
--- /dev/null
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.tests.sysmem.host;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.FileInputStreamSource;
+import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestMetrics;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.InputMismatchException;
+import java.util.Scanner;
+
+/**
+ * Utilities for sampling and reporting memory metrics.
+ */
+class Metrics {
+
+    private ITestDevice device;
+    private TestMetrics metrics;
+    private TestLogData logs;
+
+    /**
+     * Exception thrown in case of error sampling metrics.
+     */
+    public static class MetricsException extends Exception {
+        public MetricsException(String msg) {
+            super(msg);
+        }
+
+        MetricsException(String msg, Exception cause) {
+            super(msg, cause);
+        }
+    }
+
+    /**
+     * Constructs a metrics instance that will output high level metrics and
+     * more detailed breakdowns using the given <code>metrics</code> and
+     * <code>logs</code> objects.
+     *
+     * @param device the device to sample metrics from
+     * @param metrics where to log the high level metrics when taking a sample
+     * @param logs where to log detailed breakdowns when taking a sample
+     */
+    public Metrics(ITestDevice device, TestMetrics metrics, TestLogData logs) {
+        this.device = device;
+        this.metrics = metrics;
+        this.logs = logs;
+    }
+
+    /**
+     * Returns the pid for the process with the given name.
+     */
+    private int getPidForProcess(String name)
+            throws DeviceNotAvailableException, IOException, MetricsException {
+        String psout = device.executeShellCommand("ps -A -o PID,CMD");
+        Scanner sc = new Scanner(psout);
+        try {
+            // ps output is of the form:
+            //  PID CMD            
+            //    1 init
+            //    2 kthreadd
+            //    ...
+            // 9693 ps
+            sc.nextLine();
+            while (sc.hasNextLine()) {
+                int pid = sc.nextInt();
+                String cmd = sc.next();
+
+                if (name.equals(cmd)) {
+                    return pid;
+                }
+            }
+        } catch (InputMismatchException e) {
+            throw new MetricsException("unexpected ps output format: " + psout, e);
+        }
+
+        throw new MetricsException("failed to get pid for process " + name);
+    }
+
+    /**
+     * Samples the current memory use on the system. Outputs high level test
+     * metrics and detailed breakdowns to the TestMetrics and TestLogData
+     * objects provided when constructing this Metrics instance. The metrics
+     * and log names are prefixed with the given label.
+     *
+     * @param label prefix to use for metrics and logs output for this sample.
+     */
+    void sample(String label) throws DeviceNotAvailableException, IOException, MetricsException {
+        // adb root access is required to get showmap
+        device.enableAdbRoot();
+
+        int pid = getPidForProcess("system_server");
+
+        // Read showmap for system server and add it as a test log
+        String showmap = device.executeShellCommand("showmap " + pid);
+        String showmapLabel = label + ".system_server.showmap";
+        File file = File.createTempFile(showmapLabel, "txt");
+        PrintStream ps = new PrintStream(file);
+        ps.print(showmap);
+        try (FileInputStreamSource dataStream = new FileInputStreamSource(file)) {
+            logs.addTestLog(showmapLabel, LogDataType.TEXT, dataStream);
+        }
+
+        // Extract VSS, PSS and RSS from the showmap and output them as metrics.
+        // The last lines of the showmap output looks something like:
+        // virtual                     shared   shared  private  private
+        //    size      RSS      PSS    clean    dirty    clean    dirty     swap  swapPSS   # object
+        //-------- -------- -------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
+        //  928480   113016    24860    87348     7916     3632    14120     1968     1968 1900 TOTAL
+        try {
+            int pos = showmap.lastIndexOf("----");
+            Scanner sc = new Scanner(showmap.substring(pos));
+            sc.next();
+            long vss = sc.nextLong();
+            long rss = sc.nextLong();
+            long pss = sc.nextLong();
+
+            metrics.addTestMetric(String.format("%s.system_server.vss", label), Long.toString(vss));
+            metrics.addTestMetric(String.format("%s.system_server.rss", label), Long.toString(rss));
+            metrics.addTestMetric(String.format("%s.system_server.pss", label), Long.toString(pss));
+        } catch (InputMismatchException e) {
+            throw new MetricsException("unexpected showmap format", e);
+        }
+
+        // TODO: Experiment with other additional metrics.
+
+        // TODO: Consider launching an instrumentation to collect metrics from
+        // within the device itself.
+    }
+}
diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
index b763c78..b4b5ca7 100644
--- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
+++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
@@ -30,6 +30,7 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.os.Trace;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -42,6 +43,7 @@
 
     public TouchLatencyView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        Trace.beginSection("TouchLatencyView constructor");
         setOnTouchListener(this);
         setWillNotDraw(false);
         mBluePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -63,48 +65,56 @@
         mBallY = 100.0f;
         mVelocityX = 7.0f;
         mVelocityY = 7.0f;
+        Trace.endSection();
     }
 
     @Override
     public boolean onTouch(View view, MotionEvent event) {
+        Trace.beginSection("TouchLatencyView onTouch");
         int action = event.getActionMasked();
         if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) {
             mTouching = true;
             invalidate();
+
+            mTouchX = event.getX();
+            mTouchY = event.getY();
         } else if (action == MotionEvent.ACTION_UP) {
             mTouching = false;
             invalidate();
-            return true;
-        } else {
-            return true;
         }
-        mTouchX = event.getX();
-        mTouchY = event.getY();
+        Trace.endSection();
         return true;
     }
 
     private void drawTouch(Canvas canvas) {
-        if (!mTouching) {
-            Log.d(LOG_TAG, "Filling background");
+        Trace.beginSection("TouchLatencyView drawTouch");
+
+        try {
+            if (!mTouching) {
+                Log.d(LOG_TAG, "Filling background");
+                canvas.drawColor(BACKGROUND_COLOR);
+                return;
+            }
+
+            float deltaX = (mTouchX - mLastDrawnX);
+            float deltaY = (mTouchY - mLastDrawnY);
+            float scaleFactor = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY) * 1.5f;
+
+            mLastDrawnX = mTouchX;
+            mLastDrawnY = mTouchY;
+
             canvas.drawColor(BACKGROUND_COLOR);
-            return;
+            canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS + 3 * scaleFactor, mRedPaint);
+            canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS + 2 * scaleFactor, mYellowPaint);
+            canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS + scaleFactor, mGreenPaint);
+            canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS, mBluePaint);
+        } finally {
+            Trace.endSection();
         }
-
-        float deltaX = (mTouchX - mLastDrawnX);
-        float deltaY = (mTouchY - mLastDrawnY);
-        float scaleFactor = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY) * 1.5f;
-
-        mLastDrawnX = mTouchX;
-        mLastDrawnY = mTouchY;
-
-        canvas.drawColor(BACKGROUND_COLOR);
-        canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS + 3 * scaleFactor, mRedPaint);
-        canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS + 2 * scaleFactor, mYellowPaint);
-        canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS + scaleFactor, mGreenPaint);
-        canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS, mBluePaint);
     }
 
     private void drawBall(Canvas canvas) {
+        Trace.beginSection("TouchLatencyView drawBall");
         int width = canvas.getWidth();
         int height = canvas.getHeight();
 
@@ -141,25 +151,29 @@
         canvas.drawColor(BACKGROUND_COLOR);
         canvas.drawOval(left, top, right, bottom, mYellowPaint);
         invalidate();
+        Trace.endSection();
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
-
+        Trace.beginSection("TouchLatencyView onDraw");
         if (mMode == 0) {
             drawTouch(canvas);
         } else {
             drawBall(canvas);
         }
+        Trace.endSection();
     }
 
     public void changeMode(MenuItem item) {
+        Trace.beginSection("TouchLatencyView changeMode");
         final int NUM_MODES = 2;
         final String modes[] = {"Touch", "Ball"};
         mMode = (mMode + 1) % NUM_MODES;
         invalidate();
         item.setTitle(modes[mMode]);
+        Trace.endSection();
     }
 
     private Paint mBluePaint, mGreenPaint, mYellowPaint, mRedPaint;
@@ -178,21 +192,26 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        Trace.beginSection("TouchLatencyActivity onCreate");
         setContentView(R.layout.activity_touch_latency);
 
         mTouchView = findViewById(R.id.canvasView);
+        Trace.endSection();
     }
 
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
+        Trace.beginSection("TouchLatencyActivity onCreateOptionsMenu");
         // Inflate the menu; this adds items to the action bar if it is present.
         getMenuInflater().inflate(R.menu.menu_touch_latency, menu);
+        Trace.endSection();
         return true;
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
+        Trace.beginSection("TouchLatencyActivity onOptionsItemSelected");
         // Handle action bar item clicks here. The action bar will
         // automatically handle clicks on the Home/Up button, so long
         // as you specify a parent activity in AndroidManifest.xml.
@@ -203,6 +222,7 @@
             mTouchView.changeMode(item);
         }
 
+        Trace.endSection();
         return super.onOptionsItemSelected(item);
     }
 
diff --git a/tests/UsageStatsPerfTests/Android.mk b/tests/UsageStatsPerfTests/Android.mk
new file mode 100644
index 0000000..cd29b51
--- /dev/null
+++ b/tests/UsageStatsPerfTests/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    apct-perftests-utils \
+    services.usage
+
+LOCAL_PACKAGE_NAME := UsageStatsPerfTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+# For android.permission.FORCE_STOP_PACKAGES permission
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsPerfTests/AndroidManifest.xml b/tests/UsageStatsPerfTests/AndroidManifest.xml
new file mode 100644
index 0000000..596a79c
--- /dev/null
+++ b/tests/UsageStatsPerfTests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.perftests.usage">
+    <uses-sdk
+            android:minSdkVersion="21" />
+    <uses-permission android:name="android.permission.DUMP" />
+    <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.frameworks.perftests.usage"/>
+</manifest>
diff --git a/tests/UsageStatsPerfTests/AndroidTest.xml b/tests/UsageStatsPerfTests/AndroidTest.xml
new file mode 100644
index 0000000..c9b51dc
--- /dev/null
+++ b/tests/UsageStatsPerfTests/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs UsageStats Performance Tests">
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="UsageStatsPerfTests.apk"/>
+        <option name="cleanup-apks" value="true"/>
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct"/>
+    <option name="test-tag" value="UsageStatsPerfTests"/>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.frameworks.perftests.usage"/>
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
new file mode 100644
index 0000000..8467bee
--- /dev/null
+++ b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.frameworks.perftests.usage.tests;
+
+import static junit.framework.Assert.assertEquals;
+
+import com.android.server.usage.UsageStatsDatabase;
+import com.android.server.usage.UsageStatsDatabase.StatCombiner;
+import com.android.server.usage.IntervalStats;
+
+import android.app.usage.EventList;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.os.SystemClock;
+import android.perftests.utils.ManualBenchmarkState;
+import android.perftests.utils.PerfManualStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class UsageStatsDatabasePerfTest {
+    protected static Context sContext;
+    private static UsageStatsDatabase sUsageStatsDatabase;
+    private static File mTestDir;
+
+    // Represents how many apps might have used in a day by a user with a few apps
+    final static int FEW_PKGS = 10;
+    // Represent how many apps might have used in a day by a user with many apps
+    final static int MANY_PKGS = 50;
+    // Represents how many usage events per app a device might have with light usage
+    final static int LIGHT_USE = 10;
+    // Represents how many usage events per app a device might have with heavy usage
+    final static int HEAVY_USE = 50;
+
+    private static final StatCombiner<UsageEvents.Event> sUsageStatsCombiner =
+            new StatCombiner<UsageEvents.Event>() {
+                @Override
+                public void combine(IntervalStats stats, boolean mutable,
+                        List<UsageEvents.Event> accResult) {
+                    final int size = stats.events.size();
+                    for (int i = 0; i < size; i++) {
+                        accResult.add(stats.events.get(i));
+                    }
+                }
+            };
+
+
+    @Rule
+    public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
+
+    @BeforeClass
+    public static void setUpOnce() {
+        sContext = InstrumentationRegistry.getTargetContext();
+        mTestDir = new File(sContext.getFilesDir(), "UsageStatsDatabasePerfTest");
+        sUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
+        sUsageStatsDatabase.init(1);
+    }
+
+    private static void populateIntervalStats(IntervalStats intervalStats, int packageCount,
+            int eventsPerPackage) {
+        if (intervalStats.events == null) {
+            intervalStats.events = new EventList();
+        }
+        for (int pkg = 0; pkg < packageCount; pkg++) {
+            UsageEvents.Event event = new UsageEvents.Event();
+            event.mPackage = "fake.package.name" + pkg;
+            event.mTimeStamp = 1;
+            event.mEventType = UsageEvents.Event.MOVE_TO_FOREGROUND;
+            for (int evt = 0; evt < eventsPerPackage; evt++) {
+                intervalStats.events.insert(event);
+                intervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+            }
+        }
+    }
+
+    private static void clearUsageStatsFiles() {
+        File[] intervalDirs = mTestDir.listFiles();
+        for (File intervalDir : intervalDirs) {
+            if (intervalDir.isDirectory()) {
+                File[] usageFiles = intervalDir.listFiles();
+                for (File f : usageFiles) {
+                    f.delete();
+                }
+            }
+        }
+    }
+
+    private void runQueryUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
+        final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
+        IntervalStats intervalStats = new IntervalStats();
+        populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
+        sUsageStatsDatabase.putUsageStats(0, intervalStats);
+        long elapsedTimeNs = 0;
+        while (benchmarkState.keepRunning(elapsedTimeNs)) {
+            final long startTime = SystemClock.elapsedRealtimeNanos();
+            List<UsageEvents.Event> temp = sUsageStatsDatabase.queryUsageStats(
+                    UsageStatsManager.INTERVAL_DAILY, 0, 2, sUsageStatsCombiner);
+            final long endTime = SystemClock.elapsedRealtimeNanos();
+            elapsedTimeNs = endTime - startTime;
+            assertEquals(packageCount * eventsPerPackage, temp.size());
+        }
+    }
+
+    private void runPutUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
+        final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
+        IntervalStats intervalStats = new IntervalStats();
+        populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
+        long elapsedTimeNs = 0;
+        while (benchmarkState.keepRunning(elapsedTimeNs)) {
+            final long startTime = SystemClock.elapsedRealtimeNanos();
+            sUsageStatsDatabase.putUsageStats(0, intervalStats);
+            final long endTime = SystemClock.elapsedRealtimeNanos();
+            elapsedTimeNs = endTime - startTime;
+            clearUsageStatsFiles();
+        }
+    }
+
+    @Test
+    public void testQueryUsageStats_FewPkgsLightUse() throws IOException {
+        runQueryUsageStatsTest(FEW_PKGS, LIGHT_USE);
+    }
+
+    @Test
+    public void testPutUsageStats_FewPkgsLightUse() throws IOException {
+        runPutUsageStatsTest(FEW_PKGS, LIGHT_USE);
+    }
+
+    @Test
+    public void testQueryUsageStats_FewPkgsHeavyUse() throws IOException {
+        runQueryUsageStatsTest(FEW_PKGS, HEAVY_USE);
+    }
+
+    @Test
+    public void testPutUsageStats_FewPkgsHeavyUse() throws IOException {
+        runPutUsageStatsTest(FEW_PKGS, HEAVY_USE);
+    }
+
+    @Test
+    public void testQueryUsageStats_ManyPkgsLightUse() throws IOException {
+        runQueryUsageStatsTest(MANY_PKGS, LIGHT_USE);
+    }
+
+    @Test
+    public void testPutUsageStats_ManyPkgsLightUse() throws IOException {
+        runPutUsageStatsTest(MANY_PKGS, LIGHT_USE);
+    }
+
+    @Test
+    public void testQueryUsageStats_ManyPkgsHeavyUse() throws IOException {
+        runQueryUsageStatsTest(MANY_PKGS, HEAVY_USE);
+    }
+
+    @Test
+    public void testPutUsageStats_ManyPkgsHeavyUse() throws IOException {
+        runPutUsageStatsTest(MANY_PKGS, HEAVY_USE);
+    }
+}
diff --git a/tests/libs-permissions/Android.mk b/tests/libs-permissions/Android.mk
index eb38623..f4250c8 100644
--- a/tests/libs-permissions/Android.mk
+++ b/tests/libs-permissions/Android.mk
@@ -13,3 +13,17 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
 LOCAL_SRC_FILES:= product/com.android.test.libs.product.xml
 include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product_services
+LOCAL_PRODUCT_SERVICES_MODULE := true
+LOCAL_SRC_FILES := $(call all-java-files-under, product_services/java)
+LOCAL_REQUIRED_MODULES := com.android.test.libs.product_services.xml
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product_services.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions
+LOCAL_SRC_FILES:= product_services/com.android.test.libs.product_services.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml b/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml
new file mode 100644
index 0000000..082a9be
--- /dev/null
+++ b/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<permissions>
+    <library name="com.android.test.libs.product_services"
+            file="/product_services/framework/com.android.test.libs.product_services.jar" />
+</permissions>
diff --git a/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java b/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java
new file mode 100644
index 0000000..dcbdae8
--- /dev/null
+++ b/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.libs.product_services;
+
+/**
+ * Test class for product_services libs.
+ */
+public class LibsProductServicesTest {
+
+    /**
+     * Dummy method for testing.
+     */
+    public static void test() {
+    }
+}
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 6cc3dd3..e529b93 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -34,7 +34,6 @@
 # These are not normally accessible from apps so they must be explicitly included.
 LOCAL_JNI_SHARED_LIBRARIES := \
     android.hidl.token@1.0 \
-    $(UBSAN_RUNTIME_LIBRARY) \
     libartbase \
     libbacktrace \
     libbase \
diff --git a/tests/net/OWNERS b/tests/net/OWNERS
index ce50558..7311eee 100644
--- a/tests/net/OWNERS
+++ b/tests/net/OWNERS
@@ -1,6 +1,8 @@
 set noparent
 
+codewiz@google.com
 ek@google.com
 jchalard@google.com
 lorenzo@google.com
+reminv@google.com
 satk@google.com
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index a5ee8e3..3452819 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -16,17 +16,34 @@
 
 package android.net;
 
-import android.net.NetworkUtils;
-import android.test.suitebuilder.annotation.SmallTest;
+import static android.net.NetworkUtils.getImplicitNetmask;
+import static android.net.NetworkUtils.inet4AddressToIntHTH;
+import static android.net.NetworkUtils.inet4AddressToIntHTL;
+import static android.net.NetworkUtils.intToInet4AddressHTH;
+import static android.net.NetworkUtils.intToInet4AddressHTL;
+import static android.net.NetworkUtils.netmaskToPrefixLength;
+import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTH;
+import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTL;
+import static android.net.NetworkUtils.getBroadcastAddress;
+import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.fail;
+
+import android.support.test.runner.AndroidJUnit4;
 
 import java.math.BigInteger;
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.util.TreeSet;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class NetworkUtilsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@android.support.test.filters.SmallTest
+public class NetworkUtilsTest {
 
     private InetAddress Address(String addr) {
         return InetAddress.parseNumericAddress(addr);
@@ -36,41 +53,125 @@
         return (Inet4Address) Address(addr);
     }
 
-    @SmallTest
+    @Test
     public void testGetImplicitNetmask() {
-        assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("4.2.2.2")));
-        assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("10.5.6.7")));
-        assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("173.194.72.105")));
-        assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("172.23.68.145")));
-        assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.0.2.1")));
-        assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.168.5.1")));
-        assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("224.0.0.1")));
-        assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("255.6.7.8")));
+        assertEquals(8, getImplicitNetmask(IPv4Address("4.2.2.2")));
+        assertEquals(8, getImplicitNetmask(IPv4Address("10.5.6.7")));
+        assertEquals(16, getImplicitNetmask(IPv4Address("173.194.72.105")));
+        assertEquals(16, getImplicitNetmask(IPv4Address("172.23.68.145")));
+        assertEquals(24, getImplicitNetmask(IPv4Address("192.0.2.1")));
+        assertEquals(24, getImplicitNetmask(IPv4Address("192.168.5.1")));
+        assertEquals(32, getImplicitNetmask(IPv4Address("224.0.0.1")));
+        assertEquals(32, getImplicitNetmask(IPv4Address("255.6.7.8")));
     }
 
     private void assertInvalidNetworkMask(Inet4Address addr) {
         try {
-            NetworkUtils.netmaskToPrefixLength(addr);
+            netmaskToPrefixLength(addr);
             fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception");
         } catch (IllegalArgumentException expected) {
         }
     }
 
-    @SmallTest
+    @Test
+    public void testInet4AddressToIntHTL() {
+        assertEquals(0, inet4AddressToIntHTL(IPv4Address("0.0.0.0")));
+        assertEquals(0x000080ff, inet4AddressToIntHTL(IPv4Address("255.128.0.0")));
+        assertEquals(0x0080ff0a, inet4AddressToIntHTL(IPv4Address("10.255.128.0")));
+        assertEquals(0x00feff0a, inet4AddressToIntHTL(IPv4Address("10.255.254.0")));
+        assertEquals(0xfeffa8c0, inet4AddressToIntHTL(IPv4Address("192.168.255.254")));
+        assertEquals(0xffffa8c0, inet4AddressToIntHTL(IPv4Address("192.168.255.255")));
+    }
+
+    @Test
+    public void testIntToInet4AddressHTL() {
+        assertEquals(IPv4Address("0.0.0.0"), intToInet4AddressHTL(0));
+        assertEquals(IPv4Address("255.128.0.0"), intToInet4AddressHTL(0x000080ff));
+        assertEquals(IPv4Address("10.255.128.0"), intToInet4AddressHTL(0x0080ff0a));
+        assertEquals(IPv4Address("10.255.254.0"), intToInet4AddressHTL(0x00feff0a));
+        assertEquals(IPv4Address("192.168.255.254"), intToInet4AddressHTL(0xfeffa8c0));
+        assertEquals(IPv4Address("192.168.255.255"), intToInet4AddressHTL(0xffffa8c0));
+    }
+
+    @Test
+    public void testInet4AddressToIntHTH() {
+        assertEquals(0, inet4AddressToIntHTH(IPv4Address("0.0.0.0")));
+        assertEquals(0xff800000, inet4AddressToIntHTH(IPv4Address("255.128.0.0")));
+        assertEquals(0x0aff8000, inet4AddressToIntHTH(IPv4Address("10.255.128.0")));
+        assertEquals(0x0afffe00, inet4AddressToIntHTH(IPv4Address("10.255.254.0")));
+        assertEquals(0xc0a8fffe, inet4AddressToIntHTH(IPv4Address("192.168.255.254")));
+        assertEquals(0xc0a8ffff, inet4AddressToIntHTH(IPv4Address("192.168.255.255")));
+    }
+
+    @Test
+    public void testIntToInet4AddressHTH() {
+        assertEquals(IPv4Address("0.0.0.0"), intToInet4AddressHTH(0));
+        assertEquals(IPv4Address("255.128.0.0"), intToInet4AddressHTH(0xff800000));
+        assertEquals(IPv4Address("10.255.128.0"), intToInet4AddressHTH(0x0aff8000));
+        assertEquals(IPv4Address("10.255.254.0"), intToInet4AddressHTH(0x0afffe00));
+        assertEquals(IPv4Address("192.168.255.254"), intToInet4AddressHTH(0xc0a8fffe));
+        assertEquals(IPv4Address("192.168.255.255"), intToInet4AddressHTH(0xc0a8ffff));
+    }
+
+    @Test
     public void testNetmaskToPrefixLength() {
-        assertEquals(0, NetworkUtils.netmaskToPrefixLength(IPv4Address("0.0.0.0")));
-        assertEquals(9, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.128.0.0")));
-        assertEquals(17, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.128.0")));
-        assertEquals(23, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.254.0")));
-        assertEquals(31, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.254")));
-        assertEquals(32, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.255")));
+        assertEquals(0, netmaskToPrefixLength(IPv4Address("0.0.0.0")));
+        assertEquals(9, netmaskToPrefixLength(IPv4Address("255.128.0.0")));
+        assertEquals(17, netmaskToPrefixLength(IPv4Address("255.255.128.0")));
+        assertEquals(23, netmaskToPrefixLength(IPv4Address("255.255.254.0")));
+        assertEquals(31, netmaskToPrefixLength(IPv4Address("255.255.255.254")));
+        assertEquals(32, netmaskToPrefixLength(IPv4Address("255.255.255.255")));
 
         assertInvalidNetworkMask(IPv4Address("0.0.0.1"));
         assertInvalidNetworkMask(IPv4Address("255.255.255.253"));
         assertInvalidNetworkMask(IPv4Address("255.255.0.255"));
     }
 
-    @SmallTest
+    @Test
+    public void testPrefixLengthToV4NetmaskIntHTL() {
+        assertEquals(0, prefixLengthToV4NetmaskIntHTL(0));
+        assertEquals(0x000080ff /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTL(9));
+        assertEquals(0x0080ffff /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTL(17));
+        assertEquals(0x00feffff /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTL(23));
+        assertEquals(0xfeffffff /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTL(31));
+        assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTL(32));
+    }
+
+    @Test
+    public void testPrefixLengthToV4NetmaskIntHTH() {
+        assertEquals(0, prefixLengthToV4NetmaskIntHTH(0));
+        assertEquals(0xff800000 /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTH(9));
+        assertEquals(0xffff8000 /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTH(17));
+        assertEquals(0xfffffe00 /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTH(23));
+        assertEquals(0xfffffffe /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTH(31));
+        assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTH(32));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testPrefixLengthToV4NetmaskIntHTH_NegativeLength() {
+        prefixLengthToV4NetmaskIntHTH(-1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testPrefixLengthToV4NetmaskIntHTH_LengthTooLarge() {
+        prefixLengthToV4NetmaskIntHTH(33);
+    }
+
+    private void checkAddressMasking(String expectedAddr, String addr, int prefixLength) {
+        final int prefix = prefixLengthToV4NetmaskIntHTH(prefixLength);
+        final int addrInt = inet4AddressToIntHTH(IPv4Address(addr));
+        assertEquals(IPv4Address(expectedAddr), intToInet4AddressHTH(prefix & addrInt));
+    }
+
+    @Test
+    public void testPrefixLengthToV4NetmaskIntHTH_MaskAddr() {
+        checkAddressMasking("192.168.0.0", "192.168.128.1", 16);
+        checkAddressMasking("255.240.0.0", "255.255.255.255", 12);
+        checkAddressMasking("255.255.255.255", "255.255.255.255", 32);
+        checkAddressMasking("0.0.0.0", "255.255.255.255", 0);
+    }
+
+    @Test
     public void testRoutedIPv4AddressCount() {
         final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
         // No routes routes to no addresses.
@@ -118,7 +219,7 @@
         assertEquals(7l - 4 + 4 + 16 + 65536, NetworkUtils.routedIPv4AddressCount(set));
     }
 
-    @SmallTest
+    @Test
     public void testRoutedIPv6AddressCount() {
         final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
         // No routes routes to no addresses.
@@ -166,4 +267,44 @@
         assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
                 NetworkUtils.routedIPv6AddressCount(set));
     }
+
+    @Test
+    public void testGetPrefixMaskAsAddress() {
+        assertEquals("255.255.240.0", getPrefixMaskAsInet4Address(20).getHostAddress());
+        assertEquals("255.0.0.0", getPrefixMaskAsInet4Address(8).getHostAddress());
+        assertEquals("0.0.0.0", getPrefixMaskAsInet4Address(0).getHostAddress());
+        assertEquals("255.255.255.255", getPrefixMaskAsInet4Address(32).getHostAddress());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetPrefixMaskAsAddress_PrefixTooLarge() {
+        getPrefixMaskAsInet4Address(33);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetPrefixMaskAsAddress_NegativePrefix() {
+        getPrefixMaskAsInet4Address(-1);
+    }
+
+    @Test
+    public void testGetBroadcastAddress() {
+        assertEquals("192.168.15.255",
+                getBroadcastAddress(IPv4Address("192.168.0.123"), 20).getHostAddress());
+        assertEquals("192.255.255.255",
+                getBroadcastAddress(IPv4Address("192.168.0.123"), 8).getHostAddress());
+        assertEquals("192.168.0.123",
+                getBroadcastAddress(IPv4Address("192.168.0.123"), 32).getHostAddress());
+        assertEquals("255.255.255.255",
+                getBroadcastAddress(IPv4Address("192.168.0.123"), 0).getHostAddress());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetBroadcastAddress_PrefixTooLarge() {
+        getBroadcastAddress(IPv4Address("192.168.0.123"), 33);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetBroadcastAddress_NegativePrefix() {
+        getBroadcastAddress(IPv4Address("192.168.0.123"), -1);
+    }
 }
diff --git a/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java b/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
new file mode 100644
index 0000000..edadd6e
--- /dev/null
+++ b/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import static android.net.dhcp.DhcpLease.HOSTNAME_NONE;
+import static android.net.dhcp.DhcpLeaseRepository.CLIENTID_UNSPEC;
+import static android.net.dhcp.DhcpLeaseRepository.INETADDR_UNSPEC;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
+
+import static java.lang.String.format;
+import static java.net.InetAddress.parseNumericAddress;
+
+import android.annotation.NonNull;
+import android.net.IpPrefix;
+import android.net.MacAddress;
+import android.net.dhcp.DhcpLeaseRepository.Clock;
+import android.net.util.SharedLog;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.net.Inet4Address;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DhcpLeaseRepositoryTest {
+    private static final Inet4Address INET4_ANY = (Inet4Address) Inet4Address.ANY;
+    private static final Inet4Address TEST_DEF_ROUTER = parseAddr4("192.168.42.247");
+    private static final Inet4Address TEST_SERVER_ADDR = parseAddr4("192.168.42.241");
+    private static final Inet4Address TEST_RESERVED_ADDR = parseAddr4("192.168.42.243");
+    private static final MacAddress TEST_MAC_1 = MacAddress.fromBytes(
+            new byte[] { 5, 4, 3, 2, 1, 0 });
+    private static final MacAddress TEST_MAC_2 = MacAddress.fromBytes(
+            new byte[] { 0, 1, 2, 3, 4, 5 });
+    private static final MacAddress TEST_MAC_3 = MacAddress.fromBytes(
+            new byte[] { 0, 1, 2, 3, 4, 6 });
+    private static final Inet4Address TEST_INETADDR_1 = parseAddr4("192.168.42.248");
+    private static final Inet4Address TEST_INETADDR_2 = parseAddr4("192.168.42.249");
+    private static final String TEST_HOSTNAME_1 = "hostname1";
+    private static final String TEST_HOSTNAME_2 = "hostname2";
+    private static final IpPrefix TEST_IP_PREFIX = new IpPrefix(TEST_SERVER_ADDR, 22);
+    private static final long TEST_TIME = 100L;
+    private static final int TEST_LEASE_TIME_MS = 3_600_000;
+    private static final Set<Inet4Address> TEST_EXCL_SET =
+            Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+                TEST_SERVER_ADDR, TEST_DEF_ROUTER, TEST_RESERVED_ADDR)));
+
+    @NonNull
+    private SharedLog mLog;
+    @NonNull @Mock
+    private Clock mClock;
+    @NonNull
+    private DhcpLeaseRepository mRepo;
+
+    private static Inet4Address parseAddr4(String inet4Addr) {
+        return (Inet4Address) parseNumericAddress(inet4Addr);
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLog = new SharedLog("DhcpLeaseRepositoryTest");
+        when(mClock.elapsedRealtime()).thenReturn(TEST_TIME);
+        mRepo = new DhcpLeaseRepository(
+                TEST_IP_PREFIX, TEST_EXCL_SET, TEST_LEASE_TIME_MS, mLog, mClock);
+    }
+
+    /**
+     * Request a number of addresses through offer/request. Useful to test address exhaustion.
+     * @param nAddr Number of addresses to request.
+     */
+    private void requestAddresses(byte nAddr) throws Exception {
+        final HashSet<Inet4Address> addrs = new HashSet<>();
+        byte[] hwAddrBytes = new byte[] { 8, 4, 3, 2, 1, 0 };
+        for (byte i = 0; i < nAddr; i++) {
+            hwAddrBytes[5] = i;
+            MacAddress newMac = MacAddress.fromBytes(hwAddrBytes);
+            final String hostname = "host_" + i;
+            final DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, newMac,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, hostname);
+
+            assertNotNull(lease);
+            assertEquals(newMac, lease.getHwAddr());
+            assertEquals(hostname, lease.getHostname());
+            assertTrue(format("Duplicate address allocated: %s in %s", lease.getNetAddr(), addrs),
+                    addrs.add(lease.getNetAddr()));
+
+            mRepo.requestLease(null, newMac, null, lease.getNetAddr(), true, hostname);
+        }
+    }
+
+    @Test
+    public void testAddressExhaustion() throws Exception {
+        // Use a /28 to quickly run out of addresses
+        mRepo.updateParams(new IpPrefix(TEST_SERVER_ADDR, 28), TEST_EXCL_SET, TEST_LEASE_TIME_MS);
+
+        // /28 should have 16 addresses, 14 w/o the first/last, 11 w/o excluded addresses
+        requestAddresses((byte)11);
+
+        try {
+            mRepo.getOffer(null, TEST_MAC_2,
+                    null /* relayAddr */, null /* reqAddr */, HOSTNAME_NONE);
+            fail("Should be out of addresses");
+        } catch (DhcpLeaseRepository.OutOfAddressesException e) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void testUpdateParams_LeaseCleanup() throws Exception {
+        // Inside /28:
+        final Inet4Address reqAddrIn28 = parseAddr4("192.168.42.242");
+        final Inet4Address declinedAddrIn28 = parseAddr4("192.168.42.245");
+
+        // Inside /28, but not available there (first address of the range)
+        final Inet4Address declinedFirstAddrIn28 = parseAddr4("192.168.42.240");
+
+        final DhcpLease reqAddrIn28Lease = mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, reqAddrIn28, false, HOSTNAME_NONE);
+        mRepo.markLeaseDeclined(declinedAddrIn28);
+        mRepo.markLeaseDeclined(declinedFirstAddrIn28);
+
+        // Inside /22, but outside /28:
+        final Inet4Address reqAddrIn22 = parseAddr4("192.168.42.3");
+        final Inet4Address declinedAddrIn22 = parseAddr4("192.168.42.4");
+
+        final DhcpLease reqAddrIn22Lease = mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_3, INET4_ANY, reqAddrIn22, false, HOSTNAME_NONE);
+        mRepo.markLeaseDeclined(declinedAddrIn22);
+
+        // Address that will be reserved in the updateParams call below
+        final Inet4Address reservedAddr = parseAddr4("192.168.42.244");
+        final DhcpLease reservedAddrLease = mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY, reservedAddr, false, HOSTNAME_NONE);
+
+        // Update from /22 to /28 and add another reserved address
+        Set<Inet4Address> newReserved = new HashSet<>(TEST_EXCL_SET);
+        newReserved.add(reservedAddr);
+        mRepo.updateParams(new IpPrefix(TEST_SERVER_ADDR, 28), newReserved, TEST_LEASE_TIME_MS);
+
+        assertHasLease(reqAddrIn28Lease);
+        assertDeclined(declinedAddrIn28);
+
+        assertNotDeclined(declinedFirstAddrIn28);
+
+        assertNoLease(reqAddrIn22Lease);
+        assertNotDeclined(declinedAddrIn22);
+
+        assertNoLease(reservedAddrLease);
+    }
+
+    @Test
+    public void testGetOffer_StableAddress() throws Exception {
+        for (final MacAddress macAddr : new MacAddress[] { TEST_MAC_1, TEST_MAC_2, TEST_MAC_3 }) {
+            final DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, macAddr,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+
+            // Same lease is offered twice
+            final DhcpLease newLease = mRepo.getOffer(CLIENTID_UNSPEC, macAddr,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+            assertEquals(lease, newLease);
+        }
+    }
+
+    @Test
+    public void testUpdateParams_UsesNewPrefix() throws Exception {
+        final IpPrefix newPrefix = new IpPrefix(parseAddr4("192.168.123.0"), 24);
+        mRepo.updateParams(newPrefix, TEST_EXCL_SET, TEST_LEASE_TIME_MS);
+
+        DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+        assertTrue(newPrefix.contains(lease.getNetAddr()));
+    }
+
+    @Test
+    public void testGetOffer_ExistingLease() throws Exception {
+        mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, TEST_INETADDR_1, false, TEST_HOSTNAME_1);
+
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+        assertEquals(TEST_INETADDR_1, offer.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, offer.getHostname());
+    }
+
+    @Test
+    public void testGetOffer_ClientIdHasExistingLease() throws Exception {
+        final byte[] clientId = new byte[] { 1, 2 };
+        mRepo.requestLease(clientId, TEST_MAC_1, INET4_ANY, TEST_INETADDR_1, false,
+                TEST_HOSTNAME_1);
+
+        // Different MAC, but same clientId
+        DhcpLease offer = mRepo.getOffer(clientId, TEST_MAC_2,
+                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+        assertEquals(TEST_INETADDR_1, offer.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, offer.getHostname());
+    }
+
+    @Test
+    public void testGetOffer_DifferentClientId() throws Exception {
+        final byte[] clientId1 = new byte[] { 1, 2 };
+        final byte[] clientId2 = new byte[] { 3, 4 };
+        mRepo.requestLease(clientId1, TEST_MAC_1, INET4_ANY, TEST_INETADDR_1, false,
+                TEST_HOSTNAME_1);
+
+        // Same MAC, different client ID
+        DhcpLease offer = mRepo.getOffer(clientId2, TEST_MAC_1,
+                INETADDR_UNSPEC, INETADDR_UNSPEC, HOSTNAME_NONE);
+        // Obtains a different address
+        assertNotEquals(TEST_INETADDR_1, offer.getNetAddr());
+        assertEquals(HOSTNAME_NONE, offer.getHostname());
+        assertEquals(TEST_MAC_1, offer.getHwAddr());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddress() throws Exception {
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, TEST_HOSTNAME_1);
+        assertEquals(TEST_INETADDR_1, offer.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, offer.getHostname());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddressInUse() throws Exception {
+        mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, TEST_INETADDR_1, false, HOSTNAME_NONE);
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY,
+                TEST_INETADDR_1, HOSTNAME_NONE);
+        assertNotEquals(TEST_INETADDR_1, offer.getNetAddr());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddressReserved() throws Exception {
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_RESERVED_ADDR, HOSTNAME_NONE);
+        assertNotEquals(TEST_RESERVED_ADDR, offer.getNetAddr());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddressInvalid() throws Exception {
+        final Inet4Address invalidAddr = parseAddr4("192.168.42.0");
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                invalidAddr, HOSTNAME_NONE);
+        assertNotEquals(invalidAddr, offer.getNetAddr());
+    }
+
+    @Test
+    public void testGetOffer_RequestedAddressOutsideSubnet() throws Exception {
+        final Inet4Address invalidAddr = parseAddr4("192.168.254.2");
+        DhcpLease offer = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                invalidAddr, HOSTNAME_NONE);
+        assertNotEquals(invalidAddr, offer.getNetAddr());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testGetOffer_RelayInInvalidSubnet() throws Exception {
+        mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                parseAddr4("192.168.254.2") /* relayAddr */, INETADDR_UNSPEC, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testRequestLease_SelectingTwice() throws Exception {
+        DhcpLease lease1 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, TEST_HOSTNAME_1);
+
+        // Second request from same client for a different address
+        DhcpLease lease2 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_2, true /* sidSet */, TEST_HOSTNAME_2);
+
+        assertEquals(TEST_INETADDR_1, lease1.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, lease1.getHostname());
+
+        assertEquals(TEST_INETADDR_2, lease2.getNetAddr());
+        assertEquals(TEST_HOSTNAME_2, lease2.getHostname());
+
+        // First address freed when client requested a different one: another client can request it
+        DhcpLease lease3 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+        assertEquals(TEST_INETADDR_1, lease3.getNetAddr());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_SelectingInvalid() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                parseAddr4("192.168.254.5"), true /* sidSet */, HOSTNAME_NONE);
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_SelectingInUse() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_SelectingReserved() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_RESERVED_ADDR, true /* sidSet */, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testRequestLease_InitReboot() throws Exception {
+        // Request address once
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+
+        final long newTime = TEST_TIME + 100;
+        when(mClock.elapsedRealtime()).thenReturn(newTime);
+
+        // init-reboot (sidSet == false): verify configuration
+        DhcpLease lease = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, false, HOSTNAME_NONE);
+        assertEquals(TEST_INETADDR_1, lease.getNetAddr());
+        assertEquals(newTime + TEST_LEASE_TIME_MS, lease.getExpTime());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_InitRebootWrongAddr() throws Exception {
+        // Request address once
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+        // init-reboot with different requested address
+        mRepo.requestLease(
+                CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, TEST_INETADDR_2, false, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testRequestLease_InitRebootUnknownAddr() throws Exception {
+        // init-reboot with unknown requested address
+        DhcpLease lease = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_2, false, HOSTNAME_NONE);
+        // RFC2131 says we should not reply to accommodate other servers, but since we are
+        // authoritative we allow creating the lease to avoid issues with lost lease DB (same as
+        // dnsmasq behavior)
+        assertEquals(TEST_INETADDR_2, lease.getNetAddr());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_InitRebootWrongSubnet() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                parseAddr4("192.168.254.2"), false /* sidSet */, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testRequestLease_Renewing() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1,
+                INET4_ANY /* clientAddr */, TEST_INETADDR_1 /* reqAddr */, true, HOSTNAME_NONE);
+
+        final long newTime = TEST_TIME + 100;
+        when(mClock.elapsedRealtime()).thenReturn(newTime);
+
+        // Renewing: clientAddr filled in, no reqAddr
+        DhcpLease lease = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1,
+                TEST_INETADDR_1 /* clientAddr */, INETADDR_UNSPEC /* reqAddr */, false,
+                HOSTNAME_NONE);
+
+        assertEquals(TEST_INETADDR_1, lease.getNetAddr());
+        assertEquals(newTime + TEST_LEASE_TIME_MS, lease.getExpTime());
+    }
+
+    @Test
+    public void testRequestLease_RenewingUnknownAddr() throws Exception {
+        final long newTime = TEST_TIME + 100;
+        when(mClock.elapsedRealtime()).thenReturn(newTime);
+        DhcpLease lease = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1,
+                TEST_INETADDR_1 /* clientAddr */, INETADDR_UNSPEC /* reqAddr */, false,
+                HOSTNAME_NONE);
+        // Allows renewing an unknown address if available
+        assertEquals(TEST_INETADDR_1, lease.getNetAddr());
+        assertEquals(newTime + TEST_LEASE_TIME_MS, lease.getExpTime());
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_RenewingAddrInUse() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2,
+                INET4_ANY /* clientAddr */, TEST_INETADDR_1 /* reqAddr */, true, HOSTNAME_NONE);
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1,
+                TEST_INETADDR_1 /* clientAddr */, INETADDR_UNSPEC /* reqAddr */, false,
+                HOSTNAME_NONE);
+    }
+
+    @Test(expected = DhcpLeaseRepository.InvalidAddressException.class)
+    public void testRequestLease_RenewingInvalidAddr() throws Exception {
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, parseAddr4("192.168.254.2") /* clientAddr */,
+                INETADDR_UNSPEC /* reqAddr */, false, HOSTNAME_NONE);
+    }
+
+    @Test
+    public void testReleaseLease() throws Exception {
+        DhcpLease lease1 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+
+        assertHasLease(lease1);
+        assertTrue(mRepo.releaseLease(CLIENTID_UNSPEC, TEST_MAC_1, TEST_INETADDR_1));
+        assertNoLease(lease1);
+
+        DhcpLease lease2 = mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY,
+                TEST_INETADDR_1, true /* sidSet */, HOSTNAME_NONE);
+
+        assertEquals(TEST_INETADDR_1, lease2.getNetAddr());
+    }
+
+    @Test
+    public void testReleaseLease_UnknownLease() {
+        assertFalse(mRepo.releaseLease(CLIENTID_UNSPEC, TEST_MAC_1, TEST_INETADDR_1));
+    }
+
+    @Test
+    public void testReleaseLease_StableOffer() throws Exception {
+        for (MacAddress mac : new MacAddress[] { TEST_MAC_1, TEST_MAC_2, TEST_MAC_3 }) {
+            final DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, mac,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+            mRepo.requestLease(
+                    CLIENTID_UNSPEC, mac, INET4_ANY, lease.getNetAddr(), true,
+                    HOSTNAME_NONE);
+            mRepo.releaseLease(CLIENTID_UNSPEC, mac, lease.getNetAddr());
+
+            // Same lease is offered after it was released
+            final DhcpLease newLease = mRepo.getOffer(CLIENTID_UNSPEC, mac,
+                    INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+            assertEquals(lease.getNetAddr(), newLease.getNetAddr());
+        }
+    }
+
+    @Test
+    public void testMarkLeaseDeclined() throws Exception {
+        final DhcpLease lease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+
+        mRepo.markLeaseDeclined(lease.getNetAddr());
+
+        // Same lease is not offered again
+        final DhcpLease newLease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+        assertNotEquals(lease.getNetAddr(), newLease.getNetAddr());
+    }
+
+    @Test
+    public void testMarkLeaseDeclined_UsedIfOutOfAddresses() throws Exception {
+        // Use a /28 to quickly run out of addresses
+        mRepo.updateParams(new IpPrefix(TEST_SERVER_ADDR, 28), TEST_EXCL_SET, TEST_LEASE_TIME_MS);
+
+        mRepo.markLeaseDeclined(TEST_INETADDR_1);
+        mRepo.markLeaseDeclined(TEST_INETADDR_2);
+
+        // /28 should have 16 addresses, 14 w/o the first/last, 11 w/o excluded addresses
+        requestAddresses((byte)9);
+
+        // Last 2 addresses: addresses marked declined should be used
+        final DhcpLease firstLease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_1,
+                INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, TEST_HOSTNAME_1);
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_1, INET4_ANY, firstLease.getNetAddr(), true,
+                HOSTNAME_NONE);
+
+        final DhcpLease secondLease = mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_2,
+                INETADDR_UNSPEC /* relayAddr */, INETADDR_UNSPEC /* reqAddr */, TEST_HOSTNAME_2);
+        mRepo.requestLease(CLIENTID_UNSPEC, TEST_MAC_2, INET4_ANY, secondLease.getNetAddr(), true,
+                HOSTNAME_NONE);
+
+        // Now out of addresses
+        try {
+            mRepo.getOffer(CLIENTID_UNSPEC, TEST_MAC_3, INETADDR_UNSPEC /* relayAddr */,
+                    INETADDR_UNSPEC /* reqAddr */, HOSTNAME_NONE);
+            fail("Repository should be out of addresses and throw");
+        } catch (DhcpLeaseRepository.OutOfAddressesException e) { /* expected */ }
+
+        assertEquals(TEST_INETADDR_1, firstLease.getNetAddr());
+        assertEquals(TEST_HOSTNAME_1, firstLease.getHostname());
+        assertEquals(TEST_INETADDR_2, secondLease.getNetAddr());
+        assertEquals(TEST_HOSTNAME_2, secondLease.getHostname());
+    }
+
+    private void assertNoLease(DhcpLease lease) {
+        assertFalse("Leases contain " + lease, mRepo.getCommittedLeases().contains(lease));
+    }
+
+    private void assertHasLease(DhcpLease lease) {
+        assertTrue("Leases do not contain " + lease, mRepo.getCommittedLeases().contains(lease));
+    }
+
+    private void assertNotDeclined(Inet4Address addr) {
+        assertFalse("Address is declined: " + addr, mRepo.getDeclinedAddresses().contains(addr));
+    }
+
+    private void assertDeclined(Inet4Address addr) {
+        assertTrue("Address is not declined: " + addr, mRepo.getDeclinedAddresses().contains(addr));
+    }
+}
diff --git a/tests/net/java/android/net/dhcp/DhcpServingParamsTest.java b/tests/net/java/android/net/dhcp/DhcpServingParamsTest.java
new file mode 100644
index 0000000..dfa09a9
--- /dev/null
+++ b/tests/net/java/android/net/dhcp/DhcpServingParamsTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import static android.net.dhcp.DhcpServingParams.MTU_UNSET;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static java.net.InetAddress.parseNumericAddress;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LinkAddress;
+import android.net.dhcp.DhcpServingParams.InvalidParameterException;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.Inet4Address;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DhcpServingParamsTest {
+    @NonNull
+    private DhcpServingParams.Builder mBuilder;
+
+    private static final Set<Inet4Address> TEST_DEFAULT_ROUTERS = new HashSet<>(
+            Arrays.asList(parseAddr("192.168.0.123"), parseAddr("192.168.0.124")));
+    private static final long TEST_LEASE_TIME_SECS = 3600L;
+    private static final Set<Inet4Address> TEST_DNS_SERVERS = new HashSet<>(
+            Arrays.asList(parseAddr("192.168.0.126"), parseAddr("192.168.0.127")));
+    private static final Inet4Address TEST_SERVER_ADDR = parseAddr("192.168.0.2");
+    private static final LinkAddress TEST_LINKADDR = new LinkAddress(TEST_SERVER_ADDR, 20);
+    private static final int TEST_MTU = 1500;
+    private static final Set<Inet4Address> TEST_EXCLUDED_ADDRS = new HashSet<>(
+            Arrays.asList(parseAddr("192.168.0.200"), parseAddr("192.168.0.201")));
+
+    @Before
+    public void setUp() {
+        mBuilder = new DhcpServingParams.Builder()
+                .setDefaultRouters(TEST_DEFAULT_ROUTERS)
+                .setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS)
+                .setDnsServers(TEST_DNS_SERVERS)
+                .setServerAddr(TEST_LINKADDR)
+                .setLinkMtu(TEST_MTU)
+                .setExcludedAddrs(TEST_EXCLUDED_ADDRS);
+    }
+
+    @Test
+    public void testBuild_Immutable() throws InvalidParameterException {
+        final Set<Inet4Address> routers = new HashSet<>(TEST_DEFAULT_ROUTERS);
+        final Set<Inet4Address> dnsServers = new HashSet<>(TEST_DNS_SERVERS);
+        final Set<Inet4Address> excludedAddrs = new HashSet<>(TEST_EXCLUDED_ADDRS);
+
+        final DhcpServingParams params = mBuilder
+                .setDefaultRouters(routers)
+                .setDnsServers(dnsServers)
+                .setExcludedAddrs(excludedAddrs)
+                .build();
+
+        // Modifications to source objects should not affect builder or final parameters
+        final Inet4Address addedAddr = parseAddr("192.168.0.223");
+        routers.add(addedAddr);
+        dnsServers.add(addedAddr);
+        excludedAddrs.add(addedAddr);
+
+        assertEquals(TEST_DEFAULT_ROUTERS, params.defaultRouters);
+        assertEquals(TEST_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs);
+        assertEquals(TEST_DNS_SERVERS, params.dnsServers);
+        assertEquals(TEST_LINKADDR, params.serverAddr);
+        assertEquals(TEST_MTU, params.linkMtu);
+
+        assertContains(params.excludedAddrs, TEST_EXCLUDED_ADDRS);
+        assertContains(params.excludedAddrs, TEST_DEFAULT_ROUTERS);
+        assertContains(params.excludedAddrs, TEST_DNS_SERVERS);
+        assertContains(params.excludedAddrs, TEST_SERVER_ADDR);
+
+        assertFalse("excludedAddrs should not contain " + addedAddr,
+                params.excludedAddrs.contains(addedAddr));
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_NegativeLeaseTime() throws InvalidParameterException {
+        mBuilder.setDhcpLeaseTimeSecs(-1).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_LeaseTimeTooLarge() throws InvalidParameterException {
+        // Set lease time larger than max value for uint32
+        mBuilder.setDhcpLeaseTimeSecs(1L << 32).build();
+    }
+
+    @Test
+    public void testBuild_InfiniteLeaseTime() throws InvalidParameterException {
+        final long infiniteLeaseTime = 0xffffffffL;
+        final DhcpServingParams params = mBuilder
+                .setDhcpLeaseTimeSecs(infiniteLeaseTime).build();
+        assertEquals(infiniteLeaseTime, params.dhcpLeaseTimeSecs);
+        assertTrue(params.dhcpLeaseTimeSecs > 0L);
+    }
+
+    @Test
+    public void testBuild_UnsetMtu() throws InvalidParameterException {
+        final DhcpServingParams params = mBuilder.setLinkMtu(MTU_UNSET).build();
+        assertEquals(MTU_UNSET, params.linkMtu);
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_MtuTooSmall() throws InvalidParameterException {
+        mBuilder.setLinkMtu(20).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_MtuTooLarge() throws InvalidParameterException {
+        mBuilder.setLinkMtu(65_536).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_IPv6Addr() throws InvalidParameterException {
+        mBuilder.setServerAddr(new LinkAddress(parseNumericAddress("fe80::1111"), 120)).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_PrefixTooLarge() throws InvalidParameterException {
+        mBuilder.setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 15)).build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_PrefixTooSmall() throws InvalidParameterException {
+        mBuilder.setDefaultRouters(Collections.singleton(parseAddr("192.168.0.254")))
+                .setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 31))
+                .build();
+    }
+
+    @Test(expected = InvalidParameterException.class)
+    public void testBuild_RouterNotInPrefix() throws InvalidParameterException {
+        mBuilder.setDefaultRouters(Collections.singleton(parseAddr("192.168.254.254"))).build();
+    }
+
+    private static <T> void assertContains(@NonNull Set<T> set, @NonNull Set<T> subset) {
+        for (final T elem : subset) {
+            assertContains(set, elem);
+        }
+    }
+
+    private static <T> void assertContains(@NonNull Set<T> set, @Nullable T elem) {
+        assertTrue("Set does not contain " + elem, set.contains(elem));
+    }
+
+    @NonNull
+    private static Inet4Address parseAddr(@NonNull String inet4Addr) {
+        return (Inet4Address) parseNumericAddress(inet4Addr);
+    }
+}
diff --git a/tests/net/java/android/net/ip/IpClientTest.java b/tests/net/java/android/net/ip/IpClientTest.java
index 89453e0..5a8d2cd 100644
--- a/tests/net/java/android/net/ip/IpClientTest.java
+++ b/tests/net/java/android/net/ip/IpClientTest.java
@@ -32,7 +32,6 @@
 import static org.mockito.Mockito.when;
 
 import android.app.AlarmManager;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.INetd;
@@ -62,8 +61,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.net.Inet4Address;
-import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.util.Arrays;
 import java.util.List;
@@ -84,6 +81,7 @@
     private static final int TEST_IFINDEX = 1001;
     // See RFC 7042#section-2.1.2 for EUI-48 documentation values.
     private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01");
+    private static final int TEST_TIMEOUT_MS = 200;
 
     @Mock private Context mContext;
     @Mock private INetworkManagementService mNMService;
@@ -126,8 +124,8 @@
     private IpClient makeIpClient(String ifname) throws Exception {
         setTestInterfaceParams(ifname);
         final IpClient ipc = new IpClient(mContext, ifname, mCb, mDependecies);
-        verify(mNMService, timeout(100).times(1)).disableIpv6(ifname);
-        verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(ifname);
+        verify(mNMService, timeout(TEST_TIMEOUT_MS).times(1)).disableIpv6(ifname);
+        verify(mNMService, timeout(TEST_TIMEOUT_MS).times(1)).clearInterfaceAddresses(ifname);
         ArgumentCaptor<BaseNetworkObserver> arg =
                 ArgumentCaptor.forClass(BaseNetworkObserver.class);
         verify(mNMService, times(1)).registerObserver(arg.capture());
@@ -200,13 +198,13 @@
 
         ipc.startProvisioning(config);
         verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
-        verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
+        verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false);
         verify(mCb, never()).onProvisioningFailure(any());
 
         ipc.shutdown();
-        verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
-        verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
-        verify(mCb, timeout(100).times(1))
+        verify(mNMService, timeout(TEST_TIMEOUT_MS).times(1)).disableIpv6(iface);
+        verify(mNMService, timeout(TEST_TIMEOUT_MS).times(1)).clearInterfaceAddresses(iface);
+        verify(mCb, timeout(TEST_TIMEOUT_MS).times(1))
                 .onLinkPropertiesChange(eq(makeEmptyLinkProperties(iface)));
     }
 
@@ -230,12 +228,12 @@
 
         ipc.startProvisioning(config);
         verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
-        verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
+        verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false);
         verify(mCb, never()).onProvisioningFailure(any());
 
         for (String addr : addresses) {
             String[] parts = addr.split("/");
-            verify(mNetd, timeout(100).times(1))
+            verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1))
                     .interfaceAddAddress(iface, parts[0], Integer.parseInt(parts[1]));
         }
 
@@ -244,7 +242,7 @@
         // Add N - 1 addresses
         for (int i = 0; i < lastAddr; i++) {
             mObserver.addressUpdated(iface, new LinkAddress(addresses[i]));
-            verify(mCb, timeout(100)).onLinkPropertiesChange(any());
+            verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(any());
             reset(mCb);
         }
 
@@ -252,12 +250,12 @@
         mObserver.addressUpdated(iface, new LinkAddress(addresses[lastAddr]));
         LinkProperties want = linkproperties(links(addresses), routes(prefixes));
         want.setInterfaceName(iface);
-        verify(mCb, timeout(100).times(1)).onProvisioningSuccess(eq(want));
+        verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningSuccess(eq(want));
 
         ipc.shutdown();
-        verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
-        verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
-        verify(mCb, timeout(100).times(1))
+        verify(mNMService, timeout(TEST_TIMEOUT_MS).times(1)).disableIpv6(iface);
+        verify(mNMService, timeout(TEST_TIMEOUT_MS).times(1)).clearInterfaceAddresses(iface);
+        verify(mCb, timeout(TEST_TIMEOUT_MS).times(1))
                 .onLinkPropertiesChange(eq(makeEmptyLinkProperties(iface)));
     }
 
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index dbf81d6..e3db7e8 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -62,9 +62,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.eq;
@@ -85,7 +83,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.net.CaptivePortal;
 import android.net.ConnectivityManager;
@@ -114,7 +111,6 @@
 import android.net.RouteInfo;
 import android.net.StringNetworkSpecifier;
 import android.net.UidRange;
-import android.net.VpnService;
 import android.net.captiveportal.CaptivePortalProbeResult;
 import android.net.metrics.IpConnectivityLog;
 import android.net.util.MultinetworkPolicyTracker;
@@ -135,7 +131,6 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
-import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -196,7 +191,16 @@
     private static final String TAG = "ConnectivityServiceTest";
 
     private static final int TIMEOUT_MS = 500;
-    private static final int TEST_LINGER_DELAY_MS = 120;
+    private static final int TEST_LINGER_DELAY_MS = 250;
+    // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
+    // LOST callback that arrives immediately and a LOST callback that arrives after the linger
+    // timeout. For this, our assertions should run fast enough to leave less than
+    // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
+    // supposedly fired, and the time we call expectCallback.
+    private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
+    // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
+    // complete before callbacks are verified.
+    private final static int TEST_REQUEST_TIMEOUT_MS = 150;
 
     private static final String CLAT_PREFIX = "v4-";
     private static final String MOBILE_IFNAME = "test_rmnet_data0";
@@ -876,7 +880,7 @@
                 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
                 IpConnectivityLog log) {
             super(context, handler, networkAgentInfo, defaultRequest, log,
-                    NetworkMonitor.NetworkMonitorSettings.DEFAULT);
+                    NetworkMonitor.Dependencies.DEFAULT);
             connectivityHandler = handler;
         }
 
@@ -1465,11 +1469,6 @@
      * received. assertNoCallback may be called at any time.
      */
     private class TestNetworkCallback extends NetworkCallback {
-        // Chosen to be much less than the linger timeout. This ensures that we can distinguish
-        // between a LOST callback that arrives immediately and a LOST callback that arrives after
-        // the linger timeout.
-        private final static int TIMEOUT_MS = 100;
-
         private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
         private Network mLastAvailableNetwork;
 
@@ -1545,20 +1544,20 @@
             if (state == CallbackState.LOSING) {
                 String msg = String.format(
                         "Invalid linger time value %d, must be between %d and %d",
-                        actual.arg, 0, TEST_LINGER_DELAY_MS);
+                        actual.arg, 0, mService.mLingerDelayMs);
                 int maxMsToLive = (Integer) actual.arg;
-                assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
+                assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
             }
 
             return actual;
         }
 
         CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
-            return expectCallback(state, agent, TIMEOUT_MS);
+            return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
         }
 
         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
-            return expectCallbackLike(fn, TIMEOUT_MS);
+            return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
         }
 
         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
@@ -1601,15 +1600,15 @@
 
         // Expects the available callbacks (validated), plus onSuspended.
         void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
-            expectAvailableCallbacks(agent, true, expectValidated, TIMEOUT_MS);
+            expectAvailableCallbacks(agent, true, expectValidated, TEST_CALLBACK_TIMEOUT_MS);
         }
 
         void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
-            expectAvailableCallbacks(agent, false, true, TIMEOUT_MS);
+            expectAvailableCallbacks(agent, false, true, TEST_CALLBACK_TIMEOUT_MS);
         }
 
         void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
-            expectAvailableCallbacks(agent, false, false, TIMEOUT_MS);
+            expectAvailableCallbacks(agent, false, false, TEST_CALLBACK_TIMEOUT_MS);
         }
 
         // Expects the available callbacks (where the onCapabilitiesChanged must contain the
@@ -1617,9 +1616,9 @@
         // one we just sent.
         // TODO: this is likely a bug. Fix it and remove this method.
         void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
-            expectCallback(CallbackState.AVAILABLE, agent, TIMEOUT_MS);
+            expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
             NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
-            expectCallback(CallbackState.LINK_PROPERTIES, agent, TIMEOUT_MS);
+            expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
             NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
             assertEquals(nc1, nc2);
         }
@@ -1633,7 +1632,7 @@
         }
 
         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
-            return expectCapabilitiesWith(capability, agent, TIMEOUT_MS);
+            return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
         }
 
         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
@@ -1645,7 +1644,7 @@
         }
 
         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
-            return expectCapabilitiesWithout(capability, agent, TIMEOUT_MS);
+            return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
         }
 
         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
@@ -1769,6 +1768,12 @@
 
     @Test
     public void testMultipleLingering() {
+        // This test would be flaky with the default 120ms timer: that is short enough that
+        // lingered networks are torn down before assertions can be run. We don't want to mock the
+        // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
+        // in detecting races.
+        mService.mLingerDelayMs = 300;
+
         NetworkRequest request = new NetworkRequest.Builder()
                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
                 .build();
@@ -1986,7 +1991,7 @@
 
         // Let linger run its course.
         callback.assertNoCallback();
-        final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
+        final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
 
         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
@@ -3210,12 +3215,12 @@
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
-        final int timeoutMs = 150;
-        mCm.requestNetwork(nr, networkCallback, timeoutMs);
+        mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
 
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);
-        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, timeoutMs);
+        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false,
+                TEST_CALLBACK_TIMEOUT_MS);
 
         // pass timeout and validate that UNAVAILABLE is not called
         networkCallback.assertNoCallback();
@@ -3230,13 +3235,12 @@
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
-        final int requestTimeoutMs = 50;
-        mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
+        mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
 
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);
-        final int assertTimeoutMs = 100;
-        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, assertTimeoutMs);
+        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false,
+                TEST_CALLBACK_TIMEOUT_MS);
         mWiFiNetworkAgent.disconnect();
         networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
 
diff --git a/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java
index 27a897d..b017130 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java
@@ -16,22 +16,35 @@
 
 package com.android.server.connectivity;
 
-import static org.junit.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
 import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
 import android.net.NetworkRequest;
+import android.net.captiveportal.CaptivePortalProbeResult;
 import android.net.metrics.IpConnectivityLog;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
+import android.provider.Settings;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -39,38 +52,273 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.URL;
+import java.util.Random;
+
+import javax.net.ssl.SSLHandshakeException;
+
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class NetworkMonitorTest {
+    private static final String LOCATION_HEADER = "location";
 
-    static final int TEST_ID = 60; // should be less than min netid 100
+    private @Mock Context mContext;
+    private @Mock Handler mHandler;
+    private @Mock IpConnectivityLog mLogger;
+    private @Mock NetworkAgentInfo mAgent;
+    private @Mock NetworkInfo mNetworkInfo;
+    private @Mock NetworkRequest mRequest;
+    private @Mock TelephonyManager mTelephony;
+    private @Mock WifiManager mWifi;
+    private @Mock Network mNetwork;
+    private @Mock HttpURLConnection mHttpConnection;
+    private @Mock HttpURLConnection mHttpsConnection;
+    private @Mock HttpURLConnection mFallbackConnection;
+    private @Mock HttpURLConnection mOtherFallbackConnection;
+    private @Mock Random mRandom;
+    private @Mock NetworkMonitor.Dependencies mDependencies;
 
-    @Mock Context mContext;
-    @Mock Handler mHandler;
-    @Mock IpConnectivityLog mLogger;
-    @Mock NetworkAgentInfo mAgent;
-    @Mock NetworkMonitor.NetworkMonitorSettings mSettings;
-    @Mock NetworkRequest mRequest;
-    @Mock TelephonyManager mTelephony;
-    @Mock WifiManager mWifi;
+    private static final String TEST_HTTP_URL = "http://www.google.com/gen_204";
+    private static final String TEST_HTTPS_URL = "https://www.google.com/gen_204";
+    private static final String TEST_FALLBACK_URL = "http://fallback.google.com/gen_204";
+    private static final String TEST_OTHER_FALLBACK_URL = "http://otherfallback.google.com/gen_204";
 
     @Before
-    public void setUp() {
+    public void setUp() throws IOException {
         MockitoAnnotations.initMocks(this);
+        mAgent.linkProperties = new LinkProperties();
+        mAgent.networkCapabilities = new NetworkCapabilities()
+                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+        mAgent.networkInfo = mNetworkInfo;
 
-        when(mAgent.network()).thenReturn(new Network(TEST_ID));
+        when(mAgent.network()).thenReturn(mNetwork);
+        when(mDependencies.getNetwork(any())).thenReturn(mNetwork);
+        when(mDependencies.getRandom()).thenReturn(mRandom);
+        when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_MODE), anyInt()))
+                .thenReturn(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
+        when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_USE_HTTPS),
+                anyInt())).thenReturn(1);
+        when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL),
+                anyString())).thenReturn(TEST_HTTP_URL);
+        when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTPS_URL),
+                anyString())).thenReturn(TEST_HTTPS_URL);
+
         when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephony);
         when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifi);
+
+        when(mNetworkInfo.getType()).thenReturn(ConnectivityManager.TYPE_WIFI);
+        setFallbackUrl(TEST_FALLBACK_URL);
+        setOtherFallbackUrls(TEST_OTHER_FALLBACK_URL);
+        setFallbackSpecs(null); // Test with no fallback spec by default
+        when(mRandom.nextInt()).thenReturn(0);
+
+        when(mNetwork.openConnection(any())).then((invocation) -> {
+            URL url = invocation.getArgument(0);
+            switch(url.toString()) {
+                case TEST_HTTP_URL:
+                    return mHttpConnection;
+                case TEST_HTTPS_URL:
+                    return mHttpsConnection;
+                case TEST_FALLBACK_URL:
+                    return mFallbackConnection;
+                case TEST_OTHER_FALLBACK_URL:
+                    return mOtherFallbackConnection;
+                default:
+                    fail("URL not mocked: " + url.toString());
+                    return null;
+            }
+        });
+        when(mHttpConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
+        when(mHttpsConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
+        when(mNetwork.getAllByName(any())).thenReturn(new InetAddress[] {
+            InetAddress.parseNumericAddress("192.168.0.0")
+        });
     }
 
     NetworkMonitor makeMonitor() {
-        return new NetworkMonitor(mContext, mHandler, mAgent, mRequest, mLogger, mSettings);
+        return new NetworkMonitor(
+                mContext, mHandler, mAgent, mRequest, mLogger, mDependencies);
     }
 
     @Test
-    public void testCreatingNetworkMonitor() {
-        NetworkMonitor monitor = makeMonitor();
+    public void testIsCaptivePortal_HttpProbeIsPortal() throws IOException {
+        setSslException(mHttpsConnection);
+        setPortal302(mHttpConnection);
+
+        assertPortal(makeMonitor().isCaptivePortal());
+    }
+
+    @Test
+    public void testIsCaptivePortal_HttpsProbeIsNotPortal() throws IOException {
+        setStatus(mHttpsConnection, 204);
+        setStatus(mHttpConnection, 500);
+
+        assertNotPortal(makeMonitor().isCaptivePortal());
+    }
+
+    @Test
+    public void testIsCaptivePortal_HttpsProbeFailedHttpSuccessNotUsed() throws IOException {
+        setSslException(mHttpsConnection);
+        // Even if HTTP returns a 204, do not use the result unless HTTPS succeeded
+        setStatus(mHttpConnection, 204);
+        setStatus(mFallbackConnection, 500);
+
+        assertFailed(makeMonitor().isCaptivePortal());
+    }
+
+    @Test
+    public void testIsCaptivePortal_FallbackProbeIsPortal() throws IOException {
+        setSslException(mHttpsConnection);
+        setStatus(mHttpConnection, 500);
+        setPortal302(mFallbackConnection);
+
+        assertPortal(makeMonitor().isCaptivePortal());
+    }
+
+    @Test
+    public void testIsCaptivePortal_FallbackProbeIsNotPortal() throws IOException {
+        setSslException(mHttpsConnection);
+        setStatus(mHttpConnection, 500);
+        setStatus(mFallbackConnection, 204);
+
+        // Fallback probe did not see portal, HTTPS failed -> inconclusive
+        assertFailed(makeMonitor().isCaptivePortal());
+    }
+
+    @Test
+    public void testIsCaptivePortal_OtherFallbackProbeIsPortal() throws IOException {
+        // Set all fallback probes but one to invalid URLs to verify they are being skipped
+        setFallbackUrl(TEST_FALLBACK_URL);
+        setOtherFallbackUrls(TEST_FALLBACK_URL + "," + TEST_OTHER_FALLBACK_URL);
+
+        setSslException(mHttpsConnection);
+        setStatus(mHttpConnection, 500);
+        setStatus(mFallbackConnection, 500);
+        setPortal302(mOtherFallbackConnection);
+
+        // TEST_OTHER_FALLBACK_URL is third
+        when(mRandom.nextInt()).thenReturn(2);
+
+        final NetworkMonitor monitor = makeMonitor();
+
+        // First check always uses the first fallback URL: inconclusive
+        assertFailed(monitor.isCaptivePortal());
+        verify(mFallbackConnection, times(1)).getResponseCode();
+        verify(mOtherFallbackConnection, never()).getResponseCode();
+
+        // Second check uses the URL chosen by Random
+        assertPortal(monitor.isCaptivePortal());
+        verify(mOtherFallbackConnection, times(1)).getResponseCode();
+    }
+
+    @Test
+    public void testIsCaptivePortal_AllProbesFailed() throws IOException {
+        setSslException(mHttpsConnection);
+        setStatus(mHttpConnection, 500);
+        setStatus(mFallbackConnection, 404);
+
+        assertFailed(makeMonitor().isCaptivePortal());
+        verify(mFallbackConnection, times(1)).getResponseCode();
+        verify(mOtherFallbackConnection, never()).getResponseCode();
+    }
+
+    @Test
+    public void testIsCaptivePortal_InvalidUrlSkipped() throws IOException {
+        setFallbackUrl("invalid");
+        setOtherFallbackUrls("otherinvalid," + TEST_OTHER_FALLBACK_URL + ",yetanotherinvalid");
+
+        setSslException(mHttpsConnection);
+        setStatus(mHttpConnection, 500);
+        setPortal302(mOtherFallbackConnection);
+
+        assertPortal(makeMonitor().isCaptivePortal());
+        verify(mOtherFallbackConnection, times(1)).getResponseCode();
+        verify(mFallbackConnection, never()).getResponseCode();
+    }
+
+    private void setupFallbackSpec() throws IOException {
+        setFallbackSpecs("http://example.com@@/@@204@@/@@"
+                + "@@,@@"
+                + TEST_OTHER_FALLBACK_URL + "@@/@@30[12]@@/@@https://(www\\.)?google.com/?.*");
+
+        setSslException(mHttpsConnection);
+        setStatus(mHttpConnection, 500);
+
+        // Use the 2nd fallback spec
+        when(mRandom.nextInt()).thenReturn(1);
+    }
+
+    @Test
+    public void testIsCaptivePortal_FallbackSpecIsNotPortal() throws IOException {
+        setupFallbackSpec();
+        set302(mOtherFallbackConnection, "https://www.google.com/test?q=3");
+
+        // HTTPS failed, fallback spec did not see a portal -> inconclusive
+        assertFailed(makeMonitor().isCaptivePortal());
+        verify(mOtherFallbackConnection, times(1)).getResponseCode();
+        verify(mFallbackConnection, never()).getResponseCode();
+    }
+
+    @Test
+    public void testIsCaptivePortal_FallbackSpecIsPortal() throws IOException {
+        setupFallbackSpec();
+        set302(mOtherFallbackConnection, "http://login.portal.example.com");
+
+        assertPortal(makeMonitor().isCaptivePortal());
+    }
+
+    private void setFallbackUrl(String url) {
+        when(mDependencies.getSetting(any(),
+                eq(Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL), any())).thenReturn(url);
+    }
+
+    private void setOtherFallbackUrls(String urls) {
+        when(mDependencies.getSetting(any(),
+                eq(Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS), any())).thenReturn(urls);
+    }
+
+    private void setFallbackSpecs(String specs) {
+        when(mDependencies.getSetting(any(),
+                eq(Settings.Global.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS), any())).thenReturn(specs);
+    }
+
+    private void assertPortal(CaptivePortalProbeResult result) {
+        assertTrue(result.isPortal());
+        assertFalse(result.isFailed());
+        assertFalse(result.isSuccessful());
+    }
+
+    private void assertNotPortal(CaptivePortalProbeResult result) {
+        assertFalse(result.isPortal());
+        assertFalse(result.isFailed());
+        assertTrue(result.isSuccessful());
+    }
+
+    private void assertFailed(CaptivePortalProbeResult result) {
+        assertFalse(result.isPortal());
+        assertTrue(result.isFailed());
+        assertFalse(result.isSuccessful());
+    }
+
+    private void setSslException(HttpURLConnection connection) throws IOException {
+        when(connection.getResponseCode()).thenThrow(new SSLHandshakeException("Invalid cert"));
+    }
+
+    private void set302(HttpURLConnection connection, String location) throws IOException {
+        setStatus(connection, 302);
+        when(connection.getHeaderField(LOCATION_HEADER)).thenReturn(location);
+    }
+
+    private void setPortal302(HttpURLConnection connection) throws IOException {
+        set302(connection, "http://login.example.com");
+    }
+
+    private void setStatus(HttpURLConnection connection, int status) throws IOException {
+        when(connection.getResponseCode()).thenReturn(status);
     }
 }
 
diff --git a/tests/net/java/com/android/server/connectivity/tethering/SimChangeListenerTest.java b/tests/net/java/com/android/server/connectivity/tethering/SimChangeListenerTest.java
deleted file mode 100644
index f58ea7e..0000000
--- a/tests/net/java/com/android/server/connectivity/tethering/SimChangeListenerTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.connectivity.tethering;
-
-import static com.android.internal.telephony.IccCardConstants.INTENT_VALUE_ICC_ABSENT;
-import static com.android.internal.telephony.IccCardConstants.INTENT_VALUE_ICC_LOADED;
-import static com.android.internal.telephony.IccCardConstants.INTENT_KEY_ICC_STATE;
-import static com.android.internal.telephony.TelephonyIntents.ACTION_SIM_STATE_CHANGED;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.reset;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.internal.util.test.BroadcastInterceptingContext;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class SimChangeListenerTest {
-    @Mock private Context mContext;
-    private BroadcastInterceptingContext mServiceContext;
-    private Handler mHandler;
-    private SimChangeListener mSCL;
-    private int mCallbackCount;
-
-    private void doCallback() { mCallbackCount++; }
-
-    private class MockContext extends BroadcastInterceptingContext {
-        MockContext(Context base) {
-            super(base);
-        }
-    }
-
-    @BeforeClass
-    public static void setUpBeforeClass() throws Exception {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-    }
-
-    @Before public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        reset(mContext);
-        mServiceContext = new MockContext(mContext);
-        mHandler = new Handler(Looper.myLooper());
-        mCallbackCount = 0;
-        mSCL = new SimChangeListener(mServiceContext, mHandler, () -> doCallback());
-    }
-
-    @After public void tearDown() throws Exception {
-        if (mSCL != null) {
-            mSCL.stopListening();
-            mSCL = null;
-        }
-    }
-
-    private void sendSimStateChangeIntent(String state) {
-        final Intent intent = new Intent(ACTION_SIM_STATE_CHANGED);
-        intent.putExtra(INTENT_KEY_ICC_STATE, state);
-        mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-    }
-
-    @Test
-    public void testNotSeenFollowedBySeenCallsCallback() {
-        mSCL.startListening();
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(1, mCallbackCount);
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(2, mCallbackCount);
-
-        mSCL.stopListening();
-    }
-
-    @Test
-    public void testNotListeningDoesNotCallback() {
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(0, mCallbackCount);
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(0, mCallbackCount);
-    }
-
-    @Test
-    public void testSeenOnlyDoesNotCallback() {
-        mSCL.startListening();
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(0, mCallbackCount);
-
-        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
-        assertEquals(0, mCallbackCount);
-
-        mSCL.stopListening();
-    }
-}
diff --git a/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java
index 2757296..388c7d0 100644
--- a/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java
+++ b/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java
@@ -52,7 +52,7 @@
             final VibrationEffect effect =
                     VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE);
             mVibratorService.vibrate(Process.myUid(), null, effect, AudioManager.STREAM_ALARM,
-                    new Binder());
+                    "testVibrate", new Binder());
             fail("vibrate did not throw SecurityException as expected");
         } catch (SecurityException e) {
             // expected
diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk
index 9795188..1149b8a 100644
--- a/tests/privapp-permissions/Android.mk
+++ b/tests/privapp-permissions/Android.mk
@@ -46,3 +46,19 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
 LOCAL_SRC_FILES:= product/privapp-permissions-test.xml
 include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := ProductServicesPrivAppPermissionTest
+LOCAL_SDK_VERSION := current
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MANIFEST_FILE := product_services/AndroidManifest.xml
+LOCAL_PRODUCT_SERVICES_MODULE := true
+LOCAL_REQUIRED_MODULES := product_servicesprivapp-permissions-test.xml
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := product_servicesprivapp-permissions-test.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions
+LOCAL_SRC_FILES:= product_services/privapp-permissions-test.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/privapp-permissions/product_services/AndroidManifest.xml b/tests/privapp-permissions/product_services/AndroidManifest.xml
new file mode 100644
index 0000000..511ddee
--- /dev/null
+++ b/tests/privapp-permissions/product_services/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.framework.permission.privapp.tests.product_services">
+
+    <!-- MANAGE_USB is signature|privileged -->
+    <uses-permission android:name="android.permission.MANAGE_USB"/>
+</manifest>
diff --git a/tests/privapp-permissions/product_services/privapp-permissions-test.xml b/tests/privapp-permissions/product_services/privapp-permissions-test.xml
new file mode 100644
index 0000000..43baebb
--- /dev/null
+++ b/tests/privapp-permissions/product_services/privapp-permissions-test.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<permissions>
+    <privapp-permissions package="com.android.framework.permission.privapp.tests.product_services">
+        <permission name="android.permission.MANAGE_USB"/>
+    </privapp-permissions>
+</permissions>
diff --git a/tests/testables/Android.bp b/tests/testables/Android.bp
new file mode 100644
index 0000000..f07f09d
--- /dev/null
+++ b/tests/testables/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+java_library {
+
+    name: "testables",
+    // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_MODULE_TAG
+    // LOCAL_MODULE_TAG := tests
+
+    srcs: ["src/**/*.java"],
+
+    libs: [
+        "android.test.runner",
+        "android.test.mock",
+        "android-support-test",
+        "mockito-target-inline-minus-junit4",
+    ],
+
+}
diff --git a/tests/testables/Android.mk b/tests/testables/Android.mk
deleted file mode 100644
index f3cbac0..0000000
--- a/tests/testables/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := testables
-LOCAL_MODULE_TAG := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.mock \
-    android-support-test \
-    mockito-target-inline-minus-junit4
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/testables/src/android/testing/TestableContentResolver.java b/tests/testables/src/android/testing/TestableContentResolver.java
index 0850916..a0afef8 100644
--- a/tests/testables/src/android/testing/TestableContentResolver.java
+++ b/tests/testables/src/android/testing/TestableContentResolver.java
@@ -20,6 +20,7 @@
 import android.content.IContentProvider;
 import android.database.ContentObserver;
 import android.net.Uri;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 
 import com.google.android.collect.Maps;
@@ -35,7 +36,11 @@
  */
 public class TestableContentResolver extends ContentResolver {
 
-    private final Map<String, ContentProvider> mProviders = Maps.newHashMap();
+    public static final int STABLE = 1;
+    public static final int UNSTABLE = 2;
+
+    private final Map<String, ContentProvider> mProviders = new ArrayMap<>();
+    private final Map<String, ContentProvider> mUnstableProviders = new ArrayMap<>();
     private final ContentResolver mParent;
     private final ArraySet<ContentProvider> mInUse = new ArraySet<>();
     private boolean mFallbackToExisting;
@@ -62,7 +67,23 @@
      * subclasses, or null.
      */
     public void addProvider(String name, ContentProvider provider) {
-        mProviders.put(name, provider);
+        addProvider(name, provider, STABLE | UNSTABLE);
+    }
+
+    /**
+     * Adds access to a provider based on its authority
+     *
+     * @param name The authority name associated with the provider.
+     * @param provider An instance of {@link android.content.ContentProvider} or one of its
+     * subclasses, or null.
+     */
+    public void addProvider(String name, ContentProvider provider, int flags) {
+        if ((flags & STABLE) != 0) {
+            mProviders.put(name, provider);
+        }
+        if ((flags & UNSTABLE) != 0) {
+            mUnstableProviders.put(name, provider);
+        }
     }
 
     @Override
@@ -98,7 +119,7 @@
 
     @Override
     protected IContentProvider acquireUnstableProvider(Context c, String name) {
-        final ContentProvider provider = mProviders.get(name);
+        final ContentProvider provider = mUnstableProviders.get(name);
         if (provider != null) {
             return provider.getIContentProvider();
         } else {
@@ -128,7 +149,8 @@
     @Override
     public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
         if (!mFallbackToExisting) return;
-        if (!mProviders.containsKey(uri.getAuthority())) {
+        if (!mProviders.containsKey(uri.getAuthority())
+                && !mUnstableProviders.containsKey(uri.getAuthority())) {
             super.notifyChange(uri, observer, syncToNetwork);
         }
     }
diff --git a/tests/testables/src/android/testing/TestableInstrumentation.java b/tests/testables/src/android/testing/TestableInstrumentation.java
index 3207b48..c35dc68 100644
--- a/tests/testables/src/android/testing/TestableInstrumentation.java
+++ b/tests/testables/src/android/testing/TestableInstrumentation.java
@@ -38,22 +38,26 @@
 
     @Override
     public void onCreate(Bundle arguments) {
-        sManager = new MainLooperManager();
-        Log.setWtfHandler((tag, what, system) -> {
-            if (system) {
-                Log.e(TAG, "WTF!!", what);
-            } else {
-                // These normally kill the app, but we don't want that in a test, instead we want
-                // it to throw.
-                throw new RuntimeException(what);
-            }
-        });
+        if (TestableLooper.HOLD_MAIN_THREAD) {
+            sManager = new MainLooperManager();
+            Log.setWtfHandler((tag, what, system) -> {
+                if (system) {
+                    Log.e(TAG, "WTF!!", what);
+                } else {
+                    // These normally kill the app, but we don't want that in a test, instead we want
+                    // it to throw.
+                    throw new RuntimeException(what);
+                }
+            });
+        }
         super.onCreate(arguments);
     }
 
     @Override
     public void finish(int resultCode, Bundle results) {
-        sManager.destroy();
+        if (TestableLooper.HOLD_MAIN_THREAD) {
+            sManager.destroy();
+        }
         super.finish(resultCode, results);
     }
 
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index f8d223a..8b4cba1 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -39,6 +39,12 @@
  */
 public class TestableLooper {
 
+    /**
+     * Whether to hold onto the main thread through all tests in an attempt to
+     * catch crashes.
+     */
+    public static final boolean HOLD_MAIN_THREAD = false;
+
     private Looper mLooper;
     private MessageQueue mQueue;
     private MessageHandler mMessageHandler;
@@ -77,7 +83,7 @@
      */
     public void destroy() {
         mQueueWrapper.release();
-        if (mLooper == Looper.getMainLooper()) {
+        if (HOLD_MAIN_THREAD && mLooper == Looper.getMainLooper()) {
             TestableInstrumentation.releaseMain();
         }
     }
@@ -199,7 +205,7 @@
     }
 
     private static TestLooperManager acquireLooperManager(Looper l) {
-        if (l == Looper.getMainLooper()) {
+        if (HOLD_MAIN_THREAD && l == Looper.getMainLooper()) {
             TestableInstrumentation.acquireMain();
         }
         return InstrumentationRegistry.getInstrumentation().acquireLooperManager(l);
@@ -291,7 +297,7 @@
                 if (set) {
                     mTestableLooper.mQueueWrapper.release();
                     mTestableLooper.mQueueWrapper = null;
-                    if (mLooper == Looper.getMainLooper()) {
+                    if (HOLD_MAIN_THREAD && mLooper == Looper.getMainLooper()) {
                         TestableInstrumentation.releaseMain();
                     }
                 }
diff --git a/tests/testables/tests/src/android/testing/TestableContentResolverTest.java b/tests/testables/tests/src/android/testing/TestableContentResolverTest.java
new file mode 100644
index 0000000..71afda0
--- /dev/null
+++ b/tests/testables/tests/src/android/testing/TestableContentResolverTest.java
@@ -0,0 +1,61 @@
+package android.testing;
+
+import android.content.ContentProvider;
+import android.content.IContentProvider;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class TestableContentResolverTest {
+
+    @Rule
+    public TestableContext mContext = new TestableContext(InstrumentationRegistry.getContext());
+    private TestableContentResolver mContentResolver;
+
+    @Before
+    public void setup() {
+        mContentResolver = new TestableContentResolver(mContext);
+        mContentResolver.setFallbackToExisting(false);
+    }
+
+    @Test
+    public void testDefaultContentProvider() {
+        ContentProvider provider = Mockito.mock(ContentProvider.class);
+        IContentProvider iprovider = Mockito.mock(IContentProvider.class);
+        Mockito.when(provider.getIContentProvider()).thenReturn(iprovider);
+        mContentResolver.addProvider("test", provider);
+
+        Assert.assertEquals(iprovider, mContentResolver.acquireProvider(mContext, "test"));
+        Assert.assertEquals(iprovider, mContentResolver.acquireUnstableProvider(mContext, "test"));
+    }
+
+    @Test
+    public void testStableContentProvider() {
+        ContentProvider provider = Mockito.mock(ContentProvider.class);
+        IContentProvider iprovider = Mockito.mock(IContentProvider.class);
+        Mockito.when(provider.getIContentProvider()).thenReturn(iprovider);
+        mContentResolver.addProvider("test", provider, TestableContentResolver.STABLE);
+
+        Assert.assertEquals(iprovider, mContentResolver.acquireProvider(mContext, "test"));
+        Assert.assertNull(mContentResolver.acquireUnstableProvider(mContext, "test"));
+    }
+
+    @Test
+    public void testUnstableContentProvider() {
+        ContentProvider provider = Mockito.mock(ContentProvider.class);
+        IContentProvider iprovider = Mockito.mock(IContentProvider.class);
+        Mockito.when(provider.getIContentProvider()).thenReturn(iprovider);
+        mContentResolver.addProvider("test", provider, TestableContentResolver.UNSTABLE);
+
+        Assert.assertEquals(iprovider, mContentResolver.acquireUnstableProvider(mContext, "test"));
+        Assert.assertNull(mContentResolver.acquireProvider(mContext, "test"));
+    }
+}
diff --git a/tests/utils/testutils/Android.bp b/tests/utils/testutils/Android.bp
new file mode 100644
index 0000000..4be6534
--- /dev/null
+++ b/tests/utils/testutils/Android.bp
@@ -0,0 +1,30 @@
+//
+// 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.
+//
+
+java_library {
+    name: "frameworks-base-testutils",
+
+    srcs: ["java/**/*.java"],
+
+    static_libs: ["android-support-test"],
+
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.test.mock",
+        "mockito-target-minus-junit4",
+    ],
+}
diff --git a/tests/utils/testutils/Android.mk b/tests/utils/testutils/Android.mk
deleted file mode 100644
index a76616f..0000000
--- a/tests/utils/testutils/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := frameworks-base-testutils
-LOCAL_MODULE_TAG := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under,java)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.runner \
-    android.test.base \
-    android.test.mock \
-    mockito-target-minus-junit4 \
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 861efd5..69392d6 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -474,9 +474,9 @@
                 if (value.dataType == Res_value::TYPE_NULL) {
                     printf("=(null)");
                 } else if (value.dataType == Res_value::TYPE_REFERENCE) {
-                    printf("=@0x%x", (int)value.data);
+                    printf("=@0x%08x", (int)value.data);
                 } else if (value.dataType == Res_value::TYPE_ATTRIBUTE) {
-                    printf("=?0x%x", (int)value.data);
+                    printf("=?0x%08x", (int)value.data);
                 } else if (value.dataType == Res_value::TYPE_STRING) {
                     printf("=\"%s\"",
                             ResTable::normalizeForOutput(String8(block->getAttributeStringValue(i,
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 7a33de0..2ecf25b 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -15,6 +15,7 @@
 //
 
 toolSources = [
+    "cmd/Command.cpp",
     "cmd/Compile.cpp",
     "cmd/Convert.cpp",
     "cmd/Diff.cpp",
@@ -124,7 +125,6 @@
         "ConfigDescription.cpp",
         "Debug.cpp",
         "DominatorTree.cpp",
-        "Flags.cpp",
         "java/AnnotationProcessor.cpp",
         "java/ClassDefinition.cpp",
         "java/JavaClassGenerator.cpp",
diff --git a/tools/aapt2/AppInfo.h b/tools/aapt2/AppInfo.h
index d6f5995..7512353 100644
--- a/tools/aapt2/AppInfo.h
+++ b/tools/aapt2/AppInfo.h
@@ -31,9 +31,12 @@
   // The app's minimum SDK version, if it is defined.
   Maybe<int> min_sdk_version;
 
-  // The app's version code, if it is defined.
+  // The app's version code (the lower 32 bits of the long version code), if it is defined.
   Maybe<uint32_t> version_code;
 
+  // The app's version code major (the upper 32 bits of the long version code), if it is defined.
+  Maybe<uint32_t> version_code_major;
+
   // The app's revision code, if it is defined.
   Maybe<uint32_t> revision_code;
 
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index f064cb1..0a517ab 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -408,6 +408,41 @@
   }
 }
 
+void Debug::DumpResStringPool(const android::ResStringPool* pool, text::Printer* printer) {
+  using namespace android;
+  
+  if (pool->getError() == NO_INIT) {
+    printer->Print("String pool is unitialized.\n");
+    return;
+  } else if (pool->getError() != NO_ERROR) {
+    printer->Print("String pool is corrupt/invalid.\n");
+    return;
+  }
+
+  SortedVector<const void*> uniqueStrings;
+  const size_t N = pool->size();
+  for (size_t i=0; i<N; i++) {
+    size_t len;
+    if (pool->isUTF8()) {
+      uniqueStrings.add(pool->string8At(i, &len));
+    } else {
+      uniqueStrings.add(pool->stringAt(i, &len));
+    }
+  }
+
+  printer->Print(StringPrintf("String pool of %zd unique %s %s strings, %zd entries and %zd styles "
+                              "using %zd bytes:\n", uniqueStrings.size(),
+                              pool->isUTF8() ? "UTF-8" : "UTF-16",
+                              pool->isSorted() ? "sorted" : "non-sorted", N, pool->styleCount(),
+                              pool->bytes()));
+
+  const size_t NS = pool->size();
+  for (size_t s=0; s<NS; s++) {
+    String8 str = pool->string8ObjectAt(s);
+    printer->Print(StringPrintf("String #%zd : %s\n", s, str.string()));
+  }
+}
+
 namespace {
 
 class XmlPrinter : public xml::ConstVisitor {
diff --git a/tools/aapt2/Debug.h b/tools/aapt2/Debug.h
index 382707e..a43197c 100644
--- a/tools/aapt2/Debug.h
+++ b/tools/aapt2/Debug.h
@@ -38,6 +38,7 @@
   static void PrintStyleGraph(ResourceTable* table, const ResourceName& target_style);
   static void DumpHex(const void* data, size_t len);
   static void DumpXml(const xml::XmlResource& doc, text::Printer* printer);
+  static void DumpResStringPool(const android::ResStringPool* pool, text::Printer* printer);
 };
 
 }  // namespace aapt
diff --git a/tools/aapt2/Flags.cpp b/tools/aapt2/Flags.cpp
deleted file mode 100644
index 84977ab..0000000
--- a/tools/aapt2/Flags.cpp
+++ /dev/null
@@ -1,189 +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.
- */
-
-#include "Flags.h"
-
-#include <iomanip>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "androidfw/StringPiece.h"
-
-#include "util/Util.h"
-
-using android::StringPiece;
-
-namespace aapt {
-
-Flags& Flags::RequiredFlag(const StringPiece& name,
-                           const StringPiece& description, std::string* value) {
-  auto func = [value](const StringPiece& arg) -> bool {
-    *value = arg.to_string();
-    return true;
-  };
-
-  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
-  return *this;
-}
-
-Flags& Flags::RequiredFlagList(const StringPiece& name,
-                               const StringPiece& description,
-                               std::vector<std::string>* value) {
-  auto func = [value](const StringPiece& arg) -> bool {
-    value->push_back(arg.to_string());
-    return true;
-  };
-
-  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
-  return *this;
-}
-
-Flags& Flags::OptionalFlag(const StringPiece& name,
-                           const StringPiece& description,
-                           Maybe<std::string>* value) {
-  auto func = [value](const StringPiece& arg) -> bool {
-    *value = arg.to_string();
-    return true;
-  };
-
-  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
-  return *this;
-}
-
-Flags& Flags::OptionalFlagList(const StringPiece& name,
-                               const StringPiece& description,
-                               std::vector<std::string>* value) {
-  auto func = [value](const StringPiece& arg) -> bool {
-    value->push_back(arg.to_string());
-    return true;
-  };
-
-  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
-  return *this;
-}
-
-Flags& Flags::OptionalFlagList(const StringPiece& name,
-                               const StringPiece& description,
-                               std::unordered_set<std::string>* value) {
-  auto func = [value](const StringPiece& arg) -> bool {
-    value->insert(arg.to_string());
-    return true;
-  };
-
-  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
-  return *this;
-}
-
-Flags& Flags::OptionalSwitch(const StringPiece& name,
-                             const StringPiece& description, bool* value) {
-  auto func = [value](const StringPiece& arg) -> bool {
-    *value = true;
-    return true;
-  };
-
-  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 0, false});
-  return *this;
-}
-
-void Flags::Usage(const StringPiece& command, std::ostream* out) {
-  constexpr size_t kWidth = 50;
-
-  *out << command << " [options]";
-  for (const Flag& flag : flags_) {
-    if (flag.required) {
-      *out << " " << flag.name << " arg";
-    }
-  }
-
-  *out << " files...\n\nOptions:\n";
-
-  for (const Flag& flag : flags_) {
-    std::string argline = flag.name;
-    if (flag.num_args > 0) {
-      argline += " arg";
-    }
-
-    // Split the description by newlines and write out the argument (which is
-    // empty after
-    // the first line) followed by the description line. This will make sure
-    // that multiline
-    // descriptions are still right justified and aligned.
-    for (StringPiece line : util::Tokenize(flag.description, '\n')) {
-      *out << " " << std::setw(kWidth) << std::left << argline << line << "\n";
-      argline = " ";
-    }
-  }
-  *out << " " << std::setw(kWidth) << std::left << "-h"
-       << "Displays this help menu\n";
-  out->flush();
-}
-
-bool Flags::Parse(const StringPiece& command,
-                  const std::vector<StringPiece>& args,
-                  std::ostream* out_error) {
-  for (size_t i = 0; i < args.size(); i++) {
-    StringPiece arg = args[i];
-    if (*(arg.data()) != '-') {
-      args_.push_back(arg.to_string());
-      continue;
-    }
-
-    if (arg == "-h" || arg == "--help") {
-      Usage(command, out_error);
-      return false;
-    }
-
-    bool match = false;
-    for (Flag& flag : flags_) {
-      if (arg == flag.name) {
-        if (flag.num_args > 0) {
-          i++;
-          if (i >= args.size()) {
-            *out_error << flag.name << " missing argument.\n\n";
-            Usage(command, out_error);
-            return false;
-          }
-          flag.action(args[i]);
-        } else {
-          flag.action({});
-        }
-        flag.parsed = true;
-        match = true;
-        break;
-      }
-    }
-
-    if (!match) {
-      *out_error << "unknown option '" << arg << "'.\n\n";
-      Usage(command, out_error);
-      return false;
-    }
-  }
-
-  for (const Flag& flag : flags_) {
-    if (flag.required && !flag.parsed) {
-      *out_error << "missing required flag " << flag.name << "\n\n";
-      Usage(command, out_error);
-      return false;
-    }
-  }
-  return true;
-}
-
-const std::vector<std::string>& Flags::GetArgs() { return args_; }
-
-}  // namespace aapt
diff --git a/tools/aapt2/Flags.h b/tools/aapt2/Flags.h
deleted file mode 100644
index 3b3ae71..0000000
--- a/tools/aapt2/Flags.h
+++ /dev/null
@@ -1,71 +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.
- */
-
-#ifndef AAPT_FLAGS_H
-#define AAPT_FLAGS_H
-
-#include <functional>
-#include <ostream>
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include "androidfw/StringPiece.h"
-
-#include "util/Maybe.h"
-
-namespace aapt {
-
-class Flags {
- public:
-  Flags& RequiredFlag(const android::StringPiece& name, const android::StringPiece& description,
-                      std::string* value);
-  Flags& RequiredFlagList(const android::StringPiece& name, const android::StringPiece& description,
-                          std::vector<std::string>* value);
-  Flags& OptionalFlag(const android::StringPiece& name, const android::StringPiece& description,
-                      Maybe<std::string>* value);
-  Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description,
-                          std::vector<std::string>* value);
-  Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description,
-                          std::unordered_set<std::string>* value);
-  Flags& OptionalSwitch(const android::StringPiece& name, const android::StringPiece& description,
-                        bool* value);
-
-  void Usage(const android::StringPiece& command, std::ostream* out);
-
-  bool Parse(const android::StringPiece& command, const std::vector<android::StringPiece>& args,
-             std::ostream* outError);
-
-  const std::vector<std::string>& GetArgs();
-
- private:
-  struct Flag {
-    std::string name;
-    std::string description;
-    std::function<bool(const android::StringPiece& value)> action;
-    bool required;
-    size_t num_args;
-
-    bool parsed;
-  };
-
-  std::vector<Flag> flags_;
-  std::vector<std::string> args_;
-};
-
-}  // namespace aapt
-
-#endif  // AAPT_FLAGS_H
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index 1dd46ba..a73d56c 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -76,7 +76,7 @@
     }
 
     std::string error;
-    table = util::make_unique<ResourceTable>();
+    table = util::make_unique<ResourceTable>(/** validate_resources **/ false);
     if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) {
       diag->Error(DiagMessage(source)
                   << "failed to deserialize " << kProtoResourceTablePath << ": " << error);
@@ -120,7 +120,7 @@
 
   io::IFile* table_file = collection->FindFile(kApkResourceTablePath);
   if (table_file != nullptr) {
-    table = util::make_unique<ResourceTable>();
+    table = util::make_unique<ResourceTable>(/** validate_resources **/ false);
     std::unique_ptr<io::IData> data = table_file->OpenAsData();
     if (data == nullptr) {
       diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath);
@@ -184,10 +184,7 @@
   std::unique_ptr<io::IFileCollectionIterator> iterator = apk_->Iterator();
   while (iterator->HasNext()) {
     io::IFile* file = iterator->Next();
-
     std::string path = file->GetSource().path;
-    // The name of the path has the format "<zip-file-name>@<path-to-file>".
-    path = path.substr(path.find('@') + 1);
 
     // Skip resources that are not referenced if requested.
     if (path.find("res/") == 0 && referenced_resources.find(path) == referenced_resources.end()) {
@@ -257,6 +254,53 @@
   return true;
 }
 
+std::unique_ptr<xml::XmlResource> LoadedApk::LoadXml(const std::string& file_path,
+                                                     IDiagnostics* diag) {
+  io::IFile* file = apk_->FindFile(file_path);
+  if (file == nullptr) {
+    diag->Error(DiagMessage() << "failed to find file");
+    return nullptr;
+  }
+
+  std::unique_ptr<xml::XmlResource> doc;
+  if (format_ == ApkFormat::kProto) {
+    std::unique_ptr<io::InputStream> in = file->OpenInputStream();
+    if (!in) {
+      diag->Error(DiagMessage() << "failed to open file");
+      return nullptr;
+    }
+
+    io::ZeroCopyInputAdaptor adaptor(in.get());
+    pb::XmlNode pb_node;
+    if (!pb_node.ParseFromZeroCopyStream(&adaptor)) {
+      diag->Error(DiagMessage() << "failed to parse file as proto XML");
+      return nullptr;
+    }
+
+    std::string err;
+    doc = DeserializeXmlResourceFromPb(pb_node, &err);
+    if (!doc) {
+      diag->Error(DiagMessage() << "failed to deserialize proto XML: " << err);
+      return nullptr;
+    }
+  } else if (format_ == ApkFormat::kBinary) {
+    std::unique_ptr<io::IData> data = file->OpenAsData();
+    if (!data) {
+      diag->Error(DiagMessage() << "failed to open file");
+      return nullptr;
+    }
+
+    std::string err;
+    doc = xml::Inflate(data->data(), data->size(), &err);
+    if (!doc) {
+      diag->Error(DiagMessage() << "failed to parse file as binary XML: " << err);
+      return nullptr;
+    }
+  }
+
+  return doc;
+}
+
 ApkFormat LoadedApk::DetermineApkFormat(io::IFileCollection* apk) {
   if (apk->FindFile(kApkResourceTablePath) != nullptr) {
     return ApkFormat::kBinary;
diff --git a/tools/aapt2/LoadedApk.h b/tools/aapt2/LoadedApk.h
index 41f879d..dcb085a 100644
--- a/tools/aapt2/LoadedApk.h
+++ b/tools/aapt2/LoadedApk.h
@@ -70,6 +70,10 @@
     return apk_.get();
   }
 
+  ApkFormat GetApkFormat() {
+    return format_;
+  }
+
   const ResourceTable* GetResourceTable() const {
     return table_.get();
   }
@@ -106,6 +110,8 @@
                               const TableFlattenerOptions& options, FilterChain* filters,
                               IArchiveWriter* writer, xml::XmlResource* manifest = nullptr);
 
+  /** Loads the file as an xml document. */
+  std::unique_ptr<xml::XmlResource> LoadXml(const std::string& file_path, IDiagnostics* diag);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedApk);
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index 808b29c..37013c0 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -29,6 +29,13 @@
 #include "androidfw/StringPiece.h"
 
 #include "Diagnostics.h"
+#include "cmd/Command.h"
+#include "cmd/Compile.h"
+#include "cmd/Convert.h"
+#include "cmd/Diff.h"
+#include "cmd/Dump.h"
+#include "cmd/Link.h"
+#include "cmd/Optimize.h"
 #include "util/Files.h"
 #include "util/Util.h"
 
@@ -43,114 +50,121 @@
 // Update minor version whenever a feature or flag is added.
 static const char* sMinorVersion = "19";
 
-static void PrintVersion() {
-  std::cerr << StringPrintf("Android Asset Packaging Tool (aapt) %s:%s", sMajorVersion,
-                            sMinorVersion)
-            << std::endl;
-}
+/** Prints the version information of AAPT2. */
+class VersionCommand : public Command {
+ public:
+  explicit VersionCommand() : Command("version") {
+    SetDescription("Prints the version of aapt.");
+  }
 
-static void PrintUsage() {
-  std::cerr << "\nusage: aapt2 [compile|link|dump|diff|optimize|convert|version] ..." << std::endl;
-}
-
-extern int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics);
-extern int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics);
-extern int Dump(const std::vector<StringPiece>& args);
-extern int Diff(const std::vector<StringPiece>& args);
-extern int Optimize(const std::vector<StringPiece>& args);
-extern int Convert(const std::vector<StringPiece>& args);
-
-static int ExecuteCommand(const StringPiece& command, const std::vector<StringPiece>& args,
-                          IDiagnostics* diagnostics) {
-  if (command == "compile" || command == "c") {
-    return Compile(args, diagnostics);
-  } else if (command == "link" || command == "l") {
-    return Link(args, diagnostics);
-  } else if (command == "dump" || command == "d") {
-    return Dump(args);
-  } else if (command == "diff") {
-    return Diff(args);
-  } else if (command == "optimize") {
-    return Optimize(args);
-  } else if (command == "convert") {
-    return Convert(args);
-  } else if (command == "version") {
-    PrintVersion();
+  int Action(const std::vector<std::string>& /* args */) override {
+    std::cerr << StringPrintf("Android Asset Packaging Tool (aapt) %s:%s", sMajorVersion,
+                              sMinorVersion)
+              << std::endl;
     return 0;
   }
-  diagnostics->Error(DiagMessage() << "unknown command '" << command << "'");
-  return -1;
-}
+};
 
-static void RunDaemon(IDiagnostics* diagnostics) {
-  std::cout << "Ready" << std::endl;
-
-  // Run in daemon mode. The first line of input is the command. This can be 'quit' which ends
-  // the daemon mode. Each subsequent line is a single parameter to the command. The end of a
-  // invocation is signaled by providing an empty line. At any point, an EOF signal or the
-  // command 'quit' will end the daemon mode.
-  while (true) {
-    std::vector<std::string> raw_args;
-    for (std::string line; std::getline(std::cin, line) && !line.empty();) {
-      raw_args.push_back(line);
-    }
-
-    if (!std::cin) {
-      break;
-    }
-
-    // An empty command does nothing.
-    if (raw_args.empty()) {
-      continue;
-    }
-
-    if (raw_args[0] == "quit") {
-      break;
-    }
-
-    std::vector<StringPiece> args;
-    args.insert(args.end(), ++raw_args.begin(), raw_args.end());
-    int ret = ExecuteCommand(raw_args[0], args, diagnostics);
-    if (ret != 0) {
-      std::cerr << "Error" << std::endl;
-    }
-    std::cerr << "Done" << std::endl;
+/** The main entry point of AAPT. */
+class MainCommand : public Command {
+ public:
+  explicit MainCommand(IDiagnostics* diagnostics) : Command("aapt2"), diagnostics_(diagnostics) {
+    AddOptionalSubcommand(util::make_unique<CompileCommand>(diagnostics));
+    AddOptionalSubcommand(util::make_unique<LinkCommand>(diagnostics));
+    AddOptionalSubcommand(util::make_unique<DumpCommand>(diagnostics));
+    AddOptionalSubcommand(util::make_unique<DiffCommand>());
+    AddOptionalSubcommand(util::make_unique<OptimizeCommand>());
+    AddOptionalSubcommand(util::make_unique<ConvertCommand>());
+    AddOptionalSubcommand(util::make_unique<VersionCommand>());
   }
-  std::cout << "Exiting daemon" << std::endl;
-}
+
+  int Action(const std::vector<std::string>& args) override {
+    if (args.size() == 0) {
+      diagnostics_->Error(DiagMessage() << "no subcommand specified");
+    } else {
+      diagnostics_->Error(DiagMessage() << "unknown subcommand '" << args[0] << "'");
+    }
+
+    Usage(&std::cerr);
+    return -1;
+  }
+
+ private:
+  IDiagnostics* diagnostics_;
+};
+
+/*
+ * Run in daemon mode. The first line of input is the command. This can be 'quit' which ends
+ * the daemon mode. Each subsequent line is a single parameter to the command. The end of a
+ * invocation is signaled by providing an empty line. At any point, an EOF signal or the
+ * command 'quit' will end the daemon mode.
+ */
+class DaemonCommand : public Command {
+ public:
+  explicit DaemonCommand(IDiagnostics* diagnostics) : Command("daemon", "m"),
+                                                      diagnostics_(diagnostics) {
+    SetDescription("Runs aapt in daemon mode. Each subsequent line is a single parameter to the\n"
+        "command. The end of an invocation is signaled by providing an empty line.");
+  }
+
+  int Action(const std::vector<std::string>& /* args */) override {
+    std::cout << "Ready" << std::endl;
+
+    while (true) {
+      std::vector<std::string> raw_args;
+      for (std::string line; std::getline(std::cin, line) && !line.empty();) {
+        raw_args.push_back(line);
+      }
+
+      if (!std::cin) {
+        break;
+      }
+
+      // An empty command does nothing.
+      if (raw_args.empty()) {
+        continue;
+      }
+
+      // End the dameon
+      if (raw_args[0] == "quit") {
+        break;
+      }
+
+      std::vector<StringPiece> args;
+      args.insert(args.end(), raw_args.begin(), raw_args.end());
+      if (MainCommand(diagnostics_).Execute(args, &std::cerr) != 0) {
+        std::cerr << "Error" << std::endl;
+      }
+      std::cerr << "Done" << std::endl;
+    }
+    std::cout << "Exiting daemon" << std::endl;
+
+    return 0;
+  }
+
+ private:
+  IDiagnostics* diagnostics_;
+};
 
 }  // namespace aapt
 
 int MainImpl(int argc, char** argv) {
-  if (argc < 2) {
-    std::cerr << "no command specified\n";
-    aapt::PrintUsage();
+  if (argc < 1) {
     return -1;
   }
 
-  argv += 1;
-  argc -= 1;
-
-  aapt::StdErrDiagnostics diagnostics;
-
   // Collect the arguments starting after the program name and command name.
   std::vector<StringPiece> args;
   for (int i = 1; i < argc; i++) {
     args.push_back(argv[i]);
   }
 
-  const StringPiece command(argv[0]);
-  if (command != "daemon" && command != "m") {
-    // Single execution.
-    const int result = aapt::ExecuteCommand(command, args, &diagnostics);
-    if (result < 0) {
-      aapt::PrintUsage();
-    }
-    return result;
-  }
+  // Add the daemon subcommand here so it cannot be called while executing the daemon
+  aapt::StdErrDiagnostics diagnostics;
+  auto main_command = new aapt::MainCommand(&diagnostics);
+  main_command->AddOptionalSubcommand(aapt::util::make_unique<aapt::DaemonCommand>(&diagnostics));
 
-  aapt::RunDaemon(&diagnostics);
-  return 0;
+  return main_command->Execute(args, &std::cerr);
 }
 
 int main(int argc, char** argv) {
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp
index b78f48c..ae01170 100644
--- a/tools/aapt2/Resource.cpp
+++ b/tools/aapt2/Resource.cpp
@@ -96,6 +96,8 @@
       return "styleable";
     case ResourceType::kTransition:
       return "transition";
+    case ResourceType::kUnknown:
+      return "unknown";
     case ResourceType::kXml:
       return "xml";
   }
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 6fcf0f6..879d0bd 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -66,6 +66,11 @@
   kStyle,
   kStyleable,
   kTransition,
+
+  // Not a parsed type. It is only used when loading resource tables that may have modified type
+  // names
+  kUnknown,
+
   kXml,
 };
 
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index d0faac3..58b5e8f 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -26,6 +26,7 @@
 #include "androidfw/ResourceTypes.h"
 
 #include "ConfigDescription.h"
+#include "Debug.h"
 #include "NameMangler.h"
 #include "ResourceValues.h"
 #include "ValueVisitor.h"
@@ -38,8 +39,9 @@
 
 namespace aapt {
 
-static bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs, ResourceType rhs) {
-  return lhs->type < rhs;
+static bool less_than_type_and_id(const std::unique_ptr<ResourceTableType>& lhs,
+                                  const std::pair<ResourceType, Maybe<uint8_t>>& rhs) {
+  return lhs->type < rhs.first || (lhs->type == rhs.first && rhs.second && lhs->id < rhs.second);
 }
 
 template <typename T>
@@ -51,7 +53,7 @@
 static bool less_than_struct_with_name_and_id(const std::unique_ptr<T>& lhs,
                                               const std::pair<StringPiece, Maybe<uint8_t>>& rhs) {
   int name_cmp = lhs->name.compare(0, lhs->name.size(), rhs.first.data(), rhs.first.size());
-  return name_cmp < 0 || (name_cmp == 0 && lhs->id < rhs.second);
+  return name_cmp < 0 || (name_cmp == 0 && rhs.second && lhs->id < rhs.second);
 }
 
 ResourceTablePackage* ResourceTable::FindPackage(const StringPiece& name) const {
@@ -115,42 +117,52 @@
   return packages.emplace(iter, std::move(new_package))->get();
 }
 
-ResourceTableType* ResourceTablePackage::FindType(ResourceType type) {
+ResourceTableType* ResourceTablePackage::FindType(ResourceType type, const Maybe<uint8_t> id) {
   const auto last = types.end();
-  auto iter = std::lower_bound(types.begin(), last, type, less_than_type);
-  if (iter != last && (*iter)->type == type) {
+  auto iter = std::lower_bound(types.begin(), last, std::make_pair(type, id),
+                               less_than_type_and_id);
+  if (iter != last && (*iter)->type == type && (!id || id == (*iter)->id)) {
     return iter->get();
   }
   return nullptr;
 }
 
-ResourceTableType* ResourceTablePackage::FindOrCreateType(ResourceType type) {
+ResourceTableType* ResourceTablePackage::FindOrCreateType(ResourceType type,
+                                                          const Maybe<uint8_t> id) {
   const auto last = types.end();
-  auto iter = std::lower_bound(types.begin(), last, type, less_than_type);
-  if (iter != last && (*iter)->type == type) {
+  auto iter = std::lower_bound(types.begin(), last, std::make_pair(type, id),
+                               less_than_type_and_id);
+  if (iter != last && (*iter)->type == type && (!id || id == (*iter)->id)) {
     return iter->get();
   }
-  return types.emplace(iter, new ResourceTableType(type))->get();
+
+  auto new_type = new ResourceTableType(type);
+  new_type->id = id;
+  return types.emplace(iter, std::move(new_type))->get();
 }
 
-ResourceEntry* ResourceTableType::FindEntry(const StringPiece& name) {
+ResourceEntry* ResourceTableType::FindEntry(const StringPiece& name, const Maybe<uint8_t> id) {
   const auto last = entries.end();
-  auto iter =
-      std::lower_bound(entries.begin(), last, name, less_than_struct_with_name<ResourceEntry>);
-  if (iter != last && name == (*iter)->name) {
+  auto iter = std::lower_bound(entries.begin(), last, std::make_pair(name, id),
+      less_than_struct_with_name_and_id<ResourceEntry>);
+  if (iter != last && name == (*iter)->name && (!id || id == (*iter)->id)) {
     return iter->get();
   }
   return nullptr;
 }
 
-ResourceEntry* ResourceTableType::FindOrCreateEntry(const StringPiece& name) {
+ResourceEntry* ResourceTableType::FindOrCreateEntry(const StringPiece& name,
+                                                    const Maybe<uint8_t> id) {
   auto last = entries.end();
-  auto iter =
-      std::lower_bound(entries.begin(), last, name, less_than_struct_with_name<ResourceEntry>);
-  if (iter != last && name == (*iter)->name) {
+  auto iter = std::lower_bound(entries.begin(), last, std::make_pair(name, id),
+                               less_than_struct_with_name_and_id<ResourceEntry>);
+  if (iter != last && name == (*iter)->name && (!id || id == (*iter)->id)) {
     return iter->get();
   }
-  return entries.emplace(iter, new ResourceEntry(name))->get();
+
+  auto new_entry = new ResourceEntry(name);
+  new_entry->id = id;
+  return entries.emplace(iter, std::move(new_entry))->get();
 }
 
 ResourceConfigValue* ResourceEntry::FindValue(const ConfigDescription& config) {
@@ -302,9 +314,15 @@
     // Keep the existing attribute.
     return CollisionResult::kKeepOriginal;
   }
+
   return CollisionResult::kConflict;
 }
 
+ResourceTable::CollisionResult ResourceTable::IgnoreCollision(Value* /** existing **/,
+                                                              Value* /** incoming **/) {
+  return CollisionResult::kKeepBoth;
+}
+
 static StringPiece ResourceNameValidator(const StringPiece& name) {
   if (!IsValidResourceEntryName(name)) {
     return name;
@@ -321,15 +339,17 @@
                                 const StringPiece& product,
                                 std::unique_ptr<Value> value,
                                 IDiagnostics* diag) {
-  return AddResourceImpl(name, {}, config, product, std::move(value), ResourceNameValidator,
-                         ResolveValueCollision, diag);
+  return AddResourceImpl(name, ResourceId{}, config, product, std::move(value),
+                         (validate_resources_ ? ResourceNameValidator : SkipNameValidator),
+                         (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
 }
 
 bool ResourceTable::AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id,
                                       const ConfigDescription& config, const StringPiece& product,
                                       std::unique_ptr<Value> value, IDiagnostics* diag) {
-  return AddResourceImpl(name, res_id, config, product, std::move(value), ResourceNameValidator,
-                         ResolveValueCollision, diag);
+  return AddResourceImpl(name, res_id, config, product, std::move(value),
+                         (validate_resources_ ? ResourceNameValidator : SkipNameValidator),
+                         (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
 }
 
 bool ResourceTable::AddFileReference(const ResourceNameRef& name,
@@ -337,14 +357,18 @@
                                      const Source& source,
                                      const StringPiece& path,
                                      IDiagnostics* diag) {
-  return AddFileReferenceImpl(name, config, source, path, nullptr, ResourceNameValidator, diag);
+  return AddFileReferenceImpl(name, config, source, path, nullptr,
+                              (validate_resources_ ? ResourceNameValidator : SkipNameValidator),
+                              diag);
 }
 
 bool ResourceTable::AddFileReferenceMangled(const ResourceNameRef& name,
                                             const ConfigDescription& config, const Source& source,
                                             const StringPiece& path, io::IFile* file,
                                             IDiagnostics* diag) {
-  return AddFileReferenceImpl(name, config, source, path, file, SkipNameValidator, diag);
+  return AddFileReferenceImpl(name, config, source, path, file,
+                              (validate_resources_ ? ResourceNameValidator : SkipNameValidator),
+                              diag);
 }
 
 bool ResourceTable::AddFileReferenceImpl(const ResourceNameRef& name,
@@ -363,7 +387,7 @@
                                        const StringPiece& product, std::unique_ptr<Value> value,
                                        IDiagnostics* diag) {
   return AddResourceImpl(name, ResourceId{}, config, product, std::move(value), SkipNameValidator,
-                         ResolveValueCollision, diag);
+                         (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
 }
 
 bool ResourceTable::AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id,
@@ -371,7 +395,7 @@
                                              const StringPiece& product,
                                              std::unique_ptr<Value> value, IDiagnostics* diag) {
   return AddResourceImpl(name, id, config, product, std::move(value), SkipNameValidator,
-                         ResolveValueCollision, diag);
+                         (validate_resources_ ? ResolveValueCollision : IgnoreCollision), diag);
 }
 
 bool ResourceTable::ValidateName(NameValidator name_validator, const ResourceNameRef& name,
@@ -398,37 +422,57 @@
     return false;
   }
 
+  // Check for package names appearing twice with two different package ids
   ResourceTablePackage* package = FindOrCreatePackage(name.package);
   if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) {
-    diag->Error(DiagMessage(source) << "trying to add resource '" << name << "' with ID " << res_id
-                                    << " but package '" << package->name << "' already has ID "
-                                    << StringPrintf("%02x", package->id.value()));
+    diag->Error(DiagMessage(source)
+                    << "trying to add resource '" << name << "' with ID " << res_id
+                    << " but package '" << package->name << "' already has ID "
+                    << StringPrintf("%02x", package->id.value()));
     return false;
   }
 
-  ResourceTableType* type = package->FindOrCreateType(name.type);
-  if (res_id.is_valid_dynamic() && type->id && type->id.value() != res_id.type_id()) {
+  // Whether or not to error on duplicate resources
+  bool check_id = validate_resources_ && res_id.is_valid_dynamic();
+  // Whether or not to create a duplicate resource if the id does not match
+  bool use_id = !validate_resources_ && res_id.is_valid_dynamic();
+
+  ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
+                                                                        : Maybe<uint8_t>());
+
+  // Check for types appearing twice with two different type ids
+  if (check_id && type->id && type->id.value() != res_id.type_id()) {
     diag->Error(DiagMessage(source)
-                << "trying to add resource '" << name << "' with ID " << res_id << " but type '"
-                << type->type << "' already has ID " << StringPrintf("%02x", type->id.value()));
+                    << "trying to add resource '" << name << "' with ID " << res_id
+                    << " but type '" << type->type << "' already has ID "
+                    << StringPrintf("%02x", type->id.value()));
     return false;
   }
 
-  ResourceEntry* entry = type->FindOrCreateEntry(name.entry);
-  if (res_id.is_valid_dynamic() && entry->id && entry->id.value() != res_id.entry_id()) {
+  ResourceEntry* entry = type->FindOrCreateEntry(name.entry, use_id ? res_id.entry_id()
+                                                                    : Maybe<uint8_t>());
+
+  // Check for entries appearing twice with two different entry ids
+  if (check_id && entry->id && entry->id.value() != res_id.entry_id()) {
     diag->Error(DiagMessage(source)
-                << "trying to add resource '" << name << "' with ID " << res_id
-                << " but resource already has ID "
-                << ResourceId(package->id.value(), type->id.value(), entry->id.value()));
+                    << "trying to add resource '" << name << "' with ID " << res_id
+                    << " but resource already has ID "
+                    << ResourceId(package->id.value(), type->id.value(), entry->id.value()));
     return false;
   }
 
   ResourceConfigValue* config_value = entry->FindOrCreateValue(config, product);
-  if (config_value->value == nullptr) {
+  if (!config_value->value) {
     // Resource does not exist, add it now.
     config_value->value = std::move(value);
   } else {
     switch (conflict_resolver(config_value->value.get(), value.get())) {
+      case CollisionResult::kKeepBoth:
+        // Insert the value ignoring for duplicate configurations
+        entry->values.push_back(util::make_unique<ResourceConfigValue>(config, product));
+        entry->values.back()->value = std::move(value);
+        break;
+
       case CollisionResult::kTakeNew:
         // Take the incoming value.
         config_value->value = std::move(value);
@@ -450,17 +494,22 @@
     type->id = res_id.type_id();
     entry->id = res_id.entry_id();
   }
+
   return true;
 }
 
+bool ResourceTable::GetValidateResources() {
+  return validate_resources_;
+}
+
 bool ResourceTable::SetVisibility(const ResourceNameRef& name, const Visibility& visibility,
                                   IDiagnostics* diag) {
-  return SetVisibilityImpl(name, visibility, ResourceId{}, ResourceNameValidator, diag);
+  return SetVisibilityImpl(name, visibility, {}, ResourceNameValidator, diag);
 }
 
 bool ResourceTable::SetVisibilityMangled(const ResourceNameRef& name, const Visibility& visibility,
                                          IDiagnostics* diag) {
-  return SetVisibilityImpl(name, visibility, ResourceId{}, SkipNameValidator, diag);
+  return SetVisibilityImpl(name, visibility, {}, SkipNameValidator, diag);
 }
 
 bool ResourceTable::SetVisibilityWithId(const ResourceNameRef& name, const Visibility& visibility,
@@ -484,28 +533,42 @@
     return false;
   }
 
+  // Check for package names appearing twice with two different package ids
   ResourceTablePackage* package = FindOrCreatePackage(name.package);
   if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) {
-    diag->Error(DiagMessage(source) << "trying to add resource '" << name << "' with ID " << res_id
-                                    << " but package '" << package->name << "' already has ID "
-                                    << StringPrintf("%02x", package->id.value()));
+    diag->Error(DiagMessage(source)
+                    << "trying to add resource '" << name << "' with ID " << res_id
+                    << " but package '" << package->name << "' already has ID "
+                    << StringPrintf("%02x", package->id.value()));
     return false;
   }
 
-  ResourceTableType* type = package->FindOrCreateType(name.type);
-  if (res_id.is_valid_dynamic() && type->id && type->id.value() != res_id.type_id()) {
+  // Whether or not to error on duplicate resources
+  bool check_id = validate_resources_ && res_id.is_valid_dynamic();
+  // Whether or not to create a duplicate resource if the id does not match
+  bool use_id = !validate_resources_ && res_id.is_valid_dynamic();
+
+  ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
+                                                                        : Maybe<uint8_t>());
+
+  // Check for types appearing twice with two different type ids
+  if (check_id && type->id && type->id.value() != res_id.type_id()) {
     diag->Error(DiagMessage(source)
-                << "trying to add resource '" << name << "' with ID " << res_id << " but type '"
-                << type->type << "' already has ID " << StringPrintf("%02x", type->id.value()));
+                    << "trying to add resource '" << name << "' with ID " << res_id
+                    << " but type '" << type->type << "' already has ID "
+                    << StringPrintf("%02x", type->id.value()));
     return false;
   }
 
-  ResourceEntry* entry = type->FindOrCreateEntry(name.entry);
-  if (res_id.is_valid_dynamic() && entry->id && entry->id.value() != res_id.entry_id()) {
+  ResourceEntry* entry = type->FindOrCreateEntry(name.entry, use_id ? res_id.entry_id()
+                                                                    : Maybe<uint8_t>());
+
+  // Check for entries appearing twice with two different entry ids
+  if (check_id && entry->id && entry->id.value() != res_id.entry_id()) {
     diag->Error(DiagMessage(source)
-                << "trying to add resource '" << name << "' with ID " << res_id
-                << " but resource already has ID "
-                << ResourceId(package->id.value(), type->id.value(), entry->id.value()));
+                    << "trying to add resource '" << name << "' with ID " << res_id
+                    << " but resource already has ID "
+                    << ResourceId(package->id.value(), type->id.value(), entry->id.value()));
     return false;
   }
 
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 8534eaa..c40323c 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -146,8 +146,9 @@
 
   explicit ResourceTableType(const ResourceType type) : type(type) {}
 
-  ResourceEntry* FindEntry(const android::StringPiece& name);
-  ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
+  ResourceEntry* FindEntry(const android::StringPiece& name, Maybe<uint8_t> id = Maybe<uint8_t>());
+  ResourceEntry* FindOrCreateEntry(const android::StringPiece& name,
+                                   Maybe<uint8_t> id = Maybe<uint8_t>());
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
@@ -163,8 +164,9 @@
   std::vector<std::unique_ptr<ResourceTableType>> types;
 
   ResourceTablePackage() = default;
-  ResourceTableType* FindType(ResourceType type);
-  ResourceTableType* FindOrCreateType(const ResourceType type);
+  ResourceTableType* FindType(ResourceType type, Maybe<uint8_t> id = Maybe<uint8_t>());
+  ResourceTableType* FindOrCreateType(const ResourceType type,
+                                      Maybe<uint8_t> id = Maybe<uint8_t>());
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
@@ -174,14 +176,18 @@
 class ResourceTable {
  public:
   ResourceTable() = default;
+  explicit ResourceTable(bool validate_resources) : validate_resources_(validate_resources) {}
 
-  enum class CollisionResult { kKeepOriginal, kConflict, kTakeNew };
+  enum class CollisionResult { kKeepBoth, kKeepOriginal, kConflict, kTakeNew };
 
   using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*)>;
 
   // When a collision of resources occurs, this method decides which value to keep.
   static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
 
+  // When a collision of resources occurs, this method keeps both values
+  static CollisionResult IgnoreCollision(Value* existing, Value* incoming);
+
   bool AddResource(const ResourceNameRef& name, const ConfigDescription& config,
                    const android::StringPiece& product, std::unique_ptr<Value> value,
                    IDiagnostics* diag);
@@ -208,6 +214,8 @@
                                 const android::StringPiece& product, std::unique_ptr<Value> value,
                                 IDiagnostics* diag);
 
+  bool GetValidateResources();
+
   bool SetVisibility(const ResourceNameRef& name, const Visibility& visibility, IDiagnostics* diag);
   bool SetVisibilityMangled(const ResourceNameRef& name, const Visibility& visibility,
                             IDiagnostics* diag);
@@ -299,6 +307,9 @@
                           const Visibility& symbol, NameValidator name_validator,
                           IDiagnostics* diag);
 
+  // Controls whether the table validates resource names and prevents duplicate resource names
+  bool validate_resources_ = true;
+
   DISALLOW_COPY_AND_ASSIGN(ResourceTable);
 };
 
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 8ebde75..f4b0124 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -25,8 +25,8 @@
 
 namespace aapt {
 
-static const char* sDevelopmentSdkCodeName = "P";
-static ApiVersion sDevelopmentSdkLevel = 28;
+static const char* sDevelopmentSdkCodeName = "Q";
+static ApiVersion sDevelopmentSdkLevel = 10000;
 
 static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
     {0x021c, 1},
@@ -54,6 +54,7 @@
     {0x0530, SDK_NOUGAT_MR1},
     {0x0568, SDK_O},
     {0x056d, SDK_O_MR1},
+    {0x0586, SDK_P},
 };
 
 static bool less_entry_id(const std::pair<uint16_t, ApiVersion>& p, uint16_t entryId) {
diff --git a/tools/aapt2/Source.h b/tools/aapt2/Source.h
index 0f312d6..92934c3 100644
--- a/tools/aapt2/Source.h
+++ b/tools/aapt2/Source.h
@@ -31,12 +31,16 @@
 struct Source {
   std::string path;
   Maybe<size_t> line;
+  Maybe<std::string> archive;
 
   Source() = default;
 
   inline Source(const android::StringPiece& path) : path(path.to_string()) {  // NOLINT(implicit)
   }
 
+  inline Source(const android::StringPiece& path, const android::StringPiece& archive)
+      : path(path.to_string()), archive(archive.to_string()) {}
+
   inline Source(const android::StringPiece& path, size_t line)
       : path(path.to_string()), line(line) {}
 
@@ -45,10 +49,14 @@
   }
 
   std::string to_string() const {
-    if (line) {
-      return ::android::base::StringPrintf("%s:%zd", path.c_str(), line.value());
+    std::string s = path;
+    if (archive) {
+      s = ::android::base::StringPrintf("%s@%s", archive.value().c_str(), s.c_str());
     }
-    return path;
+    if (line) {
+      s = ::android::base::StringPrintf("%s:%zd", s.c_str(), line.value());
+    }
+    return s;
   }
 };
 
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
index b37e1fb..8eabd32 100644
--- a/tools/aapt2/StringPool.cpp
+++ b/tools/aapt2/StringPool.cpp
@@ -367,7 +367,7 @@
 static bool EncodeString(const std::string& str, const bool utf8, BigBuffer* out,
                          IDiagnostics* diag) {
   if (utf8) {
-    const std::string& encoded = str;
+    const std::string& encoded = util::Utf8ToModifiedUtf8(str);
     const ssize_t utf16_length = utf8_to_utf16_length(
         reinterpret_cast<const uint8_t*>(encoded.data()), encoded.size());
     CHECK(utf16_length >= 0);
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index 4b3afe2..0778564 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -303,6 +303,25 @@
   }
 }
 
+TEST(StringPoolTest, FlattenModifiedUTF8) {
+  using namespace android;  // For NO_ERROR on Windows.
+  StdErrDiagnostics diag;
+  StringPool pool;
+  StringPool::Ref ref_a = pool.MakeRef("\xF0\x90\x90\x80"); // 𐐀 (U+10400)
+  StringPool::Ref ref_b = pool.MakeRef("foo \xF0\x90\x90\xB7 bar"); // 𐐷 (U+10437)
+  StringPool::Ref ref_c = pool.MakeRef("\xF0\x90\x90\x80\xF0\x90\x90\xB7");
+
+  BigBuffer buffer(1024);
+  StringPool::FlattenUtf8(&buffer, pool, &diag);
+  std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
+
+  // Check that the 4 byte utf-8 codepoint is encoded using 2 3 byte surrogate pairs
+  ResStringPool test;
+  ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
+  EXPECT_THAT(util::GetString(test, 0), Eq("\xED\xA0\x81\xED\xB0\x80"));
+  EXPECT_THAT(util::GetString(test, 1), Eq("foo \xED\xA0\x81\xED\xB0\xB7 bar"));
+  EXPECT_THAT(util::GetString(test, 2), Eq("\xED\xA0\x81\xED\xB0\x80\xED\xA0\x81\xED\xB0\xB7"));
+}
 
 TEST(StringPoolTest, MaxEncodingLength) {
   StdErrDiagnostics diag;
diff --git a/tools/aapt2/cmd/Command.cpp b/tools/aapt2/cmd/Command.cpp
new file mode 100644
index 0000000..09411b9
--- /dev/null
+++ b/tools/aapt2/cmd/Command.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Command.h"
+
+#include <iomanip>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "androidfw/StringPiece.h"
+
+#include "util/Util.h"
+
+using android::StringPiece;
+
+namespace aapt {
+
+void Command::AddRequiredFlag(const StringPiece& name,
+    const StringPiece& description, std::string* value) {
+  auto func = [value](const StringPiece& arg) -> bool {
+    *value = arg.to_string();
+    return true;
+  };
+
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
+}
+
+void Command::AddRequiredFlagList(const StringPiece& name,
+    const StringPiece& description,
+    std::vector<std::string>* value) {
+  auto func = [value](const StringPiece& arg) -> bool {
+    value->push_back(arg.to_string());
+    return true;
+  };
+
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
+}
+
+void Command::AddOptionalFlag(const StringPiece& name,
+    const StringPiece& description,
+    Maybe<std::string>* value) {
+  auto func = [value](const StringPiece& arg) -> bool {
+    *value = arg.to_string();
+    return true;
+  };
+
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
+}
+
+void Command::AddOptionalFlagList(const StringPiece& name,
+    const StringPiece& description,
+    std::vector<std::string>* value) {
+  auto func = [value](const StringPiece& arg) -> bool {
+    value->push_back(arg.to_string());
+    return true;
+  };
+
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
+}
+
+void Command::AddOptionalFlagList(const StringPiece& name,
+    const StringPiece& description,
+    std::unordered_set<std::string>* value) {
+  auto func = [value](const StringPiece& arg) -> bool {
+    value->insert(arg.to_string());
+    return true;
+  };
+
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
+}
+
+void Command::AddOptionalSwitch(const StringPiece& name,
+    const StringPiece& description, bool* value) {
+  auto func = [value](const StringPiece& arg) -> bool {
+    *value = true;
+    return true;
+  };
+
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 0, false});
+}
+
+void Command::AddOptionalSubcommand(std::unique_ptr<Command>&& subcommand) {
+  subcommand->fullname_ = name_ + " " + subcommand->name_;
+  subcommands_.push_back(std::move(subcommand));
+}
+
+void Command::SetDescription(const android::StringPiece& description) {
+  description_ = description.to_string();
+}
+
+void Command::Usage(std::ostream* out) {
+  constexpr size_t kWidth = 50;
+
+  *out << fullname_;
+
+  if (!subcommands_.empty()) {
+    *out << " [subcommand]";
+  }
+
+  *out << " [options]";
+  for (const Flag& flag : flags_) {
+    if (flag.required) {
+      *out << " " << flag.name << " arg";
+    }
+  }
+
+  *out << " files...\n";
+
+  if (!subcommands_.empty()) {
+    *out << "\nSubcommands:\n";
+    for (auto& subcommand : subcommands_) {
+      std::string argline = subcommand->name_;
+
+      // Split the description by newlines and write out the argument (which is
+      // empty after the first line) followed by the description line. This will make sure
+      // that multiline descriptions are still right justified and aligned.
+      for (StringPiece line : util::Tokenize(subcommand->description_, '\n')) {
+        *out << " " << std::setw(kWidth) << std::left << argline << line << "\n";
+        argline = " ";
+      }
+    }
+  }
+
+  *out << "\nOptions:\n";
+
+  for (const Flag& flag : flags_) {
+    std::string argline = flag.name;
+    if (flag.num_args > 0) {
+      argline += " arg";
+    }
+
+    // Split the description by newlines and write out the argument (which is
+    // empty after the first line) followed by the description line. This will make sure
+    // that multiline descriptions are still right justified and aligned.
+    for (StringPiece line : util::Tokenize(flag.description, '\n')) {
+      *out << " " << std::setw(kWidth) << std::left << argline << line << "\n";
+      argline = " ";
+    }
+  }
+  *out << " " << std::setw(kWidth) << std::left << "-h"
+       << "Displays this help menu\n";
+  out->flush();
+}
+
+int Command::Execute(const std::vector<android::StringPiece>& args, std::ostream* out_error) {
+  std::vector<std::string> file_args;
+
+  for (size_t i = 0; i < args.size(); i++) {
+    StringPiece arg = args[i];
+    if (*(arg.data()) != '-') {
+      // Continue parsing as the sub command if the first argument matches one of the subcommands
+      if (i == 0) {
+        for (auto& subcommand : subcommands_) {
+          if (arg == subcommand->name_ || arg==subcommand->short_name_) {
+            return subcommand->Execute(
+                std::vector<android::StringPiece>(args.begin() + 1, args.end()), out_error);
+          }
+        }
+      }
+
+      file_args.push_back(arg.to_string());
+      continue;
+    }
+
+    if (arg == "-h" || arg == "--help") {
+      Usage(out_error);
+      return 1;
+    }
+
+    bool match = false;
+    for (Flag& flag : flags_) {
+      if (arg == flag.name) {
+        if (flag.num_args > 0) {
+          i++;
+          if (i >= args.size()) {
+            *out_error << flag.name << " missing argument.\n\n";
+            Usage(out_error);
+            return false;
+          }
+          flag.action(args[i]);
+        } else {
+          flag.action({});
+        }
+        flag.parsed = true;
+        match = true;
+        break;
+      }
+    }
+
+    if (!match) {
+      *out_error << "unknown option '" << arg << "'.\n\n";
+      Usage(out_error);
+      return 1;
+    }
+  }
+
+  for (const Flag& flag : flags_) {
+    if (flag.required && !flag.parsed) {
+      *out_error << "missing required flag " << flag.name << "\n\n";
+      Usage(out_error);
+      return 1;
+    }
+  }
+
+  return Action(file_args);
+}
+
+}  // namespace aapt
diff --git a/tools/aapt2/cmd/Command.h b/tools/aapt2/cmd/Command.h
new file mode 100644
index 0000000..71dc6fe
--- /dev/null
+++ b/tools/aapt2/cmd/Command.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_COMMAND_H
+#define AAPT_COMMAND_H
+
+#include <functional>
+#include <ostream>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include "androidfw/StringPiece.h"
+
+#include "util/Maybe.h"
+
+namespace aapt {
+
+class Command {
+ public:
+  explicit Command(const android::StringPiece& name) : name_(name.to_string()),
+                                                       fullname_(name.to_string()) { }
+  explicit Command(const android::StringPiece& name, const android::StringPiece& short_name)
+      : name_(name.to_string()), short_name_(short_name.to_string()), fullname_(name.to_string()) {}
+  virtual ~Command() = default;
+
+  void AddRequiredFlag(const android::StringPiece& name, const android::StringPiece& description,
+      std::string* value);
+  void AddRequiredFlagList(const android::StringPiece& name, const android::StringPiece&
+      description, std::vector<std::string>* value);
+  void AddOptionalFlag(const android::StringPiece& name, const android::StringPiece& description,
+      Maybe<std::string>* value);
+  void AddOptionalFlagList(const android::StringPiece& name,
+      const android::StringPiece& description, std::vector<std::string>* value);
+  void AddOptionalFlagList(const android::StringPiece& name,
+      const android::StringPiece& description, std::unordered_set<std::string>* value);
+  void AddOptionalSwitch(const android::StringPiece& name, const android::StringPiece& description,
+      bool* value);
+  void AddOptionalSubcommand(std::unique_ptr<Command>&& subcommand);
+
+  void SetDescription(const android::StringPiece& name);
+
+  /** Prints the help menu of the command. */
+  void Usage(std::ostream* out);
+
+  /**
+   * Parses the command line arguments, sets the flag variable values, and runs the action of
+   * the command. If the arguments fail to parse to the command and its subcommands, then the action
+   * will not be run and the usage will be printed instead.
+   **/
+  int Execute(const std::vector<android::StringPiece>& args, std::ostream* outError);
+
+  /** The action to preform when the command is executed. */
+  virtual int Action(const std::vector<std::string>& args) = 0;
+
+ private:
+  struct Flag {
+    std::string name;
+    std::string description;
+    std::function<bool(const android::StringPiece& value)> action;
+    bool required;
+    size_t num_args;
+
+    bool parsed;
+  };
+
+  std::string description_;
+  std::string name_;
+  std::string short_name_;
+  std::string fullname_;
+  std::vector<Flag> flags_;
+  std::vector<std::unique_ptr<Command>> subcommands_;
+};
+
+}  // namespace aapt
+
+#endif  // AAPT_COMMAND_H
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index a17a0d3..62c19fb 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#include <dirent.h>
+#include "Compile.h"
 
+#include <dirent.h>
 #include <string>
 
 #include "android-base/errors.h"
@@ -27,7 +28,6 @@
 
 #include "ConfigDescription.h"
 #include "Diagnostics.h"
-#include "Flags.h"
 #include "ResourceParser.h"
 #include "ResourceTable.h"
 #include "cmd/Util.h"
@@ -41,8 +41,10 @@
 #include "format/proto/ProtoSerialize.h"
 #include "io/BigBufferStream.h"
 #include "io/FileStream.h"
+#include "io/FileSystem.h"
 #include "io/StringStream.h"
 #include "io/Util.h"
+#include "io/ZipArchive.h"
 #include "util/Files.h"
 #include "util/Maybe.h"
 #include "util/Util.h"
@@ -121,17 +123,6 @@
                           extension.to_string(), config_str.to_string(), config};
 }
 
-struct CompileOptions {
-  std::string output_path;
-  Maybe<std::string> res_dir;
-  Maybe<std::string> generate_text_symbols_path;
-  Maybe<Visibility::Level> visibility;
-  bool pseudolocalize = false;
-  bool no_png_crunch = false;
-  bool legacy_mode = false;
-  bool verbose = false;
-};
-
 static std::string BuildIntermediateContainerFilename(const ResourcePathData& data) {
   std::stringstream name;
   name << data.resource_dir;
@@ -146,81 +137,20 @@
   return name.str();
 }
 
-static bool IsHidden(const StringPiece& filename) {
-  return util::StartsWith(filename, ".");
-}
-
-// Walks the res directory structure, looking for resource files.
-static bool LoadInputFilesFromDir(IAaptContext* context, const CompileOptions& options,
-                                  std::vector<ResourcePathData>* out_path_data) {
-  const std::string& root_dir = options.res_dir.value();
-  std::unique_ptr<DIR, decltype(closedir)*> d(opendir(root_dir.data()), closedir);
-  if (!d) {
-    context->GetDiagnostics()->Error(DiagMessage(root_dir) << "failed to open directory: "
-                                                           << SystemErrorCodeToString(errno));
-    return false;
-  }
-
-  while (struct dirent* entry = readdir(d.get())) {
-    if (IsHidden(entry->d_name)) {
-      continue;
-    }
-
-    std::string prefix_path = root_dir;
-    file::AppendPath(&prefix_path, entry->d_name);
-
-    if (file::GetFileType(prefix_path) != file::FileType::kDirectory) {
-      continue;
-    }
-
-    std::unique_ptr<DIR, decltype(closedir)*> subdir(opendir(prefix_path.data()), closedir);
-    if (!subdir) {
-      context->GetDiagnostics()->Error(DiagMessage(prefix_path) << "failed to open directory: "
-                                                                << SystemErrorCodeToString(errno));
-      return false;
-    }
-
-    while (struct dirent* leaf_entry = readdir(subdir.get())) {
-      if (IsHidden(leaf_entry->d_name)) {
-        continue;
-      }
-
-      std::string full_path = prefix_path;
-      file::AppendPath(&full_path, leaf_entry->d_name);
-
-      std::string err_str;
-      Maybe<ResourcePathData> path_data = ExtractResourcePathData(full_path, &err_str);
-      if (!path_data) {
-        context->GetDiagnostics()->Error(DiagMessage(full_path) << err_str);
-        return false;
-      }
-
-      out_path_data->push_back(std::move(path_data.value()));
-    }
-  }
-
-  // File-system directory enumeration order is platform-dependent. Sort the result to remove any
-  // inconsistencies between platforms.
-  std::sort(
-      out_path_data->begin(), out_path_data->end(),
-      [](const ResourcePathData& a, const ResourcePathData& b) { return a.source < b.source; });
-  return true;
-}
-
 static bool CompileTable(IAaptContext* context, const CompileOptions& options,
-                         const ResourcePathData& path_data, IArchiveWriter* writer,
+                         const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                          const std::string& output_path) {
   ResourceTable table;
   {
-    FileInputStream fin(path_data.source.path);
-    if (fin.HadError()) {
+    auto fin = file->OpenInputStream();
+    if (fin->HadError()) {
       context->GetDiagnostics()->Error(DiagMessage(path_data.source)
-                                       << "failed to open file: " << fin.GetError());
+          << "failed to open file: " << fin->GetError());
       return false;
     }
 
     // Parse the values file from XML.
-    xml::XmlPullParser xml_parser(&fin);
+    xml::XmlPullParser xml_parser(fin.get());
 
     ResourceParserOptions parser_options;
     parser_options.error_on_positional_arguments = !options.legacy_mode;
@@ -233,7 +163,7 @@
     parser_options.visibility = options.visibility;
 
     ResourceParser res_parser(context->GetDiagnostics(), &table, path_data.source, path_data.config,
-                              parser_options);
+        parser_options);
     if (!res_parser.Parse(&xml_parser)) {
       return false;
     }
@@ -299,44 +229,48 @@
 
     Printer r_txt_printer(&fout_text);
     for (const auto& package : table.packages) {
-      for (const auto& type : package->types) {
-        for (const auto& entry : type->entries) {
-          // Check access modifiers.
-          switch(entry->visibility.level) {
-            case Visibility::Level::kUndefined :
-              r_txt_printer.Print("default ");
-              break;
-            case Visibility::Level::kPublic :
-              r_txt_printer.Print("public ");
-              break;
-            case Visibility::Level::kPrivate :
-              r_txt_printer.Print("private ");
-          }
+      // Only print resources defined locally, e.g. don't write android attributes.
+      if (package->name.empty()) {
+        for (const auto& type : package->types) {
+          for (const auto& entry : type->entries) {
+            // Check access modifiers.
+            switch (entry->visibility.level) {
+              case Visibility::Level::kUndefined :
+                r_txt_printer.Print("default ");
+                break;
+              case Visibility::Level::kPublic :
+                r_txt_printer.Print("public ");
+                break;
+              case Visibility::Level::kPrivate :
+                r_txt_printer.Print("private ");
+            }
 
-          if (type->type != ResourceType::kStyleable) {
-            r_txt_printer.Print("int ");
-            r_txt_printer.Print(to_string(type->type));
-            r_txt_printer.Print(" ");
-            r_txt_printer.Println(entry->name);
-          } else {
-            r_txt_printer.Print("int[] styleable ");
-            r_txt_printer.Println(entry->name);
+            if (type->type != ResourceType::kStyleable) {
+              r_txt_printer.Print("int ");
+              r_txt_printer.Print(to_string(type->type));
+              r_txt_printer.Print(" ");
+              r_txt_printer.Println(entry->name);
+            } else {
+              r_txt_printer.Print("int[] styleable ");
+              r_txt_printer.Println(entry->name);
 
-            if (!entry->values.empty()) {
-              auto styleable = static_cast<const Styleable*>(entry->values.front()->value.get());
-              for (const auto& attr : styleable->entries) {
-                // The visibility of the children under the styleable does not matter as they are
-                // nested under their parent and use its visibility.
-                r_txt_printer.Print("default int styleable ");
-                r_txt_printer.Print(entry->name);
-                // If the package name is present, also include it in the mangled name (e.g.
-                // "android")
-                if (!attr.name.value().package.empty()) {
+              if (!entry->values.empty()) {
+                auto styleable =
+                    static_cast<const Styleable*>(entry->values.front()->value.get());
+                for (const auto& attr : styleable->entries) {
+                  // The visibility of the children under the styleable does not matter as they are
+                  // nested under their parent and use its visibility.
+                  r_txt_printer.Print("default int styleable ");
+                  r_txt_printer.Print(entry->name);
+                  // If the package name is present, also include it in the mangled name (e.g.
+                  // "android")
+                  if (!attr.name.value().package.empty()) {
+                    r_txt_printer.Print("_");
+                    r_txt_printer.Print(MakePackageSafeName(attr.name.value().package));
+                  }
                   r_txt_printer.Print("_");
-                  r_txt_printer.Print(MakePackageSafeName(attr.name.value().package));
+                  r_txt_printer.Println(attr.name.value().entry);
                 }
-                r_txt_printer.Print("_");
-                r_txt_printer.Println(attr.name.value().entry);
               }
             }
           }
@@ -415,7 +349,7 @@
 }
 
 static bool CompileXml(IAaptContext* context, const CompileOptions& options,
-                       const ResourcePathData& path_data, IArchiveWriter* writer,
+                       const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                        const std::string& output_path) {
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling XML");
@@ -423,18 +357,17 @@
 
   std::unique_ptr<xml::XmlResource> xmlres;
   {
-    FileInputStream fin(path_data.source.path);
-    if (fin.HadError()) {
+    auto fin = file->OpenInputStream();
+    if (fin->HadError()) {
       context->GetDiagnostics()->Error(DiagMessage(path_data.source)
-                                       << "failed to open file: " << fin.GetError());
+                                       << "failed to open file: " << fin->GetError());
       return false;
     }
 
-    xmlres = xml::Inflate(&fin, context->GetDiagnostics(), path_data.source);
-  }
-
-  if (!xmlres) {
-    return false;
+    xmlres = xml::Inflate(fin.get(), context->GetDiagnostics(), path_data.source);
+    if (!xmlres) {
+      return false;
+    }
   }
 
   xmlres->file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir), path_data.name);
@@ -515,7 +448,7 @@
 }
 
 static bool CompilePng(IAaptContext* context, const CompileOptions& options,
-                       const ResourcePathData& path_data, IArchiveWriter* writer,
+                       const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                        const std::string& output_path) {
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling PNG");
@@ -529,15 +462,17 @@
   res_file.type = ResourceFile::Type::kPng;
 
   {
-    std::string content;
-    if (!android::base::ReadFileToString(path_data.source.path, &content,
-                                         true /*follow_symlinks*/)) {
-      context->GetDiagnostics()->Error(DiagMessage(path_data.source)
-                                       << "failed to open file: "
-                                       << SystemErrorCodeToString(errno));
+    auto data = file->OpenAsData();
+    if (!data) {
+      context->GetDiagnostics()->Error(DiagMessage(path_data.source) << "failed to open file ");
       return false;
     }
 
+    // Read the file as a string
+    char buffer_2[data->size()];
+    memcpy(&buffer_2, data->data(), data->size());
+    StringPiece content(buffer_2, data->size());
+
     BigBuffer crunched_png_buffer(4096);
     io::BigBufferOutputStream crunched_png_buffer_out(&crunched_png_buffer);
 
@@ -605,7 +540,7 @@
     if (context->IsVerbose()) {
       // For debugging only, use the legacy PNG cruncher and compare the resulting file sizes.
       // This will help catch exotic cases where the new code may generate larger PNGs.
-      std::stringstream legacy_stream(content);
+      std::stringstream legacy_stream(content.to_string());
       BigBuffer legacy_buffer(4096);
       Png png(context->GetDiagnostics());
       if (!png.process(path_data.source, &legacy_stream, &legacy_buffer, {})) {
@@ -619,41 +554,31 @@
   }
 
   io::BigBufferInputStream buffer_in(&buffer);
-  if (!WriteHeaderAndDataToWriter(output_path, res_file, &buffer_in, writer,
-                                  context->GetDiagnostics())) {
-    return false;
-  }
-  return true;
+  return WriteHeaderAndDataToWriter(output_path, res_file, &buffer_in, writer,
+      context->GetDiagnostics());
 }
 
 static bool CompileFile(IAaptContext* context, const CompileOptions& options,
-                        const ResourcePathData& path_data, IArchiveWriter* writer,
+                        const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                         const std::string& output_path) {
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling file");
   }
 
-  BigBuffer buffer(256);
   ResourceFile res_file;
   res_file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir), path_data.name);
   res_file.config = path_data.config;
   res_file.source = path_data.source;
   res_file.type = ResourceFile::Type::kUnknown;
 
-  std::string error_str;
-  Maybe<android::FileMap> f = file::MmapPath(path_data.source.path, &error_str);
-  if (!f) {
-    context->GetDiagnostics()->Error(DiagMessage(path_data.source) << "failed to mmap file: "
-                                     << error_str);
+  auto data = file->OpenAsData();
+  if (!data) {
+    context->GetDiagnostics()->Error(DiagMessage(path_data.source) << "failed to open file ");
     return false;
   }
 
-  io::MmappedData mmapped_in(std::move(f.value()));
-  if (!WriteHeaderAndDataToWriter(output_path, res_file, &mmapped_in, writer,
-                                  context->GetDiagnostics())) {
-    return false;
-  }
-  return true;
+  return WriteHeaderAndDataToWriter(output_path, res_file, data.get(), writer,
+      context->GetDiagnostics());
 }
 
 class CompileContext : public IAaptContext {
@@ -701,10 +626,6 @@
     return 0;
   }
 
-  bool IsAutoNamespace() override {
-    return false;
-  }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(CompileContext);
 
@@ -712,99 +633,33 @@
   bool verbose_ = false;
 };
 
-// Entry point for compilation phase. Parses arguments and dispatches to the correct steps.
-int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
-  CompileContext context(diagnostics);
-  CompileOptions options;
-
-  bool verbose = false;
-  Maybe<std::string> visibility;
-  Flags flags =
-      Flags()
-          .RequiredFlag("-o", "Output path", &options.output_path)
-          .OptionalFlag("--dir", "Directory to scan for resources", &options.res_dir)
-          .OptionalFlag("--output-text-symbols",
-                        "Generates a text file containing the resource symbols in the\n"
-                        "specified file",
-                        &options.generate_text_symbols_path)
-          .OptionalSwitch("--pseudo-localize",
-                          "Generate resources for pseudo-locales "
-                          "(en-XA and ar-XB)",
-                          &options.pseudolocalize)
-          .OptionalSwitch("--no-crunch", "Disables PNG processing", &options.no_png_crunch)
-          .OptionalSwitch("--legacy", "Treat errors that used to be valid in AAPT as warnings",
-                          &options.legacy_mode)
-          .OptionalSwitch("-v", "Enables verbose logging", &verbose)
-          .OptionalFlag("--visibility",
-                        "Sets the visibility of the compiled resources to the specified\n"
-                        "level. Accepted levels: public, private, default",
-                        &visibility);
-  if (!flags.Parse("aapt2 compile", args, &std::cerr)) {
-    return 1;
-  }
-
-  context.SetVerbose(verbose);
-
-  if (visibility) {
-    if (visibility.value() == "public") {
-      options.visibility = Visibility::Level::kPublic;
-    } else if (visibility.value() == "private") {
-      options.visibility = Visibility::Level::kPrivate;
-    } else if (visibility.value() == "default") {
-      options.visibility = Visibility::Level::kUndefined;
-    } else {
-      context.GetDiagnostics()->Error(
-          DiagMessage() << "Unrecognized visibility level passes to --visibility: '"
-                        << visibility.value() << "'. Accepted levels: public, private, default");
-      return 1;
-    }
-  }
-
-  std::unique_ptr<IArchiveWriter> archive_writer;
-
-  std::vector<ResourcePathData> input_data;
-  if (options.res_dir) {
-    if (!flags.GetArgs().empty()) {
-      // Can't have both files and a resource directory.
-      context.GetDiagnostics()->Error(DiagMessage() << "files given but --dir specified");
-      flags.Usage("aapt2 compile", &std::cerr);
-      return 1;
-    }
-
-    if (!LoadInputFilesFromDir(&context, options, &input_data)) {
-      return 1;
-    }
-
-    archive_writer = CreateZipFileArchiveWriter(context.GetDiagnostics(), options.output_path);
-
-  } else {
-    input_data.reserve(flags.GetArgs().size());
-
-    // Collect data from the path for each input file.
-    for (const std::string& arg : flags.GetArgs()) {
-      std::string error_str;
-      if (Maybe<ResourcePathData> path_data = ExtractResourcePathData(arg, &error_str)) {
-        input_data.push_back(std::move(path_data.value()));
-      } else {
-        context.GetDiagnostics()->Error(DiagMessage() << error_str << " (" << arg << ")");
-        return 1;
-      }
-    }
-
-    archive_writer = CreateDirectoryArchiveWriter(context.GetDiagnostics(), options.output_path);
-  }
-
-  if (!archive_writer) {
-    return 1;
-  }
-
+int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer,
+             CompileOptions& options) {
   bool error = false;
-  for (ResourcePathData& path_data : input_data) {
-    if (options.verbose) {
-      context.GetDiagnostics()->Note(DiagMessage(path_data.source) << "processing");
+
+  // Iterate over the input files in a stable, platform-independent manner
+  auto file_iterator  = inputs->Iterator();
+  while (file_iterator->HasNext()) {
+    auto file = file_iterator->Next();
+    std::string path = file->GetSource().path;
+
+    // Skip hidden input files
+    if (file::IsHidden(path)) {
+      continue;
     }
 
-    if (!IsValidFile(&context, path_data.source.path)) {
+    if (!options.res_zip && !IsValidFile(context, path)) {
+      error = true;
+      continue;
+    }
+
+    // Extract resource type information from the full path
+    std::string err_str;
+    ResourcePathData path_data;
+    if (auto maybe_path_data = ExtractResourcePathData(path, &err_str)) {
+      path_data = maybe_path_data.value();
+    } else {
+      context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << err_str);
       error = true;
       continue;
     }
@@ -822,13 +677,13 @@
         if (path_data.extension == "xml") {
           compile_func = &CompileXml;
         } else if ((!options.no_png_crunch && path_data.extension == "png")
-            || path_data.extension == "9.png") {
+                   || path_data.extension == "9.png") {
           compile_func = &CompilePng;
         }
       }
     } else {
-      context.GetDiagnostics()->Error(DiagMessage()
-                                      << "invalid file path '" << path_data.source << "'");
+      context->GetDiagnostics()->Error(DiagMessage()
+          << "invalid file path '" << path_data.source << "'");
       error = true;
       continue;
     }
@@ -838,17 +693,95 @@
     if (compile_func != &CompileFile && !options.legacy_mode
         && std::count(path_data.name.begin(), path_data.name.end(), '.') != 0) {
       error = true;
-      context.GetDiagnostics()->Error(DiagMessage() << "resource file '" << path_data.source.path
-                                                    << "' name cannot contain '.' other than for"
-                                                    << "specifying the extension");
+      context->GetDiagnostics()->Error(DiagMessage(file->GetSource())
+                                                    << "file name cannot contain '.' other than for"
+                                                    << " specifying the extension");
       continue;
     }
 
-    // Compile the file.
     const std::string out_path = BuildIntermediateContainerFilename(path_data);
-    error |= !compile_func(&context, options, path_data, archive_writer.get(), out_path);
+    error |= !compile_func(context, options, path_data, file, output_writer, out_path);
   }
+
   return error ? 1 : 0;
 }
 
+int CompileCommand::Action(const std::vector<std::string>& args) {
+  CompileContext context(diagnostic_);
+  context.SetVerbose(options_.verbose);
+
+  if (visibility_) {
+    if (visibility_.value() == "public") {
+      options_.visibility = Visibility::Level::kPublic;
+    } else if (visibility_.value() == "private") {
+      options_.visibility = Visibility::Level::kPrivate;
+    } else if (visibility_.value() == "default") {
+      options_.visibility = Visibility::Level::kUndefined;
+    } else {
+      context.GetDiagnostics()->Error(
+          DiagMessage() << "Unrecognized visibility level passes to --visibility: '"
+                        << visibility_.value() << "'. Accepted levels: public, private, default");
+      return 1;
+    }
+  }
+
+  std::unique_ptr<io::IFileCollection> file_collection;
+  std::unique_ptr<IArchiveWriter> archive_writer;
+
+  // Collect the resources files to compile
+  if (options_.res_dir && options_.res_zip) {
+    context.GetDiagnostics()->Error(DiagMessage()
+                                        << "only one of --dir and --zip can be specified");
+    return 1;
+  } else if (options_.res_dir) {
+    if (!args.empty()) {
+      context.GetDiagnostics()->Error(DiagMessage() << "files given but --dir specified");
+      Usage(&std::cerr);
+      return 1;
+    }
+
+    // Load the files from the res directory
+    std::string err;
+    file_collection = io::FileCollection::Create(options_.res_dir.value(), &err);
+    if (!file_collection) {
+      context.GetDiagnostics()->Error(DiagMessage(options_.res_dir.value()) << err);
+      return 1;
+    }
+
+    archive_writer = CreateZipFileArchiveWriter(context.GetDiagnostics(), options_.output_path);
+  } else if (options_.res_zip) {
+    if (!args.empty()) {
+      context.GetDiagnostics()->Error(DiagMessage() << "files given but --zip specified");
+      Usage(&std::cerr);
+      return 1;
+    }
+
+    // Load a zip file containing a res directory
+    std::string err;
+    file_collection = io::ZipFileCollection::Create(options_.res_zip.value(), &err);
+    if (!file_collection) {
+      context.GetDiagnostics()->Error(DiagMessage(options_.res_zip.value()) << err);
+      return 1;
+    }
+
+    archive_writer = CreateZipFileArchiveWriter(context.GetDiagnostics(), options_.output_path);
+  } else {
+    auto collection = util::make_unique<io::FileCollection>();
+
+    // Collect data from the path for each input file.
+    for (const std::string& arg : args) {
+      collection->InsertFile(arg);
+    }
+
+    file_collection = std::move(collection);
+    archive_writer = CreateDirectoryArchiveWriter(context.GetDiagnostics(), options_.output_path);
+  }
+
+  if (!archive_writer) {
+    return 1;
+  }
+
+  return Compile(&context, file_collection.get(), archive_writer.get(), options_);
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h
index d95cf1c..c429d5f 100644
--- a/tools/aapt2/cmd/Compile.h
+++ b/tools/aapt2/cmd/Compile.h
@@ -1,14 +1,77 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #ifndef AAPT2_COMPILE_H
 #define AAPT2_COMPILE_H
 
 #include "androidfw/StringPiece.h"
-
+#include "format/Archive.h"
+#include "process/IResourceTableConsumer.h"
+#include "Command.h"
 #include "Diagnostics.h"
+#include "ResourceTable.h"
 
 namespace aapt {
 
-  int Compile(const std::vector<android::StringPiece>& args, IDiagnostics* diagnostics);
+struct CompileOptions {
+  std::string output_path;
+  Maybe<std::string> res_dir;
+  Maybe<std::string> res_zip;
+  Maybe<std::string> generate_text_symbols_path;
+  Maybe<Visibility::Level> visibility;
+  bool pseudolocalize = false;
+  bool no_png_crunch = false;
+  bool legacy_mode = false;
+  bool verbose = false;
+};
 
+/** Parses flags and compiles resources to be used in linking.  */
+class CompileCommand : public Command {
+ public:
+  explicit CompileCommand(IDiagnostics* diagnostic) : Command("compile", "c"),
+                                                      diagnostic_(diagnostic) {
+    SetDescription("Compiles resources to be linked into an apk.");
+    AddRequiredFlag("-o", "Output path", &options_.output_path);
+    AddOptionalFlag("--dir", "Directory to scan for resources", &options_.res_dir);
+    AddOptionalFlag("--zip", "Zip file containing the res directory to scan for resources",
+        &options_.res_zip);
+    AddOptionalFlag("--output-text-symbols",
+        "Generates a text file containing the resource symbols in the\n"
+            "specified file", &options_.generate_text_symbols_path);
+    AddOptionalSwitch("--pseudo-localize", "Generate resources for pseudo-locales "
+        "(en-XA and ar-XB)", &options_.pseudolocalize);
+    AddOptionalSwitch("--no-crunch", "Disables PNG processing", &options_.no_png_crunch);
+    AddOptionalSwitch("--legacy", "Treat errors that used to be valid in AAPT as warnings",
+        &options_.legacy_mode);
+    AddOptionalFlag("--visibility",
+        "Sets the visibility of the compiled resources to the specified\n"
+            "level. Accepted levels: public, private, default", &visibility_);
+    AddOptionalSwitch("-v", "Enables verbose logging", &options_.verbose);
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  IDiagnostics* diagnostic_;
+  CompileOptions options_;
+  Maybe<std::string> visibility_;
+};
+
+int Compile(IAaptContext* context, io::IFileCollection* inputs,
+             IArchiveWriter* output_writer, CompileOptions& options);
 }// namespace aapt
 
 #endif //AAPT2_COMPILE_H
diff --git a/tools/aapt2/cmd/Compile_test.cpp b/tools/aapt2/cmd/Compile_test.cpp
index 212f2cf..dd5198c 100644
--- a/tools/aapt2/cmd/Compile_test.cpp
+++ b/tools/aapt2/cmd/Compile_test.cpp
@@ -18,21 +18,22 @@
 
 #include "android-base/file.h"
 #include "io/StringStream.h"
+#include "io/ZipArchive.h"
 #include "java/AnnotationProcessor.h"
 #include "test/Test.h"
 
 namespace aapt {
 
-int TestCompile(std::string path, std::string outDir, bool legacy, StdErrDiagnostics& diag) {
+int TestCompile(const std::string& path, const std::string& outDir, bool legacy,
+    StdErrDiagnostics& diag) {
   std::vector<android::StringPiece> args;
   args.push_back(path);
   args.push_back("-o");
   args.push_back(outDir);
-  args.push_back("-v");
   if (legacy) {
     args.push_back("--legacy");
   }
-  return aapt::Compile(args, &diag);
+  return CompileCommand(&diag).Execute(args, &std::cerr);
 }
 
 TEST(CompilerTest, MultiplePeriods) {
@@ -93,4 +94,56 @@
   ASSERT_EQ(remove(path5_out.c_str()), 0);
 }
 
-}
\ No newline at end of file
+TEST(CompilerTest, DirInput) {
+  StdErrDiagnostics diag;
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  const std::string kResDir = android::base::Dirname(android::base::GetExecutablePath())
+                            + "/integration-tests/CompileTest/DirInput/res";
+  const std::string kOutputFlata = android::base::Dirname(android::base::GetExecutablePath())
+                                 + "/integration-tests/CompileTest/DirInput/compiled.flata";
+  remove(kOutputFlata.c_str());
+
+  std::vector<android::StringPiece> args;
+  args.push_back("--dir");
+  args.push_back(kResDir);
+  args.push_back("-o");
+  args.push_back(kOutputFlata);
+  ASSERT_EQ(CompileCommand(&diag).Execute(args, &std::cerr), 0);
+
+  // Check for the presence of the compiled files
+  std::string err;
+  std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(kOutputFlata, &err);
+  ASSERT_NE(zip, nullptr) << err;
+  ASSERT_NE(zip->FindFile("drawable_image.png.flat"), nullptr);
+  ASSERT_NE(zip->FindFile("layout_layout.xml.flat"), nullptr);
+  ASSERT_NE(zip->FindFile("values_values.arsc.flat"), nullptr);
+  ASSERT_EQ(remove(kOutputFlata.c_str()), 0);
+}
+
+TEST(CompilerTest, ZipInput) {
+  StdErrDiagnostics diag;
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  const std::string kResZip = android::base::Dirname(android::base::GetExecutablePath())
+                            + "/integration-tests/CompileTest/ZipInput/res.zip";
+  const std::string kOutputFlata = android::base::Dirname(android::base::GetExecutablePath())
+                                 + "/integration-tests/CompileTest/ZipInput/compiled.flata";
+  remove(kOutputFlata.c_str());
+
+  std::vector<android::StringPiece> args;
+  args.push_back("--zip");
+  args.push_back(kResZip);
+  args.push_back("-o");
+  args.push_back(kOutputFlata);
+  ASSERT_EQ(CompileCommand(&diag).Execute(args, &std::cerr), 0);
+
+  // Check for the presence of the compiled files
+  std::string err;
+  std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(kOutputFlata, &err);
+  ASSERT_NE(zip, nullptr) << err;
+  ASSERT_NE(zip->FindFile("drawable_image.png.flat"), nullptr);
+  ASSERT_NE(zip->FindFile("layout_layout.xml.flat"), nullptr);
+  ASSERT_NE(zip->FindFile("values_values.arsc.flat"), nullptr);
+  ASSERT_EQ(remove(kOutputFlata.c_str()), 0);
+}
+
+} // namespace aapt
\ No newline at end of file
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 3c8beaa..86b1f4c 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
+#include "Convert.h"
+
 #include <vector>
 
 #include "android-base/macros.h"
 #include "androidfw/StringPiece.h"
 
-#include "Flags.h"
 #include "LoadedApk.h"
 #include "ValueVisitor.h"
 #include "cmd/Util.h"
@@ -104,10 +105,7 @@
   std::unique_ptr<io::IFileCollectionIterator> iterator = apk->GetFileCollection()->Iterator();
   while (iterator->HasNext()) {
     io::IFile* file = iterator->Next();
-
     std::string path = file->GetSource().path;
-    // The name of the path has the format "<zip-file-name>@<path-to-file>".
-    path = path.substr(path.find('@') + 1);
 
     // Manifest, resource table and resources have already been taken care of.
     if (path == kAndroidManifestPath ||
@@ -310,10 +308,6 @@
     return 0u;
   }
 
-  bool IsAutoNamespace() override {
-    return false;
-  }
-
   bool verbose_ = false;
   std::string package_;
 
@@ -325,37 +319,18 @@
   StdErrDiagnostics diag_;
 };
 
-int Convert(const vector<StringPiece>& args) {
+const char* ConvertCommand::kOutputFormatProto = "proto";
+const char* ConvertCommand::kOutputFormatBinary = "binary";
 
-  static const char* kOutputFormatProto = "proto";
-  static const char* kOutputFormatBinary = "binary";
+int ConvertCommand::Action(const std::vector<std::string>& args) {
+  if (args.size() != 1) {
+    std::cerr << "must supply a single proto APK\n";
+    Usage(&std::cerr);
+    return 1;
+  }
 
   Context context;
-  std::string output_path;
-  Maybe<std::string> output_format;
-  TableFlattenerOptions options;
-  Flags flags =
-      Flags()
-          .RequiredFlag("-o", "Output path", &output_path)
-          .OptionalFlag("--output-format", StringPrintf("Format of the output. Accepted values are "
-                        "'%s' and '%s'. When not set, defaults to '%s'.", kOutputFormatProto,
-                        kOutputFormatBinary, kOutputFormatBinary), &output_format)
-          .OptionalSwitch("--enable-sparse-encoding",
-                          "Enables encoding sparse entries using a binary search tree.\n"
-                          "This decreases APK size at the cost of resource retrieval performance.",
-                          &options.use_sparse_entries)
-          .OptionalSwitch("-v", "Enables verbose logging", &context.verbose_);
-  if (!flags.Parse("aapt2 convert", args, &std::cerr)) {
-    return 1;
-  }
-
-  if (flags.GetArgs().size() != 1) {
-    std::cerr << "must supply a single proto APK\n";
-    flags.Usage("aapt2 convert", &std::cerr);
-    return 1;
-  }
-
-  const StringPiece& path = flags.GetArgs()[0];
+  const StringPiece& path = args[0];
   unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(path, context.GetDiagnostics());
   if (apk == nullptr) {
     context.GetDiagnostics()->Error(DiagMessage(path) << "failed to load APK");
@@ -371,24 +346,24 @@
   context.package_ = app_info.value().package;
 
   unique_ptr<IArchiveWriter> writer =
-      CreateZipFileArchiveWriter(context.GetDiagnostics(), output_path);
+      CreateZipFileArchiveWriter(context.GetDiagnostics(), output_path_);
   if (writer == nullptr) {
     return 1;
   }
 
   unique_ptr<IApkSerializer> serializer;
-  if (!output_format || output_format.value() == kOutputFormatBinary) {
-    serializer.reset(new BinaryApkSerializer(&context, apk->GetSource(), options));
-  } else if (output_format.value() == kOutputFormatProto) {
+  if (!output_format_ || output_format_.value() == ConvertCommand::kOutputFormatBinary) {
+
+    serializer.reset(new BinaryApkSerializer(&context, apk->GetSource(), options_));
+  } else if (output_format_.value() == ConvertCommand::kOutputFormatProto) {
     serializer.reset(new ProtoApkSerializer(&context, apk->GetSource()));
   } else {
     context.GetDiagnostics()->Error(DiagMessage(path)
-                                    << "Invalid value for flag --output-format: "
-                                    << output_format.value());
+        << "Invalid value for flag --output-format: "
+        << output_format_.value());
     return 1;
   }
 
-
   return ConvertApk(&context, std::move(apk), serializer.get(), writer.get()) ? 0 : 1;
 }
 
diff --git a/tools/aapt2/cmd/Convert.h b/tools/aapt2/cmd/Convert.h
new file mode 100644
index 0000000..fcec23d
--- /dev/null
+++ b/tools/aapt2/cmd/Convert.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT2_CONVERT_H
+#define AAPT2_CONVERT_H
+
+#include "Command.h"
+#include "format/binary/TableFlattener.h"
+
+namespace aapt {
+
+class ConvertCommand : public Command {
+ public:
+  explicit ConvertCommand() : Command("convert") {
+    SetDescription("Converts an apk between binary and proto formats.");
+    AddRequiredFlag("-o", "Output path", &output_path_);
+    AddOptionalFlag("--output-format", android::base::StringPrintf("Format of the output. "
+            "Accepted values are '%s' and '%s'. When not set, defaults to '%s'.",
+        kOutputFormatProto, kOutputFormatBinary, kOutputFormatBinary), &output_format_);
+    AddOptionalSwitch("--enable-sparse-encoding",
+        "Enables encoding sparse entries using a binary search tree.\n"
+            "This decreases APK size at the cost of resource retrieval performance.",
+        &options_.use_sparse_entries);
+    AddOptionalSwitch("-v", "Enables verbose logging", &verbose_);
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  const static char* kOutputFormatProto;
+  const static char* kOutputFormatBinary;
+
+  TableFlattenerOptions options_;
+  std::string output_path_;
+  Maybe<std::string> output_format_;
+  bool verbose_ = false;
+};
+
+}// namespace aapt
+
+#endif //AAPT2_CONVERT_H
diff --git a/tools/aapt2/cmd/Diff.cpp b/tools/aapt2/cmd/Diff.cpp
index 16c7bba..262f4fc4e 100644
--- a/tools/aapt2/cmd/Diff.cpp
+++ b/tools/aapt2/cmd/Diff.cpp
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
+#include "Diff.h"
+
 #include "android-base/macros.h"
 
-#include "Flags.h"
 #include "LoadedApk.h"
 #include "ValueVisitor.h"
 #include "process/IResourceTableConsumer.h"
@@ -64,10 +65,6 @@
     return 0;
   }
 
-  bool IsAutoNamespace() override {
-    return false;
-  }
-
  private:
   std::string empty_;
   StdErrDiagnostics diagnostics_;
@@ -348,23 +345,18 @@
   VisitAllValuesInTable(table, &visitor);
 }
 
-int Diff(const std::vector<StringPiece>& args) {
+int DiffCommand::Action(const std::vector<std::string>& args) {
   DiffContext context;
 
-  Flags flags;
-  if (!flags.Parse("aapt2 diff", args, &std::cerr)) {
-    return 1;
-  }
-
-  if (flags.GetArgs().size() != 2u) {
+  if (args.size() != 2u) {
     std::cerr << "must have two apks as arguments.\n\n";
-    flags.Usage("aapt2 diff", &std::cerr);
+    Usage(&std::cerr);
     return 1;
   }
 
   IDiagnostics* diag = context.GetDiagnostics();
-  std::unique_ptr<LoadedApk> apk_a = LoadedApk::LoadApkFromPath(flags.GetArgs()[0], diag);
-  std::unique_ptr<LoadedApk> apk_b = LoadedApk::LoadApkFromPath(flags.GetArgs()[1], diag);
+  std::unique_ptr<LoadedApk> apk_a = LoadedApk::LoadApkFromPath(args[0], diag);
+  std::unique_ptr<LoadedApk> apk_b = LoadedApk::LoadApkFromPath(args[1], diag);
   if (!apk_a || !apk_b) {
     return 1;
   }
diff --git a/tools/aapt2/cmd/Diff.h b/tools/aapt2/cmd/Diff.h
new file mode 100644
index 0000000..c388888
--- /dev/null
+++ b/tools/aapt2/cmd/Diff.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT2_DIFF_H
+#define AAPT2_DIFF_H
+
+#include "Command.h"
+
+namespace aapt {
+
+class DiffCommand : public Command {
+ public:
+  explicit DiffCommand() : Command("diff") {
+    SetDescription("Prints the differences in resources of two apks.");
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+};
+
+}// namespace aapt
+
+#endif //AAPT2_DIFF_H
diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp
index fd133f3..29e471e 100644
--- a/tools/aapt2/cmd/Dump.cpp
+++ b/tools/aapt2/cmd/Dump.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "Dump.h"
+
 #include <cinttypes>
 #include <vector>
 
@@ -22,9 +24,11 @@
 
 #include "Debug.h"
 #include "Diagnostics.h"
-#include "Flags.h"
+#include "LoadedApk.h"
+#include "Util.h"
 #include "format/Container.h"
 #include "format/binary/BinaryResourceParser.h"
+#include "format/binary/XmlFlattener.h"
 #include "format/proto/ProtoDeserialize.h"
 #include "io/FileStream.h"
 #include "io/ZipArchive.h"
@@ -38,13 +42,6 @@
 
 namespace aapt {
 
-struct DumpOptions {
-  DebugPrintTableOptions print_options;
-
-  // The path to a file within an APK to dump.
-  Maybe<std::string> file_to_dump_path;
-};
-
 static const char* ResourceFileTypeToString(const ResourceFile::Type& type) {
   switch (type) {
     case ResourceFile::Type::kPng:
@@ -76,184 +73,6 @@
   printer->Println(StringPrintf("Data:     offset=%" PRIi64 " length=%zd", offset, len));
 }
 
-static bool DumpXmlFile(IAaptContext* context, io::IFile* file, bool proto,
-                        text::Printer* printer) {
-  std::unique_ptr<xml::XmlResource> doc;
-  if (proto) {
-    std::unique_ptr<io::InputStream> in = file->OpenInputStream();
-    if (in == nullptr) {
-      context->GetDiagnostics()->Error(DiagMessage() << "failed to open file");
-      return false;
-    }
-
-    io::ZeroCopyInputAdaptor adaptor(in.get());
-    pb::XmlNode pb_node;
-    if (!pb_node.ParseFromZeroCopyStream(&adaptor)) {
-      context->GetDiagnostics()->Error(DiagMessage() << "failed to parse file as proto XML");
-      return false;
-    }
-
-    std::string err;
-    doc = DeserializeXmlResourceFromPb(pb_node, &err);
-    if (doc == nullptr) {
-      context->GetDiagnostics()->Error(DiagMessage() << "failed to deserialize proto XML");
-      return false;
-    }
-    printer->Println("Proto XML");
-  } else {
-    std::unique_ptr<io::IData> data = file->OpenAsData();
-    if (data == nullptr) {
-      context->GetDiagnostics()->Error(DiagMessage() << "failed to open file");
-      return false;
-    }
-
-    std::string err;
-    doc = xml::Inflate(data->data(), data->size(), &err);
-    if (doc == nullptr) {
-      context->GetDiagnostics()->Error(DiagMessage() << "failed to parse file as binary XML");
-      return false;
-    }
-    printer->Println("Binary XML");
-  }
-
-  Debug::DumpXml(*doc, printer);
-  return true;
-}
-
-static bool TryDumpFile(IAaptContext* context, const std::string& file_path,
-                        const DumpOptions& options) {
-  // Use a smaller buffer so that there is less latency for dumping to stdout.
-  constexpr size_t kStdOutBufferSize = 1024u;
-  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
-  Printer printer(&fout);
-
-  std::string err;
-  std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(file_path, &err);
-  if (zip) {
-    ResourceTable table;
-    bool proto = false;
-    if (io::IFile* file = zip->FindFile("resources.pb")) {
-      proto = true;
-
-      std::unique_ptr<io::IData> data = file->OpenAsData();
-      if (data == nullptr) {
-        context->GetDiagnostics()->Error(DiagMessage(file_path) << "failed to open resources.pb");
-        return false;
-      }
-
-      pb::ResourceTable pb_table;
-      if (!pb_table.ParseFromArray(data->data(), data->size())) {
-        context->GetDiagnostics()->Error(DiagMessage(file_path) << "invalid resources.pb");
-        return false;
-      }
-
-      if (!DeserializeTableFromPb(pb_table, zip.get(), &table, &err)) {
-        context->GetDiagnostics()->Error(DiagMessage(file_path)
-                                         << "failed to parse table: " << err);
-        return false;
-      }
-    } else if (io::IFile* file = zip->FindFile("resources.arsc")) {
-      std::unique_ptr<io::IData> data = file->OpenAsData();
-      if (!data) {
-        context->GetDiagnostics()->Error(DiagMessage(file_path) << "failed to open resources.arsc");
-        return false;
-      }
-
-      BinaryResourceParser parser(context->GetDiagnostics(), &table, Source(file_path),
-                                  data->data(), data->size());
-      if (!parser.Parse()) {
-        return false;
-      }
-    }
-
-    if (!options.file_to_dump_path) {
-      if (proto) {
-        printer.Println("Proto APK");
-      } else {
-        printer.Println("Binary APK");
-      }
-      Debug::PrintTable(table, options.print_options, &printer);
-      return true;
-    }
-
-    io::IFile* file = zip->FindFile(options.file_to_dump_path.value());
-    if (file == nullptr) {
-      context->GetDiagnostics()->Error(DiagMessage(file_path)
-                                       << "file '" << options.file_to_dump_path.value()
-                                       << "' not found in APK");
-      return false;
-    }
-    return DumpXmlFile(context, file, proto, &printer);
-  }
-
-  err.clear();
-
-  io::FileInputStream input(file_path);
-  if (input.HadError()) {
-    context->GetDiagnostics()->Error(DiagMessage(file_path)
-                                     << "failed to open file: " << input.GetError());
-    return false;
-  }
-
-  // Try as a compiled file.
-  ContainerReader reader(&input);
-  if (reader.HadError()) {
-    context->GetDiagnostics()->Error(DiagMessage(file_path)
-                                     << "failed to read container: " << reader.GetError());
-    return false;
-  }
-
-  printer.Println("AAPT2 Container (APC)");
-  ContainerReaderEntry* entry;
-  while ((entry = reader.Next()) != nullptr) {
-    if (entry->Type() == ContainerEntryType::kResTable) {
-      printer.Println("kResTable");
-
-      pb::ResourceTable pb_table;
-      if (!entry->GetResTable(&pb_table)) {
-        context->GetDiagnostics()->Error(DiagMessage(file_path)
-                                         << "failed to parse proto table: " << entry->GetError());
-        continue;
-      }
-
-      ResourceTable table;
-      err.clear();
-      if (!DeserializeTableFromPb(pb_table, nullptr /*files*/, &table, &err)) {
-        context->GetDiagnostics()->Error(DiagMessage(file_path)
-                                         << "failed to parse table: " << err);
-        continue;
-      }
-
-      printer.Indent();
-      Debug::PrintTable(table, options.print_options, &printer);
-      printer.Undent();
-    } else if (entry->Type() == ContainerEntryType::kResFile) {
-      printer.Println("kResFile");
-      pb::internal::CompiledFile pb_compiled_file;
-      off64_t offset;
-      size_t length;
-      if (!entry->GetResFileOffsets(&pb_compiled_file, &offset, &length)) {
-        context->GetDiagnostics()->Error(
-            DiagMessage(file_path) << "failed to parse compiled proto file: " << entry->GetError());
-        continue;
-      }
-
-      ResourceFile file;
-      std::string error;
-      if (!DeserializeCompiledFileFromPb(pb_compiled_file, &file, &error)) {
-        context->GetDiagnostics()->Warn(DiagMessage(file_path)
-                                        << "failed to parse compiled file: " << error);
-        continue;
-      }
-
-      printer.Indent();
-      DumpCompiledFile(file, Source(file_path), offset, length, &printer);
-      printer.Undent();
-    }
-  }
-  return true;
-}
-
 namespace {
 
 class DumpContext : public IAaptContext {
@@ -298,10 +117,6 @@
     return 0;
   }
 
-  bool IsAutoNamespace() override {
-    return false;
-  }
-
  private:
   StdErrDiagnostics diagnostics_;
   bool verbose_ = false;
@@ -309,33 +124,320 @@
 
 }  // namespace
 
-// Entry point for dump command.
-int Dump(const std::vector<StringPiece>& args) {
-  bool verbose = false;
-  bool no_values = false;
-  DumpOptions options;
-  Flags flags = Flags()
-                    .OptionalSwitch("--no-values",
-                                    "Suppresses output of values when displaying resource tables.",
-                                    &no_values)
-                    .OptionalFlag("--file", "Dumps the specified file from the APK passed as arg.",
-                                  &options.file_to_dump_path)
-                    .OptionalSwitch("-v", "increase verbosity of output", &verbose);
-  if (!flags.Parse("aapt2 dump", args, &std::cerr)) {
+// Use a smaller buffer so that there is less latency for dumping to stdout.
+constexpr size_t kStdOutBufferSize = 1024u;
+
+int DumpAPCCommand::Action(const std::vector<std::string>& args) {
+  DumpContext context;
+  DebugPrintTableOptions print_options;
+  print_options.show_sources = true;
+  print_options.show_values = !no_values_;
+
+  if (args.size() < 1) {
+    diag_->Error(DiagMessage() << "No dump container specified.");
     return 1;
   }
 
-  DumpContext context;
-  context.SetVerbose(verbose);
+  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
+  Printer printer(&fout);
 
-  options.print_options.show_sources = true;
-  options.print_options.show_values = !no_values;
-  for (const std::string& arg : flags.GetArgs()) {
-    if (!TryDumpFile(&context, arg, options)) {
-      return 1;
+  for (auto container : args) {
+    io::FileInputStream input(container);
+    if (input.HadError()) {
+      context.GetDiagnostics()->Error(DiagMessage(container)
+                                          << "failed to open file: " << input.GetError());
+      return false;
+    }
+
+    // Try as a compiled file.
+    ContainerReader reader(&input);
+    if (reader.HadError()) {
+      context.GetDiagnostics()->Error(DiagMessage(container)
+                                           << "failed to read container: " << reader.GetError());
+      return false;
+    }
+
+    printer.Println("AAPT2 Container (APC)");
+    ContainerReaderEntry* entry;
+    std::string error;
+    while ((entry = reader.Next()) != nullptr) {
+      if (entry->Type() == ContainerEntryType::kResTable) {
+        printer.Println("kResTable");
+
+        pb::ResourceTable pb_table;
+        if (!entry->GetResTable(&pb_table)) {
+          context.GetDiagnostics()->Error(DiagMessage(container)
+                                               << "failed to parse proto table: "
+                                               << entry->GetError());
+          continue;
+        }
+
+        ResourceTable table;
+        error.clear();
+        if (!DeserializeTableFromPb(pb_table, nullptr /*files*/, &table, &error)) {
+          context.GetDiagnostics()->Error(DiagMessage(container)
+                                               << "failed to parse table: " << error);
+          continue;
+        }
+
+        printer.Indent();
+        Debug::PrintTable(table, print_options, &printer);
+        printer.Undent();
+      } else if (entry->Type() == ContainerEntryType::kResFile) {
+        printer.Println("kResFile");
+        pb::internal::CompiledFile pb_compiled_file;
+        off64_t offset;
+        size_t length;
+        if (!entry->GetResFileOffsets(&pb_compiled_file, &offset, &length)) {
+          context.GetDiagnostics()->Error(
+              DiagMessage(container) << "failed to parse compiled proto file: "
+                                     << entry->GetError());
+          continue;
+        }
+
+        ResourceFile file;
+        if (!DeserializeCompiledFileFromPb(pb_compiled_file, &file, &error)) {
+          context.GetDiagnostics()->Warn(DiagMessage(container)
+                                              << "failed to parse compiled file: " << error);
+          continue;
+        }
+
+        printer.Indent();
+        DumpCompiledFile(file, Source(container), offset, length, &printer);
+        printer.Undent();
+      }
     }
   }
+
   return 0;
 }
 
+int DumpConfigsCommand::Action(const std::vector<std::string>& args) {
+  if (args.size() < 1) {
+    diag_->Error(DiagMessage() << "No dump apk specified.");
+    return 1;
+  }
+
+  auto loaded_apk = LoadedApk::LoadApkFromPath(args[0], diag_);
+  if (!loaded_apk) {
+    return 1;
+  }
+
+  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
+  Printer printer(&fout);
+
+  // Comparison function used to order configurations
+  auto compare = [](ConfigDescription c1, ConfigDescription c2) -> bool {
+      return c1.compare(c2) < 0;
+  };
+
+  // Insert the configurations into a set in order to keep every configuarion seen
+  std::set<ConfigDescription, decltype(compare)> configs(compare);
+  for (auto& package : loaded_apk->GetResourceTable()->packages) {
+    for (auto& type : package->types) {
+      for (auto& entry : type->entries) {
+        for (auto& value : entry->values) {
+          configs.insert(value->config);
+        }
+      }
+    }
+  }
+
+  // Print the configurations in order
+  for (auto& config : configs) {
+    printer.Print(StringPrintf("%s\n", config.to_string().data()));
+  }
+
+  return 0;
+}
+
+int DumpStringsCommand::Action(const std::vector<std::string>& args) {
+  DumpContext context;
+  if (args.size() < 1) {
+    diag_->Error(DiagMessage() << "No dump apk specified.");
+    return 1;
+  }
+
+  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
+  Printer printer(&fout);
+
+  for (auto apk : args) {
+    auto loaded_apk = LoadedApk::LoadApkFromPath(apk, diag_);
+    if (!loaded_apk) {
+      return 1;
+    }
+
+    // Load the run-time xml string pool using the flattened data
+    BigBuffer buffer(4096);
+    StringPool::FlattenUtf8(&buffer, loaded_apk->GetResourceTable()->string_pool,
+                            context.GetDiagnostics());
+    auto data = buffer.to_string();
+    android::ResStringPool pool(data.data(), data.size(), false);
+    Debug::DumpResStringPool(&pool, &printer);
+  }
+
+  return 0;
+}
+
+int DumpTableCommand::Action(const std::vector<std::string>& args) {
+  if (args.size() < 1) {
+    diag_->Error(DiagMessage() << "No dump apk specified.");
+    return 1;
+  }
+
+  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
+  Printer printer(&fout);
+
+  DebugPrintTableOptions print_options;
+  print_options.show_sources = true;
+  print_options.show_values = !no_values_;
+
+  for (auto apk : args) {
+    auto loaded_apk = LoadedApk::LoadApkFromPath(apk, diag_);
+    if (!loaded_apk) {
+      return 1;
+    }
+
+    if (loaded_apk->GetApkFormat()) {
+      printer.Println("Proto APK");
+    } else {
+      printer.Println("Binary APK");
+    }
+
+    Debug::PrintTable(*loaded_apk->GetResourceTable(), print_options, &printer);
+  }
+
+  return 0;
+}
+
+int DumpXmlTreeCommand::Action(const std::vector<std::string>& args) {
+  if (args.size() < 1) {
+    diag_->Error(DiagMessage() << "No dump apk specified");
+    return 1;
+  }
+
+  auto loaded_apk = LoadedApk::LoadApkFromPath(args[0], diag_);
+  if (!loaded_apk) {
+    return 1;
+  }
+
+  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
+  Printer printer(&fout);
+
+  // Dump the xml tree of every passed in file
+  for (auto file : files_) {
+    auto xml = loaded_apk->LoadXml(file, diag_);
+    if (!xml) {
+      return 1;
+    }
+
+    Debug::DumpXml(*xml, &printer);
+  }
+
+  return 0;
+}
+
+int DumpXmlStringsCommand::Action(const std::vector<std::string>& args) {
+  DumpContext context;
+  if (args.size() < 1) {
+    diag_->Error(DiagMessage() << "No dump apk specified.");
+    return 1;
+  }
+
+  auto loaded_apk = LoadedApk::LoadApkFromPath(args[0], diag_);
+  if (!loaded_apk) {
+    return 1;
+  }
+
+  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
+  Printer printer(&fout);
+
+  // Dump the xml strings of every passed in file
+  for (auto xml_file : files_) {
+    android::ResXMLTree tree;
+
+    if (loaded_apk->GetApkFormat() == kProto) {
+      auto xml = loaded_apk->LoadXml(xml_file, diag_);
+      if (!xml) {
+        return 1;
+      }
+
+      // Flatten the xml document to get a binary representation of the proto xml file
+      BigBuffer buffer(4096);
+      XmlFlattenerOptions options = {};
+      options.keep_raw_values = true;
+      XmlFlattener flattener(&buffer, options);
+      if (!flattener.Consume(&context, xml.get())) {
+        return 1;
+      }
+
+      // Load the run-time xml tree using the flattened data
+      std::string data = buffer.to_string();
+      tree.setTo(data.data(), data.size(), /** copyData */ true);
+
+    } else if (loaded_apk->GetApkFormat() == kBinary) {
+      io::IFile* file = loaded_apk->GetFileCollection()->FindFile(xml_file);
+      if (!file) {
+        diag_->Error(DiagMessage(xml_file) << "file '" << xml_file << "' not found in APK");
+        return 1;
+      }
+
+      std::unique_ptr<io::IData> data = file->OpenAsData();
+      if (!data) {
+        diag_->Error(DiagMessage() << "failed to open file");
+        return 1;
+      }
+
+      // Load the run-time xml tree from the file data
+      tree.setTo(data->data(), data->size(), /** copyData */ true);
+    }
+
+    Debug::DumpResStringPool(&tree.getStrings(), &printer);
+  }
+
+  return 0;
+}
+
+int DumpPackageNameCommand::Action(const std::vector<std::string>& args) {
+  if (args.size() < 1) {
+    diag_->Error(DiagMessage() << "No dump apk specified.");
+    return 1;
+  }
+
+  auto loaded_apk = LoadedApk::LoadApkFromPath(args[0], diag_);
+  if (!loaded_apk) {
+    return 1;
+  }
+
+  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
+  Printer printer(&fout);
+
+  xml::Element* manifest_el = loaded_apk->GetManifest()->root.get();
+  if (!manifest_el) {
+    diag_->Error(DiagMessage() << "No AndroidManifest.");
+    return 1;
+  }
+
+  xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
+  if (!attr) {
+    diag_->Error(DiagMessage() << "No package name.");
+    return 1;
+  }
+  printer.Println(StringPrintf("%s", attr->value.c_str()));
+
+  return 0;
+}
+
+/** Preform no action because a subcommand is required. */
+int DumpCommand::Action(const std::vector<std::string>& args) {
+  if (args.size() == 0) {
+    diag_->Error(DiagMessage() << "no subcommand specified");
+  } else {
+    diag_->Error(DiagMessage() << "unknown subcommand '" << args[0] << "'");
+  }
+
+  Usage(&std::cerr);
+  return 1;
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/cmd/Dump.h b/tools/aapt2/cmd/Dump.h
new file mode 100644
index 0000000..0724d62
--- /dev/null
+++ b/tools/aapt2/cmd/Dump.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT2_DUMP_H
+#define AAPT2_DUMP_H
+
+#include "Command.h"
+#include "Debug.h"
+
+namespace aapt {
+
+/** Command the contents of files generated from the compilation stage. */
+class DumpAPCCommand : public Command {
+ public:
+  explicit DumpAPCCommand(IDiagnostics* diag) : Command("apc"), diag_(diag) {
+    SetDescription("Print the contents of the AAPT2 Container (APC) generated fom compilation.");
+    AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
+                      &no_values_);
+    AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  IDiagnostics* diag_;
+  bool verbose_ = false;
+  bool no_values_ = false;
+};
+
+/** Prints every configuration used by a resource in an APK. */
+class DumpConfigsCommand : public Command {
+ public:
+  explicit DumpConfigsCommand(IDiagnostics* diag) : Command("configurations"), diag_(diag) {
+    SetDescription("Print every configuration used by a resource in the APK.");
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  IDiagnostics* diag_;
+};
+
+/** Prints the contents of the resource table string pool in the APK. */
+class DumpStringsCommand : public Command {
+  public:
+    explicit DumpStringsCommand(IDiagnostics* diag) : Command("strings"), diag_(diag) {
+      SetDescription("Print the contents of the resource table string pool in the APK.");
+    }
+
+    int Action(const std::vector<std::string>& args) override;
+
+  private:
+    IDiagnostics* diag_;
+};
+
+/** Prints the contents of the resource table from the APK. */
+class DumpTableCommand : public Command {
+ public:
+  explicit DumpTableCommand(IDiagnostics* diag) : Command("resources"), diag_(diag) {
+    SetDescription("Print the contents of the resource table from the APK.");
+    AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
+                      &no_values_);
+    AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  IDiagnostics* diag_;
+  bool verbose_ = false;
+  bool no_values_ = false;
+};
+
+/** Prints the string pool of a compiled xml in an APK. */
+class DumpXmlStringsCommand : public Command {
+public:
+    explicit DumpXmlStringsCommand(IDiagnostics* diag) : Command("xmlstrings"), diag_(diag) {
+      SetDescription("Print the string pool of a compiled xml in an APK.");
+      AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
+    }
+
+    int Action(const std::vector<std::string>& args) override;
+
+private:
+    IDiagnostics* diag_;
+    std::vector<std::string> files_;
+};
+
+
+/** Prints the tree of a compiled xml in an APK. */
+class DumpXmlTreeCommand : public Command {
+ public:
+  explicit DumpXmlTreeCommand(IDiagnostics* diag) : Command("xmltree"), diag_(diag) {
+    SetDescription("Print the tree of a compiled xml in an APK.");
+    AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  IDiagnostics* diag_;
+  std::vector<std::string> files_;
+};
+
+/** Prints the contents of the resource table from the APK. */
+class DumpPackageNameCommand : public Command {
+ public:
+  explicit DumpPackageNameCommand(IDiagnostics* diag) : Command("packagename"), diag_(diag) {
+    SetDescription("Print the package name of the APK.");
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  IDiagnostics* diag_;
+};
+
+/** The default dump command. Performs no action because a subcommand is required. */
+class DumpCommand : public Command {
+ public:
+  explicit DumpCommand(IDiagnostics* diag) : Command("dump", "d"), diag_(diag) {
+    AddOptionalSubcommand(util::make_unique<DumpAPCCommand>(diag_));
+    AddOptionalSubcommand(util::make_unique<DumpConfigsCommand>(diag_));
+    AddOptionalSubcommand(util::make_unique<DumpPackageNameCommand>(diag_));
+    AddOptionalSubcommand(util::make_unique<DumpStringsCommand>(diag_));
+    AddOptionalSubcommand(util::make_unique<DumpTableCommand>(diag_));
+    AddOptionalSubcommand(util::make_unique<DumpXmlStringsCommand>(diag_));
+    AddOptionalSubcommand(util::make_unique<DumpXmlTreeCommand>(diag_));
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  IDiagnostics* diag_;
+};
+
+}// namespace aapt
+
+#endif //AAPT2_DUMP_H
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 1a2da7f..119f56a 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "Link.h"
+
 #include <sys/stat.h>
 #include <cinttypes>
 
@@ -29,7 +31,6 @@
 
 #include "AppInfo.h"
 #include "Debug.h"
-#include "Flags.h"
 #include "LoadedApk.h"
 #include "Locale.h"
 #include "NameMangler.h"
@@ -74,74 +75,6 @@
 
 namespace aapt {
 
-enum class OutputFormat {
-  kApk,
-  kProto,
-};
-
-struct LinkOptions {
-  std::string output_path;
-  std::string manifest_path;
-  std::vector<std::string> include_paths;
-  std::vector<std::string> overlay_files;
-  std::vector<std::string> assets_dirs;
-  bool output_to_directory = false;
-  bool auto_add_overlay = false;
-  OutputFormat output_format = OutputFormat::kApk;
-
-  // Java/Proguard options.
-  Maybe<std::string> generate_java_class_path;
-  Maybe<std::string> custom_java_package;
-  std::set<std::string> extra_java_packages;
-  Maybe<std::string> generate_text_symbols_path;
-  Maybe<std::string> generate_proguard_rules_path;
-  Maybe<std::string> generate_main_dex_proguard_rules_path;
-  bool generate_conditional_proguard_rules = false;
-  bool generate_non_final_ids = false;
-  std::vector<std::string> javadoc_annotations;
-  Maybe<std::string> private_symbols;
-
-  // Optimizations/features.
-  bool no_auto_version = false;
-  bool no_version_vectors = false;
-  bool no_version_transitions = false;
-  bool no_resource_deduping = false;
-  bool no_xml_namespaces = false;
-  bool do_not_compress_anything = false;
-  std::unordered_set<std::string> extensions_to_not_compress;
-
-  // Static lib options.
-  bool no_static_lib_packages = false;
-  bool auto_namespace_static_lib = false;
-
-  // AndroidManifest.xml massaging options.
-  ManifestFixerOptions manifest_fixer_options;
-
-  // Products to use/filter on.
-  std::unordered_set<std::string> products;
-
-  // Flattening options.
-  TableFlattenerOptions table_flattener_options;
-
-  // Split APK options.
-  TableSplitterOptions table_splitter_options;
-  std::vector<SplitConstraints> split_constraints;
-  std::vector<std::string> split_paths;
-
-  // Stable ID options.
-  std::unordered_map<ResourceName, ResourceId> stable_id_map;
-  Maybe<std::string> resource_id_map_path;
-
-  // When 'true', allow reserved package IDs to be used for applications. Pre-O, the platform
-  // treats negative resource IDs [those with a package ID of 0x80 or higher] as invalid.
-  // In order to work around this limitation, we allow the use of traditionally reserved
-  // resource IDs [those between 0x02 and 0x7E].
-  bool allow_reserved_package_id = false;
-
-  // Whether we should fail on definitions of a resource with conflicting visibility.
-  bool strict_visibility = false;
-};
-
 class LinkContext : public IAaptContext {
  public:
   LinkContext(IDiagnostics* diagnostics)
@@ -204,14 +137,6 @@
     min_sdk_version_ = minSdk;
   }
 
-  bool IsAutoNamespace() override {
-    return auto_namespace_;
-  }
-
-  void SetAutoNamespace(bool val) {
-    auto_namespace_ = val;
-  }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(LinkContext);
 
@@ -223,7 +148,6 @@
   SymbolTable symbols_;
   bool verbose_ = false;
   int min_sdk_version_ = 0;
-  bool auto_namespace_ = false;
 };
 
 // A custom delegate that generates compatible pre-O IDs for use with feature splits.
@@ -546,6 +470,10 @@
   return ResourceFile::Type::kUnknown;
 }
 
+static auto kDrawableVersions = std::map<std::string, ApiVersion>{
+    { "adaptive-icon" , SDK_O },
+};
+
 bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
   bool error = false;
   std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
@@ -643,6 +571,20 @@
         FileOperation& file_op = map_entry.second;
 
         if (file_op.xml_to_flatten) {
+          // Check minimum sdk versions supported for drawables
+          auto drawable_entry = kDrawableVersions.find(file_op.xml_to_flatten->root->name);
+          if (drawable_entry != kDrawableVersions.end()) {
+            if (drawable_entry->second > context_->GetMinSdkVersion()
+                && drawable_entry->second > config.sdkVersion) {
+              context_->GetDiagnostics()->Error(DiagMessage(file_op.xml_to_flatten->file.source)
+                                                    << "<" << drawable_entry->first << "> elements "
+                                                    << "require a sdk version of at least "
+                                                    << (int16_t) drawable_entry->second);
+              error = true;
+              continue;
+            }
+          }
+
           std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
               LinkAndVersionXmlFile(table, &file_op);
           if (versioned_docs.empty()) {
@@ -785,9 +727,9 @@
   return table.getTableCookie(idx);
 }
 
-class LinkCommand {
+class Linker {
  public:
-  LinkCommand(LinkContext* context, const LinkOptions& options)
+  Linker(LinkContext* context, const LinkOptions& options)
       : options_(options),
         context_(context),
         final_table_(),
@@ -975,6 +917,18 @@
       app_info.version_code = maybe_code.value();
     }
 
+    if (xml::Attribute* version_code_major_attr =
+        manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor")) {
+      Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(version_code_major_attr->value);
+      if (!maybe_code) {
+        diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
+                        << "invalid android:versionCodeMajor '"
+                        << version_code_major_attr->value << "'");
+        return {};
+      }
+      app_info.version_code_major = maybe_code.value();
+    }
+
     if (xml::Attribute* revision_code_attr =
             manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode")) {
       Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(revision_code_attr->value);
@@ -2040,197 +1994,12 @@
   Maybe<std::string> included_feature_base_;
 };
 
-int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
-  LinkContext context(diagnostics);
-  LinkOptions options;
-  std::vector<std::string> overlay_arg_list;
-  std::vector<std::string> extra_java_packages;
-  Maybe<std::string> package_id;
-  std::vector<std::string> configs;
-  Maybe<std::string> preferred_density;
-  Maybe<std::string> product_list;
-  bool legacy_x_flag = false;
-  bool require_localization = false;
-  bool verbose = false;
-  bool shared_lib = false;
-  bool static_lib = false;
-  bool proto_format = false;
-  Maybe<std::string> stable_id_file_path;
-  std::vector<std::string> split_args;
-  Flags flags =
-      Flags()
-          .RequiredFlag("-o", "Output path.", &options.output_path)
-          .RequiredFlag("--manifest", "Path to the Android manifest to build.",
-                        &options.manifest_path)
-          .OptionalFlagList("-I", "Adds an Android APK to link against.", &options.include_paths)
-          .OptionalFlagList("-A",
-                            "An assets directory to include in the APK. These are unprocessed.",
-                            &options.assets_dirs)
-          .OptionalFlagList("-R",
-                            "Compilation unit to link, using `overlay` semantics.\n"
-                            "The last conflicting resource given takes precedence.",
-                            &overlay_arg_list)
-          .OptionalFlag("--package-id",
-                        "Specify the package ID to use for this app. Must be greater or equal to\n"
-                        "0x7f and can't be used with --static-lib or --shared-lib.",
-                        &package_id)
-          .OptionalFlag("--java", "Directory in which to generate R.java.",
-                        &options.generate_java_class_path)
-          .OptionalFlag("--proguard", "Output file for generated Proguard rules.",
-                        &options.generate_proguard_rules_path)
-          .OptionalFlag("--proguard-main-dex",
-                        "Output file for generated Proguard rules for the main dex.",
-                        &options.generate_main_dex_proguard_rules_path)
-          .OptionalSwitch("--proguard-conditional-keep-rules",
-                          "Generate conditional Proguard keep rules.",
-                          &options.generate_conditional_proguard_rules)
-          .OptionalSwitch("--no-auto-version",
-                          "Disables automatic style and layout SDK versioning.",
-                          &options.no_auto_version)
-          .OptionalSwitch("--no-version-vectors",
-                          "Disables automatic versioning of vector drawables. Use this only\n"
-                          "when building with vector drawable support library.",
-                          &options.no_version_vectors)
-          .OptionalSwitch("--no-version-transitions",
-                          "Disables automatic versioning of transition resources. Use this only\n"
-                          "when building with transition support library.",
-                          &options.no_version_transitions)
-          .OptionalSwitch("--no-resource-deduping",
-                          "Disables automatic deduping of resources with\n"
-                          "identical values across compatible configurations.",
-                          &options.no_resource_deduping)
-          .OptionalSwitch("--enable-sparse-encoding",
-                          "Enables encoding sparse entries using a binary search tree.\n"
-                          "This decreases APK size at the cost of resource retrieval performance.",
-                          &options.table_flattener_options.use_sparse_entries)
-          .OptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.",
-                          &legacy_x_flag)
-          .OptionalSwitch("-z", "Require localization of strings marked 'suggested'.",
-                          &require_localization)
-          .OptionalFlagList("-c",
-                            "Comma separated list of configurations to include. The default\n"
-                            "is all configurations.",
-                            &configs)
-          .OptionalFlag("--preferred-density",
-                        "Selects the closest matching density and strips out all others.",
-                        &preferred_density)
-          .OptionalFlag("--product", "Comma separated list of product names to keep", &product_list)
-          .OptionalSwitch("--output-to-dir",
-                          "Outputs the APK contents to a directory specified by -o.",
-                          &options.output_to_directory)
-          .OptionalSwitch("--no-xml-namespaces",
-                          "Removes XML namespace prefix and URI information from\n"
-                          "AndroidManifest.xml and XML binaries in res/*.",
-                          &options.no_xml_namespaces)
-          .OptionalFlag("--min-sdk-version",
-                        "Default minimum SDK version to use for AndroidManifest.xml.",
-                        &options.manifest_fixer_options.min_sdk_version_default)
-          .OptionalFlag("--target-sdk-version",
-                        "Default target SDK version to use for AndroidManifest.xml.",
-                        &options.manifest_fixer_options.target_sdk_version_default)
-          .OptionalFlag("--version-code",
-                        "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
-                        "present.",
-                        &options.manifest_fixer_options.version_code_default)
-          .OptionalFlag("--version-name",
-                        "Version name to inject into the AndroidManifest.xml if none is present.",
-                        &options.manifest_fixer_options.version_name_default)
-          .OptionalSwitch("--replace-version",
-                         "If --version-code and/or --version-name are specified, these\n"
-                         "values will replace any value already in the manifest. By\n"
-                         "default, nothing is changed if the manifest already defines\n"
-                         "these attributes.",
-                         &options.manifest_fixer_options.replace_version)
-          .OptionalFlag("--compile-sdk-version-code",
-                        "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
-                        "present.",
-                        &options.manifest_fixer_options.compile_sdk_version)
-          .OptionalFlag("--compile-sdk-version-name",
-                        "Version name to inject into the AndroidManifest.xml if none is present.",
-                        &options.manifest_fixer_options.compile_sdk_version_codename)
-          .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
-                          &shared_lib)
-          .OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib)
-          .OptionalSwitch("--proto-format",
-                          "Generates compiled resources in Protobuf format.\n"
-                          "Suitable as input to the bundle tool for generating an App Bundle.",
-                          &proto_format)
-          .OptionalSwitch("--no-static-lib-packages",
-                          "Merge all library resources under the app's package.",
-                          &options.no_static_lib_packages)
-          .OptionalSwitch("--auto-namespace-static-lib",
-                          "Automatically namespace resource references when building a static\n"
-                          "library.",
-                          &options.auto_namespace_static_lib)
-          .OptionalSwitch("--non-final-ids",
-                          "Generates R.java without the final modifier. This is implied when\n"
-                          "--static-lib is specified.",
-                          &options.generate_non_final_ids)
-          .OptionalFlag("--stable-ids", "File containing a list of name to ID mapping.",
-                        &stable_id_file_path)
-          .OptionalFlag("--emit-ids",
-                        "Emit a file at the given path with a list of name to ID mappings,\n"
-                        "suitable for use with --stable-ids.",
-                        &options.resource_id_map_path)
-          .OptionalFlag("--private-symbols",
-                        "Package name to use when generating R.java for private symbols.\n"
-                        "If not specified, public and private symbols will use the application's\n"
-                        "package name.",
-                        &options.private_symbols)
-          .OptionalFlag("--custom-package", "Custom Java package under which to generate R.java.",
-                        &options.custom_java_package)
-          .OptionalFlagList("--extra-packages",
-                            "Generate the same R.java but with different package names.",
-                            &extra_java_packages)
-          .OptionalFlagList("--add-javadoc-annotation",
-                            "Adds a JavaDoc annotation to all generated Java classes.",
-                            &options.javadoc_annotations)
-          .OptionalFlag("--output-text-symbols",
-                        "Generates a text file containing the resource symbols of the R class in\n"
-                        "the specified folder.",
-                        &options.generate_text_symbols_path)
-          .OptionalSwitch("--allow-reserved-package-id",
-                          "Allows the use of a reserved package ID. This should on be used for\n"
-                          "packages with a pre-O min-sdk\n",
-                          &options.allow_reserved_package_id)
-          .OptionalSwitch("--auto-add-overlay",
-                          "Allows the addition of new resources in overlays without\n"
-                          "<add-resource> tags.",
-                          &options.auto_add_overlay)
-          .OptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.",
-                        &options.manifest_fixer_options.rename_manifest_package)
-          .OptionalFlag("--rename-instrumentation-target-package",
-                        "Changes the name of the target package for instrumentation. Most useful\n"
-                        "when used in conjunction with --rename-manifest-package.",
-                        &options.manifest_fixer_options.rename_instrumentation_target_package)
-          .OptionalFlagList("-0", "File extensions not to compress.",
-                            &options.extensions_to_not_compress)
-          .OptionalSwitch("--no-compress", "Do not compress any resources.",
-                          &options.do_not_compress_anything)
-          .OptionalSwitch("--warn-manifest-validation",
-                          "Treat manifest validation errors as warnings.",
-                          &options.manifest_fixer_options.warn_validation)
-          .OptionalFlagList("--split",
-                            "Split resources matching a set of configs out to a Split APK.\n"
-                            "Syntax: path/to/output.apk:<config>[,<config>[...]].\n"
-                            "On Windows, use a semicolon ';' separator instead.",
-                            &split_args)
-          .OptionalSwitch("-v", "Enables verbose logging.", &verbose)
-          .OptionalSwitch("--debug-mode",
-                          "Inserts android:debuggable=\"true\" in to the application node of the\n"
-                          "manifest, making the application debuggable even on production devices.",
-                          &options.manifest_fixer_options.debug_mode)
-          .OptionalSwitch("--strict-visibility",
-                          "Do not allow overlays with different visibility levels.",
-                          &options.strict_visibility);
-
-  if (!flags.Parse("aapt2 link", args, &std::cerr)) {
-    return 1;
-  }
+int LinkCommand::Action(const std::vector<std::string>& args) {
+  LinkContext context(diag_);
 
   // Expand all argument-files passed into the command line. These start with '@'.
   std::vector<std::string> arg_list;
-  for (const std::string& arg : flags.GetArgs()) {
+  for (const std::string& arg : args) {
     if (util::StartsWith(arg, "@")) {
       const std::string path = arg.substr(1, arg.size() - 1);
       std::string error;
@@ -2244,27 +2013,27 @@
   }
 
   // Expand all argument-files passed to -R.
-  for (const std::string& arg : overlay_arg_list) {
+  for (const std::string& arg : overlay_arg_list_) {
     if (util::StartsWith(arg, "@")) {
       const std::string path = arg.substr(1, arg.size() - 1);
       std::string error;
-      if (!file::AppendArgsFromFile(path, &options.overlay_files, &error)) {
+      if (!file::AppendArgsFromFile(path, &options_.overlay_files, &error)) {
         context.GetDiagnostics()->Error(DiagMessage(path) << error);
         return 1;
       }
     } else {
-      options.overlay_files.push_back(arg);
+      options_.overlay_files.push_back(arg);
     }
   }
 
-  if (verbose) {
-    context.SetVerbose(verbose);
+  if (verbose_) {
+    context.SetVerbose(verbose_);
   }
 
-  if (int{shared_lib} + int{static_lib} + int{proto_format} > 1) {
+  if (int{shared_lib_} + int{static_lib_} + int{proto_format_} > 1) {
     context.GetDiagnostics()->Error(
         DiagMessage()
-        << "only one of --shared-lib, --static-lib, or --proto_format can be defined");
+            << "only one of --shared-lib, --static-lib, or --proto_format can be defined");
     return 1;
   }
 
@@ -2272,35 +2041,26 @@
   context.SetPackageType(PackageType::kApp);
   context.SetPackageId(kAppPackageId);
 
-  if (shared_lib) {
+  if (shared_lib_) {
     context.SetPackageType(PackageType::kSharedLib);
     context.SetPackageId(0x00);
-  } else if (static_lib) {
+  } else if (static_lib_) {
     context.SetPackageType(PackageType::kStaticLib);
-    options.output_format = OutputFormat::kProto;
-  } else if (proto_format) {
-    options.output_format = OutputFormat::kProto;
+    options_.output_format = OutputFormat::kProto;
+  } else if (proto_format_) {
+    options_.output_format = OutputFormat::kProto;
   }
 
-  if (options.auto_namespace_static_lib) {
-    if (!static_lib) {
-      context.GetDiagnostics()->Error(
-          DiagMessage() << "--auto-namespace-static-lib can only be used with --static-lib");
-      return 1;
-    }
-    context.SetAutoNamespace(true);
-  }
-
-  if (package_id) {
+  if (package_id_) {
     if (context.GetPackageType() != PackageType::kApp) {
       context.GetDiagnostics()->Error(
           DiagMessage() << "can't specify --package-id when not building a regular app");
       return 1;
     }
 
-    const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id.value());
+    const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id_.value());
     if (!maybe_package_id_int) {
-      context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id.value()
+      context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id_.value()
                                                     << "' is not a valid integer");
       return 1;
     }
@@ -2308,7 +2068,7 @@
     const uint32_t package_id_int = maybe_package_id_int.value();
     if (package_id_int > std::numeric_limits<uint8_t>::max()
         || package_id_int == kFrameworkPackageId
-        || (!options.allow_reserved_package_id && package_id_int < kAppPackageId)) {
+        || (!options_.allow_reserved_package_id && package_id_int < kAppPackageId)) {
       context.GetDiagnostics()->Error(
           DiagMessage() << StringPrintf(
               "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int));
@@ -2318,71 +2078,71 @@
   }
 
   // Populate the set of extra packages for which to generate R.java.
-  for (std::string& extra_package : extra_java_packages) {
+  for (std::string& extra_package : extra_java_packages_) {
     // A given package can actually be a colon separated list of packages.
     for (StringPiece package : util::Split(extra_package, ':')) {
-      options.extra_java_packages.insert(package.to_string());
+      options_.extra_java_packages.insert(package.to_string());
     }
   }
 
-  if (product_list) {
-    for (StringPiece product : util::Tokenize(product_list.value(), ',')) {
+  if (product_list_) {
+    for (StringPiece product : util::Tokenize(product_list_.value(), ',')) {
       if (product != "" && product != "default") {
-        options.products.insert(product.to_string());
+        options_.products.insert(product.to_string());
       }
     }
   }
 
   std::unique_ptr<IConfigFilter> filter;
-  if (!configs.empty()) {
-    filter = ParseConfigFilterParameters(configs, context.GetDiagnostics());
+  if (!configs_.empty()) {
+    filter = ParseConfigFilterParameters(configs_, context.GetDiagnostics());
     if (filter == nullptr) {
       return 1;
     }
-    options.table_splitter_options.config_filter = filter.get();
+    options_.table_splitter_options.config_filter = filter.get();
   }
 
-  if (preferred_density) {
+  if (preferred_density_) {
     Maybe<uint16_t> density =
-        ParseTargetDensityParameter(preferred_density.value(), context.GetDiagnostics());
+        ParseTargetDensityParameter(preferred_density_.value(), context.GetDiagnostics());
     if (!density) {
       return 1;
     }
-    options.table_splitter_options.preferred_densities.push_back(density.value());
+    options_.table_splitter_options.preferred_densities.push_back(density.value());
   }
 
   // Parse the split parameters.
-  for (const std::string& split_arg : split_args) {
-    options.split_paths.push_back({});
-    options.split_constraints.push_back({});
-    if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options.split_paths.back(),
-                             &options.split_constraints.back())) {
+  for (const std::string& split_arg : split_args_) {
+    options_.split_paths.push_back({});
+    options_.split_constraints.push_back({});
+    if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options_.split_paths.back(),
+        &options_.split_constraints.back())) {
       return 1;
     }
   }
 
-  if (context.GetPackageType() != PackageType::kStaticLib && stable_id_file_path) {
-    if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(),
-                         &options.stable_id_map)) {
+  if (context.GetPackageType() != PackageType::kStaticLib && stable_id_file_path_) {
+    if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path_.value(),
+        &options_.stable_id_map)) {
       return 1;
     }
   }
 
   // Populate some default no-compress extensions that are already compressed.
-  options.extensions_to_not_compress.insert(
+  options_.extensions_to_not_compress.insert(
       {".jpg",   ".jpeg", ".png",  ".gif", ".wav",  ".mp2",  ".mp3",  ".ogg",
-       ".aac",   ".mpg",  ".mpeg", ".mid", ".midi", ".smf",  ".jet",  ".rtttl",
-       ".imy",   ".xmf",  ".mp4",  ".m4a", ".m4v",  ".3gp",  ".3gpp", ".3g2",
-       ".3gpp2", ".amr",  ".awb",  ".wma", ".wmv",  ".webm", ".mkv"});
+          ".aac",   ".mpg",  ".mpeg", ".mid", ".midi", ".smf",  ".jet",  ".rtttl",
+          ".imy",   ".xmf",  ".mp4",  ".m4a", ".m4v",  ".3gp",  ".3gpp", ".3g2",
+          ".3gpp2", ".amr",  ".awb",  ".wma", ".wmv",  ".webm", ".mkv"});
 
   // Turn off auto versioning for static-libs.
   if (context.GetPackageType() == PackageType::kStaticLib) {
-    options.no_auto_version = true;
-    options.no_version_vectors = true;
-    options.no_version_transitions = true;
+    options_.no_auto_version = true;
+    options_.no_version_vectors = true;
+    options_.no_version_transitions = true;
   }
 
-  LinkCommand cmd(&context, options);
+  Linker cmd(&context, options_);
   return cmd.Run(arg_list);
 }
 
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
new file mode 100644
index 0000000..e58a93e
--- /dev/null
+++ b/tools/aapt2/cmd/Link.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT2_LINK_H
+#define AAPT2_LINK_H
+
+#include "Command.h"
+#include "Diagnostics.h"
+#include "Resource.h"
+#include "split/TableSplitter.h"
+#include "format/binary/TableFlattener.h"
+#include "link/ManifestFixer.h"
+
+namespace aapt {
+
+enum class OutputFormat {
+  kApk,
+  kProto,
+};
+
+struct LinkOptions {
+  std::string output_path;
+  std::string manifest_path;
+  std::vector<std::string> include_paths;
+  std::vector<std::string> overlay_files;
+  std::vector<std::string> assets_dirs;
+  bool output_to_directory = false;
+  bool auto_add_overlay = false;
+  OutputFormat output_format = OutputFormat::kApk;
+
+  // Java/Proguard options.
+  Maybe<std::string> generate_java_class_path;
+  Maybe<std::string> custom_java_package;
+  std::set<std::string> extra_java_packages;
+  Maybe<std::string> generate_text_symbols_path;
+  Maybe<std::string> generate_proguard_rules_path;
+  Maybe<std::string> generate_main_dex_proguard_rules_path;
+  bool generate_conditional_proguard_rules = false;
+  bool generate_non_final_ids = false;
+  std::vector<std::string> javadoc_annotations;
+  Maybe<std::string> private_symbols;
+
+  // Optimizations/features.
+  bool no_auto_version = false;
+  bool no_version_vectors = false;
+  bool no_version_transitions = false;
+  bool no_resource_deduping = false;
+  bool no_xml_namespaces = false;
+  bool do_not_compress_anything = false;
+  std::unordered_set<std::string> extensions_to_not_compress;
+
+  // Static lib options.
+  bool no_static_lib_packages = false;
+
+  // AndroidManifest.xml massaging options.
+  ManifestFixerOptions manifest_fixer_options;
+
+  // Products to use/filter on.
+  std::unordered_set<std::string> products;
+
+  // Flattening options.
+  TableFlattenerOptions table_flattener_options;
+
+  // Split APK options.
+  TableSplitterOptions table_splitter_options;
+  std::vector<SplitConstraints> split_constraints;
+  std::vector<std::string> split_paths;
+
+  // Stable ID options.
+  std::unordered_map<ResourceName, ResourceId> stable_id_map;
+  Maybe<std::string> resource_id_map_path;
+
+  // When 'true', allow reserved package IDs to be used for applications. Pre-O, the platform
+  // treats negative resource IDs [those with a package ID of 0x80 or higher] as invalid.
+  // In order to work around this limitation, we allow the use of traditionally reserved
+  // resource IDs [those between 0x02 and 0x7E].
+  bool allow_reserved_package_id = false;
+
+  // Whether we should fail on definitions of a resource with conflicting visibility.
+  bool strict_visibility = false;
+};
+
+class LinkCommand : public Command {
+ public:
+  explicit LinkCommand(IDiagnostics* diag) : Command("link", "l"),
+                                             diag_(diag) {
+    SetDescription("Links resources into an apk.");
+    AddRequiredFlag("-o", "Output path.", &options_.output_path);
+    AddRequiredFlag("--manifest", "Path to the Android manifest to build.",
+        &options_.manifest_path);
+    AddOptionalFlagList("-I", "Adds an Android APK to link against.", &options_.include_paths);
+    AddOptionalFlagList("-A", "An assets directory to include in the APK. These are unprocessed.",
+        &options_.assets_dirs);
+    AddOptionalFlagList("-R", "Compilation unit to link, using `overlay` semantics.\n"
+        "The last conflicting resource given takes precedence.", &overlay_arg_list_);
+    AddOptionalFlag("--package-id",
+        "Specify the package ID to use for this app. Must be greater or equal to\n"
+            "0x7f and can't be used with --static-lib or --shared-lib.", &package_id_);
+    AddOptionalFlag("--java", "Directory in which to generate R.java.",
+        &options_.generate_java_class_path);
+    AddOptionalFlag("--proguard", "Output file for generated Proguard rules.",
+        &options_.generate_proguard_rules_path);
+    AddOptionalFlag("--proguard-main-dex",
+        "Output file for generated Proguard rules for the main dex.",
+        &options_.generate_main_dex_proguard_rules_path);
+    AddOptionalSwitch("--proguard-conditional-keep-rules",
+        "Generate conditional Proguard keep rules.",
+        &options_.generate_conditional_proguard_rules);
+    AddOptionalSwitch("--no-auto-version", "Disables automatic style and layout SDK versioning.",
+        &options_.no_auto_version);
+    AddOptionalSwitch("--no-version-vectors",
+        "Disables automatic versioning of vector drawables. Use this only\n"
+            "when building with vector drawable support library.",
+        &options_.no_version_vectors);
+    AddOptionalSwitch("--no-version-transitions",
+        "Disables automatic versioning of transition resources. Use this only\n"
+            "when building with transition support library.",
+        &options_.no_version_transitions);
+    AddOptionalSwitch("--no-resource-deduping", "Disables automatic deduping of resources with\n"
+            "identical values across compatible configurations.",
+        &options_.no_resource_deduping);
+    AddOptionalSwitch("--enable-sparse-encoding",
+        "This decreases APK size at the cost of resource retrieval performance.",
+        &options_.table_flattener_options.use_sparse_entries);
+    AddOptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.",
+        &legacy_x_flag_);
+    AddOptionalSwitch("-z", "Require localization of strings marked 'suggested'.",
+        &require_localization_);
+    AddOptionalFlagList("-c",
+        "Comma separated list of configurations to include. The default\n"
+            "is all configurations.", &configs_);
+    AddOptionalFlag("--preferred-density",
+        "Selects the closest matching density and strips out all others.",
+        &preferred_density_);
+    AddOptionalFlag("--product", "Comma separated list of product names to keep", &product_list_);
+    AddOptionalSwitch("--output-to-dir", "Outputs the APK contents to a directory specified by -o.",
+        &options_.output_to_directory);
+    AddOptionalSwitch("--no-xml-namespaces", "Removes XML namespace prefix and URI information\n"
+            "from AndroidManifest.xml and XML binaries in res/*.",
+        &options_.no_xml_namespaces);
+    AddOptionalFlag("--min-sdk-version",
+        "Default minimum SDK version to use for AndroidManifest.xml.",
+        &options_.manifest_fixer_options.min_sdk_version_default);
+    AddOptionalFlag("--target-sdk-version",
+        "Default target SDK version to use for AndroidManifest.xml.",
+        &options_.manifest_fixer_options.target_sdk_version_default);
+    AddOptionalFlag("--version-code",
+        "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
+            "present.", &options_.manifest_fixer_options.version_code_default);
+    AddOptionalFlag("--version-code-major",
+        "Version code major (integer) to inject into the AndroidManifest.xml if none is\n"
+            "present.", &options_.manifest_fixer_options.version_code_major_default);
+    AddOptionalFlag("--version-name",
+        "Version name to inject into the AndroidManifest.xml if none is present.",
+        &options_.manifest_fixer_options.version_name_default);
+    AddOptionalSwitch("--replace-version",
+        "If --version-code and/or --version-name are specified, these\n"
+            "values will replace any value already in the manifest. By\n"
+            "default, nothing is changed if the manifest already defines\n"
+            "these attributes.",
+        &options_.manifest_fixer_options.replace_version);
+    AddOptionalFlag("--compile-sdk-version-code",
+        "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
+            "present.",
+        &options_.manifest_fixer_options.compile_sdk_version);
+    AddOptionalFlag("--compile-sdk-version-name",
+        "Version name to inject into the AndroidManifest.xml if none is present.",
+        &options_.manifest_fixer_options.compile_sdk_version_codename);
+    AddOptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
+        &shared_lib_);
+    AddOptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib_);
+    AddOptionalSwitch("--proto-format",
+        "Generates compiled resources in Protobuf format.\n"
+            "Suitable as input to the bundle tool for generating an App Bundle.",
+        &proto_format_);
+    AddOptionalSwitch("--no-static-lib-packages",
+        "Merge all library resources under the app's package.",
+        &options_.no_static_lib_packages);
+    AddOptionalSwitch("--non-final-ids",
+        "Generates R.java without the final modifier. This is implied when\n"
+            "--static-lib is specified.",
+        &options_.generate_non_final_ids);
+    AddOptionalFlag("--stable-ids", "File containing a list of name to ID mapping.",
+        &stable_id_file_path_);
+    AddOptionalFlag("--emit-ids",
+        "Emit a file at the given path with a list of name to ID mappings,\n"
+            "suitable for use with --stable-ids.",
+        &options_.resource_id_map_path);
+    AddOptionalFlag("--private-symbols",
+        "Package name to use when generating R.java for private symbols.\n"
+            "If not specified, public and private symbols will use the application's\n"
+            "package name.",
+        &options_.private_symbols);
+    AddOptionalFlag("--custom-package", "Custom Java package under which to generate R.java.",
+        &options_.custom_java_package);
+    AddOptionalFlagList("--extra-packages",
+        "Generate the same R.java but with different package names.",
+        &extra_java_packages_);
+    AddOptionalFlagList("--add-javadoc-annotation",
+        "Adds a JavaDoc annotation to all generated Java classes.",
+        &options_.javadoc_annotations);
+    AddOptionalFlag("--output-text-symbols",
+        "Generates a text file containing the resource symbols of the R class in\n"
+            "the specified folder.",
+        &options_.generate_text_symbols_path);
+    AddOptionalSwitch("--allow-reserved-package-id",
+        "Allows the use of a reserved package ID. This should on be used for\n"
+            "packages with a pre-O min-sdk\n",
+        &options_.allow_reserved_package_id);
+    AddOptionalSwitch("--auto-add-overlay",
+        "Allows the addition of new resources in overlays without\n"
+            "<add-resource> tags.",
+        &options_.auto_add_overlay);
+    AddOptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.",
+        &options_.manifest_fixer_options.rename_manifest_package);
+    AddOptionalFlag("--rename-instrumentation-target-package",
+        "Changes the name of the target package for instrumentation. Most useful\n"
+            "when used in conjunction with --rename-manifest-package.",
+        &options_.manifest_fixer_options.rename_instrumentation_target_package);
+    AddOptionalFlagList("-0", "File extensions not to compress.",
+        &options_.extensions_to_not_compress);
+    AddOptionalSwitch("--no-compress", "Do not compress any resources.",
+        &options_.do_not_compress_anything);
+    AddOptionalSwitch("--warn-manifest-validation",
+        "Treat manifest validation errors as warnings.",
+        &options_.manifest_fixer_options.warn_validation);
+    AddOptionalFlagList("--split",
+        "Split resources matching a set of configs out to a Split APK.\n"
+            "Syntax: path/to/output.apk:<config>[,<config>[...]].\n"
+            "On Windows, use a semicolon ';' separator instead.",
+        &split_args_);
+    AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
+    AddOptionalSwitch("--debug-mode",
+        "Inserts android:debuggable=\"true\" in to the application node of the\n"
+            "manifest, making the application debuggable even on production devices.",
+        &options_.manifest_fixer_options.debug_mode);
+    AddOptionalSwitch("--strict-visibility",
+        "Do not allow overlays with different visibility levels.",
+        &options_.strict_visibility);
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  IDiagnostics* diag_;
+  LinkOptions options_;
+
+  std::vector<std::string> overlay_arg_list_;
+  std::vector<std::string> extra_java_packages_;
+  Maybe<std::string> package_id_;
+  std::vector<std::string> configs_;
+  Maybe<std::string> preferred_density_;
+  Maybe<std::string> product_list_;
+  bool legacy_x_flag_ = false;
+  bool require_localization_ = false;
+  bool verbose_ = false;
+  bool shared_lib_ = false;
+  bool static_lib_ = false;
+  bool proto_format_ = false;
+  Maybe<std::string> stable_id_file_path_;
+  std::vector<std::string> split_args_;
+};
+
+}// namespace aapt
+
+#endif //AAPT2_LINK_H
\ No newline at end of file
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp
index 4afa8f0..47288ec 100644
--- a/tools/aapt2/cmd/Optimize.cpp
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "Optimize.h"
+
 #include <memory>
 #include <vector>
 
@@ -24,7 +26,6 @@
 #include "androidfw/StringPiece.h"
 
 #include "Diagnostics.h"
-#include "Flags.h"
 #include "LoadedApk.h"
 #include "ResourceUtils.h"
 #include "SdkConstants.h"
@@ -54,36 +55,6 @@
 
 namespace aapt {
 
-struct OptimizeOptions {
-  // Path to the output APK.
-  Maybe<std::string> output_path;
-  // Path to the output APK directory for splits.
-  Maybe<std::string> output_dir;
-
-  // Details of the app extracted from the AndroidManifest.xml
-  AppInfo app_info;
-
-  // Blacklist of unused resources that should be removed from the apk.
-  std::unordered_set<ResourceName> resources_blacklist;
-
-  // Split APK options.
-  TableSplitterOptions table_splitter_options;
-
-  // List of output split paths. These are in the same order as `split_constraints`.
-  std::vector<std::string> split_paths;
-
-  // List of SplitConstraints governing what resources go into each split. Ordered by `split_paths`.
-  std::vector<SplitConstraints> split_constraints;
-
-  TableFlattenerOptions table_flattener_options;
-
-  Maybe<std::vector<OutputArtifact>> apk_artifacts;
-
-  // Set of artifacts to keep when generating multi-APK splits. If the list is empty, all artifacts
-  // are kept and will be written as output.
-  std::unordered_set<std::string> kept_artifacts;
-};
-
 class OptimizeContext : public IAaptContext {
  public:
   OptimizeContext() = default;
@@ -133,10 +104,6 @@
     return sdk_version_;
   }
 
-  bool IsAutoNamespace() override {
-    return false;
-  }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(OptimizeContext);
 
@@ -145,9 +112,9 @@
   int sdk_version_ = 0;
 };
 
-class OptimizeCommand {
+class Optimizer {
  public:
-  OptimizeCommand(OptimizeContext* context, const OptimizeOptions& options)
+  Optimizer(OptimizeContext* context, const OptimizeOptions& options)
       : options_(options), context_(context) {
   }
 
@@ -378,82 +345,24 @@
   return true;
 }
 
-int Optimize(const std::vector<StringPiece>& args) {
-  OptimizeContext context;
-  OptimizeOptions options;
-  Maybe<std::string> config_path;
-  Maybe<std::string> whitelist_path;
-  Maybe<std::string> resources_config_path;
-  Maybe<std::string> target_densities;
-  std::vector<std::string> configs;
-  std::vector<std::string> split_args;
-  std::unordered_set<std::string> kept_artifacts;
-  bool verbose = false;
-  bool print_only = false;
-  Flags flags =
-      Flags()
-          .OptionalFlag("-o", "Path to the output APK.", &options.output_path)
-          .OptionalFlag("-d", "Path to the output directory (for splits).", &options.output_dir)
-          .OptionalFlag("-x", "Path to XML configuration file.", &config_path)
-          .OptionalSwitch("-p", "Print the multi APK artifacts and exit.", &print_only)
-          .OptionalFlag(
-              "--target-densities",
-              "Comma separated list of the screen densities that the APK will be optimized for.\n"
-              "All the resources that would be unused on devices of the given densities will be \n"
-              "removed from the APK.",
-              &target_densities)
-          .OptionalFlag("--whitelist-path",
-                        "Path to the whitelist.cfg file containing whitelisted resources \n"
-                        "whose names should not be altered in final resource tables.",
-                        &whitelist_path)
-          .OptionalFlag("--resources-config-path",
-                        "Path to the resources.cfg file containing the list of resources and \n"
-                        "directives to each resource. \n"
-                        "Format: type/resource_name#[directive][,directive]",
-                        &resources_config_path)
-          .OptionalFlagList("-c",
-                            "Comma separated list of configurations to include. The default\n"
-                            "is all configurations.",
-                            &configs)
-          .OptionalFlagList("--split",
-                            "Split resources matching a set of configs out to a "
-                            "Split APK.\nSyntax: path/to/output.apk;<config>[,<config>[...]].\n"
-                            "On Windows, use a semicolon ';' separator instead.",
-                            &split_args)
-          .OptionalFlagList("--keep-artifacts",
-                            "Comma separated list of artifacts to keep. If none are specified,\n"
-                            "all artifacts will be kept.",
-                            &kept_artifacts)
-          .OptionalSwitch("--enable-sparse-encoding",
-                          "Enables encoding sparse entries using a binary search tree.\n"
-                          "This decreases APK size at the cost of resource retrieval performance.",
-                          &options.table_flattener_options.use_sparse_entries)
-          .OptionalSwitch("--enable-resource-obfuscation",
-                          "Enables obfuscation of key string pool to single value",
-                          &options.table_flattener_options.collapse_key_stringpool)
-          .OptionalSwitch("-v", "Enables verbose logging", &verbose);
-
-  if (!flags.Parse("aapt2 optimize", args, &std::cerr)) {
-    return 1;
-  }
-
-  if (flags.GetArgs().size() != 1u) {
+int OptimizeCommand::Action(const std::vector<std::string>& args) {
+  if (args.size() != 1u) {
     std::cerr << "must have one APK as argument.\n\n";
-    flags.Usage("aapt2 optimize", &std::cerr);
+    Usage(&std::cerr);
     return 1;
   }
 
-  const std::string& apk_path = flags.GetArgs()[0];
-
-  context.SetVerbose(verbose);
+  const std::string& apk_path = args[0];
+  OptimizeContext context;
+  context.SetVerbose(verbose_);
   IDiagnostics* diag = context.GetDiagnostics();
 
-  if (config_path) {
-    std::string& path = config_path.value();
+  if (config_path_) {
+    std::string& path = config_path_.value();
     Maybe<ConfigurationParser> for_path = ConfigurationParser::ForPath(path);
     if (for_path) {
-      options.apk_artifacts = for_path.value().WithDiagnostics(diag).Parse(apk_path);
-      if (!options.apk_artifacts) {
+      options_.apk_artifacts = for_path.value().WithDiagnostics(diag).Parse(apk_path);
+      if (!options_.apk_artifacts) {
         diag->Error(DiagMessage() << "Failed to parse the output artifact list");
         return 1;
       }
@@ -463,28 +372,28 @@
       return 1;
     }
 
-    if (print_only) {
-      for (const OutputArtifact& artifact : options.apk_artifacts.value()) {
+    if (print_only_) {
+      for (const OutputArtifact& artifact : options_.apk_artifacts.value()) {
         std::cout << artifact.name << std::endl;
       }
       return 0;
     }
 
-    if (!kept_artifacts.empty()) {
-      for (const std::string& artifact_str : kept_artifacts) {
+    if (!kept_artifacts_.empty()) {
+      for (const std::string& artifact_str : kept_artifacts_) {
         for (const StringPiece& artifact : util::Tokenize(artifact_str, ',')) {
-          options.kept_artifacts.insert(artifact.to_string());
+          options_.kept_artifacts.insert(artifact.to_string());
         }
       }
     }
 
     // Since we know that we are going to process the APK (not just print targets), make sure we
     // have somewhere to write them to.
-    if (!options.output_dir) {
+    if (!options_.output_dir) {
       diag->Error(DiagMessage() << "Output directory is required when using a configuration file");
       return 1;
     }
-  } else if (print_only) {
+  } else if (print_only_) {
     diag->Error(DiagMessage() << "Asked to print artifacts without providing a configurations");
     return 1;
   }
@@ -494,57 +403,57 @@
     return 1;
   }
 
-  if (target_densities) {
+  if (target_densities_) {
     // Parse the target screen densities.
-    for (const StringPiece& config_str : util::Tokenize(target_densities.value(), ',')) {
+    for (const StringPiece& config_str : util::Tokenize(target_densities_.value(), ',')) {
       Maybe<uint16_t> target_density = ParseTargetDensityParameter(config_str, diag);
       if (!target_density) {
         return 1;
       }
-      options.table_splitter_options.preferred_densities.push_back(target_density.value());
+      options_.table_splitter_options.preferred_densities.push_back(target_density.value());
     }
   }
 
   std::unique_ptr<IConfigFilter> filter;
-  if (!configs.empty()) {
-    filter = ParseConfigFilterParameters(configs, diag);
+  if (!configs_.empty()) {
+    filter = ParseConfigFilterParameters(configs_, diag);
     if (filter == nullptr) {
       return 1;
     }
-    options.table_splitter_options.config_filter = filter.get();
+    options_.table_splitter_options.config_filter = filter.get();
   }
 
   // Parse the split parameters.
-  for (const std::string& split_arg : split_args) {
-    options.split_paths.emplace_back();
-    options.split_constraints.emplace_back();
-    if (!ParseSplitParameter(split_arg, diag, &options.split_paths.back(),
-                             &options.split_constraints.back())) {
+  for (const std::string& split_arg : split_args_) {
+    options_.split_paths.emplace_back();
+    options_.split_constraints.emplace_back();
+    if (!ParseSplitParameter(split_arg, diag, &options_.split_paths.back(),
+        &options_.split_constraints.back())) {
       return 1;
     }
   }
 
-  if (options.table_flattener_options.collapse_key_stringpool) {
-    if (whitelist_path) {
-      std::string& path = whitelist_path.value();
-      if (!ExtractObfuscationWhitelistFromConfig(path, &context, &options)) {
+  if (options_.table_flattener_options.collapse_key_stringpool) {
+    if (whitelist_path_) {
+      std::string& path = whitelist_path_.value();
+      if (!ExtractObfuscationWhitelistFromConfig(path, &context, &options_)) {
         return 1;
       }
     }
   }
 
-  if (resources_config_path) {
-    std::string& path = resources_config_path.value();
-    if (!ExtractConfig(path, &context, &options)) {
+  if (resources_config_path_) {
+    std::string& path = resources_config_path_.value();
+    if (!ExtractConfig(path, &context, &options_)) {
       return 1;
     }
   }
 
-  if (!ExtractAppDataFromManifest(&context, apk.get(), &options)) {
+  if (!ExtractAppDataFromManifest(&context, apk.get(), &options_)) {
     return 1;
   }
 
-  OptimizeCommand cmd(&context, options);
+  Optimizer cmd(&context, options_);
   return cmd.Run(std::move(apk));
 }
 
diff --git a/tools/aapt2/cmd/Optimize.h b/tools/aapt2/cmd/Optimize.h
new file mode 100644
index 0000000..43bc216
--- /dev/null
+++ b/tools/aapt2/cmd/Optimize.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT2_OPTIMIZE_H
+#define AAPT2_OPTIMIZE_H
+
+#include "AppInfo.h"
+#include "Command.h"
+#include "configuration/ConfigurationParser.h"
+#include "format/binary/TableFlattener.h"
+#include "split/TableSplitter.h"
+
+namespace aapt {
+
+struct OptimizeOptions {
+  friend class OptimizeCommand;
+
+  // Path to the output APK.
+  Maybe<std::string> output_path;
+  // Path to the output APK directory for splits.
+  Maybe<std::string> output_dir;
+
+  // Details of the app extracted from the AndroidManifest.xml
+  AppInfo app_info;
+
+  // Blacklist of unused resources that should be removed from the apk.
+  std::unordered_set<ResourceName> resources_blacklist;
+
+  // Split APK options.
+  TableSplitterOptions table_splitter_options;
+
+  // List of output split paths. These are in the same order as `split_constraints`.
+  std::vector<std::string> split_paths;
+
+  // List of SplitConstraints governing what resources go into each split. Ordered by `split_paths`.
+  std::vector<SplitConstraints> split_constraints;
+
+  TableFlattenerOptions table_flattener_options;
+
+  Maybe<std::vector<aapt::configuration::OutputArtifact>> apk_artifacts;
+
+  // Set of artifacts to keep when generating multi-APK splits. If the list is empty, all artifacts
+  // are kept and will be written as output.
+  std::unordered_set<std::string> kept_artifacts;
+};
+
+class OptimizeCommand : public Command {
+ public:
+  explicit OptimizeCommand() : Command("optimize") {
+    SetDescription("Preforms resource optimizations on an apk.");
+    AddOptionalFlag("-o", "Path to the output APK.", &options_.output_path);
+    AddOptionalFlag("-d", "Path to the output directory (for splits).", &options_.output_dir);
+    AddOptionalFlag("-x", "Path to XML configuration file.", &config_path_);
+    AddOptionalSwitch("-p", "Print the multi APK artifacts and exit.", &print_only_);
+    AddOptionalFlag(
+        "--target-densities",
+        "Comma separated list of the screen densities that the APK will be optimized for.\n"
+            "All the resources that would be unused on devices of the given densities will be \n"
+            "removed from the APK.",
+        &target_densities_);
+    AddOptionalFlag("--whitelist-path",
+        "Path to the whitelist.cfg file containing whitelisted resources \n"
+            "whose names should not be altered in final resource tables.",
+        &whitelist_path_);
+    AddOptionalFlag("--resources-config-path",
+        "Path to the resources.cfg file containing the list of resources and \n"
+            "directives to each resource. \n"
+            "Format: type/resource_name#[directive][,directive]",
+        &resources_config_path_);
+    AddOptionalFlagList("-c",
+        "Comma separated list of configurations to include. The default\n"
+            "is all configurations.",
+        &configs_);
+    AddOptionalFlagList("--split",
+        "Split resources matching a set of configs out to a "
+            "Split APK.\nSyntax: path/to/output.apk;<config>[,<config>[...]].\n"
+            "On Windows, use a semicolon ';' separator instead.",
+        &split_args_);
+    AddOptionalFlagList("--keep-artifacts",
+        "Comma separated list of artifacts to keep. If none are specified,\n"
+            "all artifacts will be kept.",
+        &kept_artifacts_);
+    AddOptionalSwitch("--enable-sparse-encoding",
+        "Enables encoding sparse entries using a binary search tree.\n"
+            "This decreases APK size at the cost of resource retrieval performance.",
+        &options_.table_flattener_options.use_sparse_entries);
+    AddOptionalSwitch("--enable-resource-obfuscation",
+        "Enables obfuscation of key string pool to single value",
+        &options_.table_flattener_options.collapse_key_stringpool);
+    AddOptionalSwitch("-v", "Enables verbose logging", &verbose_);
+  }
+
+  int Action(const std::vector<std::string>& args) override;
+
+ private:
+  OptimizeOptions options_;
+
+  Maybe<std::string> config_path_;
+  Maybe<std::string> whitelist_path_;
+  Maybe<std::string> resources_config_path_;
+  Maybe<std::string> target_densities_;
+  std::vector<std::string> configs_;
+  std::vector<std::string> split_args_;
+  std::unordered_set<std::string> kept_artifacts_;
+  bool print_only_ = false;
+  bool verbose_ = false;
+};
+
+}// namespace aapt
+
+#endif //AAPT2_OPTIMIZE_H
\ No newline at end of file
diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp
index 4e77e9a..c6c82b0 100644
--- a/tools/aapt2/cmd/Util.cpp
+++ b/tools/aapt2/cmd/Util.cpp
@@ -29,6 +29,7 @@
 #include "util/Util.h"
 
 using ::android::StringPiece;
+using ::android::base::StringPrintf;
 
 namespace aapt {
 
@@ -168,6 +169,7 @@
 std::unique_ptr<xml::XmlResource> GenerateSplitManifest(const AppInfo& app_info,
                                                         const SplitConstraints& constraints) {
   const ResourceId kVersionCode(0x0101021b);
+  const ResourceId kVersionCodeMajor(0x01010576);
   const ResourceId kRevisionCode(0x010104d5);
   const ResourceId kHasCode(0x0101000c);
 
@@ -184,6 +186,14 @@
         util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_DEC, version_code)});
   }
 
+  if (app_info.version_code_major) {
+    const uint32_t version_code_major = app_info.version_code_major.value();
+    manifest_el->attributes.push_back(xml::Attribute{
+        xml::kSchemaAndroid, "versionCodeMajor", std::to_string(version_code_major),
+        CreateAttributeWithId(kVersionCodeMajor),
+        util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_DEC, version_code_major)});
+  }
+
   if (app_info.revision_code) {
     const uint32_t revision_code = app_info.revision_code.value();
     manifest_el->attributes.push_back(xml::Attribute{
@@ -355,6 +365,17 @@
     app_info.version_code = maybe_code.value();
   }
 
+  if (const xml::Attribute* version_code_major_attr =
+      manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor")) {
+    Maybe<uint32_t> maybe_code = ExtractCompiledInt(*version_code_major_attr, &error_msg);
+    if (!maybe_code) {
+      diag->Error(DiagMessage(xml_res.file.source.WithLine(manifest_el->line_number))
+                      << "invalid android:versionCodeMajor: " << error_msg);
+      return {};
+    }
+    app_info.version_code_major = maybe_code.value();
+  }
+
   if (const xml::Attribute* revision_code_attr =
           manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode")) {
     Maybe<uint32_t> maybe_code = ExtractCompiledInt(*revision_code_attr, &error_msg);
@@ -391,4 +412,21 @@
   return app_info;
 }
 
+void SetLongVersionCode(xml::Element* manifest, uint64_t version) {
+  // Write the low bits of the version code to android:versionCode
+  auto version_code = manifest->FindOrCreateAttribute(xml::kSchemaAndroid, "versionCode");
+  version_code->value = StringPrintf("0x%08x", (uint32_t) (version & 0xffffffff));
+  version_code->compiled_value = ResourceUtils::TryParseInt(version_code->value);
+
+  auto version_high = (uint32_t) (version >> 32);
+  if (version_high != 0) {
+    // Write the high bits of the version code to android:versionCodeMajor
+    auto version_major = manifest->FindOrCreateAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+    version_major->value = StringPrintf("0x%08x", version_high);
+    version_major->compiled_value = ResourceUtils::TryParseInt(version_major->value);
+  } else {
+    manifest->RemoveAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  }
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/cmd/Util.h b/tools/aapt2/cmd/Util.h
index fb8753e..cf1443e 100644
--- a/tools/aapt2/cmd/Util.h
+++ b/tools/aapt2/cmd/Util.h
@@ -67,6 +67,11 @@
 // checks this at runtime.
 std::string MakePackageSafeName(const std::string &name);
 
+// Sets the versionCode and versionCodeMajor attributes to the version code. Attempts to encode the
+// version code using the versionCode attribute only, and encodes using both versionCode and
+// versionCodeMajor if the version code requires more than 32 bits.
+void SetLongVersionCode(xml::Element* manifest, uint64_t version_code);
+
 }  // namespace aapt
 
 #endif /* AAPT_SPLIT_UTIL_H */
diff --git a/tools/aapt2/cmd/Util_test.cpp b/tools/aapt2/cmd/Util_test.cpp
index 0c527f6..b9fb5b2 100644
--- a/tools/aapt2/cmd/Util_test.cpp
+++ b/tools/aapt2/cmd/Util_test.cpp
@@ -18,6 +18,7 @@
 
 #include "AppInfo.h"
 #include "split/TableSplitter.h"
+#include "test/Builders.h"
 #include "test/Test.h"
 
 namespace aapt {
@@ -36,4 +37,51 @@
     EXPECT_EQ(root->FindAttribute("", "targetConfig")->value, "b+sr+Latn,en-rUS-land");
 }
 
+TEST (UtilTest, LongVersionCodeDefined) {
+  auto doc = test::BuildXmlDom(R"(
+      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.aapt.test" android:versionCode="0x1" android:versionCodeMajor="0x1">
+      </manifest>)");
+  SetLongVersionCode(doc->root.get(), 42);
+
+  auto version_code = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
+  ASSERT_NE(version_code, nullptr);
+  EXPECT_EQ(version_code->value, "0x0000002a");
+
+  ASSERT_NE(version_code->compiled_value, nullptr);
+  auto compiled_version_code = ValueCast<BinaryPrimitive>(version_code->compiled_value.get());
+  ASSERT_NE(compiled_version_code, nullptr);
+  EXPECT_EQ(compiled_version_code->value.data, 42U);
+
+  auto version_code_major = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  EXPECT_EQ(version_code_major, nullptr);
+}
+
+TEST (UtilTest, LongVersionCodeUndefined) {
+  auto doc = test::BuildXmlDom(R"(
+        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.aapt.test">
+        </manifest>)");
+  SetLongVersionCode(doc->root.get(), 420000000000);
+
+  auto version_code = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
+  ASSERT_NE(version_code, nullptr);
+  EXPECT_EQ(version_code->value, "0xc9f36800");
+
+  ASSERT_NE(version_code->compiled_value, nullptr);
+  auto compiled_version_code = ValueCast<BinaryPrimitive>(version_code->compiled_value.get());
+  ASSERT_NE(compiled_version_code, nullptr);
+  EXPECT_EQ(compiled_version_code->value.data, 0xc9f36800);
+
+  auto version_code_major = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  ASSERT_NE(version_code_major, nullptr);
+  EXPECT_EQ(version_code_major->value, "0x00000061");
+
+  ASSERT_NE(version_code_major->compiled_value, nullptr);
+  auto compiled_version_code_major = ValueCast<BinaryPrimitive>(
+      version_code_major->compiled_value.get());
+  ASSERT_NE(compiled_version_code_major, nullptr);
+  EXPECT_EQ(compiled_version_code_major->value.data, 0x61);
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp
index febbb2e..ccaea4e 100644
--- a/tools/aapt2/configuration/ConfigurationParser_test.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp
@@ -703,35 +703,24 @@
 }
 
 TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_NonNumeric) {
-  static constexpr const char* xml = R"xml(
+  auto doc = test::BuildXmlDom(R"xml(
       <android-sdk
-          label="P"
+          label="Q"
           minSdkVersion="25"
-          targetSdkVersion="%s"
-          maxSdkVersion="%s">
-      </android-sdk>)xml";
-
-  const auto& dev_sdk = GetDevelopmentSdkCodeNameAndVersion();
-  const char* codename = dev_sdk.first.data();
-  const ApiVersion& version = dev_sdk.second;
-
-  auto doc = test::BuildXmlDom(StringPrintf(xml, codename, codename));
+          targetSdkVersion="Q"
+          maxSdkVersion="Q">
+      </android-sdk>)xml");
 
   PostProcessingConfiguration config;
-  bool ok = AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
-  ASSERT_TRUE(ok);
-
+  ASSERT_TRUE(AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_));
   ASSERT_EQ(1ul, config.android_sdks.size());
-  ASSERT_EQ(1u, config.android_sdks.count("P"));
-
-  auto& out = config.android_sdks["P"];
+  ASSERT_EQ(1u, config.android_sdks.count("Q"));
 
   AndroidSdk sdk;
   sdk.min_sdk_version = 25;
-  sdk.target_sdk_version = version;
-  sdk.max_sdk_version = version;
-
-  ASSERT_EQ(sdk, out);
+  sdk.target_sdk_version = 10000;
+  sdk.max_sdk_version = 10000;
+  ASSERT_EQ(sdk, config.android_sdks["Q"]);
 }
 
 TEST_F(ConfigurationParserTest, GlTextureGroupAction) {
diff --git a/tools/aapt2/format/Container.cpp b/tools/aapt2/format/Container.cpp
index 739555c..d4b4571 100644
--- a/tools/aapt2/format/Container.cpp
+++ b/tools/aapt2/format/Container.cpp
@@ -270,7 +270,8 @@
   }
 
   if (magic != kContainerFormatMagic) {
-    error_ = "magic value doesn't match AAPT";
+    error_ =
+        StringPrintf("magic value is 0x%08x but AAPT expects 0x%08x", magic, kContainerFormatMagic);
     return;
   }
 
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index 8215ddf..3a39a6b 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -338,10 +338,13 @@
 
   const std::string type_str = util::GetString(type_pool_, type->id - 1);
 
-  const ResourceType* parsed_type = ParseResourceType(type_str);
-  if (!parsed_type) {
-    diag_->Error(DiagMessage(source_)
-                 << "invalid type name '" << type_str << "' for type with ID " << (int)type->id);
+  // Be lenient on the name of the type if the table is lenient on resource validation.
+  auto parsed_type = ResourceType::kUnknown;
+  if (const ResourceType* parsed = ParseResourceType(type_str)) {
+    parsed_type = *parsed;
+  } else if (table_->GetValidateResources()) {
+    diag_->Error(DiagMessage(source_) << "invalid type name '" << type_str << "' for type with ID "
+                                      << (int) type->id);
     return false;
   }
 
@@ -352,7 +355,7 @@
       continue;
     }
 
-    const ResourceName name(package->name, *parsed_type,
+    const ResourceName name(package->name, parsed_type,
                             util::GetString(key_pool_, util::DeviceToHost32(entry->key.index)));
 
     const ResourceId res_id(package->id.value(), type->id, static_cast<uint16_t>(it.index()));
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 6fd4c8d..8641a7c 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -133,11 +133,10 @@
   }
 
   void Visit(Array* array) override {
-    for (auto& item : array->elements) {
-      ResTable_map* out_entry = buffer_->NextBlock<ResTable_map>();
-      FlattenValue(item.get(), out_entry);
-      out_entry->value.size = util::HostToDevice16(sizeof(out_entry->value));
-      entry_count_++;
+    const size_t count = array->elements.size();
+    for (size_t i = 0; i < count; i++) {
+      Reference key(android::ResTable_map::ATTR_MIN + i);
+      FlattenEntry(&key, array->elements[i].get());
     }
   }
 
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index bab7010..af19b98 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -17,7 +17,9 @@
 #include "format/binary/TableFlattener.h"
 
 #include "android-base/stringprintf.h"
+#include "androidfw/TypeWrappers.h"
 
+#include "ResChunkPullParser.h"
 #include "ResourceUtils.h"
 #include "SdkConstants.h"
 #include "format/binary/BinaryResourceParser.h"
@@ -236,6 +238,62 @@
   EXPECT_EQ(attr.max_int, actual_attr->max_int);
 }
 
+TEST_F(TableFlattenerTest, FlattenArray) {
+  auto array = util::make_unique<Array>();
+  array->elements.push_back(util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC),
+                                                               1u));
+  array->elements.push_back(util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC),
+                                                               2u));
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .SetPackageId("android", 0x01)
+          .AddValue("android:array/foo", ResourceId(0x01010000), std::move(array))
+          .Build();
+
+  std::string result;
+  ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &result));
+
+  // Parse the flattened resource table
+  ResChunkPullParser parser(result.data(), result.size());
+  ASSERT_TRUE(parser.IsGoodEvent(parser.Next()));
+  ASSERT_EQ(util::DeviceToHost16(parser.chunk()->type), RES_TABLE_TYPE);
+
+  // Retrieve the package of the entry
+  ResChunkPullParser table_parser(GetChunkData(parser.chunk()), GetChunkDataLen(parser.chunk()));
+  const ResChunk_header* package_chunk = nullptr;
+  while (table_parser.IsGoodEvent(table_parser.Next())) {
+    if (util::DeviceToHost16(table_parser.chunk()->type) == RES_TABLE_PACKAGE_TYPE) {
+      package_chunk = table_parser.chunk();
+      break;
+    }
+  }
+
+  // Retrieve the type that proceeds the array entry
+  ASSERT_NE(package_chunk, nullptr);
+  ResChunkPullParser package_parser(GetChunkData(table_parser.chunk()),
+                                    GetChunkDataLen(table_parser.chunk()));
+  const ResChunk_header* type_chunk = nullptr;
+  while (package_parser.IsGoodEvent(package_parser.Next())) {
+    if (util::DeviceToHost16(package_parser.chunk()->type) == RES_TABLE_TYPE_TYPE) {
+      type_chunk = package_parser.chunk();
+      break;
+    }
+  }
+
+  // Retrieve the array entry
+  ASSERT_NE(type_chunk, nullptr);
+  TypeVariant typeVariant((const ResTable_type*) type_chunk);
+  auto entry = (const ResTable_map_entry*)*typeVariant.beginEntries();
+  ASSERT_EQ(util::DeviceToHost16(entry->count), 2u);
+
+  // Check that the value and name of the array entries are correct
+  auto values = (const ResTable_map*)(((const uint8_t *)entry) + entry->size);
+  ASSERT_EQ(values->value.data, 1u);
+  ASSERT_EQ(values->name.ident, android::ResTable_map::ATTR_MIN);
+  ASSERT_EQ((values+1)->value.data, 2u);
+  ASSERT_EQ((values+1)->name.ident, android::ResTable_map::ATTR_MIN + 1);
+}
+
 static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
     IAaptContext* context, const ConfigDescription& sparse_config, float load) {
   std::unique_ptr<ResourceTable> table =
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/Android.mk b/tools/aapt2/integration-tests/AutoNamespaceTest/Android.mk
deleted file mode 100644
index 5d7a6f7..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/Android.mk b/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/Android.mk
deleted file mode 100644
index 91716b9..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE := AaptTestAutoNamespace_LibOne
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_AAPT_NAMESPACES := true
-LOCAL_AAPT_FLAGS := --auto-namespace-static-lib
-# We need this to compile the Java sources of AaptTestStaticLib_LibTwo using javac.
-LOCAL_JAR_EXCLUDE_FILES := none
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/AndroidManifest.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/AndroidManifest.xml
deleted file mode 100644
index f585840..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/AndroidManifest.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest package="com.example.android.aapt2.autonamespace.staticlib.one" />
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/res/values/values.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/res/values/values.xml
deleted file mode 100644
index 3e57b0f..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/res/values/values.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-    <!-- An attribute from StaticLibOne -->
-    <attr name="StaticLibOne_attr" format="string" />
-
-    <string name="Foo">Foo</string>
-
-    <declare-styleable name="Widget">
-        <attr name="StaticLibOne_attr" />
-        <attr name="android:text" />
-    </declare-styleable>
-</resources>
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/src/com/example/android/aapt2/autonamespace/staticlib/one/StaticLibOne.java b/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/src/com/example/android/aapt2/autonamespace/staticlib/one/StaticLibOne.java
deleted file mode 100644
index 886d48c..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/src/com/example/android/aapt2/autonamespace/staticlib/one/StaticLibOne.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.example.android.aapt2.autonamespace.staticlib.one;
-
-public class StaticLibOne { public static int FooId = R.string.Foo; }
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/Android.mk
deleted file mode 100644
index c85496d..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE := AaptTestAutoNamespace_LibTwo
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := AaptTestAutoNamespace_LibOne
-LOCAL_AAPT_NAMESPACES := true
-LOCAL_AAPT_FLAGS := --auto-namespace-static-lib
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/AndroidManifest.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/AndroidManifest.xml
deleted file mode 100644
index 8d3c506..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/AndroidManifest.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest package="com.example.android.aapt2.autonamespace.staticlib.two" />
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/layout/layout_two.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/layout/layout_two.xml
deleted file mode 100644
index fb20220..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/layout/layout_two.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<View xmlns:custom="http://schemas.android.com/apk/res-auto"
-      custom:StaticLibOne_attr="@string/FooBar" />
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/values/values.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/values/values.xml
deleted file mode 100644
index c532387..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/values/values.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-    <string name="FooBar">@string/Foo</string>
-</resources>
diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/src/com/example/android/aapt2/autonamespace/staticlib/two/StaticLibTwo.java b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/src/com/example/android/aapt2/autonamespace/staticlib/two/StaticLibTwo.java
deleted file mode 100644
index 323f53a..0000000
--- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/src/com/example/android/aapt2/autonamespace/staticlib/two/StaticLibTwo.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.example.android.aapt2.autonamespace.staticlib.two;
-
-public class StaticLibTwo {
-  // IDs from StaticLibOne
-  public static int FooId = com.example.android.aapt2.autonamespace.staticlib.one.R.string.Foo;
-
-  // IDs from StaticLibTwo
-  public static int FooBarId = R.string.FooBar;
-  public static int LayoutId = R.layout.layout_two;
-}
diff --git a/tools/aapt2/integration-tests/CompileTest/DirInput/res/drawable/image.png b/tools/aapt2/integration-tests/CompileTest/DirInput/res/drawable/image.png
new file mode 100644
index 0000000..1a3731b
--- /dev/null
+++ b/tools/aapt2/integration-tests/CompileTest/DirInput/res/drawable/image.png
Binary files differ
diff --git a/tools/aapt2/integration-tests/CompileTest/DirInput/res/layout/layout.xml b/tools/aapt2/integration-tests/CompileTest/DirInput/res/layout/layout.xml
new file mode 100644
index 0000000..e5835ed
--- /dev/null
+++ b/tools/aapt2/integration-tests/CompileTest/DirInput/res/layout/layout.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
diff --git a/tools/aapt2/integration-tests/CompileTest/DirInput/res/values/values.xml b/tools/aapt2/integration-tests/CompileTest/DirInput/res/values/values.xml
new file mode 100644
index 0000000..62ab652
--- /dev/null
+++ b/tools/aapt2/integration-tests/CompileTest/DirInput/res/values/values.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+</resources>
\ No newline at end of file
diff --git a/tools/aapt2/integration-tests/CompileTest/ZipInput/res.zip b/tools/aapt2/integration-tests/CompileTest/ZipInput/res.zip
new file mode 100644
index 0000000..00e396d
--- /dev/null
+++ b/tools/aapt2/integration-tests/CompileTest/ZipInput/res.zip
Binary files differ
diff --git a/tools/aapt2/io/FileSystem.cpp b/tools/aapt2/io/FileSystem.cpp
index 1387d22..16a20f4c 100644
--- a/tools/aapt2/io/FileSystem.cpp
+++ b/tools/aapt2/io/FileSystem.cpp
@@ -16,6 +16,9 @@
 
 #include "io/FileSystem.h"
 
+#include <dirent.h>
+
+#include "android-base/errors.h"
 #include "androidfw/StringPiece.h"
 #include "utils/FileMap.h"
 
@@ -26,6 +29,7 @@
 #include "util/Util.h"
 
 using ::android::StringPiece;
+using ::android::base::SystemErrorCodeToString;
 
 namespace aapt {
 namespace io {
@@ -64,6 +68,50 @@
   return result;
 }
 
+std::unique_ptr<FileCollection> FileCollection::Create(const android::StringPiece& root,
+                                                        std::string* outError) {
+  std::unique_ptr<FileCollection> collection =
+      std::unique_ptr<FileCollection>(new FileCollection());
+
+  std::unique_ptr<DIR, decltype(closedir) *> d(opendir(root.data()), closedir);
+  if (!d) {
+    *outError = "failed to open directory: " + SystemErrorCodeToString(errno);
+    return nullptr;
+  }
+
+  while (struct dirent *entry = readdir(d.get())) {
+    std::string prefix_path = root.to_string();
+    file::AppendPath(&prefix_path, entry->d_name);
+
+    // The directory to iterate over looking for files
+    if (file::GetFileType(prefix_path) != file::FileType::kDirectory
+        || file::IsHidden(prefix_path)) {
+      continue;
+    }
+
+    std::unique_ptr<DIR, decltype(closedir)*> subdir(opendir(prefix_path.data()), closedir);
+    if (!subdir) {
+      *outError = "failed to open directory: " + SystemErrorCodeToString(errno);
+      return nullptr;
+    }
+
+    while (struct dirent* leaf_entry = readdir(subdir.get())) {
+      std::string full_path = prefix_path;
+      file::AppendPath(&full_path, leaf_entry->d_name);
+
+      // Do not add folders to the file collection
+      if (file::GetFileType(full_path) == file::FileType::kDirectory
+          || file::IsHidden(full_path)) {
+        continue;
+      }
+
+      collection->InsertFile(full_path);
+    }
+  }
+
+  return collection;
+}
+
 IFile* FileCollection::InsertFile(const StringPiece& path) {
   return (files_[path.to_string()] = util::make_unique<RegularFile>(Source(path))).get();
 }
diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h
index 6be8807..fb6bf6e 100644
--- a/tools/aapt2/io/FileSystem.h
+++ b/tools/aapt2/io/FileSystem.h
@@ -59,6 +59,10 @@
  public:
   FileCollection() = default;
 
+  /** Creates a file collection containing all files contained in the specified root directory. */
+  static std::unique_ptr<FileCollection> Create(const android::StringPiece& path,
+                                                std::string* outError);
+
   // Adds a file located at path. Returns the IFile representation of that file.
   IFile* InsertFile(const android::StringPiece& path);
   IFile* FindFile(const android::StringPiece& path) override;
diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp
index 269b6c5..8e6d713 100644
--- a/tools/aapt2/io/ZipArchive.cpp
+++ b/tools/aapt2/io/ZipArchive.cpp
@@ -20,6 +20,7 @@
 #include "ziparchive/zip_archive.h"
 
 #include "Source.h"
+#include "util/Files.h"
 #include "util/Util.h"
 
 using ::android::StringPiece;
@@ -121,9 +122,14 @@
     std::string zip_entry_path =
         std::string(reinterpret_cast<const char*>(zip_entry_name.name),
                     zip_entry_name.name_length);
-    std::string nested_path = path.to_string() + "@" + zip_entry_path;
-    std::unique_ptr<IFile> file =
-        util::make_unique<ZipFile>(collection->handle_, zip_data, Source(nested_path));
+
+    // Do not add folders to the file collection
+    if (util::EndsWith(zip_entry_path, "/")) {
+      continue;
+    }
+
+    std::unique_ptr<IFile> file = util::make_unique<ZipFile>(collection->handle_, zip_data,
+        Source(zip_entry_path, path.to_string()));
     collection->files_by_name_[zip_entry_path] = file.get();
     collection->files_.push_back(std::move(file));
   }
@@ -132,6 +138,7 @@
     if (out_error) *out_error = ErrorCodeString(result);
     return {};
   }
+
   return collection;
 }
 
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index db1561e..d1a70a7 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -256,9 +256,20 @@
     styleable_attr.field_name =
         TransformNestedAttr(attr.name.value(), array_field_name, package_name_to_generate);
 
+    Reference ref = attr;
+    if (attr.name.value().package.empty()) {
+
+      // If the resource does not have a package name, set the package to the unmangled package name
+      // of the styleable declaration because attributes without package names would have been
+      // declared in the same package as the styleable.
+      ref.name = ResourceName(package_name_to_generate, ref.name.value().type,
+                              ref.name.value().entry);
+    }
+
     // Look up the symbol so that we can write out in the comments what are possible legal values
     // for this attribute.
-    const SymbolTable::Symbol* symbol = context_->GetExternalSymbols()->FindByReference(attr);
+    const SymbolTable::Symbol* symbol = context_->GetExternalSymbols()->FindByReference(ref);
+
     if (symbol && symbol->attribute) {
       // Copy the symbol data structure because the returned instance can be destroyed.
       styleable_attr.symbol = *symbol;
@@ -303,7 +314,7 @@
       const ResourceName& attr_name = entry.attr_ref->name.value();
       styleable_comment << "<tr><td><code>{@link #" << entry.field_name << " "
                         << (!attr_name.package.empty() ? attr_name.package
-                                                       : context_->GetCompilationPackage())
+                                                       : package_name_to_generate)
                         << ":" << attr_name.entry << "}</code></td>";
 
       // Only use the comment up until the first '.'. This is to stay compatible with
@@ -374,7 +385,7 @@
 
       StringPiece package_name = attr_name.package;
       if (package_name.empty()) {
-        package_name = context_->GetCompilationPackage();
+        package_name = package_name_to_generate;
       }
 
       std::unique_ptr<IntMember> index_member =
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 10a97d8..fa208be 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -107,6 +107,55 @@
   EXPECT_THAT(output, Not(HasSubstr("com_foo$two")));
 }
 
+TEST(JavaClassGeneratorTest, StyleableAttributesWithDifferentPackageName) {
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .SetPackageId("android", 0x01)
+          .SetPackageId("app", 0x7f)
+          .AddValue("app:attr/foo", ResourceId(0x7f010000),
+                    test::AttributeBuilder().Build())
+          .AddValue("app:attr/bar", ResourceId(0x7f010001),
+                    test::AttributeBuilder().Build())
+          .AddValue("android:attr/baz", ResourceId(0x01010000),
+                    test::AttributeBuilder().Build())
+          .AddValue("app:styleable/MyStyleable", ResourceId(0x7f030000),
+                    test::StyleableBuilder()
+                        .AddItem("app:attr/foo", ResourceId(0x7f010000))
+                        .AddItem("attr/bar", ResourceId(0x7f010001))
+                        .AddItem("android:attr/baz", ResourceId(0x01010000))
+                        .Build())
+          .Build();
+
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder()
+          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+          .SetNameManglerPolicy(NameManglerPolicy{"custom"})
+          .SetCompilationPackage("custom")
+          .Build();
+  JavaClassGenerator generator(context.get(), table.get(), {});
+
+  std::string output;
+  StringOutputStream out(&output);
+  EXPECT_TRUE(generator.Generate("app", &out));
+  out.Flush();
+
+  EXPECT_THAT(output, Not(HasSubstr("public static final int baz=0x01010000;")));
+  EXPECT_THAT(output, HasSubstr("public static final int foo=0x7f010000;"));
+  EXPECT_THAT(output, HasSubstr("public static final int bar=0x7f010001;"));
+
+  EXPECT_THAT(output, HasSubstr("public static final int MyStyleable_android_baz=0;"));
+  EXPECT_THAT(output, HasSubstr("public static final int MyStyleable_foo=1;"));
+  EXPECT_THAT(output, HasSubstr("public static final int MyStyleable_bar=2;"));
+
+  EXPECT_THAT(output, HasSubstr("@link #MyStyleable_android_baz android:baz"));
+  EXPECT_THAT(output, HasSubstr("@link #MyStyleable_foo app:foo"));
+  EXPECT_THAT(output, HasSubstr("@link #MyStyleable_bar app:bar"));
+
+  EXPECT_THAT(output, HasSubstr("@link android.R.attr#baz"));
+  EXPECT_THAT(output, HasSubstr("@link app.R.attr#foo"));
+  EXPECT_THAT(output, HasSubstr("@link app.R.attr#bar"));
+}
+
 TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp
index d03cdb3..d40795a 100644
--- a/tools/aapt2/java/ProguardRules.cpp
+++ b/tools/aapt2/java/ProguardRules.cpp
@@ -39,7 +39,11 @@
  public:
   using xml::Visitor::Visit;
 
-  BaseVisitor(const ResourceFile& file, KeepSet* keep_set) : file_(file), keep_set_(keep_set) {
+  BaseVisitor(const ResourceFile& file, KeepSet* keep_set) : BaseVisitor(file, keep_set, "...") {
+  }
+
+  BaseVisitor(const ResourceFile& file, KeepSet* keep_set, const std::string& ctor_signature)
+      : file_(file), keep_set_(keep_set), ctor_signature_(ctor_signature) {
   }
 
   void Visit(xml::Element* node) override {
@@ -50,11 +54,11 @@
         // This is a custom view, let's figure out the class name from this.
         std::string package = maybe_package.value().package + "." + node->name;
         if (util::IsJavaClassName(package)) {
-          AddClass(node->line_number, package);
+          AddClass(node->line_number, package, ctor_signature_);
         }
       }
     } else if (util::IsJavaClassName(node->name)) {
-      AddClass(node->line_number, node->name);
+      AddClass(node->line_number, node->name, ctor_signature_);
     }
 
     for (const auto& child : node->children) {
@@ -74,9 +78,12 @@
  protected:
   ResourceFile file_;
   KeepSet* keep_set_;
+  std::string ctor_signature_;
 
-  virtual void AddClass(size_t line_number, const std::string& class_name) {
-    keep_set_->AddConditionalClass({file_.name, file_.source.WithLine(line_number)}, class_name);
+  virtual void AddClass(size_t line_number, const std::string& class_name,
+                        const std::string& ctor_signature) {
+    keep_set_->AddConditionalClass({file_.name, file_.source.WithLine(line_number)},
+        {class_name, ctor_signature});
   }
 
   void AddMethod(size_t line_number, const std::string& method_name,
@@ -102,31 +109,38 @@
 
 class LayoutVisitor : public BaseVisitor {
  public:
-  LayoutVisitor(const ResourceFile& file, KeepSet* keep_set) : BaseVisitor(file, keep_set) {
+  LayoutVisitor(const ResourceFile& file, KeepSet* keep_set)
+      : BaseVisitor(file, keep_set, "android.content.Context, android.util.AttributeSet") {
   }
 
   void Visit(xml::Element* node) override {
-    bool check_class = false;
-    bool check_name = false;
+    bool is_view = false;
+    bool is_fragment = false;
     if (node->namespace_uri.empty()) {
       if (node->name == "view") {
-        check_class = true;
+        is_view = true;
       } else if (node->name == "fragment") {
-        check_class = check_name = true;
+        is_fragment = true;
       }
     } else if (node->namespace_uri == xml::kSchemaAndroid) {
-      check_name = node->name == "fragment";
+      is_fragment = node->name == "fragment";
     }
 
     for (const auto& attr : node->attributes) {
-      if (check_class && attr.namespace_uri.empty() && attr.name == "class" &&
-          util::IsJavaClassName(attr.value)) {
-        AddClass(node->line_number, attr.value);
-      } else if (check_name && attr.namespace_uri == xml::kSchemaAndroid &&
-                 attr.name == "name" && util::IsJavaClassName(attr.value)) {
-        AddClass(node->line_number, attr.value);
-      } else if (attr.namespace_uri == xml::kSchemaAndroid &&
-                 attr.name == "onClick") {
+      if (attr.namespace_uri.empty() && attr.name == "class") {
+        if (util::IsJavaClassName(attr.value)) {
+          if (is_view) {
+            AddClass(node->line_number, attr.value,
+                "android.content.Context, android.util.AttributeSet");
+          } else if (is_fragment) {
+            AddClass(node->line_number, attr.value, "");
+          }
+        }
+      } else if (attr.namespace_uri == xml::kSchemaAndroid && attr.name == "name") {
+        if (is_fragment && util::IsJavaClassName(attr.value)) {
+          AddClass(node->line_number, attr.value, "");
+        }
+      } else if (attr.namespace_uri == xml::kSchemaAndroid && attr.name == "onClick") {
         AddMethod(node->line_number, attr.value, "android.view.View");
       }
     }
@@ -149,7 +163,7 @@
         if (attr.namespace_uri == xml::kSchemaAndroid) {
           if ((attr.name == "actionViewClass" || attr.name == "actionProviderClass") &&
               util::IsJavaClassName(attr.value)) {
-            AddClass(node->line_number, attr.value);
+            AddClass(node->line_number, attr.value, "android.content.Context");
           } else if (attr.name == "onClick") {
             AddMethod(node->line_number, attr.value, "android.view.MenuItem");
           }
@@ -180,7 +194,7 @@
       xml::Attribute* attr =
           node->FindAttribute(xml::kSchemaAndroid, "fragment");
       if (attr && util::IsJavaClassName(attr->value)) {
-        AddClass(node->line_number, attr->value);
+        AddClass(node->line_number, attr->value, "");
       }
     }
 
@@ -202,7 +216,7 @@
     if (attr != nullptr && !attr->value.empty()) {
       std::string name = (attr->value[0] == '.') ? package_ + attr->value : attr->value;
       if (util::IsJavaClassName(name)) {
-        AddClass(node->line_number, name);
+        AddClass(node->line_number, name, "...");
       }
     }
 
@@ -225,7 +239,8 @@
     if (check_class) {
       xml::Attribute* attr = node->FindAttribute({}, "class");
       if (attr && util::IsJavaClassName(attr->value)) {
-        AddClass(node->line_number, attr->value);
+        AddClass(node->line_number, attr->value,
+            "android.content.Context, android.util.AttributeSet");
       }
     }
 
@@ -256,7 +271,14 @@
         if (attr) {
           Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value);
           if (result) {
-            AddClass(node->line_number, result.value());
+            AddClass(node->line_number, result.value(), "");
+          }
+        }
+        attr = node->FindAttribute(xml::kSchemaAndroid, "appComponentFactory");
+        if (attr) {
+          Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value);
+          if (result) {
+            AddClass(node->line_number, result.value(), "");
           }
         }
         if (main_dex_only_) {
@@ -287,7 +309,7 @@
         if (get_name) {
           Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value);
           if (result) {
-            AddClass(node->line_number, result.value());
+            AddClass(node->line_number, result.value(), "");
           }
         }
       }
@@ -295,7 +317,8 @@
     BaseVisitor::Visit(node);
   }
 
-  virtual void AddClass(size_t line_number, const std::string& class_name) override {
+  virtual void AddClass(size_t line_number, const std::string& class_name,
+                        const std::string& ctor_signature) override {
     keep_set_->AddManifestClass({file_.name, file_.source.WithLine(line_number)}, class_name);
   }
 
@@ -383,13 +406,15 @@
         printer.Print("-if class **.R$layout { int ")
             .Print(JavaClassGenerator::TransformToFieldName(location.name.entry))
             .Println("; }");
-        printer.Print("-keep class ").Print(entry.first).Println(" { <init>(...); }");
+        printer.Print("-keep class ").Print(entry.first.name).Print(" { <init>(")
+            .Print(entry.first.signature).Println("); }");
       }
     } else {
       for (const UsageLocation& location : entry.second) {
         printer.Print("# Referenced at ").Println(location.source.to_string());
       }
-      printer.Print("-keep class ").Print(entry.first).Println(" { <init>(...); }");
+      printer.Print("-keep class ").Print(entry.first.name).Print(" { <init>(")
+          .Print(entry.first.signature).Println("); }");
     }
     printer.Println();
   }
diff --git a/tools/aapt2/java/ProguardRules.h b/tools/aapt2/java/ProguardRules.h
index acaceac..01dad0b 100644
--- a/tools/aapt2/java/ProguardRules.h
+++ b/tools/aapt2/java/ProguardRules.h
@@ -56,8 +56,9 @@
     manifest_class_set_[class_name].insert(file);
   }
 
-  inline void AddConditionalClass(const UsageLocation& file, const std::string& class_name) {
-    conditional_class_set_[class_name].insert(file);
+  inline void AddConditionalClass(const UsageLocation& file,
+                                  const NameAndSignature& class_and_signature) {
+    conditional_class_set_[class_and_signature].insert(file);
   }
 
   inline void AddMethod(const UsageLocation& file, const NameAndSignature& name_and_signature) {
@@ -77,7 +78,7 @@
   bool conditional_keep_rules_ = false;
   std::map<std::string, std::set<UsageLocation>> manifest_class_set_;
   std::map<NameAndSignature, std::set<UsageLocation>> method_set_;
-  std::map<std::string, std::set<UsageLocation>> conditional_class_set_;
+  std::map<NameAndSignature, std::set<UsageLocation>> conditional_class_set_;
   std::map<ResourceName, std::set<UsageLocation>> reference_set_;
 };
 
diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp
index b5e27e0..83c72d8 100644
--- a/tools/aapt2/java/ProguardRules_test.cpp
+++ b/tools/aapt2/java/ProguardRules_test.cpp
@@ -37,7 +37,11 @@
 TEST(ProguardRulesTest, ManifestRuleDefaultConstructorOnly) {
   std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android">
-        <application android:backupAgent="com.foo.BarBackupAgent">
+        <application
+            android:appComponentFactory="com.foo.BarAppComponentFactory"
+            android:backupAgent="com.foo.BarBackupAgent"
+            android:name="com.foo.BarApplication"
+            >
           <activity android:name="com.foo.BarActivity"/>
           <service android:name="com.foo.BarService"/>
           <receiver android:name="com.foo.BarReceiver"/>
@@ -51,7 +55,9 @@
 
   std::string actual = GetKeepSetString(set);
 
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarAppComponentFactory { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarBackupAgent { <init>(); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarApplication { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarActivity { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarService { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarReceiver { <init>(); }"));
@@ -71,7 +77,7 @@
 
   std::string actual = GetKeepSetString(set);
 
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
 }
 
 TEST(ProguardRulesTest, FragmentClassRuleIsEmitted) {
@@ -85,7 +91,7 @@
 
   std::string actual = GetKeepSetString(set);
 
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
 }
 
 TEST(ProguardRulesTest, FragmentNameAndClassRulesAreEmitted) {
@@ -101,8 +107,8 @@
 
   std::string actual = GetKeepSetString(set);
 
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(); }"));
 }
 
 TEST(ProguardRulesTest, NavigationFragmentNameAndClassRulesAreEmitted) {
@@ -146,7 +152,8 @@
 
   std::string actual = GetKeepSetString(set);
 
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr(
+      "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
 }
 
 TEST(ProguardRulesTest, IncludedLayoutRulesAreConditional) {
@@ -184,7 +191,8 @@
   std::string actual = GetKeepSetString(set);
 
   EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr(
+      "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
   EXPECT_THAT(actual, HasSubstr("int foo"));
   EXPECT_THAT(actual, HasSubstr("int bar"));
 }
@@ -203,7 +211,8 @@
 
   std::string actual = GetKeepSetString(set);
 
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr(
+      "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
   EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
   EXPECT_THAT(actual, HasSubstr("int foo"));
   EXPECT_THAT(actual, HasSubstr("int bar"));
@@ -224,7 +233,8 @@
   std::string actual = GetKeepSetString(set);
 
   EXPECT_THAT(actual, Not(HasSubstr("-if")));
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr(
+      "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
 }
 
 TEST(ProguardRulesTest, ViewOnClickRuleIsEmitted) {
@@ -261,8 +271,8 @@
 
   EXPECT_THAT(actual, HasSubstr(
       "-keepclassmembers class * { *** on_click(android.view.MenuItem); }"));
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(android.content.Context); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(android.content.Context); }"));
   EXPECT_THAT(actual, Not(HasSubstr("com.foo.Bat")));
 }
 
@@ -279,7 +289,8 @@
 
   std::string actual = GetKeepSetString(set);
 
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr(
+      "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
 }
 
 TEST(ProguardRulesTest, TransitionRulesAreEmitted) {
@@ -295,7 +306,8 @@
 
   std::string actual = GetKeepSetString(set);
 
-  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
+  EXPECT_THAT(actual, HasSubstr(
+      "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp
index ad5ad4c..ba9646f 100644
--- a/tools/aapt2/jni/aapt2_jni.cpp
+++ b/tools/aapt2/jni/aapt2_jni.cpp
@@ -25,15 +25,12 @@
 #include "ScopedUtfChars.h"
 
 #include "Diagnostics.h"
+#include "cmd/Compile.h"
+#include "cmd/Link.h"
 #include "util/Util.h"
 
 using android::StringPiece;
 
-namespace aapt {
-extern int Compile(const std::vector<StringPiece>& args, IDiagnostics* iDiagnostics);
-extern int Link(const std::vector<StringPiece>& args, IDiagnostics* iDiagnostics);
-}
-
 /*
  * Converts a java List<String> into C++ vector<ScopedUtfChars>.
  */
@@ -126,7 +123,7 @@
       list_to_utfchars(env, arguments_obj);
   std::vector<StringPiece> compile_args = extract_pieces(compile_args_jni);
   JniDiagnostics diagnostics(env, diagnostics_obj);
-  return aapt::Compile(compile_args, &diagnostics);
+  return aapt::CompileCommand(&diagnostics).Execute(compile_args, &std::cerr);
 }
 
 JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(JNIEnv* env,
@@ -137,7 +134,7 @@
       list_to_utfchars(env, arguments_obj);
   std::vector<StringPiece> link_args = extract_pieces(link_args_jni);
   JniDiagnostics diagnostics(env, diagnostics_obj);
-  return aapt::Link(link_args, &diagnostics);
+  return aapt::LinkCommand(&diagnostics).Execute(link_args, &std::cerr);
 }
 
 JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping(
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index ee4e702..c5c78d9 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -282,6 +282,17 @@
       }
     }
 
+    if (options_.version_code_major_default) {
+      if (options_.replace_version) {
+        el->RemoveAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+      }
+      if (el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor") == nullptr) {
+        el->attributes.push_back(
+            xml::Attribute{xml::kSchemaAndroid, "versionCodeMajor",
+                           options_.version_code_major_default.value()});
+      }
+    }
+
     if (el->FindAttribute("", "platformBuildVersionCode") == nullptr) {
       auto versionCode = el->FindAttribute(xml::kSchemaAndroid, "versionCode");
       if (versionCode != nullptr) {
@@ -346,6 +357,7 @@
   manifest_action["uses-permission"];
   manifest_action["uses-permission-sdk-23"];
   manifest_action["permission"];
+  manifest_action["permission"]["meta-data"] = meta_data_action;
   manifest_action["permission-tree"];
   manifest_action["permission-group"];
   manifest_action["uses-configuration"];
@@ -355,6 +367,8 @@
   manifest_action["compatible-screens"];
   manifest_action["compatible-screens"]["screen"];
   manifest_action["supports-gl-texture"];
+  manifest_action["restrict-update"];
+  manifest_action["package-verifier"];
   manifest_action["meta-data"] = meta_data_action;
   manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
 
@@ -376,6 +390,7 @@
   uses_static_library_action.Action(RequiredNameIsJavaPackage);
   uses_static_library_action.Action(RequiredAndroidAttribute("version"));
   uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
+  uses_static_library_action["additional-certificate"];
 
   if (options_.debug_mode) {
     application_action.Action([&](xml::Element* el) -> bool {
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 98d06fd..3ef57d0 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -52,6 +52,10 @@
   // replace_version is set.
   Maybe<std::string> version_code_default;
 
+  // The version code to set if 'android:versionCodeMajor' is not defined in <manifest> or if
+  // replace_version is set.
+  Maybe<std::string> version_code_major_default;
+
   // The version of the framework being compiled against to set for 'android:compileSdkVersion' in
   // the <manifest> tag.
   Maybe<std::string> compile_sdk_version;
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 5bc004d..adea627 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -329,6 +329,7 @@
   ManifestFixerOptions options;
   options.version_name_default = std::string("Beta");
   options.version_code_default = std::string("0x10000000");
+  options.version_code_major_default = std::string("0x20000000");
 
   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -347,136 +348,199 @@
   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
   ASSERT_THAT(attr, NotNull());
   EXPECT_THAT(attr->value, StrEq("0x10000000"));
+
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x20000000"));
 }
 
 TEST_F(ManifestFixerTest, DontUseDefaultVersionNameAndCode) {
-ManifestFixerOptions options;
-options.version_name_default = std::string("Beta");
-options.version_code_default = std::string("0x10000000");
+  ManifestFixerOptions options;
+  options.version_name_default = std::string("Beta");
+  options.version_code_default = std::string("0x10000000");
+  options.version_code_major_default = std::string("0x20000000");
 
-std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
-      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-                package="android"
-                android:versionCode="0x20000000"
-                android:versionName="Alpha" />)EOF",
-                                                          options);
-ASSERT_THAT(doc, NotNull());
+  std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                  package="android"
+                  android:versionCode="0x00000001"
+                  android:versionCodeMajor="0x00000002"
+                  android:versionName="Alpha" />)EOF",
+                                                            options);
+  ASSERT_THAT(doc, NotNull());
 
-xml::Element* manifest_el = doc->root.get();
-ASSERT_THAT(manifest_el, NotNull());
+  xml::Element* manifest_el = doc->root.get();
+  ASSERT_THAT(manifest_el, NotNull());
 
-xml::Attribute* attr =
-    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("Alpha"));
+  xml::Attribute* attr =
+      manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("Alpha"));
 
-attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("0x20000000"));
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x00000001"));
+
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x00000002"));
 }
 
 TEST_F(ManifestFixerTest, ReplaceVersionNameAndCode) {
-ManifestFixerOptions options;
-options.replace_version = true;
-options.version_name_default = std::string("Beta");
-options.version_code_default = std::string("0x10000000");
+  ManifestFixerOptions options;
+  options.replace_version = true;
+  options.version_name_default = std::string("Beta");
+  options.version_code_default = std::string("0x10000000");
+  options.version_code_major_default = std::string("0x20000000");
 
-std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
-    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-              package="android"
-              android:versionCode="0x20000000"
-              android:versionName="Alpha" />)EOF",
-                                                          options);
-ASSERT_THAT(doc, NotNull());
+  std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                package="android"
+                android:versionCode="0x00000001"
+                android:versionCodeMajor="0x00000002"
+                android:versionName="Alpha" />)EOF",
+                                                            options);
+  ASSERT_THAT(doc, NotNull());
 
-xml::Element* manifest_el = doc->root.get();
-ASSERT_THAT(manifest_el, NotNull());
+  xml::Element* manifest_el = doc->root.get();
+  ASSERT_THAT(manifest_el, NotNull());
 
-xml::Attribute* attr =
-    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("Beta"));
+  xml::Attribute* attr =
+      manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("Beta"));
 
-attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("0x10000000"));
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x10000000"));
+
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x20000000"));
 }
 
 TEST_F(ManifestFixerTest, ReplaceVersionName) {
-ManifestFixerOptions options;
-options.replace_version = true;
-options.version_name_default = std::string("Beta");
+  ManifestFixerOptions options;
+  options.replace_version = true;
+  options.version_name_default = std::string("Beta");
 
-std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
-  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-            package="android"
-            android:versionCode="0x20000000"
-            android:versionName="Alpha" />)EOF",
-                                                          options);
-ASSERT_THAT(doc, NotNull());
 
-xml::Element* manifest_el = doc->root.get();
-ASSERT_THAT(manifest_el, NotNull());
+  std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+              package="android"
+              android:versionCode="0x00000001"
+              android:versionCodeMajor="0x00000002"
+              android:versionName="Alpha" />)EOF",
+                                                            options);
+  ASSERT_THAT(doc, NotNull());
 
-xml::Attribute* attr =
-    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("Beta"));
+  xml::Element* manifest_el = doc->root.get();
+  ASSERT_THAT(manifest_el, NotNull());
 
-attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("0x20000000"));
+  xml::Attribute* attr =
+      manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("Beta"));
+
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x00000001"));
+
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x00000002"));
 }
 
 TEST_F(ManifestFixerTest, ReplaceVersionCode) {
-ManifestFixerOptions options;
-options.replace_version = true;
-options.version_code_default = std::string("0x10000000");
+  ManifestFixerOptions options;
+  options.replace_version = true;
+  options.version_code_default = std::string("0x10000000");
 
-std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+  std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+              package="android"
+              android:versionCode="0x00000001"
+              android:versionCodeMajor="0x00000002"
+              android:versionName="Alpha" />)EOF",
+                                                            options);
+  ASSERT_THAT(doc, NotNull());
+
+  xml::Element* manifest_el = doc->root.get();
+  ASSERT_THAT(manifest_el, NotNull());
+
+  xml::Attribute* attr =
+      manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("Alpha"));
+
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x10000000"));
+
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x00000002"));
+}
+
+TEST_F(ManifestFixerTest, ReplaceVersionCodeMajor) {
+  ManifestFixerOptions options;
+  options.replace_version = true;
+  options.version_code_major_default = std::string("0x20000000");
+
+  std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
   <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-            package="android"
-            android:versionCode="0x20000000"
-            android:versionName="Alpha" />)EOF",
-                                                          options);
-ASSERT_THAT(doc, NotNull());
+          package="android"
+          android:versionCode="0x00000001"
+          android:versionCodeMajor="0x00000002"
+          android:versionName="Alpha" />)EOF",
+                                                            options);
+  ASSERT_THAT(doc, NotNull());
 
-xml::Element* manifest_el = doc->root.get();
-ASSERT_THAT(manifest_el, NotNull());
+  xml::Element* manifest_el = doc->root.get();
+  ASSERT_THAT(manifest_el, NotNull());
 
-xml::Attribute* attr =
-    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("Alpha"));
+  xml::Attribute* attr =
+      manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("Alpha"));
 
-attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("0x10000000"));
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x00000001"));
+
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x20000000"));
 }
 
 TEST_F(ManifestFixerTest, DontReplaceVersionNameOrCode) {
-ManifestFixerOptions options;
-options.replace_version = true;
+  ManifestFixerOptions options;
+  options.replace_version = true;
 
-std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android"
-          android:versionCode="0x20000000"
-          android:versionName="Alpha" />)EOF",
-                                                          options);
-ASSERT_THAT(doc, NotNull());
+  std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+            package="android"
+            android:versionCode="0x00000001"
+            android:versionCodeMajor="0x00000002"
+            android:versionName="Alpha" />)EOF",
+                                                            options);
+  ASSERT_THAT(doc, NotNull());
 
-xml::Element* manifest_el = doc->root.get();
-ASSERT_THAT(manifest_el, NotNull());
+  xml::Element* manifest_el = doc->root.get();
+  ASSERT_THAT(manifest_el, NotNull());
 
-xml::Attribute* attr =
-    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("Alpha"));
+  xml::Attribute* attr =
+      manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("Alpha"));
 
-attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
-ASSERT_THAT(attr, NotNull());
-EXPECT_THAT(attr->value, StrEq("0x20000000"));
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x00000001"));
+
+  attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x00000002"));
 }
 
 TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index 28e71cc..3a5d585 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -80,7 +80,7 @@
 
       // Find the attribute in the symbol table and check if it is visible from this callsite.
       const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveAttributeCheckVisibility(
-          transformed_reference, callsite_, symbols_, context_->IsAutoNamespace(), &err_str);
+          transformed_reference, callsite_, symbols_, &err_str);
       if (symbol) {
         // Assign our style key the correct ID. The ID may not exist.
         entry.key.id = symbol->id;
@@ -202,18 +202,12 @@
 
 const SymbolTable::Symbol* ReferenceLinker::ResolveSymbol(const Reference& reference,
                                                           const CallSite& callsite,
-                                                          SymbolTable* symbols,
-                                                          bool auto_namespace) {
+                                                          SymbolTable* symbols) {
   if (reference.name) {
     const ResourceName& name = reference.name.value();
     if (name.package.empty()) {
       // Use the callsite's package name if no package name was defined.
-      const SymbolTable::Symbol* local_symbol =
-          symbols->FindByName(ResourceName(callsite.package, name.type, name.entry));
-      if (!auto_namespace || local_symbol) {
-        return local_symbol;
-      }
-      return symbols->FindByNameInAnyPackage(name);
+      return symbols->FindByName(ResourceName(callsite.package, name.type, name.entry));
     }
     return symbols->FindByName(name);
   } else if (reference.id) {
@@ -226,9 +220,8 @@
 const SymbolTable::Symbol* ReferenceLinker::ResolveSymbolCheckVisibility(const Reference& reference,
                                                                          const CallSite& callsite,
                                                                          SymbolTable* symbols,
-                                                                         bool auto_namespace,
                                                                          std::string* out_error) {
-  const SymbolTable::Symbol* symbol = ResolveSymbol(reference, callsite, symbols, auto_namespace);
+  const SymbolTable::Symbol* symbol = ResolveSymbol(reference, callsite, symbols);
   if (!symbol) {
     if (out_error) *out_error = "not found";
     return nullptr;
@@ -242,10 +235,10 @@
 }
 
 const SymbolTable::Symbol* ReferenceLinker::ResolveAttributeCheckVisibility(
-    const Reference& reference, const CallSite& callsite, SymbolTable* symbols, bool auto_namespace,
+    const Reference& reference, const CallSite& callsite, SymbolTable* symbols,
     std::string* out_error) {
   const SymbolTable::Symbol* symbol =
-      ResolveSymbolCheckVisibility(reference, callsite, symbols, auto_namespace, out_error);
+      ResolveSymbolCheckVisibility(reference, callsite, symbols, out_error);
   if (!symbol) {
     return nullptr;
   }
@@ -260,10 +253,9 @@
 Maybe<xml::AaptAttribute> ReferenceLinker::CompileXmlAttribute(const Reference& reference,
                                                                const CallSite& callsite,
                                                                SymbolTable* symbols,
-                                                               bool auto_namespace,
                                                                std::string* out_error) {
   const SymbolTable::Symbol* symbol =
-      ResolveAttributeCheckVisibility(reference, callsite, symbols, auto_namespace, out_error);
+      ResolveAttributeCheckVisibility(reference, callsite, symbols, out_error);
   if (!symbol) {
     return {};
   }
@@ -341,8 +333,8 @@
   xml::ResolvePackage(decls, &transformed_reference);
 
   std::string err_str;
-  const SymbolTable::Symbol* s = ResolveSymbolCheckVisibility(
-      transformed_reference, callsite, symbols, context->IsAutoNamespace(), &err_str);
+  const SymbolTable::Symbol* s =
+      ResolveSymbolCheckVisibility(transformed_reference, callsite, symbols, &err_str);
   if (s) {
     // The ID may not exist. This is fine because of the possibility of building
     // against libraries without assigned IDs.
diff --git a/tools/aapt2/link/ReferenceLinker.h b/tools/aapt2/link/ReferenceLinker.h
index 7887915..b0b4945 100644
--- a/tools/aapt2/link/ReferenceLinker.h
+++ b/tools/aapt2/link/ReferenceLinker.h
@@ -36,12 +36,10 @@
   ReferenceLinker() = default;
 
   // Performs name mangling and looks up the resource in the symbol table. Uses the callsite's
-  // package if the reference has no package name defined (implicit), or if auto_namespace is
-  // set try looking in all avaliable packages for a symbol of that name.
+  // package if the reference has no package name defined (implicit).
   // Returns nullptr if the symbol was not found.
   static const SymbolTable::Symbol* ResolveSymbol(const Reference& reference,
-                                                  const CallSite& callsite, SymbolTable* symbols,
-                                                  bool auto_namespace);
+                                                  const CallSite& callsite, SymbolTable* symbols);
 
   // Performs name mangling and looks up the resource in the symbol table. If the symbol is not
   // visible by the reference at the callsite, nullptr is returned.
@@ -49,7 +47,6 @@
   static const SymbolTable::Symbol* ResolveSymbolCheckVisibility(const Reference& reference,
                                                                  const CallSite& callsite,
                                                                  SymbolTable* symbols,
-                                                                 bool auto_namespace,
                                                                  std::string* out_error);
 
   // Same as ResolveSymbolCheckVisibility(), but also makes sure the symbol is an attribute.
@@ -57,14 +54,13 @@
   static const SymbolTable::Symbol* ResolveAttributeCheckVisibility(const Reference& reference,
                                                                     const CallSite& callsite,
                                                                     SymbolTable* symbols,
-                                                                    bool auto_namespace,
                                                                     std::string* out_error);
 
   // Resolves the attribute reference and returns an xml::AaptAttribute if successful.
   // If resolution fails, outError holds the error message.
   static Maybe<xml::AaptAttribute> CompileXmlAttribute(const Reference& reference,
                                                        const CallSite& callsite,
-                                                       SymbolTable* symbols, bool auto_namespace,
+                                                       SymbolTable* symbols,
                                                        std::string* out_error);
 
   // Writes the resource name to the DiagMessage, using the
diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp
index 0b7b1ce..be38b96 100644
--- a/tools/aapt2/link/ReferenceLinker_test.cpp
+++ b/tools/aapt2/link/ReferenceLinker_test.cpp
@@ -267,7 +267,7 @@
   std::string error;
   const CallSite call_site{"com.app.test"};
   const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveSymbolCheckVisibility(
-      *test::BuildReference("com.app.test:string/foo"), call_site, &table, false, &error);
+      *test::BuildReference("com.app.test:string/foo"), call_site, &table, &error);
   ASSERT_THAT(symbol, NotNull());
   EXPECT_TRUE(error.empty());
 }
@@ -285,13 +285,13 @@
   std::string error;
   const CallSite call_site{"com.app.ext"};
 
-  EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute(*test::BuildReference("com.app.test:attr/foo"),
-                                                    call_site, &table, false, &error));
+  EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute(
+      *test::BuildReference("com.app.test:attr/foo"), call_site, &table, &error));
   EXPECT_FALSE(error.empty());
 
   error = "";
   ASSERT_TRUE(ReferenceLinker::CompileXmlAttribute(
-      *test::BuildReference("com.app.test:attr/public_foo"), call_site, &table, false, &error));
+      *test::BuildReference("com.app.test:attr/public_foo"), call_site, &table, &error));
   EXPECT_TRUE(error.empty());
 }
 
@@ -303,74 +303,19 @@
                          .AddSymbol("com.app.lib:string/foo", ResourceId(0x7f010001))
                          .Build());
 
-  const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol(
-      *test::BuildReference("string/foo"), CallSite{"com.app.test"}, &table, false);
+  const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"),
+                                                                CallSite{"com.app.test"}, &table);
   ASSERT_THAT(s, NotNull());
   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010000)));
 
   s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), CallSite{"com.app.lib"},
-                                     &table, false);
+                                     &table);
   ASSERT_THAT(s, NotNull());
   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010001)));
 
   EXPECT_THAT(ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"),
-                                             CallSite{"com.app.bad"}, &table, false),
+                                             CallSite{"com.app.bad"}, &table),
               IsNull());
 }
 
-TEST(ReferenceLinkerTest, AutomaticNamespace) {
-  NameMangler mangler(NameManglerPolicy{"com.example.thislib"});
-  SymbolTable table(&mangler);
-  table.AppendSource(
-      test::StaticSymbolSourceBuilder()
-          .AddSymbol("com.example.thislib:string/thislib_string", ResourceId(0x7f010006))
-          .AddSymbol("com.example.thislib:string/explicit_override_string", ResourceId(0x7f010007))
-          .Build());
-  // Lib2 is higher priority than lib1
-  table.AppendSource(
-      test::StaticSymbolSourceBuilder()
-          .AddSymbol("com.example.lib2:string/lib2_string", ResourceId(0x7f010003))
-          .AddSymbol("com.example.lib2:string/explicit_override_string", ResourceId(0x7f010004))
-          .AddSymbol("com.example.lib2:string/implicit_override_string", ResourceId(0x7f010005))
-          .Build());
-  table.AppendSource(
-      test::StaticSymbolSourceBuilder()
-          .AddSymbol("com.example.lib1:string/explicit_override_string", ResourceId(0x7f010001))
-          .AddSymbol("com.example.lib1:string/implicit_override_string", ResourceId(0x7f010002))
-          .Build());
-
-  // Sanity test: Local references are still fine.
-  const SymbolTable::Symbol* s =
-      ReferenceLinker::ResolveSymbol(*test::BuildReference("string/thislib_string"),
-                                     CallSite{"com.example.thislib"}, &table, true);
-  ASSERT_THAT(s, NotNull());
-  EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010006)));
-
-  // Local references are fine, even if clash with remote ones.
-  s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/explicit_override_string"),
-                                     CallSite{"com.example.thislib"}, &table, true);
-  ASSERT_THAT(s, NotNull());
-  EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010007)));
-
-  // An unqualified reference to lib2 is rewritten
-  s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/lib2_string"),
-                                     CallSite{"com.example.thislib"}, &table, true);
-  ASSERT_THAT(s, NotNull());
-  EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010003)));
-
-  // Qualified references are left alone.
-  s = ReferenceLinker::ResolveSymbol(
-      *test::BuildReference("com.example.lib2:string/explicit_override_string"),
-      CallSite{"com.example.thislib"}, &table, true);
-  ASSERT_THAT(s, NotNull());
-  EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010004)));
-
-  // Implicit overrides respect priority ordering.
-  s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/implicit_override_string"),
-                                     CallSite{"com.example.thislib"}, &table, true);
-  ASSERT_THAT(s, NotNull());
-  EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010005)));
-
-  //
-}
 }  // namespace aapt
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 91a55b3..afb8ae0 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -281,8 +281,17 @@
           dst_config_value->value = std::move(new_file_ref);
 
         } else {
+          Maybe<std::string> original_comment = (dst_config_value->value)
+              ? dst_config_value->value->GetComment() : Maybe<std::string>();
+
           dst_config_value->value = std::unique_ptr<Value>(
               src_config_value->value->Clone(&master_table_->string_pool));
+
+          // Keep the comment from the original resource and ignore all comments from overlaying
+          // resources
+          if (overlay && original_comment) {
+            dst_config_value->value->SetComment(original_comment.value());
+          }
         }
       }
     }
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index cf504c4..79a734b 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -178,6 +178,49 @@
               Pointee(Field(&BinaryPrimitive::value, Field(&android::Res_value::data, Eq(0u)))));
 }
 
+TEST_F(TableMergerTest, DoNotOverrideResourceComment) {
+  std::unique_ptr<Value> foo_original = ResourceUtils::TryParseBool("true");
+  foo_original->SetComment(android::StringPiece("Original foo comment"));
+  std::unique_ptr<Value> bar_original = ResourceUtils::TryParseBool("true");
+
+  std::unique_ptr<Value> foo_overlay =  ResourceUtils::TryParseBool("false");
+  foo_overlay->SetComment(android::StringPiece("Overlay foo comment"));
+  std::unique_ptr<Value> bar_overlay =  ResourceUtils::TryParseBool("false");
+  bar_overlay->SetComment(android::StringPiece("Overlay bar comment"));
+  std::unique_ptr<Value> baz_overlay =  ResourceUtils::TryParseBool("false");
+  baz_overlay->SetComment(android::StringPiece("Overlay baz comment"));
+
+  std::unique_ptr<ResourceTable> base =
+      test::ResourceTableBuilder()
+          .SetPackageId("", 0x00)
+          .AddValue("bool/foo", std::move(foo_original))
+          .AddValue("bool/bar", std::move(bar_original))
+          .Build();
+
+  std::unique_ptr<ResourceTable> overlay =
+      test::ResourceTableBuilder()
+          .SetPackageId("", 0x00)
+          .AddValue("bool/foo", std::move(foo_overlay))
+          .AddValue("bool/bar", std::move(bar_overlay))
+          .AddValue("bool/baz", std::move(baz_overlay))
+          .Build();
+
+  ResourceTable final_table;
+  TableMergerOptions options;
+  options.auto_add_overlay = true;
+  TableMerger merger(context_.get(), &final_table, options);
+
+  ASSERT_TRUE(merger.Merge({}, base.get(), false /*overlay*/));
+  ASSERT_TRUE(merger.Merge({}, overlay.get(), true /*overlay*/));
+
+  BinaryPrimitive* foo = test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/foo");
+  EXPECT_THAT(foo, Pointee(Property(&BinaryPrimitive::GetComment, StrEq("Original foo comment"))));
+  BinaryPrimitive* bar = test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/bar");
+  EXPECT_THAT(bar, Pointee(Property(&BinaryPrimitive::GetComment, StrEq(""))));
+  BinaryPrimitive* baz = test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/baz");
+  EXPECT_THAT(baz, Pointee(Property(&BinaryPrimitive::GetComment, StrEq("Overlay baz comment"))));
+}
+
 TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
   std::unique_ptr<ResourceTable> base =
       test::ResourceTableBuilder()
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index 420a127..160ff92 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -97,8 +97,8 @@
         attr_ref.private_reference = maybe_package.value().private_namespace;
 
         std::string err_str;
-        attr.compiled_attribute = ReferenceLinker::CompileXmlAttribute(
-            attr_ref, callsite_, symbols_, context_->IsAutoNamespace(), &err_str);
+        attr.compiled_attribute =
+            ReferenceLinker::CompileXmlAttribute(attr_ref, callsite_, symbols_, &err_str);
 
         if (!attr.compiled_attribute) {
           DiagMessage error_msg(source);
diff --git a/tools/aapt2/link/XmlReferenceLinker_test.cpp b/tools/aapt2/link/XmlReferenceLinker_test.cpp
index d321f8f..ef99355 100644
--- a/tools/aapt2/link/XmlReferenceLinker_test.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker_test.cpp
@@ -18,7 +18,6 @@
 
 #include "test/Test.h"
 
-using ::testing::Eq;
 using ::testing::IsNull;
 using ::testing::NotNull;
 
@@ -71,29 +70,12 @@
                                                 .Build())
                            .AddPublicSymbol("com.app.test:attr/attr", ResourceId(0x7f010002),
                                             test::AttributeBuilder().Build())
-                           .AddPublicSymbol("com.app.lib:string/lib_string", ResourceId(0x7f020003))
                            .Build())
                    .Build();
-
-    auto_namespace_context_ =
-        test::ContextBuilder()
-            .SetCompilationPackage("com.app.test")
-            .SetNameManglerPolicy(NameManglerPolicy{"com.app.test", {"com.android.support"}})
-            .SetAutoNamespace(true)
-            .AddSymbolSource(
-                test::StaticSymbolSourceBuilder()
-                    .AddPublicSymbol("android:attr/text", ResourceId(0x01010003),
-                                     test::AttributeBuilder()
-                                         .SetTypeMask(android::ResTable_map::TYPE_STRING)
-                                         .Build())
-                    .AddPublicSymbol("com.app.lib:string/lib_string", ResourceId(0x7f020003))
-                    .Build())
-            .Build();
   }
 
  protected:
   std::unique_ptr<IAaptContext> context_;
-  std::unique_ptr<IAaptContext> auto_namespace_context_;
 };
 
 TEST_F(XmlReferenceLinkerTest, LinkBasicAttributes) {
@@ -213,31 +195,6 @@
   EXPECT_EQ(make_value(ResourceId(0x7f020001)), ref->id);
 }
 
-TEST_F(XmlReferenceLinkerTest, LinkAutoNamespaceResReference) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
-      <View
-          xmlns:android="http://schemas.android.com/apk/res/android"
-          android:text="@string/lib_string" />)");
-
-  XmlReferenceLinker linker;
-  // Should not link with auto-namespace support disabled.
-  ASSERT_FALSE(linker.Consume(context_.get(), doc.get()));
-  // Should link with auto-namespace enabled.
-  ASSERT_TRUE(linker.Consume(auto_namespace_context_.get(), doc.get()));
-
-  xml::Element* view_el = doc->root.get();
-  ASSERT_THAT(view_el, NotNull());
-
-  xml::Attribute* xml_attr = view_el->FindAttribute(xml::kSchemaAndroid, "text");
-  ASSERT_THAT(xml_attr, NotNull());
-  ASSERT_TRUE(xml_attr->compiled_attribute);
-  EXPECT_EQ(make_value(ResourceId(0x01010003)), xml_attr->compiled_attribute.value().id);
-  Reference* ref = ValueCast<Reference>(xml_attr->compiled_value.get());
-  ASSERT_THAT(ref, NotNull());
-  ASSERT_TRUE(ref->name);
-  EXPECT_EQ(make_value(ResourceId(0x7f020003)), ref->id);
-}
-
 TEST_F(XmlReferenceLinkerTest, LinkViewWithShadowedPackageAlias) {
   std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
       <View xmlns:app="http://schemas.android.com/apk/res/android" app:attr="@app:id/id">
diff --git a/tools/aapt2/optimize/MultiApkGenerator.cpp b/tools/aapt2/optimize/MultiApkGenerator.cpp
index 9cfd730..e92c121 100644
--- a/tools/aapt2/optimize/MultiApkGenerator.cpp
+++ b/tools/aapt2/optimize/MultiApkGenerator.cpp
@@ -26,6 +26,7 @@
 #include "ResourceUtils.h"
 #include "ValueVisitor.h"
 #include "configuration/ConfigurationParser.h"
+#include "cmd/Util.h"
 #include "filter/AbiFilter.h"
 #include "filter/Filter.h"
 #include "format/Archive.h"
@@ -98,10 +99,6 @@
         util::make_unique<SourcePathDiagnostics>(Source{source}, context_->GetDiagnostics());
   }
 
-  bool IsAutoNamespace() override {
-    return context_->IsAutoNamespace();
-  }
-
  private:
   IAaptContext* context_;
   std::unique_ptr<SourcePathDiagnostics> source_diag_;
@@ -269,7 +266,7 @@
 
   // Make sure the first element is <manifest> with package attribute.
   xml::Element* manifest_el = manifest->root.get();
-  if (manifest_el == nullptr) {
+  if (!manifest_el) {
     return false;
   }
 
@@ -278,21 +275,35 @@
     return false;
   }
 
-  // Update the versionCode attribute.
-  xml::Attribute* versionCode = manifest_el->FindAttribute(kSchemaAndroid, "versionCode");
-  if (versionCode == nullptr) {
+  // Retrieve the versionCode attribute.
+  auto version_code = manifest_el->FindAttribute(kSchemaAndroid, "versionCode");
+  if (!version_code) {
     diag->Error(DiagMessage(manifest->file.source) << "manifest must have a versionCode attribute");
     return false;
   }
 
-  auto* compiled_version = ValueCast<BinaryPrimitive>(versionCode->compiled_value.get());
-  if (compiled_version == nullptr) {
+  auto version_code_value = ValueCast<BinaryPrimitive>(version_code->compiled_value.get());
+  if (!version_code_value) {
     diag->Error(DiagMessage(manifest->file.source) << "versionCode is invalid");
     return false;
   }
 
-  int new_version = compiled_version->value.data + artifact.version;
-  versionCode->compiled_value = ResourceUtils::TryParseInt(std::to_string(new_version));
+  // Retrieve the versionCodeMajor attribute.
+  auto version_code_major = manifest_el->FindAttribute(kSchemaAndroid, "versionCodeMajor");
+  BinaryPrimitive* version_code_major_value = nullptr;
+  if (version_code_major) {
+    version_code_major_value = ValueCast<BinaryPrimitive>(version_code_major->compiled_value.get());
+    if (!version_code_major_value) {
+      diag->Error(DiagMessage(manifest->file.source) << "versionCodeMajor is invalid");
+      return false;
+    }
+  }
+
+  // Calculate and set the updated version code
+  uint64_t major = (version_code_major_value)
+                  ? ((uint64_t) version_code_major_value->value.data) << 32 : 0;
+  uint64_t new_version = (major | version_code_value->value.data) + artifact.version;
+  SetLongVersionCode(manifest_el, new_version);
 
   // Check to see if the minSdkVersion needs to be updated.
   if (artifact.android_sdk) {
diff --git a/tools/aapt2/process/IResourceTableConsumer.h b/tools/aapt2/process/IResourceTableConsumer.h
index a3a7719..30dad802 100644
--- a/tools/aapt2/process/IResourceTableConsumer.h
+++ b/tools/aapt2/process/IResourceTableConsumer.h
@@ -50,7 +50,6 @@
   virtual NameMangler* GetNameMangler() = 0;
   virtual bool IsVerbose() = 0;
   virtual int GetMinSdkVersion() = 0;
-  virtual bool IsAutoNamespace() = 0;
 };
 
 struct IResourceTableConsumer {
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index ef2e448..70efbf5 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -114,16 +114,6 @@
   return shared_symbol.get();
 }
 
-const SymbolTable::Symbol* SymbolTable::FindByNameInAnyPackage(const ResourceName& name) {
-  for (auto& source : sources_) {
-    std::string package = source->GetPackageForSymbol(name);
-    if (!package.empty()) {
-      return FindByName(ResourceName(package, name.type, name.entry));
-    }
-  }
-  return {};
-}
-
 const SymbolTable::Symbol* SymbolTable::FindById(const ResourceId& id) {
   if (const std::shared_ptr<Symbol>& s = id_cache_.get(id)) {
     return s.get();
@@ -204,6 +194,7 @@
 
   if (sr.package->id && sr.type->id && sr.entry->id) {
     symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(), sr.entry->id.value());
+    symbol->is_dynamic = (sr.package->id.value() == 0);
   }
 
   if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) {
@@ -221,25 +212,6 @@
   return symbol;
 }
 
-std::string ResourceTableSymbolSource::GetPackageForSymbol(const ResourceName& name) {
-  for (auto& package : table_->packages) {
-    ResourceTableType* type = package->FindType(name.type);
-    if (type == nullptr) {
-      continue;
-    }
-    ResourceEntry* entry = type->FindEntry(name.entry);
-    if (entry == nullptr) {
-      continue;
-    }
-    return package->name;
-  }
-  if (name.type == ResourceType::kAttr) {
-    // Recurse and try looking up a private attribute.
-    return GetPackageForSymbol(ResourceName(name.package, ResourceType::kAttrPrivate, name.entry));
-  }
-  return {};
-}
-
 bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) {
   int32_t cookie = 0;
   return assets_.addAssetPath(android::String8(path.data(), path.size()), &cookie);
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index c798cbb..51a2e37 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -89,13 +89,6 @@
   // results are stored in a cache which may evict entries on subsequent calls.
   const Symbol* FindByName(const ResourceName& name);
 
-  // Finds the symbol from any package, for use as part of automatic conversion to namespaces.
-  // This returns the symbol from the highest priority package,
-  // which mimics the behavior of the resource merger and overlays.
-  // NOTE: Never hold on to the result between calls to FindByXXX. The
-  // results are stored in a cache which may evict entries on subsequent calls.
-  const Symbol* FindByNameInAnyPackage(const ResourceName& name);
-
   // NOTE: Never hold on to the result between calls to FindByXXX. The
   // results are stored in a cache which may evict entries on subsequent calls.
   const Symbol* FindById(const ResourceId& id);
@@ -160,11 +153,6 @@
 
   virtual std::unique_ptr<SymbolTable::Symbol> FindByName(
       const ResourceName& name) = 0;
-  // Finds the name of a symbol from any package,
-  // for use as part of automatic conversion to namespaces.
-  // This returns the symbol from the highest priority package,
-  // which mimics the behavior of the resource merger and overlays.
-  virtual std::string GetPackageForSymbol(const ResourceName& name) = 0;
   virtual std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) = 0;
 
   // Default implementation tries the name if it exists, else the ID.
@@ -189,7 +177,6 @@
   std::unique_ptr<SymbolTable::Symbol> FindByName(
       const ResourceName& name) override;
 
-  std::string GetPackageForSymbol(const ResourceName& name) override;
   std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override {
     return {};
   }
@@ -210,9 +197,6 @@
 
   std::unique_ptr<SymbolTable::Symbol> FindByName(
       const ResourceName& name) override;
-  std::string GetPackageForSymbol(const ResourceName& name) override {
-    return {};
-  }
   std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override;
   std::unique_ptr<SymbolTable::Symbol> FindByReference(
       const Reference& ref) override;
diff --git a/tools/aapt2/process/SymbolTable_test.cpp b/tools/aapt2/process/SymbolTable_test.cpp
index df40b26..1f59d70 100644
--- a/tools/aapt2/process/SymbolTable_test.cpp
+++ b/tools/aapt2/process/SymbolTable_test.cpp
@@ -120,39 +120,4 @@
   EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.other:id/foo")), IsNull());
 }
 
-TEST(SymbolTableTest, FindByNameInAnyPackage) {
-  // This represents lib3 --depends-on--> lib2 --depends-on--> lib1
-
-  NameMangler mangler(NameManglerPolicy{"com.example.lib3"});
-  SymbolTable symbol_table(&mangler);
-  // Lib2 has higher precedence than lib1, as it is closer to the current library (lib3)
-  // in the dependency graph.
-
-  symbol_table.AppendSource(test::StaticSymbolSourceBuilder()
-                                .AddPublicSymbol("com.example.lib1:string/foo", ResourceId())
-                                .AddSymbol("com.example.lib1:attr/foo", ResourceId(),
-                                           test::AttributeBuilder()
-                                               .SetTypeMask(android::ResTable_map::TYPE_FLAGS)
-                                               .AddItem("one", 0x01)
-                                               .AddItem("two", 0x02)
-                                               .Build())
-                                .Build());
-  symbol_table.PrependSource(test::StaticSymbolSourceBuilder()
-                                 .AddPublicSymbol("com.example.lib2:string/foo", ResourceId())
-                                 .Build());
-
-  // Sanity test
-  EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("string/foo")), IsNull());
-
-  // Test public symbol resolution
-  const SymbolTable::Symbol* const found_string =
-      symbol_table.FindByNameInAnyPackage(test::ParseNameOrDie("string/foo"));
-  ASSERT_THAT(found_string, NotNull());
-
-  // Test attr resolution
-  const SymbolTable::Symbol* const found_attr =
-      symbol_table.FindByNameInAnyPackage(test::ParseNameOrDie("attr/foo"));
-  ASSERT_THAT(found_attr, NotNull());
-}
-
 }  // namespace aapt
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index a07d79f..0564db0 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -81,10 +81,6 @@
     return min_sdk_version_;
   }
 
-  bool IsAutoNamespace() override {
-    return auto_namespace_;
-  }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(Context);
 
@@ -97,7 +93,6 @@
   NameMangler name_mangler_;
   SymbolTable symbols_;
   int min_sdk_version_;
-  bool auto_namespace_;
 };
 
 class ContextBuilder {
@@ -132,11 +127,6 @@
     return *this;
   }
 
-  ContextBuilder& SetAutoNamespace(bool auto_namespace) {
-    context_->auto_namespace_ = auto_namespace;
-    return *this;
-  }
-
   std::unique_ptr<Context> Build() { return std::move(context_); }
 
  private:
@@ -182,15 +172,6 @@
       return nullptr;
     }
 
-    std::string GetPackageForSymbol(const ResourceName& name) override {
-      for (auto const& imap : name_map_) {
-        if (imap.first.type == name.type && imap.first.entry == name.entry) {
-          return imap.first.package;
-        }
-      }
-      return "";
-    }
-
     std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override {
       auto iter = id_map_.find(id);
       if (iter != id_map_.end()) {
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 5a8ff09..7cd023b 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -149,6 +149,10 @@
   return {};
 }
 
+bool IsHidden(const android::StringPiece& path) {
+  return util::StartsWith(GetFilename(path), ".");
+}
+
 void AppendPath(std::string* base, StringPiece part) {
   CHECK(base != nullptr);
   const bool base_has_trailing_sep = (!base->empty() && *(base->end() - 1) == sDirSep);
diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h
index b26e4fa..219e1a0 100644
--- a/tools/aapt2/util/Files.h
+++ b/tools/aapt2/util/Files.h
@@ -70,6 +70,9 @@
 // of the path.
 android::StringPiece GetExtension(const android::StringPiece& path);
 
+// Returns whether or not the name of the file or directory is a hidden file name
+bool IsHidden(const android::StringPiece& path);
+
 // Converts a package name (com.android.app) to a path: com/android/app
 std::string PackageToPath(const android::StringPiece& package);
 
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index d1c9ca1..9bef54e5 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -297,6 +297,53 @@
   return true;
 }
 
+std::string Utf8ToModifiedUtf8(const std::string& utf8) {
+  // Java uses Modified UTF-8 which only supports the 1, 2, and 3 byte formats of UTF-8. To encode
+  // 4 byte UTF-8 codepoints, Modified UTF-8 allows the use of surrogate pairs in the same format
+  // of CESU-8 surrogate pairs. Calculate the size of the utf8 string with all 4 byte UTF-8
+  // codepoints replaced with 2 3 byte surrogate pairs
+  size_t modified_size = 0;
+  const size_t size = utf8.size();
+  for (size_t i = 0; i < size; i++) {
+    if (((uint8_t) utf8[i] >> 4) == 0xF) {
+      modified_size += 6;
+      i += 3;
+    } else {
+      modified_size++;
+    }
+  }
+
+  // Early out if no 4 byte codepoints are found
+  if (size == modified_size) {
+    return utf8;
+  }
+
+  std::string output;
+  output.reserve(modified_size);
+  for (size_t i = 0; i < size; i++) {
+    if (((uint8_t) utf8[i] >> 4) == 0xF) {
+      auto codepoint = (char32_t) utf32_from_utf8_at(utf8.data(), size, i, nullptr);
+
+      // Calculate the high and low surrogates as UTF-16 would
+      char32_t high = ((codepoint - 0x10000) / 0x400) + 0xD800;
+      char32_t low = ((codepoint - 0x10000) % 0x400) + 0xDC00;
+
+      // Encode each surrogate in UTF-8
+      output.push_back((char) (0xE4 | ((high >> 12) & 0xF)));
+      output.push_back((char) (0x80 | ((high >> 6) & 0x3F)));
+      output.push_back((char) (0x80 | (high & 0x3F)));
+      output.push_back((char) (0xE4 | ((low >> 12) & 0xF)));
+      output.push_back((char) (0x80 | ((low >> 6) & 0x3F)));
+      output.push_back((char) (0x80 | (low & 0x3F)));
+      i += 3;
+    } else {
+      output.push_back(utf8[i]);
+    }
+  }
+
+  return output;
+}
+
 std::u16string Utf8ToUtf16(const StringPiece& utf8) {
   ssize_t utf16_length = utf8_to_utf16_length(
       reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length());
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index 0eb35d1..36b7333 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -197,6 +197,9 @@
   return error_.empty();
 }
 
+// Converts a UTF8 string into Modified UTF8
+std::string Utf8ToModifiedUtf8(const std::string& utf8);
+
 // Converts a UTF8 string to a UTF16 string.
 std::u16string Utf8ToUtf16(const android::StringPiece& utf8);
 std::string Utf16ToUtf8(const android::StringPiece16& utf16);
diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh
new file mode 100755
index 0000000..29bf74c
--- /dev/null
+++ b/tools/aosp/aosp_sha.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+LOCAL_DIR="$( dirname ${BASH_SOURCE} )"
+
+if git branch -vv | grep "^*" | grep "\[aosp/master" > /dev/null; then
+    # Change appears to be in AOSP
+    exit 0
+else
+    # Change appears to be non-AOSP; search for files
+    git show --name-only --pretty=format: $1 | grep $2 | while read file; do
+        echo
+        echo -e "\033[0;31mThe source of truth for '$file' is in AOSP.\033[0m"
+        echo
+        echo "If your change contains no confidential details, please upload and merge"
+        echo "this change at https://android-review.googlesource.com/."
+        echo
+        exit 77
+    done
+fi
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 9db3f02..018e9c9 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -69,12 +69,19 @@
         self.raw = raw.strip(" {;")
         self.blame = blame
 
+        # drop generics for now; may need multiple passes
+        raw = re.sub("<[^<]+?>", "", raw)
+        raw = re.sub("<[^<]+?>", "", raw)
+
         raw = raw.split()
         self.split = list(raw)
 
         for r in ["field", "volatile", "transient", "public", "protected", "static", "final", "deprecated"]:
             while r in raw: raw.remove(r)
 
+        # ignore annotations for now
+        raw = [ r for r in raw if not r.startswith("@") ]
+
         self.typ = raw[0]
         self.name = raw[1].strip(";")
         if len(raw) >= 4 and raw[2] == "=":
@@ -97,25 +104,39 @@
         self.raw = raw.strip(" {;")
         self.blame = blame
 
-        # drop generics for now
-        raw = re.sub("<.+?>", "", raw)
+        # drop generics for now; may need multiple passes
+        raw = re.sub("<[^<]+?>", "", raw)
+        raw = re.sub("<[^<]+?>", "", raw)
 
-        raw = re.split("[\s(),;]+", raw)
+        # handle each clause differently
+        raw_prefix, raw_args, _, raw_throws = re.match(r"(.*?)\((.*?)\)( throws )?(.*?);$", raw).groups()
+
+        # parse prefixes
+        raw = re.split("[\s]+", raw_prefix)
         for r in ["", ";"]:
             while r in raw: raw.remove(r)
         self.split = list(raw)
 
-        for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract", "default"]:
+        for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract", "default", "operator"]:
             while r in raw: raw.remove(r)
 
         self.typ = raw[0]
         self.name = raw[1]
+
+        # parse args
         self.args = []
+        for arg in re.split(",\s*", raw_args):
+            arg = re.split("\s", arg)
+            # ignore annotations for now
+            arg = [ a for a in arg if not a.startswith("@") ]
+            if len(arg[0]) > 0:
+                self.args.append(arg[0])
+
+        # parse throws
         self.throws = []
-        target = self.args
-        for r in raw[2:]:
-            if r == "throws": target = self.throws
-            else: target.append(r)
+        for throw in re.split(",\s*", raw_throws):
+            self.throws.append(throw)
+
         self.ident = ident(self.raw)
 
     def __hash__(self):
@@ -135,12 +156,18 @@
         self.fields = []
         self.methods = []
 
+        # drop generics for now; may need multiple passes
+        raw = re.sub("<[^<]+?>", "", raw)
+        raw = re.sub("<[^<]+?>", "", raw)
+
         raw = raw.split()
         self.split = list(raw)
         if "class" in raw:
             self.fullname = raw[raw.index("class")+1]
         elif "interface" in raw:
             self.fullname = raw[raw.index("interface")+1]
+        elif "@interface" in raw:
+            self.fullname = raw[raw.index("@interface")+1]
         else:
             raise ValueError("Funky class type %s" % (self.raw))
 
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index a8411aa..ce9becd 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -524,9 +524,12 @@
     0xFE837: (ord('0'), COMBINING_KEYCAP),
 }
 
+# This is used to define the emoji that should have the same glyph.
+# i.e. previously we had gender based Kiss (0x1F48F), which had the same glyph
+# with Kiss: Woman, Man (0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468)
+# in that case a valid row would be:
+# (0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468): 0x1F48F,
 ZWJ_IDENTICALS = {
-    # KISS
-    (0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468): 0x1F48F,
 }
 
 SAME_FLAG_MAPPINGS = [
diff --git a/tools/genprotos.sh b/tools/genprotos.sh
new file mode 100755
index 0000000..f901c9f
--- /dev/null
+++ b/tools/genprotos.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# TODO This should not be needed. If you set a custom OUT_DIR or OUT_DIR_COMMON_BASE you can
+# end up with a command that is extremely long, potentially going passed MAX_ARG_STRLEN due to
+# the way sbox rewrites the command. See b/70221552.
+
+set -e
+
+location_aprotoc=$1
+location_protoc=$2
+location_soong_zip=$3
+genDir=$4
+depfile=$5
+in=$6
+out=$7
+
+mkdir -p ${genDir}/${in} && \
+  ${location_aprotoc} --plugin=${location_protoc} \
+                      --dependency_out=${depfile} \
+                      --javastream_out=${genDir}/${in} \
+                      -Iexternal/protobuf/src \
+                      -I . \
+                      ${in} && \
+  ${location_soong_zip} -jar -o ${out} -C ${genDir}/${in} -D ${genDir}/${in}
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index ebdcdfd..40ee490 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -116,6 +116,9 @@
             if (field->message_type()->full_name() ==
                 "android.os.statsd.AttributionNode") {
               return JAVA_TYPE_ATTRIBUTION_CHAIN;
+            } else if (field->message_type()->full_name() ==
+                       "android.os.statsd.KeyValuePair") {
+              return JAVA_TYPE_KEY_VALUE_PAIR;
             } else {
                 return JAVA_TYPE_OBJECT;
             }
@@ -181,6 +184,16 @@
     expectedNumber++;
   }
 
+  // Skips the key value pair atom.
+  for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin();
+       it != fields.end(); it++) {
+    const FieldDescriptor *field = it->second;
+    java_type_t javaType = java_type(field);
+    if (javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
+      return 0;
+    }
+  }
+
   // Check that only allowed types are present. Remove any invalid ones.
   for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin();
        it != fields.end(); it++) {
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index 5d2c302..ccdd145 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -48,6 +48,7 @@
   JAVA_TYPE_DOUBLE = 6,
   JAVA_TYPE_STRING = 7,
   JAVA_TYPE_ENUM = 8,
+  JAVA_TYPE_KEY_VALUE_PAIR = 9,
 
   JAVA_TYPE_OBJECT = -1,
   JAVA_TYPE_BYTE_ARRAY = -2,
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index e519909..8038a3a 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -349,8 +349,7 @@
            argIndex++;
        }
        fprintf(out, ");\n");
-       fprintf(out, "      if (ret >= 0) { return retry; }\n");
-
+       fprintf(out, "      if (ret >= 0) { break; }\n");
 
        fprintf(out, "      {\n");
        fprintf(out, "          std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
@@ -360,6 +359,9 @@
        fprintf(out, "      }\n");
        fprintf(out, "      std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
        fprintf(out, "  }\n");
+       fprintf(out, "  if (ret < 0) {\n");
+       fprintf(out, "      note_log_drop();\n");
+       fprintf(out, "  }\n");
        fprintf(out, "  return ret;\n");
        fprintf(out, "}\n");
        fprintf(out, "\n");
@@ -439,7 +441,7 @@
            argIndex++;
        }
        fprintf(out, ");\n");
-       fprintf(out, "      if (ret >= 0) { return retry; }\n");
+       fprintf(out, "      if (ret >= 0) { break; }\n");
 
        fprintf(out, "      {\n");
        fprintf(out, "          std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
@@ -450,7 +452,10 @@
 
        fprintf(out, "      std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
        fprintf(out, "  }\n");
-       fprintf(out, "  return ret;\n");
+       fprintf(out, "  if (ret < 0) {\n");
+       fprintf(out, "      note_log_drop();\n");
+       fprintf(out, "  }\n");
+       fprintf(out, "  return ret;\n\n");
        fprintf(out, "}\n");
 
        fprintf(out, "\n");
diff --git a/vr/Android.bp b/vr/Android.bp
deleted file mode 100644
index b5904d6..0000000
--- a/vr/Android.bp
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Library to perform dlopen on the actual shared library.
-cc_library_shared {
-    name: "libdvr_loader",
-    owner: "google",
-    srcs: ["dvr_library_loader.cpp"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-}
-
-// Java platform library for vr stuff.
-java_library {
-    name: "com.google.vr.platform",
-    owner: "google",
-    required: [
-        "libdvr_loader",
-        "libdvr",
-    ],
-    srcs: ["java/**/*.java"],
-}
-
-prebuilt_etc_xml {
-    name: "com.google.vr.platform.xml",
-    src: "com.google.vr.platform.xml",
-}
diff --git a/vr/com.google.vr.platform.xml b/vr/com.google.vr.platform.xml
deleted file mode 100644
index 952b476..0000000
--- a/vr/com.google.vr.platform.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<permissions>
-    <library name="com.google.vr.platform"
-             file="/system/framework/com.google.vr.platform.jar" />
-</permissions>
diff --git a/vr/dvr_library_loader.cpp b/vr/dvr_library_loader.cpp
deleted file mode 100644
index 0b4298a..0000000
--- a/vr/dvr_library_loader.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <dlfcn.h>
-#include <jni.h>
-
-#include <string>
-
-extern "C" {
-
-JNIEXPORT jlong JNICALL
-Java_com_google_vr_platform_Dvr_nativeLoadLibrary(
-    JNIEnv* env, jclass, jstring java_library) {
-  if (!java_library)
-    return 0;
-
-  // Convert the Java String object to a C++ null-terminated string.
-  const char* data = env->GetStringUTFChars(java_library, NULL);
-  size_t size = env->GetStringUTFLength(java_library);
-  std::string library(data, size);
-  env->ReleaseStringUTFChars(java_library, data);
-
-  // Return the handle to the requested library.
-  return reinterpret_cast<jlong>(
-      dlopen(library.c_str(), RTLD_NOW | RTLD_LOCAL));
-}
-
-}  // extern "C"
diff --git a/vr/java/com/google/vr/platform/DeviceInfo.java b/vr/java/com/google/vr/platform/DeviceInfo.java
deleted file mode 100644
index f6da66b..0000000
--- a/vr/java/com/google/vr/platform/DeviceInfo.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.google.vr.platform;
-
-import android.os.SystemProperties;
-
-/**
- * Class to get information about the vr device.
- * @hide
- */
-public class DeviceInfo {
-
-    private static final String VR_MODE_BOOT = "ro.boot.vr";
-
-    /**
-     * Returns true if this device boots directly in VR mode.
-     */
-    public static boolean getVrBoot() {
-        return SystemProperties.getBoolean(VR_MODE_BOOT, false);
-    }
-}
diff --git a/vr/java/com/google/vr/platform/Dvr.java b/vr/java/com/google/vr/platform/Dvr.java
deleted file mode 100644
index b07d634..0000000
--- a/vr/java/com/google/vr/platform/Dvr.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.google.vr.platform;
-
-/**
- * Class to load the dvr api.
- * @hide
- */
-public class Dvr {
-    /**
-     * Opens a shared library containing the dvr api and returns the handle to it.
-     *
-     * @return A Long object describing the handle returned by dlopen.
-     */
-    public static Long loadLibrary() {
-        // Load a thin JNI library that runs dlopen on request.
-        System.loadLibrary("dvr_loader");
-
-        // Performs dlopen on the library and returns the handle.
-        return nativeLoadLibrary("libdvr.so");
-    }
-
-    private static native long nativeLoadLibrary(String library);
-}
diff --git a/wifi/OWNERS b/wifi/OWNERS
index 0efa464..0601047 100644
--- a/wifi/OWNERS
+++ b/wifi/OWNERS
@@ -1,5 +1,6 @@
 set noparent
 
 etancohen@google.com
+mplass@google.com
+rpius@google.com
 satk@google.com
-silberst@google.com
diff --git a/wifi/java/android/net/wifi/ITrafficStateCallback.aidl b/wifi/java/android/net/wifi/ITrafficStateCallback.aidl
new file mode 100644
index 0000000..0c8e777
--- /dev/null
+++ b/wifi/java/android/net/wifi/ITrafficStateCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+/**
+ * Interface for Traffic state callback.
+ *
+ * @hide
+ */
+oneway interface ITrafficStateCallback
+{
+   /**
+    * Callback invoked to inform clients about the current traffic state.
+    *
+    * @param state One of the values: {@link #DATA_ACTIVITY_NONE}, {@link #DATA_ACTIVITY_IN},
+    * {@link #DATA_ACTIVITY_OUT} & {@link #DATA_ACTIVITY_INOUT}.
+    * @hide
+    */
+   void onStateChanged(int state);
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index af44b7e..12f50c8 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -26,6 +26,7 @@
 import android.net.DhcpInfo;
 import android.net.Network;
 import android.net.wifi.ISoftApCallback;
+import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.PasspointManagementObjectDefinition;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiActivityEnergyInfo;
@@ -125,7 +126,7 @@
 
     void acquireMulticastLock(IBinder binder, String tag);
 
-    void releaseMulticastLock();
+    void releaseMulticastLock(String tag);
 
     void updateInterfaceIpState(String ifaceName, int mode);
 
@@ -180,5 +181,9 @@
     void registerSoftApCallback(in IBinder binder, in ISoftApCallback callback, int callbackIdentifier);
 
     void unregisterSoftApCallback(int callbackIdentifier);
+
+    void registerTrafficStateCallback(in IBinder binder, in ITrafficStateCallback callback, int callbackIdentifier);
+
+    void unregisterTrafficStateCallback(int callbackIdentifier);
 }
 
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index f210b61..3a4e88b 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -17,6 +17,7 @@
 package android.net.wifi;
 
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -40,6 +41,7 @@
     /**
      * Ascii encoded SSID. This will replace SSID when we deprecate it. @hide
      */
+    @UnsupportedAppUsage
     public WifiSsid wifiSsid;
 
     /**
@@ -51,12 +53,14 @@
      * The HESSID from the beacon.
      * @hide
      */
+    @UnsupportedAppUsage
     public long hessid;
 
     /**
      * The ANQP Domain ID from the Hotspot 2.0 Indication element, if present.
      * @hide
      */
+    @UnsupportedAppUsage
     public int anqpDomainId;
 
     /*
@@ -214,6 +218,7 @@
      * @deprecated use is80211mcResponder() instead
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean is80211McRTTResponder;
 
     /**
@@ -226,6 +231,7 @@
      * Timestamp representing date when this result was last seen, in milliseconds from 1970
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long seen;
 
     /**
@@ -284,6 +290,7 @@
      * Number of time autojoin used it
      * @hide
      */
+    @UnsupportedAppUsage
     public int numUsage;
 
     /**
@@ -291,6 +298,7 @@
      * {@link UNSPECIFIED}.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int distanceCm;
 
     /**
@@ -298,6 +306,7 @@
      * Else {@link UNSPECIFIED}.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public int distanceSdCm;
 
     /** {@hide} */
@@ -314,6 +323,7 @@
      * Defines flags; such as {@link #FLAG_PASSPOINT_NETWORK}.
      * {@hide}
      */
+    @UnsupportedAppUsage
     public long flags;
 
     /**
@@ -391,29 +401,45 @@
      *  @hide
      * anqp lines from supplicant BSS response
      */
+    @UnsupportedAppUsage
     public List<String> anqpLines;
 
     /** information elements from beacon
      * @hide
      */
     public static class InformationElement {
+        @UnsupportedAppUsage
         public static final int EID_SSID = 0;
+        @UnsupportedAppUsage
         public static final int EID_SUPPORTED_RATES = 1;
+        @UnsupportedAppUsage
         public static final int EID_TIM = 5;
+        @UnsupportedAppUsage
         public static final int EID_BSS_LOAD = 11;
+        @UnsupportedAppUsage
         public static final int EID_ERP = 42;
         public static final int EID_HT_CAPABILITIES = 45;
+        @UnsupportedAppUsage
         public static final int EID_RSN = 48;
+        @UnsupportedAppUsage
         public static final int EID_EXTENDED_SUPPORTED_RATES = 50;
+        @UnsupportedAppUsage
         public static final int EID_HT_OPERATION = 61;
+        @UnsupportedAppUsage
         public static final int EID_INTERWORKING = 107;
+        @UnsupportedAppUsage
         public static final int EID_ROAMING_CONSORTIUM = 111;
+        @UnsupportedAppUsage
         public static final int EID_EXTENDED_CAPS = 127;
         public static final int EID_VHT_CAPABILITIES = 191;
+        @UnsupportedAppUsage
         public static final int EID_VHT_OPERATION = 192;
+        @UnsupportedAppUsage
         public static final int EID_VSA = 221;
 
+        @UnsupportedAppUsage
         public int id;
+        @UnsupportedAppUsage
         public byte[] bytes;
 
         public InformationElement() {
@@ -428,6 +454,7 @@
     /** information elements found in the beacon
      * @hide
      */
+    @UnsupportedAppUsage
     public InformationElement[] informationElements;
 
     /** ANQP response elements.
@@ -704,6 +731,7 @@
     }
 
     /** Implement the Parcelable interface {@hide} */
+    @UnsupportedAppUsage
     public static final Creator<ScanResult> CREATOR =
         new Creator<ScanResult>() {
             public ScanResult createFromParcel(Parcel in) {
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 2918cf6..ce8d71d 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.PackageManager;
 import android.net.IpConfiguration;
 import android.net.IpConfiguration.ProxySettings;
@@ -61,6 +62,7 @@
     public static final String pskVarName = "psk";
     /** {@hide} */
     @Deprecated
+    @UnsupportedAppUsage
     public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" };
     /** {@hide} */
     @Deprecated
@@ -305,6 +307,7 @@
      * By default, 2G is chosen
      * @hide
      */
+    @UnsupportedAppUsage
     public int apBand = AP_BAND_2GHZ;
 
     /**
@@ -314,6 +317,7 @@
      * 0 - find a random available channel according to the apBand
      * @hide
      */
+    @UnsupportedAppUsage
     public int apChannel = 0;
 
     /**
@@ -438,12 +442,14 @@
      * This network configuration is visible to and usable by other users on the
      * same device.
      */
+    @UnsupportedAppUsage
     public boolean shared;
 
     /**
      * @hide
      */
     @NonNull
+    @UnsupportedAppUsage
     private IpConfiguration mIpConfiguration;
 
     /**
@@ -456,12 +462,14 @@
      * @hide
      * default Gateway MAC address if known
      */
+    @UnsupportedAppUsage
     public String defaultGwMacAddress;
 
     /**
      * @hide
      * last time we connected, this configuration had validated internet access
      */
+    @UnsupportedAppUsage
     public boolean validatedInternetAccess;
 
     /**
@@ -491,6 +499,7 @@
      * @hide
      * Uid of last app issuing a connection related command
      */
+    @UnsupportedAppUsage
     public int lastConnectUid;
 
     /**
@@ -533,6 +542,7 @@
      *  the network we need to be before autojoin kicks in
      */
     /** @hide **/
+    @UnsupportedAppUsage
     public static int INVALID_RSSI = -127;
 
     // States for the userApproved field
@@ -561,6 +571,7 @@
      * @hide
      * Number of reports indicating no Internet Access
      */
+    @UnsupportedAppUsage
     public int numNoInternetAccessReports;
 
     /**
@@ -592,6 +603,7 @@
      * this configuration and selects "don't ask again".
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean noInternetAccessExpected;
 
     /**
@@ -624,6 +636,7 @@
      * since we will now consider that the configuration belong to him.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean selfAdded;
 
     /**
@@ -1557,6 +1570,7 @@
      * Helper function, idenfity if a configuration should be treated as an enterprise network
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isEnterprise() {
         return (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
                 || allowedKeyManagement.get(KeyMgmt.IEEE8021X))
@@ -1740,6 +1754,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public String getPrintableSsid() {
         if (SSID == null) return "";
         final int length = SSID.length();
@@ -1840,6 +1855,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getAuthType() {
         if (allowedKeyManagement.cardinality() > 1) {
             throw new IllegalStateException("More than one auth type set");
@@ -1902,42 +1918,50 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public IpConfiguration getIpConfiguration() {
         return mIpConfiguration;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setIpConfiguration(IpConfiguration ipConfiguration) {
         if (ipConfiguration == null) ipConfiguration = new IpConfiguration();
         mIpConfiguration = ipConfiguration;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public StaticIpConfiguration getStaticIpConfiguration() {
         return mIpConfiguration.getStaticIpConfiguration();
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
         mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration);
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public IpConfiguration.IpAssignment getIpAssignment() {
         return mIpConfiguration.ipAssignment;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) {
         mIpConfiguration.ipAssignment = ipAssignment;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public IpConfiguration.ProxySettings getProxySettings() {
         return mIpConfiguration.proxySettings;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setProxySettings(IpConfiguration.ProxySettings proxySettings) {
         mIpConfiguration.proxySettings = proxySettings;
     }
@@ -1991,6 +2015,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setProxy(ProxySettings settings, ProxyInfo proxy) {
         mIpConfiguration.proxySettings = settings;
         mIpConfiguration.httpProxy = proxy;
@@ -2012,6 +2037,7 @@
     }
 
     /** copy constructor {@hide} */
+    @UnsupportedAppUsage
     public WifiConfiguration(WifiConfiguration source) {
         if (source != null) {
             networkId = source.networkId;
@@ -2149,6 +2175,7 @@
     }
 
     /** Implement the Parcelable interface {@hide} */
+    @UnsupportedAppUsage
     public static final Creator<WifiConfiguration> CREATOR =
         new Creator<WifiConfiguration>() {
             public WifiConfiguration createFromParcel(Parcel in) {
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index bb3af3c..17847ea 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -16,6 +16,7 @@
 package android.net.wifi;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.security.Credentials;
@@ -139,6 +140,7 @@
      */
     private static final List<String> UNQUOTED_KEYS = Arrays.asList(ENGINE_KEY, OPP_KEY_CACHING);
 
+    @UnsupportedAppUsage
     private HashMap<String, String> mFields = new HashMap<String, String>();
     private X509Certificate[] mCaCerts;
     private PrivateKey mClientPrivateKey;
@@ -574,6 +576,7 @@
      * @param alias identifies the certificate
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCaCertificateAlias(String alias) {
         setFieldValue(CA_CERT_KEY, alias, CA_CERT_PREFIX);
     }
@@ -612,6 +615,7 @@
      * @return alias to the CA certificate
      * @hide
      */
+    @UnsupportedAppUsage
     public String getCaCertificateAlias() {
         return getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX);
     }
@@ -760,6 +764,7 @@
      * @param alias identifies the certificate
      * @hide
      */
+    @UnsupportedAppUsage
     public void setClientCertificateAlias(String alias) {
         setFieldValue(CLIENT_CERT_KEY, alias, CLIENT_CERT_PREFIX);
         setFieldValue(PRIVATE_KEY_ID_KEY, alias, Credentials.USER_PRIVATE_KEY);
@@ -778,6 +783,7 @@
      * @return alias to the client certificate
      * @hide
      */
+    @UnsupportedAppUsage
     public String getClientCertificateAlias() {
         return getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
     }
@@ -948,16 +954,15 @@
      * for Hotspot 2.0 defined matching of AAA server certs per WFA HS2.0 spec, section 7.3.3.2,
      * second paragraph.
      *
-     * From wpa_supplicant documentation:
-     * Constraint for server domain name. If set, this FQDN is used as a suffix match requirement
+     * <p>From wpa_supplicant documentation:
+     * <p>Constraint for server domain name. If set, this FQDN is used as a suffix match requirement
      * for the AAAserver certificate in SubjectAltName dNSName element(s). If a matching dNSName is
-     * found, this constraint is met. If no dNSName values are present, this constraint is matched
-     * against SubjectName CN using same suffix match comparison.
-     * Suffix match here means that the host/domain name is compared one label at a time starting
+     * found, this constraint is met.
+     * <p>Suffix match here means that the host/domain name is compared one label at a time starting
      * from the top-level domain and all the labels in domain_suffix_match shall be included in the
      * certificate. The certificate may include additional sub-level labels in addition to the
      * required labels.
-     * For example, domain_suffix_match=example.com would match test.example.com but would not
+     * <p>For example, domain_suffix_match=example.com would match test.example.com but would not
      * match test-example.com.
      * @param domain The domain value
      */
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 3eb13ce..1e03891 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 import android.os.Parcel;
 import android.net.NetworkInfo.DetailedState;
@@ -48,6 +49,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
 
     static {
@@ -67,11 +69,14 @@
     }
 
     private SupplicantState mSupplicantState;
+    @UnsupportedAppUsage
     private String mBSSID;
+    @UnsupportedAppUsage
     private WifiSsid mWifiSsid;
     private int mNetworkId;
 
     /** @hide **/
+    @UnsupportedAppUsage
     public static final int INVALID_RSSI = -127;
 
     /** @hide **/
@@ -98,7 +103,9 @@
     public static final String FREQUENCY_UNITS = "MHz";
     private int mFrequency;
 
+    @UnsupportedAppUsage
     private InetAddress mIpAddress;
+    @UnsupportedAppUsage
     private String mMacAddress = DEFAULT_MAC_ADDRESS;
 
     private boolean mEphemeral;
@@ -148,6 +155,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public int score;
 
     /**
@@ -157,6 +165,7 @@
     private boolean mMeteredHint;
 
     /** @hide */
+    @UnsupportedAppUsage
     public WifiInfo() {
         mWifiSsid = null;
         mBSSID = null;
@@ -248,11 +257,13 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public WifiSsid getWifiSsid() {
         return mWifiSsid;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setBSSID(String BSSID) {
         mBSSID = BSSID;
     }
@@ -280,6 +291,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setRssi(int rssi) {
         if (rssi < INVALID_RSSI)
             rssi = INVALID_RSSI;
@@ -298,6 +310,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setLinkSpeed(int linkSpeed) {
         this.mLinkSpeed = linkSpeed;
     }
@@ -328,6 +341,7 @@
      * @hide
      * TODO: makes real freq boundaries
      */
+    @UnsupportedAppUsage
     public boolean is5GHz() {
         return ScanResult.is5GHz(mFrequency);
     }
@@ -337,6 +351,7 @@
      * @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
      * @hide
      */
+    @UnsupportedAppUsage
     public void setMacAddress(String macAddress) {
         this.mMacAddress = macAddress;
     }
@@ -366,6 +381,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public boolean getMeteredHint() {
         return mMeteredHint;
     }
@@ -376,11 +392,13 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public boolean isEphemeral() {
         return mEphemeral;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setNetworkId(int id) {
         mNetworkId = id;
     }
@@ -405,6 +423,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setSupplicantState(SupplicantState state) {
         mSupplicantState = state;
     }
@@ -446,6 +465,7 @@
      * @param stateName the name of the state, as a <code>String</code> returned
      * in an event sent by {@code wpa_supplicant}.
      */
+    @UnsupportedAppUsage
     void setSupplicantState(String stateName) {
         mSupplicantState = valueOf(stateName);
     }
@@ -463,6 +483,7 @@
     }
 
     /** {@hide} */
+    @UnsupportedAppUsage
     public static String removeDoubleQuotes(String string) {
         if (string == null) return null;
         final int length = string.length();
@@ -527,6 +548,7 @@
     }
 
     /** Implement the Parcelable interface {@hide} */
+    @UnsupportedAppUsage
     public static final Creator<WifiInfo> CREATOR =
         new Creator<WifiInfo>() {
             public WifiInfo createFromParcel(Parcel in) {
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6963ed0..b56a758 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -21,10 +21,10 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
-import android.annotation.SuppressLint;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.net.ConnectivityManager;
@@ -32,9 +32,9 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
+import android.net.wifi.hotspot2.IProvisioningCallback;
 import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
-import android.net.wifi.hotspot2.IProvisioningCallback;
 import android.net.wifi.hotspot2.ProvisioningCallback;
 import android.os.Binder;
 import android.os.Build;
@@ -318,6 +318,31 @@
             "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
 
     /**
+     * Activity Action: lunch OSU (Online Sign Up) view.
+     * Included extras:
+     *
+     * {@link #EXTRA_OSU_NETWORK}: {@link Network} instance associated with OSU AP.
+     * {@link #EXTRA_URL}: String representation of a server URL used for OSU process.
+     *
+     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+     * components will be launched.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_PASSPOINT_LAUNCH_OSU_VIEW =
+            "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW";
+
+    /**
+     * The lookup key for a {@link android.net.Network} associated with OSU server.
+     *
+     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK";
+
+    /**
      * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
      * enabling, disabling, or unknown. One extra provides this state as an int.
      * Another extra provides the previous state, if available.
@@ -758,9 +783,12 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION =
             "android.net.wifi.BATCHED_RESULTS";
+
     /**
      * The RSSI (signal strength) has changed.
-     * @see #EXTRA_NEW_RSSI
+     *
+     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+     * @see {@link #EXTRA_NEW_RSSI}
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
@@ -774,6 +802,7 @@
      * changed on wifi.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final String LINK_CONFIGURATION_CHANGED_ACTION =
         "android.net.wifi.LINK_CONFIGURATION_CHANGED";
 
@@ -889,9 +918,11 @@
     public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
 
     /** Anything worse than or equal to this will show 0 bars. */
+    @UnsupportedAppUsage
     private static final int MIN_RSSI = -100;
 
     /** Anything better than or equal to this will show the max bars. */
+    @UnsupportedAppUsage
     private static final int MAX_RSSI = -55;
 
     /**
@@ -899,6 +930,7 @@
      * {@link #RSSI_CHANGED_ACTION} broadcast
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int RSSI_LEVELS = 5;
 
     /**
@@ -906,36 +938,23 @@
      * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band.
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int WIFI_FREQUENCY_BAND_AUTO = 0;
 
     /**
      * Operation on 5 GHz alone
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int WIFI_FREQUENCY_BAND_5GHZ = 1;
 
     /**
      * Operation on 2.4 GHz alone
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int WIFI_FREQUENCY_BAND_2GHZ = 2;
 
-    /** List of asyncronous notifications
-     * @hide
-     */
-    public static final int DATA_ACTIVITY_NOTIFICATION = 1;
-
-    //Lowest bit indicates data reception and the second lowest
-    //bit indicates data transmitted
-    /** @hide */
-    public static final int DATA_ACTIVITY_NONE         = 0x00;
-    /** @hide */
-    public static final int DATA_ACTIVITY_IN           = 0x01;
-    /** @hide */
-    public static final int DATA_ACTIVITY_OUT          = 0x02;
-    /** @hide */
-    public static final int DATA_ACTIVITY_INOUT        = 0x03;
-
     /** @hide */
     public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false;
 
@@ -946,9 +965,11 @@
     private static final int MAX_ACTIVE_LOCKS = 50;
 
     /* Number of currently active WifiLocks and MulticastLocks */
+    @UnsupportedAppUsage
     private int mActiveLockCount;
 
     private Context mContext;
+    @UnsupportedAppUsage
     IWifiManager mService;
     private final int mTargetSdkVersion;
 
@@ -1050,6 +1071,7 @@
      * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
      * @hide
      */
+    @UnsupportedAppUsage
     public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) {
         try {
             return mService.getMatchingWifiConfig(scanResult);
@@ -1585,13 +1607,12 @@
      * Return the record of {@link WifiActivityEnergyInfo} object that
      * has the activity and energy info. This can be used to ascertain what
      * the controller has been up to, since the last sample.
-     * @param updateType Type of info, cached vs refreshed.
      *
      * @return a record with {@link WifiActivityEnergyInfo} or null if
      * report is unavailable or unsupported
      * @hide
      */
-    public WifiActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
+    public WifiActivityEnergyInfo getControllerActivityEnergyInfo() {
         if (mService == null) return null;
         try {
             synchronized(this) {
@@ -1740,6 +1761,7 @@
     *
     * @hide
     */
+    @UnsupportedAppUsage
     public String getCountryCode() {
        try {
            String country = mService.getCountryCode();
@@ -1754,6 +1776,7 @@
      * @return {@code true} if supported, {@code false} otherwise.
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isDualBandSupported() {
         try {
             return mService.isDualBandSupported();
@@ -2019,6 +2042,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void cancelLocalOnlyHotspotRequest() {
         synchronized (mLock) {
             stopLocalOnlyHotspot();
@@ -2461,7 +2485,7 @@
         }
 
         @Override
-        public void onStateChanged(int state, int failureReason) throws RemoteException {
+        public void onStateChanged(int state, int failureReason) {
             Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + ", failureReason=" +
                     failureReason);
             mHandler.post(() -> {
@@ -2470,7 +2494,7 @@
         }
 
         @Override
-        public void onNumClientsChanged(int numClients) throws RemoteException {
+        public void onNumClientsChanged(int numClients) {
             Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients);
             mHandler.post(() -> {
                 mCallback.onNumClientsChanged(numClients);
@@ -2992,6 +3016,7 @@
      * initialized again
      * @hide
      */
+    @UnsupportedAppUsage
     public void connect(int networkId, ActionListener listener) {
         if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
@@ -3017,6 +3042,7 @@
      * initialized again
      * @hide
      */
+    @UnsupportedAppUsage
     public void save(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
@@ -3035,6 +3061,7 @@
      * initialized again
      * @hide
      */
+    @UnsupportedAppUsage
     public void forget(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener));
@@ -3049,6 +3076,7 @@
      * initialized again
      * @hide
      */
+    @UnsupportedAppUsage
     public void disable(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener));
@@ -3103,9 +3131,9 @@
      * an AsyncChannel communication with WifiService
      *
      * @return Messenger pointing to the WifiService handler
-     * @hide
      */
-    public Messenger getWifiServiceMessenger() {
+    @UnsupportedAppUsage
+    private Messenger getWifiServiceMessenger() {
         try {
             return mService.getWifiServiceMessenger(mContext.getOpPackageName());
         } catch (RemoteException e) {
@@ -3406,7 +3434,7 @@
                         mService.acquireMulticastLock(mBinder, mTag);
                         synchronized (WifiManager.this) {
                             if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
-                                mService.releaseMulticastLock();
+                                mService.releaseMulticastLock(mTag);
                                 throw new UnsupportedOperationException(
                                         "Exceeded maximum number of wifi locks");
                             }
@@ -3448,7 +3476,7 @@
             synchronized (mBinder) {
                 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
                     try {
-                        mService.releaseMulticastLock();
+                        mService.releaseMulticastLock(mTag);
                         synchronized (WifiManager.this) {
                             mActiveLockCount--;
                         }
@@ -3535,6 +3563,7 @@
      * Initialize the multicast filtering to 'on'
      * @hide no intent to publish
      */
+    @UnsupportedAppUsage
     public boolean initializeMulticastFiltering() {
         try {
             mService.initializeMulticastFiltering();
@@ -3559,6 +3588,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    @UnsupportedAppUsage
     public void enableVerboseLogging (int verbose) {
         try {
             mService.enableVerboseLogging(verbose);
@@ -3573,6 +3603,7 @@
      * to decide what to show within the picker.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getVerboseLoggingLevel() {
         try {
             return mService.getVerboseLoggingLevel();
@@ -3599,6 +3630,7 @@
      * @return Get Network object of current wifi network
      * @hide
      */
+    @UnsupportedAppUsage
     public Network getCurrentNetwork() {
         try {
             return mService.getCurrentNetwork();
@@ -3719,4 +3751,107 @@
             });
         }
     }
+
+    /**
+     * Base class for Traffic state callback. Should be extended by applications and set when
+     * calling {@link WifiManager#registerTrafficStateCallback(TrafficStateCallback, Handler)}.
+     * @hide
+     */
+    public interface TrafficStateCallback {
+        /**
+         * Lowest bit indicates data reception and the second lowest
+         * bit indicates data transmitted
+         */
+        /** @hide */
+        int DATA_ACTIVITY_NONE         = 0x00;
+        /** @hide */
+        int DATA_ACTIVITY_IN           = 0x01;
+        /** @hide */
+        int DATA_ACTIVITY_OUT          = 0x02;
+        /** @hide */
+        int DATA_ACTIVITY_INOUT        = 0x03;
+
+        /**
+         * Callback invoked to inform clients about the current traffic state.
+         *
+         * @param state One of the values: {@link #DATA_ACTIVITY_NONE}, {@link #DATA_ACTIVITY_IN},
+         * {@link #DATA_ACTIVITY_OUT} & {@link #DATA_ACTIVITY_INOUT}.
+         * @hide
+         */
+        void onStateChanged(int state);
+    }
+
+    /**
+     * Callback proxy for TrafficStateCallback objects.
+     *
+     * @hide
+     */
+    private static class TrafficStateCallbackProxy extends ITrafficStateCallback.Stub {
+        private final Handler mHandler;
+        private final TrafficStateCallback mCallback;
+
+        TrafficStateCallbackProxy(Looper looper, TrafficStateCallback callback) {
+            mHandler = new Handler(looper);
+            mCallback = callback;
+        }
+
+        @Override
+        public void onStateChanged(int state) {
+            Log.v(TAG, "TrafficStateCallbackProxy: onStateChanged state=" + state);
+            mHandler.post(() -> {
+                mCallback.onStateChanged(state);
+            });
+        }
+    }
+
+    /**
+     * Registers a callback for monitoring traffic state. See {@link TrafficStateCallback}. These
+     * callbacks will be invoked periodically by platform to inform clients about the current
+     * traffic state. Caller can unregister a previously registered callback using
+     * {@link #unregisterTrafficStateCallback(TrafficStateCallback)}
+     * <p>
+     * Applications should have the
+     * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers
+     * without the permission will trigger a {@link java.lang.SecurityException}.
+     * <p>
+     *
+     * @param callback Callback for traffic state events
+     * @param handler  The Handler on whose thread to execute the callbacks of the {@code callback}
+     *                 object. If null, then the application's main thread will be used.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void registerTrafficStateCallback(@NonNull TrafficStateCallback callback,
+                                             @Nullable Handler handler) {
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+        Log.v(TAG, "registerTrafficStateCallback: callback=" + callback + ", handler=" + handler);
+
+        Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
+        Binder binder = new Binder();
+        try {
+            mService.registerTrafficStateCallback(
+                    binder, new TrafficStateCallbackProxy(looper, callback), callback.hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Allow callers to unregister a previously registered callback. After calling this method,
+     * applications will no longer receive traffic state notifications.
+     *
+     * @param callback Callback to unregister for traffic state events
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void unregisterTrafficStateCallback(@NonNull TrafficStateCallback callback) {
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+        Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback);
+
+        try {
+            mService.unregisterTrafficStateCallback(callback.hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 928a1da..045291b 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.Manifest;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
@@ -721,6 +722,17 @@
     }
 
     /**
+     * Enable/Disable wifi scanning.
+     *
+     * {@hide}
+     */
+    @RequiresPermission(Manifest.permission.NETWORK_STACK)
+    public void setScanningEnabled(boolean enable) {
+        validateChannel();
+        mAsyncChannel.sendMessage(enable ? CMD_ENABLE : CMD_DISABLE);
+    }
+
+    /**
      * Register a listener that will receive results from all single scans
      * Either the onSuccess/onFailure will be called once when the listener is registered. After
      * (assuming onSuccess was called) all subsequent single scan results will be delivered to the
@@ -916,6 +928,7 @@
      *                 scans should also not share this object.
      * {@hide}
      */
+    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
     public void startDisconnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
             PnoScanListener listener) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
@@ -930,9 +943,9 @@
      * Stop an ongoing wifi PNO scan
      * @param listener specifies which scan to cancel; must be same object as passed in {@link
      *  #startPnoScan}
-     * TODO(rpius): Check if we can remove pnoSettings param in stop.
      * {@hide}
      */
+    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
     public void stopPnoScan(ScanListener listener) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
         int key = removeListener(listener);
@@ -1164,6 +1177,10 @@
     public static final int CMD_DEREGISTER_SCAN_LISTENER    = BASE + 28;
     /** @hide */
     public static final int CMD_GET_SINGLE_SCAN_RESULTS     = BASE + 29;
+    /** @hide */
+    public static final int CMD_ENABLE                      = BASE + 30;
+    /** @hide */
+    public static final int CMD_DISABLE                     = BASE + 31;
 
     private Context mContext;
     private IWifiScanner mService;
diff --git a/wifi/java/android/net/wifi/WifiSsid.java b/wifi/java/android/net/wifi/WifiSsid.java
index 5deb80a..9acbc14 100644
--- a/wifi/java/android/net/wifi/WifiSsid.java
+++ b/wifi/java/android/net/wifi/WifiSsid.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -42,9 +43,11 @@
 public class WifiSsid implements Parcelable {
     private static final String TAG = "WifiSsid";
 
+    @UnsupportedAppUsage
     public final ByteArrayOutputStream octets = new ByteArrayOutputStream(32);
 
     private static final int HEX_RADIX = 16;
+    @UnsupportedAppUsage
     public static final String NONE = "<unknown ssid>";
 
     private WifiSsid() {
@@ -58,6 +61,7 @@
         return wifiSsid;
     }
 
+    @UnsupportedAppUsage
     public static WifiSsid createFromAsciiEncoded(String asciiEncoded) {
         WifiSsid a = new WifiSsid();
         a.convertToBytes(asciiEncoded);
@@ -220,6 +224,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public byte[] getOctets() {
         return octets.toByteArray();
     }
@@ -246,6 +251,7 @@
     }
 
     /** Implement the Parcelable interface {@hide} */
+    @UnsupportedAppUsage
     public static final Creator<WifiSsid> CREATOR =
         new Creator<WifiSsid>() {
             public WifiSsid createFromParcel(Parcel in) {
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index 2ea6e79..ef9c59f 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -16,11 +16,12 @@
 
 package android.net.wifi.hotspot2;
 
+import android.net.wifi.WifiManager;
 import android.os.Handler;
 
 /**
  * Base class for provisioning callbacks. Should be extended by applications and set when calling
- * {@link WifiManager#startSubscriptionProvisiong(OsuProvider, ProvisioningCallback, Handler)}.
+ * {@link WifiManager#startSubscriptionProvisioning(OsuProvider, ProvisioningCallback, Handler)}.
  *
  * @hide
  */
@@ -28,84 +29,122 @@
 
     /**
      * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
      */
-    public static final int OSU_FAILURE_AP_CONNECTION      = 1;
+    public static final int OSU_FAILURE_AP_CONNECTION = 1;
 
     /**
-     * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
+     * The reason code for invalid server URL address.
      */
     public static final int OSU_FAILURE_SERVER_URL_INVALID = 2;
 
     /**
-     * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
+     * The reason code for provisioning failure due to connection failure to the server.
      */
-    public static final int OSU_FAILURE_SERVER_CONNECTION  = 3;
+    public static final int OSU_FAILURE_SERVER_CONNECTION = 3;
 
     /**
-     * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
+     * The reason code for provisioning failure due to invalid server certificate.
      */
-    public static final int OSU_FAILURE_SERVER_VALIDATION  = 4;
+    public static final int OSU_FAILURE_SERVER_VALIDATION = 4;
 
     /**
-     * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
+     * The reason code for provisioning failure due to invalid service provider.
      */
-    public static final int OSU_FAILURE_PROVIDER_VERIFICATION = 5;
+    public static final int OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION = 5;
 
     /**
-     * The reason code for Provisioning Failure when a provisioning flow is aborted.
-     * @hide
+     * The reason code for provisioning failure when a provisioning flow is aborted.
      */
     public static final int OSU_FAILURE_PROVISIONING_ABORTED = 6;
 
     /**
-     * The reason code for Provisioning Failure when a provisioning flow is aborted.
-     * @hide
+     * The reason code for provisioning failure when a provisioning flow is not possible.
      */
     public static final int OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7;
 
     /**
-     * The status code for Provisioning flow to indicate connecting to OSU AP
-     * @hide
+     * The reason code for provisioning failure due to invalid server url.
      */
-    public static final int OSU_STATUS_AP_CONNECTING       = 1;
+    public static final int OSU_FAILURE_INVALID_SERVER_URL = 8;
 
     /**
-     * The status code for Provisioning flow to indicate connected to OSU AP
-     * @hide
+     * The reason code for provisioning failure when a command received is not the expected command
+     * type.
      */
-    public static final int OSU_STATUS_AP_CONNECTED        = 2;
+    public static final int OSU_FAILURE_UNEXPECTED_COMMAND_TYPE = 9;
 
     /**
-     * The status code for Provisioning flow to indicate connecting to OSU AP
-     * @hide
+     * The reason code for provisioning failure when a SOAP message is not the expected message
+     * type.
      */
-    public static final int OSU_STATUS_SERVER_CONNECTED    = 3;
+    public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE = 10;
 
     /**
-     * The status code for Provisioning flow to indicate connecting to OSU AP
-     * @hide
+     * The reason code for provisioning failure when a SOAP message exchange fails.
      */
-    public static final int OSU_STATUS_SERVER_VALIDATED    = 4;
+    public static final int OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11;
 
     /**
-     * The status code for Provisioning flow to indicate connecting to OSU AP
-     * @hide
+     * The reason code for provisioning failure when a redirect server fails to start.
      */
-    public static final int OSU_STATUS_PROVIDER_VERIFIED   = 5;
+    public static final int OSU_FAILURE_START_REDIRECT_SERVER = 12;
+
+    /**
+     * The reason code for provisioning failure when there is no OSU activity to listen to
+     * {@link WifiManager#ACTION_PASSPOINT_LAUNCH_OSU_VIEW} intent.
+     */
+    public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 13;
+
+    /**
+     * The status code for provisioning flow to indicate connecting to OSU AP
+     */
+    public static final int OSU_STATUS_AP_CONNECTING = 1;
+
+    /**
+     * The status code for provisioning flow to indicate the OSU AP is connected.
+     */
+    public static final int OSU_STATUS_AP_CONNECTED = 2;
+
+    /**
+     * The status code for provisioning flow to indicate the server connection is completed.
+     */
+    public static final int OSU_STATUS_SERVER_CONNECTED = 3;
+
+    /**
+     * The status code for provisioning flow to indicate the server certificate is validated.
+     */
+    public static final int OSU_STATUS_SERVER_VALIDATED = 4;
+
+    /**
+     * The status code for provisioning flow to indicate the service provider is verified.
+     */
+    public static final int OSU_STATUS_SERVICE_PROVIDER_VERIFIED = 5;
+
+    /**
+     * The status code for provisioning flow to indicate starting the SOAP exchange.
+     */
+    public static final int OSU_STATUS_INIT_SOAP_EXCHANGE = 6;
+
+    /**
+     * The status code for provisioning flow to indicate waiting for a HTTP redirect response.
+     */
+    public static final int OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE = 7;
+
+    /**
+     * The status code for provisioning flow to indicate a HTTP redirect response is received.
+     */
+    public static final int OSU_STATUS_REDIRECT_RESPONSE_RECEIVED = 8;
 
     /**
      * Provisioning status for OSU failure
+     *
      * @param status indicates error condition
      */
     public abstract void onProvisioningFailure(int status);
 
     /**
      * Provisioning status when OSU is in progress
+     *
      * @param status indicates status of OSU flow
      */
     public abstract void onProvisioningStatus(int status);
diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
index f6183fa..984cf7d 100644
--- a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
@@ -136,7 +136,7 @@
     private static final String NODE_UPDATE_IDENTIFIER = "UpdateIdentifier";
     private static final String NODE_AAA_SERVER_TRUST_ROOT = "AAAServerTrustRoot";
     private static final String NODE_SUBSCRIPTION_UPDATE = "SubscriptionUpdate";
-    private static final String NODE_SUBSCRIPTION_PARAMETER = "SubscriptionParameter";
+    private static final String NODE_SUBSCRIPTION_PARAMETER = "SubscriptionParameters";
     private static final String NODE_TYPE_OF_SUBSCRIPTION = "TypeOfSubscription";
     private static final String NODE_USAGE_LIMITS = "UsageLimits";
     private static final String NODE_DATA_LIMIT = "DataLimit";
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index b019fd7..6772096 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.p2p;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.wifi.WpsInfo;
 import android.os.Parcelable;
 import android.os.Parcel;
@@ -40,6 +41,7 @@
     /** @hide */
     public static final int MAX_GROUP_OWNER_INTENT   =   15;
     /** @hide */
+    @UnsupportedAppUsage
     public static final int MIN_GROUP_OWNER_INTENT   =   0;
 
     /**
@@ -52,6 +54,7 @@
     public int groupOwnerIntent = -1;
 
     /** @hide */
+    @UnsupportedAppUsage
     public int netId = WifiP2pGroup.PERSISTENT_NET_ID;
 
     public WifiP2pConfig() {
@@ -66,6 +69,7 @@
     }
 
     /** P2P-GO-NEG-REQUEST 42:fc:89:a8:96:09 dev_passwd_id=4 {@hide}*/
+    @UnsupportedAppUsage
     public WifiP2pConfig(String supplicantEvent) throws IllegalArgumentException {
         String[] tokens = supplicantEvent.split(" ");
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index 98a595b..22dc2ed 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.p2p;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 import android.os.Parcel;
 import android.util.Log;
@@ -96,18 +97,21 @@
      * WPS config methods supported
      * @hide
      */
+    @UnsupportedAppUsage
     public int wpsConfigMethodsSupported;
 
     /**
      * Device capability
      * @hide
      */
+    @UnsupportedAppUsage
     public int deviceCapability;
 
     /**
      * Group capability
      * @hide
      */
+    @UnsupportedAppUsage
     public int groupCapability;
 
     public static final int CONNECTED   = 0;
@@ -120,6 +124,7 @@
     public int status = UNAVAILABLE;
 
     /** @hide */
+    @UnsupportedAppUsage
     public WifiP2pWfdInfo wfdInfo;
 
     /** Detailed device string pattern with WFD info
@@ -179,6 +184,7 @@
      *  Note: The events formats can be looked up in the wpa_supplicant code
      * @hide
      */
+    @UnsupportedAppUsage
     public WifiP2pDevice(String string) throws IllegalArgumentException {
         String[] tokens = string.split("[ \n]");
         Matcher match;
@@ -279,6 +285,7 @@
      * @throws IllegalArgumentException if the device is null or device address does not match
      * @hide
      */
+    @UnsupportedAppUsage
     public void update(WifiP2pDevice device) {
         updateSupplicantDetails(device);
         status = device.status;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index 3d0bb3d..72edd56 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.p2p;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 import android.os.Parcel;
 import android.net.wifi.p2p.WifiP2pDevice;
@@ -83,6 +84,7 @@
      * @param device to be updated
      * @hide
      */
+    @UnsupportedAppUsage
     public void update(WifiP2pDevice device) {
         updateSupplicantDetails(device);
         mDevices.get(device.deviceAddress).status = device.status;
@@ -146,6 +148,7 @@
      * @return WifiP2pDevice device removed, or null if none removed
      * @hide
      */
+    @UnsupportedAppUsage
     public WifiP2pDevice remove(String deviceAddress) {
         validateDeviceAddress(deviceAddress);
         return mDevices.remove(deviceAddress);
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index 32673c7..01feb1e 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.p2p;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 import android.os.Parcel;
 
@@ -37,6 +38,7 @@
 
     /** The temporary network id.
      * {@hide} */
+    @UnsupportedAppUsage
     public static final int TEMPORARY_NET_ID = -1;
 
     /** The persistent network id.
@@ -95,6 +97,7 @@
      *  Note: The events formats can be looked up in the wpa_supplicant code
      *  @hide
      */
+    @UnsupportedAppUsage
     public WifiP2pGroup(String supplicantEvent) throws IllegalArgumentException {
 
         String[] tokens = supplicantEvent.split(" ");
@@ -169,6 +172,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setIsGroupOwner(boolean isGo) {
         mIsGroupOwner = isGo;
     }
@@ -212,6 +216,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean isClientListEmpty() {
         return mClients.size() == 0;
     }
@@ -242,6 +247,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setInterface(String intf) {
         mInterface = intf;
     }
@@ -252,11 +258,13 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public int getNetworkId() {
         return mNetId;
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setNetworkId(int netId) {
         this.mNetId = netId;
     }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
index 64bb00b..8d92253 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
@@ -18,6 +18,7 @@
 import java.util.Collection;
 import java.util.Map;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.LruCache;
@@ -33,6 +34,7 @@
 
     private static final int CREDENTIAL_MAX_NUM             =   32;
 
+    @UnsupportedAppUsage
     private final LruCache<Integer, WifiP2pGroup> mGroups;
     private final GroupDeleteListener mListener;
 
@@ -48,6 +50,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public WifiP2pGroupList(WifiP2pGroupList source, GroupDeleteListener listener) {
         mListener = listener;
         mGroups = new LruCache<Integer, WifiP2pGroup>(CREDENTIAL_MAX_NUM) {
@@ -72,6 +75,7 @@
      *
      * @return the list of p2p group.
      */
+    @UnsupportedAppUsage
     public Collection<WifiP2pGroup> getGroupList() {
         return mGroups.snapshot().values();
     }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 8075e17..57f3973 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -19,6 +19,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.net.wifi.WpsInfo;
 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
@@ -325,6 +326,7 @@
     public static final int CANCEL_CONNECT_SUCCEEDED                = BASE + 12;
 
     /** @hide */
+    @UnsupportedAppUsage
     public static final int CREATE_GROUP                            = BASE + 13;
     /** @hide */
     public static final int CREATE_GROUP_FAILED                     = BASE + 14;
@@ -486,6 +488,7 @@
      * @hide - hide this because it takes in a parameter of type IWifiP2pManager, which
      * is a system private class.
      */
+    @UnsupportedAppUsage
     public WifiP2pManager(IWifiP2pManager service) {
         mService = service;
     }
@@ -731,6 +734,7 @@
 
         /* package */ final Binder mBinder;
 
+        @UnsupportedAppUsage
         private AsyncChannel mAsyncChannel;
         private P2pHandler mHandler;
         Context mContext;
@@ -887,6 +891,7 @@
             }
         }
 
+        @UnsupportedAppUsage
         private int putListener(Object listener) {
             if (listener == null) return INVALID_LISTENER_KEY;
             int key;
@@ -1099,6 +1104,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setWifiP2pChannels(Channel c, int lc, int oc, ActionListener listener) {
         checkChannel(c);
         Bundle p2pChannels = new Bundle();
@@ -1117,6 +1123,7 @@
      * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}.
      * @hide
      */
+    @UnsupportedAppUsage
     public void startWps(Channel c, WpsInfo wps, ActionListener listener) {
         checkChannel(c);
         c.mAsyncChannel.sendMessage(START_WPS, 0, c.putListener(listener), wps);
@@ -1363,6 +1370,7 @@
      * @param c is the channel created at {@link #initialize}
      * @param listener for callback when group info is available. Can be null.
      */
+    @UnsupportedAppUsage
     public void setDeviceName(Channel c, String devName, ActionListener listener) {
         checkChannel(c);
         WifiP2pDevice d = new WifiP2pDevice();
@@ -1371,6 +1379,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setWFDInfo(
             Channel c, WifiP2pWfdInfo wfdInfo,
             ActionListener listener) {
@@ -1401,6 +1410,7 @@
      * @param listener for callbacks on success or failure. Can be null.
      * @hide
      */
+    @UnsupportedAppUsage
     public void deletePersistentGroup(Channel c, int netId, ActionListener listener) {
         checkChannel(c);
         c.mAsyncChannel.sendMessage(DELETE_PERSISTENT_GROUP, netId, c.putListener(listener));
@@ -1413,6 +1423,7 @@
      * @param listener for callback when persistent group info list is available. Can be null.
      * @hide
      */
+    @UnsupportedAppUsage
     public void requestPersistentGroupInfo(Channel c, PersistentGroupInfoListener listener) {
         checkChannel(c);
         c.mAsyncChannel.sendMessage(REQUEST_PERSISTENT_GROUP_INFO, 0, c.putListener(listener));
@@ -1425,6 +1436,7 @@
     /** @hide */
     public static final int MIRACAST_SINK     = 2;
     /** Internal use only @hide */
+    @UnsupportedAppUsage
     public void setMiracastMode(int mode) {
         try {
             mService.setMiracastMode(mode);
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java b/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java
index 98683cb..153e03c 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java
@@ -16,6 +16,8 @@
 
 package android.net.wifi.p2p;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * A class representing a Wi-Fi p2p provisional discovery request/response
  * See {@link #WifiP2pProvDiscEvent} for supported types
@@ -32,13 +34,17 @@
     public static final int SHOW_PIN    = 4;
 
     /* One of PBC_REQ, PBC_RSP, ENTER_PIN or SHOW_PIN */
+    @UnsupportedAppUsage
     public int event;
 
+    @UnsupportedAppUsage
     public WifiP2pDevice device;
 
     /* Valid when event = SHOW_PIN */
+    @UnsupportedAppUsage
     public String pin;
 
+    @UnsupportedAppUsage
     public WifiP2pProvDiscEvent() {
         device = new WifiP2pDevice();
     }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
index ebf5c2a..ef1bff4 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.p2p;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcelable;
 import android.os.Parcel;
 
@@ -53,9 +54,11 @@
 
     private int mMaxThroughput;
 
+    @UnsupportedAppUsage
     public WifiP2pWfdInfo() {
     }
 
+    @UnsupportedAppUsage
     public WifiP2pWfdInfo(int devInfo, int ctrlPort, int maxTput) {
         mWfdEnabled = true;
         mDeviceInfo = devInfo;
@@ -63,18 +66,22 @@
         mMaxThroughput = maxTput;
     }
 
+    @UnsupportedAppUsage
     public boolean isWfdEnabled() {
         return mWfdEnabled;
     }
 
+    @UnsupportedAppUsage
     public void setWfdEnabled(boolean enabled) {
         mWfdEnabled = enabled;
     }
 
+    @UnsupportedAppUsage
     public int getDeviceType() {
         return (mDeviceInfo & DEVICE_TYPE);
     }
 
+    @UnsupportedAppUsage
     public boolean setDeviceType(int deviceType) {
         if (deviceType >= WFD_SOURCE && deviceType <= SOURCE_OR_PRIMARY_SINK) {
             mDeviceInfo &= ~DEVICE_TYPE;
@@ -112,6 +119,7 @@
         return (mDeviceInfo & SESSION_AVAILABLE) != 0;
     }
 
+    @UnsupportedAppUsage
     public void setSessionAvailable(boolean enabled) {
         if (enabled) {
             mDeviceInfo |= SESSION_AVAILABLE_BIT1;
@@ -125,10 +133,12 @@
         return mCtrlPort;
     }
 
+    @UnsupportedAppUsage
     public void setControlPort(int port) {
         mCtrlPort = port;
     }
 
+    @UnsupportedAppUsage
     public void setMaxThroughput(int maxThroughput) {
         mMaxThroughput = maxThroughput;
     }
@@ -157,6 +167,7 @@
     }
 
     /** copy constructor */
+    @UnsupportedAppUsage
     public WifiP2pWfdInfo(WifiP2pWfdInfo source) {
         if (source != null) {
             mWfdEnabled = source.mWfdEnabled;
@@ -182,6 +193,7 @@
     }
 
     /** Implement the Parcelable interface */
+    @UnsupportedAppUsage
     public static final Creator<WifiP2pWfdInfo> CREATOR =
         new Creator<WifiP2pWfdInfo>() {
             public WifiP2pWfdInfo createFromParcel(Parcel in) {
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
index a4118dc..c9e9867 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.p2p.nsd;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.nsd.DnsSdTxtRecord;
 import android.text.TextUtils;
 
@@ -173,6 +174,7 @@
      * @param version version number
      * @hide
      */
+    @UnsupportedAppUsage
     static String createRequest(String dnsName, int dnsType, int version) {
         StringBuffer sb = new StringBuffer();
 
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
index b931475..3563198 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.p2p.nsd;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -83,6 +84,7 @@
      * {"upnp", "10", "uuid:6859dede-8574-59ab-9322-123456789012::urn:schemas-upnp
      * -org:service:ContentDirectory:2"}
      */
+    @UnsupportedAppUsage
     private List<String> mQueryList;
 
     /**
@@ -91,6 +93,7 @@
      * @param queryList query string for wpa_supplicant
      * @hide
      */
+    @UnsupportedAppUsage
     protected WifiP2pServiceInfo(List<String> queryList) {
         if (queryList == null) {
             throw new IllegalArgumentException("query list cannot be null");
@@ -166,6 +169,7 @@
     }
 
     /** Implement the Parcelable interface {@hide} */
+    @UnsupportedAppUsage
     public static final Creator<WifiP2pServiceInfo> CREATOR =
         new Creator<WifiP2pServiceInfo>() {
             public WifiP2pServiceInfo createFromParcel(Parcel in) {
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
index 7462b85c..2e7f448 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.p2p.nsd;
 
+import android.annotation.UnsupportedAppUsage;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -72,6 +73,7 @@
      * @param query The part of service specific query.
      * @hide
      */
+    @UnsupportedAppUsage
     protected WifiP2pServiceRequest(int protocolType, String query) {
         validateQuery(query);
 
@@ -262,6 +264,7 @@
     }
 
     /** Implement the Parcelable interface {@hide} */
+    @UnsupportedAppUsage
     public static final Creator<WifiP2pServiceRequest> CREATOR =
         new Creator<WifiP2pServiceRequest>() {
             public WifiP2pServiceRequest createFromParcel(Parcel in) {
diff --git a/wifi/tests/assets/pps/PerProviderSubscription.xml b/wifi/tests/assets/pps/PerProviderSubscription.xml
index 1fb8309..e4472ce 100644
--- a/wifi/tests/assets/pps/PerProviderSubscription.xml
+++ b/wifi/tests/assets/pps/PerProviderSubscription.xml
@@ -368,7 +368,7 @@
         </Node>
       </Node>
       <Node>
-        <NodeName>SubscriptionParameter</NodeName>
+        <NodeName>SubscriptionParameters</NodeName>
         <Node>
           <NodeName>CreationDate</NodeName>
           <Value>2016-02-01T10:00:00Z</Value>
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 20e49cd..5058080 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -25,9 +25,6 @@
 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED;
 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED;
 import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL;
-import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
@@ -47,6 +44,7 @@
 import android.net.wifi.WifiManager.LocalOnlyHotspotReservation;
 import android.net.wifi.WifiManager.LocalOnlyHotspotSubscription;
 import android.net.wifi.WifiManager.SoftApCallback;
+import android.net.wifi.WifiManager.TrafficStateCallback;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -57,6 +55,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -77,6 +76,7 @@
     @Mock WifiConfiguration mApConfig;
     @Mock IBinder mAppBinder;
     @Mock SoftApCallback mSoftApCallback;
+    @Mock TrafficStateCallback mTrafficStateCallback;
 
     private Handler mHandler;
     private TestLooper mLooper;
@@ -702,7 +702,7 @@
     }
 
     /*
-     * Verify client provided callback is being called through callback proxy
+     * Verify client-provided callback is being called through callback proxy
      */
     @Test
     public void softApCallbackProxyCallsOnStateChanged() throws Exception {
@@ -718,7 +718,7 @@
     }
 
     /*
-     * Verify client provided callback is being called through callback proxy
+     * Verify client-provided callback is being called through callback proxy
      */
     @Test
     public void softApCallbackProxyCallsOnNumClientsChanged() throws Exception {
@@ -735,7 +735,7 @@
     }
 
     /*
-     * Verify client provided callback is being called through callback proxy on multiple events
+     * Verify client-provided callback is being called through callback proxy on multiple events
      */
     @Test
     public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
@@ -757,7 +757,7 @@
     }
 
     /*
-     * Verify client provided callback is being called on the correct thread
+     * Verify client-provided callback is being called on the correct thread
      */
     @Test
     public void softApCallbackIsCalledOnCorrectThread() throws Exception {
@@ -1082,4 +1082,84 @@
         when(mWifiService.startScan(TEST_PACKAGE_NAME)).thenReturn(false);
         assertFalse(mWifiManager.startScan());
     }
+
+    /**
+     * Verify main looper is used when handler is not provided.
+     */
+    @Test
+    public void registerTrafficStateCallbackUsesMainLooperOnNullArgumentForHandler()
+            throws Exception {
+        when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+        ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
+        mWifiManager.registerTrafficStateCallback(mTrafficStateCallback, null);
+        verify(mWifiService).registerTrafficStateCallback(
+                any(IBinder.class), callbackCaptor.capture(), anyInt());
+
+        assertEquals(0, mLooper.dispatchAll());
+        callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
+        assertEquals(1, mLooper.dispatchAll());
+        verify(mTrafficStateCallback).onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
+    }
+
+    /**
+     * Verify the call to unregisterTrafficStateCallback goes to WifiServiceImpl.
+     */
+    @Test
+    public void unregisterTrafficStateCallbackCallGoesToWifiServiceImpl() throws Exception {
+        ArgumentCaptor<Integer> callbackIdentifier = ArgumentCaptor.forClass(Integer.class);
+        mWifiManager.registerTrafficStateCallback(mTrafficStateCallback, mHandler);
+        verify(mWifiService).registerTrafficStateCallback(any(IBinder.class),
+                any(ITrafficStateCallback.Stub.class), callbackIdentifier.capture());
+
+        mWifiManager.unregisterTrafficStateCallback(mTrafficStateCallback);
+        verify(mWifiService).unregisterTrafficStateCallback(
+                eq((int) callbackIdentifier.getValue()));
+    }
+
+    /*
+     * Verify client-provided callback is being called through callback proxy on multiple events
+     */
+    @Test
+    public void trafficStateCallbackProxyCallsOnMultipleUpdates() throws Exception {
+        ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
+        mWifiManager.registerTrafficStateCallback(mTrafficStateCallback, mHandler);
+        verify(mWifiService).registerTrafficStateCallback(
+                any(IBinder.class), callbackCaptor.capture(), anyInt());
+
+        InOrder inOrder = inOrder(mTrafficStateCallback);
+
+        callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_IN);
+        callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
+        callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_OUT);
+
+        mLooper.dispatchAll();
+        inOrder.verify(mTrafficStateCallback).onStateChanged(
+                TrafficStateCallback.DATA_ACTIVITY_IN);
+        inOrder.verify(mTrafficStateCallback).onStateChanged(
+                TrafficStateCallback.DATA_ACTIVITY_INOUT);
+        inOrder.verify(mTrafficStateCallback).onStateChanged(
+                TrafficStateCallback.DATA_ACTIVITY_OUT);
+    }
+
+    /*
+     * Verify client-provided callback is being called on the correct thread
+     */
+    @Test
+    public void trafficStateCallbackIsCalledOnCorrectThread() throws Exception {
+        ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
+        TestLooper altLooper = new TestLooper();
+        Handler altHandler = new Handler(altLooper.getLooper());
+        mWifiManager.registerTrafficStateCallback(mTrafficStateCallback, altHandler);
+        verify(mContext, never()).getMainLooper();
+        verify(mWifiService).registerTrafficStateCallback(
+                any(IBinder.class), callbackCaptor.capture(), anyInt());
+
+        assertEquals(0, altLooper.dispatchAll());
+        callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
+        assertEquals(1, altLooper.dispatchAll());
+        verify(mTrafficStateCallback).onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
+    }
 }